cfitsio/0000755000225700000360000000000013246025103012000 5ustar cagordonlheacfitsio/CMakeLists.txt0000755000225700000360000001214713246025103014550 0ustar cagordonlhea# CFITSIO CMakeLists.txt # Suppress warning about WIN32 no longer being defined on Cygwin: SET(CMAKE_LEGACY_CYGWIN_WIN32 0) PROJECT(CFITSIO) CMAKE_MINIMUM_REQUIRED(VERSION 2.8.0) # Allow @rpath token in target install name on Macs. # See "cmake --help-policy CMP0042" for more information. IF(POLICY CMP0042) CMAKE_POLICY(SET CMP0042 NEW) ENDIF() INCLUDE (${CMAKE_ROOT}/Modules/CheckLibraryExists.cmake) INCLUDE (${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake) # Allow the developer to select if Dynamic or Static libraries are built OPTION (BUILD_SHARED_LIBS "Build Shared Libraries" ON) OPTION (USE_PTHREADS "Thread-safe build (using pthreads)" OFF) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}") set (LIB_DESTINATION "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}") set (INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include/") # Define project version SET(${PROJECT_NAME}_MAJOR_VERSION 3) SET(${PROJECT_NAME}_MINOR_VERSION 43) SET(${PROJECT_NAME}_VERSION ${${PROJECT_NAME}_MAJOR_VERSION}.${${PROJECT_NAME}_MINOR_VERSION}) SET(LIB_NAME cfitsio) # Microsoft Visual Studio: IF(MSVC OR BORLAND) # Define ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE) # Need an empty unistd.h in MSVC for flex-generated eval_l.c: FILE(WRITE ${CMAKE_SOURCE_DIR}/unistd.h "") INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}) ENDIF() IF(BORLAND) # Suppress spurious Borland compiler warnings about "Suspicious # pointer arithmetic", "Possibly incorrect assignment", and # "Comparing signed and unsigned values". ADD_DEFINITIONS(-w-spa) ADD_DEFINITIONS(-w-pia) ADD_DEFINITIONS(-w-csu) ENDIF() #add_subdirectory (src) SET (LIB_TYPE STATIC) IF (BUILD_SHARED_LIBS) SET (LIB_TYPE SHARED) ENDIF (BUILD_SHARED_LIBS) FILE(GLOB H_FILES "*.h") IF (USE_PTHREADS) FIND_PACKAGE(pthreads REQUIRED) INCLUDE_DIRECTORIES(${PTHREADS_INCLUDE_DIR}) ADD_DEFINITIONS(-D_REENTRANT) ENDIF() # Math library (not available in MSVC or MINGW) IF (MSVC OR MINGW) SET(M_LIB "") ELSE() FIND_LIBRARY(M_LIB m) ENDIF() # Support for remote file drivers is not implemented for native Windows: IF (NOT MSVC) # Find library needed for gethostbyname: CHECK_FUNCTION_EXISTS("gethostbyname" CMAKE_HAVE_GETHOSTBYNAME) IF(NOT CMAKE_HAVE_GETHOSTBYNAME) CHECK_LIBRARY_EXISTS("nsl" "gethostbyname" "" CMAKE_HAVE_GETHOSTBYNAME) ENDIF() # Find library needed for connect: CHECK_FUNCTION_EXISTS("connect" CMAKE_HAVE_CONNECT) IF(NOT CMAKE_HAVE_CONNECT) CHECK_LIBRARY_EXISTS("socket" "connect" "" CMAKE_HAVE_CONNECT) ENDIF() # Define HAVE_NET_SERVICES if gethostbyname & connect were found: IF (CMAKE_HAVE_GETHOSTBYNAME AND CMAKE_HAVE_CONNECT) ADD_DEFINITIONS(-DHAVE_NET_SERVICES) ENDIF () # Find curl library, for HTTPS support: FIND_PACKAGE(CURL) IF (CURL_FOUND) INCLUDE_DIRECTORIES(${CURL_INCLUDE_DIR}) ADD_DEFINITIONS(-DCFITSIO_HAVE_CURL) ENDIF() ENDIF() SET(SRC_FILES buffers.c cfileio.c checksum.c drvrfile.c drvrmem.c drvrnet.c drvrsmem.c drvrgsiftp.c editcol.c edithdu.c eval_l.c eval_y.c eval_f.c fitscore.c getcol.c getcolb.c getcold.c getcole.c getcoli.c getcolj.c getcolk.c getcoll.c getcols.c getcolsb.c getcoluk.c getcolui.c getcoluj.c getkey.c group.c grparser.c histo.c iraffits.c modkey.c putcol.c putcolb.c putcold.c putcole.c putcoli.c putcolj.c putcolk.c putcoluk.c putcoll.c putcols.c putcolsb.c putcolu.c putcolui.c putcoluj.c putkey.c region.c scalnull.c swapproc.c wcssub.c wcsutil.c imcompress.c quantize.c ricecomp.c pliocomp.c fits_hcompress.c fits_hdecompress.c zlib/zuncompress.c zlib/zcompress.c zlib/adler32.c zlib/crc32.c zlib/inffast.c zlib/inftrees.c zlib/trees.c zlib/zutil.c zlib/deflate.c zlib/infback.c zlib/inflate.c zlib/uncompr.c simplerng.c f77_wrap1.c f77_wrap2.c f77_wrap3.c f77_wrap4.c ) ADD_LIBRARY(${LIB_NAME} ${LIB_TYPE} ${H_FILES} ${SRC_FILES}) TARGET_LINK_LIBRARIES(${LIB_NAME} ${PTHREADS_LIBRARY} ${M_LIB} ${CURL_LIBRARIES}) SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES VERSION ${${PROJECT_NAME}_VERSION} SOVERSION ${${PROJECT_NAME}_MAJOR_VERSION}) install(TARGETS ${LIB_NAME} DESTINATION ${LIB_DESTINATION}) install(FILES ${H_FILES} DESTINATION ${INCLUDE_INSTALL_DIR} COMPONENT Devel) ENABLE_TESTING() ADD_EXECUTABLE(TestProg testprog.c) TARGET_LINK_LIBRARIES(TestProg ${LIB_NAME}) ADD_TEST(TestProg TestProg) # Copy testprog.tpt to build directory to allow quick test # of ./TestProg (or .\Release\TestProg.exe in MSVC): FILE(COPY ${CMAKE_SOURCE_DIR}/testprog.tpt DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) ADD_EXECUTABLE(cookbook cookbook.c) TARGET_LINK_LIBRARIES(cookbook ${LIB_NAME}) ADD_TEST(cookbook cookbook) ADD_EXECUTABLE(FPack fpack.c fpackutil.c) TARGET_LINK_LIBRARIES(FPack ${LIB_NAME}) ADD_EXECUTABLE(Funpack funpack.c fpackutil.c) TARGET_LINK_LIBRARIES(Funpack ${LIB_NAME}) ADD_EXECUTABLE(Fitscopy fitscopy.c) TARGET_LINK_LIBRARIES(Fitscopy ${LIB_NAME}) # To expands the command line arguments in Windows, see: # http://msdn.microsoft.com/en-us/library/8bch7bkk.aspx if(MSVC) set_target_properties(FPack Funpack PROPERTIES LINK_FLAGS "setargv.obj" ) endif(MSVC) cfitsio/FindPthreads.cmake0000644000225700000360000000621113246025103015355 0ustar cagordonlhea# - Find the Pthreads library # This module searches for the Pthreads library (including the # pthreads-win32 port). # # This module defines these variables: # # PTHREADS_FOUND # True if the Pthreads library was found # PTHREADS_LIBRARY # The location of the Pthreads library # PTHREADS_INCLUDE_DIR # The include path of the Pthreads library # PTHREADS_DEFINITIONS # Preprocessor definitions to define # # This module responds to the PTHREADS_EXCEPTION_SCHEME # variable on Win32 to allow the user to control the # library linked against. The Pthreads-win32 port # provides the ability to link against a version of the # library with exception handling. IT IS NOT RECOMMENDED # THAT YOU USE THIS because most POSIX thread implementations # do not support stack unwinding. # # PTHREADS_EXCEPTION_SCHEME # C = no exceptions (default) # (NOTE: This is the default scheme on most POSIX thread # implementations and what you should probably be using) # CE = C++ Exception Handling # SE = Structure Exception Handling (MSVC only) # # # Define a default exception scheme to link against # and validate user choice. # IF(NOT DEFINED PTHREADS_EXCEPTION_SCHEME) # Assign default if needed SET(PTHREADS_EXCEPTION_SCHEME "C") ELSE(NOT DEFINED PTHREADS_EXCEPTION_SCHEME) # Validate IF(NOT PTHREADS_EXCEPTION_SCHEME STREQUAL "C" AND NOT PTHREADS_EXCEPTION_SCHEME STREQUAL "CE" AND NOT PTHREADS_EXCEPTION_SCHEME STREQUAL "SE") MESSAGE(FATAL_ERROR "See documentation for FindPthreads.cmake, only C, CE, and SE modes are allowed") ENDIF(NOT PTHREADS_EXCEPTION_SCHEME STREQUAL "C" AND NOT PTHREADS_EXCEPTION_SCHEME STREQUAL "CE" AND NOT PTHREADS_EXCEPTION_SCHEME STREQUAL "SE") IF(NOT MSVC AND PTHREADS_EXCEPTION_SCHEME STREQUAL "SE") MESSAGE(FATAL_ERROR "Structured Exception Handling is only allowed for MSVC") ENDIF(NOT MSVC AND PTHREADS_EXCEPTION_SCHEME STREQUAL "SE") ENDIF(NOT DEFINED PTHREADS_EXCEPTION_SCHEME) # # Find the header file # FIND_PATH(PTHREADS_INCLUDE_DIR pthread.h) # # Find the library # SET(names) IF(MSVC) SET(names pthreadV${PTHREADS_EXCEPTION_SCHEME}2 pthread ) ELSEIF(MINGW) SET(names pthreadG${PTHREADS_EXCEPTION_SCHEME}2 pthread ) ELSE(MSVC) # Unix / Cygwin / Apple SET(names pthread) ENDIF(MSVC) FIND_LIBRARY(PTHREADS_LIBRARY ${names} DOC "The Portable Threads Library") IF(PTHREADS_INCLUDE_DIR AND PTHREADS_LIBRARY) SET(PTHREADS_FOUND true) SET(PTHREADS_DEFINITIONS -DHAVE_PTHREAD_H) SET(PTHREADS_INCLUDE_DIRS ${PTHREADS_INCLUDE_DIR}) SET(PTHREADS_LIBRARIES ${PTHREADS_LIBRARY}) ENDIF(PTHREADS_INCLUDE_DIR AND PTHREADS_LIBRARY) IF(PTHREADS_FOUND) IF(NOT PTHREADS_FIND_QUIETLY) MESSAGE(STATUS "Found Pthreads: ${PTHREADS_LIBRARY}") ENDIF(NOT PTHREADS_FIND_QUIETLY) ELSE(PTHREADS_FOUND) IF(PTHREADS_FIND_REQUIRED) MESSAGE(FATAL_ERROR "Could not find the Pthreads Library") ENDIF(PTHREADS_FIND_REQUIRED) ENDIF(PTHREADS_FOUND) cfitsio/License.txt0000644000225700000360000000260213246025103014123 0ustar cagordonlheaCopyright (Unpublished--all rights reserved under the copyright laws of the United States), U.S. Government as represented by the Administrator of the National Aeronautics and Space Administration. No copyright is claimed in the United States under Title 17, U.S. Code. Permission to freely use, copy, modify, and distribute this software and its documentation without fee is hereby granted, provided that this copyright notice and disclaimer of warranty appears in all copies. DISCLAIMER: THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT SHALL NASA BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT , OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. cfitsio/Makefile.in0000644000225700000360000001401513246025103014046 0ustar cagordonlhea# # Makefile for cfitsio library: # # Oct-96 : original version by # # JDD/WDP # NASA GSFC # Oct 1996 # # 25-Jan-01 : removed conditional drvrsmem.c compilation because this # is now handled within the source file itself. # 09-Mar-98 : modified to conditionally compile drvrsmem.c. Also # changes to target all (deleted clean), added DEFS, LIBS, added # DEFS to .c.o, added SOURCES_SHMEM and MY_SHMEM, expanded getcol* # and putcol* in SOURCES, modified OBJECTS, mv changed to /bin/mv # (to bypass aliasing), cp changed to /bin/cp, add smem and # testprog targets. See also changes and comments in configure.in # Default library name: PACKAGE = cfitsio # CFITSIO version numbers: CFITSIO_MAJOR = @CFITSIO_MAJOR@ CFITSIO_MINOR = @CFITSIO_MINOR@ CFITSIO_SONAME = @CFITSIO_SONAME@ prefix = @prefix@ exec_prefix = @exec_prefix@ CFITSIO_BIN = ${DESTDIR}@bindir@ CFITSIO_LIB = ${DESTDIR}@libdir@ CFITSIO_INCLUDE = ${DESTDIR}@includedir@ INSTALL_DIRS = @INSTALL_ROOT@ ${CFITSIO_INCLUDE} ${CFITSIO_LIB} ${CFITSIO_LIB}/pkgconfig SHELL = /bin/sh ARCHIVE = @ARCHIVE@ RANLIB = @RANLIB@ CC = @CC@ CFLAGS = @CFLAGS@ CPPFLAGS = @CPPFLAGS@ SSE_FLAGS = @SSE_FLAGS@ FC = @FC@ LDFLAGS = @LDFLAGS@ LDFLAGS_BIN = @LDFLAGS_BIN@ DEFS = @DEFS@ LIBS = @LIBS@ FLEX = flex BISON = bison SHLIB_LD = @SHLIB_LD@ SHLIB_SUFFIX = @SHLIB_SUFFIX@ CFITSIO_SHLIB = @CFITSIO_SHLIB@ CFITSIO_SHLIB_SONAME = @CFITSIO_SHLIB_SONAME@ CORE_SOURCES = buffers.c cfileio.c checksum.c drvrfile.c drvrmem.c \ drvrnet.c drvrsmem.c drvrgsiftp.c editcol.c edithdu.c eval_l.c \ eval_y.c eval_f.c fitscore.c getcol.c getcolb.c getcold.c getcole.c \ getcoli.c getcolj.c getcolk.c getcoll.c getcols.c getcolsb.c \ getcoluk.c getcolui.c getcoluj.c getkey.c group.c grparser.c \ histo.c iraffits.c \ modkey.c putcol.c putcolb.c putcold.c putcole.c putcoli.c \ putcolj.c putcolk.c putcoluk.c putcoll.c putcols.c putcolsb.c \ putcolu.c putcolui.c putcoluj.c putkey.c region.c scalnull.c \ swapproc.c wcssub.c wcsutil.c imcompress.c quantize.c ricecomp.c \ pliocomp.c fits_hcompress.c fits_hdecompress.c \ simplerng.c ZLIB_SOURCES = zlib/adler32.c zlib/crc32.c zlib/deflate.c zlib/infback.c \ zlib/inffast.c zlib/inflate.c zlib/inftrees.c zlib/trees.c \ zlib/uncompr.c zlib/zcompress.c zlib/zuncompress.c zlib/zutil.c SOURCES = ${CORE_SOURCES} ${ZLIB_SOURCES} @F77_WRAPPERS@ OBJECTS = ${SOURCES:.c=.o} CORE_OBJECTS = ${CORE_SOURCES:.c=.o} ${ZLIB_SOURCES:.c=.o} FITSIO_SRC = f77_wrap1.c f77_wrap2.c f77_wrap3.c f77_wrap4.c # ============ description of all targets ============= # - <<-- ignore error code all: @if [ "x${FC}" = x ]; then \ ${MAKE} all-nofitsio; \ else \ ${MAKE} stand_alone; \ fi all-nofitsio: ${MAKE} stand_alone "FITSIO_SRC=" stand_alone: lib${PACKAGE}.a lib${PACKAGE}.a: ${OBJECTS} ${ARCHIVE} $@ ${OBJECTS}; \ ${RANLIB} $@; shared: lib${PACKAGE}${SHLIB_SUFFIX} lib${PACKAGE}${SHLIB_SUFFIX}: ${OBJECTS} ${SHLIB_LD} ${LDFLAGS} -o ${CFITSIO_SHLIB} ${OBJECTS} -lm ${LIBS} @if [ "x${CFITSIO_SHLIB_SONAME}" != x ]; then \ ln -sf ${CFITSIO_SHLIB} ${CFITSIO_SHLIB_SONAME}; \ ln -sf ${CFITSIO_SHLIB_SONAME} $@; \ fi install: lib${PACKAGE}.a ${INSTALL_DIRS} @for lib in lib${PACKAGE}.a lib${PACKAGE}${SHLIB_SUFFIX} \ ${CFITSIO_SHLIB} ${CFITSIO_SHLIB_SONAME}; do \ if [ -f $$lib ]; then \ echo "/bin/cp -a $$lib ${CFITSIO_LIB}"; \ /bin/cp -a $$lib ${CFITSIO_LIB}; \ fi; \ done /bin/cp fitsio.h fitsio2.h longnam.h drvrsmem.h ${CFITSIO_INCLUDE} /bin/cp cfitsio.pc ${CFITSIO_LIB}/pkgconfig @for task in ${FPACK_UTILS} ${UTILS}; do \ if [ -f $$task ]; then \ if [ ! -d ${CFITSIO_BIN} ]; then mkdir -p ${CFITSIO_BIN}; fi; \ echo "/bin/cp $$task ${CFITSIO_BIN}"; \ /bin/cp $$task ${CFITSIO_BIN}; \ fi; \ done .c.o: ${CC} -c -o ${ eval_l.c1 # Note workaround for yyfree=fffree conflict /bin/sed -e 's/yy/ff/g' -e 's/YY/FF/g' eval_l.c1 -e 's/fffree/yyfffree/g' > eval_l.c /bin/rm -f eval_l.c1 ${BISON} -d -v -y eval.y /bin/sed -e 's/yy/ff/g' -e 's/YY/FF/g' y.tab.c > eval_y.c /bin/sed -e 's/yy/ff/g' -e 's/YY/FF/g' y.tab.h > eval_tab.h /bin/rm -f y.tab.c y.tab.h clean: - /bin/rm -rf *.o zlib/*.o *.dSYM lib${PACKAGE}* y.output so_locations \ ${UTILS} ${FPACK_UTILS} testprog.fit distclean: clean - /bin/rm -f Makefile cfitsio.pc config.log config.status configure.lineno # Make target which outputs the list of the .o contained in the cfitsio lib # usefull to build a single big shared library containing Tcl/Tk and other # extensions. used for the Tcl Plugin. cfitsioLibObjs: @echo ${CORE_OBJECTS} cfitsioLibSrcs: @echo ${SOURCES} # This target actually builds the objects needed for the lib in the above # case objs: ${CORE_OBJECTS} ${INSTALL_DIRS}: @if [ ! -d $@ ]; then mkdir -p $@; fi cfitsio/README0000644000225700000360000001066013246025103012663 0ustar cagordonlhea CFITSIO Interface Library CFITSIO is a library of ANSI C routines for reading and writing FITS format data files. A set of Fortran-callable wrapper routines are also included for the convenience of Fortran programmers. This README file gives a brief summary of how to build and test CFITSIO, but the CFITSIO User's Guide, found in the files cfitsio.doc (plain text), cfitsio.tex (LaTeX source file), cfitsio.ps, or cfitsio.pdf should be referenced for the latest and most complete information. BUILDING CFITSIO ---------------- The CFITSIO code is contained in about 40 *.c source files and several *.h header files. CFITSIO should compile and run on most Unix platforms without modification, except that Cray supercomputers computers are currently not supported. The CFITSIO library is built on Unix systems by typing: > ./configure [--prefix=/target/installation/path] > make (or 'make shared') > make install (this step is optional) at the operating system prompt. The configure command customizes the Makefile for the particular system, then the `make' command compiles the source files and builds the library. Type `./configure' and not simply `configure' to ensure that the configure script in the current directory is run and not some other system-wide configure script. The optional 'prefix' argument to configure gives the path to the directory where the CFITSIO library and include files should be installed via the later 'make install' command. For example, > ./configure --prefix=/usr1/local will cause the 'make install' command to copy the CFITSIO libcfitsio file to /usr1/local/lib and the necessary include files to /usr1/local/include (assuming of course that the process has permission to write to these directories). All the available configure options can be seen by entering the command > ./configure --help On VAX/VMS and ALPHA/VMS systems the make.com command file may be used to build the cfitsio.olb object library using the default G-floating point option for double variables. The make\_dfloat.com and make\_ieee.com files may be used instead to build the library with the other floating point options. A precompiled DLL version of CFITSIO is available for IBM-PC users of the Borland or Microsoft Visual C++ compilers in the files cfitsiodll_xxxx_borland.zip and cfitsiodll_xxxx_vcc.zip, where 'xxxx' represents the current release number. These zip archives also contains other files and instructions on how to use the CFITSIO DLL library. The CFITSIO library may also be built from the source code using the makefile.bc or makefile.vcc files. Finally, the makepc.bat file gives an example of building CFITSIO with the Borland C++ v4.5 compiler using simpler DOS commands. Instructions for building CFITSIO on Mac OS can be found in the README.MacOS file. TESTING CFITSIO --------------- The CFITSIO library should be tested by building and running the testprog.c program that is included with the release. On Unix systems, type: - % make testprog % testprog > testprog.lis % diff testprog.lis testprog.out % cmp testprog.fit testprog.std - On VMS systems, (assuming cc is the name of the C compiler command), type: - $ cc testprog.c $ link testprog, cfitsio/lib $ run testprog - The testprog program should produce a FITS file called `testprog.fit' that is identical to the testprog.std FITS file included in this release. The diagnostic messages (which were piped to the file testprog.lis in the Unix example) should be identical to the listing contained in the file testprog.out. The 'diff' and 'cmp' commands shown above should not report any differences in the files. USING CFITSIO ------------- The CFITSIO User's Guide, contained in the files cfitsio.doc (plain text file) and cfitsio.ps (postscript file), provides detailed documentation about how to build and use the CFITSIO library. It contains a description of every user-callable routine in the CFITSIO interface. The cookbook.c file provides some sample routines for performing common operations on various types of FITS files. Programmers are urged to examine these routines for recommended programming practices when using CFITSIO. Users are free to copy or modify these routines for their own purposes. Any problem reports or suggestions for improvements are welcome and should be sent to the HEASARC help desk. ------------------------------------------------------------------------- William D. Pence HEASARC, NASA/GSFC cfitsio/README.MacOS0000644000225700000360000000467513246025103013635 0ustar cagordonlheaBy default, the CFITSIO library will be a "Universal Binary" (i.e. 32- and 64-bit compatible) under Mac OS X when built in the standard way, i.e. - tar xzf cfitsio3370.tar.gz (or whatever version this is) - cd cfitsio/ - ./configure - make - make install --------------------------------------------------------------------- To install CFITSIO using MacPorts: --------------------------------------------------------------------- If you have MacPorts installed, you may install CFITSIO simply with the command $ sudo port install cfitsio +universal For more information, please visit: http://macports.org https://trac.macports.org/browser/trunk/dports/science/cfitsio/Portfile --------------------------------------------------------------------- To install CFITSIO using Homebrew: --------------------------------------------------------------------- If you have Homebrew installed, you may install CFITSIO simply with the command $ brew install cfitsio For more information, please visit: http://brew.sh http://brewformulas.org/Cfitsio --------------------------------------------------------------------- To build CFITSIO using the XCode GUI: --------------------------------------------------------------------- - tar xzf cfitsio3370.tar.gz (or whatever version this is) - cd cfitsio/ - Start Xcode and open cfitsio.xcodeproj/project.pbxproj, or just "open" the file from a terminal command line, $ open cfitsio.xcodeproj/project.pbxproj and this will start up XCode for you. - Press the Build (or "Play") button in the upper left corner of the GUI. --------------------------------------------------------------------- --------------------------------------------------------------------- Below, are the old (and now obsolete) instructions for building CFITSIO on classic Mac OS-9 or earlier versions: 1. Un binhex and unstuff cfitsio_mac.sit.hqx 2. put CFitsioPPC.mcp in the cfitsio directory. 2. Load CFitsioPPC.mcp into CodeWarrior Pro 5 and make. This builds the cfitsio library for PPC. There are also targets for both the test program and the speed test program. To use the MacOS port you can add Cfitsio PPC.lib to your Codewarrior Pro 5 project. Note that this only has been tested for the PPC. It probably won't work on 68k macs. Also note that the fortran bindings aren't included. I haven't worked with the codewarrior f2c plugin so I don't know how these would work. If one is interested, please write and I can look into this. cfitsio/README.win0000644000225700000360000001376613246025103013471 0ustar cagordonlheaInstructions on building and using CFITSIO on Windows platforms for C programmers using Microsoft Visual Studio or Borland C++. These instructions for building the CFITSIO library under Windows use the CMake build system that is available from http://www.cmake.org. =============================================================================== 1. Build the CFITSIO dll library This step will create the cfitsio.dll, and cfitsio.lib files. If you have downloaded the CFITSIO DLL .zip file that already contains the pre-built versions of these files, then SKIP THIS STEP. a. If CMAKE is not already installed on your machine, download it from http://www.cmake.org. It is recommended that you choose the "Add CMake to the system PATH for current user" option during the installation setup process for convenience when running CMake later on. b. Unzip the CFITSIO .zip file (e.g. cfit3360.zip) that was obtained from the CFITSIO Web site (http://heasarc.gsfc.nasa.gov/fitsio/). This will create a new \cfitsio subdirectory that contains the source code and documentation files. It should also contain a CMakeLists.txt file that will be used during the CMake build process. c. Open the Visual Studio Command Prompt window, likely using a desktop icon with this same name, (or the equivalent Borland command window) and CD (change directory) into the parent directory that is one level above the directory containing the CFITSIO source files that was created in the previous step. d. Create a new "cfitsio.build" subdirectory, and CD into it with the following commands: mkdir cfitsio.build cd cfitsio.build When using Visual Studio, all the files that are generated during the CMake process will be created in or under this subdirectory. e. Decide which CMake Generator you will want to use in the following step. This depends on which C/C++ compiler you are using and will likely have a name such as: "Visual Studio 10" "Visual Studio 10 Win64" (for 64-bit builds) "Visual Studio 11" "Visual Studio 11 Win64" (for 64-bit builds) "Visual Studio 12" "Visual Studio 12 Win64" (for 64-bit builds) "Borland Makefiles" "NMake Makefiles" You can see a list of all the available CMake Generators by executing the command cmake.exe /? Note that these names are case-sensitive and must be entered in the following step exactly as displayed. f. Execute the following commands to build the CFITSIO library: cmake.exe -G "" ..\cfitsio cmake.exe --build . --config Release Where the string is the string that was selected in step e. Note that the "..\cfitsio" argument in the first command gives the path to the directory that contains the CFITSIO source files and the CMakeLists.txt file. The "." argument in the second command (following --build) tells CMake to build the files in the current directory (i.e., the cfitsio.build directory). If this process completes successfully, you should find the CFITSIO library files that were created in the "cfitsio.build\Release" subdirectory. To verify that CFITSIO is working correctly, execute the testprog.exe file (in that Release directory). This should generate a long stream of diagnostic messages ending with the line "Status = 0: OK - no error". g. Other CMake options. CMake has many other build options that may be useful in some situations. Refer to the CMake documentation for more information. For example, one can build a 'debug' version of the CFITSIO library by executing the command "cmake.exe --build ." instead of the 2nd command listed above in section f. One can also make a thread safe version of CFITSIO using the pthread library with the following procedure: a. Download the precompiled files from the pthread-win32 project (http://sourceware.org/pthreads-win32/). Put the files for your specific platform (.h, .lib, .dll) into a folder 'pthread', parallel to the cfitsio source folder. b. For the compilation of cfitsio follow the cmake steps, but use this change as a replacement for the commands in step f: cmake.exe -G "" ..\cfitsio -DUSE_PTHREADS=1 -DCMAKE_INCLUDE_PATH=..\pthread -DCMAKE_LIBRARY_PATH=..\pthread cmake.exe --build . --config Release You may need to adapt the paths for the source directory and the pthread library. ============================================================================ 2. Using CFITSIO when compiling and linking application programs First, depending on your particular programming environment, it may be necessary to copy the cfitsio.lib and cfitsio.dll files into another directory where your compiler expects to find them. Or equivalently, you may need to specify the directory path to the location of the CFITSIO library files when creating a project that uses them. You may also need to copy the fitsio.h and longnam.h include files from the \cfitsio source file directory to a standard 'include' directory on your system. When using the Visual Studio command line window, application programs can be compiled and linked with CFITSIO using the following command: cl /MD your_program.c cfitsio.lib The /MD command line switch must be specified to force the compiler/linker to use the appropriate runtime library. If this switch is omitted, then the fits_report_error function in CFITSIO will likely crash. When building programs in the Visual Studio graphical environment, one can force the equivalent of the /MD switch by selecting 'Settings...' under the 'Project' menu, then click on the C/C++ tab and select the 'Code Generator' category. Then under 'User Run-time Library' select 'Multithreaded DLL'. =============================================================================== cfitsio/README_OLD.win0000644000225700000360000000671613246025103014164 0ustar cagordonlhea=============================================================================== =============================================================================== = NOTE: This is the old version of the README.win32 file that was distributed = with CFITSIO up until version 3.35 in 2013. These instruction may still work = with more recent versions of CFITSIO, however, users are strongly urged to = use the CMake procedures that are now documented in the new README.win32 file. =============================================================================== =============================================================================== Instructions on using CFITSIO on Windows platforms for C programmers These instructions use a simple DOS-style command window. It is also possible to build and use CFITSIO within a GUI programming environment such as Visual Studio, but this is not supported here. =============================================================================== 1. Build the CFITSIO dll library This step will create the cfitsio.def, cfitsio.dll, and cfitsio.lib files. (If you downloaded the CFITSIO .zip file that contains the pre-built binary .dll file, then SKIP THIS STEP). A. With Microsoft Visual C++: 1. Open a DOS command window and execute the vcvars32.bat file that is distributed with older versions of Visual C++, or simply open the Visual C++ command window (e.g., when using Visual Studio 2010). 2. Unpack the CFITSIO source files (cfitxxxx.zip) into a new empty directory 3. In the DOS command window, cd to that directory and enter the following commands: nmake winDumpExts.mak nmake makefile.vcc (ignore the compiler warning messages) B: With Borland C++: First, follow the instructions provided by Borland to set up the proper environment variables and configure files for the compiler. Unpack the cfitsio.zip source file distribution into a suitable directory. In a DOS command window, cd to that directory and then execute the makepc.bat batch file on the command line to build the CFITSIO library, and the testprog and cookbook sample programs. =============================================================================== 2. Test the CFITSIO library with Visual C++ Compile and link the testprog.c test program. When using Visual Studio, the command is: cl /MD testprog.c cfitsio.lib This will create the testprog.exe executable program. Running this program should print out a long series of diagnostic messages that should end with "Status = 0; OK - no error" =============================================================================== 3. Compile and link an application program that calls CFITSIO routines with Visual C++ Include the fitsio.h and longnam.h header files in the C source code. Link the program with the cfitsio.lib file: cl /MD your_program.c cfitsio.lib NOTE: The /MD command line switch must be specified on the cl command line to force the compiler/linker to use the appropriete runtime library. If this switch is omitted, then the fits_report_error function in CFITSIO will likely crash. When building programs in the Visual Studio environment, one can force the equivalent of the /MD switch by selecting 'Settings...' under the 'Project' menu, then click on the C/C++ tab and select the 'Code Generator' category. Then under 'User Run-time Library' select 'Multithreaded DLL'. cfitsio/buffers.c0000644000225700000360000014775513246025103013623 0ustar cagordonlhea/* This file, buffers.c, contains the core set of FITSIO routines */ /* that use or manage the internal set of IO buffers. */ /* The FITSIO software was written by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ #include #include #include "fitsio2.h" /*--------------------------------------------------------------------------*/ int ffmbyt(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG bytepos, /* I - byte position in file to move to */ int err_mode, /* I - 1=ignore error, 0 = return error */ int *status) /* IO - error status */ { /* Move to the input byte location in the file. When writing to a file, a move may sometimes be made to a position beyond the current EOF. The err_mode parameter determines whether such conditions should be returned as an error or simply ignored. */ long record; if (*status > 0) return(*status); if (bytepos < 0) return(*status = NEG_FILE_POS); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); record = (long) (bytepos / IOBUFLEN); /* zero-indexed record number */ /* if this is not the current record, then load it */ if ( ((fptr->Fptr)->curbuf < 0) || (record != (fptr->Fptr)->bufrecnum[(fptr->Fptr)->curbuf])) ffldrc(fptr, record, err_mode, status); if (*status <= 0) (fptr->Fptr)->bytepos = bytepos; /* save new file position */ return(*status); } /*--------------------------------------------------------------------------*/ int ffpbyt(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG nbytes, /* I - number of bytes to write */ void *buffer, /* I - buffer containing the bytes to write */ int *status) /* IO - error status */ /* put (write) the buffer of bytes to the output FITS file, starting at the current file position. Write large blocks of data directly to disk; write smaller segments to intermediate IO buffers to improve efficiency. */ { int ii, nbuff; LONGLONG filepos; long recstart, recend; long ntodo, bufpos, nspace, nwrite; char *cptr; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); if (nbytes > LONG_MAX) { ffpmsg("Number of bytes to write is greater than LONG_MAX (ffpbyt)."); *status = WRITE_ERROR; return(*status); } ntodo = (long) nbytes; cptr = (char *)buffer; if ((fptr->Fptr)->curbuf < 0) /* no current data buffer for this file */ { /* so reload the last one that was used */ ffldrc(fptr, (long) (((fptr->Fptr)->bytepos) / IOBUFLEN), REPORT_EOF, status); } if (nbytes >= MINDIRECT) { /* write large blocks of data directly to disk instead of via buffers */ /* first, fill up the current IO buffer before flushing it to disk */ nbuff = (fptr->Fptr)->curbuf; /* current IO buffer number */ filepos = (fptr->Fptr)->bytepos; /* save the write starting position */ recstart = (fptr->Fptr)->bufrecnum[nbuff]; /* starting record */ recend = (long) ((filepos + nbytes - 1) / IOBUFLEN); /* ending record */ /* bufpos is the starting position within the IO buffer */ bufpos = (long) (filepos - ((LONGLONG)recstart * IOBUFLEN)); nspace = IOBUFLEN - bufpos; /* amount of space left in the buffer */ if (nspace) { /* fill up the IO buffer */ memcpy((fptr->Fptr)->iobuffer + (nbuff * IOBUFLEN) + bufpos, cptr, nspace); ntodo -= nspace; /* decrement remaining number of bytes */ cptr += nspace; /* increment user buffer pointer */ filepos += nspace; /* increment file position pointer */ (fptr->Fptr)->dirty[nbuff] = TRUE; /* mark record as having been modified */ } for (ii = 0; ii < NIOBUF; ii++) /* flush any affected buffers to disk */ { if ((fptr->Fptr)->bufrecnum[ii] >= recstart && (fptr->Fptr)->bufrecnum[ii] <= recend ) { if ((fptr->Fptr)->dirty[ii]) /* flush modified buffer to disk */ ffbfwt(fptr->Fptr, ii, status); (fptr->Fptr)->bufrecnum[ii] = -1; /* disassociate buffer from the file */ } } /* move to the correct write position */ if ((fptr->Fptr)->io_pos != filepos) ffseek(fptr->Fptr, filepos); nwrite = ((ntodo - 1) / IOBUFLEN) * IOBUFLEN; /* don't write last buff */ ffwrite(fptr->Fptr, nwrite, cptr, status); /* write the data */ ntodo -= nwrite; /* decrement remaining number of bytes */ cptr += nwrite; /* increment user buffer pointer */ (fptr->Fptr)->io_pos = filepos + nwrite; /* update the file position */ if ((fptr->Fptr)->io_pos >= (fptr->Fptr)->filesize) /* at the EOF? */ { (fptr->Fptr)->filesize = (fptr->Fptr)->io_pos; /* increment file size */ /* initialize the current buffer with the correct fill value */ if ((fptr->Fptr)->hdutype == ASCII_TBL) memset((fptr->Fptr)->iobuffer + (nbuff * IOBUFLEN), 32, IOBUFLEN); /* blank fill */ else memset((fptr->Fptr)->iobuffer + (nbuff * IOBUFLEN), 0, IOBUFLEN); /* zero fill */ } else { /* read next record */ ffread(fptr->Fptr, IOBUFLEN, (fptr->Fptr)->iobuffer + (nbuff * IOBUFLEN), status); (fptr->Fptr)->io_pos += IOBUFLEN; } /* copy remaining bytes from user buffer into current IO buffer */ memcpy((fptr->Fptr)->iobuffer + (nbuff * IOBUFLEN), cptr, ntodo); (fptr->Fptr)->dirty[nbuff] = TRUE; /* mark record as having been modified */ (fptr->Fptr)->bufrecnum[nbuff] = recend; /* record number */ (fptr->Fptr)->logfilesize = maxvalue((fptr->Fptr)->logfilesize, (LONGLONG)(recend + 1) * IOBUFLEN); (fptr->Fptr)->bytepos = filepos + nwrite + ntodo; } else { /* bufpos is the starting position in IO buffer */ bufpos = (long) ((fptr->Fptr)->bytepos - ((LONGLONG)(fptr->Fptr)->bufrecnum[(fptr->Fptr)->curbuf] * IOBUFLEN)); nspace = IOBUFLEN - bufpos; /* amount of space left in the buffer */ while (ntodo) { nwrite = minvalue(ntodo, nspace); /* copy bytes from user's buffer to the IO buffer */ memcpy((fptr->Fptr)->iobuffer + ((fptr->Fptr)->curbuf * IOBUFLEN) + bufpos, cptr, nwrite); ntodo -= nwrite; /* decrement remaining number of bytes */ cptr += nwrite; (fptr->Fptr)->bytepos += nwrite; /* increment file position pointer */ (fptr->Fptr)->dirty[(fptr->Fptr)->curbuf] = TRUE; /* mark record as modified */ if (ntodo) /* load next record into a buffer */ { ffldrc(fptr, (long) ((fptr->Fptr)->bytepos / IOBUFLEN), IGNORE_EOF, status); bufpos = 0; nspace = IOBUFLEN; } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffpbytoff(fitsfile *fptr, /* I - FITS file pointer */ long gsize, /* I - size of each group of bytes */ long ngroups, /* I - number of groups to write */ long offset, /* I - size of gap between groups */ void *buffer, /* I - buffer to be written */ int *status) /* IO - error status */ /* put (write) the buffer of bytes to the output FITS file, with an offset between each group of bytes. This function combines ffmbyt and ffpbyt for increased efficiency. */ { int bcurrent; long ii, bufpos, nspace, nwrite, record; char *cptr, *ioptr; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); if ((fptr->Fptr)->curbuf < 0) /* no current data buffer for this file */ { /* so reload the last one that was used */ ffldrc(fptr, (long) (((fptr->Fptr)->bytepos) / IOBUFLEN), REPORT_EOF, status); } cptr = (char *)buffer; bcurrent = (fptr->Fptr)->curbuf; /* number of the current IO buffer */ record = (fptr->Fptr)->bufrecnum[bcurrent]; /* zero-indexed record number */ bufpos = (long) ((fptr->Fptr)->bytepos - ((LONGLONG)record * IOBUFLEN)); /* start pos */ nspace = IOBUFLEN - bufpos; /* amount of space left in buffer */ ioptr = (fptr->Fptr)->iobuffer + (bcurrent * IOBUFLEN) + bufpos; for (ii = 1; ii < ngroups; ii++) /* write all but the last group */ { /* copy bytes from user's buffer to the IO buffer */ nwrite = minvalue(gsize, nspace); memcpy(ioptr, cptr, nwrite); cptr += nwrite; /* increment buffer pointer */ if (nwrite < gsize) /* entire group did not fit */ { (fptr->Fptr)->dirty[bcurrent] = TRUE; /* mark record as having been modified */ record++; ffldrc(fptr, record, IGNORE_EOF, status); /* load next record */ bcurrent = (fptr->Fptr)->curbuf; ioptr = (fptr->Fptr)->iobuffer + (bcurrent * IOBUFLEN); nwrite = gsize - nwrite; memcpy(ioptr, cptr, nwrite); cptr += nwrite; /* increment buffer pointer */ ioptr += (offset + nwrite); /* increment IO buffer pointer */ nspace = IOBUFLEN - offset - nwrite; /* amount of space left */ } else { ioptr += (offset + nwrite); /* increment IO bufer pointer */ nspace -= (offset + nwrite); } if (nspace <= 0) /* beyond current record? */ { (fptr->Fptr)->dirty[bcurrent] = TRUE; record += ((IOBUFLEN - nspace) / IOBUFLEN); /* new record number */ ffldrc(fptr, record, IGNORE_EOF, status); bcurrent = (fptr->Fptr)->curbuf; bufpos = (-nspace) % IOBUFLEN; /* starting buffer pos */ nspace = IOBUFLEN - bufpos; ioptr = (fptr->Fptr)->iobuffer + (bcurrent * IOBUFLEN) + bufpos; } } /* now write the last group */ nwrite = minvalue(gsize, nspace); memcpy(ioptr, cptr, nwrite); cptr += nwrite; /* increment buffer pointer */ if (nwrite < gsize) /* entire group did not fit */ { (fptr->Fptr)->dirty[bcurrent] = TRUE; /* mark record as having been modified */ record++; ffldrc(fptr, record, IGNORE_EOF, status); /* load next record */ bcurrent = (fptr->Fptr)->curbuf; ioptr = (fptr->Fptr)->iobuffer + (bcurrent * IOBUFLEN); nwrite = gsize - nwrite; memcpy(ioptr, cptr, nwrite); } (fptr->Fptr)->dirty[bcurrent] = TRUE; /* mark record as having been modified */ (fptr->Fptr)->bytepos = (fptr->Fptr)->bytepos + (ngroups * gsize) + (ngroups - 1) * offset; return(*status); } /*--------------------------------------------------------------------------*/ int ffgbyt(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG nbytes, /* I - number of bytes to read */ void *buffer, /* O - buffer to read into */ int *status) /* IO - error status */ /* get (read) the requested number of bytes from the file, starting at the current file position. Read large blocks of data directly from disk; read smaller segments via intermediate IO buffers to improve efficiency. */ { int ii; LONGLONG filepos; long recstart, recend, ntodo, bufpos, nspace, nread; char *cptr; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); cptr = (char *)buffer; if (nbytes >= MINDIRECT) { /* read large blocks of data directly from disk instead of via buffers */ filepos = (fptr->Fptr)->bytepos; /* save the read starting position */ /* note that in this case, ffmbyt has not been called, and so */ /* bufrecnum[(fptr->Fptr)->curbuf] does not point to the intended */ /* output buffer */ recstart = (long) (filepos / IOBUFLEN); /* starting record */ recend = (long) ((filepos + nbytes - 1) / IOBUFLEN); /* ending record */ for (ii = 0; ii < NIOBUF; ii++) /* flush any affected buffers to disk */ { if ((fptr->Fptr)->dirty[ii] && (fptr->Fptr)->bufrecnum[ii] >= recstart && (fptr->Fptr)->bufrecnum[ii] <= recend) { ffbfwt(fptr->Fptr, ii, status); /* flush modified buffer to disk */ } } /* move to the correct read position */ if ((fptr->Fptr)->io_pos != filepos) ffseek(fptr->Fptr, filepos); ffread(fptr->Fptr, (long) nbytes, cptr, status); /* read the data */ (fptr->Fptr)->io_pos = filepos + nbytes; /* update the file position */ } else { /* read small chucks of data using the IO buffers for efficiency */ if ((fptr->Fptr)->curbuf < 0) /* no current data buffer for this file */ { /* so reload the last one that was used */ ffldrc(fptr, (long) (((fptr->Fptr)->bytepos) / IOBUFLEN), REPORT_EOF, status); } /* bufpos is the starting position in IO buffer */ bufpos = (long) ((fptr->Fptr)->bytepos - ((LONGLONG)(fptr->Fptr)->bufrecnum[(fptr->Fptr)->curbuf] * IOBUFLEN)); nspace = IOBUFLEN - bufpos; /* amount of space left in the buffer */ ntodo = (long) nbytes; while (ntodo) { nread = minvalue(ntodo, nspace); /* copy bytes from IO buffer to user's buffer */ memcpy(cptr, (fptr->Fptr)->iobuffer + ((fptr->Fptr)->curbuf * IOBUFLEN) + bufpos, nread); ntodo -= nread; /* decrement remaining number of bytes */ cptr += nread; (fptr->Fptr)->bytepos += nread; /* increment file position pointer */ if (ntodo) /* load next record into a buffer */ { ffldrc(fptr, (long) ((fptr->Fptr)->bytepos / IOBUFLEN), REPORT_EOF, status); bufpos = 0; nspace = IOBUFLEN; } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffgbytoff(fitsfile *fptr, /* I - FITS file pointer */ long gsize, /* I - size of each group of bytes */ long ngroups, /* I - number of groups to read */ long offset, /* I - size of gap between groups (may be < 0) */ void *buffer, /* I - buffer to be filled */ int *status) /* IO - error status */ /* get (read) the requested number of bytes from the file, starting at the current file position. This function combines ffmbyt and ffgbyt for increased efficiency. */ { int bcurrent; long ii, bufpos, nspace, nread, record; char *cptr, *ioptr; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); if ((fptr->Fptr)->curbuf < 0) /* no current data buffer for this file */ { /* so reload the last one that was used */ ffldrc(fptr, (long) (((fptr->Fptr)->bytepos) / IOBUFLEN), REPORT_EOF, status); } cptr = (char *)buffer; bcurrent = (fptr->Fptr)->curbuf; /* number of the current IO buffer */ record = (fptr->Fptr)->bufrecnum[bcurrent]; /* zero-indexed record number */ bufpos = (long) ((fptr->Fptr)->bytepos - ((LONGLONG)record * IOBUFLEN)); /* start pos */ nspace = IOBUFLEN - bufpos; /* amount of space left in buffer */ ioptr = (fptr->Fptr)->iobuffer + (bcurrent * IOBUFLEN) + bufpos; for (ii = 1; ii < ngroups; ii++) /* read all but the last group */ { /* copy bytes from IO buffer to the user's buffer */ nread = minvalue(gsize, nspace); memcpy(cptr, ioptr, nread); cptr += nread; /* increment buffer pointer */ if (nread < gsize) /* entire group did not fit */ { record++; ffldrc(fptr, record, REPORT_EOF, status); /* load next record */ bcurrent = (fptr->Fptr)->curbuf; ioptr = (fptr->Fptr)->iobuffer + (bcurrent * IOBUFLEN); nread = gsize - nread; memcpy(cptr, ioptr, nread); cptr += nread; /* increment buffer pointer */ ioptr += (offset + nread); /* increment IO buffer pointer */ nspace = IOBUFLEN - offset - nread; /* amount of space left */ } else { ioptr += (offset + nread); /* increment IO bufer pointer */ nspace -= (offset + nread); } if (nspace <= 0 || nspace > IOBUFLEN) /* beyond current record? */ { if (nspace <= 0) { record += ((IOBUFLEN - nspace) / IOBUFLEN); /* new record number */ bufpos = (-nspace) % IOBUFLEN; /* starting buffer pos */ } else { record -= ((nspace - 1 ) / IOBUFLEN); /* new record number */ bufpos = IOBUFLEN - (nspace % IOBUFLEN); /* starting buffer pos */ } ffldrc(fptr, record, REPORT_EOF, status); bcurrent = (fptr->Fptr)->curbuf; nspace = IOBUFLEN - bufpos; ioptr = (fptr->Fptr)->iobuffer + (bcurrent * IOBUFLEN) + bufpos; } } /* now read the last group */ nread = minvalue(gsize, nspace); memcpy(cptr, ioptr, nread); cptr += nread; /* increment buffer pointer */ if (nread < gsize) /* entire group did not fit */ { record++; ffldrc(fptr, record, REPORT_EOF, status); /* load next record */ bcurrent = (fptr->Fptr)->curbuf; ioptr = (fptr->Fptr)->iobuffer + (bcurrent * IOBUFLEN); nread = gsize - nread; memcpy(cptr, ioptr, nread); } (fptr->Fptr)->bytepos = (fptr->Fptr)->bytepos + (ngroups * gsize) + (ngroups - 1) * offset; return(*status); } /*--------------------------------------------------------------------------*/ int ffldrc(fitsfile *fptr, /* I - FITS file pointer */ long record, /* I - record number to be loaded */ int err_mode, /* I - 1=ignore EOF, 0 = return EOF error */ int *status) /* IO - error status */ { /* low-level routine to load a specified record from a file into a physical buffer, if it is not already loaded. Reset all pointers to make this the new current record for that file. Update ages of all the physical buffers. */ int ibuff, nbuff; LONGLONG rstart; /* check if record is already loaded in one of the buffers */ /* search from youngest to oldest buffer for efficiency */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); for (ibuff = NIOBUF - 1; ibuff >= 0; ibuff--) { nbuff = (fptr->Fptr)->ageindex[ibuff]; if (record == (fptr->Fptr)->bufrecnum[nbuff]) { goto updatebuf; /* use 'goto' for efficiency */ } } /* record is not already loaded */ rstart = (LONGLONG)record * IOBUFLEN; if ( !err_mode && (rstart >= (fptr->Fptr)->logfilesize) ) /* EOF? */ return(*status = END_OF_FILE); if (ffwhbf(fptr, &nbuff) < 0) /* which buffer should we reuse? */ return(*status = TOO_MANY_FILES); if ((fptr->Fptr)->dirty[nbuff]) ffbfwt(fptr->Fptr, nbuff, status); /* write dirty buffer to disk */ if (rstart >= (fptr->Fptr)->filesize) /* EOF? */ { /* initialize an empty buffer with the correct fill value */ if ((fptr->Fptr)->hdutype == ASCII_TBL) memset((fptr->Fptr)->iobuffer + (nbuff * IOBUFLEN), 32, IOBUFLEN); /* blank fill */ else memset((fptr->Fptr)->iobuffer + (nbuff * IOBUFLEN), 0, IOBUFLEN); /* zero fill */ (fptr->Fptr)->logfilesize = maxvalue((fptr->Fptr)->logfilesize, rstart + IOBUFLEN); (fptr->Fptr)->dirty[nbuff] = TRUE; /* mark record as having been modified */ } else /* not EOF, so read record from disk */ { if ((fptr->Fptr)->io_pos != rstart) ffseek(fptr->Fptr, rstart); ffread(fptr->Fptr, IOBUFLEN, (fptr->Fptr)->iobuffer + (nbuff * IOBUFLEN), status); (fptr->Fptr)->io_pos = rstart + IOBUFLEN; /* set new IO position */ } (fptr->Fptr)->bufrecnum[nbuff] = record; /* record number contained in buffer */ updatebuf: (fptr->Fptr)->curbuf = nbuff; /* this is the current buffer for this file */ if (ibuff < 0) { /* find the current position of the buffer in the age index */ for (ibuff = 0; ibuff < NIOBUF; ibuff++) if ((fptr->Fptr)->ageindex[ibuff] == nbuff) break; } /* increment the age of all the buffers that were younger than it */ for (ibuff++; ibuff < NIOBUF; ibuff++) (fptr->Fptr)->ageindex[ibuff - 1] = (fptr->Fptr)->ageindex[ibuff]; (fptr->Fptr)->ageindex[NIOBUF - 1] = nbuff; /* this is now the youngest buffer */ return(*status); } /*--------------------------------------------------------------------------*/ int ffwhbf(fitsfile *fptr, /* I - FITS file pointer */ int *nbuff) /* O - which buffer to use */ { /* decide which buffer to (re)use to hold a new file record */ return(*nbuff = (fptr->Fptr)->ageindex[0]); /* return oldest buffer */ } /*--------------------------------------------------------------------------*/ int ffflus(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ /* Flush all the data in the current FITS file to disk. This ensures that if the program subsequently dies, the disk FITS file will be closed correctly. */ { int hdunum, hdutype; if (*status > 0) return(*status); ffghdn(fptr, &hdunum); /* get the current HDU number */ if (ffchdu(fptr,status) > 0) /* close out the current HDU */ ffpmsg("ffflus could not close the current HDU."); ffflsh(fptr, FALSE, status); /* flush any modified IO buffers to disk */ if (ffgext(fptr, hdunum - 1, &hdutype, status) > 0) /* reopen HDU */ ffpmsg("ffflus could not reopen the current HDU."); return(*status); } /*--------------------------------------------------------------------------*/ int ffflsh(fitsfile *fptr, /* I - FITS file pointer */ int clearbuf, /* I - also clear buffer contents? */ int *status) /* IO - error status */ { /* flush all dirty IO buffers associated with the file to disk */ int ii; /* no need to move to a different HDU if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); */ for (ii = 0; ii < NIOBUF; ii++) { /* flush modified buffer to disk */ if ((fptr->Fptr)->bufrecnum[ii] >= 0 &&(fptr->Fptr)->dirty[ii]) ffbfwt(fptr->Fptr, ii, status); if (clearbuf) (fptr->Fptr)->bufrecnum[ii] = -1; /* set contents of buffer as undefined */ } if (*status != READONLY_FILE) ffflushx(fptr->Fptr); /* flush system buffers to disk */ return(*status); } /*--------------------------------------------------------------------------*/ int ffbfeof(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ { /* clear any buffers beyond the end of file */ int ii; for (ii = 0; ii < NIOBUF; ii++) { if ( (LONGLONG) (fptr->Fptr)->bufrecnum[ii] * IOBUFLEN >= fptr->Fptr->filesize) { (fptr->Fptr)->bufrecnum[ii] = -1; /* set contents of buffer as undefined */ } } return(*status); } /*--------------------------------------------------------------------------*/ int ffbfwt(FITSfile *Fptr, /* I - FITS file pointer */ int nbuff, /* I - which buffer to write */ int *status) /* IO - error status */ { /* write contents of buffer to file; If the position of the buffer is beyond the current EOF, then the file may need to be extended with fill values, and/or with the contents of some of the other i/o buffers. */ int ii,ibuff; long jj, irec, minrec, nloop; LONGLONG filepos; static char zeros[IOBUFLEN]; /* initialized to zero by default */ if (!(Fptr->writemode) ) { ffpmsg("Error: trying to write to READONLY file."); if (Fptr->driver == 8) { /* gzip compressed file */ ffpmsg("Cannot write to a GZIP or COMPRESS compressed file."); } Fptr->dirty[nbuff] = FALSE; /* reset buffer status to prevent later probs */ *status = READONLY_FILE; return(*status); } filepos = (LONGLONG)Fptr->bufrecnum[nbuff] * IOBUFLEN; if (filepos <= Fptr->filesize) { /* record is located within current file, so just write it */ /* move to the correct write position */ if (Fptr->io_pos != filepos) ffseek(Fptr, filepos); ffwrite(Fptr, IOBUFLEN, Fptr->iobuffer + (nbuff * IOBUFLEN), status); Fptr->io_pos = filepos + IOBUFLEN; if (filepos == Fptr->filesize) /* appended new record? */ Fptr->filesize += IOBUFLEN; /* increment the file size */ Fptr->dirty[nbuff] = FALSE; } else /* if record is beyond the EOF, append any other records */ /* and/or insert fill values if necessary */ { /* move to EOF */ if (Fptr->io_pos != Fptr->filesize) ffseek(Fptr, Fptr->filesize); ibuff = NIOBUF; /* initialize to impossible value */ while(ibuff != nbuff) /* repeat until requested buffer is written */ { minrec = (long) (Fptr->filesize / IOBUFLEN); /* write lowest record beyond the EOF first */ irec = Fptr->bufrecnum[nbuff]; /* initially point to the requested buffer */ ibuff = nbuff; for (ii = 0; ii < NIOBUF; ii++) { if (Fptr->bufrecnum[ii] >= minrec && Fptr->bufrecnum[ii] < irec) { irec = Fptr->bufrecnum[ii]; /* found a lower record */ ibuff = ii; } } filepos = (LONGLONG)irec * IOBUFLEN; /* byte offset of record in file */ /* append 1 or more fill records if necessary */ if (filepos > Fptr->filesize) { nloop = (long) ((filepos - (Fptr->filesize)) / IOBUFLEN); for (jj = 0; jj < nloop && !(*status); jj++) ffwrite(Fptr, IOBUFLEN, zeros, status); /* ffseek(Fptr, filepos); */ Fptr->filesize = filepos; /* increment the file size */ } /* write the buffer itself */ ffwrite(Fptr, IOBUFLEN, Fptr->iobuffer + (ibuff * IOBUFLEN), status); Fptr->dirty[ibuff] = FALSE; Fptr->filesize += IOBUFLEN; /* increment the file size */ } /* loop back if more buffers need to be written */ Fptr->io_pos = Fptr->filesize; /* currently positioned at EOF */ } return(*status); } /*--------------------------------------------------------------------------*/ int ffgrsz( fitsfile *fptr, /* I - FITS file pionter */ long *ndata, /* O - optimal amount of data to access */ int *status) /* IO - error status */ /* Returns an optimal value for the number of rows in a binary table or the number of pixels in an image that should be read or written at one time for maximum efficiency. Accessing more data than this may cause excessive flushing and rereading of buffers to/from disk. */ { int typecode, bytesperpixel; /* There are NIOBUF internal buffers available each IOBUFLEN bytes long. */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header to get hdu struct */ return(*status); if ((fptr->Fptr)->hdutype == IMAGE_HDU ) /* calc pixels per buffer size */ { /* image pixels are in column 2 of the 'table' */ ffgtcl(fptr, 2, &typecode, NULL, NULL, status); bytesperpixel = typecode / 10; *ndata = ((NIOBUF - 1) * IOBUFLEN) / bytesperpixel; } else /* calc number of rows that fit in buffers */ { *ndata = (long) (((NIOBUF - 1) * IOBUFLEN) / maxvalue(1, (fptr->Fptr)->rowlength)); *ndata = maxvalue(1, *ndata); } return(*status); } /*--------------------------------------------------------------------------*/ int ffgtbb(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG firstrow, /* I - starting row (1 = first row) */ LONGLONG firstchar, /* I - starting byte in row (1=first) */ LONGLONG nchars, /* I - number of bytes to read */ unsigned char *values, /* I - array of bytes to read */ int *status) /* IO - error status */ /* read a consecutive string of bytes from an ascii or binary table. This will span multiple rows of the table if nchars + firstchar is greater than the length of a row. */ { LONGLONG bytepos, endrow; if (*status > 0 || nchars <= 0) return(*status); else if (firstrow < 1) return(*status=BAD_ROW_NUM); else if (firstchar < 1) return(*status=BAD_ELEM_NUM); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); /* check that we do not exceed number of rows in the table */ endrow = ((firstchar + nchars - 2) / (fptr->Fptr)->rowlength) + firstrow; if (endrow > (fptr->Fptr)->numrows) { ffpmsg("attempt to read past end of table (ffgtbb)"); return(*status=BAD_ROW_NUM); } /* move the i/o pointer to the start of the sequence of characters */ bytepos = (fptr->Fptr)->datastart + ((fptr->Fptr)->rowlength * (firstrow - 1)) + firstchar - 1; ffmbyt(fptr, bytepos, REPORT_EOF, status); ffgbyt(fptr, nchars, values, status); /* read the bytes */ return(*status); } /*--------------------------------------------------------------------------*/ int ffgi1b(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG byteloc, /* I - position within file to start reading */ long nvals, /* I - number of pixels to read */ long incre, /* I - byte increment between pixels */ unsigned char *values, /* O - returned array of values */ int *status) /* IO - error status */ /* get (read) the array of values from the FITS file, doing machine dependent format conversion (e.g. byte-swapping) if necessary. */ { LONGLONG postemp; if (incre == 1) /* read all the values at once (contiguous bytes) */ { if (nvals < MINDIRECT) /* read normally via IO buffers */ { ffmbyt(fptr, byteloc, REPORT_EOF, status); ffgbyt(fptr, nvals, values, status); } else /* read directly from disk, bypassing IO buffers */ { postemp = (fptr->Fptr)->bytepos; /* store current file position */ (fptr->Fptr)->bytepos = byteloc; /* set to the desired position */ ffgbyt(fptr, nvals, values, status); (fptr->Fptr)->bytepos = postemp; /* reset to original position */ } } else /* have to read each value individually (not contiguous ) */ { ffmbyt(fptr, byteloc, REPORT_EOF, status); ffgbytoff(fptr, 1, nvals, incre - 1, values, status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffgi2b(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG byteloc, /* I - position within file to start reading */ long nvals, /* I - number of pixels to read */ long incre, /* I - byte increment between pixels */ short *values, /* O - returned array of values */ int *status) /* IO - error status */ /* get (read) the array of values from the FITS file, doing machine dependent format conversion (e.g. byte-swapping) if necessary. */ { LONGLONG postemp; if (incre == 2) /* read all the values at once (contiguous bytes) */ { if (nvals * 2 < MINDIRECT) /* read normally via IO buffers */ { ffmbyt(fptr, byteloc, REPORT_EOF, status); ffgbyt(fptr, nvals * 2, values, status); } else /* read directly from disk, bypassing IO buffers */ { postemp = (fptr->Fptr)->bytepos; /* store current file position */ (fptr->Fptr)->bytepos = byteloc; /* set to the desired position */ ffgbyt(fptr, nvals * 2, values, status); (fptr->Fptr)->bytepos = postemp; /* reset to original position */ } } else /* have to read each value individually (not contiguous ) */ { ffmbyt(fptr, byteloc, REPORT_EOF, status); ffgbytoff(fptr, 2, nvals, incre - 2, values, status); } #if BYTESWAPPED ffswap2(values, nvals); /* reverse order of bytes in each value */ #endif return(*status); } /*--------------------------------------------------------------------------*/ int ffgi4b(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG byteloc, /* I - position within file to start reading */ long nvals, /* I - number of pixels to read */ long incre, /* I - byte increment between pixels */ INT32BIT *values, /* O - returned array of values */ int *status) /* IO - error status */ /* get (read) the array of values from the FITS file, doing machine dependent format conversion (e.g. byte-swapping) if necessary. */ { LONGLONG postemp; if (incre == 4) /* read all the values at once (contiguous bytes) */ { if (nvals * 4 < MINDIRECT) /* read normally via IO buffers */ { ffmbyt(fptr, byteloc, REPORT_EOF, status); ffgbyt(fptr, nvals * 4, values, status); } else /* read directly from disk, bypassing IO buffers */ { postemp = (fptr->Fptr)->bytepos; /* store current file position */ (fptr->Fptr)->bytepos = byteloc; /* set to the desired position */ ffgbyt(fptr, nvals * 4, values, status); (fptr->Fptr)->bytepos = postemp; /* reset to original position */ } } else /* have to read each value individually (not contiguous ) */ { ffmbyt(fptr, byteloc, REPORT_EOF, status); ffgbytoff(fptr, 4, nvals, incre - 4, values, status); } #if BYTESWAPPED ffswap4(values, nvals); /* reverse order of bytes in each value */ #endif return(*status); } /*--------------------------------------------------------------------------*/ int ffgi8b(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG byteloc, /* I - position within file to start reading */ long nvals, /* I - number of pixels to read */ long incre, /* I - byte increment between pixels */ long *values, /* O - returned array of values */ int *status) /* IO - error status */ /* get (read) the array of values from the FITS file, doing machine dependent format conversion (e.g. byte-swapping) if necessary. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! This routine reads 'nvals' 8-byte integers into 'values'. This works both on platforms that have sizeof(long) = 64, and 32, as long as 'values' has been allocated to large enough to hold 8 * nvals bytes of data. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ { LONGLONG postemp; if (incre == 8) /* read all the values at once (contiguous bytes) */ { if (nvals * 8 < MINDIRECT) /* read normally via IO buffers */ { ffmbyt(fptr, byteloc, REPORT_EOF, status); ffgbyt(fptr, nvals * 8, values, status); } else /* read directly from disk, bypassing IO buffers */ { postemp = (fptr->Fptr)->bytepos; /* store current file position */ (fptr->Fptr)->bytepos = byteloc; /* set to the desired position */ ffgbyt(fptr, nvals * 8, values, status); (fptr->Fptr)->bytepos = postemp; /* reset to original position */ } } else /* have to read each value individually (not contiguous ) */ { ffmbyt(fptr, byteloc, REPORT_EOF, status); ffgbytoff(fptr, 8, nvals, incre - 8, values, status); } #if BYTESWAPPED ffswap8((double *) values, nvals); /* reverse bytes in each value */ #endif return(*status); } /*--------------------------------------------------------------------------*/ int ffgr4b(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG byteloc, /* I - position within file to start reading */ long nvals, /* I - number of pixels to read */ long incre, /* I - byte increment between pixels */ float *values, /* O - returned array of values */ int *status) /* IO - error status */ /* get (read) the array of values from the FITS file, doing machine dependent format conversion (e.g. byte-swapping) if necessary. */ { LONGLONG postemp; #if MACHINE == VAXVMS long ii; #elif (MACHINE == ALPHAVMS) && (FLOATTYPE == GFLOAT) short *sptr; long ii; #endif if (incre == 4) /* read all the values at once (contiguous bytes) */ { if (nvals * 4 < MINDIRECT) /* read normally via IO buffers */ { ffmbyt(fptr, byteloc, REPORT_EOF, status); ffgbyt(fptr, nvals * 4, values, status); } else /* read directly from disk, bypassing IO buffers */ { postemp = (fptr->Fptr)->bytepos; /* store current file position */ (fptr->Fptr)->bytepos = byteloc; /* set to the desired position */ ffgbyt(fptr, nvals * 4, values, status); (fptr->Fptr)->bytepos = postemp; /* reset to original position */ } } else /* have to read each value individually (not contiguous ) */ { ffmbyt(fptr, byteloc, REPORT_EOF, status); ffgbytoff(fptr, 4, nvals, incre - 4, values, status); } #if MACHINE == VAXVMS ii = nvals; /* call VAX macro routine to convert */ ieevur(values, values, &ii); /* from IEEE float -> F float */ #elif (MACHINE == ALPHAVMS) && (FLOATTYPE == GFLOAT) ffswap2( (short *) values, nvals * 2); /* swap pairs of bytes */ /* convert from IEEE float format to VMS GFLOAT float format */ sptr = (short *) values; for (ii = 0; ii < nvals; ii++, sptr += 2) { if (!fnan(*sptr) ) /* test for NaN or underflow */ values[ii] *= 4.0; } #elif BYTESWAPPED ffswap4((INT32BIT *)values, nvals); /* reverse order of bytes in values */ #endif return(*status); } /*--------------------------------------------------------------------------*/ int ffgr8b(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG byteloc, /* I - position within file to start reading */ long nvals, /* I - number of pixels to read */ long incre, /* I - byte increment between pixels */ double *values, /* O - returned array of values */ int *status) /* IO - error status */ /* get (read) the array of values from the FITS file, doing machine dependent format conversion (e.g. byte-swapping) if necessary. */ { LONGLONG postemp; #if MACHINE == VAXVMS long ii; #elif (MACHINE == ALPHAVMS) && (FLOATTYPE == GFLOAT) short *sptr; long ii; #endif if (incre == 8) /* read all the values at once (contiguous bytes) */ { if (nvals * 8 < MINDIRECT) /* read normally via IO buffers */ { ffmbyt(fptr, byteloc, REPORT_EOF, status); ffgbyt(fptr, nvals * 8, values, status); } else /* read directly from disk, bypassing IO buffers */ { postemp = (fptr->Fptr)->bytepos; /* store current file position */ (fptr->Fptr)->bytepos = byteloc; /* set to the desired position */ ffgbyt(fptr, nvals * 8, values, status); (fptr->Fptr)->bytepos = postemp; /* reset to original position */ } } else /* have to read each value individually (not contiguous ) */ { ffmbyt(fptr, byteloc, REPORT_EOF, status); ffgbytoff(fptr, 8, nvals, incre - 8, values, status); } #if MACHINE == VAXVMS ii = nvals; /* call VAX macro routine to convert */ ieevud(values, values, &ii); /* from IEEE float -> D float */ #elif (MACHINE == ALPHAVMS) && (FLOATTYPE == GFLOAT) ffswap2( (short *) values, nvals * 4); /* swap pairs of bytes */ /* convert from IEEE float format to VMS GFLOAT float format */ sptr = (short *) values; for (ii = 0; ii < nvals; ii++, sptr += 4) { if (!dnan(*sptr) ) /* test for NaN or underflow */ values[ii] *= 4.0; } #elif BYTESWAPPED ffswap8(values, nvals); /* reverse order of bytes in each value */ #endif return(*status); } /*--------------------------------------------------------------------------*/ int ffptbb(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG firstrow, /* I - starting row (1 = first row) */ LONGLONG firstchar, /* I - starting byte in row (1=first) */ LONGLONG nchars, /* I - number of bytes to write */ unsigned char *values, /* I - array of bytes to write */ int *status) /* IO - error status */ /* write a consecutive string of bytes to an ascii or binary table. This will span multiple rows of the table if nchars + firstchar is greater than the length of a row. */ { LONGLONG bytepos, endrow, nrows; char message[FLEN_ERRMSG]; if (*status > 0 || nchars <= 0) return(*status); else if (firstrow < 1) return(*status=BAD_ROW_NUM); else if (firstchar < 1) return(*status=BAD_ELEM_NUM); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart < 0) /* rescan header if data undefined */ ffrdef(fptr, status); endrow = ((firstchar + nchars - 2) / (fptr->Fptr)->rowlength) + firstrow; /* check if we are writing beyond the current end of table */ if (endrow > (fptr->Fptr)->numrows) { /* if there are more HDUs following the current one, or */ /* if there is a data heap, then we must insert space */ /* for the new rows. */ if ( !((fptr->Fptr)->lasthdu) || (fptr->Fptr)->heapsize > 0) { nrows = endrow - ((fptr->Fptr)->numrows); /* ffirow also updates the heap address and numrows */ if (ffirow(fptr, (fptr->Fptr)->numrows, nrows, status) > 0) { snprintf(message, FLEN_ERRMSG, "ffptbb failed to add space for %.0f new rows in table.", (double) nrows); ffpmsg(message); return(*status); } } else { /* manally update heap starting address */ (fptr->Fptr)->heapstart += ((LONGLONG)(endrow - (fptr->Fptr)->numrows) * (fptr->Fptr)->rowlength ); (fptr->Fptr)->numrows = endrow; /* update number of rows */ } } /* move the i/o pointer to the start of the sequence of characters */ bytepos = (fptr->Fptr)->datastart + ((fptr->Fptr)->rowlength * (firstrow - 1)) + firstchar - 1; ffmbyt(fptr, bytepos, IGNORE_EOF, status); ffpbyt(fptr, nchars, values, status); /* write the bytes */ return(*status); } /*--------------------------------------------------------------------------*/ int ffpi1b(fitsfile *fptr, /* I - FITS file pointer */ long nvals, /* I - number of pixels in the values array */ long incre, /* I - byte increment between pixels */ unsigned char *values, /* I - array of values to write */ int *status) /* IO - error status */ /* put (write) the array of values to the FITS file, doing machine dependent format conversion (e.g. byte-swapping) if necessary. */ { if (incre == 1) /* write all the values at once (contiguous bytes) */ ffpbyt(fptr, nvals, values, status); else /* have to write each value individually (not contiguous ) */ ffpbytoff(fptr, 1, nvals, incre - 1, values, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffpi2b(fitsfile *fptr, /* I - FITS file pointer */ long nvals, /* I - number of pixels in the values array */ long incre, /* I - byte increment between pixels */ short *values, /* I - array of values to write */ int *status) /* IO - error status */ /* put (write) the array of values to the FITS file, doing machine dependent format conversion (e.g. byte-swapping) if necessary. */ { #if BYTESWAPPED ffswap2(values, nvals); /* reverse order of bytes in each value */ #endif if (incre == 2) /* write all the values at once (contiguous bytes) */ ffpbyt(fptr, nvals * 2, values, status); else /* have to write each value individually (not contiguous ) */ ffpbytoff(fptr, 2, nvals, incre - 2, values, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffpi4b(fitsfile *fptr, /* I - FITS file pointer */ long nvals, /* I - number of pixels in the values array */ long incre, /* I - byte increment between pixels */ INT32BIT *values, /* I - array of values to write */ int *status) /* IO - error status */ /* put (write) the array of values to the FITS file, doing machine dependent format conversion (e.g. byte-swapping) if necessary. */ { #if BYTESWAPPED ffswap4(values, nvals); /* reverse order of bytes in each value */ #endif if (incre == 4) /* write all the values at once (contiguous bytes) */ ffpbyt(fptr, nvals * 4, values, status); else /* have to write each value individually (not contiguous ) */ ffpbytoff(fptr, 4, nvals, incre - 4, values, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffpi8b(fitsfile *fptr, /* I - FITS file pointer */ long nvals, /* I - number of pixels in the values array */ long incre, /* I - byte increment between pixels */ long *values, /* I - array of values to write */ int *status) /* IO - error status */ /* put (write) the array of values to the FITS file, doing machine dependent format conversion (e.g. byte-swapping) if necessary. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! This routine writes 'nvals' 8-byte integers from 'values'. This works both on platforms that have sizeof(long) = 64, and 32, as long as 'values' has been allocated to large enough to hold 8 * nvals bytes of data. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ { #if BYTESWAPPED ffswap8((double *) values, nvals); /* reverse bytes in each value */ #endif if (incre == 8) /* write all the values at once (contiguous bytes) */ ffpbyt(fptr, nvals * 8, values, status); else /* have to write each value individually (not contiguous ) */ ffpbytoff(fptr, 8, nvals, incre - 8, values, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffpr4b(fitsfile *fptr, /* I - FITS file pointer */ long nvals, /* I - number of pixels in the values array */ long incre, /* I - byte increment between pixels */ float *values, /* I - array of values to write */ int *status) /* IO - error status */ /* put (write) the array of values to the FITS file, doing machine dependent format conversion (e.g. byte-swapping) if necessary. */ { #if MACHINE == VAXVMS long ii; ii = nvals; /* call VAX macro routine to convert */ ieevpr(values, values, &ii); /* from F float -> IEEE float */ #elif (MACHINE == ALPHAVMS) && (FLOATTYPE == GFLOAT) long ii; /* convert from VMS FFLOAT float format to IEEE float format */ for (ii = 0; ii < nvals; ii++) values[ii] *= 0.25; ffswap2( (short *) values, nvals * 2); /* swap pairs of bytes */ #elif BYTESWAPPED ffswap4((INT32BIT *) values, nvals); /* reverse order of bytes in values */ #endif if (incre == 4) /* write all the values at once (contiguous bytes) */ ffpbyt(fptr, nvals * 4, values, status); else /* have to write each value individually (not contiguous ) */ ffpbytoff(fptr, 4, nvals, incre - 4, values, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffpr8b(fitsfile *fptr, /* I - FITS file pointer */ long nvals, /* I - number of pixels in the values array */ long incre, /* I - byte increment between pixels */ double *values, /* I - array of values to write */ int *status) /* IO - error status */ /* put (write) the array of values to the FITS file, doing machine dependent format conversion (e.g. byte-swapping) if necessary. */ { #if MACHINE == VAXVMS long ii; ii = nvals; /* call VAX macro routine to convert */ ieevpd(values, values, &ii); /* from D float -> IEEE float */ #elif (MACHINE == ALPHAVMS) && (FLOATTYPE == GFLOAT) long ii; /* convert from VMS GFLOAT float format to IEEE float format */ for (ii = 0; ii < nvals; ii++) values[ii] *= 0.25; ffswap2( (short *) values, nvals * 4); /* swap pairs of bytes */ #elif BYTESWAPPED ffswap8(values, nvals); /* reverse order of bytes in each value */ #endif if (incre == 8) /* write all the values at once (contiguous bytes) */ ffpbyt(fptr, nvals * 8, values, status); else /* have to write each value individually (not contiguous ) */ ffpbytoff(fptr, 8, nvals, incre - 8, values, status); return(*status); } cfitsio/cfileio.c0000644000225700000360000073625613246025103013601 0ustar cagordonlhea/* This file, cfileio.c, contains the low-level file access routines. */ /* The FITSIO software was written by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ #include #include #include #include #include #include /* apparently needed to define size_t */ #include "fitsio2.h" #include "group.h" #ifdef CFITSIO_HAVE_CURL #include #endif #define MAX_PREFIX_LEN 20 /* max length of file type prefix (e.g. 'http://') */ #define MAX_DRIVERS 27 /* max number of file I/O drivers */ typedef struct /* structure containing pointers to I/O driver functions */ { char prefix[MAX_PREFIX_LEN]; int (*init)(void); int (*shutdown)(void); int (*setoptions)(int option); int (*getoptions)(int *options); int (*getversion)(int *version); int (*checkfile)(char *urltype, char *infile, char *outfile); int (*open)(char *filename, int rwmode, int *driverhandle); int (*create)(char *filename, int *drivehandle); int (*truncate)(int drivehandle, LONGLONG size); int (*close)(int drivehandle); int (*remove)(char *filename); int (*size)(int drivehandle, LONGLONG *size); int (*flush)(int drivehandle); int (*seek)(int drivehandle, LONGLONG offset); int (*read)(int drivehandle, void *buffer, long nbytes); int (*write)(int drivehandle, void *buffer, long nbytes); } fitsdriver; fitsdriver driverTable[MAX_DRIVERS]; /* allocate driver tables */ FITSfile *FptrTable[NMAXFILES]; /* this table of Fptr pointers is */ /* used by fits_already_open */ int need_to_initialize = 1; /* true if CFITSIO has not been initialized */ int no_of_drivers = 0; /* number of currently defined I/O drivers */ static int pixel_filter_helper(fitsfile **fptr, char *outfile, char *expr, int *status); static int find_quote(char **string); static int find_doublequote(char **string); static int find_paren(char **string); static int find_bracket(char **string); static int find_curlybracket(char **string); int comma2semicolon(char *string); #ifdef _REENTRANT pthread_mutex_t Fitsio_InitLock = PTHREAD_MUTEX_INITIALIZER; #endif /*--------------------------------------------------------------------------*/ int fitsio_init_lock(void) { int status = 0; #ifdef _REENTRANT static int need_to_init = 1; pthread_mutexattr_t mutex_init; FFLOCK1(Fitsio_InitLock); if (need_to_init) { /* Init the main fitsio lock here since we need a a recursive lock */ status = pthread_mutexattr_init(&mutex_init); if (status) { ffpmsg("pthread_mutexattr_init failed (fitsio_init_lock)"); return(status); } #ifdef __GLIBC__ status = pthread_mutexattr_settype(&mutex_init, PTHREAD_MUTEX_RECURSIVE_NP); #else status = pthread_mutexattr_settype(&mutex_init, PTHREAD_MUTEX_RECURSIVE); #endif if (status) { ffpmsg("pthread_mutexattr_settype failed (fitsio_init_lock)"); return(status); } status = pthread_mutex_init(&Fitsio_Lock,&mutex_init); if (status) { ffpmsg("pthread_mutex_init failed (fitsio_init_lock)"); return(status); } need_to_init = 0; } FFUNLOCK1(Fitsio_InitLock); #endif return(status); } /*--------------------------------------------------------------------------*/ int ffomem(fitsfile **fptr, /* O - FITS file pointer */ const char *name, /* I - name of file to open */ int mode, /* I - 0 = open readonly; 1 = read/write */ void **buffptr, /* I - address of memory pointer */ size_t *buffsize, /* I - size of buffer, in bytes */ size_t deltasize, /* I - increment for future realloc's */ void *(*mem_realloc)(void *p, size_t newsize), /* function */ int *status) /* IO - error status */ /* Open an existing FITS file in core memory. This is a specialized version of ffopen. */ { int ii, driver, handle, hdutyp, slen, movetotype, extvers, extnum; char extname[FLEN_VALUE]; LONGLONG filesize; char urltype[MAX_PREFIX_LEN], infile[FLEN_FILENAME], outfile[FLEN_FILENAME]; char extspec[FLEN_FILENAME], rowfilter[FLEN_FILENAME]; char binspec[FLEN_FILENAME], colspec[FLEN_FILENAME]; char imagecolname[FLEN_VALUE], rowexpress[FLEN_FILENAME]; char *url, errmsg[FLEN_ERRMSG]; char *hdtype[3] = {"IMAGE", "TABLE", "BINTABLE"}; if (*status > 0) return(*status); *fptr = 0; /* initialize null file pointer */ if (need_to_initialize) /* this is called only once */ { *status = fits_init_cfitsio(); if (*status > 0) return(*status); } url = (char *) name; while (*url == ' ') /* ignore leading spaces in the file spec */ url++; /* parse the input file specification */ fits_parse_input_url(url, urltype, infile, outfile, extspec, rowfilter, binspec, colspec, status); strcpy(urltype, "memkeep://"); /* URL type for pre-existing memory file */ *status = urltype2driver(urltype, &driver); if (*status > 0) { ffpmsg("could not find driver for pre-existing memory file: (ffomem)"); return(*status); } /* call driver routine to open the memory file */ FFLOCK; /* lock this while searching for vacant handle */ *status = mem_openmem( buffptr, buffsize,deltasize, mem_realloc, &handle); FFUNLOCK; if (*status > 0) { ffpmsg("failed to open pre-existing memory file: (ffomem)"); return(*status); } /* get initial file size */ *status = (*driverTable[driver].size)(handle, &filesize); if (*status > 0) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed get the size of the memory file: (ffomem)"); return(*status); } /* allocate fitsfile structure and initialize = 0 */ *fptr = (fitsfile *) calloc(1, sizeof(fitsfile)); if (!(*fptr)) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate structure for following file: (ffomem)"); ffpmsg(url); return(*status = MEMORY_ALLOCATION); } /* allocate FITSfile structure and initialize = 0 */ (*fptr)->Fptr = (FITSfile *) calloc(1, sizeof(FITSfile)); if (!((*fptr)->Fptr)) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate structure for following file: (ffomem)"); ffpmsg(url); free(*fptr); *fptr = 0; return(*status = MEMORY_ALLOCATION); } slen = strlen(url) + 1; slen = maxvalue(slen, 32); /* reserve at least 32 chars */ ((*fptr)->Fptr)->filename = (char *) malloc(slen); /* mem for file name */ if ( !(((*fptr)->Fptr)->filename) ) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate memory for filename: (ffomem)"); ffpmsg(url); free((*fptr)->Fptr); free(*fptr); *fptr = 0; /* return null file pointer */ return(*status = MEMORY_ALLOCATION); } /* mem for headstart array */ ((*fptr)->Fptr)->headstart = (LONGLONG *) calloc(1001, sizeof(LONGLONG)); if ( !(((*fptr)->Fptr)->headstart) ) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate memory for headstart array: (ffomem)"); ffpmsg(url); free( ((*fptr)->Fptr)->filename); free((*fptr)->Fptr); free(*fptr); *fptr = 0; /* return null file pointer */ return(*status = MEMORY_ALLOCATION); } /* mem for file I/O buffers */ ((*fptr)->Fptr)->iobuffer = (char *) calloc(NIOBUF, IOBUFLEN); if ( !(((*fptr)->Fptr)->iobuffer) ) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate memory for iobuffer array: (ffomem)"); ffpmsg(url); free( ((*fptr)->Fptr)->headstart); /* free memory for headstart array */ free( ((*fptr)->Fptr)->filename); free((*fptr)->Fptr); free(*fptr); *fptr = 0; /* return null file pointer */ return(*status = MEMORY_ALLOCATION); } /* initialize the ageindex array (relative age of the I/O buffers) */ /* and initialize the bufrecnum array as being empty */ for (ii = 0; ii < NIOBUF; ii++) { ((*fptr)->Fptr)->ageindex[ii] = ii; ((*fptr)->Fptr)->bufrecnum[ii] = -1; } /* store the parameters describing the file */ ((*fptr)->Fptr)->MAXHDU = 1000; /* initial size of headstart */ ((*fptr)->Fptr)->filehandle = handle; /* file handle */ ((*fptr)->Fptr)->driver = driver; /* driver number */ strcpy(((*fptr)->Fptr)->filename, url); /* full input filename */ ((*fptr)->Fptr)->filesize = filesize; /* physical file size */ ((*fptr)->Fptr)->logfilesize = filesize; /* logical file size */ ((*fptr)->Fptr)->writemode = mode; /* read-write mode */ ((*fptr)->Fptr)->datastart = DATA_UNDEFINED; /* unknown start of data */ ((*fptr)->Fptr)->curbuf = -1; /* undefined current IO buffer */ ((*fptr)->Fptr)->open_count = 1; /* structure is currently used once */ ((*fptr)->Fptr)->validcode = VALIDSTRUC; /* flag denoting valid structure */ ffldrc(*fptr, 0, REPORT_EOF, status); /* load first record */ fits_store_Fptr( (*fptr)->Fptr, status); /* store Fptr address */ if (ffrhdu(*fptr, &hdutyp, status) > 0) /* determine HDU structure */ { ffpmsg( "ffomem could not interpret primary array header of file: (ffomem)"); ffpmsg(url); if (*status == UNKNOWN_REC) ffpmsg("This does not look like a FITS file."); ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ } /* ---------------------------------------------------------- */ /* move to desired extension, if specified as part of the URL */ /* ---------------------------------------------------------- */ imagecolname[0] = '\0'; rowexpress[0] = '\0'; if (*extspec) { /* parse the extension specifier into individual parameters */ ffexts(extspec, &extnum, extname, &extvers, &movetotype, imagecolname, rowexpress, status); if (*status > 0) return(*status); if (extnum) { ffmahd(*fptr, extnum + 1, &hdutyp, status); } else if (*extname) /* move to named extension, if specified */ { ffmnhd(*fptr, movetotype, extname, extvers, status); } if (*status > 0) { ffpmsg("ffomem could not move to the specified extension:"); if (extnum > 0) { snprintf(errmsg, FLEN_ERRMSG, " extension number %d doesn't exist or couldn't be opened.",extnum); ffpmsg(errmsg); } else { snprintf(errmsg, FLEN_ERRMSG, " extension with EXTNAME = %s,", extname); ffpmsg(errmsg); if (extvers) { snprintf(errmsg, FLEN_ERRMSG, " and with EXTVERS = %d,", extvers); ffpmsg(errmsg); } if (movetotype != ANY_HDU) { snprintf(errmsg, FLEN_ERRMSG, " and with XTENSION = %s,", hdtype[movetotype]); ffpmsg(errmsg); } ffpmsg(" doesn't exist or couldn't be opened."); } return(*status); } } return(*status); } /*--------------------------------------------------------------------------*/ int ffdkopn(fitsfile **fptr, /* O - FITS file pointer */ const char *name, /* I - full name of file to open */ int mode, /* I - 0 = open readonly; 1 = read/write */ int *status) /* IO - error status */ /* Open an existing FITS file on magnetic disk with either readonly or read/write access. The routine does not support CFITSIO's extended filename syntax and simply uses the entire input 'name' string as the name of the file. */ { if (*status > 0) return(*status); *status = OPEN_DISK_FILE; ffopen(fptr, name, mode, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffdopn(fitsfile **fptr, /* O - FITS file pointer */ const char *name, /* I - full name of file to open */ int mode, /* I - 0 = open readonly; 1 = read/write */ int *status) /* IO - error status */ /* Open an existing FITS file with either readonly or read/write access. and move to the first HDU that contains 'interesting' data, if the primary array contains a null image (i.e., NAXIS = 0). */ { if (*status > 0) return(*status); *status = SKIP_NULL_PRIMARY; ffopen(fptr, name, mode, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffeopn(fitsfile **fptr, /* O - FITS file pointer */ const char *name, /* I - full name of file to open */ int mode, /* I - 0 = open readonly; 1 = read/write */ char *extlist, /* I - list of 'good' extensions to move to */ int *hdutype, /* O - type of extension that is moved to */ int *status) /* IO - error status */ /* Open an existing FITS file with either readonly or read/write access. and if the primary array contains a null image (i.e., NAXIS = 0) then attempt to move to the first extension named in the extlist of extension names. If none are found, then simply move to the 2nd extension. */ { int hdunum, naxis, thdutype, gotext=0; char *ext, *textlist; char *saveptr; if (*status > 0) return(*status); if (ffopen(fptr, name, mode, status) > 0) return(*status); fits_get_hdu_num(*fptr, &hdunum); fits_get_img_dim(*fptr, &naxis, status); if( (hdunum == 1) && (naxis == 0) ){ /* look through the extension list */ if( extlist ){ gotext = 0; textlist = malloc(strlen(extlist) + 1); if (!textlist) { *status = MEMORY_ALLOCATION; return(*status); } strcpy(textlist, extlist); for(ext=(char *)ffstrtok(textlist, " ",&saveptr); ext != NULL; ext=(char *)ffstrtok(NULL," ",&saveptr)){ fits_movnam_hdu(*fptr, ANY_HDU, ext, 0, status); if( *status == 0 ){ gotext = 1; break; } else { *status = 0; } } free(textlist); } if( !gotext ){ /* if all else fails, move to extension #2 and hope for the best */ fits_movabs_hdu(*fptr, 2, &thdutype, status); } } fits_get_hdu_type(*fptr, hdutype, status); return(*status); } /*--------------------------------------------------------------------------*/ int fftopn(fitsfile **fptr, /* O - FITS file pointer */ const char *name, /* I - full name of file to open */ int mode, /* I - 0 = open readonly; 1 = read/write */ int *status) /* IO - error status */ /* Open an existing FITS file with either readonly or read/write access. and move to the first HDU that contains 'interesting' table (not an image). */ { int hdutype; if (*status > 0) return(*status); *status = SKIP_IMAGE; ffopen(fptr, name, mode, status); if (ffghdt(*fptr, &hdutype, status) <= 0) { if (hdutype == IMAGE_HDU) *status = NOT_TABLE; } return(*status); } /*--------------------------------------------------------------------------*/ int ffiopn(fitsfile **fptr, /* O - FITS file pointer */ const char *name, /* I - full name of file to open */ int mode, /* I - 0 = open readonly; 1 = read/write */ int *status) /* IO - error status */ /* Open an existing FITS file with either readonly or read/write access. and move to the first HDU that contains 'interesting' image (not an table). */ { int hdutype; if (*status > 0) return(*status); *status = SKIP_TABLE; ffopen(fptr, name, mode, status); if (ffghdt(*fptr, &hdutype, status) <= 0) { if (hdutype != IMAGE_HDU) *status = NOT_IMAGE; } return(*status); } /*--------------------------------------------------------------------------*/ int ffopentest(int soname, /* I - CFITSIO shared library version */ /* application program (fitsio.h file) */ fitsfile **fptr, /* O - FITS file pointer */ const char *name, /* I - full name of file to open */ int mode, /* I - 0 = open readonly; 1 = read/write */ int *status) /* IO - error status */ /* Open an existing FITS file with either readonly or read/write access. First test that the SONAME of fitsio.h used to build the CFITSIO library is the same as was used in compiling the application program that links to the library. */ { if (soname != CFITSIO_SONAME) { printf("\nERROR: Mismatch in the CFITSIO_SONAME value in the fitsio.h include file\n"); printf("that was used to build the CFITSIO library, and the value in the include file\n"); printf("that was used when compiling the application program:\n"); printf(" Version used to build the CFITSIO library = %d\n",CFITSIO_SONAME); printf(" Version included by the application program = %d\n",soname); printf("\nFix this by recompiling and then relinking this application program \n"); printf("with the CFITSIO library.\n"); *status = FILE_NOT_OPENED; return(*status); } /* now call the normal file open routine */ ffopen(fptr, name, mode, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffopen(fitsfile **fptr, /* O - FITS file pointer */ const char *name, /* I - full name of file to open */ int mode, /* I - 0 = open readonly; 1 = read/write */ int *status) /* IO - error status */ /* Open an existing FITS file with either readonly or read/write access. */ { fitsfile *newptr; int ii, driver, hdutyp, hdunum, slen, writecopy, isopen; LONGLONG filesize; long rownum, nrows, goodrows; int extnum, extvers, handle, movetotype, tstatus = 0, only_one = 0; char urltype[MAX_PREFIX_LEN], infile[FLEN_FILENAME], outfile[FLEN_FILENAME]; char origurltype[MAX_PREFIX_LEN], extspec[FLEN_FILENAME]; char extname[FLEN_VALUE], rowfilter[FLEN_FILENAME], tblname[FLEN_VALUE]; char imagecolname[FLEN_VALUE], rowexpress[FLEN_FILENAME]; char binspec[FLEN_FILENAME], colspec[FLEN_FILENAME], pixfilter[FLEN_FILENAME]; char histfilename[FLEN_FILENAME]; char filtfilename[FLEN_FILENAME], compspec[FLEN_FILENAME]; char wtcol[FLEN_VALUE]; char minname[4][FLEN_VALUE], maxname[4][FLEN_VALUE]; char binname[4][FLEN_VALUE]; char *url; double minin[4], maxin[4], binsizein[4], weight; int imagetype, naxis = 1, haxis, recip; int skip_null = 0, skip_image = 0, skip_table = 0, open_disk_file = 0; char colname[4][FLEN_VALUE]; char errmsg[FLEN_ERRMSG]; char *hdtype[3] = {"IMAGE", "TABLE", "BINTABLE"}; char *rowselect = 0; if (*status > 0) return(*status); if (*status == SKIP_NULL_PRIMARY) { /* this special status value is used as a flag by ffdopn to tell */ /* ffopen to skip over a null primary array when opening the file. */ skip_null = 1; *status = 0; } else if (*status == SKIP_IMAGE) { /* this special status value is used as a flag by fftopn to tell */ /* ffopen to move to 1st significant table when opening the file. */ skip_image = 1; *status = 0; } else if (*status == SKIP_TABLE) { /* this special status value is used as a flag by ffiopn to tell */ /* ffopen to move to 1st significant image when opening the file. */ skip_table = 1; *status = 0; } else if (*status == OPEN_DISK_FILE) { /* this special status value is used as a flag by ffdkopn to tell */ /* ffopen to not interpret the input filename using CFITSIO's */ /* extended filename syntax, and simply open the specified disk file */ open_disk_file = 1; *status = 0; } *fptr = 0; /* initialize null file pointer */ writecopy = 0; /* have we made a write-able copy of the input file? */ if (need_to_initialize) { /* this is called only once */ *status = fits_init_cfitsio(); } if (*status > 0) return(*status); url = (char *) name; while (*url == ' ') /* ignore leading spaces in the filename */ url++; if (*url == '\0') { ffpmsg("Name of file to open is blank. (ffopen)"); return(*status = FILE_NOT_OPENED); } if (open_disk_file) { /* treat the input URL literally as the name of the file to open */ /* and don't try to parse the URL using the extended filename syntax */ if (strlen(url) > FLEN_FILENAME - 1) { ffpmsg("Name of file to open is too long. (ffopen)"); return(*status = FILE_NOT_OPENED); } strcpy(infile,url); strcpy(urltype, "file://"); outfile[0] = '\0'; extspec[0] = '\0'; binspec[0] = '\0'; colspec[0] = '\0'; rowfilter[0] = '\0'; pixfilter[0] = '\0'; compspec[0] = '\0'; } else { /* parse the input file specification */ /* NOTE: This routine tests that all the strings do not */ /* overflow the standard buffer sizes (FLEN_FILENAME, etc.) */ /* therefore in general we do not have to worry about buffer */ /* overflow of any of the returned strings. */ /* call the newer version of this parsing routine that supports 'compspec' */ ffifile2(url, urltype, infile, outfile, extspec, rowfilter, binspec, colspec, pixfilter, compspec, status); } if (*status > 0) { ffpmsg("could not parse the input filename: (ffopen)"); ffpmsg(url); return(*status); } imagecolname[0] = '\0'; rowexpress[0] = '\0'; if (*extspec) { slen = strlen(extspec); if (extspec[slen - 1] == '#') { /* special symbol to mean only copy this extension */ extspec[slen - 1] = '\0'; only_one = 1; } /* parse the extension specifier into individual parameters */ ffexts(extspec, &extnum, extname, &extvers, &movetotype, imagecolname, rowexpress, status); if (*status > 0) return(*status); } /*-------------------------------------------------------------------*/ /* special cases: */ /*-------------------------------------------------------------------*/ histfilename[0] = '\0'; filtfilename[0] = '\0'; if (*outfile && (*binspec || *imagecolname || *pixfilter)) { /* if binspec or imagecolumn are specified, then the */ /* output file name is intended for the final image, */ /* and not a copy of the input file. */ strcpy(histfilename, outfile); outfile[0] = '\0'; } else if (*outfile && (*rowfilter || *colspec)) { /* if rowfilter or colspece are specified, then the */ /* output file name is intended for the filtered file */ /* and not a copy of the input file. */ strcpy(filtfilename, outfile); outfile[0] = '\0'; } /*-------------------------------------------------------------------*/ /* check if this same file is already open, and if so, attach to it */ /*-------------------------------------------------------------------*/ FFLOCK; if (fits_already_open(fptr, url, urltype, infile, extspec, rowfilter, binspec, colspec, mode, &isopen, status) > 0) { FFUNLOCK; return(*status); } FFUNLOCK; if (isopen) { goto move2hdu; } /* get the driver number corresponding to this urltype */ *status = urltype2driver(urltype, &driver); if (*status > 0) { ffpmsg("could not find driver for this file: (ffopen)"); ffpmsg(urltype); ffpmsg(url); return(*status); } /*------------------------------------------------------------------- deal with all those messy special cases which may require that a different driver be used: - is disk file compressed? - are ftp:, gsiftp:, or http: files compressed? - has user requested that a local copy be made of the ftp or http file? -------------------------------------------------------------------*/ if (driverTable[driver].checkfile) { strcpy(origurltype,urltype); /* Save the urltype */ /* 'checkfile' may modify the urltype, infile and outfile strings */ *status = (*driverTable[driver].checkfile)(urltype, infile, outfile); if (*status) { ffpmsg("checkfile failed for this file: (ffopen)"); ffpmsg(url); return(*status); } if (strcmp(origurltype, urltype)) /* did driver changed on us? */ { *status = urltype2driver(urltype, &driver); if (*status > 0) { ffpmsg("could not change driver for this file: (ffopen)"); ffpmsg(url); ffpmsg(urltype); return(*status); } } } /* call appropriate driver to open the file */ if (driverTable[driver].open) { FFLOCK; /* lock this while searching for vacant handle */ *status = (*driverTable[driver].open)(infile, mode, &handle); FFUNLOCK; if (*status > 0) { ffpmsg("failed to find or open the following file: (ffopen)"); ffpmsg(url); return(*status); } } else { ffpmsg("cannot open an existing file of this type: (ffopen)"); ffpmsg(url); return(*status = FILE_NOT_OPENED); } /* get initial file size */ *status = (*driverTable[driver].size)(handle, &filesize); if (*status > 0) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed get the size of the following file: (ffopen)"); ffpmsg(url); return(*status); } /* allocate fitsfile structure and initialize = 0 */ *fptr = (fitsfile *) calloc(1, sizeof(fitsfile)); if (!(*fptr)) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate structure for following file: (ffopen)"); ffpmsg(url); return(*status = MEMORY_ALLOCATION); } /* allocate FITSfile structure and initialize = 0 */ (*fptr)->Fptr = (FITSfile *) calloc(1, sizeof(FITSfile)); if (!((*fptr)->Fptr)) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate structure for following file: (ffopen)"); ffpmsg(url); free(*fptr); *fptr = 0; return(*status = MEMORY_ALLOCATION); } slen = strlen(url) + 1; slen = maxvalue(slen, 32); /* reserve at least 32 chars */ ((*fptr)->Fptr)->filename = (char *) malloc(slen); /* mem for file name */ if ( !(((*fptr)->Fptr)->filename) ) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate memory for filename: (ffopen)"); ffpmsg(url); free((*fptr)->Fptr); free(*fptr); *fptr = 0; /* return null file pointer */ return(*status = MEMORY_ALLOCATION); } /* mem for headstart array */ ((*fptr)->Fptr)->headstart = (LONGLONG *) calloc(1001, sizeof(LONGLONG)); if ( !(((*fptr)->Fptr)->headstart) ) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate memory for headstart array: (ffopen)"); ffpmsg(url); free( ((*fptr)->Fptr)->filename); free((*fptr)->Fptr); free(*fptr); *fptr = 0; /* return null file pointer */ return(*status = MEMORY_ALLOCATION); } /* mem for file I/O buffers */ ((*fptr)->Fptr)->iobuffer = (char *) calloc(NIOBUF, IOBUFLEN); if ( !(((*fptr)->Fptr)->iobuffer) ) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate memory for iobuffer array: (ffopen)"); ffpmsg(url); free( ((*fptr)->Fptr)->headstart); /* free memory for headstart array */ free( ((*fptr)->Fptr)->filename); free((*fptr)->Fptr); free(*fptr); *fptr = 0; /* return null file pointer */ return(*status = MEMORY_ALLOCATION); } /* initialize the ageindex array (relative age of the I/O buffers) */ /* and initialize the bufrecnum array as being empty */ for (ii = 0; ii < NIOBUF; ii++) { ((*fptr)->Fptr)->ageindex[ii] = ii; ((*fptr)->Fptr)->bufrecnum[ii] = -1; } /* store the parameters describing the file */ ((*fptr)->Fptr)->MAXHDU = 1000; /* initial size of headstart */ ((*fptr)->Fptr)->filehandle = handle; /* file handle */ ((*fptr)->Fptr)->driver = driver; /* driver number */ strcpy(((*fptr)->Fptr)->filename, url); /* full input filename */ ((*fptr)->Fptr)->filesize = filesize; /* physical file size */ ((*fptr)->Fptr)->logfilesize = filesize; /* logical file size */ ((*fptr)->Fptr)->writemode = mode; /* read-write mode */ ((*fptr)->Fptr)->datastart = DATA_UNDEFINED; /* unknown start of data */ ((*fptr)->Fptr)->curbuf = -1; /* undefined current IO buffer */ ((*fptr)->Fptr)->open_count = 1; /* structure is currently used once */ ((*fptr)->Fptr)->validcode = VALIDSTRUC; /* flag denoting valid structure */ ((*fptr)->Fptr)->only_one = only_one; /* flag denoting only copy single extension */ ffldrc(*fptr, 0, REPORT_EOF, status); /* load first record */ fits_store_Fptr( (*fptr)->Fptr, status); /* store Fptr address */ if (ffrhdu(*fptr, &hdutyp, status) > 0) /* determine HDU structure */ { ffpmsg( "ffopen could not interpret primary array header of file: "); ffpmsg(url); if (*status == UNKNOWN_REC) ffpmsg("This does not look like a FITS file."); ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ return(*status); } /* ------------------------------------------------------------- */ /* At this point, the input file has been opened. If outfile was */ /* specified, then we have opened a copy of the file, not the */ /* original file so it is safe to modify it if necessary */ /* ------------------------------------------------------------- */ if (*outfile) writecopy = 1; move2hdu: /* ---------------------------------------------------------- */ /* move to desired extension, if specified as part of the URL */ /* ---------------------------------------------------------- */ if (*extspec) { if (extnum) /* extension number was specified */ { ffmahd(*fptr, extnum + 1, &hdutyp, status); } else if (*extname) /* move to named extension, if specified */ { ffmnhd(*fptr, movetotype, extname, extvers, status); } if (*status > 0) /* clean up after error */ { ffpmsg("ffopen could not move to the specified extension:"); if (extnum > 0) { snprintf(errmsg, FLEN_ERRMSG, " extension number %d doesn't exist or couldn't be opened.",extnum); ffpmsg(errmsg); } else { snprintf(errmsg, FLEN_ERRMSG, " extension with EXTNAME = %s,", extname); ffpmsg(errmsg); if (extvers) { snprintf(errmsg, FLEN_ERRMSG, " and with EXTVERS = %d,", extvers); ffpmsg(errmsg); } if (movetotype != ANY_HDU) { snprintf(errmsg, FLEN_ERRMSG, " and with XTENSION = %s,", hdtype[movetotype]); ffpmsg(errmsg); } ffpmsg(" doesn't exist or couldn't be opened."); } ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ return(*status); } } else if (skip_null || skip_image || skip_table || (*imagecolname || *colspec || *rowfilter || *binspec)) { /* ------------------------------------------------------------------ If no explicit extension specifier is given as part of the file name, and, if a) skip_null is true (set if ffopen is called by ffdopn) or b) skip_image or skip_table is true (set if ffopen is called by fftopn or ffdopn) or c) other file filters are specified, then CFITSIO will attempt to move to the first 'interesting' HDU after opening an existing FITS file (or to first interesting table HDU if skip_image is true); An 'interesting' HDU is defined to be either an image with NAXIS > 0 (i.e., not a null array) or a table which has an EXTNAME value which does not contain any of the following strings: 'GTI' - Good Time Interval extension 'OBSTABLE' - used in Beppo SAX data files The main purpose for this is to allow CFITSIO to skip over a null primary and other non-interesting HDUs when opening an existing file, and move directly to the first extension that contains significant data. ------------------------------------------------------------------ */ fits_get_hdu_num(*fptr, &hdunum); if (hdunum == 1) { fits_get_img_dim(*fptr, &naxis, status); if (naxis == 0 || skip_image) /* skip primary array */ { while(1) { /* see if the next HDU is 'interesting' */ if (fits_movrel_hdu(*fptr, 1, &hdutyp, status)) { if (*status == END_OF_FILE) *status = 0; /* reset expected error */ /* didn't find an interesting HDU so move back to beginning */ fits_movabs_hdu(*fptr, 1, &hdutyp, status); break; } if (hdutyp == IMAGE_HDU && skip_image) { continue; /* skip images */ } else if (hdutyp != IMAGE_HDU && skip_table) { continue; /* skip tables */ } else if (hdutyp == IMAGE_HDU) { fits_get_img_dim(*fptr, &naxis, status); if (naxis > 0) break; /* found a non-null image */ } else { tstatus = 0; tblname[0] = '\0'; fits_read_key(*fptr, TSTRING, "EXTNAME", tblname, NULL,&tstatus); if ( (!strstr(tblname, "GTI") && !strstr(tblname, "gti")) && fits_strncasecmp(tblname, "OBSTABLE", 8) ) break; /* found an interesting table */ } } /* end while */ } } /* end if (hdunum==1) */ } if (*imagecolname) { /* ----------------------------------------------------------------- */ /* we need to open an image contained in a single table cell */ /* First, determine which row of the table to use. */ /* ----------------------------------------------------------------- */ if (isdigit((int) *rowexpress)) /* is the row specification a number? */ { sscanf(rowexpress, "%ld", &rownum); if (rownum < 1) { ffpmsg("illegal rownum for image cell:"); ffpmsg(rowexpress); ffpmsg("Could not open the following image in a table cell:"); ffpmsg(extspec); ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ return(*status = BAD_ROW_NUM); } } else if (fits_find_first_row(*fptr, rowexpress, &rownum, status) > 0) { ffpmsg("Failed to find row matching this expression:"); ffpmsg(rowexpress); ffpmsg("Could not open the following image in a table cell:"); ffpmsg(extspec); ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ return(*status); } if (rownum == 0) { ffpmsg("row statisfying this expression doesn't exist::"); ffpmsg(rowexpress); ffpmsg("Could not open the following image in a table cell:"); ffpmsg(extspec); ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ return(*status = BAD_ROW_NUM); } /* determine the name of the new file to contain copy of the image */ if (*histfilename && !(*pixfilter) ) strcpy(outfile, histfilename); /* the original outfile name */ else strcpy(outfile, "mem://_1"); /* create image file in memory */ /* Copy the image into new primary array and open it as the current */ /* fptr. This will close the table that contains the original image. */ /* create new empty file to hold copy of the image */ if (ffinit(&newptr, outfile, status) > 0) { ffpmsg("failed to create file for copy of image in table cell:"); ffpmsg(outfile); return(*status); } if (fits_copy_cell2image(*fptr, newptr, imagecolname, rownum, status) > 0) { ffpmsg("Failed to copy table cell to new primary array:"); ffpmsg(extspec); ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ return(*status); } /* close the original file and set fptr to the new image */ ffclos(*fptr, status); *fptr = newptr; /* reset the pointer to the new table */ writecopy = 1; /* we are now dealing with a copy of the original file */ /* leave it up to calling routine to write any HISTORY keywords */ } /* --------------------------------------------------------------------- */ /* edit columns (and/or keywords) in the table, if specified in the URL */ /* --------------------------------------------------------------------- */ if (*colspec) { /* the column specifier will modify the file, so make sure */ /* we are already dealing with a copy, or else make a new copy */ if (!writecopy) /* Is the current file already a copy? */ writecopy = fits_is_this_a_copy(urltype); if (!writecopy) { if (*filtfilename && *outfile == '\0') strcpy(outfile, filtfilename); /* the original outfile name */ else strcpy(outfile, "mem://_1"); /* will create copy in memory */ writecopy = 1; } else { ((*fptr)->Fptr)->writemode = READWRITE; /* we have write access */ outfile[0] = '\0'; } if (ffedit_columns(fptr, outfile, colspec, status) > 0) { ffpmsg("editing columns in input table failed (ffopen)"); ffpmsg(" while trying to perform the following operation:"); ffpmsg(colspec); ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ return(*status); } } /* ------------------------------------------------------------------- */ /* select rows from the table, if specified in the URL */ /* or select a subimage (if this is an image HDU and not a table) */ /* ------------------------------------------------------------------- */ if (*rowfilter) { fits_get_hdu_type(*fptr, &hdutyp, status); /* get type of HDU */ if (hdutyp == IMAGE_HDU) { /* this is an image so 'rowfilter' is an image section specification */ if (*filtfilename && *outfile == '\0') strcpy(outfile, filtfilename); /* the original outfile name */ else if (*outfile == '\0') /* output file name not already defined? */ strcpy(outfile, "mem://_2"); /* will create file in memory */ /* create new file containing the image section, plus a copy of */ /* any other HDUs that exist in the input file. This routine */ /* will close the original image file and return a pointer */ /* to the new file. */ if (fits_select_image_section(fptr, outfile, rowfilter, status) > 0) { ffpmsg("on-the-fly selection of image section failed (ffopen)"); ffpmsg(" while trying to use the following section filter:"); ffpmsg(rowfilter); ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ return(*status); } } else { /* this is a table HDU, so the rowfilter is really a row filter */ if (*binspec) { /* since we are going to make a histogram of the selected rows, */ /* it would be a waste of time and memory to make a whole copy of */ /* the selected rows. Instead, just construct an array of TRUE */ /* or FALSE values that indicate which rows are to be included */ /* in the histogram and pass that to the histogram generating */ /* routine */ fits_get_num_rows(*fptr, &nrows, status); /* get no. of rows */ rowselect = (char *) calloc(nrows, 1); if (!rowselect) { ffpmsg( "failed to allocate memory for selected columns array (ffopen)"); ffpmsg(" while trying to select rows with the following filter:"); ffpmsg(rowfilter); ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ return(*status = MEMORY_ALLOCATION); } if (fits_find_rows(*fptr, rowfilter, 1L, nrows, &goodrows, rowselect, status) > 0) { ffpmsg("selection of rows in input table failed (ffopen)"); ffpmsg(" while trying to select rows with the following filter:"); ffpmsg(rowfilter); free(rowselect); ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ return(*status); } } else { if (!writecopy) /* Is the current file already a copy? */ writecopy = fits_is_this_a_copy(urltype); if (!writecopy) { if (*filtfilename && *outfile == '\0') strcpy(outfile, filtfilename); /* the original outfile name */ else if (*outfile == '\0') /* output filename not already defined? */ strcpy(outfile, "mem://_2"); /* will create copy in memory */ } else { ((*fptr)->Fptr)->writemode = READWRITE; /* we have write access */ outfile[0] = '\0'; } /* select rows in the table. If a copy of the input file has */ /* not already been made, then this routine will make a copy */ /* and then close the input file, so that the modifications will */ /* only be made on the copy, not the original */ if (ffselect_table(fptr, outfile, rowfilter, status) > 0) { ffpmsg("on-the-fly selection of rows in input table failed (ffopen)"); ffpmsg(" while trying to select rows with the following filter:"); ffpmsg(rowfilter); ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ return(*status); } /* write history records */ ffphis(*fptr, "CFITSIO used the following filtering expression to create this table:", status); ffphis(*fptr, name, status); } /* end of no binspec case */ } /* end of table HDU case */ } /* end of rowfilter exists case */ /* ------------------------------------------------------------------- */ /* make an image histogram by binning columns, if specified in the URL */ /* ------------------------------------------------------------------- */ if (*binspec) { if (*histfilename && !(*pixfilter) ) strcpy(outfile, histfilename); /* the original outfile name */ else strcpy(outfile, "mem://_3"); /* create histogram in memory */ /* if not already copied the file */ /* parse the binning specifier into individual parameters */ ffbins(binspec, &imagetype, &haxis, colname, minin, maxin, binsizein, minname, maxname, binname, &weight, wtcol, &recip, status); /* Create the histogram primary array and open it as the current fptr */ /* This will close the table that was used to create the histogram. */ ffhist2(fptr, outfile, imagetype, haxis, colname, minin, maxin, binsizein, minname, maxname, binname, weight, wtcol, recip, rowselect, status); if (rowselect) free(rowselect); if (*status > 0) { ffpmsg("on-the-fly histogramming of input table failed (ffopen)"); ffpmsg(" while trying to execute the following histogram specification:"); ffpmsg(binspec); ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ return(*status); } /* write history records */ ffphis(*fptr, "CFITSIO used the following expression to create this histogram:", status); ffphis(*fptr, name, status); } if (*pixfilter) { if (*histfilename) strcpy(outfile, histfilename); /* the original outfile name */ else strcpy(outfile, "mem://_4"); /* create in memory */ /* if not already copied the file */ /* Ensure type of HDU is consistent with pixel filtering */ fits_get_hdu_type(*fptr, &hdutyp, status); /* get type of HDU */ if (hdutyp == IMAGE_HDU) { pixel_filter_helper(fptr, outfile, pixfilter, status); if (*status > 0) { ffpmsg("pixel filtering of input image failed (ffopen)"); ffpmsg(" while trying to execute the following:"); ffpmsg(pixfilter); ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ return(*status); } /* write history records */ ffphis(*fptr, "CFITSIO used the following expression to create this image:", status); ffphis(*fptr, name, status); } else { ffpmsg("cannot use pixel filter on non-IMAGE HDU"); ffpmsg(pixfilter); ffclos(*fptr, status); *fptr = 0; /* return null file pointer */ *status = NOT_IMAGE; return(*status); } } /* parse and save image compression specification, if given */ if (*compspec) { ffparsecompspec(*fptr, compspec, status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffreopen(fitsfile *openfptr, /* I - FITS file pointer to open file */ fitsfile **newfptr, /* O - pointer to new re opened file */ int *status) /* IO - error status */ /* Reopen an existing FITS file with either readonly or read/write access. The reopened file shares the same FITSfile structure but may point to a different HDU within the file. */ { if (*status > 0) return(*status); /* check that the open file pointer is valid */ if (!openfptr) return(*status = NULL_INPUT_PTR); else if ((openfptr->Fptr)->validcode != VALIDSTRUC) /* check magic value */ return(*status = BAD_FILEPTR); /* allocate fitsfile structure and initialize = 0 */ *newfptr = (fitsfile *) calloc(1, sizeof(fitsfile)); (*newfptr)->Fptr = openfptr->Fptr; /* both point to the same structure */ (*newfptr)->HDUposition = 0; /* set initial position to primary array */ (((*newfptr)->Fptr)->open_count)++; /* increment the file usage counter */ return(*status); } /*--------------------------------------------------------------------------*/ int fits_store_Fptr(FITSfile *Fptr, /* O - FITS file pointer */ int *status) /* IO - error status */ /* store the new Fptr address for future use by fits_already_open */ { int ii; if (*status > 0) return(*status); FFLOCK; for (ii = 0; ii < NMAXFILES; ii++) { if (FptrTable[ii] == 0) { FptrTable[ii] = Fptr; break; } } FFUNLOCK; return(*status); } /*--------------------------------------------------------------------------*/ int fits_clear_Fptr(FITSfile *Fptr, /* O - FITS file pointer */ int *status) /* IO - error status */ /* clear the Fptr address from the Fptr Table */ { int ii; FFLOCK; for (ii = 0; ii < NMAXFILES; ii++) { if (FptrTable[ii] == Fptr) { FptrTable[ii] = 0; break; } } FFUNLOCK; return(*status); } /*--------------------------------------------------------------------------*/ int fits_already_open(fitsfile **fptr, /* I/O - FITS file pointer */ char *url, char *urltype, char *infile, char *extspec, char *rowfilter, char *binspec, char *colspec, int mode, /* I - 0 = open readonly; 1 = read/write */ int *isopen, /* O - 1 = file is already open */ int *status) /* IO - error status */ /* Check if the file to be opened is already open. If so, then attach to it. */ /* the input strings must not exceed the standard lengths */ /* of FLEN_FILENAME, MAX_PREFIX_LEN, etc. */ /* this function was changed so that for files of access method FILE:// the file paths are compared using standard URL syntax and absolute paths (as opposed to relative paths). This eliminates some instances where a file is already opened but it is not realized because it was opened with another file path. For instance, if the CWD is /a/b/c and I open /a/b/c/foo.fits then open ./foo.fits the previous version of this function would not have reconized that the two files were the same. This version does recognize that the two files are the same. */ { FITSfile *oldFptr; int ii; char oldurltype[MAX_PREFIX_LEN], oldinfile[FLEN_FILENAME]; char oldextspec[FLEN_FILENAME], oldoutfile[FLEN_FILENAME]; char oldrowfilter[FLEN_FILENAME]; char oldbinspec[FLEN_FILENAME], oldcolspec[FLEN_FILENAME]; char cwd[FLEN_FILENAME]; char tmpStr[FLEN_FILENAME]; char tmpinfile[FLEN_FILENAME]; *isopen = 0; /* When opening a file with readonly access then we simply let the operating system open the file again, instead of using the CFITSIO trick of attaching to the previously opened file. This is required if CFITSIO is running in a multi-threaded environment, because 2 different threads cannot share the same FITSfile pointer. If the file is opened/reopened with write access, then the file MUST only be physically opened once.. */ if (mode == 0) return(*status); if(fits_strcasecmp(urltype,"FILE://") == 0) { fits_path2url(infile,tmpinfile,status); if(tmpinfile[0] != '/') { fits_get_cwd(cwd,status); strcat(cwd,"/"); if (strlen(cwd) + strlen(tmpinfile) > FLEN_FILENAME-1) { ffpmsg("File name is too long. (fits_already_open)"); return(*status = FILE_NOT_OPENED); } strcat(cwd,tmpinfile); fits_clean_url(cwd,tmpinfile,status); } } else strcpy(tmpinfile,infile); for (ii = 0; ii < NMAXFILES; ii++) /* check every buffer */ { if (FptrTable[ii] != 0) { oldFptr = FptrTable[ii]; fits_parse_input_url(oldFptr->filename, oldurltype, oldinfile, oldoutfile, oldextspec, oldrowfilter, oldbinspec, oldcolspec, status); if (*status > 0) { ffpmsg("could not parse the previously opened filename: (ffopen)"); ffpmsg(oldFptr->filename); return(*status); } if(fits_strcasecmp(oldurltype,"FILE://") == 0) { fits_path2url(oldinfile,tmpStr,status); if(tmpStr[0] != '/') { fits_get_cwd(cwd,status); strcat(cwd,"/"); strcat(cwd,tmpStr); fits_clean_url(cwd,tmpStr,status); } strcpy(oldinfile,tmpStr); } if (!strcmp(urltype, oldurltype) && !strcmp(tmpinfile, oldinfile) ) { /* identical type of file and root file name */ if ( (!rowfilter[0] && !oldrowfilter[0] && !binspec[0] && !oldbinspec[0] && !colspec[0] && !oldcolspec[0]) /* no filtering or binning specs for either file, so */ /* this is a case where the same file is being reopened. */ /* It doesn't matter if the extensions are different */ || /* or */ (!strcmp(rowfilter, oldrowfilter) && !strcmp(binspec, oldbinspec) && !strcmp(colspec, oldcolspec) && !strcmp(extspec, oldextspec) ) ) /* filtering specs are given and are identical, and */ /* the same extension is specified */ { if (mode == READWRITE && oldFptr->writemode == READONLY) { /* cannot assume that a file previously opened with READONLY can now be written to (e.g., files on CDROM, or over the the network, or STDIN), so return with an error. */ ffpmsg( "cannot reopen file READWRITE when previously opened READONLY"); ffpmsg(url); return(*status = FILE_NOT_OPENED); } *fptr = (fitsfile *) calloc(1, sizeof(fitsfile)); if (!(*fptr)) { ffpmsg( "failed to allocate structure for following file: (ffopen)"); ffpmsg(url); return(*status = MEMORY_ALLOCATION); } (*fptr)->Fptr = oldFptr; /* point to the structure */ (*fptr)->HDUposition = 0; /* set initial position */ (((*fptr)->Fptr)->open_count)++; /* increment usage counter */ if (binspec[0]) /* if binning specified, don't move */ extspec[0] = '\0'; /* all the filtering has already been applied, so ignore */ rowfilter[0] = '\0'; binspec[0] = '\0'; colspec[0] = '\0'; *isopen = 1; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int fits_is_this_a_copy(char *urltype) /* I - type of file */ /* specialized routine that returns 1 if the file is known to be a temporary copy of the originally opened file. Otherwise it returns 0. */ { int iscopy; if (!strncmp(urltype, "mem", 3) ) iscopy = 1; /* file copy is in memory */ else if (!strncmp(urltype, "compress", 8) ) iscopy = 1; /* compressed diskfile that is uncompressed in memory */ else if (!strncmp(urltype, "http", 4) ) iscopy = 1; /* copied file using http protocol */ else if (!strncmp(urltype, "ftp", 3) ) iscopy = 1; /* copied file using ftp protocol */ else if (!strncmp(urltype, "gsiftp", 6) ) iscopy = 1; /* copied file using gsiftp protocol */ else if (!strncpy(urltype, "stdin", 5) ) iscopy = 1; /* piped stdin has been copied to memory */ else iscopy = 0; /* file is not known to be a copy */ return(iscopy); } /*--------------------------------------------------------------------------*/ static int find_quote(char **string) /* look for the closing single quote character in the input string */ { char *tstr; tstr = *string; while (*tstr) { if (*tstr == '\'') { /* found the closing quote */ *string = tstr + 1; /* set pointer to next char */ return(0); } else { /* skip over any other character */ tstr++; } } return(1); /* opps, didn't find the closing character */ } /*--------------------------------------------------------------------------*/ static int find_doublequote(char **string) /* look for the closing double quote character in the input string */ { char *tstr; tstr = *string; while (*tstr) { if (*tstr == '"') { /* found the closing quote */ *string = tstr + 1; /* set pointer to next char */ return(0); } else { /* skip over any other character */ tstr++; } } return(1); /* opps, didn't find the closing character */ } /*--------------------------------------------------------------------------*/ static int find_paren(char **string) /* look for the closing parenthesis character in the input string */ { char *tstr; tstr = *string; while (*tstr) { if (*tstr == ')') { /* found the closing parens */ *string = tstr + 1; /* set pointer to next char */ return(0); } else if (*tstr == '(') { /* found another level of parens */ tstr++; if (find_paren(&tstr)) return(1); } else if (*tstr == '[') { tstr++; if (find_bracket(&tstr)) return(1); } else if (*tstr == '{') { tstr++; if (find_curlybracket(&tstr)) return(1); } else if (*tstr == '"') { tstr++; if (find_doublequote(&tstr)) return(1); } else if (*tstr == '\'') { tstr++; if (find_quote(&tstr)) return(1); } else { tstr++; } } return(1); /* opps, didn't find the closing character */ } /*--------------------------------------------------------------------------*/ static int find_bracket(char **string) /* look for the closing bracket character in the input string */ { char *tstr; tstr = *string; while (*tstr) { if (*tstr == ']') { /* found the closing bracket */ *string = tstr + 1; /* set pointer to next char */ return(0); } else if (*tstr == '(') { /* found another level of parens */ tstr++; if (find_paren(&tstr)) return(1); } else if (*tstr == '[') { tstr++; if (find_bracket(&tstr)) return(1); } else if (*tstr == '{') { tstr++; if (find_curlybracket(&tstr)) return(1); } else if (*tstr == '"') { tstr++; if (find_doublequote(&tstr)) return(1); } else if (*tstr == '\'') { tstr++; if (find_quote(&tstr)) return(1); } else { tstr++; } } return(1); /* opps, didn't find the closing character */ } /*--------------------------------------------------------------------------*/ static int find_curlybracket(char **string) /* look for the closing curly bracket character in the input string */ { char *tstr; tstr = *string; while (*tstr) { if (*tstr == '}') { /* found the closing curly bracket */ *string = tstr + 1; /* set pointer to next char */ return(0); } else if (*tstr == '(') { /* found another level of parens */ tstr++; if (find_paren(&tstr)) return(1); } else if (*tstr == '[') { tstr++; if (find_bracket(&tstr)) return(1); } else if (*tstr == '{') { tstr++; if (find_curlybracket(&tstr)) return(1); } else if (*tstr == '"') { tstr++; if (find_doublequote(&tstr)) return(1); } else if (*tstr == '\'') { tstr++; if (find_quote(&tstr)) return(1); } else { tstr++; } } return(1); /* opps, didn't find the closing character */ } /*--------------------------------------------------------------------------*/ int comma2semicolon(char *string) /* replace commas with semicolons, unless the comma is within a quoted or bracketed expression */ { char *tstr; tstr = string; while (*tstr) { if (*tstr == ',') { /* found a comma */ *tstr = ';'; tstr++; } else if (*tstr == '(') { /* found another level of parens */ tstr++; if (find_paren(&tstr)) return(1); } else if (*tstr == '[') { tstr++; if (find_bracket(&tstr)) return(1); } else if (*tstr == '{') { tstr++; if (find_curlybracket(&tstr)) return(1); } else if (*tstr == '"') { tstr++; if (find_doublequote(&tstr)) return(1); } else if (*tstr == '\'') { tstr++; if (find_quote(&tstr)) return(1); } else { tstr++; } } return(0); /* reached end of string */ } /*--------------------------------------------------------------------------*/ int ffedit_columns( fitsfile **fptr, /* IO - pointer to input table; on output it */ /* points to the new selected rows table */ char *outfile, /* I - name for output file */ char *expr, /* I - column edit expression */ int *status) /* modify columns in a table and/or header keywords in the HDU */ { fitsfile *newptr; int ii, hdunum, slen, colnum = -1, testnum, deletecol = 0, savecol = 0; int numcols = 0, *colindex = 0, tstatus = 0; char *cptr, *cptr2, *cptr3, *clause = NULL, keyname[FLEN_KEYWORD]; char colname[FLEN_VALUE], oldname[FLEN_VALUE], colformat[FLEN_VALUE]; char *file_expr = NULL, testname[FLEN_VALUE], card[FLEN_CARD]; if (*outfile) { /* create new empty file in to hold the selected rows */ if (ffinit(&newptr, outfile, status) > 0) { ffpmsg("failed to create file for copy (ffedit_columns)"); return(*status); } fits_get_hdu_num(*fptr, &hdunum); /* current HDU number in input file */ /* copy all HDUs to the output copy, if the 'only_one' flag is not set */ if (!((*fptr)->Fptr)->only_one) { for (ii = 1; 1; ii++) { if (fits_movabs_hdu(*fptr, ii, NULL, status) > 0) break; fits_copy_hdu(*fptr, newptr, 0, status); } if (*status == END_OF_FILE) { *status = 0; /* got the expected EOF error; reset = 0 */ } else if (*status > 0) { ffclos(newptr, status); ffpmsg("failed to copy all HDUs from input file (ffedit_columns)"); return(*status); } } else { /* only copy the primary array and the designated table extension */ fits_movabs_hdu(*fptr, 1, NULL, status); fits_copy_hdu(*fptr, newptr, 0, status); fits_movabs_hdu(*fptr, hdunum, NULL, status); fits_copy_hdu(*fptr, newptr, 0, status); if (*status > 0) { ffclos(newptr, status); ffpmsg("failed to copy all HDUs from input file (ffedit_columns)"); return(*status); } hdunum = 2; } /* close the original file and return ptr to the new image */ ffclos(*fptr, status); *fptr = newptr; /* reset the pointer to the new table */ /* move back to the selected table HDU */ if (fits_movabs_hdu(*fptr, hdunum, NULL, status) > 0) { ffpmsg("failed to copy the input file (ffedit_columns)"); return(*status); } } /* remove the "col " from the beginning of the column edit expression */ cptr = expr + 4; while (*cptr == ' ') cptr++; /* skip leading white space */ /* Check if need to import expression from a file */ if( *cptr=='@' ) { if( ffimport_file( cptr+1, &file_expr, status ) ) return(*status); cptr = file_expr; while (*cptr == ' ') cptr++; /* skip leading white space... again */ } tstatus = 0; ffgncl(*fptr, &numcols, &tstatus); /* get initial # of cols */ /* as of July 2012, the CFITSIO column filter syntax was modified */ /* so that commas may be used to separate clauses, as well as semi-colons. */ /* This was done because users cannot enter the semi-colon in the HEASARC's */ /* Hera on-line data processing system for computer security reasons. */ /* Therefore, we must convert those commas back to semi-colons here, but we */ /* must not convert any columns that occur within parenthesies. */ if (comma2semicolon(cptr)) { ffpmsg("parsing error in column filter expression"); ffpmsg(cptr); if( file_expr ) free( file_expr ); *status = PARSE_SYNTAX_ERR; return(*status); } /* parse expression and get first clause, if more than 1 */ while ((slen = fits_get_token2(&cptr, ";", &clause, NULL, status)) > 0 ) { if( *cptr==';' ) cptr++; clause[slen] = '\0'; if (clause[0] == '!' || clause[0] == '-') { /* ===================================== */ /* Case I. delete this column or keyword */ /* ===================================== */ if (ffgcno(*fptr, CASEINSEN, &clause[1], &colnum, status) <= 0) { /* a column with this name exists, so try to delete it */ if (ffdcol(*fptr, colnum, status) > 0) { ffpmsg("failed to delete column in input file:"); ffpmsg(clause); if( colindex ) free( colindex ); if( file_expr ) free( file_expr ); if( clause ) free(clause); return(*status); } deletecol = 1; /* set flag that at least one col was deleted */ numcols--; colnum = -1; } else { ffcmsg(); /* clear previous error message from ffgcno */ /* try deleting a keyword with this name */ *status = 0; if (ffdkey(*fptr, &clause[1], status) > 0) { ffpmsg("column or keyword to be deleted does not exist:"); ffpmsg(clause); if( colindex ) free( colindex ); if( file_expr ) free( file_expr ); if( clause ) free(clause); return(*status); } } } else { /* ===================================================== */ /* Case II: this is either a column name, (case 1) or a new column name followed by double = ("==") followed by the old name which is to be renamed. (case 2A) or a column or keyword name followed by a single "=" and a calculation expression (case 2B) */ /* ===================================================== */ cptr2 = clause; slen = fits_get_token(&cptr2, "( =", colname, NULL); if (slen == 0) { ffpmsg("error: column or keyword name is blank:"); ffpmsg(clause); if( colindex ) free( colindex ); if( file_expr ) free( file_expr ); if (clause) free(clause); return(*status= URL_PARSE_ERROR); } /* If this is a keyword of the form #KEYWORD# then transform to the form #KEYWORDn where n is the previously used column number */ if (colname[0] == '#' && strstr(colname+1, "#") == (colname + strlen(colname) - 1)) { if (colnum <= 0) { ffpmsg("The keyword name:"); ffpmsg(colname); ffpmsg("is invalid unless a column has been previously"); ffpmsg("created or editted by a calculator command"); if( file_expr ) free( file_expr ); if (clause) free(clause); return(*status = URL_PARSE_ERROR); } colname[strlen(colname)-1] = '\0'; /* Make keyword name and put it in oldname */ ffkeyn(colname+1, colnum, oldname, status); if (*status) return (*status); /* Re-copy back into colname */ strcpy(colname+1,oldname); } else if (strstr(colname, "#") == (colname + strlen(colname) - 1)) { /* colname is of the form "NAME#"; if a) colnum is defined, and b) a column with literal name "NAME#" does not exist, and c) a keyword with name "NAMEn" (where n=colnum) exists, then transfrom the colname string to "NAMEn", otherwise do nothing. */ if (colnum > 0) { /* colnum must be defined */ tstatus = 0; ffgcno(*fptr, CASEINSEN, colname, &testnum, &tstatus); if (tstatus != 0 && tstatus != COL_NOT_UNIQUE) { /* OK, column doesn't exist, now see if keyword exists */ ffcmsg(); /* clear previous error message from ffgcno */ strcpy(testname, colname); testname[strlen(testname)-1] = '\0'; /* Make keyword name and put it in oldname */ ffkeyn(testname, colnum, oldname, status); if (*status) { if( file_expr ) free( file_expr ); if (clause) free(clause); return (*status); } tstatus = 0; if (!fits_read_card(*fptr, oldname, card, &tstatus)) { /* Keyword does exist; copy real name back into colname */ strcpy(colname,oldname); } } } } /* if we encountered an opening parenthesis, then we need to */ /* find the closing parenthesis, and concatinate the 2 strings */ /* This supports expressions like: [col #EXTNAME(Extension name)="GTI"] */ if (*cptr2 == '(') { fits_get_token(&cptr2, ")", oldname, NULL); strcat(colname, oldname); strcat(colname, ")"); cptr2++; } while (*cptr2 == ' ') cptr2++; /* skip white space */ if (*cptr2 != '=') { /* ------------------------------------ */ /* case 1 - simply the name of a column */ /* ------------------------------------ */ /* look for matching column */ ffgcno(*fptr, CASEINSEN, colname, &testnum, status); while (*status == COL_NOT_UNIQUE) { /* the column name contained wild cards, and it */ /* matches more than one column in the table. */ colnum = testnum; /* keep this column in the output file */ savecol = 1; if (!colindex) colindex = (int *) calloc(999, sizeof(int)); colindex[colnum - 1] = 1; /* flag this column number */ /* look for other matching column names */ ffgcno(*fptr, CASEINSEN, colname, &testnum, status); if (*status == COL_NOT_FOUND) *status = 999; /* temporary status flag value */ } if (*status <= 0) { colnum = testnum; /* keep this column in the output file */ savecol = 1; if (!colindex) colindex = (int *) calloc(999, sizeof(int)); colindex[colnum - 1] = 1; /* flag this column number */ } else if (*status == 999) { /* this special flag value does not represent an error */ *status = 0; } else { ffpmsg("Syntax error in columns specifier in input URL:"); ffpmsg(cptr2); if( colindex ) free( colindex ); if( file_expr ) free( file_expr ); if (clause) free(clause); return(*status = URL_PARSE_ERROR); } } else { /* ----------------------------------------------- */ /* case 2 where the token ends with an equals sign */ /* ----------------------------------------------- */ cptr2++; /* skip over the first '=' */ if (*cptr2 == '=') { /*................................................. */ /* Case A: rename a column or keyword; syntax is "new_name == old_name" */ /*................................................. */ cptr2++; /* skip the 2nd '=' */ while (*cptr2 == ' ') cptr2++; /* skip white space */ fits_get_token(&cptr2, " ", oldname, NULL); /* get column number of the existing column */ if (ffgcno(*fptr, CASEINSEN, oldname, &colnum, status) <= 0) { /* modify the TTYPEn keyword value with the new name */ ffkeyn("TTYPE", colnum, keyname, status); if (ffmkys(*fptr, keyname, colname, NULL, status) > 0) { ffpmsg("failed to rename column in input file"); ffpmsg(" oldname ="); ffpmsg(oldname); ffpmsg(" newname ="); ffpmsg(colname); if( colindex ) free( colindex ); if( file_expr ) free( file_expr ); if (clause) free(clause); return(*status); } /* keep this column in the output file */ savecol = 1; if (!colindex) colindex = (int *) calloc(999, sizeof(int)); colindex[colnum - 1] = 1; /* flag this column number */ } else { /* try renaming a keyword */ ffcmsg(); /* clear error message stack */ *status = 0; if (ffmnam(*fptr, oldname, colname, status) > 0) { ffpmsg("column or keyword to be renamed does not exist:"); ffpmsg(clause); if( colindex ) free( colindex ); if( file_expr ) free( file_expr ); if (clause) free(clause); return(*status); } } } else { /*...................................................... */ /* Case B: */ /* this must be a general column/keyword calc expression */ /* "name = expression" or "colname(TFORM) = expression" */ /*...................................................... */ /* parse the name and TFORM values, if present */ colformat[0] = '\0'; cptr3 = colname; fits_get_token(&cptr3, "(", oldname, NULL); if (cptr3[0] == '(' ) { cptr3++; /* skip the '(' */ fits_get_token(&cptr3, ")", colformat, NULL); } /* calculate values for the column or keyword */ /* cptr2 = the expression to be calculated */ /* oldname = name of the column or keyword */ /* colformat = column format, or keyword comment string */ if (fits_calculator(*fptr, cptr2, *fptr, oldname, colformat, status) > 0) { ffpmsg("Unable to calculate expression"); if( colindex ) free( colindex ); if( file_expr ) free( file_expr ); if (clause) free(clause); return(*status); } /* test if this is a column and not a keyword */ tstatus = 0; ffgcno(*fptr, CASEINSEN, oldname, &testnum, &tstatus); if (tstatus == 0) { /* keep this column in the output file */ colnum = testnum; savecol = 1; if (!colindex) colindex = (int *) calloc(999, sizeof(int)); colindex[colnum - 1] = 1; if (colnum > numcols)numcols++; } else { ffcmsg(); /* clear the error message stack */ } } } } if (clause) free(clause); /* free old clause before getting new one */ clause = NULL; } if (savecol && !deletecol) { /* need to delete all but the specified columns */ for (ii = numcols; ii > 0; ii--) { if (!colindex[ii-1]) /* delete this column */ { if (ffdcol(*fptr, ii, status) > 0) { ffpmsg("failed to delete column in input file:"); ffpmsg(clause); if( colindex ) free( colindex ); if( file_expr ) free( file_expr ); if (clause) free(clause); return(*status); } } } } if( colindex ) free( colindex ); if( file_expr ) free( file_expr ); if (clause) free(clause); return(*status); } /*--------------------------------------------------------------------------*/ int fits_copy_cell2image( fitsfile *fptr, /* I - point to input table */ fitsfile *newptr, /* O - existing output file; new image HDU will be appended to it */ char *colname, /* I - column name / number containing the image*/ long rownum, /* I - number of the row containing the image */ int *status) /* IO - error status */ /* Copy a table cell of a given row and column into an image extension. The output file must already have been created. A new image extension will be created in that file. This routine was written by Craig Markwardt, GSFC */ { unsigned char buffer[30000]; int hdutype, colnum, typecode, bitpix, naxis, maxelem, tstatus; LONGLONG naxes[9], nbytes, firstbyte, ntodo; LONGLONG repeat, startpos, elemnum, rowlen, tnull; long twidth, incre; double scale, zero; char tform[20]; char card[FLEN_CARD]; char templt[FLEN_CARD] = ""; /* Table-to-image keyword translation table */ /* INPUT OUTPUT */ /* 01234567 01234567 */ char *patterns[][2] = {{"TSCALn", "BSCALE" }, /* Standard FITS keywords */ {"TZEROn", "BZERO" }, {"TUNITn", "BUNIT" }, {"TNULLn", "BLANK" }, {"TDMINn", "DATAMIN" }, {"TDMAXn", "DATAMAX" }, {"iCTYPn", "CTYPEi" }, /* Coordinate labels */ {"iCTYna", "CTYPEia" }, {"iCUNIn", "CUNITi" }, /* Coordinate units */ {"iCUNna", "CUNITia" }, {"iCRVLn", "CRVALi" }, /* WCS keywords */ {"iCRVna", "CRVALia" }, {"iCDLTn", "CDELTi" }, {"iCDEna", "CDELTia" }, {"iCRPXn", "CRPIXi" }, {"iCRPna", "CRPIXia" }, {"ijPCna", "PCi_ja" }, {"ijCDna", "CDi_ja" }, {"iVn_ma", "PVi_ma" }, {"iSn_ma", "PSi_ma" }, {"iCRDna", "CRDERia" }, {"iCSYna", "CSYERia" }, {"iCROTn", "CROTAi" }, {"WCAXna", "WCSAXESa"}, {"WCSNna", "WCSNAMEa"}, {"LONPna", "LONPOLEa"}, {"LATPna", "LATPOLEa"}, {"EQUIna", "EQUINOXa"}, {"MJDOBn", "MJD-OBS" }, {"MJDAn", "MJD-AVG" }, {"RADEna", "RADESYSa"}, {"iCNAna", "CNAMEia" }, {"DAVGn", "DATE-AVG"}, /* Delete table keywords related to other columns */ {"T????#a", "-" }, {"TC??#a", "-" }, {"TWCS#a", "-" }, {"TDIM#", "-" }, {"iCTYPm", "-" }, {"iCUNIm", "-" }, {"iCRVLm", "-" }, {"iCDLTm", "-" }, {"iCRPXm", "-" }, {"iCTYma", "-" }, {"iCUNma", "-" }, {"iCRVma", "-" }, {"iCDEma", "-" }, {"iCRPma", "-" }, {"ijPCma", "-" }, {"ijCDma", "-" }, {"iVm_ma", "-" }, {"iSm_ma", "-" }, {"iCRDma", "-" }, {"iCSYma", "-" }, {"iCROTm", "-" }, {"WCAXma", "-" }, {"WCSNma", "-" }, {"LONPma", "-" }, {"LATPma", "-" }, {"EQUIma", "-" }, {"MJDOBm", "-" }, {"MJDAm", "-" }, {"RADEma", "-" }, {"iCNAma", "-" }, {"DAVGm", "-" }, {"EXTNAME", "-" }, /* Remove structural keywords*/ {"EXTVER", "-" }, {"EXTLEVEL","-" }, {"CHECKSUM","-" }, {"DATASUM", "-" }, {"*", "+" }}; /* copy all other keywords */ int npat; if (*status > 0) return(*status); /* get column number */ if (ffgcno(fptr, CASEINSEN, colname, &colnum, status) > 0) { ffpmsg("column containing image in table cell does not exist:"); ffpmsg(colname); return(*status); } /*---------------------------------------------------*/ /* Check input and get parameters about the column: */ /*---------------------------------------------------*/ if ( ffgcprll(fptr, colnum, rownum, 1L, 1L, 0, &scale, &zero, tform, &twidth, &typecode, &maxelem, &startpos, &elemnum, &incre, &repeat, &rowlen, &hdutype, &tnull, (char *) buffer, status) > 0 ) return(*status); /* get the actual column name, in case a column number was given */ ffkeyn("", colnum, templt, &tstatus); ffgcnn(fptr, CASEINSEN, templt, colname, &colnum, &tstatus); if (hdutype != BINARY_TBL) { ffpmsg("This extension is not a binary table."); ffpmsg(" Cannot open the image in a binary table cell."); return(*status = NOT_BTABLE); } if (typecode < 0) { /* variable length array */ typecode *= -1; /* variable length arrays are 1-dimensional by default */ naxis = 1; naxes[0] = repeat; } else { /* get the dimensions of the image */ ffgtdmll(fptr, colnum, 9, &naxis, naxes, status); } if (*status > 0) { ffpmsg("Error getting the dimensions of the image"); return(*status); } /* determine BITPIX value for the image */ if (typecode == TBYTE) { bitpix = BYTE_IMG; nbytes = repeat; } else if (typecode == TSHORT) { bitpix = SHORT_IMG; nbytes = repeat * 2; } else if (typecode == TLONG) { bitpix = LONG_IMG; nbytes = repeat * 4; } else if (typecode == TFLOAT) { bitpix = FLOAT_IMG; nbytes = repeat * 4; } else if (typecode == TDOUBLE) { bitpix = DOUBLE_IMG; nbytes = repeat * 8; } else if (typecode == TLONGLONG) { bitpix = LONGLONG_IMG; nbytes = repeat * 8; } else if (typecode == TLOGICAL) { bitpix = BYTE_IMG; nbytes = repeat; } else { ffpmsg("Error: the following image column has invalid datatype:"); ffpmsg(colname); ffpmsg(tform); ffpmsg("Cannot open an image in a single row of this column."); return(*status = BAD_TFORM); } /* create new image in output file */ if (ffcrimll(newptr, bitpix, naxis, naxes, status) > 0) { ffpmsg("failed to write required primary array keywords in the output file"); return(*status); } npat = sizeof(patterns)/sizeof(patterns[0][0])/2; /* skip over the first 8 keywords, starting just after TFIELDS */ fits_translate_keywords(fptr, newptr, 9, patterns, npat, colnum, 0, 0, status); /* add some HISTORY */ snprintf(card,FLEN_CARD,"HISTORY This image was copied from row %ld of column '%s',", rownum, colname); /* disable this; leave it up to the caller to write history if needed. ffprec(newptr, card, status); */ /* the use of ffread routine, below, requires that any 'dirty' */ /* buffers in memory be flushed back to the file first */ ffflsh(fptr, FALSE, status); /* finally, copy the data, one buffer size at a time */ ffmbyt(fptr, startpos, TRUE, status); firstbyte = 1; /* the upper limit on the number of bytes must match the declaration */ /* read up to the first 30000 bytes in the normal way with ffgbyt */ ntodo = minvalue(30000, nbytes); ffgbyt(fptr, ntodo, buffer, status); ffptbb(newptr, 1, firstbyte, ntodo, buffer, status); nbytes -= ntodo; firstbyte += ntodo; /* read any additional bytes with low-level ffread routine, for speed */ while (nbytes && (*status <= 0) ) { ntodo = minvalue(30000, nbytes); ffread((fptr)->Fptr, (long) ntodo, buffer, status); ffptbb(newptr, 1, firstbyte, ntodo, buffer, status); nbytes -= ntodo; firstbyte += ntodo; } /* Re-scan the header so that CFITSIO knows about all the new keywords */ ffrdef(newptr,status); return(*status); } /*--------------------------------------------------------------------------*/ int fits_copy_image2cell( fitsfile *fptr, /* I - pointer to input image extension */ fitsfile *newptr, /* I - pointer to output table */ char *colname, /* I - name of column containing the image */ long rownum, /* I - number of the row containing the image */ int copykeyflag, /* I - controls which keywords to copy */ int *status) /* IO - error status */ /* Copy an image extension into a table cell at a given row and column. The table must have already been created. If the "colname" column exists, it will be used, otherwise a new column will be created in the table. The "copykeyflag" parameter controls which keywords to copy from the input image to the output table header (with any appropriate translation). copykeyflag = 0 -- no keywords will be copied copykeyflag = 1 -- essentially all keywords will be copied copykeyflag = 2 -- copy only the WCS related keywords This routine was written by Craig Markwardt, GSFC */ { tcolumn *colptr; unsigned char buffer[30000]; int ii, hdutype, colnum, typecode, bitpix, naxis, ncols, hdunum; char tformchar, tform[20], card[FLEN_CARD]; LONGLONG imgstart, naxes[9], nbytes, repeat, ntodo,firstbyte; char filename[FLEN_FILENAME+20]; int npat; int naxis1; LONGLONG naxes1[9] = {0,0,0,0,0,0,0,0,0}, repeat1, width1; int typecode1; unsigned char dummy = 0; LONGLONG headstart, datastart, dataend; /* Image-to-table keyword translation table */ /* INPUT OUTPUT */ /* 01234567 01234567 */ char *patterns[][2] = {{"BSCALE", "TSCALn" }, /* Standard FITS keywords */ {"BZERO", "TZEROn" }, {"BUNIT", "TUNITn" }, {"BLANK", "TNULLn" }, {"DATAMIN", "TDMINn" }, {"DATAMAX", "TDMAXn" }, {"CTYPEi", "iCTYPn" }, /* Coordinate labels */ {"CTYPEia", "iCTYna" }, {"CUNITi", "iCUNIn" }, /* Coordinate units */ {"CUNITia", "iCUNna" }, {"CRVALi", "iCRVLn" }, /* WCS keywords */ {"CRVALia", "iCRVna" }, {"CDELTi", "iCDLTn" }, {"CDELTia", "iCDEna" }, {"CRPIXj", "jCRPXn" }, {"CRPIXja", "jCRPna" }, {"PCi_ja", "ijPCna" }, {"CDi_ja", "ijCDna" }, {"PVi_ma", "iVn_ma" }, {"PSi_ma", "iSn_ma" }, {"WCSAXESa","WCAXna" }, {"WCSNAMEa","WCSNna" }, {"CRDERia", "iCRDna" }, {"CSYERia", "iCSYna" }, {"CROTAi", "iCROTn" }, {"LONPOLEa","LONPna"}, {"LATPOLEa","LATPna"}, {"EQUINOXa","EQUIna"}, {"MJD-OBS", "MJDOBn" }, {"MJD-AVG", "MJDAn" }, {"RADESYSa","RADEna"}, {"CNAMEia", "iCNAna" }, {"DATE-AVG","DAVGn"}, {"NAXISi", "-" }, /* Remove structural keywords*/ {"PCOUNT", "-" }, {"GCOUNT", "-" }, {"EXTEND", "-" }, {"EXTNAME", "-" }, {"EXTVER", "-" }, {"EXTLEVEL","-" }, {"CHECKSUM","-" }, {"DATASUM", "-" }, {"*", "+" }}; /* copy all other keywords */ if (*status > 0) return(*status); if (fptr == 0 || newptr == 0) return (*status = NULL_INPUT_PTR); if (ffghdt(fptr, &hdutype, status) > 0) { ffpmsg("could not get input HDU type"); return (*status); } if (hdutype != IMAGE_HDU) { ffpmsg("The input extension is not an image."); ffpmsg(" Cannot open the image."); return(*status = NOT_IMAGE); } if (ffghdt(newptr, &hdutype, status) > 0) { ffpmsg("could not get output HDU type"); return (*status); } if (hdutype != BINARY_TBL) { ffpmsg("The output extension is not a table."); return(*status = NOT_BTABLE); } if (ffgiprll(fptr, 9, &bitpix, &naxis, naxes, status) > 0) { ffpmsg("Could not read image parameters."); return (*status); } /* Determine total number of pixels in the image */ repeat = 1; for (ii = 0; ii < naxis; ii++) repeat *= naxes[ii]; /* Determine the TFORM value for the table cell */ if (bitpix == BYTE_IMG) { typecode = TBYTE; tformchar = 'B'; nbytes = repeat; } else if (bitpix == SHORT_IMG) { typecode = TSHORT; tformchar = 'I'; nbytes = repeat*2; } else if (bitpix == LONG_IMG) { typecode = TLONG; tformchar = 'J'; nbytes = repeat*4; } else if (bitpix == FLOAT_IMG) { typecode = TFLOAT; tformchar = 'E'; nbytes = repeat*4; } else if (bitpix == DOUBLE_IMG) { typecode = TDOUBLE; tformchar = 'D'; nbytes = repeat*8; } else if (bitpix == LONGLONG_IMG) { typecode = TLONGLONG; tformchar = 'K'; nbytes = repeat*8; } else { ffpmsg("Error: the image has an invalid datatype."); return (*status = BAD_BITPIX); } /* get column number */ ffpmrk(); ffgcno(newptr, CASEINSEN, colname, &colnum, status); ffcmrk(); /* Column does not exist; create it */ if (*status) { *status = 0; snprintf(tform, 20, "%.0f%c", (double) repeat, tformchar); ffgncl(newptr, &ncols, status); colnum = ncols+1; fficol(newptr, colnum, colname, tform, status); ffptdmll(newptr, colnum, naxis, naxes, status); if (*status) { ffpmsg("Could not insert new column into output table."); return *status; } } else { ffgtdmll(newptr, colnum, 9, &naxis1, naxes1, status); if (*status > 0 || naxis != naxis1) { ffpmsg("Input image dimensions and output table cell dimensions do not match."); return (*status = BAD_DIMEN); } for (ii=0; ii 0) || (typecode1 != typecode) || (repeat1 != repeat)) { ffpmsg("Input image data type does not match output table cell type."); return (*status = BAD_TFORM); } } /* copy keywords from input image to output table, if required */ if (copykeyflag) { npat = sizeof(patterns)/sizeof(patterns[0][0])/2; if (copykeyflag == 2) { /* copy only the WCS-related keywords */ patterns[npat-1][1] = "-"; } /* The 3rd parameter value = 5 means skip the first 4 keywords in the image */ fits_translate_keywords(fptr, newptr, 5, patterns, npat, colnum, 0, 0, status); } /* Here is all the code to compute offsets: * * byte offset from start of row to column (dest table) * * byte offset from start of file to image data (source image) */ /* Force the writing of the row of the table by writing the last byte of the array, which grows the table, and/or shifts following extensions */ ffpcl(newptr, TBYTE, colnum, rownum, repeat, 1, &dummy, status); /* byte offset within the row to the start of the image column */ colptr = (newptr->Fptr)->tableptr; /* point to first column */ colptr += (colnum - 1); /* offset to correct column structure */ firstbyte = colptr->tbcol + 1; /* get starting address of input image to be read */ ffghadll(fptr, &headstart, &datastart, &dataend, status); imgstart = datastart; snprintf(card, FLEN_CARD, "HISTORY Table column '%s' row %ld copied from image", colname, rownum); /* Don't automatically write History keywords; leave this up to the caller. ffprec(newptr, card, status); */ /* write HISTORY keyword with the file name (this is now disabled)*/ filename[0] = '\0'; hdunum = 0; strcpy(filename, "HISTORY "); ffflnm(fptr, filename+strlen(filename), status); ffghdn(fptr, &hdunum); snprintf(filename+strlen(filename),FLEN_FILENAME+20-strlen(filename),"[%d]", hdunum-1); /* ffprec(newptr, filename, status); */ /* the use of ffread routine, below, requires that any 'dirty' */ /* buffers in memory be flushed back to the file first */ ffflsh(fptr, FALSE, status); /* move to the first byte of the input image */ ffmbyt(fptr, imgstart, TRUE, status); ntodo = minvalue(30000L, nbytes); ffgbyt(fptr, ntodo, buffer, status); /* read input image */ ffptbb(newptr, rownum, firstbyte, ntodo, buffer, status); /* write to table */ nbytes -= ntodo; firstbyte += ntodo; /* read any additional bytes with low-level ffread routine, for speed */ while (nbytes && (*status <= 0) ) { ntodo = minvalue(30000L, nbytes); ffread(fptr->Fptr, (long) ntodo, buffer, status); ffptbb(newptr, rownum, firstbyte, ntodo, buffer, status); nbytes -= ntodo; firstbyte += ntodo; } /* Re-scan the header so that CFITSIO knows about all the new keywords */ ffrdef(newptr,status); return(*status); } /*--------------------------------------------------------------------------*/ int fits_select_image_section( fitsfile **fptr, /* IO - pointer to input image; on output it */ /* points to the new subimage */ char *outfile, /* I - name for output file */ char *expr, /* I - Image section expression */ int *status) { /* copies an image section from the input file to a new output file. Any HDUs preceding or following the image are also copied to the output file. */ fitsfile *newptr; int ii, hdunum; /* create new empty file to hold the image section */ if (ffinit(&newptr, outfile, status) > 0) { ffpmsg( "failed to create output file for image section:"); ffpmsg(outfile); return(*status); } fits_get_hdu_num(*fptr, &hdunum); /* current HDU number in input file */ /* copy all preceding extensions to the output file, if 'only_one' flag not set */ if (!(((*fptr)->Fptr)->only_one)) { for (ii = 1; ii < hdunum; ii++) { fits_movabs_hdu(*fptr, ii, NULL, status); if (fits_copy_hdu(*fptr, newptr, 0, status) > 0) { ffclos(newptr, status); return(*status); } } /* move back to the original HDU position */ fits_movabs_hdu(*fptr, hdunum, NULL, status); } if (fits_copy_image_section(*fptr, newptr, expr, status) > 0) { ffclos(newptr, status); return(*status); } /* copy any remaining HDUs to the output file, if 'only_one' flag not set */ if (!(((*fptr)->Fptr)->only_one)) { for (ii = hdunum + 1; 1; ii++) { if (fits_movabs_hdu(*fptr, ii, NULL, status) > 0) break; fits_copy_hdu(*fptr, newptr, 0, status); } if (*status == END_OF_FILE) *status = 0; /* got the expected EOF error; reset = 0 */ else if (*status > 0) { ffclos(newptr, status); return(*status); } } else { ii = hdunum + 1; /* this value of ii is required below */ } /* close the original file and return ptr to the new image */ ffclos(*fptr, status); *fptr = newptr; /* reset the pointer to the new table */ /* move back to the image subsection */ if (ii - 1 != hdunum) fits_movabs_hdu(*fptr, hdunum, NULL, status); else { /* may have to reset BSCALE and BZERO pixel scaling, */ /* since the keywords were previously turned off */ if (ffrdef(*fptr, status) > 0) { ffclos(*fptr, status); return(*status); } } return(*status); } /*--------------------------------------------------------------------------*/ int fits_copy_image_section( fitsfile *fptr, /* I - pointer to input image */ fitsfile *newptr, /* I - pointer to output image */ char *expr, /* I - Image section expression */ int *status) { /* copies an image section from the input file to a new output HDU */ int bitpix, naxis, numkeys, nkey; long naxes[] = {1,1,1,1,1,1,1,1,1}, smin, smax, sinc; long fpixels[] = {1,1,1,1,1,1,1,1,1}; long lpixels[] = {1,1,1,1,1,1,1,1,1}; long incs[] = {1,1,1,1,1,1,1,1,1}; char *cptr, keyname[FLEN_KEYWORD], card[FLEN_CARD]; int ii, tstatus, anynull; long minrow, maxrow, minslice, maxslice, mincube, maxcube; long firstpix; long ncubeiter, nsliceiter, nrowiter, kiter, jiter, iiter; int klen, kk, jj; long outnaxes[9], outsize, buffsize; double *buffer, crpix, cdelt; if (*status > 0) return(*status); /* get the size of the input image */ fits_get_img_type(fptr, &bitpix, status); fits_get_img_dim(fptr, &naxis, status); if (fits_get_img_size(fptr, naxis, naxes, status) > 0) return(*status); if (naxis < 1 || naxis > 4) { ffpmsg( "Input image either had NAXIS = 0 (NULL image) or has > 4 dimensions"); return(*status = BAD_NAXIS); } /* create output image with same size and type as the input image */ /* Will update the size later */ fits_create_img(newptr, bitpix, naxis, naxes, status); /* copy all other non-structural keywords from the input to output file */ fits_get_hdrspace(fptr, &numkeys, NULL, status); for (nkey = 4; nkey <= numkeys; nkey++) /* skip the first few keywords */ { fits_read_record(fptr, nkey, card, status); if (fits_get_keyclass(card) > TYP_CMPRS_KEY) { /* write the record to the output file */ fits_write_record(newptr, card, status); } } if (*status > 0) { ffpmsg("error copying header from input image to output image"); return(*status); } /* parse the section specifier to get min, max, and inc for each axis */ /* and the size of each output image axis */ cptr = expr; for (ii=0; ii < naxis; ii++) { if (fits_get_section_range(&cptr, &smin, &smax, &sinc, status) > 0) { ffpmsg("error parsing the following image section specifier:"); ffpmsg(expr); return(*status); } if (smax == 0) smax = naxes[ii]; /* use whole axis by default */ else if (smin == 0) smin = naxes[ii]; /* use inverted whole axis */ if (smin > naxes[ii] || smax > naxes[ii]) { ffpmsg("image section exceeds dimensions of input image:"); ffpmsg(expr); return(*status = BAD_NAXIS); } fpixels[ii] = smin; lpixels[ii] = smax; incs[ii] = sinc; if (smin <= smax) outnaxes[ii] = (smax - smin + sinc) / sinc; else outnaxes[ii] = (smin - smax + sinc) / sinc; /* modify the NAXISn keyword */ fits_make_keyn("NAXIS", ii + 1, keyname, status); fits_modify_key_lng(newptr, keyname, outnaxes[ii], NULL, status); /* modify the WCS keywords if necessary */ if (fpixels[ii] != 1 || incs[ii] != 1) { for (kk=-1;kk<26; kk++) /* modify any alternate WCS keywords */ { /* read the CRPIXn keyword if it exists in the input file */ fits_make_keyn("CRPIX", ii + 1, keyname, status); if (kk != -1) { klen = strlen(keyname); keyname[klen]='A' + kk; keyname[klen + 1] = '\0'; } tstatus = 0; if (fits_read_key(fptr, TDOUBLE, keyname, &crpix, NULL, &tstatus) == 0) { /* calculate the new CRPIXn value */ if (fpixels[ii] <= lpixels[ii]) { crpix = (crpix - (fpixels[ii])) / incs[ii] + 1.0; /* crpix = (crpix - (fpixels[ii] - 1.0) - .5) / incs[ii] + 0.5; */ } else { crpix = (fpixels[ii] - crpix) / incs[ii] + 1.0; /* crpix = (fpixels[ii] - (crpix - 1.0) - .5) / incs[ii] + 0.5; */ } /* modify the value in the output file */ fits_modify_key_dbl(newptr, keyname, crpix, 15, NULL, status); if (incs[ii] != 1 || fpixels[ii] > lpixels[ii]) { /* read the CDELTn keyword if it exists in the input file */ fits_make_keyn("CDELT", ii + 1, keyname, status); if (kk != -1) { klen = strlen(keyname); keyname[klen]='A' + kk; keyname[klen + 1] = '\0'; } tstatus = 0; if (fits_read_key(fptr, TDOUBLE, keyname, &cdelt, NULL, &tstatus) == 0) { /* calculate the new CDELTn value */ if (fpixels[ii] <= lpixels[ii]) cdelt = cdelt * incs[ii]; else cdelt = cdelt * (-incs[ii]); /* modify the value in the output file */ fits_modify_key_dbl(newptr, keyname, cdelt, 15, NULL, status); } /* modify the CDi_j keywords if they exist in the input file */ fits_make_keyn("CD1_", ii + 1, keyname, status); if (kk != -1) { klen = strlen(keyname); keyname[klen]='A' + kk; keyname[klen + 1] = '\0'; } for (jj=0; jj < 9; jj++) /* look for up to 9 dimensions */ { keyname[2] = '1' + jj; tstatus = 0; if (fits_read_key(fptr, TDOUBLE, keyname, &cdelt, NULL, &tstatus) == 0) { /* calculate the new CDi_j value */ if (fpixels[ii] <= lpixels[ii]) cdelt = cdelt * incs[ii]; else cdelt = cdelt * (-incs[ii]); /* modify the value in the output file */ fits_modify_key_dbl(newptr, keyname, cdelt, 15, NULL, status); } } } /* end of if (incs[ii]... loop */ } /* end of fits_read_key loop */ } /* end of for (kk loop */ } } /* end of main NAXIS loop */ if (ffrdef(newptr, status) > 0) /* force the header to be scanned */ { return(*status); } /* turn off any scaling of the pixel values */ fits_set_bscale(fptr, 1.0, 0.0, status); fits_set_bscale(newptr, 1.0, 0.0, status); /* to reduce memory foot print, just read/write image 1 row at a time */ outsize = outnaxes[0]; buffsize = (abs(bitpix) / 8) * outsize; buffer = (double *) malloc(buffsize); /* allocate memory for the image row */ if (!buffer) { ffpmsg("fits_copy_image_section: no memory for image section"); return(*status = MEMORY_ALLOCATION); } /* read the image section then write it to the output file */ minrow = fpixels[1]; maxrow = lpixels[1]; if (minrow > maxrow) { nrowiter = (minrow - maxrow + incs[1]) / incs[1]; } else { nrowiter = (maxrow - minrow + incs[1]) / incs[1]; } minslice = fpixels[2]; maxslice = lpixels[2]; if (minslice > maxslice) { nsliceiter = (minslice - maxslice + incs[2]) / incs[2]; } else { nsliceiter = (maxslice - minslice + incs[2]) / incs[2]; } mincube = fpixels[3]; maxcube = lpixels[3]; if (mincube > maxcube) { ncubeiter = (mincube - maxcube + incs[3]) / incs[3]; } else { ncubeiter = (maxcube - mincube + incs[3]) / incs[3]; } firstpix = 1; for (kiter = 0; kiter < ncubeiter; kiter++) { if (mincube > maxcube) { fpixels[3] = mincube - (kiter * incs[3]); } else { fpixels[3] = mincube + (kiter * incs[3]); } lpixels[3] = fpixels[3]; for (jiter = 0; jiter < nsliceiter; jiter++) { if (minslice > maxslice) { fpixels[2] = minslice - (jiter * incs[2]); } else { fpixels[2] = minslice + (jiter * incs[2]); } lpixels[2] = fpixels[2]; for (iiter = 0; iiter < nrowiter; iiter++) { if (minrow > maxrow) { fpixels[1] = minrow - (iiter * incs[1]); } else { fpixels[1] = minrow + (iiter * incs[1]); } lpixels[1] = fpixels[1]; if (bitpix == 8) { ffgsvb(fptr, 1, naxis, naxes, fpixels, lpixels, incs, 0, (unsigned char *) buffer, &anynull, status); ffpprb(newptr, 1, firstpix, outsize, (unsigned char *) buffer, status); } else if (bitpix == 16) { ffgsvi(fptr, 1, naxis, naxes, fpixels, lpixels, incs, 0, (short *) buffer, &anynull, status); ffppri(newptr, 1, firstpix, outsize, (short *) buffer, status); } else if (bitpix == 32) { ffgsvk(fptr, 1, naxis, naxes, fpixels, lpixels, incs, 0, (int *) buffer, &anynull, status); ffpprk(newptr, 1, firstpix, outsize, (int *) buffer, status); } else if (bitpix == -32) { ffgsve(fptr, 1, naxis, naxes, fpixels, lpixels, incs, FLOATNULLVALUE, (float *) buffer, &anynull, status); ffppne(newptr, 1, firstpix, outsize, (float *) buffer, FLOATNULLVALUE, status); } else if (bitpix == -64) { ffgsvd(fptr, 1, naxis, naxes, fpixels, lpixels, incs, DOUBLENULLVALUE, buffer, &anynull, status); ffppnd(newptr, 1, firstpix, outsize, buffer, DOUBLENULLVALUE, status); } else if (bitpix == 64) { ffgsvjj(fptr, 1, naxis, naxes, fpixels, lpixels, incs, 0, (LONGLONG *) buffer, &anynull, status); ffpprjj(newptr, 1, firstpix, outsize, (LONGLONG *) buffer, status); } firstpix += outsize; } } } free(buffer); /* finished with the memory */ if (*status > 0) { ffpmsg("fits_copy_image_section: error copying image section"); return(*status); } return(*status); } /*--------------------------------------------------------------------------*/ int fits_get_section_range(char **ptr, long *secmin, long *secmax, long *incre, int *status) /* Parse the input image section specification string, returning the min, max and increment values. Typical string = "1:512:2" or "1:512" */ { int slen, isanumber; char token[FLEN_VALUE]; if (*status > 0) return(*status); slen = fits_get_token(ptr, " ,:", token, &isanumber); /* get 1st token */ /* support [:2,:2] type syntax, where the leading * is implied */ if (slen==0) strcpy(token,"*"); if (*token == '*') /* wild card means to use the whole range */ { *secmin = 1; *secmax = 0; } else if (*token == '-' && *(token+1) == '*' ) /* invert the whole range */ { *secmin = 0; *secmax = 1; } else { if (slen == 0 || !isanumber || **ptr != ':') return(*status = URL_PARSE_ERROR); /* the token contains the min value */ *secmin = atol(token); (*ptr)++; /* skip the colon between the min and max values */ slen = fits_get_token(ptr, " ,:", token, &isanumber); /* get token */ if (slen == 0 || !isanumber) return(*status = URL_PARSE_ERROR); /* the token contains the max value */ *secmax = atol(token); } if (**ptr == ':') { (*ptr)++; /* skip the colon between the max and incre values */ slen = fits_get_token(ptr, " ,", token, &isanumber); /* get token */ if (slen == 0 || !isanumber) return(*status = URL_PARSE_ERROR); *incre = atol(token); } else *incre = 1; /* default increment if none is supplied */ if (**ptr == ',') (*ptr)++; while (**ptr == ' ') /* skip any trailing blanks */ (*ptr)++; if (*secmin < 0 || *secmax < 0 || *incre < 1) *status = URL_PARSE_ERROR; return(*status); } /*--------------------------------------------------------------------------*/ int ffselect_table( fitsfile **fptr, /* IO - pointer to input table; on output it */ /* points to the new selected rows table */ char *outfile, /* I - name for output file */ char *expr, /* I - Boolean expression */ int *status) { fitsfile *newptr; int ii, hdunum; if (*outfile) { /* create new empty file in to hold the selected rows */ if (ffinit(&newptr, outfile, status) > 0) { ffpmsg( "failed to create file for selected rows from input table"); ffpmsg(outfile); return(*status); } fits_get_hdu_num(*fptr, &hdunum); /* current HDU number in input file */ /* copy all preceding extensions to the output file, if the 'only_one' flag is not set */ if (!((*fptr)->Fptr)->only_one) { for (ii = 1; ii < hdunum; ii++) { fits_movabs_hdu(*fptr, ii, NULL, status); if (fits_copy_hdu(*fptr, newptr, 0, status) > 0) { ffclos(newptr, status); return(*status); } } } else { /* just copy the primary array */ fits_movabs_hdu(*fptr, 1, NULL, status); if (fits_copy_hdu(*fptr, newptr, 0, status) > 0) { ffclos(newptr, status); return(*status); } } fits_movabs_hdu(*fptr, hdunum, NULL, status); /* copy all the header keywords from the input to output file */ if (fits_copy_header(*fptr, newptr, status) > 0) { ffclos(newptr, status); return(*status); } /* set number of rows = 0 */ fits_modify_key_lng(newptr, "NAXIS2", 0, NULL,status); (newptr->Fptr)->numrows = 0; (newptr->Fptr)->origrows = 0; if (ffrdef(newptr, status) > 0) /* force the header to be scanned */ { ffclos(newptr, status); return(*status); } } else newptr = *fptr; /* will delete rows in place in the table */ /* copy rows which satisfy the selection expression to the output table */ /* or delete the nonqualifying rows if *fptr = newptr. */ if (fits_select_rows(*fptr, newptr, expr, status) > 0) { if (*outfile) ffclos(newptr, status); return(*status); } if (*outfile) { /* copy any remaining HDUs to the output copy */ if (!((*fptr)->Fptr)->only_one) { for (ii = hdunum + 1; 1; ii++) { if (fits_movabs_hdu(*fptr, ii, NULL, status) > 0) break; fits_copy_hdu(*fptr, newptr, 0, status); } if (*status == END_OF_FILE) *status = 0; /* got the expected EOF error; reset = 0 */ else if (*status > 0) { ffclos(newptr, status); return(*status); } } else { hdunum = 2; } /* close the original file and return ptr to the new image */ ffclos(*fptr, status); *fptr = newptr; /* reset the pointer to the new table */ /* move back to the selected table HDU */ fits_movabs_hdu(*fptr, hdunum, NULL, status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffparsecompspec(fitsfile *fptr, /* I - FITS file pointer */ char *compspec, /* I - image compression specification */ int *status) /* IO - error status */ /* Parse the image compression specification that was give in square brackets following the output FITS file name, as in these examples: myfile.fits[compress] - default Rice compression, row by row myfile.fits[compress TYPE] - the first letter of TYPE defines the compression algorithm: R = Rice G = GZIP H = HCOMPRESS HS = HCOMPRESS (with smoothing) B - BZIP2 P = PLIO myfile.fits[compress TYPE 100,100] - the numbers give the dimensions of the compression tiles. Default is NAXIS1, 1, 1, ... other optional parameters may be specified following a semi-colon myfile.fits[compress; q 8.0] q specifies the floating point mufile.fits[compress TYPE; q -.0002] quantization level; myfile.fits[compress TYPE 100,100; q 10, s 25] s specifies the HCOMPRESS integer scaling parameter The compression parameters are saved in the fptr->Fptr structure for use when writing FITS images. */ { char *ptr1; /* initialize with default values */ int ii, compresstype = RICE_1, smooth = 0; int quantize_method = SUBTRACTIVE_DITHER_1; long tilesize[MAX_COMPRESS_DIM] = {0,0,0,0,0,0}; float qlevel = -99., scale = 0.; ptr1 = compspec; while (*ptr1 == ' ') /* ignore leading blanks */ ptr1++; if (strncmp(ptr1, "compress", 8) && strncmp(ptr1, "COMPRESS", 8) ) { /* apparently this string does not specify compression parameters */ return(*status = URL_PARSE_ERROR); } ptr1 += 8; while (*ptr1 == ' ') /* ignore leading blanks */ ptr1++; /* ========================= */ /* look for compression type */ /* ========================= */ if (*ptr1 == 'r' || *ptr1 == 'R') { compresstype = RICE_1; while (*ptr1 != ' ' && *ptr1 != ';' && *ptr1 != '\0') ptr1++; } else if (*ptr1 == 'g' || *ptr1 == 'G') { compresstype = GZIP_1; while (*ptr1 != ' ' && *ptr1 != ';' && *ptr1 != '\0') ptr1++; } /* else if (*ptr1 == 'b' || *ptr1 == 'B') { compresstype = BZIP2_1; while (*ptr1 != ' ' && *ptr1 != ';' && *ptr1 != '\0') ptr1++; } */ else if (*ptr1 == 'p' || *ptr1 == 'P') { compresstype = PLIO_1; while (*ptr1 != ' ' && *ptr1 != ';' && *ptr1 != '\0') ptr1++; } else if (*ptr1 == 'h' || *ptr1 == 'H') { compresstype = HCOMPRESS_1; ptr1++; if (*ptr1 == 's' || *ptr1 == 'S') smooth = 1; /* apply smoothing when uncompressing HCOMPRESSed image */ while (*ptr1 != ' ' && *ptr1 != ';' && *ptr1 != '\0') ptr1++; } /* ======================== */ /* look for tile dimensions */ /* ======================== */ while (*ptr1 == ' ') /* ignore leading blanks */ ptr1++; ii = 0; while (isdigit( (int) *ptr1) && ii < 9) { tilesize[ii] = atol(ptr1); /* read the integer value */ ii++; while (isdigit((int) *ptr1)) /* skip over the integer */ ptr1++; if (*ptr1 == ',') ptr1++; /* skip over the comma */ while (*ptr1 == ' ') /* ignore leading blanks */ ptr1++; } /* ========================================================= */ /* look for semi-colon, followed by other optional parameters */ /* ========================================================= */ if (*ptr1 == ';') { ptr1++; while (*ptr1 == ' ') /* ignore leading blanks */ ptr1++; while (*ptr1 != 0) { /* haven't reached end of string yet */ if (*ptr1 == 's' || *ptr1 == 'S') { /* this should be the HCOMPRESS "scale" parameter; default = 1 */ ptr1++; while (*ptr1 == ' ') /* ignore leading blanks */ ptr1++; scale = (float) strtod(ptr1, &ptr1); while (*ptr1 == ' ' || *ptr1 == ',') /* skip over blanks or comma */ ptr1++; } else if (*ptr1 == 'q' || *ptr1 == 'Q') { /* this should be the floating point quantization parameter */ ptr1++; if (*ptr1 == 'z' || *ptr1 == 'Z') { /* use the subtractive_dither_2 option */ quantize_method = SUBTRACTIVE_DITHER_2; ptr1++; } else if (*ptr1 == '0') { /* do not dither */ quantize_method = NO_DITHER; ptr1++; } while (*ptr1 == ' ') /* ignore leading blanks */ ptr1++; qlevel = (float) strtod(ptr1, &ptr1); while (*ptr1 == ' ' || *ptr1 == ',') /* skip over blanks or comma */ ptr1++; } else { return(*status = URL_PARSE_ERROR); } } } /* ================================= */ /* finished parsing; save the values */ /* ================================= */ fits_set_compression_type(fptr, compresstype, status); fits_set_tile_dim(fptr, MAX_COMPRESS_DIM, tilesize, status); if (compresstype == HCOMPRESS_1) { fits_set_hcomp_scale (fptr, scale, status); fits_set_hcomp_smooth(fptr, smooth, status); } if (qlevel != -99.) { fits_set_quantize_level(fptr, qlevel, status); fits_set_quantize_method(fptr, quantize_method, status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffdkinit(fitsfile **fptr, /* O - FITS file pointer */ const char *name, /* I - name of file to create */ int *status) /* IO - error status */ /* Create and initialize a new FITS file on disk. This routine differs from ffinit in that the input 'name' is literally taken as the name of the disk file to be created, and it does not support CFITSIO's extended filename syntax. */ { *fptr = 0; /* initialize null file pointer, */ /* regardless of the value of *status */ if (*status > 0) return(*status); *status = CREATE_DISK_FILE; ffinit(fptr, name,status); return(*status); } /*--------------------------------------------------------------------------*/ int ffinit(fitsfile **fptr, /* O - FITS file pointer */ const char *name, /* I - name of file to create */ int *status) /* IO - error status */ /* Create and initialize a new FITS file. */ { int ii, driver, slen, clobber = 0; char *url; char urltype[MAX_PREFIX_LEN], outfile[FLEN_FILENAME]; char tmplfile[FLEN_FILENAME], compspec[80]; int handle, create_disk_file = 0; *fptr = 0; /* initialize null file pointer, */ /* regardless of the value of *status */ if (*status > 0) return(*status); if (*status == CREATE_DISK_FILE) { create_disk_file = 1; *status = 0; } if (need_to_initialize) { /* this is called only once */ *status = fits_init_cfitsio(); } if (*status > 0) return(*status); url = (char *) name; while (*url == ' ') /* ignore leading spaces in the filename */ url++; if (*url == '\0') { ffpmsg("Name of file to create is blank. (ffinit)"); return(*status = FILE_NOT_CREATED); } if (create_disk_file) { if (strlen(url) > FLEN_FILENAME - 1) { ffpmsg("Filename is too long. (ffinit)"); return(*status = FILE_NOT_CREATED); } strcpy(outfile, url); strcpy(urltype, "file://"); tmplfile[0] = '\0'; compspec[0] = '\0'; } else { /* check for clobber symbol, i.e, overwrite existing file */ if (*url == '!') { clobber = TRUE; url++; } else clobber = FALSE; /* parse the output file specification */ /* this routine checks that the strings will not overflow */ ffourl(url, urltype, outfile, tmplfile, compspec, status); if (*status > 0) { ffpmsg("could not parse the output filename: (ffinit)"); ffpmsg(url); return(*status); } } /* find which driver corresponds to the urltype */ *status = urltype2driver(urltype, &driver); if (*status) { ffpmsg("could not find driver for this file: (ffinit)"); ffpmsg(url); return(*status); } /* delete pre-existing file, if asked to do so */ if (clobber) { if (driverTable[driver].remove) (*driverTable[driver].remove)(outfile); } /* call appropriate driver to create the file */ if (driverTable[driver].create) { FFLOCK; /* lock this while searching for vacant handle */ *status = (*driverTable[driver].create)(outfile, &handle); FFUNLOCK; if (*status) { ffpmsg("failed to create new file (already exists?):"); ffpmsg(url); return(*status); } } else { ffpmsg("cannot create a new file of this type: (ffinit)"); ffpmsg(url); return(*status = FILE_NOT_CREATED); } /* allocate fitsfile structure and initialize = 0 */ *fptr = (fitsfile *) calloc(1, sizeof(fitsfile)); if (!(*fptr)) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate structure for following file: (ffopen)"); ffpmsg(url); return(*status = MEMORY_ALLOCATION); } /* allocate FITSfile structure and initialize = 0 */ (*fptr)->Fptr = (FITSfile *) calloc(1, sizeof(FITSfile)); if (!((*fptr)->Fptr)) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate structure for following file: (ffopen)"); ffpmsg(url); free(*fptr); *fptr = 0; return(*status = MEMORY_ALLOCATION); } slen = strlen(url) + 1; slen = maxvalue(slen, 32); /* reserve at least 32 chars */ ((*fptr)->Fptr)->filename = (char *) malloc(slen); /* mem for file name */ if ( !(((*fptr)->Fptr)->filename) ) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate memory for filename: (ffinit)"); ffpmsg(url); free((*fptr)->Fptr); free(*fptr); *fptr = 0; /* return null file pointer */ return(*status = FILE_NOT_CREATED); } /* mem for headstart array */ ((*fptr)->Fptr)->headstart = (LONGLONG *) calloc(1001, sizeof(LONGLONG)); if ( !(((*fptr)->Fptr)->headstart) ) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate memory for headstart array: (ffinit)"); ffpmsg(url); free( ((*fptr)->Fptr)->filename); free((*fptr)->Fptr); free(*fptr); *fptr = 0; /* return null file pointer */ return(*status = MEMORY_ALLOCATION); } /* mem for file I/O buffers */ ((*fptr)->Fptr)->iobuffer = (char *) calloc(NIOBUF, IOBUFLEN); if ( !(((*fptr)->Fptr)->iobuffer) ) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate memory for iobuffer array: (ffinit)"); ffpmsg(url); free( ((*fptr)->Fptr)->headstart); /* free memory for headstart array */ free( ((*fptr)->Fptr)->filename); free((*fptr)->Fptr); free(*fptr); *fptr = 0; /* return null file pointer */ return(*status = MEMORY_ALLOCATION); } /* initialize the ageindex array (relative age of the I/O buffers) */ /* and initialize the bufrecnum array as being empty */ for (ii = 0; ii < NIOBUF; ii++) { ((*fptr)->Fptr)->ageindex[ii] = ii; ((*fptr)->Fptr)->bufrecnum[ii] = -1; } /* store the parameters describing the file */ ((*fptr)->Fptr)->MAXHDU = 1000; /* initial size of headstart */ ((*fptr)->Fptr)->filehandle = handle; /* store the file pointer */ ((*fptr)->Fptr)->driver = driver; /* driver number */ strcpy(((*fptr)->Fptr)->filename, url); /* full input filename */ ((*fptr)->Fptr)->filesize = 0; /* physical file size */ ((*fptr)->Fptr)->logfilesize = 0; /* logical file size */ ((*fptr)->Fptr)->writemode = 1; /* read-write mode */ ((*fptr)->Fptr)->datastart = DATA_UNDEFINED; /* unknown start of data */ ((*fptr)->Fptr)->curbuf = -1; /* undefined current IO buffer */ ((*fptr)->Fptr)->open_count = 1; /* structure is currently used once */ ((*fptr)->Fptr)->validcode = VALIDSTRUC; /* flag denoting valid structure */ ffldrc(*fptr, 0, IGNORE_EOF, status); /* initialize first record */ fits_store_Fptr( (*fptr)->Fptr, status); /* store Fptr address */ /* if template file was given, use it to define structure of new file */ if (tmplfile[0]) ffoptplt(*fptr, tmplfile, status); /* parse and save image compression specification, if given */ if (compspec[0]) ffparsecompspec(*fptr, compspec, status); return(*status); /* successful return */ } /*--------------------------------------------------------------------------*/ /* ffimem == fits_create_memfile */ int ffimem(fitsfile **fptr, /* O - FITS file pointer */ void **buffptr, /* I - address of memory pointer */ size_t *buffsize, /* I - size of buffer, in bytes */ size_t deltasize, /* I - increment for future realloc's */ void *(*mem_realloc)(void *p, size_t newsize), /* function */ int *status) /* IO - error status */ /* Create and initialize a new FITS file in memory */ { int ii, driver, slen; char urltype[MAX_PREFIX_LEN]; int handle; if (*status > 0) return(*status); *fptr = 0; /* initialize null file pointer */ if (need_to_initialize) { /* this is called only once */ *status = fits_init_cfitsio(); } if (*status > 0) return(*status); strcpy(urltype, "memkeep://"); /* URL type for pre-existing memory file */ *status = urltype2driver(urltype, &driver); if (*status > 0) { ffpmsg("could not find driver for pre-existing memory file: (ffimem)"); return(*status); } /* call driver routine to "open" the memory file */ FFLOCK; /* lock this while searching for vacant handle */ *status = mem_openmem( buffptr, buffsize, deltasize, mem_realloc, &handle); FFUNLOCK; if (*status > 0) { ffpmsg("failed to open pre-existing memory file: (ffimem)"); return(*status); } /* allocate fitsfile structure and initialize = 0 */ *fptr = (fitsfile *) calloc(1, sizeof(fitsfile)); if (!(*fptr)) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate structure for memory file: (ffimem)"); return(*status = MEMORY_ALLOCATION); } /* allocate FITSfile structure and initialize = 0 */ (*fptr)->Fptr = (FITSfile *) calloc(1, sizeof(FITSfile)); if (!((*fptr)->Fptr)) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate structure for memory file: (ffimem)"); free(*fptr); *fptr = 0; return(*status = MEMORY_ALLOCATION); } slen = 32; /* reserve at least 32 chars */ ((*fptr)->Fptr)->filename = (char *) malloc(slen); /* mem for file name */ if ( !(((*fptr)->Fptr)->filename) ) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate memory for filename: (ffimem)"); free((*fptr)->Fptr); free(*fptr); *fptr = 0; /* return null file pointer */ return(*status = MEMORY_ALLOCATION); } /* mem for headstart array */ ((*fptr)->Fptr)->headstart = (LONGLONG *) calloc(1001, sizeof(LONGLONG)); if ( !(((*fptr)->Fptr)->headstart) ) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate memory for headstart array: (ffimem)"); free( ((*fptr)->Fptr)->filename); free((*fptr)->Fptr); free(*fptr); *fptr = 0; /* return null file pointer */ return(*status = MEMORY_ALLOCATION); } /* mem for file I/O buffers */ ((*fptr)->Fptr)->iobuffer = (char *) calloc(NIOBUF, IOBUFLEN); if ( !(((*fptr)->Fptr)->iobuffer) ) { (*driverTable[driver].close)(handle); /* close the file */ ffpmsg("failed to allocate memory for iobuffer array: (ffimem)"); free( ((*fptr)->Fptr)->headstart); /* free memory for headstart array */ free( ((*fptr)->Fptr)->filename); free((*fptr)->Fptr); free(*fptr); *fptr = 0; /* return null file pointer */ return(*status = MEMORY_ALLOCATION); } /* initialize the ageindex array (relative age of the I/O buffers) */ /* and initialize the bufrecnum array as being empty */ for (ii = 0; ii < NIOBUF; ii++) { ((*fptr)->Fptr)->ageindex[ii] = ii; ((*fptr)->Fptr)->bufrecnum[ii] = -1; } /* store the parameters describing the file */ ((*fptr)->Fptr)->MAXHDU = 1000; /* initial size of headstart */ ((*fptr)->Fptr)->filehandle = handle; /* file handle */ ((*fptr)->Fptr)->driver = driver; /* driver number */ strcpy(((*fptr)->Fptr)->filename, "memfile"); /* dummy filename */ ((*fptr)->Fptr)->filesize = *buffsize; /* physical file size */ ((*fptr)->Fptr)->logfilesize = *buffsize; /* logical file size */ ((*fptr)->Fptr)->writemode = 1; /* read-write mode */ ((*fptr)->Fptr)->datastart = DATA_UNDEFINED; /* unknown start of data */ ((*fptr)->Fptr)->curbuf = -1; /* undefined current IO buffer */ ((*fptr)->Fptr)->open_count = 1; /* structure is currently used once */ ((*fptr)->Fptr)->validcode = VALIDSTRUC; /* flag denoting valid structure */ ffldrc(*fptr, 0, IGNORE_EOF, status); /* initialize first record */ fits_store_Fptr( (*fptr)->Fptr, status); /* store Fptr address */ return(*status); } /*--------------------------------------------------------------------------*/ int fits_init_cfitsio(void) /* initialize anything that is required before using the CFITSIO routines */ { int status; union u_tag { short ival; char cval[2]; } u; fitsio_init_lock(); FFLOCK; /* lockout other threads while executing this critical */ /* section of code */ if (need_to_initialize == 0) { /* already initialized? */ FFUNLOCK; return(0); } /* test for correct byteswapping. */ u.ival = 1; if ((BYTESWAPPED && u.cval[0] != 1) || (BYTESWAPPED == FALSE && u.cval[1] != 1) ) { printf ("\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); printf(" Byteswapping is not being done correctly on this system.\n"); printf(" Check the MACHINE and BYTESWAPPED definitions in fitsio2.h\n"); printf(" Please report this problem to the CFITSIO developers.\n"); printf( "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); FFUNLOCK; return(1); } /* test that LONGLONG is an 8 byte integer */ if (sizeof(LONGLONG) != 8) { printf ("\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); printf(" CFITSIO did not find an 8-byte long integer data type.\n"); printf(" sizeof(LONGLONG) = %d\n",(int)sizeof(LONGLONG)); printf(" Please report this problem to the CFITSIO developers.\n"); printf( "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); FFUNLOCK; return(1); } /* register the standard I/O drivers that are always available */ /* 1--------------------disk file driver-----------------------*/ status = fits_register_driver("file://", file_init, file_shutdown, file_setoptions, file_getoptions, file_getversion, file_checkfile, file_open, file_create, #ifdef HAVE_FTRUNCATE file_truncate, #else NULL, /* no file truncate function */ #endif file_close, file_remove, file_size, file_flush, file_seek, file_read, file_write); if (status) { ffpmsg("failed to register the file:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 2------------ output temporary memory file driver ----------------*/ status = fits_register_driver("mem://", mem_init, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, NULL, /* checkfile not needed */ NULL, /* open function not allowed */ mem_create, mem_truncate, mem_close_free, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the mem:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 3--------------input pre-existing memory file driver----------------*/ status = fits_register_driver("memkeep://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, NULL, /* checkfile not needed */ NULL, /* file open driver function is not used */ NULL, /* create function not allowed */ mem_truncate, mem_close_keep, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the memkeep:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 4-------------------stdin stream driver----------------------*/ /* the stdin stream is copied to memory then opened in memory */ status = fits_register_driver("stdin://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, stdin_checkfile, stdin_open, NULL, /* create function not allowed */ mem_truncate, mem_close_free, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the stdin:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 5-------------------stdin file stream driver----------------------*/ /* the stdin stream is copied to a disk file then the disk file is opened */ status = fits_register_driver("stdinfile://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, NULL, /* checkfile not needed */ stdin_open, NULL, /* create function not allowed */ #ifdef HAVE_FTRUNCATE file_truncate, #else NULL, /* no file truncate function */ #endif file_close, file_remove, file_size, file_flush, file_seek, file_read, file_write); if (status) { ffpmsg("failed to register the stdinfile:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 6-----------------------stdout stream driver------------------*/ status = fits_register_driver("stdout://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, NULL, /* checkfile not needed */ NULL, /* open function not required */ mem_create, mem_truncate, stdout_close, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the stdout:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 7------------------iraf disk file to memory driver -----------*/ status = fits_register_driver("irafmem://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, NULL, /* checkfile not needed */ mem_iraf_open, NULL, /* create function not required */ mem_truncate, mem_close_free, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the irafmem:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 8------------------raw binary file to memory driver -----------*/ status = fits_register_driver("rawfile://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, NULL, /* checkfile not needed */ mem_rawfile_open, NULL, /* create function not required */ mem_truncate, mem_close_free, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the rawfile:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 9------------------compressed disk file to memory driver -----------*/ status = fits_register_driver("compress://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, NULL, /* checkfile not needed */ mem_compress_open, NULL, /* create function not required */ mem_truncate, mem_close_free, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the compress:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 10------------------compressed disk file to memory driver -----------*/ /* Identical to compress://, except it allows READWRITE access */ status = fits_register_driver("compressmem://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, NULL, /* checkfile not needed */ mem_compress_openrw, NULL, /* create function not required */ mem_truncate, mem_close_free, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the compressmem:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 11------------------compressed disk file to disk file driver -------*/ status = fits_register_driver("compressfile://", NULL, file_shutdown, file_setoptions, file_getoptions, file_getversion, NULL, /* checkfile not needed */ file_compress_open, file_create, #ifdef HAVE_FTRUNCATE file_truncate, #else NULL, /* no file truncate function */ #endif file_close, file_remove, file_size, file_flush, file_seek, file_read, file_write); if (status) { ffpmsg("failed to register the compressfile:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 12---create file in memory, then compress it to disk file on close--*/ status = fits_register_driver("compressoutfile://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, NULL, /* checkfile not needed */ NULL, /* open function not allowed */ mem_create_comp, mem_truncate, mem_close_comp, file_remove, /* delete existing compressed disk file */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg( "failed to register the compressoutfile:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* Register Optional drivers */ #ifdef HAVE_NET_SERVICES /* 13--------------------root driver-----------------------*/ status = fits_register_driver("root://", root_init, root_shutdown, root_setoptions, root_getoptions, root_getversion, NULL, /* checkfile not needed */ root_open, root_create, NULL, /* No truncate possible */ root_close, NULL, /* No remove possible */ root_size, /* no size possible */ root_flush, root_seek, /* Though will always succeed */ root_read, root_write); if (status) { ffpmsg("failed to register the root:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 14--------------------http driver-----------------------*/ status = fits_register_driver("http://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, http_checkfile, http_open, NULL, /* create function not required */ mem_truncate, mem_close_free, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the http:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 15--------------------http file driver-----------------------*/ status = fits_register_driver("httpfile://", NULL, file_shutdown, file_setoptions, file_getoptions, file_getversion, NULL, /* checkfile not needed */ http_file_open, file_create, #ifdef HAVE_FTRUNCATE file_truncate, #else NULL, /* no file truncate function */ #endif file_close, file_remove, file_size, file_flush, file_seek, file_read, file_write); if (status) { ffpmsg("failed to register the httpfile:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 16--------------------http memory driver-----------------------*/ /* same as http:// driver, except memory file can be opened READWRITE */ status = fits_register_driver("httpmem://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, http_checkfile, http_file_open, /* this will simply call http_open */ NULL, /* create function not required */ mem_truncate, mem_close_free, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the httpmem:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 17--------------------httpcompress file driver-----------------------*/ status = fits_register_driver("httpcompress://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, NULL, /* checkfile not needed */ http_compress_open, NULL, /* create function not required */ mem_truncate, mem_close_free, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the httpcompress:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 18--------------------ftp driver-----------------------*/ status = fits_register_driver("ftp://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, ftp_checkfile, ftp_open, NULL, /* create function not required */ mem_truncate, mem_close_free, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the ftp:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 19--------------------ftp file driver-----------------------*/ status = fits_register_driver("ftpfile://", NULL, file_shutdown, file_setoptions, file_getoptions, file_getversion, NULL, /* checkfile not needed */ ftp_file_open, file_create, #ifdef HAVE_FTRUNCATE file_truncate, #else NULL, /* no file truncate function */ #endif file_close, file_remove, file_size, file_flush, file_seek, file_read, file_write); if (status) { ffpmsg("failed to register the ftpfile:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 20--------------------ftp mem driver-----------------------*/ /* same as ftp:// driver, except memory file can be opened READWRITE */ status = fits_register_driver("ftpmem://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, ftp_checkfile, ftp_file_open, /* this will simply call ftp_open */ NULL, /* create function not required */ mem_truncate, mem_close_free, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the ftpmem:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 21--------------------ftp compressed file driver------------------*/ status = fits_register_driver("ftpcompress://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, NULL, /* checkfile not needed */ ftp_compress_open, 0, /* create function not required */ mem_truncate, mem_close_free, 0, /* remove function not required */ mem_size, 0, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the ftpcompress:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* === End of net drivers section === */ #endif /* ==================== SHARED MEMORY DRIVER SECTION ======================= */ #ifdef HAVE_SHMEM_SERVICES /* 22--------------------shared memory driver-----------------------*/ status = fits_register_driver("shmem://", smem_init, smem_shutdown, smem_setoptions, smem_getoptions, smem_getversion, NULL, /* checkfile not needed */ smem_open, smem_create, NULL, /* truncate file not supported yet */ smem_close, smem_remove, smem_size, smem_flush, smem_seek, smem_read, smem_write ); if (status) { ffpmsg("failed to register the shmem:// driver (init_cfitsio)"); FFUNLOCK; return(status); } #endif /* ==================== END OF SHARED MEMORY DRIVER SECTION ================ */ #ifdef HAVE_GSIFTP /* 23--------------------gsiftp driver-----------------------*/ status = fits_register_driver("gsiftp://", gsiftp_init, gsiftp_shutdown, gsiftp_setoptions, gsiftp_getoptions, gsiftp_getversion, gsiftp_checkfile, gsiftp_open, gsiftp_create, #ifdef HAVE_FTRUNCATE gsiftp_truncate, #else NULL, #endif gsiftp_close, NULL, /* remove function not yet implemented */ gsiftp_size, gsiftp_flush, gsiftp_seek, gsiftp_read, gsiftp_write); if (status) { ffpmsg("failed to register the gsiftp:// driver (init_cfitsio)"); FFUNLOCK; return(status); } #endif /* 24---------------stdin and stdout stream driver-------------------*/ status = fits_register_driver("stream://", NULL, NULL, NULL, NULL, NULL, NULL, stream_open, stream_create, NULL, /* no stream truncate function */ stream_close, NULL, /* no stream remove */ stream_size, stream_flush, stream_seek, stream_read, stream_write); if (status) { ffpmsg("failed to register the stream:// driver (init_cfitsio)"); FFUNLOCK; return(status); } #ifdef HAVE_NET_SERVICES /* 25--------------------https driver-----------------------*/ status = fits_register_driver("https://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, https_checkfile, https_open, NULL, /* create function not required */ mem_truncate, mem_close_free, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the https:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 26--------------------https file driver-----------------------*/ status = fits_register_driver("httpsfile://", NULL, file_shutdown, file_setoptions, file_getoptions, file_getversion, NULL, /* checkfile not needed */ https_file_open, file_create, #ifdef HAVE_FTRUNCATE file_truncate, #else NULL, /* no file truncate function */ #endif file_close, file_remove, file_size, file_flush, file_seek, file_read, file_write); if (status) { ffpmsg("failed to register the httpsfile:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* 27--------------------https memory driver-----------------------*/ /* same as https:// driver, except memory file can be opened READWRITE */ status = fits_register_driver("httpsmem://", NULL, mem_shutdown, mem_setoptions, mem_getoptions, mem_getversion, https_checkfile, https_file_open, /* this will simply call https_open */ NULL, /* create function not required */ mem_truncate, mem_close_free, NULL, /* remove function not required */ mem_size, NULL, /* flush function not required */ mem_seek, mem_read, mem_write); if (status) { ffpmsg("failed to register the httpsmem:// driver (init_cfitsio)"); FFUNLOCK; return(status); } /* === End of https net drivers section === */ #endif /* reset flag. Any other threads will now not need to call this routine */ need_to_initialize = 0; FFUNLOCK; return(status); } /*--------------------------------------------------------------------------*/ int fits_register_driver(char *prefix, int (*init)(void), int (*shutdown)(void), int (*setoptions)(int option), int (*getoptions)(int *options), int (*getversion)(int *version), int (*checkfile) (char *urltype, char *infile, char *outfile), int (*open)(char *filename, int rwmode, int *driverhandle), int (*create)(char *filename, int *driverhandle), int (*truncate)(int driverhandle, LONGLONG filesize), int (*close)(int driverhandle), int (*fremove)(char *filename), int (*size)(int driverhandle, LONGLONG *sizex), int (*flush)(int driverhandle), int (*seek)(int driverhandle, LONGLONG offset), int (*read) (int driverhandle, void *buffer, long nbytes), int (*write)(int driverhandle, void *buffer, long nbytes) ) /* register all the functions needed to support an I/O driver */ { int status; if (no_of_drivers < 0 ) { /* This is bad. looks like memory has been corrupted. */ ffpmsg("Vital CFITSIO parameters held in memory have been corrupted!!"); ffpmsg("Fatal condition detected in fits_register_driver."); return(TOO_MANY_DRIVERS); } if (no_of_drivers + 1 > MAX_DRIVERS) return(TOO_MANY_DRIVERS); if (prefix == NULL) return(BAD_URL_PREFIX); if (init != NULL) { status = (*init)(); /* initialize the driver */ if (status) return(status); } /* fill in data in table */ strncpy(driverTable[no_of_drivers].prefix, prefix, MAX_PREFIX_LEN); driverTable[no_of_drivers].prefix[MAX_PREFIX_LEN - 1] = 0; driverTable[no_of_drivers].init = init; driverTable[no_of_drivers].shutdown = shutdown; driverTable[no_of_drivers].setoptions = setoptions; driverTable[no_of_drivers].getoptions = getoptions; driverTable[no_of_drivers].getversion = getversion; driverTable[no_of_drivers].checkfile = checkfile; driverTable[no_of_drivers].open = open; driverTable[no_of_drivers].create = create; driverTable[no_of_drivers].truncate = truncate; driverTable[no_of_drivers].close = close; driverTable[no_of_drivers].remove = fremove; driverTable[no_of_drivers].size = size; driverTable[no_of_drivers].flush = flush; driverTable[no_of_drivers].seek = seek; driverTable[no_of_drivers].read = read; driverTable[no_of_drivers].write = write; no_of_drivers++; /* increment the number of drivers */ return(0); } /*--------------------------------------------------------------------------*/ /* fits_parse_input_url */ int ffiurl(char *url, /* input filename */ char *urltype, /* e.g., 'file://', 'http://', 'mem://' */ char *infilex, /* root filename (may be complete path) */ char *outfile, /* optional output file name */ char *extspec, /* extension spec: +n or [extname, extver] */ char *rowfilterx, /* boolean row filter expression */ char *binspec, /* histogram binning specifier */ char *colspec, /* column or keyword modifier expression */ int *status) /* parse the input URL into its basic components. This routine does not support the pixfilter or compspec components. */ { return ffifile2(url, urltype, infilex, outfile, extspec, rowfilterx, binspec, colspec, 0, 0, status); } /*--------------------------------------------------------------------------*/ /* fits_parse_input_file */ int ffifile(char *url, /* input filename */ char *urltype, /* e.g., 'file://', 'http://', 'mem://' */ char *infilex, /* root filename (may be complete path) */ char *outfile, /* optional output file name */ char *extspec, /* extension spec: +n or [extname, extver] */ char *rowfilterx, /* boolean row filter expression */ char *binspec, /* histogram binning specifier */ char *colspec, /* column or keyword modifier expression */ char *pixfilter, /* pixel filter expression */ int *status) /* fits_parse_input_filename parse the input URL into its basic components. This routine does not support the compspec component. */ { return ffifile2(url, urltype, infilex, outfile, extspec, rowfilterx, binspec, colspec, pixfilter, 0, status); } /*--------------------------------------------------------------------------*/ int ffifile2(char *url, /* input filename */ char *urltype, /* e.g., 'file://', 'http://', 'mem://' */ char *infilex, /* root filename (may be complete path) */ char *outfile, /* optional output file name */ char *extspec, /* extension spec: +n or [extname, extver] */ char *rowfilterx, /* boolean row filter expression */ char *binspec, /* histogram binning specifier */ char *colspec, /* column or keyword modifier expression */ char *pixfilter, /* pixel filter expression */ char *compspec, /* image compression specification */ int *status) /* fits_parse_input_filename parse the input URL into its basic components. This routine is big and ugly and should be redesigned someday! */ { int ii, jj, slen, infilelen, plus_ext = 0, collen; char *ptr1, *ptr2, *ptr3, *ptr4, *tmptr; int hasAt, hasDot, hasOper, followingOper, spaceTerm, rowFilter; int colStart, binStart, pixStart, compStart; /* must have temporary variable for these, in case inputs are NULL */ char *infile; char *rowfilter; char *tmpstr; if (*status > 0) return(*status); /* Initialize null strings */ if (infilex) *infilex = '\0'; if (urltype) *urltype = '\0'; if (outfile) *outfile = '\0'; if (extspec) *extspec = '\0'; if (binspec) *binspec = '\0'; if (colspec) *colspec = '\0'; if (rowfilterx) *rowfilterx = '\0'; if (pixfilter) *pixfilter = '\0'; if (compspec) *compspec = '\0'; slen = strlen(url); if (slen == 0) /* blank filename ?? */ return(*status); /* allocate memory for 3 strings, each as long as the input url */ infile = (char *) calloc(3, slen + 1); if (!infile) return(*status = MEMORY_ALLOCATION); rowfilter = &infile[slen + 1]; tmpstr = &rowfilter[slen + 1]; ptr1 = url; /* -------------------------------------------------------- */ /* get urltype (e.g., file://, ftp://, http://, etc.) */ /* --------------------------------------------------------- */ if (*ptr1 == '-' && ( *(ptr1 +1) == 0 || *(ptr1 +1) == ' ' || *(ptr1 +1) == '[' || *(ptr1 +1) == '(' ) ) { /* "-" means read file from stdin. Also support "- ", */ /* "-[extname]" and '-(outfile.fits)" but exclude disk file */ /* names that begin with a minus sign, e.g., "-55d33m.fits" */ if (urltype) strcat(urltype, "stdin://"); ptr1++; } else if (!fits_strncasecmp(ptr1, "stdin", 5)) { if (urltype) strcat(urltype, "stdin://"); ptr1 = ptr1 + 5; } else { ptr2 = strstr(ptr1, "://"); ptr3 = strstr(ptr1, "(" ); if (ptr3 && (ptr3 < ptr2) ) { /* the urltype follows a '(' character, so it must apply */ /* to the output file, and is not the urltype of the input file */ ptr2 = 0; /* so reset pointer to zero */ } if (ptr2) /* copy the explicit urltype string */ { if (urltype) strncat(urltype, ptr1, ptr2 - ptr1 + 3); ptr1 = ptr2 + 3; } else if (!strncmp(ptr1, "ftp:", 4) ) { /* the 2 //'s are optional */ if (urltype) strcat(urltype, "ftp://"); ptr1 += 4; } else if (!strncmp(ptr1, "gsiftp:", 7) ) { /* the 2 //'s are optional */ if (urltype) strcat(urltype, "gsiftp://"); ptr1 += 7; } else if (!strncmp(ptr1, "http:", 5) ) { /* the 2 //'s are optional */ if (urltype) strcat(urltype, "http://"); ptr1 += 5; } else if (!strncmp(ptr1, "mem:", 4) ) { /* the 2 //'s are optional */ if (urltype) strcat(urltype, "mem://"); ptr1 += 4; } else if (!strncmp(ptr1, "shmem:", 6) ) { /* the 2 //'s are optional */ if (urltype) strcat(urltype, "shmem://"); ptr1 += 6; } else if (!strncmp(ptr1, "file:", 5) ) { /* the 2 //'s are optional */ if (urltype) strcat(urltype, "file://"); ptr1 += 5; } else /* assume file driver */ { if (urltype) strcat(urltype, "file://"); } } /* ---------------------------------------------------------- If this is a http:// type file, then the cgi file name could include the '[' character, which should not be interpreted as part of CFITSIO's Extended File Name Syntax. Test for this case by seeing if the last character is a ']' or ')'. If it is not, then just treat the whole input string as the file name and do not attempt to interprete the name using the extended filename syntax. ----------------------------------------------------------- */ if (urltype && !strncmp(urltype, "http://", 7) ) { /* test for opening parenthesis or bracket in the file name */ if( strchr(ptr1, '(' ) || strchr(ptr1, '[' ) ) { slen = strlen(ptr1); ptr3 = ptr1 + slen - 1; while (*ptr3 == ' ') /* ignore trailing blanks */ ptr3--; if (*ptr3 != ']' && *ptr3 != ')' ) { /* name doesn't end with a ']' or ')' so don't try */ /* to parse this unusual string (may be cgi string) */ if (infilex) { if (strlen(ptr1) > FLEN_FILENAME - 1) { ffpmsg("Name of file is too long."); return(*status = URL_PARSE_ERROR); } strcpy(infilex, ptr1); } free(infile); return(*status); } } } /* ---------------------------------------------------------- Look for VMS style filenames like: disk:[directory.subdirectory]filename.ext, or [directory.subdirectory]filename.ext Check if the first character is a '[' and urltype != stdin or if there is a ':[' string in the remaining url string. If so, then need to move past this bracket character before search for the opening bracket of a filter specification. ----------------------------------------------------------- */ tmptr = ptr1; if (*ptr1 == '[') { if (*url != '-') tmptr = ptr1 + 1; /* this bracket encloses a VMS directory name */ } else { tmptr = strstr(ptr1, ":["); if (tmptr) /* these 2 chars are part of the VMS disk and directory */ tmptr += 2; else tmptr = ptr1; } /* ------------------------ */ /* get the input file name */ /* ------------------------ */ ptr2 = strchr(tmptr, '('); /* search for opening parenthesis ( */ ptr3 = strchr(tmptr, '['); /* search for opening bracket [ */ if (ptr2 == ptr3) /* simple case: no [ or ( in the file name */ { strcat(infile, ptr1); } else if (!ptr3 || /* no bracket, so () enclose output file name */ (ptr2 && (ptr2 < ptr3)) ) /* () enclose output name before bracket */ { strncat(infile, ptr1, ptr2 - ptr1); ptr2++; ptr1 = strchr(ptr2, ')' ); /* search for closing ) */ if (!ptr1) { free(infile); return(*status = URL_PARSE_ERROR); /* error, no closing ) */ } if (outfile) { if (ptr1 - ptr2 > FLEN_FILENAME - 1) { free(infile); return(*status = URL_PARSE_ERROR); } strncat(outfile, ptr2, ptr1 - ptr2); } /* the opening [ could have been part of output name, */ /* e.g., file(out[compress])[3][#row > 5] */ /* so search again for opening bracket following the closing ) */ ptr3 = strchr(ptr1, '['); } else /* bracket comes first, so there is no output name */ { strncat(infile, ptr1, ptr3 - ptr1); } /* strip off any trailing blanks in the names */ slen = strlen(infile); while ( (--slen) > 0 && infile[slen] == ' ') infile[slen] = '\0'; if (outfile) { slen = strlen(outfile); while ( (--slen) > 0 && outfile[slen] == ' ') outfile[slen] = '\0'; } /* --------------------------------------------- */ /* check if this is an IRAF file (.imh extension */ /* --------------------------------------------- */ ptr4 = strstr(infile, ".imh"); /* did the infile name end with ".imh" ? */ if (ptr4 && (*(ptr4 + 4) == '\0')) { if (urltype) strcpy(urltype, "irafmem://"); } /* --------------------------------------------- */ /* check if the 'filename+n' convention has been */ /* used to specifiy which HDU number to open */ /* --------------------------------------------- */ jj = strlen(infile); for (ii = jj - 1; ii >= 0; ii--) { if (infile[ii] == '+') /* search backwards for '+' sign */ break; } if (ii > 0 && (jj - ii) < 7) /* limit extension numbers to 5 digits */ { infilelen = ii; ii++; ptr1 = infile+ii; /* pointer to start of sequence */ for (; ii < jj; ii++) { if (!isdigit((int) infile[ii] ) ) /* are all the chars digits? */ break; } if (ii == jj) { /* yes, the '+n' convention was used. Copy */ /* the digits to the output extspec string. */ plus_ext = 1; if (extspec) { if (jj - infilelen > FLEN_FILENAME - 1) { free(infile); return(*status = URL_PARSE_ERROR); } strncpy(extspec, ptr1, jj - infilelen); } infile[infilelen] = '\0'; /* delete the extension number */ } } /* -------------------------------------------------------------------- */ /* if '*' was given for the output name expand it to the root file name */ /* -------------------------------------------------------------------- */ if (outfile && outfile[0] == '*') { /* scan input name backwards to the first '/' character */ for (ii = jj - 1; ii >= 0; ii--) { if (infile[ii] == '/' || ii == 0) { if (strlen(&infile[ii + 1]) > FLEN_FILENAME - 1) { free(infile); return(*status = URL_PARSE_ERROR); } strcpy(outfile, &infile[ii + 1]); break; } } } /* ------------------------------------------ */ /* copy strings from local copy to the output */ /* ------------------------------------------ */ if (infilex) { if (strlen(infile) > FLEN_FILENAME - 1) { free(infile); return(*status = URL_PARSE_ERROR); } strcpy(infilex, infile); } /* ---------------------------------------------------------- */ /* if no '[' character in the input string, then we are done. */ /* ---------------------------------------------------------- */ if (!ptr3) { free(infile); return(*status); } /* ------------------------------------------- */ /* see if [ extension specification ] is given */ /* ------------------------------------------- */ if (!plus_ext) /* extension no. not already specified? Then */ /* first brackets must enclose extension name or # */ /* or it encloses a image subsection specification */ /* or a raw binary image specifier */ /* or a image compression specifier */ /* Or, the extension specification may have been */ /* omitted and we have to guess what the user intended */ { ptr1 = ptr3 + 1; /* pointer to first char after the [ */ ptr2 = strchr(ptr1, ']' ); /* search for closing ] */ if (!ptr2) { ffpmsg("input file URL is missing closing bracket ']'"); free(infile); return(*status = URL_PARSE_ERROR); /* error, no closing ] */ } /* ---------------------------------------------- */ /* First, test if this is a rawfile specifier */ /* which looks something like: '[ib512,512:2880]' */ /* Test if first character is b,i,j,d,r,f, or u, */ /* and optional second character is b or l, */ /* followed by one or more digits, */ /* finally followed by a ',', ':', or ']' */ /* ---------------------------------------------- */ if (*ptr1 == 'b' || *ptr1 == 'B' || *ptr1 == 'i' || *ptr1 == 'I' || *ptr1 == 'j' || *ptr1 == 'J' || *ptr1 == 'd' || *ptr1 == 'D' || *ptr1 == 'r' || *ptr1 == 'R' || *ptr1 == 'f' || *ptr1 == 'F' || *ptr1 == 'u' || *ptr1 == 'U') { /* next optional character may be a b or l (for Big or Little) */ ptr1++; if (*ptr1 == 'b' || *ptr1 == 'B' || *ptr1 == 'l' || *ptr1 == 'L') ptr1++; if (isdigit((int) *ptr1)) /* must have at least 1 digit */ { while (isdigit((int) *ptr1)) ptr1++; /* skip over digits */ if (*ptr1 == ',' || *ptr1 == ':' || *ptr1 == ']' ) { /* OK, this looks like a rawfile specifier */ if (urltype) { if (strstr(urltype, "stdin") ) strcpy(urltype, "rawstdin://"); else strcpy(urltype, "rawfile://"); } /* append the raw array specifier to infilex */ if (infilex) { if (strlen(infilex) + strlen(ptr3) > FLEN_FILENAME - 1) { free(infile); return(*status = URL_PARSE_ERROR); } strcat(infilex, ptr3); ptr1 = strchr(infilex, ']'); /* find the closing ] char */ if (ptr1) *(ptr1 + 1) = '\0'; /* terminate string after the ] */ } if (extspec) strcpy(extspec, "0"); /* the 0 ext number is implicit */ tmptr = strchr(ptr2 + 1, '[' ); /* search for another [ char */ /* copy any remaining characters into rowfilterx */ if (tmptr && rowfilterx) { if (strlen(rowfilterx) + strlen(tmptr + 1) > FLEN_FILENAME -1) { free(infile); return(*status = URL_PARSE_ERROR); } strcat(rowfilterx, tmptr + 1); tmptr = strchr(rowfilterx, ']' ); /* search for closing ] */ if (tmptr) *tmptr = '\0'; /* overwrite the ] with null terminator */ } free(infile); /* finished parsing, so return */ return(*status); } } } /* end of rawfile specifier test */ /* -------------------------------------------------------- */ /* Not a rawfile, so next, test if this is an image section */ /* i.e., an integer followed by a ':' or a '*' or '-*' */ /* -------------------------------------------------------- */ ptr1 = ptr3 + 1; /* reset pointer to first char after the [ */ tmptr = ptr1; while (*tmptr == ' ') tmptr++; /* skip leading blanks */ while (isdigit((int) *tmptr)) tmptr++; /* skip over leading digits */ if (*tmptr == ':' || *tmptr == '*' || *tmptr == '-') { /* this is an image section specifier */ strcat(rowfilter, ptr3); /* don't want to assume 0 extension any more; may imply an image extension. if (extspec) strcpy(extspec, "0"); */ } else { /* ----------------------------------------------------------------- Not an image section or rawfile spec so may be an extension spec. Examples of valid extension specifiers: [3] - 3rd extension; 0 = primary array [events] - events extension [events, 2] - events extension, with EXTVER = 2 [events,2] - spaces are optional [events, 3, b] - same as above, plus XTENSION = 'BINTABLE' [PICS; colName(12)] - an image in row 12 of the colName column in the PICS table extension [PICS; colName(exposure > 1000)] - as above, but find image in first row with with exposure column value > 1000. [Rate Table] - extension name can contain spaces! [Rate Table;colName(exposure>1000)] Examples of other types of specifiers (Not extension specifiers) [bin] !!! this is ambiguous, and can't be distinguished from a valid extension specifier [bini X=1:512:16] (also binb, binj, binr, and bind are allowed) [binr (X,Y) = 5] [bin @binfilter.txt] [col Time;rate] [col PI=PHA * 1.1] [col -Time; status] [X > 5] [X>5] [@filter.txt] [StatusCol] !!! this is ambiguous, and can't be distinguished from a valid extension specifier [StatusCol==0] [StatusCol || x>6] [gtifilter()] [regfilter("region.reg")] [compress Rice] There will always be some ambiguity between an extension name and a boolean row filtering expression, (as in a couple of the above examples). If there is any doubt, the expression should be treated as an extension specification; The user can always add an explicit expression specifier to override this interpretation. The following decision logic will be used: 1) locate the first token, terminated with a space, comma, semi-colon, or closing bracket. 2) the token is not part of an extension specifier if any of the following is true: - if the token begins with '@' and contains a '.' - if the token contains an operator: = > < || && - if the token begins with "gtifilter(" or "regfilter(" - if the token is terminated by a space and is followed by additional characters (not a ']') AND any of the following: - the token is 'col' - the token is 3 or 4 chars long and begins with 'bin' - the second token begins with an operator: ! = < > | & + - * / % 3) otherwise, the string is assumed to be an extension specifier ----------------------------------------------------------------- */ tmptr = ptr1; while(*tmptr == ' ') tmptr++; hasAt = 0; hasDot = 0; hasOper = 0; followingOper = 0; spaceTerm = 0; rowFilter = 0; colStart = 0; binStart = 0; pixStart = 0; compStart = 0; if (*tmptr == '@') /* test for leading @ symbol */ hasAt = 1; if ( !fits_strncasecmp(tmptr, "col ", 4) ) colStart = 1; if ( !fits_strncasecmp(tmptr, "bin", 3) ) binStart = 1; if ( !fits_strncasecmp(tmptr, "pix", 3) ) pixStart = 1; if ( !fits_strncasecmp(tmptr, "compress ", 9) || !fits_strncasecmp(tmptr, "compress]", 9) ) compStart = 1; if ( !fits_strncasecmp(tmptr, "gtifilter(", 10) || !fits_strncasecmp(tmptr, "regfilter(", 10) ) { rowFilter = 1; } else { /* parse the first token of the expression */ for (ii = 0; ii < ptr2 - ptr1 + 1; ii++, tmptr++) { if (*tmptr == '.') hasDot = 1; else if (*tmptr == '=' || *tmptr == '>' || *tmptr == '<' || (*tmptr == '|' && *(tmptr+1) == '|') || (*tmptr == '&' && *(tmptr+1) == '&') ) hasOper = 1; else if (*tmptr == ',' || *tmptr == ';' || *tmptr == ']') { break; } else if (*tmptr == ' ') /* a space char? */ { while(*tmptr == ' ') /* skip spaces */ tmptr++; if (*tmptr == ']') /* is this the end? */ break; spaceTerm = 1; /* 1st token is terminated by space */ /* test if this is a column or binning specifier */ if (colStart || (ii <= 4 && (binStart || pixStart)) ) rowFilter = 1; else { /* check if next character is an operator */ if (*tmptr == '=' || *tmptr == '>' || *tmptr == '<' || *tmptr == '|' || *tmptr == '&' || *tmptr == '!' || *tmptr == '+' || *tmptr == '-' || *tmptr == '*' || *tmptr == '/' || *tmptr == '%') followingOper = 1; } break; } } } /* test if this is NOT an extension specifier */ if ( rowFilter || (pixStart && spaceTerm) || (hasAt && hasDot) || hasOper || compStart || (spaceTerm && followingOper) ) { /* this is (probably) not an extension specifier */ /* so copy all chars to filter spec string */ strcat(rowfilter, ptr3); } else { /* this appears to be a legit extension specifier */ /* copy the extension specification */ if (extspec) { if (ptr2 - ptr1 > FLEN_FILENAME - 1) { free(infile); return(*status = URL_PARSE_ERROR); } strncat(extspec, ptr1, ptr2 - ptr1); } /* copy any remaining chars to filter spec string */ strcat(rowfilter, ptr2 + 1); } } } /* end of if (!plus_ext) */ else { /* ------------------------------------------------------------------ */ /* already have extension, so this must be a filter spec of some sort */ /* ------------------------------------------------------------------ */ strcat(rowfilter, ptr3); } /* strip off any trailing blanks from filter */ slen = strlen(rowfilter); while ( (--slen) >= 0 && rowfilter[slen] == ' ') rowfilter[slen] = '\0'; if (!rowfilter[0]) { free(infile); return(*status); /* nothing left to parse */ } /* ------------------------------------------------ */ /* does the filter contain a binning specification? */ /* ------------------------------------------------ */ ptr1 = strstr(rowfilter, "[bin"); /* search for "[bin" */ if (!ptr1) ptr1 = strstr(rowfilter, "[BIN"); /* search for "[BIN" */ if (!ptr1) ptr1 = strstr(rowfilter, "[Bin"); /* search for "[Bin" */ if (ptr1) { ptr2 = ptr1 + 4; /* end of the '[bin' string */ if (*ptr2 == 'b' || *ptr2 == 'i' || *ptr2 == 'j' || *ptr2 == 'r' || *ptr2 == 'd') ptr2++; /* skip the datatype code letter */ if ( *ptr2 != ' ' && *ptr2 != ']') ptr1 = NULL; /* bin string must be followed by space or ] */ } if (ptr1) { /* found the binning string */ if (binspec) { if (strlen(ptr1 +1) > FLEN_FILENAME - 1) { free(infile); return(*status = URL_PARSE_ERROR); } strcpy(binspec, ptr1 + 1); ptr2 = strchr(binspec, ']'); if (ptr2) /* terminate the binning filter */ { *ptr2 = '\0'; if ( *(--ptr2) == ' ') /* delete trailing spaces */ *ptr2 = '\0'; } else { ffpmsg("input file URL is missing closing bracket ']'"); ffpmsg(rowfilter); free(infile); return(*status = URL_PARSE_ERROR); /* error, no closing ] */ } } /* delete the binning spec from the row filter string */ ptr2 = strchr(ptr1, ']'); strcpy(tmpstr, ptr2+1); /* copy any chars after the binspec */ strcpy(ptr1, tmpstr); /* overwrite binspec */ } /* --------------------------------------------------------- */ /* does the filter contain a column selection specification? */ /* --------------------------------------------------------- */ ptr1 = strstr(rowfilter, "[col "); if (!ptr1) { ptr1 = strstr(rowfilter, "[COL "); if (!ptr1) ptr1 = strstr(rowfilter, "[Col "); } if (ptr1) { /* find the end of the column specifier */ ptr2 = ptr1 + 5; while (*ptr2 != ']') { if (*ptr2 == '\0') { ffpmsg("input file URL is missing closing bracket ']'"); free(infile); return(*status = URL_PARSE_ERROR); /* error, no closing ] */ } if (*ptr2 == '\'') /* start of a literal string */ { ptr2 = strchr(ptr2 + 1, '\''); /* find closing quote */ if (!ptr2) { ffpmsg ("literal string in input file URL is missing closing single quote"); free(infile); return(*status = URL_PARSE_ERROR); /* error, no closing ] */ } } if (*ptr2 == '[') /* set of nested square brackets */ { ptr2 = strchr(ptr2 + 1, ']'); /* find closing bracket */ if (!ptr2) { ffpmsg ("nested brackets in input file URL is missing closing bracket"); free(infile); return(*status = URL_PARSE_ERROR); /* error, no closing ] */ } } ptr2++; /* continue search for the closing bracket character */ } collen = ptr2 - ptr1 - 1; if (colspec) /* copy the column specifier to output string */ { if (collen > FLEN_FILENAME - 1) { free(infile); return(*status = URL_PARSE_ERROR); } strncpy(colspec, ptr1 + 1, collen); colspec[collen] = '\0'; while (colspec[--collen] == ' ') colspec[collen] = '\0'; /* strip trailing blanks */ } /* delete the column selection spec from the row filter string */ strcpy(tmpstr, ptr2 + 1); /* copy any chars after the colspec */ strcpy(ptr1, tmpstr); /* overwrite binspec */ } /* --------------------------------------------------------- */ /* does the filter contain a pixel filter specification? */ /* --------------------------------------------------------- */ ptr1 = strstr(rowfilter, "[pix"); if (!ptr1) { ptr1 = strstr(rowfilter, "[PIX"); if (!ptr1) ptr1 = strstr(rowfilter, "[Pix"); } if (ptr1) { ptr2 = ptr1 + 4; /* end of the '[pix' string */ if (*ptr2 == 'b' || *ptr2 == 'i' || *ptr2 == 'j' || *ptr2 == 'B' || *ptr2 == 'I' || *ptr2 == 'J' || *ptr2 == 'r' || *ptr2 == 'd' || *ptr2 == 'R' || *ptr2 == 'D') ptr2++; /* skip the datatype code letter */ if (*ptr2 == '1') ptr2++; /* skip the single HDU indicator */ if ( *ptr2 != ' ') ptr1 = NULL; /* pix string must be followed by space */ } if (ptr1) { /* find the end of the pixel filter */ while (*ptr2 != ']') { if (*ptr2 == '\0') { ffpmsg("input file URL is missing closing bracket ']'"); free(infile); return(*status = URL_PARSE_ERROR); /* error, no closing ] */ } if (*ptr2 == '\'') /* start of a literal string */ { ptr2 = strchr(ptr2 + 1, '\''); /* find closing quote */ if (!ptr2) { ffpmsg ("literal string in input file URL is missing closing single quote"); free(infile); return(*status = URL_PARSE_ERROR); /* error, no closing ] */ } } if (*ptr2 == '[') /* set of nested square brackets */ { ptr2 = strchr(ptr2 + 1, ']'); /* find closing bracket */ if (!ptr2) { ffpmsg ("nested brackets in input file URL is missing closing bracket"); free(infile); return(*status = URL_PARSE_ERROR); /* error, no closing ] */ } } ptr2++; /* continue search for the closing bracket character */ } collen = ptr2 - ptr1 - 1; if (pixfilter) /* copy the column specifier to output string */ { if (collen > FLEN_FILENAME - 1) { free(infile); return(*status = URL_PARSE_ERROR); } strncpy(pixfilter, ptr1 + 1, collen); pixfilter[collen] = '\0'; while (pixfilter[--collen] == ' ') pixfilter[collen] = '\0'; /* strip trailing blanks */ } /* delete the pixel filter from the row filter string */ strcpy(tmpstr, ptr2 + 1); /* copy any chars after the pixel filter */ strcpy(ptr1, tmpstr); /* overwrite binspec */ } /* ------------------------------------------------------------ */ /* does the filter contain an image compression specification? */ /* ------------------------------------------------------------ */ ptr1 = strstr(rowfilter, "[compress"); if (ptr1) { ptr2 = ptr1 + 9; /* end of the '[compress' string */ if ( *ptr2 != ' ' && *ptr2 != ']') ptr1 = NULL; /* compress string must be followed by space or ] */ } if (ptr1) { /* found the compress string */ if (compspec) { if (strlen(ptr1 +1) > FLEN_FILENAME - 1) { free(infile); return(*status = URL_PARSE_ERROR); } strcpy(compspec, ptr1 + 1); ptr2 = strchr(compspec, ']'); if (ptr2) /* terminate the binning filter */ { *ptr2 = '\0'; if ( *(--ptr2) == ' ') /* delete trailing spaces */ *ptr2 = '\0'; } else { ffpmsg("input file URL is missing closing bracket ']'"); ffpmsg(rowfilter); free(infile); return(*status = URL_PARSE_ERROR); /* error, no closing ] */ } } /* delete the compression spec from the row filter string */ ptr2 = strchr(ptr1, ']'); strcpy(tmpstr, ptr2+1); /* copy any chars after the binspec */ strcpy(ptr1, tmpstr); /* overwrite binspec */ } /* copy the remaining string to the rowfilter output... should only */ /* contain a rowfilter expression of the form "[expr]" */ if (rowfilterx && rowfilter[0]) { ptr2 = rowfilter + strlen(rowfilter) - 1; if( rowfilter[0]=='[' && *ptr2==']' ) { *ptr2 = '\0'; if (strlen(rowfilter + 1) > FLEN_FILENAME - 1) { free(infile); return(*status = URL_PARSE_ERROR); } strcpy(rowfilterx, rowfilter+1); } else { ffpmsg("input file URL lacks valid row filter expression"); *status = URL_PARSE_ERROR; } } free(infile); return(*status); } /*--------------------------------------------------------------------------*/ int ffexist(const char *infile, /* I - input filename or URL */ int *exists, /* O - 2 = a compressed version of file exists */ /* 1 = yes, disk file exists */ /* 0 = no, disk file could not be found */ /* -1 = infile is not a disk file (could */ /* be a http, ftp, gsiftp, smem, or stdin file) */ int *status) /* I/O status */ /* test if the input file specifier is an existing file on disk If the specified file can't be found, it then searches for a compressed version of the file. */ { FILE *diskfile; char rootname[FLEN_FILENAME]; char *ptr1; if (*status > 0) return(*status); /* strip off any extname or filters from the name */ ffrtnm( (char *)infile, rootname, status); ptr1 = strstr(rootname, "://"); if (ptr1 || *rootname == '-') { if (!strncmp(rootname, "file", 4) ) { ptr1 = ptr1 + 3; /* pointer to start of the disk file name */ } else { *exists = -1; /* this is not a disk file */ return (*status); } } else { ptr1 = rootname; } /* see if the disk file exists */ if (file_openfile(ptr1, 0, &diskfile)) { /* no, couldn't open file, so see if there is a compressed version */ if (file_is_compressed(ptr1) ) { *exists = 2; /* a compressed version of the file exists */ } else { *exists = 0; /* neither file nor compressed version exist */ } } else { /* yes, file exists */ *exists = 1; fclose(diskfile); } return(*status); } /*--------------------------------------------------------------------------*/ int ffrtnm(char *url, char *rootname, int *status) /* parse the input URL, returning the root name (filetype://basename). */ { int ii, jj, slen, infilelen; char *ptr1, *ptr2, *ptr3; char urltype[MAX_PREFIX_LEN]; char infile[FLEN_FILENAME]; if (*status > 0) return(*status); ptr1 = url; *rootname = '\0'; *urltype = '\0'; *infile = '\0'; /* get urltype (e.g., file://, ftp://, http://, etc.) */ if (*ptr1 == '-') /* "-" means read file from stdin */ { strcat(urltype, "-"); ptr1++; } else if (!strncmp(ptr1, "stdin", 5) || !strncmp(ptr1, "STDIN", 5)) { strcat(urltype, "-"); ptr1 = ptr1 + 5; } else { ptr2 = strstr(ptr1, "://"); ptr3 = strstr(ptr1, "(" ); if (ptr3 && (ptr3 < ptr2) ) { /* the urltype follows a '(' character, so it must apply */ /* to the output file, and is not the urltype of the input file */ ptr2 = 0; /* so reset pointer to zero */ } if (ptr2) /* copy the explicit urltype string */ { if (ptr2 - ptr1 + 3 > MAX_PREFIX_LEN - 1) { return(*status = URL_PARSE_ERROR); } strncat(urltype, ptr1, ptr2 - ptr1 + 3); ptr1 = ptr2 + 3; } else if (!strncmp(ptr1, "ftp:", 4) ) { /* the 2 //'s are optional */ strcat(urltype, "ftp://"); ptr1 += 4; } else if (!strncmp(ptr1, "gsiftp:", 7) ) { /* the 2 //'s are optional */ strcat(urltype, "gsiftp://"); ptr1 += 7; } else if (!strncmp(ptr1, "http:", 5) ) { /* the 2 //'s are optional */ strcat(urltype, "http://"); ptr1 += 5; } else if (!strncmp(ptr1, "mem:", 4) ) { /* the 2 //'s are optional */ strcat(urltype, "mem://"); ptr1 += 4; } else if (!strncmp(ptr1, "shmem:", 6) ) { /* the 2 //'s are optional */ strcat(urltype, "shmem://"); ptr1 += 6; } else if (!strncmp(ptr1, "file:", 5) ) { /* the 2 //'s are optional */ ptr1 += 5; } /* else assume file driver */ } /* get the input file name */ ptr2 = strchr(ptr1, '('); /* search for opening parenthesis ( */ ptr3 = strchr(ptr1, '['); /* search for opening bracket [ */ if (ptr2 == ptr3) /* simple case: no [ or ( in the file name */ { if (strlen(ptr1) > FLEN_FILENAME - 1) { return(*status = URL_PARSE_ERROR); } strcat(infile, ptr1); } else if (!ptr3) /* no bracket, so () enclose output file name */ { if (ptr2 - ptr1 > FLEN_FILENAME - 1) { return(*status = URL_PARSE_ERROR); } strncat(infile, ptr1, ptr2 - ptr1); ptr2++; ptr1 = strchr(ptr2, ')' ); /* search for closing ) */ if (!ptr1) return(*status = URL_PARSE_ERROR); /* error, no closing ) */ } else if (ptr2 && (ptr2 < ptr3)) /* () enclose output name before bracket */ { if (ptr2 - ptr1 > FLEN_FILENAME - 1) { return(*status = URL_PARSE_ERROR); } strncat(infile, ptr1, ptr2 - ptr1); ptr2++; ptr1 = strchr(ptr2, ')' ); /* search for closing ) */ if (!ptr1) return(*status = URL_PARSE_ERROR); /* error, no closing ) */ } else /* bracket comes first, so there is no output name */ { if (ptr3 - ptr1 > FLEN_FILENAME - 1) { return(*status = URL_PARSE_ERROR); } strncat(infile, ptr1, ptr3 - ptr1); } /* strip off any trailing blanks in the names */ slen = strlen(infile); for (ii = slen - 1; ii > 0; ii--) { if (infile[ii] == ' ') infile[ii] = '\0'; else break; } /* --------------------------------------------- */ /* check if the 'filename+n' convention has been */ /* used to specifiy which HDU number to open */ /* --------------------------------------------- */ jj = strlen(infile); for (ii = jj - 1; ii >= 0; ii--) { if (infile[ii] == '+') /* search backwards for '+' sign */ break; } if (ii > 0 && (jj - ii) < 5) /* limit extension numbers to 4 digits */ { infilelen = ii; ii++; for (; ii < jj; ii++) { if (!isdigit((int) infile[ii] ) ) /* are all the chars digits? */ break; } if (ii == jj) { /* yes, the '+n' convention was used. */ infile[infilelen] = '\0'; /* delete the extension number */ } } if (strlen(urltype) + strlen(infile) > FLEN_FILENAME - 1) { return(*status = URL_PARSE_ERROR); } strcat(rootname, urltype); /* construct the root name */ strcat(rootname, infile); return(*status); } /*--------------------------------------------------------------------------*/ int ffourl(char *url, /* I - full input URL */ char *urltype, /* O - url type */ char *outfile, /* O - base file name */ char *tpltfile, /* O - template file name, if any */ char *compspec, /* O - compression specification, if any */ int *status) /* parse the output URL into its basic components. */ { char *ptr1, *ptr2, *ptr3; if (*status > 0) return(*status); if (urltype) *urltype = '\0'; if (outfile) *outfile = '\0'; if (tpltfile) *tpltfile = '\0'; if (compspec) *compspec = '\0'; ptr1 = url; while (*ptr1 == ' ') /* ignore leading blanks */ ptr1++; if ( ( (*ptr1 == '-') && ( *(ptr1 +1) == 0 || *(ptr1 +1) == ' ' ) ) || !strcmp(ptr1, "stdout") || !strcmp(ptr1, "STDOUT")) /* "-" means write to stdout; also support "- " */ /* but exclude disk file names that begin with a minus sign */ /* e.g., "-55d33m.fits" */ { if (urltype) strcpy(urltype, "stdout://"); } else { /* not writing to stdout */ /* get urltype (e.g., file://, ftp://, http://, etc.) */ ptr2 = strstr(ptr1, "://"); if (ptr2) /* copy the explicit urltype string */ { if (urltype) { if (ptr2 - ptr1 + 3 > MAX_PREFIX_LEN - 1) { return(*status = URL_PARSE_ERROR); } strncat(urltype, ptr1, ptr2 - ptr1 + 3); } ptr1 = ptr2 + 3; } else /* assume file driver */ { if (urltype) strcat(urltype, "file://"); } /* look for template file name, enclosed in parenthesis */ ptr2 = strchr(ptr1, '('); /* look for image compression parameters, enclosed in sq. brackets */ ptr3 = strchr(ptr1, '['); if (outfile) { if (ptr2) { /* template file was specified */ if (ptr2 - ptr1 > FLEN_FILENAME - 1) { return(*status = URL_PARSE_ERROR); } strncat(outfile, ptr1, ptr2 - ptr1); } else if (ptr3) { /* compression was specified */ if (ptr3 - ptr1 > FLEN_FILENAME - 1) { return(*status = URL_PARSE_ERROR); } strncat(outfile, ptr1, ptr3 - ptr1); } else { /* no template file or compression */ if (strlen(ptr1) > FLEN_FILENAME - 1) { return(*status = URL_PARSE_ERROR); } strcpy(outfile, ptr1); } } if (ptr2) /* template file was specified */ { ptr2++; ptr1 = strchr(ptr2, ')' ); /* search for closing ) */ if (!ptr1) { return(*status = URL_PARSE_ERROR); /* error, no closing ) */ } if (tpltfile) { if (ptr1 - ptr2 > FLEN_FILENAME - 1) { return(*status = URL_PARSE_ERROR); } strncat(tpltfile, ptr2, ptr1 - ptr2); } } if (ptr3) /* compression was specified */ { ptr3++; ptr1 = strchr(ptr3, ']' ); /* search for closing ] */ if (!ptr1) { return(*status = URL_PARSE_ERROR); /* error, no closing ] */ } if (compspec) { if (ptr1 - ptr3 > FLEN_FILENAME - 1) { return(*status = URL_PARSE_ERROR); } strncat(compspec, ptr3, ptr1 - ptr3); } } /* check if a .gz compressed output file is to be created */ /* by seeing if the filename ends in '.gz' */ if (urltype && outfile) { if (!strcmp(urltype, "file://") ) { ptr1 = strstr(outfile, ".gz"); if (ptr1) { /* make sure the ".gz" is at the end of the file name */ ptr1 += 3; if (*ptr1 == 0 || *ptr1 == ' ' ) strcpy(urltype, "compressoutfile://"); } } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffexts(char *extspec, int *extnum, char *extname, int *extvers, int *hdutype, char *imagecolname, char *rowexpress, int *status) { /* Parse the input extension specification string, returning either the extension number or the values of the EXTNAME, EXTVERS, and XTENSION keywords in desired extension. Also return the name of the column containing an image, and an expression to be used to determine which row to use, if present. */ char *ptr1, *ptr2; int slen, nvals; int notint = 1; /* initially assume specified extname is not an integer */ char tmpname[FLEN_VALUE], *loc; *extnum = 0; *extname = '\0'; *extvers = 0; *hdutype = ANY_HDU; *imagecolname = '\0'; *rowexpress = '\0'; if (*status > 0) return(*status); ptr1 = extspec; /* pointer to first char */ while (*ptr1 == ' ') /* skip over any leading blanks */ ptr1++; if (isdigit((int) *ptr1)) /* is the extension specification a number? */ { notint = 0; /* looks like extname may actually be the ext. number */ errno = 0; /* reset this prior to calling strtol */ *extnum = strtol(ptr1, &loc, 10); /* read the string as an integer */ while (*loc == ' ') /* skip over trailing blanks */ loc++; /* check for read error, or junk following the integer */ if ((*loc != '\0' && *loc != ';' ) || (errno == ERANGE) ) { *extnum = 0; notint = 1; /* no, extname was not a simple integer after all */ errno = 0; /* reset error condition flag if it was set */ } if ( *extnum < 0 || *extnum > 99999) { *extnum = 0; /* this is not a reasonable extension number */ ffpmsg("specified extension number is out of range:"); ffpmsg(extspec); return(*status = URL_PARSE_ERROR); } } /* This logic was too simple, and failed on extnames like '1000TEMP' where it would try to move to the 1000th extension if (isdigit((int) *ptr1)) { sscanf(ptr1, "%d", extnum); if (*extnum < 0 || *extnum > 9999) { *extnum = 0; ffpmsg("specified extension number is out of range:"); ffpmsg(extspec); return(*status = URL_PARSE_ERROR); } } */ if (notint) { /* not a number, so EXTNAME must be specified, followed by */ /* optional EXTVERS and XTENSION values */ /* don't use space char as end indicator, because there */ /* may be imbedded spaces in the EXTNAME value */ slen = strcspn(ptr1, ",:;"); /* length of EXTNAME */ if (slen > FLEN_VALUE - 1) { return(*status = URL_PARSE_ERROR); } strncat(extname, ptr1, slen); /* EXTNAME value */ /* now remove any trailing blanks */ while (slen > 0 && *(extname + slen -1) == ' ') { *(extname + slen -1) = '\0'; slen--; } ptr1 += slen; slen = strspn(ptr1, " ,:"); /* skip delimiter characters */ ptr1 += slen; slen = strcspn(ptr1, " ,:;"); /* length of EXTVERS */ if (slen) { nvals = sscanf(ptr1, "%d", extvers); /* EXTVERS value */ if (nvals != 1) { ffpmsg("illegal EXTVER value in input URL:"); ffpmsg(extspec); return(*status = URL_PARSE_ERROR); } ptr1 += slen; slen = strspn(ptr1, " ,:"); /* skip delimiter characters */ ptr1 += slen; slen = strcspn(ptr1, ";"); /* length of HDUTYPE */ if (slen) { if (*ptr1 == 'b' || *ptr1 == 'B') *hdutype = BINARY_TBL; else if (*ptr1 == 't' || *ptr1 == 'T' || *ptr1 == 'a' || *ptr1 == 'A') *hdutype = ASCII_TBL; else if (*ptr1 == 'i' || *ptr1 == 'I') *hdutype = IMAGE_HDU; else { ffpmsg("unknown type of HDU in input URL:"); ffpmsg(extspec); return(*status = URL_PARSE_ERROR); } } } else { strcpy(tmpname, extname); ffupch(tmpname); if (!strcmp(tmpname, "PRIMARY") || !strcmp(tmpname, "P") ) *extname = '\0'; /* return extnum = 0 */ } } ptr1 = strchr(ptr1, ';'); if (ptr1) { /* an image is to be opened; the image is contained in a single */ /* cell of a binary table. A column name and an expression to */ /* determine which row to use has been entered. */ ptr1++; /* skip over the ';' delimiter */ while (*ptr1 == ' ') /* skip over any leading blanks */ ptr1++; ptr2 = strchr(ptr1, '('); if (!ptr2) { ffpmsg("illegal specification of image in table cell in input URL:"); ffpmsg(" did not find a row expression enclosed in ( )"); ffpmsg(extspec); return(*status = URL_PARSE_ERROR); } if (ptr2 - ptr1 > FLEN_FILENAME - 1) { return(*status = URL_PARSE_ERROR); } strncat(imagecolname, ptr1, ptr2 - ptr1); /* copy column name */ ptr2++; /* skip over the '(' delimiter */ while (*ptr2 == ' ') /* skip over any leading blanks */ ptr2++; ptr1 = strchr(ptr2, ')'); if (!ptr2) { ffpmsg("illegal specification of image in table cell in input URL:"); ffpmsg(" missing closing ')' character in row expression"); ffpmsg(extspec); return(*status = URL_PARSE_ERROR); } if (ptr1 - ptr2 > FLEN_FILENAME - 1) { return(*status = URL_PARSE_ERROR); } strncat(rowexpress, ptr2, ptr1 - ptr2); /* row expression */ } return(*status); } /*--------------------------------------------------------------------------*/ int ffextn(char *url, /* I - input filename/URL */ int *extension_num, /* O - returned extension number */ int *status) { /* Parse the input url string and return the number of the extension that CFITSIO would automatically move to if CFITSIO were to open this input URL. The extension numbers are one's based, so 1 = the primary array, 2 = the first extension, etc. The extension number that gets returned is determined by the following algorithm: 1. If the input URL includes a binning specification (e.g. 'myfile.fits[3][bin X,Y]') then the returned extension number will always = 1, since CFITSIO would create a temporary primary image on the fly in this case. The same is true if an image within a single cell of a binary table is opened. 2. Else if the input URL specifies an extension number (e.g., 'myfile.fits[3]' or 'myfile.fits+3') then the specified extension number (+ 1) is returned. 3. Else if the extension name is specified in brackets (e.g., this 'myfile.fits[EVENTS]') then the file will be opened and searched for the extension number. If the input URL is '-' (reading from the stdin file stream) this is not possible and an error will be returned. 4. Else if the URL does not specify an extension (e.g. 'myfile.fits') then a special extension number = -99 will be returned to signal that no extension was specified. This feature is mainly for compatibility with existing FTOOLS software. CFITSIO would open the primary array by default (extension_num = 1) in this case. */ fitsfile *fptr; char urltype[20]; char infile[FLEN_FILENAME]; char outfile[FLEN_FILENAME]; char extspec[FLEN_FILENAME]; char extname[FLEN_FILENAME]; char rowfilter[FLEN_FILENAME]; char binspec[FLEN_FILENAME]; char colspec[FLEN_FILENAME]; char imagecolname[FLEN_VALUE], rowexpress[FLEN_FILENAME]; char *cptr; int extnum, extvers, hdutype, tstatus = 0; if (*status > 0) return(*status); /* parse the input URL into its basic components */ fits_parse_input_url(url, urltype, infile, outfile, extspec, rowfilter,binspec, colspec, status); if (*status > 0) return(*status); if (*binspec) /* is there a binning specification? */ { *extension_num = 1; /* a temporary primary array image is created */ return(*status); } if (*extspec) /* is an extension specified? */ { ffexts(extspec, &extnum, extname, &extvers, &hdutype, imagecolname, rowexpress, status); if (*status > 0) return(*status); if (*imagecolname) /* is an image within a table cell being opened? */ { *extension_num = 1; /* a temporary primary array image is created */ return(*status); } if (*extname) { /* have to open the file to search for the extension name (curses!) */ if (!strcmp(urltype, "stdin://")) /* opening stdin would destroying it! */ return(*status = URL_PARSE_ERROR); /* First, strip off any filtering specification */ infile[0] = '\0'; strncat(infile, url, FLEN_FILENAME -1); cptr = strchr(infile, ']'); /* locate the closing bracket */ if (!cptr) { return(*status = URL_PARSE_ERROR); } else { cptr++; *cptr = '\0'; /* terminate URl after the extension spec */ } if (ffopen(&fptr, infile, READONLY, status) > 0) /* open the file */ { ffclos(fptr, &tstatus); return(*status); } ffghdn(fptr, &extnum); /* where am I in the file? */ *extension_num = extnum; ffclos(fptr, status); return(*status); } else { *extension_num = extnum + 1; /* return the specified number (+ 1) */ return(*status); } } else { *extension_num = -99; /* no specific extension was specified */ /* defaults to primary array */ return(*status); } } /*--------------------------------------------------------------------------*/ int ffurlt(fitsfile *fptr, char *urlType, int *status) /* return the prefix string associated with the driver in use by the fitsfile pointer fptr */ { strcpy(urlType, driverTable[fptr->Fptr->driver].prefix); return(*status); } /*--------------------------------------------------------------------------*/ int ffimport_file( char *filename, /* Text file to read */ char **contents, /* Pointer to pointer to hold file */ int *status ) /* CFITSIO error code */ /* Read and concatenate all the lines from the given text file. User must free the pointer returned in contents. Pointer is guaranteed to hold 2 characters more than the length of the text... allows the calling routine to append (or prepend) a newline (or quotes?) without reallocating memory. */ { int allocLen, totalLen, llen, eoline = 1; char *lines,line[256]; FILE *aFile; if( *status > 0 ) return( *status ); totalLen = 0; allocLen = 1024; lines = (char *)malloc( allocLen * sizeof(char) ); if( !lines ) { ffpmsg("Couldn't allocate memory to hold ASCII file contents."); return(*status = MEMORY_ALLOCATION ); } lines[0] = '\0'; if( (aFile = fopen( filename, "r" ))==NULL ) { snprintf(line,256,"Could not open ASCII file %s.",filename); ffpmsg(line); free( lines ); return(*status = FILE_NOT_OPENED); } while( fgets(line,256,aFile)!=NULL ) { llen = strlen(line); if ( eoline && (llen > 1) && (line[0] == '/' && line[1] == '/')) continue; /* skip comment lines begging with // */ eoline = 0; /* replace CR and newline chars at end of line with nulls */ if ((llen > 0) && (line[llen-1]=='\n' || line[llen-1] == '\r')) { line[--llen] = '\0'; eoline = 1; /* found an end of line character */ if ((llen > 0) && (line[llen-1]=='\n' || line[llen-1] == '\r')) { line[--llen] = '\0'; } } if( totalLen + llen + 3 >= allocLen ) { allocLen += 256; lines = (char *)realloc(lines, allocLen * sizeof(char) ); if( ! lines ) { ffpmsg("Couldn't allocate memory to hold ASCII file contents."); *status = MEMORY_ALLOCATION; break; } } strcpy( lines+totalLen, line ); totalLen += llen; if (eoline) { strcpy( lines+totalLen, " "); /* add a space between lines */ totalLen += 1; } } fclose(aFile); *contents = lines; return( *status ); } /*--------------------------------------------------------------------------*/ int fits_get_token(char **ptr, char *delimiter, char *token, int *isanumber) /* O - is this token a number? */ /* parse off the next token, delimited by a character in 'delimiter', from the input ptr string; increment *ptr to the end of the token. Returns the length of the token, not including the delimiter char; */ { char *loc, tval[73]; int slen; double dval; *token = '\0'; while (**ptr == ' ') /* skip over leading blanks */ (*ptr)++; slen = strcspn(*ptr, delimiter); /* length of next token */ if (slen) { strncat(token, *ptr, slen); /* copy token */ (*ptr) += slen; /* skip over the token */ if (isanumber) /* check if token is a number */ { *isanumber = 1; if (strchr(token, 'D')) { strncpy(tval, token, 72); tval[72] = '\0'; /* The C language does not support a 'D'; replace with 'E' */ if ((loc = strchr(tval, 'D'))) *loc = 'E'; dval = strtod(tval, &loc); } else { dval = strtod(token, &loc); } /* check for read error, or junk following the value */ if (*loc != '\0' && *loc != ' ' ) *isanumber = 0; if (errno == ERANGE) *isanumber = 0; } } return(slen); } /*--------------------------------------------------------------------------*/ int fits_get_token2(char **ptr, char *delimiter, char **token, int *isanumber, /* O - is this token a number? */ int *status) /* parse off the next token, delimited by a character in 'delimiter', from the input ptr string; increment *ptr to the end of the token. Returns the length of the token, not including the delimiter char; This routine allocates the *token string; the calling routine must free it */ { char *loc, tval[73]; int slen; double dval; if (*status) return(0); while (**ptr == ' ') /* skip over leading blanks */ (*ptr)++; slen = strcspn(*ptr, delimiter); /* length of next token */ if (slen) { *token = (char *) calloc(slen + 1, 1); if (!(*token)) { ffpmsg("Couldn't allocate memory to hold token string (fits_get_token2)."); *status = MEMORY_ALLOCATION ; return(0); } strncat(*token, *ptr, slen); /* copy token */ (*ptr) += slen; /* skip over the token */ if (isanumber) /* check if token is a number */ { *isanumber = 1; if (strchr(*token, 'D')) { strncpy(tval, *token, 72); tval[72] = '\0'; /* The C language does not support a 'D'; replace with 'E' */ if ((loc = strchr(tval, 'D'))) *loc = 'E'; dval = strtod(tval, &loc); } else { dval = strtod(*token, &loc); } /* check for read error, or junk following the value */ if (*loc != '\0' && *loc != ' ' ) *isanumber = 0; if (errno == ERANGE) *isanumber = 0; } } return(slen); } /*---------------------------------------------------------------------------*/ char *fits_split_names( char *list) /* I - input list of names */ { /* A sequence of calls to fits_split_names will split the input string into name tokens. The string typically contains a list of file or column names. The names must be delimited by a comma and/or spaces. This routine ignores spaces and commas that occur within parentheses, brackets, or curly brackets. It also strips any leading and trailing blanks from the returned name. This routine is similar to the ANSI C 'strtok' function: The first call to fits_split_names has a non-null input string. It finds the first name in the string and terminates it by overwriting the next character of the string with a '\0' and returns a pointer to the name. Each subsequent call, indicated by a NULL value of the input string, returns the next name, searching from just past the end of the previous name. It returns NULL when no further names are found. The following line illustrates how a string would be split into 3 names: myfile[1][bin (x,y)=4], file2.fits file3.fits ^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^ 1st name 2nd name 3rd name NOTE: This routine is not thread-safe. This routine is simply provided as a utility routine for other external software. It is not used by any CFITSIO routine. */ int depth = 0; char *start; static char *ptr; if (list) /* reset ptr if a string is given */ ptr = list; while (*ptr == ' ')ptr++; /* skip leading white space */ if (*ptr == '\0')return(0); /* no remaining file names */ start = ptr; while (*ptr != '\0') { if ((*ptr == '[') || (*ptr == '(') || (*ptr == '{')) depth ++; else if ((*ptr == '}') || (*ptr == ')') || (*ptr == ']')) depth --; else if ((depth == 0) && (*ptr == ',' || *ptr == ' ')) { *ptr = '\0'; /* terminate the filename here */ ptr++; /* save pointer to start of next filename */ break; } ptr++; } return(start); } /*--------------------------------------------------------------------------*/ int urltype2driver(char *urltype, int *driver) /* compare input URL with list of known drivers, returning the matching driver numberL. */ { int ii; /* find matching driver; search most recent drivers first */ for (ii=no_of_drivers - 1; ii >= 0; ii--) { if (0 == strcmp(driverTable[ii].prefix, urltype)) { *driver = ii; return(0); } } return(NO_MATCHING_DRIVER); } /*--------------------------------------------------------------------------*/ int ffclos(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ /* close the FITS file by completing the current HDU, flushing it to disk, then calling the system dependent routine to physically close the FITS file */ { int tstatus = NO_CLOSE_ERROR, zerostatus = 0; if (!fptr) return(*status = NULL_INPUT_PTR); else if ((fptr->Fptr)->validcode != VALIDSTRUC) /* check for magic value */ return(*status = BAD_FILEPTR); /* close and flush the current HDU */ if (*status > 0) ffchdu(fptr, &tstatus); /* turn off the error message from ffchdu */ else ffchdu(fptr, status); ((fptr->Fptr)->open_count)--; /* decrement usage counter */ if ((fptr->Fptr)->open_count == 0) /* if no other files use structure */ { ffflsh(fptr, TRUE, status); /* flush and disassociate IO buffers */ /* call driver function to actually close the file */ if ((*driverTable[(fptr->Fptr)->driver].close)((fptr->Fptr)->filehandle)) { if (*status <= 0) { *status = FILE_NOT_CLOSED; /* report if no previous error */ ffpmsg("failed to close the following file: (ffclos)"); ffpmsg((fptr->Fptr)->filename); } } fits_clear_Fptr( fptr->Fptr, status); /* clear Fptr address */ free((fptr->Fptr)->iobuffer); /* free memory for I/O buffers */ free((fptr->Fptr)->headstart); /* free memory for headstart array */ free((fptr->Fptr)->filename); /* free memory for the filename */ (fptr->Fptr)->filename = 0; (fptr->Fptr)->validcode = 0; /* magic value to indicate invalid fptr */ free(fptr->Fptr); /* free memory for the FITS file structure */ free(fptr); /* free memory for the FITS file structure */ } else { /* to minimize the fallout from any previous error (e.g., trying to open a non-existent extension in a already opened file), always call ffflsh with status = 0. */ /* just flush the buffers, don't disassociate them */ if (*status > 0) ffflsh(fptr, FALSE, &zerostatus); else ffflsh(fptr, FALSE, status); free(fptr); /* free memory for the FITS file structure */ } return(*status); } /*--------------------------------------------------------------------------*/ int ffdelt(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ /* close and DELETE the FITS file. */ { char *basename; int slen, tstatus = NO_CLOSE_ERROR, zerostatus = 0; if (!fptr) return(*status = NULL_INPUT_PTR); else if ((fptr->Fptr)->validcode != VALIDSTRUC) /* check for magic value */ return(*status = BAD_FILEPTR); if (*status > 0) ffchdu(fptr, &tstatus); /* turn off the error message from ffchdu */ else ffchdu(fptr, status); ffflsh(fptr, TRUE, status); /* flush and disassociate IO buffers */ /* call driver function to actually close the file */ if ( (*driverTable[(fptr->Fptr)->driver].close)((fptr->Fptr)->filehandle) ) { if (*status <= 0) { *status = FILE_NOT_CLOSED; /* report error if no previous error */ ffpmsg("failed to close the following file: (ffdelt)"); ffpmsg((fptr->Fptr)->filename); } } /* call driver function to actually delete the file */ if ( (driverTable[(fptr->Fptr)->driver].remove) ) { /* parse the input URL to get the base filename */ slen = strlen((fptr->Fptr)->filename); basename = (char *) malloc(slen +1); if (!basename) return(*status = MEMORY_ALLOCATION); fits_parse_input_url((fptr->Fptr)->filename, NULL, basename, NULL, NULL, NULL, NULL, NULL, &zerostatus); if ((*driverTable[(fptr->Fptr)->driver].remove)(basename)) { ffpmsg("failed to delete the following file: (ffdelt)"); ffpmsg((fptr->Fptr)->filename); if (!(*status)) *status = FILE_NOT_CLOSED; } free(basename); } fits_clear_Fptr( fptr->Fptr, status); /* clear Fptr address */ free((fptr->Fptr)->iobuffer); /* free memory for I/O buffers */ free((fptr->Fptr)->headstart); /* free memory for headstart array */ free((fptr->Fptr)->filename); /* free memory for the filename */ (fptr->Fptr)->filename = 0; (fptr->Fptr)->validcode = 0; /* magic value to indicate invalid fptr */ free(fptr->Fptr); /* free memory for the FITS file structure */ free(fptr); /* free memory for the FITS file structure */ return(*status); } /*--------------------------------------------------------------------------*/ int fftrun( fitsfile *fptr, /* I - FITS file pointer */ LONGLONG filesize, /* I - size to truncate the file */ int *status) /* O - error status */ /* low level routine to truncate a file to a new smaller size. */ { if (driverTable[(fptr->Fptr)->driver].truncate) { ffflsh(fptr, FALSE, status); /* flush all the buffers first */ (fptr->Fptr)->filesize = filesize; (fptr->Fptr)->io_pos = filesize; (fptr->Fptr)->logfilesize = filesize; (fptr->Fptr)->bytepos = filesize; ffbfeof(fptr, status); /* eliminate any buffers beyond current EOF */ return (*status = (*driverTable[(fptr->Fptr)->driver].truncate)((fptr->Fptr)->filehandle, filesize) ); } else return(*status); } /*--------------------------------------------------------------------------*/ int ffflushx( FITSfile *fptr) /* I - FITS file pointer */ /* low level routine to flush internal file buffers to the file. */ { if (driverTable[fptr->driver].flush) return ( (*driverTable[fptr->driver].flush)(fptr->filehandle) ); else return(0); /* no flush function defined for this driver */ } /*--------------------------------------------------------------------------*/ int ffseek( FITSfile *fptr, /* I - FITS file pointer */ LONGLONG position) /* I - byte position to seek to */ /* low level routine to seek to a position in a file. */ { return( (*driverTable[fptr->driver].seek)(fptr->filehandle, position) ); } /*--------------------------------------------------------------------------*/ int ffwrite( FITSfile *fptr, /* I - FITS file pointer */ long nbytes, /* I - number of bytes to write */ void *buffer, /* I - buffer to write */ int *status) /* O - error status */ /* low level routine to write bytes to a file. */ { if ( (*driverTable[fptr->driver].write)(fptr->filehandle, buffer, nbytes) ) { ffpmsg("Error writing data buffer to file:"); ffpmsg(fptr->filename); *status = WRITE_ERROR; } return(*status); } /*--------------------------------------------------------------------------*/ int ffread( FITSfile *fptr, /* I - FITS file pointer */ long nbytes, /* I - number of bytes to read */ void *buffer, /* O - buffer to read into */ int *status) /* O - error status */ /* low level routine to read bytes from a file. */ { int readstatus; readstatus = (*driverTable[fptr->driver].read)(fptr->filehandle, buffer, nbytes); if (readstatus == END_OF_FILE) *status = END_OF_FILE; else if (readstatus > 0) { ffpmsg("Error reading data buffer from file:"); ffpmsg(fptr->filename); *status = READ_ERROR; } return(*status); } /*--------------------------------------------------------------------------*/ int fftplt(fitsfile **fptr, /* O - FITS file pointer */ const char *filename, /* I - name of file to create */ const char *tempname, /* I - name of template file */ int *status) /* IO - error status */ /* Create and initialize a new FITS file based on a template file. Uses C fopen and fgets functions. */ { *fptr = 0; /* initialize null file pointer, */ /* regardless of the value of *status */ if (*status > 0) return(*status); if ( ffinit(fptr, filename, status) ) /* create empty file */ return(*status); ffoptplt(*fptr, tempname, status); /* open and use template */ return(*status); } /*--------------------------------------------------------------------------*/ int ffoptplt(fitsfile *fptr, /* O - FITS file pointer */ const char *tempname, /* I - name of template file */ int *status) /* IO - error status */ /* open template file and use it to create new file */ { fitsfile *tptr; int tstatus = 0, nkeys, nadd, ii; char card[FLEN_CARD]; if (*status > 0) return(*status); if (tempname == NULL || *tempname == '\0') /* no template file? */ return(*status); /* try opening template */ ffopen(&tptr, (char *) tempname, READONLY, &tstatus); if (tstatus) /* not a FITS file, so treat it as an ASCII template */ { ffxmsg(2, card); /* clear the error message */ fits_execute_template(fptr, (char *) tempname, status); ffmahd(fptr, 1, 0, status); /* move back to the primary array */ return(*status); } else /* template is a valid FITS file */ { ffmahd(tptr, 1, NULL, status); /* make sure we are at the beginning */ while (*status <= 0) { ffghsp(tptr, &nkeys, &nadd, status); /* get no. of keywords */ for (ii = 1; ii <= nkeys; ii++) /* copy keywords */ { ffgrec(tptr, ii, card, status); /* must reset the PCOUNT keyword to zero in the new output file */ if (strncmp(card, "PCOUNT ",8) == 0) { /* the PCOUNT keyword? */ if (strncmp(card+25, " 0", 5)) { /* non-zero value? */ strncpy(card, "PCOUNT = 0", 30); } } ffprec(fptr, card, status); } ffmrhd(tptr, 1, 0, status); /* move to next HDU until error */ ffcrhd(fptr, status); /* create empty new HDU in output file */ } if (*status == END_OF_FILE) { *status = 0; /* expected error condition */ } ffclos(tptr, status); /* close the template file */ } ffmahd(fptr, 1, 0, status); /* move to the primary array */ return(*status); } /*--------------------------------------------------------------------------*/ void ffrprt( FILE *stream, int status) /* Print out report of cfitsio error status and messages on the error stack. Uses C FILE stream. */ { char status_str[FLEN_STATUS], errmsg[FLEN_ERRMSG]; if (status) { fits_get_errstatus(status, status_str); /* get the error description */ fprintf(stream, "\nFITSIO status = %d: %s\n", status, status_str); while ( fits_read_errmsg(errmsg) ) /* get error stack messages */ fprintf(stream, "%s\n", errmsg); } return; } /*--------------------------------------------------------------------------*/ int pixel_filter_helper( fitsfile **fptr, /* IO - pointer to input image; on output it */ /* points to the new image */ char *outfile, /* I - name for output file */ char *expr, /* I - Image filter expression */ int *status) { PixelFilter filter = { 0 }; char * DEFAULT_TAG = "X"; int ii, hdunum; int singleHDU = 0; filter.count = 1; filter.ifptr = fptr; filter.tag = &DEFAULT_TAG; /* create new empty file for result */ if (ffinit(&filter.ofptr, outfile, status) > 0) { ffpmsg("failed to create output file for pixel filter:"); ffpmsg(outfile); return(*status); } fits_get_hdu_num(*fptr, &hdunum); /* current HDU number in input file */ expr += 3; /* skip 'pix' */ switch (expr[0]) { case 'b': case 'B': filter.bitpix = BYTE_IMG; break; case 'i': case 'I': filter.bitpix = SHORT_IMG; break; case 'j': case 'J': filter.bitpix = LONG_IMG; break; case 'r': case 'R': filter.bitpix = FLOAT_IMG; break; case 'd': case 'D': filter.bitpix = DOUBLE_IMG; break; } if (filter.bitpix) /* skip bitpix indicator */ ++expr; if (*expr == '1') { ++expr; singleHDU = 1; } if (((*fptr)->Fptr)->only_one) singleHDU = 1; if (*expr != ' ') { ffpmsg("pixel filtering expression not space separated:"); ffpmsg(expr); } while (*expr == ' ') ++expr; /* copy all preceding extensions to the output file */ for (ii = 1; !singleHDU && ii < hdunum; ii++) { fits_movabs_hdu(*fptr, ii, NULL, status); if (fits_copy_hdu(*fptr, filter.ofptr, 0, status) > 0) { ffclos(filter.ofptr, status); return(*status); } } /* move back to the original HDU position */ fits_movabs_hdu(*fptr, hdunum, NULL, status); filter.expression = expr; if (fits_pixel_filter(&filter, status)) { ffpmsg("failed to execute image filter:"); ffpmsg(expr); ffclos(filter.ofptr, status); return(*status); } /* copy any remaining HDUs to the output file */ for (ii = hdunum + 1; !singleHDU; ii++) { if (fits_movabs_hdu(*fptr, ii, NULL, status) > 0) break; fits_copy_hdu(*fptr, filter.ofptr, 0, status); } if (*status == END_OF_FILE) *status = 0; /* got the expected EOF error; reset = 0 */ else if (*status > 0) { ffclos(filter.ofptr, status); return(*status); } /* close the original file and return ptr to the new image */ ffclos(*fptr, status); *fptr = filter.ofptr; /* reset the pointer to the new table */ /* move back to the image subsection */ if (ii - 1 != hdunum) fits_movabs_hdu(*fptr, hdunum, NULL, status); return(*status); } /*-------------------------------------------------------------------*/ int ffihtps() { /* Wrapper function for global initialization of curl library. This is NOT THREAD-SAFE */ int status=0; #ifdef CFITSIO_HAVE_CURL if (curl_global_init(CURL_GLOBAL_ALL)) /* Do we want to define a new CFITSIO error code for this? */ status = -1; #endif return status; } /*-------------------------------------------------------------------*/ int ffchtps() { /* Wrapper function for global cleanup of curl library. This is NOT THREAD-SAFE */ #ifdef CFITSIO_HAVE_CURL curl_global_cleanup(); #endif return 0; } /*-------------------------------------------------------------------*/ void ffvhtps(int flag) { /* Turn libcurl's verbose output on (1) or off (0). This is NOT THREAD-SAFE */ #ifdef HAVE_NET_SERVICES https_set_verbose(flag); #endif } cfitsio/cfitsio.pc.in0000644000225700000360000000040113246025103014364 0ustar cagordonlheaprefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: cfitsio Description: FITS File Subroutine Library Version: @CFITSIO_MAJOR@.@CFITSIO_MINOR@ Libs: -L${libdir} -lcfitsio @LIBS@ Libs.private: -lm Cflags: -I${includedir} cfitsio/cfitsio.xcodeproj/0000755000225700000360000000000013246025103015434 5ustar cagordonlheacfitsio/cfitsio.xcodeproj/project.pbxproj0000644000225700000360000000624113246025103020513 0ustar cagordonlhea// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXAggregateTarget section */ 462A28570A4EF04900AB8766 /* CFITSIO */ = { isa = PBXAggregateTarget; buildConfigurationList = 462A285C0A4EF05400AB8766 /* Build configuration list for PBXAggregateTarget "CFITSIO" */; buildPhases = ( 462A28580A4EF05100AB8766 /* ShellScript */, ); dependencies = ( ); name = CFITSIO; productName = "Build Universal"; }; /* End PBXAggregateTarget section */ /* Begin PBXGroup section */ 22831BBD1146D2B6004A1DD3 /* Products */ = { isa = PBXGroup; children = ( ); name = Products; sourceTree = ""; }; 462A28340A4EEE3200AB8766 = { isa = PBXGroup; children = ( 22831BBD1146D2B6004A1DD3 /* Products */, ); sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXProject section */ 462A28360A4EEE3200AB8766 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0630; }; buildConfigurationList = 462A28370A4EEE3200AB8766 /* Build configuration list for PBXProject "cfitsio" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = 462A28340A4EEE3200AB8766; productRefGroup = 22831BBD1146D2B6004A1DD3 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 462A28570A4EF04900AB8766 /* CFITSIO */, ); }; /* End PBXProject section */ /* Begin PBXShellScriptBuildPhase section */ 462A28580A4EF05100AB8766 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "# shell script goes here\nmake distclean\n./configure\nmake shared\nmake testprog\nmake fpack\nmake funpack\nmake fitscopy\nexit 0"; }; /* End PBXShellScriptBuildPhase section */ /* Begin XCBuildConfiguration section */ 462A28390A4EEE3200AB8766 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = YES; }; name = Release; }; 462A285E0A4EF05400AB8766 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = YES; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; PRODUCT_NAME = CFITSIO; ZERO_LINK = NO; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 462A28370A4EEE3200AB8766 /* Build configuration list for PBXProject "cfitsio" */ = { isa = XCConfigurationList; buildConfigurations = ( 462A28390A4EEE3200AB8766 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 462A285C0A4EF05400AB8766 /* Build configuration list for PBXAggregateTarget "CFITSIO" */ = { isa = XCConfigurationList; buildConfigurations = ( 462A285E0A4EF05400AB8766 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 462A28360A4EEE3200AB8766 /* Project object */; } cfitsio/cfitsio_mac.sit.hqx0000644000225700000360000005550613246025103015613 0ustar cagordonlhea(This file must be converted with BinHex 4.0) :$f0QDA4cD@pIE@&M,R0TG!"6594%8dP8)3#3"%11!*!%4HY6593K!!%!!%11FNa KG3*6!*!$&ZlZ)#!,BfCTG(0TEepYB@-!N"AR#BB"&J!9!U)"eJ#3!`-!N!q'!!! $([q3"!2JYCR`K,@Cp[N!N!8"mK%!N!C$#2r`rrJ!!-0!!!"0Y`!0$N0'DA4cD@p 38%-ZE@0`!*!4Da3*KJ#3$aB!!$i$!*!$&[q3"%e08(*$9dP&!3#[H%fHYCRfmJ# 3"3(U0!#3"Md0!!"9XJ#3"[8H"[LUJEpCRC+&h2,Qp5XR2!PhHq4S2H%,ApKQqmJ LNkpp8AlddNfr[1A)MP#1Tai![I"-haEmadlZiRN5eLh2&pPQYb@hMpc#pMQahU[ MjF@A)`YEb',mbF)EN!#&l)[`r)9RmFZHm#-lbAEK#qr)l6MKLpjbR($&#Ur-Vr0 fK0r#Ma`RA-)l22Q&,13AFTY-&L1cK5jN"9K($6SEG(C1mZ4R0R4JEhDp%a[NjC! $GhCHIV6,b@DM((4ffHR#LbqH!ph[phRj4[C&&ShX)r[YiRdmbHkebmMq[(KN$cV cFa#2l)[X86b,,-plB#b!Vl2VCAikk,fqbH,(bq[*l53meJ,!&[`"jhIkI5f1'd% 3,!Q#dUUJp-!lJY+$p5"BH5ma(bKeP6LDVcDZZdeKNN4a8UiQm9CAbqCLA5QIqP[ XPi0Jl8H#i"hHrpUqXi,J3lqkj2T6Yh"H2r[XNdTd(rB03A$L`5"Bk[dc2RMIZPh "b@rE'34[ackdki2h"FF(`H@c#NqI)P4GS[!F,Pp*9ei&5TqF6!e5'Z+9D"fM`h3 SKb"@J#a`!MD',FIf`[E'9Q$lB2YLqf(lBdr#RS`GJ$d&1a!l&(XDGKKf1,B5HcV f$1`)l*RBNGLcX'GMcm'HKld!Hb&f0$D-(B3GV&F8@iSYXeH9XJm!'S'I``l"RSX p(cX+1aCEK4f((@pf`QYP)SqYmP[j5"8[%qfa(pAKIHX%hY3A6jljZ2T8+l$Y9P+ 9ZSABJ5Ud2KH'fm*+)da6PhC[$C1M&eJq8#d2EIU0kPcTFK1[N!#9EL'@!Z3P+,c -9icR6L[c8`j9I`iR[I25%D#SDkA4H$YaNp&-Gc1XG32c$IHfjC@#kiCLM)K%k9U d0C!!+Y"B$PJ09iKRp+T'ImNm&#%J!p"afpL5RV[@,,R`mrF[ZH#ElqrD[qq5V[h AhHR6KErIYIm6PcaA6"*I""A*,da(Ij9Gqfr-+elX!'`CYKcE#pX2#j!!mKDmMrF f[!P[`aGVCh(5hqLkFX8[lETZ[FY'fki@68BZ'4rrPF(qU1%Ur52RpBmU,(M&e-r [ZMjp9qrk4M`40Y,amE22fMMRMCjalUk29a)ACUirLCZM'DkYiq-#6)e-2)$BNji $[H19,-l5)CG-ZI*`jkGdGbVIp'Te-(q&F1rJqXfekDJZ"VeXY&TjXIkPJR"+B'p X,f`j0LE!&GXAfcq[XZ"cN!$HrL9`cYkY)A1@E%VP'l5+hlRcbk0[mTDf2KX`YaX e[DrL-$5@ED`1G2ZkcR%$Fa@`J+rA8&Ll`)9ePk4(B5"I%%P5e4$j5bD8ZL99"C' %"%)')C`36FJTK2"&@%JPj,)HqlYBb1JU,136iJN"K@"#6L'VI1!b4*@kJP$@BGG L4Gh4a",#Z4rl8L`BHMX@BVS-#r0EJEd4Za,lHpJef*Z`P0R0f&Z`eGL*@0jl&aD -K&[`XMABGGK*f-RBLl$)*TGJT`JBa8l$6XI1`0CLRiqGLGf"[3%,JGq$I3N@rVF HHkYa$AMM[GJAB+r&3Z`KlK"pb2NXib@3!(k)1%)!K2[P15X)"&GM)IQ)!4"pq!T #!&`#-@!$&R5![%2Qlm4HJpf%I4lfaGM0@05cV9J)r6EXE1`Fl+ABZGKjf-Z`ml% ,X*GM&f,"JLZ`,m3ZaYiPU$4)UGRfhGJP@0',!Vq$[4Ul&,YDF#,f+Zc[B+r%hS0 YCr+j6bUTE-2`KTkK[Zkqc5UCjSmUeDA%`6[rejF4)l,TiR`brVA3*Hm,%a+b-,* 3m2Vmm)Grm!5eR`CPMk%khMkK4`-Vr9'@4R'j@Uf8aebD5H$HN!#%3R@q1)AA(!- ,*PeY!S[6i&1kHG`*(+DSEhGqHe)rN3YqQb2j1!RK3Fcr%)dV5eHAPR@*'(UI%,* )f"hrVb$680&UjfB4V1HqC*df[aL&i!5iCF2hhkV$Xr!4rp,Nc`R6Uq!!q&D2TeQ B,2,38L0LY!''CqYC[k2Ei6&eaif6jJX[#J$6`Cm+2mfIND*raNQlmN!cYD6qDhR iehPEAiE`T##&'[YlPQU9DGfVFiN+aG3d"p9Cr"U,Il(jejT5GAfZ@k+UQ[MRfAQ c2FC,l,`Pec"4*3dBEV-mfqdq1r+cj1VIXf&dS&`T9q*@'MGFZEpRl,pCY8HMYE" hS,I"43%j5H+E+PXTX"5C[L@5"*hjT*ck(p+-T'pPA6eAME"lC``ZA"'DN9&,k4l 3V35k$q"r4B!'5-[V2ffqh+G,[2'9A[C+-mQ4Hce6diRfMY3c"p(TcH-lB&51Ndq [$2IfR9iq[EGRV)IMSS(+Q"TA(#UI-kB[e`fL%R@hP1SR6VjaNXdRhjpH,Bp,dX- 85VFXPH*+Ve+iDrm(e&0&Ve"NH8pG[9G[aNDV88Xp2hqKFUUVaZSTqNGXbG"!4Xq 8bTZ'GimiHUU8),CXb,ASJe,U*bV2S1[LSrHS&biT)+AqS0jakVLrZJPI4G4Sb2F KI(e'Ym6dEDP[iqYl396Ar5"4rBELEIL#kKRV6eqQj!ZUEqNNA2)f3I8iREc$9HK &#UVhD8!MdYX%2iA[&-[h-AbRCT8ahLri(A`$XmE&p*Q&T$F-LPS9hLDN(V6"PDa ",eG)Z[q3!%E()H'(e&meY,&XP$Z&e&pfQ[Lcq2i3hl$H*#3qp(Pm`mH5N!#qYG" Am9@Z)&"m2m3RI@k)kQ(eJCh4UMYU+kbqY4'4VK%i6Ve5CrSqeV#8FGk"12VGk!r $pa!(5f(#AqC!2adqDY(fiN@NcG"I4`Pc2VpVrar!jb2U@EXJ1+&1r868mdCr(MR S4k1h$YmIF"MYm5$bjrM'H$b)2)"[V-H$b02iUM`H409R0XlM395pGH-p(N69qcA "id&8Me[Ym5#UrVf*(JqLYq#VmAJ3r5+q54i2SUV,b4i2BY+4,[*i%"0ZAHca)#E "i"+2"c(edNhap4h6@dleH"$6@dlcH"#l(Crdl9&rXDrMQf(jrN8BD2#J4$ed-cd HP+JAF*E(Ja,9j@b2"bAUmC[MmD"%IAQAHM`S89h1pAK3mL9mmc`HP$b+lc+2"k8 5$HCl2#K92b5pGG,69kSq3hVXj+e,e50*Vaep[26@JFY5ck9-Cp#pGb+2P0l"'5b @[X(5KcR6FbFpJDA2F1DY"&r+K$(df8Q2AjNN#RV[D)AQE[4,#T%S8lI3e4Hj5kR 4-Y@Pp!U'`BNbeHAbJ@DEZLN6hUqSELU$ifArJ1rDLi,cHEpb[HA+4PY[@*lhGPD [8FYJZIM%kNEj21URA2fAer@A"lKRZCT**#re9hiG[M8HrmVr'YpDMhrPUX[Vam+ %ZLNAaXM!MNTk+hZT6h$pU-Y)dNYeZD'-8hc8aNBh'X*EHUQ2%8iL$6Qpe)F)&i" Z[)8$[!2I"cR3qiM[#3kf@kUh-'EEijG)[ZNYE"A9X6Fb@1qmVr06Tk9I`3FhZQ& UEINqI25GlR`m&i&k#f0f5C38hr[`lHETjEkpralI(QT,F+Zh4QcFL'STp95KZVa THQd2H&#KZYbl*48Z93J,ETDL+6lHlKDAPDRV#YAPmrhp+X4ME[AhUp#dNaHdfa( [A[(2q&iS495S%lfKYjhILAMR2Z*aq`+5L`pFS2F5HJ@hi!haJ@(dkq*l0`GkGI( "AH"Sq,l,!Ei$(D-h&@k)MjjFqPcaJ5P`,RcdfG)ELZr9(+K(I1!@ICriU(AH&Kr FL$jKB)aq9[J12VJ42Dri`$,H#Kq#*Afdq(kI!p0,m,fI`rhQq`+(9jM[D3k[p,l qkUGpPIRJ%16(4mm`Ei@2IPfCQ+*pVqG!MH0$#RfYq6l2!4c$pkmFb!-9T5rh!I2 "Ym"Y69(PS&[6a8H0[G&m$h*iNrR!@VJN[Up`J"FE1!m%0jZ2AQ[i1$kDcmL2Mcj TX!iIp3b'ib2[@mhh%3j[-aqm"$b"*S0rEcFII2%GjU-Iq*hQJr[#FI"4jqmb(hF $0r"pQ!1F%4riqV$hR5)qqKlc`6RIDcl`'mc%4rr`RjL2HRl%I0bCZXEhF3l`1(` #[`(K#45(RZX2Q)qHG$J&2[UBVAapUM$ecmd(VX%&m&&,F(Cme"rk!ckd"pj6[S' 5T)R&"pHKM["4hr"@I1!([!mI[%dQlfJIZ)$QJ)qhi`haJAr`GhcJabHmEj!!qVi rD6l`$jc("liqEMjkh)@(D"pi*ra%qkM$6jX2[Jk'ii0,`8IN'b`"L9Kmp,6rMIR SdIjEmr&qi"Xqm)Lh`NHGJ+[ii)*Ip,iK`Sm[Q3m0!Nk+$rjNCh)-%Ik"DILS[kq D$hcL,[LS5HS1hcFiJ#(b$C@fK#D!$r`!Zr$4RdiHI25pIp0mF",d%(aJ)PL"MjV mP[QHj2"YlcY0'XChc%G0`hI``5HrCcii#6`,(aJRlGRDalYc&rQ'5926ij6%"ip mbRa`EMJ12ZB4r,2ji#(8*Mk`$#d#(l8"*XJhA'm2VmG(EF&Pm-(RIQ3qCK[)j#E YJdZBKS2!,i06RZ3hR$VaY-&+HR)BCD0pdVR!U!cY%rk[V(HP%TkZE,j&*4LJV21 m%La6[PFR8+BfY1iRhqQ3!"5PZ32iC,k#XZ&"Ti-V5[L-6rLRm[e$J90d*p-E&$K &8kUBJB#21m%aj6Z$'+8q&(`bld'*fq)6,UM8RB42hPjTlJ3qiA)U*d[L%kaAiT, i"&18Y"hj4R"rTEN(q%6c8MD$B!6m@`N(m%R6K4)1ia0m9H+-q)5V+"0J4i#$5V- Em%QY+XePN!$[61+91#!qi@G+I!fID"h+jPbF#6iTm3Km`Tq8G#eme"ED*Ml"%@A khdMH9jRq0e,eD[@rNHKH-J(0q!5cPI!"Rf#U-[e[*&a#L42K%ka4QVdKheR5)Uh qGaEDJM,plbcTY,U[4Ac#GC8d"(c#Se6HkL)q`@@Pq4[bRDekdYd[iT2l+'N#q%5 I8MB)kQc9+0SJ2Z($5[-hm)&2k$Ri")Z9jQl)G`ieVc4r!jr-he$5ar#*0UE`Dap B`P`1I033A!DIm#*Pc86RJ*8UEp!@D96U5QPZ"ci4UT4`(KmD0CS92Z(j5T`&Rr! pC6hIjm)IP'CNb(FH'+5N1H160e,Lb2L%IfZY'jr`HbAZL8riZC)`KSpDK,2J%`k JT2R)GciiSU6riC2l+r%&I05LkB31R)NHSD6ri411UU6ri42HSU6rbAH"-"KHJ%p U3%Nc`3IfS2rK%ae(L8[L%be!5DI&*aa5D9B)2[#-H4hbA3Jf+Fe9`3G1S,AL%`e 'LI2L%ae%5EI%*aa4L8[L!hIYh+C4F!1PH5li`(+d3Aab0bAY!Kpe3lm"2Y%[P$J M2Z'd5[UEI+-e$3JY!TpJNl*T1+1&$I!eI+*Y+G2r4ZXH9[mE$3G@T[q0d6fXrMG '2!$p%"mD-9S%2UN6C3eBBlL2N[D,$fjN1pI(L"m`4`DID!R+QN2'S%FScB("ar[ "fI%*MeALJ2L%[bPV[KX,$e(LFIJ%aj8d0(b#IFSDmmH#"8VD&$jk)Y#kmFPE+-e N`5HkQa*ra`GqfbEqX@J$b[5rX@J0b[5rXA"eCIVI@''`eIr'`L&eMiCm9A!YCIT I&Ca%QIjA*IbcqPq9"K0BrDq+qP5Qre@T&Uhq9i@ZSdcrUd,E8UEr9D'c+02rUX4 6VIih6K1BV2ih$JkM62mETlYDr@mFpDa-raY(,QAkhcLpYpAraSN6@2e[($aFQIi h(XkQ62mE,jjKpEra`L5VrifRaT6TIq24pC6TIq24UT6TIq24!*6TIq09deErQb# 1CI@r#F*1Urp08(eBr@q#kX2UIa1)9kEr64"rYIVI"(36CITIYDCH@[f['JkT62q VKQmSdrqUK3G@rkY@69MpVaTG6jRq9bd-X2TIY6LheImQ`Vf9kAm6iA[+p,q*F!p PqYp%m@1Vrde869[pEb*kRc,pEk,iK0Ar*UVQV2jA)kjMpEmDiBI9rfVJ)FVd[aV a4D[reBMh@2f[4M9YpEmD0#aPqPm01SXbr@q5F06UIj2%JDcq0dPFfHTrNm"LCIV I*1'heImQkAj@rjXNc,$khb6d(@Akhf6a2k[r6BDl+Y2r*N[RX2VIC$#DbCY1Q3r PUGI)m,#a8r0&eSpX0(SE@2U'3ph*@k+**%a%KDVl"`Elb$c1cZ2Y2-(1ARb0R6I Cq@)lAf,R+ADHDZGTGTjZjaPfVVAc6$[2X[0X1mqamk9fRQ[RHADqc-lclEc!cTI EHD'G&pQjbXjAf(Q*RCIDq8SlAfARCADqfXlAf(QjR9IBq9SlVl6c+MZ[Y[0eGUk cmaSlVlAcHMY[X20'R4QRD2eEl,c9cY[X[(fKRS1[ca[ejqI&[%PGB)%ZZdBr1rG I5+G1BX"G+P[)XT6EZCHGbaDbPLe9`a@6MlL#66"J)8(jm[PHGbm&F`R9mMIP+G6 199HAPTr8cMVT@ppq8Y6+bT16mQpH03NBV@I5Bq8CNqdX16B3XA9FTSpccS'T%Dd 6a6TlfeeId-ZiA,F#p%CIKPll'2SfFYB3,HI`iJ#3!-`NXe%!81m40qN5ekU4Bcd c8mf`B!e[$H-fRA!IC'YVU"C)YdX4Y03&l6V*83$Z@a"ea3aSG0B-SN-(%cXH1`& EMDh"EX*HM,d%1`A,hJ(6X01a-l#ef*PBV@1*RB1p&$XA1`pl'ABqGJ(fFZa#l#* X&IB+l",X8Zb9f+Z`bl"ABkr",XHZ`&k,ABPGK9f0[3jEKef$ABYGMpf!hBMG)U! AZ`flAB43E"!E`SDa6F``*bPZAcaQVT!!#f(B[NrMM8l@TEAGAJP@lE`m1'lANU" mmEU6ejkQMR$h,Iph+Fb86idDE*i)l`JB3"QDfphM1@``eKN`"GY&mECQP3(DCC& 5D)qPlCDf@YTMDBZP(CD''0TZDBHPcC!!pN,D#QQ*T4@@&PKDAfPjTG@9&PGD@fP TTC@9'U$eN!#@3eS0D6'N$C2f5pSZDEHNMC-f6GSYDE1N[C)f6pSiDDpNE!MM3KJ 63SXPVC@d90*+53XPVC1d60)U5BXNVC'dJc*+K"%LM!jKC!JYXE6#dJ*,kbXYYE6 -d[T+bbZYVV6FdP*,UbXYN!#d2Y,b5,XVEDkdYp,@5MXVEDbdVp+f5VXUEDUdjY) @56XNEC!!M$pTfN(&@aQ#m3@-,@"F!@-6')[!Z!*[0aA'%M#1J$%%6EZQ-&l!@qH "-3+-9fKDhB(fFpV1D6HRcCcfGGV6D61R[CbfFYVED9rheQI`eQ9)VXS!2D)Yh&[ c)ENq"'h`Y(V6iZfY'q'Y%m+S$'3e2BP8V,GALaf*%Grki0Lq,ibZB'3&SbVS&'0 -"H-T["eJ[,8N''-!@$-@JE%(b48I'*X!BKpDpB%a!i`AS(Z-F3+-%8#@C)3!S`- B'F#S!-E)b2JBhHl2k"K'aL!m-'U'N6'-LQ&8#Qh"Y-VbCV6MmfkdS20fM)TK4)b -2p(M0'3X$+-dp!J0aX)`GS*DCK3-)f!BrF,)&aReSXF2b,JE4Q``@S14'S`BB*` 'Bc4S#kFGR$C`fVpTqkEPR*CbfVjTpkE0QjCd@XYT+DIeR(C[fVaTlkDYQhCZfVK ThkCYQhCY@YTT@DGGQcCYfV0TbkBGQcCXfU0TLkBGQMCSfTpT[DDeQ[CRfTjTGkB eQaCV@UYT`DEYQACRfTaTEkDYQACQfTKTAkCYQGCZ@VGT@kCGQ6CPfT0T5kBGQI% XM'9K(!)M@4M&`SJA4VJ`LS84,)aHB33-ia-BmD&l4aM43#XiidBBad(E-f-!"(F CYm*S$dCk-'k&-5Z-@'$%#U09'+R#+"9'U$#HJ6%bM2aJe!FM2KM"`(J2aRS`KS2 a'icGB0`')cdBfF'i$FCX-&k$N4q-lQ#X"b-f'+h"5!e'D6"#Jp%CM-aJ9!BM-KL 0`8J-4Q%`!S24&ibmB03&Bd)BFm&i#mCD--j#Ml&Jc)q-pp%M*aMY`dJI4J8a#SL 42ScbBB32Sd!BT`'2BI3'A)C4([!B4[N``SIa'A!D'G[$'"BpIS@a2B`'J'm`USI a#Y!#16#+4ir!B2b#m"l'XM#1K6%AM',4)eJB9F#S%PVA'Bh*q!hDj)@6-)U#F4' -L@!m"+-X'%R"+!T'9M!QJ[%3M)@JCB!a%)arB1`$iaiBmm!S$%CG-1D"m3k-G@# F!f-F[2%0MS)2rM2k16(CU!5M$ZalURYfpJNEUH*SqmBHf[c'ai8a"rBp!lkHEL0 b('hI1*(94Pbiim#q*lma1hZhM8&cXRdZXadr4,pU@[Y"cm$pfHF%DFjdKFb`pkU MH5Upr4`8A5*Lk$Uid6E,1l"-95+9lNcSbD1l&hVbk!k(RMad39aEj+&,BQq4Kmk *L88H1JPULMad)H`UmS#TZiXmG#rX+I,3q6#Tb%2Aa13L$jd9&a9jk,kiZ-K$KmB P44kk0kB8HHM`Q&VNS3YN@T%(pA9kNBFZNKP&(MT0DSXmG+2-,2,3XA*VNBHZPPP &(P6&'iSmG-IX,2,33I1#)JmG0V1,2(6Kc#Rbd+PcDC'(ETkj44kkIHB9HHJ)ZUc )3pI3r#)2R88,LMadF&eHj+(lDf'4Kik3!%9&(VU1VLMbd('fZ-K$pp4Y44kkS*B 8HHKkfeINSIYNDC'(lT8VLcaddYeHj+(ElUSL$aej0aGjk0DlXmK$4ppG44kkrZi ZmY!CH-qL!Zpp1)m$k(2,,8VMVYR"bUf`E&rk5br5U1BQAcTK2PdCMSIkG-p8)c- bjAMD2(-r@##5KrlrB88HCJ--,r)`,f$S5hRL%'TA(kdXmM"[B0P,#N3b$l-)4QR 2S)C)rGPamcS2X`Xb(45qdkcjSdUeC*C2I2eV58KIXPRcCmI5+Mh3CXfIG41G+4C b[90jDUXa2G"QcCrYH@Z,@I1RVUd9AS,IiES$rAh-QMm,`MCeDYEmf65c$(ABV2Q M5P&UpaiDCXY4qmfD2lZA9EAbMelcCdCBQfDjd-H8Cee@4CN+D6C"T4YC6aG"Q+H 1VrNcJRZIiHm6*PE2Zj!![[Z`9$lQBB$'c"SC5CjbZcGpj9,cBFhaJ)",$hjBXaA S,qpI+KhhY1@4qSbSpTLE)HH)HX6T-jHHqmJ'lR1"ca04Qa4c0)3$4$5MK(NDV!M %h)l4j)RCIHbD$a(09V"V2N4jUm!j0,a('5GjTZ8KMQi%ZqC$9!SMA5Tb[qK[Fjp URbHUf5,-jC!![[@SjT6B04qLQJNa5H9[lc0jZU3kL!QrQ0NKq@*kViZe"T(N'6C rlfEFNf92jAh#c,[XUcc"rGH[mrH4&GGNKGLeE[N'YhepVpX@eIapYZIe,HjebeN Kad5Z@miU30C9ASNEF9)UYHV+)b[Ul$dRMbJID'ec#@X,LDpda)80bl-Z8jkkLBC EXE&GCmhA4G'-d'9"11d'aK4AbXT%UK6QH(Cp[4)hfkrMjV@0b,@bJGi961rDcCS lXeTCFZQ+8LPeqEh&bIX3*50jBqrUl8X5(N&#PV'5d2C5+9QQ2(YQF1[Vl-iI41T K%I8!CkJ-6JM[,j@@hZTakR+Rp`rZrkMLi5M%rq@K(LQTXbYmrEbalHXRF+IU4ee @ZTcYa9E6ec4HGj-mebQ2HNrT[F69-4,[qHCESac1JPY&JL9[U'JJYpPhNLR"68K !2ekU*mqK32Y5YrCiYEF%U01"(lX%aMBjLp4R*pNh`(30PeNVqUmqGdeMJ92P@c! kd,GbS*@jT-95Al0QfNK(khkiq@VR0pIjY+2FM'e&iecl[[c1GCd,"mD#ffkfMC) 8qiia14*5-KdCH0SC+frl@([P,BpFP8rm(FSSViUK[JdE%D*Z'4dE1CAckk[9@0, C"dHLZPUX2a%kl@SAH)KiE[AerSCfPJXm-6DN84Q"JpSQ9'jBK[Dj#ch[&,@&LAp 8lm!Bm@TYlq#`KV60MQSCpe)M[8QX)@+VMP[B86XFjF-0p8j!iDhj!%1plia#STD MhRp+aTd0+G[H4M,q6-4ZZbr22Se8X$[8l-[($EJS0[6dR@N*mTQ&,ZeH9@khca( )&Fh1,rU-*iM1(j,2lY6PJ2X!"6TZG2q(E"AUT-1&a'E9UmHM9T4&B52Dm6pXmMR GI[8iC(KVe++jcK&4)rqjDh-kU20,l1cUU&J&S'Y,NL-pCA4+Z`+kd`k[e@4fDY9 ITCT'6b33P,D5rpVVblAb49JC)0Qc[@[,$lZfDCD3!,"d,lF$i6[3TY'FiaGhFXj -3XQ0Gfhph#C5KrYfp4Uhh"3qedCcjh-AFYaqhLL9%`q%m4Q2IYS@bTEa'BrqK4E I&CmGRr(S*br4q)bcY1f$Zf4m4T!!@BP#V3bj!PPGCT!!Gq6EQ'AYYDYAEf9)bDL ddqUZaFh9l55ZGfTCZRTVIAVefGeRVkl(YA4ef)jX-A$(b'IQ*0#r`jb%dNAZjL3 X'"eF'fahbA4D(Xh#9Me-kVBjlFf+VD`Q$[cF`Gl!ejF[F'(G*BZ83BQ2#c'2#h@ eiG(bD+IGC[bdbidpq,J3@V4ZVNU*HP30AC!!YQJKMpZQIk*PZd!rIc#!hJ0EG*2 Y8dQSV9aF+Cp66Q28RiZLlr8DKK8Xakl!ASYGL9f&ABfp$PZ(AB0GLef2hB$GL0f #hBVGKQ8VRZkEHTY!R)JJp2SpXXefX*0H[dFZCqX5[pI[NI6HP6Gmqm'hD'GDPhU [RkYQ9T[$p3X1Imhf(T*pJ4CqDpeKIK!F[PGl8l[-2KI[,#Dhh+5q30IVmj9XcI3 $@9+,N!$C!i0p$0,SBqHqkdFfDP012R856DqTE#(,8QlRAREZ[C!!Y@bTfJ2T$Z3 +*'!e06p"qI,4YQ2B!QQm&(+(@&qL8E$KhlIcAIlX[F@*"-,iGaGYLdh6jh`Crfl feVCEDbrS0,)Sk)m54KiXF9009J!-V2AA&'@NFU#Tm8'bfrCP`9"edf(hM,$4L1- @-k@fY)1K6HA+kXUCCrT%bmV9-+f&MGblf1d)URhpKe1R(S#eZH81@q*0FG+SGpH J,22,P@lb92D(Umk0aYI8hpV08qLiaCe@&M8G`5DN,Y[#1CjVp1&FmK`YYf$1L9l AMaa,"SBhEPB@(CYk&aN%%9Kl0++T,NJ5Ih[VY'q29qcdY"PXVJchca@!MN[8Jdj UAiX,aPm[lY@#`2U`jKCH2&N-bDcQ2Ef)KZH63Y22P`UDh6-@V"ebbC3V$a2EN!" 4JJpNE,f'9aT0"4N[1hZa908hKc5PS6UD3jV5m)V0)C12EQMSqldCDC*NpNZ62l) M39)TIE%[QG!2@p1CR+3$9k"Yl54Mf$E&mQadYHQddm5eVKjPYEKKRShe$KiZXPB UcYTJbPQdFDbCmi#9aT0)XfR1ml`jcqBj6q)@2)Eal*P2ZFGbERDAiYJDeleM4mF H`$Ki!12K!Bb("c!HEQ-mA-CiH!$M5Gb#"c!HRYYk%XRe8iM,[!"iZUf6Cpqe2@c $AGILZUQ@GV*)3EZT-JRDJ+ZTiRHT$,R,MYT032r5@U--6QT)mV*Hf!ae(BENlA5 T(LBp#kQfNfCaXhb4Zh4lR066S+G@)j-JrHiYD6!@JTk3!+IG@G5D5Z&5d#Tj*Zf GdBNDGE5mh8QB"VhD%(5$5mSqCm$c"KD`P*ab6HeH&LBYIj'P9Dkic6@#JC(bF"Z XPh9hGJE',q*CV6qHPRHVMHYZ[@[P[TP4UN@rYV,iT54,2#SZ)5,Q[$2HbXUAPV$ B@`Yc5pab3a*hfX+(RHd`59dLZ,SaE)a2(R*S!-0"a@k-+"KG90ZR*l$LZMlCPJM qV'ZV%rEK%Dh6HREj))Y'*0f8K*1UD(&Yi8SEQ9qB`!J5l(468BbN%E$F!JUl1S+ SJeLmYPCl'EhhcXc-KrVS[56Z*$9A(NXF,3,a!VEF5aI2R%Bm33%Q+R46F`&-GM5 L@'jahG!*bAU,5Q!RLhhDU'@p[B1$clrAaM"apHITLeP@T#',af*p)XK9#+'9Ifl ,!MAF5E+YFEB`rm660dl+P3VcbCUSJ59,KYkYPRh@1`ehlEr`9XkX64S*MKr@-Y1 X@LS,C1L2*F'paJ9@5#eTD#eUXk5dV-L[2`4X6`9Kr9E@M1@l&mZJ8li(X$*QS%6 $%Gk,VE#iMf,l((`NU(2q'VE[a&Dj!XpLq`9[r$Xp)rGRK9KmJr,he-0EP0C326R 1%bVT)U`25`i@+QIe9h`XhbdM$A3q9RJG'2bH4LbShm)hU*dV,@SA"ePK9IYHcQ' )q@4PRm#E'r"bmE(dh'RXc5ip)HTfI-0q0MLCqP*I`$GF1l'+lh-F+VQS[*&kc0H DZYV@Lch$"#-'3Bm)lRJ,F8(G8eCFr3&E!J@erLUV`C+$qM[,Vd`De*,KCr[pMi* kVA1#%fqLI64i&Ejc[4i8[)EcHGVi6AbmdrPqilIJjr"GB(Ik,!G@A-A(ficLIP* 6`Ar$0pSM48Je1FDV6b&KJeh*0D5&jKP2MBmPbPNi(jrFd9[*0E5$`i5HUXC5K+l %9leqFideB%-I%,B)S5I(UcR8j*X3"CCSa-3NeB[ihXlC6UB+#4XZ#Zii$8`+I4E IaG5(e&Y)Up8bAS)FRq%`KIH6@JSpM'qUAi3PT(I9qTMiRZ6!Zq%$5eL&&VJ$5r4 VL!p-B@PkI&,EHM&kI+a$5`hL3beP$9amV"2,%[2iZ!q,bZ160pI,b10MZA8@MXF (AK+,$qaKFAKm9"M,`H0l)3I`#KmeEAZ-`X*1&RR(pcS1LmhhS'%b[SFiX*`l2M# *"GcaIB3$li!2!'@4GRaIi-#bl2LqaB&Da[F$$Lbp$J@J2X!FI'!Sq)N2hX##k[M !!TC3adFGk0%KiZ-GHA0ma,!`1Mj'V0Q&Db,##4BrahFA"`hfiJ-EE$Y,4'r-dZI ihX@"2LamImV"$Lk*h-2"-*(!mF)!kJZI`%)!h0'qTcR!Ck!c[+XGp4CP[9h0Ar# "`CBb4B9jGP1qU0E,K52J!hGXNdj8p8mM'6lUdfUe8G@2V!QXIEb['Bm51%&[FC2 jL,'E@dA&NfifhpdFU!YmVq"JPGbS10UYjRXV"pEfaFGUZq!'2M$b0[0pR)-G2K- 94YT9L+1UHcJ1[LFi[-Kmm"+`@VkBq-mGjQ0GAeB3aXGk[#mf(eJ'4Z'MYPRY&aq e4#hMidej6hcFl4lc`32fQimhVMFIY8iX2YB2&PkNIAr&!5k'MbfU`%0m2q4`RrF j,MkNqG%LL(i%[P%(pMh926[lK(%(4pXh&M'Q#4I'(0Mh$$cXG1-@MVC[($*'%bl FF@$INpqBREhli+*ZZ2#bI*ZR"Pai+AcKEE1cepkjL"XU1'G(HTYQ'HI+jjiEkHf H(c9C0fRp@$*UXSl4cmP4NhA@`Z8dqDaZ1NVVVGSb5(kf2dVRS6*HhM@h3'YUXmC i9XP$i,e&([TrlL[bX*lKX0IbR&K4I!kBmI41ZB(6hQJX2F"TmT(KA6CSpT!!"Ki DTqR(0-2fc)3Y%jFFf*@)5)hY5S5PKddP3QfACb+!k9kqemliLNFN*RfCN!$8[#m 6XLaUMHKa8N&lejahj,f)Q$96Fcb+M0p,ABV3YMFM029Q"(L[j$EkJX'*'q,@XI( 3DQLSZJK!ac$MPQ6`90fV$FMpr&bSiaq0,02EEC[RFr`HYF2[YaP"Z8rQI2+`(6P U'qQ2jR8FZXHmVFPN0rECGf@`f)*0&CYRGE`q&Sq1f)bXirGBfVGjV(YLBGHFjLm eCEEYdrIBQ$ArVrMe2CL5r&bpkRX8X*1TZ-9[q8"9Drhm&Mp!i194fqD9(ApA'4& YCeJGVrZGD@)c[SlIJfp8V3&,2[kZqKjk*YlaHaKqcqcE0VScC2%*TV0JD0!Qhq@ qaLR3"epqdH#2%1E`2C`"$'AKq4Iq'$NEaPQhISi+TP2!cY3SlSjlR(rQBJ(hk(b 3!*rHS`1!Ihk2)T)IZBFXd["rY@qBkI&kKERVHa4HSf(UH[ipGM#)f"&`Ml@[[Qc aA4P&k0fM(BPqHSmGVl,6iV['lq%%B1lk(VZF6DEmcHHHB0`bK,KVL%VMV2r@EeI @@56J(RbM+**Rhj@4UVibIc"*E2%*jZkSB+C1!14d+b$9SDpVKTEl3p14Tfelq@F dRG`ph#DUmc%Y*PXG[p"LZZja9)[TZXG4,DEl(NHdQ1)ph!YD60Ylr%U,b6hX-eT -m4j(YCLfDra5LqQkac%YjZ"&A!4D6'F1ZkG(amF5(m@lTKIpD2kF(jT1&SKqSHR N%GmCS1N8aelfV`aZY&Rj[rRSVh&2G&'i!lSIA#IG"PZ1-5rTHU@c+0(lf[$&'BT lSQ[KHUemHI`cpcL1`('QA'$FrriHlT[ZKpf,!Bb'PfE[FHH8&lUbddAp(ia!,Y* 4dFFB3GFpMM+#VRXF4I,ZHaa"mZ)pMQP9EIIiP9D9Hj!!Cj!!XhL2SmMCGSeI)QI A2BjT93F[%Vp(3Bk4HqKT#Zdjc$hd+R,CMdZX5ifmjr1i!638IBr#i'4INFJMQYa $9R&T[mI#LDdr[SGlGUTjFY&!GmVRSTYUIZ)10-f'lCG9[M0B%1@PC('jb4BXPb0 V62mNAeJj##l)8YH6JqdZQ8l,SeRBUSG*rG!+km6+hLakRf`4GkkRdD1ZlT*&bU$ %ai@Sa`AGdV@NdaEAF,Qa"amA3MNZ10b3!+$Kmh%KY[MXp$`VRlK@#Z#%Gf%R@2M !#@E#BUNR[K(kL&kLA$-LGK9hc(d+@0JD4Uh&RUT3aS[%1&ic[d9m5Vq)1b921FH ZEH-PLVNP`iXm[6QH9Z6T`h&SNBFK3*9&R[iFVhiT6hbVHiNkLH10Vp@&5$kIi6# S9'V9e8NY[X&C0@3D6@JP[L%0laZV0icJ8k8P'j3(Rm3a*@EBdVk'DkB-[5*SmhR ,H[XUSkA5H@[bqlcZQT-ICjPLh[BRXrrbR[RhNErXZlH@5YIZprF1RM`lqp4Q3Xr %MX5HK@AKBZEMMH$jcV(h18re+IB-,$1&,X"HL"f&(8fH-CDR#MX11ail!FZFQSR B'ZcTj*PNH5l#ASaP`#*,)c""4pifm'lXD[*iGF'XYKAB99LQK6-CD41@'YK-RLf @"dD`(FXXTaZ`G+%c*BJ"3#[*XmIbh)6GLi9C#Xr81&CLY4NQ6kRP!EGX5@YX!RF UX1"+Ar,dXcc81h8f!(X+pP6X308f45jj"PZHSF)YXFa"C-)4%hpRBDGJTj0RYZ@ j&(X*PL%YFl(cX-`eBi,b![*S("!I`iHZ`#l'-U0a+IC+l&ABUH4CCRQZ`5iAAL5 "5*Vf`cNJbDXE[(MYRH!&G6!02"J[j%TZ0a,2drMa5)(JjV1#kkkrPraPj"'mN6a 5%HSA5mHVU'kE9I`$`L2UMI[GAb*4iMl[2QFbrfl$Ip[Xi92LI4iiDal2IR$l[q2 C!ffl$r([1aS[q9qQr2(h14$r6VZIi1*69j)RD(Pi3M#!HZ(p)PerqYAbrqZ"pN0 acXqHR,jKG!#&EPXD0eajU02)SV@96TV&cI*&lY,YF9*2AdJa[9Cc+(Z,`Qc,Lr& ,3rS!GjG(ACC&VDNA8ma'%U`F#Y[YPa2-k%50HVP[*NYJcFha6!QSMHYZ[@Zp($i c5K%Jec8RT$kfjE"#69[dSL6HkQVCLf@LUA&Fh-aQ@"BQVCIIZ,Cr5+T8Fq6FNI* `1iZDdBlrZ*ZH#E1`Nl8l,ck1$XmrRSkrDZL&8,q68`TmQfZmN!$%m[RfelFTfTq ITX"m#40H,''rVl!Y@MSQXU'j!M(p,,N#N!#qQBlAed*&4`C8`[cMqb*L@l6hH[C FQ52Ur)LpV9-*UpG-(i0d%Z3!RHJ11#G"(X`*cd%jd9NJpi*c'1"PD#N8,lDeb(9 4j!%m%Am3[h4m-hJ6Pi0ZSV2!(3r12PJVD"0BJ'a5G!#fRb$hh&Q`pS)lbc3$e&j X'UEMJCPbb%%dd6Q!*VSGRSR2JV-AR(R+*$#RJZ@e1Q'B"$NB*VS$KNQ3!)GK`R- `6(3@KVhJA(el'9U+`S[0&88HKK2a"h&*acI$-(%j'#Bk#m2ai1b$YF)`J38B*N8 ($2X*FXqGK@%[Z,0--c$XaDCK1"kB+BFF$"1GJf'Lff'Bq#`-Hm'CTmc#m1bHX@- `6))F$"2G!F-Nb--`i6NB*MS,`ej`VVkp$#e&iFAQLL)2`iRiJlLNijYKQ,JF$"1 GKH&iF2E"@Q'B`!)-Nk)$K[d%ZHI1`V!Ah&QQ'4MfBY-`(!r-P%-1KSR1`6$4l6" -I"D'[H$-8ak!i4jCULK-p8K6AH*88CiU#&5(*+T1NDSJ8h8,9Ge598kX+XT9Km@ P(RQT4f!U5%b(4+C1Q5N[0"@NTU,B9*5EHU5IS[M6)rpd#8"&#DJJ!Kf5J6U&S)) 8e#d'GFY"18'S+!NG&R"k**`H%DFJia`5FMUPR,bB8j!!FiU#6P(5kC&ALJ*,Mm6 5*E)8CCD#d(*)DZN8@`Tb5lIJdLfjj%5ASZab@#6TN8PkK*+#9(*),1Q85r+#58% b+BSQ4GQNd-a4E1I)0h4d0bJ8@K3kQa3+E3S&GEbSMqF9mQl&Yk$jGUUq"Gfh)$F @"FHmj0JYS49%Y%iC,5ZN0DmEPqCF,6P5T+XP342VDXR43,YD-U4i9dZ#*2(+a+F )35D*,CG-H%Hp0*!!Veb+1,&T6@(S9dYSLRqe*%K#86Dqp3RR,L33-'T*IS$GY@4 *%V0-I&FKqY3X%`ihbmEQLc6&cPS5T1KC-X&5Pc)IDfFmPB609l%aP5J,N!#T,1d SQ8U8JmT8QLaHTV*N3$1G*&Z`k8c09C[1d9+H$F@9!p,Q2+eSfT!!j`#NTZ+cZ*V +NJ(A!dQk(VJ&CP-*1V%fP5S$Z1NN4iUi$AV61CV`pd##BK&NN6L9*3[(5pU1$@, *e3('ITSX&2XjfS(B6j1$B6p*&S6p("N)ENb4VGh'2-f9fjLKT5b6TC5$hR5@9Z" 0CMN!Zhjd&R6p("R)E8T4H03@Z2A$1m(@6j5"fXB8KiUe$@BE-c5"E&0ijl0R!GE 2NB9AM`l2G"1GU5QAP$dbYZDB29CpK9$VkTXIYUBk)A1m-aPQaV9M[,e40XlRk*! !9aSeYCB859%Y%cpVTZC!,e(6mLr[bfqCm#k@e&jrU83(Lr!!l@bYa(5D6$Nf-,K m6EBNkQEUqHT-jFQ8D$T*4jfQXa@*EkCLI8"YVpFNJ@bYeLE1dPUVM8NbPCSN![N k2C!!TNMVmMAUCmP8D'1+M[TXc0A*PlTVFffYpTp5!CPke!,5("%-b(4)-b"2Mfa !QL0!3kCZMF(,dX0F[93GaHJPkDR(3hT$)P%"Qh5LGY9"ef%"HXR4)dk3!1B35-I cG1JBm5cG*A-%p-Pd60JJea'1i'IU+F9Z[F6,FK4iZP36,dP11)PRk+UH([Q%0$d #*@N1XbB5G4-R,mY4lZ5PkbUFBMr3NVL6e&aj,('-`Zc3LKCh@S$R3E%(AM#R%8m !)Ch0,2J1*q,G1K+P1(cf&3r+,Le2QHjSq1RYZaieV6GdC22jErCG@m5*PPGY&)U 2hE[V44XjHMVAXYlH`F(RRmq%0(&e%jALj5DNLB1EU!DqE@*5h0U%T'ZL-Fc5Da1 9T0+*L"4l5B5e[E62RK-"(ZlDPfpJaFQJ11fb3BEY'ZF"[QILNM`X%G(mDUfeR!K 0[CT(Xha[kJe6p-Q%T+L5#@QN45BS5B%5%@QkN`KYHc1Ip53#@SRIaM"ap9FJe-4 hL%FQ48ie-[%GFT&*NGH*6)+F3'6L1e'q-8H,HQ45C'@M4(L1YLGbG(+$4*i@HTU )cPGYZi58c("3X,!CQN8M%eR38%b5V0#4##q@5MH05Z6*P8UVpZ'(jUSSThDBq*c -BH,Ep3f6)5YX*-)l&Be%RN1&NT%m%Y%(Ud(QDVF6!F)lH3!CmM5!m%i@3)Cf%N" mRJ-3AU!!U45Y$)!-13,J4HG"c8Y4+&8[6@ZPHX'j3Zh!rN5#0ZMA#9U3!*r!)[# 6)iIlAR5K3RT3hdZ6VC!!JjJIMmc@6Kla#Fm$2Z%GH%q#(0ald3@dpp,de%F@kle JV`UF5CqkYUj&(,HQfC&Y*BDcbH-T1iPVh+PS2PXTaK6AZ)1R@XAK(1,BcY(r2[A (@Lc4h#rdMr0aRbG1hd2ZPi`V[B`P"HcpNR'Vf1kap-&QPZpiP0bNmX-FRLD1R3r mZ0$6(#UE@ASNRp*D"[DGN[IVp4AZFN'cR4k*@r)P&MqFhmbQMVa6@&XqpZAH[,G r[jRD&Z,6cDc"HbAM*[`CprZckL$cQ82Iiqhe0TAb$IiDKe(YK+e$3RGp"KpE9FT h$aZaK!Gmh2YlP-2Q1eHA0h%2[4IID"phhkFiR1RMIU)FGLAr)GTUXFc(rGd`2MD [*0rM(1l0im,R2S52E5cPZeml,mccq4l8FMKX)mQ9EeqS*hq,K'dIeM+9YLlpZ-M 0(2CCAITaBH'%9cGqA&5EC`keZ[(MpYdbAamIdhD6GSZ2I3r1emFfE9eTGiLkij6 jqRMdER`,I0aGfJV5eXG,@IBaS+dhLI[#I(eFYaiI'e-5pr@jqJMYH4)I@e6+GlH fac6e%4j66E+GTP6kcSmXe)'r(QL81SlAJ4mArZK#25AcIA#K2[bi'2H,eiFI0dL EE*Vk#&qKQVEiqe%``pC(q'HZ*X$Z$R'UDXM84rJbl49P0h9mA*KNkL0mP6E*[0& i!29UkL0mm4I`X8%RqIjk(Mp'DKm0kJ+mCpF*@aq[%TEFl12k#*pUmVLq2a$'[F4 `p`dFH[Zi4l3Tk*hfVYqIbpG[ac*m$rLiJF*eQqq*hIM),eqrlmlIljZ2iRZ2MqZ [c8C0[RklKB[[pA&pYEQRHHr!pi9re"h[)AK[hcY`81rdQ)ql6(R0H`Iq4MjUJAZ `SjTjlm"REX)((`'R(jkrhkHI`XHpL101jRiUqD3+eF60qrVmrCl8Qhl-lXe@4HC qUNGepR'lamUjq`9M[4re5(f$8qCq`6F+Ym!%q9CqFqjq`HekXdrjZ$fU$h1ri)l 2iK-HT2%*(Q0`)R,5,q$lQ[%RkRb`MhZ0DSLkNqq2`0Q5YSm,kLfqlH2HIJHBGV+ 2Up,Z(YraeiL#0j9rjH0@LdYqeqjh,cEQmH16fZ6dHmEcK'F%l"jVK5AJ!h(ic(Y (hUQY8rr*iUM4#Rq2KiAh6eUp2U6,QlK(YENV03,ZISR$&"rhT,C#IFTi*29XlK' jm6&m2c4FNHeFe8-qVYHr%N#0JarJE#prMbm+qm!Vm!Rq8HAcVEJ0(cRPZi8kL&4 ph$4aPAme(JchXMMp0['-Ic-H`#DTDqcHi-(6aVHNEVckZ&YFlNIfIY5cVBpc2SE [aclZC'fiqL&r[fq)GpUY5%qqKhFGk11qqNrc&,C#m3rkHfb$0hLVcFD%XjCrI"q I-ZifK)e6JeB(Ei&2H#[6KS9h&PGQ82G+'#*IL6BZ+S1AJcXq[jQ+$K%U+epXpkr aCNVEbI*dXMeV++qRf1i9TjVq!-6GKkq[MkZ(@bYK[RbIH"rjq[ZiNm!QTBeQ`8Z iKHB0XGhh8@2+0Q)j9CaEmiEBqjk&HbPY2-XlNIF-Rkm5,&$'ef2S&UEqBVY[)*F b[PkLYp4i'G[p1Ef0jHX$a&%d(XGfGm(2e&NqVPceq6`Ipa%`5)%cZQlJ*b90pLT ,e)Cq*p&[!KpUKNGhAbX4(cEhVYr-9VNUhrK9q,&XH4YHjq1Q28#FfE&CR3l[-$J GfhX&@mFUEE[+m`S1'Cb1lAN%A&6#4[P1S`i-6XIfDQPETHeKjCXcAkreer2f#Vp q$lQIVBrkc@b4Ue4he-dr(-+Rf0irr#*aXTbXcJIqDGb0lGd%cLREb(B''mmDr)l Y$H"-5Y[CNNq`bZ"hE1m0ZJFEfa)(cl6hH#Am4QQ,@qLmE'aVm$Zfjbkp"j[Gb[F DX0$L5[e[`Qf8YYQ&(m#A0*l&pYccF@'-LGXXc$"i8lm6V85*Ji$Im(jlMhI`4SS Dj(XGA-6JI@c2RGmLMXf#jAX6ZSc&TrSEU3QPlAQTErL$a[[BRZpG54akMRbRL0F Ch0Vr-&LSE11AQ2L*`DhpGi%T5TbD1RMPI2fK"5MHAlp6R0r(p[kPhS-YGZ8E*Yc 4r##fG`IF58PMNDm@hF6`JpMH')kUT)2"ekN6c3pLHem(Pe2DJ"IHrm3KIL$i)4L Pa#APfiM@B[L"h%0d,28QidrS$JCIpcm+*e$D(*JiH*jp[dAS@1TYaZGiAiYc`IZ *XlVA32&JJkreTm+TP1PHmm!2Lkre[`kI8kClKD89fAZ-q50mFKGJlA,UfI$Df0j 2#!2Bh&MLVJ)$,&lZ[d[Da'Gph%e`"3m[[k)D%icPQi9qjZ(PD186rBV[IYl9`m[ TUPIi(Hq"eQMIqir&rG!*LB2[fATpC!mqZ$rm$lbf1,G!R"`p3Ei9UN@,Pkq(f`@ NGj%2($&iZIpCm$)JIB!ikX2HBk5`!&iXheid#3m[2kbDrRXIYdFkVF@jkQ[*`CE $8$MZBqYl`+IaIGR(E8AImI"bJIL0h8`iV$UhpbMrAAaImA%28cm@,qY6m@2"+,l h``-p[(`[R&qCRMTEqT("brTedP$J&q#Ik+mHAMi'Pe@fi9G)R0lJCAdGV89*2k3 1@1h-eTr@@RKciQK0X2AhQ',3#H@l9RU"`F[pMdQMK0m"0E)KQBHA&G*DV)Dm5hU (aFYDD3bm!lL1CQ$`X[l0dNVJ0I+pkX[cH$Ri6`K!db$IQqIamR%d+D80RAQR""q Y[dEB)abCEr!#AXj%Te&k%rPZ%kjB[0`RIX`fd2!Ep%',Pj23m*9d@RJ'HN1*jrF 2`1(9Z)rl!,JFbHXlF0a"Z*Db4@0,a31Y(V!6M&#f#QaIEE&XiL)R`&'9l8Sd8"K QimD+hjKGM03PB*9h[he`"LAq+mGedS00A138DPMC)T,$a5[X[GmRhQ#hqjUR,C* Yh2IJR-TfcC`R,,4a6iQAQ&fE9%6GH[Hq(Crb1U[DaqE0hVfMD!E+G0D9iZ[fr5k rN6LVXki8cl$hqaal-bRMlCY9ccEZafJJbVDT'b3F2kNC(qfV#1FiC2@5Z&lqr`d !"8PMEfi0D@p38%-ZE@0`!*!4H$-*KJ#3$iB!!$q)!*!$&J#3"'PMEfj038063!# eQI#%YCR`K!!!!HB!N!B"&3#3""F@!*!)JE)4!!JF[-XKL%Vqkr)IQ(qRr&[Nla6 hDYcMFCFjq"YaTmHeLN[2GdpFcRaEjcXYAk0m21qMq8VPh6[[,ARVj-h+FeLHar* XRZHi20im2E`Aj5RJ6I0HR2Y9EqIFjhU,j8l,I9eZP$XeGilF20HCZF[QV*!!Frm F0q9-c,&GMVGcP-Pa@1aj14V(GSQp1qE4f25BR@-hL'NEFkrRVTMdQ%GLYiSj-,D qXmMT%0kG+6`p!r+B3c"H,b-CF*54$%p[fY"-D$T(Emh-i#$Rk@eK'$HR8'ZQ(!T cYqY-%A+HIQQ%K@(XR2`ZdLmbcpr'-b3U-8II58AYQIfMclTCrUa,aK5GkLJ8DZY dYLC!(J4+k5cqV!ZZX3#3!`d0$&*&384045j0B@028f0`!*!4KZB*KJ#3$Mi$!!" $(J#3!aErN!4849K8G(4iG!%!VZP",E@CpXm!!!'X!!!%5`#3!md!!!*C*YQfB3# 3"M&!%3!)(1ad#')JLFI%1Rb*Jij4$SQpPB0bK,62fc8T)G'Ij216P-l"P'KkQ)V "9!65Xe)GTD5H!!J3)B2Y3fARKLIIKp0[UTHYN!"1TZXCRhC&(mcFBpDR'HL$*'B bTRkDJEjBKM3rJcd9[(l15!U(i9GF#&#aYR)HIf+0dbT$lV2bl"JXUUC$EZHE"al 2iakBaArh`'Q21'8UXp'm)bLH6D%Jj*ZT4*peCGa0ec5-ImP4+,3"j!m%ZqTYqZ6 3G)IlBUBS06Yib'K"cmeeX!8+SJ#!)!1BM"JC-!+`$L,X(*!!!I2)5Sk5@mQapmK 4)jc-'!()lfAi9c`$q#LHiJRk%3`%F23LI'9'RJd))mKJ"$&X*HX$!2R!j-"86Di hP&T,(j5qZD143lS3BL2ThP2PI'XI5AP$NipTUQ[5Y8[4mDG"DGPqH44E5H18D(G GRYhHlZ5J4h+q)$f2NA("kX4KNAR[25[cBc!alGMBre3)MJ2G"UBhKAa3RC@#L!k YLdqqiJYGlkUJ`N*eRJ92AV,"NXVII@4++M3fa6*3F@STdf5#C'1L-A!6e&"Bmk- i@SYrMNqP%#KPLKKmkB3@RNJV6mT!k,10E!"'#$la2"5TmcHT!P5IN3-mIH58Q96 #$lKPhbr8+NLf&J("!%4ND4QlQ0dA*j@UqNA-l&mPQMPd'+DhCae+d4&89pQj2k, C$*%#4#&Sih`6FaYB&mlVIM,@B(82mSImU#!"I(BSTA4f0&K[0Bhpe#"`31l*&!Q GjeQd21Fj9$,cK*Z5-6*A$6f@S"H0)mXXp68BV-T,`8&6,QpI3ZUC1dK"1cN)G&H &59X*!0YIFKAPj&eMT@k&q-$'e8kVj0K(+E'e@DqffpAjf3A41$Y%i#mMa'&E0V( @dUZSC--2ZAjm2YUCDYGEa'#3!%!*lImdGq`IE-J"rMa-*q8HPC2dkekJ#P#K3!U 6KaS80)bpFKkS&H0D+KTFM!Makqek*cDEeIVmVlaVp`MSlqK9EiHF[1p`(jN120# 90cC%kk9BRkifTk[eqXJhZ,jECVAm"V`IMITMrqNXlklhKl[p$@hPqZ48LRmK)3Y MCQPdFfP[AfeKB`#3&JQ'!4B!&3+L!GB!N!-"!!!rL!#3"aB!N!1'!!!$([q3"!2 JYCR`K,@Cp[N!N!8"mK%!N!C#Q2r`rrJ!!-0!!!!3DBZi!!!: cfitsio/cfortran.h0000644000225700000360000041006413246025103013774 0ustar cagordonlhea/* cfortran.h 4.4 */ /* http://www-zeus.desy.de/~burow/cfortran/ */ /* Burkhard Burow burow@desy.de 1990 - 2002. */ #ifndef __CFORTRAN_LOADED #define __CFORTRAN_LOADED /* THIS FILE IS PROPERTY OF BURKHARD BUROW. IF YOU ARE USING THIS FILE YOU SHOULD ALSO HAVE ACCESS TO CFORTRAN.DOC WHICH PROVIDES TERMS FOR USING, MODIFYING, COPYING AND DISTRIBUTING THE CFORTRAN.H PACKAGE. */ /* The following modifications were made by the authors of CFITSIO or by me. * They are flagged below with CFITSIO, the author's initials, or KMCCARTY. * PDW = Peter Wilson * DM = Doug Mink * LEB = Lee E Brotzman * MR = Martin Reinecke * WDP = William D Pence * -- Kevin McCarty, for Debian (19 Dec. 2005) */ /******* Modifications: Oct 1997: Changed symbol name extname to appendus (PDW/HSTX) (Conflicted with a common variable name in FTOOLS) Nov 1997: If g77Fortran defined, also define f2cFortran (PDW/HSTX) Feb 1998: Let VMS see the NUM_ELEMS code. Lets programs treat single strings as vectors with single elements Nov 1999: If macintoxh defined, also define f2cfortran (for Mac OS-X) Apr 2000: If WIN32 defined, also define PowerStationFortran and VISUAL_CPLUSPLUS (Visual C++) Jun 2000: If __GNUC__ and linux defined, also define f2cFortran (linux/gcc environment detection) Apr 2002: If __CYGWIN__ is defined, also define f2cFortran Nov 2002: If __APPLE__ defined, also define f2cfortran (for Mac OS-X) Nov 2003: If __INTEL_COMPILER or INTEL_COMPILER defined, also define f2cFortran (KMCCARTY) Dec 2005: If f2cFortran is defined, enforce REAL functions in FORTRAN returning "double" in C. This was one of the items on Burkhard's TODO list. (KMCCARTY) Dec 2005: Modifications to support 8-byte integers. (MR) USE AT YOUR OWN RISK! Feb 2006 Added logic to typedef the symbol 'LONGLONG' to an appropriate intrinsic 8-byte integer datatype (WDP) Apr 2006: Modifications to support gfortran (and g77 with -fno-f2c flag) since by default it returns "float" for FORTRAN REAL function. (KMCCARTY) May 2008: Revert commenting out of "extern" in COMMON_BLOCK_DEF macro. Add braces around do-nothing ";" in 3 empty while blocks to get rid of compiler warnings. Thanks to ROOT developers Jacek Holeczek and Rene Brun for these suggestions. (KMCCARTY) Dec 2008 Added typedef for LONGLONG to support Borland compiler (WDP) *******/ /* Avoid symbols already used by compilers and system *.h: __ - OSF1 zukal06 V3.0 347 alpha, cc -c -std1 cfortest.c */ /* Determine what 8-byte integer data type is available. 'long long' is now supported by most compilers, but older MS Visual C++ compilers before V7.0 use '__int64' instead. (WDP) */ #ifndef LONGLONG_TYPE /* this may have been previously defined */ #if defined(_MSC_VER) /* Microsoft Visual C++ */ #if (_MSC_VER < 1300) /* versions earlier than V7.0 do not have 'long long' */ typedef __int64 LONGLONG; #else /* newer versions do support 'long long' */ typedef long long LONGLONG; #endif #elif defined( __BORLANDC__) /* (WDP) for the free Borland compiler, in particular */ typedef __int64 LONGLONG; #else typedef long long LONGLONG; #endif #define LONGLONG_TYPE #endif /* Microsoft Visual C++ requires alternate form for static inline. */ #if defined(_MSC_VER) /* Microsoft Visual C++ */ #define STIN static __inline #else #define STIN static inline #endif /* First prepare for the C compiler. */ #ifndef ANSI_C_preprocessor /* i.e. user can override. */ #ifdef __CF__KnR #define ANSI_C_preprocessor 0 #else #ifdef __STDC__ #define ANSI_C_preprocessor 1 #else #define _cfleft 1 #define _cfright #define _cfleft_cfright 0 #define ANSI_C_preprocessor _cfleft/**/_cfright #endif #endif #endif #if ANSI_C_preprocessor #define _0(A,B) A##B #define _(A,B) _0(A,B) /* see cat,xcat of K&R ANSI C p. 231 */ #define _2(A,B) A##B /* K&R ANSI C p.230: .. identifier is not replaced */ #define _3(A,B,C) _(A,_(B,C)) #else /* if it turns up again during rescanning. */ #define _(A,B) A/**/B #define _2(A,B) A/**/B #define _3(A,B,C) A/**/B/**/C #endif #if (defined(vax)&&defined(unix)) || (defined(__vax__)&&defined(__unix__)) #define VAXUltrix #endif #include /* NULL [in all machines stdio.h] */ #include /* strlen, memset, memcpy, memchr. */ #if !( defined(VAXUltrix) || defined(sun) || (defined(apollo)&&!defined(__STDCPP__)) ) #include /* malloc,free */ #else #include /* Had to be removed for DomainOS h105 10.4 sys5.3 425t*/ #ifdef apollo #define __CF__APOLLO67 /* __STDCPP__ is in Apollo 6.8 (i.e. ANSI) and onwards */ #endif #endif #if !defined(__GNUC__) && !defined(__sun) && (defined(sun)||defined(VAXUltrix)||defined(lynx)) #define __CF__KnR /* Sun, LynxOS and VAX Ultrix cc only supports K&R. */ /* Manually define __CF__KnR for HP if desired/required.*/ #endif /* i.e. We will generate Kernighan and Ritchie C. */ /* Note that you may define __CF__KnR before #include cfortran.h, in order to generate K&R C instead of the default ANSI C. The differences are mainly in the function prototypes and declarations. All machines, except the Apollo, work with either style. The Apollo's argument promotion rules require ANSI or use of the obsolete std_$call which we have not implemented here. Hence on the Apollo, only C calling FORTRAN subroutines will work using K&R style.*/ /* Remainder of cfortran.h depends on the Fortran compiler. */ /* 11/29/2003 (KMCCARTY): add *INTEL_COMPILER symbols here */ /* 04/05/2006 (KMCCARTY): add gFortran symbol here */ #if defined(CLIPPERFortran) || defined(pgiFortran) || defined(__INTEL_COMPILER) || defined(INTEL_COMPILER) || defined(gFortran) #define f2cFortran #endif /* VAX/VMS does not let us \-split long #if lines. */ /* Split #if into 2 because some HP-UX can't handle long #if */ #if !(defined(NAGf90Fortran)||defined(f2cFortran)||defined(hpuxFortran)||defined(apolloFortran)||defined(sunFortran)||defined(IBMR2Fortran)||defined(CRAYFortran)) #if !(defined(mipsFortran)||defined(DECFortran)||defined(vmsFortran)||defined(CONVEXFortran)||defined(PowerStationFortran)||defined(AbsoftUNIXFortran)||defined(AbsoftProFortran)||defined(SXFortran)) /* If no Fortran compiler is given, we choose one for the machines we know. */ #if defined(lynx) || defined(VAXUltrix) #define f2cFortran /* Lynx: Only support f2c at the moment. VAXUltrix: f77 behaves like f2c. Support f2c or f77 with gcc, vcc with f2c. f77 with vcc works, missing link magic for f77 I/O.*/ #endif /* 04/13/00 DM (CFITSIO): Add these lines for NT */ /* with PowerStationFortran and and Visual C++ */ #if defined(WIN32) && !defined(__CYGWIN__) #define PowerStationFortran #define VISUAL_CPLUSPLUS #endif #if defined(g77Fortran) /* 11/03/97 PDW (CFITSIO) */ #define f2cFortran #endif #if defined(__CYGWIN__) /* 04/11/02 LEB (CFITSIO) */ #define f2cFortran #endif #if defined(__GNUC__) && defined(linux) /* 06/21/00 PDW (CFITSIO) */ #define f2cFortran #endif #if defined(macintosh) /* 11/1999 (CFITSIO) */ #define f2cFortran #endif #if defined(__APPLE__) /* 11/2002 (CFITSIO) */ #define f2cFortran #endif #if defined(__hpux) /* 921107: Use __hpux instead of __hp9000s300 */ #define hpuxFortran /* Should also allow hp9000s7/800 use.*/ #endif #if defined(apollo) #define apolloFortran /* __CF__APOLLO67 also defines some behavior. */ #endif #if defined(sun) || defined(__sun) #define sunFortran #endif #if defined(_IBMR2) #define IBMR2Fortran #endif #if defined(_CRAY) #define CRAYFortran /* _CRAYT3E also defines some behavior. */ #endif #if defined(_SX) #define SXFortran #endif #if defined(mips) || defined(__mips) #define mipsFortran #endif #if defined(vms) || defined(__vms) #define vmsFortran #endif #if defined(__alpha) && defined(__unix__) #define DECFortran #endif #if defined(__convex__) #define CONVEXFortran #endif #if defined(VISUAL_CPLUSPLUS) #define PowerStationFortran #endif #endif /* ...Fortran */ #endif /* ...Fortran */ /* Split #if into 2 because some HP-UX can't handle long #if */ #if !(defined(NAGf90Fortran)||defined(f2cFortran)||defined(hpuxFortran)||defined(apolloFortran)||defined(sunFortran)||defined(IBMR2Fortran)||defined(CRAYFortran)) #if !(defined(mipsFortran)||defined(DECFortran)||defined(vmsFortran)||defined(CONVEXFortran)||defined(PowerStationFortran)||defined(AbsoftUNIXFortran)||defined(AbsoftProFortran)||defined(SXFortran)) /* If your compiler barfs on ' #error', replace # with the trigraph for # */ #error "cfortran.h: Can't find your environment among:\ - GNU gcc (g77) on Linux. \ - MIPS cc and f77 2.0. (e.g. Silicon Graphics, DECstations, ...) \ - IBM AIX XL C and FORTRAN Compiler/6000 Version 01.01.0000.0000 \ - VAX VMS CC 3.1 and FORTRAN 5.4. \ - Alpha VMS DEC C 1.3 and DEC FORTRAN 6.0. \ - Alpha OSF DEC C and DEC Fortran for OSF/1 AXP Version 1.2 \ - Apollo DomainOS 10.2 (sys5.3) with f77 10.7 and cc 6.7. \ - CRAY \ - NEC SX-4 SUPER-UX \ - CONVEX \ - Sun \ - PowerStation Fortran with Visual C++ \ - HP9000s300/s700/s800 Latest test with: HP-UX A.08.07 A 9000/730 \ - LynxOS: cc or gcc with f2c. \ - VAXUltrix: vcc,cc or gcc with f2c. gcc or cc with f77. \ - f77 with vcc works; but missing link magic for f77 I/O. \ - NO fort. None of gcc, cc or vcc generate required names.\ - f2c/g77: Use #define f2cFortran, or cc -Df2cFortran \ - gfortran: Use #define gFortran, or cc -DgFortran \ (also necessary for g77 with -fno-f2c option) \ - NAG f90: Use #define NAGf90Fortran, or cc -DNAGf90Fortran \ - Absoft UNIX F77: Use #define AbsoftUNIXFortran or cc -DAbsoftUNIXFortran \ - Absoft Pro Fortran: Use #define AbsoftProFortran \ - Portland Group Fortran: Use #define pgiFortran \ - Intel Fortran: Use #define INTEL_COMPILER" /* Compiler must throw us out at this point! */ #endif #endif #if defined(VAXC) && !defined(__VAXC) #define OLD_VAXC #pragma nostandard /* Prevent %CC-I-PARAMNOTUSED. */ #endif /* Throughout cfortran.h we use: UN = Uppercase Name. LN = Lowercase Name. */ /* "extname" changed to "appendus" below (CFITSIO) */ #if defined(f2cFortran) || defined(NAGf90Fortran) || defined(DECFortran) || defined(mipsFortran) || defined(apolloFortran) || defined(sunFortran) || defined(CONVEXFortran) || defined(SXFortran) || defined(appendus) #define CFC_(UN,LN) _(LN,_) /* Lowercase FORTRAN symbols. */ #define orig_fcallsc(UN,LN) CFC_(UN,LN) #else #if defined(CRAYFortran) || defined(PowerStationFortran) || defined(AbsoftProFortran) #ifdef _CRAY /* (UN), not UN, circumvents CRAY preprocessor bug. */ #define CFC_(UN,LN) (UN) /* Uppercase FORTRAN symbols. */ #else /* At least VISUAL_CPLUSPLUS barfs on (UN), so need UN. */ #define CFC_(UN,LN) UN /* Uppercase FORTRAN symbols. */ #endif #define orig_fcallsc(UN,LN) CFC_(UN,LN) /* CRAY insists on arg.'s here. */ #else /* For following machines one may wish to change the fcallsc default. */ #define CF_SAME_NAMESPACE #ifdef vmsFortran #define CFC_(UN,LN) LN /* Either case FORTRAN symbols. */ /* BUT we usually use UN for C macro to FORTRAN routines, so use LN here,*/ /* because VAX/VMS doesn't do recursive macros. */ #define orig_fcallsc(UN,LN) UN #else /* HP-UX without +ppu or IBMR2 without -qextname. NOT reccomended. */ #define CFC_(UN,LN) LN /* Lowercase FORTRAN symbols. */ #define orig_fcallsc(UN,LN) CFC_(UN,LN) #endif /* vmsFortran */ #endif /* CRAYFortran PowerStationFortran */ #endif /* ....Fortran */ #define fcallsc(UN,LN) orig_fcallsc(UN,LN) #define preface_fcallsc(P,p,UN,LN) CFC_(_(P,UN),_(p,LN)) #define append_fcallsc(P,p,UN,LN) CFC_(_(UN,P),_(LN,p)) #define C_FUNCTION(UN,LN) fcallsc(UN,LN) #define FORTRAN_FUNCTION(UN,LN) CFC_(UN,LN) #ifndef COMMON_BLOCK #ifndef CONVEXFortran #ifndef CLIPPERFortran #if !(defined(AbsoftUNIXFortran)||defined(AbsoftProFortran)) #define COMMON_BLOCK(UN,LN) CFC_(UN,LN) #else #define COMMON_BLOCK(UN,LN) _(_C,LN) #endif /* AbsoftUNIXFortran or AbsoftProFortran */ #else #define COMMON_BLOCK(UN,LN) _(LN,__) #endif /* CLIPPERFortran */ #else #define COMMON_BLOCK(UN,LN) _3(_,LN,_) #endif /* CONVEXFortran */ #endif /* COMMON_BLOCK */ #ifndef DOUBLE_PRECISION #if defined(CRAYFortran) && !defined(_CRAYT3E) #define DOUBLE_PRECISION long double #else #define DOUBLE_PRECISION double #endif #endif #ifndef FORTRAN_REAL #if defined(CRAYFortran) && defined(_CRAYT3E) #define FORTRAN_REAL double #else #define FORTRAN_REAL float #endif #endif #ifdef CRAYFortran #ifdef _CRAY #include #else #include "fortran.h" /* i.e. if crosscompiling assume user has file. */ #endif #define FLOATVVVVVVV_cfPP (FORTRAN_REAL *) /* Used for C calls FORTRAN. */ /* CRAY's double==float but CRAY says pointers to doubles and floats are diff.*/ #define VOIDP (void *) /* When FORTRAN calls C, we don't know if C routine arg.'s have been declared float *, or double *. */ #else #define FLOATVVVVVVV_cfPP #define VOIDP #endif #ifdef vmsFortran #if defined(vms) || defined(__vms) #include #else #include "descrip.h" /* i.e. if crosscompiling assume user has file. */ #endif #endif #ifdef sunFortran #if defined(sun) || defined(__sun) #include /* Sun's FLOATFUNCTIONTYPE, ASSIGNFLOAT, RETURNFLOAT. */ #else #include "math.h" /* i.e. if crosscompiling assume user has file. */ #endif /* At least starting with the default C compiler SC3.0.1 of SunOS 5.3, * FLOATFUNCTIONTYPE, ASSIGNFLOAT, RETURNFLOAT are not required and not in * , since sun C no longer promotes C float return values to doubles. * Therefore, only use them if defined. * Even if gcc is being used, assume that it exhibits the Sun C compiler * behavior in order to be able to use *.o from the Sun C compiler. * i.e. If FLOATFUNCTIONTYPE, etc. are in math.h, they required by gcc. */ #endif #ifndef apolloFortran #define COMMON_BLOCK_DEF(DEFINITION, NAME) extern DEFINITION NAME #define CF_NULL_PROTO #else /* HP doesn't understand #elif. */ /* Without ANSI prototyping, Apollo promotes float functions to double. */ /* Note that VAX/VMS, IBM, Mips choke on 'type function(...);' prototypes. */ #define CF_NULL_PROTO ... #ifndef __CF__APOLLO67 #define COMMON_BLOCK_DEF(DEFINITION, NAME) \ DEFINITION NAME __attribute((__section(NAME))) #else #define COMMON_BLOCK_DEF(DEFINITION, NAME) \ DEFINITION NAME #attribute[section(NAME)] #endif #endif #ifdef __cplusplus #undef CF_NULL_PROTO #define CF_NULL_PROTO ... #endif #ifndef USE_NEW_DELETE #ifdef __cplusplus #define USE_NEW_DELETE 1 #else #define USE_NEW_DELETE 0 #endif #endif #if USE_NEW_DELETE #define _cf_malloc(N) new char[N] #define _cf_free(P) delete[] P #else #define _cf_malloc(N) (char *)malloc(N) #define _cf_free(P) free(P) #endif #ifdef mipsFortran #define CF_DECLARE_GETARG int f77argc; char **f77argv #define CF_SET_GETARG(ARGC,ARGV) f77argc = ARGC; f77argv = ARGV #else #define CF_DECLARE_GETARG #define CF_SET_GETARG(ARGC,ARGV) #endif #ifdef OLD_VAXC /* Allow %CC-I-PARAMNOTUSED. */ #pragma standard #endif #define AcfCOMMA , #define AcfCOLON ; /*-------------------------------------------------------------------------*/ /* UTILITIES USED WITHIN CFORTRAN.H */ #define _cfMIN(A,B) (As) { /* Need this to handle NULL string.*/ while (e>s && *--e==t) {;} /* Don't follow t's past beginning. */ e[*e==t?0:1] = '\0'; /* Handle s[0]=t correctly. */ } return s; } /* kill_trailingn(s,t,e) will kill the trailing t's in string s. e normally points to the terminating '\0' of s, but may actually point to anywhere in s. s's new '\0' will be placed at e or earlier in order to remove any trailing t's. If es) { /* Watch out for neg. length string.*/ while (e>s && *--e==t){;} /* Don't follow t's past beginning. */ e[*e==t?0:1] = '\0'; /* Handle s[0]=t correctly. */ } return s; } /* Note the following assumes that any element which has t's to be chopped off, does indeed fill the entire element. */ #ifndef __CF__KnR static char *vkill_trailing(char* cstr, int elem_len, int sizeofcstr, char t) #else static char *vkill_trailing( cstr, elem_len, sizeofcstr, t) char* cstr; int elem_len; int sizeofcstr; char t; #endif { int i; for (i=0; i= 4.3 gives message: zow35> cc -c -DDECFortran cfortest.c cfe: Fatal: Out of memory: cfortest.c zow35> Old __hpux had the problem, but new 'HP-UX A.09.03 A 9000/735' is fine if using -Aa, otherwise we have a problem. */ #ifndef MAX_PREPRO_ARGS #if !defined(__GNUC__) && (defined(VAXUltrix) || defined(__CF__APOLLO67) || (defined(sun)&&!defined(__sun)) || defined(_CRAY) || defined(__ultrix__) || (defined(__hpux)&&defined(__CF__KnR))) #define MAX_PREPRO_ARGS 31 #else #define MAX_PREPRO_ARGS 99 #endif #endif #if defined(AbsoftUNIXFortran) || defined(AbsoftProFortran) /* In addition to explicit Absoft stuff, only Absoft requires: - DEFAULT coming from _cfSTR. DEFAULT could have been called e.g. INT, but keep it for clarity. - M term in CFARGT14 and CFARGT14FS. */ #define ABSOFT_cf1(T0) _(T0,_cfSTR)(0,ABSOFT1,0,0,0,0,0) #define ABSOFT_cf2(T0) _(T0,_cfSTR)(0,ABSOFT2,0,0,0,0,0) #define ABSOFT_cf3(T0) _(T0,_cfSTR)(0,ABSOFT3,0,0,0,0,0) #define DEFAULT_cfABSOFT1 #define LOGICAL_cfABSOFT1 #define STRING_cfABSOFT1 ,MAX_LEN_FORTRAN_FUNCTION_STRING #define DEFAULT_cfABSOFT2 #define LOGICAL_cfABSOFT2 #define STRING_cfABSOFT2 ,unsigned D0 #define DEFAULT_cfABSOFT3 #define LOGICAL_cfABSOFT3 #define STRING_cfABSOFT3 ,D0 #else #define ABSOFT_cf1(T0) #define ABSOFT_cf2(T0) #define ABSOFT_cf3(T0) #endif /* _Z introduced to cicumvent IBM and HP silly preprocessor warning. e.g. "Macro CFARGT14 invoked with a null argument." */ #define _Z #define CFARGT14S(S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ S(T1,1) S(T2,2) S(T3,3) S(T4,4) S(T5,5) S(T6,6) S(T7,7) \ S(T8,8) S(T9,9) S(TA,10) S(TB,11) S(TC,12) S(TD,13) S(TE,14) #define CFARGT27S(S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ S(T1,1) S(T2,2) S(T3,3) S(T4,4) S(T5,5) S(T6,6) S(T7,7) \ S(T8,8) S(T9,9) S(TA,10) S(TB,11) S(TC,12) S(TD,13) S(TE,14) \ S(TF,15) S(TG,16) S(TH,17) S(TI,18) S(TJ,19) S(TK,20) S(TL,21) \ S(TM,22) S(TN,23) S(TO,24) S(TP,25) S(TQ,26) S(TR,27) #define CFARGT14FS(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ F(T1,1,0) F(T2,2,1) F(T3,3,1) F(T4,4,1) F(T5,5,1) F(T6,6,1) F(T7,7,1) \ F(T8,8,1) F(T9,9,1) F(TA,10,1) F(TB,11,1) F(TC,12,1) F(TD,13,1) F(TE,14,1) \ M CFARGT14S(S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) #define CFARGT27FS(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ F(T1,1,0) F(T2,2,1) F(T3,3,1) F(T4,4,1) F(T5,5,1) F(T6,6,1) F(T7,7,1) \ F(T8,8,1) F(T9,9,1) F(TA,10,1) F(TB,11,1) F(TC,12,1) F(TD,13,1) F(TE,14,1) \ F(TF,15,1) F(TG,16,1) F(TH,17,1) F(TI,18,1) F(TJ,19,1) F(TK,20,1) F(TL,21,1) \ F(TM,22,1) F(TN,23,1) F(TO,24,1) F(TP,25,1) F(TQ,26,1) F(TR,27,1) \ M CFARGT27S(S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) #if !(defined(PowerStationFortran)||defined(hpuxFortran800)) /* Old CFARGT14 -> CFARGT14FS as seen below, for Absoft cross-compile yields: SunOS> cc -c -Xa -DAbsoftUNIXFortran c.c "c.c", line 406: warning: argument mismatch Haven't checked if this is ANSI C or a SunOS bug. SunOS -Xs works ok. Behavior is most clearly seen in example: #define A 1 , 2 #define C(X,Y,Z) x=X. y=Y. z=Z. #define D(X,Y,Z) C(X,Y,Z) D(x,A,z) Output from preprocessor is: x = x . y = 1 . z = 2 . #define CFARGT14(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ CFARGT14FS(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) */ #define CFARGT14(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ F(T1,1,0) F(T2,2,1) F(T3,3,1) F(T4,4,1) F(T5,5,1) F(T6,6,1) F(T7,7,1) \ F(T8,8,1) F(T9,9,1) F(TA,10,1) F(TB,11,1) F(TC,12,1) F(TD,13,1) F(TE,14,1) \ M CFARGT14S(S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) #define CFARGT27(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ F(T1,1,0) F(T2,2,1) F(T3,3,1) F(T4,4,1) F(T5,5,1) F(T6,6,1) F(T7,7,1) \ F(T8,8,1) F(T9,9,1) F(TA,10,1) F(TB,11,1) F(TC,12,1) F(TD,13,1) F(TE,14,1) \ F(TF,15,1) F(TG,16,1) F(TH,17,1) F(TI,18,1) F(TJ,19,1) F(TK,20,1) F(TL,21,1) \ F(TM,22,1) F(TN,23,1) F(TO,24,1) F(TP,25,1) F(TQ,26,1) F(TR,27,1) \ M CFARGT27S(S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) #define CFARGT20(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) \ F(T1,1,0) F(T2,2,1) F(T3,3,1) F(T4,4,1) F(T5,5,1) F(T6,6,1) F(T7,7,1) \ F(T8,8,1) F(T9,9,1) F(TA,10,1) F(TB,11,1) F(TC,12,1) F(TD,13,1) F(TE,14,1) \ F(TF,15,1) F(TG,16,1) F(TH,17,1) F(TI,18,1) F(TJ,19,1) F(TK,20,1) \ S(T1,1) S(T2,2) S(T3,3) S(T4,4) S(T5,5) S(T6,6) S(T7,7) \ S(T8,8) S(T9,9) S(TA,10) S(TB,11) S(TC,12) S(TD,13) S(TE,14) \ S(TF,15) S(TG,16) S(TH,17) S(TI,18) S(TJ,19) S(TK,20) #define CFARGTA14(F,S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE) \ F(T1,A1,1,0) F(T2,A2,2,1) F(T3,A3,3,1) F(T4,A4,4,1) F(T5,A5,5,1) F(T6,A6,6,1) \ F(T7,A7,7,1) F(T8,A8,8,1) F(T9,A9,9,1) F(TA,AA,10,1) F(TB,AB,11,1) F(TC,AC,12,1) \ F(TD,AD,13,1) F(TE,AE,14,1) S(T1,1) S(T2,2) S(T3,3) S(T4,4) \ S(T5,5) S(T6,6) S(T7,7) S(T8,8) S(T9,9) S(TA,10) \ S(TB,11) S(TC,12) S(TD,13) S(TE,14) #if MAX_PREPRO_ARGS>31 #define CFARGTA20(F,S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK) \ F(T1,A1,1,0) F(T2,A2,2,1) F(T3,A3,3,1) F(T4,A4,4,1) F(T5,A5,5,1) F(T6,A6,6,1) \ F(T7,A7,7,1) F(T8,A8,8,1) F(T9,A9,9,1) F(TA,AA,10,1) F(TB,AB,11,1) F(TC,AC,12,1) \ F(TD,AD,13,1) F(TE,AE,14,1) F(TF,AF,15,1) F(TG,AG,16,1) F(TH,AH,17,1) F(TI,AI,18,1) \ F(TJ,AJ,19,1) F(TK,AK,20,1) S(T1,1) S(T2,2) S(T3,3) S(T4,4) \ S(T5,5) S(T6,6) S(T7,7) S(T8,8) S(T9,9) S(TA,10) \ S(TB,11) S(TC,12) S(TD,13) S(TE,14) S(TF,15) S(TG,16) \ S(TH,17) S(TI,18) S(TJ,19) S(TK,20) #define CFARGTA27(F,S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR) \ F(T1,A1,1,0) F(T2,A2,2,1) F(T3,A3,3,1) F(T4,A4,4,1) F(T5,A5,5,1) F(T6,A6,6,1) \ F(T7,A7,7,1) F(T8,A8,8,1) F(T9,A9,9,1) F(TA,AA,10,1) F(TB,AB,11,1) F(TC,AC,12,1) \ F(TD,AD,13,1) F(TE,AE,14,1) F(TF,AF,15,1) F(TG,AG,16,1) F(TH,AH,17,1) F(TI,AI,18,1) \ F(TJ,AJ,19,1) F(TK,AK,20,1) F(TL,AL,21,1) F(TM,AM,22,1) F(TN,AN,23,1) F(TO,AO,24,1) \ F(TP,AP,25,1) F(TQ,AQ,26,1) F(TR,AR,27,1) S(T1,1) S(T2,2) S(T3,3) \ S(T4,4) S(T5,5) S(T6,6) S(T7,7) S(T8,8) S(T9,9) \ S(TA,10) S(TB,11) S(TC,12) S(TD,13) S(TE,14) S(TF,15) \ S(TG,16) S(TH,17) S(TI,18) S(TJ,19) S(TK,20) S(TL,21) \ S(TM,22) S(TN,23) S(TO,24) S(TP,25) S(TQ,26) S(TR,27) #endif #else #define CFARGT14(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ F(T1,1,0) S(T1,1) F(T2,2,1) S(T2,2) F(T3,3,1) S(T3,3) F(T4,4,1) S(T4,4) \ F(T5,5,1) S(T5,5) F(T6,6,1) S(T6,6) F(T7,7,1) S(T7,7) F(T8,8,1) S(T8,8) \ F(T9,9,1) S(T9,9) F(TA,10,1) S(TA,10) F(TB,11,1) S(TB,11) F(TC,12,1) S(TC,12) \ F(TD,13,1) S(TD,13) F(TE,14,1) S(TE,14) #define CFARGT27(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ F(T1,1,0) S(T1,1) F(T2,2,1) S(T2,2) F(T3,3,1) S(T3,3) F(T4,4,1) S(T4,4) \ F(T5,5,1) S(T5,5) F(T6,6,1) S(T6,6) F(T7,7,1) S(T7,7) F(T8,8,1) S(T8,8) \ F(T9,9,1) S(T9,9) F(TA,10,1) S(TA,10) F(TB,11,1) S(TB,11) F(TC,12,1) S(TC,12) \ F(TD,13,1) S(TD,13) F(TE,14,1) S(TE,14) F(TF,15,1) S(TF,15) F(TG,16,1) S(TG,16) \ F(TH,17,1) S(TH,17) F(TI,18,1) S(TI,18) F(TJ,19,1) S(TJ,19) F(TK,20,1) S(TK,20) \ F(TL,21,1) S(TL,21) F(TM,22,1) S(TM,22) F(TN,23,1) S(TN,23) F(TO,24,1) S(TO,24) \ F(TP,25,1) S(TP,25) F(TQ,26,1) S(TQ,26) F(TR,27,1) S(TR,27) #define CFARGT20(F,S,M,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) \ F(T1,1,0) S(T1,1) F(T2,2,1) S(T2,2) F(T3,3,1) S(T3,3) F(T4,4,1) S(T4,4) \ F(T5,5,1) S(T5,5) F(T6,6,1) S(T6,6) F(T7,7,1) S(T7,7) F(T8,8,1) S(T8,8) \ F(T9,9,1) S(T9,9) F(TA,10,1) S(TA,10) F(TB,11,1) S(TB,11) F(TC,12,1) S(TC,12) \ F(TD,13,1) S(TD,13) F(TE,14,1) S(TE,14) F(TF,15,1) S(TF,15) F(TG,16,1) S(TG,16) \ F(TH,17,1) S(TH,17) F(TI,18,1) S(TI,18) F(TJ,19,1) S(TJ,19) F(TK,20,1) S(TK,20) #define CFARGTA14(F,S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE) \ F(T1,A1,1,0) S(T1,1) F(T2,A2,2,1) S(T2,2) F(T3,A3,3,1) S(T3,3) \ F(T4,A4,4,1) S(T4,4) F(T5,A5,5,1) S(T5,5) F(T6,A6,6,1) S(T6,6) \ F(T7,A7,7,1) S(T7,7) F(T8,A8,8,1) S(T8,8) F(T9,A9,9,1) S(T9,9) \ F(TA,AA,10,1) S(TA,10) F(TB,AB,11,1) S(TB,11) F(TC,AC,12,1) S(TC,12) \ F(TD,AD,13,1) S(TD,13) F(TE,AE,14,1) S(TE,14) #if MAX_PREPRO_ARGS>31 #define CFARGTA20(F,S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK) \ F(T1,A1,1,0) S(T1,1) F(T2,A2,2,1) S(T2,2) F(T3,A3,3,1) S(T3,3) \ F(T4,A4,4,1) S(T4,4) F(T5,A5,5,1) S(T5,5) F(T6,A6,6,1) S(T6,6) \ F(T7,A7,7,1) S(T7,7) F(T8,A8,8,1) S(T8,8) F(T9,A9,9,1) S(T9,9) \ F(TA,AA,10,1) S(TA,10) F(TB,AB,11,1) S(TB,11) F(TC,AC,12,1) S(TC,12) \ F(TD,AD,13,1) S(TD,13) F(TE,AE,14,1) S(TE,14) F(TF,AF,15,1) S(TF,15) \ F(TG,AG,16,1) S(TG,16) F(TH,AH,17,1) S(TH,17) F(TI,AI,18,1) S(TI,18) \ F(TJ,AJ,19,1) S(TJ,19) F(TK,AK,20,1) S(TK,20) #define CFARGTA27(F,S,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR) \ F(T1,A1,1,0) S(T1,1) F(T2,A2,2,1) S(T2,2) F(T3,A3,3,1) S(T3,3) \ F(T4,A4,4,1) S(T4,4) F(T5,A5,5,1) S(T5,5) F(T6,A6,6,1) S(T6,6) \ F(T7,A7,7,1) S(T7,7) F(T8,A8,8,1) S(T8,8) F(T9,A9,9,1) S(T9,9) \ F(TA,AA,10,1) S(TA,10) F(TB,AB,11,1) S(TB,11) F(TC,AC,12,1) S(TC,12) \ F(TD,AD,13,1) S(TD,13) F(TE,AE,14,1) S(TE,14) F(TF,AF,15,1) S(TF,15) \ F(TG,AG,16,1) S(TG,16) F(TH,AH,17,1) S(TH,17) F(TI,AI,18,1) S(TI,18) \ F(TJ,AJ,19,1) S(TJ,19) F(TK,AK,20,1) S(TK,20) F(TL,AL,21,1) S(TL,21) \ F(TM,AM,22,1) S(TM,22) F(TN,AN,23,1) S(TN,23) F(TO,AO,24,1) S(TO,24) \ F(TP,AP,25,1) S(TP,25) F(TQ,AQ,26,1) S(TQ,26) F(TR,AR,27,1) S(TR,27) #endif #endif #define PROTOCCALLSFSUB1( UN,LN,T1) \ PROTOCCALLSFSUB14(UN,LN,T1,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB2( UN,LN,T1,T2) \ PROTOCCALLSFSUB14(UN,LN,T1,T2,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB3( UN,LN,T1,T2,T3) \ PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB4( UN,LN,T1,T2,T3,T4) \ PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB5( UN,LN,T1,T2,T3,T4,T5) \ PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB6( UN,LN,T1,T2,T3,T4,T5,T6) \ PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB7( UN,LN,T1,T2,T3,T4,T5,T6,T7) \ PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB8( UN,LN,T1,T2,T3,T4,T5,T6,T7,T8) \ PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB9( UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9) \ PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,CF_0,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB10(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA) \ PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB11(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB) \ PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB12(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC) \ PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,CF_0,CF_0) #define PROTOCCALLSFSUB13(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD) \ PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,CF_0) #define PROTOCCALLSFSUB15(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF) \ PROTOCCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,CF_0,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB16(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG) \ PROTOCCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB17(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH) \ PROTOCCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB18(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI) \ PROTOCCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,CF_0,CF_0) #define PROTOCCALLSFSUB19(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ) \ PROTOCCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,CF_0) #define PROTOCCALLSFSUB21(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL) \ PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB22(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM) \ PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,CF_0,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB23(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN) \ PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB24(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO) \ PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,CF_0,CF_0,CF_0) #define PROTOCCALLSFSUB25(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP) \ PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,CF_0,CF_0) #define PROTOCCALLSFSUB26(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ) \ PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,CF_0) #ifndef FCALLSC_QUALIFIER #ifdef VISUAL_CPLUSPLUS #define FCALLSC_QUALIFIER __stdcall #else #define FCALLSC_QUALIFIER #endif #endif #ifdef __cplusplus #define CFextern extern "C" #else #define CFextern extern #endif #ifdef CFSUBASFUN #define PROTOCCALLSFSUB0(UN,LN) \ PROTOCCALLSFFUN0( VOID,UN,LN) #define PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ PROTOCCALLSFFUN14(VOID,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) #define PROTOCCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK)\ PROTOCCALLSFFUN20(VOID,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) #define PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR)\ PROTOCCALLSFFUN27(VOID,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) #else /* Note: Prevent compiler warnings, null #define PROTOCCALLSFSUB14/20 after #include-ing cfortran.h if calling the FORTRAN wrapper within the same source code where the wrapper is created. */ #define PROTOCCALLSFSUB0(UN,LN) _(VOID,_cfPU)(CFC_(UN,LN))(); #ifndef __CF__KnR #define PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ _(VOID,_cfPU)(CFC_(UN,LN))( CFARGT14(NCF,KCF,_Z,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) ); #define PROTOCCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK)\ _(VOID,_cfPU)(CFC_(UN,LN))( CFARGT20(NCF,KCF,_Z,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) ); #define PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR)\ _(VOID,_cfPU)(CFC_(UN,LN))( CFARGT27(NCF,KCF,_Z,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) ); #else #define PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ PROTOCCALLSFSUB0(UN,LN) #define PROTOCCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) \ PROTOCCALLSFSUB0(UN,LN) #define PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ PROTOCCALLSFSUB0(UN,LN) #endif #endif #ifdef OLD_VAXC /* Allow %CC-I-PARAMNOTUSED. */ #pragma standard #endif #define CCALLSFSUB1( UN,LN,T1, A1) \ CCALLSFSUB5 (UN,LN,T1,CF_0,CF_0,CF_0,CF_0,A1,0,0,0,0) #define CCALLSFSUB2( UN,LN,T1,T2, A1,A2) \ CCALLSFSUB5 (UN,LN,T1,T2,CF_0,CF_0,CF_0,A1,A2,0,0,0) #define CCALLSFSUB3( UN,LN,T1,T2,T3, A1,A2,A3) \ CCALLSFSUB5 (UN,LN,T1,T2,T3,CF_0,CF_0,A1,A2,A3,0,0) #define CCALLSFSUB4( UN,LN,T1,T2,T3,T4, A1,A2,A3,A4)\ CCALLSFSUB5 (UN,LN,T1,T2,T3,T4,CF_0,A1,A2,A3,A4,0) #define CCALLSFSUB5( UN,LN,T1,T2,T3,T4,T5, A1,A2,A3,A4,A5) \ CCALLSFSUB10(UN,LN,T1,T2,T3,T4,T5,CF_0,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,0,0,0,0,0) #define CCALLSFSUB6( UN,LN,T1,T2,T3,T4,T5,T6, A1,A2,A3,A4,A5,A6) \ CCALLSFSUB10(UN,LN,T1,T2,T3,T4,T5,T6,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,0,0,0,0) #define CCALLSFSUB7( UN,LN,T1,T2,T3,T4,T5,T6,T7, A1,A2,A3,A4,A5,A6,A7) \ CCALLSFSUB10(UN,LN,T1,T2,T3,T4,T5,T6,T7,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,0,0,0) #define CCALLSFSUB8( UN,LN,T1,T2,T3,T4,T5,T6,T7,T8, A1,A2,A3,A4,A5,A6,A7,A8) \ CCALLSFSUB10(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,0,0) #define CCALLSFSUB9( UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,A1,A2,A3,A4,A5,A6,A7,A8,A9)\ CCALLSFSUB10(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,0) #define CCALLSFSUB10(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA)\ CCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,0,0,0,0) #define CCALLSFSUB11(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB)\ CCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,0,0,0) #define CCALLSFSUB12(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC)\ CCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,0,0) #define CCALLSFSUB13(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD)\ CCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,0) #ifdef __cplusplus #define CPPPROTOCLSFSUB0( UN,LN) #define CPPPROTOCLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) #define CPPPROTOCLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) #define CPPPROTOCLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) #else #define CPPPROTOCLSFSUB0(UN,LN) \ PROTOCCALLSFSUB0(UN,LN) #define CPPPROTOCLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ PROTOCCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) #define CPPPROTOCLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) \ PROTOCCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) #define CPPPROTOCLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ PROTOCCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) #endif #ifdef CFSUBASFUN #define CCALLSFSUB0(UN,LN) CCALLSFFUN0(UN,LN) #define CCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE)\ CCALLSFFUN14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE) #else /* do{...}while(0) allows if(a==b) FORT(); else BORT(); */ #define CCALLSFSUB0( UN,LN) do{CPPPROTOCLSFSUB0(UN,LN) CFC_(UN,LN)();}while(0) #define CCALLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE)\ do{VVCF(T1,A1,B1) VVCF(T2,A2,B2) VVCF(T3,A3,B3) VVCF(T4,A4,B4) VVCF(T5,A5,B5) \ VVCF(T6,A6,B6) VVCF(T7,A7,B7) VVCF(T8,A8,B8) VVCF(T9,A9,B9) VVCF(TA,AA,B10) \ VVCF(TB,AB,B11) VVCF(TC,AC,B12) VVCF(TD,AD,B13) VVCF(TE,AE,B14) \ CPPPROTOCLSFSUB14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ ACF(LN,T1,A1,1) ACF(LN,T2,A2,2) ACF(LN,T3,A3,3) \ ACF(LN,T4,A4,4) ACF(LN,T5,A5,5) ACF(LN,T6,A6,6) ACF(LN,T7,A7,7) \ ACF(LN,T8,A8,8) ACF(LN,T9,A9,9) ACF(LN,TA,AA,10) ACF(LN,TB,AB,11) \ ACF(LN,TC,AC,12) ACF(LN,TD,AD,13) ACF(LN,TE,AE,14) \ CFC_(UN,LN)( CFARGTA14(AACF,JCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE) );\ WCF(T1,A1,1) WCF(T2,A2,2) WCF(T3,A3,3) WCF(T4,A4,4) WCF(T5,A5,5) \ WCF(T6,A6,6) WCF(T7,A7,7) WCF(T8,A8,8) WCF(T9,A9,9) WCF(TA,AA,10) \ WCF(TB,AB,11) WCF(TC,AC,12) WCF(TD,AD,13) WCF(TE,AE,14) }while(0) #endif #if MAX_PREPRO_ARGS>31 #define CCALLSFSUB15(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF)\ CCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,CF_0,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,0,0,0,0,0) #define CCALLSFSUB16(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG)\ CCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,0,0,0,0) #define CCALLSFSUB17(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH)\ CCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,0,0,0) #define CCALLSFSUB18(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI)\ CCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,0,0) #define CCALLSFSUB19(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ)\ CCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,0) #ifdef CFSUBASFUN #define CCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH, \ TI,TJ,TK, A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK) \ CCALLSFFUN20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH, \ TI,TJ,TK, A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK) #else #define CCALLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH, \ TI,TJ,TK, A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK) \ do{VVCF(T1,A1,B1) VVCF(T2,A2,B2) VVCF(T3,A3,B3) VVCF(T4,A4,B4) VVCF(T5,A5,B5) \ VVCF(T6,A6,B6) VVCF(T7,A7,B7) VVCF(T8,A8,B8) VVCF(T9,A9,B9) VVCF(TA,AA,B10) \ VVCF(TB,AB,B11) VVCF(TC,AC,B12) VVCF(TD,AD,B13) VVCF(TE,AE,B14) VVCF(TF,AF,B15) \ VVCF(TG,AG,B16) VVCF(TH,AH,B17) VVCF(TI,AI,B18) VVCF(TJ,AJ,B19) VVCF(TK,AK,B20) \ CPPPROTOCLSFSUB20(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) \ ACF(LN,T1,A1,1) ACF(LN,T2,A2,2) ACF(LN,T3,A3,3) ACF(LN,T4,A4,4) \ ACF(LN,T5,A5,5) ACF(LN,T6,A6,6) ACF(LN,T7,A7,7) ACF(LN,T8,A8,8) \ ACF(LN,T9,A9,9) ACF(LN,TA,AA,10) ACF(LN,TB,AB,11) ACF(LN,TC,AC,12) \ ACF(LN,TD,AD,13) ACF(LN,TE,AE,14) ACF(LN,TF,AF,15) ACF(LN,TG,AG,16) \ ACF(LN,TH,AH,17) ACF(LN,TI,AI,18) ACF(LN,TJ,AJ,19) ACF(LN,TK,AK,20) \ CFC_(UN,LN)( CFARGTA20(AACF,JCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK) ); \ WCF(T1,A1,1) WCF(T2,A2,2) WCF(T3,A3,3) WCF(T4,A4,4) WCF(T5,A5,5) WCF(T6,A6,6) \ WCF(T7,A7,7) WCF(T8,A8,8) WCF(T9,A9,9) WCF(TA,AA,10) WCF(TB,AB,11) WCF(TC,AC,12) \ WCF(TD,AD,13) WCF(TE,AE,14) WCF(TF,AF,15) WCF(TG,AG,16) WCF(TH,AH,17) WCF(TI,AI,18) \ WCF(TJ,AJ,19) WCF(TK,AK,20) }while(0) #endif #endif /* MAX_PREPRO_ARGS */ #if MAX_PREPRO_ARGS>31 #define CCALLSFSUB21(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL)\ CCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,0,0,0,0,0,0) #define CCALLSFSUB22(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM)\ CCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,CF_0,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,0,0,0,0,0) #define CCALLSFSUB23(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN)\ CCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,0,0,0,0) #define CCALLSFSUB24(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO)\ CCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,0,0,0) #define CCALLSFSUB25(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP)\ CCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,0,0) #define CCALLSFSUB26(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ)\ CCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,0) #ifdef CFSUBASFUN #define CCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR, \ A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR) \ CCALLSFFUN27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR, \ A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR) #else #define CCALLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR, \ A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR) \ do{VVCF(T1,A1,B1) VVCF(T2,A2,B2) VVCF(T3,A3,B3) VVCF(T4,A4,B4) VVCF(T5,A5,B5) \ VVCF(T6,A6,B6) VVCF(T7,A7,B7) VVCF(T8,A8,B8) VVCF(T9,A9,B9) VVCF(TA,AA,B10) \ VVCF(TB,AB,B11) VVCF(TC,AC,B12) VVCF(TD,AD,B13) VVCF(TE,AE,B14) VVCF(TF,AF,B15) \ VVCF(TG,AG,B16) VVCF(TH,AH,B17) VVCF(TI,AI,B18) VVCF(TJ,AJ,B19) VVCF(TK,AK,B20) \ VVCF(TL,AL,B21) VVCF(TM,AM,B22) VVCF(TN,AN,B23) VVCF(TO,AO,B24) VVCF(TP,AP,B25) \ VVCF(TQ,AQ,B26) VVCF(TR,AR,B27) \ CPPPROTOCLSFSUB27(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ ACF(LN,T1,A1,1) ACF(LN,T2,A2,2) ACF(LN,T3,A3,3) ACF(LN,T4,A4,4) \ ACF(LN,T5,A5,5) ACF(LN,T6,A6,6) ACF(LN,T7,A7,7) ACF(LN,T8,A8,8) \ ACF(LN,T9,A9,9) ACF(LN,TA,AA,10) ACF(LN,TB,AB,11) ACF(LN,TC,AC,12) \ ACF(LN,TD,AD,13) ACF(LN,TE,AE,14) ACF(LN,TF,AF,15) ACF(LN,TG,AG,16) \ ACF(LN,TH,AH,17) ACF(LN,TI,AI,18) ACF(LN,TJ,AJ,19) ACF(LN,TK,AK,20) \ ACF(LN,TL,AL,21) ACF(LN,TM,AM,22) ACF(LN,TN,AN,23) ACF(LN,TO,AO,24) \ ACF(LN,TP,AP,25) ACF(LN,TQ,AQ,26) ACF(LN,TR,AR,27) \ CFC_(UN,LN)( CFARGTA27(AACF,JCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR,\ A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR) ); \ WCF(T1,A1,1) WCF(T2,A2,2) WCF(T3,A3,3) WCF(T4,A4,4) WCF(T5,A5,5) WCF(T6,A6,6) \ WCF(T7,A7,7) WCF(T8,A8,8) WCF(T9,A9,9) WCF(TA,AA,10) WCF(TB,AB,11) WCF(TC,AC,12) \ WCF(TD,AD,13) WCF(TE,AE,14) WCF(TF,AF,15) WCF(TG,AG,16) WCF(TH,AH,17) WCF(TI,AI,18) \ WCF(TJ,AJ,19) WCF(TK,AK,20) WCF(TL,AL,21) WCF(TM,AM,22) WCF(TN,AN,23) WCF(TO,AO,24) \ WCF(TP,AP,25) WCF(TQ,AQ,26) WCF(TR,AR,27) }while(0) #endif #endif /* MAX_PREPRO_ARGS */ /*-------------------------------------------------------------------------*/ /* UTILITIES FOR C TO CALL FORTRAN FUNCTIONS */ /*N.B. PROTOCCALLSFFUNn(..) generates code, whether or not the FORTRAN function is called. Therefore, especially for creator's of C header files for large FORTRAN libraries which include many functions, to reduce compile time and object code size, it may be desirable to create preprocessor directives to allow users to create code for only those functions which they use. */ /* The following defines the maximum length string that a function can return. Of course it may be undefine-d and re-define-d before individual PROTOCCALLSFFUNn(..) as required. It would also be nice to have this derived from the individual machines' limits. */ #define MAX_LEN_FORTRAN_FUNCTION_STRING 0x4FE /* The following defines a character used by CFORTRAN.H to flag the end of a string coming out of a FORTRAN routine. */ #define CFORTRAN_NON_CHAR 0x7F #ifdef OLD_VAXC /* Prevent %CC-I-PARAMNOTUSED. */ #pragma nostandard #endif #define _SEP_(TN,C,cfCOMMA) _(__SEP_,C)(TN,cfCOMMA) #define __SEP_0(TN,cfCOMMA) #define __SEP_1(TN,cfCOMMA) _Icf(2,SEP,TN,cfCOMMA,0) #define INT_cfSEP(T,B) _(A,B) #define INTV_cfSEP(T,B) INT_cfSEP(T,B) #define INTVV_cfSEP(T,B) INT_cfSEP(T,B) #define INTVVV_cfSEP(T,B) INT_cfSEP(T,B) #define INTVVVV_cfSEP(T,B) INT_cfSEP(T,B) #define INTVVVVV_cfSEP(T,B) INT_cfSEP(T,B) #define INTVVVVVV_cfSEP(T,B) INT_cfSEP(T,B) #define INTVVVVVVV_cfSEP(T,B) INT_cfSEP(T,B) #define PINT_cfSEP(T,B) INT_cfSEP(T,B) #define PVOID_cfSEP(T,B) INT_cfSEP(T,B) #define ROUTINE_cfSEP(T,B) INT_cfSEP(T,B) #define SIMPLE_cfSEP(T,B) INT_cfSEP(T,B) #define VOID_cfSEP(T,B) INT_cfSEP(T,B) /* For FORTRAN calls C subr.s.*/ #define STRING_cfSEP(T,B) INT_cfSEP(T,B) #define STRINGV_cfSEP(T,B) INT_cfSEP(T,B) #define PSTRING_cfSEP(T,B) INT_cfSEP(T,B) #define PSTRINGV_cfSEP(T,B) INT_cfSEP(T,B) #define PNSTRING_cfSEP(T,B) INT_cfSEP(T,B) #define PPSTRING_cfSEP(T,B) INT_cfSEP(T,B) #define ZTRINGV_cfSEP(T,B) INT_cfSEP(T,B) #define PZTRINGV_cfSEP(T,B) INT_cfSEP(T,B) #if defined(SIGNED_BYTE) || !defined(UNSIGNED_BYTE) #ifdef OLD_VAXC #define INTEGER_BYTE char /* Old VAXC barfs on 'signed char' */ #else #define INTEGER_BYTE signed char /* default */ #endif #else #define INTEGER_BYTE unsigned char #endif #define BYTEVVVVVVV_cfTYPE INTEGER_BYTE #define DOUBLEVVVVVVV_cfTYPE DOUBLE_PRECISION #define FLOATVVVVVVV_cfTYPE FORTRAN_REAL #define INTVVVVVVV_cfTYPE int #define LOGICALVVVVVVV_cfTYPE int #define LONGVVVVVVV_cfTYPE long #define LONGLONGVVVVVVV_cfTYPE LONGLONG /* added by MR December 2005 */ #define SHORTVVVVVVV_cfTYPE short #define PBYTE_cfTYPE INTEGER_BYTE #define PDOUBLE_cfTYPE DOUBLE_PRECISION #define PFLOAT_cfTYPE FORTRAN_REAL #define PINT_cfTYPE int #define PLOGICAL_cfTYPE int #define PLONG_cfTYPE long #define PLONGLONG_cfTYPE LONGLONG /* added by MR December 2005 */ #define PSHORT_cfTYPE short #define CFARGS0(A,T,V,W,X,Y,Z) _3(T,_cf,A) #define CFARGS1(A,T,V,W,X,Y,Z) _3(T,_cf,A)(V) #define CFARGS2(A,T,V,W,X,Y,Z) _3(T,_cf,A)(V,W) #define CFARGS3(A,T,V,W,X,Y,Z) _3(T,_cf,A)(V,W,X) #define CFARGS4(A,T,V,W,X,Y,Z) _3(T,_cf,A)(V,W,X,Y) #define CFARGS5(A,T,V,W,X,Y,Z) _3(T,_cf,A)(V,W,X,Y,Z) #define _Icf(N,T,I,X,Y) _(I,_cfINT)(N,T,I,X,Y,0) #define _Icf4(N,T,I,X,Y,Z) _(I,_cfINT)(N,T,I,X,Y,Z) #define BYTE_cfINT(N,A,B,X,Y,Z) DOUBLE_cfINT(N,A,B,X,Y,Z) #define DOUBLE_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,INT,B,X,Y,Z,0) #define FLOAT_cfINT(N,A,B,X,Y,Z) DOUBLE_cfINT(N,A,B,X,Y,Z) #define INT_cfINT(N,A,B,X,Y,Z) DOUBLE_cfINT(N,A,B,X,Y,Z) #define LOGICAL_cfINT(N,A,B,X,Y,Z) DOUBLE_cfINT(N,A,B,X,Y,Z) #define LONG_cfINT(N,A,B,X,Y,Z) DOUBLE_cfINT(N,A,B,X,Y,Z) #define LONGLONG_cfINT(N,A,B,X,Y,Z) DOUBLE_cfINT(N,A,B,X,Y,Z) /* added by MR December 2005 */ #define SHORT_cfINT(N,A,B,X,Y,Z) DOUBLE_cfINT(N,A,B,X,Y,Z) #define PBYTE_cfINT(N,A,B,X,Y,Z) PDOUBLE_cfINT(N,A,B,X,Y,Z) #define PDOUBLE_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,PINT,B,X,Y,Z,0) #define PFLOAT_cfINT(N,A,B,X,Y,Z) PDOUBLE_cfINT(N,A,B,X,Y,Z) #define PINT_cfINT(N,A,B,X,Y,Z) PDOUBLE_cfINT(N,A,B,X,Y,Z) #define PLOGICAL_cfINT(N,A,B,X,Y,Z) PDOUBLE_cfINT(N,A,B,X,Y,Z) #define PLONG_cfINT(N,A,B,X,Y,Z) PDOUBLE_cfINT(N,A,B,X,Y,Z) #define PLONGLONG_cfINT(N,A,B,X,Y,Z) PDOUBLE_cfINT(N,A,B,X,Y,Z) /* added by MR December 2005 */ #define PSHORT_cfINT(N,A,B,X,Y,Z) PDOUBLE_cfINT(N,A,B,X,Y,Z) #define BYTEV_cfINT(N,A,B,X,Y,Z) DOUBLEV_cfINT(N,A,B,X,Y,Z) #define BYTEVV_cfINT(N,A,B,X,Y,Z) DOUBLEVV_cfINT(N,A,B,X,Y,Z) #define BYTEVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVV_cfINT(N,A,B,X,Y,Z) #define BYTEVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVV_cfINT(N,A,B,X,Y,Z) #define BYTEVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVV_cfINT(N,A,B,X,Y,Z) #define BYTEVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVV_cfINT(N,A,B,X,Y,Z) #define BYTEVVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVVV_cfINT(N,A,B,X,Y,Z) #define DOUBLEV_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,INTV,B,X,Y,Z,0) #define DOUBLEVV_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,INTVV,B,X,Y,Z,0) #define DOUBLEVVV_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,INTVVV,B,X,Y,Z,0) #define DOUBLEVVVV_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,INTVVVV,B,X,Y,Z,0) #define DOUBLEVVVVV_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,INTVVVVV,B,X,Y,Z,0) #define DOUBLEVVVVVV_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,INTVVVVVV,B,X,Y,Z,0) #define DOUBLEVVVVVVV_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,INTVVVVVVV,B,X,Y,Z,0) #define FLOATV_cfINT(N,A,B,X,Y,Z) DOUBLEV_cfINT(N,A,B,X,Y,Z) #define FLOATVV_cfINT(N,A,B,X,Y,Z) DOUBLEVV_cfINT(N,A,B,X,Y,Z) #define FLOATVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVV_cfINT(N,A,B,X,Y,Z) #define FLOATVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVV_cfINT(N,A,B,X,Y,Z) #define FLOATVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVV_cfINT(N,A,B,X,Y,Z) #define FLOATVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVV_cfINT(N,A,B,X,Y,Z) #define FLOATVVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVVV_cfINT(N,A,B,X,Y,Z) #define INTV_cfINT(N,A,B,X,Y,Z) DOUBLEV_cfINT(N,A,B,X,Y,Z) #define INTVV_cfINT(N,A,B,X,Y,Z) DOUBLEVV_cfINT(N,A,B,X,Y,Z) #define INTVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVV_cfINT(N,A,B,X,Y,Z) #define INTVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVV_cfINT(N,A,B,X,Y,Z) #define INTVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVV_cfINT(N,A,B,X,Y,Z) #define INTVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVV_cfINT(N,A,B,X,Y,Z) #define INTVVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVVV_cfINT(N,A,B,X,Y,Z) #define LOGICALV_cfINT(N,A,B,X,Y,Z) DOUBLEV_cfINT(N,A,B,X,Y,Z) #define LOGICALVV_cfINT(N,A,B,X,Y,Z) DOUBLEVV_cfINT(N,A,B,X,Y,Z) #define LOGICALVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVV_cfINT(N,A,B,X,Y,Z) #define LOGICALVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVV_cfINT(N,A,B,X,Y,Z) #define LOGICALVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVV_cfINT(N,A,B,X,Y,Z) #define LOGICALVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVV_cfINT(N,A,B,X,Y,Z) #define LOGICALVVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVVV_cfINT(N,A,B,X,Y,Z) #define LONGV_cfINT(N,A,B,X,Y,Z) DOUBLEV_cfINT(N,A,B,X,Y,Z) #define LONGVV_cfINT(N,A,B,X,Y,Z) DOUBLEVV_cfINT(N,A,B,X,Y,Z) #define LONGVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVV_cfINT(N,A,B,X,Y,Z) #define LONGVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVV_cfINT(N,A,B,X,Y,Z) #define LONGVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVV_cfINT(N,A,B,X,Y,Z) #define LONGVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVV_cfINT(N,A,B,X,Y,Z) #define LONGVVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVVV_cfINT(N,A,B,X,Y,Z) #define LONGLONGV_cfINT(N,A,B,X,Y,Z) DOUBLEV_cfINT(N,A,B,X,Y,Z) /* added by MR December 2005 */ #define LONGLONGVV_cfINT(N,A,B,X,Y,Z) DOUBLEVV_cfINT(N,A,B,X,Y,Z) /* added by MR December 2005 */ #define LONGLONGVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVV_cfINT(N,A,B,X,Y,Z) /* added by MR December 2005 */ #define LONGLONGVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVV_cfINT(N,A,B,X,Y,Z) /* added by MR December 2005 */ #define LONGLONGVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVV_cfINT(N,A,B,X,Y,Z) /* added by MR December 2005 */ #define LONGLONGVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVV_cfINT(N,A,B,X,Y,Z) /* added by MR December 2005 */ #define LONGLONGVVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVVV_cfINT(N,A,B,X,Y,Z) /* added by MR December 2005 */ #define SHORTV_cfINT(N,A,B,X,Y,Z) DOUBLEV_cfINT(N,A,B,X,Y,Z) #define SHORTVV_cfINT(N,A,B,X,Y,Z) DOUBLEVV_cfINT(N,A,B,X,Y,Z) #define SHORTVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVV_cfINT(N,A,B,X,Y,Z) #define SHORTVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVV_cfINT(N,A,B,X,Y,Z) #define SHORTVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVV_cfINT(N,A,B,X,Y,Z) #define SHORTVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVV_cfINT(N,A,B,X,Y,Z) #define SHORTVVVVVVV_cfINT(N,A,B,X,Y,Z) DOUBLEVVVVVVV_cfINT(N,A,B,X,Y,Z) #define PVOID_cfINT(N,A,B,X,Y,Z) _(CFARGS,N)(A,B,B,X,Y,Z,0) #define ROUTINE_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) /*CRAY coughs on the first, i.e. the usual trouble of not being able to define macros to macros with arguments. New ultrix is worse, it coughs on all such uses. */ /*#define SIMPLE_cfINT PVOID_cfINT*/ #define SIMPLE_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) #define VOID_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) #define STRING_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) #define STRINGV_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) #define PSTRING_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) #define PSTRINGV_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) #define PNSTRING_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) #define PPSTRING_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) #define ZTRINGV_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) #define PZTRINGV_cfINT(N,A,B,X,Y,Z) PVOID_cfINT(N,A,B,X,Y,Z) #define CF_0_cfINT(N,A,B,X,Y,Z) #define UCF(TN,I,C) _SEP_(TN,C,cfCOMMA) _Icf(2,U,TN,_(A,I),0) #define UUCF(TN,I,C) _SEP_(TN,C,cfCOMMA) _SEP_(TN,1,I) #define UUUCF(TN,I,C) _SEP_(TN,C,cfCOLON) _Icf(2,U,TN,_(A,I),0) #define INT_cfU(T,A) _(T,VVVVVVV_cfTYPE) A #define INTV_cfU(T,A) _(T,VVVVVV_cfTYPE) * A #define INTVV_cfU(T,A) _(T,VVVVV_cfTYPE) * A #define INTVVV_cfU(T,A) _(T,VVVV_cfTYPE) * A #define INTVVVV_cfU(T,A) _(T,VVV_cfTYPE) * A #define INTVVVVV_cfU(T,A) _(T,VV_cfTYPE) * A #define INTVVVVVV_cfU(T,A) _(T,V_cfTYPE) * A #define INTVVVVVVV_cfU(T,A) _(T,_cfTYPE) * A #define PINT_cfU(T,A) _(T,_cfTYPE) * A #define PVOID_cfU(T,A) void *A #define ROUTINE_cfU(T,A) void (*A)(CF_NULL_PROTO) #define VOID_cfU(T,A) void A /* Needed for C calls FORTRAN sub.s. */ #define STRING_cfU(T,A) char *A /* via VOID and wrapper. */ #define STRINGV_cfU(T,A) char *A #define PSTRING_cfU(T,A) char *A #define PSTRINGV_cfU(T,A) char *A #define ZTRINGV_cfU(T,A) char *A #define PZTRINGV_cfU(T,A) char *A /* VOID breaks U into U and UU. */ #define INT_cfUU(T,A) _(T,VVVVVVV_cfTYPE) A #define VOID_cfUU(T,A) /* Needed for FORTRAN calls C sub.s. */ #define STRING_cfUU(T,A) char *A #define BYTE_cfPU(A) CFextern INTEGER_BYTE FCALLSC_QUALIFIER A #define DOUBLE_cfPU(A) CFextern DOUBLE_PRECISION FCALLSC_QUALIFIER A #if ! (defined(FLOATFUNCTIONTYPE)&&defined(ASSIGNFLOAT)&&defined(RETURNFLOAT)) #if defined (f2cFortran) && ! defined (gFortran) /* f2c/g77 return double from FORTRAN REAL functions. (KMCCARTY, 2005/12/09) */ #define FLOAT_cfPU(A) CFextern DOUBLE_PRECISION FCALLSC_QUALIFIER A #else #define FLOAT_cfPU(A) CFextern FORTRAN_REAL FCALLSC_QUALIFIER A #endif #else #define FLOAT_cfPU(A) CFextern FLOATFUNCTIONTYPE FCALLSC_QUALIFIER A #endif #define INT_cfPU(A) CFextern int FCALLSC_QUALIFIER A #define LOGICAL_cfPU(A) CFextern int FCALLSC_QUALIFIER A #define LONG_cfPU(A) CFextern long FCALLSC_QUALIFIER A #define SHORT_cfPU(A) CFextern short FCALLSC_QUALIFIER A #define STRING_cfPU(A) CFextern void FCALLSC_QUALIFIER A #define VOID_cfPU(A) CFextern void FCALLSC_QUALIFIER A #define BYTE_cfE INTEGER_BYTE A0; #define DOUBLE_cfE DOUBLE_PRECISION A0; #if ! (defined(FLOATFUNCTIONTYPE)&&defined(ASSIGNFLOAT)&&defined(RETURNFLOAT)) #define FLOAT_cfE FORTRAN_REAL A0; #else #define FLOAT_cfE FORTRAN_REAL AA0; FLOATFUNCTIONTYPE A0; #endif #define INT_cfE int A0; #define LOGICAL_cfE int A0; #define LONG_cfE long A0; #define SHORT_cfE short A0; #define VOID_cfE #ifdef vmsFortran #define STRING_cfE static char AA0[1+MAX_LEN_FORTRAN_FUNCTION_STRING]; \ static fstring A0 = \ {MAX_LEN_FORTRAN_FUNCTION_STRING,DSC$K_DTYPE_T,DSC$K_CLASS_S,AA0};\ memset(AA0, CFORTRAN_NON_CHAR, MAX_LEN_FORTRAN_FUNCTION_STRING);\ *(AA0+MAX_LEN_FORTRAN_FUNCTION_STRING)='\0'; #else #ifdef CRAYFortran #define STRING_cfE static char AA0[1+MAX_LEN_FORTRAN_FUNCTION_STRING]; \ static _fcd A0; *(AA0+MAX_LEN_FORTRAN_FUNCTION_STRING)='\0';\ memset(AA0,CFORTRAN_NON_CHAR, MAX_LEN_FORTRAN_FUNCTION_STRING);\ A0 = _cptofcd(AA0,MAX_LEN_FORTRAN_FUNCTION_STRING); #else /* 'cc: SC3.0.1 13 Jul 1994' barfs on char A0[0x4FE+1]; * char A0[0x4FE +1]; char A0[1+0x4FE]; are both OK. */ #define STRING_cfE static char A0[1+MAX_LEN_FORTRAN_FUNCTION_STRING]; \ memset(A0, CFORTRAN_NON_CHAR, \ MAX_LEN_FORTRAN_FUNCTION_STRING); \ *(A0+MAX_LEN_FORTRAN_FUNCTION_STRING)='\0'; #endif #endif /* ESTRING must use static char. array which is guaranteed to exist after function returns. */ /* N.B.i) The diff. for 0 (Zero) and >=1 arguments. ii)That the following create an unmatched bracket, i.e. '(', which must of course be matched in the call. iii)Commas must be handled very carefully */ #define INT_cfGZ(T,UN,LN) A0=CFC_(UN,LN)( #define VOID_cfGZ(T,UN,LN) CFC_(UN,LN)( #ifdef vmsFortran #define STRING_cfGZ(T,UN,LN) CFC_(UN,LN)(&A0 #else #if defined(CRAYFortran) || defined(AbsoftUNIXFortran) || defined(AbsoftProFortran) #define STRING_cfGZ(T,UN,LN) CFC_(UN,LN)( A0 #else #define STRING_cfGZ(T,UN,LN) CFC_(UN,LN)( A0,MAX_LEN_FORTRAN_FUNCTION_STRING #endif #endif #define INT_cfG(T,UN,LN) INT_cfGZ(T,UN,LN) #define VOID_cfG(T,UN,LN) VOID_cfGZ(T,UN,LN) #define STRING_cfG(T,UN,LN) STRING_cfGZ(T,UN,LN), /*, is only diff. from _cfG*/ #define BYTEVVVVVVV_cfPP #define INTVVVVVVV_cfPP /* These complement FLOATVVVVVVV_cfPP. */ #define DOUBLEVVVVVVV_cfPP #define LOGICALVVVVVVV_cfPP #define LONGVVVVVVV_cfPP #define SHORTVVVVVVV_cfPP #define PBYTE_cfPP #define PINT_cfPP #define PDOUBLE_cfPP #define PLOGICAL_cfPP #define PLONG_cfPP #define PSHORT_cfPP #define PFLOAT_cfPP FLOATVVVVVVV_cfPP #define BCF(TN,AN,C) _SEP_(TN,C,cfCOMMA) _Icf(2,B,TN,AN,0) #define INT_cfB(T,A) (_(T,VVVVVVV_cfTYPE)) A #define INTV_cfB(T,A) A #define INTVV_cfB(T,A) (A)[0] #define INTVVV_cfB(T,A) (A)[0][0] #define INTVVVV_cfB(T,A) (A)[0][0][0] #define INTVVVVV_cfB(T,A) (A)[0][0][0][0] #define INTVVVVVV_cfB(T,A) (A)[0][0][0][0][0] #define INTVVVVVVV_cfB(T,A) (A)[0][0][0][0][0][0] #define PINT_cfB(T,A) _(T,_cfPP)&A #define STRING_cfB(T,A) (char *) A #define STRINGV_cfB(T,A) (char *) A #define PSTRING_cfB(T,A) (char *) A #define PSTRINGV_cfB(T,A) (char *) A #define PVOID_cfB(T,A) (void *) A #define ROUTINE_cfB(T,A) (cfCAST_FUNCTION)A #define ZTRINGV_cfB(T,A) (char *) A #define PZTRINGV_cfB(T,A) (char *) A #define SCF(TN,NAME,I,A) _(TN,_cfSTR)(3,S,NAME,I,A,0,0) #define DEFAULT_cfS(M,I,A) #define LOGICAL_cfS(M,I,A) #define PLOGICAL_cfS(M,I,A) #define STRING_cfS(M,I,A) ,sizeof(A) #define STRINGV_cfS(M,I,A) ,( (unsigned)0xFFFF*firstindexlength(A) \ +secondindexlength(A)) #define PSTRING_cfS(M,I,A) ,sizeof(A) #define PSTRINGV_cfS(M,I,A) STRINGV_cfS(M,I,A) #define ZTRINGV_cfS(M,I,A) #define PZTRINGV_cfS(M,I,A) #define HCF(TN,I) _(TN,_cfSTR)(3,H,cfCOMMA, H,_(C,I),0,0) #define HHCF(TN,I) _(TN,_cfSTR)(3,H,cfCOMMA,HH,_(C,I),0,0) #define HHHCF(TN,I) _(TN,_cfSTR)(3,H,cfCOLON, H,_(C,I),0,0) #define H_CF_SPECIAL unsigned #define HH_CF_SPECIAL #define DEFAULT_cfH(M,I,A) #define LOGICAL_cfH(S,U,B) #define PLOGICAL_cfH(S,U,B) #define STRING_cfH(S,U,B) _(A,S) _(U,_CF_SPECIAL) B #define STRINGV_cfH(S,U,B) STRING_cfH(S,U,B) #define PSTRING_cfH(S,U,B) STRING_cfH(S,U,B) #define PSTRINGV_cfH(S,U,B) STRING_cfH(S,U,B) #define PNSTRING_cfH(S,U,B) STRING_cfH(S,U,B) #define PPSTRING_cfH(S,U,B) STRING_cfH(S,U,B) #define ZTRINGV_cfH(S,U,B) #define PZTRINGV_cfH(S,U,B) /* Need VOID_cfSTR because Absoft forced function types go through _cfSTR. */ /* No spaces inside expansion. They screws up macro catenation kludge. */ #define VOID_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define BYTE_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define DOUBLE_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define FLOAT_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define INT_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LOGICAL_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,LOGICAL,A,B,C,D,E) #define LONG_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LONGLONG_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) /* added by MR December 2005 */ #define SHORT_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define BYTEV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define BYTEVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define BYTEVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define BYTEVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define BYTEVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define BYTEVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define BYTEVVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define DOUBLEV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define DOUBLEVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define DOUBLEVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define DOUBLEVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define DOUBLEVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define DOUBLEVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define DOUBLEVVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define FLOATV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define FLOATVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define FLOATVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define FLOATVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define FLOATVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define FLOATVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define FLOATVVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define INTV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define INTVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define INTVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define INTVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define INTVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define INTVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define INTVVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LOGICALV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LOGICALVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LOGICALVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LOGICALVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LOGICALVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LOGICALVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LOGICALVVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LONGV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LONGVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LONGVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LONGVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LONGVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LONGVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LONGVVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define LONGLONGV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) /* added by MR December 2005 */ #define LONGLONGVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) /* added by MR December 2005 */ #define LONGLONGVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) /* added by MR December 2005 */ #define LONGLONGVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) /* added by MR December 2005 */ #define LONGLONGVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) /* added by MR December 2005 */ #define LONGLONGVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) /* added by MR December 2005 */ #define LONGLONGVVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) /* added by MR December 2005 */ #define SHORTV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define SHORTVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define SHORTVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define SHORTVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define SHORTVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define SHORTVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define SHORTVVVVVVV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define PBYTE_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define PDOUBLE_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define PFLOAT_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define PINT_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define PLOGICAL_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,PLOGICAL,A,B,C,D,E) #define PLONG_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define PLONGLONG_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) /* added by MR December 2005 */ #define PSHORT_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define STRING_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,STRING,A,B,C,D,E) #define PSTRING_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,PSTRING,A,B,C,D,E) #define STRINGV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,STRINGV,A,B,C,D,E) #define PSTRINGV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,PSTRINGV,A,B,C,D,E) #define PNSTRING_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,PNSTRING,A,B,C,D,E) #define PPSTRING_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,PPSTRING,A,B,C,D,E) #define PVOID_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define ROUTINE_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define SIMPLE_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,DEFAULT,A,B,C,D,E) #define ZTRINGV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,ZTRINGV,A,B,C,D,E) #define PZTRINGV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,PZTRINGV,A,B,C,D,E) #define CF_0_cfSTR(N,T,A,B,C,D,E) /* See ACF table comments, which explain why CCF was split into two. */ #define CCF(NAME,TN,I) _(TN,_cfSTR)(5,C,NAME,I,_(A,I),_(B,I),_(C,I)) #define DEFAULT_cfC(M,I,A,B,C) #define LOGICAL_cfC(M,I,A,B,C) A=C2FLOGICAL( A); #define PLOGICAL_cfC(M,I,A,B,C) *A=C2FLOGICAL(*A); #ifdef vmsFortran #define STRING_cfC(M,I,A,B,C) (B.clen=strlen(A),B.f.dsc$a_pointer=A, \ C==sizeof(char*)||C==(unsigned)(B.clen+1)?B.f.dsc$w_length=B.clen: \ (memset((A)+B.clen,' ',C-B.clen-1),A[B.f.dsc$w_length=C-1]='\0')); /* PSTRING_cfC to beware of array A which does not contain any \0. */ #define PSTRING_cfC(M,I,A,B,C) (B.dsc$a_pointer=A, C==sizeof(char*) ? \ B.dsc$w_length=strlen(A): (A[C-1]='\0',B.dsc$w_length=strlen(A), \ memset((A)+B.dsc$w_length,' ',C-B.dsc$w_length-1), B.dsc$w_length=C-1)); #else #define STRING_cfC(M,I,A,B,C) (B.nombre=A,B.clen=strlen(A), \ C==sizeof(char*)||C==(unsigned)(B.clen+1)?B.flen=B.clen: \ (memset(B.nombre+B.clen,' ',C-B.clen-1),B.nombre[B.flen=C-1]='\0')); #define PSTRING_cfC(M,I,A,B,C) (C==sizeof(char*)? B=strlen(A): \ (A[C-1]='\0',B=strlen(A),memset((A)+B,' ',C-B-1),B=C-1)); #endif /* For CRAYFortran for (P)STRINGV_cfC, B.fs is set, but irrelevant. */ #define STRINGV_cfC(M,I,A,B,C) \ AATRINGV_cfA( A,B,(C/0xFFFF)*(C%0xFFFF),C/0xFFFF,C%0xFFFF) #define PSTRINGV_cfC(M,I,A,B,C) \ APATRINGV_cfA( A,B,(C/0xFFFF)*(C%0xFFFF),C/0xFFFF,C%0xFFFF) #define ZTRINGV_cfC(M,I,A,B,C) \ AATRINGV_cfA( A,B, (_3(M,_ELEMS_,I))*((_3(M,_ELEMLEN_,I))+1), \ (_3(M,_ELEMS_,I)), (_3(M,_ELEMLEN_,I))+1 ) #define PZTRINGV_cfC(M,I,A,B,C) \ APATRINGV_cfA( A,B, (_3(M,_ELEMS_,I))*((_3(M,_ELEMLEN_,I))+1), \ (_3(M,_ELEMS_,I)), (_3(M,_ELEMLEN_,I))+1 ) #define BYTE_cfCCC(A,B) &A #define DOUBLE_cfCCC(A,B) &A #if !defined(__CF__KnR) #define FLOAT_cfCCC(A,B) &A /* Although the VAX doesn't, at least the */ #else /* HP and K&R mips promote float arg.'s of */ #define FLOAT_cfCCC(A,B) &B /* unprototyped functions to double. Cannot */ #endif /* use A here to pass the argument to FORTRAN. */ #define INT_cfCCC(A,B) &A #define LOGICAL_cfCCC(A,B) &A #define LONG_cfCCC(A,B) &A #define SHORT_cfCCC(A,B) &A #define PBYTE_cfCCC(A,B) A #define PDOUBLE_cfCCC(A,B) A #define PFLOAT_cfCCC(A,B) A #define PINT_cfCCC(A,B) A #define PLOGICAL_cfCCC(A,B) B=A /* B used to keep a common W table. */ #define PLONG_cfCCC(A,B) A #define PSHORT_cfCCC(A,B) A #define CCCF(TN,I,M) _SEP_(TN,M,cfCOMMA) _Icf(3,CC,TN,_(A,I),_(B,I)) #define INT_cfCC(T,A,B) _(T,_cfCCC)(A,B) #define INTV_cfCC(T,A,B) A #define INTVV_cfCC(T,A,B) A #define INTVVV_cfCC(T,A,B) A #define INTVVVV_cfCC(T,A,B) A #define INTVVVVV_cfCC(T,A,B) A #define INTVVVVVV_cfCC(T,A,B) A #define INTVVVVVVV_cfCC(T,A,B) A #define PINT_cfCC(T,A,B) _(T,_cfCCC)(A,B) #define PVOID_cfCC(T,A,B) A #if defined(apolloFortran) || defined(hpuxFortran800) || defined(AbsoftUNIXFortran) #define ROUTINE_cfCC(T,A,B) &A #else #define ROUTINE_cfCC(T,A,B) A #endif #define SIMPLE_cfCC(T,A,B) A #ifdef vmsFortran #define STRING_cfCC(T,A,B) &B.f #define STRINGV_cfCC(T,A,B) &B #define PSTRING_cfCC(T,A,B) &B #define PSTRINGV_cfCC(T,A,B) &B #else #ifdef CRAYFortran #define STRING_cfCC(T,A,B) _cptofcd(A,B.flen) #define STRINGV_cfCC(T,A,B) _cptofcd(B.s,B.flen) #define PSTRING_cfCC(T,A,B) _cptofcd(A,B) #define PSTRINGV_cfCC(T,A,B) _cptofcd(A,B.flen) #else #define STRING_cfCC(T,A,B) A #define STRINGV_cfCC(T,A,B) B.fs #define PSTRING_cfCC(T,A,B) A #define PSTRINGV_cfCC(T,A,B) B.fs #endif #endif #define ZTRINGV_cfCC(T,A,B) STRINGV_cfCC(T,A,B) #define PZTRINGV_cfCC(T,A,B) PSTRINGV_cfCC(T,A,B) #define BYTE_cfX return A0; #define DOUBLE_cfX return A0; #if ! (defined(FLOATFUNCTIONTYPE)&&defined(ASSIGNFLOAT)&&defined(RETURNFLOAT)) #define FLOAT_cfX return A0; #else #define FLOAT_cfX ASSIGNFLOAT(AA0,A0); return AA0; #endif #define INT_cfX return A0; #define LOGICAL_cfX return F2CLOGICAL(A0); #define LONG_cfX return A0; #define SHORT_cfX return A0; #define VOID_cfX return ; #if defined(vmsFortran) || defined(CRAYFortran) #define STRING_cfX return kill_trailing( \ kill_trailing(AA0,CFORTRAN_NON_CHAR),' '); #else #define STRING_cfX return kill_trailing( \ kill_trailing( A0,CFORTRAN_NON_CHAR),' '); #endif #define CFFUN(NAME) _(__cf__,NAME) /* Note that we don't use LN here, but we keep it for consistency. */ #define CCALLSFFUN0(UN,LN) CFFUN(UN)() #ifdef OLD_VAXC /* Allow %CC-I-PARAMNOTUSED. */ #pragma standard #endif #define CCALLSFFUN1( UN,LN,T1, A1) \ CCALLSFFUN5 (UN,LN,T1,CF_0,CF_0,CF_0,CF_0,A1,0,0,0,0) #define CCALLSFFUN2( UN,LN,T1,T2, A1,A2) \ CCALLSFFUN5 (UN,LN,T1,T2,CF_0,CF_0,CF_0,A1,A2,0,0,0) #define CCALLSFFUN3( UN,LN,T1,T2,T3, A1,A2,A3) \ CCALLSFFUN5 (UN,LN,T1,T2,T3,CF_0,CF_0,A1,A2,A3,0,0) #define CCALLSFFUN4( UN,LN,T1,T2,T3,T4, A1,A2,A3,A4)\ CCALLSFFUN5 (UN,LN,T1,T2,T3,T4,CF_0,A1,A2,A3,A4,0) #define CCALLSFFUN5( UN,LN,T1,T2,T3,T4,T5, A1,A2,A3,A4,A5) \ CCALLSFFUN10(UN,LN,T1,T2,T3,T4,T5,CF_0,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,0,0,0,0,0) #define CCALLSFFUN6( UN,LN,T1,T2,T3,T4,T5,T6, A1,A2,A3,A4,A5,A6) \ CCALLSFFUN10(UN,LN,T1,T2,T3,T4,T5,T6,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,0,0,0,0) #define CCALLSFFUN7( UN,LN,T1,T2,T3,T4,T5,T6,T7, A1,A2,A3,A4,A5,A6,A7) \ CCALLSFFUN10(UN,LN,T1,T2,T3,T4,T5,T6,T7,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,0,0,0) #define CCALLSFFUN8( UN,LN,T1,T2,T3,T4,T5,T6,T7,T8, A1,A2,A3,A4,A5,A6,A7,A8) \ CCALLSFFUN10(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,0,0) #define CCALLSFFUN9( UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,A1,A2,A3,A4,A5,A6,A7,A8,A9)\ CCALLSFFUN10(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,0) #define CCALLSFFUN10(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA)\ CCALLSFFUN14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,CF_0,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,0,0,0,0) #define CCALLSFFUN11(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB)\ CCALLSFFUN14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,CF_0,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,0,0,0) #define CCALLSFFUN12(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC)\ CCALLSFFUN14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,CF_0,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,0,0) #define CCALLSFFUN13(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD)\ CCALLSFFUN14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,CF_0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,0) #define CCALLSFFUN14(UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE)\ ((CFFUN(UN)( BCF(T1,A1,0) BCF(T2,A2,1) BCF(T3,A3,1) BCF(T4,A4,1) BCF(T5,A5,1) \ BCF(T6,A6,1) BCF(T7,A7,1) BCF(T8,A8,1) BCF(T9,A9,1) BCF(TA,AA,1) \ BCF(TB,AB,1) BCF(TC,AC,1) BCF(TD,AD,1) BCF(TE,AE,1) \ SCF(T1,LN,1,A1) SCF(T2,LN,2,A2) SCF(T3,LN,3,A3) SCF(T4,LN,4,A4) \ SCF(T5,LN,5,A5) SCF(T6,LN,6,A6) SCF(T7,LN,7,A7) SCF(T8,LN,8,A8) \ SCF(T9,LN,9,A9) SCF(TA,LN,10,AA) SCF(TB,LN,11,AB) SCF(TC,LN,12,AC) \ SCF(TD,LN,13,AD) SCF(TE,LN,14,AE)))) /* N.B. Create a separate function instead of using (call function, function value here) because in order to create the variables needed for the input arg.'s which may be const.'s one has to do the creation within {}, but these can never be placed within ()'s. Therefore one must create wrapper functions. gcc, on the other hand may be able to avoid the wrapper functions. */ /* Prototypes are needed to correctly handle the value returned correctly. N.B. Can only have prototype arg.'s with difficulty, a la G... table since FORTRAN functions returning strings have extra arg.'s. Don't bother, since this only causes a compiler warning to come up when one uses FCALLSCFUNn and CCALLSFFUNn for the same function in the same source code. Something done by the experts in debugging only.*/ #define PROTOCCALLSFFUN0(F,UN,LN) \ _(F,_cfPU)( CFC_(UN,LN))(CF_NULL_PROTO); \ static _Icf(2,U,F,CFFUN(UN),0)() {_(F,_cfE) _Icf(3,GZ,F,UN,LN) ABSOFT_cf1(F));_(F,_cfX)} #define PROTOCCALLSFFUN1( T0,UN,LN,T1) \ PROTOCCALLSFFUN5 (T0,UN,LN,T1,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFFUN2( T0,UN,LN,T1,T2) \ PROTOCCALLSFFUN5 (T0,UN,LN,T1,T2,CF_0,CF_0,CF_0) #define PROTOCCALLSFFUN3( T0,UN,LN,T1,T2,T3) \ PROTOCCALLSFFUN5 (T0,UN,LN,T1,T2,T3,CF_0,CF_0) #define PROTOCCALLSFFUN4( T0,UN,LN,T1,T2,T3,T4) \ PROTOCCALLSFFUN5 (T0,UN,LN,T1,T2,T3,T4,CF_0) #define PROTOCCALLSFFUN5( T0,UN,LN,T1,T2,T3,T4,T5) \ PROTOCCALLSFFUN10(T0,UN,LN,T1,T2,T3,T4,T5,CF_0,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFFUN6( T0,UN,LN,T1,T2,T3,T4,T5,T6) \ PROTOCCALLSFFUN10(T0,UN,LN,T1,T2,T3,T4,T5,T6,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFFUN7( T0,UN,LN,T1,T2,T3,T4,T5,T6,T7) \ PROTOCCALLSFFUN10(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,CF_0,CF_0,CF_0) #define PROTOCCALLSFFUN8( T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8) \ PROTOCCALLSFFUN10(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,CF_0,CF_0) #define PROTOCCALLSFFUN9( T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9) \ PROTOCCALLSFFUN10(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,CF_0) #define PROTOCCALLSFFUN10(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA) \ PROTOCCALLSFFUN14(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,CF_0,CF_0,CF_0,CF_0) #define PROTOCCALLSFFUN11(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB) \ PROTOCCALLSFFUN14(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,CF_0,CF_0,CF_0) #define PROTOCCALLSFFUN12(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC) \ PROTOCCALLSFFUN14(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,CF_0,CF_0) #define PROTOCCALLSFFUN13(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD) \ PROTOCCALLSFFUN14(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,CF_0) /* HP/UX 9.01 cc requires the blank between '_Icf(3,G,T0,UN,LN) CCCF(T1,1,0)' */ #ifndef __CF__KnR #define PROTOCCALLSFFUN14(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ _(T0,_cfPU)(CFC_(UN,LN))(CF_NULL_PROTO); static _Icf(2,U,T0,CFFUN(UN),0)( \ CFARGT14FS(UCF,HCF,_Z,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) ) \ { CFARGT14S(VCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) _(T0,_cfE) \ CCF(LN,T1,1) CCF(LN,T2,2) CCF(LN,T3,3) CCF(LN,T4,4) CCF(LN,T5,5) \ CCF(LN,T6,6) CCF(LN,T7,7) CCF(LN,T8,8) CCF(LN,T9,9) CCF(LN,TA,10) \ CCF(LN,TB,11) CCF(LN,TC,12) CCF(LN,TD,13) CCF(LN,TE,14) _Icf(3,G,T0,UN,LN) \ CFARGT14(CCCF,JCF,ABSOFT_cf1(T0),T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE)); \ WCF(T1,A1,1) WCF(T2,A2,2) WCF(T3,A3,3) WCF(T4,A4,4) WCF(T5,A5,5) \ WCF(T6,A6,6) WCF(T7,A7,7) WCF(T8,A8,8) WCF(T9,A9,9) WCF(TA,A10,10) \ WCF(TB,A11,11) WCF(TC,A12,12) WCF(TD,A13,13) WCF(TE,A14,14) _(T0,_cfX)} #else #define PROTOCCALLSFFUN14(T0,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ _(T0,_cfPU)(CFC_(UN,LN))(CF_NULL_PROTO); static _Icf(2,U,T0,CFFUN(UN),0)( \ CFARGT14FS(UUCF,HHCF,_Z,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) ) \ CFARGT14FS(UUUCF,HHHCF,_Z,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) ; \ { CFARGT14S(VCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) _(T0,_cfE) \ CCF(LN,T1,1) CCF(LN,T2,2) CCF(LN,T3,3) CCF(LN,T4,4) CCF(LN,T5,5) \ CCF(LN,T6,6) CCF(LN,T7,7) CCF(LN,T8,8) CCF(LN,T9,9) CCF(LN,TA,10) \ CCF(LN,TB,11) CCF(LN,TC,12) CCF(LN,TD,13) CCF(LN,TE,14) _Icf(3,G,T0,UN,LN) \ CFARGT14(CCCF,JCF,ABSOFT_cf1(T0),T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE)); \ WCF(T1,A1,1) WCF(T2,A2,2) WCF(T3,A3,3) WCF(T4,A4,4) WCF(T5,A5,5) \ WCF(T6,A6,6) WCF(T7,A7,7) WCF(T8,A8,8) WCF(T9,A9,9) WCF(TA,A10,10) \ WCF(TB,A11,11) WCF(TC,A12,12) WCF(TD,A13,13) WCF(TE,A14,14) _(T0,_cfX)} #endif /*-------------------------------------------------------------------------*/ /* UTILITIES FOR FORTRAN TO CALL C ROUTINES */ #ifdef OLD_VAXC /* Prevent %CC-I-PARAMNOTUSED. */ #pragma nostandard #endif #if defined(vmsFortran) || defined(CRAYFortran) #define DCF(TN,I) #define DDCF(TN,I) #define DDDCF(TN,I) #else #define DCF(TN,I) HCF(TN,I) #define DDCF(TN,I) HHCF(TN,I) #define DDDCF(TN,I) HHHCF(TN,I) #endif #define QCF(TN,I) _(TN,_cfSTR)(1,Q,_(B,I), 0,0,0,0) #define DEFAULT_cfQ(B) #define LOGICAL_cfQ(B) #define PLOGICAL_cfQ(B) #define STRINGV_cfQ(B) char *B; unsigned int _(B,N); #define STRING_cfQ(B) char *B=NULL; #define PSTRING_cfQ(B) char *B=NULL; #define PSTRINGV_cfQ(B) STRINGV_cfQ(B) #define PNSTRING_cfQ(B) char *B=NULL; #define PPSTRING_cfQ(B) #ifdef __sgi /* Else SGI gives warning 182 contrary to its C LRM A.17.7 */ #define ROUTINE_orig *(void**)& #else #define ROUTINE_orig (void *) #endif #define ROUTINE_1 ROUTINE_orig #define ROUTINE_2 ROUTINE_orig #define ROUTINE_3 ROUTINE_orig #define ROUTINE_4 ROUTINE_orig #define ROUTINE_5 ROUTINE_orig #define ROUTINE_6 ROUTINE_orig #define ROUTINE_7 ROUTINE_orig #define ROUTINE_8 ROUTINE_orig #define ROUTINE_9 ROUTINE_orig #define ROUTINE_10 ROUTINE_orig #define ROUTINE_11 ROUTINE_orig #define ROUTINE_12 ROUTINE_orig #define ROUTINE_13 ROUTINE_orig #define ROUTINE_14 ROUTINE_orig #define ROUTINE_15 ROUTINE_orig #define ROUTINE_16 ROUTINE_orig #define ROUTINE_17 ROUTINE_orig #define ROUTINE_18 ROUTINE_orig #define ROUTINE_19 ROUTINE_orig #define ROUTINE_20 ROUTINE_orig #define ROUTINE_21 ROUTINE_orig #define ROUTINE_22 ROUTINE_orig #define ROUTINE_23 ROUTINE_orig #define ROUTINE_24 ROUTINE_orig #define ROUTINE_25 ROUTINE_orig #define ROUTINE_26 ROUTINE_orig #define ROUTINE_27 ROUTINE_orig #define TCF(NAME,TN,I,M) _SEP_(TN,M,cfCOMMA) _(TN,_cfT)(NAME,I,_(A,I),_(B,I),_(C,I)) #define BYTE_cfT(M,I,A,B,D) *A #define DOUBLE_cfT(M,I,A,B,D) *A #define FLOAT_cfT(M,I,A,B,D) *A #define INT_cfT(M,I,A,B,D) *A #define LOGICAL_cfT(M,I,A,B,D) F2CLOGICAL(*A) #define LONG_cfT(M,I,A,B,D) *A #define LONGLONG_cfT(M,I,A,B,D) *A /* added by MR December 2005 */ #define SHORT_cfT(M,I,A,B,D) *A #define BYTEV_cfT(M,I,A,B,D) A #define DOUBLEV_cfT(M,I,A,B,D) A #define FLOATV_cfT(M,I,A,B,D) VOIDP A #define INTV_cfT(M,I,A,B,D) A #define LOGICALV_cfT(M,I,A,B,D) A #define LONGV_cfT(M,I,A,B,D) A #define LONGLONGV_cfT(M,I,A,B,D) A /* added by MR December 2005 */ #define SHORTV_cfT(M,I,A,B,D) A #define BYTEVV_cfT(M,I,A,B,D) (void *)A /* We have to cast to void *,*/ #define BYTEVVV_cfT(M,I,A,B,D) (void *)A /* since we don't know the */ #define BYTEVVVV_cfT(M,I,A,B,D) (void *)A /* dimensions of the array. */ #define BYTEVVVVV_cfT(M,I,A,B,D) (void *)A /* i.e. Unfortunately, can't */ #define BYTEVVVVVV_cfT(M,I,A,B,D) (void *)A /* check that the type */ #define BYTEVVVVVVV_cfT(M,I,A,B,D) (void *)A /* matches the prototype. */ #define DOUBLEVV_cfT(M,I,A,B,D) (void *)A #define DOUBLEVVV_cfT(M,I,A,B,D) (void *)A #define DOUBLEVVVV_cfT(M,I,A,B,D) (void *)A #define DOUBLEVVVVV_cfT(M,I,A,B,D) (void *)A #define DOUBLEVVVVVV_cfT(M,I,A,B,D) (void *)A #define DOUBLEVVVVVVV_cfT(M,I,A,B,D) (void *)A #define FLOATVV_cfT(M,I,A,B,D) (void *)A #define FLOATVVV_cfT(M,I,A,B,D) (void *)A #define FLOATVVVV_cfT(M,I,A,B,D) (void *)A #define FLOATVVVVV_cfT(M,I,A,B,D) (void *)A #define FLOATVVVVVV_cfT(M,I,A,B,D) (void *)A #define FLOATVVVVVVV_cfT(M,I,A,B,D) (void *)A #define INTVV_cfT(M,I,A,B,D) (void *)A #define INTVVV_cfT(M,I,A,B,D) (void *)A #define INTVVVV_cfT(M,I,A,B,D) (void *)A #define INTVVVVV_cfT(M,I,A,B,D) (void *)A #define INTVVVVVV_cfT(M,I,A,B,D) (void *)A #define INTVVVVVVV_cfT(M,I,A,B,D) (void *)A #define LOGICALVV_cfT(M,I,A,B,D) (void *)A #define LOGICALVVV_cfT(M,I,A,B,D) (void *)A #define LOGICALVVVV_cfT(M,I,A,B,D) (void *)A #define LOGICALVVVVV_cfT(M,I,A,B,D) (void *)A #define LOGICALVVVVVV_cfT(M,I,A,B,D) (void *)A #define LOGICALVVVVVVV_cfT(M,I,A,B,D) (void *)A #define LONGVV_cfT(M,I,A,B,D) (void *)A #define LONGVVV_cfT(M,I,A,B,D) (void *)A #define LONGVVVV_cfT(M,I,A,B,D) (void *)A #define LONGVVVVV_cfT(M,I,A,B,D) (void *)A #define LONGVVVVVV_cfT(M,I,A,B,D) (void *)A #define LONGVVVVVVV_cfT(M,I,A,B,D) (void *)A #define LONGLONGVV_cfT(M,I,A,B,D) (void *)A /* added by MR December 2005 */ #define LONGLONGVVV_cfT(M,I,A,B,D) (void *)A /* added by MR December 2005 */ #define LONGLONGVVVV_cfT(M,I,A,B,D) (void *)A /* added by MR December 2005 */ #define LONGLONGVVVVV_cfT(M,I,A,B,D) (void *)A /* added by MR December 2005 */ #define LONGLONGVVVVVV_cfT(M,I,A,B,D) (void *)A /* added by MR December 2005 */ #define LONGLONGVVVVVVV_cfT(M,I,A,B,D) (void *)A /* added by MR December 2005 */ #define SHORTVV_cfT(M,I,A,B,D) (void *)A #define SHORTVVV_cfT(M,I,A,B,D) (void *)A #define SHORTVVVV_cfT(M,I,A,B,D) (void *)A #define SHORTVVVVV_cfT(M,I,A,B,D) (void *)A #define SHORTVVVVVV_cfT(M,I,A,B,D) (void *)A #define SHORTVVVVVVV_cfT(M,I,A,B,D) (void *)A #define PBYTE_cfT(M,I,A,B,D) A #define PDOUBLE_cfT(M,I,A,B,D) A #define PFLOAT_cfT(M,I,A,B,D) VOIDP A #define PINT_cfT(M,I,A,B,D) A #define PLOGICAL_cfT(M,I,A,B,D) ((*A=F2CLOGICAL(*A)),A) #define PLONG_cfT(M,I,A,B,D) A #define PLONGLONG_cfT(M,I,A,B,D) A /* added by MR December 2005 */ #define PSHORT_cfT(M,I,A,B,D) A #define PVOID_cfT(M,I,A,B,D) A #if defined(apolloFortran) || defined(hpuxFortran800) || defined(AbsoftUNIXFortran) #define ROUTINE_cfT(M,I,A,B,D) _(ROUTINE_,I) (*A) #else #define ROUTINE_cfT(M,I,A,B,D) _(ROUTINE_,I) A #endif /* A == pointer to the characters D == length of the string, or of an element in an array of strings E == number of elements in an array of strings */ #define TTSTR( A,B,D) \ ((B=_cf_malloc(D+1))[D]='\0', memcpy(B,A,D), kill_trailing(B,' ')) #define TTTTSTR( A,B,D) (!(D<4||A[0]||A[1]||A[2]||A[3]))?NULL: \ memchr(A,'\0',D) ?A : TTSTR(A,B,D) #define TTTTSTRV( A,B,D,E) (_(B,N)=E,B=_cf_malloc(_(B,N)*(D+1)), (void *) \ vkill_trailing(f2cstrv(A,B,D+1, _(B,N)*(D+1)), D+1,_(B,N)*(D+1),' ')) #ifdef vmsFortran #define STRING_cfT(M,I,A,B,D) TTTTSTR( A->dsc$a_pointer,B,A->dsc$w_length) #define STRINGV_cfT(M,I,A,B,D) TTTTSTRV(A->dsc$a_pointer, B, \ A->dsc$w_length , A->dsc$l_m[0]) #define PSTRING_cfT(M,I,A,B,D) TTSTR( A->dsc$a_pointer,B,A->dsc$w_length) #define PPSTRING_cfT(M,I,A,B,D) A->dsc$a_pointer #else #ifdef CRAYFortran #define STRING_cfT(M,I,A,B,D) TTTTSTR( _fcdtocp(A),B,_fcdlen(A)) #define STRINGV_cfT(M,I,A,B,D) TTTTSTRV(_fcdtocp(A),B,_fcdlen(A), \ num_elem(_fcdtocp(A),_fcdlen(A),_3(M,_STRV_A,I))) #define PSTRING_cfT(M,I,A,B,D) TTSTR( _fcdtocp(A),B,_fcdlen(A)) #define PPSTRING_cfT(M,I,A,B,D) _fcdtocp(A) #else #define STRING_cfT(M,I,A,B,D) TTTTSTR( A,B,D) #define STRINGV_cfT(M,I,A,B,D) TTTTSTRV(A,B,D, num_elem(A,D,_3(M,_STRV_A,I))) #define PSTRING_cfT(M,I,A,B,D) TTSTR( A,B,D) #define PPSTRING_cfT(M,I,A,B,D) A #endif #endif #define PNSTRING_cfT(M,I,A,B,D) STRING_cfT(M,I,A,B,D) #define PSTRINGV_cfT(M,I,A,B,D) STRINGV_cfT(M,I,A,B,D) #define CF_0_cfT(M,I,A,B,D) #define RCF(TN,I) _(TN,_cfSTR)(3,R,_(A,I),_(B,I),_(C,I),0,0) #define DEFAULT_cfR(A,B,D) #define LOGICAL_cfR(A,B,D) #define PLOGICAL_cfR(A,B,D) *A=C2FLOGICAL(*A); #define STRING_cfR(A,B,D) if (B) _cf_free(B); #define STRINGV_cfR(A,B,D) _cf_free(B); /* A and D as defined above for TSTRING(V) */ #define RRRRPSTR( A,B,D) if (B) memcpy(A,B, _cfMIN(strlen(B),D)), \ (D>strlen(B)?memset(A+strlen(B),' ', D-strlen(B)):0), _cf_free(B); #define RRRRPSTRV(A,B,D) c2fstrv(B,A,D+1,(D+1)*_(B,N)), _cf_free(B); #ifdef vmsFortran #define PSTRING_cfR(A,B,D) RRRRPSTR( A->dsc$a_pointer,B,A->dsc$w_length) #define PSTRINGV_cfR(A,B,D) RRRRPSTRV(A->dsc$a_pointer,B,A->dsc$w_length) #else #ifdef CRAYFortran #define PSTRING_cfR(A,B,D) RRRRPSTR( _fcdtocp(A),B,_fcdlen(A)) #define PSTRINGV_cfR(A,B,D) RRRRPSTRV(_fcdtocp(A),B,_fcdlen(A)) #else #define PSTRING_cfR(A,B,D) RRRRPSTR( A,B,D) #define PSTRINGV_cfR(A,B,D) RRRRPSTRV(A,B,D) #endif #endif #define PNSTRING_cfR(A,B,D) PSTRING_cfR(A,B,D) #define PPSTRING_cfR(A,B,D) #define BYTE_cfFZ(UN,LN) INTEGER_BYTE FCALLSC_QUALIFIER fcallsc(UN,LN)( #define DOUBLE_cfFZ(UN,LN) DOUBLE_PRECISION FCALLSC_QUALIFIER fcallsc(UN,LN)( #define INT_cfFZ(UN,LN) int FCALLSC_QUALIFIER fcallsc(UN,LN)( #define LOGICAL_cfFZ(UN,LN) int FCALLSC_QUALIFIER fcallsc(UN,LN)( #define LONG_cfFZ(UN,LN) long FCALLSC_QUALIFIER fcallsc(UN,LN)( #define LONGLONG_cfFZ(UN,LN) LONGLONG FCALLSC_QUALIFIER fcallsc(UN,LN)( /* added by MR December 2005 */ #define SHORT_cfFZ(UN,LN) short FCALLSC_QUALIFIER fcallsc(UN,LN)( #define VOID_cfFZ(UN,LN) void FCALLSC_QUALIFIER fcallsc(UN,LN)( #ifndef __CF__KnR /* The void is req'd by the Apollo, to make this an ANSI function declaration. The Apollo promotes K&R float functions to double. */ #if defined (f2cFortran) && ! defined (gFortran) /* f2c/g77 return double from FORTRAN REAL functions. (KMCCARTY, 2005/12/09) */ #define FLOAT_cfFZ(UN,LN) DOUBLE_PRECISION FCALLSC_QUALIFIER fcallsc(UN,LN)(void #else #define FLOAT_cfFZ(UN,LN) FORTRAN_REAL FCALLSC_QUALIFIER fcallsc(UN,LN)(void #endif #ifdef vmsFortran #define STRING_cfFZ(UN,LN) void FCALLSC_QUALIFIER fcallsc(UN,LN)(fstring *AS #else #ifdef CRAYFortran #define STRING_cfFZ(UN,LN) void FCALLSC_QUALIFIER fcallsc(UN,LN)(_fcd AS #else #if defined(AbsoftUNIXFortran) || defined(AbsoftProFortran) #define STRING_cfFZ(UN,LN) void FCALLSC_QUALIFIER fcallsc(UN,LN)(char *AS #else #define STRING_cfFZ(UN,LN) void FCALLSC_QUALIFIER fcallsc(UN,LN)(char *AS, unsigned D0 #endif #endif #endif #else #if ! (defined(FLOATFUNCTIONTYPE)&&defined(ASSIGNFLOAT)&&defined(RETURNFLOAT)) #if defined (f2cFortran) && ! defined (gFortran) /* f2c/g77 return double from FORTRAN REAL functions. (KMCCARTY, 2005/12/09) */ #define FLOAT_cfFZ(UN,LN) DOUBLE_PRECISION FCALLSC_QUALIFIER fcallsc(UN,LN)( #else #define FLOAT_cfFZ(UN,LN) FORTRAN_REAL FCALLSC_QUALIFIER fcallsc(UN,LN)( #endif #else #define FLOAT_cfFZ(UN,LN) FLOATFUNCTIONTYPE FCALLSC_QUALIFIER fcallsc(UN,LN)( #endif #if defined(vmsFortran) || defined(CRAYFortran) || defined(AbsoftUNIXFortran) #define STRING_cfFZ(UN,LN) void FCALLSC_QUALIFIER fcallsc(UN,LN)(AS #else #define STRING_cfFZ(UN,LN) void FCALLSC_QUALIFIER fcallsc(UN,LN)(AS, D0 #endif #endif #define BYTE_cfF(UN,LN) BYTE_cfFZ(UN,LN) #define DOUBLE_cfF(UN,LN) DOUBLE_cfFZ(UN,LN) #ifndef __CF_KnR #if defined (f2cFortran) && ! defined (gFortran) /* f2c/g77 return double from FORTRAN REAL functions. (KMCCARTY, 2005/12/09) */ #define FLOAT_cfF(UN,LN) DOUBLE_PRECISION FCALLSC_QUALIFIER fcallsc(UN,LN)( #else #define FLOAT_cfF(UN,LN) FORTRAN_REAL FCALLSC_QUALIFIER fcallsc(UN,LN)( #endif #else #define FLOAT_cfF(UN,LN) FLOAT_cfFZ(UN,LN) #endif #define INT_cfF(UN,LN) INT_cfFZ(UN,LN) #define LOGICAL_cfF(UN,LN) LOGICAL_cfFZ(UN,LN) #define LONG_cfF(UN,LN) LONG_cfFZ(UN,LN) #define LONGLONG_cfF(UN,LN) LONGLONG_cfFZ(UN,LN) /* added by MR December 2005 */ #define SHORT_cfF(UN,LN) SHORT_cfFZ(UN,LN) #define VOID_cfF(UN,LN) VOID_cfFZ(UN,LN) #define STRING_cfF(UN,LN) STRING_cfFZ(UN,LN), #define INT_cfFF #define VOID_cfFF #ifdef vmsFortran #define STRING_cfFF fstring *AS; #else #ifdef CRAYFortran #define STRING_cfFF _fcd AS; #else #define STRING_cfFF char *AS; unsigned D0; #endif #endif #define INT_cfL A0= #define STRING_cfL A0= #define VOID_cfL #define INT_cfK #define VOID_cfK /* KSTRING copies the string into the position provided by the caller. */ #ifdef vmsFortran #define STRING_cfK \ memcpy(AS->dsc$a_pointer,A0,_cfMIN(AS->dsc$w_length,(A0==NULL?0:strlen(A0))));\ AS->dsc$w_length>(A0==NULL?0:strlen(A0))? \ memset(AS->dsc$a_pointer+(A0==NULL?0:strlen(A0)),' ', \ AS->dsc$w_length-(A0==NULL?0:strlen(A0))):0; #else #ifdef CRAYFortran #define STRING_cfK \ memcpy(_fcdtocp(AS),A0, _cfMIN(_fcdlen(AS),(A0==NULL?0:strlen(A0))) ); \ _fcdlen(AS)>(A0==NULL?0:strlen(A0))? \ memset(_fcdtocp(AS)+(A0==NULL?0:strlen(A0)),' ', \ _fcdlen(AS)-(A0==NULL?0:strlen(A0))):0; #else #define STRING_cfK memcpy(AS,A0, _cfMIN(D0,(A0==NULL?0:strlen(A0))) ); \ D0>(A0==NULL?0:strlen(A0))?memset(AS+(A0==NULL?0:strlen(A0)), \ ' ', D0-(A0==NULL?0:strlen(A0))):0; #endif #endif /* Note that K.. and I.. can't be combined since K.. has to access data before R.., in order for functions returning strings which are also passed in as arguments to work correctly. Note that R.. frees and hence may corrupt the string. */ #define BYTE_cfI return A0; #define DOUBLE_cfI return A0; #if ! (defined(FLOATFUNCTIONTYPE)&&defined(ASSIGNFLOAT)&&defined(RETURNFLOAT)) #define FLOAT_cfI return A0; #else #define FLOAT_cfI RETURNFLOAT(A0); #endif #define INT_cfI return A0; #ifdef hpuxFortran800 /* Incredibly, functions must return true as 1, elsewhere .true.==0x01000000. */ #define LOGICAL_cfI return ((A0)?1:0); #else #define LOGICAL_cfI return C2FLOGICAL(A0); #endif #define LONG_cfI return A0; #define LONGLONG_cfI return A0; /* added by MR December 2005 */ #define SHORT_cfI return A0; #define STRING_cfI return ; #define VOID_cfI return ; #ifdef OLD_VAXC /* Allow %CC-I-PARAMNOTUSED. */ #pragma standard #endif #define FCALLSCSUB0( CN,UN,LN) FCALLSCFUN0(VOID,CN,UN,LN) #define FCALLSCSUB1( CN,UN,LN,T1) FCALLSCFUN1(VOID,CN,UN,LN,T1) #define FCALLSCSUB2( CN,UN,LN,T1,T2) FCALLSCFUN2(VOID,CN,UN,LN,T1,T2) #define FCALLSCSUB3( CN,UN,LN,T1,T2,T3) FCALLSCFUN3(VOID,CN,UN,LN,T1,T2,T3) #define FCALLSCSUB4( CN,UN,LN,T1,T2,T3,T4) \ FCALLSCFUN4(VOID,CN,UN,LN,T1,T2,T3,T4) #define FCALLSCSUB5( CN,UN,LN,T1,T2,T3,T4,T5) \ FCALLSCFUN5(VOID,CN,UN,LN,T1,T2,T3,T4,T5) #define FCALLSCSUB6( CN,UN,LN,T1,T2,T3,T4,T5,T6) \ FCALLSCFUN6(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6) #define FCALLSCSUB7( CN,UN,LN,T1,T2,T3,T4,T5,T6,T7) \ FCALLSCFUN7(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7) #define FCALLSCSUB8( CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8) \ FCALLSCFUN8(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8) #define FCALLSCSUB9( CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9) \ FCALLSCFUN9(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9) #define FCALLSCSUB10(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA) \ FCALLSCFUN10(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA) #define FCALLSCSUB11(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB) \ FCALLSCFUN11(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB) #define FCALLSCSUB12(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC) \ FCALLSCFUN12(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC) #define FCALLSCSUB13(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD) \ FCALLSCFUN13(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD) #define FCALLSCSUB14(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ FCALLSCFUN14(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) #define FCALLSCSUB15(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF) \ FCALLSCFUN15(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF) #define FCALLSCSUB16(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG) \ FCALLSCFUN16(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG) #define FCALLSCSUB17(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH) \ FCALLSCFUN17(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH) #define FCALLSCSUB18(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI) \ FCALLSCFUN18(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI) #define FCALLSCSUB19(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ) \ FCALLSCFUN19(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ) #define FCALLSCSUB20(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) \ FCALLSCFUN20(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) #define FCALLSCSUB21(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL) \ FCALLSCFUN21(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL) #define FCALLSCSUB22(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM) \ FCALLSCFUN22(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM) #define FCALLSCSUB23(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN) \ FCALLSCFUN23(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN) #define FCALLSCSUB24(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO) \ FCALLSCFUN24(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO) #define FCALLSCSUB25(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP) \ FCALLSCFUN25(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP) #define FCALLSCSUB26(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ) \ FCALLSCFUN26(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ) #define FCALLSCSUB27(CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ FCALLSCFUN27(VOID,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) #define FCALLSCFUN1( T0,CN,UN,LN,T1) \ FCALLSCFUN5 (T0,CN,UN,LN,T1,CF_0,CF_0,CF_0,CF_0) #define FCALLSCFUN2( T0,CN,UN,LN,T1,T2) \ FCALLSCFUN5 (T0,CN,UN,LN,T1,T2,CF_0,CF_0,CF_0) #define FCALLSCFUN3( T0,CN,UN,LN,T1,T2,T3) \ FCALLSCFUN5 (T0,CN,UN,LN,T1,T2,T3,CF_0,CF_0) #define FCALLSCFUN4( T0,CN,UN,LN,T1,T2,T3,T4) \ FCALLSCFUN5 (T0,CN,UN,LN,T1,T2,T3,T4,CF_0) #define FCALLSCFUN5( T0,CN,UN,LN,T1,T2,T3,T4,T5) \ FCALLSCFUN10(T0,CN,UN,LN,T1,T2,T3,T4,T5,CF_0,CF_0,CF_0,CF_0,CF_0) #define FCALLSCFUN6( T0,CN,UN,LN,T1,T2,T3,T4,T5,T6) \ FCALLSCFUN10(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,CF_0,CF_0,CF_0,CF_0) #define FCALLSCFUN7( T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7) \ FCALLSCFUN10(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,CF_0,CF_0,CF_0) #define FCALLSCFUN8( T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8) \ FCALLSCFUN10(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,CF_0,CF_0) #define FCALLSCFUN9( T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9) \ FCALLSCFUN10(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,CF_0) #define FCALLSCFUN10(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA) \ FCALLSCFUN14(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,CF_0,CF_0,CF_0,CF_0) #define FCALLSCFUN11(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB) \ FCALLSCFUN14(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,CF_0,CF_0,CF_0) #define FCALLSCFUN12(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC) \ FCALLSCFUN14(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,CF_0,CF_0) #define FCALLSCFUN13(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD) \ FCALLSCFUN14(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,CF_0) #define FCALLSCFUN15(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF) \ FCALLSCFUN20(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,CF_0,CF_0,CF_0,CF_0,CF_0) #define FCALLSCFUN16(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG) \ FCALLSCFUN20(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,CF_0,CF_0,CF_0,CF_0) #define FCALLSCFUN17(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH) \ FCALLSCFUN20(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,CF_0,CF_0,CF_0) #define FCALLSCFUN18(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI) \ FCALLSCFUN20(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,CF_0,CF_0) #define FCALLSCFUN19(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ) \ FCALLSCFUN20(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,CF_0) #define FCALLSCFUN20(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK) \ FCALLSCFUN27(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) #define FCALLSCFUN21(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL) \ FCALLSCFUN27(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,CF_0,CF_0,CF_0,CF_0,CF_0,CF_0) #define FCALLSCFUN22(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM) \ FCALLSCFUN27(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,CF_0,CF_0,CF_0,CF_0,CF_0) #define FCALLSCFUN23(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN) \ FCALLSCFUN27(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,CF_0,CF_0,CF_0,CF_0) #define FCALLSCFUN24(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO) \ FCALLSCFUN27(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,CF_0,CF_0,CF_0) #define FCALLSCFUN25(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP) \ FCALLSCFUN27(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,CF_0,CF_0) #define FCALLSCFUN26(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ) \ FCALLSCFUN27(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,CF_0) #ifndef __CF__KnR #define FCALLSCFUN0(T0,CN,UN,LN) CFextern _(T0,_cfFZ)(UN,LN) ABSOFT_cf2(T0)) \ {_Icf(2,UU,T0,A0,0); _Icf(0,L,T0,0,0) CN(); _Icf(0,K,T0,0,0) _(T0,_cfI)} #define FCALLSCFUN14(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ CFextern _(T0,_cfF)(UN,LN) \ CFARGT14(NCF,DCF,ABSOFT_cf2(T0),T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) ) \ { CFARGT14S(QCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ _Icf(2,UU,T0,A0,0); _Icf(0,L,T0,0,0) CN( TCF(LN,T1,1,0) TCF(LN,T2,2,1) \ TCF(LN,T3,3,1) TCF(LN,T4,4,1) TCF(LN,T5,5,1) TCF(LN,T6,6,1) TCF(LN,T7,7,1) \ TCF(LN,T8,8,1) TCF(LN,T9,9,1) TCF(LN,TA,10,1) TCF(LN,TB,11,1) TCF(LN,TC,12,1) \ TCF(LN,TD,13,1) TCF(LN,TE,14,1) ); _Icf(0,K,T0,0,0) \ CFARGT14S(RCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) _(T0,_cfI) } #define FCALLSCFUN27(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ CFextern _(T0,_cfF)(UN,LN) \ CFARGT27(NCF,DCF,ABSOFT_cf2(T0),T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) ) \ { CFARGT27S(QCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ _Icf(2,UU,T0,A0,0); _Icf(0,L,T0,0,0) CN( TCF(LN,T1,1,0) TCF(LN,T2,2,1) \ TCF(LN,T3,3,1) TCF(LN,T4,4,1) TCF(LN,T5,5,1) TCF(LN,T6,6,1) TCF(LN,T7,7,1) \ TCF(LN,T8,8,1) TCF(LN,T9,9,1) TCF(LN,TA,10,1) TCF(LN,TB,11,1) TCF(LN,TC,12,1) \ TCF(LN,TD,13,1) TCF(LN,TE,14,1) TCF(LN,TF,15,1) TCF(LN,TG,16,1) TCF(LN,TH,17,1) \ TCF(LN,TI,18,1) TCF(LN,TJ,19,1) TCF(LN,TK,20,1) TCF(LN,TL,21,1) TCF(LN,TM,22,1) \ TCF(LN,TN,23,1) TCF(LN,TO,24,1) TCF(LN,TP,25,1) TCF(LN,TQ,26,1) TCF(LN,TR,27,1) ); _Icf(0,K,T0,0,0) \ CFARGT27S(RCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) _(T0,_cfI) } #else #define FCALLSCFUN0(T0,CN,UN,LN) CFextern _(T0,_cfFZ)(UN,LN) ABSOFT_cf3(T0)) _Icf(0,FF,T0,0,0)\ {_Icf(2,UU,T0,A0,0); _Icf(0,L,T0,0,0) CN(); _Icf(0,K,T0,0,0) _(T0,_cfI)} #define FCALLSCFUN14(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ CFextern _(T0,_cfF)(UN,LN) \ CFARGT14(NNCF,DDCF,ABSOFT_cf3(T0),T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE)) _Icf(0,FF,T0,0,0) \ CFARGT14FS(NNNCF,DDDCF,_Z,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE); \ { CFARGT14S(QCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) \ _Icf(2,UU,T0,A0,0); _Icf(0,L,T0,0,0) CN( TCF(LN,T1,1,0) TCF(LN,T2,2,1) \ TCF(LN,T3,3,1) TCF(LN,T4,4,1) TCF(LN,T5,5,1) TCF(LN,T6,6,1) TCF(LN,T7,7,1) \ TCF(LN,T8,8,1) TCF(LN,T9,9,1) TCF(LN,TA,10,1) TCF(LN,TB,11,1) TCF(LN,TC,12,1) \ TCF(LN,TD,13,1) TCF(LN,TE,14,1) ); _Icf(0,K,T0,0,0) \ CFARGT14S(RCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE) _(T0,_cfI)} #define FCALLSCFUN27(T0,CN,UN,LN,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ CFextern _(T0,_cfF)(UN,LN) \ CFARGT27(NNCF,DDCF,ABSOFT_cf3(T0),T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR)) _Icf(0,FF,T0,0,0) \ CFARGT27FS(NNNCF,DDDCF,_Z,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR); \ { CFARGT27S(QCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) \ _Icf(2,UU,T0,A0,0); _Icf(0,L,T0,0,0) CN( TCF(LN,T1,1,0) TCF(LN,T2,2,1) \ TCF(LN,T3,3,1) TCF(LN,T4,4,1) TCF(LN,T5,5,1) TCF(LN,T6,6,1) TCF(LN,T7,7,1) \ TCF(LN,T8,8,1) TCF(LN,T9,9,1) TCF(LN,TA,10,1) TCF(LN,TB,11,1) TCF(LN,TC,12,1) \ TCF(LN,TD,13,1) TCF(LN,TE,14,1) TCF(LN,TF,15,1) TCF(LN,TG,16,1) TCF(LN,TH,17,1) \ TCF(LN,TI,18,1) TCF(LN,TJ,19,1) TCF(LN,TK,20,1) TCF(LN,TL,21,1) TCF(LN,TM,22,1) \ TCF(LN,TN,23,1) TCF(LN,TO,24,1) TCF(LN,TP,25,1) TCF(LN,TQ,26,1) TCF(LN,TR,27,1) ); _Icf(0,K,T0,0,0) \ CFARGT27S(RCF,T1,T2,T3,T4,T5,T6,T7,T8,T9,TA,TB,TC,TD,TE,TF,TG,TH,TI,TJ,TK,TL,TM,TN,TO,TP,TQ,TR) _(T0,_cfI)} #endif #endif /* __CFORTRAN_LOADED */ cfitsio/checksum.c0000644000225700000360000004230113246025103013746 0ustar cagordonlhea/* This file, checksum.c, contains the checksum-related routines in the */ /* FITSIO library. */ /* The FITSIO software was written by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ #include #include #include "fitsio2.h" /*------------------------------------------------------------------------*/ int ffcsum(fitsfile *fptr, /* I - FITS file pointer */ long nrec, /* I - number of 2880-byte blocks to sum */ unsigned long *sum, /* IO - accumulated checksum */ int *status) /* IO - error status */ /* Calculate a 32-bit 1's complement checksum of the FITS 2880-byte blocks. This routine is based on the C algorithm developed by Rob Seaman at NOAO that was presented at the 1994 ADASS conference, published in the Astronomical Society of the Pacific Conference Series. This uses a 32-bit 1's complement checksum in which the overflow bits are permuted back into the sum and therefore all bit positions are sampled evenly. */ { long ii, jj; unsigned short sbuf[1440]; unsigned long hi, lo, hicarry, locarry; if (*status > 0) return(*status); /* Sum the specified number of FITS 2880-byte records. This assumes that the FITSIO file pointer points to the start of the records to be summed. Read each FITS block as 1440 short values (do byte swapping if needed). */ for (jj = 0; jj < nrec; jj++) { ffgbyt(fptr, 2880, sbuf, status); #if BYTESWAPPED ffswap2( (short *)sbuf, 1440); /* reverse order of bytes in each value */ #endif hi = (*sum >> 16); lo = *sum & 0xFFFF; for (ii = 0; ii < 1440; ii += 2) { hi += sbuf[ii]; lo += sbuf[ii+1]; } hicarry = hi >> 16; /* fold carry bits in */ locarry = lo >> 16; while (hicarry | locarry) { hi = (hi & 0xFFFF) + locarry; lo = (lo & 0xFFFF) + hicarry; hicarry = hi >> 16; locarry = lo >> 16; } *sum = (hi << 16) + lo; } return(*status); } /*-------------------------------------------------------------------------*/ void ffesum(unsigned long sum, /* I - accumulated checksum */ int complm, /* I - = 1 to encode complement of the sum */ char *ascii) /* O - 16-char ASCII encoded checksum */ /* encode the 32 bit checksum by converting every 2 bits of each byte into an ASCII character (32 bit word encoded as 16 character string). Only ASCII letters and digits are used to encode the values (no ASCII punctuation characters). If complm=TRUE, then the complement of the sum will be encoded. This routine is based on the C algorithm developed by Rob Seaman at NOAO that was presented at the 1994 ADASS conference, published in the Astronomical Society of the Pacific Conference Series. */ { unsigned int exclude[13] = { 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60 }; unsigned long mask[4] = { 0xff000000, 0xff0000, 0xff00, 0xff }; int offset = 0x30; /* ASCII 0 (zero) */ unsigned long value; int byte, quotient, remainder, ch[4], check, ii, jj, kk; char asc[32]; if (complm) value = 0xFFFFFFFF - sum; /* complement each bit of the value */ else value = sum; for (ii = 0; ii < 4; ii++) { byte = (value & mask[ii]) >> (24 - (8 * ii)); quotient = byte / 4 + offset; remainder = byte % 4; for (jj = 0; jj < 4; jj++) ch[jj] = quotient; ch[0] += remainder; for (check = 1; check;) /* avoid ASCII punctuation */ for (check = 0, kk = 0; kk < 13; kk++) for (jj = 0; jj < 4; jj += 2) if ((unsigned char) ch[jj] == exclude[kk] || (unsigned char) ch[jj+1] == exclude[kk]) { ch[jj]++; ch[jj+1]--; check++; } for (jj = 0; jj < 4; jj++) /* assign the bytes */ asc[4*jj+ii] = ch[jj]; } for (ii = 0; ii < 16; ii++) /* shift the bytes 1 to the right */ ascii[ii] = asc[(ii+15)%16]; ascii[16] = '\0'; } /*-------------------------------------------------------------------------*/ unsigned long ffdsum(char *ascii, /* I - 16-char ASCII encoded checksum */ int complm, /* I - =1 to decode complement of the */ unsigned long *sum) /* O - 32-bit checksum */ /* decode the 16-char ASCII encoded checksum into an unsigned 32-bit long. If complm=TRUE, then the complement of the sum will be decoded. This routine is based on the C algorithm developed by Rob Seaman at NOAO that was presented at the 1994 ADASS conference, published in the Astronomical Society of the Pacific Conference Series. */ { char cbuf[16]; unsigned long hi = 0, lo = 0, hicarry, locarry; int ii; /* remove the permuted FITS byte alignment and the ASCII 0 offset */ for (ii = 0; ii < 16; ii++) { cbuf[ii] = ascii[(ii+1)%16]; cbuf[ii] -= 0x30; } for (ii = 0; ii < 16; ii += 4) { hi += (cbuf[ii] << 8) + cbuf[ii+1]; lo += (cbuf[ii+2] << 8) + cbuf[ii+3]; } hicarry = hi >> 16; locarry = lo >> 16; while (hicarry || locarry) { hi = (hi & 0xFFFF) + locarry; lo = (lo & 0xFFFF) + hicarry; hicarry = hi >> 16; locarry = lo >> 16; } *sum = (hi << 16) + lo; if (complm) *sum = 0xFFFFFFFF - *sum; /* complement each bit of the value */ return(*sum); } /*------------------------------------------------------------------------*/ int ffpcks(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ /* Create or update the checksum keywords in the CHDU. These keywords provide a checksum verification of the FITS HDU based on the ASCII coded 1's complement checksum algorithm developed by Rob Seaman at NOAO. */ { char datestr[20], checksum[FLEN_VALUE], datasum[FLEN_VALUE]; char comm[FLEN_COMMENT], chkcomm[FLEN_COMMENT], datacomm[FLEN_COMMENT]; int tstatus; long nrec; LONGLONG headstart, datastart, dataend; unsigned long dsum, olddsum, sum; double tdouble; if (*status > 0) /* inherit input status value if > 0 */ return(*status); /* generate current date string and construct the keyword comments */ ffgstm(datestr, NULL, status); strcpy(chkcomm, "HDU checksum updated "); strcat(chkcomm, datestr); strcpy(datacomm, "data unit checksum updated "); strcat(datacomm, datestr); /* write the CHECKSUM keyword if it does not exist */ tstatus = *status; if (ffgkys(fptr, "CHECKSUM", checksum, comm, status) == KEY_NO_EXIST) { *status = tstatus; strcpy(checksum, "0000000000000000"); ffpkys(fptr, "CHECKSUM", checksum, chkcomm, status); } /* write the DATASUM keyword if it does not exist */ tstatus = *status; if (ffgkys(fptr, "DATASUM", datasum, comm, status) == KEY_NO_EXIST) { *status = tstatus; olddsum = 0; ffpkys(fptr, "DATASUM", " 0", datacomm, status); /* set the CHECKSUM keyword as undefined, if it isn't already */ if (strcmp(checksum, "0000000000000000") ) { strcpy(checksum, "0000000000000000"); ffmkys(fptr, "CHECKSUM", checksum, chkcomm, status); } } else { /* decode the datasum into an unsigned long variable */ /* olddsum = strtoul(datasum, 0, 10); doesn't work on SUN OS */ tdouble = atof(datasum); olddsum = (unsigned long) tdouble; } /* close header: rewrite END keyword and following blank fill */ /* and re-read the required keywords to determine the structure */ if (ffrdef(fptr, status) > 0) return(*status); if ((fptr->Fptr)->heapsize > 0) ffuptf(fptr, status); /* update the variable length TFORM values */ /* write the correct data fill values, if they are not already correct */ if (ffpdfl(fptr, status) > 0) return(*status); /* calc size of data unit, in FITS 2880-byte blocks */ if (ffghadll(fptr, &headstart, &datastart, &dataend, status) > 0) return(*status); nrec = (long) ((dataend - datastart) / 2880); dsum = 0; if (nrec > 0) { /* accumulate the 32-bit 1's complement checksum */ ffmbyt(fptr, datastart, REPORT_EOF, status); if (ffcsum(fptr, nrec, &dsum, status) > 0) return(*status); } if (dsum != olddsum) { /* update the DATASUM keyword with the correct value */ snprintf(datasum, FLEN_VALUE, "%lu", dsum); ffmkys(fptr, "DATASUM", datasum, datacomm, status); /* set the CHECKSUM keyword as undefined, if it isn't already */ if (strcmp(checksum, "0000000000000000") ) { strcpy(checksum, "0000000000000000"); ffmkys(fptr, "CHECKSUM", checksum, chkcomm, status); } } if (strcmp(checksum, "0000000000000000") ) { /* check if CHECKSUM is still OK; move to the start of the header */ ffmbyt(fptr, headstart, REPORT_EOF, status); /* accumulate the header checksum into the previous data checksum */ nrec = (long) ((datastart - headstart) / 2880); sum = dsum; if (ffcsum(fptr, nrec, &sum, status) > 0) return(*status); if (sum == 0 || sum == 0xFFFFFFFF) return(*status); /* CHECKSUM is correct */ /* Zero the CHECKSUM and recompute the new value */ ffmkys(fptr, "CHECKSUM", "0000000000000000", chkcomm, status); } /* move to the start of the header */ ffmbyt(fptr, headstart, REPORT_EOF, status); /* accumulate the header checksum into the previous data checksum */ nrec = (long) ((datastart - headstart) / 2880); sum = dsum; if (ffcsum(fptr, nrec, &sum, status) > 0) return(*status); /* encode the COMPLEMENT of the checksum into a 16-character string */ ffesum(sum, TRUE, checksum); /* update the CHECKSUM keyword value with the new string */ ffmkys(fptr, "CHECKSUM", checksum, "&", status); return(*status); } /*------------------------------------------------------------------------*/ int ffupck(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ /* Update the CHECKSUM keyword value. This assumes that the DATASUM keyword exists and has the correct value. */ { char datestr[20], chkcomm[FLEN_COMMENT], comm[FLEN_COMMENT]; char checksum[FLEN_VALUE], datasum[FLEN_VALUE]; int tstatus; long nrec; LONGLONG headstart, datastart, dataend; unsigned long sum, dsum; double tdouble; if (*status > 0) /* inherit input status value if > 0 */ return(*status); /* generate current date string and construct the keyword comments */ ffgstm(datestr, NULL, status); strcpy(chkcomm, "HDU checksum updated "); strcat(chkcomm, datestr); /* get the DATASUM keyword and convert it to a unsigned long */ if (ffgkys(fptr, "DATASUM", datasum, comm, status) == KEY_NO_EXIST) { ffpmsg("DATASUM keyword not found (ffupck"); return(*status); } tdouble = atof(datasum); /* read as a double as a workaround */ dsum = (unsigned long) tdouble; /* get size of the HDU */ if (ffghadll(fptr, &headstart, &datastart, &dataend, status) > 0) return(*status); /* get the checksum keyword, if it exists */ tstatus = *status; if (ffgkys(fptr, "CHECKSUM", checksum, comm, status) == KEY_NO_EXIST) { *status = tstatus; strcpy(checksum, "0000000000000000"); ffpkys(fptr, "CHECKSUM", checksum, chkcomm, status); } else { /* check if CHECKSUM is still OK */ /* rewrite END keyword and following blank fill */ if (ffwend(fptr, status) > 0) return(*status); /* move to the start of the header */ ffmbyt(fptr, headstart, REPORT_EOF, status); /* accumulate the header checksum into the previous data checksum */ nrec = (long) ((datastart - headstart) / 2880); sum = dsum; if (ffcsum(fptr, nrec, &sum, status) > 0) return(*status); if (sum == 0 || sum == 0xFFFFFFFF) return(*status); /* CHECKSUM is already correct */ /* Zero the CHECKSUM and recompute the new value */ ffmkys(fptr, "CHECKSUM", "0000000000000000", chkcomm, status); } /* move to the start of the header */ ffmbyt(fptr, headstart, REPORT_EOF, status); /* accumulate the header checksum into the previous data checksum */ nrec = (long) ((datastart - headstart) / 2880); sum = dsum; if (ffcsum(fptr, nrec, &sum, status) > 0) return(*status); /* encode the COMPLEMENT of the checksum into a 16-character string */ ffesum(sum, TRUE, checksum); /* update the CHECKSUM keyword value with the new string */ ffmkys(fptr, "CHECKSUM", checksum, "&", status); return(*status); } /*------------------------------------------------------------------------*/ int ffvcks(fitsfile *fptr, /* I - FITS file pointer */ int *datastatus, /* O - data checksum status */ int *hdustatus, /* O - hdu checksum status */ /* 1 verification is correct */ /* 0 checksum keyword is not present */ /* -1 verification not correct */ int *status) /* IO - error status */ /* Verify the HDU by comparing the value of the computed checksums against the values of the DATASUM and CHECKSUM keywords if they are present. */ { int tstatus; double tdouble; unsigned long datasum, hdusum, olddatasum; char chksum[FLEN_VALUE], comm[FLEN_COMMENT]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); *datastatus = -1; *hdustatus = -1; tstatus = *status; if (ffgkys(fptr, "CHECKSUM", chksum, comm, status) == KEY_NO_EXIST) { *hdustatus = 0; /* CHECKSUM keyword does not exist */ *status = tstatus; } if (chksum[0] == '\0') *hdustatus = 0; /* all blank checksum means it is undefined */ if (ffgkys(fptr, "DATASUM", chksum, comm, status) == KEY_NO_EXIST) { *datastatus = 0; /* DATASUM keyword does not exist */ *status = tstatus; } if (chksum[0] == '\0') *datastatus = 0; /* all blank checksum means it is undefined */ if ( *status > 0 || (!(*hdustatus) && !(*datastatus)) ) return(*status); /* return if neither keywords exist */ /* convert string to unsigned long */ /* olddatasum = strtoul(chksum, 0, 10); doesn't work w/ gcc on SUN OS */ /* sscanf(chksum, "%u", &olddatasum); doesn't work w/ cc on VAX/VMS */ tdouble = atof(chksum); /* read as a double as a workaround */ olddatasum = (unsigned long) tdouble; /* calculate the data checksum and the HDU checksum */ if (ffgcks(fptr, &datasum, &hdusum, status) > 0) return(*status); if (*datastatus) if (datasum == olddatasum) *datastatus = 1; if (*hdustatus) if (hdusum == 0 || hdusum == 0xFFFFFFFF) *hdustatus = 1; return(*status); } /*------------------------------------------------------------------------*/ int ffgcks(fitsfile *fptr, /* I - FITS file pointer */ unsigned long *datasum, /* O - data checksum */ unsigned long *hdusum, /* O - hdu checksum */ int *status) /* IO - error status */ /* calculate the checksums of the data unit and the total HDU */ { long nrec; LONGLONG headstart, datastart, dataend; if (*status > 0) /* inherit input status value if > 0 */ return(*status); /* get size of the HDU */ if (ffghadll(fptr, &headstart, &datastart, &dataend, status) > 0) return(*status); nrec = (long) ((dataend - datastart) / 2880); *datasum = 0; if (nrec > 0) { /* accumulate the 32-bit 1's complement checksum */ ffmbyt(fptr, datastart, REPORT_EOF, status); if (ffcsum(fptr, nrec, datasum, status) > 0) return(*status); } /* move to the start of the header and calc. size of header */ ffmbyt(fptr, headstart, REPORT_EOF, status); nrec = (long) ((datastart - headstart) / 2880); /* accumulate the header checksum into the previous data checksum */ *hdusum = *datasum; ffcsum(fptr, nrec, hdusum, status); return(*status); } cfitsio/config.guess0000755000225700000360000012743213246025103014331 0ustar cagordonlhea#! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012 Free Software Foundation, Inc. timestamp='2012-02-10' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Per Bothner. Please send patches (context # diff format) to and include a ChangeLog # entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm:riscos:*:*|arm:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build SUN_ARCH="i386" # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH="x86_64" fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; i*:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-gnu else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo ${UNAME_MACHINE}-unknown-linux-gnueabi else echo ${UNAME_MACHINE}-unknown-linux-gnueabihf fi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; cris:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-gnu exit ;; crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-gnu exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; hexagon:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; i*86:Linux:*:*) LIBC=gnu eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __dietlibc__ LIBC=dietlibc #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` echo "${UNAME_MACHINE}-pc-linux-${LIBC}" exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } ;; or32:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; padre:Linux:*:*) echo sparc-unknown-linux-gnu exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-gnu exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-gnu ;; PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-gnu exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; tile*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-gnu exit ;; x86_64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configury will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown case $UNAME_PROCESSOR in i386) eval $set_cc_for_build if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then UNAME_PROCESSOR="x86_64" fi fi ;; unknown) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-?:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-?:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix\n"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; c34*) echo c34-convex-bsd exit ;; c38*) echo c38-convex-bsd exit ;; c4*) echo c4-convex-bsd exit ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: cfitsio/config.sub0000755000225700000360000010527413246025103013774 0ustar cagordonlhea#! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012 Free Software Foundation, Inc. timestamp='2012-04-18' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Please send patches to . Submit a context # diff and a properly formatted GNU ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ | be32 | be64 \ | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | epiphany \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 \ | ns16k | ns32k \ | open8 \ | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze) basic_machine=microblaze-xilinx ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i386-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -kaos*) os=-kaos ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: cfitsio/configure0000755000225700000360000064365313246025103013730 0ustar cagordonlhea#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= PACKAGE_URL= ac_unique_file="fitscore.c" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_default_prefix=`pwd` ac_subst_vars='LTLIBOBJS LIBOBJS my_shmem LDFLAGS_BIN F77_WRAPPERS CFITSIO_SHLIB_SONAME CFITSIO_SHLIB SHLIB_SUFFIX SHLIB_LD LIBPRE ARCH CURLCONFIG GCCVERSION SSE_FLAGS RANLIB ARCHIVE AR FC INSTALL_ROOT EGREP GREP CPP OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC CFITSIO_SONAME CFITSIO_MINOR CFITSIO_MAJOR target_os target_vendor target_cpu target host_os host_vendor host_cpu host build_os build_vendor build_cpu build target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_reentrant enable_sse2 enable_ssse3 enable_hera with_gsiftp_flavour with_gsiftp with_bzip2 ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures this package to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] --target=TARGET configure for building compilers for TARGET [HOST] _ACEOF fi if test -n "$ac_init_help"; then cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-reentrant Enable reentrant multithreading --enable-sse2 Enable use of instructions in the SSE2 extended instruction set --enable-ssse3 Enable use of instructions in the SSSE3 extended instruction set --enable-hera Build for HERA (ASD use only) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-gsiftp-flavour[=PATH] Enable Globus Toolkit gsiftp protocol support --with-gsiftp[=PATH] Enable Globus Toolkit gsiftp protocol support --with-bzip2[=PATH] Enable bzip2 support. Optional path to the location of include/bzlib.h and lib/libbz2 Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF configure generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 $as_echo_n "checking target system type... " >&6; } if ${ac_cv_target+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$target_alias" = x; then ac_cv_target=$ac_cv_host else ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5 $as_echo "$ac_cv_target" >&6; } case $ac_cv_target in *-*-*) ;; *) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;; esac target=$ac_cv_target ac_save_IFS=$IFS; IFS='-' set x $ac_cv_target shift target_cpu=$1 target_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: target_os=$* IFS=$ac_save_IFS case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac # The aliases save the names the user supplied, while $host etc. # will get canonicalized. test -n "$target_alias" && test "$program_prefix$program_suffix$program_transform_name" = \ NONENONEs,x,x, && program_prefix=${target_alias}- #-------------------------------------------------------------------- # CFITSIO Version Numbers: #-------------------------------------------------------------------- CFITSIO_MAJOR=3 CFITSIO_MINOR=43 # Increment soname each time the interface changes: CFITSIO_SONAME=5 #-------------------------------------------------------------------- # Command options #-------------------------------------------------------------------- # Check whether --enable-reentrant was given. if test "${enable_reentrant+set}" = set; then : enableval=$enable_reentrant; if test $enableval = yes; then BUILD_REENTRANT=yes; fi fi SSE_FLAGS="" # Check whether --enable-sse2 was given. if test "${enable_sse2+set}" = set; then : enableval=$enable_sse2; if test $enableval = yes; then SSE_FLAGS="-msse2"; fi fi # Check whether --enable-ssse3 was given. if test "${enable_ssse3+set}" = set; then : enableval=$enable_ssse3; if test $enableval = yes; then SSE_FLAGS="$SSE_FLAGS -mssse3"; fi fi # Define BUILD_HERA when building for HERA project to activate code in # drvrfile.c (by way of fitsio2.h): # Check whether --enable-hera was given. if test "${enable_hera+set}" = set; then : enableval=$enable_hera; if test $enableval = yes; then BUILD_HERA=yes; fi fi if test "x$BUILD_HERA" = xyes; then $as_echo "#define BUILD_HERA 1" >>confdefs.h fi # Check whether --with-gsiftp-flavour was given. if test "${with_gsiftp_flavour+set}" = set; then : withval=$with_gsiftp_flavour; if test "x$withval" != "xno"; then if test "x$withval" != "xyes" ; then GSIFTP_FLAVOUR=${withval} fi $as_echo "#define GSIFTP_FLAVOUR 1" >>confdefs.h fi fi # Check whether --with-gsiftp was given. if test "${with_gsiftp+set}" = set; then : withval=$with_gsiftp; if test "x$withval" != "xno"; then if test "x$withval" != "xyes" ; then GSIFTP_PATH=${withval} HAVE_GSIFTP=yes fi $as_echo "#define HAVE_GSIFTP 1" >>confdefs.h fi fi # Enable support for bzip2 compression (disabled by default): ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # Check whether --with-bzip2 was given. if test "${with_bzip2+set}" = set; then : withval=$with_bzip2; if test "x$withval" != "xno"; then if test "x$withval" = "xyes" ; then for ac_header in bzlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "bzlib.h" "ac_cv_header_bzlib_h" "$ac_includes_default" if test "x$ac_cv_header_bzlib_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_BZLIB_H 1 _ACEOF $as_echo "#define HAVE_BZIP2 1" >>confdefs.h fi done else BZIP2_PATH=${withval} fi fi fi #-------------------------------------------------------------------- # Check for install location prefix #-------------------------------------------------------------------- # make will complain about duplicate targets for the install directories # if prefix == exec_prefix INSTALL_ROOT='${prefix}' test "$exec_prefix" != NONE -a "$prefix" != "$exec_prefix" \ && INSTALL_ROOT="$INSTALL_ROOT "'${exec_prefix}' #-------------------------------------------------------------------- # System type #-------------------------------------------------------------------- case $host in *cygwin*) ARCH="cygwin" EXT="cygwin" ;; *apple-darwin*) # Darwin can be powerpc, i386, or x86_64 ARCH=`uname -p` EXT="darwin" ;; *freebsd*) ARCH="linux" EXT="lnx" ;; *hpux*) ARCH="hp" EXT="hpu" ;; *irix*) ARCH="sgi" EXT="sgi" ;; *linux*) ARCH="linux" EXT="lnx" ;; *mingw32*) #ARCH="" EXT="mingw32" ;; *osf1*) ARCH="alpha" EXT="osf" ;; *solaris*) ARCH="solaris" EXT="sol" ;; *ultrix*) ARCH="dec" EXT="dec" ;; *) echo "cfitsio: == Don't know what do do with $host" ;; esac # Try first to find a proprietary C compiler, then gcc if test "x$EXT" != xcygwin && test "x$EXT" != xdarwin && test "x$EXT" != xlnx && test "x$EXT" != xmingw32; then if test "x$CC" = x; then for ac_prog in cc do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu LDFLAGS="$CFLAGS" LDFLAGS_BIN="$LDFLAGS" if test "x$FC" = "xnone" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: cfitsio: == Fortran compiler search has been overridden" >&5 $as_echo "$as_me: cfitsio: == Fortran compiler search has been overridden" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: cfitsio: == Cfitsio will be built without Fortran wrapper support" >&5 $as_echo "$as_me: cfitsio: == Cfitsio will be built without Fortran wrapper support" >&6;} FC= F77_WRAPPERS= else for ac_prog in gfortran g95 g77 f77 ifort f95 f90 xlf cf77 gf77 af77 ncf f2c do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_FC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$FC"; then ac_cv_prog_FC="$FC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_FC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi FC=$ac_cv_prog_FC if test -n "$FC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FC" >&5 $as_echo "$FC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$FC" && break done test -n "$FC" || FC="notfound" if test $FC = 'notfound' ; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cfitsio: == No acceptable Fortran compiler found in \$PATH" >&5 $as_echo "$as_me: WARNING: cfitsio: == No acceptable Fortran compiler found in \$PATH" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: cfitsio: == Adding wrapper support for GNU Fortran by default" >&5 $as_echo "$as_me: cfitsio: == Adding wrapper support for GNU Fortran by default" >&6;} CFORTRANFLAGS="-Dg77Fortran" F77_WRAPPERS="\${FITSIO_SRC}" else CFORTRANFLAGS= F77_WRAPPERS="\${FITSIO_SRC}" echo $ac_n "checking whether we are using GNU Fortran""... $ac_c" 1>&6 if test `$FC --version -c < /dev/null 2> /dev/null | grep -c GNU` -gt 0 -o \ `$FC --version -c < /dev/null 2> /dev/null | grep -ic egcs` -gt 0 then echo "$ac_t""yes" 1>&6 echo $ac_n "cfitsio: == Adding wrapper support for GNU Fortran""... $ac_c" 1>&6 CFORTRANFLAGS="-Dg77Fortran" echo "$ac_t"" done" 1>&6 else echo "$ac_t""no" 1>&6 if test $FC = 'f2c' ; then echo $ac_n "cfitsio: == Adding wrapper support for f2c""... $ac_c" 1>&6 CFORTRANFLAGS="-Df2cFortran" echo "$ac_t"" done" 1>&6 fi fi fi fi # ar & ranlib required #--------------------- # Extract the first word of "ar", so it can be a program name with args. set dummy ar; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="ar" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_AR" && ac_cv_prog_AR="noar" fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test $AR = noar; then as_fn_error $? "ar not found in your \$PATH. See your sysdamin." "$LINENO" 5 fi ARCHIVE="$AR rv" if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi for ac_header in stdlib.h string.h math.h limits.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF ANSI_HEADER=yes else ANSI_HEADER=no fi done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { void d( int , double) ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : PROTO=yes else PROTO=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ANSI_HEADER = no -o $PROTO = no; then echo " *********** WARNING: CFITSIO CONFIGURE FAILURE ************ " echo "cfitsio: ANSI C environment NOT found. Aborting cfitsio configure." if test $ANSI_HEADER = no; then echo "cfitsio: You're missing a needed ANSI header file." fi if test $PROTO = no; then echo "cfitsio: Your compiler can't do ANSI function prototypes." fi echo "cfitsio: You need an ANSI C compiler and all ANSI trappings" echo "cfitsio: to build cfitsio. " echo " ******************************************************* " exit 0; fi if test "x$SSE_FLAGS" != x; then SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $SSE_FLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts $SSE_FLAGS" >&5 $as_echo_n "checking whether $CC accepts $SSE_FLAGS... " >&6; } ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : c_has_option=yes else c_has_option=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $c_has_option" >&5 $as_echo "$c_has_option" >&6; } ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test "$c_has_option" = no; then SSE_FLAGS=""; fi CFLAGS="$SAVE_CFLAGS" fi CFLAGS="$CFLAGS" LIBPRE="" case $host in *cygwin*) CFLAGS="$CFLAGS -DHAVE_POSIX_SIGNALS" ;; *apple-darwin*) # Build for i386 & x86_64 architectures on Darwin 10.x or newer: case $host in *darwin[56789]*) ;; *) echo "int main(){return(0);}" > /tmp/$$.c $CC -v -o /tmp/$$.out /tmp/$$.c 2> /tmp/$$.log if test `cat /tmp/$$.log | grep -ci 'LLVM'` -ne 0; then APPLEXCODE="yes"; fi if test "x$APPLEXCODE" = xyes; then # Flags for building Universal binaries: C_UNIV_SWITCH="-arch i386 -arch x86_64" CFLAGS="$CFLAGS $C_UNIV_SWITCH" fi # LDFLAGS used by utilities: LDFLAGS_BIN="$LDFLAGS_BIN -Wl,-rpath,\${CFITSIO_LIB}" ;; esac # For large file support (but may break Absoft compilers): $as_echo "#define _LARGEFILE_SOURCE 1" >>confdefs.h $as_echo "#define _FILE_OFFSET_BITS 64" >>confdefs.h ;; *hpux*) if test "x$CFORTRANFLAGS" = x ; then CFORTRANFLAGS="-Dappendus" fi CFLAGS="$CFLAGS -DPG_PPU" LIBPRE="-Wl," ;; *irix*) CFLAGS="$CFLAGS -DHAVE_POSIX_SIGNALS" RANLIB="touch" ;; *linux*) # For large file support: $as_echo "#define _LARGEFILE_SOURCE 1" >>confdefs.h $as_echo "#define _FILE_OFFSET_BITS 64" >>confdefs.h ;; *mingw32*) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for large file support" >&5 $as_echo_n "checking for large file support... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { _FILE_OFFSET_BITS_SET_FSEEKO ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : $as_echo "#define _LARGEFILE_SOURCE 1" >>confdefs.h $as_echo "#define _FILE_OFFSET_BITS 64" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ;; *solaris*) if test "x$CFORTRANFLAGS" = x ; then CFORTRANFLAGS="-Dsolaris" fi # We need libm on Solaris: { $as_echo "$as_me:${as_lineno-$LINENO}: checking for frexp in -lm" >&5 $as_echo_n "checking for frexp in -lm... " >&6; } if ${ac_cv_lib_m_frexp+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char frexp (); int main () { return frexp (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_m_frexp=yes else ac_cv_lib_m_frexp=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_frexp" >&5 $as_echo "$ac_cv_lib_m_frexp" >&6; } if test "x$ac_cv_lib_m_frexp" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBM 1 _ACEOF LIBS="-lm $LIBS" fi # For large file support: $as_echo "#define _LARGEFILE_SOURCE 1" >>confdefs.h $as_echo "#define _FILE_OFFSET_BITS 64" >>confdefs.h ;; *) echo "cfitsio: == Don't know what do do with $host" ;; esac CFLAGS="$CFLAGS $CFORTRANFLAGS" case $GCC in yes) GCCVERSION="`$CC -dumpversion 2>&1`" echo "cfitsio: == Using gcc version $GCCVERSION" gcc_test=`echo $GCCVERSION | grep -c '2\.[45678]'` if test $gcc_test -gt 0 then CFLAGS=`echo $CFLAGS | sed 's:-O[^ ]* *::'` { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: This gcc is pretty old. Disabling optimization to be safe." >&5 $as_echo "$as_me: WARNING: This gcc is pretty old. Disabling optimization to be safe." >&2;} fi ;; no) echo "cfitsio: Old CFLAGS is $CFLAGS" CFLAGS=`echo $CFLAGS | sed -e "s/-g/-O/"` case $host in *solaris*) if test `echo $CFLAGS | grep -c fast` -gt 0 then echo "cfitsio: Replacing -fast with -O3" CFLAGS=`echo $CFLAGS | sed 's:-fast:-O3:'` fi CFLAGS="$CFLAGS -DHAVE_ALLOCA_H -DHAVE_POSIX_SIGNALS" ;; *) echo "== No special changes for $host" ;; esac echo "New CFLAGS is $CFLAGS" ;; *) # Don't do anything now ;; esac # GSIFTP flags: if test "x$GSIFTP_PATH" != x -a "x$GSIFTP_FLAVOUR" != x; then CFLAGS="$CFLAGS -I${GSIFTP_PATH}/include/${GSIFTP_FLAVOUR}" LDFLAGS="$LDFLAGS -L${GSIFTP_PATH}/lib -lglobus_ftp_client_${GSIFTP_FLAVOUR}" fi # BZIP2 flags: if test "x$BZIP2_PATH" != x; then CFLAGS="$CFLAGS -I${BZIP2_PATH}/include" LDFLAGS="$LDFLAGS -L${BZIP2_PATH}/lib -lbz2" fi # Shared library section #------------------------------------------------------------------------------- SHLIB_LD=: SHLIB_SUFFIX=".so" CFITSIO_SHLIB="" CFITSIO_SHLIB_SONAME="" lhea_shlib_cflags= case $EXT in cygwin|mingw32) SHLIB_LD="$CC -shared" SHLIB_SUFFIX=".dll" ;; darwin) SHLIB_SUFFIX=".dylib" CFITSIO_SHLIB="lib\${PACKAGE}.\${CFITSIO_SONAME}.\${CFITSIO_MAJOR}.\${CFITSIO_MINOR}\${SHLIB_SUFFIX}" CFITSIO_SHLIB_SONAME="lib\${PACKAGE}.\${CFITSIO_SONAME}\${SHLIB_SUFFIX}" case $host in *darwin[56789]*) SHLIB_LD="$CC -dynamiclib -install_name lib\${PACKAGE}.\${CFITSIO_SONAME}\${SHLIB_SUFFIX} -compatibility_version \${CFITSIO_SONAME} -current_version \${CFITSIO_SONAME}.\${CFITSIO_MAJOR}.\${CFITSIO_MINOR}" ;; *) # Build 'Universal' binaries (i386 & x86_64 architectures) and # use rpath token on Darwin 10.x or newer: SHLIB_LD="$CC -dynamiclib $C_UNIV_SWITCH -headerpad_max_install_names -install_name @rpath/lib\${PACKAGE}.\${CFITSIO_SONAME}\${SHLIB_SUFFIX} -compatibility_version \${CFITSIO_SONAME} -current_version \${CFITSIO_SONAME}.\${CFITSIO_MAJOR}.\${CFITSIO_MINOR}" ;; esac lhea_shlib_cflags="-fPIC -fno-common" ;; hpu) SHLIB_LD="ld -b" SHLIB_SUFFIX=".sl" ;; lnx) SHLIB_LD=":" CFITSIO_SHLIB="lib\${PACKAGE}\${SHLIB_SUFFIX}.\${CFITSIO_SONAME}.\${CFITSIO_MAJOR}.\${CFITSIO_MINOR}" CFITSIO_SHLIB_SONAME="lib\${PACKAGE}\${SHLIB_SUFFIX}.\${CFITSIO_SONAME}" ;; osf) SHLIB_LD="ld -shared -expect_unresolved '*'" LD_FLAGS="-taso" ;; sol) SHLIB_LD="/usr/ccs/bin/ld -G" lhea_shlib_cflags="-KPIC" ;; sgi) SHLIB_LD="ld -shared -rdata_shared" ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to determine how to make a shared library" >&5 $as_echo "$as_me: WARNING: Unable to determine how to make a shared library" >&2;} ;; esac # Darwin uses gcc (=cc), but needs different flags (see above) if test "x$EXT" != xdarwin && test "x$EXT" != xcygwin && test "x$EXT" != xmingw32; then if test "x$GCC" = xyes; then SHLIB_LD="$CC -shared -Wl,-soname,lib\${PACKAGE}\${SHLIB_SUFFIX}.\${CFITSIO_SONAME}" lhea_shlib_cflags='-fPIC' fi fi if test "x$lhea_shlib_cflags" != x; then CFLAGS="$CFLAGS $lhea_shlib_cflags" fi # Set shared library name for cases in which we aren't setting a 'soname': if test "x$CFITSIO_SHLIB" = x; then CFITSIO_SHLIB="lib\${PACKAGE}\${SHLIB_SUFFIX}"; fi # Curl library (will be pulled in to the shared CFITSIO library): # --------------------------------------------------------------- CURL_LIB="" CURL_INC="" # Use curl-config to get compiler & linker flags, if available. # On Macs, prefer XCode curl-config, and reject MacPorts version # until further notice to prevent build errors: if test "x$EXT" = xdarwin -a -x /usr/bin/curl-config; then CURLCONFIG="/usr/bin/curl-config" { $as_echo "$as_me:${as_lineno-$LINENO}: result: checking for curl-config... choosing /usr/bin/curl-config on Mac" >&5 $as_echo "checking for curl-config... choosing /usr/bin/curl-config on Mac" >&6; } else # Extract the first word of "curl-config", so it can be a program name with args. set dummy curl-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CURLCONFIG+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CURLCONFIG"; then ac_cv_prog_CURLCONFIG="$CURLCONFIG" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/opt/local/bin/curl-config"; then ac_prog_rejected=yes continue fi ac_cv_prog_CURLCONFIG="curl-config" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CURLCONFIG shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CURLCONFIG to just the basename; use the full file name. shift ac_cv_prog_CURLCONFIG="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CURLCONFIG=$ac_cv_prog_CURLCONFIG if test -n "$CURLCONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CURLCONFIG" >&5 $as_echo "$CURLCONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test "x$CURLCONFIG" != x; then CURL_LIB=`$CURLCONFIG --libs` CURL_INC=`$CURLCONFIG --cflags` # Also reject anaconda curl on Macs until further notice: if test "x$EXT" = xdarwin -a `echo $CURL_LIB $CURL_INC | grep -ci anaconda` -gt 0; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Rejecting Anaconda curl. Disabling HTTPS support." >&5 $as_echo "$as_me: WARNING: Rejecting Anaconda curl. Disabling HTTPS support." >&2;} else LIBS="$CURL_LIB $LIBS" if test "x$CURL_INC" != x; then CFLAGS="$CURL_INC $CFLAGS" fi $as_echo "#define CFITSIO_HAVE_CURL 1" >>confdefs.h fi # No curl-config: else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: curl-config not found. Disabling HTTPS support." >&5 $as_echo "$as_me: WARNING: curl-config not found. Disabling HTTPS support." >&2;} # Incomplete stubs for possible future use: # AC_CHECK_LIB([curl],[main],[], # [AC_MSG_WARN(Not building curl support for CFITSIO)]) # AC_CHECK_HEADER(curl.h,[]) fi # ================= test for the unix ftruncate function ================ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ftruncate works" >&5 $as_echo_n "checking whether ftruncate works... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { ftruncate(0, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : $as_echo "#define HAVE_FTRUNCATE 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext # --------------------------------------------------------- # some systems define long long for 64-bit ints # --------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether long long is defined" >&5 $as_echo_n "checking whether long long is defined... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { long long filler; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : $as_echo "#define HAVE_LONGLONG 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # ==================== SHARED MEMORY DRIVER SECTION ======================= # # 09-Mar-98 : modified by JB/ISDC # 3 checks added to support autoconfiguration of shared memory # driver. First generic check is made whether shared memory is supported # at all, then 2 more specific checks are made (architecture dependent). # Currently tested on : sparc-solaris, intel-linux, sgi-irix, dec-alpha-osf # ------------------------------------------------------------------------- # check is System V IPC is supported on this machine # ------------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether system V style IPC services are supported" >&5 $as_echo_n "checking whether system V style IPC services are supported... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { shmat(0, 0, 0); shmdt(0); shmget(0, 0, 0); semget(0, 0, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : $as_echo "#define HAVE_SHMEM_SERVICES 1" >>confdefs.h my_shmem=\${SOURCES_SHMEM} { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext # ------------------------------------------------------------------------- # some systems define flock_t, for others we have to define it ourselves # ------------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking do we have flock_t defined in sys/fcntl.h" >&5 $as_echo_n "checking do we have flock_t defined in sys/fcntl.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { flock_t filler; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : $as_echo "#define HAVE_FLOCK_T 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test "$HAVE_FLOCK_T" != 1; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking do we have flock_t defined in sys/flock.h" >&5 $as_echo_n "checking do we have flock_t defined in sys/flock.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { flock_t filler; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : $as_echo "#define HAVE_FLOCK_T 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi # ------------------------------------------------------------------------------ # Define _REENTRANT & add -lpthread to LIBS if reentrant multithreading enabled: # ------------------------------------------------------------------------------ if test "x$BUILD_REENTRANT" = xyes; then $as_echo "#define _REENTRANT 1" >>confdefs.h $as_echo "#define _XOPEN_SOURCE 700" >>confdefs.h # Additional definition needed to get 'union semun' when using # _XOPEN_SOURCE on a Mac: if test "x$EXT" = xdarwin; then $as_echo "#define _DARWIN_C_SOURCE 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lpthread" >&5 $as_echo_n "checking for main in -lpthread... " >&6; } if ${ac_cv_lib_pthread_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pthread_main=yes else ac_cv_lib_pthread_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_main" >&5 $as_echo "$ac_cv_lib_pthread_main" >&6; } if test "x$ac_cv_lib_pthread_main" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBPTHREAD 1 _ACEOF LIBS="-lpthread $LIBS" else as_fn_error $? "Unable to locate pthread library needed when enabling reentrant multithreading" "$LINENO" 5 fi fi # ------------------------------------------------------------------------- # there are some idiosyncrasies with semun defs (used in semxxx). Solaris # does not define it at all # ------------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking do we have union semun defined" >&5 $as_echo_n "checking do we have union semun defined... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { union semun filler; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : $as_echo "#define HAVE_UNION_SEMUN 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # ==================== END OF SHARED MEMORY DRIVER SECTION ================ # ================= test for the unix networking functions ================ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5 $as_echo_n "checking for library containing gethostbyname... " >&6; } if ${ac_cv_search_gethostbyname+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostbyname (); int main () { return gethostbyname (); ; return 0; } _ACEOF for ac_lib in '' nsl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_gethostbyname=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_gethostbyname+:} false; then : break fi done if ${ac_cv_search_gethostbyname+:} false; then : else ac_cv_search_gethostbyname=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5 $as_echo "$ac_cv_search_gethostbyname" >&6; } ac_res=$ac_cv_search_gethostbyname if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" cfitsio_have_nsl=1 else cfitsio_have_nsl=0 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing connect" >&5 $as_echo_n "checking for library containing connect... " >&6; } if ${ac_cv_search_connect+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char connect (); int main () { return connect (); ; return 0; } _ACEOF for ac_lib in '' socket; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib -lnsl $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_connect=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_connect+:} false; then : break fi done if ${ac_cv_search_connect+:} false; then : else ac_cv_search_connect=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_connect" >&5 $as_echo "$ac_cv_search_connect" >&6; } ac_res=$ac_cv_search_connect if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" cfitsio_have_socket=1 else cfitsio_have_socket=0 fi if test "$cfitsio_have_nsl" = 1 -a "$cfitsio_have_socket" = 1; then $as_echo "#define HAVE_NET_SERVICES 1" >>confdefs.h fi # ==================== END OF unix networking SECTION ================ ac_config_files="$ac_config_files Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by $as_me, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi ac_config_files="$ac_config_files cfitsio.pc" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by $as_me, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "cfitsio.pc") CONFIG_FILES="$CONFIG_FILES cfitsio.pc" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5 $as_echo "" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: Congratulations, Makefile update was successful." >&5 $as_echo " Congratulations, Makefile update was successful." >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: You may want to run \"make\" now." >&5 $as_echo " You may want to run \"make\" now." >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5 $as_echo "" >&6; } cfitsio/configure.in0000644000225700000360000004506013246025103014316 0ustar cagordonlhea# # configure.in for cfitsio # # /redshift/sgi6/lheavc/ftools/cfitsio/configure.in,v 3.4 1996/07/26 20:27:53 pence Exp # # copied from host and modified # dnl Process this file with autoconf to produce a configure script. AC_INIT AC_CONFIG_SRCDIR([fitscore.c]) AC_CANONICAL_TARGET([]) #-------------------------------------------------------------------- # CFITSIO Version Numbers: #-------------------------------------------------------------------- AC_SUBST(CFITSIO_MAJOR,3) AC_SUBST(CFITSIO_MINOR,43) # Increment soname each time the interface changes: AC_SUBST(CFITSIO_SONAME,5) #-------------------------------------------------------------------- # Command options #-------------------------------------------------------------------- AC_ARG_ENABLE( reentrant, [AS_HELP_STRING([--enable-reentrant],[Enable reentrant multithreading])], [ if test $enableval = yes; then BUILD_REENTRANT=yes; fi ] ) SSE_FLAGS="" AC_ARG_ENABLE( sse2, [AS_HELP_STRING([--enable-sse2],[Enable use of instructions in the SSE2 extended instruction set])], [ if test $enableval = yes; then SSE_FLAGS="-msse2"; fi ] ) AC_ARG_ENABLE( ssse3, [AS_HELP_STRING([--enable-ssse3],[Enable use of instructions in the SSSE3 extended instruction set])], [ if test $enableval = yes; then SSE_FLAGS="$SSE_FLAGS -mssse3"; fi ] ) # Define BUILD_HERA when building for HERA project to activate code in # drvrfile.c (by way of fitsio2.h): AC_ARG_ENABLE( hera, [AS_HELP_STRING([--enable-hera],[Build for HERA (ASD use only)])], [ if test $enableval = yes; then BUILD_HERA=yes; fi ] ) if test "x$BUILD_HERA" = xyes; then AC_DEFINE(BUILD_HERA) fi AC_ARG_WITH( gsiftp-flavour, [AS_HELP_STRING([--with-gsiftp-flavour[[=PATH]]],[Enable Globus Toolkit gsiftp protocol support])], [ if test "x$withval" != "xno"; then if test "x$withval" != "xyes" ; then GSIFTP_FLAVOUR=${withval} fi AC_DEFINE(GSIFTP_FLAVOUR,1,[Define Globus Toolkit architecture]) fi ] ) AC_ARG_WITH( gsiftp, [AS_HELP_STRING([--with-gsiftp[[=PATH]]],[Enable Globus Toolkit gsiftp protocol support])], [ if test "x$withval" != "xno"; then if test "x$withval" != "xyes" ; then GSIFTP_PATH=${withval} HAVE_GSIFTP=yes fi AC_DEFINE(HAVE_GSIFTP,1,[Define if you want Globus Toolkit gsiftp protocol support]) fi ] ) # Enable support for bzip2 compression (disabled by default): AC_ARG_WITH( bzip2, [AS_HELP_STRING([--with-bzip2[[=PATH]]],[Enable bzip2 support. Optional path to the location of include/bzlib.h and lib/libbz2])], [ if test "x$withval" != "xno"; then if test "x$withval" = "xyes" ; then AC_CHECK_HEADERS(bzlib.h, [AC_DEFINE(HAVE_BZIP2,1,[Define if you want bzip2 read support])] ) else BZIP2_PATH=${withval} fi fi ] ) #-------------------------------------------------------------------- # Check for install location prefix #-------------------------------------------------------------------- AC_PREFIX_DEFAULT(`pwd`) # make will complain about duplicate targets for the install directories # if prefix == exec_prefix AC_SUBST(INSTALL_ROOT,'${prefix}') test "$exec_prefix" != NONE -a "$prefix" != "$exec_prefix" \ && INSTALL_ROOT="$INSTALL_ROOT "'${exec_prefix}' #-------------------------------------------------------------------- # System type #-------------------------------------------------------------------- case $host in *cygwin*) ARCH="cygwin" EXT="cygwin" ;; *apple-darwin*) # Darwin can be powerpc, i386, or x86_64 ARCH=`uname -p` EXT="darwin" ;; *freebsd*) ARCH="linux" EXT="lnx" ;; *hpux*) ARCH="hp" EXT="hpu" ;; *irix*) ARCH="sgi" EXT="sgi" ;; *linux*) ARCH="linux" EXT="lnx" ;; *mingw32*) #ARCH="" EXT="mingw32" ;; *osf1*) ARCH="alpha" EXT="osf" ;; *solaris*) ARCH="solaris" EXT="sol" ;; *ultrix*) ARCH="dec" EXT="dec" ;; *) echo "cfitsio: == Don't know what do do with $host" ;; esac dnl Checks for programs. # Try first to find a proprietary C compiler, then gcc if test "x$EXT" != xcygwin && test "x$EXT" != xdarwin && test "x$EXT" != xlnx && test "x$EXT" != xmingw32; then if test "x$CC" = x; then AC_CHECK_PROGS(CC, cc) fi fi AC_PROG_CC LDFLAGS="$CFLAGS" LDFLAGS_BIN="$LDFLAGS" if test "x$FC" = "xnone" ; then AC_MSG_NOTICE(cfitsio: == Fortran compiler search has been overridden) AC_MSG_NOTICE(cfitsio: == Cfitsio will be built without Fortran wrapper support) FC= F77_WRAPPERS= else AC_CHECK_PROGS(FC, gfortran g95 g77 f77 ifort f95 f90 xlf cf77 gf77 af77 ncf f2c, notfound) if test $FC = 'notfound' ; then AC_MSG_WARN(cfitsio: == No acceptable Fortran compiler found in \$PATH) AC_MSG_NOTICE(cfitsio: == Adding wrapper support for GNU Fortran by default) CFORTRANFLAGS="-Dg77Fortran" F77_WRAPPERS="\${FITSIO_SRC}" else CFORTRANFLAGS= F77_WRAPPERS="\${FITSIO_SRC}" echo $ac_n "checking whether we are using GNU Fortran""... $ac_c" 1>&6 if test `$FC --version -c < /dev/null 2> /dev/null | grep -c GNU` -gt 0 -o \ `$FC --version -c < /dev/null 2> /dev/null | grep -ic egcs` -gt 0 then echo "$ac_t""yes" 1>&6 echo $ac_n "cfitsio: == Adding wrapper support for GNU Fortran""... $ac_c" 1>&6 CFORTRANFLAGS="-Dg77Fortran" echo "$ac_t"" done" 1>&6 else echo "$ac_t""no" 1>&6 if test $FC = 'f2c' ; then echo $ac_n "cfitsio: == Adding wrapper support for f2c""... $ac_c" 1>&6 CFORTRANFLAGS="-Df2cFortran" echo "$ac_t"" done" 1>&6 fi fi fi fi # ar & ranlib required #--------------------- AC_CHECK_PROG(AR, ar, ar, noar) if test $AR = noar; then AC_MSG_ERROR(ar not found in your \$PATH. See your sysdamin.) fi ARCHIVE="$AR rv" AC_SUBST(ARCHIVE) AC_PROG_RANLIB dnl Checks for ANSI stdlib.h. AC_CHECK_HEADERS(stdlib.h string.h math.h limits.h ,ANSI_HEADER=yes,ANSI_HEADER=no)dnl dnl Check if prototyping is allowed. AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[void d( int , double) ]])],[PROTO=yes],[PROTO=no])dnl if test $ANSI_HEADER = no -o $PROTO = no; then echo " *********** WARNING: CFITSIO CONFIGURE FAILURE ************ " echo "cfitsio: ANSI C environment NOT found. Aborting cfitsio configure." if test $ANSI_HEADER = no; then echo "cfitsio: You're missing a needed ANSI header file." fi if test $PROTO = no; then echo "cfitsio: Your compiler can't do ANSI function prototypes." fi echo "cfitsio: You need an ANSI C compiler and all ANSI trappings" echo "cfitsio: to build cfitsio. " echo " ******************************************************* " exit 0; fi dnl Check if C compiler supports sse extended instruction flags. if test "x$SSE_FLAGS" != x; then SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $SSE_FLAGS" AC_MSG_CHECKING([whether $CC accepts $SSE_FLAGS]) AC_LANG_PUSH([C]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],[c_has_option=yes],[c_has_option=no]) AC_MSG_RESULT($c_has_option) AC_LANG_POP([]) if test "$c_has_option" = no; then SSE_FLAGS=""; fi CFLAGS="$SAVE_CFLAGS" fi AC_SUBST(SSE_FLAGS) CFLAGS="$CFLAGS" LIBPRE="" case $host in *cygwin*) CFLAGS="$CFLAGS -DHAVE_POSIX_SIGNALS" ;; *apple-darwin*) # Build for i386 & x86_64 architectures on Darwin 10.x or newer: changequote(,) case $host in *darwin[56789]*) ;; *) changequote([,]) echo "int main(){return(0);}" > /tmp/$$.c $CC -v -o /tmp/$$.out /tmp/$$.c 2> /tmp/$$.log if test `cat /tmp/$$.log | grep -ci 'LLVM'` -ne 0; then APPLEXCODE="yes"; fi if test "x$APPLEXCODE" = xyes; then # Flags for building Universal binaries: C_UNIV_SWITCH="-arch i386 -arch x86_64" CFLAGS="$CFLAGS $C_UNIV_SWITCH" fi # LDFLAGS used by utilities: LDFLAGS_BIN="$LDFLAGS_BIN -Wl,-rpath,\${CFITSIO_LIB}" ;; esac # For large file support (but may break Absoft compilers): AC_DEFINE(_LARGEFILE_SOURCE) AC_DEFINE(_FILE_OFFSET_BITS,64) ;; *hpux*) if test "x$CFORTRANFLAGS" = x ; then CFORTRANFLAGS="-Dappendus" fi CFLAGS="$CFLAGS -DPG_PPU" LIBPRE="-Wl," ;; *irix*) CFLAGS="$CFLAGS -DHAVE_POSIX_SIGNALS" RANLIB="touch" ;; *linux*) # For large file support: AC_DEFINE(_LARGEFILE_SOURCE) AC_DEFINE(_FILE_OFFSET_BITS,64) ;; *mingw32*) AC_MSG_CHECKING([for large file support]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include ], [_FILE_OFFSET_BITS_SET_FSEEKO])],[ AC_DEFINE(_LARGEFILE_SOURCE) AC_DEFINE(_FILE_OFFSET_BITS,64) AC_MSG_RESULT(yes) ],[AC_MSG_RESULT(no)]) ;; *solaris*) if test "x$CFORTRANFLAGS" = x ; then CFORTRANFLAGS="-Dsolaris" fi # We need libm on Solaris: AC_CHECK_LIB(m, frexp) # For large file support: AC_DEFINE(_LARGEFILE_SOURCE) AC_DEFINE(_FILE_OFFSET_BITS,64) ;; *) echo "cfitsio: == Don't know what do do with $host" ;; esac CFLAGS="$CFLAGS $CFORTRANFLAGS" case $GCC in yes) GCCVERSION="`$CC -dumpversion 2>&1`" echo "cfitsio: == Using gcc version $GCCVERSION" AC_SUBST(GCCVERSION) changequote(,) gcc_test=`echo $GCCVERSION | grep -c '2\.[45678]'` changequote([,]) if test $gcc_test -gt 0 then changequote(,) CFLAGS=`echo $CFLAGS | sed 's:-O[^ ]* *::'` changequote([,]) AC_MSG_WARN(This gcc is pretty old. Disabling optimization to be safe.) fi ;; no) echo "cfitsio: Old CFLAGS is $CFLAGS" CFLAGS=`echo $CFLAGS | sed -e "s/-g/-O/"` case $host in *solaris*) changequote(,) if test `echo $CFLAGS | grep -c fast` -gt 0 then echo "cfitsio: Replacing -fast with -O3" CFLAGS=`echo $CFLAGS | sed 's:-fast:-O3:'` fi changequote([,]) CFLAGS="$CFLAGS -DHAVE_ALLOCA_H -DHAVE_POSIX_SIGNALS" ;; *) echo "== No special changes for $host" ;; esac echo "New CFLAGS is $CFLAGS" ;; *) # Don't do anything now ;; esac # GSIFTP flags: if test "x$GSIFTP_PATH" != x -a "x$GSIFTP_FLAVOUR" != x; then CFLAGS="$CFLAGS -I${GSIFTP_PATH}/include/${GSIFTP_FLAVOUR}" LDFLAGS="$LDFLAGS -L${GSIFTP_PATH}/lib -lglobus_ftp_client_${GSIFTP_FLAVOUR}" fi # BZIP2 flags: if test "x$BZIP2_PATH" != x; then CFLAGS="$CFLAGS -I${BZIP2_PATH}/include" LDFLAGS="$LDFLAGS -L${BZIP2_PATH}/lib -lbz2" fi # Shared library section #------------------------------------------------------------------------------- SHLIB_LD=: SHLIB_SUFFIX=".so" CFITSIO_SHLIB="" CFITSIO_SHLIB_SONAME="" lhea_shlib_cflags= case $EXT in cygwin|mingw32) SHLIB_LD="$CC -shared" SHLIB_SUFFIX=".dll" ;; darwin) changequote(,) SHLIB_SUFFIX=".dylib" CFITSIO_SHLIB="lib\${PACKAGE}.\${CFITSIO_SONAME}.\${CFITSIO_MAJOR}.\${CFITSIO_MINOR}\${SHLIB_SUFFIX}" CFITSIO_SHLIB_SONAME="lib\${PACKAGE}.\${CFITSIO_SONAME}\${SHLIB_SUFFIX}" case $host in *darwin[56789]*) SHLIB_LD="$CC -dynamiclib -install_name lib\${PACKAGE}.\${CFITSIO_SONAME}\${SHLIB_SUFFIX} -compatibility_version \${CFITSIO_SONAME} -current_version \${CFITSIO_SONAME}.\${CFITSIO_MAJOR}.\${CFITSIO_MINOR}" ;; *) # Build 'Universal' binaries (i386 & x86_64 architectures) and # use rpath token on Darwin 10.x or newer: SHLIB_LD="$CC -dynamiclib $C_UNIV_SWITCH -headerpad_max_install_names -install_name @rpath/lib\${PACKAGE}.\${CFITSIO_SONAME}\${SHLIB_SUFFIX} -compatibility_version \${CFITSIO_SONAME} -current_version \${CFITSIO_SONAME}.\${CFITSIO_MAJOR}.\${CFITSIO_MINOR}" ;; esac changequote([,]) lhea_shlib_cflags="-fPIC -fno-common" ;; hpu) SHLIB_LD="ld -b" SHLIB_SUFFIX=".sl" ;; lnx) SHLIB_LD=":" CFITSIO_SHLIB="lib\${PACKAGE}\${SHLIB_SUFFIX}.\${CFITSIO_SONAME}.\${CFITSIO_MAJOR}.\${CFITSIO_MINOR}" CFITSIO_SHLIB_SONAME="lib\${PACKAGE}\${SHLIB_SUFFIX}.\${CFITSIO_SONAME}" ;; osf) SHLIB_LD="ld -shared -expect_unresolved '*'" LD_FLAGS="-taso" ;; sol) SHLIB_LD="/usr/ccs/bin/ld -G" lhea_shlib_cflags="-KPIC" ;; sgi) SHLIB_LD="ld -shared -rdata_shared" ;; *) AC_MSG_WARN(Unable to determine how to make a shared library) ;; esac # Darwin uses gcc (=cc), but needs different flags (see above) if test "x$EXT" != xdarwin && test "x$EXT" != xcygwin && test "x$EXT" != xmingw32; then if test "x$GCC" = xyes; then SHLIB_LD="$CC -shared -Wl,-soname,lib\${PACKAGE}\${SHLIB_SUFFIX}.\${CFITSIO_SONAME}" lhea_shlib_cflags='-fPIC' fi fi if test "x$lhea_shlib_cflags" != x; then CFLAGS="$CFLAGS $lhea_shlib_cflags" fi # Set shared library name for cases in which we aren't setting a 'soname': if test "x$CFITSIO_SHLIB" = x; then CFITSIO_SHLIB="lib\${PACKAGE}\${SHLIB_SUFFIX}"; fi # Curl library (will be pulled in to the shared CFITSIO library): # --------------------------------------------------------------- CURL_LIB="" CURL_INC="" # Use curl-config to get compiler & linker flags, if available. # On Macs, prefer XCode curl-config, and reject MacPorts version # until further notice to prevent build errors: if test "x$EXT" = xdarwin -a -x /usr/bin/curl-config; then CURLCONFIG="/usr/bin/curl-config" AC_MSG_RESULT(checking for curl-config... choosing /usr/bin/curl-config on Mac) else AC_CHECK_PROG([CURLCONFIG], [curl-config], [curl-config], [], [], [/opt/local/bin/curl-config]) fi if test "x$CURLCONFIG" != x; then CURL_LIB=`$CURLCONFIG --libs` CURL_INC=`$CURLCONFIG --cflags` # Also reject anaconda curl on Macs until further notice: if test "x$EXT" = xdarwin -a `echo $CURL_LIB $CURL_INC | grep -ci anaconda` -gt 0; then AC_MSG_WARN(Rejecting Anaconda curl. Disabling HTTPS support.) else LIBS="$CURL_LIB $LIBS" if test "x$CURL_INC" != x; then CFLAGS="$CURL_INC $CFLAGS" fi AC_DEFINE(CFITSIO_HAVE_CURL) fi # No curl-config: else AC_MSG_WARN(curl-config not found. Disabling HTTPS support.) # Incomplete stubs for possible future use: # AC_CHECK_LIB([curl],[main],[], # [AC_MSG_WARN(Not building curl support for CFITSIO)]) # AC_CHECK_HEADER(curl.h,[]) fi AC_SUBST(ARCH)dnl AC_SUBST(CFLAGS)dnl AC_SUBST(CC)dnl AC_SUBST(FC)dnl AC_SUBST(LIBPRE)dnl AC_SUBST(SHLIB_LD)dnl AC_SUBST(SHLIB_SUFFIX)dnl AC_SUBST(CFITSIO_SHLIB)dnl AC_SUBST(CFITSIO_SHLIB_SONAME)dnl AC_SUBST(F77_WRAPPERS) AC_SUBST(LDFLAGS_BIN) # ================= test for the unix ftruncate function ================ AC_MSG_CHECKING(whether ftruncate works) AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ ftruncate(0, 0); ]])],[ AC_DEFINE(HAVE_FTRUNCATE) AC_MSG_RESULT(yes) ],[AC_MSG_RESULT(no) ]) # --------------------------------------------------------- # some systems define long long for 64-bit ints # --------------------------------------------------------- AC_MSG_CHECKING(whether long long is defined) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ long long filler; ]])],[ AC_DEFINE(HAVE_LONGLONG) AC_MSG_RESULT(yes) ],[AC_MSG_RESULT(no) ]) # ==================== SHARED MEMORY DRIVER SECTION ======================= # # 09-Mar-98 : modified by JB/ISDC # 3 checks added to support autoconfiguration of shared memory # driver. First generic check is made whether shared memory is supported # at all, then 2 more specific checks are made (architecture dependent). # Currently tested on : sparc-solaris, intel-linux, sgi-irix, dec-alpha-osf # ------------------------------------------------------------------------- # check is System V IPC is supported on this machine # ------------------------------------------------------------------------- AC_MSG_CHECKING(whether system V style IPC services are supported) AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include #include #include ]], [[ shmat(0, 0, 0); shmdt(0); shmget(0, 0, 0); semget(0, 0, 0); ]])],[ AC_DEFINE(HAVE_SHMEM_SERVICES) my_shmem=\${SOURCES_SHMEM} AC_MSG_RESULT(yes) ],[AC_MSG_RESULT(no) ]) AC_SUBST(my_shmem) # ------------------------------------------------------------------------- # some systems define flock_t, for others we have to define it ourselves # ------------------------------------------------------------------------- AC_MSG_CHECKING(do we have flock_t defined in sys/fcntl.h) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ flock_t filler; ]])],[ AC_DEFINE(HAVE_FLOCK_T) AC_MSG_RESULT(yes) ],[AC_MSG_RESULT(no) ]) if test "$HAVE_FLOCK_T" != 1; then AC_MSG_CHECKING(do we have flock_t defined in sys/flock.h) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ flock_t filler; ]])],[ AC_DEFINE(HAVE_FLOCK_T) AC_MSG_RESULT(yes) ],[AC_MSG_RESULT(no) ]) fi # ------------------------------------------------------------------------------ # Define _REENTRANT & add -lpthread to LIBS if reentrant multithreading enabled: # ------------------------------------------------------------------------------ if test "x$BUILD_REENTRANT" = xyes; then AC_DEFINE(_REENTRANT) AC_DEFINE([_XOPEN_SOURCE], [700]) # Additional definition needed to get 'union semun' when using # _XOPEN_SOURCE on a Mac: if test "x$EXT" = xdarwin; then AC_DEFINE([_DARWIN_C_SOURCE]) fi AC_CHECK_LIB([pthread],[main],[],[AC_MSG_ERROR(Unable to locate pthread library needed when enabling reentrant multithreading)]) fi # ------------------------------------------------------------------------- # there are some idiosyncrasies with semun defs (used in semxxx). Solaris # does not define it at all # ------------------------------------------------------------------------- AC_MSG_CHECKING(do we have union semun defined) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include #include #include ]], [[ union semun filler; ]])],[ AC_DEFINE(HAVE_UNION_SEMUN) AC_MSG_RESULT(yes) ],[AC_MSG_RESULT(no) ]) # ==================== END OF SHARED MEMORY DRIVER SECTION ================ # ================= test for the unix networking functions ================ AC_SEARCH_LIBS([gethostbyname], [nsl], cfitsio_have_nsl=1, cfitsio_have_nsl=0) AC_SEARCH_LIBS([connect], [socket], cfitsio_have_socket=1, cfitsio_have_socket=0, [-lnsl]) if test "$cfitsio_have_nsl" = 1 -a "$cfitsio_have_socket" = 1; then AC_DEFINE(HAVE_NET_SERVICES) fi # ==================== END OF unix networking SECTION ================ AC_CONFIG_FILES([Makefile]) AC_OUTPUT AC_CONFIG_FILES([cfitsio.pc]) AC_OUTPUT AC_MSG_RESULT([]) AC_MSG_RESULT([ Congratulations, Makefile update was successful.]) AC_MSG_RESULT([ You may want to run \"make\" now.]) AC_MSG_RESULT([]) cfitsio/cookbook.c0000644000225700000360000005254213246025103013762 0ustar cagordonlhea#include #include #include /* Every program which uses the CFITSIO interface must include the the fitsio.h header file. This contains the prototypes for all the routines and defines the error status values and other symbolic constants used in the interface. */ #include "fitsio.h" int main( void ); void writeimage( void ); void writeascii( void ); void writebintable( void ); void copyhdu( void ); void selectrows( void ); void readheader( void ); void readimage( void ); void readtable( void ); void printerror( int status); int main() { /************************************************************************* This is a simple main program that calls the following routines: writeimage - write a FITS primary array image writeascii - write a FITS ASCII table extension writebintable - write a FITS binary table extension copyhdu - copy a header/data unit from one FITS file to another selectrows - copy selected row from one HDU to another readheader - read and print the header keywords in every extension readimage - read a FITS image and compute the min and max value readtable - read columns of data from ASCII and binary tables **************************************************************************/ writeimage(); writeascii(); writebintable(); copyhdu(); selectrows(); readheader(); readimage(); readtable(); printf("\nAll the cfitsio cookbook routines ran successfully.\n"); return(0); } /*--------------------------------------------------------------------------*/ void writeimage( void ) /******************************************************/ /* Create a FITS primary array containing a 2-D image */ /******************************************************/ { fitsfile *fptr; /* pointer to the FITS file, defined in fitsio.h */ int status, ii, jj; long fpixel, nelements, exposure; unsigned short *array[200]; /* initialize FITS image parameters */ char filename[] = "atestfil.fit"; /* name for new FITS file */ int bitpix = USHORT_IMG; /* 16-bit unsigned short pixel values */ long naxis = 2; /* 2-dimensional image */ long naxes[2] = { 300, 200 }; /* image is 300 pixels wide by 200 rows */ /* allocate memory for the whole image */ array[0] = (unsigned short *)malloc( naxes[0] * naxes[1] * sizeof( unsigned short ) ); /* initialize pointers to the start of each row of the image */ for( ii=1; ii 0) { nbuffer = npixels; if (npixels > buffsize) nbuffer = buffsize; /* read as many pixels as will fit in buffer */ /* Note that even though the FITS images contains unsigned integer */ /* pixel values (or more accurately, signed integer pixels with */ /* a bias of 32768), this routine is reading the values into a */ /* float array. Cfitsio automatically performs the datatype */ /* conversion in cases like this. */ if ( fits_read_img(fptr, TFLOAT, fpixel, nbuffer, &nullval, buffer, &anynull, &status) ) printerror( status ); for (ii = 0; ii < nbuffer; ii++) { if ( buffer[ii] < datamin ) datamin = buffer[ii]; if ( buffer[ii] > datamax ) datamax = buffer[ii]; } npixels -= nbuffer; /* increment remaining number of pixels */ fpixel += nbuffer; /* next pixel to be read in image */ } printf("\nMin and max image pixels = %.0f, %.0f\n", datamin, datamax); if ( fits_close_file(fptr, &status) ) printerror( status ); return; } /*--------------------------------------------------------------------------*/ void readtable( void ) /************************************************************/ /* read and print data values from an ASCII or binary table */ /************************************************************/ { fitsfile *fptr; /* pointer to the FITS file, defined in fitsio.h */ int status, hdunum, hdutype, nfound, anynull, ii; long frow, felem, nelem, longnull, dia[6]; float floatnull, den[6]; char strnull[10], *name[6], *ttype[3]; char filename[] = "atestfil.fit"; /* name of existing FITS file */ status = 0; if ( fits_open_file(&fptr, filename, READONLY, &status) ) printerror( status ); for (ii = 0; ii < 3; ii++) /* allocate space for the column labels */ ttype[ii] = (char *) malloc(FLEN_VALUE); /* max label length = 69 */ for (ii = 0; ii < 6; ii++) /* allocate space for string column value */ name[ii] = (char *) malloc(10); for (hdunum = 2; hdunum <= 3; hdunum++) /*read ASCII, then binary table */ { /* move to the HDU */ if ( fits_movabs_hdu(fptr, hdunum, &hdutype, &status) ) printerror( status ); if (hdutype == ASCII_TBL) printf("\nReading ASCII table in HDU %d:\n", hdunum); else if (hdutype == BINARY_TBL) printf("\nReading binary table in HDU %d:\n", hdunum); else { printf("Error: this HDU is not an ASCII or binary table\n"); printerror( status ); } /* read the column names from the TTYPEn keywords */ fits_read_keys_str(fptr, "TTYPE", 1, 3, ttype, &nfound, &status); printf(" Row %10s %10s %10s\n", ttype[0], ttype[1], ttype[2]); frow = 1; felem = 1; nelem = 6; strcpy(strnull, " "); longnull = 0; floatnull = 0.; /* read the columns */ fits_read_col(fptr, TSTRING, 1, frow, felem, nelem, strnull, name, &anynull, &status); fits_read_col(fptr, TLONG, 2, frow, felem, nelem, &longnull, dia, &anynull, &status); fits_read_col(fptr, TFLOAT, 3, frow, felem, nelem, &floatnull, den, &anynull, &status); for (ii = 0; ii < 6; ii++) printf("%5d %10s %10ld %10.2f\n", ii + 1, name[ii], dia[ii], den[ii]); } for (ii = 0; ii < 3; ii++) /* free the memory for the column labels */ free( ttype[ii] ); for (ii = 0; ii < 6; ii++) /* free the memory for the string column */ free( name[ii] ); if ( fits_close_file(fptr, &status) ) printerror( status ); return; } /*--------------------------------------------------------------------------*/ void printerror( int status) { /*****************************************************/ /* Print out cfitsio error messages and exit program */ /*****************************************************/ if (status) { fits_report_error(stderr, status); /* print error report */ exit( status ); /* terminate the program, returning error status */ } return; } cfitsio/cookbook.f0000644000225700000360000007277313246025103013775 0ustar cagordonlhea program main C This is the FITSIO cookbook program that contains an annotated listing of C various computer programs that read and write files in FITS format C using the FITSIO subroutine interface. These examples are C working programs which users may adapt and modify for their own C purposes. This Cookbook serves as a companion to the FITSIO User's C Guide that provides more complete documentation on all the C available FITSIO subroutines. C Call each subroutine in turn: call writeimage call writeascii call writebintable call copyhdu call selectrows call readheader call readimage call readtable print * print *,"All the fitsio cookbook routines ran successfully." end C ************************************************************************* subroutine writeimage C Create a FITS primary array containing a 2-D image integer status,unit,blocksize,bitpix,naxis,naxes(2) integer i,j,group,fpixel,nelements,array(300,200) character filename*80 logical simple,extend C The STATUS parameter must be initialized before using FITSIO. A C positive value of STATUS is returned whenever a serious error occurs. C FITSIO uses an `inherited status' convention, which means that if a C subroutine is called with a positive input value of STATUS, then the C subroutine will exit immediately, preserving the status value. For C simplicity, this program only checks the status value at the end of C the program, but it is usually better practice to check the status C value more frequently. status=0 C Name of the FITS file to be created: filename='ATESTFILEZ.FITS' C Delete the file if it already exists, so we can then recreate it. C The deletefile subroutine is listed at the end of this file. call deletefile(filename,status) C Get an unused Logical Unit Number to use to open the FITS file. C This routine is not required; programmers can choose any unused C unit number to open the file. call ftgiou(unit,status) C Create the new empty FITS file. The blocksize parameter is a C historical artifact and the value is ignored by FITSIO. blocksize=1 call ftinit(unit,filename,blocksize,status) C Initialize parameters about the FITS image. C BITPIX = 16 means that the image pixels will consist of 16-bit C integers. The size of the image is given by the NAXES values. C The EXTEND = TRUE parameter indicates that the FITS file C may contain extensions following the primary array. simple=.true. bitpix=16 naxis=2 naxes(1)=300 naxes(2)=200 extend=.true. C Write the required header keywords to the file call ftphpr(unit,simple,bitpix,naxis,naxes,0,1,extend,status) C Initialize the values in the image with a linear ramp function do j=1,naxes(2) do i=1,naxes(1) array(i,j)=i - 1 +j - 1 end do end do C Write the array to the FITS file. C The last letter of the subroutine name defines the datatype of the C array argument; in this case the 'J' indicates that the array has an C integer*4 datatype. ('I' = I*2, 'E' = Real*4, 'D' = Real*8). C The 2D array is treated as a single 1-D array with NAXIS1 * NAXIS2 C total number of pixels. GROUP is seldom used parameter that should C almost always be set = 1. group=1 fpixel=1 nelements=naxes(1)*naxes(2) call ftpprj(unit,group,fpixel,nelements,array,status) C Write another optional keyword to the header C The keyword record will look like this in the FITS file: C C EXPOSURE= 1500 / Total Exposure Time C call ftpkyj(unit,'EXPOSURE',1500,'Total Exposure Time',status) C The FITS file must always be closed before exiting the program. C Any unit numbers allocated with FTGIOU must be freed with FTFIOU. call ftclos(unit, status) call ftfiou(unit, status) C Check for any errors, and if so print out error messages. C The PRINTERROR subroutine is listed near the end of this file. if (status .gt. 0)call printerror(status) end C ************************************************************************* subroutine writeascii C Create an ASCII table containing 3 columns and 6 rows. For convenience, C the ASCII table extension is appended to the FITS image file created C previously by the WRITEIMAGE subroutine. integer status,unit,readwrite,blocksize,tfields,nrows,rowlen integer nspace,tbcol(3),diameter(6), colnum,frow,felem real density(6) character filename*40,extname*16 character*16 ttype(3),tform(3),tunit(3),name(6) data ttype/'Planet','Diameter','Density'/ data tform/'A8','I6','F4.2'/ data tunit/' ','km','g/cm'/ data name/'Mercury','Venus','Earth','Mars','Jupiter','Saturn'/ data diameter/4880,12112,12742,6800,143000,121000/ data density/5.1,5.3,5.52,3.94,1.33,0.69/ C The STATUS parameter must always be initialized. status=0 C Name of the FITS file to append the ASCII table to: filename='ATESTFILEZ.FITS' C Get an unused Logical Unit Number to use to open the FITS file. call ftgiou(unit,status) C Open the FITS file with write access. C (readwrite = 0 would open the file with readonly access). readwrite=1 call ftopen(unit,filename,readwrite,blocksize,status) C FTCRHD creates a new empty FITS extension following the current C extension and moves to it. In this case, FITSIO was initially C positioned on the primary array when the FITS file was first opened, so C FTCRHD appends an empty extension and moves to it. All future FITSIO C calls then operate on the new extension (which will be an ASCII C table). call ftcrhd(unit,status) C define parameters for the ASCII table (see the above data statements) tfields=3 nrows=6 extname='PLANETS_ASCII' C FTGABC is a convenient subroutine for calculating the total width of C the table and the starting position of each column in an ASCII table. C Any number of blank spaces (including zero) may be inserted between C each column of the table, as specified by the NSPACE parameter. nspace=1 call ftgabc(tfields,tform,nspace,rowlen,tbcol,status) C FTPHTB writes all the required header keywords which define the C structure of the ASCII table. NROWS and TFIELDS give the number of C rows and columns in the table, and the TTYPE, TBCOL, TFORM, and TUNIT C arrays give the column name, starting position, format, and units, C respectively of each column. The values of the ROWLEN and TBCOL parameters C were previously calculated by the FTGABC routine. call ftphtb(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit, & extname,status) C Write names to the first column, diameters to 2nd col., and density to 3rd C FTPCLS writes the string values to the NAME column (column 1) of the C table. The FTPCLJ and FTPCLE routines write the diameter (integer) and C density (real) value to the 2nd and 3rd columns. The FITSIO routines C are column oriented, so it is usually easier to read or write data in a C table in a column by column order rather than row by row. frow=1 felem=1 colnum=1 call ftpcls(unit,colnum,frow,felem,nrows,name,status) colnum=2 call ftpclj(unit,colnum,frow,felem,nrows,diameter,status) colnum=3 call ftpcle(unit,colnum,frow,felem,nrows,density,status) C The FITS file must always be closed before exiting the program. C Any unit numbers allocated with FTGIOU must be freed with FTFIOU. call ftclos(unit, status) call ftfiou(unit, status) C Check for any error, and if so print out error messages. C The PRINTERROR subroutine is listed near the end of this file. if (status .gt. 0)call printerror(status) end C ************************************************************************* subroutine writebintable C This routine creates a FITS binary table, or BINTABLE, containing C 3 columns and 6 rows. This routine is nearly identical to the C previous WRITEASCII routine, except that the call to FTGABC is not C needed, and FTPHBN is called rather than FTPHTB to write the C required header keywords. integer status,unit,readwrite,blocksize,hdutype,tfields,nrows integer varidat,diameter(6), colnum,frow,felem real density(6) character filename*40,extname*16 character*16 ttype(3),tform(3),tunit(3),name(6) data ttype/'Planet','Diameter','Density'/ data tform/'8A','1J','1E'/ data tunit/' ','km','g/cm'/ data name/'Mercury','Venus','Earth','Mars','Jupiter','Saturn'/ data diameter/4880,12112,12742,6800,143000,121000/ data density/5.1,5.3,5.52,3.94,1.33,0.69/ C The STATUS parameter must always be initialized. status=0 C Name of the FITS file to append the ASCII table to: filename='ATESTFILEZ.FITS' C Get an unused Logical Unit Number to use to open the FITS file. call ftgiou(unit,status) C Open the FITS file, with write access. readwrite=1 call ftopen(unit,filename,readwrite,blocksize,status) C Move to the last (2nd) HDU in the file (the ASCII table). call ftmahd(unit,2,hdutype,status) C Append/create a new empty HDU onto the end of the file and move to it. call ftcrhd(unit,status) C Define parameters for the binary table (see the above data statements) tfields=3 nrows=6 extname='PLANETS_BINARY' varidat=0 C FTPHBN writes all the required header keywords which define the C structure of the binary table. NROWS and TFIELDS gives the number of C rows and columns in the table, and the TTYPE, TFORM, and TUNIT arrays C give the column name, format, and units, respectively of each column. call ftphbn(unit,nrows,tfields,ttype,tform,tunit, & extname,varidat,status) C Write names to the first column, diameters to 2nd col., and density to 3rd C FTPCLS writes the string values to the NAME column (column 1) of the C table. The FTPCLJ and FTPCLE routines write the diameter (integer) and C density (real) value to the 2nd and 3rd columns. The FITSIO routines C are column oriented, so it is usually easier to read or write data in a C table in a column by column order rather than row by row. Note that C the identical subroutine calls are used to write to either ASCII or C binary FITS tables. frow=1 felem=1 colnum=1 call ftpcls(unit,colnum,frow,felem,nrows,name,status) colnum=2 call ftpclj(unit,colnum,frow,felem,nrows,diameter,status) colnum=3 call ftpcle(unit,colnum,frow,felem,nrows,density,status) C The FITS file must always be closed before exiting the program. C Any unit numbers allocated with FTGIOU must be freed with FTFIOU. call ftclos(unit, status) call ftfiou(unit, status) C Check for any error, and if so print out error messages. C The PRINTERROR subroutine is listed near the end of this file. if (status .gt. 0)call printerror(status) end C ************************************************************************* subroutine copyhdu C Copy the 1st and 3rd HDUs from the input file to a new FITS file integer status,inunit,outunit,readwrite,blocksize,morekeys,hdutype character infilename*40,outfilename*40 C The STATUS parameter must always be initialized. status=0 C Name of the FITS files: infilename='ATESTFILEZ.FITS' outfilename='BTESTFILEZ.FITS' C Delete the file if it already exists, so we can then recreate it C The deletefile subroutine is listed at the end of this file. call deletefile(outfilename,status) C Get unused Logical Unit Numbers to use to open the FITS files. call ftgiou(inunit,status) call ftgiou(outunit,status) C Open the input FITS file, with readonly access readwrite=0 call ftopen(inunit,infilename,readwrite,blocksize,status) C Create the new empty FITS file (value of blocksize is ignored) blocksize=1 call ftinit(outunit,outfilename,blocksize,status) C FTCOPY copies the current HDU from the input FITS file to the output C file. The MOREKEY parameter allows one to reserve space for additional C header keywords when the HDU is created. FITSIO will automatically C insert more header space if required, so programmers do not have to C reserve space ahead of time, although it is more efficient to do so if C it is known that more keywords will be appended to the header. morekeys=0 call ftcopy(inunit,outunit,morekeys,status) C Append/create a new empty extension on the end of the output file call ftcrhd(outunit,status) C Skip to the 3rd extension in the input file which in this case C is the binary table created by the previous WRITEBINARY routine. call ftmahd(inunit,3,hdutype,status) C FTCOPY now copies the binary table from the input FITS file C to the output file. call ftcopy(inunit,outunit,morekeys,status) C The FITS files must always be closed before exiting the program. C Any unit numbers allocated with FTGIOU must be freed with FTFIOU. C Giving -1 for the value of the first argument causes all previously C allocated unit numbers to be released. call ftclos(inunit, status) call ftclos(outunit, status) call ftfiou(-1, status) C Check for any error, and if so print out error messages. C The PRINTERROR subroutine is listed near the end of this file. if (status .gt. 0)call printerror(status) end C ************************************************************************* subroutine selectrows C This routine copies selected rows from an input table into a new output C FITS table. In this example all the rows in the input table that have C a value of the DENSITY column less that 3.0 are copied to the output C table. This program illustrates several generally useful techniques, C including: C how to locate the end of a FITS file C how to create a table when the total number of rows in the table C is not known until the table is completed C how to efficiently copy entire rows from one table to another. integer status,inunit,outunit,readwrite,blocksize,hdutype integer nkeys,nspace,naxes(2),nfound,colnum,frow,felem integer noutrows,irow,temp(100),i real nullval,density(6) character infilename*40,outfilename*40,record*80 logical exact,anynulls C The STATUS parameter must always be initialized. status=0 C Names of the FITS files: infilename='ATESTFILEZ.FITS' outfilename='BTESTFILEZ.FITS' C Get unused Logical Unit Numbers to use to open the FITS files. call ftgiou(inunit,status) call ftgiou(outunit,status) C The input FITS file is opened with READONLY access, and the output C FITS file is opened with WRITE access. readwrite=0 call ftopen(inunit,infilename,readwrite,blocksize,status) readwrite=1 call ftopen(outunit,outfilename,readwrite,blocksize,status) C move to the 3rd HDU in the input file (a binary table in this case) call ftmahd(inunit,3,hdutype,status) C This do-loop illustrates how to move to the last extension in any FITS C file. The call to FTMRHD moves one extension at a time through the C FITS file until an `End-of-file' status value (= 107) is returned. do while (status .eq. 0) call ftmrhd(outunit,1,hdutype,status) end do C After locating the end of the FITS file, it is necessary to reset the C status value to zero and also clear the internal error message stack C in FITSIO. The previous `End-of-file' error will have produced C an unimportant message on the error stack which can be cleared with C the call to the FTCMSG routine (which has no arguments). if (status .eq. 107)then status=0 call ftcmsg end if C Create a new empty extension in the output file. call ftcrhd(outunit,status) C Find the number of keywords in the input table header. call ftghsp(inunit,nkeys,nspace,status) C This do-loop of calls to FTGREC and FTPREC copies all the keywords from C the input to the output FITS file. Notice that the specified number C of rows in the output table, as given by the NAXIS2 keyword, will be C incorrect. This value will be modified later after it is known how many C rows will be in the table, so it does not matter how many rows are specified C initially. do i=1,nkeys call ftgrec(inunit,i,record,status) call ftprec(outunit,record,status) end do C FTGKNJ is used to get the value of the NAXIS1 and NAXIS2 keywords, C which define the width of the table in bytes, and the number of C rows in the table. call ftgknj(inunit,'NAXIS',1,2,naxes,nfound,status) C FTGCNO gets the column number of the `DENSITY' column; the column C number is needed when reading the data in the column. The EXACT C parameter determines whether or not the match to the column names C will be case sensitive. exact=.false. call ftgcno(inunit,exact,'DENSITY',colnum,status) C FTGCVE reads all 6 rows of data in the `DENSITY' column. The number C of rows in the table is given by NAXES(2). Any null values in the C table will be returned with the corresponding value set to -99 C (= the value of NULLVAL). The ANYNULLS parameter will be set to TRUE C if any null values were found while reading the data values in the table. frow=1 felem=1 nullval=-99. call ftgcve(inunit,colnum,frow,felem,naxes(2),nullval, & density,anynulls,status) C If the density is less than 3.0, copy the row to the output table. C FTGTBB and FTPTBB are low-level routines to read and write, respectively, C a specified number of bytes in the table, starting at the specified C row number and beginning byte within the row. These routines do C not do any interpretation of the bytes, and simply pass them to or C from the FITS file without any modification. This is a faster C way of transferring large chunks of data from one FITS file to another, C than reading and then writing each column of data individually. C In this case an entire row of bytes (the row length is specified C by the naxes(1) parameter) is transferred. The datatype of the C buffer array (TEMP in this case) is immaterial so long as it is C declared large enough to hold the required number of bytes. noutrows=0 do irow=1,naxes(2) if (density(irow) .lt. 3.0)then noutrows=noutrows+1 call ftgtbb(inunit,irow,1,naxes(1),temp,status) call ftptbb(outunit,noutrows,1,naxes(1),temp,status) end if end do C Update the NAXIS2 keyword with the correct no. of rows in the output file. C After all the rows have been written to the output table, the C FTMKYJ routine is used to overwrite the NAXIS2 keyword value with C the correct number of rows. Specifying `\&' for the comment string C tells FITSIO to keep the current comment string in the keyword and C only modify the value. Because the total number of rows in the table C was unknown when the table was first created, any value (including 0) C could have been used for the initial NAXIS2 keyword value. call ftmkyj(outunit,'NAXIS2',noutrows,'&',status) C The FITS files must always be closed before exiting the program. C Any unit numbers allocated with FTGIOU must be freed with FTFIOU. call ftclos(inunit, status) call ftclos(outunit, status) call ftfiou(-1, status) C Check for any error, and if so print out error messages. C The PRINTERROR subroutine is listed near the end of this file. if (status .gt. 0)call printerror(status) end C ************************************************************************* subroutine readheader C Print out all the header keywords in all extensions of a FITS file integer status,unit,readwrite,blocksize,nkeys,nspace,hdutype,i,j character filename*80,record*80 C The STATUS parameter must always be initialized. status=0 C Get an unused Logical Unit Number to use to open the FITS file. call ftgiou(unit,status) C name of FITS file filename='ATESTFILEZ.FITS' C open the FITS file, with read-only access. The returned BLOCKSIZE C parameter is obsolete and should be ignored. readwrite=0 call ftopen(unit,filename,readwrite,blocksize,status) j = 0 100 continue j = j + 1 print *,'Header listing for HDU', j C The FTGHSP subroutine returns the number of existing keywords in the C current header data unit (CHDU), not counting the required END keyword, call ftghsp(unit,nkeys,nspace,status) C Read each 80-character keyword record, and print it out. do i = 1, nkeys call ftgrec(unit,i,record,status) print *,record end do C Print out an END record, and a blank line to mark the end of the header. if (status .eq. 0)then print *,'END' print *,' ' end if C Try moving to the next extension in the FITS file, if it exists. C The FTMRHD subroutine attempts to move to the next HDU, as specified by C the second parameter. This subroutine moves by a relative number of C HDUs from the current HDU. The related FTMAHD routine may be used to C move to an absolute HDU number in the FITS file. If the end-of-file is C encountered when trying to move to the specified extension, then a C status = 107 is returned. call ftmrhd(unit,1,hdutype,status) if (status .eq. 0)then C success, so jump back and print out keywords in this extension go to 100 else if (status .eq. 107)then C hit end of file, so quit status=0 end if C The FITS file must always be closed before exiting the program. C Any unit numbers allocated with FTGIOU must be freed with FTFIOU. call ftclos(unit, status) call ftfiou(unit, status) C Check for any error, and if so print out error messages. C The PRINTERROR subroutine is listed near the end of this file. if (status .gt. 0)call printerror(status) end C ************************************************************************* subroutine readimage C Read a FITS image and determine the minimum and maximum pixel value. C Rather than reading the entire image in C at once (which could require a very large array), the image is read C in pieces, 100 pixels at a time. integer status,unit,readwrite,blocksize,naxes(2),nfound integer group,firstpix,nbuffer,npixels,i real datamin,datamax,nullval,buffer(100) logical anynull character filename*80 C The STATUS parameter must always be initialized. status=0 C Get an unused Logical Unit Number to use to open the FITS file. call ftgiou(unit,status) C Open the FITS file previously created by WRITEIMAGE filename='ATESTFILEZ.FITS' readwrite=0 call ftopen(unit,filename,readwrite,blocksize,status) C Determine the size of the image. call ftgknj(unit,'NAXIS',1,2,naxes,nfound,status) C Check that it found both NAXIS1 and NAXIS2 keywords. if (nfound .ne. 2)then print *,'READIMAGE failed to read the NAXISn keywords.' return end if C Initialize variables npixels=naxes(1)*naxes(2) group=1 firstpix=1 nullval=-999 datamin=1.0E30 datamax=-1.0E30 do while (npixels .gt. 0) C read up to 100 pixels at a time nbuffer=min(100,npixels) call ftgpve(unit,group,firstpix,nbuffer,nullval, & buffer,anynull,status) C find the min and max values do i=1,nbuffer datamin=min(datamin,buffer(i)) datamax=max(datamax,buffer(i)) end do C increment pointers and loop back to read the next group of pixels npixels=npixels-nbuffer firstpix=firstpix+nbuffer end do print * print *,'Min and max image pixels = ',datamin,datamax C The FITS file must always be closed before exiting the program. C Any unit numbers allocated with FTGIOU must be freed with FTFIOU. call ftclos(unit, status) call ftfiou(unit, status) C Check for any error, and if so print out error messages. C The PRINTERROR subroutine is listed near the end of this file. if (status .gt. 0)call printerror(status) end C ************************************************************************* subroutine readtable C Read and print data values from an ASCII or binary table C This example reads and prints out all the data in the ASCII and C the binary tables that were previously created by WRITEASCII and C WRITEBINTABLE. Note that the exact same FITSIO routines are C used to read both types of tables. integer status,unit,readwrite,blocksize,hdutype,ntable integer felem,nelems,nullj,diameter,nfound,irow,colnum real nulle,density character filename*40,nullstr*1,name*8,ttype(3)*10 logical anynull C The STATUS parameter must always be initialized. status=0 C Get an unused Logical Unit Number to use to open the FITS file. call ftgiou(unit,status) C Open the FITS file previously created by WRITEIMAGE filename='ATESTFILEZ.FITS' readwrite=0 call ftopen(unit,filename,readwrite,blocksize,status) C Loop twice, first reading the ASCII table, then the binary table do ntable=2,3 C Move to the next extension call ftmahd(unit,ntable,hdutype,status) print *,' ' if (hdutype .eq. 1)then print *,'Reading ASCII table in HDU ',ntable else if (hdutype .eq. 2)then print *,'Reading binary table in HDU ',ntable end if C Read the TTYPEn keywords, which give the names of the columns call ftgkns(unit,'TTYPE',1,3,ttype,nfound,status) write(*,2000)ttype 2000 format(2x,"Row ",3a10) C Read the data, one row at a time, and print them out felem=1 nelems=1 nullstr=' ' nullj=0 nulle=0. do irow=1,6 C FTGCVS reads the NAMES from the first column of the table. colnum=1 call ftgcvs(unit,colnum,irow,felem,nelems,nullstr,name, & anynull,status) C FTGCVJ reads the DIAMETER values from the second column. colnum=2 call ftgcvj(unit,colnum,irow,felem,nelems,nullj,diameter, & anynull,status) C FTGCVE reads the DENSITY values from the third column. colnum=3 call ftgcve(unit,colnum,irow,felem,nelems,nulle,density, & anynull,status) write(*,2001)irow,name,diameter,density 2001 format(i5,a10,i10,f10.2) end do end do C The FITS file must always be closed before exiting the program. C Any unit numbers allocated with FTGIOU must be freed with FTFIOU. call ftclos(unit, status) call ftfiou(unit, status) C Check for any error, and if so print out error messages. C The PRINTERROR subroutine is listed near the end of this file. if (status .gt. 0)call printerror(status) end C ************************************************************************* subroutine printerror(status) C This subroutine prints out the descriptive text corresponding to the C error status value and prints out the contents of the internal C error message stack generated by FITSIO whenever an error occurs. integer status character errtext*30,errmessage*80 C Check if status is OK (no error); if so, simply return if (status .le. 0)return C The FTGERR subroutine returns a descriptive 30-character text string that C corresponds to the integer error status number. A complete list of all C the error numbers can be found in the back of the FITSIO User's Guide. call ftgerr(status,errtext) print *,'FITSIO Error Status =',status,': ',errtext C FITSIO usually generates an internal stack of error messages whenever C an error occurs. These messages provide much more information on the C cause of the problem than can be provided by the single integer error C status value. The FTGMSG subroutine retrieves the oldest message from C the stack and shifts any remaining messages on the stack down one C position. FTGMSG is called repeatedly until a blank message is C returned, which indicates that the stack is empty. Each error message C may be up to 80 characters in length. Another subroutine, called C FTCMSG, is available to simply clear the whole error message stack in C cases where one is not interested in the contents. call ftgmsg(errmessage) do while (errmessage .ne. ' ') print *,errmessage call ftgmsg(errmessage) end do end C ************************************************************************* subroutine deletefile(filename,status) C A simple little routine to delete a FITS file integer status,unit,blocksize character*(*) filename C Simply return if status is greater than zero if (status .gt. 0)return C Get an unused Logical Unit Number to use to open the FITS file call ftgiou(unit,status) C Try to open the file, to see if it exists call ftopen(unit,filename,1,blocksize,status) if (status .eq. 0)then C file was opened; so now delete it call ftdelt(unit,status) else if (status .eq. 103)then C file doesn't exist, so just reset status to zero and clear errors status=0 call ftcmsg else C there was some other error opening the file; delete the file anyway status=0 call ftcmsg call ftdelt(unit,status) end if C Free the unit number for later reuse call ftfiou(unit, status) end cfitsio/docs/0000755000225700000360000000000013246025103012730 5ustar cagordonlheacfitsio/docs/cfitsio.pdf0000644000225700000360000425434213246025103015101 0ustar cagordonlhea%PDF-1.4 %Çì¢ 131 0 obj <> stream xœuUËŽE Ý߯èÕRº(¿ê±’0 ᆠbæ¤LB2Ãÿs\Õwº¯Äèª5–Ëv×|™R¤)ùoý{uøö-‰Lw‡4]â»;|9P™Ö?W÷ÓwǦk,µÐt¼=Œ„¨ëdI#ñt¼?ü^Î \œk.áû9E1&oæ…#§\j8Î ÅZŠpø çZ‰´í~ž))²–ðÎc[«0ÜÌÊ-Ü ¨›Iøê—)W5 ßx*­‡JnÑJ ogІôS·\Ã-ÌÄœMž-¶sê S¶®PML€üÆ1øk¸ìÀ“…{(gÎáïŽi5\oÞ­ìŸÇWV©D䪳j5ª´:-f1¡“éx F/:£Y%3Àà^Š¥8c)£L ^¶hÊK©:BŽF ä÷Æ,«Ü΀Õr¡ð~Е³¡­>‘Á¨ÓØjÞ•úì—Öh¬˜(’ŒÍö×AKIE í‘E ‘MÐÌÓqgª(¿"‘”,Ü£¨Î{$#?)¯7‰SI8'Lëãfîú{pS¬U'è…“L‹PäAàèÙ s(Rr„\^ºÅ‘„_¼“Ì%Ÿ!ÝeÝu“ÓYÄè ¦²ëj³V¨òYÒ€‰ù$†<ÐkfƒB ®ÅZÔ”tôòû\¡è Z]K<Úò^°&š2ŠRTmœ6“‚>÷sÁ€\?œ¡WyrÆ-ROΤŠ-µ¾õPê´€ h~˜Çz¶ðÚ'£*Z¡×“r08h/fÆ2Š“§ƒrq#¿G“##AkiÚÓU$Ìåz+éZuÝ…<[ÿxîÀpGÔÚ¨aŒŠ—˜H¡¦õ™‚;ó=Š}uZD´±Ÿ^?æ®§Îã¯fo„E;2Éx€¤Ë¸”‚Çð#TËõ¼wHú0sñyj×>p§V÷­ß<ýÔ#AÞ#JÖZDv‡VïŸÚx>Î ÝÚßuv³}~“I dhýé:?5²yá WÈ1‡Ÿà̯dxå üc𱄄¯¬1iêz’ñèuŒïžÑÎÿnȘ¾ö®I9-û…o^ë6žcÐÚ÷vûpZ®e·+Î=ã ” ¬§ÈôdѰ¸ýn?^¿â÷`…íendstream endobj 132 0 obj 846 endobj 143 0 obj <> stream xœ+T0Ð3T0A(œË¥dhl¬^Ìe àÄé\…\†`% P*9WÁ)¬Ì(¤gi`i¨’Æ1ÀPÁÜHÁÌÂDÏÐH!$—+Z#SÓHÏÜÜÜΈ ñâr á BhyÞendstream endobj 144 0 obj 101 endobj 148 0 obj <> stream xœíšÛrÜD†ïb/%ªVÌLÏñ’„p*,pA¸vp(b'äíù{4Òôjµk;vâ­àJ¥²‘æÐ’¾ù»§{þXªN/ÿ)ÿ.>üN-O^,ÔòSü=Yü±Ð¹É²üstº¼³ÎÍìÒØ.Ä —ë_ýzÌÒùÐ%¿\Ÿ.~jî¶+ÕEã£ͳVuIMsÖšÔ9²ÔüÕjŒ‘´oã6µÖ—ÛÆ&qûE»Ò·Déçõ<¿Ó0©K*åùÒrýåbýÁOnWÉàR¢æóvE]LyX¯è=†Åµ-ÅæOLë•56ÂÀ©N)ïšc\1LxYµ®Ó*'ø ÷­U1ðºk™†>l¬õx׳>^°ivÁŒòås¬¬un¹Ò‰G5C×tèB ~6MA5Á;¥]s§µ‘v³âŸ6V:<Æ]kµ1ͯèb©³Î4ßðcð6þn -#ž¥¶ãüÍß[â gÆü¯š"ú˜¸r £j¶v…¾èF“«ó?Ïm{õ71Õ“‹ó?Ïk:ÞÏXz W»FÒ€W™!eÂ(Å z),A¥›Ú&ºCþ¯W¤0T,°^Adç|ßQ÷ VIÞ9^šë$aðu¿ ´"ž’³8šÎŽALž…<¯êþ`©QhýM„Uyß9kó³:Öq™t1!idƒ2Å~^1è)ßñë7 3òB§º2žõsYÃO›Bþòda¡™ÇåŠ8ž{ a±eÊQe𣖣Àd5¿ 5:“x`‚,ÝÿT’žn«ÕqøÓ•ϼmà~ÀÕÃçõ0|À9†C‘ wVð2« ßPKm»É ¼¡ìï"æ…++›ám¡p”`ñ +›Ý-HÇ·80ô±Ó&¯ ¿ÇT÷&‘ÆúeœQbê.”ÉŠ_É›B4´¸(D¦Bô ú xo><蕘3"7ÿªq¶Ã¤dF_B€ £hHRíF‚*?BBˆpÌs>Klgúf”; Þ¶`«åÐë>Ë Üj0p£mݦÛ[Xn–,.FK·E)—/ª(¶âSՄ㑚¨0mov9…Q¼Rð†c r!'d Ddã"8@tKÎ8£ŠNàØb:"Û·n£íŒ²“DÞB%dªE}>Z:¥ÂuÇÏê÷Š! ñó­ƒ;ÔPzovÏŽ&Y—9÷û\ñAÜ›6áàF¬e'íY%ªŽÁ.Quï9CJ‚ðšâ}RÓÆwkÃ>|¹äu½/¢þ’ïŽØ$Ãï/ŒÌÿ» [ðéÜ$ôå¹Kwe†=‚'²}¼kû¯„¹\J¼[« 1] 8·bLÞ Ê©zªbqÖ?+òO·Aû®p‰ˆ!Ú tFM{=7Ô×BD&¤ÞઈõÙÍß«n¾…¡H!ùjÁd¥‰÷¶•Zç9úÑlörð©stíž#˜g.‘G~£û€ÒÞª=ŒºÊè§ŒšNV–g«ƒ½°OžÍ[Oœì\þaÄÂÈÅ›—GÏÞž.]T¾UÊ×RÊyí+…÷ªwýWøäG›E´ç½^·¢­…Xìe}4¨ÇÈú6ä{k›Kœ,H”ñÖSí,ß%·Q ¡Z á#,Øq¸0”)B 3e  JS÷óã†z œFÕ’ÓVçB@Š,FG|¸m~8B·ãÀ*QXõØh•îÛÚjwo‡¶F;žµŠIš&Ê;Õ´ú«·\§ä'u‹×b€ô›N;o‚<…$zËâÏø¼Oë e›³Ù¶/0”?Å=¯æ¼R A ¦;L»£Ts!ÔÇðQ°ÊIÇø~u'"™x« o9 [†»½UšëSš«–ô…Ò¸½U}»#±!°›?´*‹ƒ ‘rÁJ¦µm>ke“Ùhº #ëå%Áéæ‘¡G}d•0ç÷\(M«{žÚ2{j6cwd}6vïçrÖç­ÍÃïÎA;ÍôØÊ»…ZÍcì˜^ µÍTÆ4P²;RŸ´‰Ï¬Z-7qgº£™ ~*F9Ý úº5Ókû„K{ηýÐ&5=7ÎÆ×EòM—Ê»ç½àiÊ®gð^‰­ásöé˜[ÉM'«ªã:Äžq7O\ÆÈq±ö:ãîKâŠ{ÄM$1ÄJˆÛózuø$š¦ÇYY´ËºVÎ<Ú†Fy—jiZڞ˗œl¸™T˜;j™…ÕÈ<@íÃÕÿ kE5k7ñâm\Ü4k<ã¬}/x_Ò/k¦òp2JScû¤Å¼ ФÅ\lÖŸ£+mwe+\.bîI5”ªÂfª!7|RGz´µ›äƒùpäGãWœû²#ôv;]Â-çD´ØX„1+ÓpR+˜¬Íït Ø+fê‚»²ã½‘ÃÉNèɳLBM`E‘Éß¶~p§{ëÅ·øóÇDendstream endobj 149 0 obj 2148 endobj 178 0 obj <> stream xœíœ[wܶÇßõ)ö‘|XÀàúؤiÒ[ÒZëæ¡§®lË9¶å¤Žë¤Ÿ¾3 H ¸äjwC­$KGÇÇÜ%€äÿ¹`¸?­¤P+Iùÿ‹wgOž*€Õå‡3¹úÿ]žýt¦R“UþïâÝê‹Mjð+eT«Í«³®µòzå‚J¯6ïÎþÙüÐj὇æ¿íZ ­µRþ_›?ÑñAòãtBìbóû²]ƒðA+Ó|G›Zšo[ÝlÊž¯ÚµÆX¯ÙïoÎÛµÅ=^…—<ªAÞ‹t] [ÈÞ(„>Ý£´QÖÈ,}–ŽPø¼‰I:?kôN¨jfU‹…>Æ+o:i*šÀqB¸òOŒâZÔû`ZÒ„u.5¾*m^dØ bË4¯y8–C«;8%`B&^9~~ýIiÀGD7ÅþœÃqkB{ÓÌ6iN—m7˜!ÛW„æEí.Zô5ŒF?å ŽŒþ˜–qi_tkôxEÚ1$v›Ó@…$ö†­$zd ì>U*óïÂÕÀPg×€ï/(…lGei9§È=+Æšæw­ž!åy‹*(v›@ð±píLeÑp$Í-®]ز÷DÉè%”Tºµ›6Qb«ó­¼ÛŠODWXð·©Š‰?ôÑó½ÎJÞ‹¶g1Or‡*ªð؉‚q– ÕÛJô ·øÇI>³NtŒ¯°lUÚÇ$'Ý]«ÙHï;ÂÈÓ¼NÏkÜrÌä‘×>hÁFhûX-û!íÎ3Ñ8‰Òt8ÝêiØÇstRS µøÈÁ ´7 ¥ë¡Ì“Ø¥ºù=’â}@£\Ýt&tˆ™EŽã‘ÂÕþv:kgŠ\:T>­*“?´þß C :²ª¯h˜™e4MB‚ß7­B색9 ó.6ϺRØ4L«×eìýÙp;³7†+ò;Ù×ïÉRccß|*q<]N…ñæ$NceÞ©¤G‘軑w‘…ÄœRJ,ÐØ”ýçEYJ(iœËy¼:uÌxÙήM˜¤ýP‹rö¿p¢*ðïÆ–œ"hŒƒäË--O÷@ o=n ‚Ož*«F BƒF%¤ !†"K‹k™Œ ¹YÒx¡çDV ÒF¼›ˆ…td—%Þ`¼Gc»†(¥ ¿L÷Ýj\$"ŽGd"%Ñ ´ºÈ¤LИj×wè´âß^µS)GêÉ|IB5Fç}=‰3²€B÷оv 5Ïñ9_ ­JFÝÉ£7"b¤õ”žt$y"˜)²’IÖÅÎó*íÆ ÐB¾$ØWÊiX<ÿþžîAÝ ð¼5¬E£B™áÚ{²µB 1å’ê°p|J:Àܹ!>¼ÜxÁB”§B}~,1–h ×Ê'Ç*¬ŽŸ·:Œ…Â;áü’¾T–Hy¶Pyf¡*þtáoè:Ǧ¡Î¯ FÎ;: Ç:ï QÕu÷hžn@½'€Püi)Ë䨚ˆRï–Æ¨V¹)W¾Î¸Fôrü8uS·ûs€k7ÉH-”šY$¸®>=Ñw²ÃÀšš¯—ÕÓ‹©€Ì¢±Ðý9-àjíÛÏ—5?¥ÅN´ºã5†}ZKU°Øð¤[OÏûûÏØ£'6•Ð+êG*kƒ°Î.¥–xv{¯,Ü)OÑ…NJ3ÉàÈãSŽ\ñâ5y÷/S¸>^ ɬ‡­là½åÈUa0›]';•mäÇ-IU§B”eÚ-CSÖó²s¥ ‹…äO¢#ðÈÖ±l™´jÄ­æ¼Kf‹ÉüÛd9•MbË3_Òò qàù*í™[%J«9P¦:äP$ªaeÁzêÈZ¢üšMŠxiçÊ×1a«OÜvöl1jw¥‡Â)>´×)ÞzÔâRœÛh÷ƒ‚ðVsø†±þŒ¾][Ç6^UFŸåPÞ·sEoŒÀ­"x³“Z)ëÐc=Ñ"R—ØŒô<‡£’§Œ²Á7ËÝÍ)«S#•bY0VÅIIK JSMè.!:Qe‘-g·Š­¬»UìaÍh)» Àg»ÑT‡å©Ô4»µX>n:`ºÅLe¬–”E/xèá}[Å´Ÿ:‹äCܧˆ3µü|5j1û×'9Œçr6Mßh^¤¦ýü‘­ˆÑâóÏz7ÆV¥W¥m] ™“Lªr_1„ÑÂÀ¤·dKK—ĽW€uˆ29å¿1Áø*õÚrp÷÷‘%(ˆýÆj_™¸«$‡9ë[ùŠüîvBéqž"•¨ÈKú¡üV1zÏ`ª–²~Tø"7†1”e»Ç|¡ ÂÁq+ÔŒ/Ë*ġ“\f®­´lr´­Þág훡`^ÓÁtŠiòª„5n$}ÃK ‹-Yy}¢LǃÉOÀ´XÙ9±Jú€˜>#Ø«Uµ>MÔÄ–¦ ‘ëœõÉ–ÎóÉ`«ê·ËËS’5_½ŒÑr„Yn±ÝÅT[~'K *ÞhÉ {Æòp{ –[Àáڲ͹lª6‚ÊìFV­”÷ñJ¾>uQStYÇ£êÖ©ª°ÑRBW-…`Pv·Q½„9^uÁ^&™"Œ½Çô¬”™íWß°‘£V)gàh³K7úg:q'ß(ú ½ü`‘Ãk_;¹ÚËÏKáZÂ$uÓɇ}«y˜þ½.’Çí&½¹C†ê [mb‰ÕÚÏ ÍYLR¬ eŒ± xìÊQ[•œÖµéTÅÜKÀ ®yGŠ• M-<±73JñúDvbVQƒÞCRö±¢ÚY½¯X-äó»™rÆç¯Àb вþ7ùæZUÔÃ}Ÿ·]q]¨C pÆÅv—y©$—3.ù¯åÓ`®¼5´](o$>¢”KëÔh”ÓˆäÜTWÓþºÔ´“Ò ýƧzùrøë‹à»Âwï;§K‘;Åg¨7:*—g…ï¬Ä½TͳnºjxPŠÞêé‹ÛËA[ð~h4lPïf*à73Æ ð,sÍÈè!§¥“ÚÎô“u‚Ê^rêïÞ¨æMYŽÃ‹¨p.¶Ê1UÂø¯ÊH¼ªÑ=:õ#rCKq¾*ŸÚª:vcßäÄÐh*_9þÅ›ªU-Bc ·µÔø§q‚'z/+°"«ê÷$†xÌý˜ añcX2i¸“eʳ?Ž3»þ2ÿc'ä±8m.tÝ[Ôù UV&5Us5rŶ³éY†y¦À'Å´ÁÿÈHÿ(€4穾ڜýÿþÚ]Àendstream endobj 179 0 obj 2789 endobj 217 0 obj <> stream xœí\ËrÜÆݳò³÷û±´YÎËqª¼Hy!“–ì*‘’ìXŽüõ9·Ý}Á gÈ!EÑ,K Ð/ Ï=÷Ù|»ƒ\ ú7þvqòÉ7RëÕË_NÄê)~^ž¼=‘©ÉjüïìbõÙ)5 tkˆ"ÊÕé‹“<€\yµrÁ R­N/NþÓ}Þ¯õàƒºû']*¥d÷U¯ºÓöàI¿–ƒ1Ö«ù“÷k‹'N¸ïNÿš–øœÆ©AL{zŽ©Þõkñµ©õ#Q­ÖZ ^Ƙ¹ÞvC¯ï½î &*Bòu¾F“‹~­ç‚wÝ›¼m÷ªtü¡7¸%•êþÛë!‡—ú#?X»¿£w÷Siü ½žµÞQëµV'¤Y^P=«º¿P£"fÉCZÇi”6ÝÏýÚ Z›¨ºç}iâu^ìÏ4Œ4Fý†¾AˆÂ —ýšïe`}òÊ¢5Ýe{ÜæÂz]Ѓ5_jm6MÚÙ%BŸz{ƒCÚk0ÝàŠ0 ­”Ž!Ó–Knü<êtðíUoGÔZÉQ»Ö.ÁÈTƒtBåÅy @ @6vßö1ÁT¯{탽@A¸‹ÑuçØôh”>O»h•'T­çõF×s\Òö›ˆý§QDð¨wŸ£Æ'˜BŒ ÕÞ ‘d±6}ߣ¥¶° 1&†Y¼­ÄMˆ‘” H@&ðƒŠ´°A)N‘dGó΋ Æ•!•hQ礯k,^½ìoÀ“1dgËÕ"o¬†Ð‡ÕZFÚˆP6€Qƒ¤Ýð¢0IúÊ/ˆ&è©ïÖx+­•VÝYmGxÙ+ì6ŠQ‰p¥‡Ë¥hw­Ç¦j€A{jFŽò1JZ–Öè†}>’ÈkEP‘÷@Œo‘–Å71… ƒòœ)n…ÜVN€Î´qÎ ¡q—Y§Tùç‘ÅÜ(¸3á?ëu êt÷ã" œõ`è>Ïû¿Ê cëž>Ò:5”æ×6Ü›C2þ’†ƒäKsÇ\÷æç£/½g\0š O±^&ŒÉ¹Ô‘3ƒa.ä0dÒwPVv\aÓ|¿hd@Æô°Ë8}² ¯+éцå~s‰ühå»ù P‹æÃÁò±Ï"ËÿºŒœ4w†:u0ê’F€ÆøGO*×8®P.z˜ÁZ‡@PÀ\pì1™Úì2!M´‡é£ [o os}iËõôÃÛVÔàèLßĦo²¹FLÈB#ðí„z›Î`4=Qõ.kð{íÅÇ*Æ,Þ„³_u¥#ÖLî  pOî!7FÙ#ò0¡Ç%L,v÷²× ¶rÓFåêÓèŠtÛIïàøåw ]zW•mö°»-¯aÑ6-·h±/ˆO¼ƒx2·sêv.iM«.Ë *@sU—WuŸöÜðmWb˜\éAÍz]b›GŠ©lâÁâˆ~0ã[tÚ8ÉT§Å-:íKæÏØB Ú†îm!WýÈHjz‹<¯í^×$Þµ ½»Ùñ‡€¯}¼+# @äCê*|Å_eÄqAÈ|é†/渿ɱ¨«b‚ ñj}×»¿/ °¸ç.Á¸Ý§Ηüùb_Amüm ƒ:Ç÷¾Å.»ßz¼nšÜ+‘?šÕ8šõH¬$Ü;?$~˜€žÑž®d6Þ‹A•ø6ÎBH30δ/ì¬ìÉï ™Õ\K_6G’Ÿf@£×°fÑâ ê™ÊZ~Ó¿¼.ž¼ pÁÃ&¹,`¢-(¼9´ÆÑwòÜL©ŽÐâû¸±Ä6ÿÊÔßy %~ÛGÓy¦Š™†„™0ìæÄõùæŠ+oÝ1=]§bÓ·Ne¡NÞŒCËl¬udx«G¸Éf›žëØn#^|Øžófsç ãÎ)iܹ1z>Ó~Ç y«€5Áâ|4Ú¶8 ~éÚÂLu ò@ûši[Ö|̘èË•’fþ^á-1¸Gˆbnbû˜cö@yŸ`d"Tk<~üþ`j3|Oyö+ôæ Rž…è­ÝŸµ\ƒT ÀS>Þç|<³<ªŠd&ü{ à$âN°Ý±‡¨cU‘;i…%ÒÚÃòò aÏàCŽa Ù¶šÃW,¯1‡x3Tßòrã·y„Õ`%Yn1ÇÉâ®\+|k1؆Š?58].xu–ušÂíyæŸ5¿M´êf„Yv/óBênê3*?ŠÁÄÙóÍ€î¶á.¥Â/Zu_ç"DmB[Øÿ˜t´NTÁSÒ¡“†!jB»Y‘Þ…ñΰÎ܉^(î#õî (wG!ÎUM`JÉܲ‡×ò(¯ Ðqq;hÏÞywŸ”!Åq Œç„: Ûõ&І׾û´"˜=ŸÀ/*¤Ñ©“¡˜g­ôÓôy™‘|œlnXOãj*q¼dàIN‘û¤-C{ “L\˜·µ?Læ±æ‹ùO(«IÙÄ™ÂHÐÄgtBlnh*|ÝÐ ÊËqq€¨ ‘rw…\Y£¾yí;lBw¡Û`ǖƪ )iNÄž6” CJƒoãáÏz«ra1­¶ ý¥òÉê«+ŸÌÑ\ïÅš§‡@ª5û*bÊŒìð€'µï,!Ѹ¢Á‹éäÅKjJÚÒ·š•Ï×dÁ]FŒ—‘G3()kýà£Ú“vÿðÝY,‘B¼¦æäÿÖPÒÊ¥S›†±w½Æ8nRF@sYsDïÎ*XÚÕ@G‹Ö@{[¾U!ÜJæ• ”—yÁ­†òƉv˜‡¸Ý,qqÿÄe¬)Sìwv¬q³kuŽVÛdýÒaœGÛWþš4f ޤQÞ’RqÓI7 ˶[¨¥UØ¥ñ<6š^²×ðxר™!7ŒMa:>D=heí¤”Êb§¶æõ²tÈRšR$ëã¤ÌöÕä HªX…“ú©ZV¢{…h-m>æ…µ-…¿JǼh¹„ÖëÉÑ0V[ß({Á&”®|\Y+XU½Òé cl«eUC03A-ÁSnÀZäË+'K͇ Ã²ÙúŽ¥l~jCi %*þwUxÔÁþx‚LUìN_y@ƒ ²Â.Ò±÷ÔeÚšj@»¢š v kå')B¯‡¸áÎÁ»¯ÛvgûpFÈáõ«3ÈMóÔóÖÈM‰6CR"t<þõ,Áꢵ…~·²¸Få˜ÏF5ôXAÕ«ÅA:mQ vù5Ù»˜å‡ÚŽ®Œ“xb õH»Y©1‹wgºŽÂn ‡k]üØí”s)næ.–síF˜ú +!é§Ô“Ô’_O³âÑÛX1ô`«bvúz‡˜·Â)yaéÛƒÓU妓¿µQš.V“Ž: þ¡ÃùˈcY;GÁMæE¡ U—0ÉC.!¶¬A{y?PWbÝ[O ÝJ0[5ëÉéÉ¿ðïÿÂv›endstream endobj 218 0 obj 2637 endobj 252 0 obj <> stream xœíœIsÜÆÇï¬|ˆ9‡i÷¾ä'ŽíÄÙd:—T2%Ñ®˜’%Šüíó^/èL˜!‡Ã¡ÄR±zà‡¿ üyÙØpü—ÿ¿º¹øì™Pjsýî‚o¾„Ÿë‹Ÿ/Dl²Éÿ]Ýl>¿ŒÍ<|Äbsùê" 6Nn¬×LÈÍåÍÅ?º÷ý–3)¥®û±—Ì9§þyùìï9í¯¹eÜ×/ Ûoû­bÎK¡»¿à¡^øîϽì.ë™/ú­`Z'Éç¬ë¾í·Î8áó\ãµn•ÕÌúÍVqæDiNÑ›ŽÃËËì$ýE÷[k AÅÉÞÀ¹ÿôŠyo¥è^ö¦Rvï`F1cD÷š|¿z¦´±ÇÓºtÀÎ[%-ÜæqœRÝõüK8¯,3Zw×Ðó~Wcœ•Ãeì^õ[ ­-dˆ·Ø1ݯêh?•>i¥Riìb™w°²_Ò=R.ØØ¬¸Äî^^ÖouØ ÇbæWÛk0UL>l" ÊÀu„[žA›íµ6j=¯•Ã#ĉñ½Áy¶e¢­Lí ™y8Èþ _„)_ ÙJÏ8w6¯ ßûîD9­ Q÷ÀÃCÂU›FÌ,hª˜ÁìÖl…ÂVÙ’û€e,¢\¤Á j—µÁ{Ð Ž*@™ÅÝI+M ÌY÷D× ] ~D¡Ë&Ö•KÁ¨J£NtŸ÷¨Â؈M¾ãÞéÈv‘ƒß÷¸;[cê–î¬×’ ø:ÝxËÓX™gãXVf™SÞ¨ÓbqŒÍoŸšK ϰ}Î@VZ’0] KV ”Ö²ƒö †½­zÑ)˜¿$W&Dyܯœý_²1Ccµ+jó:[_VÐgaÒÆ›–þÊÈg×ÐG(Pl—SV¾˜½JûîQ¿a"¸U›ç¦€ïÅ™tuÐtž\(»[¸ÆÌÀU>2›QÊ4L#Wyº•¾ˆ¦*ú—–´"¦ÂyÙƒÇ#ùHÇ?o+°ÃE}>Ù“L+«œb;#9u{q*á%³«›°6­+]ãˆ{h1Mv†€ÿ½d,\–B÷Í­g¥„/rj‰,‚TÇtÄ⤶Bø5>öÞ‡j\y—öPô 9Ùƒ\5/}x 7H)9]î7câˆêfv,×ä~)j9°oˆ°b~[Gk*æÕp4Œ@ÌÄ«5ból‚sËôú´>¸™jdØoû>‘yuKDºJäW Q¿ƒ»÷ñ;$0°àm÷ ”¼Ì|×·±"î0¢á¦©eFp”ã0b@}´Ÿ¸i˜< Ϥ;È»S–§Œû¯äj4 é#ôL‘Á£yüÀÚüÂyßúG ÚZÓb€=häxÜ4W@ËC.ÉY¸Õ[ÌAbPe#¾‚d;Ìa\\¤l¤%bô¢¹Tu¬î•df˜Êƒù|¯r¾¥ró^FúPES m7de@€øÄÄ<{m+£(~¨~/Š;)º?V?µjb«IëЗð|())žäxÎz&Ú '4 ï“ÍH™4l&rrVÞ\ŽË\Eã8”ϸã'†AÁýÑ×Óš!‹>m+M4pÐZ \œÆ„OE)ÜÖ)á‘y´L˜½”RŒ?Ø Çc,âKPíÛæðʆýSòYð¢Ш8¾î%Æm‚&ô`Ï0ZZ?G @+¾ºez„Uh]èȲ2Us?Öpñ1+ö' ÁZm ͈ µ÷/²…µÓÌÀ6w&÷õS hÁÅCßµ]Œ Dƒ¯š»ªMªrô÷>ðo4Û]ÊX¦Ìš H²«ÙÌ¥0‘B.3 šô„ÐaEn|ô®Ö,» B–d[±÷A:¤[{Û¨n# ­ª•_âÊ–ü|š|Ý ø°ÃI·fÈ¿ï š{Á ['˜cRØ{p€lÜÁá˜s%/åÁTLºß³ ªiü#O¹hÛÏTøÆæ7MÜ7bi  ‘º Uÿ0–’z£‡è¯q8ô}´c }¼wbÌ|³½ÎVÆH™çbyO’Ÿ;IVš×wºé¤úê¤Þ‰­R6µg¥äÇKØ^V–õ̪ÛH3 !ÈÝËC”$à-ãè9œžF¾®Sò<ø!`cÒnj״Ë *?or¸8ÓãÄN™9\Š}ðSåKcæmÁA¹KìÌÍ•í>tôÌÔº¦Ïž #ƵæZ¦ZMÅ1žâ œ1@î"jÜe°jBF# :K¡D¤ÔÃýåñöè¢Äá¾q%;H»èz‚i‡VŠØ”°Ð4`IA µ¡[ž“a6˜Ã¯À·"–yéÀ„-W[À™`7‡o:>‚ùÚöZIæu㉜†hJv¥&Š_6< çýNìpT¬€F.è pz”Zœl¯o¬a™>ŠèO•–Ó3AÀå7j#'S§i¶FF—ñãÞR10gî\¤zàsX«gÒì«cÍ)øý”{T8H}ïZ ÓÚ^ô¤2µT–2!Ù¸¯úh&i#wó1(Ñ´Ì9çc´näcÊð°÷x®W+û¸èkX'ÈîêÔÏf÷¦a û¨!ük¯ÀòÐ¹ÉØP­•Ù$æ­´a°O˜mÖVÛ¡a7¼ïU<ݨ,ÏŒ²Ÿ"§†î5$ÕÖy;Óbf;+…%?¢ŽŠïnª%êÞBªE9œ|:*‹¸1t–YwOï¿êö牖#5ÔÄË'¼‘Dð¤6PÅ:ÇÙNè÷7ÏG?|;—Í[E¬ôÞ `NcI Ê%‘·ä\Pñ}³ºSç8Û£‡lס×Ò²`ÒÛã°¯‡ü Ø”¢C]G°ð ¦b aLÅ\õ† ÁUñÜ=7!î¡°wâ;—Ä]ÿ½4(fmpOÄV<ÌÿaM—t˜ñA§¦ŒïB‚á¥aeR· OΓ‰ÀMÐǽXåH€~)`‡#±w(€ì£×SIÀæèqõ¹R¬NZ?N´ƒE#J%¹i¾Ž2*ÙÌÖƒh¿øš*8U ¸Í8£OOê9š¶'/®¶MŽjÄç_‡˜¡™=*Ó¤‰•iG©«ŒÅÏg²üÍ÷làê8×IŸ,³»?oÖݱGÜ}Œ7–Fug*gî),˜bÒ2q—xȪ6¡U\IM›QŒ´SÅ5>;Eq ešø!'aÚ}.ðüB¦C¥0n2>fEÀT‹)9Ú°”(4Äž¬iÎø/ŠˆÀdÿ3W:_»4þzÇ`÷0;œ@jM »fÅ)ÌšCA^mMK^H¸›„¥¼Ñw½læÓª¤"¯–÷“\, ˜c ì¢æV'O½C«Æ=öئ‡¾DHÌ8âÀÑŒ>Êé3Œ; ©,­û á Óš¹d j׌Uæ“\-%EQ -ý L4 ÞâÌKú­Bòtì¤ð|1lã]CrŦ¨/fï¼?Ní Îo`ïÏÝPB®¦‚œP÷ÅåÅßàßÿ™o+íendstream endobj 253 0 obj 2681 endobj 289 0 obj <> stream xœÝVMo]5Ý?ñ#îÒ^ص=¶Ç³¤ð!¥y;Ä¢jÓ(IÚ´Ô_Ï™ûé›ÑTBèé*Ž=žÏ9ã×Cðqú›ÿ>¿:Äàs8£Í`?©  "ž‹,°ùçMŸ¶ž‰u¤àªø²-3†Kì1숫,#&c‡I2dy‘‘;e¼W6àâ+ÎývZ¦d`$4fÜkT r?÷Þb/¼›¼1ÀÌ8jÉ@ö‰š†ÞÜb½†B•‚ õSπ’—ˆ±4  Yš8÷±.EŽXAâ¨Å2âq„üïå6ê—|˃‹âÓÆSêy7ž~ á@žÍüÔâU:í9?™k)=uîšÞ@+FŸ‚˜à Ö\ËH—ëÊé”§‰²’— ù’É|ÉÖJ®3Éh,9iù”Ê"Ná$â ì²U„ÌùÿB¹id§JsÇÎO¦O”s‹K…íT‡¦´¡iiUµ.ª­È˜î¯‚…k+èdt{¿*övé»M7‚¨°Wöžm`ÚŒ»±÷²áLQw¹oE3üZnPù7QñßÂàç“ýö0ÙÿÒºš´uB…;hÇ$Õ•O€U´Ïõµ#) èOp‚»Qª_êÅ×”ÍS ¢„0¶2ï¶Ý÷7ëûÝ”®ó:¢^×Ýl?Þ¦mqLf¯‡{ÑöˆžúžòA§ip^{Ûœš÷'és¾Õ"€A-B„á€ZàÁÛY»cwŸ¿DZÇÎþ¥‘¿-ÍŠ4­ZGÅÑaÑçH}ª:C(¯¸€2hƒ|¬ÙtKª`óƒîDg³úéëz§¿/õ‚}“RúËé ón}hÓc¼âCZҎϤ-ú€‰3tÕtº…( ¬¶ŽJ_½“ãágüþÀ„“endstream endobj 290 0 obj 932 endobj 301 0 obj <> stream xœe1 Â@ …÷ûIîÚ¤«RE½Mœ*‡Eð÷{W òyä=¾L€ž‹¾»ÍêD!Àð4Û<ƒ™ Íø®~„uškšO¾Å– ÝÍ@ FO i4ûrzf&ûpìE$ü›kڢ⒱ñ¨šn´qUð¢LÑŠeRR»wlÓ/é\E>ÆZx‘ˆ4bÏ®ªs"¤åW—Ì1ë 94qendstream endobj 302 0 obj 168 endobj 306 0 obj <> stream xœÅ\[\Å~_¡ü†U^r&òú~É›q!" à çÁxÍn‚ÍÚÆ‹!¿>UÕ·ê>}f×% äñL_ª«ëúU5¯ÏÅ*Ïþ›ÿ|öòìÃ/¥ÖçWߟ‰óOà¿«³×g’†œç?ž½<ÿ肆™s%Vç”;¿øæ,- Ͻ:·^Ÿ_¼<ûjyt8ŠÕ:ãƒ[®Gµ*‹/ObN8—WùÛ¨–·¹FM\žà;m­\ÞŽÚ»5,W Ú{åþqñ§²»Y}ðw·v5:†ó‹ÏÎ.~ûÕò)-+œ5ËwW«‚¦ |ˆÒá²b5*Dã–V©tX..¤né#,à–g0M[­[àŸ¸¾ BF˜‡‘.FØ©Ìi$J³jã’è4þ* ‰)¼fYzRªˆ§”VèÈ~'bÆ.ÁGà‡t>n2i(Óžã'çÜò ²Ë®Nèå Fé‚UË­W-µl#óBZ?Ãg©•¤E…1mè;8µÔÁÄrª’°F‰ñº?Õ#¤Õ üðÞÕpr QÀ…^´ßŽpiÆD›„¿Î»*b²Âôò=|g kAtàç$šå%ÞsÞøÖÂ5iw »n ×%¾KßÐÁÁ |’J-G înv‡s/ÛÇ6å^ËjlÔùK¥ÍÉIéwåWkµ ò#H›_^”-ëÞ_·¹p= 8Ú€ZàÙØ_B^8€äY¼qE²ø üå¶­ö΂×zzÎF'òÙÙÕzCë¿"-öév+ÈßæùEBP5ƒêq :ô^îß~w…D‡5‚ìáèž}ÊÀ5Z bG’¢à¦ó–Ê…¼\I‡²@`û.¯äe =`¥d^¶oq»6ñi¦#†åƒ6æE].qFÈ*€6ô›ál¤µ-yÝÖyŽ¿Gš´Q­«*à³*(/‘¡ÇÂÑ£Sà„JŒ}²Ð.Î{¶^•¢&¢?¢:+°©ÒOe‹M9j…×­¹fµ Þ·®–’U²@t0`XE”)Ø÷¸˜µÞUuÛSĨÌAMˆzEóÅ ÁO‰víc·Là&¬LýŸ`iW Û0Ñk—íÉéÐ!„á.T 6¥Í^a Ø ­\¡¤Î¸¯ˆÌO!,sÎL²}Á,Y9Ó AÙ&ŠÌhQ¡çÝZ—y-ðUlë/É!FááÑsF°Ð pHCdæC­ø!Q‡6‡¤9xM¸‡1E dR‚;µE‹$øL2pp=JÕi/QÌ€³` ,Óù¤‰+¤;2'K2F3ÛÂÌ¥ß eÀÿ#C¦’á”DÉ€õ€7[¶P"2‚ÞfU¨ˆpTcõk2òîi`ˆ.RZyCœ(CÀ#é’Ýu§§ önêI’ÛÀë™A‰”À=Âí¤ýé è,v&‚ƒAÖ>yÓ)e:§¦œ¤-t“ÙI×`¡Xdm®S§Ç¼íïæ)…–Ì`QŠÑ†Â?z°¡FtÍï%ú ˜«w‰4¨?ì QIg¶¯«Ùfšƒ"¡!¶2ž-Ô~þºíÃèbr‡ÁÌ )BæÄ‘t§øéàèÚÞµð*/gMh#›Ì·OÍq ÑŠ‚8ÈÅŽ¾‘yxPËçðßãfé?Mñfû‡_0ÉL|:Ãst“ç&©ÄÒS™†TõÌ ;ˆrW¢3…a½¦0 4Âê¹®1gpË$-Q暨*šÌ €°Ü¢WŠ™”½Å*û]í­—§j‡\R 0ØG\Íý  4I7§C„tD± Ûõ7à³ ˜¸9Þ6ÌÒ`¥Ã=‚’¯»ýÞ-x‰ww([ úAÏ[Ü•†øÓ;¦•í/Ú‡£Q"p£Ïl#RŸM)äuÙðÛÆ_2Ç‚ObôIGÀ¦°pë¦×›JXmùF»™&(—™J'™D ;2%œæ±C‹„wbHª&Ú;jÉmˆª¾½+ªëc­z;CØT Ç‚¤,ñQöbuaÏWPÄ”Dу¡Ù¦ž$«_`<Œ|6\n›Ü1e.­è\ rªåÈ3-IŽ[ˆR[„MîgÜ’õŠ»²ª}ÃècTLt9{âSŸY\¶ªyƒ"Ç’ /Ó žZ”¿Í¾ÌÞØô`ù®¹ŸYø‘xú«&²€ºXâ(B‘cš¬Щï&#Ý—8"ÓÕ c(Tü»‚¦÷Qî“‚äe¦y´øÕMòQ¼7Y9ܪv“‹4VNbõ´¼{T¼0ø­ÈƒŸùÂÅên§¡ÒLÈ“÷tʳÅÛÞÛh ÙÑ;‡© lå§ÿ½0/!nBØ.=x5S’3SåËbª¨–m‹ì„jƒUDsÃù ÎYjÑ©zŸÛNâö` `’Ú²Qff5ã‹A#xç@™4†Êèûz_0G+XìgÚ/W0œ—‘ ¸‹FÀG‡¢UŸV-# Hu@È ÅQˆ9ÕxÐìIšÙÄ|7É̘œ±aì\²<ØŸÇ9Ã9p^Û™¹&Œ»ùÆŽfÁ!bbŒæ(S>{ï Tûg É9$=<€j p¡Ÿ “!Ò~èÛДý¤vÍÖ,¯9¦›* ç}W@Ãç¾OR~.¤ª• Hu6ñv&+}`Ä»=WTš½L+A9v—ôÔ°¦ÚÙÅÐ%Ì]\¨¥¢L‚ù1f£sÄ©•\·ÜÎ7¬g›ë±Ô£™«tÑÅT7ÄévaFVhÝ!—dNkæ©®q¡äÞvRZ6« ±§W•iHgýão“z ªw*B’SÉÌ5^σ„ÒÎòúäˆRåàæÇÄì$KBiŽž°C0­3v_(1Û½_|4dˆ;àÒ¡WÕ® & ^³”ÿÈ m?"§Úó1a³pù5µ˜¡.O&Ï•zªI±s!,ð,xl VŽ­¶Éþ„Ó5Ÿ*9;ÊטA ¼µ !"c½5²Ú*Ú€[Uk•1[âV]}ËJ,’J Ød–šOnû²Ùù‚CC°e}æ3ØhPq·& ~žoÐBÆn³R:žM´åvjm‹¹îqð!ižgôsÏgͱ"ðä>ºDx…ºC—:7›~Å‹” @ÿÍ¢®öžü÷‰rÂVBÚ]Ð|Ç:õîÔÈRy¨¨à)Á¼JhªÄÎF#8bÄ2ÿÆhæm[û*&»ÏÄ^l,è~t ”k*q¿kʰÏèý2"|êt1¸8|©6Fm7†AKç<§mSeñ8b‰–›D°|âíÑ(ä¹/Ì×û¨Ê`}ï{†Xäª_ìió×Zú D’XÓ;û·µöz“ «wæ,±’=±;*áÍr¶Sœ­feØk–”ä çWŽãOS.´FÜJq•nCëä¾×W<Ÿ? DöqL ’%3Ë“'ð÷{X¾¨Á=¹üµ¦‡SÃ!VicQßp¯˜œ+%C’ÉÛ å³õ׉)BΪ³psQï"‚™³…?hQ3sا{%:֪ν¸]*º˜8q¨÷ôYM±¢m Ä SE g’“À ¥wÞóž"ž‚c÷uvŒÔ‡‚+¸ëK^³Tæv¦-S„eÇ]ÄÅ OT§Å]¦­Å{üBçQ†³0¿ gÊÐ.ÃI-@n>9i*Šë»áW2t$´úyž‚M½G?ÎXˆØKÀÁÅ_XÙ-œë½ ‹‡gÍlÙËBªr]ÉÐ'&&á‹LînR¾‹2üb°®MÌy.ˆ&ÉØUÏ@ Ô8&§º|¦ n™ÈN 4·àN%-iï‰HôÞþRIE‘èà~Zÿà·kV8màa8v¢BäÔ2Q±1L'^Ï Ç©RÃÜü”ö>ßiÝ;%nAö]wŸ¬ÞePJ§jeצ¢TjSÙÓK¥RöÕe2uŠó"4ù%Ò(¥¡¦ØxIgñ«-™nëV¶ »¯s P–÷ÃRØ©(N,G’DÇ&©cFuñ¦·Š×‰3 ÏÕ+y˜ËñþÁò>n+ÕŸÛŒ1¡FÓ²)¼W¿ºI ñ8Ì™&Y…è¡ÜW× •e„©3ö»~±M‘¯¹³â™çÍ|²6¹„)"Çw‰ƒsð—­Hýz^ Œt‡ÖÙT¬;Ö>®x¶¯xv3õšïc*]¿?`wŠwqk¿1 ÔsX}ÞЃԻî[Šðtö[»ô€ˆ%ÁAã0ð˜ËÙq}ãS¦Åºr]æ[ßY¾®ˆÎÖ·—r‰ðþœ@î jŸ>„Y*Çì Ø€G©`.jÒÉôáh"{Íò¯æöÛ%?cåøF§³š™ówŠiË8fQÔ™cÂÚ~æï«ÙÄFa9Û‡VƆ)öP‡òÌ"º¢:Øl,¡³Öö«^®š„²–îg<ˆáª’>¥þîÓç!`§çõÁð¤w{¡Ii“½m*SYܦËê>tQd o‚šâÍz’0”‚ï*noj=%@Óš ™of Ô§{n^"Ìe‘©n”,\ˆˆ‘ãÑ ?ì…wˆ]¶=îZNÙÇûŠÔ¡aŒ‹@þù‘y¹}òªÝ—F÷Î(mtyËlb7ïÀi³£õi»ÙCpëJ¸÷œT¡ã0†ÐHCU†ò%þŒÈñ ùˆ¯·­·Eø£Wl~y(.5=\ƒtô²œU2äâCã2Ð[u¡EÒS‡¶–Xƒ6uR9Œ¢Ñ‹i0iØ‹ó(‘øj¾{sþ<Á Ž‹•ßµå/¾áçT±iWvª‘Âwxy”²DÏvx{ °VÚüÐÝNšŽM[þ>OÝ÷ÁjíÉv¶‰u(ÁQ¹„ˆ8͞蜤çÈ:ŒÃ÷ìÑéÍ©"ô½Ea^,Zuvb7Фwaë}^7Yó—rr|ÒÉ ¾¶Û~Ú~Åæßù%ºø“DfX‘¨pûÉ“vÄÞ9ϱ±¡aó`,¡Çé)¹ó¿¤ÉLÄZª®æî€þï ¥%£Ç›gí#Ì“ý͹¾U_.6L‚—ž›|¶ 2åbÙ™åo‡H—˜B`šžß_ñú¹ªöŸà;öÐj˜à×s3¸Ø:wxÖÕg\¥ÀÆ\g“™W©Ô6<ój×lùß±*˜/Šü‚t > stream xœå\I“·‘¾sþ }Ó« ¾ba-@7›ã±Ç¡±e‰O„å7»¹—n‰¢(ê×OfbK ²ÞkJôÉR°Ù¬BaIäòå|{±ÌêbÁÿóßW¯ï=øJsñìí½åâ÷ðçÙ½oï)jr‘ÿºz}ñÛGÔ,À£9.Q]ÔZ{ø¯ÉÎ!¬>þ ­¶ÖlTÖeúR°÷´@£ _àQ;3‡‹#LnU1¦u>‡ïß×·ØÍ²(uøÿù þ vOðÇ%þx[~K¿Ã^á<›ŽI<5Lmž¶‡Wõáܾ©/¥Ï/§¿8µÒéçfZçÜb?Ô×Úë§õá êgµŠœž½m _Ô‡7õ!RS™ÙùXè‹{þóïÔ_£«Ž™)öªRìY%‘è_}~KôüŪ9‰ Ùnê³ZÕlo……3²}_Éö^ð»úðImø@ÚúuÀ³äßösÕmÉFàÖÍÁDdq‹Äß(²o&½Âî)G¤_PÝáÛ鸠¨) Í»éè@zmt0} ¿)­qVjv.¬¦ ‚¼FîÑ(†¦çp?Êg¹ñêõá>Žá k{xÜä!üâ‰k£ÆÅ!ÙìlŒš ŒP™…µió`“«ãéÒÜ,j6ݜ؟MéOOËÛ¥VcØëkèPÃ?¼bÙÒŸ·_/{¢\ÕæíÃ׸…ÞÃv½ÑEË&€ü¸Dxê¶TÂo^•¸œt0³E{ï­¤ö€½F¡P–ö¢=|ÎÙö õúæwÿ{*ʘi`¦Ð¿N¬ Œ{­CœÓ—÷H²«É¬³Õ«?¼œœa#Òó´M@}dÈÛäõËõªhËßµîU¢KË]ôlÍŠlˆ å´ÏäX’ì˜ivDª Øég5–LdWOR ³UK¡¢_“j1$Ó0í©hŒ‡\&w®Ø1ª€™½ü«^¿À™$ÃûuæAgÀsY©\p›¦€-’åtÖË<þZZ5kC4®ëq» ¦nÈÖÞØú…ͱ|„J§u%>ÏÓí³ ½þM¬óÕÔ›+ÔúÍ[ÃÇ‚#õøT037|>åá«ÚO[ÌóÖð‰Ð°îÂy#äâÒN2ngÜUÍ  zÆÜ…©ÁÏøwÞ~ú=J–ŠÀ“ÌÖÔ®;–†— Jƒ§ ’(Ùè&ªÜ¢g{Õ,h,ºÀf§™”çÍø0äÙœ,|³Qµ([ƒÕ hF¨’Ö ÍÙk_µÜ¡ÀýªÆT·0’¨š­¯VøÍî7œ„] ÝE1“Ô|¾½•¸LÝ-êgÙ´ëð© îÌ››:á°J˜V²<à›êŠÉÐ ,ïeéØàÝ¢p†Ç ˜iùÔV¤sMƒ, T ýÛ±#Ø­Êûh‡ÝÚðáH ª ¶'‘«7>·ÿóÎ9‹v ÁtÔu\§^G' d¸¦_ îÊéˆ6MÞ¬#*»NÕ6‚·'§Í®•žaGQ>îY›khÅfI ±^YTf‹÷P^`ˆÃD®à;ÿ‚GÔNªzN£2½IV;/¡JÂlB7E¸ªGPÚMàKc`uÄ•Ù÷À]_Nͪ6¡O,Šn”ŽN£g|œß&ÆÍ«;*X÷)·£z!yÛNbÉŒÜÈ1£×€Ýõ¾(›ÐMŽí*'ì"úY`ŒªƒfGvÓÛzu mÀÐ x蛎–npF?à7ž$£›]7­2ƒÎâYÛ‹²RØQÝÅ|è°¿%;D5ô:ˆJ"~ò¶í\ÓÆÍ[:‚A—%ì&Ç\"ºL¸]@¯¾ÈßÂ÷¿×íuÓ üáŸRâ‚÷ÙDh_ƒÅx߈ÃB¼Ma'ÝžÅóÄHånJMò²“äéõx ®þ/C7EkV—uâu1õ±S¥¤Ë¯O«ß[aÑdRB¦cE=ÙMB=ÉHž3u“2£€öbD&–ÞV—q,¸ìúk+ú¿v‡ÿ9þ¬`ÛhPp‹ãS®ŸeÁPj^lUô¥ƒ¼€‘UÛnRA˜8¼k\Yù®ì€ZyOU§- ¢¸%ˆd2ž¿“ô,ž¥ö”è!Y-£Æ}Sz\y6šmwŒÈÏá&†%‡XÀ ±ü9³H½‡½ãÜJô¬/䈔 =3Ë|`þ'M^“¾SJ+>.‹@Aõã²6åè (‰è$m—Wÿ 8}MvhæX¯ë˜Íè„!q½žC­èÃð»!Rž -œÏj$)p$9¢%œYä‘!¤mJ¬Ë=&97{!œ,nwŒáptÔ ÂçÜ[Êýš’Ök\?®ü€ªá¡†Š¶egå?3ª.dñk-®«òþMÊ%¤ª¼‰@¯ú– „½} ¬¥û¢»°¢ ½ƒÁŸ‰ @¸PA,òìÞÃ4‘× ÅSbŠŠ)P !¦­^´¨áA¥8TÓï0*ƒúýuЍæ þæ1wÝ>yF£;èýõ´ Œkné‘Â0bÊò’W¤ "F[•ubš´¢º×T¹¨C‹Á§àeQ«Inƒ ŒžC”Ì:3Õ=–R¡o<ºXÑÅ£qªd[D•â!vk#SuE}âJQŸÛ‰¥`Ý:ŽLk2]Ú%‹R|b ¼A_tѪœœîÌR)ëë WŠ•°R© ÐE“Ǭ‹Ò1÷úÏ)D§µc‹MÞoÁA¡Ug t¼Ù £¤ãZxdB…¼Ù§îÜNbmp]„BHW¢=Ö6›r³€ÒïC8ëË¿„Š‡Â¦£¹¼' ^·´¢÷M„øýóÈ9ÁµÆ*r`´n3HÕØê¸b…ƒ’p€8už?í°ñ©e¯ŽÆÜC)ÑÀÆ;3¢ óy»_ˆZ Ocìa¡¯²Ûycjô(C8 ’0ˆ÷<®²Çj¨W¸s+zÄh¸Go9礆*X&`ªœ/V»æŒ_çm=“Oº:!7œ}áØ ‘ªCPT·¹V(g@]Ëö¾…–^phûjxQœÃöõ£g} ¬>gž@ŸÆj•ïÌo8 •òcÛZö–ÇNVƒÈ«_SŠ&Yâ Q¾Ï”t->*ÑølTÅÂľv\kÒQrÀ­„ )º¯÷ÍîºP'̉ã„ÝÆ?¼XQ³rËÕ¶âEÓjBÁa—“+†©Õ9oRî”%ŠšÛÓMt›+ܧü¾u9h{ìè'6ÑÖe*Ð_Y‘KçâõµŒ)±ßj¯ƒ¾Ù÷…;ÿ&i‹«'#À$üg­æü߉f·vøUƒaâÑßNÜ(33ú²ª’½(+62¬8Eœ˜ò”òiclÃì8Ūö†Ê}"f¯³˜3^ëƒÿÔUËKaeœËªrXyc’PS×’zŸO¤  ÷Ux&«éð­dÞÆÜ°Ï¥;ŒTßLU’pN”»^åúà3º±o\–a÷ « HÅ´ÈÞA†HP·ºˆÅþR0=W]ž\B8ݱdÛ×Ù7Ûž œ6}î=­ÖsÜüæ‚ìá}ºE` N 5ÉÈ%‘´WÈXÂTH½á 6úµƒ½ ’N¥^ÇuÉR*Šy´­¹'pkª£˜?¸Ÿ[Ã;Dô {³Hzï)E¤'—«`´ejé#åû©UAJ¨»H'r,Z+~dX)UûO¡¬@²íã~okð‹¸}†kZÉ`äöÂÛÄMIBSê Ö¯·°Ô`/ä1ÕìZ*Ë©âÆZœ¬[.!º:†È­JÖ†e^Šäå³¹÷3ýtü¨d?ØZ[£#¸æµrý&o6…vìä@$ÏtêíËM— í*%Iù¯iT ãöv ‡÷X`ŠKp‘µ÷}‰ä^ÕþxÅÚNÿY“òòwÛœy–ƒ Vcõ=Ç"fnzê?0)7ž-…qw‰/ztåðèŒÂØ”5À˜6æj+?§b0¥Æg“¡I”„“ÍUXîPÍ@„¿Kùu²VÔ…éꙢ?K:4Ò¶0'€& _!B qYAÕb¹W]g–„D„ÞrÈÙdÎÞo¬G>¢¨çx¦/2ös:CZÐR®üÄð¨Yf£¶M˜…R‹ÞÖŒQƒ¤Ij¸/£EwÚŒçesÉÏ Í½“’:QX‹´ëË~ÕÐT€¹Um=O×S;°[ïÃvRølO æ¥º,/2(]ÿhîp—ªÆRöjéK@‡åì™%jó»j®’IU~/ªØ¨u Zøeðï~Ws™it.ªEÊÞ¨®š@<¼Åüîslà³´L†ïŸŸûì0µ®v½z9†ÒÞñâ¦Ñµ£°U_á+9Û³šRámò¨ÄuYÂê0q{ÌùŒrY Ká&¿P¬¶¢£€ì »¾Þ¥’wÑyƒüVíå¨grÆaôkâNéÁÞ¡Hm©t}W<‰ýü&N4ûr¢2žT5¤½"_þýµ.;Í»ŠåL·³âƒ1ŸK‘mwNÌ?šè†5„ÝêcÎüäX1‘kÞ¾T§Ô,霱IÈønYºÚZ¨ŠžÏ’ÿÄÜ\§dÕ&‚³Ñ <üZSÖ ¥í‰ =¯ÊÃÖ+Õ1ÿ=w ÄK¡îš¥ÝºpE+Äl÷½ÛÐUnæ<ÇxU»Ñ#»w²>q|·Ìõ\ª©ŽÀ|lR3Dœ .'ÇUCéÐU-Ø b#fõ™Ð*Ÿ6ˆž)µ;;â™g `/µ»é` ÷³3—¬óvMÓClЧ†“ê}Í›[BOŸæt@©Š^–¹Ýk²5anIx[ øžAocÿÑ©šå1Ùm¸Ý‹Ýóè@Óáþ›!5&¤âDÞDôPbNš Єxõ÷è¹yõ[ë…#[bô1/ð†)Òü¨¨2}¤þuAeôHÚœ¨,²®³sþ‰½IbÞþ‹­_2L3†N^ˆírÿȸ+¤E÷OS §˜wÙsö½p¶Œ%,{ÖZòý<Ö’ä³°q`¨%™–ÒÉ’Zøí,=„ûw"О("Ú“£µMÍ즆©`Üwqe7iSG-  º€‡°ýõ‡/p= ËE>l´¯VË8´…ÖÉ/¯AÞm´·GÅVž\sAbJÿFÀ†NZ©LWN ³üJ5FŽÚ(«NU3üÖùïë¤üFg²’º2I Œsß­{f)›áÈ^ò¶…Љ…Ñ>EŽÑƒ&'êJ‡ ÈK‹JÑscô™ºÛª!*Þ9E}¥%ºÜÖìœ`|R¯p klÇ…ïrhZðÐÊZÖ81е Ý¢Ú/5¥xØ<øßi²ìÌcº(p­$ýïJ oÒ´Ú쀅_6)èÿ˜ ˆÏñ[R:ù´¬xŒ+ïyº‰¿) Yde¬ÇñÇ’ðf2©šœ*éÚST54—ïýbÜQ…v£W€ûeñÌy—ÌlKŸÿ–2)Üb ‹»êÄtµœ§éfÚ'—hˆ\(I £‹„öw2Œ uoÖúÝÂqÇ@öÅøclªKÛçèŸæÎÌ&ÒevÀ³šòÝŒK«ñ «îdðe ç(ß«\ ølô¦âëN袇íÌlÃÉTun<‹õeDbésÇ÷pQ–ë¸ØálHˆa«KWÌʹ34wI^ˆîÀù:½”ƒNÀƳKgʉxµ9(#9Xeiëž±8yÜÝœåØá q“'–”cf£uw›#FSY>d¨ íŽÖè°W7:œŸOäb¦ï¢K¡’tƧDd3¶ê6îT5V>3¦%†Ïè…äÿ¦ƶð¢ý†RÌÎågòÙ[<œÁÞ2|Â>g¨¦Äë€æ»H·„„¥pÒùËGZ9¦l`¯EvB÷MûeVŸ¦äEûHW¶žÊ†kü7»’icÍrñqaÇ’Ž»0fÎ|k‚ÜýÓ] ֵŚшü(ú¾Ã¹|ºÙTëõD‰)TCAt¢Jo,$Xa —n¶éâ=H´ó—1rMìêö+3\IW)Æô”»÷ C˜_€—öøõf¢KÑc,‡Om:—9 ¼VqFZÃo¾kïÑÍõÉ1ŒÊ™bÄ‹F;°T/&]lèvéè=·,%`ëÛQIùø™ •ót †WïWv”º… h—¬ÓÛ…AÁN+‚tþr¼È¨¯²Þ»×‚Ý­DúÝ£{ÿÿ¤n4Òendstream endobj 312 0 obj 5735 endobj 318 0 obj <> stream xœµ]Y—Å‘žç6?¢ßæ^õUåžå7À`älPsÀcÏC«$FR·-È¿~"rÈŒº­ÌñÁºª%+32–/¶ÔO§ËA.ø¿òçåó“û_+cNÿr²œþþ{|òÓ‰Jœ–?.ŸŸ~tŽE¼tX—Užÿp’P§AŸúhJŸž??ùçNíÝî°×‡‚Ù™ô—³׃^âîýq»÷gæ¢ZÌî¿ð§Ö&„Ý—{½ûÛ^¯‡àµß}»·0@\ìîóý™Þ}²?Sk]л?Ã_wÙÃ0jµq÷üòÞ8S´ÆS‡uvݧï…uU»‡û3‡·W÷?çM tEÖ냇5_Á:`êøÐY¾xfüØšï½Èã8§v?ïÏìÁÓø¦f­Òzw2F½»l×n€Ïa10Óàm¦²û±RëYýÑGú&¿†ƒsz÷Ñkµ{Òßý遲³n÷ª_ýÉà\ – UfjW:¿ò$½¾ïO'G~¶éýÈç©Ý]Á<Âz°|È~ÿÙüÊeû•W ©u Ö§DÞúu¶$–YÙ4Éâú³d&äçø ³.ëU¿~½×@q üÙ'v³GfИ¥qÈE~w]ÍîÜX¤ÝšF%³yŽEØt2Ù¿ xú%>¢˺š\,ÀÏFíÁ3ñ`öiËãrp¾~&(Ÿ/äС®euicðbP±ì^|‹C¸ƒV®PkQ»×{gQøb«?ûª'‹«p°Ðö&| &§*¢Ñ”ÚÇ$J…|gÊÀì©Ø‡¿Ü›#9‡D2Ö§Å—a<¨ƒ¼¿F‡7]€†±pYþ¾7( L†ºà0a0Ö \ìºfDÂ6•[L’Ý¿vmÔ¯‘%㺜®a¨Þù”Û=ø«òi’]7}7È+¶÷ák]Á‘G>ÝÛ´=šÆÿ×' ‰lÖe— á/f-L†½i›Œc ³iµ[çû°÷/8W“!IÂúæ°˜µJOgÑëÎa‘Hö°(M™§ôª3wgAqŒÆ—¨;5J`L<©§ÌÁ™(­ ? ‰B»UIµ²Hd vp ¸`вÕxõaÿyàoÉЩ¨² TR$IpkÌyÔ­ °*qE-ËU‘ gCš˜ å72äçdPš-þGŠiµW#ßCTMJ“Çyõá{eCÔX¶z`< ¾®½k‰KÉ2 —¶w+¦ýÀ·"ïW¡ç ÞíQR=°‡äåkaÆ?ôJú2žÕÀx†Û×dBÀ¬º Aþ¦±†ª»²ùiˆcrŠïÿ.Ìi‡"P‚žÌM¢¨zãüÁXõÛ%7‹L(n,Š*¼x“éµF_Ž]CýfÈæȉÚc“-èÉÆ?éÀè‚s|Gwu?špš I]q=Ù¿ÈÏ,Êm X3˜ç.\ïŒt ]– 3Ö` £´?é‘)’‡ú˜h”¨O¨%|"ÈSåuOqÞö 3ŒÒ*Tìµâ#UpÈ4>ÙxP‹#Èe´Ý² HÆ–ŒÇ×2ƒz×3ÈÓáNEû Ùý.:³e¸Fj“²Р!‰h#ÖeªC³.D£Œ6Ä•‰ÆíŒàfT­• }_.2{ë õÞ†¥ Фàù4ðîƒÌg(c] dq¦a·7¢¨µ4ât)õv¤hUí­ÄÙÈ!Ó½Þøb4q'x.7bsî)ÆJûÕGÚÛdO‹—«'#´ÉêÝGûÊ=í›[€vO‰áy$ŠßÏYT"|¯JÊ5Òˆ½ öƒ® á“ûqlE@™cüï v¶ìF“C¤Š“m¦ ‘¡+A¯o»õTXŸU¿ˆ:Ñ„¥'s{¡_¼x“m.†[6!V‚Ä·S ‡ØqÛÂ¥}Ù´pÙ—MnƒcQï×Ð'½ÇÓóÏOÎÿøÏ‚’Øò9[ãÒœ‰\gï+(=®-œî¥Aonh3Jàù¨såð³êh(Þ¨¿wGi^HÎ)Åz`=ÓÎà 8KÒM÷{7â‡o÷)"‹a”G|“Ä÷06嘿\§$A s,è‚ÐÇøþÀUÑ.ú <í(3K‹NoÃb»qQG º¹ … ›s¸Å[R4È®#Æ¥šþ¯‡´¶dçŽÞE1˜e±Üb¢ýê%É?‰!T W×[a5oe:ð,•/”«#?t6„kZÝÝ~:.‡»ü’„–€Ÿö*YßÓÚÏA>° `íÍ»†îÈ ¸B@0Ž÷ÇxÍ;"þ­¨Æˆ}² ò,†È±!$²~º_ÍUŒ˜d ø*VQê4QEc¾¥8M]Šú/¼þ¨Ø~—€ÞhÝ7›ØñóQ(AD«®†5ɩ冻N“¬¸ù¨µÎ˜HÄp² $´8%X¤· FÃ@;¾¿{6;ò0òÚР=‰ª{LÃaf°$ØÙ™‚9?mÎõQÏäC6'rÝéÅû¾-ÚM3KëªK”79z_£O¢–ÀÒEo€‹b“ü‰w8‡È\öùhqSB7Êq3’ƒë@¸&3£û®¥.žÁ}qOIä‚p|vŒÔ lN¸v^´H»¿u¼’ê Lu%ŽžV}–®|få,K¾%° Ð•Nœú¯ÖÌQÛò«5&äÖ~V!ý&|×0-ÐwN7¦¦Õ5lŶäɶÚÔ¤€ÙÒ`aÍ–Ý—âåR~ÇŠooÅa÷<ø8qÒk‰0ç=ûáª$Hôõ=*М†0+o¥ŽŠ¦4ˆ˜ƒeA=ü’Ë6BvôÞ –qŠ™pƒG`=‹ž ¦'Ý#`5ÖwÈ|НE KMIÇ|C…ñ‘©YØÜº(@äctmØäaã®àUܱ .ð‰”/&5"èn ÖTB¦+ÛXr΄19¶.Éñ_qžÈ\3Ay‰f6•®+f§%+]ÕwÔUΰÇ/ãÕ~ÜËl: ™Ü¥¢Ôt €b˜µÀZ+ùÀ3[\…i†*h’Ø!qŒ†À~dÌzݦP@ÀEk™îüˆà{¤Uräó°3¬Ày’W÷x/ë/ |¤(…hú§©@"{‚U ç@ôªû Ù¼)çG/#‚š~V•@EÂO[.nú¡p%ÿ‡×V‚úD¨_鿈ŽýS:"÷{z‡lÖˆ´% eøwû aâås»ª”HB­ÇqzjíÕ&‡íß³U$±„Æ/%€äòO~Ì5o©õ1àhú O™Y$røSõZ f:p3ÜL¯é#Y¨aiUö_tUÐIz±—ªd ¸žíq(;V"$²™Ëy\ì—¤4é‚;¿ÉÁTð·#F>&á¤ÌcvAK~NŠi÷LT c0 4kJêÖâV:vMuj*$T¹U”Õ3ÀÉ;tVoK)ÞwñÝ–§XÞ!Õ²`¨Tx¥œéÆBQb.•ë“·íuº Ë>ØkZÁÈ÷;!ì©lq,:EØ ­§Ã\Ðç]º@S±/å-Õ÷zE»î<ܱ{Z!aè¢1Ôq´ã²‹JW•µ‰'ukD±e1˜íž]ÃYÇ=Òëâ×™±sF»²0f‰Q0µ*1ç«°â®&´´µï=PËÁGýž<_Ë»†£PÚ ÔËÄÔZTØ'bŸØæ}?™pXw°,ä/'ËC.زeZ}ÉFéÅ*u‰¹MÅUWÍj“øô -·æŸd6«.©9ï7õ-ÔȆT°0Õg 6„v# uÀ¼¾¢y:`îèYˆQ™¬Smò5(¬ ½“Úr2ÅXpÇ:(š)ß%h¦. –ŸeœJ†¯~‡Õ¤œV”0ú× ÃêÉä ô'€¿›Ã‰ Yó® !#Sd@)AÍÛãvRyÅZå¡Ö£Á,nă ²tkiÉ^¶bY3ÇC´Š÷!Ͼ‚ÿ«¨µgTj·$z¨وni¯ë1ÈМ⭎åBÉíÚÞú$8éÝ!,§‹ýŸqNo@(9l3çN˜—\%Ÿ2jLÚ6u¾y{Œ{ýâ›NÝ0ºu„C¶‰¨°®à·³‘õ«Õ]u¼ÝƒÂ¹P\û5X<ônÓ´q„[>×:|r~òÕÉO§ }:kå ƒ¯:z´ë§Ú¯©øíòùÉGNî?øâôåϯ¾?¹ÿí©:¹ÿþßGÿþxðçÓÿ8ùäÁéWÛçºðSPê¹.:®Ø;ˆ­m:æ³]2Âk1¢‡‰‹õÍ^Ïé“<9Ó*ä~ĦzI}*dÑ-ÒN’ÎÛÝEÇ6¯jO‘ëZYZ»%&oïÝòCFé¤Å'ƒZ³9r`6§†¼ã†²Z¹×̱EùæžÓÐkE2M·#àc̘4‰Ú ·ˆ•רs"ªŽ—Ͳwð+íOõÚ°E+P³A¼’M[RhùžÏú«C£¡3¡ç²t+IPXØó{ž!à’0vUl%ÿäx$ÙõÞÈ'(,•qX!EQ‚ ös.8ÜdY‚ê6U~b†¢kÞíxÒ¥•ôvªñz®³9¢LÖªTv$üB‹½ýV¦û ½ù=Px5´²‚k%6¶Ï€G(ˆœ¼mÄ.wÚî^½»!)e=äî÷Š'ÈþÓÀÌyYDÕl uèѵkׂ¹Mfö‡Ääˤ–t@ËXP…™K†rHÑ3-Nv€1.ñ<ɧĿîƒJJ²¸ÇšyÇe¢Á¯øÓì-+_r·sMþ¸cÍèC? )v.ì“{[r]¡#îÛàâýPøØ‘ójM•rŒãfis´=¾ï:\שA¾öó”à­sR‡W 3:CÄcJº²Ú:ø7Ì@=XZûÕøÔ(*½Â´ÛmÞGÛ™ºÇÎI–¬ß®G÷UR;ž—‰O@­C@¹¡§nGÔ41-U©¶oU–“ü¢FêÐZJÌÀÍÍCmßžv†È ;É&Ç õøÝŸ›¦-ÞQelU")ȺYÅ9qö®s2P–5lšT±mÿ½t7ŒmYzýmiô+íhH<܇ŠfCæ¹5rzE²ΩÆQQކŰA¨ÿy´¯·Ç•¯œù,D·æÞ»€ŠÁ®·3ªšFä’ì•JñÖvÇŠÌñ¡&ˆ»Ïš1´ú­Bn!i"•„­%Öù¶¨‹%³ª‰×”«²SÇÎ-ާ±‘r)ÙåFƒÏöZ(õÍNgHuªR 3VE1²ºÔGEA=gÜQ`ÿ‘áÿ±_¢–R¬\,AÉQ®e©§3dZpÛÑU®¼M~ai 9 F\mâ5lœÈD3IO¥ZXˆ[Òé­¤ÚšÅJAÃÙ¸¦Þ{¡2Tâ/¹Å®µ‰‚zn}Šß²©=âs|33 ÁL1½R×µ¬·––\åö"\ ±MÃÌúvTrê>•¦5©´z¾€k‡ú|Ò¹žðq|ê G“'ªèD·Ôn#ñsÏB+i³”Ï­ÝdìšìmV$7¦PÝ”©Ìjëúü„êÄvOîi!nÚ#EÛ‘,’¥O™^ë†ú‚°#ÝÈå:hH$1EÛ_à9gp^5óê3Š’|nÓMy0²25.7åóYlzÐäe2#p%3k7ÇYÚ75õˆSKÖ¯zˆ:±'ᘈU®ÌƵÂtÛùíæÛ¶Ã„ãÑk¨» &d aãDÆî¬ÜŸŽÖ\„J†Í°»äD'µv›4TçÞjâ…¸uk wï ygËØá“PóFìÜIêtÂ|Eo±âÀx€ b)±9-'%?q¿l. ïÈ¥ˆbÔˆµŒ±ä6é^»W³Ù,þ}|Zeåµ3v•A—;##F Š)S¬ žkŠtl6àöò½¹k¸­Ã{¥ÏP š üj…WW2¸Ð},Å__â9 1/°Û÷GkÚ*žiÐG*ô?éU›¡j:;’ä0$P4oñìØÖ*ì%ršŽ(ç¢s‹!4¯RŸøîâ]VXKmÈs$óS ,ç‰~ŸZ½k΀jpxÚ%õO ‘œ`Ü.xh‹Å3«ïÜÄb>®9—5¤3óÃdÍÒ'ïë5¡5%“BУڥ¿?QÛOßëúØ£º8ð~´‘F² y±Ž î dºœ¥pG5=l4;ÇÚåêð;$…Wi£æ2¶ò¿\0=ø¢3P'¹¬[Q—.•»@JÑYJQPòú‘æŽ!ãŽÓ1õ_¯¨ÚXÆe¢$¾÷ÑvRBo0¤DÐx]Í;K'agï¢æÜz›Æ½~ZkŸ¶XXÔlI%¤'~è§]Ð4gV¹½n¢q’™¶3Ût–Ãøñ……o« 7òñ½u·Œ¡ÖkpÁ…öª–›Z:nË¿I½JBN,¦Ãùº³<¬ô8Ÿ@zìVon¶Ÿˆ-È>ö’ÎVb5>éHX¬"ÿf?ûÊì8×Uå'HÆ OÉ|»_q>pM4t”c®"øé‡áJ&šyÆ¿+'ZêyÚ5}ѤgˆU¦å§ŒÑ$IEÃæCÆÕŠÚ8 £¥tÔpê^5ÜÒ ÄÏ$«?éÁf=²•xر¸‰´2=¸ï‘ß vn¿Œ‡{ò”, èÔ í{ü{-l6›ÅˆE›7*…Wäà>`ý!¾k»þгi‰o·)×±ZÄæ³aþ‰†ý`ÀãÞr”ÖØ¤¢¡¯Nþ·{[endstream endobj 319 0 obj 6326 endobj 323 0 obj <> stream xœ­[[sÇ}Wþ„*/ÞMéÛÌý’7ÌÍq°Œ‘„“Šó@$ŒScŠÊŸOwÏ­gwV lS”äýæÒÓsúôéÞŸÅ"þÉ?/_ýù‰ÔúøÅÛ#qüþ¾8úùHÒãüãòÕñ—ç4,À£%Š(σgÒðÒK0 ÈÅ›0Í»*ðØ/0ÒÂovz×þ&i¬.fvצáÿ©ÜABO×àË73˜dwÓ‡ù ÐMRúé¿óލà?°xÛ(0ÐN?Ñp4q0lqúa½ƒS’Üúz>X¸6quúÕ ‡¦–§ÿn¿¾¤Õ½ÎÛÀ/oÑ7Öo`³:î9\œ1R©éª=üôlf‹¼D›Ì¢D('0Qµ¥Û¿Í^ÓŽF„aÆf¥•6Å"ïøÃ<ÒK7ýŠHóN{ö1X Ö.¦;7sL>…d¥IÆ’Í:D¸Oì뜆*2ô²îÄ.®ôÌׯ‚…È”%ìnö…‹†.Sb4ûæL@aè=½oa[|±„ÿˆÿñ Ùb+b±8­ZÌ¡¼Ì†DkØÄä !«÷àøgm±6/}0]ÔsýøÓ@áɆ¥n|Ö¬©Ñ{‡â¾ƒÔpR¡’Š`8ñz†õb€KWÿ1€²Øaþ #Õ9ï ú:]€ÄÓ´rÈWt¸·Hwx¹…$Ndq5ü|Y¶Ån‰×.®4œâ³Á Fð]ÜE¤Ü@¸B¿žº"9eôhoÛ‡¬]8~€ÈÃXQzÑà¡ D­ Y{~ÌÐÓjh¿j5æ:ÅPÏ„B¯ ãÀv€)Ù¹7ä`+–Ã'¿AºÅÃe僂‚l*³¡\–1<@Þôû\–¸¨‡7”l¯Ú°Íý lŸöÝÐŒ†d,B –ä'ŠCrW˜ï2Is7~Ýw²»±€9Mý}àÑ{Y±ºæ¼”¸VÛݸ€·)|‡?È¢°œa»0&dPÝr¦{H÷æZÙtØG$ ·¼¨ÅF›Ýƒ8kSÚÈÙ]*£s²·ÌK9ÖÎsl¸EÕØXZ]‡§4ž*7OÐvToî&>®ñu·)3À‚‚”$¬ÙÚ)6$žl< }%;ÏL^ÉzÄULŒ°`Laë=ÃÝ7ZEÔ*b%EŽí€Ùv¾Â‚µP®ì¤3¤M:É^¹³Á£­’»´¸ôßÕ{ù*¯öãJÒa€2VÊàÑ ìÐq¸ØM$:ªdúðÝÝ…Ïœ‡Û‘Ðêýâ*Z™9q”ÂZ„?„áûYaÒ³é„]†­A»wv7”65¡k]èJÖ,;ä{ÒÒ7§$nµß•Cm{O ¡÷-’F&þÔÂïz'K¥ÀJîìÅC:‡wº'Óƒ@ƒbD9”÷Ã8I‚ÄB„Ñ!Š_ôW“î£÷S¶+«¼iOÙÖIáEP¿²äRqµ¶¼p2 ¨­”n Æ€¸”ú£ÈMn²á©O–iݧ)ü$0;v=V@mK¦›žå` 0z%‹J$3 »¶ú'fX!k ‚à,rª[Ãa¨"›ä_• 9n0ÌÁ'RS\HCÞtJ ¸Ò`4WVëÃTL•P'Šˆn…)~ð²ÏMɉ½fZS8ƒ@SJù`É~ÕS²K…~îu´Ž†€µÎÚ²¬ðÎBÒ0çØé€pœ$·aàbŸ ä`!2í/l[Üî¼-÷¬“´3ä ¦Pr+FC0=˜½—ïg¨€0’5|;\Ï&Ï2#Ïð©'v{Ì›EÔúqötæÜô´j¬<=€L.²Æ•3j ˜{hy„ùvú¢@²‰|ÜÑ4jë u$;áø¹ œüýŒGÈa;ž:`¬AÕ¤ Ž´ŒwlwTÄÿ€¼‚ÊÜw9ņp§ñßÑ¡«®ä$ßþn)"ÊøºœþF `”e-=v6<ª³8AG(Çûx¬¹Ö—yÕ>«l1ÅúÆ)t?ú÷¾•˜Ž"„ Ån묕l@ëbïÀDì64 ȶÅóÆf=„®ç:˜×ñ0ݹmçs0¢ðn£àÀé1’vË*o"Ü]Y6Ð0Üž¶&(®AG¸˜¹Á«Á©!JNr•¦Ìôå\ˆö"áËx+šÁZ¨ø‰¥€Ipόɻ}o—¶ó+,è1Ò9‡°O:ÖÅízÊå¬F ØRzÃ@ûÁDÍÁ´‚ì9Ä$$Jd,–0 7ÕŒ’ TmÊ}è€Â·7‚~fè[+*Y¡T3¢¯1ÃM:)¹äXL— ~ŠÔ›MÉ%ÃYŽ"óŠV¼Ú`pÊpøx6r\«u2&Vò†tªñ…€ÿÓi]m¾Å•ÝôžZŒT;ùª‡×§Ò|Õ븆´{à"A0FWp„5eÍñœt"+TÂLšÛÓ#šrR¹-ßðf‹ûü°|3ô>ôf¤d’’ˆ´LÀÄ•ügN°ÞƒÅú`n¶œ‡—Š}g)ùt|‹ òûiW´¡š‘–/ð”pÌPÆPQÇPÙ§×ê ðW |Ë;½T¹“ŒmþB ^üå4$”pzHŸ²Ñ2 邜‘7w5‘^ñÌ=l …hÆãÜ™µ…‰P:µRb\šïK¯V±Ž™®hu äjJ~w«[~q[·([ê–Ae^>fGÍ´ä4®÷{ͧ xBÍ7.áÐJ+¨ºZ×b´,§G4&ÙV¹“~d‡uÞN”0¯3J*k Ô\$ UAéY@tu_Ào€â:š•Õ$רÔþÛ9k!•íØ¥2–û¾ãýÅ$ôPf¨²­Ø„„Çpwövp'æétÉŽ>bÓºöK™öp¦.3ˆ¾ýÖäNü8!ÖHïY$/gVwì6‚.åBÇÈCåˆî³ÞóblÅF2.Á[În§i,îœH* õˆ_QË`ÄüIï[L—ƒAê”Oä-––îñÅ*†săQÃW£zœ»ŒÍEei/ô­På"•<ŸÖpý Á£¼"TÔVëÊá^a¬¶ò–úu«¸¦§zŸsI#3®fI+½¾q[¤ýEßì5+ž=v[VšŸ–JÕ<¥Ý'C'/ÒgLv³e{üò"0ˆIß5Ú‚ 7ª™¢c*ví©ŒÅfxÉ`!ÖYÚiÖ¬.ap©©WµÂ"‡%†AÜW'–û< 93½g C&õÑWŒô5´ /j½ŸÚ¦¤x;PÜ)K͆À‹ª¥ÙCÞQ=M¥Î§a_ ¨œ l}¯!¾˜ÊcœN3^¬ ¤¥}ôbîF=ŸÛ`*à[µMòžÜ¾óŽ¥Ý3«:öJåözŸ@oæ¶èÛw¿ ƒ$,Õ´m DÅ׺4ÁGØêŸhš!æ†ø¡£)&óë­ø#e’=8Ʀ•ƒ»¸ÜT„MNWÖfÅZ›Tnå6•£:É_Íí{X˜Êƒ%¿%FP!•n]‘ßÑ`ƒlЬÞuÀL±yÑÍn“×ûM:ßFA‰wWMEMFŒNÎ…YØlÚÇíN¦ÚÄ,µ&:Óñ\l+w8õªü$a JTظ€k›–×µúŠòô^C=»ÖqN{¬ßáÑ×m¬úø‹ßN&%L;Û™ˆ¯|'ÚÝö&!®Eôð-2ŸXÞÐOLÿJâþùÑwðçÿ 0-®endstream endobj 324 0 obj 3395 endobj 328 0 obj <> stream xœ­Zmo]ÅþnåGÜo9¸'gßw+TP©¨hQ‹‹*Nbl‹Ø1±M“þú>³¯³çP’ËžÝÙ™Ùg^wÝ,³Ø,ô_þ÷Ååѳ ¥6g7GËæ¯øsvô둈S6ùŸ—›Ïã4½‘Ël­´›ãŸ±qrcœÚ_}?}±Ý-³±Úy;owr–ħ“í2»Ø%L×y4Èév+æ ƒÓécÊ1½Ù³Ÿ$QòÊ9i<þ[Ù]ÏÎ;A»3küæøë£ãòÆ^ZoÑXf-}Д!©Ò?OhXx-Àmí|vº ~„_D˜®0W{!Àб!fo›z¿/ÖY|wø?_wVNO_b†2ÂJ?}å\¬ ÓñvRÎ)9}ÛH° ßµe–ÚO_ǹÚ:Ÿ9sÁMÏÛª,›Ó6Œp¢ŒèdzG4œ64Í =+m%iÎ*"&Šæ$t¿8½èiÞªy PÒÍBOŸƒ7œ€^ïˆ!¥%ôsQ§¾ª¿^®?K,¿jƒQ§`C9èT΃&$}'z0D-ØE-.“Z´†hª A'iUÒ;hAAK8 nô]Ô |ќ簄ˆ…"„¢ƒcÒy±(bÈÒ:bÈ0j-r™ð%ösÎC'ˆ³òSo OÀ›%øjz±Õø.¤œ^C"é´"å­·u ÂKì…7“¬˜n¹~qLFcß[ð彋ÖfÚÊ+N˜VJ¥ãnJ—ýD)çh(†”­ü¬´q›»Få–ØƒÊ¥›4¾,´ŒŽH“’ üƒÃ¤’Ügåz9)böô¢òsšˆ@§OÚÌW…³Æ7©Aøx"?LUÞ°Ã\&7¢?lIJN!¡»’æà´Ž_ÂWeÍ8á£>Hv8 ó6šö]DTH> [«ãoh™€4¶ðMËßÁè6qŸo€ñM“ÙÆà¼Ì™¡ÈJn¾‰–(%ˆ\UfH®]l‡s1v‘I¾ï¶BÀÁz3ýy+§ÿàÏ3løþý;È[«L+Ü3?²h<€ª –'„YY4@¼$£´ÖÙx80äˆ[8o%MÔ[Ÿz§;°E¥àŸŽžs²Ãö˜‡™íŒÉ‚É(W¤4ÌÂɇñ¤x‚waxúmÚËW$¹Ø'5úÅXªødI=ï´Lfˬõ%ñFANf(¢¾BÙêGr–­P# ßÃY1T²$¥=\æÞ§ÓxÒ3…núÒ°Ÿ´e%0ü:Ç"·¹jõÇÈÄ^¶ÕTæ“Ø;§šDßóÑ1+¹à°€¿}Mjî}4BÒ,…í¯4::Þÿ¶õYA³ÎlÖ1²ŠƒUùÎãÆ1Ø!Yè?ð'Ë@‘ó«´3X§Qi,Æý$‘„î •Å°•÷­6@ 5y îéq˜ÌAu&f84®1â¥E*ÖÈŽ‰22V£ Ø+Ý•ó&Ûôut$ í3 ÚoIŠqÙ°ý–Y ?ÇÞ‘s½¨he¸<‹¬F .ËÙ‹Ä¢æÇõqôÎÂcÂÇG²x*àx¬E‚zcb8˜¥1 Ö–UÒ;ÿ/öÀj4¡Ç\ó;ò.V'|×r—ë 则×è³,™w–ã£KöM‚ùa™àÁü íCþEY@’'>ûéMí¼RCʬt c<º%\õ&s»Au a štÝðP4µ$]0ŽÚ–÷Æ–¥#^³t¸~Ã2TI•EN“¤”u ÒôÕ ôŸRwœ}˜þMc†dÃá8Ca+OzK,‡9r…ùã;|4*ÙŠ$Éy2È‚zÈÒA`m Rã² ¹w!NË¢Æ9¶D^ñ`‚ƒ‡6÷9ïG'ØJRéÛùŽ\CÝ j +÷„ç{À&ÖÖ8±;)CO)ÔI‚×íîõ6ï¿øGçb=´V¹XNlž× ÁË- ¢rú×®§gæOf•PüÄá.-hnà’€©à’+úŒRXMue³ YèŽâ þ¢Ä`^P=F%M?Ó_ô•Фåè¼bôÐØé{úÿ]ýëºR(™ôá-iZGÕÿi|ÖoëàI|SÏê¯ÓÑFè‚KSoêàm<ÙRÎJôª~~Å?·5Ź`Ä_·‰W‘ŽY’NÓçëûéœ×±¡Tkbáö}ܵջo©€ª5Ó)ß| ·çé§ŽVXGO9U®ãÕ„møLáƒe'mÙxîõgŒ”%´\ÖuÒ R§=(I‰1GbgÕË“oF‡ÎfÊNóB˜Cš,?¤îŸ÷fî¦;€<¨8›\yÞ ^ õÊcÆ}YÕõKÖ#jú@_P[ek§Ó+óŸÖ.G˜ý¥ãÎ,žNšq>Zôf$ÒË6ØöŒ5MüIÒA&ÞM|@ªë|òT#ÄTïGZè/Tï¶é€&Ed}S¤Scoѹ.›»ÕršùÓëÎòàEì<ï¾_ujb(Ø ò»ÎçǶ"Á"•;ij¿äìϹü)žNM@8Kaòš—!ƒ„³”E®Ã…â³”—g=þÎ^†µ”ÇòHȆåP Çq>“¢øq«tú¤GZ$w_d±Hû¤ºãöY!t_µ¶ªé•c×Na sD=Æ…ùÃ~×áƒ^¹¸;cû2ë#âÀç¾”H­_¶ D-’•Z h²¥ÒÒRà—øìUMÄ¥õ3ÐÃJ¾®½W7fÙÜÌfØoû„ä±¥ÜÐÜ)–7ïi{h""cª±~:Ð J‡á»jð)é/¥“ÃjðaüOÚ=ª×P6îâIU{aQ¾®‡÷Ⱦtlˆ ˆz°‘(Uê}îÉIA@sÙ/%Æ"¾ìÌøÊ݃26(6È>oHeà^õòÞm½KWœ˜¢Â+&MF­+…Ró–1㧺_kkSϹ낰NÊ“ÖannÅdµþ§]×#k´ÏF˜î)ÄP Õ…9ç‡e´Ô÷^ xíÚ+ô¯ú]ßÀéhyÕ`Ö×2k_ž"TW;vmfUÊSÛ¹Ý KŒl¼³1òÕû:,]bC|ˆž®’Ã~Zù%–·"¡¾¥Þh2¾ë0}›ãÏ2êz_%Mщ?NˆÞ‹3Øíu“Ñ5“â-ëP7{á·nØbÊ뵂;j@FŠrBŸì‹M½k¦sUP.Êîš(é¬7™aPÉ'D+¿LZznkî>TKK5+> /Ë;·; Ü§ÖëÅÀ_kßðCк¨˜eý>´òıAïpbȵ:Ì.ë+QÒÝ ôŒ €«§“}–Ù™P¬eÏï,·Ê tA™¹£…"Áº[Æ4&èÑ14—ØHø£¼TÍ|`€HzsÉÁ6Ëù-&-Ž_'Õ~ž:”¦‰9Ä$µõyÛu3V“¤ÚFQ©ù )šH>ðÀ‘[˜ÍZ˜i$W]gò""=5`WVç-î ë«‚ss DTf}îÕFøî]´QDeðÞ¿hó>Ýd d®âQ­ÚRý­DDÉ,•ÝšŠÁˆü¹ÙmÝù®[<ðOrÀ÷Å‚\%/©šxð&®/ ËjuÃñ,ŽYÆð>«¿\'•;eÛß)·N/ôhàPÍTPÐW­¡ÏzwÏH³äR`Ò³ÎiçMA„–õn½Ÿß•ø(ÇËû½Õ{…xŽËy¢¾Ö£L¤l6 ¦ƒàmé%ÛØ§7ºëM¹Ë*DÓÓkïiÎd®”MA‹'MñZ6D?5²ëý£"oã;€º™à5AgϼÆ|¯T„jVL`ÔÆoëV-fÜã ݪƒ×ÉZœ™mmS‘“7:&´½­ß_d(w(aÛèV•~ƒ íz`iä7|¬œbiôDÍHxŠ_žÑÁÂ(gÍ•/{ý³›¬B%\_“³=zŸ‘¬˜[`2¬¤ÚÞ°ú:™ùÕýwfôtgðά@7È=P—÷ñ«Pú#+‘‹¡-uu¯\[²“ô¥{8zÇcrÊàÞ'¥—Bd*?«þm ;zß=Š®4óSçóÈèÓïÛØ[EyâbÝûõåA­µ+ßž”¬J†ø³‹6£×ŸWÛú´tø:dý|ª^>|Ezн¸xWʽ@ Ë0*ÏŸ”W¤ï™¨ Ú\V» 9fUËv³5ôõ/ÇGÿÄÿ(CÁendstream endobj 329 0 obj 3469 endobj 333 0 obj <> stream xœ½\YoÇÎ3‘±ÐKvs4}Oç!€e;¶Ù‘%IÁФHB¼ÄC “?Ÿª>«gjvW´ ^îÎôôQÇWGWÏûE߉EÿÒß˽§¯„R‹“Û½~ñ-ü²÷~O„&‹ôçðbñì 4àRç{/o÷bbáäºrqp±÷¥]™ü›}ÓÜh~pM¾Zí«Î9ïÅò»•è¼´_~¹’Ë—«}Ñimœ\Ô6ßÄ«JËWpUAŸK¹2Ë®Ké;)hФï/½ÖôÉ/W¾§>Ç[ƒ½[þ# w¤í¤·©Ñ …†ÙÉ®ï sP ûÊc…ûZawκܴɃàÕ׫}Ï81ÐÁ±d'•^¾XíKzëÙJw &2äe1H$MšÆ«ÕàºÞKµüûJF2+¡(™÷…sÝ û@&'¼ÿ#LéæRM-ŸâÇ!~\álû^ˆå%þ|‹gøq‚÷øqƒÇ«}=ØÎn¹¿ÃÇiº“z8ÇŸ×ð‘ •˜Y'l/aj*Î*‘ÇÓ0Ë Fg­³:ô)Mg´ wpVZuÚÈå|,Ðâ4>­½ Í• ÍI'ø$Ì)j{Ò§ÆeåGo‘øÆ hd°”8ž ÷mŠË“Ä͆®¯ë8)§ty¯B‹Ëf”wÖuZÚË:w½<¢+¹ ˆ¤ :+aùbzÞÁTʈo £¡Óª—äé#œ3þ0ù¾‘–Ü?¯ó…›½Ðjù±*ÉÒ]ä§E[¼Ø;øý?²Šˆ^¹ ]g¬]þwe9 pñoâOÛÛ4ü %i½ÄP²e^¾M»•8š0D(aרD;h‹šç>;ærÈé)AJ“óúe&ÊÆ«‚P¿UbÙl&#9êC¨–&0„p}$S¿­_Oà‘T"DZ#Œ% 9.ÄÁƒò€³ÓC†ê×µÓØþSÁ´î¤lÄ3ϹÈBN+FAÆ"‘Ò]¯ù´Ö^$æEŒe7J™¶yÅØ7™Æqîeß8”42Øeºh€ˆJøösNf…K0½'GÑ„"¡ö¥ö…)\ Kâä\^9¢[â‡;TÅ—8Ñx¼ó†>5؃ë OQPNZY·øIP ð^£eS”—T`0 mý<´ö*(õã§b¯ Å‹V\R‰ ýö WÛå®ÜŸ79ø nt¨@$£–ßC§Ö*£Z°N l®3‘SBéÎY÷&ÜŠºâ:›U%C-tKüŽˆ@F¹å´èR‚HÐ&cW\rYå±±‰I®¨yId4rÃJøú$r zµ<]TŒp‚0Ò‰åÉâÁœ&Ö£DYÆÖ#xGø´É>ÔAIj•ÁÏIŠ„d zdü©™>4DŠöˆÇjO•bdÙ°Õ¨æm£Y“OœÏcÖÈ &°…-% èEpÖÖ-âÂ¥FéÓ¦‚<ª²<™ ŽŸ¾úÁLg…)TÂèB>Æû‘Cô ¶Sé$* ±zëÖ¶5“ƒæ=’r“‘ Šêpô¬©­eî±±ÅpñQö•è/;¡ˆÆ¥.ßTE¿¯Tu¬Ì+œ—Ÿ%þô²Ÿ³ µÌ÷Ob\·ŸHÙZ=â0#™ˆ„W{X¥ m:ÿMÄ2臛VÞ ?8Ó+ŒÿT²¦D&¯«ÌY'çZ„¥âªµªgS#B€ajoQyÐÞ JÍÔ࢟í•ÜGƒ‹®V ‹Ý¢rd6åÚʨc"DŽ ¤ó%ðFƒE´!úA)&“‘6¼ã¼A;¤ DŒ´SËe¬£ %‹j’•£Ø”T G‰ˆ™¥†ø—Ul1ÚÒ2Ø27À’‰èG1€ÎP Í« ­­‚·f¬Ì9ªH¢VkÑÆ,@ÇèÍ(ZÍ{C”,Ô6Ã~¶ÑW-ÄÝÅôz[3^^V³&.–ö1ˆŸå`g+«]µ²k£‘’™£vWX8i§ mÐ75-ûï-VºÕ>¶£ -§Ž`òÍò‡pŽ,Mž£qt„Y)?ä©¡ÅNþMÚ<‰½`˜ºÍHµJU5&Û­‡;²µÈxÕëÎË‘AÍùÀ”¦ä<FG’%f-Æ$¼›†˜]¾ä1Ík?¦ûpnóQ‘ªÉ¾Gà5–ÿù(¢c<€ŽÄι»&m ‘FÀF’®Òè  ŠmRØÙ›²M×ÕçÆdÃŒˆâ§Q@È™]Œ×±©Vަ ɪ#†›Nˆâá!tLû°æ*åò¤íá©Ñ…¼ÊUë‰Â¢‡„Ë#ÌFœ)¹G••w³ FDzÝxýö€3F¼'™ÆÑÎñH›¸0µžÌmråh ­#ØÄ<˜û5mÑæ Iòm'mA ÙíÛ‘Ègƒ=þIÅ€A ±’ç-ýÒ‰¬d¿'ì¼g$œ}(wºEºÄLNï8R%ðs¦# ué. “G\§t¡ê„ è?ྞ³)iÖ µcoÙ–¬ÊÈ‘k†OÁH©Ö/º¯š‘ýèæ½Â¯ªtN@Ñ{C¥÷u•^Ò€DÛ9{©¢W)¦õj¼%Ü)Ïá່ƒFFpJÁ%ÃpýÔdWêÇáÄæ‚Ž2q±Y’'àƒcËä: ó j`x©ß9F ptþ“öÀÞ)‰ãư’€6­É>,aIñwIû™ðŠ ÈÃ&€§$à®ÐŒ WÐIUöO¦ÓÏ 7±PyËqB•œ¸[CБZ?¹é”K$fCd«>ÚŽF2r‘kC™`\h 1µ#z¸Ëlf·]ªa#|ïœþ ðÍbâØFÄN‚ F˨Ђ/ÿ Ôp&xZA—:6a·ÊŽãÐÝR®T;ì3+×lsðB3‘yÜsÀ½Ò]”3Te޾ŒšM1¥¹ÑÍ|NÖ«5ª½+ZŽ y‰ ¤N6Û%¬?b&C¤4+Ÿkb…«äè¢A’n´ÏpÍèõTMƒâÙ÷kÑ7ì:¨mÂ){æÈöê5¨^„psº;œöçv‡Ñ[Yœw\SÏ»D ß%Æ ~O¼ É3U×­çPH!ø1ˆ&0N~ ‡BÚò>Ä(IÖúÝóiB®,Ù…\Ä4Yj/\&%I·’æ7Ö/éÕ©°ÉYB± 8AÇC*m—“*û])†Æ w´?¢Å— g »1?ÙíÆ³#&ÕX/ÉɦôèOdUY‡t‡šÆô%S©ñ»ø"€Qî…å4Ãe*áûf ¡ 5yßìý¸÷~¡T¨ èÐѰÀA“…îŠrÀÂËgÏ÷ž>ÿ~qws¼÷ô¯ ±÷ô;üxöò+øóüëÅoö¾y¾øñSË1µŽ®3 Ô)k2q™!¿$îŸý,ɻɒ^®LPZI+;SÑfðÙ|[:š Aƒ¿;,ˆb1•ˆddËîIÎøÁý‰,·Å Ä©\¢T9Ü„ããíâlÌ~XpCl2õœµY'¼kÂkeuÐaºÍ^6¿í>·—”E¶®ÁË#–Àább%m¸ó÷ |ˆ–ÂoÌRß:ÖÏB?Føè<+ߦ.ƒw/¢È`Z|ˆY|(…¤ñþ}½_{:¯Qbý0{xÁuzÓÌ)¬(ÖPÆ‹§µåº\¼Ì+ÔH¥\n|]îßÔ‡jÑñ 7æº^,³ %¨YecªÜ™åNøvEçLA˜xï"¿ ÅMiþ™èÒ[ç–Ç•‡/*ê˜Wœ|¬Ã×Ï@ò C(~N÷o9"‹8É¢vÆòÕÓé*Oûj †_1¼‰ªë$)D=n„7};Ú—‚”âëíC¥hªÛ‡¢mE^DŒ™cíûeþˆOŸ¥ŸtÙ‰V•áw•#¬h†ßn”y^ÈÎæZ&!»åZÖ%2<™‘av¢õþ-]2y(]¼ÈzeèL ™¡º˜„rõ®a:ªÿqáÏUfWðh-“Rߥ6™»·«|taÝÊÁß-šxÆ­÷¶ɪçî4fqä†ó¨ŽyÎÍî ÷8ÛçÃQ®dºoÄ*ÏžˆÀÙ„¯:&äòÕ®Õ` ?Ĥ^Fàýeau†wª”AÍÏ+œGñX—æg”Ëé™nU‰Öͦ wGû˜jÖš{¦±îñ}œŠ&t¿ä&ñ±òáw¿2ò«–£I æ„øqè ݘŽ&2Èãsàž¨ç¾> Ü‹ i}“<‚Œ c`g¡­2˜¸Rç`­Ä˜Ë?r¬f‘ ’û¾i™ÙqÃ1–Uú*"ïf$º"ežçÜÚˆzo/²üõmUÿ»FZG`Ÿd´BEù»«3õC4Ï·ÔåËþõYn©Dhùó’BbC¥ÚGµ“jv+Ynä„“,Ïñœ ç/jÇlD‹=¬S@­nÅ‘i§ÑŽ´Z7RsÞÈ¡qˆRÛä°k]öÊ­÷­Å®¦ü24ʦ+“û¾nèSüëžú«,Ϲçdòœ*çÛ?¯ÊÕ ˜°F~ÈÈËܧ“ð-.©pLJ± K”ìN¶ÆP;Ëœß|KÛ¬G5‘zVN: ›“šÜž´)‰œ<5ªd’Ù-‹ûdQ9pÏ:ü}ñ&²te`©h3ò3Î+3 6TiÌωõ¨Ê|Ñ(såPÜAOË¿sðt¥à”ÓÐÆæO#†«ºì:Þ6sT[_éÓ2 ;Æ×@¬¢Î Û ¹@~()_âoÞ¶:Šˆ½dŠhÖ᪖ÀáóòñPmL–œÌû*4¨”À¥Ë¯ëÜÿU.¾¨Ÿ—‹ÏêÅWåâ—åÛ«z»ŠÊ¿êÅ—ô™|ñ \üQdý– õ9kn8q9áøY™<ÂFÔD„Ä–î9w“åò ØùìžOc²þ3Ž\ò’o Óªt1ªZtW…{‹Ïw3¥P“"¹®«¹æÈÊësnÌ Ý_d[ó‰“>· tÄ)iëçp™©¼Œ ÁFÎú(>?ÎELÂFÅìñ=I/™„åàﯠ(®ÄȸVŸ HÄѪQÜ`!KrÆ7rä¦ÍåÔ¯Y|¯½ìÏ—Ú{»¹§‹*ÛæLhRâÄ&MÔòžÈN¶T_QèšÄ‰?UyiÓH º‡'ZŒ9.nTa?ŸÉRewAýQöätçfŤKŽ9ñ`H’ˆ>Ýüø‡-Ö—ˆëÔžŽ9›^Üâ<âfWð|³ŸE*èòQ{#Ómv‰ÑÊÚXGHš¿ÎÍÕòoðÕ‰ ¹¤Æ¡ì µ[î;¡Ê{\›vãñ5 ÖìXZ†ó·Í¶ØŽ;\´´ _ѯ’a'‡×šbÐðnƒt2ž`i© é]oÃ;ÌRí èĦÚáìÿg-Cß.$ÕÍ€vк"¬›Q>äéqМ®Ùáõ%T{ØR®æuL ¢/+rkÐ5÷sõž©4gô¢tì|ãaLµxÏ·Ùµ.~§B”É;R¹?s€ÀŽÏž³5ª¦L/õŠ«‰•.xžŒ9¡ßö‘‹°·–r¦I·§µÀ×6ÐÓ#Ïv*L14/ó{º2Á @«oÊ&læØC먴 Ûš0þG_dƒ¹õ4ëøåa¿Š`k€V?üBÁN/Rc«Ý_àÒ}zk¢Âª+$ö:ùM¦‡÷NGõŒô Bà_¬‚¯²¤K¼éb_3Qªô¢“lxË˳L–¾ž=8û ÂM+ç…<+ y•ÑL}9dÑœ$MÚW~%2´Æî·ÕÄño–¡olNÛ‘s>»¿Ë§E¾'MÞüÓgÇrBæ4Ò—åà5ºî““pÁ{E·¶þb×)Q&Gü¸÷EÛùãÞÿý¬êèendstream endobj 334 0 obj 5054 endobj 338 0 obj <> stream xœ½\[s5Þg?âµ[œ³Å™è~áa«’ [ ÄÀR°Žm’,‰í$ýõÛÝ’F­Íñq( °ç¢‘Z}ùúë–_®Ä WÿÉÿ?~qpë©õêÉë±úþ}rðò@Ò#«ü¿ã«;‡øXÀKCQ®>HÈ•W+Ì ÕêðÅÁkµ±ëa£ï½Î¿l}ˆƒa}¸ÙêÁ)ôúÞf+c¬WëG›­…M´å%Íú>>B„«_mÔús¸#í ¼á£|w`$­a,Ö6[Å_¼³1ƒÖÊ…õ7›­B^¸õíb &ÂÕà]ÿP®ýçðŸ$‘À—jœ,öðè7Ú¦‹[-/cL÷ò¥Zÿ³2rPÚ¯OÒú¬•ëS¸oŒTjý3L•í×G ¤7éÓ{^„w¹Ñ°§äúc,‰ðWka®zýj­wŠ{‰ظ>‡qÆ_õ`¬Z¶‰Äf$ÝxµÙâTMTì;ù¢†&uV7f ÏÀ´ZÓ§”NŒ“À«Ó‹^†zýfââ€þ–6ÐÇ(ù4ðÅ‹ú"ü¨ìª(«ÃOÂã0 x¡YÀy Î5­Çk½~V>ÎVR{²Q ÁHßfâ\µ¬ÁEâf«UEÆ5±8ÇÁ@™ä¸zü›Õ³™¤p«´‡­ SiŸ¤M6°‰éµhM¹²I{ d ïæ/)/‹¾áƒ§åAÑ8¾‘>–“dfE\?åob¸[ ó³ nžw>[ZëË6IWÕØÿ” 2ñdn¥¬j"×QV«éäí±&ðÝBUý­ö ¹ç¥4÷` ¶LTõ§S@ãÉûÀÉÀÚ È×þ¶ú›‰\ÔAŠºJÍÆÃÇõ{TWÄå;êJs)±7ñ3—øº¸Ø³þtÒ»}‚Ã/`ö?­çÓªm—7ÆKà²`j´uÐÉ®"¬ÁÆbXw«c˜i™¾hÞgA#ouµ & ^72Ó¨ ÏüRÆ&M/zn0<˜yqT¤õuçì'n·Üg‘;XŽwþ8)†UnÜ'×â— ,Âרo¾™Ì'ËìÇÆÄ—µÛ{ôFðÖaˆäZ”UưèÝÂh5šcGùgÑkÔ’ãÑŽ6–>>p^Ž€z.i3 O;žôxî” × æ·Ÿà C!tªZ¤9 y,ª–°ÙàE˜Ûgvþ8‹l I8mllTMÓ¹ïŽ.ýÆÞÝEÒü°}Žo€ûy“¡Z¹@}TSÈÎZç;ý¤°i²^õ4½dþRžüõBS¢Á‚’­aè^²µ.>˫ՕuœüšåHÙi[ˆd±81ÚÄž‚¼ FÑã&üÑ] àH { ƒþ&cG2XóÐ0šÀ?†ÐÃ|µÝmNÉ0²„ÚÐQí9€úS—v+qß9N»Ís¶aw!²ªSÀ•s¬÷¸p0ø±;¦%–ÒA²¯Emk0ýþV‘-îÝ­¢Ìa,˜•çn­ÂjŠ#8V1è½ ðš„oÈuäô¢wðàV‚þAl\‡ê,úÖ/a)òìf:ã­êÖ]86}4qÈ~»‹@Dün#qž—noÔúßðï­ ^Uô€? ¯ým»ž)Ç2|*Hkm L·Ç!K¬kÖ…¸„¹ß¼"³ž`º&ì-ëÈÕ.ÊóÞáÁ×/WZSñJ¬@ÂJ+aì•ñX¿ X¼sÿàÖý/W—¯ÞœÜú~%n}ÿ¹óð.üïþ§«¿Ü»¿úz¹.ØnZ© ¢}üŽ…¯Ri!ÿO¯Zsm{¨Š]T¨ «E‘0Û+ÄXÿ‚Ë@1,r`… šø|Ë1pýÛ÷ÓÔisKšäГjÊÚ‘ßÇuø­(*8ÇÉ`ØàC sÎ3n _êyÈsŽæY.@¾3ÑÅÉÓ¯N`¸UëÿÖÚçi'0 yhÓ}H‚’=NHd5å5=t”,èXÜǤ½[+Éi›‘t›È‘&bXŽèAFð”•Þ››F)=ŠïÛgÅh+…Ó8Çž. '›Íy[z­úW¡IŽÄ*ƒ¡0Ú¶ @ź’J%„)ý¬*\ŒÅ >ý×5XÇ›!ž: V\Æa=¥C“Öf9¶Ø„V‹pî*G êºèh%à)r´Ögþ@G‹á5ºæ-.{Z¦¡E«0n.št’Q0Üþ²c5ZB´¶€™K 7BJÁV»?A6€§²yVܼ Ú©dÎ" pù]pÈ˵2.D«–++¤zf \¶ÅY²Æ¾/ØÑ‡Ÿ)#ª`él‘j?©èÞl.K”uŠ17Ê{’À´ëÓï͇Ky‰_LĆãÄF“¾â,§é K™½/kb½<žæ¬ Àj¸¸ oš’gë³5¸Ÿ½ü5’ò˜f2ÝFè%hÏ"72€«ÑA~5Úó…tÛNîUEˆÑj9Zª¢%¢¾†uËOW»b<ØI¦o@‘X@e¦ÀuÜt*SUø2ÇR€¤eï—WÄ©|W±‡5ª ¾5%ý:¾Y¨˜ÌâI«ì“ÐÉ‚óÕ0ù#·a꯰M(~Óš[婌»„{ šÍ¥×bPÆõV(÷2—I¥ôåÃh0£XY+:'üÖ|g,è„ìpŸøÝÝÅ„œX™`IPómlÐìKù@yå{iKñ„G'®—îìUÕ”yùwV&ÅbÆó¬Mf’&ĉ‹Ÿ@˜rÎÚùgž~Ì©°†­ªTïíäJSçc1§¿‚ÌYÿ%±]Ký—*u^Â÷ëà·OF•ÄdlÌɼ6IYÿY~U(NûÒ—«iÔn3ºƒæ Øt[•çÿþ{ЈA––+C5Ž1‹W‹éXjºã/ýÆ&ÊÝë½)cØ^etR¨£Ìv÷c¬ßn{;éR~§[}á©òe©ÿľoÝÇÑzyÒšÐóï)* EZô˜AçâJ½cS`„ío½Á€m5ŒM&2£Ö¶y[äØtñ¬{3lº2lßã„´`pÏè¶ôyF ›-:É\–‹ÀæEjd€Ÿ´R'Øx‹Ì4Ûc[ÐÝæ …½„Z.²uŒ"¼†ˆþ‹® õrÿó®r÷yú>ÂOCV°þ.‚MÙÀ½ØƒÔŠ˜vJ“–6Í–&Q˜úZG2k(ñ‰ï³g‘Õ¯ÙÈyÜÉ`æÜ63pH=ϰ'¥~Xléê“웵~§: ¸Þ9_Ñ.Ë]ÓMïÌŒ¼aœDÁ8XGF!IÅ“ þ3*,Nk*qé ÕÐËhºmì4›(w®Ë¯) hÞOÂóJ—2ŽáŕǵjßcÀj ª¯”&b‡ Éõx­¨fÓGÊàšêŸ¦¶OEO´”iS_L:ì&Ýû)áe茖hšI\ÕÏŸ2És—IÛ RÙà3±è2›‹e}“ŠY˜³íL›Ä€™ï£©Cø¯åP†ºß?ÁѺ¶6aJǸØG6ŽÊ`[ª™Ø `¨uAN ÄÞ¬“Šù” N)^¡wªE¥{t,Tæ³HðaB@1šZj¬6ÎpÏÕApù÷ã´ß§Õ‚.3 ¯ºœÂ â';íYÇš«VvIdF 3­ßAz1ÍIo ¨C·U„wF¥ÞÖò÷0-LNå)j±V*ÕsçnC_×íÌ”±å "ÓÁ°ÂIé¤NÉà³¹E¾ì(¦²:÷£úåZ(Â÷Çð¸LôñUÔT £@zð‘…1£Ÿ˜$_$8ñÁ¸&¶5õ¾çUå )|‹ëDŒµx!-ðã·#±pÖåoø  í½iîWùÄ„­@”-jŸt²3΢Ì•ëDÈ…jç€XFæ%F³³UÅ—3ß5|§+Cÿ„ƒmê%üúàÿ°pÊõendstream endobj 339 0 obj 4749 endobj 343 0 obj <> stream xœÍ\éo·ïg5ÄûÂïy«]K2 Änœ¸Èmiш,É’k¶eÅqþúÎr¸;«ÃqÐ&ðÓ—çð7÷¬^®únXõøþyp¶³ûÝ õêør§_}ÿŽw^î ±Ë*ÿ88[Ýß‹Ý<4u¡ÃjïéNš`X9µ½éµÚ;Ûù×Úoì¿÷þŽÝ}ßtºïB—›­îœ aX¾º¼ ëO6jýÍf;tÆX§Ö{µÏ§©U¿þZ5̹V»î ]©Ð©Ï]úÎŒá#?Ù„žOúù0ôný¬ü¸ÁéÜèh:èC‹`ëãÍÖÂ7xÞák\KuJ›õ›­âîoL§a#žŽa¯4yßm¼ëú ôúŸ•ȬÍɼtö«-É !$ŠQýúVÆ Gé{¿~¿áÇ%~à¯Ð> ëøë+ü¸Àcüèò`뺳cWþÅÎÞŸËü§Øå~œãÇóØz÷•>ÚlMp]ð.íø)M›†À`… ñcœ,5>«¥q·|;­ëDOj#-Ìz_ô¢4žÔÆÚóÃÚxÊ·4_èUiÜ—ßÖÆKãÏÒ˜_Jã4ÑkiG»¼ ¬\h¶‰WËî3ÞËU¾O;«ït•Y´‚c àÍ-À0Œf¾z4F¾1ÁâB l#¬¤;غsÐh•Â- µnT¸3Cq'4öƒ,5öveaS¥Éô´ë3gºqøly c?ÆqWuÆSàF`o½>Ä­ØIXg2(Ýè›å ežÐŒ…÷q+¾ëÑÿi.šÓâfý°·£4“ùJxÚÒƒu¥çx ç;cõú'zšˆî4ï×ÏIà†H;‡×‘ò]˜î]§Õ@Úàƒ*$ël÷` ?€Œt¬‘ÁR. Œ» 6nÍŒ ›œe‡u…tˆ~@+@ÞRšßö8 n‰di/ʳ¾õªjã _(áTÙOeÚÚ³ì#ÑrTÐVŸnáè¹Þ#¹¶D¯mºH¶Lok¢·5Gïèþò]yG«À ’@híQeÄÖâÂdAU$nè»±èÙç›n,ÊÕ)VÑŽbXM×üGÕ(|-q=“"­ºþtµ&ÝÝSü”±i4óoDîc;=N½m>~kJýZp;C0ùÜŒ#>Â0šò9ŸU‹ÎÍZcPÌŠP9ÞXnöðéT` fG¡É–%‘tVÂg1±0+/S€ù3\C´k«Øbp:Ûf´85Ü' ¹©Æ(öÞˆŽ³uZi#­„;4c´ &†–²Lèe" L=C-»°ÿ’%e:_POz=ÛñÑ$¬º!ˆ£ûˆð2ÁRqž=o¡^ƒo‹G‚³O:1fd…*Ü… >šÍMI<¨kÌ»-fÞÞãº( Ò`x·G»Æ- mŒa#Lî I丽yCÈ¥¹5Àatoö•sÇE›x0AxÃ6˜Fp9ÀÞ¸'ĸ„ƾw‹a²&.‡Ê=û) ºÑbä¸sjÌýi=Rôz/Êréû6J‡!h%ÛºE²ëBq ’§ÊÜàºÒÌnÀ|LåȼŠ.ö$êù§i!n—?(ҺͱÔDìräµ ~œôžE…Ÿ–FW]iìøäpÎéÚ–Æ/ê˜.>gÏXØü€Ï2À/Eòó· ie6ûyi¼l¢Ý‘aaÐ%Ÿ~¾ÏçµñHØg{`(Ư³ð‚Âß1?"v¹ñ²ŸÖË.—S®¦™-%1øã#éè¿ØYÞ?T<†45]IH8”îïUÞzSrôüûúõ«¼wP|S+K—äa¨1,²ˆ†b½4ü²þRfé£Ú¸ʯýÅ٠м… a­l'„‰F”Dh@?le Aÿìäm5õø¼~ý¦vÞaûú•P “±7°«u˜êš»aé¯(‚úë3Í@Í$¦]/þÁtcÞZ1)}ü” Ã[ ¿œ£®YèËLâ†xß‘]úÕ‚ª`‡‹™l´i¢tS.U:WIƒè •ÕßÏ‘üë^›#ÝÎU½N`C38údcñRJªÂ§ÌkrpÔhD÷ç\ Žàñ¬Žö)³ Y&‰ù8R„œMŠùið+ð˜!¶åWø$‰vŠ]Ø1ëˆ~œ¿\¯ìÓX-û4h#OrÎH‘˜Ú ·³‰Y®éw)aFÓ“:¸‘û¦mb<¹Ì3'Q8~1¶ùB à)űà'Ë·Ö± | ³9ö´×Ä´MÊŸÞ+ÃKT)?ãLÌ`âEäL=K,I™Ý F}Ã7t‘@» CãµâŠU9³#…‘­pX£„“Èë9û¤\=d¹x¡²@ZKÉŠg<î~Ž®î¯ãç5tðG VMFòIe9´©¼‹!æê­Ç"‡¤Zt¥óø¶ê`)Ñ@(îylN\æ76@ÁÅ<áqä’ßâ>kÌZQÚÀysóh=Õ0_ômÎÃü#È#)¬‰‘Yžy*¤˜ÄBŸÇ0½y¹´/3ñÊî#á®CaíÄefÑÀÊ*‡ÕA-žnÁq NNÍ3R CFÆv~ÖÌò¤.(D« ž´‰®­i\1ÎÃÖŠóF 1 Ó¼Q N¹xcyiÉéÖ$•š8PG¢Þ­?Á™ÒKLÇìLbVˉwô FÃéw¾³$-›ŠI¿šikÒ–ð—ÃS£Žñɉ¶@ql´6|ɘðJØùB¬1E‹ ˜ ÄX´E¼…į qªšŠç׆KþÖ•_2OißD@Âmì‡.}Z…À¢äõ$‰[W»Ç‰Ú`=MTMµCW׆÷sùO¤O«]j‰ÂIÕ&\DA¯|ŠÊ1E±Œ ^)ž2ÝoE)«3"WKöf… ÈõÈw6~œëF7¹°ñ/!ð>©ß9IÚäð3Ó.·¨·“c½ÊaÀQO÷?Ky/Õðà*±PøÚÊ…œ^S!åUEæÊ™x>ë î ¬&<·Î˜b‘ 5º-×$ŠØQÎ?‘XFŽ#gM¶Ü\5…|©oyÕÂH.d˜"묩´æš Í(ÉÚ¹>‘›Ä@Mz€ç¦£G*Ÿ±lý”ñ1ÁE4¯§)—Êd~+3I¾b,JǬ‰Åœº6¯çm­Bn#ÝJ!z;`pÕÀ¹7ˆÇ1ËègÌÞ<¿ÑvÃo¬ÁÁÕ1P–3žþ0q6Ù¬Ju€7&9(¦J¬IwØèF£ßÔ;§7æ2˜ õ°Á Ø;UGÀ’‘¿ûH ÷s"TÀÖ¾uyf‡2Þm­•’ TÓü°¨¨Zn]k—·a‚Ëd¿E‘k¶"8×-Wü4ãþ„YiXñú+Ú H¥¤¶ŒÞ_…‡ ”ÈïwzêÉ1ªÎÄ<ÁG– l[ ÛÔµî}–@é]åF–žA¶ÕoŒq&ÆC¡[ÞèÐ[9¥¾ìO<³7‰'dâHåà‚Êу£ZÃTº0R†™JnøÕš¿|¿PF+Tp$&JmÕÙUeVL1Å>>Nd@,=L[P•…‘wäšÔ-ä¹ÊKznkzËgªL' ¥‰’›씊ïAx-”Îî§qÜ`xíØ]ßõàÞ€X؈ª%— Ù›rqvø¬ÂîÆì|ì8òÚÞ½ +}Xÿe“JüÕ²î¦LÐôR5Açu,XJŽ÷÷9cOìBºk]ôr@Ʊ2¶¯qôþÓqY©Ï–ûµëæmªªç†®|ü;‡$–ütz™!–D‡Î%ósœ3´ñÀÑtª(…Y ¼Z*…{¤ï-™}Tu“ò}}ïçºV®â~ÇÈ5ÒøÓ½ow^®´îÆø)tõ+åá¾<üì¢ßM½ÿhg÷Ñ—«×¯®ŽvvX ;»ŸãÇýoÀG[ýaçÓG«oïúÆjô›FXúüÖ*£ÄDNT6¦Weú°P¹5ÓÙôÎCŒ=©JÜ÷M9@®Å—>wÊð¶¼ éA',Xt\¡œky<¾t²\…[^IÉ¢ß+kÆSéZN¥\RQN6›¦ƒ(ÑôJãÃÚóQiÜ«›çôõëZsÑ5yïm¹+åÒ55uºÝçºÃÊ\Œ5G_VNŽÃOó¯˜qãÕ“[_ªX õ\þ¶4¾©|8C?Gh‘Cl&óm=Ão‡]âQs‰¥& ÎÜ…£¬}+Þà¤Ó3N8Iº?áл4–À¸[ð ‘„I>±0ä…„€‰×Å?…P×$²¤<Ƽ„¤ÎΊº®øœD!$ Ô&rïö?ͬµC)Àê‹sPG½nNº¼ñ½ë 쎉Œ~ÓBçdÓÖ*ɬy'á4ÇÅ×¥ñ'wú[–‘ûIH5'¼N œK½–Ô.•ÊÝ^¼Ÿs˜Í͇h§·"Øu¶¶‰ r§"ÝI9©‘«L?ª4|2{ ˆ„ýƒ$Ñ#×SÁW…¼.¬š âç"´ÊUføˆ7ä&»ªòïë*H–Lœ9«Šþ¬…^"hÕžgÒœ‰Óoaƒ\Û—X”œ ªt£sN• 'bÌfW¢p|µ@Ò¹ÄlŽÇD/Y¥ÓãÓÁïSPc)í+¾ã·;ÿuðœXendstream endobj 344 0 obj 4509 endobj 348 0 obj <> stream xœÍ\Y“Åöóš1áÏL«ë®òƒ# ÌbaöjW‚ÕÎ"Ç¿wfYÕÙ3+iq8šé®®#+Ï/³ú»Í<‰ÍŒÿòßËggþ&”Ú<ýþlÞ¼ÿŸž}w&b“MþsùlóÎ96óxi s›ó¯ÎRbãäÆz= ¹9vöÏ­Ü™í´““sNmUü±w>LröÛw{¹}´Û‹ÉûÌö¯;¹ýËn¯&)¥µùN³‹wÞ‡;ÒNÒéí'xGkãäöo;%'!lØ~Üž|§&'¼²p{?cïÆ»íÛÐÉGpÇZeÔö3h®í¤•Ø~±Ó0?ãË\¼WÛsì͹ÄöØOó,¶ï¶«ïáÎYGçIž‚þ ÌQúH·y’Ú‡ÿ9ÒÚS"j+' d<¿Ò…I”P´Ñ^«0Y¿Ùk=I?‹Ôúèyû~<Áç8LYlÿ?/ðã-˜Òì§àí‰ÖO¶–Sîü»>x‰Í|wÛ=|•sl›îýܸ¨Ÿµ‹·õâu»Øÿ>v½=Ô _ŦYè8«tñëîQ#üPiÇâý÷ÚýGõây»øY½ø¨]ü¸ÁE"¤û?p“|έ‘´<¤¯Zylª2”§Ov¸ÛJ+ÜÛÌ/ÚC¤«oÚ×›n*¹ma-½z&—‘k”µÀ[{ ¬è‚KýKÌÙéYƒX”…„tÝÄý×ÎjÆÕ—ûqH¥¥ÛoQº@]øOç “ÌÎRk‡‹ž'c¥V¸jœ)|šæ¢m¹B瀖j 0_æÉºY‡€ ¡@Ç(%·?íÌÀë2Y#OÈÉh- ò„r~r0þ»µá{¸=^…?OÎHáu]o­Žª ¬¦ >†¯³ÖÉÊ®š'¥ñóó7ÿ™•ŠÓ'šÀ{¤á›2ÉÏxx>«ÇoÊ—›¦;"‰Q«9·¸og‹Æ~Õ/@»Þ¶'o[£å—u"øÔ@:`!)Zƒ\&ÃÅ%°,®á{ÜHcœ•±ÑWH,l° ŠHüÓN¢Š7iRÈï°Y:ÈȤvÇáÎU]YGMqJEiÎôé.–ÕaG^à6ß‹RúNR†RÛ#diYÈÒ[`‹"°¿ì¼›œÙy Wª£#K •Þþˆ†Ëy`Âvmà:w¡íâ—È"ó§«V&ÚÃjPM¦îæ¤`½Ÿ¬yYÁè¼.ü–v²Œ+­§ûå„%Ík·È °Hcª§Ò™ ¹šVQºhß` Ò4„…ɰu¢~¹J7¥Hê}¦õ^(Xõ,É3ó‚| IЂùI™T4pΗLò65ÐÆ¡lRQ·ÿ ÊråîU}‡,'é§'’Ôójš<)ë*€‡#‹|"OàÑTZë@!‘¯MDñé2©Jè•Q»+f”È>ÄyÂÕ¸« ÛÏAg‚qÑ>_ûü9O—cO¸,½Ü„¸OÖBZ‚à€A‚nŪä'j"‡G“)]?$V7(ÌÜCEYº2'HÓÇ•éH5@¿ÎtÊ x¼…«Ö³‹[×$‘ðãÃåŒÈA$ÄiÓ»iS+ÏDÁ@D©0Á'J$íêÅÜÑ.){# ŠôwÒvvÖ£¯­›DûÀhü¨¨‡«åÉïˆ{Ñ Nƒ}è ‡ƒ€´+j)ÚÿÂ6‡Ô}ØhœÂ @94«5·‰šíïKŸƒ°}KTö^Í*š1ޱY¾¿]¹8]E°BOw8rÒø’“î¼âΚ$ ¿eÞ¾4‹wÊ0D„µ¿¦Œ_Möey†¸ØäÆßHެ‰*ýØÎ^22Ô&yÛzªktræÈÖ&Òµ·6Øîª9tW+æ¡Ü«1h… ž/$ùã’uÊ:›Â¡Q&nÍÛ{o×ÈŒ&Žq¿­¼çµ0á¢9Þ¾´o{{ÙôœµÎRH(`9ÂUó×ÔŽ†pT!?(b}Q°Ñrûå¶Îˆ.4 Ê‘ T²r—ƒbèÝÖ´ÐÕ­8îpQåô宸¢”ºp•—‡Áäõh'Ç ýIf^Y®;œ6ì6׳¸k ± ±rèn謱JM$QÊ”DYÇ"Û¨Lzäò.FZHÔÒ SpÙªF°M¥ý/Øè©J˜¢ƒ‹ðP˜ª3Xà8"¡Ÿà}=<ÆÍ’:ºGT÷ˆ„ä+v"Ñ/tÔ¼n·Mµ™Íå»d$ˆl#ù R85›£é8gõþ¢¯àMCõuœ8š³oH=m&*TÆN)žè¦Í~Ü:®ò,q Œu£Œà¤AU"ç>$„¡˜í]ãŠîZd'Ûœzü Öþï8 7Äë’“I¬äõö棡£k>X“Cu-‰'WH¢55 ÌÆa²äø¢ýWýncJXp§—ÁÑE3Í8~îÃ;]Ù &ØBñA"´Œ"{Ï¡ ’¹÷#­ ¯JÖÄ$ ¹P«¶~_,ì$²å"lÀ¦7;éP:"KƒAQ2"Ú@oÀgsˆzèå‚“¾ªìȨ¬Û5ÄDEx\7ƒ¦ëa?™‰”7tfHž‰¦ÒOVûqí{&%BH$@,ÿÐ8”?NÉPÇqˆŸ³¯¡Lˆ^Û2´IŽÖ"²o$Cî„™-<["y+(Ò}•ÎÁi# }‘† ÞòžP …t¨±“2 jÖs@‚uGtN‡,8œ2:ºB÷’¥Ð) !Ð\ƒÕߢIaP§¢º¶²‰§#ž*4ô=N_.ùÂ,F'…Ø t±j¯rÎóîqà@¡d^WÂQ™iÑÅõ2BmêÂ$´ÀÉ%ÛˆÓ»CWБ"$JÚYØÒ*RT´l€¼Š!7SLù­Öï*vU²dX4&HF zõ4q8J¼´,EmeËrI¸¸|‘0¬…Ñë oô:ªøõ«Öù±É)¬A‘b9À­õÎÁôÙÙO¤ö=hT Ä4 .’°P0øÐ¡æmñ××E¥*ŠùûN *ë—ñŒ$!Âj ™§>ÛÙ&‡•È1õzþJ·üÕçxh  <('ìz¢ "-ržù6ç‰,D) ¤fe˜<>ßå‰öʺ)áŠ8”i0|öv`”NøyI4]3Ù«–ÑÚÇ„÷Œ¾p—Ü*OÓŒÙ|ÊZKRgW­e½{•gÓx]*N¸GؤSjO:åÉ<è8‡š¯»iÝ“$]©ušæ.µÉûá½vk¹4¡Ì”K{·Yü…ÄÏFÐÀm)ñXY{¢­‰Z®wco0jò‘±{B[%zÍÏ%A¨¶.šÝvqØ…J¥VÞ{ˆ£ÂélXŬ«íB”û\¶šê9^þ§ ³ÛD¹³#°žp3åWÒ8\wÆ]f=¯†“Åtlbdu‰zÔR´Ÿu.f˜×@ÇB’ã(Ùe;µUJÁžóø Rf¤z¾_ á#¡ˆóܽ—½(GjÒCç´dX?.·!ŸíP:„³…7!Á{óª+ñ3þå™ìz¬ÿ0øÄ=ƒJX[Ê2Äá*ðâÒ¹£Þ @ÆÜèQ§"3ïZïûÈc< "nZ=+tUä×] iðÀîËÎ*ã"îãrCº˜–1Ú \µäˆ)TŸú!‹l¬‘”§ §þHpÅÆÉÄI< ⿽*jX%\*•9)Y‹£9\hqðZŠß†W?kI€…Y:…ú¼×*…R’—k´9Ò>áôoFc¶”èÿ&Ho¦t –= (vFõ Æ¥·ŸÔ” ?&—Ë}š iýT•Dcº?Á~Â>i‹T|x~öéÙw¥bÝÙ ®Õä7RƒÅžýFYLã±,ðGg}´ùáù‹'g¾Øˆ³àÇ;Ÿ¼ ýi󛳇6Ÿ® öö½ J5Iè.š‹õ‚©`/̈ô°•ù=lVí¯êJ{»6@¨+¼ÐÏñr=©ÎåXµUBvà9à/X(Ò>€`AŠüÁ…é“ò`¢;oóuó—›ôbŽÆÙ˜«¶%;5j–˜„`XÒRíqè]ñÂ.ά”v,2Ñx¿2¡]S$S-œžF‹6 •KË`(…}Ò4¼–#F£]‘Ä;É\EÒq ù‚ ﺤɑ"bú‡Ü9[º)€‰7{Üôºø?ÂpÓÕö~\âbq#ª“Ê/qy¸šT¬™|‡õ~¨ôñ¤<—ªcÑg¬å¼®w÷­`°}>á Iia+²|N;'Eˆ‹zG\~UÌÉ‹‡•BA´g»R“úm™Yì€ ö ÕÞFôf¦œCœ!‚¨·m]¯q‹(Ús_bè¢ÏO"ö6@ã†U +@ 4*!ªÄ¿¿š†6Y ãh´•QÅRøŽä»ùyzm0âþõçéNΓuL)̽jùG‘´Èà±ë±K«A RÆóã΀ëheò– ƒ”-6 Ùr‚0ž,†‚p[¨•š'ŒY‹(cfNµ4§MÑ“3ƒ$¹¿,ÂÅCÝg…‡Í§&V¢Eñpo9 Ç«(|ÖÇüëOmâí‘… *ù8-Vfþb‹—º2ÝTÞ‘âè69qD¨gX= ‹þWu›Äla¦8Τîä7z˾P!Xï0Ézb;Žù7è.sYÁ—ðoL:ÿq2NSˆ¯ÁÆ$ÏIø|ÐGL­>ÑG ºýÚaV4èå• ÉÊÝ4‹—»ToJ)Ôé­,E Pdï/*§ˆ—ØC6¥rkáHÊ”Sê®Ó’Þ´,驯S&G„)•Œ¤ì”@Øà."f,ª|ïT&A€dß»ÎEdœ„E>/WGEã¡i(xHFP.g—öB«û>x™Oº ebG—? ŠÁä} 4ç Ÿ'¢bj{¸Ò jÄrÂ6𸠹”»Ê NßOà²÷jÊÜU”oq(+ê¯ÏŠX)$`¬ì„þ'Š nÕ/šÕ¹fL[@ØãÌ­{ÑKœd–¢—}Ì^âºZ,SÓìΆÕÖeÿcÐS+VJ½Ecå‹Ô]uâbݳ$ÓÖ¯âÜY1u\B<Œ©#XˆEÄvØò˜0]­‰£1ëÿLúðð‡›5ͪGHÎqn$¦5’S(><1V%ÆÐ~¡üý)¢,]³˜(L¹sŸ=Þ9_¸š)JïK Ú3¥¸%¶oî‘dFŒ¢bÕÁÚ*$îcjo ¾™ÁA¤RoCz9ȹIipµU§opÀ¥WrTÀ#IC‘>.‹gz„nYˆu[+’˜\ÏËá à"¶Š8Q§S'îH*.«÷Htã©]ãÔ{Êô€îËÀ¬îÛPÔB Qž¤½0¶Ëê/¬h}DJ2^3ÁÄÕ"½¾–âÙƒÓØÂ‡ŽË‡R×>åÚ›ô–ªYCª“~»›cè¦hq+s¹¢O´R±’h=æUÓP WÉTI'ƒ)éàÈhàØh=×µò]2²¨÷õJЉ”¤ä*Ean˜¡€‡ìe=³¾p2·žÌRò{ìO\jª•s¹K–v6z­}IW®Ò;"š¥v²xY¹4æ%Í E2ñúj®;D)±5s̃Eæ|+vwž Á½™Gz ‚k1ˆ%®G¬áGÀ«AZö}Êz£Û°ŸDÄá+Çæ® ÄæäÄÕƒ»‹¢€ s½Ò1 ‘ LS$iÉžT§ÁN¦ èóP²GŽ^d|‚ñ“L¥;d@Ëñn›²Ò‹Àh¥y‚—³†ÆLÖuÊŽœIKåti¤¹¾¦ay>bˆb<¢nMŒRÊ¡këKY^í`Ù2†6厴 •¿ƒ'%ÍK'(âË*ˆ¸,ØK}$ï‚tt"îX¢HÉΊœb/­&¸Ýà1® :Ò¤dÇ‘2ºv$SÿŠ .(áÞÁ’^#夥¯ z T†[ÁÚºãŽYH½–ï}è€àšÛXTŒjòNÕ#*Õ¯—mÉ&íŽÖ,ïï.¡+€Á^K4Æy¼«iaNK÷!MN?,qz‡FêíåbØäÔéÈ’gV\Ùl/DIu¡az{†ªâ¢§01H4'¾Ãº¸c[ò l…Y£î„.¸Á»”7ÂyÇ5ǬŠ{¬±Fu_F+Q½N\ÐrŽ‘L½0PÔ 77Y+êeÔݶ¸¼Ϥ2ûÁnôRXôa–- %¾ NÕ8dÂrMxbGv,2Ù™í]ŒYéô=µ(_%ûØNo3Üqf÷)ý QPBˆuK;¢bÖ2¾1ïÔ¬×àxqo_ÊÕŒì€å®$%ÂäŒ )­“X,áñ2½—9ûËŸ‰¨ãqïø"âʺ2f¬c~TW"© :H­ÏÊRá|…°óñöS'v_±°zyö=×U¯cmÝ+ R®BúíJw/;‘ók‹×M9µÜƒÁ”Ì‚¬Ø¶ucÌžu[ÖPjÅøµé­1õð`y…ð8œ½*e-s¡åœNMঀ^p¶îW’Ã1)ÃäƒøLĆTFo ˆ<ä“âY´n2Àwð> stream xœµ[iGÝÏ£ý-¯dWcºÈ«²²„÷`ŒYù„±ì‹¼Ã\Œ™‹9`°µÿ}#òŠÈª¬n@¶COV‘/"^D5¯¢• â¿»'[wžH­‡—[bñþn½Þ’~Ê"þ³{²¸¿í§9j1ÈÅöÁVØ@.zµ°Î´R-¶O¶ž5rÙ5bÙ=ßþ.q¢X2t°d{¦=X®tÛ÷à ›¯—²g†æÞR5?,W²5¦ëU³Ms†Qm\óF5ìÙ(8©…q¥†VI¾#L­Ô` _yo9¾éc|ä)úæ;8ùöÖ§tÂa8AÆÒx=°ê5=ÏköHéA~Ó¹æ8=oMÓЗpM1´(;Ÿ¨…jå(cWÇkœÓ¯A=½ÖlÛ ”]ÀµûÆànº€šyFƒ/à£kM§,[¿›?‘ÎPQYíª9X"´pmoeò´rz¾ÓT0tkÀ.ÐÔªÕôVP‡.‰Ý‰•à53‹AÒ«¿Vg»x!ýN—ªo;#4 Nûóe¼,L ‡´'–çÐ^J´Hp]ŒJë­¢m ¨¦UÒÓJ¢|Bu½Èg¿ FÅ"ÞÁ/âÕð4¼š¶0פx aUˆ¶ë¢O»±MÏc<°àylBŽŽƒ®Ôºy#s¢´.n9xcïæ94»›âÅ%„ËÅö7[Û·ž5:Ä~=Øöåñ]×j%™tg8hÛÁÙÙ1ÁG)‡¸×Þ²¯XŠŽ ¥^7+ÝvÎP›¶‚r† ò¾BÈäh¨Ì=z0:gÀA [AØÞ!TâdX(AÙ›¿×“¢ôìsoõ@÷½w vòÊXç}…›jˆEK«ds•@08ï!b਺pöNqÚ{ÿk<§—–,©˜c2§Ì¦8ÎO£sª^NÃspN¯°N½GÈA”aH¯†ZƒW´èܶ”=¹‚Õàá"„ƒ¨, ºÁOÓ j"ZÏõ†4¡“£˜¡÷vÀ# jøêÜQd>§ÈP96™Ë˜à¯Ú«kdþkÚ†œpœòT·1åÁ! §~= æ§z<:+Óý R‰ÉÂ~g ü*Ç¡…s²¨ì2(DRs6²1K¤`XN©QÚä1þ:§9á{J@dž,Ò‰}Ýù|üu¤ [PÝÚ$†¶€² æ@8ŠŒv©ÚŠÎç"„îœÆ!ífYlóYÞ™é`ÇGJL¯Ž¤Ë¹Q¦¾sÊmñð«k³ÂŒ€‹>ÜÞúqëõBëÖú²¦%•@§­[tƒ@Xlܼuçñ·‹«‹ëý­;?/äÖ¯ñÇýÀ?¿\ümëáãÅZ‚Hi[a𜶋eÈi‰^Æ1É¥>ä „X¸2‡Á½¡ ÑEŽšóÔ)BZŽ‚8æ­`K=ÌsQœ÷ wž¨oÈPË l¶Ú”jì;f,p ®%x¢& p’Ÿr‰ÆÄÌ¢ßD¢$ ÚÅ![͹t ¦Z6“spÉVèóg/WSÖ4?/?_q¤Q‡3 £2éfç‹1ÔœCA´4rÛ®–ñôy•k@±ífø?›>!#À…y)°z–nRÊôeI-”r¥G™y j¾?.b+1ѳ|`%“˜ÈaÇ{¢QFÞÃ0ËÃò¦÷Cð–]ë g3µvíp+ª—¶ªgÁ¸®cêÒ®cTZÌà®}Á$X†Â ^‹ó“SÈ\aš®Ê„&Ô°‘ö~ÁÁLtV’š¢¬Î*˜Muí¤°y–Ó-»ÙB£‹…†µXh<¥L³[+ÌØ½ó¯V#çbhC?Cfh{ŸÙúé³µc¦ÀöM“ÀC˜%bÒEÒY«Éy ] î¿ç‰´-%„¶ÎàÊ‚¡–(JgC(ZËàœh¥ÔcÊ•õRÔ;Õ4³Ë_`T°¸ä”YÈ 4ã½ylqoïN϶’dÑ5J¢Â☑*Pfµz`TëÕ0@‘ÚÃe w¤ÔìH†ùÒ©kñõÞïÊ4ñ,´?WQ7ãþˆ/"ôg™Fî1t¼ºø –Ž÷Pƒ¥útƒ^>Ê ÑSB8³îS†Õ š„“ „ÏJ^T÷Xg[׃žÞE>4C‡"¶Á ¾:Ù@™Òfjž'ÁFH‡Ôõ fÜZ,7åQYªYH ‰V!K5@Š)*ìäöFà*Ì÷ìbÁÁ Ên%ö«1£‹~¥¢‹8ÌÕº•PH°»ð”4ŽF€ìoO¦­ÐHN¶½ˆ]X¡Öx?ùÏhÌZ(@§Ñ¼(ƦçZ¹~|ì4 Õ>sî0‡‹mWSHª­×ÇÇØrÿ-0zJËî[ÃÌ„gÖjß´ ÄdùlÍKšQ %—‡õx²ê8—½a ©øcêdúÁ¸TÖ÷!#3a\h˜Þ‚8}I1H"u¬Ó/–Òæ¨Vв¬¿=y³/JØë“§!@'©ÛÌøã÷¸k…lÿçp¦”àŠ‰É;¤ƒ¤£sÚ)Š€ïUF´<•éÑRZ¦–"âx¼bÉ¢Ö6K»N—É÷þ•* Mé!8û:£í_Ó, Û[»¾xú@‚1+Ucß·FØRÃæ!÷O¦Á ³Æg(idÿ`€®FÞ½ EŒq¬ª>/ÓÄ™~gV·™óÐQµØbˆ`/œ!ïTºh2×À¥ŸWèsT?y {ɱ¦±îªÇ¬ ‘áF뀌ÎE<ÇÃÖ°±™ð†NÜ(YÑuŠÚ+ Ñ<¥§·.c°„×/¬5Zëðò£ž›¸! Lÿ˜JÞ÷3oMÊ÷TÜÔʧÔz5Ƈ0êñ Çï_Â÷¯ÓÐ\ëa* Á`¦\gï/L7øW\eOuüî ¯PóÚ™7µªÂÁÓ‰|­÷{Ü‚IÝL´§]!A›\òïTÅÍþ›ÑøÞKÿR~×_Àùi“+£¯ý“xœgë?Ãí­ç‘¯¦o0yóë­ïâB¸ä•&º÷^Pr²âEìÇ܃—+=†1Ö§úž¿¶$¥WÙ¦å¢A®}q—rÑ„T'tïyª¾¥¼½ô‘’³g0QšÜ¨DêøÂ{=Lò´½qf"H‡¦›˜¼…`«ß»·Vkm¦»tº$l¥ºçoøUL;é›Þ[ø“ ’ÌôèR~›” ØižHl) Óuµ·zg¹ ç_^ÌUÜéksE>]wöÛ43—¬§›’ÁÝy¬¨ø†LT(”‚©›ü8Ä_…®˜o#¾+Ï@|ÕçUˆ’‚Ÿòt,=‘$…¾^Ãf.¶»¼U5®ÀÆ 05wð÷[°‘@ÐBqV£0t(^çÁk<ʃ4¸Ÿ÷‚p/òÀ»tˆa³ÞÔ–²ýp‘ Í‘óÚó³âø8‡8ä!ú¶ˆ3¢ßé†ÛÀÃîæMúOø¨Cñ+Ó™1"žF‰Óýoj6»$C³­Tžz›pxZB='µAZ^úôøvòFÉâÔ =¯:Ù%7Å4ŠÒFw Ûã«?|ÃÉÔ Áa\Va°@@uó  ªšçJ˜ÿð5g’OL” v$—3€þǯ";ˆF ¨j4¢ÀsRK‡Óâz¶è’vÒd:¯êf=J. ºo«~¿G.¼OêyQfÖ9T!ÖXB7¤W+*R%+ñâmd¼`pïu1#ìT&œËÌO<ˆ.8ЃsE]ädw%’Dþñü\zx^ÆÐq•MïÙÙ[Îâ>{‰"Åäy²þ&¬5s^SÄ%WYš¹©ð¿—ŸIÏ¿¬Áéad›§(ÇÛtü›õäèº\Cà¬ßŽZ<^û7ٳθ~b+1ùk¥òò¥p·ä|:¬n—£|}\¸Îì­ #À|h\ oÿ¦¾£ÁG5#vñfþ’¨íÉpðGÌt£’» á«äâûµÁ"}a¹)W¯¶mo§A_˸ð­ŸU®ÚÑÃ}ïx;A£Œ.EƒäᇉÌÁeµ§ñIͯãA/ëdmÔÃ|Z£¨w”Á|œŸþ^(AÖ™Ò›¸p“·O ±‚E¼ogó£øÒÛšõŠ“édÿ¸¶¨Úð*ˆ_ºÝ\ã>}<§C /`G%´Ë¥ö鯃 G_ W¸ætc³ÓïQé“§Œ–TBWjW¦ÑQ_ ,OóÃ5_„ióÇ*sxFƒ2 Ÿ¦\8/ þFk>σŸÓ ¹Îä=AI ë÷O=Ü ÷ÏÓâï_ >†B1EˆõŠ8ªÁõ=ET „÷èMQÿšÚR¹Ñ5øêAQ]…”‰U|žUMy—Ëêÿ'Ô[ÿ͉»äendstream endobj 354 0 obj 4166 endobj 358 0 obj <> stream xœVmOÛ0þÞ_‘O“ƒã—Äq„öa“ÓÄÄÆ"mRA¨+Z )ðaÿ}wŽã—ư©Šëûîž;ç!c”g ö¾šìŸr)³ëÍ„eGð\O&ܨdöo¾Ê>µ¨¦¢ kxÖ.&½žÕ"Sº¤\díj2%"¯Í­ëZe^ŠZ7T0Mó‚Ó²¬jA~å‚|„çk.©R¥ªÈ7/<Πʲ´T¡ä4—‚r®rb*„PŠšk©@\0ªuSé:°.+yÞ~1ŽêаH™'ÚK88‡³ÂÓkJ.CÍ¢”à¡Ê É`§¦éWÜÁÈËaF㜬œÀ¨<â°É‹²©i'ûj+Ÿáð›Øàë†Ã9®Ö Òd/^Ý«ƒ ÖÊêÁ+n8õ w๛€uÁh}š-9ÌU°åÖZ9ð·½/,g Ìk²và7b”ñ’ÜûE·‘8-¥YF>õf+Œð€®»œ©·ÑdØ(”†gÀ#0NÅc*Ԍݷ zïûº5¨è¾n[Ç<ųuê C™ùþÕÉÆ¾Œ»iá¼|½ÙºüüOùw.è÷.MS¾K l±^¯Ï•·0ìòížÙåX(¯m*ÓFf)p›Šsœ<ÎD5¾”ý:&Ôk—Á<ŸÜíXÞ„×Î]TÛ°ønß¹c1¯ë5…/¡¸ÅPø«ˆ-‰²ÝD .­eV7ø4zå¶ûp—”²Ñý1; Aî"ÃÍÿXña;ù¿¿-m_endstream endobj 359 0 obj 906 endobj 363 0 obj <> stream xœUP;O1 Þó+2ÆÃ™ØI.öØ¢R@ˆGÉ‚S:Tü 縇¬ÈÒçïáøâ#’½æ~<»«¥äOß.ú½½“»8š(~ndz߶‰&¡F%߾ܯùÊ~”ŒÄ¾Ý{ (¡|´û.‘øO¢Å$íÓh×0$¬U•Â-ªJÖ°Ï0æ\*‡öÇÙý¢)K8šÌ³§4œY‘iíh”ˆ¢¬9¯•и6½ë#QŠ5> stream xœÍ[Y“Ç~_á¿0oê±™VÝ? Y¶dËøZ=8„#´°°ì%nüëYgVuõì,à°!z»««²²¾¼³Þ°™oþMÿ?¾8úòï\ÊÍÙ«#¶ùüœý|ÄÃMúïñÅæ«ã0Lm›fsüô(NÀ7Vl´•›ã‹£§¯·;6k£¬3Ó³íNÌBÀäÓÉ–ÍÞ0Ãütîz1½ÞòÙ ¯üôd ÷¤Ö|z¹ÝIkf7IœÉIk…ù×ñóêj¶Îr\]ëYIï6ÇßÿêÇé>¾§gÉäô{XLjÁÅô]X‹ë¦ãíŽÏÎZ)¦àP¸ïùôW¼+Óf³Ni5=Ç÷¸õvºÀÆ;f€Fà™”^K:6Óæ€Y³g>Òægn˜È´ÁÚèæ@ðèVÊkXDÌš^Ácok/ù¬µ³ –S0PH5=W\ Ãä으¾|µÕÓåvg”mÉÄo·2\ñ4Nñ ÇzXLá샀£zTÉ‚½©YJÃT¨¾þiuÀy+K73®–ë ÑiÇü¹%„´ÞôSâÈw0RðÙz6“WÐy»V6l{‚T‹Y[‘¹e J~ß²Ü%âruä›Å¦ñ¥'¸>N›©QÌÃ( °’Hº±+Àü‘ùhWVžÂïl’ ˆÈñ)HÆùrç„þy»3ÊÌ‚›é” ï@*Èóø’Ò.“j¹)ÀQ8F€€%^ 8ÜaB$ÁÀOãÑÃŒt¾¸ã¸k€²®÷pnH&jXêª"¨Þ|V$guZïÂ[Ãt†6̾ƒ×%0Ì!ãv‰s;.aû(ãÈÀ´THŸ1Ö(ÍË­^h• 4ÖÄõ>¡‘*œì A² c„ o–ñåìð.‘r¦;ǧ•μS <ˆ(áŠtPŸN®#wl įòûÏוÛp)Q`™D¤¿Føˆ™y?ý§B€ ªKß©óUñ©è½‹{v3BÙBË)ÝÓì{-à{ždFƒ²Ì<ª´×‰NÓÞAÛ•º¬÷V˜Xû¼AŒbôB)ï›*]¼õõ:y‚X~-3KØ 'ë1ÃoÕ䤄qE“páF9uZ…ãIo.’,Ñ\GÂëð«LÃÒ|ˆÒ„0„5!y¿¨¥ÙóoR±f@×&˜{X­S©8T‹Lƒ Z§ñ­F½FrÒb™{9ó HÌ5ÀQÎ8˜)/2%2Ú%È2˜j*&„3m‚IôÌ—r¬ÆÓIGîSî%ÖÂt&¢ö¢'ˆÕëúErhnZŒ#¤AÛÇᾇ ? ~¾ ÎŠ•®Tχ“8=cvl˜OªD 5„'õ@QðNó>|?ˆNöï½,Š4™ÊŠ£í¸¹oòx+-xrÖPFJQÎѧBÎLí@~“˜.ÏŽëQ†Qk€Ÿë½ÊÐÒ²>,DZZãÔ¨Nªuˆ†ª^AÒG­æH§˜ÝΪ3ÒZ9ªÌPÃ$c–÷ZXUœôÍ Z•cb6^.¾Ò8Œ¸Q×ë”NîÞ)™*m€«…)7jÚv^Á®ÈO‰‡b=Æy…mX°W1`ÁÕè¨^?^uì.dº52ñ°8†Å÷ütyÄ-hK a=<€Àïùíäò¹\p_ |oôbºJC‘$XƒXÖfEð¡F!A"ƒvA»g3èâ"MÜRAQð${ ~"<;o°öpyQ>„Cµ‡kœDm€ww|q†41Ù+¥õù@‰“Ç)ÞÉf6é'ˆCª~:Ù.b%eƒÝ’Rõê‹FkE]: € -¹÷Mh£ŒCìu6NÍ2uÓ¥v!Ò®¼ï‹èʯåygNfúiL\àÒÝŒE`‹ë"­CͺâñeÎ&]ôm‰+ã•C/;Onʯq ƒðwðDD™u,Xìt^ÔeãS…Mƒ#ýp*w+‰q)kü8Œ}¸-ïÜMæ!¾‚‡hL•E¢Ø&-¡j<É’%X:üYIÞ©w‰."…36À†o·¢ÙBH!ª‰-¨þ•=P¯¨BJ$D;wÚÚájxŸQ_>Ðrú)FÈYÁcàÂ(WÓ)Y2är<¢nÓƒ~€ßЇ 8- ; $9Ÿ«‹õ­Zãñú8¤®¿`ƒ<&—5 §š¬ÐˆÉÐïBš$ûíNçébƽ´‡Zï‚z‚£æNRœšm¿›–\‹¦ÏãpÅlðyZû}!'îÏomñÈ9ÉAµvY߇´ è˜ph%i’†ÒR‘ºÈ’Dw2 ÃÂ0 ÂÖd—"¸è"NCƒÞ@„~â@kw¯+â ÞÇ“œÛQdDÔ4jW${J~„a&#}°ìMgLò e³e…€cŸÈZ!QNBLÄy3{òG0!W‰%j—éHrÄß#u uq-+©| ޼\±Ö5ÞR‘]MŒ u(Ø8¥Óü7¸bŠDrT]—µÐÙdÀœe4FT6qà—‰¾tÖãr™èËhlY<îÁHÇa·:˜‚|¡³Þ¹¡) ô½ÀÍp  =Šèû±C}·ùC;¬#ù ®æ€©ã¯~PÄ-_M>Ë2zŠ!‡ ´¨ƒ9Pr%'q3Cà8{ìC®§lhôxiòq”Ù,¬Ú¢¦w™¥ûD(‡¬ó>ÙÞ‘!š˜«G#Y/¤Æð,ò®•އ/Û$ ެ]Pud0IshW­©%zCÀ–Q 6nx¡-ÏŒe0>l63'àÌeãÓÏC0ˆKÁãQ\¦ „¡Ë ^Æx¨w2ònF¹QNl‘¦M9Åe¶UxÔÄjœJXËÌÄžÅÍ£’äI8ôìŠp˜º§¥dáu´jf‚$1±:-}‘tñü+øˆ|5!G^]}é’,zr)pÂ×-$õ‡ !ÖJhCЉ‹m¥lÝEùhrm`TÑ«ÿè‚sVõ}ý­²¥y«ÞZ©>„‰r>Öeë )K€RÉ3ÂMKëB,¼‘+>©tý!½Šeþaè¾ œGi1à^>Hè‘zΆ|_\„ùýÏ)X ÌÎ2f&¡ 7þ†Îêð¢ÁYoÃf" W‘SŒËcwÉ0xébzå‚×<ˆB27[ëÒe¹P]ÜltRI”°H g+A<«VâÐ Ù´bâñ¬`7yëU¬ˆÛw^ÑóÖ"ìñi܉]57¥kꌹ©I|–tåÞØ"¹¬ñžø„UVF¶s­Æw›u“áFgwÈÙ‹-ðÌ \fåó9¢¤§r&ýtn"hRrƒSîµišóÀ–‡#½1¯& †b)jZÔ­š^_ø:À+AdZ Ø\¯.³½«=P ,Êk -øMfªñœRYd W;JÚÐÓóJþê2ƒr@a¿91½P†¢žR“A¢9L£?!•·ßÚÿC²ä¡¬Nìm…xN¼ Ë0Šo°Êãtz´Ÿ5š!¤´Æ-ô&µŸ"æÛe4kJÓK€ÕäAõŒ[×€ÖR²Ê”Uû‡ß³ˆåõ?Á/[²Ê"T·ë˜÷7D¾c†v<^µ ^u^ÚʱËAj$«ŽF¦+¤e†¬¦ÞÓi,€(%_éïhlwͱ4^y—‹! òä^–™Ø™)-£™`ú4±}Í‘O¿Üêa'^b!*±“„u¹Rh ÉÀ¥æ ?}SSäŸGš‚KâºÛ†:¤)ÞÁƒb jTt:0£‹\ðÁ¨ê*ŒÑÝü`w#x‰ùJ†Óþ4K7QÒW—i^Ð7w³4-2%ÿ[„ù:UÌ1hÌg}xi£K˜#§µè%J%Ó¡SCÈÙ”,ù(E‡¤Z¿®âöÀŒ x%ØŒð=Þ:UûšVš£@ëÿ.°…A‰¢œ¿*¾Ì»Ï¥6H¡º‚ ¤õnËV–)x<Ì–ÔP0¶‡ì!ìgµÖµ8”°á¡ÄŠRÑ¥^æ¤ú,Š–õöE/"ÍB„h_Þªw‰$ãøÄ» øÔ‚É[áó«-®Éõ¸×pP3D "äÿ¨É͇j8ÑÇ •úå:´Œðÿ#´ŽRÓûOÕžP­;ò é~¿®V|T¿Ytº—šŽ±¼snvÊS‘]bÚyë-5àÁÎ),I¡P;W´ØÐÐ/]שÓŽ‘>„Ãz?ú¢;¼(oцR]òAàL‚Ô‡’ZÕ@&n§‰4Ìï?ºùä¦~’XìSxhdÚvHFç4ªB?“~qê¤ZE+5™ ©¥6»‹7  ›ŸT©áݲ ºiW>ÙW²m\ü…¨¿óeb§™m»Ì’öË<^ŠBɇA)¥çøàÛvãl}uÓŸvݦ⪠”þï¶+0ö]÷#Iþ {þ³£ª=uçÒ¯2îgD­„/|¯ÇH³~{;ã_E€–tú}”7;òÕ:gèEÓ±åШ‹\Ð2 ÿ¿$5®X#½©Fõn‹´¸È.&Œq¡ì9rCt(äp©Ju€î¢e6!úrV£‚°÷ð3õ£b¢‘ä™Hjú²1©sÛ x6ò]ÜDß1ªZŸýl ”ÎÃ9ñ&¸Ï© zW¾1ªCN^tj,Ìݲï~œc"²‘qË©?%×dtÍôMEyµŸ«u±ip¯<‘0ª6r4lIÌ•O@L_/&E®¸ÒB`KÞ_ѯC:u#p£RÞEV‹Œ.:$´ë]®|eF¾ðBUry ,å² 4Ap»ÌÞŸ`zi9ýÿy€ÿ`?ùôçô@3 àoápé ·ø½¹@ІÄ0$”Âpóeþa¥ éLI"P‘.ºñÍËz$¶!^•ç¯ëó—åæózó²Ü<+7C+ÈXê ÛÃÈbú¾üÓp€ìVÜ`¢OÛIº‰dÞ…êßq¹ù¬Ž|^n–µˆ-ç/(_óÈåæ»zóªÜ|YožæÝDÍŸŸÔç¸ó„sW¸QpáÀ(¿½p^n¾l|˜ÙŒïfJTaÂv43!ßý þþ]ÛÚendstream endobj 369 0 obj 4117 endobj 375 0 obj <> stream xœÅ\[Çq~'„ä/ì›Ï ´£™¾·?؉;P”DÜ2¢Yq%RµKŠ¢ÛÞUÕ·ªîžsÎjiD„ÀÙ¾V×å«KÏ›«uÙ®Vü“ÿ~ñý³>ß´¾zùöÙzõ/ðÿËgožmÔä*ÿõâû«ßÞP³–¸Æíêæ›gi€íÊ«+̲©«›ïŸý÷a;Úƒ9Úÿ¹ùWìVÞEŰX½nî å?¯õâ}ŒÛáwÇm‰1˜xøÍQþãx½-ÆX¯7Ô&¨Í>iO?‡§†=h˜lçJÅEmÐùZ«°¬›>üóÇöÎ~ýBÔzã£=Ç!ìb¬˜^¡íêWÇûý æŒúÉ´iÞ«$ÏuÞì5,Ôo1¦=çl«>¼:^ÃüÆD{øž†u±Æ¾;j… ÷ðÐÀkØÚáO8•RÊÁÓŸ¸UeíáöþÃñÚ,Z›¨wðsS°!}¸o#ßB£ï× –¼cc¾…)£‡Ö÷Þh®ýƒ¥9ut‹Ò‡¯pqH(GëŒÛ“¿kS¼Æ‡ëb€N?BðZÃâèaŒú`a+op‡8¼±p(¯äÙ>ðŸ/h™J6â×õküÇ2Âÿx$ºi¢ £ÀKl¢€'ÒLìÍ][x›0·Áã‹n°:ÉŸ°‰žs¬ïÃ9ÙJùX¸üþ¨€Ì<íÅ®‘&ù–†ŠÖÐtxr®PÕo©Š?•߈Àp@ùL„u+4ðu~x†£¾EµÖ;Õ˜Êåeã\u€¶˜ök6:ðCxª€%6Ãú¼jK.ݑׅ ×›&[U"Æ]jmí–÷¤|Y‰á ÑabåL+´¸†Z+­þKQÑ,j ¥H¿(åWêüªÒŸ‹ÑëÖ6ws+væ8—WÐQOH¹ˆ'Ãøt¶ŠÀåE ‰g éœøœË„¼à$& ¿wñÕj`lUU')ën‡6.xžEq!“"(° NW1ÈÄ×>º¢ÃàF¦€e ;: uT¡ªc"„Ìâ,>ûòPY“I#${Š7Ñh¿øZ¿<âtÛ²þø&|ØéúpÔ!ïoµºIêš•dü+ÎÊ!GÎX°0 B? C"cãÐ7™›·Í—=á1´=4¡’WH*ÁJBò!ž¨G˜$ÞÀê5èPÃÇyݧq. 5‚Ó0¦°¤µOeIhºhØ_>_|ÿk\à†& Io0HÛÜ}^>œ‚”J&“Œ½ ù¼¥£™e]=h" œMP„uVÚ,ü þÜ:KØ™ùU“¨ &«Ða [—]q¿ŠIo¨ŸÊ˜ÆÑšgj0«hÝv4=QÛOGkà†^šÞM[ *éKÌH&‹4#§@ÊCV0nB<jböŸ †|\¹'ñ­6ô–ú˜@É')î’­ì5[boåz›ÅÙ݇E«*“eŒ»%ªò‚‚=UèÈ2Qg•s­Áx!GùC[R 'mÃr‰b J»ðÎtb3µ§+„õ¯(œí™=@È ƒ:¤Y„"ª*ÝF@+'£\72À¢åsOåÓ6qì£C$]“tS$±¡„+Ó!i,ð,’Ù¢:>h¯ï'¯ïêë­2¹¤QÉ̤õIfÒŽÜô*KhÍ4ºÝñ”VGÞͧâVSòL»"ØÐAé{.pÏ)$òB™Ao¡ÿb´3ÌÖq—#`ñ/“Ú²@~M«õê%)C ,°Mº@'W"û©e·±Ñ¾€Žki"1S‡dq`Çåéÿ²—–#Áé< æ$N4îÈDòA±ŸÐc:«±Ÿ:AΨ&Ïz’w&.¤ÂF|RÐyù?¢ôh0®qÐ ‘sb¥±ÏË®ƒ+3vÎì¸Ê»=lƒúP;Áú*x:XÁ‡ ®ÞVŠr5ˆL´‚÷iö5ºŠjÁhÝÿ–1sO›pø¬ÿ –v6û«¬Œ6û(%¼GΟ§^ó· ܬƒ¦ðsÀ™(ß¹L…LRÄ’Ï û¸‹’HëTÁȃ”üSožcTèlVᾦ‚…ÞmKh˜[–¥¼O&Dâ—=Á8¡Uë=L¦¸…´Å6y2„†œIÖï]ó &`ÙÏ( £ö¥ž­G½çœ0Ó™0¬ßWÆÓñqMÖ˜²÷¥¡yX6€ÞÙEtdÏq:Šä>klÞšÑ'¿Mjô±e ëI6~ÈR(¢JÁž2ïF@‡F`øš1Uå>F¬]/6Û“Gd ž·d@wQ:¡ ý¶‰¶l–"ŒÄ(̃:F— „Õ¤„'UX°)ò„GUà<á®öú!¹±ˆÓ…8•N<®]r,³ñ¥cv#jÀa¹P¶î„žË€…AkŒ"\ê³Å2Æ—Âñuò‘=Ø"3Ï—.0¸v0Q£A¹à864rÔe~'°16mÁ_ãm˜o24qÔ?oDJMá?}øw$ Ø+Å=vj»bÄÈ[fâ‹ (Å9ô&mÓ\ÃY3'z×$„M•ymÉ:4Hm¶×»‚5Qj¹ Öoi†W-tÊôÁS²p\O¦tÖ“bWZ. DI(&“%LjvòÅ{Î œ¢x‹42¼?Õµ“¦ˆñO;¬1úcl@™«@2N†o¤2ä±¥‚CPZjÙí;cl¤ŽôgzlJOò}içOñ,NdÏz/bŠ¢Ÿ[iPµ¬ªƒòW£né²@ÓÆtRëÞæÈ|ð\ÿ!i1õÖsßÓþ‘ëýW­S âÙÃ${ÅÕ°ò²rC» PY‹ÉY5 XF$ð‹„=Fî¼í4u†ã31˜ Z`âkký¾m§2dê €ãzªq0ä\H€U±¤h H¦u ˆÖõ%%­s–r‡ûŒ´ÊnÎw·ìÌ”Â!Ìø›"Ìï>'ðÒ}bÍoS¥LÁe u$N6FŽÊ™à¡5I±ï ¢×¶§Ÿ U ûúšš%VS"*$ šš2$¾p’—Ù[N´“¦ä’€þĬ à‡B€è]³N¢ #ô&©VÙ»# –ûkàõTBh@í¶_¬šð³cªu_MOœVÉÐ(s™‚bKþü<èfÐÆ8æºÈ§E5¹LÚ”'œøÂYÃ÷…(ÍÁ¦&ë&üìS¨mcT²T*)>tŸ~L8 ËÓÂ`DŠñÌ\w še ¤š5ÃûLŒ˜v9YÕP5ÇùBrêsµ¦±?Ûò¹(lž0áªD„kJû]êð²Â¼^‡$ß6βI“hè’áÀ{ÑTòúé³›8UôSrã—³¦€D²øÎ†ÎK¾M..þ„džsÁ°K}6†¿SÝs ÊÁ4¥$ÉÖ%£:öë<ÚAwgK1¦]kû‰DmTùƒ‚7!ÿ/k+y PBe€þ«@ñí]e %v¹¢p³ç%¿ßåý+-Uù¥®HórO£«äãê 1(bʾ?ç²hg—Ñ„„KCÃ<ÐÀ8/³íLo²d®Hñ& ¡`­)q ™`G‰•ÑøìOJ+"1ŠÙsûqúMÍœ‚\9Q #F» Ø™K"Y“¦W[ŸrØeöŒ<ša”ѨÝÔ#Ôp–ɘ,Ü/ÌÏõÛuy‡q­VšäîjSEžsÌTo—²&ðt¯ÈR´'uÁCVî<÷ùPK±rw:¬wï³Ãz4UyqW¢”èž«y¾ †F+‚y÷MKδã:ZÖ.,ÄêË:*®ë¤Ø_B+÷ç2•ê†uÍ)xJWÑåªæYKJñmQ«6îaɧÅõë™LîK&*×úúh\Mä$ Hômœ‰þ¼#hÀÒÛ»%TkOCjô2 ××~ín,fT*.óåß×›œÝåOø‰^^ýo8×fË­É[Tyš]±d ¾@¿|¥PÀ_NDôå>hÜt?{_g7¼™'Ãe52Ai¸&–ÙI{Ðx¦Z÷K#ße¼¡_)r<Ï­ä²àí'á}X%a #5k8i]¹3´ŒT¤¦áÇ”' ƒ6;¡@Ükjò¥¬™â/ÆÓ†ÿr´ÅK˜RK`F›N„›@˜»TÚ£Œ”ª²y‡€AWíĪ1>ˆ¹Dc ëî–°Èzœv‡£+û03„®§wj©pbhÍÏ,Vi\¬6~N(˜zájQübäµ0¬^Sþ1ĄƗ?ä@XøŠNÎ_bI±cÚ&惦—XR|b¼½‹{²X äº{{õ”U¬bwŠ}»íbÍ Oæ mVâmg°ÜÖÏplAðs´©É¥¿ÇcC¤¤é'j%ß—Ê3@4ù4 ;í*¤Z,Îø‹cù81^Ú˜])“ŽyT8S–Òa+Ñs [ znŽâÛ¿®ióßÇÍIÇ Ò9ÑTmг{JàÓ˜¤L›Oü)6K´c ïiÏõh6­ §˜™éÖÎîUƒt¹Ðuh©)Èp"+tAÂ*ûÉçr9NŠîHDÕëP};‹˜}— ñÆJÏžTQ¼Üs–`Q?>ΔjRºÎZQaìEòÞ˜ÏÛ®™¿€p¸n*àòÝñütžò©ŠÿøÇÆÌ{²f꤈\€ñß?üRÙ7‚§³ÓcLý Jâ[ B±Çÿÿ$~¬Å‡E–ÿ ?6—¥Ç¸úU w÷u³¬¾½É…—²bóañþNe¢Å¦µ~"è6­õËïÚ§SR$”êéGR¹üª]éBèè+"¼¥$?¼¬°·K±s ƒß=ÚͶ2%+M.~Îi¸YÖ}q©Òa@y“ܨO54L¿Ê¯sýÄ䲱垸ò\‘ü];ÊñÖl_(šoÓâ{¯f]*°F[ˆñ3ºó©Ð<)_·‡ׇµ‡Õ‡ßÔ_ßÎzÛ.õáËöðíd ¢Oùyß~ÞŠþÝS´È¬›ë¡ýü©þœ+Ã#4“qP|ÕÇxË[Oêé±a^‘ÏÇqSÒ«ä ¿ÓÝJ)š—U}EäÁ‰$?›"8OT9ªÌ=§G§¾Ð45B¸W›èrþôžÔ^Å…pxö*‚ÛE«'ß;Ï9å×R[&ü©<Þaã_°a™|!õÉͳÿ„?¨}¡endstream endobj 376 0 obj 5175 endobj 380 0 obj <> stream xœí[[s\ÅÎó–ÄVò³{<÷KÞÀ¢ÂEK¨¤Y’%–d, C~}ºçÚsÎI¶…‹ÁÅj5מ3úaÍF¾fø/ý<<[=üŠK¹>¹\±õ'ðÿÉê‡CÖéÇáÙúÃ]¦Ö‚ƳÞ=]ÅøÚе¶r½;[};<ÚlÙ¨²Î §›­…€Å‡ƒ ½a†ùáEjõb¸ÚðÑ ¯üp¼6©5^n¶ÒšÑ WrÒZaþ¹ûKÞ]ÖYŽ»k=*éÝz÷éj÷޷Û-…bW`£Ni5\à¾Üx?œ„oV9Qxe€0øÎâ@ï.a¼Óš~}†ôrÇŒÎa å¸Q–2ùèŒ>‰c97ÃuÀŒ6išõv8ªÇðØáµž—þ:ò¼;ò2¬¯„¯làj”Êdƒ‘8…g6(`$³Š©aÜÈ‘q.üÀa.ìȈ‡Ã²Ö¨ác8Àgr؃½¬–LêaZQrØG²¤ 8@›†Ïa€±£Þ~„­\kÔÂ^ƘáAœ$¥‚įÀ-8!’"`ÿ+ O+Åujc eHa)—È a¹ÒùÔÐ8zæƒð%Ëþ`#`œNXõg O2€’EœBTÂ0L†›iÎM Px° ò–RŒÆj 8råˆ_\AyÆ\áà"H¹´Ùhí¬(häB`£”ÐlE±cì7Àê"Gk½ç üfvâÎsf£æ_N‘ù0Ï‘XîŒHtúj;š% Œ4=¨Óâ©PŠLÕð*ÈÌ!ÜŸ•þH¡Vg@1›ÆJJdìc£C#óo…À-4ô™CFm§¶\Â|&"ÃÎPÞÆ€¬XM`'¨ZNrI0¦Ö[áFŒ .÷ W¸YoƒU "–ÈD„݉ü=~Z†#hF¶)hJl»À??aFWñ·•°˜‘¨$޳2EüE'ˆÊ, "E:PæJ£ ¤X+HÎZºXæ Ö¦ ˆê›ô4‰Ó($s‹­PÙ a+Qâ‹ …ú ü§õ­!ØB0†`¢a¶tà1™ Æ ïncpíc8; BÒË¡QÀÊ‚¹%E-ôÞ‹m“Œ¹HEý‡ã¨¬ÿDÕó–õôõ ¢÷x &‘ñp(íPMèhdÓu5U'«ÖŸw, ò\ÔQ•ó¯àþ^mrVË:¸˜ÂxS¦Éé%+WHÖ ð­µGÕ?VÈœŸ×þÂÉ ÑÆ¸v𬢫E¥×¸¸~ÜÀ– ô7K]WEÌKi7Ó¯žÿmt ͋˒× 4BŒÐ >­Bm˜2£Ò²Ñ]©-øeü#TŒ¾_‡œ¿‰Ôý ®©*¡EUn„(/i+Š]X7 ×Ñ–‹H#øŠÖç=æ hûÇ¥xTwˆÉmaæÄo¥s ˆ£¯+N‹ŽÕD§ˆ¶eâe ,›ì÷jÙÞE™Hþ]ô‰xñº5aÒ‚—OÔþ17ýJœnõ«øÓ Ô¤GzÑÆLÈRoƒÚÜ]"(=ÇÀý'X÷:âÞGÕF³kt±ªÞkê-÷«²‘hv­…µÑ)À œ{ôδáu<ÉÈrÏoŠçb¿Rí¬Y¸X›’ýHÁ8Õ)  â 輻<èÆøþ`òSW½Å#d¹èþ1¢8ƒk‚¥èÚkiŽFu¢ÁĨdœ”Û¨Oäd`ô;«ŠUÐ:¨+`ÇClð¢îqЮÖsdEM¯{jÑ.]NàGÐI:²e0ЈŽÁ´ðúñVV4‚Ѳ?"õÐeZѱÃ&â[ve`>‚ÚÇ[7'(ï\q0TÝ%}Ò©sõº˜ éYc“ÁÓ"F&w÷>˜ÏcŒK•¹¬Ú…}c¶ð¨O#4‹ãYêl®™õoõðzÆölþ“ ŸëÔf”¶YÜá’u…ŠsZe:ƒ d‚˜°Úå4/¹÷®ºfõ³ „*‰U—˜"²È'TXÅj]ÆEUÔ'U®ÙX裿 =5¡ë¤8$½Ý1\O1Ï›p@#\gŽg&õ†(‘YÕ²:rY¤á4®ë{ÙÒ$E¸”¦&M)­ÿéÄPÀ 0„uß ó…Æ¹ï)MïÃTaÐòt½ i$&›4o´'„iÎÒd™$[Å2aÆ ú(‰ÊT+Öªt>žéy ȤT·úš_&‚K¿Û 38hˆ¦Å’ÓNÙå<;†/‘LÒœÄÉ6 »ƒÓÁÀËKI~àIkõsA1t}ÄÄÂãQ…{}• t™Ft L‡Ó8¥œnB…ᜯjâÝQ¨Ó²ñm‘Û-8”ÉãÝêËÕkÈâM¸,‚݌֑ÖÂïS¯ >Ü[=Üûl}õòúxõð›5_=ü3~|øÅ#ø±÷Ñúw«Ç{ë/o¸˜hŠDùb«`÷Â>¸M¸Ÿè AHE„°L7–:Å» [jàfC÷جֆóQê7ŒƒÙ»8 økxsÂ;ãš–=¢8ÄïcŠCü69ÊRè ˜Vã^ŠHÙ CW†:ô‰1m‚èÑõÛ¥¿1„ÞšÛ»F¡äÌ+­4'µÉ…Ê(±Ÿ¡Lc¦ ÉŸgõœJãDeÚRœZÚ1|{vÑš6ñNç‹.Ì4=Ù4…§n‘.´˜Ê•ÌnÛøèÆdœæÇ2p޳L·ÅD @̤d{1íƒiK s{>íE{J¯«5¸× ÅD+I ÿ/êäjê;Eÿ6DªB`¹T÷lhcŸù[,­Ü4˜ÀøbrO“_¬Ø©"ÌuÓ »Ð-}½S€uF£Ûë[óŠÎJݶ…¼Þð¾¥²å¢é$.»C”J%¯·rN¶crìcT5Î¥Ñ^^w~Ô}˜!ƒÈfᙤd7p§@-—hí+ƒŠj²,!´ûT«}sá0gê¿«_$&5oº@¤%ž1Ó×õ-Òù}P{¦kîÛß6³y9APPÍ9ybGm|),u7éW´QUIpSLMþd¡ˆ•ÈšDG)„’|²jÏVwS×Λ&|¤¦¯¦–”ƒ˜™ü‚¬MÂ<ôR×Ô!ÅÄ_åN®ƒ+v”vÈ7({™HÞ$6qÆì¡Þ6íݾÕÃä2dU äÕÞ º5?2f‡O7ñÅ^íI¯ô¼ð,/¼×{?L‰ïù.Ò’šû̉4*=ý{UV ¯Á=¤ˆñæ'6â  Û”ÆçuäóÒxQKãAm¬ ŸÑÕs÷ :A|óÂÉtBRÝýe¯ñ°·Ñ1ƒ.Ö;Ý_èeâŸKãemüSnDᦷŽRdïɣˣ"©ú¨ò¼0݅¾ïŽ"}Œ+›ý  ½{ó!¤Êá³2ø1†M „ÆWä©‘UrEiÔU’Kã{©‘W>gÁO9Ï)[sÿyi<é à´‚÷¢4>­{ÂNZÆ[Ô§stu÷$„žÑ‘ì<´ãérÿÃò5È-[úøDýždö×Òñüø?0ý¾ÂÀˆh…D ¶Ìñpy;4þ…ò}oùª¯jc]‰h°Ô{moý+‘{Å£¢*™÷’ ƒ„¸2ÿºyÿqéß«+íJã~UçÓ!ÕÌõìúËLˆ¦¦ó ±ˆø«èÚ„„Áü]kÔß‹ïÓ8yK«G¿rY¾½E~YŸ;!þøºv˜ã#BGÄÏšSWŸŒ¢ oJ±ˆ€m×&–÷©ÏŸg×?ªOÜõL«ü­@¢†K$;ë~=îŠù*¯%[ „@٘іúÞ³Ìá3Ô€’Öló­{Êãbó¿*@ ±õ'H™eÿS.àQéÿ¸®´Wwµq¿ç,>¯9îaèeƒ1ÒšÍF9—..V¼ê¤o8»Ñ‡lÓì_Ä‚ì'C‘üÉ®ø“ý ùÛÆeé¿¢²ì¹‹ë9z¸êbä§Š‘dG,ýC‡7sF‰»7šëb>&˜Œ»²à«Œ—6Õ¬ù uÇ÷¶a~HÈÍs/«» s`Ͷp™Çzçíñz‰}†èyŠëg=êÚ˜#c¨ÚÓm¯p‡$žLš¸IÿDæ¸K(pž´ƒÀŸ+žZ_Ú±~GeìŸ4 ޝ®X²Ø%¾ÑS×Çh_®þ  f3endstream endobj 381 0 obj 3702 endobj 385 0 obj <> stream xœí[ës7ÿî¿Â3ýÀ™Á—ÓãîtÌôC^д ¤‰Ó––N'0 Øæ¿¯^«•lÏÛ P†Áèö¤•´ûÛÕ®öøÐÍRÒÍÔûïéEgí€0ÖŽ:Y÷©ü;ì|èÝ¥kÿ9½èn t7!Ii•U¤;xÝ1 H·¤ÝBð”Ðîà¢óWBzyRôò¿?«!"ó‡PJSVÈQƒ3Ùs³×giYVI~ê‘´ª¯’õMö{}’rž—4`ŸmCe\$’J*ɶL¸œ.•o(­RJ`¨éÄhJ/“犉œ»(’§=ÉŽT†G– É"+ô¤{òMQ†ÅKTŒ‘äY¦Y–Ë žJ^\¤´$–Wž‘äȽöÆlõx*£V®ö³ÛëÓ ÆþëÃ^?—MÉÝÈæË¯OÕCÑí³Lí¢2r|/—”«Ÿ õóJò ™\O™œÛgfú •²Œd¬ßÈŽY¥;ž¸Ž§ÀÌtü¤GÀ6i% 7š*ÉgõJ©£bR‘0rßo;â×cÄMG”Œx%d[è%â%ö|ƒ…Xâ{$Žñm #3ÑûtÛ†÷WŽx…ÄKGü›h¤%«Å?cáCáJßL–ƒu|íäÉ»`‡Ð¼1MÎDr¬ šÞÒÎ@yÌ—Ì16/™7Å›©kª•J`©èöi)- p¸îðsêà4²?4P%=µ$æ)ldW(1tmá…Ð5xfàUjÔ¬¿³!ì·T›”Ó'1`ñæµÏz¢*=ñ<¢ ‘6ã+Î 2Q¤bžè°î¬TˆB!y‡IpÛ9ïÎWŒTSäÊ ŠwÛ¡¸ï ê–>îˆWi×`võG•صª¯c%-L{qüNìZrè`x‡S(¡SXoínõ½Ê±î²©Š–+£s»ä/iqø›«Dh V! wÚIp_¤üpˆñ»’ØüßJ9UU.î@“/ü¯]ÄÜ‚Y°šØ,ð¢÷^X€¯"¾¿¬¾á7ÎëVnúPæÛ)õ£OÀ¢R¶W­”°XïâC†Åz{¤‰¹5óíÔÔgifkÕšÙtšÙs“îšÑi“œQ=¬A=ÑX ïY®jÔÄ1]÷âeoFoÁKx euµxJÙÓ·Ü,TÑæ³7©§¶ˆÆt¶AlÕÚ»_d _º,hV+Q;]xyÓÙ°Ò%dd¨Ë½f]*ºë–.õã“ÈeŸ}^ö¡èíaßîSk&KøÔd*ÖXæ§&àP[}jb‰s|iânª÷¾ƒÀM>ò’jOŽUަ °.Ø2—X+ÌÜ¥•“šñ"6VÂ$³éD¾o_ZÝQñ’U¡D{?l¶÷Å|÷Q€ 'aH¦MÓ»üÏ¥(D˜tþv'rr »™ÔýgÝňô^%Ö*‹/¡¡1ªs¸^†ÛƒÎ¯òÏç· Ïendstream endobj 386 0 obj 2356 endobj 390 0 obj <> stream xœÍio¹ò{~ÅHïÃΠƷÝ| 9«Àò€´»<¡[ÊÁæåß¿*UîŒ'!»‚ˆžî²]®»ÊÇß#ÑÉ‘À¿ü»w¶òtGj=:ºZ£ðÿhåﻌòÏÞÙèù »u½èåhv¸’È‘W#L'Õhv¶òרL츛¨Î{¯Ç*~L}è;%Âxm2ÕRèñ»‰ïL¦¢ ¡·Áç÷^xáÆ“©ìŒ±^_C·ŒÒ8®oÁgÕº Ÿë8œ ¥Á8D¦ì‚÷Ь=àÕ:÷p©JX ŸSmÐ!»¾¦S½D¡—Âó¬ã㉆)¼Ö™ß÷H)æE¦>LJïÿÍ~‹Â µÔ€îNÜl„%A>~bSO-uÝs .¢=tÌBºÀÇiyДzüu(Â#aüÚ$æ]|\ç·Ò¿oññ™dAí쵘Úoõô3Šn)C~³6¢Þâc­„±„þ%icFAn;kC>  fò-3±V£.@,ÅÔnBVV[ÉøSË[¾_\’ø×ÅlN¬@Ç´•JŸ•ï•ÕóûÝz·e„·-_ÿÙ¤¶J# %œCï¶PŸ‚l0c%»Ò¾-¨³§Ìþ[¡îŠ]œCÀù¼7çTD‚®*ŒùÂŽýþý~YéNK@͵.FÕ5Ê}”ᢠb¶È&pNYðìNæÜ%½ìóôXo¤l{YtGÂÐuYFà‹RSYìµp^µôÅ%̰¨­ˆkT8óÀ/ zÎ+ûYÖy¿B?2Ù­Qž‹1v£Œé]¤8L¯mûç•E•Õy"|ØjöëVìz¨xy”Õ•€¶°ü|TÄZ¨,Žýµ•2Tü+jk ®9fI]2"ã-…ŠM•±”ºG•Ó†nSx<"­îQ8ä×gÃÂu¹UDC#9éAÕvýMrýíâæ´(IZ‰k½(O¿¯.ç黦u5›ÒoìW¼ýä4}@´^³ÉݰpöíŠaeG [©l…뚦ç>”å¹VºhÅšóy£ ¾ÂT­¬9„|x¼{p¬úaÉ{“ìá÷bi†åÞz÷3J‹}JÐ]©tSKÏÔw” ”­ž Tµ‘Îç Í@GÀÍå³ã: "rÄë–íI•‹¤êünõLðÑjþÁ4›+Áô-ì¦>ßÌeÁ”¼ ç¬éc5qF㨖s¯«í®³ÈØu®HSY]Ñý¤«âÐQi®0,ÚÎog– þMììúÍíÿ«‘b.ˆ¢]+ö˜°Ç¥9j?Ÿ„°!Èåw­ÆÒ”oΦþùÙTk6µüloÈw_—oó¦o[¤²[^ÎHÆÅ–·ô(dH¡îm}¯‰‚µ!Ó¯ŠÄ´àfX'm^T“ß9±Z‚ŽÈæ:ÑQòîèF¦¨…ý=›‘/ŠîÕaGd}•¤Ã‡"ï‰ÞßYÏ­ÅÑÍV+Šî0qH\„¸Èùë£uú󰣘U³ƒÇf$M§Sñ88—Ø.è>¤h&ªÞɆJ©¢£Ã/ؘd'µw&ÕMÚ(Óc¤`ÊhWÞ¥¥`pÖ[,P¥Ì¯AuJ‡xÜ­­Ð¥£Ãd¢;éCŸWÚH˜‰Z1£c½ '<Á6ÞØ4&§·ê,P”JAvòÊ;­EÊ€RãJã$ò&Œazâj ÇÓù>iz+ó”Î_á„•FÓ<š®U}Žœo*à ¯ô6.€ öö&€R)H\6î¹å>Üp@oŸS³1õЪŒÇ¼±Æ6Pôãéäu¼7à”lÍèM}yâ†ñ˜ÁF€iU¿òÔç°ëB\'¢èCuw!uT·>cZç‰K¢ÛÓJÆ>«¸Vª3VWw °Ï5]˜ØEþLÜÙà›Š“rS„‡àÁ¢ö[F •éí·\¾À±PK+͈qw¼¯‹¢M¡Øz`> stream xœÝ\Ys·~gTù |ÓlJ;Á=˜¼%¶"'¥È‰Ã¸Re»’+6)ҤΟîÆÕ˜Áì’å¸R.Û$h4º¿>é§}ÑË}ÿÄÿ_îýþ+©õþéížØÿžîý´'iÊ~üßñåþŸhš‡¡~£Ü?8Ù äþ ö7½Tû—{ßtre;¿²ßü—xÁ—(¥zí`ÕÁf~¶Zë~ÆQv_¬d?ŽÞŒÝWªûûj-{cì ºƒ2çiÕÆw_Á¨ìÐØ®‡/J½’ii˜¤U/¥º/‘ìí\÷läähˆÞ áhÓ¿Áç¤.?üiùQkÙ½X©^ <ZÆ÷j‘–²ûWþÌÖ|¾2½÷Z©Ä9žçùj­&„ùç®Ö~êQ~µÈ×Q€k-ðcãQXd­ìÞ„Íh»×«µQ¶—p¼s`oݽ‚1mpnw r{¹ÂŸAtø!­+ƒ70»×Ú ÓÂì øO®‡îÏxòÁYâGXTå¥Ðx ÚÇu á‹ÄEÙáIÊÞÓçAÜ 5°PûøAiÓ]Ñ5À|Øã5ðàý 5-¨Žh¬”Ýå Ĥåà¸X2e}^{Ýd8q½… H_fžpïÍTxø…gP|6Á‚4p6çIxY¦…ó@K›Œ¥,KB³¾û¶«„˜­Á90Ã)1‚ÔH”°A÷#B^G—öB_­´Gøšî]P¡’&CE®ó¦ºûOÞ%œðÿžŒZ1–Ïl/ÆØy¦Kséã;8Õ=Îs¾]eºOÒ Šh2ZK D… ¢*Pb„Ñ:â‡Á3E80Ú¦,MmÙz’`äƒò×Ú à<`øL¾ M:=ø^ó]ΚĮ*Ôœ- ˆ©±²PûÂêµv#áhÙJ‘8¸W ¬(ͽñ„õ@h䆯´ØàS1»ŽŸ˜e ¯Q8èã`ŒK%ëȇŽBw“HҠ߸žò¯ôHWø1qñ8æ`¸ƒÁFÍÑ{ÆíǦƒ#|‹nPÂÀ¿F±Êei †YC,–TÆj3/?} ”£VÁ(‚tÈ.ìèƒÏkÎÈõh" œÑÖFb”÷).˜Q¥c;AE‚æ@g_¢^œœ!Jöê@,É›ÀÝô!™òº·Á³(7 ²“O‘˜ï¶ r#T±µ¸ïJ¯Fº^H75ý ÃHFâñ¥DÃ-Áˆá>D5U: 'Hî$¯…ÿz6ÇcZ¹  †m’‰\q%ŽÉäkÀ2r ‘LM‹[¿à,èL`B0J: ó£ÚbBïºÍI\8qöñLµÃ\P–"þ‡ˆ <*ðnz·8ô¨`¹˜9£oÒDL9¿K¿<Æ8 Bn§}E¯h„',-¹ýdv5 )u[2€Qˆ:À )R-‚‡ö²  fy;K—pº2Nš»%'‚9©ÜÍÑ‚mŬ’à ìE3‹Ö0uè²OÐ…ðܧ‡{a $”óìê0f¡ª`ÉRËgŸEéCn+€Z•¿„DZêúþ7Á›@jÉ|"¨GŸ@MF´rZÃRD"©þ2ð•Sà‡¢ðÎ6ßC˜ÊÀg…Ê×uÝ‚eLÿ'Šß¥Ãw¶X,Ú¦ãð}É ,†~à1?# ](0ä2ã>ÛC¬ Od„è×™A6ø"²dŠÉëqª²fÙ=ŠÆ*b©Yq<Ê^h&ã`àÊ.uÏ©e€­Ä$¯‚pYœåÁÔþï¢v4ƒR%WõÓÀ¸q2‡€î ]véÈpíÒYú„¡¾&ˆ²\ÄSÄ–z#T6šäϘ,ux·Âö€²–s€ÎaSœ>sõÑX{˜üš˜°Z÷3;K®µrˆ”Ú¡WY§Tí£o‘!·;ïM?7,·ÌKY§q»ª†We&ëÅ„â~pCêSHðm°F‰xüØc1˜m›¶Çý˜Ó¹)Zn (+¡¶¥Ë%Há(óÍ•ÿ†¹cüÎÓw’üŒÊVî~²_¬Š®›û3Çœ=Á$^0G0N‡«3[‚–ø£5˜oIŒ£²U˜\+'z1޵Ù*£ž3§€FÀŠÐÃR¦ Ü'ˆu£\)ôÈ—Ÿ•% 8%'Ÿ• ÛšAèñ ¼T™«­{X³ͬS…À ( h‚äèn¥ž¡s)ëÉ„³ÎŽãÇ9,R#Aö…íØÊ:x†„`P£g…ë¦.UsH™àK&m†¬8Ô½Õ”7MNHækùЛ!òhV»ó˜”5Uõ* O/[Q"¿ÄÚBdbíÏuÕ®Èð]¸wëôÎÒ‡€`Þ~üÁ»b™%6HŠMÀ]¡àÁ˜ÝÆr]SÌÊþ˜¡t¢vÊa¬Ð7é„Y«²Ú’<‡SÝL©b†b3mÀp¡í¤M„‘ Âýè÷r¼‡¼á-‹·0‘ž,šãزÚMË­a"ÌAWH±jáKJÜŸ6”³\Uà>k@ õ I¦`Í¢´(…ÅáV†áö´Hioà\xþŸi]q‹=ÂñÑ Àà<ïcnsÆ»7 ³(.à{d­¶´è#¡œ0‘±(Ï` cBÓ\öjåÏWxEfcÃ"/ÈžñŒ*!P+‚XĬMj5hÊý`Ø ¡ø‰D–jlórNK°R!“fJrµ²¼œŽY*æqW¡Yó¿‹t°°òA%éúªîœÔqÊjº¡¨Ú<íA-oÅ›5³k ô¥c%+_Ìö¨«H(l*帽V'1º|Ÿ•ê®P ËM0[åÎt陖ᙕC$>÷¢òºÉ•V¹m¡È (ü‘«HÅÎ|ÜÈãJ˜¸.Ziª ç™ü«èµ¥­ ¨ ´’y¯³)„ŒÁ) .nÜÛzÃ’çu¸JÇn`[oàŸ¹Þª¢9jaKn¬­¢¶¬-pJÑÆ:lß»¾CY`Áœ&Kf&øk©Á—ºõqr—±MLÄ«‹Ô-h$I6­33€´îWÎ vã‡ìØÚMò´(šÅèF¾7 ·nŽ·^Y©v4+–ë¹f>¥–¾ø­8€ð5’˜[,GÒ9f7Ù‰¤u¬ŽŸ´gsϵàù¬“Lê2%y¿¡«jŽ„ýd ’å<Ô5Ö>£ýzG_ÊlêÛ°‚íZç¿XÞ›`Å[0;}ã€=z×íY¤ÊÁläHÞ·*/¦ÕNZØ,\f~r’¶žu4 QQÂä gúòš×õá.~_C³6› Ù±_Õà®ä6=Ñ ›é-ÏûÕåmUƒ„»¥&·Óth¿Òž¥à‚óo HµL¬QòK Sl$¶](ˆo0CÒjr³ÜÊÁm#_@`O€• ¿#î€xê‹VòlÅ-±CݦYBQ7˜Ø²VèÚðعV,ǨVWcä„JKe«‡|æ-7ot\[å÷ÍŒ«ðð2Ýùe³ElK³Ð}àµÎ:YƒåD•$ú0?þr’£jèmGDˆò„àE„(/ !‘C+¨[,‡†‡|\ýέv j —òœ˜ò‚Šö‚`âyç‰Àù…ÈÁè©s¯Ö)DQÌÕ7‰¿:Iƒ?ÈIetÌjTäÏr¶ pª×;’quä¸é‚ƒŽ«¬ºîzQŠ`bähª[ÕØ¹ÐTözñW†Øb£)o˜ë=º•¨ì &ç_?ëi<œ›úX’Qi_ÏÊJ¸F(M1»ð-!9^°Ç˜Å×7bTlË#’l¶· 5ddBÚ ‰Q[ÝØ%MHÍ[ŒÍ‚yñ~« [¹Œxë†Ô¡måç­Å-;©_Àµ ŠT|*E—Ao˜™Äþçîì=K‚÷·£÷Ø …Ì‚Ž­e<ìL¨YP`â\*J_Õ4&Îݵ*ûÂRôUi”Sܵ(U£¦@ùsÜ{’»‘mù{­ÅH¡÷}ibƒöÀÊM–S}+èyš*b}놭o©Q[' ‹€".ªw gWXRä_ž„Æ9æ>ùEÅ%À=Få„'U‡V†ü÷q¼`õ••E#VħÐïyyˆ›io xóŠ*±žz×Ä^Áwõ–ŽÂvõ|hbB"¼u*‹fm£ Aa?ÎÌj4n3³·â \emHg<æ˜úªàþÚL•íLÉ›wuZÒŸ68Þ¯B7cv?±»rM뱓nïåSPËi¢\ù“tÇò©|P{Œ»^-°ïjeyw2¨´^!õaBê¨z“µv›¹:Ï\‘*Ãà«2X„‰ùŽi“0ð¡Ìz½ Ó‰2¿O{V3B´søj;–àFóïç j;ù£A÷â±fìl"¾ó"¾òý*“º©è[*ž·8míÏÎÄo¸¢3{Üæ{?ö.*à Da¦U‚dòéyŠ‹ª1åÀ¡>)ì'­úl »u•´ú<~Yf¾ÈƒÏÊàî™!¶~¬D¬ð¤oH‡¸[šA3"ü!¬8xµtܨ°£Ö¦­åïÊô¤¬í7ÀgF÷&YRσxвô¬ÌZ4åh> LßTXͦQþ‡>}SSµeFH|º#Ÿ×Gž*üÇ>òÒAÈ-ŽúÓ4Ÿ‘{í‹[¬¾RNN2Ê'/ '¸Š„F¹Jv–ÉÞ‹8ß—J²ÒDÑËÖàë–«-ÍnOøàÜB[²9_@3ѾÍñVdÔôd‡³;ä眺=ȼç*!¼ç5¥øtrg5´$ñ¾¥‘M\·‹¾[‚º\Ò=¶“–pn¶/]‚éCªmIílÁÌÛSg2׊ڜhž‘`ª¯T¾II +Zᦨ—¾_%X>jaŽeåp,híÐßmk°øUñÿ7-ðÔØ‹3RishÞËrw=Þp n*¦’ߔѣ™Š£ ÓÜIúÒ*rZ&]é<™ôé¯YçéENÔ›— ß¼ÝCÿDñÌúQ¯»­¿Â5/þ‹|ˆÖ‘RÝð",¯RÏàºøŠã‚›ãŒ›"ÑëÜ0%¦²`·a§ÁÛ’³PxÝZÅôpÃñ‰©ð$¬û:ÄÅÛÖ÷rÞ7-“`è§þjÎòíÖ3®ÔÁ"3)*eª¿¤Nâà“VØüEívH+Ÿ(_»í¶ŠËÊýnÓåå¯Ù%·Âß½0–Ôôà&¼i±v—$gÑœYK³jƒf&°”fí Ãï*…‚ÂS…u—ÅœÿqPÜF2²ÿ¹ÛhÀƒ¥hñá³Ñ=¾vÏ=Ñ–<W=ˆY§]á¹t4YÇóbÕèxž¶ä{ÜËE³k×t’“ú²Ä³ºcŒ®6ü­ÁÛIþ@ãÖÞ[­ºeMBçm‹½›í9­$þô`ïðÏÖF…´endstream endobj 396 0 obj 4501 endobj 400 0 obj <> stream xœí\m“·Îç‹ÄVR)v1;7zÉ®|0;¤Lâ—3q*NÙg8*p`óïÓÝzki4{{€«âª”‹õÞŒF#µúåéG­}¾±ñ¿øÿûO¿J­]Œ«Ïáߣƒç‚š¬âÿî?]Ý<Âf/ ~ôbuôð t V“\Y§!WGOþµÖ³6r˜¦I­ý±œäèÖŸm\·Æ¬¿ÝÈõßàß­Í.91ªõQø*…^ßÙlÅàœ÷fýw¼*¥´Úo•tÃᣟÀ¿»Ð¡µÚšõm|Dk3Éõ7ÐNÛA[h"ïöôÀ§p]ÙAŒÓúÞF¸å kòõf;ÎÓhã<6Å×ÜÜèA)iÝú ¼Ú߯îà{V4WZûfò£QéOœØä½Xÿ3¿íË0^¥]3t_µ7ÿ>ú+­Œã"‡6Ãè@êG' iÂõj¹w¶j&á}hpT„{š;^?@ñLƒ‰>Iët]=‚Ó…û0c­…”ëc¸üq–A­OJGxç%,€sV øk«¬Ç Æ;šõ”'®Ü4­ŸaƒVBÑëLõ|ÿ‹Í¥¬½L_í¨¡yjsb2-u7†'ÏʘØð.pž’æF9)œ(ŽthZÿ˜æš'}¶‘  â*\Ã`jZ?Ül%ômGŸÆ«ì4(y©¥Ò­ÿ³QÔDÄ b“(05y»þy#Ád$ˆî|ƒ , (-<“Ô Âá¨Ö¯7F“•.¾+á_ùôª(Kh½¾=LbÂÒsQ–“pÔ7¨•6"Êʽþ)ˈ7ÈË€dÂ;FA‚Ã~A¢àœ’]Áa·µäðÊýÔQ%9x_i-§Ð:Êg‚)±A’9n…½egÔa5>_``ÖQ†Î¢Òje@b²QÚž˜Ÿât­u“åšÉDŽQi9ótgønë¼2¬ÓvñÝ8E¥@†>ªÊ¨gVt2{9Ú¬7,ÈÄ3-¯ÝC˜ªØK£¶Zjhì`ÙËÍFŒ*—¦ËΚ²áf£)Ãb–™{|„¯Tà»q¹p¨;Í]¨lÉx¢:‘ „¹’!Všu‚}À @ŽO7àv•ð.‰µ“­÷K²ÀãQ»Ðsi³ììÛZ9zfIì}y²aAV@µi¬˜´>J€Ô” ârÿ‡&q GiÁÿ%m€e9®õ,?ÏÌÇŽ,ºµEåƒP‰Xàxæ¸qYÑ‘Eq‚ù¼ši°›4‰sT8D+Îֵܽè‹ç¯]V;½YùJßèšQ¤d ·`ÉE¯úEX¹Ó:²$ÁE¿:nøõ;;ð¨sZ8j¾% ŠDý áëN¢æËAؤùKÖ}y¯³€Qý\ÐS¢pEOgnµ?÷++&/ÁD„% Ø™(~¿¸WlÆ,+úWÐþÆ \G.º6‹¼Ž&ÚɤÌé÷¤Ä1É mšâ8Ç?Yùñ‘ŽòƒÛ·ðV´ræöY´xÖy¼ƒÈ˜£íƒz7,ó€ MÐ¬ŽŠK!4s#yó\ÀJŽáuÇ]2%d–÷˜{e¦²ù:â3g)Ð0Q‡Øæ>„uÈœÁ³²ì dc)¦ÿ B(˜½ðÉrê;HX<^Ù‘þ*ÃÔiŽ´è2ÊÙ rUï íÀyÊ‘øÛ^H„âœF ?Å2²ôUžEsˆ)ˆ­)lNL¿à0Ô6í&±õÒâ@Ãd³«ˆÕ…& –»£|›«¨àHÛØÎ‰±-Ò˜Î(` ÈW’ø'«£³v†:pO–\G /x•…@ü2´ an•Ô†jݪ¬ FÒÈö8O#,秬G^BÃ9}'.œ"aÓ¹´²¨{Å3 )CÚ<Ã`³è¢9|;–iùÙˆr£ò¦í¬!K 8zÂ๠oãK…ÈDTGŽ?£ª(‚’cÐïçÀsÑ ª[¼v•©¥,6Ú©öSÇ™‚TH‹Ì@ªž¢EåžëŒõJ2K˜ÓýT¹gš€Ì :¼,/®ÂÌ\ºéjâ“pP«WG_]ßApHã ìq%¥ª˜Ê€êã¨tUÝIqÈ ã¨_tèUAе÷ QÃBKz~gªÂSé&ÔÚMÖ@ûŒWq*˜+TÞ¶ñ q®ÎsOÊ̺…­âÅ9°Ÿuô¿AI34<ÓÈÒ·q­J´Ã™Ö¼Ä¡ (âjŒ>âtnÖÚ2À[EÉbZA ¶Áñ]¦~FNÓ9°ó+«ËÜjÅ„X7þ(&ø„aA[ ©5¢ 2º©qžìièÜ Rß™ZQÀ._ŸIïF…tÔŠ^JêÀ|¾©ö(>ü˜…;Èoá• U­dnGMY^eD&f_ cnô=Ø>ã»"ÿ¡FC{²9b€f ÁI.yÂ0ŸI2 9wÈt½É7§ÍÈñ ’JÔq¯ ôfóA¹x ­ŸPPÉFplN4Ìgì?v‚Èi½ˆ, cº–µ3ËS²¤Žg`µ¿?,ÀÊŠˆä#*¬ÿSº­ùÂ*Ý4D8â@¤½äõÙñ©ÖÀ4ì"­£ýI ç,<sb?K³Ärx`†[Ø]‰4çaû"˜ê\bx09¼Ã¢èúÏåhï >¹Rh!ü±3´”€x»Ø—©W’„ç0§Dû×K:ó`Þl òÑMŽÄ]ÁaQ ¸^•å¬=}"{÷`aó>ÑDóy† ¨–bh•áBitæ2ÞËêºX’³)6Ï‹´i"ªÐs"‹¶v…’ÝÁhÕ¼ó¶ÙÿdI/óX#xÄaƒ*;L—l¥›Q«ÀܲYvjÑÙÆmAªLKá+z °*ˆ¤¶{›¹ëAÍc›©ž)@`‡e>,P ¿jÜ-„ý¸s«`Få&¶O÷‘™Ý± ¦îD·tþf²MV]§Œ/bñ+&Ϙ™P9Gñ>ÑI³\ ”{º‚eÝÈéôdóFlSÌù©Qõ.'Bxºå”Hü míS]Õ£Œf^ 2½tÄVöfr†Œ“®±QÃÂHCK:ýX|ð@?(Úè=sðŒºYØÅ‹ƒ’Y¹p6·¾:x¾Ràè|˜[‰I+4`å±lÇ᩹›wïÜ]½|ñêÁÁá?Vâàð/øqóË[ð¿;Ÿ®~wpûΪ× {«ž–NåÕGÄÒ©< ·¥÷`ÍÌÛY•ÐõˆÇÆB.YHÆï¬)&^®%Ã÷Ïç9ãÒ²²ø¸­üUÕ»‰?ÃÈÊ}qBÕ8P1Œ`W±~ài«xE^ tsŠE‰¦‰u $Ý‚×8Ç€5M!`€V¸;Э Õ¾!–þ0ÕØaŸ„l—º{(oª· üXï²YÌã^³!صÝã +â÷›‘ÔHñÍò’ð”nRá³],q i²qœ¨yË-^[“a¯òùÔdIDï¼íËÊ+77«²žTŸ“ÔãieiPž9Jï3 èM mtÆÔ"–bÊÒòE¢6 }¯ªÜܺ’ŸŠ‡P¸Ì_a¤ÍéR®voS™ÝüWr˜m=ñÕHå#¹ŒGhÄEˆœé|QÐ0ÛEÑŽ=Ìê‡# rúlÖCsL n²¥W7] s~„ÔθåúHTôQ`b]­¨c…ù«O鱿ün Â _—qSä.‹¸´—”©úE%Û’Í‘‹¢å<]Q E© lO{'û·ÍãrL¦ä7ù–Ù\¬LdÈ‚ kã©Îíñs¶½‚ÓÙNgÁyµ*³¤ƒczÏs±l+?’6­ EJ…\/XV:uRÞKÇ â¸½se·u¤‹6Q¬`*Ç S©&Xõ¶b{a›Eï^L[+å;Ÿžì/«™FãiFÈÔ½WOÍ4ú#Žf¿VBqdœ*> zŽ*e)„×Ât·´“e÷Ä­Þ0 -t: ¹pƒš|¿ÆÏðã.~àOÌE­éÆ=üÀŸŠÀß—PH+m5« ë/\‡×Ê‘¼ÊÝüäc”Xgi!\|Q.žç‹½‹ó7<*ëÉçÒ@f½_䋯ÊÅã|ñ ŽMéÃÒ ¾¢»žïæ{(~ƒ§‚|K˜£ÂÕ™ŸñFi¡þ?þ„H˜Bv:·>‰MÒXðX±›bòŸ—ûå=ÊÅË[Æo¯D“.¾Ê”‹¸ÐñêÇé¹É,‰Æ£bzHšõ¤ÒÈ1l¡|›•ìv­d_ärjüYúI–ß¡°,ùÅÃ8ø4 ùÔ‡ÿk¬æ“üq’[ÓÝiTê7¶„ù×Vš%¼HÎä—cãÛÊ/©l´_˜ßèˆÈ¯¼ðƒ$ƒ0¿dªûK8àÄÉ1û¦SÄÂÈ<+kê$šjr+ËÆÔ¸'bmIÄwWoàtIZ®,Q@¢êÃM³âøÅD3ìº*¶5{)»û<›Osé,IJÅ#Ió–çÆK×,s` å~D#rf^,ÿôBÀ5óó ì\ÕÞlwò OФu5Ø÷Ä©ÕòdýË6å5ŒGÚ]ÑÊ΄°=Ö«–ϲª¦(ÊÚ wþHÏ¥ î2tkÎvží W#.)7jRØóÚ‚Sí¨ýìUq£´›vw(8µ‘”è#FÏ0&ú¢ÿCÊ_ Rb ¡ðm‰jž2(šÁ½$1â9cŸ Dø16 sžá"Ênt,²ù²> stream xœÅ\Y“Å•žç¿¡Ÿ†{ºEåž5f1hÂ#š11àð4’–ÔZ üû9K.'³²nß–›˜ ®²²r9y–ï,Y/ÏçIÏø_úûþ³³î)cν>›Ï?‡ÿ½a±ë{µñyc¦Œã“¼¬»-âpÕ“Å1·ÐKLü>N¬I²Ú#}ʰýÇ:ÔÓ„v–)ž~H>´‰íy_®QÎ< #˼É×™­î¤„h\%nXbùе×ù¸@ ÈkÛß¡*ŽL„rJtvÅ.Õ!Q£ÕöÍÿ’ô®R!s Òf^ªþå¦X° ²qéÿ+rG½‡:ÌSyˆBjðÀ@#;z?݄澪ƵÆÁ‹F|rÒŽÆ<ƃƺ @Ì;ð]%±vf6«‰÷Þ¬ÖJ):7Ö±U%Un´Ex»µ —.Î7ª¹õa+ó¾]YÓćìÜ1ÈÅqt+4 tìS 0~‚ßš}Ñá+\¾%|-NíªÒ '¬'×§VS¿f7ÀY×z¤Öø¨Ãtò°òçº> –ÖÎÊ®(QÂàŽIøbõÌlðBP´}ÄÏ H§Îìœ=OÞº%~ÝýoÞàw%>ô~òUÀ ü7dȪ< ¬“‹v4+;;˜‘´Q¡lØ,Æ_­t¸ax:Œ$¶¨V{+ Æ©‹küÙD¶µ?‹Ú |NäØ7ü‹ˆPÇo(®“ÜK^BëãTÐÕf«Çê8£O”ÀŸÍ™UÇõ°žžcñK®q*žDžÂãC‹8ƒÐ·˜èt¿Q˜B´ Ä‹yuÅÛ5žc!uÆ_½ÜÄ^p8QBÁøÿw{ÖÕà6ju,\E°GùiÑEÝŸ¼â5Øó8ó€¯ï%aG„ÂÞD_À"à±ù†Ï[?§ñ׿¨ò°rs çàåM<ôiÒ¢Ÿ!·ãBgCÌ)b:ÝYb'` ìŸ%નK~½9FõÒ)£Ð6žìÊ"°A²ÂêÑîY(Ò7­Q|iº“fÔ¸”²¼¼ø]E³Bft(¹ùXìÔh‰Œ-¡Y“ë#´Ât‰ðI~’i1¢®K€BÍÌ–3»·âµl9 ãŸåxÀ‚èʵNÁŒùe-@ˆê($—$¾ `&æËø]í]¦y²2‘Ä)™ ¢Yk6ªä´Ø`&‰°pÛÐ,÷ø’1Î Y  µxçqÅO,=L€ßÚ˜ ×]ÈNŠÝ”Ý`×0 ~'al˜aâ ÑTöCìîʬ’ØØW ¾ ¤°‰j…Ð@03±ë úÒ-YR~®Q²‘t– Le6\WòXàd2šðk„’Uu¹xþO¡2j«ðÎß¶êi’À-ÈUù`ÊmÉmfJWãbÅv9äðÀ…^¯¯!riuI.¸U‘”ÄZN€j]&NÀ2pà ¥Ø¢[‘–S*<’ÎÁÊ\IS@!8{R´id*ÛGp÷çx ŽòKqÄ [Ÿ·”|“´ã\ £ÀJUU(p õêÚ+~úµîTŠƒ¾¨)6´õYYuçfÐÁpvóÄ59Œ†£à JÑ;µjžB±o)|•ÂEiû[z˜1΀‰³|Diïǧ‹ªü’û`ª .¨X©œ31”i'¡@¾mpAgÞX/Sk LQnÝÿ[ü½lçEK¨ËåÞÞç`„9môë–¡/[¦î.+=ÂZ߈Ì×V\ ‰Óâî¼ne¿îàæ1c:Fò¢g>ûE@™‚_ª,H‹Ðf÷fÕˆ` üW` ËÃãA¤·Y_ÙöFJ»É›uZí½*.i\g£t0dhOÞs¢l‚˜#· £š–g.x‚-úJvֱמºa5`4birôr+âÅ«9BžVÔM=,sÈ ÉÄdÔœÌÞÀO [í0ÒÔWc,êí|0YÚù“ä`øi6ËÀÃÀmŒH2äàé¥aéoà¬ü±çàÊÀAk®üIKž–¢È-;£—ˆî :!èªbyÀ2ŒlX2Sùç‹æ'+ÎäZÑP–И—Ö–¢Sƒå°ÀŸö3ô4ˆkš¾˜[²ûW`æÈ¹zØV ½Þ£] Š"L¸BÓGôº¹§Uµá±g;c"ât4s`ØœVÍ¡Q)%B'©\zvñ¨,§ ’ö`t œ#²Ṅç*€‡)gÆ Cœ‚ ™`Øz“妷?¦àµeÃæO»Nñe\±¶®¾Äd‰Ñ†a—ÆûÓÙÅï¿'Û_TÇMÂz)tsBÀš0{‹Þ°ø(b®ÏwÛ™ ÐÅ!C5ôRnµRÖ)XÊ: 黼iå<èL¬S¸Õ éÞx*ÌÀÙLÉ—‚O¬u¬°Û%œëzWâ®.ƒѺ¤ÖªéIQ0%@ëÚCËjJ »ð‚3ÒãΆÁb°Ø÷£È~%¥Ê)!TG½€¹©V¸Óxt‰Z-°ev>lÔº|“£J±+ïÊa9gÖQ¢&@÷´þ`OT÷0”Ã;M`N„*O9Þf%–¾â¦ÙkÏUè§ñï*s‰ŠÂ¡H®B†Á:ÙÉ(w˲“Œï*;`}¨.­ñEHv"0–Áòêy=¯A¹«E]lQYba’?ÃɶFÏ%²Ü QÁ©wI-á¦I#yÜmL$ѬE¸›QëØ_i£"õüzÜÎ¥Çíé6’”µ¸2('ˆ‹õ]®êyjóGíœf$D=ýE©Ë œA‡`ÛÓÇ6ß§W¯°#Äœ(PÖG¨- JϽ»U³î$cÅ‘xo.‘’cvËF7‰¤ Ì©«Oª,³a[=’IjLÈ…XÐ õfÈ+©L±&À0µšRÄF%­ iR­ˆŒtKØÍGîø÷ýLã×>#]†U2Q´ö¬±Î|TSVó^¯äòR÷¹.CÅ>z³D€“ 7«3vnb·Ó­À“mmñÍê€ €RŒÙkB/ŠÂx4i(‚œœ"פŠ72ŦÖ_m¨eô1)n$DºÚ—챦¦ ¬ÏT·TëÙŠ“¢µ˜Çö'¥“G°©yZ٨ª 2¥O5ÝÒEñ~P¹äŸXá¹²1šÎ^Ð[V­¡½/Püº0Ɖäš‹Äq[ñÏ"ºMüSó¥”xrÀæ®1òìãØÙL~Ÿ ૈqDg:þÁŒÀF'1л‡Ì>âÉõÆ¡©5HDi­Á;Ó£Bè5²¬Œ“'åÜ@cåhVªkÖÑ¢šø‹}©w70н=P´,ŒÇM}vqöõÙËsc&O—÷Pëžḛ̈Žç ¥ýä#^ üøîÙw¿<óêíóþz®Î>øÿøø/ŸÀ_w?=ÿ·³Ïîž}Ó‹‚ZÑM²|WPäûkYþçBŠÐfÕf¶¡R ”ÅéÌAóq‚ìÖo‹f ú݆%É€ßÊ‘ÕZìJ1›¸9ó{ˆÕÊ+ÚvíTq®ÝÈ¡ æð+«¼hàºÞ¢«œæÈD k`d¬r ‰ÚQNOR¡Ì’oS7Ž|vA}V]©2;G:6#ÏXÓíôûb*hUÚÍØw] )Q–ßí9f;"«êU‰¨e¼ÍJé†ÙR0wD¤œæ|)[æ;çK&ý-^Lá_ͼ‰Ë¿Z—VËXÑqqpTåShÒ K=Éø ’P¥MõKE³œˆnºü¨W­ŸÌ„kžî'æí¬¢Bx1²5ö­æëƒ½ùŽZZok\º%Á‘â*² ’¶˜&pH&³ÖA)7à!8DReý8!½èâÍa¨õX6n+[¶Û»õØM• K|ˆ^æ ]·"=êúñ­Bľâœ6j¯ËýF•tW¤Š&g7y»u×j:«êaŽß©2óƒFÍ TM… ^m²žÕC¸‘F¶šÕpuv_9‡”9…ÞnRFµò“˜¨ð¯äüiù7ßÖÌÒ ï*ºš+éÄÐÛÅ÷QÍEŠtuZå²®öyÚ‚â{H‚çF |êífÌ‚Ùh¯¬Á&8¥9f¸ñI\ÒresÞIµ¨R' Wá²&H”¥@ÇUÉË Ñ"ZïR´Ìõ P`±“‹…pïœ.Qce¾BàÔỽ.¢¡û¬~Æa€Ëñ"UÂ~Ë“m¯¥òÇܶÀ7 ;· ïýy)/…O †Êyº¬Öå `=€2¹6.T|±íà èÌHìoéàÍšÍìqG-Jr"ÚÆlé–åj…w¹¸¨ú4×;øè o¿–qPˆG¨—.ð“î"æ·É´ÛL2÷üo’…¹Þ€i hª¿PVÊìËèd"T˜‹lÝ™í+£Ș̌B‹Ž›ºÚЧpïHí»šlvíäÅ¢«ruíšË()’‡æ‚yÜ(—{r.}»à“nÞê[¹èEÌt,àÞ†½ÄþçzŸÜ§”¶5–îݯå‹À#ÿ¹Io"—6up·”ˆ´3 ܶüÖ÷ºbëqBdU‹´¾%°Z\“iÒ¤ä¢Ð@b\qw¥uhRÂu>ˆ.U-äᄼڻ'U¼ÛœzžÁŸÍ‚z/´~”ŒúÊ{×ݰcG¾¡»û0ÃÌhT_åÅ9ð6‚›.R´Qâ¡ûß)1äc¼43Çmü†Ÿ0®”½Ìµfãºì«ä!vLœÀæc ù¬& ÊlÒ›¡h·™öUì몙ÔÛô›9Ì»Y\w0—`Ò¬L¾;Ým>%þšãXB„®ä…0dŽøûŠ!âíçBÕZsyJ§tŽbt~Ì2—'Uj†š7½V7s-ʰzEàÖöZbþ¸ô%œ˜=æ·,ãÀÊ ‹Â9Þk’î€O"~~ÅÍ$ \ažrí=on•°¦_;zç’¯NétÓ<_Ãô«Ï‘¯UTÈg#uÛú7¢tš.¢ªæ;JGBTÔúMJtÀ˜AðTuÕ}½KäÄß—¥1µ¢.¶ ß•{—¾÷šÄç%D-tÃ[kS±NCµ‘ü0“b]ßšŒÊCä%„Ì ¸ŠÚ.®Æ‹OäÏ\ö6æÈçê4ƒÕS ©s‰kc苽¿Úˈøb¡ð‚¾Ãñøc4âšû·E8ƹþÖæ~pär?Órp²09c¿™Ï—¾Ñ£á€¼=êóåï3Þa –þv”0[þsy~½—kg÷f~ûcSùÑŽQrËG&ë†é#@&¥W—RQ*´£ Bë¯Þ12™ù+}‰//m³õ,úfY]5åKKÊ¿ƒd¦+ÝjÃ÷W1½sH–>9e³šÖ$}3¨Ôe©•„KÛß„‘®^âF!£åºø·ò›”<Ò+FÊ{ÿ-ÞKM”õ$ä¾H¯íñ`—|Mo›>®¾!:å"ÖtýÆäàóRÍ5´WºòhÔ¦µLßsò×]äÉãÅ¢Ñå£ÖAV>J7ÖÀ)¸qnˆÈÒJ€¸4¸*b›[µ“­9ð_„ƒFp|KiS ÿúíÐÅu…ío?÷y¤Ø¶§‚6¤ð/†<^‚ÀªÏ•®1ƆŽöFs¦ŸD•tõ#NRe1Ð@×0B D‹5tôhïÆ# Êù-¨£œéXj*w¸mãs|VMâ›R+¿ÊšÎ¯º¢¼ƒ”H‘—9o….$ö©¼˜ׂÆS ôÑ¥N•B5ú)‡Ñù]k³æ]}U§ç±~Lj‚ôÍMТd>›˘îVKâÓ—¿N/¬³‘®‚ÞÂý“ÌNÿ)"¦Ü3Ê4—‘,~ôké>: $`#NºsÀûÝŠ?£ÈPµ“n¡E¢Ø7p÷7ø'öãðjj¼¬=1ÿëý@L®yýá5¯ÿÇqºlóÏ·rÐüy ]¹äBVöŠæ:ðb°ž ÷¯çÿª=ÿzÌO˯giíüEè—’·ýõÙÿä¼ëendstream endobj 406 0 obj 6029 endobj 410 0 obj <> stream xœÝ\Ys·Î3Ë?bËѬJ;Ü€]~°äK)ŸeDZ] EJ¤b^âaJIå¿§gc³\ºD=Ä.-—\}~Ý _/†ž-ü?þÜ=Úºÿ˜ ±Ø?ß_¿ý­×[ÌwYÄ»G‹ÛØÍbSïÇÛ/·ÂlaøB[Ù3¾Ø>Úú¥“KÕõKÞcDüee¬ëù`»'˕꥔NuO—¼û~¹bð«2Õ×ï–+Ñsεî/­é'U· BÀ¤²ûb)to¬õ„縷0ó·ð/.¦Ý=ÂÙ­cƒé¾\Â,ÌI }X®û<,. ñ3œG÷Ø“ Âép°¾s,õÇÍ–éÈ$°™Fr'%îB܇ê>Í â|d%–›í”+`;ë,e/×¶û9oÔr&éFã†Ùß¶ÿæen©0¡O?XçöÈƒØØR…ž‚ Ús%9W/VÀnØž #ŽaÑî~¦oý00Öå¾Ë~œÃ^×LuŸÀW>ÀbÐ<äÓpܽÒh××[Ûwé^b‡Wt®¸Ò3üõ ?Îê.~õg©lk?~íðÓÏz‡pä¶Õ~žÐýÞr%ö;ÞÎOKÏ'¹ñ«Òø]n|\·«9…ïÖ¯_µV?/¹ñEi<¤…Àô8/ļ ÖOG­Æ2ü¢µ¹{•ؘìAKPzÊÙ %—yÔN‹Î³Ò¸“ßVó«ÁöΚî¯ë™³Ój¼,Ek~]æ¯çç¸ÿƒ¥¬ xýC zT‘üÑ4¥•À”¶XqØk¶hÙƒòR£ì¥Bm=,hLw T)Ïqð[½÷±–øV²Ð›ëîd ß&E÷ÇRxzkÛ+ƒš.a Æy÷]ºF˜çð꠵ѵ<ùÅÃä§Ë@TËzž·þå ø'\ \…?ŒNâ¸<Ù‹D –VÀV\ÄŠþI:>ÞJX– 3B6§Œ4`q£È:¥ý*”UÊèsä²RFs”ÍçÛ[?l½^phV°»Œ™^Ú…éµE|ðhëþ£og—/¶îÿ´`[÷¿Âß?„>[üeëóG‹æ±V€Œ‚¡{†u`sw+Ú"O ÁÈ#æ)‘ jü}P"Aä%Y DšûAœ7º©8³²å/稹`]O º~¸gŒÎ,@Ø}±µ íð.ŽÑ€‰‹€¹xmÁ]TŒ¼G¼ d8%É d}F‘ƃ²(±Îªé˜â^hçÞ:c{\Õ°à]¸QÈÒÚ?þÚƒ|-´ˆàHy?P™Õ^1iôl85¸Ü 1Eb÷dèIÝ)>у,".j‰Î!F;p‰a‹ûq&mHhÓ ˜€`¡­÷r#/P9aÀç2‡t «Àñ„É5º‹‘H§áß öb=bÚpÞ%úyp\ È»,‰ƒŠ®ÁY2h©Ð÷[‘:Q¢Êî%õ@ŒA¢©ä0!ü†æº2"*B2JÈýØ#M‘çïkŸŒ“æ&XJaH‰ù‚À‚†~$ &Vòw$ˆÉ>òZƒ6%î†$¸ÄŠÄØkYðH „· $À|Œº  o|Ügþ$GèAéOjH°$b‰‰b¶ðP9é[æf=Í‘<¼?(Ê\L6Εõ:3^\9Ô)x`ר!ÖÌ»\fø€® †!ˆÜšËe`Ä\.¸/}îU!¿e¦ÔD#GfÉà ôo› >„Œèàfû¥ËÂÓP`,XH²® ÙFLªm#H%Aðœ<©P16ud\KÈw]rd þ>by—~É+:(r xè– >àøœF:ŸkÄ;²€}­‚›@—ç$BÈ‹è¼pØeÙdàw€ÆôÚ¸‘ÄI€W6áš0Nû À܇ºfƒ'AQf€9ì×» &ÆÞµ¯9-AvÜ’v¢‘–dê7ßR´Ä¨"ä,`¿@]V`Öfý’W0ƒ­R%À:Wù½'¸×KM=Øa 2 O×~O`ILïÕ$,Q˜Ûßb5ÆhÀ!î¤/éì$'~-FsÀ/AÚmØÂ«¼c¤w›à5‰Ê¹|Ób2& €nÜÇ­ÕS¿…°1‹_ÒÜ-9)aw–U ‹D:8k°¼ç™$²R`ætL™¦|£ö•£ÔýPìY%ÞÕaé\’êãÀâƒ7 —\ç¤Äˆ×)¦ÐNƒ-5Eœ¶r>ð4¶ª‡|®ƒúuy"€³0R >˺=ŒÄ6½P•ãVE.œõQË­“)˜¨I™{ÐBÐk—µR`uÊ0Ÿ’O‚ò hÿLó?ÍUÒ¯Q¸á+)—*j®¬ÎgÖŠ½Ùþ€ìYÅ1Rþvªµ2´|'2$bQ]‚ Ѻ®]„0!Ù¥.æ0ûòmâÐÕî‡Yu³ùpp6™¶–®˜štX~ì–ˆZ¶âöM %¾h’¡8è÷A†âÜGï3à WvܺTö¯c!âm›Á6úûq°ª“÷ŽŸd$4ä;2ŒUfK‰8‘4ˆ~›ˆŸâõwXid ÏùŒÕ9o.äÄç&¾6ÍUÎrv\êPå'=ZÏf%Ô-‰¯ÏJP€BR”ˆ±)†Ê`´4Š'¡‰+ŠŽí‰TE®$êTˆô¢;AºÆÛ:K‚,éõ5×§pt*ÜÌ ^–Ï‹z­Ä¢ÖK‘b™?–àq‚8Aàû%elÒ;פŒ?Ùp½ðeýp õéÒW…1 ñÉh-Õ*'‘¶‘½aEhp>mZB›KFéœO'Ú 3I1¹vÂLhäàÚ#5"Qî9vðìãÎvîð¼™™øÓJäH¬ê˜§˜{]¬³×È%5ûa§xÀ•ê „b¾ÒÞgKX_^ ó¿“´cøÎË?›‘ Æ{!ùH"Åì.Ç«¬(Z¥¦±Ð—²‹›<9V^¦Ö8S…"¹”]0U«DŠßÔ8-UÔÖîKÎ~VPÚMrêd¼­¤• O£*à „¦ÔE¯³&ý~‹r¿!qo ˜¦:†žáõ'¤ &ýàï12ü ¦0Ö:ó.NøTÕNC®*«–L$¯J 8J”¤àí -Ææ4<Û‡³!¸{‚»á®‡_õÀÛƒ„ø˜Ƀ=ýNNF£–ÒZS½,º ¥NBÀ#\0'S´¸èþ¤6=Îß"”[_>Úø¸¾eZǥƵöæ Â]PêëªDãàj|cäIªÝÈ™³E¼ â3xâí«ª¡gã¶ #MÀ›¤ùèÉ$!ã_ÅÀ/§X‚E¼’Ô‡ALŒŠ-uô‘àØ(5Û4'`LŒe®°Žj1ªÈñV‘¹™A—í=,ÃÿôE9¼Ad¡µ¯Ëey5ìL¯ÜЈGªq:1µ¼²Ú,“¼C iüqÅŽ±é‚-²ôèäpYA 5«"R°¡UÅj¹ë¦þŽ Î3·K„ åꂆ?,†Fd³alÖBy³žSÝ(9g÷#tHƒ„ö7… LR 0¤ñTaR#i¦Yd¡HµtúWÕrt=¯†‡Waä¦þ~~àïñ£*„C%Oo`¹C~± wÄçBèWÌÉ,Êã!7þV×½­pC²^åV ƒ õ¿û£¢ãöIa¤¾]íI1çy»›Y˜çKö"¼]‘oë‡;øäÅò–Âa¤}z/ÿ^‘sì”lÒXÞ-8ßL4‡™ODñÁ¨Ž3¯ýã+:s¤+œ=’Î’ˆËëTP'ùÉ¥\:ÿ£÷?ÒB§ùùn‹ —3sn¢»Ùô“M$¹yKz³Lïý”™w²Rú.h!¨ýýÆ¿„$Bõa³]vób½$žÍ¼¿=¿†ÓeI |³ìîç–»‘8&É&Þ\£Ç­íÏS¤p5™ùƒXQüŠ•ñ¥ïÝÒá~õÊ 7IFHß¼`^2{™÷ÙdòDž{0Ap©1:›ã,ì$ÃñA.„pk^þÙIjbH#ñš§-N’éwè–Óó½²Ç2þ <»^»Ó‹KL¯…]¶Ö,ɽœÇXC|ÉIåKÒFɨƒJÅî㩯ÙnÑbkëÔm.'J5‘îУ˜×ŸUœ³Îßæíýn6uÿQ¸}:1uÄ’ø®áÂbv[ê°4>£€:µÚˆTf>þŽçÕ|Þ½êþ—:ÂînÂç— s4mr>î=ÍVÖ¡¢møqf¤T¢=âIkDÅ HG4´·ýmóÓìVÙð‡Eቿ(_çº]ízÔ!¾Jš&kÛä^å©‹Ñ¡œåà/ßGK·¾ØïæÖ—ƒÜÃÄkµb ¹þPÈ sö9ˆ·ìŸ×ÓÌi¹ê&/Lßãä> stream xœå\ëo·ïg5èßp@ú.°ÖË÷²A>$~$N8±ämR´²¤È†mɱ-«î_ß™ák¸ËÕ”K›¶-r^q¹\r8ß<–?-úN,züü÷ðåέGB©ÅÉ›~ñüw²óÓŽ .‹øÏáËŧûÔm€¦Î÷^,öÜ ˆ…“ ;èNÈÅþËï—reð¿¿î =DJÙ) OíAÏÛ«]Õ9ç½X~¾÷ƒöËOVrùõjWtZ'—û¥ÏÝЪô°|­Âðn©áuÜ‘ÒwR¤GC'%;!´[>ÄAàÝÖ.?[Áp‡1ún€!zK/ýîX+T¹¸c ^)±üj%»¾7ð‚Ï`,=tÒ‰8–éÅòq¾Íž¹³ÒÝ0()ÓÌq=V»r40¿½·Ú5p £ú)¡8ývÅ0t½^ìªWáOaJËcüy‘®`6B,_æÔå-þ¼7ô¾ë…Y~ —²_ lîóÏGéqœP±=ììƒý¿_þˆžñ±â›þ†^àÏëº ½îæÎgyª?,ñ—F}‘ȃ¥qB÷›«]í,Íx?7>.=÷rãç¥ñan|T÷«1=²êy¥ž/rãii<ç„M7‘žCçGë÷ŸµÖñ¦4¾Í¯KãYn¼¨çé`tsµÑÓå1_n¨¦“:I »]/)^â»ÒúXYÁøáz,§ Å£ãAk%Œ$¹ñ}“⸜¸­ÆóÒXø÷‡U¾ü¨^½p@ Ø•p‘Eî.éC’bLZìYƒªÉ7å!¼â8®ÀóƧծ¥1 ­N[óf¬pÒêY6æˆäž16ãöÓÜxR½$LR³Iž¥%ëµ3—­ù•ûkäî¼Éš§Q{õ©ŸZovèìЋÀ²¤½pËó½Hì™ß¤è½‡‘Ô¢LÊÇüÕ*¿û¹ñ«=èåþ7õ\(¶¢†ò{™•_ 5gäˆi~–ž{÷ߤç4Hu­’žïpIù'bº–'•`”C`sØì-€$x‡s´Ê¡aOàÑÞÀ* É€Kæ>Rð>8†´Ñ¤rS+¾'þiÍí“JI%qá0'ã¬d쪇ʃxvEÃÓ¶×xGJ¸§*zo¥lç¼ä¨2bIéµøO¹z·2ºƒw4ð ÀˆÎ9Rée9ÑžÒ´¯W# iBž†l¢€o•ŽkpJ5I¢—*L8h×4òÙÌ»I¶­uVsjDŠ¡ ¢|˜¾“€‘þžžä¨GÎñInàkæMi+ZÚ–¾¾¸Ax£é €{Ú4Q( ?/r·±ìQp èâoç¬ã€:î¶F0íÄÀ;À¶I!;™éiˆÐ4QÂrQ^yAÚtQš Ÿh ¼3¬ñiyiZÉW¢Y­_ž£³u±3¸1¨zä+!LÝi'àt4ðcZäP8Æ6{U¨ÿªtbžÕ¿?K{tPäVå: SÈÄš ª3kúŸæŒÕæ¦<øÉÊ TêXH…{‚,3ôècb–þ+òü¤ ÇC×£ûÙb¾8ÒVgçÁYSù¹Õìp§å„K¢Ág)^éJÛé ô„ѽb‚]^3a± dJ ÄG ~oÞa'l ÖÆ€Š]”Û‡é¢poaów‘3EKÑJ¹–’PÌôá._å‡;.ó4iЋû•0Ï©UrѳW~Z¹È»Üµw”6MïF"62SÔ½¨³4ºñªÁ5Zi¤Tš€ ú RwðpgôÖµ †Þ±9ÃP°a(v|‰Y\dén™ o¦êï”–[åZšXÞe Æ€µù-s«E‚ܺŽèÑÒ’±Óâe¨ ¸¾Ó`‹2ù38¸þ/p !zg‰ “HÀÇlJH½<%˹4ðÁà¬çQ›È°Ï5#p>˨ÕÿÇ(•À…"pNNG.ÑÄ%†8Çæ¿aN´Ó M¬\£\­DÚÎ5|Š‚µ+N¿QM-×ÖÁ^n›_¬¦}Z©A\g)Pöˆ‚²Èï•Û7ð¶$Ö»”C®2`äƒ¥Ó Q}p%pWÎã;xLЬÖà›tË×úSlé(k 5UHW’â#ZÇfH'¦VÉÛ: ] '9 £>£ƒÒ/¥I¼¨Óæòõ¯¹ÕVH¯—%tï“,B‘T •¶§0a'®Œ÷Ó|.Š4°07CɆ^Îb¼ÞN…yùÁ7* ¯(¥Hkµüé*± J«B‡B6´r˜ÐÏÐÊiœˆ ö!ìFƒEÔw¥âô"€§e’¬“ga¤Œp_fn¯tD¾@¦Ö’idD”QÐÁeÔr?2ßàhfw÷w¾Ùùi4µ”‘AZ,„v0ÏaR»>`žçÓû;·î¹xûúüxçÖw ±sësüùôëÛðÏý;‹ßìܽ¿øæªÙ.¢] ÍBþ碤%r\Ü"iæáÀ–ÿŽE¸¡ø"ʶq ü(ì\T" ãs&YL)5„ ¹EYrýç|º,rP+Gvy°ïò•ªH*Óµ€¡58p»Ø’ÊÈk›~HX™5ánf²Ôd’%˦LŒª7TTïÌó9 .DaERaųwGõ©„ãt`f ÒÈi„L†•%S¬¢îYxMcÞÐé=&Œ=cÜËÀ“ zyg…i>Øôéྵˆœ»:pE`šé‘gùŠ¢¸@í)6»‡Ë‹•è„BÍzJ ߣ֑ ¢PÉÿ;0n·©#¦aŸ†„Õ쯑µŒ(ëXë!!§¬‰ƒjaâ|a B¦4ç€(%Y:ò1Ãìz­Ó:°ëI ‘FnÚžÖ¦ˆT°‰²W)W9¯š É`ˆ DFcÆAH¦¶ðÏ¢ º‹:ƒÖRR´£-È$.í8 ›† ñ­…§ XštÏA¸D2†Žð?Åmç^| ˆÞÔh8—£Ö \˜üI˜ ÿ43"=sÇ`à'9ÛÏ :«À¤åÎéjÁêN@á¶ÄZf±½^[íˆTBQFë”=&UQ0¸²'E!ÝqŒ½%ÁÕ¬·þ1q•CP\ÆÈKVVa•³ E°m'áãD@C#¬-ª™¨éû˜„XM°]tã‡×ŒO‡OX&ú•‡P‚–rα Ü1X­±‘¦HA;€6-˜Ž;–ÛÔ:¬ØŸ›3x»…iªQlS¡<œ)/’²±“ŒGeÃùÃo£iU¾¾í1ƒõ¥ýÁ8$Ô¦2fHÈP™Àuv÷1OVjj «AÀ?h±û \+†"=·š¯R4LÏÚä@¡¡åNr¦’<Y‚!ˆTÇV* HXãºØÅèàXX f‡l"Ü›ÍC)n:ä1Tœõ¼À?!|ˆ‘•ŒÉ>edÔ|m—ÊR¸ê;x­s…nSŠË1žsʬVŸ³L6¤Ñçµ!‹¼9Q8]¹©9D¶lAa&Œù¥ëà`½Ü›ÑÀßITf¡4mÛ–¢+ÆÃ+ÆŽ\¯!Ƕ"ë­CO^ó¨Ì3&]L΀§)TÂlDyO3’ójl4ô¤¢'þ[T©Ó -*±*]=ÐlçJÈsÓ”ì\àd¬‘q€–FV^’F˜ý¦˜+éÔgµ sjŽßõÆzÑÂu¦•ú$ÜaTÓ¢1» #`dÓµ%µð1ã|Æp Êw˜¡L1YçÙŒØ~äáði” j¹llf Zµø€¼E š¢o’ý·â ¼[k`µ¦fyk |1_ÏL<Ó„àš¯›4¢DŸ„ÒÖÝDÑÚè0¶G‰äþÀÉ,Ï>ãjÄ'ÎÆñk PJ]׆ó$hCßT`•¡Mî;ÆÝz^ŒœRxkhíÏC\IJ=õ­¢!âòQTGUïÐð((MUÒ‚‹_£¢áf´ÜUzmoÄõ2Ùbsªl`PÒíPÂA-³ÏK!Š‘±ÎLdʧp{ùÈ2Äänì‹4£…CRº˜BÀ\ÒX4öÉŠjOŒ õÈ×,nÓÌeå„lz³Dë×pb婇ŒM•©€¶àì· WÓ@Ìñ;ƒ&­šÊ mœž/üKñì7Aœœdât%Ÿ X'ÖÞ¦Z”Q"ë]y±)Ê!f;J“|•AÐÆº3¦nÙ·Êí–Ót&Ž|wM8IEŽJ:ªd¢×òà‚¨×VkÆWÊY›f$‚áè9£4ç•KC®ü …ë$L+˧h+UÃi«ùR‡¯nâšG® Kj_Ü É!E ›wñ)ún ÀIJì•MÉ·¼˜ÊÒ°=ËíïWƒC¿ƒ¸†ªÇ€v,Œó´Ð® ²†ø³Ù<3:ëžJÒ§›å¾=åºä”h(”> Q»žª¦òå&™¤¸@l_óëƒ÷j¬™Uwéþ•°Q(Qp¬†¬IZôË)¼ëqˆVÚ”6ñO5˜=Ë0L\ƒ1B—Ð}ìŒár²‚¹ËZœ®r¹C,lpÓÊ4^¶ßH \(¥üÓdY޲^?YFnUQTDVG´z3UVeÒË>Š‘4a·¶µ&4ºlã;U#uBqSsI@Œ\^7®Òuù• /}—‹Û6ãUÍQz)â’\öàd!hU.3Ó>ÂôS±XØcxÐôi#_p©«¯RÞ?§F•v­þQ–ps¢4©P˜Ç ­É\æ½á)í½ˆ¹íŒ.MÇ"Ã6pz˜Æu£µ á{±¶ri6g|WšçëHBÊ:dqR3j¹dHæPwWPMèÿ;RÆãG×öµíb5„#®žókÆ^)%Ÿ3ÍK~p¯5–œD1f* rqhÙ®rK’ü¾cb=Ò)pŠ Í p‚g*CkâÎúÉ•jE¬þY´C™‚NY7l܈Râ0 DGšvi6E£bͨL‰‹!…‰˜³Kˆe[⎫žóóÍÜüˆíñ‘§TVwBOë§óÛYRbÆâA©i5Wæ†ý§\î5MT¨qwµìéK›­ÉQ [ñ0]Æ„ˆèM_—¯gãtl¬‰95uµ}")­¤=}-·>IH!,ª§V¤T닦Â.ÊËYk»¼ ã"kƒ7u‰F˜°B•aZ^ØiÒç ràHsâò´ ì _e ]Û¢`Iæ—\Ã6¥ ª‹%®€4QØ£„ÄRr#x)¹•¥ìVƒ£S~zÚ^ÜvÓ‰ÞÑG|ùöy¾}”¯šOcI{>ycRÇâ8JâL=›ÀŸÍS˜‰dß,4MXaY¡6\˜ÚtãPÆ\þ=*H<óãñ*rö ¤ ÂaÛª´»ŠFÐKª¦iA–Ï›|A…Òâ4dí.¡"Ðr5¬VÚ±ú¢RÆ1u–.+:@Ýkí<*RWEŸãÐÞ8|Š67Z…Ålµ—~ËhÆùm«QG uŒâµ$9Þ0Å+¬øHɼ; Ò¯Š“@Llq]OS"92 Çy¿i}Ú®ËêXhšTD0à­U‹4íEÄg©kýR„ŠW3¬ÔÆòLŒoÍ•®Ôö\«ßΊÞI™à5^v¢„œw–úÞÐB§ÄáºT}*K)õ]›Zàø ßô8‡å¥Q(¥M§t”r¥ '°Ì|à—&÷ÇÚ¢OŽŒ‹ÂCšJ‘ÈïáÍÄ´vÂÙil PáWDð7jtüÀVáYcüì3º{Úeù þ|™;à ~ ¦œÓ¡“éˆ*™;™U8bÜ·[¹1µG©§é±WàߥsåÊ‘fìü¯ÓÜÈN¸«N°KǤ•ÓÉ~,ï< ËöÑdkÞÇ&ù’÷DÕ÷an¨O°ËZ&$°·´KÊ7þŒ?ßáF”è4Õåà$Cözéòs°+¢×Èw¿º½xÞú}n¼h7÷º:ˆ ƒ›Ý‚-Òýv–„Dh%Àmš¹£XCè_Š*œq/ß¿ß:Ep/Žìòt"åøº£ÖÑ“¯WC›GâÙŸ=Þq‹;ómÞêò8ö“ {µ¬Ûžÿj9H‡ 6+lÈ™Nùô̱³ñ¼V-¸VJiæA¡ íüž±_í‹lS:&;~ŠÛoiEõÿÀ ÍãBËÊ^VÜÐØá·i(Uóí»µ¥¼`^ÙàÌ×0ä/Â!w³ê~”9Óïx¸ì]5MþdŽÛùÞ½2J9@v¿4îµìÁÃÂÇ-æyÝâ˜×EU´YæMÙ~Æ'OœÄ3LJ›=OÇÅúyŽ E¾ÙùeKûCendstream endobj 416 0 obj 5414 endobj 420 0 obj <> stream xœ½\Y“ÇqöóŠ?b#üàJÓ身ìÐЄM "±Ã"ö'Ãà.I<þ½2ëÌì®ê™Y=}TgeåñåQýýå<‰ËÿËÿ>þöâÞgB©Ëç¯.æËÿ„ÿŸ_|!â-—ùŸÇß^¾…·y<5…9ˆË«giqéä¥õzòòêÛ‹/wzovÓ^NÎ9µ³ñÇÁù0ÉÙïìbòa6b÷§½š¬ÕÖìþ‚'µ6Nî>Ùd¾É‡`vìjr^ÌŠž½‚³^`ýîýr0 –»÷öa†+@ˆœãσ2s¼5ð?{Y^¥´ß݇+ ~˜ßâB»‡x(¥´v÷罘Bð:ìþZî·ç?ÛfœŠ›íîÑþ`à´Úò Åìºcýýê¿"¿=e$L}š=ðòê ðOËÔÞ¤;•PôÎC¾õ æÉ‰Òÿ /Ú=Á?OñÏ3üó þ¹ÉçÌì§àíî#üý þÁÙU@à< ±û_üùÿ Ã"óÒÑçù‚„y €°òˆ€‰ÎÚáÉ{õä»ð.9O³Ð»oëÉkxgü×E€j÷²^Ú®ßÔ“ÏÛÉëÉ8•Çnw[O>k.‡i=ãµÚ(êÉ«vòQ=ù |Xæv¯êõÛõëÞÉ×íðU¡ÒО2.à¡VnÀuV®®þ+6ïrøC{âÆ­rø¼½óÝvö^=ìÊÝß{%éÝíƒeÑÈ]ß Ò¦4ŠñR"é3Ê´ø`p•%¨±³z÷]R úð²¨{ðp£…7©ÝÏM%_´GÚ8+eA1%ÊtÑ«výq=ª¯¹NäêI);k`Q>ÓžGyŠÒ*£< P!£ùÐÆºB ÞšG“ÚÆÉ“Á5€|xù/÷\~:†K|Ò. 0ª6¾g’:A¦ÿnHP‹€å 41`’ EzȺö!ÎÞL3¸áªË¯ðÜŒâØìò•™ÃbR¥ÒQAÍ•}3tÜ3iè8mŒv´²Úùdz¼*¤-–,êÐâ `ÆnF‰õL~²“ v&æáׯW õ!~` 1ÄÒK›~>.¬Y™jÓðVkÑç0‹zðbeOµ~°î“–câd•põåÑi@)µˆ™¢¯AP<ºOÛuš8 qÄp¡)Àh­ûʆ×AÑ ãÇ{Ó‰ÐRXüÞgxŠå?Æ7ùˆãaIBÑj¸å§…AjW› |³pe}t§ÄWÙ~×û]b“š%]tëmp„€ªÎR$k¨ÌÊâÕ£b€oG¦A[.ÊQª`½}uÝ+/‚¯ Óž˜óJ_ x‡¶2A¿4ÖA¯¢£á‘Ùi€Pð 9È¢…ðÜâƒ=DF è~†w{2R¸¢G-O}SG1q ½v!½G÷.Á€a(cL@`­&¡"j›„…–ÚDŸåaJÃ>`™ ðLd¤PÒ©´ŽfòóAr¨á„ ‹Bóç$ò½°… o³¸8@’µaƒÅ´ –ˆúç ]¾.$#&Hãhawœp×¹å14ûäâêÝ/iºÐ%X —èÅ c•h7_Ôð2¹=Ãzöq°ß®ÁbO·ðü×íY±§A2ß1sD†§ÆÁÞb”O¬LŒ:ƒ¬ª€èýßµ³ “öœƒ¦€/Ö*å}#Ä0º‰b+)ĺmëŠ0š\©Öƒ'iõ´VD…ðUAÄ%eà ^†>e¡$WØ3 *¹–2¶IÖçeMô¡\æÛ»rieÊÒ¹¹ÈälŠLJŒÃŠL EÇ*B .}õi —ꥤ 11”“0Ú))  hy§+úÅZrü!œ„µÓ¶§Æâ4ÎSjž#Y´éT¨zÑC½Dº[ZÇ$•Ž"ìé9+A_7'r ;a{qOMZ‰en­ào åVn_Ó dÖ^šù²&)p:y̱¨*¦ø bÊ1PÄXJÈh*W™™” ;–,Ô³ÜÔ¸ÀМ¢/Zi¢ùj·†cÏpP*èkM—n¤÷ÖVžgõpNK!\GT8ÕSjV!Ï?¼R×p%¤Š!Ù¹)t/`OWqkþ9ùŸYÃ{mymb,Tc9CšŒ„ñT_x}“ßLHãqç˜ì8ƒ,ä®_bn:ò´sô„ ‘²zœ¶BKäkyàÊ)—›nlá²)¿3%ÂišpÃ+MÖI0ˮÓ~Bo§l8%È ‘‹šöÚ X'‘˜QêdÇHøѸm2¾æR Š 5M6¤çFC©”›’r.ÄZ ‡À€ÄŠñ:öOSüíã¤èÏ9ì9Z{>·B» ×µžòŒ*`Ä©ýŠͤKaÛSÑ”pvÝ\éàªÐjmóqì£a–ÁB¿‚õƆ†ÛŸÓ(„ç\ë}ø¬‹=%\‚Žˆ{¦_ˆŒâ`°¶Èœ`"r¿Ðñ‡©jw*U1=æb1x•6þY/¢ÞÔ>³мPE}bñu&å‘j25À–Ó!OXĽ¦šÃ-·¸Ètb¢åš©þ¯yâê4LUlðɘ W¡Lâ†îyãed$ާõ"&5› =Ç499— d±>(MÌO0K aëLÑéA:‹q•qËZhî7Ãä…®±ÂñÌABüî\ÄßJ‘íQŒu&¥ˆ0‘MAÿ,DD·ºõš!Ol5ë`ïNù§ly·¸é=¾ËLƶÓa‘ĸ+ù—µ‡HqÜÙ-ê•bÜRN¶ÓѤa‡% ë/ÛA2¡°0 …‘)9½]ú"á[tZ¤¢ÃÆu'KŽ.¤4{˜G.ÒF¦–þ%pêQ-iÈš‰"Å7­ôÙ³Š„N‚,š.]c3Z³ëk lWaxðP4‚—Áȉ™h+u… 4qiA¹Žu“AfÑb³Ù7n2p­Éàô~€G©/5k2h½¬µûÖxpÓžy^ úƒ*~)à,‚…ƒ…}ÑÜkW NÛ××Eòl#Û¼•žÂË»­ì5oðyÙr[¸A •»ÏJhÅ,ö¢F“S§Ã®h;Í °WÊÓ Þ“ú<±Ð¿"«-žZÔ‚A:-ãê×¹ ]<¢Õ²gPdglw=!ñ6ÄýÓè8…±×+iþ3½mY–n°AÛ^sý<¬SîÅãen Ë‘Kiã1ƒó5íŸ1Ð*.F¯C@1Ê7/± {étp‘M‚È_SøåDŽÓ…Éïï‹=%)2²#佚Óá=¥Ø|§»™èTyRdä¿¡tb³Žâ‰!l:îÑØ AP® ¥þq&³ýdÞm±±ÝŽÐX* ÚmÐx•¤à³ôUú3¹ÎÞÙ§°@.mE%ýÑXüPf¤zeîeEƒá/!båå§Ê’¯Lbœ§Å3M­»¸kÏ‹çÍÇŒz2²cÆ;±™WZ‡·¦9`Çlhé$ÃüöcUn°É ‡Cˆ!• ÒÔy‰f®~¯™=5Jí·g¶,{™#^6ƒ¢Èñ uÂjȹ°°KކuÜfZÃxWFZ =œ[»+U”~ecÜë×' úxÜÌ'0¾hqŽÑ­3¬pÇ@%ÜjF· ₸b1¿Úþ˹²Ikk×AÜbþ#ª9‚í;cãV@Ç—¬6š½¤4‘-Xù$ÚªB什÷ë ÚSm7Ù{íä'õäý6Òï÷qûYåoíûõägíäÃr²¿KB›Écga}iˆ»KP q躄54L¤GávåŽàU ‰‘aë|` è°®¯¥zI6la#áÝ¢·;øA$WëŽ,qsí«‰óãû0ÊÈFq{%S¿OvÜöÈ´%bTN{ P8iyP©ermÏ0>™™$º\´4R€¥áUŸŠ‹yÐJLâ]1á¨gy#ON^ĦQ=o&(~¾Ö8°ä{ËÊ=%©dÒ8"™<%g%…mO@é’°.B¸n‰Ÿ%{'IᔈÎm9À„£‡c%iöÕ<·Í}öHùM-„`äp»0¦¦3σÉ_+ HOk Ésbª˜¯«.)ô§„ÓD YªqPÕÁ¼*`uÖ+`¢u…ã=¼½ˆ‹ ´ILBÄE`²¹Ç{WE«|!÷ªÒ%`!y¼UŽƒàbšÂLÕ(Æk$hÞ ªô®›…\T£ºNéÇÜ@Å‘ñHÙÔõN¶l³ÁEÜk]ˆñÕ÷†ÔõüÎR?óF Lá°A: Rƒ×>¼ÑýƒX Ì€/:S B׿TòÇ4ƒ›CZß<Í ŸzAó×]÷84)…dzÛIb˜kï¼rÊ⢷Àeíäõo²rÊÏoGÚ~PcAs»ÇβP†˜£äè6[ÎXÐ{ ³ŒOúwrÂF•ž¯—ÅÑdâ£H©~b9έv~7ÊUÅèÿ O ³›¼&,¢Ýë~!Øüßöyß’)ÛYY†ÔXô 7—©~ ý¸ªR’jQÝ™““=ïòX ~ú¤‡Š.ôhãG/sÌ„ vjñHIÜãò;¬‡éøï8»Y:„×›[6{."ª% °ôÈê;]ÃÐJŒ]—R“œG§îšùsf"OI5)É”³^®@>zìö«ö]ð5ù[ ‰}\°Ý”ˆ4lÖú[ A~‡@t&̸⺇UÚy)©m,årKš•$’ßþtAÌM3´ªt´Õ‘[5i·Ýì]ÈÔÇʤ«š Z Œd",ÕÁ›Ä4`ðÙߌ™Ü8_ã»~/‚S£dqL"j}$àU±q´aÕQ¯jFµl4JõöºÑh-gÂÆnfiÃ9¡éCLF/ìô*ûÛ[±Òç”~ëŠ$(3zÍŠ¤‹¼ëm¤g\X 󆆜UXD¤#Vv|XY f*ŸÉÁ{|ê_~½¤\[Œ’¯æ~[ä ™”¸þJÅ·ðj«©7-€8»’fMJ3!‡¹òˆ•gNnVrî<•èNAÐëTPm@'{@E½…ŠdiÚëݧ7µ¶ëlh•ÄÏ­ÏäL'«‘â^:þͪ…¥Ÿr?-ÿ’1CÊ™¥®Æ0©VT?ÆîZ‰•aU‰Eñ¬ßЫJlÀµYfwK%V ¬þy bJC(Âe–¾¡uºJ0\핉!ë­'ÈîÇ—ÆU²ÚL\bÿuÿófEÈE?å}ò·Uzñ'iï§<¢šˆ§µš¬_ ¹²,J _ŬIg/|Jî;9äRw#`¯Ý—`ŸöÌ2ÕŸ·‘”Ðïö "JH:TçÛ`SA¹zÐ$S,l'ÉâLg³¢êd’˜ù%mY$æ$¡ñâ_(o[Û¤r“É*›Š·¶¡ÆßÑÃïçi !þó?£7ã'‡A¼ŸÅ ™Ê:¦Ç$Û´y𓌜ᯓà›íuÉ@Y»Qʾsý õÛ`‚TaÉ„»V/ŒŠ_l|ã‹›êÉg¦À“_‘ËäMw»àö¶Ž²Ë„…UÍ K]Bdâf­ìíS?eÇÓ¹™XžR_¤bµ#ÔŽs*¤«¼ÿõÑWYsòmýɽ;¢"ä.ÛZžZÈÂëõ·†M1¦ ýTÍ&ˆ)TA¿Ò®×Ϫ·jÞ§üb[É«¯¶Œ,ÚkG‰¯ùRá'kÞBú|‘/ƒWÒí óF¸šÉ:;[ J;çéÊÅ;orÞü¬×Eª6¾p©f~à‹ðS÷ ›ß0=¢5¬“’ç~¸A¦Èg»™!ç죩þôâ1faendstream endobj 421 0 obj 5606 endobj 425 0 obj <> stream xœí\YoÇÎ3¡±ðC²ˆ£é»;AlY¶ȧh'°kR¢ K$E‘–•_Ÿª>«fz–KEvò–V=ÓWu_=/Wã V#þ—ÿ>~qpï+¡ÔêôÕÁ¸úþ?=xy â+«ü×ñ‹ÕGñ5MCƒX==Hˆ•“+ëõ äêèÅÁwk¹1k½1ÿ8ú+vñ#í"¥”…^G'ðæýÍ¡œ A¬?Ùˆ!¯Ãúý\±9ƒÖÆÉõQ{çAjUÚ¯¿‚V`X‡S­x"e¤(]ÓKJBh·þ¹­]¼áDHcŒƒ‡!F'ýžX+TûñÇòA)±þl#‡q40ÁÇ0–öƒt"eF±þº>&}>ÜèÁ{%eY9îçÑæPN¦o ü„Ñ3ý8É3Õˆ»‰ŽW°ï­sëg©»1bý&òb0Z¯?Âu:g]™x„牰^Œ '•W`×wÒ:˜õsØôR0’†& ðúûMš ö $×ÊÅmÔèóFrW°~…­Æ8+×Çu€í†Œûcùq–&µp§¸¤¥k_a›<°h?h#m^•Tz} K”ÒAÆùãHa}S‘'/ð‰µÎjÒó¤íö.®\“¨LN§T!'>’†‹ ë– üY ÚDY„e`Å…°£[©akFÅ]o=¤áq‘¦¶ì‹¶ìëöó w(@ p¹F0¯çÓ]w·;#‡©È}9«`t<,T±ë׉䨴֓WÓÀΪýJ;‰:Ë-ª@&pò¬upsÄQÚX*÷•§qý)áéc²¸é¼(k§Ø ‰ÆìöãÖÿ~64¹p¸döa{'ê¾W5ô[ÜEÍg4ùcóCLþY€Ú ¼o¬YØS½±{Õhq~fAPSû¢ŒËv`ÎýÕ Ut=š2¥W¸«5"Ý~hŸ×Ñž¤·ñ™A¿žWÅo\·nÙP*áè*e2À‡2@Ô—™Q_V½DQV²\UžµŸÄ/ñ³-fÑÇ92xíÖÈ­5 €ÑŒ“ž0r“ô]á aäŽÅoV±qÊéÆôíÿ]Ùd½Ô&º3SÄüyñœL ÚùIÖ®Ü5QÔ+Ñ—|”œÅ]œãIm|ST4-—|B8A šÞvÅ f¨£•=8ÕwÆ&nã„‚ÄU»îB:O¥µc ¨(ÔD-î¸uÍ=ñ”wÁï¨9J\f=a=¶Êë&TÇèÚi¥£*Ôðp"/³FG7ázjÌÛÐ3é4q+ Ljñp üç˜ðíg5´vÎG“±Z[ë5%@K’]£$eG§iáºPéd‰ïb—EêÊÌWs îYfËqpòEL*•þEÄ©úQÂ":›c%"òÑQ€Û‡/œo€.£Ð ößͤy>õõ3h˜Œ‰èæ<Æ‚“1åÕP¸„*}ds§LZ0²Èg€<œ¸BŽó3•¹x×÷1 BþDÀãb8r®,€$>7Ñ8ÁÌZ‹ æ ¾ð/H? Ég: QÊ·€DÞ«I (A"ùŸÛ °Lq Ìßàƒ±ZÀû„ˆÓXVo‰qä°þºJ`׿%BõâΊµ€9‘ŽJÔ“äû‚SÐÂú…À8s !„‹) !B„fRXQ ”‹ÁAxÓWŸÆxŠKCEjú&†Ú"ttsæ¶Ö¬ëôjLÈ$ôîx#É)N¤áNñý†ÏöˆÍ¢H†Ñ @Ô’{”Ä¿FiØ ³¸é°šŠ&Œl´• Ñ&r‡™Ù¸hâ–Qs/§.¾pïqä‹«qSÙ¢2ïøÀb*Wh÷|ȲӓQ[$^3 ‰0Q,F;T©h˜7uÊ5D×TaÌÖ·ãsس±,5Çïù§2èrRY+QÙ}"¨0`Aÿ–2•Ä#’ˆû¾D{æØP²g`Gá€7YÁ÷€ò# {n¹T&]w†rÏsÒ @oö‰©%Š0s*4+^”üšÓÐô]ìÊœqNîö'‘)6$hÕÙÒ܉-+<åhsÛfÆðþ,ÖÚxC¥eÇ*æ*H½ÁÇI/¼Þ`íÆÂ¶ŒÇ¯pkè'ù8žY”‰Uˆ&¨c ÂÔÙh¼ô‹Â€!\üÉÂî%ÛŠ\íâ¬ÝÑ®b-Aä°/ßM¨+‚ŠI/GÜ…ûÏå¾rã &TFSèM™¦Åý8ÛM®íϹn9 ³ VLŒ°Ó‘ëI)Ï Ñ¢(ôÓ{å|ö`+;Æ,ÃQ’,z‘5üõ¬³ŸWé|Ð}¬ÜŲ#žÛ„“œ¦Î=Iv$ŸØμ»e6O3/=of’WÀÌ•¿Ö%æÏ_,Ah|_XMxìùàèà˃—+¥"þW˜+]y¬oñ+X¿F•_<<¸÷ðÓÕÕåõ“ƒ{[‰ƒ{Ÿà|qþzøáêw®¾¼m=ÒÛ'ÂÄF, ëF×²Ó Ä⺅ü«/\“ç©ë® FD«Ô(‰”RcLõÜ¡²Z@_ÓË´züMNFX—ç™L×›»ñ`€{›ƒ ¨&غyQE Wû¸É’ÊñXofäBÂRÙ“*€JjeW¼Goê¶C¢$9Û'П\@©>ίÇXø˜_3B;ä*,½H*‘ö[Õ‚å FØyì½_p… ùëM.z|´°êo6 αJ(€$À¦é÷ ž/ d;…NYw²±¤^j@ìðÂM÷3f¬\Ä'ó²\áãE·t¹ð¦±.V`"b¿YHhgB¶“´ªä8©“Ðaì–í:‚× ¼ €*„¡ørËa/!Ë›Áô,@êxùOë«Àà`—}YœVhâM  s˜#hFZl2gø²K\0¡æEC=XÀD¯¡ ‘*‰ÈÈ„½oúJàF9”X†¢“ðüŠFd?º9ÕÑ·£)aFmP'‚I@¾XÑCˆà÷h·®.îŒ ¼-WM2M¸Aib±,ÑνB9&1Âcb¯“ ̉ Â1«=Ê©rèÕd?Ò–ÝCkdˆ¢L1gRbüµz/Gåa¨ÂÙßÔRy»I‰0N‘Û'ÞxÊ[J8/Âç3<ËJoˆ w7GÈ¥£ÝÏ«ëØüÅÚ{w8¤ èñ† –Mfax¤Å^”ITÄhßb±’{øòN:s8EX¢øà“dJÄ|H ¶Ž×óØTÖÊœ‘šHÞ©¤ËB“J1h¼P·@ø˵ ¥¢gÚ­ïqô<’J”u;<|•eÕn¬T‹Î^ÖœOS ú~WgÕuϬì÷2THOŒAý—"ç¨õŒÆØËBŠåÑRzBw­›LKöÓŠ)Í¸Ý áù¬-KŠŽ„<檤sKQóLõñ{Iª@mÕ³fX¨1%eÃ>NÍbœ´>¢è·É`ݾn ”Ú|”m³Yç!u£bÈo±4*¤ãOz7 àM\ ÖE%ép,‰; +?Éfͱ$raGOôRa6Z×Sf оW´ù,¿)Ã"([J•w®}”l~„u2-h”eÄÍs¼Ó3õ’i"½Ó7vNÇÅÓŒQäfê0<ði–³IŽæ9°Ù¸Xd»„ú·\#0‹™‹ z(°{ª_¶T§_¶Ë¾™Ÿº}Ž;ff¶W‹zÝ®M.1ҤĨúßÞý3. Ä Ä¢¡ÇÎŒ­Y©ù¬VgÄ”s$Ÿ¹uCìæx!ó¤f™å³–°<‘õ.%ž‰R"/·6;E‰„¶I;n¹]AÿL§Ò¢®(ÝBÔ¦RÂ+õ˜ÙŠÈ:†©odÖ™Ýò柶Žß^yËkdZDÔ^Ä@E'£—ooáOt|g„Éi±œy i @–oÇ̤4ÙÓÜ•ýöe-†]÷’†Ìºª!Ó°|ñùŒÏ…©uç4á‹·ËÊ+ NÁ©!Ôe«Åáê•­šâ¢üêE«ÒâÅèN½# A7‘;/àè«5mv)·èª´NÏ'º—¼ûB¼ö¼|‹ ´[©štÝ  ¿ù}¥wŽ^>¸Ú ½’ÚBýÔ¦½™ÓO0ÆÛÔö§ÎŽv9k/Æë/~p1àí§0hWÚ@ébäÖBÞ¥0¾îXI_n@ g_n@X 2 ¡sZUÜÞ8ð^;rù€,ð´’.&ÊÄàÀî‘=Òoð¢Šèÿ.I(+´ÜçB ßâí-QÁFÏ™)Óç9÷*hD©[ì]„a1©ŒÎý;ÉD(o££ÖUÀmœë™N@\š©*%Úµ““Ûg‹U®Ýಃ‹¦xŸXn*s@dP]sàò’å¦Þù£$lRáYîŸ`&“¢r¥)$<³è6äšýÌJbœp~Wij¼ ×¢5¶ÅîKåO! · Íû&¢€*øõ¼­[ÍËõ'×Fò%…EAÆ"é R\G¸ø¸3ù ZçÉ>Q`ñ„ò h¥¹MÊÌ!¸èTkÞB æRZнö,Jª+(,#F£B‰“ !ªÜ±‘žÑþ·&Ó¾ç\÷€zãØ<=˜ËZ ½_$*fUû,å1JIãÏD”Û'ý s¬2´lÍÄAÁ:'Îôå¾z öðð/äæe¥ÞíÍÜæIM)/Ÿ ãÈê¤zZí&ƒ´!.Cö±à$%”oçà)¹9Ó½mˆh´žø)¥²]:î:ªGú‘”ïNzR¾¥YÒ#~¹@•¼Ò¤­o<˜ä/k´Ëëy´kr/(¨¹é a–‰ªš˜‡™ÕDÙš¤é:©ëZäè&;c™Žmɦ(˧W¥6bîÖcig?ÂFR;ñË ¿çT£\~ú9XªgqB¥©†áˆÅ ¬ZùbµéÎCQ̶SWaò)“«À¿Ðß3Á•9ÆüÖIùH²ez]¤xÞéK ÿÄ"µ¢Í$¯àîÒÓËúrl;Æ?ÎkÛeû¾ÈIm¤ŸYyZ[/ØUæýÑq7XŠœ&™}f¥-ä„uŠßf¿à÷õù«ÞLÛ^#ù`K#JþÒJü;5%ó5XŸ«+´*úõ‚Óî¬r•CåOϼ‡©ô”>{Pû\Έ™6CÛ{ë¾ìÑò ¥îåumxÖûÎsÖµPôuoèéw~LçtS¿›óe¢òüMm|Ýo`­¡þz¯=n…‘Jòi›ü%ô™ë'ÅÎ+áQ Æ“-òÄÞû5d&õ8i\ñHGü’{·ÒÑ%v՞ɱݥ^Ušm˯:c|Z>t'›Jsþ/}ÿ³Ò++¿<ø7")>9endstream endobj 426 0 obj 4983 endobj 430 0 obj <> stream xœµ]m“Å‘¾Ï{üˆý¦™ íÐõÚÝƶ`ƒ½gÇ…¹V»°â,´’Aù×_f½fVeÍôH"X³ÓÝUÕYùúdfÍëËé .'ü_ú÷ö‡‹ÿ¬Œ¹¼ÿñbºüüwñúB…[.Ó?·?\>¹ÆÛüê°N«º¼þî" .g}é{Púòú‡‹¿ïìÞí{}˜çÙìü1…/®–i:h3ïþºWJÖÅí>ÙëÝŸ÷WÓaY§yò»§û+uX–u—žìíÁåüîóý•Þ}†W­µ~wµ7pAÍ.¸Yïþý®ÎjµËîz­ìî÷ðÑ,0«‡¡aöu±+››~þd¿N‡Iée÷?åÞ¿àî`NË\Õ4Ã|WFÏp‹I«Õ~ɯ±,®ççé¬Ë Ä2F¿2n‚eõôä ¹)ŽfWþŠ^ â «ûßë?„½[è¦Óûr}{¡ônî¼JW®Ì„äYã ŸÀè@îy¿¾Ï~Ä[f»û º,~žëÕ—e»{x‰Éì`¦ïà#,Åšew³'ƒ¾À[\Øü4–V»çuˆoqúà`®Oã–)ñ·¸³wŽòÅu½žá9ãü ÆZÖƒÖ:¿Âìušv6&,¬þõ¦.âG\ä ÷ëÝ-ßZm,¼Œ¬`ÍîNX¯ÞýkïìfhÞø ½9VfX™õº„¡îa€òý¿ö&|Räù—H^,˜ß†C±›É 1ªâ¶ëÕœV™!ØhùÎ;\ð—ow±wVyí«³eñÞgêàõD³ nˆ„œT¦^þ.¼7jN‹Ë/÷ DÎþpÓŠÃj¹ì¾¬þOøcVq­H³ôJ’%?{K?–©ÈÝ‘?¼žÖ ™RW@cç' vSgðŽ"_9©€Ñ)SŒu\~mdÑ4JôMZx¨gü$WD@âTÀ| ›f¹ÄµØ9¬e$Vy­DÞ¢¢Ó ‹«20ÖÏ»gpï‚Ú-Òµ×·i2BÖ—Ÿ§ë낼à€ÔR4Fe 0& gÂè_ï ÓÝI£T¿gGZ‚¦³–i«ð•§WÞ&Äù>ÈŒ™ôAù,2Ôžò~½Ça×Úfw+§ûuäÈ‚Æyd¨þF¤Ž—ì”|OÙ[n/‚Vo~ÃD<«ƒV+à(w”i}®,³²h» +‰BATܺDB‰&£’ÿjô­Õ;·*Q•:ø°hÛˆŠõÁº—M'\úJÇ=h8ªga`ôÿPš´; “A*ßáÒ ÃâŸÏêŸßW[ØJÌæq:”Lã4ÊfÑÃÖc ßóÔe(ä,KÓjƒ Ë×3oãÆ*°œ—ן_\ÿ×ß©©mȔ·°ÕÆÚðÂ=Yñˆþ%êÉ$³ÀÕ•ß;IUŒãæwßtS½"Ò›,€îbÚ"®Š‚Z_$ßýÇ… æ’Û–*»²¯À%'(k}Hï?¯hµ€Ñ‚£^“ÑTée=5v0Š:ñzD¡&Ì[áUͬ¥Æ¶üÛ^Ã1…êgXèîçêñÍ[ÞíÞÌa?ž—í—æH BÖË…H)î'T÷¼zÉMƒmnZÙí5˜[¸.« º˜nbÎCUHâ>¬*ˆ$õ+íýÊÛ"Sž>07þE¢D:Îëª$× ÷‘Õ¿â3ªÝŸ»˜`Ñ,Xt¤—|U?¾¡F^LPf‹‰t²6ëW;E ±wXÐŒÒ]éåà—âJoŒ)Ö¨,_qÓðÎŒn!vF‰¼‰4Ž›ì˜M/õª²0ñê¸ñyÔ¿#£¸çq¿ÝrüÆäFG*q߀¨pÂÛÕ“¢K” ÜmaÏ\–m4'½5}”Á“°ó/ÑÓÕllG°·ÜK®Bú¸ÌžËEglj_£¹÷EÙ°M@” ¹OŠS¾£ ¼• fÔ\ÎÏôv¢§b(îF!º5àˆ+?æô ÌÜ6) ;â–$E9Ê´½`<Ûn “òµ¥8;0c‘Ÿ‚sVèp­*zM'ha"4dÍ(5°zš‰Ô¡2·Ôšb]Âtâ–ã·Ùy©“v~Œöà‡À”yBÑë ·rÆ%Fž}Ø¡M\gé¼a¥µ< ÞG¡›ök0‹ßáfâSkkq›½?ø™>c "!Ï€púÓ*yÑGá:ð®ëõ ¬Qñ$p‚´˜gJ̳†0UØM|µ,-„ìgÙ= ^¡"S?„F‹a·¼Ä˜IOªÕè0.D‰J¹ìÝ£Dt”ƒ,S¿ýK”Ü)Ç7ž¥».W´`eóÕ$F‚ÜĈizÆ-ÉóÊžÃÏè©xMoDÇı%¦H»'³McóÓšãFOÄ`M 3n^Å ¯5kÊ‚¢Ãà‹á1²ðñ'¾ø­~y ø­¥¬Ïdn ïœaNsðT¦²â“üPÂ`½Ö‡uÕ¢‘fÔR>P«`-,\¨1Bý!L| t»>˜(UÕñGy6åðM2GyÖMxKW[)ä)PÛ%b}Ž€*(d}ðž8Ê®sA5Ôi”r«Ðð¬(|'Dé8F¼¬a©ÿÁ&…±L‡iâ*8ˆH¯W¢B–PRj‘N„Þ oG,ÎíŒ*\•ॹ•T 7U)’Y‘–¼nenrÀ6iÔŠ“zÜDB¼‡”Šw‹º»˜N>ƒÜ4>2Ž7°oE  xÚ~kŘ%í>øñÿ@Ñì“¥"¢5Èæ (½é'HH€êå&cw ® ý#³TÀij´ˆšºAD™A²Îæ^·aˆÚèƒÉmïNH‹uÈ“„Ù$üIÀè´9¦ŒsüB`‰H"k?ˆQ1té¼És¼¸°œ äÑâÀÞg’‘•¬ÿ§…®6ó†Á ´€ßÂ¯ÒÆâã¾ ;¥¨\~³ ™B ۘ–lØëê R@ÇìÄ<™$÷Ôš,£æ$`È®²UÈ) ô`Ô‚¢±>Æ:…—ñP0¯€D}™]¦Rs]ü2¹cà†þŸèv1},ó´.røOõ=Õvf"ÚNmÕ¹qx“ßfY™ŒOSòUQ½hºh/>Qµ*çÆûB[¤„0†»<õú Ô.°†Æ0Ä «F¸;ÐŽÍIZ#‘\‘ QP³„aM®‘Z£LÁåÞ[Û˜|CS¾q3iÅÛ’Ca‘ñâxj[Œ¥[ÕÈØb£Ñ˜-°±Ñ7‘u%µ-ÅF øì5f(ÒKLÂ1gÂgÅ¢‰1jW^ç.yßvæ^Z$Õ¬`æ]NÃr ^¦gÂtÙ‘qTzˆÃ´9 $ûJ|NQ,òËØù¼Ü ¦Åœy` ù¬:Gyœzû½dýpì‘: ¥QÐ͇PvçYq)#w2H» ÍÝÊ )i+ÈÎ 4 žÜ; ùî&lB¡XÌw6–xa“S‚%^+Í2\êÉôQyb$FØêÆá~Îܼ˜$üL)A/ÆúÖwƒMrþ–šŒš]¬hÓvlE¹MÆÌzˆ_˜ë#ÎÕ¸¨]1B®2ÕÎ4Zk+S‘Qª¾é‹Ð€§¾Þ%+=ÌŠeÙÇ‚ÍZc9Ì<4îX«j»-¼|#ècÖZ˜ÔTŽ­+x¾ŠÈ¬ä‰ÞJpBÉÖÌ)–ºâÖ7‹[_Ê}!Uv+§’268mQÁ´­þP¤ìi’}d7¤øx‘ ¾ õ§˜P^µÒŸn >?¼úüd7z“Ž÷·£ô–ƒÉ_“WNzþEeC¾ü…Ô¡I˜J“Û:ާ¤´u–®”[ú) |%AMTÝלögO#QQœ#“}š‚x- ƒM³ššÄœa¶žfÇØè?Ôšù#¼p'û›‰-¸Y?¶¶1g²'Ü[1«#*~¶ƒ±ƒ_UÕ:ÙÔ¨S´™åéŠå¿h8¬ç̺ “èS¶Ôîʳ°²Qé/ìé³Ñè}Å»1O(—¸{&F˜"g梃¤a¶–íYg¢‚€`Ýy[2d ­Åtì÷‹ACœt6<ž£h3ªÖ)T£Ü·Yf?Ä¡­}ä5ÇL ‰_ʪ'¢D p°O/ñè§ó¤—5 …6ðbÓ4íÀ3Ƽ´_%>Bo…«™…­¥KùÀœU±Fb£+”(JŸ6$wfŠÀÜÉù­­Qb61‰%ÄÈŸ]_|uñú¶Ì‡ÖXìr :Lßr ò6ã¿·?\þÛ¥ºøø÷øO¾üþyú›Ëÿ¸øìéåWã6Þñ‘Ûp &qpšƒ^b'ލlRÌiÝÒ’”±¶ø.0@è!ùÕß+ÿW¯ØÛl4£Iý÷î{!ÔÃz!ì.»xŽ¢ˆZSë^+4úôX…”q6¼×T?ð „9tM/BmoXá!‚kZÉÉ‚ =M”sÆ¿‡fYθ!¢b×RÖœ—a·³ç`C4BQ2@='“d¤6¥bXd‚nÓâ"•Uî/²Ü°YÂØL9ÄL<Ú§¥ÇÚÂÍ*H˜Ò¨#EmáÁu¡ÔaÖGÔ/k¯{Q×ûë¯{Aáaë>e9xÞ4³î}Äq'ªøþ o}@ô˜AMÃêÇÂ@ÛTT”ÂwóºÛ’¢{gœðyN9&m‘»ÇÂ[yš E]Aa"Ü*{©xò:´ C,“ʸ‘…{§ÙNè1 ·“­Êw¼‰B¯Oíþº_àI‡njÉ…uKàµcÐ’××9àªÁg·+ˆa¾ü-~òE±qlBwðsüè'˜;]~V±Â° ‹Ì€EÈÚ†ª3/‡"‚OКx‹´qAžÌìó vqxí|Œ””ÑsLm™H»˜´z´G/Ó¸ Qžà¸Ú(?§ë“µiYf]mOˆ0WÇ#.x4SÀ^äÖgõµ^”IËKÿ¸ÇrVVîU·›ôá@?ã}À¾ÞÀ yˆÅß®~Ù`(oÉhÌ¢=Cä’p$ˆ'ß’{‰ïü*3éH©ÕÄͺ{ ¬Þ¢{–®¤ä0oêŒU&+­l:Þºò}IÛÙÒB,Ov72Ç7qZT&¬–f€'Ï6‰°=éœÒ Ô¦G¬ãLü/ã& ì’lvìY°(pYI‘¸Ê}VÕ­´YM™Æ[Ä3ç¦-ºéº4©þˆÖ·hÅBÆØžÜuÖI›OæÃgY2)¤9•„è5E CˆU–¾A5¤Ä¢ÜHšKáœæ¨EvÈxËžŠI$ü-jâÞñOA¹‚(ÝýzIþë½µ΀ÃÚ×°ÐNÙŸ÷]Xxè!aƒØbše„ö®àxf•1!i §‚qŠ9÷Ÿ'²¦uÐÙÈh9¼Ü7…Åñ8ÒM]GO]·øñ¸l}½/7>JÕÆ6‘d…xSzíp!_Õý© ”‚Z[àý—•SÓBð\ÈŠvt9YÚ+¤¬¥¾áªåÇœ¼Äêßf6i˜®ók°JGÕ£ ¸¨Hßr<›<«žF§]hïtßß$µü‘{xmÆj¡ÛÐíþ€”Ä€öq¢,–CA¾ýÍ>TËùKCᜟ„ÝÛ~u˜›q~ Õ.‚)Ä1mÖ<Î¥R_55¶±~q.xzê€|ÇŽè`¼5=H  +†”|”ÒÖ.’Åö­Ë“lõ}±8µH÷$â ¥k“PbGTʵçÊU3Z<ïì1äê?ICê ¤f³VAö“Ü+©†PBå²¢Á.8îå½<•ái«±©M¿rãÆAÆè’X`¹ôø—UH2N%~™„ö›ŒµÏˆ^²Iö»+ Ù;w®³”[ýXu¡X KŽòhj ÑwâÉÛÆ«N~œ¡uqÄ1íÿLªÃjA÷HŠ£u¤Î.ÉuX!®Ç–<µõv.W#ú›Z(¸f ©GgúTY2Н'<:Zêÿ„0 Cã9i*ôž°ÆõÜ3fhŸ·«Ø3oƒ›ÔBµ}¤êœ„>’ëÌýƒE ˆq´Ï½™[„ Œ4ë±û˜R³Y†N¤U±ÌaÚÅtî²ó0¾Ý„ã=£N\Ü‘óªRr»G'g'¥eci‚!1 ­ÈçœßÄv2W‚ã®§&ô©ÇËpöµ½gÐS¦Ð7š^÷=ó+Øž1*fc"¶ø¦ôó½ÏÒÊèÖ"¥L§:Ý´Þ夈Tw=ûT&Üxðd±uÓÚ@¢—>y2fZJðÈpäeêUöÕÊÍ£Üt"ͨØåsT±‹åD÷è.&¯1·Ô”¾±¸¡6SÌmøvnV$ ²Õe-‹—gFžL<±Ñ}$-›ÎŒ pÈîlCRCQ.FÇ÷Õ{:W"¼óÿ\®Ä¤K{zê­ÉIG2máí/âN‚Véòk“¦×˜›Å{ƒu KY&ƒýÛÓûÜ‘£K·žu‘ϵ€—;Ʀ¼ v̦Y—E5‘‚³ìÿªÉßÕ#ѳ5­pÒ5÷Œ’}8¬²6)¹Xñ*ÍŽè69w°"iSú/ôÛ„ÎÉ™æëJšhÄlT#AÞ\Éçöa=R³œ<òëÍLÛCø z¤^QpiQ4XÔAçap‘4e×îÈ–Íé;N1/™¸,¦‹:»Œ=dÏi?ênpw”²G^=&/UW‹89·ˆÂ¡>os); '‰8Îw˜â‰*§4 ØÀÖ][NªUö~•’MG½‡D‰Æþžj’ßžUËýNJ“š†Ð±§•书²‰ÓUÖÁð«5‡×7Ïò¤¼±%N18þš'uSçy‚{Á*64l(ÞŽDâ¢BêpNÛD¬>±ñ è¹n;»T*½<~L³Š þĶ‘ƒaâ —åˆùX”-gÏÒš<Ęý lÍá-ª~b:Ç`šóʾKW6W´‘WÝP1‡rCaa¶™ãÂÂ4K9µ—‘HØ¿íGcÊí"âBØ/¥/Vh–~ vEI±ôwÞv®âæü<Ýá>Ê¬èÆºZ©Á㎺Á¤F/lÛ°_·‰ÀmäHìÝ)<¥ý¿÷ñw+0šDÃÖßA(&6û”Ûß’HB½f€hÎ.ºÒÚ‘ßi‚×±Klƒ „¡Üê!Éða9ý![?½û\ŸgP #P/LfÏÀíO¡%} ž‹Qœx\ÇÏx^¬Þ9ob¶$áZÇ3 ÎñÇBÖH$ã>ÉÀ”ئE,ü $Aûü$2~OóÌãdúߨhvKNa  Y> stream xœ½]Y“Çqöóšaÿ…}ÓŒÍmvÝÕVø”(Ñâ±=ˆŽ@ƒ vI’è_ïÌ:3ëè™]` =Ý]Wž_ýã庈Ëÿ—þ}òÃÅG_ ¥.Ÿ¿¾X/?ƒÿž_üx!Â-—éŸ'?\~rnópiÙÖM\^ÿõ"¾@\:yi½^„¼¼þáâOy4{4ÿ{ý_øˆ_é#RÊEYxêú)Üù›ã•ZœÛ6qøü(–móz;||”‡/WbÑÚ8y¸®÷|¯*í_ÃU±ÁkÝAÃp ü"å¶H‘7)¹¡ÝáøÛÚÃgGxØâ;ÖÅÃ+Vý~±V¨úÇ#|—ß”‡ÿ>Êe] ð¼KûE:‘ÞeVqøŸò3yæ·G½x¯¤Ì3Çõüþx%›ÓŸ¿9^øÞžöoùUÚÀ+µâ*¶¸a ÞćŸaZÞ[ç7ðÃ0 ,ÇËp[ú &úLÙ9§O`šZÃþ…^æËå_`Á+,Xù<ˆÞÌá®zО֫|ˆg0´Ùc6rñE½÷b1ÚÐTá¥ÐôÜ`‡a¯2‘UHëà®Ã÷xÈ0O ×!•Ưð˜r›=üýˆt!Ófüt¼Ò‹Rz“8kéWóð·£Ñ‹³Òóx3˜©†‚dKɃ¿Â©m‹V2-Ú)Õ.Ú­°)žüŽãþ¥Þóòˆ§»¾êÌ,d åè^ã»lxד22\ðkÜWc庥)±>-4†Œ£•[$ðÑágçàM/êÏå‘Wy³\Z8ž´›Òú4¥Íè´(Ök¯â+ð‡çaùÍ–§9aÉCdOp./ËyV¸GWi“®„‚e®2îUÙ‚g…¶_Uþx^‰È– „çµÍ ù1Üc)ß„ Àò.ýþ¤4çÙÍçCxlâ†}J/VuøJgI"ÂoðôuÝñoê;Ó `›ÒÏQêü®ãä—8Uà E%¾«"‘Îj² øc#2ئ"C¯n©T‡·þƒpe}'cœ<Ÿ§8Q.EpD—J¸ùÈ‘Ò ÐTçÿ•—“q‰ÅC·pè‚Ðë‹J¥ävv5±®ú6ÍQë–„ÉmáY„¬ËЊ²EyæIþ£\! #ÜLÆDþûåèAZ/€°ÒH=Òvö0›»–Þ脬̲yËY"óJ$¸Ç-ëG}u”ÄÐ5ƒBzr¸*/ÊÙž$nŽ ?þ^)½œQÚ Zø9ªVXés÷QZ8þ¯ñGäáSœ¿Ô°ÅŠÒÏ Ÿ52|¥³Ÿ£_7&µ¬B+G½!Ê‚°U'«` •HOö’žÀ³ûÄÕï/®ÿíO‡OŽá …,{º½ŠÇPåÙhÂĸ{/ëlÀ82`‰©ÚUÒÈ^ƒe3à6îëI©˜hç1׭ψ|(çCè˜+>ò`ý[ÁýŽ LäÏ:ØÓÊO\ŒN…Ù7Z,Ij§ýµë6|ê'œÌVϵ»:Ž2Àã$¸ÄR,_¶…NÉFe:ØYIŒ>WPj•ŒÁÎV>¨W£è›’€?_Á›€èV?P²\w`N]4];Ц’”¨?|nðV4<À4”°{D½Ó£`zI¢á>r}NÁ{ÒÉ™ïSaó;òÌz<Š]õa`=æFÓŽŽˆ<0š¢xá6öà57A°¦­lTp¦„_ðýU(n.ZßFÚbšó¥ù³L€ÃÓV($!¦V4æ_¨È3šÚºÈlîÇU_xt—‹_₌4±í#3m í27íÙøy*ho­`#IM ³7•à)ˆ²–†³Aâ«hÊA×g(Ç$E_ì†FBQøÄôR`Éu®ò"N÷éÀv`†=·Âvq+ 9¡+0D¶Itñ„È6ÚnD¾YE«HTã`*×’-€²ÞE¡Õg»º¬vÔ+îq×%/ä CºÎ¦¦¢òþ&¼c.á“i¸ã¿1{ÇùMb¶ƒÀÑÞwÖåÓ \ «ÜÓÞÞ£Yl1”ói{ÛŸ;sO¨\E{ý‹XÿÄ`Êö$£½Šz4‚;š-ë[˜ì\¹J;4U%™V™Ýú*»‹žP#Ò˶jl60Š0¯Èü=tÄêlÞ~¢ÅZÑZÔhx8¿(3·éÒ9®À‡àô7:"Š0;©0ý^hFâ×®‹X™1 I¸fP9<ŠÄªAþFœB&MÈ dBÌhÛìÒ©Â@–ÑñÍX>h”«Q@y™å_ꃅпYEa›¬Ëõ„.“" ûPÉS…K¢1Æ>'åÚgÈŠQO˜†B)q#¸–¨^!‘q܈ÂU6Àx#Ñkv*N9&£íT­¨zø²„NPœªx¯„Â~8¯0µ†š¨Ñ/ÑD6­ >’ù«.ÄëßG¨Z*qWΓT††«ÄÛê¦ì­KXrª¿’‡0Ä/'íâ¬X·ÑÓk42‘]õqätáÍÞÊ#+†^ °¢a2iZ€ÞèSfV‘ñ:3?û+‘0Œ¢Î c¿,§’îûÃuG…Ú«êȦ¸#4KöDÖiOA†bš‚ö!¬F<”=#»* ü(DZ¦DlF—)^¯[°w-2ÔÞrC ç!‚òçüeÞÈÜžŠòÌÚ‘Åh8ù‡m³Ù)æ$ÿ’8Aé¾)ël"©Ž:h( ”ë¨Ådb…ÅÆîYtþ6±…—E"{f¼@Š}3à±×¸>¶X^YAI«Ù$cw±ª¦Ö«Œ lÌCQe”èÈ™JG6O; ™(îg¢! I„ÖP!µD’õQì$ToO ÊÈPȤFŒ„Ѷó¹ŒF½·©UÞÃítFcY1>ŽBm„f7äÝ­w˜‡;|°þ¹“#}@­9‚¾¥áñ >½¾øêâÇK¥€µ^Â>øK{²¬þÒ¬`ryäO]|ôè‹ËŸzóìâ£?^Š‹>ÇÿûäËßÀ?~{ùOŸ>ºüê®áeäaÃ8h„sÇ2é1îæËPÞ¼Ÿehtߨ2êi1ÌâÔü;¤3a'"0†àâtx =A þ)lÂUôŒÑ®1ÙÁ¨0VÅÌÆ(Ç€!FˆMÖåH/N4o » âØ{RƒŽ åm  .—ȸƒ  ‚B·òØøàÅD7>Z¨Ø—¨)aPC?ÐUcT–ÈnÄdC$RU üGç³V˜º1,g!ð<Ä€¾‹áJçý¿“â‹•ŽwD”“IŠ2 „[™¢9žQPüyp!¾ÙŽnBðziñ­‰…ݹ9b2‰Û:Jò&¹ïTÚ8>ØøQBŸ–£‚l´à~V5Ò‘ð ôú¤|€ cVø6«ù.¾”'¿Ìç0Õm'°x¯Ghœ DÓxU²ÀS–úI#»¨?ZG’¢Þè(qFA%LŠfħíL„—Š2êlØn -ï<"tVV1ÆE(¥eh¸zèlp¨ü^Fhði U=c¿lЦ•îEyóJwqF}•š@†’%(<«bèfnm1V|okÖ‰`jkƒUûpf Ã¤™Åë‘ØK–)oSC¦kÔ´±}kÔèIò5î`ò‘<=÷ ›ØÜ®BÍôd¶Æ¦ÜPßX* ‰ô¹)6éXÄMp(j|Âq„…¢À€ß;–°YÕŠã3FÖ18Ó÷]ÓHôˆ¯tÏW$±þMcŠUðcHk”H3L4Sh˜¤ªe¯ôCXH2èµØcÀŸYk‘P˜&'‚£ÕIÖQ|˜¥^=ÈÙÕ4ÀT¯ŸoŽÄzÆ‘UŒË3¬5€rŠ:ŒfpØ-Œº50&C0ƒaP7YæQC(ªIGêóEe§ÓQìŒr-è& $Œg ŒAÊÑ2ƒ\AAöÎÉ&µö!yNÀçîx[ð&T„BáÏ·†:1îPgX¨Q§±Î0_fÞ’-i‚pì¹jéÖ‡|YR3V-2K hbà¹1nЂ5»PÎY–aòà˜¿O£DTeɈíŸÕ¡Ž]ÿ‚Û}}”3xpó÷(MIÂÀ9îdL¢"â\“zgÎ\æ#Šÿð ŒQÆ qÔ†IKõ/BÞˆÉzŒK^´Œ˜óˆ’1?ó£TÊY(MÎwV–ÐÄø2 `OÁzâß¾NŒ‹ÂL¶Â«ŠZ”ä$“oh¢7 ý(–YñJ޼ÉFþGù›Óuú˜sõ\c†ÕJQV¢’ˆ™/±·ˆn!:ß3lµ¸™œ™Pð®L•"7±@oŽÐÅÈ€òž&±U‚#T­¨’G€rF8ؼ*àÅð=c‚ŠLJù'¬çDVÙŠÿ;¹Bö3¸ BŠEı6¤ $÷î‘}é¼ßË:0c§YÇÚÏa}9²¾óÁM|æ6Óì†{Ò(÷ö‡½óh¼=øæ…0´¿´"aâò­ïa¹Óh ¥ ©:Ÿ+ªŒ÷A¯:`‡|®]ZLD3A2F·ƒËø$Ù¾ý‰ÃqÏ“ø]ÍØù(Bo çx¡K•ÿ£§ªï¢ŸauÕÅÑ8]Iz  ñhOa4’Í9, &˜õêíœ.΀/þ`xë$$«o¬ ­!½TM0Ûª–}Œg‹Ü7ÀÉHa­$ ´- ¢eõS5”'$ -ÀÉU(Þb(H’lpjÅó`OÊ_ÏáQŠ·+EL8º>Ü1Äšß…»"ì"¹÷S9iEµb±5e¬Ç%á¢(¥Ø, à×#Wm]:å;NƒàN=Q$'ctùÊ,±).ÚJ;bú¶#•›²Úfõ¡0¨Û”b¶ïºžS–]W!/ƒÇËâLæ]H I˜•Ђ³3òÌt¸üÖyf í3ø&¾<æî—?ï„”´Þ+bhLå̤0G'ùö$Kÿnÿ‚™÷ \Ì x‚t¢1Õ°‘ÁÌ#¤ä¤žL[‹›zFjšŽÄúíað¢œH¹±X+>Lø‡T4Šò»#¦JJíic„/pX·(xê?ñO$Õ¯Š¬Ã„„/åÇVêoßqqÛ‚5 <Ë4ÊkO‰øŠâRó9óX;Q×eõ§Ã2†’;9,L쨇…0dp³Ô6ä:FüÑÔ‡a”I˜¦ «ë•MµU¬°kÕÁE¼·øíÊOhëæ‘4œ"AÎoï3Z´Ó€ Òu{8ŠÙÀçþŽƒÊ6ÊRš€ýy°‡çc=rq-Ü5ry†/w…œÔ@›Û]ŽBJí&Äô|)õÀÆ8™¤)•lÊË^åm™àúùàxÝg½õ —V‹®Ø¥2òعŠãˆ¼ 4\Ì^½—e¢»F—1÷ø@Õh¼›û(„™¸}ŒÃòb ‹V¿m±¥ÊwT#4yVÈ ÚCÛJ1Oj)¥S4+%Fß·¾ÂºÀ(,¹Y¾C%[ÅVˆ ›6m(e<ß*eD ­!g _ôRLqLî’;ätȹɃ8áòî¡ædøí[ºðtIo‚ ±U¼SmîC÷S¼bÇê猷«:܉M3YÌØ4÷¥l ðyõHÌØ„Èöd¤`ÇK¤¥o¶€‹ŠØÜeghÛ³—Ï‘\D¬ àÕÍã]à…x3ÓA‚ï¥ žcmèTÑ6” d‹~Ⲝ”¶ë´Ö¡Ìò”("Mކ)§|P,§²r,šPÀ¶µ·`)¸ôH¢4m¶MŠ_Mñ‰T<¦ÑXìWôÑÝmp“ð6Ã<Í.‰.kÙ¹Êr©"á ¼U’ÈR²O& £›8ª$ïûþX wîšj=v OG›"1(sȆÉê- xcÒ¤qNƒ¯aM¥Ñî,-r»Ý„ݯÁ¹¹„ ’9Ћ»¨DkñÔ¦7ú¶Ôïry‰eúÎ4Í úé”2P˜ó% ÖôEªýsÈúФøãvhµ ºsÙGžA¨AU„hˆF¼Þ;©}â¼mA¥Ö”Fœë¸+õ®æ=“ÈAì姇çöòÓÁ`qN·(ê>fËKÖNeqüú;F‹I™HÓsm·ùk58í&“hP) EnJûÍŒ£ÏþÉe×"zW<¿o·È0µŠ”À½eEÃÞ{¥KZæNUÂ͵?oÖ‘{ŒœS8‰û4ƒpw[G…ü™*/R~Õ½óÐCÎ’ØÍCÏ:óÞRçÀ+¶­Dq±UE.FgiÌ€br ¹ß>Ï;™Õt×"‘P²F Ž=-—j…™Ê.ùV¬TѳŠÕWÄÊîa^n‘óñ4OŒÄYG´§yÁlrLè³—ä¸I‡AzÈzbìŽúG¼Ã¯N•(I¹c·²ÉMHÅB*Gê‚ •³“ÚÀƒÎu¦í‡˜  †E?CÍ1DmÉî•>dJóð™C_ÉPï­ h}}ÓE’Õ0+N Ãâþå˜àZ*_ôós²W'‚¨19ÔtMáßweUÙØX-2íãµÔÒ¡57Ï8án–8àÚv°hpÑÔ)Ùì}ñs’Åx³¤œŒ8 ˆwXòõäk™‰•³ §v‡ï^¡âÎúK±‰‡¨$¦½i'TgØ|' K~Ú¥Ði¿CÐ)tkBr#|bŽÔýØ]ÆÅÀNcº•áS?ÂcÞÝ%a°‰4Ü¿:½â“˜®€(×,Gåa}jfr¼AVZjìf˜úùˆ¹0¿|évtÒªSA¨|Œ¯´fUèCbe™SÖÐ?ŸáSÖ¢FGÔv[°CÒæUR‹Ø’ÅáÎyrñE^¤N38¨ íóUpˆáü†2 ¨È­z‹ó‘ï0¦ç…—>‚ߑ§vÞZ™ß ,’ÁH ÷Æõ£é½†rиá˜@‹ðÝ¥ltŸn!­œ±±6‰œ÷­œñÛ.¨ª¤ .E_p‚‹Ð^ÇÀþh ÌAÁÂ82ZuÈ<:™ÕýdûÖ¼¡ˆ75î$CˆóìûD8 5£xï„`§Ø¶^ G6ú?±DP`ºä³òñUÌÝáŠ9R‰¢b5¤ã}ü¦‰³ÿ¦‰mÔjŠÄM¾µj¾C¢§e›LO˜XÊ¿)Óó%eñ‡¤°FNùÌŒ’êfŸ™iý5Íì>d ò¢©­:éGÕ„Tr§]ó ² Úff'3SÉH÷¬ñ×Ò'†™pìs9¹ô¶pÆ0}¡û´žë%œÅ²ªìaükù_£*áO¼;‘rüä¶ã’ÿAÔ{”$EüìS.5ßSÒˆ­ïx“=”ç]ZTÊZ"8·„[lØ BûuÒ%³ðâ™ä"R×<–ê])aç½`˜øõd¿Îî+: ±'QR4Š(IsCnS¡³‡ÛƒfØÊ  £,±·r´6|6‘|H„}$0ïÍ×ì[ù¬±Ã›žæ6T'Zá ,½˜~Ú¿ú»*—l˜VÈ>MÆ ‹õš¢É”hÐýZ(ÅŸ3ž•`ĽØ\€wÞL²GN& ¼í¦…?` CgFcªÞ*"9 ¢_óyJtvßÃ<%~ƒÏs(Owó“š RrÇ•:d£@Ñ®]¦ ¯†™%Î…bŸ5~ææ¤-5€Q&Tœ«‹¯s¹Í‘‘=êaµhkË'íRJõ}¬r³;IC7ófwä˦Ô(‹–%¬¤6I¢ ÿ¦ò ±ßþ±úŠéݧkZ!y‹¨š»R ‹±’'á=jT£±|R,u‚Ò‹œµ¾™¹Y?r°qô%”Ù5:B—rm‹ã$~J嬤¡äuèˆÜŽSWÇC.Öœ&;…¿MÆ$ÓÖ8ß÷áÆyˆþ€†þ``™Í’­‹_œˆv8>o™¦k'y-;l˜cïÜeÇÔIž‡a õeš\gŸÛŒGÚÛ±/du½Bq(ü,'IûcƒU†=,-k<чA]|uñÿžendstream endobj 436 0 obj 6715 endobj 440 0 obj <> stream xœÕ]Y“Çqöóšþ ûÆwXwU?øA;ªåäryAmÀgÿûÑÄý t£`uO"À^=z ûƒÛ៼1ÐF0×7Zœ¼\–ôÀ_pHÖBÛ‡[xöåñFœƒžÁ@Œ?Ù¸Xƒ} Û†“1vÁÞiÛñm‘ lI»“5–v÷¢|ýò#‚ԇ׃—ÿ }‡à”Œã»kO<ƒ•0Fis¸‡/È«¹%Vþ÷<ürø Æ%áÄáamõ E²>|Ï;zžB€¨”7Œ‚Ù˜<6¯õák:®´nÐâæb˜Ã¸«JXÝð þP>™épúOóê»¶¤wGÜq-ìIYdáizYy™_²ô¢òYîÄË0|åî¨`vÖ/Mߊ%Ïn±¦—–÷q|Ð?4>l­àŒŸA ®Ä׸)8[Mýºã{TgÐvx OÛ#§2„(ëeê7VÔ •V€ˆlnÜ ²j¸ÎÀÜdéÐ,*w(m3Ëwø®·ñÝ,>Ú/hëˆwBbCT®áfc“d 8×&ld›™ºdeˆŽÁÂÃ^Àf,Ž~ÜšjRôGìP÷É×÷Øêr`°ž0u#c[->Óžne„ÙÂþ(S6 4Îö[|F}v &Õ>¿àV!k^6µ€Ð™"ÿD`°¿~QˆpÁ~.‹Ëá³´ìoZN§àb8µôí!S ¾ÚT„4ÂUÄé8ßdåŠQ㯷½¨Ÿ½jzJûIš"/EÔ0iE^µÕÈkçîï yQ™Ê¿oÆßðºÅ:˜n]ò> Tgèo,ïíÃdmœDù¿1`8¥4c•Êa·ç0@#—Þ‘F:WREö)¾¨àSªs÷Ç4*eaTzÒâmÓ/£W5q¦Î#~íìÄ3{Ȩd§Þ-$®¦5Lšx'+,&¸þ¬½¬àн‹#åA&V §ÚÄí®ŠmÆj—q²JÀG’oïÓѰÅà¶Ühø7ÈDöô0žè†’;ªúYóXYìÓ„¹ØgTÑz]x‘Nj1ÑÛ©¹k¾eðW"6-Ð7€ €CÙ?Â0¿Iv\9ïãKÁÇ—nØÃ72B‹Wƒa'—[ö™á´ÆõíuÊ@$_fœœŠqɓάçÁ|KœnœƒS÷i¾ŸkÿÃæz ö£,ø JEìW!CDôŸáœ "ÐË–ˆ3K•º–Ž6A–ßÙï‘$scj”‹bÖâŠöv²¦REßC´°ŸB¶¥Š ·¬$¸8Ü5l™XtMž×&§Î‚¸µabSD¤×0ûùá¨áÉ w ª™ºû%<#fؘ V?= Ès<½Kð­YÒ¸E¼-‹h’·ƒu!"‘5Åz‹8/ue6;¤.ög§ÄCéî¼ÔÅqËÃïw„ExXdBÞ!ý–‘ý$¬Ú§‘— (“r9ü©l Õa€úKŠÒõ¨2FÂ*øÕÊ#?\H”WÓßaë¾vÃïqŠÁV¯YeGQ=Mád£5’?-à™sVÅl=¡Þml5–\Êyw¡e^™&ä% ½ B‹a[Ôà0àw3é6 *¢:󘂳d) Oæ\犷,|Z5xq9IuÆÈçùu(‚ɰœ\ãÕvÙðfŒÎ ãæÀ+ü @ª°Óøém¡ÉIýdˆX¤šA©]Ž œ C¨Ø6òE·¥I%O(UZlyYx’Hïe,“cæ2 Æt“KZTz#¢PåŸP{8‚ǧ¼f¡qw ¦RØ®J˜y bÓwBô¶qp—zù¸¶rŠA2 µÇp0Úql8’f /Š1xueaq²Ýsþ9‘{¦9 B?¢ÈŽF}vÆPgö‘yöÚ1*Êí1-糸O'tsBrliöÜ%={Ýõ13ýå&‡ß‘}MfÈ‹)°­þm‚鯷ؖ?óáÈ(‡ÈˆùåÒ¾xÕÝÄ0§"â8×åÅœ°IŒGCXEÆ/¡ ×Üt'#£÷a¢|:ÃAà•}ò*Æœ¯’Rø…€è7vz …äö³ã™ÛøÄé}Çe5–±&ÒV5šÛ`z£ Þœ‰£”í" ³´rv0e(óJqšzŽ˜d›…Ö%ƒ¹éÌ‹t#¿²¤dÇÜÁEá4’Ö൚kbr^õ¸)§F,ŒDSgð7b FšôzиyEwíÕT‡JÂr‹C/HvøÌ¦½ÊƒÝP.…£î¤]^dà$ØóbÖ-$ïH<LjtCŒhˆ§Ï*¿ð,N“Ù}šdøw§Ž Iõ<ìÖqÓšì„[ë<ü@i2;P²ÒHçY¸¾ÂEÒ1МôS«fƒK®Û¨™!®”A9Tò3WGtŽd® hÿn H¤ØÊt’ÿÿˆ—û±Ù9B¼X7ØÉËEDÝP÷Ï1ªMÔå*œHÎÝý%êRn¢ƒŠ/žóÎu¹/NÔ½•ÏÄ0õblô¿c¸L¦_*V¤î šL"05z^]Ñ•ÒLê)”™wðÝù$mB¦ë¼Ô@ •Å9Í„°ôö@‘Âé™/Ð Ðgz|2À•AÈ÷užXôZ³FéÄ1Åñ1¾…Ìùœ2d¼\! )8:â§ÇM¸Yö Vstïˆë% ”þ¢_tq»qÚªn¸®’º-E©ó`¨œú.Ìb+-ç$ Ü’Oõz Rêtæ· 71Õ—‡º™™>ÃD¡X6´"¿9UºKKšb6U25»¬¤ í• jä—S>Ñ×Ò6ü¬>öå†/L‚]9à“Ìtˆ“Š–&°¾‹ÏjaÌ­ëA¢<•E{ghŒ‰˜×À”èÅ*K}S#Ÿ†€xú Åy}üèêó«ï®!‚q±âËh¯ÍvÇÁO¤ áç“—W|rõþ'¿¹þë÷¯Ÿ]½ÿ‡kyõþ¯ðÿ>øí‡ðã“®ÿéêãO®?ŸWw`&WcÊE+ø ý‡Ta|¾øc:lQ±ög¶ĆÂ@†½ðbE¬s ¦‡ðÄ?~…ù£¯Ÿý]¶+ÓµÊi$§ ¸&?ÛZHÀù»Ár³ùr«5¶Å¢åİ­ÃÓqÏ’h2! Z6‹Ê8Ø$û°6y=®È¾Ê};á ¬»`ó®GS"·<©òäF}J*Õ(A¥Õ0Ç›SƒÇûtx‚£‹ÚöÏÀq£'awˆÖ  ¬Ð)¡Ò)ŒnŽç T_U¯í%?º¢à®‹íè…ó-µ¢}’º/åüLê;éÎóæÌ›`­Š40[q–C-*ž«©ª~_ëø( m ñ\§1@%ùÌÑEĹã)·Áí´q~éèï<ÕìßC¦0ÐY¨É¹ÕòzëàÞ‚wXŽÅ^IR8ò6g«ˆ w¨géP1lx ç-ëc= Ä•¥[˜ØÈüà"“æ4r³¬5)w.iG|MfÂWœ.#¶.¬”Sй m«xäP0èã^·e##˜‰]$¤‘@±†b†Eë3ÞŠc–¾#a…áWÔ7SÀr>,IMòr¼˜fÕ4æ$< %«7Ï"Ǥj0Ÿ7M‰Oé2œÕ‘Å5J(9’­ T\±,ÝqÚ¹=vVTDÚeËyÄ3Sá§4’ÙBYÛÎ í=µÄÒò”úÀV •Ó.byì×j-âNª·9ÀØ@:ß79—NÙè„ÓõfxËaFdüM§Ÿµ‚0@A³ç"ߘšVÑ¿µ3¶xÝD=5aŠ”‹að¹†ï›qA1pJƒ{øzqõ–ð}exÑÆªÜw+È,¼…’W.Ä{O"––ž‰x\2?ÌqÉìQ§¥z’õ]¸lý] Kïåeš0=ܽ¨¬O³€x’[ºkê*“Oåâ¼)8kLÙM²Ù]0;‹W‚{ˆŽ?&œZæ|!EÌÖgךl¬SµÃcX Ýó¶ˆZ•Ñ•KGÆè \¬ ìö€roY¢ æLyG©F"wCÍ¢gà¬f¡f™Ô¹™1^ddÖ¤‚j oŽ“á·Äð¿Ls ÕÆÃBè|Ôq‘ŸÔ_¯x ¯p{Aµâ°}UÊÏæÇ¥ã–¹–îfGÕ2ƒÈÎE¬$~U^ßΞÀ®KaW`›À.–ïg¹eÌAzF|SaÔ:Î-eãyòfñó²›Ó@<hÃx&bñJ‰ñé$iþ¶†šŽçJr•~ú†<%¬?†ÝîmÍ0ŒÆ R'~6|.'Üé(KEö¨ÈUQ4Vë¸í 8?³ŽJqLåÅcc¬¼~K½ÊUÌŽ¿âæïñÈŒ˜Ð|>Ư?OŸ;€7>IÎäðFKs\k£Ãï1© ,‡ÿirO\Έi.†ÙÌ]Î|–‡Êpr×~}õèŽg*9+`»–NŽa^’Nó0åy˜¯y‰øì0 WN>¬oI)º2Î:4_ùã1ž ó.,¡CÊkO ]4=Ó”òºæ- >‘X³çìåWpCI½‘§h_TyöŠþž‹MÅ$aQô~„3NÃsÛ'zÁ!/ü…{+Š\'²>û&UÁ#ij&Q<©,ïngÛS-·ÖùÄú ° ­ùºžP¶ÚqåòØÅíäsØ0Þ?as(’¡K Žnƒá›1®\—Ú\ƒ),¨båz ÕÀVßÐñºñÞÞ¼BƒrKeý œ0˜@[Ä æè´)Tæ® äð–óÚw‰¨Ö1/n®2–? ßCj㵎§ ]¤„°S•òøø¤L!ÏIú°ÈtÁ˜ -ø}n+ÞúR˜OM.c~ø «£SwIˆ¡[ò1XZ¼ÇD£¥…ÝÒÎ/äëáQƒ¢+N)ae© E»ÎÂl±DΊV.Å+O«ËN!Îf½Í·ñ¬Ð±†ƒÞœÄœú®¨‰Vz™8Óg©-ô <ÚçLŠ“ŒzTáÿQ´Ú\Q±Ü!Ì«ƒÞãípÎÆlç’°9±º&ŠgÈà] h›Dˆy²yÅšA¹f¸»sЬŽ(Ïn`$ÁÕ)ŠJ¬˜¿ÈËRHÈ=äÆ72ñ˜.¯ô~²½NMŽ¡2¯ÞÊ ÇQìÓ¦„Vð©æ(ß0Ú>\…™'†öÜÏšñùƒ>–Q‘†îÚÛÛé/ûbø§Õ+Ì ;A6¿9iìŒûLÚ¢˜gN†ÄôÅç^ é¦Ò, ÚX¬H.‘qÉ72y©X1á9»£E,6àŸépÐD®‡|[wL¡ävÄê²ð¤!RËBp  óg'‰¦íŒÔFÅ;F‘VŠ#ÆÕ (ë ÇššQ™J'†}v™6žðaBG±ëBGš~Ãodý¼GPíæXT µYJ’ç†ÙQ´”³+­„“ö4>µ?<t·¶XÁ¼â£¸°ƒ#ìòA²öÏ +¸>@Ñ Q¾ ×"ôýcýq_´AÞåÍÑàÿW ~z‚$Ê3V í¹ê/ž‰)¦Œḭ̀¢ÕNÅǨäÔ¥¡UÝy$²Üét—QjDv*òÃÑBˆætO¯Š¨´ËÖ€ÅÙBrQ@Íi†x·{½†pr‘2‹°Ò‰¶du y8ÉÊæ­c*Ÿ0M:æ¨~3+jÎŽ k"£2@kjÒ†¾ùÍ’¬ù¢‹çšBŽ”MgŸ¯¾hß“‘¼<*ǵbŒK\¯YÛ¯*¢Â.ͤzæ7DñXÜ24F¾o^œÍÁæWr&ÉÕʲþ\<èû× Œ‘ê÷òÇþÿñÛú©i‰¥â¡(¡ JX[¾œÂ̽t&:s~U~æ8Ì–0ªªTÔ銞I/E%ÆÏR†7g2¿ÓS>Z‰x@K*oðTåÏvÊsÕÎàa¨ÓâÒ)Ÿ7]Èùd¬'­~þÉ8ýÒ¹ôÎ.œ–‹ÅçWûÎó(CÆ{TÔåQ]|DgRÑic¢ê—û؃ï\k®„ìjN[Xn9ÈÔvÔz‹}6¿”1º’Ò3ÀÙñˆä6‚v²·Ë˜êzoU)Kh —ý݉ E,œa¤¸£zc+(Üu÷A‘ –˜´Tx Ä{¸-%«“¡Þ™Ä¬Ü6¨ÝSžŒ«ö¿8úúœ¿ ÐRe"uþ²éú=qÝí@"ó¹©`W¡0ÉÇï¹òo‚QÌBûíó%‡N!E¹ ¶Õ:’ü±wè×KÌt.‚)æ„G0†é.? !·b·6§^Üu×ß¶‰}å¿8ÂО¡’ yÒ[ÒÎOÑš•¼6i0>4þ]—‘`ÕÊ@F(¹V(\ ;É_´éêÔÓÊçòv±f)àùp<Ó.ß“]Æ40Zb+:Îè¢È–¥'Væíîc+óÃ,Ù”;fúÆ)“ÌFv×°Ç8yBL•¿H„¥êBÇ’¡öe»0W§âÇógWӦ뎫á¥ñ,¤°ÔZñ눵ÒÙªø =G »˜7-'wν|Rß+»›á‹¨¢±XT¼ ‘È)üâJ<œ$OAâñ'AMÚÀí.r7»¬Îò³ÃÏB­er‰Vê™ìÓx;$ñ½à³,9NÝïD(rƒE¹Ú ÏÕ¸ÉiÀr`LèxÛÆT­—䘞ÖcRÒQwÄB~\BdÓkMê´ÄŽØk¾½WÎuÓ¬BÝ˨Ï4pz3Í߆¨vuWI»{#êZé3“ ã?Â…×7Œ-%Ê÷º"¾«¦‰ë´ÎÈ“\Ĉlp·‡³TiJÒK,«"dEËm7‹‘‘‰”¦/0—ˆÇ~ŽÝgþóÃd JrH*å÷t°:_ ÛêÚÒjÉçš<òÒí'ÊŸ4± ‘ÕÌëÄwa§ 5xt…‚5eQšâd¦IæUÛŸ<g8E»0gRaý„ëéö׿j8rÙÓÙëVòÂݤX&ý¥tÊS$Är›. Àü`ÛèiáK#Øv'„qým{+GƒöDšlÙý"82?¿Wwóf;ºt*Ž|©7èó—ŒpäVÕ&]9½íøzû3‘CŽ[ˆ˜«Ë@1^™£—õâ<„Ýß^–¶ä_q4 U‹æÇWîR¡N&lz]tõî»ä·[ÏìGÒm3¾aªÙß+¨q&ìÏD*ë󫿃NúZendstream endobj 441 0 obj 6460 endobj 445 0 obj <> stream xœ½][s7rÎ3£ªü¾ù—8˜TíCäµ½ÚxµMצjªP¢Li-‰²%mdÿúth ÁÌ9G¦][\Ñ3˜ Ñ—¯oàçb’çÿ—ÿ}òòìÁ×Rëó›7gâüsø¹9ûñLÆ!çùŸ'/Ï^Æa.M³˜åùå÷géòÜ«sÌ$Õùå˳¿ïÔÞîÂÞþÏåŸñ‘ ø#J©I;xêòF~²¿Ð“÷ó,wÚËižƒ™wÿ±W»¿î/ädŒõjwYÇ|š®jv_ÃU9ÃkýÎÀç&¸£Ô<)I¦AZMR¿û/| |Û¹Ýç{xœÓ;ÄàÂÅþî8'uýå¾+ÌZËÝ—{5 aáŸÃ»L˜”—ù]VÈÝ·å6{æ{3… •¢™ãz¾Ø_¨îÅüö7û ¿ÂÛ3ýZ’_d^h«˜ßÂ|ŠO¤þöj§”'Ÿÿ .NZ›Yí®`SŸìµŸ€ø.˜"쮘w·pã{|ÔK{­iåfñg¡'ë,,]ùɘð»zÿ娧•ѻǰ 0«\ž›Ò&NCÊIÛþcl~·8·9Xµû¿ÊŸoðÁy²6Œç…‹"jwá²W²Y§ÕÓ|ê»Þí‘)`æS!Z6µüò3¼ËÀ>¨ç”4ô1åÂîy9[z»ÒÖß-€­_¥É{PļTNè²¾òYa×:'õº>úºzQ¾[gð„¾–èC“¨pêL‰ñ{B%R¼®¼ŸWjAÊñá›Ji'LüÎKXÃ@Ìn›„MóNÑr«ñ9Æ3…´×ø žÑ4'¼}›·Vh¤ß®àÝÞ¥e.ôü…ë'| 6öubSŒuݳñÆS#&\ýªP5¡Žù@¡Ða†¤ÉƒŽ‘ =Ã÷`uÏi™¨‘Ä Γ}›yÒIÎõ›ÃžûnW8 G£lŠw7Tæúg§§׃’šŒƒo¥~ÆU8`Æ¡Ï*‹³£BGsòß#“ðM}D%yAK‹ÌlçVHêÓ3¥ù3,0Rz 0*D•ø”mÁuåàïö¨ºÜ$æ™ó8ßú„©hÐO&²Ñ]Zƒk.**e“Øw ‰@tdÐ+¶7[¶y32UexfP»O=gf®]:!£†uð"1‰±EÑâªYWíÆÅûŒS6>™& wÆ?yh&±y‰/„÷X3\È/e¢ìËì,°¬µë*=Û˜’ÇuL•´"3…‘˜­ØÐ)ÈEUžØ”¾GÚÞC}&ëübaÎâ’HÓÚ’„N €ºq¥KLªrb˜49 ÄùÇ@mP5bÀæÔ)6|iý­‘;@t@œ™Ý¾MçY¯r[Z€ Î<¼ ~ð ïTö©˜ÓrÝZ"NkO8Ç;Oó@ì%ÎAr·8Gi×iÖ†¼NGÞ8Z*ëãÎ[•¸Œk†—Í¡Žßø¤s¶;´]Žò©E€Æž@ÖL.;ã¶0 !Üy-¸Ý £Ö Î.€„¬›œzȧóýµ¼[ÊÅÂÆã#¨k¬NÞ—M`êF…çY¥àû +"„!²l5@ý«Æ_¡©6øÇäh?Îv’ôô˜Þ’ë‘hÒZ ’*Рë"W3a ² å8ïÅ@áà¬7 °!Û øñÎÜÄg£å–>…³Ý<²q.Em˜à°àÍÝnÎ3À½FÏ+RDõ _CË9· í²t’ Pô¼Mÿ•u[ºçmÏ`OàíŠFñõ¦egzï¡$—y(I}8Õ›HuŽ˜Ø ²/ˆ¼á‚"æÎÜiуJ½M ý]E"b;Ím‹á Áá¶~aèŽážÄûìÏã׸΂¤­s‹Vá9W¨Äs®ƒDyÞ‡YÎ$ÿäW»ÒigšµZ3à&ÎÁÉ6:†šV­Zziù9r¼TS(>ö’³ñ*íš¼>l ,ö3Ó®‚3ÛçS€#Y Žç‰Â°? ÈOëY÷;h=¿C5QeWøÀ@ªÑýº0]{äG4PIšÓ¾ %”¨Ñè3÷¸2ؤæÀt꧇©'ûϽ5` Uháñ»v°HáyâJX6Ú›ãµ(ñ˜]99D™"ûØ`ÔÃjâ1Ü$à£6ˆ6{L†0ö‡Î ” h‰Ÿ{Séb ž.!9/n÷ŠùƾÏ[$µžÄ<BrݼŒ E²_ù÷EñLë/ÌŠª `ߊò”7î?¾¸€†C½Ex )¸fAX2®QºbfñdÔjÜ"1+“K æ.¢±ZŽÆ’¿“tvãÐ2¥¯NÏO¨Y ÕôaÁý £ ªˆ¸µŒ\\ê % ¹ ¤U.væMq%dq%XtŽé«&´‰éö‹¢žŒ¬‡xø·± Ñ!w’¿¹Q7­½»ªÀ|”âMÈ>)—bwÒÇ MqWâÊAÌd«™¯Šzã¾C†‹œj±½ âgðƒÎÜ-æ¿Òx· ptÒˆ‘áÛreékë&`¾œµ¶Î÷³lΘoÈ{Üp€348Î`eoyÃ0·±QÒyœ± 3èT^f‰p<=·…6k¯at"æ$ 㑞±3JàÈ9.\}ÛpáRþרD†$PÕ Û¨=ÌÇ3>›ÈŠÞ’kku}zØeó½OR–Åà ò|Œ3P2(»¬;“ T³Ü7˜ ³“à™0§a÷5N¹:ëÑ~”ƒkJÒv7sÁ½1œ’Ŝɛšjî|oú„ë’l#_¯”2ùÇn+”áàÇ¡]Ži¢‘`Øi’ž•É1 ± zëlfÆW) p¨‰®Î£ä¶7ªD¢wêzyrU­×ªBh½òR[`>(Ht碖.­¡ìª,øpd¸ ×&¶åªFTÊ&3®BfGõZÊ!N/wÈá)í|DÝ„ö½;T4È)ÆàŒXñ?²ìƒˆD!¦ÜŽÆ/#¡oc°eÕ”är‘ÓáXŒù#më+¢nS€oeZÉg÷“0¼Øc\ Õežr(Lr—¡‹£Žä‚«î¨Ö¬. Ǿã&¤¬íÕ½aáW6‹bÎæ“Ý£4$;ë‘,­©^Ä(ÔJ°Íƒêc†æ&‡<¤ó& XÕûÛñHœÃ”/Qñ¢9œˆLañ"3„<¿üâìòã¿ï ÆÒ½˜n×Q"ud¹¦a3×Xˆ"'©Ñ|†r¤‹1i1y ¨8»>Á95úÊ‘}q€’ÁDפ7 x^¾úKät¯]Z·×‘¾À«NháóPsÖbr^˜™žW‘‚äQ1*ˇYækFZ6î6®­ã«4 éPRÁÞ«ŒV|j jJh"Ú$«ÖñnZU:ŠE²DÒp>Ë$2ØP‡¢®4­ÀX¥5Q’uf§<=(X» ü´Åã1n³þ,qÿ54°‹Uö»õ(«œü&;]0ôÞfˆÿM†s­Ú @¤XñÕ8³àaahfÍÚ_7J+&™}©,ÓÆÊ I9d ˆá‹ pµzt„HR¼µðt§ÆH3X˜§^7®òŸÆ„J•¤Tý×Ùv¸³p'y°ì¬Â…¼Á² ÊÓGIô½þu«f”ôC}œ+®Z¹÷/þˆT⊱ø¡Žkf•t¼`%ZTHlKÕÆ2Ýû`ŸÚ NÕ¯ÈÁe–4É*3.dÙ”ê Yj½ùêø£ZÖÎic˜Àe¥.¨æ g~¯2ï²—¥ Ð6¥H¼%MÌž4eç±ÓE­d®¥*qRòÀôÎ…\•+]âäœû5*cœè—H¢æ8b1GÛò¡¼‹ù žgd3™y¥Žñ–¦®•Y·!ƹÎíD†š>®@Ö u¯²oUØ ;IÞíTþ‹éôïöåÁû¹¯ è<—(ÓÂÄJùIcjÀ×ö}L¾’á´Åoɳ¦~«AÝa¦@«ÕóBÃÊâ7ã¨ò\4“øcáç?1ð;w:è½È¡Ðü¢«ŠÐ¢fþÐAÖ<åË@ÊÆ´a.èXd.2NÄÿ•35âÙ f,Úyí•©ªø9G Óy˜Þà¼ÞXV ;"kÃøT,žk¿³b±ŒëKS¬¢5Æ)ì«ÐÔ˜³;/h%ÑÎã­y-þfyl¶k×#øÁri‰ÁÔ.¾Æñd½x™eLp¬êï®SzPؾ$žS”áE¸­-=g‚‚úD¥$ãšóKªó=‡©üØË¢öCÀ`ŒÎ(¦O¹RDkT GÇo²‘¤Ð_nî<¥M6!ôãeí;:ØE.D”ÁÆbùÃŒOZw‹‹óŠšúÞ·Ú4€‰äˆž(¨- Oko5ö2ÉPC3”.$àr&øÄqÌ¸à ÆŸ]%BBç58„A¡ä<^xªX`iFDª08à ÚÄ763jž·»t=e‘%M³gLØ™ê´#;¹èvL*|X¬»”+ûö쫬ã¶Éá]bé£z„x`ƒnÂFmű\æH-Tou+›7, CÍ“¬&ˆ}䇜އO´¼®wÍl¨‘•ã–¸Zd®óŽvõ(g‘EǯÃý¡€Ô ŠÒ’ZkÓDCðƒ.ñtôH*=L75ýõÎw¥ ]ú¢ÍïÜÏ%=Úó “CrcUè‘ “!äæXuz'|çRÆ©)Bd9wãì䇽²'ñ˜I“Q9Iå\´¼G«~8(K“°g x’y³Hì”.ì½°Øvf–fÀ7xséT ódµgh\<âÓ6²Hñ»Æpå>hãյœ¾ì‹Cìßgabókñ=´j7Ú=)kÛ8T¸ø‹=‚ ¥UW» ¯´¯Ñóî£Å°!ûd÷õ¦ùŸ±q{©Z?M榿s(2„ƒñ˜!½‚‘8Ö°ºWQ© ýù¿õÌ¥‡iZääUIJ–‹®,› ¦¶ï½è”FFO,_y8ÏÊÎÛN¯ Z&$‰ÜÌ×f>2“ÂÄpB„Ü“šHÕ"+ÓØbÑ‘àrÐEnr\?fÄàêºχ‚>¾À¤®ð1`:ê0›¼æa¡í mñp‰*›Ö¦XØäå1bUê£|h× ’ ÒÇ–u‡­4Y‹%™:NÈ:¶gµü“xØÔøî§v…7ûzÒ‚ï3vñÀ‡&ïDK×£"Új î xžÒ"Ë{Ìlåö®vü©JÕ,©T^l…ŸòΕÞí¹ïµ`­ø”9ÖÁqû†Cè,iy°Lrø”äïû}:ak‘Ûd¦¡34kbq`ˆswƒž¶Ä¤œ "ï„Á1¯ZcS³vºÍ¡XÑ‹’ «Å³é=ð`ñÖ§—g_ýxpÊÅãámá\l7 ç à)<Ôðᣳþrþö§wOÏüí\ž=øþßÿ~ÿ<úãù¿œ}úèü«S:Äú@«ð;“I§Æ*1*Ÿ¤ßÒɃ<—zD ËÃóÌ]²vu­€ù®ñ7_«‰mæ|­,ÿ„Gb Ç·{ÅÌÒélÅ娑°l˜äÅíþ·È~k"ÁäãDZ ™˜ÂK³J¨ "}äŒi¿!ºM3~(`/e¤Ô°6ïð3K‰é€ßaâ ªšy3X»ÌêbXgÛÜš"Z_“ êwÙ ð û5¥ ´n»]uVvÉ5XlЉ ¢™¦ Öê:e,”#7jM9ÒÑ;«U99ñÞ`¬Æ´¤se‚cáÒÎËý^Óô{iêµÙ<8 Ô/É ßp,H§jƒõ¬ž+€œO›'_€£d-ew]F •¤pòìA€4飨ܟJ6ÂåMdd¶S!›jŠtÚÊë¥0øSYlg÷ÃÇØO ¦µ‰£H//¤…­ÔÜ ûÒ‡×eÞ@WA Œš0—"&5¯‚ªÎý5…<È"åX`Í:|JAn:5Ài^i¹–²[œ`s¨†·+'»ÞËLbEÓ8òq3ØWtÊZâøN(¦ëÜ๨o*hg6”ÎZ’vÉÛ˜]ã§êQ5ízpÓ6Áœäë–‡ÌF‰ÏZ´)>fTUIXÍ´cSÐyÍ–ä}ÖØ¶z¾Qîø]F ÆÓõ2uštNÑ ©½– ðÀJ2„Ò0¬z³)Z·t¯¨×7Â)^xFUŒ¯ßçÄ}=Ë'ûÜ‚Ðÿ$GKÎZñ«ÉhM ò‚¦óë#"^”5·1§ÒúÚ$QÈÂd²´ˆ—•ž Oúö¡ô!sÀV#/›:ɼt¶ºaªõC,I܆ÅEm­hªÔhϬÉÕ ¬ö›^…) ½‹ôÝo{¤È~äs¶!õK ”аy› ÚN›êh€=Í»Qù)èTÿ dÍ!ê ^Ž3)>–˜0UÓ]˜”:3³ <º¤”:‘­ˆDkí3TRe\WTÔ¥ªd: 刃80ˆ‘v_Ö~(CÎ<µ‘Fzw‹¨èXìÍÒÑ”]~Ô·q£\º68’<½`X`ÄOÁÈsc®Ê!l7)Î+ý©¼LŽÏt ø®ö¾öЎÎ0c‡ ¬©J÷RÈà£CÌ­é¦ȵ øÖq)bK«w£ Ž˜Ó°Ìú†gF ÔÜk¢­™…®£Ž˜uã̱|!4üt Žòñ±‡;šV³o¹Ê}ã§|Rê¸*X/‰Ã€RW~Õ ¢£-»£9W*6F"2 #ð:ÐC:þéÔõ7·LXýãq»ôÝèÏ^ÕK¤æ×òMKëÊŽ|YwO³‘#¬w ¹Ú”µ2É_W'@Ö[Ö½*žï wƒé¥OBÆ,5@½Ÿ‚¿VbAé#rÄ æn2B×7\åþ²Ñ9,,pÄ\ñÔ/Õ’ÐÒû)Ö2«r‘cM«,ê"á;mÄú…W bÕºƒ}ÉwN8ü7©5³t¤7Ú7>ÍAÂí„9XÖ5JÀ¶î ÿ"“Zk©îBGö„Bkz[ûönËQÊ—ó®,kÅ ‚å\–òrÛšåa˳W–]çmk†°¾Ö¾ù»Xñh¶On×.eârþ­ü­.Ú ¿²S¾Ðæ‰CôÆîS—ÞýÃÕPÔÜŠuâ+5d's_ÌF‘¦>÷‚Å¢Õ‡zñóoc Í.€•|> stream xœ½Z[sÅÎó)ªø çÍ»g½ÓsDÄ!JaÀ *q‚d˺ٲ0ί§{®=»s$9‚”KÖÑîìLOÏ×_Ý{^oçIlgú—~Ÿo+¤Üž^oæíøsºy½aÈ6ý:>ßÑ0G—&?{±=z¹‰ˆ­…­qj°=:ßükP£¦&k­þ!Ã…›ç ¤>wr²NÌrøÛˆŸ¬Ñz8wbrÎ{=Õûß;=)efÃ|„˜`öy€òy/f;üsÜ©0VOp,Ì“’nørÜŸæ).nŒ2‹Åq' `ølôs2Åz/øô´þÆ _bòÞ)nÉ¿þ\긯”¶ÓìÐ]G'è"@ø1”¶ñêN©y²f»“øKxŸøxìÏKiPšø•ÖOÊ ?ç:G· ¬QÃЬSüy1*ÜŠ®q¼·“Æqoqjç ˆáUu:=ñ–ÆÀ´¸.íä†á×Q†…ΊãÄ„¶]âSu0Ýp3ÞÃI½Ú30Rñǯi§Zãjõ™´BØ+ñ®žc÷c¥$»Ã@éùZ4Å’”ÊC1R©öIî ZÑØD8aá:áñ š±kÕpÕÙëoãƒDx i¯³ÎF:yB1¢"3‹3“60<‚9£lÈw´ GgöZ5‘fF{ñW°÷§ð˜Bä=M C¤²s²Âñs¢;/éO‹X‚ä2á—!ëwÉühô q_g0ü8/ÔäQ‰àn~YØOð|Ü…‘h-ž1xüœàÅNÈó1ƒ¸z9švQtìâ-a±DGöSÝïYB‚àzÍ Çåb<™|dítL€]TgœÒÄ0ÍøñVØÓ Zý6؇™%ê5Ñ/íX*7ÌóÕ$Ÿÿ²‹QÚ²‹¬“ÐM«žò½-Ñœ8A"¾, œãdß~ÚÆ#…uåòÏbÄÍzFäãe •0ßU CðÑ  ` ŸÈ.&ãÓZîb+LÆ'àƒ ŸHŸ’«0 Aäñ€"ñÏè(B±èn"0œ†v|‘äg«ùã‰9­£iÃmÞÊû8iÝ‚)%2Ò{pefUÝ–Xrð÷è¯G:•”$^qBcºdÒfÐáÄ?\šØnA•2Šš}àŠžhÁE„—ÿJTáœä´'¢3ÜUd˰b´GÓUXÝM{˜ÿpÚ I&xîVBZà('"ñÁ|©æÈ—ïªý´ £…Ã'ï ½V˜¨À-­)ÜnÏ—0‡wn2R> AÄÍd/|l±4ûuºŸ¼£fK(h—ס9®Ê÷r÷["Q»ÛºÃë@àý4«|Êg|ûŒWª\Dº£ë(Ì¥}E‚:ؤ jb0Q!FµÆè"Rˆ–\çÜKØ@'ä¨ t—6x¶cŒöMLhÚ¯cXEð=†7éŠ '¼ÿ`åÂBO0ÚŽ'OŠ oJ–³[ä7KšÍ3õpSï3Jn(<"È€LQ“À¼±(~c{aª™Q*møjô µø¨¿—Z2¤ÞýðQ7ÚÒ¾Ëbuõÿ–8` ž d6]U|^ã`ΰ<‰?5ÂN’…X6´rÃRÚV !ÅÍZc¹ÌeÅ媌 Q¥‹à¡•‘R™‡È` ”àƒf˜Ù*7³m–㓃 ¾c!Úp ì8}Ø–‡&ãtžËU7åÈq¾ÝS«¹^©qÌ*ÕEGE¯Fæø$ýPwAÄTµËÛ1]ôûÊû3V0¨™.¯_’ËqUKúÙWiÄì/ ò VKºOil`B´Ëúd–gIÔ¸ô3ÇËÄ~+Æ «TbjKKU`“NÃ^”¾3.ò§J-Ô¥Qh(¥\†Þ5]@Vt³[  Ï‹äâÉ÷#B7ð`öNó  Üò˜»¨… "|ŠÀ:ÕÖ8 õŒ>ªÆn"£Éb"+¤Ò眼Íìx½€*-‹VçÔ@{>*RèÓUVG°9ôQ-ò'-mt(ÂYô—Hä)0¡°‚ºx­s·V$1Ù$g¶™2·X‚BwŸˆÔd0YÈpè¾1˜N4êvvè?ŽšE¶œuÙå^2b)™Ì%£ð¤¾Ü}/—Å(òwN“¥Îg'É´bVïVbƒ<— ˆ_€Á†öŽ«òÚ¿ÐJ3u¶n{…ÏÁÇR w’^¨)ÕΓ߲=*Ï:ŸÊÝ"°`¡¯R¯ˆ‚äÑšÊ ß=J™nvw Kžô€›fïYL1 ×KsWIÒÄyo‚W)>Jí½ê'gãÏ£0XS²Æ"óÐ IXr{ ?§vj†Á½býÓ4ý?0fŠú\¿j"*ê-QÃhõ RjÈîì]\ª¼ò;åïÿHù˜øÚí£Qµ¯5Ÿmžm^o%z9|_‰¾´Å}zú>Ö jGß‚:8Ü<>|º}ûææÅæñ[±yüwúïà›Ïñ×á_·Ù<9Ü>ÛÿݨÅK²ôÝ(zGCïTAÏÄ/H5Š®)Cú¶`êùØŠ 2ªµuVÌùy¿ÑÊûç­‘?]kôýß{w‰‹½…Ÿ8‡…>Ûü×FÔendstream endobj 451 0 obj 2639 endobj 455 0 obj <> stream xœ]»N1 Eû|EJ»;ï’Çjñ\B…¨±Õ+þ_™™eWÈŠlÙ÷'9XGl]5ï&s±eïíþÇ8;êÙ›ƒáYb×´›ìU›eE[T]eÛ¾Í`›Å¦ˆÅ¶É|€Çãg»ï–âÎ-"B>©«}©òO9×Êp‹Lµ–Pá^p` !fvÒl–®¶ÚåªØ AבND* ­‹È 1‡ Ï¢»S‚Çua8*Špi^ú¨“”ØŸŠ»Î*Õ{†'r.ê‚QY¡d^YÑ1¼ÿÏ<7¨/r¼yÏò|>~Ã!j©ôþ›f^5~úUW|endstream endobj 456 0 obj 252 endobj 460 0 obj <> stream xœ½[[sÅ~Wñ#ô–=ZÏýÂCª€‚©¤’Øzƒ1²,¹°%#cç×§»çÖ³;{α-*p´;;ÓÓÓׯ{^ŸŠYž ü'ÿ÷âÕÉ£ÇRëÓ«7'âô/ðÿ«“×'’†œæÿ\¼:ýúœ†™S%fç”;=~’&§^Z¯OÏ_ü0}³;³uÆ7]ïÎÔ¬L>=݉9:áDœîòÓ¨¦ßvrŽ*š8]îà™¶VN¿îδws˜,δ÷Êýûü¯eu3ûà%®nílt §ç;9ÿü‡ékZA©èa1øR#†7»39;£âôוAÈ8]àr6J%zƒrÁùé;˜B[%Õô=Ñ(œÓ9N¼×jzïMκ:æýN&fez³Sq¶ÊGÚ¤8ÿ%|̈Vã.a.Œ5Ósx,”rVÇŽô øP[ _âjv0à1<´ÁÀ¼·¸aé£7Ó}#¬­Vöëƒï§¡²¦°7ÀyÏQÄÄÞ8K'Ta/°AÃÄRh‘„_ØY˜"ü‡½£E©ÖaA/–ÕÎ2¡l²W¢¡zA»^Fó³MÃÌrv(ÍïÈãȨUõS"–dv¡}w#}¹\ï#©FâªF |‘yLšP²H,kuO“ñ3Ëuì4FPpô'cÉpï5éß(i â]þÚ>ù-²Ôßš¦M÷íõȽ¤@Ûj–TÔà(åVzÚ¹›Ä˜>cä>Q"Až5u`ñø ð;.Æ_(Žº£ð5Ó˜Ñψ5QÞ‚Ö{}Âh›£(·)ÚŽQïÅ Å<³ÂtJåpÓ"´¦¯pCÄ“9ÄDJ0Šè:™`Ïw±NömÆžA^ЇDO<ßæ{†H¿ÚA~aºçúmN’•'÷’M6l=i „çE©àmu+F· ÆÍ¹aEKƨÊh4ÿiC‹$)§ÇÇ$c˜ø8ùaÉP–- °•†Ùûž$'/öÿ úB¾MùV,Ç€ÍÌ">l aò¥¹±}Êü¢ªlfRPr!ÁBC~—B‘Ñ“,Ùãˆ/»üC6 ¼“Œ‹`—%oÒЂ"hô×›õ9›ÂØa™ ‡3\¶wc„ÃÉA\VIî¹Ï!;ÃTT¿ ·Î÷JàÂ6nË Ä¡Ü~6T‡A d¥ .E%åwI9zëØa¥<ðéEÌ9ÃXô.rÅ*[€ !»ñ£,¤CpÓöÙ †·vÃÝ-GÉ7bX¦,Ë:`ùU*f*ð²ãBujÍÀÕÄ(a)ÿ îôx×CŒå]l4‹ÒÂ:wÚÈ•ÈaŽ,Îô:±[! Oá ßYi¯—Vgk䵇ðË‚sŠøcô›jójlùZ¼Æ27ÜçþrMfÞpáѤ$U´µÿ0w±Ë$q)ÜÜy0ž/ÀÔRq‰rHÝ¢b&ʵðÞto‰ø —ÙW`Dÿw•Îc»¾¸“7üÕNqw™‹N²Ú³"¬g Íö¾A(Ssiî ÏÂ,yšòÜTmúbô6hCØÙ*.½j¦•j(ÿ)µÀm—yÀÀu™©K.¢39{+î„)·4R2ÙL&MrŠ^îx­³Ã°w½‹9¾«EYH³ŒÊµMŒ­L(ÚqÛægK ‹Wìà˜;í•áòÒ˜8èMõ=KD·›ÂeܹÞñ‚hýôŸ*ÝŸñ²¨£œ½ošZuçOõQ[Áû&|¿öeÁ0–í. aFjrž‰¯›ñdþk  "c·ÚI@ðÔ¿µ: ôLÓî÷»¢û¡z²jÁjM³Õ“ÃÒñ­&‚¾<‹q„Õ 0Yyˆ¦0ˆ ¨)ìˆ:iÊ7U;¤ÂÛM8„˜³Ñ„Sgz‘ãMìªlŒÃk«™½y)ÉÖŠR²LùGæ¿„h¯º88šQ÷AWl¤OxˆXèë)Ùß”u:ç—ö×UéXøY'æ+ä)sJüê‘Òß7\‹ì³§uR§Ž´t¾ÎVQб‹Ÿ”¦½u¾)ÞP}–óí¦Þ8Œk7@ ä†SmÝ&Glƒ ¨h;Tu©äµ…°—~¯pÀØH,Õ""ôê€KËÛÒë°ß§†wÀ”!/Ìoz¶'îÄ3+{O»ÜJºJ-ã´PÕª#‰Å,ôñÊr"ÝÈ!>)&B±¿š)÷†œäʸÛ_(ŠÌ¿èä±ÉÛ×U_3ïÎb„.£ÍQ)ñg«õôËÔ’rFÑ~æsÅ?ÑŒ’Í-¦/Jý[³jë¾zJñ§£þ•¾økDÊÒ6-T”;Œê”\áh³<áÚWßÊIa‘€fö{©mƒy3¯ÉW··ïV½Ï ‰‡8¼žÚ `#[27™EûXK“™¾¼a·28LÈžv­E<(]¡ž}ÆÅ<äU²ÞÎ8ÂdÊ¢k· µ{úïÊSöÅÉŠ×Hî’qÝ&ðž[Žî}ªØ—r;åÒ2ßw‚šÊ\f¨_¬û`¿ißò¦·¡vä>R¢RʼnP`⎶¿XŒÔnÃörëh™M×"¦‚ K¼"‘u¨ ù©jž291»PëŠìã’¾ƒc1õM£x~LŒ–=îÁ€ ÞU¢EdnrP šræ!.ÒGÌ#”:«“C™DM».ÓÇ¢8…·‹%U2#{à³K—‰U#‰ku]Ci¶†f¥†µé r”y”F–à¶ÀêÓ®=ž&Ïý ®ašêØê<þM·è¤AT]aQPC@l‹‰Õ,¼¡¦T,q£A°c-Œ†˜E£X‡®/HG* foADr¨œ3ê+„ELÌ” †îAZ‰‚òíß Óe8£]÷û6“ÊñR`t±Ì+²N™ ¨”5ÌÏ”!\Òí ƒ—é¦Ç;TLi›ý~9%~þ‚öIéM{}‰C,¯ïyil檕¼Ôªp‹ín¢ÜéaEVZ¼Yë%é.b¾ðž·T­g5;èPú>ñúܪÚ!î©cÐÅ”¬IÃj•=@ñŽXòôµt{ÉÕÓ#¼Îõpü+ "mx³ŸåFÏW«Ž¡’8,IñQßF2v~«Z3" W[¤Bì\2|¶ƒ©;æ¶á61i,eP%^ZÐÃ`¨»X—8*qôƒ}NŠB|s|ë”lé ôGµÔ\y A0$K˜½…eˆSxÿ5M «"£ž×‡(ŽD6áÉé'ü9N"ÞþTÿüµü+ ~S‡<­¿îù[ãSµí­L«¦wd‘c=¡ÅÒÃËö°­¿€yD4È{yú¢ ½©kû{Ö‘OG;zËÃ/pѤ{ì#AÒ/ê°ëÑ„¿¶¥??¸Ÿòð§ö3_Â~SvŽ^£Ç{ÇGÖŸÔ³˜~ /0µ'eŒiZõGÛ_¼ÖhÜvH@ÉgßÇD†¢$’­Í§o‹=dÉÛ„dºD ,YF›Ó¥Õ^ÉÛG!IŸhM8˱iAˆàuåÁÆøþ® æv¹?¶fö]ëðb!ì[àÜ&œT°b§×©îÑ·–Y"™+• Ìcƒ}ê—Ý´ªé •wÓ/9ßÏ0 š˜ˆ°=Ò€óKe*ØY/ï[J&vìäòqõãLt”.¬ûO—úåURËê:ˆ2„„Š®`RGôÐ%/þ(ŸÞ6ŒÔÝù RËF'føŠ~#wÁââ˜ñm^pëå ZB˜˜iºk\^Ü Èí²`Y»ì v·¼ëÕ5µBî Ù.µÞ0±_Ýž7ïEo\*îÒHl¾ý‰W‰Iž±#2:È5ALtÅ61V”)ýöüä_ðÏÿ?©Åendstream endobj 461 0 obj 4350 endobj 467 0 obj <> stream xœí[[s¹Îó©ýçq†â º_’ª°a³ÞÚ„œÊC6µe|Œ¡ð _€ý÷é–FRkFÇ>Ƙ̓¡°ÏÑH­Vëë¯[­áÃ’ |Éðïø{ÿxñä%—ryx±`˿ÿÃŇ]–ã¯ýãåÓÝÐÍAÓà™çËÝ7‹(€/­X§.–»Ç‹ÿt²×èõwÂ!ŽUC¬„ƒQ»kèù}¿’ƒµÞóîÇžÞ;廿ö¢û¥_ñA)mE·[ú<‹­R¹î%´JÛi˜lèWÖºApÝ=íÕ ¥0.ˆyÕ¯4 °Üu;8ÖÁf• ÓªÀ=~²ÆŽ]=g–N>ÊR^SYÏ¡ƒƒ> “’wÿì³Þ(ðYY èÍ “æNÀŒœcÔUêQ'¸Â fPÚÃ)θS BPû_½Ó‚³„A“ùɤ£êÂòqOêm\q妖+0¨åÞǽ9ïWhJåEwFUŠ ÑÁt¥:Ò¸[p Ös΀F¥}],v ƒ-d÷{¿ $r ¶ß™îd —ø@ÌûÉtû½´`­»· ƒ2Ý1tŒ±F…TÝZAkkDúè"`&°!‡=<@àö]Òó$ª¤À˜DD‘û÷Va½é®Ê:K‡“Ò¸ŸËc€¬Ñco©¤¨èò¦”ažNÕœ ÚÔJYVrÚ‡¾Â1Ü·ù¶Æa áÀ¦É5ÉLãË Ì"À™5@a/Š÷^v{­À³„ 6ŽÛîµJâÐÓÊ”êþŒ2\°+2öú¼:ì¿·¢žè¤d0IE—ùŽP2øeZ%ãtãG¤ 4Oy‚fXE;¬À7µa"šc.D∠g+œàÂuJeqݧ襴·Ø0C ‹¨€¶â5¤[+êd'dž)\Ïësͺ‚pAHñ#ØÇî=ôÖ"lE†ÎE¤!­9Á ±ÄYÑÄšÁYæƒá0åDÒ‘\Ö¤£'½Öqø!ØùL̾¯¹{ý¿¿£Z¸FÞý†_qÁB‰p‘ñÁAz;‡~ÇIlÑJyg»'0•`ašØ5xD£@H©ñ¸4 à±fÀž+~írë~éú67î•Æóqm0÷£üü z^”N¿Ý¨Éøé×>?ù^óÚôñ v×™íe/›±vÉ£Œ¬ârñ!ÄaMtJÃuØ(à7Î")›àÝWAzÆ8¤ ·÷ÐBÿÉO ‘Z ÓÖ¬IÊ!%¾M "A—Ô†»&@0hñÌS\•Ð/-#©¦Lâ–»ãŽ5o¤ƒòí*Fà]ž7±¦Dˆ“-š·²Ž„YÇ9Ÿãê”ð“q„òý X²xVZö8’ÈíH=Ñß ŒÏ#˜'Ü=ëCƒõƒ›Æ†qÇÇ4d#¬™ ¦û¾Ä‚˜r3J]wËóW%VÏ1úÀÔ³Äi ¯Ã‚‘×9ÕOê0®6LxØi+è³ä ¸L†âw­|h=HWÏ3rÚ3嚈+EB¾2Ð8u'Þ0ñd‚… º4C• r’‹'»ž!™˜ãÉ5JÏuε)ñ!|Çd6Q"â“qÀ'Å_Á=‘sØîÓ Ì*aã…¨N#Ͳ“ØìWœ‰¢Ð‰ÃžUªåŒ¢‚c${ÏÐ)šoÄgùvU0žùE߆_4f‘xž`6eΙÒ” Y¨Úæ· ²NI°Ñ,¨Íòî“ZW yÌåט°-˜9˜:¦¤”k‚á뵬BоMê¥}Ĭè4§Zë…ÌfÛüë,K8ÏKÖ’Ó±ø#õSpˆ`HLÂ$ËùÞ,+9ÑY«ñ²™ˆýPºîäÆŸKã3åà‹"‰ØEy~ÙJÄZ)Ýqn|4!Vº,½öZW­™1‰‹­7äp%wVÛåp$ÀÔ”¯ ¸!ð¾›â¨dR8dzÝŋŇ%x 5 ð ˜RXÐØ-•ƒ,P9¬,=ÝY<ÙùÇòòüê`ñäßK¾xò#þxúË÷ðkçoË?-ží,_ܶÞÄ'Úàö~Âå”|TqSÊçá´7+ b<%•½Y1txYMä3þ5‰jH&ÀCÁù’ƒâsˆ×Rˆvj0;¸gëBü÷«‘ŠßÎS‰³­žd²_ìù\©Á€ËYê=º ·˜+ž3V›÷³ËÌÐZaÁÉfý ®~ÿúƒD­ÿ\^*»í6¸¼af‹ÌXHkAùÑ£%(‰éúw!…N©mèù:´09=«ø£YI]ãÕô za¾½nM:Ùêºô‰s?V&5!"LíML‰U'„T0f~è`|4#Yù(߇rµ´l૎ñä nòÉ!´Áý¾ãQU8ù´µƒ³¬ŸRfA©-Ó÷êxÉÂ¥„µ˜ø(¦„Égýwa ªú¿âô8:?=+OÏgb¸ÈVÙ\œœá×7øõ†xÀã¡èöqg| tl ¦l¬ñÓ`¨˜ %(yo*:5çüT²lr Ä[1sˆˆH3V!²eÖsÄ„é„À ·­®C¶zwt+Lû¬ªvs;t Dt«|Þ¹%ºa3²wÞÍy9BúôÅqÔ*RO%î9ÙG!||Í8*ØGï[Áb%ú7½a^øÃÝùðiwJ™u¬·¨h~WRn©b©IiàÌ‘èÛmÖAW°*Ç7R‚v¤»™ÒPY+¾à®´öD#CÎ0VÜRRZy•Á¬€o OdšºßÇ£/H ×¾ãݧ“"‡OŽgLÂUÇ8¤Ÿ[Q*€áwŠsC‰s›˜`rÿ3ž˜™Mh+ÙNßF‘ÊDFOÁAŠäuF7¯tÖ9PÃ>•HÕˆ¨M®uFËÕI—Œ¨œ¨zXKhbr¼Qbª>|&£~Ë:×§\º*]R‰‹…J‰+\6ñ)&@V‡w®»vª”tÀèM{³Öñ"§ É*x(×¹°;¡P`œË® ó›8_àëàSïhf\D·M.Ö~¯(×Z•Sä¨ñàNqßNQ]Ć¯Û²þºeⳆíþð?à Ñcç×’œ…Vw-­_¶lü€ð„ßá_ÜaD±Q8LÞÜM›oýÜß‚¾Ã×Ïu~r”Deœ‘•l[ :hÿ×ÿŸ¡¿ÅⱦÇE?õ¹ Ÿú¨2Ïý¢ü'°ËJ©Ê B·à§œ)|k£íaûñÿÃÄüª¯ þ{åñÁã²¾6àßðêæ^«±rûÔX¿t®8_,þ‘wUendstream endobj 468 0 obj 3006 endobj 472 0 obj <> stream xœÅ]YsÇ‘ÞgÞ8³K »Ž®ª~ØË–-nȲdAk;$E$DH!’(RÿýfÖ™YG÷à 723ÝÕuäõåÕ?ŸNq:áÿâ¿Ï^ž<þ»Pêôê—“éô/ðßÕÉÏ'Â_rÿyöòô£s¼ÌáW‡eZÄéùó“0€8µòÔ8}òôüåÉ×»y?ï{y°ÖªôœY·äävÞ+øÞÌóîÉþLœ[–yw¾?ƒo˜ÔîKø¨æƒžUÿÒOñã²8½ì>ÆKÅA«e÷‡½šw,£ÄRh¼ ®ÑÚàÐ0°6“ÿ¨¤†?æÝß÷JÄ$äîox“”Ò˜ÝWûô05»,"Îb“Ý}¶—i`¥]Ù ÷íùÿøÝtt›ôl“ƒ:¿„ÝQ°!ð^y¦årpúôLM+–%\@vãû2åïögðá0Öþöö†z¹?“c¬Ñðç™t‡i²fwnÔ°cx#L`¶z÷Sùön} ¿”2“ö’‘¾Ûãæ)woàœ3RÄï¤Òþ>cJ.ü9é÷pUªºž¥™ž³8W²Ìz÷*o!¹é|:ÌZ‘1¿çKÃ=Ñlür?®ŠÌð1üù[9Ïx‹¦ì(zض°UÏò˜å›§€+­‘~ÊVÃÎß÷" ü¢œž¼\Üa6‰$~ÛKäŽ9mØ$pÚX)”m’ž P¼ˆ§%íGع¼Ê·/òý™¤ŸÙóË82LûYšB¼D{î!¹Ø+{Xœw¿"óÀ²Dž¸'븺3gg&ùë~ÖØ¢jcÞÖ„T»¨f¼ÙxŽ&v=›€ ' ,9—ó`È?ÁípvfIœ¬làÔO÷nv†ƒú4í¾Ùåcž`øoöðµÎYœÜk¼ è{ãi° ΂0ø<×ZØ9zuYΩÄÏQáºp›ÉD˜Cúó€G/RQáé˜ÖK‚åÛ¼¡…,_qvgü Fâ^’Lçše‚4®/&$=âU3ÞFûv‹qs/²RBGQ%µì­ì[Q[–Ù½k3mŽ#¾`%‰!¡ƒOì~ì°â;Â'ÁL“0éë†Áüd õ,ü³çˆø,‰@ä¯0!°^€]hP°`vþ7Nh°íô2ìÿî‰%}ùYõ¬¤i“‰ó0+ƒVPqœeâù§'çÿ¹æÁ@nP÷ 63ñèÊ)៟|qòó),Âx/ìÐ!@ºƒv§³8Œ÷ìåÉGON?ùëé›×o¿;yüSqòøü¿>ÿ#üóäO§ÿqòñ“Ó/Æ-NÝÉ£%2ÌM\ZG˜ñãIKü“¤n4›÷eGjnø‘ðÐÀ ”9X*˨^µ2ˆ’Î ©¦ž^ Âä‡ë$”!º®*Õ2iú&Ê \Zf22 µ½!ŒnÉjhàV(Úk†QBJÒ`æ ÉA´¿¸™Lå÷ä#NÆt|ÌUJÐÙL“]ÇD+éSjŒ½…Ž4ŠMÂi~’3P X _!¶ÞU죞Cß‚éÇ»=ª]Ýåø (ô M±`.ò|b^êÅ{;º",ÙZà:BútäEؾÉoIr(—Ôœ¼1fàlNÿy÷XoÀ7!õZàCês0B¥Ÿš"Uçs绂B¥¶!èÌŸ<Šk<ÑcûLEX¨z!ÿÌs”cÒ„O#FÖÍò=`ø×ûSââ“wœV˜œeqsŸã=ÁG4b=íô.>$â\1ÆùÌ’¹ù*®B ”[ã£6¦âi(Vò\Âè)´ÝèIãIÁG’Ðã݉B;ûG¼ÂùÑ«\ ×‘àg°B2Áò_*÷7~K@1¿“ãŽ-n‚] &˜m “ó/˜§!f ÔqŠ‹—Ÿ°\¼¯ðãù«+ê½c­giQ\dc>F½þ ÿ‘cM ½0Í«Ê%æÖXù>ç܈>U¦4)ÌÕ0¨@¡ LøP*‡ÓÔÐußöGÕ8iõ¸Ü}:Ðÿ’úÕú‰. È Ñ‘ë$W˜¥ (9ÕîËk>ÈÍy‚Oo²ÿÆæt†j—DHe´X¹‘V»~Í«Àœ(þ;_S¨4º¶Jb‘'ì‡ø`§ÉRbÊ]ĹOórŸsÈÏ{„ÍÒÊ*WŽ5•&îQ#‹!±&¢‰ µ$Oqß1ræ—Ñ!°È>&«ý;ÝB’è?Ú§ãú²Œq¾w&‰LœŒƒp®èSØ2‘~×T¹õ = x-æùÝ%Žî î#˜OÓž=ù„P™ü‹2KEuŒ'Üy†à_'y8„þÒNw„þFy-f:|Z¡Ñ~êUà} 8ý!¦m@bÐYs{~ ­C‚cÖ)Äñäƒgªs^GBj^³Ç¦ï{áó¶ÏëHH °A}óBÔÄfÝó’¤X IE½=®&ZUZôþu¼ÌKÝ­½7rä£ëR;ÝšŒ´æ<Ð4¶r“Œš `Öeû äÊ`2k’P L´;Áé>Ür¬`Z€sk 3ÁX‡¶‹Øö¤0e¢%ÖëÝ0‹/¤UkM„IX^ÏêîÙ¾wŠ_õ¦sƒ%–?(û¶æÜpòx«:¥\NyÌ5áB)6EÊqƒ²   —; QJm¦·ÊEûZ’—ècV®µúì„”VË{¨§ÂÙðã£bk—{ÔbbŸv™kÕâH\Ãâ µù›ú jh‡Ev¼SYǦ?©c…´ÇñJx ÖANXØr/~˜T6à¡î’ÜÈËHãØNB_–\O§±ò`PA`å}øaxÜÊ›®[y¢j®Éú†ÆkÐÊXzŸy¢¨-1ˆ¢õ½¤Š:Ô_ïÞa›÷j쟵³¥4ùN !~„èðÝ0&½oN ¢ˆÆuÁ£äÃøsk‡Wz7w|÷ªµwËæp–sHÄáYª`£ ÛŽgøb]mˆ¼½DñxQ>>ì¡ÈÆO ™dƼÍhTˆ¥…£qt„Þº‘ÃÒç­áBQ7J]¬æ˜ÜRÉß‹RÕ¦—¾Så+ˆnóH¶ª'kzBr”m av&UÇxZ@ÇNÞ]P¥yÇ#q'/©Zû*´Åç%±,¾%ûÎÓꮹ۬õ« âA¸’irœÈü—¢SƒÈú¢„„ × íÃbÑ’S4íÐŦ 2ÂëXï.i±Z¨ _ÄÒ± 6Ò¡r!('Òæ¡9¤Hâî+-èùpŽ CN³Cr+¿“]ÓÊ–”+äÃ~Œâ‘$™}Û(÷1V~Ù”yu-1¯ÿ£Üç1½§Ê/áKI×\×)»ú…dÜ]°±îàóÃpšDÉ•7£¾o­§ïR<"Œ4ƒÆL‘ÀûuRÚ唹`Ó“ˆŒ•Ãn¢ÛA¡qæ(ÏJ@žRbšÓ€)DÒϤќœhy×T縊O25U6/ë¡Àtù1F&JT"ÆM½ñ¸Ô1²›å;Ê ã2È,d{©·1ʃ'8. +íµ9Û#òJÒ`Nù¹}hÓm¥êr’ •¯@ˆt™ “—ÍE¤jv¤ö„FCÀœ+ýLHoÞÎg{¯¶»÷GÑ–| ‡µù´ƒ$iHxµt6r`ßþ ?UÜ¥ÄȘôªJ!_L–°‰òðæÂ¬E<ÊaâÜÎ{™ø¸9 ªgœ¾HÉ õú¶ýqÞí}§5ÉÊ·»¬”svXn›Zܪ³,™\7²#º…A)›g–$}­?w¨–1•ýKhGâ¡!_$ÉRhEÞ$JR“ b%µ ›BîŘu 9K æ¥]‡4V½¶2”bB³!;̪ìõ¨¡>••ùÇî_KÝ`è;ˆ9·ß¼._§¶JR­ƒøëo‹Èî"[8_>‡²¶%DìËCóWØ˲Ádëü:î¼GDj,š»nY•‰3&x¶&Bª©oL+®ºö/ksuÒ4’¯$…üCº‹¿—´d["‹(l´œLÒÃÐUÏV•ÕNm“^•m1Ž×VS¼÷ŽÄˆcš«kšhùaòñ-©‚PeåÔ'FÉ(õYD–²gƒâ¹JË`µL ºSô]§ƒüõÔÒQ¬YÜæËaév¬ý…9`\òªƒ¬:™D¬p³_IÃdO0N`äÓÜzV㻑@ÌãáÓM–ªÐw°>q8Vƒ^úI“M;B>ûupñÌìRü›·†Š- "îÅ”‰¹„°æu¨˜Z¯WP,¼£ bÊ Áþ»@E=Ó.ü«PÑçAÌýtTµq=éFjú CÈ~[F>ù ò<cË~ÃádôŠøŒ –21²³c»óÏtž~ÚGµñç2—ˆ¾ šµÑ—BËÜhÚb×gmnŒ9q‚ÆÎÇ·CÜôlâa0¯eŠð®ìX¯?ÑÎÇõÚOWš#|^fU¥'a7¢’XÇw8ˆ†uf$²Þ©B¯ÁóŽÓ‹°ÖÛ“3MµâtÂf;æòHÒ‚‡Ò==äGæ…;2X“síŽ>|™Ã˸ÒƒjÅ€Iü+4J( G²* ÌMNH&…µqB•À¹YWßù^ZFVr³²ŸwÒ %U¬Ø7“žÙî¡ßxžÂ>´"† ê-}û>'²œØÚâ–Ä BeS9]Å%<ÊÔºIâÎ8˜y÷¹ÿ]äè?îãôc M#Š å~½ jÁCnâ¶±8ÍÁYiª¶:„üŒÎ 1rQÔͱ`:ÅÑzvã^Eã5ÿy d€&éEÒì©ê‡ÒOR*aÖà0LòF@½]4èDë5å^šüÓ±&¯ '§5_yñ˜;|G¨eE_WÒ¶Ý–RǘÉíjªdQíú)Πd?yô½"Æcûª{©£Ÿµ]é Gú }ÒK¹"?gïLªŒ”°O!+Õá# H]ÿ•5ų9 c§*œù–4RäA‚ä4mÜ&¨§a9¤òÜŸ+ɃÅ›ôýä™èЈø µ°7U²Îýðf‘Õ½7útvŠú¬UÄTkù¾ÝŠ-¾AÅõǸEYà“SL ´Ç&äÅ=$8½¢hò~b)Å!9#Á9ZpdvqJ` JlŠQ×5R&EÞÍRIïLÃhÂaã‰Uã?#ÆN[ŒOø%UI£Tü–¸~‰Y–Ì [c~lØ® Zˆ¹ kÍb×µ#èm–Ž-!ab²Ðcç–6€•´>‹™Oï²UQÕK¤%¦ì« ™ÖpîÂìÔ¬¢êM’^·³•£‘*ðßWކç«HR,雨¼Q©ß¬7“e“[‘ZCž©ÒhRÒ:nܘÿö´|KžÔsº’§—ש×rl­B]¿Jêa\eïwTTw^íYœ8¦Å¹étü$üåVrWNïÕƒ›A/ïLÓýB ö,j±¦RÚ†îÎÝ.,ÄúaúOÓ:Ò™wgɆk²g»’8bÚf²9ªàᳯ®vîÉõ—,ëD×eÌÝlö,•H«2Öhö^¼¶•\ÛGŒkrµ#x7=‚ëî°à´Ýu´”¦›°N,ñ…'Ø´h¬içã³Ð±'ñætY ïŒÙhäƒi*oz‹­lˆdïÆ¬_mü~MÜ€÷Ó‰-È©ªØ!¾LìVÙ±nlÎÜ [ õ:ö½…­ýQ¸I¬û^éFÚöÖº=ÖMQpbo_×—Ç>U"§§ˆ‰4¸’4 \Å©ö£ A ÆÑ+CžÜABo‰¹ñèKó˜{áŽÈ{ý7€VÆÒ=O_Ž›À%=ïžEwzÙk‡0gÇ“ØZ*ꣂ"Ú+™6ˆëùžÕC…WgnÔ{#sôE8V‰yъ䎔&°ëûf/Rµ b¹êOß×K ¼ŒƒT·ˆãcÒö¢°¥ áq¯R ©–7ÆçÕÊÊÍŒr}ÇâúM)§vh·ÇÃ*0ù^Ó/L°|n”~vë˜ü‹U»Ü1ÿ"8Cî’~á©Vô ¯<µ¤šš÷ ìËwÄ4÷ˆj[¿È¢ l vöRï£^jë =ÓÈŽíA¶bP`í·]b×ÍàëÑ©Oë·W´7îÓÂ!†| ±¨ÔKװƲ‰¯‰#ç–_œüv#endstream endobj 473 0 obj 6870 endobj 477 0 obj <> stream xœí\ë·‘ÿ®èØÜÍžvóÝô!”À—øËåœ âÀ6‚Õ®¼,í*z9Î_U|V±ÉžYIÆ]€X°4Ãa³Éb=~õ ÿv6OâlÆ?éßË÷>ýR(uvýúÞ|öøÿúÞßî‰Ðå,ýsùâìWç¡ÛM“Ÿ½8;ÿî^@œ9yf= yvþâÞ×;µ7;½7ßžÿ'>²Ììg'¹ÀSçWÐó×ûƒšœó^ì~»“÷‹ö»G{¹ûÃþ &­“»óÚçóتô²ûZ »3ð²ipn™¤0»_íõ¤”´KæûƒœXv_à³ ü§Â[Œi-Àìñ“³.uõbvôåi,í ë¿¡ƒ”“T>?¦”Øý~_æ~^Wóž¡“‹„7 ]p®Ê¤¹,Rh|†™´ñð€’“˜… ¯š¤”0í?íå4ÏFŠô–ðPó~òÒ4uéDÚ¾¡ý4ë³Ô ïãÞü( s›õîi]ùhÔZH¹»ÏrÒJîna ^Â×&,-ï“|3b¨Üfg»»Þä"¦æ~CämíüzLÖ:{\ïó ¤Ò»O°¿ÒÃoðI…^íÈÚKÒó²|z›¼,N©üÆÕŸo ·ãrp͇¼èƒÀuÍ2®=>lAŠ8õ•²0³»_[[ÙYSšÃÆ*a&Ñ2ÓŽ_@#5AÝâ²…[,­sDšžã# ¶3iŠoZ¿á«.q»´åkSÆ¡X]u^Ev¸@–’¦ìòÌmV|1é›ÝH¨Oä_*ã·£æ‰yÊaud ’P'ÿ<±9,ËùÌæ„òß“§ÊP/+ϼ¬\:à)ÐøE!H2´. #ÍSW®¼ÝÞA›ô;üòY;ªd%SÉyþ 0.K‘Ö H¶CØ<Ðz³A†™þEƒ¨pv©2’ uþ¿ ük.Ÿ>ÿdn‹ýf\ØäÅ]Um¬=EùôÙ´„NèŒSù¶4vm,[Aýݽó‡_ï~ˆfNÌ„až×°#.(¤Ë"-+C€¸KUꉨwöX+¿iÜ`Ó 5Úi€ ÿO¼)ŒYHûAi‡Ë¿;ÇÅI¿{×ã\²Î*To×r$£>Ý6­¸ ‘ípm!];‰ XÀ'¶oú.“0ªÉê,‹cÙÊBzöv+‰8=¥ȯ'¤/‘Ød%›fEºH+£5$Cô¡@j’\éá®°µ–ì@ 4Eú§ì‡øNow(_AØTWÌã"òK;ÓåõµAP­¨ s3K€]ÄšUî(kZv{“/¤Ž„“µ:@™ÔÂàï„Gp0fc'ƒÞúG¡™d²öRÎŒ98½ü#q°„+F@`'dA i }[ ^™|€R¸Gd(e2ÿ6[ñ:ú/Fk³îäZ4˜o^u”âËê.$Î,PÏŠZ›.&"¼¤æÞ¡s Âë]®£ëȽ]lu²/2Â@SjG Z£Ä¼3T0öCœ3`êZUbâÒwœ¥:ø'Õ$/ù÷;ÕgºûÒÎ7:pÁ{ôž!t*C7A²¬o½À¿#­@•ƒtòÝ%¾qtÐ=ÓL—u­ßU@Q z[)Š/¹â¨»§]{%äÍØ,°WªºHOÖ”˜É¢.n÷†<ô¶™Ô…Ž4æÙ˜”à¬rR¡4›ü‡½²Jpb vÂI|¹ ]Òj¹ra’6d(Ùs´Mïˆ 56HøüÛÊóY¤…E‘¾ ¿F$ueò½‹NçÌm}ÆÄßûý¬6>/OjãT»Ï¼)¯kã×½ÞÑÆôéæÈ@ßR˜‘/Kã-›»«ë~^~SV_ÔÆ:‘J¿Í³Ã0`jü夿ðC^‘ß[Gz?¢þX[#cþ(kßc‰í_6‘q éüR€Rù5PB$.b]"˜”1%íƒ?à›Ró¼D È1ë&ÒÑgÞà§¹€ivâq=­Bì Æ”¿æg†B™Þs^Ç$1Öÿ‚§¬Õ` 0ì©e°æUWmå˜Æ%Ø&OÛ¬0áë8¢qj D"d#7/㪵¨ÑcBÏ 8Wùm1Ý`¾ ²dà›Þ«ôÌ;4þ¡F¼¿ˆKYÝ%ÎJ•ã ÌÅs“æSxÊyk‹L³`ì‰Dl÷zXl/1[¸ ÃÔ•ëW¨8ùL‡4mÎÃ@5`Œ@µw{ä±2 Æš9€é´BŒ'ƒ÷Ê»6vò‹%Ì:†¡jïX¶ËßÉõÐèÙûâ»j½á9ãì´ C’ ¦˜=:Vw—ƒ κ:#‰‹ÞJ×ñ”‹j­ÑT–ö÷‹²‹z×.zm d%K[)Ü>Ô´÷+ÛÄ`’Šx¡¼$NÂÙ€þE*]„mTàc:bECe*4 W¸¨ƒ^ʇ—‘Oräò¦7~„:Â+™VVÅ[ K—cnk(xqÑm\æ0OBõÛo&š8û³fàÚd7xjÖÆ§íp<™F fjR Ê逈/¢w8óÑ6Õâ)Ð5áå&º?Õ hXp‹G‚yJÅ"~øÿŽÇòGÈÈ ùãËŠhžÖÖ‹ ÉÔî—@)pw }gX`¶F臌2/©ˆ&x_¤¨2“fäbÄÄîHì ø8$‹¹8Å¡%öŒÛò 0Ø7/'9ïpå}Sò[Üÿìy³#¿áv¢á½"y»F‡h(ÂqšO7´NÈ|j’ÖŽ˜f(È ÎÈÂ)33CÃS–&'[s—£f*jõkîUc;t\Á$*ÕA$¹„‚9èEܳV¨ -1|4J™8­‰†Ê Ì”ƒ_£¤î °”ÒÈžwŽKléŽ~XˆÉ*Žx„ÄÈ:05!š8ìÊdöÞˆ¡PI=Ž;Îäc’€þˆ*ç¢X‡pR|‡pBPÄš»„p˜—”}“Ù6³l?CA2Ö[a›N±¢å[Ξå!š6"iÌž`itÊ ÔAÎWˆ!5­=!©Ð–ÏM}Ù²\ÌôŽÚÉLwݼŒY;"ÒyLËŸ¦–aìÅ?AßIÄ}öhµ3 ‹YÌ‚cí䟃%EÂë%Kå였^U’œw+ÏAHãÔˆçœ"šÒƒJIÏú†ôðý*Diëc”Ÿzî‹"IB¢oAýEƒ$ýÞŸ¤sõ“€¼©•¥ÜJøš+÷gL c±‹“SÍþ2î¿.¶–ðz.>¹ßCøO$EjMœÅf:p ëÔ… r‘^\lj.°$ú""D¹äè2 žôÄ ï× æ]oë(ÆÍIþç½G*†}µL¯‰äÆoö bj.¸6³ÓÚP¥]Ú"ÄÅZ¶:¤ß¼v€þ« ôŸ°=$«#›X—‡ÊÇ*ÛìX¢e=ÉgXvÿÖu@ÞÔ\¬æÕôj_Òá¦;qò¶Ì+'h% ÐN´¼|ù}–&ÑJÎ=|ZÓGÛLQ6!Œ`†+ä[ßÇ%@ëu$ž³8ÛóhÀ|­‹òLHt)#úo€‚e6­Þj»qÈ¿KÚá§6 ¯XÈ¡ %8+œvͱÉ®Ã^ö ÐrÕ²¡öñ‹mê@ÙÜs’[–pRCæÔXÈ¿‹Ž“øžúà%Ò·jH_yØ3ÅÇ^Ln)ÀVpLä5ñþ¸Ø6VÊâ‚$‰ÞÍÕnÄK”^©Ñb›>z&êqO/c¤ Ï n1@_õêÚþ•NjýEm­õlÇŒ–ŠÍêùË´n-Ôæ*×/XWWxâ"eg=‰¹©}ˆ5Ô$ç$K’H*¹®T0³¥™ßA.먷E ”d›c"°ÎJW…Ëj[V+Ï`¯Κð‘ïØÈ¦ÒŠU«ÅòohGšS3®I*40 ð‚šþ*Z ¿Øžßí|p4ÿ‚ýÕ…ÿQàœY'÷ÜvÝyœ&­†éUÈÐ@ÖAyXÇ´FV0<Œ”HqžíOîE<…Êvÿ¨Aý˜cðM¥ê¨Å… C”íåfà]ù™%&M¥Õ:”Þä$¶âü‘*ŽcÒ"¸²'YU’©ÍUNš¥]3" ×tÅ]ñÈHŽ ¿QÛMµ{TÂ{_‘ÁÀ¼¶™d¢£…"¨ ¯ÖÈÚ£J5ÔŒ/¼Ä'Í›ë ^ÝìpJžØ”ê$Éÿ³i@M½Òªãb>.dƒ d•ÏkŠÖ37Xzd¢‰U¥¨*q ¤Ó•­l‘!9ÃG!г÷ ‘bZ ‡åoª݈ËÄ:¶FÙF!Øäpǯ*ðí­Ñë –²KH÷oÏæ>C½› 0O*Bmª…shäØÓûT7FªNÉðÜ: Ëmó²'eQVSËã<ñic¨ "êÁÀ ÕÒÀÌ8þ 2OB¨1ç™#¥}èÅ#C›çŽÒ¢8Ç“]©p$bG»†b+bk¬ŸÙCž^ZÅJi°<çÒZ]3¨ß¹åú ¥ãiU‘G’Eo&?›A„’( ŽyÖnL§oTÃ’cèϾ‹àº:=×{Ž}¶Š»`”Kl-Ô£§ˆ.šYòn@²ÇŸ9JØåO{ÙÊ…]ˆýúI¨^<ïT¯×?.EŒñ´/Ñ:=5/ Ø3‘[ßã˜oj t!ÝÐñéV´×+áï†9›XÒ¦x&ш$â¸ô¨h$]8L¬¢lëÑõ XD“uˆejÕ©fV¢ÁÙý¾¤³nYí1Ä{›©½ L}Ìlô5q…ã2Þ=_#U»Ód<¥pÙµ¨–C„8ì@“hÙ0p!*ã9  Z¼‡2å±ÜT…H%f‰`bj´gÌz“ +­/ zpá+Ô´¢$KßF»J8ºyÓѨ ‹¤®È5#ëìb<â•Ù«DŠ$SÇ nâb^8Fpq“¯ËUT„‰zÁo’""˜îRqéP‚€áû™Ó7YሡaÉ›VXîèF ‚¸DV«ëá‰ÙT÷F·¹8F~’°„ïûwªŒniCÓ\Rw‘©áÛ"jA© !òæÒ¯Â¥™&ãdiÙˆ|X†žH´³c%Êù “¼Í‰©´ŽuÙXå³ú©²/ ú¤}÷cÞM·k%y6¦Õ“Ä)à擄BYœâwÌð\nsv5!r07¦«Çp¾ BK}K‹Ûœõ°N#Ü›è!3¤©ßã!3¼KJˆa"^#©zX¹ ­wcË i¹¡­­ä”^z©ñ˜ˆŠ]{$Ä·†¤åÉ#T’ýW ý*Ürﱈ•y‹ùfÏ‹ºÆ«â,±Rv®f°3ª™dúÂ91L‚)ÍP HI[ÀXM(Ë¥…áÎÓ±ªâdknã$³ Çz1g{lh¼ç( WU†ò{2h4ÛKlô5EB-¦ÏQr—÷±ÓN]½ý1´ÆÁ€ ’â':·¯–h- •keh¹% T¯5{PÊœÇ(õ¤3ˆ€ÓätPWZL|ân[=Üzáye)©âhËT~¬Jdàà”gW dPÐD–¬¥Ðk$"ŠF¤ÖèH]¿6‚ĹxDŒ,zˆKSÔ¡{ö”ÜЩ ¥eŽÃÇPëæ¸b–Në7)©ød¥J(¡[a74ùé6¸;Û˜¸H9xrÓt¤Ó,©ˆ ´$[:æP}2:®b¥ 1e¯Hé°è‘Ž´Tv¥£T®9™‹¹Ã_ê5q|ÏŽñp_ß"uØ‘#Ð-ÿ[ Ý^C~ò” Pàù5hÉ+ìfŠÉToÖdm"`Ñ•€ïsq%V‘ä±E%º¬Èͬ²-_ë6ãÖ¹¡â ;mY™CA?ìÃ=n±'~òBW§»§˜´ôâÝ0nhV1ƒìIÝ…-6Ü%ŽaµáPô+½6kàº<†ì¨â‰uR;|Û•b @v£•ü NÞ³Û ù–ñÄÅÝ3ózÞt3òÀ[ð¦9&×Í"œ<&™}æÐ&ì"ܵ>ÁgÆçCÒ‡>e £ ï»\Yyüóó{ÿþOé¯endstream endobj 478 0 obj 5592 endobj 482 0 obj <> stream xœÕ\Y“·‘ÞçYýˆyS·‚S,Ü€6B—-:dÙ¢é+VÞIQ qf(’#›ûë73q%Žêžá!í†BRO @y|y?®‹8]ñŸôÿ‡'wï ¥NŸ¼9ùéDP“Óô¿‡§Ÿ>Àf-a âôÁ÷'±qêä©õzòôÁÅÉîÌÞì–½\œsj§è3çÃ"W¿ûr/wŸïõâ½5~÷çý™R~ Aí>Ù+³û þ^œ«Ê?¥Ð»/ögbÑZÛÝŸög~Ù•~*©á³»¿Wr«Ô»?àGRJk¡k¹{P»»‡}ø V·ûÞ¤.•ö¹O'ü=ø-…ç4jã–Õ™iH ‡-Ï´ ‹×§gj]œ!68‡—±GÌî þ|µWH®»êôïqîBÊÝ ˜¤±‹ò-³Æ¤éú]0"f=µû Žñ,/uíó4Ô°àÊížæ·—øÌ.Z‰Ý?©KB™öSZ>Ü+í´Â·ù›‡Ô¹TšH|‰ó3ÆY £Âüýbl¦Ô)Å»Å÷Ê.Fk¾0Kw8­·‰Â†Œ¨sZVøÓ/kðÛãj·'ÙûBãÅþL.Ö:«yÃò;‡E+[–—H¨¢v¸­Ï÷È XÅX‘ù#Îv™TàªúìQ|& Z€ñ¥²i3ˆÑãPÁèD~ü[®z÷üô°ûÒ–ENH—÷©Œö¯ýÙ ² \°Ôæa~´™° (”g‘ « Ï^×O‰Ó3‘gÈ·«Œ´â7ßïA VØlž6AÓG–½¯|Êváy•²÷çô`_ÀýÈHsF)CÕø"T®<õ¼vô ¿×Ûü”xNK³¡6y.ÎÁäÍ®_ææç±Í ÊIQ}ú@ƒ6ÐAî®+ÕÉ×–×uöQ%î%Žh6ßîŠÎðÉÞtß‚b3FÀKbôU,Jf>g’üG‘À–"Mͬ:ü®Î¾²saOFû·û´¬ðáqiÐÂÀŽÚNhÙ]áŒvÐÉðlÖÓ!+)?©²×DÁ—ã Ã5z=oÉUÕ˜ææPkOŠì°EϪÒ%„õrY%¤Œ²£?£!„_¼ƒÒûë½wñeV¤ë¶Ð*˜,c¶Ê£Ð6rØr{VTnËd•¡vݼ‘¨‰”À©†^û­Qgí— À'{hÂëÍ:ŽöY5w÷t˜<@Ôa’Ö5ÐF±o¦„»/ƒaB€Š˜QÈa™:õ‹ ¥…†~Οl|Y4r+Y•M™™¢y—E!µM±Ò23Å E´~Y,¬¦—d {D’Ö¨µS>ËVׄïQ}?¨Lß F¢nsðmÁ™HöMZç@úÆIiL¿ùl:hùWP¤†ïôUcƒaN¬YUöT;÷r’Ÿ?JܬB‹ÝV`RÛ}‘š±ŽZ’/‹ D íl  -È&ÿ~O6½ší vZ£;ŒÉP•Á¤°\à'h„=TdTºtkDIåý‡…ÛLÇÕlå)w0Ã[ fquO +A¶³nj`²(:K~.rÒ°~¥¿„Šˆ¾Ö°Uà\%Ùz®ä±ï±6fLØ¢ëÌ´˯‰æ¿JjÐ8ò’JÓÁe®î[ÑŸG=®ÊŸW•Ê-­þx‚?˜nd7aˆLÆ 8¦Ì¾AaN¹â×þUh½Ã6ÿ&ŸãX0t@—|€·‹-acÊÄ bb„3(˜)oÕ9gí%sbÔ¥q¨3]ïWGdaãP&"¸ÈVV©ø{þâÁÉ7'?*µXòáaOÀëUÇ95ÆÓ#ŸÞ;¹{ï÷§¯^\?>¹û×Sqr÷Küϧü þwïóÓ;ùâÞé7Ûñ‚Ö—Îñ¡×EXg‘>Æ ÎOeþÞHÏ·I±aÅ•{ÿ¤8‰J€“ÂdûŽýýÈDþ$ê äõA1iÍ#±¢S­÷ªDÏž3g \¢¿Uþ‡s+]®K$¤‘S¼e!/•‹’~Ê=iövÕSixÕ÷•Ù#ïl\¨›0fÃ8«r+YÔÖùëMY·ÏØ 7ÅGߊíõOŒë¯Û¹4J¤ÍÌAʰùÌ£Ú ?Züès€¹kYã"èïòðOtÞüâšÚêµ ¥L¦!².2!æU²î0ÀÁí £P«Q\ä[Íÿ( ޲}°4Nª¼%²‘¬ä\ÒR´ºS‡“;mÞ-h¡d¦òo%p8/k{þgü˜4x®áÙûœ©NÙ_#8¬t¬‹ƒY^U4„Ú«i²X€’ka/–Î.tu¹€ö2 u$–àj¦ºág¶öMœäº‘Ó,œ\xPãÉ|Îã–“}kƒ’?­ñ³”¤Æh:ƒPJMÕ–{;‰ÎcŽòÚÆÎÏ·öz É"¼•ý\<ódÆ––Ä3›VQXa¶ÿ5¾—¢e1Èì·ìV“ÝȬazg9²ÛXÍÖcn¤Æ»·§23Û3õ„ãV‡-éCõCRy²'6Êþ³ Þº¢x +*©å"_<†Ì"gìiaØít±¡“7(P–Ìñ­*,bd¿-°@˜$¢5Ï.Ì%½N†eµ®ù¬aÙÕR}Ž”\HC(ò˜°éœÈAÉfPF²Eè”6ùMr¶`)ÖRA‘ uÀu?¬T† ZÞ£ÎȲù~׫;œ¨)–çmÌþÏ|»Ê–m"a¬¡ˆd"»kõ†®³Ù$ÞA‡ñ9‡C,f‘«=„Þân¦ø#À…CÌMíf§fËYÓ2ähŒÐœ¡Ž¼ŒõcÜJx’/1ZÌ6`×ç-c4dD½·–\Á%ô‚p“ªŽþ œ‹]¬3#Ÿá`LÜ¢uð,“ü„pq«8G{ƒ:t¢ï'@”…ÆÐõÀ‰BRB«‰çÝÚ¡ÔƒþÔ¨.ŠåÇ„ðÜHG†²[$AvE#e4ù!ÂãûÆçz^!q&µßtèÿ}¿¢Ðð‹1*Û⢀[úv³¨ègâúE‡ßè(Æu ‡¨SiN•?ôȪ!ôb¹Kíþ})M²7GVÑõr”^K„5n[t”.“Ø wОÙ&'ÌÿÁ¥öÀ¥ûyCÂrúNm_OÇH™FiðÝ&Ê­ÿ›Ç 3&j}õ/0d­Kâ;á#Z¯Ö?›û9È‘ÓHg>h9Ù¡¶M¬HÛ.† VxÌ­oPéôñþÌ I¸žñYAËÞÚÜ F´Ášh[ª ]tß ™k+ ™OMá‚:Ä.—õÀž=Áj®˜QocÚ’ Ü€ÛÈ7-æz–Šíô2f˜§<ÿ$´N<-W)ÒÉ(J¬‚kjoS×'/ŒçÅ;9ŲQŒ”bÎD]kΛ(ÔëilaXp‰D.cÀõÚé|ð”:;³Äñ±æ£5ùqìᬤ³+峊ÐÄÀŒ$*Ë]0»‹2üÜ*!ƒ[‰Ò=é6y€QÕÌ(¹ÒbÍT³kD’%ÆY•}ªø!FoèÞ­ºjtÖD¯š'pjÅJ~’C°è‚8²âê:h5êÉc.iØ«FBSb’–ªÕÿÓ"¹IЬMÐPyû¦&qȽÅ.Û@,x(à̲§Ð9y¸ZFR“X½ßàÀ‚ ±ûþ‰™ÚZKzKsŒo¿/Ÿ–v¨L½£Šê»0Š\Y+ì!ÕÔq|ø¬>¼*_ÆO¿Ý;}Z¾ª_nù¬ü B »fß<Ÿõþ¢<¥¬E<õq’uËú[á8Uì}zxÞ<Ì?¯9ed…5•äfÒû¨Åã[ŒŠrüå öûQÙàgå׫fÓËz©~Ó-¬©;¸éø&ä‡Ïøzç¥}OO݃ü?½ñãn§Ïru?ÆÈ±˜ !É×7 ‘ßGKïÃêjnÀñ8ÜdÀá’w÷žmÈ;‰ÎŠ…~¨ÕzqÄn=­Èãfqj§£q¹˜~t'°ÏºÊŒàΊ-dgÓÐhÝâl¸w†l6ùñ"£ÛØøÑ»àÇ ÞÝÿ;~¼9®a¬QWðböðÑÀe¸Ùw’)R¬†ÿWf·8—·f·küÏ‹Ânÿ(í0\À¶…6Ð÷îßÂk®~ Ðü«(<¹ÒGuÌëY÷ÏšN_7³Ëý¸¨¾ö¾S‰ûU¹q¹>x(Èʂ①Þj‘‹˽:½¢ Ǥ­a§ dVMGÍ”Yë}¾Ç[Œ –Κy±8‰Ç[a…,4À¢„NQÄ“~J\!èÔ‡Q‘uÑÒ…źÅJ ˆ!· r1šˆNä)-,Æ3$`>I)œ‚’Ëú:önmî\h3uIìÍW'>š­áXJ›þ`UÁ:¬¼CåÄ8u3TRD™õÇb ˜ÝäÔ¯ÌÊw­çx9Pϼ*)ÐEšÇ. ÜÆøŽÍ¬?Í%ØaÅ!°YP€ãžÁ˜˜Ÿã^TÎ>&0?œ¥ïÏe´YP¿Ík<_Ê=¹ù¹Ê¦Ž» téJñA:ƒÀÞÍ«r*?5¾Gs lRŸéCì¬Ë 1q3ßû÷@šµš2]ÀµMnT»ÐÝÚp"מ×ìÆ›çN£Rs§)ÅįˆI'WÁ-ƒ±ºãÎ>^²+GKмÖt³z2áF%h1òV%Üxß ׄfék–pÐÞt§õç›Å85Ý^B¼:Þ^RB×Ogrs‰féŒè/|hê³62­MB\e9l¾Lˆü-»â™Ê=l/öèFJ­æU¸3–b'¬D{È^ä㹌içžÄ•`ÒÝ(ÿÆE'Öu%p³-Eu&꘲³GÙ{^öÒgFÁè#9ˆU¼â‰@LQ®Ô™W÷Äê‰ B}¡K;<@¦ÐÞ1”Ò¶Ç&~ƒØõ´]ðkÇx57!?EWåŒ ¢Ì¨[i|’;×hó›4ÒfªæÎm5GÊkIv‰ÝH¤”f®]Bkc¢ÐO Ë6®ØéÒ^ÅZO¿’Jº­¼%“M·[m]KŸ±ƒ*ÛØ$VÉ+­{nE:}çµhZò¢¸z0@:ÛÓIw@¸A JÍ}sKȤòËÀÎÛâš/ÈŠàb®>³2SųÒÜtOºRÔh|P˜hÔà; Çþ¶èÉqóú+r¨% 3È×§òÇëH&µÄ…“‘œ6{¹yÇ‹©‚‘WºRü2PÌöà7 Nn_|p,JÊž2LÓš+‹zJBS~ºUËGmžGœUÂàôµÁUmj¤òÕàZâÅÁêyÑÓ˜YO×%Ì΋Õ@x7ÚÂnˆ ÇÛµbc€A3;p~(R¤¼êc²’õä‚m*No´)7©È·QÏåˆÉ¨‡øqv-ÄÖ}8ˆÔd,Ø<0,5 C,#EŒ2Å1d¨E,Ón_Ô­·z´Ü6ŸêíJ‡#¦Ã/c鯡C mUÌö!Ðt"%^àÅf¼$¦¨yZïµ±KªAx¶Fœ´!ñD–5“Ä-•nòr‹š¹`Æî_cˆc5°e˜¿‹Î™ “ ¸¶ÀŽ3T#cÙK3ˆä½þ¥ôÛ˜7KFeM3jUõÛÜ›„ǘ€ò›(^ÍëEƳ“2¬TªØÛº jδ®œ2´tX|¬ÛŠ¡´?PÍöuIùÙ_Ê/–½¿§›YÂ:^/…\öz -^/•}H–u-:ñÐñ(HCÆk¨%ãÕsrŒO¢oų²o{

Ýgþü çÉCšU Óëõ=ó8¹æÈ¿îãE‰åîïùÙö½.Rÿ"´cQ«}cÒÛ¢‘O˜Þ”7¡1¨_†Æ`{7®²Cº0lr«KHÞM4‘ðd7 × µ—¤%æâ›i6‚tÛLñž·a‰€*˜¾íµåÁ M¬õï‚øÃüõÀí‹©âôØqñCÕYñª€)¶"wÏ~³"jvçÀMñI.붺?ö8^•…~tº¤ºófqEtÓûô|ee41´«Îa™¦É)»þ^ªx˜§YØ:YÓÆ(Ö¾$ùØU¡é”! WÜìÆÆîLuº» 𛌧šÙQô†aµÝ ìUØ@2þÍÉÿ7¥áendstream endobj 483 0 obj 5458 endobj 487 0 obj <> stream xœí\ko·íg!?â~ónà»^¾É P§nâ¢IóPÚM(’,»µ®Ërâß>‡»Ü{¯d)F1"­¹\rHžÎýÓjØjÄ?ñ÷ñùÁ£¯™«³«ƒqõ)üvðÓóUVñ×ñùêñ¡¯f¡hp£c«Ãg¡¶2|¥­_žü½½êt¯þqøGüÄŽÕ'FÜÂW‡'Pó“~-cœcÝg=œ³Òu¿ëy÷e¿fƒ”Êðî°ÔyJ…´Ý×P* ÙNAgC¿6Æœ©îq/!¸¶¾™oúµ‚ ³ÝSüÖÂÂ÷* M­©èñÉh«:6ÚylK:EÛú3Tà|à¥τ`Ý}–|RFrPI1Ë¡Gư Ê*T”År&ñhfÊÁ‚ldÜw5pÎAìo{>Œ£â,öâ?šôO:¢sÃâšÔ˸fÒ £\­aB s.¬Í èÄݦ ü2<êQw×¥ô5È`NÝ›^I˜Vn»#X•—©Rõª:6(©º ¨ò þjç),œ”Œóîœ"§1䈉ÖÛ†y€¶5©ùª_Ëq¼ÎÒ^a“zPŠu#vÃt"¶c„èžSa°!.$Q7HXÅ…šQlI1ø]†,É_rá­F–ú_~Æ0ÒýÛ0bAw?÷ÜÁ3Œ'Gx–Žw'8XhP7ÇšËÎà+²b“FJŸ'ar¤f°X 㤘›¢8©"Os£F—æßãÜØÑ ñA)}¢"^á<(ÍGWòô÷ Ì´vgèBø…ú¹à9 É)Y÷›„9 &¨ßj š¤ôȃøçýšZ-= ŠŽ{pãPNVwŠt„÷t4 ªDße¶ Þ Š¡‰ùÚÖZjå•vtX»û¾Ë(Š `é@Ç‹•££Oe_T60´,” Hú¾‡¶˜Àr¼”ÄÈAíÒ|{äæixYÖÜI0n¦ûW¾ðú¥”A þr?aÎwA@ð¤<‚¡– <ÔÆb#Îy#@`w¥+˜z5=T%ü=Aµ€#.®ÑžE›lÓêÎQ8êa¬ w…ÂÙA•k§ƒÅæjm‰œ^RNåìܰr°* vAhmu¸ ÆòƒRšW‡¼^ø<ÙÉÔ‘ÞÙÏqþ†¬eDŽez4LWÖ“Tp4×ÐnWKH‡×¨çroÜ5m×D½gªÄB„¬ŒûQm1Ñ€VfaˆJ=©w’'õ(BÕ‰hëìSd#‰ íÀ¨%8B°YœJÛ}„ ½ µKfŒ¶ùäðૃŸVàÌhïŠÁ\Ù˜t5Œv{% Ö¢ƒ÷øéÁ£§Ÿ¯^¿º>=xô×;xôþxüå'ðëéïW¿9xòtõÕMÝ>©Qì]:ïúM5j‹”vnýkHépg¨¤DÛý­·°°„ü×Þw^Ο‚V8ÅtÏ©-¤à U~Ž_Ô­¢…×eÇ!57-%>)U‡øàÍ &joN V€±± Z«³ö ‚¾ÐZ1çáŠþWxƒ;³÷'À¯d¬ûÿzŽ?.ðÇüq„?~Lõ|•P7e¿§àp$xm÷zá£ï!Ôòæ,‚Õ¾áPxT Ÿç“\ˆ„íÝ¡SZÏ6ì°ë©üáë«úÅKü ª¦]uæ×—õw¸IwcEP»ùͦIæ®%/NÀü£Rx^ ¡'錷…C£"Ø]~H'=½?É…×ÕG±ðm)¼Ì…§ù) bÕ z¿jutT’Ñ§Çø•Á!‹¼Î« [ #1È»‚öU\þ„;í«‚6ïüï´›/rá›RX$5ÿq˜Ÿÿ£”›»è&›Öó;èæ†ýϱªdÅÞæÂËÔJpÜqÒŽ[p<¢"œzé tNKÍ_Z½E:j­À­€[>ú¥ÜZ9Ó#1F~š-t%¼¢úV1 !“@o«„÷Óþ­ÃÑOt€( ªÃ;¨¸gŠUnŠ0S…÷¢ÉOCã¢QøH¡fÌ\±sŸŠD.ѧ‡~[ $ºlÔ;»¨¸ƒÀi­!ôLcˆzäXÅç½@>JŠÚLÑÊšQa¢¿ ÜG¾Û‰+¬Èj¢$¤L–8«0¢9µé™KÂ~›9Úf’‰VéãwÂxµ˜fCÊfW$ž¯—ÄƦ HÁ¼P††­d 5%¹„!Ûùêàû¸:ÖÎWgôv@BŒ"Dæ&%r° ãqª‚å$ø¼,¡[ r{%ÄËE¥áiBHCÔlbOúF ðA –ƒ‚K8¦aN0äA;.¹g2)’üÂ.êDÿ[xÀÛk~ÂWhÞx£ =EOdÎÃb™ùþ@À²¡Ï<‰ßÓ°@œNêºBQ Ì!:ÓžAk*iM ljÁNÈjÌ&Qª?)hð;½Ô`_u·HŸúÉ••š ÃwÊ% × –˜SεÁ‡aÆø(—zÓP—XÞ@£BðCœ#]ÅÙ/ oü8 :Ž Fõ•0k6àH­6 !Á4ê‹WÁM…è0ÄžFâ ,ªP[3ªÒ› Cm¾¦’74¼].# j@œ4J{À-öuœ ó/ú Å•ˆ©?\n |,:_ºWû¹"Ÿ”ˆ5ù2ø÷6L„–^Å«|xLo4<³Ùx‚«­wî/kÏœp‰ˆ ±í¨“»ØöÔQå¼w2%>É™"7ÚïúU¥v[=…Ðì^ž‚ojÑSÈ--îù>˜øKYÎ:ifk¶L«1yé„kRÏbLÃÈ™9Y›Ò®2þ@—§ÑA=’–DêÑÀ7”ݦJ¼AO[G6çZQò§ÌŒ‹Ä¼/r©ßèÑ„TL³Ÿ˜¥}‘'­?q ÑJQ—…ÄÿßÄ‘Bx¾"n"Ü(  é÷‚H„ønˆ(\'½LS“ü÷%x$¯~1õ])¿Ö’¤¡æÑùâZVlGû´óvÈŠdáJzÒ«)뵇?70;œøÕ~]a5-7¹i’¬ÄGca€†{ŸúÍ™ØêMšv5Š5p%¼8?ËÁi…ÐnSb¹ù|”ŸKJÆþÒ]pÏ$Nj„Ì[Ä"UêoÄð»8"BF“³Æ‘á1£ŠP†ï%±XÓæÜMîv"X—HOÌø®Œ~a¹_¼Éé,’¯†Å}%Ë‹yl™n$Uœî…Ý29¥\Tååáû KÕ1»ß@™ç§ åJã)´ wg„¬`¦k¥™O‚Bš.®¾ÑMcÜà‚"=ȯ3ª¯›èoÅ™”PHúø ®Rk3£{C{½7dûEhÛ‹ÚëɶJ´û«ëWÊKƒ! º™S@^ߌªE¸ïöib86Õ]”&‰ºÇ !Šà|}ñúNNØê‡Æ–˜.!wVÒã£^U9yÑéÑ.&T.‚;„·]l>¹Ø½¶õ]ŠÉí+<5°¦mÉÑ.êÚ]µ¸{ä)žõ]®&[³£¤¶­Eý!?ú:“egÒ Føs›×ÌHY¶y)©+ô4=ÑÓõ‹Æž¾ñ&A¶G®fBŽ®&øb.MÛIÀdÄu! )Ó()ñA" ´¥“¢ï-Õ­“0£’‘SI‹§ò†¸@ ¾Ò,a¤p;‹i){f]\O 7jhù¤€~rŽ3Ën¨tù·ª„IQÙvªn^ òD%p{¾¹J¤íÀ¨A Ü*È-ùMñf·Ëk÷¹¬,²`ø6co‚ß1·ÌûÊK'†.Ü•\öð–…»™‡G]œ™[Üß¿Kî‘rŽDÞ÷ÔjdKˆéH|šrXûáM§=9DÜ4¼–}o®ï›ÏGµ+ŸÑõN²ö̰mZk¬¾üo/`_Œ¡Ó±ôÎõ¶¥˜þë݇Þ÷²U|gWñÊH¸¤s™yà*ê5TNü«?$UÝÅ —«(äÒÊ3ÚÜ=ßÑ)sñŒŠg!±ÄéæL©ó¢Åµ^µÆ@j¾Ì…A Bè^ì¸Ýó¬5Q5}c:ù’~>¿1Dî×¼Ø.çÕBïä`¼q½æ˜6R8ù·p^•»3µxíVS݇õ µ˜‡QCfY.2P^Ò!‡‚|wVƒÝîÊê’øþ”뫃Ð#STendstream endobj 488 0 obj 3968 endobj 492 0 obj <> stream xœÕ\ûo\ÅõïÏÄJý]ÄÞÌûQ©T@¡I¶P£´‚ª2Np"ÛÄ1þõ=gžgîÙ]ÇNE¿Õ7¬ïÇ™™óøœÇÜWlâ+†ÿKÿ=}qôà+.åêìúˆ­þÿvôãMVé?§/Vc3‡&Ï<_à++VÆ©‰‹Õñ‹£oÖz£×ÓFLÖZ¹Vá­u~Ì­nÄú“Í–OJi+ÖŸܨÉ9£]~¡Ìú«ÍV*>9kןÁÏIa íøOèøx#ídÒë¿Ö6ГMÎ3Ë Œ¼•Ò]®yÜ_ì€ÖÇ𗵺íñ{8Ï™]ãTÖzÏq©Ä¤´‡ÆRLœqAIùzÃ'ïò´ê/u/¤rë¿o¶~Zîþuüçp&Žn6Ð;1û}üöX©v£SKÍiËmjº•l²ÜûØÃldw\®'o˜ÈHuœÉõ%ÌqµvÒÊñõkxa¢_¿ÚH<1Á×Ï"ÍÊëõSxïØ¤µXŸÂ*Å…XßÔ÷/7[5Áq0•*/ Wnzf2\Ãð0°'Œÿ°á¯q ¹þ~³…]W(!#!µ/°§™ŒÕ‰F+åœFãF·þtƒ'bM'ÿ'Ó99Áž†´>î;u€óÌÖeµ|}_ãZ[#èÏK Ô¥ÝR­ŸçÞØ¥ø´4x£z6)éÖ?W–)Ýš5ņäíE%“ìÐU}Z»¿Ü +Hl¢òÁ#M…)¸~i›«úæ —Ž g3`æ3†pV5 <ßa$°aPT‡1tÀ3rÓ;õý\Q„ 56ã ÇdVKØ”ôB‚+cçÅÃ6¾ÀIŒ±FAÐÏÞBxÔù ;¾‹Ü£… ½˜í"—G%{X¦––›õO¨t­‘v¶aÿ@¦LÎ<è·Ìä¸78‚“ë/`éÆp™”6w¼¨}Í]c¨>«-âSÍ‚šÓpb…9âQ>i8 ÛŠCfùú첕?æ<¿L\V²íâ‚~{`-'šô5.MXÏŸ7¸ï¸:/=ms¢Ë€u»ŽvLÝ()#ã µ=˜V­tŸß°ùUâ¦îªr3^>A²틆=#™Ñ I.óÍIí/öï9Ì–…h{éƒHÈøÉ ;'Êùúßøç)þƒZ*è¼`ã T¿AÅÆ°:åüv!¶Z°8n7΄‘bÛËúðª<|]⊀9=’' Š/é¯o×iLBpì}ݾ8Çà|€½& ÷½òæ"7Œý®Êº_â?ï×UÔ6Ï+¹Í„ùa·åyyÉ$,–S¾êwÕ›ùeù¨ ê%¬->¼húäC~Ñ›ý%¥1?ü¡÷ðu³Ñ‹Ù?€‰€Ñ¢^.:”8܇ ’@V»{Ý´ÄŸ(t'‹§iËòÏëÚöÛMÃ>K<(-¨;3“{|¼ñAÖ•¿™Š6«(„} ãà!*iKx[‹G>ÖcDÈR] E,^£â¶¶‰"qv0#)t9•¸ËØW±â¡¥“4o—ðÏ‚S#Á¾U½ŽÜ °BXŸù¡š®tL¸ ÑNW`Xï€ÎÊ­K“©X¼³â'â_ïc7ÄfÓfD4`ªÿï‰u%›ö³¶ñÈ?'jP—†C‹å@Ayc›ñsѧµÉÓÆpÄÆh=‚ápÅ8Ž F¨†&ägªóÃf¸…^Û’Šþ—¶äÓÒæQ¥ñóòð“`0á·%Vâz ûóçå!Ñ“UÍ“Ù?¨ÛºÏLì™þ¤÷°UÈé!êãzu bÎõ±`2ž‰»»®,bT3TÀÊú€Ñ¸ ,Á]ˆØê ”sç/ó,Ï82qqÄÝÖÿƒ<½ n tGÃ3Ög‘.Ga_ë!ã_¸«ÊƒÉÌz2€Þ÷Íöqu¨–HM }t‹{öî5£Þ}°Ï&0h¢Jý:Ýê*7!í„t‹Þ*iCÏünåÇ~w»?ƇÅщû#-¾Þ$g,›sO.06@E‰@X˼kÈû«À#›¤ÝèF“ú¾õ€Kô€IÈYPc^—Ða¬|±98>ñc+‡$#l}CŠÿj§•=Å’­­ñÈÖÂ+@£¶î!ê;ЗHöRxq0æ=YP”³`]¼½¹–ÐC Nîõj Š06s“KHÂuAR0.üzãlô|9p<*7âé@ ¢‡ ËñÈüiÚHSMÏë­„E5݆BB`Ò"¥Ïe+M­l¤0àRÇ™GÃ…a¶‹¹ÒÇCAR-n£1‹tÁ”uÃO‡.JÓb‚Õ!„¨]Ãü”ú%­9°¨ÌºEË%†ØAÊ)†øH#е#sTf%P6ªnNó˜Q¸Ø”ØñáÜ ´j;²¤_ó>ÑJ‚NU—b¿“˜'Ø&B[MMV}QU"Q¯Ág@°—­áH—¾èàxÂÖ]÷n—öW•úXùç€xðó8‰œºB¸P« äǵ-nz¼–CbVvÝÂ;_잯Žò{$)5qMãà°Ö[Šh5°:¸¢ïò2ù)`4H€ká£Ô(×Õnå×á™üE¹>ˆÿëôbJTÉæÅ$Ãõ!fÈá%ÔåÆŽÃKÚJ<¤ÊÖÌŠ66d\@–»ÇÔzÐ6úîzòŠVje¬ü°Ü ûP MÔ Äǹ쪔ËÍ +DÕY´D(¸}ûžŸá¹Öº×ÒÛ˜šéyeC&‡à”g4õCI€ÒŠ¥¬I»6|R‡4$I Œ;Åì†Löƒ@êÜ»„õ’ÛÔžw'ç˜Î{·Ý?m§¡¨Ële¹žEî{qŽ #´÷ͱ…Òÿ³e6΢ I?-ï`^sÚð»I`Á*(îH$¡ãC³“»@m(È w8Ͻ›7³+Öxb¸[,T‹Œ‰ ¨œæ)Oæ@º´IYd%¢~»uÅD^L©Ãߌg¿¨pæ;݉âÄ>¯<ܤWY@Õáq—ü\H£˜’»K™DiwúO‰½ã [³MXœòÉV“Øóíǹ„±¶Eö6 VÌG›óF00¡áT µ`¿;â£Ü÷ý¤”ÇYìÛ²]k"ï÷æG²Ȫò›¼FUÔ•Ý1.fi;§)ÞòŒÀó‹Îëœ20¼ÁçŰ\Õ¹/‹"ŽBUÕÉLëÄO‹n1Ј»bHYÝ73 q~!Å^=„ÑhÄœ…y^çlX¡¶ŠÖÿ6YN‰V^xª‡ì¼™gÂST¿÷æù2*NKØŠÛr£Ð’ A+Ë&§fð>u )3ô™¨„2±Ó =8 òŒËä“>Bνváp¡ò/½ŽÙ‘¸[£:\”HÏÆiåL C±šP¢ÿãzô%ÐFï¤ÊÈOD†ɸiXÚ¨÷z«ÒËËIÙ¯ýÒ¸méä“EÛ”60§ pJû X¢¶ÙŸ™¬¦zž z0˜sÛçÁw½ÚiéÖž\¦$… õ}?%6Ç3æôNEÕÂ7-s5e‡>z^7JÊq—-ÊìñâN•MÒ‚ûÊßð¾àwJ0ÕœÑyùÕÖÀÅÆ¥‚:ÖÀÙyñô"·ô„v]>¬)ŒEnÉÜOux}ÕöË¥ÐÄ÷Ö9š=k!SÕqR7^v·(‡~{"©Ve܈Y†ÈÇäO8HÆ*†¹è͹ðk€‹ƒââ± Aj.Ák𣜸(3ˆ C”¯oƒÕÑÁê|Ck¦é4¦°ÖÒÑ» $¨Ð (D‘ƒöûjƒº‘‡ò„Ü`ÑfèñÆÝމfÈça…"`¼è"TÂ%|2Þ‘i*E7uôÚ§ŽsQ_Ò®7lB™Wº›zCiþüèø½oèm¦n q²õkƒ5¯´…S=ÞŒ+ úz˜ +Ù^ –GDÐÛ Ni¾¯R=«Èôö•œ÷¹oQºf(н*u‚àÍÃnÉ„“ºxè¾ï²45Zûœ ÀUuD.M=uĺÒÔ{³=ÿãIMÖ”8p'c—nô"Qh ›Åm›r'ÀEF^¯üÒ)É…­«c¼…Åjœ? × ÷læÇÜd¶À JýmESá6l êµÈÞvR¨Ñ3¯£J$IÚÅ26Aecäl àGØBêÔv˯:…¬Ã%áẜðÂÝî; FÇé_¸q’÷…Ó{tîóò^oÂòÖ?Iåe¸ÕÞÍ Ûv9ÎD6‰ý.¥/¹ ¶5 ÷.C.ȪNáÓЖé[¸ô³ìF•†(HÂÆ"œTD{Ò¤$ ´­xô"GÍáwnF‡‹>AµžGM‰¯‚Œ¬=rZ‚[éKÄuèDeQwr5w”z¡NW ‹e‹Ôè»›%ó󻘠\Ô¹STr¡“Ý0±ÿ$6Bdún^Aº‚ÆäTªÍßÝÄêÍCRƒ©Êó@–K[µ`¹\êØ©­ þÍY3ò³j Hº[_ ÃÂ÷By$Ñ¢wÌÔç(/îQ(åÙ¥ÿOáÊö~DbæËtO!„Ž™ià³"óÄÌ—0'ꈦ¦ {Їû¸¤AX¯ŠH¤G®e›AÊ©†Q‚,"‰Ènr0;¦½Ç£Ýú#ŽW¦ÏÊt ØÇÖ÷ÚÞ]¥àwÙ½Ÿ!¼0s?pQûÝÃÄ%Þ2Ô³x–ŽnÏFÜ{£;éÖY‚°IM–Šƒ7Gh‡2’‡¹%oçü®õΫ ÿP=Üeò<ïH7+h hˆ_þi®º/€“5Ó¤$H¢<Û3ƒ€{`?v]yàCî?4a°,¦ñêJ*; åH´=ß2QM±G§ Eš¹¾ßYüa…MXøàöH!átÄÔdâØîib|»bËÊ å ½‹8Ãû_ác óšnÜdÉÇ– ±ÐÜ!c|¿?–#SéƒV³ïóøDî„m• ¡z?àÙR’’0Ø~%m-ÐA™ÈÖ!æÕ?9>úòèÇ•Œ.[¥nå¬ÀÚzÃ=–f¾8úèÑуG_¬^½¼yzôàñŠ=xˆÿ|ô·á?þ¸úÍÑ'V_Ž?õ7»¿‘>õ‡ØË FóXúà_7©Þ ×nÎy(&{Û„ƒ Ó,énƒÑmñ&YZNöÉv;$$S©VŽó¯’ã6KÀ¦tç!ø3:¬m fv&gu_=ØÂ™Í‘d7vC׳8[æ¯o– ÇàÒ‡¡iŽó¡AäÍÇÀ€èWyµ/ WxÂì l£Úž:yO;­&Ý·É3 µ`âóE|ÐÆbØ&¸²ªrþš¹ˆ»;ä¶d)Ôœ*†ŸìkŠÅ¸€}Ð/oQ à—ÄJYX;h± ð3œé«ÒÚ1‰ÎkèõöIPæMK"Ùŵ¤4|Í ç“õªEÁ3Ôí¿qÕâLê#“ÓêÔaÚ½I"â<ÞºS¬uQ.{iŰiO Û®Ó˜s˜¢yU‡UG¢Ž¤zg7ÜnJŒv‘¸Ë¿Œ8¿ÅAB‡m×üäå¼|»ÝÞ"gbé¥å 8_ý¿ö±žendstream endobj 493 0 obj 5074 endobj 497 0 obj <> stream xœí\ëÅÏç Ä~ó®åO¿»# °N€ð8B"ˆ"sgldß1>ƒÿûTU¿ªgzv÷V)A±×3ÓÝÕÕ¿z×ÌÏ«q«ÿKŸœÝÿJ(µzúËѸúþÿôèç#A¬Ò_'g«é1—†0±:þñ(N VN®¬×ƒ«ã³£ïÖjcÖ~cþyügâÇfˆ³ƒô0êøžüh³Uƒs!ˆõ'1„àuX°‘ë/6[1hmœ\×gÆ«JûõWpUÁ´k‹ ›­s~¬?ÜèA)i=Móõfk`€~ýÇzøŸ¢UÌi-'àOüå¬K1:¾xšKÃçú+< å UÈÔëÏ7…nœðaÝ Ð=ÂCFx + ­Ê$Z¼À4ƒ6(9ˆQHZjRÙßlä0ŽFŠ´ š¬ÏM¤K'Ò™(½Ànc$žÉ6ÊêDñlÌfT˜=ÀÙ(å…XëéEgרë¿l¶r0Bû°~‚·ƒtzý~eXÿº‘a0^¨õÌ£ÇQ¿~…c¤r®Oa3pŽNYä“F`mšHÀðÇp¶Þˆ1Àƒr°ÎÈõO™ˆsº¢Oa/`¬Ï“à,lÁË<ø5Þ:Øî«O>ÁÛÀa€ ìà FŠÏt¶VR«õÈ$À—,«`!eìP¼¡úÃàTù É–pZÁÏ$â[iÆ8+YN©z÷¼®OG3®Ÿ#¤á^žX*I˜`"¥sDÛþiêœÊø~]ekáÐ׸Ðs¸“²Þ`$=ÒMYÙ¼UIµ·%‚XM6Ð ÿeàö L{809g.X±<ç6"í¼•8%hç³ýáñKG›¡]—ˆû £YØ'ÎkA,´Y¿,4` Ìz „=š¥í|Ö8ÁhRNgsËØF>ƒñk®&)ÃÓeBT®ç3ĆáÓH¥QtpLÄ¢’Ië“ $. º'f¼5BNF…v¥¯Œ9¸· ¦œ GäÅÆp«ÃN«°6´rƒ=y•j”`•™Æu5Ûã¨H¥'#x+“KtÊ£s|KžÉÚ—y8pÎ[(ËlUëã/f‹¼ÝÐEÕ`øB§‰éà×ÍX^ò$?8t›*ò#?3$¨*œCUÉ…«ÀîgÚ•ª(=WE{oL!Ð&>’ø¬êŒ˜=™æDO¹.Te©^cpŠÛù•²È¯ÅÛbxÒÊÁTå!LÓ‰J Š.©P¤)œkô;åZQvâ¿(\r_„û'>º 2y=yë­ºïDc€Á¯÷ü%1Éc†Âf+¡x˜½…8Û«€É ÉIù Ö&)F*Œˆ2,ÞAÒˆ-Ã8 ±þþ#>Ú|¼Kמáˆ/:ø0#9!Q½‡iˆG`û}XUi½8†€ !(Ô§åâ³z±’ò²\$W~c‚¦å3ÀÛénmõÆ‹DÀÔÀÝrûe;w·¾—§îðSŽ4I|à¼ÒÊz·Ü^ï?)ßö6ø¤^ü­\ü‰ï€-”.e:P w’Îêý ¾Ñ9KÄÏIÊ„ŒâBØæÙøS+@v•ô (FQªËÙx„á?ÃÇ,9µUN’]Bi ,Î%ßuŽ à¹+G…Y3u¬Ñ è¢ûQæk´SìÎ{=ÕqšVÔó úªfÔ/Ébz×ඤfvºcØUnšRn)À´˜Ýú³R"hOšÑ"&5ú)œ ¯¥Õç'%Ât0XGü4& ˜UÞ¯“àOki©1Øëü© ŠŠ–,gVë—ÿ(µƒ~4ïN-¤ÜjA•mö«üb>h:m»–Yõ“MfðÂÇÙÆ@IL€Í“ójÐJÍË”ÄåZ&¥;™!û„t ¬idÂxÄd"A©UÖÃ; 0ƒ´‚2lÌ7ž*PqýÑí¹ì^q~7/3Ÿ·™¶f`Ò@ùÂE@n'ç,œ’ö«ªƒÁ¦Àœg‹€DÝMT¶$Š„åÓ±ü0›ï3 ÔZ°9¬°ÏçÃÿx‚sš‘*ójVÎw&°öBqã.œ L‚pDrªGU©6DüÄ™[Öž¹3!À¤¾&–| d8çÇ&·Öñ‡¹s‡.šÆ%ÇYˆÚfŽñÅÆìI‘ðŠ-ó;sù.ÄÂBײñÜ¢„0ó·â¯ŠVž*.&×5õF•*LHØ\[áetv“7Ìgžmdg´ç’õ©´%7é°ÆÃ-äE<»”Î?ï0Ë ˆÆÊ$áÈÒ?wáŸwð€ ðFpÇ´zxÑF¡’ËŽÞw¾O=™ù{ibe˜?0”_å¹zi¢R#;Z‘@_3¥…ÍƂӼá`1•Ÿ~&3­L±Êp[Rž®—ó’Î*¥Nû‰Îbèg" gCÂ5gU—ÓŠRÄ1¼#Ç[Øåc‰ù{=íK¨ìzÓñ°çÁd Q’ŸD@‰ì«®EÓ<ËÀbªe"W¶À˜ÎkºŒ’6Ç êVC°Ì‚¥^ ˜sÞ2L=eVDŸå¨QÒlJ¸&|Ì‹µ¾.nŘãd‘c*ó6‰UÞæ¹Ò†yûtöM29Ö9(dÊ 2…ê ³TÎ¶Ž·ôn^02¹4U‚(Š —3ꑜ±³Ô@|ÈÚ] Фô’® Ó\÷±e™óÛ“4GÓæÃ“ÐYŠºÉ™z†ºr -’òä*íË–) Œ”ìgË–*l*§r¤lP¯ãg’zxÎŽ†š¯„IÙW¼=¯ëæ4¦AôBwâe¡V”ŠìV·×®••ËÆY¡­¥ÞAñÃß6›?ÁP}Pü(æÒV׿úúxî¾<úy¥Àe¦¶_ Ð¯ÀU&Ç@ð+­ÇfâÝôÙêõ«Ë'G÷¿]‰£ûŸà~ñüõèÁêwG­¾¼j‹1,럱Ÿ‰‘Tuþ™?c#%Â4âdÏ<ˆ¸Wª›‰áy›TS{Iꯟ¬‚ÏšéæÍUM³Ï¡ñÀЩT”ÌÃÙg¼`ñS f·)h9”^OY®¾‹½ž‹x›7£µu§^Z=²C{Í$ÈüN»bb‚÷&©ÈÜás˜]5µWé³&ý“î`•,9©Ö-8©»ZC5 &õP3ÅÆºÀëê6ëô8r³ŽvÍÑ·.izr_ÌÙHžÅÎTäøLZKYÛRd¤q·å©ERÍU7ö< † øÎÉ,:¹J­LѵG:ž{hZéRKŸé;s³*Æó¨_üH £Ikõž†;Ö›yC3iØH¬;,„Ña$×jÚo݆õ%m£š£0yØø¸É½RÉÛ‹é X%Cßóšô`µî–É€n†h1Ÿ„³p°VdØêàv†#Å­´|cW†²ä7÷"ü–$S¡šÍ‹W%š?çZf¦d@EÔDõ÷œ¢¥’9ÊÿÈus§ññçx Xó%É*KÉ™êêÿ”¨wßÚ‹™;àbø+|e…Êj³ð7v=àÑý_“+ê½v㬚кl:ŠaN4œ¦ÉU¶¯æ„Óš×Ïʦµoåõ=F+µ("VUû/ì,¥¬Yél«ÑY—ö’.£ŠhvS\a°:ËDWæS¬ —Yr¾ß\UÐöߨÙ-“÷£”%78ͱ‘^蹩šŸt´–ð&Æ™uµ:|¹ƒ(·ŒbBRaxÇÔbîRÝ×.zgç«p{uL› ˆN卵ˆÓ°ái+Õ³¤jm•EvÖ¥y¯$FŽñEV1ÏÐrÓ1†É©à‹ßj:2 ÒOßdS¿€ö¹§ß¹~7qê or6ô2RƒËFIgþ2Õ=ïŸc`©Ö&sZö£U(s¦õN0¿hGLë´d©Ø¬†Püã2ˆ½±QG¹oWÚAŒ¶×­}cÏtoêcÞã«°Àø¦«ñ=¾ÔçJ=¾Ô»K½tãy¾Qš?cŸ§§~^9Æy»m¼¬{´ôŒþ'{w÷5¦ž–ûMê΋¬“÷e¹XÙu/ºÄ;ž”‹¬½ù1'¸ItÞ<|Þ#îl7©ƒùA¹w\‡þ£\ü¢^|˜8ä5oÝ}Ól"wᾨW/;­»¬Åù^RT½ëK äÏ & ‡|*7âêÿ3èì:'Wgç=)ˆLè´›BÝäE©”Â"•H®ŠÝl×K°ðÜy¬cùÉw º ö¹²{÷£hfÖÁî\7ƒ î.úhOù®ëÂ[Ìß¼˜‡ûÖvgίS)((Ç>!S¹ÝMCË{¢·:f©÷öÓ m¨6©÷¥sh}SNRêøY“Åf¤D}“¹œç+𯻥wB¤DMÚƒ‹©ø!‰5d¹œ0Ï š¿i‡âÓ%}ÿ¦i¯¹b[ÓÎ!R~_HàFê ØÀ/»+Ñï}‡¥­fß/RöÚ"Æû0uº#IO¬µæª"ƒÇÂìxNþZ“Þ˜ŠIö‘5S÷×›5O\¯ú“û{¯)X±‡7ô¥¸ób|úßõâ×¶Ø×"CkQ7~ÖÞ\ásyÔŽ½5Âå1búɬçh^H¼Åçâ‡inç5Ø®p2š¸œÆænüzŽôùû` ø“¯ÀØp›âw™C¢ÛÁß±5ј¶_±Ñaj>¦aRŒÞŒÒ£k‘…IO ûê«Êêªi>¨ÂÜ÷í}(}ñã°VQúœEÇ¡8Ð Ë­« åžIéfÿw©næ÷—óÓ÷Õxý> stream xœÝ\YoÇÎ3ã±@¼+ˆ£ékºÄGbårlÓp‚((R&‰¤J–þ}ªºú¨îéYî’R$FlîLŸuuU}Õór5b5â?ñ¿'¾J­Î^Œ«?ÀÿÏ^ˆÐdÿsr±úü›9|4øÑ‹ÕÑO4€XY¹šœ„\]üsm6f=lä`­Uk~Zç9ºõ×¹þjs(­•ëßÁÏ/7zpn2.½ÐÓú»Í¡ÒbpÖ®ÿRÊiâÿÜ(;X§Íú›ÒzŽƒó£'ùP© ÖåªÇÝù ÌúÖú#ü²ÖÔ=bçÅh×G8•µÞ Gi9h㡱’ƒ…äKùa#ïö¼ꯅJ»õ÷›CZáþuôÇÀlj ëFô>:+Xªßly¨¥œ^ªq°Â{jðh½QHV)Öoh`íÍú’þœ`OχžÀ޵R®_ãbŒ±SøSMz0Z¯¯ó@çe 'øÞCc¿~šº,¯_”yØì×H07¡×o7è<gŽa'y-o:3¸õ4ù ~ÚiÐJ¬O‚¥ÒáÅÅæPÓd'ªÉÀ¿þ ÿœ©€Ê‰ ?½ÿ ­ñ_éÙ£MØU ¥TY]»š-¶¼ËêÓ:ã£KœÉÃ^|èÿjs¨¥´—ë3øÉFa{£Þ£€ÎÈt%@Ÿ’0 ]-è3°0ŽeÅTzÍèÓÐÒ Þð²速Ù΢máP›uKzD}'½H£ŒHï·Ê5—ëOÊS&L®ËD,F-ìÕEby?ëÝK/pÌÀb›wdÀ8Oi\ïowëM¶_Z´gšmiDuC?¢ ’"”Ó¬¶º¨_B›×5ÜÇ¡5l[Á1a{¢·(™oº­‰T¨ÛÍŒ‘6rrKj™5¥(Ùþ¸íÚúÏLJgì‰$í¹"gdɽ߯.T„»Hg»„)‡¬è›Æ¸6guhj|ðs“"9åS"ÊMV˜üÇ,À £Ðй8Ç.ìEŽÐ²ø¬„+tö‡“ºÖ%jÿ£˜þJd± ZöÉï¤L|E?,®^<ãÈy5Hèóz‚Üšª×ÑÊÃñ›Úžé" ô¨¸ôqû -Qk§íb•ø |c¦ö²UîÔ ¦OvÓÕ'yY‹¾Q\rÏÕ9­›¸óÚ–G+ ô Gô’Öp¤#çÞBYóûQ¶YËËÞyqŠƒêÀ˜Ûé˜Y¸àD[~·Xt¢;NJÚR9Oq¡hYì­ ö:kùVØ@/ Oâ1 ^ëÿ³µ4 Â‚ìæÒáŽP]Z×øž3Ñgô*;>E%ú>_Ú£ÝníáÇ0úÊ÷a›AªK82Œ^”gžà²}QŠo…ƒ¿•7ÙÂÿTxóCégÿ%É|¶é'YÉýHÊþ¶ãº—·E4Ÿóy æ® Юj²]K“u†›™ä¢hŠž7ó²ó&Ì6ºÛJÈÅ^&zpFGNŤ%6„©á(†É¼ûWØœ%òÞG‘£X—&˜äè™F±q»Ç¹‡ÐZ)R“H°úlØU"’9×&gw‰€YˆÇQúÊNQ#—5²̰t¶xÙY¾H 5PíAƒP “YJ£p¿¥Š)4Bàß§5¦é&øéʺ¢ß sÎ]üD†â·â”=O¬ €XÀئ_Š´‘î£Á‘(¡d›’’´Ú[{28¶ rþXæõ§Y*“ ä­E9&nÂ^j;ÿ3®(ˆ•L%¢¾§´±T­ß-M°R o—‘ŸÎM_#ŒþOg®;N ò‹ödù\(YqJð*¡x‚÷ ’S î°‡at`ÝžÂÐ!*ÇÝr°1ÝBoÐ+ tA“!ÖÿÆŸò„mÓÛðìY~ö¾nü:·Cw7¸ÓÁ°c˜éBVC{$×`~9†¹©ÿO¥ÙY~ø¬<,Ëzž†þÆD5 ˆVÉÀ=ZãÔõΨ÷ëúEZ"ˆ$œuf}/¿~Q÷ ºŽô8½¹ª6X¦I‘Ô£ƒšu:/ïù@”0ü½ žä‡ï{s—‡ùaé¬Hî°uzxY¯3ŠÄ½±ÙH—=^]—‡çõœäÀlÓyœ“ñš5À?14=&Û†N‰fÙêÔòͬ?vz´)] Nˆô<ééJµ·ô:)­÷|ø¾]p:Íuå]ÑŠz~F\¶þÔö~£54fwO)ª@¶cŽdäm~ó<ïñMÖšûÑ>º©Ñ¾Ñ3Ö¾í ÁóJý ÓÃçÖ^6ÄEë$ne™¯òËž`1]ØÝôv%ç¸÷°6}ñá²å{ð0¢òôHNBð¬·ÄU½Q]ô| ¬rÅÁíèŽÙù5q:w6@ ߬Ïco£æ:ƒ,ð›Ê²"¦© @’Uz¨8à5\{ŽÉŸå¡vZÅAé5}ëÁúº‘1z”˜äš–¡bMÁÛ.H´Õƒçhå¶TÑl£1Þ[Þ(¥w‚Á‚œbÊlsuö'ÆŒ-²GWäºÂá4øÁfÊ)(L¢A“vk£¨vÓìÒò\FJ@ôgœOU1À€S±±g&1U¶Ðá'²ÆþÝ‚”dƒBŒA?øËâš×#>—ô€G¨ãø² lM64ååüòn&Ѝa eQwŽ¢XZ”‡5Úi$O_óªU—¦!ñ¸¤afadÛ 6Û$¥AHžG†³¸ÍJy¥rbŸ–’Þàrã$¡˜ Æ0À£ÞzÁ3ÐÁ{P ^EqE²€çÅBº•z“€ÓŽj ¯bÚ$¿gyYµ°JŸ%T 4¥ß{·tP^xñ&Û]Ë:UHaD ˆ{7õE$Á-^1êçñ/dµÓÔ/I³¶nÞ”C±°J²ýw²Á£HI§-¯9®a=–ÃN€nJbÚ_y\òÄKžvÒ“©gÔýLNÎFZ Å)/Æ-E@^°Ú°„—½ˆ$`5!A¨PŠJâiÏuÊso7AzÌ!J^üVÞç’Dž‰A7ÓU²Êp÷à®Èni}H ×ð‚#ÅîÊa“tŠÅºøE€=ò<â~3.vªöC—–*ˆÐiu$Vs<»:.œbB÷×EY >Ð<3vZ™“†$ Ùt÷ŧ¯Ñf6RI‚#Á¼Áßè’S{˜ ÀòSa·Ç¥Îáã¡æ™WVÞ“gMò qd¦„=EÍx€hƒ¾k€ÑŲfµjÆÏô=ác4G*¸±Ë‡F,‹[†ð*óW­(W:Øß˜Q©ä‡KÜ+ë‚»;•:š ŠÚ= õpHD…+êéÏuÒVêíø‰Ùìv®|­ †zÇOÏrl°:)lúŒiLJ½k^fÁ‡ÕÄ1Åɨ\]\ÁëãR/¦Kh“'ʦßT*7//M*ÓèËbĪ©RtfºQX[¸8+D ¸j-ÚW©è¡:y!®Š$fzÑÁN!ìþñ2âf¦W1G‘tÇjÔê5ϰÚÈT»BÄå*ÀTvÐ8ûÝz:ÌY”Òº ‘JçÀÆg?j¡ˆ- bfâ[u;ÕÒ×s]w>;ÈÎeS!ºSŸtf.ëbÊÀ ÷/& ‘Å“ ½ä@qÄT_’è-õ¥QîÂm ±[‡± $_IQgxÒ9pV Õ¬/ãq7åÊâX1ÞE_ñgzÍN…Ø)Æ D‹€!ê¬<«€åØ9³|s 6ýsewvšy5tm‚Ät´s©êVÒÍ0ô\Þ¾Õ¯Æ攵q½Šá›¢Â¯ îîlÁgú‰w‡¶…÷Ó‡îò‹œç§¢UzFÜM£Ú ™cpN5芭oÌíbß„F$‘¡*ï{ þÂŒ^éõo`P5ÆR™;a-]œìôƒµt`f²(‰Ÿ \Î5ä¤4=J&ûA!÷î5=ƶÒyÜøÿW:?FÆmðï$MÂY£¤l¡Œ±-rÛ€ß;Š©q o€x‹¼à¤Ž²›d^• Ú¬ ¥?w>s™”ùØÀ§ó K›û i˜ù9‰îÁ;2”\†Ë!w*‰!×Ì|„æÒES_ˆR‰Í»!íÁÎê5Û»Vñú_l2£ C4Åo ó‰™a,(pC'ôtkå–®9ô£j 8›3ÒY;\#Ýž)å]ìd§UÎp½8ôS?Eæ hV%YX~$d¢ä?°A¼ý3ò›² ½3Õöª›_.’ƒœ uÙˆ’Ù8i~‹ó¸*ˆ/•”͵ÑE¿YÒ”»]I)ÅÉV ÉiO¼ªŠ€ë+{³K×y”®åñ†þƒi\¾ü;Üéþê Áâ¶öȳó¶(eè™ÄÏÓ8)þÙFÁ]¤=Æ–¾SˆkM®‡U¶NšôâÍã&"M1ã WÚ ÏË4uºí•+"M{F†\‚1 ¹”Ù’K¨3äu‰JIÙ)Ky=–J¹·19­ Dù-ÒÜ:1êp’CÇPUÐaå|UˆŽG¤½´)7DWŸe?Y͸vÂs³bæ,âe¨úš!3éfc¾BÚ¹æRþrŽV§«ì[Ðê-PÅå[Û.›3í ´ ØU—/ tAºÎÕÔ"tì0Cû=àá¡€ÓÔ3Ï–LŽ“œå‰é<˜OÉlËÍ1ˆèIGæEêܯΓ¸õ˜C!ÂÔÇFÁåã:³ ÊÙð}Åc \6å™ó¹G…Ãu±§ú²mä;—„v­7h’^=<³‹ÀS¦Ê·e;©fÁ/Žm½i‹š?ú‘dØQYÒâpdßœJ”EË‚UJ´þX¬›?´\5¤+MŽÊGõ¨Ãi8O†Ó&¦\å\âí8Ý|6ô2•õt=Òôjjh·;dÍó_!öñpÚ®$JnW’˜cä5T2Ò|Q£ò¹–¿¨±?z‰i]­x‚ŸÎ¸äÞ§´¾j@OËE;lAM¸’•kÉü§oÆà1¨n¯¹)GîÛï†P‚’Ró¹¬Їõ[ö¡&kÌÆöî– F”o9í2]¼¥ž2±¥»ÿ`õ‹>Ü|Nå4¹okïNáwÆ6m¾ò L6ûê¯!eÓÁzG'NŒªå]T ²§ËÅjT¡ä—,xRØ E À&5ו?~ËÊI” T®ûÑ Â’âG7T4yL‚.’w§©½ï¼þEAØŒ9ÿ‹ê7äú³xÓÐ1Xt¤9ÇÊËFÛ#°Ðf»Yå:‘Y5óÂóSŸ4o§ìyZ†—V)mq©àŠø†ùÀ!ÁuVŸDã™›âÓônßvkÒNkûƒBùûbA)ÎK/Ó!ÂÛà÷{Š1í¥÷‘ˆýñzôñ*Ô¢º€Œ¶!Cù¶ÇÉâ×üo_|{ðr¥Ô0…/ ÂrÜJ!a›€`«ÖO.>xðàá_VׯÞ<9xðãJ<øÿõùß¾€ÿ<ürõ‹ƒ¯®¾]þŠa“!Œ_1D'[ã4Xy>dXô¾|ÕoyŽÓcS¸ÍÃʾ"ø÷¼f@_¸‚²7BìÉëꊺÍèfÐÌ’€¨Î³È%• b²þ.õxR‡³ŽªP²&»=-†;pÍ-Sæ¸5U—÷ìkÞéÊnyúÌè2%ä©ñ»<@u¡—®èú= $–Ä·™c"3Éü/®é°›¨]ªŒù¼×²p㺂XÒU³›P­Õ7þæHèýÍnK²}VBÁöÉ.Ò±&`i~O—V5C‘ò¹Ù•æ,–$‘e+éf ´iº‰bRq¸XŽ‹LsÕÂØ ‘ ÖÿÛƒÿ_Ç{Gendstream endobj 503 0 obj 4941 endobj 507 0 obj <> stream xœí\ëo7vïgÁÄúaç Òxø&[´Å&ë6ÞÍ>’( ŠdQ(’, ¶%Ŷœxÿú=çðu8ÃÑ•- ŠéŠÃ!ÉßyÞŸ6Ó(6þK¿O^í=þZ(µ9³7mþ þ?ßûiOP—MúuòjóÙuóÐ4†)ˆÍѳ½8€Ø8¹±^BnŽ^í}?è­¦­ùëÑïñ?5¯8;JoBÏÏ·‡jt.1|±c^‡á·[9üe{(F­“ÃQíó$¶*퇯¡UÁ°ƒÉÆí¡s~” Ÿmõ¨”´ž†ùf{hà'üðßõðŸ¢YŒi-'à?·øÉY—º19>yKÃÇú3tr”*äה߶…nðI] Ð=A'#¼„…À.H«2‰/…Æ`˜Q›/(9ŠIHšj”RÙßnå8MFŠ4 ½4›ŸMšH—N¤31‚ŸÉa:”CØP'Bˆgc·*õžºƒd>´ ÉMv8ƒÍ×ZÀ‚ÞÂfzoÀ›ºm¯·‡x8:Èár{(ýí–u}^»žás1m†ëÚú|+´¹á=NŠ[áÜð×iŒwz¸€míÔr8‰”H9>^âh¸wŠ“s?Z <¾è#æ ¾³Án§œ•é¹SŠ/¦¼}Yáv0†žÁGš'𗮀®WðĹÑZ‘LÜ”gwR*=ü—ª\`dv)š“k¶ ç›W[åpNˆx]LŠó?öØfÖyÊM0AÈÔ!öËß[HaKÄûp=N€;«9#—yê‹8šåä»+ú¹ âÊNp“@1(|Úî²FO²è{qDžc)Oº* ™´-¯#÷J.döa¤U‚„ 2_6 ëñÁi%FµÉÎBÓJ@ìO´b”äÌu\Wì„-رõOz.“øJg û ôTÉò  ·åõÈi_ˆ=Lðq{Ö@­¤^)S–,‹"ñ¾5]ÁØþ­ÜT09ÊMÜâg¨%éã]TÜTJ’þ'åÍ«–…ØGŽCF9  Ȱ#XÃ#N\îYØn&ÒáÜ ¿Å×Q:r¹wÓáZ”–ðÕÀGêÆ¸¹­š@‹ÇÁß>#6Q2™Kê47ŬáP½¬­œpFm]>T+9qW‰¸à9;°Aë ¨•œÈ4Y2ND†È›Z"ìQ÷²óø´1ÜÓF´Zc&Ë_ãª`v­Ö¡ª,YVs¨"¿pË*AÕ˜‹™gLMEعÆTÄUHµAŠaùß@Y¸Ã—øƒÌÚi‚ `´bYµÃÿàÛ‚q‰®Á JG‰K†ò8nT@ÔP·ᣊªÿûòüE}éUi|\ߔƿ¦‘&Ghˆ¯kÏKãEm|[kãK Öîþº>?+gµñ47Ò™ à3? ØCŒ÷ð÷æÀ¼FZ+:>AbØŒÿ‹"0hB$D€Š^ä±óûòà¦L’ÕÎLdü¬¼ø¬.á¼4ÞÔÆËÒø¶4’”-¬pÎvIñí7탗‰üxøfØ/¯Û÷hêÙž”'Ï+‘Ǽ{ÆÓ~DÍŽ-×x܃[}ç ŽþïðQNw!D ¾ûîvAÉÖ}Q/›žFû|§ÙsFS§õ¦á$ü¨Á„üaÛõÒõDQE‡ßˆw7ßóój 2k¥\ëÿUAXë<ï>Ž&¹&@5!Õ¶­|B& ë B€]JÞñÅÞàpl®da,2ûÖŒ_È#ƺ¡—ß5 Ñ4F`t 0hÌñÖßÁÁ¯ân!®ŽãÆ ¤™Uз® î'ØVÌýÀÓ$ÝD”pÑyša2Ü€­j˜¤]?’ÞG8ÊlÕi‰öp2]Ñð~Þ5«‰»°g‹®fJŸ-CS ¾àXy¨æyÏœ¨KJÊÌ)fF0s¢Ò„vÒÌG|Çô÷EÇÜ«pD1 Á¸¨„NB1?¿Ýý±ÐEëÐŧ)XS¬Rp=œR%?õd€fS[Æ ÈuË¢lWÓÇjA.ZÎñùñvf¸ ¤*¦ÀAi9ŸŠqR?i¢>“ eÛ‡áVã—Ò¹œI‡öAöáï‚÷ï°hÐg¦áÔö˜‹PåÚ"2‘Þ»Lv±ž1 5š‹ð(Ƥ¿‰[¾È™$‰³%‰#ǨÄ\ÅððaZo«ú¯¶«¢—ÉR¥Í¨TÜT©ûc7êÈ¢NØ©ÎÑÛè†S;狯2ï7F ”¶„`#áÃ!ÌRDÉ,i`Ÿ¯B®JF…Ë¡2™Ÿ;z<öRû2´U2:˜™|nÐMë¹W1 %mwãæåÑZÏ·ãۙČN£¢=»®à:Æ´² וÇÕ¯Zúˆ*48¥iÑ,ªLG0÷Ž ŸÔî×u²ÞóÈqkZ>HX1f+(ù+V©=C±bÝžýÒYÇžl°5]}€?ç]2Ê×m”±YBáhp8RÕë„Ì*ð=ùD¼½Ý0YL¤E-æ•ïã~-d:Áf|µ¯5pÇ$b…oM%Sþ"–p =c ’jRìZ“ò]¸&úYã<înæÓš?@.ußüÉágXT³jûÖÀK¡sÚ²Ö,ú`K¤ íóB áóÖb ‚2¬]}¹ÂØñkì7;4Њ]¤õ0Óˆq€FßkˆÆÀÕ÷ŸŠÿ-hç/оHLQÙ‡ÓJ¹3ž»A‰¡y µk1[.OZ.µv NL¬g¾²dÑ«& ‚kw2¨ƒn-¿•õz/—^çqZñX&€¢1o-²CJ8å©‘díTl3Cð´5F@ÖVópæ°,ÒZ·mZR[OÉó¬Â9šO®3ø5÷ šDdB&nñ“£½¯ö~Ú(5Z*æœø “C·Lc&Az,úìéÞã§ܼ}}s¶÷ø»Ø{üþøì/ŸÃ¯§¿ÛüÓÞ“§›¯>´p}!˜ˆÌ_ªÚÍ#éÓ*ùJœùéÉWKZò»):ÖØaG-Hàí*X«ñ¨ÓðdÌ¡Ä`)…ÕA¶Ÿâ¨†LŸ¯˜FuËS`n!ÄsˆÔLÅäø_WØ®ÅaO1ÿÍ•ûo³%þe{h0¬ ûh6°‚LM- JúOÈV#~4Â)¢ˆñóéB-!nd1ÙšÛ ,Æšc!Ó"»¬Ê@Ù\Îê=¾=´Ö!_DسtꙃÝ{ÛcØ j1–>7ÒbVZ®ÙF)oª’YJUÍÄ\ÞÕ"# wBó“ØâÀa!…™ï;g1­gÍèd4èÔ® í1Û‡ç;ýkÒºjÉ ¶Btã*/g ©„ «?!/çÇ aR+2Ã]cÒ3¤nÁ…Æ:ÎO¿( ‚[ÔCp8xÂè>p‹B{C®è®¿XÇ3ùB âH¬w,2· 1Yf¬ûVJ”@îDå*…ÌÉøVZÍ`7x^/ûE©‡qgXù6†ª—œÄíe1q 6,}ÑñqÆ@¥OMeàR„ÎêP¸ïXó1§%ÆRÎÒ1’I@h3‹ ÁÞQ'éÔ±°ã‡aÎÚmÈoÕh•±6TçÔäQA“#M"òÇŽ;ö IY™4'Š}Ø0p4fŽa7Æ)¬:~LÑd‚ÅC -–BõÂ%Üš¦€~+ù óA_`ÊàjñÎ"éö5—z§’ãÎ ™l/8À¥ãrᤠC\’WìÕD…tÎj&ÊM6o<ã®ÚÍL›èÉ9T‹¨îÅÀ…̓ÜX‹´epN!~%ɦ ×\~&íõpuCI&ÞW,€‹ßÁèÎß­¹´Â„™ó2+K¥ ^±3t0"³'öSõú~ÀÙÿÀA1¦cÖ’Nnžt<-Wck)ç?W‘Q Õ‘$άûd~;½ë,³#ÛªNÃ8»lÖ‡ãÐJûÑÚ¦÷q³²«6ód»¶è¬$‰à˜-©jÕ±žÅpOæ5»§ÝÝqŸgögŽ"¨È t€ »ŒÞ²²ÄÖ‚f)• à?ø[ 廯ÔÁ‹ªüÖ„‡ '=FyÚûAqý Ëââ¥7º&s—Øé 1À…wÛäG{–ߌÖ;N¯K#»ŒX§lný îºíºóUo]Õç'½Æz™íUï.\ï’Û—ƒ˜Þ Íèw¿ï¶ß›ò—Å/kãE³› ⤀q—]bÓç¿Ôën'|Xrƒò1G7¯ú¥{“'”Ç €Í¡î—Çu¡õÞæYÁñA}ïî÷úØó¥‘­è=ß±fŸ"‹|ì ÂåÕÈÚxÓƒ ™Jõ.lážûÞ…¥Í¿*ï½k÷ômÛyEr,—@)YKgÁ„ÈârìIo÷Þõ ÙHžå=dyû6ß"yŠBú‡äùÿ*yþ!n~=âæYÙ¿³òƒ¼jwüUKÔù}†¬»UžÔÆ×=ž­ŠZIÅ@‹‘Ê ¸F²Åë³ÄH„µçü?8D,{j/Ÿ+½b `8·—ϱ¸°ÙN£ Ái¬VÆûÚ†ÒóFGòW©F†?àLFhî <Ò¡?´².•O©êiÔÓ$§%s@\9?:ð6¾Û‚Ÿ<©˜:Ãç–ò#8¥¥+&`8 ¨®'7^‚ m‘”§u°ß0ùרqRŠ‚üeΛÜs1޳i% [ì¬Á›ÅÝëûà7Å/Œ‹æ¸Ûµýï¶Lþ¦D­ól)í(â`Ó¶û=f20޲6ù&¯V”§_u¢ÊìMÄ~ý¢‹Æö–6ÏÅG/­q¤Û.Ç‘·ÐëŸbÉpqÐsÄ$ ½ºIáwoìç­\M$кW¾#ýWüÖs@k×{b¡ŒSŽýÑbs0XÚ¤faTGuùÌ?dQPŒ4íþª8ÚTÛxóµ+»±¨|Åç¬û£¯”..òÛQj1óùðhm4‘º÷0e-¦ôî‡x(ÈÒZ»ë¾Y¾¬– *Ë¿£ã)’ÔMn¬ª;W¾:¬~ùwœÛÈ¥^¨ù·@æc5~ K¬®ÞÆ¢Äw[2ÑJß^ÚÈ÷×lS©Pö¬’›7Zk5‡ Ç ü‹ÀðÊœá£í2RVáÞ¢–ŽØÔ/:pXˆ¹zó¹vQqíW{-Ð=öendstream endobj 508 0 obj 5032 endobj 512 0 obj <> stream xœí[koEýníð·Ìr'Óïn$daß»‰BËjeâ€Q;6ÿ~«ª_Õ3=÷^ÛÀ.DÈs{úY}ªúTuÍwÇÓ(Ž'ü—þ>y~tÿ‘Pêø›—GÓñ'ðÿ7Gß ªrœþ¿Ðvx´Ù*-FïÜð'x¥”Öò†_@ÃÏ7ÊÎk3ü­Ö–ÓèÃä& =o•²0/ßwÇ70ê}˜ëçðË9Ó¶ø¶ðALn8Á¡œ A`?JËQ›••Å$$ŸÊg1†àuàXW­²PÚ7[Nøü‘öÄsaÃ|ÇɃ¼OÎ@Æ(V±1Xs«e½>Þªit"„XáÎv@ OaEZ )‡7¸$œˆõÇ ´’Ò˜á ºú~³Õ£R:Èá æê¨U¾Í›ø5–Y(µì–ˆ¤N¡‡‹\κª#c³¸> ò|ƒmõ(Uª"•þ'cÛ:ÈK1ÎJOÁ69ÕÞƒŽ¼Äf´ŒZç<¦ƒaC°©ýXwd>XðØf«l"ËÓj^Ô^à$PžuYߟÕGB…ƒ@'4Ä@¸ìMgh-à[,ö_¿aâúqƒ8ÁÂâ3@–»ŠCHè´Ñ·„À*73Z¸Ÿ`ኞdÒÒ³ ÄJ,<ãù¾ã6‹47'lZÔ$øÆfA^Ô1®àÓJ·*ØIÆÇjàØìýVO–£‡64ÛJßÂõõ\öW€•ñ‰uÛ­Ta"E`¥Q„0’t„Õ™¨«Ó‡Í¤Tfðëà¿âá‚éª$5 ´ ianx¾ë „³|˜F»`DI¦ò«g#mAà ÙÒÁÔ&>¥®ŽÕB¦€>«aN°ïÌ*Î…cê¦Ùi£Ý§x5Ñ~eÄÃk€…“¶Ñ¤œj’ Úfí͈N“–6þ|Ž"´ÖY]±ÉU$a+!F%]’¤•ð:[Å€ý$?ÄÝ F¿ãúRñ¯‚[W¾\‘” ¯ž´ŒVBWd–lôVº) )L“iƒ,$;¹•”Î/„5¢ÉFË¿kªí6'Ž´ñÄ9H5`Éž oNip#âB.;söý%.ÎRéÖŸ_y¸Ú¨þ¼Øðß@'^Œ“0-—L;°§ 3Йھ‡ÆƒTpmz\Íl,õRè¡QÐÏ€O`Ý@ÀØÞÃÅâ–5Mÿ ¥‰Ù@ŒõÍ$xGÅ 8ëˆVaX]ðnør(h~¿Ò£÷KѨÇ5¶Fɯ5:Ã/7å±ìLм€ªnbÂX¢‹ìc€™A{DW®‚Œµá—ÞÓs ©ÃNœ ÂJ+ÿ{\7ôÓR8ït Àdg63ëñG¶Iy-I­“ˆ-á?-;Ì´?Ûzšê.ÔP¿.µ BfÙ#s§ÄkíÂðøŸ,À†ÉØYz\ð^6ºÑnÆZ³É¶þ÷ØÎY0Si¢`µÈª=Ø„‰WDU±|Ó©´z3' ©_FüǬsºz}ƒ–AÄÍ ™N#×m—ö P&AxGs¸ëç\ü\AlïkÉÙ4ê?šMfë± fÞj=KY'„²vr®`L­vÚ¹„y‚™ðc[Àív§žÏìdBfÊxÁŒ¤ò£¹;bfDå Ñ¦‰†ÉÒ™‚äÿ´>Þ)ìà º¶9Ðù*S¹ ?ï´ÐsR¼“ßÃCèJÀx±š¢™-ûU<ýZ­±ú4 X_(LÛNßK Ô[I¼+@Á24 ¼1•¥Ñy»~DüYUb…É*!aÀ0oÛtCl8 Ðg J'A¶pR6׳Õ1ü3Á\TTíOœ-ÑG€„kœ÷´´á±qžÞ%“@2Q•Z¦O´Š‘Öùx î;wßÐ9š0"2QòJf•¢½+’^zŒˆF<Ud HàÂÌgh]¥×H%¢åGÏaˆe(]m°ec²”‚Î ÷£“à¼rˆR3"Siz›ÛÚz`ÆÅܳ0Ä “En Æ€œf’m8 à¢´+•ÐQ°»ûªŽUÛ°PŽ÷ŒíÎÈÍøýG0<üA·v:†¿ëJ·y8°,ê✠9”`|„þ?Qê´VÅß>+•© У= A÷a5•b%Z9ÈdÐcá³Zø&’…‚R M¶* ~Áv>çØÏËöÅEš)(8YwËëm;ZܽTqrÔ:¾¹¬3cò:+ïO›÷» ßôþ´<¡+ÈÖ‚FåÂóÚæ”OÖȉæy·'Á§½!/{“{¾{—Â“Úæ‹Rø÷ZøEçiÓïÖÒšÙã#š­‹ZúšOšT¬Q9î•6)p„uNTPTdI>U4>î5½ÆÃž-õyoÖÅýAí>Té¿<lÉUËÀ#e ß‚Ùð Àð癿â¾.P?+"jµ·€G1íu$Àû$˾澾žæ–íúMsÿß5·ñÿEͽÿHÑÁ3©rsËêÞÕ 3Ô•$ÆÏ7¨Mã9Ì<üÈ2·Ú…|;„ˆ°ÛÄUµ‹PFK;ãž×Šlܽ‹‡!]¼á¨ÎJËrÆØW\Þ–±x×ëǘk8(0¬m u¤xcV˜¹©Ø=wSŒnêÏŽûâŽØ*¨õån¢í¯Ì°l”fÔô2šõ[¶¼Þ9B&±Ÿû£ç†ãz ¼[6îKWè=ïã»ÜçR`| ÂìœøªƒƃÑ7zÆ Ì"º˜3`Ý<ºÆ|*\?8P#ansëÚÛ- ,V"QØÝ¾HT¬½’.5™‡Än–ÊŠñ0Önuu¬‚P’’·@¸vu¬ úV~!éžå¾Ú®[õ&pZ”ÀXvmÆ‹€µ h½Yc[Þ¡]µ~ÔY†¶MP‚í.Vª6 Ƈ'/½’¥Ä@b­z±|J7Z`{ ¾înïj$®Ä>ô°vÆ!.œÛaÇB§dqsMÁu+GN6!÷ûù ´2xšO +1QÐc5 Ak]Ú´k4Ð}×,ìÂÆmÒ9&LZr{òWpä˜Ç/§ÑNŰ#Wà\Aê2“%ÙÕ6•ÑÈ€Ž±Ra¡Ÿ¥dt.€y¸ ØY eª{_¶²IfÁ!z×׫í4÷tDÁ´Àid7ËGÇÙKœÕrǯÃs²ÇЫr”iö Ê3óÞÃd¢àÕ5C¯‹ ƒƒŸS”:z߇ä²Õl¬õTû„]Ë=i”æ¤çfú­ó÷zh–k®Î —v†¤qx.ÅžƒõׯWÞ-OøIî÷‹øoËwì¼Tþ6·U®J³77Û»o;úµlÏrØhWµð{Nië0O°‚´`ÒBñÔõ[gžùaõF"½ÿm»Z.²ãñãX9QôíV‘±®jS~Ån—£š»Hå%K½ã#´Iu?kºÖEDšý5.núŸ5ĉ2ªwäó×”S§…7CAM©§«ßo6qáIä©âkvl÷®þâL¬tõ†¥¹çˆ²AI^Ú9óñ@0Ûz£T?@W.é))íWëzQ¿ºutu:ã%ÆÌ©Ì,5¸Rѵ|`ëF{{KÂܤë˜öp‡]!Ä¥g´V¾Ý ‹ AÈK?ã³õ=#™ì±¯ìñ½ÙÝ7vʆz‘OöMo~¼³‰w.¢sg‘õ§¹KáÌ]0`ª ìc(> stream xœí[YoÇ~'ü#øæC;š¾»b N”ÄA'6#°€"%R—¤J"òçSÕgõLÏî’K "w{ú®ë«c^Ž;ñ'þ=Y<þž qxöæ`<ü#ü?;xuÀ|—Ãøçd}øÍ‘ïf¡ip£c‡GÏÂìÐðCmåÀøáÑúà§Nöªã½úåèÏ8ÄŽÕ£naÔÑ)ôü]¿ƒ1αîO=œ³Òu¿íy÷÷~Å)•áÝQéó$´ i»ï¡UÀ´‚ņ~eŒ8SÝ7½„àÚúi~èW f»oq¬…¯*`N­éþÐã'£MìêØhèâq.éë;èÀùÀ…KÄ`Ýßú¼oœðI9 ì{„NŠY+2†]p¯BŽXÎ$€i© |`#ã~©sÛþgχqTœÅUü ÉúdѸunX¤‰b”&«H”\¨aÎÚ¨^ÄÞ¢«Áé‘'þØ;ŽÇäÝë~…w/ï^ô¾MtoáR­Õ°Ñg°QíG:G¸ß›r©op¿JY#¡¯„FÆýœB›Ap›žÍ»khµx6KºžäOyõ/Êì¥ß)N‰£u÷ïz²ø˜ ÙÝ"8Æéî}Ï|6¦».#çÃ9Œ$P´–INò§Æ@\æ]^öÜ JŽé¶Œ0,_Qi<§Ç‰·iÛ2 ‚R! ©Ð”É$ypµB O›ªÍ(¿¡×Ez|Õ#s¬/+¼/«üŽú:•è9²î¿p«KËŒqÀÖL¤k2°_¼µ›Ì´ñ Ô˜¶‡s^ÑN—!UÜ‚‡ó2¾Œ:é…ÛçøÔB‰H,ØË1¬z) s= \¦xÙ.ž¤„A®@v ‚?û6F΄·D&•ãÆÙ˜ïArIŽ”r¤óÜâÎåÀÇð€0ÝÓ°7=jr…­HO2É€Sj¯s>"›Ûq™Åñ ZÕ­iIÜëiëÙˆ€’ÅyApè @§îtBdî aú¬ x·îA ælâdN¢¶Þâ‰ÜÀàf3Ï]žK½Ÿ÷+ŽÎ*z¥H‹5^©tf‡™šÀÆó¹dx!¦yu·K ÃÇ{†WΆss©U¶†®ó¨pñh”°x(éfztO´¶Fûýá|¢áQ…èUÐÍ\›l9 SÑ×0ZºfT‚ªWB©!Î  `¢6—j°Â{)²x›÷ꡘMì.Â<›Wª@-ƺÿàWzoâH$Yxú:wöm'øë*¾“`¶G ÛcX±P\/Œñ—Æ”íun|]ŸåÆ“Üè¹>#¨©ýs‡kÖ§ £ßÔ.‟†ðØWùñu=ÎâQì?ÉOÎË&i÷0¥ôSNw^÷L§¹‘,ôu¹­ùùeD¨÷=%y[7¥±Pûç>}l0!Qo8ÏQÒŽ,\ºÞ ¡­ˆ8•êÄ SMVY: _Gø¿‚¾žvR©J÷ë€Æ ¿ÐE×!èM2ÝÕ=쇃«ÐŒÚ¼ß½ ‘åÞFì ¢Óx6ƒôÀ ¡‰÷'¬j   Žd\"/9Wý\œCÌ2¤öD‚Em(˜)ˉq VçÅF§e%DVÁp÷\PÙieÿ’¥ éð(õŒØ ÌZΚád²Ë‚çÉ=‡ÓsVZ-=ž¸êAX@•ˆH ¡Y uœÜìÝ´¸?1¬FA"*¦·‚žw½’à£rjºaÍ›&Ç#>!æI…’jþL£ }G÷ –X²—¼?â^Ë v‹[T¿šn!¯‚~¸ 20r¸œ$³«š`›©¸Žl»´"wç½Ê-bâI„ ùEiÚQ êÍ4V>²¹?^mcø|%8ºa|G†ˆ ®Ä'xRX ©RTöU9(Òˆ€1ÊÄ(é38Ss¿‚rÀÄrÖ³›„á\è©êåÌS`Q˜lùN:‘(¨Z²5‘e>¢¬Èå}IÕ (g6êšMã6ñOPòÅ5f`ñ‘¸såiÄÔwà4šÜ ؽÖÁÓògËCÐsÙè‰ÊãJl/Š‹U^tÝ…ÄžVñÔ+ÏŒ:M#9¨Êp}×åúš!ŸšÁ“;P;ݸÐÌé†=#¾[”8ЋMhÚ›ÝüÎ]ý0ôæÞþÃMÆÕxROqr|š]«gwøØvnZ8»8%§ËnC6Ý¿N·áeË º-—-„¿®¼±Ú«`ò³r_È¢ÖÚÁ(?èÁrovaŠSlvsaþ ‚¨µÔA-Ü=Û0”*èA`³"Ý íÊhïÅI;0&·ªŽ(Í­ìr8bw+›¬ZR`´2;w"`Á2v»I˜:]igEoîcŠ ül+GDè#ÓWøÊ6ÄKNs??â¶¡¯òˆuÖŸµP…` ߨ1×}C´¯rãú³ ´ü 5fëZë%ç›{ÛÚÇ× ;(Ó‰Z$zålI›z¬J‰i–ÔÝôª…gÙD¯Ú‡OÎyG/+6 “I1ÙypkM’}—%Ù°•47p3¸]Asçå²Ð-›É>¨mk¬Öùè=óØžŒPÞxdª ºï©Aã£A‡xT¶vàCŽbÏ ×råɤ_~‡t2ƒr yŽìC¤Õ¼ë ƒsjâ$G ­uå>çy’(IT›wïøÔ$­÷?ɳÔQ'nà²%›¨br¢ó›Wõø„¤ì¯¨šð‘E*ŠÜ$?’MàDÒÊ ¡ÏÃDÜ™O"ò³çÏv‹Ÿ¯[*¡¨¡Ï7tU™åY:à“éìË–íx¿ß>>ËhëE7.i÷œEÿ=ˆh FËR®_ÐÓÉͺ˜»¨ßTîÒ,Ò«“ҤȈ(Œw8¬gÞPËé 5-×µá*Ê »ÃtÊûד8D]œD4'™íÅüêH-h]ò¥2bC)·ý¶÷òXâõ󚊉X¶í³»YË•=ή~«j!ŠS |Àãi«¹*ýÀ€‰5*YËIÐe¡ðY ‚áy¹j¬ß^®*F5/®x؋ؚ®Ñä5†{³ŽZð C¦È qM¢+U¨ÏSC…˜Rƒqµ[žªây5öªÉðÁ™Ù^“Mœg2Ae d0^2Dt@ß%οÛÛ1¼yº·4"*UäÓ$„µõ½GR*“öÕmžãrÝœDnð…®Bˆ-΃I¸«²QDË3&×núF@h“´Jµf®B…×¹+·œF>^âhnF¿Æ.ÌÆ¥ó{M=»:½j–ÑHÞݮۣG0 Ú΢ý“‹gðFº…Ghõ‚Rm¿6“™t© 4mÜ,%ed?·ÑmÝäŒS,âkŸÜC%›¤ Nó0‰1Ôã­Š¸ôÑÙM%¨¥ÑW™k³Pež^I*snÚ–D˜qZA^7=ÎÆ/]&°O¬E*> stream xœí\Y³\Å‘žç;Äü†~£›àÕ¾LÄL`ÆhÛ,"v€„$£I,þõ“™µeÕ©ÓÝ÷ a?ŒH­sêÔ’•Ë—KÕóXäNàÿóßw_ÜøLj½»ÿâBì~ÿÝ¿x~!©É.ÿuçñîý[Ø,à£%Š(w·¾»HÈW;Ì"ÕîÖ㋯öö`÷ËA-Þ{ÿqéC\”ûO—r1Æzµÿìp)–…n‡£Ýÿá 猳û÷Ø(xèX»ýŸ—ZÇEŸ_´¯ùï÷Q,BÍ?øü\”RŽÚjK(ƒF Ò ÖcßÚÂ7NîϼŒ&ì?„oŒZŒUøç¯áé—¹ÄLÜßÂî½Q–÷¸¾?Â,??\Zø§u±ÑØtþ?U€opˆ†46‹0g­)¤â_~1žõÃ³Ùæ™xþzë¿iÇßJ˜ñ"ìæ­»°ƒÆ×›Zj©yËKXÝâÂî¨ä‰é‹‡0‡ýüã% $#LMï¿Ã?ÌõþÎS)÷_ã?ïâ÷ðGõ×ËúëëÚøûúì—Ã¥v@bÝ€Q” R+ø¥ÁQÇõÓòð^}øK}ˆëSðWq)õbPi9ÙãxýüÓ×/úeêV§I»§¾~Ö÷þóÝܶçN}ó Mò6ožº4ÔåYË!ú§‡·ÛÃÇõaûæÝÖû&B>¬ïž´OÙV¾Ã ÀÞ¯Çk_µ‡mëÿr(?‘ú—•ü Äü·à¦õÅWå¦éÊØæ&Ã?37XΜ%î<ôæÔcf'Í¢S¤4ü¦Õ¯L‘g æHx# Ø"øZJЪ”£D¶3É* ê @(£‘ØVAƒÇö!øèaªz‘`ÎdפPƒ ŒÍLÐY¡ûù·´´3Ú-NÙôw‹Õzÿ4ÍÑPS|-вVÉ`ÀFA¿VÑÆ%ÀÒÁHtˆ°´R΂NF+uŒfÿ3Ž*µò:eÕb)ÞÃ…9çÒfi#‹Å(/eëNsR>é4ÅRò9ݨsþSš³Öhb š?wÒ¥½L¥i¨n6:·4¡ŒŸZ, ¶êã‹[ï|•í_B#÷{{ï`à—T ™G‚4_*íQ4Iüaº&*˜¦Å â—N jÀ"NI˜`F1O6ú……Î$﬽¿ Ý‚öP6`Ç4 Š—*ÙýOmÒùcÜYlsÀ)›@S¾Ûf}§6Xçvjƒªìǃ5‹w*P“G¥¿Wã”6´h ¤éVªŒ_ŒcÝwTM|ó¬=e˯=Æ-uÄg‚êR½$ÎWª”>kY·¤^ EÊSذì'—µ!# a/Áh ‚K¯u†£6ŠÔG ÝTHŸ¦ù ®{P1§Ã[íiž…r!3SðÙKl@tÌþ#e¿ƒÑ`&.„ƒùIRËiRѶeùðú¿‹zï|Ax´Kæ{”ŸÏq‡DäÓyT;M+¤>ój’ùÍííUæTm‰SqOPú-Mj©'ÐlÐì`T™H:Bü H›³xyÏäŒImݱ§i*¥É‚öÅ ù£:7–1 •]sû`{Ñ…U‚¨9Û Ož HÌ€š KÎûrÍk+’åO[$¼bŸ”`Wïxk4Œ6‚3ä§ÝdAËþ•ÙeIô´`Üv-ÜâU£ÉtŸ²=·š¨ñ-ô_.²N ø'¶%+Ú$Y¹Ûž6QÇæ· ]é¡ãõKâí£#ÃkѶɛ›¥OÄj ^íä¯ÉÖß‹y !(äè]\$Ò4Fôç ·ßæ•¡ÚG-Ášy½Ò{>³WÛCäoàX¤ÂY}q,SiÃvt D9ƃš©¯r,š(Éìãd¡GNnì–­œX`ÓÐúÕÈ~uÄG¥‚üÔ\Õß§9šÕÈwÎó±p>Ïf2Ö ¹–€#TÌ L6&¨Ö¬>_Åm~+•‹N5sµ³C ˆ‰ëd€AÊÃËÀØ®±yÕÃLõ‚Pt¯Ò°WÈ´*ûŒ2–¿Szl]´³+Àä~jãAë¬5Ot׊ o²DÂÞF²½ÊIš^J¦®îrÑáZ  j—<&FL!F*â€è®¯@A9@Œ:¨ýßÕ Àõ&Wwê/TXA‚ £ª|¸†Oà#Xã§Ç ËÛ€%ª+>w®¾'¬÷a‰™ $fYë ‡••ÌÒÇ– Y܉NEâ›2h&Œ3¼Ìâƒ_ù91Öi%($×AhÀa+1¼wkÊ›Åt¸×'À9àþ:âTöª½hÆ&Ë Ñ ÆTyP:ÃU'Žp¿¡"øõ¨ñb¶wú„T ªñš1:¶aŸoûj° PÍö¡’âRÿÓ½Ô§( |銲zkBã©ÇÈaÄ ”œD'Ò–è^eMð¤Òj—Ëy;DóJšs/• ¥ÞT|i¿MvtiµGt =m™ãÁÑÅ‘Bv3±z¥ÕCÊ5¼)êzFó ;©*_¤×F¤èÇQÜKê•kqfòõp5~a+…1ƒÐƒZTû1¸m“N+;bSÿoÚŒÁNáF½©›P[¤è¹‘è•eň¨º†¬•{G’,¾ÞFó!;¦?ä |X´[ñAÉa'JSüw ¶Vz„HDz#ò^úF³lgd ® ”<]æ­+·à5×9Œoz”=ó ËÖ[ÞY%?¦mެ•zL»5a%]Ž,M’}Ü•&Œs´5˜ft°þ e¾„ÿX‹U¤È4rùàO²‰zôŽ1úäÕbåJ©?I£”1•ÊÆRe,ÏÆ²y,t Á cèäod!*ã£?- ÅŠôq j­4æWˆ:RÉseA£Q‡=ÿ[ƒ¬,:«6ÀY¡q=Ð+ž"S¿ðëvJ®ôJ·RÓUãó€…ûUe~-‰ØWU‚_ñr5Q=ò¿–Çõ} oSÄOΤ$£óö¢À¢©×žqÒÅ~‘UËnòiŠãlüÍZ‹ú»L(ûÜJ¬ÕhÓ7l»×i\—©“’:^Ö¤¥KRGj¶«H5©ZðYß%c‚•Ëßb»k/§ä2U§ëóàhDfþe•ˆ·fЍìÜVˆh󚦷±Mö£šaßÊy!ÁmMŒ*PöM3ê%(6“Õ³{ª»{; ÂveÂí(…®5hB–Ÿ3sé\ñ` .”Ûë>¦·þeÑ­Ir¥töî}·Üv‡2pžÁchq µe'HµÎ2/½æ“+H+qýM¿97ÿ®%0NfÓH6G?õòýªÆHݹU!C¹Ì¿Ã{¡Y‚’ïÊnþùH ,¢awMý:q†ƒ^­'äæš ]}T;èŠ}QŸ ßõZ»êÕÊiÏêTD€Ú·22¯*RS»ï\J†Š˜±7…F²{úVN «ºäâäËõHë0ïŒ>JUVàâ³@e(¦Þ£T¦òYg¹\Y±í·A;^BÃzÄ´÷Ǹ¤Ž®Úû¡ïòµèö®è®áiªýv:¹âÝN§ú›kÖVÕÔ‰'ÑðÒò.yJ yïÕæÓ²!ïÒ«}–q¡ ü)á•sm…bŒã}bQ‹Eô…C›*]ë¶A•öþ4Ï BÊ}Œb.Æýyö!‹štWÎã%>Nëë•ñVhîOF¯í²4…ÞÂnC–¼5m;‹¬Õ»4„|;ky9Õà"u8Û…a¬sãþ`¨h0†a›i…R)1á Ó°Ñ6Á‡HÁ‘¦ßç¶Ošp1õËe„çÇ<ΉsÿO(úJyÏâZV7­™ê†%¸…ÂñWc©=ŒÚº¨·„!•âXžDfÈ&˼–bAïi3vQ]Gž“+XT3‰©2ÜæÈr\>RŽì÷¨Ð( ˆ ƒ’{R“Á`»÷¶«sP{õ'.m”Íæs×Q ²‡‹KÎbly àYÅë Ê>™ieŸKq‘cõPQP4„¥–®§×yŽjšÕ5Â/9[Æßøª—Åœgü¶:¬S!¹Y”8’;5ŠdoRÉ ‹£½W±ZÀüË9=‚׬¦‚Ã:þ_$}ˆJz~"*c’&€òñ‘³Tö1 ¯9&͈½ȼ“uáiÞa~óÌ7”yù°ä蕞1]΃­r™øåfnÍç«)/á…RÞ‚§T8]ÑSc#Ï›¢)½7‘† Û\•ã[§“*9Õxn:6”Ø‚(n|&­ä§`p:p“3ròPšõ‡@ñGd‹,,¤v”­åµÛÖ;GÁŽª­\|xÀþLÍhärë6£çìKƳ›ÏŽìÄÚÐÜgy¸¸£Ñˆ~òÇ£4ùV°f C>.ÉuÕ§+ÄRÂu(ì&–žìÀ8aº¼i‚’…ÇJUŽŒ\ 1ØYÝ×nvÓÀ¶ë£j®ö5ë’5d9¾¢pì‘*Ó´À§Ò–F5æpÖH½ r<êü>Ä©a ck+DɆdkÑ's†ª&‰4j®ŽbâRŠ"•*œÇDx@ͦZë¬ÑMt¤ªî:)ZCLÜ&)³©e˜ ¦LL¹Ååi-òú¸6–tÿUqïÄ*Òú ÚX^÷û0‡,€]dìsx™ÿˆÈÚõ\Ã~aä)UŠ¥IË3¯(s8Ãmøù«Ã¾@.ñ#Å»<Ù¿&K‹Ã‡š oà×ÞºøôâùNëÅÑau„%;‰ ]…BrÃßw_¼óâÆÍ?ì^þðêÞÅÿÙÉ‹áïòüuów»¹øðæîÓíƒñƒ¹Éã%Øe³ÃC<Þ¥³ñÓã3xˆ9Aÿ Å$l9®ƒÿÄ`†W„3º•â1”ðª±$Ô››dtæQ ¼q2Ì[ÄŒÃÙû5PÄ0«á-ð£Å:– ÜÇ’6 ~:kožZ`Ùìu  –Rœ×&Àñ0Þ&yŒÂ*¯ß€<Æ!>\‘£ž‰<`[ÖÔA•…¬auðQ¥N/,®LŽR¯ Q;nRÀÈoÃ(Vn1Ê@ ¶w©d}AQ-3>0RÖ*T“ 燴N>û“"¦œç.bª˜f\xŽŽš=óº7©y·X…ã,jCkKœ…1™Aîá×XlbS>l¢R4¶/LšeŸ® /W…3WYú5X>Õd‰¥æù)ìõiŒVëáÆ­´ žm¾˜i8µ §D†M²mRïe€¥5®opY=¦³ŒTô¨e­%Õ<Ë.8”‹#8 lM¯ÙéÀ  +7rÞ%qàÆvâ—ØßÔͬòvv[d—!PéÆˆÙñâ»ó®ë–‡]¸Õ¥’‡õéÅÿÍÐäcendstream endobj 523 0 obj 5832 endobj 527 0 obj <> stream xœí\YÅ~ñ#æ{-OS{UG ‡$"À <@„Æ30¶˜ ÍöësΩíTwõô½ã±A  Ý]ëY¿óU]~8ƒ<øwúïéåÁ{ŸK­ÏoÄáÇðÏùÁ’š¦ÿœ^~tLͼF1ÊÃãïâòЫCÌ ÕáñåÁW³µøÏÿ]‚hºx7¨½ŽÏ åŸ·Gzð~åæo[9Œc0ãæÃ­Úük{$c¬W›ãÚæI|«MØ|o5 »±0Ù°=ò> JÚÍG[3h­\ a¾ØYèàeØüûøKÓ¬ÆtŽ/à¯[|òΧ¦£žOžÆ2£åc} ””s7­åæÓmY7ø¤îÖ- ‘•AÁŒRb\«¶i-AIƒ`˜ÁØ:h5H!M5(¥`Ù_nÕ „U2ÍB&ó³IÓÒ•—Q'Zj®“#é lçðêå8FÝ<‡‘7Wø¯—Ð]Ž ½ùÿü<½Ô›[œ])7ßàÏñ_ß–¯ß”Æ—ù+k|Æ¿šà†1øÍ{0•4Ml O í"8Öÿy}yV^^–—¸IÐɈ[9 ['TÜÓל¯ÝDì}Û~¸H;±b˜Õ£òù¦í÷ÿø85ƒù nàyipU×Êäø¨÷ý¤¼ü¹¾|Η˜_Ò„$¶ûL·Í÷ôò¤÷òU}Y5üõ6?¢|Š€•ä[3šÛòõ×ÔÍ@@b$ËÁ€æÛÍzêR~]¶;†·e=kʼìéíçòò¬g6—Ù˜Ñà Ùi×Eiz]›^•—çdÑ´¼Ý­öÛ«ÍÓ?¨ÕæÇÖlñÑè@vËTû»1\|^ïE6dµì1Sjyú-ÃâobØŸ”¦ŸÕ¦Ÿ–—×—ë-Íà9<€ ì¸'ÖÌÌ {'@•ké2âšzƒvráíøÙ Ê+šÈIjg¼¡¸ûEñnv¿ ð›ûîõioü—=q>ï-ïqu†E9c/ÞÒÄÊ6Keo8ÆnFºÙØÍZ¦äN­»öWÚFo1zpa º.ó¨ý—Ù΋ 5:iúJ¨*æ¥C ù–óÒ‚?vÓe(p„½3TÏAÿÈPÿÿNûI}ÛæÕì'§ÕC¡vèƒ:{¾ yR˜‰Ý=Œo¿÷¹´²©¸ jrv0§ÒÛÜvB²@fÄõ4”I‚<ÉkìÐ@Ü“JÁj,¬œ’´s0X‘h´£,{U©ŒÚñ'ljaè)Os8˜]!Ÿ‘âƒsÞš-51£Úü‚sÈA:i¾°Ç“­FG#5·zPƒ:5WÆ Úr柰ç¬÷D’€œâ1Dìû tq°V6¢´AÅ‹A)íG—$á5ÿÎv‹óX못Õ E?‡RÉPiQ}–ÚY²”´†Šn… l§å© ùÎT#øõ,z‡ðˆÐ’úÏjêiô‡<¿ —¤¡æ&Š´ %ZèÀGƒ\U–ì,oH¦]8cÇeŽÖ@…‹2­P,˜¨RŽP˜ ´p’-ñY'Û¥³sÞ û3Z«%¯ŽÔhòœ&3ù]d™b T1å¢_jTŽLZ@ËÕ5wf±ÕI®¶­“ÜÇÊ„ m !%V{0gInå„K*òcìAôÑÚÕÜ0 i´uJA°µŽŸâj§~ ÁÕŒ!*” áÁçòz¥ÝÕ[óJ—å‰ I_Vkm½‘ôã-aŒ×Më®8^w¨©¦T7=oMÞ8[,‚IðŠ›d²hDagÉ-2Æ!©S’ Ä†¬ bZn£ê0ó0d‹a™g³î{Z CQã}¨­l$´i …ÍŒc…¢)—ïgÕ0ëwdV•!s«¶~W„Y°¾lÔßD»à’yô!½Z ¤ÁÇõxz¼>-°öÛ‚m_–?~ÃSÇ&x‚IwÜÓžíÁ¾»-¯t»»˜ÃZNC<¬}ÚÃu¸›Þþ~ÞÎÁÞúL•Qìè.¡Å6ò6Yʼ¥òê_^g{aléÊÛ²bLûÑ6‹Ü¥öOÙ^»D¼—g$+¼ØsßÙOv*þßÙÃw’MµW×ÃØÊVK¯\#6>6§pvp¶{r£KN6/ÖtÀÃbžŒÌÞµÚ5ed&H„RFE¤˜8@*#XV>‚«µÒŠçç^ÖÍé öϪŒë ösÞ¬â”Åúî|KyÝhK8¯4ÃUkœG‚Q ÙÚM;>ÂÏ•!*f|ÕA ¹?Ú4°òš@i°Tµ í¯d¦!™Çf¹Þ²áÙ”lÇyWZQëï¢M*‰qWdtUvû´âNJдc"HˆÛH@¸jl*7Ëǹ(ã0¡CÈËÍ›y: ø/ xD¯kžæ‡:éu³°˜\ Z„)R«¤Ùßð Ä}€’¤Z€i ÏA«³võ¼ÃF˜~4Õ1”§R÷·_úä5ʲ…eË5Ÿ‰XØlšœÈM8Š–ƒÂøø“ƒãG_å cÏ3ï¡€V _·y·uBTq $EÑåAÁÌwï6÷}7•q`eËÚl5©N6ÁãIvÐTº÷J:¶:hgQ/kÏD¶ÈsŒr0ÂTÈÛÌh1ì„ó ’ «Ê–îƒ+Š#J b(é1›£T"UÇ+ÐØkÄè3wx[ ©¸Ñ˜m&1‹5j¢ìŒ\]˜Ù:`H ¢y9a€Ð}cø¥6¿©Ñûžø Ç.lP-=À"AWÄ*£Sü?¸O³Xÿ?;4™ï'MQÎ{0ÌíÊZeÑÎ}#c€ŽˆòfêgXé„]x™¢ín¼eÚËÉR"×Ô;“såG–ø’ÍŠwK¸´»†@(KÀ*B¶|Ñ„ÕÈ/ØSŠD†°z@‚ÆUˆY³w†#&äL¸¥^KžÍâ/ YÌÒ„ú„ž8‡‰\ü‚sÄc^N{^£xrhÝ2v^ ƒ ó–‘'fŒ9xÊÈóF:ŒŠt#D(kàRÄPðæåHŽN>,M“ë+O®,Q›;1q— ¯i(ÀÏ<6¦Pàg2lBA¤ù-"×ôÕí4F8ÃhT˜ÜQjH{èØk£~g< §÷yÃvÍ6C«AŒã4´Æ·ÙÆk¦¨ë4æ%ïîÇè)°i¥›ðÚu…{G(‡nB²”„ÁVœ"“–žë5F¶Ä°Tyi'f1|GøêìnNÉü# § ö?UÒÁ o7fÞ *œ ßt!û¶Ì»éSkôcØ82AáÊ~\Ô a^ïŸÔé|^ú“z2ñúË«¿lñw@pý—(ˆ‘Î&.Sá%Ùﶘ5 Ê@Wcç(~z„]ú˜¶0¶™)õOõEHl,ã"²˜œªÎpÒ8C}šQ³ \Q ¢·ÜT‘(Ú }ŸÀÛÞ¿ÂÛ>÷Ó™‰Å`Áã ¥á%=tdvM<Ìô8‹Æ“ÄÊo ®ùE•d÷å¢Jð±ÔÁ•E&¼N3¸@§øIð¡•£ôó˜¾\„ž:O€p_Šó.8¢±M,Ô¡³*»x­…À½6Ÿ¨BÃ=k3)9VC䌡™m³Ý9_ìõQø€ñÙéÁ<¥¤…GÓŽ»ºÃ´[%Ú)Tÿ:L5#ÕØk´›?îªÁ"-s¢V¦ë8§PÒi€&1lXª9æ ™›3¦W™Â ¹È-{[¼ñĦÊÉ TÓg9¦7–Ú*+³–à5Ëy% «žPû]V¦†Ó>QlH¨ÖHß½/Z9§“iüÝ aq7--аÇv~jÙJ5už°Lë¶—Ö€(î¨F« z3ž¹jõ»S´k<ò«ñ¿Ëjzßÿué_Œåxü<¥ßIÇ8H P{eé@ãΓ4,/ ‹èGy1…ÏëÐd Yiõ9nË´8\qgÕ˜;í]5*?âÝèåñšƃµ_'2:=A;Þu6‘¤±Wå¿ùS:…—ãFT™¼ƒJ:,dg¡3³D!×ÉGôÆñMn¦ïÉ>€SvÆý¨…ì!Ó¸Rd%Þ߯ŸÛ§¿"ç§3÷£dãµVßG8;l 3ggxióùð&ÝïM »e¼y®¨ãÖï jK¨z˾nœXêø>å"³ì!ȹyEA.0e'mRC «§g‚ÕgʵԾÈû'/?n­§Â¤Dx·mÀô—^¬ŽLs×®ÁîV¨¦Æ³(—O÷†.³]À`yšr‹ºs#&Û—"…“7éXÜEçØèp“#•†E§{á«”\:W%±ÿïÆuYäºùº÷µûÆ/cIo¢0؇zÃ4ßÔ$|v³’]U«?ž«×æÞÔoâêVëÕÍr²\…Ìw&k›îUGv ¯Ûò‚o¬½AÈnó¾*/_öÆ»éÍü¢<å_ØËî>ëÝF;»+|Z[^s¥Í¯3…]ò}Í×±ëVÁê+â~ÑíôSítÕHŒ-eé‡m€,¬šÏäGˆÕè“röú}Û“ãƒÃßÿ%nQ‚endstream endobj 528 0 obj 3781 endobj 532 0 obj <> stream xœí\YoÇÎ3ã±oÚ5ÄÑô݃¬XV”Øòv`%RÌKeëß§ªúªžéÙ‘’ìÄ‚áÕp¶êêªê¯ŽÞg«¾«ÿ‹ÿ><Ý»õPjõøÅ^¿º ÿ?Þ{¶'¨É*þóðtuû›y|Õ ý VöÂbåäÊzÝ ¹:8Ýû~m6fÝmdçœSñ}ç‡Nö~ýÕf_tZ'×ßlöûνëíú¾ö~Ìú‹ê¬ÕÖ¬?Ù`#ï``e×ÿÙì+5t}ïâ¥7þd3ô]/´â¾„ÇNJi©­R¸„4é  A˜Ô8[ècÅú.¼sbÐ~}úhÙi#ñéWðö»è†Áëa}€Ã;7 "}ë»Tþk³oàO ëb³1rîãô0¡ç nÓ°‘ÂfЬd'z!yÏ·¦gcàôŒÚH‰þǃÐŽ{¾•@q×{ØÍƒ#ØA óÃÆ…–J(ÞrV×Y¿‚;é{z<Ögøñ&¦Öðï§ñ¥Z¿@:û^ˆõOøçCü8Ç üx?å§¹ñ!þù?ŽñCæ¾ð§Dx»>É­OòK¤^³†Õ¾P1ƒÄþ°Æî5u¡÷‹ú‹“8éAŽ„Yœ¿9K C¿‹¼Èçøqs³¯‡°«¥ÍÓBn5azÙlYÈ ‹óÒê2¿|Ùï¢5óóüDÔºnð†ø^>)}y#{R©BÇÃÒò¼± μ“éå)_הޓjL6>jåAp{è…ÌRû¼Ùé—Òé¬â#%=ÞÌmqtÐLÛ„Çör‹¤7d9¬éç,·¯³h‘T%©&9výWb-zžU›–&ú¸%9/[./ÙZ‹ þ°IÑQk9l3j÷>X'R!Z¼Ù¨¦ù¦Cq'¾Ý dþ%î‰î”Òƒ„¥Å#á%V FÒÞk0· +P®¥&Ñb}Ž7Œ–8œžJ÷C0SgÁ®Y°çáÏËbpOÒ|Ø Çkª ²@ÀŒÎÊÔû>(ý2$Ö:«iþ8P‰æŒÒán|™fx™¿xRFM=G‰Löš5ÀA2ɹµØA2E*MÛ©•…S²ùÏ SwõžvÎY—ÎbïU‡n§¾ÀäÇ-”Ýd+s~åSN½æ‘\eö“jöôXOŸëùö¾IÕtÎÚ«Ÿâî â’ÏŽ1‚8íÜ1ŸoÍÏÓs_çý…Ö> é(™¿CD 2¨“¬Û·¨ Ñ W4¸Øf¬å—ΉžÏ2Á•S䑨Øf¤®$¨¨Ç5Ö®Á €ÂÇ9$ ãJ° 7ÒRØ¡¿…9Í{±Õ™97tdÌA†!H‹Ç<-ÆÌÁ½1µÐË¡Aì^u6m{¹0èñ¸ÝOpó°ÀØɾƒî}od R+â!6ÆØ'.¥\gËÏ””ÇmYÈXîÃÔd#¢ù‘8U¤ßÔŸrª2îß§¾'´Ö•1SVÓš+¸m›Þœv©,œ›)lh<"<6%¼_ÞÏíÀô‹K0ÉÈ#\ŒpLžËØÅ«ëÛðÆš7Öš¿È;ÕÜ&É÷0ÆIœñ" v;Ä-Æ‚g&²·l±+—²óÇB)+²TIïØœÒöEÞs%KŸèú(‘Å»MB ed‡¹v.°€MªÄgSq ¨ û¬µÍAÀE1˜ö0ÙrÊÍ\ðÔèFßïúQ³p&uLžª0Ÿ Áà`@è|ÓÆ<ãÞm‡MØ&,òÙzÍlDŠô²â«ˆaèo|Ò"ìhÈŸGöC'U@» Pœr”'ÜD…A#Õ”ì•IÍÆd‰Ê+_k‰ŠÔÓŠkäw1>C¸Æº¸&.ºökÕ­ÀöyΆ…Ñ(ëÈøÌŒƒí¹Ô¶Ä¤Ì‚ƼϹ IîsR ¢ã¦}Ø?( ž`£ •W¬7 |=4{² 0¼ÀŸéöEÓ0Ÿ—FH[ ÿŒ#˜a³D‰ÕÐÓFuh%y^’‡ð*Ľír´üø/ksÒK:CYH;Â]å ãVºˆ¦z°Un ¢üŠÅºò»3õK2Œ‚ ~³qæÍ‚>„yGþÞj-(BùŒçËÚŒ!†Ã´w›až?IZÚÀ@S%’Á0H›ftâì·îU4Øéð1jdÄ‘Ù‸8föÏj³_I*PMª°Up釡ݦòXuЫ‹zˆ€›HO ªêCÀÜý”•ímçd}Üô‰®¢U$y³(<²Ibù¦’­iÚëú|GüPoÙî)'[Zã¥ü >-ºÆ;K*)ÃÍby'’f@tbK´EG…Øz·}B_Bªe¢ ´hÙôÉQV…J€ÉਂmRjû úö¹}¶Óë¼Q•“~>ìTË\üD è{Jõ,±åAÏÒMFlÅi«(ì¼Iâþ¤ÉÁådíº°…@\k ±Ée%ÌõFwX9pËõ)kÎGE±ZPì(ú€ŸF‰KÑ蛑ɟ[éeno÷HúÙS¼?ô‘ÿ í\8 ~™Ôž3 y@iL#Z$Aâ´å7º©ô…šµ#„%& Ùhë¸EÅ„"™IåBm3™vMsku. Öü(Ctà)ê3 ™¤ *0ApÅÐô”ØŠEyJLØŠpÑlunŽ­ 2™~ÙƒH&]ˆÑ»žƒ×Y$ås-a‚’‘¹lTr\ÃO´ä%‰æ&œ²C27ÙÚÈ!X‹žǯê*†‰»c>±6ˆV:Éq¦°ÜÈs+Æ X"É–/H_JP^@²êz™ÀµƒÉt§M?p@„&û˜DÉy¦ÈF ì-RÁ’H”°ê­Vn‡GÉ·Á’¦ý?Jy™' x͘ÞÜÆîC|}3:Ib¶æŒ÷1³%Ž›BZK=VÂAƒæ*qÙœ Ì4•¦œÕV™éÇ!©U´9z°¥ ¢-âÓéMåC\-ú“Yºè@>&¶®rß•ȉ‡”7X“¿øÕ+Ì”3Î;›EãJ¶ê¬¸ÇeÝ9ØûzïÙJ…´d¿NùX‹•€ Ã×Þã-‚Û÷önÝûbõòùåñÞ­oWbïÖßñãöWƒî}ºúÓÞ{«¯çïŒòßñn€ 4Γï,NseùŸ_†€ò^–ì’õ2vewÔYÙyý®KªR"O{K¹Ìåµ?¬`$©¼«Úüµ?Ûk>Ï/¿,-ïç—wËËÝ-M€ðÛË~Žs~Μ6û°Ú~v‡•äܬ.vPÅ¢Øß~!QS£ÞAÉÐú/õòÈ,Q±_è=êwT¬“¨éÞ‘¦Ëþ*ZÎËÆ²8þqËþÞ¦ò%…~›FúhLuÓ¤ÆwWt؋ֽœkÚ 3ŽËþ_Ú‰÷h"hüËÊX8C|¸,`òñÇ5ÂÿB¨G ¿*D݉bãùvÕ§‡å«–,5·ë·-tþ¡–©Išòì”%[p Ps63ôݳùo~cxóÁȽ#·ôª´[v±#†Ñ1W‚~¸õ¶ªe‰0QhÛ…€¡\I¸ IМ”[öŸúoÏBU9yLtÒÅ”F¢³JVÏe…òH¥¬"ÔA¦<é‚\PÈVW5˜[î{Ï”Uð‚é°{LßU³äN(Ö³«‰ª)_Z*çoÓmxŸ+ Bu]h¡lHºÎÖLK ”µT5E•>C£°‚ EÆw²ç +”u l<Ïò"Ö8 ×—°«j¯"É,q³ãörâ¯Õ!Çrü¹ìh“¿é’Õ'ùºUâoø­žxRÓ2jLx­‚ã)¡W•‹‡‚ ÇSMLÃXuñ’.Ù—z€³F³>¼lž‹ôô.T,¸ÀÇd‡Zõ]xu¬©â"Õ¶Õ†v¦Ô]j¿°´"Ý’r+©qóÝUÊÀ¤Æ-œ?‹t¸7TUVÄ*1ž]TcaB½3»ì¦êG$Kk½T\aÊ#ÿ ü¶”Uà›PB0 {•¿°%S§XJ¡ä4Ÿ¹ý·â¢k3þF6ugÁz°Ó£{úxÛÈ)Þ™¡ÆÍÙVY@2bjGaây vÛï¬$ñ¤ÐÑœ/žHw™”%¬0W1“¦Õ3c±pX¹5³IXpõiZû0.@Çw"t†ÁC€ã*Ð:- /Y­X¾R×:FíUÎÃÑa'wS[ecU-W˜JÌWÃÙ`«þ¼¡b"<0'å¯t N*~ ¥ëiá ÑLÌèO7…·²Ãô )â ‘F5*ë·ýÜÅÐP£«ýÜEu±PÛE¿³Ók`%æhVÐdWf¥]¾C·÷úÁÓ}ÈRHÖúœW'7dªÁ.?UÈŽÉx,øµÒ\º4¨C ûäv_ó‡M4wwÆ7kÅ ˜Ÿ0𕕯ãÀœê(¾Þû/¶X÷endstream endobj 533 0 obj 4337 endobj 537 0 obj <> stream xœí\moEþåGø»Qüs}ð4?H@³ÖYM}`ÿOâ4‘­@q"N©ÕEÈ]C¾,7Nj¯ùIã‰[³ØI™si-¶L¥"•¦T^ÛÈ;¸¬Àe‰ý#T­¬—['9µ3dF"h—Êî>Ê{ˆ»™­Î/€ªt› ¬Ó^àœœ°ù'ÚÁõrÐD„Õëµw8´@ƒi`:ÖÄ ÈI14_ã$E^´Wi.7ˆÂ F¯~CJ©\È(Ò@}vbÀ^˜pG-܃ٗbBÉe».;èIJëÃ1Ž(b. ÜžôÓŽ:‹ äkÖÇ‹hl[_Æy…–—Ä…ÒPÀ'†+Édw¥¡û p.@nÀ Bçuu^¯Õ=FU$–y:ê € «Y„MJ¬îÖ«lI_ƒ7d"€\Æà¸ö•]¸X«´’_×acø¼PAµ`2\Íò]¦38 в¶Yf‡×3ôÙ$Ïù‚؈ù>©'uê;HSQ6Í ÑŠmâ­dSEH G½ºª0È£‘G} ¢â×.$ПäÚW•u²\œl |‡Ç¹‡‹VqϹÖAòmXnš$iO)ÉÖã::“n£Åso´f«Qá¾#‰ãÒ´dн ¬wíI6?#ìºQyûup\eÊkô"~ed(³×#lŠÎ®Þ‘Ôÿ€ÑDÀ7åÜÁ vÔCÓ¢.*P2#ºÜ×™pŸ­ð''n'žo,ŽéÙð5u9X±Õ3f¤#§ÀƒÈ)¿ÖéUüž±_0e üªºhP¥eÈ—S•B\oAûQ–MFµË“©%! .èâI • ç½ÄErW] ÿ+ê´@Kr…¤6ª® tVè»\¾œw.ñ jÖyëœp²/œÝÕ‰h euÛœ2¥Vr¤Î.Û.™9X^= „l§àI­—-åÔZ--…-5QFGù†!;á¬åÌ‚e ;Ù7Ž 0HëlôÙãý÷JXØÁÐE6¹âý&ßOîˆÜ$]ôö¯35¡ÉUÜ:µô+Ú‚(šÖ‘Ú ø nF³ý¬6€ùô³RvO†ì°Fkï"&¾vÄzÇý󖜰Í7U4˜½¢ÈªmÄé#þ)`‘OxF)l×èYÿzÖƒ7öï£*pOÈà2ßÛ8q8.»úG‘Òò1r»ÆSÓI}¦:EÕKI¢‡YDSØPG<3˜nÖˆØ/Úñ“(ã]pVÿcNû ìÝõ1_Ÿ NK@FÚGAîÖÛçÛè ho—õöô8!‚’+všÈw«ë9?.¾Å|2bTUÞŒ°#!JZ3é d//^Í@e<ÄüY溡S3£Q|ò¨*À@sðZ.áLŒ´¡€Dáž—°Z?x¼Aá¬«ÒøçríIêJƒï6ÜŽ{!¦Wùâïe;-wÚÀÁ yñ~ÁÙtñu/ÒX#fyt¡Y뢉0¥‹Çµå½žXkï,@õÛæPYýF#Ÿ5#çhU;tþÙŽÛ¦0›Vƒõ"Óë¶K~ê˜EÛÅâló˜\¤CŽdQ4Ð`WƒåÜóñ€Nöê;ü㫲؇(Ošs¯¨S‰AÇ6¯Š¾œUXQÜáAivPçô]¹øU½ø0Ç6CÖsŽÞ|ñ°·ûiÒ~Ø™º#÷:mBð]@åðòîcv#Í·#Õ?ŠI~"ÜFÔ8n‰®ydVÜ4·åŒ«À¨gÜNàHƒ3ât:2ZS²Kî·GFš-øÌAncE$÷o·c%ÊèÌ|Äœ»lè6ˆG ŸÚ9”~´¦Ð¶”º= Èì†H.I£ñ ùòš5ÕÌ‹‡?رÒq”€mÓBXü2.$Îä7 镸M‘=emÉû;N'6…»ix$µÈÇåæÔÆîÜ…‡¹§é”<¹(r [ ³V|3ÿò¸¬,¡–Ö¢e1»ú-üÇr¥%`íR­Ó‹MêëE>çºqâM¡ø}þnû똶]\6®|3Ãå€þä4=‘`ޤƒk)Ö%Sû¼¨¿hRàß–¿±KB‹x‰«å ×ø× ×çÛß—_‚KKO`êÀYæqΙ¸:‡ZÊ'4@fâÂIò<M ²™àAŸ‹XW°ŸVÚây˜Yh2 OôÐ[Å}…aMˆå(¡(DŒgŠ“ hœìH.È<"Ø‹ŠÊn¬%žHâ¸(ћьU·ïtÞÑîÔ“hQˆ»Óæ ϵ`QKP@K§úgk0éJêIL‘Ïxƒ2‰Ò"ÄÁžú įy„$ÁÚÐÀŠ‚.,KÚÄ1Y„JFs©¥&ExF?Nß7Ï™‰l¢l)@ËÒókR ’Më·ýYôFüH€yÆ]šÆ*Gv¾‰ët?UZH¡¿ s…šÄ¼o¤Paâ™_vméŠjó‘Ôªa›wÕªfGI9ax?.+ˆ1Úë²?…íÐÕ›Æø¢–øÁ»Õd!BI» )»ä ’å_X¶`Eqj͵袖 ôœ¥óÖR DO6².Úè,›—Ýš…y*Lh»¬D_v'…°õB4éÉ òÏíŒÈ¢Ú‘XiǦĪ•YòM"m?µ¿”Mx§uµeY'AÞ$ï_Ò‘ÛÒýxƒå^7†AÀ]`¬™'«õ-õ8â.ï–ìŽÕuˆ•ªwMö³žyŠŸâfº_|Lr`¬ê0{‡\?XUIù€kåú³'ÝÉõ§óÃbXämN-: Q­£ð¦¹~:üIqã\¿–ý ‡-¹~4æ)ob¼zŒÞFð¶˜xë(e}ƒ\·ÿ1Â`ð4×£³×JõÇG6eúsœ¬a ŒT7H ~`왃75ÃÏ0 +¸?Œ‘N­z©~cÁ5r·›êO®ß ã4 «ý¥i1×`ça¤ÌúI³JÉ·–ëß×Ï ‘Ctlê«] B^´µø%i…qñûÎB£›$Yˆä¡´œ 想©öüï¹+vÈ¥¸ÃÝšª õþ%_€ßƒ;¹5ÊFÛH7óÙ¢=è'ÁFYo€o,0¾q)KdA³ ¾é£¸íˆÞ–wfR¨Žôá:u’»@RiíB ¼~}—Ôsu´P²ÌÄ#z{<ŽG#$·}®ÃVÛܦ§L˜Šl}Ó ƒvRcðË¡¬+¹Nh##³Ð`Raö¦azåÏñâä‡-„cúh§TLúaº&U‡ã!­÷÷ª5ºÌÅÆ¿ÕÊV\Ô¯+b/òÕ˜Wˆùþ¬%Foþ`þÉÞ`d"ì—¥Âv|÷D‹¦²}ö+Zz+pRA¾´ÿPAô^Va‘†¥‚!éÞ³Õw™µwSŽÛP@¹…è˜X˯?/ù½w¨ßM2òc“Ì?çmÓŸ'ò‹•މüv ÌrõöˆRÌNˆò½#J8<êݰe âMúÒC ÞTcïºÜù´Y]Óºï;O~pߎ“X í'£;ÓàaÑ‘ç|Ÿ)§¤*ÿ`,$ß>é‘ÖóÞî7Z?/ð?ëA«aÇùí×3¢¢ØÄ»#ÇX²0ÞI1oð­±â›|ç YQMvq—ïáì̼ËÞåÊ»¬ÙØ ûž3ìæW|j@R¬±há5ŸÉGä(‘çËÁE ¿S _ßÒ7´ô~ñ–dN'“‚åT]‘*Ÿb>¹ym$¿!¼å J¹&b¹ª–å*™$&Éàü%ÌØ;Åï¦W¼yµ7+*>Œ¥,Á[>zŽãàÞÓw÷6žHžø(ÍÝHžcaE'5a2‘ kƒHðfh «7K0'?°bûcMy‰ž'U*xe4¯é¼~“ äž%7Á×¶T¬tZN3âU¶³#8îˆ1T”ºËǹŒgŸi|°Æ:‹YŠ}å$àšzÌ'º˜Odù¼î Û¾½’k ›š&öêÌbÕIJ¦/_Â*j‡ßðª%¹ËÝMê‘k®í2AØ ªfÝ›–1Q)4/ «©¾’'üË:½y&Ugé†äÃöß´ùߤRg,ß½¢U¬ö”ÎñT–t±7¦ïÛ§…-Ô’ ©˜]*jŽ ÖÏ^Và6ìRN¸þTü€Ë¶äêÀö43×~Á«ÿfh[¼‡ V¡…e.zÜV·˜¬gÃÞD¬(Ü!DX~±³#&LÖͺ}–0Øw&²Õ¢ÅËÕ1MtÎ>bú(ß··„DªtÔ;|©ˆÕ·><¸óø÷ÿì)SÃendstream endobj 538 0 obj 4331 endobj 542 0 obj <> stream xœ½]Y“Çqöóš!ÿ… ¾xÁmvÝÝô“(Ñ”MŠp(Â’Ã^`ÉB¸H¼~½3ë̬ÊAOÕYy|™ùUÍw—ó¤.gü/ÿýøùÅÇVÆ\Þ¾¾˜/ÿn/¾»Pñ”Ëü×ãç—Ÿ>ÄÓ<4­óª.~{‘n .ƒ¾ô‹”¾|øüâ¯wt‡é¨§‚9øø«°¬“ž—ÃçÇ+5-ëìÔáOG3yo½;üöhÜ4Ïðép,¨Õ.‡ÏŽWÆêÉ:sø|œÂ¢fsøü¨µ \þ%ÞÓZôáÏÇ«yZ–Õ-ïP}¼rðÑ®®|ô³ÏcYV8šï«½?üûQMëºØõ¿þ[”ÌB_n7Í ¼õÃxS /Žϼ²z{yef|ƒ5ðî»ÀKhø>úurðˆ7m8¯Ò Ö-‡›vôîû¼ß²x­àJ Ç•ÖxŠñxº?<-þïàëáE»C»æqýÔŽ½Æ7w $[>¯ãS¿?^Ùɘ üá¼±‹³–ÆŒ9¼Äƒs¾©6Ô‹ìªéÇoê9ùëRß×Ì:^IFLÞ?n鯆|B_3 ÄG‡t¥—iVÖô£#"®ò{!‰ÃÆoSâ ‰Ä8âÜë¾ÔE)ºá-3 Oex=¯ùƳÊC†é¡¾KÃZ¥âÑA¡ ¹UMZÙÃÃdøñI;¡ŠÂâÁrìb4€öËá9~ã}ð6¿,ŒOMJ9öb  mDùA-uàQßóK_)¯5ëôîD›$ l:]ÅŸ_Óh8Ǭ䪟єÑ$ÁÖ_5‘æ—ñ³õKT{xƬ¹éÀ¹z]&ô9}ƒ'éh·ø êÂŒfìè5ÄŒ›Ú4¤ÆÇrý%½ŸBÝ•”ñ6=wó»&ã'Ãï&óö˜n6ýè¤!5=ßš â¥^'5UijÞÇ 'ÍsØ6×<¼jyžMX=Ѻú51›Q£×Hbù }û¬Q™<˜a2L2ÃF…6à µÒ4?j5x©hýÔPñdèÉ$’€¢I€·KrúÛ¡*½h( ·…ýîI‚ÒÆüw§1ín¦VÂ߇éÁ¨`t. Äbk–uú*:ƒ8b’·üï6jíAÁÙ3üùÛ±ž~ gŒ*Y2x4ÇjŸêCgŠäÁÏʈ‡(ƒÒýb—IeŠÃø¤\PÆ„>¢ë:k;zü¢íåŠãU”.(×Ý5ŽÞ¾Õù2¯fúK §~ÈOÇ>ȇ,Êή@tÆàÜ=Èçg£nNåf Âe(„Isy¥Ý´S¾JSÁ©5Æ[ éŒÑï®(uøüçcüFçèú"VH_Ä+ž×“¯ñŸ·ø¿oê)¯ó?5â¬ÅÇ{¥³hŸÖƒ/ÛA£õþáÃHõG™NûVºá+é†ÏÛÁÛr0Î8EäÆChéU/tŸ×ü‹gùµ`|àŒ•o^”ë ²PÑTpV-D!œËvÎÓ6FöÀrP<óY=˜†‡0ñ$îo%‘µ'_?Åц ±\ó“vÍ5½f(ƒÒ+|S>–IÞëe=øBÇS¦ äNQ•N/  IWèþš‰Ñé]G³ÄÊÇ×í\0¸r¸¤ öR¡ãó:Ù™÷“‡„,Ö”hàÀ4ç`½L`®ð"z…é þà¹Ï=8­ Z:ƒÛ[Â`TfRð!€¾ÆËm’„¿®à©Ât/ã×Î(zuœPÈ¥ìŠShÔ½`Ôƒç{¯4O_­Ë—Å*o¶å¦øÌéNÊ[172 Ú/.>ø+ÍØþ3º:“Ôïaûž„±.sÔf!ŒùkÊ8£±J„‹)žÛÙ›×€‚®Ì ß ô¶oÚÃ^±4›!l½„N9À&&WŒßë}Ñû2:b6r}Ìvhfƒ40nk+¨7:f+§c„!ºKîäøû}2©5<[”˜ï83 Ö‘Ëj’DRÓ–%=j3À0a¾7Ë¿ó×ÏHŠeržøSK©Xð¼JoxŽ$‡•B-8Ì› Ue>©6¬qR÷Õ® …%Îà¼q]¶ï˜qpë±ËJào‡`˜¨zšÏ¸‰~S£ªÃùQÕy¡"޽‚tœÒ¥ ¯ ¿K¨ëh¨…9«6gjÚ~EAÌsn²\@„?5[…Í )žhÖMëL"T`%Qåa«Êÿ:fx8òyŽÊW\ºNàqÿyÔ4›i:ü3ŽÁž MÙeyàuÄ $syDäZ}–T`hvÐŽÁy~Z‚ö%=­¹Mzoò¨P8yTΦ׾宷Ãñ$GÇ0>Û˜ÈIþàÞˆ'nÙÎF¥5Süø€'q˜¿âwººK|4ÌŸÛd§þW:¾„-S+šPÞŒjOuIÕÀ¬êpfŠþãÑÄOôbWKH_B’åm´°¿Ài!¸…ët¹ôE’ *+k*j…i1kQuœÂå3øª"=eØç)òP0»Iå@ïFºßîcVŒf¦ÆÀÝ›“ [ÍÈ…ÉëQ[ !¿>í#2Šàxà> ‘ 0§0òDK!²û=Ê<)ZÃy!ÙÍI·{ªÎÆÝ.:Ÿ`cÀ9åM©ò°Èž‡Årñn°ST9Ç[¿ŒçÉ‹$x.Ãc¨„¼nÀx%)ìuH0Y“Q væê8Ç[kòÝÌâúq6¥%Qå3äEÖr"!Éö¾k¯7Ç-HíQ(Ó•€k¼xoâ=`”) $‰ðˆòòèFá æuÁd»z)¤Xrȃ™ôyHipìÕgR• p ¶ôŽXG, ×f,µ[,ªZ×7„°侄<¤à0d.ÚRÐCî#à ËápaV±Â s;eã»§ *£"„ǹÀ¶`Ëpn3¿°<íNÝ妆'ÖÔK1ãZ»iSå½‰Ñ CâéK+Þ`À+R¯p°çÁ4;ËÊ‚åñ烆ÕÕí0;oÄÖÖé7Ì䌷ѿüÔ¢Y§theOJW‡ÿ-ßv˜¬<éŸÛ÷©ÿehLD­„T%uâ­¤R’ÝL(·sFå!ŽTÁ‡°­æÃvü~ ÛË’:Ö¶!“`‘õÐfòdßÙ4ò„Þ1®­¦&ŠÄºm‹Î½ËE`¨y§\%ÆÉLJج›2,£X7ÆõYÑ^ÏÖy'‰%RlÂÇb¨SXP©M–FxÍ$iNB.´ŸÁÑm·6Ù÷vN=L¢Lð\äc,tìÙZˈÎÞá³h)©>+tKaýЊ¡¼Óßñ–!¢Z2 Ýde'Y•š‹½©FK$mó¯³ÀÀ· ä¬³LSÒ?OÁ+R;.2oÞä"ÉK±‹Jʳ¨RÀ*$%!÷Ì%œà !l©É& „@8+N€ÂÌ×Z’c©™µ®8ä#’P_»ª¬ÄI)9+ 4±xÖ9Ìf ™t@Kšßx{jÂP™æÜÙoƒê‡×¥íeú}ÇT)%† íîDFð^Ka1Ç#˜dxªµ'jD+‰Q§<̪6YRa™ð( âŒ[Àãå)̽Ô›ßu#ÕÒhj«X#°‹ù轃«Œ¢y‰†TÃ]´eq®eù-¬Hè3YPW hgFêSD©XcHfN4²½D‰d‘]NŠÆ0ÉL.ÃðG&õ‹—äƒXë²^Ênù¼K‚,§X!"b}SG©›!„¯ýt15 Ôé*qyüIœE^®’çÄgu“_º˜ ïò­Q5‚¬4ÇQf_GišTç‘$˜F­[ÙNÉ”Ášy¦ 6–À@BÇÁ©xC#–##ʰ,J¬‡e¥{óãÑYˆ?y²Ÿ˜>’ã¼qi¶î®Þ1Õ†÷$üž|’±.Ö‰\~:êÎμ¡W­AµÝ¹l¡é6žÀWFdÇI’¹mÈú‚äMoš¦oš òЬeþúìÂ\¹xÌðã©Ø†J ÔŸ—‰vëw %ÝF‹¢±_CæÀ4lšÊîÕ¥J4ÇFüfWhÜØßÕxMj{³ì¼3â ä +ÇÆö4!ƒë’ÛÓ™“fÍ~{Ÿ‡X÷ø`IŒ˜Â0¡‰óQ+O´¦­_b|¸g”ÔGƒ2ú˜„jÜj6ÝìBjÇôV#²zmXbTeH£<4£ŸHç1¢Tõ'Yàf§à›ç®]½!àἆ‡2^‰"àx… |bù¥'Pø¦¥Í¤‡%_I‰ÓݳŸÜ,é'¿ý8¦›H?‚,bÜ.'f¶xW¢øKoÈ¥J¡˜€K%×.÷¸=²r1‹;`² ³¯=£ êY)€B²S^¡]˜‚ª"€'¹ŽâDï=„À ³0ReîIz(¡l¡‰@ÄA¨¶†ƒgxb,#rE—“[’œÔ°“<§cá^šë[i= €s´R›}’$)sLCì¥i`«2Éð]¸Ó´Ùi­&EÑ\r•À*< Æísx&ѵ¿e%ë.8;4îéïær% o=.l œ°ÒS4©.|Ccž`Œm@ ž2ðJ|3ɵ\gLc[I^ܼ]~Y’ÉÙ»ø˜F ïlƒÀ,™±†¯R y´Iö›V9eù/Ê,–ZÖÎÕ Á·ÚŠõØ;Ìðª7…’­€A)P©'½ß|"NªÒ¸1ƒÆ?¤”Á`O‰\¬ó@&<§Ïv Dç§Îw¡¶w5…ëža’hf¸¼íG²¦EZ& æ[¡d>{xñÕÅw—ÆDÖÑ| óµ\j ѲÀÑ9.G{üüâÓÏ/>þüO—?|ÿ曋ÿr©.>þ#þïÓ/}þû˸øìó˯¶Wöq*gYÙÎÆws›V÷‰¶}{”Ë»í­XÑy*Þ„&¦~vñ âZª«Ã©r1·”XÑ ³ENu8H©dHÃ0¢Z@÷¤èÙGüÆ”»cý‰5´I°@ÜüÞÊ•2¸Ýd—­+Çm±6g…‚0^Xí¸=‹¸ FÆLXÀ‘FÒMk¸”*Yw‹ziu¤‰«)xOrhŸ¤¸W_ü>ò)B̧X ÅXdD¡iá·¶=7:qr­LŠ:e4lˆ|ƒ=vCáøæ~æ§ÇR§éüP½–w<¥–bá¡yéÈ;e0wNÄJÇßø.§ßmágó=•æfÍ>Ëq ‡q80_žVšþÛvü—æû¦d?yÄËÚº!T˜6Êv®W×~¾é¹—×)_ÄD‡—¿¤ž)€¡Æ³F&~Þ÷™H×å¿=:&#œr¦ÇSŒ¦ƒ/º‚CÆú}0±XÆÁc}&Ñ}2Ã%%v†ùô’& œƒð*k©Åm-æu>ëpÕm—üÉÕDÂp³‰9+ÈÞu›ðŠkK#¥•pHÞC¹KH0¦$ñ(ƒä¬1¾´VKvXŽt{d ÿ¦Ú¿6,Øl*1ÿ6x29\a¥¬µŠ÷X˜]eYðàñH(-È‰ÚøKî3›@ôx§.Œ=SìsËë‘¥µùÜ;o­A¶ÚY”TÔèû俥`—1PleŸ\œÞh0„*Žñx#… CâäXdUZH@@[]œz)ó‚ hZ”o!YI—ºåvÿ5—-Qö´I„2y‹ L$Òtö³4>Ë[¬F³¦sA Ìè>Ö‚Àf¹­ˆ…;ý˜¶*H¨Q‰^¦>™«ßqA=«Ìe­#YRWc&ݖˆ“bÜc厑wrYý&U*Ú|¤JºD.¨kÆ’úKk„)^I W$T°1ŸZR¥¯}ç5U ?¤5¼R±¤ëbe.Y_³,¡CX'ÊÈ$d‚„´«Æ˜ëÄRJBš¢Å&KìÓodC¼–DÈÃŤûDzØG„}2©±À Ž~ïÄ_ÿBÂFÒBí\o*‰Wïa/•®' Cµ° ‡G¥vO­8™ÿ"£õ¼¿ÆhQ@iý)]Á)•–I'o3 ÕsÖ®Sú8¯Jœ t:õ Xd׉&ÔâcÞIUBEÚ ±‹››ð4uØÇEœ¡U„Ža6øƒ•?°“ï4OjòRǹ¢¬qFü£-¼u¼|ºÿÄ0Kw£Xõ2GMy¯ËStðð ê*m”q"ÙŽ¤·ÖìlYº6'Ï’ãF Öž‚dek’“äÚÓçëDD=b[t”©DåºÏfÖ\¸íÆË)!·¿’|>‚<ýœ{n€ŠÅåÛIu×$fíØVÑ·dÜ§ÒØØcnPJ·ùdb®‚vÂ×–Ð¥I¥gUŒÂ` åîŠö”4fÊ~cé /ÏŽïUˆÂÚŽÙ¶ñÑûw`J\ª?¡Nÿ,Å…a1”Ìÿ·Šxë!ò¥ÊÕL¶H¼›ñƺ±²ñ5•#&gu‚M¹ª{^îÆjÆR¾8ÝȈÝUn ü 5æa±c”IdÏØ¶9-!ÜâçJÎH‰os—Ü Öõ­u ‡dïÙP:ýë²j“PÀ=/«V0¯÷gªsÔK¾œïw„ïØ1øóÖµb0-™AÄ“<1ÀE¶Þd,=¥Š(ša]l)-1Ëhò¶Ä©–X—ó°:oŠéíöRöy‡Óë.òžÀÛå)hS!æ# Ù9làˆ¡ØÏ záqfíN?·Ýê5Ï2$tGlÒ¶.È'f<%ÊQÄöT&­î5ñc#Ä­¢»bγœ› xåβv­µ@{–ÉÞÉ;váÂxÌ÷” }m/qÜ»'F@C—nyŒ©×âêrLåØÒC@Á׈/*6µ…ŽšIÕÉ?–½ÄiÛ–ÐëR{Ê…0îaž†ðYÞ¹P‘C_7×O>ê§F¡^ÝäìF¯›5–"²·uüY|†š‰P§¢7#Ô¦˜‘Þ˜‡Œ=õÁ§„%ž\}Œw îΙfRòè­{óE'è·G\g¡ìq¥5õèp+WE^I¦•ðž!Mä“o­Z#¤r¡xÎZµ¼µ Ùò7k<â/àe@À‰"´’öW6»¬e{ÛÕ!k0ÉN[ºý‚¸Ö¶ãöà(\X?y|¸£e¬šì±Åͯ[ë~¥õßÚ~ñq…Áï<¿5§³Ï ~¥ýìæ&23h­.Fœ}'3)ý¥O2Å ®tEÚ2±>,‘²ªœ‰TU…gß#eU¹ü_¢¬ªc]ò®€q37\‰ÀsK¥+Œœ©” ÅZkÕNùªBÞÃ…+˜ò.Ë6vQ §g‘× @îü¯ËBz”òV&¹2yº“pàæ.<)ƒ›5*ɶ„VŠfÉ1Yg3Üæ%†+ ¾œAêžîicµ†Må!ÅF¸ Ä^Ñ‚«€¿? 4ØÝÃç sЍ[/éœÍëRW‹}R*3Dÿ©ù*f¨¼¥4Ætæøý£Šþ9±½im²ŠejcÛœÂñd¹§Úƒw²ÑxÓ*go£tØ Ý=¤4ŽâdlmU‘3O½$jù©·èJql&K¸TôÚï}Õ¥p›”CB’gµWV Ngµ;±yoˆ8z_½kêè’|¯§Îð¼ÚC$3‡dd`œ Ç•êÀ ^mÍ%Æ"\#@•r-/'…?kcÈbågjÓ÷)GG X …ÊÒ xs¬ûC0‘ão'ìÈ‹æì¯~,6çý9EzœÈ€wVr‘u¶ESæõ]@bly²µ£6±P$•’Í©%wC ÀÞì&BÕ ®]÷wÄoÀêeòf\î3‚qKêà¢ò¬‰³×m ±$Œ\øÏÛT¤hI¬xè_ŸúÕ%Ú¾¦ù¨óø&<Œ3RzÞb‡7Uî$ÝEk³m#6{È‚”ÍT5¯H‘2¢lwÃ7§¸'“JìNw†I%^€ ¢÷ÂIz†^ø¦¾;ˆ{=‹‡SxÄ,$ümø¼n‡æ"_ÙB‰µå¥Šd£‚wív¢J›¥ÌÜ$Ñ–ìð˜þ(Ê)8Jï6Ÿ„ºV#nDùæH»*#Q¶Â½öwDžŠlËà?ûþ~ùV K éðù!ˆýÖl)SFÒ¶FnëÚ£i¿­–†¡õb6÷Ëñ7”ô[¬´ºcÝ'7T…ªAù¤y©9Õ[kñ—ÇÎð°e‚›}íñêµ3"¢ÀeÛÅöh•ª.äÜ»/ƒúåÄÕC‚vœÁHÎRäñãJrÜ©FüÁA“oRõêŒýTþ¿úgvÜOå>ó7§Áñºtá7{"‰T>nIör­¢GR¿“·£’ÌAw`S”xÖih\?É8»¤¡Rv𫸬TäsŠ]ÀÒØãKçäÍÐó®…£ó[#ˆ?»Ë8PÇèê·Aç~§ÝURÑ'Ÿi«K.Âîö/y¥x÷Óï‰Wl-E?g‘j¹q;bòsg,¹Î’ÙZAÔ-¹¶Ô™ «Ø¬3ŦYZŠŸ6§ {M3¾Ç'^TìzlïhCZa_àÇÔ@#vŠ]kKÀ¾¯†b‰•eŒfç7,sµ^4 ÒH¿ÞÐ\‰&*ÖÉÆFÜ<èJ“ÜÖ¦c¸®õPÓv­å{åí’~`ZŸ uSX+>ïlnÏÛeª§sn”^ØU&’[øâÞlWN¥­6Oï´“à¯.þß] çendstream endobj 543 0 obj 6893 endobj 547 0 obj <> stream xœ½=Û’·qï´+ßÀâ‹ö¤¼ÇƒË˜JåÁN)¶SŽ£Xt’Š•’+‘Š$.%™º}}ºqísæ¬ÈHÅârƒK£ï·ùúñrVü?ÿýâ«G¿þ³2æñËo-^>úú‘ŠCç¿^|õø·Oã°ÎÛ²©ÇO?{”&P½~ì‚=+ýøéWþzcOëM8­ÿóô_ð•°°W¼;ëo=½ƒ‘ÿtº5gï·MÝüþ¤ÎÛìv󛓾ùèt«ÎÖ®^ßLO 7†§¦½Ya±óéÖûpÖj½ùíÉžÑ.Äi>>Ý®ð‚Wáæøn€ÿL\ÕÀœÎÑ üó òÎç¡›Z<]<Ïe·•Îõo0@ë³6[yÍuó§SÝ7Nøa; ì{A« VT ‡à^Íš÷´²øLs¶ë/}V‹Òq©³Ö¶ý—“>/˪U^%¾Ô­OÍ[×^å;á×x›/åêÕ¶¥»ù=Ì‘·¤CWÿW€”sÖ­ôšÒÁàdÁ K»Åá:,øüæ\Ú—p¹y ÿ¸‡?ßœnñîì¦o>/¿û,‚ƒƒ¾jàÿ &Ú6ØÂÖ~‹Ï—¬Ï^·WÈÛŸ†,Œ- zåòC»xIûóê›×öÆ´­þˆGX™ ¾…€kFßܵéëê¸KØ£w–,I¶ô-i]·@ÞA0! Lp0{ÖK`Ó@nºÝöü¶ý‚öÓb€Þֳх7»¬@=¾ìÉ; [‰·µG&e`„=èð»Fe餋ºù O¤Ò¾Þ¶! ˜ÛІ%¹ËÑð!9[Zw]¶².¾ÞF╸+È‹²,®•á4¼÷)ÍÀ?Vá=ëÈ ÷iÙv\|ˆ³}ôPWõlÁÛ Â[…³/:ARÁx—–\TÅ/Ä¥û“ñ09à×÷¤¾Å¡À;Ä‹ÿ,¡5Ò‡ˆöõ0ND2Ü,’S1ëæ ü€‹è‚àJkÜ•Þؼ"ËÔ +ª7œîjm⮄3¾ÆÝÀO7q_á‘èo8ãEïÓ"ð Í }Öt1Á„n½ÄêA:^‚h,Pv`ŠDÌ¿ÈtcζÍÀG} ”ÞŽNðñû&Y^UöœiøRÚTlèÛè‡M¡—xƒ¢¯¿PÝwcì(¡.œL÷U¥£µÊŸHðÝ^`r„äËäˆn O4ýs*dÒÍoMJÜÏ$Ò®<7Ï)ï¼56 ŒŽÕª)ƒ‚×F×µÛÎê°¤r Ð*aVY{Ó(ä>]ÍR™+â-îŠlòM£…Ke4/ÐCŒ_a%kçâ'ã=‘a¯Ú÷ô+8. +—X~F¼¸P*žµÓ‘MJºÝË~]Ü府¿ Ý éü©š ÷¥MZ-ÓQfÚ Íæ¤†à ê)^¸YÜ9XU袃Ï!sQT €C´#:fc¬ŽÈM]Ò‰+é“ñ÷ì°ƒ H¼Km ¿•ô6é$<ëΨ€S, Š.*:E±êG-l5_"-Ô¤hdÐXJÖ€N@C `°‰ ØG” É5 &JÞ§jdªòP°¾‡N -PxWcyæAŸÀÅJ¤6šœƒ¼ÄIY2^«©A¶/Íò‘Q\SDïª:Ô1 ÿ6ÓþB©jÝ¥Ô<½¤Ò4LçUÝl«Ñt¡Š1]DkdÂ%á´ß7ó^Ò¿Ì×¢6NÔPIÀãB„h+Ýú£¶Âé‚Ùc'vy¡=³óM@nã€)¦ cJy5‰EÓÕ<Ãý┊Ö2Â#‹L®6à:ïË„=}€{)󞉇’H†'‘&u"fž—Ås?_ÒÌf~‰¬Óƒé<Ä71*ŠEÙc6 µRLUëÔôáN*ü…sQs~ÆaL\Q6RêkôØÅ#-[ Xg#v^R]ïÒ{/ªc™¸CP*Êí§‰T :Ù+ ’¸jâÊæøÐÉi<&¸t1öS‘0‰æÀ] 6$:~^5ªqv….W‚ª™ä¬!o ~º,ƒá4Y¨å.KÔ]Î'xp•ëuÃïž-¨ø“À¡É…ÝG—Ò!e)ûž,õ”g& :ã.k$Œjå»a·&éOŸ|µîŒ´ú'Ñ+F¹£¾ŽÈ>Ô01 Œ¡® "øX@ÜiLÇ$fPÄAhQ" šv‡ 1&`lÀðu0¬¸®Ï<;úâfØâDÁiÏI8Ϙ™}ÈñXZ7_&íu¥1žÏù-#®gÒ¶Û ³ cHÃaüu¡è5‡äÖî7/¾`É’Æ"j_M4raQ›Ô¤ÅŒßS…&c%–DM¬EB {2R§ÉXHÑõèŽÅZЛg“ødZ¸Oµ°}µhÛ¶B c°Œ(C¯€qª`'×,1Ga?ƒ~3ë8y4úYµàË"[ËMbP¨·à¶ÍIôó%JÕhâÙMx‰;?$W§¸ÐÆŒøß1漑!ÛLöêçk®âÇËŠÓ­â;’0™»»šc~ÝœøtR·_Ÿ+{ú¸gP\þçyÉô‡Ð‚@q#[ð4¹áO)ë,'"+f­ -¥Ø1`QBTè§AýаÑàÐ̰`I7_Õ¬r‚ç Å‘Pp¦€xþYÔ“€(ˆÒͤ–%Ðçk ) Þä^% Àê,Ü'’í]µŒ8Úc)‚4 è×@´ÛAÐ,¤J‡>;ˆù‡J‡%<pM:ÖͲ襠{Ù”e®Ûû^«²nžøEB4«él ¢V±Å-¿Fi³&òꢌ‘É1ãM ¶ wø\r—y]Ç%³Ã¡Ã¥ñÍT…Ljj Õ¾\W³Bæ(ݦ¤>Ûž±ß¿œÕ9ÑëÑ(h^Fô!;!Y ì'j£œr5E]ÑrÞËSI0»µ"šëßìåAéÄ·›}ÐߺS³ÔW,Õ¥4Ä;Xbfd *â·Íø‹¾w 8ÃÒÅšïò\È.ŽÉò†P‹Y6<åDÇ¥ëó zƒó´ ÚÀ8ú­@¦UVæè¨}¶r„¹/–”b2r5ªtV…óæ VPd§wœaj(ƒœë|y¾=¬Û§üƒX‡«#ÖÍ$‚U†&„påÅÁŒ³f¥I¯vIÞ1Nò@ †m¦{8xLv;âJ¸µ:9R¿«J—‘3ÒÞŠøä†jrôf™{ˆâŸtÁñ”…„à÷gM_zO6§Æ²©NÚ0¿Ù½ÊN&¼h6ˆ'Þø1ɹ9¨0ÝyÉ>9U -ë[!4qÿÓ¶Œ>,4­ñ¸ÞÄ@¬Di¸ëW8$iBï(Ë­ÈÎ!î¢cáZ¦@ÙBX{ä(8î“Þ@¶èê.*pèÊæ-çïlØí&äU¿ÎÐZ{Í%ÆÞ³û9;`œÞ–¡D›<»šxv‘\—”þÃy•Kš“lQÌr–øÛ¦;)AÀÛy·›ÅƒßƒÅ«Ìqw$n¡‹“ç£Nõ®K8ëÌW±ËĨ³˜µ³WTLáòýIc²„¥èÝ{5:G1ñÚˆ ³›Œ"ñÔr>âH’ƒ³°Éè)Íyp,äѻ皼Fé&%ªu®Þç‚eE²è¢YSãMŽÐÄ9Pî›UB瓬š©Áé,ˆ="|géÅÂ\9ipÇ €e÷Å;õ3U,oàB¦ZÕªr`Í`Ý]‡ûs/;2Q.CAP!Öô%C`+NÖÊU/•ËDíî@ðâ*÷X^<°”MHÊ¥lDhL´Á˜¾k~º'Ý‹£á#VQy9dS~D ¤˜}1.š„ÃvT"…\\Å[Yg‚â`‚±ç”ñN«ÃJ ›Xv$ãkðßF0p¬–KéZBá~âe*øÛ £¦“£D6´::ß«¼HQvï2·ž¦_NÌt¼¶E5Ú ñFçÅAñ• ØËÃËéÁRèK$Ð fu ±¸ÏNdÌ¥°8Þô^X<±Ìd3¬g'”ƒÝ5æÀlꂯz)·P„z“1| ”·›èèEmuÇ· YÓ&¦¹È£$(·æ×^ù’B#]…§àÜ%¤Æ­î 9®]]¶ºÍ–\˜2= «‹Á;X÷ž¥Oº- ¨ÚܹùÇ‹¹2’â,2]·ò¢X©ÌqŸ%u%Ú ÃÚrœ!I~c¢çœË›™‡­º&ž±˜šìž`6Üëw­¼¥Žø¥DœmTŠ kØ\Ä%$†ì[»<ïvé«|;[zѤLgž¡_üo$áóC+I¼Ç]©i™èG‡šêŽwK f‰¡ݪó;ºd–’ÚaU ñÒZS™t+Ë$]¢öR5»ø¤á½H„^50ÉêUM`‰bň¢\4ÕW9Ú9‚´w ™ÔDU"5–ÿ…+-ÑÀ Üš*ÉšÄÀ±tsi—¬—Œý6ÎÁ/lò£d¨zNˆ%µ*XÝEÔÄΣÃçïÜñTÅ. R–FÄWŸ ¥¶@w•.Dûx %†­±cÞ¼Ù'$“ ?É^ïýdc¸<ѶX8Ò•½"à KMª_r·íœ•5 :²2µ6V¨IÚY (» çv®:‘ô²›ÌQXWGYùž½$bä|âg‘w^»ìN®ôˆÒøÌ¿F·ßÔMRê„—&1F©æW±Š+Sò»›†P¿8®‚Ò¤|{&è/ +ÃpÆK[ñÙšwœ•Å2b‹å`ƒ$kÅ |½5ÒIoãS{‘ U7(hö+® ÓöæZ«Xhð’mL>w[t(’f4r¡b«ß@íyRBOMŠ–f'tz+"ŠˆRU;øä®BM‚@ŠéWTAJ¦ˆàB"úÐr »v¹‚˜p'2€¯l`Y%è•þ™—y™T~*X;Äõ,-£ð¹ÁÈC)&dê ¸“Þ.L=¯£J´˜ƒK wTñòFÈQ,Ñp¥ú ¦`TÁä] 'fU©aTø“9Ç3uËA¹Ê^¦ikhJ³MÊ8'ë?*QYøgOôjÈ3¬h# A VN3… ÉG >Å©¯ÊÇŠ~*ô$qË+dqÀPã”ähz—µÅ)fóËEgÃÃBq†\–ÜÕQs}ã/wB_• 9&Ï„ú³. P³À†ÐK£§ý·Y„Dƒ€Éï¿CóEm°ôã.P³g–ÌG§È[}¬g×k’õÔ_JL2=Ëš-å’ù l!³¾ÇB&â¦-ÄtÎõ•p½¤©ÝÄÓ¢­éZhÐÌ!zøZ˜‡‹R®k¥+›¢y*Q1Sj]8`ŒhK­Cn¼ç¨s¡O*-âÅõvÔ{­˜Ê ã2éBˆ:5‡a¬¾TŽÍÈ¢Dùl,×”L¢“‘Û²ßáˆÁ7ØöFÝü'üÚû5ˆ"åuº&»²¼U.Z&ƒ£Â½ÜŸZ#’M ÛED!€†-0³_u‰¡(j²îYD&W#‹Æì‘6K> Î÷®r‡i"dWcF”æ±ûš$6w$‘­fÉ6ÚÕ .‰ÁûªœXg6ÍU$HY³¯h.&ç9 Qí ÑÉzOfRœ„ Ìfkæ÷YšU ä¾l²°iü‹œ˜h¬(o—¼¼%R)2µtÚ·¬…ïÔú–N›Ö©œ,‡ž¦î¤•rŠŒ•;±ò0 „صFæøcio™ElÖÁJ_h$ošV’"g.¥ã‰êäÒ`m”² Rsñuò9×ò‡Rô¥\³–ìYÀ1iQQ¸Øïó±Q­½Ö.u77ÔfÂ0ƒä¸Ë‰ž†{¾jG§ixÓ1‹ëHØ2ev©õª4{<«§ÂA*ŽÀá"‡Íqâ=w`•mKbð¬\8zÎc:ìàòžxÈël)qìÉiI ƒØ ð'F¼ó(Ùµ/$wIVë°'-”ýîëàK7ÅÁ¥ h¼Ä«L΋1Q7ÓKqTÛóRi…~ØÎæŠ Ù¢6n>72J…8ÁÇÆE_·Û<Ð,;ž,r J¹(™u+7AEO¢!}o±Ÿ¼•¬¦E`>¬W‰ÌÛ·J{7°74ñ"º!†‚ܬenoU'x1N1ìg $ä€÷y?*Þö™¥¨éÿ/Ì#C¶TE†1ðYÔ‹ë­.¡IòÜäÆíå"’ªåé©L)š2Á_ÂxL ’äAVÔÞºÚÎ<Ýý)i oÒŽBUmH†%É™Äì§ek•}[Š?¼ï*“…¦¯Nz弬!ù-[Í)à Ù‰ðw‰—,›(Œïë0s½ ¨ÂŒÎZnAˆ#A¬8“ÒþR]â"é“ÉÔÙṵ́!ï¼â$,Õ^—àáJ´xWéÈ%™ÔúšNÀT¼ÏeÒÍ•¡y‰fÞIêYJ[ÛˈêÖfМsáö³RÎJlq4740@´å/Ö˜”)dµƒ¨¶ð¶+<Ž3,MÒmŲ >Û¼ø‚lú‘à¥pevÎìx¤‡DðF6;É1ÒB›$©`†LNGÖ÷>cÖîÍ„r0µ‹Ä³8Ê:¤|0ÒV‚ij·Ú©Ø Y¼3’¯Ü5ص‡¡ (µ6}TA,KàZš©„v¹‡KþX˱ÄHÒP[êt7_ÑìXP$¹SÇ"^ÞkŒ4Kº˜÷S~dº™JfãÏG²ËÅò±kÎXH‘<Ôs…ˆ]•Wð¤ù×YRj©Õ÷£Gg§ªc"¸4]S=XíYþÐÎNÉ~>ì{î–Vß;ü Œºz–\ÕÛ² Eû±‹dìê=¯()àk•§í»1$÷ãÂwcJ¶æ!fœRÎäÓºëc.UÖ»½/¿P×ë E~b^ÚwƒMÞ±cEò&dÔ1òšhcΦ‹X•ò¬1˹¶äÁZht6äïK}ŸmM: ]Ìô.ê¬èè;Å}Hi“¤·]ºó+3Ñ`?±yÅC3ÑlúäÄ 2Ð~–rpzs¸‡j—f‘e{3îÀKèÑ=ÓÊ "¬;íŒÊÍ®©YÔ4™9·š•?Ö¥ _ýñ¯Ò_Ì#‹yÛ%{I­û”¼M&§}ûÉNÿ·öÝ#YÓœ`ûô×ÈINkVr 꺘Ït­Øú5¡·]dËÖmS3&ì©ðëSb,Q×¾zËð ™Î—8UѶ±¾ "o«lÅdi©R¿Úݹ³JpQG3|ö9¡Ö›+oý9§„æû‚È›—§.ÿª‹¹Ô;ã}ÑÑÿúN>¦ŠUãFJ"¿ˆFÛr—2À’Á•‚/0 5 Ü7½:6Ô%0G¯Íj:Äîr¹W@JËoÁy»•¸y4VY%¥ÔE‰('m”öj“<¸Œ+Ê„2±i‘tÞ*7:Ù8Ç( ËSÆ¢pÝ)õ/+Dz=Ç¿¡'k€¦j–{]SNûêœRRËM±[P UµÛ€¯N{–-Î sLh>s)+CXˆf]ð9×–.r’’¡B˜C!êoÖ>@ñ‰wf£ŠV³È“c á{:ömú˜e`­ ·ØÔ8 –ö…Tãš úV­{=õ Õ¥w¾”%|ïMϽ‡Èug‡%~6ãgëÙY=ès`¢]˜MÇ¢’#6õS§gQ'IŠŽ%vB{u콯ê'ó8ÖòN?Ûµ*M‰QˆD⊙‚›¸ô 'Úíui‚ƒ…·»ŽÂv4 ®øŽ*ŽÉ÷h" þmÉNÔ]á}5½µŒæEÏ5–S®K w:dÛïXRñ0³t™5\t™vÂ/¾t¡Ö v‘ªf&dÑi"›lhGF’ õAêÐÔ¦!1¦Tg?ʆIºV„°·¬ttbj“¾ub$pè1TüK—雪>—©äbC7¶{ÜûÐNh±QBFÒºê0‘±^ê¡™‘åÝÎŒÄò£Ku1PBÜ6)ŽÒ}i›´µÄ/ázh€\ìôÕ°qçãÅ5r!ùY¦â«±‚™OÙ–\˶©rB ñHå…Ž´16‰hù'—õŠÜjl_œãGº—X Ë­—´.*u/.é/­èó4¸(¹wÛJǺSúÊÀžE>î“ >ˆÊÿÀ&ÆK8ï|®„UÚŒû=Œ1“_‡÷žíUZnN÷JáÄ P”>‚«/ÏÒ'ÚåÏœ°–cÈ4ë…QÑ6ˆè%þªZV?Šª:…ö}ôL^ú:‘ø¡Wù3ų~Ämòm¡Úù›[íù‡\¸ùÐ.É™Ö>}ôïðÿÿU›ç!endstream endobj 548 0 obj 7187 endobj 552 0 obj <> stream xœÍ\YsGÞgÙ?bÂO3LÓutw•ûà6ÀÆH¶#Öð’@¬% èïß̺2«;{$Àà ‡Q«º»Ž<¿X­ÛÆ9ß¹gÈû«u—Öwù²oû´ça4Í«û~ùãJ5Þ;ëíý;PÆñ#ÃtMëàÔ{pR ‡ó«Ÿ\§;kÓâ ||à4®ÖÁq7ðìóH×/Ïqí¶i—‡«µöºé`íW«Î6C¯Ýò1<}œixIÛ?\Y¸RZ#Q­­úå舎÷<¿~Ž 8\my—@µ¡·°¼í]§—oðþ€d]>™]÷e[Ö.h}<Å)ßÎZ;8È€¯êž†=°ùÒ1áHËqj »ˆ‡ÐÆ.÷ËUÙíSÜ"žÀãD-L£pçå>[ýYÜb ruÒàÜ` òîð §câšÏà0Hhz¹¬òjeàÊÜìÚ( 쉇Š¿¶…;|N”íû¦µ*K;|™÷ ¸Ö3¨žíã÷‰²j—/ã‘Íà{ÎvØ%Ó¶ÉÜ*íº:ÅÙ}g—oÜ­bǪHü3ŸË"†7ó›ñä,P†ŽñÌ=lËeî8£ÃTg¸ódÙj‰ƒrœ’lã—üé¸`ЧL̵2pÞVGšfh —Q™\Z©¡(„¸•ÁàøpÜa¯ÕHFŒî€MABóhbSßZ¦q¯Òb=XŸÂPÜcðÜ´>è½ø'{Ï´ðékQwŒ¸¹¨ISÅ R ëöR&[¡âu½7ÕrɼJ *ÔyéXj3Øà—§ÂŠ*…Û/wHŠdÁ `”‚Î8¼~çƒXÜ s¥íY¯•pj$ cÍÔRãýëZjÛ¢Ç2×v¤(èHg×GÇD=Y738Ø•âîºpP¦½4ÉãZ=qάŠíæä» ò ¾s«<»¶AìÀLCÔ Å@ÈXˆp;ÇÌ÷?„ÃÀ¦g'ÚÐCºwå!Û'9h#as¡+cZ-2Šs ìÑj¼¨õr_Ò¼,ôh=´ï”Y’ÀÊÔ>ã5Á£"5ÇtZ悼 °Æìÿ!÷õ—d²I7Šñ©œKYå—A³Zð "F“mf}DÅ¿üx¢>`9rd—Q “q¢»6ÜoÚPÎÌð8«9’}ÀbïîÎÞ?_þsÁ8 ÷#"%í7aû°‰‡g5¤$ÝFó2ƒõ€M«ºì¸¤2Pm*«  ZÌQWзÙT“Î .¨‰‰Ö¡Ç79Þ+ø;Àùóx.{"o%«ö¶,PÁÄü>*„õÁ À í÷d±ˆQC?(™™Jc+YùèhoàmÕ¾'‚€]¦Ïj©Õ¶ oÌüŽü* Q·‰MoÕÐâÊ•5”¬Ò§ö²<ú ¢5d°€(±Oç@šGRyXtʱ*fe²€¸üÚT9Äií„û@r®‰=ÖGëÊì[ 䈅ýz_‹ jѦV˜çôŽàÔNðàHí i&<Õ24F\Ö»xøpÕñÿ—Á/¿Yå]í‘°Åo8`Î<¨”d¼WéÙp™ 4$¿–YSb‚Ü¿µ·óóÎË…1MÒ!@·§ rëk-þÜ?ÙùæÎÎÍ;÷g—‡;7[¨›·ñŸoî ?î|·øÇέ;‹ŸçS/u"§^ŒƒØfÑ ¾ñ}̾|g±µ%¿áÀ޳ãß^ižaÔ˜= Hþ}üÓ@”Ö¨^UçQÀÜ/œl€Uø¦å`¢(m…RNIo’ªÛq’…y82W qt>l¹†äË·ÉqRäì™§r¬“«®JòHÜñ4c7KrýZq~–ÛÊyd·ýê?"·B:\$˜‰nß¹«E”/“A{kg£†»Opm[Yv³ µ©ÓmˆQç]n81X~¼2ÁGŒã™)ŠÅÑ'Bä_§bxMöMªû˜´ŠQì[¥Á‚È ý(ˆJ› fBšEqµeÉÀ)¢g²I</šý,ÑË dþd°aX°È#çôÌŠ¤¼CÄ1ÕgPG&zCëÅ\p¯=F,¼(´æÁ6Ù„*z )/1UB+Z~F@-­ç9`±Z6Ç}¼MÇ™<"بR¾VÔvƶ.”Å®1¡ÎsÊÓ:¥öLµ‘Â;WæóŸ±4Yß#™Êëßc¯Ó0ôÃŒóßÅ·bWÙKQ~×VǺweWÃË[ÀR怄¦µê’èÞ–ìúëa:¶nt¢€'r34P‘0-n]¨4̧ÅÛ`Ä?ކ>AÏG©}B¨%] Ú6 ß~\=hcý=´þsY"l&n®>ÈÎHÅÐ Zÿ6 BTô,=ÉÕ‡,RÏñ,ãz{„Y­mT¥ÈÌGi…Ïi”Ëw¤Z_••çSiÍÔUŠÎzDt\º¡ª¶!¼CTbÅÞwk§¥«.oU7dZŸ,Sþœe™íânZÜ:›™¤câæ m€Tf¦'‚õŠ]˲V25ê „ˆ¦¥DÇAl’áÔÜ{ æ¼Êæ¶Fã£J"f¥¨š ÚèÇ?ï„n‰hOÖ˜STz("›i”(“߬ߦ§»¹+Oç²Vð'[üMÝ¥uØAëͨãy!V‹}"br&ßx'6†K’ÂDr­ƒmÉnd Wë6†{ÄŽ¾œ³YRRÊ2äºï´ ìöFÉÝ~bý4§“@s?Õb—Vÿñæ„0 > ·Snä/ôuáhÃ;&8CÔ麬+7p *¢*ŠKCç‚ê©-9Lfì‚ØN"#‰ vRˆ)¤Xé…˜õ-ëÿû‚ðÞÓf?¤¿^i쬆qÜL-Nì(12Ön‡ÀW¶[ŽwùЂ¥Æ0&سI,·i².†ÙÞÚÞ„%ÆMláiWT?€“}|¹:qKU˜Q8JIQÛ]땦·Û¥žOY¸_p!pª¯?ž¢m‡WbÓcöØÏ+)¡È±þÆðÆØ‰·¿¾üçŠy¸%…Jþ¥[ëöÝ&mXG\vˆ”¯kÒçéÈuäAâ> ž y•šå8xžZªª––­=ÃNû\`'(%)èk&«ÒߦÔ~â LL`oÄÜÍúÐÆ…ÍI¤ß§èõ ø®M+K=wbF⢰+DŠlömêRçuÇê‚ô:_€úoýúÃ:Žì³Ï«œ{£2ì²±â}Õœ£fû ‚g­¢Á”ÄÆm»‰‚ ›2¼ÎÓµr‚·8m-(ƒ)ºýÊ…ýfÝù2îŵƒ$ ó_|$ 1ü'5#JUÀFƒ}¾< PÍÒ¤à_·ü²ûûÛP`'’¬¶!b¤–1$œù;7‘²óV)¼ùï3Bm{üVîd:'e‚I‹%¤–Ë].å’„L ‘}ÙñQÓµÉMûðGé*P”šKýYCU.rè¦ôj0[@GafWn¢am‹vgK2Uê«n´)©P„?¼¦ÞÕç»SÁ‰7ÓÜÊÒüÌ/ò¯².k¥’­\é „‡6b ŸëD9ë!Å`Óæ;t­b? «è&o ¨Rý¢Ê,”Ö¨M-Riž±ùUl‹Ös&_ê´™º²\7|§2Œ¿}9NšƒŸÓNòŒ‚uµ^nØ—ÕeM¬7¢`~É+Ô7ˆâ%õ5DåØm‡ÛúbɇC}2@öÐjŒZ¾‚ጄ ²ª~óø;ö”.ïá?·à º ¸2€,ø3YÑG‡5î¢×/¿‚ÇÛ¼,÷§ûoËà£<ñ°ü¹ Þ¥'o•Á_¥Aöä´y¬jgbÀíòè.=úmüšï–Á[4ø(Š>|h<~×¼6ø‰ ¸Ññ·5W—ÆÒ ÈRšÆŠ¡™²F²¡Â˜¡Û-¤Ù‚¼ÆÇƒv?ÇP C|ˆX¥¢ùŒ>& ÄÒà—°f‹8S-(÷ÿC÷ï”ÁûƒºÖ=(÷ŸÓý}i%|IÅ$±ò[ºÿS¼Gƒ÷ËàIhv%™âã‚»Bf~¢Á{Ò9Óšh_Øû»Y·bà•FÏ’ø‡„íÁ¸”(önEÒ<+m A8?mC¶EAx“(è#BâvF¥úä: >IÖ ¯vXöŠŸsùHWÒ;øõEòºep“jÙàQõzÞçSI<ÎÊà9 ^xKâs±}£gd§.ùN9Ò¦*©È'yJ o9o1 `Â4eæH‚qº%NÆ.!î "Ñ©ÆT_ Ç6ËÕ9™‹b)޳Ì$óPîœdç'9Md*-þLVFoƯ¦ >«3“U¹ßÒý¶ Þ Á¹'ƒ ‚™žÎ±;õÂÄ{/éÞ¥dÏø!2á&¢+Šæ9™CUío6IÑ‹Š¬ùòÏh1ºŽJ‡Õ¢ÕR(æá3a¦’±ÃJšjCVª è´ƒë ö49Ñp#ëW,„”ÑøË!‰{[îÒãÑ)ùy‘®¯¤Ác"ö,ã'ƇQp#1_äõ)—à.~Ó;]”ã´6fi“ß—ûwè>)ì.¡&šé„žd›dzT ãl±±µ-]p’Áé¨QÐV„‚5Oo—Gʨ¤8ÅðaNŽÝôOƤfûÕÖ§ä?”ØÇIÐáBâsl_‘8EœþRÚÓÍ”èÐì|-y¸çÒyèhtÿœ*o 5ŸTW-f Pøþ(Ÿ¤š þìCµ–ˆÿ¢º?u‚tʧÒ`Y&Yÿ?Òä\~¦çTšK³¬Ê ¨TØ;NÀ·a ŸRVpYѽÑ5•¦Šø†Tæ¯ ù`zßd›vþôúy‰÷¶äls1ÉÃÿV‘ÈÿÈô^øË=Ÿ˜é÷'L?—¨Dô¼”$ဂ†'ë«lHTNØ/Fr_ÕÀ—OLšÛih+hÏÃ_»¼ûwìêÁ®Ï–Ðù6ú^Ó1\ÞÍ^÷*L1›ÅI÷ÿŒzö8N:ÚcØS#¯ÑûÇâûçc%ý­^žòyù—…vS7Òà#²¼ ÛS‡i¾ÈW¶“ÊU‘ÙëbµùÝR@)‹˜âõ´|¸ÊR«ëäå XV6!¾ø]• c´!…^Þ̲ìf„¸)—¯uÞùÈ„·#endstream endobj 553 0 obj 5097 endobj 557 0 obj <> stream xœí]és¹ÏggÿˆWù’÷(Þ0ºF3›J¥8¼‹ØeÁlª6›"Û€m(øëÓ­«[#OGÙÊcÐèèVÿºÕꑚ׳¶³ÿ ¾8X»õX(5Û9^kg?ÂÿwÖ^¯ Weþxq0»³éªõPÔ í f›/×|bfå¬ëu#äló`í_s³0óvaþ½ùwlÒ·YÛ5²‡V›[Póîb©k‡AÌï/D3 ½æ·rþh±ÖÆÊù&ÕY÷¥J÷óÇPª [7X³XZÛ7R˜ù…n”’]ïºy²Xh`E?ßÀ¶=üO¹QôÙuœ€ød;ª¢µ|ðЗ ïëg¨ e#Õ›)%æ?-ÝØá:qt·PɈ^ˆB`¤U™@K/…ÆÐM£Í ”lD+¤ª‘RÙO²i[#EÅ5Ï ¤K+¼L”P\&KaT£ºÙ&ÔŠað²9€žçïñç%þìá@m+Ä|ÿº?Möv~‚?ÿŸ©òþÕuõ Þ¤¶ÇáGwjN ¾É_€Z`¾m»ùëTø eÛ´À§H…íb)4}çH) ÿ Úþ¢çKìXëô”ª>O…‡Tx’ ÷¨ðC*¤6'ôz³ ¡OÝ[,v³çßoÓû·µÂ}¢þ¯Dýïsªñ˜úG­z6JY©¾iuT´eFK|<¢FŒÁczdÔü¾èx Ⱦ@aĹ4BÇHÊR*Ý €/@»éZéIÂÙCÙ°4qNÖ §©0§Ê¯˜„vó÷€¨'éÝSzw'nfó oSá]^3K…÷¨p£ÒÑ}z½ž ×:’0í`3[°mSÀ­H6$ƒn”÷óóêŽÑÛÁ_,jr'Ôïnµ‡­ôèð Zà£÷x0CÿYìÍýÔä ÑùBÖ1©œLU› í¡¬ 0„óƒj&ZJRïŸ0õs¦º¡ðQ ’뵎že„Ð „ ïjfˆ‰w7°×[¦mU‰Uñ±[@e~è ŽVÍ £ÁÙÉ-G&} .€®XƒÂþnyE&Z_Ô ö~†ÉÈà_™”]ó(fQ±¦a¦#ŸgÑÑœThðˆr'j)uÛ€q„YéTT ^ ΛܪèÕÀÓ6.ïÈ}cC¤ž¨Mêh`…5¾ µvŠÓu¶Ónrw&ͼéóÆ(X]½-§-´W%m¡h°„„WÃüèùÁH‚½~Ê0'qöl&+¼ÚxwÏ©N;Aí2† åûkQ'p„Þî87:þí&úŸèP«ùwäBŸ¤ŽQŠÆØN"/ë›k¿¬½žKݹ ÒÏ´•(è™éÁàê·w6Önm<œ¼9Ý^»õÏ™X»uî<º lÜ›ýam}cöËe7Ú"}8®)nò"òÇ&%ñŒ28)¦b’Ó‚]ÓŸ€ÓÚ¦ÏùØK©b-0v"pãÌ«VûAóª“= Ê X ¸4Æùšº•±n±Œ¥aÎ l²ŽÂPLwptFLxìmÇ,V¢Qcóƒ~`[wÓfi©qqP“ÆÇÓ+¯a0¢&¡+Þ5šŽ­‰÷âÚ O©÷ÿ‚®ô0Õ­d­·°wØ~Á^,¼7²cïËG ôÓ…Vh«4ÀÂf<a¡rÛFÐ+ߥ3C]¾ð«0Œj: K¢2¬@þ=Òfa–»I[§9)ÒQ.öWdaj*ÆHõ„q ÍGÑì5$½Ý% €.˜ç¦3 eÑ`‘!tšç&÷<&UCj¶àû½‹.Ÿ÷;CÒ*,%«ƒ ¦§\k€á®Õnn  DOU|g@!8€ŒDbœ\~¨Ý‘g—à ŠX(d¦K„íôöY ?úNR‹,ªÞn¥·.ÆÇP©ÄZ³šÕ€‹;ª¹b¸¦÷[5ôd’aóýƨ§Š3ߨÊ9vD ¢iÏ^C }8˜Ãð¹é¹Éƒ° ˜©v±û<®Çû!5{Fä^êãH(dñḬ̈E³8ëhÏ€õu1ý²Ö5Yþç™[äÏé …oyai÷K=èíçÚ -àUvPÃTõcÉk+ƒ!)­r?N@«ÚÜ ðÞ’^vç™Ò«ñ^bí‹Ø—bɶjÒžúZ Iš_7À®Æû×0؆|\ ¶•µH3ê½IõbÛrê˜C4µ2ÉÖÖÂ`}-<34Sçñx“ÖÊÉNÛÑ{œœ7“>¸|D :]‰å¹(0Üîó%gEÆÛ5Aåh©©lÆÄÞ1ZžÜÈàöÕ™£Z÷ç=¹ááóøhÛE||ܰ7i?å˜ÏP8oñ,õGº„=aœ…¥ý„¥O^¨nýŽkðxϧ¯dñp=þø¯qÔ÷Ìΰ“«D,Áãä¿›„{·»>TäñàìÅbbÄŠO3ówH•vFËÑ›l­.wåÏyK¦™q«~ÂåOúý—ÓÏVG$¥lƒÄ<«ÒÉV—,ªÒq©\‰0æÇÔÏÒl“`)&ñº ‚çá°Í‚®[+†áøÈ~1™Ne)+ñ÷J3‡BçFïäX£·[©ÊשÚMï™Ô2®Ç¸pkÐÙÞ¨qLÓ!° UkCðà[…V5V^Øœ§7GQˆiþU8ÅÕÄN—b>AÏ {°>Þqo¨¬Éhòpè¥CÐojâË—ÒâõVm¸„E¤N«‡·‰Ïü쮟۩s}o2K@3å@c`›Ó¦³»­Ü@¡$À,j:;÷#Õ½C£cÀÊöãïïÓ¤Ï1i¶Ã9Pj!WÝ ùû¨+Å/u€òl‹÷ù\œ0êê–§ €ç T)'>_Ø«aœryÊÜç3?ãí§½Ö§qŸ§Ž—ö²jdoÖ¼ÁÏê‰×“rËó„#sžä¬r ûoÛa Ù áÏW}GR³W5A1Ý{_SØ+Mm÷²C>îÅWÐÓL.µlVÜÎãêcáÃf;áâŒ0Ó®sÜïeÔT–®ŠëœÎ^jáŽå.¥mDº u#³³(Ì·³WµFÔý‹Ú´ð1Ë0r>AŒºÑö+m쿈¯³,ä|C+5 Ò§‹oÇj›±oÇ.xlà:>| ˜ßŽ \ÙÅ¿1AO-*öõ¸Ž¿_Ú·ÍâEÄÈ}QkT/îÃJyáNáúpãN³Íþ”ߺ+X˜” zNߟœ]Â3ÞYa§“ù5­ƒì”î²ã÷GüÌm:rŒ³¬­;]K7dŽòãÐa”ÞòzþÈ4žòÅ#ØTŽ î´»¶V½wCÙ‰ë/ßQaõ 4z Š®œ¶W¦/ÚNÞ,€¦»v„D!ÆßD˜cuMom&òp¥€®£ó爛ãm&<Ô|µ£Ðßã&I@×vþ#ÞÄÞÿ†ïÍ.KLAy5¦/¼É^bŠ©û¾éVyá 3\ôj´¿ð&€ÿ›ü47XÁÁUÊ—Ïf8lâ2°Ai;"›¢›ds<—ˆ½v…\ŠÖ}UÁ}àR:.ÁøéF¶}L ÒZº‹÷gÙýÚõó¥&Æ(­ÕóºheÆü´Ê¥`¹¿<— K[òÄÖu¸a|TdDqì¯9KP7éq’}©Äà§yÅìÃ͘{Ø»;|鲑µîºÉ#JWó”zœ6o>÷Ã4K½0R¶z–ŽÖX¢ÍbÙãeyÞ°Ê(~ÿ¥¸ô•]²]{õSJõó â¦æÎžQ•åÄÍç….#žo¬ ,žï¡tûiŸ=Á°ØEÇŒï)nf~ñ¶^g‘dGÙ±%ÒÆÍvvŒn/%À¶8{ÖCòC–P H}…rfØ!ôZ¨‹â2˜s+öènª[ü•±ñšæèZ:JŒnó–‹>vÊ}ÖÉ(qA <7ì ]ËÞÇ($^Wí‹MN•6IO¢SRÞ+oNÇë\Ú߀ίsA/¸¤ä&ýU¦þâYj*r\pdÈ%iBÛp–ÿ["6üûMZ ŠË–#Ÿ]qØ9ºýÆ\>÷ÆŒn]3`¼Cùpkáâ8Á+Äs…Wˆï1È«šî>Ž3ìÉíGŽXé ã(4×ÌÎÌn´w4K¶ØÙì)çГ"0D‘˜aH§1»_øKÜ|Èr@ð ¶ÃÏ I©Þþ`~¥p—kÓRö\pàªÖ`ó÷߆§C£ b.·ø|‚g,ãiÊ09@¢íøªÎê2÷ò×,ïØtnˆAöÎùjåŠsC .™Œ“r*Ü[TÜbfCîç©Ó˜w2í1ëÖû^«fÇ|a‰æìàJý§Òk¶"怠e…C¡Œ‹/%–a&†{d^øm—ù£lº˜ÃzAá þ/ ú7«óT;çyÃ8xF— ¿3ýD¢š+_¶Û&­œ e`#8;2 ‰_µp31½J;ñ“ëEnù4kVtŸ†5týÔP•ÑÝÄZÏDòA¢¨`íÔnJòóAÿlEU1Á’Ë+T™Íˆyçf3 8ŸB8[ûŽê–\tgD7é)1÷ ƒg õójˆä’\,2ÂìÖˆt‡[É Ý>-›e:)ÌfÂÝ£©ôR°Øb¨ñJŽÐ•Ù*f¿kǬEr˜³¬ ÞÝŠÌpNˆ‘€¹Ee̓]gmFiÜíôT–_Ãw‰½$Û{Ä,ÚLíÒà•ÝDH-•vB> stream xœí\[oÝF~7ú#ü©ÈQ5WìC»Ûm»èm/°Ø6(NìøØ>NŽÝÔýõKÎitl§ivQ¤Ay4šáÉ”ÚWû}'ö{üÿ>¼Øûä©Pjÿd»×ï ÿžì½Ú~Ê~üëðbÿóœæp¨ûQìï…Äþ ÷­Óû{?6¦5M×ÊnÕXÿËjpc'{×|Ý®DçÆÞˆæÛVuÖjkšÏZeº¾‡«/al£vÍíJiÙi£š¿Âe78Ñ«æ{¼”R {ü\Sk3Èæi»ê;çFã\! ?kW.õhÒ¥ím”Å0וÖ6ßµ¢G§ÇçÿðšqüȰ\×;8õÁQ<©h Î\Å;+Õã Æ0á»V6›v%õkªf‹;N7W°£CñTó²Õp!¤lóÕYÒß¶8‡TÐþJ³®AÎY)hþ&\Â|;ââ4¾E)T‡ÚxÝ®t§”%Ûúj5ª½!åç«¡`¶Ó¶yÑÊ¡3Lt‹I4R:î`¥ëîøeGÜ ôؼi%žÌ„“»¬¤Q[00Œ£hNÉ’A ©´?/Ša*bâ}\ù(Xç­ JÑéÎÓ=´‚YJI•¬‚cxŠ‹Í-‡1àŠDªîµ0:ÃB÷Q2ã¼dYž T•µƒ Ÿ´é¸½ð–4Ú+æE‘‘–n¦ |0Zr®Üôæ². wö@3e¢’ Øê”ÖHˆ¢SJ¡›¿£Óƒ’w+%šƒ`3}F ° Áå„λ*t% ¶—A¯Q™¶z¿!5GØR³Â.Ã]q…à¹EõXXÒ0OaÂÃ_ãщ~¨CÝ;Àà2®¢—ýF¹¾CtÒý3ævé*o¢OßçˆÚòþª J£4Àäd%!< ¯˜àóQÔl„ñ(Fl=íh´Ý`£%÷z‚O{•³´phá9÷€î/'墑0@„·«„ù³ùQ¢zïªUÄ–‰„¦ 3HnU,ȯ|øyA£ÓU7 “ öÙÆ©nÌÞ‚³Ù‚,wêCb¨Ê“Â]Tmj~„ó Œ³T¦ëe¸ÇƒçlTrrUלYÙJØ"ßf½§?Ñ*!Û…– Ï» ´– uŒÇ•e”D=B&Ä´ŒæY£ä1à°b0† `»Z9õ{saÚâWFØÈýòç!•9¥‰iJ¢ë¨§Ù?øfïàã¹N€-?Ò$BÌkÓªDàü2Sø£ÏŸàù€=ƒ2¥_šëå~œ[¡¼—SN˜r?Ò¸ ±ôÒÌ@Ÿz¡UóK ” 4äêù1vùœqêŒÞÆ` ûu Ä©þÔ±vð“+̺|s8Oø5D‘¡“¹v9ª1éHJþZ ËÞagÑýý$8D/fq¿ üiš 4¼@"i ¾³á¤g°ƒß½Ö¼±C§wЕ=\€B4?çø¥ c‡øc“n„ÉXÅye{ øUŸ<Ô‘`ã<ýŒ¯óàvaf¼:§Û°‡˜‚>®-y™ið*^Óàë<ø4†zKÓàyDGð)(UIÆ Í¼©‰sÌôéÉ¡0Ô ¨$Ækzä1îEµ3 0Ὡ݈‚¤Ñm1/wëÙhuòÎý©¥á'ù2°´ 6&­K{Gà;Ê;äjóæ0d’뜭—’s|œÕ ²Ý=sbî`†?$=ú$¶úJ¹+à)A ’cBÙJ vãhß(g ,Oed?o1žKÁ Lù‡B"¤ÏA± ¤N¬ïHTÕšJäÒ–ÙÊ“¯zŒVÍ¢1ÿ¯6~Ž"#²‚¿me†ÑZ?Q±Áï'òM!Kº.—P,3³ñì6ú!\ÈJ“Kê[ˆX´xÁɘ\1.½eìÐGN²¯|·½ë˜îP+%{ŒaAœ -ç‘Ir4ò̶Ëé¯}ð½´od¯‹¬z‹7´ç¥÷x}£ÝXÌoµ_¸,6Žs=h_ Ö©è²Ïj!Çq‹p1}ïÓn mϲ7UšYø‰?jÆ buƒb†8L3 ÑSÁdÇ>ð½—3↚õ?¡¨š’¨ðfk¥GÑ ž±³.çzƒ âÚEZ‡’#9/;àU©¯EðOÐúG¾¤œ•»‘BmÚ¢ä]þ,†³|;`ít©z~9«ÔÓ7Oó>dìsÜç-<Æ ½…ÏtÖðlÀÄcþ´i~$FÛó™Ë’ô°ÐÈ R˜ÏM…ô¢«H„¿²LVOÒˆ¤/ìîlø{!J¦‰ÖÇ6ÑûO¯XO5SHÖÁ¿-‰Tਙ˜RÓ3PÊ®¸¼û‹Âçêt»—8a¼êîý áG,ÛÃáê¢Æ(Yß’¶,;Çqð9 >Jƒh Ýw=j|qIäOÞØž%dîn ®Àî뛫^ ? w€´5þÕÕ—ùþèþ×yð|žfbVzaênÿtahÍ·œÆ¨¯ü8‹ð•0u\}1vSà—ôŸ±¤¨¾dyx$‰5´–|Ïé =ô"y탃zM¾Æ?¸CUKïÞêe©õÿ¿lÇb{²|UyzZÍ#¢nÓW¥?Âdo¹3“ŸW–*O3S¤em6—ý]ZygF?fs|’ æÀêiæ7µ€ð}ß×\‰ÌK9ï.§ª†ï×ܨӞ!`漆ÚéºØ‰‚zJdŠcò“»]W=ú„ð»QƒÀ€p™èGÈÊ, \æD›:Ȥ¦„ë¹Bó)¯ššs×"5¢ïúÖ‚ž9*0B4|¨ äÝ20­¯+ôž¦õ< ¤Á;fÞƒ§¼·šêYY$+KVL÷ÿ.Ne¦sÝȵÃŒmBcŠFÊ<†¼å§M??˜¦cï¨;‚„þ$ÞaxúŽƒÄ“ð%Ü«<ð%RÛËûØ"eA6Zvr8²$8„Óï«HeÏi¾½-è<ªŒÂòyMéÕ¯ª_ŸK\ÕP³ø DDÅÑîýÖd7¼­e„I÷”²Pò˜Ïùó)`?¨"`ù,]ÞêSi\Ü;iΆ™z2Ë¥Áv¹eìC¥› «=¦ß«¥aKú¼¨©®J½¶d®›¶â&“IJ«’$}3ߢ†oõƒŒC>sÉ"¥ÌqT›¹$g¥Š•…»f î ³±iµNö c›89EÑTáR:ž;áýÊKÙ«ô¿>øŸ0ÇMTÈ\»Kÿ¥ÂÜÕºÝÏ\~ôÅÁÞ?áÏ:2´endstream endobj 563 0 obj 3551 endobj 567 0 obj <> stream xœí\Ys]GæYåâ7Ü7îIYÇgöªxˆCSlID•¤@–e)D[b+Žùõt÷l=sæH2˜¥(H!ß;ûôúuÏÌýf·Ìb·àéߓ˃'Ÿ ¥vg¯–ÝÏáÿgßj²Kÿœ\îžQ3EsX‚ؽ<ˆˆ“;ëõ,äîèòàó½™Ì^NæË£_b¿4]œ¥‡^G/ åGÓ¡š Aì1‰9¯ÃþÃIî7ŠYkãäþ¨¶ù8–*í÷ŸB©‚ai²y:tÎÏR˜ýÓIÏJIëi˜Ï¦CœðûgØ×Ãÿͪ`Lkù~6á'g]jÄâøäi, ë·Ð@ÊYª»)%ö¿™ÊºqÀën`Ý 42ÂK˜Ql‚kU&­ÅK¡± 3k ƒ’³X„¤©f)%,û÷“œ—ÅH‘f¡NÝülÒ´téD䉊óäP(`ÊîPk`Í""k`4µ å2/@Ø×øýÿœB¡À,µÿ ¿_áŸüs‹‹Y!°5µñÇH /rï%Àš cóWy^ã ²Xš<BµD9/Jái-<,…'µðº^–O7µúÛÑ@¯øârái)|1je¤ÌËRx=ó²súäÂÇH¤rl›ç£9¯•@.^gÚ‰ý›ZÚÒ ?jåñc&þó eA3/^d}¬ûÇÊÃ\ 2|lt[˜~‚ZâFAø6qZãúŠd W꺰Ñ泬Õyn›Í¯ùÙŠ!î(öòÁ"ÖD,ÊÁ¢¢Êõ ;uªün™PehÝç1Ãc1kùºªÂ«Ñ’‡|Q?¾Í[6ä7U¾â„&qÐj.ÆùU' TG¢`›¼»Q@IÏmH^P'ögœ<ÙpTÞ^Wšü‹¥¤òa¨¶g#µœ[:iX(ZÑCéf!Bˆ”²¸Í/&-òÏ(Ðiím]ÒŠý¼J&¹ Eµ© —¡˜±%Ö|^‹ºò¥.£ê ï³èq-”¬%ʶî¾y$5tZÜ7Í—¥!%xAbrÇ_ŽÔñbƒ£>¤²˜È×-·ÁaÎAvÌ>*jñU2ÑnûÈ©ï ªÕ8.’ð:u‰¦ÁcA¤½Ež,ü¤‰îmv3²+ß,ÔEÖX=¶`'#ûXÉ̬ÎUõrלÎÕëË—Ox§ì/Åeö9[½V‰»‰¯`å´B‡÷«ƒ£>o&í‹=V½iÄc…VΫî_rùà>Qåy3ÉA­èûß„ ¼#ÿ'šÕÆyKƒö¨!iÇr„ÄçèÍ"Ÿ¯3w£Þp¡S½Ÿ¨¨Õp%½Êæ<¢ ! /êH·œ[kÁf¹Ÿòkrµ¶Pƒž\ÿ¬Ö•ÂÏÄù¯ñŒîÿžñÍ3²L.þöÏùY±Ÿ—‰}Ùs¯5.Ú¿¨kß5zƒª(%Ùå®u‹©DÕt¦äÿñˆd­{,P®ìù~4û06¹©îňùokl2#.«CmÍÑÀ·¾ªm_•8#ÈA؉¶©:°avÜN9¨,Ú_¤-»ãah‚Nå0u¼éÄ‹í¿ºï¡KújDò^T!¥Ã”Þ =+m%¥^ŠM4zeƒó;N/º+ íe@; ÿ‚²èý‡8¦5‹" -a4©Ãþ£IÌBa s7rvÂQªJ9Q­Ô,œI b§X¿ÌʇýSU*aQàpÖEëÔT!¬ý¿Å$–±Jš{‹ØÙh~Ã{X’¬éó8•°¨‹ƒÊ$ºNÍʈý§°Sk…ñ@gÚ³¶Q›bŸ×Ph`¡&- {_ÕêS,´%l™1¿¥sÖ±MT‚k– Î¥¤Dù¶RVïtÒðIH‰¢%fc¼‹K ðÅ÷1·¨ƒ„µ\%ö´”ž‚ÐØ[‰r!1çG29W‡#“Áñ³6Ò²z6Z=Ðd©Æ‚D aï Dãíë ÇÐ=¼€þÄuÃü@+E‰ŠœÛd•ÄM9E ¤I4Àµ¬–.•æ#àŒµsïº]F8 ªÆ„\£Aë:)ƒbÅEî[û’zYë¬nG$Ó²À÷lXp€—8rÀL(n>7nywˆYÖ¸Þ`4_Ò*7ŒIV–zý,5Õš§AyRUQÄÀ”¤•ÞùÂ]!@XúºYGNbWQp‚Œ4¶JFcI[ï34$šÎQßçq(cD¦«·c¹ŸÑhjÐÊ%_j¡£Ndd…ç=m¡M˜E§`÷ˆ Ã~y\k³øëàZ!¸¨Ò΄IðHñÎh<ÎõÒ*íÔYÉÄí¶šÕ³wÈrnò÷ÐŒ2ñêö0³òj)Óž4Vð‘†,ª­íQ“=ÿ ¼ô`}mñ¥}GšÛwV+e V©0‚5fép—€i¸€! /J¿ÂWÃC[h5º"/¸×Epû‚+±r ¬wµ–%¦(ëIE<:Ìôi“ØWU®Óô˜ò…ðc¡¥H ›Ùqü~êœCg¹Ñ>ãÆpJ#¸\œWoÁœR½p"›æd´/²z픹Óög ¿©eèÑ´éÌ?¬e´&Q'(šYÚYƒ›ú•»î<Ðþ)[˜H;ðÛ:D;ÐïçüÎ9:¿KÍÚâkL3^íÐÕqS^©ëÝV‡À¬yÔÈEÜ%ÍÙ½©~ä¼V›GÒ+´L¼›:UZ3:–h?‚3ûÊ®å/êð§y¸;“³!:µÞ&Y/9h1šòž:êßþ/܈‚½°´X¹ÿk5ùU OÊ'ÐP-Í,øÈ ^©®&€ÉF»ÆeåJæ ~„CZ¤7}§lÊú`8@>dt5c ‰¾ÒK™¤—+7Ô©‘ (i`Âi.°»†l÷ÌÀ‘O1Ú1B†IMPõ$ºˆ­çÀê]Yñi€+,ˆ§kq4é6ýÐÜ‘d0¨j¡apYC5ùûÑBÓ¶õ^Za Tô!ѧõ2…D‹ÕO ÑqïZsBvø?[?§˜v`Öå¦z›õNw±¡#´cÍC›ëhX0Œ¾]±Sw<Ø\4 &[·Ü €än7-¼_ȇvªóݲ³É¯$M_T'Ñg“aËAfGüq¡™"B6Ö»¤ÐoôhÃÚ‘ £ËZâñÃг7 Ïswy£í´ñc¹?¼–&ß²+†ôÿVíÎ`FSÇÕ<÷*´Öò&n½ªÒ9ÌlæØBgƒÅéÄ<¨a\<£Ü:˜w;¬&Âò!‡ÉÚ¤22Ÿ.Ä$êêÊN ~Q²‹zט°F 5÷¥ZZÜŽ¦»ám­~TÕnë°-0ÝÕI¥mÜsXÄ{ŽΚ>ÝóN™”Ab'ÒµX7!@UM0šÿß±°,,EÆÒ·ÙãÛž69"V1îíöóay†±åg£ýóR’AOcÝÇGŸ|³ÎYzÌ÷;-%¥G¸)ìyryðôÙÁ“g¿Þ½þööôàÉvâàÉ/ðÏÓß}ÿ<ûéî?Û}ò®OQ pƒI`.ߢ0m¨gk¿¢ýÛ#é0œÕw/)u|:y7†³û?Mrs›FÀ’þÛij9ó°Ê„iA¹ã-,Àmª9Ö'â¨W;q"#¸Ø¢x%#'1fïÕòËØ1Ýû³à"€QŠÂÜ2éw]z$‰7>ŸÙLëœÆ¨ëG¾â®|jÔ-èîÈ×T“E×/õ†÷È(rIù ¦øn㔯xpÜ—ìÓU×´™ÎÛ¬ixöcš·µ'oœUŽ=eh3°9²N›1·ˆïA‡ƒi®Ç™ª‚ÛIlü"M¨,w™Ì¹±µvðA´­ûrÆøõM ÇÆ9;¼Z‚0"¿]gGÓI†Ã×2ÑK4 ;&'®Þëôû0`f–fiOêºìòÆÖ‡©eä\áN«uÀš]âÖn©x<Ì[f'Ùƒ–À"j&C­TÁä¶K Þ{žZ§}Dû¤xN(‰úúl ~1ä¢1óië-2»ÃÀíÇ‹z!ÞÀXgÊeÀÔ–þ§³P,€%i‡˜ìCÝôªÈ¾NÃK%‡I›f[´Î¥‘ïl›eX('™Ó¥!Þz€mΤkT%7Å,DÝîb- Ù†:ƒ$Ù£´Ã ”>´mô7‚¶™µaw¯ìU›å¾Ö*WÄA7&™EÞ(>'\·´¹‚Ç%kKôVz¬fùjÈ‚¯‹{”Ãã ۣ𧭶–þÒŸñ hO²Ye·‡Iž3T/|ÉI%xn‹]iâ¹-LdHcöë¸G™T„Óe² íՃѓ™ñ•î1ò±y+ÉN9ùðSê{’`˜á’t%•»»AgøiÆú´¢bºhMã½u0Ã[SÉ Ç#÷{ãú«VäÛ£)JZ~ƒYU„çCÜE÷jˆ½ªÆEaO[iMýÚ~çh÷zt!gë<,ÃvdºÀ$ÖðzB¹kJ“,B%·!: vým¯>3»Œ¥¤ ù–±Õ€Y<^@qU/x4z½ ûWˆ±7ο¸Qº®ðaåíØ9ó*ßüįEl¯8 ©˜=K$^¶°ã´û/[¼ÃñûU…û0ex±)óµ&™ê¸£MS=º Ä©wvD®sƒÒ–Êï‡Y¡ìp@ï4a…üÏódîßmàÖw=ó½Q…g|_µ‘×:êx€Á¡5…Ow\¶HñÚØv¾è¥ ‘ ƒÃË´ëÄnž„ߌXÙ£óN]*Œh ËÍ¢Ò†Ò£Ìmž³—ˆ#Ç.»6Á/[°Q“ð—~JöØœ5ÜÓH÷T×ïë¿ØÀt—µ¦tyha7f3“aeir6S(Þë=¦jÇè1¦³z#Ä”<Þ2jL!”òƒâw„³c¸ób%§k<Œ³¨ÐAl¾ï*bû%RÁKküÖbT/¥kœt×1DÐÃ\ñqRWŸ0°Î_§C z#Ñݴ݃Ëm#`Á‹w$ë+ ÀÒ[&ÒÉ_E>o\Ñ>kB­`·+Êò*œoýšÔåú‡k0ªzwÀ«Œ|ê‹Ðü+4aõü³¾‹ýó”šÖ-9.íèëŸKc*£G‡ˆ`Òëå'½º¯ÏùØ#ÉúؽŒ«/Æž7¯Ý¤Œçî+°z¾ZòŠöçuÌþƒR}Óö£²’̓qþ³2‰v£õ²WƒìÝçÛRÈÞÖ‡ŠåO(1 [[þ¦þ¼Þß2áðõ3ëú›ì½^e½¬…ìGx6©Aw¦ÆgóëÆö§Öoó%Ì,eŒè~ ûƒt±8¿ý YX÷Û¾­¥-#òÇÏkÛ/*0q¤ŽOþHï«endstream endobj 568 0 obj 4726 endobj 572 0 obj <> stream xœå\YoÇÎ3á±€²+ˆ£é»;D¶l+päÈ¢‘²áТL ¦H]ô‘_Ÿªê«z¦‡»$%:@ ˆ\ööôQõÕÙÕój5b5â¿ôûÉ‹½;_ ¥VÇoöÆÕgðÿxïÕž .«ôëÉ‹ÕÝìæ±ic«ƒöâbåäÊz=¹:x±÷xm6f=läàœSkGì;9úõ_6rýh³o­u0ë7ûjp^ ½¾õརOr¼³Ôýüÿš”Äh×w7zPJ‹ý<`ìƒ}¿ÚxëPvý/|" ãèÖXœ‚.bÁëFÑA®¿ØìËõ=œ\ZÁJ˜§¿‡j­´ÏtÂ{ðW¢®çdÓÆ £Ê%j©‰=•P¼ç¾nµ¯ÆÁ‰b÷'°€õ3üqˆ?^ÃT@«H{ ÿ~‹?~Àg¸Òqû¨õ üñ|‹?noöupCð®Œ(q‹ÞÒ¸åÁ8¸£ÁcãÛÚó¼4žÖÆç½žKã·åSY‚¡%ÄÆÝ×ñ´öü¥7åii<¬/øãóu<ïmÆ4"ÀŠÍþ¦ùž-¹Óz^?¦Ç´òëo6¥9£D¯àÌy;ö£X¡XXüà2*0•JyX›6‚èHÀ#HÂàJÙ8åF/ÔU*·>É]ÏAX­3È£€><‚Ôó&Á”ƒ äç”:Z)b -ÎGp@=ŽÒxä“`daÙH‡ðÉ䔄V¡ÓÔìiœÒÁ”Ö€BÏQ)˜ˆu(Ëì —z8 MA: Ô–Ã|‰ÀFpá’:‰Õ{·¯ÅFu¥U˜!ØQfqýl$ÇSؘÖBÒz”ŒÚé-| •„ä¬åkÒ ÀX\¦Œ¢"ÿb"®$hŸï‘ìƒ6Ò²áQ~…@A5 I7è(m~“ÕØÙF†åúç¨SÌñ» ˜OÓ“8 B)”8]ªøÅIÖÖÍ¢€™¸­‘3¹õMÔͨû›‰$ãyWí8.Ó<ÙÈ]žuT*Š˜ô?¨‚Ì™îT“ä΄}Y{2r£)÷bqy¯MÇqá$¯¨nºîpî*4h-MVSk”Ï~Å9LÛõ…¿NÛaDWua¸2 ðC·«®úÐ/,wˆ¨J C†Qb4»Q,º©Qe@ÐiEÖ‹Rîc‚ý²RùÈ3–g‘Ö#X¹ -¥ë{–ø°*QÔfÑ1P²ë„…–”EÜ_R4‹DrSöXXÒÅù|(J0Ö¦#±ˆˆºÈ*¶°¯KõŽ.4FGÉ÷3¶É¡@éƒô2Öq„MºOñ4—(Ö9ë5‘EQ·`$ŸŒ’ògD+*m UG7¥ê‡•‚Gå¡r©¶s!E3( NVŸn‘ ¼Sf 6+3r½9Ä›‹EvøCóa 6«ùN^ ËÎÙËNÇeÉ„ÇRÜ}ëõMeÓöd~¤ëÒwM"â OÑšh7eÃñԃ£(w ]>課(q¤(|å0‡Åod8ÆàqDïÞ´‡§3òƒËñï<ÊÑïS £ÜvM(‘B@@‚Ç6“ƒ¥t6•”‚ÖÒE[•ÂØÇÂÖH¢¸RÊŃðÃF(gç¯i_­ïF-¯Ø™éyïd‹™È Uä„©"!ËwtZž(v¾¯>í¨¥b¦lîNÔ'È+º ò=¿ª"²‡F&°Ó‡‘ÈÇqG˜ ýO§«ÏÏb|iÊ÷a+²¨a¢ xKnJç :a/H4éxˆ MÑñE`¸¥Á1°i”¸ÙV®†p=Žä§]á'Åø±´Zƒù<³LFfdzÕäµIZÅÿ΋ª dãƒ\ûñá&ž>[ÁënºªkóŽƒ5+e¬åèœÜ*³Ú)” >æ,i|…l Ú…yTÖ-âYŒÅ¬Ð5'¥øˆõF„¾lGŸG1yÈjK ÚÚQŒêfÌ_ÏY…ya˨ÝÛjš*¬'é4l¡wM£…jñK•CgxaEÞvœ•g­Ø¶"©ÐZ†®³“”Žvžìö„³OäѺ¬C#*qðEƒ[ÛðSƒùÔËu)ÚF/f—‚-XD,bÙMæ1)jb÷õ\=âŽË×€?Ê*óun'g‹ªâ.()t7bѱÏý ¶2ø1}…—Ú̓ÁE¡ýôHd–Þ ÕÓ)*½ësW3?‡õ<²9;êÚž Fe«Âr¨@:>Ìy–CÙÙŠrU—Љ‡Ÿ6Fƒ”9%9,V¹Uå§±—Â[PÔ³ºTÛM™RØ4+tÇê.ä˽ƒ½‡{¯VJ –jüÈþ‚¥Ž~%®z¼9p÷þÞû[½}}þtïÎ?VbïÎçøãîß?†_÷?YýnïÞýÕÃåû“cÙtŸQgqœ†î<(©b¶Úe,¯ÙŽ´Ö÷¿f«Ù,¹^xÐD>¬;ø:^ÀâÍY5Vø M>m¬žSä0Ç©{îx ñ8.89Œè`‘yw‚W,9w>W:ÑREf‡]µaeŽÐàrXPdÊ»Ö%¬€›÷É™æ^Á. Í&É.&k§UkLŽ#¤MÎ^¾'rV!>˜ Í›dßrFó¬1Ûò£Ý0ËEdX²\™£˜"•»zˆ‰à‹ †”úÙj £¥ÂäW±TÛN¬KþK°ŒkU˜ø`>ÍQ f+lê§ ?ñéQž6cËLÌŒ¡ë7Ë¥¾ÉrÅ]¶žX§èópúzíAÕ{ðq‚]¸ æ„j)Â%Ï%¨ÄàÒf °A(ÛÉŒåœyÅEGGdxâù¢“$ta’>Vb]Å8²yPôèÌÈ÷©èAö°&”½¦uRšN÷Þÿ¢ñœÜµ‹¾„}B$讕K‡Râ9ÇéÜF¤”,ggÂ]2ñ°@ 4bÝEç­ym¬á9Ó8³OѨ¡ï¥b…ìâ⛼ˆ€rëb꽑ïÞ­¿›»æƒv‰—Ô>Œ®É ¾ŒkQ60©åþ€X0Ím-É×eQP›k“¼ð«±bY±hº1×”¨pl ϧ}$ -jnlÕ½‰ŸŽk·1¥­â‰«h>‰cø÷)Äa„y¥’1mÕ;ˆçÅ%kѹ¿%kïFT–lÑŸn”…õ©ö‚­7×Öóm_ 3C8f¿¸WT3ù}?yzzŠÚah¤£R¬¹pƒ+–}9b´¯¤Ycxå{êfWéÑGÜ2_H¦ÀfúîŠT‘±¸Ÿa3ïzê‡ÛÑNCú\%ìºMl{ŸÄ¾…YÑëÅœÌB€³ UWçS´&rƒßHË`•w¥s6;†‚zõ‹`KmWLcªnS\”‰)ƒ¿B$‹éÈ } Dx^77‹f/›Ëïnc/›s†^6·KÝIFõX^“2)yëå¦þC|«ž¼¢(ÃŽµr-É …0-¯)M>šò’*Ìû~¾iÞ__‹'€n¬ûmžò¢4áýÿ½‘äYendstream endobj 573 0 obj 4598 endobj 577 0 obj <> stream xœí\éÇqÏçÿˆýÆ÷îpúîŽá’,Ë4äC lj‚€ZR\ÁÔ.)Ц˜¿>UÕWÕLÏÛ÷–’ƒ´!éíLŸÕuüêèyy>Oê|Æÿ—ÿ^~wöà eÌù³Wgóù§ðϳ³—gŠšœ—ÿ\~wþÑ#jáÑ”æ¤Î}s–PçAŸûh'¥Ï}wö;·w;»wÿùèwØ%΢Kð“ŽÐëÑhùñþÂL!¤¤v¿Ý«)¥hÓîýÞýi¡&k]лG½Í'ù©±q÷<50,M6í/Bˆ“Vn÷ÑÞNÆhi˜/÷:w±o„ÿšÕÀ˜Þóüf¿‚¥iRsà“—±lr|¬?B­'mRífŒÚýaßÖ~Òwëž¡‘SQÃŒJa\«qe-Q+‹`˜ÉºŒžÔ¬4M5i­aÙÞëižVeê´˜ŸMZ–®ƒ*g"ñBÙ4ÍöüTJùlÊÈj6»ÏöbzþS$—Jp÷áE‚W†wÉÔôÎÕÎ:!1l5ͼaí=§Ýc8ÊëNå'øfž¬Qü~ £³^Ò£2O>›tž—q 0‰-,S1&ù Ë2|^\Æ÷иŒó¦‰·÷ì)Æ` 5ùº÷x^Gy ݽÂÙâä`qظµx… r.x½»Á&pŽÀµìéë>ì‹Î½/p@Š»‰åýoȲªës@É«Þ3/iV0¾1nò¶ÊßS$1ÌvöÀ=Éâ†g « ÉóyÙ@¸X'ö/0O@ѱ‹Š°„Ì*º2ý¸‹J*õ¹OTJÎâJ/ÊR/@FœŸõŠ+ó)*ç«<& ™ä,«qÖ°×_›Ò &/ØS{¤oÀ䓱ÞïasÞ»ªÎB^[òÞ¿eÞK1 ˜øþðc&ï¬ú—™œi­ÕJŒ3‡WR™Ê& Ÿøª¯ì)’H:èš?­þlŸE¥sÝ·õøvG¥¢§AàÚȶßà_°³É«°$ SF  qk°¨˜ ·ÊÙgÊÁfŽáÝ<00Ûeec?Aú¬ÁCXŠKæÀ<ýE&CÌ«øûÞY°:JÁ~-(gl©²]¿¼ÂgzrÖráͳ)­Ë¾Ñ780”Óýê&4hbAöìþ8“’YlŽÍßúm«¾¼i`Ä:dËÖN5évó“õË ÙÏÇ{X-†À®t;¯ÅA ¹¶dœŒÍч \®¥OßtÕÛZ>ï?òš”_ë dü> ›º´ Ð y´¢È'K–íH&³èê*ó47€¾­Oi ¨•Á4.r…E !w,Lo*CvÃÆ@Á£‚Ìaó_íšØ¼é½¯’eÌ{‰úÁMʤÝP¿Á£·6MTh‚·ä~¢€ÔúâüS óï\þ2“I{€¯L“Õjšƒ´}.RÌ4§ÄŸ ¢¢S:–µo‡ûK¦?(•FŠ¡‹KQ  .™£‡"{“i?“fi?ïeMž<øO Ê´Áo:IÐ^#Íø°Ž!ÍQ„;Ï3¢£"îüÛ\ÄFôpšò.ŒÒßVfò;ŸƒJGÆ´Y«jHµ>"J©Í,–7„Rj<-쌴ï—ý ùüÌÅc©PG#Ðôž¾À/À”`×d>¦ÿŒF¹†& ðóhÖ©4$ŽÃiQ³|vöèá«_u rò@ŽBSC—¨à ëâ‚xBWh—Eô…D8ŒòånG>—À«Ú ¯¾3æªOHpJp~f )+!@adÃc}¦ËÁœ%ö¨‰x¸ÂÙðañS4xè§HV`;)xã"|ëÅV2^Eè¹Ã¤-ƽþÅ)!áÞbGMÖ‘ûøŽ‹9×4m†-ƒq€(*×9Ì5B¢LÛض¿-HÚ‹ƒÞ7¸Ô:wÃõ>1Õ‹J†Óc•ó¤y—Ñ~Á¾È™,ŠÍY ê!ê¤ 6þŠ~J³=ÎW¢°Ž÷wv¡+ìp «•i5;4˦„V8-1& > „p¡«ÁåR6¤ðWL‰ŽIJdø¼‘p˜(}(ô•â ³¬<57û¥Óé|•€!«ØOÕe"€ŽÐPQq÷¤?Â^Jš k”-z¼î6w­¥ði;Lw†¤Jù¦«ù&çOº¾ï,YÝ3—„B¨¦ôëfíÞ2wj¤¤k0 Ž_DFr(Ka^Áƒ•ïq»@&pÜFÌæêD¬ 5x4§X¥9´7¬æ•ÖÜþ¸_<Ù‘± xü>Ã?=Œ\#BêHµœñ£ž’f‘BÃ*ˆèÁ¶~Î{º¯ƒì¾ŽÞ=g¿ eXé‘2 N*Š£Y?³kò¡ôH´ŒFçhdÜç®Hù1úbÝÑJ|Nôó¸€Å_t?ôž¿T%ÄÒØEˆ_8àd6'r{°êvå^ƒG£Y¨J†‰‘˜à'0ª×®)Ï}<ê—ªj^CÖÞ þ®lÎ4ã ˜&Ñé8€R¸¾‡|‘Ê[òVœ ºA(/WíÃ:f%B^lQÖ´1‰HD$§²ËÞˆ ‘œ¡£Ã«A€!lLä5lgè¸ Í'³®YàW8Q6üõ0,øeIf‚R]fº^Îó7U1Nؘ²?EuÅ‚ u‡ 1ñ¶Žxökh‚PÌg¸™‰ ‰ÝyšeÌDÎÏ/¡DJ]ß½×¥{ –‘™?”!ŠÌÍe+R—ˆ®MŸ{°(r‚ ÉÎÉ8 ‚ Æ`ù$‰†¼_vr{¸O{Eê;¼‰àæ„:çS*E 9WñAme'™‚ÿ²38{Ê5<+g^UÚk“¨ŽçÔŒ)tŒTTÄUe‡ 9¢6àS›=ÇSàŒ6ÙËasõ˜d­:fáîÍ,LMK£Y ¥a_÷/3{Èü·¦ö M:í 0$8JU:SÂd¬æE£kY5çMÎXγ[Эßp 7>édíÌ^UbªÊƘY ¡Z ÇÈ’CÙÐqÎf­þYcT¡Å‘ “™”Œf…ÄrLt èÁ…=ùe­J‰ò~s.y_”´¡ÀB*Ó*ÚÊPä]ؤ9‘‡ÆVx ­­0©à~ª¡vBl¨È•BÃZeÕlS…âÍ&<©c  Å/xq݉çÕsI•jóëÈBàÌíì±ûúÒõp¬£øA êóÄ23/–-Òñy'à÷8-)+§·½ä\Ía#QúÏû™°H“G¬ÕùºU€×ú¹;óeTO•òúK™$¯uòÛÂRêïZ§„‚d{u{©S‡º¿ªÇ® kÀ;LÍ—Ü §u1[Ö —|ÝcáYà°äìpÊˆŠØõÂ8˜2*án܈dà‚dÛ@²µØ‰³Ö°ÂÉÎ3þ®jØçdÐ ãðcCÔE—K‡¼K»´„ÆçÈŠlÞ–··²¬]ÆÌ±¨ÙËúã /µYÄHŽª4©ýìÝIèˆÅ¥º°åRªÀîÆ~ˆdÊåÄ+ù’Œƒ©Wv¦áX$èÍÂá\»¤Ü54!—”mž|2,O `^sz&æ¦{šËÎ`3„àÁ–:*¢ky´dÙÅ·©íá% lþ¢cñ>Üêx¸¸°„W† W’Eds!ËáxœB÷…ÓÊj,õɸòYÄAû „t¬_³‡‹êNå¨îts.Z¡XiöXŽÏϹžN):Çñ½YK4¾WSÇÆÙûÅ@ q7Ÿ<:ûüìå¹1d/æs˜2žÂÆñÜ`¼8F¼ÿÑóþÃ÷¯Ÿž=øË¹:{ð[ü×Gúþóð×çÿtöÉÃóÏO½1fëIððë­ù~oJ0ÎöZ €¢ù±Vt;ÄRÇõíe%ÙáŽQ¸L䔦²@\ps¾e3ªåb²¶.'(bât×ôÅþ8\¬ÐõLö¨ ¬#<$™ïo'YÎF\lƵDMóeÙ¦á™ÿÛ+§ZZ.@lC[¨†¢DŠÎÙ?²’¨Eá;ƒã«k üöà"S¯1*ª Y(5/^U'T1–Xª°2!EÏ<ŸøÔR&Ð->4Ì:Ž/m¬\ÿZ £Eãbãò•Z‚S}28[¬ÑäR©}»ÄºVy¹ZBðпãŽr@ð“ Ç¿[,œ>_4'mxàêºkæ:3ûTA€0JUjª‰×nýºÍµTÈuGT˜“¨kf÷4<“Å”g]nù­™ì5{Í;…>üðÅcˆ€õ• Þª)[ÿ^ýw½${U•¤ŽDÜîJZ>æñV#8‹%®÷ ¿3#ÆÆR…çèö¶èÉZ‰\¤yÏ·^‡eã%öÍÙn…a4Ý„.Å:½ãE•Yðê8\SÂ´í® ¯ÄÊôZ¥yÐ@ÏN”­V­Ì¡×9Òj›}b£ÛàÁ2Ãø’¨Fü³¼KÑ?'ã#&ÖqXïÌŒ¯s;¼ë¸¡B·çPsH¼ÓÔöñå@ÁãµVóÀ$æ ^å›ì”´øØwÕ"©±VìÄû9n®§Ø3˜ƒï 8Ã2±¤úÙîþ*?ÙÇ>¥…ÊÑúäf#¼_d„º‘&tr¯ìqv· îºàͯƒ±4ûÇýiûÔXö{þ“yÏ.ÍðË%å®Õ–f9ÈšyÙDª%`÷®w‹¥¦¼ècuíÅYdKp /ú¼ýÖÏBrË ™Â*ìÂ@Hù0 çß,¢Ô#¾µ#¿X覈EKHïší¹È ȼIä}¢€ä7(äÄÈhÍÔî¿ðOÌeÐbó[zv‰ÿBÿ•ö–Ó[4ÁDLBcxß6†ÝŒ³Ì4MnJú¶éŽ@ï_^¶‡ÏÛC2\ð{]ŽõÕ瓛Ƚ_ÉÏ˺À’Ð¥„Úë²ÚO ÎYW|ÛÞ\÷E2öõÞô÷ÏG^·‡ßõ‡ˆß^‚°»…AMŽ Ü6é#ʽm_ô‡OÛÃËþð¦=|Ò~=]¬ +1ÛÛÝu{ø¬Ô²%}/fÇŸ¨~_¬žF‚Ð|{µí}R¹´:ÈêBƒ=oìw]8ÔáW@ùБ¾i'þd/¸óªkÎÍIi|Ñ7ðJ,ª<|Ýí\æÙ§(q®Ý©¶a•ÖÄE¤¤=àšÊš×/ªß®òùrh?£>гùIõýù²j†ÆèE fúH}Ðùòåhßo7Mu?Ì÷²ÿÞTÿß1Õÿ«R9´­xÏÅá¢>ZL2ÛïE÷½Ù>Ál7¹ÿÿh¶©Âäó³ÿµ5¨endstream endobj 578 0 obj 5461 endobj 582 0 obj <> stream xœí\YoÇÎ3‘±o™¸£¾ÙŠ£@¾m4© á!‰¢-ù×§ªÏꙞÝ%% Žm$g{ú¨®®ªþªºz_¬ØÈW Òÿ“óƒ»_r)WO®Øêcø}rð *«ôïä|uï«9,=ó|uôø vÀWV¬ŒS#«£óƒo½Öø£µV6|ØXçGÁÜð÷µ¾Zoô¨”òzøp½‘£u‚«á<ªÑ9ž5¡ú§ðûI3rf†{k5JɵÁzxèë`Ý/×ÎÒ ÿÁ~dÌGk N0-¡ ½wʧ^”ÃÃõF ÷qp1* =Hãp1|†´ !Œþ]Ú‚­÷< ï9Œ€ÃßÇJIåò-wßý+p×Q¶)mGæ€sG§‰[ð›jjNknRÕd£åÞÇj-»ýr=zÃDîøËõ˜è™¦=‚é*Å­^­%ðÌ>\×ex¹Þdv\ ó¡2p«V}Z«>Â÷zÔZ §µôY^î+ä‚ÖΪáy}}–_¯¥ÞàÒ°QH;üן3Y»HÝ »¡ %‡Kà×cì–K{èaâ^'a’BªP§ŒIæyk=cÂyæRO%-Ðãèò>íÏ%S«I™Ä9óD®•²Ë0^IzT(%d<¢›¤2£2Ó / ‚!™¥É럖ÂAÚ•Ž3ðºò DjÏ˯™Ïáûã@$ré}^?ÔßÚÝy‚Þ€³œ?À£ƒ 8ÂÕ¨ÍäXžE”q2nZ9a9­xQKK›Ó,µ ‚µ‰zƒ @̼Aîl„×A™¸„±AO—…Üx`žþ\KkÕ*åØñý£ƒ/^¬¤M0ˆ@)è%Ú+ãV(ÁQÁÌÞ{pp÷Á'«W/¯ÜýzÅîþÿÜûüCø÷à£ÕŸî?X}±l|'ÚžŒ/‡q<`0vNEL9)¾aåªj-Ó­˜±÷A·¶tŸb£o`½A-é|ðÅuÏ@}lÄc#µ ¶ê§®b7z(ÁÖB¯sîá{½Æ"4úºð^-‚ TîÆ–*“†T ½±:tsçÇ@ûc}ä‰]’9žŽ SŸê4Q¬‡:ɸÌLý ã–ÌG0§d6ÜdNƒyxš,”y±PÈÊ ½Ö>jÇÄ‚=¯ï«y)»‰Åý}ÁVyèY´`¤AþFË ½‹Ôͬ¾vTªfU!¬e‰Q†)º=±©mŠ“­“Üu:¦ ©n°ÉGk„RZŠRîú¼‚/˜7Š×û}œH1¢À_”k§2FØr˜L>Ð[f‹»—€ñ$§  «giɽk•¹a„%2›Ç,h\îŒE,ÁµÄQ#?­€E@áÀ]CP5[2$ gYŽF¤«â¡ðÇuF  ÐÀêø–ÏÏã^)™ {%ÅeOŸlÏdø“¼7Vƒêp]+'Á”ÜRsÕˆ1A6D*9G Þ(°ÌŽñ¬*› ÓhT6øƒp io0-8Pà{üˆÖ2߆²üs‰ÎÚʧ¥+ì%ð«åΆÆÚojá÷¥ð§Zø¬ž–§Wõ5p Ôá.ÌC°0‡Xëq­õ¤žÔÂÓÎpA|à‘{k[¾p -‡bë«öÅYb¬3¥‡;åõó¶ÝKüx˜*‚²×™^T"É꜔÷—õýY¯Ñu)<¯…0’òq³ûÚ{:Ý5èÊþùš\ÕÂç·[½T¨‹ã"I 8wz#§• ûë¤4ñ#?^պ߮×}œZ¬•Svê_Ú‡cèÍŠ{ÆEÙhðë &J¶¨ìm’ñQêb’’qG3Gv¶ÓD†–t'/F÷çb‰‹”{– WTkcHFöÛ®ŸEŒ}isÙRŽJz¤žtÇF «´á¼èx»3kÜA| 0¦yÍ'Ð/x½o-lØZj¦s•ÇoÁÂÇuÇF' ÷1æ`ÃñÍÆ¤i?uÓ(~ºÊ š¬Á˜ 'Pó¬ãÎ}2>1]‰m°‹ º¦ ÓDi› °º7ŽC’Èp?ÒD½”ÿØAK¹½Ò‡¼æf§<ï‚pŸ@{c´µ¿lã&ÐH$™Ø4€^ŽœrŒ¨~wb½U£ÄFxåzWxµl”ÝÓKÚ‹¸Ÿû¼C³ˆ¤žÑ9þ¡m¿1m+kø9ŽÛxðçãÒÏüEÖ¡Ý*™z“ù½Sìê‚I*Jö>³_D º–+åè¹ v G¶¡êxb&'ª÷=$ù¼âÃÖ!à r^@žâFò  r:½©ãb÷Ö^Kîc¿#Î:›| À ÌÅüø£d-äs #ÌÉ备*,ýæ÷‚‚亵=ˆF8Xó.¡àŒýjBÎÏ{´ì#Ì:ÓÅóÑÐ^ÚetV[Ï£?1,¢?ÎÍ£?,E…ñ«1Ø’‚zì¥Ì¢q«*†ý9w˜{N»—§'´ÝPG‚™ ¼%$„%Ukæ!¡&¤À¼ƒ°‚ÐxÔ6Sê÷7ă©AAüçá‚iæ‘Ägó°‚0>ÄòÞ6¬ œ¼QXAÒ›š°‚plkX!°U»…‚Æ8;UXûa†"RI6½¨µ'á…À8¥7LëÍ 8”„åx×á…MbA»oTò´Šâ,JeÅ[…ØðÜÂʶ[%Bì¥Â²cj§'Y`ù䓽$Ÿ„SšÜ, ¥§ v“y¦@:¥^ãÿ_,™G`àÈà8% t4šeºµÓï‡nPTßÒ½÷~•Áb?ÀÅ-B¬·o_¼žŽ×²zÈ]\ó6ÒµÃþÚ¢\Õ¯~Ús<_æ.qáºÓyV Ï×[½—åé°öþêÿ“)ϲöD¿D*P²±„6` ïЊtEòaøë.‹Á€†gÓü«ßeèíöêN‚pV‡‰ï qï­ü¿¶@Üáwi~‡ÑÁr l÷‹~½ö”ˆnŒ&ªn„Š¿ãøÈöŽã©8‚F1F5óˆgßcá„æµîÄñç…8^?;ûrÝ$ë Í3ñ?®ÁoàëZd}Ý@ó8AM{LùÓÁëÔËÙEaàáö¤j¥F£û±ÁBÑa7v<‰xœ?4aÄÀ ©ÎóCãm™¯ñ†Ea`~Þªp-±”{ó(NWó´Q<†/&)Fd ÝÈô¾›ýMÒS§1¬8‹Ùa›Ë69ͯÀËaf2Éá<…9U‚^(Š‘Pnÿl®M½«KËéhýØ#Þ˜ZJG£É )M‹È"y<ÆÀh‘Σ —'n|×3 Lëðæl›‡:CÚ´ ñÀåPç4¿àbéèZµ–ò  ÍOµJÁ[ÄžOÜ+Àè6÷ªf±ÞÔ½úMf ïéb;ŠyÖÛNÉDÎz„Ö>‹aop”ù¨·íOÎOõ®EK³é9OQÒU‚Sž˜ïÛ'S)ÚH+0ƒJÁË•Ñ÷¥Ô 1ðÞïtBöV‘}œš5÷‡Úì­6Kágµæ§¥ðãZ¸»fë^ï¡\}W€ú"E»²b\Í’Û©fS=zKíBü­Vœ^kÙ,^ÏVOè5€ï­BÀ„o³¶ÓBv~.øz ”«‘Ép‚*bÔ÷v?cuˆÒ«‘+ Nj|‘_>Â/l<}²‹L-43*„,( T¸6d-"lnéEÝÆ,üDN¤´WPGƒOЗ‹Jd`?·:¬ñäBZX Éñb©Ljœ…Á´6urçk¼p#¬OS’1‘ÀëŲï"a‚u¸zôðàèÎ7ßÏ5JGžL©5½É;¿¼—HB–ƒ(.Þ”ªIž®-;±ýÆé’Ž…ë¨Í‰b6Wî¨÷+ðWÍÒÜCÞƒ. ´ùcýZƒÙW+äo* _­ žÙlnç´ØûäºÂ¹’Qñ5Z Ó[¼ææ»Ôèßut^•»¦Â•“äÅS\ƒ9¤}Znr£”,ÉôrC¼§,¶dã¦|‹Œ‘|O'ÁííÉñ%^íÞy%÷>žÄ¯–ÇÅŒñI¬nIÁsGIÄC=èÒ€ó¾ƒyÐÜÏСÞXDp©x¸D2rDèébõŽáÈÞ=Ú$ÐÍqÌTg‚”çcKÊæM˜x;øÓ¢%ñ;>ð[Bè\’@~•º™ž‘wF$Sûë:pXÈöz„ÐÑqŠ|´Æf>*ÝᣠÛÚàƒ'Ë–BDQb eáª9ªí^ì9N»ªÁþȶš¥ç¿‰}’ï#»áx^Ïî"ºJ8SgÆ[mž%oÔƒàr„øÅÁÿìÖð³endstream endobj 583 0 obj 3798 endobj 587 0 obj <> stream xœí\[ÅÎó å7œ7ÎXÞqß/‘‚„Á€#0Ƭ$DdÙµ½{Ã^cüïSÕ×Ꙟ³{vm@‰°Ç=ÓÝÕÕ_]ºªúü¼b#_1üúûàdçÎ#.åêÙ˶úþ{¶óóŸ¬Ò_'«»{á3M£gž¯öžîÄøÊŠ•qjäbµw²óïµôÚ ú?{ÿÀ.Ž5]¬…ƒ^{‡ðåGî­õž¯?øè½S~ýá Ö‡]>*¥­XïÕoîÅV©Üú´J6L6»ÖºQp½¾;¨QJa\æëaWCËÝú>öuð?f•0¦1”€O|²Æ¦O=g–NžÆR^Ó±¾„„…ô¹›”|ý`(tã€÷êj€niîÌÈ9~‚´Jhq‚+ìÃŒJ{è ÅÈaªQd?ÄȘ<Í:Mæ'“&Ò…åiOÚmÜåÊL­v¡–{÷f{tØ9qìqÎÀ”G•Oà=W£:„G ­ Þs!ÖÏ`Œç@+°A®Ok¿ôh˜é¾~†ÃÊÑ;³>ƒž""pc3.½·Rò¬ßçi"qB*D [g_|gaÕyYšQEÉÌ™GÂÈZr—µí%¶±@å­AÓå¶sÞÂ9uXü)]c&û <Õ¶—¸×Z[#ò£w:@ ”¾€¥‚XXnÖoÄ€ðj*‹aü ‰Ì{æµÊ$ ‘IâÌŒÓqÍ\MÛÙèñÎêõëŠÓ—ÜZ©v)pP$;ЉÒÌÓ­D:ŽK§'áK ‰ÏáÄn5ÊIXœèBÝ?AVì&^ìâ´a"²$ÑËYažaŠnpÆá~.úèp –Üo?.Ø{:Ø]ú帄´ΪM[T^d†k‘4WA_¿.[Ý#ü°¸úD^߯1-ë¢þõ @²˜–ìW9©ëÝ/Bõ&AÔ`dš*T©“äv}Þ“Ÿ7hŒt÷&IBd@P![ŠäFØ'íÖÂ}TÛqÏ̇ T¸Œq4ä ÙN(‰@êkkÂÎmìB]E;A„ꨇʅióëH/,C]bN`}ÌûKÖ,§kîò<.±ð_”%¾¨—L¦˜‚)23ŒóN”Ê'¿VøÐY©€G¤4묊#„£p¯v0JV1@3Q¹ËÅEÙ«È<ªl³‚å¢}y¯²„@·¡¾•„Ìt:08`Sƒwp¯ïªÝª¢ðšeKlÍ´¶"SÓ#õNˆýWÍ—!®Lô…4à9‚6†åšõ7ÐÅZpA¾FÚ ÎGôçYë—Ì ~ë~­~1·*¿àì LTa“º’¥$vÌ`”…µ¢–èê)×åjiΡŽHý´¢î¿„nÂ/ú1p â7;0 æOþ=³09}7=n g"o œfʶÌA_ôqqM–QÏD€Àlß¶å‰ì2vÜAs0?××t46=^¼û¼Ñ?Ù %èÜÿ ZŠH{ÿq^jv¥GÁà}Œ‘uLÍPb &éoÅñ,\GóùpIÌÒA³—.+È3§àD7¤™Í®/ç£ÔË †ó õÍûýŠTUx–+ª¿Œ_\ÊÆ­)0½ê¿n'o <Ä÷K#žàwa pe˜+¹œážÃwl@×3±mé‹8š¿_¦–÷ó'ÉuCìf»„¿^© xÂîÚ¸ráìäèÙºÂųN÷ýój‹Ë …Âãáÿz6:w0²@š@nHá]˜/á%Ð.s°lÁ.‰ åEÑÄÏšcsu{†¯%z  ÀÑH†¢@™ý¢÷ì¹G—F8ƒÎe£þ³ 'a^‚07öy<¯€ãPç>ÈÕ¨¼Gù*7/e÷’§u€T)„I¥ ŠBd[ë‘o8º5!•_¢ƒ&Œµµñ°ËúèºDˆECíÑbÑhúîžß}rŽs,(õ›ø5¤/´ xJB(Ÿ;³£ûKfo*ÀQpQƒ+Ó¶roêª2«Ç³?,8E¤U‚7‹!r¦:XŒh`#L¡KÌK0rxŠÈ§ÌY64:ã#B«XM>ì šFdR=ë«u2ÀiUrïòÚ&a¥lše/œ“,C`Ak&§sâéSG%«môwœ˜häâ4µi9Ýãê6ÕZçi¦ÊÛ@ú'9Ù*ùîù0ï Â@ ÂKcÐÝS%‰øewLß@ùSW M<ˆÖ«ŸA÷i·|Þ$;¾$ÑiÔä´‚áúoË¿H„ÄÝEtýÁUQåÀ:5JŒÓ°F D P€g­I@HŒ?™çHãÍ^”¿AOnSÍŸ=?nú…,û´#D¯K¾ úþq•­â¯ÆlI”*¡:R“|p…`)z0Øp ®Ð,P¡‚±”žÅX<Æ€”ž8—ÅâcSÌOH.Ûü„è¯ØNä•ÈVp7Òƒœ×p*@õ„Ë‹oP™„%` œ¯(/Nó‹@làOüø‡òqhC¥ØD<P•ë;0•`ašøi2h £—þ¹ñ¬4¾.A™Ã32Ú gzwºˆØûeûâ8Ñ qæ[åõyÛ/,åvú,æçåÍ—•È¥ñÓÚxù— l øì„Ïë—/(é¹ñâR¥§L1Hâ» øôª[ED˜ømÖé<ìLPZ ˜¬(­–#øˆµ?kÅÇW -ù[8ÇP4킹 †ô/ñ±kHÈa‘‹ãòtQžn*!‡×–bìÿ”?%ä†ò[ Gøç~š.Sú¬|~5£[ËN…г?„ì”7G•È}úyÆì­Þrê—KœÊÇT 6IÑíi˜²`R’NH2O(ë¸ßk|ÕD`|Œg—¼'¿“Ž>.ƒ¶ë àcb{ð½î0ê÷_ÅÄY£rª„l_W¹58›oqƒ³<úÕéx[Jv ¢–@M$ïÚšõ ìôõq³›Êè‚öÄ»›!žlwyúsðß­¼üé¾\.dwqÍ›C±´b”fr&ƒì–øÁ Ú£&Nä¥*Ó¥Tã‘MuQ'õ‘Ãs“”Òõ²†"– ¶iÉÒ« o„"g›z8RÈDâ_È4Åd(òi‚{1Iئ ?,Ñ&b"¡À$©F Aá“·À0;Y: jô‚iûmÌk(<††·-S ‘@ikš¸Ì+ ¹—(“$P¶)±?­äËÑ«Y2='s”ˆ"e«±B•;îPRE(C} ÿ}wDäí¥QÒRžP™ò…JfU»Ÿb1a½-ô;¥»vŽÈt©Ê…?,$Žó,F öç.4"u¬àâ¬)ò¨øAãÆl¥›”„l` Ö£Öx ¬IåâR Ãʃà']’©»•&ç‘ù6s!Ï2É4JM-&¥!óXlææ•êLK^»Tû!¶“²À„)ÎÐÿº&qß äÓ"[»a:è:ªäš*ÂRh™étçë*d4£6V2MÔÉxµ…—ŽMS†Æ/–~vón3¥µ)}¨ÁÑûqýF4 ¨ÝçõmK5KEÀ)g¶­8Íxªr-³™æf#àÅ(Tü ö2£±ºý¦TO:üçC“=í–“öìB*& VÙÔŒàT‡õM—4%GœJÝ×ö¸ÀÖ•îÀ,TwŠŽjÒ≗ÊÛõB‚°Öãʤ–~™¤™²ROUŒ³î¦Ð²<ÔñHg³ŸA2wwRp”5ºÿ¹€“:Ê/[‹T꺨ëAƒXǯ ÎE,·fe¹!…™îmôSá_kþÉÿš @Ï"#Ê’EkÖ»@jE2„ËõMT?žg°Î],Û‘tõdrÛ€Q…ˆí ¶îUrjØ<Õ=Ív" ß*”î¬e¶“|3ÊAÖ* …)Ù÷|V\ºÁêò©–Ö.¨ùÞžPáÈYø »„$8Ô¤FÌ#'-ÌK@rõF¾±aߺ)ôƒ©m¨5[]ê4—@5ˆ4:yƒ©¸æ˜R…ûlÔbÆMʨºk¼4K--/Ð/#7xC–ÚDíM†AO¨VîƒÉRr¡kR¢ç%Q7ŽÖA®Ê‚؃¤Oˆ~íV¯HÒ-¥PNçþaI´û¿PAN§Œh«Z#­>O·;…¢;Dê‹ðœm±¡AW<àdF—[­¸D‚g{±åXRËÉ6ÄþŠîS`OÅÙLÜÛNwn7t¯¾ù·Wé‰×ÊŠIéÐâéÏF’—ŽK’&Bu„C€¤ Ñö“Ó iý®½ÍœŽ¨Ž^¿¼.¢‚ºïG/ı4[$­¹@à:WÉæ¨?À$ŒØøÏ èóu?N•Ô´{äâÿóÁúQ‹ÀàL1GYO\º¡šóô\)¤=ÐÈ¡#ù±D‰/ÌBÕO§àŒ µEY’¬Å¹[ç=®Z–„ÙÕ˜÷ÀD†³!Ò}µŠ¤ƒ^¼fF~Ï´Ýe©«šS&é´ã^§W¥ñ¤6†0–|««d§ 4Õ„ÇECSj|SÏKã“fN g,‡¹áœO{‹±°Î”;ÀÍÄ‹CŒ›‰—4IV˜¦´wÜÓ€º}JMp¤ÒÛGŒŽ˜cüF%ׂþ5*òzÐùc¤­;ü_6Ói]=uÑOš]ê·zâEðÿ¦4ž×Æ'tv²ƒ}ÐèeLW2bZ3þq‘7«0:Áð$mVÎ+¾…”ûëHªØ\0ùÎÓí[›Ãáª8 ÒUúÏ3Ç=v¿¬ñ¤y«G]ÕØ=•ú›Jf¶¤²%‡û+$ž§‰ãwšoV~”bâìȫ囓£ˆî ÏSÇÅkå:žQ8u,ÔÚ:3‡¡éh`—„Ÿr$U«ÑèÙ%gï¨?AT½ÙÇ8:ªh†¡l"D&¾çìæQ÷’‡Ôi£!ÔIl«;×b¤7ÑOûC¶Íi¿°ÈÜÖ†o¥ ¿½@®7?|T†D”Ò…léG+x÷wæ?|=îíí|µóóJÂq+üŽž WàÜÃ6ÁßpDWœêîý;÷¿X]¼xõdçÎ7+¾sç3üãîÃà¯û¯þ²sïþê«m² NP€PøÛe LÃW•%¥Ûp6òþŽ«Æìî_ä~ÜþÜMBàt!SxS£ ñ´¦y`aë€ì‡Ÿ˜ÇQ<ðâ®À0þô~÷å2/¿ðKCÀ96ÕÆ€CùÆÛÍÔ‚´_÷.e-^#1ö¾xÅiñž©øSE[þ Hþ¹¨|Ï[Æ»éBÃú'?’Ò¤ £Ê ëú ÿm¥$¡Q±4ÁiþþU RÍS6ØZï\“Cû«=˜’Û³ÝäE³áñ÷,Ìbty"ÿ_íü㻋µendstream endobj 588 0 obj 4275 endobj 592 0 obj <> stream xœí\éÅÿî ü û7–ßÐ÷‘ˆHH䵂(Yvíµ•=ŒqÈ_Ÿª>«{zÞ›5HQ¤ogú¨î®ãWGÏ÷'læ' ÿIÿ?¿¾÷Þ\Ê“ËW÷ØÉÇðïå½ïïñÐä$ýïüúäƒSlæðÑì™ç'§OïÅø‰'Æ©™‹“Óë{ßìô¤wó$fk­ÜÙðÇÞ:? æv¿ŸÄîËi¯g¥”×»§½œ­\íþ?Õìœ ¿›5¡ù§ðïà‘43gf÷Á¤f)¹6ØŽCã`lûÅä,Ð!ÍîkìágÆìîtâÓšðÙ{§|Ey±{4íÅî!N.f%a)`.vŸ!mBcvK¿Ó@°õž§é=‡pú‡ø§RR¹¼@ËÝßNÿv×ÑmSÚÎÌÁÎ^¤Ý‚M–{%üìÔÉ^²Ùrïcƒ'@ªR\ˆÝ¿¦= Y»{ž7øΫµ5b÷Ã$a?ŒàõíM$ÅÀÆ]N0¾ ;r s¾®§Pû½¨Í›÷{Åá|¡çy!ǸÊӯװŸ³1Ö(œšâx»7uß mWõPf`er÷´s³ÒÂÀº÷ЉYáÜNðqøõ#tâi[„T»—Ð0&™&=µÜÔãB­¤¿ê8H.° Ò~÷í®¼§[ Í൤Ó<«+/-Ï'i—€ÜgµÏy™ç vŽœÚ“x.Z;J(òƒðnö"3Êõl!¹-GüÕž~<%Xð³Úà iñÎêfëâŒÆÂkè$qoŒ‡“%§˜xB@G¤<îœf>QëµÂSËó]•‡y¥w”:ÄYbü´Ò=¢ qÁÐÌ€Ð0½û‰0þ‹È!’K"ßN……AÙ(åfÁ5UOQ§ |êuæ_áí›IXX…í˜\ÂnX&DT[xŽ—ÐŸp哿èG¬÷õž%}K8 »ÝàðÐ^úq›'ø^Ãô%RžT±wq,P»œû…ôD®·@-Ïl¿Ê5aë´$Šz€ý<‹¯½3Ûd¥_C…¥ mÝíaü{/ôJKrâV•¿c{ŽˆG@h€×¡O+ã?£l ía7×ðMRˆ¹ùE{”äP= ¤ÇDDâùæƒJ0KZOdIºÝ? ä'ÒéÍ8NVKMžî¢äÈužOÄ‹™y?¶&EÖÌÊE`šž[œ™Î0:î½RwUý·ÁŠnŽBÞ,jt.ütYüëAF.3º˜Ð)°Æg¼ Ø?l„$ŸØ­YQpø‡bªê1LhØñ:Ž´iI”E¾Žëjµ6a^âÉ|¬°C;›ÈS(x_M‚ò,Z-'½ãaêÊMpV¤Q7 7íÔc¯ÇzN”d:<€J{e|PtÇPy ›À_Wçd¼j…qÝ&4£Fw DLÔó¥'‘‰î@=ê>í¹ž„#Ô8•UÌs˜5èGÍ=Ø,N|ƒ²4°ç»¿ãŸçø\C°˜(²{£•ÿúŒ-X÷)ò>X8œóÒöÅèáUy`=üFï®å%•}Opìýª}ç‚{ Bvþ~ys“RҺܡH«¨mžWr› óÃaË«ò0’Hˆnk«×åá£ñ^Œf~Y~jÑsÑamñáMÓ'òðýùˆ¤«QËJçõÊì¹å`zçÛ%Ö¡ªÀ´x´çµeKT7¶}]Ÿ^ןFùü×»MCA8/l€ÒÐC9›ô¬‰+Ê3 ~9ÿØaÜqQ=à³ÑC²Ö*¡¨§ÒÏß6«~ï ®y£›™CÌ AfR“†_@}xܬt>V½uTÀ8Žu.‚”wÐ!YdÃP·¡í%§0>©Igtš”¹ÎǼið@n^1ym=tX‹®½Iº.Ø"N7Üjí|ÐdhP|Û«:ºÆõg÷C©M`}Ðø6zÈ5gíØ-x6i„ÎìÿÁþ]ÛËLQ[cYH–'z30OäÙeôNÏñŸ`¥+œn\ÊàJ O£P·%ƒÝ%ƒLœ…Ýß©:u&Çw ç:>y#c úšê 9LJ@γ r *#åg12ãP·ôxþoeæÇx*â÷·ôlCÀÿ²ž­ë˜/ùO‘ù²kƒb¯8´â¬^ûh!eœ4Õ™D—Ì´îJ _ºu¼ž|»ah ›“-lãºhA¸p›D8l`W³!9@,bê*·ñ'§[ì†á–¡×=É$űA@ÊrVÅNëÙùÎ5ºÙ’—`d^#²¼*æ¤u>×”\8ˆ.(ˆJVó²\ 0»Î J*·Áe%ð›Oÿ}Hü²…ÄoR_å –€‹ÁXæ b£cù%îÿù­ò£òð³ÚçÓòðãúðxK¤v¸¦—£Õ7„uØÖ ]ñhAü  ÉΜ Y!ßhA2Ò¨ËHßMÃQVFxNdì³êm˜õÏ ‹ŒQF‡½NØób_°FAQV›“|·Ê é6Ð^}’­…¢4:a0¨)°P}h¶3Í—“n'‰±Vpf˜" ©ï².Ô‡ºÊc(dUûÅöŒ&I>YFY.‰Ê¢šRR15ˆ™·Ez§š×|Ì8HÉ>Ì»»æ2щœ-ˆ ‹Ä0ZR¤ø¦à¬o’á1¼å™‘Ë2ù~išR{l^|q¨Ð´=¬1²w3”· ›üTú èÇú¾5ÂE’_ˆ3#ÒT‡˜¾ ©%¦—ÚÌKžïÒ—½§,uVŒEž#,ì†2p>rˆÚ|c“j¦Ñl„=ªÄ¨¡ë,: C⛦‰^–Ĉ£¥ Ý|y0;›«`0勼¢B‚ÿHö!¾ H3¡0§®n Gbœ$-×c &A|¤éú[@°ëbØ.J»§ ‹œräæ¼ u›,c6Mµ5‰2=¡æŒHïp×tÞåHçë®ýÏpO (mѵ÷Ç ý[Iô-@.À»¿4亡ˆ1·z³uÏ[À¹\MA¶|$r°xCddw–B0ªêBiÿºþØ ñQ‹Š¤:á`ÒÀGŒ2dE!ÐEÑQEl–Þ[å@9ˆµ²mÿКMÇUXFJÍL ÔRðÖóP½¢f§9ì6 –u³Õ6=Dæý0ƒFN¯ ýu‚LÆxŸÝlBÌ'4!žÓpåc¦O=Lô!ZH--sÈhlVŒ éXì¦5îN*ÿfgàüFÀ9½Áb7Dð{˜$ä‘©0zk Î×)C@±ÌTÆ'žç]Šë”!c„[#,¦‚CšQò!úĬœõöäôѽÓûß LiC8Ê}êl0UùQ«a`¨-WÃ4$âÀ.&ùº6Z¯x«ö 9*\´¢dZÂíJÄpIJ UL¤óÁD®ÚÀ’#æ}JšBÒÐÑÌÈø´Ð³ŸW`ÛÝÊ)éÕÈ®@Ó"2:YGc0s¸Ô›,Ù­ít|æœVS.*:s$©è´zvÖõ[Iªš˜ ­8#´¡ t: éU)“]Œ8 åÑPU-ÊS“ÈR%Áq®ìÓžµV/å™™æ´FHÇ#¤Âš;1¤Ž%)›Úƺ‘ÑÉ‘žMÃ\AZl@¨%W—ÒI‡Y‘/MLöƒï?XÝåPV°”¥©Mè˜WÛ¸h˜·Âpʲ:&¼ .òïÒ§4>h‰\®dŽ^…T¼£ô°‹%Lz¸~ óN„Hß‘¤ž›Áø÷j¥[¡h¥V'Ô:·<+ƉWCW¯èö¶ÁÔä$fÐ RËñ®å%Á‰Û5Œ¸ZK%•YÚÆ‚†Çó i‹ÏÖÊ?IÙ+–ž¯ˆOƒœ M[³Àj;/.¤åÆ‚ŸãÅ¡ЪϠ]dN9Pä“LC­™Ã ú¯Ê_©zõ7Ñï" ‡îÃ^·ä‚×ÿ(Ê9‰(ÕWK$ònö2Žàòì\Æä‰úT9}{½vgUñ¦#cÊÒÓ­eJäTÇúx+Š\…„±R@a!`˜«$ K8'‘Á”HdH8’Ïë7(øw{uNºÈz[àŠX ÏÎñP­[.ïðŸ‹ôãf‡NðýµRx”íûÙÓZqKª7ÔH{¾Y@Ĺú«mzEXÔš´¤ù6ÍéDZËa`’Œ‰Ëµ1a´¡ú9ï gO•aUŒŽ„ŠÂ¹(5ÎI,¢ÑKGããÉ]ôqƒJà •XÁxHôß-}g¢0Ò–•ÆmÎ:dC¨~<º$ØYôC Åv’"4¨P¨NŽ{ÜÚV}D•)G•6¼âÏâýÕ6’›c]‡³¾¿®Ñü*Ï—ö0š‚{°½`´h#®,V$^PÁ T`}Jc7uÖ¢Èåþ…§ n,=#ó•‚¹¹u…kƒË8,Ö3®––1‚¢£ØÜ2@ÝÄDQ-xlÍfYȇdºÛÙÑÖ™Öûï­Ÿ;Íú›<~·fqS#%ä:ßsœ_5ɺ!F‚­h¤sËÇ'B¸¹IKŒnØþ6E5íÉàÆ-j1çÂÊt÷ ÈMñz/-+ÙpãHõùCÑâgpÝõßEP$²ã”+9•Æm_/ÂÏ·‡t_›¸zEŒÚl´Õ$éNâõ'¹:©ªAQ+é¦b“¸ ªŒuûÖnò”»&¥¦õÎ’p+±IoÈ™”êØ t°Ø‹cEÁî)ý[ÚVx•Ûò»Lç¯X¬*&-Ÿ~ŠŸ69Tj5 x?Y¼7é~Úø(?úJd ÞuùpÙªV¡tš+â¸C@>ìµÚl,»DÔ_óIeà^´6–`¿ruNñâÊ•¥ÄŽJ´ºÊþEʶ À ?à†ï½GíyH#éäË o}4Q2§sÔU¬)zXËÒ|<°#ø=¯N›jzXxAÏSz9*p¬‡À=Üå.Á’amÌÚ·BÂíƒRoêÍT¾ßÊí ÷ › ¤H|õñ4v!ñ0lÃAñë|Îùqý䨷roO÷ašœèæSMy ;Ò”¢ùÝG<RJÐFðÆT~׊¤ŽX3¢Ú\ЗK½Ý O6ë843Öóà"ɗúͱ‘ÛÀ€G‹FîT¯Ñ¤_x§È±Ë<ÖØÄÀԈܪw†žbc]›ä ¡¾KðÔ8àø+0_¦¡÷³1PVˈä¢$´¶km&¶^ÿ Ò±ï…uõ…yZìzÕk §Dx³¦[»O ´™}â8_’Íšê.¸¾«Pà§{ÔD#žCM+RCýÛÂÉ£¦ðo®mCB¹öa eo¦±±jŠ“o*?οòÚVwä&yÞðÖÕ`İZ·©c¢qeŒü€…㌗(GШC4õ7lK#¤ª°a­ tµ;„EP4ÒOŒœ•ïyÔ+YÛäàÏý„÷3vb!ѺoËkãe¿q1Mþ–Âwƒ¯jñu„öêVñ0þ•P_»_v°Xî·jÒý|²h^ouBc*QÑÛCyÏöĆª˜9ÈÉÃÓ{þVÚÇendstream endobj 593 0 obj 5451 endobj 597 0 obj <> stream xœí\[Å~wü#öÍçXœaúÞ­H‘B „(" ,B DÉâ56b½klÖŽÿ}ªªoÕ==ç²¶£("ˆpvfº»ººê«ëÌOgó$Îfü'ý÷ѳ{~!”:{òòÞ|ö)üûäÞO÷=r–þóèÙÙGçô˜‡KS˜ƒ8;ÿþ^œ@œ9yf½ž„<;vï›Ùšßšœÿ‡ø¹âì$=Œ:¿„'·Ý©É¹Äæ[1…àuØüv+7ÙîĤµqrs^Ÿù$^UÚo¾€« ¦¥Å¦íÎ9?Ia6mõ¤”´ž¦ùr»30À ¿ù ÇzøŸ¢UÌi-'à÷[üå¬K1;¾xšKÃçú3< å$UÈԛϷ…nœð“º {†‡ŒðVAZ•I´x)4€i&m Pr³´Ô$¥²¿ÚÊižiÔ­ÏM¤K'Ò™´Ç¸K‡²†:B<œã˜û3ðÅ{ëÜæñv'Ý< ª^|ZÙrAOÃ3b@ÏëHš˜Õæ X¡ò8 <³³­w¯a°ñ“V~ù .€˜@<‚sÖZÈHãõVºÉè™/ð¸<ñoä92ÈEú<0ÀßßÖŠ"tJµ+â$RéÍKd§1ÎÊJ†Ø¼ØîPÞtˆtÜÖ‘u:¾½Õyƒ7›6:â5bÒº~E.™0$9›ð—‰ëçEË>…Ét€c›Ë-Š… ~R2kæÅ–oá‚VÆ ¤FØÍ›ÈRå‚Ý<‡UñÐæÊkÒ͉͑MF¦Ÿ¨¡ó#‘VÎO¶(ðeb|^ ŒÐ‰F#oâÚ3hí **”4â7è  x´UKëÌYœû¢Òˆ„=„?ñß2 ù³K ÚÎ;ËȧDÊÂE£,@p˜­ ÛDfIbÞ©PLTATP„dEl¦ü£>V.ÁózÖ“œ=-èç<­‘–È„oŸŠ¼@ja{ʰÛ7HÌL[¸ˆg;‚Ír~¡è³ŸÈ^Ë€{UÞ2º¬iÊ;‚´cIDÉ«ŠÂy‰”RÀúäMܦG9™RqŸá¼Ò¦ò-Îãéo òÀ_˜ztž´&Ÿît¬€ÊÊó\¶ÖeóZ³‰xîCÐëf0©ÓIli ȱ0¯ìLè€t(C Ìà£ø'@ÿU4J‚µoa!´(: QÎ"⮎ÞÔ±¸«óŠÐ é:fQ²Œ,x´p-l¾†Goj¨FבÑhîð‚÷¼à@ÆFò¦À øbB°C«DÀ…¹>p’8ÖÓ‘c`€¬I¨lA6—¨Œœ´– —d³ù®N~UÔ…‰m7:Œ© ¨*Ö>{3Áó“ë<ÀFŠ&UE¿+²²µ*7´‰,°¯’½ÂUvH›fõNW­¨øl Á‚@hešCi§9„V&‘~"û*Y±jÚ€%ßUM«ŠTe KnJ¡êªî6𦘨·žy•G´Zơպâè Jƒ·­˜çûÃ?ž&mïi%©zÚŽ.+_æ­­ÆUE‚s­8´Ysnz“†FõÑ:Ù*f;LyœärX,R2‘­>U«  ¬+Öã&v\—NßV(yN^¶»@G;s•íGwHQí”™4he'^·=Úáì,VSlÙíã8¡±ㇾKë v"Úí%ËðRÜQƒ3ì8J®Œj?ùp.ƒ0¯ÖveV<#–ÁLÒŸ’h‚3$EÎlïÆ.$*£i„òïÈU ņ6%Ð1©x†'O çñ#ƒ–Ð-“ì\i¾è¡$ ßrL¯Áx–„o7EªØ×h zdIëÕ¬8ýÌ¿'Ümà§iŠÌ,Ì%Êø·Ûò3»HHKT¶?Ý;øMN†ÍFPVÉÏdÈ×b‘œÖjµ­Kù€×`œ.i#çhÊï†.@qÂ:ezƒ ˨²Í4WKG>†K .qÈÓº×WØ ªŒ¦$5xŽŠû?Mc*Î éœcS2Æ¡+1cl½žÒ‚(÷A^96¨‰ŽÖ<Í%¡ü ¦Ðžïu‡[Yñ"eÀàÙñØ hËý­\•I:KÊ´æI‘ìÙ±Ýéb•ŸêØX!bæ<³€~àÝ-¶^ãþÀ¬eò½ˆ»­ï•`Õhèá<Ù.u©ÅJ¼ :v8m «Øš*^®wdÐa›5%zgø #ýí÷¬ÐI'§’VÕv]Œ ¸¹/ÚoaQSrUÍŠ¢ØƒƒÓ^9‹Âhó'žÕ,1ñRvIÞ¨í†]|ÒJôMk2Ê„EÒ³ Ñ'˜™-(OŽ,^ëA. Nõ$w™G­.ìøè˜Q•A5ÜÎ#ÿ ýÇ C¾Ïb^Ô‡Sý©ØcâÝ„ä/ÀŸÕÓ1“UæëN·2åÍœ5gÐQ=ç:ùåfOhâgªn´±Oë*K]qe?:HtÄ-Ð×Äéûù—³Ñ‹ÌÓ¤ :¾æ~Ë^ ¨¹«·i”cJÃ\'Ìäzû„Èj8Hùž¨†XÓÍ*)ƒªs´ŠÍ¨q%ºj8·pãƒIˆ—kõ”¶:ŸóÅʶ‚dÌrI­ÆŽúº {XÌøë顊ãÓÕ6ñ„pƒâ'Â6›µU(†¤¡8El~oj6™ØÖ4±øiIgäÂ0hd\[ 9Aé–ëi dU<·ÀóvsÉæªI$³¹Xzkád¡—óËŒ¢ÿH •®vr˜u§*Á1;º6O@ÒÓŒ/ EBDP’ÓQ‡Æ°ÒúóÔÈ¡.kvÙe¶¶6ˆùb9X€}avwµ\)£ÖÞQ¯”T\¯r¥ã£•R“†)\z™EkŠÊ59òáÂÞõ#¬<‹œ0[5lf ȶ$–_oÍ9ÎVòÂQ!{@l½´Àá˜oR 8_®î 7rE*妻ŠÔoK!sáS´>…œ'4ú;àŽ;ݸbNJ꣌kªˆËOF¨É¸Æ–çǽËçÐO]­³¡£yɿе5ÙY· ¸0›z»ÆmŒ&êQŒ Úi99ŒJ˜»õ|À£78Ú£¯vta¾±/ZZzÍí"ÒìÑí-¯T‘&Ö2¶œœhô´š—,â\ìd:Déá2¥­áéPTøþXúò”̰1÷¿Vо>ŽÜ[7‡¢æS7§cu³ Á¯Y¡o‘ ÷Ó,2p‡-2Àî¨ÆŸ¡VÒ; ß¾h#—Ö[‹cpÏ dãã¼;žÌ]¸k±°ïrLŒ9ª&pàaGÎIîuÕP¥ñE¯R–\ªŒFµ$µ?Q°AP+qôçq4¦X˜µ¯‹!›w[LyIE£Rÿj½VûÊy4÷E­+ S9?HÊØç?¥*Ä¡X„Ü?Ùåñ"¿íÛ'#þ4)¬ØVf&[¶Ñ2½€sH×%hñšçYéý-õ0ÅgBÔq¹ÓÞ³9l¥bKýÊë>½:íyM&µ™‹VBöìU6~þ"=ؼb2 ªð¥ÀH‡‚ŽÑÏ\ɯúÜÕ_‹‘ÅšWÆ›‚ kþ[öRúo©Wô8éC˜ÂSvÕš³¿9´v™*Œ#›í­ ¹ÿ„EÞ"߃ Kd™÷S.J}c%‚ˆ/Y X±3hÊC¢tÜ7%S[*ÚÆJʲîÑy2 6½—ÃìöQhÊÁ.Ê1m¦L³Œf'¿evF 5ö¬¥›ŽJ,S…Æ_‹aŽüó®Rç1eêåñßVÃUìa ]¾ÒTý`¬Ä±ó\uþ°ç¬I…:¸çÄc* $ºF½Òç—Rjm~-!M{Ѻ³CÒ¬Û T»«'”EJ®½ûXdj‘¯ºFæ*‘d鮈ٌ<ÐVÙ†.‘…­V±Êɰ—‹£U‹^ ^zTŽÀÉo;Àö©X4)}Šãž°Uƒ2+Vw?TœUï »(iUm›) 1p¼c“šVlªm[iRžU¡MÛ`Ú³…j’ L~¿(“Ôbù–cV\£Z4Ëí}Œq¹ß²öÚ7lk×Z0.R·ÙuóBÄì‰Ko±µÚŒUÎR›mW<*ʃ,k½¸õZ< zÖ޴³‘üE·E,êÎýjG`›?ĉ#¤UÉã“bY$šè•×äAGšb;D]g»R™>î.Š32ƈøEtÇãä XbóOüŒVöò*Þ}TFX§t’·÷~ ¨¹,"À…@ÍÇJ]¼ø¨^¼ÊI'à*~@dÑ/¾ëiŽó¼lo\%JA®¦Yà7òíçí8ÚÜéÁÙÑèxçºRÆøuYî_4÷÷]|3Úøãò °Dòàê Ç|ãƒnËÅgõ"íÓ£Sй°tÿÏõþçåâ§õâá'uˆo‰±þ¡þ|bšée³©úE® ‹º¾«WƼnÈO?c 'm äŠEjéí'"‘Þ4t.o æT‰yÑŠõ,JCvÆ­‹÷ÂÎk.+ËÃfŸ.^7{)Z2 þãrÿ¼Þÿ[¹ø—zñ“$Š @G2ÿ‚ëU¾x1R„,ôa󛌂KÍuŠú§¬>àêùÉ¥PÅ×`G¢v»†ÏR,vƒôt“(1ú/ gšÿ¶ü‰ˆêâk¶wBÔ" D-úò ¢þ‚¨UðiDkrß# þ‚¥ï K³~\¯6ë“aÑH"#ù4Œa¢ýzÀƒwè9žŒ1ÿÇšµoï² À ×(ŒÀ0Ë#ìbºõžC°Å+&;å$}0¿ƒ {É„Š.åèœÏMy±°èYòî-_+¡ž@Á ¾]• OÊšÉúúNIj7=í’øžjתrú+%&~nø¸WJR{ÀÝ_)Ùè#bõ­i*Pš0þ$QþÀE‚£?;3výE€Øráþ‡_ãLm¬‡ÛÝ0i®¥Ø½_pÂ7÷çôÆDÀo®~962\ý†ž˜÷@9}Ææ_{_I<Ô΀ïÙÆY êû©øQV8òuš"89¾Å*ÌÑß*<æK¿Þ–:ÑWEo—UÚÓ? ‘>¸³Øf¬I:ûÒ*Í?~˜ê1§½=þZ I¤¤/ɰ3«·9È]¹x¥6Ä–ÐQ‹s]g\qet‹/è1E ½Iol~r~ï¯ðϰ® eendstream endobj 598 0 obj 5081 endobj 602 0 obj <> stream xœíˆ0ŽÁ±ßï¦p¿ý3~‡q Û‹§Gg`ˆbœl̳ب·_ïÎõö..®k`£a¥·ß lZkï·¬ß]À!F•— VÀåïâŸÖ;• 5ý÷Åv'Ž6ëÂ0N€¹‹«Œ­¸s8òÜê8LvsnÆ!¨Ó€=¢ÃmÙ9;¯'hpÛ§¿7 ™hààœÞþ+üTjÐfû9 ~¾Óapv£ë õG^úÄ ·“Ó •ßþ¸ÝÀ¸× æ¬3]Ãè×ÔŒiP(Öø¸ÞÓh“޳;æIYûU"œì…œâå þù Nqð>x X§@•¶—¸øÒÚí£[éØá)k`çËñ¿B²q.NŽ–¡/hBéCœHÊ”ÕÝËê@Z|õÅc:Àè,üjðp‚±KE8ä†Ï‹û<Ì«U=mì¾î_4e´é8hùÑF͹2ðϨ†N#|βó|])5cfÈ[SZ·iË!’ÿ?îP LÃ#Ÿ=ïÝÃfëWm"6{!Œã挫&éˆlk ±Úˆ?HCG²µn‚8£—ógþÅù-ÊÂó;ÎÙoÏÓº€í¯MÖõxórgŒ³ÄÆz¢ÔËÊ<¸´@=Œ DÜBt๛ölba‰4±óA’T¦ÊÔ«A9üßî|mB,ð#EåÙ5pò#Xdmœ3ˆw;]ÑIR@s²dŸ^uV¾ÕºŸwº¯)ð·+² »`o\nß4FH¨òp4Ä %Ä fÒ‰L ÎýÉB|ã9…Ùþ?'@¡ö„w7Þ BÕZ ý2ñ”qä:®›„õ£]JWüòªñ(x¢”eVâLR"..Ù‰¥‘ÍõÎqA¤zÚD)b„ß„3'c¾¶R: «zK¬Êà©Ýl¿KUÒ RC4Yÿ¸«.+Í^KË‘xW¢gŽ1Êtè²æPòˆqò§_û.dɼAœ Ãó¶dÕ5¢š©$lêÚBŒ@¤GJnê³"ö¨[ãÏŒ´o$™õ˜k¤|Ý´³˜³m"3¨ï&¥ †s±.ñ{¦¨ÔŽ4séˆ+¨€ÍÅ×gŸÿ…ìþ´;¯âHÇ@RP{ÏpȘBOƒÞmœÂÒÂx+³¡Ý¸—òªs´ ŠÊ6žŹbâé‰DòÜpÁ­~Ƥ•ŽéNFl…¬Ú ÚQ20˜‡©5ßÃ^Xôû4fTÔèÁƒá-£ˆÂ&#§£‚E0kAf‡ ³ƒ’êJ‡‘,ÇŽál˜ß”-nX¾4ÅÜ äZK0O#`Ó¬ÌXÍ“k?-MD’ÛjZÜLöõ Ùâ03qµ,iæÇMª2å$mÝ«’úlÇž‹YZÙZ.ó2Ù^&ŒH#ÉÀëŠí_wMLËéx.b³9`œŒë Õâ¼Á´ªÏÌ:$ÁZ@zÚ79Ñ•“]Q–× Ül½ÌÎPP3[âÛã¬ÅÜõªPÆ2Иœ<‰ÙåMZiud¥Ú˜T-*‰óäP(Ê=¢—Û7É^†¡…(UÝFÔß(ñºªÙLδ™«Ñuî’ ’Ц#?:#äˆ#ý<®ûLí§K­ÏN…EP–#KÔþu€-ø"NL%müº>¶3#`lÎÙŒb5¸|X&e¥«áüÿ×ÎD$´~ ¬]5#PŒ=HÓ ­ çNóõÃì;± ÷èP†¹dsªGäH÷of/c!&0/™)’,`4´ ¹¯”r:kᢇ ;~`QBIqáÛÃD(þý• Cê™4%ÈËf432³€ Ræ3ªâÒW˜‚ð<¥€‹JxòhQfÄØæF2c,þIÿ¡š0!ñÌšNêͺ¥¾1:ÆL¦<ïQ"â\:´›ÞO6ƒ`Õ”,«,äy°£ëZ£ªÅSîÛ*W=(WÂ3¼Æi…JävÉpp°|sþ’Mä g¬ÊB¿å´õå#í¼4fØüÐî[Še»‘b5„iƒá–¹G&ŒÀ¤I€8ýà 2EP-k¾åJA¼±RsMßtã= @dly{at35Ò,­åÎb$hè÷"0(æOÂMOnÛ1Gµk‚ãð}š÷D<ÍW] c ±Êj Û$%ò®†SiEù0(¸³×‰“Û®»*¹“Pbø­ûwÜÉŠ¤)¶St5ÖxÓˆs)t¸ì%_Ão~Ð'»ÌÅâìâ—àzvÀ»].Ã.l,ä³uÕ¢B<œI)"üX08Y“K×&ꆙNé)tIük*?*²Îs¸è}æ¨Ì®ˆ.OÌx £”²³xöó´*Z:c=ÐSW‚+ÊÀcZáVV#bŠKUÒd»{qöÝÙÏcÈý7°‡ic¢®œ6N‡_á…ò÷ÏîÜÿÏÍë—7Îîüi£Îîüÿï‹oÿÜÿróOgwïo¾[¿f–÷¥åšÙÄ88Ò! æ»ædàf†¨Ì¸ «UàÙL¿¬V¡$¬•q›xÍj©«9üo+ˆ5ã$¬]1"#£ËG1)‹VZßš¸øô[qägÇÐ L3#E¸‰W,¾#‡à^8ôAØ!&t¢ffüòòc(L}άôe=¼®‘Ân1ecb |Ádzb,¯‚¥j$›Ðæ <ºé'ð€ãqˆLíþÝÒ/Ë¢©DSfÒ¾kÓ,Ý goÑ‹+÷âr¦bagœo”ÍÎö̬²Ù®Šk;"Yf©+}™íŸóº)“Ä(ÃÉló@"œò!ÖŒL !"@ÓŒn³xÿ`=¦<>²2Qè ¥«Rú“Â?b/vAв³:'õ\Ö9÷uN0œŠä–?Éëj_6^öþœw³m€V†?,ë¿X%>Ž %‹þòëÖx12Áš‹•§â+ü‰Ù:Nî¶}eìUmí&(žkèÕ£™©fVë¤ãß!´.å\ aÂï„… ½#iÕã$*vmv¿$>O‘*é0RåÌ’Š>ÔK¬7¹QÆAWRûNâ{ÙLËÈ=s OÉ–cùeÑ™3I)útõ¤Z)–å+RÄ´]gŸxònZfÑÌB­1]Ÿ#î .ô“ó ¸Í‹;—t‹¥ý“¶›vw¦ïÚ´\Ð}”Äâÿž'TȘÉûÇޗׯl.LÎäMmJèçDå[ïòÓ‹¥)‹ÔÈãÐýhÎñ«,3ª¡5&ë¡AdØJË=gõÊ”‘ѼíÂ~ÜW/¼K=æ9.£¥ôª”Ǧîp.3À¢^-.¢fJãYŒ‹ÚiÀlôµ{tÀiãÚnu¼H‘M¨€3R=ü´q&Jzn*»£CpæÐ3uéyøC TD`¹êÅÎ7\ß=¬¶-9MÓýOñ7’ ±ÏÖ…I—Ò’zÚ,×;¤êÒ¼Lm7Ïôò/ÜšA½†°Jþq›'bPV‹„w<Í &+Åm?¯Ý/äw´§Ûy 0R¤U0tuØ®ë6¾mͶkÆÔílP²ÏáÕ›‘Ãì‘§½šÇ<§b¤€núºöÓúÿP¿jÇG–Övs­Š1óJlª  h?ˆØªº®Û7¿ ð ¢¾n­ªò™ÜÀѱÈmï þÒÜË6^i•À¬¹”Hbg‘%ÄwòÔÉd¸'L/;ò•DfÊBóíÜûþÌ«FñðyL©ÿ¢õÿ¹6~ÛïS×[ =fþþÒc‘§œp3Ä^[ãð¥ûöVà 0Å1öû\LÅœŒrêoy낪oº”r»1ГŤ€)r–Ĉ“í»$z³ø ÇÒå §F¯(E Ô„úÔDžú¦’/ªŽ€©F‘T‡ëz ׯ«CêÈèè¿B{–$þ UȧÑ*¸M?î}ô²\N×XOB·ì~+rò5¢¾ÊR¨ ­R(Z×Dj¡^zÒ]ª•äBü U †«ìF©!:¼ÒC_ÄSv(tUãvàÅÆ,úV௚ PæÁÃÀs¥4xgqû=ú•£¡dQƒ736Ý¥XË`Y/^&:ŒnÁ·QLgɳ¤&EéÇx{¬GŸ æS6RiÄÛµk€ÁŽ£¦ÚHª" •šÀ;)Ö‘VA>Ao 2iÇ„qRld]œ-yS¾NÎùüN‘Ńin28¿yÿ µ¿N¹Ø¥Ìb§QŽ!å´ T7¸Ö©žÀqÌ÷Jkõb³Ú Œ¤”|WïWjÁd@°_ ÆæÕ:kîw³“ª1ûǘ&3¾ PË0Öð‡áIHÇÃsò’“%ï–šsênA,ÊãεòƒÒ¢âç]2Ùq‡HqóôÞe Êž">d'‹Ù YÈ0 ×Òyl’ :åÜ3ø»eJ%¥Ú©eÌæ¤*7£Óüh[E ²M/Û¾ZAëѤèp7ñE7ïŒ'ð— ³E}â,rƒû’¹óÇR Jä‹ µuÁåú”^‚j@fGO|.¤Hà<‹rQ¦ÝšZF¯…W¼œ— )ouιZ7?°po‡ãƒ%ߢ`»vTÓgçäþS'À+Ê ¨<.¥s&ï’u)"Îùé Ê~5v/ËìqNtAÓRºdô9ôªA.Þÿ„¤[vY¿;áe™—ß«vi½×éPù™+ËÞ™U™$”-\;"æ #!•LM 33òÌ•’‡/+%éŽEqþ`aï¿ÖIºwj×»üD-©j{ŠÆ³Ì ¡YfÉÉæbb¥–íT*/Wmå—)¦=Æõ\ßÓö³wAºD[à·fE˜œRÞÍ®³¨LÒ¤pSÚ#^šñŠBùŽIfƒÕ‹®|Ò/gÊøCød¤¼(n\ + ÃLTÇò%ßÔæn-✕ØC&)±–¢k'¿’së ›ç$$‹ÞYÖ•à(FäéÞ•eñ’œuf]°ã€(î^î¬ÝwYÖXn#L¥øSùuÕI9´¹èªŸŠ—Š­æEv\Ð[w2ùÈtvùðÈâ ƒk–®ì„àe9Ó-Ú™NÃT–qö2«®W¹"ž¦Í¸¨Ì»œËQµ™oeáp!íùE~<üNaF‘©ÙÊ3Í8~«ö´cë‰2HM‚UÙ3$¬?λnVÿ˜ïk× F×Ä ãìú寸8w†4Cü0|?—ôÀc à°³% Vå׫’±©j•K„dË mþú8¢¡œù²:?йŸ^"’ŸñÂu:ñqtóg¨üÈðLënuÌÁK„0¿ü"­:—äöµ%áFº;=>(|¢TÊ#Ù0LJÓzù øIWLÌò0BëW5=<ã"ÿjY«\^Æ)Ô<t9]ŠÜ:êwd°‘KÉRŽJðºÐ(ú ߉©Ç| ¥`iŸ‚‘„ú¶Å¿áÇ镽Ïvõ£÷ÉÖJŒ2ÅÒ÷y¦H>ÏÚcå%ÞÛI‚ì™÷ S½Kkc–Fꢌ ÏÔœwþ&É­U—¨iÊÈÓwÐêG™kQR¹¼hœÀpíì$ˆ–3ÇJ™½`Ä{ܲb);hf¹në‘Ä­RèØh}®’¯T ’"©WJšöuù™·ƒÐu¼²ñSZq削Þ+mÇ^&싉Yíð¢Ì­Ì>ã’6gœøÓ\›JáΈ}(UAã™R_¡d½;Ü.«qN š:>Sy´¢Ë7}%T–jiƒ«…ÄóÇÂŒ+PÁâ)ÃNñ”ÒSI§"tö¢Ë0ß(kjÇÚ¦Tsª¦ÉÚë°¦AÃf‚¼,Ï:õÉ‚êéù5kúä[ž™ÿ ߘì&"ŠÜBºIINàqmDï=Æ­nÚˆ±žxIƒµ×uM üÑ—Ulb˜W7&ÃÿZ …„b*•?áÍ5² æå«EËÉ|ØY]2ã[¡Í0%6?Ÿ#™-sNvfBç=æRŠ*žjM˜^¨b>±s3.‡¸;CÁENØìA²åS­IØ©­|,†Ia¯5íCF¾‹ìLÙûA2³uñ’Ï»ëÆi¼L9%îÕJfºWS;Ó½~S€Y™l™™Â=…ô_M%~n•É7_ç@ ´CvfÙuB‰(Šeàç9NC.ñÒRGûýPít JKX 8ZÓ³ k'•¶Ü¿Åê¥@KÍÚãþ«Ý ,aßâUªò}¿«’ÄðT uöXY{¬+Ž•qÚiÍî͘tȵ *"/c!´V5TgG”ÒaûãKÖϯ#Øq"‚ê–Òv_”ÑÏ#µ¸åí¬:Ž^Íôw¿¼åðs·Œ&bWüݵÓé\œ7{&êô·Ëå¨Cîí”Âኽ‹ÎT8‹â°‡|Ÿ›oÏê\™ýø¡oþ”7¨uÌï—žõçh;mÀ¯Â>ÝkJÊm€­`:Cy@H½úóê8à@Ä¿ àøÖ”ÓJB¾$äà¸9QŠ­­•fù<yo/jiÿ±Ûª‹›ë¶ß¯â‡ÞtÖS½HÞuvxÝ §9Ï¿ÿñC8> stream xœÝ\YoÇÎ3¡±@¼cˆ£é»ADŽ+°4ò`Mê "–DÙʯOUŸU3=»CŠ´ƒÄˆ´š£Ï:¾úªz~Ú ½Ø ø_úûäüàÑ7B©Í‹7Ãæ¯ðÿ?ˆðÈ&ýur¾y|óp©‡QlŽžÄÄÆÉõºrst~ðýÖvf;tæŸGÃWüÀ^q¶—Þ::…'?éUïÜ8ŠígèÇÑëqûçNn¿êE¯µqr{TŸy¯*í·ßÀUÍn tÖw‡Îù^ ³}Üé^)i}hæÛîÐÀ NøíS|×ÃÿTèUA›ÖÒ|Úá/g]ztƒ£§¶ôhh[‡¤ì¥ókJ‰í—]76ø¤ÎÆ=ÀCFx = àX•IcñRh|šéµá%{1ºê¥”0ìï:Ùƒ‘"õ^šôO:MC—NÄ=QBÑ=9VÃt6‡° NŒcÜ›3hy{¼…×Å»£¶Ïñßgé¢Ú¾ÁÞ‡Aˆí¿ðŸõnxïÿ7^ã—åáŸÓ»Ú[hUoA¸™©ƒøü’(Þ’‹¯ëEÖ\ºˆÓƒÝq‡°¶Æ2Îæ‡-àÛòö~ãþñ 4Œýõq¹}Åß sz‹¢Úå3°zð+li6ŸR£ƒA*°bV†mÉ÷Ÿ¡%µ½ûêUØ tvÐ8 ’å¬ ³”ܘÏèQÂv© ï2hú §£B8/•;³ƒ­<ÁwÀO…»JÁ}åiOÇ]®Sª¾Fžx@§€ó“*ŒUi‰z@ÞnMV7×êªþ¼®?qÖ°äbû#üðàsdÔMŒšž«CÁ\Ô¹Õ¿ ƒ“R¹ÑÒÉ‚²ùäù’Ÿeè—]°ç#x%›¥¡N§íÊähz%ƒ¤É»÷cåqoJ+ÌŒÛ¦ó  ‚EÜçâž·LõŒâÿ™‹›X÷=^æÆÆ¶¾NÌÙùd ·6ŸdaW¯g¾õ-(Ùàµ&T­3¡ »}×µë˜*6±Õ6¡)E“â2YTÞÁÜF5Rf•—Ö¹†Ê£‘­ÏÎUÞ;MU>ö:¯­(ÿL]²!£`x‰¦fÙZ'èŽòï£]ÄQÔA%µŠ~ÕÄšb?Ö94,f¡_(ä6¡‹EÓlGœî M³ƒ8-/}uz¸ëjðˆÚÓãÄØ«8ã«þó} ‡JÓêµ8ÙÑäýâÊ9ÃŽcH í@Š`ˆ<2lⲋ£öbKFñ²>C–"Š€•ð6ŽJ`­®ŽàaNÌ»ëíÚŸáÂÞ¯:é`§Á1¿G9‚hS-#ØGDGÕ›§p „æ»C¡à€wß%cáE"cU.£(£µX”Š´ˆÍýÃÇ—E°Êƒâú7˜I`ʪw!º¼¿Q­Q©´š! °ŠUªð•(UAæ¥êuù"#InœÕTÚa¶÷`“Þw0[h>‚øA÷rY4S‹ÙɱýàYQ²ïD;Ⱥ¥¡¤6ê‹ónƒˆÇ)r×Näì¬Ú?b‡°Ãdz$WÐiã‰æØYÂh»¬ *š¥/Õ–pP`3?R«^%¯!Œ'åWz7cy5®±è¢1Ûq´è2`ð±Ù0b !.Ë{˜¨YÀ±-€Þ€ïd•0Ô:`™SÉm‚kÑ€H æZæó|Š,ûû&²ß¬ÑÏͺ!ÄprÙx§.VoXœPØÜ™–5FV;}—ǸSW£_H«Ã=C&Øø9Œ’x™c[gÚ1ì‚-Œ5åH§^$]½COãì ¡4d¦Ëaá#“§r#xªLæ9éU˜(ÀgîµO²¼ÀšÞ+°I„Þ"Àz“"‹¨\Ô8Š ™“©”¡w;c©7ÝÊ@à¾b©º"u|%´*QU¦“š,ëp$’'k€‡Aâ’KvÌ $6º&X#"ˆí­˜¯€ nH ×Mµ‡ù0ß{˜ð‚+Wȃ5Y`7Ç™W3¯Dƒ^Œ}R Kg¼–Ç^WJ©8ÑyXÌp‰Ê‰¦ì>ƒ²€Œ¢Îö2:5p®nÑzI/I©Óú“Ðg”fZ‚  °k¡à?“&‚£s8æ4z» ­æ¾³Sãç³ä¥‡ÞÏ}ôõlÐ×^4¦Î16Wƒ‡¹+ήš9ðêãó¦^·À@m“<‰œû¨C&í$7„+B|=Ú‡“}ùFbÎP_·Í$tÀ8Ø÷œ D„ Â;qçÊy '‹? ؾ­ºòYÇ’dß ì¡y7ltO¯þ¥Ã˜Ì“l)(@Ï| HlÈâD4ºãU„‰wÅwœ`±ª®q¨ºˆ¡<‘ŸÇA¬ÁK‘HYiÂ<&,„Fµ€vs|ÝæÈÙqB©ü±Nžüü²À‹ï2Œú»Œ×È:T‚ùǸ¦fF2‘‘ÌW"²ÞýM5H  À­Ò+ò+mž¢d5ÚB“µÛÿd™-ZÀb²€[ 7OËò“ˆ-ò#Yzq¥‡b§Ÿv`.œWÙcØ–†Ïe6‚<ܰjm«¯ö<7(À6Èrb¤Ñ2·¶´¶ÅÕY*˜ªÅ/±{M9ïÀ CL6YoWY×8.¼ZâvF$\¯SÿÔ‰ 7<5p<}pûÊ=‡õadÇÅsTÖh"bh’lÓ!p÷YY ˜½ð½õEªÉÚgÇh†ЊZQV\:£·é‘HQD“òYyÝQ5’œFâîâRp¤=£y@™=x—±,PÔϪ-ºÈ»ª’Ì g÷¨I1ÁW ´•mеE² Í26"4||IRwùb§Ê¤Á§¶àЂ¾”S똓Ÿb¶ü2 >xRñ2£ÓÑŽ+Ê'2]L3À½|rtðõÁO¥zJ€`Ê~£ ˆ²„¿]¬ñ99?xüôàÑÓ/6o__?;xô8xôþñø«O௧ÙüîàÉÓÍ×7-7RVBû;ê…5G-Øbk–Gï‡èïô!pà£_“>U3›Ô3aH«mÀ¯—µrï…{Ì8Ç &Z/BÊ,ÇÍÕ÷Ûæ <8Kââ;DÓ3LÑE³0˜ðJ&G÷6yQh]R ½œÙ¿3¹žþ¸}r9ðÇ…;8ɌLJIÕØü7b=Öd÷åTOËýfõIóâûzñв“´²Ð÷O_Üs‰¹?©¢Â2IpóÒ)PÓ´Y£l*ŒÉÇsv.Žæ¼ÜÈ"Ÿ¨¼Âf ðΩ×m?m­1‘…ÊS½ªßµàÕdág$‡5˜)·ÖþuKFÞ³E†ØÑ-Ë4ã⎙ ä={?»:a¤^ÕgkYB}%s\ZWÒa/1VZ¼Û cvÆ ›_¥@ÁÔL‚÷Z € T—.i5Zð¯–2PÄ=q÷ñJš‹Ø2LpÕ¶4c/5†ÁzœxŠŽí2C¨AÇqlѶæ—.öí<D°õ’”så¥Lô˨¡u´±Âl¯¤µ)x¤ 0»L‘VktÉ#äI_$/,[‚Šehî—`ŸB©µòÁ'ÍÐPõÒ9 (£ØËn±ô‘dÁ}^,ÑÞ¦€ñ¼³“3K¸ÒŒ»ÚW{)cñÈMøÕPM áø0V‚9ŒÞO„P K:ü{bS”kü¹“#üpÉ™¶Ó.•1ŠELK½¨Ÿi–w[µEƒ¡¤5>yÑU¥L3'=±™(RÄpF–%‚"Æ'Çim%áç@žGW9Ü ü@ŒkVÁ„/ŸýHÔ@˜&(¬($„ ºÅ`Ån2EI’êÑÑL yµÅÀÍ,|ªlÍÚ†´ª‘û´-M¦m»b‰í'Ú– }™¶)j —åð†ÚV“¿‡ åSN9÷kvTO¤ìô<3”¥½Ia¼NelÈ:ŒYÆyî‡XhVTXàE§tÅ O!CMªâÀÊ.¿7{§Q·À©gx+ÄižÜ˜S!‘$Û77¦Z™DÕ2,D 6>$u©ÜzŽmRӵܿj¿$U«hƒˆÅ$ˆ‡ôÑ®‰Ÿ$y‰‚… r˜ÅH)XI³÷ñ¹yÐʆJD&›fŸ ì[n•åwÖ¡ ê…pÉ”+p?VWà“évfwa;rå ͼ¬0¢…´’®ã®FˆôÖFXM½§&.§…IpC}—éŠP«X ÖÐj€õW\ú ˆOÇòÆ‘½J¼:6?¤3ÿâj#RIµ$¶D¾çƒƒf¿ˆX4°‰÷¸±&Ås FÉ!\kÀ(<$˜1›•ò ÎÒnó¨©åÜc"¾l¯Íˆó´õÁǼ(™…º8 ¹ˆ'9‡5µ„=‰MHjA—rÑ`4¤ÓD!Öå8&ųRÀ˜yηsAÉ`šU’yì&”^w,i…—iêìËß'«B4(±Æ© …#;ÂM6È;?ŽV£(úÞ~u\*cÊn;åWü¦ðbžõãµÈÓø‹TžÄÂwŸóÒ^×BúE½ÄÜ´s Î0;¸]ùQ:€²BÏð˜Ï\ÏBBÞÝé40:9kD!”)ôËëì«”Ÿºcþ÷DQ’;6¦ÅB$3¸߇’/èè…'Ó”8µ«+虘Á‡ óÅb½TSÖÆY8ÔZÔˆ RqøòÛÍjéH‘¬l%•k€CvŽa¹*~yTO£3"äfùaSÜäQ”7±ŽH„w'¦Ó óðƺe\ÂFi»ÞÑD£Ÿ¦¸dõ/+2Wa4Îü€ÉÌ ãpãp'g„›ø¸E½Lðq ö§d Y«õD™…R.0àÒUdjôj#1³i†‰s™ÔìIÌ~ì89˜èŒD>0X¿½B F«2.¾FQ5`¤ªÑҶ܉ª¡ thðì´€`T×â¡IT64@ÊÅÓ)e~1Í|eU\A³Dt]hÎ/·ùAî!‘ÔͧÉg ÃSƒÆÌ­`UEcxž/2†ä[AÉŸvr)G ã”ú}UÞºRX9tï/w:’ÝÊÈË}¯Lår—Ĉô&Laö6n²]81H"²ÛÂ¥ômŠ[&”ʼn˰xÆ@ø³9aÓ ÑÌkKHâ‰+!ìüM3P‘|WHXÒ¦=N†+å•ÚºÍ=ÈoU t]þɾú’Š5po¼ Ö®3PµÔ¥Y2q²\ tGŸLºÙ¨_íËwyØ*þ~\í+Z"Ó$5¤ª>ËëcÑäP8Û|ÿËf³çµôƒ,4/, &ÉÈ9…v2JvÙ¼¸RQ ò4µ§LZ¢¤—OM…ïˆAc–ýç£Fzˆu.:¹ÑŹÛu/„økåJ ÇLöŒ\˜c œ³”JXÛ«éÉPC¡}’³ú˜(pü‹EZ ä[œ2!vu~n=»s £aIË”ÂXBÃ1eÕ:€ËaÌ»V²fòAƒ2~±°, L~óhÁÃĬ’²o3Q-„ÅB£”;Z€¹Ç<·µ„7òBÝciLN2Hó˜jB9ˆ¯sѯӽõ#Bëý×Ók3R^[(ËN¥ZµŽà Röû¥wHÇäÝDòÈ F­Ãa©)æeG'Ÿ#_p0s©×ƒ†‚V8}gÓÍb1‰róM>êQävv$)f„‘$ï› ’+¦ pËŽH^n9—¥÷ÉÚ zÔµázþÉ¡³ÕlV·„ rù^ñ5º,ˆ\>sXC?F×(BLP˜ÙÚ]mcßqYFƒ9Ëâ–iÆtænLJmi±ÈS“iíÿ˜†²@,Oµy2¦ušfÒ0ÄlƒØñ uð¶ÇãdÆHÀ(’k"UEŒ.I±¯éÿU)±V<ûlcË9—¯þ ká 4endstream endobj 608 0 obj 4807 endobj 612 0 obj <> stream xœÕ\éo\EßÏĈO3Qæ¥ïc%d—¬B¸ Pä#±#|$qLŽ¿~«ú¬~¯ßŒØ™y¯êê:~UÕ=/là †ÿ¥Nwî|Ç¥\]ì°Å?áÿ£;<4Y¤Nww±™ÃGƒgž/vŸîÄøÂŠ…qjàb±{ºóóR¯ôrX‰ÁZ+—6|Y[çÁÜò³•X~¿ZëA)åõòóÕZÖ ®–÷ᣜ“á“`ƒ³&4ÿ¤83Ë»+5HɵÁv:xÛ`ÛïVÎÒ,Â~`Ì.wW@œ`ZB>xï”O£(/–Vk±¼‡“‹AIA ˜‡‹å×H›˜å¥ßn ØzÏÓôžÃ 8ý=üª”T./Ðr÷ëî¿we›Òv`8·{Ü2À ¾Ò±¥ä’¶\+¥ãkÉ˽=ž Ë3üó &âH“˧øýYz(—H'cœ/ã×ü³‡NÊ×Ëòu¯4}ÏñÏKüó¸|‚é²À™åÑj­¬öbyæ,Ìû?­ÍÊýúð¤<<¨—‡/˧v¾øY$à)2bÍå  ‘#¿,‘Æ–qœ‹öEXî šhp½¼Uޜ冱ßóÂɰüÛ°fïà•#ë:®4îÑ%K‚ÜÝ*ŸÔ–oèùa]÷íDt¯Ä<«-›•å‡Ý–'töL|%é¼¶¼¤Û?óyoö)Å Âs¬!ËÌMoÕ§Ïi[Üc (Ï ò²¾Øö4~TÒQFß.qL°(fЂGÁÑÞűƒ"å(›9¥ ¿IK»ßHKT– vðÎa",Ë*zF¹7•œžÈÓ]P–ç =émhè¨'DIŸõHºèÉÃK:Qúôºáv$‰¿I'ݽhØH(ÉÏëοn¶»X‡;»·~^~ ¶™) ÷ç­l2£ÊìáeyûË þ&›®yk©aIŽ|Ip Q¸ìJví?׃Gâ’|'Ç¡¹Yþ¾Ò*ºÍ=ð 'Ù‡^V‡‰Ï_­$¸=#‚tHÏ­èÃãÚß;ò.€íÖžü|´åB OB$}ÖŠh-*C¶Ý§a*µR!‡€m Ëœç@òݳArVG1N7ó²v:)óÖ1çi VÂIØ¥™D‘6<ùZMÎ òdóQ «l' 3´å•øÜ 6þ…U‹M ³Ñ‘DôD8S€&¬>òí Ù7$­+ÌDÚˆ”œO,è£!²öN lç^|í£™œJ:¢¦äIAëFÏÎW½Hùkä€ÍÂʨ(—É$!…ô~‹}l{”Ú§H™G‹Fš·FIûŒŒÊŠÁTÖ‹:í‹ MÜËFðFripÚ*‚åmÞ~]¥.[³¬žY*ç…> >aoR¶Ìc$ ݰ©Þkß:öZ•n”!ñ …µU0_;|Ù‘æè8|‹f·«d×-\ ‡!Ž%z…ŽÔ²Y'ïP^ûÚ™øã¬¢¤p>Áf– ˆ§‚Õü¨¶­bRy\¹·»óí΋…”ƒ ‘&Lî°}í†Ö°AlñëÝû;wîµxõòòÉÎ/øÎ/ñÏÝo>‡î±øÛνû‹oç£Ú‘{NQ­—îÁ^k-Ñ£Ÿö¬SÞðjaæé¶þ9t E6tWoqŽHå–€uòÇ!I7(Ãà Ÿ¯èÆ!q}¥N ÚðsºÏ}“2¶c¨IGÁ¿qzã"µUT§â®2Z“LÆéêóaÇÀ¤q…qYõ{I{ö£-×Â:´U¶ãÙóM­¾´<šƳ{Q§¶ƒƒF‰«øQô„aß;;Qíé0C‚P2)²T2£É^¢ý Sô}d:„à]cÕ8¯®@¡L¢jH"É’èôí1QÛ?£ØÓ4ý¤&~ð#¨1J>ƒAnãW˜”›9×F°¥”:º³V (! $2˜ÑJRf¹Š"üœÌ €Ë‹ ž$‡Þ­:°!êç›$76D1ï‘mz•²,4¦z\ž5¨õÎ`ÒI’• &ÑjM?lI¨üQ™¢§%)ÐfBhÚæ ù¡šùüPÝûé†Óò~¯7üa/ pZ‡ÿ´nƶ™nõm‚èßvsAm*'¤W¼§‰‚&»p¤B‡—Ôᨛk:›ŒQÑIwÖÓ†Í@Ùœ¤¶3œŸ™m¯Îö¦a|'×q»´Ð,Ξ”ÜSPÍ’TI‰«³’¸zC…,)dYŽi7ód/ÛìËT”êÃË^î(äJJÞÑŠZpàAF =™ý–^±Azo•SÅÁƒ8ÊŽBÐfÀès1¦Ç"¸|i™Cš‚y¥¦—`óŒOu æ–q]pÅÎAgµ¼¬½T=Uêq–{”ÓWèÂbž ¢kÆoÔT ¸ìþ—8°±ÜšÚûz3P™ ÿjàÊBÒý(ïÐÁ„4—†£ÿ©Q)ë â'fõ i‡3¾Ãix6A§)ITx3Y¡äèÎà‘VUº» -ˆ>§ÚRàÏÙ8æC‰ª”ã…žª¸ÿ“ê¿b:/3Æzã #·k«iv "‘ühN„5® 9~‹ï9ìÃÝa5JkðTÝ:Iè4±pÃ×êIq„á9U Èï úÉ#|CV6 ÆTÈ^wQ«ã G …€]$YŸgEà‘fÓp"`¡>v=],kâô 90Š}pw5šM^a”åè€q"ƒØŸä½’[ ßS€¤Û¼@°u€FyMàV8)R¦+°¨µà{iÁ>gU0¶ÇuíÇÙ0E“tÂU‘k2½çuÄÉ]]H>Í"+ˆ,ŒÉɋ̥^ˆ¸·Òi¶ØË¶ÑZîJ–7M7!‘‘½⑽Fß*¸G{°¡Æà#›´ R\y1U·(R§‘n7Yfpj ‘K|Þ¯#¤1çW+#|^-f…üN‰$ê(Ä>k;áEˆ[·å‚6˜ LQ)<î›Ü…í¦A8L¥½Cö*«‰Ò…(ÇY´å$÷±… h^ˆñMQ&¶r!ìÔpA˜!Ýïpñ¬¾¾H&&›ÊÕ»²Ü3øS/hÖ*«EjP_vÀê'˜g/ šÕ¤jÞ¬E7[PÈä§Íp­GщZ"&ÙÊ3|›Æ®!‰éÍ(í±ßÊ‘Ƕ0ÀTÒÌðUÀŒ™iŒbBÕ7–³Âý¦<:k¡fÂ…o2á"^ˆ?;_éQbe’½ß§XdîÃZûY~¢i ¾crà@Û¢:™r<áÂÑm“1¡ ýr[!à:+Š–V¡WÏ*AôHfhB_qÌ»©fkÔ¬gÒÞ)ä •n„¼pö§'UâÒZ´0c'²9Ÿ­€a)©v›&Ë3¤0ÐKÞ—‚ÌË0çh9<äÖ]ïÃ÷¶"Їï°0ÌÁÏÏ&DŸàT¥’Ȥ¤WEÐ@Œ ZƒèÂKe.nzPB[Àô[—üy¥÷›T÷·xl ¬®óÌÂV’sdÿˆ²]½(²þI¬Ð ©—¯êÉ·¯`bc4`È8€f••Ê„©›šŠÔSªŒ¤ »Ÿ>ŽÇÕÖ™²VTë.xKêW¯Wh"xÜQ˜r˜ŠíÒÓðï¸JyÙá轤ŠgwŒ ÒVöm>rA¡Å˜ÀêP=3ab‚¾\»Ñ]7"ëvÂUj´²-QôŽ{³Ü?­€%w®bby%ø/´¼¤[¬ØÀêY¨Ál[™e\ 6¤cVœq´ ¯8Ø‘’‰›kqßJy»s&A;j%Ðã+á]/lK-a'Á'yÂãµé ù\áXk&°a\üí[üL¨²s ¡G"cÆgв–l‘gM‰°Ú%N¯=ÐÓÀÆG ù·SâAÚåOé+–3äò?Èc1!<¹s@ŽÄÌÆU£ãl5;Ó`áñùM Œþï@„—¸rï]Ìɦd—öI´5±Qý¥ˆÇDÇ@©  ö:5ˆ¦€É|ˆo»2“ÔQò±:¢P6úˆEìšÁê‹´æ‰>ü û8Ä<¼£YådZn$mG1ÓHÉ÷>\+¬ëåÞ -;#æk,,££)>úËy“Æ…‡½2L#J!u´!Ô˼Ž>Aê S^ô©‡‰¢ÇÌ߯Jˆ‘ £ÉXÑ¿\s¦Ç»•ÁMZK¼„t­£0J†DG´ƒÝó) F¢3§¹ê´C7íû †-ƈŽQ‰"SÛZáÙ)@sÓõ-t-Ñ”gitäýXÐtüFsÉJË]ÔÈp²u°u¸ºõ`ÅY¼ ñãŠcÙi"d˜z‰ ÷Ë`xäzRÂ’&p N l·y!¸µvCp»ÉÖR¼«£Õ¤ÍÛÀrbŒžP AZ8zqœâ£(­9W‚´ù,Ùi8F<{¼9Hk l"¿µ§ÓzlÌýÆkJm ù=-_éšÅùf€ì^eH;Mn ’ÑÐdT }D$`üæt˜ EˆbÀÑ…Ûx÷Fs^†"]Že·YÏ’,gÍÞóÈñ$ ­€ÀÅ—;s<2³•³TÞYµ„ê^)G:0W°„+AáÉm‰tí,ÜŠi¯`:+™©ì{Ý4A¯Üˆñ^0îñ¬ÆìUZrC—¼‰Iˆât6ÉÊŒB;Ì¢ÄcEä £3!Û–kËé*J?\‹Õéà¡ÍÛ´à2FX¥¿G`ÞÏ„uåNß„¾º—‚pÏ›¢[h|[«XøX½lÏŒ§à„SùêÕƒ ¤\Œr~¨ÕÁÈÅI<>MÂ\-ÆË—ƒÐ[Ä<9pk|ß#É÷ªS‚ùaÉ}Ï Ö°GR‚ûNŤ¹UêÖS§ê}ë„êbž¿›•ˆ—hHmïCÔ¹´±1^ Å Ón^¨µVÊdžüÓÌ^¥5÷Š#NäÕlE¼ùSŽ¿I©¢lÁ怿V‡* Qý÷`HS/V,"ÎÁmÍhS28,b¥jÿ>´nâçµ üªr¤qC=)·Ñ™¸pˆMõuàJÅÔãÝ,?Q=£ú0KŽAŸŸ éÄçw²Íñ¸b€¶•ïBV^ÈÙsv‰á\*Œy= Š­“¹Š–K£¥¦+ëB’$Û~OˆÛciY€Æd0N©Ø˜q<üÆó®ŒY£·Zˆ¦Ô™*hÁ€‹ã¸Z–ë{qU­9¾ÌÔœrì)\\«4˜°U•Ç^æ w¢ I‹ö« #ˆ8-“wóyí¯ñ• 05mžøò7ýáÅ~îVÎð§¡ë$R< h€M¶¼þä9ŸßüjD<ünF?˜@Žûã®ÇèõrÈ˼ˆåßÓôàçuFËÕ€^ûÎFþ-†­w6@ˆðæ ^üº>\¯Ê­ˆçå=¹‰0wUbzÑãe¾Ô ÈûsžÃç™3÷ûåa{g!矌”hÞ§ÓO¶7¦ÔšÁžX©½ãp§¹tò/+t…¹½¢@—¯(Hˆ”7mþò ÙŽJ;¹ŽPïÀì7 ]Æa–üªÅÓ:K•ß7½î ¦?lsNwkq„ÛU,YÊ$Õ>n% ±u¿‘ÅÑM´…³;9¡i7r†\`9jFÂÔX+ù78H°9ÿS+áÍyQຑ¡aµ?ã¬/-_ÿQ?¨óß+R™_ÿX~V>(è ôks=‡kÎæå2 ä:Šh‚îé<ë‰K{q¨Ê"z¿Œ˜íò•wwz'iþ'tP-çqwÌñšÔrZÕ_§—­ê–½½Ì®¨jÄòIÕ¿[e¯ŸµBP¨5ùüWñ¾ûÓ6¯g¬{¶Éû½N—½ù³#ÅêkÇúww™Xÿ§Íz()énÚ“îæÔÍ?^•[sí¥Á‘MÁ¶éÌ;ààzýcÖ1¬S»¶¾ðÒ1ºÔö¿$—½ñžÿåÒ1¾9ªÿ9 ÂQ,/Âq±¢¿ü4''±Ë‡X‘‚w‰¹(ÏÞÒÈNøõ*®þ*Ù™ƒcÙ­_ôÞ¿k€]Ý)DìqTêIO ’¹ž]¯!0c4Å›@kþÿ€€Òx˜[ޤ&!ø)F½I©É¿÷[ÏÀ¼-_÷Æ$?¡vHU%q«q8-'Û¹“ÒĹ»y-?òíÎNÁÔ³endstream endobj 613 0 obj 5158 endobj 617 0 obj <> stream xœí[YsE~ׯÐã´ÃÓtÝUû ,l¼ ò†q:ÐH²lIØðë7³Î¬žêé^ˆ°ÏTב•ùeVÕov‡žíø7þx±óÉwLˆÝ“ëa÷ðïdçÍó]vㇻŸíùnšz78¶»w¼&`»†ïj+{Æw÷.v^.t§¼S¯öþ‰CìP 1ºçFíAÏ¿wKÑã[|Õ±Þ9+ÝâÓŽ/þÕ-Y/¥2|±Wú|Z…´‹ï UÀ´ ‹õÝÒÛs¦Ÿu²‚kë§ù¾[*`˜]|c-ü~UsjM ø²ÃoF›ØÕ±ÁÐÅã\Ò):×sèÀyÏ…KÄ`‹o»L7NøEÙ Ð=@'Å,‡Ã.H«P‘Ë™Ä0M/•ƒ‚÷l`Ü/ÕsÎìï‡AqWñƒFë“E#éܰ Á•É’Ià½Þ]C s.Èæf^œâÇ>~¼…9ø«ÚÅEn|—HÂ00ÚüÓ_ðã%~Hüx•~™;?ë–%nµßnhü6û¹<þOnü´4>Ë/Z½*O»¥TšÅâ“üü l8< ù;[,±˜âÄâuîvU¦¹Ég¥±ô¼,û¹ñ–vÖ3í×ÜøKéù{n|ךómi<Ê×@çàÇÕ€ô¥Ä\ï¬9 °…€åeÒ·ýÒE§µ‚®È‹ÔúIþŠƒ—qô`ªôÀç€q€¿Ï&>ãÏ Œƒ0å‘^),ΘZI‡?ÊW ˜)%f@¤Tφ”³a=´e‹[ü¸)ã®òVÒØ4ÿ$£M>LÝäo¾Ë5~ü >fz†K×8.@½‰Ì ?ÁßáÈm”Sc¤Ø¯ ØázÀ1#ì *€1~¾‚Ã܈åœn95^ÐE .×÷<¨„² “ëÜø´@”P@ñ˜¶Sk¤¬b¼¬~TˆŸGų½'/=;ã=»OŠiy’óÁ“‰ŒÒö"aHï¦"¹#OÓ®Š>oÌ©ë´%ãñWć—…ˆ­.Ð9-ÃO[ 1ß´ìÆIe’šïW›—΀>«ÑY1²Ñ:xNÕ“òE¡'E ’ݧ$›¤ƒxË)Q±&KvS±¥"šö®ef½0-î‡È ºm!ü(‘=€*- dbî/8rªf3¸^l¿Ôb‹zh±•>ïï ¶Âlr¸^}Û#‰­vÖ²uŠmäã¤È®7•â»›ŽZl:-Rl äqžLÖ¼&<^Åe±PÕQDÎuB±´ø.)D/Ó+é°Úæ'ÑŸ‡MCà8áÉOXç9¼,ãœèI‘|³i¿è:;Z¬¢_äŸþÔEŸ "Ū(S@dŽÑå’Û^Û…Õx—ºr š «Ve ,× $ÁM¯¤eè)s`/GÂ嚇S2†êÈ\Ç{e$sÒqh•ðœq‚⤠Òô[AÑ•R#üJCØø€YôÙ…ÆÈ°ß1²ÇðÜPîà»RžX²ðQ¡ ~¸?Áe—üIÚ‡^`'×k•¶g„hn×­HÒïà¨õ7ôB~‡u¤T³ë”ç8ùAéCX ŒBO{b2‡Úë0ý w pÎ’¼w`AÔTÛKÅ5¡ÿ,-vYR<¨üvðšvPZCO§dêÊ ££ÂœK|ÂÇxr9éJaX¡ö:æ hi<¥x4ýü´±<ÏÀXB„aAe¹•½–lË$CdØPËË•·åIé~õ ëçìôÕlYטgRÊIæÁNjèïG8[Ð~mÊxlÃЊ£Š˜{/ BÓTÜ\+¿»w¥g~|^¾ ¢ç ›Ë2ÍëIÃzÆ0VKc&`llZbdÆfZÄ! Fäeàý`\RÂÅÛ‚œBdÛmPÁM¦K¯®%»%ŒÓÉnCíÎ@€‰Œ6&㋟yá<]ŸÕíÄgfÓ¯§h°Nùì$fgÌYL’º$)Û§ip~äIHØ+ç—нóƒfJc¾u0€èo€Z­¥VIòs¤ Ì ìŸÎEÒªÿ­ÓÑ1­*õxÀp‘`·@àà9JÏI ÆŠñ1 Ño‘ªó8ötÃvóC<¡@[Ø Ö!X(î)‚°6"*ÇXÁÉfÁ²zÈ 6OëµGÖûžÖüôª î<ø@àd—·"Yi!µ7ÒA§›†¸˜VÏj™”i–ë<£–¨[´S‚zz¤ *—l0©pXÍ,¼/¿›Úºîtõš0ó‰¥ÿ£ò{§`$Õ êòˆÛJxɲ7]y?(~éBÅ,ñ0jw+ù#eÛ$=¹kOž`6 -“'H<_¦(ç÷ù3E€¬ùe+‡'.=öIÂ’sCìù¬bópäSœRjŽcèT`»_A?±YO;.I Ù„kˆù¬4Ȉ\€íñ`'¤žôzâjÌÿÐ9¿w;6$™'ºQ¢0”€GOX 4Í-¡ö îäSÛÑuçW\œÞêäÕã㉈Ïè@Ÿ|ùÉxpË›ñÄM-·ÆK™Ä±¿÷õÅ´š%Oä ¡„q°¡GèyAì ÙèÔÉâ#Ú«RƒÆ‚cT‡ÚœzçBÕ~{ Á¶qÆãž"7¬à”{X"¾³Ö¶=I T@Jƒs„¢ÄëâTçJ#¤?l»ö`"yÒeáŠõ‚‡¼lÜc(Nk•kÏÎ)ê¯|DØÇ:Ff:!5(@2îÙ=)¾›ñ ÁÖ{½1®!ö”€¾íLá©{vìÛ.¬¼¾$C2%`^a~†V‡ßè ¹¤™°n²Ó2m£ d‚$ÍÈ«­‡4åúÐ’Ü" 7ÚN,~Í" ðž Ɇ‚c3ö\î›Ac 612¡oâÆ‚ê-&¬ð˜©èçœæMÊRåB2-õù#ú”áÁUFÚçyª’ ã­œàE•Ò[ÍMæ*w ÕçÅ*³ú¹O’´åÁyÌԆĦ ™ºÂ‰cš½Œ4¿My]ÂnæuWKß%ÿºµc’h/”6RöÖŒªŽqÁæLUA˜LŸÒÆ_å矗ç/ê¤ex^ç=UoôÀôÀ“@iò:ðùuÎ~ÞÔÝkfçÊët&ýƒsüõsWsÝ¥œBJòwå=Ö(fôômÍ~ÏÅ_»Tø=‚WÀi8Yë]åfу³ŠG«ùþ-vÿ»kEÔ,vì·fÊ4sºèYÕ¡”6«$5¥T—à S ^qá¶Ëc”à«2äêð¹ü\!pȨ̂¯µObÙžÕ[\E‘ÌŠÇg:©h%ØÞ©’zÇ›0´ †US'GZëi5ù¨jSíËNõ¢¢à_ëµ7œÖKpâٜcãóÒ¸ rmŠèm‹Åù˜™³,¤±ÿëŽÞçi÷Õ¢ŸZ±ÖWýÄfE¿”àÔ]$ÙNÁ *¸;ÐÔPñF‘ë0!Ëy áðŠíJ ;“°l¿$|ÐI=§éVœ2ì ˆ»¥`–Kµ›qêÍ­žL¡Ùá¡RhàrcmûZcšÏm' ®ÂœÈèr’ ÀK µó?£LUÜ͘ã>âIçî*ÂaFŦV¤9nP¿«*b•lŽAļú}ši¤ l@3ÐN* Øç= «¦E¢¨¥Qº[š-8m¤ÇЪ‚q@ÖÎEÆ©"·m®Vô ÐQÉ¥7$yÚvî”N…kHX…¯Ê>i›˜˜vtM¤Ö¥1¤EI>©?R„4MnùÄ#‹Å󶺞åè¿ÜÚ¥W«­_&è6 ÁÓ⃠›ø‚fb¡Ëzû5† ѹó2©@‘‚ÖT)˜c“*FØáj=ºe³Ñ¬ŒE0Œd@go3Ô§óˆ>EaM¸´»EK>Êñ’NEyˆž| ûÔ”.>”ù9E69†ˆáÍu~z‡mvÿ)^væþĽ_:!\L Gý(¤ÍÞÆÌ¿¯‹Ç}•GiK#qÇËE¯ónÕ1oú[^‚n|­=H#¸›vU¯fc ºK6â4?EÏÔÏÚDÄ•Ú=yMÄébæYÕ: ÷0n…{ÞÁÆÌ·þþÕ‡hüëX›m_šx¤€¼ö_0 ß (}ö*ü–X/Úï×2ý¿¿zr¯tÁVïžT©5$_¥›´#ùŸéÝ6Å[gR¶ñq“›Üœ5Îs 7 ¢_t<{LPu¥ .˜ôeð©ëƒéÞIô¿¥Õøï£Öˆvïx=6\3¨cƒ°„WTÁՃĴRø˜v®noHlú ”žbëï??±Â\¹Ç¿.†PDX.‘LÈñÆL©4’p%_sªÃ3Ò×—0…2½Üô‚G^² AâB1"l©!6û‘Ðèp\Gq†Y¹-uÕ? Žé=ïp]âhRù&ð¥I¥””Ûì8 Yb­š®ÿcF%࣢s×íÖìÅmTé†8•ëyй#™\L!1óçÐ*5}µþYguïoÕr>ÙÓhãþò¤m*éÜ–ïxÛÄß?ÓŒjlµ-¾æYÞ¨+×å.j;Ü\€½v÷÷Þv)¾½ƒÁÐù0ýµý)£6eÞiÜ6pûè¥ÿ5¼t¦´œ-ë<È»«[zëwªT_µM½š–ª@M.ÁѼy­ªãx¦¹w™Ó×Ó.¿·Éël’99ë‚?Æë\¹mtsóx¥Éÿ“ÂÕã ®Km-/ÃE@'&åSÔ˜ˆgÕ4ÔÒÑþnï ¾ØÛù7üý6”M¾endstream endobj 618 0 obj 3646 endobj 622 0 obj <> stream xœíÙnÇñðGð-3w<}w'0[±c;ŠœH´#’KR„x™¤æëSÕgõLÏr)ɈAÒlŸÕuWuÍü²;lwÄ?ñÿ£‹Ïž3!vOowÆÝ?ÃßÓ_v˜²ÿ;ºØýr‡YlÜèØîþÉNX€í¾«­ßÝ¿Øùg§zÕ =Œ1¢³þÇÊX7ðÑv?ô¼ÛïWb0–3Ù}Û¯Ø`­sª{ŠÎYéb«c£IcÙ(ºŸà‘"ºç½à¹ì¾Ç~ιÖtiN–~=_áO)•áÝ‹~¥àQ:õ¯ýïüá-=ŒF Û_Ãa4À/ú4R1:r‡®Ä8æ\˜¡zÑ\—©Áé‘§…¿ìå g¼;K¸ºèµ¤rÝ]/xÍY÷2CÛc¿ô¿é•Œæ¶;ÏÓ ¯é` OŒóî¦Y=()[‰·¢sR÷uy$[ÞÁ$å¤[XÔáá;,c2¨yÛyP¹ÝÕÂa.ú´6ZR(n‘¦¢UÝž‘'8¿!´Ž'•º{ë¹Ã8Ǻ›~…è—Ž ¿Àœac¤±…K[óB. ™~Õ#WˆqtbS€”‚€_à9Ì ñ?c¯a:=r$(Ìu÷0ÜH¬Ä1 ž®tc&6F8 ³zÄ÷ëÒS†GsÃê~ØG÷uˆ4Ú$Y‚Q¹~‘§ã¡W¤_ð݃Bð§Ïè"ÄÅ3#VDied÷s×âÏ)®-Œ,Œ|My25LÿÜçÖ¤¨‚È &*™µÂ¡„‹Á£%ÈWA‚!Š9¯“Nð÷Ylôp cÝ¿ñ'ÒNÿ¼Âð|¡ãešߦ>2=Á dU¶ã¨3­ösÈšó¸ŸtÀ3ÖtŸæîë´W˜wƒ?AŽ€™ …uŸå˜¢øm^aÃc·‚ÿ@éṯó°«M9Ðe ÄãÒ»ªÑzÈîèJiÃÒxP&æÆóÒxWr2ºïobèe\äá<-x×…¸?¥ó2PVy9p„C ‹øO­€eÁ SÓgù1RX9c…3-²R‹ªºl jæ%2客t&2È8 WýFˆ|•_·Vº.¯éÁü!€ˆ_çÆoËÈýÜø¢»€|QFâŸVܤ-ã(‹ÔËbùtgÿÓµpXÓ² Ò·½‹äÌâºÛ’cÝЦ¤”ÆûÒxMi”8è¤Eâ›rG¡.6þ¾ÐˆåF]Fî•åEîçÍþUi呱Û+T>®ÎŸQp5Œpäq‘Œ—Y¿k(l¤ A»±5/[‘[ؼ)Ø,sRv)Äxך~ۃ˖¦}Y+Õˆ‚—-¥Z)¢ç\qSq 9r0LŠ®z1‹®Y ÍÔfBzy•©yšÎµeMÒ,"“Th¥ao[øù]:(]9¡ž`𬷡^œþ?¢^Q.EC»ÍFÔªD§k“Zõ<Ê>§(ñ‘Ct¹å#$ó¨¥ËúMq½,’ùž‚M(’,¥÷óf ý¦5«Ðä¾@rNY/¼l·öŒâôϲ-5ï’w…º5K¥Gð²³3¹­ =ÉÎÍUObîm¡ýA&ñYM{Oq­AñB³¢ÎZt¬‰›HöëYRoZüÐäÌÂZ{… øã&• •‰ÛÑÀKþ\åyZÇåGAùیϳè*pbä²çͶùˆž£§Iž9{K±?ŸDDêeß¾ÚBä9IÎN6S¤)ÅÄ'vúë2ôinü¾4~Q…§éñY£ª?ÎÃiOCnQëÁåä"Yê+8«5ÞË\ä”Wv`ÌMR©!|bÈni–KÚŸøãס!õ5WfÓ p“•³,dû|›¹>»˜YÎEËÅd\?B0^µPqŸß.0\j\Á¨2n¸äÁÒLå&ò½'¥PüÓ ¬K ­s†ü\6Ì“ï¶ßd½vT»Š×ý{…í%ýDüÜãz¿ê =ˆ¼nQ¶³Ì©mÈÖ°và¡ðEð…ïÆLHìAa˜îá"Û‡’-ž,/³ƒ—VH1úm¦_ÍDr–Œ¦·lo#M™’0”oKÓ+Êóè¬Ež:"*Ê!%ÓZÔ½iÑô¾xÄÔií¦mœÓçe¡Ïçᔕ"NÆÂ¤Õ³‘7Çj-ÚÄòMkãÂ~šŠzÔ¥@lôÑhAA[>cüxA:Þ¼ÕEÕH<Â]Rb8$ñ¹«¸&=¾.òO ½7¶Q¾šÔY:Þ„£YFÄèÚf¦™ž¨²XsØ«uK'î[µ%^#Lþx Ô,–кxâÔt°Ï«i ·Û濚$,Ì~\›nôQ‹W‹[·È´þ %S÷^ËÖ:°!z7c´ÃW2-‹ë‚èmÎ_Ò”Ö£äÜT×|TH™¢Äšb2¹àûUËÒCWÝÍ…/hJŸ]ù¶Å]§­Æ¦×ZqW’ݳJ6=ð•›w;#ç\ö£ýšÆÖÞÁ´'ò{©Ï*Oåx¿´Ä¬öâÒ=u}i÷,7ÖÎql$¾1Gj»óë.¹cŵáŽïE;š œä.“ƒšûj ;cÔ ü/Aê¡ø0 „zÖ»Î䌛÷6 ®j|P’K¼ ÂXHrž§œå§»^ C*ŸíN ܸîy5$£á€J¿ŸŒöRH¦ålm\ç²tc£ÖÈpã€e+R‘#‚«”?"’ÈŽ,‰¶‚ÑÂ9Ú`èÙ „|Ùi#¥ÌŸW è×½H´EÉŽ½çþA«Pšã€¡”éžô«qPÂŒ5-Î(ý0ÒqƒA·—€„3§ ²#VÅBÂÉãŒP$ðÕs¬…àˆ"8årmËÈ;ìfÒi^»ô‚)²1n2ðf‘8UÖ8“Dêñ&åSÊúⲤ¶šºö+?\õ ÄoË2Ój4=%¤m ÀR‘©mÂA¥¨UÐVWËié«åJã¤FlV,—ê×P­;î&Em¤Æi©vŽŸyì„#¤%…Z*úËÀ­Ër8 QÏf»‡êÙŽ°¶L*mÚ Ýxã•Ï9q 1®i$…oí⽄\eåµ/X ÇÔ07‡pR³ö$0j‡oGÔø@h-ò6–ˆ36pæhQZ\kÚR}™¶0NdŸ»/z7Âx‹õtJÀONêØüºдf"µù£×ªõV¦1 až{”dÎ9c˜Éäžu:sbVR¥HKÛ„‚ÅM…MRðV¶ÀéRÝ8áЫÀHhf‰¡?ƒ GYp¢—¸<ð¥ÆòJÐÝJŽK5š•@¤Æ|®"À¥hclï%bFnUÚš!Á3`>Ká’j™»}1!ÇJÞŽÃߌMÜFJS… {‘‘¸®ºßžwȸŒ0½çi€f™'°ið s#‹(ÖÜäªZ¯S¼pJY‹FœBeÓsœ0N7d'¡]Ð •{Dž,ˆJƒ n¨Ø\—Ö¢opøA(˜^%LÕ2ÁÀêÚË&öA´ÀMમë-ÌÒv¤]Ó¢o<Z>©6)mœ_Ë·€.ªUÑwL¶GgÒŒË*>Ç}áÜλÀ¾‰OÐa±ãFF÷ÐË-…ÄcUGµÆ/@ئAó_6ÃB˜éÃ[²4’j€`'l©{¾ ï$¢í˲‡ñvzu3²¹¶qJF¡YĬŠo ˜&ŠpüëŠ×kaFR’-=-¿Îj‹µ3pë€',¹Ç É2¤bvÆñUßŃ„²ó¤8Ešyûç%, øc JŸ0{ËÂH\˜¤V¹‚vð¿Ö ¶Å2í†[DÌ^Íj´ÂTØÈ^G¹±’ñ&ç!ò@åKQ¿À=ác®¬ð^S!­½ ´Ù4ÜkxŒ¤ñ•®+‡‡«†`"ÒˆålÈ¥*sQ.½1Èüæ Î’ÁÊUòÂ''¼[Áer ¿À&êý€ð(ƒOP8~ò¦A,ÀO›W/¤ÉdxfpòÎ@«{F×båLÈáÀX”S”‰¾òš4îZ›oL a-š!¢°ZÛ Â¦G7 zW!)G™/é¤ÂûeF@áÄÀ Ÿ‡jƒca˜’TððoÊLRSø/øÈù(³j@T_4ÁþÉ)e„¯ï‰ÄD§Ô˜–WÊe}ptwFç9cIˆÐŠÑ;ù53ŠQ´½ÒÐ_à«åæWqFáÁù¢O/•7¼WþjT"ËaJV—^[ZtÿMmf"³íˆ"4*I½ªÛ=‡€á$Ä /§1 #SäÐý­¼‡†™œHU5¦àBÈ»jÏâKmãZÃf½ü5ÏÞñhµ©ˆ.‹ƒDxù3õ“Gö°›Œ!Î:ƒ=2‚Ú#«ù½x9o ã>Ð$ †šÌ(ïÌ=çhgÚ¯BV!_·ð?C(+.‹é:×AuJekB ©ÀPáË.éxQ§B¬ú1jÝh¢M:LûjꟕõúIü[`“zá2…D…%ʾ2Ž7üMÉ]=_}/! ƒ¢`$Þ°– =iaZÅü`.žµ s#B Â)5_¬N€oHÙF3‰9¤pã=¹âx)}­ÿÇ>i|5¿Jž²uöˆû²` 6f„óV4ˆt Ï`J×i”†¸DÖåÝŠ,Ÿ¸H[<ËÚß_A¾iÄн7š™'"]iAlŽ—.þ•}þ­2(+ 6nS!@woÔ4oqL(FÈ£$³uŽÎIőр½¨b"=ønýåÒ—aa­ùrœC†U.ÆÚ ˆðy•õÔÿGV&ži;ý¿¤â…PÞEL" ¸ñÓ05UÒDæ&ª”æõ›l•ìªá-ÆV)[Ot§‰ä.8Ꜫ?YºÓ¯£øå;}².jüú{“úàW>HåÛîK>$O÷ˆ«þàË-'UKT_­ñË·’÷õjÕWk–¿é³áÒ»‘C‹éDa}™ÊPŸçµ8Ï1›%¤¥ý1q‰nš'.ñ¾S(öa‰Kã¼—¿Õ5Oñ5“3Uioçl›“óÓr…åOì> stream xœå[isÞHþnøþ(¥òj5§fŠ‚* ×bøÂR”c'v*>’uœýõt÷\=Òè=lï²U$G–F3=}>Ý=z<âxÄ¿ñÿ³ë£/¾J_ÜÇ¿…Gï 9Žÿ]yBÃÜüèÅñÉë£08žä±uzòøäúèŸíM§{ó¯“ßã+n¬^™ì ¼ur#ÕoÔ0MÞ‹î«^ Þ;í»_ö²ûK¿ƒÖf’ÝIó"ÜUÚu_Ã]ÓvúÍ4¹A Ó}ÙëA)iMó·~cà…I¸îwø®ƒ?ŠVU0§µœ€ßôx5Ù)õbœøâq.í ŸëÏ0@ÊA*Ÿ^SJtê3Ý8ዲ {„AF8 + CVe"-N /À4ƒ6^Pr£´Ô ¥²ÿÞËaqzi¶>[4’.'d¢„â2Ù«a;Ç`è$¼²y3w7øã¼.]F»3¢’±» >€æƒ¶ºÀÙ«8|fÙfðȬh§ o´_7hÐÂ)˜ß° ´…="Ÿ-»yYFãs¡zµ]Œ L?k«¶Ü þP4žYóG`W˜ ì WרåJwŸÑʤT“· ”ÒÃõ4u·@+ˆ „öw¡$¼¦û±7üt´Ÿ«ž&$Å\Pî@¤ñ1h•6*îvRª¹[×vt¿îÑìŒ&{FÝQÂ"ÕDÄ2Ä Š_Þ‡vZ`íduEQZü"ˆb6.ˆÃ׃àPøJÙ$ç0T˜ÌB5@±šÐÅðX~ç^_ްælÁË$^û…ˆF±[B“°IÏ¢ß"iA¨©-9Ì(@þ¦”&Êa¼+‰Vã'¸-‰ Œk¨~D-¯5©MYGDíhqKÊ[ŠB—µàzÎF7d‘Å z~–ux¦­ pLÞÁC ÞG™Ók9-°S‚ÄY¨c¤qFÒjf ‘lâ²»–Jâ6ÝHSÂ+Ëí{RM ²Y;ó°âtp©² Qƒ_Eƒ[ÕäÈç~7ê$†/ç´¨3Tt/ÃS9QÔÉj¼j¦àmkbÓÚ)™„«œ”–kÔ†åH÷#'H÷MòÞgY™ ¢tì¨ÛZ{ÓKP}+…­ì „®•qE¿ËœWÃÌàÃØÂ7eh–~±¹çßÉ>ù¼ÑæÒ% "¿Ñ†O‹M¸Ìoñ¦¡ºfQZ`•h+~ç€0ºÜE¥û‘Q£÷I1Ô-X r?ÍÀ·˜Gæ8A¾¿ÌÅ(á^a# ôŽä½Gtd>ÙHÖQd¥Ìç,m!q¨å0¼Ñ\‹q´ìM~4IŠ­À]+þª•›‡æ¸*Š„ŠaØàñãæj—ßôéLíÛáÐP„#UËë+C^ÿS%­9ÔIÖpÀ:íUУ,)õ‚rÔCf¥sÊ‘õÈ¥™òÛ@ñ6ýkê6ô`™{¾Ä[H@ æ€ Ì÷¼•Èâ>WÒ38D¨UÅcò‘ûŒÓQÂhðó¤$§j=) .bWRrŸo¾+7KÊóv=)Éîüÿ<)ÑɾÕ~IÉ?‚ÖAinF1âZpLˆÎœ¤ãÖ­ÔúVj`úd=XÌ!‰E/³ïK«‰ÅcT}æßß•uöBKÉî­oxަŒøž‚C­ 9yÊœj¼ÚÞòiíÖ6 ›A]Ù,Å:°•åÈj²€¬¦äµ1˜”ðT…½@¯]Ç…‘•OU"c-bj€×&–BòBÍe[a<%Ä0ê™SX͵OI?v°2ž0^å­¦„îãl»k†ôÓ D5°Ž‚{­ù‡¤-IØÜ£=MVB0æv¬l€«¶`ðßG!›6XÈËû’OlY¸;ñ Þ³×Cöne‘ü ô &¡ôV•Ù¸(Ý}€]âò+1z4¦¹+(‚P1“Á]Õˆnnu¨HŸY:ÍΘLz‰EàQPú}Rø%WÜ „*NE±ÓN|¢X­Nb%"¢XݤgbÜÛs<Ú$2Éa­§("”U8æ¯!u*[Ê/ÏëI1Pó©˜  ¢¹8Ï¿Ï[2ùž›N«œ€©Æè(tnM¶d¥y7Ñ¥Ã.²’·œ7b`È ¤bÏSªoSÔG=sÉñ{,s˜Òª°@™ô5Þ]G‘0PÊ2KÃjQÕk#+a ¯h£µÞ—U®é~oCoÃMðbU­•žH­›ÕŒïÊðê9à.Ȭa@´f-—Ö¬ ï<`Š0M`e¶ EÔvE#Ó½ÙdKžÛàÂiíÆ_5bG­´Qüè' 0[×ðJ™ ilšd!M¨c·‹](<%f¾2WÕ ¬H ~Z«h’Ý$w¤ÕYõ0Í¿Ìv;…tþSi”ùƒw·t™¹ÑÄOWË« ÉqK5N©Jž°€wFVð"”Þ¨äŠhkÏš;Á2Ùý<ªø^¯°À@LÞW}wÛ¼Dö©279àìªwUŽÒšey”Ê)Ëy ¦ª½n†Öò¥à¦rÓ0ù‘j Z„le/90MÏX:·Y ¢¹@¢ Q;áö¡ /Ñ£Ï<}ô¯D^í_ÝdZ+zPR“©Ò,Áýçm<2¬(„â±)ïˆFÀÌðÁJžEaÕKÓIº ¡u{? ”Á« À±Ñ Ólz|_‚=¯mQ f‹ œç{N¯\a¬JËZO[·™[ãkÔzf,wôIpHÈh GÒöîk—µ1¥C@˜µn®‹}Ì5°Ò¬§7>?}]ì#Ÿí fý¹.v^žŸæ›Z7o[»K°Þey~Þ*¹Ý曥ÐH¾ÞC$öúi+~¬äÉJ~x‰ :âu&Ò}‹~z¿¢óèøx6vj ×ФKW‹Ž¾Ìq_p4™šF­"Ôè@¿ôlZJ¤Ü¬Ä‘L°Q'ô|ö-ÉÓZ¦”§Q¿Íâ¨C…¥FdËu÷«¥°ÌOú&‹™b b©%‘ÑŠGAxèI{`Ö¬—Uš+È–IÌñ¦ÊbzhòI… Ä_ötxÌH[0 o0‹kÅñFKƒ Ƈ^E@+lØ«P ¾­ªäÍú†ŒBRpN4š¼Ì߃ù`,tÍÊÜmm[¨CZÒÓñü„¬m«¨Qö×ùâj^dø!á¾äc(+á>…ˆOCª ÂÇË%â+0ðb{'´Ðó#8¨Yú·7 qtó¢5ò‡†hôW-xÃY(ÕB•w ‹7¯gø’fÊ}iï(v^UÀ“m.aÀ â)±÷YpL¢sEì¼¼µÄ“3”y]Æ>¯@&¥jÒÍkRM›x–SÒúŠÑQÍé)õ®ÛVÃÖ0ÿª¬ÙÁ¦sÙ%”t84Ð6A»u]~#µ£Š$‚qt÷iû€¨±W]I˜†]¶.n ©Œj³â7¥ŽÐ„Å:p«ÈUÙÔPÉÃÚ$?Ä"™¨¾@gæïW¼¸ =<ˆØN³–51ÙÔ€CšÐUƒF¬BÛû.‰ª ÝSÏÝPA!l‹îyJÛìH‘­P•ìÜ8¤sµ¼—”CÁ.d–4’Ï0F£Ù„rcnËË$£rªÒ8¹g5+ÄbǼÞ,Â/mܲÏ9<[ÑÏf#–ìÆ¶J§¦ 8ƒŠ”ô¼‘•!‘;[lבÂ%Ξ¢Û›Ïølò*¿Bˆëá×÷pt«Ä¸µ°ºR¢Òª.QÝg¢«‘ÖM&ÿ¼À”«¼»›80=©QW‰ë1®îªèÀu[Ðå!µ«ÆN‚pò"@ª>ßY"’o«¿¬Ýq‘¥›oú)‡ÆºŸq€¸ï7-v¿8û9BWs…Uó(l|öb­Æ3³ø€)-ñ¬®1Ui ûÆâ[ýCNxÅ@ÿÀã¨R#>‘»Cä ýíƒÖ,ÿÏs–h¼8ª#’Žñj% »ˆŒˆhB,†¬EòVìÎ#¡óð¾6jרg苜‚ÌÃçà^Jöv¸ J½5íJªÑ8¡¶8#‘hLfõÔ EUxk¯­rqQtfEí k9&²âç µ%ÌJ>«‡Lˆ[Ó=ŸnùÞ Î½, ¡5QàîªÖÈ/ÇâmC- DpÂíŠ6Oé–½*7+øXª¬Bµj« díB–ç;gbÈÒˆa^6 °²`Ün!>KÓÌã†7™qÍ™7þ k ºƒû3ÈÉdòâäè¯ð÷¿jÅ»endstream endobj 628 0 obj 3650 endobj 632 0 obj <> stream xœí\YoÇÎ3á±ožu´£¾Ÿ‘aÇ±Í 0ìÀ¡H]ˆ(ÊeGÿ>U}V÷ôì.)ÅöC(ÎôôTW×ñÕÑûÓ†Í|Ãðé¿ç—'w¿áRn½Ké86t7­™ÄÐë§·; @;àÊt¶U³Ó ½ÝW•7bz slfÊçÏ€ÉÆ!¦ xlÝl•D°Y a™ž„Oí¦Kx‰qŸÊ3 ä<ÖŽ ú¥'™¼§ù¢Ü¹Þ ‹×Ók˜ÄøÙ)Ü x•I T\Á"c¾÷*¦Ç3Gº%×@ Üòªé%Üc°·|¸'ÂÌÂ1¸üâäô½ïé6?.›VÆÕ ›3=ÜîD¸k( KIÒX.®¶ÒM¿ÔižäÏâ|†™é<–ئ¦¸ )•a¾WuÐõV‚”ÁSD’\qàÍKœŒÏÚè–äü¼PöÅîJŸæ¶É…·uýóðŠ*PB¾õ%\kò"!<m¹#s\ã×Ì̹Ó½À?%¼ ‘Ž<óY|’'Jò.²dB[N¾Ùm >×|úžÃ͚霤¦àÛ´níQšë§Q„Ç¿³JÖ/=(ë¸ $Öûe+.Q èˆ ¤Ànj¸`Ë,Öp•(ŒK¯{­2{‘g¶ ‹Á¦)åÐôd{‚ƒêt„g8e}°2yàã²}8¢4yýq}‰0÷5DX1O,aœ`¹A.îw\†í‹Ü0Ž‘wДðYH"ÚÝŽ"¨¸£Ì±µD5qG•A=û&-Xt%¦?o=£ƒÀ.K-àw‹@µxÖ í»µ ®œˆ€ï]µ‰Ö,±Òrúy«Õ ûãÂú‹R½êUeUR‰ ?LEvÎZ­"s¯Jxà‡ºñ·aÙü.æ!’\ÐѾ¬|)¿ŒZªÍ oLÿÊ_ù8( ØÔÙd=!¬¶Þsêw[Trù]´äÀb.üg<³_Zo2û­¥ìÑÊê*àE¢Y?lqML‹5)¹wÔ5ö ˜hg.©xŸ¡Ìxg50¶+w°ejM%"áAÜ#3‚´&"O:ÇVaÒ¸“Þ±àÀ“ÄÔï8БmBŠéK¸2F5¯WõéÇè¢5>]¡F+X†%iCͺh­,5m;(×½/‚E7¹­˜PTµƒ£w§‹Éø*.‡þÕ/ d3]iØï~a:ht¾"F¤•\¾ßYcï5Ìå1ˆÆÐ¦ÇT)ƒ°KY…á\,èè öÁ0Ü(¢S‘¡ *wÔÞ’} –Ç] ÇA¡ôغ7®'©SÙ%a3ø@×÷¸Ò^†ýj…:,ºêd¨a§ÒLèˆw¼eÁB±ÆE`Cî#"DÛcˆá%H 3P#ør^®zß jì!Ð|—–B‹"Ì8¤N24Ò`!RÒDDꜫŠ,­à5{”]/Nà ‘æ0_!kà”ŽŽøˆ|ø áUrŒ°ä+Z×ðm/HÛ/¨„ë-Ž ¼m‘JÚ…¬÷Q•ò9Æo¢ Ñ3+C0;Î~±´ïZ%dØÔ"›w;Ë4“FȘeTP.àŠ;¨ë!¼ ¡ìÐt£M€cDpRcwƒ˜¥ÓŽk|GbD)I.P$™ ÞƒÈÉU}MJ£È;áP¨˜•áb¸‡'QkX ÀÀÁ¦ísSTQ™‡é£š¹F£ÉÜ:9þ)C¨õ9 爡åÒ`3^E“/vf­&ÓôWËÞØ¯ÆÁˆ•(ñÔYU¯jZDª(ÄÛè2˜-ŽÝ*‹›ø†ÎBÚ”]I±á8Ò_1Û‹H¿³¼»¤œ†æ4§!1ヶ*æ4øVSb=îy’ùÏ0èâ΋†£;¡<˜€ÕíãìQõ°dadÓÈêëôQ QðCp‰9Â=jIˆvŸQ ´ÆÌÐ1&µ–¡èG¸B=ÛâÓ,èÅ×p™Í¾ç‹EÇ}F+ë¹O_Wòd€;›MèÎJŽó.Ë(r &)x z(¯eUåÓ÷#p:ï>¡z`üp•Ò¯ˆ°(î5 AÝX™-곇„Hy£Î|8Ó! ‚ƒÐc5©…5cJ˜œ$¥2@ÈYT©QøÀÊ‚z:vàè<•ì£0ž$çS:4wwbÁ?牚 "ÌÉ@©ÌX})¢Ö{{+S°0ÅhÚ·§È(ÇÐý PìÞ 3w8œpïùšm š±äÏR®£þØ%õKÐ{L£Ýè˜"#Íôé±§“}Vd˜YLâ”WŸõ² ûœͪK|…´+\ArU¶ûCméÌÎë­³Ó€P–È8)ŠéPô2׎B[ÀúŠÏ¨’L$ŒæÈ³?×r‘ÐÄÇi !õÕ$ζ5^‚T ÊeÙ`´YƒÝg9 öäß”*“K|IU¨óŸ—–>þÃ6?^_rI½þüž“>Ö–|1YOà;â ÕÐ܇ŠÂµøóha13cœO?⟘ZÛŸþ˜‡] ƒ¯Ë¸Ë27¸ z öÚS•F?¨7ï–›ëÍ‡åæ£rõ²>¾Ø:ûܹ:eÐTxŽu´ÖNÖì4²Öú'¸l̇÷(Éq}ñÃwÒ˜P£/‚r¾WF]Vò®ÊÍg£Å?®7qj0(ÞÙ0õè%J^|þº>Pn6¿h(‡  ‹}ÇOÿrDóp_Õ›/ëBBæ¶ìÉ·‚ª`.×GÑ$u„7Á¯Œ)}«ñ†ÁÐÒ¿¾$øí¬4l¨°bà5(&€ïÃbÇáb•‰Áô¡²^ïæs9ÉàfjjÏ~³LpˆÜA·e‘‚÷GÙ§t)!~¯ÏIE\¾[ž';Šª á‚v±”±žaÂê#áŽÿi Iž¶}J®b¹ ÐÑ"Zê|fª3jtÛÇÞ5G|T=/¦¤¢æxåHÉáa–‡‰ˆ[C+ì˜?B;«úºØ2á]‚©ÊýêÍÐÅqƒj’ý­ð.àôÐ9ßó&B|$u¿ä¬sZ'z"ýÀ0ð«S.ƒm3gC¤zH'IòjùñÌv‰09¦nT š«êSÇH¦ÔÓˆ)]àpÎYÉ/%د|E¬ãRÇ).kâ£ú‰ —j*9æÑã '*A³"ù‰­ä¯f˜öÇQÄÈ×›yˆž?ÀKÂ|¾-Ý+þ¤z†”-âã‘M6P†x3qÏ“ê÷n%VQ…¥À5–K™NEY¦‹R† •d‰ñÌ/?¯fêªíi —£@‹…TP ºiQ‰òo±%ŒÕ]¯u¨Ÿ—¥æ&t;MòYë}U¯Pð£­+yƒ\vR1ó{„ÍW1óPG’U­W6î´!T\wE €À@îe:×êÇ ÍM/rô”kp|Ø·4h–¯®JØ[5Áùf›1ý]E×i挜/ßVPt]‚¢2å"(*…AQ ‡@:°‘ãÿ~\¢Ÿ)rÐÛÅEM—–}^‘èæ•·{ÎJ"Žëú¼¾Dâ©å¼ݬ|)_׿B¼“nî£C"ò_î w¨]uqÙ®‡y“s) 'B÷2•Ìö%2q :˜}ŸCŸ:òj6¡ ¼.ïˆ[ìýlö4Gep3šŸ¤ùš f\ã0}Ó®+Ú¿‡èŠ5íÆã‚° ñЂú Utô¹f/'9{É!øQ¢…X,5z5$3j€$OÍ/©VÖB¤d°5¦¤ªb>*´Á² #}ÇJŽ“æ¶\J`Åâü0k_\êó!T,Ýd)… jx‡úFØ"¢'ÝÔ¤ËcÍÇ®ù;ŠÝlŸ‹ï<£Yü·›¢Ä¾ïRí…ÓG—}Ûà´¹æ¨I/3ŒÁ™7˜1· 4]sЉP¬Zí—IÑnÓ-‹õ, ëcºwmTœE¾?êÀެM‡CĦš£Y5Ä¿h$8 ißè’¤#¤tÚþAâeŽ©€k÷åJ=žæÔ‡©E¥ºÄBÈÖ‰¯Ê­ŠåÚ½†=¡¾[öÐÙÎì°¾1ÏÒ!bè}"–Àõ"1æ(Q mÅjPZêÚk¨ˆ¥ˆé×Lˆ5ÒûsÍliç’^„ÁÅ !Á”ŽŽ¶»¼ÅY?9=ùúä§Mj‡dà‚Û€**üøR<‡ç|>¼wr÷Þ—›ë¯œÜýdžŸÜý þ߇ûþsïãÍN>¹·ùzýôO‡tÒéeÄì~g–&ž:¶Rlò›Jf¡Ì#ÍØ _jZ߫ш98“Û&a„èµDy ˆHÎWÑLí Ë]ÜšßÚÅä¾›³m_´Z:•‘ÝÖ©$wÕ¬½N%¨u¥.-¦o®Ôâ&Ji:6jo½½uÔØÆP1|M U‚"À8ßÃò.‰“Ä |Ù_“É‚…¸ïu!%Ç}´v䲆k íU~²ä·W„ºÅ_m!.ms!ï¼<#Eµ3ÊÉüB÷.F#¯Gå02l8tƒh“DŽd^"@:[ÜÅËW‹×p,FœdËTØŠ¨ß*äÌ%³³ˆ‘CpLðPõ‹[`©v|>õ%`ýGL3Yû*ioŒÿ*iåòýTTc¤öv¥´¹ÇÙ®ÇûÐÁŠqMΈØýÔV1¤E·ÚüZ6íàɶ.ûŠaußÂBCÒÐ+fiåålwšV@i‡¶¡zslJ"Ÿ MÁšÁO·¥£„T6X¤Á»•ŠAõ½hÓÓ¹µ=ç‡Å|u².!¾OÇÒÀ&Ãë²¢%*ON{¿B¶šÙ†±m—oäûzËV”Ÿ¬Ö”ä˲}1oëƒuƉ ‘$eä7-^ÿ4®mâÊ÷´fEˆð+\¦#¯v‚Œô:ÎPµµ"n‘jœJf?.½5üë§Ö«h·Ë§èr ¼ùå Ü"ÝÖ“º7T³*3UÍ2ï¦üŒèÎ-kÀUˆÖ•¦Ú>›Û>TüíŽ#.Oñ &Rg–•sç–ºçeIJ™*çÉïq,=¹²±Wx_õD³z¾ç%rÖ¬gqS:9|VúýåpÜ"cÖÏ¥+ÏææDæ1åpe|æî è¢(K<K㨵ß!ǽ;•8¸¤PK!væº8îGq"üœåh zð½|ŒŠ¸ñ@ž±˜d±lYz}z¸ºð¤z53‘×»vH=áQ=ç»´g'‹`64bT6.nî9œ®Ë¤AoAݸ¨‡S ÂjâÑ‚ó¿·,W‹…oöË!ˆŽÃ/Nðž ·ZÙZË?E"ÊT­à¶T‚<êØ—ÄJ•¼Iú‚dÜRÛ0þ쯴g½ÉDÚ[äÕ5‰ÝÍ=ŠGãîš.“l Ï–Ó'ÍK?šËåÉ¿å!ñaeI¢S‚Æ÷±ã\ªðXÄ—ð¿mˆì²hh1QÁá9ÍU³~˜M¬üÐD ­ÿZÛ"á30š•LAOzÛæ0J]•²ó×'ÿ¿nYþendstream endobj 633 0 obj 4751 endobj 637 0 obj <> stream xœí\mo'µŸO©/øï‰ì­Ÿm¤R¥@E¯- jQ©P.÷S“K¸$ǧïÌøi¼ëý?yÑJ6^¯=ÏÃÏ3ãüx<âxÂÓÿϯŽ#”:~y{4ÿ½<úñHP—ãô¿ó«ãOO©›‡¦1LAŸ¾8Šˆc'­×£Ç§WGÿÜØÁàÿ:ý#~â§ægGéá«ÓgÐó³áDÎ… 6_b Áë°ùd›¿ 'bÔÚ8¹9­}>­JûÍ7Ъ`ØÉÆáÄ9?Ja6ŸzTJZOÃüm81ð~ó~ëáE³*ÓZNÀ|rÖ¥®ALŽOžÆÒÁð±þ ¤¥ ù3¥ÄæÉPèÆ?¯«º'èd„—0£ØiU&Ñâ¥Ðø 3jà%G1 ISRJ ûÛAŽÓd¤H³ÐG³ùÙ¤‰téDÜ%ß“a5,çøêDqo^ÁÈ›×øã>vGm^àï¯R£ÚÜâìÓ$Äæ‡ük|ñHüñ œå±ósüõ1þxQ~ܦ/$J·ô]ì}W‘z`v@O€uÆN2ûý??ÇyÂøõ›D< ùh+=3â?NtpðÛ| Cȉ–û¿®d2Þ<*ïßÕ÷ÏKãYm|Sa3xv Uß_¯|”/j#Íäi=ûÏô¬¾?ë­.ôöA}ÀAsëmÓµòœ?uÇ7÷nºÒa4&d³q[¿ú~h¤ìl+¯Fï@^dÀÿ»8‚Tê>³hf (Ti¢¤­“›p'5èm½KóöÝW›{Š–GIJ£°Ý²®µ+Ê„²£Ñœ[ÏÀÕîØG»Ñ8M/^×~(ÀÚŽÍà¯À€©QQ4¬uV×$€â­%Lª9©qQRÅYêÐ/pXÀxïkès…}Ì‘¦wJÍ×–f-D1âoê#ã ¬´à?<’)`«•l|FÂ|P4í/ƒ’çIi•G&ð§j¹òòzÓ˜NزÀ´»(n Ó`\³ô—)µX)5•Yè"¥Áè–Tšjyb[u6(²4uKp'RmžÂ£ #ÒÀdí ´WJ¤EM‚½­]ÔÉK?´?ÆŽJ‹í‘ 7n”ZÌ .ŠÂeÞ ”‰ŸjÇá…„á%ßú¤?RÒÖ^+9]kŠO Ð3ù41)ô\à¬h•I$Á(çI²L$Nzg™¡Ü.ÐÀYäæéŠ8€ÏShZúJQ‡Zj:JÎbyørc’D3› i$òÁ’ßÉŒrò\<˜ÌK=íZÝÉ$V ˜áˆ —°=;‚¬Õ–÷¯ƒœ—§ë¤@p±Œ¯ ¤È6  ¸3´lo£bIOó^ɼïÈ#~&'  «-á™*Í—ì)2”b¦¸Ns­,ãyÃ`‹‰;zN¡Éóþ’;rÉ[|ìIZþ Icð#¥Aca]ʯ›|K>l›Y´“›Eín½4‹8~¢ÒNº;(ÚãÈ£?ãrx"=.Û¶£ÛHÈõipñ®7G’b îã 0`U\÷øÞr‰^skÄI /÷ü€™¢Îì£ãÊc¤G ôæzy §3=+, SÁoªX§ píð&j›5â»r€ùÐ÷w¡ão'@(W@­ÿ4 ïn–‡úî÷Âpg{ú ˆ>" R.”DÃ)3üˆS&-P ×Õ¢³¡±bõÅ»Á;PZXð‡¹- ?­´u«‚Y€…EEÛ¿ÀN(ó-vZ: 4U.€®+ PÑN öú¬uˆÜAYqÛØž_“õKö³+‚컎©Äùá×lÑú¦…ë®ék£Õ¼€€BqÄRÿ²>€µ“dÇg†ÏO¤ ]ŽÚ@C`”¢å Ù…_JÏ0Šx/öô<²(.mˆ RWPD"®q•k†ltáZTä‰:ÙÑ;¡‰SZÀ&Ì#¦ì Ó²BÊÁZ’«$Î5; ˆxˆg«èž Xx·AWÀVGg Ö!£j-Ù‰¿ ¦ª=kÁXŽ,có ÇFä„<¤£–l®³¶§®Wu›ÄÀbj­¯ž§òÌ­¯ÿ%éîúm QH4 ¯fHÝ;½àIWÌÇèºÚÚ›IÛYÚxÏ_ˆ,´ÂNëQ"]?LfU): ,åái—³³@@ŠfMç (®ºFÂê‚ß²°ãyŽé’ÑÞ›ù—óáĵ`~ŠÒ'ÞïÅ´€ÛÝYƒÅY™å,ÊÜ |<å%Xé6ý3?2Kò‘¹ø¿žn cü6²sŽVO£/Â.Æ¡YM+PZß÷õæ²=gåñ™æ0)˜IûƒH3ä¶ÿáÁÞ¤¿,+ãíŒÄ·#^¬Fo©ími«àù¶ŒrŸv†œ-ŒšÊ‰%vQ¡Ñ[ý—¨ü¶â>÷~”ϲ–/< UŠùX¶»oÏUòQðs |·&¢‘©ÌªeÖ?q¿'÷?ÒÑE%»u—½h «ÚÉ10•$1Vk.⌱x*­ŒxmqïP…1IäÄâ^ǶŒI…Tó*+T&8+’ $±:(§‹úвE9ÆÃÀÞaÒE~X“ò6ó ¤USQ"øµßáî¢_ŒÍÖ`åŒÝ)Z ÀôMÙBì€9kÓHN4ôN• »1ºÅ•4Ú|’«AW[×…JJŠç4‘îDûZqšž$ò7ÇÒ4drt [+Ç×픇~Ï;¦=ž$î´Ža™µS­--ê7u§ÑPE!–‡‹ AÇ–^|¿±|iâ=Å]‰Ž½ X÷µp6Ûžµw·t¾Ð˜2Ê»¨;ns?|†^Ï ÙŒ¦Zɦ(zI+kŠŠáXv)ÆÍR™jSÐX%éeñ±íEViš¬*¶NC)=AÅ:“«ò°À+aF/vÇ0/I…6¢ÙóC‹=‰ªC{lÔæ·C¾ÙXnœÀš[OÀìf'rqyÑqÖú–ÍbIv˜ê¤ë•`+¿w&•3DÓŽèÝë"Õ[îA¥zöýä}/(„ZDußó@ Nåvœ×íywá:sH8a•,®*y˜“– ÃÂÅ»" hP›'% ã{…•y)nݲgίËåãàåÕkS…wHaýä ¸“××Þ'ÙiBèÝ £ÝgŸ¼÷8˜Q_ÖÕ+&kð fùÒ”_¬ SV’ιˆX–§æN– ‹—»YîçI{‹›uB­ÖbU³ó•j>Ç×øÍ¶éÆÄX±¥8€î®üº[bM,Y¹l…7AHà•Á;ØIÞ?|ˆ7ÙÁ1q³c_"É’Ü KuÀx/‘ßT3bpg­As1$RÝšê^’"l7ºxÙ]ÛV ¡O½[°žÁ‘5Èù~çÛœÆÌ™ëö4Ùyˆ|ët Øž‹˜¼ýƒý©ƒry”þ2ÁN?*µú!&ȉÙ.P`œ·°\ma9³ÛÙ ÒèbÉžxG˜ÎÜú¶T³ÌêUeðg–g›AþrŽ!—:ظ´Êµ)gì&Û†~h­VrÌV®úÅ•ì®^™‡(€·F³¢x@äÍn0 ´3>—ùk¹ô³9Ó˜<ß®Á’n/³ä¬ô*êIæBíã ãԿ屄–t'UrÐuñ|ш4K±„+q#²?ò…HÀžÖô×O|EÕ5É$çR´Û²‹Mä¹È¶€.î9‰å1³S55;ß/ 4ªÁûÜxß”ËyùŽ2£”w¡ )Ê»> stream xœÕ\éo·ïg!Ä~ˬ‘ o²@ $nÒ¸HÓÄQQ´IÈ’c¹¶¥øP÷¯ï{<9œÙ•d(‚È»ÇwüÞÁ}¹™F¶™ð¿øïÙ‹£ã‡LˆÍ“×GÓæÏðÿ“£—GÌwÙÄÎ^l>9Án›F79¶9ùñ( À6†o´•#㛓Gßj«†qËGcŒ¬ÿ²3Ö|²Ãß·|8ÙîÄh,grx°Ý±ÑZçÔð~tÎJ[›LêË&1ü>r]Äðp+øÈ&.‡¿ásιÖthìN†þž|Š_¥T†ßlw >J§¾?ù‹ß¼¥»‚>ãdac'ç° ë7ÛÔS1Ús»îÄ4æ\xCmEw\¦F§'žŽ«PŠ ?å ÏÝž¦opÛzœœNá£Ô£³zxÛQÊhìSs6¼Úîä(„ždyý²Œý^0õl+¡‘q>\Áþ.·@W%'AÆ:…öÞ m›ž´X%à|Éç[© k1~W¸‚ñ51JÅé\¸†Ûµ6Zý¢¹8|Tpêß ~ÉFøÅÃÌÓÃÛín®ÆiJܼ³<N‘š?ÀûÂÈ‘35|Ð9›ÇJÊÕÕ"p k\:t²pÜö+üªFô.Kº¢KºãfÓØ‚œUh×,-;`§@®‰E²k>¹á»-ÎhGÆ‹8%gç¯&<•|´cžì<|䆑ç?º—ÖóòÖuy«Pú ©v܈QovLÀbAN<ÁúôµFã!p؉RŽp-Òî* ‹@.'Ã5¸’ðžå}¿ÅFP$À;§a܉Iʯe¨—a\“¶ƒ2P˜“ÌU5­V«Äï\A/a÷òbZ/¼ù&³ú6:/Ê„AËó²r¤ì§'G_½Ü$/jlÐvíӣ¶ ûG%và“GÇþºyóêúñÑñ?6ìèøsüóÉW÷áŸÚüîèÓ›¯—­C£ï¢uàŽ,„p£•ÁBÂîÑ}qC‹»L‚Zÿ v5ªzjª´S°‚lgɪçØpQAˆÊáÀ¡#óZB9¨b©‰(_ù#l˜e¼M4ÅìéÀ¦Ãä`Þs–*£Z•s*… ¨|-®óf`%çtþ¨“z³ÝUË6ò»e¼ 6˜¹ zC9ôF%Ú@ƃ¢-ë@B_¢a »š˜×§ÞJæ39/r¼UI•KkA•óîÆ!¨>ès€ž¡–TZTÉèK¶rÝS=Cþ8‡ÈŸÔÛLûŠÃWk– =TmÓÛlzqNR Q _œX<‘‚¸dÃ4öȧ=MÜŸæQ™¢¼DæÆîÏLdÐî@+xZ׶Ѽ"ÕÊ|ñ#ï訚Y J#=/{2„¤ãðE‰U䙺'/×øÀZXúÉG'÷¾¥žèE™Ÿ*p!€± _PàØ»laA ®¼.­†EÿBVv%?&›x:šQÁJFNi6ÑÛ@i(½“ÃÇÛäãÏ]m”?Ü/Hàp?¢qÇ]ϰ#et1ªb²q4ë‘{ä2 ÜNNŽwLãUm~OŽvù<шNÁŸû «T— 0ËÎrPƒùB¦ri Qx2ƒúDƒÚ_É̯ Yi ”~ ™97rœf|ç@Ÿs42¿Á€¯FK÷p —SpF/êîé‰öxt›w©E¾î€ E6üÂPn¦¼â­90{O9jWˆ0³àÁv€‡ž™hYAx‹][VtÃ8 ”·ˆu žj* JC›EOÅK–©Æ"Ö£öUÒ¶ÖÂ!QTmmè@ WÜ%o•Gÿ»µJ· ÁqÀèÌñ/·ª2Z±4ädzJ¼áÑÞè.Zãã4¶È‰&ׯBÀ sŽ¡(‘òÏÌEÖôKqWИ‹÷"QÚ ¾h_hM¸­¬ãWbpG–{ €¬É°œ[…j“„ލ"z†3"ŒC›c½Ë»wí3~!°Œ·\YDc:ÀA Jå°~…N°ñjžàCó‘Óåd›œb×-oäŒÆ ÙTub(=0vt}æìáF©ï æRœ£*‘‰«:²=}WR—â³5R!@¸b:0,Ê õXÌQiç§ôQÂDD¯?ªôj³Ä9bÌ’¡ð_÷D(µV ̳IíL¢Ci:”=©®Ü/8ÎŒ\&Á©ïGyüžaÓ•nÒOIΡ&&¾òâ¡„oÿy«$øÜÜÖ±f* Cæ­LJC(œÑ(…Ŷû©ÂŠ-F–ml1ºg‹²$Ê€ž<ö}‡R³ÈÔ‘P‡è`ÁigÜ…tKt™·QÙ•T,9È)ÝüN¼‚ÆÓzN[ƒ³÷Ÿ®ëЀwÌ Àžš ÍëhùNÉ_ I–Jmô‰™Ù½ñßQ*›™Rã³E ”#!bWòýì ñ9.S‚¡×RKcÀñD¨C\$ K8þ]°+Ÿü*gÒ/™;k$äógÊÖHÜ;ÿh:û®d×!Åâj?Bpwp>ÓGDËíĘ55Þ¾Ö¥Á‰ã‡‚‰*u Ÿ'ãŒÏ]s‘Ô×Lç­ÇèÊ[ ˆéÝ{øhrÓèxÉÃøÇBsë]”ÒÏ? /ã> áÓ©iª×¹ÏwCi=Ë­¥ñ47"¹@@0ñ{Î1ïù¢4>ÎÏKãÓj?áÓ›òØgO}k7Á¿cÀÜÈøHSÆ'h:ÐèTé`¥3uî÷y MKyz5oŸÿJr• ó£4Ëk«*nL$è u/È£€?1/°è&ìjUÆï9-‘¤ÛùŸžfˆ¼~Ùr,(Q¢•…¼™‚(묔`!™zxh"j-»Œ›(™9‹Éx¯qZËd/f CüIMº/¾XW %kÄ׋ÓÛJF3‡ã¾Å? ÿ|Ÿ¿>ª;£S žâÄ”—BlО;Ê'ÊÂð‡"2?ú>ÂÜ€ólàŸ–wžçF¢xnKcõú\2‘pVÉðL$n7QÑÙÐ…ï¿‘"õŸð~çÁ]:ç~iQU£÷>ÐóðÆîãDð÷>Q!8‡V¬³ª17ËfJ1ßÖÆhË0È@ø‹ØˆóúÍðœØÀMXÒེíH¡q©ºl´(Úµ9ч•—lACðIÚ¡ Qn+¤0G³Nœê¶Zƒµ¿—ãä|Æ4jã¿h\kåj÷ÃÀmÀ©‰ìV¥$&•_3}¢è kôCSi·Êïhé—¹ š;qûB” ¡fîæ½Xïw7ˆžÝšx@±ÿe¨æ%À©ÝR£^Ý£ÎÔÝ$"I Þ2º3Ë&‘õ}zýAŒ‰Ïd2ù¯„ÊLNlX~Ö•ts && o–ƒ›Þé¹l,Rí6ã‡Üö˜Z²èO=KBgîR{ÀéùÚ×Î,ìuÃ1Ì'¦<_xçÇb}ŠÇö¬ç Áè@ïExèZÏJ׋žICÈàœ$ØÒø©q¿q, Ò¯ Ìн'ZCU²³D鲈׽ŸVéãuíXÉ– âëX¦‰x—Xë]ì¸g¹ôû]žû«úÜÏæGnµ/Ë8DÙsܯzÇqvëãf¡$ä^ï¥ÓÞ¤ç³ó„IßÇyÆÆënPa»rB”oå35ï oåóXj_pjO™Ò¬«P‹fŠh+X ߙǰ0¬Ü ÂÅLóækDžýWS¢TÁ ÖÝŒ7Úg+O«WIvòËl'hü_ƒÖ?u JŽ`Tvkjñ#B(Ï/˜NôÙàÔ ¬ÿ‡~ê»…ñ¹ °^œ;zI†”öjú‡ZpŒ$EÛW"1w¶}:C*­‹¿b"„wÒãó£S ·Lá‹§*È\¹ÌéÂN~u]A! Z 9&±p¾XqC@I“¥A(Wc-†|s£¥Á±”LûÝ_ù]¬Gs PƈuÏ…Xw0P÷º £I¥ázá쉫uµ¥=°^\Ó±ÈaXsÄ•´GÏ5´QÎ<#¶E²€f±hD–*±õ›²]Ò¯xi Õ3à=±Êy‰¸Û˜Ö]HàÝlå”JÈÊÁäûÍÖéÛï-Tè2íY¨ŠY¦®uÙØÐ75Õ­ot5;awì^&ꮥ6‘z‹¢tëœ r§Ëœ?ÿ·©é•ÊvÄ7z;@X…È3Š•L/ —Íæõ¡1àÃ¼Ñ ¦l bC%óÝ•8Å¢ßÊøâ>¥Ú+k7E‡A~0)œÄ'齿ñ¹SÀÿm®L Aq´v*Ÿ½ÌØSúU†<ž’œãœ|~„™¯Âæ§ÞIµ5VõÕª åôÙÖ1=Ѭ(%žF5ªºKnÏ—?Jéý3bï¶rÞ…úÅ^ÝuáQ.îLRäBƒ¯øÿTjeJõagÙ/ˆìÝ£èU¡ÈõÜ]¶OW‰°Ê•›eÑp!zÌÇ»(_@&ðo’Œª°Á…Ëï•bÆF¼cW­w½i¹Ä*V¿Ö±Õhr“¸;áÏ©é*¦¸™ZÏG¥¥Ô‚Ò*w‘æ Y—æÁÚñžQ²¾nÝYðnŠY¸ÕÛ^ˆÏ|žJ+Y÷ÞÑ^ø™Â·ÀUx«„2¨wÅr„߯ýAÄ)âï‰7·×¢}Y“ Å¢ Ð%Õ®áTJ™±PË©Žÿ´ŽÁÓvzñÿ^‚Uz"yÅÛ©mÐ1¾îØê÷à8“ ñ.’¤ÖäÏXQÊÖTÊj §òP*®šêî˜[ˆ¥¬†/F[p*tó½ûDÍ2—*'WðBìN€rát™¥Äs¢™™ÃX~Ä?¯/¡¹ÄÈ :Œ/:.Ý­*h–/ÇÒÒ,_Yß³ˆå¸ÄÓ¯Hšê?\#ÂK³Ï­)ØH©×wø&/;2”ÒGÒܰ&¶65ÈFÕ@ˆhÿè#›y­w0Û½ÂJ´thç! e(î+HW§!‰*8€mœ¢|ò{ëé¿…«35ލ}óô“‡£ÄwQà`{ ùH•@©ºE&Â÷¾Þ¦Â½ç9‘‹Kf&´=‹…B“]MB”LO7³ð,¼z×|ÓÿM¢ª \Ê?”\¢=,ÿðÕÖ×àÍ+HëØPÊ œ†{%7œ¦Èþ]RàéžÓsàáEÕ»:¥C IwÈ®XÖ*Ó¿ŸCf(f&êökTR§„GM¸½°oÌ›ÀÊ`WÔ¨s ¢¦Pþ#„6áFý¼8#kåBpaÔ¥è•úud÷Ðendstream endobj 643 0 obj 4839 endobj 647 0 obj <> stream xœí[[o·~ׯòâ]Çg³¼“R iÒ$E𤉠$hŠB•9°-ù"9ñ¿ïÌð6Ü‹ÎJÇn^#ö.9çòÍûòxÄñˆÒ¿gÏ>úN(u|ñúh<þþ¿8zy$¨Ëqúçìùñ''ÔÍCÓÆ ŽO~>Šı“ÇÖëAÈã“çGÿìlo:ß›ü‡ø±âì =Œ:9‡žîwjp.Ñ}Ñ‹!¯C÷§^vßö;1hmœìNjŸÏb«Ò¾ûZí L6ô;çü …é>éõ ”´žÈ|ßï pÂw_âXÿ)šUMk9éñÉY—º1:>y¢¥ƒá´¾RR…Âu€¨VH\ƒyï”ênê˜ÔÓ Û]ÖÖ_zZ…âmQJ#¨]¥Ô*IÑwoz£A¥'™=ËÄnÚÎÒÈê 5ìý:êVÞŒ4c¡Q8«<<îQ¤÷ƒÍ»ÎÖ9š`€c9*Š ZÏXgª‚ÀŸQÞ£Hóú87á~k3(­’Y¤\;&Rhå‘Ý`t–$ÚúÐÿ©ÇÅ™AÐlì%*‚„‰”­<à–?ïwr°ÖY•p•§Ë^:šr•”ÊN:Šy¼K6h$ž¤û°C©·­:cG½²ý†Ÿ¦A’Reo ÏÏÀXƒ¶Œl«!2ÈÁ€Éd'°0Áé¾FêVÙhòUœsß»M+G”áZÙšÞÒ8¶7lêÌ‘à¬L·‚ Jv~U·n ˆ˜ÀhÅL÷erÁòy“nË )¸\GCHVdS¸ŠkÁ?ȬŒ“ èS*(hdV`t$£Í5L«ŸTeZ%ØS4Ö4OÔE=á˜ge¢Ì1ˆviK°Ë Ÿ«ìÉ}-B Y‚ >J§h:º º©õÜy¢rV…¾©!€õ¼\ŠÙ–âVŽ}˜»_3•èeR?$·ìð±j ÷°"?ŒÁÏíÕš1?µ÷(7â÷³RòÍŒ$0ðÞÁ”a³î’_–œ¯«(šîny$R+ÀÜ ‰]d œ‚'«C]PTÖ…j!ä¹ÀÃN­j|‰W‹Zö¢@®»(iÁ”ýýÅ_D´ίÁFJúA‰@àHÿ LLAŒ$ \c|ƒ|Ñf¢Eˆîßøóþ…FLáÞÒªãÛ7¥3uÁÃ…Ríí¼ë>‚©äHÓÄ®4{KÔcãëÚX‰ž•Fò`ðŒ8¯5UðÈ;T‰¡ŽÈký*­H>,}ÊRb48ôk vrºŒÌ®‘“#õzXßT¶kÏgµñ¦4>®4Ÿ'᜕÷O–(½Jœµ=\ El|^Ÿ/ÍyY¯ËÓ£Jý—ÒxYÇ0%y¸´Q×|÷ç7µ1 ÒÊÂa›:‡õJ£æFÕÕ\3m³è˜é ¶Ÿdf^ŒŠÌ÷²úäÛ° ú:æ¾Ï˜w4† :ÅG“ šAdF8ª²p…Mé/pF#ˆŽdHÌMá ó_§½i@mv} ¹€W)TDÆ¡Ä>8›ðÙBP§À΄Ã<óÁ÷,ói_à@ ó˜y惯ß2ן›‰à<¡?øø¾'B¸ŽÒÑñ'A{%¹oMqƒ¨ýªƒ‡m¿‡ƒ×Aütõ€ö.>ñÎRßô‚Ä­_¶;›TÆ;ž‚‚…K'qºƒ µ´€ÞUØ•¦žƒiô(6êŸTGϨ|ôñ·´†<1 XWûpj­†”ეjK/ †Mvã¦q:®,D°0ýþ(§:ºâµó@T–óÁëu“¼˜¸ØX9Éï ëqûAcÛØÚŠMžBž“Sð]sºë¦\ÃçAP˜Jn@ú·‹w©42¥RW” U‰×Z²æ>ªyãO¯êŠ»;Q=g½6.Ü *¤4ÒÒ`Þ½]dÊ…³*×ü‡]4CK­¦Mdqô¾K ÞQ#»÷¤LTQ¨ò’¹j¶íWe…ˆgÚS‘¶f—bÌ @S±@›Ô¶ÅL€@ôд‘•Pª] yLuŽ€9°[ëÈb±@"ûh½øJrµù•áCëÇH0KËoSp"o|[ #_gþy**¢5rÐ h;"*±£ Üñäq²úìIßP¡½JØ·š¾É=éÛó’ó/Ö³C¦<²å,–&Wãxh#y ³pE%Û¢ý|΂òˉø1Ky''±Ö‹f%µêþSÜüVq ÄŠÉ«uv«×¦Ý+ú[NdÀ4ЖöÙâH´§Ê½X÷˜Ö…ƒ8ÚŽÓJâ ÛÒý­¦Eµo}gH—pÛ¼Â,퇨ú£lñ‚ìêË$ô&™©B8®!–õ\[+Ã[qž|]A`Ôeƒß*v[+¸ƒ¢ÊÃëíwlDšªìâ÷¡¶ ÐX¬^Mï¢Ò¾Ë^´wUÖ^˜+¢ZÒÍ!C~ÿl)7Ðn¡¤W°öt‰ôÛ~wmGšï’0ÔønKíò÷(µk—€ U¶ƒ·óãDìº ·˜ƒù¬:Vrut釸EmÝ~È¡M èÌ/^Örý‡ø¨)éÜDò=©ä€‚ ~/lçàÂðZ£ÈªËr³ÍÅ“ˆñ%ŒËú°ÒÛúË4ú#ÌXé|{Œ-n}Œßúg>ËJî >¤±Kß‚‰'ð%ð/܇‘QSÙ Ñä¸)rc=yR©<®§#k©5UØÖîcEêúvhiÞ¿š¨\ k¤Š&}WXƒ¢Â[§•ÄA§z¿ýÆÂ»cEÈ­'¹éàiaùC|D›w S°«“ìÚåíEÒ¸_`ìÙ?^"‚¥¦„6cQÃ@XÐ*â€wf.s[ ”±µ ÌÔ¸»'Bï3íšRuáMáºÜg`l2dq{b„¨µ VÏ©ÇúÍa}†ÿG4›MÅáˆhÔ^Dó)X6ظÐÌOKáÌo¡'fncê#$‰±Ó­§™“œ·þ¨v§‹:§ª`³4·ì*Ó39àÙ6^Ç>gá‡æ„tž®Ä¶ã¨¸2}àé*^’·Ž®KlÀ:°ë³œ}ëij&1¨& f‚{X…•Éð ÁøÈ|8½Ž]’h8¬¥­ËGò³«’ÚŒ ³­3¼ßÅ_¢Õ–PÐq¥ë«³‹!·œ,m0'~—VŠ{Æ@XaјâÑ$ò— IØFÜ!Õ /4K•?‚]I6¯Ï£È—o€æ›¿%;Å?åxÀk$t϶6}…;k$M7º×okûdFN°­úÙȃwð[ ͯ>b` 4cö‡~‘‰DœÝ²áÊ¥Pø'«–´år½ŠWŠî}g²ð*?³MkS„Å#í¹Æ×“ìÉ%±\윲ó!oÖ À-ÂÅ“ì¶pN|rºz±†Ý~(¾¿Äo̤òùª°ËhŸ9žl}¦¥ûie5o"»fç]|™aú2ÖZý¤r¬{Qîõ¼fÇê`×ùg¼Z»ñ¢ì9?/ß½XE¼Zݽ|×àReS {ê=9¨ÛˆAÏ—P àõRp{Jx3ü/îªn<Ô[/Ÿéß lÊø¹Ú*Ø$oeïï§TÁ¿~,ƒé~.ëØIèSá7iX3Vt„Ýùʱ{•~ M"!Yq‹ã`¥øÜ¯ŽN&F 1°ÐøÌƒ²ÆLæNhj:·,cMÛð¹Ë„´ò/ð¯oÊ ïòü³•«2{YIg33©âZr¤Ð“Y¸. ¤±(¢ÏNŽþþ wôPendstream endobj 648 0 obj 3836 endobj 652 0 obj <> stream xœµ[[S¹~§Îàq:Åtºm÷mNU2„ –XÈÙS)B B¶òïd·-¹[=·åÔÖN_dI–>]¦ç¯Í,Í73ü¯ý÷âfãéQ®õæÕýF¶ùþ¿Úøk#·K6Û.n6ŸÏpYCi“5ùæìÆ#oVj³¬Mš«ÍÙÍÆFERŒÒD¥UUéQmÿWu“ª¬'j4KÆ:­j•›Ñn2ÎÓºnšb´‡MS›¦mò¬òkóLÎàQU°DŽ­Òì’_’±*šf¤ñ…~”a} lfµ•÷{¼ƒAÃsÉV@ UW—øØja¥ÈuZ”\ÕÞÆìIËî.~ì·¬™¼Æ£q`,Ç(WþOdÑŸ¡ÃtIƒ† cš:ÍàÎcaTfUÌ¥íÕMñôöÉÐtŤ>ŽDw›œü]¹‰À|¹û'{¹³\–›¤Q´©‘(5’‚+¾½}j.>Ƚ‡±Ü/û8–†l¡ A‡YëÕ­Šü±4-0Z²áØÒz@&ή!‹,­*A¹…¬ñFÒx$PŸã!Ùú{J‰9âX²IöTHšÉ¢=í£ˆ\ã¼äÊr@$€Ç¢© ‘ZPü oôá´H SŒžÆÝòO¹R£+X£‹´£¿Òü9,ÿZNµ.3cÿ¼AÆÊ²* Ûý=ÑÀ¥ÊÙìÓ¦Àž„i”¸çÁXfae•—œÍ{ 0+¬£"Ÿ•×>ð|À1•š¢i‰Vº'¿.A~C{u&ï=¢EåEš~$…I«RÕVü/žÀÃ|úÈ28Žõô­´};íÃaë yU­kKØT@DÛµ· Ú‚1ºñQëÒ)Ä輯f<ˆ`÷Õ¬ªœÔÜX‹ÔÜ&è¹Tlõ¤+Ñ5 ÒúU^ƒkü¸1p¦uÙÇ8`h¬ "ky§¡RW´<õ“røVM™– 4t…~cuwhv‹ E.…ò¢”nE³¢8ï|‡¢ŸØ{q³ïÂbO¦]lgâÇ×v‡©Kp¯jôÔ”=Æ-ý@^oi0"ê†Á¯ùÌc~2±åüc„<\àÇGü8›¿µrÅ'8óÃOƒ¡û5Aä­6OÕÿvRxѯ^OKš?—d‘ ?½EÑvHi}FØüû0xuy˜Yè½tSçÒà ’Uý‘t‘¾È#ÓÕà©öJ#¤Ï 1D‹Á!)-ä ¤×Y••ó—A‚šr“!"³¥<­' 6å‰`D§½Ç¼(5­¤ `Ì ÿ£Ù#€Á^iî(]¯ÍuEHså! _J’ :ÑÅV^„§»$Ò£N Î¥tÞFÛªiDí³ú!Ve‡À8¦}U£ èLcQÖ^;S ô¯®B2ë˜ðŽ2p½M†œL3è½s Ññˆ;¼nm!¯—÷Gq¹…=cj­ìÎ/zºKÀ.þNB É™ aäÊ•lñx^Þ>2P &qž‚¦sAi´ /¢@Â%¢©§2è˜n-íP塵,“hx`ÛÎcÞñôÜõZöfbb‚V4ZE©.(øvÊ,${»ã­¦À;¿ \ îߺÒ~â;wQRäS«ÒD© u qéMÞÝ®KÙr-ç‘WµÚ‹s›ýH&nï“L\Óh=lâí0>‡æ Qº‚3!Ë~‘ ’Teå;"šðG§DŸ-p-‘¼ÎkçN#ÖB `¦Ü³\›ŒW‚ÞØô1™D{÷ªWeŠ}fu ctU äâÌøŽ*†%SYk¦PœSþÊŒ“Ä©7#ç¹?_Ž¥‹Ùg®ÒÚ Ùiâ³,—oQF€ gRƒ±œDé˜ÍÄB&TÖ@Ö¼–Ò#Êžþ¦Á;žöùÁK~.%’xq¥-0#8µ]lÏCúk›_v¶¼l¯ef‘=lɵ‡œ¡pàMãz.þm°×çèØ&Í›°üÝ ƒ;ýŒ òêça~—æg¥Ý0x*R¢^É3š?•ÈOàÝÞ ­¯µýVddGbt&éÎÜRéÑ&  ¥ Uä›Ç,²óCÖ”¡3ï$+ŠÖo¦¤QhÏAuµY"²O|0vcG!Ú/ˆìªÙgAËLøÇ4GLÁÁ§¨ÍsI mûÛà]é Iû7að«t%L¨(µëO_J­¬¾  -_ þ„e²èE‘†À7ïÝF›ü“ˆ~‰ˆFñÜ”©î¶?ŠW²‚ý1dk¤`ÆÌ¿;±CJ<Ó€¡ÕÅè­äQ„– é)ÓI¢4‘(J{&e5ä![Ÿ «ŸÑİ>?¾½¥Ñ‘ØÞ…¾ ù e{#sc6ÉÄ¢?QšIÊa·tÊõ„^7¤£~JL‡L#Qû¹Î[iåD²EåQz+©ˆ%(ý ¾+JÎ¥¬„Éÿ:ºµå¡|ð5è¾ÿQÜxû%°îøóˆÄʺz¾Š®úÕlK[”V.ÏÈm¤qÛC(dïTtTm¿Q?Z^ j#©zÏ_TÏþ_ÏW[y,ù°¤ ÿªH1_¬m .#èK¤² SVûx/ú‡Ý½´5øiôæBçð£`¹þ}…y:-%ö<ë=äÙ”"[ Ó¤TN—¦´-QZ‹'‘Ò å£×™Ç¯'·w³!šÞ·NœjXm¼²-©Aó&‰L5V„{îHkó:VâŠb°ô|ìýx îóñMåÖÎ\}Œ–öÄmξOóKèx:ÔË£&õÜ&šóÜì÷ ¡èvî^”Ï w„Žvÿ¿Šî5$ŒžX.ÕIZ¢ùö»tÝSÇ:½VÂÊâ¯d¹ŒM¦{Ñe®Ÿ•e¾Œ«[O4.o™ü#ë‚1 ¬îÿ%v(UTiUv‚á$„»µÚ¸Éb—Žb2%5'’—,ÊÜEJ êÈ(QºÏÊÔg”,¢7ܤ¶#å 8ɨöCì$ÄÏOáÄw‘IÓ ‘‹”nP¢K8.þPÒ—©ÏÅàžtïâtËRÀ3}ˆ óÒ9—žHŒEw7W"%1Æï®Ã“Hi-žŽ$›òÁÖÞ™ Ç”(ÛŒ|1cæp*ÒÝŠÊ©.·q$Øçut¶-©ç]ü¼<%º²wëðÄ9™ÏÓÍò”Dž†c®E°ï‡!àJq°€˜ð“—Oÿ >=0ˆ”Ö†å)­ÅÓ:Àðé1áz±Íàz>,¯¨˜¹~éõœ!/[õ¬¼}#ÿDJë@€|÷kBÀBCZðÂÝ ïöÚ·ÿŸ¢3Eõ° $kâ×äý*V],x[ŸWÒ`ô@?]º§7ì©äj¿¬<—NþIœ}‘ÎGð^’Ñ¿“î[nKË`Û´¶:ů¶]Ùz–ô Xw ¯bí#ã XÿÕ±—Ä.ú-i[½dŸ’Sf§²b}éN‰¤˜r2Ë{ÕÛžU¬ð«”Œ%šìž©Ìœ¿u¨gõÈCÚAÖµ8ãƒu[§ª2-”Еen»qÌÈwFq­ pÃ5¹ñËŽˆ•æŸÓZâÁµ‘œK¶‘ìï߄ᶩµ@ݱÀ˜„SéoÝD†Ã,I|ýo&Í‘t­¬ùgAÎþIKÉõY[ƒý3ò£õ‚.„‚lð*ö}B¶è*ÌàUˆ/èíJWA°±³ —ôsîh ¸,:\Òûº_hTÈÀ÷ã@Xp/v<î[$ºªÒ\eÚçÈô#¸ÏaŒ¼š¯8Û—ÇðG»àOé-7ñ×p5Ym½*âM™¹Â…¤Þø%1ÿ–Ýi“ôc[gH´3Ûø þûÀâhÍendstream endobj 653 0 obj 3372 endobj 657 0 obj <> stream xœå\[Gæyñ8o9eÇÓ÷n$â‚Q 1ÊA‘³»ÙµðzlŒÉ¿§ªúV=Ósnë$ˆ°çLwWW×å«KŸï7Ó(6þ—þ¾¸={üW¡ÔæúþlÚ|ÿ¿>ûþLÐ+›ô×ÅíæÉ3zÍã1LAlž}w''7ÖëQÈͳ۳¿oÝ`¶Ó`þñìO8ÄOÍgGéaÔ³Kxó£á\Î… ¶Ä‚×aûá ·ŸçbÔÚ8¹}Vßù8>UÚoÿ OL»5°Ø8œ;çG)ÌöÉ G¥¤õ4͗ùNøíSëáŠVU0§µœ€? øÉY—^ br|ñ4—†ÏõxAÊQª‡)%¶ Ý8áÇu7@÷/á%¬(¾‚´*“hñRhӌڠä(&!i©QJ dÿmã4)Ò*4h¶>[4‘.Hgb?“ót(çÀP'Bˆg#µµƒJ#f_Nðóè4Ú©ís8ˆ†sd¿r{ËãÞ^“‚„íÀdï-~SÙ™¿‡½ž©¼/1)<;:Xšs ñqr“Ý~“Z«­á0“ÓØ~[§‘ç|ŸYÄ #ù§á\Ggét*n‹Mö2OVˆ6Û 9à®ÒÛ»½ñ¦Žº…™Dg5¡àÔ5,ò>Ez d”°÷qý‘05NÁg¶:+lä|³(ú×e³ (Zá=—웯îqIOgÆf¿PÔ$Ø,l›•¢W8¥¤)_×§LlPkãþ¬ž\['QiÉ{6ðíM3q>Џn0š/üºˆ&Ÿ&¦ ЦDIØänY¤´%7çŸdäÇÅÖÆÎW¶K;ÅCR#¤dJqUžáËgï9¾É&›ó×»êý4N"®Å¾¹„oÂò'øÁ^®gÈ6½é„åSÝã"•œšé5aŒà4JöÔº©‹ƒ¤²áªBŒŠˆæœäÚy®'°…‚Z0P@âOx^R*,ž½ò°ÛI99Ù(ì¹ôÈ&Åר$|€ókP·¶E ÊARˆ.[ZÙ*×IµU@ïUðÔIJ ùËøÎwøO²¶®‰ÿøÓ´ÌË¢+—UAò†¥ç‚ƒãš—ÒȤ¦h >2 e”7¿nüm «P5—fbŸON›²oïÈ;>\Ù² MÓ¨´:Ѿe{Ô¢â.ÝÄ.ƒ,W!„Ý«FÌûäÉ¥7í YÑgLÛ· SüW×€Rè=‚5¼Oâ6Qgñ?Æ-¡C2p²r2«-Âá3äIŸ¬0õí¾°V—ðoœM‘÷{w 6{a¯döÂÊ…UgWK¢O;oÀsʇ»A%Cóvv¬%3÷@¯6–ë_ƒÑ€M“öÐDv2ò'mCWÀ`\eVµN‹è2êê Ü„TYÄöã¼*/êÃJÈeùtU¿F l"€•¿¿«ß¿*¯‘ú@°á}¾¹åê]’ž7›K‰#ᤕßÖ7_ĈÙ.›UòÇ›f¿é]QÎãÌ%jÑÓê}„ÁbÍ.@Á“ Ž1oñeŽÍ`ShŸf0Ix¥½5JL{ mÎP+EA)ù@ YžËÇŽeÊŸ"úC`­è#ì7ïÕ‘%o1v«‚!Ÿç®xð¦>ÖÔdÔ2 Í\k]]“,- ñpà^ÂÍ ðSë¹I‰°PIÜZÕšÙ„îÂKÄŽ»Fýà?+ìHŽÊú3\ÊP@“3Ö­$frÐv±/RƒW!Š''fàt0ÉÒÉ‚BP‰Yø‡gAc$ŒÂ„e¤w%?‘à\b‰0ä6ÅÐÌú®„&ÎLf¹Ãy Ý$T0×èI’‰_I&ßVuxÑËöƧ¤Hd*,*kȈÈCìÎR…Ài–°Ûc‘¼kN7ˆ a{GæNƒ¥À´ÐEF[“éB-nYq’ÎjRäÌ¿þ¡ Û,õZ†~Rù81°¯™ƒYž¼q¬™ÎOÑ}çZǪd¦ J7÷q;€w¹Tm"¢ªĩÀ RðDú®4©­–6 „K®NÅŽ(„¯{v¼š‰¥=Ð$N& 9¨rZk¢…OrE¯”a²å†¥âÓ)I·¾Ì’|‡y–èÒv'âìÒÉ£ôW=(¢Á?±óVXü>D˜2 %ó¥VJ {½Û!ºt%v×t¤>¨žaòˆ‚˘.3A9ϸ —Ò÷ÌŬ‰¿pù²ô—s¹˜4Ã?{y8ªó­ eÎÓ2³¨r¢=fÛq‘iZxÊlƒ‡ÚÒNÚSI¼­›YJ&Û2mûLü,cÝO™wWc…üdFqc—­ï”-æø®õI›ÊÛ4—^¸‘©\ËùM #ÄíÛSòD\‰Õ‡S=:(¿ö³†ô)KgF[Ñy«Ò JvmUÓT×0ªJOD“óµ’|`’aY`$ÉÓ¸hL?$ ©5W‹YÓ@ãVíI-²kœ½à´•žÄ e©g–L–†RÑ]cþ¨ÊíÂ:¦*Pì áÎý–2Ä‹¶ @Û5%Ë›ºÀ,c)ø“kñ,ᮢD$ …(ãDÞˆíoê¿BŒÖﯪ½`M R IàƒÙdÆÀ¡}´8gØV»¾•M*R¶£x­ýÔ–ü•Æ*¸h«øÕÀ²z>ƒ8LúK§ç–œq®¢U‰}ÕùºÈÔ õDŠÉ{Úßjp[…öº s‹¡Ê»À*“ÜÑÒvªÔ-Ë<äA ¾ó0agñ0 Ôi)Æï| £¸aãÜ'Ø(‚ö3éŠ(‹Ëé’¡%~±pc3#Qžÿ„í¬ˆ]&:ö/Ö.Ä2Ñ¿#üˆuQG¬üáÈ*µæþ£û6 Òœ²têX×’ZWØa¶y«¤TŸ"­ÙµD;R“EþÃ!L\¸ê¡ò@0wÒg߯åô&OÛâºÖ•¥uö¦Ô6%êQ¯¶d%›{iM¶‹%·Þ]c"3ÉNè¡ôË*×u8š:àè rêQ÷oO¦c×ZÑ*S`¬½”GBà µ[ÎŒJ L ¢€ÊA Ƚ­‚¹t/ÓRÊuçldí²^e€–žFì°‚c²”`醼w¥rX+o}˜B.mA•Û™ÕÆØ÷~`n³ä¥/†Ð>Cìeu¢ßXB° %m}ºM Œ@!µÔC“AJ¤€êPÄXD‡õÞïu €£hÓ®.`;øÄQE‘Ê>q$òÔ,O-J0˜÷׳#³Ó齜sãi<,­©ÿi͘ËlÆJ½fÇ?ÈGÔ‹98ÆœïâàlIÆyˆˆÃß«wò:IG§×d#áóòÓ’ßhd‚%Þõ 2?UPHÖ\ÓŽS5B’‰詚)ÆŒ¿Õ÷™‹Ž<7 Z fgu+"^B`$íåC\DS]Žöà”é¢.e(@Î=CõbXÔfÖ¹( ÷Hp±~^·ßÂg$eN:b£ê¢ƒ//>ë$¯æuíJD#š‘´OüWû÷DZS÷^“ÇûE»÷XûÃÎî=µ§'éy~y^”?¾É#J;ѼqÏ£ow;;jgÇý‘M{åäwwáaÊ㻌€âÌ­ÿñ^=9¡Y[혫 -»ƒnfk:ìÖ9¢³êrÏ>_Ô·Í¡ç^"Ö«vßÐÂŽÝŒžÄ<Ûÿ³õ 7Q_f}C~oßÐGÕ³5±cuškÙ(nˆÀæ8ªœ¯öL$»Ò½}53}»[;®ãd(;;ö|S°É¢JÜ‹ƒö—7rÞÖ5qd.+³È0Ì|ƒÞÆÈž™¥ÃØeÚÜ–»r@s©Ì/U’­ñ5Ï7 < ×ǧÌ<7 ¢ØÓ!y0³¸JÄò¢‰»‰O‘¾‘7F¤>ñãîbCÌ¢8×Ô.4€½]tÞKŠÿµ³6ŠXU7¼1ªž@ÓE' ¦f¼r«5—çŽë££zöéz}…Îð\òÍÔëÏ ‡>J/ÛðçeZ;°+Ôù®8öi “v´=áÇö¢œà(„z‡wMðº¬ZÉ;¬%ïcǽ¬¬¬ÇÄò®\A5™&8%38êýA¼à üª×£—ͬ üÏ!^‡†#a¡<ôÕæ‹¦M.î¢ÅMuK«EU5Þ̦šp³Ýbd‚šXŒœL÷’Uý„µ/hÚY~åèîHgOaò–" 4¢„ñj,mø}9×»VôÒGpàémŒc—ùÁe FºÔ¤“ñöGƒ”2sײèH¢’?kUa&3¸êˆQ߃2¥íAVPoJX†ñI˜E. Ôζ5IL¾þäzáM¿ßªiñy•=[çÎv–\–m÷Yüá¨ÁŽ S—›¦ìuhðcOŽ|‘ß–x'^Ó¸àÀ<†îï€P컨t]²Žýzãb84æi÷Da€gA΋L½°Aè"Bàt1 ›âÅŒù œ÷‡NèÀ6ÔDS ï·WöE•û¯›PaU\ͦ&›b¶Sâ¥z[aATóª™ó˜påe _%ÙÊVCÓ¹jBÓöÌ­u÷½cê^ yÓD]é!ÅDåFÏÁQxW*ßÙ¦Fœž‰bn†µˆïˆ§Ò/¼ÜÌ}NÇ@5†P†‰’X¸¾ö²Elê3©íÔ¶E®5qÈshn>OßCƒ¹ÙBœK¿‘´=ð°Tr­c>_°¶ÓœuB=yæâ°H¤×\GØ=Ñeÿ2žÕz¥úm†å'`–Ž–!U„Yµ©÷Ëý›þ‘— ëé¶ CòÕª÷³,>G@„ÇÜâR©É€±òQ>{­©TØ-çw ìz~ µ0ÒúÞñ–H–^˜¡>4 Z¼ô¼R9ÿù*úu*Vù2Á¾žŠæ:üji”zx$¿qÔiƒÄŽb¥Ymm× Å&ÜFë»—Ê×Úç3âÔ¦‹£›¢q®ó[_»s“ 1)|Ã6uÆôÄ4µëôFÝFÝëthÂ.ÙLùxL•›ŸAlÍVDJ7€—B3šÄ~0¦°Tؤà&èç<ÄŠ(•Ò_'A…$¯õ™çµœõ3WšÁóÒˆ¿¬Á(lwñè.îUµ£;×Ci?¦ß‚‘ê…V&VÑoJK¢\H8ÓkÞÔJŽÁ:äÀ½ß²ž?+f²âg›½1Êò²úì]I¸ú ¥3Ã÷¹–Phû¦\L“úZ6‚ÁµŸr±:½’CfÙ†,½³^-/ÍrMŒZÖ[Õ¢ÜXÓáÍäkõŠOú)G=#[E&üì싳ï7`÷-ýÆ#pÊodpðù™ æl/nÏž<={üô³Í?¼¹:{üÕFœ=þ#þñäó௧¿ßüêìã§›/Žý9IÌcy ˌٷåÒy”Þ¥¿ôY݆’Æ¢eüÙ·!^×n¶q4ÈÍU~$Êo= NR8.˜ÃîOàY–ü3GÎÓUMöÛ`Uå ›m~n>b¾lò-{ÐÛ,˻뻱ZýÂO~¶›ù•s ­‹7¼ Íó¬g«no/|P6‚%Þn¢9ÓÔ¿ÙÀÌRáÆ·v;ètŸ6K—Š™‰h¿5„ßÀÌàw1éBlêU¯]¹ëQžqst²‚òL Øgÿ!pendstream endobj 658 0 obj 4976 endobj 662 0 obj <> stream xœÍ\ëo]ÅÿîòGø[îE¹‡³ï]$*¥ÐVm)mÁT¢P!'Nbç„ü÷ÙçÌž=÷ÞØª޽gŸóüÍìœóòtžÄéŒÿå>?ùèK¡Ôéåë“ùôÏðÿåÉË»œæ>?ýÃvóØ4…9ˆÓ³Ç'iqêä©õzòôìùÉ·³5›i+'çœÚøøÇÎù0ÉÙo¾ÞÊÍÙv§&ç¥Ð›¿lwbò>³ù Áë[ƒ˜]é+fµù~•º¨Í—[%'1K½ù>—RZK§Æîdê/àÉñO­“›¯¶;¿ê`þ{ö×xxOO}¦ÙÃÁÎ.à0ö/¶¹§ŠöÜÁ|“õ§;5ON„F<…=l®ðÇO°qÇñï§¹Qm^ã>çYˆÍ÷øç üqŽ?^•§›Gøãû2"uŽmÏëˆë0è"‘xÞbí,ô—›`}9ÇµÓøÇ­Ûem$cŸÔƋڈ'—ð;žo'Ôdì,ÓA¿ÛàÒñÇ“²“4úU>8Lùa=sÝ|êÓNŸÞ‡müæ÷0(Šd{X»?i»äëÌašA’>¬Wz–Æ‹Úx?9{Z¯ZO¿6ý3FêÜø– Z6¾`,ä«Ãæ_ýõh¡óQãÏ­1ÒÊo¾Û2Æ.„§ô¤"«•˜¬ .±šèÕ“ª=ñ,ÊNÆ¡hg}¿j_¤_ílq3¥w¨ ”<j%REÃc!% ˆœ¬uVÓñ?–éq´öqôÃ-L£1tKç ®Àk8„²³Ž>¬sÖC…³nRÒ#™ÄdŒ³¥§SªL¦ƒ\œÑ ÕH;øÇä9¥Ò”­‘L„»ª'ª¿¼Å€1Sl'äl×0Œ²DVÐjt>+.‡¯¶`/ž9®MµÛ›)XQ,žÂ#Ù¨¼mN÷ ­.Œ㣒M gõb’¢‘À9@ÒÑŒFùS&CžŸ€¿þóX+íu§—l%;Çí7 $ͮІ[¾o…gåM\<—ŒÞ‡¯¯g]ÞyäD%Ó>n•4(*oL t£žH*W7=K Þ|Úô1{@å\&„¶&ÿf ìé‹ä 5¨»sæ†ânкx…>VgÛàBn˜G:Ý´-þ35‚^'R>Øz4{¾©껼©žÂvÀº€cQÂU‹„ÏØ|° @ Ô俲LCU‹6(UVm˜EÙƒ¶ßP!»Fâ«hñWe?ÀV´NžZk¯dT½¤ë4¼ýv½Kñ¦a©§õÉUÛÛe‚.»r.Çy\\…Îl†}2VM?δÍÎÃê<’1øÓ³ÏOÎ>üv³Cº‚)÷zèj`'e­û´ C{m±(ü(*YB7>2`hÿ¨¹;/„£³j?eôþ~õ(Œ–ØÂKnZ¡³C5gMG©ÎNWKNÖ%~ÛXe€ƒ hMwp<¥$‰Ç¹”YÚ›¸X•í:‘V'Øf|”J²(Îòëv7GÓÈ)•´uT…ÖYƒôzœ”ÇDtœYìÛ2Ùsƒ˜á'ž[ZO<÷,ˆ¶Œt ‰âL´‹T;Lg¸Ðd…&+ À$µÐr’ºW‹Ê&&8>¹í„Q6Ú¢m²€?H¨A ˆ&­ÄPðÞ&âJ ðÍV¢¯2†ª!š2dž„*P–âF«—³Š¶†1ˆ .*®|Q Ta»Ì>vyg‘À‡ò¤G§ÃàÔŒñ…í 9cÀV QÛA›qˆ£ñrŽŒ°-ÁcÓ‰ÿ`Od FQ g39[r® „AG€¿îæRBé¹È¬‰½W%¬½‡m6/¨iŽô„Ís¤ @%sc‘mÐeÛ Úôˆ`„8 6š{%ñNŽÒ 3ž›™«†°/zÌšÁ1¡5ÚAï4Ô´¶ j˜piÚq¹*?›@܇g'3¨‹½›_89*c`Ãß4Äðt°,|J2Ì‚ t;3ØÖ)›ˆ®cyØ­êÓ/4M(€ÎFZà±Í<.ãˆ6×å®އ°¿Jw2)³YQ~âäjLgÞ‡™F„úÏ ‘’†*Ë&è/’¿L4œ°®»<‚ =ýR\`…„ë#­¸Ù_Ý‘zµîë.rpYâ(‚¶FÑsöXÚ„(°ÄÇ`>d§™Üµ-ëÍ­u©Ë¿ÔMÚè Á’§´Ë{°Ô·$|ê¡"˜_uù£‰—9æÌ¸ÎY{<Íq/Ø‚¢/WÃÕÉ™3ª/O~hÛ@Ç97Ôϰ;:ùU¼Ÿø*…ÜÚøõÀ ¯Ëv“‡gzt%¾™ =ñ #]ʱ.Òƒ;‹!·ò&Md.¡ðR¢‰*Qó OÆÝÊ2±€®§Ž;ä®êKrDs#_E½ÃÄñ>bb0K â9Ѓ¬~"_’¾þªd^dg扄2 ÖÒ&hÎr56›‚pƒ#7Æ4%ŠKJp¶ƒ 5’Èã(—ó6$à¿’ÜHÇD¾BW¨”dŠÒX¹¥ˆõT¤sBÂÁÐÙ”~ô³H»¸‹HRz3•ë¹é]DÚÇÝöÅŒ(°˜\wb3¦ítn«0âÅÐè"ÕÏkþed1i06v%²·@ðV!{œÃØ~ÕöFïy Wàv ½ÁÀW*Ö´ÇÜa¦âÝD3¤²ˆ HjÖ5 Sˆ§u‘IfLnPU»æ0¥òßP„M Ã1Ul_§ãë×ö棭é”#ao8’ûÐ2OÙá½¢©Ÿ4RßÃEUŽÅî(Å]…öHÞ1,G:¹9†’|EþÁþæ’¶ … ˜oIª À¶YAÏŽDz¿×íÎR--¢Fn¿®UoÌVÊcÛ°õ8ÿ²@4¨‰ƒPà>ή‘‹`K¼)](‚‹»ºdþ™!Ø#ZÚ ø!r5 ª ­#™j$.sªZz¯aZ§6] >ñôP ¯bkKÖÑÙ.íØQ[È}—(ÞD7„{ôƒ¤=[ÌÞ#bj£ V£ü~É·­bÛ|Á1 (°;q㛳O>húñ%ê ³Eþ,­"ns©Å@¢wØ2ñ+]ðÿ<‹ñZ(yTÞy%i‡·ÂÓ¶z%wßb{\¤-W­dƒsÒxœ&±L="¹‹He-N¬{s%’Çô½±†¦¦o*Ç+F$5÷máZ¤R²Ã€þÁ…µ¹§´6j9áùú)HŒ'C€%šìw{g;[7_‚0£#¶[ø«œ_ î…»J>'î £5rÅ“í¯¶_€z…*:èV @ '9v1qZƒ)@‘”&°$£5ŽûX‚$Hqæ¾™C`C’©fưŸÑÏ%u)$oð’€b¯»ÝPõý•Ô«Œ"Ì…î²¼MÖÝtc™µˆka ºz¹÷’PQ¬ÃðŠ_¥'æ1‚jf™f§â ÉÍ–˜•y›X„!7(2åÃu3 óÏÁQÖt6°»PÔÞgªŽV5)ùn»žRD1]Z¦¨÷![òAk%‰!d3AH|“—»¯OÈÆ!ãw9õ¥3%‰m-áñR`K ýõí<íIæºY ÁNB¨! «·±õ’Sš”þç=£QvK£Ç±t.T’6Dœ;éMbTO—dªÏ/.¼¹êuYÜrÑrûü:Éê Èi¼TM¦P!=|‰%Ô4¬{¸"–÷Ë¥N»´²>Æ=çqÂqá/ä%ÉÈGé0†ehÖw÷5äVðˆªbNß”©åõ3‘:Ùÿ0*RÊF¨Ø‚¦ /‰Cù™ÛžRe©öIYÑ ýVËazªÏ¡ï¬,e ex PÜWöqdýC^dQhöá%}ˆ5Cq‰jAÇU-ŒéoÿS†_ªÞRZGJÑIf&UJ@?é|y].ޱ c“5M^V!¥ ²nóIéÂ^(œI™qhrv¿IäJRŠåNʦxî¡w·QÃô ]½Z.A3~‘_Yѯ*Åë¦üÒçQUŽö\­ ÎÙ•Ê«¾X;9¼ÈHêñ¢ ;2Å‘%l(¼‹÷X¦w¤’¥Q%芷C’×lzº\¥EØk/?–“ó hQ2Ž"l ñÚ‹*XÓA,Þòö:Þ®ìyõ1ñÍÞî]š,Ã<„â¬kÚ‹AÕ‚FâÆÞ­¢Ø7ßÜä£d‹#oïÊlõ²š^+áWn,ü çhífï{6ä8'å4èòY§¸¾hÊ>Ð}8“U™Fž±ë…E•i†#ìõ›#’ ¹k’õt¼”qòF3“À‚‡ÛÞÑÊmþ¢L[¼îBz•í"‡Ø†×Y—ð÷PÕàM®»Ò;:ƒ·qÑrGŠJÂ^ôTêû†Iö6èç…â 4¬Ub%bÈ£ª¢°¶uµ*ª\åÉ–Ûÿt-ùÓÜ’¢nµfh+-®–æí©tVö·Ò,¯5b¯îÐ+ë|ôÅg>ŠŒ®Úf?Géx÷h z&E‹ldÍ™þ-²ÛKV²§,P=ú{yIÆÛè›õÖtª†-˜û éÃ(%¦wv¶9›ð¢ØD•÷#éƒþ²ÒG•DŒýlË·²æáe¬G´X1†&ø¨ªStzàh@ÖW«ø²~% ôÀ;±„V&òZuøí†UäAiíZb& Òù\tœk%€zNy_]®Ä§Lew{HÔtx¯y‘äŒ×i_§5øgA:iË/øÝv^ |ûqü{&‰§b ÓՒصŠpIki4;B<4÷)ÅóUOIÔ±ôö-õ «¤ÔíêC—¨­¿Øó>W¦Õ-¬{^1Á—¸cn¸‘Aš?b颦ë9 |YJ7sí6cDƒCüm,/ ˆVCaVØÔ+–ã òò‚İšÅ+mÆC‰»Ê…Ð+¥1bY¢ïº*:J¢Æ:¿=ª%Ó­ËÝz·übÜ nJÁ¯Åû÷¬ Ÿ¥qÓ¯ÇÄá³`™ bÀ ûù‹•õGrXä~«HºŒø˜¿ÄÖNÚ9,íŠuqË1Bܰï„åºÁÓ Õ Zý$XûŒXi|U_ŒÛÇȇÞÎGmÉëÖxUñ¤Õ¼Ô¼¨îGÏÚ ~=+sß°ñÿo¢ý³c²púðüüÓ«[‹ÖbV«ó”o¼±‰ºçïÜ…é‹. ›5p£)³·’¥4¼ù™(/r»³2 @ø¸ö*ŽòÑ»ç´gù¢_Óòé@|ž¿©÷l4ýÛÚø¦5^×FþA3ûXõ¦>:RU´orŽ{:r÷€H>ÙÖo :ù¨#YÿUãÿf`Üuˆ±{šÁÓ/&òÏ,–^-Z},§ó–¾{ÈŸ Ô!PãòO)àpñ‹f¥õAû59!ðWä*þ³N–´Z ŸF²ëL|¡Òñj$oFÏW™—Ù|9ˆ_VÄ9ñ£ûdÙóáï_.Ž„ðÑh aŠn­¢1e×d„tðe¢çen]ãe•‘ÆB ê7ÿxvò/øïÛ|M"endstream endobj 663 0 obj 4914 endobj 667 0 obj <> stream xœå\Ys·~gùG°*Úµ£Á±+±E%v,Ù‘˜Ã%û")йK‹¤%ÿûtãl`0»ËC‰ãØey„ÁÑèþú`Úí;¶Ûã¿áÿ‡ç;ž3!vO.wúÝ?Á';?í0×e7üïð|÷‹}×ÍBS7ôÛݽã'`»†ïj+;Æw÷Ïw^ÎÌ\Íø\ý¸ÿ5±}1ÄèŽ[µ=¿œ/DgÌ0°ÙŸç¬+‡Ùç|öÝ|Á:)•á³ýÜgÏ· igÏ¡UÀ´3‹uó…1¶ãL;˜ËN®­›æÅ|¡`€avö޵ðp« ˜SkJÀ“9>mB×õ†.æ’ƒ¢s} 8ï¸â0!ØìÙ<ÑîåÝÝ=tRÌrX‘1ì‚´ h±œIÓtR 0@ðŽõŒ»¥:Î9ý·9ïú^qVqƒªõÉ¢tn˜—‰`‚Êdd€PÀPÆÁËf3ÏØ|¡ù ºžÍŽp¥¾glv<_p”•Õ³³VãmTýφ4¾É=ñ=à/bö¶5Ó/©ñ}n\¥Æw¹ñW²Ý` v ïO[4ÁòŠ÷Ó4¦ÆË@=ðv™rÏóbŸaÎ×ùý»‚f|”Ââ(²~ìP1·2h@Hjý*?îçÉ^äÉÊâãAî{Ôì@ˆìR_„‰é™Þ]pÓ±„ŠÞç {¿È\´d˜Yw´=¾Lïÿ˜ß?Oó¶/SãU±©12!'-BVaNö&Ꞥ÷¥TBã½Å¨è^G Ù4rˆìäîT[éž{éÝŸ’Q¾‘õ‰ê,[=¯233’ÎZ,Ù–‘D¨—ƒÁ]“å?L¨óØ<ÌPXµô&‹ª­4ï‹¥bßË7ÁŠ\ªB¸‡$ŽbEªÁîî³³ÿû—ÿA»úsËfp]mÙ:™d™-‹IC㣉å£L[àÉv÷¼…½e ³@ý둜J¡è; ì³rBýHëen-ÙRa¥BÐÁHþA.ž^Aû~‘^Aìª '›s„Ë›ˆ¯NLÖ¤ÿ Jl5^µÆ8¿b±™”ï&† ¯ Ñ|ßËÛ v«808™¶¡;kb²+<Ë(¿[h‹A ÇÌÀ[Ž˜T0=û'ä˜c=…¼Ik©MÚ¾‰cg©c¢{=û & SL®,ë… ÊC+W’a+˜r¡iP°Ž •È«9ìç}žæ4¾Xæù ØÒ÷uW÷äî2GÈ‘„t!%È )8-™®óÐKܨRFs¥€ÌЧ˜ŠJÀŸ_{‚À‰ƒKU8Ì­ë2&õBêN Ö$ù"?jÎLu¬X2îÍyL­–tô™·C®"HºM³Ö7[ŠÉ÷É\¡®€[#£?s%ÛI)Wºëm†ÞW˜>Ã?7³¿Ó A àbÌ`PÝzg"yå¼Á?Pk³_³åßY®ÄÆÓy;´¿“Vã»[z f0æcè{o´ŸG¦d~­aàLàß%þÑ¥I5ˆAi—×c¦_¶‰‚‘)qÓ1xÝ2§y?-®IÓˆI_µ¨j„{w¾mzº_²¼·Gn#‹÷F,$üÿë%ý§çµçºÂ?²/uýzüÀ™ÈyÔ»d¿ÜSÞQ’}f;>&¡×ª–Á€ÒCÊMÝ2º*6ØÖÏBXÀ8µ PÖgs§£aØ7Oæ‚ö@ fïR`²‡tb®å²0g¦ð¯ÑŒ=ñ‚”-ß¶&OEмj yÕBÒq IËcäRR”1ÖonJ-î/—üoÔ*Gb:+ð9¦÷íf]¼‰-Œy鲩ç­ðÒ!¹ ŠP~1eJY z5ZUÜñì€9¦ )88uXe¿ÿ>ü&&g \áŒèüP]X/Q™·©oaxïX‹¼OÅA5ÉdŽ7þ ôZ"õé’ëzà{;Ýš=cydfEF ö+cæåÈø†A"3³äãìS‡/ü;…Úÿo`êõkK𳦠ÏMÐuc˜DÇV–y&rë§.L=ðÇ0áAiØÂËÒ®ý.3>ÊYÐjìëd£ÎJ¹¶÷É¥¡,P ®´mƒî d·uQp`]ˆç ѤWSö¤\}Ë/~™Qö›ŠÔÓ{ò¹'Ã{Y1îŽÇ*¨_d‰=N¦Ò)d]SÂ=§Ô}dY÷7–Ÿz`åM"~ÖñÓBIJ{(ÓÆ`¥]n#uä/R: SåãëlörÏ/ `Ö±º¬¿´X=K°z`åwª\=H€?¾.çjÞ„¡,§XQ²XÌ_𡳶g~I>ǼR4+y,¹ØŸ[ÙqðE±f£{éŠ=¤dFŠ4©&•ëAš3ZÃB¯$µ‹ØÞâYèÍBÁ‰qŽ‚ëÝ©ƒ.æ\)WÎ#5#Ä2TEy —$õ*\SèN•õ;TÈ^ZÔ*DhkVúP'¥ìÌ Ö®»?œ;asÁ0§Ý Çr÷X½SÂíw9OÅø´FŸÔˆ³Ç. aÉCIµ:ùý²0ÕѺ¦e*­é‚\DqâtéÉÅmm€}aàSh´ˆ$¢Id†àƒõÄžG§/e;Ê«6— ƒÅ¨Å™kk;žìu )!™cJÑfœ‘AÄd Jýjš»|(¢/;jLâ×Üøf È"l!!zޤkñƒ±Ñ)\“`œ•ššœ(BàD}NïnÁBˆV®0ÎÖÈ4ø3† g> Šku#œâhD1Ð=@ßñ£„~]ÉÙƒùÄ~’[Ih11šŽOš(ˆëaò r™AYƒP¤ï¢uU^x1¹HÈ%@ƒ“¸íÂ`i¿)%sá+.¾¬@m³ì­Sô›GÔE¶êVQÓш£JX“¢ž¹vÌ|‰1 —¬Ô… 3éößãm;i¬=:xó@ "ïº4íƒ?ÝŒµì12³­TõA@U/«è )¬Z§ÎAý.Ë(g áÎ!Âɱ¨'s°[f€í’Ëá IozM_-s ¥Š cBÓ™ÉÅ–ïÓÍ›ïòýr{$F$ Õ&ºÑf4’XåøAq“#ÈB7·¶Ó1NQþØK*M0„ p;Si†#O`…VôX‚³•ŠBaDí ŒDžË2Þ)ùRÀ=Åò¤j“^ŽêRN?Ðãhn 3^ùôqñŠ&™>Êš1w}ª­§µ´Ê?; L+IŠ„@‚Ì!qÛzp¾­ ôÇ6UÓÃz…1“éÍõƒ£§nÅENGbóX 0è%UÈ»€Ûxµµµ‹f¿¸ ™° ;=~} x6Û¾Ò¥žü졉–“—C’T£ÃG4CRÍz=,;ÁÚÙ?0·uwÞÈm¶‘¸;Å$ºwœ’&žü¬J•ÔoÐp#ì´4ÆmO?‰® Üé¢_:tZŸ&¤žÏtVaÁÝýÀƒ:7úH‘p¬d·2=r8Ö‡åLoЇ‹=ŸHT«bw™ñuþ@) e|!ÐvÚ Ð[±›ØÒqŠ_XÓv–™ƒÊŒ”–5’¶`ÆŸ‰I‡™Ú§ CF?>hŒ™[.ú%ü"$‡ša¤ûˆ¿82¹bV£tËêUp"Û£‡dê¶o¢A¹H:ŸW¶–qé«ÚÜè¶g'&µ‹D]e6Ÿ¹ÆD°×¿ÐôŠ\€nÚ[¢mYyŠâ5FÜÚ’ 9jppàþ4œ¬+©”£izY&‰ ä·?!½LÓæ~LOùmÓçö‡eÀá9RW²G!›s!ÃØ2F;Lb‡J2jèPŠMÉàÈV¡ƒ.1ºl,o(<¤Ë#ÆÚ€~ºK! á")ŒîLÙûЛ—£+?ƇôŠ%YwLYY,ášÙ_rб.ºRnˆîwnN!J8–z š°Aa‹ù(|’áC²å©XTåoUTîâ¶1ŽiNE -DÇëÓž„èûP÷ðŸÊ G$2®>C¢µ’X‹?I0 98¬¸jÛE\*°Y»ø)Ôõ dbQ±ú»)Á~¥£Ü{€ •ë˜Q 6Õ39æ»dœ!Ékm¨Àeœ×K‰C Mj›£’ZQæôOƒ2ÕîpeiªOI4äò  ÀlTEðJŸÚ·i{ú"oÖÈÛm"BàØ}àèÛ¸½‡QGDŽås,¤ÔAŒð(í‰ ¢”KÉ‹r˜®Ô þ.¼‰ÆbR…˜òÓe°ô4m³B¸Ï]¤|R•)¥ÚH’,A2Ò+$ÝvŒñ-Ãi|ßÚèΚ¡ôDñD@VJ÷Ihã.I§úÆÐZ¤4ÅL-ã&8ÁÁ|å‚`‰®&Hò—­õø«§¨¼2´üT\'fì¤íM3̰‰©ŠvÇÔ×—°·o=•ÅÒÂ6Ê!Ó$Ri¸ 71·³7:H Q«``ê{³ÚÖ$‚%;)ßT¾)¨:ž¾)+%#/µJᘤ‰Z`¼0©XÊ5» ‡`Úü;—ìÑ{c+æ+jVضëß6¤ÿVØ«Ô{ãy¾V©¢9ʵl9#æyVEò¼ öEjYœ"µõA¸ø¤H Í2Xö·\•½ÏÓG—H9$ÜèWðÒÂÅ/ß³ÍÓùT<°®p”§témò{FÍ£²'­Æ|2–ü8ƒûÝ**_¯#‡X[ƒŽ[=óÏrä×Gñp±*ïéÅ›šùlôu‹Nrìø:5^å½7{ßòÔryÄÚ_ð£§gñÖ9Té9BŠD-ãkBÉ« Þò%ý¸‡$ŽÁ„”æ¯T4S?O°ÿ§qírU@£qéñbªCüÅ‹âçœë×=xMr¾©1UyÙ­±luë,ÌY:âó¸NæñZÙ2>%63pù­Âƈÿmâ,þ®Ò}â¬8¤Ÿî’$ ÑUÚ«´ƒ5V¬º xTúw·,Þ‰¿?Ò¼‡s¹^¼å5ÍlÂ×ça¼Û|¿"ßä“Fêp¯>)>Þ^Æ{û;…ÿ Qè—÷endstream endobj 668 0 obj 4490 endobj 672 0 obj <> stream xœÕ\mo7¾Ïú‚ïC¤4Ú,_–ÜmQš\Úú.mÚÆÅ¡×…c9¯²åø%mQÜ¿¾Íp—kI±Û¢"­¸$w8|æ™!9ë·ÓºÓÿ…Éýo„RÓ“zúü1y;®Ê4|L`µ‹ª®îÄôàùÄw ¦VNM«+!§'“ïgͼ™UsYYkÕ¬u?¶í*Y·³oçrv0_¨Ê¶RèÙþ|!ª¶íºfö/»®Õ](íDmc]Q«Ùwp)-TQ³oæJV¢–zöïK)á]cuÖõ—pçþÔº±röt¾hàRwÍÿrƒoù¨ NU·0°ƒ% Æ‚üjj*¡xÍ…®E%Ìt¡êÊŠ®ó-þÝËz¶€/(GqOAªÙ~œàÇ3²®…˜ãÏs¨XwP`gküýܵ¯jѸ߾&t!Q;­ÁFè\Çtÿ<6Òî¾pMÎù3]MxÜ2¾¢š/J…—©ð"¢J„ªSü?žÜý~öÁÐqDnü¿’ØGøû%~„ÎÝÏ£ÒcùH™øÔ»ƒ§®ÓSWñѨaÐèa*t¤ÀŸ3ÇË%¶l«®µ¨ š‹¨ëç%e”…CqÇžŽÒý—tÿ°0@V¸Y)ºÛh›ÙYiú/®ŸTV˜A.\Ý£Þ/yïpmqLbÖ=^jÕré_v’×] .¡ί„k´¬EBšØœ»ã0µ 玄òxrØvÞ}¥·e{Z¥Â_É4®JsHú~N…TsE†|È›G°ÐƒK3sIO?+Õ¼ä5‡"1Øœ†wº‡Ú0_—%2Za³ñ*“4Îçefƒ…Ž*`EÙV¦­…Ÿ²WÑ!˜”j+)Ìì5vƒDl])»TÖ êé9• VÃïàô*ø¡„ã;pÆW M¡RJÀP9ÊTî•jèDH ÃPà!Œ8‰Ø³©M¬i…áÏó¤ÒîÉ~4ˆ„ktía¨ˆú´Êµ†6MÕ4‚ ²i¯¨µLº* ]«ã_[µ¶³‘?wÜŸ®o´pPªaCþe¾¨¿´ÖiË™®1Öh]ÔÁ* @ a*d§'µåC”­pº.‰Ï:φ¼\¨P±–¢\¤ º"0%¢!àu£f{söì‡.°]'BPà.¿›Çã+(Ýr1÷ü(jåÏÔ*uº¢ ¨GÝq æ‚Í•­´´ŽóT H7NDÿw£©½9N¶ðt“fîIÀ8A¾®qþH¶-h#‹ŽGL¾ž¼*†‰Aè¯j%U¥ÛicŒ©d‹¡àƒýÉýý/¦—çWÇ“ûÿ™ŠÉýÏñãÁWákÿŸÓ¿MíO¿s"ˆ¢S5øŒ–\ŒønÞèÊÙ:¥­Ò®’Ô„(͈$Ԣѧ˜æI ¡’0Á8Xø²Ø3<¼CÕ“Åû¨HÇ(ʈžG*ÂM„®È–|M­“ÕÆ±É^Â…‹_Y”üį_QüBYm˜{ž`·®‹"nùÂX1 E¤HCôÔyÍmcŠU’ãÉôœ¾ÕveÝıjO=èùÀ!!)îíf,–Î:ÜC7°ÄíÇ&ëy‘U’D8p h1‹¼}èíâ•ZG»Cç †]w#„æžwIè@3¼*-^ÏQAwÒ´A=µ @§&•±zïpÉcM+èî’:¬â=D½À ôɳ¥ÑK"ã8õÚsGðÆëd“<ë¹*Ãë”ú{á5ê3÷††0ê ` °ˆloâ b».cGƒTÞ ¹ˆ«ELµ¬kJê!×̇ãž¡Af³ç‘ßAµðÃ40¥Kw°ÓfA‡Ç¯WKmƒ8H xã¬|ß8¼XËyçWïü•í Ì£s‘ÖÆP!êg¬ÔŒ™DÃM`;ï7 b¢]Øk"¦0K4 =I‹\æ4®„`NÁõº–yô/KÁ ‚ØÝ¯úJ±ŒgP¿‰¬¹‹>±”´ƒŽ†®J¶ž»îExš³Möm~ì€~v p3`ÆB9ïän¡\5+eÍ< ” )S|/Òfû4hUã&´s$%y™·%S8"Þc,@ê`Æ‚þV4=%³±'š`k•žÓE©M×Aàp•QÉuPîÆåE›ñŽ×9’`Oç¸4Ð . ú<Šßš'¨NóÎ'PŸq)Wwim"QÌflHÞÆà–ꢑñP"bù²³Ð„ñª¦NêÁP)¨î½Ì 5ªb,‚ ¦ŠU–*rÝ€VE.B¸}/˜&%ù’÷Ãw¡&Pš×Ââô¼þ$d^„båHÆ`ðy橼êzá·ç+”ØÀ$eËd~¾Ì$ÓD”0Áû¢ “if–j¼Ø(Ù*R£ª]™“Qðy¢ö?ËF1 ÊÎf¸‹ øÈÖ¤bnѺ†YB‚5ÃãUD(‹-i©•{$Uú(]¸¡›©Ÿ©Av|b5(a©Ë!æq yðÊ6óqËU«ïŒ.q…04œêà¿çWÈ–…Sœ´_ãöÌ1‹’)ÂÐ}ŒCÒŽ‘ *MíöÂF¬*Úp´?Óp2<7Òí Ý„éyXLaLq$£rÕX·-s§`ùwhJ¼eÂ\å.×­Ú/ïrs QõH€5»øC  (CBi·Ã*>ȸµrãÆ“S`£K –•;f}.D Xœ[imš8!-ÜðHÖ§„)¸XW𦒽½•âm"¬1ŒæÖ‡Æï笌,½k4­ÛÓÊ€ü=YÃxLÂäÉ-I÷Ò÷?ÆK‰öÂ×Âó‡Û Q#»™—8.Í€¹Â¾­ë{è²µðRÚbCY€,csçò¢¿D=ækÊ|Ñ߸øut‘ŠcSèaSÀ ÷*%¬ „ƒÞ2Ž×ÇïÚi«U7€4@Ýh ívVŠ·sp—‘haÅ®¼D颥ޛ+Þm¸× Tw³Û{Älãg=‰ŸûCÄ-wøãñÒÎ3t»#ÈãÎE¹ G vstá«w¨Â6+”ã†UŠèÊfî>®6d»½EÍÈ‘sjÁè¯$ž$þž>Ô¶U °–ѽƒ AñfXûðC—AŠÆ>ØÀ¬Ï†ù ª6(6|ÇCϘ‡ÿ;]×ìø§TæN°)uÂc¯bY:Gà®Ùu'âü„%þ0‹¥n™xJÇíɇùþ ºÅÔ ÅF™e™„<ôF¢ÅÇÍî§ÛwéT|ŸÒ6>‘#;³ŽrÒ‘øUžTá’ t~Ž>1;Ǧ¼†t`7Þ¿.Áeƒ&\úÁUœÆt.¯ru(HSÇ“:Ö##…g¥T„Ke›¬K:x·!— ”m²¤|÷T{,¼7Où59P½:œfbiob„ƃ §™B%å6kœOKZ¤ŒŒ%_ÜI„Þç4«»A:ä -K3Ç’“.ÂC…æ½®³¾D­Ûq%"¤‹J£²bJ)ŸG3rbâ°´¯uI3›rQnž Ãq€ÖGu±`ˆJK ö~–îd©”ØÇ ü{üø1^ùÊ’¤ù1Þ+p>O[Å]1‹9_EÌeæÌí-Xažßõ^è h¸?ÏÒñnÀ`y:¦#å&É} (Ï;·æu" >û<9×½™PŠ*<)¦˜ðU"Ô "Ô1GT„g1¾8C&’-.k±­'.’& õÙˆññtÖk þ6Õ‰°H¼æPâ%Ê5L9®m‚½Ë´UŠŽ) R;(ÿÙõCay¼wJöy‡d¼M•ë®uü÷®TsUÂË1qB—¨G¬—eŒ~èYfb”ð&s±IÚ@âÇѤB ×ì0¡Ùè£hô"6 ©ùÙ‚;b6µdyzçË îàZ—ÝâfOiBïP…-‚:­®åà÷Bßn¹°~¿ç½üÌõ‚ÈkxhG7ðSŠC²àL¹S²÷%¦ +Šâ€×¥i !Ùyi2‹Ë…Q* ²Þ*ÆËrJûñ†prëõÉNPî9¼1»Sè7,ÌsÒa”´I€ˆÕ,ba…$dam÷AÖUÚ˜oAÛ›ÁhœþSªMoælâôáâ|§…ÒµT{ó…Nìé†Q›ì:s4ƒ¸È ‚*›Í@jeä€Ú¸îuÞ´³hZ9ÎhÃY¼­`†;Ô{%sd6:¶Zî5¯-›¥UÉF)ú­ãÈÞ[¯ÿl¾þ‹+ðäÏVàÉ_\§¶Oÿâ ¼ˆ~®Zp•î"+o úBá*d/X]P1Ú;'mcâÃRaööݦ-úáëgRû×qÓ9ÌçsþÚW–º¶vo>¤£EôiÆ¿ ݤé\æÀ ^£ZȦsi3áÌPŸ6ÇN×ÔOk ­×f,Ô=¢¹­ôy§«ù6Ëd“MëÎÙ³cE¾—ºMI›ï ©HLöZئ±¾q;{²ëðœp&ºKzSÈ““Ö`¦\Lt‰isÙ<-dKy6¯¶H¨“mˆåcÉìm%5eúÈ£Ú½óJJR¬…ßÇlûé3Y¶¦;ðnù‹”%Jð¤Õ „ñÔõ@çì(Ñ3š'Žÿø"fž.]:Æe#Œ›,4Oýíe‚mJ¾å,¸a.h/í<¾è9|û'K`í'º¤²Â[9†åMcf²Ëñзø _€>›âðGÆб1`MŸÌ.n€š>ƒ"+€ç#?L`Hý…)¤€èrf)a´—zöá¦CsÓý ‘þ†ÂpîâÊ4íÇäÖ~K~#g´— ¨ði*|H…Ÿ¤ÂǥȀ:º‡s¢a%vé:>J…{Ø¡r[ûÿËŸ¢ñ=ð²“:/ûãÂæÝ²XÁ,ißõSØ‚Ëè„Ë}jt@žR€ô&‹ÏX,벿ϰHÀDĺ[l»ÛÁÀÍ Ÿëÿ&=¡ÂgßàÇ“„±½¯ŠZšªöïzát*׎͵ÃÙj…“ÍV/Ä+ ómjð%ÞÙ·7 ƒí\ߘÚÝDêÏuÿ8}lÆÕù$É¿·Æ%&}=ù?ý®Çxendstream endobj 673 0 obj 3869 endobj 677 0 obj <> stream xœÕ[[o7~7ú#Œ¼xN¶g¢»4(ú&é6‹^²ÓvÑ…“8‰[ßêK¶‹Eÿû’ºR3šãñ%À6Aœs$‘¢ÈEÉ¿o³žo3üÿu´õà[.åöÛó-¶ýwø÷vë÷-î‡lÇÿ^m¶ë‡9hê6ðíÝ7[ß¶bÛ8Õs±½{´õcgWºS+ýóî?ıŠÄš^8 Ú} #­Ö²·vx÷ÅŠ÷ÃàÔÐ=\‰îÙjÍ{¥´Ýnó$´Jåºo¡UÛNÃdýjm­ë×Ýg+ÕK)Œólž¯Ö,wÝS¤uðGúY%ð4† ðù ?YcãÐ3K'¼Ô )¯o`€½C"“’w_¯²ÜÈðIY ÈÍ`æNÀŒœã”Uê(‹\!°é•€@Šž3.üT½Ä~±=cZð8‹'ÍO&¢ ˃M$—Ô&k®4Þjù0Ûü8w÷ðÌ!Ð6Îtq:Æ8ï¾Âž§øãküqœG ó2az&Âw$>‘Øq€Áj°ýàt÷gøqž%miÃe_níÞ_&¡Ÿé‡ÛHX8,°ë ˆõ(àÝ¿ðdzÍb=JùÑØ“<‰¼=h˜£–ˆ3e±ñAn¼¬g€“"ÊI‘ï$7ž•Æ×¹‘¬ä87îåO¥{•ä°¹;¤#SÿËܸ_ËÈs“ ð٢ȱñÁÍuìÕ»w'â;0ý‹ ö§ LŸGâ§YÔ¿€é/sÿqé?h¡Áùš½•Á‹f—|³fïÐà¸Kußá/<&!èËÛüûÜø¨È÷<ª|Ýo-oüOnü÷b”¿½ ‹®–˜p³®–š6%7ÝPš>Γì.°æãFq¡ÛhÍ%»Ý¼pO–ªo³pwí>¢^± «>«ó‡ëèìZ-ÆÙ¬D·VÔ¯™àYžò ±ÊÀOÁ¯¿Rº+ªHT€²QD¢âå^Ïùh޾kHtt'=¿¡DÏ?˜D#x/¶ZˆŸä¶»Ž~é‹3²<úC‹å™âÁjQHÏ£I–ù0‹µ,¤·÷›ï[ÂÎ.ó:û¾RܘøIÖ(IÃïå–ÆSãÆí§)«ç¿$kÉúuVäWYà«d-*þ¤Rñƒo¹æõéÖö‚Ç[áµÇ[±’_ÉH2ªkäÅîÊ©^0å0ëÁÊ‚a DÓ¸JÆüÁßZÈÈÄŸµ†„L'¡Ô 0# k€`F0 w ëQ+eS„š&uŸ–—å#¦ñjè±PRÊ7An`oL³…“Ь(Oa{­˜$bœÙ0½J¶±z„TI=Ò&©ÕV²Kê1íÙöVˆ ÉXoE‚.Ô‰žkïÕ|“lÆwœ–zÓi®¹¤á–/U»'hhЊ`3ê2ÁĹRNŠ´8a\RÑG_–Ž2šHÒêG=¬ÅÀ{å¶×9 >¾X‰hgFyßzpG€‚`.•¤8ËjEPf€ú%œN´’u›Ц|äšÚ‹x^&xïq0pCÜä ™è^ N D ›LÞ‚ù¾Ÿ¼×v‰Á4k°˜Ç«ŒAìÈÎØXÖ°a]¾ÿt²Þ€®4Á{ò,ùhm­@„g9Œ{BQ•¾„¦¬æÌ»€p®wrH>gÅ Žƒ}ŒQùð$(”/#¸_ä´SÄ"ÆL±·]®”¶;ŒúAÞ|.ÊùöMÞÑlÞ $÷òmgy¿:NC|=ª®qHo¬@ö[þŠÚÅCò´¨r–_WµŽØøSWmµi‡B'ÓiA•ìS¥û0Ê“àDoòðÓzÁ¸-kP³jðÔìÖðŸ qù´µÆ’É’"ÏEnܯ´¡™óEž Ê)MØäT漬Ø{N°§|‘û—þÅö›j7×-ÖA|y‹¬Äo(òžÿŸÌè²€#5–ÊÝE)ÅÞTÕ£|·á¢‚èú¬vÑ‹†¯a†j´†5-Ulñ€ƒ–wžßZg-¼º2$u·¬q”_V%ÕRuKäM WzKä1‰VÒѪ]R¾S´ÀwP Hdïâ´0Ãý2`bezR@= ]•ßEI!?¸Ÿ½e¯v£fÏêpü#þø9} ƒEnCL‰¿‚üޱá/Èñné§såÜô±®ç’E•‚®O~!“SŠ&¿Ž® #DªÃ öFx"ÎË ~Zë(J~6ãÈñ¬ߨkÄŒ[úg1â›2KNG-Ë6¯Í*ò»’O[4çtäTb6m•óÊöÉÐû¤ñ@˜·Çý蛊Ãp¹î_n^É~‰G;-_Û)Aú.5ŽÛÿûÖ¨ÃTö‹o7±0oNrÖt¾ó2ö"ç&mZ`BŸÒ¼¡‚Ƹ»ŸSšëï»Õ“he’&"I$kF×êî85îµ,ZüD¤ƒ ^_ÑKã»ÚÀe;¥µC·Á2\˜QÆ_©VÁQß׃]¼J­¶t)·Ü|šHÉš÷Èo«4³dE-Ø~ÉéÃUÄ™n“š™Ýñæåž´Œužnȹ7£˜†Y›ÑäÃÇA"IÕ\õcsÝ×E7Ùk%rÓÆ ÁUË1á†qšZ¤FVå!ÏŠ«8¥?­„Œ5Ñ®ÞPø!É>Ïñ{T˸̽8íUÞ¿)Ä7ª h£¤Üy˜?¬L/[¶ŸKW®¨ý«„G¬ý‹+kÿÏV’÷ZÅj>©ÊÅš™³Ê¯Þ1Rá›Vö}¿›ÊêX­ËêÒ²žÓâ\áÞ*‡–oÃŒh¥RÐ;ñ7ÓÊ;.¬ÅdŽñ€ž«½¥+EFZÇ-ÃðP2ÇÙqçwÖ¿h¬Š³Òç¯"ÑÂCK‡ÕÀ†§:·tC/…›§t®ÇéI?¹£ Â×EO_ßl25¦7ƒì…äcB¬kZ8‚HCëš¹RY*š¤ÌIGr]—> aN€ï˨WŒX\/Æ A»„õ+ÐÊtÅ”¿Ð3õW¢#P"'Éo"Žûùx¹¥²è ²ð-°@¬{«W Âá@ÊW¸q &žŒEÂ[b€ÝɈ™J þÉ)hHÞ«£+¬" ‚t%ã6Lh0 ìTL"×‰Ý Š$† •ïá´˜¹MÛ®®®åFV ázŒ9¼´4:ùÞäL.71UÇ_ˆ5•$Ðjýínó³ä—“È7Ìé%%¹¹Ä@j™Ÿu'IÒ´NˆžuÔw[ä(×HØIëáõ½´“XÑÍ^àâj¡ƒEP´‚¤ h" „Å{üB6*Oø%7óÑöÎMm’X©O”*Ó[ªß¸÷YMƒdZ¦1U–k3Þ¡çÞ¤µ—~\úË2¦ÄÜ,å'5ðãZëè»W¥«é [Îoâ ¥émIî0×C|P%„¾bYë¼ ‘8›¿—C{Ìäm„æ¤mßó»ªûœÑs3ÉÛ:^Å̺æ*ÒÑ_¡çÑ|“Ar.tßÕ@lA{ôv6×°‡ñ⺢¢aô4 Àô<#,§»Ë5’ˆôbAŽA °–]ó‰Â+š™Çü;s,ɧ—mÂÏoÃïÅ­ƒêx?ÿ¢«Šï©ß×d™ß${±¶~³§RïºêZ~aT4$F!nÍû)é!#/÷Xß7žt©*/<­Pª…ö[E`5¢ãøHbGâúM®NlÇ^#óysÛÊ1,éÕ?‚)>é™{˜³¼@ð^(^R”?±`¤]ºÐ½&ÊÉ1Nã¯%ò4)ä¾4RÏGucÈ5v º€ˆï¸Â:°Ï¢ÑOYŠ”Fâò¥å9d³Ã¯ÆÂÞJC7||È”1€“ î Ä|£UµO¥èx@€™±l2ä™x¼•å#Žáù« ,¨úŒy\CTûð0~]‚ƒrçKŽ ¸18GFè6*Ï”ôbIXR(5z5c P·“zšKÝ9p•ìÕ`ßf h>¾Áù8eãtÆ0›$'÷&F…,ipfjT„Ùô­0þb/Š<1ª žYñ/7Z5ç@¾p9:æI݇ûÂÍëâàË+Ë (5¨}3€¤?øú¹Ô>P¯Wþ¥1w”½÷Q:4ܓݭÂßÿ°iendstream endobj 678 0 obj 3462 endobj 682 0 obj <> stream xœí\YoÇÎóÆ?bw rÔ÷ ,Ÿ l9–m”V&óÒAIɯOUŸÕ3=»+JŠ'0Dçè®ê®ã«£ýtɾdø_úýøbqç—ryò|Á–_À¿“ÅÓ¯,Ó¯ÇË»GøšÃ[ƒgž/~^ÄøÒŠ¥qjàbyt±øa¥×z5¬Å`­•+þ8´Î‚¹Õ_×bu´>”ƒu‚«Õ½õ!œó^¯¾ÂKïòé®çÌæw9“«¿Á¥°ðŠ\=XK1p&Ôê|.„0†¯“¡ïÓÏðO¥´«ïÖ‡.•×?ý90ï(WðÎÀ0v´f,Ð Å7%—ôÍC%k³<”l°ÜûøÅаºÄ/`"îÅ?ãßgé¦\=G:ã|õÿ¼ÆÇøãY~ºz‚?æ{ñåã2ôIzEYÆ¿Syªø:\ \Rgȯz7OêÍWåîãruZŸ—›ð¹rfðpóCz3¿yÕ›ó¼Ü<«7ër¼(WÀó)ùªÜü¦~s¿Üü¢ÞÜý¦ò®Ýê¢á(_¾^ãFKa-²´åËW õx©¤KDSÖ.ëeçgg/=ë¾@;©ï>™‚—È+ª‹_}Tî"w ­~ µ\Ú0±Ej?,7oðÇÝeÙ‘Æ$ºi™9Ý*wy“»"T…­e=Ý$œ_P¹š~“Ib|’ƒkûîHªß¼î’Ô%¹Ý‡Î¿¨"p<¹‹—7QšÁVª,ÌDV\ÄBy‡å!ØXþ볩8OnÞ ûò¶Ö­:]¡ÅËÏ÷1yà¸þO7yÑŽñ¼ï{X¾žíù­<98 žöî½¼÷á«þm¦ñ]bñö„Ï ÍhËÏ:ž»/Š·6¦=ùQ“š7Q3 BäCr´b-Wr-»Ð“ØùI²§®ÂÚ(¸âB€’vø)W¿À0 äÜÁé7Ç`_à;ºï¿ƒ@’‰A[µú°r?ÞôæGCÈù áòƒúü<£~´ÛL BÚÕ£58 Ó¯þ±>dH§õ&‘a¥Lc ©pYs ¢h‘óã³<äÏøÔ#„T]v‡ÅíœòH;’9Hðl¢òŸ4¤rHrç*÷!“AXc”/SØa½çÓÝJœñ`zÂRKC‘Åý¯†ºOq\.T©4¾åŽ>ß¶ÈøU$4¼¬ñ̘´Ø¨ÆØ@-HœwV㊻A€µ >X)'¸Š¼j^+ruµ5yUB¾dù`AP¢aÄöi\)ÎQÆeØN$01*Œµ0¼€ðR€ä\µ›¾AV`P3ÞÇ Î@ƒ8îºtƒÒÂÑcVçj"GÒ±°Uˆ[] ¬Ôtd”…®5¡ˆ\öŸÄiÑÅ Aƒ|›êgܽLÔqäÑGãµmžúÍ~5ìYæ›1Ps¾“ÙÊag™.c4ÐAfväà”2óž‡ÿ2H„BŒ‡X?‰.û¬HZY=7ZR‚´›Â¸²› !u ôéÞ†›—õó«˜8L, ì*™ÑDwÐÊâ&H=³ †™ñ&à79y2“t$ÀsA}ÊwäAõ q´(Ì%È^Zq¼´âÅ‚tXƒšmÍ“¿™ yZLHá%eÝ%­Y˜œ.¦Ë“ïÁ"eyª<½!NC}S}€[ÔÑÝN¡¦ÀJH¦d÷Ð!NeÈô—£4)4îyøÖû×i7ÑÅÐ&J³Çx¸:áŒá:€7v ÔaÞE§…¨’‡”ĵ4ÈL±mfõr­Õ`p#Y­Îw•qþfŒKóüÇYñùÞÈ·d>;‰€Š¶ò:Íš` ñ%PVµÍ0¢Ø-´C˜†Ü3‰æŒ­£±óÈ+iÂu½{WÃ6‹‘¤V½òÚJÍyd”|Æ%62øT2˜Ç]´m×Ò÷t6ÿ:;sŒW¬£wbšñ"MÎ*¢%E®»FÁI ›¶à ©1#vŽÙõÔ/×èñØ,2c›· .¬¾Mtá)Q‘›Œ5zHͨõ¬pŠ6à(Î3 ÓDP!Á³§¶E{€T£®hHˆÂe0>¨Nc— šŽb^òŸsËŽ1f% ìWp+s0z€«´P@]¡y™´.6¡iÕ„åÄàVK~¹ž†^(®FJ,œ»17“qÂê:Ðkš²ŽÒ¨’ÆBôš)ERšÅ&¾Ax\¢1>zUA~'PÃ5Ù¬P ËhGñ¸È'RG¸¼®¢:=|è °M¸LÛwй¡jêû³"¡]'"Ðs!WQãèÃ# #‡ÖI6•"d¸*@D¸Ÿ»ðl½0˜fä}êT7”WÜoáe­Š! {5”I\ÙFp+œ™Êz¢_r;‚*y#ŒË®SXÔ37 § ΩeáÁ°dÒÚÔD›¾˜‘pdy\ö­F–,X•])âG­±Œq.ìC)œ´»OÌJy‹-ÂÄÊP,t½&Vºnì91!Ÿ©d^^%pSd¢ÿzÛiß,…ÆPJ¬ŽÓáÈ”Wôœ)-v§ÔŽi¤ OÄè1ÝÜ̼9½ùC½ù-WæFó]µÊzJæº>¯µÙ±ßšz^Ÿ7ëBgb.¬N—’‡½›7ÍâÕËÉÑ—‡õéËncùùdÐÑaƒƒ¦×˜Ô8ݘª¾›¼ùá A$úQo›ŸÔívË׿ýçÝÕý•ÊˇN§jòîSdo®?áê´ÕŸgóúC8«]ŽDjiþ¿QêzöôçÙoBŠýèÏ´=ƒÃÎa«mC5;[3¾_ûàâK†=Ôצý©Ÿcg£5Ç‘9+ý]Åkä<[-±°¾W:쬂²IŒ»‰›­yªA… ¸_Ë’Ú’*d‘'˜Q{:bg‘VAª>;Z|»xººM8Å-… ¸…»ð*žy¿{oqçÞ×ËÏnž,î|¿ä‹;_â»ù~Ýûtù»Åg÷–ßΟ„mG: ÁàÌ@: OSzä„Cº”ÛÞ/ýP$C@?û¸¼p?qW ëXÝô^7£1Îá4µ•ˆY=«¶èí7•™Nü¡\83B³¼ñ&ã³IBçÀ÷Q¿cè|£°Ž$Ú¤Ó= ˜z`'t³Zí©Õô`›¸ñƒûö»¹5Ý`¤“«2: ûgc£Ù#WH6VSä4hBXý’;=a¸j;»µËÜ>X÷™,àŸ°ŠÁ@ðæ3b²ÌNš°Ï'Æ jÁèÌ kÆêŸcÙ*ÝM†r>‘æXƒ'äÛ0ã~2)iÄáµp@ã-Œ¢Uhëmc¶›$Wb@òÙxœtª%¤‰Œ®r£ çµAnT"ãó¦U”pœ¥/Yé†`²mÍ=-Õ\¦ sÊkåŒäãéré0U™›O éùSŒ±ƒÌOœƒÑnÖ9pø~k0èæ=:î;˜fy®Á˜Áû^\ƒ‰ð*0p`òTsj*®£9WÚug*ã06t©Ñ2ßDáub¨]W#<Ðtߨ˜#ÛP)í£Z5ªÞŸíª²iBæ¦upMÆ/ŸvÑÒöT®¬•,} ¡ °Ó˜pÜN¼µôM.[1rLïê ’¹óM[Û«œÓ\¸é4Ó–úîvvtä'½¼XìÂü˜d©»©²¶~Úž•{rSlÔÆÑŠjQj¯†Ë9´> stream xœ]‘;o!„{~%·aw…2ŽœW‘‡Cª(•£¸ºÂÊÿ—²œI|É¡h5ßÌ Ž6ÚÐר÷³¹Ø!³=|™`oô?˜£ÁEbǶŸí¦-²¢#¨¡¢mŸæd€VÈæɶټ9ñÉeŸÞÛ}GJøƒH*JµU^ù‰A¤Vt·¡Ö«»ôäžü„crí¬Ùž¦‹Ûé”ÕÖ% ?‰ Lnã#0S.‹Í‹Ÿ’‚ÅÝu¶èÇK*«gÎë×¾Ÿ$ËV ²^±¦µ×£ ˆ€¸þ`Ìèüoïn¸=ßF{%,¤‰ˆ]Ò»r] aì€Ú@LU&À€´DiíWOB") ô/:ª“`“m3Ϻ¾Áïhœendstream endobj 688 0 obj 282 endobj 692 0 obj <> stream xœµ\Y“Åöóš°ÿ¼©ÇÁ¶ê>ü( ¶&lÐ:ü@8‚½XÉ:Vèß;³Î¬®êžYí ´š©®#ëËÌ/Þw;6óÃÓŸ—¯OË¥ÜÝütÂv…ÿnNÞð0d—þ¸|½{r†©`³1ÂìÎ~8‰ð;måîìõÉwÓûS6k£¬3Óóý©˜…€É§ó=›½a†ùémúÔ‹éç=Ÿ½ðÊO×{øLjͧ÷§ÒšÙMgrÒZaþ{ö÷¼ºš­³W×zVÒ»ÝÙ?NÎþôÝt¶?å³³–YX—ÍÊqæ…ÙÄl”Š;sÂ8c§¯`„Ô‚‹éiØ 3Ö•¤˜žÅŒâe€ðÓ?q26 åè§xëpÖkx ëµÄSÀ Â)­àìð3wŠƒHêà[”7ÞÇ»™) ûòb–Jðé}Ø3ÚLoêf.áq©¥d¢¸C]ž“1¦ ÏÁmΞù( ªã9(ßYýþY]4€$j‘R´] )ÈÈ…Üî¥áy?ý‚š#„´ÞÔ­\Q€âQ„TEe䬕 ²€í{ж÷u(@™é™þ} {©gÄúk¦1Ö(²VU¢+·0ÒáÞ’˜P?àßð)›žf|ú¬Y>¼Ì?¤]›ÕLƒÁ|±G,J8(Û]Òq,wÓMº{®(Èíá_“\-7ÓE<ŠÀkE–!#Ƀ`/§uϸ“S FŠ©Ý)k´À¸£÷ÕBd»›ë4Î05š03 Zzo‡?¾Ê×Vî¯Nr— žáÓ÷ùÛ_÷ƒ‰V"ÜÁ×Ëxa¬ÁÇLÍý0ŠÃxý#QgaŒœ¹°á8ŸõÖ€ ÎÕâ9p´¦¬Ìâ®Ó#§ˆ¢èäO()lz†(Xh¸·±q±Áwã­ /áÒy`cÒ¡—ö ¨{r-àù, Uv¸ÖEEó«‚Ì¢‹³â ¸o~{ô·u–Šï¨oÜØÊ„u, ­É#uÆÎÀI8e{ ¤QA/²ˆ‚bïÚH*oõf¯ €‰"̰¼0°g=}(‹g–™…Á¾4‚IÅ@] Œ&ë (Mµç7¢› W5`á\ñ"Ëp0Âjœ¢±b÷q50ÇDÕnâ6½/6- tˆp;ÕdÅÎÀVêê5~ ÓGÀ:至譗êAãåÀ©46ÆÙ ©d½€&‰ýÒ0Àç.¶U‰hV)‹)<£qn8X!!Ê¢BpÝÒåˆÜÆß4øbP—° ÅpQ+²haÞh2+“£"BÇÃÒJ ø¶ñ—¤ºˆ:AE–Ë ®¡YC#dõW ZŒ—î:?”!J¨U†ÌîUo .^¢¹´>=£Ïc–w Ž¡Ï–à¼6ÂV‘¦ÞÝ õ1²t.ÄÈ>sD¤…"!Ò>KÓo㘸Bà–Zš½¢rùù©‚®F‰¼;N„úŒúÊd@ãy« äÇdSÀB !‰E€{HnÂMtT>󵫪+D5¸êz¾”Ž[goüܰÁ·ÂVØ»¢Ð_p1¼ïg£åº ;;&‡T §Ï†>†9¼D!ïÅåb<®fo°©¼ìk”&îý‚þÁù0q´b…Ëù7ÉC«h†Lå±YNÂп¹J¢n|ÖÀwägjpäµô"ŧCiå:2cmMT±›v §Ž{£0YôYÈ1çG XÅu`ßk¸Î¹^t‰¼á38æÕM_2¤Û˜~ñnƒ6…0JÝ%“3Æ{™é|¯© ®91Œ–„]ÝצO9½hãͪ¯‹ITŠÊJs”ÓK¹­aw”F%ŠŒ”AEëùdŸ“©}Ò÷¼b¤ÆÔ‰Ed¢Ò¥b‘ñ6œˆ®´ÆýIqùB3’PZͨÉ*"iTBsªøCõwƒQ—tĆCD ÓÐ9 R_@“ìu….–Ìç"5ÚáóCEËy]“ÌA€s±¼™EZ®£H>'T¹ekm¤ò*%åâó•F ’4Gd³lΓB`µ–W7ÒP%;ýfcß­ùL\H”òª¥¢»ƒë¢0Ñ„ËáK!ðÌꀒbDá´t«ÍV½ÉQs±Ø‘}µ–e˜;BD¹³@)ê²Ó*y’¦¤ûÞŽ< ‰A%¦ÍÕ2¢ÅÛhµLâ,\WT]8yˆ' âs”¾ÉÅRÒ å) Ü$C!¶¶mš,fÜÔf•£DiaòA‡BÜññSŒ4< ¿gUK·î|ÈMpc·Qv‚]*ö(I>kMÃæ¾"ò×åØ;Ñ:äÌÈj`ð¢6)]ª˜¤˜#H¤õ}dM‚øcYS•e˜î°™²#øvYŸ.„d†è“£›&e¨Æn¥Œ’› IFU ƒÂo°Vë®­}´Z¿C2§á}q¸ÔÜÕñÕÞc“ˆª'Ò,½(D™#¼|ð9çûQ¹êVM¨¥©£< Î]æãk¤yÁ!U,Æ!æÂ6i˜ûµ*H‹yW ¸c&x¨ujzl&×™Œ"}9ÿ|٘Žºâ¿Ç¶' ¤Ë’7½â/{0íÖHÒÁÐØ#ŒÈª¹ËN¸>ÍtQîÊõv,Ô<˜Y·c)À¸m è(\$Q’[§ÞeìT˜æÛ»\7ò>Ä|ã’af¤]É'±YŠŒÇ#––*±pwHÈüAÊÈ`†KŸ­]¸oA5ϺEÙf®™b¥Ú> :yL²]^U’¥òjd»¾ÊºS>äØëÝ$¾³ c¸·ïEo¥ùÁ&þþT|8$}Ͳ P·—ÈmEë×Iê¯b*Ú§h­©I"†p°2˜£«ÉÄG»eÜÞ:[ fλn_öZA*í ½{â@jbˆŠRf7žÊZÞÚq©M‹ˆÛ¦æyaûG ë4’ªIæ7ò£ÚÎ2™ÊNžÊ8G‚®d(ÁÜ£¹ã[”÷תª¤ylåÕuXc`‚û¾›\TÚèkH!GIQVè?çocϬ´Œöe†ææv :³çÞGéþ1Ölû.N¥K ®Áý·À@*yZäŠIx9Ê^H ÎQ2ø¡k‹râJ«kP«CµJ­ul†Ù ñŒ§ôêñž´S¸íD¼­ÞLħå?¾"N¡Åx‰\'µ ŒŽ<²5/¦áMÕ´•N=ibv&Ç=Æ…òØ*³iE=nÙߣ%v‰yªÏ+åj[ Ðü>‚Û¤C·Û÷%Äö.ƒÔöÉâ#²å´‹A¥(H`EøR|±2ôýõ=a¹Óà{j`Á‘›ÀÅô¿ ¾%óMI¼Òà~é IÌÔ5Aj{Ýä ²S´«Á_ôT MòÎJÝÄðeßvb™ÙYašNA1ŠÆ½µËì„.¬·÷0wØÉù8ŽËÁ¨5Û½‡ŸQe&† é|UëÞp /BXÿÑ1-”»-'.c3ÛÝ/‹ Š Z8.Dàõ’úÝEk–7K²½>æz‡i׉cpÒðXÊrTR¨à>2Þ¯µ_‡:nÈÞ¹¬.üZY]x’ÆkF8 `˧p’çŽFjGm<›%waMèçô»ðuÝ“…c0aºæá¶õǘ¥ñn»²ØQÎÊ[ ÂZœx=©g´MI ;Ãò ¡FDX¶>·eaî‡Hî¥gL†Ü‘UD¿Ïæú:F+Q¼ÉpH?8h0ˆº¢˜V‡y“ê΋šŒ˜u“œ‰¶dœœIn?bkÄêó7dzú¦k+ɧU‹C5Œš·¾ƒ·R÷aæÊWESÈeSã×U†‰˜\·Ð~|êL8q9±2†$¥7i7ŒÁn€…Ñ!Ÿ ÷ ZæÌBŽ¯ë˜®$ŒǦšHÇÈT§Õ¥ÙQ)JÎÖjÄ1.’ÊòYÖZç*‡ £8µŠ™ËþCEôŒTóGåŸ2¯yJ"ŒaÝ•L¿p„mäîI!7ilOÛ›O:dš^G¢ÊùÀ½ïW³Ïе–[´ŽdÎբ˰AÑ’z»UL3æ?Pj Úó²…ïZú}L>Þ«v 9¾ªü@œ.v&Dï‹ÅjÑi¦á!äV ŽË7ÛKGä4_¶,òŸIb›dDP9#-9©iô‰´½¬?¾uU5³ØËs½«ûå¤(y3-7šÊ;Œ Z9ᯇ‰ñ5ç³ÅǵˆtƒI»MÛèj2êÈÅÆ+äü|~Ó1´øl%i Ú¾F’[†»^Õ»tÔ­WHÚ<ú£X€Å ØËjP^ôÛ½ÅüûÓç¿!™)¯ê%åKMJ݉ý´ý¶²õqo1­wÁö5¬lŒ2i/cÕ±Q®RÌiú3Cï¾Ùp4¾eMG–ÚoÝ:×’¤×HÉw•z)þÆÎLeŒ—ÂùX†¯Å§ÒMÓ(Ó¼Øó¶‚ŒtÂõñåÅð !ä‚lþòkõ\}Lþƒö“ׇ>'ªÐô6(B‡×tûD°ßV7¤h¨Œ­ixîÖ©ôž»éšÀ.I3䂃†ðE¿ES¯%|R0¬¼#©’~Æ@ Êå°õ„ì (!ÏŒ^é`î¤òÒӌơ‡Ú66^ü)’­Ö Ò«RÃy©ŽÙ17;Õ½ܼӪeéRÍMtfe¹SÞ#°c+…¯2ÕêÛ&˺zÝÓLKdáåfý¢$¶öÛdÅã,ÖÞ¢’´ÀŇ4}S+œŠ¶I‹Ð«"bôº`û#÷H’Ä¥± rïç˜j,¡Ü”9×ùK¾žé_âþýK¡(®äfk½ð<ä]Zë+§8°†: 9 »3H€D´’ ;wˆÅ§]ÅÛœÃX‰àiõ«T¸®¨Föõã:Ñ;¶‰®—úš|Yßñ/9†ä`ôA^rŽ…Àp@‡ãuYŽþ:†e¦€h(ÒVDÑóº^ ¨¸5+ TÞórmî,‡P ÆL¼ÆoÃô‹¶âaç c.GÊ@éO`—~Qê IRµò†zÚGëXASRÆ‚7í¡5á5ŠWeË¡3#*=> stream xœ½\Y$Å~_#ù/Ì›»STÞ™¶ü`¯ð%ËÆìX~ËvöË̲0Àzÿ¼#òŒÈÊê®nƒ=uäñÅ‘‘õÍÅ<‰‹ÿÍÿúõ£?J]¼øöÑ|ñGøïÅ£o‰øÈEþßÓ¯/~ópi sWϥą“ÖëIÈ‹«¯}¾s{³ó{óï«¿à+~f¯x3ixéê|¼¿T“s!ˆÝŸöb Áë°ûÝ^î>Ý_ŠIkãäîª=óIºª´ß}W´º³Ð××¥ “ôéÖâ'ø0¼©íñ{üå¬ÛýÛõAÌŽ¾ÿd CÕ:˜üü£v‡„À®ò[Ðry ÛJc4³Ä!Îpv³…9ù0ïL~ÔK¡cSÐd:mPÿ1ü þ{Ü^ ÝÎS3RZ‹ÏOól¤È¢ç«u™d 9BZ‚Wð 4©vßB3ržŒ »kœ£†–^pÍ;½û†æ½un÷v©'¥ì¬w÷MHO÷~ÁB”'AFä6yéYjßÀˆÛKw°·{é&£gEš¸†ëu·­½þš1¿@1Úif÷~zXicËäiÞ…S ƃƒJ—Aê £<æ€s'OÞ¡ ¹ð² ¨Ì ^À1“¦ÈÏë½r •"ìÞ¡zH©\°±/PPcuìsìõUìnZûØhëÿú >ç@…ìÚˆP$Xæ¬E±¹öh)³Q±+2´¯’J…ýË(Ñ@ð¶_jXë7I8W„¡@þ*?<§•Äë šQž®Ð³òHŽƒåA(oè@ñÎ×p'„ÉúÜbYÐwØ'Î-±90­ÚvVeg%+i¶>˜_–.šÑe‘ß%ÌÇØY&1â˜3@=&zÎW¬ª`–OQZ\|‹z#ªä\@ð#FÀµôDluÏøl¼#ÝKɺZ•uO¢1c÷ÎLÆ©²@¥§lÔÅ5$j& =bƒ%vSæ`YwqþÐH×@o´Û/ìÍz”Igo6D$ZÕ[ò5Àª¤_r ºÜFõ’×[bΞ˜ 4i€ÝºÕÛM«n›ú½©ÊTúǫؿö“šªjÓ3'€ #sYJY|k†êŒ­VáêbW^UÉI°$”ÚÕd­³:ê}DÔ{|’GóY¨·ÏîhþƒvõuQøg5«†¿Å§¡cé¹ôQ;½‘QäZOèæV, 7'—ËZÓì«[viaÙý!`<ºªªyÍæ¸•%í«Þù˜V ‚ÒA±‚ExéÜb±KhñÓ¡CªO'?‹*ö²½s„l×Ö™Ëo÷3Ë¢¤#:'×9LfL[˜È€™çÁt¶?Æ_NÔs¤Il®’̦cØyPël#Oàž9ÒýÂÞQ7~ÕÜ{ôB!Æ,›BS¤CÇbSdÙÕ|Fh~Ç]ÃTn$ÄΣ¹L¤G´N‰„‰Þš¨í÷²U3¹>®¤-$,F9~Ê$ö…,QÍFI–¥¨Â¸à[z:Z¬ÚnŽ£Ô,ëÔYVda0À—dÂÖä®á S¥4zËd†ÒAs%^­S–º:z9mî+Xj)ó"GÁœ††Ë^c ·2'ú`¼BkÎÉ’T¬Œx™Àkzµâlr>~œ2Im‚Ø@‰$©&”pEà=©JÃC$÷»h‘8±Ò7i·=™–k_¹Ðˆë4ý®Â¹g¸×8Sy°€!Œvdg ~ j‹+·†’ß´¦fC0ž4ƒ#`RVʘ‰ JøŠ/xg+¦7ä~kt‡{À^]{ÀW ð­Á¡¡/)ÊX*&¦™L¬IO- ÇÜǼ٠­y™´fZ/ñ(s¡â¦~QØö4{rß|q)g»L×ë £ÐVÆt}–Ï¥F¥šE“Å¿Ó3†ñjš…a'@B‚Ï[Þ">¿Ä¡*-uˆRp þ'g¤ð(@W¸Š-YÚ·`µ+]ÃEá|ùÁ¸±oT%¢wÿÚ1)«¿í(ˆ¢ïŽX’÷“ð!2š°1+?ŸFóqʚܥ¨²8ËYkÒ|{g¸Ï¡æI»àަ5"I¶–òÍE†£‹‹.a4JR¼o@üùYͨZC/ ª½5DSЕ%Ù*Ð…CJƒ 7yÀJ[@Lƃ¸ñí*FÀü| SY>£$û’Cs.EÁ.Dº²Æ8µMiN2Žu%V©§`E‹¸8Žò//°o̵ê1…ÅYؘ/Îû3Úá«'¦|»x½¤|‰cÆë LzÄ·0 t‡Ý}±«O®Ä†éõLx“ ¸[~ÐHì) nS =0ÉÍ“íÀ”‘QÕ a˜‰Š·ÜûI Ó!ç[ìý8ÅÝ…:æ›n©º–ÿb_5õ×$«úñgJ(¶ë-âÆ+Ò4Dp2ÆÁ r‰¿O$h#‡uºA¢Rv4»O©õ¤u_Ïðå€2Õí'OÉ ß,ÌŽK«èG2÷‘àlñ(ïsKÚ'Œ­¾ACç6!¸K£IšoeßFGîÀHHŠ€p™DƒÊcrï:?K«žA,²~/uÄÉaJmÊ Í’kÔ4pY:W‡%—"dÝDX¦bân%ð©ßæ$;ÐÒyŸ¬ Ëaåê–%-ÁÂ(_…¾6æX µÄw“³(©çã”Ø $õÚhIRE“<â@JGD•›~ÿØ”¾j#«&ˆuß6”í¤símZËÙ›YÅâdŸRR-,ÝžÙÊbXz¸²‘~Œ•ÍåI~6ζ¤-háCÀh/ˆÈÞ§¥8íZâRê!²éË0Ó0.Ú­ZÝ Î½mca#õ6ÃB;ÀÂ1aaXq²Áˆ²iŸÄÂ0‡Š,,'^qÜòn'˜%g­›Ãëƒ3VCûdÔK³A Ц!Л¹’ .Á) žÕ÷”£Ö =Ù0éý"—fú3` G‹5'­þz´ƒ;Œ-iIÉzyÜÀÆÜTïš”/kÕe·™ÑEýÑ‘5?ïÿ+5œù~o°¦[z.«ûÞ?çÊ”BßG·Žý±ö>œ‹g=ãu¶+>„A™^n¡Çy2Žr¯Çð`8õóRñPÇÚ^ZáÎ^@lne*erÃPáUæèžlßs((Ng.û2Œáça:ã°å<¨ÛaeŸjjŠl×5ÚÃÈ$Ý×d}Ũ`€1Ÿà›¶pq&`0Ðì¸ò0«q:–˜§ã€ËÒö4L»…»GY Î"^93ˆg³¢ã”7Òð ÅDÔdßÔ»vPÉ„MúT[,{Êx‚ÉÐâ‰vh¹ÊˆçÕŸ¯YDIÛ(OZ¡<: AP‘ÖÍ‘duÇR—åºl‹zäyê7ÑËe•VäÃaŒÅ0’š(Yh›ÒÍ¢FS…{Ù´ž‚j,1‹'ìÊ™Ÿ+ªW&0pT5*¦-B“RÄ‘úõÚùAÁW¦iöÒOá,?+‰Z#°üd±_ìD Íûž{®Ñç©| ¯)gåY¡ã˜]ßÒÁ*yíHbk…ê`uX%¬{…êŒSi¹.ÿÄêûZª*Y`œ nò„ç2Ÿ~0BÈùôT)/ºT1¥î”¢§³ˆá¯L•éh1ci´28Ï{y¸úv¨žO7çZ ®:ŸDnCbL«T_´1ãÖhÝ9è´+Ò0ön^HßçÄk'¡Ì‡{3¶²”k®:ÿ~_¿±u5bÌÚL:Û`˜ÎÚöm ÃãÞʼnœŽò¡©Ž ZùÐlWTX’¯:6—„ƒÕ¹m_Ê”~–¬§£a;À›ÑÑO¢¤±•c5¡bÉËÜ[=‡}e“# Žî‚A‘ÎÈcõžkåQxí0{TŽ%ŃñÃïw¤·–í®{õ(ˆ5þºHɬ»ÅÓp§(º’1˜ÝbUÙ}DïÇ~Ý# á”À‰¼ÖˆսRò08ÔYÍáCAŒß.t&m¹zBÅúïqŽœ€\ÖW ï8˜Jr1&ÂC Ñþ¿0Û±§]ç Ø+«×m,Æ»ÄR»ªþž1Eë}"‚rV'Cô²ÌzµZýÓ}<êç|g±ÁW²üï÷õ¸ýu< ¾¥sK|yY OÊ>H™ô† t\žÿMŸr<ËÙzøÜîëG ºJ,“r Ç?Ö¯ 8Fù¢4ì1éð !GYñr¬}q´bí8Ú'¯b](î¬ 7ÆáÃÝ!i…2+й`6OúðçFœÃÔÀ¦Rõ(Žä˃ÚÈýAm±²‡õ I³¸õÆ”‘oT¬nÂyA7,‡yþ¸LŸè?rž‘}~#éÝùF—åÌÚô®Oio‹›Òþ8$¹¬ YH|}#ò!ÎÃCp=µÐðÜód¸#©6HËçQH<ž:å<<(ü¤W«ÿÈ9Œ˜“\ Ñ- +kòÖÓ$4¦ê—Mn»A”’?èïàÇoòvÉÁPsú\ÚÜ€ÊIÙQ’{8È% ÁiãG ‡Yâ@¥âU©õÃ[£#¥ä¯WÙiö<‰—?%±-Ê·Ú¢ð¨Î“q®%ðÊp7±öX²%fϬ–ÌE,U7Ç¿ŠØn·ð ZÇ 'wÊÅ]ªµmbžîȉ”üCèˆIõ”p`)&~J8 ¤û\è(aEâÞ N) Ú¤ ‹Ð˜çyÏH"@°%޶,?± MÿñºÕO e“–m¼“žÛ–ˆïˆ,Ó¤Ôà@ìÚ'zÌ/Å"±¼­3¦üA¢¡š¢|rõèðïÿK Wendstream endobj 698 0 obj 5087 endobj 702 0 obj <> stream xœå\[sÇq~gô#ðæ=,bµsß•žlZ‰¤lG†Ê•’\ÎA‚ˆŠ(É)ÿwwÏ­{vfö ù”RI:Øk÷×·ÙîùñdÅÉ„ÿÄÿ¿¸~òù×B©“‹wO¦“ƒ/žüøDø&'ñ/®O~s†Íf|4.Ó"NÎ^= ˆ'Oì¬G!OήŸ|;ØÆsjþS7/£œæálwªF7‹I ¿ÛÉá+øS‰Q«yøýîTŒó¼,&5’Bcx­µ¾ÞNã¼Ln²Ã¯w0Ü2ÉÇû#þ”R9‡m•ÂÖnøËN9\ÉœÞK›Ç’‹ÖÃ`[|± ÿºSØÔºáXÛvb\–Y/Ãs?‰[çó?Â19>tîõ׳÷„9Å´qã4ÑÎÎPh³ì ¶px™- ¢òÝìC$ùœ R Þº¨áûÜù4¯%{(O8çâbXó¼\Í%ÞGZI;s°¿H"J ã[ ÂÇôE–e<ˆ'™—ÀQ \½9qe6^5+-¼Õ+$„3A5îZóH”†É”Ø’¸ÔäE.( YÚƒê7NFb!k ä_á¬ÁÛ  Ÿ•ñ|î‚Z‚þ5bøi'±· Ûdkû!ÑL!r¥'Í ы† è+ð(`ꓳÿ|röô[p%$7ëÎkNmÑòsÓüz-:ÐfgL´Ûààk0ÄcJ¢ ¨btèEa´8"ˆï°Ÿöö!"L[W¨dfF±Ežßu´8†U{Ü‹õ:áªCÜ‹Ðy4 +z KAG¿ /Ä}•˜¶Ò³>*.íŒW%Ì)¸ôJKI€HÖZ?3íGª(/6íE«¦pãîÙòPY0…Cær¥ ¼‚ÏCÏyÉV{›™û‘–ùU~–Xdyõfe ÌfmÅÔ½Á­y$UiÍãQ[  dÝPC¶í–¡+TDh4k/FœøE‹g|0èÆVáÊk+é rÀ£X¬ð`®…aôcêâzξ’MO6h…ç©Üàx&[é‚.- wtgÊ÷òrý dñ›êŒQõׂJÅõÕ§ ~ߛʵAQBïræVþ.Zx1Ú$+\g‚¦½[íýØìMÐý<` óäµ|×â $@Ì€Áã×ä20¹£ §6ŽpC +Xb†Klƒ>ÝŒš…›\|qž%)v¤TiØÉ0¼&YHà´–Û/t/Ï9ŘšW ‚•œ ’d'©¶iô Ê`¬Ò A §Jâ3kŽÌX²Š¸²DFQŽÙÌÊÆW4â’˜­Ýj¸hvƒ„ôfLƒå `nDzWXMT¥H¢rX÷äN.X5tÞ™[ž®½Wîlœ—N@âé†R‚Çü›‚p€güÙ¦!B þ ”ÐU˜žöJš^Úš<ÄÄ¢d°!‘0¥‰þ™^\Rh(Ìb¼XŸq8W™5ùhñ¦%6ôëœìñËìaÅí ¤Æ ¨÷“6êa§ÐAñ›†¶ÓˆJ¼+ “òÒ÷H‹"lÐŒùp·F5méßóyd•©jA“‹ô¾ÚO‰àž7´Jóh…­þ]‘ÅféyÛȤÙùà­Z2?oÈ0¢ÖÚéÊäÉV:E†Ì…kž1_~Äz¡N›@g9KQbä¢ì#ë*¦'?+R¦´oH¢Îôtd·ð¬®À9FP8Ï{†ãLæ}§Éõ±ë#,Ùð1Ê©˜f gvv>éW¡Kôœ =š˜Í†¯Bï2bc mj[¹aÄÖ=¯õ;צЏ 3y4âŠvü9Írˆn&Æ»RÕÛeaödû© ´¬·‹2ã–Òh#c²&Ej´©UÅ5Ax‘¶p'‹c2Œ³UÛ³³³J5'(á›q–Ê¢öCybU(²ŸèˆŸÑó ÆêÏ¿‰ãÇú°©§¸£/àwáOª<ýªÂ/X…™f´âÚBk„, Å$¨áðDw>Ç¿Ÿ¢MÀ’˜ÍŽ¿?ÌhAòOzÿ6ÿ¨zñ§A^‹‡‡ê-Xâ‰IzÿšÞ¿¤÷—ùýmñžæL÷­–ÞR/!X§5ÝQË›Î>ãÃËÖ˜ˆ‘iñ­öxÕšä:X ¸L¶$Œ- Ÿã†~¾ ?Ñ–$¤A9 R[F„ríl Op+ŸÒÓÏóÏ ÞýRKåþ°3žäF^¾Õ:¹G%œôq†gáíËH 4›'bøuÍÁüÎÐùñµ`ÚÐ->\¶D¨:|%D½£ý\rî§®oZ“ÜFa\4ÃÑFzÕ×-Ÿ3=üÛvËû‹µü=<ç<>øÜ6ñõE8§BU³ô&ð@‹‰üé7îé˜9¨Ø³+Ž_½IÍI× _z—ßxȅLj;PÈàð2–Z|¿é’É—WaóâðÇôÖïòûßÒûo6ôÅM‹_ûãoøÃz;I Äö"ç…kºRs%&ª‹/ ©¬CÌ VͲOJš¯º­¥.ÊuyqÙÔGa¦2"»,4‚ÐÂ^O4Åî’.ñàÁ3§&x¢ÑKcàÔ›í–ßw,Yê^°5i‹c€£÷{zÿ}~xÕšóËÖœ-¤µ-“—óäy¨d°V¨zK°{ *ÒÏŠiˆÝ3Ôú@ ÍJÃåQçn^®üFÐ5í‚eŸÁâmηø‡ÿ™ð?(Òñ¡°5tÓâJaË‚½ÓÃwC~zFMÏòÃÿ¦‡Ê¿jñê»]P3ä§¼º?Œ‰üôð˃Ž\?ÓÞ†¯qœ•eßoAYtv¶tKó˜n9ϺM¿²Þ®\s ‡œ\‡…ˆAoZNö-‰ìy […Hô¥‡¿´|–—0&CaijV¿ï˜MFêõ9Ù¦Ë:ošÜ{Aì-yÚøÉ ÀÛ6JG°ìè^뵌Ffw§²8áí1X\f-’qÙH`蛜ãròØü=ÿ…á/Žô¾2?ý0Š(úi>ŽêòÏV:°áøï*sÙŸ‹Èå$úÌõ`\¾Ýâ2 d3ÄÜ·hÿ ÉރŽàι¶ë@žgïü.ÍÙ<çišÊZEM|ö}‹±%³êHé]“™·ž˜”·ÁK¡Çµ™Øl'~–ócKë•+n/E‡BxUŽ$Ð×-º]´¨$˜ØÆ¦;Ív›#°|ow)øºN ,똀\+¦ ¹W-Ž_ôH¡Gö©w¢RÇ7eÐ“Ž…îá~“~x0àžµBsæ)ï9¸"”ùº©Pú6ÊŠ#4ÛÏŸ#ìýÏÿ8‚lèMÜeÆäãÒ0Eç,BLÒnØñ×ÅÂj—‹öżÚWp¹˜6ºiueÎà»–JÛb-Ià‘™óßPÓoòÃ?ÐC U΂Ú+ G¤¦|C]ËQÒϳbmÜd{+úfÞF¿,2“ˆãmvït)†Ë­Ï*X/8›j»é±‘o”\ÏóŠ×BÓpÈæ¾o¾esXîqžTûcÇŽoÓÑ´ÈJT£1ÃÔ÷ÂáþG}Çx¹K^6y]‡üìyþó*²6¬±YË…ÉI%%Óœ¦2ψå7´>ùãêTo¡«DÏV.Lña> Óú˜ß¨:é&h³&ž5Ær¨1l™sJ¡r³/‰bßÊÙà«,‡"÷½5ìFRiÌk¤´Ò£NzÏáC£l,!ó§Ÿ·ZC-+â·œí¨$}ûøÙ%˜ê|#詚<­,fl‡lG×L"ÏÙB‡² «•‚ÄÒ·YÂ+/KPm¦D¥DH7ÁOb‰L‡œ†?MsÈm ¤,ÝЋ2é…%Mjo&„3"æ¤VBsH6Š99zèf+a±‹61%¸5š¸ÌºW&dèÕ9ˆv*² R#‚ãʹ¼™‚ªÜ8-K+³ÔïFwÓ³S¥Ã{–HžÓÌÃI aÚ¬kPA(Zw’a™P…$pÉŠbÙkA`Çê/5…ê˜fÕ'OÌ:㟂/«îQZ‹å€›ÏH‰×%z1'ä€^¤$•Jr>á­‘ M:Å …úBt¦ìRžK‰¦q,3~c®¾$XJ‘ÿè9qq³1U¸^in&Û*_1~nšŠ-‹²o¦r¡Õ§ :YdA‰ëqÒ<ͧsiŸNVT¢Ò’ýj2O²@é@RÞ/à6IŸ¡ä¸Ðç*þEõLú·*¾I…¸¸k[Y¡I`g%yr!®Œ |‹,SJñ¦_͉/b={¤l™wÔ+XåÀËšÍK 4³¥Z3\÷6 ›ÉÝ#V _ìÞ-Jø,³JžÇ«Ø…¦¹âeóì¯-'s-”W…ìåöCi#Û¾él'ÝöÆ´énQF,feˆ•~µîxðµ$áÊÚ^›´‹U¾xßVz1U¼2ýö?ÄVîÌvÂ5›·Yß–š.¸Á¾Bâ55ˆ6„°¥Ö,ugÎIT¬{´,]¤dkC®sû2¬ÿ‹uŒÊ +«<²Ë ¨´ºâ€9Lɱ©jÌ¿lW Åz-×ìŪZ#ý’>jU-zÏvBݨuÀ£xøÒ¬Õ9RÊ“ë‚úñ‹v±Põ^5¦‰7+ɲYÔ±£iKý¼ZµUô‚(_ª¹º ’Á‚¸Å­‚¿¯ð0™fÊØÒõï•sñE¬q4ª¯†`@dVj/3¼E\´TôÞ™PÅ ‹˜ì¬ú ·Ážm‚Þ†«Mî&Pp ôNä:e©3|v²8,Ú‚0{Ÿu$#—Ù±;qm÷ü'Ò´{^>üÉÏT”~=F‰0¥Cf•ýb§…¨Ý·Þî÷Ÿð¹Šs¢î,¼(œ²ÑÐЖ±vü4Üc±hca µÛÎ|˜ß"÷Ikœür´þ0| ¬.âî´ïC¬þø lP›O]½ ±º´ X¯IçXÝ€>ÝZ0™UõÕúr®0é”JÃ)ίÅên«ÚÅA;-lÃ)ó¶ˆIû;â™ÂRÜ•³:SX4­Îü™„*cÙâ>žÀ1¡J§'1ª«¿#M Ÿžù‡ÍƒÆÓ©@·Òµg·`°`—}ð¸°úÆß]±Ä\\™ŽÇ„ÊÚÁ4´—¹=-·RPà âñbq*®ƒÜ+ê~¨žæ1ÄÕyŽ¿¤G ¿ÎW¶²˜“Eª˜¢GŒ>ñ׌ÖS¯¤§/Ú RØÛ&؉òÊž?e²ñ{ì ®”%rôc%(xk&ˆ^]·h¶>Z¬Ég1æ>ì\&*¿aJ „ò¯÷µ æá/0¤s°ev Ê…È_ÀÙXïs­¢‰÷›.u~í ±vˆ´ª¯2ÐjŠWÒáëþ…ˆ«ÏÑ­ð¢ü\aŒ×£ÇB–vDíOs@ïú¨§gåÃvî‰úêÑ0Ïûù´Èk¸W€ÑøV§M8µŠ,(Ö¢ W¹C÷^l.DÆÔõpÿ ÂW|“€éJ=WÉ2¤X]W~ï+O`¥>—«ÉÞÅ{ë®ðmcPáV²ñÝPßs4Ö¾K~ôŒüæ-yð~¢Äl,ãÿ=ªÖéFX¯Ö¿Ûe íýk÷ü-AëËöº‡óqqÝï`í\ƒ~º€a GO-«)†`ûøÝ ¯!kÄáì–¥›‚·­Ùø¨ìIYFÉÜÙiùY‰¢$­ì¤> stream xœÍ\[Çq~'ä/ì[Ît&}ïiyˆÙN 8ŒH,#Yr©¥ ’K‰¢eZ>U}­êéž=»\‘@ép¦¯ÕuùêÒóÃ…Xä…ÀóÿŸ¿~ôO_I­/®ß=€?×~x$c“‹ü¿ç¯/~÷46[áÑDO¿}”^]¸Õ,R]<}ýèχõhâhÿòôß±Ë*X—Õ.:=½‚†ŸOzñ>yøãQ.!¬&þå¨'¹c½:‚â¶^¤&ÔC 1B“¹Xm,œ‰,l†S]râ\FÉP«ƒ×E2#¿Ðc¸Â%¯)rUî$á@Ò¨Æß&вQÒ8ü{¦:òQfà2ýÛÆ<¯Ê¦ÓÍõnéôÌáeÔ+Sö1@BoöÙÇ%Ý4fmhÀ-o¶Ó€Þ~}»£¥w“ãÿ ›®€!$mt ¤?9‡BU“tþÕzfƒö™æúØ©Ríü¢âk,ý2÷„°ˆÊ=âá³:Rà¯Gk&i¼z¬ï{Uú®Ÿ¬öíÚI°†ë·¸m0n§ZÁZ¾iú/k7å%yÿ¼LÙ>;à:Ñ4¦¤ß·aë`õGÝéКd&1jbÖDËËÆÎ¨1®ò.]~QòCÖpš˜Ç §SUjÁžuU>F|M@J}Ýdy)q€ë4¾È„'*a£dP :ù+;1:³G¬dÓdQ` 6|Ù¦ }jÃWíèñ5J}³ —\è™ÖN„r;j›AB&™±nef¸oŽBÊÖQ0µ1äA¯• G|ÝiâÖä&= «#­‰jÎ?A•1|R&m}¸DÕ¶¯jä^«€{]{û·meòž%&’c—4¼Ó‹Uë{_Ũ´YUló¶³]ëŠ\ @Õ¨ç¨_32I[õŒ'ù§x\[…н¸Ììô÷´ÞI"a·˜¦´†)’†÷ÉèxInjTdz™ÆDœöKû)“œÿØÔQ-““i;‹úªŠ‰®øK¹úOvh:®±ŽŠ¿`Tï%?R ”iµ ²L;oÔSìeJo»»S‰Z+Å`^ºÁ½t“1ò3Ò.mÕé¡VAѪ3-[ïVQÓÀÃä©×¸¥“2‰ŸQ㜉Zòóæ&ïÝÙ1¡züøþIckÒ€8ð eJc C0ƒŒjhƒ‡†‡£r<¤ŒA ‚±SÄ¢us¦T6 ¥"1‘¶.)ÔŒ ¾¸i2µà4n=Eð_-;æF²{u«¿p•·j3'åwv“/ì â'¤mÖ®lÊ«¹žÀ¥9K£3›xRzÒ¤„Go˜r%õÞøžÛ•ÂÃ>ÀkMÝãûE*C™^ÜØ4ë‚d‰M‹ÌxÃÞÛhg¢¢Q+Å[n£…‰ÞÀ9V*š4ŒßuÊú*­ÎìÊЮO»C¸ã†!Ð6D‡ÑG Ýt<™‰5e,Ô”¾†Á:+Ú‡"D糨 ¢Û{-9Åaq¢]f¹ÎR4s¸…„™=Å–£uϧÏÚŒ!lp¾ >F2È~°Kãâ·ÝÙûÄbÃ%Ñ£¤‹x[üªÈC8:ÌÖüö S&$·?=!¬ìŒDb:wø„¢‚M!¬ÅCØ \,øŠ"xŠŠ›"½‚¬x(÷† íFZFú»Ç&ÛX&ÃYÑGERñz'?4ÜÎu¡ÝD%gpÛ¥Lü0ä{ðÓ_e«ãW$jOºÞÓ ¢Ý$5!¤ž‹Éتî÷¢KÌJ#µ,à d;×ÏŸ†`Tá˦‰6³<į!Næe²7åÍÛé±{­³šFr"Øèº-¦h4èhHy”²Ø÷·g6f`üFA ÕKæ6ÆÖê0±²ÕäŽ ãÞ¬Ð'æ”Ì…„±ŒS˜S°šrI_>zúéŸPÞì…’&U8(` «- ¬Õ!Z|‰ËÐF™—í,PHbñVÉ•+ØAx»‚‘œ‹ SÊh4z‘~ 27ŒâçN¶³&Øá_qDi¼±¥»´Ñ±ÇÕ h†qª“lžØ]¡2]×E®Á ™q½ÒE.?ŸG êµ³yFZ2x[Rë3LÍiQ(H4uE±Éé“^ÞXˆk:I鄤­üS[tœ|k¢#GD·É´&›dÂ~¤Z»5 Õ9qa/ܹŠ%«æ.âÒ‚½Ó”KNÊ&ùˆÝ)ò'ñžûm‰ÄMú!ÇÉa»½m)c’ò}’÷­¹iO¿o‚­Cƒs„kßbÛ8–q=Dzó{1°8Ì-€&*4ð 3rÉ·›ô®¤¯¶âfŠÃê\['%ûó~cþxT åOŒét¢­ˆIS‚p‘¤4»,—¼—Ô4cÆWUž¸‰.âC²Ò$I6²C'iðìN‡¹ƒ “†ï²¸[ ~sÔë0ÔËÃÐ ôJf7Sfï•Cf4*g‚3{’E}Y'wàÒùÁâò’~dï £+W5&rJó6…ÆÏ&KÌå7.‘ôn:ø^™ÂÝ šÀrWõÒ{@‰Ï0xh¯L÷Ì¨Š˜ˆ©J¡?­4×rì2£ª•‡²è$E-CKìðª³QŸjùhM±Sý°±YSh£ç×Ã?ãx…Å”ë>§¼•­SÔ.£¯"·5ý×¼[w…ûC1C3 $EŸ‰M7¦øWì+.u›"8·ÄXæb’I yÁlYÊ3pz#¥PmèJo¤hX)4†35z¼øSzU¬iA¤Øx•mâè½HmQ9œ ‰±¹ÛÄ&Y\„$ñ:)Ùg3­ºìoˆ ¤>:Np{Ÿ(2œƒî£$€5‰ï× ¯¡ô~Ÿwƒ=dQO‹æ`È*H`šEÊnÊLð7u¯d¹©Þ N¿¦nuªŸ$^yÉXZº#”·†&-ΘsÇ@þvOÆ2î•C”BÓ°Ž’®¹ÎI*?N;mëlÏLãr…̰·•`b‘.%dV/[8GüF¡Cæ2ÜêUÅ­­ŠDÁy![=Ÿ¢1+q›þè®:äÚ.”Ù)Õ«iºXgâK&ë2¹§Áýµ´gî°1g5†Õ´"`tc‘Wíg÷” MW‚øªEˆ/ìíÞ’tƒz!-Í­L4«sè3]à{T;4ˆTc`Brrš+Š— b½äv—bórheesS ,ó›¦~9ǵNžÒR{©x-øx¼2Ðþ,‹–b]¿n§7ŒS{+ؽ圽@AÀ[×±gé¼'®Ç ý֠è ÿ?ÃË›†D‹zþKƒ`¬† ‚›Èƒ˜tŸ tiÀI6¢Ýö&åÔ_a‹>ÐNe(Áž~]ûŸ5¨Ævƒò=Ƨ$ô'¾³²ÅA­ÜçæçP†/<\ºøM¼õ¶‚lÛÐu4M˜ç™ðð ø!jñu]*Góå‰<çèÓœ†wŒ\_ËÒ:„‡æª²qÓ—H¹z{¿pÒ’c4ÒMÂ`SצbÀQ¶\µdu²é:¢4g.s¨¥ÀY—´È.Zvá<¤œ#PMßü@Úîë°p:–`ݪ¢Âž¨ç¾˜ÆÎFÙlë´½¶Äë%†%l 'È¥&%¯[”i&8,YXσ ‘x†Ë´Òåþ³ùã>ƒÜàO²Þõfîyuƒ]D.;‡ãÚ–mq÷› ÝÙoŠÉ¸ˆ™ÝËü5mý¯æ ³)ÏqŒHátÈCº6ô·?Æ™?#ì~G÷^6ìÀó€kˆ5S)νØÕQ¸›Õív§/>Œ>ûÁ›L¤Á§!h¢g«¥»422à*#Ç¿më½ó5’ô‹·•Ð ÇOp¨õaÜðø À^¤0¨µYF.F2µÚC{x0åë(&v¿Ž‘UMRKy—³;§Xߨ‘Îp*ÀRGÛ±wá›c 7¸Êz·—mS>yzueÊ p ±lÔÁt%û¯qx½ì\W†n·~ ÆXöYûŒ±Žrk²pÒÑüy$\H&ýì[7´d ™_µHšD‹©¦?§~ða+ØšÍB²3üê8~+Ž˜øÕâdzÄ;bS°¸IÒ¶O£Æ=rNGgß14}üóŽŽaÑç1{-·þ`v‡”%_ð˜ñx9¿MAcãŠäŠÂ÷Ä)vç)RÀ®‹ç Õ]¦yðe–;l¡Ë¥(ÑÃèo‚ñ+ûÏšjpfubF/Ùå–Ž7ÖRçÞBÓø ™z'ä|$ZžöÅj‰Ûlt,™ó‚~½²d÷I2J3!ÛìAþ~Iö<ïW–ïÊKÿŸ0äI…8Ãݤ¢PÞTª¿|6Y:Ðׯ;³Ö)÷í«×eˆtÜÔ[ Ð ×C³m}?â°a‰Í¶îsƒÀ"õž]Ö§[jó¢Ì-µù{r›ÉHÖý¦ò=E9·!úvDz9'<t%x¡!Z’¼Yk§×rrîm ù{^ÌÉìþ1_ ËU‡Ý=lRÈyÆ]]öî:lÓù&KW¤«w§`m ,¤ó#¯4¤«š¤íøå*žy™„©DAØ®}óÉ™Ý8 Šˆ ¼ò¬J=Ef¥ðá!¾SŠ‚ÇŸ¡:û;üò®IÂÑç9È÷8È· 6Õ9´`º‹ü†Ç¤fN¿Ä¯a‚,›âõŸR’OÏ‚ýEcFé i”Ô•òð?üÒ:ŠbôšÛ3ÒøŠ¿¿óÃvCXã¥ÄÒüM{ˆNCõœÊhÒûËöþÇúðÇöð²>üж¥Ã&·³<ø©µz±?iyC[æ_Ÿ^¿B?%}—ìÓúðê–Ñ/»ÕÆ à«ú0˰u˸ª]ç>Ñ&Ô§ßn~¢ýyÇ6Oè^~~VÛÖºÿл¸²¸åÄ@8?¬ abüûcÆ"i _Ö.ñ?h~’K? 9æFd—ÜýÓ¶ÀŸ YŒñ}{ø{ÊbùW¼,”ßãøñ¬²FŽ·ƒáƒ¹¾£Çš6îÉY¿1á‹ÑRøg&{Å BºÂó]{ÏûG¢®Ròm9 oY™–ÓñÇûMd+JÖßÖŸã`¥§X˜û]`x34rˆxne`§”¤ÙõÖRÁ\XyßÊw}ºåEr¡Þ} ñ q­ÀëN—ʾgîòíb)TnÌÅ©fŽ˜n½{aQŠBZ> stream xœ½][³·qÎó‰*ù û¸k{—¸¦Ry°lEfÊI,ë¸üç7‘,‘<¤DF¢óçÓ  n fvÏá¡Ê%s¹;ƒK£/_ßÀw;uÒ;…ÿ+>y}õàÏÚÚÝó¯ÔîkøïùÕ»+Ù•?ž¼Þ}yEüê4«Y﮿»ÊèÝdv!º“6»ë×Wÿ½¿?Ìiš&»·é/Ç)Î'£âþëƒ=Mzvqÿ—ƒÙ?<õ)Æyöûß|šÂ¼ÿ ¿tÎOfÿÇÃQ<ôŸðûùÛÃÑZrÞîÿí`ÃiŠÎìÿ ¾<cBØÿ>:xwÆÙôiž£›ñ%xÅ9®Œ£…‘é÷¯á%NfrûkjšæYïÿPÿ '…Ø©¼?k5ñGË-ì à3;·ÿíH0Goø³Ýb-炤 S"Q[ØïÚkl¶6X}ë®ÿ=oäçÄ;©GwýŽ+ éƒÏOÚIœðÑ9ušÂî+ƒc›óÿLOwãâG|¨ ü+øi£ö#øë{Ø[ŒÁhøœ ,Cûýÿåcœg» #¨ ûxü%qÑ›ƒ™NÞ)ËFxãœ6fÿàNÖDöóMg†gà ëfCƒrð‹ð‘¸ÿ˜yÅØ4ñwø²…Ìû‘ÀÞOÁ”Á'kùhò'÷OÒŠŒuìÉì¥gõÉ3;y¯Ù븄~Ë8Ø#I“:òè»ç…À t£Ÿa‡°?Ôœfck{¿„0ÇŽ gyÀS7Ó|²AÓ!ç¥ÂTáäBzá±nìÛxŸó…DþÛ>=î›X#¿mo6žþ ŒÑ³5—Û¸DC0ªí•7ÅhZZÎõ¢ Ζ~™ìüí@à Ž…G ›ÊdzäƒZÙFæWíCfFX‡8»r¢BŸ6lì4‡2ÚüB›ŠåmúÈîOq,üK¶Bì€é;_¼FööMáLà_5/VT žG&m¦|Ögœú”@ ·7̘­²á Ÿ¡VÓ„$fßg€a,×ý†¢02d•&7’‚„ôÆš“tá4'›åO‡d$]göio (‘L²æÙfÝa É&ñ£?…I¿°Šó\3>©Ÿê†¿àt¦_a§"pX=g²ÝQq:­OÖ“Þq ÈMf;u‚VVe3_ dÍJ¶(žÌl™oLVÜ÷³|›MX%ªÐ(È ¨©¦†+²Š©;¹›öƒ“(² ¢dS;PzÅĤg´Œ“|ï™zN_*Þ (T!mIê±>ˆ“CÒP¡Ã¶ÆMwÕß3©‚b|·T›':]T¢·Th" z½iª¶±yàÖ0×á\2QYpD×TÑL3lK¸Eh´A±8`ò¥Bñf<¡P(z&…B[ûWühÐíUæ^åN³!æ]h„lX ‹‰ fŸ.À}Íí+kÜEŽ~ûm‰=€>šCû©ÕDäû³N . Z?к~ýaRÚ ÷K>Ï›OlÖŒÓ`Éœ`»O~rDQúe\›ŽŠçhœUn­˜ŠÍ0&*ÆúE< ˜X[ÀâÐY“l(œ¸æ#MPÌÇÁßÿ©)»&O/›Â¦¯†r÷ñ§Ó4«Ìßš°{ƒ_ÜôéÜml'•?"±áP'Ãç¨:C_Ø\ '¬ˆjñB˜ç>ˆ‰Ò®Ñ&/ie>v ,m<ª1¿ e3·®Í‹%,À$w ôS5T”õŸfx NäAé˜/Ä€¢€8ª¤Øï`Bf•T4ùR°&džNâ3z{Ã#d&»±ÀoÐÒ{äɲžæ„¬W!ë¬ÏCÖ9$5{/˜5Q@ƒ@›ÔïÈSÁ`QL›‚’M€WB.^ ôre §HIƒ†žMÛÂJJ·GAKtÜ ¡U$H Q ½Hbbq^ =_`¥™ô`¡Yåç½IdóJj4d=áKwˆÅDßá‚ðœÆ-¨Ûœ¦äÖ—8çQ¯©ÖgP>Ôþ[q2-Ì‘@Π§{ ÕþBîŠ+Ggˆ—€:ïI³D˜U¹qS¯“ïgp"ß³E=ÆrÖDYOa@Ýà:ž‰Ï–¢ù¹dc&Û&DÁ÷œJ¢á§ã/¨Mü”@ÜjÔ¢®8v W8ËK@CÑ–)8¸L±xá‘h!¥A²AqàéÜæì‚§‘~^¸Es!²²ðDR´n ÙS€À¯;…ub‹;Û!Æá¶‹RâX2?ëL‡<klÛ›ÏnÀ|Å–ËT+Cõà3…•ª1PÿcXƒ¾nFó ä Rö§ìi‚Ñìòì>mæ³q;åU¶Ÿ«AйYŸ ë}.mA¡+ÆÉÏ"èîu1CÊÕéÓnã&€G?1j…"{Sl²?EÇL.ÎÉ£Û NA@ÿ’C<À‡½ ̪Ci཭¸\cX `ÊcnÁ)ìYÌoÚ†ô¸Xœªq`ÆøâW×Wß\½Û¤‡”»2ƒDht¨âÎÍvF£þäõÕ—¯<üÝû><»zð×¾zðü¿/ÿô;øãáïwÿpõÕÃÝ7ëyâNÎJžXë W óÀ2s®x¸ødò°>²¾'<3÷KìɃìÊ=mä<Ï…KÖØª¿Œ²·Ö_L2˜W0$i† !Þ:ÕŠ&<£#š¬ÇŒžÈ!žQ`ß…l|2‰ƒÕK@…³ûpêÒhì-æ­½X¢ËMÀb™^[¥È"JeÔ"¥C%G&H¥ ÓQàë Ä2“Y%¹ÝQUF¸ñ¦Ñö­TkjHçãzÔUµÖ&â(‘º“Ka8‘v¢Q‹"Š+{„dÃÔ3êV®ÆýI)§&6bu³‘R'² SÉêÚà}íª½&_bi q.´1ë.ÎD\!ð–çaÖAÌëMó¼h‹DP˜SÔy˜¼éU‡ìàÞs&èèïÂSÄúÊËÓ%àIÌ¢æ‹ä¯ÈÑ4&IÉ$€^ ‘»&”X°#Òù¹°ÈÏòhÞÞ¹è ÅcEý9/£/ã0m{Qï\o&9Åß-ý¦)…ÉlÄPs',ä­JÏc¥¦~\”´à£Œ³?ôçßò&øä²¤_bùÚöÒ¨…,á Yˆ%Ýyÿã KvºøX²!0ÁÐê° oçuq¸nŠ¡ÿ²‘èÀµ°|fOgȯ0UEž%Ø$´û:'S¯[óE{9A%%Lù | 9M¬  ðm€=€ù •ã&ÃÀF§\©ÞĬÔmÉàôغb”ÝÅd¾X­ Ó±7gUtX¡:Mé!ŠÉTÎÆ©k¥ÒˆÕ?± Ú‚ÿg «§$Îeà® ýõXô¡A(\Îþï‹h¢ˆ'!VÚ.k·È¿mª³«íR.•GѤ®tkXd"Ã=4Gû]øPƒØNw/ÛNqwǃ2T,fW|(°_¸Hb,Í`<ÿhâ© ¿Âpð»‹Ä.èY‹`hR]púw÷ÕR)ÚÎFà¯Ïê×`zçQèÞ|^_ÍQâ/±'ÀÇFli³<­e Òg¥š¸ïqàEúËdw-fûbaK‘‚,ºBÏš°2U 怢t.V•¦Z'öåÍØHŠ6ƒ~J±Xuëï*×#Œ¢£Èú»–j¥ª‚ä!Ūõê‚ ­Ì|ëZSú–8"ÈòÀ`xP[j«GÙBèÞ9+dÁŒM.n†ßÕpîÛêù™+›ˆ"É5¦Èé’” ÅÈ<Q™ÿ>ƒ½_ñ¥xv£°Ãj†ý©0Ë©‚Ñ­¦M*—ÜÆžVS5”ÿ Ò:‘³™Ô¡ t!~µï`uÅÊñêŽ\/^D-½nÙìiH™â‹ëÍòñ¸ÿ­ËŸÙûÜKÜ^bœ­ðh‚)gq™‡Ó*9ú*õ$‰8C§fšÖmk®A¿erœe^Vã.—¬|6¿ E¹VæÉ¢ÁXm‡w T1û’öúXŒ&ïLŠRÐ1SGFI–²„A(µ¦w2h3FŽt¡ÅÖ»EuÕù%×ÌÓ0‚̉ÑXd¯HzlFè(¶™âÏ¢žŒmÔþ·Ãǧ%S`Óm¤7/ØH1‰%–‰¶ûÐÄèMû¸`\¸>àSÊ |Èîèб'ßåN’‰U$Ê%|5y¦3ÃÞ …òšV0­÷÷*d`Å$lúÍÊF*öƒJ §¦”°ë¼Ì6̪QƒRÉ“~`6Þƒ2Jë3£ ÆÎSZ¥ñTÎ’mÀšt@Jµ˜n®ÿ½Ø93å¹lÔL‰¿æˆ‘’n8¯vk‚ÊV2I¤C¸(»T^wa‰¤uá ¿X5Á, _ ’‡³0µE°B$Nº.u’È–¥b;–±aáºäwô‡šQ85Å|Zù ²l,³.—U.‹’0 ­ФsE.â?/&a^©ÉyÏJÕ+!Trˆñ’6%ö&éñ³|_£ôwlëÁ9]äJ¡ìl†Æ ±È¥’¼>&s¤Ò}Ò»dD.iKÞ6«QÈ„K:[¨Â˜ÌMÖøÙùÊv.+Ëèrå‹®4¬¼,Ãk+Jžjéb÷/´S-¸{Kؘ´ÞidW^•ðžÝHî¤eIî¨x/ÉlE`= z±bÿ¡Ðnõ½"F‘FÆÌ .D••xW/ÆÒ4ÇzÅ"ÏF0SÇ1qJüÿ›ýÁ<”*•?0[)¦³¹¬žyq/xOX LNéÚôFxíÂ7÷ìâ1L3Ú•>ΡMçDŸ%6kšó9ÒE8 ßg•M9o«£å‡EM×*Ž^æÎEü¬¤7Í€«Wë¤(#zA6ª|N݆¹e:žZ(ª«‘^3ô·'Ð4À¾2˜5râ…´øjL‡«¨pàœCÂ0!sô›•)éqå÷ wÇ÷kaò8²bo–XBñ‰ÀÃ0`ˆ˜Ï»,ŽKÆ jè€ÈT¶n¦`ˆÁè³K)ϯ®…·c˜“šÀÛ·Pçi3ï-h*àæPûk‹wF 1’ùpHzôiûò~@ö^Õ_ÛsoÏ!¶I¨STMÍM^PvèìØiš÷ÁwÀàK ðwŒn*£›¬¦qt\\¤<ƒ1$²eô;rʪÛcS–:MÞèèØ£uu? èñÁšˆÙ-pe¦8ëò q¾['(RÀ•ß#˜8;¢–buOþžÎ±)ó>TŠ–Ñ˜íaÕ*:¿eΓ4a*0†–`ãÕ@]a‚Ÿõœ¿*€$§Y‡AUú0^ÕÍŒåÖ¶fÖ¹b*EèMƒ\R%Î 17$–$¹|ÂA›f#æ²ÍA“@˜yWi~'û°C#+G¶[µQÑ‹ëPsFµ\iͰQðJñ¨T=åï'ÕLQßÓš»UDwÁqJV!‹ƒè¶kâÕõ5Š ¸ý™w؇ñÉ%® FžjaÈNq7nšP–KUœ"b¸)ôòµ$…Œäb£ßhm*Ǽ…!»ÔYñ½w¯]e±lñös´®äî-³¡Us¥Aànu%0Ñwk í0úŽ’},ùÖB ªMâj}ÍŠÁtÍÜ(´ Êà9c'ä.v·RóIJ™AX/Áê³µå-ƒ¢i„ôñà(x™jÏí|f#-=ˆ®bäLi;`ûÒ ¸ÕA˼ŸˆªÊ·\§!¨«O†enÓS‰›äZýË?,:,ŠÅí’àDÈ"*ÅNI ²A×X´³V^–"·ËAROx#–û$ßråÒ‚s”dMRåHßÁšÐ -k9'¿ìR(„fáÍHûK Ó\HnJÎø^«bA0;‚·AЍ}W©KÞU8ˆ<çqÖoÿ¾âE.:V­€]ñö÷2JîúÐr¬ßùE¡«04){œ¯7Á&ŒA„ƒ[k7u‡Úi~JÈÙåŽíUé(Wâlc¤Î”Ý_vÅÂ"|‹ÆgTßÁªöC®à à`Q%°ªÊ¼ó•‡*ª”ñëj|2ØÊÔ–yŒL·ö L§O¹e Ë:•KíúPk Ïö©«Q4)…÷üŽÕ’,ujDÍÒ8Ñ 8ßøŽ%¹;EEÁÝ$穯¸œvVUçÛ`î÷’ºzÍÖö²40_/jÚÛ44U̸ɺ\PöyYñ<–½ÔâùÀlE—Éœèù•R¨kÖ$ÍÕ®Ü×¾˜ðX½«o%$[bVm ZŒm[â³°0ž¹9ôÍœ¹ƒÇ™¡%ªI-X¶3[H ÛÛ–nŵÛÇÜÅHø±oÿ¼¸ml;£€~™M–â‚æ|w “[rÜYž¢dÐïòæÀs=ÆÔȲÒ/Ëп\Y 9z¢ºk*Þ}uS ‰BÒOYúèÄâ<ƒW*”æ:iѵ’‡«ˆÈ:FøÍÙz &8#¦‘éíL*)úK{× 0¸_Í^Ab»å^ÙOð¯ÞOéJïëï¡—ES[=´þË.„(ÉNìv°6±zKÒ郗·ªËzލÓEÙã ”ªo”ïJ ‘;eåX\Ü¥€ fÞISªO?­Œ¨¬‚µ·ÈÊázýõz–S(ù°÷xuuœAçñÊ·¢ìÁ@Ö\‹[àðç²Fh¨Ì2ÀÕ¶ÉY%ûZ¾‹.©`Cœ«Àý©¡–IÜ~Û¥§€ˆ÷1 nšE‰jÊaŠwõ Vd:×ÝF¼€¢©HöN¸+_PT'ô¢ )M—œÍ«—œQ“6)Ä9=´U$nnW$]Âdw¹Ÿ'• Ó é ¦Õ !èÄy ‡3lVoÆRÁJWø$ašUÎ-…©OQx-#°¦]²÷8¾w2P1c`4œÄÞ<›ªºñÝ2ÿÂúÙH‰÷Öá ¦¿áb\¤ºyw¹³ìRÑVÄO¬œ@É5ÖÚÀYHv†•è«>õ÷`|R9Ŧj‡1«f—M®ÌMêV÷Š«zú¼5䌽HöA$±âÁå}9 Þ9üyòs×7PÇM`î»ìI¹­ÁÍÆàvçfgdö¾§°45p]è†6 Õ§J­ú(ÇQ_ò-öõ²¬T:i4¿ŽjXcÁ¥µä¯^ï-Ê‘B½¸³ZœÛÆ\»6‘Ao™û–$Ñþ<XSµô+·(ùä÷=œxz6DKgw޹ú:àô¯‚t}9åZîqpiy»F‹ȸ¦ˆ¯Ueyå6Ä–DÌ|}›j÷‘IÎJCÝE@±R+þÁfJÄ I¹ae ¯s”SV/ur­wÜ&’IKÃÙƒûÖJ=ƒ-ã–ˆÕK»mKãÏÃ×ÞÍE ‰e!ù°éÁîœK— ºVA[é’Ë»FŸpÙÙŒû“- ¸j+ [ˆffyÊM–+NÄ?©²OH4pƒª®8D¦Dz Vµ°o«8°X©ã ÕߊZ7pßó{çe«¾þžL¬áç÷Y*NG¸ “Ø? Å;`8+«7tø.¹•"·cêUµ_ªÊÙ7ùâ l¡·Ó9ÞÌ:õ1¬r|é-Ýè” hÇý”‡¬õ[”zëQµlAjàÖô »F˜´üû6ç6úË¥%ÊúÁÖòýHö†¸¬3rŒ–Âøˆ¬y&–”ŸaÅ»¦¥©k&£6ê;RàFñ°µH&çYžmñïá æX¶©3Ç¥U…ww®³ÒÀ9FQ`›îøæêÿuOŽendstream endobj 713 0 obj 6109 endobj 717 0 obj <> stream xœÅ]kÇqýNðGì7ßkèŽûÝ=6À¦;ó’˜ e$«]¾ r—"EËö¯OU?«º{î%©D‚ÈÝ™žž~ÔãÔ©êÑ÷Wb‘WÿÍß¼yô‹¯¤ÖW/Þ?W¿ƒÿ^<úþ‘ŒM®ò_7o®~ó46 piYÅ*¯ž>”:W^]¹`©®ž¾yôÇC8Úƒ:Ú?=ýG|$öH°‹‡žÞBÃ'Ç“^¼_WyøýQ.ëÌzøõQþõx’‹1Ö«ÃÓÖæËtU›pø ®jèõàà] \Wj]”¤­[_bcxR{úÆ¿?âOÞùÃ?`¿a•ÂÓç¿>ž`¨Æ¬67€ôá_ ”øªüô\žÂ¾Ò­P8D÷…æÖe Þæ¦AI»‚Ž‚$ÓiƒúwX††ÿž´ÈkÈËS7J9‡í!¬’yéùnÒÚŸàE^®kÚ‚Ü‘°òð:²f1îðç#üíÖ‡kXÞwÇ“Y´vÂ^Á `éú·iÌïu¹þìØÃ f¢µ6zvó®=úzúÚ†à`Q_ÂV È^mVEGq}Ô¶æþWhîpÝá¦v~Öw~h»øæxR‹sÞ™ò~¼ú»0‹5¶ã3\°X§ªŒJ¹< ¥ÉbÞ^@Cã!íám»J:½‡A„•‰6dçøi~«¦þ§à$·9ЍxÅíÈx<Ýù¼« ›uí>ÒþGØ–Ì™{`R2ŽibÆÜûÜ Š4x/³3åøŽØäŒHå©;ά÷Ë&˜Ý25\××­(Í`È­ïmžƒf¾&J~>Šòp:i™8Ðùñˆ•0LÔQ¿Ë[0™þÐ=ѧ†É'€¦ÃnÔ{>êø“$Ê‚ äm”ìMÉÂUã²Wc"‰{¤y¦¤·-¼®­ÇEaÚß+¤Ù„CZpÓ>}S¶÷«iÇÏ}a]Š‚¿qDEUTEWÐ8¿€§O“½íe âãv‘U"¨ÙíÍ6•àÃ(¢mß%Ñ–»¼¸nK¾ëöîSÚà“¸ ¶àzŒŒDê/¨4WCf¼©©GŒgBT[|¨ÿ€6€vÂxg14(\‚)®aúÄã]h]wÆ‚RèÞWä—âHŒ–›ÆÜè´/S©lþ›„eYvâÀ™Ñý(dš´†â¡C\„‹£ É3n¬DýøæP»«‹´dTãIT݆¸”f¦C¯Îî|'cð6îðÇ*éžüSý­t© t2&Á´~jò2Á^öͱêèEÈ8(J=ᢠ4zÃÙ1eÉËÅÝÌã¦y˜\N–§à£E3Ò p{ !×Cá{Ò("[a³a–ßhÝÏË`Àÿ{Tv€ÞŠü{¼h¢_þÛ„bØÆÍkŽÑýEšúÕ¯ÙùìàáhÖÙ#œ˜aÉbRÎGÉÍ8¸]T†9g\/ØÅûM8ŠÎnÆ —ÄËõ£c·SS`sÇ>Æe ¢o7XWÆ[q²*m^Ö8S© z˜%VK-(ºÒŽâ±Nëp,/W‘°â†ì[ÇBá¯d9›¼mfžÝÏ´Žß‹ç*À*ºá+(g|Â2¢<ŠÄ#­½•0»“Q×î ê 7¢¦ŽXH!XÌ7¿jHˆéèH”îÉxtµ^ѧÉÀ&¼Em)!(AO[B£Jû·|¤‰SÞEÚ‡ñZÅÝ€F íBð!ÓÞræ1¼þºŠ-1W¬‘«‹Š’'äÄ–›Ü3¡²)u$=Z°ädìâjøBfQ’•*ÌýI¾Áù¥I K &;{Ù=„4®>|J”÷HrwˆߘªóÞ&®ª\ËÞ†` E§#I„:eÔF’*îÓE®3¦V!ŒÞP`|`]Iè4‡H)€DáHš†Óð,ð€·"0 šn[fEbwr |¼XÛA`æFH.¥ÄÎæLl'­våe¢,°€å#Ø»ä† FNªóͳm½Í†zãÞ1NÅhª3$UF¯|'ɰ<-jrê J;aç†'sÖ$ÒÉ+È}ÒF•JÑ#Ó††"áê§šVg½4—NÃ}¬ÊzhìƒIeß%蔉ª·éí”­¸t¢(è$§ÒQLs3zã‘AdåDøœÕ„‚êòxêÁ¥¡•ˆÆJUJº9¨dG,ë[´YýÕ9Ö Á CGáðëã*(«õ‡±z?¤@Èþã(%º +<ãMlõeÚuŸ$åšSùc×óÇ¿=¢üûZM3úØíoޏ‡Ò:|)-e¥XZ9 Ò×AÚaåÁ/²7ø‹Ô.¡»çìé]öY®ô!1Ë{âRÄ&N–͈ L净¡ë +Jʬ.+u¬ Z*W¥ÆŒŒ&á·(±Xöêª øæ7üy5‹Í%$.‡Z)ûA ZÝo·b \ŽÑ´Ü_'W"dDîtz5,ÖËõ Z°ž8/x JžèŽ\!@åÁMñÆ$­>K×-bVÌÙ5ºÊÁ\~»en :šR9x.m U°FIçET_ºb”Dç°G)€VŽÀKËY$LdæEÚyTö)y—ø¨¼ó6íü*"L;³ó£ 52X¤¨³Ôâ"’œº3¼ú‰äÄ,ª¡q]ƽÅTàë"s¬{>#&ŒŒ¥Éùê«b›¦AÂOÀ›q$ו»‡1"'L)E§MY¸¡1z±zÜÔ’Y•<+ gJR˜)zªJûã§?gåø••‘4˜Øb®“C P‡ÐoU²ºœÞX‚ÖÂ¥B½½¢ž#Ò–,z¼®µ…„¡™³WSH³¯2ôF,•^ʈ>R 5-º9Wd‰’÷÷fVÐq3[§Îý?ÑñÄ'BÃm2Ÿ­žpl+r§>’˜IMq3#]=²ÐHDK}®ÊJy ë&¹È`¿Ýr˹ÐxV‘Ÿ–kGE> ‚Õšò’Ã5¿£èì®i=ã1ÃTÂô®€ThZ¬‰4ûÙè%7o¯ÜX³\€:x‹gøŽðnUÓ&ëÓIHîv ¡.È=P ­À#^“uTÓºs¾ µª6$œ3‹ÏŠ·´ 2$¬ÖD;ÎÈ6pÓqÏ…kÝ1®¯›tG­â‰­_ã8¿œiÝEã© ¢ùdl­Å§Þ[$µ¸N"ƒtÔÅ•ý.J\ëA–´†?o‹N¶ÀbÁîX¾£$­6›ùÊ×]jnŒ£ûÚïu#`4úm*±Á¸~#[9Jå¶Š€|AÐI†É\]zŠV~¼T‘ø ¡ÿÆ’lí`&´ Ñì ´ÓG"ÿ3\}Þ1ÆUå˜t8EÒIoiiÜ.‘-3]ÐÖ˜MÂnÑÒJŠð÷Êxž>w Ÿ'5sŽ~*–‰¤º(ë–C)-£ÕÜô 2•ìüOÊ‚wýYaef‰z£&üW=ûú³ÌÅi×d>ì„df™f¼Üu¤àXô´}ò-káØLÙ-˜D‘YLèË‹”×f}aZ<ƒÙVx©ävÁÂP‡\G]ÂY…~‡ r`ÀÄbáRR‘í2”²íòP2à RI>¾àÏáSÆCq5¸Ð÷–*(b¨òÂ0$Qø ɵO¸ä=M:œõ;ôžr5Zò.þ˜_v0Ìè ·¦„½Y·Y6Âû>õàñ®\Np6¶ÎÙqBb~«Ž+ŒÌ_‘Š.ÊͧãMÆCžiÙ@S#5qKÕ•¢¿$è/¾¬ËNŒcÆ Á›š³‹«„䄘ù”¯äÆ ë„¿Ç?þ.ÊT›ÿ@›c&E¦J©tã>ß0kªœöóc}‰¡•KÜB¾ø]»(ëÅÿnŸ×‹wqÀ±ÿtáÔZuãN÷h÷ŸÕ‹ïÚÅëYË{Ú’NìÜ;÷ÏQ]œc¾8ÿ"€mÒÅ ¶õ› ÷LF;¨ÉU78B-–²eÁBVpéÉ ŽY>t‹ç²|9ËÛeùÐêqŽ¥! #o/TGT†®R¿+QŽp¾îÞÜxòzd {âB5LùL³gt'‘Œg*Îr½áyéÎÄû¤ø¥#þ§¯)G 7É‚×Ët±n fÞso+5ÜtG7êèÇÓÙç‹Ð @ƒ&Lív¶5“ØL´§áˆ;‰lV=›ò¸Ü”ï ö~[ÈÄ#€¬‚cw+'™úT&MÓE1*—]Ñjêò|P3­á}×oÝ‚^¢lå£;´È¤’ãÎå/6Lü˜n§™'C¶„{‡6⮜©M+‘Þû¬àAè²N+1X÷ÃW§º“MO:Š}8³¹’°ØÆ©˜ÓËÁN/^ Æà°êÅüòHÿ Ûúñä(©qt÷±¡Õ˜0(›~yˆëÌ C.?ßœC¼ŠN^™ìs¾(U´8¡c†·<òþˆ…`C\ÊÌ¡oÐù•ˆ|Ÿ'Kê$žy‹·J“û7Ò¶W¾CÀd†P7l‘>¬’ ¤uù.ÁL‚}uÄ-ñËåö‡43é y: XŲz»¾;OB;W´(yRÌ7 °IW+<ö‰–E41hÙXh=hY‚YÉx±ès ¾q’Vf–Ѫןl,lB>cwÊ_°?¢™Éñp–«¼¯i’GAß´&3ðOÐ7Xã ¬'5ÏRÍ—}ÓÆL¾.k|Á‡¨©æ{6kú¶W´Åtµé­X<’%G::•T ÇùéΈ»S¸whóbìYq© é’ªÓ‚Qnº2û—–Šû?⌺ZâäHíãçù†G>ŽÙáÌâ‚=MoÒÊPp+©‚W"i¹<ê©vYðŠá† ÚN°N9ºKhWÙsþ)Á1žHçÒ»ÂBn-[· HÍÇopøÏs ƒòõ¹Žöl:7:Ý<¯€ðNmž<¯û¾3¹q16q‘ È£Aˆu“ðÆ·¶ò?–¨  ÙžÈç8&4ùª[úPãO÷Y7„;vãÀߤ^Ü©eUýÉØ{&Q —äÏ`Ø|üh÷9Ñ@tò›ý!uµê£ã‘#ßN¦|ýV´Õù§|p"•‰n|yçáçz¸#Gßñá%ýBæý‘É÷Ζºe°6”*ˆZ«!«¶“å2¿;.i¤QÕ›RI«öF~õ-]Yrj?êˆn¸¶vE¸i¦›ÒߟáÎõŸ±ÀœE-Þ[ÒÓ¦˜³6®ðHSÅbÇmv®-öA}OK؈ •çWz ï¬ÿè ŸºZ6zð€ÒnÊ Nï\ ?š„ŽE¥E!¥¡†~ âÃÔXù2E_g£jÄ G¼`Züj‡èU­¦û¶gJ03†jÝ‘Üì^šF½—×̱¤Z¬Àœ ¼/»< Ga7:aÚ¦éG?gáoòiµ8®œºåÓAŸAnfˆk:˜ýÞ‘8"Ld¯f•t¯F RJÎQ…×:÷%zâŒÜÀÌüØ\=‘s†'§ .ŸÔÆbìJ–ó­ô‹Vµ×ÙäÎï:»O1ÞìTŒ—éÕQ4QóÍ8T„’XEìI2Ñïiötš¢N7Þ—k5½›o´þ^ç&% bZš¿jW¨ISž ŸdÑZÉHÃ'ôv¤ÔD:7‚úóÚêf–†~Ý.~ð°à±–ççGû~–\&-_ÓyávµAÌä`‡!˜•’9h Y)H‘ƒ'³Ûi÷¸ó2þ*ˆ€Þ±Ñ–Õ¼ÙxáøÐ|5Žõꯢ|ùôÑ¿Á¿ÿ ×J_endstream endobj 718 0 obj 5679 endobj 722 0 obj <> stream xœåZYsE~ׯл)´ìÜ3•'p%”ˆ' ‚‘¸­Ä¶ù÷tÏÎÑ«•-Pì•мšé™îùúœ^½™¶ ›¶ø/ü]\L¾z΄˜ž]OÚé·ðÿlòfÂ<É4üY\L¿™#™Å¡ÆµŽMç§“n65|ª­lŸÎ/&¿VºVUSóÆ#*é¿ÌŒu omuPÏDc,kEõ>r.Œ©~¨E£µÔªzVÏX#¥2¼:ÄGç¬tÕ“<:ÏÀ¨àm#5CZ^}‡TÖ:§ªõLÁ ¸€£0*räZWOáQ˜†3–9Öš°¹qŽE–BÚêy=k€;)«¯k8ˆ³ŠSZ²/Ð °ÙóZð†µŒÓù_êx&²žHðcÍ)ëpÃìïó~,U Ò´t0?Ü-@-jÕQ &(å Ðk´Â߆ۖu+ÎA†ê?n€ÊíDuŠßÏਮQζe¬zÙŸ8Á+üxéüXG|“&Žñã(-ƒ'ŽXí¿wÔïòàë4x’«Òè9eçOjÛÀµ^ nºÇÈ ÒÀfViú*O¤ÁîÓɪe=C{|”¦™>o²Ìƒ_‚­…/’ˆxÙ;lDø¸,ãÖÁw5êU0Õp^†ªÎÏÓ#.ž…Õ3nÆœ»Gð+ViÙnê‚qRÒâQ²¢Ï4}•là 4úVrG}#ZÖܪïóÃŒ¿N£½$ýNæîIƒ½…¯—÷H}A2¢.ãhÏw‡½J<ª N¾JÌN~0¢%Ð%lµ«>ƒÿžn·¾ëËê­p÷‹µ¾¬ï+ûoŒBû™4ô¶ÀýÞÚ/£˜‚ ´­1âm:ïy0¹{ÑG%TŠö÷n$-9†èÏ’éeBú2€‘Þ7¼7)_”¬órL T S_•ùXïÃbJ¬ëŸOÓœàîÙ«D\Œ°Å‚j—°‘}€V÷]3ÛƒÔÉ­u)6qýèƒð#}\‚ôf_H»”Œ5²»§FЏ[‹’ü¡ßêLú†ù¥ÃÓßôk¥èOÈ/r ‘à¯8o¸°¹[’(ƒnhך(tC…ҢгD‰=Ë~7q¤g9òì 3½ÑóÝS}|Ô#ÄÃëˆ1Ó~KŒ †9‰-ÄN¯JÖ™C5©¿³è¾/ ã;dØ­y¤ç·…«}ß+ûÇñ-»Q‰Uë|œÉˆU÷&…ëF%kÈI°E’rI®?<"íuïðûw1@›ÞÅ ýôÞÅR>ÊÌT÷ýYÏLº#¦%«Rë¿f›tÛ®s>±wïRÿŽ{gUáÇÓ¸0DJò; \Þ½½b=  ù-o¤æ*¾&*¶‘Ò»(sžY¥a°¯ÑaN(¶wãÎyÚóUâ3ºéíU6# ‘«˜¡ÝMž<ø¶ä4$ÓäV1ï^@À.îmïäö€â;ÒPÜUF¿Ÿž7blG‰£Ç¸ÙM‘ñÀ!»÷‡©0P\>ßqV\ë<ÅÞô³RXÓØ¶¨¿G}T+Ûc¡Ãš3ë˜7.f]¼+"qwYûxF½GI†”YI ™%-¸žÌ'?ÿãàõ8endstream endobj 723 0 obj 1877 endobj 727 0 obj <> stream xœU»n! E{¾‚Š!¶Á.“ÕäUä±!U”j£l5Å*ÿ/ÅÌL4„@æÜ{  -´¹í§Ù\1F{þ1`ïtÍÅà‚Øm;Íö¦.k)ÚúmV´…ìÈ) Ù:›Ç>»äóg}l†Î!©¨~)xðC ¥ˆ »÷D8‰»öä^ü€!¥\ÈÕ™ÖjLìŽZêêFÍ Z'’@ØÓ»ãÔ`UÆÒ'Þúv*cqÍ—¡ôú7?h«)IÞÑ=+€Ø¢6•:ÿ©š×Úcj-‚ÞCQßÄ„KÞP&L‹•1vÏÙ›z×oxÒuØ]L¾Úcã@&l_?Uóªóá[cØendstream endobj 728 0 obj 263 endobj 732 0 obj <> stream xœµ\Ys·Î3˕߰oÞMyG¸ç)’[‰O‰.UÊÎ)Ò”"‰¤%Ѳþ}ºq60˜Ý•HÛ%r9ÐhôñõýmÅ&¾bøúýôÕѽG\ÊÕÅ›#¶ú þ]ývÄÃ#«ôëé«Õýãð˜Z 6#Ìêø×£8_Y±ÒV®Ž_ý¼~°Ù²IeY?ÛlÅ$ ¾>Ù°Éf˜__§«^¬ßnøä…W~}¾kRk¾~½ÙJk&·¶8’“Ö óßãåÙÕdå8»Ö“’Þ­Ž¿9:þÛÏë'/&.¼__á\Ü*'p06)á¼2ë—8/wŒûõÎ:éuÂ8cáÅ­p—L¤1 Œ–‡PZÁ{ðÑ1£ÍúyÍz»¾ ¹QV Ïr§8,×f{޳Yxfý¸¾ÿ~³…û‚Y¾~ƒ’@M|É/ÁHRxãÖ¯ð}5)xôÜ×Nº¼FoÕú¦Zç|ž ¯GúìYTz-ó¤ÂgÞ:ØìÉ3yë'n˜È¼= ``Î$î)ð])¯Ãº<ÐcåúŸ¸o-LüÇuž3Kßz¼Ù*Æá=³~º¥(.Ç×&@ž¬QðQ²I %aEeŽËø$–$p «” ÖKd¢b„©¡ëÆ}ƒ´Ù@þyVïâ¬×õOlr΂ˆž„ÄmÞÚ“H¸‡ ÓÚA}‹÷%È ÿŠz¸§×/62ÐËÉÓïQ>€ZëÍúÝFxølã‹ ej’RRäÙa“ž–7ñ™Ë€Átëßc×»uI…eñõ²è78…‡Å Ä¡HÁ'ÆPŸÏ@‰;f’E&FZîÒÔŒ¯?‰×sIoGé0&¤A÷Ÿ5÷°C‚ÜOl°Ü„‰/ëÈ‘ûFÀC¿¢Ì(夠¬QS²4Eºó¸‘^+ʉvXdÃ6óaË%p ²#=Öé¼HoýtFU‚\”.kŸÈ0‚£‘ÊijÕ`ykñ "oq‡vn} Lô:?tÃ3¦“|1%†4_FJ”äTмüAµŠØK\“ƒë>ÉB›É¸¢ÒZ™¿G ¥–ABÊ#—‰m`â’d2Ë#Ý&_l¢%R6ÈÒI;GÞ ÔØ° þ ˆÜdéoµŽ0Ÿ|¬LIfÁ»`VpG¢ÿÐTΪÄUQ$÷/àM¡™‹ŒWýzYÞ(—ˆ6Œ„™€›epM’lYjÛ>[uêè@›Õ'ò1hOpÈÎÄ áX°‹IÀî=£j÷a$¥¨™}A¤ðýÆY ‹©õgð¬W Ú./BXËhœ Yža*ŒonS’¢sÝ%/FN&É‹¨T¤Æƒš5’À.cùJæS811ïç¦%è“™»KÞU€Öª¨²–½@ÊÎ*©ôŽv;¹˜™Ê_öDÏýâä¼.Šä6„3“ä~Ùm€K ²xj²¯‚Z90îÕßÔ×G!! ‡Tð’´K8«£#†Q‘¯JÝÉú‚fyˆæ]Ö¬/à.È!˜Åïq*L1¬¿ÃœƒwʇkaM° ·€*ÁMÅDÄÊw H)bs¦›Ô€2›a3—‹‘P`ƒ¦ê¶p%àÃÚ I’@q4¶´Q•È™VUöE!¶1üm€‰"¼Úg}ø cM‚†ÖeKã©®"VPQ•ξµ#ÞâRɹi¶²îïWhý¹WnýÍÆi´€jýÌ¥ÄxþQÈüxfAÕ¾DÊÀpBAÜõ[ËWÒ' ¬!/}·DØÒ Ôà"¬Mœ-Ä '…µ3ÓrHg›k"Ì7@-,«jçU…ˆ[©g†°èEÜ^gFv>åGÚÐ’q*è¸16 ìMãN± æPŽ‘ ÐcöóÈ!ä™:­ú7ž¦èG >âÛнŠo iç– ¨!è'ñ~ޤ‚þšE“‚TSññ÷e#º¨‚l\„1Fh c÷F‰L'ÝœðˆŒ"µÉãÕ6ºmòoá£wyp¥Ý †m­n‰¯ÝA‹ÏD’?ËÓ‹Íœ‹x~æóôZL_J.iú’ƒú­¶hГQžÀ˜aÓÂvE€ñÇ} R0À4[Îbî0=J\÷ñ&…bú&䧃ÊÉ Ù:~Ó†¨Q ‡Ð,E~1%d<]|‘ždÉj÷O¾]<-_׋çåâ[ú)ß>É‘WE;rÖ¼a ׸ÌðI@v  ÚF>}(sàU`†&„}AßÎäÞ”‹•C•—Ïë“—”—é"®öº&Í}Àa=ÏñÇi¦¶p8Ô1®XFä|V–ô{þ_|YxuÝÞ(r±°ôºSϚ̤þTîOõþ¿éÅÌšÇ;÷œÊÉ˽LTѲ#ÛJ^¿*ÿ7’½§õbYܰ¸°-êi¢nF—ªŒ¤m2ê2„Ù¨$÷|î_&‚G€E …ñwxŠdft+ÃpNá}W á*D‡=Ëqfžè6eœÉüËR‰R4éÒ¨˜©ú8òÜ‹”N…=+á-Ž*0ƒC±üUØÙ>½–Â’Œ}0¯ä"jžå ë>¨EH÷†”5<=­£€rÒ¢üú8¥ û«Âx);ØÒ”6ÕãßKöM$ݦàj”.Òœ\ñ¢†Ä„bÌ‹]Ò¾ëŒhpdCQÈMLIÉ ‡C|–d,J#)þkÕÌ*Æ$Åž§ued³®"$Î4ða®õYOÆë{0þû„šü!cÊ/\”üd²I¾äiÒ 3 •µbZÈ:‘ñÏftˆÐÑî\œGLNÅÎ>²R,$œA^¸“TU›r(r(Ô|¶?r°ïI-"wQù‹UŸë4HÉíûÄX +Úljì¥)%Û â0Cé'%÷[#Ò´¥ÂÛ5­KKK­‹:)£½…RÄ êÒ^' „Ãt÷žOAÈ1+æ‘}ž;½«`bz‡‹Ô.HÉËx½Ú®Y>U‘HõHŒcÅËF»1– Áò‚ þ&?¹Ë+ÀC*u]ìs)-¿«Ý ·®I#øÈ‡s/«åò¦,BSRɈè-ëjQ"û s›j`¬;¨®èœé^Ô ›!ïÂOE©ãé  *±‘Ý nüu©í‰¾¶÷®‚³þ޹Nâ$ä™éBÆÿ4ÜŠáõ®¬Xˆ'Ú¬êHõq§]$ÜÔKxZ™§ÛRªlGÚÐ Ó <E£ŒYžx‰*öMÌ^þ@{‘ªH a‰¾?ÍïTtYQ,aËuj&ˆ`KV!•Ḩi·¥¹•jajm¦Z)õ±…ì ¾Ög_ Ø Ë2åÙÛé‘dAÆÛlܼ‹$r°Å“KŠÙ–]êìuÕ…3u¹*‚öð RK|V‘UçU>Mò#†ÉÙ$ûiú¡­‡{OÔ¨Ó:ƒÈÈE´Õ«yÍÔĶùCrÑ’“Ȧm^T¡´9ÿ(]]ë€Àú©¥ÁBÔ!K2Ö%?(ظ–ÉÉúž*š7•4O(Mrïãt|#‡u®ñÈL¡ªikðµklvµ6). ¸˜ÛðØ¥¯æ&OH¢¶*ÍØ$•¸UɃ&î˜ ¹ñ&ÇÆø®ÞîÒA¤úë"µaã'I‡:åNhs¹…õ»ñÁ%°H!ŸslCx©¢‹ø,R5ì÷&–o±©ÜãyÓžMÁ*cÕED¾³1-QÆ2Jý 5¾5:¶–‘ö˜8Î)™2¥„ÕÔƒ~ϳ mOMë&ÔEò=:™«† \@áhüFaÏìTJu%ƒìã@µ.Ì€u]À•·-úå–Κ9Æ/ŽzXO6zPÄQwɰ¥Ö¡, sº&îç-„Ó“Ô²,B")s`™Û°‰ß•#z–J~¬’…P!l`ûLØ~5K½#ìrû³®Q<²j?¶oìwÜü&'zì¨{Uɲ4j:eJÉY½‹Øà†rvl_¿*q:ö•’HT¨È1Ûþ9î™cúQÔ;šo!:†e‘3vÁµQR uÈjÇæ/H%¨‰µ¤M¼õlálHé!¾rèäÃ2= µftSÊí&íDT£˜ªho voìqi‡$·c[>ÅÑ€øÈ¬ö@Å^=Éé—“˜3BÅ^Οà_ˆH°OLË”r»­ ê¶{x®Âm’˜\JìèšÜ*|ÓñèÎàHÓaçøÚ½Ô™;;#‚÷ÇÝž9&Ã%D¢ó0\ÜÂ]ŽC2,fIhÒ¾M¼ýYJ!«»ò(ÒFêl[3Èü f&o©'Ö$˜VÞº}e†60˜oú®† DK%òˆt:‹—Ï8XNrs;*”$Û”Ï5!œ¼½x® d>BSvàÝPýÚ4-Ɔ/¤ýûs@h͇# EEîñ0˜_>n?­º“tÆŒÎØù¹‰ ÊfLæô0ïRøXÎèÈ[ ÁA”Ïa0aB¯òž6›ÅŠ˜@jÜÊj…¿þ´‚˜Ðfò¦Y*†-AñÚ_ Ëøe>±%GOÊ>åã‡åV-o’-KVü°Ÿ¡wOÍ[õòÜ¥Ä_>à9Ì©7 aÖοÎâ FtÅwS{ gYMwà9’¤ËŠXÌM¢fYó¼±pÆÁë>øáù’¤WO8p¤‡Ö‰u< aÀ²ü©ebˆõNƒÌQ5>ú› Òú–å…ÄôÈŸ¾(¯±èÝ,êô]º¨ïÔY„œ–ûlÀ¼~Óû|ÈŠ[¢¼Táh¯eþÔ| Jü†¦Çn¶ûB6éúPÛ^tÏùK>ö§à¤@»1‘CáDë¼Û¤>I¿#!f4­j£•¹Iíᨡ8uä0Žש~i¨’Ô„ ¿‚Ø üVãxäÈ©ÐaÖ~ÖO=sˆx\ãuÃ5ÿ&›y:€+$bŸg·…·ä<'R‘šäó0]2 E*ô-¤¦ß=}—S4§Ã J»¯{04S I ä8¨Æ8äŠsñA`ã>æGøâÑÏím1ó×êí4ÆÔ¤§,®‰SaÑím±£–s“éLÉbµ8“—;ë9ëA©Ò»ÄÑîþRÌ{lÖdƒ…»ö4[f‹k_hðØõ½.ƒ&”þñ|2œ±3tÛ²ÉÂ-ýjo¨rG‘š8"C&IB Ò- Á„ºŽ‘dp­?ýÕ`ˆ&endstream endobj 733 0 obj 4774 endobj 737 0 obj <> stream xœí]éÇqÏçÿˆüAó¾áôÝ“ Dš¶iH–D­!8V`,w©%-î!^ó×§ªÏªžž÷ö ø!°Q3=}T×ñ«£Û?N£8œðŸôß“óƒO…R‡go¦Ã?À¿g?ˆÐä0ýçäüðáQhæáÑ8O³8<úá v <´^Bümð3ØùŸ£?á'~bŸ1N¾::…–6[5:7ÏbøãFŒóìõ<|¾‘Ã×›­µ6NGµÍãøTi?<…§b†nÝà`¸ÞH9R ßm”ƒöÖ _á—RJk±ù4úYÎZ_`/q¨ßA eG!4 ù.ýÔ~Î]Ln²ð½7ÚO°3ÿSÃŸÉ æ)ÍÛKèû137óðífk` Nøá¯9N“)“‡ü«Lƒ/qµfTÊÁ4”Å$$æ_JWäû8µF†©IÚ]O:‘öˆo+R^nÕ4:1Ïq¯ÒGz6ÃsX¾Ö@ðá ìœSäÑIùõvÝx ³ªoO‘ÐLêG\ |L_@"ãšœ~Þà†Jc†KØá×›­è9ô3±°o »iÃùf+GkÕÃ1²ÀìMèÙDNóð ~zØia¼­œåhtž·Tzø%­ÜlÓðiY໺üÓ–Ø&ô¯†p&8¿™ÎqަÑúL§Ôð‚vËQ£±l½uú™Njé„.Öf6É@ò$Œ6 dÐcN]üë Yä"Imíú5î&|äƒìe,R:ÎÒÔåK뇗³Ñy’ÈígQt5Ì »#‹4œçQ[Aº{Q¿DJ ïéÈqf“H €Hõ‹Âîe—Ô<\ÕÎpªÇq§27ma|¥¦É#%¶‰[Û4IJ‘5žG*Iìà ßå=Ù«K̃;K¤ç’Ï"ýôÎ’ž/6Ò @Öq#9Œ³rø~õê·—™‘³ÈÕšÔŠ›A—d5ö8¶Ô@ã4oä<6oCÿú¿…/‡P(3ZãÿüÝEbZ§ã0 .TOŠJt_e [«àÃøË€*!ºU!Q’÷qÝybˆR¯ª’~õU …úËf©xºñnœf©P±c¿È)i‘„•–¨†2Û½*"q̹ôGœ”‘ð % ,ý(ª¤#a‰DG¢&8­½Uù œfØÌ>N¾pÇEÖÏ”¥ Óh³Ü7äH\ ÑÏ\PUyŽ„°›eÜWõ´óaN{‹bd‘I]®¤ Š j-l~U¿~É­TVŠÚ‚~!Œx×>Ïj];‡µÇˆ ®Íɨì}œºôT<ëWDJèN5 ÚA;Žé-î¤p£苃£{Ëì‰T}A7`+Ý„;=|¶´Õ¿s{²4êTgðI#W|–Eg¦«&ºÔNºÕ¥{¥œ§sÖ¬¹ôä¢5æa…žRœÌ˜mºô•ï:>Ä]'‘®ˆ¡ ë,DÂIYtk/]í¡!¬S;D±E[çnØBÜqÖ»ä=g TÔ§Œt’±¶oC£På©s ‚tõ"p{ý𫳶*©%š‚‡Uá½c&¹õÔlTS^Ij¢¹qL†9ëµU°ÃÜ—cl~UE¨‘ã`½2fHeÖß †‰N¼«Z؉@0ÐýÑÐÐøŽjE'upCªª<^`ëÐFÍ·‹yæ]ð&ºAØ#Á÷  ´Â`à_†ÿBÆA5Ò€Èû䨅ŒÃ?ss•ºÑsÙî¨zÕºÛ+÷â`T`øïV JW!`›@x3ƒÿàWÀTÖ¶ 0µGñ¢)§¨ñÁSP\<ÚcF¯€|[Xoq¶ÑÀyŒ³E ªø'DÍþŽ}àFÒ27‰_çÆ]aG0¬Äõ˜„m;Hìÿ "Žôí:NiŸ__ñïÂD`C^–7HDðõ¼¥ ¼(ï/ëû“ÞÃóòð¼>|N»O¿ÞÖו^0% 0vf½¿¨-é ŒœÂä÷zCþÒ›ñ«úð%£æbr8¥Câ:T"ÃçŸi|ôOh·ÁQÉÛ•ÿ„¾TÄ'…sŽ—°M½W^×…>{^˜í~ýnßìïõÞÿX’} ctr¸ÐŒô†½¯ëX>|×c—fŠðl‹ô`%:{ ‰ Ä¿,ß½ç4}»¹Žx/—€jÇÙ°÷†YÄw?ô˜”Pï}5_”‡§tüZî&sm¹Ð<ÅdüSóü?Ö<€&þ©y>ŠæyðTÁ¨¨ŠL”« Nr£ºi%À3š„S—ñª„«¤‰ ±½Zø³—Øó^0ñ¢:ïg1Õƒ|ü¨¶üýÇ|â  }[; ¾ÂH aÙ&¬Ý ¶ÓÉËÃ Šµ JИ5•|¨ŒŽ‹³ˆ˜®‚ÉòõojçÜ©_Ò+‡Ï¤êûdôÒýw±º±4’ïJÐ:FñÐ}n:€¼ïÌ.¡;J¬Ø¯iâ¹ÄŸøGPyCýtÒà¤ú3Ù¯Åe›hàˆ‹º†ÄF²dJ°%óâcK5¬¹ö9XVóÏjŸ$’ézsUZEëîÀ‘ò¢ÁÆK×áÙ"ÿ—CN„5?`J]“lÜ%ÏÁ¿•ôÐ2þC…óÒÕ ‘„IJà_,ÒÁkN ÉšvýÖ¢TV„¿ï¨-ëà°?x×­Y¿œŸ­úc 9û®I0u(ü?'Á€Í.Ž{?‚öv5Ë+§ÊÊdlâÝ…¬Ù“ˆá1#i0ª6%ñÙ¥C_û®Ñ­ÈŸódJ¤Ozš cSÛ"µ„ê‰g ~b®äµp{mŒÃœR¶î$^‰2¿vÒ•8X8º› #ÒŠô4>Ä¡;Ñ °4J6:pXùwºjœ„ xÏè¨.HŽ˜¬gAW#ïb#hª††ÈºñµÈó›$YóXÃVd`@  âšœ aàÙeôhMD6ýg=¹ ™Ý&Ç‚HÏÛ*š¡Á6Ý,ñó8šËù.HnKx…AM¬WfÆ~èFø†(p²lÎS(õ-k&‘p¾¹KÆÎÜÏâò»4´0Ã÷³{ýÄHÁW[Iä&BÆâ©°(ÀëQN°ŸŸ—B€‡8º­'ýíi„¬ß+A¨A¿ó#a2ž` $4­¸×Íy߉eÓ­ å“í˜4Ð $8a”‚UuM±šÂH”#& «Q£«¾'À,í´ŽÆ¡ƒU®aüÀF–‹ÂZ·1“týÒl#›]FþyO J!ÏÓ"5m»î çɾ(q+òÉÝiC1Ïz!‚×tbyN÷n4æä?}Ø"?ýwÿØ„>ÈúVîÒÓ8…]U3‰¦:¬§uÔÇÜ }‚Ï#@6 ÂßàÍ…b.ž¼·€ª_•†?l¦ÑO`SX¬;›0ã}DÛ)‹¨3ô®1Ǧ86÷ëQ¥F—|,çgŒ‡a—è>^´p¬üŒ¹ºïÐö$ék@Á²Åên ¿0â£bmO­î&µ†Gñ}SÞ³Z;¼ãI¶ EPĤë\ 4Óz·ºŽ£/®Èb \˜L³mø"Û)À¨X-×”<¬¼ÄõöA•]Ö •[HkÖ!H®Z’XmÙ¼ÉåtÈ˳¬|Á;5/V¨2š/DïÌsÞl—º¬ÈH¤áÈ>†)Ås¸`bÁ£ ¦À©NL9»mp6_'À¼TÅê…¹ @¤Œ ¤Æƒ9¥f¼8„u–a–ìoFša€ó§>.nù§¢EäÖô.îF0 wp&ôÚÀ—Ê'¬£§=΢{€Ñ¦€bM†!Uy7p†‰gžjŒFáüžå£[h~R ³Áv, ó®ãoó×[pTñLÖPuS…é.°‘#»Ãã¥2ŠèÔt»è+ ï…_$l†Ð›XBo–Þ„MéÇ;¤2!#ùŒkäXã,e±¹Zº¬Žîâà~\~%úA¦@R>aÜŒ‡hÛ^´±0 5˜æ.2aœ(¨ÖBêë';fãúšð,®}ö¬ˆ“/í6Xø¾ñŠç ’òÄœ$0Ž3Å/ª¢§'žòÎ’¡‰IØëfáÀMh<Òz[JDÈqWJÞQaÝñ±\V8ã(·ÇÞ´V)'W›RÅ¿–ÌÜjÄu þQe¥ç-^+sšño©ð0W ¬“ g€x„ëÏ›j–aèÝqøÜ8 «)2Flˆ™â|°oòAVíŠJ®N=ùèëGu&=–P‡¤XsKÏRS”QÎŒ&)†¤x4OQÙUÓµ;<OŠPpÌÏ< ŸÜoÅgåd+Ò†8›C-äì̪°¤3³á˜?ÏØ$öýÆh¬Qð<³½p“RrêIb>`)w¸ÆiÚTs³ìLÿ@ÔhnV,ExEI:4"…Êíï7å}>T!åJN¶›Ô-9û%ˆAmGB77qMqÜ’ío,ížS49×—ŠAˆš¯Æˆä‘êC~ˆ6µ"‘Ô-±7(jÜ€xÏ@ÿ {J¶ºe¬‡îÂÛ„¾ºÙHõJôð@?W‰Aâ½Å:&R¡ùâ0íŽC)=Õœ¯:ã(‘N=9#GÿWÂ7õܶ»v¤óˆó˜‰bµîýžQLØ<¿ wę̖,¾3Arè²N©ÜÁÀœ’á`]×ß9k° Ų⠚kk.ãÀ¼âR\¯â2Z._f%‚V‰þü‹hÏÁÜPSk#½B©î}£¬« *À–¡ó®÷EÖ”×qwº§,G wÄ:Að‚ãã«%')[‚b¿ÅµG-;Á˜.tä"Mí&^ ÆLX,Õ"oyߦõj&xòýy"±e`ÿC=þÕ½î£(öó¸ßÖ,OáÝîàªs^78 Œ¨¨­£\Õ‚&–ÆÝüJcý9C½Ðãó X‘”š™ðv¨ ’ž†ïž³í0ìã¶%ôhà@‚eØf=ñH¥öy±ì¼e)yëiUròw¹ÇP£”Ëûê5HëDÝšÔâÆRÎÕœbEŸ¼,t1-‡d9«Ë XgÇTDJÛ™%&4x|tðÍÁO‡àÙpð™?”ÚÁ†€%³ÃóÐ'çŸëÝ:ò ?¶ÚŸ3øˆ8×_ÎÏÌÒ)ÓãËf}‚À•ÐìLÐ+  ÓÖXRã§±« Û.Íy~s[~Rê'X:^go¾ô´ªõøÉ}æRñÀ›s—šµú4$†þ¯'² •ˆb˜äö‰¨\O¼«¢AyRý‹äÜÄ*H´µLç€X·zH…E{ðtQ hqðžàb¡^˜ ɘ© ÁN/’¢ Œ`'±!ýÊaR`ˆUù‡\«°„^PabnŒÀ‹ìÆ)G|×|瘊VO¶ŽI¸e8¨©Ï³~›ÔZÍÍÚM‰7¸É"=-øäüÞ‰€¶|yãOž![“õ%¡öÞyÞ¥) i­oÉîáÕâÁóŠãòšHÃñ†«Pª üGjð(ç }ÛêqjïMfá4×òº*3÷ë´ø=A$þ²Ìò.2f$¤E„zœµa`“õ³t~XI^@®ªvfp7¥îV1ZÎG⋵”U>/Ù{¶º¾tÒEhbÖÍ“è®û:V§½¦rjܾrcµQ¬1N."7Wö(Ú¸Æ]ÃÓºò©Ãz%á^‰ÛyÖ‘*£þH"$·(·O=—èÞû1ò)˜ñˆQ¤CWmuÀªûsM€e‹+ú•ͦ¶g_«·ä k'öØ¿h-†S:¼§Mïpdâ‡Í„¥ÅÝ|Û‚ƒÓAÝ4>.SÊÖ±åÅp­&GãÉ:{8j×¥ÆxFΊ»8+‘ût¿VãòX6sO:ã ëç&cý6ÑSwÏí²TVÿX?*³È5t½D\"u¾’ —»ØÝeØñ ‹Åô/f±nqß¿Œ!uùŒz-¹Zh¥y–«a{9´%…X6¦1bŸUÔ»+ž¿«Âü·I#¤ñ¡p—^à@‚¯•×c¥—’¡6ÊøT5£&¬­óÔo¨%aØ£eº½Ñ/Ÿ(8ŽÄJžtY¦Ö­cO J=²Ì$ªãä—íª•u×™iì¦HìÜ49êR³’¦àK® ÆLòg2¹&¹´ýoìs*|’ÉTdÇY›P¤q\ûè¥mbxxKžd”y?⥤÷“×}÷Õ<Ñ4ƒ´ªÇ>ûÅëuœ•Ì8IY£Û‰ÙãR1 NV‰Nšž¤‰{ü¿‚ ¼Dö¦pÏ+ô‘æè4æNÁ/h@`Õ]å­™žñåp fDü Ѿoþ458mendstream endobj 738 0 obj 5807 endobj 742 0 obj <> stream xœí\YoÇÎ3aä7ì›gíhúî~H_q”8>d¶Mʤ^â!‰ÿ>U}VÏôpy­h†aqw¦§»ºë«»fß,†ž-ü/þÝ=Úzö‚ ±Ø?ß_Âÿû[o¶˜²ˆvŸnã0‹—z78¶Øþe+LÀ†/´•=ã‹í£­uf©º~É{cŒè˜ÿ²b\=—Ý÷˕꥔Nu_ÀUø¨ ï¾Z®x÷—¥ÀG´éVðI.x÷Ùr-g²û?rεî¾^òn{ +ÂÞ}ßžã\Ö:˜o’©?‡Ç¸êÝKaz¿@˜Ö8Ç !€$ÁºKÁ{60N×úç’õÎYé`ÅüPXαÁÐå„´i†Ùoÿͬ¥'$õƒ…CÛÞƒƒ²p6pX8r%¹ë­\¬ÄÐæ\@¶õ ¬n Ði» 8k5gÝA9ÍWpß±^IÕ}T®&6àm;ôJñî²Ü>Çù•²F œç9Õ=ÞìJqªcz5=ÿn [ápŠá²;[®ä0ô&ú8QDxð9 ´VIÝý€ÏèÁá¡|±½õÝÖ›…½öH[Á°—ZöÚ.´ÿ~?}¾õìù?g—¯¶žý°`[ÏþŠÿ|úígðçùç‹?l}ñ|ñÝ<ªk%TsézD¶½ À~hÿÂÔ<¨ÜàAŽÐá`-ïv€ñÇ68ëÙŒ àã "Ïá­–þñ2o¦ê$Ì*£™€LšŸ}kØ‘éþ‡bYdàÀº«å ¤— ãtd/7†h˜îö†8<˜!¤â NÉ´a´a£ÄÔàÊjHí^܇ ÛJè‡ðëaž4,Nª9L“êÞ®+ÊËSi)/yL§ìbÅ<=ð y#˜Z6ˆS­l­º`£Ã`£zðãNõ )r@E5æy"\7—Šª DTQPy 5^ÒI&Å%˜ò`³eo-ï{M0>…@j® ç`,ó¸ÂŽqÏ®æÈŒ3D†3€Œ †H QK lWšNŽ#‰°Ÿ,ryäaùÞt»™Ð%QŠ»K€LïxÒÉ—¥/E~PWL†RŒ2ŸÈ¨µT02°Ë—EVÈÀ,¼’ =(Ó§ìÞ.•ìA~,ÙRzIGÇe‹´y¼Çýz¼›Ã¶“iu½‰Q„Dmÿ&À‹kÕeƒáPªŽ¾Lp¼ä€9 r@ȘjI„ÆpÏ V!(íN4¤=š>í` þÐò~A>¾Î"yRéZ²xS0²V ÞE™³xîŠ9(ûtto#äŸ{ s«ÊÇ6v|çÉü€ýMsmý #$ o–ð)6ýFúÇ FI-ު̉ƶó ;ãTÇÝÍ<Åu½@à¹ÔÚ¿Àÿ–ºw@Ù¬LåHØ1‹îÖ³^€*ÌJãu\KÒaÄeËõBí*¹×®•ÆÅk TˆÌD–&¡ ¦¡{›ãÒ´Ê% M|Î+Â1IOâQ¢©Æ¯§å ò±2 àYLtN2[T]數ŸF!7"‰Au 'HXL€ Q‚÷§ø<æ=ó%ÝÞ9mêwØ‘mlw#˜›2$‰ªÂ(@È û#“E–Þ_ª"/E´#þñHj{Ð{äb²ôé+þ+±ÕE£§Y F ‡‰ŸTa›"H2ëMø^ ï$Ò™„"Ò½â 75+¡¥BvRðdèXºý!”G 'h)ã< }*i½·vsŸŠ„%J&A( MI€£Gk…÷"êE9ã3yÑÇÌfÙ8Œn¥h{ë~‡äSxüîM¹?^M«Í‰[Ä©mC øŒ¥þú÷Q.Wcû„8¥:>(5 ðöÐÆY”‡ÛêüdTžâ ~¡îç2´r¬AS˜žÁÄë\g ÉË]EÀH_‚S‚f¼)EÜ—y‹ÌöÖ@¶YÉF:Ú ñ~­üëä†P^§uÂÅ —ØéÛ’µ!CäÅ@c|ƒŒób»—³Ù sbô¨,ü&³’ãÉÂ: –÷ÙˆqæÁgɾϒ0O²t>q²y’áôyEòßK0KBè—Kî¡+@-TöƘŒR3D«3‘‡›SD ÁƒÙ¹Ý,Gm Ô @÷Cv}©碇`©÷káÞ‰.´ÑpäbÞ¼¦(ÆKÜIJ™5¢ W±ŠW¶-¦-*à¸Iš(€ÊùøBª1=£ŽÃ1ªÒ¨|ª;®Ëûm^½ðÆ1#Þ ò_·&ùc¯BÚ\eõìÍÜŸ‰‹ˆ¿'ÀÁÜïlŤWÓ†xï=3ªZ‚1 g h …Z˜?†µœµ$0=uƒC¬9õB«(‰9o›pý2Qù4µ A¥„x¢SæÒëÌ'!ŽIQ}ô9 ía’yp{ŽXŠMr8ˆÏ–'˜Ea6‰F–žwáZ¢SIÙ5ÑQšîiº#œpH('RМ¤X¨LÜçÒÚ^TJޏxhàdH,ò¤m9ÆâYŠ&i"Xb®¡†Ç*@,¿0‰ 8cft£ø¼¹•t¬œ«m \§†Ð6ExRšGÁ€„i[›Æqvb asº[‹öpC©.ÅBbåÞ*÷‰AðS‚GWö#óúÐÖÂB…Ý8àI*‡©`‚z+ˆ -Ê(–BEÞÒk Ç[o‹‚Mc¦4ẞdˆHëþƒ_QÙxex]yë& ÿÄQ¼Ÿoìâ?'ùŸ3D˜볇Ò`¡‡wÏ`}>øµÃó¿”aûùâërq7_<Ͻê樔ÜÈ#ý©Ã¥ëå§éø=Ѓà"«îI¾}Z?çÏái®ÔŸÃöò€“Bëe¾øs¹x˜/¾*³<Éß—‘gtdºXNêm¹¸“/–ÙL>qWHá‚Èp`z$w{:Hª×eeš1}¾æZ@š±ù÷:Á”‘CÿÛÜùX€Ýw9’Órñ5ew9’@˜Ú˜Ê’Ç-a"ˆ¾Õêéc^Þ‹NºzE×÷¦T)Ϧ£¦$}¬±±ŠÔr};lœåÑÕ†QñÅS𙑠ÚÎŠà”“$ô´Î§ð~¯\¼ (™¢àUÍû›7ùD´t!é¼µÐNëâe¹X´úOËô1zu`ù¶XqLi â×b(ÊÔéâÛ–˜Ñc™Z“%ž.³¾ž&Á ?ˆÝ)ªí1-P¡ì ¥t œ×ŸÜT[Œ´ÅoÚö¥·SgA‡–$KJ, ý5©¯„Ö4–,ÖTxìwkø»5¼ÞÞ¿[õÖðÙ ¦XGÉ¡¼yÄ8*+w¾ÍÎTˆºr'röK,32›K:!¦[ ®{6\Ó 3y·mZÀœ”¹ ‰3’ºh¬â³rã 8tÚgGóëuCˆÀ|;.ªúšilè‹176àÐÝF‚»Qn–ªrð%רhWz5#qMR«&QgdÒÕ%;šo8ÏÉÃÒŽLŸOnhmïÖ<Õh E^R6Vä–Új„kšékç'…ZXà´K(å9Ï8ƒ aKéNìÁæFö^b*UÀ¡•¢íؤÛÀÁ•‰ 5XÚØÃÍ@šçóu&šKë1?'\9?ëðQ3¯§’À5&»\÷² g/q=² ØËªîòÖºÁUŸàeÊÆµfU¡j]Ú¸IC> stream xœµTËnÛ0¼ë+x¤Œ˜å’”ȽèÃèé+UQM®í¤âرÓÀùûîR%!nÀ©SÔpwg¸CéZhBóÕÜgËìÉ X+η™¯èž]gCDs›-Åó*†‚jQeuÞˆ28FTËì» yÁÿÕ[N zR€Ò²ª9E¾ÈÇVyòu 18”Ïr#?æcPÎÞȪ‹™Ô¨uAž He½ôD§hÅTä×ÜzŠ/½üÀ™Æ˜²äp­tNs•šê%EØR¸¾”^^3uÛÚë’òœ ¡p¥|ÃÅý¬|ßÛêFw0T{Â4¤¼@ù9´A~ËÒº É=p˜Õöàï¶PÖz’a ¦/óK*Õ˯¥!1“4Ó/×ðµGlߣ1@©|)ÆV+ˆµW§’JË9+~3“Öò'?^ò° Â:( ¥Üñó:EoSôŰs3,Æu wV.Sx,‰4÷ò.ë.r•Àm5:ÐEŽz}Õ­´ÿ“s—ÀM¹HàYÞ&pº¯f”„‡Ê¹û‹œv:ÔÓN‡‚xêl Eì~ANk ³Áª¢Ô¦6û¾3 mgs×ÖAËüEV^ðCþïöï»±NàEîún8 4w@zDW œ e<øþÚЮI[k‡¬Í”Ýf“ ¢:ΪÑlÞ¤À›ÖM£cûfüü‹‡isbr´¯ «};ß$pÞ7 ÜûÞ/îyIŸ¼§ÄN-D{h‹;ñ»‡ª6ýpövýn@ß<äßï5_À«Æ·xú¨5£öƒ\›9M nÒIˆ«§9\iReŸèúꨶ:endstream endobj 748 0 obj 635 endobj 752 0 obj <> stream xœ½\Ys·Î3£±¥—ì¦ÌÑà’'r¬”ìØ2ã$•äeÊe‰”mÉG~}ºWƒÙ]R¦ì’´;;4}|}`¾ßÌ“ØÌøú÷éË“O„R›ËOæÍ_àÏåÉ÷'‚nÙ¤ž¾Ü|pF·éœ'k¥Ýœ}s'7Æ©ÍÙË“o?ÜΓ±Úy»}¾;•“”0øö|7OÁÎvÛWéjÛ×;1tØ>ÛÁ5eŒØþ°;UÎN~ëq$¯œ“ö¿gͳëÉy'pvc&­‚ßœ=>9ûã¿·ŸìNŤ‘bû-Î ü,p\X§RÁ(xž´ôA[ > ¯P™¯k£·OwjžTPH;\ôBml¸§@°2JÉf„H2|Û¿ 6Ñ{«6„ív¶ÆÊÇ8ƒ n{U/^â¨bòVlŸÀ´ÆkòHólÒPÂjA|tÞ[Whµ> %a¯8~$ µ ™§6y sˆ<  .3OÏ€XÌ ÷ø­u00š†OBÊ8˜1Þi¸xªl˜Œ6Ûo¼Õôl£'¥4ˆé³rIˆC8êžf=ƒZº‰­à'(«Û—H–µÎêþ¦2Ô«z-1Ï _W»Ÿ`Ëaðë7¸(7i¶ïp³e°°¹ °g §pë<ü§ò.K¡·_&Zá¡OP7ƒùÿ–óÙ°ý;Ž©@Êá~af‘™$AÜpNFqZ‡t"I‰• ûï!j“@+É› ryQì†ÑïÕ1®?#c­Æ&>д«´`Â}˜àýÄ¥Ÿ¦µŸ “¡Í@|²“•ƒU¨Óšì7‰}ë€ 5† O¡JuT n›–¸´çC1ná ¯ã]UÝAS ô4ÏíkVɸéÒr¸íO;EÏ &­éG¸uȇ2›ísV´j £ðPªU‘ɤßǧìöë2í¯x™à¶Å'„P yeOGšÀ®]FYA[ã¬$)‚)$XÙÏw ®jJ…\N`©³”/ŒÎ[)ÀÀz d~¼ hCMdLÑ·ïCè®×X$¥OÁ2 ðjél‘ª½(žEvÙjáÍàŠËÍLËþ”oNbW{*Â$㊟w{ncŸ’œ¡¥Ë¶[äAaµ`Vüs¯²­LFò”è6†IQÕ†i°¡çísøµ3uð³?¡•R"õª:V³ŒSà#EnظUìÙc¿ÆÁLXñ²õxÍÌ’yô ¸±l’W ëÔY\/9^¡qD·!²qÄ¡*‹£ÄçIfø@ü„Ö[qº:³ƒv¦=€9|Ã> £‹»:W¶z¼XšÏcœ»6&ÙOiÀ”HÃØåäkH˜B/íÉÓ£„Æ_W¡ dˆz³6öñ¸é™iøö8?«•&Ó0-ÑÆöª¦PW£ß/xCέ'n±~òEB€®ÜœÑ¸ÁǙٽK\bdÛ;ãs"~³ƒò…H)A¢™/~‹Ï(°‡h`]% '6s ­ØAKa¡Èiˆx õ"Ì{t>é–™çtg·Òì+ÖŒYÑg#8:D¦(A>¢Ì*·×‘4­Œe(˜©à×èö­wDn–¥zñë!ÃøÏ@˜¶ƒoÆhLƒÔyÐêà#"ÇüýÇ¢­ìPR ô½.d$0¢×+é—ntêW½Ïu„A@×PráµS@©á\pŠI˜Â.°fõbâaŠSÜ5mÿAŸ$ÄzL‚Ž˜ø†Àz9pF!0s”¾¯÷‘¨6Y¢ÞP×O¼õ\<_RŒ,5.Ÿ<”¡“Ãg­i·ª~[°Y¿-Làd *ƒÉ&߬@Ô¼¨U""a´˜LÄTq±ö1*š%áŒÜdþ.D¬^‘í>×¹ÍDƒ·0-¡Ò:BÅuŒ”£u>68N.³ƒ  ‚m\‡©[`#‘!L²ÄÍÌÓ*Ì‚GòxË—á‰Í ü›*Øeˆzc•uŽ!t1Í ˆ@ }}Õ‹åÜħ0&D%sriõ­¿¨‚vUýóãï9 °Ã˜ðPT‰â™ÀXYƒ£M(Ã{ì©Ô¬‡ê¸Ø%ÄÔN45¾º¢¸¤ã‚G¥ÒGïRµu¿¤ç…̰R‹*ûp5ÇçV÷y‘%Bó$it£¸Ù® ôƒ#t €Î‚-ÃL‚ݦyR°Häy–­zw6ˆji“ç¦`5ûî„DŠ–Ï†Wé‰ÀÐDEmF\´ù°±‚s@œ¢° QðzóQ‰MJ¸ÎHïP˸£n<îWÇú‹Ñªæ_T ‘7ܘåïM’èª>Ó+~dTëðj¨\Øu¯*D›âÜ›“*REŒËÔd¶ ]vp=|"i‹3ô‘ñQØ, 0XÜÄ/ bʘ=ß5~îÕ@¡»¼×áì(ÏèÎ1SÜ U/ 5‡ðö&æY%Š«-˜õãxqÎsA,‚y®û­ç¸n OµL‰³®!>æ¾ÒÖdžxaDf‘mˆ÷KÑ š±ò0™rvuBèy1±ý4CQ6CÑÉV«Z=Xƒv 2˜Ë¡]µfîÄ•ó¡~aiœè‡Ò×Íâ„9ÖêÂìf›1³Ü>Æ (&¬)Œ+˜%á´ïºt5(ÏËý¼“€U¤kl$‚Dæ ŽÐm DSØ5-L“Õ'ªÿ‰n!q¤ÅƒÏ«xÖø€!&d6‰Ä µ~¥QÛnȦʠtÌ”Î5¬xù˜¤¤¼ü1 o$Ï#…o1-2¼§J!fÿ1ÖM¹óÎ$¤yÞÚÚïMð_$¶E !$zS*€Ï“m]Œäþ*A{#Ç+åÙ¿ ͇êxÕm¶ÖEs¢ø”ëHܪ ‚¥ÆiD¿‰|¹¥ÚâX·T[ž`KüB‰õwd[ÖgÇ„9)4¸#—Úr}Ƽ¨B\ôY/^ ¶×ß1÷q?ª|ð+€ˆùŸ…çåùŒ|ïÞ¸" c–+TUc¬a iöT®ž²Àú+ó¦‹òa§ÿ,'´GÿeŒCÇ¥$NèXû¬,ýºDEeê˜Ï¢s3zEclŠ^,“õ[B¢´!MR¬<Ö F7÷]kR%®´GM&¹ï…à5ž î6À{²GGŽyUrñÓDôÈD–þÊ7ÁBb©Ö‚çH¥Úƒ°Ž/‚°¼±4þ%QJžËˆ5M¿¾m¶ ©¿i¶ŒnÝ)ú:Æ…Óü©€‘œ„ Y¶Çeõâ–×LІi‘eŽÓ™â;{5Ì-C;EZ“CT~Ynîcœ}:ùT±–è‡IæŠ"SÖbåë82.9'ãb*÷[c~dËÆ5ƒlóß †i%qX°ë¤œ•YápƬ›Üo˜{S¶szG±ý®Ú• Ö’ÑKàÔƒa‡i±ÐÄJZu ™Iã)©–¬4šÞ 'RcéÏñÅŽd§[â¯ø ¶†ÙšLZ[wØÄçiIÚ¦\†Y¾Š[¦; M ó7Ó_Å¢Q“‘â—þ–TÄQ{ãÔ=ϱí9«Àñ_à™6}X?. ¥Ê²Æ\?í€ëΦ=*ó¦WÇ®ñO©Å Äãù™˜ Ñ \Œ†zñƒ]Î@²Ÿ6Fž|qòýF)*‘ÎØ¿VÂîø$ê±—öƒG'}ºyýÛg'þ±'>Á¿>øüCøçÑG›ß<|´ùbO‡mS*̶”ÖI˜Lš¶ÿæ2¶'Êa/>ƒ¾¬êÊ”èox»5tSa&*„#oÚ±Lz>¬Ixрſ5ˤ·ÓMwÎ2 Sfݰ¬¢Ø÷wr¼Â†'Ò¿ž(oÑ Ü=O”qžÊ“¯ OØšx\ÈšÛXpEI Ú­¢„¦"Ë¿V’‘ íƒk·æ„ªîpÍ@®¥¸Y6%UšòËýtù,J].³¡­¦tÖ iXXƒ\Ò¡¤©g±ö¦ät_âEݯ“ÄÏ“-}׋ŒDëR®%ÅEgѬ[ÆÄòÎõ"%Ça‘é1æ—µjuo_×'ï8J-ˆ­V4ÇÒX Ž­Ó°ûxÜVh)‘4|ÖÔu¯%¯¯,á¦gßf§oìm˜Rcã©ð{OãY‚ãÒS01¥§V²ìy$ž²¢GìÊÁÖjC=ïš¼Ü0jÍ•inÙ³¦Åž¢)ˆÂûÅ%,|ëÚ)§Q‚ªë~E±”¼ç;ñmžJâG¶TÇš¡a¦¬q u­£zRb¥¦ÒÜ›‹ëL é¬:mËEá0X›)[uS¹+rYàh£íædßöŸ8¨.ò2Ä#áo£óQ7Ö¬:éÜex+…ž*üU¦Ëö9„ ¨d–ÃCå^§; Ä^¬›kSÛƒh¨I¾½±­% ДŠX–Æì”GRâ]ë[OÍb¡ £xÿDj‚ú-zá˜Å?ËšR»–%샪#ßt!•…7˾èLÒŸS{ƒò\Yøq†,UF Œj예ï#XUăì=²Ÿ£gon²“¥›™òÌçY®ò¹y;#eÁçý†XÊZWøQ¥îl?ó*¹OX{ÀŠjŒ>j|¶PJQUdvOxuMÿQS½m¡eâ^ëh˜Wa½G¥¨¾D+ÖÃØ6ãH\aÖ½=‡Àéç^†„ΆšT´·ÉÐyBv¿¦j‡þ¼'aÅjìK4òÆ!e<6Ûžåvžø:ö,·ó”Û_6¤ãG =IˆyÝ)âÂë©ìWf.²S«6µwëž|7cìú “¥7jO ™Â/çèhÅ¢Ck6ˆq†XY¯S— Yè:@»wigµh]kÜ[Õº¬¢îý¡¸àVñªóm[–bŸ´jËŽÀ¬žsÍ©òù%kr5: Ê’…ôú©† Ó¾…‚E Ù½ŒáPZaýˆP§ñ˳^øËÊ›2=ÖŒÍPlÙ‰¯¥ˆQ1e—lƒƒ˜ð³ñFo¸è߯0¾Ìò=ìåfâ¸ÒÖߨÑfwšTÍà謸Ýɺ8Uà‰¾Áhvfß½0㻚ZtêÔjúÏË8£7ÑÀê“_"~µ˜îxû+{(L§ýö?Û¢GU¸…±¬ÿ可 °&jȱŠ;¬;‰­ >™ƒ½µæC%ÐFß«™”»ëÝÑæpMúŽgÇv©tì2ê?;”4 þwtT-#¾­ëÇðs‹lˆ™»3It'½M¥´Á³4òg¥˜†õY:’ñ¸¾‚âª>~TQ¬,« ˆÝö‹&á6ÿµ\ô9ެ  L3 Í_ó™mìMe]ÿ5ãx )׎úå\,pX.&3ß¾MQ!Gãi…hÜï°/Ã#ª×æ®Û2ÈHk“ûó2´WªÞ]{œ¢¶µ»f¾.QÙ¨QÕ×Q‹ÛSã}€½·nq3ÂËÕ•7ØÜt×+×`g]V>nÃB¨p°ï®)Å^](küâäÿíkR+endstream endobj 753 0 obj 5140 endobj 759 0 obj <> stream xœí]ës7rÏgFÄ~ÜuyGx“T¥ê|ç³uuNü +îRW4IKŠ-‘¥Ó9}º¯Æ f$—U©8©³–³ Ñènôãì/+1È•ÀÿOÿ^¾9{þ­ÔzõòîL¬¾€ÿ½<ûåLR“UúçòÍê³sjàÑ0ŠQ®Î<‹È•W+Ì ÕêüÍÙ_ÖãÆ®ÅÆþ×ùŸð• šW¼´ƒ·Î¯ åï7[=x?ŽrýåFã̸þÝF­¿Þlå`Œõj}^Û|ŸjÖßÂS9B·~`¸¾Qjïè6ð:¿‰ýÁ›bð¢p4Ô·­€tiúÔ°Nâ÷›â‹†?áU!õú‹ |!­©7)Ôú?°µRʹõ÷h&,çeákÖï¿Cg_`g~PcîBÈ….Î+±QkI}°I~·ÙZø¨¼L«Ð.Ü6-ÃV  {ãj|³pÎ8Ë{ª?Û˜†².mg&ôùùÙ7g¿¬4¼B¢±5Œ«´DX9«Ãà Üg/Ξ¿øjõþ݇ë³çÿ¹’gÏ¿Äÿ|öõïáŸXýÓÙç/Vß+†R¹ÁÐ8ƒ‰’KÔp1­ V0€øŒº0&†J*öòö¯øú—*¬?DæšÑ®ßwBp°,¯a¼÷zýsþPžü0ÖB›õ5tbü€|½©}‹‹]éädû®öÎò¾9 ´à'L÷ÞWЙÂI?WB !ˆ”tëË È–±Î¯_Õ†HÁ»ÍÕŒ‘ ËBiœ˜×hÎÏ ±¶š;öõMœpr}Uû®/½­o6¶é^tÀ C—>fSò2¤)ÖÔ9Éõ³úýõ…O Ò–,K}å*1Yë¿o¬¼ƒ%ÄÉÖ&xWH8(ò¿Å®·Ú©A…ÕLŽŠ0©yÅç½U& ÖŽë—-{qòi–ç¶¾S䄱ê%öã‡1¸õʤµ@öÂûðËh©i6æ{è¾’0õá#µ÷¼6b\z0¢=™¾‰ÂšÛI 8imXÿ·Ê±5ÿyá=œp¦x†ÍãC Âúqƒ†\Øøµ8—YÆBàeìÈZÉdøb"où9®Ì„S¯I‚T€U6Y„ê lÄwÐN >W­Œ³æ×•®nóH"ÌR¦a›©ú<ðä'ìì0êcµÿ¯‹ÇÎ-P+7‚88.Ø“@/K }íçmý¾ˆ g½#½?ô3ë iKâãVêÁ:‘æK°¢Ø  ó@:ìg$FµÝ¬ÿº.B÷Ï+&P¥ñø ÿG¦XÚAfš™y…ý möVm‚'c¬‚$Ômž×fÔ A¾¿6(;¸6ÁÁ^¡ÓÚÁ.¢Ù¬{¤Ï®ß ::çaböfÛ±VF÷µêÒ‚ ¸{’8êFàh~6ç+Žù ŽŽ'¾2 cscð§ Ø1Øÿ¸ÿõ1ÚYàƒ/.ÜMœÚîdc‚V\ÎÞVq¹ÌƵ T=f+°-S¢Oq∠Üè×>jÓEÄx‹ÞÖ –˜|‘“ù ÆÃºG .9!eÖ8ÃÛ²¿ýŠ®—]' –‘\šS“m…Aådl=’ŒáJ$ ‚dŒ®vÀŽ! SZ4‹W(i蕽5–Ua—L1:t,ð¹u:&" Žƒ‹A\bvàºì I·ÐE»AÏ‹ÜÌ¿£[AÖ†Ë3Æ’Ë|òYXðfB»-Ìd§eÇ «ŒªŠ;Q5¥È…`UÃ…-  º¿5â÷Æ‘‹Š3qº±ùÔAw05[)´©ÕY`4“úž¯‘¦ LÏãù„ùkÖõ¢Þ¯Ÿolßk.ý]w=ò­ñàTQ’ùÍ=ÛÊft<æ0ÙðƒU±vïãÁâbS(Êú¼ñ:&Ø7ªõ'®šüo íZ¢Ù%!4 |/÷žˆùi®uvÿpþ8óâQÊÛ¦.P„6SoÜ:oëKÌéÍ*Ÿ–Z!1 ^¾_MHÛ÷@ºèu| ­dÚpð”‰ïÌ©o¥g‡S¯]tê9­4}pzN¢>q&®ñFÈ¡ÀÀµªØå F|`,…Ìb|[å!u"ÍÌ[㚪&KuÕ‰ÿžu=˜ò5F•`½ 8J{ˆÃƶ>Á’ë©/ÚÆP0÷;³¥Ýw?ÔÝ•­úm}šæàŠaCYgKÀ‚­y¨Èƒ& qM!ÄÝ­’ùã½F 5=Fà J9£þ–Aogr™wµ>µÕ‡.üà<µEE $Z˜«ÈþîòVÉ8Û‹ðqñ^ÆØ¶êå.ŽŠrF½Åh¸M»@g(éDÏp ÈEú¬%9ÀèY«½£')íxùU¬ó"´›Rz%Y4l}Ök× *£XðGÐÄö¢e¶+•¾+±yÙÁ¥`N.µ;ɪ6Ù¦åhw®ªA]¥«‰ ¶s„’®AwVœWr¨£ºK÷¬›òy=×2ܰU4Ql?kl)w78¬˜¼Üa~DÐ.²¬z½¤ÌîÔãUòílÔÔ<ü·7Wf(jOÿ ß M&ƒ¿c´!7€m¤KiÐâØz>X¥0g€y*+ß‚_Ëz~¿†”;ÿä/ë€5o@µ RHÌÃJN \µùy«Ã¨hkh†0kwß›ó€>Ò6–?¾¦¾pqßÖ‡èIzC¦û|&K‚ÿQ× }%î+ØR:\ýü:ò˃øY,9á*K`Îlt|ç=<´0Ž.)ƒCwO ( &×þ¬äA'Ø¥q}#{äFw‹SÒ#ZʦFH+“äÆšÐ7–Ñ€e­ÝJŽ¢±¼ŸùN‡æ’’v$7Ñ]þ°(UeaëGßâáöM(%$5¸6R-—4ýÀìL;³èUºì×hï(ù²¯»]®>²`¶KÇ‘Ñ8å‰nd#|ü#K½׊Õ@Ï“CMòÊ—ƒ/žöã)çB\ãùÛÆ˜‡ÅŸâÀÆŽåEþ›/T/tX’³±ˆù}ÆðS­v”·dE[ý¶IóBòiÒ|"g·Ý}üb3I(C i¿m1gcöÎÜ¥¿æNŠVh)÷tŠx%VØjr£ˆ~7Ãq˘Ð-ŠžŒáèCýl-ÔÊ–ÝÍ_j$yz=BÆMÀš¸!tûº"°Š\«¼_Ey‡Å.®úç‘# [³¬…MÚ(–" >™–‰P¢Á}Ãmä˜Zg©¨HÍÓ³Ø{"1 e,Hùîš„s­ß ¢gFø„˜k\ÕÙ–ÔúÄeœg=]b 6'hÍbc*ÜLÒª‰øeVLä&ÁZ4B˜ËÎ"ž äƒc¹˜üö$'صuŽÇC µyÐ]ìÀ-‹IѶ*,&ÞŒQ}y–‡Ž°˜|Ï„õÓ0xºÜX÷ ž]6V‹ƒáÇÓ¤Z3½|æx©dÀ.¬åµÆ(PX‚ÁÛÒ‚`Ô(i·ž‚`”Ç ­K[y ‚¡Ý,ìB~$Êç”w«Ur×8&šûac”U§>¶Ø Érþ^à˜ÓSJà˜–ÒãÐ1''1¢cZÇä#‹ÿŸ2J{RèRÈà½@"< szB#@†ú@æ2'_¸éHØq™Ó2œÐÿS™ÎqÒGÈhW ±ã%0eãIËhÒá-lJÑ©Áûàc”x:Q~:ùF­¥Øa®À_ôh+M"œ“s;ªµˆ ìAcâ1’@c¢°k åèžD`¦Q=Ø>‘J!’¹U©ûcœ"ÐÑéiwÖ54÷JƉ°;ì6HýÜn·š¶tEÁ$¨Æ£*nšð< ƒ^d ÔÉr0x>ÕV‡%|LŽÛj ð× VD,ÛâÜŽCÇ€Xàþ­d‘½!© ªð+wp Þàø$„ªJ0Bï±2jóɉ¶µ™Ñ¼O.7Ol©&%»”#y(.†vBÙÃŤo)dRžË,2S²eO̬¬WǤ»¨ñÈûÁؘ{Ãbê+w ó®4>-,¦Â-*šâ7XÌo°˜£a1 ¦ÆÆL®œmà&1 ïîLÀcuÔtn¾y¤¥4¾Kâ\ët‹õDL×㽪g÷Zž%Œ²sÁ–r–9U¼hòB™ð>æ×}˜Ü›&ÔnIš.ÄyÙb~º÷\¶—J¼¬U¸ÅK%â‚™#.€>¤”%mB×rv`ŸMYÆ^ÚyolŠ®¤0î´e º4Zv)ð±Iç¹OÁÖé§â%ŒËgrÏ c ò‹É>¿„ôªWlâåæ0hù˜ÈÜ/ þ[^ÞàÎSD>^a{Vƒ]FæÍ®&‹¸2H>pwwSCfe{k/øÕsr@ðólÿèýÜCW§ ›nôÎ?‚w¬s6Ö›s߃2x„Äö ‡»òó/ìi¹ÿ°rÃÅ;?uÌÄüÓ†GÆéä¾§¢o“JŒì¾üåKËÙ/fkªCÔôz§=»“VxQÒôÖd«“)‘7Žf9“Wö v"rJßœý/Õ˜Åiendstream endobj 760 0 obj 5793 endobj 764 0 obj <> stream xœí]ëÇqÏçƒþˆ…?í¼áô»Û@X²"3°­‡AO¤ˆ<Š¥ø¿OUõ«z¦gvv—KÃA èn93;]Ý]_½ú~ØƒØø_úýôÕÍÃo„R»çïnÆÝðÿó›n=²K¿ž¾Ú}úóxic»ÇÏnâ ÄÎÉõzr÷øÕÍîýÁ쇃œsj/è·Î‡AŽ~ÿÅA Ní÷ß”¼iÿåáV RJk÷ÿ~û¯·bÐZÛý#üä}fÿ¸ñ<§Ü ½ß?>ÀxrÔrÿk¸ñéAJ c÷¿Ão„àuØOk9h%óPB¶Cå'ãEçG bt4âç‘äþñpkà£þ¿ÿ­˜çK¡F«ñøV À¤aâñI%òVk3X¿»U#®Dˆßx4ì_ãa €4µ†ÿ~‘.ªý;¤s…Øÿÿù|?ž”/?Çßá¿–‡éÚ[üq?Þã7‡[í,Üû‡0’Ç‹ßOWÇ[úz¼øc½ø´\ü¾\ÄÙJøŒsºj0v”qrÙã˜ílâ·ßµ7^&ò͆Q˜ý/Ëœž%ª+)iN`&Áù/ÊíוR¶œu&oëýûrñ}½ø¦7ç¿•‹õöwõ6âñòþ_ê’£é—|)ØýtñIï"#´²Ä_ùcâO#®S "´3ÒƒLwFT—…n_âço·#ˆÅèF SÖ Âùý+¤ÃZg5¬¢òûŸPÌ@èiY@~c$­@„­$NA Ò Íx_j¸`S n °^dp~ø i#@ú€`±¿ã_'¤ÜR}?JïK¥ñKð›”À·é£G…©%ª£¨sJM©S¨+ÔáƒoêÇYß½.zù g9 ÍÆy¯ø¶~ïeþÙ 6ÉHK²WçÔ×µSť҆ݾ§·Næ®ÇA*Gs{vÀíW°D¦lö›ºñE yœˆŒ®ý Eœ ›p&AEÂßÔ;õEq6Áhz„m¾ëe¹Y?!ÅFÀpnöŒæ@²·_‡Œ+3’8Ü*!©'jé(ë)Y1ze½WqxBávæýª·Q9Á `‚ö¿Kò¸b`<™¸whWŒqV¢m¤Õ;Ôr£É #¶‘½ÉRÃÀfƒãüù¤+þs6+ä¢gáT€C”œðÄ¥ÚxöèÓò©pí'S¹Å»¨·äHܾ$‚J ‚ðDêÓ}e€ÄG ¤G+œ?±4ítfiTòÒ´WÕiÆ=8Ô3%ˆ¿œì"ì—Šì’WF‡9o*I¼9[åQdÖ3cQpQ«Ë¸˜&E\l² ¿'1¾•!0ÙŸë[$Íö8Ó’^´Qß¶÷áKÒôýFçÈ€‹¡7;R'/Ö·2 ¨“›ômf©!éXï?ÂÈvÒ1.»;Ðòk£ÀÎ=ÀžøöÑ÷ Œ.œ¬Ïüªð%1oü†ÈÜ›1®ORÎ:|îóÇ7_ßü°Sj°„ÄáÝ~§¼Kûñš~¾ÿôÑÍÃG¿ßýøöýw7ÿ¼7‹?>ýê3øõè7»ºùüÑîëeÔ?Á õÀAGØÏAÂïaý­j™Je ìÐG ä+ÀZrJ£b@ÖÚ¥•ऀü"^Í*ánnP˜˜—KU‡0ÍußZÇÆ¤‘@½Åt) JŠSm×’ à5Âà¯B•Y]¬ 7AL/ôŽ˜åǧQ:,ZË]¬9ã‚m[d Ð#:FÆ ôú®Ç@h_0¹Ä»Ê,3¯„9£·w}Jø†Ò_·•ùº¿Ãå7™oQíuM5£LWuÍMe›êG o Kä4—™¹hì ঈ=жÓàSœò#|r60·1„3$i])—"‚Å¢ƒÒIžÈ*I:s†½Q„…ö_[º1ñÄ…eâ‰P—¡5©ü¦!Cb/ÅôÄÖc°#z¼c\}M µY¼‹A$ñi‘ë8÷Ö·È¡§>¦×pŒ¸`Ë`N7¨×ÐÇ6ûïÙæK)0+P$ÐfaÙ?rYQè«“qŒ¢o?‰Èõ.Z^ñ2pÖÉø2Í 2ekó¾Î4ck˜íÝ”¡«¡IL|WëA‚­‚N®™ÑzõÀ0¨¢Ó4ÌšfªÀáê¸.Ì矫–…‘±Û4¿Ö\­/ÆeU+ÀS%U‹^«½¢ª`‚…qpø› ­Y&V‘`×Õ ›$'´ÆT'p˜Úy9Ó®RÅXì©nmbé,¼mÂöFØŸ" #Ûpn#¼¤ f^#Fè@ò@$yĘ6D–¯jd–Ål«™Àh›²×çP…îØãofö³ê›ã«%¼ hê,âþ†ï,ã‚Ýÿ|À8“t.{‹YÆ˜Ìæe´þt ƒ7ä­8 w‰:˜ç Z¢|X¦¤*†Féš¹z®rk…†ØëRkt‘ÅïQÕOÑ”yvŒ«š¨áyÙS5àçJðÄÏ×(a$ÐfÔh\]OP¬…ÆqPž3… þ]›R)`ÙB—Pfþˆ†¦'Õ¢ÉÏâ¬\‡âv0ÇFÖH Fi;R@síÁ‚Z×{‚m€›ÃÀ=Ø“Q‡@6˱ Ùï3\ÅjÁA÷ Pã‰á"iä"™3†ÇzÇ@þð¶`/ ·F 3ó@gáŒd¦û”ƒ„wÓ-É0³‰Åk`·ï+›95䕾­(´^­è¶€–ãèôtf„ÔdYÚ˜eËrlwËx7ºé†»Z¤y….©Õ~vDÙ£nó$«E»ªDŸþ–ËTÌnOd§~qC4(o×jn6ÄErhî£3FeP\ñéN")ˆªjt.»wixi}?IÛG™bÆ 6ÞÊ8¿ìD~7ó« |Ò®ÓÌcœW<–j¬(HH^2M‚ì„ù(“G›Ës¶Ò‹IUI/g›Le2-ß𜳇DI7ŒÝŒl‹õñÀˆo`8`w‹ÓŸ¸*¸T=¸x"cƒµ–ŠgÑ‹+ ¶ÝO-ClmáMSc4Æ|?³±MÈ»ŒØÈ­^ÃD3AlÂCYMæ`A'ËF2Dçg9CLDëÑ„«&¾QÉY‡™ŠY8s«‚5ŠòuušeÀB4Nób¾k-|ü=rž™»›˜j—ÿ1aÄÒŒR¿œ;Ôc4ËÅ|§,qmû_nÂÂ*ж¢Û‘/'ƘIŽ4“8 \`ÙÏŽá7a›“%§rªs¬øý‰“%bþÅÙ¶1edñj5“,Ç€¯ÂTÏJéZ\Ïx¯S [Ú˜¡nÝÒXr:ÎÖ4Ào$µ*HuÕ*åA+ìP_y™¢Ñ0*­«“¬F;4wŠ‚¬\8R©CdJ½ø`áŠKC¼ÒÔò¢Z˜ .[ ÓWäA×"Q”Ì*ט~sRâr{3P> ir{`F{¹=ÊŒ°õ_Ìí¥"ÃNn/ݹ ¹Gopç%÷&aÝ €AxOˆŠÏÜ_i‹Š'÷éìFŠżå^j¬ˆ5XD”ýÓêL‹ä Ô2ßú˜ß(ìø?lªÉ iÇAeQš2tv|Rn¨øIf™7ÂZò—•~nÁkší‡-š#û'ÌÄû\¯ecØ Dàw7È`¦ôN]¢èáFe59…„E;ŘZZMÉ<ö¦û"ì?'%ØQN 2ZC™g±l9»†?Ó±TÅØœ6»…¯É¶\¸®1ו-W£6+¶Z„KlYâw×ÊËÒÝ‘¿û͵çJnÔL¸^ÔMMÖ`Uâ6ADA4­&V«gç³S‹šw©”º|<‚¾Ÿ—D f¨«—~çy25€)˜$Sãžð´/#Koò}›Óê­QÕš5m©³!ϰÙÉìæ%—ÊŒÕtžëÝPÑ=ˆS·¬ —’åŒìØ”guº“ØÖ”.Yêà”¤4û $œ–S>ÕËh÷J¸fž03IŽ(Àë¹¥WÎzµíu=‰ŠíFPø[¥Wáeª#P~{¡Êz±šôT"{q­…Aåg(„^ãRœn+Ô]£§ 59žuøE­éºVuZ]Œg|T5-Qó4•úÌ‹^ «ë>ù²\Œd°B³ûúÔûÞš<ë¬ ¹nA.¨óæh™[oO,¨ƒ}]ÅÓYa{?¢dEI@ÎY¥_ŽÉ÷ñK˜Ed¬Ñ)­sRËúv[e]éFéÃÎ|œ„]ÎÖä8à>(vlu‹Í‘üB:7┾2B(KE´[ÄYçt$[øqÏéHƒ÷h´ #qÊÍõdŽÎq²–»±ŒjÙ·Ôթ訶 /b±^ã0GÄ*‚Ï+Ӻά˜n©•¤Äfg‡qœ<ˆ¸áìc9:!…ÅxĤýIŒ2lB¬ð!šOˆñà L Š¸šIoZm±_°ãØØßX¢ÇZuU”0‡¹p´‹¦S–¢Î.ãÂÄl½©ÖËù;E”åA%Ë¥ñ"¼È÷ðj1XgúŒ½½x5uHâÜ—ØÙmT´Ñ"u0TO©mÇ¢\K{¸ 2([²øÎRZ= yûã}Xë…0Z’?/…2Wn¢7¨CaœrB]é½JGᔄá2ÅîcQìÌàlC1KQöWü?pK4KO­udQáÙ•”¼-õ_k‘áŽ^]:%û’ÚV~&§¤#¿Ž’ÛÃÅ2ï~)í¬Hñ.-™ŽE­LS,Ôâbx}˹T‘}o}ê®]c~pÄwù8¥fòÛ-stö‚<.ÿ±nÖ‡écPõù÷Të!Çq¼nw#,0¸exrÒEÂïé šë“ë%lfX ùK„è ÍŸpc¶Èz®X $@4¯›œr`‹ o·9°µ]”¬ÑÌZ4³Hõò®Gúr¡”8*n®d=uòðJ&Í¢C7gñärtÖ}R½WˆÆ²ÅúéRºVxcÍÂ3k¢ @À˜JÈaSXwhýr¬ÁT¶êƒ̸´4³Xˆš¶Ô\w<+üÓÖQWo=*¯J<2&&Ê4g•þéÚ©]ç9†05ál’§ž®GÇ©s‹p߀q±áúX=Ú†Ó—T<ç{1ߦ|-ò²s›A±‘·¿†wÙæXýõã1»É¥’¯ãípŒ+æ3‰ên)&gáH|kкÕ) ÉÍŽ‹Ân(ÕD50Nß;ï_¦@_f!]‰L™nåä ˆ“'E†>ŸE}v‹+zÀ~çu\³`ÏPÖ.À8³y ˜mi”“±ëìÚôbªMˆJo%2þd1z!;[ß)Ž¿ŸDãмøéÙK]p¡Ô/N ‡‹°ú¢3Ì X®|îàñx1~ÿ|üI¼n5™,aQ½ «ÓíRïËBÎr¥3Â&Qnà”cQîõÓ½ . ]Rz:u;>)¨Qå ^­©¾Èʹƒxàõiß’|D$V’ ‚ ûÕIÖèHµ4G‹‚‘ÁÏ›Xé´•8gÚÛö#ªLTËQìää“ZLÒéÉçõ~àˆ¬÷ƒ]½ñMÔÐw=#Ï~`MÒŽ±¼¸ƒƒAg*m)OÉ'Œ#U½óSÌþHi ÃÝ?vÖJö•z'¿NO:mÍA»™Èl=°Ù³¹FK»Þß_B"/Ñm:ŒðÅ×7ÿ Î08endstream endobj 765 0 obj 5573 endobj 769 0 obj <> stream xœÍ\ÙnÇ}'ø|¼#ˆ×Óëô<Ä€;Jg“é €I-‘DÒ¢(YŸ:½VÏôÜ l¦‡3½V×zªš?ŸôkqÒãßøÿ‹·G_<J¼¸;êOžÐ/Ž~>¾ÉIüßÅۓߟùfŽ^­Ç~'gÏÂâd'Öéµ'go~XYÉÎüçì/èâúªË ÖÊR¯³Kjù‡îT­‡aÅêOX£Óãê«N®þÑŠµÖf«³Òæ›ðVi·zJoÅHÃ+GÓ­é‹”ãZòþŒæŽþQ©'Æ£žýÚQÇÞú©žvJÒÒ…n¯† ¾;4EÇoéWêÚ µzÒÑazG½\ý­¥”Ö®¾ï¨Yohqa_†>³qÿFƒ=Á`ÃZŽiˆ^, qVVÆ•~ ¶ÉïºSCrá”PüN…!ÚÙ“SÕÓºÇ1œÆ+yuï©;¨;ªÕsüþ*¾T«;ÌÞ÷B¬~¯øqƒoñã?Îó‡÷uãøñ.÷¸=ô`Ö£³«/hRZOš4t¤'‰“ ï/òË÷ååE~ù6¿Ä–%=cc§B­íeØá+ÌYo)ô¾«?¼Á+ZP?Ò›Õ£¼þçiŸy)qOi'ãà—ÿ*¾.+e4m-ÚÓ$¼¼­:Å—ãbˆá¿,„Ú6Ó#¾Áù ç­—÷åe9í»ôÅÚˆŠ¡”^+OoE«Fèí:›O8%ªucOÔÖı$Å '¦ô(i’$rP´¶ý¸úDJÐ,-Z‘ Y’Š—áõhplômm]º_w’Þè^±.e¤AZ“R[»vIæ4´3s2~5´Qmäò¤¥ õtlô¾/ oË#[«7Ž£q⃂l™Õ³ÒçMê“÷,=o:,-,u‘.@*½ºÄv­•`ŸoÂKç³Ü;“ßo ÛËûÎËà ×Ö‰tÊïÐѬ•tí)¼,X;Xí·ùjppÊåÍi¯~ɳ¤éKôètЖ¸Ë i›$4éd@QŒ õA$rð¿"ŽFCê‰wײ·ü؆xèlÂÛH-£øª5{H5‰'íÓá¬Òaä¯lذ3X zJK<Õ‹‰Ò:¯9è –¼eü—‹ÌÅå©pv™ =:. ¬¤Œ£–Ò]š\bfÃxdÂõ‘¶°cý82ÚA¡% @ùÝ”ã1ÆkXgIÇ=í£%­¤æ¬ºí¦ã*éK\ Ŭ‰å̃ÅPIãuï.¢˜fÇú NÒÆ3ôBáäZê$ù0õêCgôšÊÕ„Ëë¹,ë!oG“'Ľ—…?¯Â‚¶«ãÒ-î_ZÇ娈I”e§ÂÉ¿br‘ž2'^Yî“t±YðkK>Ê”S¡ ^A•¼ ˜dM*!H^81ž§%ée-oÁºÁsö’ÖV}8¯Ùª1Uk­æbÍ–Ñ@$çn¤A¿Æ[8˜p>ïTœHâ2:ZÓG¸´‚s`ºš1é†é#¯§1a¬AAHa4WЬ¯VnI`üa=ŽË[6`Ô´L¯<\ÜqN$,cû*U/ ‘ÅÅþš¾ÒšìH^.}µäqÙ‰ÈÓ±ôÄ⇂Qh¢µÓÙÄp–¥N†ô$ÁR^„DS—.ÇE~.RÃó¬cÀ­¥íMÐŒäVUÇt´u›Du=5ÉLøJëÖ,a宨/iϵ•XP÷SµNõΘÒ/G28"‡Y ×{±™s‡í572Pÿ¤™iÊ­—t<OnµŠÜ©&Nƒs¤üsîíàü¡C”årÇÝI5wçºe8°øóʾ䮸_¢{éý’]©±‰úiPRäf°w)–åÒâ¼÷lqKL¾är1åâÏSKÆJ°Eg»àBeŽÏYXXvÒLï‹xÓ°ŸpEsˆ(V'rLÓ³Ë ¯«Ø÷4¯6%;0r’„¸QŠí¦V|È–¨éà,óÅ‚¦˜GÕXµ‘òNÏéèëÌL©ùýl; 'é rvâÏì‰$“¡C„Ó{|%ôXBÖ1‚?ñ8áC »cHý*Üà!ß$4^DÈvW„$|h´üÕ‘ê¿É-oÊ¢¯9IŒì½ú¨µç‚¼kÅ÷Œ…dçùéUù\ÖqU^^rœB““…­þÆÁ‰q7p‚pÑŽ“¾aB½çcA¬Ø…ÓZ¶~ðO7Äx‡°è'Êb)ìwÂÇ‚›"²ä ^dÕÑÒJ)¨YÐJÞuÔ²é¢õ Éó÷.È‚[(¢×3WjtÃÁ«CIïA Élk sÁ”²ÚQ4dÏxØSìÓ¾Ò°ËA2LòV°!MT,d1r5·˜è=kÙäÚ$7\N´Za"Ò1šlÔ –s;=µÈùÔ³åîðj¤MŠWkÏó¸ÈÀÌïŠÔ©\}Zì`‰ù´ßÆ,ÌoÉYšBWb8Yš‘kmsg‘ŽÚ0>…Å»œMxÙXÆâ>M6_i¯@$ ZÁI[iô:ò=yÕœËÞÓ'À|ìR‘Ãâ„´MДªVvÎ’`¹Ë†ÿö ¼e"MßöF0s$¯ÿã’;¢¥¥6ú~±ãÎjÖ)š1¤Žrˆå™ª˜šÇÒÜŒÂ_Ð2¶ò-ƒúbÙ¢ë¯ Úx=ñ€qÖ[IŽdâĘ{#H:XÈ1IðÜŒÁÖ° >û²º!¡86ª{å¼=o¨ÞfØUoÆâ%‹&­€ïfø­b¡¼¥«ceG†a줒a.ˆWIÉ žÖ+QV`í°ú:–Y ÚšYvcoWòwn'w$MÚÄêf4(p9ã’¼›AT« ð³óŽ©ÖéxÓ:Ä® 1é_%Çe¹És/«W,êêPÀ"½»Ë>‹Èêq›¯ò‚¶FË>HT¶Þ¨›`_ Ì–íô¶ð?TŒ´H`Oà…³W{ÒQ›û½ÖÊ|’*º,ìœ÷-jg†øa£#ã‘<£–…É:.²[üÜŒÓÙÑ93ðchû¯±àV4r2Xº¶ ° о™Úh ¢v§ýÝÔ+ÌÓê(‚,ÙÃuò’Ôê+¬?äÿnÖ5’îÌ z£?M $ªÕ¿4K%¤ÉIªä%\?ØN˜€O… /9â›t­Yî?u’¹,°ž´“PPÜò ~¢­˜÷H¢Ôh—‡—dSGoÊ7ò a"gôæíÛ£³G?øÚ–¢ÇCê>ëaA`×Â"Îf²E>BjŸš6@F‰tMœ~÷äi±çIf±ŽGøf.Þ/k‘¹çBiðÕûŒVð/-¹Ê ¾åØsãÆ¤/é}S…XçUH{¦™…ÖÆqÏ3/`@µÙ6Ú‚ y¢”¬à|žšÐ Óœd˜|-œ/ÁÚàß{¯ªXV&áÛü{m‘{/S™Ø`ÏîžtnæØOB©Óº©ïSzSÌe>¸þ½– ®?da^ïü†¹ÌÅ0ü_Å´˜bŸ¦›rsZ„Ü\ÓšX:<ưj’ÔC<Ф^µbz°g¿‰= ””J6£e£¸!k˜ŽûE©câžÂxÅ}Ò¤¡¼xæ_[¶Cˆr–doKä](,hÜ4i­Ã8Z~ŽAŒ$ê´˜t ‹®CÂj 6C o’|Q^Ã-R…™ø–šÀœ×:»Š&ØÉú:” ©ð:ì†%çY6«¦8üÒùÊUIß++Ã6‘phÃÙ³HC^Êqkþ¼æ±6Û‘œÛ¨ò<ð0rø9™›*¥¸)^b/&€r :d±a¨óæ2ðý†øÒ;v^Œ²¹6–Ú„Õ$)Å¢9ATÕ4T‰` ”6C±§E>åérÇÊdž‡­ÞOö¼¿ØgŸL50 ©}¥%KOãØˆ5 ñrRâZ'/ 8UôD*_U‰àœD¯d$[Î {Ût*˜Ó¥{x9Ì>"Ÿ5úì*Ò1Íü»’ùÁ£sÞ{RQÁÛÏÆ&°EˆÍÝÚÎPÕ„Êq9Ù}Jn!“ˆ¤ ^²HÍÒê³x&®¬BÜýcŽM}@Õ…»_û;÷s-ùô‰€¸ÍÚvÜ6hÖt0ÙÚ=]Ò…¤³}rÚ×Ä_åÎu%|Nè²$6²§½óIlÙï‘ÀnÏØÙt?,ý¶Û1½-\vÂÒÒeL–w®RÌRøç­NÕ®æ ¶&}3(êG-â?o-™È»É’wɈ³ì6k€Ç|NÞâñ>BÛn-²ê¹+|9`á‡F~|ð9PÏï:É·èÔª_J‘ç„).Â\VÏe…X$&EˆqQÄ4ƒ7Jã$S[ŸšÒfÁžðÀ¿®ö™D #K3<´ŒØ#xq¾£Up¹Îy§´bv)ÓέÀ&põ+Jî¶3݃Äåˆ åÈ!ùØHíT.?ã„Ê\)c=¤Î꺂ˆS‰mrç/à˜ ¯3ì—±¤B% }o›£]Ï©¾|’üq=-s—f×ôWªú‹ø'Ëî“„N«Ç!»G8Îä„(žžß@a] w~5 ó뀘¢sq4Ä%¦jÁËë—Ò2»0^IÊL/d[‰x¢wÓäxë…¨c b¢µ:¬œ$awµ#6qSÇÑG·M¿ï"då`]£ò±L+ÞàéϯüzÕrH™ª6•L® ©ÑnÌ Ç áee>Ò#«ˆü¤z™ø‰¶Ÿ«€£ïAh.;‹u}(•_É(þÝpˆ˜ÞF189ÝÙÐÎ,Pfç‹Féì{Í=ôfím¤)NS´I…¼jö¥ºóeKç<ˆû©ÝÐ óƒ7E@Âr‘:ð!Fä#ö|VÓ·RÞ>‚[*Šcõì¾äúo寿Çâ_·Ö¢™Ûk±m…¨ÄD ×u¹Ü¥Î=Ï‚dGrõ·Æ‚Y&º`ÂÔˆ´Ë»¼3Ô’¹ßdb!)^Š-|Ý=qé’ÇÂq°èZë6Sb0·¤H׸³ß ¢™Ó+Gí}v / €D4Ã:–í}úg¬2cɪ ˜dº·]:ï*±`1bæ¬u³¶¾[‘&Ð öu.þ3 ªJãÈQÄÜ©tù/ ¼l:2K-ß•ZÅ’9\Bµ‡—Ì%æBhF&Ü዆®ÎãÖ­ t-s=«Å¬¯éŠ 6RstÓé•Wð-§nO)ZðàX;U¯“nLÕj\ÈkMo¸[ÜÐâ:Üx>T-zgÞ-ªE+|²«JãfFÄ5³ íRÓid̾zP«™¤Ûqá¸Ò*E¾§a¦ÑÃXŒdz½Š¡à“›qFmYô¸©~È7tç…¥ï‹@µ.”&„_U¦õ†3ÅÐrn¢G1$X2;Â7y7Efäwlf©£úR5‹O0£á&7µÿ¨cFa@ýß߸Ì?z#_¥ˆèäOÒ»ŠO YzÆQ1ki {#»iS®•lø›Ÿ ¨Üù¦Íç„!+›d]›ãƒA 0t>ؾÌß/9$ؘ馵6Ó—rþ­ ”JŸPðNÚEV(%é`•–#™êйHºPN"IIm¬Iå<Á˜ ¶ÄÅe ‰$ÉMè*^<¶¤C…<å$ú¯ €Qî+ ký•p²B A(HX{¯(âW°“¥ø†ò´ƒè _W6™FXèFØ©T`ÅÉÕˆŸóˆw²2ƒÐ¦ ÚÂH°)±Ûe&žª‰Šià`êü"a,ÿò‡]6űìwß‹ë WàKÍ#%‡Ç;;–Òæš¸VüÜoêá¢Øðå•{•ÎåöDzbÀ%+Îx˜>O˜”‚ËÙðÀv×Ī;sWI¡Ï/¼·ü²ÿ–»º¬ld‚]’HˆiR}Voa¼+‹ìÆ¿;ɃŽïJcØ«’ƒaLþ¡‡ÄáüêêãúÏJD–`„Èø¥ÌlÒ}ß=ëbþJ%@¹^AÔÑV©Ã2½7ßœý“þý/˧•endstream endobj 770 0 obj 4530 endobj 774 0 obj <> stream xœí\Y·ÎóF?bÞù×ÚnÔzØðÁ#ÖÜÙë>Úõ1æ¤]¿|`ð¦õ7›­8çZ¯ÿ¾áëoá«äƒlýŒÖZjµþ|³eƒ”ÊprñéFB0¥Óm©áµð4¬1i.ëØàœ•n}Šq@Ás|Ü:6šõ×@A|›*Øl|4Ìþûô¯žQ–rF L8½€…;X«Ø¨0R0AGnøAÛÕVŒÈžx 4¬oðŸ·0s@šXÿŒß_Ç‹býéGÆÖ?á×Küçe¾ûS~Ã;üçº|ûO/âWŽ,°zýk “H£‡‘©õc „žŠpïçòÀe¾ø¶\¼É¯óEä‡Ï¸Ò-ƒÒ#KþqDÔkÌ4ÐW‘X5:O×Çyõ~Ì%Eø¥¬?U8ã™øgxX¯òÈÛÑ—~½ðÙø)ÂÅ›2²°ôeïâ‹rñe¾X16ÝöÔY¼ì8™è­_+!âMu/^<ë]|W.qùq“>FÙU¬’HÚã÷G€rgÃþðèŠ:SƒÃMŒ²z6‚ÊŒfÄuKÐf,P$ ‚{ŠPq¤SÈ ÔSé¸çºqƒT‚ }U†"í8(…C¹”}ÕõöTpDÙ‹xžžsÏvca.[­¼œ8?6¹¢ï’×Þ•È>£ed¤Ðr#\¦ÿ«Aè~ÌÝùF0]@à«ðŒ–¼¨·T¶þ2Û¤g°©Ø)x\Àeé%=.éÎs• /¸ë‹Þüd!/òÓ¿ãûˆ€ ¬µÑ2h=A›ÙF^…Â!À°*Î’,¶✒ž‘gР€éb¹}SÞù´ÓƦõ¸(7QiF Ä ü°=V×”|®qÃèô½Aü\½üœÜðVk+8¸dÙšW…âÊ`I\¹sèå*7YôìÛâƒÇ²&)2sSf~¼I/1àÿ:/Açö7˜pýYh´Enê¸%Æ0"P„O ü9'{[+rø†ž˜\-/9ÏŸ¦ä˜ »ÔÕ”4}#†þÛ]¥ÊÈh©,™õ,Ì•˜M4(,Xà5/Øà‚•NrfG›Œb7â-“©ä ßQD/_ë3Lc $¹†HùãÖ¯!½mÁ(¼Ù+ÉDõŠ«iƒÁQR’ñAŒÃR¼«dÜ‹g•‰ºÆ‰íkÄ=?ƒÑÂháõ:™ p»Iðõ¨©$žgqïLŽl¸Á—¥M(ãA%—{•Fä•ÅK“¢Õ¾p¦ç/l<¾Ÿ Cº}ѵìiž2câHjT`9Þ7ëDÁ¹ƒ«D7IHz÷B bã²ãŽún@”ç5Ÿ(ÉùIæõL¾6—df?w¿$óúÿIæƒ$™,ãâ°$“à6)®“†X\¿«32958ô€Ì\!IÍæãþƒË6Î@ ¾ FÔY0 ÕxQž»¢¶<ÚÕå!£4e„‘ouF®=ÙeLL¼cttAådý)Ì^ëpNëz›Bð»ŸMùŽ ¡uܰ®Q¿ÝT\ÊÝD·¥ëL½ˆ24}íe—‘½ŽFéå‰G3 §O‡ä®„<¬¶m™7µH j`2¨D‚&!î± L_œŽ Æ!yD9,EŽW%P¢R o.N¶úzÏhï¯1\ù->Lc`0ò+a‘}—Tk~ë$»¸¡¼¨Õ8ˆ@ɾE’e4á~½Žq¹DN6³ÌÐp‚;RØ™z¡IwØÚ9IÁÓGH*è)s)nÄ ‰DZ\Ûj>:ï @½·÷š>н_~-õŸ‹ÿifœ–ϼ£Á¹ÁR¡•‘hŸÔú ^µÞw?jmSÔÜrk$½ÕÈr©QM[Ã[˜ ¤ã‚YA‰‚Ù5TQë#™p¯e®ïÐðD,¨›Ãá!Ä«L|jsÊ+Ëú¦ˆ/ ÚÎe¨¨—S„0@㿈LBÛY@ªû ‹ÐÞõìYÀšŽÎÕ!:ž˜&wL¤:,£G—F$Ñ k »¤Á´à.1ãMàdGðA"ñy/Ú]ˆĤʈڌÇá¬xÓ¿ldqGk“ƒ·ôñ‡œaÍéX \zÀÊ7#Vñ83ëIžWËÕÄ-F ŒÓؤq*×!ˆÓ–?¼Kêq!¢ïcŽh^”‡J®IÈ(ûœ´‘ÛÝ"—÷Kʹùí÷7Øq5µÅžÛqT5©º†äÑÄRèQRܸ™®}Œ±ÿT¤‰}ìêjñARÌ!V¤‰x‚½ R¦ƒƒÐQ€€¢Ã"RyF}IæPu¼ô“ô…•²1qé“`®¹˜áÒ!^¤«g —nÐbÙ`²}¾éìúïk`ˆ÷ÏáR˜@L7UÇÈÄmJÐ<ᮋÞD(•ï¬X êjŽ!nóÅ»yâCWºG‚ ZP"çþÜrîu0 ÐBw䥧F%>îH¶§âÉ´!£ vA!³ŽÎTC!øãÿhÊA·FY`Æ<òÝäy|£U" \ÄpýVZ ƒE>+ÙYP|ï-Ë4¤ß1ªÇx_…¬±¦%»ó«°Üâ{,)ô ùú\ä9bû‰n+¡³®;F÷uÝ`ÖÌ$Kf·{ ¸Ã^èÅKX”Ñæ ' ¢ÃwÞî‘ í-PFfaTw²WüÊ[‰¹c !F!Ú:Íî05×:õÃGsA€F ×Mî®…‡´fìúPvYÑéŽFV’ðKåkÏ$äèÄ=—#fÊá(›Ê¾eÊFÆI´ù7 ­„j¸%A„oǪÙ(Ž ›hµ£ KJÞd@–©dÏ`+ÚÀÞ¼?h…”e¶qÅ“È IÞA±°Ç‘Öy|¢ÁV¬¥ØJ¢l‡¡hÁõ}K²m渣[(Çà†š6¬}eñ½ì[št‡¢‘3>;0¼é))é<ðYÈ»jšÀÝVýî‚AW#|š¾5…=Þ”¼½‚Š<܆ª½³38ag›·;ÈÀš¼=άs ²Æ.v¡fÊìQ¶¦yš¤Pﻥˆ)&tHE³$D:¹è•°c¯R#d1<ŠÝ)Ñq/…¿üãÝÞº]ä'ì‡X‚¦ªHåêƒv#¶™&á*5÷p‘Šz19O"z[Kûk‚k!öÙ¦^lLP° ­¾Ø¶v>ΡÈ\\×Ö#UI¼K?FûjcÀŒ à™›ÁõÑdw]NÝö4÷j£~–ã "õµ/¦}1¹µ£–Ó9*–bvÛí¨‚°ÇvM`ƒU°ÐžúÛFIHû¹­¥òœ4L%iþSlÑ2H™—´8÷ƒÛ÷ùéÉw'¿¬ ]ÒþÔðÝ®ÀqXëŠ[ˆ®F‹gž>?yüü«ÕÛ_ß½Ãj¹6r¥ú°J¸ø‡“l®0ãv8!¶ÙÞK9(€WÇ'2\Ã+šiŸ49RØœ‰0uö8ÅŒ[ÙMî:)TèÝï¶”¿¹#ó>ƶ­ØEé ÓéV½Š¹4úf–˜`ò&9lÊF™õÖzîC“—Ärã‘Z.¤–+y꥘`•LD"TȰ}w…Œ©Áb†â«²4G×ÈÎ7U¡ ÓŠ‡®‘ç‹;jdï©Q÷àÙê®{Þõ&éWÒ¨ÞùË÷X½ÛYs^jH?Su«^_™!Ê 9m’;¤+~.®Äõ¦½G‚µZÅÔa¸Ó dU|”¶nJ팤º$h™žUåÎ'HñTæ<ŠïL¨êd ÖàÌ®L!9ÝÝUFLëÇZs÷U#ìxD£gœô=– 8ˆ’s·Ã¾c³Ýc­ô­%8ºnaŽ3Í‚»ñÔðeíþ›##]LŽ„—ùà”Å lÎËîàx:*¸N§þ*8AÛ5Ÿo)o$¨läq ꡾±¿¼±0GÜ!‚=5†î¡ì.ÉMâ Ö鈈MIhz¯âqʶÖ„*4«ib¸õºûUmËtؼ^Ä—Ž šF’= jBjìÜ`´ž–]qî#Û×ôôˆà¢Fw©ö{Àè]§+tIªP Ž…SiŠKF·E£„¶óåïhË<ª1VRÓªêÔlKmÓᒭ류iŒ–Á²TXmÏ¡QqþwÎ[\rØqZAűDKÞâcv`ŒwΜ@pe²Ðï=r"µFŪ+©R…ß' •Tn°4V¡¥Q´ú†g„µô5Ì¢ÍÉ¿ áŦ-ßBFeÓQï°ˆÚ†ïPÞgósÆ…ÿQøË f\#Ä=è TÇßö!=N…üyš÷ßÃÓ¬4F”æ'Uwö³€8nöè=¼QƒÙLß²ûx¢Ý°°‡Ú^=Ô36Ý €8 +@ǵ”ÂÞ¥¦/c<èÖuôDQvÅT Ÿ ^3ᛞۂº{xú3¤a· èÞäüf4.™Œ]<8ºÁÚIÿêÚE¥ £ëßH8Ò锸¶Î’ä7DÒû«z|ƒµÖQè5ä.U2áüûrDû¾Q‘G§«çx>‡ãÍßàO4PŒ   ’ÌØzÈ͸Ýe±Õji¿ vVùÚ}?Ý´"žT¦¿d|å¢w“žš˜ïèJɯ+éKy¬VþtÈâì-.î¬.lô{ÌâÜÙ„‰m[ÙØ‡lvµyæà«5IW:¬Öµ»)Øo`E6Ù}~¯À|gùáÖ‡äç~ ¯‹—÷3xþ{ÛùPÀgaX:R¶ø‡C? fùŽ"°‡C¢´a?4Ÿ~Èó –{ ÔK*ˆhú1´ÒÚ7R‰ð‡›T›Š’“¨õ!r<ÆÛ$òí~—ïúC²ÙQ}wò?ö+­Ìendstream endobj 775 0 obj 4413 endobj 779 0 obj <> stream xœ½XYoGÎó*?bÞ˜Aì¸ï#‘b@à($àlE!B¾°Qlc|ñïóUwÏtÍæ ÁÎtWU×ñÕÑó¶½lý-¿g³­]©us|5Ícü;ž½ÉDÒ”Ÿƒ³f{‘È–ú(¢l¯fY€l¼j\0½TÍâlög;ÛšÎþµø‘X‚˜°xÙk®Å!(tsÝ{£lŸt²1˜ØþЩöY7—½1Ö«vQiåUmB»‹U!Ö·ÇõØQ*öŠ Ú!ò€?zà$yà}£pé¨ÝN+¨.Ízm˜¼ˆ”Â+X…ÔíãÒ Y¤I¡Ú_ˆZ)å\û[2a¡\¶Ëb›Éý“0ß«8ˆrƒˆEÕ"ˈZË$ƒùk7·xT^–(XÉ£0/a˜k½cÌÑp.ÔKa¶}tB Aã<ê Ž‘>´gÝ\õÎygÚ7í?d…÷^‚¦¹ÞZÕîQÔ ñœ¾Q ‹PH+£Û}PxJ9¶}‰E¥{­-¤Ú‡ØÁÙï`#´¯H¦1ND"5 4QAK§i%{çm{X…àµnO²“L´IGe¡£lA¾Ä}S /êãë.¨Ûó¼æes6Á©çìAÄ~å;øØ¡Õ\:‰V¾·Fh&.ûCiÓ’záV½IRqàÀùžü/z¥}²9‰sÝQèÉ»*È!ÒÅ ^:J0CøT'#Ê’-0ÜZ³Y¤E l«Å.ÅUª^Åâê]⚳ИŒÓ€c\ƒ‘°ž$ !›¹Ô½%Ø&Sy¬<±H Kù(§$[/~q”®¹¢Ó]ŠÝ¸¶öŒAÏ$ ß®c ÓòØ-…0Ø‘¹Fœt‰Di¦ÀE¼b@Ö½£ýØ{”‘Š'†é[²ŽPFÑ ‘¢7¼Ž¢7:lΧ(“J_œOA¤‚ñqùTÝËp@êX·˜›®¨RZ§rÉF3< Y¥P[uÉ‹T\ UtCí gN•œV÷ª”˯벨Jä©S¸2ø³Å û6†løÁAŸYs‡ÐÝÁ£ =yíE;¢™¸Ð:1xØzG)6O-ö“(ð3Ö‚@¶÷k?¼OBuÒEÂ[/º¨TAJ ›¦ÐDõë-üÁl›´/Ëc3¨/'õroŠêµ#íוmâsEγ7æë{²XV ˜ÿ›·TãlÈÚžƒC6Ê¡ŽÛCÖ}zšJ:§äéˆôú”úø»Zîk6œ×œE A-ßT•\åܬɆïÂŒà¤ú´x³9he0 R¤©åÑbö|ö¶Ñ:.„C *f/B㤦a‹fÝíÙÖÎÓæúòæh¶õ{#g[Oè¿ígð³ó°ùföh§yþ©°T3ÎQ”~i æcÒSÄÑ9ãìfM ãæÿÐÕDS67ÒYý  íXÄ̃Aû'kª÷á3zÚÕ€:Ë”šÓ‰ØH1>6„¬×nl6Ùà6äàGô7çËô1ŒýÓÄÓHϺ¹ŒIMÀåêtûLêö 6·Šbë¡4Œ±J)ÈŠÕ¦¥8ÄàÙA¥Cb˜ònøö«¤š¾¤‡‹pÎkÖ©:jž“¿¨'Ï;šÖQrjZ—KÝépZT× `WT‚sc¯ÛK%]Ñð¿¼ÅÕùÎÈlt¾ÜÅ|餔VŠ<«wÑr “R*lΫz[0+ ñÊLê‚Û¤â7Pªé˜ÆœIÝøž¤(”·H I7_å}³†¹¶Ô[ô—öUlbP<žDtXϼ­ä’~ ™†sp‡hl¤)è+2šå\:§—nSÉ•›{ƒ‘N_WQ‘3EåÚín˜ùvÉ÷ùƒk¹ì†US»TXE»ÀNºÿ±êÀ.])´ô·ØÜ‹SzÙ3+¿^)L¼KýùsïòÐn«wyÓoå5Ö[*Kõ †zk¢_®˜gù{s·ÜYþ«oóñw“'²ÕdL—{W/–T–.¯›†Mjž–‚å>hõ›gþD0v‹Éý}%–Cï,±¬ð­c×°QVí;%’è˜éÙˆ¸µ«¥ž|Í¢ÏK ÄèTù§K*ï–>Æ w®é?ò })íKz%#’7PÒ—$˰ör$>›Òí¯oÓˆ´…Cá¶áÐ̘ìÁtýc.mX¼\³Hö*<Ó7:Ê9 ¡´MÜÀæË&eî«éÆiQï…´í]z?i.F¾ëÑ Ô!¢O꟎Ûoª¦çã"äX%†zeñ¨RÖÅýºx4.^ÖÅ{¤aHCÊëqÿ¼î³8®sTŠW^¼˜0•Å{ÅPôû¤óO¹Ëº*po²8<ÞÔÇÂEŸHp;åMíèùì_…Mî*endstream endobj 780 0 obj 1801 endobj 784 0 obj <> stream xœ½\Ys·Î3£±oÚu‰#ÜGR~ˆ|$J9v,±â¤ìTŠ"eŠe^:hGþõéÆÙÀ`v—”œrÉ"18>¾n4ôzÅ&¾bø_úûäòàñ3.åêìí[ýþœ¼>à¡Ë*ýur¹zrº©•`“1¬Ž~<ˆð•+måêèòàûõg›C6i£¬3ëW›C1 “¯7lò†æ×7©Õ‹õ» Ÿ¼ðʯ_n MjÍ×o6‡ÒšÉ­=Î䤵Âüûè¯yu5Yg9®®õ¤¤w«£¯Ž>ù~ýVPŽsWp@„×0/ìS*¥Ìú“ZJ±>G ¸cÜ]°wйµ™ôøµ ‹sI¯åú‰Š‹vÂH«Ö_B©¹ný4ì’á×G›C>9kaŠH$3ÚÐßàllªvµ~ÒÂúÀ&뜱”„7¸®Niµþš™F˲#Í-'[޵y)YæÚ3è¡bz}'Ä­rb}[©ŒK{c(K®êwÂß·¸M£€º|\ägòÌÇãòSLä…)fæL¢˜ÀQ*ŽëP29ií×/b+ŠÄñFÇÙµvÀås ì„íJ®&ìRÚ€kvÒ ¦}·‘0Mp˜UÁL\dšš¤T {?â~€næÃü'¥Ò M t¿†>·‘$c29Y™l#OdKÐP”™ö»*oË‘(ÀÆ´¬å¦Îìž 2ÅÁ. Š|žœ]{þŒR!„´žÌIö„ -¹Ë{d±ÕŒ§Ð̘ïÆ+Öí\oP è‹Q`/ŽNÁL\"÷±Få=èR­`ÊÄLËݘo¸s.'Š@ò:’(…œ€ºÈõ¦Ùß;®'cnëJ¤C\‰ñÔfô|„ƒ h§Î‰ƒÒxꆳ25qžåCèWµëœexÄäâ$yd<'ú}EçhCb‘»‡‰½‡­:ÔˆdÐ$˜ì¤W ÃÔ\ä¸$£‘ñ-¯k$?·U½ Z]:¢6(´ád#-ŸÖ´#ŠØÍHÉ –JÃñŠ‘@*Ð}¿\Eó©^GB=ûã ìq%A548´Ù8¬ÐZÆcë‹JciÇõŒ§Yýˆ €4j?7­R M@úÑ»ÀЉ1î$•÷ga!8¤ ÑeH >%ª—šŒËê…2E¤?›´¤óH¥Bå‰ÅVvVx@™ã£oœ5J™¦~& $í–NgíÎ_.QÑÁãÓ+zê$Œ«TkªÉiM%Éš‡@º”Œ¹¤NA z-äjU—s*E"Jë¯Ä™PÅø‹Î{RÞR—B¦.4ð3¸Cè+‚¹ û‚&€0D øu»<öñ p„¿<`½';m„3ì×, lœTÿEË„á'dœGÝqœ¸¦AàZ/{ß¼ˆ ¢nÇ”\@wTáÍ‚²F9ÁUÞ$l‰g¢t7±Â£Tc÷ꈰ.…žò:tŠÙ.ã&±-AÏ`Î% ¼àAгe² ùÅÑÁ·¯WÀm2´°mЮBHGaÞ÷ÉÓƒÇOÿ¶z÷æöåÁãïVüàñ_ðOþþüõôóÕï¾xºúvK6¸ÕÉ” æÜNN­{“Â×1®o㼤˜i3Ët£æŠÿÝÀåºÇ š‰i„S¤`ÙL´ Áú²àíæáËSFˆÓ8¥¡¢<ÄY1[îC%éT•($Ñj¢=´2bÇy3‰úZg†ƒ¦éTL…›òr¿p/„çC¹Î÷;«0ï±%_žD‡<9<Ï™M/|^'IÑ9+PÐèûÎS®,º0è!á(uëõpšæ-H(Þ¿.Ã!ˆÜe¹Ï=mlâÀ°DÈ႘å˜ÉqÕ=’ !Ï]aLÖêGéÄ…c˜ÐtÑD›AèÅÄiжpêZXSÉ¥SUÅz_òÔ B…½·’Mo¦•މ֯bxÚZ̓òëOQ'ež…B'Ï,ì÷ N8ÌcŽÆÓY¥¾ƒ½Xë˜jºI;ªwXi©Üú‡M9väªö%€ê\¡Ò!sÖ@Ÿ`3ø>ÛÊ‚6ˆ¼ÉäÇMSÍKÉ,ˆšd“ûY`f¥ìl‹FiËd!ø,’ý°ÈÀØ>L•èá.†¹ÏJ¶ÝÕkÖÑíÇ9uRûG„Á˜+áÁ¶§\i5ã·#/?¥°7l¨EKC±WŸh¤¦†|ªèpsÕFüñLýn¸ÔjIwA“÷EPDmîeqg´uô¢f`?öƒAOñ.bIp2RQ°‡ñ*² #,Ü_'¿H.ÇG7âaªÑ™š¡"/Ï·*_VX°…Ć“ûÁ<8&_òoZQOœX¶åÁÇl»v1l]ˆjóçQqdmWÖbc,þK «Ç%Iìe©KiÕ§H‰Ûí€rô\}ÕÅÞ)¿þjã‚ÁQë•6âr¦Œ,šËKeÞ(àkV=«ˆ¯«Å+ê`˜ÍúÏZŸw;R ,ÜÚ%|´&I÷S*ŸI®.r߱˯¤¦3^cÓ Fï‡*#Cµûb@{•D(o>ƒh=Ï^â®ÆIÉQq~$¾Y®éÀ‹ý&â£^Gtò| 9‚ÏŸ×õÁ!ÅJ©DöÈëÙBéÜžXiw^Dšš™EÊðî˜ 0ªjŽ•ÒÀSïCc?ɇGHqãâ<4$rke{À±K@&—ÉKzHIrfM}²ØÂ˜¡VEsâímj$±f~gºGÆ«EÁK7ÏâcÆC%¼°l‹•’ŠÜï> ¼fõð '³¢î}U)¬~«‡‚# þçÞW•¼ÔÊbÙÇ›bâ–u‡C ®vdí*â4•‘þûô†MfvyÓ cïÕþGÓ¢I¼hø¨f??±i_Öéš×H.&—/ù G/tê”U¥Ó35äX믦°€d<žVûLÜhcªÃÍ2ß•žgòcf%Ü«.D,)JO–^:ýÖæ;=ÞU““CÙÙ³¹Óò­9MÀª“ñÀñIšZvs‘wj¿â·èfml ÿ¤|¾®”^ѵrcæ±³dЫúý¸4¾ÉĨ@ÇŒ;ç¥ñbīќ—å§—õsØJ&'s^ÍIö’Œ'û<]˜4ïóçÑ óf<Ùhn%?¦ƒVÉÕÄ.¤ýçkbÏ›†ê<èMC‘™Y•å!Ç¢0óàÊdA7tMoꫨoþNÄendstream endobj 785 0 obj 4775 endobj 789 0 obj <> stream xœí][oGrÎ3c á¼ùŒ ަïݲÀzíÍ*p²öšF€¬ƒ%ꆥDZ­µ}ªúZÝÓ=ç6…<؆ÄÃ9==}©ËW_U~Ø-3Û-øüùôõÉ£¿0!v/Þ,»‡?/N~8a¾É.þxúz÷ù™ofáÒìÇvgÏOBlgøN[93¾;{}ò×½›Ô^OêÏþo±Ku‹`3Óp×Ù´üÃt*fcœcû?MlvÎJ·ÿýÄ÷_O§l–R¾?+m¾ W…´û¿ÀUÝú‡Íps7s¶ÿv:UÐD:Eû 7’G>Æ«Ö±Åøg~5òx þûÿ™N%|tN¤û±«/àþEÌŒvôÇ ?mh—dÜdP¤ÿ?CÎg.\ºM¶ÿ¯)O;$O†)/ÐH1Ëቌa #*ŽÅr&ñèf–ÊÁ ‚ÏlaÜ?jæœk½ÿnâó²(Xª³rSó|òÐ8tnXØNÁÝÎSÇæÅ.l‹2æ\Ø×wÐõþþõ3þõ Ÿ´,Œíÿ†¿¾‡>Ìþþþ:µñŸBÃNû‡°!ÎÌÎÿuhm8 ŽÕ¾e¸ø¬\ü[¾ˆåËþ¢×ê’¶JÏéhÒÅWùb÷qÓE\.Ø"¥Њ¯NÎüuÿ#Nâ*OìÂÛ° ßïñïõ:äe K÷6/ΛŒýªŒãi¾øýT>îKƒ{w•ÉÁख~­ä‹×Õ<s3*Ç]÷"ŠÀ›^Ë—>]|Ö›h–EnzSnz_Fÿ \}W5ÀRX\èæ*~¼™pƒ׳–Éš½+7áXbÓh«ôFh=ƒÙ<U]Œ3¡>‰Øº±³jv(G•Õ´lñò g!¶g“E;#V0TfFs¿ªJÈY)†SÁqÕ“I*7~ÀïÚ„hÒ´ÊËA˳ò`´ BÌ,Æ'¥«K0.`·Dy¨MC”ŽÇ'q!q©|k4‡ Š÷\„~ ³åæ T÷”|-±OŸú¾‚éWÍC©Û¼Æ-ÒÚh‰‚sS>†54B¿Å'ŠYÀj’ûË÷ä"‡azÿÓdÍl´0Þ]- 2u/³¥ósʯ“Ǧ>ÙKœ¤þqSî Å"=¼)«Š+ÁÁ$)Þž‰Ôf–c&j™y5“¾Â¦‰€tJaKiªúh¥94Ñ^ J땉J’¨H‘ñ\ ˆÇÝzI{{Tï#ZyÝr¶E­Ë&`ϹÁUl°“0T\+‚M•X¤÷8 ÈIÓÁOÂ{®SøŽƒwn£ì¼j.ËÀN¹Ž¿Ü˜Ejom£–úÍh Q¸ÍÎáMkEQ{{†!Œ:½fû'å>ªõ0>„‹ Ó—`m÷Лƒ%Ã…}Ž}\bm—l%a¹×ð,‡nœ†b´R8æRô "á«°*Ù’+º¨ˆX†Zn«eK.|VFãÛ|OÐÕÀ·¥žú»^É^_@ܤ ;{žà7¥V/5ÅP°˜RŽ•Œ.bÏž|åk1ŒæÉ$ìõ`ð(vä9Ñ$ÁuüLjþ¤£àÉê¬âÇ>+«—ñKp ç ýiTÀæ6Éÿ¶1â ɵó¸BÛûÅ(Çç$\Ñ“óE§Æb·ùñí5¼!u]vaíj¼0§×¤Â&,be¤²Í»hŠd'P@P Ê0éÚjº£zÕ”[šuBo×'®@ qH/“¼ˆ\_…ó)9‚’äÍ”òªAgÓÂ|ì/_ Ä‹!b‚É %g¸»]Ê&V ¶K ãÇ  Ó*ÙQ°à-N̈ñï­á}Ð[>ˆ=’6úñÓ…mxžÁÏ\ˇX@îbÊ"<ï*>È-~E !L3™ðÊ$ã÷/aå²vÆgéeñÕh:#µrÅ!·‡éœ!¸àÊßw°ÂÌyw?d}@µÓèr“¸¯ú×Å„Éý|Jæê§ÈÞ-¶oBÉÎbXžü0ò‡°<¿J¼Á¼ÆU*`x@I¼+_ÅÃôV{sËȳUƒlq)pIjÐ$]ÐR¾Œ„¬Ø¢¶aJ7©P‹_„¡ý¾.ö6(Z!v €Öž¬ùT4f‹O+­áN…ÏÜ…Yù~ŸEëßðªð»ËaX6þYqÒžÞ{’±,a’»¸–,&fa… ñ NíÇ <4o€ÖMOaõCÇCUC’hÐ1A…þç-ÆÝ¤ÂݰŠ:fiX]P"yØW ¾ª]ã¸ÝA}È«Ž.e‚®ñHa8ÉnûDw?}Qo±¾z¡úbmÕ@\¾í¸w‚;*@ZUeBpí ¸ ”þ–ƒ¸ûÅzwÿKCË#’WÂ&ª^ëNÒm£'̱ÈöÉé ÕB¿0)’çÁ0CÈšdôP½6²]ˇfrd·“+f¦Èû?ˆâÇE ïZíæ/ª[JA—Æ4tÚfÀo¤N'd—ÅFË«4Ѐ:­ƒ¨ËÅÒ#»!1npÎSŠi­à[E¬‰õZ¤×§Û˜laU•t^bîN†?ŒÃXlÇ.§¦l#Ä3X…Q»@”©,yvÛ\ß—Q K…f¾d 4HÜ_é fk‰Ïa†ÚÁ#Ve©þ#’‹ç«C珞Ï^!Ÿ¹ðÓ¦ø´¸Ï¤ve(àBqŸ$êB8bÍôÝÏØ[¡Ð¬qÍïùd:ȘxNs‚¬N)¨SûG„†œ9ÿ¾€{Ÿ ç2—ƒ(ÓïS}´Q—– É—¦bŸh:õO³5pàvÉŠ¦÷®%ªd³#|`Aj[â30Œ R»;*ëI.¬x¼¢Õ9:íUWÖÅC¨8‚«Áe…tpWó«‰~…ez'G‹aÜ]_Ê‘#ÐÍ,:6ƒì>ÒsÙ¡Þ!QøZÏû^ç_ß$J7§!šÌ€D}µf3cQHyB^õèÚÂ’fºõ¾²õDËCKf£N+FY:L`12ÙWùº¦„»-/鲄>m?r€{&K]gd¶ÿ;XÆÜózJ¥ÿóÞÅ›_}ß FÅït•˜“÷ô$®\z~ÜzWúØw qe7Þ”úÄü” ‡û8­-=‹8ˆK_-ÇÜ‹1û/2ªŠÔ*„›ÀØ —ÖT6îé×3“NjJÌ·;\5J‰Vó¨ènûµ¡øˆ”yYV÷à[ÒÔ×°Ï樂”—)–›ä« »’=IiØ?"CYÆPä¨Ç,cTêÆÚd8ÙèÚ-ŽÙX¨þ´~ŽAnõú`X:ײbWS§FO/M¹ºH¤nŽQ))’å…_LøF£Ýþ;üZ IÌOê8Ž*Ýüû|3©¯_ý(°SŸP1êüUt ô(EEX@ž zDm»1^ GLO’ßžÚŒê¯á&63¦âx¬23Yyî,[°ÔÌWmŒ( ÿ½¬°ªÂoa>jû¨W:PZ2LlãØ;–iµ?tª:~È•à›ÔxÊgÆ’°nËÕ ê×âÀ¨úú¢v—“…pÇîÆÔßXEi ~ N4–”móŠñ`Ebïã"ß9 ‰‡À údÊy’íþ’yÂo>ŸCr]C*xÃØH¨â+?Æ\4FÒõ\[ x6pÈó&[–ýñ}Ä#ö]P1ÍÍ~-¤ î–øNR²JŽu4`ýs« & eÁMÅYS9» ~RˆãÛÜFsÊxX½¨iˆo^ùô¢Ýâw°²Ï^—±6Çh:~§É¨ŒH:i|~ª²DZzMíÂ:¢ò+¥(§~M åØMó¾ºþ1ÖÕAL¢¯+fl‘”ýeÖE ÿ6J&µ¸Wê«Ó…†ç( €ê)å:ç0ÊZô’Šh4bbšô™%ˆ¬-Öw×…_÷X [®½ÎüËe¼cÍ.¤RY¦6‰§rá˜z5”+’)oÝG*•-u/{…o§N©l·&¸®'^Ó:¥Ïny-!ˆî2$RyxÝÒûƒƒ§ŒX¨Œü]ØàM’ʺc $}¤ƒÙÊ\ YUJÞ°2mzÍW©ãøª¯'O¯r’úRûè5ñ_s¨.×ýøÄÐäSòýIžüFSÄÎXÏö]³ièWèÇëÞ6úê¿O¥£[ïíNi¡UMNS¿aòJ0±áŠWhÅ2%k¸k_S­R:BAJh–$§4>k˜~Sý àVT€ l²Çÿ’ÿAFΖ`ʪú‹ñÁšÍÓ2~úàÓðÄF0àa“18¹«â{ñYÛ’õYº„Çwñ®'æZ„¡gqËÒ“íéÞë÷“Zk™:¾“8€"(åÖ"oÑw†w„N20ûæäÿD½] endstream endobj 790 0 obj 5460 endobj 794 0 obj <> stream xœíÙ’G‘ç ‡ù…yóŒCÓ꺫ˆ€Û,ưÃÈ»’VÁîêëïɬ3«ºªgVÚ•pF³Ýudeå}ôóÍ<±ÍŒÿ‹ÿž^žÜý+bóøåɼù=ü÷øäù óC6ñŸÓËÍç÷q˜ÅG“›ÛÜt`Ã7ÚʉñÍýË“nÝNm§ŸŒ1bËü{cÝÄg»ýÝNÀs­ÔöÞnÏ&kSÛû»=<µlÛoá§P“T¢?ôøÓ9+ÝöKÊ&)Üö³PÛ/Ê*ñ'gGÁ)5. K=ûŸ‚KøCmÿº|b3ãÛ?ã$ιÖÛ¿íÒ&4ã‹P86›íŸv<-,¤M+f¿¿ÿMKÑ$•™f ˜º±cv*Œ¦Bè^2=½Ù‹y2̹0ã—it³.þÄAqáW€/k5gÛó|=D$éIÁI,O /~¥¬‘~W0HnŸ¤{»*£ŸĽ.O_á$ —n·•§i~ZS1ºn|¹ÛóIk£qc¼.äöNœ×GK:éž™I go/}ð¬Ñ/OáÍ#øS  M>^Ó™ûá®p¸"á^—XIV:¯ÁÆ%Йsý1ä>Vîøúpµk¾D$ñÖ§«H…Â"z™œ”VÛÓLˆ9Ì“²Wq†;hXÂÆÔìèÏvH¸ò, ¼Øíå$à,6®èTØê΃Wp„îbœ2B1gš–' Ƈܰíc˜w'½è5J §Q+>‹%ê¯@Bý€…1€§¿á ›” ×Ä8ßþ´ÛÏ^üCV/ï ±DÑa4/÷ƒë^Å›Œ‰èÃû*—X.<¯@(¬¼ ¤è¨Ý-ÿ€Ò£Ç=ôE Ôs_Æ>¬43µŠ:\é4ÿê¡® 8î(¿~Ô-jöܨP®Æ¯Z‘?4Znœl ´HÊ™rˆì%zè*EîÇu¥ÔƒšMÏâ9;ˆŸ =±p5”«dXOSDA&ŒÓäÀA‚€[aY”1]hÀ˜Áª}7i×Ýq"·²çr³ç€ãL@ìg¸‹¾@¥Ãáfä\O>Ûò‰3MÕÒ9RZ` ·„±”Ú~·ÍïgX໼rh<›ú–À qŒ 7ø^O|¡ôµóJ¿ÿô¦p‰Äfœw!t(o\Vx$0ï¦ó#ÀVÀ&Û{Öx¶šTvöæÏ[Ø{–y»Š·Ìª(/X3|²’'¾"ÖR¡¶ˆp˜8ÓÀ}?.0¡E²0»½ƒG×Üã 8 Ü¥yx^6LÆ&Ü<›Í¦'ȧY‹Ãbž¢ÓöL3¯ÎU.)°ü:+zcñ瀟©€Š€÷½‡6âÃàŠ;˜GÂ>¨¦= V/¼ùoñŸ”š­†ôOn¹m!>AðE‰Öµõ”zZ7|r×ß„Nÿ5WÙ:®hà AÙ@_¸+HÜZYQ˜%àn;$…ƒå$•ç<+oˆ­Ÿ =ܵÆÓv‰ž§¢5£1ïå‡T}> `-<|ÿ¬°Þëò´æ‚„ƒš F®ÖŒƒôª¿š˜8A‚ãÆY\9§ü›s¿^1ì*N‰?Æv¥à¡ìMO»½^îÄ< fªØBÅš0TÀݰxà¬q‹šP ݆ì§VLOöû8àÐYÛS/-±G’A°fgûñ òðiMÎo õׯbr”ç ×ÏkZ¿È4†Ì>W.kM˜¹†×\ɾÌ!Êa)`ðižs†Kb´ Ð#P#JÙªÂuøçér»¼ZÙ¬0A`•¬ìwÍi^Rp¤Ï@ô Ç OÌ(;H_úÑ%±Q.Öíõò>¿è`uÜ®xM ¼šøœůk’LDîB´sŒÁmšÀ+Ò¨Y¼Ã/ïŸ|sò|#„§éy'´¡è»‘pûøïéåÉç÷NîÞûzóêÅë‡'wÿ±a'w¿Âÿûü/_À?÷~»ùÅÉ—÷6ߌÃϳÃÏBÙ ·ÁPRˆ@°cèØZ'¨¢¶ÊA^¤¯aŠÖLø°²QÞn,r=©´Êª~J˜íS–‚ˆ/”O€õÆ\€ã)#©{¬STô`°–E'qÚs…vF£\Fê 1¡Ù$6zœ¹Î,Õº>.¨*œÛ'‡Mg¯·bf 4`$˜WÌôl oI>vr†žÞÕ’9Ðm{±¯ŸHŒøÇʸBر|ÎÙ¾êÝÛ%%B©žÖËopô+ãèÝÒ"ä/;˜¥¤­ë×Ô ¡£›“-°Š4Þ¾^’n‚íU›â£ÏUH/ÂÅ{ÙL¬vÐoÈÊÀÕ™‘ƒ6ÖXÌ‘"¡¤ÃhçK:4^Ôý `ˆ«rÙ$¨Ó)•w:WKŠ”›ßþwDZ|O‰6Ì›QyO£p?Ï ™Ãûéú[UhÔç ÚþËð`¥:B² À? XATœVÔ¼ gÑKª¨ü¨<-ÕL[ô¤pe~SX€?Ýï»CMýL•¼ò‰@KÈ%ùÀL&ðŠÒÀ(}§÷…“†ñ8+NÒnÄ<+˜u{ñ8f1怑‡TzR†`óY8÷ÖÁæ³™¸¬à ä!Œ0 í|$0Óaaån8×çåÊÃA¼»·– JOBõ_?DåP}hé£{‹œ¨ÊQÂÈ–å–^Ž<+xŽài`äç~Þ¯ˆ†&¢HÆ ¬±àw‘8:”§-ùÉPÖL´&ˆªªÀo/Û6%óz™ ]RÈä·p:“ÓC@õ‚ŠZ×è$¢ì:º Í3û*†|Up¶Zy#Å[T‡J&}ýÇ:£¬‡}aø¯ñ'÷Üô¯Rü“’ƒoHþâW.«BªÜtºŽ¦`ú>ýñ €&FÙÄm¯Âub¢àœZ!슣í|AÉ ’‡—˜ p“’ÊX`[áq“ô¯4Þù£@pKœ¤ $Ç|ˆ¹É`‚·N3ijÖjãQòŸ¨™ ø3@£•Oß‘ ˜ìM“²VÑ04P((#´ÿº*(]£±ÞrÙaRWÆC›˜—Æ5ÅÈénNÉR¸„.…×Îòo¯–,ëóPƒ* ²qY’Ö¾õÇñ*P!EKqÚ*å¿.¢ÁÊ(»Õ…@ßijq’Q `VI¶:]Ë‘üåjW|Òb¡±HFyºÂî<¡p’W«kÃK.$Ðy8`-Þ¯«cS)° ¶7-›—F,€;¶Ä³©–KÅò [I6 ±J«†AéJ}ãô”.g](ãËQz(éé¤B˜½êÙ³ÃaÎUiï'Ðã©äþà: Œ¿™º8þ †Ê¡EVj)Ý¥{DFç ŠB”‚ü¶,¨{Ôƒ­k7+ÈbÜ›uPg«¥úX1{3eÝÇns=î)fRhð÷Òqë*¤RäŽ{™z„"7Á·êެ(Ò+é*Ÿ¼Ô–ê`ñ ‡žéÚ+OµµÔ_F]ÓQ@° FÈVŸ¥þõAÁ’q“É‘œEVZ€Ey¿X(ßFTŠ¡£tÖƒJÀzÖŒ¤zAh8—vá)ˆ–\ú Ò†*ÇÃ@ýöp¢š²›âèž0ëT:Цk†1ê»Æ:¢ïŒÆbåÿ+ù)õÎüîH>IåûáÛ ÄT´Ž¥²þQÅÖ2ª`ßÍ®zÏ0Òè‹}JÇw2’fóïëžÄTI»çº”à¥ô™H£?ŽJ±r¦ŽRùöÁ•‚Òˆ’a”*vÖ…IþH[£ÒU‰™ õA;uy©HeqË‚zt_IQ^¬`¶k+Æôï«ãÜÒÜáÄh¡´àC½ší¦¢®+a),ëD*Ç"7¡{aÜx¬ø&”RêƒÁŸ#îp1xìÃèUwñÛ U(4KY<É…FŠáœÊÐè•Q§:K!¨Nxè@*9&öX%9 ö¥¡Þ‰Ìë J‰oš0â;ñÿصD쫎"1³|Ë!kÇc¤œpÃY†0‡*ᬵð¯[qûaö^[€•`r¼‚ui Öõhc •âïÁàÖÖø$°ü—töÞ‘PžÍõÎÝìÊÆ*¢íF¾¯RUñžå[ù©‡nP #ÁàÃêÙÊÚªÚî:Òyæ«aKoÉ:,¯²c…5µ‚ˆ ñu©Ö‰ã&È 8¦T‰­[g‚Î;~`2\$š¤!gk‰íßtô&8Û ÐEÇ•]3")Ù¶@àeº·ZÅe‘ðŠÔóJc{i!†AX€V}GXƒYá:µ³E­ÁЧ÷qlܫϱŒ‡â5`”`ÂM6V½öoaåž4~ª›†N1Ç@^þ8\ý½*Ö‹=£L7A¸”žB\ã†êÙúFê[Ç·`,î“ñ½fîÒnþ>X6VÄS¸‹:ö»Y9Øeþcœ´ä½S`Ïß©‰ª´ 䆰¾¯ËÇ€#R?HôCmOÕB˾ҒÑ6;•ÜÏz³ÓlK7Á»4;ÅCt»Eš®…EÈY~Húà®zKëXÞÞ^cÏ—=>è=¬òâCßJ‘[ËŽí§07ÚOáË$5áCÇ— ô?n6ì§ð!÷aÅg^s½Ô'Ö‰؉{ÛlX,>švn^VoäŠÂq1±~Âã¾j;íöŽa”RŽ+ÄCADÃ'9¬“·Õ¤˜È§õÖKŒ<‚uß,ËÆ\1ßH*¡ Ku/fœÌKXYuvcÛKmKÅôH'®ê‰¢Â¹¼Íß#‘Sò}¶[¨™ÃŒ±^å“ßuÊ™bL³& VÇY—߃ûUxw§üŸD³ž©vÀ¯´æ5Ï;Ÿ±8vqš7‹AÕq*üÐïÈáÖ>;È]ü/7´C®þ¸”z¥â§È Óåì‘]‰Ö³d‡$gÿݦº˜‚&Jxr©Â×£®Ùg²ã@ŸÝ¡N"4÷Ëh­*îŘ[-Çù¨¹í(€‹`•Ï;V”Â:ÌW«ŽøÄ¿q îB\b‘3Ä+O‹™,¸›}ñð"t2Ô¾öØÚn=Q2ØMj…<6ë.>ˆ_è”dW¸?ðUwâ,ÞYøæäæZQÀendstream endobj 795 0 obj 5050 endobj 799 0 obj <> stream xœÕiÅ5Ÿ7(¿a¾1ƒ<í®»ŠHHœÁ8€% DÑÚc{-ïå=0ä×ç½:_uWÍÌ®öÐ]Ç«Wï>úÕbØbÄãßONîÿÀ„X<¿:ÿž¼:`~È"þõätñÙ¡fáÑàFLJÏÂlaøB[90¾8<=øiéVjiWê_‡Å)v¬¦60 ³70òóÕZ Æ8Ç–_¯Øàœ•nùéŠ/¿[­Ù ¥2|yXÆ|ž i—?ÀSËúÍxι8[>Z­ ‘NÑ5ÈD²å|jßó›ÕšÇgðXþsµ–ðÓ9‘æãR_ÀüQ Œ.ôÕ mè’nYÿo0€ó —¦ Á–Wùȸ ÙŽ< Å,‡Ã! *Âb9“8–¤r0AðŒû­ιÖËW|G¨:,“&û“M#èܰx5¬àÂñàd0̹p­W8_)£ùò6±¸–]>]Iøµ|’½hà bùAAQy{w{ ¸µV¼yì9<>+ããnÖH$'á¤"À[‡¡zÔÂZºqPRNv9Ikçy7²Ósø9Âá­^^"q!÷àÜ”A`#ÚK<Å%\¸‰Ó M0£él‚ºk– £sÏ`í02)âi¸gnÇ8XЕÉ~‚5­µd øÓüèlÅ @Í ,Ž”À¼±‰OÃ*FK2…þ¸Lo=¤áíeŒg \çMŽò[/)€ÞlP_FÃc¾¼@ðц=+ÃÊÊ×åáYcAOÜ<²–h?/ˆ'øÇq Î%Êë/à#|SPp’Ç<­ŽƃßCùŒâ‘-?uD÷OòÄão½#Q¦úóÃ4òœ"2=¼ÎÏZkžRXÓkÝ‹Öt¼x áÄUk¿£ÖÛò°ÉÏ«üóÏÕƒ+VѤ„óÛ‘yšŒÔÔ¸×âCz×ð†úi~ l•¨»}í‘r˵µî“œ²"ç„Æ®Ø¬©fÓ"ÃB/Ë.û¬w,ÃÓ'-î¦5OóÏ H [JÄù½(·z¯ÀrÜ{]ƾ¸#AáÞkmzU;¹åî•k=O|ïAVõðýùž¸ªÁ —w—冉–Úãn"U]´F^´¶ß¤ƒ™ÚSNÛŸ·îbÞGùýayÿEùù ü|˜ŽÏ'RšˆÂòÄÿ'Ì’~¢.æ/YÀm¿IügnÖÄÐÿõ+ÅvÔrii”¿Ûû­k|Vaï.ì æÓ °DbøhÕ » estÝz˜···Øó÷ ì”`£Û/¶S¢»-žøSÇ!†"5‰ËJp;1ÃìÀñÍÊÛNn!9`gÅg±ôà0qÒ ˆ›2諃ÃB$Ï[ନR!n'q¯ë´ÂQô›¦ñûäLí ¾tSw³Ä––ÁÊÓÀºÏè’Œê£äp›N„'!ãÆ‘x€wH+pK+Äu4ÆÅ ¤Ó(Cƒä`è ÿsæ+O4FZPôŒ¨ã8]lÚÏ£‹GŠt4šÃ2­ei¬?©(Hç!~´{é‡91†£†Q²‰ÀÚ•Â-TKå´Ô6™æ@¥l@â=uêÁã¼ü9ï¡Ó\î/ºöºäMÄ›£<˜bduB­¼La)@êëT%ECŒ1fg;œB'‚Ö@ÞmÇZ}Þ“@;‹½"Ì]ðÇþl†®hËÓ?`›Ûâo6ؾ¤HGV~P*OAD‚»]12‹„ž3%bgÛù¶­bw)Œ4¡zÒÚÛ¨hD*/gqÂÂk©‚piÔQÌ¢g8 ùÃ`|’<›„›g骔ÂpŠ*ícŽ[â£H /ñ(%,Á)}þºuÚ[øô­ð¡Wc¬/;Ø-jsÂoWjÏ(w/ú Ä.‘ŒL-³2ÎsôÞf*?nÕ“*¢Ž¸©ª"Îö%qv"›çÕ ø´’ò!ªkt›3‚"†¯P)zõ¶B1©z,EI<³–ë¸4‘2$Ÿ4¯ÎÙ·X(egæÒ k*pÐófxY=hÛ«žyÜDè¬ô€al|\%e5#5Uò!C-£<÷"4Déœ×°V1ta‘g]‰Ž¦º=wv+0lŒ{Ø:L,9ëe³lÒOA‚C¾˜©mTˆ–{£tÈ»×½ºe9Ttï”D-Ðpz%Ü©±â1luÑd‘ó@§¸/¨Ò2‘j"¡nÌɱ(㵈ïç…tГ4‰x’ÕÕnÀ2Ä¶Ì †ÎŒYf2+jlÊyU¥W¥Å¢­Ó­€á£BºYÆ+‡0- û`‰/ùù²iË _¨¾nÒû8€0§è¥Ëu¨¢ UZåópmmìƒLE­20‚“M—v12Åé ÷Æz)»O¢¾á µ2wTú¢A.oÃÄ„)|äèÚzE\H âBèÚ`ޝ ÛK±S»úHÖÐÕz4ÉA.‹#Gô"&SÞ¤áïÌ3¿(šf`Ô0,T`€ E¡ðõ ™Qõj –WL˜è+áf¢—!uTsŠòµW nÃjÝ’@Þ¯™€czG««˜&}§± Z÷gäÂ6œ@übŒ3Ó^¯¾`ÁƒïKáN€Õx’ûG³–±g“…Ô5è 9Sš=ܵ5¼þÑõkg~ Ëã›2ü¢„ª÷°x£~îÿ`ù–uüŸÉ%Ç¢ÃÈ×1£íQ¼zwêmV é¤éM£!ŠUyLçÁÀáë¦nNøµ¡\ûõ ›F9ž'Ê›T1zCÉnu²7MŠm¹Þ›h÷"á1vk7Öºlkö±ûÐ@‚ËŒ'öÅG*Gòr™}%È‹¨nTa•(eŠÃŒ*¦ßÐW ˆ Fä_Ôf2 xa—¶©¾ª „£p/î% Q팊¹üy”õ1q—ªâ’ŬÊ;²_$'â¿IwµÈ·8z¬ Üô lø1öA;×Û3…á¶“Œèƒ6?‚ýîÁW 1~?œ‹GŠÅgx Ùe!°×µè=¿KÙæ‡ÚŠª--Ïxš½…Òó(½]5#¦º,«{bDÿà=܆½1^.ã­÷‚Ûñ½6fq þíŒÖ5hÏfêÜÆ.Š•„À l lRYy\žR;Úôë!:ùm‰;«êl÷Ý$ëÌ“™4¶m1-üÓG2 t¾1›ÚwàfõH{¦«&é/ÄÈè¼¶Žé*ÁÙ4ÚY¥P péåv-ÌYHôª­CoÃ]ÒUÈ0hðï£Ê½=µ#[•Œ]¸´åÈi™Ô°•}Fº»¹¾žÍ;І#êS9¢'Ñå’ØÜ‘¬ˆ‰×Ø)¤ —fMŸòY(ͪ½Rm9“´¯.ਬ¸gø ݳ!âÓK#|Ú5–ÓkS¢Š`ÈÄðv;bhHãZæúrM]ÁINjKÂýÓT/.ú™·Ð‹ÀzœÐðÄH¹4‘1Z<“R“|Ö0„V®ju=’ÕË[‚”ÓÒ3Ù,džc')&™óñ›»åìve¶÷QŒÁ¨Æe’M&™Z´]e×OK;•þ­ÜüH çì h 9_•l:Ð~fœv¸)|ž#k)•*%êΣEÚíÜ$6Ü%µÑÒSÚsý]Û—ØÞ‰UTšÎË%BØ Ó¤Yk\RšÜƒÊFðíN\t£{y²É]“¼Ž¬ä`‘ÚR'ƒõQ!ܦæ6´ÓÅ»i ¾èÂvOÒ;é4ht•{¬Èš ¤ŒK ’4 '?³U޶•Â|Å­“›BÚuF ¶fÆ—›ø>Ѹd%h0-y¿‘¾bôC>ÄÇZ ç¡R!àR"“b[X£E !¼£wÏ–¢ÉŒ¡Å`ØRñ¡%0ÀZ¡ÓߨDº—á)p¯E ìjƒª!?02Ÿâø¨õU´U~R#hßn«€S±<áqGj§Í«DqÚ—ˆò©A‘òôøÑ tIo­¼%ŠÑa‘  < \æ{Ü¥$FT4Uüy·´Ö'ŽBùÍÙ„Ä*¤ÕÇ>¤¥&òõqGbÄÁTt «I…÷ä[ù“rÑ­€4!r `y‡°ô›!)0Å\sóf?X7×BÌ”0Ík¢ƒS¡×¤8‰«Ý98 œï~g ã1âôî¼kÍÃ>žÞbxÀ*…ß|x÷°ØÜKáß‘NoÄŽõÎøâÜÆl?vö¹¢ßÍ–À"#ñ~ˆŒ¡r4 ªšÅ”á/qÕ -Zʽ:¨\ÂẻnG£z©å¨æL5‚; žRI ·wÄ:ÈH]V½ÛÌ2Ðnò–óâ|Bý ç¨å*øo™¸ÃêEÉû>¢7/Ü´²IÎðIf¯Ò4å0„ôB•ð”®’ƒ5`€Pèä!Q’Ú7©¤Â·7©AbNTYÅvBbÏ8w]®”œM>z¢i2„p}+/ÒoñFȰJ¡f”þ[TÁSL®ª¶3W5çËíÌ»kro*\+•õbnsáÂÊeמY/æ ïR~Ãci–ßÉÝþWèÁ¯Lèä^ƒ]ÊX€¸i~O,†NÀmõ#û î­ëš÷‰é‘òÚ]­å£×&HY$~¯æùÃDÄB&±`D4ʳ—“o;Ý‘(At1¸©*6¥¾’y3úøV„Ž‹X,Þ ûUÂ.›3G·PäJÉÆwq&æ®v± ºQ†}\Šv¥G²Û9ËÆµVÓ2ãÚ:—NfnkàÀï<…îœÂB[º]߆ª½¬¶9OC×±¬°ª¶í„ª2Áu Ã) áÊ;‰1¶‰§’{}ø ŒfßfRÝP‚XÇ8 ×шK3hFI4Îi‰æ:ªá3FTk²'B©åJÕ´~ÒŒ UÒq$´ð·°Ou°?컯öpÞ¥:ˆA›}U}í7U½D÷9M &5eb„¤îýxCÏtËGÖLapÊÒ5:#Å>‘¾)ò&½ =‡ù-éŒLÍ“||Û>}Už”‡¥ÏúªêÆÛÖYÃ_šß[ߪðí³Š´F^Ôóü׿î­ró'á¿C;bÐ$éØÀ“l[ë›Ýbõ8øÙŠ|!|ÊÌílrmÞi帧YO¾û;ó›Ô`Òû÷½h¼^>ŠôŠ€ƒ‡«5ùÖiÝ ß.Ðø‹Ã|‘¤;û*_Ý“´D>“ úUÛp‚ñy ðæGØÊ· âWN·Ÿùz•û×ëo€XA)ŒvÒü"Ê{¶ßü.ÈÍendstream endobj 800 0 obj 5139 endobj 804 0 obj <> stream xœ½\Ys·Î3“±ožu‘£Á <$U–­Xr9>™òƒJQ¤L¹B‘ÔA¹ä_ŸîÆÕ˜ÁìR´(»,Íb0ðõ‰†_n¦Ql&ü7ý}úâàÁB©Íùëƒió%üw~ðò@P—MúëôÅæá1vóØ4†)ˆÍñ¯‘€Ø8¹±^BnŽ_ü<„­Æ­sjôãÈù0ÊÉ·røb«Gï­ñÿ·GJù15|¶Ufø~΋IåG)ôðh{$F­µ~Üx²=*©á‡~Ø*9ŠIêá[üHJi-–Ãq%÷iø &7|oI¥}¦é„ÿÏñW´žÏQ7N¦y|–¦ÿ¥žFðžG©ë‘šF'Bˆ_ˆ­¦­êÒ–r”™òOÛ@+æ‡WÛ#=*¥ƒN`¸ë:gx„ÕÒÊ϶8u!%ö†¾£’~øu{$q‚nêG—ñQ3œ–¯ÞlnÃoy£®`,è«´…'†opm€-;œÃÏ þÕÓ: ½ƒ®°ÛÊU⌉ÒypJÕ¦Nº´þAlK¥é}ç³Ìº Àz ŸÀ¾2õƒç•‹g¸lv4Zw|×ÙH›– Ǿ©³ÂÉJÐðˆ›,mMÙUN²óõɶùùWNŒ°+l°×Ucœ•i×'1œ!÷ÐÁŠá÷*'izÒ‰Ú3降‹{šÛËCéDZ86dœ@0:o!È ˆºáoµå¢tãô”–£É3+½¸-†«|ãI @Œ„v&²¶ÝD&àT’^9®Ã0Éÿ.ŠºqE]»(@׋ý°“&äÔ‘®@<š+ŽNÐi MåL·ì´·H˜–ûBáã­=çuH¼¹ü®ÑH‘Í—Ù,#ã¬éôg…ö T— üo²L+oÒ6!®ñKïA„ŠÖרffC\ÑjsáÈœX“USlå¤Slè« z'ìðßXë,b@ÈÎtV1}¨wPAEÀ”…0¬1³où8ÏÐGFÒèJ¸–‘*>yø³Šv.‡¹‘s.¬÷àF= Œ0 õ0XøÈȾ²žD¶b¯ÑŒ¨tè էηQ0á6^µ ¨„QÚˆ¦K.Y\å¢ò7vTZ­+Sã LuÔ®35—gÆ)«jkH* ÁdTYGæg)¹HûŸoÊõE4ØyÚCh‚¥‡%~礑}‚å$+,/· ôõ‚:Û*a;õ!’xt|ðýÁËR£%Ï ó0¶v”~c%LôøcŸM&ü¨ZÃÏŠ+n`¯`–°ìJf‡Ùú¬Ðøç6Óe`V^Õ Q¥«j€› ¶S­•¢yÕ ©êqš˜ÿˆ: ­Ñ aÑP¤±Pïùµ­Åqmÿƒ=~Œc¸s ÛÉpS-Äçjn1V¬HÁ cØžü8ÕÖª´N [Ò..s!ÔÜ$œU©è¹í$)fœ„Ùe•Ô\d®¢§Šóe*0*k« R ð1 ®2!òº7)¥@ú0Î(lÔ‘Õýgî7Uc0kUMÔú¤ xxöcLʤt3©ç…çºõéºJ¥I BLmͬtY£Ÿ€ä´î"B] ækÍ”fîij6ìëú—9ßãl€w™ çFžL&”Èü7‰„#M|ƒ^ ­h"0jÿ-/.Û.ôâyþ;Ó‹ëD@{­~x£È‰Fˆ½Èòzõ–ÈÅÆçµ±Ò»®…# 6eœOkpä_¶ðg?Qùú¬YÌTˆ{ÎT §åÊT¸Yu2 [ÊÜ*QÅîw–óyÎÁÅìɪ›ì1\>ç`!ô”+¹‹Û%œ& 71kµÅ»]¤—³–Àd_ø0‹œCêùasèMÓ?›ÄZåýy‡¸}v™Œà:f%À¹»Ÿ·M:H`vöƒ$¢{ ø`Ï;–ý)ØSc;m Z±î ç•á˜Â,  ŸÄ\¯K7‘^ß•·J Š‹¡'ƒÚ”`ȱ¹š@Q9ËAÝóMö¤aÏf¨íä Ÿ'.^Ñð‰¨ø¸…âEÀÞ3y‹6þþ":PËà T¢iïŠNû;¢Ñ@<ß?ïZáú2Þçn ®v}º®óaÈ:Ä]CEæ;QgDšçZ†©+æ»´š$©u/^>90ïW]ò™WÜØ|ŸbK=™ùªZ µš)ñ¾ð¶u=S¹¢óµ–SÌéðª²QëSb¶þ ­½ 4z?¢f1/¬õBÜ‹Nºî²¸ +Å’¿8LqˆóThvKÓ–üé{—dDÖ&dE°;âaŸ…º<—ÁÝÝ„er±­ã6:æ+Ë–ô2–l™ÍCXe§}¢)¥-Eƒ&M:5ÉO´„iEZ[ØÛ_€˜Û»~† W22å&œuóÜDÚ›‘œP2¸©Æ³3GÐãÀ%ÑšÏ&™€°þ·’/ÌØ³ÏY½ ¹âù“ò:VÝCMãä‚ÛDÉ=AÔ)þ|ijLá&GM¬s ¬jLßb`n^€hW`uúQ+ kä'Ñ ¬ä-«ã­S6i_²ÙMSN»ÂÐMIâ{ëÉå{[òè!ÉÐ~Úµ§Äa;zG‡ÁjŠ’RƒëŽ¡ÝZ¹èä¾_£M -~÷ G;EÎ:þãIZ_&ç³Å踔§éÄK/r<’#*Q2”MGX 0âiáþ8Jã™@r>X…‡‹¨\öÆQÚÅãýqWêΡn7ŽòŽT ×Ä ¤L ´OrÓ/¯Ú€±ñIÍüG¡— 8~i@fp¼l­<Äí:@K™°*-šè,mžÍ=¬œOwbCh×DJ@Zc\õWü©!B¨—îúóDIÅÒ l–½483p'k¾y´p~Ì› Û} W†f¦]§Ñ2‡ExÁ©E¯?ΦuûïÁ“±Æ°š§÷°ÊrR‘©·h§®’ÎîŒÌ$¥"wè·Å6cðAJ;{_¬è<Ô{›é·w4Ó~´4ûfK¢™n=“)ÐÑůÅ÷ ·ã¼ŒÀºÒR¡­Le]£W@­{5ê¶erÔθŌˆŒüü z_Óé›2Dm_l± ¸³Tî2䤃݆‘-t@uŽå#NY“%JµÆ¡AšF@qqî`¬Ô€3 Ypbrƒ«¤´°('èKö¹C¸¬¯#uk3q¡û%mÔíæøëƒãO^M Ø]TäIÈ¿D ßœÃâFNX¸ê¸È€•Bp³؉Î7]S +~¢šH”]¦›Úäq>Cumâ‰õWŽx [<ˆµ>ðâºæÇš2X‹®‘kËõùUü&øNð˜mBúè¶E¸ÆBg7M†˜_£ž'×´òxá¬÷UÂ$J>â2ÕF€ŒxÁŠvhaMÇÜE•_gžKÕílj;—©ÙIžyÉN®< >D»&nÍO)l1ûT“‹‰µƒñCO¿³ã‰5lŪ›Àk^kq¬³*X1ŠÅJŸÕ„o.SB='7 ˆ¿ë›ÕÆÅáKŒIKqP·|†¢„0ÁÆü¾•˜Œ2<ælˆ+]0h¸ ÚöáÝ [ézY<~ЖÓlsÄø«;÷³ìdòµyu¼°é¼ËjUp[VP܉° ³¼¨ ýbÖ±9^R{é²âéÇh&ð‹ÈR #²Òx©È€æÓÚѤëB¨å´ëª2€Ù]p†>YáEšÝ!&Ú‘ehƒ€Ù€¶¥¼´ƒZ1"BÙŒé×}Ål}]žQ.6íúôýT¥îHƒÀfÙŒ"EÕä#Ù²\V1\\ãTÛ&Ñ+)ú;ç–×|Wq]ðìg~Mà.X§Ž¼üoY‚€ä*~yRPêÔ|&÷=NAIeW—›ÁéÚuÚh@W45˜Ê7bÑ«ŠÀeÅ9ÅËîp 4Û‰Õ£€™ÞFx;?Ê;Ù*‡‘}<àõ†ª“g6’õ²õ{"Ìe­¤òŽó—¥si켿ÑÖå-E…33À»&«Í“FÛÌ"šŒ¨¯õè¬à »WîÛI™3? 0IÃk÷kåD¨(­œ÷d,_UrÓ!‡w [ØÂŠ(GÆŒ,Ô+ofš O—µõuSë”ÿˆ±N¨´b,žž“â¶x¥¦ä·°)«Ä_ä“!áÓòúºýŽ’‡)W0¹á¸$¡ób÷¶ŸçÌJ¤¾ÀRM™œ4é˜Êðr¯OvCá0CÛÞ‰¹³ÐßôïÊ\@WAr‰h¹Ëû~ž“3Ø‹×?`Ÿ$ %Où£7‹Ö´Ì…îðÚ༦§«>Í:)êŸfÉÒ¹½-Y$,±Ó¤ú0ôgJï®úô/Ú \BôáRÛ\ v”f¦jųÔ~ ¯še­ùC\ÃÆ<é}sÞ×»÷Ó•,Èp‚IF¿õ?ªþùºtú¶2üMidŠxO’ÌÉTMbÜð!§†pMŸ1&:­¯PMä@Ȳ{¯º¤æZDÎ}-džŽˆcd6q¹|Á7# îI Š“"þ—½ 9¬Ú³–_6ls¶{—7kâQSð½kÐÌë+ªoí|–>féƒäàÍ‹ˆÛ+=¹Fï†ÒÊj‘gÅ•NÿâM 0…@+¯£…í:Éx(ŠÕ,¥¸C’~ S:L162’òyké ýµ|EPûY fÿójî Õ;½çè[$¼c¿Ü“$ó1¾ëÜ|šŸÍåÛŸ¬Þª=¥£º"ËS¼W1äu†öCkºµšHH³Û›‹»àu.4ÀïYÒäMD‰h¢º¦¶2ÖÿÌ/1÷8íõ?ËNº¡W*»y- ÌJ ‹¯û´»ØìdTéæÓü+»ãݘ±FÊÛ;œ-`­£VÃÿf,øúKaÅ|³t¥æ?§–idôJµ›á·µ“| !‡^ùZ7é°Z³˜AYé3D^b~GmÇMâü^袗©Ly³Ò÷+Mv°¬þöê~ïš: Ù´ÖÀubw©jJ¥¹”Ýž²ì½4k&PdòþçAÑólUäÙîçJ×TQ§HÚ@ƒ¶sm°¸—Î)q½Ó«sBcáÅFW÷7w!èÒT¾,Äöð–nKûúTt¼ó|ïS1^‚k¦Rù|Ê-X,§¶{q-t.8ÀVÍj»É0†nе{²µÐŒùÿí‘¶Vdi»F»Q\é²Þì^|·œ¨Ç7Û5¯G;÷ýÁÿzc5endstream endobj 805 0 obj 4341 endobj 809 0 obj <> stream xœíŸ¦V¥ýö+hU0ì6Àd´K&)¶_ïN tÑÁÐ1ȇdÊ'Øêƒ˜]œó»S™Ûà?µýëîTÃcª|C}ßÏjt ÿÜᓳŽIÖMEÆÿ3tr’*”Ï”Û?íê–q@23ly†NFx 3 ]<¬\™¼/…Æ`˜I›(9‰YÈ8Õ$¥´vûß;9ͳPµó“IóÒ¥é8•Pô8O…“³€ÉäDéX_ÂÈÛ+üñ#|=†ßãß/s£Ú¾ÁÙçYˆíßñÏgøã5þøœ×~ñÏ¿×Î/ðÏ üñŽÇ;hõÛÇ0‹œã ©.žôAH`—ðˆb!¿‘ÖÓNçb\F<D"åBd!§2ï ’Žø½„ÐÙ8ÄQ²`ÒOá±JZ‚­ÏaŒÞIæG;ÛÑA«YFþgìHd€ÕW!4RêöAk­¨Õ0„®V.ƒ©`ÅÕN:Øt`!“$½+|UROÁ;²†w ö]ê9Ž‚I%ç ¹]N ˆ4$“thÀEH0B(”@Wáús¼ /Éô´ØÀñ Mü3mÅ"h_TñL†ÊðöJæ5ƒ˜i4‚ÂpYáDpkèêÊæ•%]§ Ø"ì ü¨o 핹2=$€p‚ œ”dzñ@`PüdÛFtp…h!&%ýu@F›¡ÜPÔ•`ïZ”.@ "ß#šà÷iGZ QH"§:Èi¡§‰ªE]"mšÓc>^F¯¸ˆ‡Evó#v•¨v9«³!Íš(’@‡pÓ1qä:ëƒÖz™$HgSµ…zhz4R;‰8¥ñ§ˆ†tøj- #‡e¸›—Q×_V| îàû5ò ú³Dƒ€Ì„'f¢K^ ‹ñ‘öð0oÎ UÍ×.ÌðrÁR¤‰, wO>¼IÖ]fz±$¯¬×DÆöLÃDäD”>Cþ× †3á÷Ÿ"½€É ush¸ÃÒK'xãèj=àå³úÕyVu,j•ƒ¯Ê=å¼×M©@ÕáYÁCWYdßÑÈɰa¬Ä…‹r4øšŒ9ÄcÒ§œüZÍ!Î#óËg¥Ì”­ræÝp×ÏK¤Ò‰õÄøa3`MFˆ.LÚV5ÊÍÀ­ö(06 ½®Õ(<Ãj>Žô㢾\ѦC"b\…_y¢ñOŒï¯±k}”…y“þ4*WÀªã©:½ämmIíi´)€,²v&Ê7 Þ ç%Úùåßr¥É¢^£·¿ÃÑ@#„óøb嶘è§É±`fÙqÎà#:ªàÁi?=;ùòä‡Ó.ú›Ð#³úÊõ˜Š^¬Ÿœ<~òÇͯß~wòø/qòøsüññ¿‡_O>ÙüÛɧO6_¾¯o+úp5…ìßlŒ8P’*T4¾ÚÁB‚õ?;™( ¼^ˆÂz3-Øy!(І‚£†ÁÉOº93$•ó®~=²ÿ@3C]bDF0t$#¦«zøû±‹s[a""zÏ~ëÖTÇAã¹:åņ#? &öêAi?ž!mëSÀ-/elðQ\¢÷Ä«¥Ý” ¢„Õ⯓eàªÈ` WzÐU×þ¡â_:ÙàÒ“ÖRåKR* £ø)ªä(Bú†u×:˜QÀ ®ò#šg‡G—à<º^PDr½˜YúNö€[Š“»V¨ˆ6nTÒÆÏšnõ¢™ËEV-%?5 ºÂz·´9£@œûfKT¥ˆ4Ê&OÉí±Qô.¯‘±>vå~rô·˜ƒH S­‘²@¢Ñj¶ëš/,‰À£ê2ZmÖé‹ð#.îÏ« ;É Ð’Ð­ç |Öco®¸M´3J àÜĵÉ3K¦%¶6Q—q™:jÚUÖ£â^O“~œ¹~húßÚÒUèƒÕŠ*‰k~Î88øi¥&÷EKCçSX;ôUr­Ôãë]‰+ýÙ?ò´Ã¹Û©ÞtÞ¾CúQ,ü´3 é¹{Û›“ìzÊÁ 3y„vtcûY|pt¢}òfWb¯kçˆýÐâõ˜èÄKúii|UŸÿSD'…%žö6ц»ém÷]k„™ï£f}h¦«]'Öñ®7};@²‘ËÚxÝz^QhÃAÅž{ 9ï­þ; n²%3û¨WTVïéò:Û!ó®?²HR¢±Èømê)<ÖSú"?'X<[NÊn@Oâ6!»"ŠŒ†ðC; ïC$Œäæù>œDÈñÖ§ÙT•ûÿÉæh²ùCmüsëù§ÚøYk<Ü…ä{סu)N]‰b@õÄ5sˆÌ–ttKêêÄRÝRé{Ž£Æ(S –)¹ÇVµ³>Ú©$Ch£‚Ÿ€5úì£GT×fR ‚õ¤>™q¡|¢V ÄŽŸ{È0Ìõ®2M£§w¤~gŸëým“Þ ‚¥`|ìÖÁ¢cb:i#xÞ‘ºsô/ëˆ<އ'¦ÜÒ»I#Vå‰,|ߺjÚó󔆤œÌJŸ¹/k°Jœ:ìi‡cAßÚ­é“;„ ±%ë@ä {¸ s˜£ã(Ü9üf$=õ«ÒUl¹C=$qÙ¿)_c*æ½Âl5‘¸} &QǵéS˜´kà¼Öbß‹l#÷rªNFæ|I¬*"9ÜÀüJQwJgP¾[$bS">ð3g–Žòõ~SÀ4ƒOk:vž¤Åmr´_X€{ƒäsIü¿òw¯ddR–ÂÀoH8q Ý ñ(3¨!EecYaƺB‡çRoã÷TMaò"ŠGs8N‡VâtŠx9Ž^4žË|1¦¿tx°(ÝX– æ‰'-Cõ>hÌ08@YDHpå|»C„Eo² Q$‘ü¯âóP{²âLŽÈXcè÷ÄEøuÞ‡dâyF²Ðr.$Þ‹µ.±–†ŠEà6Deh~Š» ¥¨CÞ¢FA¿ß±dʶ¨’‡ýÃ#9øyœŠvÔXÉìmçŒ Ï®cQV¢Ä½m¤ÁT? >8GIÕžß,øÚÍ$릆ue*€ÄM8ã_È‚‹Žn³ÌÇ2{ãGéô‘Ü;ûy¹¦jzðdí-2ñ›$ZwÈ}’BüÓzr¬ñކM¡ÇJŒƒÎóD H…˜‘Rq}ȼóû# ¢FEbÔ/¨$É€¥ôö¶MGýF#h•jÌîU%Š´–QçÓ6ß/åfap’lÌ q‡ç†w"ÞpòM³úp¶žºDˆë ¦@ÎqðóÙi‘Ò¯9ÙuäBÃJð”\9 ¯L–€H˜ÈÙp’” ["~o;äu™Ã¯ª=¢Ú5σ(ß÷Ð7¦TŒ=3fWl–_p|SA¹Úaà©«?UU_jÑÒÀHš—J–Ѩ%FèÙ¸¬Q=%¾Sâc>‰F&“uÈ {I:DÅšÊr«Žû‹!]¸÷_à;çü¬×²8³ß¨m*Ùå¹Ç'Ï 6 Âs¦Ùv@¥B†8€@¿ñáXÇMfç=ÈԌ艱TÏj¯æ‚€Œ´˜ ¢0­ûÌÆ´‰ ¼9dÏùð\œU¼v6Ü¨æ …÷¾ôî$Û÷fõÎõÑ.XST2Ëæƒ¬'‰÷¼'Çgºœ$jX6åê7ƒ£“ø@$ó:O/NRµï±}ÈÔLÂíXÆ%cRúüí¦üÜRÅÒŠÍKMlÖeÚCíø á¨1Êü¢Õ±ðd¢E†M®ájw³Pp›xð¿Ð%{,+Ö¶ÒìO®++9Š•ÎSlLDîE†BìT}â^bRÕfb·´ìŒ;0^ñì>©S²©wéºÃ¸W•8bë®ýð†§0ФÔÒ;¦Ö”v ûvœü€, Å nÑÑÓËg^ŸÔB×"f²w˜C`"£1«Š¹e}<Õq¾V*¸~ÞêM#fíF'6梓ÀgÉC¢fNwÁüedf1O‹gƒHŸRo±0›ÈzpäÁU:ÐåˆÜ’û =Ñ¢ù¿:®”ç÷]6N•Q‹ Ù×¶®´qór=…/ËåIw',ç>³š°n %Iî9+DÛ[dv%(qÁñ”³œ®Nx‘•hUò«N=Âýh$Õ¬z›{\¶áÀ×Ä6á¶ÜÂ6aÈ (Ì)%­Z×Y´k&šùð, S§˜°­méÊàߣ†t]¸OºYv‰Z[+‚“»Ž@2â0åºC”åè3äóGÍ#:¬‘‰$ˆC8úuuBÔEóV¤ö›½²`¥­D$çÍ€¨¶’ZDúa¶…»‘¦ñFKB[ŠØÍD¥ú`2NÓbbßšŜÜ22Û/ª±»›‹31'ï  )ëÖç»v‘yÉuü—œ½®¸.s@ûT|ü–ÉÄâA¼àL‰j:µ §H_YÏc(×6"^rÎS\;̲¡€)“Ò×ã1øÊäÐ$¢•jüÓ*¸ˆ9Ïq6A‹Éšž•S>ÓF9V¼—éߨï R'ƒXè0ש1øa@.'ÆSæ?V–i%—÷&§œòHy( ô·²‰û¥áÏã꣜7ùÞ '¥lþ8S!×ô[ăøp¿…ò˜(ï7`öˆû5ô½œ 0‘Eƒÿ–¾ 3ï)ËZü*[Ò,Ç·ô´¡ 3Ï‹¢ÕÔ0¼›À#wµÜÁ˜¬ƒã#ù[ºî:gF¡ŸU-“ï1Ø/ó.dÿPáÐ xkVLϳV[mÖîÍ!(U=Ç‘wî̽=Ôù L€„ë ½"#VÒ·íšÏ6Ui¼†¥[*Qxï‘U…öÝU\ÜÖ 2?.¥Xîˆrítš–:þØ´,hO ßc±¼Sf/‚§=WJsfI§HC-²ðl¦Í2 ƒ©5c,[KNAŸ‹™#TwÎQµkÎNì_äøzpGù&ÿ[q‰dn[?»UºP÷¶¯,âÌÚR¯wƒJ¿•ÄALè‰à¼YPé[dÛq+8Rn·02²¹š++̸–ÊkT¬rEí\$/ sp­KP°€Zˆðë• ´›³PK޶ª·±á¸:’ðÜR²Ÿ²çß*¡þ.óÐuð1uöum$%!?ׯK–‹¾ÎZ'…w%EáPz]ׯŸ$íª çÌñ $¶ç"=äÔO—;^°éË7`Ÿµ/J•¾¯w´Ú¦“oOòi­7ìDÊãßZßoÙé°Â u«"bãu%®Zä^6JzF1%cq=þtÏ\ºî<“fÂoMÊ8Ì×x×ñÛZnü–žs¬ýð†,‹ƒ¹áꦉ5¬Ñ¤Ë îaäßõ¦¼Z!N®ýi8º*‡¥|Ô©y¿Ú«;. !%W÷ÎÿŸÞ’ÿ?í5^±íü+ñÿûç²û€Mð·¯]Œç<†ÊV\gÍ]S`µ¶Ž¸ëŠÿ/ùi|ÇÙi‡ RvÚx*c€•_µ?ŠŸò­/¼l‡Û­°»Là\늻Wôó. }LujîySŸõ–C Ã´t±úRpY8(©ÏOßûë×ÏáíÂ\6Ǖе;AãH’‚6›“å¾ ó5cÓ ¹fÒ•p´TÝÉYºâØQsàêB Jaߎ¥<>ÞÕH—š:¡÷›{éÊʃa¼tAá*¼=´4óʼn·N˜/&_» è®r‰·²„c·Õœò T1¢Å®;í^5WÕÕm²Î@f3â<®<Še_à#Ë<$^A¡•Ø&V©îaTSª¥ˆ÷òö*_ø {™.b·¬WÆtZã÷ºmxvtéÁrI9½&Âϯ‰Y¢óØ R¢¥{RAð‘§‚Ä4Ò¥#î9÷=t‹K3.Ï4FÑîRGHÕ(/&Á:Åܹi»hŒ” \xç$c€Ýü¹(+z#OÍèß™Û '¨IÙ'etûýF!£ì*ŸºWýd?b®ëzPþæÛRIƒcªŠâý/£» ëHG¤ëˆ”fA}Zº«µ;Ýe‡8ÿÁtm½Ëj÷æ1ìÜ.Y/ˆ7#X%´ÇKMy†9ñ¯—ʵÊæûòÌ+þ-ÖãuÙx×ùA‘ƒçû«&òN×wN_±+½¡uÜ·/5 "ª£÷Yjêí0ËpÐËNùA¼Ñ2¦{ÝÍ¡â"_kKŠ¢ûZÉaGv¼XJÙeÆVʰ” íý£ c8¹>|¨7å‹%Y'È‚$Ö?AÏí× ‰º—¡÷n¤^è@íEθ„õ£Ö‰Uó,#¢ÔaÛ=•IëÊjvªƒñY%Ñ+{cdúË“ÿÎ\UDendstream endobj 810 0 obj 5399 endobj 814 0 obj <> stream xœí\YsGÞg-?b»ž¦ë®zq„Á¬aÃÆ6–c7b½áÐ… €Äá_¿™ufuWÏŒd_ 4S]]GVž_fñz5l5âßøûèlïþ3&ÄêôíÞ¸úþî½Þc¾Ë*þ::[=ØÇn›7:¶Ú¾`+ÃWÚÊñÕþÙÞ:׫nèù`Œ÷_ÖÆº¶{Üóî›^Öje»_úµvpNt_÷Buáû`,EúÈ™ìõk6H)u÷s¿VðIþ£à¾¨îY/øÀF.»ð%ιÖ04ïöËpOp ëØhº§ð$)¤Mcfÿ»ÿOO K÷(´…mîÃÖìf„ð{¯¥_Âj-ÆÁ0çB§—iïoûµí  ÇlPÊhÞõk>hmî`¨W©wþpÒã Œóî ÀØ €4W½@¢qÖ½ –Nù÷ϱ¤í>'@s¡ŽòÀ×å9Î3HÇÓGÃt\ÆçfPš¶#†ÑٲŸ£¥_Ìiï'”LÀ+iÑFˆzAehÎAÇàD0C÷Û ¤èžãøxâ®»h뢶{ïÚ8ÇÊÊÎËŒ§~EdâýzÄáÓdÕÂÒ»äà^öxæÜ‰AËÄáHoâÀ€ï ‡59%ã²Ã'è)óBO Èu>,%âÄšÃÎ#ñ¸ad¨H+xÜ‚‚ža #ëŽ#WètÔÀßÝ%Ž>’;ò p™°bŽB sãqf8.ó—UyþÄXûóy É66¬ö›89§uvçEäŽVØ×ïâ9ÎâÇÞºŠôÈ2F›¨àHíçH,ê^€iI&)L]Žã‹‚-ñ~s›Ü+ãZâ˨a*guSˆ´Df3SfÚ)PÄeH¢®g§€Lt”XìÀ‹ƒ`zÈê±Íˆ‰Œ”ç¼àãºKã‹2!Ñ9mcâ^­ZDJŠhüž:æ7Ài¡@ä5=â¦\M8<ìÏ3¸r6l“Йhaº³Â¶¸ã8¢ÈQäy© ^^y‹C‚ÂQl™áGáÒƒGdJ/0üÅ&kùo°–_â$}žöplÎJ›ÃÃô ùs™=½È[BÂWý7ñ<¾'M÷?4û@F÷G¢Øƒ:ãÆøC"=®ôµ7è*°8ô™Ç_à+hoÙ"ïúC¹Å=_Vê7±Q®¥ÓäIáÉ"õA¶Â @¼w½’ ÜW_¸nHMb`b;m¸¶åÃ~wTêB{uZ±9ehTÕÛ<†ôBrƒ+&˜ ®Øš©Á‚zwËUîÖÚK×Z1çÝI4áÉþÀsÆ‘±î7üúœ¤¡ßï¹í·ÜÙ?8ÃèBX­¶»³ðÑÏzyjÓ‚6{“ß–Æ—¹ñ,7zO>ã.jåòk‡óÕëÏCÒ¯â‚%Àþ©î‹üø²~ÏïöËØDº¬ç¼,’ÐîîŸ<—­}(0“t¾È­3ççåù‡ÖôåÉF^åÆ‹Ò³ŒyêÊ÷ü¢µƒÖêOZ'èç„8Åšî«´zK—רžu8kY¿×$Òa¸­¥,…¥Û¿*¯«ý§¾¿ö­…áƒÐ«57ŸW"¢oa4ÒµÌGºF œéE+óc3Àîhšw€$”Ö©¿%E/•¶^øàõq`,9˜óp%,Á¶ƒxœè¸õ€x\HY? ç'^ôΣàÄùÖu<,®Úãì/T ¢_p²à}‘è|Dk‘\iöMêèªl÷7bHgë°Þ³)8@ ~gЋp,RPGŽD3‘ÂV>byÉ£ahêùaÜäÆE¿³¦_ãc˜z0D 'ë—žÃÁÕ0Ný¼6Õ¬‘ÕÐWkP­ŽM0ô3ÎCtï‹4Ât©•ñ‰§ðÐKŸH.Г‰\%ޚĭꇮìN!¬D:¡¼óµ5~FÓ#¸ä]#þ « Î|z#*6[ 'ù:(‡€²Þ/½lbzemïHl¡,+ˆ;2!=a‚L‡´"akžö§·!–WÖÃd†š×IüS=ª[ÐLrŽÆSz¼MˆÉP»áÀ˜ð±µÄ#·¬…ÕNÙÛÐ7Èü˜GS¯ØV‚D’¶¬Ò\„Ó9¬ðUf=cÝ›Ê2U éóhï§½×+ˆã´ÇûavÅ•Àè|%UP"Gg{žìÝòýêêÍõÉÞý­ØÞýÇøãÁáדoVÛ{ôdõÓrnabAcn+ˆ/5Î3Œ2äŠâ&Æ4l+1øòºµèU|úu[>pY­ûEeŽÓGÂðèr=ðÑÃt“áˆ<Ïx…QÀK ÚêÈØÎY`rÖU¶¡6‡’Ë 2è™Îpº¼ƒŒ" ¤'·+=‡æµüÑ  #*²¨…ƒŒ §÷…ôuX)Hy‘ –Ô˜–Äi 5³bbçêUáÕÓ^:ÎL: ´1‚y³˜ÃAMÆ?3©ÃhÈ ب¼ã·A$„dpËP4ð¢‡- ÎbõfçMŸÕšfD2D$wBÜ1Ÿ”ZBÜãHeu„÷¢o䟸WϷΡF{ÀX¨pX˜êº¼ÔžE–|Õ0$~!Ò€¡˜æQ‡hk—.m€0÷µÐÌÉt0¸¤YòljÖ[ãÆv„î`½Êȹ[¦‹¸õh¤ªœ¤Œ9É)‹ãr¸6&!°J- °80Q*è·è],¸miÉZ·œ×ÄÁ!J3kÊæKè¤JÞË.ì‰=eƒbÛ¡@1}g˜õÜim¹·G¾†½Î᫬…ò.Aðôϳ§QG2^¦6"kåÒ‘ˆ\•ŠÃKS|Jú ÀÂj¸ÊƽמÝb ÂY/ÆA0£^@I~! šdÑ Ú )_Œrˆ‰h<­hé<²—âmõ¶M7#'ìN WíJÀ‰øÍl§=…¬žgn‘')úJÊÂê´$ª]ó°”Ûõ*u¡  ãDHÎÜ씣t|¢7ãr’3ŒOÛÉ´wF<ˆâÖØëþ¸È äÇ„¸zÍD°´«øUZí‘Âm`ëQ ~<¦Ã-¤"¤¸›TD¡Åsº”H…±J¢×Ò§ ¡t¯Ù³Æ'Sdò¢ÂýfÛ¯W7Ÿ¹€Ö ¦£ûUÈmCk¿h­¿ }Ðj¬±É؈ZÁÈ$0½?¿ 4»¡“ÏÐY7šbçMæ ÕzdQ´½£Äíîª.é_'‘•±ú—A§He‰2l L÷Z^Êqt…#~ÑrA¥s)Úª 7! ú2É´HáUða+ªlbƒIùäb¿+ê?W:±"ãn®¯¢¢O¡ÓQkŽlUb,üÑx×F.Šcž¦¹3£ %^€B¯£ ÏoÛ•‚|\z¶U{áø„ó-%Ï©©õ”¬³è7†ââ=¶jXg7¢ %ap‹7Æ‹¿Rà _‘‡ºw1$䬡W?‰-‚mÀÓ¨-¶]ûô†$qŽWC’ü Ô¸J,Û|˜ø®VC( Ÿ–¤9ðx ;«¦½uÅF´wUN&Oñd7k€/ÿO§ô¿5@˜Éam®ºùÆtàÞÒ(ç/ÔWª,ÕîQ$=_ÕÞ>„£årÄÉLã“ã¾AYñ›èÞÔ t8ÄÉŒSd.M%hIañ än á øŽuL~‡Ó¼T=¦‚¸9FŠeFŠI­JûMÀfZÀK*Ÿ…ç«…ÚæýǢț?ñ:`øYA=MZùͪ¿IQ…/Ø(—JnS7±»)ðY8³a­—¸dÁï&¥(ÿˆV‚–nX¹åPŒsŠÝOS'x|i%3ui«/Z†»µcˆ8lRäê3î y+¹UsÿAåòuO¢Ú´rEEÇ«N1¶ åY•Þg”ßfèì*ãg¬p¹r¼Í]Þ¤Xúró+‰Ç-˜æy‡üYpÚŸQmÂp£ßZhû¦t|”,Ïrã£Òø07~?í·"£×¥.¾ˆÿ§½ÿ=Ž]Êendstream endobj 815 0 obj 4122 endobj 819 0 obj <> stream xœí<ÙrÇ‘ûŒpì7ÌãŒBhÖ}<¬#,K+s%Ë– …öð†ƒ" €! )B"õõ›™ueuWc ÀðÃJA²Ñ]GfVÞ™…×1ÉÀÿó¿Ï^=ú›Ôzsþó‘Ø| Î^I²Éÿ<{¹ù섆x5EåæäÇ£´€ÜxµqÁLRmN^ýÏVîìVÀµ³ÿ{ò8-ˆnš–“t0óäFÿqw¬'ïc”Û?íäc0qû‡Úþuw,'c¬WÛ“6æ‹ôV›°ý¼Õ°ì6Âf¼W*NJnŸìŽ- 1Ñò5ØD¶åc|¢žöüzw¬ò;øOoÿ{wlà1F]æãRŸÃ|¡'Éú÷>yçù’ n[ÿ/0@©IéX¦i-·ßì*ʸ ÛP0ÈÊ `G)qHȵͰ% N€e&c#LÐj’B*ÚjRJ9·ýn§&!,ê¤MšíÏ6Í +/óqj³‘fÒÆ)<Îã|ž@“ÉËÓ±FÜÃaàdô$¤Tq«aM©ü»Áš VPpÖ¯;áÔö ‡:€ðãµ³ÛçuúSx’(»}Qߥ¯ÿomJZÆz»=…µl(1—¶B»¶K[ð4#i_ßà\ oíö+@Æ çeûúOBjåuØþºÓf²ÑšíUÂÚÐl1Y§Uð…“×ÎCMÎIØÐë¶ù[ܨbb—Ø~Þ‰ ÄXv$ <ÖÒ‘ÀI˜ @ؾ>:ùÏBL:F¬?!tcöÒ;\< àˆäÎp „]ásTðôtÒ`…@”oûHô‚9Ž$ðˆÆj€:¥¶?“ñ&_!ôB( Â©´—nûŒ}dÛ¼Eù“&ÂšÏ lö%n „%¦k&>຀9Z(¦¥eHüŒ§â^XÝJ®¹À¥c(t•;]ÈßëE;E'TÑpYh…È{D ˜v~µ6é%€þÁÔÚDµý%×;ÐT˜ãö'"­'q.ŸIžp"ðÒ¯;4$Êûùælá|1é1&À„úBÓɕ㿨ê3Ÿ* ˜®b€3•e}Üîº OgeEd/Óg­’BqzRóS  üÞ#Æ€Ìÿ ‚ruð]â!‰h/êíé¬ 8­»"~`³àôÂ4?`ŒNx6κ‚-\œP€ÛÊÀ…õ¨Ân4ã[ÚÖ@0ƒ s>”ém á™WM¬Ç§­ƒssÞ`UP^ëö ¹lCF Ð%ú÷ÄJÚ:ÇD8‚7å43aETAË8a8p¼ÐŠ(áa«¨™·¶*ZHb°­‡VàÀT>c¬~Æy¯1:ç8ínµýû¶~~Õ¸?¯¥\`›–wž½­{•p–ƒ#©>Ïp=Rwž¼ÚãL’‹6Éó”x\k@¢zCxÚ3Pãsüéï»ú#è° 4…iâä\:[}Ç뜴ïOšX°¨‘­.uùŠ~Dkà#zw.ζ3~gLU­_r)ãy=’»t´nžÏ½”ÿWƒá,©4z×™Zšn²%¤Ñ•`ýŒñsa5ÆULáבHrë çNƒçÏsEÛÍmÊwû)jEt˜ê.øöªªü¤n„Õmö/3 Õ‰aÖæ„\¯Í™F„`\h b}‡²mÐS5+'èD:eiPspþµ oÊ»®ÛÆe!"¼ôÉfb ËGtÜs3s’š±pc„Üàözo´#̆{¾f’t=02ÃI§ 'ô~ex„Á3Ýÿ#¾S÷­Â'b»-ž'5¡Ž”±°øoÝFH ¯úó×’úi©5y%Ƙº½Ì(ª™jMxwzÙú—50Hú¢´Ê‡g ±™ÊrÉ×RsøÁF Qe QŸÃδ=2™O ù i˜¾ 禀ÄKÿ(?EÒWzwáé‘:Hƒ®«ü–g˜àPD·`+%h›4”Üp€ƒ£•ÒËÓöòl0’ ž•^lÁVÏ‘` µ/2\`çÀ*Úí'õó«~"…z‡’(_.Œ€/ë÷«ö½Q欽üiôò}pz‚ÝÁ››Ð×þ}"ß> >á«°ïùåÓÑËëö²m ¦9?BIÓ)tœ¥>$0ljîz¨Ûãþ·Ž«ÁœŠŠü抰¥^îV­@¹uQ A!‡½,)td ÀÅsîëâè;øº÷ØØ§ !¹ª¶Bê!Ÿä—fWf¾ÍUv·&/™reqcÆháo³ÕÎSd%DXÃ\ N±,<À"áoj$üyÂmîœè ìöÒýkæH#ŠÒÍ5éi&½ Ìí½àJ%}Uº×C|äÚ'º¹ÈÀâÕuVAÎ|çW—ÎBuÑòû<:#V÷LU|ÜÕ”ù~ƒˆÓó™ëŒà¼¾eõëŸö:ª¥½M¢ˆ4a.{…8‰£›TÕêlã’eàŒ@²pPI 'ƒ®qÆMȯÀ5lv]Îk5Ö½îÔwb ÓSÔc¦IÃ,e#Q_g5]pêÕô³> êÌÞgYr9 g>ˆy—¢§fòé×Xú†Œ\Іzù¼Ç“9(Ë sæ˜À²BVÁÚ&¦€¨¨fIì¯>Í·70Ó“N¥C©„¾s\v~`\F±ÍU^À†è¬Ý’×—íå«At±ɪÀ<|Hvë è§Qxù~ÿ°Èì]}ù|€?µ”k½?.GqÚËÅž"²'Ó ÀÇ”†˜¿ÅÇ.å–Ã'Õ²\˺«{¬ò0™ì Æ…õµ«ÄÙ:ÉAဧ€ \Æ {­ÉÐð‹ÂSÆ‘”of¬$}ÁW>†Ý¨T52*Y‚wÑÒ÷™i ßµxMq h_œ}{ôz£õä¨M97ÒC¤¡ÂFE‹Url~ýìñÑ£ÇÞ¼}s}vôèûwÅþÚhÃqè-d„W±PBª‚…à¬vXŒúL0*½èÔ;ãV¥°SÔÌ´-ÏEÞœTGæEÐ Ðm׊U–)º¦t Äg}I¸-À‡ceæ8XÍÒŽ2&ûZVbpeR€²`^\¾IÆê±CLðqŽÓj&Œ¸÷€¦™¢3WÑ ñÙÇ@dÝõhœ÷ûU³C{RXûq¸Ë4#{ÜXIÑ©Œ~Êßf“›ÖtHn3Ó/–›%ó‚Þ&e–uñ´F9Aßeþ›:-©HײB‘<»ié”i„Åþ SÛ!³¹Ý£C]\kVûÂÆ¬ IËSp‡Tä`ž¢ŒÛo`Fâ5 :úAKaÎVÄÀ—’ýRKW6g¬›yÇÑȳL׉j#{±¦üD5)°—<+_ãOÖ£=¨[ÍŸÞu"¥~J•]Š`—Rÿ® Àrò´;ôµ÷ò3½gó%6©ÉXïW°UË­ƒ²ªëˆäPÓ§À€¡öŸ d$öWû怟*ï¯­×øÖ‹Ù7¤_Jjó ²q<¼ºŸn ã|Ÿ¿ÌäY«D0Ç]QMouQGWF{cúDõÚ+q|(Ì7+UtÉ_Ÿb›e±9á$¡küªŸÓ´ßû¦fDXú8ó`k%õ”'_šW#J j¡•¤Zx2KUÒ;-©ò£Fü#©a/ÓäH…D]ÚÞ;1`¨0ËÁ[·XÀɽ/Th`Œ0Ž;\7ˆþBõÚõM BRSù·Z3Ž­obTl(s„]¯•vV·ÒAŽxU¤Æˆ&5ÈJL†5Æ/•}×ÅÌ:âJ±ú¹ÃŠ[±W¬K+ A÷wý­Oó¹RúeI•QÌØXzÐb1ï Åa¬Í7øôLPr+½ý~‡}{k]µ(hÖkI„õJ[ïQƒ¥˜µÛ\¥ÅÑK/Uk“‚lv-/]Z±ÞÓÍ9XÁIf½¾@5¥IèïdÔoHœ–!xZARãÈB“3u‹žg-0> stream xœí\ioÇý.øGð›wq4}÷ °LJÇ–›†ÄÍC"™HKJ"#)¿>UÕWõLÏ$-;A`˜Úéé£úÕõºf_ìõØëñ¿øïñó{¿Jí¾º×ï=‚ÿOク'¨É^üçøùÞï°™ÇKÝÐbïàé½ÐØsrÏzÝ ¹wðüÞßÃÒ,º¥ìœsj¡è˾óC'{¿øv¹o:­õ`Zî øhœ\|Z>~¼ÜWó¢W‹?àUïhûÑR.¾Ä¯ÃàõÀïüu¹¯;?ˆÞð^>^ÎÈ->_VýcOŸ,áïìÀo|hèÕ¹ÅqRJkyƒ¿À“ß/•ƒÙ)½øº´'{˜‚´¦•…=\V²½¼íwË´†Z¨—kp‹Çe¶Jgq9áÿ~ðí“ç è¬‡=88¹ uÿƒÈCk%o½¯…ë”ÝÛW}çÄ0„§~\ÀDOñÏ9þ¹Âyõ½‹Wõgøç L¨º^˜Åý|û²~î%~}šÎóÕr_âò½ÅæF ðEÑ8áþy¹ÿ<_¼,Ÿå‹OÊEI¾è#µFºjTzzSdzß ~óšVùþa¹ÿ¦5|Y=Ù—åþ×åããðQ+¿xT®ÎµE (å;a@Ѹq©›üaéœ-ùI5Q&ˆØÄËNïí ÕÛË0Ö—>ÎZáÐq•Ó8'‚Ð1þ¹À?×\¼[eŸõn×Ò‰kálh‰£Ÿæ Ç¥ÕE¾x] ,^¼º.ž´puÕ‚ué¤9Ò‡ðQö¼ßÜÀ«²Ù‡“«øñš?–‘d†¥—¹A€€µ H׉lZÈl¤ Lª- ƒÿOøõ5þyY7A™…»•ôâÝ3üsÓÎÂýañ07|Zò´¥èg-Ù¿á»>á*%ÜÇÅÒÍàß•=ÎwÎ*}-ÍC—šºÜ^ Lü« }zðxù¿ÕÒVý£p î Óø"žú^'ÌŸ’ÆÑŽü"&TúÿÛÐÝ,ÛÁW-4\µfQ Ú²¢ädQ‡M°ç¾{ûZƒ›£‘KÕ È„éܾˆ˜ï—…Á’lS§”$¬+†ÆWKa¨•¤—J°)’]<+¡2»ñ+ ¢c¸,A÷!ŠT×Rà,AOýÀz;„Àð¨<÷,M»†€ÕhSKÕâ\|î¤u”T’rñOŒt¡7Án¿Å XJå F]Bô/!²¾€Þ˜(XǸ \8, Õ܉Ñ}•SÚÊÊÅ‘¨ ò7ÆGÙP„ýy»¿ùu8–ƒ|¤ŠÂGôdãiÆ—åN3Ïò"˜ 0'^eÿ¸* Ñôƒ-‘ÊÆiÇ`.h‚`w0ìY€R‚·Ae£]QG«œÏ“ nUe)?@OìñÇyÎW0{k…bõA´ÀbGŽm¼­¶:n«´°™q[™ÙVÛ-ÉÈåÈéÇœ/6°½né ט4#P/q14Uão±‰§ý΢ßÅE[=‹#„€­ð˜o3H\st€(D@šŒ±ï´‘–¦µÓ•R%ùdÉù–äâÔØŒp4t=¦½l˜ë†@ò‡Ž°+=$µ9Køa¦= æÂƒƒÑ„èÞÀöÛöR±Íx­è&ÂZûäÙ)-1ד€Kgã`ƒ0yÓ„×Â{ý×–}pp¨ €Š÷´öJ&TÒ(’Mᬬ'õ´ ˆ¡öÁ÷—†Áî¨,õ8#ð"(¸É#ÅqY«>C4~ek-náŸfî+Âd´"êÌØpå–Ç(G­4a:=s\YõWhŒq–¥E@†•CŸòòÔ ¥§ËÚhÐBc-l$Š2>kÎr>Ág«r\ô¨ŽÑœWµ®‘b9a+½#ôü{BÿIØÛjĈ4xä‚õë*79a;Í ëÇM1ÐõYnpœ\dq"È™ÎEÄ(áòþEÍŸâ×›mƒî°ÌÝÛÄ à5­ {ñmqqšÞÙÆ>Ž,³Ì¤sÒPd¨²Ñíø"˜¸È 3š/nù* Ÿ{D£: MǪ̀Àõ±M‰Ï'Åù‘lll®3¾£1|¶ÄOÎ:Îü±H„‰72Õa¼ï jQÃFQà„ÐÛq…A ”õgÅX¤fMS˜M`0àAuݬI Ê ">™B1ÙgåƒIhˆnÌ p£†ëíEv ¯K|Sâʇ]JØÌÓjæe’!å ¨cž£ÚbE[â·Ö'!Õ1:Ä=Ö–öxSð¾#¡HQXïa?iØ<¢ŽìÑÐCkpG qQŽï `ÜhÔ5#Ò¸ù×-Ü2š˜ü6¥ D½ž8e¯“Y¹sâ§tã(Ó)#öHí ªÏƒNˆ ËŸR’Ä£ŠÚúµHŸ»ÌÏkãiŒÌ烙¯óÅgiÑäRŽ~×ìÁŠËaʼÞÀ—oâ ÑÀpp^øš'‘ïA";›ÇÜð¤>=ó –Q5E—Ú¾lrG÷«É¦¶l²o+ÐŽ¥8‡Š†•¶³c*ž x‘U2ÓX>€±hÔ1‡G„nÞs¨¥³¤ŽmÚñ~K¡ž¶¶”íóóÑ–ÞˆðlŽÜdšŒäö#—mÜ@OG>¬Ö\°79ËïøaB¯ç޼¤VìÜ/áÜwÂöç¶#ŽJŒ)¯(aB[›Ñ¦Þ=5i„£FTº*TÄ(ÅüR ¡¶Š‚ó,vgÉ(ÿîŒ%Sà™ÚÌ’I3nÇ KQÈ]-åP¼#š[ŽöóÆl2›¨ÆÜÃ> ¬„ÄüAµÍ/º¨µ²ð#xó¼fU¦U¾]™^‡³ñ|g˜bÔ~²Ž‰â™ÝlLD÷u*²ÃZ2&çª M‚#äEi ¥­n®(ãéÛPûJ;RÉÊA€‹´_pëÉb£Ä´@guõ A 싚 k±HŽ ‹–Wù$¨*»ÍYIŠ|R›ùÒåaB/ƒ-ú9-ɯ0X³1JÓÒSÃ/¬jÞV>ÇOÎWçãí‰aJX¿,A’Z{"J(sV°@’5ø i-©Ã\åWø˜I˜Û5jÛU†°#R˜¶ò“Òtu+¯BÝk½«W)K˜Š¡»Wöh€y(Žs× F)v>ˆHWÓÁ}vÖV®ƒQTºNAº©øãrÈWILµ˜áœÙAGX$â[«d»ã–An=. œ‡…ù¼ŸÏ*“‹ü¸È‡#l‡ mN ß©ÊÃélÊPX³»n8Üäõ€ˆÃaÃ<œŸ9lž‡!ý¹8„ ‹Ÿ§.ûÄs^åêS<š¶k2Ìx@ÝôaN ©WÄBmÅacN2D#ƒé‘Ruæãð)œm ÏÈøe!H¹ø ^ˆÞYv‘å åb©B³mq#ÂÏŠÙåG‘™«Ë[™/–C€ú¹µü[Úbik÷u9ž‹e·Ǧ$ܬ¡$ê´MXuÎMæSú›äL±yþÝâN Eó^-"vؽadgªƒ)óÈb‚é±vçÄ 6å0`×gßq¦›,~!ƒÌ8–Óü=m"5$0Zv‡1›ß+„ÚÙi¨`•¹Nµ±™f$-Ïûd8I/`Î"} —nNÈ(¢Û‚‘¡j‡¾J޹‘^•|{ô‘ì¸a “«AúI€Ãè÷*gå {,YÏÄp­X—ŽÑÌÀ¨Tv0Kv±²•Wh–Æd4 NÂõF*T׎XÉI7²Àù”f˜uâÖÞ**£ÓÒMîàtš!פŠÂxvqB•Ì#“:­14½p}T² ³ÈÞHl`s’}Ç(!.1̶Å@±ð8XžÅ]L¸H$.ÜLd]Œº&ùªúë9ž‰[¸ušWšCan/²2§ØÔ‹ª ì¡Y$²TÂ2ÃI͹°»1iÅì%­ó§%I?©ÀÝVð¶¼^Ñý—1†ièi<­&êvÉ—qSÅ $³ñeŒæ7¤H›RÒ)åOs«i6(®¾6ëãp·N.k¢¿Îœ´ ™Ó f™_H§=›N¸¶Gãß2l¶k³©|Sïrâ6B­á©Q8|"k‰'hÖÖñ Ö¹FÈ7Ê(g3ˆqÒ:Ç›;]CÁ€CÒ¬¡ÞÕ&‹õ|ŽæSºŽ¹«î†\{°éhÅäL ¼¼ðÓWcùÞœj¤òùÝ ½†¨[šîÈÐÇåÞÆÒÿj=Ë«£¿X­gbU•8ý/Õzþò•Sa—‡XM[ùц“ù1ï äo‡òÉI­ç6e”òG^FYj) /2П/ÓÛ·¹`”u¶¦¸ðöe|ÈwUÚXçó…w]:Ìv¶~ó8¢–V‘Q ¡ÖUÍV_NTáÝ]:I•9Uѥޮ蒻ŸhõOÅ‹Û&²MÞ§Ákb¦œ}}ó!–ÿݶ .GêðR‹FA‚SÑ‹JsÎfud8µÁSùï–tÚ†ÆÖ߇JAr`a÷•ñ'ðƒc¹]Š“â­š …#~ì{¸ï„6g1lÊ:èÇÀ'ÚͲâ%¨˜FC!6' õ}3¾lÉ FbN$SW½“‘·G˦¼®ùúçÉHC2DwHšo¯ÝAžDiþ¶%þìÕ¯`]£={¶=7µµ­e˜ÊŸpÕŸÜû3ü÷Âeœendstream endobj 825 0 obj 4613 endobj 829 0 obj <> stream xœí\YsÇÎ3Ê?oXÆhçÜ™—TY¶"+Q|ÒåJd— fV¿N;Ƨþÿ><›<ú–K9=¹štÓ§ðçdòë„û*Óø×áÙôñ¾¯f¡ˆ¹ÎñéþËIè€O{15V1.¦ûg“3>׳þ¨¹þiÿ¯ØÌvU3É7Ðrÿj6_HÖ÷ÎñÙsΜ³ÊÍ>‹Ù×ógJé^ÌöK'¡T*;ûJ%t;s0ƒr!|öÝ|¡¡ŠršöA’!Ÿa©u¼ëý˜Ïç Ëà?9ûç|¡à«s2µÇ®>‡ödœvô—9~ëMO»$ó&“"ý„`BºÔLJ>ûrž—Œ’‘aÉTÒÜ ‘s¬baæRǹXÁ6€n˜ÒHÁxÇ…Š !Œ™}?¬ë4ˆj¿4ŒOS=Û)¹¤Û¹p†YÕ‰)…õܹ°¯?ΠïÙKüx×8T×q>»ªœâÇ1ŒÑ9Öq=ÛË©Û]âÏObEîëüä¶ ‘c V×Ü1ܱ³ü|Yž¿Í…G¥°ôtV a$åzø¡f†NiNnt.óÆþÉ…§¥ð8úá-|··ó 5æu5&yNd‚_•´Q¼ôa5$@*hHê»×¬¹,=¾myUÉ9ÖÅÞRIfìtØÖPåGyŽ[lÂÇÓ¼¶ñœ¾‡Ð9~,ñ£ì9Š7à/ïn`x|Q-&ž@Ÿ¢óˆ+‚&‚4Ë"¸Ì6^±¬ÞëÎBO½'`ÑÝIS/KÍ‹\ø{),}·ú$à½ËèÜ—­æ¿7a^S¢f½éÀaª)±‰×½ Õ¼¥„øN3ú* ùfp.©àÆëÙk!èß»C6Úó\øU©ùe.|Z 7×Lœ?šÎA.Cñpä²;sr«9¦¯uÕ¤®y–B  ´ ïê²4¸¥‚ Õ0->0 t{þØ–íVü²5æ:Ë’—¼…A !žÁÆ!Þî- ‰ö>`Ëò@qÆÁVæå^qÆACxïÃ|¼×¤ÏyþcÔ‘á·G-ᤲ¯Dûˆ!"¤Dô1ïÇMnGÔ³X€²‹ïòÎ&Í$ŒtÞß‚Ǽ¿3^µÀðºU3f]îY·`|]<àñý¯ÛÝ̹Ï'û{/‚J^dv:l«ß½ÃT'  p™¬=k|ƒ'ZÑÉ÷E´;óã[¤»¯äÃ'|Þ+ïÒ¯OP½?e'çn ÊxD‘³“ªnAÚÁ÷äm-{/0Pÿ'ï’¼ÿ§O’Õ”sæ4D•x†¨`ޞ¥bJ%°ºyǤs½²36ç p]Éaao lÁ¹¬w³æ$PÒpt¦°¢ÑÖgWÎæ¾ó ý7¬ª¹²J¡ª½Üs¦¥é1¾ŽiËQ’SÐBÛÔ}Ͻ/%e}§ñ„VÁðRZw5ÌôZÐá_§ÉŸû‡È·Œ}…G´°Y\ÕÁ;Dã¢w}²Üñ—w^Ó1óñEÉa"Wx–«µ…~qͪG»ï#˜€r8SÛ†-M‡{)lŸ@}xíÑìWÅ´RiˆÞ¯+¶ñ06ÆöþÜ15?M‘V´— àHÓ*\‹‡Ï– Ff€âV†© ~ðÍUªg(¤òŒ­Á‹µvöOÂa`N¿Ããt3p&ì±}ï¥A„7DÓË Q&ÂRX ?ȹã-Á‘qÅG­hxLϤp¾Î`ÕºgJËd8˜l.ˆhÃI#\ ª¦vàHìö+NªçIÄOl×Ô Å°^Xò ­'¸°ÛŸçÖÇá±6:"Àiå ƒÑîDÇ7oDÔ2ra—_›·ß‹*dF8C‡hª )m]Hw+¯иËXIhz"èF%ß÷O2è ® ´ PýP1$ŠC\¼%Ê+#“,($… FS– ®é­$yï,‚Å Ðkj™pX,¾÷È òõùAÎe53 ¶H‡*öhõ8‚wpåný°”?¼×k º½ üDÜµŽŠLlØ–ˆ¦ÙbÜexþQÑ•¢ ¥+œÎ“ýÉ7“_§R2ãïDá­¡©Â]4v*œöžM?›‰ Ì„•€™†2Ã9G’Hz‘dµnY;~‹äµ2÷Ú+sôøiÇà(Üu#Ý H•¬|«¨ÇjxZOoÔpjdyM•ö(aßšL÷0–e9$ ‚Ìx͉ðÊ2à ö÷ÄÑ2£„ÍÅ,*ð²v0ð¿kô@ÀK‰¿”΢.®Kmi2l<” ŒÞã°rnb]+³0ñ¼'.¾6®#›‰"ÄÉÿà®ÑÒ„ºŠàÈn 3õ5ãÆI©½³ƒ?ÑÀ`V»õêá'Qù‘˲0ÔC¢-ˆ®‚¾"Én!ü¥Wñµ¶$µ:ŠÓ6µëì˲Ó1²4©õÀ<á‚j—¶,Ý­÷ÓI¿xÒÊbÅVh^…6nv+ø\6£®Áïêò%…æÎ÷)nÐ{Ü®lQf§Réí]ÿä&ùæ‚ä³ \Þïf© 9 œ‘¾_à÷‘·!Ùp ¼ƒakl8D¥ªrK–Åf¬†LIÔu–Áá ¬xr7Õj£¼e'ÊþX 'pö´ê2)v’ÆBמLktžÈµä/òµãïçÞ7E–ÁŸbuŒ,è€Äƒ9Í\vš¹4s-‚ݧ&¾ÌyèßøðJHlEKŒ|œtÙ„Ô2Ðt/ÉÕƒ2t¶%®Âk=ƒ€þô´À¢Ë¡21+—(­cR­qp0Gd¾ÃÜÛEÍtMÒ “Ô²÷9‰N²ÎÙ5䙼ð»'f˜:åCâ!¼jX‚~âB_%ÄÒ6¹âiùõ¤FŠu_ÎorùQT•7Ò¥"Ý]DÜcHž ?­ä=5ÈD²Òáý{Kƒˆ\±à:y]Âenqˆ0êšô+z0» ¦Ã›ö^ø$¸2!ö¯ÁTì=ïI42" ôn«HŽðÚy!ö7ÄO–°‰ |ÆY.¬œæÝüxÙ2>Å) Ci²5 ¬ Î,Ö,ûOöš(Gê´kei”IYš‡[7†Ò·yö[ÃP…leÜ.ïÎEúý‰¨R{ZÃÚ…B¯èÃ¥ŸúûÄYJ‡”#¬P.]§G™îÕZØûçFS'{àøf5(GW˜r@G0Z§c ôW#kb:ÌvmŠé|ÞpWJˆ• Ô˜Î}ÞPÍ>NmFyBœdAÏ0ß AÊÇ!ÄwÈô!])êpÑǤéŽbÖ©vSrÓ€+-©Žw­@BÛä?Ÿ— éuÌá±Âš.&+³˜Ÿâ\Ü)ë¥d0»@!Fµ#Ë“8l…ÌÚÖg(0êâ7„ZÃË€qTÛêLÍ«vd)4™ëô¦éGñ¬#ýVÈ늼ÈbI`5ëüg’¨H‹í;¯­¤meäÃf Ü®¨~Û„d eÖ8 cü(S9CN§\É*‰ÛzØÐœV v²ÅYBLìâã·¹V æo#Kÿóù¾žy}$׋Oˆ°/2£aïDÊÔÉ s7\c£My.Òúkë\±Þø¨oBæ¢}v!ÛpÖpü=³ò*¹)ÃÞ°$%@½<¡µ’ZoLUPQµ÷›ê3¢}-6{íhƒD%9Bª›VF:Àá•x÷³6ž ÑGo0€‘d>R; ÉD¼Úño’=l8c¸ad.IWj÷0:*AUb=ÁQ›:Ôõ¦ÚQÔ€p¸„ÄáȈ;)*§ÈoømÌRÔ°`4‚ˆj£1ó°ÁS'°TbZ±ÞyÊY3^ÿ¤y¡·$PH‰ >ò‚‡!¯ê[|œ·¤¥6Û„#†«…Ôºy²;Jm ÎÜŽ:5° sãE-µF#¦e3>™ß”‰ÅnVAœa\çøQMؘމ)z¤H%oŽVãTnÁË1U OÛoK¼>‚÷ÞrÖòŽ—þPÃí¶RÅ_tòOßÌÉ]žpi!<¸Ê•ýkí¶7]±.ï|¿)…å…rÉæ}Þì»ËE'²œò®Å»Ö«úž‘-½lå{¿Ë<~kÕ$èVtȽŸQ¿þ1¸Ä5ø:~Y:hpzqG‹ì„ /óAüÚywðä§—à JË"üÏU~êóè»}aáŽ*õ"Öȱ\ý$Þ¨åšÜ…=oÕü©@ã¾¢0uu'|Ѻû/:кw"þ€w¯ÿÛöó\¸_Úü#~] ŸDsŠ ´j ´I¡ïùÞîXwQ·Ðݤ°ù¸®æ4Ô\3¼‡»SÍõW6¾™ü¡Ž0endstream endobj 830 0 obj 3734 endobj 834 0 obj <> stream xœí\YsÇÎ3Ê?o\4÷쾸*¶”XIœØ].GV%)QŒyÉ$¥ðß§»çêÙ Q¢Ûå2ÌÎÙÇ×Ç4öå\¬å\àñ߃ÓÙýo¥Öó£Ë™˜ÿ þ?š½œIê2ÿœÎ?ßÃn6­{ÑËùÞóY˜@νš»Î¬¥šïÎ/ú¥]¬—jí½× M_V¾ë×Jt‹,WvmŒéíâëåJÂGëÕâaùøÅr¥×¾“B/ak×õÐ÷Kµø+~íûÎôüÉ?—+³îz),ŸåÌ"qG~ñ岚gz°„!w=ð- 10«÷‹¿à”RÎñ?ÀÈï—ÚÃî´Yü½ô‘¶ zchaí`ášµZK!ïûÝ2aêû^ÆãÀüâoe·ÚdryÙ=Ùû3ñ©ã 0V®]<Ø;ºK µ€ÿíÒ†ÞZjÞ{eŒX«n¾Òbíe߇QǰÅþ¹‚ÅdÛÓ‹çøý86êÅ%îU)ÿ¯¯ñÏÏu—gø‡žþ”;SÛM~ðÿÐÌ'Ë•B2tއÞ÷€“Þ­…´‹ÃÜø´ô<á=­è¡§¡éBãqéùßÜø¼5ü¨4ÒLݺïü¶™KãÓÜÈÎñ¤Ìt>*Á&d»¸È?•Æ›Üø¸4>ãK牱Z¹µw‰ëGÕâGìlÖëÎÌWR¯­*tÿq‘¹™&¿¬œD®JÛŧùñE=Ž!±Dø ?yQ¶¶Ï»'æ}Ú"F9÷Mi<Ëû¥ñ´´‘h<È{e̹ñëÒø0ò®7l¡ëÖB¯Z':iÊÓq~~VI{R±C¾ûôü |<®Ög«2ÆFwÀ:’ À«’\ÜCxHÂ`û.ôAV!—4†X£lª ܦÇçø§Pà4+{ b¾é=ú3˜à¸…û—-8Øo52¦Lúq™>ÒIô@t[)¿– æ"ÕÆz¿;Ì´$ð¢6"{¿w˜éÁ`QþæBOpË6JFI™@Ê„uÎ$™f0Áòf¤?¨÷šN«C§Ï˰ƒM3<ÉÃ2ÞzõÞ¾ Þ–-1¸æB”_µ¶4ô ¦AžmB\dýˆ›`6KäeK\2àš_Þ‚Sjeåfj³ÖÀD:¸Zê¦+íºGU‰Ôü~ÙSØ 40‹6½‚sÅPâj þLçT?e° õ+µîƒï{Qâ T›}÷úø •BÒ¤ç‡á£.œH@¼b¼Osãq%,àbëÆ]9aʮ،àŠË |Aiµœ4pW'©óuéö¤ ”@¹TðE÷ —šzJöøà ¥´ï˜$q”‚å¦eDÂ94L­%ßX@kD¢œ×Aºàt¥áßM¢0 N¾ÌËw86ˆÝëòœMW>À0 ˜ ì@c£5tÎ;¤±Æy€}7A¥¤cqÌÓÀ8«\ޒ󑆽5tô³Õ1EÇ ñŒ¨ø/Jçý0–öᚃ¯] Iس…ÆA÷HeåÂ׃´T™Ÿ¯Ž]½tL~¢m°ë¡+ÎEÈøŽˆ”%¥)²xÔ"/ŠC„ +EØ!®¤šuÈkÁ¾ŒÓÄd&Œq·7laìêQ䤼×Á,ÍGÜ¡³³yì_æk)ú`¸­"òMŠ¡i(ÑÖ¸È9ö˜´ãUCéZº“÷—Ž(%)\“8ûĪàÂÄgƒqœÅÉÛˆ¹„DxÞ,J âU¦‰Ú¢…*ƒñФ™÷cBÖÔŒ<øßypU!b ÒƒK]6R0 ºù‡¬üK g-OØ0ùb YÚ‡1Çx¢æ êˆ7cÁþ=¬¦ƒŽ0â–i‹xL³¬ÉcaRg9fäà¢%øEÖ­´h؃‰Ù2 Š’•Æ´ìMÙ1ªbð4ÚÒX©?ø ¨Ócõ/ôÀ9±+¸hd÷q‡†¼M¶| IÀoà¾ï“Œ¯` Z‹Lh§‡ãýÂ"å%—þÜFù0]%v &Ë´–I”Xí,JEH7+¹#9 þcÛÊ!Ǭº"„çè—‰6täFT( |Vü¦¾gd?x~2!눕]ðõnãGà苌< àÚ¢cØ…\4%=6>ªGöG/\ÎlÀ|ƒöú8%ߑޏ]i ³•õ®ƒ¼–».²Ü¤3ޱaqc¹f¼(ã‘(×¥ñy’Ó5öòiΣ¥í»  ÆhÉ D–-& ;±FôO†H†RZ0>Ü›}3{9×zíèzÓósp¬ zx@Ñÿ=8}þhvÿÑW󫟯ŸÍî?—³û_âŸÏ¿þþyô`þ»ÙÃGóo¦¯"D¼ŠÒcÎ9gÂmÄëbYZî;*¢†NŸÂ(w7§0­);ÅP¡H¢B+çýô–(aw[vÊñ-OÔø#£1`ú…¡k/Ñs@Åuˆ¶Œ"Æö^ƒ[…=ª a2.Èp÷0<1¦B‰ó‚D¯àœ<ƒ•˜•g×:_ÁJÎið­Â' ÈÊ®ŽðV“" ž`®n…Î )0†÷UŸé2;f˜CXÍ)ŒžãY:°æH3òFÑ ­DˆkŽØ0=áê ` ô÷|CP„a˜µf ÄÂ¥‹¸¶ù î8 º  ¿Ùg#9W™íMîÄÎ~©ÒS®‰­…F‚¨*îMr1‘g±¢,á6'Ž9W#ZK~å^Óœ> Óâ±G8JT‡´M¸ÑºÓ7èÁŠ÷7xU댄…$â=Cz:Õtú¨r½§Ïá\°Wïý®‡ý×çØÓ›îÜ<,Z§ìy°7-( ±¹á­ íwt©Pñ­ÚÉ3z]†eæFR'§A0oeÃS/HúV”FJÎÑ`ÝÚVò.& ÞTyÃFZ( 26ÄéÌ¡¹ùâ,8âŽ!*ÇÙX´ ¼Àþp"Cùø:S(CÌǶZ$²Î¦ Nƒtѱ(æô„&Äke^ØL ц8èP/Id€Õm nÓ‰x‡¬]¸Iã¼]¢ìQ¤–tï: iÝ ÃÍš–Ìš>Á”½èÉjl‹¨öQ‡¹¬n ÝmÉBæRÝõÔÀª"`Ik-âuh†æ£#LÂw¢vëÒ(TaçÈ‘ÚÕ:ïšÑƒ©JÒ,gUŠnãùö´Îa<²V™Mà!›6:špnr”. ǰS3« €?S‡âºß¢ .HD¬%‘d*6E²ÌKd(…Ü ë0÷ª¹G‡: # ›ôé @Ùiôê« ¨äµ ïÑËÊŽœk@)«RØJªÃÖÛ sÊ·<¶ £G(™Dœ]4ÝàXMªÑΊTé7IúgGBì”'gÈŽn­{„É„=:x‘¼jÎ>ñ&&ß‹9„©¼7ßk¦Ý[»“À`¬X3Âzó>=pŒ­ƒË½sof‰Ó¿çc€÷­êc¼µ3 ÞÒl­Uµç–•N7}»8“ÌÉ;fÉ/–3 ณXzF<Ö%uYçâP‰Ú7×Är"œÖ­"\aƀŒVL»×¥FÀ_ð€ rh¬†N > ~BÌ~e?96n•>T*ûmן‚—Òé¾ã…wW–u’‹+XyÄÑæšäš³äÕm/WjÔÖœ4¦GÒäµÊÅúõ” ½Í>X‘Ùy«Òe;+o¹Fæy):]¶Š‡ž•Š!!“—uVF]M—Qá›à ܧh Í§IW‚J”cÐ×ëü”Š]B‹)aØ×‡ª”Ü¢’¯'xÂ$Ï8 [ÝŽ%×L„.«Œ4ó‹ø> ø˜k¸ô;¯á¢+kðøß] X¢ïé¾ZH*Ä*F™ÉÓ%(˜>Ýι6ýñÃZÉv¦õ%Kà7˼&/î…"—<¦2Œaòm/ b¤nDG—ÆÛªÂ½&‡¸Ë‰Ê0¦?Ü €—3%,ßÄ.9Sœï«[к>€%ç¶$hoíg‡|Ñèža-sïèbz$8&ÊF×Ι?.:o —NŽ y’çv)ÊU%ïŒw剳 ¿$ [’ÞMdaP×cõâ vÓ^ÀóÁ={žN”¤PÚPÝ”³p=ýêhËk”æÁ|}1Gûaœ(„5ÅÆÛP` N¨š ž›âÞ”dª»?N½`M©¦6YŸª{ªíê:fÙQ ¬ö9)§×sXi˜…©‘dqÒCbbeŒBn‡œ"'–3Æêoj%É•\x¤Ú‘ÉÁYFF•V”Qd,•îÆ ×TKÈPõíì_w!¿P•ààp4©•¸&!ã$ ¹"Í.äN:Y¨èX ‡ÌñfnB ÚÙúf¯™IÉ…m$äA•ˆAW¢e`»Éc½D Ü^ËCÎà¢a^긪‡ÍƒY^/I]a:RÖ†ºPrÃŒéb¦abtX²r¨©eµ·)O| ¡O O Š6=F·)ý± Ç®!|ºÜ®Òë"æŒÝw¶Ê§pJîCÙB?¦¦4¾%ACÀ4;Õ6Ø.Å‚ø úªUYY¼ùÒ1ù‚.¨³ƒJ‹Ö‘ºB°AÊã’â£ÂÂü5”*¡§›ÿša¸ AAP›æ¡IÒ;bv’õ·¥Båt(äv²†Ä;CâOF©utxšNŠr Uª4%·*˜ZÙÁ ¡òDêòa\’òçõïŠW‰5æ¿åO ”ñ«\4% Ž,o’êF1ç º`T‘0Û«ÜÁ»'mÚhñ•é†Þ¤4Áå‰s/vo lGŸf‡d9Ò ÍOíÂÁ€Zz—B¥MA×EÛ„òjør~ZMM€ëƒ¨Ø;éÆ6““ï1£ÅQo%*ÙΫzÆp^9P"Ce룺EåÀÔ¨ åE:Ük¼£ÁÔo]Õ¸GºÔJ2öuQÑšPJ3éë:T\~T?¸$+ŠUÔ›KŒ*UÑöîOq°4ã §BOô2LŸ.¤¶^8¶#…°æXìèÁ±#yu+ÿƆ;°6Ø ŠŠëy¦Nã<•âóè¸ÔüfW¿H'ód4‘\¼LtwݤäÖDˆecàmD[á vP8mƒÂE‡5:f¬ØwÇN:è4¶á¡½QÁ @’qÛ,:êÒOlÆó~á2?Mé×”pÃ3ã½…zó·B”Äú†Ëƒÿóß—¬üy+½_½$;-GÚ¢[;Gú3_¨ñ«úÝWÚvÎÉŸ [P;!Ý›ýN˜þ¼Jsn;&ùŸ-ÓO„ƒõ¨'+Ì¢=cV}Ç1æKõ£äñqÏ&©~ðÿaSÜõe‡úƒàÃã¨cQ¯_JC·ŽB± Äæ É“ÂÆ[À {•BYï?|‘_èÕåoèÃÑ'›|‘Xôö|qCœ2¿·!BÐYÆœê 9µN 3µw×Hô@ЇCŸæ+±®šè³Ãk¸"ë~¯á:ãÄKYãøå[l;löñ+¹ø+bF¥µ¿çÇ ž144ö>õ›±Þœ¶HW%…7ÊØ]dåãõï*kà¸ÓÇëÑ0ì Ðk#¿™ý™‡}endstream endobj 835 0 obj 4175 endobj 839 0 obj <> stream xœÕ\YoÇÎ3cä7ì›vq4}w?Ä€;¶;ñAÃ@âÀ¦H™D‘´$êø÷©ª¾ªgzv—¦¤ 6D.gú¬®ó«êým5b5âÿé÷ɳƒûß ¥Vg/ÆÕðïìà·AMVé×ɳէGÔÌã!ŒA¬Ž~=ˆˆ•“+ëõ äêèÙÁ¿×bcÖ#ü³󟣿a7?6Ý”„…žG§Ðú/›C58‚X¹C^‡õ'¹þfs(­“ë£ÚæóøTi¿þž*v`²žK)Ößo 4ÑÁð1XG6å|êƒÍùÕæP¦gðŸZÿks¨ác*÷Ç¡>ƒþ£è¯üä¬ãC²u³E±ñÿ ¤¤ ¹›RbýMÙ2Èf†-ÐÈ/aF!°‰‡•+“Öâ¥Ð؆´ ÐAÉAŒBÒTƒ”ÒÚõ9Œ£RÕN“ùÙ¤iéÒ‰tœFðã îI*ÍvƱe—‹sVÓàøÁÙLHì_è̶˜¨#ŒñÝs8‹[GѬ ù@!9#Àt'|^ƒ,磽IÌ ´$~¹®}žm€÷”ô~ýø ŽÆH[{¤ÔøžÈ…ÒøÊ¥UØÚã:[ß”EF‘i \°™C€W‡8aÙpï‡2¸t$Ê`÷‰ Œnlj_à@€pz”дåv˜ø6.ÚÂ!6Ç}¨‚  •§iIvL§¼>)œ^yþJº1ΖÞiÔ§V”P40²óF•m 1(ÎboQØf»ØjÎófjG`H--Jy—‰Ëö_àöðLÔTήkë:D93UA)ž”ù'#”ž&r[>]]6î±6Y¿Èö~pVdÖgê–,Í×ÔBq“€ÊWÅÓ…¹ Âé‚$ˆ,Á^ÉÜ@ZŸ•” •Ô‚$ĉ‰óVˆ‹MðqG=J_UuÜœ˜: N‚½'“Ƴ I~@kå´±?­ o?,rÛUš,ÁÙ†±Ä+¦ª”‘Ò 3Ã\Œñ9–:„yƒ72©VX›jÖÆñô D¿äé˜}gçi\ãàÞ‰{”ÊOø)¾1$ؽ]$uç8%ñÔ¤@Æ¡E•‘pà Æýiƒ‹e¶Íóºr!ã‡8{0šñBbb @1ؼY¢g=.ã4x˜KÊô쨑=|S›_U мïðO´˜22(-³U²¯«{Q¨ÛèÏF„—uêm|…(†jAᣎÌÝ„£tUIjPµRH³2ý^Ù¿ê¬íZó ׯ–5íz7XàäÏHhtäÏÜ1ÛÕììרôî¡ÑŒ/“Â`>sé2 yA,ôÔêi8»PF×á²Éîºà-MÝZb[Zx«Vûn,7‡ùH+çÞCÙ¤ Ø9yQuA·ecvU¤wß좎¯C,˜]% ñ6[ui9÷JÅ¿!¸œ}C\‘ñ;.¶Ü‹A7˜¤HÈ&ZabÄgl5ÞÂV{ÞóIã3ì’5dé,:‹‰‘“Çåû^ýähØö‡,$1SB5› èeN·'0M‰Û5".G¹ŒoDKtóÅúgüó æÇ3Œ‡_<ÅJcx¡ʉ_߇±åÇ%ÿâ ˆnNJÛ«úð) =$JÁg\v«òAN{¿h_œ§Å ’½[Þ\ä†e)ißÏñǽº‹ÚæI]n3a~Ømy^ÆeÐâƒËÚêº<|Ùïª7óóò‰VK í->¼húäC(¯ëÃg|x¢ßèvßn‰5ÀÈܼAÔé i³$<«oï•>Qƒ‚[`õ„ ˆ'ããtrÀothwÎ$n­D‹l|YN¼Ï­?Ž,»k›w{Ç_Oæ¸÷Ñ£Š9sô±»hØŽ‰¯WÙr˜ýp—7P£=:.RVßà3çüxÓ„™W1èÖÆ·F¦ƒÏЦ`-b´t0ÒToºÎÚ[‹*X ƒiXèD½­¥¨ŠxjE£h¤g @‘ä¾$Ð{7Gʰ3”è:ÉìøùÙ[k $ÊBL™CôQSŒ¤†<º±/JâJ Äñ¤5uq”$¬Ò|šÚ nSèÔÄŽlC/0Ë}Ìôì ØlÅãÝÇÖI§¦×?=o]£v$îã•ÞgqC(‘Wì¹,¡alÞ6ûZÒÛYˆp×>Ÿè«ÑËuö¼îl½+ôH Çe&h!Cd*K°E0ïö¤ãU&Í«>hƒÝóa+Xò`êГÀfg@¡ô#lEÌч™˜O3T*}Ñ"®÷fðºByí)4N•Òf€èº{¤ÈZŒàl©,¤îÅÑ“ªE ¥öŒçñýr83êã¦ÓVŒ®kû‡S¯:° % ‘¦ @ú b•ʰ½ „«SÒ@a¤8i°¨|T$p¯NäQ\ Qö“6?=YpÌÜþ^°s²ß^+ÝœK›„, ×@YMøMG2g¹¨"½bÚ%Æ®†ìž>Ó¶2ö“¬ƒ¦ÆtATT£á¢ÙiÞÓHú>Ú8sYàÉ1žz1 =J ¼²hâ5ˆWÐX)ªOºßÀj¥2[t?ìuÿ7@Y%ÔG)|ʬhÔ¿"(YcvÍ› “o133ï¹µìHWGc <¬Œ£ˆ¬9xê)Ô3 jð& EhÃøý²òÅÌ…ÁN uޱ;7ÆÅFåt+ŸyF…½•úÊK"º,ÛZ”¾\eZš°l&ð½Ý7¦œ½Ž\ÄåñÕÜì‹ea`O ð“Ž)óf—#ÏâèzÞš«ËQkÓ·CçóO Ñ'"  è?Ìr‹òØif(#>d¼¡ ª»°^À©Dl¸½`€SÜ…×’htÌÕ{qÿÑÆ,aJR4º®}QÉnwŸ—†;ŠðtVU¿ y]À‹Ú„‚߂҂Ã7/y· ^•Öçõ!&×,’N²£Æ²¨Øô×^ÿ§õa Â_.C<Å9¹ÄC¯¯Ú~ØÉXFÅ¡×EóæqHÍÂý§ 9fˆCRŽ{HJís¯Ž^¢ËÞ@gµå,‘¾êmã¼TÌè)ª:íÍYA¨‡Ëø‘ŽõófÒ óœÌ€œtؤfÄB’›9{¬¤|Vø;‹Éÿ SqXûÎJƒr›ˆ7ëàœÝ°óiÁïN¨uñ‹˜ÓÃŒ "à§Õ‘&ê6Æ™0›ÏÐÑŸÚ/i¢ÓžÖýˆçW;ïOsÄÒâ(¹#ùÆùÏOÊúYW[b¦p_”åWtºã»ªÓn«š@ë7QœšWÔÄ‚Ÿ·Ö÷jQ‡Ýâžc´QK›öA~â9Œ¢XJLáŽä,€(Ï$ž3mæÏ9m °â´ÔŽ h>š2¡†ÉÁ˜eºj^¯M™1/þ¤çÞ”’Ç«F9a¨Â]wyïtJÄRÑ(I5(³*I>ÛfmZ]2¤õçGßü¶Âš4*ÛÄÂÆ•ô`µµ_) ôÂbÐOÜðõêåóëG÷\‰ƒû_âO¿ù üzðÙêŸ?X}{ÓQéÃ@Ó”*Ñ«Vš-™cVH¸¸%Œú ;PÂc^Žoá¦BÜ0jìOðVeMûù’’Cü3I|`WòQ2Ó[]Éêž¼œø—þ°]ëlSô>)yE޹-Œ0Oz”®çEoÌÆ5e[L~Šÿ‰ÅŽU¯Ø^c$±8XYEŠæ6žf@Œ)§=ˆ‡ùò0š>{¬AçP¶Ž ±Á–†X²² úu’Fغétto%Eî„RAL Ñïß©»Ð>°¦oá“QÖ‰è\O55àb@Ä5}) n4Xì­‡l®äm¯iM†1PE:Þš¶ :‘Í]–Þu'±úÒ·:úêàèn©PÄ‚©néHƒfjã(Žï)¦.îÅ´.ßB¯m [–¶ŠÌ÷ÜÔÖ“/À Š\¡] °²eJÇÝDt.øu§µ-¢¥µXŽyý©NÖ"8L›ê©p:ðÄ„\v€Ñu[°À|@üÒA!®fU.cœN÷<7pwpÔ@…[Ù/tnP:O‚çM* “kŠÃ:ª.¿Um–›ár¿TcÎÓa"Sk+fèf›飛ItÓz½(¥l!ƒÀ.9œt^!+å»uŽUŒJÒÍÝ:øË¥T*Ö+6yæT¤´+wÝ…hj:ÇnQ³±W2ô(»),i:Û´íaæìªC?…s&–²%_–¤K4åô»âC²"ÙI,O'Ùfô jy¹ÔæòmhoAÏ£5"š–ë… l{Âq†æŽ‚¯£#¿³+¶T5ÎRí®Ã{BÞ³[p‡\\Úçûž!`±Þçš©´¨u¿H¥0Ä› •½ãlŸÆ­õS‘œÑz9L»Ñ)LœåCQÞ+ÜŸ^¼feÉÛ ; >Ðxµ"×mгÔÚ<"Vr‹ Y@¦y"Š ÞQ"%;©œœBvi‡-b'öCìR¹óhD^Šáî’ôrˆsˆ [×z À–òV¥-c¬Zïf"Ûb‘NÇö¢^·Ê)ob‰]©8\—¥J' ¡ÀÉ7ô.úf»†cg<+[[H}Ô“ÚÓ¸m§UH½2ˆ„Úe¬n/R0iNO -·Ö„;Ãòò#Ì· P·’»XLŽÓG0œ3uì_û´ÕW¥mß&}(¯Öf.^és’?lŸ±©ë2Ér@à2»g´+SÈŠwq}äG+çŒ]¿Kå 8T3+¥Íü6Ѥ ǰÆkÊÓ–Ò¾zûâ=§k—öy^ÿÜ"#ô¶fqèyò†Ôîtâ>ÚÙ8Ù,B>0¸ #i`³yN´)ŒfðLʸß,´ÌkBméãz.ïÊ©Ã94µËÃ,G•‹\ß³a¶¨ M;qã²Y†à‚âÛ]<÷ãvëšòpØ®^Âë˜C O¬+j h#1ææwÒúƒtáhܰuÐožp¼IR2²Ķ_«é—-d”øI Î#\3ùꚦ2à> stream xœí[Ys·Îó&?bß4£GƒH*®Š-%Vâ(¶CÇåÈ*ER£åa²˜_Ÿnœ,wiùPÅ.—ÅYœF÷× tãÛå8°åˆÿÅ¿û'‹‡Ÿ3!–G—‹qùøÿhñí‚ù&Ëøgÿdùá.6³X4¸Ñ±åîËE€- _j+Æ—»'‹gëU7ô|0ƈNø;ƺ¶ûg¿£)¥SݧýƒOex÷¸|~ÔïˆÁX6Šî –Zë íŸzÞ}‚?³ÒÑš÷;r°ŽŠŽòFaH‘é>î«ñq¤G=t±F;Zñ9t‘0ª1ÝßιִÁWÐóË^ NÈî¥ ôî¤ô [(|`#ã´í}Zî_¨qŽÅåÀL÷´P+df—aöùî_ý>YºR±A[؃Ýà;Vð¿é¶Þ‘\BßåŽÜ ʧ=ºÄ •²Fvç¥z•ª÷za»\Ø8paº—ý÷mLwÓ]à!ïN°Fk`-tRÝôáÀ &i£P#`4gÝ«0¡uwØ#½Œsl-¸Ô‡–FˆÔI -9lÃ)¶„­k õ Ǻ{i=„¿÷PNôÀ™N«Ò£[³*£e½*Ñ}Wö03sU> ñc¿€O;Hŵ'$SiÕ]2ãÍÉÚ°©ðk#ÝÎÞíç³Å€;7È$"§Í)ç¬<®ÚÍ‘:nXrd¤aX®S2 "Úyf“V¯J]Z·²ÝkT `‹ €oP…8—Ó°VXÁM%]HòCÀxÜuoz% ÝúYeb®é„qì©Ö+E`ÇðUé‘®iÄÑ^Z¸ ò®ÆÁ*¹C-s1Ž"Ç” âòbÆrÔ³³ž(„2bFµW[wÃÆÆ–ad”e\§TEêZrS„%¯t"í« H ¼ÜÃá%ðH6´†»õf­:ÞpŠ4D×n%-’à,Á.˜uGfD08TÁj7( àI ^µ1[B¡7j5·€æ°à@ŽÆO¢,ç…ŒóRJÄ8 &é³ëSMeÄ(*Wä}¦†8ª!˜Ïÿ¦yò„d@Ü,²£°‹‚ *@XyÇ êéõ6"ðó»b³› “£ô{1'6°ìÖÿˆró:×Þ¤ŠîYì6_á ŒFëÌýΆú³Rš Zë¾*…¹ð¹ß‹-%öY)|ÝX2WØbÒjÕjõ|­°[ø~ ûÝ%[Aäò$öS]`ò{Ññ¦Õ’ðúšNIäHÖ#ÕsòÑs©©ègÕ⟇KðSÂÙ÷*˜B8µ(Î’9|P ƒ?š©5™ÀEQPµûYó®0g¹÷%Özõšoá°?²÷@óWKçJÜÔ|“G•>Ç»³ºi)z™ï?Ûè­~¿Ô¡·ránéóU.ü´>ŽŠç$™èº5Ñ&½¾› ßf«ÏŠZn¡ÂIoóÈUEÓTµœ ù¨À|?Ÿ¿l)ÌUS‹>—ú·-%]7RÚùâQ½huzP `Ü¥ðEKÚž—9P9$S{‘ `eŠ yTQ‰œ;m/)~yÎÂÏ :›œõJ}ªß¯D¥5{•'Xº$ÞÂ]œ>{• ¤ø26춯FkK8p’õ;áG8Ö;ãWýAþŸí¤òÞø+û-ñ9oÂÝÚb¤$s@ì‡i hNôÆbq -ÜY>.¢N‚ åÍL…°íƒfƒ“jÁéóeé¶[ƒÉÏs· ¹S%ûqoEÜBŠk*?©ðM‹¤Õ„õÐu·a.îü˜;sï.[Ò²Þ½ûƒÜ‡Ÿ3Ū[F ËñŒ·ŒY D/šñd¦‡"7c\zTùÎÕÕ=‰Ø¦ g¤XZppçªj1»àÆ^8Ð` -Ÿ±ú†\üǨ RÓûm#ãH”´ŽCT×õB[¼$Oô¾Ÿ¬±„̃i,Q*›ÂXؼ²'WéS‘Î>"ÉB›AHžîõÇêÞx5‹œà†aÀ`» ²ã«$h™æ)\@q¶ãºx‡W(†2“ï9BB††a*Å=^lÂeBƒÅÏWÕ­»P`—m©Í¤“Ø,ÆuZZ#È @ýOwüÂhÑ­‰2„8F ÛÁëGå—¿“0JX„=÷¡Ù¼oeTºB½x0d4f¼¢ŸÓ’,¾ŽðѤ*Híäþʪ±¿M"„‹K˜u¯_“‡p‡8FF˜ŸØËóÝ®[†cd hÂßá,x]“_o~ßõ gîOTSΉ»jѱ½±%†“4HžÆÞ¬4¸=Á½S¦ÙÄÁÀ^hz‰P 1•KƧÀWFÍTÛ¢í•C”׃’8g$æ(`<ÙÕbZht§@hu˜^&‡QpTI¨uÌà^ÁŠE/ÊØÁ(Ÿ¶8äu±%}_   ¥¬ÅŽƒ„ÃŽ²!\Ãsz Ž$tšç$m¯´QÞÂËI(qœ>õ•‚)2÷%”°¬él`•Ç‹O»÷Ÿu_Â’e$±_û¬Jñ ¡so½üPÖGÁWQÓ}l®Ç€ve,švÓpiP•ðéU`Z Ó§¼mÀÜAÀâI¦—O=³[ezÅô­m2½p™šÑ¡b6z(·fÐ4hÏØÄc iNH:µ›2ëNk.¥ÈyHÔñ ‡îºr)¦òÐJËÉw9³Å¸ž­ÓÅPh”%~ÀY`ÂBc«t3O×DR šO6÷¸Ã’ê¨>ÛÎߎ‰¤£)ÉÆ¦é¥±C+i‚=x7PÂûÌ[y–R[ŸŸ&.IB+Iª’“4Á:á c‰!¹`í´°³Ò]8RS%Ä”¹—p‚ƒZ:K›ÀI,а#LWbEòsŠÜ!äK;‚FݱxXAGT ˜¨ ᘜ÷9*ˆ`¦#I5è«+áý@éØÀMW¡NphWƒ¶|“›üQqÑ?F@À\tãÁžôÀ)Ä9qd©/šyÖ«ÛÏ3UŽ–P´®ösuH¶=¢½i`Êi<ªœª„‡ êÉŸ6¥t–¼s«Ðqàb«fg-ÌJãs¢¦‚5ålÜ:y, ”0^hg9¿8¼ãʸÏl’3œNZÒ¤s6 N+)q•¾UNæYLöWfо¸DÙ†ßYŠ×$Ÿ’ä…å>ä잤䪖ò*,.yËd0¿!rËS¹ ؙ쟒þÎaÓØïtUéú/†S!N;âµ®H²0×]wxov؆<ïPxéa2ßnl–û;°YQŠË¤3G²:Ÿ‡,y;Œ6#ô†8ÊÚkb,ü- v%®;‡¢î9Ñ6¢L+Iw‚ùpR BŠö=I±neIÛ>ãQuýS”|ýË®O²ÿêžcl~w¾¼…Á¾wŸ-¾] ¼cÇg@ø gÉ„Áùá/ô³ø¸èÃ'‹‡Oþ¾¼º¸>\<ürÉ?Æ>üô#øóäÑò7‹ÇO–Ÿ­r4ñ˜â“#&GŒ Á<ƒÐáÙ’ø4¿îÑàö‘Ç;îÑ[1ÚзCOë§AñÑœX6?ìÀdé™ 9k¦³!¿žy8Åfê…O ‚Û7õ7À5¹Ýl 9ZÝÉ~Át¿×ÙNçâ ¹…OlxÓŒøHkÂGÿBÀõü1NJªI{ÑDÿ§¯ZB¬@z@Ñ #WÓtìüÄ%×’ä}$&dbvWŠì‰ÂïÔžüú‚cùÑä¡ …ötc¨øÆÌzïd”+Ò"rh.šõù–Ñ®7AþX·-îÆcZ}ÃX{åsÓw~+u›R9ü•_’§>Û_[rñé×ù:ÒÇòd¾§Ìwn±¢ä ]ÄËɘÑ3š”%e®yAyÙ¯½ üÆ>ãÅà÷Éý 2T ™&ß'¿­º¡¼%ÃÍGJkSßø;e¶uèoMo{Šm𬡽Ýïã\‘5A¶®j}¹HQiA^.¬Ò?9"R”v DL)ókM=I&ðªµÍåŽú»V J]±_E²ÔÏZòrµf ¹ôÇàù9åÅœ0’kVfnêÈeÊð°¤°N¾**Aäìm–³1ÛÜó"§«jaë³§B\jš2qÌ3Ñ9 y3¡Ç+¡ö^èg‹ÿ»)>9endstream endobj 845 0 obj 3555 endobj 849 0 obj <> stream xœíisÅ5Ÿ7ùûY—5š¾»+ª;àÄ€íˆÄ¸(¡•ec¶Àùõy¯Ï×3=»’­2U¤wû|ýîkß,‡ž-üü÷àd±û„ ±<ºX ËÏΰśóK–ñŸƒ“å§{~™…¡Þ Ž-÷ž/ÂliøR[Ù3¾Ü;Y<íØJuügWêÙÞßp›ªm‚õLÃν5¬þlµ#zcœcÝ+Ö;g¥ë>YñîÑj‡õR*û½²æ~ÒvO`TÀ±ƒËzçÜõœuÿXí(X"¢gäÊ8jŒ¿óáj‡Ç1øŸèþ³Ú‘ðÑ9‘öãQ÷`ÿ zFúë ?mè‘n9ÿkXÀyÏ…KÛ„`ÝW«üd<Ü O`‘b–ÃŒá a±œIÜÇôR9Ø xÏÆýU=ç\ëî›ï‡AªöʦÑýäÒ:7,S0AɹcU/ø –€”Þ0ç]/áèîþ9„ýÌõˆÄ“ø=~:Ã뇱……ƒƒÓíã÷ãü§,< !“XkÒÇË<˜?­vÎôΪîy<+{Î Xåùã2_î<-ƒGyð¢uûyþôQ¹}?>Ÿx ’5ÝË<+úhô’ÞžOéãÒ`ýŽô1>D ‹I£#<}ôáä#ž°^!;é€7’0“•ërÔeômþˆ›wâî`d¥9@Š× Þ‡Ï÷ÏEèÕ`QÚÓ6ÌxŽ»È«¿Ç¯~öÜSV*<¾ë2Mò“ón:qœôrSÝ<ýºÞçt·èƒ<ó¢Rey8Rú#'Ï©0J¤&sÒÐ8wËé{Q¼8(°xçN »g-pæˆ[NOÓwQYži¬ŠÒèÁDŸ  8 *@ÀÉ’%pÒTDõ\VpQuÀQcj6ÒM¹¹“¤%ÈÍ~õþî*Φ{¾[Uò©Åû‹f­YŸï³e«tHÈdã¤Õ^Åïi Ûó[*l,l^ïa;Èf¸f;oft@c­32oQü&9 6Í$þ.‰˜‹•6˜Ë¦¿jqu!`÷çϤÇ#AÑ ùpºöi¼£ZÞŒöjõ¸…¢¢KïPh~Ü Ñ.ë<øCKY3‹´±|ýg´Tßë2ø,YdsC’>Õû6ë’<­ IúãǦ‚Y7•ÕIÙöläz0Õsù[7P÷òÜ^Ùúï<ø¨ Þv2ÂÒW-Nû©Ùñž›YÉm‰  0k8¨×²H§±úöHE—íµدæ$&ÿPPuS¯Â€¹7ª¦Wø6Yý1 NüÃŒÙßœø=Ìs_—­_åÁÏËàö•(I·)™Áa´TЦ#JÏœ|6|Ã9I}gå“[6Rã·#¡»O˜bU¦CÂ+“ÈZ™¸–¯ÒòQzL3 ‹âÛcîf0>"DÉŒ0”ÏT ˜¯á~tÁùað&£yZÎy÷Á,Ž12æet9œ–<ÓADtp˜T@Ÿ‘Þ 0Å1Ë$è¾õø\.d÷K¸XGGQ׸¡G½ÂLÅÈô[²éçfç8À `ÜÙ ÿ¹=-«0¥’=<8 å8ÁvU`+g_à#,(jCôÖ!È|Ÿvùì`ü‚|ÍuÏÈM6þ+#Ù9’³ÃœfÚË&{=§¹M&öôÃ,pJ8]Æ#TNÉæ'àC|Šu¿ÚÑnČ݋œ—Ë6‰¢xÀi¹øuYzUF‘ñ-¯ÙFfÓ.»Ì×îBqmÉDóŽ£î݃Ì9"‘×à3dÕ_=d`)ˆ™’CÅ'+p-—ÝTP. 4t;‚;à–¸BsF/ReŒïÁùýš#ËêÉUÏâ½Ìh ÑK„[‚!—5`‡G6$wFÅË/ Œ‹…€§82ý¢\ŽûN‹ì ! n@{w“$t’v5sÂè­°º–üåÅI“ð ÿûD ²¾/$ĸpÝ( W½(¼D®ë•mW+†éÄ]Èò¨*À(% ç¦Am(ŸebD9NÀùà:ëüõX%!óý©0ôikµ¥JhÊ›Y2²Ž**µbÅK˜³¦¡°¼_†a1Kך5ïIð W DiµßüCÙœ·D¦L㯥¼]EuÃÄ#&NËÅñ@ÿUª‘xDY"#ëz¡X- éÊZàjqöoƒwü¯4z÷ÏÀØ Æ:ç¹s­è›ªT‚ ïï-/Þ,Arµ/ai)±P¥íR€â†{±èöéƒÅîƒ/——çW‡‹Ýo—l±ûþùôÑgðσ{Ë?,î?X>¾i)N Êñlb9AĊν–²Œv´¶ÊV‚UvoTÿ¹Œ \ü\¬O‘¤cò YH"ÔÚyˆ©qX‡‰ZDÞ/|Nü²rNÂ8b 016\¯)ç$ˆËàN´lÕëaôK}Ú‰]Oì *ÄOxšK ËÁ¼ nf54ˆP´ çM-iМˆ ©l’mœà*únLÛûúné`â„E©ÃÚ =×à6;™ÇWC3нpqkP*¢pa8*\tòùA3¢à{dcÁ†û0Ù)ÄRR[BÚálIâúèÝ jÖÇŠ›ˆ¯”(¶•˜õªlÜâ7ÎEeó)u„¼¦0dh¡D°R}D€^W,(LŒ©šÑÌ’À³APšûÀ-qMbý ‡pP~‰'ØÛ‘CVã׃̂s^Q\Œ)eOE6€¤æEÉb$$k«Ù`uÆ¡ †ê´ÕGªZ-«H#ÆzävÀàÞmÖ®R^œìrIöÇž#Ò}ØÚqñÜÐä°uƒ‰§ñ\‡€=sKn—§„XéŠÏ‹„ˆZ&HLl× (’7ÁZ‹™+cœŽm>Ö,„P JÀù-9F›ø-\¿ŸNÇ™]Y¥òñ#wªzM:®…ê\ïH¬× K€÷1UXþñµu?$J ¸_`9stM”+a=|·Fæs;vûõÄìÀCÀ%wú¿‰»3›WŠÜ{>àçäòíªb}a`Ó4„«ž/­=¤©3#šnÖ$D3ÆˆŠ—SN„ òa‘ïÀ[¤#+~Ìï‚C‹oƒï6ò®G”âÒ‡¤ì‘W4ëê‰i›P $ÇÓnR‚(Φ– +6& o1Û~‘g«RªÞÀß;µ\”tó†–‹ß`J}[-º…·v-ºtøÔ‰g_üv7¹iÛ;/V3‰m*c`zDÌ ¿Ôuý‚åH8ÿç§:Ï}œó܇…„7(á“ùfCÝUkåš’Š p¸›Üykm¿bÉ­(ªa Ù Jn×èˆl®XœÙRáVVÞ¸àW8þiëè\úìËÍ¿·Žýÿë±’=%z “K>àö]ØpOÏýQ™fíUð—\ :)Z~H­v3-z«mK‰2û9â6J”XhÈqõ48 {}“"‚žü ŠÁwçuœPgm[nï‘ßœò˜Â}deªE¤Z Ÿ†¹ï’ùB¶Ã¬æàæ"˜­Þp{V, o«ß4ßZr(!‚ï¥ _²a´ä$8b !šXrӭȉw,–ÌÍÐÎxÕÞ‰ž ”i¦YuÌ_v½R•Hà¸oäNÝ TRÇü>ÌT¢ŽŸSðCì ÈÂÙFÌDÜxBY>Éì$ø´ó…ýÑ]GuÕL\.ÑeQò¤¶ë‡%?dyÑàVTOZz4½{ò ¿„Àº9Cgá\ô¤ŒôBVç~…²ãÌxE–Ps$¿œËZœpNHNxG€ˆfN ¤˜ÙïÓQ:Hm3Áöi3ßHÁ]*«!WIäHbº«j˜1)¹ÜåŒqvœ c´D‰e‚2_r¸/i9ïx’÷Å÷*î‹cS¬cÖ¡œ•xt)Zk¦ýdAªÝIH™É‘4ß}) ̯cV_Âñ>ÓõQÄ…äÖ|x+’N©§›0—„6˜T!Écð|´ëVP5‰¿LâX‡œ²Ö&Så™$RäVÚ¶éBÁ•Ü[bRiá `hœ•¼Ï²IØ•A¥“D >þ¸à<Æ™¡(´8LR„27ôs:˜Hæ£f¬Ò?YZâ_ÆÀbóÞJÿäåï¡Ñ´krûÏb¦¿ªyÙZI¢ë÷C®[·—(¡Ž­ Ò¯áîT‰ÕR·ã~«s’tanj¬DW燫£©òãÌ$?ÕO>’d}ÐèFÈ%ß<‹:º  rÇ¡zqÎH¬â2Ð4ŽãA£; j—qPs®û” =*g®7L`ý 㽸ã9ŒH£€•P&-<—«îïºbÒb:nPƒFÚ° ˆ•õuU0éÃÀ• ôåBÇ_Z€iàÐ'¨i  §k¯¨ôL:M :õ“‚)r÷þ ÁšAºØˆ´½‡‹½;OSu«`ÍJZeǃ‘Óú.j«(ÏJøÎ!âá‘RXË®÷ ±¹mC”Ä. yMÇ^†–ŠK%}x›Ž”Á¢u»vlÇëþ¢9§DjÄÝFȉ®9rˆ‹Or/j²Â’úøç1êcØÙp¨Ó%EíÒ#µ Ÿ:5U„7[‹›”œSÕJâÂfÌÏÖƒ3¡ÞÇ·Fjªªß#1ž’帑?°VkÖø4äãX¿”Ú÷¤TM¬¹K{žWVJ_Ãú¶câ&ÒN i|³ÆÆN ¿¦´Z(5Ój!ß~v7oÒp!­ò6£I r£Xe|ì\ŒFZ’¤ ~$qGçŠÜRÿÚMqÍŒÿMJ‘…öSÌ¥_üÁ·^†WÝçXr”‡Ñ¡¿k”çˆÈàþ&dh›sFmÈa„ÕïÇü+dìJ\»™>=ßÅøxñ?YÚ]`endstream endobj 850 0 obj 3838 endobj 854 0 obj <> stream xœí\YoÇ~'ü#øÍ ÜñôÝâ¶s:À‘…„")R/‰ZI̯OUŸÕ3=»K‘”@$íöôQ]]Ç×U5ûjwèÙî€âÿ‡ç;ŸÿÀ„Ø=¹Þv¿¿';¯v˜ï²ÿ;<ßýb»YlêÝàØîþó0Û5|W[Ù3¾»¾ó¤s Õõ ÞcD'ü—¥±®çƒíþ¾Xª^JéT÷ýbÉà£2¼ûº|ür±½±lÝwØj­ƒ¾¿_ðîOøÕ9+}òÏÅRöÖ±AÑY¾‚YRdºoÕü8ÓW bvôÁ0D¬ÆtD8çZÓ?ÁÈ,„ê„ìþZúÀÈHàNJ¿°Ð°°…fÁ{60Nûþ¸H{Ø÷5α¸؃éþR¨2³Ë0ûtÿþœ,=©X¯-œÁþð«ø üÇÞËøt)†Þ0çB§óÅ’÷Z[Þ]Â'Û°èQXE)Ö½HçöY9¨c`—”ŒóÔáL%ð‚ CÏ´t=†íqÕ+X~UúÀGa{©Iº_”çq=èBÍ{‘½¼{³xÀBt§”¶H£û$p8Q²cBM&¡Ì™›pÕ \:+é¿>G)ðu3„%| ^HÇý×xNFKBb™²´Åq†éîç0y·Z ˆÁô‚'ñ¸F±RÊhNFEò59ú´%aã‚ 8|š%1ŽX=£?e%9² ¹ad¶°–¦]¬Ÿ·O£ü+Fåw¸ä¦wzàIDS[˜ "?þ Ôh-µòš8QIFæG”3éLwƒÛÀ’¹îçÎïFsãA &E÷u1"Úä`ßãÆ™¤­#ÃËèŸx¨¶gL’ç#‰BÎK”E؆’ƒ¨e/¦öa …à‚w‡hΤ҆NØÆÃM(4žƒ«éJÏq†¦Æ%e –çeÙËš&”Z©r±FjÃîQ¸…“W.<ÑÁ/‹þ6[æ<û¯ H‚‰Jì¸zÅN9¦}sy*`ý¥kåíAxòÿA “ËX÷/üzŽÿ\â?G¹Ÿr滄ÎÈ(O6°$x‡I›³ºûÑL‹†^taWðüœÎ–sãanôƒÏè2–Lô*+ˆür¼¥0úº~péU½PÝãüøªç7±;‚'z‘Ÿ\" ;_æçÇåùMkÐ*7ž—FX ´¾HÏÈðü´xš7xT÷LG¹‘léwå\6íî1å'yZ«Ò¡ Õ ÇÙ0œ Jþ€+æj9å€x}LË)#›³œÒË·~HÓ° 0‰¸½i”ŒÁ:úö¦šÁ º>òS&žƒ&èH¼p€Je:ôYP‚+2¿¨g}ˆàËos€‰NÃ!rÀp6!qB"t… |£s0$Óûe‘€û  N:˜qè£`Mñ¶ïsZ IY.€ ®ÝƒgnÁÄë‘<ÌÂu¡z!égÓ*®‹wq ú s#¤±†‚^´\ú Þ•ð~ íÁýjGL Ù ¶š‡§LHŠ'Gv(o yÇòâ³Q@¨Ãמ–„s€0bPTéÎÒ¾Ñ 9› k°†<}Ð35ŽÊÿY––U%‡iQ*Ò“®&}¸¬y? fŠÊ§„ñf±4~ÖÀÉ…œ£"ÑEŽÇàyŒb^ÿÌØ< Œñàå /Vx1¼ðap!þ÷un<úU—-à„ŸR'ÿ²…ÃnJãEËón”1{eö¡ã—‚5dÑFë}›,ê£\ gïg1òv¡d·ZKŒ L¶jØ_EmIŒŠ_áˆj“Ú=×Ö@ †Ê&ÑÊnU~K°'1Úª&\‚sK0Þ¹Ê4ï‰AÏ #WúF …ì󤸿{ðíÛaˆ€cÈ¡³¶»Z+¼ctÖ†8 “0‰ìþt1×—µŸ8Y¨)ƒíˆô(. èm F;’‰^Ì,Ž3ÁJfË?º×ˆ]¹?úYø¬@´Œ¤k¬`7l ý$DgV%ÄG޾ÈuYok£fy¥Þ\÷Öp'”FP×ï÷"å<öõ{áñ¼æD–HÙ#Ü œ‰ËaÏÉ‘”ýHmœ!‚#.w0”MZI`ïªÈrŒîŠA~k< 0™¨b³È>žÕ®F4œÁT :#Ôk,Ê|Ø{&‚ Ç(õœ™‚I0ð26S(ÀÑLq Æ)š)¥ZfÊÛ$62é%Ž×Âý­(ß$$ï%9\©`õÒ=Þtd#úq ôSg3ŠFmêãl^T/Š‹ÓðÕzC|‹‹xõ–;W¤{6`NÓÙÏ@mæUºæj}ðz$fµ•O7 kÀïƒ ÞK71›=†¥nü7Ye˜“ç)‡S®8W!0ž¿°ŠzÎxÁ œª}Àèóáâòè1סœ!ÄR¶C9±s3ÍDj™Œ÷¾¸äÞ4¬Òº8G¿ng]@ J‚+·X€(ÁLnÄW‰x•ʢ̢Fëô+q tçY¶éÐjTpÜÈ á^“£A-8ñ\š5Û‰ƒÍüQ&r}FÈï„Ïo¼tYè@9hLþ@’²˜/™T£ì”ªl|;Ù†Ö½תAHsáÊx3V_c¿ª×çÄ5ó¡ŠðpéåsV—ð9òqD\t®à°7i(Ъ°Ý[d“k œà)ž‹ÏSL§¿©I‡Ú]çœäµ€rPÚXŸjÿÖÜ-qQØ =ÓI¢O<ýÝ2òºÌK¤šk ÏQ'6c4I§Â\“† @1xÚa4»V”½ƒC.‘שâ¤ÿÐ8Qœ5¢ψ‡R€Äþ\î@X³qZ=î €¢¼Ÿ_SКfÝCç%¼O!7Îg ï“z‚©¬õ"Á®†££k¸ ê‚ölZnn ®Ùò;À}r­æÖø q¼VÃ5Öû¹¦o¢×hn´wbdA’fêg’Õ¡…añ€Ìà'#ÂX Gå;¹Å=Í[~?“¦ hvÊ•8Š-žƒvž‘DOŽ)¦/‹K¹J”õšäTSD•ðÌXiGHó š*æ|‰‰¤9ÑN¢% o¿Ž†90߉5Â4Ãp„‰W-›~4ÁÀ©çPú«Ñl5òcQ¡*®2D©-µ ž6$í>ØbÄqë iÔlÅ͈I¸9‚‚²Ù†ëAzÁUO7U)HàQí3Þ»žY^%W˜ö0Ê~!¬ÿlö Q0Øãw3„T‡tk'7åñ³Zâô[Èfö’/}¸{Ó•áN±ÊxéÝæâ4Ö?FÕ ‡½lE_{b³‘°à‹ƒ¦\š^ÒìÕ â±ŒÕø.I&O•¢ER†T'ð–ôzŸ ¿¦Ñ8Xm·L>1¨Êœ'Õø•oÖ·.»˜ŠÈ’±¦ê'.w‡÷&c¤Mˆ¾J á»jôË ¥Þ'¼Ò~±U(CÒ˜|zIR©:ÎfZO‹××øcò¢Ò@R‰ê‹i™¤1þI–¡o÷•-Ê—gão½ð[Ê ›âëw)Ýö휔1®44Tuúʉ¤(“:R’ê)ª«RRñç@ê2ÒXzLô"¹Uí(0 ‘Ëlýh<µ[ÕÒ:†Ä€úC~T( £-®¤|j”–r Åéû( K¥9X‚¯hã+¢ìÓ R_f!Lmº7&Ä4ú}Vúr aîñgCdx7~¾‚Ô×SÇ4"`|RBšnÖ–ø¨*$çë5“W|ÅÃIÄ"¿7W‘úãbîëHU›^ßHcÆ¿}ó‘o²~¥Õ¢¶1yn‚²ß!Þµªó§—{ޙª%§Ä½iѱý…‚\H‡t›š{ñ7\¡lÏ4]¢¯½¿ó7øó?ï¦}endstream endobj 855 0 obj 3999 endobj 859 0 obj <> stream xœíi“7ñ»ñØo™¼ãÑ-U•„dS$.xÞ]oŒ÷Âö&1¿žîÖ՚Ѽ÷Öq$•øY££Õê[ÝúÇÑ4Š£ ÿMž^=xü©PêèâÕƒéè×ðßŃ<Ôå(ýqzuôóêæ¡i SG'ÏÄ Ä‘“GÖëQÈ£“«_ bcè¿icžœü‡ù©¦Ä(,Œ<9ƒÞ¿Ø«Ñ¹Äð›Cð: läðÉæXŒZ'‡“ÚçÃØª´>…VÓ¡]Ê0J1|¶96ÐEÃç`Ù’¿ÅVÄähÍ7Ç2µÁ?jøËæXÃÏTSýÆOj|¢_m𗳎OÉàf@±ùÿ¤¥ y˜Rbøý¦l'd+Ö'èd„—°¢ØÅäÊ$X¼À4£6(9ŠIHZj”RZ;|¾‘ã4@ÕI4[Ÿ-š@—N¤ãTúHÀI#ñ8ÓyNF'BˆÇ6Ó¨Bp€îŽU)/Ä æÎ ´7ÜÂ)¸Q$g©uFÛ œƒS^ã‘3Y=œôaÑÁˆÑí4Â$A:=¼_FY'†o6@Æ 5Üzš¤ñÃK#•…½ŸÁDÖfú§Ÿœ ï{—ራë`åð<ïàš>*aØÚ¯Å@6eFpÜ|üàä}d•1Ûò—ƒdæ”tXbRÃW•šÎ3ZíÚpdÆ8€ 1#ôh´ÐKWÀ«òx¨wœ[·À=¯z½·@y$ÐÎKÜ«R: *ÊDv²¬ûsØ'P©$ô!BB4Ö WˆmkÛ üô@€€:F™éöÄuœ ƒî`Ò´UÜ"çeq«`uݨ¥:O‚MZß×%­„Ь1E¬b²êØ%áFPÆ4jJ3'ØÁÂß|ü[ð¶Õ|cĨIòrõŒwÉK4—PªƒÅ ®?)r…ÖƒgˆgÔÎŒóbÿ'²72ªjF=íÉ-@!l4¶ù–´­7²ØüjxZ§ÏÌa†¹å¾c•ÖœÍvÑaã(e‚ÑÀlÙNVt ¥Â¨ 1/=¨rÎŽ†Ùeà2„)’å¶ñ|©8¸a–aÿ¦†$¾ª ¨’x$&`’ªŠ]„»mÁÂÚæ:ý2Z~’5qÓF%¹Å›ìScíšÁŸlsËh¹Xï,[,aÖ„ŠY—]¸Ön¾dÖ[&F㌢´êðé’É9mi[*RùÓÍfzÁ„(ÚÖ`Hí¶´þ`š/_ö|ìGåd˜؃âQÒ"*»Ïjr£Ÿ Ñ3Ä3C>O/ß’pqKJˆ[ŸÖ¡—Œñ¶kÐp`¬Ž:`êdañu¬'T·6q’gžôÑ{ÞhKï]²l|84¬´þÁhOºYeÙ×2 <¹Î,)ÒÄüµ#9’ ¾óƦ¨ÄX¢£Ywí—ljI f•m"R1aÝîI6ö{«ÎÂX- 2w£@úf\±Q··É!0£Ô™ÚÙV»ÂW*½&}“©Ñ¸Ùo<Ô4%Gëס‘¼­½3›òZ±èɆ S^í8C5®÷kŒ½ 3±¶ärZ{§rd¶ýmWÔ Ç|”¥cœ±Î„;'&¡çG³àä¼ÖÜB_[Š5Šcq–ì/L›ì*iKXÕ¶cNÌv•i´ìJ%õJ⽯^Ñÿ…¹gv²½mBÓMìš³| sð…v£A2&»)fPáëî’ «E4swú¼ GcrS¬úN{ánæ®ÃSZ¦ t¬i œíE/XÔºe2ˆ~é v bÉåéåÈg7+Qúæ&‚¦1ýÝ΃ûÀíQ³e]‰ûÕù=Id0x¨;\#ÔŒð>;FÜÈNÌ®µô; 1¿‡Ç Àå¾Óè‹¢°:IN2ÈÙqøÜÒ;²]÷qµôŠœ'æ—2fiƒ ¹•‘q!L6W·QLu™q[œ3¤ò^4麮uA¼áŸyžvÓðPAMfÅ"d·ŸÇ ‘­NÙçeèIÓY,²Â9v„ù-þä43ëŸG“šH-öEéx…Þæ8ßWH«j{ ¼ï´ë¦ÓuÈ–¿ ¼Hb³|ÛÑÎ" ÿ˜ß<¯JÙÔ‚ÇíÅœŒÈ$}Ñp›ü‰’©À”%u¬k?Yâ+ )k:‚(Á- ¾¨(jתóÜu¡ÊSÝw"ì!D‰˜ƒïY‘BÇô5^nƒ*ç—ÛÇÂŒ/0ŽÁ<±èɤøÝ1I2 pHÍ ¿ íA¦)Ê<1üÿz‡ÿCr"I·±‚M]bç¥íMþ0|‘擘xâ-‹½_ÖF$‹RV’M¿ßÔï×¥ñ¢6V _ׯ—¥ñ úÈax ȉ6ÛŸÕÎw¥ñ‹Úø¢4¾é­õ(N[{]öz=)¤à7æm´2íËQÓb>Ž~Õ~¸Lh…u)Tû~ù|ÛŽÃÍ'éŠï´|ùª¹åÝ㔚¦,g˜{ž÷0Qb[¯Jãù Q4ûÛÀñu¯çeïìÎ:2“é~ÐÞåDXªkžÖž7Íæ:?Ï”àO¼•‹qAôe,!’G 1iïæRág¦Z5cP µ÷3KF¦«›x]˜“¾~¹ÿ'¿,2‘›ò¢¢¡,pü<žöyóo’7Ï{ ˆ±Û‡>gçyWÊlŠÎé3îc'àQQPäçbÆøxÚô-ÃÀUáï,?¢gíúg‘ø÷m¾ž|טßöÙTÙDBŽ~þ‡™*§=ò¹}qwÀL ±w7Ó>qXe@w¡'H0˜S,zÒ2‹»JËw•Ô™¤`ÒòÍ‚…°ï£n‡«fÃùç³:ìtW‡Ù Oʰ"ríÿ%î}$n‰‰Š;N?¹ñëH—3@ÖEÏvÊ\<ùdî²{Õ£–uËî¿Mä¦ú¼Ž´±¾DÃvH«ÀdpÀ §'Lì„ÑsQ4Õ’€¤FÒÁj`$Gøn-…T%Þrê·""œ‚¿ð1[#œhÝ„ކð‹w Þ`I –¢bôNYÃ]H˜Ãòœ~MZç%q E%h>†}G²rÓ¨¼>ÇñjÊ~¼RHâgµkÜlãamc=ËgšÒN»X5ÑS…ŽB³BI§|EØeÜ1!?Á;+-cbL‚ø%Ž1VÏvX´nÒ!Ô‰*©É5C_aô^»n ¸-ñÔc±ÌU0<°þ®jYôäY"-»¬Œ)kÇZ`œ(h ˜¿}勞0wxõ)ŠOYËXÔ¬¤†.³nÛ/‡§t×Jy.äzÀm/]L›Ë[y“‚ðxa,:%ƒ÷.»£7¬…óïXYüüAU¤wJ¤¿gï¥-àŽ¥¤k?v©U®Û;Z<<©Yíú-ËAj“-¶±¶ò8c†ÊtÖ ™'!%›ÒÒ…r¹_êËÜV¾è~ïR~$<ë£& ’r™—9i8i·äàa·k[’rdo;\Ã/•:yr äqsl•¡›¸˜2ôJÉJ—–·å¦µ[æù5¼›¢PçÚw›/Ù&y–uLð¬d€%:"[Í ñB½[‡‰æÀêÒš¾;ͤÛü…}—e0_Ë’XàY3 Ö9å> ó´èˆ¡ÖÈεpÞ±¼/d¡´<êœ ß¾ÁM cù™þ¢ªªR\Œµ¹ÎP¢J§öкϭ³õ cU¯°¡H2À.¸µŽ*foúüïW(Ž 'èrõ5Z…”ºD6ç§*ŸU³¹Èê#3í¾K¡ÚL§`n^æE9áŒXb5”w&M7äR/Æž2‹¬$n’,{ôÀ¬׃£-gûÖƒÕy‘j0¥f™q;bÈŠj!î¨õfIXÚwßUzΦSY º"}•g¦+Ô»éæIw hX²¿-2“^-¦,¹Õß©¸,Ñï}ê…[bTÌ—ë§6/ê%A8¬ `!*œýì`p—ØKÌZlŠRB´[Í™#’ÛtâYq<ñûzy*`«T®Ù6u/•†s²™U™Tz9@)õ7–›ê"¹¬£tTV ЭwiË/ Ð=¦Zd¸û–=šb”xJ¾TÓÃ¥ŸEXSþ’j D³:¼\=WÑÛh/r…¦ÚQˆ€ü òbnƒ‰ÁÞ}ølSRÖr2j Oõ“T1 ”õY‡Þ‘/M•™7ÁÌ&ЯŸ`(ÿîÝP:¦çµ× 6©îêUøÌáéWó[E%»Ø3Ild»ª2Ò hº”¢ïl˜\È­OžºGS¹Í1>ûñAyŸúø¨èçäRDœ,í!DàUÉÀ½pœâóÖ€ KsTÌLþ.8Žži”6¢½Ñ+œ½h%ØšwM¬<Wñ·…$T9‚õ!ì……®ç€°Kõ¶n ÆãÀ:ÂÔ6–@Û$ÊÂô†Ì§=¹{­Q¢Áê€Ä(9ô ¡^2/Òî[´gJrÍ:~ÄÛ­ª#7Ø:Né=^:Ë”4ó 2¬› mÎgW…,Î6누Šnz\ë,t¾µ™©•:@À£d•è—v‚[­+<³/Q€¼³‡ZÈXÜ$»‰b$T²Ö¦ ¹ú›Ý,æ6å’™3MÿÖïÃP¡åŽÇU’äU¦c–¶P¿J®³­.Úa=cµ欎ŒFÄcÏiØñZaG.è}*RÕòÛ9È…6ë»ZM϶?á«Õè\ÞVfÉ·Á3ú[âÒò,¼'Äw€¨3*g±®¤²òç)¨„t‡ID…0rg ×íi'5™÷T˜Q“l•Vô$À¾šœï%â ü„5n‡”פ𙯮DkPí-<š‰"™µJ4«${¡…ɤ¶Ês]&±b‘7«`Y¼¦uœ–k‰|T+½¨6¹*g]ÑBñEø¥—á_­{¡”C¼‚ùÞ‘î.âfÄÝ«Œ·RÌåX®ß0íiâ£IZ¯¿Ÿ•«fúÕ(së>xÏ Œêð¢×¡˜s:nHšÞ£$¸¥·ùñ$Lµ·Xhµ 'Úñ¥v¦_RÐãŒëT&iY„gÇs+?ÙÄz5Ó‡¤˜ŒnD%>«`¬ä›¤#AœB”'r´æòŸÅÖbÑJÝ¡]¿ÈçUíz&–Û^2ñ™Ý_Ãs¥–eáwB~t·`ï•ô»xèž¡šüDÉúFfgÝxwS}îGøZ¡²<ÐVeµï¢Ð3wëE_ô°B¾+ g¯´fS¡ÒÓM)œ_ ù7"&ÊbÃdñ¬J ‚·Ä쌞ݜ„‘òfn_ôžw@DO’lŽþ[M±ïD¶Üº›ðvÀE˜ÉÏbUÓ£Ò\'³€½Þeiþrxðåá³¶œ< |VÖ‹sÖÙx}cÇúyÜâ·µ£ñÚ?ŠÍ„ó¸VöØiáàF½íª£X„ʱ¢¬OöÆŠ¨´ $ÀŸ Ñ9ãûVÓP«îCߺŽºK kÖžm1óù2.œÃŠ8JPññrifÂKâÞ¾÷ú›]é0Ÿa¯Øî…@%\³zÉëëT~H–·繘«O|n#[!¢*¬> stream xœÝ\듵ÿ~á¸oÙu¸±ÞJ%U†“S! ©ÔúíŠ}66g}º[¯Ö¬fwÎ>Šraf5š–Ôêǯ[-{*&y*ðOþÿ½g'×oK­O½:§ÃN¾=‘Ôå4ÿïÞ³Óî`·€MSQžÞyx’ÈS¯N]0“T§wžük·v3mÕä½×K?Î|ˆ“aóåöÌNƘh7ÝžIx´^mn¶Ç·gzòA ½ù[CˆÐ÷ÆVm>ß1ù›nÏÌ¢–SùP‘8#¿ùh ô¼³–u§3ÒÊLÆ• i6··g¨ªhLù,½ùh9§­¦ ÝÞCH³ùÐÐq°ÀÛ2ÉLCxáºçÛ(&!U Ï¬Ø|“QJ9ê§eœ‚yXX˜ÏÃZïá[ma'7ã²d„¹ÞD*^8€+øºÎ#­ÕÇ(9‡nÁòf(/ËhZK>[8“í:\‡-ÅN»y˜ó¿ï|z¢#¼i¸s$€‘ø A«dá9ò‹Ãy°iµ)!QÌÀ%Îo‚e 3Éÿ¥îZjÞýÌ1©pz¦2+¦¯žÀD6çø×w0°;F½yˆ¿ŸäF½y…“¸ðÿ”Ÿ›õ-µÝ­/îÕÎ;üù4w6 (×a%h„Ô žnNp›µñUklôžÖF\Ÿ‚g\řԓuB¥å|³ÁñúùW’üE™— ªÒn®Õ×/úï^âÏ÷sG¿ûõÍó6É‹Úx·5>­Úç—÷ZÏÝ`ÄáÔxu£ÿÄKÏ—#š4f€fóGx™AÁxR»ž·®Lp®vð»n¡ƒÖ‹ö˜?3:l¾Ùvû âoe'ÏÚLš$&t IÔVµEÚ)¢˜dmáFèÁLž‘`g^¡òY¼)JáL²“„ ç@}7˲M"èÊ×Þ)ØÜòõTòiqOÊÃy"à`ôG@–ƒEÑ+dñ³—hεvÂÐÏgÈ0}FæÉ)mòœ¼Ö¬-ç%MÉÀÞ 5!EÃ!#ìs"FKƒQÜ¥%ÉÉáˆwÛ|êp½à"€Iy‘8âs¾È‹öUž²w¦¬[$<Ø"Iò\ZQøJ©cK)ów–ÀápWÈ«Á4´ŸŒužoË.bûæÊž3 ¶içÀƒXS– ZRHxÚÎZn®™Ÿø°µfŸ¬p ØöÉh_¹ –JÅi$?¼‹ÜÜßÞjpQiî2Î;p¦"NTάÞñKà½dRû# 8ÒOùýVâPÖÖ9x˜¨Èœ ¿×qózkÍ¢z‰½à’^h£Sd@RgÆW$(`ù€ ž÷o*Å“[W:ô›­€ÉH†¶í÷ò]õ’5öŠˆ0鲉·îÏ·Lî¶üeUNt9* ÆžJ㜪t’.˜Š&ã‰Þ$?”ÛWPÜ=­$߆XªŠ-›p#Áý}¬ÇM8SWA–šz·(æ…o÷[kc vß•…F7q ZÓšöfJÃ+¬ŒŠ‘íÔÈWÍíÚ«òYöÄ’u[ìû÷ ­2ûXw¡ÙèöÔ—íÑõ^t¹kÁ¨hÅÈàþàWyËLôœ@- Z&zYD'kœ¸£Å uof´qøÝ潡.‚0!¶’ Ýzówhôöññ\i±ãy¦z··î"ÕÌ/ɵv„ã˜Ü˜`£“ÔÀˆüú¥–K–[ºIWoÍe¦pÈhÄŠ}sÑT…u<( ƒ&ú‡Ä`p ‡†g~Á'ɤ<¯´·èöú@» v_¤{¡RQÁŠÍ*Zšg’ ¬›üzàAâA c 0á ‚ øjIÂ}³fË ©]¯‹ìq‡¾¢µXü™öÑ%hÔ$¡ýZ"ƒè“w,´xigI(‡Ÿb(ÞÅ…Ù9#Á}çl,wÎÒJºÇÌØáÙVÆB2ˆbŸéBfû¯Á]›"ûÌ•­vUÿ‚Vܧ+xól x”És‰kb¸Ëü Åhb#ÂnZc°º‘›2¤]ó+üN&”ÄœÖô†¶ü 1êPdSKün—T7û²øFKfd’ù¯ÖlѸ#jP´ÆÚ¡E±ê¨qOMã€BŠ{ÞID_û½MD߅߿ԈþXPÛæËâã§£Z þ¬‹¤*|ÓèØûËÌ”Ç>qÀöԂʉ‚áêžÎ2 MZELÛöªJ`["ý¼¨oÑèqbÀˆI`b¬O èu‰?m)4“<À”ô¼Wø˜|é’c.ïÆOSTZ~±Øq•cï'“Âà…$“u—Ç!ð˜œ#°gìs”0ÊReÕ%>êã¾ÚÎ#†€ÑAÈ'ÐG‘=T20×÷ZãùÜh—ˆÈGÂ/ÃÿÀðCû¨²òUÍøxq¯ClÐrtÆä/^´Væ“›§EŸ¬2%ØIÉyLÄútpÈOУøn¿úÊÁXMºJ|áG˜éf“¿XáH0Åòf•i³ø°’+‘ÛÜò`OÚVÀFbø­÷Û@åzT“¤hÕI§ö޶øƒma÷Ø{³£v.ñ5PÜuàû`¢ï£d\”)7ïú¦¼s@¨ÝÖðSm«–På>§ìÁDšE¼Áœ8gù0”ÕœQӀݥp9×!ä0†ê#&ûe9¸¼)y9c¸ª°|¢Åœ‡# Þ.i–òz ¹Î>Rܘ¸þ0©ˆÀm79•ÅAZÇÝ0’ÀÓš¿ ƒ[5ÏÁ¡ ñ˜%çà¼åà0ôu½!|¡ú1¨9 õg¡ü0ñ´ZSlÃAKêŒiÂðEeïþ4ÿe‚m¿òÄhˆÂàË*:ï_~Vß|Ñ&y«6~Ü÷41è>¯#èöúF,§;ÀÞ5§;–NvZd°ßØŸëäFÂmô¸âT§JžùÁó!­ë(^§ð9nAÆÄê‹«0NþúáL rŸ‡¤ÅÓ¹Aeäü *¡8ߎßO£ °mx‰Á¼ì¦Ê€7ú–Rú­7ú,*ÑÐh³êž§Ä`=Fëó0Õ‚·w`ìgqÁ2*]šFb’FÄŒßÀ¡¥Ì¡©aÎ! ÀsVò}+þ<¶d‡—‹ rŽsµùTaŠÿ‡=ìÎål¯'-+îŽ'V.áçÍØÏ/ÓfXëV­ùªœë1ß_½³|+§ß€ñÏæˆwõç]î%ôÈ{LµEòÆÙ] =rõì‘ÿŸFéñÈ%¿$lCsº¶–qŒÅ¬†¢q¤u’_Øô¦C¿þN 6ì»pí.’C]tíäp׿Uöˆ=' s'ŽÝœ»LôÙ9q¤øÜ:ȸbއ îM88ÃÙÉG…Å¿æŸÃüXråarõ(¤Ãs<ùQ×V‘2;{Ë @K_'Pó´IÒ¦¢v2Þu->z–²)¢Ôe @vê~Òn^áÁÙ¡ Ëž<ûìt´oº"϶à =¨Ù¬Ø²ÖC¥K“jnðÜk0±!))ñÛ²Y-QR›0¹¡0-[K’tý$@NQ=£–)ÕY»|Š““’¦èË”Çéîr$ ‚&TàÅF©¬%Œ ‘ÈÅFƒXº¼yIVFØ*j–ãûyÈ’¨&å@‡HÅJ« kÍGAI ¯^&ž»3ˆz«V³r”TÚf…KyEWW·Tÿ𩺜«,z½ZøÔ<ïeáÓ¯òÀì*S'(ÓW›6Y¯fH‰A©ÊXdh´Š°}¤¥Í)(¨6N%¤åeö5Ì¢âêˆúêÀce¬ö”`¤-Øf †4×c m‚÷Gn®ÎÑ©-Xq¯ÚÖòùž¤Û\*mé-ˆŸÚ'‰ ¦xQuÁZ* æéú1y0Á$ ÀÿÐu°‹ðC¦¤» Pê%Zë Äôy0að°CLÎ ù¬x×q`@ /,ÀÎ$Ø\;ðçúH§,¹r+Ш¡4 }†´‚ìfþ9’µÚXÊG|m’Œj¼>å$&ÊIâ5hÓA™£$ø2Êõ_t™]>É”6Ò¡o“Q!Ïœ&ärݸ®hø|®××_lñHTº`I“KõgÒ§+¹$‘ðŠ-ô¢Í€fâÁ÷ÿ¼ÉL”4SðÇnëÏêà:KóþqÐ^5F+ÊN0v¯êì¢y„Ãe#}&,z烅€¬ž•yðÕµ+Å3÷¤ »Ô3»këT `ÁÌA6B¶îÈvT.¦8¬g ¨”2R+ƒSA zr¬‚ö®YW*ÈÆ”•0õÎÊŠ¢/ªÓpW¨[/VíWÌT„©ÂQÀÄ!vÖÚ’md™#‚Q³ùóV•PÔaz(Ý "§È#”™ãHm^'D—€†µæ5߇Ìëý}ž=¦°fD(Äè* œ¢Û_DŒ×5+Ov!¬áÿrÅÊöW¬ 8A´ïð¬|¢¶+doWÐMwœ=(ªí¼¤FLã&¯An®ä†­¥ê'¡è„ºÏ?/×öÍ"†Q Ÿ™@×è40ÕÁ*¼KØj‘÷Yy×–ëÐgÔÛQ•v9Y›>¨,ÄàZózÁ‡ØˆA²_”qbWKfÃUbx@À·Èð®`–XÒ' Kãø±)Jã㦨y6P’fÍEH* Å©éRÙ)P´SN“À²H¿DíöDo/……~ë`Æ@ŒQd G³ŠJ)“Ú´Nûµ N’Ù¾Š 7ùÙHösTa>¼Ò+KááRÙù~Éx­Å0©˜á̤ƒUÝÓvˆ&zÞt²x L=¾²Ú§È×^ú©ØŽêÈõ€Âù¸tOíèí–\Tûö ¯/h~¡,è|*e¾`ß1àº,|bטf‰³|,ôÖw‰†·†ºª%Ôåt+fé®A'¼öS¡ìWo"2p:vîÕLÄâÕ¶œÒaÙ› yûÈ*‰î—”¡a”óÅtÔðyM=O‰H…MŽ x=‹ê«å‹Ú$|”84, Ê7Ö}S¼Åv㤾 |¢ ö–,ò¾$¥±?.(_.(|³.Âðš?u·}ÊíŠl˜!$£²¬C—”‹$Ho÷€±™_.M*7Ö\Áñ2·Ç°䉊Ín•£ŠÈÒ¥£âÀʵìÏDŠ%ñªÊ›,¸ÇsöY*z膶ø^&æ;[Îl¢ò¼vtdÄy±]QAW²wp“^÷v¢¯Ók´ïÉõÐeàI2;Wz’œà~ÑZód¬ LÐ_³¡ƒ¼ýy„Ö°p½\<ðbäc†§:AN“ÙéçÛ.)Eªe­™Üob΃]Ë) c‡Ø;Že‡Xœ’I)6Dxl7º%[I²ѵžGvuCÙ×Ä)V…b5Í ðÌð2RZ:°¹Š»ùz “ëYå(ÓŒîÖaª)YVB¶˜R 9tjàâQ‡§¢>Ù÷Çzù’kJ‘P¦3XVÄ’0™¹Nð3îýSÜ®XútÄðÓ‰°k·ÃðŠ*/Ê1zÉ‘ÕâØCAÊìPyà‰æ±lÚÆ†ˆµ"s¿( ½-™ý;ÉØñ}èãÿBÒªUÇó§zß|¤wÿ˜Ù\™×GíÃ*çPèvxóÎÉßàÏÿ ›X›endstream endobj 865 0 obj 4243 endobj 869 0 obj <> stream xœÍ][“Å•ÞçY~ļ¹ÛA·*ï•áð±Í ÆÈ6v¬´i$@ÆüûÍ“™'óœ¼ôe4îB­îªÊÛ¹~çRo.—½¸\àÿùï'//ýQ(uùìû‹åòwáϳ‹7"^r™ÿzòòòƒÇñ²5|µ÷‹—¿½H—N^ÚUï…¼|üòâëØšøGnÍßÿ'ܶ.ì6%ö†;_‡«?ÜîÔÞ9ïÅæ÷[±÷~Õ~ó[¹ùÃv'öZ'7ë5¥o•^7 ߪð؃íÃ÷Rú½›/¶;.ÑÞÐgÉ÷«‹‹c~²ÝÉü]øŸÚüe»Óá£÷ ï‡Gý&Ü¿¨½ úí>9ëè#ɼɤÈó? H¹—ÊãmJ‰Í§Û²dx 9,y ±Ê0¢pÉf®LžË*…†ÂcöÚøpƒ’{±‡ÚK)­Ýüi+÷ËbÂV=®75ã“AóÔ¥ù89ìòy†=Ù;á}:Öüd±¨Íóºô§aß#7/ÃǽµÎêÍm8¿ï`§•²‹Ž¹%\ä7¯ë­ä‚aþak}Fùî‡pëjÃâÊWÿ„MpVÚøèUÄñóó´—á[ ä³¹ 3¹NcÚÅÖ'¼ªóxg¯$߆›¤õ{òÇzèdŒf~N©CO'7Âæ¼­¾=­D*½ù&döÆéÍ_7ý=]´r¹g¿¾Û¨EØÍ¿o—0!…£‡ÁΨâ£ÇŸ_¼¹Tjo£P¶¹TÆØ½]/­Q+üDÍ_<úø¿.øîíÓ‹G_^Š‹G¿‡ÿ|ð‡Ã_ÿæòß.>úøòós2ëÞKg¯“ :guÿæ+ñßõϱ㜴’À“øÑ‰Wá6$‹¤w=ÛÂÂ¥Û+]`‹ L8o§ ×Fƒ¬zø…If5\¸B!+qýŠÊ^| AëUÉùŠü¶ågX‘YDs”Ý‚°øSÀ1,>3¥7噪 GyS~ÿ‰ŸØN…†8{nX÷pòYFÛð1ÓeØ ½Ò’\NùFžMئ¬²'P [‘lô|^GSAzMyl4@Yä“2R’£Ü°"´§‚>ƒ#"rlCRæ2]^½ª×=¸S”˜•NR´šûÍ)ÇyéF/Ý[qñþTá­L’õCjʺ4Î/T•8n§g:ê›°yhµZd«q®™~¯Î0½M;áW›=Êdê¯ù„Éd(ýFeãxñ™êrÞX"?J?ÜÿUqÝßÏÇŽîÏ0c\M[‰ñ´U=ZÑM¸®z¢S(Å)ÅÆ“OŽ]Íé¢Wd ¶ŒÖ½‚éåÖ"²G®JZ!m× ‚úZÁÕ¥<×etÇë‰Â˜HËWg Ý“ËÁZ›y^%zã#–3¯t]`J­5PÙ]bmÒ¸ V3°ÍLªJ/÷4”ßi( §CfS¶EÐ^Zky*ý»f¸à^Di›ˆÇ<䋤@#Þ;¨{›Ìë½T‚°¶r$Š&·l€ Ëà 9÷ WÂÅþMu›¦Æ\rûx%î²a¬NmL˜ßn¡¹Õ ÄNnɺW…/ªPh„ì3„=|cWýÆNJ =X¢¼a$¸ã9’€'Äx›ã9¿³Ž\ŽEÏ?µñÓJ¸¨î¦dÔ–-ê³MèCÚÍ7ÉÈ5 †O;âÇ.ìâ,4bºÃ³®³Í—-´’§ø\~ce’ d%ÿ ¿.¿Wö0á×]8è½#.7]‰Þö ¿¸â„¼ÓŒ“,v"lòiŠíL™| ¤Yj¹~†@‘%ilÔct_ê–y)â¸Ã-:%Ùýj‹¯_ÖŸÑ«`"Á]„‡Ft• 7ýè4B„býÔe¥¹{8FÉ%òOsÈ "1Bøn3ø²Ú›&…ÔA0ý:£¡ŽŒi@áE2rËÞ2ÊÒ†Ì";©º8óð”ê#–ш‘ÌÑ’Þö±«E”ù×½ B¸5ª!2Xµ<Ãðª¨Kh•CTÇ|=äC]"fðÔqÌEÖ8¡KÆï0Ö`”µ f ž£~ÀXƒ“—&‘Ëx"Š€®®³¯`)Øò,Eè qL—!D^†´1ô`Ëraëˆ¯Š¨l®iM*ö’®»æÆP5ݯ’“ °g•0„•¿Ñ7:‘š…QÇ!EuÚnJü¿Ÿc7¥Ñ{3% ¾‰MHíÔ¥xc\¾ð,›¥ÚÀã Ál’qÑàk‚Îþï\5µ0W-ì]ô¦NzTxæ§HgxÓŠ,îj½®7ª³U‚‚ŸDmа¬`]2ÔçÃo郑ó¨Iôßl÷4CÈnxѨÆ5ûlwîÝ2ß-í>‡ó8sDÿÒNžÊu,Ù/Uƒ9ôÚ@€•îªE1Ì@Ky@µæÓAt¸ÅCsà ±{z“;* "†T fŽjÎç¬S£w¸bÝ sÖQ>©ñ³c/amÖšÖ‡#÷ÍðŒ §}ÙE =ªÎk)¶ÁŠ »­Ü¿â^x†šÑàÑf P!BpàléI à^L9_‰ÏpCõ¸' ì5HRCЇ i§G$˜ßêƒvŠŸ%ìC„¹xä‹ó´z…ÂcŒ™AQ …s*:;ºx"…Cz%ˆU¦Nà÷Õ™ŽpZ%À¼þ5e•ÌÜúj£÷¶»dBß™T•_G}Šná¡£:B“g·Úxxx~ÍnÕ„®²x:؅͹§$—Àª¤[ì6m¨„ÍÎŽµ§˜3„c_4Ò=YþU:H8c¥ÇlTb'8ƒ@Áâ hÎz%†‰kˆ´0ˆVþz‹¹²…²Ã9X6€VÈmàÎøÀwú„/ꊭ¢•@ˆ¤ê4W¼MzjÖóDðTœ&zq5´GLc¡Lñô`¹†É*¡5Oà­R,®…BÝdÈV§H¤`ÀTÝYcÔ °²”Í^vñ_e¥ƒ‰H®„™xLx%« }C­p4°‹-kƒ¸4úqÚ›WÈEó¸7‹Íkd¢ž:é”A‡dÜ\{‡N5@qMÆŠ["$?Š£Þd Uª¹$Úƒx·[•s ~ÜBîÿ¢å@}H1ŠÖ’4$˜Yp…´óŽ!ýêÖ0‚,²?Èàš6ýq §%Ö$Æçi¹”|>N*L†»ß9ùÓÞÜ/Šlå&¦óÄÄœ¯¨16H  .ÔÉØ\—Í.mzÐ D"Â<#*÷)ï”M®¯à^h¹q›Ûåµsþg¼¥–¼D28F‰A™Ao›Õxˆv­ƒºVh‡à‚m§;ƒ§„wæüQ—À:#Wß˽~N¿0ö?F/O…±AÓ­Ïy©UR 3ÆQõdÇ¥s7ûi» @ÿÒ2Ræ†Þ/£¤¾I²-…ýA¤IÓ†¨@›Aú–“`fN·Œkt›o:ÝØ€mvß‚9í„â5ys8CIOˆ¿-¬q®#Xȳ䔺:!OätCŒææ æ—^¥ÈC4#ñ¡É…Ÿ`Îæå:vĬ´m©’dر7:@c H^Q«ç¶º)Ï»<þ›úc'úåy#¤~7ã+sÆÒ§l4^*! }iÉÑî©ŒŽ»CùášÊQv Êd­ˆ?9yŽe‹Äø=ÏþOêéÑ·8ÃÙ$}n@›ú5$"ÑŸ\<þåÂÂd tibYCu'×hèŒ;;N û¦è…e#tøðV“ÞOìØu¥|ãTÛÃÇyü¬’ÊÛÖà{¸P”á ã@f–wA±ˆ¯&øDÖðÏšA~ %(³‡_„7?YÄ8Í6ù|yÙ Vþ¼ò0H3±=øêR;[„_£c$Ô4’˜ ̬h[ Ëy&‘ÒQ ó6yâ¢Fð R ÿX¡Z=QD›b]¸¢ÊW•¤¾aÚú/ÓŠj†%OÃÙ’"^ +"‚x¼Õ¹€ ˆ}‹¥¢Â‚:CEã{ö±Ca´£úÁ¨™ñY?@4Ã$›lI¾R²X­)uì> ÓX¬K8‹àµV|þ^*ó¡°(¡—à/ wT ½F^G‘ˆ)N"e‹œ å/SׯýIÆ–"å¯òFœnRæ Dm>¯TH æ"~ÓïòMj,ž¦m²îJúj‘òFé7Ozc‰S<ç䜰8ʮ͖•êYcZVOÈÍŸy£‰òjR½z¼"3 ÔÄ_Gf3EòîõzàÐ÷5Pèd q³yrmYäyÎ+h6<ÏàBËBó2…¸>Ci nKgl¬+ðèáà]" idOÍò®Ž1´IÙÝxËÃs!>†}sý2ÕsÌVÙø€§Ï‘.Kï0!ÝDIªk…sÕ©:³¶Ù²¼ÁUV™‹7’¡]Êó4í„ÐEÑÒø°¥Z‹þ¸Ýv¾ÊÉÁó¸»äßg¥‘C£Y³};’ÑÝúVçð«#=l4p9™WÀíYa<‰w&½t˜MÖ{OÞ+Ây`ñ ®Õ²±ŠS|´5ƒ„Ž–Ô×¥üqÜtéíÞ6``Y|ª·i9À0 2!›Ëą˹ g¢ë˜Ãÿ@è: yG;»Íj™c \É€ÂÔgWרàV¦ë0ñIЈImÍ´Áo¹±$–Pà»l‚:‚_—_k—øWªk~]Øœ—v‡³FBê+N*ëRZ‹äZ”2ÆJ5Ó=J,à„Õ½S£v½HZýÂ[=l`¬H>ÁOŒ ÕgtRÆÈ2-2 óÎçv[Úœ{ÙW(R£S/©[}LÛË…›šØƒlq$Z0ýà>hë¥Å9`DÚË¥@PèÌ,XìÍöÞЧy{¥ù©ió?Gõ©ÇäôŒ€3lß;0FrÇ ¶3 ï¤C8‚tPQ]dŸv^þ@lÂå¹8–&š½…av~[Э×Þ¿æˆ, $uì$‹“@è£Ü·÷êÏ£(úïXîY,°î%}㈤Ï,E6ˆþj'»<(¤!Aç…d¶øÿ:6¿Gëúzþês›OÙ;+:4`3=æ¶±'ꨶƒ­„ØåÉ.êœT6`­òÕH‘e¿ØÓls$ë†.U‚LlZÑØ„½3*rW)ý,ÛOdÇ|{‰àÒõvTovFºwR¦]tŠD¦µ–¹yeýò Q}o¹òA+KÊFו®õÅü9%z725ïИ°7É”oúU¥pÈDÕb©®mÕ:PÕ&› ¬cýê³fû;¡Nœæ°(!í¢ „ïÑ\î–«6`rIeêˆQUk©5ÕØ|€)8âV,„AÁiS ŠÛ8šŠ=ÌÜb ð/S=mk[©eeá½\´xO°{lᬛ˜©fâ‡5]Ê}Ýj†cÎM>…†#ëg¡¦Á¦–¢3Iš"5”ËL•Œ™ì@’éMÇúD·2°2+EM=¨ýЦÖÃÛÓ¯a¬ú§u4ýá¿hºú{53)'ávrN:ðæ•ažTû8Åÿ±öø®+ž>KÞÆ«Kx¢×²Ü>!ˆ¼AÁŠˆFSPYÌ$dFD 9˜V? ^Aa|̇1MÚƒNf6Ÿ‹ÒUÌ»…—h@œ[@ºôŽ òQòÂÒ?ÁÌÝN|_K­î®K¦ÙŽlC^T{Fƒ8‡Žˆ,©›\ÊëÀXçš¾R‚ëLÿéÍî¤|©üN0¶U+5(ïž HÊbwy ¹m—=nt¸5H/'Hòåy…Ç2ÝÙ‹È&céãb&¡Ü½9 #š[ü3ÑÆ°¦……™úNI`d¹µ]r@Ù&e—ð¶$ã<“Ά$žŒit±.rŽ% ú(_ p‚g{•l½‘7KfZ ü2„™ãÙ"è X~.™zR¬rмˆF-^ý»°@ xïJ÷ƒC EX&iü^X.…¿@ج16;U‰ÚÒÙJÖòéÓKˆŽçÛ[ ‚Ü—×Þîòžp6î_R’YcŽ’C“œpžÓnfd-â»>¾À K€N}¥D zÑë¦bQ’Û 1ˆ™Û“À†&óé”e×4^s¹q€Bq0|Á)™V2uá÷ÖèC4~Õ¥B ”‹]š7hܖëÈù©‘_| ¤"©$ƒ2S­Üþ¦ãį·îA²seíxDéNuÒÈ,<”‹X yغƒÍœóG(Çʶ„45[•F~],{1؇*¤XÅ ž“;;=ïÒ8·¢E&S‡9D&yj-Ù㆓…n{.[6Ñ™‘z_âYé9V\)µÑ®§t©“MPEÔ–æÌßÃú±"œ\{x¶N¯p9?vËú* ¾ÔÂßáBÂèéçñ…@*_Þ8a:`.åe¹õq‰ÌHd—{X âM“üˆ"’ñy£òÖIC['Ÿ÷Ö:¥6#6SŸT÷ ±”ß¹snzXZDÚó`ʱ#öYÀXU 6aÝ%µ¢Óˆ”b#ýò4nøæbóßðO àh-K`õé×åb(ˆYPÁæ[âQ@-e€tQ4|Ð6ɾH_¾®_~‡_F?"|+| @£i×Î9=ç{þÃMži`ˆ˜±øËòók~_\ÜûùÂX.Š¿¼ª3#ûu]~¿b¿úò§ÑŸ–OôQ7n>)_~Vïù´|ù»úåñ+µ_cn=€ƒ½Ž˜V7ã§õË›ÁŒ_ÖŸßÇÄtJ1A<~>{üøYnŒL+øM ÔÈað¹áuäÛ—Ãk_Õk¨ß~ÏV’?ääó‹ÿÑ…å„endstream endobj 870 0 obj 7226 endobj 874 0 obj <> stream xœíkoܸñ»Qô7ì·JAVæ› H{ipEš»¦[ôá RÇNì\íuλäßw†âc(qíu뵃faX+‘£áÌp^œÑO3Öñÿð{pº³ûŠK9;ºØa³çð´óÓ÷ ³ðsp:ûÝÁu=ëùlñ~g@ÀgVÌŒS³ÅéÎ^Ó·ºéZÑYke£ýÃܺ¾Ì5içºSJõºù¾s¸ÕV4ÏòíïÛ¹ì¬ãL6ßâ¨s=À>mEóûÞ©žÎü³«ÎõœiŠåÀ‘"Ûü¡|ÖhMßZäU€")T§L$H*×¼jç °Š^©øšs²ùà2Fjé zÕ: KpÕüpȾcÀàÓ6p0ËLqÿ´íYǸpþ5Íšï!„ñp’÷³., ŒÙ°¬¶Þ•–1¼yŽlñh}†X$2%€ü=Ñ1ðjûžS ½ÂfËãjRrJÎK$DZÀ.l)I³@óëÅwdÓ  ‹CЂ⯠ŒiÁ£ÌQ^ÒAÈÊ$!RTLG5Nƒlãq”à¿lõ.¹¤àsÅygfsÉPVýðê†'ÆËw]…ÜKG3R“Í#œÙÇËy¼ 0~ì3^hgšø¼ÄË% ÂþEÃ;í\à^ä%E4¼Êƒið‡6Ýþ6Í#»sá:ƒÒ˜ ÐÃÄ_•š÷øü! J‚ý >þ’8Í ïðò&Ž À§øx”&öðò6HdÊ HHYÚ£ÉzÇ+ 5ûÕ¸ª‰í8 ^æÁÇ;g …˵ÑÈËПÔÐ]þ¤†þ¨‚^¨7 é:¦¢f— á­’n„t°ªÞÂnx<)dq!ø—à ðvò¾ΰ»¥ J®ÑïϹì´ab Þ+›¿|Œ—ÿóRk'ówW¥²ù±—³ñ1Òø#…Žƒy~,$“kÓÝœs^ï'([ªÓ.^Çid¹Ö½›-^ì,í5?4‰ñdGI—éÄI0°Amôàn²À.KEýbTÏVèWÔÄ#Š#BžÕ<ÍÇv¬È°Ð‹4ø]†|™ŸçÁ›!§gnbwçmÅÖ3óï ]̃Ùjïpøv„ÇÛ4jýó`—¢®b—益BFO«°Ë K¼ÍEÁLaaÂtzlawÞÀ-„I|q•7ý:"Û29›“pQV{ífeu~_3¤ãD¾Œ"7¸™J¢ã@¶6ï6nÚÑÃë7¯:ø¹Æxá<}$rúN}É`æîáýIvu‡â]˜®I!½| âC88†¸;“ãø}&êYN­Õ4³šEý\SÇ“RßÝØº²•®,þ&Aï¹ßÔ¶ËtÞàé³ÿšÒù¬i+“´¾U™ý5ùúšÐëÒ¬›Ð{ û?Jè·YüÃfñ$UŠn³PD$ÓW—}ã° •’Œ…÷,÷ûŠîxÃî(¬á»£¤Uwœ—LìD­\A6Bç…‰ˆ¼`ï´Gï‘™$݉„ôÜÞ?V ?´C¶M;9FŠ•5„®³{Ii‚yãwò_~™^«¢ƒºŸ)GøÃÜÆ<¶mÓš¤šñ(/ƒD^ø6n³ë”„00Ð Ð$þf;v2t’­±´IºšeïÎûº3jœÁúÈ‚2´ž²Aœ5!“˜ Ì„àè÷˰v«³~¦í=À$BIågHNÉBB @(¸ïo†µ0Äzh21 !臈V}-â¿_NËÈ–?ذÅÀØz:”8‰¨s.UhòHg‘+…‘VÊe0²ÓÊIa¸éaÙh¥×¨1"%L¿̶<Ç„‘Þà&ôgü°ÀöL{Ÿo!Îܵ¨’WYßQI8&¢<¦÷Z¿î¯óºQÁ3pv¬ø”ïðà ¤ª enÈxÜF¤xµ4Êû¨½”J£¦"ÆeÉ©¥€t:Ts2Cüu%$R®”eªØÎÒ„úúlâšÃàç³ÙÍUôŠLT^HöMÎö4©ø|¦1ž&EFÁƒùšêxÓí²’Æm°Œ7žåzu¼@÷ÕñÒAdTÇ˲òÛ:Þ—zêZc¡ ÷vžZŸ¤åŠ…*g 5NFÑfµH_]F²c# g¤Í| Vsyl8­qTS1¦ª»?ªùL]§rð( Z϶IŸbÂqke4ŒÃ™NNàç$Ý#)&x^K§Cq}ÂvÝ!#„Â!£ZÂCðKxCféKx¼i›…”èÕ°Íå"¦±â‹=9Î B5l¬ ˜öí²‚P‡^#+˜ _'+è×È &èOV¸°:úqA¿Ûû“‚5¾Ö©Í6)øR“‚».Åæ€ˆµå>¯šÃ]A,…ÄÂOY¹ m)Pùƒðq*ï¤TÀ¨;h'ú°ÿ©Tþ‹h8¹_/oÙ¤›|ó¿öŸ =JHîë³¹ rÛ wû 7R›mÛ¹{ rD¹K*¢r JÆ`–ôWÖèPRŠn„½}àM·×\ˆË|ü!ÙFîr‘iüTS Ld5?ðçBë¤÷ò©N½T!­ó»8ë V*| ›ÀØ$ìßVlͨ£Tôl`Ö‰Á¼oü$ˆôÓH3‚4yª ·ƒJßhÜó=k¥o®Ž„&øÊêˆï•ð WGž-vþ ÿ@2¡,endstream endobj 875 0 obj 2430 endobj 879 0 obj <> stream xœí[[s[·~×dúø–CMxŒûÚ™¶qvÖþŸëWÓá0ËŠa’·ÜÀÈé ¨ÿ>žÈ¶ëœãÍ7cÞ:g•kþ:Í÷ã o•Òh¦™æyß*•m~€V l“µÐ.„ko~O4(§)2LùOlµŽ³ÎÏùr<¡ þÈæ—ñDÁGçd¬¾†ñL¶œ2úÇ?u¦£,ɺɢÿï€@ˆVH‡IÉ›oÇiËÈÌ [f@¤¹0#çHbaåR‡µXÁ6­ÒHÑrÆ…ŸªBÓü4-cD5̓–æ'“†¥‹Ž÷ê”\RuN8wmgF “¶ãÎõj=ÎÍ þ¸„á@2|‹ßB£l.pvÆ8o^ã×ßñÇyIrˆ?^—ÄWøõMlëI.@²¦ÙKÔorãMj¼Ì_Š‚/†Lñ.÷_¦F Ô̵ „u•/2å»ìýîmçwÕ÷ŸlÌþ(SžÜÂ~Qc?_Ï~AÙ£v%˜‹°Ñ7畉T9ˆÎ„•´ë "3f™7‰Øº(¤™‘uÏ2Á›Á0¤}´‚ÁÖºæY"ÀmmºV‚‚ÇhÃD¿=oŽþÇYiaÞ®ö’™}•lÒºŠ_“`eóß²7~küRÇÆ¬†ß ÑäÆZ·Qpk½ÙXÎÆHU3‰¢è»qû¸kíìhúrgº»×üÚ¤'O#Ï‹à_½t³[ ,;ûõ„ŒÚâiÍ€çY§sÊ#RžR_gSÞl¢`¹q?S^×íâÓ&Ú­ùá~j¼Î‡TîĈájˆ¬Œ/®×Ëiаir»¬¡#:m•‹ +å¬R2[³EMG5aÞ™…§ü:5N3åÏ©ñûÜø<Ç·ÝšÏkæ“…}S‰9]ó¿»•ñ8f«Ýšz.k«¸,œšØQ L¿Ž ­BI¤y‘CÛ2ó®Šz6cÈ— /Ý:4†¦CUÀ:†6¥ Ws¨ ö¡*ša% }%:„•¬,$i:ÆåÓEOÆ¢kµê`{ê#úø Á¡*ð šE¯Z) S`G™a1Æ‘‘ïrýƒV(4D$1¨š|QDŠ’ãún%2Àõœ;)½¶ÆyÅë¸åý¸?–w`¶Ã99”Œ½êUBã}YcUô¼(kΓçáJ½Jú?â˜ú\ôg½Æü4Læg¹ñ ôPK:,Á&)âã¢>Þ¯r%Î@ìŒûM×¼f]ãM-ÜY/æÍ³ÍÛZÜ:¯õój0Ëë8.KI¯A~·¼DòA¥¨!­Ç”¶/×,@)ÁIu9ˆCÃäâÝTaÔ)² Fgï„>$c4«~Bhˆ½\EÃéi>$C_d‰÷Žû›üýšÒnjW5ë ©îK2a[ãs „qþ)Àì,täÚù&0¥>Ò ›À­à#wƒ[ÞDÕ&pkÀ~¸Øo·ì5ö\äT ™A©%döXÑ(\¬D[ó˜QHÈxBhë³…X3»V'ª¤Üãjk‘Rã ‰)å®I®Âøc1p¥î’[Ë´š ¼å´j}Í‹©A ¼[z f›^ÿ¯Òë’q,b:u4CÈŽxzH”[ô°E÷‚–âÑF@b?¹Á9Õj¨I°;Hݤdܧ†uU=…«Vb‹š!pØ}C Ék¯.8"þ!¨Z9ô­Š{QÁø8S(“‡ |™U\ôöÖ§C2ûJ´\3©GrS³„|Û§b‡Aaÿ©Â5vŠôÒ!5ä¼öªÁGåºt\r_"hè³Á’׈uùu=€PÀOV–bÛÜúÄsëú‹!+£!t÷q1$ Aâñ‹VTEß‘.‡®è…M¼ÂØ£ÿvò–ûÁ[Óa"*.d°7ð5¬agåíNqs£‡×SB*r”Û¸Ž{!spؾ RPÀ$äE¹‘:Š›ÆýA,ÒjÕ²‘:OœÆ”·[\y8Žô$Ñ¢…ƒ:…ô›#[?«åÛ:Ñœh‰øÐÕ‘…ïÃm ›í¸M Ô¶ùçí´*,e?/égéùOy»g›x{Ç5ãQX‰°p4êØ‚Š™jêñ\ìþc@5nø‚ Ÿ"•wäT¡`ö•3Æh”§¥² ׇ5sþÙL`3J m3‰ýo•T¾WHãÍõ]i®èвw‹7ý~µ0ÄmèêD ®O,ŠØj¶åY˜N'_3|¶h6v':H¬Ë ÔD°d¯¸+%ý=-5ô(ƒ%UÜ “+BxP“8ø[e&×902%›¦ßiò6iÉ?o „º¿vLûŒÛ; ÔZ´È«lîh$`œœñ°|ô”¨keü¼ÊóDûÎÄ9¢â·ü ó‘–­€šgF=308Ëk -u§‰²5sÿJžÒËí6Oé´h椇Äê,JÒH¤J.õ‡†m;ú®`ý½;¤0ŸçÊ—÷‰.çe1t–jå\*½N½{’–’SFú>+H9¬ùHÁ;¯€K‚(×Þ\=Ö«­ àé¼´­-<ÝÂÓ' OóåÖƒÂÓ{½éšFÙÉúwyªgï‘AvÄ'÷€¯È· céÛ@˜±T5­©E#WÑ¥b‹TE8±ÞLC+¬a5¥ÀÂŒ®`ˆr@ëþàºwy~=ÌÞù]ÞÄtŠ#Ûü”~#„Ô¥3ºŽXê}‘Ojý(^Æ}5MŠä$¨kÔ‹€bÕ2hAp¡;ÃýÒRØs”ý‹…\}õø£Àç¢>Fx´ÁË?‘ö?Û£G>êÍö-—,jL‹B/^ à /Sÿw¹ÿÛÔø"7ÞN‰‡d͉ÇgÛæŸÄ_ î±Q‡gÎÁýÊiâørEñãJZ\Sù{bñãu¦+9-~,Wh8ë†gã(ÿ[À^(8w̰#,*„ûëÒ/RàOj’Ÿé+ħý Gn“û6¹ß5¹Ë§ÜŸOwþ ÿvø½endstream endobj 880 0 obj 2690 endobj 884 0 obj <> stream xœíÙr9òÝ;á7ªº(ÝÒ± GÌÃÌ2Þ¶_øà˜¯ßL©.µÛÇÎ.AЮ–R©TÞ•©~·:luÄñïæÁÊÝgLˆÕÓ•qõ1üßYy·Â<Èjü³y°z Á, ntluíÍJ@ÀV _ÕVŒ¯®¬¼è\¯º¡çƒ1FtÚ™ë>Úî÷~¦)¥SÝoýŒÁ£2¼{Xìgb0–¢û G­uûžwOð«sV::óï~&ëØ¨(–€…!E¦{Ô>£•¢«ÖÊ.@‘àr6Iø •ãÃõö²ž2ÁÇÁºèiöz`£éî÷r‚k›öÅ…O3tY÷¬·(º{«ÕÄ3ù¨ ؤólð + ,6d¼ûIåœkÝý+/\«ègžUÆÓÙ%d– 7ìÕÚÏ^,•³TlÐD½¶âe Qü¯z z&€¯ÎÄ8æ\Xô²:º7ø±‡gHÖ82ÖÖûø± BufpÖt·óôq½î¿ÞÂGÆ/ 3GÀ!<½ÕÝaÜHBîP ò(ž—ÁãæArôÓ<È¾Š®C¯(óì%[´_z¬IKSX”úãE,зèdù‡•–RÓ¢šÖô(& °ˆ}ÑÏP“”³a—¿ÃÀw üÑÔ¼óö…¦Ï÷°èˆwh4Á#œPnŠîSöÈ"¯âqšæ,ÚiÄ6F‘ЧÖ`Ó¢½ÂXx¶WØó´šŸrÖÚ³hÅË>=F7®Xí˜ÁÿÙ‘k惖h¹[>\‹¦×gjphÞQøÏúD<7šQƒ†€)™±@œò–, ~(ç¿Ư"Ìž`€¡k#„=¢b~páNÁœ[‡B”là€q«Df*«×î.0„>Í‘M Œ¡•T–ÍÅi¢a¯³mg³óŽüu‚C–Gà<¶Q½Î³/Šo´ì«è:š’V@ÕõÝ>J3IÈ Fµ›Ïj£ô"K½ý^Ë%´Ñï·Ðï\Œ~¿BŸíNôÎ -™ 4o$‹âNiý…UTAÙ³{#\IÈÝ[•Pç–!ì«’†Ý­’ HÝ æcÁ›œýíÔŠø¿¾Àèá£ÂÞI:H„éÇÞÖ³oél"ôÖ`‘ÅÊ`~òi$™Ý¦K0£Uc°˜0ýªâfQ_>Q^Žn˜/CtçZiþí!%»þX·[¾"Ë0IÆ3ü(»Ë¼“gýÝ#:¿ý(„”ÔÈ. }¿Åî½ç¶+ƒ›¦!×á\Ó¹mNݤÅßèµhÎ|¾'Ÿ'yœq ¯ü˜+róM…%"J°<¥ÈA™øgÈ(þG³‰r8tNâk^6‹éVÝ|‚ËOèô®³0Ÿðcßó‰ïùÄ÷|â¿$Ÿ˜‹ä—O-âúf0.þ¤’azüT‘BJU(°Mdï.Í*f_P…©ùü¢N-¤ÕÆŠ/‘Z`ÑñÛÕ¤„\erRóº&%Ù`ò{Ÿëù09Ênèa5cÜuÒÆÍaáwÜIH.Wb5ØÑ×rTk‚bƒ5Bü^^¾OÌX‡BIca–Æ?Ë’€F™PØÂÞ ³Ý#<…ešcógJ9ƒ¸è›+VkÚHf„î Œjl¢“iÙýس m\h †¡ø¨ÍÀA] y‡eÑVDjmw‘rÁ´‰TRFPáªõ'X¨SZpP+T3£%±åe-P 8Ý([ígV 1bŠuÏz,e1eÁÄQ šé å°æ HAF곃ãYP#=?h4–çAŠbž>†i§€—v…iÇ ’Ôƒ¤â3Ñê¹Ð &«Ø‡AÌ»}À;à¹E¯æ·äƒDÜò<¡<€Õp`Ê÷ÆF ,‘Â(°˜ûÅr9°.¯9Ãi&¨ê^BhLºO‘×`„í*.×óv¸Å.W½}Œ]Pf]ªx2îéÁì¶*…ÎÃR”ŒENÈ|e3Ö5ؤoim´œ+Â6륂y(Ì«ì ×~–Tf‘š¦sõãRýˆ‚á GjǤŽÛ¨Ù’£ì”Ή+6y!IÀÇx~3`V©”Œ+[»5ª×àU9§•åÈ‘´d?¡Aãh°´ ÛgˆsŸÖƒË¬pI¼D"„ˆ€÷4ðÞ'q|eCJÁ‰*9Š$,‰ôNù\_£;®E¶—a Šp"Œ(AV#£ŒªEø¼R•j>U <7à 5¶géVï±½í«ÛyƒÃLv|SõÃi¦?¯½ÃŽˆ:–Ô`{›!¿A0î[E«ëò½”ÁŸN”8—.G­äoWŽªÊzè $žm7Ze,®3¡,& \XÐuV 0ÁÚçv͇ª”ç¨/DšÎÊÓVkz«REƒ‘Œúj‚u^)]}ÛÁES´Jž£!ÒB†ç_e¹ƒ°šTþ!¾Ã ߎ)Ú’áÓ,˜ó6¿‰;J<ßnÑx¼¤_7“†µµZj0ºÍGG *j'y»p[bQ—¹?„Cãu”ÝF,к»‹‘þЕ‹KOZx^ðH"Ed¤ÊÈ•…ªÎ%ya§J·Y,ög>7½‡yÆ¥U¶2{…µÕÁ½1«ÅN0×®ÏsGKÂBnVÑTÏÊ`S»· t"ਨ»àx•É-%hò#dqÕg±<ƒôf?þ à„„K”£èîíÔR6è‘nª(Na« xÙMzÈZº“ïká7|)QxBÝÝʃñê‰Ý"ñ)öòÃIj7|+Iìg<9¦XyäNzÈ#ñF’Ô‚°òüÎc0s³Ä†¬ä®e ›y,_Lƒ“4›â$«îˆa2rŸ‡,2î 6œhiÔ»Ò^Î0Qñ¹sÞ|S¦ƒ;\ñê$ö “Ü„ÌÝ #J«³]…Z~éªÆæó I2'-H/f.ãêÎû꘣H‘ ='áá‡bR{$a!© æE¼˜dpô)ó ¹ zj¤•uÌ×÷ß÷JB"ÏC4(xÏ+büÂâÉ‚@ »<-&*žW“g#ËFÑÜȪ÷ ‰¯ºÌô‚Rl¡Ž÷Üb#vÖ@*L•isg½ jÅ%ùoÖJ†.¦V9xoƒ”|A†O2¤I˜CXbaäqAægÅ"Í"]+—7·Œ‰Äj¹?½ÔóF½l‹rî>Ž,M9Ö>ÙÖï DL ¢bÔü\ MI“+yÔÃn†¼ý0_s)¨ÄHæ*Àú[oya8;êÀ‘E€uPx¯E7LníÆˆ ªBj¹¢ô .S>_»‡Ü½Bg}Ç ¬x5yìÃåbÛ{ÅÇ\,’c’ª?^þ†Eà ï-Å¿m±¯û·tl¿N³¹\:—ήñ->„¤­¾N‰š6†H‹»Oº¥WµÝÜú:Í(²g¹.@šQG é͵…¤‹ãäs£QäûÙ*HÊ+ãyEnŒÅ rßäâ†ÓäoZ<8Y"³­Ö¢êjÆT%¶‹F5ûDEÖ,'„¤kõ×%®ñg« Ûl;×W‡æ~ʰD€­Nßi 1º%ˆ&,–h¬#·2Øe¢R¼èt›ž|êÂŽ[ƒMËŽç›»õÏ_Ò|íÛÓ°Ú¹×wß.q˦åÊßgyÎß²©Å}9Mý¬>^}ñ‡!_ãÖçÀò7¿‘cŸ*Æ>z{í=êÝúoæéçnêd>|÷þß½ÿͽÿ“ }óŠ&ô'ÈAEHQu¤H¿]å¶Ô™–† šÿÍâêZQPNWø‰ó5#Ì ã¯l®­üþýñ¤å£endstream endobj 885 0 obj 3480 endobj 889 0 obj <> stream xœÕ\[o%Çq~_ ù D^|FXާïÓ6`Å—$PlGbÃVÐäji˜KRKíJÚ_Ÿªê[UOyÈõ%‘ íÙ™¾TW×õëêùæd™ÕÉ‚ÿæ?/Þ¼øÉʘ“×÷/–“_ï_|óBQ““üÇÅ›“ÏΨ٠æ¸Duröõ‹4€: úįvVúäìÍ‹?Ôäè??¹ÿ>ûwì¶.¢›Q³òÐóìZÿËtjæbT‡Ôãjãáç“>ün:U³µ.èÃYkóËôÔØõð<50ì!Âd3<×:ÎZ¾œN4±Ññ1XG6å¿áÓ5ª%МŸO§:?ƒÌáÓ©…Ÿ1šÒ‡úô_̬ø@¿šðWðÉèfD±ñ ´žµ‰¥›1êð›©.d3Ã’häÔªaF¥°É ”—iYµ²Ø†™­‹ÐÁèY-JÓT³ÖÚûÃMz^¬:kºùÙ¤™tTÞN§øvžæýžÌAضUO&·îdÆÍÑ/ºì~^Ðx5Y˜FÁ‚¾f®«ß5¶½Å½0ÆF}¸Á г5úp {×µž†EÿÌá ìéìýüá_C_åAN £Ãììbø4o&X‡ÑÖþ-Wࢮ¤iT˜EÍÀpœùklBVNÞídÂW§ß5¸ÇŽqv®,/-¡¿…ͼšMK_b}õU^gÖÙ,ã¨Ù—q\|}ö¡Êl}Ķúu"#[ µ,êEÑ£È5’Š,þ3¼Âîq+œ žËéEý5›,d:‚Añ‚í#ÚnG7ÎGªÄ¹ÌöÇXAÕÁy¤J[‘¤FàWŸò›¦s™õ+_}%–­º­•Éê= »Ž0\õl¬Ï†yáÝ_¯Ú€Ù†‡Z®=Èg±Ž–E»'`ÛBœpβlè¦÷8Œ§E7)&¢Þ55ic´Ž7m´ªsy›ì>(¾ð¨ÊúäÔê9º¸&ýöŒ9š$§âŒŽmjzƒvŠì&ìªR‡ÿÁ¿¾Æÿ½ªoéÚ2¥É"Rãû:ʇÜî äÔé…¦IMI\ îX=ž¾mêCÚmøþNjúWœO.‚‘Ô^\gº€³óÞèÓúúNö£å½Ì A¼¯ë›ÛFäM}øº iiÈôð¦µ|;ê.WÒœ+1íÓÑûFâùèá» ¿šÊÏq0a@ ‰©ËÙÄQs\(ñ‹ Cµ ,óÖŸ4U–nNƒv¹`÷Íp~ߌ¨š§'›82°—Í`·®ÉùA=½Äùé``ë©¢á-&ªF`['t%‚ ò¾7’ÌÒâò.ñƒð‡àÃZðþhÚº4Qˆmô´²aúZ¶Gï'gçàsxß2pÐ5«C…ïvA?gA°RJ £jUDüHcK„.ëq¢še¬°Àç)!%Wmš6÷ÆëH\áB4f:5¿¼íVÊ ÅÔ)Ì«”Æ;³O¯½­ªÛÆV%,5Ë-»mA‘™¡“¶\¯ ¡ÝŒù§_Ð`²"¯IDÓ'aÈÔR (›Lï(ú‚XºHíÈâ ‹F9”‰\Y~5Á Q`_9­‡LÍþú{ï »iýšÒ-\A ‚~×°Ã6g} !my†ø°B/ñ¥Õ£Þ*- ù¢†‘M¯½%Á­-KïP§uK™ÇŽ<¡¬ÛaTèÌ2—ò,Òr¢ö ÷?&0añU«Ïõ-œ¡âÁ’Ò¹±u!nJ ‰k\0¼5Zº3v¬„$)Ó1 Â?þ‚˜+Lª˜ÙãÑüwâÔĮà 0^‰‹ „nʳý˜Ýø+¶Ù¾ßÉÊ{©m{ E™w7ÂDl=  nE˜.ãÂÀl8‹üH6žLU‘ÿ§B‰'¶ ¹  1V‚!Þª!—poÀ‡Ç%¾ ïeãØyÎ2T8ô¦Ùاå)êG¹­ÏE!ý†¥˜,b¯¬v*‘2Hu/½øú6f–ÞœJé-“ݧ žW`ñ÷l|Ñ1àv”&!³D¢uÇãÞ;²OÙ†WOr/%Ca)7Ë€¯È»ûh‹ëíB=ræ°">«¹Æ_çè>‚mãZ!!Lʵ‚îb«’]˜‡"oZ!„¤¤mtæ Æ| ìŒå¤#ˆDfzç(žÖ-c¡¦,æñi“à9?c“°3«aèô hò»ŠE¶&¯*HÙp±«úâ<£}Ç@“wõá·íáU}x÷ÿ šì(-_Ŷp6ÑÏà'žýÆDñäd›ö„.íqÐåÙ´Zˆ™ìÊ$V:)‹çÍz7BIÙ˜Ft÷Iöã1ÿö-f<*Δc#»¤³‰½™-žwaøFf—< IZ…~«1•Ž%Ÿ”ÿlARý^"ƒ?s"£"X’öc ЗH¢#TXäd´ÁtzµåÇ@èÍ>#1öyÂŒìfÿ7Ký¡XåºwZnõ>ÒYš¬4çRYù¡Ž±î+DJkdúÜÓyTC]oc €ï¸_¦–µm v pyŠ…z­J)Œqè¥Æáz9~1CW¾õà#cRp+ûlλâˆ!¦žÖì5W· ú˜Ì{fêí$äOš R!Ÿl:¿8«E·æ%óq6!‡()Õuób‹z`§Iñĺ}qߊ]FÉÎmÅ=S &»2+f­™>Ìq±y!uêËìèx„äç¥Ë¸æ¯Z–rœàf‡C{¨ÑV\ RˆŒuÙ«‡D9—’<_¨òÐÃz)T ⿾¤{ÁsÖ]oúJÃÝØS¤3 5Îp‡µ¡’ƒó%>ÝWÔ~±ÕE cÈ2Ú€ÅBáÄykº ñü&‘,›Þú|ŠÁR\ÃëRÁy›öK qÂO§T›¢˜+Ô|lµu_6Ehf¨GœR­Sq•—Ì”o“›lR:“¿+чŸy1GpÁµkg ‹Î¶ÃXMÆé%ÈGi½Àç,iÐeëª-™aîðšË¡ëØÈ8dëã“嚪íACZÆâûýqIýÊjÃ:ºØõÐÜ€AT]?ꎈN)UÁlM!Žwµ ñ aËïë_éEÍk ÒÒÀh) ÌÉÍ0|FîÔ'…Öoó·O –²ÚÏkƒß6Sþº=|¼%îþ§OçÏ[Úø¡þz%j_lÄr8õW%<¹2âße™²Å•Ÿ—é'zøÄi˜›b)P]uJRQ:H‚ËÏݶŒäÒ€%÷ï[[F«žºn?Ï[Û;Ái†\ñp=è?T>À÷SÁQö@­/…¢U3ug•ÿ¿Xð}ë¢:“ã>¦†úÌ$•ÜQ¡LÁ›U‡¿IÞP±ë)mª‚z?À„›wº¿ÛÀ ©JXœgˆ\aoVý D!•P(·~< @”(”¼æ!@Á¸cÞB÷ÖŒjè³[0z;DÚ[úc ½û#xF!;,Éï£Þ­6eçåe)óºIú*úPë8@aVpXÁDæ$Å`~2PJÏÄ›cÇÈ" bù-Öw¯ÉVR`­÷rq"NçøÙ ªˆñOÕcˆÑ\~su€ôc@­”;Žj-†‡ú *–ÝCý],ŒËØ1‡ú‰…㪒¡‹³„ø9hYì8ö5>p õíCdʺkO™ÔÕÞ³ƒÔ–í°ˆ·SqN<{ÒAøx)¢*$qCzÇ# 3L°DÏð°»%32¸Úꎧýʲô9w©‚æ«—kýÈkx—Ï—öb[²'ƒ|2Ø'3š’+9Qì¿qžÛƒI<å6žüè§Ü.ië µ’"XŠ"ïã„|5¡âGÕÀtŒq l t®cÚ„ƒŒ+ûЮ؊ ¹°!U“ÊÛLo[Å—×.q²âD•q+)¢Ž9ˆÄm†ý<ü²0VŽ À;µîÛt}t‹§ x.ã{ˆÇ£Ä­kÏÚÿx…9Ïñ±(#<¤ïƒr”,ê;ŽaýxŒ‚‘‡…ÀóZéݤ´í+GaoËÂñ*VƈmÌÐEEšú­0ì?ÕØÅpc^ëQŽ”÷¼Ú> bX˜wïnhAÉJAÊj¸´ Çî¸èDpRåðqØ–]é"‚Ķ|‚ve)§l™ç“ëo"¢À¹§J6 ±â?FÍ‘‚É8ì¹,H©Ak™„Õdû?Ò ~Ÿsm+óMã?<²Ó÷‘v*ʨ Ä! #†…Y#øXYmƒ ¬Ä ©ò¸ûnàsåù‚±Á ç:«§¡ ,ê¿<_Ô‡oFèê•@òD ’û»ÃÍÿ8lÏØ‰=˜VYd,³\ëc v)Q ¿+ åû‡i_Él@ˆì•B¥½ÅsN§4ÝK€_+­ŠÀ¯4ˆwkù lj:x Œ·æÏÉÃ,¬W_ã¼.ØÄ>±Î`ì)VEj¼K °.ó¢ñƒ°nï€t 5CtìÅÏ6Ï=Œ´PzŸœ¾r¿@õCÖ{™í²h‡^'u©êiV6RerfÆ ½4ÊÆb¥‚2DVÏ>qöéË/êÃ˘À¡vfûÁûW4L‡#Šô‘‹n"4‹²;9ßÎþ›>TÈî…À§¸¥Ü|yó­-rŒ<ñLȑ햖îB1O8môaê#ÍtéçÔÚ•Ò"é(Fɳ¼ØgQª]WEbµ}0F,¥a—S—A¤JµO¤X$]®sý¼^Éb÷°ä—b ^0†¦ø3Ÿ«ûÕé{O¿Jѱ7@Ù¥$ëÕHYz’`=ÛOÕERý­¢þè]ìG¸p…!Æ£é1Ó$QŒAE/ºa=ù9¯¥”´q6öŸ´Ø”3†vn€Td› ln…Jxón¯nIE:Ôb¥r#Ò¸8ên•æRðqh•ÏèkuËqg9·¤TR°ò2ñ7i0¬£o¾äO¹ðL¹»¹‰Í%º9Õ)ÞÚõB*Scv—nðA•ZÂ>U4êÄ¢¼®ÂŠX!Ó†Ñ7 ï{-@F Kœ.© ´pôÍ¡Q…Þ’‚üsxo²\4ºlWÒÊGLB$Ñb·-¤CÆS^’?¢vgù扄<1›·âFQSŒ:Ï'½‡*w÷]ÂvžZÆV¾ç¹0Órû>MjæøÓˆÜw9ì“c-92¯ÒMûG|žP¾£" ù®KVòW¬†jÕâ_î’N/Âoñãžáf’°yM;+ÔKž»œfJ·1Š‚š1AÛ–iQçXø–cK@Ù®º i5 ŒV‡£ï›®HÖ™ vtn¿æÑ™sQí'ÅÁ¦ØªÛº]5t‘…gó±ü 'žñû!>¹äĸÊWŒ´‰[myøšM> )…‹Û³}{¿i¢?Îjã–Û×ÜéÐo\Q’E%ŠŸG¾(KžYÅÍ· 8,–ã«Ä¿í!äéæ|삯Ì€Âa–c°œeXȸ1ãÝ5ïá÷iŽî9§‹‘Ênë&Dfç½ynŠ[ K‚È{·OËÉqáµ¢êæ#¾“>d R‹*}è@Ú`Ø)~…Á¤‹*_ŽÞ«z]Õ¶úÝ–KÈÉH¼â@}sô^„½‰ø÷S:¸;õYâ6dðüni÷…„Ç®„Œjä?i3rFçÓ› +0Ý(Î:U¯´Z»ó¼æRXUAµ»ö´óÜ{B1<í¨)F|4c) b÷E' 4îÞCÖâÕç‘cPŠËo1þòìÅ¿ÿ ; 6·endstream endobj 890 0 obj 5093 endobj 894 0 obj <> stream xœí\[o·~Šþ½u×°6Ë;ù ¹¢A¤ŽŠ4MŒ@–dI‰tä‹d×ýõáu¸Ë=U±Æ0lïr¹äpnœo8{žïÛñOüÿøjï£GLˆý³—{ãþ—ð÷lïùó]öãÇWûŸb7‹MƒÛ?|º`û†ïk+Æ÷¯ö~ê\¯º¡çƒ1FtÚßë>Úîûþ@ RJ§ºïú—Êðîórùi cÙ(º¿a«µúþµçÝ×x뜕Ž>ùW ëØ¨è(ŸÁ( )2Ý=Œg´Rô­Ã2 P$¸¤†IÒø„Ê@qŽáû沞2ÁÇÁúÒ7}˜Wè¦û¤—ƒ\Û4/¾øMî]Þ{Ô[” Ýýo«ˆfòQ Ò)Œ&gƒg˜°XaàuÁaBÆ»o‘TιÖÝ?ò‹‡ý̳ÊxZ#»„ÌRá†=>üÊ«ƒ¥r–Š Ú‚¨O@¼ $ŠM¯boÅhïƒØý@ŒƒaÎ¥·Dsl¦§GžÔ_ÝhFÝš¥dÆvG0Ý .¨T®»†Û( 5κ×E˜/P@£ì.’Þ€X«¡ã)ŠM JJÑæœèŽÃ4œûqWEô/‘AJY#)Чô¾-=ÃFˆ2ë+‹ÑLúY¥Y…_G$EI.za€æº7Ø \xržâ€UóîIÏqXådçÂ8M¦4r!‘pÔ¥%¾Ï¡UŽÎ†#_a'>hػ‰4hÛÑFç/'2yRÞÌ,Yõ¨ðBö„¸ræPƒãªP}â`†ÙîÒæTÉ5V0Qé ÜÃúAÑHœ ó]À~¡0þ‚©PüÈáðäÿAÞ ãÈX÷ Þâ’¼½Æx% |ç'¹óeºõ«OOãxÒ€¢YÝ}“‚M¤IË^@Àmx~–oJc™âInÄ%s¸Fã:ð ò+ü¹Ã9ë%…·_Ö.#Àâadª{?«ßó x;‚çø:?ù¶ùMnü²4nî)…kK¸qQz¾ ¤§ÆŠ®Ôx_ç«D1ØßûBñqi<ÏGÕëéò!΄þÀMÞh¸gÉpjòðR ;YIº\ì‹Öµ*kòR¿6}/+Rc_¤Óo‹FO´òã¢ø·Ù_&] Œ8ËN£¡%^ãýy6A CÁ$øäA~ûU!èˆÚdj¼Í§Õ*ж¤Ù E«JˆÉ]ÉPFn›ã nõÀM^à„#>€ë;θ gÏ=ü#LÃŽqá–6C…é1Åmçe ,¥ŠŸEÜd>fOZ>˜ijÀ÷¬§ ÆŸgtïÝ ( *õIUÈЏ‚ÈF߈|w²‚œ¸ÑZ€U#ÏãIÑ*è*àë2Üy™'õ6œŠÆ0.¹£ §9Cˆä@÷a/©ƒËÌ[TIÉ=ºÏmD2ÏzÔE†s i† p `ѽÕžÈ 8¥dN8㟠ÿî3ÊüE•Àœ…bS¿>ÿ°šS§õÔ8fÖŽZžRwm` þÇ" þŸ‘õú8õ8w¾ÎQß/y#¾‰ïn‹¬K€J‚…ËÆ>ù.‘õ¦}½bÉ|«V8qÕÍî7°Dÿ}Â`O­U»Q»Uðø48T‘FÎjÖ”§jÒÓåiÅÿÔ—´Öl'ºuâáI˜‰+ôÙ[¿,¤2®mþ ƾÑT’®iÇ«~ª¢• `D¡Î[ðùEA"%¤|°Ðs.ug¾y¿"Ù·…µ}ØOù–XòeÒD¿i-öa‹Aç=ˆ—1këŽÅ9x³ébÎÛƒ£šÉå4ëX1§Už°Iõ`iœ&/Êà—Þ~9¨±ÒÉ~WùéUö4uÓOžã½ÌsÏŸ×hT"u½lz‡0©ó'DŽ QG¶%â;žµº.'Ý8ÒcpJz³þ¨öMvS-'‰™§õöuL„Pi2ªbÈ$=ÌöPÔó¶jë~ËWÄ\k ý×õšÐ|ük6€æãÓ¬…¾“JÒ9VHG`ÅLÖÖuã!ã¼Ö/%V‚:„,Û³òäYÉýtËué4yr‘Ï×ë¤Î`Gp§±žÆh“êI„`4Ûô}ä˜âDƒn['øù*fw`°iôñª‡PrT-Y‘ÔK¬u€}+ç AåD¬»XUÙœPaqo©P%¼j538‘@‹ÁìïT‹I~§¤`ž“lÛm=zuaI‘Ά{b¬fYL"y&ɹL*3‰üžÌÅtÒ–†.æ‘Z•)/bä.GÕ_ŸoÂú 9Å[„j«ŸÆ[ìÿ’{ÿÔÚn—@Ô ®Ý .áî-…ÄUHìëÓÍÔÉ͸®1üÅBØÐþrýMÐW=Ó)Å©Rß³Æ\¼ÑwðÖt˜O›4Ü4éÝòqNðVRííð–WÇÿC¼UÁ¨ØéC¦õþ3­ÅºÞQ¦õ^aÓ\¬%ÛMænÓï~Û2‚MWdúm²½;£´ W¾j )Ö]ñš±ˆ{¼–SòâÞñZ8ù”s”€Ï[uËuüÏ}¬xOá*øAn][ŠÎHùzT¡…OMº’Zi“N§"E1åhÄ“cáö'™Äb!ª¨Ú(Ô—T²ÉÁ/ÏÐG*Иó¦†qùj”šVj#ó£ý[Cd˜¾Km6Z}óÉ|¢h}îä‹Ö“õ–ƒÈBÌ^ã@3.£'ªÀI¼¹1:.ÈäEeɨ‰Ý:|™Ú6ªDò+ö•­È%xJ™3O‡»³ pøu€ËN–‹ C£hPg û6ª3A]i2ë&[•ùwdo[ç¸f̸ÀùP©Ùhk½¤ÀíN…Ö‘[uL[ZÇÚÿYÉ"uϹŒž%O‚}‰Ô¯#àâá£ùbQu¸6¦¬0XØÉVÁU÷Ÿ<=tªê¦½Sõó-b0¢žþ·„[ÔÿöWoÉZ1³!úÒf›>c“d®Gªëù"î±{4òC“_ P©…¬ùj;ãÛÚos¸ø¢95­›©¸p‚(nü‚‡ gGejnHq,¢þ¯Ë *Jj/–rõÖ±ô)@(4X”Šôÿ®²§T|1›?lùf%Æ~bC+ã·(òÛ º´nGðTúSå]“oHFTÉ€l̸§™¨†ùäŽÅ-&Vñçëž»ðc!x`²Žþð=ãñ×HÙDüÁ‰”r;‰ß2Bì¦s••ê¤ÐN¾Ë™¼(9S«n©¡É—W½ñ0Ûοµr‚¤‚£20éµ”å=wÁ#  K¨Ù2–wØ”>œ­Œ ?ºqNý}#¦IÕ)Z/šL*fÚ`2Ûþ~†ÃÝ¡› QE^é@ fœGq/gð’rCAYTô‘°só*pÊ“ÕAnÿS+\* SŒ6#·FP¤63Cí‘SÒäô’ØhÑ…æe­ƒQ±VÈwUn†û«°6ˆ;b—×u„ò›“9Á³º)E¿V»ö¢¶FQ^ò㸾Ï÷þþ Å“Sendstream endobj 895 0 obj 3598 endobj 899 0 obj <> stream xœÍôb3Ob3ãÿóß§Ïîý(”Úœÿr4o~Î^‰øÉ&ÿuú|sÿaüÌã)ÌAl>9Jˆ“ëõ$äæáó£¿oÅÎÄ?~gþçáïq˜ŸÙ0%&aaäÃ3øúËݱšœ Al¿Ý‰)¯Ãö¿wrûýîXLZ'·Û7_§§JûíðTÁ´Û‹Mð\Ê0I±ýiwlà ƒ $K>À§>ˆÙÅ5ÿ°;–ùüOmÿ¶;Öð3UÆãT_ÁøYM‚NôÍ9ëè”n™ÿ;ø@ÊIªP†)%¶ÚÕ-ã„deØò á%¬(~âre2,^ `šI›”œÄ,d\j’RZ»ýóNNólUÛ n}²h]:‘“SÁ±\¹œLN„ŽõàÃ{ k\픟f¡ÕöÍhÖr{'öq«”r{–V°³ÝþOg?ãÉOòã{9§#}[,)§‚›ŒÖÛGíëgåu› Åj ˜P€Á `÷FŒ !&…khܯÒÛ·ˆoøÔa~ô1Yë¬Þ^·U.Ê*mà]˜LÂ* †`€- ¡ ¬†©þZ‰ý3ܒƳéñB~žì”ƒïEؾÛy‡Ó²È›FhÝ–Rˆ>=ÃiZþlR¹½Óž’µAZ0&x+ì+- ÉAÁaÍZnN«›—‚YI¤Û~ƒü„T&(Á'|^¦õœðHÈzðfJ|ÿñ(âgМ°ã³('£„‹'8‚Ñt‰ÅC éíy†¶¬’À:.{:þ2v–ikûÉ éO#UÜ®†óøgüiãvŸQJÅ/a# z[ۉФunûz°Ð¯;£'æ´»Žàp‚ËDêŸU<"ñž÷Ud”v‘@loᥤ’+»†}@ï¨Ð¾Lk2Öø'qJ¤ð¼±HàpLi§•˜ù 5mãºn\+àTÙ$Ú_wø8Bâ¨ÍtÅ‘ZO+ˆwv@7¸æÝ<ÌöQ´¬åäÜh#‹Ÿˆ3@‘ Dò „)"CÙÈ蜽€zQÈ32*„6ûHù“uI‚sIÒaû1þ5‚6€‹§H‰åûë4IM‰·æÀ›f€jAV-—dx(÷ ’…Ö^ɪ’3',8¸0FûE¶LÄx'ÅWø½žÊ!¢Ê(ëâöâfQ`$ÕlOE8ˆGÁD$­QéuA<_—hpU20ˆ¬!Ä{€­KHÛÖü«g¢q5”œw†Òœ i$4]$„²:B¶jÙäÇÈÍí\¦öqò³ &ïÕ®[v°ñŽ»]‡BÔ‘J‹î?w3PŽ`\ãS@Ä\ب±QÍ[„ƒ`ŒÐLFÕ ÔŠ($pB£I|YTümÔ£ÆR£I¿hf¹HSy` üwÌEwÓþ­°$9Y5~=!·fw7K#qÖBÖEµEŸo æz€GÖëbZ÷†id’ =‘8n,¹© /ôT7CFPSŠ ø¬­W¹áÝÜȆFm¾™©ãgТø41_2Püäçj}#¿$¾V‰·yV©|ÖhºÑäU:?„ÈGD<´¶Ï“°aU3ô(ÛÇNpL3xÜ:›èeã·5Ñç´àêY'‡õX MÎzé‚Ê\ÐåYÛYS3æ~ ^PÃ!ÃUtæ<¨tı@'4Œ#xeÚ¨5Š£4 hÐ{ü; W ¯ ¥ú[Fzð-ì=x@u†âè 'ãq0­¶ÆC ¯Î¼&Õ,+{d—Eq'R ò¯+‰Žu}TP[¡£ad«×Ô—4QKà¹ÕÓ}ÞeSB'œ=qwÂÕ¨Á)pO¶­Ñ¨.+‰´w®(†e1ù³EiÒ&²a¼QÑGmŒA É.zo$Z²Øu:8j×áGÄè´IþQìFµ4À`z bÔ¾¿1#áVŒX}Q%(+?åË«ë‚dJ¦ÃЙ¶×a"ÙOÌÙ*âá@欕Œ”9;ÁH†¢› dH5í b$¡Ä´'à#152,ð›ÐÙdž«ä Îb¡ã^UÍN6½ÒAüÊ0f‘:,sÜö,ÊA n颥í$µ‰ í¡œ.¦ „~Ó>onlwpq5$&t§C²-w+Ï2ƒCüj%ŒvHÏÛú½ûadõ~Q÷n-w…µcobÄÄ}åƒÍ§#£GƒµÈWÿÕ4a~·Ù…Cóƒ)á "$ÅöQ¡ŠE‹£×m«ñýßá€pFd!ϘgHX¶Ò V“Å6@6ÛkfIr£k.ÝÐ1±¦D0ÐIÜÔŸZè|Póz­rÃΖ@AÔ~?@’B²S"ʆ¡Þ/T‘CŠ-ó!l’á%FwÛÏDBšQ9£ßD3ŽˆVþúáÑG/6 ÊmÌavi|òÔoàä þ}úüèþƒ£{þ¸yõòõã£{Ùˆ£{ßâîÿ%üõà«Í}ý`óÃmótÊ©¼ÆEb®îÈÎÛ_ßFGêSlÃõ’octÔÀ€«°jaæÉ~ X:W‚»O^¢¬351FöŠÆ­3Ä$ê40Z[–ªö…]A´/)ËpÛÞXÞ³Îh¶¦ÀgïO”H Bf%0#ñO °¨f1]^$ŠX\«óµO»ˆ5&‹¬ý8òKÃQ°ŠTÄ<ˆ‚½~P›™ã¢ó$[z+ƒ , Œƒ’Bü©—¯5üÿéäXhw&ðyG—U;ÓŽ‚zBdŠ>4Œ|‚¦MNâ–ñHqÉT¶ÌÍ–À<&FÛk ÉÊ$aÈ­†‚’Á©°Lu¦$ûË¿îR‰sœÑÀ¹¡žšˆ!Ò”.ÁÜ€Tc}N Õ²“‡]6±_NÌìaÔiF†yAÄÏž¤££¤co,F‘…þøP³Ý÷ù­ F˜…ÙãŒÕ¯CŸ?O©¢0&Õ± ˆÄùá6Q´Ç c¡h†]=À.!Ûry 8a×ÛùZ$øÐaW°lÌ»8XÞ$}HhõÞ }Y5‡š ºZÀ†®F žÁRÑ]@H ÈB\íÑôÁ‹8À¯Øþ/þ%eT(ä”Êéíiýwýãô⡉¹Ô{°¨šë¢i`Ô]@ðþº>ü]{xøK$˜†ógí«—Ad;m÷åáU}ø¦þ*ÐzC¶Hö}Yž£ã4G ’ç€àO­<‡$ºŒJ¶°È£ÅpóŠ¡ÐIŒ¡)^9!ÿUe‡ Oÿ~´F@„ð £Ô‰0ÂOi)¹hPŒpÚ°Ò¾£èŃû¯ÝAÊû|ÿQžŒ¾nãGÃ5þÌ…bF0Ñ¢S1hÂÅêÂzf§†ue Éòg>¾¿ìB”¶r£R⑘2Ùç&ÇÀEX† ‰‰)²ÿ-I,6÷If´ó`F«AÜ3f“c¼&”xJz´>'1x¢‰Ó^µkg¦è˜n,¼[§”—ɲD:Ù­¦ý(ÝßeÃ1Ú„éúÆ«Avl,Vò(ZËøt¤ok‘uü9­Ê"©äJ ó„¥sÉðk§oà“å×É€Ä ?Û‰†ò\¢À m–ÿÑx<äƒ6ràåÉ ‘¼iŽ×€ájZÜæ¤;†7 Ë—k:KHgH»ûˆ?2²«§2e@eV‚¿,€)z’\©ºlæ\)3°ºÛB†áº‘ÀÕÎŒÁmµ9Ò·4nÄÆ¡¬) Ê“ÚTthêG,rOMGV[ƒ£ñ¼ª8±ÄE­œëwÉ8…a!å¼3nmñ8y6b _œÔ<ÍÉ¥"4­—¡]"y‹ËD÷„ì¥Ã®O¤ÄWaSd:hH˜ÿ‚Ô/½%a­—q£äYž”Ö&²¿5±ˆ¡¯ÔÍ”æØÀ>–É Ù–ìœÕ—±É4zÉì´üÍ53B´ÅZÒp Çà¬=|<0wŽA•º·v ’]ëþ?9xAú˜Ž>š½/Gнù·CW~òO‹QŸ——ìÐQ× I\òš›»o“WßΧk¸ƒ˜:‰`#öå‹‚¾«J%O8=ÎD3@Ôÿ¹Y¯ôFˆ)€†Ø*JOûˆ‰€†@N{6Dš‡ylÿÐY,oB‚u­* zf…0¼ Â!zòFÌ!Õeúɤü¨ýé‘èâœs½(s¾ñfÁÌ/L($Ì‚ËÃhðŽ¿ÂÑø{VyúT‹ lJK:Ôî¾€¤¢}æÝKÅ*<|ÏÊ_ñtJ0vÅ5tÍ/®Ç0R…ž’„k}"ƒÛ®¯éó„JyÚèîÎðSÆ ¥òz ›Þ]ÔÕó¯n΢Ñ­¬ñÖÀ ²V}«\é늙 ¹f¡NÚÏÕ¾¯‘[Ç=ÇXSmhóÚ ãìΈI.‹¥lþªw)“(ã$Ë‚Á’¿7H2%¬ÖŒÜ˲º?èÇ~¶ Y Û¯„O'hƒbˆ9µÜe©d8Y F,4(Ü"£J¤”´®xë*|0ð9™–Œ/Xm¢$™Só„t’¦r[mžÚE>bå¬Ç+=EWƒ»Ÿ^K@Ò?  5.±q£ˆ³Ôì?hÕ´£ÒY" ö•ÎJ™(i4ˆv]D¥|£ýu¨žBšyY您2É’hO%–¼HÑq£µ¼©²”:5´®. SCaeÂW9æF4w˜œ:ÖJä¼µ4±ŠpŠW…˜¡éEp ÏžúÊ庆o@T“`N¡õâ#¥0±¹‘½kc¼Ý`óð.WûH÷Þ­fŒ=q{¤~î«ßçÕ`ÝÍ,̈ŸÛ£!_ÑBi¼kD’üOÐLZ¬WͶ9õWjCbÚ¥ó~â«Zå[HµµÑèbÊ$”è&o?]ZpÁ¾9ßfœ‘ðøE®ER,ã…gÃôÞ (œ}œyÙ M«”Aôþü’»6ç;Öaúfèªÿ3š’Z‘öá}Ê Ëq2UåbeIÊk]B–Ú¡ýb@Yí±„rÿ=÷ÛÇv?s|Jïé½ZÐÒ¾´åyZ|nɺ±óoR\ï6j±V>‘z¢b½¹Z{4¾iaá‹kÞN·8±?âM(ŸŠè¸í¤«Ö¯ÛÀŒG+ȼÆUîäGC$ßý41–¥jP‘äªJ«UÛ¬äI«þØçß쳸+e˜µa‹VüÕÒ‚ÜðtÍi¤KL-ä$gŽöŒ7êPÚxú<ý~ã¿ã–RF›³a%üP¸& 0ÔTbŸ¤5B˜5¨åœ·¿PëŒ@Ì¡¾ 8ŠÌî|öG…rJ8ÅÚ>T3(Ÿ§÷ÅQûšPqÀ¨ äÀ +§9 ¥å~MãªF’-ËHÉo3ÊýfË‚t#ÛI…ÎT×"õ`1ä—Æe%iðæ,Çx´­õÇO'i_¦f³‡Íɬ™„ðØ)µ¨šÍ|ÃN¹‘m˜-¿Þ—W© ͪWø$vYZ[}½E˲,irÇeG”¤f,¬J×MŒ® ™ƒXOÌrè´"H¼9–íÖØÊÂïîé o Í"JÆQŠ:qûð|îk(·Säk–NâŒË²|VšØMRžvYK.ô©?NøŒw9´[~òK*'“åk']ƒ3Cô«`ðME•ŽqÙ<;þAeÁ˜ ô ú¹¥"ïð `¥AzD—«žÑÂuúÍ忬—ú´F†Ò z²«×3­(HМSS†Âðšd·§ÇpÑV*\nxóVÝW$-u,Ùkêõë]xa¨ÞKçc¼Ç…suö8ׯg2‘”mŽýæÁ9ÅNá Kb4Ý(®ÃÃø+MÈi¿ï­T>Š!­ÜJb¥ f³:ª–”tCXnK/‘ÅYeÜj–Mc‘,û¥—4Ó$½ßkÛ–K/†Ê¢ ÷z­e¤ ѾÖtàÇÄS®”Ãà›w±¨÷`HÑ«¡"=®>N>èÜÊh ~…RxØ4fA»‹_¤·ûÂÿ6 äž³¯°pÁc¡¹í§AÖ÷íÖÓ˶ú?rƒIHÇHuQر3›xŸWÛ6R‘CÁÒuNÇ;Phäñí"õß1A¯Edϲ¦2Uµr3YáàáÅNÜωH¶rÜœ¹èêªÚ"ÜŸÜÎÌ+Š:£ C¿AË)â³Y/éÈôY 9ÐñŃ\eÕH2}}ðÍý&gx³(¿]o°e®VžçKm†;Y'þ ƒ¹ðý,ÂÄeøoûÏâ‡Dz—÷•D6n(ÌW“‘ºô¡Îè’€©y^¿l©Ô¼ÌŠe©GZ“ —pC¹·V$Ì .·9Elö6_— 늌ö]ñîJª×+4Š—CBÆ]ù~Hl7 ŒîYލ[4FÖ#Ù ‰?ôßÈß›¤CMä7BÀßöߨ–.2åÃûò­ ò:œ¬ÿ àÄ0¼öÔ±Kº~)‚ÿÍ~ H…CíD ´o`ebBÂ/î%oÎóiŽÁè)Xº¹§œ¨¾0¹MshÁ¥n#+5ªí±òc–rו #7¶M¸d¹·ÙÓ5“è,»7¾]Ôží>3K2Un-’ˆJ~½ ±RzRñ¢&3ð5qQ“?’KWn|ÁWš$Œ²^ÔäôRãú"-„ÜVc÷‰©TF¸ÌN£Ë‘ÅF>¡¿ßîë°¨¬ÁÎ1·LLø@›0Øæ Ò›Òz‘Z(jolî¨ÀÐD ¦Û4ÅÓ¿[3¾9­s¶&SPÿ±Î<(Þò±º.é À%ÿ¶ºä·uÔ[¾äY}z–ÇåþØ‹\,/h;¯xo%óåáùèamU(°~Ãa=k°~SyË·~ÖÐódWº>®ø~^ÕÁ— "“Ë1íû÷UÅïGÿr ªendstream endobj 900 0 obj 5979 endobj 904 0 obj <> stream xœíÙr·ñáGðÍ» w<¸1•Jª|(ŠS.Ù±éGv¹(R"e/—4Iüûtãl 0{HtìJT.S³Àè»ÝÀüzÐwì Çÿ¿'{Ä88»ÙëžÀÿg{¿î1÷ÊAøçäâàÓ#|ÍbS7ô;8z¹ç'`†h+;ÆŽ.öžÍ†¹šusÞcÄL» c‡Ž÷vöí|¡:)å f_Ï •á³Çùñ³ùBtƲ^̾ÀVkx÷“9Ÿ}‰?‡ÁÊöü{¾X¯è,ŸÃ, !2³¿Ïa>£•¢£Žò*‘ಓ‰ó(=ߤ17®æ‘ Êqä› H—aIZÙƒ|g_†F~Ó"ÃY ¹bxÝxÒ"òŠvÇFÀ@‚vC3é¿,¨¨Ø?< ªþ òmn< ƒ¬!´\ƒÈú‘xskI=|”Â"ùBkÓ,8ô¢:/@½µí™×ë7Ù’žg«ùÌ•”Œsä1Z.ÝKGŒžwJ 8Jrã kð¶´@hYSsVÎ ý¨^š.š†Ÿú7u¯Ëá:…üâ ×ûz2À7uŽÁ¶¨ÑÞâχ2Lm„(byq³§Œ.*” ‡ÔÍG(ïQÊFð±•R„A§Ñ» ³Àiì”ÐüåàŒa¬ÓŒçë¹’`’¹uØ,ãüwc†á0²(š”¶ãþòn¾såC௞E§P1¯©cžÂ©x§µÑ2`Ѝ¬’"s ¥'!Eô/Ÿ#%P˜¿óžÐbˆ<ÿaž° ¦ vmaƒÆ!p)#H»·£`\T&r¦²wy`KÈW -ºñ;ôßd²Ô§!s“#ý@Gó«çõ:ÁkØŽé‘ÓØÖS£XG–rlq'í» Nú×IPp'iÁ-%ED³±!•‹[Øà¤¼ †Õ‘ZcS¥ÖØ8Rëà?b𒬬!»áÒ[Öö|?7®Zýh†€_ ¾[£'ÀP`ç]lñe ŸÖ`ê¶Ñ—!ˆ7`)F]ÉÒ½$OÀwÓqØ$ŽÛ«6ï*é•RF k6A*T"º¨cŸEXD‚8uH~cuHRýWDÉQ»¿¤ÑaÒ`cSóa /F­ò¶¢ánˆ¼ÝxCÚ¸Ûò´F 3ø½Ã‰šàè:B€•_ý( ÏOÁ¡i 4âÿ§9ÆÓŒ3㢢ì^£ã圡é&8m†I„KºôÁ ¾©Â—›ùíXŽá,î¹â¢Ça#¡;ÃéF‚Zöàň­¾ôS>Çí›”-z98ï_æ´H¶-"þïçPò€w­ñ2?À{ %¤´|ðÐÕ8¬'ûw4>µ\Å`©iž‰E[ b„ÁKñ-vPèiEº'¬ó­¢ƒB­"RWk·ðM'vóžã¼Ü:õ~wK´ƒÎý˜níZzáR/¹‘U°Ò»…ûÒj~ù$BEŒ!xw=ÀÒ6|8€‰‡´ø=ÈD"`±IM;ø´ ûÁ%x‚”.aÄ[¨´­våçQªk?¯{*õ…ìz>´sÝ ÕV v”{5'éÛ˜àC>úžÛ˜áô©»ŸðçuJx‡ô©ð˜l$iÝeê¸IS!9 š¯aö1¬U\¯Jbæt'ÉR¾N7E0eü Óni1Æ&¦Ë€’Ï@ªÙ£Ô}UŽs¸†‹ìíª™*ÍùW’*]¶ݥƋ" ›=Ìzb1%ô•ûŸ¦Æ'¹qó›(Á™æ$Å|Ý o‰}½“ž"´Vím|,_ÉÞ¯sÁ°mà$A!JÐI~™Ð?¾KZK²Ù×ZËGʺ:–CËUOU—½ýJÆÄ+žÆåK~¸.“E˜ Å$£%AÌt‘TC( J@(ÁpkïZÄC"xz0æÑ„Ïëî\”|‡’ ä°›, :å@‚! lYÚñtNÅÁªžt ÕÁ:ÿ$…Oç†CžXøŒï{ÅcónßÍù¨,èùÆv* ÒRÓ #…qö®u~¨Å…2ñꪅ¢ÌHÅþ<™œ¼‰ÚìÒgv6Y±sõÔa×<,•θ SQ7UmÛÊòŽ…³‡¨ º½ƒÕdï0ªJ’æR!ŒIæXqÏÑÉýóÁó‚Ó«áÏ ¯!ÃÃæW=aÊ ÌÆ ‚a®DV˜.8ã ¥ùèÒBØÞ‰î¤hëÁõ—õåZ2üÑÁFÅ-Ô+@®è•Qm·¥Á¸¿‘ñTæz‘fmYëåÅÈ.Ÿw”Y@ŠuŒ‰éRƒé]nü•TIîJY&h™üÒS7GaÍ:+³WwGÊÍ@*çäp}¥ÀNÚã…P¸ag»TsüÙF?5È>9¢D¨ïõ£QÎ)*ô¸Ÿ0ÖÕ>‹³Pe™Áá^:‡ŠöÞžûÃcD¤«³iØXWy|u!œê’em'œ?«k;þäÀ¶G;êp­:‘Žº¶SŸupå|þ~òLÏö) ±á­Np*u ‡ès6¥œÕ~e”+øw¯álˆ·0E¸Jú2ýùisúXâ™úž¿[¡'¿¹¦Ð“\Á‡,LJ,ÇÿX–ãQny—Õ7U›–­Õ‹È6À1>º!´)R×z¦’!ü-S rd¾Ô1Þ‹?„¹ÖbjžbªvTg³Z!¢ ç)%žU¥™o¿I)ñ÷-ÅïÈ*iLƒŸ(Õ¡‰"R\z5AÈ(}KŠñ  A]¥W멼‹ÅEýÁ¤†%‹ž¦™êúÎèÕ\ŸhWzã¢[ÖÏôc(¨A€¾¦f”Tr²fäÚ>ÔŒ>ÔŒ~ÇhŠH¯êŒîÙ8×±c’Yt]zƒÛäê褄<$õbL‘-Ü‹oË@­n,L÷Æ*ì;Þ©d´S±†D*µUŒŠå¼íyrÃ)|²^sJÇK<òqâd¾‡|TJZíJK›Tª‰M&æ}«±Y*ój¼ÃzMhÞù.΃ÄF%û´¾*”£vñU!®‡”ÿ\…Ÿ²ªm<Ïy“Ñ5ÁQ‚¥®‰p-]‡ìÿñ%zçœYOS<$ëðÂvc?ãcéf¹hºª‹Z‰û—9Q!‚ã ;txiË[f§…¶›tÛIz#ûŽŽ«wéÊÏ´æ‰A¸šÔèîŸ+ÎÙúÎÏèƒí;?سÅeûõw~²¸vy.…qàÕ¨f‹™ÑXãñ2L¢ò©)4â,BN+pôÀ»~¨Ë¹ôõK£¨$#…a·“­gy1ôk8x²íœWqØa\:‘²ÎÄÕ˜‰xgêðAqk¾ªº“£uEå7O”2É×þ„·Š‹=/êX¡ˆNDiÄ»+ˆ ‰'—!G!ÌÛêv_ùé”?gC†Ÿ­Jw[ŸÏð§UßA57ê0$€zßÁtŠŸkˆãŒ˜jþÊWCüñ€ÅÄeHâ8RГd@Žƒ0RËrܺ4–ë¢ìJ>A4ÐHÑSZCô P¢ô Í舆?·xÁPvík¨þ ø 1b̼Zbã9-z4m›Û}tH”ߘY÷ ç×xøVц~3ŽÔØ¿3›ßaŸànp†0asd¾ÝEãàôà°Lº‡>ûÁö[bûñKuŸ…¯E™‡; ¹»ÔK|C´}‚ˆwR•ìöÊ…'{ëPØî³ÑзŽûQº—pÿÄÓ/ʃï!ƒèßÇ2è–ªýÉ!À v^½Û~àAHüdbî-–R¯?Wå'Û6 Îô°M£¿ñ4„/Y ÿ‹‚Ý<Q==ÁÈe‹Ï=¸ïCÉßþsÍýð㣽ÁÿvÃåendstream endobj 905 0 obj 4388 endobj 909 0 obj <> stream xœí\Ys·Î3£ÊoØ7ï*â70IU|F)DZcºrØ)‡%’6EJ”dKÿ>Ý8ÌÌ®,'.—“2EÎàlôñõy¶aß0üü÷á“£ûåRnΟ±ÍGðßùѳ#î›lâ?ŸlÞ=ñÍ<F6òÍÉã£0ßX±1N \lNž}¹å;½ðÛéü »9Vu“|àzžœAë÷vÇr°vùö;>Œ£Sãö;±ýtwÌ¥´Û“ÒæƒðT*·ý+<•0ìv„Éx.Ä8¾ý|w¬¡‰5ƒt$S>À§näÌú9?Þ‹ø þ'·ÿÜ+øueêC½ý™8èÃþf¥C’u“E‘ñÿ „„S7)ùö“]Þ2Hf†-3h¤¹0#çØÄÁÊ¥Žkq‚+ìà JÐAŠ3.üTƒ˜í;10¦T'¥S3?™4.]XŽSrIó˜óq°f4,Çp¬—0òö¼€îÐiøÿ¾Œåö9ÎÎçÛ¯ñÏ[üñœâ3üñuj·}™ÿ'?{”‡òí¾„ÓCrÆ· ­_—‡/òÃ{p®FŒ²ˆ‹™–Z0øÝ’îZnsòñÑÉÝ/·_móƳff¦/®¢`¢êíÝüúiÝï6î×7„“šãô$üóû›ê § ‘žTDR£]”©4SšÓòþUO¼žS‚¦\õZÆHAw’§òšÜkYÜuiHß.RyÍ`²¥ä­çbáÜ 2Ÿî$J&=­†~ª _æ±ÐAû‚†–£Î L§µÜä"¬ˆoCƹÊã<òG *ÔŠôËà‘ŒÇ£bœ t&#¤ -n<)Ò¨/ËT‘Ì’Û´f|:¤¦^*…5ÀþnGïçz',<£»’vKøÂ¿È‡pV=Š ìüNyOš–÷åµÅnh&¼ñ å]kI§«ôÎNS´áì __йaF}&’ZÉ"aé€=¤Ý~_|¶<ÛUù¦åžý.(cJÁDuª0"œ´vó æÃ÷EDof—Zd& Lçm­åÄD+*= $¯#Ög ”dåÒ¹@1Iùª0[ùVG…âíž*“Áa¥èçªÂîT*⣉’`<-gÞ8>pž´…Aþ|T¤ΆÁkYž=#kxYËðU%‘µ¥**pŠ;ºËhkà’/joy€¦<°i~AÅæX ˜Ms*7‘z†)ª aO # \%½KNØÁ‹TæNlÒt–ijuž˜•pús\tàFÊ/JªES^…Ð÷Dóa›¼´Gž€~Ó¥ñM DÔºÈÊZ˜<®€h—ýÚäØŠw¦®£L%ÈÑQ·—ÑóeIî¾Ï­qFÖQcü! Èkœlôj2ÚNæïia´bA^N숸gIç½{ ù(lí·»×ÁÀ¤8PÄñ¬Qô>Ò˜½ŠŽËGQ¹.œ^–:^ž˜´¿|Ñ,6hvÍ­µiPEQ­ÈÚz#Òá|caÍYÎ+MÊs\ó¦³*#›Á‰N¬%GYeìgšŽ y¾ÓõÈA¯Ã[Ã7ãV»nIf¡Æ62¥ÛC•¥O47þÂ_qìm |¹ ‚”7= •bÌ‘D"?O+‰ ¸\ƨ¨Ãæ©Aü£¦^@œÎR¤²?âL &_YA}ÞG¨²#’nt6 0NSCà5mÃÊI$ã–ß áIëÆfúÓˆË'¨ºÇ¢ØÏZ‘‚î;©Eí¶=!“åNM›3Ïæ&@02e³ê§=ˆÑB|! 电)@O:¹p_æf‚L¾Ûi]¸ÍgëÎ5XßK3ÑÓØö!±ÒÀ”Ø+`Ï·-P±Màô¸×Z}W†2q5ì =%ñýÎÛ#%ÈÛŠû%pº³Û4 FÒJ/z£,ùèLÏ”G3Ÿ?&K8ѽ^Жav˜Ól×á9L€Þt (¤ÐtÕz™–øÕ„gºJšÐgˆÓÏdGôàPO‘°Äÿ87r›Lc[$Œõu~8—Eéæ!@ ÆîI””9Ê: M㵓™þi”˜Ù+iØI£È6\0›FñÏ~Fi”_r'?ÙÜI9$€J†ñ–GWÒå\Þjº‚ˆâÓÙ -õ޲™òPZ,ù d+¢òIr†\îmA0r·Í%;&k VZÇþÏ×éüœñYž5¾ïî¦ðuïaצa8`¾çÕûé"^ôæ+Âç3"YVÒ"ŒE¢ßBfDŽÌטxÉ}„X0g€ÜF8v³Ö* ·å€ªP½E­˜Œàd3ú£v¬ŽÈß¹øA°X ˜ä@ >ÍÏww)†™yªŽbà\¤¨¬Ì/a‹Û5t‚§×ÏI’O'÷ Ÿù (ÕD‹{ä$Èû:ž’át]Ä¿ ñ‡õ;Œ=;ÑjÍæ´ÎèýGY’%ò„®¯1¬cCEU“3!AcŒó‚„;p—ë0—g‡X!AÿÅKP?ñBÈ{€ Lõ 9ÆcÒ·èŠF0º’iõ03iôýÁÈÊß6„AËxý¨?r{Õñ-Dý}uwƒÅ<Z‘µD¬ä8–âÉ)d ¼ Ë>44<…+4ýÿ~d‰ S&­ækŸÑ"Ñ 2ÉTä<Í Vaµ`ð²!ÍrÃ( "g;2\z#†$Q$p|g²ÊŠ7 Zd][¥ê“b$a`…!ƒ.ObGŽõ¨M®q¶À83"8"LäÝìf4z‰Ñ‹?áÄ â.äLðµË;¶iÇ$¤üvÌ|l  i‘h$êzQ1_e6ˆÈ³ÿ¾Àd÷Á™hŸ;Q¦ ³ÁòBi…Ïø ŸºGl˜Ô¢§íÌåíVí©®N1è–F‘SÞCcÅU†>«ýÀ²`¿&XKØÿ¬g ΢Ìêè'ê“à‰ZÏ؉˜çÉÀ;P·R»WS•™÷÷t†h×K‘.È%dµ§:&r±$B¨Þ’òWóù‘6úÓF†q¥Ðc?Msü$}VmŽåEB!VÇ]zN,œ\éÛ%œwF@ÚM›¶­xaŸµªî¥.ÎëÔE/v_C˜R푵Ç<¸E¤šó<Œ^LCÈAé}PyЕ¶—àCÝ`ˆlŒÒ·dÈ,T̺y´¬ä*‰u­tÉldܤŠõ¸ªâÑмCÔKRáËB•µœÊŠúè+ë @ñI]Ì?Í’ jßnŠ%wDCž¡ðð5Œ¢ö –T?–5ð4Ÿ…-¥ÁîÕuq[uú.ŠJtªçPªŒóæc6káÁä¸WA…TÎṮº¯!QÛßá¨Þá_NùÔ×5UìÔÏ]èI”Àé®Úû¹°äoÈ û®¨jê"ÊÎXé]™Alhô:ÊÏ‚„_™ÎIâ‡WÙëÀé s‰Ï'îHGƒFŠ:˜)ç†ûe{¤$ˆ RÌG AéE4© õyé´¥\Tm4õy7Xkð}œÆœ‹K¦ïf“§ûU.\{‚G ³œO,‹2’†03‚Ó¤Öªâ:±\ù–F£MñiÓ,?kÄÁò0ÌÛÝ<4¼ÑdóQ&îÅÑÀox›´ê­^gb\ã^ŒCRÇÈ8Tø=Tf ö 1€ gÖe1ñý²bY©„¯ÿÈÓ¥8ƒ\(U¡Œæà@ nC޵¦™÷³„•êŠÌRwŠ2¼¦ª˜èEêu¢ÄvaDz‚RŠ¥´LS«Šg«Ê›²ZÕûò{¯:µ¨ö˜Å {«Õð¯wÌ׬Kãµ~Ș¥‘ÌsÈ:8¡qð‘zÍÛj|‹Ú˧õ؃׸ƒ=âÄŸ®b€´”8…rèéiL¸„å¯Ð®ÄC®ËÜ€EÍôW{ÁZ²_Û‹²­íà­,÷ÒjÇ  Oƒ‚)»À(?1@xR¤N”€àʹ„¶zØG÷†AÁâ’JÐ$M¨ñ£þ!`žÔ´².‰.aÍI<‹@]äËq'´LNãzDý+LpÍz‡<ÔŒíUûŒ^),G•Ñ*3¥:æÅË,JО/lž.!X#h‹zâ{*ž[×ÇÜëÒ6uZ›õŠŠ#÷ZoET¯þ@Ö)®«ðGC_,x&Ìߥo§4Ò·gNHÁsfA±U¤nŽ!Ù§ÆãŒ»ª¡Láêö"N¬“óg£gؘDëPbnˆq®ÇE–êõ8 ó©Š+¾Îð,à¡Ò#|¨u`D„`“/ÊÞö ÐxªõJ¦cŒƒˆÙ 0Å·±0•ÂÙ“¸)nhîºQ pçû_uZÇèàÈ2¹_Aô' …““®()D¥Tƒ@È87Q˜nï7 ñ”¡ì_0¤^Ðàaws ¼ãÚù¸Ý$MÍU1x¦T“¬ò>9N\¤ä7¥yNy\*M¹è3,ˆQ¸ŒÿÊP-8¦±áÄf¼GŸmˆ÷èÙ6ì0ŸÛöC“àzã¢Ä\ýu ôÀ<$öá÷!у™ªåÞm©{1C#i½_|Üá6Jk“ã½rDÎõMs¦¢Úm µ¯8´õÍİÑZSO/&òpã&­Nðå‚f_ú+RÝÂø 0:{úãXÝíú¼¨vÒC,¸  ¨7"‹Ž K¨×ª¾MOì€è‘¯HFĶ?„÷ãRHH™&•7{3GâMwz».ü…úÁÉÑgGÏ6Rzöeü˜ÎFZü\Û‰7n~€èÝG÷üyóâö壣ûÛð£ûÄï~úüóàýͯŽ>x°ùìÐÏÿ49âD°Îðm¢µ ØÍüÂGç0(ò£/̓hÞ;Ý(6ÝÅ*nÖ+ÿø‹E<(ªµ®y;¾öÉûEFH¨îuô½e{-=adÓ—]}VÅ#Bz‚Ô½ìÇßG¦í»ÄÇ^@Dë9‘„*ƒ„ڈÉZÑ8&\Zeîºh§ä"Ž9]dù¶º¨„µÓE›QÅ5ü¥‘”|b¥Söy/®™ë^¸ U… 8ˆiw«vû#¤Òün]ƒ§ÛÝŠþn£Ï\’ÎÿóÛK¾âû&7¾Ê/þCÇSÖÀû/¦¤Šõǹ¹S®ìŠ÷\oïžâ'êjˆùsºßñq~ÿ—òþ“üð£òp½¥÷Ú§W n)¦uê¤ô¿œí÷ù·´Z§[múµnš.0åõN/kÕ+Oê¥wnG]–¶õ½±êv†Ù]РQâ¶¼¿à÷‚K‹š¾ˆ7þާìGدlF¸…ܶ;¥ä_¼–rÚ;¨r¤õméµ”ŸæÍ†@xó6®5`.KÓ©äÒêð᡺Pvšƒv–FIJ뉛XA³‡4¢ÔÇÓ‡Œ©†EØìë­_Ï´Ä|ãbpG3¤ä>æg"/Þèx’£Ý«°+FÀË™K"²g’•ÿ Dü‚x©m‡¦5è"Ÿëè%ðIÅÐrv¢\ü¾L¢¶2™Úß*;•(qˆˆÇFÀcmˆ›Pª|š«ÿ²ct«¨`K¼PN’8×Uåõ•Ü÷>9I”Ô%u+Z;µ[!JýB̈+ÙK¤;™i6ä’ÒäÊDpçó͘"Iüm,¸b+} N~[•΄c©eX¬%©eòyŽ ©`ȇs3ÏçÕ˜åêNfùì¼ê÷ˆM¦ü»p]¶ïÔ÷Ëß*+lÛù¶YqQªdhJ››¨ÎLUlP¥˜R‘!Iÿ´þz¤Kí¢TÀœ>uÞf6h¶³Çû)† ¨‹Ña#.3¥¼úlR”~Ÿ-gú| dñ“9Aͧæ#zÚøµ«x± ÉÍC¨{Ýz°ú[ÍÓ3¯j!õwNÔJ(3mùC„¨í´¬zçÜ•¯ Vù®T̶–CÌõãâÝPûyØÂÜ=ÊÆYø¶Ô%Í…¡(ñ™©ù蟧Nm!f¿Oæcæj)ÙžTw,FëTiÅÚÅÉ×ä‚yGM/TÃ#ƒR_–ˆ‘îÿUò’†VJð+’MJðK¡Ïk0E]ù¹ºd>å–„VIRg7#ôôs%)gô*A®VÁI„ëéí>Ò‡Fš•ôQ¬Pœ­¦©JIàÇ-§ %+;þ#þYòp¾\v{æ¾ â?XÔÛÿ'þÓèá²þýà9¾AØ„~¦šzé«ßV‹˜‰¿d»üKüåç)ä˜Æ`®«Õ“å¥þßW²°mÙç;…snk™~Ñ‘ÐL›G\üèFyXÇŒ¦rØýRJŒå¼Ñ'ËúôÆô |æ `‘‘æ(ñ€1œCÎÒg-?;ú/Sk•çendstream endobj 910 0 obj 5624 endobj 914 0 obj <> stream xœíYYo]E ~üˆûÖsªÞÉì •(” „Zá(Bi’&•²µiñï±gõÜsn(BQådÛcþ왾]p&ÿå߻Ǜ[B©ÅÁù_<ƒŸƒ·".Yä_»Ç‹'Û¸Ìã <ˆÅöë$@,œ\X¯™‹íã߆0š’9çÔ`ãKç“Ü?KôÖÁ ?ŒKŸÆÉáiûüj\*æ¼àjøG½°öËQßãŸ!xè̯ãR37TÊ× E EnøfyÎCwm7-`‘’ši JŠ|be²Ç… p¿]>Z¦$gÞÑMÏǤWY&¸žŒš)%­/zqãóººíÛ½K•~݆ƒqàLÉ"‹’4¢¢Ã”‚Ã*Û•…B/ÐT)¥µÃÏuãvg¿ˆ®rÑÖì.¥kT¤¿oáàiœµÌzõö„W@D%üÀï¼Úºz™—/gN„v¹QÍʆËe¾5.Á¯;n‡}8³ÖÂùá=ÄÐ{+ÅpÑ"ó#Ÿ|r‡äÜ!ÉÒöt?ÁÁ˜0ìÑÑ(_Êá]aŒwzØ­ƒDþ›‚æ³¶»):£1JH¦Ìðâ—¸:!Lˆa'YÁÁÿF£™³Òà™Õ„㯚¶£2^"èÚ,•FG”c±Ñ)…Έ(W!ŸW£}Uñì1ÁZg£@%TÜWM;ɲ´¡G"ÆÒ•e,! *˜þUÁ1 ò›±ëÏŽZ¹@BÑÚCŽè’ÉRèp@qôWÌXQî„oûs¼!Ù0–ƒà„Íö£K¼Qd2ÏðÐ…Uë&ÇOš6¢¤ LƒVò@ž':1.…$#È+‰îZJ癑b±x H•è8‰ddYð–º[:f4Zg9bŸ¢[‹€=[ Rôƒß⟠móœxb’N_À¨IÔß‘f&¦ÑšXßAXЦÊ3m¤%xÇS'+H¤ì9¥."kfÒdr¨”;Q¿#†b`,$›í1­˜§®?ÑJn“ÏQ9 h0”‘@Û ö$cöb¶ ŒmÉ–‰Â„êªp]Ä ¬Fm¢¡’ ö]˜¨ë³\¬&ÅrM¢÷¸ÒCé 4wêôQ•¾S™¨×ú+—ó6žÀøˆÿ.Ë"ü“"øMðÔëIž˜Û–®€Í—–ñ*t ,µ°®—~8WBPzÎ$ µ  BŒ¸'xNž>Ÿ­iù Á›h*‡n†O’µ¢²Ôè"Êi$ö‚ŠÄ™‹Õ †hš#ìb î¬jéÒvOk2ˆ:G’‡øjE Æ„{ý±8Å‚8“.”$@ä‰xŸs4ìnÈ=s1\®)/S¹u ãB½‰^ÉÙ}Os¶Š˜+)¨·Õ²T²cúÊpD ”(Ù'°óˆ Œ[*¬ƒˆ óéËÙ·m"ÊAP­[Ϫ¨ v³ çêÐG}®ƒCE§ãjêEc@Y®Å– }¨CD²ç=©›UïÇE«ÅçÎNÓ‹‡¢uÙ¨mð‰Õ‰ëS:kéµ%aÅ[}xÕ Øø™¶U&&E¸¢­Šrõj³Ó¤aAspQ†¶^-ëRU16¨«Óˆ¯éP&3ú£úÊ0é2¡Sâ@Ÿ—£ÄfDS”¶/P©­Ã«àºHˆp—ø 7— >"yvAÄ>]¨MBJ[ˆÜE°h\{X­½"ãa2žX€Ê ß@\ÍB'kØçji<™q¾‹¢OmÖ÷QEÕ¤CQŠ{ɃÙ^•Sf_E6CÅÆÚNαà ØíÌc‚?h7ÚNõ}x§½µá=ð ƒ=*’R”Ú³üe{Á8l›mÇû&å<=`O»¶ÑQ å§ãÚ5ô‰ nZ®ÄC,™Ö¬ç4,ûP”ûÛóÜ ¶K.¥!¤ùJ]þTáË”†Ÿ%h4(9{…ÅÞK¥\xPÆÈKT~sÑ>½ÿ<ÃÇ&´OÏ4äE¦Í:©6 x ¦VÙ]q3Ëî·Á£øÙÜuï3ñé ßg€ê“š7`N¼Øàq‘ذX¥ôAôômB àŸø“X‘êUšØ+i1nÒ*;¢¼³,TC‘Å ì&(…k^Qš6ÆÊ N†ùƒ:¸×;y0–GøÆW§ez¶Èuáå€:û#ÛÄQ6r–qa†‡uú¬ßó(/ä.îN3'ÍHâÎÝ:Úææ6]ÔÁã6štÀ;£Fhåùmþy|Ö¯_iÒímjÙåm,3ÜC Ýð>%'§"OêàA\ö°Í¿ëB‹Ÿx;›ŒâçNJÈ AîÆuÓ£pw LûþŒq>­¸¯6ùñÓö×=RökBĈø¸åºØ?œÁ*ÒÎÜàEl©÷r,ŸñdøÐºXB±õõ¥òÐG˜ß6æÐf‚ÅÇåv/º9æ{ ï}¾ÿ‹ù~+Ëg¿´¤n6±ã…’ë­,Þ€ hH®àµú´„g‰u;íɧ˜NdCWÈbš´ûsé}Ï3ìqž9ƒË;âŒóñž)>‚)š÷ßt…ú*8’:~Z»k½ùh#·ÐJ2Yÿ‡©·§l¸ì0Ò±‚„Ë\ÉãÖ¡Î4-Î(äìxß q“.) Ö„ÈÊÙ̸žtÒü§!é™õ\ çüWè¦u$ñ´5•ƒîä^Òkšèœ“¹¿¶Ü“Óß!§[t/¥û¸–µÖÒÈ]”Zó? º§Û?¿¿òÞmendstream endobj 915 0 obj 2056 endobj 919 0 obj <> stream xœ]QKO!¾ó+8ÂaGfæè£¾bÔV¼h<ÕØSÿ?qØÝZB _¾p°І6—}»7gd¶»oì®9œ(vÙ¶{{Q'ZQ$Úúef´™ìX" Ùº7ï}r4¯zßd%ü‘1Žª¬ŸÊ¾ôCÎ"èn=‚H‰âÎ=¹g? Ę2¹zâ¬f”cqEYmh(N$@è^ü”%õ°‹¼kh yÊ|ð-˜vo~ˆz᣾Y]©>0`otíÛ)¹·ìzw¥:ÿ'%±eÌèýï•›a—¬WJJXH¥hsNK—B›@m &Q`@š¢€ˆÆÑ½z‚’>U=‰þåw¡KuÊØ¾sUÍZ祀tùendstream endobj 920 0 obj 290 endobj 924 0 obj <> stream xœµ[Y“Å~ßP„ÿ¼iÆÁ6u~³ |… -OÈËê #í‚%üë™ueUWÏÌJ‚`¶§ºŽ¬Ì/¿<æ§XäNà¿ùÿ7¯.>ÿVj½{þß ±û ü÷üâ§ ICvù7¯vº¢af§Äâœr»«gi¹ójg½Þ]½ºø~ÿÅáR,ÖÜþÅáR-JÁäûëƒX¢NÄý]~ÕþÍA.QE÷OðL[+÷?.µwKØKœ)hï•Û‹üYj÷ï«¿—˜Å/q'Ö.Fǰ»úÇÅÕï¿ßIKgÝþ×Ã¥\¼’i1¢t°^cÜþ5|4AàÈ'ôQJÚM𷃓…ýŸá©¶ÊI½‰ HýþÇúéiéŒÙ…‹oŒ‡ƒÃÎe0äñ »ËÕÁÚíµ-¼O›^ÂÆT\¬ò1ï;¸:—VBÖs¹Ø"Í¢S(§qNY"A¼Âa@’ô N¶ô"¤€}¤¥Ôvé ›Aº`ÕþÝAëEK-a·0Ô9‡—ƒ·« ìûí¥âÀ©”4y¤õvÿ l[ê`êþhÓE¤ Ó¢l FÃù¤Ð `øä=œôoxºìèª}ÿèp ÷lL´y@ˆðñkUzÿ_|h­wjÿ6 C}+oÁG@SàoOÓ†4QÃtNIœ¼ *^Ø×ð§õ‹Á+30T e/@ƒ•óž½Ø¾ÝV|Ò>¦ï•6¤SÆá>ø–ß§Yµ¨–ʃœ£Éó{2!‹+ƒâ(/ÊÅÇ(ÑÎÖ‹¼Î‹ØN.YÆ6ô¦~z Ú7 ÷ÏP­Q~±ìKZx§~ÏŽøåïàþ-Ûl·%ØœÆw‚ÁÓ¼: nhA‘H®ž~žÛºÀ°åňT$B©üEÊÚbíË _ݼeät±2{B¼c‚‹Ü 7þ°x)f·ú¢)éCXSZô†æ ³ýÏœÏmÒì2ä3Xn¸‰ E*#áÍ/H’”°š]$•´3íÇצ@0hÆòôITjÀÜ<Œœ-Sj¶N®!Ó‰F2ÿè¨ò’p¼¹ÂN%©IòŠÔVŸS´vf„(6šâdÁàŸMO{O›ÁVyÉ|Ù*™çZ[æõ–=d*vצâž:/Ë2“!Τ<Û÷À º ¶\32²ˆ,ŒÞÿЭ7ˆîÐÀÐ÷èÃ$âùƒ•BGÏî Ý5¨±dÈŸì£ÌÅÁ£YÇl(œ®p1!nÊÎ|\ ¿í:T@w TºÆvSNÒvì ’5±·ü±}ßNÚ«LᶃϺîÿDék(ÓYá8øy*Ž÷ö†û4ç†ÀR€ñkçHT ¨Ê&óÌî´’Òaªæù™–~à’p¬àï>+“%¤Ïgê‘~ƒ«1ˆÖQË2ÝÆGÝB#@Ý_ÜnnB FZêÓ‚¸Ö'Àno£¤©)gC¼ù|B‰.@f8í¦„ ¾]¹,ffOޏÈñÀ}Êfð _°ŠmÑ–®Ú÷ëØñÁãYE®¿¸u¶ŸãÞ9í-áð›¤ìç®Ð¿ \Š¨Ø«6/€n&Ï!Jrèj=[á½j5„^°(êMçE˜ËyR½CÒðt¹O#§p*›ZÛƒÜ$0{¥1 Sy³6À*•äÜ¢Pð¯ù=0o8ý£‰Q±¾lô&À­>ÏpÐõÙØºý }þ%ePð¥Ž3  ,:r¼„ßÁo¯ö!S—©‘%¦(]©ÚZr392h‚ª;¦=„° Õ½KƳ€*ß”ÁÇ­èXNÓßÁ@â֣ܜá{&%£^ßö'ßTsr,jÿøçö¸žqÛûâDÌû¾cL¾¾3Í›±4Á5ÅöUçÎ`²Å³žB$)aÊ4f¿,aø¥Âtlô÷ ÚÏ¡{B¥ÜöI9Ab…¯)­×ù=6ïÎ IØÃÎ>¬K²MùÞúßàœ BÌÀ’}%†‘rbB&¢ß Çc%‘Âã}fCú3b—vKaó@mÒ6Wžl:%*©÷ÙáÖ(¶>È~|È¢£P4`î¼fñn 1Ì1n˜w¾TN9™ |sènRŒf…ÃÑû¿T¡G†wT/í¿Œ6 ½ËTøªS¤ãÌí »P¾’¤âÒ@w¾E”x3ÂW>O¡©Ñ‘Ä.ëÎâšÛJ’:®ß©e—ü0S¿o~îúIu†©“Ç2f¨;âªläòªÊ;MÖ£óR)#ÞÍÄlÈÁ9¥›fGÖõêBŠù2‘ÿgâŒst5}}ãÏ`¬&?ŽÀ-šÁøó›ê´Y¯Ö*:ã’©˜uއ:Ö÷ƒ]ãÄf1àlâÏrvXF…þS–St¸D›ª œ ëéCpì”ižÇ%~SrÑï.o¦àÆŸñŒ×T7h-V“L´*[W5³SvlÜ|² @Åp2eyB—73¨¨¨ÐÇž|‹ùž¾l¯€#ãe¬ÍKLb ò®–éë&ý™™³%ÔaÉ :O9»©Ý=àf>)¸š4ë­ŠbLÛOz f©«Þ†D —j_ÅÐÛp ¯Îë’â%ªYA¾ÍÚ^)©]Tã”7—?̇i*¦JûVj*i·@¦:«’eÝYiƒq÷m‹#¥µCi¼˜qN€“D>AU>{©]gÌMõ5ÖâÒ…xÎ >e3X_J .¤VC¬‹`ãPß5rÍ’ìC7[I²{j#8'Çî°õu«» ÷‚Þ¯w(³Ú<.<‹¶Ú |<MP¥Ð†sŒ9Åš;Ì ç:3ŠÏ,¯¸¼L³a…ßA°#¥î•ʨnËœXíEnÌ}¢+m¦óöê?k$9UºN{(ßÜ5ý®jÀ:ïæŠ’ ¡§Úôl@rZ2ÀÓ¡ìCg1¢s,/Ð%”ñDòK*E§¨õºÿsÝýÒOÄԨѓõÏúö†2'yíƒçve.óÌP÷±*ã­Ù’ÛF!’f$áõÄžðjusÏ ƒT¡C§É:¹  Š‚wïÕM×Ö›ÑG šÿ–$D\í¨äVýš-ÓVBŸiý“ëŒeuÕwk†õÛÑ»®’Ç('›Ì±ëÂ%0'ü°ÎŸMªJJ¡ößTÉîà¡vF’eÓ[É*{[û~¦¼®­fMo}¦~ô¡¦i±SþºÌî:ŸTZØ´:ÞÂÖý¸¥P¸-g¸<ÿùˆˆ±'Æ”ÀÚhÌ>5í’œvâœ:ҜԤ3%'€?È+ö0ð›Ó\±ü€ê®).ËÌÝæ33Æl°AódzUñØ õ¹ü &óRC·=ÄÞ¼=¬{:ªŽgÒÄŠ£w´§x¸ß8ä/ÁsÁ™(Ö›K\:2 °û´9î“ñáÉv·#ÑMnú€3nï'¤N€ö9–§•±°ÞcF7»tV/†SÁz!E]OÛ’™Þöaûõåä¤Þ*ºÂüÛÙfN6ÈÙÊej·rÅé®,dæ(µOôcÚÔŒ0TMøêÀÉË,‹ÄRaÇ~ËrŒ]”¨=jJ.žó#\Â>¯5ëÕÆ©W—–æà9×ö:ž³Tïçœ,ARÒu±h7”;Xl¨Aó!:<b“xZOÊZíЛD”HÇgê\}©~ï·;¸ð§90g”2ûžÎº¡ÐÇ~%aJk]|ŸC"2‰™æ[k½2Öß\ݧk÷ñ·€‘©)¨NxVðÒT8ŽÑĤNõ U‡ºþó¤U±GϵGªŠtl+ÁoîOfÉ©éÏZªã2Zà&Bƒÿ÷‹®¿Ë0›‚ÿtÂÃ/¯.þÿþUëä endstream endobj 925 0 obj 3939 endobj 929 0 obj <> stream xœÕ\YGr~'û/Ì›ºu±ò¬*~Øõ®¼6ÖòZ¢e’9äP9C‰CRÜ_¿‘WDVTw-0’­ª¬<#¾¸ó§‹q0#þ—ÿ}úêÁ£/s×oŒÿ®üôÀP“‹üÏÓW¿LÍfx4,ãb.?:0“½ˆ³Œ½xüêÁ·;³; ü>|ÿø_ð³yŸ-Ë"|ùø Zÿãþà†iZ³ûÓÞ Ë2ûe÷»½Ýýe0ƒ÷a²»Ç­ÍÓSççÝ—ðÔ,ÐíDCŽðg€·Öƒõ¼á7µßuGØý0Úö~˜çà#ñhnÃ`Æy÷ù?œâ´ûg|?/Ιݟ÷‹í·ŒDáÔÿǦ‰^:ìÎì¾Úü˜Ì¼û¯½Æ1XC_<ÞÃæY3Oôí7{›wMnö!oÛÁÿÓî¥Íft»©¿„ݳýÁ[?„`w/a(˜·Û]ÂöÜÁ¼æ9¸í×3X8LÏÚÝÏðUƒƒ‡~:Þ¿~Ò¨½âH>Á‡ÝCåõÖ0ƒsqô»J»›öí5 =ŒÆïžÃöÂÓ8.ùs {ÜÖ19·{Û>ÌýúŲÖop~vˆÁà°ðˆw¯ÛçØ/ë¢ Q¿{Z{}«,µ|¦yÕš]å1ݲ{·wô‰aÓdÀ>€‚L Á.q}á–Û½›qoÜîýÞ.ƒƒÓ»a{'f „±ó«FmG´¾ÄñÃìRvÛäžmœa ;çÍË"àÇä‹-ô‘~†)Ú¼{Kð匱7ß/†ðS]°5`;ã˜_ö‡ Ô˜‰Vþ )Æ)V|AŠf¥|ˆäl«笨æ9ÏS¢Ù1r@¿L¬©‚káBItììˆ]3 dTÜqYž¢ZÜÁÏ[)Wpù Èc$¤ÅÉ"™œÁ.ã<¨Ð {¶ÞÒvºIF§MáâŽõŽ3¼–³L•ÄeÊÚQFQÜý*xØ´kÓ©ÿ­ÅݸÐYämw@‰ˆhª„yÝDÇÛöô7ß vüŽí1ŽI›ƒ`üe mš”1pܰjX¹iâ¦QÛ{|ìi;Øæ5Še#Þl}^UÁž¥a‘%¾ÛÕŽêëJD?2<Øi¤/68¯öøßåë‡ýl‘FØ¡7±’ŽÅH€½ýÐÁMKÜ}‚ãZ’_÷$T˜OPr£O 8y¶â7ø§#dšÝH¶ã~ÄóÚéÅoÏÌð¡]óLãí+z&ò}ßDÌRmÎ˰q!½Qˆ­M⥧ÌÔ` ’ª`fxúÝú]ÁÁ>R¸gQ´Ài÷Õ °»fÎX/ªb:32é `2>š—L“,üŸØ*ík/‚º½ƒéÔ&¡s·É¤å€þ´&:\ÝE6]É$&‚6l¿ËÒi6ëò¸è:#°a¡'8¨°ûý¾ìPQ˜² cSÍ{çì+tiwS%bˆe&ŽÑ+ÂÈnBÕKï± &V˜ãÌÔˆ'AösÜ”¤Æ9¨ë“š‡{ -Òqa¦g­ÜAC´SR =l²GWº`é\›Óy€’Ãäéž4°Þà¹Õ”e·e×ÇB»ÁÆÝÊ?бLB®|…V*ƒÙ"!LËäC'ŽÖÔÚADi º¬ŸÐÀ›;³eË5B[e%ð™à–?$ÎEC’ÛÕ‘}tÉ¢‡%V‹¦ö{»ÒX}t\7bj(ß]“o­,IQ”¸¦Ám:Â\…õßpžÈßãvùaZœT ›ha<ÁxõŨб”³ËÆLÚ)I4ÎhL Ô¢æ2pKE,™£Fª-nB_GµíP,{4Fqêd¥E2 |„âY>¸23ëT7Tp‹A†3寺ɤSa_8dôvj2Lf¤‚ÿeÖØ¤>rÈ=©°ŒÒ$$ÍïÉqqu³ý:;–Ðú”k‘X}©vͪšwDÓÌdǹÂrðëâ8) Þí‘죙ÔëÈ]XA‚jò¨™l¸¯ÒŠné'>È{"%DCk¡—0:Ï‹Ÿ­bþ&×Á!Ô„«ªÌÓÍŠw´˜5*"Ýkè…MÑAfŽr?Aöjé.RÕ¦@ôJËÉÓ£°>·ðwE:¡5  -.,—WUk¼ê—šLqõéæ·Î6I±ò\hÜhÝ#‚PŸæYgœH2ÝöèǹèIÅ;Ò^l²É ¦häîù‰¼8þ$Ó ÓJÀW]g/£2F.j£úl„<Ë–¯‚l´¹Xú¥â¡g ú.W°ejÉG-#$BÅ»Únx– ™h§é5£›áS§IÇn^ÒÁ,p£K+ˆ§áTŪ·='Dóa½‰=>åZT9FÍ“ÒÃ~•©~ ð³Þ²t2ì˜Ï¹mºú=Þó½ãþª|‹ïðï—l‹bÀ›ßê4Ïô.asÔ5FÒM}I„1¹šN+s‰Æ—ÁNK!ò£N!;ï¾PZÈïT¥2­Mä_Ûߵϴ+fqÉŸŒ:¯3šã¨'˜ÙÑr=tœäT¤ƒþé—Ê;&͉•HN±aÂ5t©Q D'‡‡²°‡%Ž‚¶È½â(¢½¯N PE<0ÉGÂßà6©À&UþpQã6âß%¡dˆÙHí ƒ^Þñm<åxŠz„óÎæœ€àA.#$Kaø¹}^Æ 0õw5îsìÚ¤Ó¬%VÍ9wéCS}=?Zò{nÑ.êUmÒL}L¢X—ôÏ6ÿý ¤¡G?ÎÒ½Ææ+·ë¨í ýîçöO}†3²³ÐfÔÐöì~™D„C“aÁÀU IÕiάBßL­È¡æÉ¥ƒCö>ÿ{z]ËgÔ€æh¡ÄÂq:E =‚Š8ª¦Àv‹ÿ¥7ÐÌ„{±)ñÑGû¢&Aû4ðqGL6D…Ë& ˜yÛ©zÕ¾<è- /É—%'¢å”J4€ÊÔ®ª’yíç’bf'=œˆ[ЊHgbƵtíZSÜO2œl¡²©Y®g¢2.š¤,í5AsBe‚ᚯjcÒ:¾•þeð/‹}*ž¥v©ÐtŽ»ïËCá%–lO6F>P5¦Óa|vZ\½IŸ4,xt#ÇSô.ÏÉ LÔ®z]¼µIq™cÿõj.pŒbYP‰)?úH9âõÑ/Y/ÁÇßfgSo™ã®ƒ†¢]œÄåJŠ-0Á&ÇYXÇ lùKL!Î2¤ Ÿ0˜zˆ}Ê©ª³r­D°ÏpøQÜEÛ8Iý”>‘m¡ÚygÚDqRsÒ…P%GìT…ª0ëe2{ŠPÅÇ,ôd®iŽÚ_î;gt‹(²4gt1%+Õ÷Ê •Çô§D$Àí-»T¤­r´ÜžYÑÂ=š³……¨ÙI)$ Ï1e Õ†ÈÂÓ2u(Ç‹ÒR¤£cݧˆ 3[fÓdIÕe-UË+©JZŒ:º—TÝÿˆ Î6KÂ:;a˜„©Xžšð·•°ŽÏë²´HG’¥ÕµûÛïô"5Fíî¯[¦vDË‹ôÓ(Óç±ûÈu´3sõ,nžðYnÌ09>†#Ðf¬,IèÄÙ°¸†’G0N&Tõ’É2qj…Ÿ´ü2–ÔñׂŸµ„K[¦ßý]ÛÖ­Û„‰V¡´‚ZeÇÛ*=ëáwrýÊäå­•ÅÄÊâ`J-!6k;: ‚žò×ÞW`Ò|mDZqmñºA¦n~!|+Æ8™_aÃ’ÖK†bŸ vÉŽbÖ¥§i´¶‘ GÓIî¬ìöQU÷äùgýÿwR82 ÒgïꯛÚî® oêCLRŠXêIÛM¿¯-ucƒŸ?Þ˜°¶½šLL¾—S¹:˰ŒÞU^Ç2«ÂkFt_Cà͹±~ÈÙ§4^%Ã&7¹µ‰ÿ¶2ù­I^´–ÛÌã|Æi[Zë½A.Ï!Sñì-¸t“§ ê™ð…7¡¥'¨LX$~Ö*7ïOú”,AËì¸é<Ïn=¥Uv®“DBô­ÔÏÖÜNy¥Tœ‚üüRèÄN+Ö•˜/™Ù0‡S…Ã_ˆ*åTêë‚«uÀ (üÞx˜™TÅ.ëöëÚ{ø…6Ó!Q@ƒöjs‡ùVŠÐ± ¯]þ†*‹IÎz?Œ®RÊ×ûR|œZ‡ÑR)µCñm¸Oùk‚–ð‘þšÃ–b0Ød¸Ë ­\ØH>ÎUÁ¨íEv†—»¬²õš}9õ)"6\ZÌèZ& ‘Ù Ø4.z]Öõ^OX|¨IéBQIHW£›L‘#Ššá°­lþm—GE­v©¦ZÊwzCÎ$íû÷èóš¸<™¥‹ëØœ2äWœ6´Øú™Ûš^iÆ.S6+½Žuª…­:âÓÌ»®whçldÄù÷P©dBè·Gª³°ülòSFÊf/o’åŽE Õ< R° u£çN’Õï„ÿ½r9’¿EqS‡XRHJMKcp²Îè.{r¬lMÙùôACm‘à 쥯4Îg³»Ì¢u˜ê1z©(É·é›Ñl§ÏÈߟhkjÀî¼x”ö}ib³«áj •4•e”ÞU,FAÊÇúžÊ¦Hf«f‹ü´€*ï˜Ê²é—M;ŠfG{ŽÜ顨œÏCaÎȃ³ÌJ~º¶ó8gÙÓ(éÓz5ÓM˜^,ù·õI%$ƒ7L”yvM£–ú,rÊ`eäýTx*¦B:üt4„øÙâÇU–£B¢‰Ð$$Ì`•4åë´úqlAÓqEt'Šê7ï«;Ç®¢Ž"ˆÃ’ÏD´5ÁéR-…Äê8ÜY2½Rž‚F¿f±Õ¬ÈœåVy¤gyï«>¯ö6Ztdæ&ëa(ýÕÌt²Á)’÷´Øô©ñPß¾©–üÓjØ7ãüR3ÎÙCiî§_·{ŠM”zÜ&W>¹«ŸígtPyÃúfÞ€Gõá»Úð÷E”†—{ õÜûð¼½þu¾PU²-(^A¤žø¤cŸû(ÜÜ;‰j©<Þ¤«_ÈWyO)n5kvvœå^·Q»]’vŠœ{q4“âiÍœ'7.ÖH×'•òÑ:å£&|SiW%ŸŠ"J‡2\SÃnÌÎhï+ÏÒXÂÀ-¬¡GT4×›Êõý=7ˆå¢øG1iJ×IIˆ_Îφ8G,¤*ëJdsM”uÊôi“nüº›ã«{¸"ï›Mö¢¢]…¼ÄÊŸU´; y©ñ‡Šl[—ÚÝpL)ßh9î´»ex¥€Ø› >­ás ß׆m¼Ÿ[ÃgíZßwüõzÀ;>ïÒ瀬¶UëѯÌ}­1…§VÈe—Z-¯`GÈ×–üÇފܼ?§‹ad)nb¾"†ÝsF¸¥°‡?ywIñÉ¡IuÂC™à-m‰„·ÿÜ/´>~QÖ“æèû(¤:'ÿQ‰»Ü#Íê×Ì\É·ý¶ÈòqQ·õ¯FùÿÿåNQÞhÈò¨6lšÙ³ÖðeE1_0€¢HPŸ‰ÄOäŸ×g«ËÑ|ñ}L6MYÞ‰ˆ'SRk°Œy5¯Êa×õ•dÙ®À&9Ð׳ҵb—šI‡â·DoÅ"õ­ôá8+1¤âñ«õ¡ }ÒþJô¹—‰Ÿ— >h÷QrݬV^fOsñ}æŠ ÏãÃ/ÛI¦ºËœ°ËB«çøBï‹$¥S ·žòŸÔáKïrV]öJ7¡K9ºQµDø“ZmdE/·5æÕ.Vb31ãØtU“‰ª¯©¸û[ +•5l´¦#^“È‘¥bí1Wš±ˆmŠ—w/±‹6ÅeÙ%æÖ÷!©”Ÿm 7k´º)j¯š ï2¾Ùµ•,äÄÕ¼Øö7ŒÞ“ "½ùU] ¡é;éFí(÷[ÙXFêY€zõð;èM‘‡ßƒ‹Ã=Ry—é(_x“Ô²sLðQhx««gr †0¼Í—‹ç#õ.̰*å)~¿<ìý÷ý˜|àZ‘æõ¾»WI*ñ‚é{ {¬ÃŸ´°`NÎ7“c"N’Ýpû[BéŠÅ‰é2H¦cLðõÞöwK+•Ž[ý¿N\½4ù ÕÉÊkÍ:·œÊ4Î'qݸf2)iE-—¾GmCðüæRøtðSJcĬö+“ÚEˆŸ“úþyz>ËÓ«7 6œf–ݳ×Ô’¿_T¥NXÖGMXtnïÏ´­”î0ÇHEOºL­Kín‚*5*­TÒÙÊ{uðò0àìœZÑeÞ(:Ÿd=Ü,§ó¹xuQÑ6$¯!Sê—óWuT®8bÀ®Š¾Ð|~7å ÈÍ„êXõÚý®)Kg·u¥PGœEü¢<‹Ú:vÍ^Ò]HŠË¸Žáã)®² JH¹KyÔR¸n§@u,§®åؼ½Ü>*2úÓ…žX”É­êrxéA¶4ù0ÆŽ˜)Š+M –uËx©ÒÈõm)EqëBò[ëQV‘l'äýÄ¥G Otã ó2=V±óÝœi‹$·°“ºe$³¤+©˜¬`èÔ5]e¢ê!â~÷¬…÷üz£:€Ý˜pÊžùˆ<ï\³tÜ ã2ýü;ü÷7@»Ðendstream endobj 930 0 obj 5725 endobj 934 0 obj <> stream xœÝ\Ys·~WR•¿À§xÇÑŽqcÆ9ªlËŠÙ±éCåø"u%I“’¯_Ÿn\ÝÀ`v—´ÄIJë%€Á>¿nì7Gb”GÿŸþ{úòÎ[ŸH­ž^ßG…Oï|sG†!Gé?§/Þ=Æa6³˜åÑñ“;qyäÕ‘›Ì(ÕÑñË;_mä`7þƒ½÷:4ŒÃvbTÚo>Ôñ+G7Á¢ŽÏÒBü³ƒ£µ¯Ö¿5ÚŽÚmµ½œçøÔïÊh©«ÝÂW”&9lõæüx‚ÏácBÊÍ üó1~ŒUïæ~\ãÇWe°Æ?ÿ8lÍäÆy6¸i§>Á§ÃVAû4¹0c|æšÿ±)­²|¬(­_—Ö.夙GU(÷6¬HûQ)½¹^Â,Óh¬Âe8 ¥Íæ|ØZøjà|pSZŽÖ˜°l{—Ÿ–¡qåa„ˆD³ªL޲8Ò…4œ¸×zóŒ&Çxÿy樗¸ç¼ÃZ S5¬~ñyy1MÅÉf[vâå”¶'äæ ¦s.¡ˆ›3Z¦¹¬˜óRãÓe YªqÚúѸÍPwÔÚK 2Ï“·›ïðYàmçjªøµWÅ…âanÓám¥­*žá™XLÝ&ïÝp"©ž"œ¡¼g·FÚ ­§¥—õ"OúšˆMzŽÏ©p–å¬r›KqJ6Çk„ 4{D­üé܆+N¤3³ l4»QÉæ\Ù,eµø’@œf]B²Ã\ò]^˜ÞL"aø~Ø äh?;6rMXÌ i-‘O·0¤¬ˆ…mØŠž·¶"³°²…Þ‡‘0¡óéÐgËÍ1ê?)i6Ÿ¦=Wÿ–xéEaðÂþ º0«’Õã‰:ÊËòR7m¾e{'YI'¥`1ðkzéIà&˜ÄŒJ¸ÝË Lžw¸ÜÎSÜ|—§NÂyNò£$"£–2*h©®RC?ççŸQ(øCÏÀ\\‹ "²ÊÖZYX¨ «¹¤žË–5’ê:©x®å” I€ÿ‰²_ˆ¶ ‹!”¥Ô7R‹µäeÊyÝ•ŠÄÉôØœMùt¨ÅSkæ8\Mr”Ž™ÚÚ¾VÏ`ÑžÖÕ3¾VwI­ŒQiªæ•l ž»u+=ïA]Îµî Ÿ‘àii¼ FôŒ?Üæ“ÒBý(%à… Óü¾*‡}CîJã«.hð%µ¾YéØg3c|j7€·â ò‘ËÇÕmàå-søÐá˜5¨eLÁ”Ûã/™‹°š'0F•G1Â)‡êÍõ½‡…bQàê@PˆïÅO vÔ„›ÒkÁ¾ÖÜh® L}ˆ}pš ÊnþqEÍ? aµ¯¤IÙ%×âHÉ×Â}Ö ’R<áÙôMTƒ£2!fŒú&vtÈûs´¹/`4Põ]ˆýÛnXß*>¬2 yý¸Œú/+E¨À`H©úÚ¬"ž§}ççD„wð gF–ô%²0Ízâ"°ÌºˆI®iP äÔ)ŠjÙú»çÑÏù\„dÐr"c\fxÏã´ˆHUvm"¹Ñp·Á}ÀŸ5H‘libý°çÜ"¾ãæŽX¯Ñ3€k¼Øh¬ZNmOªŒ p^Ú>Á¥L³ð"ª&'¨™)8HŒ ]ÉCu‹ð 8ü‰o‹° šê%½®D\ÌZF¯qOª±«É©Ï|Íê/á+ܬÄkHVc಄ð«áQØ£•]Ÿä,a]z, ß(!™þGÆãèm8QËl—÷Kr×Ö=ÀÉìr-ó+¾ë"d4üÑt¨Ÿ%2jîÛ–“ L“ .ÜtÍñ)L{œÀ ÇéE¬ÛÑÀ9zM>gŽ^ âj=ôJÖ!,ÈPäŒõ¼Ý}2Æ^j àB'˜ “Èàè8kj˜{< ¿Ô(k‡:•*~ùU8•—ƨñr*ÿF‚jö¥‡œhÔf·óϰwK‰ŽÕÚ1ß>õ´ôÒ€'ØiI¯k+Žç¢§¶X:üO7f*,äc7–¾@OÉÐj1ϵfˆ€5w5Ï:&=¹ eculZ)KÜ Ãx’ëÍ‹¤wÒ)×^f1o ¿,ØÜu¿ µAë—¡Î"mÔë)ã(ÝŠm'õFýµ‹DÍìôoÁïwÌ­$™2y'ÚL xèaJã1™sÌ®è˜'8,%•¬ß>ß0¦AjÊpÝsÀznŽñgÏçU2·°$•å¼vä2mVÓ—I0Р™(’»ø=EÕ“§ãèV¤“ëZ¡Æ]å2—×l]Â8“} »¬ ì>üñcrX?‡õ oš"øZDgZ3ûž=­‰á<¸îZ­ *I•fÌÑÆº À`+¥¥ðef)àF±vQÅÊüßMQºÎ:œ§Æ{„cor¶½ /í¤yã³<£´5†¸ ®‚щð‘ƒ=ˆr£L÷å]ÿ²^aFO[v‡7h¼Å„‘ Fl›÷p©ʇii9‰Ãkþ½?@ æ'#ùd±S£¦µº[£µÒª““üWE§\ñÓ¬â[âQzd7s-Œ¯âšùFºÀIkHÑ“ãlB/â©xtô…U%+·ˆ Éhí©.À½Iôñ;E¹cdz/vd¹l\\ˆÚG¸Ü_ÀëÔìAÐÔºÓp:‡Aª£».,MÎW&ŸìPÂ[N‰GüÕ!¨°Þ¬ðeUø"BN¹r 0”cRPžé8=ÅéÈ ²ØQ÷B†#-§pùÂaaãæ*[5sH½fþ!n•ÿ'tùQi|NçôÁ໥ñaÍý3µR ˜b°(†'þLn4<Ù‘ M3ΊCÅ!•÷"‘€ zͳÞÈ9AÉ2vj%vY-aWsHmNÄ×ôO«NPÎÜ :Þé(+ÔL­„Ùˆ‹„¯å‘%B…•×¥Ž^_©ç ¬ ·+ãËnÕ·ÂY¸U þQ½SÆl,ùj°óPidªëæ@º=†å|½;Û~8vT­ ‹‹²ƒ±VSȇw©8óÖÐÞÚJæUÊÄdnp>³ìaB²°È/–¸m Åžõ^S<±¨–»Ø¹<‚- 4¯SÈÛ 9Û¢á3Væy:³&ؘoº)Væ—hvR÷E$»ëR¡ÊÃ6N¹VÀcûÄè yöÖatŽ`~îËÌ9!®‹SÁ‚F'°în[C4 Ǫ`–ÊK އ¼ZE“ÈU´?SÚ2—#?’{”Zëc®4«èˆÙ¨³ŽVnêl{Ê4s«_Djç4a.,*÷¸kÎŽnRÁ…ps“(¸ FÔ3XKmàßã£õB›U– +Ú_Ɇݬö%x ¾Ëy?²ÔârELÁÿ±áÀ@"£¶ã$жe%&ÄÄQ…Û‚õ¤Lþ‡joZJs¹(53qË"3!g°‚¡°dSpEéur$UujÈ} Y;èÎAx €40?U¬õÊy:½7aº¦¨¹É§lË>†¼E]M©e*‘O›*¨#Ÿã®7È*~€Ìôã5/dâH3ç_X•£v­ªn 𤅠ʶe†Rü@Uᇈ²©)LåJi¦+±ö2a¼]‰AœÃTžÞ ¾ ÞkÀåÕë4½£šR£$§°ƒ Óã…ü¸›‰ÙØäE×9Œ¦íÌJ[šüÊ£nÄ…3Gôk¶§ý’ÒŠ¨•Ö*ÝsÉk¢ûƒAð÷¤'Ö¶€a£pÀ6—]÷ËC1³œ|ô&0&#!)³6.nÝ8yU×é$Ÿ¹ëíZ«4‰%«¾|÷¤@b‡è>boáŸáƒÔÒñžÜi†Wâà±ô^'PeYl7VpȲÂîº×8–Ƨå«Úûv@û-§)¬4vŸQ÷Ii|……7’µ½Åß`M¡Y÷Kê¾dèQžçqocOø“¾*m×|_ù…´¯©›#PyžÏ9*•>ˆUJ³bÍqyäSX§›·é‰Z‚¾*'{‘ÎÝ*lràgÕé—³Îiø°b – $‰jϪ#Éu”o¥ÂQöˆ)iè6Î(zÃ4‡±–¼¤ÆgœÃÒ·Sê¾(WUAg¨Èœ ¦ð ”ÏÑö–$hå¿/ý¿§‡Ö(ƒ_MH*òE±¥°¯‘Øzó'j-˪.‚ÎuÁ~`ž£p‹Xå‘4®.¨<‚®mMωG°"ªàs²ªÕ€câêt¼~î¸ æØug¶}EÅ.Uæ Ž¥º¥ñT+lKÎ,XÌ9…® ¸›Š,@Á¿G>TDø{lÌÇú”| 6ÓóŒn™ÐûDbpuekç{¾h寃Úe(¨a+ßdQ§´ŽY1\#¸ŒJÝâð ÚyÝK—@¨íˆGêëÚŽèï ¾Ã/_¦Iw^¤Á»œÎ®T€ô'¡¡—´æ õ¢@–¦oî”î¿Eœ6V+áNš# ¸”¿ÜËÊs¾1”tù/ká»ùÚ6—r]QŽ—ˆœ°¤9¶ež¦Ýû/+5—•J—²vT £6ºMr€ï­nkšòsàƒ0r‹x½Ä‰)=¬ÖÌÎÀ4IJ˜ª*Ó Á‰—m›tZ¢¶•}¥ß·^]'«z[GdU­cB:: «8©”XbÐ’«œ–¦?¨Ð)Ö‘î(Zy•È"›žž`§Ù¦Îaåéjs•®+*$FªVê°MgœV.* :.ËÀ莥¼yLWûAžÈÌRA©ó ™ˆê²>{Ùï³p,z×aëµ^gŒi3câ¥k0~;𔆂‚¬¸;,Òæšß èŬkœw‘aiWÁ|³s_¾ÝE×:ÂüÝ4£‹®ê•=(ý=vä³ kþŠgþÊ «’ŒÊ<ñÌC£'¢ “³fE$¹ÊTL}‡åÇÖêÀß„ºÑ]”ä®ô%²}á<¾AlaÒü3±ÄÔB¨• °Zœ&u 1Œ®ƒÙ謃Á0,Íwg¸ÐZ•ù!Ô¼÷—€8óá3øKSgMȵ¿ˆZÃÍìîR|ÙdT¹ºZü¿çbKh׿Ú/Dþð‰òSHZ€„ ‘ä´µÎ0bÈ‘ ¯3ö̓œk‚5ºãyó:ÿìÛv¡“6ßÐ-ûeóJ—‹y@I.®æýfð”T%]¼Z‘WkmaBv¦ ;wº½ÍÙ|y &_÷¶{q†ÍÚ“–³^ʽ6¬x'¼s_;S§F+C'9A-ø2{‰£}â‘¥W¯M‚<§•í&I×J» Òæxþí’ô£[dû^\(oü›Ei'ª×Âq©²$ƒ=³ËôãûT?˼Vž}ùÇÔ½¸sžœ8ÿ¢££'`é[ÿðPÚ™_Û¦%Ôªú‹’9y\áå>&Z®JÏU1t=$ˆÌ<…½œPÆä¼<ø%¨˜9çì2´_òz¸ô°·÷]éáå`†U…‚êËòêð;U”(|wàù•˜ ãî/֕Ƨç׽콙UL¿‚íö†uïÉÓUt¥Ésúí_3[Fj|\æaÅØ+¿%’GÒÓ,÷tUÞØý]QJ~6I˜rV ïÚådÈ:W]Ô'D™Ö†¡|йÓÓÀ³È`á™ïËi]ûy’hÎòSÏ{§sÒùCÎdù~ÿUï|òC³©“vq{__ÿÈkžéƒÒú?+oWçòë¡‹"B¯{’ÁåaÉÐL£€> stream xœí\ëo·ÿ.øÐ·Ü¾õ’\îrý©M7)Òĵ4Eg½kI§ÜI–ýßw†¯îÎÞíhŠÀ°¼ærÉá<~ó ©_ëJÖø'þ{|}ðä¥2æð|sPþþžür |—ÃøÏñõáçG¾›ƒ¦ª¯{uxtvP‡>l]S)}xt}ðãLÍíLÃßvn>ú~æêâ³¾¯l _@ï/æ Su]ß«ÙWsUõ½kúÙ_æzöb¾PUÓØNÏŽ¨Ï—¡Õ4nöZUÃv~ÊþVðV7u¥Þñ‡<îx þ[˜íÙ¼©œ³MË_<ƒîÚVªv³çsü°k»Ù×øÞõƨÙ7ó…Æþ¦ÑÌäBÒÿÛÖvip85{5_Xxè”›ýk®«º¶Zù/ŽæÀ<­\ç¿ýa®׌2œk‹È¶E]­÷þ ãÏ.ðÇ)þ¸9t cw³þÿ–¿1ЮÔì2ýwv>_4}¬1³eúˆ­a¹þ›wøÃwßä¯ïr áü'w¹ ¦‘ᮽÎWÔƒ[¬ø«üþ½ÿ>7>ÍÈÕUª­õáB™ÊÚÞœeŠÊ)8ÁïKf<ÅOòÏ9åa±¡ßs>´aƒúµ³e^K3ÿ4Ë«9²YuÍìž–¾ù–€Ìì@]®sÛ)uüiŽ9[›ÙùýWôþYnü>tŨÈ…I€—Ôq•'$ ú™^Çyœ•$óçlp”¥îuå\IL9Í3¯'fÆÇÆ8xϦNïйS×KΖô~4ioqÎÔ&Oú:ĸuC¯¨ëmîzZH`0txYÂìÂÔ`,`ù¦­ @àY€2§joÿˆ, ÚçêÊ6vö(´Z‹kÕ^®Ñð¾A0Ò ùN5h€˜Z·€Wh#°LÖõ1¹²•6˜JS ÙôÆ¢¥(°DzM½ )/ý´‰ów|Ì›@][‡‘¼µm×6ƒyu ¤¬EÓIËâ­;cÀt¶‹Ãh@å4Œa&À}×ö`(©-S‰ZS)¥Qpxšö’úÚ´$Œ‘ý„,fdá0çsËÈ{Å¥L£¯ê&ÙQðA³/é zœk_WîQÄ©5ŒÓÛ¡t@õ&É<+{}•Ÿ¶îã j…¦Ò(UÝEbkå c«ŽjÕ˜–“Œ$äQn溽í5›"èW«á—VƒçË«GbÎp†¦qÆ»ÌEdœwè'<ÿnÉ PÐ^Û8¦d¢bZ•DÞ‚« t€«»ž›º2ªk¹N²Pœ†€Èy+·Ú{í°‹ö…øvnü“*ÍÃÔ°¶–º!¶ô m“ÅL?(¨Ÿ¸î{Ïç¸`dê ײ¤Qñ}§Ú¼:˜û5u-Ln¡;d˜"–ȃ˜Ža©,‘Íj0Ð#êúÇêyf«¹ñB#Ö§°îy0! GsˆùÑÓ•v„«oÙuÃO©'º2öûÆöžä—U¢þ¢/ZÔrRåÄÌu"xÛ…Å€²1h³“šnÀw¦îfd€’ Æ-뱆5Ö–«åUmzï›wû‰fì ´%‡m—µ]ó'nv rI‡­cÓÜy’G[˜•ViãJÄ\ÔÜ1ÝÏöÀ¬jàcZÝ1“¦\#%]ßUìY7TÇìX&ÈdÄ}ŒyùõI,œg|éÚ‰®­ôC@CôCÜÁ}¡Æ|A1dЂÖÚ·¸äÂbÌWd ¬ÃwØCÇ– Ú%PܲÔ4`yHñÊ^¥¦ØÝžHï. ßí>ØÛVÆþVú`P÷‚“1¾0=䆻ú'Â×¢$j¸¤·ªÛ“Á¡}¥z-EŠäáŒj@_»_ßÅU©cʘšC˜Ê.øŒ)±œFåšd/ Ë.„‘³:<žUÀƒZÕ…i QÛ²*$«NµƒM|¯4¦ø„àpŠO­í|th!{)”ûsa0kÈܱcÛŠi`ª‡´î蛃£?mÉç€|`]¶‡LØB_rc $Ž ¥‚OzLŒÜVÌcŒ9rÈ-pÜïÇÙà<ÎS5e¾-go'Ã0 &ba)–Iz_õ)³€Y@˜Ù_C#>4àçñmüd}[Ù¨il\²ÂbÝ+§DíÀB¦ÑÙ–‹åÿàj Ö“F¹W¶Ñÿ0]2â1G¬‹ÁÙ\@€¡Í`2''i±h [ª°cœ7”Iþ4ÇÁ RTç£ EsS^$F”žî‚<ݨ„€â8ÎeõÀgŒÉ¯3ÓB7&«‚Ï’sÈá•:!ç‹@<T40ZèÇYѾÞ2#f¤Ð:às”QÏ?gÓ ÒǾ¸ã‘®ÐJãZì㬕b¨t¦è0zà8œeqÃÀ¥²z+³³êFŒœ3>nè0î™Ñ­÷±ÍÖyʬÅ[J LÍÕ‘T×0Jp¢éñÉÜ&-õ\°Py2^戵–5ü%¾‡A™Ï¢¨‘™ê¢¥Æðñ šýž ‘ÐÆàµSŒš&ú[ì(°©4#2`æM©¤ü,N‰Î©¶»«‰¨‡Fy† ¶ÜGÜAWP?(ƒÕ^¢/jü€@-€ïl;AÅÆC¡eõë¼!ÒçÆ+Éa=—ÕðÙûs>¼¸_‘/Yq©ó UèioæMZCÃ÷N¤YΨq™ï‹E°ý“¸Ÿ1/vclÕµu*dólõ{.~»åiþš‰Â‡LLK¿kåÍ3ì»,%âW߈Î÷Eg‹¨×)±hɹ;–è©ÄáÄË“0óƒ43qï‚¶æŠÆá¦XÏ—³cùïsãuÑ3í<Ü‹ð›}Φýl=¢ÇiW·°©u-Žƒ î !qiÂ7lÃ¥*ÉGëý°šôuT$Ï4eÃÖÜ•$”qv#éòmn¼•ع–¤µ!E=› ¦IcÒ¥Wñ¬ì©ñž9Ö­µ$Ö¥$ÖÚF ZJJJS>ìX:3´?çíª‹‘ ã ¤©kI=í‹Æí´Ó‚K=À‘ªùGP::Ápú(7¾ 5ìØ’)ïƒÔ('DcZ J= Ç–>1ŽŸ„¾I+ 6!¹ßÎ_ö9Yjy ƒd6†ç4d+›tdýÉá§e’¬¯$­xSèãžZqVpqhÕ®ç¶Â¨¾$¿-|]ˆH97yG ~á7ñ»Òò0òÕûhîÈe‹^ñíEØÄ9]Çìx-òíW J¨nBÔݵ° %L~‚¬]Ï[ïFálInýw±ªT±/³ÄwE 9íoóÙ1„aë£Li–âñ¥nÞèUã™åZ²ðë HO@ÂÒI˜µ‘ŸXIƒ^IZñ0!áqðp#~'ñ†eW#ëªëž^Ö#ñÐÕþ‘s}ª«M¯È|;¯ëÓ«¶®\®t1². õKßoJ¥ÁÃõpÇ0æ,’ª·’…‰’œ:ØÉ 0èýŠCt–èŠ2ßÈrÕ¯%½Ê,DùŽœÂƒDü†äNë¸/¸:6ÿ;’ûÃHT.o;Ä_‰ƒ½¦Á˜ºÜ‹ wUxk„í«Ö~} M—âï‰_û g4æ=â”ÿd­`íšÊb%±ÖMÆÔŒŽ™yÆ;¶q"áu“ƒ`¬o¥+cI̧ q-ña*ò)0nE¦´–XR€}ÒÔ¢ì”>#ò5÷¢}Ða_f”¦¯$ï{9Òç¤NQÝÎDÕez½Û謶U>¶)èg~T<Ü; °Ût‡¥)éñ±½Þ„ÄÆ'’µ0Ù?lW»KƒœD‰¯&„;“‹³ì‰O—½˜±ÅBÕndÝ)ÜU±–q_/ç^Um×wÛ@bl•>ƒ6aO,ÄlÙ Çý†“¬.—)Ц<ƒË˜Ä¹¡‰3Ið$Øó^-ùì¡60n%<¿ØáJÅ ÷Zja:ëzrb¾Öç+ Œž¢ö9¶š§$%‰ã š<\ã:ÏnïáØ%¬gá ËïÕ™á嘜$d<:Ïkõ 9+¹—·h&}Ù2y°ðƒ¼,2' ÝmÒÅG…Êý¶ˆBK¢áXbéÕ maâ‚‹ õK.ؤ8´q'B,ó¤Sµ€±'¡b€ÞgÌ–×ã – ° n²XÄ"F¤¹æ—·–V¥-Mf2Œe1/Ô>!ÖdÜ Ý_·[ÔkIÖ!Ÿ‘ ï"½‘ôàŽ€ð·ª¤Çqú€B+•‚!ƒ0K5ö,! ˵$ØtwÕèïKôd~lW>@IÝ—ôþenü–¸ºÞ.JVUÝû„w)­(S¶Ý´¨µµüb>އ1®y(¸7Nò|Æ@1;I< <Ôm³Às¥G>J Sù‰ >™µìY™¹‘f¢vml¾ùÿ¶k^,³‹‚Ò ÅäuXœ¼9¼!_µIR5ÌQOÅÄ[C›²”ÏÏéìÈb‚ø )Rq††¹×tùV¢d-éÉ¥Ô(nc•µwº2. ²lqPë¿ÏÂ>ç²ã}Ûp96·~6>—Þ«&%Z¦H@ŠÙSè'ü¯%3¢‘ÞÓç¿ÓнŠ/¬?Ú8´Êl‹d†UÊí?Å™±ˆtŠ¡²ˆ•ÅËœ"köOØË¸o¢20KþH]b™RîíwVh…àiO ¹Êbõé{þ- Œ‡ŒÛ·’J‹û•F”ŒgÅï Ø·»#J:—øY¬0Óôï$‹º+’0v|TkŠæòXcZÞ Õ§ /£-G# /Är»ë ƒˆ–´¼<9ÎqåðpÊ·±à•mŒgZKúC²Áq3Ü ›T 1eÚáüJ#ÙS©ñ®Ø"%Å8·S¯í‡(Js¸ÅåëB%”'Il—ԥĩ`…€žäßß Àx\38¸Ë×Öo|×UaÃгîºòÊC¸ Ð4WP>àw:Ä[åm•t/€Ÿ_…ÛäƒtWQ¾ý†óÒµ…í·ßØ™ü|;#g]»I¡ãÿtªåÇÝË»gq}[…c>MMx5àI¸ÂƒÊ"1…ý¢ d{Œgèñ¼ÿ®«Kéð¿ÂK•áƒ/+§ØMúŃ_€Á®æñ«áË@ºpGï+).1ЭTÖ‹×N>Ëß&YŒ½Ìâ v_i(ÊnÂÒ]º\Á~Þ{Xò‹çñòB`NéhÙ” šŸ¿e®÷N—ÜA¿ÓåG3¼¬ë¯$¶ÃßP‘%O¦®<àUË~ »îÎ\͇¿Xå¯â–÷¿Ä 8¬±ŠÓ c¾<:øüù/³ôˆendstream endobj 940 0 obj 4193 endobj 944 0 obj <> stream xœÍ\YsÇ‘ö3B?oœqh†uWµ"öA²e“É–Lz½ kc(Ra€DC¶üë73ëÊ쮞hÀ»¡9ì£Î<¾ü2«8U{}ªð¿ò÷ù»“§ÔÖž¾y¢N ÿ¿9ùáDÓ#§å¯ów§Ÿ½ÄÇ^ÚOjÒ§/¿;É èÓhNCr{mN_¾;ùËFoýFÁÿû­ÙÇíÆÐ?vI©½±qó›­…ëÁûÍóíNïSš&¿ùNSrÓæsüéœfór»ƒg“ÑnóÍÖl¾Êw\`Ïü÷ËßÑ™óz îåEŽ!n}}ÚjèÎ{ƒOïÊã;«öQOS}Kíí4E—`6jï”2>Á<ôÞÚ Áv;_KZÃ;; k¹Onó{zˆ*ºÍuýoÛ,”WÁm^ã[“ûïáQ?훳­Û'¯TܼÚîL„)ZÃß¿…5 ÑlÈN~TØ<Ë=i¬—Ú{ºúÛÄpálðû¨Ò榶ð#tû‘t‚`æ^Oqó”·¸i?Ã+q‚Ýᙽš&«ÙËË6æ§­…Õ ÖŽo··‡ea‹¾8yùË¿l>ÅEP0¼Çõq°®ÞÑ#H‡ñ0@˜•1&ÄHCô†dêÙVKù©•¥©;³™y2ã} Fê mLí$(š줃¼m}Ø[¿y‡S !ÂÎÑh¬!Ž Ø½w`¿lÚ;oðõ´]ÁvÑlø¢wcÝæà- ïÃv{§l›–±x¿¾ß_ú¨_¼ê?¿¯ÚV®EØ×74Èa‡Þòö kè´ì tƒõÄ~–Õqt™ ,I.,.ÌôÛMëäOÛªÉÄÍJ“Š ¥LÁ¿Ýf×ÚQßW[” ØiW]•¶- Šl[ÚëmTÔ´öä ©ëwÛà ¶5 Äb{p&ŠÌ:÷5µûŽ oŲb^MuŰ1¶b7ýj MJõT¥(àvÖß8Í]çNÛ½Êäé–EMÑ-…5`M8iüfó÷.ðMò$Ìîí–zu Ââ"—£‰~Û–±?ÙÝ´wp*Ÿ¿<ùúä‡S°w< ”;$½Wé4ÀXðoð/Ÿ=?yúüËÓ¿ýxûúäéŸOõÉÓgøÇg_ý þzþëÓ_œ|þüôëu¯#MFõ::‚€~)—=ÏÍBrQ¯Ë¶ÀäçÆ„ôEÑîBôÛÁ¶¢L®·Bû˜uX´«˜jå¡]10‰$Ÿ5Ø:Áë¯zË—õzo|©C3úÍvÒ°ï`?ŠfTîOsYĶÙPou“íµÕ–/þ.R}Øk˜þ¨ÒkIŠhªôk¯8Ä+ü'¬%¨Ò½ÚÛö ýqÓüŸúOšÌþøþû䦄µ— Ú‘”µ?¿}Ó/~Ò.>ퟶ‹oÛ¯×ýöY»ø~tñÇ~ñ¼]Ü·_oúí÷íâw+ïÔ‹WíâÙèõ³-NÙë8îçº]ü‰ŒN³‰Ûþ nM{0ÕkC¼3ð.‚ Üaeë Ìeÿ±sÚƒ@Â\«qBQ[º¿lßài‹b´ùUouˆ ™‘ÛBÀÃø¶•µ¸[©ëÜ÷rtcß‚ ‰P L˜6Ô7 «çŒ#a.6”…<øš›¥®‚—W«vâ21h03 çu f`Û²Zq9N'ø×4†¬âWމ¼°½Í ã“ àä‹Dè¬ÎÄDÝéw”åZn<>ã>·6Èüx»Í ¶žEmòn†j@¢îÔÎòC,â1Y0 ¾Èo9ÌG½­ËÖABöÑe¤>àdcäNöM]‚mÑÑ0"ñàRv›±ñ‡„"æÿo(»˜¶ØY‚ÈË–”Æ.iÞgìíĆrN{ -ö“¿Æ*øK+mѸca‚˜˜ TAi‚ 8]4A ¸Ž†°X²ýâÕnãò¡÷q¨î‰.Ö@±8Ys¶* •ÃÎ`ÇÒ‚Ï@Çò.ð–Ý•1S¤8¥Àgø¸––иD–pÙ*ƒççÍLÝMÞ%ÎM·3x%[UÁ½iÄÎT Ÿ@ºÉ ÏÂ0Clà#@®‰Íú:o ,ó/ÂÃG04 b©Yhƒ0̓VÁº9!ád–å«N•¼ÀåE- kö­-?.ÇyLûц—]F0Jx}m‰ dYGiK ˆÆiÍÛX¡ 'ÀÆADåo»&\KôÐ6úeNÓ,eÀm¢"‘_U‰ ÂÔèÆ*šýT²\C[—8”›;!}o3ÔWŽPCn5F=ö¼lâßó¾*CS¬j5M¸Éëj—w÷U‡öÏŸ·°¹š±kO„JÁ% 7JSR£ä÷SG ]eód‰VçJ€2ê" XŠsç3]PY|Ï‚ï.éMR±!’?ks 6¸~š \ª³ëªT5Â0?Ó¸K6ÔeFïôadõ*ë+õKPDÙô @*uÖFhb“¶ t®¸–¡F5±âÀ$`GU|ÛH `.<±VÕ¦Ðý¥'N"p¤i"Ïð¤ö?ÍöcÑÞHc³Ø|û ®¨ƒmpý|¤ØMÎK„QëÁ„8zIQ7 Cä~–AºBX-@z  p(¹GuLŠ“ `Ћ“!ñ†æ†&yÞð̈AJœ ŽœþBM\ˆ¸ ¢•šàcçâÄë¬gÅ\°LÇ??PMÐÃc¢12 þU„hoÛø|£Qò¼†f¡â ´mÌ42v_ “0 ;¯@®É®ÈþȾ‚¶2ä˜Åv›L…Ší¬Fê:KRž›Ù²kÑÏv å%®˜f¼ïs âIëéÎÀhMZ«Tê¯0§ˆ¯}ÔÑnÒi?˪HPÒ}~e×µŽìjÇ ·ÝÊJ`øª[Í ¡ÄÎB€þf;©*d¬žŽè]<‰“ÏÛÞ<Þ7îp"3wnˆ ÖâÑò`^^cÍQБY,\_˜ÇD bÌ×÷«ÃQ —qÆæçœ(ÍHŠæ.––SÙ–øs¬!¢I´RR0„yì4ð@lPêÚ»‰)Àu۔€¯›ã«ž7d Ïü ©ísôuå8 Ìôˆ%W’±†e¥¤~ðå&®gÂK0Å`i«þt]çZž²À‘CÆ’2AwâZ˜rÎRgˆ4t ]‰Þ*¥ÞÕ æ†Ù…dxb†Ì´„»Ùì]3UÇX9\UƒlnZ€töói*•˜… 4›`aþs‘KÇ·1¬09¸bÞ‹mÆùÀ¼ü’SÈ–Úq µ~ ¯Ù´RHp1Š$ýn”#Îý,·…¸k\épÀ,Ñö Æ.°òid‹Z+#;šs£ å¨ó>áŽ4ö‹\x³68r“=Äš‡®‚÷íÜÙ{Z8\­ä˜óî>ù×Hr§ZVÌÜ-«QM'{àøæ¹ÃjšÞã*©tj5ÀéÇLÓ{ƒ©ìm#¥é‘Ïüt ±0؉ióŸð/YÎ5°G¼ýïpÐ(c|ÀlCþ„ åÁΕ⯓Áâ³ùZuUzž\¢2{r¥Äb«Nò-Í™ Óƒ¥L-àh”ê/¡\¡„ÿš³u†—˜|´‚)&d=ž‹é iØIN-¤ƒ RLóà,%l×)ŒSë>t¶qùCäÄÚÞøéC&•…>8 eÕëTSN§jˆÞƒsBü‚ð0Jã NÆF00Æ ˜É]°–$CMÆ*´JŠãRÖÔEAÓ.CÀs¬Ë±•?˜SÕ9^æèè~èdVÈ>"`ED=Lööw%aqg0+ž…о÷ár¼bV^A| îñé’Fò0*¿€XOfcÇ…RÕø¬ø1J–ý,Y) [ô¢O@rM7ÙŸcf£jǽs“-¹ žäf¨]FÍŒóQ5:Zã>î“igW0aC„ô1AÆØàˆa›Å‚ìMÒz«X»qwúK×Þ¸–|')´r-=T;›¶¬¢©¥ž¢ÆÒoþ«I7œXi@õ,r›|â\Qõ(_:<ñÊÑžÞdÕª9…¹óÀÐL<#ªŽt¼jȬj%Î2B¸5-_hrü&×< ³”XƆõ¼ÚñŒ@·’Ý¡E>œ.ûÞ'U˜íÔKJº¨ø7Î9“ÒP2³JfG,ËÕ|ëQîû/F‹Š«JÀÎHçVy+Ed,¯´LáP¬)ɽYK0ˆD–{@pÔ¢IØ|fªVQ¢ëŸÙ¬«¾„c6|µ¬kiËØl/¤¦_IÁǦ€ l[œª´÷j뱇˜óå(c·uÓKeMZkq"^i»)I®­ê‚L›Uï”MfÑÇÞàŒ¢,k#A† Ö»ô/DUY\ oÇB>Œåû“ÌX·ŸWäRîÂÎqþdDGþË%3åÓì4eaçjN†—3ŒÔŽÕý8Ï¡Çø©HŽJ­>Ù:2£«±@ÉÎ|È|s:›¦+3Ó,u‰û/™9¨+p‡Ù¢ ¥S6"ô?œ YÖÝÌ‹mòœžù3¼£„%¢DV^FYV«™7”l¼ g[Œ„ÞÈ¿É9å©TG«\y¹#ÖŠ›ãGp¤ÞÞVÖ.‘ðIæ¬Ê”ʸÃMcÉñY2õ²–’÷jJZ£°8’‚ÃYáƒÃ×-ÀL‰1bÈ[X#¼Y-â‘ Ó²{}ΧßôذÖ9µÂëM–fÇ ªB™î0ÜA—¨ ]ò”òãt|Y Š˜º\wº¯Ñ¦ÅÀø;1‘bàÃÀeäÊ1S΃… _dV_©0TR©dSA YFyÐ}I~‚÷Ÿ1΂ɤK$÷ 4 ޝEטH<ÆÁÖHyû¾Q#K:¤x’rV§³,‹©wÞå½á€M)'ÁÖ Ä*´¹W­%…S>q2åVª hMåÙ5é’ýÊ@X9É ª:o¹îäIQݰ/a4-â¼ ž"&'*}ê8ŒXáA?ÆTÇÔ¦ßjSÒQï9R(ÂÐ'-S Y¨é€EŠ\b×Të,ÔKܵvàâ̳Ä6^µÖšnibg 2¡2¨vʬ×ÌŠphŠ4üÙcey»lM”îyZÄëJÉó_yA}|l1mkÍx<³ˆLÄoS Ä]©ÉÓf:Y qÝ´¿ãù<²·z %oKs×èá˜çdæ·äË«V—•KÖ,\.¦¼qSNy3ó±r’ÇN dM¯9Ù6Dv•yÓn¬áÍâŠÍÌŠŒ]l®ªÞymV\¬WŠPíªõ­ºåˆÿ-ËÚJ½ãFgçM>3vœ(¥'£+ŒŒ³@œÕ”ý•±ëë QÀ,—`¯0·¬P}„2†‰gS¤×–ŠXûŒ÷8Џ`Aéšs<=«ib’d]4ÍÉrŰýׂºÈµO¸ƒ«ÒïU®·¿[ž–®¶4oC¦fŽL_t`…wHåNçj¬Ž3˜ÇŸ¨#ÌèRfT&oÅ–Sé«óÍv=ëmÄÃ`?Aºó8øývĦVñP{vdœN—ÏŒ£éþ¿82^ÊœVŠe[èå6¹Ì‚/ëæ¤º·WOu3¶UQÇ»³Â¡Ê:žõ1 ™zv–ry>Hèr€?ô foQn}2_¼lw¶»14rÇ

pqWDô¯SˆDÍðd 3,ãàêAê–:¾Y >rd&ÏÇRý_Y>,‘™\÷µzFÖ< B™/*§¢GCÂvJ?ž¡ÂïU\K©DCïZ!Ø,Ö/Š`jkçŠer“ i^²´àËPÉ0I>ZV†iWò ÎÇÑJãACoE”7º_êÕ\Ì0ìàÁDð¾ø¥Åµ4åLÿìå»|È3„Y"9Y¥Ñeuqz ÅõªÉ]Šù.‹OÉ9pV~ùrFÉ×ãˆa¼ß ø¾e¦myDy!ˆ¬<£$HD›ŽŸÚÊGj ¢4ÒùäeÐRƒ'øáz3v–œlÎ’}ýtp’••¯˜åê°±·¡ûÚü*J½Ï"¶£|}UÀjöè,›œicƒíÓ­™g@‡4vô9ˆL‚uXl¯÷n¶Œµô&ÎZÝQ™jÍ'1³³ &W³®æ‰uNéŽ-Ãërª)ì§–=-ÑÎdaGXx‘CH\ø™÷Å‹*ŒýÁƒà·DËg|Du] ©‹³!¤cÙ÷KÚ÷áÉãÐýú?IðVRšîC©³-Ž>á!œr$“–Vj# ²7 ZÚŸÁ;L¡Îšs¡e”67k"ÛCÑ%#ël™z7üvÛ^æÜ!ɯOþq³Qendstream endobj 945 0 obj 5433 endobj 949 0 obj <> stream xœÍ][“·q~§Uñ_ØÊKÎqéŒwÀoq|M'‘ÖUNYyXîR¤K$wi‰RôïÓk7˜sv—åŠ]*¯ÎÌ`0¾|ýuþpµ.âjÅÿæÿ½}÷âç_¥®^ûb½ú-üóúŇ"Þr•ÿçöÝÕ/¯ãm~ZÂÄÕõ×/ÒâÊÉ+ëõ"äÕõ»9ˆ£9HøÇÍÿ\ÿ+>æWöX‹±ðäõÜý/Ç“Zœ A~wK^‡Ã?åá?'±hmœ<\·{~~UÚ¾€_E€a]|å ÿ,pUêu‘šÞøç:îv þð¶_õâ½Ñ–^øÜ.Í"VøÍtÖ~×}PJþp¤]¤_áÏ?¼¸þÙ_²òy±*AÔL|}€iÁ¤¾EÍ2ÆÇ9Ãúx§¾CÃìŠBШIR‚ ~¾^虇y×áÈí…¯qø±0sø+KFÀûVPÐÁ[6ì{¸ @-.®ò‹6ÒÖI‚h>¶wåù:+óÀlà7Š|Ä}ú1xKîü”žµTâ¶þX'Ýî{„¥2Ú‘ñÞ–»~„%håÊ—ë@gƒ_Tfdáßê4z{†ÿ¨²BîËüÖ \õ‹ß¶ÙÁe¹ “ø?Ck˧pWÕBÁìÁ5fw×¾ë@-ÉÔâ¥[ÍÊúJ'²|‚Ñq¡² ?k®åm½^ÖLëñ y²ô'Ék\¯\ü¼ Ü2‡štȳmBmè2~þ)ÿI(Еà“p%\XÐŒ7žu#¶‚+aÁV•Ïo° ³÷íùöc'Q¸/¤ZÚnÍEÏ„I”ý àóÝtá­aÚíÀÄ\·Zø.i{ðèŠO8òîð?£2ªþÉzä7ò–Ïa’ TÜ`Ë­·l3ëMeÂL?ËÝCQÄ¢íûöÌCû“I7™„]t±ˆìtŠ£µ: ¬ ^iúõÐì]¯+÷X…/~è[|¹›Á_!оðôlÉO†€7r¯šŸß®²}ms¸í¯æ™I( O®ß!¤€ qÕn×?O€¤´?>65o7dº*buq~UÙ‰›õ.éàçøvpÅN O U)¶5fîbÈF«™¡©%gv={yn¤‚¯Ó ‚¯žLAd°–]YÄdð:F3‚3Ãâ$†:ÿ6*ºMvêÖÁ¸MÞvŸl"®³E„ŒíqÖ ¨IX²~è’‰Ü#–Õ ùd',7„»¼ ZŒ²\yLȪ@|Ó­×ý,€[Ê’äÆDLe«ÿBTý7F|Jý·0¾ryí`‘\ô9o9r)xª[&¼¹È£[§sÄšÐh©ú£Ÿ!}1ØSÔeúYuÁƒ,3ŽÒô’y|ebè¦æ6Œ·ý+PÃê'd/©Ö-¢V£W6#ëŠ a˜\VNƒØð’ß‘4n†diÉÒ3Šû°Q>1;­þGÊ4 ! ŸKœ+÷ñ3…ªð) »­0ÊÔ&Í—ˆÒ ejèÍ~‚ œ’°¶vg)AÉQ«a¼¢¡­Ý9T p’%8GŸ4Š ÜâG}ˆ~´E35†êAþœ¸UÁ+8£ À¹èÖ0íín¬¡©©À9&›[‚ÈŽNãQh×½õÀwâd•=;Ü𤅔þ9€¦È|)sMØdÂé<=EÇâ6ê\×ðõq~Ñ(’+MîRê­.¢*½ÞFÑéêî›Y2?y{T˜*èxUiW¹^-¾Ì1 ,vÓ€6~é7ØKi}L¹^ÖÇ~ÄAeàDÚÙ hã#,^_OlëǸº…X…Áô ?Y"¦.Ü ˜"õ&9Ô¹“‚wQávà.fùøy„‡„ÇNp³Rëêã¿•k°šynÈ”!É6ÚÅå!öC4 P½ ”—ék”>NËó‘Å c«r-&<S@2)å’}Ë÷Ì*êïë4KLg‹‡…”=ìmïõ .c€bº¡AgCÐ#|[VH‘Ô³³óo’Z‚³Õ€toVÅ”`˜ÏüF§Ú Bœ$ª¶‰!žèà=÷j»NŸ*,Ì,¥¨|¬2ù!K$P¯¬!¬Ã HÓ“ê{{`‰ªØ"CÝõá!¯Ü…:T.åæ,OŠ#|Ènî*¨1‘¥Áy%˜‹Li,¢x8…CT ~•óÃÜóMÃÞÌgPq;CÉM¹?Gr/Qc·Ïm0Y1·“»A¼èt0ˆhƒ{”|€‹¤ëP×w2R\7ü"%d'´î±ÑL'H©b JUP(®o%I |—ŠéÜ`Z. ú"z•ìE u\ì¥×{–Ê²åØ§9wðŒ ~±N3ß¡™«øð\Ø ³>x%éƒtžÉL’Txô¸kfp߀Ìð}»À"»!ŸF°ñyÿ'¨´C#àíÞÅ9øÔˆj¶èŒ¥šæ ø^!qò_Ì‚¬ÐVi;DÒ%âX*˜põTý‡¤åû„žMüDAyÝ*KÙ†ô´¼9t Ê™†cü(€Ë{þ¡Åˆø+©,’Ð?H,O1ΦÐ[òW†×…™Zç§wrä!p´°ñ0E‘³ŽeƒJ¸+‰ìÙÀ_†‘¤¾ôbB“ûŸòð†›Ä4Ÿó)ìú)9Q%·¨’ Sü£w&bžëÕ8øŽiHŠlóqú…8/fšDƒgìVpð±_ýmHÛg¼¡6µù bU±t,¤[”öñ µ¨É ü»8W7+à~/ORkó´ZÂBÐ bSoÚk¬>gš—\óðŒ%Áð0óY³¦¥YßCêÉZ5ê÷3(F°Ó’ N¬~yD! Ãxé=Êj„ÿK’’Aÿ4æ0³ï¯3°#eÛ.ޱÄÑöÆìØæf?ÔÑ ùu§äZ7•ÎD#t:´±•™ÏBp­‹×gM¥zëyÑ¢„„&nÇÞ¿ÝPj™ýbh¬,*qs„Cƒ¹k&A’<„hm2Å?IC¨‰U´?ªÕ[njœ­&Ѝ¯B÷`+®€/2Ak"HWqBW°ä,áçŠ{Iȱ‘9ÞÁU9-R^Æ|{¤…“ÚÄŠ!›OªD¡„‰‡µÜ* æêÝ +1ñ)÷)SÃ1¬ë} tÃÇ "„úPûoj–O1ÒLÅNΓ f\~E Rdk$sð7H¹ï +à§<Š1Á›1l:bVJ1w<ƒA3‹[Oòýà;Ì0Qg#À‡¿¿<ˆ%qñ0S@ŒÜœõ=7T>µFMýê@z7Ã¥à6˜ä÷¤^=ZåfW¤àR¸e™²Ö ’2­_±P/VÛ¡ú c.á´pa¥éÊo2áu#ž¿rmo?áú< DØIJ4¡ÉsŽ1+¯‘•CÌÑò}–É|×صŒau×2F´ŒÎI=hfN÷<—¢$Ýde±³0Ff@„[ü¹Âî7¹é»áIQR!”$ ¬3–Q6‹f“‹²è®„–9ˆó…±¼.)Õд%QÛµ2L䆔㶩½fD”:†ýϱìâÐţݓ¢i]³0 < ‡ºD(ž#†ŠªÚ³"µ’kÍU¥™8­bnQnb\>?Ùt"¹•T‘ŠF©Ç5<åZ{™•r“uºe­Ö9*ê§*n“Ð7¿bi•ÙvVŽmÖö3AuÍ2qvÞÖYèŠáhoÓ^‹š7!lc ¬nC¦¾¡'ô‚*µ,óæ4¬àžÜ*bžN $ñÆÃPµm† צ1„¬Õ„Ͼ¬vƒÒʵ "ßÖn8Õœv»÷O;c…"e–yàL–R)†Ð1ÏR_šÆÅß)¸”ñ^Ü,Õ§V\°4 Í”vœÌÓ™?ÜP |6 M÷- #”·•¨–6O ­jg§à>¨ è)æA¾ÙÇ?˜uÈIš’øxµãyŽÒ&¶¿? *¥ªÚ°ø? <„ªëÚoßÒ”It¾ë lU¼K!¨I=¼:î†Ùd<—HYé ‹Ñ÷­èÒOwvÕá2Í’<®¾/hç܃ÂŽ—ƒ¡×êžüçßðy ˜ìë«·½ç[`›ÍŒË[Æ9ÄK2ø(@{aeÄ!Á;€n©®Y›nÆd ÞTÇ}|[i¤æøÊD„Ú5„ ÂÓ¸­)\ÔŽŠ¨Eúé+ZÕj¯],v‹¸=“¿ÍNߺVùËŒ"Ì §v„rβJ}¨ Ÿêì…õÞ™»e·Àã’:#! ï©ô‡õÉÖÕÁ2B´M`›ÉÆ‘¤ÄS³RäÚô´ ‘t½Z˜„ֺܳÚ\;:‘©Y9z?aL©œ<"ÍDËgŒ«þ[T*´gÈcŸ3»©…q•C…bhzØ'vûÏÉͦy¶øÙë t’Ô«rÈ»’Üøt‘+)ôoUæ‹vY$nAðÊ"Ñál4Ê›\•÷˜ž•Ϊ|>ÈBáQ#¿PÇ;¬S¿U~¯v!-_ÃŽ•m¶"Ç5ë[‚²6ÕO"+â¤qÐ_2áç_(Ç·èZ\”7›ŠºÙô§uCo·þÄ›ÖY#i‰iyŸã¬•aw°ãƙݸ“ä¯1îŒËŸÔ}zfé%~Î>“Ø9TÁNÙZùìvܘ*v¬Á‘WXðªô†nV‚šmòB½Ú­›¥Ë´86Y€mObÊvSâh÷Ï'é•5%a>&&>º ]lCpÚß<;zTQzœ#¦ÏÂý¥9ò‘¸?NøbÜ?jkåY~B»Œ§±Àz²µñàï§Ñ®ÿÑþº=ÝNk¯§£ ?ig"6:•ÜÑ)à¹Æ=ó„ö|ã%§¬çô^hzùÿv|î?Rœù(þNšðIŒ> stream xœ½\Ys·Î3ã±»)ïppJùA²[)ÛñÁ$•²ý°)’eÝ¥(ùóén\Ìb—Èå@£ÑÇ×öÅjÄjÄÿÓï‡ONNJ­._Œ«/áßåÉ‹A¬Ò¯‡OV÷Îð1—†0±:{t+'WÖëAÈÕÙ““ŸÖbcÖ#ü6rpΩµ¤?¶~©Üú/×­1ë›­¼Á¬¿Æ!xÖ÷ñ£ÖÆÉõÙf Ïz)ôú_¹þ.ÞÑ–=óËÙ_ižS¦¬âÎÎAHCØ|z›înÕ88B}èçÍf«m€•øõ%üý þ½j½·ÎÁ_[íÂ0Ž._”b}µÙ$ –p/ûÁXK/?ÎËÇQ~­ÝÄv´ëWø†ŒñlD˜Fúa:¾Y†ùm³þI‰¤\狯a[¹~»‘a£Q@††á¥Ò8©¶nv=¯Óï`L$ï"®ç~K\v!ˆùGâ}ÙIxÖ/¼ê®Î ŸW‡3½Â=2ÆYYÀ§_ẪR:H6ÃÁžèzZ_>O´Ã‚Cˆa¡e#·UiË›þ×gay·œRÝÝ¢¹2ùÏ6Ê Á;ןȒN¤9ƒÑD ÒŒ„:?høp,¼c,,Á¯ÒžŒ‚Þz‚ë±ÖY÷G¾.#×9vEþ ,þº™»ND2W¿ Ov”‘ ENÒÓÆˆ¼-^x&ÛiOì¨ó⣋(Uñ¼æ[ù´‘å¼ÛN a¤ruöõÉÙŸ~"$C‰•} 3`$BP5ì` )Œúº×LÏv$6[8P µþ–cÏŒ3í𑑤ñlÔé€:*l«ŽAÀâì¢B¢¬ÀÅ„é‘ñWé£GÅÖS?±wïä™Oaü÷†‘u^Ÿ«/U¬›ÛSTfÊê^%=ÃÝ+zV‡)ïÖŸÏÌ*Æ)-´§.È­³Æ{%Ï[ÕE%Ã¥ƒ"糚\Õ!™«Êæd ¯ï'arÂfšQ=‹ÖG6lRÍÈ0RM|äÛÏë"ö?VKoÔnýÃFÉA«ÖËhùíú[û/ÑŠ =8MoP[xÇ­RÑ7ýXyþ÷ò´W–½Ç<,{š9ÛûÅÑF]1ð 47ËWpTlF 3á‘eBJÜ©=.uLšHèñNR=T{„#–÷®[¡Ã{O™òl¥%æs+‚rWõ8«B½`×Ñàɨ³Sk:qrUÇv]7Õ¨…˜¡•lÆ”šœõ;Üx¸½s¨/ñ5?(ø´ï˜Æw©©ó¢ç1f°Å½µúÝøIZ´¶´aš `Ò 6Êû¢ÿÏ#ûÐËÕ‰ªQ(ƒÂ#Š¸ÞŸ_ò}!ßk$±P³ ,Ó>Üe «dÞ`ë2…¸ÁÏ6yǬ.Ö7˜©æ¦H0·Ϫ,ßÒÁ_¤×ÈNdƶ.œYITsTtøC‰½ÎÝ鯝5âxâK><)èY ‚Mêbö³zÿǪ¯ì´ B Èê¹ÂþÚvF„» ^Ï•'-ƒ ðhy¸»D*i†ó0«ŽÏ°Ç/gz™=F¨FS¬¤4ÀAð[­Ô“R!—:ëÔeS¥`¡Õ"%œ]@ׯñQGQKcÌ€ùš´ì¦ëò²ðqü{'‹f”ÈHÕ6‚8%I0±6û¿›‚”Q ú¦$KÆ.*%•Ì Ì¢Z^KŽ_.œ îü”,>‹®GýnãAn­·ë»€L:¿?ø ½á5~ÚJð•Rð0’ïô®õÈú-rùÒ,m•”‚lÑíq%q\κj·\%5HQª(sÏ»êC'éào™¥¯¾N4N4â1’â‰{ŒŒ›Fý²4%MT£œ~° àFq×4ŒÁw AìØVðYÅ‘ñ¤ök $!Á̽ .Þ$Øóc1¼¸Àûg'ߟ¼X)5XÊY~ÄÂ:üÊÀ°`Ì„Ü{prúà›Õë—7'§ÿ\‰“Ó¯ðǽï>‡_¾XýáäþƒÕ÷Ëù‘6 ‘ó#: þà,9EÂh§UEK Ö|L;ÍX‘lª÷S0ó r/‹\LP9B4›ƒ^U'rQ­!“î"®…µáÓÌÚ‚3ø×#´} íÒ^t²[(ŽA†I¯ÈDºß Íö›í4àR8K¶÷ÿo ëÙÄPt½‹Ÿ˜æc ¼hJQ²º¦”ÀâW›œ¦3 ‘søó—O{÷óîÙåM–B¶“¿Ï¹¿§ÙŽžÙ¡ØÆ÷À«™®Ôþ›Yø‚`¢a/0²|P1w™Ü1‘‚îX•¼%™=˜@Nr)WnÂyí¢ÌûÀ4¿vC˜ÂâzXx­Ú£ŒiM/ ¨¤¦ä÷…Qã ÏLÀbe¢¶€ïù`|•ÜÍ5îN02ó˜\!Òˆ©©„Š 2¢j„gÍŒœÛUlÔ °‚૤Ùö L1$wZ9ÛJ‹r³ÌëÌ`qe1 UªåÅ…=Ý”bY+7Ö@‚ ¦­‡è¶˜i+Û€næ Þd¹ÉºMö¼j€`'¹0åû1)ê·±Àl``ÊÂZO™,›.¥ÅYܸk%„­VM-r˜+ñcu5Þ'Cx`?yÎÅ„ó¬{æ¢òN3°2)w3ÌF’lØã£´­ô±é£MÔ`¾ž&ÙÔˆƒib•#ºùÖ”/5Q.ôt¤U¶9ÌÈÃa9uœQWŸæ ›#uN’”|ZexžÁsmÓ•NöÏÓƒÎ(ßÖhË×5I$ÂL£k{ù¸nðªó˼κ«P–ÐxÇÙ'c¢‡«6cy+¦tl6^L¿§|ø—©ô†|`´tÀt•rRc/úÇCkjÜ0Oô±ý~¿÷>ŒnÌ=fÄ‚|.ÀGw,¨Ï‡²ÙVÌ V¯Mb I£äAÀ•Äئ¡ ¡˜y+Õ¯µ‘”ÅÛ¦VÛ2ç9a¼š+vjáþ>OHd¡ØÌ‚€IãÔ ½á&ƒÞ‚Šbe|øÈ ^GbEM‚ ’Eº$K]ºJ1$¸[ÊÈQ´ŒkWŠÓ>¬}¬²÷ R§HÁ‰ÔmØ<Üv¬Ä¹àrÏ`L;ÂG=ŽÒ`áJ  Ùµ¬·ã5/ÄÚ©xëõú[¤ÅºÑ¡©,¯c413’èÂ[Aºè 0Ïb°tûa°5$$Zkjf.ïßÀ:¬3Q*‚PؘWùöEÄXÞÃæG;+¢Í AJLh"ÿH¹ÁôþcZ’1–‘ùz#1=¯Xt0§ íäóD¥–õÁîÑ`G› “ÄRÄ$ñD Ša¾Ü˜™•f½úÒÄ$gíGÕ¦°V.”ؘ3F¬¿P–*æ›Ú¤AmÉmëÚ´´”Þbηm2éy ¶³Úã-“Ж™Ç;؃qi¶|ˆ°ÙQa¯ Æ3‚ºÆPË| 5ãÅ;õâi¹xZ/¾,ŸñOùöërq¨–‹½žîçªGÑËz1Í®)¦b„nÕ„øî[$6ºáÈyý8ÔG_—GwÝQš5‚‰|í?åc_aFÏ΢ÍJ!p®àúÓÔœ(ÃôDu£1ÜAöÓ¬@0M<ÈÖdç”ýÊÇÎó~ÃgµìVe˜<Ãô©—z®ŠYà("G§Ñi.7H¥DuZÌškþˆó13hVå ¸á¦q:ÚTûÏçÇ2pmË܉mýþÛ‹,ñ­]}öxˆýÉ‚… ’·Q³c†¦‚» 걜Y3ž‹ç ر¶«*FÅHÌ[ay¨ÆDö`›g“Ç*ý T‘ öc’x©mžEó¦–DAªÖÄU/WkJ¿+µõÉ~ª&'ˆ•XÏÒÑ9±«#rìôLbôf„Xó¹=’ŠD&,ÏB%0y 7– Ô„šs™~,„hT¥ÑæjdQ8,¨‹Å£XDQ-}©Ò¸?ا6ÎØqbïJùrO7x\›KÉ%H&¼™†7Z ,ŸÇм²  .¨ >lUè´ÃûTOÙ “Ì¢V[öYÚ±žIcÇ<˜¥ÍLJOYóZ¾Y:-ÚV)—ÔVÙíËz‘qlq37=Zº'²PG›8É‹±”ú>ÿ0;€¬±lTãBh&Ktp*Œ, &WHaîkÚµWïÂ)ùÕ*9¯K­­a"$*vÑôK˜#(má¥ÛTö÷ya.Š©@ °*PÑeû³å$6š#×~ûyô‚=yìêA“öŠô+·ìòi?#ÖM¡“2ÉŠõ;»’uL™Ôï9˜E’•A UŽOäNëöKGúVå`ïzj•çäGѨbçÂ_`¼1'Í’©ß–ÜöÅ\±" ˆ±ph7†{&T¥lËMý#Æ“VùȘŠ1Ô•³Å ìö¾õ$ÃbS³Vö}ÍÃ~–CË)pw‹&û4a[hJmó{v‡>žEìˆsñ|ÆÊW—è;•ºöGHªŒß¯ÁõŽ,‰6·ôrétO×a¤¯‡Éçµó×Ô€àUÿcÈØ8Ê4¢—0夥™¾»̓Vä„ CÃi±­­è¾Âê߬TÝQQLl”L»š€%2k^Ça¸Š}¡ ûîšÚ·ßH€DeRbmË4±OH¬5܉° òÒä>™¿ajÇÔÊ~¥LЦ»¹ËlXÔ²ÙMNv_Êk1þXƒŸih2[y]m†›:œœì™Ý”_óÎæ!+™7‹hµæ(ZÁïEMÁúKÉhanCÄ/ðiNQç°‘Y(ލHP~ýèÐ>±©_ÌÜ¥N?oÚ |¦<ó1u±,™•ï¼Gv´@jÒfÙwó¬+žƒg€ª”ÆÝ!lR ¥]kP³äZSW9ïn”Óù¦³©šàì½Aýs9Y€&—ˆŽ?(m@ßÈ"øSPzø[ᙓ%XNù4ýh1ÏÄbÅå/ðh3óïÅÂeàØ¾Å|ê0çää+¼˜,aÓ îU\d9Š-ä/Ÿa<â{ÛTö›6ŽDÍGI˜÷q¿80X!åvâÅ—9ƒTR=ÔÀ:›¾‰½;ÒÓ¸osÖ)¾}Ý$0òMñmžQÁ'åHOV±¼é塺u¸n•ï¼|zr¸·¯XßùµÞ®¹¤§·³4ÒE#ÝGA±ßâá¬ò%¼Òglp Û†2–÷¡nŠïOþ3iˆßendstream endobj 955 0 obj 5164 endobj 959 0 obj <> stream xœÝZéo%Gÿnå° f¢¼qŸÓ=+@,9(„°1"ˆðÁç³YÛÏy¶w×ÿ=U}Uõ›~>%Dhµö¸Ïêª_Ý?ìŠAî ü—~]îì½–Zï.ovÄîàÿr燆ì¦_G—»¿ßÃ<4 “˜äîþéN\@î:µ;z3Hµ»¹óÏNö¶Óð_ôö_ûÂi^TÓ¦i°#ÌÜ?†ÑŸö =87M²û²—Ã4y3u¯zÕ}Ó/ä`ŒuªÛ§1ŸÇVm|÷Zå˺°%l× Ð«Œ”á¿+ëÎÂ忆Ý>ëÍà½5#ïø †+;Há»/zœèF×ýûý¤µì¾ê Çk£Ø),„¤ÿ£u.tj\Nvßö Nú°J†û=0OIïÂÜïz•¸V3{‘ضÐbpð¹÷E?ÉÁyãºÝ/Ì õ(Lwç]•êNâ!¬•Ý9ì ‡ÐÝU¤ÅLºóÀ[ Úû¨:FÎjhYã  Ðíò>fRl:Ûœ€ª¼šöD-{ƒä Ï3šñ0ŒÆS\AÀ ²ûˆZ/òbxB¡9¶{GÞØËiݕɑÅ@VL3 0ßàRBH\i¡@~„=s#|Y Ù±(_ÒÈ¿•Æohä¯Kã5‘N¤ÞAˆ$ug¡ã‹øXÁ˜Ý#WqÓ‰¾¢4.hÁ ƒâPM›k¡Š^&ú›þ b8{ÆíºØý9ƒÕa1PòÜU]'¯\±¥QÒ¤VcÓ­€Ù)ºôu‰´V•å(b!K‘QgÝÜAg;Ž,œTÀS#<ã胫ù%ò]€I[$¯¤<ã¥{ pô î5JÍCœ)’‹š{'îcÔäÐÏÖ>&&^ ݰ"UÐæ£Áj ÔÏÙíÕYwHŒ¦Y j4Å âjè²ß0®ÅV£ê09Ž c¼U»[#1`hDV ÷ær¾SÒ•á!€ƒ!߬&ø˜†~8eüp 0£q[«ƒŠ‡ð%"öÿÄ`)({œ‡¨õZ„a#‹1tmÖP90ðòz‡hÅÑÓ•¸/ÜPH÷®4žFUyúº™â¼›–”Æ55Þ¶Ö £ª}Xúï‰#2t¿ÚÙÿ81¦ LWÉ:ó7®÷ £Q7#ó®[›µBßÓVã g¸µš<â{a!BÔSèËBôÓÖš'-ŽžpæGòF×-»æ#3nùÈÌú‹qMqWt`Ç÷¼ª pÈ1 ä¢þmþbYJH“W}ÛÂÓEÂÓd˜+9EŽƒ+<Ù`“ywÔ¸¤•š <ñ¬R¦u ·hÃUÞd6D’¨'îß·DrÑò£ËŠùÃÏMÛ.ºß0¯Z€ø ÞA´Ì²Ã9bN[Vã®(1/}AX¹ (9;Âe ¾W­ÆËÖ¾¥1ï Øá¤a†ø•eß \?°.³Ýï?ŒòFF.jkl€>÷˜r磪*rE)-%Õu¬+.")JÍ•ŽI5Š%‘K_Î3ÀYÙ¦¤ÖwÓ)ÖR Zñœ:æj,³ã!mÊ4Ü8KQÉÄJ4íh·ˆ)T¨2aªÍÅyJ𦤹¥¾åŸA'ÊV ËÊ=Û fl¡€çš¢Ç:K3y)5¥ªž°šÎXi¤ÄœGÞÑš×I*úÙõžÂ•})]’> ,-,ÓS¹$°¨“—QL-.+ Éf c²ÃZ!É®ZŽ7*Àþ˜‹7†¿žW)©ÄGÀPY„àÂ>³|ÕC:Ø*n䑯?«›ÄönU €Ú1œ¡Rè,oÛŒµŸ¨Þ€³Bþ:ŽA|Ô Æóuª‚Vl&æx¾„nü|09](çÀVpÛ¸ ›ü*,¿O).?Ka "ö´Ä•ùGñ¢‘Ó!ˆQý2Ѷj‘¯báv3,Øk9"ÉâUyÝò»7ü+wSLÃøË*ÚÎÙ(‘TBS~¿‘ü”eb&Ó}\¾þÕŸq°*m¯ çVå‹2šËVìü"à‰~^á!5¾lñ"Pæ¨iõ½VŒvÝÚ’¾.Zû¬·Ì™‹º%!¶ÐaÁ¥t[BÚ½R]4&ëÕi댉JTÍ›>háØ+…7c"&ÊuÏ;®1z3£ôA«î‹ˆïHÕBF|D^5®Šf6“±{ÊHˆMgU$š—£(í¼OH —[Fæ•XÐëh€¬–JC…ô<ܼÖAKRFè¡SµsYMÇbè9¯…ÍÌËQ?‚gLF0š#«ó1apˆ¤qu2r›„šSÛ„„d:o…L€Ud¯³C÷Ílvƒ7k f×þÿ²’øÌ01SJu…—•<+7PTþùn€L~MH]D ^¼ìëÏQ‘ñëeý|WŒ„#Œ<÷óÒÒÞÛ÷cœzÃdýý &ë§’¢qv£UÐ4'G/Ï3„©$ø˜!ü ‹ÁmaÎÜc6+tß‹qJ×'¶û'´ûVêB1÷½¯°“ŒQÁÀuuÍè¡”NhÎËMUSƒò?ßÖ#âøáC±ùÎ’XP¨˜Îó„@¼1„t£ò1×ôuë,7•giÅ뎟ÀÈù‰òÃè…ä…Àøì6<~`5Òƒê¢äWìÄŒ¡Þ\_Œ”oèõ ÀX|Ë«½ùFãm¸ðÚw³Ç©xõg-ð-Cz Ê^>ÌžQqùœa¯ê“ä%eãyl|zVªáì¥VõÓ ‰7ìFå„ ÏgoúÌj½ôš&ÕäSûƒEuã<»(Àºî 'FR¯sîIåæ*<áyðN%#çE/*¤-÷xÆübóЖ¢?ÓˆñY}Rö€~ã¦%Ým\×ZÁ¨JŸø²â]¶A)W½ZG‚ØÃ#6ó¬f »¥+@ÏíìºéŠóБ¼${Ò‹¼€|9%mß[’‚3þrIIhaÀY~l¼ Ù›´Uà{îØ°„[öÔ9KIøî/€ÌÈГOŒS4ž{«ÚDÆ“΂K!G>ßßù+üûs†›ÿendstream endobj 960 0 obj 3093 endobj 964 0 obj <> stream xœ½\Y“Çqöó?bB⌃ۨû ž’–à dQ\‡ìÖ vÀRô¿wf™ÕÕ3»A)HÎvWי痙õýN,r'ðÿå¿OnÎþIj½{öæLì~ ÿ<;ûþL¦&»òŸ'7»GØ,à£%Š(wßžåäΫ f‘jwqsö—½<ؽ€–ƒZ¼÷z¯ÓçAˆEi¿t0‹ÖÒºý§µÿúpncL´û/çðþpû?høÖY»|8—KÞ‰?c &bSlh½Úÿ:ÁŽ~Ÿ8gœ­/ûÛŤÅ:kcåâLüâªLçÿÅÖçåí¹‹—1æFßÕ•¼*±X÷OaÆH¥ö/ó ¬•ûoç*-Æï_A§?Îq©N˜ý“Ö¼x½I½«'j¥m÷oaU!8%÷ÏûF=…×B/Ö9ò¾MòûrÎ;“* óUûoàg€±”#3hß¼ì?˧e”[”Òeÿ£¥ùêý%´!Ÿ¼J*¿Xã÷ÿw8ø¥ŽNÛÜöOÚNÞè\…EïpsVË­Ûᵞn}ã½ÆAp­yŠßâŸ@Z²~ðܵpK0•(°CiÒäôa®ëfMÇ+gíeÝ_!ûö×Ó‰Ö¤•‹_{ü)ᇱóǶ‹”ºtnáí«ÔyPVïe ³!s¨;ióÎ÷/¯úžN°M9-}›Mb‰²7ç*oÑU'úFDexk!±Nø…T=ã PLð‹w°À Ýé-º¯}Îêç܇#À¡ëM¡Õõ¡Ùê˜I~~æ8ŠÒéüŒ‰ùV<…ïÛ'¯ðRH`—bß–è6 8OOѧäL*/G è™ðƸùyµu.OÚ/Îlóal[IëÌßxú †ŒNVÎ`+Îó±©õ“ɘlϰ%œ1ýÙhþª"Hgq:& õrRÊK"dü5‘2H¸DÊ`oÈkÅ’›Ià+ÎG¸Ãhß\7ÞͣʨU⌺9‰5l yþyPqQ„Q¼ÈsVR&ÖG]‡š©cñAŠFN8®_€©`Óã¶6(B~µ¹¯üxа”(­]4U!mv’vÙG¿ä4Ô‰«9Êã’rû‘œUâ‡pp nª…žN(—}µ-ª†7; G[€(Ô&ÝýåÙÅ¿¡Š °Ÿ‡ðÓ¡,šDQéöª¿ÎÏ‚”{«£äØp<΋$;ÚçoqõҊĘðUT>‹v go=,Ï, oAkËÑ£ýþà¼UIÞG»à‘“>Ÿ××x¸^À6ááªEĨe{£PÍ–LâYÔ¨¼J»ë´0ki÷öDF '¬ñ^—¹E~RvjjM)_·ùë®q^ràÆ çÌþº< ÞM–¸ÐÔØžFp‰¡/Wê@‘8¦«'bœ¦+µŽ$YÄò„8™"ÁùiOy‡ôþºK–×Yœj¡ÆUn±” É>.JG‘z°³ÏB#¶yØÿסZÏ/'úã§2mêÙ¶^&#"›J±jƒ¢p]²PØôÉ„Èd>ÆÉhØW…ž’¦R Êø¦ضçÃòzÛþI‡)©=E:%‡Ï¬³J WW$¯­Bz º§Hq°ŽÊšƒ§$ýlÔç]À#9¡ÙÔ%,¯Q[Ä«‘¬YoÄ"GQ‚âxSyüM6ÕE¦U½²ãªE6{zeï©]¨EiðŸ¸t‹†k˜¼_\ÃÞ·ýgotÝ~==xx+}6FZõ“ÚC„ç,zœfÿ«öŒó¼=¼éŸÎ~Ò>¤¿Ö©þðWlàâ¢ùëÙ<Þ¶‡—³‡·ýá›ö0)æüó7‡©«{NOXU¬gÄnŽà”à[çØÁ–­ïGžñbò(ÐKˆÆ7+õ¸üv«’¨{Éåq±™Ó¬‚O"wíwäùQ“âgtšÈH¥6àÔ+ ÃL„ó† @Ì&ÌQX2sÔ¼Y—ûQ휜–(ÒX,M·fã(&yU³O1ät×¶êh[”¨Ä¦Ð­1¾ÀÖA#Iƒ ÕiöþB?ÐÂ&K„@¨¯óî3Ä#`sw•\ÑŸPJ„ÿÍ|MpB=í¿kš"¯qG¹¸~Ù¤ûm7^rg ôö4²´Ä ÂÜhЭô•£XœÐLO1Ý¢´<€!³c~êý£@Ì+ [ÞÌm /NiôâXÀôwÍvA¬üO¸ç!‰˜Õ&ì?G$2Ø ýââ쫳ïwЕKÁ[` °SAÚE„Q-`HøÑ㳇¿{ûÃíÓ³‡Þɳ‡¿Ã=úãgðŸÇŸïþåì‹Ç»¯¶Å\rÖ@± 8 ¡Q—£Å9l«­Nkøï¶"®‹ù-î!¸š!V_3ø÷Äà¼åâî·übiÞG(ÙÒa·Ä0?v-(üS¼?,õþ¸MÔ´Lý‰^³Ìì6÷šYÈP) ý¸á¡V)¶qÙW±åã[ƽé/·ÏõŽd@%U:7rç ¦vó Ó_NR¦év5 lWÐSg?dÒ¸%)’'rÊV§€ƒ9Ö½šuñE)à:ØÇ"$û˜˜‘•–N8®PåAµ Äq¤¯âVÉLd€‹Å Ã|~>L;"¹™aâ3¼KÓ#xÄ>Å«B^ Ã=׈40ÌxB=¤qÕJÜy @éDk*ÅI/Z:ÔMTu^bG1x[BdU,{^§4!åS¾ËÉ" ,œSIÓLc!ÄEïArÒr°n8uÌíDÙª‘q69¥ÀÊ+}‹ï«¾Õ›ú6e¬hËQGu:šž"fJØÎ…†Õ.iH\'gLn˜¾œ§øIPKnØ$"±9e’Jâ ,G“#³Xîf g :g×ôW8{HeýÜf›2‰è#4L ªþÕíJq°`I3 i§•#ΜW÷ghóý¼Ûh,†­lXJäjµ>’FÅ GÑx–{@W%uh57¡V²¼zùW½+TèíhÒä§YŒzêul„5Ðq øŸ¦Êýë2é-Ÿ ÞF˜ä1ê2ïð”±î¯ÀÒî¨*7J~Áœê49œµÆQÐDq™#¶È³vÅ“6†¨iÅlÑ„sÀvÂþ,è‘2=biSvÎS¹qÇ'”;VÈ85!ePuÜ` u0"?˜ô•X%Ã=/"49ÛˆÁ=Þ” ª?)T½n°Pïâ‡þIƒ~1 ÈŸ‚nÚÃW½å]™¸ÁÚþ^èQ‰}ô•ãHõ'Iå÷F‹|q™tK1½Ø’€vrÎ׃.V3“1™˜óÚî’EYÛrü K¨ìê2øG¶Í¯D'É»EwísÔˆÁƒ­›å?02m=—‚_Rð"£ö9Ø–G*NlB}Q89·ÿCs¿<„äþ˜ýÿdÕÄ?º1½6cKnDÓ²}“ç…C’HXÅÌêH(’›&â‘^R„#‡Xy"ª2n)väûš† ›–ÝdÉÒ÷г«ÙŸÆÏElÕ•8ß²á/¹Ž9ñðggÓ ¬æâN2W6ÍiZAµäj– ÊIúñ.VúÑ`acæ8§œ «,9‘\B¯§Í[’ƒ„¢¸ª'÷n‡t ¬,Ö¼ Äœg×i`¼ (AàÏ:i¯'ÂÊý=`'ã:$JJ·…’áy¥ã“iN¨o;ܹͦœÓ¾aÌ’%P~8¿€¯³Åd-FÖ’paö!q7_¬l@¢ïK`·Ð8®“‡^kê€÷TŒvà_›S|dà•¤ FŽhU{ý&ðý2„ë1µdK©O»ty#ã»› ÂÙ¤mqÉîCš `qƒã,&ëÚ.0ŽKph±=}Ì‹6¿Äô1ñŽMÿ¸¦¨©˜²U‚hR aj\Nz TÒ|BÅ'ÛHÀdnu®¿0Ôºa.Ì)"+%b¨ýƒï28ûÉfí»< ^OÒöÖy±Û‹ ¿Å›(ʦ $³‘zˆî.®Œ¡?v/çy“ùÒäü€,p5r%¸ 8(7î6ìXØ"-MÁÝ$Êã'ÄXr5ž 8ß„¢ÝÍZŠ4]&FÙ¿™*%8ww;69>‰ßŸ'+BLþ sf9§sc¹l7–ç²IÒºû7[ym5(ªålŒå‚}*å}£Ûëi0Øuy€±44xU!ÿ(xy8¥ÿ­¼!¼C$¸N¼3¿ Éb<÷êü7‡|JÛ< -Ô€ÑæªzžpÁæ5e¿\Ñ™Œ°Â?›Ó à:‚lËä¤4C?êÜØ*.ÙŠKp~Lye[»±7R±Ë6A9UßÒì# ?MÑçÝ\5Êzu`ÅÕ³È!bŒ$²êiS(»Æ"Qx%OM¹–xÊ/YZImæarÒÃ;‡0°¶¦&^„r9†Tš9ƒ W6!2ÐpÝW»†B¦$”®Ršîâ†ÒYg¸¦›˜ìxuÑ<݃GåшwŽ™zÉ*V*šê¨Âã®­™Œ}ÏMºàÔÅOo,Þï!»k!'æR؉(8UÈ™/~rû÷EÎëAx’νÎ'Å þ,µt, []g0\¶¡ÛmdMӜʪng6+b'Ö§ó^Øwð~Þ½ò9Õµ‡ý$r6‚Ý2ñ*e¬¯úH`¶n1@kQ‰Ü­q÷÷-%>¼)µÄÄÚ&V!¹w#]\%l ¥Iåò©ì¾8“=âl®TF2vUŠb•&§Uu|ª?f=Ñb&§ý´{_[Ã<¨¼\aôŠœiõÍp/Y‹¡¹ —¯¶˜)v] ÍÇ0štô\ˆmõ²ûŽÕì¬ï3{·;bÞωɽ{û0oÝ"º­wâ$?aʨÜôó—Ú°[CØçßêãfË-­BÙì¤ÁšÊtñ.:Ù/>ýîAíEþ¦Êr@ÓI€€ÓéŠ3Øg¹„Z]iéP}ó!â‘(c6<̽ h¤S¸*ì Í­ëô ާøË¡ÀœCÌh0±t=Š‘Œ‹DNØÒÍSdÛå«y›¹±)šÚ] ”êsη/µFÇˤŸyH·CLÊF¦úë™m’0~ãÍ(©‡ŽËܪ ±f9-Ñã-”Íô‚Ñ{Rs9Àfèì]Þ™ãƒÒ/ßÕ²ªå¢ÕÄè!kºç•— ˜´ÎC– † ñ§î/Ë»]#hãUIÒoV[ßACä~•ŸŠ™ü.¨V_¦Õ°³ô£FNÜafs« Šºšl#—±Twᾂ•»ÄO|>” â§§;Á½Ñ~f*%¥{ÿÇ®Q¨,A®ì:†fša»bvRH†«>fu•S,¼ +ï¦w1•ËY}Š¿’Ë`Š<íÝѿߎó=˜}Àí+cBB_H)­ž¤ÜëNÙóKbªéÃjhRü諳ÿf/†‰endstream endobj 965 0 obj 5575 endobj 969 0 obj <> stream xœÕ]Y“·‘~g(üFOêv¨[…³¿Y²½Þ í%qc啱CŽLrEÎŒDQׯßÌÄ•‰º›Ô8b7«P8y|yúöj9ª«ÿË?}õè£Ï”1WÏ^?Z®þþ<{ôí#EM®ò_O_]}ü˜šxtŒKTWÿö(u ®V}åƒ=*}õøÕ£/wjïvþè½ûëãÂÏÂ">‹ñè<|ùøZ²?˜ãºÆ¨vÞ«cŒÁÆÝï÷z÷oûƒ:ZëV½{ÜÚü1=56ì>ƒ§*B·+ ¹ÀŸ#¼Õv9jË~QûÝv„Ýÿ Œö‡½=†à¬ç/þ͵;ª%ìþ´ÇW¿îþ߇hŒÚ}º?hlo¬>ÂHÔNýŸ¡±÷n]é¥ÁîÔîóýÁÁ/« »¿ìõqYœVôÅã=O«°Ò·_ìu¢šQ†Sí Vôöê`–ã $LÔ{ýï~ÆÃ/p}Ë¢Ôî%þóküqowßã×ðGQvb}ûôÑãß~¹{ßÝàëÒ4õv}®#üú£“_ÓÛÁtÛLSãs£ ^±Ÿ•g©ÝÓ:ïÛ2¯ÔøufûìüPæšÚA/y'x¶žûöð#ÖcÀ=U+åUkxÏv®ÀmÑ7­áõ~=Æà–Ž€Û_Õ~~M÷ÅÉ­áßê€í“ïÛkNàÒϳúì—Ú0‹ºÔ o‘Yz=ªÊµÿ ¢ù< …s89‹r¢5핆8ÜÀòð»ýÁ±Q³–× ó߃°Áø L/@¬ [ÚlìÕ/ž¦ }ÅöEY\Bi`£cýˆïÕq XÁíÞ´6mˆûÖ³x_‚žØ½×ž½,“ù: ë\ nËâ¬Kìáýê--äYz+'¦A­¤áWcÚ Ÿ&Íä¬EÞ)ŸÔׯQG9·z½ûZ.á¨MØ}µ«áLPB (.q›¦<ò¨OmÖ˜x6€b[t]„w“5–¹þ®<úha{ô¡èú`Ô¯ö8uJÕ·ùâT4¨I£ØbŸ7…Éhø¤=E¢±•ÖF¶Ì¥9Fx˜&¹¨Bd½*ê‚mCé6çIZ¼Ó¾}ˆ;ô¢öwÛA!Y"ÍïG21A+Ëš¦E¹%–EÁØHžC¦Ï±‹!‘é:³É‰M‡þ”6G+Ð2M2ê.t‹™GfBøè­Ë&ã:ïöŽËˆ¬³Y­ “ÌAØßû¥!n¨‹é}îùˆ‘Ë¢LÌk,C [ÁZëŸ+Ž8{ L|PðaV1š©Tz¾c jG‚ Ëœ7¬‰=&* ±4›ß†·’@ø£©àç‰ìG03#o“{4À¸†°€PÆ1×½d¿AK CI¾>Žn­J$ÉZæöä4>®n­ŽE9b'Y[kØ|¿¾Cr†£Ñšuv—â!çPa ÒhcübÇ&ðVÞ@°[ €-D0aÐÌ qnÖúuzç2 Z&T0òçØU E6דØ'`à=âøÅÏAª½sXc…L€ôôˆi;]ˆKòN*YÀC%+ÈÎIÌ÷ÌŽÐC´©cåÑŸö“o¶ÝÃÞÚóÂUUt’›6,Á©³šöÊÌbÑ.F5¶Ý*äÐvAîL=nÕ‡8-Ø,e¶*]ÈÎmæ°ÏŸ4Ñ:Ù'Á§ÌE` ?¼VñçÅ<ÿ–¥)‘LŠÓPˆš1TÃZÞ6¶ž'¶ìË"ó~™åë2ÄM!S]šZ˜:Ù~ÉúËó¯ï²êEã¤ÿeÄúPme§Çd‡IÔ@÷»ž—˜‡4[a9²PyxÜÜÈâÛÞu¢„< ãZ$æãuÙ";éyºµjBŽâ"í"‘ä1I8«!‘Òɇ™!ôî ì²âoï×/>¨¿1RnVÏèl%Ãt’,oXXëÄÐiÜÞ¬RÝE\&2êâhgþcŸ" ÌP|o‘bf……‚é¶‚É þói/ŸZå Wiãs>CÕ¼ ›„ Ð1 .c÷ä¼hÁ­g½ð‚†è%xÑ$ÁÅ»Ážà¥Åt†áNâ¤ÁvÚ6 QkŠ‘ ±Q‘®³D„c8)Be@ÉFŸ€~eÁNqå¿eØú’i¡paÖV‰¤Ñä³â&*îC4¨HF =<…ÚÀMXGàûæþpâ¦#QIÁ04mŒÐ«YŽ âÕFG¾ˆŽ Ôx]éÐÃð7Óe.¹‰Y{v3ÂhHB뉟·Â¡–H±xƒïAw’F kø†i5Æì¿bÏÑ3p«äõ»6 Åb€Æb '6ÖGJX˜¬›‹ ¾^5h“¢ç›N‰ øH§¸…Ä\ÎmËÏœšNýžSˆÐp‚.RÆAEa50‰—ìá"ìùº±Ã’ýŸH7|d!0^è,ò­ðêD' ¬R ûe2Á8¿«6Zµdg Vî.,¢Œ´÷MòrMRøl«ä™`3 )2 ]²y·—|Þ“o˜MÑŒ9Æ…Þ>†¥=©Sñ$´† $Œ'ÊÔÄKЀÇ:_Š-4¬ž7ú¹7Âèhï("sÖO×þ„Ÿ^ÇrÂð›4¿Âí-údJ¬¦níá/uÖõý‡ÍòŸ1+·¸G í!K~l|îÇÙ÷#«ïóyë4c‹ z Ú— †tJûã`Ë_"9UvŸÛ‡‘±’âzÍÐT‰æ~+¯ßˆPZé~j{Fv¿²û“¨&­XÛ=ÝîÛž4“3¦ ÊÍ0- S䥻“Z—Ñ"ã©ÎHt,Þ…,pZëŠìº T"ÍÔ3jÇ­4ø„£¢]   WýÀ5äŒ »‚v>L]mI”XÂîù¸í,!‰§ Þ[ªm‘” ÐÊÎcl^Œ …‰&zY½•ëÂã.¹G:g e)¡BGú!“É•8<étcxn”ø&+&£8dÛ܆E•/Ž?¹MËD”‚ód¬ SD^³»$ Á’ ¦iþkòsÀqS„,† <×I\Oø3Á“Ud‚1‹BmC YnҪ˜¾e üf0‡áGÅu“Ã[úçl\&©SOkë-¤Ù%?)ÂPcÈ7ö)H®Ï…GQÂUš¢Û!³6…ÏŒ¯Úʼnµ]¥M)A,¥Ïß°øÓ «L‘eg‰H%1àF+#Ãgæ³Qô™<ž”Ïë4:OË*9Ù(b˜¶SÒ•2Ѓ†ëèºÜvŒ¢»·ÙYsÀÎ1aó¶a—^ Žv±ÌúF3 '—ˆâÂÛgÚáš'Ê䣈¥´ô)‰LX™Èœ à}‚N0a°Ý™Ü-nEùMcÔ*/ÆA ON&îo ™‚…ž[¸ .ãs–|0ŽÒHþí (¶z°ˆG}H„<$‰‰…1Hˆe!¦é‰ƒ»ßØñìÕX0#€¸ ucCDw~¢ÂÜ¢È*CÅ• k´eRÃÙ˜lÆ9%¼±6ÌD(Ò+ó‘Å\ÈtJ Í¥¹ªÎÃá™:0ªl¤SËÑ€ÍmÁ‰Ûäþ„=; ç¨|òyÀƒ÷ÈMœ· ¢âXù±Ó-¶?ËÄó‰°@µ8K‘eéˆjS.†uÅ£ W2šÅä—¤•Í’œ,È”Ô2`aC†á“Æ«ðr1¬&’ÀV¡®<—mIø{(üâßÍò0^.‘£¸’ú›²£2' Nêk^Ïp‚·s믾“yÁè‰òf™¬N…Cש§•†MÒ"e Bï¥H?1¹¹ñªpùϘ Y)'<ó—-8µèºåB žB*hCò­ l|}‚nms¯¸'Õ0µ¯3”Ú½,Z cî1S±hÚΠ°ld3¦u³€먀ñ™Š/E*wÕΰ‰7ÔdTg‘æ~?p؇…_lêç‹Trõ’„ø>ìbôÉ…àZµO—ÂhÕƒµÎh±PH k™Âùl è2¤©JÐ…-”B¡*)iß»Â$u†¬¨(ã¼`´(xÛœP£?£Ý›‡š³cü–A™á#UËîÖäî_׺Ó¹CÎçK.Áö1Ù¯KJYârBn’ƒÞ§£Þz,¨è­àñ’º‡Ö˜Gr?ÁŒ-Há1 #–£Ó)5Òî" {·¯Ua,7€ã2}=‹IŸ¬«ô°§Ée0~~N9—€%³EDXñ&/`Īf¹X†-ìþ»>< €ôKŠP÷[ª.)ºI¨nôé!}CÔÀÖ-É.T}Ê·S² dù°í¤«åkþ%Qé@ùÓ1œb^–)é±ÐÏ f^cù–M阶Aúí·‚©&©ƒÓž²JŠ(ÎR(¹R•vñØÏVÜMÃF>dLlòë.ɘ U¨ ?D¢*‚UdB\2["†Œ[¢Oä1F-ƒ\Ó²’EQ-MÉ…~RÛ•Tsk9(ªB¢¦XVnrªa˜uçø¿ý™ÝɦFQ…¿%WüaÒ2›Éu!ÞD)isÞkb2R[#—A"\°7­±Ìæb\"›ó‚ÔH†K1@'<7J–ñoăÕJyBæ,±v[ŒÛ ªßisɲƲÀñb×#¥‹0Ø´fYQ.ŸE¢ÚïÛ¬‘¹Lþç†w‘€V\RÎWÿ#5˜TÖKï™ì Ø ÑùÃo+Ù®¾_T^2 Í4¹&’ÙØü|§ çèÀ\-uA#¢´Õhž3_«ÑÛ,W¿sÉ©'Ê›A•L³d_>oCÌBh%7}ºÀø.‰Ef¿6;h¶á^^ùÜÓ6ž©9²EÒÅyÙd¨Cº¹¼ÑÛafœ¹: |½Eò²¤²Ä‹â[3ä“è À%b8siAeú×qÄLT@ƨ;•óÃ&}Î/‹Ý9Øø2 ˆ?ªzÜk³}ÍÛ8³}€}™9Æ©Š ÍÍâ´®›`_|‡0³ÂyÀ̇U<Ã2ò§¢;‡øF^JŠ—¨hXaKõEÒ^ AÿæxȺn0}áX2â°£xHw+Õ]Ê‚Î{ûÁ q¹ˆ‹R K1³o†nΙCÃx <<…!!Ö(U'Âé8ŽM¥„2()oƒ2k.(ŭ笠\>mâEþ©õXÍ ,µóóª+hä^®Ç™{ýA•’ž‹ø.k—'Š2dY:ÖéW-4€2ıó(é¦O¤©O·ÖÆèyæ"|†¢Ó^a8¬+ùÓžÎ+ˆ,ðàf† NÇæ"©ÿm ˯ãÞYâî´E ÎÏGUKÖðA˜Ú¦<àU]›–²#«•f+»‰óÞ—œç1&Í®« ,Âpú +­ä"ùüŠHóÖÀi^¿ÔÏÓ³Q'¯ò»ö£Èmûä²®BóÑ/v ì‡~Ê~¨L™²ÍSÇ1/p­uTG–ŸHD»”ãmkÐ#…kDØÐöƒgŒ9¼[Þ|IO”-Ýçi‰¼]âØÓOI2Ë §·B ‘Õ ÇÀ/€1z(ÇõØA!dÔ.£|Ì2#ÜàbC’j~ôu¸Ì-Ð «-]D ¤¥Òâ%rg¢"ã<(£fÙÆQ¹ëÌc̷ɵ©êD>"C‰ÒÓ…]îõûzë×êÅ% íHõ§û@Æîþ‚ÝEŠÌÏ´¿N¥#­ÿò8L3·k½çêóFÌ‘now€˜•rP•¥vT+‹h¨;l¬aí oƒeªvì·ÏM7^ñ£çÔ¢z²b„NÚ¤í2vUS´Y,VG9G³»–j§°"HÐlÔDõ:Í }¬îëÍ\¢Š™¸h_¸~¹ðüWaMaŸS¼À±»ñÞÖR”öAâ4ûjö33/¿Âj’ìŒf®).:Îò«FæG4‹iÄÇeƒ´ qŒ¢såÜ>‘Kc–pù%kzk‰B2¼÷¢dò¤Kê†)s2Tf-1‹Ðö'4—ŒNÌS/ó냘IÊê±§þ¸Â»û´ÏÃraá–¡í‚Usª¶§íÕ”yó0áhO¥ûMŠKüWoYpa\ ,ª·¼><Û»=ò•ÎÀ´K ŸLãlB]&W´è2wa–T]¿¹Ê¢ xehÈÒy{'eSK8¹1æ½^ëeˆKÞ—Œ•ä[UØ ]Ü¡æÕ<Ùl‘Î\ªdÍPÏ6&b÷ÂtÎÝË ÅÛ˜†9˜.볜wÇNGFnóá«Àãƒj¹˜Å—ÔQ¦à·ê\°’a?Þk¡éaV½ÏƒS†×lÎw¹ -\=OeíÖœ&r]½§Z³vMÃ×ò„|ƒ{,Ã5J£þnðn-E­´­¦ Åu@§9âu>ÃKnt;{]Ÿ„u© ˆÛoß?«§Ïým S‡E*o”.ÃÃendstream endobj 970 0 obj 5908 endobj 974 0 obj <> stream xœÍUÕWõ5ÒN’Gïu÷«®®ûèï϶ƒ8Ûð¿ôÿoß>ùÇJ½zÿd;û üyõäû'‚†œ¥ÿ}ûöìó æñÑ!lAœ]¼|gNžY¯Bž]¼}ò—Ø›Ý{ypΩ¦œûm;HåvÜŸ«ƒ”ÒÚÝŸ÷rwÿt^lj÷§ý¹8hmœ,o¤Äw»¯ö0ÆYcv¿Ã1Þ‡`vÀŸ!xv_ÂPsUØý+Ìü'øó/0ÅZe½Ô^îþc¯aãw¿…_Ư)íaL÷‡à=‡ŽÓŒÍM x¯ØÃß Ðö =‘Ÿ•å-_è?»…‚ØÜîëý¹÷¶ãBÇ¿d]Bƒ_l$ 'n6ù׋ßÓA{~‚ÚˆƒuNñâ*œŠpøy~}®¶ƒ!ÄQ¸n‡  }ø&‚mŒØ]Õ”×ßÞµRî.aù­÷VŠÝ z.•Þ½ÇÍl£ÍîMžU¦× õWõf }0p`/Êgn* »Ùº BCÔ&èÝ7»²,›XAuŠóÃ^!M*O_–æ`€ž^Nè#aw ÓÞíÏõA)äî-¾±ÖYä©Ã< |‰Ào@š~÷ϼ÷F74ò¾ÄŒ0‘|×C¾úq/ÃAn@ðßíÏó`H°ˆg;+ÙÞ"`xä2ȃÏäP¶|Ñ•¿‰gµÚ÷eûæ*á`H4 \¹û|Hë'á=üÃ4¼þE”RhÞ7{‚ÏJAxhå` /û2Ò¡¶™,pèuÆ ŸÀ†V•Á‰|»‡…´Ñ𼬸B(ñŸ‘b7¾ô‹ü( u—Dœ Ød‡:ü´wü b1Qƒ—=qã1ô|„|… ¢,{{]ÞP¼ôÒàj$¼Ä`—-y¤ŸvC ì„Èý ‡ƒpQÓ­à ì¨ØÏ«Œò+Ÿ_e09oÝÆ‡ðaqÆ™XÎ9A»tÍñ6Û¥~('Ó4³{¾—¸EPF?1®©“3Æ%.‹\ƒR ˆÑ«þ|pã€eé’Mf|é=P¢\oÄ<´IÐ!š›Ðª’'ní ¤õm/m"µKgç|‘P$¨Äy ¤ûEåËëÉÈxêVkdh¯Z®ªÜs™tJÆñ‹ >¢ ÆYÐJBd´K!Üî)¥<ÌÈ, ‡uÝqCȆ)c1@y\‘gì ~5D¦¹Ÿý€RÈIº@‡xÒEQ½©âH®Jë†9`1dö† •ÃÃE4‘MÇ5$–]µ#×°ÀÑ&ÉsÔ<ñzñ^P-²"QW6};" çß1›\mê ‹Jጔ{µïøDƒ¡¨Ñ?ì ˜kVúDå™l™ŒáÄH»Óº¥Ëôú®Ò/;bà•– x*(=?‹Â€Lª#^ÒOÔ[…$ÂBÄŸÑꊫ|=µÜQnÀ[m,òÃ(b?«–N{œZ:÷•b€9D㌪ÊçÿV–Ç0át& Ðó$Á^4æ]âO¶éyfNõCkff°D"|ÇJ’Æý5 R•Ë8éÌ.cD®!]„. Øf "«¥¿œäöO‘'86óÄ{ ª”«É·l6Û7 8A Îwõiz‘„.‡‰ïQl\Í´#ÙBþ7uà@Q™n mAÛž½òŠ‘üã¾[Ñ_ÅôÇêD¤ ˜ÀLªsq‹`àÔ4²p0ð˜t¯þdfc5§÷OŒˆ;FdËBÓÌùÎŒÕQ ȃåÙ¤T€B(ÜîUNé5Ò‚¸CR+éŠÝ_ð/äàÀ¿¶üžõŸ»¿Œ°a`M_ŸãÀ{ñ„Úôðu}ø¶<|QÞ”‡ïgsnËÛúð²<³KOÚ^p0óÈmñÐlà?„hÛ ßü4ƒóMô¼¼ÿ©¾ÿÀ'¹‘åpYß¿~¢ÛÉÔµð<«@1WýáÉÅ?œ~tïÊùéÉÑ=k^°gw2®ÎÃÓUÿON÷%8N¿œÄë¯êšõðoëÈ×3>ÌŸ-ÿªžèyT ¨‚tV -Bó¤×ÍîÙX0X~!'PZ;wI'För¤'Dq|Aôô¾ÕëBT¦lžÄƒ,dŠÈ g¿jéɧ¿F®J C1:8ÐO¥…«ú 3" {Ãûº¾‘Þ‡àü^Ö÷ŸˆWïö~ö™J}璉²¢¤q—¯Øëé%WË«$„‹ìX“‡úàr½èqXŨhy}U þ]]ä¢<Ä âÐÞb<Ê>÷f¶ágõ+j¿›1á]}8•ÕSÆ®'óCƒÙz\Y@ßG?²>õÃOD÷V×z>cAJÓ¦±/*ª®§'~YÇ^-H‚ŸÝ„?-ÛNí³toÌ¥D‹ 3__»©ÑÖ¤½Q»Yh³ò_r…9WåY©3ßùýÌÒB ¾Üðœ}܆o¼é,=caЩUßÄËJGóhð~ÈÄ\¬²Ä¯ñ§'äýW^â>‹Ž¡ÄøeÐHM1¹ŽÓ{³•aû:åI€ŠS’<˜1œøätä¹ÎI“Ö?Àêêo¼ªa[ôÖ¿Ùã'8­¦ýbŽž$G=/T} æòO¦§™Ê¿.NdþS—x–¥ä aðñÉ©)W1‹n2Ä5.ûg=y&/HMÁ½©”ë@=Äb Ž% ã9 Œ˜­¸ŽÖ4-×!¬¶ÏÇ›Å#‹ €çC¹÷&ó×ùÚ„E£Ž‡Ø¤9bËpNËUfAµ›ôa:¿gö¯Å˜x\ž˜ ‹Àž äk¹‚‰œ0%Î FNŒ“1›DMÆõ*Ð"ã3ÁÛßÜ|&Û@±})ι(pAóÁÅh9 ¾²z°ŠdDžÃ´‡á FÂÍ,°$leâV„c²¡!låbqÖAo”b…¶9·ÛeÔ[Z™ÛYbÈ’Jð@kà®kWrdùÛæc­fæAI†üc,¹ ´ðÈ;(­Çæ4~MY² ùC84S&: väfxíW_ÄHE^©Ÿ~]`ÐN²–Š_XˆŒÑvCû…Œšüý4_4+-Xp(OqF<µ~Û\ 5Å!¥€b"ó/¦YÐÄ­`3‚³aÓ`㕽¤oM3œm@+&|ŸÄæ¼a9!Õ¡²2¢¯÷)Þ–|bõ3 8áÐОFÀçå)h%f«“KZrb%­;#ÜE;Õ'"„ÏRX4OÆt…‘ø 8=~¬²ûù4á^hð{öáYùKʇKÇ“-“4<—Kã­ˆ„Z)P~.ƒÔœþ ­®{3‚çB*0G¬V6:¼Ž¦ÐP×::c ù%gšL›z¤O.Š%-Bs=ûL5Á BŒ¢\D©3Ÿº/,‘Çsh˜3ó;Qþ:Õ‹{6¼# l ˜¾è²Oui\téÔÔf›š3)Øpëtƒ·Ù)Q½ŒpnM•ß¼«ÆÔ(ît…Bl gƒŒT#0°a´·Ä!ÈÑ{¹åº{m@>ÜU häbæW‹H­ 6á¾O´}ÚáŽg:#‹ÓÇaÒFƒ¬ø¶†Î:ÉÅ]ÍwÞm„;úJÜUÍL&Õ.·-!*ߨ£¢U’ôÂ2{Jý&r-ºï¦Zj£~VŒ>ñ¾AÅ8W)²©Q°Òö…1“¿••Ÿîc©ÕVÌIJ¯J_×Xè«èÍk–²_îþÈ· ×âfW†ì´¶~E9p<§òúþ ûHr€ÑT ê,kã¶×]úªò˺bVÀ<3ë†fŒ¶üùªU5 ›­¦™zÉ]-{ã…¤MÙ‡ù×ÀBèƒ0—ˆ-z´ã«-¶G|5Œr»/Õ“Sбi¬Ê^§"ÊèÉætîX¾ÓÛŠ1€MÍÓ‡ik›=x'¢îÞbÕP³©Ü3(·ìÖ¡ÑéÈ-A'¡;÷·xQºnÒÚkÎ)ý6 ÕášF-¾?ð7ˆ˜))ò99ô!_å¦&ªþŽEup¥@uÞ¼=f»³Ž¸\à¸Çeehei‚¬OŽ&zè"³Ô¾¤æ¡ŒìÊ+ÛˆicéѤÂ4Ñ%º}£ÊÖjõF®DÜ­Šë.[ÕûëôÁr«úþ‘Òî0¸ûÌ öÎöŠŸöÔº*Û@V[-Ä ðÚ¦ c(Ò»ŒÜߤ¦³lV›ºµB*óCW3—Ëõ}`|¾ŸFDÎ!ä ·(õU†ÑbõŒqVÍ#qö 8qC€È#ñÀÌIÔ÷`äýœDÄemÛ?"æ-â=¥ƒÝäÒ²¦g wƒ&4´ºµRØ'FôLy¹( £€bã$ ƒ¹öm„["×a}Ç&iuÝo­2™©ÛÜ›mrñelòµ°B³>EJ†Ø~uÜ`E3zÚî#­Èm£óâxeübäLBé¹¥˜”}.ÆvÅa«8:’½;=Òïг ýŒ¹ŽsP;«;‰ÝîùfYjÕÒ‘]J±]tât©z˜XÍ€aVŸÚ”ý WÉG›)µÔŠm¦›ÉZMsúo ̦dí‰ÉjvÞÇŽ¹/£è[©ºU5í;LbW2¬Ú¡‡˜¶I8MaE£{̼ì¼VT‚¢³Ô¢‚2*U|_‹Y¾Û³¢«Xd±Ê ²þ;þ¯™§Ø ÙÌP‹j‹:žBÚy¹gr¤á1!÷¥æhœxñmÍ ú{Լŭý¤Oè&e¦a‰ã`éÝŸK?!;»²ºR{›ã‚„3Æ}ù>ÀÎÖvñð.³·{À<“üo’U9>1 ¯âç*º¿3 ŠU0«%k•Œ8\DíReÅŽ¥Çtí[ï¦FuîCWÛÆ ëN;³† ÁaüRÞæ³X63bKäjù ôJ&¹Ii ŒeKúØ))˜ÜZe`ÇÄVj#@£%燚&¾5¿µ9”±m:·Rtzœ|}=ñžozQ»œx½PúL`¿•tãÍvØü&²K/`ìæ4H-þÒhè¸) ¸Ø;ifœ(,ZøX áìz•ÚÄ’Çø°yOÑq³éX‘ +PÄ¿ d€-á/T¯/bÖ†@Wü€ü!sK„ó= í`ݦ™ÈÊ)-tŸ:ÄÒD Ä8°¦uƒØÙâ@ƒrðQ¯˜ز²š§¿. ±‡¯bbA‘ •aÊëk·û𠺋dà %Hç¥Þï1ùé½ve pý%°‚¬÷c¦Y‰c,?U#jËGŒwAåæ›d³2{bݶÊe –´‹˜â~DåJGJ²˜É‘§3q`4±1¨d2„VM\ZÄÀQg>ºÒä&ÅPÖ–o§ ¦ÖEßbxhÞ±ÖÚÐÑ4j"™‡ŒÉØl†nÜæÛ*Ÿ·)½(~׳tçµ20)Üåþøý,j!f5—èþ µÔtÒ`B?oµC[Dƒ¬?%S1Ó* Vœ5 òo¼é« AÇjÀìš&–ÍíA°0:]TôEŠÏ¸ZžòØd>Ùbh¨ä)V–Є¯ØF.#6¡g'a+e»` —2˜—dÇÚÕvMnRH‘7”ªd{¦MÃf^8ÇåÐ)¥¹˜à_ÜdØYbä/kx³çù€„M¾¢ÁvMÜ?æE—„—±Ü}ÊØ]š°mFR…™ G­q¶W£C€YôqÍr9.ÍJ‡$üD*¼Î%b32„a®Eçá¡Ö¡Ÿìü&âÎȽ –YùìR»ùE[m¯> stream xœí\Y·~W ä/,òâ™ÀÓnÞìyÈ} ·÷!A ²VZ¶4r,;‘}ªxV±Éî™õÆy‰ Ù#6›dëøê ?¿™'q3ã¿éÿÏ^=ùðOB©›û/žÌ7¿€?÷O>"B—›ô¿g¯n~|ºyhš–y7·/žÄÄ“7ÖëIÈ›ÛWOþzGsPðGÍßo¯ù™½¶,“±ðæíôþÉñ¤&ç–E~yÓ²x½~t”‡?ObÒÚ8y¸­}~[•ö‡?A«X`X¦œáÏO¥ž'©iÇ?—q×áð¿ƒÙ~zÔ“÷F[úà§Ð]šIÌþðó#¾è¬;ü ŸûE)qøÍñ$±¿Òr‚™Â@¸ôßBgksá¡ÂáÄá£ãÉÀ'üá/G9ͳ‘"¼q{âIá]x÷ÏG™¨Æ‰}Jd;©yrð;R/~³:¼õ×ΩyÁ5’ÁòZÅØº„É@ŸlÛˆ µ Üv»ÍȈÏ}Ôï_‘ÞÇE‚S£v^.:˜ˆ·V׈”ÔdÒ§g¢Ñ€‡Y.úRÊ “\À—6ŠYE B>/žSañ°Š1i½UCáéÊ–u‘(2 ÀÌ·_Ö8+ð¶P}ǦÊV^ l‘£§¨o@)š_fŒ5Ú0|Ä[D¸ ‘Ë¢“™õJÒžŸ5¦iÌAYz|ÿ,À ·&Ô€LØVÖ@Ùà•÷m2Z‘MήñÎU=à_Äp ʑۗµÃ@mk ¿±ùÉá;”èªðÏ ׆4̔ۊ£P¶±T©æ˜ç૬<öF/Wj0Ïx>!ɨuæ€|‡îQ–“¤HW1‚ðqÏÑ•Ÿ}B8˜èd®v¦Aög¦¹qÊhM†qš°"MÝ"¡½Hò}x‰02A:8zÔ@>@ú ˜³!g‚2ûôÖ8ðI32•à Ië9šmð†ˆl‚Òï “G‹ˆ?îhB€Žp/€ùDö $@Y)²(aï´Üb*§Qµ2h+kˆL­\æÌɸ à bd0HPeÕî_)É•«Ž uP!\„¢@$*p0SÈÉ£IèÂz ¾"PÏ.àéMA¨ñz{Ï0¿*Hoø†–—ðÃÁA¬’¬®$˜ Ô3uhˆäÛðz%OÀŽèXƒß³ÐDH¦¿„X(\ÎÌ#·+ó™VqÿíÐyÒ/ûúžÁ'®úûZ%p?<¨v„L±g¤²oŒÔÁuáËsų¿Sï êÁ½ä,Ý„:2Ö1ïʶ®3Ñ…zWÅ6ò~¤7ãð{ ™Æý’{ †RØ{¦‰9ÁµNú Äã]°Ås%D²îÒÊ3ÃÒØžkñÐ^ú ©Æ]®IÞ6çšð6ó)¯4:ú\æ{˜¨<‚‡ îc‰ªîë#p‡B¸m(›‰]0ßá\ÂL`pê)ûž‹SKòn¨[D Œd½‡Ùp5pœ‰öçPêãÞr –bþn Ø:žD@Ó]ò@*«49¾q²ÁÇ úÓ8Bõâiaš?œîb4´z–ÂóÙð|ÐuZ_Ìsk®[>Ð7fÈiyâÜÓõÆ3¥¬X÷?ÉÖ=:v²Òµ^‹½§¬ÃFh‡{¥di¶×é[À®±ôDÏ!îWeój> ®«sõkÛ$Jj9¹H,ŽŸÖa®ïY2;Ä41#ðê¨À)Ž%€Íâ<½(Ž'tÈól['amD  ±kÓuh643Í`òlÞÍϪ ÍóŒàHÓw;Iﮦ j¡Ü{=Á˜ ŒBì2}Œð2ž¶ÅK’÷Þ, èºIë‚þ[lœ…‰×AS˜t(D bÉm³’Ç$v8> (å ï0w"ªgRÅ7HJnuކªJT ±² i»÷‘·3ù´Y'°|7O„$ñ&Ùfª‹c¼sA'Ž{/ Bôw/VÖØ i:LÃf½£I‹…ââ¶XËñ2C êiYn`Ûâ°'ß-E‰M½üÄNÄÁF#ç&«Ó(ƒ¤yè@B'Dò«ŠÝ1ß[É”¢Å²-_[ê#YR雚‰$Pp‘b,‘€Sæ¹ 'ê)¤m'çè,Z‰•OÑ稾ŠíCŽˆ€ûÛe–¼ŒÙ¹\?Ë÷®Ã{´Ì,šÉr°fÖõƒvHïV1~pçœÉÞ®†„Ö—›\ŽuïÒäMX&fhܘ±}ŒôŠŠ&0ÐÓ¨s8ÈÎb)|pDfÚRF§¬_NKH÷ m”ê&†š#3mk£Tzµ‘‰’=ÓÄÐÐHwt‰öî…õ¡nÃÒĈîr0’J.c»¬5e"àÓH+ ]ÉAىѾÄw¯pÏ•;§Å¸Ê"Tâd}•¥‹ºðÆL0íUK±.¤Iµš»?”+¤-PÌãHcPœôJ6”Wˆ£ŸÅƒÄ1éÀ½ÚÁmqL)õn2¶3fÒÅÕ݆ª¾Ù7üxq*¸#t)|ud7å ¿ÏHðJ%=Bz7/JÄ)[%n±‚æÎ iß®â­ìò×—+ˈüÏ7}]¦NŠù>òº¦u H€óõ HôÓh+øv&Ðà >u\ zA¢;¬ÍìÕTõ.ß :› ³Þ(.>øcá’ìªI~è,‡Öu\å’J2líÔnŽª!²w=ÌY]½!0·44âÉ7¾éV<Ô<U¨¬’)Üã)YëÖPe®*køÜ¢KŒC ÂN)[Ù˜AE Ç?ñ ?¶O®eI@¥ÉC„/q{UŸõ¸NQÓ«Ø#=gSj¹»DZ·žr8Ñ·IC\”qŽ…ßêcï¸&QÌ!*&¸[¡‰v¶)ÎltBòÑF’êß»¯GÀŒ”C[‘9ë]3~\ï°m,ÙàhÊ"/óX6™ññ»ü‘/RyÄ<¡›Ù±Ež• ÝuNð\c˜ÊPØô¶ˆ5¨Ë×DÖmÍï^yTÁ‘CÂà ÛY€0¹>ü¥\Jis­D$‡.åÔà÷a,|Ç\`É`¢¨¼löYy†´íB³¾—ÉAšaÄ‹>­îa†r²z ,8H'1ݘ«©×—<³åêBinyÚ€!²8+»ˆaŠn‚ª Ì®KKÍáÔ{q—’󱇪vJP3ÚŸäÖ^OÁ‡ÕÜeÜ\B\Rjˆ²fÚ:¤Í“ì;!‚µ3›ð =]"=UæçcõLÒÑò4E‡}Y¥/(Á£5FM©A2a³L5U q¹iŽÈôš­¥Ëkv¢¹ Ì*"§Êœ©"W¢ÉyÚ¥|S$Ñäb;÷T RŸ`™dãÜ6WZ4Î-ü°-A¬`–|Kćø×ðÜÎÀdáDl€—ñç¥óTž¢Å>;Å3:ᦋ°a«û(>,äŒW¥ñ YH`§ÉÓwý[5ÂÙ-ú`L¥ñEé8¸ˆ#_Q_¹¯¿.;”¾_wîÉZO¶ç)Zk‡îÅ"^¯3Ð4¹¦êõQX ]Z9σ„qm-nD,M{Žü}JôäÈo/av˜³sÇUéËn7º¬¢Ä“¢ñðñN²­ÙZƒE«".‹….Äh¬;z‰H<1šš1`µ>½¾ºM:#˜XZ»¨#ȨN̶±ÚX•#ÆÑÚ ¸mîeX…k­àq´—Z?uŽÕï°Ž`hökÄÆ„’iù.)Wj³p]8,åÑÁº:B›W’|eBiùIsˆ‚ÈÊЃfeùÀ&0Z­ÇÌ &ÖeÞ«ô¿`¢R͹®7m:˜Šo¾þ¿…ÿ,ü7]Zž±{c×ÛÒ˜.(Zd=€ˆ">íŠ%Ü' ¢ÐÀèÖ™.%÷=«ß("~P ï:Òö¿(Â)ƒ1 `Ur2rt.,—U³z¥3ûOÖhû. ²=]•"2[¹×‹®»>÷Š3ÓÂøÁ ^üxÂ8tsÙ ^éÔåÎ!ƒo˜’ îf"¢œ˜©pþà¬[œeâæ|da|Óg¼r€¬ÇÖýCÈ% Da]÷ßJÆ"뎗%s#m¸Á߻ѧ‰Ö¡¦Sb|D,‰‰T¡²ox鉌Y̽ëò¾"^2³¯<¤.eä½ÊHƒ mäò/ô…1“õ`O‹ü£ºÖò™ÃM~Ìn-Q1ºn^ÐÅDL^‘ð(Q/Rèp²ëLöRÑ”S÷l rkwX%ʆ‡äYÜõ.MV‹B¤Âb ~UÑ ¯àÄàÜC¯%b÷T¬¡gþ­Z‘[J_Õçï6ú¬v¤ôÉ؉ÜVº}ƒêµÐÊOV-^Ó` Hq ÖlÂʵ/»—’¦€¼$I+ÓñäWŽ} ÓQ ñ‚;0T¤ÉÕF½Œvï$~8ZÞ®UõÑí쪡eKÛrEJãRÎã­1gbM¹Ýw%IJE>ªC‘˜3Ù–ŠTñvQFÕŠEmç1ÝI wvŽpã5‰²­Â¼¢×["ä{¥<8/°ÄpIMŠŽc×u—ðŠ«j®É% Œ|¹uŶ7&\È©â#OÉo€V/xå|—o–Ù»Ö P›‡FEçxíƒiø…±Y9“½Êna÷îÁ~v ™Ã™R!Vo!¡_Ó£À‘5,F|HÙ.³à¸—Û䃧l[<±Ü¾„¢ç㓊ËløSdÉüG¢«¾ 59]üjßÏÍe&)k‰1*Ÿa5m4G¬Ýè{.¥I ¬9bC£þ68•UXsûZ?rö’*zYB9á׿åËd™oÔM ’¹ˆÒ¹çH¼{”•ù•{(ø%%¹–•Ýÿ9ºxî‚ JHc.©T͉RåžO^H-:^ãúî³Qžõ…å’ã»øžã‹Ü¹uu t´wÈÁ©=ïÃ1@ $ü:ƒ-!¤Üwm»°Í¯Ý+Ê#§Á÷󧙄\„®çŠ„}y¸ˆZÚp‡‡Ø­Ô%÷DüÕ|™U—ÛˆÁn57»wŽˆP³qT#ßYD…8\I¯û8·ÑŒï¹,ò#bõ]SœÍ&…KQÏ{fµfšƒ\ö/,â¡ÆÞíRåB%Ácƒ[ò%$Ãh²íC#†<¢ÜXÔ‹H¦ŸÝ>ù#üû³Ölæendstream endobj 980 0 obj 5361 endobj 984 0 obj <> stream xœÍ<ÙŽÇ‘~ð#ûâ÷ac¬Ãòòš’F`KÀ9¼`r†œ!EÒ_¿‘WdUV÷¢eC ÙÊÊ#22îˆÌW1ÉÀÿò¿_œÜûVj½yrs"6_ÁŸ''¯N$uÙ侨|v†Ý6MQD¹9{|’&¯6.˜IªÍÙ‹“¿oåÎnü™vjòÞë­¥ÿÙ!&¥ýöl·×“Rèí—»½œŒ±^mÿ²Ó“sÆÙíýÖøõn¯¶ØE1¤5ôpÛ?ÂïµÛSBŒÇÈ)Æ`bí©ãöw¥ñ»²˜¶i2£ Ëö‡ÉlØþ :dÀ´ 0& S aû9ác”Ûow{1…¨¢1¼3ƒ•º%¸¢æQÛ¯à‹r“ŠzÂÏ0 ill¦pYèªó.½óe—!è„™Öý§³?Ó1~>ÆÊÉ8¢³‹|,þÀi`ï}þº×bò2ÆÔémCó³r|ÏÛ½ŽzR"lÏa¢7»½…Õ àü5€‚Sr{^l€Þàõkë”ׯH¥¨ÃóÅJïw{£"l^²®×Ð8im¢Ú>êÆ·A¡&ë }¸l^à"šÔÛkÍ'œõ¾AÄZCÝŒw¦ÿ¡&)q ü”Dz)¥ GŽ{Ù&^컳ÕòOïø÷;`ãç&$ûÌædÃ+°W;@äptia+bY{²‰ß´Ö<•ò…:„\A9vÉèñÒeœAï„'§`µÆáóE]‹8%ãn/5Œ*¡°œ„gĘ—r¢žipÙI4P(ˆ76î ¥”ƒÙjoX#ð2-8HTc¤@€0ᘑçàTøL*x€Ýίã¶Ov¤o=Ìyd…<)j +@ÁŒo=ÆSB#— #Êeƒ¾»8¹<Þû ¦^D9:žnÁ(H %Öó®lOW$àˆsa\…êE}SûÌž¸Áüp¾¸eœ7D˜­–bD°îã‘7M’Ø \ò>É%íÁ^Éûy±Ô\ˆŸ»Å8ˆl;W4+'×sâ)­ìP¦úÉÒ ›À·\D¿Yæ@tƒ]Ó™(QÉ”‰9!«a]ùd”œFu6ÐXT­„süe&ÞÌåˆöÞâw‰úaìš1;å»<©^•Á¸hÎŒñƒúâS€b©·TzCZòŠáÒ÷,«†éî™×=q\'ùŒ¶|oí[“šx:_ž|sòj£Á#%ö6Z‹°±tvè¥vzrïô/›××oÜûa#Oîý ÿúìþçðÏé›ßœ|yºùfÝwïI øîÌípÉfÿýáÈ09ŠÜõ­€GGó_¿Kóó­ŒI«ìän>8éVÝžD„“;³¿´ô­“)f–¡ƒæÜÒôKUcg¥¹F Íi’ÈWöÔ;R•¢‰ß)Û¢—˜&Ï.G\õ–Y§åÒ®œã.³ ^V$?뱜Z˜ÏêÎØiØ |–ó¦.ѕ⒈Œ[ÖìÁÒ‘ÁÜ5 ãJ†,ö³“ÙÏGÓ‹—.|aAKîì\ #W;ØûHuÎîÈÅY¥SøŽ^ò˜NÓž2™ÐBû ‰ƒ`6®/€c­\Ê}!Iì“3,׉3o}•Ž'#ºc^ÊÈŸsGï¸#'{ìÁäVàŠž –vžÍÔL¦ fÍ,kÔT‚\jHÿ‹°Tq;§Ü;.Kÿ±'\t5Á5¦´Q#âïbÄwšãÓ¬*H¯®¹T*¤€Ë"þ0 ™1DZiŒÖ“mªS#yýPÒO³(Á¬ã5bŒ.%ç¾ïlr°Û¼¡/6€ÈÅí÷µ­xÿÆtüÖœøÃ±ˆÙG n@¼Ý‘ã‹VÐ ;djÅFƒe\!Ñ‚÷IH"Á°Ê£y©[錜CúC›„aZE pÕq Wua4í²iר‘:ê’9°£Ä&xR…M2Å?óHuB‡ã{|Çe„¸JûF²}˜=x¹êêWØYØ`i¨¥N2Ç<\ñPÇÛæ”÷\À úaêå7•̾.JÇÃ_5½.éS‰®,Ð÷Ó&0•Ä–ú9S+:£“[.ΔÃLZÙ8“ø 5Ƥþ=–ì0)ŤØw¸,†ŽÛà*¤°ÑƒÖ±Õ)')—^ <`¼§}®{æ8'¡ÇWcü8p ÿÖPdpÌ#‰!¨™Øư†"ÁÓËG‚ÎÙ!~fˆJ– ³v<ÛH¯ã Â<ˆÞ–ѶÔU/´¦ì @BͧÐFiXf“„°žOî4•ÁeTѼÍüj"ç=ê¸äˆw¤2ÎÌN#[EY[Qh_KJ×èó†™SÔpRý)0Ý9ç°¹¤CbŽš‡ÇÙ"J—3J[˹°(á§sa˜˜q3Ì)Ÿ¥¯v9´q~ÜVúï„NÆP ©âbC}6Ë!Õ…Ü¥Köv…_Æì,μÐ~¸ñ ؃y”:%ûHj:5OD²]ÎåYÔZÎå‰gýK´¡ÞŽ]š.•Ù¢ÅÜ ;%>á­·Á–©Àbq(K±ò쑚èçæó"mO!g,](9bÍ}ÄA2F;Zâ–L£•2ÍX-­¸W>Gƒqi¿¦l2d¦ó¾°2¥Ë'&¸bj)C:¹36ÁIG–Y5 Ur’o4H|ã&§«¢9D@‹\ˆ€1x-ÂróÁÞD¸eŒÓ”ÑÀ×A„[ TŠ02¦O¡X¾ð@Ã0ìw|°HMì bö˜¤PB—ú—C) ×R§;1y«d0<5‘‚ùØúI^“ Ù{͆EÕþžJvŠâ”=pO¹Ì¸Ì…`~`˜]¸®¼gãóO/»üBš$‘^@N–$Æò¤˜­•È ÏùdŸ×ŽOt§aß'7ÚŽZšc5»½}*‚2Ñîc2³Lò½\\6û™EèuA'SjbmC™V;É*<¥ 7u•ù¥©ÑŽE&»398Ëdc–¤ô-LrBÞº”)‚Üçoe aÏœ{ìêÂñÖ¾hàn2š;Õ‰<†¢CuIPh©(ÙÞU:â©èÞeãÞwüW"ŽY¡º±GZ¨´`ìñõºèŠíÒ}^hŸpÒ[Å,>¸(VYÚ˵FÅÍ­] µr´XÀ}æù¸ZÕëhVÊÔi¹d^ªþa™=ô³Bs†ýôÕsåØgŠuiû”c©µ3ž›¿Ãéß ¿b£‹Š0ª®q¹P6UƒØæÒ'IÅ ?þ¸«²X&:²If›aÛdiÌÊdó€dǺT“‚N"]ªM°ºËr9•ÒJœÔ (S·ý ‘´@ÑX]+"É=VêÛ{D EÏXrQÆJ’úB#7c” ¡v¸ýÿŠ€ÚI®Ü^¸õ²¡±O4H/ýÌ~Lât…•"˜¢2Bs\wIb F3Ö(ì`» ΋ÈEf‹_èjX™.:Î,2 £½;¹…)ž ‹ëO©»Ô©jOÍaµlñ'lœYq+»0ÎÂÚÊà¢æ©F˜¸”ùã•€”)8¾ŽËî%ƒGRÚÚENùÑ»\ª5RL°{,„:hçöêençâd 97iR"–Mß ÔÔIsŽ.f×`ÓÎXО5¶1ùƒí‘QƼ-y=¢š¾¹%¡²9/)€€o!èóÑd>(¤Ð3€l^·¾O;øËÏßψ)­¿'÷¼èÞ_™˜Ž‹ FL ŒäIP>eÉÓÏkãûÆýÇèéñhùëÝ€H_7Z~>¯­ôzD™×&Šk3ʦ(€–AHC¼ yM9Ï•¦>ŽNq¤‰zÿæW&ŽûuÈ×#Ió×!q\Žd÷ ~d…8žñs¶F‹Î~Uߌ„ÉõèÄ›b™:ÌVÑbÿqüF d*k£h=Em¼Ûô„³‘˜¿½ñ®ÍVXö]›æX×—£Í¾ëVdèknüyĈw›è=f 3O.»EÛ'mÎoìÝ ©ìÁ‚JRpž›ÅùŸ²l`¸§žŠ¬®×cŽgž|Ë+s46¥«Çµ´„B´ÁX€¼õìS@C¨¯óM@8îÊ«-ª–²tée¤énQàÕ ¦²‡âa´QEÞóˆX‚YýI_øMåèÖ#­òÈŸùŠÂâic¡¼ËŒ¦¸"‘®)/~¾ŒRç½öšæÿ–I‘r[Oʲç¾ôœEÝFÑâÅÿ–•Û¤ ÃW†5¹‹RY½zõ¢Þ™½MÉ®;P8¨Í×HG¬A•^mZ}["½9P¥GµsVÆj€¡Eö˜G¾@,¢ýKKïVò’å®±(ê +Þ£­uÿ‚+(ø&CÙ¦¢Ø6!è|6úTç¬ø)áÀM¥2Ée?IW«Ëê ¾zï8‹×ê¬è†µvŒeº‚ºì§¾+îâ-аò˜_fDÃÑ'ùúéN¡SVž‘0xù‰T páé3ªÅEÁâÄ ´î-ÜK¶ uêíüÞ[Î/Pgùé”+K?ò¸Äe VÛã¥ù¬ï qË0Š;E†Øi¶@Öp:èBf¶^k_牗­•%VWcЬO)îW]Ê £å¬Sªs2v¹…|æ¶Þ]"ìô*¦;X—nõ Eß,CÙÝ@*œ”%ôü!§îGºú‹,¬+í~¹uEÔÒ§ƒ~©u¥A…£Ñ³DÔ K®äëøá ’Ñà ‘#mª‘LÈ%j?¡·üê|È€àࢻâÓЋlbQ‹dª4>ÆPïÂp5¼8¨ ž.ÄnÏ"}¡Ù°ì%_@*T^2ìêÀÕ€(9@×Ú•¿r"ƒçO²¶!4¬–¨U¹<~jd.—[­'¯Û2œÆ×Ý•^a• ú¼"§”3!’ 9¤®C3±ð×ü(g×iù%E‘a‰¸Ž™Õ@¶\ò*”ðú@rã³XƒÃJ¡Áð©µê"eɯ>ö@Fòd$8´U×=b*Ç–årõã:VŽAÎÕN*{vS­@¨ÇD®Æ±'¸Òœ®]ÎÁúòµc‚‹©3¬²‘pÙ)»—x»ZΙÂZ«åœ]pJØéµËúý¦ìsü"×"ß/(Í–y)OåHke¶©¦¨†Öcl3òXܲ)ãb øÛ<ŒØE#2Fï vw¸=ž-vJ Ä” A¸RZ‰2Ò‚]ßyñ3%ËÀ,6+á\Ú ¶M;¾ÑY·„*1¿Ñ™ÞpŸÈ`—PR™HïÉåØÝlòös^4i«Ž®.Î"-(ëYbè tÌ$.`ÉŸv£G›¾9ù?îîendstream endobj 985 0 obj 5412 endobj 989 0 obj <> stream xœÍ\Y·~Wü#Ƀ¦m‡g Àgì@^'ÒÚP` ÈX²WJ´;ºV²þ}ªŠW‘MNÏjWHlȱÙ<Šu|u°_‰^ ü×ÿÿÑù­?Þ“Z½º%Žþ În½¸%©Ë‘ÿߣó£OO©ÛMý,fytúË-7€<ÕÑ0™^ª£Óó[?ldg7þ }xú7|mÙkóÜÛÞ<} ½?ëŽu?Žó,7_u²ŸçÉÌ›O:µù{w,{cì¨6§©Ï®U›isZå ÃŽ4¥€?=öd;֢ᷣžÛÐ$…Þ<ò, bp9ÐjFoFÆ>þ¹\÷GapµùO§i÷2­ÇmÑÂtif¤êq ë±ÔÐ*”£îǘ ½n©(OÓ3Ò2þ/wP ½Ò›…¦ÂTIÃ_nÇŽ#‹Ì=n~M‹ùÝ"ãÕ×mA*ÉVê…Eáú¹(‡çKaAeÐWdXm¦.‹éió6iÕ8›æ 7¯A›Un{¾Ø²™™$Ÿãr†ažèÐA…ÊIsNy‡œbq÷œ‡pösëDj%êS0?v¸{°fÂÒžƒXÚL*ðtœõ×4GdÇlj‰yQ\Œ[ŸðŽ7$î¨&% “ÍlJZ‡•@&ØyÂ&q¢gñ%?;Ðq!VDZ*;OŽÂ5V;s¬\Iö€É]”¦?àr‘™’§Û¡)p6˜üaxÎŽ £àÜ`TÝ ¹_µ£8<Š¿âº<Ó›yă6b„ÁǦ´á¤5%ÆaÞ|‡ë`CΗ‚öú¦³¦‡YX0nèíw6­Ð|·Æv %&›ÌmGÀް­âè,‡†fDh8!Aʰd›€U¿ëTýe#&|¹4xÈ3\Ÿ½í˜RµËU";7ÔyÀšdI¶N*Ã#<áSw‰-JÛÁ9li1‚HÅ\r–½ƒ°ì¦ q×IŽã× ø$°+ãÌ*熱(V¿§:Öà9gçÙÕ3·gW=ãàö ~¥MæZ¹Í®ßwŠ;B÷ÐŒàõÈ¿¡ê|Ç0‡ç7kü6oc%:VC…ßœÒM«…Ùw” o·Ëá‰8®·°¸h©ûÄéj˜{V¸viÐ ÆóÏ‚jJ‚ßê>=Ü“øü~zß9ªðÞ|ë]A¯Èè'¸ QS 4¯ªÇ ü Z5Šuæ ;…%5h/ SáyÿiiEæ ˜ õÜý4îg °|Ž6²¹ÆŸè»ÍÅ‚§»]æŠ9`ƒ‰Æÿ´#ßAªèÁãB@5à:fMÊ)`?/©î Nˆ'ë NÞ;¢Ž42v»‹ÝÜ™°2àÂæª:iÏsMÊÈž°oÙQ‚ÐèГ% “ é.‡ìçÖyŽhŸìP•QÀ“FÏ¥Žw;’¶.{WtQƒŠe>…ã⹦‚.u&5¸èîÍy“B%ž¥áÜ>8E¬„µ¤ý¹:wDÈÕyP*8§–WÒîzÀõ™ÚIÛ‘N ˜dæ$ ,êv&ß&ô~‚SÈÒ+C 3)D6)nã5N< ¹ÉØLhDÉ!õJL­Â0í ”„ ,½uÜ¡_ý<¹-™©—R½¯å àzŠÜ¿0a³³'¸y´­&ÒêOdy¾/T?“˜(’ŒÀAI0ï2v$b“I«´'s=œ V›ÈÂcئdÑÍj $522?‚="dz ÂâsæQÝ85–ö³ßCŸÐV½Ò¥WŽ»dZJ®¿&¹†ESŸDs[ªy?®Ì[‰ÁêAô‡_Ô U¦NmàzL¬‰^ôˆQËéÜéÑ–…°Ó8Úòñ¥øxmÍ»lŽËý®‘ÍÁ®z…(Â1%åHêˆ(AÃfǪ̈æ˜"Áé3OÄËezà§Ä¾‹p²ÿô#Sn»5ö©[ˆ1˰åÖ„¢ÐÈ!&-ã¯n:ºBp‚Ì]m½Yš)¾ëVÊJ8P*7K­ŒÞîëJ)'“‚7ŒÛ3ÞHµõŠPÎU¥ÉlCVvíËG¯7ky2%îwTPit¥hf#>Bevì«V}$^±a*3 ,…Hp©P"æÞ× þ°1k-DGîéê†3&äèZyÓÆÄ'¦½KJgP½„\)UcSG·Ú”É4Æñ,¨> \j.Hm_ãCÆO}¡D%=íÓ³¿È—€©,äk)Ý]×äžP|¦ÕÍ'ù®ë#E0ècåOEU 'Eнfz²ß//.ñ>ia7"C>eòÃjž)¶ÂeåtK› ý™ì5¹¸<+XFŠIÕÜ ®.9¸Zðº“õdõÁ«Eñ¤¯K#€šÿÌ'šrs%‡âO¾ÉÝãÝ·{‰ÂŽ7‡¤ÚíÆv'çö3ϰeX),Z`š6V„úhzJ¿ù!ï{Gi‹B¹¬b“:3 9þçE<žR¹i`^-Õ”ÙRIfq »àÝàùU¿-Zä®`½¸¶‘ÕFAÖ’•VQñ "~…¤¶#GåT&"æü¶ 1“1W÷BcðT•áÜ_áHc*ù¤…mŽkËÅ‘'8ñЬ?äi|%O=´µó¬_ñ¹sŒ‡a-Ûà¯'‘©~mƒˆí‹6k&ˆ»¹4·!ÕA&/zYŸŸ)ê1Kô/ãéÍáøójñ¤Áçìb…ÜD=L¿p?—±(ÊUê±|ò惘´ÓšPøÜWÝ\"±*9I*j•rþ :X0±Ï&P"Ìʶw6M}î¸ûlO,@—fl¨ŠvqÈ%-KaÁ®°c)&Cê ã{xóµZý£öÊït%ëPò[) gám]äܨŽGéò³0•ZE%¡Pd±BÈ&€®ñ¡8ŠHäH-·¥9Ë'm¼i$›Ìã/ ½§k%„èÚ³¸h5 ².Z‚÷‘¨Ü'Û‚ʃU>ª%»X¼³4²ôÑ©=á…¢Lª¸×• TÕ˜¡_qB­C¬0ÈT~˳à‡†yæiš›œ­SHEvúìÞNÆ¿y}[@´*œë¦©êØïû˜ÅV ¶é¶;ûõï‰äˆ%ï¾b ×µžLÌVÜà <¸èJ³ÏUèÁ©°åQ¯êešu[D&C艦Çàã·‘ø0®ü^ÐJW®Ò¶†zœ’‚VJ¶¥fH%U!Uv¬|àVñ£MÍ´¼r‡bÍAûñÔ:$ŽÅîÐìcñ)WYÜÙ¸*œÊeî"dý2òeÕüdîàEž}a4g’æU“Rõý+52µk; :ø fuð·öµÀ¥:©^ðõ´.”rˆ˜Y›NgŒlrñcò€M± â±N\Oû{sé’ÿÚÅ ç|Mø–ªˆ&bqb¶Q±»o0ÌÇ?ébÇ>µ–:q—g1Š ÖypÚ[[X›Yòw-U¦â¡šC?E¸ˆPò¸›ª|8¨•$oÝ}@3¹ë r*‚tÚ[ÓLᦪ#wOïî­Óßg_ç¸JEÓdTEï€8¼º)ñ\«º‰J—~ˆu犘Ì4Ö;NUIhTé0cõ0ÙØ×ñõ'ix¿X oêøüezþ8=ÿ*>ÿ<=ÿ.=ÿ%>ߥçÏøCã.6¾­‘â"þ¢Ë¤WWÿ¼¶ú4æyjÜÖz¾C:MtOe›Z_.~º«î« ÀtóÌ>ØÊ*»ŽÃÓ\T¯Ïà< áXa~üÔ wèæú9Ú6ô±J?ÕŽçMFjßxÇ)œçê/SÏ×éP.ùœÕƒgþ¥i\=é/ãsV·÷mlü65Þ÷Sã1_“ÿõ:cÆ»lz'k#_ôÎ3•’[Åø„Ó„mŸ:ô½(Ù‡ÆÌÑÒMjDÔ›ïñ?ôë¤se®–TËž ·cbÆÏk¾ñçÔx±Ÿ{v|ö½jbË:¬óIldçô*­ó‹øüAz~ORã'±ñ›Ôø…_Ó¼ù8ª‹!ƦngÃÏï?°Ö“lúðó~ê{»äšé¦5Ï¡¼s'ñŽŠ¯Y¼†}ïV¹®ÔCnUΆ þsBÁO#ì!t–3"³!?nâ£TÄ?²çW\DLi·„¥19Ó¬Õ³ü%ÏÕ Š11(CáoÓLÙ†ÃK¬ë/¡5CEÙª‰å¬íEÍœ1xs^…Bù^­æLN%Š~TÛbr4.³0 yÝŸ“MKü$Zû€@F×£ƒhn¿ÚÙxŽ› ñ* -’™-«/(>`Pûÿ\p«D^ãŒW5ÎÈô8~Õå_œ„¯\ìAíÀìSq¯þhe—Q -.âWå³Ï»¥›=ÌDš¦&Ô^?… ªBíâUfèuùíë§8ú8ÔÞÐŒ)ªð´vz¯r‚x͸¦oÎKH/1|»&û¿ÖìÆ®¶‘ä5WÑÆí`ß1‹Uú’…_V.*CËYo»6B~²ñ@]„ …–Öë„6#fEß¿Lñ–•Ã`ªpE0s5öÅé­À¿ÿ¬ÔQhendstream endobj 990 0 obj 6099 endobj 994 0 obj <> stream xœ½\YoÇ~'ü#çA»†v<}N·‚<äpœ‰ƒØ4ò È’”HÁâaRÔñïSÕWU÷ô슔d´v{ú¬ª¯ŽÞªùõpÄáˆÿ¥O.¾ýQ(uxv{0~g¿ˆÐå0ýsrqø§#ìæ°ið£‡G/ââp’‡ÖéAÈ㋃§+±6«þ†µ¦iR+¾lÜ8RM«¿¯7bpÎ{³ú×Z ÖjkV\+3Œ#|úÚ&áµ[}·Þ(-mÔê§õÆ Zkó×ÚLrõgè0LNŒju?J¡ùüÿÆV)¥µ«ÖòùÑ?ÂY?„6b°Îqtšö®àoZ›Ü[ =(m%öÞ¤î5â&}%‡qÒ£†s‡OÚÂÕ0ŠÑY8þF8°5f¤pzu­u“ŸV[è*àô:+Ã_ÀÎ,å=ž]¤öÐ “Z8ÍI8㤀^o`Œ§fõ*,)¤_]•y.ã`au÷ôåÿ<8úæ)pa4>L«·ë͈¤b‚‰'oàù ”…“¾Åœ³°é;âÍH÷çpƒfõ=y§€ƒi$†‘p O…”°_;•x™¦–"ÌW¿¤ÙÚ6;Z 0g‚½;[0ƒ÷eÇÚKX—“J§…ñS\jR*,ÅV8ƒ¯wíc7œÓÚA¡o‘ÆLVòÞÇñã$ï°{ýr¤H‹pø __âÑAæmjc­º@>[;Yºœ­‘ÝÒ/u–m¤¼¶@b¾f¾c;\ÈFÙ´ñQ¬ÞG™P“·içfô™ÄÒº0ÛIîM=ʧH¹ Vªèt:M'ÂkV×|i0ë]M˜†ùù@ÛD*l6BÁiF©‘ã&C=ó¢ˆ$ g¡ñK¤1rxÊKH”ÿaT: #Ió9IÂÛ8ØŽåÊh'¡ŽÆgIÌîz‡÷l[t”"¼·8Z¨:Ÿ­Šä1­áÀvFž³ 1Øœž­që@yï’^¨œ›òlº(D ÄÄØ ‰Œ PÀ\_µçÒ¨;‚àÃe³à_EŽ`jùFá Z{.áxæ†E=øÆ)´ ’6lt§$ žÿ·¤kƒÉ9ð$Q¤Ñ“ȇö0ûYQŽø-QTN"kaPÓpÁúÌ”„!$ ¹W„L$`€Œñ.Ò‘YÓËZ”%è mf’$ƒÙ j¥â?“·«°¬µàÑÝ l™5K'm’wKhlncÀÛà­ˆ]0 RB²ƒƒ`ß’o‘ÍKRÓµI‰7Þ9&KÑ&Fs “OƒÍ—ƒn@Žƒ]dà<é°¬yœ…Ñ( Ì¿Sæ}bºvÕ;Ø%;Øpm°ŽB|½B®5ÚF³Œ$­Þ ,øüšpsG­Hna†‚'б“¹ÏJÑ%I+#抽­J¢¤×Aªg@&t dÂzvõ\)zÚ?ª øÞ‘«\}MÂæ¤jô£ô2ÏË6ÀL'sz}è§8‰öŠÃV Zµ!½G¤†kué]°VLL‘ç¥÷N­Q{ZeÚ¯¸êbûÌ©hiÑc$áÅeÙ£V÷ AUPØ  Ì™s"ã«Bi<’Ð÷Ô8È·ÑÕøˆdË*·µ©„q)¸³v A䀩ã1± µDƒžÓ–eÁÐa+m<žQx%i8àq ±DÈÚ@QLrN#\&íbä¼gæ!z“ÞáWW¾Û^T#2µnê#ØÄ³›§¯ÉÿK­\-¨JEÙ&2L¦ÀºJÇEû®gz¶ê,n2ÅRhJ=²ŒmDˆË1ùÊêÞ`”4í¡fÞHv…ìù‹Èv”¾©X§³äÖ»ä6iŠdN{2—6¤ŠÚ­E–A™Æ0û ¾= òõÇ5ɘš˜Ö´rô½pˆ9…~ó_êg‡Î®•¾ßÀ ’ˆUG=é¼I F×;ãTx>h‘&ü£úgbÃT?á ƒ0P (“d›®°Q‡«„Oví´phœ–")Žh+·¦¾K¨ìÊý ›„-„aù* t% —Ñ„åZé½1J&ÂãtC"gK!%E¼ñz”nà # #·a© gOÊgò^påp"Ä Ë^Ȉ`Ý—Nàž^Tÿ‰À•V¯é‹CH‚™"`ÞéÑeÒ˜&`òüFïœ|´²q?w.í2"#’§¶­Žr²RøÁ…ìE8I7^è ‘\·*%dñ>@Æ[±¹.GÿI…2±ÅHøpñÖ<©daï…‡înÂ)EP-¸ˆþ†óIÓ×}¦19Ûûbên 2Ó·óð,o–=†ŽLÚU²ã3 z:aé~qno¥¯å-ó}·z»V2³`¤sÆ£ ÉztÜL U¢XA[™W<怱½Ëĩ͹E8ü˜œ¨dŒej{Hª¨8ÊáÊ/œÝÈÔÉ\Ò¥LÕ¥j/ªAZö¹’qV ŸjÎîWñAví¾=|~1 ru?²]7±Q\; #†»Å/À«¨J ,º ÍØUB{ŠÉvìuŒEB`*$*«ìM)Øõ°œÆ ªUµ—³Q:›‡ÇìvŒÝq¡3”iT"¨¹IÊüÛŸÇv’ܫڅЮ—p*ì“/’¿j£v+„Ê>ÿr†«¢FÏ?Ï䟾qü¦·‘0AD„9Ý€#ï÷ [çÛ•PÕ¯{°Ô!hÁ‰·–ÁÌ}çÙÄ('è}ÔüºÞá²fõ-ù8 .$`UøŸÁÿ…¯²´ÉÒ=¤É†{Aj|‚GôÐF—sc·'5>G?=†  Á¨ñF8Ü@Æç×4èEiD G½XлFED“dKãûÞòuOpláK”˜øü=__P#ÐÙ€,x7òÆçô|KÏøI·ÖA$òZ î ÒÏôV`UÙJâÜ›ÂÍÐå,“Óíe"‘ˆ—”±ñ¼"fظWlÐ)=?¥ç—åù=¿(Ç=ÝôqN@óIi¸ª¹k‘Kj¼ÅY\ 9ÄÚ‰#’½ "l+F扽è2ÜR+†¼‘«Õ¸ËŠ:i\PÙcú °ç<01`ñmAe‘`÷YÉ›¡tÓ#ñ»ÒxKøa$”ÕQÏjs(½â“VDyý0‘\ÂRj<«…•$Ç*’W è–Ê­õZŒÈ5Ä| [D1`[|È’gKcžï†wÏ–¨¶f—© yÙSA¦‚†Ü¬aQ*rúLÖáüŠªßÙp”Ž(ò“,ˆ¥Ý=ÇÙÞßO¯7BßS,’^îªðÛ=²ü†3b®ö)_ÚÝë¹ÕðªÏàÿiðz˜÷´fîX«Í¬ÀjíÑQZ·•̃€˜ùïïÙªÄ훾.#ÓC†ò®¢Ø>›ØeyAiñ‚vqúÊr]ö@òÔÿÇ+Ä%߀1lÚîôw½sž“õbó×þRæèPZ³’:ZdG€ù6¹¤$¢þQì¨]uòšÎ\ ORü²'ÅÄ\æk>œ;éÐ]>ýÒ’JBÛØmZ ˆb?›„Sqw¯Ÿ:Ž'Þ‡ 炪·æã)æõgo|Ûšòãåh“ÉîFVŸtõŠ+»¨×%ûÙtK2× ÷–â}6ìM#•ı½„ËwmYo”°(DZ@*§bÖiOG¼ïQòEÝÈ´r•³†z¡?à ÃçÔß¿þž®vE5i0Þ]±jî…Ü•ØúœZ«‹ï9i¦‘?Þ;&7Ž|I@,ðÂr»óW te97ëŸó $ KÚÁ¯©þÔ·!Góø(9k]øƒæÔ¢ë*IÃ"švêÿä˜5;D¯×u4µ'1Ÿw—ûtÜ#Y©ìGwC–‹Þê÷6£}j’b…Íí6ÍtÓ[è¬×xY‰SfòëŠãî¼mH¼¹)À¿ÍœŒ}Nùƒ|—Ú»sÚuº.ÔkÖì¹õ™ÓézóÑn~׿øÌ…€ú( ûÛ^/B,³g=¶f¶ÐÏFAëÒÝÓE¦.“öeSÆ.¹"Ó”°ïAa‡îìüKÊðÞ3¿¡dl™•õm0%-føý¶¨Ãÿ®5þÞ«Ýb~¬4ÓXaå_±s²Æð$#zþýÚ\^JmBnH·œ+-ÇÒ¤¡4±¼òö~Þ7¾ÍX¸_™]LP`Y@(,vÄ$T–(ΨÒJÈcìª}¨ÉØSÜA .uN žÛšV¸‡‰÷Yóžõïû9%ãªÎóÚ¦¼M÷úu~˜4j l 335KbD¯.5 åM5éwÝT$´Ó¸œÊ¡c¡ÓÞTÌNÉ•ŸšÉ$ *LJ¬,£Ð¤Î¤Q*æí ºRf¨“‘¢˜³DedHÓ¬ŠTrÞ ï§Åº-$+ñt(L3«¿­åê/ÐRbýêçµ@] }©ÑuZw®…Z¬\H9{}±È"ˆn‰ùì,õ¼®‘§¬(ô¿<ÑhØR_UèÇS¦>ºæ..äš«¦(Pçú•˜ z´ƒ¥YvsœæE’g÷¡ ‘Ч(]­K®ü¾Z$†–¾óÐS=¥Ñ§|ÁY‚ŽN bÎus¬(0e¾´NrUWºPDQjöåº1¤±’ˆZ ëÏkY2Ø)5^M&è›JVcý××kžÑƲ÷ é¼Ì‡$†™‰§¹#–ü3Ù|žÛ«¥N¦—àßã==6!ƒ €[æü:Œ*Ü x$Œ5C#„Áåªkì\tϼ(Rv hi‰,l±µ.OlÙW¬zÏ;¬öÅÁ’)–ÍšÊl¤àù~¯çŸRiP¤W}ûwI²œ+ȼFïÛÌí ¾~¦ØçyóuýCÊÚg’<›ªcóY±Γ3Ï'Ûv^nþl]¸ ٪ٲP pÞÙ+2ÕÙ`¼>Á¹˜e›;X[.™ 8«¨-îÂO¡m¯äJ±úÝyêëBºvÔôлhúêÅaÏjZä´é-q½a’;’Åâ£×õA‚˜hËgn ÃÏê´íÆ6> stream xœ½\[sÅ~Wò#TŃ÷gÙ¹ÏP•¤œq(U àY²eƒ/Ø–±Šÿžî¹vïΞs$œ@Y^ïε§/__FϧQOøþûüÉÑG_ ¥Ž/_MÇ…?—GÏDlrœÿ:rüç“ØÌë1LAŸ<8Jˆc'­×£Ç'O޾ÄÆ þø¹{ò7ìæ'Ö-„ÑXèyr­ÿ²ÙªÑ¹ÄðùFŒ!x†Û9|µÙŠQkãäpÒÚ|šÞ*퇯á­0¬‹SNðg„¯RO£Ô´áiw9fûd£Gï¶ôÃ'Ð\šQL~ølƒuÃøÝ¥Äðåf+±½Òr„™â@¸ô¿Ccksñ£ÂáÄðÍfkàÁ ?ü{#Çi2RÄ' žÞž§™©¦ô±Ð£ÒV"Õ¶™l[5žõŽäô¤aûñ 60Âì¬Ù–*”€UC7˜Ñëá ,Ù‹Ñ$—÷#ð†^l¶Ì.µ²¹“>…ýÃ%Pö% ª%PÖàÑOJ*7<«£æ”„m>¬a¨Ïð<¼0Ê⪥ÐÃã´~­‡+èn€vï¬åãä9….|ÆÙ%UðÇ'_¼_Í‹I-s ´ïù¨t0¹ðø\¶å†sàX—”@ ƒdP. ÏÄþÔzçG;YØ•Ä9Õð[Ã+h ”ž†W­ýKœÍï4ì¸L[6P:Èa Wj~Ì-•8‰ò£6AåNXñ¼>=*ÿ¾ÍÓÚ]à¦<®Ec8«ã6®`.ïRÃÃ^ÇÕÖu¾¶lð& ¶-€A +R%н?m­ggØgœâ­Å³ ²š€DU»¬léÔÃÏ£G ¢ÏkÌs¼j²ŠmÀC‰3?À¾n¡Ì´˜pû‰ö*Ÿ™6ž·7£„9~jæí£‡7ÈÑREFDb91¢µ†ŒÍ"çt•Ræc”¤ÌÇ "H™m&ÍV( I& Uºæõ‰§/7†°à‡¨jõiE-讇é@<'5ã`<Œo‰¾Ï$§ V—ñ´‰Ìå—7;¡JДGÚ@¯aJFªççHK <×ÉìÈ’3wÊB9ùA ‡'Štdº`@Åéß"«þD%‰ÛjšX½ÀÍ X.íÞ•:œ‚³™ XÆÂ¸I@yÊ"ù~¯p4Ùmåäœ\JM„ÌœeÃY"Šú‘–5YtCMKÒ uYi–&m@²¡Ú[“Î÷*Û•-W®4 Q:+ÎÌÉÁ™Ÿ¨kÔ䘪*˜©³œ[“qQ’Áò®ì”Ní²2åçÀ0ZáAR‹ô°IÅýJÀ.RÀêJp‚¹@N‡ÆQÏÕü§fêCI–e¯Ph‡2â$*™ÿYæ<ØÞð‚13È0`"gñ¨Kû}¦+±9èÉÂåŒ7T®oØJ¾x$ê9SUZŸ––O"*>Y`‹p€㱨ëÌt¸8€ncf¸å‘fƒ$©ÙGh©“nmì7c$¢>ɪ²ÅÕÁÍy¦h}g÷°5(–ÈÖKàr{}àkÀ\ŠN…*HEÈ×RË©g]ôÈ ÿP’¡„¸•àí*8ÒÆ5ôDhM“ÃLÔ): xò€s0¡ðåª|%ªjJ¢ªyÈJf2ÌLCjäLO«‚žÐ2 Q)ÜWÖç €”xüäÌ©:—:i:QâœÊSñxÞVgÜ~1e]ȵµA Ÿ¤»jêÜÑè4ÎùTІ†3s 4¦f‚ºÅÁø¨@ÑÊ̬´¦WQ‡L #¾n^[RÈ”4ª ü%E¦_ÊK0¼‚ŠPv« óUó‡3Xà87×øV†x“㶦«’ ); ‰F޽7’NZF´(GDµ¢yâ8Ýf¬¥ÀõCôúl¿ï‚ K%Ý-a†)¨Š³ºÌÀô½’è{V?@"êëx“KwW!’¡ Á”Ýï Ú̽ ´NeUÚõ1PSêð!ÉV"锂kD†ª‡½-‚Àî%·;õÿSÛ3 G àÆ:X„< 'Ýæƒ/tœqæ¤Ã)J‹qêD‘¸ÏLÚp—åõÍ®FðÈ€qßì>xSøÜ¿³‹ÓÌeOí2®ì8Ê #A‡"Dl‡ 6a¡O@O J/ÃIïgZ;³<»"õ¦Yƒä•–Ýi.©?½Ú¸Ùžsê/<žÁ0Ü?7&]×…8«Èð<°ñŒËG{mªã,,´#*ú6*ÔiŠ>#=~íiLcitÀ¨ÅÎÕé·£WÅE¦ïëeXƒ·Ú4#ñ5ê@&7¡–Cæ"à@4]÷h1飴²Üs,æv\ÉcMÙvx é¶ŸãÙÒónNŽ3ß›w=eDs‡à–l4 ] `XL‡„ï.Ú÷â QŽ&æ3 ‚Ž8F£¨ åú¶eià™„%èsErq»ÐX6…©¤ÂQ êe×kný Éî**%÷)õ;uupjëUn€©T2g|ÜÖüã"rDpçmtúÓË«öòQ}ùS¯åÛ$õl¾__žµ–çõåø<ôÞãNÒËG­å›úò>›ÈL€òƒŽX»ÎGÔ$ë˱ušÊK¤peÔß_§$:!Ñj«ˆñÓÈßøïSüñý¦’Ô8èEIzÕÛþtSi&MZ>l-ñ»HJîeýþ¼}ÕþÅbx n{ù¬µ|F϶œC{ù ‘ôZÇH¸„œ#>¢wÇ2?â¡ì> ÂÓ$ž~[|‹?0Uszi5äÐi‰³•^Íøü¬¶¼hk‰v5ì=†Ÿ{„hœÿjÙɯtßLßÖïl“ååWõåI;ðÙ åñm;‡×ŒóŠä¶Žþ˜õKÙÁŸÉ‘B‘ Ÿ¢®8ª£™0Ýñqë¿­B[`èÉùݦÈ‘?ºÉ ÜH#]Ar§¶¼—¸f€V9‡‘^¾`–Ã_õÖô‚ŸwÆë™‰î IÇÓ¦ªöÄ|N¡_“Â@͈MÐôÔÕrÿÞí=‰{½]¿¤».ê‡qVYèã.«_6Yøp¡ˆ¯Í˜Ió²Gü«¶öÿ —ýá¢ÑÍto…scF•/þµ‘<Ÿ¼•&Dü’•só¸'~_†žx­çÎ —º€ñ¸æJœÂô€­¥[³t™ñ1Ö³ææ”u,Á'®y™WiáCa ’ÇE8Û†N`ØT;»wט—†¨šÛõ”´fÜVÃÎ&…›Çñj1%.©;{žHº8 X“²öJˆ7$ÞÕÆyœ œ‰Ý¹ñÙ¢×Ïwà}ÐêzÙ»)ù0Á‚j,HÓ"$^ð†óJÓ^z±ŸÇik#þ"¬?‡Ð"qWéè׉Ó4ƒ31•Z%&O¿°XV)fÜs¡/hf°ô)ñKOÞí듽HíÉ*hÑJ‰‘ Tq°ÀýUÒ.j1yc£–‰;ÐæzŒ¨…áù§9xhÔªéx&{óhZ¦ˆë,v‡´2NÀú• š¬á$ˆðÀ•–§ Òz¨ñK¦˜oùäÅ^Ú¥×Êü×UcÏŒ"xÔX÷ÁV©U5݉¹eªÌjÚ$-³‘Ó8e•ý`šLq­ŠK’èósƒÆf%ÿ,ìA †V è”®‘yÓ „ÓÈ«™ecJõ =V¢ %F¡‘ÍN&;Bkq÷,ýÌKJÛ\-_R³ åJÅøxì¥â#ÌGp¨LÄ,£E똢 áfæx\–Mнkë–VÊÁÒè>9qe™Ü¿ÛL0˜ÂuyᘚKЧüÆ¢ËU($#1ß–Ú´’‰Ü1ŒÕF>ÉËIV!‘kŽÎgX E„¤ùvŽ0ÆÏEoZáørȘ¾š™£˜!‚ÁºIÍ•¸l,¹šüÒ„í#~ò,éSš ƒÁ],uoL“’SEÂq/뀩¤Íðܸ¸˜¢}\&3°X£q—õTŠ”dô²® @Q+j&ZÏ4Çøz#a&éÜ\+_4íK¸aˆt>ßñÈÕQ‹Œ ®l¥–Ÿ¯d/$e«ûª¥‚J2@…BœÅÂŒr–|餳xvÓKèÍK j£áŒö® *ÔÈ;ІÖJ¿"ËhfõYʬò16p#ŽAJ\d‹Ñ+:ãJºù élgˆ©ŒB£gôÑèìÝJußk†éV‚Q]Íè÷<´K®FTßæÞ¬¢ «ç'3'X›°'ÏT·ôŒ]P9G½âå‰û”tÛ÷ý0-”ÓRb¨cÃÄn»á‡ÆKÀñŸ®‡®‰uðváÂ-««ûõÓ»H™íCôt”«ë”%=kÇIw @JYµØ¿Èï‡Ús+¢O—>œ ÉÚ …;“äÖ»1‰³£uë¹ð²Â^¦ŒÖs[©ÃÏÊ;Á8 ¹:zŒ²®lâ´ŒM Îf·Td¼R¶5kIʶ9ÏUß!e[Ÿm(¯EQ‡J›XÓÓ¸‰2ÿ¬pn=k SOLXRr@ƒ€Ã/ø£Åø0¾9üÚÂü´@à›”áoòä¨{‰þZDö-ƒ}”FPõãÝ=ÁC¶¯Ê2½B6Rh°•NÆÓÝg°™[@µ1Œ0ÍÂ|$lFZsaýÅc‚ŒËÊ‹_åEôŠ%˜^IðªlÒ@žšÝeÍÊõÓÎ^8ôÆhÆ º72j–~Š ºø!v·ÃXV7§Iª“pÈÏEÇ.ÜïÜĺ1 †D¬Þ1û"HAG²Âê½÷^ÒéõŠYãØ®›v‹¸âBAUȸíî]øÈYàĈƒ´*!Á‘ËtÃq[(xs¥Ëˆ0^_žÀÈxI°"ŽMHk ¶_PÚ«<™&j=øÎœÆ\Ѻ¨ß/ç½âçG9ZŒ!Œù=š•F”=w¶[Ç%eÅ-E¸g)Pr(ET®31¡µî#vc›Ò¸¬T¿¼U†Ï™ V ñÐtöš|…ý¸Sv¢›ÌÑmcáÔ^œ_·Möeba¢˜ò½Žc^.1k߿ՆwÇyAxOËÍŠÉ ŠÑz~¨lø 0_õZ‹Eq;Ê]IóòÛN7å·‰#Eª"£ªLnWXú Z/zt‚køù-áû\3‹R}’,-1Ø®ó‰9 :7ªwë{V±^ʵî{Æ‚»;øãö¦Ôk}?¾ÉÞeôLAŸÄ•\¥÷f3¯Ûkµ-¿4‡ô½úòN{y»¾Pˆüa ,•e0ŒY^Þ©/o·—§õ%Ãå³(·Ò-˜ŠÓ&—Ö“e,èÿb-„†l=³¢ó.©+ê®óï¦ržŽPYývt]ŠÝ»DÍUö³Õ¿{ˆ= oÊöz”Lé¬\YÿQ[ÐÚUrŸžýþÿ/WÄ4endstream endobj 1000 0 obj 4944 endobj 1004 0 obj <> stream xœí\ëeÅqÿ¾Y)ÿÂHùÀ½÷Ðï>m)RŒãØÄq`,'¤,;0l²»³»°`þûTU¿ª_÷Î$’•¹œÓ§Õõ®_÷ë+±É+ÿ¤?}ñèƒO¤ÖW·ß>W¿¿ÛG¯Ijr•þõôÅՇרlÇG[A^]ý(v ¯¼ºr»Ù¤ºº~ñ賃<Úƒ€¿í¨6ï½fN»›Òþð«ãIo~—Bþ*xè¿?žäÂnÂáGuøç£Þœ3Î>†6jß„´‡_‹áïà‘v›îð»ØƒrîðkìÁëÕáߡџŽÚÃ0ÚäQ°Í'Ç“Øö ‚1¥µþFƒé:ø;Ùáf´»Mï×4c‚䃤¾„‡iÄÏ‚ž&øìÚo*¸Ã§Ç“…L°‡?ÔoS7Úì‰Ô9ë%Ψ{ÈšþòÐæ~=ýž­ùãc"ì×ÿDû½ó4Vnn‡½¼¾Iû§á/-¶>¥·'-6/CˆÒ0ÂÊÃ×0ŒÑ›ÑòðÌxßlå7qÉÞ…ïýf^UB<ËÜñg$!ξúêhàµTêð? ›’îpsù«£Ø´V°W‡oqdk½S¬ùwÐ܆M²G¼ß4/Åß¿¬s¹‰? ÞµÕîÏ—ðsߌU.}¥€~-C>‰mÁè OqñH“Qng’Ò0¹Qç[ù5Äâ¶JW<¯ª$§‘¼tµi\™SÐ)[ä Õ4oÍ_¼<*ÐFèFöh®`¶ózÓ,I"#eHAÛFVCJϬY}Ÿ&ï„Éý"ÓDMwDÚ©¹iÍÕ¼™²ÒÔ°… z2›Zã›™ZxY[Î?ñ#Ì¢fâDœ[ò«žUþ‡ÎÀ ‰ÆV´„G¾Eƒ¥ ûÚ>D̬Eã7õ^öoã0Bšõ4ˆ¾z"aû¶ûÅåGÆ·q™.ð®pSP±_*è½Â‹Ÿ•_¯êd*«æO`Ëþ¾zf«`T[SäâektÒjék“m"­\òêÓ/JË:gðÉýŽº4;‘¤ ¾©“ÊãDÙI„j­YVÙ\1°eÌNûV6.;YMC+-ݦHÍ„‰¹€¾ð¯<øüˆ`1¤ú¡ÆÖe±Ï똳¡”FCÁH{F½[Ò&Y’D ¶;ëÛx®Y'N@¢o£KbàmZ.³)iÈ >3píM݆ƥÊ;‰³¹©]”æ,.›»ôÕŠòkµgƒT'°ˆªµ5Kÿ%åg»… WVˆ²=Ès¿+3>0,úðH‚ Ü©«çÑZŠ]Mˆ®çÛIpTåýÄü¨<ü7(Ðçkµ÷™ÖJï)ñ‡I{Þ˜ûëˆõ¬!Lå ñ±k¨Uæ¯#µâ€ôß/Gj¥IÞξI„Ùý_5çÈòÞ•a£Ç2%ì„ÕøXý?a auy¯ÂN¨ùæáÔÄ —Œ,)ÂØæI³Fiù‹o v õÔ©¼×õ#Å…~B›„$äæÿ: «P- ‡úéIƒ½ÂÒhk}0OQì4Ë=¡qGrï®u.”Q¶ Þƒ" ;‹Áãd”»ã"3Ðx[Êzªÿü–Jî}‡Õù\§G'ØÊû7™ãÏ•BÁê“ß<ËI1ƒeÀÐsÕgSæ¹Ï‹Ñ‚E®:{f§ÅTî¾ïG”bèlð)îŽÃòL Ç5å>ŒáÙ'–@_(H“X¼zÖÔ÷$‹eb­’ÍßÔæ¬TÓ¼/ð=óÜj`²]µ¯®hÚå½íÚ(¢ÇaÆ å¦1ãôiJ8w!ˆÏáuŒ ;žBÁÉÑÚÇZ‰¼ÇpÈ*žc™….LÖ›|2j]ó :gOŒ_ËJŠS«¼m˜¯‚@ÿ·E@WB›"×VínK*ƒ-k¶Â¶Ò‰´âr¨]õcý˜ðVE’Š1Jn¨B‡T3®ÎJ’—hDRÒ.¥QÜaš°º”Î­ÅUÙ¸]­h¤]O#pZîÐPZx:%"qbm™’E=±ê’(Òfºhûù ë°ä0¦j17ü²ÊºŒ «k­”»FæÊý+®ª†ŠM'=9wÁŸÞþ±­S$.XÂà::Î"ùù±¼Çšƒ ¤A0ÂVlE ¦ç•V«c‰‰žÂqœF´°B·£v„Ù «µ¥@ôë6X%' I€³foÉ]¢ü÷á3îêÃùÙÄ¥Ní À—Sñáë&¶¨±r~|Í<¬òôXž~qÞ™â Å,Ìj³þt*Êø^OYBJFeÃù=K •¡š yþžÙ’Äóqºç€k˜0ÀÞwF ]$•;“Ìtë’̪îOŽsżRÖ6úÖgÐ5Êj*¸2¢ŒUV3IàÂNvÕ^ö;u_Åi :1û*7YÑeø¡34›KÙbTÌ÷^tÁˆðVÆQÁß鈕W´__Îô?r¶àøèÃçoj$_‹›æqÁè®Kû²ü%¹*\´EÅìÔ¢çP?‰”lÍÆ¢™‹Xñ’º}“}^·NiÁ˜Ã•j3ÃÍùÆÒ—ï8ró5“¶·£ ÁÒ¿æõ‘»:âªh‚ï‘Xfÿ5SÎÝ(M‰£|Ëž&k#"-ÓI•B¹:_ßÎ]¾ 6³:’T¶ìB%J›¥;XFÌ ÚQ€“‚“žœçvÙ±Ç3ÎqpÛ×Ñ1³ØÔ;¤gšŸ}#üÒ0Ì…;“4!Ñ Ú’®ÍÕ¯à¥)‰ÔYUß; sr0Þ«º(Ã5x%á~ÕÅÜÌÏy™qmΠÒî_¯Dƒj®€ÂÚ8…U‡Í =MÙH m…7`EüÔ£ )ÀLËòLÀ<$¢µ¿‚ÀAjd˜;zk5jüÕ[¤§6 ·€‚ ›à’"Ñý¾yÒz“~´[¹éMzÏï S+)èÔ¹DK©•'V·ÄÍÌs{ƒï­Ój÷¥'²º úwi5²>αLq¦Â &W¸yÒÖxGÏJÃ8OJýcˆaQd³aö2Áçì¶ «kWOÉÐ{M™<øãú {)Å §¤ ÿ&.ÓI—é_O=%-òž2Ïby%Lσ|xÔ¿²‡ÿΔ;Ãí²nTC%× K¸°¤XÉÚ Q dsö*£/ÜX&fÓê]õ»žuâ:ÄÜZHØ%ÝÄÿ¤¶Ý µ8…y´u¹d㘶¾KÚ[ge>‹Í“‚s 5*Zai*„ž¸™SÔ;ƒqd¯9hƒég– bLpû¬6ÝÀ‚#ã¶Ø—62&Öʱ˜1Qaeo€1Q¯u‰ÏáÓD,ÎSÅñú$À»pvVüß"® tiz¯&tôq"; yYxÑ|8kÈ3À7εXÂ3ÐLìÔx%3!™ #C+_tÊi½g2Æq½û"©c޹ɤÛÞ&X¼c'pÅ2F ó„Y¢¦gÁr…ŸWq@F­›è}0QÉ*G3„cé®vðxdc.[ÞÖW0Á9x·ñÔxlèÐ:=ŽÐsÕ°f_)YcýY‹½T“²V°y´ˆŸBcY®5Ãê{8cD{[Î&lºOG¿;ž9NâwÒ{°Úxhê!*Ÿ6›0v9bA Ì FQ¹ÙÇRÌ䨀¥³iü$HD¾cò¹Ä¸G•›GkcEƒì< Gä—å Æœ3äy~s6ŒÉAÂg6GʬChàQ3(0ëe,Pdê´æ‚%–îRtLYƒ›³Ë9wv$$‡Rág4NÚåô29µcÓ"ÅÌJ¬aQ\’‰šž“l²ÐQ]2€É@£b4ÙT è\×Êz13À|œ­›Z˜’leÓEQýt9§— ~ØÎÊÆä²µÓÑ­]¥R<ƒ±v®VËxô̲ÒFƒÍ}ž°ôaåèøÇèiE›lZA%Áñ–wÜú•ÂÞ€ìÓw»j±•“å“>m›Ûò¤%AóÀy¼o]„8ͨväœ(hAb§žó‰”ݨÜqFÙ7©J•Ì/ݶ;Ÿv€ífg»'®» ½oÙt9³Ï]h·È?çÀàY¿» û¾9Žc/Ç ÖøýÆMX€!§´ŸJʘˆª'Ë*$¹?È8jþ•ÅXQÍOpŠ&d¹àf›ö~[' ¶Ö…Q Wƒbˆ'û½Ä×÷3ÊG bIoVAX¤ 6KÒs&,sÕž˜ºœYÀâ³w¨CFg(c¶»åÍd¶¥fOä¡£’øf€pŒåíœtgOº—aÞ £‚•‚½,)²¤0OýÓ4{»Êï•I°ZñüøÆ hÁ~!<¢Ã»ãQ™€ƒ6’Çü]!›—kSÉg÷~*‘ ÃOC’ä×*&ÑÉëBjR±€R‚yïSTÃñToží&*£®¿ ¢Ûþ^- ã˜ÿ׊¶ðIkmbêVº¥Ôå”ûý€1fÐÇEd-Řf¥Ù¬]By¯³Ì8‹-p†mf‡¨Ø…#™'Dûä^þ¦2Ëj?MâAv=~ûÐ#_Q!Ó¦/Rèxô‰ÁöQRfQø<ÙÄc‘l§°I‹£Ÿ”<…/èM2IÒºP9Ý…ùFÎâì:‰„¦eOOô1 MVƒ!œ· „’1}¹PW©qÍJ9P^Ä)»sç±YXžŽ¶«NcFSž&\ÏÏP²&ƒáÏÖ¬1 S­»±y¹†Ã÷.O=¹ÇÆ•Æäƒ ùÔ¤ï‡½š šØq£³¹Ðšµ–C±–t¾3ÍAÞ5 jêN­P…‚†ïSOú¼51&.]ÜÅÑÝ"_Ä`ȹ3ȰöÆ»ÜÉY(w›UNŽ#h5[üÆéÞßñê±³™+&[舀§©„MWtJÍV0/Î.Q¾u¶9~‘㥴ºGê­à7SäD´híb{/Ñp÷Ob ÕQîwü•?Wå¦$ŸåüÄù”{;¿ªõ9’c91d]–S/c)æ1/[s¹¶‘nÁlópãm 9·—U§n-œ®˜}]†?¥è á®ã•wD­/ÔÛ¸sõÁ'Ú‹”.Ìnº~/y€Yø¦¹°ËnY*‰n.Ò¡¤$WÞ¶P13â ÅŸ‘匠pt´2Ýí¢`õE%ãâí! "Æ·«K¸OâóSºØÅ¨ÞÆ»N‡"?PÖ?E¼"gÐÄnóE/OÒi„f«}^«àW^9eèvÒÕÝlq=ÞNš¦z8ßCÛ/â¾ÚL-­¶uŠºJs2 e¯oªÓŠ,s“*¦,ˤnq%0»˜ôº±Ý\Dß•¦MTÄï Ø`ž%}ƒãLá.ÐUsÅ¦é ”¥¤ÍÕºòù^?p7ÿßzÏ#ó†°´VÓ¹U *;žÊ³è¾Wõº8¤Úá)&¿™ Ï´jkPÍõ3é¶ÅŽŸì%ž³e\ûëëGÿ ÿü7€(®Tendstream endobj 1005 0 obj 5517 endobj 1009 0 obj <> stream xœ½]YGr~§ø/ŒávšÚʳ²Ø{k…ݵ-a-V~ÍP$Áá %Š’è_¿‘WDVfw›2²FÕUyDÆñÅ•þîbžÔÅŒÿKÿ¾yýäW_(c.ž¿}2_ü;üóüÉwO½r‘þuóúâ߮赦u^ÕÅÕ·OâêbÑ>ØIé‹«×Oþ¶S{·³ðϼwÿ{õ9~fñÙºNÎ×W·ðöo÷—fZ–uU»ÏöjZ×`×Ý¿îõî?÷—j²Ö-zwUßù}|jlØ}OÕ Ã.4%L·›àWmçI[þâWeÜí@8ü_`¶ßí킳žÿð;x]»IÍa÷‡=~¸øe÷Gü=¬Æ¨ÝŸö—ß7VO0 „Kÿ3¼ì½[úÑàpj÷åþÒÁ‹ »¿îõ4ÏN+úâjÄÓ*,ôíW{¨&‰}©=}qiæiF꽄‘`Yfw¿¿´ÚLÖ™Ý0{F§´«Û=ƒßg=¹Åîn`«° ­w@²»<»úòkØl ,¾Œkþ™_¸Þ‹—ž•ßÂëp&Ω´ŒÅ˜šiV6´xKcÔwnöf™¬†Á^Ô¼ÞÃf‚‡lqeÁõãB…7×pçÚÒ’âÎ5œÔ‘ãúØvßâ‘;·â0¿¬p\.3‚þû©»ÂšW¶ª†ú@ç]¢®áçý%pª6Ëêù¿‡w'cìªÙ»i‹G#Ne)ŠX]ÜY9´5myVé¹^&gçL;7¯t õëûʤå(Ãîàâ»Óž†©ãY)à}Ô3¾+£Õqãú½ž‘@°8*eh°o‘âÖCl™÷uIÿžuÜÞcY–œÑ3p=—Š’j¾©g¨I€E¼•G©³·3ûÙïnù1çoqK q$¿“)góAìwe¥uv5½]#NÊ$$?ªÃÕgìÛOQ›…Iƒ2°yþè¾îòšïíŸ/Èõ£ˆ¹gPˆsaî©ÞUfM„]Ѱp&”`qZšm9ô,*}Ô8]ÇEy6ÆóžÐèE¥ÍÆ=‚^böM¤nâYÐÈýiãÄý oâþ+[%•¡=˜–Ê•õw¦F@Ì̪AÌìÐ â½ÆïéÒ"uò—Rã,åõ÷¸Oür&šuf:Kƒ›Å'üT1ÀËÊ–Œ?ƒõîéÄ ÞDÁ².°•]G1~™åjñØÖ˜0}ÒµlÈ :é² Ô9»öá6Mhôi¤‹…¡Ó!4ÏË£W4öÅb@ŸÀo»W{C_*¶š÷ öþ´×€¥5H 3µxZ·‘_qÈo¿"EyDÄ6Žc™|¨aëfƒnäñ –—ÔQè^Y{ƒ©*7¡Ya²ÓÝ3;¶’—Å0…퓈Á2DÊ`–ÌиÄ4å$}{’×ìWë*ws'æf+ŒlˆÍ®…÷°qZÒR‹#`tƒ„÷1ÑÛÏ8íRƒ1A`™L2÷?åóO’‡ÏÀ~é`ÈÄW¦œò‹Ï)ŠþñîìHA=ÍÏ.÷HmrT"(8¥è †x úþ¼×H›÷§iqÇÐG~ïCðì ŽÕÚ!_ký9aN¬ˆZ€'ŽþÍ£³ö…pí¯½'Ifæ– Øt¹ÃLª#‚ÉBæîº;&óìT«‹Ê(0B&ñ<‚V[o•ÆEª-3‚”‘³~¾ª%nÁ$š*bíá+²Uа £:ÝfH„õ¸Lä‘ècI÷ 8;Ž{˜’bò“Å} uJ¨UØ µÆF»áhÕ0—˜½yßòqöŽäY/ABXÈaÞ|‚ÜÑ@¯¡ãYöÍì1Ïc¹8ci¶A usˆ8öÉ–-93=] ¶—_ì3#j^« (<Úè`†Å»Z¼+•ù™í˜`ŽUÁwâ˜24„Ó¬Šb*]ɉ¦€|Ôy]»É7ŽD6·æT߸œucÀ«%òœÝ“!2³¦ó#_ NÈ@Z¶++úEõ=(TÒãÅ=eF%¿Ç¥ .êækÒ(œö]Ïóf+)öÕà—¨7Óó_á 9âŠn s³âÞtmMÇÍÖxŒ­þ!îG؃e!Û˜ž´<ØoS9¸GœwùWÍpU6@é$5°:0Ó1í-¤ŒMì¤ê6mv½€ç}o¦Ì%zQU{k¤àå¨äuF>nsˆ÷IÅZŽrzlÛ5 RU“2\‹ÄÂ^”V¤^Ös syã_ìd^áë–@}˜ÌȽ† ãW™Ù¯ü,¦¬£Ÿ#hüm€=k<_(6úQñ;’˜OâwoR@©ìyX5ùñŠ)b¶ ¦Å"Ú×ÓZƒÿL%¿hOÈ]uâmçv P‘€\ƇHç¨Í” ž¯p¨xl³¬ W©¹h&oN"ÿn0§°Ãsc¾Aªpw±Ž—Ñ~ßÏîõã=ñ/ð(Ã:/³Ác.åbûÎVkãÆž¯°h÷–=ÿÿ>¢htù÷BA)?páÜÖ_ñÖø¢Òó+·_HàŸ«g]ló_ŠÍ¬ûaëC^§¥Œ­Ú_‚Q~ƒ_à)yúSDRëî?êÓÊú Ó×ÁK$YyÊB³—”…Vª |:šžÝàâ-}‰$h´~iPðÇÈšíDœÏþ”3ùu‘ÿ èú¢Î(Ì—±Žâð×1öhÔ'¯z¨ßXr‹ÎâwëÑã9Îî)îu ôÇ㑱­ŽJAž´ÜvI¬]PTVZ“&Æ‹\»/þô%²ó6ßõwG{Þ¦Ô³3”{6®Ï=?áo¸àGÔEÝC=J‹<Îâk¢Î“µfœ%Š• ¡Q] >tBB "‹Q«TY2»2ÍM·Ët–(Á7äú_·ŸŸ–ˆ%æ2 «öÁä‘ Hž&‡ú#£*¼‚pß ñG¦J/CT\ôÓÛŸJè×*5âƒÌŽF.„,¤ÇòC”6ƒ0».’ïê€&$>šm[ׇ˜C™Û­\%ç*}øÀƒ|ÂHïeq Š"8Å7‹d§[P·½‘Ãwy,šcg†Ñ÷NÉËæ!Vâ|‘¦®¨ÖÏëa‚ÆX"¨NZµÄe½ÃαÀ¥>gEÏ…p”D;³çß1ê¾k«x~Ô[âöäæÙŽJ§âTóK N‰¥lý#©“Eiý»¨ m½jp| Ï5ŽRË÷ü9¸ãš6µfý 3‹lGïZÁNŠ"dãhcIŸÿ¸wÌRêßu_N‰ @f¬j2ݸhÔàÀ›‹$?OIR—,_ï1£oÈ©G¼1<ÖS>ÝÇrÝ“sÈnP]UG’ÑÂø2ì‘c„ĽH¦‘FÇ5áÉø\Ã?1 3Ï×7Ôu•"¯ÇÝpîᘊŒ¼1Ç™Qëw}+!¸;•ÖÇOÓÉ(×-5éà‡‰Pÿ_'HÒ„y˜žHÙ8ë)gM^ËJu„ÍÚÃÖ ŒBŸB‰–6Z0fÈ~NƼc¾Ãp¥›C°†±ráóúñ'î-ZÊ7ÉØLŒaå–Á„EjIrØ2('IA$‰ «œè3çÐÞψ½¢Ï<Œ<–úN+¼ª%õ#t„m«Á€t ê]8Gœà §ñN­(î¹9®Ÿ‡m“,¬O®Ôm©•÷˺uh{˜Eú‡Ùí"ð×µ¤R·‰¥$7gœczƒxX®Ë–j>D}Á8ý÷yJiüÇqYmˆ™dVO& àØŸEåNq¶µ9aë9‘(ØËšò.)éîÔ<;({ìIƒ8Z‹Qt³S–tóß}Í-\C ä„ßÚXäÐ3†"K“€ñ»kHÌj2B|± Åok¾*ªoƼ ô6qBã)é’p‰úL÷â/,ô2ª“ǃ«ÕØ©@à-(Òr„A€Í©›4yÆçïëÁ&ÍÒD'»wô`ª÷%K`óÇNuîMe":GÐGú¾ @'Wz).€æáѪhìt¨9"ÛJÉz²,/Ǧ3VÇ6Ks˜ud eWªÚLˆ]B˜ÛSÓCyÚ`zd®G|Ç 5+šAá@JAIâÛ®2çŽgn¬ ¾J(„î¶±Tb§C§èÕ»t¼áªÓë̘&®'r ÒsÁH–žä‡óVz6Wzrõ/Ûý¼¿,$f„SÐu®ýzÃR™AI™LÀc0 ãV×±|¡Æ(o¥—€þãY §2-J_X[ýää?¬w§¹gΦ­y ©ÝUNpÏ­æÆ)Sx瀗1£M‘(ÍÝ[×¥a0jš=¥ÂçpáðLÝÙM7­â÷tü‚TŸs̬ôòLlº!SÙ82l°ºŒ¤‘øŠõoˆ‚’Øå}t¶U¡òꃔشIvk³z ­iP"ÏËtâOÆyàÄ­K)Ó{V¥JòËGÞNN‰6þ,RMz$§V.o¬wNCPSBdzS͹]Êé3ˈFYXvúÂmËŸLJµ©¯M$R‹e—ºS*™SÚ¬œÌD—f*N´QchÞ#ÛXȹ Í1"yè΂˜ƒÝ“‡®‹+‹VòŒÖ—;%Ö¬`3ÕÇ"G½Öß´K5jŒ}kÚ¯#àYƒ?R"ȧÜI!%¢½5ÙÝÑa!LÆÑè >¬Ÿ´h1P¤Yø´iqJßâ-IåØ-§Ó ¿«Ã:-%e¦—-âÿqÓRñ³n½ÜfÝXnn;~#á€q/Ε»1yÀV2ŒJÍÏFø¹æ®’>jmP®×ÆÍ­µÖyäçß`ÖÔë‚í(óð^×Ì#VÆev¡[ŠÈp&)”²¾žË]­7ÄV¯›1”Ñ u;¡zž.ãTQæp¬‡05fÖbÁòˆšuÝÆõïñëÝÊÒKí5a4™ˆ©FŠ ›lY:ãs¼»@‡¾Ü»’„…†w&hӥ޴©toë‘X"•Õ>cٮ뤤bQ°gžãEäÌa³÷êã… Oåà˜ÐÆï—Oˆ4¶ÛMç ^—)˜N¡ƒäŽ@\À ;è~D”!ö&&QTŒè2ÈÓë*aeÜìM–ƒèIí âRˆ*’§ ΖPÀ‡^NU;É»,-|Ð^mRŽ·˜3mSŒÙloTàƒF¬&˜lØ_ÈÞaZ}+?ÜŒxµÀ8Ö4`pÍÛý¹?qRM3S iç­Fˆ2áØ} ¯!A^ÉvN/¹‰ÊMÆ®äN­’ ±¼dÈ[?¶ÏH0ªœàQ¢&ÈÇ2㢆ÚJ£²ŠýmõÈSMŒYò½Ö;öWs{#²œÁO»×­%ÍÿYíTCè÷e]%+Õµ8p†ó ó¯¨;Á‹ŒÍ7ôPtàb[ŽÃüºÛ¸ þu>.Ö¦Ò‰ú$ë·aËØ°N¾^ðöh¥Ñq÷L¼â)¨ÕdÌᾺT¾Vê×ÜOøÕà!Ë6‹Fzd„–œ˜”ØØÖ9ÏJÑ_t×'pã%•~ᔿé™*0‰Åˆl°¥üÕ[LŒ®pæ¶yvë̯ã÷7å7„¹¨sÁ‘z]¾®Ÿ•‡÷õḘ@÷ݼ*¿?«¿¿/ªÊÃïëÃÛòðiþ‹ò)YAÄ| é3ü?X‚ƒb–>º*„Û[Q¨>"‘^”ß^Ö¿-8²µ÷¿4‘z÷¹N ÉF,V¬¼H!'l±À龋šk.¦µ†e7±§F4“~Ç4xM¿KÕfê  @6^ý¹©G³î`ˆô6…:m5 ÎÛ¨è#VOä—±.u±CWšñ=ÌÒæcMÔ·]-+©Ô1šU^›{—QC¬™[5uy2 ÷)7«A½Læ´ ã+5 õÇñv.“G>9Þè§²›[eYìm/'yWçAÛ·µyò"Ó¨ÕKüØ»À£ Å÷î}ÉW¥j>Øù·¤{TXÙ<óëM†âfÀ߃¢6 Öÿ_¬%†Uêÿÿ»ÜõæøýþêÉÁÿþ“<ý;endstream endobj 1010 0 obj 5559 endobj 1014 0 obj <> stream xœ½[ëoÜÆÿ.è¿ @uçúhîƒänu[Çq›8®sA[8þ ëa Ñ+zØÑß™}pfÉáÝIrš@6µ\ÎÎÎó7³ë_·ëJm×øú{ïtëé[eÌöÇ«­zû%ü|ÜúuK…)Û鯽Óí¿.qšÃ¡Ê×^m/·"µÝéíÖÙJéíåéÖ»™š7³~ª¹®º®3l`áêºÒ¦›ým¾0UçTmf?ࣆÁnöÝ|¡*ïõ³ŸæzöýÜTmkÛföæhWÕª™=‡¯áçï0dÚJÕí쟑‚nÛÙ ¤`mÓéÙaҿ禃eŒÍ«àœ·óE]9¯½µ=ífßÀjÀnÛÍ^!ÿàȵU]wíl8î¼W|‘D«î€ø™Wu|‰¤»Jûvöã|ÑÀÖ7³7ôm"c¬KâÄ•ÈÑ`M}>÷5Èx_Šß³=¿ž'Á¾_þ#èÛqEÚFU­].÷“þ,üÀßq¶é µ/¬i*Ón/L]uÊûøÕòìm|ÄI‰8ØÁÜÂþ•Ö³½þé>/4(¾kíì‚$w[øðã\«XXBÓøÙϳ~ô|nÐX¬™}š›`„Š-v ßTÆX¯gŸ£jeùèq6\¾~]«ÙÏs`C™J)^wÆÌŽˆMä¨óÀ‘ƒÅ-ègvu’©ÞðÉHVƒ}^Ág®Ï-†c­%`¿Òw¿¡<Ñ{ÀÌú¯Ðš–f•ÒN¯‰GC÷»}tB—j-€ò¦¨¦¤%¦ d_åPS¿m/¿ÛZ>~—Kõ:9†÷$gÜú #Tm‚©ÿžÀÓ€bê•iû¬¯JÊð!A+ Åu,¦˜Ý"˜jü!l ÌT/±ÀZx×ô©VÕ¿ÞµjåxÍ»PcçÄÎ? ì;-î˜8Vßµ•×}ª¤8‚HÜc¨“Š/ÔHiõW¦ÅrM{ÔÒmÅHDá¢"Š<ädxùûuPSÕÝšì–l¡Q ‚@3Ž$À2ßNºJë(Íx…q¸®qרÃ5™!`m±,cËàVQm-ÃCÜ8èB‡TLö¸"¡FD«&ÒY ½gÝÉaùè'ÓcÜ‹[ŸÇ~K‹ }~zÕ;è²ÍFÒ¬Dô WÊ óAÁ´±ˆcA©øÉêRŠ—ÅhÙ9–mSÚ7m,p‹ìZ•L“"Ñ(±!8!«Ú†Ž ß&gÒ}ûªÏÂäKÌêXNv<óTˆèº9S¯Üû–µsAL¨ç8 5—kâºkƒÈ÷ÎcèDºƒ@æTˆyëÌj 4ÇqY‚l!PvEJ{!‚<’Xb|>Aî 8…[W?žõ @1w0Œšà±S´"„ÕX³_=$›¢‚&PbnYyè¯v%²Ê,Ë.B°Á´B–O>ÔCc©¥Q´+  Z7"V÷É™-g©µ¡H[QºeÖ@ Ók&t=òªöX 82ðÜL¶mÀ Eî±¾þrv^>,ix ÂÎPJ™×N-žq²Žûu9#Yš›¤¿l¥‡¼qh9§MDqÀ†ûàµB*¨œ¶-»#ûÛxŠ9™=ñ;k…î"οWwQ…XB¢¾7ÆÐZ/}7L‚–õl§·×Ç@c'‘¬ÛuÖÍÞÞ ¹±¶e¨›@:̧¤¬(8î#Îí(¡%— ",]*V7Òw%YXÕWxmB„Ú£à.—£=„f3TN˜«“Ù°`Ì©Áøa¦\–·FG›(Ö?3úOßeŠ‹ÈX XHÇï°n†^2^v¸Â¢ÑuU×ñR5f`{ x_-Tò €”†æpŒ|ŸÍyÍF±I)ÆwgÅrið6/ÜRqðˆf`XöaÑeÿþ˜ÞŸöƒDiWZsŸ(]öïwéýuA JŒ2{ô¾”>bsS°’Ù²WIj.\5È£Ç"±“~4œ™cOÜŽz>™Ë "qÁYσ4ó2jâ˜K%ˆ*ôW ýP:©ïºøˆÖ"rð.Xر(¨ Q¨×‰gãm—Uâc›¯ I.²(ÁÉUuÿK8Âc|CÞðy…#KF¹×’îqû$4®“`G_ÒQhùsI»7ÒçgÉ;¢Ÿ ŠÌŽæüÄ„[šp^h:?‰:½\ï÷ÜÏÈW;¦I&cŠeWcÁ»p aWJÁ§¸r -¿ÏÉgÉAãš$tDsw$ae^Ò½ç<Êæ~ gYà«à1¯ðïû­¼À_ŸÍ¼L4ÒûDâküýëšüçC‰Æ’–|. þÔþHƒà 2?ü–=p.„ÉiðZ¼º¾¢÷…L~oLxŠ5¹Àº”v¸Þ~ï!‹+)YìJƒ7…ý×þîb‰ß7œ>h þ“Ë­ÿå(Å£§œ¤Y:Íý=åMï$Áàßô[ù}N;­Váp…(êŸp+ñJwÝ ?…R|FAç«Õ¾óš_I3és¨yòc Vå²R=¯6Å–Î8KÖAvþ1ZÒ×$ˆÕLÝHv^Òbã3z|ÌcKp¬NUn˜‚R¬!³ÑÐîüëLzÿ™L èÁº†•C‰{æ§ÀÞЄo‹0Sü§Q&š†Ð’:‚¨¡`;¬ù»’9^q¹°;Þ­hƒ¤@¡6O?Ñû×R†X&š#Ø/¢|nŬδ}YH…çƒl®ñ:î¡d*—Äþºí­³Ïb2jª†ú}¹† ¹:8#)•Ƽæ®Îü{§J‰4ÿM»XíäW’ÝKâ8ËÅ‘’Ó­hëW<7gD¬Ò>ïs™6öÖ,»äÙcÄÎl”ÉîË¡ò{•°báu!-M%¢L D‰5•–TËé“T·]JqèFâî„ä$f=ÚÒ…DéZŠhåæÇñ”ÌéYðSLê•,BÀ("5M&…—­pS^g&ÿO™e+û,yÆôÑ~62;ˆBBe=5¹Å¢b‰ÉWFÐMy%™1e‰R 8 AŒcЂé΃k'–YâàËoãÇ-гI'û¤Oó¯á¶OˆF|+ibÉöŒ ôpFüЍÿcµ­Mÿ/ µ™F9Ѝ—è; ¾/‘á .JL´2)?1zNÚë\bƒ†ó}lZ‹,EÝRb%,óÉOب<—…Œ¥üÇȼ€Î±âæ¡ðvóÔý¢ÿzOÏ4ø£düoûÁk~‘tyÛn¦snºgiS‘ºâ?É)”e†ßÍëšSÉ–¨ Æ´+vù‡ÅÎZm}’¬\´Ý1›n™rÖ/;,ÚeÁM–UqÞÉÆÐyŸ@×½ ©ãBÈ_,±eždûbr¼)lh¤Ÿv¨ŸÔ?ÛÒR(ÿcßÇÅ!#³+ šYÊ)B(}“^÷.mÁاì"Û×]ℌÂN‰ØéH†tw=’¬ØV½”ü¸€^˜ïVb&?}x‰IkæP¼2 8ÏÙcU·¹6I[/–[ÿ‚ÿÿRg„çendstream endobj 1015 0 obj 4325 endobj 1019 0 obj <> stream xœµ]ë]·qÿ®úX toà=ᛇ Ôiâ¸mš¦öuaèjWZ Yie+R¬ÿ¾3|Î<çÞ­ÕŠ¯Ïƒ‡Îó73Ôb‘ÿÉÿ¾yýä×_K­/îÞ=¿‡?wO~x"ã#ù_7¯/~s[áÒDW/ž¤ä…Wn5‹TW¯Ÿ|wG{0ðGí_®þ_[{-„Å:xóêžþçã¥^¼A¾:Ê%„Õ„ÃGuøÓñR.ÆX¯Wí™ß¥«Ú¬‡¯áª 0¬Ÿðg»ÊˆEúà·uÜq þðµßͲ®Ö8zã·ð¸²‹ëáË#¾è?ü Þ_ƒÖòð‡ã¥ÂçµQ |)„SÿwxØ9ë}¼©q8yøæxiᇗëá¿jÂ*߸:ñ”\}|÷Û£JTÓRSª‰eÕ°sq©Å↉|7¸"!¤<<Àdp™«;¼®_·‹ÏëÅ7íâß`Rb]|ü]½ÿ·vÿÇzñU»ø¦^¼Ã×üö‡³‰Àë·(h4ßÙî_ÓoZ%âHes.??¦ŸF¯‡¿·«ü[åçm{8„Æ]qóË/‡OÀ³Hv©50òž\ýê;²¨éò¯ÛÅû¼R äÓzÿWíþÓF‰·õþ³Ýy7»HžüP/²wLððuKHz?Î.íÜ iú9jBÝûFÒ÷ŒÑUÊÏwŒ¤HÇW”÷,„nÎÏÛL_ͶL£pq0dP²9Ïf4yÞ^âÓC6”fz@§íê« ‘N„Òd®×3š:=l¬._|ËFd’ó¸…ç‹K½˜µ6Ò,Ú8…*çR ±€Â1 žV!“‘¨»¼nü*s}'@Kºr×à¯K)µ],èiÚP€>}8â¥P‚õ :ÒhP¬0›U:…ŽÃH`¶øKÅ]P‹5ÊX˜6\s.’X€”*£]~E“xDkÜÎ;¾ ²øM¼j¤3‘sì² «ÛP7Q—{íl ?ùY{‡Ü¿†ûÒ¯A’)µwêºßÔ· M™ÍÔIó_`vÀ¬€‘z™Ìƒµ(×-Ð U‚ÿˆsn•‡ ”e Ýê}¨;¨MP0=…ƒëÈÕpÛÐÝ¥QS´·ó·M°‘9€¬ å-¼z ¶5ʺ¢ºö*{µ¤#§#ïáTã½Å„ÿél€W$Ù7ø¨†·òD¼Öñ;ÏÚgïËž'CŒl¿äóCPŒµk G›&Ð۰佇8X”H«ÒzhþÈ¢6rJ½ƒtUÚPj´‹·yt€áÊ®|ÄÑV°èɾ)yAÃà#e¿‡ì~óþäK>¾X ®¥?|Ž´r‹Ò>Þ)l,˜ç[<‹´J°É™ÁšøHž½ò2pøEÁ6‘‚x¢ ñ6ʧ‚÷W†2ö}±}%‘BÈ2ŒrQ—]æµ^¢=µÈî¸äÂA …)Z«5ËÈE©ÐoˆvðªÂ-”ðÃ;UöÅÀkßo꯺ëŸõ[…wq«@þ‘Iã?¤‹hmÈwÚK„Çï!ÙuA}…ûl¬ÈÑqÞ·y„ŒT˜W†*QF#-æü^èzñQ¢jÒ¯ÙÏ}—Õ¸;Ía´4¸¬Þ°à‡Ñµ@¯©ÂaœBæ6e;|IÇ¥Aá<&‡YÇG_ GáRCe#àx•>O>ºO-ñˆ³rsbFSíɨ0ø›ÒIjÀáÒÕ¨£dý„.õ\Ñö¨Êgl—謟Ðr°°PX jï}8ZpEœZ³(Ï¿o‚±ÁÑH|‡ìëÈ݇H#rÌõ}[Ad)Ìæ#Ñ„‹ÅÕÀÐÌcQ…4dcœ j(›k®aŠÉVÃ2N2ZTHÑ@Í—É‡àš ÐÇV¨Ì–|UöÃn½Ç”‰&ʰó£TnÙ…ìWlÚ™tÎL¼m?‰éCÓ&í"§Â@FL„O&B.¡:JÄ÷kœé™Á~ÈNmÐY!9:ÏèÑêMGõœ1.ºlíÂKjc:7”ÉÁÄ–iGmYqì:[†l¡å–šËG¢w¯¾?T;‘Í€‰¢+±ú¨ÌÐK "’é Ñ&ý4…Mè·&]h­íl&–9CóPDJxÜr|uu7ß2î½;.ZsÜ­QÞ¸ƒŸ×¹ÉÆ!±þ<ÆAjàC«ˆå-Ôk‰\‰P.}…L¨¹KÚ¯‘Å¿ÃM±a{†øqï$, °Œó¡H“¦¼°¯*¦é]8üohB‘±3›½I¤C‘ ú‚ó$òìjA­ÛR’gAä0}ŹF΂Q”]âø¼dn:–Ì?­Y‹²Vè¥Ñ Ä(Ê:x©m"‘«„è9u1ìá$’Ž{¨ˆÆž!²’ø‹ÂàtË5 àG½ÓßÓÛaÔõ§õ6xóÛzÛ…¨·‰[U¿o?"ã¡ÙëÂ;—Âò©¾f~Yö’À„(]Yþ6ó©–tEÜ[-Úœ©‚ ¯2Aû$=J‡9¡Ñ¿?ÖBàda” 4:y9ºIY)¸öà¢P©r7ñ×›-Í0@È¡’ŸÑš{@®o²kàöÍxàš^‰È"ÍLÜSodr“8}"¤·ÍåÙ:OÁdT0G°Än«+U'L¼¾6þ{n Å”>åÎÌèðxp)¯7©} f/@ÊSÔ má«Æ–M'× –»ûCwÉÉ ÓB´@ûˆül1}&¦¡£p*½Å"Qç2R¬Ø‡Ï¿wñzI£§b(Ò“ým…ò!kÏVÎ?WoßÛIyÃȤ§>Ͼàà'˜àÛDGÊ{ü&ƒ¥~ Ìß±7 r…Š˜è³añ•i1ó_:~“,/q:É@Ÿß&6xnT]îÒZSÂ'Š˜¿šRîBõ¼Š y5Ñ¡°ûž`Ã1·ùý6“×’@vŒÒ˜I!@,‰ÔÇðwÒjú±N|Ȭ²ãϾSã…(…í¿>gqD"7$O;• Oc·4¤_}®ÉaÑïÆ—?DnqUn¥5×þ¥ŒR‡û=š,¹‚Eþi&Ëæzó›H2ÿ‘¥Pœ]ù©až6WÔ៨}ÔN`Ï›9Ã+pO aÊ'GáL4L­2Žx¦¼ë3&IfÖÅÙ%$˜t©lÀ$צmQ>‰sÚ„Ê1`‚ àe›€Ä@cQK“ýd",Ž©4pÎàú9èT™ÁÂ&š®e@ž©4.ÌÀ\3./‰d< 9#‰‡1ªCX¼Í@­”K‰jé¾êìY ,⇪ƒTðÚmØ>Û.íÌ.»0–ðˆ¶+¼En7“`]«KT²É±ÎÁr|2•t®Ëêr·³µR+‘ÅJŸæÆp¸¬†å%XaNVP*G<£_Z~þúh+Zàõ(`í,†ö¿9˜·t@®nÌûi`°ÂÙËñÒ©<7A’ÉÀ—QKé7JFFîk…{{ÀnÊKï&ÑA’9xL¤Ÿ8- Üíª•_4ñø.¢á, !f€8ÎL0ž÷&¤@çÈhEO'UWˆ§+ßÏÐXƒ´ƒ%#:5·Q}´þ2sýJ ¨ˆüœ[¼(bTl :ƆäfÖa ñS6P¢Ÿ‡U•â½²8"Ðõå<¯Q3´(^¤q¨Á™™Ñ×V&5)³å Ó¤ø§‡8Ã¥hd;»K#wÀ¬ÂôsЊ%ˆs@Òù,1y¸OPUJÓ|3ÆÜ*)3v­cÇ«âE~y ÈqÆ×à(Öl¸®,rôb06š kèÅxƒX2ÏnGŠìwpãä…@dGñT!bðá^æ!±S @FÂ÷³"¨Øè‹fðoæéµâ!|Œ²™ËÌ÷wk"» u“¢pK¨Y¢¹Bµ“¥.[~Nl7…¼¨b¬71ÆœiJÐîáØ/O¨Uê~f5éÂÍåæÚÑÇ{hÚn(Nf';Ê‚9¤Èc¯œ¢ÛÖ­p,H²1£›øZ¤ö¨€D¡¯„ÿ ßL…5aV3SÿÔ…yÖq’÷'é½°R>_FyÍ%¹ÀVþn“K é|ìS{•bÛ0¿Ó6å·ü$VcPœpðH;€Sãq*rô³f”gÀ÷viN{š³Å}ÔŠ‡U£Žçõ3é®eVõÎ'gt5QœÑIµê0º¥g }¥ÌئtyrëzT¬ ìJG›3õM'"W÷lnÛjç×fΊ›ÝÒ‚Õ\-G?Žqd® ÙR>ÛüE-Žk.iÂzüD‚(u‡áw³šÔoŒuÚ1ksP'Ö¶Ó÷5 =³Ò½E¡åÕ£EÉœ&{Š£‡#ÈIíª ÈkAê3EˆŸ<“×ùI0Y*Í¢e=b´×fÙå%Úü²DEêq'w¨P.…N¬ôœ åæîÄŒ S0{x´ªRÌìáŸz!¢õ`XE?ÓÃe¥z]ùéT×–97-‘ËÅs¬´¶ØÝÒm7„q*ëYelo ±i¢ÃéÜN§³‰2ä+yiž7'‘¶Ú“/Ö,sÚEËɤSõü«¾÷¹9Æ8ËkDÅgH¨˜Öz;i•paÓ¸¡bZjŽi¥¢€Šim—}MyúS=6õm¨§OX©¬›µÎ¯j¯‹ØgSýê† (£ñtÎi÷¦ù€8Ér¥n-K’? ΘÒ)Gµ˜¥”ÉyÖÙ˜ªÇa):zñDƒ’š2JW…I`P ÈF­‚W|Kx!~"wo~ œþ¾écR÷ÎÊ-K¯ °(ѵ|"*³F}…k,iñi=Šs Ö¿dbâ™ Æ&¥=°>}2½ƒ9C¹&õ”„‘U¢Mʤž[ሠAØ®$Ÿñs‘°™¬+t¯˜¸<óvÊ•½œŽ öe…“½Ý–©i({ 0ï)Kî2  ·4ÂcuO3ÍV­(S~HÐX4™W½W4™G©Û·áÆÜ“_œxGoö}嬿¾¯Ùò%&÷«ã(+뙕É{ØŽÈ·|âÁ[¿å«ÓRðˆí£=¸NwКžmº$Ë~»UŽD7Íà$+I¦Ç=ŒžF}«äx—ÔbOÐl!zÕŸGˆv£¦˜Ï6B–±³´5ﶉ¥š ˆŠgOmV¿‡ÓpÜ;/œ?)75óÎô’î¡#NÝ*Žþl7€MA°1Oé3ˆÝ*÷Ǽ ªïiVðDÙ rí5д½¥Ä¢œ1b:9ÇbMâ¥Wö±îYr¡·Z{isÀ賋ˆÊæ^”\Þ2ËHR0+§f½Ÿ8¡¥m¹éZm·'vQã¾Tg¸`Þ&–¤É/«iõ4iU 虜Ð2µ>D”·IÍêiÛ/1;¡Wé°€ þšƒÙY¬[ •æi³1ûS0Ž÷û{Ûnw…û‰f&çEÊ0cWh‚§Î`×#ÅR#—àÕEò眯Q´‹®ðP“‚ ÝítFftxÿŒ¡@ST9Ô,&¨cŽUôÈÍžþm$QÎ\#o”MYÊÔrK&i±þ9˜ ÞÌ‘"héMîŒt0zŸ¡Ä³ªâýÆ_4TÊSܧ®Ññ¤r‡+•ŠjB‡Ç–ü_a”Àìæ&ȸj†’ÓXc •›QÜÆJ¼“öéÜŒmÆ3›ìÁÈØåX“sbÜÜ‹€<€®³Oßœ‚ã7"nšÆ9øí€ÒBÌÏcc“ÀŸýÞªLŒ™`“+£‘°!çõ`†ÒVĨ÷¼1’¸c¼W¿êúRÕ1XÆ·kk] ÑwÜå û´O?ÄgØA åb}²9Û&™‘™O—?/–s~…%Q“ÿå0ÒoáqzH ¬¢xfq‘tnÜqÄîš ˆ"ÉE'*H‚¯ò{–Lê¦2¦JyÞ3©æð=¶Ùšz‚Z“ <£Ì WÚü±Åcñ½)rï¸GKO »þ´Ñ]¨“ÁSV±„;?Ç9€ý¦gÿT¢lŸo7Ù«GkíB‰¬Tñ,ƒ~ýBžVh‡S²$ÜÛézÙ;¯3¶&…+zÔyVÚ—þéYÓFWÏÝŸ˜Å¯ÈPlt1Št 9l¶{ŽH))Qj£uk~ºU)&4cIˆ—¹´–+¨“‡µ'\ƒ)Õ¼‘ËÙ±ö¸ø.Zõ-ˆ Ú§ïÏ€¡›¼fzp¯¿ÅÂ`çNùIe 4¶ÁTMdÆ>ÎÄgµ_eúpe¿Ïù˜Ð0œ§KDUö¿Œšÿ(OCùtÇýŒÉ´®c6-œM:2[çÓoÓܰåñOíoz>xùõËc¬C+ =ih!wö2@kùØø’Н/ÙRƒ¶ûc½¹é´•U¡bäu£i^‹äžX5Q᤹êlˆg~{¿A0wc¯ÛDZ婓„W Wšdã•TÄ„”‰cä ÙæèE`|ó˜ÂNAî÷ü”î훡Ú×þù/Jð쯗P UuÍZ½¨ ï³í$fty¸²*í»Ó£=m«8÷d¬F‚Ç´$O°VàózŒ­ãï:xþL°2?] áBˆÇÊsä]'é_ìñUŽQËÉlu .Dø²¯IÝì=ÏrDJ¸²õh±ý¬J®–àl”BÓîÁÑ*ÄC²åIqœfß²’–´0ƒÉm®_›(¸Uí*RUÇêÏH8U¾9ÅŽ*Pàhç웑nvÒŸXžéÊœJ2A¸.ÂjAFɸV{1ЂX¯z¢k…òKÙñ+:/i“iì {c·í„L]+Ã1‘I"â1‘ë:-µ#C¢M¶‚•ÄÜñƒãá¡Q-Ô¼ÀŽÔ4æc•ø`%‰Éª×êoe0Z8~~[ãed" ç³a„…XxŒn'¹FÙBr]Ò> stream xœÍio%Gñûò'L0/ì›ô9Ý!ˆ#Y"‚‘8$¯Ÿ×kÅöó¹Ù ˆßNUŸÕ35ïÙ»±«õŽ{ú¨®»º«æú@ôò@àßôÿñų¾’ZœÞ>/àßé³ëg2t9Hÿ_üæ»ylêG1ʃÃWÏâòÀ©ƒÁ›^ªƒÃ‹gëäÊvþõ+Õ;çth¡aí…è•vÝW+­z)”é¾X©±wƒº¿®ÖZ½Rc÷ÙJÃÐÁÚî÷«µì½GÛ}¾òC/„ï¡cZû_c‚)×¢÷£pb £þ¸RÝ œÙõjº?¯Öxóe›¦ÑÆw¿ “»q”i–Q —š4’®¿^¢Reà¦]¿ÀV¥Ô0@²GoÆþ! ÞSœ+ûÁZ7 •þé•ÅÞëôv­Eïä8ÆN¿Y™^k%U·]­•ëGo=<Úî<àz#•ꎠù`±®7Cèt¿ùÞX @ív³ZãœfŒ#î`÷ÞJ†éå Lw ƒêí`»ãÙfè–ÝKºÀZ+Û[;v÷•·ˆ&kJ›nƒ]á­º³¼ 2i„Èiݽ®•é%™è-²…žâ_Õ¾d‡µ/„<–õ·dcV·pi˜X{2Wy»jîwƒÚ^Û¥ŽHx5ê^™+ÊÔuìg«Q‚HXM)„›«“NhJ6’†À»^«(Æ€LÝ+`(ÄkEçUƒï.ðÍ0¸!cmPbD 7(hRf!UÒäí(' ‰ÌlîȬ£5äi»”~[':+o.ë”§I6ŽÖR0BETæCáð £FïŽD˧”Ž£Õ„å‚ª³ßèÕ›•E¬°w!r[_VΘlyéç©)j-5Õ,Jõ#ê P7’îÜ#ž…Òá¯çøº'%À‡¤¥½áW+F<¼‰?E’‚nóC÷§Òˆ=(GЂ¿,ð$…]50bãe¾-wu¡“Òx]{6`çÆóÒø®®Ç¼ƒÙB'N°(‚Ô×÷¬iwÈ}ÿ‡µÃ/Ë#ùÐŽþàðóg‡&lŸ$Þ–uoqƒÆ¡ªXáב—t ¬Ð!Ìs·H‡Ï+L‡>ð­³-öÏ9¤ÜÖÆ§ +Ç÷¯ëû#½•Æ“Úx]÷O=O$Ù'O¼Ï÷ïã†x=‘9sëÇ I OñÇM&&‘š»B`”öÑeYizº›¦/öÐôަ§uÐ G‰J³;«“=üH–lö~úp’¿ØGòO(É‘¨Úw‹þ“†ðkì´.]´ç¶ðü:¨Ñ ­oXj~QWúŠ£æ÷¥ñ{NSÔUnÚÔFèé5¸äàìÔgW¡¿žéBDèïÚar¯Ót?©­?áç²ÈÇ)#8gs— § ðw·¹wÅY:5¥ýEi„Üw~6„x˜Ù ­‹o2ˆaq]Ö€UùÀõ¾À“åËöö,$˜M?¹ý G¯›ü#ž$ží8޵J:<*ý>ZAŽLÉEQ=Þ|Yë‰í wp\žÈEÄwÌÚÜždxê‘èÒÍÛÅ*]q’ƒÖºÉ«ü"þz\ps×¢¥=›&Ü+~8CƆÛîñva·ók¼`ð"\~ô4gëyøÉÅM=Õ&çß,€'´q18®8[˜½ÒZZ't瞆;¯¡û'°y´Ôä¶u[(}_Pƒ¶rtá:àMWúÔã÷Htdz„u “×eè~Ea8¤$Eõ1·o–+XT“‹žv&R¾³™À”ÉÍAƒ½ÛÂ5—3,8­ëßrô»|<Ÿ°wЧ+†56«øpÞ†KÁvN2èñ¸â&©‡xO磦Ø6説[Ðe¤SdcD?˜ÚÔÚ¢R 5ðwW7tò|³¸‡d¿ÎzLÜN&%Àg\¶;Av?w^F6hn£'š›Åû]ysÙ*¼“Òv—¯‡tC³ùûøï©Çõ¬Ègï¹  Ÿ[gíƒh³SðQñ2ñ]}|¾SR``6»Á}'Ä YßeKHtStsÕÈÙöÆ€a*\DûVʵªnž¢ÐR®\xEH÷ºÙøÜæpô’±Ù$?åŒò@NkØ#€A]@D$¦f€Ñ`“}î'ÑÓÐe"|„.{øû]èB°]q|Ï; rF`Øæ”Ã+8V)°¹Ow)ËÀ;Þ 7‚™³RZȉwœÉG&Øì¤d̳tShuO!‹Ñ­ˆ·F›ÒçÛDµF<Ùjï‹úŒ¹+áaÎàÛ#‡Uó-Ûi!°y"×½^U"³”ßO/= 5¿„CÎ*þÏßYÖ‚\½me­:âƒuVdë¼…1:¿•;ÉÂW@øÄá"¼}Í!|I4²°0MÒ&ñ"ÀEw}vݰ c©‰ãË‚¶;º$Ÿ9+ç¼ÈÃiqš‚C6uúxä²®ÜEm¼àÖ¹¬ÈÝI5kE‘tÍ•µU¼³Š¹(èÚ´È­qT6ÐÖ™Ìj5&nêîÇQbÑØÈ0³rÏú]S?ªËü­t%í¹Æç¥Q.ô¤¤­l¬„“˜SÕ͘å K•‹9þ÷êõI¾hÕã!ã1u,”(2NõI¶ÕÒ•ÌÓ.[½ÙÃÄm”·ì¿/‰¿äÞ³(·\ωcåƒ} ^ñ.óÂÈ‹B• ÚYyq_žˆ0]ÐŽ<þçz‰¸ìßµôiMïGŸ·ªIÏ{Ú8½/Xü¾Ý‹³æ}rÜ lª–&'_oVù 'ú°·3lÏOvˆ?¦+Ìõøƒ®{RC÷tœqd;¯QƆëY}¸W¬|É¡£9€" ãB]³RÕÒ­À4Ø’Îñê±âµNãÛ;¤ ùqçxÐIðc ê~­Ë¯ç­ͧ8ZŠ Ž5èûGõŸ3‚·ólcr‚1aa’ƒ[ ¼Ê¯ áf ßõ‚N¶-o³‡k,w’˜hzÖzÔle"É›ÃÒUžØ1ììêÁ³×žÈ&Æš òz6ïú¼žÓ4ACŽ$6;g1g¡ä֯놕òHOe§Œ'e¹ª¬—”b‰è7]©Ž­”òmÇ™B¯Þ°ä¾åpÅ5^¶¸÷.D¬dï„Øxí´ú·Á÷ï‘sRÑÖB„#;;Lý8Òù9ß¹%ôŽdü|EÇg2.¤GÅûëz«Ý\ÿ`%0ù FÍï¯Û‰hnqÊávLéh¾7'‹¥8X¦ÜBzFLòUf’ýCka•ÑO¤µL©ú|!¦YÌlÆìM KN!7ùÓ‚YÊFnc`ŒwÑ<'y›Û”A2ôªT%‘Äjri>¹ðV.Îsù+MVZ¬ùõôÒ-…Â+$9½·Æ›g’Èe8F2Š&“4”\`! ~qE’ ªri6Y¤4×ûó@H®ØSöHÀU«/çYU8$æ²m¹´5¾0°åÚífz…uù ; H±¹'m}@ÉÙ¶sÁHY`àX£û?—rS+¿5YW¹RÃØ”nÍdՆ̙˜Áð‹UJ[ðeÑ&ןtÚù҅Ïz6ÑPìcà˜šï{iG&›‘¨Lýÿ›• ©±\*¸¯hLÙ댑6‡—d¾ÀïWHŸ;¯°À4+.OoÂù!»Â$))ƒ 2õ>ò1Êžµ_ù픲ÕÊG£ØCOD:›¡›«oÒlŒ ¥7¼yš•¸ÈÁm© /heœ—´*W¨HAJ»*䬡ZH¥ú€‹dÀÆÎûEÊs]ŸŠ½i9•Xé ùL4ã6°‘½|2I õ¦…„šÖ(|¹ >@rÎ&zˆH€O{Bò‹`(ÅìÊ{LÀ}fÇ*4LÞþvæâ’‘hÒØG’X•G]E™x’挆vÄEq›„€á]½9 ‹Þ\JAEÌ ÿÖU·­6JË8 úÕÿbö6%YnûºTKöÉ6(pJòíרsRCJÊqÔ Ó$XÓf†'É ¹÷¤Â”ØZ9OƒMy‹C¡°i¬0tʻżX¥õ÷( ÷`€g¸orr“yˆHiÍC"J®Þœ—EÉ(Ìk$ýPÊ,=½)@,þ…'w'hëG¢©;.áœ)¾gr¡„#%RL7Ôòœ,ß .rùnò¡’nÎ|o(oY{ZLHF¡QC/Ʊ5w´â+}ü¨‰obõ‡!•z@z ŸUËÏTSªÖ–šÌ4éµ­aµ!g$ŸsùåMŠë:íj‹ÿpg…1ñ1õSP1¶ê¬ÔÏ+ÔƒXºÇ97jA·H¦ªû³|»\ÄN h¼ =²Š˜Ùÿ€haq×ìcUQ§ʼnðh+Õ^8¹Ç4ä/EIÕk£– H?ö+[y  aC%:Í̺t¿*ºžÅ‰ŒO<ßsê¡ 2æë‡[(ªêZ§§PeV±Ûg ¾‚e Åä¾#Óý$SΑ”ÄÒ⇱òÄU°I9Ÿ/¥ÑYµ'ˆwMZa GÞtü~}²ð‰‡©7á,°ýtWóQ„ðñ8C9ù^ëøÓ4®”º˜Jów~}NšPcõHqÊ"Ò§Ã"à.òÙ\ÜYc厣=©¤ëØ8ç¤TËzRÿGù¤ÞTìðàÇßË3)^Ü0«— ¨œUè/UQpŽTý¶CQ#!ç‰òr Ç”âX?-å«Ey‰u`í×!f%y±Ó0”²,1F=ÂGŽ.¦ì³äreöÑñÈ´u¶8á"üž+ÈLó]‚×-©9m‰*`Dv4 Epd:2žzW̬gsáÌ › ¼B £S‹â— Þ8«Ò(æãy… ‘ cdmš‹»€DöèæÓ½l µ·¶ú¹…‰¬£e<ôÇSÖŽãö?=|ö'øû¯ Éendstream endobj 1025 0 obj 4949 endobj 1029 0 obj <> stream xœµ]ésÇqÏgDBð{±Ü9vvÖU©”dÉ6S²¢Iœ²ò$(Pe’àÿ}º{®î9ÞH¸T”–ûfçèéó×=£7§ó¤Ngü'þ÷éË“Gß*cN¯Þ̧‚?W'oN59ÿyúòô³sjæáÕ´Í›:=ÿá$t NW}ê¼”>=yò·Ú/;þüßùàg~ŸmÛ´8øòüZÿaf¦uÝ6µûó^MÛæí¶ût¯w_ïÏÔdí²êÝyióExk¬ß} oÕÝ®4ä &øUÛyÒ–7ükî·í»ÿ Fû|o'ïëøŸCs½Ljö»?îñÃÕ­»Çø»ßŒQ»/÷gÛ«'‰:©ÿ;·¬+ýh°;µûn¶Àêüî÷zšçE+úâ|ÄÓʯôí_÷:RMû,’íÌÌÓ Ïzßï`(ï õ Vãh TÐ8W³»"’Ä¿<Ä©xÈíÀûï߆ùØmÙÝ„G7»Ý/°¤m4,ù_‘¾jÒ&’6ö£ðµ…ù¯»ß•GèÍNÆØMï. õ«Òãeç~y qVgóäÙà#Ì6S›us»ï÷Ôz5çƒ*5/°¨ÝÏekŸ—Q4ìMœà ˆ™iYF„¨‡þmŬ»Þá;Ü‘e÷>OLŒq™øöBRàY à²(¢Íø×XÉCÃLÚŸöÈÄ+ŠLYÔÓüT怽ކåj›Ìa€4ûm±i¥Èq>F­i¦ø6’{™7”*k€'`˜ @^+›ÖªW‰‚ݾCöñ°ê´!Ô´üþ‚=ÁìÜV¦(ö(¾CнÏSy$ vÔËæL!¥gèóÓÞÐ&q™xšŸÞg‰I”šÕd–´ÚûÉ.ún ½®@@ô:-v6œ‘^îAb¶f÷ƢΛ‰çÂâÞgÉx.™ç=δǶqŽÏ\ù¢<@;r¼Éaa®3Œàù ß¡F[–ÕiÆZ—8™ xQ—Þ_áî‚6Õ×ýæ “™›ž2I(¬‹“òЙµG…øU™Tyå„MÛ$"™ÙW±…›PTøÂR‹+\#ªg/yðéDÀâ$Ÿ#Ë€ÂgLZØ:¿RßEþØ4mãfÀ²(Éwœ×ŸaLûæ2o«ÒkŸòiäì(LAL}HR–ÍsM‚lÕV ^‡‘c'n¶¬mÜ{K«-ļ–â’ ÎÌ5Èè—'ç¿û»Wh;6”;VØ¿+(¬w¹¡¨T?œ?e\vÀm– ]ü‚jlE{A¼P„]}¡Ä!ƒ]Šs­Ðq-‚ß]æØgi*Vñ©8ØQÆÃ]!ê0õµð]ðS–ÕÔ:…ýR}“7ä×2©‹0ñÍ "ÿ…„Ó'!RÅ:C’Y܆@¦õ±ÙM±+crzEïŽdèç#f)/hç‘êYƒ9]$ ¿¹.3@Á+‚ûe2 R¡Òî/¦Ø£@ƒ3IÈqðÃOûÅN@^?ThÙ jîN5ÚGaM»–èEaøqV`±"]X´è`ïèá‘rç¥A%Ñ­aR[46›^Ck’~ø<<Àc6Î3 G[m :^«;fÑ…lj™ß<#Ìzþö‘tê‚#/hpÙÕ²%y¨úC—@vh´‚>£“™ÛڣݤÔ"¿â™#ó,"òŠ[›øeÒQà.t½¹ÆVI©Cݧ-ÉÝÀª…qHl­¤º£Ü$[lŽ·J¡±ó©ŸIwßÑî¸_µd8q #g@còΘaáU£»Ù2´jt7‡tUk“’P1v@5îs;Œ¿?«Ø®£zÓ±Ï)l7ä£X䮕ïÄàeor°³_›ÇZqÕ):|ÕÈAð‰ÍÑ6ĘiZsØô$ËZ³Íadû1’ÆÂ#g0:\vÿ½ßæ[9fZO`r?88í†(䤶 B¦âú¥)b.Ûæó½ºÔ(S3[Ï-»Ämæ\Œt²ªËBóºïWXåq'ÄîÐ;åÒT†s¤Ë{Lµ_!—/$+V[ ”†ÌŒýoÞתì‰YÉ‘Ý!ØZ®1aQÇ\¾CÚl4¯î¼EèɤШxeèc=›f¥_ñ"úÚ ÃD•žgR±n–6•ÖóJÐóõ2`µ#´åŽ£X3'h`,ÒÌCÒ xʶ2 mõÙ'4*ûÑ:D׌$7 lqk~Ð07©ë°½a¦å²|–ÙêŸ÷è•h M$ò€Þ÷L€R Qï ^Ç Ez ’j„ìNp‚ôjÄŒÇdÌ“¡6!VÑ~aRh©´ZYÿ]çu„a¤¥$ÛfP)nµm#Ìk^ Û~tlM ´´h\Döá=sÄX× ?éºJJ3óI",VฎMO@ò$æÆ sȹ€1Ò×b˜e;àÕí$¾w„Ùq@×ΞŠm &c©ÒU¸q&›'”ý@¥nÂ…Žu½6Î;èe8ØÙh±tÍíÛ×)… @÷k |ë™ó&zÖM”Ãü×_ð1–"32Ôn62êt2wØšzCØáuùHÆ0¸Jg¥$%×vÑ2¸/O‰ œ“ ™Kw‹8&QCJƒ¼»®Üh±6tBû16"ÃØã-x庇Pms¶nutÔDÁ»rÝ;l…QMôU„JÎñÌ½Ž˜ ‡×d8?'ªAØ`+BÄ¿N%QÓµjLM`¬£òò(SÙôOáQ{`†^ei [­6£ÓN#w6f6.ú ÈqH~è£pì³Nj_§X½ø7dXd=GÞ“åC|Ó‡ED§).$ÂD@éž½ìÔUð¿P'pÓ #}Pˆm3ÇU_‚“n£úžÐÓƒFh¸ïòw™¢voÔ™˜–£élÄlô¼¨¬o³šB‘^”J¶3Œõ°pß 794iÁ }/ßt`DÁý1pØXCôé¦bÔK9Ä„0Ûø,]+åyŸ”_þGFMj]š…B×í÷,,ÍÌß>,Ñ“bÕz®CÔ¡Ñ\”½äâÒ „s_ESåWèM`.xó缎^ì­L*#ÀÔ[ò"C"g¨rÔK K]œ—".fÚ,kai–4M`ή“qݮʢÐ^ã/v_—äéôe7ÕÞv°#15”óå€è†ÌŒE7– Ý‹(H«COXÈ_ÀB³’‚ÊéÎϸ>îË¥¢Rïi7œº/ƒ!}§´¨ÛxO)#ѯH`xMÊ [2(ïîÉÕ¢ä½=>—^ác¦à¾ãPUlùõž°nÏ^}•) ãúÈRá”J„zøwJ˜SLAøž6è—;<9WVÃõ7#ø\ o9 9NX=SJBÐ(‚ßý\H-Þc\áÿÃfB¼5VÕ#a Òxçp"w÷‘R…ÝÀz# !ä+ÐPé¬L³cžG@ˆªÜ¡êï3 ÅÇ !³¯#o§˜AX„2Ðì`UÈ„U¬¾´=ʼAwÜ&k–mRs.áw+ï«cozÂ"ÌÚ˜d%ós” ˆ2}S {‘d¤æÂ>T:ÿè<'ýkÊ,ÌŽm>ŒzImB=‡àBîøbóÌ /Q‰jAÐG›_VÚp\.+ 5JVo›%äÓc¯TúP¢Ý„P¥ò?¯keÝæ Œ(¡¨lÏJB_uÍMã;:à3¨¸èŽ0‚ôݺ‰ Cˆ'H,MlH]–ýp,+Q6­óûÏ’ãäHBð€uê]X®2ŠbñÝì 0,%–;uÖR©ó°ÌÖ„ kdÈ[°î}ñ‚Y¤ø˜›Y2l7s£Ãï &¿®²iâ&¦¶ªArÙžIMmÁÞöÈ H^E€äl1?”__ðÎÛ~z4òež©e]*ý±4þ2¿üÏòòÓá@íá~ä„k/=gÝùY»Ñ±›,z×r^ÒõrògžGwSÖÓÎÏ»w¢ÐTn`7VÚWJ{k=[«tM4•ÖWšg)å½–;7•‹¨\èGdb&¾pè"1«V"é#k»Ý}`uq [Ë…NBAǰtºÓŒì[žº`§ „¿SU¦³&Ç”$Ö U*ò7(⯣*€]ÅÊÝÉâ1ñPù¥í½\ÊˉΞl0ôþ®0œ×øUL5C®ù¥*/}yÔbL|ÄÍš·ð˜@[ZïeVnW8¥ä´^—Š5xÔ[4›ËŒž¯×²§·å÷ëüÜiØ-"ÅÓüò¦gBØçÏ„Ý`v)(BS •q,¼ŒÒoü36ØËB·'ÝÑÞöIH6ãÿUô6Ò\˜áœ–á#^öŒÄ‡­â³üt3R?å—=Óq#Ö g冼ë tÓë),‘ZLãŒVÄ8§Ú0n#a¤E½;ZQ?k;‹ÛšÖJê’V é†0±£îËU¨ëG#Õ¸4#g ¾è€pÁ‹Z]G—ǺJª‚˜ë˜“7ÞñÔR{™ËuvPk\”ÇRÆñÁôŽ ®.:¯–8“] ïž’˜l¹$ _tæÔ±Û7bÃVág “F‰—P<ØW÷™éÁ¢•ê 1^¦ «%ÏNmÐfKáŠÇ?Âù^£ÁJ®èWût)3'±¥à« ‹ÏÒze:~úÆÒEÃåãј#p¶{ÔŠj-‘ç8ÌN·ï®Zn€fðà Ùô-ܦp/Iìx!jçîL¥+Œ¦ë~;™¹:µ¼… ¦Þ)Œ°ÆxwòÄ‘nt^šCaì.çÛX»Ü˜KuN"øöÐ »_6¤ Ó5;Òò„c 4\©ÌÓÇEžÚ4AþBs`4S÷\‹U+³§ËœZC“hð@Z2q‘ÁV‹ŸÅ•»±ƒ’Ù¨‹aX•J}´„øw%˜ Æ~äÀ*:ñë|¨†² ¯âæŒ|‰nëÖK¨«ì»VB„ÃÜS¡è 5-‚—Çüd ™i"ÖídZ£“m¨<ž®'_<÷~¨^å=?æ ¥<ÊÎ6IÄ5U„¬mdO®±ùç'ßœ¼95frôÿ,€YúS³‚‘/7=}yòÙã“Gÿrúþíͳ“GÿsªNýÿõÙ×€ÿ<þüôŸN¾x|úÍ]ÿ÷X sE…îíÿ„Ì0íq‰´™w€™‡‹g/wù‡/Òe%b‘:HÖS.Ó(4.¨îê^rëén%^ÍÒÞY*íð ½n¨{’Ù!Tœ bfÂ}sòÿ€¸úendstream endobj 1030 0 obj 5851 endobj 1034 0 obj <> stream xœ­[io]·ý®æGî‡Þ[øÝr_Ò¦EÜÚA 7i Ð…lÙR`Y’×Èÿ¾3\‡¼|‹ÃüÉËËÎræzuÌ~Ìð_úÿéË£?|Ë¥<>sÄŽ¿‚Ÿó£WG< 9Nÿ=}yüà‡9lZ<óüøäùQœ€[qlœZ¸8>yyôŸ‰Ïzbð³Ìb±ÖÊÐÀCÃÆ1¶i§og)Î„š¾™…_¬fúaÞHi!üôh–ð¨Ñzúû¼á‹sÞëéñì̘›N`àbgrzˆÝJi+`Ê [œg–úÔ׳˜¾Â™í"¼™¾›7PÐó¯úlšF*7ý5Ln½çiÏ™M êÉÐ/gÏÆE^\?ôlB â‹÷Nùÿžü#¨ÞQ*Íã@­'gI• ~ô¬qô&õn$[,÷>:…WQ,­ùt¯ÒvQZL¯çZ@§LMÏfýBªé&5 ¦Ô¯¼Hý\ˆé ®ZkØÒx5 »hãäô§÷ Šú”âœ|º¨Z}†ýÆì7 ÓÓ/¸É‚)1]C·ñ°vz?k…;ï‚—ÙZÞѹò¢ßàc –å`®¢`òÚk˜âwy ­%ŒöYZB¤½žÁ`?Ý¢Õ0I°Ÿóó/çXŒ±FÕ¶ ŒóÊO`v«@_{óúŒžžÀG‡ê7dýeàU]Ï9 T¬F'MZ)[‘ó>ŒºÏf´á5¼”g{©‰ž›…Wj%©©Œð¸Á’f…ͽ^+\{°,eÖ#-wuëuZ¼AÝÄ×+™õÁøô4¨“FçI½Å”9yáu1|¬ŒM»k¹¡”—•±÷óãÁ©²7LÆ0Q½ê’l/î…³*(VêÅ»ò©Ì¢$§{ŒÎ¢˜$R]é|ÖäÛk|^/† `äëÐ9›U}ž>Ä@"¹l‚3W‹H ÞE™p±a—`øõÍBˆòÓ„æÀçà–¥õ´4^–Oïj÷³Òø¿ÚÈKã}ÀEû~_OëÈÃç͜ޅ,ð¶4^æ|V_Þ~UŸŽžùiέÃ0½©÷Ø&ØH"5Óºà’Jõ ³yòÓ÷ðóšâ¯û8ŽCšÌ!¬CÐ42^Õ ~ÖÇK|×gᵟ<”_ï;$"ÃjXˆÃ4ö kB[ O$Î=-(O#ú‰80 p+ûQ/(TÛ„ÔÜVçi3’€Œ…ë‹iÜ›‚ƒŒ–à„à ÑAÜ"O¦B]< ÑVr±•ƒmÑO]êÒ«€p¶.ÕGB!M@75h‘pV†’ J’C ¡×1EeØáƒ\uÌ%ùkyD}Áhÿqè»›±£Æb”ÇÁB”jtˆ«I[mXíÍ]*Ü`lÛŠ;x‚IWòo¶BHÚZ}jבBs;È_âT‹@jl»jÌÛˆS™÷aÂê8Õ˜ÈÜÍ;ËD'Ïð§zEìLVV·Íí0éa–{Ž1u⛄%1GDHÏúì$ûUT- å+ë¸n“ø}Ä3¸p’Æ—b ç±ºP« =݃¯Ä«c±ÕF°¼‡QýJz2A%»\žK˜A|¾—ì;K \ç$P %‰ž"ÈnÑ[ˆñ«1¤;/i” )@qI¶\Ò,8Ü; Ã/¨Eƒë`†iO•·]Q£¼ì†ˆ±ƒ³`ê Î"ð‡W'à¯#  „¸‰˜ÐÚ/ÛŒ±Û0pl ÆØ!pí°ªyµ^¬×4Šà|ðgµ²Vj Ûþ™!á¿D0F­ƒI] •=ö­}«žQ/A²|³Švwp÷¬öÔÞ€ø<½æs …W 'ÀqŽÊ1ü^BZ°°ÝV¾Ã_—éUp_Äš—yLAZrú þ‚ɬT8æäÔý]b_—ÆïkããÒøxˆaoË'ÄqiJX\õñÑÉï“$g?/ýŒ_3\¿n‡"ˈÚv ¦™ƒ1‚ÌF*Í}˜£"P‚+€½¬°LHúrú[é|X;•Ưkã÷#U­µªÊý÷Kã‡Ã02}¬ãMN…žÇêâ I9É¥û9_¤×D5D¾R]°p&°yà„!‘w*E‹&¶Ø.$0‡!PÌ‚!g|Ž_}@„)JQÜb¤É1ç!ŽtÁÙKì#Oo×ùe§­bÏ[èݼŠÙÉÃ0lÁ<°ëÖnñ£ åA0!‚¦+Ü–4]b.eH—š“ ÁP ƒBÎg’*_ˆxHò$Ö•!ŸÕ™¯Ý$òßK&3qĬI¦6§ïÏä(ƒÃºHtÛ±žA†¤R ¸b¶O[mùœ²£j:£a Œn6šÌÚí¤uèVã­“éÖÃl|@Zý1í»lV ªà€Å¶àÌ!Î%¸¬sedܬØê H€aÕwˆ1¿äSÅ “»¢øÞh¿®ÛéPúÕd‹‹´È.QSÌH&*bHH*³ëÆ .朔#Œ×{ ›5b é/³GóOhk¶L¢®µƒ­Â‘„‘F-ÖÁÙqv‡ŠJ— ‚؉û‡ÙYÎËÉCÎXêÒ‡çÄŒ…h0¤ªøÌé=²6 >*ƘÌ&gh7t P/Éoz€ê#¶¨þÔÛl`å^Mÿɹ†ˆ’©4Î,(£>ÃOhi,¯mÃt+Ì⬷yñæ°ù\´.æE°¬œLc2 æ‹X ܽ’32¥I¢#ÚvÁB k°;™{y$ïb¢juЀ`@ªÐj ¤%.lO%åÀÒfþHó;ʤvAЂ…HóTÈèØÆj’{%c¡Þ²[#‹%¹vEŒE4–Á°ˆ²°rvômJ¼rr”B»2FÃN^EÕ"`ø'ÇâOM¿­oÿǘG+±¿È5Qæ¡Ê鈲°·`„¸Ðòd“@Hja&§rY˜/Êt@ÜYè´ý+S$È&_Á«8W{cÙ·þs¿ÖÙ#K!R‡Èb¸2"0°RDˆEðç¨n‚">¦°ºnJ@|;¡k.FYs•DªdÀætHo6Æ×V+í^K&‚=Œ±;A2ÂGç§Æ¦—wâYœD@ŒûÞÂa¬jÝÖŽ"YT߃½ýçhÎÊZâËä: `åêú2M×ýdËÆÕ[ænu´‘ýa$‹ü Ù¿øNè‘ÁƒÊYI áø› Yl¤É¾3ê0!¤í=ò²Ö¸Ñ¡cò¶ ì ‡È™ÉïPÚ(€’¨\[Ýðkv ûCü©Î‘=o{ÃâááÇÛõcû-)vÆ·é†F²Òq5]ÑÑ€@hF“ ;GãÝAô%[ØoCˆdŸÙøÌv=ϹM‡ÑÕà«ã;.„Œ”ºã†R‹e3Š;ÔÚMB×7ÞÚrXêpÎåG$9QÍÓÁ|Õ’ø @{-/ ¯Æe,ÇÚê8É]¢ÂÚ:?›E¢©OçL›y—@óØZ‘Ád⹂Òÿí iðà© ®àfðG3Ìeª÷ô ô”‚Þy¢WyNÛSå›áúȵ¡xDâ†Ôò‡¢ÌÄze–梱œJ¸ù¬C{€*Í)¬ø’æ`-ŠÈ©@,ŒkúüàO¯[Hu>W>Lu‡ÕUܘjSÒ“1M•L¤x*9jOà,ÒSIªUåkÍ™€é®}BÀlÙÐtQ´/P2´ƒ¹ h(_²²Ýù<ô=‰ÔÛohlÏx¦Ùf-éfÒM»ë5~î¹Äw•H)ÃÃ_°ôGô3þ «eIÁ6ˆÌa€|<@S‘ˆÒKL¸Pƒ7–ÍßþDY0)ƒ^‘)œvk¦äÞÇ KC<Þs‡ƒƒ¾ݦv®·ÈEƒÊòœ×Æ7éÊ‚³WŽý_TâaH  «üCy‡àrwçp”ÂØ9»¢Œ?Jª¥ô“ À¯Jã’ï³PQï$!†7‰ VA…I˜¨E{å6ÚŒî©ÇkMñ Å ®[XDàg™{[*Å£CEI r”³å[=¿Ž§ mvs6„é؉'ulv¼0”*§~éñ½%^›UZå ¢Ew¿4=<ŒEÝ:1rùÈiì›·ÔiÚ¯ÿtcý†˜ïùÝðc\ð¨ÉÕ°ã²ãTnÚʆ8`4G}Ä{ã™v­±´ï<½æXrÙþ”„VIñI«+´17!¹lyZ?v©$j¯bÎw:¥wgïP©Ñ¢"HyØõ†üèî?E¢Š¨Ú'ö1È{’Çè™Á Ư̤¿þ©É0ìgÏÐ6q> ä¡g»eà{dØß8”ááÉÑ¿áßÿ¡JZendstream endobj 1035 0 obj 3739 endobj 1039 0 obj <> stream xœ½\ëDZÿŽòGléfNÂ÷»{"åJŽá&Ž€$fƒ%ù°fÍš›…µÅ¿>UկꞞsØEø0îêêzüêÑó㉘å‰ÀÿÒÿŸ¾¸óù×Rë“‹×wÄÉïáÏÅïHzä$ýïé‹“ßÒc.Í‹XäÉé³;qyâÕ‰ f–êäôÅ¿Org'ÜÎþóôøZÍkË2[ožžÃÓ_îözö~Yäô‡œ—%˜eúb§¦?ïör6Æz5Ögîǫڄék¸*ÖÓ”þÌpW1+Ãü¦Œ»‡³ÝÛ™9k¿qWv–"Lÿ·Ã½óÓWx?,ZËéÁn¯ðymÔ 3Ñ@HúCxØ9ë=ÝÔ8œœïö~x¦¿íÔ,„U’Þ8Ýó” žÞýf§×ZfïÛöZÌ~GîáûW°ð70cf|c¡zz +‚y•š¾C ýlí’Ÿƒ™¿ä˜ÅÒ}ífkìt]¯¾ÆuZ¼¡€ÖšìާgcÕöxø8܇CÃ~h?}[(4¾ÁÛ~–ÓÛ5³w*Lg0Áe¾= Ò¤I½Ö@ \´°¹º¾S»ÛàYM(–…2"]N¯v{3kmE4½¬]ì*9^÷,¯3Ïõ: .Ô_q0î•Ҍҗ;›îLÖ• ¤ÎÐrŸ–7pz¶ÔêôHvZ…—y!§óøˆò§[¬ÁÉöi6µYÅ“° à²Î„YJÆb\3 –.ó92>­ιïŠLréÌ¿˜Ä¥Ÿ |¸ïqJ=+e˜ð¡Ø0 Ù¼ùCd°±a8qYÅ3äèit«@^ݶ|ÀDÖ1!­›‡¤ž¶¿‘`úÇTFg{‡Œcô#íoVUF½h¥²\ÿY½ö´!íåNp‚kÐ?vQ΂ƒ‘YÐþ]Þ«‹c{Ù-š… †á"ÍjKáñi+«Itžg!ÄåhëgãØƒßW»É¸Ï¸vÖrí_»=°8‹›î¢° ù±ù©(®>½àTÕájƼÃ2ýDž"(‰2nF1j(MTEÍIüÛK\’HÚS­ò÷U;˜!kLl+ Y³Ó1YŠlR‚Qß1.ãB×Xý´ƒ½¸‹ãHØÛéO8 òÀ!&0NÅ’½Ñ>Ç; ZVÓ8ìÆ»Ù/‘ã?ŒÌrç ªþôÜcÞÓxC>°3`yQζ¾Žíξ¼pJ:Ë02LݘiÚ!&úŒÄXlná§‚ V§iA­==ýŠ,оÅ2tÖ*­K¹P×%3)¨²UcpßZ†l ¢F'ŸtYžcÞ ™è4 y]ßY-¾ÕG4±¸ÓË¢¶¬Hœ“7/×.!®ò—™ÿSŤ\K&5®•Jï4€Ù)¡ñ àKd}7";í< D€.qøÿ›g;¨óS+j`ÂVúmvc@À±µzh‡ÎÒmc:Ø=”¤_ÿ…G;ý®ŸQR w’̉Ö!Ÿ¢;5Z1í‹J`?˜ÎYV`–D“œ®–[^4s:»,-[D ÁaD¦[1MžŽùÕ•C*%©CžéXUÉû‘ÁFI4ýð|@Åøx9©7¥CÕEÂ"lyF;ƒf£¾cDmÆ„û›ÖIÝö@À¢ B4÷¬0T)ÁTÀ ŒÁ‘ÒÅ‹—õâY¹xQ/¾.ÑX˜%bÎß–«ðËB4%ÀÊ}[.Êú¾,Åè"{Rð'ã/Â2Ù+D8ÃÖó¬¾{Y.žÕ‹å",<)¸«Ä˜V1¢õÈEÙð‡f]lù£]¬s¾ûDsn¤)VB0Æ€°[µ5U¥Q#/ <¯ð·XJ=0ÉÆuc˜í,*WëaXØºÂÆFw›ÌJdËVtÀ[¥®(‹Ù"@s"Ç@(AÐÍš†ˆIîĬ—Å›* ÌBXÌ|I8~[nkD© 3=Ù7»Ezà Ü]1³?`=¡÷YZA¸¿ ô*&cfqÅlÍI÷aN™—y¢kX’ó ½– ©<¦…ð’–¨ 3rzlQxTÊwÆ?Ù-b˜ÎáìŒ2 \Ó–=qµ‘ZLÞð{Ái` Æi+{C¢å¡Ey ®eP&ÄÐccPõó<Ù4ÝZ¦ùu6ÒójuÒɨlh€ ôL›††ÞÂëŒCŒp yd󺘌 Aäþ(À‰Ù˜O£¯?”ãÃi«]©Š›×HÍó?ïiArÑ*gȼdf_Ä4v°7µ¦`Ç!deY¬Ã^,ÉFf6n;OŠ!\ZP„loøÚH–˜ÕƱÉD™ÀòFh¦+Nï“\¢X0 É$:\F=f“hKÎ&5_¤$äa9NÝ Õa46VC §Œ7) uUö¡ª¦{Ja²ñR·‚sÑØ®:/ï>”MÛ*Tа„¥À€è’kßf×ùÊ7ˆ©M:l¬¶½QÛ“‘c=XtbV¼OT·R»ây‹zX·Ð^ÙXßYó\™X8½äF `Ðl”â,4U¾nC©¨*»UQ´¯Ã åÈË1ðÕÙÇ¡Ì"K@ŒË4*«ªgí?¹6ÆØ.¬íô1Å€eP™ìÛ¢«ïq’ÈáM•ƒÝ'Á¤A¨:º›:KiyE¨k§hâÝlgÑk€_ƜÄ:‘tyL†¶Ê¶ÊÄ*N‡e1MqÚFƒyØ¢ž¬÷~:òkfèãA~æN1ûlâ‹]iJû Æý²B—TÕ@É#Ö&e¥²³¸øSÇ“µH²J*5*˜'Ét¨6ä˜vÖ€v,e³*3;ÙœiSTÚ–€Ÿñìj·i‰¹WÑ@•Öþ©Ö1 ֤å^É©¶¥IµVl]ô£‹ÖF‰]TÍ‘HæíPÄYk/’³×:b“S ~ôÉž7à4cµ¯/€tÆ/ }Gç¯Ñ‰0ÝÁc%u¡[2UŠC¡[fgæ\{Šìö?°B›˜²Õß”›…¥«ŒŽÈbHS[\…ã}†×5DbJ2ÊKp‡YÖ¶iYa¢ãu •º½FD¹ån¨¾QhKSíÍ NlKxYbGo(É À#†ºË°ÄþÇev¾¤ÒêˆL Xì‘©$,‚Ö{3㑊^‘ŸV¸¼YD¢9ÐêôÈFâ7*®êñÜì틱ŸÁԨ؈³öÑ`Dzîórãºü‡¥]\¦‡øï¯ð¯Gø+„?©Eb*B+±ÏÊÝ£ ?«@?=yÍ/¦_0¤6Ó’Ÿü¢þü&þDÉAêò厼ô;×öY%8ƒ4b2'ÊeœùU¹q‘opÎ|ÿ~‚a³?Jˆï1Ú~_Þ/÷·y¨%€~¡Æl¬„ØÈZ^ræLǼûõç½Ê¼¯†Ü}Ä(œêÃÛÜ-,}ÝÈTÝÖÈÒ7E¯²<âkJxÔ>Æÿÿzx#±{]ï¾9Ìšó‘€¾â·s[Åy¹ø]}ç-W õ@oF[tU~½¬·ã¢%nûãzõt¸E÷†{øä¦[„)'Ó)À/rLjò¬þûmٴ˼¥…i›?ÃÖ@@Š:<È¿â£×4&ÒyŸô fdÛù‹ÚçS™WH3l;¯F{¼]¼5ð\Ö.£·#¹¹½þÝHì+ôEÝŸõêW«ÝþðÍ\wâ(¸‹…sfýÇq”ÇäðÞ€‹Cõ{ËbÓ0‰ûC3‡’¼µÂ]q¤ º’àR»bd‹aB6/[Ò&kè¡z2Ǹœk„;·Ʊ€ñËÆ:ÊäQl¬HœÅ;ˆp»c \oáP^ûÔI9oNKxàÊt=8]ÜZ! ×5<$v›f\غzz8#ì=ÕoØÉ 2(¤®ã²×YF¡©d4C¥È6TúvU±©F^£¤ r ¨ª%”%þ3ø¾00¬s<íµ-6OÕ.~Ï€äÚ”±rƒ·UìVi0MÇdŠå–âoÕJyAù³Ÿ­à.뮎 i)g¤'‡k¤NIÑTìTà¶R« IYYŽIÿ*:jõóP²Ð;Z‹Ë"Ò7³iÇÕ*ŠÊ”µ½˜z S>«Ôy Ó1ýè±÷ï¦9’¤¾`‚¬6†×$ÛƒQDìMuR j‘÷qRÙé¬qðP¾ÖãY‡ÛÕAxÛ‘ÓÎ!¤³¥·+(æ1KÃôÊe*õ±¦@õÄðêì0:~Rΰ#î)`?¼ç,Õ‡]ñ¿í `ôã%VXŠZ)Õ±ö—<’s<§Üዲ’K—GÎ}=5Ô¨ÒÛÚÕö²l«*!ð3R¼ž?³%¤9rý´y®ä|Â0}žÚµÂZ‹ÖuzôK,©¢ƒë ÕáT‘K)®˜ <)ÇŽOã úÏá“õ¿ìJ¶úklk… táÊÂNá¨ý+‚ ˜c‘¤ã`1>»Â"­0¦“´ñÜåêˆõ6±ñìkšŠöð\R:…q¿ÓYŒŸ6œd—ÊŠ)›h$¼¤G/9äNhÇ`«é×ùÁFHE¸ºžT¢´>ûÆ;Z6±}üNÄ[*Ç´½Æ."žR1\[8®Ð°1«Üý•¾_@{ìþ49Ël¥ÖgôyëàFepˆ}µ7tÖe*c(B£ÚåWµÁ¨ß›¿â7<¯|dMÛÅn”¦Z«Þug–‘25ðp­3ØÊMÆ–æ¥ÛÜt³QûÏv%ç~¤u‹5îi瑸¡4— ž‰”\ƳjƒíÀL€]—mê¼bTÞ¦¢Ó`˜Äž6,¸a1‡ÊwS”l,RV$X®ÞjªâÏ”‹=9hG?TUYdŠo×Òx ”¨YĈƒѯ‘?Rø—íæv°ÙV¨DßPQXs™³žŠÜ› ­Ùs£Î0+²²¯ºäM« ‹§kF19€ò©€QNÕÿ×u31¼Slž_N;mÆHÚéÖ;-øœéü³X7v𩊄FÄ€™#x `µéÒ5JQ.­Å»ÓÖ©­z€kåµ×šLžUÇýsþ™,ž¸½÷?{qK£¥g»áî+âÞ§Ñîx¢@µpn*·Nä ðj‡ìVàKÇ,³Á³|¬9…õÞ¹P`ÒDÄYݶ”$3ìV}‹¤JLiÝû`fbò‡¡hGYAÞâà‰!¹ñŠ#G.Xè«ElƒjšJõÖ§—lJì N*½8D飴Uw¨H(úüÂG4sç|¢!a §ÝV±VKo1½]Bû½Ÿˆ ë¬3–aP©À<à®Þt¡ÄßÒPO‰—*Ú¬Kd(Ú£VÁX74/•¡ÁœŸ´õøA†a‹mwîc#lO/ö´!6(nžmÌÉîzq˜¯Á#†6D2æ­CØ,c`®½×·Ë¬‚Æ—„Uè#/µÅ<—¶>¯b?¶±%~TfÕ£>ȱ'ÌÁº‹’Y¢é凿ÖQ¨ÂrÍ1Êø)‡ò²UOh òçzŽåªò9]¦Å}%™Ì>cC¨ÐßÉ_Áñªm¶ª‹×$J%Énù˜8XŠºÅú›ÿ…ÓÃÎü¾ÁJƒJ:UOA°¿: cµVæ’·þë®1Åÿe)rþ©Ö ”‹*çS9^Œ?Cð¨\¼?†]|XkÂÓ®|Aá²%£~¨àþé¿Àÿf†üendstream endobj 1040 0 obj 5145 endobj 1044 0 obj <> stream xœ½][oÇr~ü#!€vq<}ŸyÔq||NàÄŽÅä õ@‹²lX")ËrläϧªúVÕݳ»¥À ¼;;ÓÓ—º|UõuëíÙ<©³ÿKÿñæÁçß)cÎ^½{0Ÿ}¯¼} è–³ô¿oÎþr·-xiZçU]üø 6 Î‚>ó‹”>»xóàÙNíÝn†¿i¯§‚¡ Š.œ/óOË:‡Ùó§þ}¯w_aËaÒ«ß=ÝŸ;xÀÂ/ßÖgS3Æ.»/¨ñ°®*µ²ª9¤5Ù­Oöë<ÍJçε·~ƒWµÖÞC‡Ô´®‹]Ÿ_ü+MýÂçÔ:5ù¦õâ*M¥…¿°wx÷yúõÜÌSPëoúŸ:?ÕÑýœgÿņnaüø«qðÙóGÊ}¯ë‡scWZ¦_÷çv2ðMï^î-´¬´Þýs±,^«Ýûø:3Îî¼Æç=^ç+•V¦å?÷4áÆè–ªø¯áKÜîÆ,úã£ØÄNhcë¯õÒ›ý¹ž¼Þ²‹×{&gCêu0f÷Û³“ónwïa¯e ÊìkhV‚µÂø°sbbàxˆÑ«ö—Ü |¤v ^ÿ»àvÏ~f‹x¹Çe734ïUŠë´ŒÎŒªÍ—©Å÷8?ã úuV4öÔÙ Êj¿¤à–w(ÀÎëyÝÝB ¬×¬éÁëøº –ÝUü¨C^ÊÕYþû«¨Ö3Iiøu¹±\êV®¥Å[³Ì9èHY½0|©Iž°seàÿ³ŽóöEƼº*.®.Öj±[P þg_?¸øçg Ã`Ûô ¦á&ÉÀâÓ̸%Ø<3¸UG^”O\¼5­PØý‰ © çõWfÓas›` ëC×UÃ^qÈBç={i£x©›U¼Èt^¾Nh¶M¸¬CýšUL°^”OUo¤ð?†ŒQêyoŽ†ŽŠ³!ÇE±êûnø,¼¯7³fûãÊôEUrr6Êþ˜”Ì€Œ%»‘(}¸Ù›Œ'x,=;®ÈW(• ½ó‡8» e¸ÌNÓ°ù Èz”>¨¯ç0%Æ »cZX4ã¶*Ý¥Ôãjj€u°*_U öŽòpR¥8-¤Jn]êì ´hE&¼J;¨ˆ&iîäáªJr+Ýyyªc©²Šê®g#¸<÷¢—~|1ÓÏúÎÝ*º``h8/LÿÞ"–€u €ÞËN6–_Y| ,z¹‰Ý€÷'÷ òË@‘„WÊoœdíBæá¯ûUÍre:¡áÉè…5ñëk#ä·µW‰ ¢ŠâÉŒ®º^@q ¹ŒÃœÆÜÑ€¿Îª#ê‹N‚ ^³r/ÂF†7 ¹ÖðÙhŽçþã ü=ÍmÕøtµòO³/] Êž_·]Mš*éi’ ‡Í™sdîôªI’ëï8¬†«”nŽØá~¦ò?*²$Ì'{™Ÿ¹àÀ4{KðcM¹Ÿæ –¡øÌŽ`úO~텲͒K™Œîréû?m0$hp]ê{KçÄšÑ}J‡lšôº’#».ÖX8 Ð 6h¬©7Nû@eYƒßE}XAMlñ É“{vkç²ÀHÂ&(Ùr£d4òY#(ÿ³(6õ¾\¯þærÏ´aåãCõÇ›*0#O2€bÅC!>PnRŠ¿ì§ª”ù‰¨ i’¤§p1z‘*‘¢î6î$#ˆk9¯+‡XÜaÄ…k hê¸Teô`ÔQT2¶Á·CWPïeb{‚Ê¡–Á\èíîT¥)aÁ·5œý[Ž6ÁæO,~–_›×éy þ”cr—ä±Z©˜ ¸Í*q•fÍsÓs§jVn{*qú­eâÅ L«-L×/l¦ÑO‚ÁÃÁ£Á¯·#àü©"¤"Ø9 wU¥¸>7r0ÌuË…Ï4ÑP5‘ðcBP8OÒA0 áçbpœÅça¤e:D3Å(Ðx3Ø(T«l߬@ýj B]"ˆp¤öL³bó‹Óؼõœ:.µLûªºå»èѹºàk¬YèŽcÜÓñz¾š3D0ä¿ìs8Êžú ß&5;Ùv 9¥šàïîpJà•ÒuÖ®4´]äž_Ó+< ï˨$Ú±tNî¾ZÛS.ˆ`,b e·ž®G{”²-xë¿@KÐe@.) e`zþ ž÷^ÕEÓkJáå2‹6@‡°kÒ5êBÇ)mt³*ó‹0(›_è:Zî0Ãjú»ˆ  ꊴØ!zû*þ™ñ+)Og8s»,:©?°5ÁHÚRíèØ’…|ó¼Š1Ùº„±}Œ 3¡ÒÑ8‡¿+÷czðqnüð—ï÷0 e &5¡ŒZÈŒbü,Å! tEÛï&§³XßÊ.sc݇ è)Ö™ Õ=¨Aï±ÌU,kÓè0`šà"i=“Ê›hÞ‚#ühC‰UÚˆ‰C³" ¯h3$‘é%½4é×UÄ»T @Š)§è„g¬ùç”Lxúßp®\TgêQ·ÈÃJaÏA@¼AqQÐü‹ ¾6ëò0ü½Ò·¥•áË,k’° =û?p5Py”éu E¦1âZa“Ølî¶Žp53•§ˆV$‡ôâ'2(w´ìÏŠÔÖåÅoZ|3â›%ˆ—¿M P¡ bë‘ ~;‘2= R¡ô¬µÜÞxX…ö¦š³® †ÐÊÕÜêvξ®çûÎ3Ë]ºK¯¹á."fÓðØ~Ã-ÜV#Ó¤ÕÙ{G ãJ %¡¶3ÊŠW2áôSÍùž¸‰ªº – Ÿ›{2DY¤Ô'hÄ nÀ¯k—ªõ—*ZqïÈæ‹¸=®¥õí†9–9í–V–{n5fÕ#«&°Í· 8óûÞY¬´.²Kï[ÀQ“°ÐðtN7HYÇd`šmê§u§g]Æ¡SÇ»÷2¾ó­,½ò³œÛC‰0AG#¼ŒæÆ™p5‘ïuA?޲З­€YƒÓŒb©„tO¯lõSfa*$l@€É×0ÿ?qÒ£i²?þ0(HfZÓPN©™ j%(Ƴ ä9$¦¤·ÃW—MÊj‚34ãMŠºq‡…jUêl¨Ñ4%y¸=’l”UâÆ”®¯µ?eC‘î€e=Mdè#Kpd;O(%ÇÂÀ2yîpöºñpz°ÿV³ŠeÊYeÉzÑÛ{VÈéð®¾õ"„(Âôžû'ø{È‹n,pà¹Vö®B#4‡g²æ”ãrz>9TÀY’^`ĸ9Q=vütD«„Ú´a¶Rr{w@ÿÏó—LÞIÕpCl“X‚i·˜åÏ M ‡hÚÆÜŠ—Ýkoûl~ŒCfÑÍŠü[}ž•Hðkµ}øŸ$LÝg‚-,Šq½I ŠÚÂ=¦ûS'ˆÞTZ¡gw,•9­¦ã‹Y–abGBÉk$võSŽJ_³ëynpÒfÒ’ é/)^ÏꀬáÒÒv+÷ ÜÔ sx˜e¨D~:9‚»C† £…{± ó‹„H@–õ昖8^êHó"ÝÞmEp,Ÿ;¢„ˆ„À¨ðŒ —¦>“À¬ÎåþދP0E°Híý‰Šb»$qqg:pnQÀ×™{ !ÃÅ4I„÷IÉá1,ë!ÀÁítö³‘c/:Š)u°Í°ŠÎñ*Kœbª‚1ÙTdͼ0s¿,€Œíëu³q]o\WMŽ Yð#•òf/é%”ù­5íƒÂ8_Ò/ ŸQ#òvíeod)ä£X{€o"1†_èVw„Æð Êʪ„žP˹%`·ùH ™ßðû}Ìø#[5‘yrënÌ<â4Ib(×>¶ïPt§¸ƒ“¹. # ¹IOtåžyãž—%¹¦Íš•å”X»5œC+²81h/ñÓˆ¿Ä¬ûkö)qkºP¾I&WÖ6nù\XWR¯.ÍhÓxœ‰'•ã Éô[âÿØÐ¬ŠEñ°Fä%ÿWÆê¢2븳ù‚«ÚŽÈÙÕ+V༅Ÿ™Y¯•AÇ‚–Nï•ô Ü&ûi +y˜e¢›0yͳ‚J æB‘i¤>*ÝGÕ'RÙâ2µ,ѶÚýÚc@!úQ dž”–¶ )ÑHQÕa‚ÿ›+žÖzœä:1`„\-aEïDÔ›9Àž€OÂäù5¿Ó•|’2C*€IQÑ¿Iäõ8|)ß÷çÑš¹XJÁGÒ„ò¥úc •]6 „:&ºîéZŸ)ìaÂÙã­+·Þ| «¸tBf‘ë‚õïËÚœ‰R\ %yÄ}˜Å‡Â¾NÒV" c_í±•/îjŠ‘;0ÐÖ¢—uóq¢œÌËF>#¯¼ñÓ`%YI=>$pì5e×ÎF™5À; Fô"˜‘üØ0¼…€R"ìMkǤfpóì ÇÅ59µÓIy}W%.Š¢øýÉ@`Ê IXŸ²æ!r…¡Ï’ŸÃ™‘ì…dᵩw'ï©-%e(áÙA¥)‰ÊÐ&Ñ{æ8–ûl ‚Û\ç8…7°,®y11gÚ-äƒ>(Q®?üÀGË`1Åc-3éA¨ÕÚë´á—+‚KOIêy÷yI?>ï^ûX¨>Ê»‡1ãfŒRà¶Ø£¢Ýo׌ÌPâtÊHŒ¹â¾ÚÔ~»²Èv50ï‘óá•,€[µ41~3×"z@`ϸEéÍÄ¢¡T?båóïL»aú«ãúqé7ܳ ¬ËM¶ÈQŠÌ:>¿Õë–*ݕϟÀƒ[(÷µ°‘ GoâÛÇ9cÏ¿¨ÜRóB˜ø’&ÙšCö¶GÈh‹x É‘f¨búÙ}ÅœòÝØ%mò‚X˜º»UâFå´™©æN›ÝqÝE4-¯b Q‰aÇÒ*K‹«S€’MÛvÒ ¢º”J KÓoäW/¿^î[Í×ËL6;mö¥,aà¶ ³2ç:ÌTÐÚÆ7ãm%³ªø&®·Ê´ÛMFå讘‰B?ι:ÚÈÚ°Øë4ºf†pîÐðÎ"ÝT{—ár¥^*›³}vÊïhA𤠣c¼Î=²Ã”LSæb––éH«£×™lÿì‹>PÇ~ôhÞ¶êÑK$G6÷ÝT™áxA™ËÑ ×Úaj£&Ðz@•}0ëIMÌŽ± iXÚFfÔ&ƃßq‹ô"2~}—«ã[rÎHz—¬%\¦nÌKLô¬³ò"óÁB…Ü¥0"\æºH>bV/_éØÌC[÷2Õ³’¼2x×ÃÄ뇀1’‹²¿©‡w EDoIмT'sÊÓ¬¢5ö&Œô²èT›ÈÏ6®.v¶òzÑ«ÆãZYÃRfq÷f%‚qÇB¬0ǽfGƒ+h‰1цUº¥ä©ìc…As楉»îw B†TÃ]pmÀ”7I/u#ÜVÍÖaVešÓïUÚ´õ¦`›ÞäVÍš1< 8yáö£÷U#ÑBjRµl˜^l{öÀj‡8”1³=S`ž@È WðË9µ¯»®Á.»>Úy{Ï+Œç?«ÁϦBìøî+øyu&v4}ò뺤AÅÂÒAƒC/ ò£u m3ØROÞÀ°fÐŽX2k:c{ò©nL Uv¥<¾ê@зty…†ÈC°f$ †ê0¢÷ŒÌÏdANXLzyÀä[úp¬éø„s”\Ÿ|pxxGž—a€¢c…5pÌ¢Xfa°‘Q˜“èÙe%„úÙd(È‹|cC7‰ÙÎ1&é²Ýhí¶„3#,*K:¥‹£zÊ;$NDœÒÅ6,ÔÚo ‰@hJ6)üÉüfî‹SwÞVúa¤Gç)8J“‹å›0±D6œP$ƒM¹Å©Ó vâM-wÂ$W)&QÞYZØ1ba_×–+i2¤‘?s‘˜|¦’!}òg2Û'Oûªd<¢$羂®ƒm²µ¬DxvU|ÅÅXˆÑkxÏo±ý‡±XZà’. 2›uEkíîø°¨)œYÜÐÔîS7 -ÑÉôì£)ë•aÁåäÜ0Y(Èï½@ÑϪ€Ê‰zY;ô÷—ñç­ í§§hc]ÔºtºW@ÆvK2®ÚÓÒd’ý8ö­CXEÕ>ÍÜÅËzz壎|@_ @°Ü¦ËóØ^›º%·~I“îN¾f¢}ÉÄ+û×–òu§ÂÑ$`š#ƒÚ#;z7h\c‹u±¾uQ2$ªP” ÄZVD°yKŒñŒó¹ jÜbâWä{F””FK‡³’8·¤ßüè©J…ó$òPÂæ%úÅá}–#~sTýŽ"ª^¥Ý0Fsr÷¶-GR+q®ÎÊ_5àí‚B—ÊŽÉõ ¡QîméÔ'†z²|ÐP¢Y)B)Ú÷ºã!÷Òš :VÇuÑl0§@„ô˜%tü±ËÜQÒš:-~”1/íÔ.IÊ0ùYÿClh ±w:%mæLý¼¯Wî]X#©*ïûJûŠ%%¿á:ól}}ÿvõ.ï2>ªÃ<%Ÿæçx´±/& …‘]ÆÐ(£(§m1€È|ã‹Òþy–P\ºzFâºfФ•> Hò 9܋Ȃ­áNå\t¶Ÿ™-ueãØ@sÑi,l£Ø1ÖO·-f¸Íu¼èuÜöûeé°E¦>ÝÉ($Ôn¥bõ¯œp›}–ÇÅhžmãéˑ͓KÞKV³ŠŒB]žñ³H±0Ò0sKÑ’QwWUÌ ”KL²R©[ʇs˜¦T™8¿œ#ÉC¿»ì¢(§{Ü)®MÈ®ŠÔ]6JadïP3áÏ-oe‰Ñökð„ž  ûØÎÌ;y,b,60Ñx¹ìüu)%´`ý°\Ueœ)»‘•t3·2ˆM0ñP\5ë|(.JŽMéàÚPt*qÒZ~°R(´eŒÎ2e‡;}‰\v#Ã=Öp{b¡m‚!‹Òí…‰mæŒ(DWýCwîbW `ðX‹È¶ô›4ùÂÆ<„écèEݾˆµåoS³3 Hº"aSDè±°§V“‹¥>pÊ»bâ¶¡E*‘K”áyYÐ Ü¡@gbûì4Îi·<¶rÏ•Æ3LUüúºüŠÝ¤µEçpnWL©Ý3´…,n mZ‹ ‘\×…ßåãëòûËòé!6LrŠ §‹à6œŽ¡K½óÚÐm¹økºBÛáãËŧõñ‹rñI½ø]¹xQ/~Q.~S>}]~È_Iósü•ßÔ‹ß–‹_Ô‹ìwù¦> stream xœÕ\YsÇ‘~§ûzñŒ¬iuÝÕ~ÓJò±a¯¼$–VÒÐà†H[Œýó›YgfwÖ @“Zƒîê:²òü2«^ŸÍ“:›ñå¿—/}öXsvýæÑ|ö{øwýèõ#•šœ•ÿ\¾<û÷óÔ,£i™uvþ÷G¹uô™vRúìüå£ïvjïvþŽûáü?ð³8³Ï–er¾<¿‚Ö_ìf aYÔî{5-K´Ëîó½ÞýeP“µ.èÝyoóU~jlÜ=†§jnCr†¼Õvž´¥ ¿iýn;ÂîÿFûro§õôÅ—Ð\»IÍq÷»=~|ØýßÇŵûÓþ ±½±z‚‘RG8õ?Ccï]é¥ÁîÔîÉþààGPq÷í^Oóì´J_œïxZžýf¯ Õ8±…l3O~gêý #Åèa¤WûƒUfš•Ý]呜SøÔ,ÐIôµ) ú<¿·‹Û=ƒ¯f=¹`w?ÁÏÉ»hxjqÊZïþ±7z ÑDòŒ4|ƒ´p.Âçýý§ðÞ„IÕ.`OnúhW8PÓÖäõe{øÔ60W ^§éÂ"[Êr‚1ârôîŸ}«Iì¯u^[û: {øËþü£MXü¡¶%3#?ÿ‡Nþg ÜknÏo €ƒ¤ÏE®ùt‘14°jÒóšÌöŽ/³ˆMØÎqrÖЭA–¬[ãbùÐÍK%¾Ï}̪-˜ë®¿æ{dø#¸ÊˆØgTÚë vOû›¼¾ÅÙö%쇰.ü¬¯ §×æ”G÷z^B‡B¢rŠŸu¦T懨fÓ)Ý¥‡°Ýã#lÓ2”ã"aäÜÂ>;ݲŸ© lÙiÍ>Ø…Ÿ=ê6g¥¨±´–ç½AÇ5ÛÿÖãG}B„«*s€Üš¨AVý;< ~ͪ·Ø5L$Ÿ_¶_Òx½ÝUˆ#z$ýº0&l=Ž€œ‚c9ÝÒýTXÉJÙüXÄEM`ŸŠ¸|¿kDùZã¿ï÷8€š”2Ñ–s¹µz>Q=±†«ßD­êº‘“__e‰~÷¬˜…àmç\ºXã o£âö X‰pDÌ÷©‘À¦€§ê6àÓ‡ÚG"4½ƒ">‰d‡¬hc¦Ü–Õ D€6 ­Ï®®Û{D,³´eÒœA²óHÔBì|§„Jþ üû=Zsµ€o@<‚bØü“ÄÀ3WeÒ#Û“çâ3߉¤ü Šž›½¸HU ü3}½èìr;^³ÜìáÞ0ݸH„ùˆÉ«„"Ó.`þäeCÕ,‡¶©KBOáE'X‘b]ùyéžj’¾æPxbZ€€œ9(hÀ8ÍÕˆ©Ë»mBRq´´¾F çcb¡mÌ1/r@‡2G t3‡a˜ © '9ô'®˜YBré:w Q~‚æ̓‡A¤„¹-ÉÇ2°p×þ¥ Öá(NHÆF=ú‘‡Â=rò{ÎŒ³Áž5œ‚=)ÆÝÆÝ©¥^hôC6eT ,ÍZÒ‚>'Zò¿±?Ô¢í)X¶ÇhŒ”‚M'Þ:ºô¤( ÿüN3%6þwŒZ“Ù[;·K ]yÓóäAÍM*p¥G ,{vã*ý¡«Óþq4iRsÚÚ›û™ Í~»Áe·îIò­•¡¹H)Då%S’¨”C¾YNÄvrv×þ«=èG£´ "~Ú;CrhŸ†Þo—™ Ì͆4oˆ8øReƒþÇîd¡µÒžoÑY (FkÙ3ºÜ9°–Y«i …K\–Ì4ÃO°Ú!¬Þž¾VÂkSQ¨`Á"‡Êø`Á@nNØ&ÌQ¹Ù£².ßæ·²¼ÈQèÑwƒ†³IK‡v‹JñV¸}üª?Ku­–š«;B4½á‹ú#OÁ.¾v­óᥪÎË9ô¨ËJúÀ":ˆŽà`¡$ºžd;INŠdàÎBqDymáH’Å©E?è›øPÌÝù,Kò’PÌNXrv^§”êžw)(­Ý¢•1ƒØär¢c'†ˆ'ú”û$£2ØL¬eU0%—ñXó³VüÐT\ócõØ,¨œ™å.mutGª+÷¬ST˳ÖT§˜D>U/ø‚Kh–÷Sð«ù…ÌQ«ŒXk¶Óõ¥¿º5àç\;d`…_å ç&–⫱²w4¶oÕ'—l(IX®ö÷8±Úe†¶á¢l.üw9y½g©! ,§V°è=GÚh깎ñHÙŒ…†f¼0W:ÿbÂ6€=²Içï+ö æ°ò?B?:{'¡ÂmÔ ÈžZvÇý‚4éÅÖ÷Lм¦Öœ¸¯yrå÷ÄiÂØB> ÐÎ,õ@€W°!ÊeڂܬüæJNWRn.†þéÀŸZ®ïú]Ó¼‹ü5öƒ]ÔTÚ‹öæYûuÓ__´‡/ûÃÞÑpUf…ç3Îd73ŠzÞ}C»®ßþÒÞö‡?µ‡)™Ú|ûÏSÆ3†4 úÓ>™žjügÿâ²=|SThÔÚûWŒ@ø-õ›þôã:¤ÝýPó­‘þD¨²4¾GJ²íú)„t<€è¥šà#ªWû¬Ùræ ]&÷‹Âîˆ×²rQ$Ñ©txÅ%!#+±TÖ¢>DQõÕT‚P–C5—Hêý½µ)Ð/Ÿõ’«¥¼„äJŽÕòµÑ©êÐ.BqF¹„A-‚ëªQЏZ¥Ž¢¡i9¥\ߔЫ%ŠOjé/àªK°,Ù¾*¤7'ÐeϤÐp `É‘¸×äø$ÉL¾ø $C#{ÙóG‹ùö•°HNúÀqOg •û@]ô ó]•Ÿ–¬¢ÐJàÚòéæ3P5’*ab˜Ûyål èƒ*2zßN_n«‡3~ÝXŒàÌâ~ e²ì½ª10FÉν蚙=ª²ªî:È‘; Ýú$ÈE‹eKYêæ`ñƒ Ý´ 爛FLM=cap¦Gª,uƧîH¥#ÆŽ]+F|2V$+!‹¸ß¸Á3^ÐKíç¿u&àW4`øÚªÆË¡W:ƒˆú/2ßVZ¡ÃŠÿ›²bŒ.W¤Ö¤• ÁA—†ÅÕ,†B\"#s*Üêšë³…˜S¹Š.Dèíªg¼¡+ÊÙŽcpj™8¾x¾et*ÇÜwÊ´8 ÆÍôøÿyˆœ„34,'{ÙþÀBvœÅÜÇ5gÄSgòV‡wë…¡bM¥d\ê8m~Cžª—üé¨.š~—ÓÜ#[—RX©41¾‹ýœ»e[wz ΖHQÙÁñÐ=%áÆa^Ÿd8ˆT¯J”iACáUŽÖàÃoÀ÷þu9ˆ®Ú…W43ˆ\ @ÿäÛò‰ÁZÜŸ…ÜÆLY¶Ü:(9uøÖ†œ®n¦ò1IÙ=Ü!ëÃÔ¯Í tz$-~¢<è ‰ê쨆P=^d1’d¾Ïjâñ:*<*°Û»©¢vÙýÏ%‰ž#ÿÍ€‚Ý9Ñã0zò9þ.Éå§EÓ:½”_¤ÍΚ¼Ë]¨•Ü `µ!÷x›Ð«³¾·J[iü‰‹!'fv 1¸Ó…ºntt”EÔH+ÀI¬Qä:®ê¨wM>ôаì„-ë Ž.:"Õë9MÒo·,×vÊ¥óïçN¯•ô /U'¢WΕÍzÝÍZK¥¨ÊsŒ¸ûµRÏF~SÑʈrð+¥ŠÅX³¾íñHyÁ…¦g‰©Wû´[)Ë}rý¿XçfÍMÞ®oax·B7ÓKÜzùZî!}G*¸nZ›I*9#Õe½Lnum…Ã‹è ©h#—Qô*žðK5JIÚ·÷þˆßbñÕù£ÿ‚ÿýÇ:,Îendstream endobj 1050 0 obj 5919 endobj 1054 0 obj <> stream xœÕ<ÙrÇuï,}J~འïhzŸ¶óB˲—*r(T$–€Æ$@‰¤Iºüñ9çôvz™{/HЮ Ä`¦×³oÝ?Ì“8™ñ_ü}þòÁWO„R'W¯Ì'¿ƒŸ«?=Ôä$þ:yòëSl¶à«ÉÏ^œœþùA@œ8yb= yrúòÁ7bk63üL[99ç½ôb·Ìó$•Û<Ù*9‰YêÍw[é'g¥Ýü°Ý)e')ýæ·[]­1›ÿØîÄ´,ޛͷÛÅNó¼lN¡áä1«Í7øYkã$ ¹›§ÅÏn¶¼×nåæw8²›¤·›ï·;4|ùCé‡QzÙ|Mƒ;ïEÅ‹ÙÅ5/YÓÇ[?O³iqmÓïð­”ÒZX˜¼_´ÿŸÓßèSmÄdëéE¥†¿5Øz¿îÔ<9á}hÄ7~¹Õ°á–Ít{ž0p ÜlwZHÜðæ‹„©ÉØá²X)ÒRn~†.àdÖe¨›Ò÷ 6å ÄmÎsŸ³8Õ Ubó Ú,“6×ódŒ§F¯Ê@ñÑÂÂz¼a3†õH¥78á¶Ñ^òÅ<«Ñ_(ç‰e+vþ+JOxÂénFQ{pÄR˜ˆ­1 ˆWÉ ‰wqyÝÏ:òGNÆ$ŒCø¬a“Æó¼€²”=‹WŒ\(ñ.«‹h<£ÉA¤Û)6:àS. ŠuØÛíÅ€Õ]žeÐ#í±•¿-mbs /´[:…Å[  ë ô—sRa¥MBM– ™—A>€ÎžeAGS0;Ì3xÄ3 » _ ’VKòÂU{¤JAÂ9«¿¼¥YP®s¬æqþ–'*삃9K*"R¡tŽè¿b &B¥ñÔù£ŒsK">w!¯BSŒ0ò’Îq/‚öÂV|]«Ž(¬ô5ÙJk ÃRÑ–´ž­¾WaõK-Ò˜# .A®iðËÀ%°«9—ÔBGº™¦dŒ;BY^f/•×ð_;ÓÉ´Kekqž¶ÞH¦[‘‹ŠÂˆ+•v™`ðNLG ×.©‚z¯éÔ/ým()¼’¨ËáŒToç€ÖÚæO›Ì…ê&n@ä?tµ'Û Óó=W:1ZH(©\W iE(o 0Pc (CÚŽy¹·¸‘’0àéÐ[l~³tµ Ê@jö ±.j=[Ö’ør´†ÈÏGÊd´ÆØÀ4àw$ž¹(Ä’` Ä•‰ÒèS¬ÏÉÄç§1àø0ºæÊ&Jx¶à?móg„¥^@Íe÷¥ÖqJ%{ÙqV2êʇ[ÜΪF2¥Pe-Øí|«Ð s)‰ u‹ŸýâÌæ]pɤБgžµ²If…5Ì4Aº.¶Z2»@ ²Ùe>ODÙ³¡ÜÌ“¾+že&´åÚ¡ûZk(ôÊ( Ž’&€4ë'@±]´z”o(ãÍž¤Òjƒ a7[Le÷Á\•‚ r†ù+í°Ü…‹&í»â)¼›ëˆB.»ÊW4¯tP§™ô^jM1–Gyàd¤›¥áÅÊRÍnáªÎ!á7²ëÆ ¬›”ôǨWeKlª|MÙ ÂÆÀ¦XHÅÛÉÏsvZ$ªÓ‘mM‹¯•Ìe4t»˜aư  âaBî{ tŠ˜íAŠ;:\~±‚ÏãU¶yŠ1ú¬¯RÆÀÞð9’^ŒíYr¨…WTÉEÊÒª•`ÄP/]…XŸ§q1”•°S‡ŸÝpî)sSÄPñ¨dã±”MÎh:ÅV9„胚¯QͰ´n•oé¸KÒE+ImkËé^»a Ó:èS€Q[òW>“e›âÞVçh\“=Ž2jo ÒN ¹UÑóÎ=¤ÛÊ8ã± ˆ³Ê¬&¸Å¸rey#)€Á g®³R‘Z”øGЀÅX=z„ÕÕ° J¬ÆÑaP2A\¡³v³¨¶ÁòJ$_ìaÑŸ¸éQ–(é-7e,XlÜØ<+ Ktð^í±f”¦Z©° úY6ÈÒÎSY2ˆDÉv˜©‘!öc–ÔÀ»YÖþÕ‹è ©{â0SÄ2vHR¢ÆºýÊ 1{¿w ®Kq[ueJ5 U’“uXÛ†íA=Ã/K>ÖmøQðc·©.dÄæ¥&õq\"•EûJ@£[¿CÔÿc|ÇÎŽ‰¾¼†ÜU :ÑE=cU»°êV- ÿ±J†û&Nµoò,37NfULJf×YX!çU"Ô¥H(°°[&eÚL"Y–áêÒ¢ø²7|‚«„YE~[x ,ƒ >¶j, \"iEöhw”÷±8o¹“§|^Ƕª²“øEQü0ªvDàMÕC}$H+Їk­˜ÿyy 3ÀÐÉʶ¾äY·£ý`R‘jUØWê–éž$ãŒÒ®2YÊ)ÉÕëW—¯DÊn‹w† ÔÊ:V¡8h?&mï‘J¸~Í%Ž‚ÚD›;jÌ9Ku8Þ“(… FÌZ 8Â7þlŒoÞ!–"“’ú«¶ •XGÚ± X¡Œç32 Ø.)céd½‰d-ƒœPÊàÏ«Ñ ÎX±þbÕýûEÓ@¡¸±£"NDÓ€”ºs›h˨a̾é80·²õ³´Õ9]Y#¹ÙTyAš-Æù" ç;ÿ:áhfJw%…J–¶QfèÂð6ôU[jî‚Ò’W!䗱󾮈[å¸5T*©[ Å4b¸¬_²0þWO`…uYü´(•ïbò¹òY—ÐF{"µƒ6"Ž¿ õ„êЄƒƒÿ¿L‡Öˆ Z)Êpa…þb©*´ù¹¼¼Ì/¯ÊË/óKàD –Á çÇüò«ÒRå—r4Ñ¿Ž^šjtOæ<1Þ=ŽB5~žNØ<ÈiÎn9ž±`•ËÁ¿0³XÏ E{\{ θq®ËôLÏã}õµÊëÈ‹9–Û8Ë(¾–¸O„@K¿ì…¯á–ï|]¨KÔÖ²I ¯ˆ:pøþ4‚^,“ú½–Ó~&¯DÂÒ™„R\ÚA`ÞÓγÙX+£=z¡ŠGxS9ªb&Û 2ç‹rÀx—þúŽñ.ì…ðÌóä!W=~[tmƒ®tX>°`Ûº…C>1 þ£ Lb6–PèFUåV—>‰F›óM8CÓ#݆ó#ÈOxOe<‘Îî¤\€Úèä×]”KX¹©uxÏC¸Êµ M$JÁë}º”PÌeg_Ì=-Àß±/…«%Ñ·ˆ9K¬±È!à5ë,P°åÁ³ÎI¼Zèï–^òâÕB‘̵è9ª Qyå$A¤®m:fû3w¿$:<æ,žÚ(/w}»|Hg 1â,Ç›SŸ%L ÆHΦ³ >DYk‰5´ÆPI£ ÕtU0)Ub¾”++ŒW£¬¾uÍ×^FÖgMyæ©j Ù{7õ‡Û΢'s¯å­k9ö©ü9>ª@`\Í6ø »Q‚“¶²ÓˆUyÌÍ#TŠ—\× [^‘8öXþÂÜùʰQX%7CÎo:ûÇâo¹ç~“i­«2s$lžnÒ@àÕ¡Uu]-‹±—F?s/ÅçQ!“¦þ.M“#šÇ”‰S ~¬Àû²Ïþ *“´ŒÞ´}Œ€é^3µ‹íwÂOJÎ*tc‡¬‰d«jš Bƒ§ÈÄBÐYó¤5ók;üÓœi¼/#þëÔÃYm(m¾J wñÑ•\ªhÆ «ß.¶¹’²É mæêx0V¦õç¡–ÖŒ½€qÝÁ«ôS x¾¤‰ÂJAâ§/ãµ™¡¾ÿNÔr|½fj†‘§Ù4u%Ovr)/¨1¡™™²š—¦À…©­’Qöîlkƃ°³D«R^hîµ¥t ‹] \X~I°$sF5_ôÌO¥õ_è/¬JbU´bGF:æ`(LµÿÎ6f»žâ/Õí m ìU¹´GÖ³`‘¨ºÞ­bµJÒ&0å0ŒÐÙ•èþä“[©V}ö ·aF*$Ø]J1ÒÍö‰L»wëJôÝNÇÄÅd眱îÏÉ0‰¹R­ÅõF­ÖìÓ>­÷S}Ï+ a^öŸhÖVyŽÛm[”Ÿv½ZÕT‰œLòìñIƒ¤Š’ƇôÝj¹qŒ1Ïh…U-F4Ø]®Ûf9-Ôú¹rp«)IÖ'Ƚ„ˆ4¼b±rB‹VaÄ˲rж†¢¸¥ÏÑi+:S±Ï'DdÒ:ê¥6VVb:Ðlòd§¤”×RÏ™|‰A\<}ÒÛ¿8d}L‰'Óºœ^ˆ5F±cw‡ä¯SŠF@³ZÅ/üH¡Ë¦$=ºž{¢µ5_ Ï ‚>Ïs•j¹d%šF3ßB<˜Ž]ö¦ìvÐiC¦(ÛÂÀåÛ(Ew“3O˜q`jÎd²îŒ Wò” š(™«G˜lñôý)ÿn$Uý‘‘è‹ñ¢Í¿å;UP2û»üò¦Jë¥Q_ñDbúþ>¿¼,/_`Öc™°êuyûSy|Ã5ùmMv°¬º~›¯Êl5·å±ìN@%­A}[Ášf“˜Òÿ0¾—þ²þ>{ÖW Põ†µÖù¢è]yËz]_F"ïù^($O éyWùÕ:óOÃÊ oÉOUÊ8}GŠY¯óØ“.^s~'²ä6“ìiªç#è¦,}ÄÚ€±zü`ÛŸ«Å¤Tú˜0Ø×-÷>ðØ“mª18߯’ƒ°Ÿ³ÌwWÿáþ™ú>.Ë|é,òå߉ÈøÈuL¬õìyÁ7Î0Ò3êeïéú¥UŽŠ¬ó/·Aôå¨í@Vþ:3$P“nIç4þþCþ~QQY|yÝ`.­ç#}¿æŒ4èÔ TG¢ö¿Jßp2\ÇsŽç §Ÿòº‚2ísñ÷';“µ±ÒKNŠ‘³.ÉÎÿg¨ m¾Îø9É—0V’%Z,ê¾÷þ$PI¿šÇêôßÛz5øg¨Â½tmRkƒR•´É“í^qõ¦hø~ßd)ý"Á=ôz•¶Fbþ³îï}'¾Ë·G‰ï;léMf­«¡¡1[8:#òÄj ŠÀ/:}8Ði*zòQ‘xÇwÿ0êþxeÉI>*Dùx(™QpBó÷k&Èm”ŸCN”m½\Ñcq×w:ã8óç š-w®jBYw£¨¢hùJ–&Á»> stream xœÝ\Yo$·~Wü#?Ø3ÆN»y5ÉMüÄÎÇv6¼†³º‘Ñá•´G~}ªx»«gFëM‹…Fl6Y,~_]äè§Ã¾‡=þK?¯>}&”:<¿;èÿÿÏ~:¡Ëaúq|uø»£ÐÍASç{/ÎââÐÊÃÁéNÈ㫃ïbiþ÷Kó£¿àk®o^ó¾3¼yt½¿\©ÎZïÅâOKÑyï´_üv)ß,W¢ÓÚX¹8ª}¾ˆ­J»Å3h†µaJ˜nÑÁS©ûNjÚñyw:ÿÌöùRwÎ=ПCwi:ѻŖø¢ìâÏøÜy¥ÄâËåJb¥e3…Pô¿Bça0Ö†‡ ‡‹¿/W>Xáß-e×÷FŠðÆÑ”'…³áÝçK™´Ö*{•Ô¶R}gásÔÞF±Ôâä‡Y¤\œPðQ{»¸GÑ\'„ZÜ€v~µì;¥¤RÃâ <@ObX\æ!®£€Ú›ÅIü8ôäñq™a cÝÃ` ±ƒÓ2€oãÌ–yƒš0wÃâår¥Aíe«Å l£ìd$ØdÓ«N*GÁƒ®péÃ`?zçð h[¸°B¥Ü„0UQ^œÓª¬F {I„$sW cï•2®3ÆûIêw)fò& ½‚¿\âžKH”ˆQ§¹¨cãŒjèŒn¬SœÃ`œÞ¤az£`z‘ö²G­Ûô«R¼ â è-ƒŒa¡€ÙÅ øè:mä„z˜añP±ß2vÈbÁ,'õñSÚ"ðd^€ V˜-M¡>€O½Ðjñf¹‚פ²~@]­’²VWÔ˨³ÏP"‰Ý¨œ“A¤vñk4C‡Ë›dz0ôš¬¡E.À9EWÞ3Øv"ßdûÞmè¼ñ¸X%’â‡EA»0|ðÃ’ësAéŠ Vh0ÀŒ½¨êG”ìŒ&,L˜þ±³ŸÔá nGº‰äp.3ãºÂ‰¼ž5 †±ÊNP8…t[Ü2Óáþ ˜ueÒQôÚT¬Fö†uÊÁ¡mÒÆ‡¾…ÎÖ •‚e¤ë$Ò€û‹,¢ó‘p%·ÉÊ“÷?fXij œ0Þ5Ú2FL-8“е*÷´GGc¨®vð ¶PSEUÒ¤Àôjñóv9€¡T:â—Â;v =Ó4§¼rÞ½]o`WtRtYÁ¢3”µ »ÁTÈÎYã‹úÌtÈÁjã5÷^’^÷³·ñVRãÖ³Äyî»äI ÑSORçB(d^Àð»Ö»®0G{}ZýG¢«Å'Ëh5ˆ/¨4™lB—¸…2à'i@gHÇfœ¸zÛøfZâóÈë–©o'þ$¨¬õ'ɘ `/§‘âÞ’¢¸ èwQé†ú"HYkÏî·ïaCD»ßÖ„AÆŒ½ZªÐ&Ȱd®êE&Å(-Ùa|ŽA• ¾¢Ð.?³A!À.öv)Ã„Ž¤kÇrL4耱×5˜»œFfŒåF}YCÊD  9ƒ°Í7»>ÅSÑÍØ®/ÌÙÁÍ0·§¼Ÿ œ¬n⫯qÅ rˆ ž!ä2°-S†¨u6ò8(ÍéÔ]0„™{pãÚ5cmÓŽSzÓ¸,7'GÕúšYÿêy?2³"BŸä°Ænqêå#Hbpj$õÑH B€†4à :%GÔÃøf?'SÚ Ž{i‹‹¯°Æ€A»`CHr:ZGО qì˜ö£„¥In6I…°¯—b“Þ`ˆ•‡B?¬Cä†j:Ã%‹`6uK"1Ø33°ó?« aZØDYü:„ltbkˆüL1Hµ,Cd×¥¼Z6JrãÀ„JTÒ\|¯¨@Í1+KP©ˆg!‘\ Q&ª°õ1{s‚ >פ‹¦±WÎx“5`+{ûÐjJ‹“:æþ.,É9ã)2^¯+SL‚*"ÉäcB¢³ÒÇ@Ã]eÝ–uNB³ ÉG„fˆM%Ƽ¹tQ½èz[èÂÚQ7J½(ÈSw>^šZç-Y ¬ªS³$©m$½â’yâ'˜É‹"Û3ˆ¶úª@’¬¸Ö±¢áËM5ªÎçƒFUE|D£êD_PØd“à§[Ò ›Ž—0ø/ƒï…%™™¤Åæ;FQ¦ðGGÞ­PÝí>*Ÿ&³…ÌHz×aù’DQ!¼í½kŒGî7MôbÊš!"41[^Ô 4Ï1j§Ë ž¥Ò„L_ >‰¤7ı¦¬2[V´Qå„gËÄ Ñ Z(xØt™Ér@¥"T‚’ÑÞ‡|p›‹Â­Ò²ë4“¸ÑçØ±¿IB:«+$Õ’øi ÉÌ‘] °lØ&õ~À`bWñàñK œGI>l¦± y7oXƒAƒP‚d6×­¹Ýáªpv!:eæ"(ÝGÌ¥]Õ½'ÖnKö’Ûö‰¤ 1Äâ9‚‚O}±cv>`ó¶’› ")™¶é>Ú†mÀ„Àlc'’!/¶£ô¡Ú!ØØ5"1<¥ñý${±%8@ªü÷D`xóÀq‰&Aภè}q“™ýGbfƒyß¾Ç.u¸)üö–6J!€tûö€²RÊñ[À·HbŠû4*Qs§2]~7å)A!+ááG¯¢^¦TRŒ¶>dÙ·­Qâ2æíg{H„˜¹–ó=Ê+ÚÛùtžÃQ{¦X¹t‡³Ø†N®1êóΆÁë¡òÐyiS®M\tƒBˆ˜ÔÆí•­ÖåxßÖ#pÀ¾áÎ1(iÄá‘“§ˆäêÙwHR:N»ˆåØ'ð ä½X©`ÙÇ„²bÉÆ¬A>ŸÁ)MóÖ ÓAEŽú&rxò´0bz0¬„%ÏIÊN>v£çÌOª$mµÉÊI —ˆ¦žŽ´â$ë)ñÙt71 ÛíÐÌë5à ú6Ò„S—¹Ì(†¨¶q-Cs%7F´v¾Dö/>{¡;8Ÿ9âIbÈ–wA,³íBöÕšƒœä=†8íŽÄÍI`Xœ§ÓЈdršS^dt<ÕÆcªukã*·&d1AŸj”å_(Æ+‘"s ¥VrR®>f^ž&O7­Ë9ir¦Ê§”–Ç‹31ÁÓYLP`ˆÅtÎ[rÁFM Oõ× ±ò} ­ÇaÐþy~ŒûæNBÌÀ¤Ö›/zqi79®k3.ÕD’;%¯Hö)HúM½ õ5f0ÖAØþmPª´  "‘M÷±ŠãÞ^‰•%-é“vÑ3n/zH­4¡M,È{žju u¹ßwÇ”ÝÎn²­n­B†²«ºûè°l¦H]LÊqJŽc²‘£¬’u#o4³rl.0ƦÄý#CÀÊž¦°‰¾¤mŽä´øu•«žµ3,Œ6Ü)ZËçŠþ*™ÙF ,‰‰é½çt„Ë­˜ã,YWp8•ŽEå†%òRaBÓxìFZ´Êq­Ú}”šìÖlšôA5àÊŒGÉÒiEÑM2oâö­´a_tOÀ®Í8ɸåèf×ùgΔ…žÜz£éÒjÈó\?º¹™ìesz?QÑÜ5§½/—”8ÛYÊ5­Ýn\¿3óWÎ*,¦±šï$˜xÆŽU(?º]×dfÌÝ´¤îP-T‚ÌHjj0(;`KA©Ñ¨¾%D (²^cR„cŒÚ,á·a£‚Üà‚3¼iW—Ìâ»øµó°^9<)©ŸÁ;Cç¼×¤üxS“\ªò‰¤9ôÒÙÖJõˆƒÍmЗÙL’—ò~æ’ 9øm d)öj®s¤’È®#ýÇh£g¶ü›ã{¿å8eÐzÿ‚Ç6—”òâ|w³z³9hޝ(Ó›6¨q°`ñUØ¡­¶çÜ…\ ‡¾¹ö»g $ì€MºRöù–Ãn è…W$ÓÈ:’ræ¦×Ìm±œ{<¥@þôÒÍåz9Ddã]ýRýýæ »îËÀ ðåñö&*æ·ðIEö°c¡ömT4”ÇùÍ¿ðkãÅU³‹xÃ:”SÌzñÀÂÅ õ±ñ²6ÞP‰rㇹ1ÄÔ:FŠíЬPAÜ_¼ù¶ ™qZB^²"â¡“ézšù˜ç¾4¾¬O¸Æui<©—Ââ§»¥…§Âj2ÎsNŒ›%jÔ기2LîxEäÍëˆßÑCm¢WDã›ú¸JvUƹ.m?,KÏÄç-ó(Jÿs°Öü~Zpµiº-;xÉéj]7‹â½bÌÙàz1Ââvyïv²àH@¦¶ã*HÝŽûÚØ 97¾)T#i}Èããëã×'Ü<džŒ·ü4¹ñ¬tü±´½®OÊ„÷Ü8”^yœN²5iÌëÜPýå g(}‡ì\½ F¸G˜BȇÑ 4ìËÏ'ô‹ß!"ª Š#5üËÏ'Ä‹:ù÷þÌüË‚Óã—ë‚Ud 1nÐ ¸!Iê½1Ïà‚3óšì&.ùM!XgÎ쿃ÅßF°3ùD/3Ð'8æ A“pŽ0lfž_à Èw3+“ÑËú•™ÿ.Å4„m#‡‰Q0…‘' ¾¾% 7º…Éü‰Ý¯û?²ûó± J¨ñÊrv™™±¿Bêg¶™> stream xœÕ[ëoGÿnåXå¤Ë òN¦Ÿ3#%ÑA„Kà8Ø‹r"|0ë5¶X¯×¢ÓýïWÕ¯êÞ©õH¸D‘‡ÞêW=~U]Õ3y=i1iñ¿ðïütïË'B©ÉËõ^;¹/÷^ï 7dþ™ŸNîÌpX¤fh1™íùĤ“ÛëFÈÉìtïY%jSµð×Ô²éºN9‚t„©ºm¤®îÔºQJ[=bÓ÷Ã`ªGµt¤ûõT龑¶«þÍFJimõš y1Õ÷圧õÔ4ZÛÖV3ßõRè|êýˆbÐ=.Ò6ýÐv0öv-šaèõP=„~kM×…–2*¬?ˆ¶K±94“çQäüùìïΘ}n%mDc{0Ôì0ÇÀüëG+¡òÑS-û¦³“)èt4øYÏ`³ê/ø¸ÀÇîݶBToAø¶‡ÝUõ ö| ¿%ò;Ào‰D1¸AÅßð0JÀýÆš~¹¦ëê«´GZS»5=±«§…î-.ˆÏA=ÆZMqÖíy7õ¿£I—‰xAăDœ#ˆ}çõýgÔÿ–¤[¥þ7Ôšˆ/ˆ¸à¶_×S=tð#T‚ºú™ŠÔcj†µ´ês3^^Ó¼XèŸÕ%”Ê Kâ˜)šÊ®%4àã!>n'ÆÑEœîýý…¦ÒC–²r¦œQð§Ç@€PÉÆFªáw³1õ/©I6Þ†@\‚iûcnûËkðå²?6¯Èš Ë[~Q˜IôÃd*Tcl+½•~©Ò¾šfí'¢!â/uôi* K€>'"…„‡òU!vPÍ9"gµ¶ ý? êCjÞ&]Ý'êÝ(‰Ì}VØ5N+=66I§WP©úÉìǽ٭g³#|‘Ì…·FÐí€ÊŠtF¡¥‘É;œ:ë}—ä£a  ÷»:Áš)/ãc‘Ûέ£{ëàqË™ÍñÃrèËPq¿:H@þм—¼»ÙÖ£øp—?挕ˆ'°PU^'æ›øÏN˜5Çô’;  pº  ó' ;=ú&(òƒzMÔ±~6‚_&JÚAìÔZ>€¤ ­9ô²fÜtZ´ ¡‡ ,xa‘±é &¼Ý¢/6ÔÄð¶U1a8ؽ¨£åHsAøøçPçÕu°©`ÙKN憖ÜÈ—¡uR¤Þ¸€UjÀvÈYp[œÞ.oLw¶„Ò§øøWÌy(”ÆTØõ?NùϷѸ=&Ɉ…ä[ø¸S&MXT?à#;Æž¤îGDü.úªÈì74àëDD|î Üý ²'6õ(Ò&eâÈÖ°ë³mt>°’ëŸhaU0VÖ›D¤”iŸ|Ìa•<áB õ+núœSP¦À :k~“ŒÃÀÓ´çã"õ"HgùfÌ,Éæ'œ‹º‘1ƒðl¤>Èq´ ÎAoÍQcŒ¼b1Åk$MÓè̹ä„;åX^wŸ4›¤bâÚ³ù«‘9iäÕè,ÉêÐ ZÚËô8Òk[íKÒÞG:ÓÃWÜJ¿&âÛB¶±ÅIà}J§îŒJl~Kc jùcóý®PÙ¶Cê§pô(Uäøü±öw4áñ|¸"Ûæ©Doâ̓ªþ[ûb½WFþ N 6y:«™¸9ðUAePþibéøüù‰ ¢…5#¨ßë´d«ÒPÄì®à Rÿ” X|By:¢¢zV,²àOè,…Ù§Ä_³T>Õ%¿dÉ ×ùÖßjö*TU÷êXJcìñó" nrƒ(t›0¬ë¥þä—czÃùJ2³xë¾]HÉìŸIrNöçóòõ¨¹‘Íq–æ]é7s¶ÙͰªŒW!»ôwɪç] b$8b³á,-JM•WZ;€rdɉ̬ §ïw ±ô=ÙªÌ÷覘X8ºÖíü…VV%» ºí7ÜíiÎü ™óÜ^75"Mʃ nùâÚ”ñæ#me¸î|Ä:ËEq/àåyÞ1£æƒ"n𦳭°Þ¹nÐ.‹2š•×¾Ùõ¢{dz Y†þ`aÎv!dõÚ;—LÁ³Ô_ÞâÝQ¢9O<¹Ër-÷Ïx7_mw£¹}Ýt5ƒ&Þž;îI–2ö‰»÷ Ùž˜—nNoî "»hp´/ëx×á~bâ%^¼vH>èõµÈÙˆ7!ñÆ8rÀ&×+Jã Úe A†y_*J#è’;¾~d y?Iü€nKH:ö,.¥¹Î\êÂ]r-ÙeÑî"…2ªoí>O£Ï“†\†Òl[õsâ¶ •ÚûÈLØÔþ„[þ˜2“mòL¨Ì"!ŸÎg¥ì¸ÞÛ8oWñ•j#u|«ZVðã=z8¥Œ¯ÙÛ»l‘5A–¬xRˆy­¯±…ð® û3 ¸QÈÔ‡þ;6û¯òѹ~çü‹½,î¥ÆË—7Hc¸—÷Ó „Î6Œæ+Í,¦œ@„Ú™³‹³Â2d®a>ç×»sözo›&vijlç3Τï‘ß°æû¿Dâ}~,ÑóÆçÊ~ánãþ2’3oQŸr€-®*Ç÷°ëâÞ,_p)#í8uaOÕ9gyÖeá·YÌÏ“ê"†µÊ¾€ºÉ;Ö©0§”aøçë5°5 Ž'±Õ(ûvõ”[~MnÂF>ZiIö+¿>Š—%oŠU™xrX|Ð2N1\°oÞ¶ÝTÒ¹2ÚМX`ß¼¸:ãpXž×ו÷[éxÅ¿‚^ŒàÕx(þ~H)Q†?ü~PO 4SÚJ÷E ¢ädªMÓ«è ¢–MÛéVW­oiŒ£°¢haq‘h?ÉÄ{ÕÙH%,T8RÈÁ£Zi©‹&Ûbá`Qcq}Ôbå¡éªïk##Âtüês]·–Ð!Ù­¡|ó³e‡çI¶NÛ«¤»ŽVèúÚ6¶k5Ø=kúå[­#wÂú×7TÆ}©¶@m­Á ³¬u¨Mß,£ŸÑœ¬Ÿ8ñÜKÏ!-ì' Pí¤—öá“X¨k\ž¾\EüB¡c,zA¶cÏ%lШÕð=/ŽXшø‰À²°‹ph‹=iFŸä®¶w# s!WK@ôí¬tjìñËZ<·54„ÄOºb+-ôY.öJ¥ók êQ4c„xcóóD\æRg,Ñ4LìÐh% ‰¤ŽM!Æk™Eîåp®@`¿ˆÖƒL¶èd®ËlŽŸ×0D£L¯jå6KþÜ“d©ü@‘ÁS èð 4  ;Ç,ÉÆD)^x iÚ}ô…‹t¢¢Fç{ðÀù‘u¯hÎKØ#è|t´„•0ñ˜ú½|­ †Ïó´îAùACÒöÎVx¸§¸t±P÷.€â–iŒ•DËVñÀ<¹´ h´¼Z3l‹©ÜyÕ»sv‡™”Æ“WL§T†g e¶Ã•>úÔ‹lw`eqaôX‰æ„ˆ€¯9DˆfÓÊ0¡è6Añ¶ {0fhDk2)K´Ç1ÿ‰Ô•X‹Ë¢á¸€µ™Q.r¹\È(2V4^r–/”M{·ã\êWïR ѧÞÖÊuÙuN¥™‹’v¿ˆ¬\Ý_àþ¸ZŸãòŒÑzˆK¬ílj*Ñ2vLBzd› îÌoñÿ*r¿:ËÝ kØû ¾öFÝíýþû”3—öendstream endobj 1065 0 obj 2848 endobj 1069 0 obj <> stream xœå]Ys$·‘~ŸØÁ?°Û¡.nÔløÁ¶ì=ÂÞµ%FìÈ’8Ã9dsHI#jdmìw&( ºIQÞU¬Cv×#‘ç‡Lð«³yg3þO¿_¼}ò‹„Rg¯ß=™Ïþþ½~òÕ9£_/Þžýú"<æáÒ´Ì‹8»xõ$6 Μ<³^OBž]¼}òéNìÍÎÀ?¹7Ÿ_ü;¾æçêµe™Œ…7/®àéßìjrnYÄî_÷bZ¯—ݯör÷ÇýALZ'wå™ßÆ«JûÝGpU,Ь ]Îðo‚»RÏ“ÔüÁg¹ÝuCØü@oîõä½Ñ–ßø—f³ßýn/:ëvÿ†÷ý¢”Øý~ø¼Òr‚žBC8ô?ÀÃÖçÂM…͉ÝÇûƒNøÝ'{9ͳ‘"¼q±âIá]x÷Ù^Õjbˆl5O>Gê=ßK7=«ÝßömÄ$å²»JÜÀW ý)¿{ SƒH¹ûjÚHiadwq8z1áùkÌOíÞÁ‹VA›?ŠÉgåî‹tûul_µ³E‚;¿LRíþ zqÎÏz÷¦´\ºÆñ ãY`Ìù~nö¦\»ßFÚ½††¤žf¡Ëm³‘혿Ú{\ÉD Kô"ÊoÿS;^¼{U.~­;¤›Jª.‹Ú}kì½SнôøÞYÍ;¿’} /NJéEj³¯iÝ„fH|z€Æ•’Jòq|±GÆP£¤‘ô°Ë0µVK¸Äž‰Ëó0G×çô(8^Õ?&Î2©š‘´žuÄFÇfÏà¬QN¿á„åÏ\î•zˆŸFú+·X$ÁhpÀ§v–‘78 w,­6òµkg͘ûŽëha$å:]WGfåæ ™7‹¤¬W=I“¯ÒEß‘¡Ý ͬdÒÃt ¿Êg›V¸°$ëõšíÞâ¼ìÊ:<ñ {Ž:¢¼ÚïùÛ½ñ¶Ò×Êâ®':Ho`Lõ|µu¨×aO@cüP€#ï›ÉI‘˜ÿ²:‡ÅWfæõ®02­¦y¬å(ð”6å¢FÀÕ›O†rD3G]ý¼ôS†ô’FJ '8Þ,>ο0ìw¤Ø…Hm£Š¯´/ö€KBôõŽQ)¤ÜDÊ`ކøR︮°|&¸ .ŽøW ÃÞâ_Oy½Ï¿@eá®(ˆ gÈ[A;kòãº÷…{_ g­Ç¯ÐîÃ+†ìŠ~AËáéö¨#0Ýà%u8þS §„þdŒ¡¯ƒ ÈÅ‚ &`#©ç}“õV™òZϤ…M¥¨–@]2µ„Üú¦¼”—ÕŸÆÍ¡5´Ð¥7\49ƒ~õ@²zCäP¶ÈïueÍ"YäØüÖUžK!¢[m3. ã# qÝÝÂ"òX³îldWîkþÑý »Ôè@E¦°Æ$¦X Gb ëø1 Îrþb ç•¥a,Þ3¡a&6u)Lë‹TÃdÆW:ë[‹¤Nfk¤]{!+U)¼pÚã3ì›ße^Ü`èãâ{m‚´p ˆK¢Ý€Û:ÉLoA£Âü™/‹$V+¬›ù°¸Ƚ+ ©§Ô¨9\œË¢³Ð*6‹ÄgúáMnX¦»ÊD%2}†AÆ#̾¶+þF¼Œ¾5ªjF¦ÒÐ±ÉÆ?sËCÕÚ—à6‚N]ó/J†ÏšÝzÕç¨o÷` œWÜÉÇ&zÐó”ûµ¯¢" µ\#ÇUDԳɭ9B½t‚·ÿ7 û97Ô ŽJbÛh< ©k© ­‚ÖhŒ|n ýZ‰!œïªÑüI¥EPá#ƒH5ŒVlð•á ã4êhã7 ñ>Æõ@]Òõµ®ïùE4<Ï|Mu‚†XSξ¶Íei”ñ!øøl—%á}QãoŠ$1RèêpWYèðf¥•Q¡a¶Š·±»yŽŽùUµò+_«pÖÈõ#¦…™†ˆ´Êw%ëºL¬lÐtÃùlŸ[CeNFXÿ‰C¤Â¦̤—!T ß‘ Ì“ÍJžõÀ8Ý;ü$0¤m‹Vwèß™øü8f!ZºQ=6 ¢0k0H¥zÝ úšf™„@ò5¶yNþP ×)ɆŠ=P”þÑðôð´x[ù÷ñâ¢úþÅ,ø :c—åñS¼¤àº¯ü¡F) \ådÏ ½ŠZÌ¢ÿ.-øïv=žmW^E´ä$½^{É‘”‰ ]^]…@šƒ\ÿ”Âh;g—De¢ÈYˆ÷à4â¼X)/é¬j’U–ù²Z{hxžMsYqE2KаA2ºu¢Êð¸<‰% évezn³Wu]joæ§tP?•tÒŒÆÈ@Ì858–í.eTn%ÀøŠì@t;ev·„VëØ‘0ZXRœëî<ßgqá9Ž Ü"!’‘D-I8ƒW2™`#çák„DÑб†Jï(@Þyi¦Ú-Ã]2=x ‚ŠøçyG¯çkQF"±j÷"Y{` ˜T±aŸÂæÉ ¾ÛÃi.•>­£ù:îŒ,× È² [¡¹â‹8W0ûóÔþ_ʈωŠû/㩸ÑsÚŒpu†sªý‰2§äÐÓœ˜¿ð9*l"ìÁÌdÙÃwh&v^Z&‹3 žDÀ:“0œ<³Ï¾® FÑ…•ÇÕØFÐÈÔÌÞÖEM%dVæ¦7,LBÅg«W8úêá2ˆl«ï%‡¬³è¥e¥qð¤%¨EìËbghö]—¤‡.¶¾()ãUÛòh &GdìÔUæ`© ÏyPšqŠJèDfð#›gçäØÓÿ5Æèí9â ñý£>é\ð Õç] &8¥‘ä/ÍEâ§'Ž™Ë:àÐe÷,Ê7S»ÏÓ8%WFÿ…ð²rvzº=£ͱ  ›yÖ/¹Ë~M}¡P|]³ïÈ£o S`ªÅ»>cÄÇ g;ð­¹®3±6WSe"ÝjOž¶ f”·rgˆú ?£ãȂƵ'‡S‹ŸÇ=¹À¶Kíœ`Øq«9‰NìAí®Üäxªü ²þàP‹ Ïc:VV$—yMI˜ˆ÷N¶˜À$Àî˜ÅL±ï¬²G¿6žó,Á1§•Øà}‰_ k^³OYJÿÕ4?GÁ#1ëøbW +õ«ŠHõ\“ü+å#·Þõ¬Ê7Ì>V2CC©ÆÈÂÜ©èAe…E™]Òš ]F‘Šô"JQåÎZ²–*ñMÇn LZc`u[µcôUÂâò°Çílˆ7Ú$#·¥›G”i£äð‰a7:P('èôbµ (KïlD»Dy]Ii45(²]4éf]%D‚ªÂ°Ž3¿q]>@sí,‡0)üs† ëh™ãM°LÖ ak ±åjICîzÞÏXa×C/¦5VÔœ@½ÚâôQç:((Ž Ûˆ‘ýˆõªå)!0=PíU±àh‡XD[Î.~ÿäâç@‡4K3š‘H^WªàØv`*kÃfÆ1F#•1¤3œÁ¢ÅN÷k#Îf‘Õ-°¦ˆ“Åt†j/ ï?üêË[iH ïE@`F§1Wæu"E8ô\9uùѸ·Y±JÀ8f ™§€#½Æ8¤Æ-R™,ê5=Þ.\ä™TUi'ˆèJï{€-.˜4à*k™À1\0­ÔIh!òEHƒhS›Ã®»xINEyÍr†0ͦÉ„k+“AÙXIž§´Ÿæ;ŠdTR7¨Hwï°‘Îë}øLL áô¯â×zó¹‰áÒýÁy˜oy?Ì׿ò›ì?æ­“U ¬më8¤îŸ2eú‹@W«Òë°Å€0ƒJfâSh0ð84xˆðöî¿ëkÁ?{÷?К©gøåþÀ 9¬&7ˆÝ/ñëۺɧéZ|­+æV‚ ú._|Z.>ϿȟnÊíwüvºø}¾ø²\ÄdQ‹Ir÷I¾ÿ¢Ü¿Í¯ËE˜€1pœòý©Ü/¡yP, þ|Ÿæ·Ú¬Z#pÛ ‚…mዺüˆ›u?¬õæ#>Ë®þs™Èûr•ò‹òÚërõMùøMùøy~¶Ÿ:Š€-0¢³jØ÷ž•fîgëôÝÏôKñú²ì¶WVˆ…_uêh/‘2íI;Û± 1»ƒru9Ʋ‡glP×)û»N ë'û¬¬*r@òÊfÙšê ˘ZEXÚ‡Àé7©é­y¯rx1/Éœo©·µlÉ=ˆŒ+&©;YÒ+T%gwÛ6™%*ôöz Ûg“§9òÀ+Rú:‡'?G¯jÎi["̹öÊojýrÔ(˜ ¦kÍgÕ¤R¯£¬”ßÙãæw­q/[ ÄF—Ö.<GÄ[ °ÓÛÄ%Ë&éå0-ӈdž<"Én¨]m×N\|48qZ­8r7ÐÐ"3Üœ}ok\%DºI5âN~toQÉ –„{pHƒe©w=kurE-¨²#+0âçƒM›ÚƱ\ê‚Ë)Å "?™%¢­ J+!bwûœÜH¡64x8ž6p Jféò.È(ãíÙ&ZaÜA§/%)å‚NÙÏ áÎL0ó1g÷“oj±A UoÒn¦ Š„cŽrÚ€ß!Úâ¾·!iteÝVª)6nk‹€eVèH¯äÈþ°†…ý¯ªÕxÚ6•~$,]úûMÑ÷Õá*+c`”FÛq &6uó<ê™+’ŠH¸Q~hû¦g¢ër-;¼ŠžÜÝ@íÃ[2¬æ°Àï;]öú)¢]ȧ»óÝ})cÌòt7Œx–í¯iaBn™A ¥àRôžPwÔµGHø„µHBÉë)YåG¨ ý2»ÙòÊÈßÅ]DÖúÛ…1]äuÎ’µµo½_Ρè¹Íˆ‹¸]…\†Í ®Õ×n`q²˜™¢ýo á\å[×¹¥¼9ÆÔ+~K~³PlGœIè6¹ðr”a%Hpˆ.µ9ù%ú“¶Úµ¥Nä¢TP~Ì|¶OÛåY»ð~ÖñÉ^–†ë¤íƒñ¸Ý ÉAAé`ÏŠê1Í>Vf¹¶Àä¸Ìhçƒó°¥çy6ÖW6»R¶{ÎLd˜åìʵON{ìÏ8gÌ Sõsnî;±bŒ=œ"bˆlrùå9u-×Ï)̨};Xà ËŽ‹Wt4cü¾ó_íœ!¥­èdoh‡ìõî…‰:Ä ¡Î±TµÑëO„©¢x¬n ¨Â\²,¸“uÚuÌ"¢§Öñh³Ï–âÑ>„8 ŠFÃÇ:¹ÀàþX·L‘åÞ®"èUäÃÙWDt·¿ƒµÂ)À ;®VµºxX˜Æ~ÌÇJV¹nœµyqó’X]Ù§jó§ÒŽ”…l·v•´¼ªÜŠ]ˆ¾TUîWz2! øuÊÞM®ÝJ%Íb×Û>K±H†ÌSuÖþÃê&q©vL—\~Tž‰wJôR ÏðVÜ^jä’G–üëar-ø÷u”BhdÅçž ú^’sSüÕE©bðm”ÉMg“¨NÒÜMõb”Ò=Æþ oSÚ(ϼ‰|¬Rt›"HnÇ“üØ€:Iœ¥{)‚|ç( «]è%fôA¬”¼ÞCÀ¶»+Iµ%Œš7ÃuÒò·d‘¤É¢Ö~UŽ—ÉÜPÑçªè…=ĤcÓXÕiÂ[Z· Äò²8*Ÿ’AL[xLóª·¿©¿K.pdé+æ/óqµ•ć¹FA³ó}‹´#¼)g•Zç"t‚ŒŒÙÆŽ­ì(I%ßÉÉwJñ×'M¸ßÁÒ ÕÉcMœGå<ŠçØMÍ(âÎcE–i”Nwx2ß!„êfmu¥~lj¦ù†¨2õГ•§çÚ}¸üÌér×hŽü:O;5ئü»Y¯]§^u•‘D4e‚(ÏõêQF¬ Ҥ±͈5M°z^öMŽˆ`W795ÏBœrÿû"ÐqœºÈN³ûÇÅŸçï=k‘*ÕÍÉyñ¹|YÊníÙF}Αš#e,JfSzò°êŠ{ÔÄÄJ©™xr¯ ¹¦TŠ ‰`Aš!9<" À¥ÑH5v»e!ãñhþÐÊcMG[0OªåTfÛ¬ÞY¯ A»rU±t2>Ë ©ÄÈ3j=ƒŠ£YýºtŸ†ôת RÑüO;Ý"õÏ“SG¥¸e³.Ÿ†Äð¡”÷UŽŠºW¹Íšùg)%†ÌUznÔ ýkOoƒžrŒW&R×ÛkÚn’PÍÍ¡·ã·FC±óçäs¡H-¿Nñ]¹tÂP„HlÖâ±0ýÓw·:Žå}Dxuž@ê­ ©‰2¬–»lEKŸ.i/¬Eè“O‚#\+^­+HCMŠÚ@ –Utk/ Ós8@©c»±ì§îÏ¡â¾îM±Ü"üÖnà‘kl• µu"G*Óîâ±zµ¨ ¡’H8~@˜ àëÝÙ:2ÊÛ£l0(ÿÁÉÙŒÜÚT tŒ±7OÊèÁI,ŠŸJ²ä¼Ñ‚ûqßÐßú\œÓØ&±hÉV{PÏ;‘ú:ewt;§ìr™·máÂìä«n!+A®é”˜µÎd Ò·ñ\/UIsÓѾÇ΀¬É,÷9W4ðE¯º¯Ûðf¢1îS!fò;3x¸N46ä¡_ù]ø²náWÈ6øCà¹géÁñ+æ—™Üî߸˼«RWCï³–W‰Á¯òE–‹\Zbi´ YijK3Ë;¾é],OÞUSKßöº¿î½ô2] 2Ib…Ì©4 ”|ššb¦î $ú_¤d7üǧäÃÈ—ù26ž¹÷ÿá4|Þ#×Mééä,ù‡Óãó R—ÿ7ü^ZÂ1³ëª„«2Ñ–¦I¬§µI9ö_œ¡þü? ëÿP­ùX«¤?z?áu9Fâ_ZÙœ;Å+ïî·BaM fþפªLzDÊ×8„9"ä—Ç!ÝY Ç[€¢/åþ‡e©K=ÚÛr¿ÐæuÅM•Øü6;’Á%Ô0jn†–¨%ÞT‰±b-$ý›ÒdÍ"éx éÑe*ÖÆzÿfñ“X£~¡Z?’¡UŒÔVYäxÀK}Ö] ¨X™³ÈÕ:ß³âZÃLî£yCtøéiH#=Ì·Õ7þA:““mø„¿ÀRþÜ «_À¿¬Âbñœ½¯7^ÿUN%}¶~›ŽDíl³S¾k·ü5™_ïÓî(;²ü¡”q¯ÿ5âùu·xþÃú¦º’™ã'Hn£Ãvöv5CÊ>™8Ï‘\í\ÔâÆÇȧ‰íí§›^ñ« 78é<ˆxêÐìNÁ1ã_ÊÀ˜‘œôÔÜ;×ü‘ÀÆô)õ%\?;n]‰Pò^êJ„úØâjøØ iÖúP ÒÔ -~£fˆí ÄB’̳qƒ0œ•´ •þÖ0 O¨XÁŽ-ÂÔÏ4¡zƒáá B¤Sˆ¥tÇÇ#%OÈ vu"D«!Ð쎌iöÛ‹'‚ÿÿÿZÐùendstream endobj 1070 0 obj 5901 endobj 1074 0 obj <> stream xœ½\éoÇ‘ÿ.øà7¿·ÐOŸÓ£…uÇÙEge.`ÃÖŠ)#<]¶ô×§ªúªêéy#ÊòB5ì鳎_]£Œƒ:ñOú÷üæÁ•1'W¯Œ'ßÀß«ÿz ¨ËIúçüæä§Ø-`Ó0³:9½|'P'“>ñÁJŸœÞ<øq§ön7Âßa¯‡iš 5hj8(mÇAÛÝöv0F9¿ûohB˜g·ûû^Óߦé›ýÁØ0h?í¾…ÇAkíýî1<Ü‹ÛýEŽùnpƒµ~ô»Sì?­,úÍÕlN2a'èûÕ^ óì¼û¼÷ÞMSz2Τùg5NeOÚzöy9 +ÿ;Yë&½û:>ÂÆw¤MLó¬ø,ÞwYׯöó8ŒJ‡tˆ¶+;ÏßóΟœþ13p.Y§€Q§‰9þš½ÃÞ‡ôö¤’̱Ót8Y«´Þ½††àoêQ±Ë5lÁ;ÍîfÐ@¨ÉÛÝϙ뷕 ¥íf룟êù t†f½­o.à›ëÄ ØéWdžvÕÌnýÔÎîì#wo÷ð0y iÜ}Æ:?£Ckcw¯p˜œ÷âD´ŸH2³{ÎÃ9¦¹^æ¹[Y‰§µžNy‰­H³™¾Äý`ô´¹"k-û}…Ò✘ ¿Û#ßáU–Š«¸ê¤5‘éæÝà[rwvl×smR¡rMu¸fœP{¼ÀißÔy"3FÅÏ„­O\·Óáõ¤Ê î|ʃBNŽ:ö"öv.÷F!O”·óDzSû$îäúÁL€› ¾O;äfÏv\^¿/k!Û\€÷z÷K<„Míx]`=bnp=€¤Ú—Ñ’ÁϘºÆ]]’æÂ~ïpüHÚÿ5ÍšeÌO 6z÷Ó®HI‡q“M»CœÞO¹¨D@Âü´Çδ“/p•yo ó€šË”Kä ¨ë ôùÞ€\XH%Ⱥövo c0(:$ä#üê‹ãI§".UÄLh81›ÓWé¬OE8“ÚLÊÊFø€É¼&E&~`¨"?4>¯bŽ+ Ï‚Ôèû}2Ͻã­Ušî‚0ÅÆ&ÅÆÃ5EID"qsˆ´Ú”KF=†¼Ô“3dÎ@¨#&ÒFèéIÒó1¡š¯2Y\ì!Bf_é9‰ Œu`çÌ(¸„Šçï¤q¹JÏD(Z>”2fäy|fsÌ4û.ÆfF²ªy´ùëƒÓÿø,ù$ÙO½Ãd¹ßU&ù‘kmµÁÌr¼Æé&Òª[9Gx&~û¹¡XH²6ü-ƒ³VRŒ‘ø=*P¼_öŽ6:È€j§ §¼Ä) "V;%´Ï$;k& ¸H[¹¯Í­‰È Š;޳N¡ž o=I=ßÁŠƒW»2°ë -ÞfdéÓ;Ülîú´§Î·ÕžÝn¼)¶ Å#è;ÜÑ\Xã+Pç‡:Ïguòò¶ŠbHíË´×C”"SžœRÐ9Ö¡` PIšßêN2ð€ì-òù24ô Ù"{i˜ì7ÞRV§Þ­ncvû¬€K¹çH'hìH–ªwøÍo­ºV¶sÜ‘úg<²ÛsZFwõláÔÂàòtÌ!¬kÝî5ìÒ™U´’!êɘ•DP(+èÃÄ2ÀÆÆ÷íƒÐ@bñø+Yxû”vgÁj½K®f†u‹šÜ'UhEÛ\Ï O}.÷ÛÚ%ݛ̌GÖoÇígêÂÜϪ† ·n2'&#oBV?p ×z¾Þ#fû¾xl”á¨ÖÃŒ±%øãå?NÇùf$ € q2 /`4|?p»P¨ÇQ%Bï¾Ä <®üªs[ìM¿>d‘3E£ü±«»1ò% ˆkç%¡÷Aœ|š§xòÓê\5ð„¾RbSÆmfñh\Û¬$–‡e(Êðó¢'¹ÉÏmp´H P€FHA ŸƒV‰_LOz3Ž-Ú¾æ N=`«Ø’ÃÖ©8 UÁ@m-ĵĶÛõרÐW„y‚UÃvˆ¢¶Ü ©ŠÙª­T¤«uƒqx;ƒ ,¸šZsp¹Œù@,T8*¡»ö‹@›à¯´EÀ÷%0ù0'~ÜNÄ !|wžu—̸䠤ÎÍaû™ªÒ™`’É<è»h›-h´zÕ°*&x6 .ÌãÈÝÆi/ã´hlîëD0ÿÔB|€P*ì•U¼‚3\Âòx¡øIÄa÷ŽÌ4«©§0À}›”&t¯yOܘAÖõ$’ÌÝ'ÝäV²K–¬•QÒÅ£„Ç$aJV¤óŽÊbcöO[ÃsHÕXoJJ5…&:ô]!ê´S×õGj¿jáÌ$Éu¦ªIK\jÁ÷ºSxr[‘8kÎuÊø´0U]\¦3ÕR,¼ZlL0 ¸5ªoÑ›fr‘W]o?S¤õ!IXÜ99ÐIãÌ´Þ>2ãLÚMöÈÄW†ƒøægn{Ž9Ún5AT0³lKC¶vÏ®ž0äxù8‡€êî`L±±+„LYk×}dÿb¾ …$o'ƒw0š¹£b3äe˜)A) æí<ŸúŽ«x2D£OéG iÈ)'€íÑwEþ«´‹±Úš¦hƒÔ‹Þø~ž÷p]Ý"˜bðê¨u…—±@'A@'òm5xÚ`²¶sW\&5èpÄiᤱGfÝ(ùBØ";ZJ ±«®M=zé§£žíD~hÔ—‘»eÒËÕÓÈÐ*ޏ€°fÕË× ¼1Õ‰òÁù|‡DêEùt’ »Òã¨lü;éØu³ºÑù«AxâšÚ¶ÔÅ¢¶H$ž¼¦S‘„§,iÏØq¹~zY•á.åתÙéÙTyph€.Yá8–õfrˆ¦ /Yjc×Ì º6 1½ÔŸÀˆ6tÔU¥bâéX–'uRÅ4iE¦é,¾AEù'KfzÇrÇQ†5ÙhÚ1#ÓI/®e(ŠâÙ¾¢¬…q‰+F(æjÀ”‹âÔ´ÄÇÕA©ïs뇰€×þ£¸»G6‚ãjÌ›•Øø)mVÎÉ…PÀȇE²voÎåÏ­gñÒ f8^Ì1ë²*´c búB‹¡GîäæžÐ›QÙF°˜wÃ.j eï}½ &½"lsæ^W~˜O¶¾Ie5‰aíH=W­10â†ÆÄÞ«Ñ;Aw©|Ý…P¦Œ„ø®Ü×k9.yÃ”ÎÆ!¯Ê‡ÅÒwÅ!]•&Ðy™c”¹:(Þ©§#^€§üίÐ?”©º­èbá `yt&>ìR±U€ÈÑ™³†M/bêQˆ›8C…-1ï—ÜßÑQ&–òÆNì÷n‰ø³¢¬Ü‘ûˆüBžÛóµ^Ï?ä(羉#ºXãÞ1òo±;4¥_‡¦Ù£½â6GÞŽ:ÝŽ­¨ÒÐÚþB'¶ Ý¢ ‚·†D›PxR A®oÑYeïf§ÍÝ­D!LKÓb䯚åmèFôأƴ‚eSG‹À8Œó,£”zK¬£¹²Y{™_Vå¶«E+ªupÆ“š²’»|‰dB_Øïy½—_ä‚ å;!“ç[gI%7›Qø½üžTôÛ\¾”2hŠqîmc1ËÓ? ºu–å hs1¬’"ÝNžÅ÷è°„®Ì¨1¶=¯{ø¼ôÁ øÏ÷©Œ‰çÕîö¥ ¨¤ðŠ›2øÅ8¥âÉÉOüò9Øú]ÕÖ!º‘*ä Z$ŒLÈZ*8aÕ`ÌÚeÛt,é…:¶s•º’gxQÃy‘±Š°gT£4Ùf*_<;C ÝÚЇeáL,dè»hüN˜|»È>/‹2d"‹‘a_/ð^‹jƒV•:`3µF ‚0 a𳦬g®kV­º‡<úPœäÏû}0[_ƒ¶Ã®›Ï´’‰@§FêWœÁñ⽿¯NÈ|‡†'e~LV*ã¬K/K^>\`×™xý î2%Ù0L¥SdúVðsQ2Iwa\)Ì> if³ÞÅÏ‹Îáe®çu¤ErÚÈ“+RQO…i0KF“U9àêuzæÌ´J¯'ÕCˆêÎn¤yÒ9Ïâ?dåEl,yÄ*x}C!øòÊ1Jgûa2¯£Æ1¤Kºñ™ÛÜB•5?æ…WH©m,4ü¯„¯ã0†JÖÑEaS:é ÄŠÚg¨Â‘7È ýjë“"£˜TÂï6@<ÖêÇAÎðÜaM'’"UÀVWV2¹GÒ°½—QØ<Þ,U¡vµ¸ÑµDä5¯FÜDd§æ"K˜c•žoŸ6eW£ËyX5 ¡¼–e%}ÖFu.áo[T]FØzŠ‚(`¿«÷wõ²$j/ÝagS&`Æ“Kß=Ÿ¬  [Õ©¾*Ì3tI$¢×ÆÆ-?É5ÀÅÂnYËõLòa&;̺_—𱼩®¥˸úqûÈìIë$¬Ú›ªJÒØ(~ç— ¿áÙܼëµPòjzv¨-Û®žÖ‘Ý”ï^ñýû¬â+“Ds™$crš@U+Jí¨†ÀT2`â•[ç¨!ÊRùT¦îHsäê·Qxßâýïh²JFiSb夿‡å¤@“(ô±xD*×Ò΂Ñü*߬F ,Eoв;’#u,_2A»­…6µ¦ Ãmü°FÖ]äEZÄIÛ~% 0:×"”mTk®àÂB±±[IŠÌ½í`ÊËx›oOªeb7ëÂ*à­GÅrY,ž’_T¦çþ= HUÞ–«ƒ^ ZØ =“Øêz3„£Wœ˜¾å q”Ëepm‚Ÿ^+jýrgd· fÙ÷YŸç`‚%&YR•ÈÒj·\X£Ùâ4N%s^Éèfq/’“§yÍÖÌW3Íéz¢»§í ©È†&"ÊœÄÍÔ*ªÚ=H¿m‰x)Óxnµ>ynfŒU\[ñ™Knš>Z½Å¤¥1úÊÒºÃí÷GéSdT妡¹Ú^¸gÁ®Ül|’ZïTR ¿æŠj4ttX² dcðóœ?Ôjú¼+}žìÁ¼dƱ2[—w<$/Œÿ“˜” ¾©Æ%5úÚóPŸÖÆŸKãkÜw®‹É·µçëÒø¬6^õ_& b:[)?¾Š1·^ZïÄ´l²Ü÷¬¶Þ”GÒÐ\……ïÊÎ.1¿¯à™ëë:×iiü>‘€«C‚‹Ä6`íÆL?T^œ—FvÀëúø¦w*¾*£ÞÀÍjúß,:0"cßÛ9;Ÿ \ôXxYÏÄNS㵋Ìì·½A×¥‘íøYi|U¥î²G¨—•äLTž‹©¢*ÍÿO†4{Ù;i…€«Îö¦M‘zÊ!d9©ärj|ß¡iD㨿ªÌ™Û­D$ųY“VáªýŽÅ—7ÿ‰BKæ¾™^ÈZ…Å‚?ËsW|Ù›èIÖuÄ4¥Q bv÷S~]zÞãò+¡O[2JW`˜MôÕ'áš©ÍÆ_¦ À²ª­º²ä/ÄPu¦öNé÷‡Ç%hÜôÖ|Uáç—e%h0twø?­Ì-g™ÚeTY¢+>¾¯ôzVçý²Î«j_/Šø! l6NO{”¨šø¼gœ~]ÁÔÜ8Tø9å3qxŠaÕªPþ6àÌ[~+Ô¢1ƒ8LZ‡¥bdÒq hQ6ù\‹£¼í5v ßE•§ÊwY{¬äGgy&îUðÑÉçü¶¶~Wÿ¯>>®}¿ŽÜùg—4ïj¿_ºìy)N•ú& ÖúEàcÌö 1â~Öæui¼ÉÖ$ÎJÖåI“ž¾Â˯õSHÙ/¶}+HžÕƱsæ,?¡` Û³©ï¤Éì¾î ÖUOFªàœ7ho{ôÎŽŸ²÷ô=(ÑYz-@¬10Î Z”Xó0¥‘šgŽ­ï£âì¡âqÕªlfŠS¿*T…$›è-“µ1½­ªö“ª&Ç퇂\ÅôF…]3tÌP$ãº&ïùÌoz4‘NšéUoÍ÷A3Ò¯ÔÎ1×aDf F0ÓK–‹X[œTå6&àQþzhJ#3敤]â>â¯Ù1—Ø `¿Ó–·š¹UÃô±Šu?ê¨,î2JŒpaï6Æ<ð YGhBÿZ-9îÉÅí1ÁaþF²b_Ÿ>ø_øóoÆKë6endstream endobj 1075 0 obj 4767 endobj 1079 0 obj <> stream xœT]oÓ0}ϯȣˆñµØ~c°•‚¤NÓ¶Ž–JkËÚ"íçs¯›ØÉšµEQ¬s¿Ï¹Îc.ä’žæ;Ydo.Aë|¶ÉdþßYö˜ApÉ›Ïd‘¿«ƒ›CHxé!¯§Ù.äVå•3T^/²k¼d%¾†—7õ' s²æ½(+Œ¬ïÑû=/´°Ö{`ç„÷ÎxvÂûÊ Æ”V±:ùœíPm»D<¦µ¡¤ÄW U)”é:ŽcÞýD”þ V;åF8Wšªk8EwU Ž8Úʲdw^k`¼Pä¯X)$¢Ö?£sU•Ö£¦tÀ¾ó¢ÄƒÇ®¸R– BDÍ‘<ΆØ1W;Ö4è.k ë—Þå…–Â"…;öV4”lŠé±’”ÛFð6H£»ŠýD»ôÄjc;O¶´“^³I´¯’ý!‚¸ˆà2¤Æ³¥.öÃ×Mz穵}Ö[ã0¦1pjTè69<¥ã|w4Ú±MB_Ç#‘Lâ:^dõ«kJ”:m#îÓÌí2Ùe,• ãÝEpž<—Ü$ÏyÁ¼,LÓÈ:¡·½üíij^XgbÓ£EË·í´´J}¦L𙤣îKÕþêÿ¤=" %¥0y¡¬€xK®±µ ]%*‚×ú힥™a1Zþ@õ4ÒTSw¨{Š.7¼¨¬%BXª°ÝíÐüØN ^ÈÔç¶´¿æÛÞrâ ÿÇH‹yX›íÐâµÚ Ûæaž)ÖüCZßþê6‚Å;K‚¹g£^…|:q²îmÌ>{O]ÐxÖãÅ–þ°pHÙÝ Ë¼<ä@ÇYôm¯ø&Öü=¤ûdˆ—阶êvˆ¶N?«¡­J}D.©Å³:û†Ï_“«¾}endstream endobj 1080 0 obj 671 endobj 1084 0 obj <> stream xœµ\듵Ïç+þˆ­Êv‰w¬÷ƒT>àG‚À\òÁö9¶ ì³Bþút·¤QkFºÝ³rÝzoF#µZýë÷Üë˜äFà¿üÿã'7¿’Zožþ|"6ƒŸ§'¯O$ Ùäÿ¿ØÜ:¥af£Ääœr›Óÿœ¤ 䯫õzsúâäûííÝ^LÖÜöÙn¯&¥`òíØ¢NÄí«|5ªíÛœ¢Š&nŸìàš¶VnßìöÚ»)l%δ÷ÊÍߥvÿ>ý{¡ÄL>x‰”X;Ãæô³“ӾߞDŒ8/ìSëhõöÅn/'£0@‚˜Lþ ©‘AÈ4Â"2 ¤#e>Dé`†½v~ Boÿ i«œÔÛçô˜>O€ßØZ?ÓZF‡PÈ ÀË)Š˜È“tBrì`'Þ›€ƒäøhŒTjûr·7JOÆ!…v-„Ç‹8ÒDËFþŠ÷‘p´j˜ÓY»½‡´„aä)ìîJØË×yR-·Ô©~‚cJ4îW²6ÂVó5Ø”Ñp¸6lÏKÂq™Ik§™èPÚ8¨aU¯5»~†3<*$ ŒQÖê#Ïê@ܳԓ&¯Z˜iý {)>Ã9^´|oõ޵Þ)<»§'_ž¼Þh=9’gØOØheä$ÂÆØ&%·îܼ÷ùæí›‹''7läÉÍOñãÖ?oÃ÷îlþpr÷ÞæËK°Óˆ@ÁŽV~Ò×™LBPÝåUx;Þ‰u wðûï¤:¾“¾`•ÜÈÇ&]{ðU¬³.ì¸ý9ç´ôu·ÛÿàœäFs¬¤é­ˆyu!ËÞ¡2 É•—™Êh9—Óc(L“æ=yØè'IF­³|â‡;Ø^ ÞnCÍòé#©¯½ YµÇg,ª­3àÖ#@°ô˼+犬o¶• ¯º_g&?o¹8-гì.*ƒš3ðYpëYòœ0YN‡Ì§d{^e £¹¹_&ëU%€1‹}môEaöóÎÑ´ÊeÞ=pÛX ‚…â à.ZóVcä/ç;Ø{O1‰{Š„;P@v,§pß3Ó´§,A(§(Z jèàQh Ð ºv¸> Fa¥õA”Qék$[Ž…3?^%ú<}Œº+w>k!!‹(x2…ùÚùòYEÒ´Û{À¤»bt(ðgu@=Ï$-N‰HØ@Æ0È@"²´yϤ)³ ]Oþ+}(£°+¡‰Û2^*«®à®Th•Ùœçé"òï¬|àñ´g« ²ªÁ¬’¤¤Ú(&Ì \Ô£®£Žd›j¬H^?m©=ýÚ#4 |ƒßG5Šó|·š‰î~Š~] à^ÝÚ€"·ßÌ×÷ q—o•É àš‘>Vh@üФòpÈÒ:¡°;Pq ¢… îZ HÁ0Äh^ê(û‘™ƒ0InïÚ~h“8ü°,j€óϪ”>á:¼Z…cœHm=±­Ç9o S/ÉEãG®] ‹ôk’‘TUÄcä˜/ºM+º…3ÈàB{$Ù©S > ë‘sÀMŠvÔYxG÷ µy´»Õ3GÜ׫ „ÀŽLð¤ L²ÄžÙ‘IHRLìp|ÿ­EÏÚ¾ŠlNÜ|°.ÑϪ3Ú«.ï8jiÜþÈhËË2‡ý«ßAÝ3ƒæ‡™—ŸqSÉí«Ròr&)ƒ„XÓÚ’*’iÛ(WäûYÕ?ŸîTV[DèD¦.2VlF£·€»­qXh+eƘAÁ¿ÄŽe›€éÁNg`† ¹û—léÃ>¸ ×p^ê@f<ÞÂѪ\Ç\ôà%Î{Úwàö±ÇCRz|5†ÇNPˆü·xèj€‘f&D ^‘âiõ#Qçl—? F%φŽY»¢«ËUô\çAõþ¯<ý¤ãK·JkÊÁD+ccD 5×aÒc&‰a-N>¨&ƒë¨by«ûUUÎohãRÞˆ Ûåy2ƒèJ/N#{EÙZ©()3ñ @ñëz@·+gî¡…›PêïáÑØ |Œ–š…9jfu,¢-빤­bf’{œøÓ„0LÍZÑ|¿ëÄj/»>ÎÛYþ¥“9ôtljéÚ3f¦šsùaG€Q“Q/+gg`'¸²~¸ñ™°|¨°Å*šEkºÆÉÌv£ìr©Ï¢†½-ô©gý>ÖƒXoû!ÍlÙcÊ‚NN)†O|kcøÓ•#S<…ÁŸ-©‰~é>Hy—Ѻ ')|qÕ#®í „ë´Ä‘ ÑJtAÓ7Kƒð*ù8ii?26™2ÓD_pÀ’^³ÀWK²É³ A:Bfèª$‘4H¸q“Ó³¡9œD@\ˆÐºª…æe ‡jºšœìý/«‘É”—À%ã¦æö…È½Ž“WB'Z%<$¼¦|}4í0Ç*åڥĄ7HL^‚x#Pà¾s(/ÇeКƒ.Å$9PŠK…^#~CaKXˆ^ð<в|@¼)A’ë|/` ç…‰¹2 t&Ï#(€)«¤•L§šXñ%Úøz™‘âB˜GÇH•ö&µ cpí‘e×oRµbŸü4;kvóøZÔŠÃïüK|× }ék/N¹2ô1Ît‡íYÑUОlMøey›WNé¡®1ŠÔÓù™¶fî„qÍlãúÌR”ÎÎÌ.Ïì!~My¶#lÅlÌûØ8œ€øŽ6îãVŸh©¹¼“½ö`ôpý dâË?`Õí]üø?àÇ}üø ?îÀä"€‹è¶¯:%ÍÏ|‹l B@„á×Ïðã›<ÄÄ@zóf}úö<ü>DŒ`À¶ŸÏ?¯ïο¨OËÅ.¨AûMf±Å ½ìO*)=«‚Õû¯ªãŒî&X')\ßfgÉ¡1pbLCtÓïè.iÏMÔQÊä„”É:±”}vÓ ºÜh‹PŒ‹@Áˆê™£ZïO•è§Î¿Ü¨AÙ0xÄz¾Ôk€‹–‰<ÔP€ÛPûœÓ€¦ÁxJ: ’p/&adM«,+.È)cÃÂÏÇ4)ÀÓ¤ìlE 9®Áò‰šsýUåzUƒdÙ{ÁåÊ#P ¹Œ m„.j¹%k okxØË¡TµBRÏÓ‰8¦¦d²OœøÖÆ’`ô!–&}º•òQÎÉÖ„ ÊO5;…è9«LúQ×{Kºþán™œNIÁ¸Ìc0³Efµ«0Õ¨Xao˜èd@rÏrÓ¸Þ’9-ÖÍà_)g84]9ÓÉä}]y"2òÎ ‹Úgå¿j¤ÙÓs~˜ÓËË/vßNÓIY0ÕæA€4T°ã¡Ü«²ÖÈìL:j±õã©ô°hPÅÅ0/j3ѵùC Î*†•É-õ£Nñ«ÉZ/zÞÊ6VJ€¢`;®ºTÍžËSÁaø8@ÍU¡NÓN}ä`H^<†9ìa°Ö˜EúŽII¥ø4sY¿â¡ZÈ:ˆ¥ ‹†Ô¹#üv£EDbIëH-ZrP:è¾]»XÅMË=ãVƒÒP8–éònCÏ˹èØÑÝ´²ëá‡.×ÚV`¿\«R‹H½±¿‡pcËz36>2–ön}"¯ŽÉo¹@Ç^¤.˜ƒî÷.²kEÇj=€0;ÉubH‹@ynîAjê4¬ý8Ѹó¬?†ßÖ©KŒ+ufAïˆmk…)u&%HŸw£Œ%Qbuó¤«ö¬¦ù ±¥u¬: d½nPæm!8n›=W9±N“åÄ̵øX4¬¿Ìâã\·9oí2g5IyiG1%iîyÓ©£B9ÅÛ·Êâ/ êÐعÔûâv˜vnÔÀN)WlD Ý%/éø«ù潎©O*ƒ)Vk3m]]ϧ™àh¯ Ê=»wÌÆ^oWOfg›ˆÆ”é}£Ùî²F7ŽéÕ=˜©Ô¿aö1ürÿÏ{A&¹n—#&ûë¬ZÙû{4Ô4.vB‰xLŒØæ‚K’âÁïgâiÚ„!Åz¦›$ÖïaãÓLkþa2O˜×¼2þœßƒ¶qí˾wp^]ºâÉ6Íë– óš×"Uú¬¯€"ÖËÖÀgæç¨“’µ`6Ö…yd?20ÜØ-z0‡/äÌÝõÑ3ÕË×}j Ûä@ûà9¶©­÷Æ»×H2ð-ºL(Žé–ÅîNÛf¤ôäjžøpª€^‘Ò~†œ°+¥†-çÓÞ`7¹ºŠzDjn•c,`¹èVò™áûÙ€]×Ñ¢ñ“¸×ºw .+ ]„kŽ”­QÝŠ[Î8õ’ýÕ8-2ùý—â¨+Ì­¼E ó¨"°u÷x.@Üí%Y EëP;ÊbK}n6®Q¿pv†¬Ôäñ¸0R:ØÏQ,9·‡‹ojU|3",_8îgaàÂe%z¸Ÿ‚¤&Œì¾ú@¯ezµŽ³ÊGVƒmï5fj*;xF´Ð—õÁÓÎ"¤òCÒ5pËYó¶Ëñc˜.Rbõø°š"Qƒí-Mseqµž´ZXø2ïnÛÀSJ‚Ì1cÕ6Ç6¥Ò„ˆM òûR7+¬3ª3ÍÕik]†E2†vÞó®ÛÈD‰ûõB³ˆ ›Ž! êµk†6à¬ÛY¨!¤E:ªD-^Ë;DÛ Ñ}¦-Œ­nS2Î/lç6Iˆ Âzæ¹u§±Œ€9bƒ(µf‚à-´k\ôôK¸ådˆwƒÔÍÛlµÅäœmYĽè„\!‰³J›ÚÎÀÌáK~^-šc`¤Wr®&÷-3^éÄÐùmÂâ G|É“ÅÏIåZ:ë6=m§í䓲Oœ$hI^œôÃ/í÷ª­xýÑ¥àùs–xÙœ2“ñœà§„ÂÛx¾qòΉuºd˜gÄlrµc#tñ@AY÷’Ù¨—!áSé­™³ÌJ«¶tÈÞmáM¹ÄKŽ)'ÞP…'¼Ø‚•žÏr œ—²ý×é;EÉ…õ ¼§òÜù´â†¨0þ… Çò ®KøAúü€ ?®þž%Ýß;gNÛŸªßsÌì>YCR÷rÿE×®®oÍQqpe¯ð®\G®gtjÇî#¯ÇEÏwõøÄ£„½8/k §$8Hx¸²„cuÓ655nZàѺF{¤›A»ƒ®°J—5kï>,Âô’Lí‡h“ŒUÕN°~¡Rã0s°EGÛ¾Š¿ò“Ú¿ÐþÁ›}æR+í(Íå—¥˜GØç‹¹ü{5³!@ñ·égþ4_žüß…ºÅendstream endobj 1085 0 obj 4602 endobj 1089 0 obj <> stream xœ½\Y“Å~—õ#6p„™v0M×]…à Œ9-–°¶-ÚU€´IÿÞ™YWVuõÌ®v1„¤™é®;óË/îN–Yœ,øú÷ñ³{ï>J\¼¼·œ|.îýpOÐ-'éŸÇÏNþrJ·yøiK'§OîÅĉ“'ÖëYÈ“Óg÷þ½“Ùøc'óßÓ¿c3¿ðfÒÛYBÃÓs¸ùƒi¯fçB»¿MbÁë°{’»/§½˜µ6NîNë=â¯JûÝCøUèÕшøgžö·Y.6µñRèÜ{úlR³µBñÞ?öF K×F)¸Ã„݇î¬Û}Œ|€ ±QìØ,r÷Õ´7Ðt"­¸Ý¨}\ò^-³!Ä•§ÑÄ¢v—±¹f÷-t¬ýl`àÇ“rн1üú,óÇi¯g¥ì¢éëãIÃE!åîLÕ{+t“ƒ›¥õ³‚_â|q–ßÉ:{:I\©Ú=¯ã]à|œ‹Úý4=CcO£~Ÿo~Í'ŸG}‰£LðÎâu©4ûtw_,¿ó Fx…C«Ý7°Up‹‘¶ì\íƒ5|\~,ľØÒ×C«Ð,~3Š·ï Ûœ– ´Þ¦ý2K©\°°7(ÒËÙf+ÃÝwª¶ƒå¤ã9·’7Οwƒ¿-å4°åœÎGä„Ï IM“F׿qÉV.šÃy§kàÇËÚQió+Þ¨@éŸ-ΠlJ¶iø8膧g3a½‚$ãxyqs÷qw÷BÁ틌›œÄÛ9Øî=ô<oñ¸qxFå<ÓˆæUUbë´™¤¯:€]†ÍQaqâ}µª­Iò†š¨‚˜Øç'°±ô«ãP²ž¡¦8À8TÒ~åÍÄ7-ÐNHá˜F0QãÚ%ÈàÔ+ìRÍKð¼Ë³F¢Ïâ.à°ð£ I`g¶{•Y-²ìˆV»ÿì:aÆ‘ç<Ù‹îVŒª¤oéÒU,¸Ù«•Œ 8{]&H6\f5˜†1bN–Ø×Ug^a'r òvÑž:ü¶À··S7`‡ž– e*– “óªfLÚk{¦B¸ÿ™Êí¸3ÊÌRHnÂ.묳‚E}I[Ec‚;öݤhËñtjR€ŒüùWœ·ŸQ*Ûn9dñÃiÅ%(ΘiS5;I,²”~Ç@›.hæM;¯$Í 6¯Ÿ®&8€Ÿ«è¯fƒÝ_àl4(;lÐHIÒµVå-þÏ8 脵ð8¢!-N;û DË·|…‘3DÃÅ$]Z´dWë'˜²œÓJlšÀ{2ÌÛb[‹mÎã•ÚçZN•Œt û|w2ÔL;kE€ -ûØ› £%pK¾ß+wÃÐØôV(ÐÜX\~iSƒl1ð|—àL?½wúÇgîŽk¯´!µ3Ú¯l1Þˆ¬ØG[œS €{JÀiÌ@-Á Þ”YÐ 8ï†áv\¥q¥Õøì“¨Hàâà´í|üþ¶¤´;´‚K ée€½%”2HâÆì¸q´_R0‘¬‘u™u£]È ‡x?[¯8gø æ^Ö3bÆYrS‚7Å!ˆ܉ìBe}pÄ;‰Â.!´¸EqVOƒ‘… ˆ3 «û,bèÃ2®Ðú¯û¸uwGŒEÑZY-ì¢:¯¬²Yd§Á ²ÚËEÁðÅtÙ­I†¼³#ȉ-N]Ã$¬àªxÀ-ŒÜ ÌŒ™¡·)ÍXóØÇê€@ ‹{|U;ˆ7Àj÷Ž%A Â, 5TéaNÎŒmÐx5D4,!›-FðS‡„‹Ò…§Ìl>ÐXIŽÐX¢'%OW'2sLMg¹·wØÅ0fÆÈÒÊ|gR·¡%ÌLˆh1ð²¿÷«!i„M‰H¤{ÆÞƒŽ‹ÐdlÈòâ>$A6]ëCÂ=Ìëó!5à—i®f¹s›; ½¹Ù;¸%@Jëe¾´Œ4X³_°áao¦²¸œàM2"ÂÙÖsˆö„Bœ 0àK£µŒa¼Ëy•xð2’æŸkAiQ ¢µÜ’òr Ea¶è<·,…]mqk%#·®ögè b=ÉäÐî¶6§5ýd‘]Uß#‰¥qhj6‰3m‚LÎ;4ù a¿ˆDZA¯ŸO’‡gâè¯|=åÐ/*ëÛØ«#W©§‚xœ<ò‘L$E¥z™'É„<À–$?Í2‰-o8Mð1DszιÓYKçÇœ¾Çøó»AašT€@ƒY¿ˆxxŸÂè´©°ið×Gø×'øÆÖw`,PT´KàÁ3¸™´óļ`%pË"HZèö¤ï %‹@6Zš_î¿ÂU…2@Û¼ÀN™æ—åÇWõÎËO5þ©üxVﬣ¿®?‚ÐÌRøèÅë—õúŸHž]»n…ŽRñƒ‹cë¨ÍŸ×ÿP~|;"O(Û²è }ÐÅÇåë×éø@)L4×kü u‹Ä˜V€¾Î^Ñ.Å+?¦ãZüNÒG¶×ßÖ9—Xï<¯?¾ä«AÔz7v;ìáYùñYs0ëMz•¥’b¬ka¨¾¯?ž×#¾ ÿmsšéˆ/GëmÊ8¡TôÍI&!s@Äc!ã|/Nv"ò3Ü%)6Ê.­ÑyÈÀ”Çf1rÁcpÛÆ09»­1$2< ï—5‚ÀXõ56òyI.2V͸vö|σè¥ÂtnêyJ+D†õôl¹ó“‘ȪIÕÒöÈÆ5¬:‘yãï!gކE‘!äÞä‹jÊ«7ßefhâÎfŠeƒ30GO¹;ŸAÒ±óÑRZ †%wMXÝb]ƒ,~2G¬ì!óYÔ1/¯Œò1t†:MO»Ðf裲x¾Ð#)‹F<[_AÊ6³×«§"d Y“`)²h¼“öN¹ ªº)1Ø `u9•|›¿3ŠRcà+`™w°‰^M%žÎ€·´é˜ùvU÷ 5€nÕ‡ "QêÓ´qŠÃ9cE€9Vcô»U°;ƒÎ5my¼•¤â€\RóÕ¹Z7V"Ä}‘¬­±A·N‹ Tƒ ä œWÀ¿‚ŸT=f:ûtöŸ(Î+Íuý!.Êp˜õ´6 dD=åhà%USb÷{e[xYH6‹2J’[íζ—š¬òa€\ÉL¼“GH‚N+l9Àß ãu,pÊ¿ÙN¾LhÆG´@oÐâö¡Üi“ |1¹?Ó„?»ÊÌ0ØG†÷›doLŒ3e»§1(·gÛ8`´õpDºû<6 ë±½[&å+o˜ÎØ=·ÂçHdC.*N5Š´¶ "îæÜŒ‘cÆÐ&å:$*‰1MÒ^‘[ Ë(ØÈ‘FK°rB;:7-Ç›Á¯ž¹_1óµ4¹¼ZÆY¨ý`.a Q“ÕI!&s‚*°Ý}ÙŸGA'ˆ×e"íuŒøϹ­ôK)¶céÇ£ÂñÖζéÀÎæµVpìTâ¡Aƒ%C⎸Ƒk™Õ•,¥Êš+C  ᢦI?8™ –×B-+¨;T±Ó¤¶ /™£†þÍP¨Yâãjjã ¼<ˆ˜˜ÌäA{0?8«þË*ëF&¥Rì¶Š˜¨(¨ ¾6Tû¯Q ‚Ñ•£ØL÷¡Ò>P8N› cȾiaÑQ<;Ÿ±¸Šù{­»å¢pKÄZµ½r –ò²j æ¢WÿåËb=s‰µ²šj—†E5]üŸ“5«Sñ|Œa[v^£°IWeÀ úN“%Ã\–0D¸ < ÂX#î™R£FGP|s™¤}ÜFݼÀÎØðš0º%e&˜\%ügŒi–—E°nX’hepÕ%«l,dɰ¬Á; $aƒBœ˜'>§Ã³EŒp…Ê l”츶­"ãK„Q™ÏRÝ"^jcQùýÁÔ^ÑX€©Â¬'#¤9*q F3ÕCè¼1„œiJ®µõã'ßáxøã w ²*æ3Øì"‚ ¶”ð²¢­,. ÛFŒŠ‡‚2Φ±õ¤ € øöÜEB/C£h)pÈu… §<Ä*Üw¦Pò‘‡²hG%*]È!íGËVÂäeçrÛÙ» j°û !y-ËüW ca±ÎÜåZ…M»:¡–NoÔm¤k»˜rªçø?ÔH”èe³LJl–&³ê7вªÑ¹}ƒ>2!hB YB‰Åæ…7.íUtHGÒv¿rÚÎy?)Ûw àÏçÍÒîšdzT,ÁêILÑŠÐ× à¡Ñ’t™ˆu,.E’×ñTƒA"†Iô/,V7ý{s|ÅÔSl´Ë)® ìY]v‹Ü] ØL ‹€|YQœãlh’iîˆwÚÕG3ã2óXpºðµ õÁ8ÐWÕ¶3ƒÜ¤#Á`Špö;©Lfíô‚_(˜p#ó:â¢ÝÉG>F6YÎÉ/cWÛZÜ•¢“ڭ宩ÕÊr—žôøM(8%Ôûgˆ!F¬@.\G ³í™£uEÿÅ¿˜úiUÇœË"Û ±e³öÍáÔñ¢ã&JE+lÍô(w˜m<ü %w³k•ý»±¸Žê“XñîU+­ìÙ³ÜëÀÒ&û5N8a-†&ƶn«F`½Èa^wµ†ZÒ*Dª¸w¯1 ©¿)ŒÊ®s¦èwî˜#V£è0ÎлŒ7ÇŽ÷Y øIÉñut°,}ñ˜a%‹X¼Å2 @Q5±{ØšE¥Â) ü·• Ä¥äÖ{ÂØãÙO©#!C¬Þ‰MÎëÇoñº ¥}`S}X7VÓÁ:”ÏFzuÎ ÌÎÀ<Kzúü5ö)Y7ÈÕ6·þ¯ ¬Óå9áH/'€/m†5=` ³7,:’Ãì ySñNÜË÷¹U^/9^]Κ•1z:àóFäÈã³ö_†œ¯ÃDðï뼕¨…ø 2!Hü«7ápL‡cd»¸T¿É´)&Ëâ£x`*êÕ2çtâPã–þ jç¬ñܳ©å3ã Þ3$‚jsÛù¾:0Æ:˜jP¨Çâ—§Ù÷sk#ƒ×Ïù‘‰Dw`e’×Bk½³³»0z éɾÆïÌ+Uàlù²XMpçé$Z£’-=Á§q­Ù(ñkËFñQXö|ÚáðbJt›ú°ÍÈh<‘+,I±R¦•i[tךÓ.ƒÿ)EjyÑ;a­ù 3pf/ÿ`µ"# Ѿøg€ç†xÁçBôMÑ~¨ZcU>°^˜UY,¦ç«âíD¯T©•ÒÙXŒkWۄ֊ʺ&‰¯êªÙÛñìì.\Š£l óž-\oIrñv66™æ‘,Aîšei€k³û7SB¢àymM[¦¯Ÿaæ62«—jÃJ´µ±:>j>xx¶}bžRÎ@3¶ƒ_¹dB­ïM>ÄØÚ,š=üôd‰ÕãÖ´6†ÁÙI~Sµ£ªÌ -‹Üu1”’Ê™Àv$Ík‰YU¢³·De‡u«êERâ·1pˆÞrÁ„Ö6“L›8ç›õñ‰Úp'OŽ6®.èFnÁà©eò>€Äy-x…a2^,‰Ì>>â.ç$ ”»!ø]ë¡¡\Œ@­;í¢õo¾¹¦LwH»w2ßÄ Wïpé,! b ±m—Jä­lݦ°¬V‹'¼<ó˜W¤;_`q½ÇQÙƒAñ¯Gøòîøêï'zlðÏñŸú¸ãgùŽ­%éÖ§ü´äÃÒ¨íýCªÒÆ.J»ã3¡þÞ/÷ö3‰&üæ3yfrüÂc¦Wz|åŸ_§Ðcu+·Ç-ïM0ÃRg̸> stream xœµ[YoÇ~'ô#äA;w2}wȃo;°cE¦q(R‰ð2)ÊV~}ªª¯ê™žå’°%ˆZÎôYýÕWWï/‡Ó('ü›þ?¹<øëK¡ÔáÛ»ƒéð+ø÷öà—AMÓ'—‡Ÿa3Æ0qxôæ  <´^B]ü{#CÿÆAŽÎ9µQôËÖOÓ(•Û [5:/&µùbØŠQkãäæ»AÖjk6/êÃo‡­Ü|2„iÖI)ha¡¥·£Ñ0Å'ƒÜ¼¶ÓèÃä&»ùaØC“çPÚc ¥°Ú|>èÑ{ƒ|ƒï=üQy´æÝ>£¹]"-ƒ>Æ~ALnó¯AŒ!xx¯º„ÿýdì¹ð´£õ ¿£Ó$3ÿÜZ+¡xë­Ö <¸…å;Bì…«‰?~Â/ðJgóg˜[N›¿Åÿ¨Å7øã»Übœ&!p&¡Fc'8¹oŽþ²÷ˆ(HynÛŒX†ù|?^–¹Ûa>ú~<¥ß©ßB²[G’²c0ÁGI½tyoÛœÅc1FlÎ3@ï`(-Go‡­•²“Þ¼ˆh-•Æ÷b4Æ;½¹¯ÀºÈÝÓàRÐ@M(.ƒ_áàvÔJlŽñµ¨à&GÖ˜Œ¿#2ÿ›j£6Ï:SƵ )ùÚ­à¾'a;¾A<'~T­Ý€?na¼ ÛÄÎÆ:nûnꮚ1rÇ“ò©>;­gjã‹=‡ƒzUÌÎT°@ðœ¯Zʼn‹•΂ÞTK§è¬léæ.é‘ Y‘Ø.›­óiØžã¬yu¹uß ºgTvÃë"§…üü3j¸[²|¼ŠñOêÓ‹úñ¾~<­m_×§ û:¸i€Ïñ¶~¼­ý®»ß”]ÃÀåm Ó Gá¹/‡(8-꺡 ©0ÓL\r´ßd¡AÝEsLLœ#sF@ça[ÄXµ–žL¢'IFèù.#TU·À뾪á²`Ãç0´0C€äP;ð4D”J8Ë ã´w¸Aðy$)Ò›‘q98ôoðœqH¶lï¢: €‘äRÕj;0òe«ØZD^<Ž“LBïp «Võ˜é©mÆak¨»p1BA¼YÃ/FÑÌôÔ¥ˆx Cñ>`Ó¢E/du©½U²Œ1ô\š| ™·kX/>+âÝáÚ¥•®“ÎÅÈŒìdÐÌßа–ŸÍ,ø"_¼cãØê>â¾ò6‰®5@Œh³¥Üà׃LE AÆ1ÃÌl×{Vuƒ)ÑùæRQî\®“Æ^Õx‹mœh„¹u¯JS+únÛ,!Ýh×ÍŠî*ˈj?œ®Ú¾”Ù N¶Iîoƒ ¥ä¤x¢ëmç7.j^c4ý¨‡Ú“ïšÓDó8Fp┯0/U‡*-ð3=?L° b5Qížà¨ù…þiðä™vm!ÂD¿º›mb€ºúì‚7—³G=çßáà:Y#›·-ÛâüHž§¼¹Ô+± 9׉Y_œë^j #ºÅL¦RÆk‹¦?’0šÕÌI@@iFeýî@ì´‰2žÔ =#€Ä$gõ5R¤‚ˆ™dt˜ÓîÉò«ÌW,»ÀË16žÙ:ù@o"Ž/ V¬é#ùª"¹â«õˆOÓ° E,§ÔYÌYjhÔ*Àr`ô|Iýl)ÆÄ“1¿#&^K4í&**Ç˹ÕïKY²».Ä…öüYALOh=[ÓuQ…©ä!znÒñÐ÷ãðDU´ÐS—sȇñc_·þo9±Œš§le¤÷˰„¨Máªú˜òý\C-ëçÜŠBL~žÊÙ”Âm5Øvˆ¼Œ{÷˜Æðe_ÎaigORÇ£Õ–›’Ÿ‡_¼°`-D"†]Mà!ŠF÷ã5\ ô­’ilaŒ³,}8 íËÚÑ.zï°x0ncuÀ뫉r´ÚzbíGáÒib¹ŠËì¼9OÌÛ÷ãçÕ>z¬ð.¡ÞàïõÕaÏI³)bÙ¦þš×¥õQ͓ۜQ›ü—ì¦Ý´þ纓œ¥=݃f'üξ)Ù6nš‹ y—u¢‚`4„Ö¤P”ä…'tҡܾ{pÞu ÑÇÂŒÎÌsfŽH¼4á¬ã—vŽ*0~È{r«±jéë‚þD)6P `eEfîbë˜ÇóDç/ë°(î"»(n/¦e5%úCíyŒ›½UË)“ö'3Áá€è59AYw–¹Ž“OB1…ÌçM´ÈšvØ’u½d³H yù@ 1«èî’øJUíYO7XÉW åòͺ‹Jt“*ã€î½oÔ°Á»éçÄI %k–‚¤µŠLŠNu§ÔÝ+ÿ~Ü\«˜UMð*ˆ .‡Z±Z‚™Z!ÅA1£JwÄbn*v¨Moru%[PØXq¢·±t]ëyÛìrH·ÅâTÏë,‘7ã,¿á»wm!‡&8/‹¼Š³¼*O¯rŸ8<:éñíE'_4K÷Éhü³ÒÿŽžRvýƒ&Û¦â+\lDÂ'9I f…¸4Ö]Sq3SÏHvSösªàŽ!³µ;¯×u,•媥Håã½)@ÕÙû:œŸ±ªün=3Á®fÒ¥GàïQ#ý¨¨—U¹>$ z¯q~=¤Ë–D'k@å|–¯†|óû:K‡Î³4 R€õÊêUTƒÔËãf2Æ/b@Õʳ¼.³Ü.KÓA3E8kêàé!«}ŸåU:öþ®nòUyØ–ÑÓÃwõáqyøª§ÑèO[¬!Oš¦(£øðóFš™2êœ÷½3]H­?b0¿Ç3œ‘ƒšŸmCr¹ãCTOµ=µ²ºôì6±™·‘©ßä9 á)6Yçü¾<ü±>|Q)±•eZý*KGšÎD¹äÒVQ¯ñúdë¯P,|Äøµç­·Éáe5/¾ ÃÏÓÅK H‘‹D¾îWÙE¯õBÞe3áQ!%Rœ^£B˜•dv›òãvÒl>r–‚Qø?ÊpIÊï¡çg± Ú úâ@þ¢8Ý{³¸“·ñî¬Ì©dM)s2¥›0q Kúš»Ç “5åWŠY%¥ÆÑç,Xmn´•«ànQ„™Ýalê-ÏêrLt÷㎗µ•ýîrð±5§êÝL2}Ûzá¼4‰cç€ÂÙY œëEÅZªrñ^jž®Ýp3 KÊö®úäÒÄhqys}®n©þX¿óÈ[ïy;¶s{@jGiš§ÝÉ/‚ò9àtó ï{mFÛfëS>¥ÔB·°~rŮҚ,Ck>#G_sAÚ‘6ÆŸ>ýê€ØXZåOH˼4DË<šD]w¯¾ºz³*i¿ówÛ¸©s ÕÂCNsܹ×ÑÉ…áR}‚Á…ßš6›í€·»¥Zbgõ*ýoò;9æhxk§_X§ûŽÖ¾ŒÆ‹b¡µAóRw›ÿ[¯ëÃøå J—SƒbIê馕׊5yÐEò$Þ[€ÎÅ$¶Y?i}1æÉ›Öèu €,…ÎÌdàÌì2©‹IÊëèIg¨:™¾ùú? ±š¬Ž{·|†%\ß’—õUΪônŧ{ $Ê–yžU‚é©]&Êßêߣó]·öë> stream xœÅÙrGrŸ'üóؽÁ4uá2–ÍekÀ ®]d$ ãßÌ:³ºká0±¡ÐhT]••÷Ù¿®ÙÄ× ÒßgoW—ïr)×/ÏVl}~_®~]ñ°eþ<{»¾z¶9Xš<ó|}øbðµkãÔÄÅúðíêáÀG=høu£~|øsŒÎLÁæ½q#'k½çÃ÷#Ÿ¼wÊWF1Ü7|RJ[1Ö=ûqU*7Ü…Uîª 7âï4n¬ó“`&q‚«|!Ýåd —úq#àFÏfg¤„Úßx¹5v8ÀCÎÃx(ÖL ÷ÆpÂòD±Tk®&©Œ@Š7‘äd“åÞGÊù(&fSù›2@€œgÎ `s©'Íç&îœNÊÆwã†MÚ%Íðvd@”7À“'pž øð°r’ÎYx^J1^/€Jx99g¬…E¹@àdŒœNã!ZðÙIÀ£<ÀRøg†3”¡ÖÖˆH‹Òz´|î9…0>âI> 9<+Wãú1ê Ü lx˜ Îä¥QR ÒrCqÄ3¹òå÷ý)2tK˜B¸vÃe^/¤¾©‹Ç½çGxþ1‘‚3¼#ˆ'cj˜˜.ñ9žÕú³þ•öDYJ. “G=G…÷†‰¨ð(×`X`†›`‚ nŒc’`ð‘·(ïà‘¾‚†—ÃU|vÞÆ½rúGØÃ\Øó°Ý^  ô+`T·Ëâ^],çúô|ªÏá«F?@ççH5·GÚ6 )¼XõEÐ$Tý_×{¯áÇýzÛ§ºízs·GÍýºx§Ró'Ŷ m Ѽ_@Ýé¢ùèîj•«e<äaÁA_Æ~$ØÙ‹°adâ¾ýºïVY¼Vƒ˜@cƒ.6bj@ˆ}@5QÀ÷ð߃´[UO‰âÝ(ÛzÈí«¶’ è<^¨Èƒ²û°îÞ/‹·êâ½·éN¼áÓ‚™×ëî»eñv]œ)I”÷§VIb„vüŠ®ñZ%þS«£{Émße½ð¨ÈD àâ¬aÜÌ$z£çV]@bmÒ΋pÁŸ)µIï%;€¨K„ûm„ˆÌ°i ·=ÃOðã¸Ú&, UA¾<á„Ñ»ŠÑó²xÖ[<®‹çwo=¡5dŒ…ˆšOêÙweñyV ãyñuÝù–îÌ‹g“—`‹n³ÚbæI2£_êÊŸqeÉ7¤ X¤ƒîáøáðã]"x Î*¨YÞ§ó¤Çâ'eñ ¥x‘˜múÑüÊ(u¸ÍBZ'HN–r6­cž¥p&_˜jœÖD%%EΚð„¤\û‰ƒ·(IMø~eXãd­l»„é“ÀdŽ\'fŠÉfŽ„+CŸ¶q¥™õ*£^U®3RõÕXl[Êø$gÕͤøÊe–„Í—¤ã'ðÀ-wUì/eìc³52²5ª-Ý2RXDb툌dö‚&éÛ^Ú\÷üE%<ë]ìH ߨªÚjw©8ü[úRi\ûMg3¹êI›íâ£îaÝnAE¯Ÿ8  qì )Û‡hQW-/ñ}‹Ù'tg3å]Y^64OT;o#$L6ŠAcü"ï#˜^éfúR;O&ýË— xÇør¾¾…páZ<½Û¡}˜÷ß  jè*9tJÍ/QÀc£FnÕÖú­œ!LùmÔ`6F8”ñØ{„Ò1âyqá!þKÓÖ( Ѭ¦¢›Ä®6‚œÖ¸‘I+·œó²Ó0îƒ*.›v;_ê,ÔlTâåŽ8‡Sî<.=Lƒ. ”Àe«¾ZN–ÓáßÍi‰K¢‚ ó¸0꽒ΤÓ÷òdÕdK)‰iZž¬"ÿQpQq‚Pæ€qFÇò&?yQg›Gž%çë‘ -—s¹fþ¸ƒH™'£‰JËÇÎ0£æ™^TãH[ üe¹£aP¼]ô¾èÑû®GÚyj×ñâÇéõÐgÉ ™â«‘YO%øŒ k)Ö£ ó‹ /#øaÌï#ì%s ¾\Oó¸=pA㇬‹T¹Ÿd宓ðôæE—öºø´£‰”!Uî¿õfø‘!}xÿÙÍàó†CË9tÇmU0Ldõ–÷ì𽶘òVtŠf¿G×Âøªçòm“ðÕSÈ,oCª€ÙÚŒ³!ý‹Å"׆vÀæä]Ô4tÀ$ÿAŒ<(×™ 'Yƒ'†™ e)æI&-ñ8»Ã”@´K5àvæêª t×½Wµ{» I8uRl@Ç ›™¬àËÛüÅ˦çÝÔ•òŠJS’‘ œšÎÀ¶N3¨Fà ;ÞñA²áá¥ÔÝN¡("·ð…0Ò¶¦­gœŽ¿š¿$Û33³Í²2Ðüª7GÍœG6·(µ t;#:€™öGˆÖ}þn,Åþ?7ªíðè]ÛÅn3ð]¥/×óaÆV:Ô¥±toh M+Ž%0½-f±ƒi¨D?ês…„ÖLœë/I˜óS2‘iêÑÐZýiõ?Y-!«endstream endobj 1100 0 obj 3383 endobj 1104 0 obj <> stream xœ­ZIoǾþÈÁ3Þ¸÷%@±ã6%‘_V4i-‰¸H#ëß§ªz«žé'’J ÎtW×òÕÚ|»‹Ü ü—ÿ?»8ùê©Ôz÷òæD쾃Ÿ—'oO$-ÙåÿÎ.v_pYÀWKQî/N¹ójç‚Y¤Ú.N~šälég™Õâ½×“£_öAˆEi?};ïåbŒõjz6«éðóçY/Îg§¿¶ç½*‹›~œ÷žœpÿ<ü@<ÎŒ±rqø9œg,üÄÙâê}þº×bñ2Æ´H%¾ŒrÀ×t˜A%L˜®à`!Ít68S*5½ƒ…‹Ö&ªé—úò(¼ÞCpJÂû½²q±6‡JâOðÝ{gíô=ÊBŒÛÃÛ …F¹”v(#…„NXþ¦¨²ý¶ G¶íUÛ‚Ìh¿ "Ów¯Ëv¥ÍtŸAåÞ™ézpN,mË‚Éé‹¶˜iä%¹î‚sÃ"¥š.97åàötÞ>ß º4i®z•NÂO¯ _ŒäY%T¹¾m_Ï·šâÏfDƒŠfñJ¬$[øeA›<™åc0±Ie † §¿à.Fް¸Àh˜~àd ž¬&„=£®” ÖÊÿÖ˜¤JeܻںtVÔZÂêNrÀ·ŠÀ^äÛKP©*‰™Qâ=*Vk Òé¢&´lƒ³qg½–f±ÆNz_U¯dŽ’¹’V¥­v}¯ Æ´w7Ȧ$Ô!/q ’°¤f•ošAiÚ,h|Rb ¾j˜ÎÔ_pu:wÐþˆbG´4ƒæ§Ý1ù™äž™y†LÔ¾!»Œ¡DÏêo fLL…"Xˆ)®wx DÑòZ†%ÚX€Ý¸¹Ó¢‰ n³Å¼ ôD\Î <Ȉêcøýb†pªU¨ ÖXUP $×8àŠ­ãj(õMžƒ¯˜R€€›d:<7(ZCæ'µ…c̦sÉŠ"È ,­=€ÙOÉö ìñ`w̓õ‡Y$Šw):ñ P¶oã+ºÈ ¾æÄ´+zÍFUämõ.9eZ¡dㆠԨ ”xî©»—Úz–· ³V†›ŽÑàYã9}wví¨LÍL‰Ï§Jåb²üTŸc…+P.ÀžÏ[ ³ É]?M–lïçñûаýc^ZC/îoh°/h °…N.c‚V%ˆ•°Ïïvgø“¸}üÏJAø3@¿nñ€›œÏ”sÓÓy3 ˆm•Ùeƒ1©WªÐù¶=^‹h8M+¨pã(sgÉ0p3cç Ã;ª|4D#•¼=Á( m:—écÅ O›c8ÚEñÁï}tkŒJ¥¶ñwùUªOµÔ]± ‚úS.ÙpJJ{¤b™ØæöÉH|ÀÔV бéãeÙ ~&%á%}}SÈ!5ô=>9üö§´‰–þZ Ñy*‘ϧ|%2 Ü÷¾ò‰™59þM·ïI%QVw™£'DìE•ò]ÝÔS”…"[$"8?~0g×õ¸×UoU¤‡NÞ»¹û×ÃUô´ª¨š½ª¨’¹­~]WödÎ*oum’§Š2}õ™Bèlš«ý½,‚¬zŽîäk…TªÈóÔ éé?³&/‘µüp<ífçS%Kß‘GñƼ“oX)‹{ŽåQs)9K9Œ~[kÛf å»â…+D„.Öb “å›Zþ’,†eA­:yðn$êgvtÊ(+ôVe^åFC–Õ¼(mkºòS Ì{rÒyÐP4ÕçÞûg=µJzZDBw£p:´wƒ43ð—å+6›r©l¨«Zbí6^'7÷,Ëø´$ËÒtGVº ®M+„š†²®æÅÇz Q0¼álñ¡u¬«dÉ¿œÄâDOÿ”âÑÚµÞ¥‘„5Q Èañ•Å'ƒ¹Öó@Å:¤²,É©RûeQ¸)Õ¢Šu·ˆÓoKwk©½U1€¢@Ï HX;tÚ—‹øëYq‚_”fM)îm!#Õµd帗@ªÂ²üQY“æIy}3Ö)ä”QJMqäÀ¼^= ¹¾çB&º)C MT¯Rø±‹±ºçˆõÈ“‡Ì'må Ž}þ®A[÷@uo/ñ¨PÜ)eÅ;Ü)«e.ôv‰øaŽWü5Jö½MËLòœ¼ª}œ!AÒGÖ·ÉÅÉM>âù¶´cæHO—ô‰ÐFÜÙö]uÚ´ý„`çQ/<¡ÔÏo)/È9‹M0–G{*6ä½Ú:\ ™üß+e¡,)¥œ¬h ×å¾óQjJþ“»§6hçò0Ô˜™Vò µ¶l³w•©”y’Gñø:“Awaó§²Xé{,F ؉Ê:ÖÇÁ*‹g¬çü;Pj b:â>¦9÷wh+ úÎæ°Ÿ¢AœCYÁÞnlŠ"° ðc|L´þ8SØm·YÄ™ƒ f_`y7PV™Žw‘Bøú‚£¤<¼ôFUÜç ?+¨F»Drƒ´Qyþ¥b£—˜°¼–ºJ/±ºëfv †=.¤R½'DH%Nb´¯p®7Ó4_ZñòºNÚÚ0ŽEš½AçÐáóŠù"1èÇ_gß&PÏÖ›aJyè5‰Ê u°ˆö1÷Ývu^ ÞHC®oB†ã»*"Æ¥À@¹5 }•x;Úƒ'¥AaÏSYR”A»¦[GÕž€Y„UPí¸qsÓõ%ÙgØÐ‹•W©|5J,X%X'c*–0ŽÌ‰›ÚÌÿ)d'mša”ïe’ÆŽM¥_ñËP|·ïŸ=]f3mpX×W8Ý` çˆwïÍSTéÁÈÀŽÃˆ((Õ“·­ÍØQšwt½ò¸a@q ¯´Îº‰qãQÏ[™äª©€’]× šc¬B+ŽS‘Ád?3Ð*Ý<È¢›Õþ­inO8¬D*é[k'ª¥¨äjØ¢{ÕKß»ÕnÞÙÞuánoî¾ù)î³SqpîCÙÕù³‡;îà¨òÒKëxäâ§Ôý­ ^\™a§› m‡ï Î'§ïÚê:”0òeÀ=@NߺðŸÆ¥µŒÂ½(§qËæNNÂ;!Æãu÷¸mXØAmÜÔ'ª.m¦k,¯Šwu×’×›¢ªâ>u>ÚÒóã‘TF?µœPübS;¸-"Sš1žK0ÂûpÀÀçöãù&ˆ4ÒgœÿÅ’qï ÁâxAßû}XÃåãœ0£AW0éBÞH [¬J¼J†Á¿i¸äo“*µ§¸~÷5g¹™ïÑ›ÿXbU1ÓÕxØÆá#œrµFìÚg¬Þ`½e•ÈíZ´Qþ(Å™­ÍDùK,üòíáäoðï¿”]·endstream endobj 1105 0 obj 2666 endobj 1109 0 obj <> stream xœ]KKA „ïý+rì&vÒÏUÖ ºÛ7ñ´âžæ°øÿÁô̈‹„"P]_…>C †0fÛÇÙ]í9F8}»÷¦“;;^"°­ã 7}‰5³Hƒ2ô/·0TÒ±@ŸÝ»g̾˜æþ4°.1i…ÄÀþiá[œ"ÕªÊþ™T[Râ_qbJ)Wñý/³[ݘšß›Ëj­u¹8D8Õ¦$¡lLN¿ÌhzÁH¥p¼lÆI좆LŒ–Èêïp¯¥úÇ5µ‡Z‹sÀ)[T?Þu÷fó½H²endstream endobj 1110 0 obj 220 endobj 1114 0 obj <> stream xœ­\WsÇö3¬òo¸7Þ¹ˆåäðà*Ø´‚P¶«$?@EªD¤DH¦½»{RÏì,p)ˆÃîÄž_‡¹×;±ÈÀÿóï‹—'¾–Zïžýr"v…Ÿg'¯O$5Ùå_/wϨ™Ù)±8§Üî쇓4€Üyµ³^ïÎ^ž|»ÿðp*ëŒnÿüpª¥`ðýùA,Ñ 'âþU~ÕþÍA.QE÷OðL[+÷?NµwKØK)hï•Û«üYj÷Ÿ³¿—•˜Å/q%Ö.Fǰ;ûìäìÏßî?;œÊ%çÃþf ‹T:ì/`6mµV°N#a‘/p¾ó}KÔVIµB+ØýŒFò:} _ŒÕi“A9í L;“N»¿:¨¸Xmüþ׃ò Ìd`c0“Öz¥× v‹ûö!8¿ÿ§’>ú2NŒÐN,&gÝþœÞË®ÉEL»Ž L¬Ê®aU†•BÃ^à“÷0ÁÚ@@Ù³öö3&ÚÜ Døøh ðBšØZïÔþ&µ…Ãã+Ýà£@t©aåOÍÀ† ª†ñœ’8ˆvÁSeã==C*TÒ Óµgl sOÇDX’‡ ÷¤ó‘ i4)öSÚtEXþÓ…J:L {±Š¹Â“³h”Vç½Ì«ÃímÚ¥Öþ±­ »W áî­Ypûßhb£D™( jÇ‹ƒ¾Ò°Ÿç¸‡d¥ 1b<Å;˜Ü b€±AþÎ.Aìpî7ØÄ/Xè²ÍÒÿA{x5¾ûÃIb^Y´8W]PÚ± Î{ð2в”¥#Æ%ü ÙÙ9ïL&+ŒÛ+gäÈ¿[3©ÖrãŒû8%"[Æy£·‚S:…Z :§™<§NÀ¢f@*e²àjy­ øT*>,Ò§¼1åI€ž7¡˜#õ±zrŒ´ ,‰Ï‘O„~‘Ò¬OO¯±i{Ƥ*ŒÁ┋>Oì%[e£·8¡Y”¸ž—÷¬§Jî“e!™è0'«n =Q+Y—~*jE¨¹ZAë&2Y%OB¡(S„wè5ìÐe —žOØ¿¬ò8ÆLÌÂùgøÙßh2Gz¸F¡Nêyy!&õÈ(€')ïö?,X9§Òs<„º`6÷RDŒX?XŸÌÒâKl ¬óæ%8ÑN–=Ây^&1°€—M¢§Jµ\ô¤åØá2ñÀ)ØYWöCu»OgG‡nÑDAòqQ§;ï‡ØP½7ê5@û²ñ¯Ç¡à\$¬³ï^6Rg¸j'ô W.AÄüm,5ÈçÓÔ pRáÄBO;ûÕFc‹™Ê&øa¶€7œ,œ?m™eËØ0•òºÕ¤¦gêBxPÜšiôpWHZ»mp×`µŽÑöĪ*àEŠó=qœ×ó9ϳ2`Ÿ_ ]&‰D5•„‘x¯š•`‚P· 쌫6¹Ì–Óª™)·D¦5ÿ/BJfÑ{Ž­Zƒ6GXýl.Yœöú:MHi1ƒ(Fs<ÇÖ—vzœ½i€.ëcm=ÙÊï+Rz‹K;J ãÿ­[tU®4S®.aT®€¤§ÊµÙ¡¡í°ìÛDeüºz“eÈ.a-AL"ë9CƒéHI\adÑr0Âr½R0œ ĸ7íÍ Gˆyndxº^…ëᣧߴXôàÜ‚, éÓ›¦{dŒ|¼2h_ò1šè³©[‹Î’m®ž„ÞÆ)tzŒ^D²8=Ú o``•>¥Xœ;ð!¥ âêêkS?’Q&ÈýcÚ+`YÔùØɆ§"¸˜\J'´@O­ô¿Â½hƒ.{”@A±xp$"9 Ö…dV¡”Èê0º£e˜ôÈ‘eFçY«àáÌBiìÔ÷Ó0‡Œñ}ú~†G)}_¾™`çÖ¬ØôË ˆfH ¸D8Ç &‡7 ““²yêp¬0›Áã0Ò”l ¦zp–U%l”,_¡‘Ö„Û’26YA#†:9U„À•Ͻh©Ú…#¶¬«N… úÐØæ™õþnïXu.`dõý.$¢6DD üTW¬l¯ïŒÖÙ$G•¸^HµùðmÖ<ÁÝL’^1 ®^SJçhÝqÕ¯ \ëòÜŒv ù5 EðÔ lØS˜ÉÒýEåô(ÉUbn¤ÀGD^é ê‰ó crÐÍ ílêãÞqêyµ‡óÉsvƒiÅÁ?3Ñ͸6ãðPùE ØæG`hI¿`ã‚Ìë*˜ ´¸VxÀ«0´¡8Ñ’Œ ¼ÁÍÞfX™m1” uÖô‚ËÄ€ÉG@ Ø£c|\E¯>yyM¶Í÷­±ºP¬IL.ò…ŸÞçˤéÃGXZ+¨Ñ£M C<{·ÌR£EBaìœÏÅ`Ucƒ–šPýãÙQë¸}b˜]YÀIe_¬ò¿ñX“µø Ž%ˆʾâ#KÖ¶„ˆp OFExêž4š¾½âTèôÁ[\¿¼2Iï¬ô~!›³C¼fÔfÈ¿ù¨´ôƒe ‘·ª÷¢èŒ¼‘áÇñ ‚q;Hp\·ÿšäQxІŸÃvœ“ºŠ0C=!»PEçÓÖ¿=B™ ä°™¢ëßKà;XNo:à à59‹aýÎÐxHáÜö°g;œÙîAYÎWœ>àà®~í"D3 ´ 3 Ã4Žž¼ìðÒà¿%H´òp» >òQ”‘Žƒ@²ðuÒý°ÝÀÃÝwcРä3ÏñºWáƒò*aм¿5ÞŒAÓóÜÁ£y4[b¦ƒ®Å†´ F‰¿]SÈÈ3x}Ù¬aÖ Zf…Oôè~C9Ïüa™ƒÊJ,ˆ¬¤ši¾ØôÅÀàU‰ÎÇ ~)§ÏÚŸ· ªëyäcæ 2É*ý¥š+k6‚Ë-…^Èq$×jÀñJÏqS#žêÂîÝ. ¢Àœ„ö~dмJZc¥hý’H ŸY}i ð2Ÿ’“Å•Ï)s3Fž 㺌]´ %ú"vð6”_Bï†ò9 FÔ“(p b¢ÉN°'bzÕTnÄ´-”6Å#LzþßÎb‹Y.dõ gé’’•¢óÖ ˜A-î7Cr]œ¾dG³xÅÖqú5°oãœS•ÛB!&ËS†­é,<~]©×5æeæ~}”™Š¹ì‚G*æn#óà ,ZWñÞ©Ï,Æ$0ÓwûʘÌp¶fQ7Ú&¹˜5Òšc“ÑtÁF–×â ×µËÏ)Àž›š‚Ÿä<'’Ã]}–ø×jÏ:|w(³ü{4µ%%F"P5"ŸÁ¤ô}qPû¿"þ’A»0‹1˜XÚh²µ‰ X਎ .G-^@Qþ hêe¥é:Lž#&¡Ó’´fÌÓôáoBž«É×ì¨n&’@Úƒ Î `)l”ž/%ã ™  ŠöØqCü™¢ÞyÜÓOÇå0„@þƒ‹0ոñÂÕ}ÔàÜýÕ7¨4Ýr&-7303-̦¸ä­øR`QHWçj)S4l͉I.CÞy”XŽçÅš„È]Ô€qPƒl¦j—ÌÀªó,F¥·2äQ:·ß€þ“¨9v )}ÈQB É´Ñ×™Cì¾J€5žuЧ1yºÜÑNs_·ØÙÍT£2A“‰éﻬQ½‘s¼³vÙ'N4nî²Åv:ÐOÛ–Þ)m6m ÑÛ˜Ñeï m=”’ ŠYo35SÆ<Bõ½{Ë –” xgäIS¢cmÍFå¦ „`…šªà$0}… }žvâ TDÌ>$*©Û‰QGVÿ I×ʨó lvÂJ=w©_püÒ'O »¿ÝĶqRyIzàˆ±‡ŽXÕ|L~¶HñÏN¾:y½ÓzqTpyŠôWQt•ÄdÀ2ÎÇON=ù|÷æç›§'þµ“'þ†ÿ<þòCøõä£ÝN>~²› &ü®‘6ËD»TU)EáNâD8•‹Þ¯.Rò ÉÏÑÝ´°a®/6²@XÃ&r‚úªfl7Ñq†šÌ$7—¾/VtÝ«*¦G•UW ]kAuÎ,>†,W‡bj àÊhÞÐpeg »Ì5M ›Ä–`m “à E Ö%ÉHÑcΜ)ëIu5 Ê‹Iõ fZPcšTdz%S6‹Jqn¿õ ã#°Eb<Å£ÅZhaÎn t|ªlª<œ2÷Ä[Ú ôõ+àà^æ ´¦”ö÷š·’™àw ×W7Þy9]ÿìÙ¤Â.Ÿ‘n=Ž\—„ö6è*×åèÈ›2™2ÕŽ§Vã òâQŠzRƒ×ì’Pܧ`µ”Mýã¾¶³ ªö–Rʧ£ƒàìÙ#Å(šÖGBk) &½›Ö N²ø¯&ÍX€eöº—ãyP˜-sÁO‹¾™W]ölH¯” D+û2—ÆšÇäC©ÈÏØc€xêÆÜê_ÕRÓ1?Ïì8sÒ±Ø4ç”­¼)¥¯5EÎv®0Åø×”Åþˆ×šàµ[‹SÚú–Iyší¿®þ´Oûãðbµjr,軟y4aÄV[5ZàÅ¡+öêÐÕqO—Vƒoï à o>Ä{”b"Зã”)ß”8>.¾•boU¹ò!º4 ”ƒ¶ÂÀŸ)S0E^”ßÇX(™GŸiP«¸+Ñ¥0‹éû ›"•Lå;“RA}&“Mƒ;°ª À´A«, ‰D½=hÇxÓÜ‹Ûîtø©¿.€fNSFQí¹¾õãäŸ&8jʳyë&qùjéC²tuò]n°ƒÙùêNÝŠÎ(ov%±R/\%ƒù[ó(¹|ÑNtXã“N{ 2Ô’Å‹5›Ö¿¿Â]Õ w©¼uv‰ž®h–§©àV[ŠjH)+ípRà£н„#çš\RR+¯±è[ƒaHì^VÂkv/“ó`AÿyÀËD`\P—/Ò‡ˆ€ªÌ~“f—ÄÕy¢Vð›é ·J]¡âÙ ˜”ê—üæ!W1¤.Ÿu¨GÀ{[º&(M(—éÚæ/VÚ‚§X°{ EE­"‰Ð1·ü–Õ¾ÅÎÞ(öÆûp?M¤†«ýTè¨üªz¡,VÇ^5‡”iª¤a– <[_ë2°˜#Š‚ Whä¾Èé‹ î‰Mà­¤^p‡w#«nEÊ®ÎJ/¸Ù¼‹.3öð(ÝcTª8u1lô/MEäW~êªsú&í¼GNsв AO>Oqh8J¥:GyâÏ|g†øÏ“Ÿ0Ç, ôì0x«è#Ö»QÎÚŠÇoÊds41x=®F'vø.B@÷²´œ»6}Ùaß±¬}g“J¿XÅf%áxÓ§³ùÉÕÆ»qUùÛß¶¾3o4^iÊžÆ0üÀÂä™WLPJº°¥ãZæ–ÂÞÕ])ÂEC 1² Ç;¸Ð Ôãò³%Ú9ˆ¼õEÓøÀ„ ±„R5’(|Ì·}$é—©Ü#@4œa~‘¼¯5Ãà•¯ö©Á‡ò‚’ÖÔn ¿ñŠ!†CÒ%úuYÌh„ŽÁŒÈv†‡Ð >³þ`eð o*>“‡twI¦èe°¿:ù?k‡Yendstream endobj 1115 0 obj 4677 endobj 1119 0 obj <> stream xœí\ësG糊?â>%wTn=ïâ Nb‡EE Ÿü¨X’-ÉvüßÓ=Ϟݙ»“t¤*öywvýšî_÷Ì›ø‚áÿãßOÏŽ}Ë¥\<¿:b‹/à¿çGoޏo²ˆ==[|zì›Yx48æøâøÙQè€/F±0V \,ŽÏŽþ¶ä+½4ðŸXéÿ?³Œ~&„ƶlq¼ÖŸ­ÖrGçøòËœ³Ê-³˯Wk>(¥G±<.m‡§RÙå·ðTB·~@l9À;!Ü øò+lúú~,„²ŽŽ…#@#)øÀ¸Y~¾Â£—OðKë¤äqX+¸Z~‡céAi;ñOC×Ür»ü#ô÷gøïq™5>Š3Ÿt§$ŒÁFc¦ CÀjä6R­&ö:’m K¹sz×0okÍ8._„ϵæËÓÕZX>h¥à§‚‡@•åyy¿Á÷ ÿ±¼²=ÃZ¿¶Òü^<]Ék 낹_á2´X¾ ]f–ÿ ?•Ó´Aœ,îrµVƒ”†©åKX1PD¦á7Ï¡ÿ‘‘öaŠÎÉfûMù™_?õsRù¹‡®F)=5œ4»<|Q:­a8`„s¥?|æ$<³åÙÎÓÀê,ix¾#œI2™xzù¶ {š¿‡ÅH&€Ð2v•¹s½BQÖ ltIa^Ð>2£Ï[=ÿ¸Z339:“–ȹXþ°’~fœ4ý@š¾_¡ *œOdÝZÉ.àËO: ZYOÀó,¼Eº-4siÒøžL:Ðñ& ñ³@B§Õœ†ØUatÝø¢ÌæŠ4\'"®¹Q`"Ð2Qb$’)!8% %„r"%D¾Páq:¯Ó_ás ÖA×Â*å,¨Ú;Âh‰BE¦æ²ÛƒïÏk±=RÆØÑäF@Ubå*C“ "±¦Ñ&q6zkõ}nó»&J¤AnNt£¡HH#"àר…“•%Dz´DêÞ©{[¯ é´{N-JžÁsÚ%¯ŒDæ©×0:ƒ²Iy.2‹PNˆ(ERJ`zêÂ𥠻ʨ—t²!¼(ªIoâLi,råF[ÉsŒ¥„B«Öi‰,M&zuÆKu\œjílXc’ ‘¥Í¢PK#½4‚©–ÞÚ{¡‘j$ªˆòßÒE”È}Ì~æÌXÔŽŠ+þ™–m§VjéuÐ=¦ü2,ìÒ`Pò2P#ÓÃw s4—£ªaÂn‚n³ÎŒFE±ô‹i×ø|³}³iXybtˆ Ö}ŽRJ/ÐÂ.»OS[Æô¦¦<G«L+dÁ¨‰¸fŽ´“o}Cf*¦ÐDš®ŠQ¡¨-9:1žò#Ñqo†3{À$[f9K|³*U4樊 ²±|Øò?Š´#a`kAz93ÿ Š™ÕÜ=­¥ìiø5Ôqâ¼lSœ8»z&µû4•oXµ×ãÞ(-mÜ:‡Ô/˜@ì÷}ðyÌ8HÃ>ñ÷Ð;•ÊïA ìÞcªèá‚i›w’ÚÿÂÏ¥¨ –c~é91œô¦÷²Ù‹J%‡[Z˜{öû— €†ߢºYÇFÙßkBb¿®Dp{"ëânÏ/#¥B¬"¹¤±ŠTŒôÕÑñ/þæƒ,oòÀ˜Á_àMùõø.¼ø5 ãp·—çO|ë'¸BÆ8ÇPsm Ä|ðfÀ?þŸfÑP.A#B‡ãü%0hE­ßô|'.ŒÞQÞ×Ã1‡›Œ_ExxQZžç‡`7´`Þn|—^—–—ùáËÞç8‹ûD wÕ:âÃóòðšÔìH9‹Ã>žž”Ÿ…ú e(¿ñŒb*©äÛòúªšþD½Ù”§Cþ xè¨6à™@±F– Êk°×YûkOæ ¾)j>YéU‘|èÿláhÔü§ïð1RްäCaÞ«½Ù|u76ÿžVÄß—‡ùáey¸É?Ê¿>F:Î> +-²ýº#óÎ+™ˆ_ùY£`’ÒϳÂï³ $Æ cöNN+2YÄ‚8„OjõYm6Ž“!ÿü>J,X£`|\tÞsgbZ­™õm®³ìø†×‰­v"K^vpCÝ*D^¶HYM!þÚ$k§ ù›Ê}YdNÎLv®g«I§5Ii›Îø =po{‹vg¥æÿÆ|”ËÏs›b¿¿+šý"«°gÞ¦¢®WÁ°/|œlݹ%¼œÄS ) '-2QxÑâÒe”A;’£ŸM!=ËÏZ²5×É`­›$ÝÔcˆÂ´_²äº†ÎÐ8 t`þŠÇU›Å ÁÙ ¹$¡: uÀÉe?¸ŒÎ’sÕÅX$W~Æmè#±/$æNÙä–á—$`¡nŠ7ÓžÓ·‚Ûˆ»…£|‚RŒæ l©K[a1ù;î(|s ¥L½t4§¡ËC™›‡øSø3‡81\ײ×ó*qÊJx O†Á¦jc#!œùÕnæ°H–Yw˜$ä¤ VÐjrçÉú%0ø·Ð D'Æa1ÖóX³ º')º£.¼-oHÄWÇ2À†»;b‡W¨áùjwXÙAÝA3»ÐÏm#¹„ô$AE®«`:…®ä¤’öóÆâg“õæ¼ ¦QjoØçŒU|’êGJvx â2ºn“¤¹;¹Ó0:®c[!qÿlÛ H–¥Q`•ñM¹l"#ò 'áú1bœÐa  „[·#æÈ"vŽ$ªý3b×g¸oÒŽ)cnJùŽ‘»“&bSYøü|6 †ó}||ôÍÑ›…”ž¯l±Æ‹ƒ‰„]@Ð-ðï§gGŸ>9zôä‹ëË·§Gþ²àG¾Ä?>ýú3øëÉo?;züdñÍM“¡ÜÀÃða4!J@§VŒ‚=qÁýUXD¢bÖUk˜ÊA PȺ]ÒˆPßû„ó  ó6s”‚‹†ò’Vo‘Ñ’)‘¸jÿJ–‘ÚÈ’ôìRdŒ²7¿#jšåaÓÚš7±Ïiª#jA—g™lÄ‘ ºL\—Ðþ: ª6ä¬Â”l¾èÄÜÁ„v¡>yçœ^æÆÿÌÈo{Í4 xt“„Jãf&)_›€ÝU‹†—´ÓDíˆ*ÿ„`ã]Ü %ÞW›ýeÐX}àÛÕÁv®ŸeÎmr»gs‚ëg-~mZ\x–~ø?×g\›/öá:"à~Ç \?ÉíNÿÏõŸ×÷ÕõËÌÍ Ô—š Ð[wê.¹æŒr÷²E®‚’oJñi[¦<ܽ'o2Ç^å_;õT™ÑRFlZK}ÕzxMNÔìPI®^-up:kï³+¥â1ƒOZsâòï>A—d‚›î ¹?ØÔÓ¨…¯Õ¶Ù#öìÏ[*;˜‡˜7Äb¢ž÷Ä Ãá-@IBkmÑ"Ò9ß  gl€¨µ|œsR·UU³WÙQüÔØ;¸¤‰ÔcZn„‚9;q׊kˆ*Ç~p+¢‰]$‚õ¤Ó“†ðΣo!i 6ŸT§•Šth-.jÐ)©1+¿&`¬¯^§‰«6Î.LØÕ|™¦¢ÕLÖ’dîWI¶rZ«™jué€QÑxÝQ7‡§Pè¶äÀbñ5æ«zÅ×cçÌÆ¯ 2çc©ÜǶbB&@žU•e/ë #\OIö,Îùؽ´Ek_“|mÁ²`EÏaÌÕAŽl€­©™¯MuÒHµœ®ö@s ]N¥žÒPäu„ÀÒ'`Ÿ$ £t„¤V [7«UDú ©Œ$iÝ—tW+Ÿ•CĭǶR.‚]yOÇ=veÈ:0!ž^@¸vž~ˆé:ôŒl8C1©<>ÃÁ9ìùª“¼(Ò¹†É½eorÞ¬l;•¥4Ú9-·ßëtHÝ‘'W•`}M›§CT2kÉS’¶Éçfª´2<œžmÉ+ì8ŽJös³aJ|_!Mð{eÌP# ”¬ô¥>êtBÎ¥pG$ÖGŸhb7k\`lÙù`”“p¾#òSxÞØ”äÁE¦Ï‡•ƒë†Å#èÚñ-ÂØôµä\‹£‰Ô%qÒ)—áP»ò>aó½t>Áîg gâóG[ÒÎ|*íC¡¹÷ýï/ó >:¸Îšaþ³íò'õ+ZÖŸ¶q>Ã|ÿÓe5éURý [§†ÎxTºjÒ{8ü3o¾¿‹Ãïes”©Ìd43¸õ ã+R&5WB“C¬lf§²­ˆ®š´šV²à~Õh“dq*ʼnÙâ£ÁË}¦Ò•mÇD1Ÿ-owæ²2>±ÓcFñX5DþÜs±wdnæÉ¦ ‡-ôd%óV­áÊ"{U§1WíÜú˜tÊ¥¶maU4¬“ÓË)9Í ài*R"ë‹xíª‚×!u-©óâˆ^uCz8ÉcKÎlKegS®o{¬Ð8 iÖq)|×EŶÍÑCb¾öqZTµi9˾û¸p8´Ùr‰Ð6Î*Ö meUåôož)_c ÌÅ4ÁÕ@´·×YÆÞ3)¸iXIOëîY‰°g¨çµ§{ð|ZˆÀøŽSéd‚8Â';rÞ°shãAÇ{O–]ÅNiJdÄòIá±ZÁ!§À„0FKËìT×o­t¯ óT¼ÿÈ;é~½ËzŸ'OöÁà«<йÿìÙn1(§S^·Äà¤Å² \ÿÿ¦É|ö%Q3g[šmXJD¥†|åA)Zñ:¯‡ ÌCw€ ÛÂ(ˆÛûÅ—žžrRMEl_Ä(­ËLHÀ½jßëÎcõiR­DÇæ¦îûÈî3ÝÚ•ôëÜzq¼=f :ˆ¯o°e„ÈvȪ]蛣„é’ˆìÉ9õB9r,e‡ ðÂü†:a0Ô®ýÝ<±mYóSÌ@G¤®áFã³òIy;óF¦¥¢³«â¡e$}ïÌEUóŸN®uhN†pIé*\ÂmÝèr6[IÞaeËÕmH‹"únMª5­v¼ˆÀ¥‹ôäÜyD.&u𱲘ºßM‘¹Y!h>÷´-Þ!hIóä~2ÁýÉL©•ñõ’ÌuQz¤K(Ÿp9Hzˆ#¸|‡ˆ;1 EK†¦µ.Vñ`ËÔ VV¥2ˆ‰œwtc»¶(ä¨9®]»þ^ÄøA.‚ÊÄfù÷eVퟗù}ß5SØnp†%Þ'š£ÀjYép |q±u1èÁM }f…hW“æd¥I;zo×:)ËïxU‡e|amÜ2}¡f°Î}ÁEµŽ•Ë¿¯V!ÃFq”‹cp]ã:!>½»üRŸb.[±¿À,VçV½ÖNÛÒ·:{·2ˆs)âà—Ò¤keNê oÂˆäÆ¾æf§…Ç÷@XB×M bpÉÙÂ[zzšúK‡H¦–ú"rö˜äÅF/H©iš—Ì N0aïÚ4*f!Iu QÙ|A•­¥pü£q^°é'‘Ø ¥ïœóˆ†kTå•Hefž‘íÝgÂât7µ6N€}öŒi£¤s´/мkz˜ÓL鬧T“‘e)ù3‘Û»rÀA¯Ó½ r ›ËgSzgâ¶å!VÏ´V½üBtH%¸DF˶$ú.Óé×U7@%®ÍÑÌEUƒ#ñ”)s78/×S×X¤hwðë›ÈE¦m_¼gûpqËÈBïnºù ½Ô4S!s“Ûˆ¹âªpVx6ëàæŸùcœw¸³†Ñýnq PHÀÁ%ús™²èêêÚx×k㪷–E oÃ·ÌæóòãˆÚÖMÖ%„‚ìhµ|^ofD³ñ¾ÍYYPC{¯”Ùñ@P¯sl¨oéï@Ñøu¤h½ Ý{Å/©‡(øõ%¯`'î÷Jëñ{_&v²ŒÛÛ‡!½á~:ç[sîû.õñŠÈ=êBe*ŸÖ`zR¬Õ»‘!GgÏ[sjºñ³Z_S«eízàíèzÜNq;0û*e.îâ=»<‚¾egœHî-¼í‹KëT¯™¢6ê¦u—¹Ö»*{(Mâýz0ŽàÛŠ‰0’Ìs«Hd?°Î—ТG‚ÒÞÀe`¬ï¹´Äí$—4Ò¦*;D•»`¶B˜3Ú3µ!! »7Êd4˜wÀh3ÎÁèàs3¼ƒMƒ-œÃ!Pi”KâWŠ2s ¿d/öfû›£†Ù‹endstream endobj 1120 0 obj 5096 endobj 1124 0 obj <> stream xœÅº÷µPêøâÝÑ|ü'øqôÓ‘ .Çéϳ×ÇN±›Ç¦)ÌAŸþpÇN[¯'!O_}»[³‘ðÚÊÉ9§6оœøyž¤r›û[¹ùz{2O>Ìn¶Íóým˜§Yhµù_èõ_ۥ̤Úü'³ù;¼ù¿jmœÜ|¾Õðƒ³as½•’Jn¾ÄŸCð:ðž…ÿ„# 'õægt.±yŒ3†iž=‚i ó°i 2h!ñ^Á€y–8lÐ4€’zÒ*¤žAÌzB«ƒÎjóà(­t¿<}½õ®,àêD™‚]3`«vŠ£é@knð’V"øþôÏDžo®6b²ö÷ô<í©…ÿ°•¹·>0´¶{Ÿ¤î'jÆu†ü–œf§g ô@OÚ!(ØàÙ[ëDØ^#^@¥5³›·ˆJc¥†u¥ga ÷ÙVÙÉJc7¿b+P¬ñaó^tf €¢«2Å±Ñ E´2ya¥Ú¼¤‰… ›qé”ß<ÇV ˆ:ôÀr„Õ@'ˆ¤ÙX ÅÎ ¶(öú»¬=/ÊœïáÉh©ÍæÎî'§¢8÷Œ¿kaò¢”ô.Á4Õ e«‹=¥ ž4>pÒb %ìr$‚FœMÂ…5“þ”õ“¤ÅÀƒ¨j×§’WeÒ²øwÛhWJ3¦…,üñé—G§Ÿ~»yH,âŬ«:5‘ý û~ZgŒÅxØ^Âb%ìß;l5ÆY¹¹Ž}-Œ7õ5xT€H „çLúïanï­8ˆt† @’'2›~ÙÊŒ£%¢ÁGùCT†Ç9z+xxK°¡®êû ´„6HZùKéͳòô2ËÄ˸„€3Ioa~ŸFwJ!åuÁbÞð3ŠXøV¦}¶1¨‘L»ÞléøµN_ǯÀAg%`Ç1jGDà« ëuý5‚m­³‘ÎÎeU—[¤ „Äb– â§u$öÎv'ì1°…}Ò0Nød0H¢€"Dž< ZÆå«Ñ@bí /Ë›—u¸¼ÓÖRäµöÉö ¥G”Òg¸  âFGÄŠ§-öJ"RN2VN9ˈœ;qn$­‰â„pi{„”(—r‡ª¿ÒÖFkG†Ç ¢˜L¨(Œ£b„ZOk±³n ÆÞEršɸ÷EåHÜí…wê(Œ$Ó`ÁG²ì @^âA’ó h8€Glî¢Ð [ _Ѻ/ÔyBiU–më(O `´nпVbpègò€ÂÓ–U~ ’ÊÄ”Ò,“@B: q½™9FyžÌ…Â8/Nl$á}(%íÆù/D­REÔ¢0GD[|/K]„¶åŽËbd Ä>Œ ôÏó@¼ÊEØ¿Ùèʇ×õç$AT!rø9²¨V¸›Ù“˜'c­ežëÊi3¼ðŒ% Q‹Í…Üëp¦i@Ëi9ŒÖx®ˆþï[«-av ‰}óãVÉHŸuN®7"MK0O;…t^ÙøÉøE!÷ÅĤó¦ê/… oi$¡\ˆ"‰Éc¦ µÖ@Ñl¤%ªsÏmÙ/ÐÐr$3¹¹}1a`y Ÿá#ñç'yt4gøæþ'ø3HrÁi !=¯C0­&û“¨P 8ª(”P]>A€‚ý»M!§ì”²Úøöݶt@Ñ«Œ_T²e´Zæv<+²~ˆ‚?AO´kÐ8ÂE<+³G×zíÑ Iü¾\§WØ6 ze‘Q KC6“ï­RD=Pi˜Qê›J©¬µv½žå—‰B¥®&ë·30z P¢UÍÜj¡±f"MƒnYVÖ$6}o5öÓÖ`åNUYƒÒ@„a ¾–ºÁc#õáæ_ïdñLßÝM$%cÍh¢1SŽd*ˆìH³´(t S@ã‹U‰\ͽY0ú,ÔËL˜¬ dFÔUeϸžìÆsAŒk;¹š¤ðmù †•Îep5îôm¹èX¡âëCÖi™9©04Až5Ûô á0ÅX#åŸ;€=F„þ²NuŠÂÞ†;üyƬª} *š4ƒ7Ó™–HÎÀ2ÍÁgÒ×s ÉùÑ’·ÖI„Œ‚4Ràaú‚B:´M§é½âÊü•i¶¤7AŰ… Íž×!~Þ°§­ôŒh‚¯¹Ì.¸iÖév‹ød­ÓÊ[{#aX‡04œÃÚêÉE² @È$7êHç³ÖƆˆb\Žq$ÇGsäA•k ^ Ö*…IBjÛšÄ#Ò¬„‹üßxŠø-’öxq¯Økk‚W:¯yÄŽ‹æ«­éôrkˆ&3óÊ„çuÀ%Ý ­"Á9Œ û|o¤Ö› cíA 9]HÕá¨k”ZÖ߸ºC.`7“ìw³ç¸I†¿œ7qÁ“ŒŠÖz)ØRµ Ѝºñ¸‚#‘‘ „-*·M‘J™„˜ö ö¬æUO€È½ÜHï ùï"JºY˜ug+IÂdcbæîr;½qìr°-SúòÀ0 ƒ;á1%PH „ÚuÁè±6#BŒZ夼‘½âž0o§À{§›½7Õu‰VSˆ ƒÉ¬K3}ò°sé¼ÜáÑá{hK ;µq˜¤ŒÐÚýXãe(d?Ãǘœ)Œ¦ì‰ôüIÌT`¤†lpÉ×hÏSü¬î¤ÇÖàâJ)†÷@û%]ãZ¢=px Ukì©Ðh˜¨)¤ª¦x:ܲ.0ÙXwŠkž漑#”ΰ-Jа“î÷ð`LÃ!÷U]Ñ[O+­Ò`Š-ïó¤Lìœa¶9¬ãt£S–AÌléèª@m4¨“¥-Yô…Žk05á̘UŽö|ü ¯öÓu€µÃòn*ÕŸRÎç7¸:ækbÆUkŠø0k}3EÜIa°›y5Q3€Ù»Œföî™c ©™ÔÆXì"°ÀE/¾Ñ$+ýý#÷*ï!Qù€)ª6vª-®ÛS+™ï£R+‹²Qî /|’üˆžÖ`tÕ Î¥ì·¦ lJ®€g,°†Ì1Lx#7Ø“ž ]‘î’Ö’œMŒÙu£ü7Õ¢Pµ·@º”škœ“˜b¢@øM6ØÏRêÎ%ËçLÑmšƒÂ@(cîÁu{èíxƾK„IÛÎ §FÌn‘ωûu‹ê:çt›¨þNe†Û‘•TÛcÆýW·Á‡—Ѯ͟Ef]Ù‹W˜î ÖV7% §­fYD÷cd‡[Õ=ìx¥ñ.‹˜<ÂÞo|)ÅR®1D«xŽTw NaНw~²6©I3%gr›hF3½‘<÷ØÅ–9¬«­Š ë.vGpU®T†*ä{´;Ã,lÇa °<^Rcq¶s>uçqp†OéØ}0ß(>E$¢Àrøˆ°Tf¿»™'ÿ«Œ)3V@KóÎÚ&*ÛÅ#gÑF½'£*šÞ¬êµ9Ï3ÜðžØ³0æJ\š_j„¶áÄvþe® ]íB•Mâ•ùâuÜ_7“ 0Šç44!M4§V ÅRŸ½’§j«6W*5f”ÝX½-óY+Á ó“ m”{`g ýó"q¬¿dÛ×B¦%Љª;Y*BØ8åÏ9½ ÌýÎ[ jÐf £À_Ae5éÔK®m¢­bçIˆñÜ¿ÑL\Akc¨/š •,aµÎA↔7(×F‹éô<ª¡‹ET»«èt­¢û¬1› U…¤r­T+‡ÙÊ_¶ ö&P6%ËíÎk]Ù7øºÂZ;V–V+Ìj-bÊÓvÝB­Ø!°¡Ú¬– †&Ë/¾¦€¿‰F’3öl»KËà¦KöD)*¨ÔØ™YC»<’‘•dJiÆ‹;„w)ÎUK:Ú°öMÄÅ;)OevEÚäœÁÚ„þ2øç\´EãÒÙÖðÖ³'Í}É»æ s0ó4ç#iÇ"°LÂd² щBœuú¬¦–VŠÍáÄQ%Ú¤æYõ·6@–—Ë·rg£]ÂüàërëÒ°Ì’ÊcQA¦|WèúêÉ6†ã5‡+[Î*–y.ãÉh 86KéšÝô$ýJ üÞšCÙkÎ¥êJÁÛa’±-Ò¨CO©Âf—ÇH(kÓ§ß”Rm,?g%á¬Ú½©füÇ’—•ºæeo¼<¬“(Ÿs)ËÉõƒêË]@f ñÈK’WÐ\Õò…›óc,ÖÀÚb±b@/r·€ÖE|Sé=SiqV(ö> 5.©4¨›S)xùœJ½#*]e+ÊG˜ƒi/Ń(ÍæÚ8» s*‡Á$ÊA¡N¬^ œ[ï&$µ1›&ÆÀˆi+ü¡ûû<¦wF¹ÅÒ0“h"/ _ix4)¯(¥ñZ:'½dÅ­‹yA~ìRÊ+À6’·à‹–ô­è5E"-¥#­ÌS®0ØQù›ܪ痳[Î.LÔJ¹ ¶áΚ&³et'üWóµÊd·  L•m¬à/£ÜÀå¶”Ý2L/D)¯º[Võ8D!Õ2Øj!Cæƒ7C†dÄÓU,3‘]ˆðnÊÿ ÁËð¯«C†[(€è )×´ŒÓ†]}¿(ûE%þx¸e•XN„Õ¨J}bûÏj:¦aøä²"¥¢c,RjÔÐ+»3$î¢AC+ÅKQcÑ¥õÀÊ€5²1U…A;Íʱ—#±[Ê7õJÊÀ6%~gv6aìw&‚0HåÔðÐè"¦H2–×êe;'UX¶#¾+§W‚\Ä›X7*Õ¶Vq­Hç%<×S©'j…ýxaIeýÙݶŠ3­‘q¦„öƒsMÞuF@Tzh³>©gtv‡öL)ôÑBy³=9¶žAºe$—£¬°°Eõiw´¥ª<<#»rÄÌìËåXà‡š*%p‡²Qº ¿¦ùÚI™G´¼À­95“£¼«š43|„…‹BÄÍÑõ# âEúÕSOmm‘󚳨·¨C¥p¢”Ã1Fù‰¹ì| íŒ@‹è>?²C- Ç]4i5šZå‰_U´JÖ|Œ<÷ò€Îݺ¡¯¥ò-~òqì\_¦Xy—ÁUv'9EX–5Á71ÌhZ£:îZšøØóWNZJGÅx ÍŒ=™Ù™rS“.g£ÿƒ×‚ô-›¦*-É¿]¥‹žFùŸÆ–Á3s –î&°¤_µÃ¢d¼¾á.ÿ’ Œz»§1¸ÏMÅÈ"¨…í5ˆíçÌâ³µ·žVæaŒÃøöíÇA"«¤|ý0ö;t@F…hmDx`g¡!0Ó±…®.|GÆ5i*–åÛ—ÉdÔòŠƒÆÚ³Ì6ìôÕ½-•êaù ä~cDdü±Ž1" ›³é—Ôøò¡žYÍ/*c‚^ÙÞ¥¯ÓŸÅ’†.â´B¾œ…J!K_¸»7–ë}Ë5w9Ž(·]XukË: “­>º1AÖÀlWMç«8{}`‘Ýñ Ä&«Ûƨ’³<:¹¶ŒA0¥º8¬œ¶7uHäÚå±Ì›h69A»Æ¡C³f9–€È>g½Ë8î6‰…œe:èS1ÏúoMîQ Åól'i\0ëS‡ðmþŽÃ̾‘¶ù?¾ÆêòÙöˆÈRm1–u‰GòöˆÊTcã\'Þhä ‚‹þ|[ÚßÕÎßÃoಠo?/¿¿ª¿Ÿ•Æ7µñ]i|^q§Av£æª#}¨¿¿)W£‘®kã[>¼>¥LrãËÚóõ܃¢õbjó¿‘ÿ‡ ^¿Ä' õp:sëUÀ€Ã·¡VÖF•P _`úÇÖŒéºêOëÆï6µõ¤´ŠÚH'bë÷C/F»òj„¶«Òø¬6ÖM»,OïG›Âœ]ÀßXëÏGbÓã#ÆZ®š×ò#ì}íûk³›¸…´]x§ Ñ5-›ÏSH[‹[ÆvÏhõ~nYݽ³Ú­âäbD½CDU4¿n.n!¹a{Öà63Ü/£ßÞMíœùñb±øøb±_ú& 2Pí2íbQc3òË&àGޝôA]<~¸òQ¾Þ£Î7ÚW[Mm|TOV­ ­™°¼n±í®/ÜqJ•:Cö•åéÞˆT2Í„kË=©ñíH _4=3ü0’Ý×1<®S¹_ˆ2FRÄ6JtgÆÔ,N˜=íb~äC5b½¸ƒâ]ftði=£Fžka~Ô§÷EâBÚ³‘Ôfv\þA`yžA¾?TZ“Ì츞„¥üÚÃ7üOâS0y[Jb'ïd[àÙœqA´dW],¦z9èé+£ÙjÞ¦ìà^g”6õi†x5Ï,ƒFÊdz´Úy> stream xœÕ]éoÇ‘ßÏDþ~ ÷z£é»;@ˆi­Mâ“IˆEÊ”V)Y’eÿ÷©ª¾ª{zÞ#MzM ûifúª®ãWG·ßÏ“8žñÿéßgoŽ}#”:¾x4ÿ'ü¹8zw$è“ãô¯³7ÇŸÐgMaâøäû£Ø8vòØz= y|òæè±5 ôÖüÏÉa3?ófRüv>>9‡¯owjr.±ù|+¦¼›?låæ«íNLZ'7'õ›'ñ©Ò~ó Ž))¦YØÍÓ-¾pÖmžaK”iX/…Þ|‹c™I™:¡§±ká…ß|ýý þ<©³ÆGiæ]ÇiJÒZühšgS†!`í„OTk‰½KdÛÁ’!Rïl«¡ ¬zs ¸ÚJ7=«Í[%q\·yQ¾¨o?Àj½·0è«-}¦Róg¿ù´E:ÎZnNáÅ{x!Âd¬ÙœÇYê`XÏq4¯<{vÉ{~ öH=˾8Ç^å¤-ñÿ†LäÒôœR›—|´žå„„e<ð±mó|0)¥ƒl† * )•¦p•3´W…äØ=6ùXÿº2…ÜOËç”î<ßÖçµÕ{œ­1Á:ÀÉþ¸5zrA„DÜ}5+à ‘e'ÇZüŒC:`<»ùnS&ʨRY‰³èw[øä$D&±™ô t‡Ñ€ãL­„§‰Ò $dî,ÑTÍ’O ©ð߈IÌ6 ¿ÜŒN+ŸEn#­§å².ζÊ!gŒ;8Ë`«ËüiµËÄÚÁ2Œe¤ÙB¢gS$Z€ ‰V›×IXcN ñL{ "…AÓoÄyêX)í²³2ÓÎÎyMJ)méÓ$Qùóß%A‰R¯„âRÂîUðÇ'>:ù÷€†Ü)\í¶" š,ÿBÍ„Ÿà¶Ò{\#r> V_¤§¤9€dÃüL#Cë Á³èëàÏ:BSÎè²hûÐ3`Ë^r¹Œ6Y1s)[ÓHoD-ßbeÇÌÖ>DÍs˜ýØ e^Y”¡ùó‘\Õ÷‘f3̃¹oëuÖ3ö-@@›ŒÐ‡󗵇Ü(Ù ¢Nk7ª~—`8ú,i¸ bÊBl2޹àGpEÉ;kÐÊòcŸNLÙ¯þCk3¸ð$E’ñ=þ5¢ÿUç6Y“;A´Æý¶#qwžRc”ƒ¥¯¿Ç>Щ ­’an>Hu .1e^hÙI ­’ï5YÅ¡®f”a¾þÒÛÊðçû8‡äX[é[Ÿ‘·È¦²%G‚e‘ºEGŒ–>§Uµ|œÕ®\‚m} Ðè3ÿfA iÏ«C‰ÎŠù߸#:8îq2Ê`ÿÒ‚zÒÙQZ,à 9:°¾m˜9ž;?oø í9hI¦¥²?¬oîs@íN¿ ²L¨•=4@(æØyÓØBÖÁB#O° |7Õ–a¯ê5Vî’¸\Ä%ʉÄ7ŠtTÒJ+ZýPp ¤ýîÙðHoí0ŠTUö +ë)øÑEa^à€–<ïi27a޳™ª£<¯¡¢ÒÙCFÈÒø5$?‰^- zÙ{¦Î±_o«AÈA”Í#èÿ0‰ªìÌ܃‰›¶ªï«TUÔ3u˜ e¡‹âœRü™õ‰ú$Ä¢ªvåQËÁUØè·Ed6X¤{qÎ0ÖxÚß„§R¸ON޾>zw ޳¥?4ðÇ`ºAÃùcƒ°[zL|öìèѳ¿øáã‹£G?G>Ç|öÕcø×³?ÿÛÑ“gÇ_ß6 ¨ã º§”Â}¨ˆ²;/’©u° jü2ÄÀÎ$4)†ýíHCŒÜÂÞŽ} L—¤9¢üèmŒk ]ÐC¯8þ µ24ÁqüÙ†¥Gmþ¸Eœëlèb §8‚¦dËTDUb¥;€O[[(qæÔÁ‡É2ɪY'ïfÂRk|–i9ÇD¸‹òÃfI+È¡ ³0¸ç¦à-²½¡Þ.íÑn¯“Ýb¿eÉßp©•6†0Šéys¯»lIIÒr—5…ޤ ä*3øÕQcídYhKì£þbŽÕB[Þ@/Ô¥ðlY:À[¶88ÓR1uvÍÕd'«i2Uh˜T²>5|›7ÛL“oŸ]’¸$“5Ê7þ¶DÍãm 2¿¿³¬UuDÁ1ÝvªFºRw8ë‘…YX:,Ø Q$kkÏ[¨ÚBü[l/ÕÂ]n$¨²<£=ã¯^8ó¯Úû(¶l½Ú'¥i:næÕ¨àî{$8ŠŠòž1ÂR9+À‰83žîBá²$-Çnjm6©LRЯC›Bþ Êô›-¸ À^–ë¦(zÒÅ.þÈ^Tn«©«ßÖ÷êû»ó_”H«)HÔo6:¾ü¥MïO‹ô7K¼‡~Å. L¥ TãeßçF¥¼ÓŒžF±ü±÷Uä™ >M÷¼<Ì’Q5ÆÛ…ÇÄV¿á ¼<š·//¹‹uŽoPš”mR žøù%Æ5Æ%²|µ §±!tx¼ é2ËÌôioð÷ácV±²Ó6Ö©,b\¹ú÷ÀºyìÆ"²þTór£ OËI"9P°×ÔªÀ b…Ê=£2>°~e3¦@²2>X¡Kòj8½Gé`5È"¤K xšš•ÛáGm°·Ko#Œ6€ÄŒéÜdÊû&ËxJ6§’ÍQ&2çE´ÊðbÛÕZd\›:ÏÙ/åuà7†Q9ϼø©¨Lä°Ê£¨³LÄ<ÍǺªñZd?à d›,ui¹¿«-RÉ#§3³R!•ÉÐtnT¨=* *QíÑÑÝc¶â*É€ò{´ú Â1 —.è|ŇÈz2Ê—Ú Í˪6Ëö`O\ùBÉ•‚N›eË–ØLsI¹iÅY++ÀðGùsó$„Zjœm¬m5L ÖF^ $ÜVHY‘—U”Å\ÉRÒ:Ð…ÿg!íY:ŸE@8í¯ÇÉùufP`€4„°7“‰…––0&ÛfÑí ÎËõstÇq§5¨Ö…Ðrx !¶tTE²¬ \€‰ä< C®a\™­Ü „œËÍyù Þ…¤ªÒ¹nçíÐèm9]yòyoÅéÈœc7å«Sa<¯ãéÒ,,BÜÙNkMSé¹:Ðå*K¬¿Å*Ë‹†S‹‚ºòvˆ»éz*žW7•Aâ+ŒPžŸ|[¸f–ÌLÈ2‰@ýö& Ž×0Õ7<ÛÞšÁ¢Q2x ø$œ–ybˆrºp&??"œ‹¥•_óÑÓƒCyL—5ò7ÇëO1ã$­7çBõ1'+EÍÜ&ð’ÍÜæ•lj¯L– x8‹D¸¿@l ŠïĦʱAq}ºJãׄK´746)Q”a¡Þ€/îI㚦^öžBxfXÉÐÙ˜5‡"2¹›üÒÅæ¯vVß3Û—Ó’³ñ"8‡Jéq ˆ§a$÷¢ qK0.¼ç´‹è¯-ƒlðö Mž^Ë5ÉV£°£to2hÊÜiÙ²’°ŸReB2JÀ"83r½ªƒdBÕžÛùØ«¾&='ÉV qYºlU"R‚êl јlÈÐ%=l¼·åÛѽfÅ u¿Là"ˆR“D¤Ó'#ÓÊ/ À³—¡»SB‰+vÈå¬ #·c‘µ úyxǨ®æ˜NÊ÷®;çíf´G˜¤Ž’ƒC@ B¹Zû±àh¹§¢YpQQPýt+8×¶<¼–Ï8t÷“ ”cW¼ÎÚsË驹-|/¸~U„D,mh5~Õ¡Rn#JVŠýv*u9p¬oyÍÇR?¥3@ÀqتÊÈN…_ž vƒú‰)¡fOk¼ƒuˆ`Ûò»r©ÒåÃèY¢¿ó¼~Í€_Áÿv„N§}"[»Óœ-s–üÒV©o¼* ¾ˆîuwŒ.«ÈwÊâéC­o’^§snJ,ŨK¯ïÉ4H7ç“.`NtœÀ»Õ±¶n/¨P¯»÷€xçq‡@ Ž3ÌääÃ0Új¢¸W•0>ܾÐä¬R‹Ty:ÁÈ#Ë20dßo¾PÚc3q¨bQQ®Ä;tl§Ä²ÃhWêóìQ¦"m[û„Õ/ì° ³å²¨™½³CÔôSSñq #³;r-c•à•Syç{ž°dÓÆ^YÕNsuMžµÚºWOÇ€W›ïVñ¾Ÿ[݉ƒê>Àüó]«A¥ %aísð-Ö9ä)¥ îCŽŽ\ãjæÙd½Òª‹)7§–º»ž–—Ú¼m58yAaä¥K"V­QZïƒÂ׿ߖ›Bd¼rïaèr˜¼\І„é¥XÆ“¦cj¿«l#½‰†Mt$ßê¯åáþ2pâPë¿còÄ<™2İ‹d=«Ü4@kY4reÇNÉy˽·Øaµ}÷x0tV[ñfr¸8Q÷]e4µ7äCúX #ZI‡ÔÂL=¤&°¶Ïià2idLjϰ+˜½KUÞ"zzEï…ÄØuþõa`jGÅ…3:YA‘ãž¹ï7Ûë0­öñ„°ˆ¦ÀŒ&UééýÏsz¯]úé„6õ5î³Ç[¶Ðã™'g¤ð:öp: 7Äù€6^¦@žŸÍôtëAp}à³KóÖwi¦Þѽ¹§[âha†<ÔœÉz§:TT¿»<îˆBÐÖÕÒ*bqt¾¹â„ŠxHY Ïúßîô¨67ßâ¶DGZ0]nÓV—ŒËË9R‡¹Ê…=­Øw„#WÊ×G™ïnÍ1>àë! |ÛpPn8~R:¤$º¨·Fv÷M‰xÈ0˜vÝš•€õº)Ò"Þ½:róÇ—jU06ÂqÍÍq&EüÔ§âŸ/ÎPÔK¨-…šcñ@51mÒÝ}ÓžEJîŒ>a”at3b* iý#“]!Ø”­÷>:7ÉH3[@‡št/{niDÎ)·4î]×-jTž„ájˆRó ãSEÄ-®YÌ%*V‹eÌ K‡Œ%Ŷtebìl]fÛÈÈgØqÍÈe­öŸuÚ_9\ß®89qbõb†µš˜\[¨"Q‹z#ZǾ²þËê‹4ÊæåÝßåéÆýåPž5JE±ËŠ\VL–o˜ÃðPÕþ8*+é ” ìŠÅõJÚÿõ¾€a.Þ*´_­ƒíýz1Ü9¸Ì"6•×íß( Ô•Ü^lÍXC')V>?Òö«,š+sU=¹5ÍVrÛÃâW,ªµˆ`$ld爫lè"k)ÖEÔiMÄ?÷”´Ôq6Â׋½Aå´$kÌŽ¾D†ßxn¸’æêع»,±ÔG¯¦(Y”+p·ò{gÔBJ iŠ·é>|½ªñío šUŸai¯×¦šÖö?pÁ’:©d² Ìkœ˜¡MY‘BÆ ”Äîk2[ÞXaÖ6äú--Y‰ü*'ž¯˜»3€ã0Ú 0Ñë—Ôš•þØÔM€òq½MåÀJ¢cÔš%…–í Tn6VNgpÛß_=çèýìÂ×å Ð'lž_bH¬?žCÁAÉŹÆëRQ¥¶ÿ¶ÐnXJhGÄhO•ÿN¡ÅÓt/°w=C¾ô˜Zu5ãÙ®æË!Ài£¶ÏGòPU­Q«ô_ºÔ• ü«qngJ¶¶hu¾©J ú-S~}ô/œ/—Jendstream endobj 1130 0 obj 6336 endobj 1134 0 obj <> stream xœ­YY7 ~_ý FŸfŠxªûxl“4m‘^‰ dû°G²`¯4Ùÿ¾$%([c§‚EÆŠ¢x|ü(¿Y‰I®þËÿŸ]}óLj½ºx{$VOàïâèÍ‘$‘UþïìzõÝÅ~5Eåjóê()+¯V.˜IªÕæúèÅ G;(ø›F5yïõàèÃ:1)í‡Í¸Ö“RèáÇq-§¥ðÃS|Œ1˜8<ÆGc¬WÃzÔ“ÖJ«áa]õ+>*P凟á½sÆÙá·ºèÙ¸SÑÏu=×M´åÑ WŒZ¡')-·+í`a¯oGm'!œžÀw^Fpµ6j2V ßÚv¶O9—M‰*ÓhŠ"iJ¾ð1Ê?7?Q ÷°±rrœ¼9ÏŽE_ÚÑ¢ô:¿«Ñš˜„ÞÁ.!8Øå2ÒZ9¼×ŒÇÇ×%*×ãZ=Þ™á”^Àß,¦ªØÍ¨üd ¸=kVr¸%9öÅ,}U^Žö–J oAØ*PaªØ;TàÀÕì;”ƒ“X²-¨@iÌq«_þÒ&*²þjÇ€O#ùGI?Ü“ÆÈå7’°wŠ?ÎvœÖíØiÖF8C9´×ºx¡ÚôƒyÛ²ôlG'NH/Ø1Ïq; :ÜjÈŸÉ•4`‚UŒEô.ÉxøþÕÔtp§D$¿ËH~gßÞ'ÊËâÔÅü•t ™m€‡td ‹“/£MfÝ4ë!)@ƒ¦7¯ÐƒP}Z³Å—U|'mQe7o“ TÉWk©á$B%—}¨àÁrp«PСhÕ}ýˆ!"H0\èdÔ~Šªä}ЏB-¬bfÉ ô­Y·U=`¥l«› Igsíô£Šâ9ª^º¨–ÌÖ w>(¦â%¯$8T%à⇃¶=Ñä?J¢íÇb À½ó‘Áý¶z¦ñ¼W߯P;º#’öûNQæàˆØ_S½h&gd©˜yÉbŒ@Ü¿¸iÍÉú4§}€r•Q¹j.¸ XÓ*e…×HœazÄËˬØj®î6¥Ÿ·9ÝÂçpa9)ŠP ÕBñUƒ!¹›sm¬ÌýÛ± Šá8sY6Y¥c'P†ÔÁºŽŽ’Àõx`UBI®Cœ´ Ü_ÍO%¨Vב|ØÒ › ¼êhÛE±_F´I €œ$s4 ¦<¯KdÎ|ôLÛî*š›;¶’¢5Ó¯%ÑPPR,3«àGÿ´ëû»¦“VLømí-ji0ëvñe<4Ñs<ÄJãx¨¥…-äž~—£®ÍT¼Úí É–0ü0Rþ°Â8ã·•Óîðï(|¥×»ü[ú×’7,è\÷…²ôÍ/z ’Ä€ë†GRÐ,¶…Ô #Ñ·øú0sBâÓƒð­KÙÙKqcއª<õ×[*†Ä ô#²“¢y€û\Ë(\ntöÿ3Ðä£oúbK` ‘øÏcý€sE ¹€Ä6`©‚8øô !ÉLH7oG»TEãÜ ä.¥Å÷œX—TÙâÕ Lâ$ç ¨î½¼À 4 tÈòº Âkž¾Ýæ&©0061.D],ñ©¦bÞ¦6¯OðlÍi|0€Ȇ³}¾õÅ­ï!íÏkÖB8!å)œ ‚or{±{ŠȲ¡Í×ÊLa3:@Ûqª[ˆµpZVU‹åýÐàCwͧ:ª¥vAl«­ºcÓæZùDóâ< «:†Á¯4d,Å^yK›´U6RoÚmýؾ¬ºf¿Þ%¹•¯vðl½Eƒ!›¢>™l,é ›Ä§ðüÎR.µåãÄÕÄÊšÊlvœà›*¤<;É, i#RÊ;ÒrB »twP’rßÏI÷9&FY„ì@ù¯åTõôv¹©Õz‘ÒDH׾Ǡ‚ª‚Ê%jÈæ_ܦ*gm±÷>s.òcÛlN;´k‹Hçc;Au©a&Â\¯íene` {üÔO´¶ÄZejÿ,knçBcJ&¼¨ÔšÈ…˜‘ˆ“[æM¹×Z© —¯M²Íä´"ØÔŸ;•ýs  ˆ’Íèݶ«“ä1l" ³M* U §{ñêZ„D¢ >—ÂvÏ'^ Ó]ñVC~äRÒž×,|?ZšeÉæþ„Á/жó©œÕ¦uÑmöA䚎õ¹È1m?©]€ÍT–FXíMùw ä„ ÖèãÉÔ’@Ö°±®3W ¸7lBYRSjZ5O¦è¯(Œ£lعÄxßuë}a\“¡%@ 8Ð>ûgÝ$æê²ÓâFlßžçæem5v6ÍUBaБ2û¸ÜE½ÃKþaú™—ŸüL½Øás?"ÎE“¬‹ˆÂŒyp£l½êt,‡Xsµ:gc³Íù-·ò;Gµ^Ló Ý­Tn‹µO·Èó(ßTÕà ­¤›®å“ùù  “MQ!è3&EÍgùä—`T¯PiOgH@ß Ðò¹¥6kh2¼7:±¤)¿|áÑ$Ž,B¯6O6_¿(CpúQ¦Þ@·IMi^mšá+{ÉX‡É¶?¼Ñ×áããÑòV¶ðëZa#ÿ±í?]Aï»%D_á¿AÔçEV® ¨‡¸²Ýow Œ,^˜Ë:*ó­Ó/#BöjúD— ª·ÔûýNïíqDÌû‹ôKÞùw˦r³ò‰éS»L¤ﯛ›¶{§QDZŠ#Æá ö~„Inj™ »Âbá@ÖW¯›k4ÒÍA­£Ç›£ßáßßÜ™‰Lendstream endobj 1135 0 obj 2204 endobj 1139 0 obj <> stream xœ]PÉj1 ½û+|”q-y“i™n”.‰é¥ä”ÒœæúÿPiÆP„0<½ ŸmðhƒÎx³¹ÙaŒöôk‚}=™³Á…bÇsœím_h,o¡¡í?f5@[ÉNÉöÙ|º eÝCV‡kQVn°ý[Øwn}­­!<:ô­qj°uïnƒ>¥\ ú…3­hL ;A£Ø.$ëåFÔ`{§‡Z*<©’[Œ8b™0Á^³²O™†É‚®ÖÈÈð*~Ÿ²Ó¥µB£ù?ãQ‰JQ’!Ke‰€T‘õצn>dþÔ£V^endstream endobj 1140 0 obj 244 endobj 1144 0 obj <> stream xœ­\I“%µ¾· ~Cߨ砋Ò.'ƒ7ÆØÐÀ‡žiè!˜é†mðŸwfjK-õÞëa‚ xT©¤T*—/õw—Û*.7ü'ý÷é‹‹÷>J]Þ½¼Ø.ÿÿÞ]|w!hÈeúÏÓ—\Ó0})·ÕZi/¯¿ºˆˆK'/S—×/.>_><\m«±Úy»<;\ÉUJ˜|¹9lk°›ÝÂòmzäòÃA¬A–/ðL#–ïWÊÙÕ/gòÊ9i•~ eÿ{ý·L‰^w)1fÕ*øËë¿_\ÿþóå\B ¬¶­Ú kàjÎa—¯ñ½ð›ˋÕXmðÆð§¿ÂPe”’üá=MµYc—; Òºubù'N õ¶$FH¯^pÆcó/þþ ¯ä&2 aÓËKú©eÈÛôpkØBÜfX…ÝdÞ&ðZÁŽÄ¦–?à—sÖ-á >lÀÊëúþ³Ã°Hë`Òà'òI›U :«<àæ`iôjŒ_žÀ,~ÕŽá˃†1BJöëçp«¶ËÓò g€ÍêU)øà¯›¸Š[~Œ ‚L,ÏáðxU¼‚qV¯Äå¶ç‘*±Égñ€Ò7w°èýlð-îv PàlÝ@>àðn›ƒŸ7™?¬cpezܧ (flÄ3¾ðÁƒèþ´¡îÙ‰­ü€K€T Šd–?Pd­Ó l×· cì“#Ø^ C‘:å`dàŸ¤u4œr%(þ±Ì|3jù9J’:oB:QGf!HÇî„­¯‘·õ³Hh%HÇå„GÂ)BˆÒÃÞd2´æd¤u¤õl¾x0¤fg ƒÌ¼Jܼ â#SÏÐ eQŠÄòÖ”ÁYƽÓË tà<׺û:ÓC«(·U'ê|dýª¤Hû³?„9¢ø"»žàpµ1sÙ«gûÓAÁ3¯ð¼¯T@:w¥çŸêÿ(µÊÔ Åå¶eûKê^ Ûù |c­³š?Rò´Lüõ..)z»õ€LK.ANdãaÆ­»"¶‘´¨\¨¶Y¹pî Èô %ßÖù¿{áq%¿š âCÜ(©Ô·U.™,ã »ÊT#œ/±G Ç9UŒMð ·U0RmàƒÏ¶ךP9œñ&’¦kHSÈñ ‡¦vÞnú¨G×þí›jYº­›“9x‹hÒ]Ȭ ÎКÆ×ÎÕ¬s†ÆÒÁ3ÁÄùqæ¸c˜ZuòŸÚ‘¢n™Q"ðMY§Ê._—jœ¦o.e¯CÅ„ÚÑŸ% ï£*x0#YêoW™«r>1/÷ >F;òdpÓf¸ÀÕß!ú.™É&÷'ùÙÓü¬¼|æ€ ÊtVžñ½Í¾žÍßÔ9[EÎþÝíhÓMÒÜVˆŸ¨>ž"[qiÐ¥*Ü1w¶Ü*!ŽÈ-Ž¯Ú³/·Éy)-Éî·*‰NK!ÊöÜ>Ut×Z>”P.—ÊH²ÖŒ_å57Û°8€zk9êkßãÙQÉûþKYEî6~!©o¸ª}\Ï“ýVÚNÃ(”µm+„GI£n+³€SÒ] ½ áõÚ—$/-|% ‡MÅõ™,u¼’†lUç†äu®ò!º Qã׋(ÐÖ«¼š XEdt ¬Að“Éù{‡(ë !è΃± ÿ÷\otj€ Õu}?PöŠôHŒ\wâ”)e­aÎ?Qó ¶ÆS訬Ú9#¦„‰ &Eô­NÁ GP³ 2E4'á¢9ðñ4ªpÑœ´'µÉ2Ö¨–fSÍöá‘*f˜™åV¶B1Ü]Ú›E÷ªú ötòy]2jCdAkˆ“MÙ~V1J´aÑ9ÍϸÅ#‡‹Æ’³ºì¤ÙÏÞãÈ»ªÿ­ïÆ#ùëƒÇ˜XKÿ«ÏA A2½ ÒoöÆL Û@D`ar§W)Çï,Ùdf©»Äˆi ¡ù|­çÀ9] f0eÌúo£íÛ_’xáVaGÓ©›ATk9Šak }¦¦ŒDnˆ»0<©ý¼<Äé{#‹qv•b6ŸQƒvIåúq¶`;AÿÈÆ'ñ’E²Ñ…ãPá]Œe‡q΄ÿë â«)½Ñßí¡yå7bÕ1ëÞæŸn¹ª”`¬L´·;“¼©Ć&aŠ*²¹n!´† 8²™·=ob®<-“¸™3œb‘Ö§%1bºÆ¬U¥>†¸zõż·ç¹½/–" g¹ Ê9¨å"®äø&f(,Ìô. ƒbé%ž°ÊêðŽCÌÙ¥›HþW«Æõ5¡/±¬M½‰Œk4`a*)Ó`ºq67Âûе/eúàaô=ôkt4§ Œ˜Ò•ƒf:l7ÌOÓ Zûx-?b½“9Ì`+€¨&S(®¼%{~*Õõ²äƒTÁìg€Ë¤ˆSø’•dÃ6¡& QZRý¦l+¦ .>i]Oö4ŽÏ¢}¿)ySbLëF*Šš¦@Ñ\ÂŒh.Øš’aEdj6ëPLò@ 4”^eñÓ“‰ü2¤u3hŽ‚©Í0Ý´.É›3eé>×¢¤¦:AŽ›uˆ?`µ+x¸m`¶ø#º¢}ý(ÆÞÙ"*û?<,ÜS®í‡}LO×=´é·£û,Ð8Í„E™‚#Ù éŸ=‹ÖÇÙyÚ ²µšX4”1?€ÀŸ˜Û™£Ö¨é®Á]„ÂØò¤õüj”…:Ö…h`ؘ„ë€àN›<…óî A¯` wßq,ø9~„”´ÛÔN– Ì}µ)5G‹v¥þBer ÅNB?Ìeõ„Ýž[Ž'b ÷ðmv.›¨Ä„ÖD1ÝÝMG4;]«"<ËÕ¦|º]aˆBŽ]ñC}/ÞHŒÞÕ„ >*&¼š"Ļô”½aˆ›âßæ³hæcî `¾)*S€iú7󹩥²˜–egw’qŒ®òì×”qÓjìWØyÊùïåÝ®ä, }*윭‰¥ÍG Yü$™ gãß§h·•7|o†¿†À–ÁÛĦÞ͈$/Îê9LZ)W‚¤üM”dÁZÛø¶Øþ!`_ÚJì‹ODÙß »9Niü^–Ú °0¿¬ø+µyl ÙŒOd4»XD1hvÁ–(±?#^X‰®y[Q›Jä{k5‘/ ¾=Ð+8x‡q¬Q1Õ«V}(T‚¯DT®ôðŽH–d €dk£ ô¸[¹ügÚQú@ac Y j'SJÁó½át¼W¸ð <Ü`# ÅÓˆ½6]L>†%`6—ˆÐQXa¨Ò¤%UšÞHÙM*„™IëÇf“.>8 3H­H«'n®V‚°Ã ıªhͯë0T×Xî•)ä4µ6ó]„´}°)ðéXH¹Á~ 温©tN·)£ª@~¹ÖùL qš<>&÷yó²ÿ÷8‘¡^„l´& ó¤°—ÿDQÎF²·u;)²•šUa¨W²5ÊÑg*Ï]Ð@ /`†Ìö)Ë%FgŸÅűÁä­y¯«èÙÙÍ”iƒ ’BOŒñ°nˆñsL˺?f™7t#°*òÕ̺Êoº¶\™g¢7Æé5Aâàô¥A 4â)ž[š‰îñjx!Øq‚¬ÌÁ®Ä¼O3~­â_?&J‰ü~bÿ8ñ°¦%”S]fßYê2f,ØÇ¬6öÙ"´›÷™4ñ&¨˜YÖTÀß®u½‚=¾$25£\ÝiÕ*3Ž¡›gQUkÚˆTuŠbÊÚÇ?nGœ‘ŠH9ba гÔÒyg¦Iö½Ð¡ùg¡Ú˜BÁŽ›Òù Í%ÂîÞ\Æà~*`„‘§–µ]}ÃT.çÒ´.èÍD#y´âapR,-ØVÛkYp§ænÑ«vy° …õÜbRìØZLš änÞ WfÊ‘n\÷6!t8f+²ÍÒä<ÀFëd7JµìÐ=vA•gÌ<ôh¸ùaÝÙ_AO?«jÄ”²tïy<•® ZçCåDÂê‘a­Ó™ÑA­žñð½^…ÌR¨eÌ}ïFþQ§&¨«KŸ=ǹ €¦kk̃Xì6Ô1p‘ÿl?ô©à 3ƒÕÌQê›ÉéâX– aÓ‚ý'lÁïTV~pÎÓ!ScýK\ž2Ø\‹€=(ÍŸRSzØÐ]s{ÇEDÓì5{ØIä+üœ”Üé0Ž&#VôÝ:)o²NPMº`úÈî4ÕøY¾gÄü%ƒ¢ Ui²ÜæTE|µÖE³%/“ifzŸêö¸Q*Ûëì,Ø’@OÿnØ& XTÖŠ^+ãÌä ´PÏš(f[:·o¶sžxEf9Bvÿyó›ÍSê”Ïb~ª-–ÀÞD©vO¥ºiݯ8.mìj;æýFùÝ(h£#šöãdšÛ\ìàÿhnŠ}„`5˜ûøZëýneé6Š÷Îp]Ôö˜á(ØG·3¶b_£„²Ø×mûmíJIÝüUͺæ-–eß1—µÓà+¶÷ȽÀ§ÉòˆR±yT§{ªÃ<ÿ(M­½51:36YkfñÂ^Q¼4£iË«BFï’(»¶™ÒÒóx$)ž”óÖ3ÕõõjNì<—Rdþ_Û[QYÛ¹µÉ¬²äDí–@{UŽLÁ@Érj.„¤NB; j~©Ý[9\‘ó:hWIÌz#8 ð"µÅD¶´±È}Íožh7É]–·×¢„ÞJ¶5¯©ûA¨!ò…‹G¸/¢ ÍsÅ+JÌ5&÷UèÆH³^ÒÄtð·´µóL€u¬^ÌClذö~Ä@äÓ§f5 mñÿÐO´z™X¾§n´×\@‰]±pfÙýÔß#7wÊé=WNLQôåL=Œ>ì,ÿ`¹›ëT8xÃ[57ñœƒfïvÇn)‹@>UÌìxÅ#]q–§ûy‹ØLOû¹)­¢¹ÈçÛLª) í$"f2ÿ"†ÓØ·v¤×  $öo~ªŠÇKì…ñm²êµ.‚` Φ(õʰÚ$ì¶–9Ged©O¶fds²áæ£!:Ä̶Á®zé[×[N즴½)XvkØûèa:Ý ¢²yœnd…Èþ×q¤UŠ¥MÑ·|¾_ªFŒ4T™4š–ëlªÃ $7rGý†Rȵbýã0X´ãbùà@4‚qù÷AR] c%xÈÜݪLóØ;ѪµMÛ'uw>ró÷[½,ãÀ¡C?_\“Ö^ɤ£&Ü‚H¸®+¦§+M›µÞ¹v1–JÚ^®T‚’<Ôä¼TLM«Î¬ˆ9u:F‘µˆ D·9³ø1þî¼Ë,\æÍ«4ãUìÚÁYc,é´ç¥Ø!–lÌ>–LÁbÉ7~C®®Õ1ÊòÒ®˜)9»¬Ð^¨K!éÑ(Ò´þ­).íó[8Vº±V!Í‘ÌÛ€rXÖt¦ËSi,Wvû*b·z* ÙoÓ Sœ§ÅK¼#X“Ö’ýÛ­¢%"Ï©¢Ñ-û½¸º\oŒ<*Ï¿ãó3Ú_u™¢Ì´Ç0f>C«7¬íçhnô!eé…ž€”LRþ»< ïºLük ¯f9ÃPÍÇûÌeºL“ zh”¨¤Ûgö;-—×nŸ»0¾±ð4~!µFå¦É0§jÓ rà…\üh7_’ôò‘>Á«ãxª-‹±âä~z)7¨…F´y(ºEák3žQR~%?&•„™–B˜"ýÎí6‰éÇe‰ÒÁœ«h»úcb^~Þ[ÿ8ýÉ'Ì* ó LMXJ§RÿâÅxvžtåqj Ó¥ü7Il<ºôƪßIFJyÕ:ê!ú9Õ6–ƒ‚çÅÌ ÕÇÛØ[k^ŸÿZÝJ Áö>Ëý¢óöqe„Ü Èî§œþ#&iúTzØÆäÐy¥içžáNï(ÑŠy®à±bÞØ,Vü‰?DÒ^±.ôˆk‚`ôXþÖÂ+¸–"Pg^Càæõõ‹mÃß* œ†Ðs4/Õ€[ žÏ yùñn*o*WŠ €Õ½”ªó$]Ëk*ì4Š´vÜrÉLI8¿#º¼Oƒ$ýbur¿r×ô‡d©›A.æY}¢+0DÖ´jÂJtíiØÒźñ¼–md—úÊOùƒ 0Ko¦_ò+©ãvItš|ý}tmlÞM÷{äÌ®w·Ÿ ñ§šDú ZïÅÐ%¤aýS­(›“EÿDŽ`: ¯¨å‹ï§†€E]ϦÔz×ÔäÖÿ“5ì®)ª}™ï4^d¼ï”œFÛA•¼ÓíÌûµ=+1ÝÈ=aAÈnæ2I…€Y û¹Õª`2´Yø×Å4ퟮ/þÿüŸgÞŽendstream endobj 1145 0 obj 4877 endobj 1149 0 obj <> stream xœ­]ësÇqÏgÄ•¿áJŸîRºåÎcgfJª¬§é²KBÊU±ò$ P! P¢ ÑÎ?ŸîyvÏöî(Jò°·;;ÓÓÏ_wØƒÚøþûùë‹'_+cv·o/ÆÝ—ðs{ñÃ…Š·ìò_Ï_ï>¹Œ·¸4Ìã¬v—ß]¤ÔÎë vPzwùúâo{u˜ö~ÂaúŸË?àca¤i«£áÉËk¸ûÓÃÑ ÞϳÚÿþ †yvÞÿî ÷9Õ`íäõþ²ÝóyºjlØ W _hàg€ï´ž­öÿ‰Oh­ÆñÎïŸâÕ0£ö:˜Á9eèµÿ>í‚w3½úg˜Ö—0†š ùëƒÑƒRÖÓ7 {5§©Ž0ÆèG×V_ùÍá8Á^…L*Nác¦ÕÖ #͉d/ÒCÓ¤öW°ì·H5LÖîŸÁÇ0ØI»ýÍÁÂ=@òéï„GMØ¿>5LÁ;»¿‡aGïö×id;OûïIeö¿I×ÜHÇ„†_€(â;¿Ãáq ÃOû‘œÆØgONÃ{ðª¼oÁ•H¯¿k×nqúnÕ´ÿ ÛcL!~“¾GBÜÑ«8)mìþü¶¶æYûžÌ¢ÒáùÁxXÌñ%îœÖÆÏø+݉[¥€Ív—¼¸ü׿e¶ j\Ìj§¸¾»å7“¦Ûp4šÿaMÿ» Ðn0Ö ¿KÓÎ{˜îr¯ß´÷%b9‹ï)Å‘&X¦ÑäŽûÄ"0uǹ'Þ#›€O£‚IþŒÂ¯QuG&: ‘äyú¸Cm¯Þ¢lM“wšòwÞ"|I{¨}z_Rž‡eÿÒÉ ‰Cîª8æ‹v y9NÑéýx@&0#P¢j²«HšÆOWœño‰zÖ¨1Ò¬G•·BÃU;¢Oãœ÷jžl|ò¡Íì¾ýªÆ¸<«A B&šÓðôMþ'\½ÆyŽ~‡¿s]ŸÕ—þ0y›@¢¼ašéš¼rõ$Æ1S㨠ÌaÔ…(aO‰QóN_7=TògUS6êcxóhq¦UñyäE¦Î*#Ù^¤5úH†Tôè—LÄgÆ™Èø xΜ³”qÂ9Æ$˜™+»òý™ê-Œ01W¥_n&ʶdð:FÔµaafsð‘CøÿâÀ­ ügŠÓÀæßà›gê¹ ÈÕ”™9É@€Š € žfw(ÛM¤ø]p¡T£«×-UM@òV7ÎŽdÂ[>msî×í5±÷ÍÐÒÐX;7èÑ­HÛ&gÝ4$YkJ+ D$Mˆi‰BYÕ‚Ö&fœ¬‰l!× ¨›T>¸kçø 9\S·w.À•†W©é{hOþóa„á4hkù%dc®¸5»Î›kfª´%ÆyÓö *É¿ã¼ÀRÓYrƒÓ.êò"#a ç˳1f;·nëò®\K2/-w¡ñÆë,)°+¶HÊ–ö]N×ìl™—™üJíBãÄçMýuþª>€4Ÿë•'£ ŒÎcô Û3/¨=쉱ÜBŒ—yOµ-ÎcÛr¼• õK“à6Ôâý ~Y "{ F‡à¨)‘5!±Î7ø˜Ž›ßtÿ½ãU¶6càþQyy1ñ!‹D ÆžFÙÒôíå•É»†š<|³v(¬¿üT$ßœü¡-‘Á¹ÙjJ¬‚@â–¤¼¤±tò×&j· O›Xg¦Èp$”ë$-¿M²äwY~€ØÕÛ" Æ êRtb¯q¼0¸ x±È‹’È…ÞØ.®¸qîup(r„Œ®$qûfñ‰ìæ5QìÄ©K«Ð!,ã©QQ=—¸üî,‘0ÜÎ,ô‹VÊëÃ0 ÄÂp„ñ¹žs/˜¬HÊuº§1™žq Šò~~ضç²dÏÀKûÞ.¾Ü$œcðهǜÐ,† Œ­­»xÄ2ÝÔ˜ò'ü^GǘÑJƒI@ÿeÍ$Ä Ã )†7“¡^ÔŸ+„ñÙ„ ˆC¾¦8Àç = È%¾`€ÛhÈÔ…ø+‘º¦((jŒ+‚Bƒ–´CÆSŽÜWvrê4z" kæäA”!!"È\î´_3A:D ·³hpa{˜p¤i7ü¾âË2 ’HÃ-ȳæˆm€ľ$’Tœðiÿ?"OΈyEìËÂψZ× ƒ ˆ"(ùu„U‹Ö„a—úl”Õ“W¤ùµ9±ÿªs“­Â&:…5é@Øè_Úí-ôþž[¶µØË*·sExíØË±³[F.¹,Š©àª€–f.J‡6$hg¯8O»x7ÇðE“gξtú]3#F*»5™‘Ϩð'êXá‹ï_%tÓYôÚæˆCÞ³x žVxFÜ‘Þþû8(e–÷ô:Ø8Ãmï]-9GƒY w‰9h<ßü¯òôèúØ%Fi³#áPgÃH“‰ûË–”â¸ÜgªL3¬#.¼öà‘Õñž3þ”@ÆâûžFE|Î:‚¢pÀ‹.·ü‡a®š_ŠOd¼¡xO=`îQ¡'v£°DÆ8‘•½4[¬œàˆ9tÁ¢'Q/Àª£f8G·'Ì¥“”grÐA$$Óia–@6 AH¬QP½Gv^ÌMZÒä”aË$ÒÚÞú“á’>"ð>ç"ã˜À8`ÑT04Æ!q¸CÔ`C8—ôø n9±î´KšDŸâQÊêiÕ†Äå¦,e,pe’ ì«KTaØU¸…Çà„ü¯––î íÀ&Í ïìÌT+øîÇ9* ¸vÑvž!Wôì8c†*7ægFd£|/Ȩ'-‰x\Z®{+RLGð™ífTc§…£}¿®= [#Ðh\tÎpŽ"³Qé¢ÙI£ã$~,ƒ¹‰«ïìéà¶Nz3|H‹e6óMR<è}ߪýº0o‹çŠ~á¾ë³ì5„§ÌBÆ‹¿¨qwË×®CÆ1—äÉÂOêbŠ*r 8ÒØý# ‘õKrÅ8ž£]Þ‚fc!~ûþ> ¯ŸˆsÊD+ƒð¢ ’8ªT)e˼¯÷Mƒ¬mõÙ::p‰«Dd·“½“¡X‰€â 3 ™NÌp¦Lv PQÆ­ìÌ Ð–¨3‘Ì®‘òD#ô¨5Ìï%‘ÐÛô‚B¡¤wX4øÈÖ‰„““Òè×wt Z—Âý_4G¦Zô¬¿‘I†‘[¬.´ÕgžuyOw»d¯ð¥Ä¤3Å‘Ì!Fuª5²¹¢ùUq^™È­PÔ‡¥ø´¿-Tv‹ÐÝ&6›aý縈ÈvŠîrœž!ø qÍÅ¿Pv÷<e#ó“ÐUà:àCE,Â*Šfõ 7Ús(Ë4%¯Û@ …‰¡3²Hi,ð^†p(RƒA   ÃëS…È|V¾o=™oŒ ¢ ‘É7q‚<ZNñ¸¤Q.æ°û.¿Ÿ,ä8øj!K¢_—¹€\è5Qèø G‹p¯_v1DöË\ÿí+-ôY‚vs,ðùÀ"bàãÎìhlQ·Õ؈síò¼¢mD@Úƒz[.ùfg˜H‰<žtzFÏXzŠ+´«±Yâlw^ø–}Ød@2µP~à{-ÖüqŸ§|ƒÊ̦þ;…zœ9ùªK9ˆlvPê„Â1±N¦/yй*k6]Ô®Ðä1y1ymzù%±ÄÉá¬^ÊQ,{×Ù%ˆ³Šæo9¸O¤ ÿrâû¾ÏxW%µ|ðrL÷|WÄâQãYÊΤB,Õv(L¿öL‡ÎogM‘Fšx!·–j M‹òZåßÅÔDf!h«å3Hœ3ëg²éº£Wy˜E鲚5†Jó#â1n -cÙ­â¨H.Åc%jÁÇÇÕ««†Þú”å/„E].KÔfÂtXãÎâ7ƒcôí‹Ê"”Îa’5ÿuvI§9ûØÉd˜ÁÙ–¤k·Ä$s)BC1ÑúýÅd€0 ­˜ð龊-;o¢§Uãú@”[§¬YfM9*xS¶‘X}YL_Ž›¸·nn¥ûJîMج£µ•‚ö ÅOÁyïd¹2æÛ7 õ4Iæµ,òãé&·L ¡ˆc4 ¹R3Àа¦ÂkYWýªñdÊ3—\PÎ/NÖÜL ÷Ó#ï! ˆI^𰢂¼Ýgr‡0Ä ¶&繑Š(²~œði°ÓX¯ÊcÔä\ŠlHéæZ(“Œ N30}0$¼æÑ£e'û:ƒ²ÌÆ`™ft‘¸õÈŒËú–>PZ•È–ÝR½Ð§0J2 ;¯ûbÁ‚ð‚Üð$RéöüPû8È@TR6mð®$;b=»¨ÇF‹„1¾©P™¶Ëz ª¨×þqJÒÓÖm ‡Ù€=°i·]ΤvÕ ZK>HI4¹Æ×ÙÃÞ$»SH§SoR" XÅa®½I ž½ßȤO-'VÁŒ 4¼GÛ3á{Æa ÊaÖì R¨nÑ £3¡-2$>……¯áVçfg¹ø8eoúJfP>D„ŸŽ›SӸKÞ5L$ªyx¡r6?bSý1FlFÇJy>$NèÇt1ëZ†L¯Ñ±5¿´èÜ‚ªUh½ØÑj,ôeSëJ…bEŒÚ>9Dªd9&hT?D¸Ù®šÉ$Q,ÀáÖú*y¤¨·™—Š*øâìtƒ^)Z¥åÌie ìE2r¥\ˆ¡d1m)+€…‚¢>'®k2âZ?âéG–Õnż"¨ÏâÇb—=ébšè£ôNì¶:]ž¶Ð-|Æ@‹~kAHcõUU/¶* ÆÓÚŠ.?U4ÁÕ‰O@Â=â"ŸÛrTͳïÓÎÿ¿¨¥E)â~¾û¼ÑôçÃd!ÚÔ3àCïk˜ÒšpJ%%•½–IÎ9°S6`»>ÜP$­ä£ßrøA¶µÔ½ÌÙ…ý¤‘GYx˜‰!4†ä°÷Ô _eQa ¨¨tKµ!ž#*‘yÕ‰’•g‰Y¦Å "P§¿€»n!2{r•·ø‘rÁö‘.Ö%”×f¡‰4ìkÁ—àzss‰'‹ºÆÅ¹}ÚTûª¿Ø¤®j/ÆÛ¥¸]AÔ$Pe ñ=Ùñ¤üUÞ£7'²Ú_ƒ•±LÒh}6¤õÝãwP4œ=«Ö/¦¨ôfìw š´öÁT nI±ë{÷–¬kßœ•uå¾ÀFÖ5+¶iI 4S$€$3‰­dÊÅà¶ÔÉ6 ½DF¹q™ m‚Ó> J½ŸÐèI›™õg¬sªÅÄ•rC…8xMßî»ÃÔ—C Eý•6‚KüGÜÞÔÏÐÁÝx«D˜ßXÍ]g–à-·Ž ¡`¶«ï z€¤™PÑ ¢Íû+<íý$—É —š‡ip‚(ºæû¬hxÍjÉEÿfdºRA5[ªì“¶P³ÑÜ0,ڭɾ“œÆàúÚÙ_x<'AÈ9$|ìšYõ¸]‘ †ÏûOËíR‹Dª"=µ3dÿu`õHß*÷®Â@ÎÝ@ÄËD`CÌ ³l•€Èy­ Eû)‚}b¹-bEx|Þ^™¶fÕÌà?ÄÃXv+c ¤™6s¬uoúp•2Ó|Ó—?’ž$©—ªª ,8˜>`àÏ=Ÿ`Ù0+ºf "%yx%ð,ìBáYÓ…íwy¶ì`¿Súñ‡XWª –ö ­°ǤлŽcÝ´ÿ,Mu=鑤)ÏLÄÚºIf"EFN鶬òh¨£vc'¯&ªê’o»>ÒäqÁ2¡“XЮ­‹ÍR¶¢¸ÖÓ!zh-5â.‚ ï;$¶ìþ[CË䲺;Ó½KôYHòŠn ‘”Ɇ…!ãš¹d¼km³JhÐ(™3š…£Ã²n謒wˆO"N¸–aèàpLéÔ š}<‡¤RfuNÀ@Pl®žøÃÀ€ÚyÒ½˜yPB7ƒÜü'†Šn~6µ a$n\q÷гG—ÞÊ®0Îèã²T/ê‚+꤄­àÝð¬(‰’¡â½uª²ˆ‚ou?®5q1À@_:¯ú€œXô†yqkβÉf-N§)ý¿í1"¦ë }Ü”éØ×ƒÍ`U*Þ& OwæÌŠž´£–ÍÔMj=ïj̉òEœ ‹¸åÖZ&[ìà†Ømm±.ûaóòAø2“8Z Pª¾ßâ›’”¾¡+"å©ÙÝà +6v™ž,c9ïöÀkhãXÑKà¶Ñ“V)åxž7Æ—„ bЄZÝÝ£Òé)ìø¡BK†ãâU™ÍY-Á8G8wqÍMãæwôiÂ:*Ñ]K{—,M„ÙW%¿wE1N:©’ã±,GjÑIÇx”ÖÒß|–8vEÌȯåÐ$sÎ1l±TÔ®nUØ‹%5äÒâ6þÆCǶ£àWíéd_"eœßò&X?_yÆw p°=,›¤ÿriˆ6Íþ þ%² –m¥|T ]`úG§‹ÜÁËt– Š$Ìþˆ¿óÅTe’FÀz›DE³,!±RúúØ.¾­ßJoÚES.ʧI+PUi­5ÝŒბãV_P!,‡4inÏHz‚ð©bóÒfÕ;æwÆz^©T€ÐzÙ±5†Zš¶|¼#¸…T†(j·Å$çwý|¾Ü¥!ª¶Há'f¨W³ÁdÓNý+UôþŒ³`ŠIŒMÿ«N„Š–…¶“ Bn5Mkª©®—<'gµa +y6YòeѽÂêE¥ú1عÙÏ.pyç¹_”£SådtÖû>P>7õ*´lfY “4ÜÑ<ä1uL Iüú‹Ã¬ðx„Ö2&Ó›Gg-á®**)ãÐÂÞÓ %5m—ÔÂÑ)\›Ï¬ù™hξ3—dœå3†°{,Ÿ?È‚\p@õt9K/-‹›ÓÉzqaX;½™*˳~½•ÊáJTž]¹Zéïn%à]y9»ôuOàßû”‚ÇùßÑ«éþY“‚¨÷Ä»ÊÉM c¦2¢¶­Õ ÑÖïÅ1¼9¿a¦¾@hPÐl¿‚¯¥¦óÑ„²ü¼³±êl©\;v3¦ðbOv×Ë)ÍåÃê’ˆ¬O¬â$d¢2#‡zJðÉd~]ªeÃ/'r†[2--ȸnæ<çáÓ1Ðb ^—Ž’ú‰k‹%céºNëóË‹¯.~Ø+}Æþ+.;‹§sŽðw0˜Ñxþúâ“§Ožþi÷Ó7OþºSO~|ò—OᯧŸíþéâ󧻯ûïàXìÁØY[5ªôoád¥ýHó3BÛ%szFy@Ì-™zÊ(M³VqžM’ëc°¨¨^Ô<-OŽÛ¨y*ÝH1^cº±«Õß²t]Õ“N4)[êÊò¡̃ŽvUÜ ¬]Óñ¶Ó'ñŒˆlíð,°êùž-_´K!×<ò“ã\²ðÍÊqw£Ÿ‹|þß0wzÍå8^Ãl$X ýrTÈ-·.„²­˜o­üÓÄq>H!\iP\BiQ|uñÿëµendstream endobj 1150 0 obj 6290 endobj 1154 0 obj <> stream xœÅ][\ÇqÎóFÈoØ—3wtúrútÛȃåÈŽ‚8±,bçâR¤!‘KI¦äø×§ª¯UÝÕgf–”Ôr眾T×å«[Ï··ËIÝ.ø_þÿó×7ÿNsûòû›åö×ðçåÍ·7*>r›ÿ÷üõí'Oñ1¿:…%¨Û§_ݤÔí¦o·'¥oŸ¾¾ùÃA׃?§£>mÛf:þãÎ/ËI›íðŸÇ;sÒZ;wøíñN¬]7}xŠ¿Ý¼ZÌá3ü­jÙ¿9š“sÖ­ù—>„õðßÇ;4‡_}8… Âä}2×ÀÊ‚w‡/Žw+Lka¬üšVöð»ãݯ-Ûâ†q7øùði[í¯a]› Ö—uyoèçm†ÿyúo‘ÀžRήêä<ïé}&˜ƒ?៾˟ޙçé¡¿àê`'JmŸ^À‡?}zóùÍ··ÈO)s {?YëVãq 8âO>»ùø³ßÜþù»w/n>þý­ºùø_ñ¯O~ûKøßgÿrûw7Ÿ~vûùüàùòËÁ}r&ĉN6>îÃÉÌzÂóùe;rÖÿuÔ‡ïá«O+ðÇí¡?žù3Ø{§ÕáU͹ ™é>4F}ø²$yFöÀŽáð¿…ú“]µ;¼8ZxX{øYÈôá<“fÛ YÀ›6òKp;-‹ÇU«ÓºnNþ7ˆÙ‚£¿nCµÙ^ï€Rns–>ù7æA$ëùå_“¾^¯djkì” 2u}Ïhհ묅¢¢^ rù³üiÒìFªA‡TâÓ¿yúO@³gã_Ïñ¯ü É…gk…¿PÌ&Š(’ÍZ€cïðßwù—é=¥€tðO$5ì£|Ÿû¾þõ¢>¬‘ËBe*š"\eQÍ0g·X¨#q‰ÄõÓe&*ˆl 4M‡z½ ?h.üXö%ŽvÙ¯¢ž¾oOv\€³4=ßfÏÊÕ†¤QÅãNïÁ3 ÄÐ]§ªíN(ópŒ?¢²ÉÐì¹;ëªp‘ýÙÍã'¢q”-’êK¾—¤ÄÍ¢n‹g2‡$¶g *ઓ-éÌc2 F3»€[}ÛôöÌ.X°0‹2Ø.ÄSv[f‰EQòVžÈ5zã¤Ñ«RÖñlL\JÞ¯ß,5" »4ÉæÇ~­ Š”ÖnÓ‰äŒ@H‡ÒMhÓ±YSœlí(ò}± «Éô/˜¸Àš³TY«±k,dr2¸ ¥Ï ›¨½ÔN<€/ðQ‡ïÁHQJÀÀ+W¡NG3dH&ùfE à:€æE'/h?ÿˆ¿²€Ë£Ê êV‘-ÿ°#™š¤v¾‰á YæZÊö‚Ì\£"܇,•l¸‡€K·ƒª÷º0›] ]EãøÄKqû[” X¢—öÚ@oôÈ)=ÚyP‰U+²ú+ú°‰ª­h™ÅjòÊG—®"ÞÇÆà‘ìé{\8‡:¸Dr ¾ÝŒbpfp|MÖä-m%³úW&CÂKI|áPÛÆH ˜ÚÆ}×feÆ6p›_"nk“\LXhm ‘ÁNÀP¡.lQÑ{ûãa4'¦ÝÛ¿ê!ùN˜"Ô LŸº>™“ÁFÐ…GñÈTã꿹J-+øÑU¥jÀ,ƒú“ÕéÑ?~Çyìe²f[#D`ð hÓ# À´ŸþxÄM$ƒÎ"ÎóT1œ@Îa½Ì¼;zºPtMЂp3‘°‡¼»ÎÉÎÌ H´îÛ­û2¸-°G3aß‘®‘x×ùÏù¥¯²Š· ‹  ŽtZƒÞþÑPaßì%#ý7+ΚME$ ·ˆ¸ï©áG´ZÖtZߦèÛ€T#K4¿î,‚"žóà5{«£[„¡m¸f+³½‘ÖýUÍÉíÖÉ£³f 2ã´Z¸郇, üL…K@>œƒˆzÄhá"R͉Æ%y ðφƒäy~Ž 1Üq‘/<ùÐâHœJwEeú¤ptcØÌÐFmä—¥è^zë¡þöØ`ˆufêÙVÇx÷ôIbI Ÿø4,õ,C­š…è±jZ¾ Á;®¿4v™ŠI ´ÚF3LNì›vÊ{€ŠÀPQ0Y H]ã*ÈŠ}ftô½b 'u’BNÖŽL_¬dÜæ Š“=ñ·¶Sc׆Á÷Á³nØ`´ Ö¾GôT°AÏñ<-ÒpòÉÔ|KÖÿnäeºÖŠÎ2TŠÛ¼S°þ´ÕœæYƒBˆö{( jn`‚¬L4²a|>‰áÁoäÀß@Î|é®Ó]ÜÀ™&ø¦‡ëˆh`½èbz¦dQ,7 b¹ö1Æ”({˜jÂÇýhÁ•>€Øù1#¶nÛáGƒs‚µlÔ§øŽ‹è[™J©YÏDáI² uar–z‰¸Ô«`o׉MN‡uõþ¡=]5oµ>–½ÍÐü™…š‹‡tæ,@,Ä}æ:4•´xÜ%w·å§W |Ïxp>$zR9¹cƒAHÙµˆ-0櫪`ˆŠ$ÜÿuÎâ|²Ip—ž£jæX³Š—ÄqЬZÌ0dó½l®PFúº†E× cÒ†þ9ÇÜ€rúõ`cЦâÚ‹=²¿èÉ!âQ[þµÓ™iq¯^€ò¨ž YÀQ.:ù–¤4’BHUκ¨Q¦ 3Y)-0z»¶zñ¥{¦âct^9꙼É'eí9¿éM2!à)8[MH/]È3$DD÷ßÄz$êw )SRýI¸é}¿#¶­‡÷ó; θßì‹» ¶¶lߢNf¥ºŒ¬U ïòìE&è(O¨ÙôÙéË&Z•TèK·rƒ(²3—þÙemMJœŠ~ÒŠëñ‰o¡©, &zÄCñ ©r Ì"*'»2¬(_4‹jeXXR‚Ѐú²¥‹ÏÔ¯‰ ©¸Ô›· 3]qǃû[Ü]*S¼ ¼-GÚ™Î×wÎf0{5ôÕ{ïNKÈòSÎâ…>©ìÉ÷„/šy€±jàQn$‘«¤ÃÂÉW“_2 FõåÿR̆flWÃãM‚™ÉÆlõZf5>r¶‹ñ?]„à‰_ú¤mk{™Qè–ªPY!¯$ë³H˜™}H…G¤à`TK÷¹8imÁ,Õª‡4<ƒo ÌŽ; ŠT áüÜ2ß•Cˆg8¯Žª‹ ^©›š2v×^ CÁ£‰rUG’fÇè@.×ÛIÑ& ÌGÅ=!¾xË÷Ý\B!â&»š¢wt®T»³L‹Ö—LßjÇá Wç~Ô;–̵¥ È40]©1‹ªâ&¬EœÖ4v¢‡uÕ<9ÌÅ`!ˆ>•wË øÛf§I ±+ÁJN[\%NëuˆF€Dljs˜ªø”Ž^a+莄–Er¹!íW xG‹†ãÔ«¡¬¸ŸP#—5É+B[Ù2𼨳FvCôݼ»ÈJ¥sÞºúy»l%Šñöo37›Óâ…’Í!ȸˆ% ³¸:ή<-Ù‰`Ïkò=·YªúØÈBÍËyÊÂFv^©HpLÌO_ɩŅ¡AÑ3çêY ð‰Þ4) ”8QÚ…XMY ð&`ToKßy‘Ó`ÀR_ã0öÔv•¥_Ú“½ú޹IÐk2ÚúØ—”•U_Ëù‰Æzµ²,b^†Ú¡d)’`nàJìÜÔêLÅ̼¿-ä)¢  cÿ5.ên2s3ô¡ÝZ³ìM¸G÷¢D»ß5©"l̳p$˜)J«‚Ñt1U °›¾žÙ¤°#j]b<ˆiöÍ‹äyÒ•ž‚k3Øë5šgP–uuü£ÖSœR>kž›WbÌ„&–pΞC&v+>Ë’°RøZj;,«›A™)ŒŠN.Ì‘òBd•ó5T„–å ˆ“âìþZñ&YIô!•›—øo"ï¢×>Ep÷u˜­kAŽQGãb- ìeß¡–’M"¢{Ê]€½ÀÄ›o^NŠI#ïMlc›'úpSÒ< bê‘óó‘{Ç£dEÖfIMÓm’èbRh›vÿ^ᘠý8å×¥÷\¹IWiö½¤ž3Ö–N²M¶~Åà FZ ¸`js¢Œ LÞP¤A~zVöj6P»I*Â)Ô¬,owÇR ¹®5ãð‚Ž>jIxfâc ,3éK³Á“¢Ð>……œ¿ŸÂª¯î=V:ÛV}ØëÌöN6qá0MJÄ‘ú/'%CÄ\ôárºÛ‚¬8G¶Š© JiµÉ³°Èt±2K+“»8ÿÅ#º’üœCÊùzœ“vÉšäÞÉŠTe/Ù"2?‰Á LÖ+54O ·uuËz ÊT+êHêŠ\±B«¿¥l¬ZÏ'.¤ S*%žTS“Šf”–.MÌÒ'­ö®¯æÒ\å·Š€ ¼XÆÝ–؆Bî¦:‡ÌžµØ½[ÂLZÒ AÛ\˜sqÙµ}Ÿ1™í‚ˆy©c–\~Z踗½®1éÑWŒu, ;'a&±!†ð5éSc>Œ‰P?鼌Oêúì,|»e©¹|Þ§é5s^ˆ9¡Väù×Tb¶Ã}QVVeűÌÑ% Øl»v2,-iIúܹêʦ÷8\8g_r]ôÐÒ9v¾$)]ír¤4¢³ÒHi¹b·­9ÒMl’¼Ô.oõ‚ ¬º×¤ { ¡lމsBÂTƒ}ã¥]â5^^渒ßü¾‘ЏÎÆ•Ä&óî3¶µ½@ e q)Y OpIÁ„ªš|”š¼dOC^为[vBZ>eÿh yRréeÔ¸sñ°ŽÅ0LçnÜ/"JɦQWûr)ÜàŸàÙ”rQ@XŸ JˆZ³îþI(’sY&j¨ýäÙG¶¯ä°(’[´—µ¥Û2„hÚósPªà·³WX,x‡—ðÝ‚ ƒórðÄ~ö}X ùjšþ÷¦¸6ªäà.cýaghµTrQ»Äq—ËS MÄ0±Á÷º^D{¼ÕÎs­ÎU™ó'ÕÕWgñx¶:ZÍRM·ÐkõZv {^ê™þšö·¡·6FQÙibèlJ®½¤- ·†i!BI„Vœïc%mØ÷ðqCãå6¨S·Ýªì‚Û‚‚ß}°,Ñ3V¯X ­ WµV:Z†5`c‹Š–/b&§¤D·ÚQdg0×)?ˆZm'Wk ½”ŽõF#]‚2s°X4·4Ê)žØ‡‘›Î×”³:佚r¡h²×G%ù’F@újo£V"sõ†Zê¶g®ÎšTyURÆIJëª)U¥³U^Íž“‘¹«”ýTÁÈd2p#3 ˜%cdë3à§ŒÍfœ©7¼)e¼s:=“DûåDÂx#Ì«ºV ²[®øÒÛ††«ÏÐmõ›ÇE®ôÚ÷J G>ÝŠÆ>]»Ô£s u /†¯ÄˆҚ9çnÉã:ަÒmåöEdËÞ`Å órPK®í!¤«½”OÈV¯KÔ•Äα¸A®É°rÞRÿØ™ÒMo!ª³y€,+M½üxRuç'®ã^­g£®­vª–’ In§YI±K‚ºå¼ ט„ÔŠ:m¯Ôv§ÍŽ”Ô\uy[ŽxñË™Œb„\ØQ_ëÁ'ÖO­§y^í–Kn¶íœžÌÕcL7oöÁ‚Ôe‹>„Ph .b¯tÕ7r(b°Š ˜%ª_`mºKΦY0\²„ƈw=¡¸ñôE Cï”ç®îG¾ØŸs=à+aã ·®j—°âxO-¼m^ 3K4Þ݇¿Î·ü,›Ðã­Wè#IÔyhIüêã7¼¾õVÙ˜³øé¾{+a7­p"Xgúò^ýZ×=]¬]€ZËß`±vA•/öò,*‘Úz»­ÕNéÅo½­Éñ‹ˆlªÁ&Òß}@ ” zpV›ï±Æmiô!±Îdà±Hl”ÃóMMÐ/iñ%®@Ø¥px]ê²sP̧†.%+U…’‡‹”o©ý Vÿ—Z„}/ð9Q):sb'91ÆŸ…–¯ŠÝhí^¡C¾uÞm {q)å.ÁZM™†ö=œÅ˜1sìZú!õXÓ ¸¡9~OY9Evúâ|ŠÀôù‚U±­aŒY²,Xì´Ð¢lÔ¦4S¾êåL|s­…ÂuµG ¨ü ¨-UöŠA¼ÁØ5‹l¬?¾ŒùSQ? µ_w uY¬N±‘á4b‹A·FvïIíšÜšu_Ç`Ñ,¯ÇKvÛLÊ=sçÛj¥ëä¯i¦Í½Rùf\¯«QBºº!k$´2ÖN*¹IcÆ)Eá‡ÄÕ¾”ÿ-”Ηm·PE_ÇZ[möËûr„#уN©Çù¼Yyz9窮“Ñ!5Á¤_Šù1~b sà†Û'k¬.M°óhfµÇàá¬KÐ,M¬Ñë28RÚîÃZÇ‚Sb?Òcq®*â\ƒãeW?tLFAÝzŸÂc€®YBº?ùj±x[íÅ=bX vRRÔb—t·ÍÄzÕGK7žQ=†€bÃ-ipêÅwy–—ÅÕþþô½óB³¢|IWwÿ¹ÔZÀ°µ¾ùºŒÀ«ª”}mŸ$¦qã÷‘•û„vãMjç’séÚªÆ\oß×ð¾ß’î R4£Í£jÏRj /®g ‹EïÕ“”{¦“¶É¢KUÛL_åë¾.qáK{‹ií-¥¼¸¤]F’ëÀõV(ße¶óÊ"õ­ê¼1'ÙJˆ©ßWª ”^ïօųêØaí~ÑE&Ú,̵›²ÏúbƒdÇâc^PûËZˆK+/.›ÝäY‹ñ»f“÷»í;ÝÖtM]A‰§h[©§ZbÚìäùOØ–¼ð4v<Ë2%kÞ}ù’Fùë½Jªt·†šL{®­ËP`M™G×—•²ñÊZ®dƤ'²iYªW¿í WqG—¡°’|ñD×ìXîªÝæYÀt†î]'ÖÞ"ݼRØ‘]t²ß PdæIÁ²›ÄLWl°*æÞÎe3ÞÙ¢û ò¥l£{Å¥ÅKuÛ­gk®fvæGU;eØ|Épgo:„$5øüX­?Í8¥C¦9ç9§Ö¥zßKJ†—¯ú¯/åeÉ<³ïRòeš÷´Œ"óô¼N€ÝþÁol—.ž:ÉäR³wKùÖv?î°´ŸX—~9wê6F×àó›ÿ|endstream endobj 1155 0 obj 6755 endobj 1159 0 obj <> stream xœ½]Y“ÇqöóJáß0oœqp‡uvu?øÁ¤HŠ Râ±9,:B‹›&€P„½3ë̬Îê™Y p¦§»Ž<¾Ìü²ú‡:êÂÿ忾¸úàkmíîéOWj÷)üyzõÃ•Ž—ìò__ì>¼‰—ÍðÑqQ‹ÞÝ<¹J7л`vÓìŽÚìn^\ým¯~à:øÿ¹ùþlVôgÆé£5ðË›GpõG‡k{ aYôþ}\–Ù-ûÿ8˜ý—‡k}tγ¿i×|œ>µnÞ ŸZ¸m| …?GøÎ˜åhôþ/ø cÌ4 ÷ S؆ŸÎ‹µzÿÅÁ§I[úÙ®ÝqžÃ´ÐOÿ Ãúî¡ýÑÌ–Þùëƒ5G­] Oþnô’†ªà*¨)έ>ò›Ãµ‡[=ç¥â+|×êæ wZÒ’¹4Wg¦£±ûÿ„ûý„#ñ~nÿøpm‚ÂÿØÿ O™ç –ãYzŒ[|û~ÉK?ke÷ŸàPÃä}žî¼À¥7íû<Î ÆO.€¹ƒP ý´=öñÁÁ`Oö?âzZ;)·¿=ÐKîà¿àK³(øº\æ¿x݆~àšï÷Ðî_ÒI჌uu]42ýúkX23ù£wþ7<µ.õ«ö)»› ÑzÙÿ‚`Œ ËÔnõHš@×äa¥P(Ìbz*êò¾Ñ “+KW†£ñ ŒFïÿ^ž€—<8\Oêèìlöÿ‹?vn¶&?PéýÃòŸáË„¸m Þ9è2àÅ»ö«—`íà±i‰<ˆ@ýòQêý{xSÐØ÷P5•·0/;•vvÿ¿ŽRŒ|‚ëp€ôéõ¶(8ùÖ&h2ª—íyO“͹΋v­-¬¤2iíðùZ\%¸ì® Œ­J:‘ÔºQM\%1x ?žæã2Oç¨Q|ä´ÿ}ûýórϦ.?áu>î%Ú³¦„uQÄÀÆoí7:NT”b\e"AM™ˆ?¬ÂˆÔáÕÀ®9¢Ú“§d&Ã¥9NÄÑqkd§%ªP'Ùäv ™vÖGµ,q@DטÚáÆ[›§—¢-wír”¢-u²| p<3¨ôD…¸]‚b~›öíʃvÍë&˜¿; -= MvÄy†£uÅVO¸zM„ÿ¯\Xà5yä]ÚÚeIÃM{î++‰”ôtJan*U£,QÔ ¿Ìi¥²ˆ‡Pî‰#ÀÁØéˆOÊ»FGðk2g¯¯+ùâ^Ê:X;"/ððKQ‰ÑyXkQ÷E?Eô°3Ê ãôB"¢Ìóøpò,Ðîæó«›ûÛÞŸò¢hLaZçñ²iâ-·ÂhÑ|7«Ûd…}Ï{!ªO—Vò¤/W‡ãýŽZ|~Iô&^ÓAr™&¹!ôÉÖ,ò•Ù–š (¶ݾi×h{oPEeÜÞ÷äÍdd¿WJ·|ÿ2yMp+Ó\ì1&g¬Ô“ä&§¨y¾-Ž<—ó†x¥¦¥‚'ÄŸ‚k°Ö·ÏþµÙ¹ê{E[ J½ … ¬©1®¸£«À+é¯CWÊ s¥Ïë3WžoU=iZHîI‰Sêd² ª¸NäÃn_7 zNM1J©1Qîqiãúš;1 þ•xÈÇè¤ Œy Œm4÷Œð¡ETr™,Û%€,‡³„™8E§“XS8?›˜ç{Þ„‘ä +Ú`SÖ¸hNQüž;ô‘ÏŽ €Æè.¹Rˆrܬ‹ =Áõ\Ð1 =yü=Là®â»ä•L‚ì$ÁÍ  ØÃE3 ÕTÔQ,ª g2´áª9@ióAl8ôM3/w˜¯š›$.Àv•Ì2Ýù(@³ º>¸*®d0ê<—Ag¢ n(̵õ°%j¦¸³ù”çBD‚ÈÍ'y¸å–q³Gb“´ÅINÓ…ê–§z¡ºÙÉEuëœõã´.)Öòt6YÔ| SU/`(3Kq(°› äùmÐiã=ÔCŠì2Ô½Mø6Žj Äß2é‹H§#ùAŸ¢ïnö‡¬ÁtÌ ÌzzŸçk?Ô6-£Ç´$܈è1É €¼¡;û¦X3j ’DÖª…Aÿl¨ݶ€fS¬Aسåp @DÏbžŠ2\@Õu‘ñôyŒ†•’õ·”"’K J#tüÃ!&Ÿ´Û³peUž¦1Ecé˜~•p:Ï6Êè¼€´f÷ጠ θ¨ïì>ø©¼#yv1i@€üÆÃgüöÔ(p;“œ¡9éWRtݲw3…›f¿É.ÂÓvO^ûOßw ¿~CgZ?BŸ~‘§ô]v¥+‚fl4Ÿ§&LBE"è6–y·\Ÿ¬y$8UüZkõΡæqÈ`²]š“ &";6v´!$}L*"¬Åf«€;Ð;Ìý$˜ð°Jyû×ëf.0x†}mÃOZm#pD0:‰óvªC@˜¥û+|¬ÜZ|rä…óí_É5~ÝI×(SwXæð¶äLÇõû÷q9`°DÄuö ³hh^”8\¢Q˜+ܽ çt:ÃÁ2Pb>ӵޫ’5GåŠb{¦Ù[·zØ£¼ívá "êÏ <ûÒ~x *Éïs¾ÌB¸€©ÌgI‹Yà ¼œé‘†T|KœÙD÷\(­Ô^—> ¬º|ì™^ !Šñ’ÈBè½ „e¶\¬áEŽ;”«ûœÄÐL­E†(ÅOðîX}aiÚˆÕ·OV¦±°Âôal›Ë^SÿΠq^—¼‰qVogRÎaà°’–¨c¨îcäÀ,ØekÌ„JsAóN²j(ÆeñйÄϘ$Y„Aº Ê(š¶SZÒK]u–¯ólÅÜ© iVÖ˜¸jgi µðÓ B+â¡„ÔüLÃ"[!¿Çk\YZéÂÌîØ[E?­ÍZÉx´Š{¨Vµ6LÛb–#‹qQÌZ1Œ+u&®°|ùz¤}¹êqjÇ”ÔÅÃO§ÂK%!å2ȼiŽ¥â¡*Ôrߥ(µ!ìy ¿Õ%ägŸH÷±rY%o6T#®‡c$¾àI;’Ùh_4}è,5ÅÆÒŒNÂú×EÒRn°O(µµ/ÛSÑ8„½GyÞÅkzÁ0°HW~†¾nëØ2oru”]Z!fpÌ9!Kt~¹‡jBØg½îò-%Fµšߟs)y‚ཨ‰Ïµòý‚‘Ú0[/“ ™gˆ»n籆äõ½%ÙB|2)AÒnÆó#ƒtEÍ’ÐAðýêSóEeºœI½k®$Ç5ã~$åuã@T€“"ömU$|”¢xïc~ß #¹ ⩌Oö÷ËCü=‘«”,'KÅŽµŸ¾$D1³Šæµ)7Ï 2£_,9–`À¡Ù”P )D_›IÇeb ÈT,š¼ ÿD:WKí,ýæM.*S I‰—xf°Í¤bzpí8KÍŒâÖtuŸ†ú¾/àÖ%ªµ^¿‘2ÞLIÌŒC´2œK’ê§Å< /Máiv³”ê.É&äûäJSZÝ>MÀ¼ÅÊf¡-Æð„Þ`Ôªâ7:›­˜ï’ä}¸Ì¶š±èy¢/ZD£À ¼É&HNÙA§2f1±N°Î±ç¶U¥¢“"Ê%2þ‡Ì$Ty—*Ý%Zñøv_õçA5²¸¶jŽ™9éßß4‡àf§þâ@£?<”\.´"Âçø¼ôÏQÞC¬C ðU™JÚ3ççÇX†”Ù§u!+¡Ì) 2Ç*"ieR¶Áíþ<î®C‘¦ð€Ð?îȆj11Ucæ%ÆAo!ª"àôÛGŒyFÜ ²d\¦­RNªÍèž ¨ šj%)( C“è]ˆ²"·ÆÜC ˆ„(í ³h]ýÒ,6ˆvN5‹íU‚åJ.ÐPi2hDJ™9÷5/,ÄUu9´È~çÚáDÜÇRp›áìAßÔ•0]–Wbƒ.ÓT&‡uApCœÉ÷Iž´,h…ZƒœwåæÐ ¶mf)›V£áU¡ ­¢¦X>€°÷r±«`<.ëà8+CVCà4Z7ŽüìêƒÏ¾ØýüãëÇWüu§¯>ø#þ߇_~}ö‡Ý¿\}üÙî«K› ÜâŽ\VÖ&—: Ⱥ­ùXÃ!{5c:ÿÝÙkôØ|ÈÄÝì:3-`Oâݸ.f ᯩµ®–BC3S0aÂÙâšh¥ä²sjŠ¿³5 p\ >—žìbg®ªY›ÿŒ!}lÄ ]œÆmJ€©®-h¼Î ]¹np:ðO‰•íâI¦)0é`Qµdü8 :ó(N¥Ç˜Q¥ T‡¹ ¬©«hyXúꨔž­ÄâyTòˆ®ËÕk‡9å\Ñap•%§Æ³û$ÛvÚ±D‚ºL^Ÿ¡¶T ÔYzÉzðàX¦X”|æ„ fçb^‰‰9LƒDæÈÈAàÆB1ÄÈnJ•ˆ¿¯ 0w­€¯!³àÜ‘€¡†HSKT.˜ÌBU4€É¾‚¤8FÁ‹=ñ°Cægð߃«Á¹š>¿úŠ^b‡“IÐÙéITœ°¤6Š9U‰è.¹) ên•ñ›èÅO[½ 5¢i°ú51o0! <Ì5†us¢'‹ø`Xb—3@ùï× {àÂ,e–J Á³+Žä~ÎæZš%$cÏDÌ# ·÷œ Ãí,J=>·òr‘}ƒ 4khK_¶œ©sÿÞ`ŠÔÍ?$^† ûkxÜ Â!ì{4i4XŽ"‰™ô'×J²ZʾÚî¿ý‘ÖÂzåÜâ³,®¯s %?|’r1'ú*³¢ÌѸš&©?¡!K„2g)pxXÒFmöŽ•˰&‘ÓM›Í?(JêTá®í ?±üÇI÷#øWVkÈB&uº¦( ”|×­ŸÔ57Š¢:–„8p19KÁ¡/È”eM©×Û½Ø_‰¶Ô%Ý`¶Ôm»ygýf¦$i{7f{°ÌѰ,þÀc³aõ¶5g(/ÜGµ|M8Ç÷¦p9p€Æ.\$ã’.¶ím¯Éóÿ¸m.qyGúSÖsKÒ¶:y`·¹ë¤¬vH"¥®e*Z$ŠíÆ:SS«ž'8ó¹`œ è<%G@¢mŒ}&†cOuudÀÆ4Yï/«­Aûà–6'“Àf"A'pEV+›z0|B5æNZZèÈ*ûûëmk=[Ùý;52¿kƒ\Q³ÀCŠ“¤(Ü+Ñv¯”ë¥53ÕOQš7ºVKò”»Ö%—ÄJçsis©²Ë­”¦2Ûñ8ó8ØDŸçü°½€ù#°ÆË2Ø.ËMõRlü'±Šrç8J¥ ²9Ï]Jª2kÑð|ßT½šy\´5·µbž»ÃZx?aaÉŒ½Ä)vþ"3^øá«t™YR¿\Ç7Ê#Øj¼M·¬èÊ„%¶Î®yK1oH=7žë¬Qšž[ºö”O4$ù†ŒTJp‘±Âež©àUòJgjZ–v ¦Á‹‡#Iù¥®.ú¨ß¼RedœLM&ç ¶¹|pYV™b‹äsäsŠ÷$ÚÀ¾&“In^4‚]pÑ#¿>ûˆ™Ä@OÄ:q§¥×âvº–\D½fyRhÃ$"°€@Ë*Š¢OÃê¬BúR>­ƒð2ò¹<'QSÁú§ÐöpÔ\9S!–êJL è³|ô°n;Ó“¾8înõ néM¡°^â¦n-ű×sxC7¾Áé…Ò:L-0WìwõhÍ>Iº:Gv“þÝ•«ò9²Ö˜+®q}Ìþ±Saîrif¡uƒ_yif娄vB¡^OùŸÖ›Èÿd1ÝÆÁ5TJÉϨç¬;DyfL"/\°"ÎFO.5½c`ó¬Õ£†iýThéF§s<I-³µüp6:¸tUJ+‰ã|¶–°µ]Jè|¬×…§r²éoˆ¼ÓQc<óX$õÒ]²ØKd ¯ò;gUëhcRñ¼ÅSÌ vÌW\ýÓö(ŸDêþ§Gq!çÔY?­¿@=÷-¦=­š%Ä$•GXG¨ÏÖVôͳëÑt"¸’Ÿ,ªTj”Ù/™ôLÆ}+'æøT>'øÜMÎg!Màb“ã#ˆî¼:ô¬^QíÖMü±x2.9* G<Øè61ГÚWš¢TŒ(rBÚjÇúœ(*ò/©¯ÝÄv37œa¿pdt7„<Ó:T+¤ìø´C6JßÖS©#cαà*rÿé°a›pnë¡8ó»8kçÎëY ƒ|' <2X[}¶I²êRY¥92ÃÆ]5SÛw`G 沺¡žr4^?'úJÃÙT'ó°Ôäh²äåø• zîÓÛÔ=05jÆ£5=Άx2!!Tí@Mv‡jtB5sfž>ë,¦[ÝÔÅ£¯z¾?¼g™§sN7Y~€90’'ÙY"°Ù¢ÁÒaÀ+œQQ2íçœ Èòǧ*±>t•XÎR[Ká)âCø÷+±œ‘ã}(ª8±ÁÏMK1Q´ÐØ48¯&˜4k:^j™EûXD2µ®%˜œÆØàø¬óQ(ìÄê:ŸúD¶ˆ( Íó¦´ë¼ö!„·.(‘¬Sâ˜Ým^%ßuêÄ?†Iºt}f¡ŸÑ؉ï“@:Ú|q¯ì‘Ô†¯ÃÀ|´À¥˜½d¿ËúhµÝG“sñ—ðR‚M—ßáò¸ÒÙl3ÏoÄÅ^zã8B`ÉøІ i,¡¸ßÐY ržæFúÄ;í¬ xpä‚‚q¦·ÓÊFGèìþ)ãöJãK‘Ø¸Û ‹µ’•›x™‘qf‰:õ>™È+™Ö]˜™6–£.Ì¥q§ÍdßmK#fl<'Wîl£SMÖx6˜(ï|N!,§Óhã”ŒÌƒÂæ{sâ-è}ñ_ÎN"rÊEDuê4ˆõ[%Ê7xÂè]Ĩá9"$iõÖÊ#˜Mùü¢ò~“sNÚ,¼0ßF˜3ê4Ž’4 ½y}À*-_&dÆÍ|Ôè&`îQ¬²á?Y=M\7½rrKWz_ÄÌÇ.B&iÊr»}î÷t•oC Iwž`÷ r°Ý<Ѻ’œþ–zÝ{»õÚpÁpqÁë·k„J’Oè¼{¼È­T±BÿBÂ{ê²Ëøì`{ÞIœ+*"›l³¯:—°J &Ì—™ç:èdÍ®ö–\æe¢ºýnœÉHÅr(D7Þ·ÉQ>5–ÆQ.oa¾À#'åãâð#Tš¼ý"°,I²¸ëá`}PûŒITvÈë*˜g墕Vñcˆ¨oi=ÿ-¤È5š’%:—\2p§Ë¬¹&Dp)s>—ˆË’Ûø¥¢€\¢š;-&´˜ôzz A‘wûŒ$±Z2h“XŸKñ;rü=;R¼œ¯š+wDŽ×çÿ¥$oßÅŽûÏk©•!?Ь[´Ÿ’»—•‹täî6Ä+z~Ï¡Š`Gs˜‰À>*w ìåHÞNe~ýꨕ(DûýŒ‚ô™uâRp³VãÊo=îi_£¯a³äê¸NÆé’Mâ fòÀï ’º(®Þ­Úƒ…®û?uæÄÔìÄ!L‚ãÓ:ÇÈáSHìì{=”õ«Xö¸döÄüŒâŽUjEµ’ÀWWÿá£Æendstream endobj 1160 0 obj 7162 endobj 1164 0 obj <> stream xœ½ZÛn7ÝçAo˜Çî…§Õ¼“O‹8q² Ö›8`Möa$Ù’`Kãk²›¯ß*^‹l¶$'A`ÈuóR,VÕ9<œ·ÛybÛÿÅßç7›“˜ÛË÷›yû ü\nÞn˜o²¿Îo¶÷ØÌâ£ÉÍŽm÷/7a¶5|«­œßîo6?lTƒ€Ÿiä“1F Üÿ±³ó´Î©áßãNúbøb´nr޹•þd®ÂG¦'gõð|Ü)˜VÂX±grøaÜÍÐm6³^Œkàóð¤Xû Øe˜“6Ùe­ ïË ÿÙël©ç¤b“¶à¼ýEt˜ø­wñíNÌ8‡ ÞᢅгŽÐöcY°ÅZmÌp<~Þ*ņ£„OŒóá=š§”ÑwCÏvƒºí*tÒ°ün§ÐÔΓ‚ñ£1Òqj öŒÆp¶0M­ÆVO vö#qsʰPÒûuñØY¡ùU?› 9œçO8À͸ãCFËôÑYeÓ†ÙᢵǸ@{æI ;¼Äþ¸NçG~‡f¸IÈà…7í–!ŠˆùÙ¯y’ëwžÃºe ²òËà“y¶dqdíyÄÎÄ¥:ú5tš¥ÏÃ7eᡱS2®{f±ÛÌÊÜ2güþãr_âŸv‚ +m°H;ÍLŠäK=Dã¡ìht¸÷-w1Ð4߯@ä†ÑèÂö¯³¹O™è¹0ÆÌƒIøàÜ1| ÿ1~4ÔpçÚ‹àÚ›©¬_É®˜ÖH½h·¶>&ÎF>‘³È£2MC¡ÉÛË:ØݵF“$Íq ´Ds†_J]º*³ýHTïÔJâ†S©qñ´)«‚U“Ö$6«NIç1à RAŠY‡±CH=IÝ·wF;¿lRUpãƒ}O SúvGæ‹™öMXùc^[Á©“¸¶to°ÏìÈÉyNcÆ©U Þ÷Ñì¯/ŒÑ&“ŒbÏsÜ7eÈP8ãY/øiJFßú,ÞðI œ¥NAt¸ên¯d~{;u˜+‰/«,‹Í/Jáï•{,[BCÙ2¹^ ˆ§èõ°C¤)ck(rIÈ®›¹ 2þ›ý_–F¾ »«Ë«½?ŽŠŒß=bè"z±1ùPV†@Ñ·€áp*F˜tµ'd –åé8B¹ùI Œhܺ˙ļžJ~Wiðà„X1sKêÔA%U©ü–£­B„£ÆV°e†µ¢Ù)mªxjµøh&›Ós†KoF]XÎ:”¡,æZ‘1W˜S0îƒ`†<,¹w ÛN,Ùzô«Y¯,Ôm‚º¤ÎäŒ^î/NÚÀ €z¬5ó(õðèWÃcÞN |¥ZCIFºLhQîCR ýyþTRb$PâJ»†á°]dA :Xj'¤û‹¼N!UHIÊên3lwb´©‚H ´ª‘>o°Ã`Fõ1¯ËU#J"1í1L¥¡Ÿ!q?Ö ¿ ÷`‹ÖUnø$ʪtJ¢~®„Ά×|A˜àçWj‚è~òèÔ^\T>ÁœíÓ·’%%ÈßÚG¡.úŸ5¥m1* b(qúOcŒ (½¤Åug~B6ËëÛÈG”XËçf!¹‚CkØ=”¦é›Ž›†ž0µƒ}1K’IŸÊ.Çód—taýn-oJ²@Ácà,.ø hdëðLOŒÑ†UÝ\G«X¨TDƒÏVb:ŽD–бûªx…ŒSÞ¿÷Iôd¿y¶y»bÒ^AAb+ŒÄV[eñ„eQZy|º99}ºýðîã‹ÍÉ¿¶lsòwüïñ÷_¯ӯ¶Ù<9Ý>[\jÙ .˜IË­2nr:ˆ.Ÿ°/qWW—!gX¿þ–!g…¨D—Q²­K|c v¼S‚±S‡g&È9 —nÚ'\•XnE<Èþ< ïÄ€µ¥ñEÇ’{=ä*hCàì!uDÀ6,@ú¸°ÃÔD5¥ÿ"q G÷É ‰Ñ°`Ò»9ç䴩йìêávE2JÞjÎPLAi®É½O:y¨Ålad-dÁ;¸V}ÄC,¹.%¢&ÚÉ^Þd‡ÿ²dÝℇ|„ˆ‡Ds$ õI†‡PHàÄp…r ï/±žU²;Îõ-½‰ð¶ ŒMƾrî>%c:YxŽ0-HÌßöÆyKÒù#µ®9­üv}(øµé;¢ 0þv}ªfçäg,2¤ó6‹;»\±€š&`iqÂc×@‹À5óìpß%#÷¢Ÿrµ+–Z롎»F8ö:«©€ež 4µç•¯sVУh²BÞqªJËy&¹Ž§4ZÊ’©S”%‰ JFl'¿îçå´˜UÐÆÌíPŸíL;ìXk3£GF’µdÔ諨SJÙySåGðW=I Gеa“Å~cÚÙÇpØ–Ì'R‡|zU½‰ ÇýAH7ULtŽ}þAU˜ñ»"Ç æÛ”‡tO}%ˆo‚`®KuªYvW„Y ­-5ÇÍP^7ŒÚ$=”•†ù6Žªg°?^E 9’yŽ¡ŽáMÛjÞÅ»š»NÇ-5K¥‡Cù¹¨¢AMeÆýÓ4)~¹CuWÐúˆS%? ]M_*R§Ã¢þa.Ë{!D»´þ½jgTÉèÑð8HÙ˜uÍ#­ª+Trí÷<ñC±rpJô7ÜWì#5°S8ܥĊ¨Äz6!Gê-txZè7 wLc-)îÿoˆ5Ž5¨'Ã.åTz#~r'ýÙC|ÓS±šZð;[÷$é+u ™ê»WXqfOmqðÔÓðՌ▵#߯Ϧ9¢>Ë»“M§9.j÷S­Æà>ꪲÀ• ëBpÀúò"ôÆØïV­®Š}Þ¬ W‹{§DÜ¥5aÕOdx_Ìýµ”•Ü0¹È†ËËÕqkáÓ⢀µÑE¢@ˆŸë]f-Ø}Md!®½1l®ß#H[–Ìš½Ño{r.a±¯°%ÞÓ¼hn<.‹宲ójYõaDóQ¹˜îPObî¸$×Ë}ç„KË%V&ßXãOÈõw@X+Ýð44œUº€’$…­ÉÏëx/ A›o*Ö/%`Í%(oã©AÞq‹Y. ö·Ì Þ§„9ònBhHÊ*^oÇü‡¥za9ä)5â¥×"ŒÔ2FXz+’‡ûj×”“ÜvÂò3ZQéé§’$oä„åUZªúÕ­ï7ëä{(=ñŠk)ýt¥¬ 3ljpM¾Ã¡™¯a¥~^L,u¯+E4À‡ÝìÁÕpá¯9¿‰«²/*êøÆâ7Ó‘H%‚±¬SüaGΨ¦%¼Á¢ œ_ÞZFHgª„y[‚êK"ü`gÄ…«ºÆ“S©þPòxÚiŠVÜsÊŠ^«+>IˆM±êÂ4~W Í=Ëʾt*ñw5òÁ§’š!Ý„Ë\­+ ˆ\‹7E4ïïEá GM ŠL÷¾«‹üåuX§íí³ ÐUßÄë°kbÑÚ)ëSUà‘Û¶¬o*R_Ò·zð "‘0\å± äÞ*¦ë7 °)o°ÂJçKòh ŒÜÙÚ¼åSç«!½³U`&ûU?@&JNüåÀ³Íÿ#áôhendstream endobj 1165 0 obj 2795 endobj 1169 0 obj <> stream xœm?OÄ0 Å÷|ŠŒÉPÛi€N$þõ2˜ît7u8ñý%ÜöPdYzyïg'Ÿ}šÏµ&w3"³?»ä«³»8\,þÚ“¿k‹­šš};¹€^È—šÉ·É}Œ}+ŠýW{šc5mc”˜,َ澃ˆ*†‡ˆ Z³†ÛHá-v9÷B¡ýyv«Ê¹†ÑT6ì2­ÀîˆÃëœ ¢RþáH‘ð8«U™1> stream xœ½][¯7rÎóÉþˆyœdÚ¼_ãd‘(ØñB@6y°,­,xuñEŽ_Ÿ*^šÅéî9£>¬†ak<3šþŠ_‘¬*ò#<‰IžþSþüîýÃW–ZŸÞþü Nÿ ÿ¾}øñA¦¯œÊß½?}ý2}Íœ”˜œSîôò¯ùäÉ«“õúôòýÃ_Îÿô('§Œ³çO5)%¼Á—ZNÊ*}~óojkåùCþ}~Ý^¾{¼ÈIJáüù7ø[^LZºò«V™ÿyù|ðqX;ÃéåŸ^þÃ_Î/Ò¯ g „w£ô&¨ó_ñ]?ÙhΆ'Û`T,Ÿ»ÏŸó¯:#Ï¿ÀÇ>@ûŸ*}ôå¡äI:Z}þ sðCÕ„­;E“ ît±nF¨ÓË×ÐŒx¼€QÛé—G=á|þ kƒ ø|ùðÍÃ'­'—x¸˜)œ¢ÓÃÉ8á/!¹_¿xøêÅœ~ùé󛇯þë$¾ú7üÏ×ÿùÏðÇ‹9ýÝÃ_œ¾¹Ay‡³Rš(ñA“U™úo-2‰¸Mœ_:á6Ñ1~À•ÒOÑuhßÚŸ†Ö&*`ׯ1zl±c¼±ñð&NgðïÑÙœó΀‹û©¼©¡·(£Ï¯ÀÃd¬räc0V÷‚½çƪÇdÚÅCÇD&/Rƒoa/á&ü“ßÿL"vö¿Ñ;uþn¶üŒ9Þ{=¿¸áÞ"—ìø¥’ÉwüÒÎJâð£’óùä–ÄKw§1Î>…C£áÇ*‡nÔ¢M€À¡¢r¼jÃÇLÚ‡Ö+¿í[ã÷Ç‹€iC]ÛŒ*ÈÃÖH˜á„¡ÆÜI¨5¹ŽP«ó\0¶S‹NÇO(Ä¡4Bë…HÞß*©ííÏòùSüjk½ÒdÎG9isv¤dÈOëø\ÆÑNÂãó·Sq­ó–¶iìá6'w©:+‰ç“nýÞÆv̺Q`Œc™ÕÑÈCÂ"õäÕ}ÌÞ˜Œ¬À!‹µ”!?§~b þ°ý1¾„Z/ÁËdâTÖi Íjhˆ´ 5àA“t£8åF]9% »hWCà¬:ÿ/„ŠÁH‘2/ „´}OìXÖ‡Ú¹i& ŒÄöü}sU䯊l ™oÐUÌVHh-˜I‰O§-JÀ¤èSŒ?‡d¤0gÊ#(´ú ŽÑвãÍîM×?<*HÜ ¸3™0?Ý‘Šj;&·U~ߘΨïgÌm2o¯Z*ŠäX™¾›è•^ |އõP#ê¡:N÷²{Ox##Ë0¥ç4ø]®]{hyé„¡YûU&ó £“ÒgMrsz•³‡¤ð ̈Æ3Ëm@e–àÿjI ã çÆA›´‹ƒ`R:$kás¶hýØWaî˜L+­ÜTZ þ?¬$Uo Ò˜ñ‰4ËÙU̶³“¦b˜â"!A®ˆç~ê+-í{ódtcút©Ên„pÔtæ< ©ˆqiʬ©ˆÛÿT€iøˆp4éÅ„y›JÒ>wtH\u9Â"äҪΠ2r´ÐÛ Á—×8´ÃKÊÃ(qDØ£<$õ÷³¸Æ m­j¡77 ?"™Æn¢„ÑÓj!I¸úi»§Ä8ƒ]3ý;ÓkáGF×@´Ð!Á¾³~>vʯ:Í9r=¼¸gÔ•©„Çn•Ô©‹R£¥¯WÝTõ@ו aÒòlR’z8Kð÷|¼hhap ž`=<|t~£`Z8$^R9¸Õžþiö„»V2dH+ìÀ1NJ ´†ûÍ2â›_ ãs9ð*ÙÉ…•‹ÁêDVH¼i‘•Yii‰¬´Ä*÷8z¹Wz7qÿ `ã&£üâºÔ’¦a㱠☨ FJ»5í¤‰x¥‰à~Ý—-Ûˆú- ¡ ešA­¹Ǫ̈í%J˜ƒ:—0c;7ðÊÁ½™cÆPsLÇÙÅd”Çt1ÅÐ.ƼEq?™L:éÁ\Û%“,˜ôÞ’ˆÀƒrƺrVA¯‡¡Ÿq)KH$JsOaÒéxHJ•ƒq\q¯\Ü›‰ !¯K†¬‡Þ©Í6Ãú›ú|·ó…ù;ðJ#Á};ʯ6©®ˆ¸š9@B€ƒ¼æO¤vþ˜øôÀ˜…xå—ྋßmäVØc[ƒE¾¶ô°VÉn&æšÌEyÜ•œph`ªãç •ÿäwDàՌǸWG$¸X)‘ýŽ{•ÄQ£f;«ô°‘C@‹‰‰88¸qW¾ìûÒ-–€Ë¾tÍ«E' Õb©]ã’x¡²ÃM6žÌƒåo s›ÆçOÛ"hï¨ ª˜×[]¿H>¾+e‰ñ‚ÊÇ0þ¹þ;Üwìteá~ÁÍ:á(â\8FÏäB^S¼"nuõ­¯ÁݳkЦµqn[¤Š½¯W:2éª?>½Q¬²ü£«j”nåØý„ÖÓ7­]í›C)æ¶)îìØàÍù°ÅÛ8¹ÄQRCÉß5¹mAÞ:;žÞÎ <ÕÍ+e;¯ö’œGtü!÷Ùf¯5Ƀ6VÖÛCŒ Lð½ú2ó§´Yò‡o6þЖùýmSBuùM‰úZ‹¹¬@âK¬@zaxì·ên´ûÉãV*VòˆR‘‹‰~q•Ð+¾õ…“Ø1zLîþYŠL³/–È7û%öæ Iܨrîg[´XÙk¢EVòØÍ)ä5s6 aAI…1Ut1QÈ­N¬u"+‡ìö‰=Û%ÌËêvu4Ž ¸Õˆ•F¢Fd¥‘ÝžB#±çzñ±ÿ}™P©¶¢X»"»±pHÕˆœòÛ“9¤ö¬f¤ýI¾ò— ü27èÖEÙõ‰•^¢Od¥—ÝžB/±çƯQn¯ñçìôâ¬Ç-X„FìªÅÊvS-²’ÍnN!»™ó×äsr*VPß>B†\ž±(I¹ ëàܲÆJ9‘5²rÎnOáœØóéxè“•æ&¡ãú0·t±J¤‹¬„²ÛS%ölVµURËVq++‹D¡Øx"ÇÌ«ñ›”kF½è’­:8næV9Vª‰Êq=ƒ’Ioóáìˆ}H‡ÄÍ9#ô­GL„„ ¡Ú¼? q'{•º/äšûiä–=VŸ”=ÞM#;âB#ALÖ©¶Æà,Fœ+i‰r6®ë±« gTýø<ÎøgÎ(b2|ÛŸ‚d­°ƒm’5lJd—=V²ªì‘þ°(–ù›ö”þÄAá.›5Ä$&-m QikøMìZ¨cZ[ ÛµöVí¼€^ÒIbÇñ©»V³:Ñj>ßÇØA# ?¬…ûtZnÍ_Ê“ÂôåI£›dL£Fݶwó Üý¤r+7+©D¹ù|RÙAR è;’X˜˜ç$–™5nUce¨ÿû§n„œ[GÏ–CÜÈZ8D «‚¿”¾ZÅÿ÷²j ±4é‚?áñ3c]dlìè!•[ÎXy$rƱ<²Px$l-¯:3Ë–­kÂÆu] b¢EifS1ø*FG¿Ü®¿h‘ê.ÜÖixl¸"‚d{³u¯×œÿ{+2ÝÅ|v³j á¨ÇàĶÃ@¤Dg!xEWÎæ[ˆÏï`ͤ-Û¨Da|Æ T××fÖ„l¨·¡ZsÌå¢xù Y‘æ I(‹é*Ý«‹u°ùß'EÞLéêãëÄ`?mÜúÐJчî¥j¦m!Ê]ИÝb4t„O2Ãh¡fQdfp-ÚX —ûäÖ‰V›Nt/ìH3×ÒÜÂßR2§¼¤ùúlÒâ §€“w3ÿÛN.ø‰M»-ºGØm•(Ï!פ>é¡Ò↛䡵øÃëö{(·Þµz(Ñ»îuQv¨ÙE Òå„©›Op7XµÝÆ#n)l¥•Ha÷ÒÊ5ÓJÎ(ÉS^*è¸Ò¿ Xñÿ>·A Ë7†´‚&YyeWñ^©Šw'¯üP¯é÷­u_¯Î"¤;–k»¬Ë]²kDÇ.Ê­ôQî^úØ¡fúÒ'é[Ïî[}XÈ4Êj14x{#·ò¶ÒÙ_‡º‡Mv¤™ÍtÌ–JmC†„ùY³×KÏ™1o¥|VI‡)½ºÀÆvcý¢<¹ß£¸Õ¿Õ£ˆúw¯K±CÍ.ÕÝû\ŸbÇ\|Š€¾'Ü·Já¿M8dq+”«ƒ5…ò^ÿbGšý«}ʽè¹ýøIÛD”Îô…“¶ÝégLÓ·B¹rHÊ{Id‡šI\j©w²XC”סÀC0â{e¶© r«–+µDµ¼—Zv¨™Z‚´UyºÓë¶wŸªÖ+âvt…·µÊàZ§!õ㛚ïv&vùtq¦ëËiw8?ÔäLéngâÇš‰‚]-D‘"D3æ×~ë/„Þ߈<êIä›Þ8lhcW{Wo$jï½ÞÈ5{#AºßÙ±o$`¯’oR:+«›Æ€ë3ÆqËÊ«W5Yù^§bGšªÝïSìP‹O5¬«k9ÿG«:F-뎨¸UëÕ¥ˆj}¯O±CÍ>Eîw*v¬Å©Øûroo§~5n¨âÏW¿"âù½~Å5ûAúneãEkæûVõm*å;öœ]=_™$êù½L²CÍL¤×§`Þ{6Û™tzüˆ=vïòêŠ kÚ*ïlÒà/ùN8gýèÙˆ[ß_}èû÷ú;Ôìkém_kËBt¨½ÚCbJÜÃæ¸±8–`?—Ü"ÿÊ%ùïå’jæ’ }‚˶©ge¥Õn¾P˳VèØEÿ…ÃëKšwpÈ5qH‘>Áá={d|uç]½eWÕW&«ª~/ì83&9 7I´ÀlqÕ¨ØÞ_g‚r‡Üêm9·àÕZ͵s+pöðÝÎ:gÈVùq÷aÕ½Èa{=Œjö°îØ‚õ¥vӵܾ’¼”åñCÓÈåä‹èU -Ûí wr B˜Ñƒ÷iÕ«Èi{½Šjö*‚ôÙ^ŹxÕUë’…Gr#†:¤Ô ^¢cÀ!ª»7–ÉϸÏL¨~FÎLØëgìP³Ÿ¤Ïö3vÈÅÏæ'×ÅÆŒ·ÎÙnJç_ãfG‘³öú;Ôì_é³ý‹rñ/‚yq4r¹ ;„åMØâzg§ŠAÕ#5ïØÆ}4Eõ½v:Å^×cGš]¯}¶ç±#.ž× w“g:,ÉÛzm³’)>3Q UÛñÙ°qû€ŒâZ‡y|‘s±CM¾Õ!½ƒªšan¬B¤«€õÀÇZ!à>£¹qÇ‘É5‘Ù!%Eó\ΑQ«õR:™ê$±mQ”‡œ¢b¢™ÂÕ ð ñê2çœÄ|r@z'×Ë…Ü'xçÛ8m䋜jr¾éSËUšÓ•NÙ‘ûrËòvúåÆ@oÒÆ@Zš²ŽCeÀ}žEq­CP¾ÈµØ¡&×ê¶&]T4×~..z‰‡‡yz<”ó ³ÖÜø2)ç1g7P¤¿.Öc …¸“2]4ïH!]ZʸàÉsH(óšR S |óðÿGF*ˆendstream endobj 1175 0 obj 4773 endobj 1277 0 obj <> stream xœ½]]“[7rÍóÔþˆy$«BßqÖIœªlÖ¥’­$–dK.[–ìµ½öþútãã¢AÞ{9â Q.YÔ É{§4€îƒÅY> ü¯üýêÝÃ'’Z?¾ù˃xügøóæá‡™ÞòXþzõîñÓém~tŽ"ÊÇ_?ä/^=º`ÎR=¾x÷ð?y´ÌÑþß‹ÅA?¦œ;«Ÿ|ñÞýGyŽ1˜xøãñ$ÏÆhèËÏòKëÕáGuøýÑœC°Æ>Ç_„(…?ü÷ñ¤u< iÉ×'çÂY)_ߪµ$ßá]¤_ž¾#Àgõáßá%|pþ ^*‡ÿ8üé¨ÕY ©èïÿó¨ÎBX%/ð‡>(i.GòÇ“…—ÊËÒ2}ƒž”Ø4'á/!s ý.ÈZyøé¨¹óþðüRkƒ øMŸ½xøâá‡G­Ï.qr#à…/sÖê³Hô§Ÿ?|òù¿=þôãÏ_=|ò_òá“Áÿ}úÇ„¿>ÿýãß=|öùãKtgƒ`…§šìo3fíáu~é„;üx`Z›¨ ¤Øàª†A;Â{\Þ´A:øó÷™%Ý!À?]ö«“ ù¹'©á[bÓZFzøÚ ­e$>/µÖ7àEÞ{}ø¾5Ûò³¥i6¡Kè¾ð~ìRº³wô·GåÏÖ‚“¼úÐì ¼5øÞCc!xõN¨L"¾B¢ „ŸD0Þ«m+do_Á cŒ„„ô‚'p«Ðó'˜$ÁÕô%ÐÔ¨|Ù¬úGV #•Nc½È®ÁRš4]ðs)a sS¸ä6©pI "ì]QŠ#3RjÙ§tX÷€ÙÍ TÀs¦0ÊmQa´Ùójüþ˜z¤wZ"}–Ì uFêÐXsz#ÑÏm”ÔðýI¯ÛPÓ£þ·ØdZOà)†.dZ _0–Igí”´ú‘…š#  Ã“È’™,nÜRÙÒ> ì·+.d†€èuŒg)q0]8ÃèiøÉ“±JL‰€ŒDnmܸ+möF€íaR€;qV¸2fTÓaRƒPcdãÆ]¹"°o,†06óBà ù&oãú˜²“ú˜2Cû7îÊMbæÈH¡‹`®ÒÛ´ ›Ñ¤4SÖð +ή\:áîïSè³i'“¿T±a¿¹3M–BÖ{‡ç ¸I-kD2˜=}œ²X€Ì+ßÃK»„w48[¦û¯ñø3_‡%í£ÛæT‹tÏn&u€5Ô¨¶’ÿ²çí QœMÛ&¬ Öæioè8ª,¯f,tH˸I”r[U)%Fõ›3ÄÄò2€‰—kGkF¦F ˜eS–”Z#{XÿõÂO vàAg}ì0‘ÍmU%›uÿ¾0¬A¦`¶©PÌ·Ï'nsÊ«Ç[†ôþÔIX3/V•ÎΉU¥Ã–ŸÄ3·U•gbÔ/+SF£¹ít¿ï'Û¦àц™aŠÃ5ngÊÀÐØú¤£K³‰%§Ý!ä!gìØ#TœR u¶kSI==üå]Ñ;ÒPüò¸rNºã‹jŽ5¦×Ù²^_ò3fÝ¡é ·ê—óOëÏN36V…8gX­+Ân3u}jÝ!1§¿²Û#MoË&…6ânpO¡Óc; òvN„Ýê€=2KæqIi³ U;»Œ1Mùì6A‡çR‹¶»¡óWÂ@³tÃa³»rÊLY*'ÏÑ=mM|‹0XCaWcÇ.eÀu<…þ ZÛRîètŽ¿Và¡ßâѧ´ç|šVgCƒbtg4!LYWÁƒÎ%fÅåÃËÏŒUý[m–þbÂËŽ[*Çhö^vW0’Çú\]9<ê®| ëszRE) KEé¸WÂŸd|K†ÿß­ &°"vÒ§²ÉM^‡õC5©ö´á•xå•àn@%¶¹0¸’¶–»¬˜ØÅϪ˜T «D«Â*7ðÊ*Á½Ñ}Ôû]pÔÐ*ã¤jWxÐRŽ6‚,và…,Š{­jgÅ|81¨š2nÊ0©žU†¥þsgܸ+g 6 Xl_SNz›°“z›ósŠçàAK­Ùæ¸WæîÛ– °æ‹ìýÍê9ÅråjmÜÀ+m÷j&Ó»£Æ…œÑدMúƒ€1¸Ô+\ÛF“fRý* ‰dÅØ;nµ‹ËËK0!pÓ²¸Ý…KôëSÒž¡ S²7j ‘”V=è.µîfµ?DöS "ø×#j £.²ÿš½ÇÂÜ£Sý{Ȭ€ï©-ÜzAÙÇ4}âö°–³ãY>Íâܘ¥’ù1²jèv·»´N‡pìètÊѬè®3ý-4oÍô—-2ĵª1~‰'î¯û%kö¯Ÿ¤¢œ™#˜  %T/û*…úÂö(R`!âåÇU~NíŸQ “¼ˆ¢¸tè fWò1Jp%¢5ïPÆÆ« ‡:Yšð{9ÙÝïTÜÚÜÕ©ˆ6÷§bÇ]œŠàn!%6òÚ!áuÞaYþ;LŸKeÁrvn·5ËÜO*·(w%•¨r!•w!•à¾R ~:·^†Ì­t7¹×a¹Eº+·D¥{·ì¸ ·÷«l_—Œ^2ooäᮌ5î!„±Ã.„]Ї#Ö"¥ÀL_Kj±(GW§½wsÄ.¶]8¢jÛ#HâÇIºV o,ÝÈ*×"måðCÕ" NR¨/WVÕ‹l#VZÍAŒ^½»ÌI*Ë•„u¨Ü¨òºßÛ¹UÉ«·7Yò!Îλ8{ƒ}¯¯s#­¾Þn.'¼‡,'ê8êD>«°k¤WÏ""éC\‹wq-‚{Ý·n [xãÜYÆÍYqà8Á­;^Ù$ºãCØdÇ]Ø$¸ïdóÖ€¢&)Àku¥¿5¢àýwk#Šù„1vÜ…1‚û¢¼„ŒŸëY0ÚîDsYȑ݌æ\gÆv0—%Ž/O›ð££½Ž[G½zÑQâu츋×Ü%àãñŠ-¦[A½FԇƎ»Fp¯¶sò,³^;Vúp‡•.USª¤4ú2=›;â:¯KŠq¦A_‰ÖßïgÜêïÕψúû?cÇ]üŒà¾Ûϸ±V?#X·æëÂj†õ®£·F}õ.¢Q?Ä»Øqï"¸7¼k'¯Áʼny ìzõ•Ê*Y?„GvÐ…Ç z‹Äåú¦}å|Ñö~l1ŒJv™úB%•©Á&?îÌ&Å}'¡7·–C:£b·35/. Ø\T “W>Ôy[€õ~äÖÕ¯>Htõ‡ø ;îâƒ÷¥,7Âþ $Áb‚ »Ä|åŠHÌáŠwájGοpuSÃW‹à¦´µ†‘^­÷­ð=¹Nª:2¡õÊõÃZ,÷{· |õ<"(?ÄóØqÏÛïÿhÏãÆœ<î]ª4ùÚaI§[á`–²írÚpázã=n üêzMˆç±Ã.ž×`?Ûñ¸!'ÇkxIÄFÆ;’£vr^¸r‹Ž`ó/nQþê_{¢ü÷8;îâ`÷³=Œsò0xs÷%èeÇŸwâäÖϯÞEôó‡x;îâ]÷ ïÂA"¨kÂ:oÚ»n~%Žç!Žw!Žà¾EÜš:n,ÍÁ _§:•þæ a´¥ƒÄâ@ÌEÛc³ïÙ5þ‹ÃQ™ÿÇ;;Å}ËárÁ³ò~åD'+!ê ËuvÍÿÊ(ýÂ(;îÂ(Á½Qú¾…Û±:Öc^v¹ÿÊ‘ûÂ;îÂÁ½#ÓPæé$‰Ífò6Œöxø&­ãº ÷-•Öv ÀVÙaVoÀîó¹ûq »Šë›Ü7TÉÍCXdÇ]X$¸·v £4¢–³·ÞeK-¦çÇ]Ø"¸7÷u/7á¾oÅÖoŽö,„ {‡ZBLaB+€;ƒ63 ^CKÇ o¶d§îw=îK ªë‰±%ÿü¸‹ëÜÄõÈ,ý²ùÙ•jöŽû(o'Ädì×:éµ#èäÇ餸ï¥óv°²¥˜Ë€¦ûS“¶–åÊãV]ÎÇ-¼ÏàåJîºkSQô~§ä¾—¡:e*dÀ»ødƒýL—¼¹Œ¸•Úa„™Bžh¸Îò-Ï•" šg~á¹´ä=š¬ü8xD徚¢:/¹šbˆ÷²ã.ÞKpï áì¿§½vÄ¥ø"~bJ³Ó¨–ا4Ó:øqC%÷ÕÛÈC¼wñ6‚{_véeMrû­+˜ªéJ ^ iÛ ãWb´q»Öì7mTŽÍX­~Ü…c‚»5ðÚ½ƒïðtËØtH» „e‘Î~‘F¥M5àÇ]h#¸‹zªÕd€]]¸—[³RÑ©‘i€åÝÝd¿r¢²(oȬI µ-‹m;bÞ¼æ·#Ú¢;6X å•ó½ºKŰãˆÅدc(äu÷1¬²wuõu”ñðËõNÎNÐ3é† ˆ®pyØ™´}õY©OuNºzõY-)¶¾gxÀÃ}[Catõº:¹Í)l6s®®ÐÊæl^‡V,ʪ˜6kë³Üw:‚·.uøª;Ž)—¤È/žpIšŠ1-Q¸ÑBcÉgÌÆ%h0ºuã±»‘žCIgNÑwqÃ*ƒ„½‹%ÚíM9}ªcä6F K1·´8Š1^GwÖð†•ðeà 徧a)Ï&5¬JBÂ%úÛòÛÛ£®ŠFæ‚jîzÚ$‹@íÙ(´÷.Úk1ŽEa\Ž$÷KŽ$¹áZ>­.¨cØ[ŠØ0uNxêPÿï­­±§e5îSpxÒÓµ.ËÂQ°,9˜¯Xv¿±ÄŽ7“$¯tßöL*$ ë/zÂp§À»µËp¯<“eá#O f•´åÍ®èo0ÄtŠþžS€4yB–©>ZÓ~ôª¾X Û¶Æ›˜¯dà¶Æ_YCX˱tð–Žéþ %ó~›éÎ,Gvï·Éû¹äÖú¯\šËô„žË'ðå”.·0#v³×o'Àæ%gMÍKÁp\N¥ú_ãÝ„¦ô²ƒZ§>mwnùŸXn½ÿJ¬º<ü¿›XvÄ…Øë .Ž —Q¤]˜•Gè•0ÀZ¿p(Ö8×9¹uý+‡òòÄÿnÙ â—k­\~¨¼¼ê£Vûí>ªŒ™ØG¹¯¨üŠ‹Óó»ée\è½¼·@¤kÐVî%D‚ÉlºØDz31ù›…kR _±i8øƒ˜rÏ„UxÙ±Hˆ-ƾ¡,ïµÀ%âIÚïOç:Ë¿'*R—Çqw;*»ZqTªÖÿptøa¬MSO¨ä¦¼úýMÃ-*_›†¨Ê?¥iÖ&ž.ÛH› Ä­ã^ˆè¸SGèv}ú6Ûé÷Y‹†;Ä0áRì â_ûͲià‚õgWÚ)9=|×ñ¹uÒ+yD'}yìØ y;ÙøŠNÁÒÄ E«s+Ä]‰»ßO·ðx%Ž#Ž{!Ž`¿,#ì7å]pg é-ÛÍÁ<½‘[›¼’J´É‡‘ÊŽ½z­ßíþw‡dÎ|Nð,–yn9nNä'¯DVqò›Ñ@iµ&ýZ¢ /!²ÔŽ;^`Æ.mC…±W·g¿ìΨ×-_£Ûvq¥Å|¾¦–ßÂ.8¦®‘]òœC¸ÎsÎi Ìj’dëÆÁñ#»¶v%hk$émy¹Ô¸µ‡³®3¿Ñd}õmýð˜ÖT4àä9a¬’ïL>9Üã¹…¯+ùDûšlÛ×¼híöÖ“77ê”,BæÌ¶@lÔ›Òíõ\„&Æ+œÑ Mж;×½ÜÏ!·„tå¨H³qÈnKæ˜ò SýŒ5†® ¾M=UFÝ%*«ßáÕ €ÕÅ4)›5†ÇõRn­æÊð•\óx‚ÙMÉo eçq؆èðŒÐÐ:1ò¸e+yD ™=v[2{;*Ôý4º"$dœ‚÷u¯CýÝZ>SQóÚ ñ•Ð7–.sqËôq+>W§$ŠÏlNÉnKvÊñêuJnÄÕ) ä’6!ôfÚ„QV¡N¹æ}ã†DnÝçê}D÷™ÍûØmÉÞ·£Àý±ÞǸzß•êvª¢ø3øœVÉ$ï`ÅDvf×F½q “ìêÕÅï¨zuïwuq[3F£¼ÚÆÀõC·®è2d`,Úu:¾­ vYèÚTDš4Ù\ƨ½3sN ˜Ÿ’ì1}Ý¥òXËšYÈ®]I#úЗZ½#¿lCíûÅ•»ÖØ,¢ÍmTð¸{Mz»L–‡öêC—g Çmï´SW¥màØºfŠ®ô6¡è}vÛ†vÙ–ÕÁ>i*2Þº9ávogÑýË}<öÝjßÄáéì2Ò•c"#ÍM2»I…dbÒ›~?ŽèÄ”Ù×”}ó©×ª+:ÇuYnUæJ'‘enbG;Ë-ÚoIó{ì™)ºÒ%»†ZКúýÎEß0v„9mŒ7>»!™Zÿø«I­GíëNoÃ`±q“ÙýžÅ-#]=‹ÈH“Zh ­¥CߞݽVsÌð7f¨}úÚžpnˆ}|[‹%#…¡‹%Ýl[þènc.FU ŒßŒì`Ô ýqÆìZlûN6‚±k5WkZÍþÅnEñ¯fÅtÞ¶`çu¿ª6þj·”ºUŠÍ"ž>náVE®üUd‚ÙÍ(3ž^<¿]Ý !ß>Ñã:2·„r%šH(sÍnF!š˜qÿj4øº½bv܆)»pre–'s0ËnFa–˜Ñ%;~w<¹ˆËK“j·c_äÖL®ŒušÉãc7£0F̸`ìæ®s,WN°C÷')ÔbÔSJs”­ò9´ä1†ýHv%çêk’óx_c7£ø1ã^_c‡Z|@ÝZ,è¨],ø5_L²«M_ëÔ¦œßŽìlwz?ÖìmÖÛy ð)‡y –}€ãÖÄ.>×4±ŽÝ†ìo͆ug{¯U‰o=B6’p+aR;%l^ÙÍȼvfÜKí­ÇŠNˆ¸m²Rž/×7S0‡cev ’È-Œ«ÕŸSÈÜi{3ø$»Ù';3¶”èÖªö›Ò ÆÊ(ÆÓt7†·Â÷RÅK$¾¨e7#SÛ™±'1à|À† öÆåÉrë~/y²D÷›>~;2„¿5ÈW»É$Y;«;ëå–c…YD|9•`<’`¶ žH\¨&‰)dL&URø›o1©Æ[ŒåÉÕÉ´/þõJïÜendstream endobj 1278 0 obj 6776 endobj 1429 0 obj <> stream xœ½\MoÜ6íYèÐQ:,M‡_W·Aë’Â@Q=4±ë'±‘äßw¨¥Y[Z7±†6+Û’8ïq>HJïZ­L«ó¿ñûÕusò‹±¶½úÐèöú\5ï3œÒŽ_¯®ÛÓóá´H¿RI'ÓžÿÕìo`ZVùØúˆÊ@{~ÝüÞ™Þu>®wœÿÔì]>eIAÔtõôm¿sŠþâLwÛ[£¡ûÐïŒr.š˜/|vÞ¼hÞµ–Û¡Šm²@wi½sV阜ž5'g?··ïï.›“_[Óœü˜ÿ;}þ}}ß~Ó<;k_|)®äfc½£Vqìc¿³*D£m÷¾'k¬õ»zP![p€é.{$l`†3Ø/ŽÃü0“u&à€®û(ïƒÇBHðÐ]Ñ h£J±óD®/äzº=õÓŽð8—â6ì¢ ÔýØE“ÛcWGa—Á˜ÙýÔï´€Ü÷·D±¡t†§¦YbÐk؆Aˆ†.ªÀ @ŽAi…AcÁbýß{j0¹îbèµkÒ5à :F Ýj0l(´x9†¥q†Œ+"‡ùÞ›™Å‡ÜæC:×&„G¹ÝlôjÂákp«©9j¥ajgëÌÞÌtþypÒ: çSŽò0”èax–ñ†à*yCÂ#é ¥qá1Ož¸Í£ð˜Í }Ë«¶2:©1»F~ÙŽº"‘º&Ïè—ºYþH…F•ijHNÒ Š: †'KSÜàQšÅàƒ|°Dá©Ï—dy™g2-V¢M!U™±yM_nBDǨEã©r”·y/Gn3 Ìofù±®ÏÓ­Z3i Ò6¢­2ýaã°>!&=iEz Æ“¥'nó(=fóšM2DNžE=]СJ1B )+WŒˆã(rc0‘Ûº}DyÎeÅÉ›OiœÆó”—Kv4Êà`Ø<ïfŽÎ¨RXGG®ÇQ”Ç`l©=+3'óhˆ­™íÅgí6ó=¶Ò;0ÀоCGaœÁ˜í¼XÈ© w–ôá‡è!›ÛTz×5$ù® q…Ecñó€Ìû nòkK‚á¡xöÍ‹æ?ÓФendstream endobj 1430 0 obj 1714 endobj 1467 0 obj <> stream xœ½\Y“Gæy üæq†`[•u×#ÆDpØf ˆ¤ÝÕ®B×ÊÖZ¿žÌê®®¬îêîÃlB£õæ×•÷QÙó~/:Ø úßð÷՛ݓï@©ýí;±ÿþ¹Ý½ßAü•ýð×Õ›ý——ñ×<þ¨ "ÀþòÅ®€½“{ëurùf÷ÏÍÁá{4ÿ¾ü‘yÁɤµôHyy¿ýë#t!xß/ ÓZiÏ?~Ý4Nþ|”‡¯ŽºóÞh{xJÿÁîðã…R¡`\w¼°ÖwRºô«JÃp6pðˆá‘Vþ‚‘Ïyø-~”–þqøî¨d$ÿï;ÊN#ápI?t^‚ž>Ž=ä¯Ç ƒ¥ƒA2¥@/¤$š ð/½„~~RR){x†býàŒñN^/$ÂéàoðñÏo]”½èe 3øýåw—¿,ž÷'1oóÇà:ë9àå %©5 tèd¯QÎ9…?¾PlgÁ©´Ã‰äëËÝ·»÷{¥:mí‡Cñh¿· £!¡ùt÷äéŸö¾¸Ù=ùûvO~Oÿ÷å7¿Á¿ž~µÿÙîë§ûoOµkBÏéÀö¶ýý ”2‰Í {¸E•˜ :!9¿(¿N+”þ©Á 9SçÕQ9böpw”®3Z¨Ã‡£BÛ´Îî{|¢Ê¥ uyÇøgPn„Ÿ+7‹vë»Þr”¶Q- ÿi²ÄíÀ1tèM’ŸêíÅF—‡ìò§áwÝר(½vŒAVèÃ+ÂpÐIY“ÍÌ›n #Pi ‰ÞG½YŒ;ŸÉÿ`²òêOBÜ3¨|ª($¦}ãÚ¤8³kЪ÷QñmfÅ0†ëÑ[: âÉ(û0ÍSÎÃR“øiBai*{Åj…„ÒmBa Ù (Ò:Ì:¶÷÷zÄ(Lz¾j ©L*õ6-S³Æ# ±Ù^3- – lOÞ5z Ù±pšê:Šßrˆ›I*ç«J¤´ØeÛÏ@ï‡ãý!zÕçh¼*ųº„3È\MIF^‹u5eOì$ÃO/͈*&Oá#di5áõ:t*Æ%V¦„UýGp½Å&?"gP6PÂ\N3TŽpô5K“ËÁ“¾-PÖÛh™Èî¨62cz®‹ŒÓ>0H«ÉO­Ç"doÉNô¬9`½X5$ÞP„–‚ÊæTÅ8ly± ñX4ýªog%Øêâ­?âu%œ êÈQªèý²^Üö.ÂòærçðÞJ,Pý;7‰­—²ø×96•€ì8hµ@î|1Ö|ù_êD¾ÎÝ‘&¾XGºÊW­é$¾¨ã~Î[4Î ;ã'Ã…È™ ÊÖE —Jjhi/o§‡(ú ªÏͬ‚ÉXáö1G¦j¼…}A+là†’uÙÖ ’Á}–-S]'üÞ`¢~ ‹7è­abñá‹G¯XÀ§àåÂ8ÏÑ-š½â¥dÒ å cC²j2£~‡ÔVšTzµP³yÍu fcg[Þ%õH ð¥j¶‰³ØVŒ"–Üâ1Â…Æ¾ÔØm£èûéªQ°2@Y#“ŸË–QãmDËB뢘X}T±†’sœ"!¿M`75¡ršÕ·<-ÔóªÈʾãqi0¶<‚!°Û\{¶¤å0Ê>B ÁçtêIwY_Ïzõ¥¹R9Â\ !wãtíyBdpø/7 w9°C\çq-E!­ýúŒk™œf x¨Ôx7‘ßgr23š,+3e`=áÖÑ~ˆh*™½héW&h̉î#kj;FfÕd³§\jš4ór6ï§shÑßøÅf¢ ½.ºX¥¥º^·=˜“FƒÒh#qèÔRž@ËFß,ä4ÊrVþå%ÒLd™¸÷Xi'5V€Ø“ÚÕÔ–‰Ë™–µ‘˜™Éºùòzâ5ãFi³^×b½“â$™od Êp °ÆT¦Ï÷8kÁWS¢xœ* ¬âDr[ð­óDb°°}w²¨?“Åabä»&Dü,üv¡MAŸ‹$‹1£?ö Á´ƒlæXlØCËÙ€J5»SÔÌ.IÊk¡aöŠÜ²¢dT^kÆ¡+ÖÛ ¡k3 à¦XiºŒÆÐÀAòjt¬(‹q]¢šznfc¯9‹‘ĂôB}øÌÈ• 0œg[/(˜’ÅÆÁY‡ÒkAªŠ´DÝË¢W©†È“õ²^ ˜¤¹>kHC‰ !É!”w’Uu¿‘ž¥(ê‹ARO8­7é¨9V~¹¦Åz]RX5ÚÆ ý³9­pXMÏ¡ÇÔkZ‹Qmᮞ±«é¨ÍSækrŠTíƒê¤ê«W¤%$X#œ³QL‚@éÿ! O™½^XÂÙéãú]ë3F†T!gþs3úäù¤ÀQo˜?£.ë-Œ%´§±¼ï0B0º²ÐÔ Uü²¤z“]jr©¾R¡_:kSØÁXzL±öÕêhˤ ÞNG4­f´·¯XàŠ…‡r“ÀµTêobÔ”Nª×UëÔd ;%ëõOšfHÆN“&±¾ðÉ^LùA÷3løåå²íÎçtyLLfø"^@ ¢”ÌYs,„ðÝ嵿ĢJ̳#z°ÑÓ5*ݰü¤ ø<ê$¿Èç|GRh³F$›uUÂaÑ”ßá—›˜·d‚Uˆ…=°¦6k]F¯X1WH‰v—ž¶Á+ÔŸ™á= g*°nŽm4ïW·“.þbL¶Ö ‰3&]Ú]3Ÿ£ã±kí' –ñÅTsÃ3 húÊ2œyÕ³IÀléÌc`àKg3™‘Åe˜ `s9š8ˆw®vÑÞØrNšÿkíæË9<È|Q%€D>øîĦ8а!!®”içÓ†DÝ[‹R‡bŒoÖ}%“Ýðl›BÕ'TU%|˜Í»Ñ™¦–µº«#é0íUŽ=“kŒ¤/CÌ/lÇj¬.£3x»¼]<%/C#0U»va p™º¼ã½|3 i†ÂCx,3‡!ú¦48~àJ[d þõÆp“k ”­ñ¹ÜxoÃ.GFo†+ZšóÞi‘QÓ½±-#c˜DÆÚ”b>éL7”o¢a؉u-u¤‰±»°|Í8EYŠThó¢bM@“ã«¶ŽÓAì7„L‚&ÈøžFuÅ=ÃÐØMaMÀNA/jHcè Á¶€LWª‡€„ÑÛ¯»Ý0êipˆ"a±«`{ÑJp}ÄH(»’~Ë\KrØýEO’ž†Ïç÷$|•2Eg¯<‰qÖ¸&7ræL8ëÈ"qæLgä:gµñS|oÃÆº"îÓ®‰B4ýîêæH¾dS%„HoûÔ­x2§ 0^þ/9Va6«]LîQ,;%9±Dßf‰+BzH£år^N‚U´¸Ò#夑rÛ/dtAðïÏ-gðø˜RÌ‹MÅ{©.‹E¿{±9jb@×e¦öB:E×»%Òrt­ ÝðùxjFÜÔ šN—ø%D1µzuÑk+÷½R¬<ûÊA² ˜/Ž6ÆÊ\ú¤ùM¹®¶Ü…k —•rj¦ŒX›~ Ð-ÔF;› |â'M¿M¯[Ô8߯Ú-p}{öSNSŽbÀõ/Åž€”hl(ŽÝ…«Èg©M‘Âx~ ¡tr¡ ´Ç°°p?¾ó^äÐ!.:Xž¶h«âeÖù§-˜Ë­®N[/°«¶aÊf¯ #Bv¿#7fÛ TÇ•$µm¬Zv8Ô©ÀܦG:‹Ò¬ê—*[C÷äš]Ä¡sDZ“ðñê6å•M{½ÏäTxÑ;Ž:/ZlrS’7D™Xåaåy«¯Áš„é&E®ü A†1ù}|Ÿ:SĦÈR"%bsV½Ø&o¢<ÄÒ¸úVÓÏ"ÒŠú 6“g™bP_íeŠšþ¦/S̹LÎò)EsÍ%ÝäýH1¤¡Øµ©Žé«/²ÄauË/\¯`|Ìß„ó'52½ï³Ø6%|®ÒI^Gn¹QÜõëØ:LÜ·#›²(I‡+Æ'⋌Ê8ùƧŒÅDQ¯ÒOÉDŒË<é‹*ï_Ç)ߟÞ!¹Êyž—JÏ`$÷ýÅéÄè:QvŠ=«[Ù¨‚Üeûùiì 5ÊÏ)ùËz†¯`€¶‘ñà$eÆÞès´ß…¿È¯1ë©’áŒÄlbI¯eŒ? ˜ˆ_äÀný–ëqœ8ÅÒ%½óR …ØË±ê‰zÄvÙ®|5Í(ëòmiJ›4­‡Â"ãé6¦MEå;.­é°­,6¿¥CH,Z%È•U² yæ†XÐØÛ…ïM˜R/ÖVÒÈíÚŠ1”ߌa´.¿òeÙ/2£™}*¯u¥™®u7çA3%‡c’Ž<³q‘R÷¬÷0Îó¥°-¨éu("}މq|q¦ÑJ=ce­`üº T»XüºŒ õÛq vªuzûfCé†]¡÷u:Í:ôâ7²L¨« YH_±%ÈZÄ¢|ãÍøÕ![’d6\Ôì\1[»û/!ª¬Íendstream endobj 1468 0 obj 4025 endobj 1715 0 obj <> stream xœ”OÓ0Å9›/á£×3ckaE Q‰âÔ.[i©Ôî`¿=3iiRÑ.,ª\»Éó/ž÷&ÝÚÀFýìçÅÚL>‘½º5Ѿ–qe¶z‰ÝO‹µv½¬Ê¥ÐÆl÷Õì`3Ràj¹¦h»µùìÀgWvãK÷Ö4)e•4جQv/EôÜÇ@„Dìî}“ƒˆ2¸…O²Dwã›$ŽÉ-}ƒ Uâ’`q‡ 9·ÕvïL÷âïÚ71 "@qß<†R ¹[ánçþ¨:âŽùo Ù_ägxâÞ~Í¥¨1êú_ŽnºèÌÜl-I}.â¦%¦UÉ&Jn€¤=™Éì½½»¹¿4“OÌä~M?¼”iöÊ>33;j²<—£> stream xœ]PËJD1 Ý÷+ºL76é+]*Ž¢ cq5â¬f1øÿ`zg„"!ä$9ç¤ôä±#.utW[ŽÑ~\ð÷–wr¼Rü¥ìþ¦¯4µµÐØ÷ow6`_ÅMÄâûÑ}c†j©˜?ûãi˜eR ‰š²û™ZÓÔঔbÒnÎ0W'¸ÅDª9x m*¼ãc£Ày²#\JQ©Ôyò¨¥Í櫇š6³AÓÙ;áΠ”ÑÀ£–y¿C¡²0ô1¬*œþŸ›Ž¼á’ Jåñ3›î^-~ëMPøendstream endobj 1735 0 obj 230 endobj 1739 0 obj <> stream xœÝ[ëoÛÈÿnôîUD,—ËçEâ8¹~ÕV ܣɖÝH¶cÉvüßwg¹»3C#Ûqz@q8fµœ}Íüæ¹ôçA«Aÿ¹§Ë­¿)­óÕV2xkþŸo}ÞR–dàþ™.¯Æ–,¤I\i1Ÿn5¨A™òRÆË­ß£—CiVäÑÕp”Æiš”4µŠÓ<ÕÑÉÐtê©X©¤(£/fT™ÄZÑ+è-*]¦ÿÿÃo$‹ËªT°‘<3]WƒñîÖø¯¿G‡Ã´Œ«$)£ÉpdÎYeª*¢khgiUgë_Ú¹ë*ÏÍæL¯Î2C±6ç(«Ú¬Ýtê:×0….ulν6½yZÔYíÒº¨¢¿˜fV©"ƒãA3)òΔƪ¬K7ke‡}—†Ð¬S×tÈÊn*Këæ¼Zi#‹¸Nêæ¼u¬Š$õç5§ÑÀNÝ‡Ö <f–܈b4åi“‚Ìcm:T×µmj³ ˆ•Gcø}÷ðØqo’*ú#2¦¥Tô3ì¾®ÍI":ÿÚ¤6³dp<×{j:ð“ÄrÝu^àø{;Ȳ¶yw‚ïÖ¡ó;¯¥YNB笙ï6tLj!͇CWnÿ p\ç5£ô\»‘61“ÎpŠÍslºQ™®(ílâÖEW™Ñ¬ñÌ(Ô‹á(«KCPSÊ6WlªFXeô ^bsi±w'4aù‘[¤tœç U° ‹±ëð˜8´¥‰a†ƒ—@Òpʸ²|»„7ÁêÒ³+f¶)•ªk-ƒªœ`"h‚ø|*<Ì1q¾ 5™ ßI ”–ò’"ËkÆ7Ô¡µ°H¨m¬’ŸìxË<"£“` ¦Nïq‡Î6Ìœ´»£³ð¹ÿ©?h¢R,A&••ðJ:…(Ü‹Ð9g€4§¤Öýc8ÛE8ïÝ£JtéÏ»¦'ðÊ‹ƒ¯<üÂ=P×å)ÒÚ¦ *É{ñ,’@IçÜëwFXu%áo*Ít*uâ˜ë6')^“ëÀ ûó ÷-ººäû5²—Í£[VËí+FS;g¢©=¥úÖ‰Ñ|×ÃtÄ—7Èó{³ ¥ÙÒìS„üR’3Êd)Í)Ân…dBÕÈú þ¤Þ]`ÖD܉y0ëôÊ h/DZ2Ã܉˜Ð(N«Æ‰XÈÁæ^~…ÇØÅîxàç;xìÁã-à/Ï ÌPy™›i£ª"‰An$m[IlœK”íˆÁòv*aQŒ ØAC Út ;ÿCB5£ìY…&iaO˜d6ŠRúrÞG¨1æ%Aú™@r¶`3Ùd­¥•æR'Úù.¿v«öG6ƒÁ±JÚô»° ­Ë¥4hŽaÖŸÁáðÌÏù.îa§!ʪº>æ€wš#Íþ,>:Åc;ñ”#É ³¨ÈûG‰A°c×hè@Ä$Þ‡‘ë/ªÙ`°ð —KÑ»nÃ+2nBOÞo‡^‡ÚîÇÍNgË"Ö©îÞ $ËĽÏ$“B,t_ÕA?D̘ª®[Ùˆe<Í6wÛ±ÑÚ,<P\@bÓùñ°ßü‰iï|ÐÞ“Dë—Ðy€ÌQøÎ¡³WݖŤz†\yOåïß„Î}6)Z`Ñš¸Ö[ Ÿ&bÑqÝ⣳^Š‘ÍmÙh³Jm&8è\œuÂðæi9àX¢ÛLÏc”Ó€ÒN‡>«=²Ô¡eQ5Ç P¬ &'˜K”‚Æ·{MœiÉx×µï"ÈãÆÀÿè Ý»ƒH¾´©´B6ý™å–‚ðoEá/–LÆØfѕ鸨<ºˆM½lÁ¤¡ãèˆéMHî±¢¦@ãIâ÷qàÜ5¿ˆÐßü†”é1#ä§GŸAœàiX˜ ÜÉi=‚Ü#î$éR†¨EsPuBÐu#.»ê…O–y+ê`®ê -„:*ááPå§@£äƤH1÷ì:K©³ÂN ¢Åà« P¬ »±Ìõð²Åš¢Èµn¥1 &D²g\á9—–<“r™F»kF*8°©ˆR¿½AÀµMWãÖªXO|V_ë•÷E\຅²fNn¤Þ„8ÏLÇX¸±%W¼å…¼s ÖïÄ´‘Øøçt~^æÏ–já>Z±f¡[±ÀÔ›öÆÒC[¤Ê—Ű0"ϰj£¨Îv£›h]ý¬žP,-¤óú‚ñSëÍn·כE_ 7!9±- :ª:élÊœËfÄ—iE×Í¡ˆ &–™QÇïW:®*E*f~aÆ’ñEÐjQ{jc­œräwЇ6¦˜:íia{{è2Ѧî„6ü„ÐÞò­” ­Ó¶ÌD®êr¹¾z- p"éò ã´è°Qm¿VWXKܸZ7T÷ؤÍw ^ÍD !й÷Ø0gðMÝ@áA×uÐÛH@®ëŽ‘ïèÀ ûæþ&Ú}\0à»Éým‚ã:0í |—ÞŽ5Å~¹dš‹iIÐàÍùUKû–Å9ï$ñ m#êz%IwJãZ?`{I·(F+Ý%/Pâ’×R'BO¼æ–.nÀKùdKO ®®ß1.¢MòI€éƪ7ÊõÑwoÀÏо¨SXŸ[?[±: ± @¬¥Ûc/šŸö6áÈ1Gõ|^@*!Xô8Ä÷˜Â’¢ÇvèÜë¡ì¾Æ¼‡¤8Hù;ÑVïnŠD¸Ö]:õÀ^›SßÐ}ëþvÚ!^¢®ˆn7š‰2ˆ€»é¯!wô`mÀ5E“,ZtOR§ÜôúÊ©Ädÿm½mѱkoMYÑúºEr,B”«ÀçÒù™ïóã¿QdPïÕ‰>ÿœ‡`R`Ðwºz? ^bAæÃÄo<ë³]²‹qÑfŸá;Âp¹ ÆM3<»˜ ˆŸ‰UÏPøªá”P¿Ö”²Mç‡Ö .µãJ›Âd´­Äš»Í.mãK óvÞÛ(ŒÊ6*±nräôð2¨·7¶nôúêð) ±_îÝQñj’âç8ä/éÆÅ ›ˆÉgmóŸKƒxf‚#EjK©ä8zS=‹ö¥zXéñˆGËνîN1û>—êÍí¼B`Üþ\I^3é(|¾$@æ*ào)|ªyˆ™÷ì” D.—ä‰Z’¬SÎyõÁYœ @¼’$u"Qöá´;Ü߿▩ë TÞAÁi:<  ¡‰·/×ãÅa7Ö$œKlÓRV9G†ûtD4ó¼Ä¨3x‘GJðx‘G¢_ŒOI ™ÜbâÝ$I:1:ÞÙ<“ÿ¶ ¯>·…«½Ô3R“’˜ziÉÕê1ÛŠoJ{i»#Ë^Æ•]Æ5¿ØÁ†:WŠBðÎ̺R›CûlOÀpO/¬Ð‰wûÂeÑhú-0ÕèÆ3ÿÙ`c¤‚»ÞÝ,DœËˆIµ‹¿}æ'œDëOnÑ1]ÞïÂÛ€½dPk!5…/Ùðsì¦ÈÑ}î3íðˆ9d‹²¨Eú:vÓ|Íc¿Ô8æÇl¢Kc³_[â;b4äž=®³âQßILãyQOÔs°ö¿*‰>áyæïÿ²˜#zDo\û>[ñ@dœÎ'£+8TOªä´­]o!ÇB{;¼ýàŽÄ/ð3µ‡WkÐÝ‘*ê!¥t­MÕ⮾ÃêüÏ0\ç._ýÑgß{Âê¯Å&úÇ6.o£òXäð´, È!´ÄZ~u[0¬e8Ýú,î ˆ; ÆóЛÚ`A-ÿUN¼"IžTI|°|ÿpö1»Fþ®¢¦ŠÔþÉŽI­1×PÃÜ$jyTs´3Þú§ùï¿°%²ðendstream endobj 1740 0 obj 2901 endobj 1744 0 obj <> stream xœÕ\YsI~÷¯pì ê Ôô­n&æ°™ñÖØ3Bòè0:|̯߮+®lµfc!g×™ùåYÕþº…ñ~¤þÚÿGÓ½g'qšî_.÷¢ý_ê—{_÷bÝdßþ7šî¿<ÕÍÊšVQïŸ^ì™âýA²_”Y'û§Ó½ß{q÷Êú_äÿ9ýMu+#Ú-I³°Ìêž§ãºõ‹ «ªÌªÞû ‡Y–f%ýzh¾æƒ¤÷6HzAݹ̳¢w¤”U zƒ~šVaç½—õó4Mвý¢(Ã$IêáÊ"̳2'³ý¨î ¢¢¦&½ã ‹"Né„§õ¸á`0(–šG‰ê˜¦j7™]Ì ¨Èã×ëb˜¦±^¹ù±þ“ÚqË$Îh£wŠšÄe\êö‚~^¯c—†‹iœR.ö-ûõZqUnŽê1z õq®>†êc?þ©>t“¹ú˜¨~ÐϪ²ææhÚ»¨§M"ÍKµL½ÝÞ™ú8Të‹¢8î=­ÛDeÍH;ø•›Á<žÙ!jÉ\Sb¢X_½%Ï‘¸âJ^éîC=’êëw¸«ŸÅ•^ÄžÏñùˆk$NÙ"í,l‘y×ß ½1C¼Âîç8'>âóÏ@œ°N”ojΜ.t(§y&N)ì”YZ6XD6ï¾^cÛ%›Ô~Uƒ÷“*©GïÇi˜Qb&Ѹp îD×?Y5«rÀEîØ›¼gK³Ä%Ý®#^#%|©y´«H1tD½û"5[Ï«’¨É¶‰ 3³Ž£t TC¡ïú[ÔB±ÃnÕÀV+|®FÒQ6 W3Æ]­šµœ~…çøü gº“,žàšÖç¨ ¢„n¤1q¡c†J@㛽Óþ®R‹5;õ¥–G^äNwðtÉÕÑ¥?¢ÙQ®eïñáºB v»ÙX‘m^HDäÒŽîO9gÊ u­Êˆ©\KcŽ$&]ÃîÒ@kû£¸÷GüŒ b þ æ’IRõôl2\¡TôTj§P}õ³šJÏ’*å­õ¯¨åúŠ“®)O}à. LþÚ,¸9îçšrÉ,ª[Oàù |~*?ñ ‰Ç¨§_¤…>PkìˆsÉ Œq¤k&y³†ð97ÚXUJisÞáWVǵ frÁÛHÚ½3<å&7U´Ä†')±?Î!9×­Qó¤a \„ã{ˆ /çRË6ãêôeÔ_1¿‚b"„§Æß]‚!X˜g]PKúÀâg̺ÍÑæ6›ŒŽrÌ¥6´4û±`Ì4Â^:°Ö \;÷h÷‚¢~örÎÞ´MõQE¾A—EañùNƒ¶¹_ŒKÚ¼ä?.àÇ>âïÿ–×8qƒèÜBé,#Ûm¦¤µUËRåàÚ£ýMYpé5ÕjlµdIé4Þsq¦”䯰{û=®$aßPa÷N˜½e:t+-DŒ×QÙ´ŸOråç_q"u'6ñ.ðI|à-CÊ9¨µŸn¹}”í#ûÂ眜2Ob×ö©Gøõ-~ýÛ>íNØtâñF}¨Rêl9¡÷Wêã4yŠÈÑý^ªOÐ…¬½‘×ÝÆH†lí%?I1Ï!Ÿ¢@Ä‘Ð8¾C≴:q¤3ÆyKü‰ï€x"-Ô쓸tÚQ›"B=óÄ«ùÖƒŒ`RB}C—¬a™Öb/.}¤´uæªónìì`¶­†_ÀÝk>rM1 ¥dج£cƒRðx =¾úŒw+‰d^IB=Fâ{ Šc~ô°gÄÛÈîg'žû¥4Ñ+ ÆÇ@ì^Uy/{j¸ôì+ëòið¥åsùà,) cæ4ípXðklG.»k1ýe%G|ŽÚûD2Ÿ6ûW¥Ç’ÌPÄi]ñ9|›J)Às)þ!1<Ô˜HY£þªÕ8¨rx„r4 Ÿ0ÅËò´þ¡ ÔOÞW¥Å>U}åÌqmÅcñë“v÷Sèz¾P0\`Þ®ó.ŒAŸQv8ˆ=À`  ðªuœAÌ4‚áÌîBeeØÙ8Š@ªg<ˆ•Ñ®´[ÌØj‰)y¥„‡‹^‘ ?T<²»% õ×ÐŒ•â܆!§eJ>“§®ˆs&9uÅÐDdh9Û*On5/Î1bëˆciu¨pbÊN–üÀÒÔG–f‹¹––Â_¶‰‹šÿÕ9O…‰SŠç+DSÛUÝ:˜oäóÖÇ %öŠïHÚ5+¢ûÎìÅ©4&Û˘ý÷a"v9°VzS$±CsþL¢´?6:àKGNR¶ÌÅ -n†R8# âSäÕL‰UxQRοî´s*éæ%ï¤פ‰C­}Õc’£}6^¬Lò¤IPB’´@oÂõ“:;¦PDÌ$'̈‡•âÙŠŒvðÇ ç»vÔV3 @rã·¡MÌÇ03(bš]ࡺ·á‹'w@ƒE¿­·Ð,/ LúâKÇõ¨!NùÒælD.Q‹a6ùÆòÜŽñ¼ïÖ¯`œdÉÁÙÁC‘Ëü Ñuš`§Ï±öïÄ4¦7Pd&íC©@äWæ’¨J™¥áç…6‡+z:Ìj†]]Ú÷x§=$:%Ä+‰'Ó4 #9)IšŒÄ£¶–VjH|ÍZúõó"‘,ï#ëå„Ú¤«8,ʨi^ÉýÌuÏÔIؽ²z7®òqò_½ñV9±¡aªZ§­'Æžíp#y#bêÒ| ú[4G|íxáÜ­Yh[ø)2ÀUrÐÚK(Ƭ¤Ü#‰–’ OG܆>ÊИCœÑuxO±î6ÄÊ×>‡C®tvCÿ€çJiýœ‘ôJ€˜úCÇfŸgR)"Gb“¢&áR´¥”• î™?cK XZxj4æºno‰aŠäN¦hw &µlÄij`‡˜x֢ܾöÎ$Û0Á0ÒS|Ñ‚|A9“\bƒ(n÷\I£cµÄQÅTý¾ÕP*ìKÄ"â½ý‘”_Šßiˆ!TÇ=(83»ã‹[ ˹+ >Çš…dvøÝšjmkÕÌ@mf2’s±LÕŸÚÔ‡YYQtÊq𴤑Mv#­oW+X{pÀ# 6hùWè\ —ƒÈ j5/âítÔ¼}íz‰FWÔ@œž³ÛEZâ•ÈŽ„ƒ0&ü‰šl¯hª ÿxî‡ça‡¨¹„«pÕrœs5ëºHÊÇb¤² -Q/]<%Ú:"³u (s[eÏ¿e„؃ZIýVÂ}´y¸´ä„÷ZóME½¥3ùŽ˜q;DPLÀãÚÚ+{Cï¡Ã¸Í|WLGˆ/Âà Õç~ô§ÁÂÞ‘£æa)þÍŒ‚%ž˜ù¿ß4¸Ø°QGöŒ„èQÚêÊä*nGF$º!"`·¼6p;¡rtóLBÙ¼U ÷‡'@ÊaNž¦œP•r·N‚3°ðô0“å¸}žÆºcqÄ?y¾‘Pr-A¯­Üê’@r—ÙUw_;‚»f 3GXµ FJ š‰œ 5Ì Lu#fÛ£c6ÃŽ„Ñ/-F›Hô‡v˜%!è€ÄטÉÅH¼ó‡ßÈ"wŸÕ1P͵-¹’FZI |.ÄVçå¬$ !‡2~DÒ`)&" !#X¸á~c…~ƒOà…Ö&a%ÉM̧vÍSÏÀø,\@ ¦ÙåŸà²WŸ„×£0M%¼µo’5qBòßûü†s&±ÊO~A—FñÊ;•» ĺ_Êò«0¤zÛµ<{µ¤õºêFÁ\ÓvÊUgâÂáÏŠ:®­ªXÚ¼.@è#h~€[#œåo]»^âYóRê$:*®îø.„È—’`±åZ2{]gæìý-ײíWK¸—~1n2«Â bmòòË{ôK$Ú8`+q•.¾>â]ýšT̽ñ²Póóì{›0™¼¡H$:]J<ÙIŒmW˜ªÈ¼×PÒdÑ7’« þð6°°Q ËÆšqŽ’%W%!ha[ù¾ ‹õÜKL9¼ý@’¸ƒ%­rÕŽWÞ[Ï979Ó†Wúy>U‚%wwÆ`‹îdÜbz3¢óŠÙ—ƒ‡lÎ.餳7†9rŽâ›@rí‹Mäe<¼2FLÃd¶ÃczÒ°Êí$Nv¾Þ6Ó]¸±h•?ÜKÐî¬ñ>íöá€7Ì®…“zêïõõ]κãzï7˜’ßw»~üåPʬ3™ö5‹æ~é$öwä a4û–Îæ7æáWZ°èW¼_;‘TçN’ýv…€«_Ñg}÷‡¶,bç¿­GpüÔl3¼ °7{j«i&„—ïÜš/ -ö¦¢ÃÏhûM«$¢ÆK€çL¾ql}ÑÉ Íùi5‰6¯ÞIOóäÚœ¦<Êи€åæ§‚~YC5?<ÝûWý÷¿ Ø endstream endobj 1745 0 obj 3802 endobj 1749 0 obj <> stream xœí\[sÚH~÷¯à-0e„¸ˆ¤ü‹“É®3“µÚMe¦R6`ÇÀ°æ×¯úrnÝG°³Im¥RÁ¢ÕjµÎùÎýˆ/•f#©4Í?ÿw0Ùûõ8IÓÊåb¯Yy•ÿ¿Üû²—Ø)ÿg0©<;µÓ²|¨Ñoö“ÊéÅž[ ©tZi£›UºY»‘´*§“½Õ¤Ö©fùÿüï_§ÿÈ/M“”_ZO³Ì\SO›^ÒïWN‡ùU/kõ´úÚ|œš“Z½Ój6šÍ¬zf¾ÏñÃ|ÍÇ“¤º2_µzÒluý¾½ÐùT«·ò‘,ëVGùBI?ÿ¯œÓù9žÑàÊ_”õª<Cç8¸Ìg6ûfÒ®žã ¹gšäÇÝê5^ø'ÊgŽùLXsŠƒ—4¸ädoÔìUÇÁ§4ó?8øš ›Yþ¥ÍŸnJ‡CxÐ>§›{ëÛifŸÊ²¤£ÁÜ1ͽ `dsÏÐÉ 6Òn·ÑÍqdÀ®ÐJ´-sAÝ]QOÒF§Ûl¹ ‘Ì<ÇaË ó}f>®ÌÇWN÷Ô²¡úÁ|4ñÄ_µz»ßË Ò±—¸Á±Ž§4¸,žŠ1•ß#^b×gk_Ó ·B€LhpßÃ"¿ËžŸÑyzȯ*Çtø8Ån ©ÈÙo á£SKG„4œ7ïô³ÊéÑÞé/HX:2Ù³O-sc-D€KÀ-h×Ri7âZ€A×6$r»i[çÒ+·V·•TëŽï3¿cÝ)¿Wêð;‡­t£ç;s‹<âÚ'æîRðfÝLUc=2\Ḭ̂Tˆ±j½ÑèÃfÞpÍÌé4ëP»;Ýr Ý’!윒ôÂéKzŒ2A~I£ '§$'N­õZVôš$¨¢,ÙC˜ñ ÕüˆÂÿ@âæ‚ŸHÙ]! ¦8e rÚsxCSKÆÍk|ÕŽ•‘ë³Æ·ÞÑà57N^Ôn5 :Öð…Bih4Å%ÒÂ>ü R ß}Òév€pS¥ŸVÀŒýGëÿ©qÇå¿"ƒEøÂžgHcK¦¿k2ñ@Kžôéú°Þ©zþç+ o€ ;%ù>i'¹bžÉ>ÅDjÏü„¾’¾F¯¤á.š¬e6 'ÌÊ™D•Ë…½§¬ëù¹ªª#wm¢ÉKè¹9y¹§ÎeâÖ£©¬b£z†""³©ÔÔöÅ ,{’›¸nƺ3öêâé.ÉBTÅÙ?£ËâÅ­™g»WÅ:SÑ'h'ŠÏ‚xß!€dÁ¬x6©EªUMË{°tÁù¹|bé@‚D²¢T ϧš[‚HúßÀ%iKÍFy>ª:ŒU³APõˆ}«ÁpLÙš²¼ŸZù݉zT®vxŠ4öÉè¿ÄÁןNhæPÛ§Z›ò}À‡©ÀrÌ:ÆP©\‡®k†8M–OÌÆÍtk•üœ?LÜvÁZ=T}C3™ÛúI#eTìz8í®Ú^•u‘I Øq<ÙUæ;Ð3˜æX,%¢u¡fhã[•ÿað ‘`§¶[Ê™òÞшñ$.²'ÐÒ UXpvRLó¸a‰ÇVª± ýå²kä·.q8¯†8¤q˜á¤ …v Ë‰'È©íq?|”~ôÞô7¨ò×(®¸;síg3/që‡iæz8ògd»nþ sjƒ^`´£÷i&Wó½‹"J•v±+CbÃNvÓ›--ÃÕkþ…ðâÍ¿Ôô<Á#È[qJÅJW¼}4À‘:H¹SFÊòZ£ ¬PV [â³E)¯±åê[»pŒyß(Ž…‰$L†À±ÆØ$·N5ôñŽÕ…†sÙÕ¸¦Õ»Èìbv‹™]ñB„AÈÅ­(Æ[IúJmLÖû\Y¹C}3ñá[öÓõ]‡¨¥jÙ\®â³ W”R›K²€ l¬|·h´y8cUîHƒÐ1v¾‘x{þ‰7¨Ê¢¨Ý>– ¾G®Ëm@&»|Q—ÐW”lÂ+!ìü’\=€Ødÿo¢û¹¶’šÐ¥™²JxÝîM¤u½Ø‘Q Ö×´•¢Îª.bJl¯)6dM%õgáSøOö)ÕƒõJy¬ ª‰¥'晓vþ9UšœÏJ¶<å[ã%UD.ø*LfÚÆEÎ0.2¹"ųÕn6za€b{H™3í±ŠÆ=¡L@K#• Q!›q¶”½Ç]†pj…`þò‹‡4$+9&2pMIŹ{âÞ$“öPOŠbOótèeQ4£nyh0L ZÞãrMrïjÏwêDUÞd% E&h©º†;5ý8Á79ZØÂÛD#G2«µ™MIJº[_ ÝUë«Q-Î P&ë”$|,g@ïnÈ€J»X.GcGÒIõîÌV5ˆŸÕܬü!ŽuªPxÛjs&\~§1[M¾éÌœlƒ¼¶zo«gÉ Èù­…H:v¢Ô?D…kÕTüü•mDEÑ+Ì3ûù#*=ÅüGTþO~9e"Í4òw¬þ³½3&,±oÂx8c÷> stream xœå\[“ÓF~Ÿ_1o±’±¢‹%ËKñ°¤€Rd7[”Çž[á¶g†É¯ßn©ÏM}dy<†M6P¹¥¾ë×çùÓaƇ‘ýëþM¾§éáùê :|fþ|:ˆËGÝ£éá£ãò±Â4…ƒhŸTćýä0/zaœOþ݉ƒ¬S˜Iýçø'Û­ˆx·$í…EÏô<›§âp0(zƒÎë ‡½^Ú+øå“ê2ë'WAÒù10‹¬—wžÛÅ Žú÷A7MagGæ~š&yÑ ƒnža’$f¸"³^‘±ÙÞÝÈtúQnZ“ÎË ó`·ŸÐÅ-0MãråÕWó'uãIÜãýl[“¸ˆ‹òù·A73ëèÇEEÅ4N9»ŽŒ]³–~<TÔœš1:§ö£¼ZÙKûñ‡»Gi¿Ó5C'‘r×´†QTtæöû™ûn¨º¶ß/à¡x`hXÍ`žŽcÛ˜X²9kœSãoM÷ÈpÊ0í'ôäGÔøÑv*Ì—^g¨ušhsްqHk¾dw5º½A?é8kX<옺_Ð}F‘§xÿ9Ý?ÆÆ·@ྠî_ŠØË^Z˜Q-×ã4ÌòÈèÕ‹ƒãowí"; ûQrÅ,/‰ÌÜŽ§gÈÓ5@59ݘ Œ| [ïWÎᙪˬpœ2–/¦ûšS®’š’Y™Õ³ºs¼¿Ô˜}E ld„™aã¹]rQ éZã°*UÀ"³Ð¡=hÉ ´ÿÄÆéÉwtâ¥eòì© Œã<;w|t\á äÙÌbÖQ1Ö*B¹Ùú>¢¨û\r2*æ|fŸõ—ëfDœ…Æ¥Ö¨®NSÎ¥ mÅùØØëm­À6јäöšZ‡ª^•z˜fY˜€Çb#­`óYmËŒ¸0Ò?„ht“Ab†ì¢†Û‘­°¾¯ò¸ø—ö«uPãKl|CÏø“´T¸M£ÿ*ØX5–TÈÓŠÙ `ŒDþ -™õ]YžÎ(ÏUSÁà ”7Ò ^piN¹ôÒ&?4î’Œ÷ïl}§‘í15þv±nÉ.É ïäD0´(sÜ:l‹[”š4ö(©w·²lʈ0û…ºüw«»Žñ~²Ý®—è¿>âÕ­svv7Ý,p«„Ðà‘eiŒ.…pŽë"PìiÕ¸É]8O¬‚ gÂ= AŽwE²F–’r‡·Ú“*ò•0Äÿ¨mêo43¿öƒÖ)™4CëDoŽ"÷Aú¹dzҪÇ9ðô~ >޼÷ÅuºÔp£•xu­qu¢é¿Š"U¬tNŽJ…E¤2Ì”¾ÃÆ'ÂOãØK­q|A"qNQÅ/€ûk_ ÖHx±`@%MF¾UÁ§:kÛ=Ã#7$±SÁŽ,‰z„hïFB#a$Y&ñ¾M—ÃűôIhÅ»—¢7SŒ g`zœŽ-ѱ@™ ô¤nx (H\>£¸¬¤«Øþx*liåªC÷x3%O5áaô¹äÂQƒ•†¼BÌ@ öpsù”mD­h"•£YÒ— ¥w6lcñÞ4eÂZú¥ÈëlíŽäÝ@Ó2p,HZ0j ^4V k¼Çîß õ%|©~M‡ Úúç/O<:û‰øF$_’¿i< ËÏ„_u,¤••Þ†ŽT’¥YΛ9a†þßjBú%¹ð/ -ÐUâÄÿ;M(#.åac¤^IìlæåØž¤¯(ˆ¥£‘F$u¿*Zj‰¾¬Z@íR[²8(ùf‹¿Ñæ$Y ¶+|DBçÚýñEŽýw &+(•@VË–²°û›¡”ú¡vT›(«æäðù°ÒÇs²ñ[Üsû&ù£M-¾Ïs6üXÅqÚ” åŸ ëoÑ/ƒžN¤MŽP% QV9U?Yék¢LÒ@Çkü:’â<ÓDúK¹F±œH:³èÑ÷9"°Ð¶X&dÊÉês­Q™Æ\k¤gÚ§2i¡5ù˜_4Âßæ(YòÙ10É“øÞ–\FO6yØE´©ÏoÔ°Rû‘ ’“MQÆ%?>=ÕzK¶ì!…h"¼oƒ¯2åtIô¯P¥Æ{ò·2ª[õ¹SLRZ5š_K‡ø±jܲ¬™–Ü0«¸¤4iT Ñ”·„F`i/-„¹ô#è{‰Xì……;é zHü¤OõB"K ¸iÊ8ýEl’£ýŠ6Ióѵ"•ü °Å¯_íJW™T÷¸ß^f ó4Û”lJ½o¯ª+Rzf^Ñ”ý~Oϱñ-5&4Ôµ¶vТ˜è„ÏÂ’ä³öb7ly…­¬HY>„Ô³’š÷0Iñ‹ßQÎwU"‘^©@j¢Y­Ÿë’ƶ6Òø³T/e<Ø F¦Ϲ°•©‰" ‹"†Ü„Ì|0SPÀ&$fBÅ»0’’†˜Åç( 'K@æNœ.AJ\–¶ìð eL$ÝDwNº!“EUÓ…¦,G1Û̾¶¤WËÙU;Üö™ÐµÂxù¹«–l²ò˜ i—´k DL„aA#\ª2<®‰U5¿,!©¢xè):Y·—P…w;뤂Ǚ&~ªÞU¯´H ›½EØ ùN›®6à™½ÆV+8l`)OiÆ9œ‰«ïÓ-Ö¥f{ÐÐ ’Z ’~ØŠÄÕÓ©n…Š!ó+öâûä°žtí„þî„_¸KÕV]ËcÕ•zãG Yfâæ(L)#LQ‚Ê ŠXtIü ~ÐÊ—øõ¶fÈv¬%ñH•³ª&ï €ë2 S΀ÅCZ6UõPõl6K0©ÊKzºÔtŸ¡ôﮞpÛ4ÚÕ Ž5Ò˸¬ÛÆýã²€LÅÉ %Ð8\‰5×D­&B/«ž©Ï*.ÆÎÚÅP*< ”ˆ nv`ïä_ÔäAÙµ 3jîc‘¶<Ábk¹¬!µ…Ó]S¸ÄŸRÕÎø“îŠÛ«'°ÏÚèeí /Ê8ƒ”a«ê.eô–Ä Y?Õzb,Mµz’–ñíMá¯ÈT0 M¶›h ìYºÎê©åœ' VvÎ}L ÎÀÏ °cŒt„ Çú˜í‚Y =IÝ÷nZ’b»æ$ò ´%” 3È¢E*՜ОM>æ”ðåöÞˆoÕC†Ÿ,ôå>àôþõò86z,i²rk)<^4¥# Øžtª=‰Ëƪmw/œ2êzªÚŽSâçÔ3#}דú¢©Õ\:“"«Ý=Ï;à5Â2ç«‘I7¶IaGÜ å‚Þ ¢(ˆŸfñP?¡KŒªCé܃°Cr†ž©h›j`‚lέ&M9_xòNïËùb´),b“úÓq`!“ê_¡dg'#p¢íšX®æ`Ù–;E¯·0<Ž'âÔá[޶Z–Ü’ ŠyRivž‡ˆnéît“Ò9›Ï,—¢â,$Àd2®©m”†yMiÇ(V+ðàu¯Nꋯ¬èï;Quh`ŽÂZLvb­õ#^@›_×_+d˜º àÁ{f;Õ‚”¹c™èê=¡¶—'ž ¤çY÷6²W5ßÒ*¿ üW„õ êúïÎrë1DN±7ëÄËž< G¯Xè+Px "0c*Þv“ﵘGÝzˆŒ•»z@G†rŒ‹†Ý¿Û— Ú{Óð$»å=Á·5£‚½® ¯W쌆S‰n©tûÂ"•¬ÀXbbåÙfa_5û’ƨîâDA¸›½õÃÂ[“Ëm5l›«Úö‚j¾Á^2 DC1¿¼éIUq¾‘ÑBoL2zLÞÕÂ,Y³GâîD=‹Ó”#mJÆ!|µT_NÓ`®¤~¤.ƒÈJÓ$”½Ri«ÒƒX‰ö?€­¡V‡4*ÈBúUªWªô¶©øCü×ô¾èkìÅ^‡¥÷ Ù‹³¯°ñ¸šÿþI<(Ýd®TMæü¡‰úâàúáNR ­Uç¼$L.jì¯nÊîðWeF®ÑÈ4ÈŠÌ67†ýYD¥D÷9ƒÕîÛÂu×BÆ}-"ˆv¼¦ß`OÝ'Oôgòàõ“=Çÿ÷Î&ƒÅpupÝjti0HXÈB,n//ÛHH¾sï¯î—e¨¤ùô1yH‡VõÕüŸ°‘—Æ<8’w<$ ŒÉ&µýÊÕ7ù!ÞšÙ"Äë[ ±^2 dJq z§¯õ.j`‹Z'/Æûwÿ)ï÷[®4þµŸr)=ÉKh«~Ï…ž;¢ŸC ÔÐöÛ,o°‘ýø ÍHë•6«‡RCfoë Ÿy¤õ9¢Àÿþ~¶¦iIÀI–Oz¡^J„ùäøàó÷¿õ÷¹Oendstream endobj 1755 0 obj 3359 endobj 1759 0 obj <> stream xœí\ksÛÆý®_Á~²˜Š Að8ãrüˆ\Ûq-ÆM§éx$J¢5!%F¤¤Ê¿¾X`ïk÷€ d{2édLû‹ÅÞsÏ}ì"´zݤÕsÿù¿§‹ïß'iÚš­vz­—ÅŸÙÎ;IÙ¤åÿš.ZO'e³¬uó^ž´&g;ÕIkØO»£¬5Êݤߚ,vþµ›´‡»Yñ'mÿ=yUtM“Twí †‰ëÓI{Ýq’ç­ÉIÑëªÝIw/ùgí~.ÜÏ‘ûY¸ŸÓvgØËw;Å_ýèPH»½^¶{æþ}î~æ¾[ZÈ“Œçoìµ;ƒ|Üͳay§#ô»yže£²c%¼áÊM'+þ1(ÇäGÐý»â~’ÿÐOúÜ_³ð=i%Âs^êÑ”EX¬É0MŠëQ¹Ñ{ÌY¸á©î?Rf4“G®ÚNµé T~¯ÒàÒ é.i¶;5cÒåY$ Ú™u#\J· £éæ×ñì$iw8êõC¤9 $FÔ”@âfň•ï\ÆÕXgž%’¡[‡aÁ@Î<áj7, ÔË­¦”ŠÆÖ–ªÇJÐTÂOõ1~D8Eº†æ»üXvðO——»k $Ö—ÓQbJ³ +Iz阴³âÆWdC2k%ÒN< ±¹ÌÿLæ_·øD¸°…Úب½0îµ~R¼|§"$p>ö>°`ÃG|?•û{,‰°Ã µ”•í£ÛCŽXØaÆÂ_sd£ÂF˜ I÷¡kòî`@¦Ñ“H£g^ƒ.SõÞh1µ²=:Öl,н=BŽHŒ&¦ïÊÖGV&¾9Mó±Î÷,|<Ω'Èehò…¡ç qž‚ê ¡T%Nl=äL…‘ã¾Õ÷c`¬„gÕÛßD”ë37z¨r][ëê Åñl £)È¢~¯x׈`.Ú`- ƒ±8¢Lƒ€1ÖÔŒR7 @¾¶¶¤ãôÌ9Â;ÃqÉßÅb(7¡0À‰¥ó½ž¨|Cµ²ÃÝ6¥i„°q¿›Öxå*òìïþ•üP²û¹mZ=‡¥Ë@Õð@ƒ”¸iE˜P™Ì…Ï´7íT^­‚¹[†ûq‹"j¸}²½ŽPPtWšì wÄMô}ªËÂ\„y£ð!}Hè€Pº |¨'=G QðZJ¶±‚ŠžjE—ð»}B2W•´ýEú±K§ê ØE”.Y0Á$ ÷mc¥øKÖ~VÙh8yì`„æ>ä¡ùT·T«ƒOôpqvŠp43Bš^_Ç4*dŠ£ UöD(Poó@}3¸,ÔL¡éŠÕWäKí0´©—±Ã{÷ó‹ûy.i¹ŽJ« X8ލú‚çx ³™°ðP98›BªxI‚rýAB¯üÙ¾\¾–^‡"}N¾­ªîøI!Èþ¹6È]1¦Ž˜‚HäÁá1C®ñïâ©%ü\"ÅLÛÀØWò`˜ÆË˜7!žŽQ'þMÄ–‚)0Ú×6C÷DÖu€èÑVµ@Hz*X˜jªH\[YQ³ŽÑÆ{©É4!]±gá&lÛ*ªõ¬ÍhJ9ñÒ)…øÔM¬„×(‰Lˆ8 Ç)>ý™ïýÍ •Ô07ŽªZ§NÖ …‚/"«k^%öìºL\ú?\§”VSc‚q®(+·¾}@,M˰&ÖP±êÜRLy÷Ž¡r*¾kÉ]‚Uˆ£š*¬ÝnŸa* i@Û•¡â2Xü„ÀƒË·0³£™Äkœ×=‰^Ô&Ð:«ëªæ:­ˆ%K»ïð©ÎÉškÆU#YfY{:Еµ¥EÊ ÖxP6%; W…ªîÈ©Œ¤š/ÜëIº«•»k®‡ˆ5áÒ…WrS9¥)ºyЖȽ€; c㢹«oíU¥SX)¾aýÍ­·àɦ°ä¼iE$n}†ªo¬ãööû»~²ÒrlÞ:4KsÊ«"ñûÚºKÐŽ§]­¯C›ÕMq2>pwXŸ9TÕ°õu‰¨ Fmpkz…ºê¤b:åâ®ÛÅ‚RUØmØdk¨^˜â^U=t{\=„U>¦6šª>€Ú䔃lYŸxSÑòàˆÛ> Z±­à[¦Ûs¤†Z=»O¼O_•ËÄÞ¸FöZLïŒ=ÆÒ›Œö'3¶ KK;K^JÚrV'a/%7€SZ_1òêv2ãlî(Ûh=ΡÃ1•*—ÈN6<(§³Dª€»Pð½ ²KûQ¹NçqeLe16‚Sï­p^ *û*=2"»B1Œ}é ­á± lúy?*ȹ|a÷û)‹4µJˤ°º[n1¹ÄÑù+ÿãÎ9eã’ë*d4’–¼“ûâ?Šð á;Ý2v‘2ú£>±¾Î( ª ^yJÓß`¥:<Új¿ùëÅÙ¶÷‰ \Ž—þPàc<,£Ý£Íó„g^ði†:³‰¬²Þ|üÊ×0ŸÒ"ÙT$€;Ð0&fí2Ë`é±w²Ò_±Çž`h¿áþ t_V´‹üí‰É/óó/‰öòáQ‚g_4<8àõÔúDê¥U&$.l£6èÁe1Ä¥¼†Ë.÷m¸ÿ´áþAÃýW²ruo¿¡ï>Ziu°LZ>¯‰¤ÏâY®üØÔàQ¦Óà­&M=o•e¹s!UÃòê‰F‘W¿¡‰ä(æƒ5¦˜n(4ı{‚99΢f'BU$ÆU”Ø$ÂÙãbS4eã‚óchÁÙPŸh¹2ó'¢|¨É,¥­ßiH³nÂe`ë](è²!¿òx4Ô…é¦VK³¶’¥íL”¡jÏ.›>¡O…ÖC¬P7Ì3aXJšûV;`¼MW`†pÀk:YhÎ}ªàIFÕÚÞ‰ö óCМÁ°:x'ïË•þ?³5ê £²@|^æH¸bm4Ál±†ÎjM™×p k² N¬GçÀ«­ÑRZ·7¼‰iì¢ÇîCZªú§´ DþQCˆAºlŠºW¨eÓòà{€ªL®Soîó¾;ˆ‹m¶­¬o-GèÃ|ëD_Æx;å.k¿7ðé{ü  Öë`Çwˆ£ˆ‡ö-¤è¼Ž+óÙÁ•øfŽ'ù ÅÍڀ̈́?×På É^æG²âÈKÒÉÇ‚ÉGèa¡b3{øUÓ¦§ ìO?XjôcÁw£Á®9óée਎Úã?7‹¦¨RŸð¤`5¼%¶òÀ†;Uµ–jÒc9­¬*´‡¨&:G´©˜²@^‘ƒÁÇWjzçè!ÐõÍP ¾'hi8ɺDo¿ÇÉÝ > B WûèUÙC¢ì#OºìñÙÄà¼éè·/Y‘Áwh²c^Åoé_…بV± Âm üÅ÷Ú mðKöC'ÃýßÊè~c o˜ˆQ ;7Òø$…:¼ l·X¥è „€ÁÈÞõ €×[ìnÁ³*³Íë é~.ø î‹ ]ù¾Ç&<ªeCÍÐNã¥ýôT¹û¬´ÍÁþp§²,Åd÷MnÞ²PÕ~EnôPbûCòÛsä¹FA,4VHÈi Üp‡{u_ÖŠ³¦OZst‚v%i®rëgý¬çzƒÝº°¶,;ÛG^‡qíD‚;¸9Úà± {¾ÎC¬;|nÐoß4V£/$g7~ÑàýJð?§X+ŽOá)‡ouŠÁ¤WÿS%…[ÞÞ”cbjÝ-ÈwÄk*|4_8†‹û¿Ú¾ÚŒµ¥ ~¡Ί;Çè(]Êê¤ã’`jÛ{O¿Ÿf}êú…ûpu>]„ñ×´¶xaãê‡+F«ÿs|Š=|‚'Uª& s» ®dS}Êf]”ÞŸíÔ‡×C’Ù+šÏtóÌMÔC@ôYxNö =D"³c¤UßýùUrPâèrðí´ÖϺ£¬—ª{Y•ÎŒQ½]™r{Sßâ˜w¿—õ µ©ƒ°ö¡Þïµ”H˜Iä-ôç[+ƒ%*[, ÑaõàÈ~:˜ÉX‹¡Á, jbÓç“¿ÿý¡ ®endstream endobj 1760 0 obj 3554 endobj 1764 0 obj <> stream xœíZYsG~ׯл„]vvö˜M*Üå0¥Ê)ȃ¬Ã¸,!Ù`å×gîîÙmI„Të¥çêéþúëžY>ö³”õ3õcæ½û¯çý³u/ë?“Ïz{LwéÛ_£yÿá@wR”6YÃúƒiÏLÀúuÞ¯D‘²¼?˜÷ÞF,.#!ÿqùçà5LdxX΋Trä`,{?ˆYÚ4¢h¢WqÂÒ¢à…À¯OÌkYçÑË8Çr°(‹*:R ¢aYÄ çMš±2z(Û9Ï+¥qRU"Íó\N'ª´,D‰V{'™žÕY%¥yô"æiU1ŽÈyÓº®«ÚJË,W9W»)¬2uÕ æ§±bäœiÍÍ?ånç9+p§c%Í™`B÷'¥Ô£fÂX‘3Ž­˜°‚§¬ê'R—š5±æLÎ-ÔãB=Îä™1LØ’fcº9Ïä{{¡lΕD]zá„g”på…÷â¤h„|ѯ²e…\^âÁµ3ÙΞ6˜A ŸÃLÇ^ø„Ïöö´oÏ|³2ãiYe–Ï{ƒ»oµ’Ji Õc†u.3!Çiï‹&×:¾=§t~ š<÷Âc>ðÂA ”Òdìq¥§¾ë̪¨½&ݲô-+˜yâ…#‚×”pAù×ûŠI('y%±Ð4ÈWä¾Sø„)_=qBg‘·À\=– ðèZ=œÅIÍË–ŠœRñ¥â ¾Ú©¢¦“@Ù»k„íí&ž{á„>E×TI½9+T«Ø±í 2(h‘ÎxDÁõ…n³Ž{= àœ4,­DÆú‰6EDWžƒ“Hx±(ÑŒ£‰%zïŒÇzK/ܨÇÚ«¡gá¸u¶¹¢P  ¿~[ca—µÎAÒ£u컈òWŠ»v…÷`ü/ü@ã>AÑ; |[†u4¥0¶3‰?P oÌkÁEô¤á<îuìûº0Ÿ^9™H•]YY•λÐe†‹î¼«èšZ'É.Ða3à½1̳oö$®µµ‘he;³z½Öt†=Ý–!…« (zIõ ¨¯©ÓQ¡Ã¡³‘!A(V.½™@Û8†U“°Œ×;ÃpêƒÖ³›Ž!ALfŠ‹e—éÍíùÔ·A;°ØÞ)eù€A]O§SŠfš~á}’˜‹k‰›)‚Xd¹w"”o]ÏE€”y%“\å äpRâÕé×à™~#ú4¤LãvQÅâo„Yû&]‹Š1mÕxH š€Jë2Œæ•pGBíe®ÈPøÙ`Pó€*ÀÞ)«ïŸF(ylŸ_êO»ùàœŠâÓ- vYެ.À«g5²F(ü± ùÿ½ÓN´tj½ª©†%0>ry„’Ó‡Y~è1v¼ƒ˜~mófÇ]+_èÝUÌŽ»õv×X„uÜ2£Ü2Ô¬¨AAy@À”DÍR}Œ£¢ËJhçëÀ®¾Ù±o˜ŽÌ𬅀6TEÓ’"X:0„Ù%©xËûݰ՞ͳ†ïÌ0|üëdò4 c@Í×Ñdñõʽºf°……µ!v¨ËHsJý Ðwn¼ öE©+¡v7Á«Û·y=-êhyûÒæ–æŽD&X·g5DC£ ÇÄ»sí³‡»ÀeÈÈ£gE°È…M#­©;N]„a ‚40øçt‹-qµzp>€³º/8òB¸P™«[ƒö$[Ƈ )áÆ ]¥ø9Ìè.Rqô]ü^Ý…‰¯á9ƒ"ÑG¼¤Þý¡Ò¢{ ”o9…ýã@'+KXh@h?}=׳ð„ûÅg ’1É{’Î{®%.(Ë w[޼%<ƒºo_4œ(œdÛ·´ `1Þ­ÓÚÇÄÕÄ:õ·ØÎÏ_A4ÖyZG‚‡ Û™Æ0^û@¹°¨ÀX81¿t¦„žk8XŠ|ôÕ?tׯ¤§F”yísJÀă‚ÕMäW!o»‰¦”ì p³[rI¡àššhe€ÊãD›àÚy[^ó1¾ô.»>ЯÁHòŠãOˆâå(ÙKÊ‹®£ºÊ/¬^‡ƒr£{¨<9FÝyÜå ÷/º<*ÚPH¯)a h—OÍ­þÒ“¶šú*ÎÒZqLÅN \„{à <í@ —H{½Õš(,¿Y˜Ùƒ™ÍÉÓÓbó¿eà¬re¿9Ñ‘†äÜ} ÷ÊÉ: —%œD:gÝ^VmâÛ‚ì¶ CX€ûÉUˆ…à[&K ’1¦ò@w2wú8ì³£KøŒ×@{C ïAØä¾= n$ºB4hB¹MT<OT%ûÇm%û³æ®J>ÛP•ìæû®dAyª’Ý«üm%ûØ Ðw|¸šÒ5m÷ Úá5íÆýMjÚ½dr[Óî¶ìÖšö¿ éÛšöëÕ´pþ—÷øÊz 3ß:NZÿ1•…èš‹sWØÚÇšÚòíOÔ—5 Wx¼+ˆC 5ûe1Ï îÊéZ1ä»è.˜Ñ#b'±zèæÑ®rfÊI-[ð9ç/´óŸ z¿ÉŸ¿SM#Æendstream endobj 1765 0 obj 1945 endobj 1769 0 obj <> stream xœÍZmS#¹þNåGøã8ÏÞg>²·°!ÇÁf1wIÝ¥(K ÇÛ-÷ëÓ­©¥q؆M²Ôc©Õ’ž§ß$óÛ¨*ŨŸî÷ÉÕÆwŸ„R£ó»jôþŸoü¶!¼È¨ûur5z7õbz$«ÒZiGÓ³V992N¦W¿›cQZ©­)nÆYJY9¯J”ÒHUœŽ¡Q#ŠyÛS3z½OD)De]ñF¹ªTÂß'Ui¬vµý×ôoa%ºtµ¸cJ­šz4Ýݘþù—V¼–¶-ÛcPa¤ÅŽŸ4×Åg©S²8€~] ¡›T`¿[jWlùÖÚU¶¸E½Z:m›ð^k£‹kÐÑÛøVå(âÊ[Ü(®ÆÕã(Q+ Ö½C `eã.”Ã&².…‚mÌHø^´Æ(ÀkÙ|j ¯lª¦Å§)…­dÀ¶¯`jQ©âËxØiÝÐ6Q•*iŠ3Ü3¶:˜Ù—@š´èåz¬êâwRs:æ­> h#ëªl[U%ìT ÀŸiΨ'ÚOÛ¢R¿9cœ•‰&D ŒMé8_#h²`d¬Sì.-¾jh”J#mºTJ72}Å­#¡B–J6‹«@Í85}z ypyUò²8‰ó´4VB{›§%…þ8¨î© “è E‘$ xJW 4£®Risÿ‹q‚«‘ ,C4q¾v“BÊ´t•Uá'E.Ñ™šam½þZDãf-öOÔ8çúÑLX@h#J­Ä°‹z¤2õY¨Xì&M º¯ Xo÷!™ê×1®EAÆÉ‚@ëÕhªÒ¥hšàB_¸=bŒ¨È2ûAmaÏi+cª&ȸÎzºM¡x4g~ á6ÞBðE¬¢1h!иhî™íãf%Ä5-;¼¬YEq-™Ф½Ó|¼Ûøƒ0=Ž $gÛÅÇÈÜC=´O46 ¦ìÒ4Þ¦”ñ¹#r˜ò z¯!)=Ž•—Re}tHì×&UB Ã¥Ïh¢$s! 91¶Àl§óáX LEhgøI¡W™}0¨¨ -KÁÊ`áË'‘`çm%)8«€–J@˜ƒ‚¬ª+Ñò‘¿M²òáÇSà“)ÖdmÄi`ÚªÆÂ¤ëžã İ‚Æ:»PÅOØ|Ç?D€\ZˆïM]ü˜5ÓØqlœSã×xq—ÑöÚòf‚“®÷hç ¡¬èg¡úqA&6†U®Ùøÿ§ˆkDc0Â-'èôà‚˜ƒ©Vp!‚ âm®_5øx¦²×¿šh›ø¡À³º—ù+Ü€Úý¸îHÇ_ÀõDã#Ô<öƒS‰&£}tioiÐm*¹Ðè™Êû^<õþ¹‰t<’¨âÛøØÁÇnס]åmVàç ¢õJld]é&6>P#¸²J@ärFÛ¿ß5ÞP#¯¾Af|Xl/Hò’‹wÝœµKÖ” {Jk¢é¿äýU“Ä«cê»"“9ͬ#œ—¼´£H„§dÿ ¤Èv@…ÈQDÎ=·§ ˆ‘CƒÛ»æÀ?Miô’~6åxoF‘zÕÆeÝ|cÐIé-znœEqoËDWfâçîNéQ|ûûáÍêÖ–°^)Ǭ>ÌÝ¿\øyMµãcßq¨ó•ÜŠfû>ÛÏäãEÝ·ùWê™1vÛ¦tŸ[VÃÉS6ñŸÑBVBŠœôÞ6z~ëô„ò€qjázÑ·~¥qÞrØS±1[Þ8Ï¸é ±«oš9™CÑêqx7tÄu ä½ÿ)_rxÞ-Öú™À[5«»ÿfn„þ#•}\ø.`Þªü*M]ç¸%Õ9[Ô’E&îúD¸Í¸m°¹cÎu‘¾hÐwáÔŸúÓ׬ÔZœˆ$g”Y¹ç†ßr’Ç)ýHße¶¦Œ¿È¦éqÉEšýè »9µý"—’¸üž£mÎíŒpOEË'ÉÓ¡Ä€<•]!¢±@ñD@+»ZLãw òf>ÆD*wRª´³Ðß$(Ž‚7 CÇÜøKn¹Æ3å!ï©l2¿M™èáûŽÉ™\Àÿaì—vþ‘œ]Xw}ä¶D›¿XDt¨N%’Xô²Y¼áZ#Âü¼×æxñÛ‹ÐFüŽB[«<`šðý#9šìEñCZ …”]* Öº§y=(ÏÖlé”Ýè<;çisª'ü㇈ê2Åž¼ö$rÇÁ@šþ½|±ÇBOêYÃO³È‹Q!›o­ÊoQñ{™®úãÄa„˜ìýclÛ 1$–¦ªø‡Ozf‰ùÎS!ŒÕØøvAã0öÊ\%„áŽo¢îŒ£î+¥×ëõð î¹ôy©ÃWºK|é *ò§ÜG|1.rN$qòvGL¶’8ç@Ë¿Z`ç¶5ò·»{$pöi¹³'v™,- É.ºZ2„¬œŽ>½„A—,Gq%Û‘è^b~µŒñ¦O,*bqh3]ãã0ÌÃùä…;—!oíÞþàªIVQ~I«k LâmÇÜ KnG³¾c¥—tŽíù”çÀŸhÿš3ô!'ç9vÉÑDk¨dÝ'Ôø…ó2ésªpÖ%\V‰ÔyÃKuí[:7Z†#â`¢7Õ y…S• ²2M 1µ¦Ñ-Þã&a‘½O»M9`.&Ö*ð–OPCé3¯ÀèƒÜak9 Êpæ*5QU*§À«ÁÕí|µòŽÃx1‰±I圞­V8?`*¯ƒxËòÓk"*΢\«½kdÆ“ìÖè3·£ä––½U"ÏNLí…[£{ŠN9´ÝM’\¶ }Q»è\kž„Ãðצ{&0-A]ïàÏ×ä| Ô%—DsŽ2¶KîÒ~ݳn\ï”È^ÿß½ÀÒq*˜ÏþB xÚëí.ÙRï¾c f¦±×»×v ª(ó³óº§Gqô¼ôEK–ô¿_bM?|?(ôÿÊs V ‚„ ‡3Î,ó/è“yáÏÎ%"Q&UüÃ16E ÿÍØà ­éÆßáç?‰5üendstream endobj 1770 0 obj 2595 endobj 1774 0 obj <> stream xœÝ\YsÛF~×¯à›­"‚ÁªÝ­ÒA‰.KÔZÞÍVʦ(Ye‘´IÆŽòëwf€™îÁ4ˆ"Mfã2 öÜ_ß=`¾v|u|ñ§üw0Úù銅aça¶ãw޸߇¯;Lvé”ÿ F½¾ì–q’—û9ëôïwŠ X' :Iy,èôG;ÿq˜;ÿ›¸ñû?‹a™‡~âeÙ¿ã½w]æåyåÎ¥Ûe^…Q†{Åcœι8nÄÇQ✈†,g~êܺÝ0Ì=ŸÅÎ>ôÒ4Ï™ã¹Ý$ɼÀÏ1õÐOi’â úÐ~ívc¾^”Çeþ_è\ðAàaŽ7tåv}>ƒŸú Ïσ¢¯A"ˆ|câ䑚7e_£°(ä‡ÏýrñŒœ—ÏáÇÜFÊåæe{15Ëø$|SxCå"AÊ äCbä»Ï›º|O)Ëó‚b)çX|슱g1gȗ࿉sñ!—›À4¾YÆŠ¯¼3ÖçLàÀ¿Çâ#Ä<Ä™îþ‰˳Äù ‰S 5ñŽÇç|åiâzqÄ©&>Ãð;j¡GMüF­>…áГ#Ä)#gL­>çí,ç_B4hL­97ˆõøTòPòîƒ|DBù 3Ì(Á´#‹&Òl{ÒTÁ–,];ӭ≱ÄdDŒ0DQñ•*cˆ¯šsCZÌYµ¤¿Ùp¤Ÿ´­³ðORfgÔ¹~§Ž1Àãœ+œŸ¡)¨ï ‰³‚9?zð}ñvž°1ÑÊ8ÑíjjJ—õC õ©ž¼GYŸ @,攡 %ì‹i©Å)³ Bê3¡l!“ó’!¶•0ö)YΗlÅHÙó^)9–Çà*wOú–GÊH™åU¦ Z¯õ¦${ÿ]6°X„K˜³ù¶Ä à04¤"|E!]˜å15Ó¼°l-¶±/8#C†ºˆ ïïHð0L/QQ÷\­d(Ï'c&éų\ ‡öŽðT44NŒ$IP·X¾¤Ó‘ç±–’]-H:!#ÏßT—é!/uë{.W¾  Äw_|0«O­M*~ ƒd9ç3œ%Œc,öLTÏø‹ÏÔFž5ñ;%SC^`N°ä<¤ŒÂ¥'(ÕÞp ±Ta]oÅ­ üBuûHé!"~çWBb:þЬ仯©lý¨‰UzØC&Aüa%“Èxº®jg»·78ÆQ$£7ýŒ¸ésèyœX•>-²{Z ûZÜOÊ"bi`B‡²ýÕ¹€=Ý~bøÓ’ˆ.? –¿…HqC:Ö í¹¦ùºa–%ªÁ:P…ÄuÚo)¨¯Á`lËJA¤¬½ZXÃÊbmÖJU„.,Í2ˆÐIÛ$Dë@ùR·ïCû…&ÞøÑß"”ë =z´ñ: =ú?…Vº/¸è’fáTwʈ5‰ïZò`p\‡”ãêîâlc¼Ò<øPCÑìHCýN£| ‘?¦,0ÊÇ­±lJΩádÉKß·àº* ù¾CÐE†·»_„ЕVñw¥ôA¡L"“­™e«¿O'Uu ùšìifÜeòEŒ2åŒå©F—ÊÓm£ º…+`~”¢‘)©#ãh¥=üNñĨ.ªhŸ,9>R¶/+¬ë>¥-ÄE¦ÉD•·‘7Ý‹,öµ6#pÑxZ*“á Uj½zc½TVMjˆq¯i"JbŒW0VçV ³}Ñjl¶•Š(¨/©Õÿ‘!vOt)K¶O)üŸjȺ'®m#p4á© åòäu¹§9,ß^¹¯ _ø¯´Ãõس¥Â¸…é¹Å8”H‚<6]𥉕‡yM&jÉì1l5©78aùÄ>fª-çÄÑVš-7´DÖIdÓ‹AêÑ ¡ün±7YsµŒ|?ä 0jºÒû‘™;²oe Ì»íJF^aÒ­Ö}¨j‚5¿P4œÛÈ”;ëM¢<ã€ùËY`ºm#‹¨¤7¾À=Ñ…µ¨÷•³^ÀØE÷»úë®¶ëõÁÊL›Ä”òÚ4ñ† ÍÑ-n.”Áή&"¿·Oa~|~Y¶V1üÃØžâýrœý&Ÿè;¡ú.âÙÞ‹x–nÏÌ7IÓjÞ8–Dô¢æ_…_Í5K+NBÙ÷fo€6^ç\˜5,¬VZ 6åÔ? ÔW8‚ÚX§4,Kèv·èÂr›j›Í ï™â{ŠC[‰+Û>\÷(zAáºÒK¥– /šœY`Ûæ!¥þW@<û±`B`•ø9Tµºf†ºù˜ÂŽAõÑ›lQzSˆ`£n¼ˆo'å ãƒÚ+"Û*ذ£œwãªùªRåßá]¿ZÞŸÿ Ýê*ýhE"_2_}UùÛ—EzQk[ Š·I/¬KÞpT 4ÔeG_ÓÀ"W.àD ÿ!!B)ä+¯8È·ÈæÔœÀ…Ìê×ðì{‘ LOšûº_Û{jÁ$Ž• LÛ+'ˆ‡%+Þb™’L1~)"™‚rĆ_Ì‘‘¯ÈŽA‚èñ+yÞâ ª\sDõ„- `ÛÂX8òMxüK¸/.e†Ìe!Ñ\ä *÷³u·Ú`7ð bäš±ã¬Õ…¯©®ãÚÔkN¡>£ØK[µ€ -S6e–µ]ùÅT§wúkåçmÕWkã êä-fûM=àá6”páß”DY¿Ä2F¶P9º¥Ye d›˜ý¾PÚ%ØÓëï¼åþ+¢{endstream endobj 1775 0 obj 2644 endobj 1779 0 obj <> stream xœÕ[kSãFýίðG;UVô¶T›lÕㄘM&ÉVЧ‡ZÌL°™ ùõ«–Ô÷Ñ:’Ǥv‹BHW­~ÜsßÝüÑó½ ç›Ÿúïå|çëÓ Šz³ÅŽß;(~g;ìe“^ýçrÞۖͲ‚äå~ô¦7;UA/ #/Ízi{AØ›Îw~탤Ÿ¿£Aòïé÷ŧQÉO‡qœxyØF¾7 ò¼7½*¾: £þ‘¹ü@wÇæò=þn.§æ26—½â’ƱçýÐ<'æRÜ…~âcñìù~ôï ¢—çY–öÿƒˆˆø™‰ÅûÄϼ<õèý5¿¿$â&rË+&þƒ{ èý‚ß/Íû\LMŒò„¦Æó}`âr¦fF òâ!ê¿eê„oßT·q”õO˜zÈ·ãržElj³ä$ô=3ÚÏL öQžxAZJ ñ˜8â–x2Ǩ­érX÷9 "/Iýº®…dŸ$å{sQb•„a&d%bYÇÄÌö™cÛÃæVJ@Ÿx%`ôþŽßŸwÊ·á•aQ’g½éáÎô«_û»fѯ4“^“:ñ‹1éYÙä;gbëKD¡Ö½˜ùùñ‹',”ãZò«¯Qÿ†ˆ·ÜòN2¡ä\Ñò±›û<¯û,x õ•¿Dó¼E-•ºB̘8dbzâ#_œ AIÌ|-õ}¥L©ïe±U¦sV±ò…£+Õ'ZWìmJw>ã^­Â˜„$Ë4ø ƒ?Aë½C1“@‰–VY®Ðû%Bw}‰a4žPŸ×Š™åDò¸ÿ[¿Ûo,¹ÿ¿PWRXlKlD/Ôüq1p+q)#‹¼,³‚ñÛÀ‘êíŒA› L ïc2…OˆG¾OP§æ0Ô·[ƒzJï¿S^ &ž*?ea¹d^Ï‘N/ÙÌ@“pfoÙfA[Ø&‹×öÎ<žÔFVYÐtèeý@d&?ojÆ_ h§Šâ,-’Í ZC…ku`¢PÌrŦüŠ5äÀí“}{#ãƒÔ‰^BÎ÷UàSß4Ђ‰Û ?>µL¯&>'ÚÅC'|8¡'Äa£AjAk… ¯˜æ-\Û.½ä§L|EÄ]éÖıñÂ…ó³Âõv2Y|YR…PÂÅAgó°"D>ª®Ê1Ëeƒö&jÖ,Z•ßȽ$´~c¦ ×¤l7 GíÎã5=žíˆ=¬SµÈ<ûŽápQ(ÅÇ¿lÃÄÚçD¼R+ÃÉoJ~pòÕ%Ñ{dÉ×]ˆ°ÚÐ2AõâÙßóD·°Î"©6 ª%+s`EéŸÜŒEñ í5Z„Þ.GÈ÷tY½eQ²ú-Ûf«°K¹ŒÎi^±Ñ\J,ìÚç O²§¦;Ÿß£1¡ÉçÏoÛ*’ˆÕÁ¨õywhâ—ìóôЂGÂ3ˆÒ ®³k1nDæXã ƒjìg‡ön ‘(﹈q-6ÔdH_B`¥’S¡7Õçs÷D–JI+ë<ÚªàXß$\Š6m/”§i”q„ÏŸ=5¤Jã^X€.czJþÓºÆtôAסKû ÞŒ¹¯R:ÛòóÖ|–Ьè-Ñ:/˜;x@cm–ß´ Ô°ÍÙÿ J×hvLœ#¢ÕšEÕMñÆöÔPaÖ'TŠ«î1YÒß ã·ÌL袜jŠ¢˜ÃðæÈì¾GÖnÁÆr£Ê¦*bÚ8<Åá="Šè~¦JÏÃJA鬴En¢'GɇD; (ö( 3«Tüi+%2A Ï߇Œ‰ aÜ1Clen\ÌÛ¤ÔC„(ë↌£SÝÕ¶Ò©;Åûm<*,gk1‚"íÙHÎÛ|4s6üøÂ¼ä=sÁ²C¢²'!9ïš±mr»/‚œÈó¸ÔíÊ9ZÐóóyÖüúŸÂ°–«6 Î)ëÝ©8âÝ)¶œNb7œ’Q’jc(2DèaýÿY0ËûUÌ[ïZõïÀİüŒw7`JAŸÛý¿2s9̾é_$ò§ä›ØiѶª KÖ‹0ýïñC6èÞ9¤¸@×™7ŒPUdÐtQïW‡ í Ùú~GÕ¤•‡N0°½(ü ã\¶7ŒñÂiÞÀ ´G î8kÒãÜ:µ“§µ:!„~ËÍkCÇíCm~@ _²úˆ>ú±ðU6Âr&‰Í–0ŒÃ%mh#tìÏu.à1*#%w!"‚)¶­æŠì/¤\\¦(‘äÔ‰t³%ŒB©¶§ZÀ ðÕ†ESÿDÉjºAŸ"tØÞöÓ·Ö®g¥ñ¹“S)|EJ6©¡)7éƒÙ¤cÉü³Í¥5ʲ¹]±gÏ޼ <×î¹´äž‘]âÍMµÍ%\z•|«ßÅÑŸ±Ò¼íRÀl%v‹Uˆ¿™Õ¯»0ÿòщekŽž(CßílôPNrî˜*ª Tã¼3‚žI®§jä0 Ë(ÌÄïõ¿D‡DÏ‘“†õ~Þ»nË…#-ã“Óú☟TYy»Ü5¶ë âY~­YŠ{¾öYÉæÎQ«Dp}¦yè'Å æIÈ ë´œ±½Ñ|Ó¡œ¨hñmù¯wÛtÌòíõwÛ-Ž‹(%¯ª¾ifƒ2,á–'; !«À>m‡P{ÖfTs;%ëÁÜüH2j1¦x𾛿«N{,PK¸W,N†Ã&ªÜ›DAqßÒkÐð'îÞ<·äG5Pãp¼›~?K!›-™oÐOsMÀ=…¾¶qÑêz¤QΨ ßqnÂ’f·šñ·®˜¥ neÞ#†è¨urý³ÛM÷_|Ϩ©Ï­lCå×Û µlîn®V`9¥ä}ÿ€B¡GîøЭ(ƒ´QOw~,~þ 7·endstream endobj 1780 0 obj 2483 endobj 1784 0 obj <> stream xœí[msÛ6þî_¡oGvN<‚ïüÔqmǓֻŽÒ¦s½¹q$ÛIk+ª%Ûñ¿?€$°»âCR²ã\¯“dÂÀ ûì³»XÀŒÂ@Bó·ùz½óSÇ£ËåN8:Ôÿ.wþØQU“QóßôzôݤjV誠 K5š\ìÔ¨Q²" T4š\ïüËS~êõ¿O¾7ÝŠw‹Â,( Ýs2Ó­w}”e‘”Þ‰?VA’ÄIÁ‹u1Í#ï•yû~¢;§Iæ½4/ŠR…¹÷ÖÇq„*õöt1Èó²T^೬¢°äµ/|Sʳœ0¡÷¯ýqª¿—”iÓ@ÿ‰½cÝ Š‚(.ù„Nýq¨Gó0Óå8 Â2ªÛQe¦RO̬<±ãæªÐ_ÓÒŠTëÅ—aóñBWxo|=F˜FÕ4â¸êÐL¾z_­ =H-=)>¡æ#Q®jÉÇ*æ’«\÷ Õh¬'•«²¬!¸2£†¡RÞ4ŠÌ›»Ês=hêrî­\å=µüà*§Tyî*õ]­™ÔXz Éh¬â ͨžÂ+ÝÜ;4óøy¼4êÅž««~<0# ZtÕW¨±%‹c/vï2šVª‹™^LY²µ|¤÷º˜j}™ñÅ·—´ ‰ÐâçÔrê*¯¨òÖUÎĘiXe‘{…+„ÂÍné*W6»Kœ”¹Á¯žhÊ 7Å$.̤º°ZÓvå|㢠²Ä²û\bo¨ß@Ÿ–źöIHÖ¶òï°Ê„ÇDp:ÑðgT)ºÀŸcS¹4Â-t¹`c®LV^çb’¶¨%žªÒüà}Kµ&QÅ•S÷¨ê^˜Ç±kwàæ©H²¢ÄÔɈ:²‚„T•ëšYM­‚ ë éíò¬­š@S4Òû‘#£á¯XUîœwgV½gÚg‘]@d¥þ1-° ƒÉvUÑ* µä£Z5/%¯:µá¸Ñ¼Hs uNPŸ#ùÍjÒÄŒÒÆJ—³M̘¸vfpè)R­[ÔRp¸)ÝthK%aýɳ®ÕTŒ‹×t„}©jP”ïOBõ©§-¼™Æ˜¶3¢£òÑÎä ßwæ±kû®n×q[7Nó$Åé;Ä“Ò3$ÊKWy‹Œ-¤;¡³$ÄèËKÞ²—ëqý êt‹†'ÕcT|p.ðrùŒ@š‹™r¼˜ v¤ƒ~:«ÔòŒOÖà%vÓ/±²iÔý#ª ¨ûkWùãVˆYª’‰c‡ùô¾%ó5>- >sÄæÞpâìßξ’Áå±[óDšÍ·ÂaÖQ¹m§m‡)cê•1çïL²±ÎuZ‘Ñ"¥IjJÆu…gF®è}¿ÊJÿåÖh!UEæQ#²4O3m ¼Äüš‡ÒC…F|ªÛ05 í"—}/¤[9k•àX…VrÈ·ò1w¹œ´õ(RuÓèp?uIƒÞŽZÞAågTfÑäH5I”5ƒÐzÑV´9Z$ø+15·ãúg‡Ð:¥g‚Ð?7†½4{åŒÙ·_´¶ª<’8Æ„ã@Øü7ˆÓcüÜUžsé[H E|p•÷HŸn„ÚÝÅ]Hp+À©RδhIJˆ·¿2gS7æºmŽGÎE:X÷\»#‹m=? °ÞW‡àä+À[,­Ô”kìd¡ýYõȲ wÛ³+ô¸y)#ÅNãK °‹Ù+µf•Ó¯`o ö…迆»»½Y°¿û6³7©›9Ø€õL eÓ¢(f_QÜÅY :¶+1(¾ƒ0Ÿoèž‹„^¢H(L$ô' AaÄ5iá¸u¢¢â¯ Ñváuâ?K°JÀí#àÊ¿2p34cJ]I“E“Ûd¿a`ùRîË…J&B¡< UT°ÅfùÅ¢Y]†MÎÐûUåUŠd‰M@A‹ƒA{°•C«+›Ýx›p°{7¾ïˆ=ßnþ©§˜‡¡”êY”9šesßÙò”¢Lú·tf›> a$H'ˆºð„yI³#ÂÂCÖÍ©}î²¶ŸNÔ¿iip«âÀŸx§~;¸ÿ‘ƒ¥WHÎwˆ°é÷y‚{Ré‚~s…0ÌŠÃ ³¼Ù*Šh¯{ Áì5dÈh‘C:v ž8ÔÜ]ƒúó¯ «Æ”;v8×ítI”e…n]©hj±~&Õ`«½õ¡èàù7JÚÊ3—ôíÙYkèT/Zƒb_³o€zpºñÑkgO»“4®L  y"ðHò‘¨m|zQ— ¶B%ÊUÝÿð=ÚámTÔÆª ݘ'”Å&£íI:¯k4ÖCl3m÷Ü5êþtãCêÈRàÄIóÔ©ñ“uõã/N¡‰%oÝàíÛ* ç>b_F4¿´¼R–O<8Ä€6÷>Û &<Ü‚þ]DêÛúÇÞ¢Œ‹ëÙ Xdgc_úùg_`m)c£Œ ‡ŽïòÀ+R]¶Ök`ƒ$=صHéðEUádlï¤å‘9n²³2,i‡{uζî"s¶ýqä^º:Ö ÚsZrÜIbv4s‡$q¥1l¸3àúåé= w¯ìCV!àÍ:ú¦t=ø€¯±p¢+4QqkÂÞ2>²V£µIÙ}f•€cxÇ5%¨zÈký:à®°}À :³ ¶N¥q$ág7ÄÜ3{¢‘}ä<Û}Èr,¼ÂÙ½ƒ¸ŸeíÁG¤ìÉTh'Si °ØçZ{gÊê¼M}óvì6èøw&¹è:‰6"ç_¡ÍNn†öí›ïÀžçbýÞU¾VKûÍ´ëÊ2»å¹Ú={Áíul®çWÙqÉæ–1gg:¤ ·HÖ „Ê qtóëᘎ0ƒ#Ž+±7ÈWtmú™ô×6»Îp:7J@·$³ZóÒ~HÌJýqû^ÑÌç.Ñ‹hÇæˆáÒK¿ƒM"¾ï—¶ó«Í€]yp z¾¶øŒ¤ÚWXûÒÆ^1úÙÇ×®î'×ÎÀŸ%‰s‹kGÏ 6´¢]žm¾ÎÁèò*žÖáîvÆüÔ±àZ3’µh½ß`¶OFXbJ¡¬ÍJl,”ý|‚çØz·/0<â¿‚ÔÃ×lÙe¹<ÈÍu\7%扄ù{ße­ f²Â€n9H—‚†â£èÓæ%7È77ØBÇ÷¼êô¥Ì®;ˆ8îEÞ $ á=¢ÿk3úô[+¡ß<[]@ŒØù{'k¤ÜuŒ[£ÝÛATëI­ß$hY J2[ ÂÀøï‚žåµó> /Contents 131 0 R >> endobj 142 0 obj <> /Contents 143 0 R >> endobj 147 0 obj <> /Annots[150 0 R 153 0 R 154 0 R 155 0 R 156 0 R 157 0 R 158 0 R 159 0 R 160 0 R 161 0 R 162 0 R 163 0 R 164 0 R 165 0 R 166 0 R 167 0 R 168 0 R 169 0 R 170 0 R 171 0 R 172 0 R 173 0 R 174 0 R]/Contents 148 0 R >> endobj 177 0 obj <> /Annots[182 0 R 183 0 R 184 0 R 185 0 R 186 0 R 187 0 R 188 0 R 189 0 R 190 0 R 191 0 R 192 0 R 193 0 R 194 0 R 195 0 R 196 0 R 197 0 R 198 0 R 199 0 R 200 0 R 201 0 R 202 0 R 203 0 R 204 0 R 205 0 R 206 0 R 207 0 R 208 0 R 209 0 R 210 0 R 211 0 R 212 0 R 213 0 R]/Contents 178 0 R >> endobj 216 0 obj <> /Annots[219 0 R 220 0 R 221 0 R 222 0 R 223 0 R 224 0 R 225 0 R 226 0 R 227 0 R 228 0 R 229 0 R 230 0 R 231 0 R 232 0 R 233 0 R 234 0 R 235 0 R 236 0 R 237 0 R 238 0 R 239 0 R 240 0 R 241 0 R 242 0 R 243 0 R 244 0 R 245 0 R 246 0 R 247 0 R 248 0 R]/Contents 217 0 R >> endobj 251 0 obj <> /Annots[254 0 R 255 0 R 256 0 R 257 0 R 258 0 R 259 0 R 260 0 R 261 0 R 262 0 R 263 0 R 264 0 R 265 0 R 266 0 R 267 0 R 268 0 R 269 0 R 270 0 R 271 0 R 272 0 R 273 0 R 274 0 R 275 0 R 276 0 R 277 0 R 278 0 R 279 0 R 280 0 R 281 0 R 282 0 R 283 0 R 284 0 R 285 0 R]/Contents 252 0 R >> endobj 288 0 obj <> /Annots[291 0 R 292 0 R 293 0 R 294 0 R 295 0 R 296 0 R 297 0 R]/Contents 289 0 R >> endobj 300 0 obj <> /Contents 301 0 R >> endobj 305 0 obj <> /Contents 306 0 R >> endobj 310 0 obj <> /Contents 311 0 R >> endobj 317 0 obj <> /Contents 318 0 R >> endobj 322 0 obj <> /Contents 323 0 R >> endobj 327 0 obj <> /Contents 328 0 R >> endobj 332 0 obj <> /Contents 333 0 R >> endobj 337 0 obj <> /Contents 338 0 R >> endobj 342 0 obj <> /Contents 343 0 R >> endobj 347 0 obj <> /Contents 348 0 R >> endobj 352 0 obj <> /Contents 353 0 R >> endobj 357 0 obj <> /Contents 358 0 R >> endobj 362 0 obj <> /Contents 363 0 R >> endobj 367 0 obj <> /Contents 368 0 R >> endobj 374 0 obj <> /Contents 375 0 R >> endobj 379 0 obj <> /Contents 380 0 R >> endobj 384 0 obj <> /Contents 385 0 R >> endobj 389 0 obj <> /Contents 390 0 R >> endobj 394 0 obj <> /Contents 395 0 R >> endobj 399 0 obj <> /Contents 400 0 R >> endobj 404 0 obj <> /Contents 405 0 R >> endobj 409 0 obj <> /Contents 410 0 R >> endobj 414 0 obj <> /Contents 415 0 R >> endobj 419 0 obj <> /Contents 420 0 R >> endobj 424 0 obj <> /Contents 425 0 R >> endobj 429 0 obj <> /Contents 430 0 R >> endobj 434 0 obj <> /Contents 435 0 R >> endobj 439 0 obj <> /Contents 440 0 R >> endobj 444 0 obj <> /Contents 445 0 R >> endobj 449 0 obj <> /Contents 450 0 R >> endobj 454 0 obj <> /Contents 455 0 R >> endobj 459 0 obj <> /Contents 460 0 R >> endobj 466 0 obj <> /Contents 467 0 R >> endobj 471 0 obj <> /Contents 472 0 R >> endobj 476 0 obj <> /Contents 477 0 R >> endobj 481 0 obj <> /Contents 482 0 R >> endobj 486 0 obj <> /Contents 487 0 R >> endobj 491 0 obj <> /Contents 492 0 R >> endobj 496 0 obj <> /Contents 497 0 R >> endobj 501 0 obj <> /Contents 502 0 R >> endobj 506 0 obj <> /Contents 507 0 R >> endobj 511 0 obj <> /Contents 512 0 R >> endobj 516 0 obj <> /Contents 517 0 R >> endobj 521 0 obj <> /Contents 522 0 R >> endobj 526 0 obj <> /Contents 527 0 R >> endobj 531 0 obj <> /Contents 532 0 R >> endobj 536 0 obj <> /Contents 537 0 R >> endobj 541 0 obj <> /Contents 542 0 R >> endobj 546 0 obj <> /Contents 547 0 R >> endobj 551 0 obj <> /Contents 552 0 R >> endobj 556 0 obj <> /Contents 557 0 R >> endobj 561 0 obj <> /Contents 562 0 R >> endobj 566 0 obj <> /Contents 567 0 R >> endobj 571 0 obj <> /Contents 572 0 R >> endobj 576 0 obj <> /Contents 577 0 R >> endobj 581 0 obj <> /Contents 582 0 R >> endobj 586 0 obj <> /Contents 587 0 R >> endobj 591 0 obj <> /Contents 592 0 R >> endobj 596 0 obj <> /Contents 597 0 R >> endobj 601 0 obj <> /Contents 602 0 R >> endobj 606 0 obj <> /Contents 607 0 R >> endobj 611 0 obj <> /Contents 612 0 R >> endobj 616 0 obj <> /Contents 617 0 R >> endobj 621 0 obj <> /Contents 622 0 R >> endobj 626 0 obj <> /Contents 627 0 R >> endobj 631 0 obj <> /Contents 632 0 R >> endobj 636 0 obj <> /Contents 637 0 R >> endobj 641 0 obj <> /Contents 642 0 R >> endobj 646 0 obj <> /Contents 647 0 R >> endobj 651 0 obj <> /Contents 652 0 R >> endobj 656 0 obj <> /Contents 657 0 R >> endobj 661 0 obj <> /Contents 662 0 R >> endobj 666 0 obj <> /Contents 667 0 R >> endobj 671 0 obj <> /Contents 672 0 R >> endobj 676 0 obj <> /Contents 677 0 R >> endobj 681 0 obj <> /Contents 682 0 R >> endobj 686 0 obj <> /Contents 687 0 R >> endobj 691 0 obj <> /Contents 692 0 R >> endobj 696 0 obj <> /Contents 697 0 R >> endobj 701 0 obj <> /Contents 702 0 R >> endobj 706 0 obj <> /Contents 707 0 R >> endobj 711 0 obj <> /Contents 712 0 R >> endobj 716 0 obj <> /Contents 717 0 R >> endobj 721 0 obj <> /Contents 722 0 R >> endobj 726 0 obj <> /Contents 727 0 R >> endobj 731 0 obj <> /Contents 732 0 R >> endobj 736 0 obj <> /Contents 737 0 R >> endobj 741 0 obj <> /Contents 742 0 R >> endobj 746 0 obj <> /Contents 747 0 R >> endobj 751 0 obj <> /Contents 752 0 R >> endobj 758 0 obj <> /Contents 759 0 R >> endobj 763 0 obj <> /Contents 764 0 R >> endobj 768 0 obj <> /Contents 769 0 R >> endobj 773 0 obj <> /Contents 774 0 R >> endobj 778 0 obj <> /Contents 779 0 R >> endobj 783 0 obj <> /Contents 784 0 R >> endobj 788 0 obj <> /Contents 789 0 R >> endobj 793 0 obj <> /Contents 794 0 R >> endobj 798 0 obj <> /Contents 799 0 R >> endobj 803 0 obj <> /Contents 804 0 R >> endobj 808 0 obj <> /Contents 809 0 R >> endobj 813 0 obj <> /Contents 814 0 R >> endobj 818 0 obj <> /Contents 819 0 R >> endobj 823 0 obj <> /Contents 824 0 R >> endobj 828 0 obj <> /Contents 829 0 R >> endobj 833 0 obj <> /Contents 834 0 R >> endobj 838 0 obj <> /Contents 839 0 R >> endobj 843 0 obj <> /Contents 844 0 R >> endobj 848 0 obj <> /Contents 849 0 R >> endobj 853 0 obj <> /Contents 854 0 R >> endobj 858 0 obj <> /Contents 859 0 R >> endobj 863 0 obj <> /Contents 864 0 R >> endobj 868 0 obj <> /Contents 869 0 R >> endobj 873 0 obj <> /Contents 874 0 R >> endobj 878 0 obj <> /Contents 879 0 R >> endobj 883 0 obj <> /Contents 884 0 R >> endobj 888 0 obj <> /Contents 889 0 R >> endobj 893 0 obj <> /Contents 894 0 R >> endobj 898 0 obj <> /Contents 899 0 R >> endobj 903 0 obj <> /Contents 904 0 R >> endobj 908 0 obj <> /Contents 909 0 R >> endobj 913 0 obj <> /Contents 914 0 R >> endobj 918 0 obj <> /Contents 919 0 R >> endobj 923 0 obj <> /Contents 924 0 R >> endobj 928 0 obj <> /Contents 929 0 R >> endobj 933 0 obj <> /Contents 934 0 R >> endobj 938 0 obj <> /Contents 939 0 R >> endobj 943 0 obj <> /Contents 944 0 R >> endobj 948 0 obj <> /Contents 949 0 R >> endobj 953 0 obj <> /Contents 954 0 R >> endobj 958 0 obj <> /Contents 959 0 R >> endobj 963 0 obj <> /Contents 964 0 R >> endobj 968 0 obj <> /Contents 969 0 R >> endobj 973 0 obj <> /Contents 974 0 R >> endobj 978 0 obj <> /Contents 979 0 R >> endobj 983 0 obj <> /Contents 984 0 R >> endobj 988 0 obj <> /Contents 989 0 R >> endobj 993 0 obj <> /Contents 994 0 R >> endobj 998 0 obj <> /Contents 999 0 R >> endobj 1003 0 obj <> /Contents 1004 0 R >> endobj 1008 0 obj <> /Contents 1009 0 R >> endobj 1013 0 obj <> /Contents 1014 0 R >> endobj 1018 0 obj <> /Contents 1019 0 R >> endobj 1023 0 obj <> /Contents 1024 0 R >> endobj 1028 0 obj <> /Contents 1029 0 R >> endobj 1033 0 obj <> /Contents 1034 0 R >> endobj 1038 0 obj <> /Contents 1039 0 R >> endobj 1043 0 obj <> /Contents 1044 0 R >> endobj 1048 0 obj <> /Contents 1049 0 R >> endobj 1053 0 obj <> /Contents 1054 0 R >> endobj 1058 0 obj <> /Contents 1059 0 R >> endobj 1063 0 obj <> /Contents 1064 0 R >> endobj 1068 0 obj <> /Contents 1069 0 R >> endobj 1073 0 obj <> /Contents 1074 0 R >> endobj 1078 0 obj <> /Contents 1079 0 R >> endobj 1083 0 obj <> /Contents 1084 0 R >> endobj 1088 0 obj <> /Contents 1089 0 R >> endobj 1093 0 obj <> /Contents 1094 0 R >> endobj 1098 0 obj <> /Contents 1099 0 R >> endobj 1103 0 obj <> /Contents 1104 0 R >> endobj 1108 0 obj <> /Contents 1109 0 R >> endobj 1113 0 obj <> /Contents 1114 0 R >> endobj 1118 0 obj <> /Contents 1119 0 R >> endobj 1123 0 obj <> /Contents 1124 0 R >> endobj 1128 0 obj <> /Contents 1129 0 R >> endobj 1133 0 obj <> /Contents 1134 0 R >> endobj 1138 0 obj <> /Contents 1139 0 R >> endobj 1143 0 obj <> /Contents 1144 0 R >> endobj 1148 0 obj <> /Contents 1149 0 R >> endobj 1153 0 obj <> /Contents 1154 0 R >> endobj 1158 0 obj <> /Contents 1159 0 R >> endobj 1163 0 obj <> /Contents 1164 0 R >> endobj 1168 0 obj <> /Contents 1169 0 R >> endobj 1173 0 obj <> /Annots[1176 0 R 1177 0 R 1178 0 R 1179 0 R 1180 0 R 1181 0 R 1182 0 R 1183 0 R 1184 0 R 1185 0 R 1186 0 R 1187 0 R 1188 0 R 1189 0 R 1190 0 R 1191 0 R 1192 0 R 1193 0 R 1194 0 R 1195 0 R 1196 0 R 1197 0 R 1198 0 R 1199 0 R 1200 0 R 1201 0 R 1202 0 R 1203 0 R 1204 0 R 1205 0 R 1206 0 R 1207 0 R 1208 0 R 1209 0 R 1210 0 R 1211 0 R 1212 0 R 1213 0 R 1214 0 R 1215 0 R 1216 0 R 1217 0 R 1218 0 R 1219 0 R 1220 0 R 1221 0 R 1222 0 R 1223 0 R 1224 0 R 1225 0 R 1226 0 R 1227 0 R 1228 0 R 1229 0 R 1230 0 R 1231 0 R 1232 0 R 1233 0 R 1234 0 R 1235 0 R 1236 0 R 1237 0 R 1238 0 R 1239 0 R 1240 0 R 1241 0 R 1242 0 R 1243 0 R 1244 0 R 1245 0 R 1246 0 R 1247 0 R 1248 0 R 1249 0 R 1250 0 R 1251 0 R 1252 0 R 1253 0 R 1254 0 R 1255 0 R 1256 0 R 1257 0 R 1258 0 R 1259 0 R 1260 0 R 1261 0 R 1262 0 R 1263 0 R 1264 0 R 1265 0 R 1266 0 R 1267 0 R 1268 0 R 1269 0 R 1270 0 R 1271 0 R 1272 0 R 1273 0 R]/Contents 1174 0 R >> endobj 1276 0 obj <> /Annots[1279 0 R 1280 0 R 1281 0 R 1282 0 R 1283 0 R 1284 0 R 1285 0 R 1286 0 R 1287 0 R 1288 0 R 1289 0 R 1290 0 R 1291 0 R 1292 0 R 1293 0 R 1294 0 R 1295 0 R 1296 0 R 1297 0 R 1298 0 R 1299 0 R 1300 0 R 1301 0 R 1302 0 R 1303 0 R 1304 0 R 1305 0 R 1306 0 R 1307 0 R 1308 0 R 1309 0 R 1310 0 R 1311 0 R 1312 0 R 1313 0 R 1314 0 R 1315 0 R 1316 0 R 1317 0 R 1318 0 R 1319 0 R 1320 0 R 1321 0 R 1322 0 R 1323 0 R 1324 0 R 1325 0 R 1326 0 R 1327 0 R 1328 0 R 1329 0 R 1330 0 R 1331 0 R 1332 0 R 1333 0 R 1334 0 R 1335 0 R 1336 0 R 1337 0 R 1338 0 R 1339 0 R 1340 0 R 1341 0 R 1342 0 R 1343 0 R 1344 0 R 1345 0 R 1346 0 R 1347 0 R 1348 0 R 1349 0 R 1350 0 R 1351 0 R 1352 0 R 1353 0 R 1354 0 R 1355 0 R 1356 0 R 1357 0 R 1358 0 R 1359 0 R 1360 0 R 1361 0 R 1362 0 R 1363 0 R 1364 0 R 1365 0 R 1366 0 R 1367 0 R 1368 0 R 1369 0 R 1370 0 R 1371 0 R 1372 0 R 1373 0 R 1374 0 R 1375 0 R 1376 0 R 1377 0 R 1378 0 R 1379 0 R 1380 0 R 1381 0 R 1382 0 R 1383 0 R 1384 0 R 1385 0 R 1386 0 R 1387 0 R 1388 0 R 1389 0 R 1390 0 R 1391 0 R 1392 0 R 1393 0 R 1394 0 R 1395 0 R 1396 0 R 1397 0 R 1398 0 R 1399 0 R 1400 0 R 1401 0 R 1402 0 R 1403 0 R 1404 0 R 1405 0 R 1406 0 R 1407 0 R 1408 0 R 1409 0 R 1410 0 R 1411 0 R 1412 0 R 1413 0 R 1414 0 R 1415 0 R 1416 0 R 1417 0 R 1418 0 R 1419 0 R 1420 0 R 1421 0 R 1422 0 R 1423 0 R 1424 0 R 1425 0 R]/Contents 1277 0 R >> endobj 1428 0 obj <> /Annots[1431 0 R 1432 0 R 1433 0 R 1434 0 R 1435 0 R 1436 0 R 1437 0 R 1438 0 R 1439 0 R 1440 0 R 1441 0 R 1442 0 R 1443 0 R 1444 0 R 1445 0 R 1446 0 R 1447 0 R 1448 0 R 1449 0 R 1450 0 R 1451 0 R 1452 0 R 1453 0 R 1454 0 R 1455 0 R 1456 0 R 1457 0 R 1458 0 R 1459 0 R 1460 0 R 1461 0 R 1462 0 R 1463 0 R]/Contents 1429 0 R >> endobj 1466 0 obj <> /Annots[1469 0 R 1470 0 R 1471 0 R 1472 0 R 1473 0 R 1474 0 R 1475 0 R 1476 0 R 1477 0 R 1478 0 R 1479 0 R 1480 0 R 1481 0 R 1482 0 R 1483 0 R 1484 0 R 1485 0 R 1486 0 R 1487 0 R 1488 0 R 1489 0 R 1490 0 R 1491 0 R 1492 0 R 1493 0 R 1494 0 R 1495 0 R 1496 0 R 1497 0 R 1498 0 R 1499 0 R 1500 0 R 1501 0 R 1502 0 R 1503 0 R 1504 0 R 1505 0 R 1506 0 R 1507 0 R 1508 0 R 1509 0 R 1510 0 R 1511 0 R 1512 0 R 1513 0 R 1514 0 R 1515 0 R 1516 0 R 1517 0 R 1518 0 R 1519 0 R 1520 0 R 1521 0 R 1522 0 R 1523 0 R 1524 0 R 1525 0 R 1526 0 R 1527 0 R 1528 0 R 1529 0 R 1530 0 R 1531 0 R 1532 0 R 1533 0 R 1534 0 R 1535 0 R 1536 0 R 1537 0 R 1538 0 R 1539 0 R 1540 0 R 1541 0 R 1542 0 R 1543 0 R 1544 0 R 1545 0 R 1546 0 R 1547 0 R 1548 0 R 1549 0 R 1550 0 R 1551 0 R 1552 0 R 1553 0 R 1554 0 R 1555 0 R 1556 0 R 1557 0 R 1558 0 R 1559 0 R 1560 0 R 1561 0 R 1562 0 R 1563 0 R 1564 0 R 1565 0 R 1566 0 R 1567 0 R 1568 0 R 1569 0 R 1570 0 R 1571 0 R 1572 0 R 1573 0 R 1574 0 R 1575 0 R 1576 0 R 1577 0 R 1578 0 R 1579 0 R 1580 0 R 1581 0 R 1582 0 R 1583 0 R 1584 0 R 1585 0 R 1586 0 R 1587 0 R 1588 0 R 1589 0 R 1590 0 R 1591 0 R 1592 0 R 1593 0 R 1594 0 R 1595 0 R 1596 0 R 1597 0 R 1598 0 R 1599 0 R 1600 0 R 1601 0 R 1602 0 R 1603 0 R 1604 0 R 1605 0 R 1606 0 R 1607 0 R 1608 0 R 1609 0 R 1610 0 R 1611 0 R 1612 0 R 1613 0 R 1614 0 R 1615 0 R 1616 0 R 1617 0 R 1618 0 R 1619 0 R 1620 0 R 1621 0 R 1622 0 R 1623 0 R 1624 0 R 1625 0 R 1626 0 R 1627 0 R 1628 0 R 1629 0 R 1630 0 R 1631 0 R 1632 0 R 1633 0 R 1634 0 R 1635 0 R 1636 0 R 1637 0 R 1638 0 R 1639 0 R 1640 0 R 1641 0 R 1642 0 R 1643 0 R 1644 0 R 1645 0 R 1646 0 R 1647 0 R 1648 0 R 1649 0 R 1650 0 R 1651 0 R 1652 0 R 1653 0 R 1654 0 R 1655 0 R 1656 0 R 1657 0 R 1658 0 R 1659 0 R 1660 0 R 1661 0 R 1662 0 R 1663 0 R 1664 0 R 1665 0 R 1666 0 R 1667 0 R 1668 0 R 1669 0 R 1670 0 R 1671 0 R 1672 0 R 1673 0 R 1674 0 R 1675 0 R 1676 0 R 1677 0 R 1678 0 R 1679 0 R 1680 0 R 1681 0 R 1682 0 R 1683 0 R 1684 0 R 1685 0 R 1686 0 R 1687 0 R 1688 0 R 1689 0 R 1690 0 R 1691 0 R 1692 0 R 1693 0 R 1694 0 R 1695 0 R 1696 0 R 1697 0 R 1698 0 R 1699 0 R 1700 0 R 1701 0 R 1702 0 R 1703 0 R 1704 0 R 1705 0 R 1706 0 R 1707 0 R 1708 0 R 1709 0 R 1710 0 R 1711 0 R]/Contents 1467 0 R >> endobj 1714 0 obj <> /Annots[1717 0 R 1718 0 R 1719 0 R 1720 0 R 1721 0 R 1722 0 R 1723 0 R 1724 0 R 1725 0 R 1726 0 R 1727 0 R 1728 0 R 1729 0 R 1730 0 R]/Contents 1715 0 R >> endobj 1733 0 obj <> /Contents 1734 0 R >> endobj 1738 0 obj <> /Contents 1739 0 R >> endobj 1743 0 obj <> /Contents 1744 0 R >> endobj 1748 0 obj <> /Contents 1749 0 R >> endobj 1753 0 obj <> /Contents 1754 0 R >> endobj 1758 0 obj <> /Contents 1759 0 R >> endobj 1763 0 obj <> /Contents 1764 0 R >> endobj 1768 0 obj <> /Contents 1769 0 R >> endobj 1773 0 obj <> /Contents 1774 0 R >> endobj 1778 0 obj <> /Contents 1779 0 R >> endobj 1783 0 obj <> /Contents 1784 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R 142 0 R 147 0 R 177 0 R 216 0 R 251 0 R 288 0 R 300 0 R 305 0 R 310 0 R 317 0 R 322 0 R 327 0 R 332 0 R 337 0 R 342 0 R 347 0 R 352 0 R 357 0 R 362 0 R 367 0 R 374 0 R 379 0 R 384 0 R 389 0 R 394 0 R 399 0 R 404 0 R 409 0 R 414 0 R 419 0 R 424 0 R 429 0 R 434 0 R 439 0 R 444 0 R 449 0 R 454 0 R 459 0 R 466 0 R 471 0 R 476 0 R 481 0 R 486 0 R 491 0 R 496 0 R 501 0 R 506 0 R 511 0 R 516 0 R 521 0 R 526 0 R 531 0 R 536 0 R 541 0 R 546 0 R 551 0 R 556 0 R 561 0 R 566 0 R 571 0 R 576 0 R 581 0 R 586 0 R 591 0 R 596 0 R 601 0 R 606 0 R 611 0 R 616 0 R 621 0 R 626 0 R 631 0 R 636 0 R 641 0 R 646 0 R 651 0 R 656 0 R 661 0 R 666 0 R 671 0 R 676 0 R 681 0 R 686 0 R 691 0 R 696 0 R 701 0 R 706 0 R 711 0 R 716 0 R 721 0 R 726 0 R 731 0 R 736 0 R 741 0 R 746 0 R 751 0 R 758 0 R 763 0 R 768 0 R 773 0 R 778 0 R 783 0 R 788 0 R 793 0 R 798 0 R 803 0 R 808 0 R 813 0 R 818 0 R 823 0 R 828 0 R 833 0 R 838 0 R 843 0 R 848 0 R 853 0 R 858 0 R 863 0 R 868 0 R 873 0 R 878 0 R 883 0 R 888 0 R 893 0 R 898 0 R 903 0 R 908 0 R 913 0 R 918 0 R 923 0 R 928 0 R 933 0 R 938 0 R 943 0 R 948 0 R 953 0 R 958 0 R 963 0 R 968 0 R 973 0 R 978 0 R 983 0 R 988 0 R 993 0 R 998 0 R 1003 0 R 1008 0 R 1013 0 R 1018 0 R 1023 0 R 1028 0 R 1033 0 R 1038 0 R 1043 0 R 1048 0 R 1053 0 R 1058 0 R 1063 0 R 1068 0 R 1073 0 R 1078 0 R 1083 0 R 1088 0 R 1093 0 R 1098 0 R 1103 0 R 1108 0 R 1113 0 R 1118 0 R 1123 0 R 1128 0 R 1133 0 R 1138 0 R 1143 0 R 1148 0 R 1153 0 R 1158 0 R 1163 0 R 1168 0 R 1173 0 R 1276 0 R 1428 0 R 1466 0 R 1714 0 R 1733 0 R 1738 0 R 1743 0 R 1748 0 R 1753 0 R 1758 0 R 1763 0 R 1768 0 R 1773 0 R 1778 0 R 1783 0 R ] /Count 196 >> endobj 6 0 obj << /Count 16 /First 7 0 R /Last 130 0 R >> endobj 1 0 obj <> 4 << /S /D >>] >> /Metadata 1802 0 R >> endobj 8 0 obj << /Title( A Brief Overview) /Dest/section.1.1 /Parent 7 0 R /Next 9 0 R >> endobj 9 0 obj << /Title(Sources of FITS Software and Information) /Dest/section.1.2 /Parent 7 0 R /Prev 8 0 R /Next 10 0 R >> endobj 10 0 obj << /Title(Acknowledgments) /Dest/section.1.3 /Parent 7 0 R /Prev 9 0 R /Next 11 0 R >> endobj 11 0 obj << /Title(Legal Stuff) /Dest/section.1.4 /Parent 7 0 R /Prev 10 0 R >> endobj 7 0 obj << /Title(Introduction ) /Dest/chapter.1 /Count -4 /Parent 6 0 R /Next 12 0 R /First 8 0 R /Last 11 0 R >> endobj 14 0 obj << /Title(Unix Systems) /Dest/subsection.2.1.1 /Parent 13 0 R /Next 15 0 R >> endobj 15 0 obj << /Title(VMS) /Dest/subsection.2.1.2 /Parent 13 0 R /Prev 14 0 R /Next 16 0 R >> endobj 16 0 obj << /Title(Windows PCs) /Dest/subsection.2.1.3 /Parent 13 0 R /Prev 15 0 R /Next 17 0 R >> endobj 17 0 obj << /Title(Macintosh PCs) /Dest/subsection.2.1.4 /Parent 13 0 R /Prev 16 0 R >> endobj 13 0 obj << /Title(Building the Library) /Dest/section.2.1 /Count -4 /Parent 12 0 R /Next 18 0 R /First 14 0 R /Last 17 0 R >> endobj 18 0 obj << /Title(Testing the Library) /Dest/section.2.2 /Parent 12 0 R /Prev 13 0 R /Next 19 0 R >> endobj 19 0 obj << /Title(Linking Programs with CFITSIO) /Dest/section.2.3 /Parent 12 0 R /Prev 18 0 R /Next 20 0 R >> endobj 20 0 obj << /Title(Using CFITSIO in Multi-threaded Environments) /Dest/section.2.4 /Parent 12 0 R /Prev 19 0 R /Next 21 0 R >> endobj 21 0 obj << /Title(Getting Started with CFITSIO) /Dest/section.2.5 /Parent 12 0 R /Prev 20 0 R /Next 22 0 R >> endobj 22 0 obj << /Title(Example Program) /Dest/section.2.6 /Parent 12 0 R /Prev 21 0 R >> endobj 12 0 obj << /Title( Creating the CFITSIO Library ) /Dest/chapter.2 /Count -6 /Parent 6 0 R /Prev 7 0 R /Next 23 0 R /First 13 0 R /Last 22 0 R >> endobj 23 0 obj << /Title( A FITS Primer ) /Dest/chapter.3 /Parent 6 0 R /Prev 12 0 R /Next 24 0 R >> endobj 25 0 obj << /Title(CFITSIO Definitions) /Dest/section.4.1 /Parent 24 0 R /Next 26 0 R >> endobj 26 0 obj << /Title(Current Header Data Unit \(CHDU\)) /Dest/section.4.2 /Parent 24 0 R /Prev 25 0 R /Next 27 0 R >> endobj 27 0 obj << /Title(Function Names and Variable Datatypes) /Dest/section.4.3 /Parent 24 0 R /Prev 26 0 R /Next 28 0 R >> endobj 28 0 obj << /Title(Support for Unsigned Integers and Signed Bytes) /Dest/section.4.4 /Parent 24 0 R /Prev 27 0 R /Next 29 0 R >> endobj 29 0 obj << /Title(Dealing with Character Strings) /Dest/section.4.5 /Parent 24 0 R /Prev 28 0 R /Next 30 0 R >> endobj 30 0 obj << /Title(Implicit Data Type Conversion) /Dest/section.4.6 /Parent 24 0 R /Prev 29 0 R /Next 31 0 R >> endobj 31 0 obj << /Title(Data Scaling) /Dest/section.4.7 /Parent 24 0 R /Prev 30 0 R /Next 32 0 R >> endobj 32 0 obj << /Title(Support for IEEE Special Values) /Dest/section.4.8 /Parent 24 0 R /Prev 31 0 R /Next 33 0 R >> endobj 33 0 obj << /Title(Error Status Values and the Error Message Stack) /Dest/section.4.9 /Parent 24 0 R /Prev 32 0 R /Next 34 0 R >> endobj 34 0 obj << /Title(Variable-Length Arrays in Binary Tables) /Dest/section.4.10 /Parent 24 0 R /Prev 33 0 R /Next 35 0 R >> endobj 35 0 obj << /Title(Multiple Access to the Same FITS File) /Dest/section.4.11 /Parent 24 0 R /Prev 34 0 R /Next 36 0 R >> endobj 36 0 obj << /Title(When the Final Size of the FITS HDU is Unknown) /Dest/section.4.12 /Parent 24 0 R /Prev 35 0 R /Next 37 0 R >> endobj 37 0 obj << /Title(CFITSIO Size Limitations) /Dest/section.4.13 /Parent 24 0 R /Prev 36 0 R >> endobj 24 0 obj << /Title( Programming Guidelines ) /Dest/chapter.4 /Count -13 /Parent 6 0 R /Prev 23 0 R /Next 38 0 R /First 25 0 R /Last 37 0 R >> endobj 39 0 obj << /Title(CFITSIO Error Status Routines) /Dest/section.5.1 /Parent 38 0 R /Next 40 0 R >> endobj 40 0 obj << /Title(FITS File Access Routines) /Dest/section.5.2 /Parent 38 0 R /Prev 39 0 R /Next 41 0 R >> endobj 41 0 obj << /Title(HDU Access Routines) /Dest/section.5.3 /Parent 38 0 R /Prev 40 0 R /Next 42 0 R >> endobj 43 0 obj << /Title(Keyword Reading Routines) /Dest/subsection.5.4.1 /Parent 42 0 R /Next 44 0 R >> endobj 44 0 obj << /Title(Keyword Writing Routines) /Dest/subsection.5.4.2 /Parent 42 0 R /Prev 43 0 R >> endobj 42 0 obj << /Title(Header Keyword Read/Write Routines) /Dest/section.5.4 /Count -2 /Parent 38 0 R /Prev 41 0 R /Next 45 0 R /First 43 0 R /Last 44 0 R >> endobj 45 0 obj << /Title(Primary Array or IMAGE Extension I/O Routines) /Dest/section.5.5 /Parent 38 0 R /Prev 42 0 R /Next 46 0 R >> endobj 46 0 obj << /Title(Image Compression) /Dest/section.5.6 /Parent 38 0 R /Prev 45 0 R /Next 47 0 R >> endobj 48 0 obj << /Title(Create New Table) /Dest/subsection.5.7.1 /Parent 47 0 R /Next 49 0 R >> endobj 49 0 obj << /Title(Column Information Routines) /Dest/subsection.5.7.2 /Parent 47 0 R /Prev 48 0 R /Next 50 0 R >> endobj 50 0 obj << /Title(Routines to Edit Rows or Columns) /Dest/subsection.5.7.3 /Parent 47 0 R /Prev 49 0 R /Next 51 0 R >> endobj 51 0 obj << /Title(Read and Write Column Data Routines) /Dest/subsection.5.7.4 /Parent 47 0 R /Prev 50 0 R /Next 52 0 R >> endobj 52 0 obj << /Title(Row Selection and Calculator Routines) /Dest/subsection.5.7.5 /Parent 47 0 R /Prev 51 0 R /Next 53 0 R >> endobj 53 0 obj << /Title(Column Binning or Histogramming Routines) /Dest/subsection.5.7.6 /Parent 47 0 R /Prev 52 0 R >> endobj 47 0 obj << /Title(ASCII and Binary Table Routines) /Dest/section.5.7 /Count -6 /Parent 38 0 R /Prev 46 0 R /Next 54 0 R /First 48 0 R /Last 53 0 R >> endobj 55 0 obj << /Title(File Checksum Routines) /Dest/subsection.5.8.1 /Parent 54 0 R /Next 56 0 R >> endobj 56 0 obj << /Title(Date and Time Utility Routines) /Dest/subsection.5.8.2 /Parent 54 0 R /Prev 55 0 R /Next 57 0 R >> endobj 57 0 obj << /Title(General Utility Routines) /Dest/subsection.5.8.3 /Parent 54 0 R /Prev 56 0 R >> endobj 54 0 obj << /Title(Utility Routines) /Dest/section.5.8 /Count -3 /Parent 38 0 R /Prev 47 0 R /First 55 0 R /Last 57 0 R >> endobj 38 0 obj << /Title(Basic CFITSIO Interface Routines ) /Dest/chapter.5 /Count -8 /Parent 6 0 R /Prev 24 0 R /Next 58 0 R /First 39 0 R /Last 54 0 R >> endobj 59 0 obj << /Title(The Iterator Work Function) /Dest/section.6.1 /Parent 58 0 R /Next 60 0 R >> endobj 60 0 obj << /Title(The Iterator Driver Function) /Dest/section.6.2 /Parent 58 0 R /Prev 59 0 R /Next 61 0 R >> endobj 61 0 obj << /Title(Guidelines for Using the Iterator Function) /Dest/section.6.3 /Parent 58 0 R /Prev 60 0 R /Next 62 0 R >> endobj 62 0 obj << /Title(Complete List of Iterator Routines) /Dest/section.6.4 /Parent 58 0 R /Prev 61 0 R >> endobj 58 0 obj << /Title( The CFITSIO Iterator Function ) /Dest/chapter.6 /Count -4 /Parent 6 0 R /Prev 38 0 R /Next 63 0 R /First 59 0 R /Last 62 0 R >> endobj 64 0 obj << /Title( Self-contained WCS Routines) /Dest/section.7.1 /Parent 63 0 R >> endobj 63 0 obj << /Title( World Coordinate System Routines ) /Dest/chapter.7 /Count -1 /Parent 6 0 R /Prev 58 0 R /Next 65 0 R /First 64 0 R /Last 64 0 R >> endobj 66 0 obj << /Title(Grouping Table Routines) /Dest/section.8.1 /Parent 65 0 R /Next 67 0 R >> endobj 67 0 obj << /Title(Group Member Routines) /Dest/section.8.2 /Parent 65 0 R /Prev 66 0 R >> endobj 65 0 obj << /Title( Hierarchical Grouping Routines ) /Dest/chapter.8 /Count -2 /Parent 6 0 R /Prev 63 0 R /Next 68 0 R /First 66 0 R /Last 67 0 R >> endobj 69 0 obj << /Title(FITS File Access Routines) /Dest/section.9.1 /Parent 68 0 R /Next 70 0 R >> endobj 70 0 obj << /Title(HDU Access Routines) /Dest/section.9.2 /Parent 68 0 R /Prev 69 0 R /Next 71 0 R >> endobj 72 0 obj << /Title(Header Information Routines) /Dest/subsection.9.3.1 /Parent 71 0 R /Next 73 0 R >> endobj 73 0 obj << /Title(Read and Write the Required Keywords) /Dest/subsection.9.3.2 /Parent 71 0 R /Prev 72 0 R /Next 74 0 R >> endobj 74 0 obj << /Title(Write Keyword Routines) /Dest/subsection.9.3.3 /Parent 71 0 R /Prev 73 0 R /Next 75 0 R >> endobj 75 0 obj << /Title(Insert Keyword Routines) /Dest/subsection.9.3.4 /Parent 71 0 R /Prev 74 0 R /Next 76 0 R >> endobj 76 0 obj << /Title(Read Keyword Routines) /Dest/subsection.9.3.5 /Parent 71 0 R /Prev 75 0 R /Next 77 0 R >> endobj 77 0 obj << /Title(Modify Keyword Routines) /Dest/subsection.9.3.6 /Parent 71 0 R /Prev 76 0 R /Next 78 0 R >> endobj 78 0 obj << /Title(Update Keyword Routines) /Dest/subsection.9.3.7 /Parent 71 0 R /Prev 77 0 R >> endobj 71 0 obj << /Title(Specialized Header Keyword Routines) /Dest/section.9.3 /Count -7 /Parent 68 0 R /Prev 70 0 R /Next 79 0 R /First 72 0 R /Last 78 0 R >> endobj 79 0 obj << /Title(Define Data Scaling and Undefined Pixel Parameters) /Dest/section.9.4 /Parent 68 0 R /Prev 71 0 R /Next 80 0 R >> endobj 80 0 obj << /Title(Specialized FITS Primary Array or IMAGE Extension I/O Routines) /Dest/section.9.5 /Parent 68 0 R /Prev 79 0 R /Next 81 0 R >> endobj 82 0 obj << /Title(General Column Routines) /Dest/subsection.9.6.1 /Parent 81 0 R /Next 83 0 R >> endobj 83 0 obj << /Title(Low-Level Table Access Routines) /Dest/subsection.9.6.2 /Parent 81 0 R /Prev 82 0 R /Next 84 0 R >> endobj 84 0 obj << /Title(Write Column Data Routines) /Dest/subsection.9.6.3 /Parent 81 0 R /Prev 83 0 R /Next 85 0 R >> endobj 85 0 obj << /Title(Read Column Data Routines) /Dest/subsection.9.6.4 /Parent 81 0 R /Prev 84 0 R >> endobj 81 0 obj << /Title(Specialized FITS ASCII and Binary Table Routines) /Dest/section.9.6 /Count -4 /Parent 68 0 R /Prev 80 0 R /First 82 0 R /Last 85 0 R >> endobj 68 0 obj << /Title( Specialized CFITSIO Interface Routines ) /Dest/chapter.9 /Count -6 /Parent 6 0 R /Prev 65 0 R /Next 86 0 R /First 69 0 R /Last 81 0 R >> endobj 87 0 obj << /Title(Overview) /Dest/section.10.1 /Parent 86 0 R /Next 88 0 R >> endobj 89 0 obj << /Title(Notes about HTTP proxy servers) /Dest/subsection.10.2.1 /Parent 88 0 R /Next 90 0 R >> endobj 90 0 obj << /Title(Notes about HTTPS file access) /Dest/subsection.10.2.2 /Parent 88 0 R /Prev 89 0 R /Next 91 0 R >> endobj 91 0 obj << /Title(Notes about the stream filetype driver) /Dest/subsection.10.2.3 /Parent 88 0 R /Prev 90 0 R /Next 92 0 R >> endobj 92 0 obj << /Title(Notes about the gsiftp filetype) /Dest/subsection.10.2.4 /Parent 88 0 R /Prev 91 0 R /Next 93 0 R >> endobj 93 0 obj << /Title(Notes about the root filetype) /Dest/subsection.10.2.5 /Parent 88 0 R /Prev 92 0 R /Next 94 0 R >> endobj 94 0 obj << /Title(Notes about the shmem filetype:) /Dest/subsection.10.2.6 /Parent 88 0 R /Prev 93 0 R >> endobj 88 0 obj << /Title(Filetype) /Dest/section.10.2 /Count -6 /Parent 86 0 R /Prev 87 0 R /Next 95 0 R /First 89 0 R /Last 94 0 R >> endobj 95 0 obj << /Title(Base Filename) /Dest/section.10.3 /Parent 86 0 R /Prev 88 0 R /Next 96 0 R >> endobj 96 0 obj << /Title(Output File Name when Opening an Existing File) /Dest/section.10.4 /Parent 86 0 R /Prev 95 0 R /Next 97 0 R >> endobj 97 0 obj << /Title(Template File Name when Creating a New File) /Dest/section.10.5 /Parent 86 0 R /Prev 96 0 R /Next 98 0 R >> endobj 98 0 obj << /Title(Image Tile-Compression Specification) /Dest/section.10.6 /Parent 86 0 R /Prev 97 0 R /Next 99 0 R >> endobj 99 0 obj << /Title(HDU Location Specification) /Dest/section.10.7 /Parent 86 0 R /Prev 98 0 R /Next 100 0 R >> endobj 100 0 obj << /Title(Image Section) /Dest/section.10.8 /Parent 86 0 R /Prev 99 0 R /Next 101 0 R >> endobj 101 0 obj << /Title(Image Transform Filters) /Dest/section.10.9 /Parent 86 0 R /Prev 100 0 R /Next 102 0 R >> endobj 102 0 obj << /Title(Column and Keyword Filtering Specification) /Dest/section.10.10 /Parent 86 0 R /Prev 101 0 R /Next 103 0 R >> endobj 104 0 obj << /Title(General Syntax) /Dest/subsection.10.11.1 /Parent 103 0 R /Next 105 0 R >> endobj 105 0 obj << /Title(Bit Masks) /Dest/subsection.10.11.2 /Parent 103 0 R /Prev 104 0 R /Next 106 0 R >> endobj 106 0 obj << /Title(Vector Columns) /Dest/subsection.10.11.3 /Parent 103 0 R /Prev 105 0 R /Next 107 0 R >> endobj 107 0 obj << /Title(Good Time Interval Filtering) /Dest/subsection.10.11.4 /Parent 103 0 R /Prev 106 0 R /Next 108 0 R >> endobj 108 0 obj << /Title(Spatial Region Filtering) /Dest/subsection.10.11.5 /Parent 103 0 R /Prev 107 0 R /Next 109 0 R >> endobj 109 0 obj << /Title(Example Row Filters) /Dest/subsection.10.11.6 /Parent 103 0 R /Prev 108 0 R >> endobj 103 0 obj << /Title(Row Filtering Specification) /Dest/section.10.11 /Count -6 /Parent 86 0 R /Prev 102 0 R /Next 110 0 R /First 104 0 R /Last 109 0 R >> endobj 110 0 obj << /Title( Binning or Histogramming Specification) /Dest/section.10.12 /Parent 86 0 R /Prev 103 0 R >> endobj 86 0 obj << /Title( Extended File Name Syntax ) /Dest/chapter.10 /Count -12 /Parent 6 0 R /Prev 68 0 R /Next 111 0 R /First 87 0 R /Last 110 0 R >> endobj 112 0 obj << /Title(Detailed Template Line Format) /Dest/section.11.1 /Parent 111 0 R /Next 113 0 R >> endobj 113 0 obj << /Title(Auto-indexing of Keywords) /Dest/section.11.2 /Parent 111 0 R /Prev 112 0 R /Next 114 0 R >> endobj 114 0 obj << /Title(Template Parser Directives) /Dest/section.11.3 /Parent 111 0 R /Prev 113 0 R /Next 115 0 R >> endobj 115 0 obj << /Title(Formal Template Syntax) /Dest/section.11.4 /Parent 111 0 R /Prev 114 0 R /Next 116 0 R >> endobj 116 0 obj << /Title(Errors) /Dest/section.11.5 /Parent 111 0 R /Prev 115 0 R /Next 117 0 R >> endobj 117 0 obj << /Title(Examples) /Dest/section.11.6 /Parent 111 0 R /Prev 116 0 R >> endobj 111 0 obj << /Title(Template Files ) /Dest/chapter.11 /Count -6 /Parent 6 0 R /Prev 86 0 R /Next 118 0 R /First 112 0 R /Last 117 0 R >> endobj 119 0 obj << /Title(64-Bit Long Integers) /Dest/section.12.1 /Parent 118 0 R /Next 120 0 R >> endobj 120 0 obj << /Title(Long String Keyword Values.) /Dest/section.12.2 /Parent 118 0 R /Prev 119 0 R /Next 121 0 R >> endobj 121 0 obj << /Title(Arrays of Fixed-Length Strings in Binary Tables) /Dest/section.12.3 /Parent 118 0 R /Prev 120 0 R /Next 122 0 R >> endobj 122 0 obj << /Title(Keyword Units Strings) /Dest/section.12.4 /Parent 118 0 R /Prev 121 0 R /Next 123 0 R >> endobj 123 0 obj << /Title(HIERARCH Convention for Extended Keyword Names) /Dest/section.12.5 /Parent 118 0 R /Prev 122 0 R /Next 124 0 R >> endobj 124 0 obj << /Title(Tile-Compressed Image Format) /Dest/section.12.6 /Parent 118 0 R /Prev 123 0 R >> endobj 118 0 obj << /Title( Local FITS Conventions ) /Dest/chapter.12 /Count -6 /Parent 6 0 R /Prev 111 0 R /Next 125 0 R /First 119 0 R /Last 124 0 R >> endobj 126 0 obj << /Title(How CFITSIO Manages Data I/O) /Dest/section.13.1 /Parent 125 0 R /Next 127 0 R >> endobj 127 0 obj << /Title(Optimization Strategies) /Dest/section.13.2 /Parent 125 0 R /Prev 126 0 R >> endobj 125 0 obj << /Title( Optimizing Programs ) /Dest/chapter.13 /Count -2 /Parent 6 0 R /Prev 118 0 R /Next 128 0 R /First 126 0 R /Last 127 0 R >> endobj 128 0 obj << /Title(Index of Routines ) /Dest/appendix.A /Parent 6 0 R /Prev 125 0 R /Next 129 0 R >> endobj 129 0 obj << /Title(Parameter Definitions ) /Dest/appendix.B /Parent 6 0 R /Prev 128 0 R /Next 130 0 R >> endobj 133 0 obj <>endobj 140 0 obj <> endobj 141 0 obj <> endobj 145 0 obj <> endobj 146 0 obj <> endobj 150 0 obj <>endobj 153 0 obj <>endobj 154 0 obj <>endobj 155 0 obj <>endobj 156 0 obj <>endobj 157 0 obj <>endobj 158 0 obj <>endobj 159 0 obj <>endobj 160 0 obj <>endobj 161 0 obj <>endobj 162 0 obj <>endobj 163 0 obj <>endobj 164 0 obj <>endobj 165 0 obj <>endobj 166 0 obj <>endobj 167 0 obj <>endobj 168 0 obj <>endobj 169 0 obj <>endobj 170 0 obj <>endobj 171 0 obj <>endobj 172 0 obj <>endobj 173 0 obj <>endobj 174 0 obj <>endobj 175 0 obj <> endobj 176 0 obj <> endobj 182 0 obj <>endobj 183 0 obj <>endobj 184 0 obj <>endobj 185 0 obj <>endobj 186 0 obj <>endobj 187 0 obj <>endobj 188 0 obj <>endobj 189 0 obj <>endobj 190 0 obj <>endobj 191 0 obj <>endobj 192 0 obj <>endobj 193 0 obj <>endobj 194 0 obj <>endobj 195 0 obj <>endobj 196 0 obj <>endobj 197 0 obj <>endobj 198 0 obj <>endobj 199 0 obj <>endobj 200 0 obj <>endobj 201 0 obj <>endobj 202 0 obj <>endobj 203 0 obj <>endobj 204 0 obj <>endobj 205 0 obj <>endobj 206 0 obj <>endobj 207 0 obj <>endobj 208 0 obj <>endobj 209 0 obj <>endobj 210 0 obj <>endobj 211 0 obj <>endobj 212 0 obj <>endobj 213 0 obj <>endobj 214 0 obj <> endobj 215 0 obj <> endobj 219 0 obj <>endobj 220 0 obj <>endobj 221 0 obj <>endobj 222 0 obj <>endobj 223 0 obj <>endobj 224 0 obj <>endobj 225 0 obj <>endobj 226 0 obj <>endobj 227 0 obj <>endobj 228 0 obj <>endobj 229 0 obj <>endobj 230 0 obj <>endobj 231 0 obj <>endobj 232 0 obj <>endobj 233 0 obj <>endobj 234 0 obj <>endobj 235 0 obj <>endobj 236 0 obj <>endobj 237 0 obj <>endobj 238 0 obj <>endobj 239 0 obj <>endobj 240 0 obj <>endobj 241 0 obj <>endobj 242 0 obj <>endobj 243 0 obj <>endobj 244 0 obj <>endobj 245 0 obj <>endobj 246 0 obj <>endobj 247 0 obj <>endobj 248 0 obj <>endobj 249 0 obj <> endobj 250 0 obj <> endobj 254 0 obj <>endobj 255 0 obj <>endobj 256 0 obj <>endobj 257 0 obj <>endobj 258 0 obj <>endobj 259 0 obj <>endobj 260 0 obj <>endobj 261 0 obj <>endobj 262 0 obj <>endobj 263 0 obj <>endobj 264 0 obj <>endobj 265 0 obj <>endobj 266 0 obj <>endobj 267 0 obj <>endobj 268 0 obj <>endobj 269 0 obj <>endobj 270 0 obj <>endobj 271 0 obj <>endobj 272 0 obj <>endobj 273 0 obj <>endobj 274 0 obj <>endobj 275 0 obj <>endobj 276 0 obj <>endobj 277 0 obj <>endobj 278 0 obj <>endobj 279 0 obj <>endobj 280 0 obj <>endobj 281 0 obj <>endobj 282 0 obj <>endobj 283 0 obj <>endobj 284 0 obj <>endobj 285 0 obj <>endobj 286 0 obj <> endobj 287 0 obj <> endobj 291 0 obj <>endobj 292 0 obj <>endobj 293 0 obj <>endobj 294 0 obj <>endobj 295 0 obj <>endobj 296 0 obj <>endobj 297 0 obj <>endobj 298 0 obj <> endobj 299 0 obj <> endobj 303 0 obj <> endobj 304 0 obj <> endobj 308 0 obj <> endobj 309 0 obj <> endobj 315 0 obj <> endobj 316 0 obj <> endobj 320 0 obj <> endobj 321 0 obj <> endobj 325 0 obj <> endobj 326 0 obj <> endobj 330 0 obj <> endobj 331 0 obj <> endobj 335 0 obj <> endobj 336 0 obj <> endobj 340 0 obj <> endobj 341 0 obj <> endobj 345 0 obj <> endobj 346 0 obj <> endobj 350 0 obj <> endobj 351 0 obj <> endobj 355 0 obj <> endobj 356 0 obj <> endobj 360 0 obj <> endobj 361 0 obj <> endobj 365 0 obj <> endobj 366 0 obj <> endobj 372 0 obj <> endobj 373 0 obj <> endobj 377 0 obj <> endobj 378 0 obj <> endobj 382 0 obj <> endobj 383 0 obj <> endobj 387 0 obj <> endobj 388 0 obj <> endobj 392 0 obj <> endobj 393 0 obj <> endobj 397 0 obj <> endobj 398 0 obj <> endobj 402 0 obj <> endobj 403 0 obj <> endobj 407 0 obj <> endobj 408 0 obj <> endobj 412 0 obj <> endobj 413 0 obj <> endobj 417 0 obj <> endobj 418 0 obj <> endobj 422 0 obj <> endobj 423 0 obj <> endobj 427 0 obj <> endobj 428 0 obj <> endobj 432 0 obj <> endobj 433 0 obj <> endobj 437 0 obj <> endobj 438 0 obj <> endobj 442 0 obj <> endobj 443 0 obj <> endobj 447 0 obj <> endobj 448 0 obj <> endobj 452 0 obj <> endobj 453 0 obj <> endobj 457 0 obj <> endobj 458 0 obj <> endobj 464 0 obj <> endobj 465 0 obj <> endobj 469 0 obj <> endobj 470 0 obj <> endobj 474 0 obj <> endobj 475 0 obj <> endobj 479 0 obj <> endobj 480 0 obj <> endobj 484 0 obj <> endobj 485 0 obj <> endobj 489 0 obj <> endobj 490 0 obj <> endobj 494 0 obj <> endobj 495 0 obj <> endobj 499 0 obj <> endobj 500 0 obj <> endobj 504 0 obj <> endobj 505 0 obj <> endobj 509 0 obj <> endobj 510 0 obj <> endobj 514 0 obj <> endobj 515 0 obj <> endobj 519 0 obj <> endobj 520 0 obj <> endobj 524 0 obj <> endobj 525 0 obj <> endobj 529 0 obj <> endobj 530 0 obj <> endobj 534 0 obj <> endobj 535 0 obj <> endobj 539 0 obj <> endobj 540 0 obj <> endobj 544 0 obj <> endobj 545 0 obj <> endobj 549 0 obj <> endobj 550 0 obj <> endobj 554 0 obj <> endobj 555 0 obj <> endobj 559 0 obj <> endobj 560 0 obj <> endobj 564 0 obj <> endobj 565 0 obj <> endobj 569 0 obj <> endobj 570 0 obj <> endobj 574 0 obj <> endobj 575 0 obj <> endobj 579 0 obj <> endobj 580 0 obj <> endobj 584 0 obj <> endobj 585 0 obj <> endobj 589 0 obj <> endobj 590 0 obj <> endobj 594 0 obj <> endobj 595 0 obj <> endobj 599 0 obj <> endobj 600 0 obj <> endobj 604 0 obj <> endobj 605 0 obj <> endobj 609 0 obj <> endobj 610 0 obj <> endobj 614 0 obj <> endobj 615 0 obj <> endobj 619 0 obj <> endobj 620 0 obj <> endobj 624 0 obj <> endobj 625 0 obj <> endobj 629 0 obj <> endobj 630 0 obj <> endobj 634 0 obj <> endobj 635 0 obj <> endobj 639 0 obj <> endobj 640 0 obj <> endobj 644 0 obj <> endobj 645 0 obj <> endobj 649 0 obj <> endobj 650 0 obj <> endobj 654 0 obj <> endobj 655 0 obj <> endobj 659 0 obj <> endobj 660 0 obj <> endobj 664 0 obj <> endobj 665 0 obj <> endobj 669 0 obj <> endobj 670 0 obj <> endobj 674 0 obj <> endobj 675 0 obj <> endobj 679 0 obj <> endobj 680 0 obj <> endobj 684 0 obj <> endobj 685 0 obj <> endobj 689 0 obj <> endobj 690 0 obj <> endobj 694 0 obj <> endobj 695 0 obj <> endobj 699 0 obj <> endobj 700 0 obj <> endobj 704 0 obj <> endobj 705 0 obj <> endobj 709 0 obj <> endobj 710 0 obj <> endobj 714 0 obj <> endobj 715 0 obj <> endobj 719 0 obj <> endobj 720 0 obj <> endobj 724 0 obj <> endobj 725 0 obj <> endobj 729 0 obj <> endobj 730 0 obj <> endobj 734 0 obj <> endobj 735 0 obj <> endobj 739 0 obj <> endobj 740 0 obj <> endobj 744 0 obj <> endobj 745 0 obj <> endobj 749 0 obj <> endobj 750 0 obj <> endobj 756 0 obj <> endobj 757 0 obj <> endobj 761 0 obj <> endobj 762 0 obj <> endobj 766 0 obj <> endobj 767 0 obj <> endobj 771 0 obj <> endobj 772 0 obj <> endobj 776 0 obj <> endobj 777 0 obj <> endobj 781 0 obj <> endobj 782 0 obj <> endobj 786 0 obj <> endobj 787 0 obj <> endobj 791 0 obj <> endobj 792 0 obj <> endobj 796 0 obj <> endobj 797 0 obj <> endobj 801 0 obj <> endobj 802 0 obj <> endobj 806 0 obj <> endobj 807 0 obj <> endobj 811 0 obj <> endobj 812 0 obj <> endobj 816 0 obj <> endobj 817 0 obj <> endobj 821 0 obj <> endobj 822 0 obj <> endobj 826 0 obj <> endobj 827 0 obj <> endobj 831 0 obj <> endobj 832 0 obj <> endobj 836 0 obj <> endobj 837 0 obj <> endobj 841 0 obj <> endobj 842 0 obj <> endobj 846 0 obj <> endobj 847 0 obj <> endobj 851 0 obj <> endobj 852 0 obj <> endobj 856 0 obj <> endobj 857 0 obj <> endobj 861 0 obj <> endobj 862 0 obj <> endobj 866 0 obj <> endobj 867 0 obj <> endobj 871 0 obj <> endobj 872 0 obj <> endobj 876 0 obj <> endobj 877 0 obj <> endobj 881 0 obj <> endobj 882 0 obj <> endobj 886 0 obj <> endobj 887 0 obj <> endobj 891 0 obj <> endobj 892 0 obj <> endobj 896 0 obj <> endobj 897 0 obj <> endobj 901 0 obj <> endobj 902 0 obj <> endobj 906 0 obj <> endobj 907 0 obj <> endobj 911 0 obj <> endobj 912 0 obj <> endobj 916 0 obj <> endobj 917 0 obj <> endobj 921 0 obj <> endobj 922 0 obj <> endobj 926 0 obj <> endobj 927 0 obj <> endobj 931 0 obj <> endobj 932 0 obj <> endobj 936 0 obj <> endobj 937 0 obj <> endobj 941 0 obj <> endobj 942 0 obj <> endobj 946 0 obj <> endobj 947 0 obj <> endobj 951 0 obj <> endobj 952 0 obj <> endobj 956 0 obj <> endobj 957 0 obj <> endobj 961 0 obj <> endobj 962 0 obj <> endobj 966 0 obj <> endobj 967 0 obj <> endobj 971 0 obj <> endobj 972 0 obj <> endobj 976 0 obj <> endobj 977 0 obj <> endobj 981 0 obj <> endobj 982 0 obj <> endobj 986 0 obj <> endobj 987 0 obj <> endobj 991 0 obj <> endobj 992 0 obj <> endobj 996 0 obj <> endobj 997 0 obj <> endobj 1001 0 obj <> endobj 1002 0 obj <> endobj 1006 0 obj <> endobj 1007 0 obj <> endobj 1011 0 obj <> endobj 1012 0 obj <> endobj 1016 0 obj <> endobj 1017 0 obj <> endobj 1021 0 obj <> endobj 1022 0 obj <> endobj 1026 0 obj <> endobj 1027 0 obj <> endobj 1031 0 obj <> endobj 1032 0 obj <> endobj 1036 0 obj <> endobj 1037 0 obj <> endobj 1041 0 obj <> endobj 1042 0 obj <> endobj 1046 0 obj <> endobj 1047 0 obj <> endobj 1051 0 obj <> endobj 1052 0 obj <> endobj 1056 0 obj <> endobj 1057 0 obj <> endobj 1061 0 obj <> endobj 1062 0 obj <> endobj 1066 0 obj <> endobj 1067 0 obj <> endobj 1071 0 obj <> endobj 1072 0 obj <> endobj 1076 0 obj <> endobj 1077 0 obj <> endobj 1081 0 obj <> endobj 1082 0 obj <> endobj 1086 0 obj <> endobj 1087 0 obj <> endobj 1091 0 obj <> endobj 1092 0 obj <> endobj 1096 0 obj <> endobj 1097 0 obj <> endobj 1101 0 obj <> endobj 1102 0 obj <> endobj 1106 0 obj <> endobj 1107 0 obj <> endobj 1111 0 obj <> endobj 1112 0 obj <> endobj 1116 0 obj <> endobj 1117 0 obj <> endobj 1121 0 obj <> endobj 1122 0 obj <> endobj 1126 0 obj <> endobj 1127 0 obj <> endobj 1131 0 obj <> endobj 1132 0 obj <> endobj 1136 0 obj <> endobj 1137 0 obj <> endobj 1141 0 obj <> endobj 1142 0 obj <> endobj 1146 0 obj <> endobj 1147 0 obj <> endobj 1151 0 obj <> endobj 1152 0 obj <> endobj 1156 0 obj <> endobj 1157 0 obj <> endobj 1161 0 obj <> endobj 1162 0 obj <> endobj 1166 0 obj <> endobj 1167 0 obj <> endobj 1171 0 obj <> endobj 1172 0 obj <> endobj 1176 0 obj <>endobj 1177 0 obj <>endobj 1178 0 obj <>endobj 1179 0 obj <>endobj 1180 0 obj <>endobj 1181 0 obj <>endobj 1182 0 obj <>endobj 1183 0 obj <>endobj 1184 0 obj <>endobj 1185 0 obj <>endobj 1186 0 obj <>endobj 1187 0 obj <>endobj 1188 0 obj <>endobj 1189 0 obj <>endobj 1190 0 obj <>endobj 1191 0 obj <>endobj 1192 0 obj <>endobj 1193 0 obj <>endobj 1194 0 obj <>endobj 1195 0 obj <>endobj 1196 0 obj <>endobj 1197 0 obj <>endobj 1198 0 obj <>endobj 1199 0 obj <>endobj 1200 0 obj <>endobj 1201 0 obj <>endobj 1202 0 obj <>endobj 1203 0 obj <>endobj 1204 0 obj <>endobj 1205 0 obj <>endobj 1206 0 obj <>endobj 1207 0 obj <>endobj 1208 0 obj <>endobj 1209 0 obj <>endobj 1210 0 obj <>endobj 1211 0 obj <>endobj 1212 0 obj <>endobj 1213 0 obj <>endobj 1214 0 obj <>endobj 1215 0 obj <>endobj 1216 0 obj <>endobj 1217 0 obj <>endobj 1218 0 obj <>endobj 1219 0 obj <>endobj 1220 0 obj <>endobj 1221 0 obj <>endobj 1222 0 obj <>endobj 1223 0 obj <>endobj 1224 0 obj <>endobj 1225 0 obj <>endobj 1226 0 obj <>endobj 1227 0 obj <>endobj 1228 0 obj <>endobj 1229 0 obj <>endobj 1230 0 obj <>endobj 1231 0 obj <>endobj 1232 0 obj <>endobj 1233 0 obj <>endobj 1234 0 obj <>endobj 1235 0 obj <>endobj 1236 0 obj <>endobj 1237 0 obj <>endobj 1238 0 obj <>endobj 1239 0 obj <>endobj 1240 0 obj <>endobj 1241 0 obj <>endobj 1242 0 obj <>endobj 1243 0 obj <>endobj 1244 0 obj <>endobj 1245 0 obj <>endobj 1246 0 obj <>endobj 1247 0 obj <>endobj 1248 0 obj <>endobj 1249 0 obj <>endobj 1250 0 obj <>endobj 1251 0 obj <>endobj 1252 0 obj <>endobj 1253 0 obj <>endobj 1254 0 obj <>endobj 1255 0 obj <>endobj 1256 0 obj <>endobj 1257 0 obj <>endobj 1258 0 obj <>endobj 1259 0 obj <>endobj 1260 0 obj <>endobj 1261 0 obj <>endobj 1262 0 obj <>endobj 1263 0 obj <>endobj 1264 0 obj <>endobj 1265 0 obj <>endobj 1266 0 obj <>endobj 1267 0 obj <>endobj 1268 0 obj <>endobj 1269 0 obj <>endobj 1270 0 obj <>endobj 1271 0 obj <>endobj 1272 0 obj <>endobj 1273 0 obj <>endobj 1274 0 obj <> endobj 1275 0 obj <> endobj 1279 0 obj <>endobj 1280 0 obj <>endobj 1281 0 obj <>endobj 1282 0 obj <>endobj 1283 0 obj <>endobj 1284 0 obj <>endobj 1285 0 obj <>endobj 1286 0 obj <>endobj 1287 0 obj <>endobj 1288 0 obj <>endobj 1289 0 obj <>endobj 1290 0 obj <>endobj 1291 0 obj <>endobj 1292 0 obj <>endobj 1293 0 obj <>endobj 1294 0 obj <>endobj 1295 0 obj <>endobj 1296 0 obj <>endobj 1297 0 obj <>endobj 1298 0 obj <>endobj 1299 0 obj <>endobj 1300 0 obj <>endobj 1301 0 obj <>endobj 1302 0 obj <>endobj 1303 0 obj <>endobj 1304 0 obj <>endobj 1305 0 obj <>endobj 1306 0 obj <>endobj 1307 0 obj <>endobj 1308 0 obj <>endobj 1309 0 obj <>endobj 1310 0 obj <>endobj 1311 0 obj <>endobj 1312 0 obj <>endobj 1313 0 obj <>endobj 1314 0 obj <>endobj 1315 0 obj <>endobj 1316 0 obj <>endobj 1317 0 obj <>endobj 1318 0 obj <>endobj 1319 0 obj <>endobj 1320 0 obj <>endobj 1321 0 obj <>endobj 1322 0 obj <>endobj 1323 0 obj <>endobj 1324 0 obj <>endobj 1325 0 obj <>endobj 1326 0 obj <>endobj 1327 0 obj <>endobj 1328 0 obj <>endobj 1329 0 obj <>endobj 1330 0 obj <>endobj 1331 0 obj <>endobj 1332 0 obj <>endobj 1333 0 obj <>endobj 1334 0 obj <>endobj 1335 0 obj <>endobj 1336 0 obj <>endobj 1337 0 obj <>endobj 1338 0 obj <>endobj 1339 0 obj <>endobj 1340 0 obj <>endobj 1341 0 obj <>endobj 1342 0 obj <>endobj 1343 0 obj <>endobj 1344 0 obj <>endobj 1345 0 obj <>endobj 1346 0 obj <>endobj 1347 0 obj <>endobj 1348 0 obj <>endobj 1349 0 obj <>endobj 1350 0 obj <>endobj 1351 0 obj <>endobj 1352 0 obj <>endobj 1353 0 obj <>endobj 1354 0 obj <>endobj 1355 0 obj <>endobj 1356 0 obj <>endobj 1357 0 obj <>endobj 1358 0 obj <>endobj 1359 0 obj <>endobj 1360 0 obj <>endobj 1361 0 obj <>endobj 1362 0 obj <>endobj 1363 0 obj <>endobj 1364 0 obj <>endobj 1365 0 obj <>endobj 1366 0 obj <>endobj 1367 0 obj <>endobj 1368 0 obj <>endobj 1369 0 obj <>endobj 1370 0 obj <>endobj 1371 0 obj <>endobj 1372 0 obj <>endobj 1373 0 obj <>endobj 1374 0 obj <>endobj 1375 0 obj <>endobj 1376 0 obj <>endobj 1377 0 obj <>endobj 1378 0 obj <>endobj 1379 0 obj <>endobj 1380 0 obj <>endobj 1381 0 obj <>endobj 1382 0 obj <>endobj 1383 0 obj <>endobj 1384 0 obj <>endobj 1385 0 obj <>endobj 1386 0 obj <>endobj 1387 0 obj <>endobj 1388 0 obj <>endobj 1389 0 obj <>endobj 1390 0 obj <>endobj 1391 0 obj <>endobj 1392 0 obj <>endobj 1393 0 obj <>endobj 1394 0 obj <>endobj 1395 0 obj <>endobj 1396 0 obj <>endobj 1397 0 obj <>endobj 1398 0 obj <>endobj 1399 0 obj <>endobj 1400 0 obj <>endobj 1401 0 obj <>endobj 1402 0 obj <>endobj 1403 0 obj <>endobj 1404 0 obj <>endobj 1405 0 obj <>endobj 1406 0 obj <>endobj 1407 0 obj <>endobj 1408 0 obj <>endobj 1409 0 obj <>endobj 1410 0 obj <>endobj 1411 0 obj <>endobj 1412 0 obj <>endobj 1413 0 obj <>endobj 1414 0 obj <>endobj 1415 0 obj <>endobj 1416 0 obj <>endobj 1417 0 obj <>endobj 1418 0 obj <>endobj 1419 0 obj <>endobj 1420 0 obj <>endobj 1421 0 obj <>endobj 1422 0 obj <>endobj 1423 0 obj <>endobj 1424 0 obj <>endobj 1425 0 obj <>endobj 1426 0 obj <> endobj 1427 0 obj <> endobj 1431 0 obj <>endobj 1432 0 obj <>endobj 1433 0 obj <>endobj 1434 0 obj <>endobj 1435 0 obj <>endobj 1436 0 obj <>endobj 1437 0 obj <>endobj 1438 0 obj <>endobj 1439 0 obj <>endobj 1440 0 obj <>endobj 1441 0 obj <>endobj 1442 0 obj <>endobj 1443 0 obj <>endobj 1444 0 obj <>endobj 1445 0 obj <>endobj 1446 0 obj <>endobj 1447 0 obj <>endobj 1448 0 obj <>endobj 1449 0 obj <>endobj 1450 0 obj <>endobj 1451 0 obj <>endobj 1452 0 obj <>endobj 1453 0 obj <>endobj 1454 0 obj <>endobj 1455 0 obj <>endobj 1456 0 obj <>endobj 1457 0 obj <>endobj 1458 0 obj <>endobj 1459 0 obj <>endobj 1460 0 obj <>endobj 1461 0 obj <>endobj 1462 0 obj <>endobj 1463 0 obj <>endobj 1464 0 obj <> endobj 1465 0 obj <> endobj 1469 0 obj <>endobj 1470 0 obj <>endobj 1471 0 obj <>endobj 1472 0 obj <>endobj 1473 0 obj <>endobj 1474 0 obj <>endobj 1475 0 obj <>endobj 1476 0 obj <>endobj 1477 0 obj <>endobj 1478 0 obj <>endobj 1479 0 obj <>endobj 1480 0 obj <>endobj 1481 0 obj <>endobj 1482 0 obj <>endobj 1483 0 obj <>endobj 1484 0 obj <>endobj 1485 0 obj <>endobj 1486 0 obj <>endobj 1487 0 obj <>endobj 1488 0 obj <>endobj 1489 0 obj <>endobj 1490 0 obj <>endobj 1491 0 obj <>endobj 1492 0 obj <>endobj 1493 0 obj <>endobj 1494 0 obj <>endobj 1495 0 obj <>endobj 1496 0 obj <>endobj 1497 0 obj <>endobj 1498 0 obj <>endobj 1499 0 obj <>endobj 1500 0 obj <>endobj 1501 0 obj <>endobj 1502 0 obj <>endobj 1503 0 obj <>endobj 1504 0 obj <>endobj 1505 0 obj <>endobj 1506 0 obj <>endobj 1507 0 obj <>endobj 1508 0 obj <>endobj 1509 0 obj <>endobj 1510 0 obj <>endobj 1511 0 obj <>endobj 1512 0 obj <>endobj 1513 0 obj <>endobj 1514 0 obj <>endobj 1515 0 obj <>endobj 1516 0 obj <>endobj 1517 0 obj <>endobj 1518 0 obj <>endobj 1519 0 obj <>endobj 1520 0 obj <>endobj 1521 0 obj <>endobj 1522 0 obj <>endobj 1523 0 obj <>endobj 1524 0 obj <>endobj 1525 0 obj <>endobj 1526 0 obj <>endobj 1527 0 obj <>endobj 1528 0 obj <>endobj 1529 0 obj <>endobj 1530 0 obj <>endobj 1531 0 obj <>endobj 1532 0 obj <>endobj 1533 0 obj <>endobj 1534 0 obj <>endobj 1535 0 obj <>endobj 1536 0 obj <>endobj 1537 0 obj <>endobj 1538 0 obj <>endobj 1539 0 obj <>endobj 1540 0 obj <>endobj 1541 0 obj <>endobj 1542 0 obj <>endobj 1543 0 obj <>endobj 1544 0 obj <>endobj 1545 0 obj <>endobj 1546 0 obj <>endobj 1547 0 obj <>endobj 1548 0 obj <>endobj 1549 0 obj <>endobj 1550 0 obj <>endobj 1551 0 obj <>endobj 1552 0 obj <>endobj 1553 0 obj <>endobj 1554 0 obj <>endobj 1555 0 obj <>endobj 1556 0 obj <>endobj 1557 0 obj <>endobj 1558 0 obj <>endobj 1559 0 obj <>endobj 1560 0 obj <>endobj 1561 0 obj <>endobj 1562 0 obj <>endobj 1563 0 obj <>endobj 1564 0 obj <>endobj 1565 0 obj <>endobj 1566 0 obj <>endobj 1567 0 obj <>endobj 1568 0 obj <>endobj 1569 0 obj <>endobj 1570 0 obj <>endobj 1571 0 obj <>endobj 1572 0 obj <>endobj 1573 0 obj <>endobj 1574 0 obj <>endobj 1575 0 obj <>endobj 1576 0 obj <>endobj 1577 0 obj <>endobj 1578 0 obj <>endobj 1579 0 obj <>endobj 1580 0 obj <>endobj 1581 0 obj <>endobj 1582 0 obj <>endobj 1583 0 obj <>endobj 1584 0 obj <>endobj 1585 0 obj <>endobj 1586 0 obj <>endobj 1587 0 obj <>endobj 1588 0 obj <>endobj 1589 0 obj <>endobj 1590 0 obj <>endobj 1591 0 obj <>endobj 1592 0 obj <>endobj 1593 0 obj <>endobj 1594 0 obj <>endobj 1595 0 obj <>endobj 1596 0 obj <>endobj 1597 0 obj <>endobj 1598 0 obj <>endobj 1599 0 obj <>endobj 1600 0 obj <>endobj 1601 0 obj <>endobj 1602 0 obj <>endobj 1603 0 obj <>endobj 1604 0 obj <>endobj 1605 0 obj <>endobj 1606 0 obj <>endobj 1607 0 obj <>endobj 1608 0 obj <>endobj 1609 0 obj <>endobj 1610 0 obj <>endobj 1611 0 obj <>endobj 1612 0 obj <>endobj 1613 0 obj <>endobj 1614 0 obj <>endobj 1615 0 obj <>endobj 1616 0 obj <>endobj 1617 0 obj <>endobj 1618 0 obj <>endobj 1619 0 obj <>endobj 1620 0 obj <>endobj 1621 0 obj <>endobj 1622 0 obj <>endobj 1623 0 obj <>endobj 1624 0 obj <>endobj 1625 0 obj <>endobj 1626 0 obj <>endobj 1627 0 obj <>endobj 1628 0 obj <>endobj 1629 0 obj <>endobj 1630 0 obj <>endobj 1631 0 obj <>endobj 1632 0 obj <>endobj 1633 0 obj <>endobj 1634 0 obj <>endobj 1635 0 obj <>endobj 1636 0 obj <>endobj 1637 0 obj <>endobj 1638 0 obj <>endobj 1639 0 obj <>endobj 1640 0 obj <>endobj 1641 0 obj <>endobj 1642 0 obj <>endobj 1643 0 obj <>endobj 1644 0 obj <>endobj 1645 0 obj <>endobj 1646 0 obj <>endobj 1647 0 obj <>endobj 1648 0 obj <>endobj 1649 0 obj <>endobj 1650 0 obj <>endobj 1651 0 obj <>endobj 1652 0 obj <>endobj 1653 0 obj <>endobj 1654 0 obj <>endobj 1655 0 obj <>endobj 1656 0 obj <>endobj 1657 0 obj <>endobj 1658 0 obj <>endobj 1659 0 obj <>endobj 1660 0 obj <>endobj 1661 0 obj <>endobj 1662 0 obj <>endobj 1663 0 obj <>endobj 1664 0 obj <>endobj 1665 0 obj <>endobj 1666 0 obj <>endobj 1667 0 obj <>endobj 1668 0 obj <>endobj 1669 0 obj <>endobj 1670 0 obj <>endobj 1671 0 obj <>endobj 1672 0 obj <>endobj 1673 0 obj <>endobj 1674 0 obj <>endobj 1675 0 obj <>endobj 1676 0 obj <>endobj 1677 0 obj <>endobj 1678 0 obj <>endobj 1679 0 obj <>endobj 1680 0 obj <>endobj 1681 0 obj <>endobj 1682 0 obj <>endobj 1683 0 obj <>endobj 1684 0 obj <>endobj 1685 0 obj <>endobj 1686 0 obj <>endobj 1687 0 obj <>endobj 1688 0 obj <>endobj 1689 0 obj <>endobj 1690 0 obj <>endobj 1691 0 obj <>endobj 1692 0 obj <>endobj 1693 0 obj <>endobj 1694 0 obj <>endobj 1695 0 obj <>endobj 1696 0 obj <>endobj 1697 0 obj <>endobj 1698 0 obj <>endobj 1699 0 obj <>endobj 1700 0 obj <>endobj 1701 0 obj <>endobj 1702 0 obj <>endobj 1703 0 obj <>endobj 1704 0 obj <>endobj 1705 0 obj <>endobj 1706 0 obj <>endobj 1707 0 obj <>endobj 1708 0 obj <>endobj 1709 0 obj <>endobj 1710 0 obj <>endobj 1711 0 obj <>endobj 1712 0 obj <> endobj 1713 0 obj <> endobj 1717 0 obj <>endobj 1718 0 obj <>endobj 1719 0 obj <>endobj 1720 0 obj <>endobj 1721 0 obj <>endobj 1722 0 obj <>endobj 1723 0 obj <>endobj 1724 0 obj <>endobj 1725 0 obj <>endobj 1726 0 obj <>endobj 1727 0 obj <>endobj 1728 0 obj <>endobj 1729 0 obj <>endobj 1730 0 obj <>endobj 1731 0 obj <> endobj 1732 0 obj <> endobj 1736 0 obj <> endobj 1737 0 obj <> endobj 1741 0 obj <> endobj 1742 0 obj <> endobj 1746 0 obj <> endobj 1747 0 obj <> endobj 1751 0 obj <> endobj 1752 0 obj <> endobj 1756 0 obj <> endobj 1757 0 obj <> endobj 1761 0 obj <> endobj 1762 0 obj <> endobj 1766 0 obj <> endobj 1767 0 obj <> endobj 1771 0 obj <> endobj 1772 0 obj <> endobj 1776 0 obj <> endobj 1777 0 obj <> endobj 1781 0 obj <> endobj 1782 0 obj <> endobj 1786 0 obj <> endobj 1787 0 obj <> endobj 180 0 obj <> endobj 151 0 obj <> endobj 1797 0 obj <> endobj 138 0 obj <> endobj 1798 0 obj <> endobj 136 0 obj <> endobj 134 0 obj <> endobj 1799 0 obj <> endobj 754 0 obj <> endobj 462 0 obj <> endobj 370 0 obj <> endobj 1800 0 obj <> endobj 313 0 obj <> endobj 1801 0 obj <> endobj 181 0 obj <> endobj 1788 0 obj <>stream xœµXyTS×Ö¿ñšëÕ"ޱIëK°­uh-XµÎµˆuÄy Š‚ „Q „L÷fß„0ƒŒa *ED«ÖZµ*Ð×Ö©ÕjmûÚꫯùéÉ÷úN@mßZï{ï{|+‹µrÏÙ¿½ÏoïßïDB @I$’A~k¦ú¸ß>+>)ÇÿD¶þŠœ¹Rð Ác cì˜õ#ÑÞhÓ0ä3œ¢%’ůùÅ'¤'Fo‹R{Mô›ä5uöì™^¾q‰Ñáa;¼ÃÔQqajò!ÖkM|xt„:ý/ߨX¯ÕîI^«#’"S"¶öÇö‹KHVG$zÆoHÜAQÔß 7ù/zuñ’¥ËüW­\½fíºõ^š9köÄIS^ðö™úâ´é3(ê)j6õ45‡z†šK§ž¥&P©IÔdêyj õåMùPS©iÔtjõ5“šE=NÉ)õ5˜ByRèáÔj$5ŠMɨ1ÔDRjU.Ià9 •^N77°[ºTúwæ“A‹Ø‘lÎàEƒ?â;äƒÇê=6{|1T=ô+ÏîaK†5Ÿ6üÝOŽHQ0¢cÄ÷#7Žì5cTï襣ïý& \Gy:sÁ69Äe5’çbZ,q.“qÕæ¼] &“n>ãú‹<9,jçRàµæ^[+¼ié€xŸo2ç7ËsWåu‚¥¬QUs°þ­Š&³O8!8EŒ?$*Í:.ËœÛf½àt›;y¡ÈZ.²»?à‹ ûXì/æËNã+RœÌô!rJ’zg9-FŠcdh>z­²¦ãÈ_Aasl3‡ñ1 ‡Ín5í”'˜ ùN½5t 1rµø)<_þ‚/ÙÏ|€=•8÷Ê:‘ŶW(< äÁ|_ñò¶Ù‹|ð`žˆoËâÓ Ö ënU7j¢@æ~å‹áÞ ½ñ@Õ£¢#g<íÜ ~.ë>s2ÿ »n±|¸9â`•e§@ ´Ud¦eåæèsU8ÛñtÈP6MG¡QisDq¾ŠX"-äù+PbÚžÇßȳ¼ùÌ o^Ã%§“±ãN©ðâ y]„vŽD‹'¼Kµ$[4yP Íh®­¯jgQÉçºG;íÎå²BƒÕ`âxŽWòfÎÈóëå:˜Í@^‚¾ äÔêš `ñ†7àtìØÍø´×ñÖ;ª;×KïÀë#§ƒ\^©Ûå»((hãêŒ ÀNŧвr@s¿BÃUG{nŸþXäqS˜Ö™Éó*A[ù„]…gu£ KÁ>ñïÉiñ'Úù´óIYI™ûK¶Ä©J×j&'KzöâQôÙÌ›qi\¿ê´&#h96¨UŠ¡Ì{¨FšÈÄâ§#§â}&C¶Æ·©þ“qÎø–F“þ®P ZCˆêv iÐ0ì£ÂKdýô`¿g¾ÿn-öÎ0á¥óÇ©¶¬õ[ÿ,°“™ß9Bbﵺ©zÖZ÷IZ³h§?*‘%2ë±oð:<• ó‡ç£jé-æƒfÍúT.“ËP50]¨Šä“õ\|Êt`§1Èhk±å!ÔÁ åÞ0,Ɇt³†Ñq>D=„XÇ|Xò;Ä:cŒA;I$Z{ÿ¹„+ÐÆ …$Z«füô…µ–¢¾hôà³¢µ:ÑbŒ8K†"ЂKgN uQ«.–(Žb¬#ñ qrá yGz–FgP¹(|â$úøÿ­|ÍèU¤@ˆ²UØró³È˜‰4¥1¶ÊÒÕ èš ‹ï4+ò›a§xTáé”>HEü’vJûZ=S1ø1¼Øyhõ;b+Á]ö(Zújê [ܸügÜÛ¸Š´1]äxP»ý¿®¤ÑÎ 2cYH se.ó/ö™éâLIºñå¹Mx‹È³Îós¾Cž´Þî?–;b‹T ]þ?«Æ¢-E1äÙ ÑONO¹ÀLvýùel·~ÔÄÀþUÆ/Åæþ¶è;")žÇ$ rRñ×ù#Õt·ºëô–év›5I`ÎÃö0ÝPi*á|\rS¢.t<üð·Är›Þ¦µè¤ëFA–Àƒ¢›µêñ¤<¯±°ûo@fP”9˜ø $Xa‰ ±òº^XožÛ¥ZäzYÚOÌäFç¬É/?ˆ;ïÒÎzq’ -ÁCÑPìƒÃñZò§Æ¯ !d@LG!h# FéJ—Ò5^6aΗÈ{_šÒ‹(Õ‡÷¿h;ìç?á…s’ðã+½Uþ“çnY ì#}8ЈÎ+óó_iÔŠ>’¡¹ zþ øÌ÷~R…üW‡ùß‘ù–ØþP·¾`®M˜ŸÅEk·ªRf-ò!Õë…›c©d;ó¶pŒßÁR‹ôì®ýç÷á[öΤ^~ GCjøãݪ¸Û ƒvGËSm1EzKLyì>8Î^î½| Ño-—a.…]J-èJ­6ÁbUöû5pˆx¿ÑNZÌ#òÒŸh‘¥ ªˆž nϘÀ'q;‰W»51«ûLÒ!ä]|M‡ÝPùæZÞÆG¨ë÷8µrãv.{°ä ,]Њï„n¸ordÚJ#˜—vÚȳ”¸--)ÝãD’|A;ƒÅ˲G½Áo6Gƒü-qÿÜ;«ðÝ$r} ç>GnÞÕH^ åÖ*Õâ¤? ÿ4§]R.²!GGß›…X41h’Õ*Ýjã¤ÑÎ7hg8qÙöŽ}à‘ËŽÕ–$·Ë>Q¾3CËóºLÞíJñÉ=Él…e¿ñõÁÉ+Èú9V¢›²’÷wßy÷bSÛ±#zÈT±x0»#I—Ti·…ž×Ô­Áãq žƒ?ׂG#ÅÙcµo¿£ºp¾ò8Ãþùµ±ÇâÍë·¨•çñUYxpã×Vø[K¯ª¢­ã£Iw–/ß¢ÎÆÃv© 9‘¯Ìƒ>4µbÏåÒ zB ¡ÅO Ó ó  †ÅzʪU‰Ì¼…P»ù«"¡ÔRg=ͤB™76ùΉܼÊwûŠäÐ糦–M/Ki:œßaÏSVÞÝ‹ü®ÓŸ¯sXƒ¤çXÛqÔØE#úR™Ç-<Šõ¹¹ê{Ò¨ì=4äú¦ý;«•Ú|uenÁjDŸ„ûìõWŽÎÄô$Ÿ !oÆ)‘×nY|íÖ¦´ò¨†Ä*è`Ï]:u£÷HȪekWúmSÎ^-«Ë8VŸÑ”Ò¢†`vÞ´e/Ì[sâ£OÎ]¹Ý¡ìCÒþõ:ñ™Ò×7PÞeZœ‰>”iƒ²^|}iLpphÄBX~šÃj&î؆=5­{ÕÅÙ[ «ö¦¼yãÔWï©>GÃòÑd8Ê¢q+®NÀÃñ(<û¬èÄ,ÕsôØ‘F%þ“¯,(¡ë|kÙð–ª´®ãÜŸ}§ùµå»LS“WªÔ+C¹%H¢¿Makí¯kHùeïШ ëeî[¿¶$©yá@ëà"QŠUZ"¹À˜¬ík‘kÖ*Ÿ7GN‚eÅ3Úç¶úž (6?//_õÏÛvm¿‡Ëà°éJÜg÷—œÏÖ`äô„^:Õ¥™{ðÀž€•aø"ŽÁ‹³³É%”cõy\~yÏi»]‰– •mHÈÓ8p…‚NK:Qz/ÃUŒv•¹‘DFÜäÏ’¿üB£×ÏÊZËS¢ââÔ•êæ½ŽÆ}îú»A­hT‰]´xÒ¹YVXF²µ²%Ú"­AoN×*]†¿/Ôg“¡nRhŠt%¥¶â"[ßÁÙr»äêÇèK´X/n”ÝJ@£°„‡†§*Ã^RãÙ°œ (ǓДk7£Á'”'ÑcÅh.4²¸ÙµQã_‰^ì@U-ŸªÞ¹P¶Ø=5Xºp æv¾¬ ÇÒW5ñ} Aÿ~GWä[ô-ŽwŽ’YŠúP–å‚F¹È*áH¿ j„cpºqº«ZnŒå³§Ûçn¡TtÀ­ßMw3?çÑ…‹¸Œ~úé2ÑÆüŒÞ¸C‹‰h!ñª¼>Õ?+Ãd2™fÞà‰3Xĸ§ïýKûO9Û_±ˆ~ñÄe—a%°i¤ø­ïº‹ß 'ˆ¢>øñ*Y¡É·çUܱ”ªþê6Á˜\q°,Ð5XŠùþ’ wQ€=þyIä“û(…ŒäTñœl¿f_ãþéäöò"½Àó„–¹ª©›õ[‰â„å‡Ôhl<áªxŸµ “÷ùK NI`),P¶ußsØ#ŽðWSuxP¤¿jçëÁ‘ë`5í˹jã‹È a߬h«­ÑØ·¯ÿÌÏ-ùF2¢»î]Ÿ¸1$}{¤Ê“ðï©D;J¼¥tcÈÕÇ”Cάñl/òð ¨ØT æ endstream endobj 152 0 obj <> endobj 1789 0 obj <>stream xœ…X T×¶­¶¥ª4ˆJ["jªqQ‰#1&qBDqBql™„€¢Ì  "‚ ݧA@IP¡eJœˆcL|qˆÑ•¼äMbMŒÏä¹äçß‚ æ%ïÿU ª¡nõ=çž}öÞ÷ª˜Þ½•JÅÍ[ä²zò$壃³Žqe&2nÌ$ƙ̼Á¼ÉLe0Ógf³˜y…±a†0¶ÌPf cÅ d¬ 3ˆ˜ÁÌ4ºn Ç$2T›Tç{¹õº¡vRƒúQï…½´(µø‚õaÏsÜ&ù}}öñêóAßWúf¼Ðÿ…Ö֖ɖ_õó´r´:ØÿÍþÅ– (ðáÀ­Öƒ¬+4ÖšýƒÄAµƒ.ã„HáóÁ©ƒ?±Ùñ‹j§cõ‹:0œ í%yA‰ª©ó°Zíœ&$U=)»ã‰±ëÛ!©ÛÓSf«cë'MÕÐoÃñt^âôÓ ß˜‘k4jOa? ,e/{‹ tXÆ×Ðpêè°qùJ%Õ$޵ú¥Wâ}eÚ'Afkdé勬¦µUtÜã%S=á¢þˆ—Ü0CÕ½öwjKcg‹¤Üí¯ò¸g^ ãWz®Ž5wáÈœ w%´ä G“œb©ÌÖjÆ"ÉÐÏáH¡ƒFÆjù‹p÷äàëëg­[4N‹l‚€Lñ»—àÿå´ˆ³Øå¦C¦ë«yFÀ⫟Þüó5òBŽÖ™\ˆ¶âJ¶$¨õ=æË!‰ß d-ZÉ7SeYUƒƒ0©å pèÄ'd:yeÒbKÜwÀ×ðõÏž`‘ì#Ñ2ŸµÂé¢ZmññæÒvh†æmeÁ¥a¬ã§aˆF¤yÍ22I’ü“¤ºŠNrz»º3»s²P 9ñÉzýîñÍ¥‹N½qÐl‰‰8GâGüÞÑ„KÐû#W²Û˜˜ ín2”ô[l3aú¡U—uçwÞ†Ïáí dÞyïÝ÷>Û†_Ï.#šŒ8£¾øJ£©RÛSG²RÂfYÕ±¡ÑúdC˹Ùhnc8þS€b£±  ±éLVð×Þ^L¬É×U vèàœ·6)ŒPÌ¿O×r1×|bWð8îûÏQ‹¶“¾"£ç¬Ü­Õ|ÝÎ×_˨í2þ'èjD<¡U–H*Zâá² :¨Ñ¡S#t=PŠ6Ã58Ž&½ ÃÉ8ÈZm—‹ŽÅô®‚üí¹÷à“¸v׺ÕûÜá% ª+C¼×¹OݶèW÷úw† : sÏ*ß>%ugtl æEÀ“ X×Á~“ë;W+a­Ž›ì;N\¹8Eg¨t)$ýx‰ÝŒ©?«8}BÃ괦͠º[¨|{>ŽZÑ¡¬àheCq|n°4 çq×+Ðê;Ñ`ˆß¡¼ÍÖªªšÒƳ^U«\7¬ñˆ5­hÁ‘WŸ<]™:c«© êá*˜Ó•ðoP&(—°ì×ð'Jø"Í`HçëB×÷¿C›ö œ€v@œ ]K†aù)ßJ¡ ­Á2´S*Ÿu€ô¡ Ñø/2©fyXu}³ß ÜI)ñ¡$¼•½`?Hü•‡P|»>tÅ^ѸݘV ü!Ø[®ýˆS ºGqbD~pÖà·ºö6JÂK´Áõ©wvðšæÔÛ‰K‡Î™1#"nµìÓ Ò`ðQ­%*.’f›à@©h„²¦¶3P|5¾hß²µ.øˆ6 *$kf¾‚‘ô±´c‚J1@’ûJÖJیÑkÛm4Û;GœªÃ/Ed_ù´¸þ#‰ NŸ°Œ"Â+ƒ×áh{N#A„DGlI gp®Z{Å·#ñ|Ø»äÂñöÆSwŽ?þµ[0„{¾5].ÌË]E[Ó@&²¬Ã1d"î?öÔtåí,Õ™éLj#þ"áìÕSÚR}%5n‘G”«‰=.×±‡µcǦóAÿ$‡9»Ïbn|Øzþ–xV·šs‰ [WËE«Ÿ†Ð²7H˜'õ”ý©îÜM{‰ Lw_z9B ’CòȘGŸpÿù¤»ƒ¸úŒÇ”Ò[à1Ô+à`°? ÷„ë!†TsÐYJñ¿<}…±ÑDË n 39tͲ¸E»¡A«i•)g/üÂ˹«WºÌJ¯8'âWz²ƒ³û8æÛÊ›p·òŸªiØ?RÍJf¬ÄúÓø×ÓËü•øY?«ãšh”môz MJ”¬¥÷fO©<@RUʧÕr†l)ddf_ªl‘úPC$D‚·)ÖÈë¸âªôÒvi O2ˆ+-ÎIì&ýdƒ ¥·ÉŸºÊá¼.˼È|ÈÛ"ÈÍÈ-Uºo¢]Š-.9ŠNfëì3 â4Eðbå¾w„ͰþßâI¶$•'B¢v±‘¾^ÎS¸<˜ÿ.qô$V{¦úÔÅ®®)m>W”ndÕó€¿]ç7[»‘"r~:ÉN&c†ŽÇñï$55—‰ 8Y˜ÀŸ˜¹zCÝ dpJÁ© ±'cЉ§’ªL¾¤ÆoÑ `œ_•ý ØRÀëWÒhÖkLaJÖ§ÏÛ½'ô{öLw∜E£ÄF<ô!B³ÞDÝàpñ 6Ä!!.Ö-åÓã^¨€ úªÐ\|ÜÞ,#³÷i¡ {‘Á:¶ÒxÙt j UŒŽ™ÿ;f¶”Ê/šqYÇŸµ$7ÉclûC´]$®°¸è`a1¯iIÙ×îõ`:>í§¯È—5¡[£´Y¤CÀLîpÝɪ*,V@ú¹ê`ED€6Ô}R¸BÀ¹]”25V?&¼DéѦ›àSÜÈâühªÃ$Ö'¨`-ø€ýóí!_ÿODg–/ÐåE®PÙ=€ŠÒoyP¦VØiسË`ÐŽ’€ËÿPKºFD¯‹Yâ>lw€Þ˜’‘“Y^uü±¨CÃBãVKþ—î\¸rþ°Ò¿ §¤!÷oTÕS·á‚ÕØ%â·éc!™ÿ D÷ŸµŒ¸Ï¥óòÄö« ø¾|ùì‚°+Þ OL#<ÖÅ­¦Š¦th{p0 uEééùÚž) QîM 좖½hUöí7™ ‡/Ýñb—šÝIæYHlÖÓjóSàÿÅ’š.&9 ôl“Å¢<€=ˆÞ:6Ù~Ûb2xgö÷ÒK²º»ôJô{#Œù±$t…üìùò“Uœ¦½aͪ¬MÈýÈ©dòå{ù䡊jíZfY…øƒ@2¸ÄxÿÔ¾+À~×O¹ÊmU³”[ ç¡1¤,”ï&ÊžÒŸ•÷œUã¹Ng!)Ï`Œ¥/Å+%¾ÄBŒÁ–•®§Õá#±÷˜¤æN¶±ÛMÎE'ug#~)àf2†ºåHO´d,y‹l@;2 ·bŠ8ýÄ®Þä²°\Žø¸éJÊ ¸W3þuâM—¯U\¤äý°Æ7ëfÎwpÝ3ÅÏÍÛÅ5ÆK1U*ÿ*Âpº èóýd`Í#ì# n:öO&†Z¡§ÈIuàýž°ØëÃœŠ½{AŸ-nOJ‰ƒ8Þ·.®òhMiSsPëLGÂø Ñ~Žî¶bþ­‡*ÓìkÂönó?œ §í]ƒNÊLÍHÙÁ•¥”Áߤ<Økì¿È«Ú.çßššý‹²ižÑ"´ d(¶ã0ÇÁìyóa¯¥>Ÿ¬7ã„on˜1ºÉºæ+WTã|TÃ}×{6š“pz SáZk+\»Þðö†7¦j‰Õ.¡-ê´¾‚RÓ莻ץÈcÛ µG KMûú4}2¤ò‘Eñ••EŇÊêÖo×¥ûˆñy~¥si=G¯˜éê_â_­ Nݱ°=smc¯édÓ]b=†®î˜ƒ:t½{ñúÑ”wÞ¨—Yã!‚ cšÑ';©Bnæ¬}üâEU€­F XàE˵mm—Þío[µ_“Òq)wïמÉdðû¯ÕËcD>dŸëQÍ£®S³cû¿·t´fÞIL’9RÂj3V÷T “qœ:}qÊF³ Íø³€ÕØ—CgÓÌÅËá2C‹ãcäž~ÞãŸ^Ÿ’¥b×€ß i¦…¤›(ZHsy©æ4§hÎÔðVo¬ ¦¦ÎÞ„µ×7žˆ¹²‡nA~Ìÿ¼°Œb¬aW¢A›¦ ÙK ùFZ³~Êû†½;®¯¨ö-T`<;¢g+û'YߥRØW!­‡-¯ˆ‹²÷åÕÆvS3…Óz3]‡EœæI®|M8Tëçìë[ÜÒl®=!ö,:ÝÙýO‹õÕ¶õðýG³Zm4·d{yŠ@ÆToÈY^ —m[Ž\ùî£'Éðr13 ô¿Ùj\Øí3S †]I¢·Ï²¶9T”É„yãG.8¶¾4FÛ¾¶v7ª¢xÍÃûÔN”ÅØ^AAÁ¯‹p5›L(AÇÑpöÆüf±t[ì“){ŸØÖöÞÚ‡©M`‹3® ÅT¿úñ¤b­Ug…ÈÝ ªf wÓîJ¡âÝ9]øÙ™%©T rÐ"÷c ü®»ÄIǞˠq‘^ôvN)ˆ“|÷CGAîk¹„íÙUt¯«ü C…<2jŒî\ ‰*¬ORv_Œíp¸¦ =ðk¡˜dK[²’Ι/Sò¨M/J‹‡-üÆò°††C•õWüÞQb™áLöŠšŸàõœ×šÜ¤ÙF]§ü¦ýæŸ8íìo‘~1Ëa¶ŸöyGXá )…Ûjàäqà9©ãk˜ã`sí•““¤R9 敨Ћz¹U~(äîu?Ä—â°wGfl¦!GŸËëØ`’M‘–ûa~~¦iÖÇPDçœÉÆÇÄÅÆÇŒ'½ç‘a@Æò®oCV¡´÷=±ƒ“'³¥œk¥ëšz²—?¦‰ßóºE·½î){Øur”°-'¬jùëŸg7~zÊß}mÄFŸPñD¤pÝ\}.ðßOj%,Ѻ¾>Þç Ç]Qó`ú[>žs‡’~ȬF§}|{!3]Z{D$³Ý…ºx)¼có‰Èã±°ŽŸî´ÍÓÑóôÝ»g[êJº3n)ÅífüA©Àp;ºQX‚/Rý‡ây!†—ä¥Û7&øz»A<™¶”äe/€V¾6úH@@TD ûiOª;ƒqò§˜C+p 0ì"#ǾJ†ñÛ9Ø¿Nʾ^/µ¿0n÷>úñbùÊ]™Ú¼Mt›»‘÷ˆ3]üý|î©ôjŠÍŠÇ…h3Ja¶ŸŽþ¶£Êüw( ‚µämJyWI/2€Œ }D*àä©ÒÕÊY%ºC_9‹›p¤ÒG¸^@îõ‡dlèÊôˆC¸#iûõµ”,ì¿D‹Šlýþ験¤õŒY™ê ³aeqDN2µõéÀmZÒJ½~bY¾)s_¶ØÐv.—º…0õ5­æ'p –Q{Ïû‰fSÕ!šüYßQÛW%/~ùîË8§=þ­D«¤ý.ûIVz—²d}6'õEö±oïé%–}³--‘=bÙÏhiÅ0ÿ ¹’uÍ endstream endobj 139 0 obj <> endobj 1790 0 obj <>stream xœ­zXTWúþæ^{dr#¨¹c‹½—X¢Qì5Ä H¤K‡¡ S¾™¡÷230± ¢Æ5nŒ1F±Å¶‰ÑhbÎ%‡ÍþÏ4î³Ù}ö·Ï3:3÷Þs¾ö¾ï÷QV](‘H$™¿ríÄ Âÿ†ñýEü€.ü»b¬ÿUÑšd =ÄÐênÀ„¡6üÂ>HÛ{‹‹D‹–ož²ÍÇ7làˆù#Nœ1cÚ@û¯mn;®t óõ p #oü:zló ‹7ÐÞßàZáŽÐk½B½Bvzy¶/=?0 (<Ì+dàÊ@O¯E9ÙïØ8/pÓü Í ‚†, ]¶$|éÎenË#ÝWDy¬ŒöüÈk•÷jŸ5¾k·9l_ççè¿>`Ãà÷§ š>cÈÌ¡¼7löp§sFεet1=ÇÆŒï:aâ¤ÉS¦vïÕ›¢S«¨Ôj55“J­¡> Þ£ÖRÃ(j8µŽA9R#©õÔ(j5šÚHÍ£ÆP›¨ùÔXj3µ€Gm¡Rã©EÔj15‘ZBM¢–R“©eÔj95•ZA½O­¤¦QQÓ©ª/eKu¡ì¨~”ÕŸ²¦PЦ8Š¡¶Q]©T7jÕšEõ ¨žÔêCªHõ¦Þ¢ì©>” %¥Þ¦XêQ7QwQʙċÜ"[Ñ­.n]N‹WŠOX-µ2[÷¶N“t‘IîÑ™ÌD&ºkß®]Ïu›ÓÍØ}S÷ç=Êzzöü¡×‚^7zÏì}å­qo5÷±ïcîó«§ÍeéÁ·ýßþ‰m|§×;gúŽék²µ·m¶åíüûMê÷Cÿýà: âÝñïç2¹ 2ìáÀƒƒtƒ.0¸d03äÚк÷ìßs¯aØæaEçß4®x»a Ì'×À•ŒôÊÏ4$·ö§?ÏJÙ,kwH«È"*o]+æ‡ñï°è]älªÙ]s_kg¡=5Nêð€-à¡'þhÔ˜Â! Õê9–àÙ¶˜EŽj}j¤ÙAž©x¿–,﫚^à+µÞ:Æ¿”þJSJÑ l±ÅÓqj\D€ó0°#¾Ò6éj¡>†z¹ÍY] %­OËÌEƒ‘·-š„“uJ½Tví*¤N…ø·©Ó¿‘ÄÔé;- qé)GâRtÑ„öZlì:ýdÞ³¾R…ð]X¤¡ku™ÍzKò¤îýõË7OÃbÙÃ$öIé¥ ð%soü7ø®­‹¹äšNî#k+§¥?û¨år¡þü ²{pÿ¯÷f\Åâ<ÙJ|ƒÅ}$NêÌZª@«é§Mã–,Ø0c¨¬¯’›ù &QÕ-´ë–˜÷CÛYôöð—¸'î3 ‹pÌþ4uE=üI9ŒXWØj :r>zØ 'ÊTj66ÂØ^áZá kˆ}À1|k¸ËÖ›€y,tû®˜ÿ…¿Í6|r&­ˆ÷üÕš âô5º`-ñÓ¾¢È¹"^©á؈—¢Ã)9 ƒt;£9í g¡}HŒ<Á œµn$F%ôg%/ FÞø;[¼î´]R¯¿Löµ.·G(ŒþP•³W†iâîËÓ©pKëX‹èä >h—¸ulël¶2åJ%$$s›ì½ë7 vxžŠ'cWìÞÇÑGhÚH†˜ÈŒ—ƒ"Q#KÆCÎÀ"`>Âw£t mØý ÝŸ€‡dº8PSz£¬£jðz câíšBÌ6//¡¢[}¥7Ñ|ô€­n9RÝÌ•O&ckÜsá4{/þ Yœ´``ÖY¥Ç49~ êþÓˆEÒQO±Õl·­á2é“‹4*ÔÃåLÅVY›ï«¢Ú­=¦«€JhQ×ý^~³Û=P°›ÿØÎkÅüÖlf.Y&“)R@×¶N"ÇáÖfI&²ÞuM'‹N”´Ùµá9h Ù.:Œï&)FëI2–EŽÅ+ÁÓ`ÀßRæîòÒgâºÖ9¬9ý*-_%e š…84­Fkq4Ï‘á·ÿ6mÏK~OG¶?“œƒKá- ö¯Îž ³‹#WùlŽZ»fÓûì+oŽ2GlvßBE„nòo}ÂâÅæþT8í5ÁZú¤*Þýüý13x~÷y2 1ŸïÛ_m’é‘?‹Ñàçä̼î#uÿüÖ—_7MY/D³ZÀ@tÖ‚jw‹Ð€ûh³YÜ:å²!’<.lžK|b×Yi†ô“\¿÷efT"™*÷ÅMD)’Žšf%h,T®+Â2Æ, DáÖmg_²ñµÇ¾$Þ)-¯a÷åÅ—wûJ¢¹×Y4ŽTñý¯2u Ñq*MD3ÆXS‰9¯¦Æ¿ÚužÏ×8Nz u¡±ì5pþŽÓ{µÍº*h„fh$U²“¶WçÖ jÏ 6[Сיѳ˜¿Ñ:‹m;ôÏ[”Ô鯓ZÛÛ«m;=òëdHs—þ>ç•éӷ榢ŒNÓ{HÐ(0;aŽ˜NìÓSrÿ~©MmYØaC^úJï#O´ž5)¿‰ùÌF_ÙÓ|N݉äTùš´D`â!%J†méhHÉM×jKK9t%¥ÜjŒ$séCùâxÀ®„<ÙöÏ,·,FzÍ!wIþé~uûî¢.éýuœ6)›@ “饲iRÕÏ©”‰IJ•W•;Ä’PöòZâà[X.« ®R|GRPüÖA"Ibáß³Ø$yÿ¾_M_i,ÿà<›Þè‘ L6dÊÐÂïãIØ »¡)x2Z{åëŠ3»IE)ßRr3n@4Ý úéêg#{~(‹†Xð´"D¢™0p¤’ ¿ƒ«iÜûqBýåªË¸S!ëh"F½—ÀÃb®Crœ³ Ý–ö48v_Ì·òÏÙz]î5®Ü"ñUÙ˜÷‚¹àKLê¬u¡xúO¯ùHê|Ihq\…:’:¡ô‡B ¢Bt þù5¨*7…7‘² Z¤C‰Dòýo°i44×ÚB/LÎ<"#•‚h<ü÷ì_DOÙ²xÞ4eó1Ýéüæ:¨&Éð(z6L@cN¨:WÍ/nð ÒÜ£pÁr}î ®B°j±Éfµ[UAßÐwZ¥’Ïâ‚…ß ûÝ 7ÚwLÏRuì˜ —ÜÈ÷³ˆJù81?Ýe³ËŠ÷_´G˜z‡& BÁY-Ð`ƒ&7 "!I­TÊßÃY¶Ø Õ(òI¶êì*öB I¨ƒ: ‚ÀC@ˆ>iŠ|4#ÛŒ8]j>äCZvZŽ€—¢o©pÓidÅï´ˆö!+4ò®}ŒF°ã79¬W,†Ó>ܱ¼]õ†Àðmq[í/¯ºÿüÊçWseÚ,²Þn†_Mï+€ódÉ­j/áÞÉàEÌ®§€x_Y¥v˜U"Ó¿£ûlÉQK~`V81+v€‹.R0«^cŠ"ï NŸ€³mG ežF ÷ʽ` KìÐlT‡Bìè°ªŠÔ9ñéŠÜ€ÌÈ©8Õv 2¤æ‘]¥½º¾Ã JX¯õ®? yªèÛ=Ct)Ú‚üŒ•›lš®my„¦]ºbî+‘£»_±i•nÍÀ?)¸);â@¯ QÈ·+¦sȉ&Bn¯OƒçÞME[€™±Èii€!º¢ªÄP‘—Z묕UÖÉ%âæÈ)ÏI2oZzT¾QµPµ"`î¶ °•™ù$äüÅCÍ¥\ šÎ§ÇÌßæ²Ù½îèÇM·ÐŒ ’yâ®gßÈ<~(?EK}VÖñ–›‚¶ Vù‘ÀûÀZØÖ¡m3 b“SðE|Ì]þ?Öß|1DÓ/ÅÆŒ¤ìxH° ð$ú@±B“P{ÚE,í;ÓtR²ÀOQ¨%°»öì9R^a©ßWØ,äA°:@Lâº^/äQOú–˜ÄøTÅÊÙ¶³LD^†fÚ¯×,UÇÀNpÒ qý´šæUO1kë´ ÔNk·¬Y­Þ ä‹ E[ÕФ.h>\Ÿ’…`ª®ýä‹jÏ,ùÞMYòü’oII±A‚ ߥ=©3Y°W³«Ã‚(]X5ó Lä~¨ y7’E¥D¡Asùž,ú¼SgµHÛc3­ÕfT63ÒØ°Â¦M_ö¥ÍF>Å’Ù®NQ12=.b‘; ¥ Í-Ú{òã¬r8õÁå^îúµàÞêU;\vú{mwð)m rO%D'[Èõ0ð\äÞh·]ZÈß‹#J|ɶeÁï¢wCÁw\­E⣚@éI”ÒƘ/‘tŠ&7SÉm>œ Ïm1?™TiÅùm¼Ÿ(pÒ… ѱhŠ¢I'–¨Q§& Ã[,F&eŽ:”]E”rá‰þ|C |Ѩ6‘mj|ÜvE|øºÀEË!•t\‘%–´,1‘Eaáñ.M>GÏï;uª\€Ø#ÁQÕ>j0‹ˆŒÛðHŒ0iäÜUŠˆg‚K"ª* Å»>›³÷CÜg<¦ð[øí§#Hjö«A=rrAEðQ¡ævŒ[–à ÌúÉûÑT4훦ãÙç5>u™ÄÙ–W…4°Š/¿)FŠÖ‘l’IE6ÆàÙ¯¥ŒŠ§¡íýèÒÙÕ‘Õ8š+e|½–FŠ¿uIO'Yj— ú¬´\¤iíi«m»,yUH úÏÚ;Ž¿@Ãï…Ä—¿*D<[  I‰Âmgm;,3ÿ6éºø®b¾ÿ›+“Ÿ Q¾B¤øT"Å3ž—6 .DÏH$¸¦­g’Ôj—I¢€n%¾Š(ñ$ÜmçVÌ‹ºIÞ E»öL&n-½((“·>f—Òhøkbäz3«±?-=R¿ÃµÂ±?î6x$f±ô‡Hráàî³ ­°MòC-Øâî*$mEèžà}ªSDö5èÎV4ZöÔž ÐÐkqÉ&»Œz£éPÅϨ£ØÖIlRžFI¶ú¡µ¤ šBM™J«H¦­ôOƒPL§§j5i ~LÛÛì­&˜È,•ñGèJh~A’ÒW³Y½¶Ãf¯Å/À)HÖ6‡~fF4¯½ËMºH<ŽbX“ŒOŸºbÆ%¯ý~E¤~¯ƒH\š“¬KMR+’Õ2ß¡!6Ç®°†€Ãpê­‘Í@#o›wó"÷÷”u@vxEët³ÐVn}!nõBXäŠG“îq^ŒÇâ)Øè´qxZ„–¡Ñh2ráðü-;÷û <4ì³[÷Ð8—àw§„ÜÄŽq‹M¹e!«‹î‰Ñ"AÇI,¸+b$ß>|@_)…\‚2*B˜°¢ˆÊêBCyƒwíú…ï¯Äaz–ÿ |íßiþަfO:ßÞ¡£/Ä(]bÑl ꨛÏ~ñ-~W†_¾1køSQ¡b•u4t÷%h2 Ú줆' ì^†Öž¾]† Ì¦êXÄU4ïjݱ¾Ò_PšËNge•ÚšB³,+¯¬ª˜{0<,Hã"KN ôfD»7pŸª˜Ç—.]kˆi)“Õï®O/& ×È•©rH`¢óŠrJ3ËŠj<#¶*ÜÝ8·Z7}80ã-úp«É˼Sµ|i+øç{Y"VEû¹‚3ÿé:Ô uû©åz]\ËÆ*n}Õøˆ ¢+¤hýÒvZ Ò ¬ØÀ )þ;;lQËñC{èeg$w‘Lu\°idgNàõ/.™Qo_M2ãéYÑgb¾0“EÝŽßAoÍüS–¸ ÑDÍ/³ÔedWs…c Æ?æy)²kÉ\y’&9Q#S8º¸‚„ì½ÀàÙ¬£[]Í |4ðæ£'hÀTœ5;4› ?éwt50ý]݃ò#µjŸÃn‹ôSOlL>TXm¬Ý{Âä¶&WözÀ׎¢U-æQ:ûæ@nl]ãÃhÐ’7‰±ø5ÿ#Û¸3€hV’ÇMè˜ÅFHH ²žóâûоÒh†^²(†2È3éstÕ`æ²Râ÷…ÎÄ#dÏâÙ'å×?ëÌ÷Xrçð_þ kÿqFôJúd¹†hIQxuÛöø€?,eà±ÏkŸÏÇŠ]À\/þ¦*rãå”Bâ°À7*6CrKÜãø¯m£.l®]WJö/b;QêùÒæêË…£…üG,(øëÓl\Ó+/ÔhOèÊ vÖuxa©2}¯Lúc¿‡­ 1ú‡™‚-Ufc סpKë„*›“ÁÐgÖŸ\AÏy[¿mYYèyNÛ}~â“ëèžî’Ái Èíìr‘s{™¢Ñ$¤p¾kªÝ÷M"}¤xÚäAÓÏ»$ËU¶$|ÍHW¦ìJ©ò6çDelš?mÇœô#ë¹5'T4õšœdP½êÁÚ{ðL­.7“­^_{ܲí‚Ï}ÂY]¿þuy¶ô›i†N,# ¤è[>´Ý+Žý¼ŒøåWä-øeŒà—kÙB ¤]’¦.O ƒü`®0ÍP•LE”!00*"xÃÉÀSWÏ]xÈIÛZÇYU‡–ïØºcGyhuuy¹Ð´ ½qü #²oÕ›QÖ}”e·ŽkÁ¶!Idûx«M-¬E£¡„$^ŽÚ¨9„1$1¶AÜ`ÎÃ_²Oÿ‘¿°$†= v TNÒ¬ $-—$l)©[(Ü^€§¶/:å/]‚›D// ¸ˆÕèR3ˆ¦K»|6'ë|K“Î(ÈÚªx$Ê}¥.N ¨RMŽâ!".(÷A¸—-FÿaEÕÔ®†]ШiT¿ª¨ô…¯ jr€(»Èhe$¹ªJ{Fg$b¸ZS-\å áàu\ a’/};e«E”1,<êƒ1N¸›­åø>ÿ¦]èIãAˆÁäˆ~ðIŠ9½²¡‘AWèZ8(p¯f‹zøÂÏkî}U­"%bâ–…­ËØaÞqÌ„ñ^†°mcë ¢V[·ˆ[Eü7lACeõgÚΑ±ÐLtŽŒiŒÁDÐ%«j^Þ¶Ó;ð:EA{³\} ÌíSãEĪ-àÚ±½O½ê…bÛ~µÍŒLWåC1èÒÓ „ÉŽ½ã?p´OêþWgÿ×Ó|£½âîÙ纼>¹ú'#·5Òî¼’_CÅ¿"Î+9µ?g¯ õÔþÒ_ÃòçýEcØ‘ P%çjs·ÅSøxMš:ƒôä»NCE»ó·'…«Î]¸ã!ÏÇ´ÐËÚìñT^®Ñ1¦ÿW_…´ÔšÁ§Û¢™mÚu|*ôä¼Ìˆæ¾¡¾&4×$Fcù»ìÙЃ®¾QAÁÁÅAõ†‚œ ‚i:­V Œâ”~)óW¬”%$É©bRÒ•é¹·¾BÝ8´þÿæ6²ð*~pÙ­‡f›¦ÈóѲ}¥mÈÝdËi”Þªo)oRl3q±àâ_k*Ú•½÷ìÖÃÓñÛ¸?‘ÍÁ2靨€˜‘ø»¿’û¤“¾ÇâÅÞ·Dp¨;¾Ê®€€³ŠÂ¨føšô{×kž=(:+-\‰7l$D²6Eû¬r&è'8#ÜÈz-Ï B ‰ù þ%›-L?Œ VJp/Pç+K™ÉvìNPM_”}>?/3ã:äèõÈcfaQøö‰¸ÿv,ƒ÷˜Dp9tæp-4|¬ÿ8ëDZYÁÝç^‘ÕË›F>Ö ºûRŒÖµŽekƒJ‚ƒƒ¢¶s{Û¶hcµÉy`—útm1³O`ÿx·µö&.;vU;ÚWz MãYç]ÊÝPÌ|òiÓå+6Ì_ë¹e•/gŠe¿h8r .2&š0|¦ý¸(K“—›Ðb&ìsÍŽ©#ú z¾ägdýÝ­_ê彚¸HcLÎòFf¸[ÝpØ¿*²9>bìçn˜1uþ¹[§k.ÜiîØIý£ÛeüP!€Ë!OÀ_x1ºÌúÑ8~ˆóšhGÝî î@Vu±%´0<& ÉsÉ ÷;¤ïEÎÄ™0ýÙ¤u›£\\9w—07˜Ëà>ߎDVŸìk:]Æá·>dcÀüÏG5ÀQ8' ÙØPytO~aÚmÅ.y~i+À™™¾mÔd®Sðz#:ÓˆÆ5¢³ÑÉVO1_„ìX&)(ƒ!beØGB¾·Fs$…ÅÉðÉuÔ¤ÕéóHç›”-QÅËUÜL|Ò¯þ×_…Iâ"!"¢ eÈGâÇYã9’ØŽ dhŠd6nÒ¨U  ´“g'åéósõÜMtÒ­þïðô=Û¾·ÕíO{•1(ðeG¾ð½þ9#ðõ? g^å`4[óé=ßUi°9Ù²ñÑ]ËÝG[úJÿfD%è‹z„dŽ‚PX²eɬDƵ°¸…žœîÔ.M“¥I¦²´´²jgIˆÂC½yÒññ¨O²ÌÅrˆþ9ûÊcÂÙ·\Z’²=ødoÉc¤¿'-Èåá­…J­Z›LpDT ¿9֨߯=òdél•!;èïLcqâ’‰05l)‰Þã¹;¹%žyd…{W(ïÚ?Û|îë¬ÎJÁŽ>ý©í‘mb–Ðüìåö)É¿ãË_#¦Zý¥ã+HJ×VËejsuY™Ìã`BØ&¤7Ý3Ùœ<‡ÖšÑLᵯô˜¼Õ¾Õ‰ÍÈÖé!ƒž˜š’¢à6-^4ÂJóºc‘Å; ý€™³`îŠ{~1óê•S÷‘U4ï<&ûÔûhj=|-–Œ4­Æ¶Íño“â!Ôvòœ¤œ]ZngæÇ±KóÑLôÁ§ùÆã-öƒ1µaþ™ô¶œ_Õ6ü¿#U³˜Eôê{ þ¿e;ǘ᾿™DM·öœGýÍèl•¸uêɪf-ßîް¡Åoϡ㟺±÷¢±î¾@ïÞjG‚ˆ²i³¿CæÈb¬F%[7Êe±ëúøB¢DÞÝŠèg?ûŠ@È¡˜[ VÚ¯ä–1¿nîîàçâŽÌ”oV<½sfmwiÕ™˜ÃÄþó§tw™6/´ úZu,ÌíÆšº³0D½tæ”Ð`ÎõÖäT°ei`ý†ïåkW¦3=ìɉ›»ëOëlêPɤŒÇŠ[磯Ù×Ûöýï¥Ç‡×³¯«»í¯¿W`G½â¹„äÜÿK’è’{‰ì AŒé K3ïÀVDWúDÄ%*œF­Ñh€QCAZMæçÏÉòúÐ3™©i©òésp·Uå.ûëJ*+ºüonë8kÂzã¯ÑÓÓbt§°Dõꢋqdã‡Ö hÞ4õF}ò;Ÿ£Ô+'.ÆÒÕÜFÜ%‹‰¨™‹{~Œ­ÏâÞw—å“‘¦Ïumz;5¡K?#ñÈør™ùÉ­¾RŒŽdóär]E¥ÁXMÌikx$¦V.^¶­,®LÆtƒ8ÎrütaaD,ö\%[:?|<á : yù]ÂIÿÖˆ§þ«½iŠ!æ5!= ×å¨ç:d½ õžú)A…R©Pº4JöÈSx2`/Às¼ñü¶‰ïˆ˜"M™‘óà3$=õ .yH ·™ŽT’›PWº`8/ü+:iFÔ%Tp Qf1‡°g™FÆEKb@£Ud:ŸßPà ÌÐ1ã° ¶ùnÜ‹‡«›vÉr6‹ÜÌ·/~Añx²ÃSñr< OÆ[ðjÄá‘Ó± ™…d¨G19)Ã%‘‡ª!Uõ¾Ç¸Ð±Ààeø4-FhzMGï¢9¸ VŒO™¸ÔZ e‹±ʸ[WlTD3Õ]$Fâ3w¯ÔŽq¨—åG’Ž0JÐ,è #ßÏ ú”·ÒÑÂ"ÙÅÒì´Lȳ˗Ƥ¨!2˜ ZéUˆ>´-ŒÏ‰‘'Ä'æcNN¸õA\®`#—§%'ËР¥X¶42I™ vj®åÐÀcñ‡Ö±ù‰ùE¹yù9ñˆS›¸£>WÒUé*½* ˜¢ÜÂü\eVtVg¹a}ã¯cE¨[£ea=Û8ê×1Oñ»¿ÅÒ‘˜nDÑ!ƒˆ·nócQ4‹j^±3¡âT+)€ÒˆˆŒãp-®¥ã^3*y'‰ƒHƒJ ¸ß$eI6 ú~½pdV<zÝ£è?”=”ï.ÃeÖüðbÛ$Åh„:´SkÔŒô%Oï6žÛUŸfàÜÕŠ@ˆa¶WÄ—–•í:³®É~8,ù‡™ß­€®Ñoò™-%豸ˆÕj5qË?Úê$S(ÈâÊv´É»qÑB÷y¼¨¢¼Œ¬œ7MEJƒ¼ÝPbæ^JÌüóõùßh…µô¦’¤¶RçWàNŸŒECdÿÙî‘…ÅÛ‰CuèËìJHªâ’”1‰ QY±Å æÃÞ„}rk‹ßõxòÛ˜Qè]ág+)´ê´(•ˆQ5ZÅžÆ%kh!…³L"à•b^‰²XS›2œ~¥y:Hÿø*àN 8É÷óËY§ç HØNÖqÊÄD‡ÿúÛ¼ÔxR'êvuU–“£ç:Ù Æ¿0 ’⿃pAùšZmM¢½·PÖ-1°ðuê×¾_:?£È VÁ¼`÷q~‹RgÃ07mâ¾9ûg^‰ÔëWÆßÕ\J¿7샯°ž°Úõ½ü,<‚3p.f(Eݯf›¡.F•ŽÈq€9°æÂbùòØ1k\Ú[’ –'ƒ¾£æÖ·ÙrÐ…q+—O?á Î@u¬‚i+$ bÂDÎO˜߃Fòw¯}jìGOTå6³a¸†~þùG‹èèÏhëC1ïˆæ±!’Ô€”­‰±)ÉK!œ€ÕÉËhâΞ€gvH2ñkÜ [ÛŸäpôÅuyû*¢*|“Õ QqeŸžh8 ÌÃý3g|°iÖº•2¼o— §(¡v<-iï.# -CÝ~9zØœUs¶›"«-SõQ'ˆå,G.æ×³ïãð‰ ê5Á[e[¶©B4ÉšPu $kR4ÈHÛäòL(æH¾iX<X´c«ëÜâ3¾²ºT‹ ö0õA†¡~q['<^ŠD¨×ÇϿYq}ˆ‘k÷)êgáÝ 6¨ùÚ‚Ë}¥?V¡,*"œ:Ùs;…QÕ1h"ÇÛGUÓü{ÏhécËp~ qzFL’JøÍ>Û¶Í™ßÁ* Rñ]­Û G]~ òõ½esôé м/4JŽÈ™EÝg<ÃÔ×_m  ŠÚ”B¡½?˜Ÿ¡JO!x¤J•E$mŽXàœédLÖ«‰KI™#ÃG±&dêôi\nQÉ›p ÌÎYQEÞ:OØÄH_Xêêéì ó`íñè3z^“ Lm±¹¼<Ú¼=Î7Åyê¥QÈ 1Ï¿GRa.½Ø±hÒM"3Þßóë„“ÚBp‘‘Ü?Ü|ðOBê}w;¬Þê¥Låv48¤330õŸÁ òþ7G'„^²Èš~òMÓ§Gª"‹QE3>…6¤2IIÀ`šþ}²ÔÎ j;Á²“ZäüOÿ13xª6+“a‹ÒNz›Ò¨ 7ôÿ÷Ä0y­GlVçfØÌXÜ•°Ä蟋ÄK;øÙ½½gÊëR+9OuR(D@x^LIêCµ7Y¢(ž¶ŽøO‰âÖ›D±ývîsÈuf$–¬ø?7æÉͦ¿ïVÅTp‰êà$رѦd•0®•3h–ü9ù$žc•ÅhG®»çÑ–n—ºsݬ¦zt5e÷èqÉУ'Eý?Îê¢æ endstream endobj 137 0 obj <> endobj 1791 0 obj <>stream xœuUyTSg¼7 Újß)Zæz:L]ª"u;õŒeqTÔ7!, IaS(„@HrMd‘- B—a±¢¢ˆŠŠRµZÅZDZZ™Aë8=ýó1Óy Îü3óÇ;ç}çÜûÝßïwïý}$áîF$) ôŸ?úçǽGrÞnܯ€c†·G ÁCîG¼é'SPÂÛ(h2šó! Éå«7ËäÙŠ¤„D¥Ï‡Á3|ü—,Yä˜"Q$ÅÆH}Âc”‰’”%HöY/‹M’(³çø&'ûDŽf¤ùDJÒ$Š IÜXé`YŠ<])Qø„Ëâ$ )AS¥2Eš2]’ôÙ¢9óüç|LïkˆµÄzb±‘øŒXN¬ V‹/b2ñ61…˜J¼C0ÄTžA@N"•äwnEnWó&÷ ÷~a°Ð*ì}*2ˆþE™©g¿Ëw“~q{àN€ ípq!6’{w8Œ)>¨3çB.è´š½X2ò¯Ü²ÔÕzZJ]6á4Â)hÐÑ.*Æ °ó'3M'Ð4/dÃþ¦<ÐvZJ(X)å0ÞãCá8FSVA6ävÐØÊÕ2ˆÆß qŽˆÇ æ1pÞ6ý(¶_À­CÅ <ƒFe‹´m«9 f‚d±:“Ö¿aï|¡”º^R¸YŒë¨è|XÅWi0öð5\ÐóØê<è£ê§çûú*£"Xœ÷"7ôMô¤_ÈÁBUËÍ·‘M¨i@ÀmG»ÄÌx…iì1ÛOÁïü8 ‰Ð„¡çh ‹wáh&¢«¥]òNýE8­p¹¹³ñËãÕG  Že;ãš·AÄC"„§n•mÙ–%Ñ*9—ƉþýÊÏ÷è”Ë µ?½[bý~V]¼·ä´Ô‘_m³U8›ä;Jçf±z$áéÿƒw£ñ4nŽ©›IéÊŠù2‹ •[h!u¢ìNºÏ}ÂXÀ¤Rg¥²ÉõÉæÝ@cÏ„•ò!±5QÜ";\x¢à\~…¶>Ó’S‘2z‡bKÀÊ-­?¦³Å0è ºýÅ :4ÙbìMeƒ¦Ìd0ØkXÓ0VU·ní êî½×³«¥ TœÐ,7¯<˜bª„Kt³ýÄDšç$YƒúìºLñkAxÙ§»Ðbùªy× ÐRÎA¾.ì‹ÂÒEúfÍÓÒ™q3…·•g¯ê»Å^Hß@KcâBáY ûz~x¾ïµ¿™t bÞ¨J-Œùt‰æäYý‰Â¾£:€v¾Ϥ švÕ¥väáá·Àa—ËQÝ @ûSH\&tQ¡ê]bÄQ<Ôöx¨HnEÁcC¢îpSQSkë˃Ø‹>Àoa¯¿ÍD4±v³f‘Z§ÑèÄ©‹V(c€ŽñkDb+e°2%Èÿ±¥~3ö5$O ޱ£ç¾·#£¼|ßhëâ¯B+™“ÉíPô“k×ï:Õ­»[Ämí'ÁûG?ªX£‚|:·,¯ºÄbªµä6&~·;'—Mq$Vðsç¿"ôw‘GâË Äy9ÙRˆƒuG%šm_lK€Ïé僑h2šøâìú‹kšÙ¨†M°" ²­ª²+Ø¡Æ\SVI¿P1ðÒaާØêj*³ýü”Ù°s\œ%MQeíĈ™Ôu¡ÄØÖÚ ®­,…¯~€„ðñÚe[çŽ6|òÈèÐíhê‰È+Ä0 Yjz†<¥.«®ÙÒPËbGð ¼ZZÄ7°þ¿ã~Š_Ýrè…ÃcfRljsîÔk˰¿ï"-Ãáq÷™Òúšãßø¨(ާ,~Õ¼‡ÑWÉ Š@W”‹×Œ¨¼ð&®FSF0Ns†zÖE¥é–d i£}P U±è‹‘/S®QS •`Øw f¼evîë›yç y àdÃ$ãÀEö]E±•N%ã­ÂZÑ>Ki_Ey‰ùŸK£D‘/ž-ó˯–±Ç ­‚=MšQ‡è“×èq†ÈGCÖÅ8•v…4S©H©Ïr8kíìxmÛðtÙ1€JxÃÚ€¾aàæ~ÂÀÎÁµ›a„HãËÂTဠ˜y èhHÛ²iÝðNw»zÞ1>‡^ïÀ·™Ý°Ê’…ÈüK0À÷ëp»úb͵3Í_ò®Ö«´.¨ˆ„¥¼+`Y~Dv ËJ„qò|'Û]Çyò²Ô1Ì00d²iòMñ¯œNùzÄB%hóØd©Èiâ_CðWpòL¦´Ç kô®›èƒHè"»Ñ.^Ë0´”Ii÷¨7¨öDB ïXá"§ãòÕ†:4ùœï†4¢æÝåšýpAÔqØgo¨jiÌ²Ê t ×²Öë='ú~Ø2wáæÀÈÕb3„iIËçüá9úMò|z­Ž¼þE=ãÅF˜Ù£/ÖC­2…=!zØúûYøÝÐÄÍ[–8¾’Š[4. ¥]6YZj®dþA£ÛþøéË?ÞšUÃ>ª?ÿ |Kß[Ò;ó·A±Íê*{]USKZezѨÖëƒüÒÒ‡úsfdi×KwˆS¶'iåúÿŠX·WôÔWôÏa1cS®Z yj÷Œ$¥¨z¯S±™RÑ›Çõ»qûÖ–ýAüô¥ËZÉy2#ž¸˜šÄ¯Å2;n¨B²2Ž)§\ú'²ÜÙ<~e+õðè¯öð$ˆÿ®H# endstream endobj 135 0 obj <> endobj 1792 0 obj <>stream xœY XTeÛ>ãÀœ#âÞQÐ:ƒ;î˜æRù¹ ¸¢¸ã2 È&»ˆ,Ã>ó̀þ3,"Ë(¢2(’–f–e¦_¥¦¿iVš–fÏ¡—êhöUß÷×ñºäÌ{ÎyŸç¹Ÿû¹ï32Æ¢#“ÉXG—ùë§¼,ýwŒ8T&¾ØC|I$óE‹°ŽDK°–ƒµÅ‘…¡ûcx_œÒ‘ËdNÎîŽÁ;£Cý||ÃíìÇÚM™5k†Ý¼@ïP¿mAv.á¾Þáô;·àm~ÞáÑ“ìæØ­’®³[åæéíÕýpÇàÀáÞ¡v.Á^Þ¡A ÃÌ›4?Øqç‚…¡Na‹ÂG,‰ŒòX¶ËÓ9z›Ën¯åÞ+¶»úø®òs[í¿&`màºé3fÎzuŒýX뉓&;Lyyê´Wz1Ìpf3‚qeF2+™QÌ*f4ãÆŒaV3öÌf,³–ǬcÖ3ó™ ÌÆ‘™Èld0“wf!3™qb˜EÌf1³„™Ê,e¦1¯0ÎÌtÆ…™Á,gf2ƒÆ– e8¦'cÅ2}˜¾L?¦?3€ȼÀðÌ ™3Ÿf˜±`♯d+d¦“{{ˆrù›6¡–ƒ,Xv(§Y Ö›c¹”žC{²²µZou­×¼^W¬ÇY÷žÖ»¼Oß>A}Þí›Õ·³_I¿¯ûgô¿6 jÀãö5/Œzá?›oä0¨aÐÝÁ£§ þÚf»MŒM™Íç¶ laˆlHÑ{CÓ^t{õùM¾RÀÌâÒr™¸¥cŸ\ªÙ¡ IMŽ&ºÎŸl’c@œšžÀE«ûôg¡jà¨Ôpf6¼!8/#ôúÌvdƒFÅ{ÄÁr¢JÑ ¿MÐ?@5]8%·Ä9rÔ’Ä*útX‚Y´2ÉPŽ2Ü‚2¹¸Ïðßz¾Az8ºøÎõ´ØCAf'YªØsYà¥$Tl¥þì§G÷³ÐEæjûùCư9©ùë–F¨|[ŠðMVše8 ûâÿà‹òÃóyÕ“ÎûÃTâzg]»}ïÛ™‘Þ9JY³ÿ:´rwg\%Ó²†|Àc%.agoXèåHz*ÉXòo¢;‹=K³ÅÙïUÂ*ûüÖãå&¥Qb’Õ£5棵\¬Á`‡N~@¦ÓFAdð݉8gÜz€¢'+y2°çõVx³¬QYqäX©Þ†Æ%Áå>°ܹ™@8 4Š L¼וãR#zšeçp˜¨k–w¨;¦ñ•!Ìut;±¸jØ’$2‰Œ"Û‰'Ž%cQƒNÈb´*IÑíQ«!A«L$¿n ,…©¥nïù6ùŸ໢OZOŸ¿ò0÷\ìíQGès ¸JÐW)i½ÈZ3Ž2‰ƒeiÉ 4@£¸—ë9GÙŒuйjñ‚+£ƒ'‚iiá¹fEª-;¤¡ß¦ê°TôùMv>–én Ç!'G/ŒàMY8{ ± É»!šó4í®®6•m[·ßýu?'XÚRr™ùç–ºBé…kPEšF;¦Çé Ò¶kéçé¶§Òm[uÌæ;owï@Q«G‚v¸ oЫˆ-ÖžbïeoßÃü¤­ã…ÕX‹#8ªç’Þ4ºéíLŠI´«“5}ˆ1ÊÅÞâ¾ ²ö¤h q–žœš\¼Ýà\ dÐpìQŸª¬I5¥d‘Ä#¡àÁýÃ"×;ßRʵºÝÀEBz¸’°ì.H.ÊÒCq¹°¯ì˜ï[P ¶§°>Úž1E•*=øÖä.Ë[‘'¸÷oƒ内¡zA—-ÁÜ•êÂçIænt·ÙËhCû wóŸ™a;ð‡å°–ë9ÅB$o Š P{À*°/tùÄëXØ»€Öð¨äâ±ößPÄþçÆ½ðyQûQåÿ·Ã2€Ë‡Übº9YsǰfœS.ûvaïf9úˆ£xi&#ÑÍC¡µw··Oçv\#õì°ëá—.·œ¾,´{¬c—¬€ •™WH>fÆRsw¯J1†u 柘A4FzØAñ )%W±ô‰™ýÓy© ÙZýOÐHŸ –Â`ëäØ_ϳ”=hݹ¶çlOÄåü3®gçlY>{nZõ)ï±Äé9BÕì˜ A?U]†kfA÷ªç,ͬK2VŠª²JòŒ"FÐp? -Ì Íð Çð‘êdÑyŸX¨ØFýCh¦ÇCh”@+Ý@â‚T£È›eb’؇Ï*ÊÌ~èTóÑhÀv‚VѰ5©ÉZЦª•¤'É%<°µl‹![ŸSÎuw÷:¼ÄÞ|VIFÖ;Ò‚4q4—ž×µC6ç ˆ£HS+‡“Âb“åÛÚ\éý×ÓMl kΰI{ã23Rrà 4éÉÚô9d¥ a°LZ®YDWûƒ;v­Æ‰ý³¢3“+À6¢.»ü –Úú½Iƒ>=3Òl6B„ bô_S…Rßt‘ùNv ¤íU>´C~¦»ºƒ@E Úæäd!mÈnÈV]Á҆ʌ©ÉT+i4Êicí±·eó³Jš®³è@VÑá?&>69y&تسz=ÔSÎm†ý’„Ú¹7Kº¬låC´D9jé¡RTé/P^®£+­Yø´…†˜pM¥|̓ƯWÇRþóõûf¶¤¬¤¬¸¼mí©„#t OnPÉóÒÄ;ä%×M»ü=•{Ýùƒ'N–6Óïú¸d ¬ Û® pߤö‡E°ýDl…}Õw¬I×5±’bh©gGG¬­Y±Qó2¬…í@Ïó.¾ó´§È&“ø¾YV!A)IìË 3³ÏK¸÷Ó¤ý±±t­—žž¢M—k/yë¤Æ £ ¦)víj¬ó,ºtŽJ J·Üâï´Ò  z]]>4q¦0c`@X¤ß¦³×ߺÜR.ôÓ)K>î‹ÐJ.úbO>?Ô1Zm|ª¼kçâÉtôœpìŒãà¬3šT­V«Ñ*ÓÓãö@(çq`wµ±© õ:a kˆÓB*ÄXòâ·“q N©G.‹b×bü°gyÓ*>–žS‡y’,L¤À¤œîGórAZmHZ´&J \¸JQ©ÿ¬KD|Þ…»pVJGXFP¦VœxJÇbuçO{ ê°-CîÞ<¬ëèa£“R¬¨Ñ?†ôx 5´ÅûOÌÄ„DHŒähäÐ(ö¢Tœ%Åq|NèÁÀ•©a—@~U$¹–Í Ã·-(Ôw²‰ ôùɶQ9P.ˆ½%¸ÑÒC‘4, ÎAñGä=SKøPRbOIz Q¶µÖ‰&tøè©ÄŽŒx0mOµ–™+×±èôœ²E–È:ïðË×ÇÑ Oúü€jߊ&eýé3†J8 -Ѧ­Ü³ ÕÀV1¥UŽæŽé¼:O«‹¢×…ü?’jbŤίóâuÚ°­C¥R¼ÆB…N·/³T_®+¥SYjÜÙwÁð:„SÜU²54uUéµi:-DpÓ%lË–ÓŒnµønŸxW.®Ç¾ÒÕuÉW6·*=šÝ VJºnú(2€Ø=rÀñ8þØ“’¢=£MKQ†,]éNWŒÒâÐÓÊZ ýQÝaccYÃÁ 3%¬b­Û åÀù.ßÔѯ±K…,ÅaòŽJüšG_"àhJÂÈKd ñ!>hG†áNzØá0ôH'¹À/çzï·Ý?Iý†*Õw3ný°åâ¥ê3TåUÕn9´2ß…ÎFû„™œBýV«fK²X¶î)çaue–oKª2PÒ 3éõHñøƒbSž^«1{Ô‰»!’ÛÖ½¯¢±¨å¨Oó"÷&œ0jžê2ùùoU¥œI–n_Ô„íÝ‚[iHT#¾Ãã?øÚ×7!3á&™¥ìœÐM&Š?«"Þçq2ÌZ´fÉJ¢ÄvE·ñ"›ðå»W0þ:†=1\—ã \ÊŸ9 Ežúôb[Pc|®²¶¸*³DŸžJ mY¸kß¾Â2cUtƒ‡Ê32:Rð¬òÊYO‹#¬þÇ€\Ïf?åî]Ѿt¼¨*·cÂR\ÂaçúþbtÆWo¼uåË•µ¡ù‚{Õ2˜JMóVHÕ©²â›èxÌÖåpØËÀOƒŽ‡nݧ͛Áišò4qç?¹·Î×w%µ<6>§›Î¿EÊg–X곿qÅ£7.”$üwŠ?Rþ;ÿOW¼H`âM‘f‚éù.ܹˆã¥¹oî`ÈÎÝÁOîÈ1Ktæí+Ò/A!×f:sÿþ­Md°QȈmÙS€®¬äI’ÓµêDAµ1Ô¸áð8Jå#æL!²Å› c•'×íOyþ0"_SYW ë9UäëÄb*QÖáè$A[ QÏ|‰k·/Ñérr…¼¼œ‚êêw6_“ܲÃOž|ãr‡Èª%ßÑÇG¢¼/OÊð3ièzuÌ⣈"jÊ×9(˾‰#»Öù%¯R\Õ?¢à]ø'\•”ìxñË«,ý:{FéÑå´~0è.É9ÞD~ÈÏÍËùHR1!š(:»CÀ­‹êØüªô¤´”4ªbÈR2ÚRT±™”Ùøè)Ȇ°ÅùE¥Ø›8Ød%Q²Õrê(ˆ¥²ªJÿ]Ø…Ð,É›ˆ‚]lFZF‚¤­äª\j°D±[]ˆÃÓXÅþßqñì¿åâþ,1z%±"Ži8äAœù7:p K¨Þí›Ñå²8@x+ñ~[7¦ÿ¤Ÿºãü¸+Ο÷ÊJ “hìèE%¼oà 2s/WbVh!‰nqAw+¨#ÞŸkC<:}I€¨¶üÚ¬ð׌oªÊí»äëké••£-–þÊÓqwnÿ[Ím‡ß§4ܘ^ê ;9Ÿšð†}¦’–³ÛÞNú“Ù³Iáb E¨F›ï>£ÃÓnÜeÒ+jLß& Œœå—Aè[iÙ±&¸ 9öm?yæ¼6Æ^!<ÝQ,D«ürºIÚÏ$Þãsr)L)­ù(’ŒÝ¯ÍÔäir9Å´‘u¹ÙKòr _PGÄáU•Ãâb\] —86r‹Û »º° +K((¦.­pb!Z¼wå÷˜ÅÛ4Ü«xöªôòÄ‚sßéCð÷hr ‘ÛsÆ­©YqÙK –v9Á:*YºQ{oë*µ0²WZ×ïÈâG|T^p%ÝåÕŸô•7OlYâ­ZµC =_áë£?UÕE›v™Ã(¥½öZ¨£½[ûçŸ;~¢æYÈGªÐê” •’>}ñ¹8ò 8‡ŸìâH¡Ö`4B׸³Ò?dÇî­ O­D—Núó."Œ}jå½¹hÝüfÑÇ Q¬åíáÚw÷àÊÎW®JÈTæê]`·0È~Ƴ¾¥tá@§Á )Ç]"×5 ¼vxzšwOƒv‹¿œë¾E#Îëºvšô¾ä"¯™½ÃÅmKb’V i\b¾ÚPøÃ ´ý`Ç)·­;wxùTû´Ö–eg ݯ\H¦ñçÕ´Ì {V$‰‡LÐï*%h¡Â }6¼ÓÑ-óóu:Èäòã!5Q‘!IØEĨq"ΑE8œpû"ô´õ¹½ù¯ü×$Ü•ã5Ôó€ÎN¸ˆ G.¤BjàRã!> 4eÑJ´ f²¤Ï†d:± –ññ]qÄçÃÞ=÷ 4Uì‡è ¸˜ëRøóÉOÐÚ(½,D/J|ÅÕ|ù¥~Ó*÷H^#DÕ ê¸0á¶×„0í¯l:µåÑDA&ø‘ÞÂèçºî_ØÆ…lµAë«$Wþú­8‰í#öÂweùØ.Ç÷q—´Of¯çÓZ^úk)Ÿªº ãÏnå²sâ¹˜Ø±š§£™çJcsãv¥ÅǦÖ¿N£©¡™±.T”eæž!Õ$>0ÉZ¨D•^Åâ%þ` I j ÉãÆ‰ÇLÐáž=ÙÆûCXA”1´:¦0.Âùì“….eU@œÛS8ƒŠÂWa9„=±QQ;Õað´))ug˜[hõbÑRŽ:X¾Vþ¼eD.ýd²KU¦8í†#\gQªØfýÐJ']㑼Ä>½ Záy´m3ËN£-ºJ¥Gj¼Ó#“]÷¨“’gêK'+š¾úgQÊ¿ø° îqhe÷1U‘–ã–MXkÞSYßh<Þ` ÈŽoÏ4w·e®ã쵎ž*% $QêD:¨£mw‹3Ùg }pð¾ÐÜ(û { ‹$Ë ñ0Â} #Lä’ŒîJsNQ=ÔqGƒj==‚‚<&?\ƒ}qÖç_=|#ô[2¹Fø²æÝsð9wÅñ=¢$³\_Ýp8f_íÁ²ã•꛲„棂¸Ûà˜¶ÙßSâ¢ñÖÄk£´iš”tH¦Þm ôYV©ï~•ÂO%¼§ð÷ÍãÄyŠjmfh´öÄ ä~ç K¢(•I¯|PiztùâqÔjŠÁ<ù˜Àï‘~Œýq¢é{Ú¥R/Ç`é•á$±˜?TCMB¼ ŽÖ—<•Ü^È×j U-lŽÙ˜àFg{Þ¦’d}º>¸xPïV’*ìÊsõ”Ó…üÂÆ–›4Ù0ñuGAúnw.|ÛOÙ^p¤¢1¤f{àŽèMÓ>Ÿ½pÒýÛØû̼E^Úæžä¯’~%Ø;÷¹ïêêOÉy‰%ÿ¥ó X¸QØv`%ì¦è°"£}H/åèW¯¿õgä"}¥æÇ¢“«’Ò³…„Ô¨Ýц˜Â:GØ>ñùóóIVn-WÍY¬Ù e½+‹åÖ=äX[£¬Òº·ÎºÃü/ïðèP endstream endobj 755 0 obj <> endobj 1793 0 obj <>stream xœ­VyPÙïaph•"^­;¥éÆ#º5Æ5›è²x°"¢x䘇aÄáv`†žûc†¹˜„9Â=‚‚(‡€âµÆc³¥)uu³U»Q+U›¤¬¼™j«LZÙŠùÃÝJ½ºëÕ÷Þ÷}¿ã},8ãp8!1ñI[V®ûŒðÏåøçùÎ&5ð,7 B¹ì›7uú ”1Åü ­˜†q9œ[ÄäJ‹óD™‡eá‘1Qá+×®]¾!G˜'JO•„ǧÊ sReìOvøÎÜt‘PV¼<|CvvøŽ±ˆ£á;„G…yBÁÄÝ1¹9Ò|™0/<>W Ì“`6]’+ý4ï¨ls~jš0S´+;ðíX"ö l'–„í¢°ÝØ'X ¶ÛŒÅaÑX<¶ ›Á„…`ƒœYœ›A¿ äFsO;&ÅLºÏðn…ˆð¼sò‚)s^s„W±°×A«Ö` ¯™—ãŸ9Òp‹JP aöZcrAü!fª<*é* ?Ôš9ø¬E™«iP•þ˜–¤¥Ò¨DÀ uµMÕͶFÊ}ñ †Qü«$ïþµŠÊHÕ¨=2¡PVšS”^¶ô¸²Ì5••^3ÙpÏ5ä¼$ŠR]‘¶”ZÏ\Ô« Ðñ¶cng½Õe%Ã^s^Ï{“3 º‡œ÷¸~ ò/¶ß]ÍLcf±èfü4 hZL2ÆM2|nFÜ—¨®ëƒí§j=´=%‘8’$íMÞøÄÁÌnúp¢! ·¹ß2³:›Ö xE9©ÌkK› Z©ЩcSµÔ€Ë©ù^°T[¬ÍUÇ©S(ÂZÒ”vøˆƒ¦¢Hõ¯„¡„ý)™" U>šìÌ{âÕPªÊ¥®Ê[燗ï¯Þ!N•2S%ŸQåy)±{OT~m3UšŒ6*, _€ãã6?á¢õ_´HMo¼TEåv8N¡k<”ˆv"ÊG ?úCPÌ-Þø® \¾(Ñ^+§ζŸ´Vvþ7Þã‡ÉÌœí&!z1µǧ©ë_ÄË“Õbª®´PlŸšÛ1…Ý}XÇv)ê)9ТÒÔˆ¿€ZÁ-?¬Ð‰Aƒ—Ù‹š|µ§/Ä9²6fîË/%®¬Ÿˆ»µÍfÿæÿ+Ðò;Ã,– W¸þÙþB¬¥¥ Ä–’Æúfgï@Úé-Ìä´¥{~{KÞª&û”ýJØ…‹¥ëå'šÏ—’çÍpŒ¸«¬¦@–[’¼m4ó ´¤… |óqCšÌµdÚ oôÜyÔÒ¥8Æ®Þ:.¾ŸYx¯qQñ5¯ÞÁò J©u¼.YU F0ó=%fež²€†€ùÕ¤h^É[Hñb˜ƒV[ rþ¾Žô ?ÿFFå`(¦Éâéëw.…¦ãV8nme;ô×]øÐ êôqn|Ü@©ßOØNØl7÷Ø¡Á¡2ª„i:Péf®.ûo„·1úIL ïROÄñß3Ž™ûªg‚TüqÚ8ÀÔ}Ƨ©8£c…duBC Áf¯cU-u5MB-¼-Œû}ã*ÁZU7Vç¾·Òþåõº®¿Ú?—0Z*Í`Ât]aŽJBëÉO˜~M1è+ÊøE¹’œC€'Wôu\ïø¶éeó˜kÁ…gùR–f"Õä2ÖV‘6_Ë‹QÀÝ‘£J©\@‰=²öà«G%—.v¶·7’ »zÕ.èOS¯¡Û9ÊRcƒ!_MÊwm~Zjß‚òÂîpý…þ©Äòøòb•Hc ‹zÅÇÅ€3\f ó!={ÿTŸg¨‡rìï*8ùÞ—m÷´8þ£$ÀÒWÛ‡}hrÃYªéúÀðÖš›ö¤ê ½š ó§Œçƒ2ÎrPÈ$½ÍE#•ĘQ°çÛÕ&Z§4td$]nP ˆ¯¨†ÚA£J©Ó•Œ|EtÊ4òלÝô% F“Ñ´xÌ¿„¢±ˆÔ½ #ò²<÷ûì'Û²6‚±ÎÝÖÓÝÙý¿•Þ™3ó%úî"Q°¦|Ÿº WÄO?˜Ç  ²AêpÛœ¨Çk*\Gгå‚ô®â§/üñ‹D\U `Õ¸tËe´DKÎ|Ñ&—¶¦Ìe‚™&’™}nÓýó½gœNêª%’™8Z¼íã$àïÒ?p ¶£ÉžsTÓ¥¾~–ß×ìkè1–¬zCiÄ<Í9w9õ«93ýè)ZHüàé”H—²O'-¯li®é¨é¢¼W<ìªnc‘sá—…MËDL”æ?t¶w4?§³FvT!QQŠl…„–•e•³K.Ô* 4¦]xÞ–T‘3_jü2¢©Ð&/ææ¹éZw««œ0–|_`Žƒ’ïs2ÿcâøç#¦¶JÜ䬬·iÍ9Y:ȦÄeÊ\úƒÂn°Sô¶B(€ ½JO¯büˆbþŠe€ïIêüÎk>aöRßû#~œÏ,}5›C>(ùLèÓMÏÑLÄE³QP ›%öÚÈö0@œå<¿öã(ÍL¥3h5…pŒ¿ûTÆ`·»¥©†¬?Yû9k(cÝרA£#Uy%±E©¹ÀŸP\¥‘Ž»rô¼ïŒFC`tzÚ†{Gï>{IU}ÇÔ¼3®ô Õ1üw‚~ú<õ4Ñ}0vß¡C9$}w+`–è÷ÿ‡Ù*ßø—iq £F“êñM¹3•œ¼Æ:Ùk Ű³ada endstream endobj 463 0 obj <> endobj 1794 0 obj <>stream xœcd`ab`dddwöõõ441U~H3þaú!ËÜüÓëÇÖnæn–•ß'}7ünÈÿ]O€™‘ÑÍ'Ú9¿ ²(3=£DAÃYSÁÐÒÒ\Á17µ(391OÁ7±$#57±ÈÉQÎOÎL-©ÔSpÌÉQé(VJ-N-*KMØìœŸ[PZ’Z¤à›Ÿ’Z”ÇÀÀÀhÇÀ ÏÀt[øFßP¾ÿÌœÇRüX;ŸñÞïÌ?Í¿WˆN›0yB÷ôîéÍ&üÙ÷}¦DݤÎîŽnކ¦¦†¦ ­3[ä,üÝóˆk[ÚZ»›$¦4Mëëíž4CޝtáOû…¿—M›6ƒíwâ4öU\—¹å¸XÌçóp.™ÈÃÃÀƒ jS endstream endobj 371 0 obj <> endobj 1795 0 obj <>stream xœcd`ab`dddwö Ž441UH3þaú!ËÜý»ï‡ÿÏ&Önæn–%? }·ünÊÿ]_€™‘ÑÍ'Ú9¿ ²(3=£DAÃYSÁÐÒÒ\Á17µ(391OÁ7±$#57±ÈÉQÎOÎL-©ÔSpÌÉQé(VJ-N-*KMX휟[PZ’Z¤à›Ÿ’Z”ÇÀÀÀ’–ÅŸÎÀÃËPÂÇÀ t(Æý OËø~tüî[ð#mñÌùŒßsÎ1_ÿã¸h÷åî…‹—Ì»hñÅþ =ýýÝ9¦5w׫E8wÊýöfïÖí®.̯­-(ðiçhiéjlœØ=µK~[ǃ²nuŽßQìÝÝ™ûÓ¶åži^ÕÍ1}r÷´©­Ý=ò6Òv4­ï˜ÖÝÛ½Žã»{÷Êî}SëÎz/M™ökm÷¥îå|ÿE3õ+è"îÍÌß&ŠÎìžW^Þ]Q+÷ÏŠ½¶»bþüîy3倎?¼àûûùŒ‡ˆ3ÿðÿÞ'úÍø‘ÒoF3#%…Ç&_¾3>xòEêÃŒ?2À|x[´ûh÷Úð +¼§dws46v7@|p«mCÜ”ô¾†îÎî Žß@ævGô6Îð<]¸©á7Wf·Kw>ÇoönçîÒâ¢ÊÊ’b×ö¶®ööîVކ©ÝSß?Ùw¹Wî;0|^vÏ^º|æÌeËNõsLšÔ3âý„>³Ýï9øJþ´_Èö[`ûf®Ür\,æóy87Ïâáa`•BþÇ endstream endobj 314 0 obj <> endobj 1796 0 obj <>stream xœz \×Þö„ÀdÜ: êq·UÛº×]qkA±.(Š Š"û’krÂö%°†E뮸âÔ¶qm½ÕÛV±ÚUmí=cý~ßI„¾õ¾÷U‚ÎÌÉ9ç¿>ÏsaoGðx<Á OÏÓÍÿÄâq£í¸ð3P”àóx«×n_/ y{Å;cfÌŸÿÁ×0aОÝác1žXO, &ˆ…ÄDb#1‰ØDL&<‰·‰ÍÄ;Äb áEL%¶ˉiÄ6bñ.áM¬$Þ#¶«ˆ÷‰ÕÄtâCbñ1“p#fîÄlb 1‡XKÌ%<ˆˆuÄlû°.G¡“‹Sì[ì[yoýB‹è;Ç`G´;¯q®r†.¡.çGºü£æúuôŠÑ÷ÿñö?~cf3"æ;˜Í`ïŽñóý؉c#Ç6Œ}<Ž·b\Ƹ†q×ÇóǯÂ;ÖO8=qÉÄÏ&͘T:™æªsUÀø›šðê¹`>4qhÅ!™:„ Pø£A]zg4eRZZ2H¤ÂꀖyIVԀƦ8ÀVÿæç’Õãâ@hX ¨`_’Ú:ÐX’^(ÏeÓ²c€PhMŠ>s@ΤeIØaô4:þd‚ž¦N_ÂÜ[t3(ÛÃ,'%BAb1cY—“y‡8><ÿIC(r¨"ËÌ㣀”OJ… ,´T³+Ѥ%p’ƒ®45 ­¢ð£:PÆV“p ŠA.HëCJ¢ñºµøîoÖi¢ˆ} ·ü‚¶8ˆbþúȼ‚¨ÛúX#ô1:~g‚RÓvìÎæNÑpùM•G°_ˆÛv 7GÐ×«ŽŸÔuŸA±¤Ì¼‡ZPÎÖwÉH§W‘}Ü£"¡ÃÕÎû¦í7T²n¨˜FN02ä7Ë}¼÷®ŸÍâ…ÓŒðK#ï’ Öšø\ Å+¾÷ ²Göf!§¦A;h÷ÃБA»ÑÚÕãÞ³ïnܸuûºûô÷<–¹²½„b<Áz¼e=YVk±ZÒã¼*PÃŽCI²³ à¼d½KM•ÍæÇ5xóz¾®8 5BAï=8À6“®1»)ÉÈåy‡Mðó«|NÌݧËAmX|zrj:£ÌÊDa°a§n+Î-›0¹£5ÿ ‡CêÛÎ'û£A’B•lê; ¢ý5}Îïp |çÑïW/î\PÊf'dIÕô:³]Hh„ïáçÝY©ÁAy@-}åòùkw//Ÿ=u•ûªÅO3h’ý‘ÝÇÍ€‚¼Ÿ~€NpÈÌŸÇn÷‰ b~jP–úÿ%‡» ÿ)‡É^o^5ÁƒØŸû¸ctaЀBê@ 3蜒Ì.ˆAÌóF™ó°H€vÅ'KAHv ª• |EîÏ+hfŸ *AUP ˆcV ƒ wö‡&Xaâ_å ݽ2¶ªKCö^A?Žx ÇÀ9pö8¹°HÐuŠæd?  C;Îs õÛ€† ~?ݵ¦ïÚ“C[Nðg"üê6âˆØOœ†œÐÐï§@»ÏO¶VëYâÝ'Ö m±ö&WCHoôž?ßÕýæ“§7M_Ý;±ÄÍZ«0Æ}-áa:aÚCòÇOF:̶s޵šÞi3}5Ò œº` !ð’– ª’yÖýXâÇ Ð*·½½#hJ+ bºúÙê»±o‡‚ïšàêG#œN@!\GåG8ˆQGkãjU¥+¯×ÉÎÛº&~­'ëd:` ÙÙ2ýêX`»‚¥¶F€øÝ«›x/Mp4¶‘—B G“oÜûh ³ß°÷a6ìï’÷‰ì{6G{‘= Àñ¶Ê¡ÆN/àY˜O‹râ²…¹á9ƒO¨ºæ¦þU•ͨ²šº Ä$0×^t†,UÉøê}Çx¡h~Àû¯žÊX§gm)_%n¹o_ðô›Šî ™ôŠŒ¢(@™#ÂNH€°± \ÝZÌ´œWpáÌlþ×éß­Ée-…gáqܘM°§ÔfèOט¯ÅQl0X›À¨<6&‹µœ«eût|Þ# ĺáÖYÛgî>6Ö"}þú´ej»dBÛÕ_›f, D±BòÍ-Õ}OsV÷ ®þÑL«Cô PwÈòZ‹Ãe¬|HZòê/P„wÆyÈ"°¿™Õ‚¿( §š¢ï9RhheþðŒÛˆ>¹ÈVlè’!¢Ïõ¡>ãó®3ÎÁ{F^ Éç–ã˜4öqL?›±ñÐ=ă÷ Ñë¬F гâ ЗJP ŠöSV”É4ònuÂÕ8.SñN{\7àfÛØÃ®÷ȹóÓÅ)ÛA]8““›“ Ê©±N(Š‘†¬ýtÇóξ3ž¡‡®&È7òʹ$>·Ó¼e=ž/Äã¾JÆG[F%ÛFnCgTdF]âIù‘øk™E VRLfêÄdÄQ*Ò žuh³2-÷¾]Ù«¨3G”-= \ƒì‚ cícuiv¥&s½ZQ¿œ”â„ P ZAvyNÕûÆçFÇ‹¦]ÐÇ?–³k¦«BO«ÊÐ Ó»“s³SX*¸µùk4a×D°ó–¬üøVç7oܼ޶ÉÓ–£ÏÚa,ö÷Fî6-ß/ÍŽÔ‡}Ò ½W¿÷Á8.BMµ]™%åª:àÒXœ}ˆå4µ‚Þcûi„ª›¾ ß2ò.Þ†•·øÜ"¸‰ÖW‚VH®ù G¦NÆÌwð‹I†Î§žÔšÓ*>%SœÊÆlݬˆËÀ²3’o)õUºôΕ‹7Vk‚ T¯zi7Ázš@x™†Gc ÈyÄF¢cè¨>zÀµUõð(ƒüP>= õò3ò³à¸:ÀçE'K®4?÷@‹¢Ì³x^ið+“6'mŠŠ z£‡áš^kúéjÌ”epŸ²|мÿhd2 ö¶èªË WÉÂ%;g3[&ÛøË Ô1©þÖØðwR7E]k„"qwRâ¾±*ÍBRwž<{æú X$êûd}ø9¤m“…‘œÌþwòÇc«·lÙµz*Ž…¹ƒÄ_…®—.^…;¯:6\›yÉ'—7Üáôï$(ƒ+éÍ»O¿tüø¹ GwlÙèëëÅΤ³•‡Dm€zzçvg£¢!ÁÀê‹krJÔšÈêÔB@i«‹ªÅM›“¼UA;YIQ`åN@½»rÙÜ]Úà21너$‰"&l$,È]}À‡ ‰šój| ¾õªã›Öø3[ë™Ä¼ÝU3µŠL‰ %Ë,¶ä¥I¥*È9Y¥9…€®Ñ“—;^QÐܬckË À@uB0ÇwٮɥÄêÿÝ7"–.Ó‚JMÜÁ¤*6¥$þ@jÉñŠŠ–‚š à3p’ú{‚”4u£I·ž¤m§%pÝðGö¿ÈüŽc¬ª~[·èqÄdØÍ´Û¤ÃmE§c<ºM>=¾~»·Ï†éì z†ÐŸ¶VÁêÛ¥Q­ú¿ñà`ÒéÌ}ÌÕAsDU,ˆ»;« ц$u­æÓCÍÑ óó0›¢Ü—Nž¿òÕŒ¼A¤—õÖÖƒçŽÐÿùj¼¿g°ƒI[õݸ>Õâ€:Р> Ú–ðãH§œÒÞSQc0TU˜žÞàxî,¿áÃŒÓ+” í—ÿy? BrV'²óòJðóa°Œ:B»ƒ½mqF¥F¥Á¯gu*O©y.WÏ|ñàüG®sÜ6®°45=×jä7]ÂY={ ¹¢µA( ;J‚[´Ú¢&¶Âwárã]EV(¥Ìæ3è_dZy¼Y(1»»» +­íàù×zn¬ŽŸóá ®ƒ>ï—£Pøel ÊEïgù0j?°7ËOU‡™ôAŸu8ë‚ú†ú‚ú\ÎEpžê*þ fáN£ãq“§ùÓ|ò,ƒ]ôríçÚOÿóþ¥í^=|—³ÿ ¥¿ª?Ñ.QçÞGÐÀ-ØxrÛ?£§_—Å®Y¿lä”g³à0èøôñO÷ܯ¸ê™E¨™žçÖn2^¾öÝÓKk×­vÛ4ÏŒ·ðj°%Ž?<üùëtö© üD¬ùÓ²}K¯³Zškµ ·B­¥àF¸ëa5d~lÅÁ7yuÂÄûØ n¬£“ÑÐÅoOÅ  Ž-ÏÉÍÕ`QP¯‹Æ%„…T¬ÄlÇ·¾aÐG¦!¾iâOš‡Ó|<Ú;§=r‚Arè[>»ûèVûícQ\9[\¼s!¥J ÒAzŽ((ÏÍçY⤇ãnÂI7á8¯…óæsvðú ²¸´´9ëFVÀI§m7üÉR(Èm.”—P®’KÑ ç o¼»„”‚ÀÀPÌ~FÆ£IÞ¶Ÿ4d_š oÊn(ÎbÊá`‡_ßp Çuñ«e† <ÀpƒÃxpƇ÷9{º5¬.Ä_º¯1ªùPmSƒ®Øÿí~ç<ý#—ŠóØñòõ5ß¿î\sÝÂZOÂúÓÄc>`+Øê³cMµJh$øhüª¤g59…ù š2Dkã;ç]^©$fŸÕ›Am9sHWžýÜm¿ ‰õ&¬p¯`ÆYùÖä”t9H¤0˜ÖëkŠ[¿ô¼ú2­,B ã/@v‰k–W­Áï[JÝ´ßX¸å 8 NŸ>ÜQHYi)ìÿßí^ßeO'nöKSÒ2e©@BIË´U?^€öŸ†5ûDEEhÛ,®è€ã:`fßÁkiïhÿ¿øÜŠ×ÃèœÂ¬\ŒþRm\tªXžÎ º?We$+ÓAª‹¸\RY“WÕ;üæ7úî¾+Û¶í[ïêÚºþÌ™Ö+w™Ù+i¹¸þøñÊúââÊH__q¤œE›¹ûôý½íÛ½ý7,[üɦÓm‡.ß³Ž4?RÑXRRæç+Ž›‹­]ÏùêxíÜtóçTº(¯$TRÕâb‰"S¥1è!Ú£HKLb˜ŸT˜ ¿EþÎ¥ŠlU Ê+‹«+ñÝ<†nÖ:»c„Ã<ƒIÓþu;tÆ&~€åV“­‹¿ßôläÊà9‘[õ~×â.¼x®àc¿X¹m³Ïä]y›ôk™”” k”*q´$줖žZñŹ#͇š˜rñ±­—õiÃç§÷Ge”2*Íð'JÀ>àRQ¬oÑ,¬¥ÐZ8…–žSùÔ庺ªY)Âã¶mbâ='© .UíÍUh£÷m H—Ê'ùZýé¢âSç,mÈëæÃ›¼Cœ'Ÿó€Ïéâý¸ ÷ay„l.ªý¸¨à+4.mÅO‚q©¢?Hy0~ÒŠ¡Ó<ÁE=\ÿœ÷ùð{.þr_«_p|Tt¤NÔ˜—«YLP¤‰3W,Úɦ¤'§ãä‰×ÊJk~7AG毡و[UÆP’R”œ‡¾…þβ‚LµP±\$ÆwSYx¹!üJJµÄKT)//ÈV”š'›¯{ª«ùP}3 ÊRsâ‹ÑЯwBíÁóC…#¿+/ÊËeT~º.*íBΨ 89£es~ù½M5€ªËÕå³Ý`3:vtž|>ã«ß1(ü³Ä4œ*¿ôìlCyk8Gµ a•6ÖÛmSHT¯¯ÖŠÓ Ó5L­áTÞ'€zùIHhTŒ\œÌ¢‰ ÁL°‡Ú 7j0N¢åô›ð¨ÛŠƒ˜²½‚Whì|xfËeíÑ€¦Å¥H‹Rs3Y8ñÊÐ,g&ïC,5]Š[R)š¸Ú¸ ÷ôëaØY#lÄ¿xÇÛ¿k‡«p®NàâéÌ,3¹¡ºÏAhÀÍwÛ~< ]o(A+Ñh4@¡á`äÇ<ùúRƒ!$'d‚äd60Ä?)Kb $à8øÎ‹—¿N$¯«f× [ôŽÝWï}òâÑÇ7,Xà³q—Ù‘OôÜHlô*nAç•äáêË {4tEVúSЀùÍþà`¬W»eE1ˆ¸&+P‚Tà—/¥•àÀóÖ#b½<51 Ĺd€ðà z[¥rá. ¼?Ø_РúTYǃöénî®—d|@éJ*Ê´ò¥šj?ÜUjn{óŒ¯ÇcR,ÄyòñëA´ðº‘Á©ŠöÏ5‚PMòºõ!ÃÓ^7ÃÆíÅ7álPÜMÌ©a ÇÙ€ ƒãÉbЈIΠñhœ œà84ž”ƒÀ<¸ØŠ¯E:Þen¾õú}:½0E¨8iB|JNrv ¿þóÃÜäü„*à¢+ÓVägfjX[׿Á–ë|Ø’MK=vHäÉ™ñé ÎÒš›_^€vƽŸøî……ø7÷kòÔYyŒÍrέ‹¯ÇvË·>òeÚŸãÑ´>×nÖó^s¥×Ü´Öé|l³Íà[6ôѸ}ÛMœ»Ü Zž—2-A‘Ž»9KSR2@•ZR“£Qç3¿wü¾®T‘4À¥¦°9O«È‘ç±V ¿c0­g#Óþã>l®å|^¡óÊÕ÷G3øÄ¤JÓ0ÍüsuªD@ŠK|Y‚®*¯¬DÓ+ÆygLðœá惺uád‡ì'[¾U°î%í ýs8bˆòéÅî8oÃI¦_îÞ¹ùšŒÞvGý[6a„gÌ?=òKKc²v8;¿âÐã¬@itšœZñ«/qV«JÛ@5C€4@ ݦ*-.-:¬FUÈÖ© /3k3…@ð9~Tt1õ4 *j@SƒP­`ÑèlLz›(8Gj3x6­-Û¯®µ ,n°ñ%NÙt¼ëÝ_ž§É1 ûÏõJ+%ªX%^[X‘^VyDsè8Óµ`ºÀv¢’c+ƒéd¯w­ðzÝ›ï.ôÍo`Ѷç:a™‰ÿÙeZ‘’–d”ùS>µæU]÷)³8‚A òÊÙï;|­ýäuðNº‡£þ‹æÏÝgHÒZ{k‰");yªé" ~¹sÖ*ï nžor5n›p«a{ÝÚœ@@%`±U™å-£Äî ¦vÒž²c¢M!Ê ƒB«  ‰J‹Çñµ~Ð=(cÕp¨'ìÛ²ƒåËN«k¬¡kŒV'³Ñjd—¥lïfßYWÍ_ä9Þùq'Œ4í1ËŽÑí —ÀêîòÏ \µ}up­Lg¶§4­03›ijºeþíó3>aÒÀÈ6$J¨ PnÌN9ýj.Dæ$ùËÙ6¬Û´vúž%E§¢ØÜÜ< Ðõ~æ8ó§ ˜Âøæé³[;®¸5š½ÏÉá@Þ#ø«ùæ/èri¹$)-=-• ‹ˆ’ȰM)H,N,‰ÓH!%ÄIÃc°*””IÊ‹4¹š<¦ÑPW^ A¾¢D^’¨‹=꡼Z«+k¨ÝÂ0rýp*Ümç‚™´"(q .Hmb`."<úË}dK"HÜ·]-6i%5?ˆ‰ £Aº*1ŽB »( áKôR`um“Î1:žëÜb‚*‹>kä\è@à›êcG©¶s}Temâ¨RDÍ9¹…ùL}ó‘ L¦œ^=<±Ü}áÊ?ˆX“1{1?{±AT+ Sì÷õ*h‡ýòò_,ùõg'q°m* Q|žÀØß4€éo1°Ÿqà@ÓÀAñÿ µ¾² endstream endobj 130 0 obj << /Title(CFITSIO Error Status Codes ) /Dest/appendix.C /Parent 6 0 R /Prev 129 0 R >> endobj 5 0 obj <> /Doc-Start<> /page.ii<> /page.iii<> /chapter*.1<> /page.iv<> /page.v<> /page.vi<> /page.vii<> /page.viii<> /page.1<> /chapter.1<> /section.1.1<> /section.1.2<> /page.2<> /section.1.3<> /page.3<> /page.4<> /section.1.4<> /page.5<> /chapter.2<> /section.2.1<> /subsection.2.1.1<> /page.6<> /page.7<> /subsection.2.1.2<> /subsection.2.1.3<> /subsection.2.1.4<> /section.2.2<> /page.8<> /page.9<> /section.2.3<> /section.2.4<> /section.2.5<> /page.10<> /section.2.6<> /page.11<> /page.12<> /page.13<> /chapter.3<> /page.14<> /page.15<> /chapter.4<> /section.4.1<> /page.16<> /page.17<> /section.4.2<> /page.18<> /section.4.3<> /page.19<> /page.20<> /section.4.4<> /page.21<> /page.22<> /section.4.5<> /page.23<> /section.4.6<> /section.4.7<> /page.24<> /section.4.8<> /section.4.9<> /page.25<> /section.4.10<> /page.26<> /section.4.11<> /page.27<> /section.4.12<> /page.28<> /section.4.13<> /page.29<> /page.30<> /page.31<> /chapter.5<> /section.5.1<> /page.32<> /section.5.2<> /page.33<> /page.34<> /page.35<> /section.5.3<> /page.36<> /page.37<> /section.5.4<> /page.38<> /subsection.5.4.1<> /page.39<> /page.40<> /subsection.5.4.2<> /page.41<> /page.42<> /page.43<> /section.5.5<> /page.44<> /page.45<> /page.46<> /page.47<> /section.5.6<> /page.48<> /page.49<> /page.50<> /page.51<> /page.52<> /section.5.7<> /subsection.5.7.1<> /page.53<> /subsection.5.7.2<> /page.54<> /page.55<> /subsection.5.7.3<> /page.56<> /page.57<> /subsection.5.7.4<> /page.58<> /page.59<> /subsection.5.7.5<> /page.60<> /page.61<> /subsection.5.7.6<> /page.62<> /page.63<> /section.5.8<> /subsection.5.8.1<> /page.64<> /page.65<> /subsection.5.8.2<> /page.66<> /subsection.5.8.3<> /page.67<> /page.68<> /page.69<> /page.70<> /page.71<> /page.72<> /page.73<> /page.74<> /page.75<> /page.76<> /page.77<> /chapter.6<> /page.78<> /section.6.1<> /page.79<> /page.80<> /section.6.2<> /page.81<> /section.6.3<> /page.82<> /section.6.4<> /page.83<> /page.84<> /page.85<> /chapter.7<> /page.86<> /section.7.1<> /page.87<> /page.88<> /page.89<> /chapter.8<> /page.90<> /section.8.1<> /page.91<> /page.92<> /section.8.2<> /page.93<> /page.94<> /page.95<> /chapter.9<> /section.9.1<> /page.96<> /page.97<> /page.98<> /page.99<> /section.9.2<> /page.100<> /page.101<> /page.102<> /section.9.3<> /subsection.9.3.1<> /subsection.9.3.2<> /page.103<> /page.104<> /subsection.9.3.3<> /page.105<> /page.106<> /subsection.9.3.4<> /page.107<> /subsection.9.3.5<> /page.108<> /subsection.9.3.6<> /page.109<> /page.110<> /subsection.9.3.7<> /section.9.4<> /page.111<> /section.9.5<> /page.112<> /page.113<> /page.114<> /page.115<> /section.9.6<> /subsection.9.6.1<> /page.116<> /subsection.9.6.2<> /page.117<> /subsection.9.6.3<> /page.118<> /subsection.9.6.4<> /page.119<> /page.120<> /page.121<> /page.122<> /page.123<> /chapter.10<> /section.10.1<> /page.124<> /page.125<> /page.126<> /section.10.2<> /page.127<> /subsection.10.2.1<> /subsection.10.2.2<> /page.128<> /subsection.10.2.3<> /subsection.10.2.4<> /page.129<> /subsection.10.2.5<> /page.130<> /page.131<> /subsection.10.2.6<> /section.10.3<> /page.132<> /page.133<> /section.10.4<> /page.134<> /page.135<> /section.10.5<> /section.10.6<> /section.10.7<> /page.136<> /page.137<> /section.10.8<> /page.138<> /section.10.9<> /page.139<> /section.10.10<> /page.140<> /page.141<> /page.142<> /section.10.11<> /subsection.10.11.1<> /page.143<> /page.144<> /page.145<> /subsection.10.11.2<> /page.146<> /subsection.10.11.3<> /page.147<> /subsection.10.11.4<> /page.148<> /subsection.10.11.5<> /page.149<> /page.150<> /subsection.10.11.6<> /page.151<> /section.10.12<> /page.152<> /page.153<> /page.154<> /page.155<> /chapter.11<> /section.11.1<> /page.156<> /section.11.2<> /page.157<> /section.11.3<> /page.158<> /section.11.4<> /section.11.5<> /section.11.6<> /page.159<> /page.160<> /page.161<> /chapter.12<> /section.12.1<> /section.12.2<> /page.162<> /page.163<> /section.12.3<> /section.12.4<> /section.12.5<> /page.164<> /section.12.6<> /page.165<> /page.166<> /page.167<> /chapter.13<> /section.13.1<> /page.168<> /section.13.2<> /page.169<> /page.170<> /page.171<> /page.172<> /page.173<> /appendix.A<> /page.174<> /page.175<> /page.176<> /page.177<> /page.178<> /page.179<> /appendix.B<> /page.180<> /page.181<> /page.182<> /page.183<> /page.184<> /page.185<> /appendix.C<> /page.186<> /page.187<> /page.188<>>>endobj 1802 0 obj <>stream dvips + GPL Ghostscript 8.70 () 2017-07-28T13:53:12-04:00 2017-07-28T13:53:12-04:00 LaTeX with hyperref package ()()() endstream endobj 2 0 obj <>endobj xref 0 1803 0000000000 65535 f 0000892646 00000 n 0001100435 00000 n 0000890917 00000 n 0000851574 00000 n 0001068672 00000 n 0000892588 00000 n 0000893250 00000 n 0000892842 00000 n 0000892933 00000 n 0000893060 00000 n 0000893163 00000 n 0000894471 00000 n 0000893765 00000 n 0000893372 00000 n 0000893466 00000 n 0000893564 00000 n 0000893670 00000 n 0000893899 00000 n 0000894008 00000 n 0000894127 00000 n 0000894261 00000 n 0000894379 00000 n 0000894624 00000 n 0000896304 00000 n 0000894726 00000 n 0000894822 00000 n 0000894945 00000 n 0000895072 00000 n 0000895208 00000 n 0000895328 00000 n 0000895447 00000 n 0000895549 00000 n 0000895670 00000 n 0000895807 00000 n 0000895937 00000 n 0000896065 00000 n 0000896202 00000 n 0000898752 00000 n 0000896453 00000 n 0000896559 00000 n 0000896674 00000 n 0000896995 00000 n 0000896783 00000 n 0000896889 00000 n 0000897156 00000 n 0000897291 00000 n 0000898129 00000 n 0000897398 00000 n 0000897496 00000 n 0000897618 00000 n 0000897745 00000 n 0000897875 00000 n 0000898007 00000 n 0000898622 00000 n 0000898287 00000 n 0000898391 00000 n 0000898516 00000 n 0000899373 00000 n 0000898909 00000 n 0000899012 00000 n 0000899130 00000 n 0000899262 00000 n 0000899620 00000 n 0000899528 00000 n 0000899976 00000 n 0000899778 00000 n 0000899878 00000 n 0000902232 00000 n 0000900132 00000 n 0000900234 00000 n 0000901157 00000 n 0000900343 00000 n 0000900452 00000 n 0000900583 00000 n 0000900700 00000 n 0000900818 00000 n 0000900934 00000 n 0000901052 00000 n 0000901319 00000 n 0000901459 00000 n 0000902070 00000 n 0000901611 00000 n 0000901716 00000 n 0000901842 00000 n 0000901963 00000 n 0000905303 00000 n 0000902396 00000 n 0000903220 00000 n 0000902482 00000 n 0000902595 00000 n 0000902720 00000 n 0000902854 00000 n 0000902981 00000 n 0000903106 00000 n 0000903356 00000 n 0000903460 00000 n 0000903597 00000 n 0000903731 00000 n 0000903858 00000 n 0000903976 00000 n 0000904082 00000 n 0000904199 00000 n 0000905022 00000 n 0000904336 00000 n 0000904437 00000 n 0000904547 00000 n 0000904662 00000 n 0000904791 00000 n 0000904916 00000 n 0000905183 00000 n 0000906116 00000 n 0000905458 00000 n 0000905568 00000 n 0000905688 00000 n 0000905809 00000 n 0000905926 00000 n 0000906027 00000 n 0000906991 00000 n 0000906260 00000 n 0000906361 00000 n 0000906483 00000 n 0000906625 00000 n 0000906741 00000 n 0000906882 00000 n 0000907358 00000 n 0000907145 00000 n 0000907254 00000 n 0000907509 00000 n 0000907618 00000 n 0001068568 00000 n 0000000015 00000 n 0000000935 00000 n 0000907731 00000 n 0001024049 00000 n 0001049370 00000 n 0001023716 00000 n 0001046927 00000 n 0001022988 00000 n 0001036973 00000 n 0000907774 00000 n 0000907809 00000 n 0000851738 00000 n 0000000956 00000 n 0000001131 00000 n 0000907870 00000 n 0000907905 00000 n 0000851904 00000 n 0000001152 00000 n 0000003374 00000 n 0000907940 00000 n 0001022430 00000 n 0001031196 00000 n 0000908076 00000 n 0000908214 00000 n 0000908351 00000 n 0000908489 00000 n 0000908627 00000 n 0000908763 00000 n 0000908901 00000 n 0000909044 00000 n 0000909187 00000 n 0000909329 00000 n 0000909471 00000 n 0000909609 00000 n 0000909744 00000 n 0000909882 00000 n 0000910020 00000 n 0000910158 00000 n 0000910294 00000 n 0000910430 00000 n 0000910568 00000 n 0000910706 00000 n 0000910844 00000 n 0000910981 00000 n 0000911119 00000 n 0000911154 00000 n 0000852262 00000 n 0000003396 00000 n 0000006259 00000 n 0001022096 00000 n 0001026177 00000 n 0000911215 00000 n 0000911353 00000 n 0000911491 00000 n 0000911629 00000 n 0000911767 00000 n 0000911906 00000 n 0000912045 00000 n 0000912184 00000 n 0000912322 00000 n 0000912458 00000 n 0000912596 00000 n 0000912734 00000 n 0000912872 00000 n 0000913010 00000 n 0000913150 00000 n 0000913293 00000 n 0000913431 00000 n 0000913569 00000 n 0000913706 00000 n 0000913849 00000 n 0000913991 00000 n 0000914134 00000 n 0000914277 00000 n 0000914420 00000 n 0000914563 00000 n 0000914701 00000 n 0000914844 00000 n 0000914987 00000 n 0000915130 00000 n 0000915266 00000 n 0000915404 00000 n 0000915539 00000 n 0000915677 00000 n 0000915712 00000 n 0000852692 00000 n 0000006281 00000 n 0000008992 00000 n 0000915773 00000 n 0000915911 00000 n 0000916047 00000 n 0000916185 00000 n 0000916321 00000 n 0000916456 00000 n 0000916593 00000 n 0000916729 00000 n 0000916867 00000 n 0000917005 00000 n 0000917143 00000 n 0000917286 00000 n 0000917429 00000 n 0000917572 00000 n 0000917715 00000 n 0000917858 00000 n 0000918001 00000 n 0000918144 00000 n 0000918282 00000 n 0000918420 00000 n 0000918557 00000 n 0000918700 00000 n 0000918843 00000 n 0000918986 00000 n 0000919129 00000 n 0000919263 00000 n 0000919402 00000 n 0000919541 00000 n 0000919685 00000 n 0000919829 00000 n 0000919973 00000 n 0000920008 00000 n 0000853106 00000 n 0000009014 00000 n 0000011769 00000 n 0000920069 00000 n 0000920213 00000 n 0000920357 00000 n 0000920501 00000 n 0000920640 00000 n 0000920779 00000 n 0000920918 00000 n 0000921057 00000 n 0000921196 00000 n 0000921335 00000 n 0000921474 00000 n 0000921614 00000 n 0000921754 00000 n 0000921899 00000 n 0000922043 00000 n 0000922188 00000 n 0000922333 00000 n 0000922477 00000 n 0000922622 00000 n 0000922762 00000 n 0000922898 00000 n 0000923037 00000 n 0000923175 00000 n 0000923314 00000 n 0000923453 00000 n 0000923592 00000 n 0000923731 00000 n 0000923868 00000 n 0000924007 00000 n 0000924146 00000 n 0000924285 00000 n 0000924424 00000 n 0000924563 00000 n 0000924598 00000 n 0000853536 00000 n 0000011791 00000 n 0000012797 00000 n 0000924659 00000 n 0000924798 00000 n 0000924935 00000 n 0000925074 00000 n 0000925213 00000 n 0000925349 00000 n 0000925486 00000 n 0000925623 00000 n 0000925658 00000 n 0000853766 00000 n 0000012818 00000 n 0000013060 00000 n 0000925719 00000 n 0000925754 00000 n 0000853932 00000 n 0000013081 00000 n 0000017649 00000 n 0000925802 00000 n 0000925837 00000 n 0000854098 00000 n 0000017671 00000 n 0000023480 00000 n 0001025562 00000 n 0001059946 00000 n 0000925885 00000 n 0000925920 00000 n 0000854264 00000 n 0000023502 00000 n 0000029902 00000 n 0000925994 00000 n 0000926029 00000 n 0000854438 00000 n 0000029924 00000 n 0000033393 00000 n 0000926077 00000 n 0000926112 00000 n 0000854604 00000 n 0000033415 00000 n 0000036958 00000 n 0000926173 00000 n 0000926208 00000 n 0000854770 00000 n 0000036980 00000 n 0000042108 00000 n 0000926269 00000 n 0000926304 00000 n 0000854944 00000 n 0000042130 00000 n 0000046953 00000 n 0000926365 00000 n 0000926400 00000 n 0000855118 00000 n 0000046975 00000 n 0000051558 00000 n 0000926474 00000 n 0000926509 00000 n 0000855292 00000 n 0000051580 00000 n 0000057254 00000 n 0000926570 00000 n 0000926605 00000 n 0000855466 00000 n 0000057276 00000 n 0000061516 00000 n 0000926679 00000 n 0000926714 00000 n 0000855640 00000 n 0000061538 00000 n 0000062518 00000 n 0000926788 00000 n 0000926823 00000 n 0000855806 00000 n 0000062539 00000 n 0000062877 00000 n 0000926884 00000 n 0000926919 00000 n 0000855972 00000 n 0000062898 00000 n 0000067089 00000 n 0001025100 00000 n 0001059050 00000 n 0000926967 00000 n 0000927002 00000 n 0000856138 00000 n 0000067111 00000 n 0000072360 00000 n 0000927076 00000 n 0000927111 00000 n 0000856304 00000 n 0000072382 00000 n 0000076158 00000 n 0000927185 00000 n 0000927220 00000 n 0000856478 00000 n 0000076180 00000 n 0000078610 00000 n 0000927281 00000 n 0000927316 00000 n 0000856644 00000 n 0000078632 00000 n 0000081123 00000 n 0000927377 00000 n 0000927412 00000 n 0000856810 00000 n 0000081145 00000 n 0000085720 00000 n 0000927486 00000 n 0000927521 00000 n 0000856976 00000 n 0000085742 00000 n 0000090792 00000 n 0000927595 00000 n 0000927630 00000 n 0000857150 00000 n 0000090814 00000 n 0000096917 00000 n 0000927691 00000 n 0000927726 00000 n 0000857324 00000 n 0000096939 00000 n 0000101331 00000 n 0000927800 00000 n 0000927835 00000 n 0000857498 00000 n 0000101353 00000 n 0000106841 00000 n 0000927896 00000 n 0000927931 00000 n 0000857672 00000 n 0000106863 00000 n 0000112543 00000 n 0000928018 00000 n 0000928053 00000 n 0000857846 00000 n 0000112565 00000 n 0000117622 00000 n 0000928127 00000 n 0000928162 00000 n 0000858020 00000 n 0000117644 00000 n 0000124428 00000 n 0000928236 00000 n 0000928271 00000 n 0000858194 00000 n 0000124450 00000 n 0000131239 00000 n 0000928332 00000 n 0000928367 00000 n 0000858368 00000 n 0000131261 00000 n 0000137795 00000 n 0000928441 00000 n 0000928476 00000 n 0000858542 00000 n 0000137817 00000 n 0000144267 00000 n 0000928550 00000 n 0000928585 00000 n 0000858716 00000 n 0000144289 00000 n 0000147002 00000 n 0000928659 00000 n 0000928694 00000 n 0000858890 00000 n 0000147024 00000 n 0000147350 00000 n 0000928755 00000 n 0000928790 00000 n 0000859056 00000 n 0000147371 00000 n 0000151795 00000 n 0001024943 00000 n 0001058453 00000 n 0000928838 00000 n 0000928873 00000 n 0000859222 00000 n 0000151817 00000 n 0000154897 00000 n 0000928960 00000 n 0000928995 00000 n 0000859396 00000 n 0000154919 00000 n 0000161863 00000 n 0000929082 00000 n 0000929117 00000 n 0000859570 00000 n 0000161885 00000 n 0000167551 00000 n 0000929178 00000 n 0000929213 00000 n 0000859736 00000 n 0000167573 00000 n 0000173105 00000 n 0000929287 00000 n 0000929322 00000 n 0000859910 00000 n 0000173127 00000 n 0000177169 00000 n 0000929409 00000 n 0000929444 00000 n 0000860084 00000 n 0000177191 00000 n 0000182339 00000 n 0000929518 00000 n 0000929553 00000 n 0000860258 00000 n 0000182361 00000 n 0000187390 00000 n 0000929640 00000 n 0000929675 00000 n 0000860432 00000 n 0000187412 00000 n 0000192427 00000 n 0000929762 00000 n 0000929797 00000 n 0000860606 00000 n 0000192449 00000 n 0000197555 00000 n 0000929871 00000 n 0000929906 00000 n 0000860780 00000 n 0000197577 00000 n 0000201416 00000 n 0000929993 00000 n 0000930028 00000 n 0000860946 00000 n 0000201438 00000 n 0000205045 00000 n 0000930102 00000 n 0000930137 00000 n 0000861112 00000 n 0000205067 00000 n 0000210973 00000 n 0000930211 00000 n 0000930246 00000 n 0000861286 00000 n 0000210995 00000 n 0000214850 00000 n 0000930333 00000 n 0000930368 00000 n 0000861452 00000 n 0000214872 00000 n 0000219283 00000 n 0000930442 00000 n 0000930477 00000 n 0000861626 00000 n 0000219305 00000 n 0000223710 00000 n 0000930551 00000 n 0000930586 00000 n 0000861792 00000 n 0000223732 00000 n 0000230699 00000 n 0000930660 00000 n 0000930695 00000 n 0000861966 00000 n 0000230721 00000 n 0000237982 00000 n 0000930769 00000 n 0000930804 00000 n 0000862132 00000 n 0000238004 00000 n 0000243175 00000 n 0000930852 00000 n 0000930887 00000 n 0000862306 00000 n 0000243197 00000 n 0000248260 00000 n 0000930948 00000 n 0000930983 00000 n 0000862480 00000 n 0000248282 00000 n 0000251907 00000 n 0000931044 00000 n 0000931079 00000 n 0000862646 00000 n 0000251929 00000 n 0000256729 00000 n 0000931140 00000 n 0000931175 00000 n 0000862820 00000 n 0000256751 00000 n 0000261423 00000 n 0000931262 00000 n 0000931297 00000 n 0000862994 00000 n 0000261445 00000 n 0000266980 00000 n 0000931384 00000 n 0000931419 00000 n 0000863168 00000 n 0000267002 00000 n 0000270874 00000 n 0000931480 00000 n 0000931515 00000 n 0000863342 00000 n 0000270896 00000 n 0000275245 00000 n 0000931602 00000 n 0000931637 00000 n 0000863516 00000 n 0000275267 00000 n 0000280792 00000 n 0000931711 00000 n 0000931746 00000 n 0000863682 00000 n 0000280814 00000 n 0000285969 00000 n 0000931833 00000 n 0000931868 00000 n 0000863848 00000 n 0000285991 00000 n 0000291638 00000 n 0000931942 00000 n 0000931977 00000 n 0000864022 00000 n 0000291660 00000 n 0000296541 00000 n 0000932064 00000 n 0000932099 00000 n 0000864196 00000 n 0000296563 00000 n 0000301795 00000 n 0000932173 00000 n 0000932208 00000 n 0000864370 00000 n 0000301817 00000 n 0000305537 00000 n 0000932295 00000 n 0000932330 00000 n 0000864536 00000 n 0000305559 00000 n 0000310413 00000 n 0000932404 00000 n 0000932439 00000 n 0000864702 00000 n 0000310435 00000 n 0000314159 00000 n 0000932526 00000 n 0000932561 00000 n 0000864868 00000 n 0000314181 00000 n 0000319006 00000 n 0000932635 00000 n 0000932670 00000 n 0000865042 00000 n 0000319028 00000 n 0000323522 00000 n 0000932757 00000 n 0000932792 00000 n 0000865208 00000 n 0000323544 00000 n 0000328457 00000 n 0000932879 00000 n 0000932914 00000 n 0000865382 00000 n 0000328479 00000 n 0000332389 00000 n 0000932988 00000 n 0000933023 00000 n 0000865548 00000 n 0000332411 00000 n 0000335857 00000 n 0000933097 00000 n 0000933132 00000 n 0000865714 00000 n 0000335879 00000 n 0000340929 00000 n 0000933206 00000 n 0000933241 00000 n 0000865888 00000 n 0000340951 00000 n 0000345939 00000 n 0000933315 00000 n 0000933350 00000 n 0000866054 00000 n 0000345961 00000 n 0000350525 00000 n 0000933424 00000 n 0000933459 00000 n 0000866220 00000 n 0000350547 00000 n 0000354490 00000 n 0000933533 00000 n 0000933568 00000 n 0000866394 00000 n 0000354512 00000 n 0000358048 00000 n 0000933629 00000 n 0000933664 00000 n 0000866560 00000 n 0000358070 00000 n 0000362367 00000 n 0000933738 00000 n 0000933773 00000 n 0000866734 00000 n 0000362389 00000 n 0000362745 00000 n 0000933847 00000 n 0000933882 00000 n 0000866900 00000 n 0000362766 00000 n 0000367405 00000 n 0000933930 00000 n 0000933965 00000 n 0000867074 00000 n 0000367427 00000 n 0000372588 00000 n 0000934026 00000 n 0000934061 00000 n 0000867240 00000 n 0000372610 00000 n 0000378074 00000 n 0000934148 00000 n 0000934183 00000 n 0000867406 00000 n 0000378096 00000 n 0000383445 00000 n 0000934244 00000 n 0000934279 00000 n 0000867572 00000 n 0000383467 00000 n 0000389650 00000 n 0000934366 00000 n 0000934401 00000 n 0000867746 00000 n 0000389672 00000 n 0000395425 00000 n 0000934475 00000 n 0000934510 00000 n 0000867912 00000 n 0000395447 00000 n 0000397398 00000 n 0000934597 00000 n 0000934632 00000 n 0000868078 00000 n 0000397420 00000 n 0000397757 00000 n 0000934706 00000 n 0000934741 00000 n 0000868244 00000 n 0000397778 00000 n 0000402626 00000 n 0000934789 00000 n 0000934824 00000 n 0000868418 00000 n 0000402648 00000 n 0000408529 00000 n 0000934898 00000 n 0000934933 00000 n 0000868592 00000 n 0000408551 00000 n 0000412705 00000 n 0000935020 00000 n 0000935055 00000 n 0000868766 00000 n 0000412727 00000 n 0000413436 00000 n 0000935129 00000 n 0000935164 00000 n 0000868932 00000 n 0000413457 00000 n 0000418671 00000 n 0001024655 00000 n 0001055916 00000 n 0000935225 00000 n 0000935260 00000 n 0000869106 00000 n 0000418693 00000 n 0000424560 00000 n 0000935321 00000 n 0000935356 00000 n 0000869280 00000 n 0000424582 00000 n 0000430229 00000 n 0000935443 00000 n 0000935478 00000 n 0000869454 00000 n 0000430251 00000 n 0000434855 00000 n 0000935552 00000 n 0000935587 00000 n 0000869620 00000 n 0000434877 00000 n 0000439364 00000 n 0000935674 00000 n 0000935709 00000 n 0000869794 00000 n 0000439386 00000 n 0000441261 00000 n 0000935783 00000 n 0000935818 00000 n 0000869968 00000 n 0000441283 00000 n 0000446132 00000 n 0000935892 00000 n 0000935927 00000 n 0000870142 00000 n 0000446154 00000 n 0000451688 00000 n 0000936001 00000 n 0000936036 00000 n 0000870316 00000 n 0000451710 00000 n 0000456834 00000 n 0000936123 00000 n 0000936158 00000 n 0000870490 00000 n 0000456856 00000 n 0000462069 00000 n 0000936245 00000 n 0000936280 00000 n 0000870664 00000 n 0000462091 00000 n 0000466506 00000 n 0000936354 00000 n 0000936389 00000 n 0000870838 00000 n 0000466528 00000 n 0000472001 00000 n 0000936476 00000 n 0000936511 00000 n 0000871012 00000 n 0000472023 00000 n 0000476219 00000 n 0000936585 00000 n 0000936620 00000 n 0000871186 00000 n 0000476241 00000 n 0000481058 00000 n 0000936694 00000 n 0000936729 00000 n 0000871360 00000 n 0000481080 00000 n 0000485767 00000 n 0000936816 00000 n 0000936851 00000 n 0000871526 00000 n 0000485789 00000 n 0000489597 00000 n 0000936925 00000 n 0000936960 00000 n 0000871700 00000 n 0000489619 00000 n 0000493868 00000 n 0000937047 00000 n 0000937082 00000 n 0000871874 00000 n 0000493890 00000 n 0000498817 00000 n 0000937156 00000 n 0000937191 00000 n 0000872048 00000 n 0000498839 00000 n 0000502468 00000 n 0000937278 00000 n 0000937313 00000 n 0000872222 00000 n 0000502490 00000 n 0000506402 00000 n 0000937400 00000 n 0000937435 00000 n 0000872396 00000 n 0000506424 00000 n 0000510497 00000 n 0000937522 00000 n 0000937557 00000 n 0000872562 00000 n 0000510519 00000 n 0000515931 00000 n 0000937631 00000 n 0000937666 00000 n 0000872728 00000 n 0000515953 00000 n 0000520270 00000 n 0000937753 00000 n 0000937788 00000 n 0000872894 00000 n 0000520292 00000 n 0000527592 00000 n 0000937875 00000 n 0000937910 00000 n 0000873068 00000 n 0000527614 00000 n 0000530118 00000 n 0000937984 00000 n 0000938019 00000 n 0000873234 00000 n 0000530140 00000 n 0000532904 00000 n 0000938093 00000 n 0000938128 00000 n 0000873400 00000 n 0000532926 00000 n 0000536480 00000 n 0000938202 00000 n 0000938237 00000 n 0000873566 00000 n 0000536502 00000 n 0000541669 00000 n 0000938324 00000 n 0000938359 00000 n 0000873732 00000 n 0000541691 00000 n 0000545363 00000 n 0000938446 00000 n 0000938481 00000 n 0000873898 00000 n 0000545385 00000 n 0000551438 00000 n 0000938568 00000 n 0000938603 00000 n 0000874072 00000 n 0000551460 00000 n 0000555922 00000 n 0000938690 00000 n 0000938725 00000 n 0000874238 00000 n 0000555944 00000 n 0000561642 00000 n 0000938799 00000 n 0000938834 00000 n 0000874412 00000 n 0000561664 00000 n 0000563794 00000 n 0000938908 00000 n 0000938943 00000 n 0000874578 00000 n 0000563816 00000 n 0000564180 00000 n 0000939017 00000 n 0000939052 00000 n 0000874744 00000 n 0000564201 00000 n 0000568214 00000 n 0000939100 00000 n 0000939135 00000 n 0000874910 00000 n 0000568236 00000 n 0000574035 00000 n 0000939196 00000 n 0000939231 00000 n 0000875076 00000 n 0000574057 00000 n 0000579290 00000 n 0000939305 00000 n 0000939340 00000 n 0000875242 00000 n 0000579312 00000 n 0000583579 00000 n 0000939414 00000 n 0000939449 00000 n 0000875408 00000 n 0000583601 00000 n 0000589108 00000 n 0000939523 00000 n 0000939558 00000 n 0000875582 00000 n 0000589130 00000 n 0000594878 00000 n 0000939632 00000 n 0000939667 00000 n 0000875748 00000 n 0000594900 00000 n 0000600138 00000 n 0000939741 00000 n 0000939776 00000 n 0000875922 00000 n 0000600160 00000 n 0000603327 00000 n 0000939850 00000 n 0000939885 00000 n 0000876088 00000 n 0000603349 00000 n 0000608998 00000 n 0000939946 00000 n 0000939981 00000 n 0000876262 00000 n 0000609020 00000 n 0000615002 00000 n 0000940055 00000 n 0000940090 00000 n 0000876428 00000 n 0000615024 00000 n 0000621232 00000 n 0000940151 00000 n 0000940186 00000 n 0000876594 00000 n 0000621254 00000 n 0000626689 00000 n 0000940260 00000 n 0000940295 00000 n 0000876760 00000 n 0000626711 00000 n 0000632197 00000 n 0000940369 00000 n 0000940404 00000 n 0000876934 00000 n 0000632219 00000 n 0000638392 00000 n 0000940478 00000 n 0000940513 00000 n 0000877100 00000 n 0000638414 00000 n 0000643160 00000 n 0000940574 00000 n 0000940609 00000 n 0000877266 00000 n 0000643182 00000 n 0000648201 00000 n 0000940683 00000 n 0000940719 00000 n 0000877434 00000 n 0000648224 00000 n 0000653817 00000 n 0000940794 00000 n 0000940830 00000 n 0000877604 00000 n 0000653840 00000 n 0000659475 00000 n 0000940918 00000 n 0000940954 00000 n 0000877774 00000 n 0000659498 00000 n 0000663899 00000 n 0000941029 00000 n 0000941065 00000 n 0000877944 00000 n 0000663922 00000 n 0000670341 00000 n 0000941140 00000 n 0000941176 00000 n 0000878114 00000 n 0000670364 00000 n 0000675389 00000 n 0000941264 00000 n 0000941300 00000 n 0000878284 00000 n 0000675412 00000 n 0000681339 00000 n 0000941362 00000 n 0000941398 00000 n 0000878462 00000 n 0000681362 00000 n 0000685177 00000 n 0000941460 00000 n 0000941496 00000 n 0000878632 00000 n 0000685200 00000 n 0000690421 00000 n 0000941571 00000 n 0000941607 00000 n 0000878802 00000 n 0000690444 00000 n 0000696942 00000 n 0000941695 00000 n 0000941731 00000 n 0000878972 00000 n 0000696965 00000 n 0000702960 00000 n 0000941819 00000 n 0000941855 00000 n 0000879142 00000 n 0000702983 00000 n 0000708745 00000 n 0000941930 00000 n 0000941966 00000 n 0000879312 00000 n 0000708768 00000 n 0000713574 00000 n 0000942028 00000 n 0000942064 00000 n 0000879482 00000 n 0000713597 00000 n 0000716521 00000 n 0000942139 00000 n 0000942175 00000 n 0000879652 00000 n 0000716544 00000 n 0000722521 00000 n 0000942250 00000 n 0000942286 00000 n 0000879822 00000 n 0000722544 00000 n 0000727387 00000 n 0000942348 00000 n 0000942384 00000 n 0000879992 00000 n 0000727410 00000 n 0000728157 00000 n 0000942446 00000 n 0000942482 00000 n 0000880162 00000 n 0000728179 00000 n 0000732857 00000 n 0000942544 00000 n 0000942580 00000 n 0000880340 00000 n 0000732880 00000 n 0000738211 00000 n 0000942642 00000 n 0000942678 00000 n 0000880510 00000 n 0000738234 00000 n 0000742210 00000 n 0000942753 00000 n 0000942789 00000 n 0000880680 00000 n 0000742233 00000 n 0000745692 00000 n 0000942864 00000 n 0000942900 00000 n 0000880858 00000 n 0000745715 00000 n 0000748457 00000 n 0000942975 00000 n 0000943011 00000 n 0000881028 00000 n 0000748480 00000 n 0000748776 00000 n 0000943073 00000 n 0000943109 00000 n 0000881198 00000 n 0000748798 00000 n 0000753551 00000 n 0000943158 00000 n 0000943194 00000 n 0000881376 00000 n 0000753574 00000 n 0000758746 00000 n 0000943243 00000 n 0000943279 00000 n 0000881554 00000 n 0000758769 00000 n 0000764825 00000 n 0000943341 00000 n 0000943377 00000 n 0000881732 00000 n 0000764848 00000 n 0000771260 00000 n 0000943452 00000 n 0000943488 00000 n 0000881910 00000 n 0000771283 00000 n 0000773563 00000 n 0000943563 00000 n 0000943599 00000 n 0000882080 00000 n 0000773586 00000 n 0000773906 00000 n 0000943648 00000 n 0000943684 00000 n 0000882250 00000 n 0000773928 00000 n 0000778881 00000 n 0000943733 00000 n 0000943769 00000 n 0000882420 00000 n 0000778904 00000 n 0000785270 00000 n 0000943818 00000 n 0000943854 00000 n 0000882598 00000 n 0000785293 00000 n 0000792124 00000 n 0000943929 00000 n 0000943965 00000 n 0000882776 00000 n 0000792147 00000 n 0000799385 00000 n 0000944027 00000 n 0000944063 00000 n 0000882954 00000 n 0000799408 00000 n 0000802279 00000 n 0000944112 00000 n 0000944148 00000 n 0000883132 00000 n 0000802302 00000 n 0000802621 00000 n 0000944197 00000 n 0000944233 00000 n 0000883302 00000 n 0000802643 00000 n 0000807492 00000 n 0000944282 00000 n 0000944422 00000 n 0000944567 00000 n 0000944712 00000 n 0000944857 00000 n 0000945002 00000 n 0000945147 00000 n 0000945292 00000 n 0000945432 00000 n 0000945572 00000 n 0000945712 00000 n 0000945852 00000 n 0000945992 00000 n 0000946132 00000 n 0000946277 00000 n 0000946422 00000 n 0000946567 00000 n 0000946705 00000 n 0000946845 00000 n 0000946990 00000 n 0000947130 00000 n 0000947270 00000 n 0000947410 00000 n 0000947550 00000 n 0000947690 00000 n 0000947830 00000 n 0000947970 00000 n 0000948115 00000 n 0000948255 00000 n 0000948400 00000 n 0000948545 00000 n 0000948685 00000 n 0000948825 00000 n 0000948965 00000 n 0000949105 00000 n 0000949245 00000 n 0000949385 00000 n 0000949530 00000 n 0000949670 00000 n 0000949815 00000 n 0000949960 00000 n 0000950105 00000 n 0000950250 00000 n 0000950390 00000 n 0000950530 00000 n 0000950675 00000 n 0000950820 00000 n 0000950965 00000 n 0000951110 00000 n 0000951255 00000 n 0000951400 00000 n 0000951545 00000 n 0000951685 00000 n 0000951825 00000 n 0000951965 00000 n 0000952110 00000 n 0000952255 00000 n 0000952400 00000 n 0000952540 00000 n 0000952680 00000 n 0000952825 00000 n 0000952970 00000 n 0000953115 00000 n 0000953260 00000 n 0000953405 00000 n 0000953550 00000 n 0000953695 00000 n 0000953840 00000 n 0000953985 00000 n 0000954125 00000 n 0000954270 00000 n 0000954410 00000 n 0000954555 00000 n 0000954700 00000 n 0000954840 00000 n 0000954980 00000 n 0000955120 00000 n 0000955260 00000 n 0000955400 00000 n 0000955540 00000 n 0000955680 00000 n 0000955820 00000 n 0000955960 00000 n 0000956105 00000 n 0000956250 00000 n 0000956395 00000 n 0000956540 00000 n 0000956685 00000 n 0000956825 00000 n 0000956970 00000 n 0000957110 00000 n 0000957250 00000 n 0000957390 00000 n 0000957535 00000 n 0000957680 00000 n 0000957825 00000 n 0000957965 00000 n 0000958110 00000 n 0000958255 00000 n 0000958291 00000 n 0000884370 00000 n 0000807515 00000 n 0000814367 00000 n 0000958340 00000 n 0000958485 00000 n 0000958623 00000 n 0000958763 00000 n 0000958903 00000 n 0000959043 00000 n 0000959188 00000 n 0000959333 00000 n 0000959473 00000 n 0000959613 00000 n 0000959758 00000 n 0000959903 00000 n 0000960048 00000 n 0000960193 00000 n 0000960338 00000 n 0000960478 00000 n 0000960623 00000 n 0000960768 00000 n 0000960913 00000 n 0000961058 00000 n 0000961198 00000 n 0000961343 00000 n 0000961488 00000 n 0000961633 00000 n 0000961778 00000 n 0000961923 00000 n 0000962068 00000 n 0000962213 00000 n 0000962353 00000 n 0000962493 00000 n 0000962633 00000 n 0000962778 00000 n 0000962918 00000 n 0000963058 00000 n 0000963198 00000 n 0000963338 00000 n 0000963478 00000 n 0000963618 00000 n 0000963758 00000 n 0000963898 00000 n 0000964038 00000 n 0000964178 00000 n 0000964318 00000 n 0000964458 00000 n 0000964603 00000 n 0000964743 00000 n 0000964888 00000 n 0000965033 00000 n 0000965173 00000 n 0000965313 00000 n 0000965453 00000 n 0000965598 00000 n 0000965743 00000 n 0000965888 00000 n 0000966033 00000 n 0000966178 00000 n 0000966323 00000 n 0000966468 00000 n 0000966613 00000 n 0000966758 00000 n 0000966903 00000 n 0000967043 00000 n 0000967183 00000 n 0000967323 00000 n 0000967463 00000 n 0000967603 00000 n 0000967743 00000 n 0000967888 00000 n 0000968028 00000 n 0000968168 00000 n 0000968313 00000 n 0000968458 00000 n 0000968603 00000 n 0000968748 00000 n 0000968893 00000 n 0000969038 00000 n 0000969183 00000 n 0000969328 00000 n 0000969468 00000 n 0000969608 00000 n 0000969753 00000 n 0000969898 00000 n 0000970043 00000 n 0000970183 00000 n 0000970323 00000 n 0000970468 00000 n 0000970608 00000 n 0000970753 00000 n 0000970893 00000 n 0000971038 00000 n 0000971183 00000 n 0000971321 00000 n 0000971466 00000 n 0000971606 00000 n 0000971746 00000 n 0000971886 00000 n 0000972026 00000 n 0000972166 00000 n 0000972311 00000 n 0000972456 00000 n 0000972601 00000 n 0000972741 00000 n 0000972881 00000 n 0000973021 00000 n 0000973161 00000 n 0000973306 00000 n 0000973446 00000 n 0000973586 00000 n 0000973726 00000 n 0000973866 00000 n 0000974006 00000 n 0000974151 00000 n 0000974296 00000 n 0000974441 00000 n 0000974586 00000 n 0000974731 00000 n 0000974876 00000 n 0000975021 00000 n 0000975166 00000 n 0000975306 00000 n 0000975451 00000 n 0000975596 00000 n 0000975741 00000 n 0000975886 00000 n 0000976031 00000 n 0000976176 00000 n 0000976321 00000 n 0000976466 00000 n 0000976606 00000 n 0000976746 00000 n 0000976891 00000 n 0000977031 00000 n 0000977171 00000 n 0000977311 00000 n 0000977451 00000 n 0000977596 00000 n 0000977741 00000 n 0000977886 00000 n 0000978031 00000 n 0000978176 00000 n 0000978321 00000 n 0000978466 00000 n 0000978611 00000 n 0000978756 00000 n 0000978901 00000 n 0000979046 00000 n 0000979191 00000 n 0000979331 00000 n 0000979367 00000 n 0000885879 00000 n 0000814390 00000 n 0000816180 00000 n 0000979416 00000 n 0000979561 00000 n 0000979701 00000 n 0000979846 00000 n 0000979991 00000 n 0000980131 00000 n 0000980271 00000 n 0000980416 00000 n 0000980556 00000 n 0000980696 00000 n 0000980836 00000 n 0000980981 00000 n 0000981121 00000 n 0000981261 00000 n 0000981406 00000 n 0000981551 00000 n 0000981696 00000 n 0000981841 00000 n 0000981986 00000 n 0000982131 00000 n 0000982276 00000 n 0000982421 00000 n 0000982566 00000 n 0000982711 00000 n 0000982851 00000 n 0000982996 00000 n 0000983136 00000 n 0000983276 00000 n 0000983421 00000 n 0000983561 00000 n 0000983701 00000 n 0000983846 00000 n 0000983991 00000 n 0000984136 00000 n 0000984172 00000 n 0000886362 00000 n 0000816203 00000 n 0000820304 00000 n 0000984208 00000 n 0000984353 00000 n 0000984498 00000 n 0000984643 00000 n 0000984788 00000 n 0000984928 00000 n 0000985068 00000 n 0000985213 00000 n 0000985358 00000 n 0000985498 00000 n 0000985638 00000 n 0000985778 00000 n 0000985923 00000 n 0000986063 00000 n 0000986203 00000 n 0000986343 00000 n 0000986483 00000 n 0000986628 00000 n 0000986773 00000 n 0000986913 00000 n 0000987053 00000 n 0000987198 00000 n 0000987343 00000 n 0000987488 00000 n 0000987628 00000 n 0000987768 00000 n 0000987913 00000 n 0000988053 00000 n 0000988193 00000 n 0000988333 00000 n 0000988478 00000 n 0000988623 00000 n 0000988768 00000 n 0000988913 00000 n 0000989058 00000 n 0000989203 00000 n 0000989348 00000 n 0000989493 00000 n 0000989638 00000 n 0000989778 00000 n 0000989923 00000 n 0000990068 00000 n 0000990208 00000 n 0000990348 00000 n 0000990493 00000 n 0000990633 00000 n 0000990773 00000 n 0000990913 00000 n 0000991053 00000 n 0000991198 00000 n 0000991343 00000 n 0000991488 00000 n 0000991628 00000 n 0000991768 00000 n 0000991913 00000 n 0000992058 00000 n 0000992203 00000 n 0000992348 00000 n 0000992493 00000 n 0000992638 00000 n 0000992783 00000 n 0000992928 00000 n 0000993073 00000 n 0000993218 00000 n 0000993363 00000 n 0000993508 00000 n 0000993653 00000 n 0000993798 00000 n 0000993943 00000 n 0000994083 00000 n 0000994223 00000 n 0000994363 00000 n 0000994503 00000 n 0000994648 00000 n 0000994788 00000 n 0000994928 00000 n 0000995073 00000 n 0000995218 00000 n 0000995363 00000 n 0000995508 00000 n 0000995648 00000 n 0000995788 00000 n 0000995928 00000 n 0000996068 00000 n 0000996208 00000 n 0000996348 00000 n 0000996493 00000 n 0000996638 00000 n 0000996783 00000 n 0000996928 00000 n 0000997073 00000 n 0000997218 00000 n 0000997363 00000 n 0000997508 00000 n 0000997653 00000 n 0000997798 00000 n 0000997938 00000 n 0000998078 00000 n 0000998218 00000 n 0000998358 00000 n 0000998498 00000 n 0000998638 00000 n 0000998783 00000 n 0000998928 00000 n 0000999073 00000 n 0000999213 00000 n 0000999353 00000 n 0000999493 00000 n 0000999633 00000 n 0000999773 00000 n 0000999913 00000 n 0001000058 00000 n 0001000203 00000 n 0001000348 00000 n 0001000488 00000 n 0001000633 00000 n 0001000778 00000 n 0001000923 00000 n 0001001068 00000 n 0001001208 00000 n 0001001348 00000 n 0001001493 00000 n 0001001633 00000 n 0001001778 00000 n 0001001918 00000 n 0001002063 00000 n 0001002203 00000 n 0001002343 00000 n 0001002483 00000 n 0001002623 00000 n 0001002768 00000 n 0001002913 00000 n 0001003053 00000 n 0001003193 00000 n 0001003333 00000 n 0001003473 00000 n 0001003613 00000 n 0001003753 00000 n 0001003898 00000 n 0001004043 00000 n 0001004183 00000 n 0001004328 00000 n 0001004473 00000 n 0001004613 00000 n 0001004753 00000 n 0001004893 00000 n 0001005038 00000 n 0001005183 00000 n 0001005328 00000 n 0001005468 00000 n 0001005608 00000 n 0001005753 00000 n 0001005893 00000 n 0001006038 00000 n 0001006183 00000 n 0001006323 00000 n 0001006463 00000 n 0001006603 00000 n 0001006748 00000 n 0001006888 00000 n 0001007033 00000 n 0001007178 00000 n 0001007323 00000 n 0001007468 00000 n 0001007613 00000 n 0001007758 00000 n 0001007903 00000 n 0001008043 00000 n 0001008188 00000 n 0001008328 00000 n 0001008473 00000 n 0001008618 00000 n 0001008763 00000 n 0001008903 00000 n 0001009043 00000 n 0001009183 00000 n 0001009323 00000 n 0001009468 00000 n 0001009613 00000 n 0001009758 00000 n 0001009903 00000 n 0001010048 00000 n 0001010193 00000 n 0001010338 00000 n 0001010483 00000 n 0001010628 00000 n 0001010773 00000 n 0001010913 00000 n 0001011053 00000 n 0001011198 00000 n 0001011343 00000 n 0001011488 00000 n 0001011633 00000 n 0001011778 00000 n 0001011923 00000 n 0001012068 00000 n 0001012213 00000 n 0001012358 00000 n 0001012503 00000 n 0001012648 00000 n 0001012793 00000 n 0001012938 00000 n 0001013083 00000 n 0001013223 00000 n 0001013368 00000 n 0001013508 00000 n 0001013648 00000 n 0001013788 00000 n 0001013928 00000 n 0001014068 00000 n 0001014208 00000 n 0001014348 00000 n 0001014488 00000 n 0001014628 00000 n 0001014773 00000 n 0001014918 00000 n 0001015058 00000 n 0001015198 00000 n 0001015338 00000 n 0001015483 00000 n 0001015628 00000 n 0001015773 00000 n 0001015918 00000 n 0001016063 00000 n 0001016203 00000 n 0001016343 00000 n 0001016483 00000 n 0001016623 00000 n 0001016763 00000 n 0001016908 00000 n 0001017053 00000 n 0001017198 00000 n 0001017338 00000 n 0001017483 00000 n 0001017628 00000 n 0001017768 00000 n 0001017913 00000 n 0001018058 00000 n 0001018203 00000 n 0001018343 00000 n 0001018483 00000 n 0001018623 00000 n 0001018768 00000 n 0001018908 00000 n 0001018944 00000 n 0000888735 00000 n 0000820327 00000 n 0000820892 00000 n 0001018993 00000 n 0001019138 00000 n 0001019283 00000 n 0001019428 00000 n 0001019573 00000 n 0001019718 00000 n 0001019863 00000 n 0001020008 00000 n 0001020148 00000 n 0001020293 00000 n 0001020438 00000 n 0001020578 00000 n 0001020718 00000 n 0001020858 00000 n 0001020998 00000 n 0001021034 00000 n 0000889047 00000 n 0000820914 00000 n 0000821220 00000 n 0001021070 00000 n 0001021106 00000 n 0000889217 00000 n 0000821242 00000 n 0000824219 00000 n 0001021155 00000 n 0001021191 00000 n 0000889387 00000 n 0000824242 00000 n 0000828120 00000 n 0001021253 00000 n 0001021289 00000 n 0000889557 00000 n 0000828143 00000 n 0000831753 00000 n 0001021351 00000 n 0001021387 00000 n 0000889727 00000 n 0000831776 00000 n 0000835211 00000 n 0001021436 00000 n 0001021472 00000 n 0000889897 00000 n 0000835234 00000 n 0000838864 00000 n 0001021534 00000 n 0001021570 00000 n 0000890067 00000 n 0000838887 00000 n 0000840908 00000 n 0001021619 00000 n 0001021655 00000 n 0000890237 00000 n 0000840931 00000 n 0000843602 00000 n 0001021717 00000 n 0001021753 00000 n 0000890407 00000 n 0000843625 00000 n 0000846345 00000 n 0001021815 00000 n 0001021851 00000 n 0000890577 00000 n 0000846368 00000 n 0000848927 00000 n 0001021913 00000 n 0001021949 00000 n 0000890747 00000 n 0000848950 00000 n 0000851551 00000 n 0001021998 00000 n 0001022034 00000 n 0001026534 00000 n 0001031561 00000 n 0001037577 00000 n 0001047212 00000 n 0001049790 00000 n 0001056177 00000 n 0001058676 00000 n 0001059280 00000 n 0001060620 00000 n 0001022902 00000 n 0001023545 00000 n 0001024552 00000 n 0001025439 00000 n 0001026083 00000 n 0001098829 00000 n trailer << /Size 1803 /Root 1 0 R /Info 2 0 R /ID [<00198625F6A1052C1C68F87F44B66A7C><00198625F6A1052C1C68F87F44B66A7C>] >> startxref 1100646 %%EOF cfitsio/docs/cfitsio.ps0000644000225700000360000457122713246025103014756 0ustar cagordonlhea%!PS-Adobe-2.0 %%Creator: dvips(k) 5.96.1 Copyright 2007 Radical Eye Software %%Title: cfitsio.dvi %%CreationDate: Fri Jul 28 13:53:00 2017 %%Pages: 196 %%PageOrder: Ascend %%BoundingBox: 0 0 612 792 %%DocumentFonts: CMBX12 CMR12 CMR10 CMBX10 CMSL10 CMTT10 CMSY10 CMMI10 %%+ CMTI10 %%DocumentPaperSizes: Letter %%EndComments %DVIPSWebPage: (www.radicaleye.com) %DVIPSCommandLine: dvips -o cfitsio.ps cfitsio.dvi %DVIPSParameters: dpi=600 %DVIPSSource: TeX output 2017.07.28:1352 %%BeginProcSet: tex.pro 0 0 %! /TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin /FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array /BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get }B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr 1 add N}if}B/CharBuilder{save 3 1 roll S A/base get 2 index get S /BitMaps get S get/Cd X pop/ctr 0 N Cdx 0 Cx Cy Ch sub Cx Cw add Cy setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx sub Cy .1 sub]{Ci}imagemask restore}B/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put }if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X 1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N /p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{ /Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT) (LaserWriter 16/600)]{A length product length le{A length product exch 0 exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot} imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M} B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{ p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end %%EndProcSet %%BeginProcSet: texps.pro 0 0 %! TeXDict begin/rf{findfont dup length 1 add dict begin{1 index/FID ne 2 index/UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]FontType 0 ne{/Metrics exch def dict begin Encoding{exch dup type/integertype ne{ pop pop 1 sub dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def}ifelse}forall Metrics/Metrics currentdict end def}{{1 index type /nametype eq{exit}if exch pop}loop}ifelse[2 index currentdict end definefont 3 -1 roll makefont/setfont cvx]cvx def}def/ObliqueSlant{dup sin S cos div neg}B/SlantFont{4 index mul add}def/ExtendFont{3 -1 roll mul exch}def/ReEncodeFont{CharStrings rcheck{/Encoding false def dup[ exch{dup CharStrings exch known not{pop/.notdef/Encoding true def}if} forall Encoding{]exch pop}{cleartomark}ifelse}if/Encoding exch def}def end %%EndProcSet %%BeginProcSet: special.pro 0 0 %! TeXDict begin/SDict 200 dict N SDict begin/@SpecialDefaults{/hs 612 N /vs 792 N/ho 0 N/vo 0 N/hsc 1 N/vsc 1 N/ang 0 N/CLIP 0 N/rwiSeen false N /rhiSeen false N/letter{}N/note{}N/a4{}N/legal{}N}B/@scaleunit 100 N /@hscale{@scaleunit div/hsc X}B/@vscale{@scaleunit div/vsc X}B/@hsize{ /hs X/CLIP 1 N}B/@vsize{/vs X/CLIP 1 N}B/@clip{/CLIP 2 N}B/@hoffset{/ho X}B/@voffset{/vo X}B/@angle{/ang X}B/@rwi{10 div/rwi X/rwiSeen true N}B /@rhi{10 div/rhi X/rhiSeen true N}B/@llx{/llx X}B/@lly{/lly X}B/@urx{ /urx X}B/@ury{/ury X}B/magscale true def end/@MacSetUp{userdict/md known {userdict/md get type/dicttype eq{userdict begin md length 10 add md maxlength ge{/md md dup length 20 add dict copy def}if end md begin /letter{}N/note{}N/legal{}N/od{txpose 1 0 mtx defaultmatrix dtransform S atan/pa X newpath clippath mark{transform{itransform moveto}}{transform{ itransform lineto}}{6 -2 roll transform 6 -2 roll transform 6 -2 roll transform{itransform 6 2 roll itransform 6 2 roll itransform 6 2 roll curveto}}{{closepath}}pathforall newpath counttomark array astore/gc xdf pop ct 39 0 put 10 fz 0 fs 2 F/|______Courier fnt invertflag{PaintBlack} if}N/txpose{pxs pys scale ppr aload pop por{noflips{pop S neg S TR pop 1 -1 scale}if xflip yflip and{pop S neg S TR 180 rotate 1 -1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg TR}if xflip yflip not and{pop S neg S TR pop 180 rotate ppr 3 get ppr 1 get neg sub neg 0 TR}if yflip xflip not and{ppr 1 get neg ppr 0 get neg TR}if}{ noflips{TR pop pop 270 rotate 1 -1 scale}if xflip yflip and{TR pop pop 90 rotate 1 -1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg TR}if xflip yflip not and{TR pop pop 90 rotate ppr 3 get ppr 1 get neg sub neg 0 TR}if yflip xflip not and{TR pop pop 270 rotate ppr 2 get ppr 0 get neg sub neg 0 S TR}if}ifelse scaleby96{ppr aload pop 4 -1 roll add 2 div 3 1 roll add 2 div 2 copy TR .96 dup scale neg S neg S TR}if}N/cp{pop pop showpage pm restore}N end}if}if}N/normalscale{ Resolution 72 div VResolution 72 div neg scale magscale{DVImag dup scale }if 0 setgray}N/psfts{S 65781.76 div N}N/startTexFig{/psf$SavedState save N userdict maxlength dict begin/magscale true def normalscale currentpoint TR/psf$ury psfts/psf$urx psfts/psf$lly psfts/psf$llx psfts /psf$y psfts/psf$x psfts currentpoint/psf$cy X/psf$cx X/psf$sx psf$x psf$urx psf$llx sub div N/psf$sy psf$y psf$ury psf$lly sub div N psf$sx psf$sy scale psf$cx psf$sx div psf$llx sub psf$cy psf$sy div psf$ury sub TR/showpage{}N/erasepage{}N/setpagedevice{pop}N/copypage{}N/p 3 def @MacSetUp}N/doclip{psf$llx psf$lly psf$urx psf$ury currentpoint 6 2 roll newpath 4 copy 4 2 roll moveto 6 -1 roll S lineto S lineto S lineto closepath clip newpath moveto}N/endTexFig{end psf$SavedState restore}N /@beginspecial{SDict begin/SpecialSave save N gsave normalscale currentpoint TR @SpecialDefaults count/ocount X/dcount countdictstack N} N/@setspecial{CLIP 1 eq{newpath 0 0 moveto hs 0 rlineto 0 vs rlineto hs neg 0 rlineto closepath clip}if ho vo TR hsc vsc scale ang rotate rwiSeen{rwi urx llx sub div rhiSeen{rhi ury lly sub div}{dup}ifelse scale llx neg lly neg TR}{rhiSeen{rhi ury lly sub div dup scale llx neg lly neg TR}if}ifelse CLIP 2 eq{newpath llx lly moveto urx lly lineto urx ury lineto llx ury lineto closepath clip}if/showpage{}N/erasepage{}N /setpagedevice{pop}N/copypage{}N newpath}N/@endspecial{count ocount sub{ pop}repeat countdictstack dcount sub{end}repeat grestore SpecialSave restore end}N/@defspecial{SDict begin}N/@fedspecial{end}B/li{lineto}B /rl{rlineto}B/rc{rcurveto}B/np{/SaveX currentpoint/SaveY X N 1 setlinecap newpath}N/st{stroke SaveX SaveY moveto}N/fil{fill SaveX SaveY moveto}N/ellipse{/endangle X/startangle X/yrad X/xrad X/savematrix matrix currentmatrix N TR xrad yrad scale 0 0 1 startangle endangle arc savematrix setmatrix}N end %%EndProcSet TeXDict begin @defspecial /DvipsToPDF { 72.27 mul Resolution div } def /PDFToDvips { 72.27 div Resolution mul } def /HyperBorder { 1 PDFToDvips } def /H.V {pdf@hoff pdf@voff null} def /H.B {/Rect[pdf@llx pdf@lly pdf@urx pdf@ury]} def /H.S { currentpoint HyperBorder add /pdf@lly exch def dup DvipsToPDF /pdf@hoff exch def HyperBorder sub /pdf@llx exch def } def /H.L { 2 sub dup /HyperBasePt exch def PDFToDvips /HyperBaseDvips exch def currentpoint HyperBaseDvips sub /pdf@ury exch def /pdf@urx exch def } def /H.A { H.L currentpoint exch pop vsize 72 sub exch DvipsToPDF HyperBasePt sub sub /pdf@voff exch def } def /H.R { currentpoint HyperBorder sub /pdf@ury exch def HyperBorder add /pdf@urx exch def currentpoint exch pop vsize 72 sub exch DvipsToPDF sub /pdf@voff exch def } def systemdict /pdfmark known { userdict /?pdfmark systemdict /exec get put }{ userdict /?pdfmark systemdict /pop get put userdict /pdfmark systemdict /cleartomark get put } ifelse @fedspecial end %%BeginFont: CMTI10 %!PS-AdobeFont-1.1: CMTI10 1.00B %%CreationDate: 1992 Feb 19 19:56:16 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.00B) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMTI10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle -14.04 def /isFixedPitch false def end readonly def /FontName /CMTI10 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 68 /D put dup 72 /H put dup 85 /U put dup 97 /a put dup 98 /b put dup 101 /e put dup 103 /g put dup 105 /i put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put readonly def /FontBBox{-163 -250 1146 969}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA0529731C99A784CCBE85B4993B2EEBDE 3B12D472B7CF54651EF21185116A69AB1096ED4BAD2F646635E019B6417CC77B 532F85D811C70D1429A19A5307EF63EB5C5E02C89FC6C20F6D9D89E7D91FE470 B72BEFDA23F5DF76BE05AF4CE93137A219ED8A04A9D7D6FDF37E6B7FCDE0D90B 986423E5960A5D9FBB4C956556E8DF90CBFAEC476FA36FD9A5C8175C9AF513FE D919C2DDD26BDC0D99398B9F4D03D5993DFC0930297866E1CD0A319B6B1FD958 9E3948FFB0B4E70F212EC976D65099D84E0D37A7A771C3101D6AD26A0513378F 21EC3643079EECE0C9AB54B4772E5DCA82D0D4ACC7F42FB493AA04A3BF4A1BD6 06ECE186315DBE9CFDCB1A0303E8D3E83027CD3AFA8F0BD466A8E8CA0E7164CF 55B332FAD43482748DD4A1CB3F40CB1F5E67192B8216A0D8FE30F9F05BF016F5 B5CC130A4B0796EE065495422FBA55BEE9BFD99D04464D987AC4D237C208FA86 0B112E55CE7B3782A34BC22E3DE31755D9AFF19E490C8E43B85E17ECE87FA8B9 1485831624D24F37C39BF9972D74E6EC4784727AC00B9C4A3AD3DA1C22BD6961 7E0ADAF55422F22ACA5E4DCD4DF9FCD187A566B7FB661D0530454D0DD6C6C50A 7A3875C6CBF8EC7769F32A1F3F7FC1C072BADEC97794D4E90E0035282A170402 356E5A9CD9ABD80AC4342A5283E458A7269252F4541CBB6452B39ED54D336D0B 19928E9CD1AB26AD83EB209E2EC75011A2643813053B5DBB0246097C4821B5F2 C92554E9140BE35B2DBFCD98809A8EC9FC910FDE9E0D86457C70ACB056EBF90F 244DC0A5BBD455E15D6E3180311D52CF50B0BF7D0A7F64F3A1821E0AEDBC2E7B AEB549FE1D51088C153799C6E089B5D5D65E1C4E2D2B430CDF1FFA23CCB25D95 5C43C8942435D0AAA3D9055FF808F2C3C887A3C469BBD98F026D0A59E26BA9F9 C2144CFE49A9AD892D4D31764F0AE3A10644AE3966B0A790684B14D11FA49785 EC5565D2B2E584CBFD85125F3FAC133338DE35361943DCE9AF05FCF2840CE512 998D42CBEC52B57B79DD63F00985881E8463396ADA47189A94DDF951A78866F0 B8A3D9197E39335277EF2294308DA70065D910943A34F7D5F2090FB4AA42ED70 CBA469A9F64B95A6FBA4BC89DBC93765E3AE4723162DF3F9D6BDE77DD5870ADE C8900D6346957B84C3CE88A8F9A12D46B8FCA50DF4433B0B8AED6A63B3DA102B 6DF94E62408E24154BAAC66B2B249C695BC0FA37A28699D9C0F3EE94AA32E3C5 8F8D7F803B5D25014D43A353D719B14B247A87898A960DF68C0C0BAF70C83917 6E9F7B3ACC64DBAEF3FDCD3A80C0AB907EE342E543D607556CBE5A9089B86D1D E768F27D74A613F3ABF883222A8596B542EBF54E9DCE327B5682AEE5F6BCC38A 2A052EC4018AE3189DC1963BA39ACDED8F0C60C83F8873FBBF0302010956C520 A7F3F8ECD0F177EDF5F4D5522C5984A3678FF32EEEB570B69C142AB89467641F 917155D646DAF3352E27BF2AA0746E062E48532256AF364EFC0F0AAE3766F75C 5219ABA60BDFF177558536E000DE3263A4A6EAAA669F9F4E94BAB336391AF5FB 280A5B39995483E788CE4820EF77AECD73B1AE89DAC3F13E333F2628CDBA431D 2A5E547D4225E6BE13119660BEBC155823A51477647F7E07A23D7D24353F584B 2B311C4529E0E408B4E89A467BC03794CF4E7AA0A717A8247D5B60F438417D01 8155F17E09D4C4FECED18CE574D6849640E5E0592D771F026BCB0CE66FD13BC9 5A89D07EE26021FD5DF14B96AEDC02AEC3E099088C1DAE4FCA2AE841B17F5C4A D251FB56462CF050AD3CA84DA12DC1D17F80301CCFDE6C35C81FA538A389E0B6 8BFF0DDC4B97D49B485E8C6AF47F951C042D2C750748B4084B3F4AC18488EEC2 900A9672A6CA2B06A0F091E8DD9DFE504A5C6DF1537AE7F54DCFD94EF5CC663A A80E1C64CF1CD751D28858CDACA6F7CD0463A86619E87B9C03C9448B44537E78 5E60A25045FBDBEE678737FA45F029D92908443C7BB9FC87B7B280C314F39A96 B5287BA21CB3EBCF7816BC0900095F3F9F11D7774BC1D1D4A7F8098C610E3FB2 C2E2E9D9DAAA6CD1EE4F35CE854B7C79DF8318CCC10C52DE36E4AC5D75ED7D8A DD4E8A3B827DC8A7D437DD38B782929EA60CAC4930F9711087DDC18574B472FA B40DEFFED99BE0C0CA85E9FA2028152C8B6423CB94E797E3651043BE9636109E 87B70592852FD5198A7D340C0E1C419D0EBAEAF483300E41A6F6B1DFEAB071CD A4E0A596509369A4EDB66ABC883443FC615AFFA74C672922D263B5F64E861C6D C44E9C0BBBBA305C9AB04FAEB77E0C25C0D67F77639F6022D028847E796879D2 B6C4AB4313FF3568E407784F1E00503A5875DC68464A720C8E55BCD80269B4DE B3C05D49DD15B581554B61E9D6313D47C39991582BECB1EF6E959CC64167DA7E F98EB7F130EE821FF04BB4842D3B8F23E81C4DB8C4B340EC9807DA0CC2627ABE 9F1505EDA580A499BDC35E348CA6A15FB197597A5A3E519DF0B4749D5DC67B8E 2D93EA98498CA6129C0993C0A6945A5137CB4A1B4B38A008B1559D719681E6AC 09FAA1D2337E266FDC02D77AE822DC13724A0620C5ABFDA9402D3DD4DCB80CA5 28F875133862164328A59F7E58E36CA06F23E651D8BBAA490D145F3788A30BA9 C5389826A4B2F17E2B301BE89C464D9888C1E798744E815C44E68B94BABB8FC4 2872E1AFBB63CA489FB1504926C84C5F8AC7E6A93942C3B0C3250EEFAFF70449 3734AA4932BBF7B098C8287D8DD2F0E75F0F7B184BE5A24A6C9EF1C7CE86D58E 1018668396EF8842609FD4C207CF3D818DA21AB4FB96EDEDF11905E15153D319 93EF1A3297FB71AC25E9FEE544D66A2E6D94D147408033B1784D060EA8BD6807 1A2194884CBEFD552D52B7B8B63A2A9A1DE5C4B437262091089497D10E4C1678 52664B16F1FA71371BDF96D038FF88F695A02B7057DB4D97CC9AF8534518BE9E FCE87619AD6BDAFBE6EE8FDDE427D3CCD32E4143AB09B27F559E7727CEF7F39F DFB7E07E86E3512757E64C82D0FA29EB1E00E4F213B12679E2307BA8A363BBF6 B3411F4C50A8E51A11D6716CB5431B6B941B5548FCA3C85B3829F7EC05D881DE 4D2E994F6C815589CB4F5188A581FD9BE70E9D01E8F36BFBB5732F89DA7651FE 9F20A732F94035BDAB79728D559647EBC1A386F7BB3489D59BCB048910AB9D2F 38F9B3B9C0648A9AFA41B4089CE3EF93E7E8E5140532EFD745AE3F000502344B 5030FC71BAC616EF9349D5C8B336FA9A3624E1D2DDBE5C596702F778FD9FA98F 5899447510DDCDE2599939667F9831B6D06ED3CE3167D15F9C502EB035A05B86 D4AA82D68A8511BFD3312250273545C5C4355629DFEE31B5A1B078BC2C805305 22A3F4865F9C978C6E71A5F5C858E21CBA36053277190DB9D89A4B985FB916D8 DEC338E997F3226EAFA917AA18C1C9B055BB82DDDD50FFE00B93DA5C9C662760 7326F16E661443A6EDCCC04FF913605AD63E022EB96C7C9A7FA60E185073E163 0A61ADC0E39B114BE69EAA874209C8713E765D017A8D727648B0340295D56C13 34A95D3D2F40CF4CD2BBE527C433E09F00BC1BD5C7425E4DB2A17204F0B8DBA2 82CA3F37C424FC07B69C89635DFB3971894E946D928802471C2B1C40F49701FB 485186D20A803C0BA76DFED4ECB2446FF25258118E593CD1EBC8ACA718B5C9D6 C4F5AC941B28716B10B283FED21A16C94E92C431BFB9C8AC3D3F1EF7DC46ACCC A82ACCE510A3F687AAEDC6839800F48AC96A5B81A97FE4F37CAA586969AB3D58 001C8134BE160EEEDB79A780D2AA57BEEBD2FBCD9A453066B6642C459A679A84 5E3FB8F50F7C00EFDE6049D2C01893750C5F60F2DC98FC36F2E656774123DFF3 E4EEE44D085083365124889B3103DFA03F5A5648446BDDAC9FA40C69D83D2D4D 0D6017D7D840A4F7CD97EFF126F48B331CAF5DE0856F689FD0FC450005793C8A 74EC6BEF32FF405AA2F4F6ADF624E0C72CEF916ABD6BDB7C0AEECEA855F07AA7 E5BE6F7DCCE459F4F390965C9350A3060825CE22CC25905FEEE40E4973C0189E 5021FF9FC2EAB4301790F255B617638A2C44F4D71A74EE96DA5178A9296D388C 0D43CD188C0F78D9A57D78EBE390A2BCCD0AC3087AF4A1273443795EF08D0F11 ABEA3A173746C05E538D88FBC0A3A1DC82A762F951E63A135F63BC3B7E05B8E6 B89DF17BD32E871FE1C967B5DA4FCB9187747B6A30B551B9C4FE920C34E40A8B E268ED41382AD1DED7E79D18469F58305CE1275C4AFBE4770BCD87D06D7101F7 5EBF74D9F3AFF9608BE5736BF1B2B33B4B3E3C8CFD3A91CECDFCD7E0A4A586FC 699EE79D7756E49DD686C65451A58BEDCF0FEED1B23EB408845391FEE74A3628 11837485BDE72131D0EF7D0EDA3E23BCEFAFF9DC2616CBC8E52523EA157DF140 9498280EB11F1C42B05BA5281F7ACE1BF40F74F3D5D61A6B852461013F773915 0BA29094461022A1F1AD4B62CD619E6BDE7CA645914ABDFE87758C039B3C3848 04BAF878C215BBC35A1D259B2CC21AA2B7C7B43165398CF37779B31190DC8526 41E02F9361CA8E7750A39478DEAA823069009007B53FCBABBA40A98C90E603F0 C76E3383938422548A9A49CD8D9CABEFEC5D9DB27F60303DE67AAC2E79EBE12E 48A2D6B687A720D73169236DFE597514C656AACF348201B76008714FEB551241 5F2C86E06820109386E5588A7E67651C1EA9422DE9307BEEED35E87B6B61F0DE 3EE5C5B7FD94350FBB081378191539122C6A73939BA7D47AF08E54C5CC4553DA 420E9680BA4B954D9BBE82A8FC559C86861760F9B24103493A26FB55E2DC7880 5ABD36590011431ED606491093B769CA74AA6F8B91076D6D8368BB39D4C7B435 CC461A9E9FBDB28772E51AC2C563DD42C4A87F7A544C8B6D10D5D2504F9A4BBD D4F1A5A6DF8278AB6F3B10214AD75FEB1B5E32801D2631983E2735BE149FAFA1 560E57087EAEC3E45526DF9C748F42E6540CCB14DE6DD11509F3F1BD6D5B3BFD 3D59D2EDB6235DEEE1A893F522497EC38CEED07774E8B23AFC381D6432B87015 A586224B9EC36C4498624E5CF2E9BE61FBFF52F479F4CD12A717C0FCC19182B5 A5A9F8D415472F4C61E8965AE972EDAC4A17776B6EC1132CE29D6396D2B01B6D BEBA1ABD3273C62B3475E2DB8B57E61208AC63BFF8CCE2BA085321FE0C9F874C A645C234812D75E9C5C02D0B0E13D57725D105724BB2C5A916F6E82D57D005F3 9F6B1F041A2B9675AF901B171E6E896F5B8FC545BC88E183AC5E5F1B2288CC5C 7351BAD140CBFA03F2FD18298551BDB15024BCBE844B418B067208EA0A13B731 58747D1B90BB00E37FD7DF9FFAAC80DBDD92E1301DDF1ADE62ACBF169FBFD927 AA84D56E00D02D5B8A34FE3D2B1AAC470336AA02062F42F2C958307142F7C6E7 BD440AC8D8C6A46DFB2B42A32BFA4255A47F3CB3F0733F294EB47AA59DD26A03 C81A4BD18162EFCB77F3BBEC3E8B225E76BA51DE178468B529D146A544180542 6EAE3A451781F5E38DF15BB377C9FE92096E976AFC14DADD11581D29222948F9 FE23D981CEE4E5013025FF3E69E479D32A7A8D25A842FB288A0EC63E23E297E0 168D22FEC35E333A2D67A37A4EED7B59A06F21F44DC6831CAFA473E48A66EDB5 00FEC1D5399A06F51A8A67A6803FE34C1B1F2E4CA8D7EA3CFA8BD046D477777A D283296A8F181D671CBA5B9793DE178BFAF807A6F71E4FC6D69CE7CFEF11D0B6 F8B23221E627475226706C19EF519D19B80633DDBF4A1AD9E271E547CCC846B3 859CD96E495D12E3D5557A309F12949ACF5F373A29C0FD4A6456C737E6F08BDE 0A0C692D66BCE059ADB9B91F8F81975308ECB3313B34093E06462C9DA76A4BB2 1D8DEB5E4526CF73DA4D9D5CC7148E5FBABDF1D45F024469B6D84BB607BA975F 1F6EE627044A93D108427B6C14528B5C6D1568E65F3450D7F4A37EE34D619138 8B7914C63A362737025C0E57F928AB5741CB79D137249914A3CEEC0DECFF639C 0F6B8125C643EDA71F2945FC7DB555E4ED2896C49E83D4515B0DA9A72764C792 9D6A72F18F15C71BB655DD64E421EFF712865D45D2642C7E63501F3289D589FB B983626C60523142AFBEADD4019BB3C4D9C6ADD66012D0CA6AAB374FCB7FF77E 89BF30C153007F48E06EE2278BFF6F0C9AD9BCE6AF9A9171A58EA65CBA2A6A82 E35D45980D84DE7D9199344686C8F08090DF43D0051C15C4E19A9D1C76E4686D 7412DAE7F6EF4E86230C43187D1997E98010F6C8E5E8941DC837C6E73E9C0947 AD2B9E8333BE73BF30D56C31E2B76DE3F6C841F42B109270CBE04D10A9D64CE9 0FB722EC4FCC3F1EB7CCAA2C6C6B3D285D786DAC189F440F32057CFC882A6257 3068C55D4470801D8E2D6B5972D30B54C54E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMMI10 %!PS-AdobeFont-1.1: CMMI10 1.100 %%CreationDate: 1996 Jul 23 07:53:57 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.100) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMMI10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle -14.04 def /isFixedPitch false def end readonly def /FontName /CMMI10 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 62 /greater put readonly def /FontBBox{-32 -250 1048 750}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA0529731C99A784CCBE85B4993B2EEBDE 3B12D472B7CF54651EF21185116A69AB1096ED4BAD2F646635E019B6417CC77B 532F85D811C70D1429A19A5307EF63EB5C5E02C89FC6C20F6D9D89E7D91FE470 B72BEFDA23F5DF76BE05AF4CE93137A219ED8A04A9D7D6FDF37E6B7FCDE0D90B 986423E5960A5D9FBB4C956556E8DF90CBFAEC476FA36FD9A5C8175C9AF513FE D919C2DDD26BDC0D99398B9F4D03D5993DFC0930297866E1CD0A319B6B1FD958 9E394A533A081C36D456A09920001A3D2199583EB9B84B4DEE08E3D12939E321 990CD249827D9648574955F61BAAA11263A91B6C3D47A5190165B0C25ABF6D3E 6EC187E4B05182126BB0D0323D943170B795255260F9FD25F2248D04F45DFBFB DEF7FF8B19BFEF637B210018AE02572B389B3F76282BEB29CC301905D388C721 59616893E774413F48DE0B408BC66DCE3FE17CB9F84D205839D58014D6A88823 D9320AE93AF96D97A02C4D5A2BB2B8C7925C4578003959C46E3CE1A2F0EAC4BF 8B9B325E46435BDE60BC54D72BC8ACB5C0A34413AC87045DC7B84646A324B808 6FD8E34217213E131C3B1510415CE45420688ED9C1D27890EC68BD7C1235FAF9 1DAB3A369DD2FC3BE5CF9655C7B7EDA7361D7E05E5831B6B8E2EEC542A7B38EE 03BE4BAC6079D038ACB3C7C916279764547C2D51976BABA94BA9866D79F13909 95AA39B0F03103A07CBDF441B8C5669F729020AF284B7FF52A29C6255FCAACF1 74109050FBA2602E72593FBCBFC26E726EE4AEF97B7632BC4F5F353B5C67FED2 3EA752A4A57B8F7FEFF1D7341D895F0A3A0BE1D8E3391970457A967EFF84F6D8 47750B1145B8CC5BD96EE7AA99DDC9E06939E383BDA41175233D58AD263EBF19 AFC0E2F840512D321166547B306C592B8A01E1FA2564B9A26DAC14256414E4C8 42616728D918C74D13C349F4186EC7B9708B86467425A6FDB3A396562F7EE4D8 40B43621744CF8A23A6E532649B66C2A0002DD04F8F39618E4F572819DD34837 B5A08E643FDCA1505AF6A1FA3DDFD1FA758013CAED8ACDDBBB334D664DFF5B53 9560176676ABB71BBD0EE56B4CC492C0652750227CEC7B86E4740EB7B8775564 332769DD30794E501BBB0E4E5CB665F3628E10B1137CC8BC5C0A64A310B5E27E 5FD6E3B04DA3914C15987E638A72790AF4073CE9CDBF6E3C749CB4DFF9C54951 A58C386C54BC4E98B102B5E91E8567D2EEEF048F2CBD5D243701D20909290B4B A3083F632D8552D42DEE0C69A4B14D8B15AA082DECC12B2ECAE6F663E6D09F81 EE2979EF41FBF12C9D8BF23B77E0A20088EBD107C5BF9DD6F03FFC3AB65B69A7 54953327E1D4AEF5A146273392BBDB321D4CC9A8FFFCFE5C515B466E21546CC7 C6209E5A76F916B03DB98BC6CED334F33E7B373D42761696F5A876CA6F93F16E 15A07E2E102148CA4F62A99C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMSY10 %!PS-AdobeFont-1.1: CMSY10 1.0 %%CreationDate: 1991 Aug 15 07:20:57 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.0) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMSY10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle -14.035 def /isFixedPitch false def end readonly def /FontName /CMSY10 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 15 /bullet put dup 102 /braceleft put dup 103 /braceright put dup 106 /bar put readonly def /FontBBox{-29 -960 1116 775}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052F09F9C8ADE9D907C058B87E9B6964 7D53359E51216774A4EAA1E2B58EC3176BD1184A633B951372B4198D4E8C5EF4 A213ACB58AA0A658908035BF2ED8531779838A960DFE2B27EA49C37156989C85 E21B3ABF72E39A89232CD9F4237FC80C9E64E8425AA3BEF7DED60B122A52922A 221A37D9A807DD01161779DDE7D31FF2B87F97C73D63EECDDA4C49501773468A 27D1663E0B62F461F6E40A5D6676D1D12B51E641C1D4E8E2771864FC104F8CBF 5B78EC1D88228725F1C453A678F58A7E1B7BD7CA700717D288EB8DA1F57C4F09 0ABF1D42C5DDD0C384C7E22F8F8047BE1D4C1CC8E33368FB1AC82B4E96146730 DE3302B2E6B819CB6AE455B1AF3187FFE8071AA57EF8A6616B9CB7941D44EC7A 71A7BB3DF755178D7D2E4BB69859EFA4BBC30BD6BB1531133FD4D9438FF99F09 4ECC068A324D75B5F696B8688EEB2F17E5ED34CCD6D047A4E3806D000C199D7C 515DB70A8D4F6146FE068DC1E5DE8BC57030ACE57A0A31C99BEDB251A0ECAD78 253AB321023D15FF7F55A3CE81514C1E7E76240C1FB36CD4874DDB761CC325F5 D588700B294849D690F93526EF438A42B9B5B0508584EA3766D35F5B8D51C458 ECB9FBD23A49576EAB06BACB7EA6D300985500835F4FE597D4A1110C8EABE6FC CE3E1F95CFD3A42446F25355381D476B2FFB6EF247BF58A6FFC5EC0E4CC207BE 46485F8E07350B37DCA8C1864E62614332A1D3C9DEDDD6492181949A2C3498C9 EC2A81C1F4FF989A4654E375F509D24D969B97D2A9940FAF43BBB286E08559C0 F8D9674B0A294B36D3A050F7DED8C80E1D230812F6B8387B17948FD29FF050E2 AAC5EBE5D96AFD0879534E2F4BB81613A1571750F9CF4215199F93813D815B5D 1C79E11A0FCBB627CDE569F88C741CD502627777BB058ECAC09B6ACCFACA69B9 8F8168B0B5A1A6EB13E884B348FBB2ACF9EB180F6E27D57F8503710CE037A34A F8B157201657C825E2A4B4A7696B58B7A988C05E43E66F0FF277A7694C555C54 AFB1D32F6DE102136FC810E1F3B5CEA42476EAC7AAFB390E3252B2169DCDEE6E 328507BD0E24734A85AAA263E0D2F64BE1607455BC855785BC27F8B30FE917B4 23AB3C812975355942E955501AF85A3C0CE836911AF679EA44AD6A7D042A6549 0C471FE294E8490024D93ADCADED460FAB7FBCDC29EFEBD2A9A127E11869E659 961B29206CE63944B6FA4B9315BCC528EB1E0223CE94C795A5D5231A7FC8545D 6B287B965F8EEDDB67A6774129DD01D5A21694ABE320BB2553043D4C42ACFF91 1009372CB03381035BEEEEFD05631E026A0980A72A67B3703323A4E7C94FFCEE 8D0B7407F9CCC043D3D184BEA4728385D6AB2FB0641DD8F5BA7E04035D30D628 7E97D31C1486DFD5B1D076B84B4ABA4829ED4310321F1F24B847C44E00185A69 37711A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMBX12 %!PS-AdobeFont-1.1: CMBX12 1.0 %%CreationDate: 1991 Aug 20 16:34:54 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.0) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMBX12) readonly def /FamilyName (Computer Modern) readonly def /Weight (Bold) readonly def /ItalicAngle 0 def /isFixedPitch false def end readonly def /FontName /CMBX12 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 11 /ff put dup 12 /fi put dup 39 /quoteright put dup 40 /parenleft put dup 41 /parenright put dup 45 /hyphen put dup 46 /period put dup 47 /slash put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 55 /seven put dup 56 /eight put dup 57 /nine put dup 58 /colon put dup 65 /A put dup 66 /B put dup 67 /C put dup 68 /D put dup 69 /E put dup 70 /F put dup 71 /G put dup 72 /H put dup 73 /I put dup 75 /K put dup 76 /L put dup 77 /M put dup 78 /N put dup 79 /O put dup 80 /P put dup 82 /R put dup 83 /S put dup 84 /T put dup 85 /U put dup 86 /V put dup 87 /W put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 102 /f put dup 103 /g put dup 104 /h put dup 105 /i put dup 107 /k put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 113 /q put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 118 /v put dup 119 /w put dup 120 /x put dup 121 /y put dup 122 /z put readonly def /FontBBox{-53 -251 1139 750}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 2BDBF16FBC7512FAA308A093FE5F0364CD5660F74BEE96790DE35AFA90CCF712 B1805DA88AE375A04D99598EADFC625BDC1F9C315B6CF28C9BD427F32C745C99 AEBE70DAAED49EA45AF94F081934AA47894A370D698ABABDA4215500B190AF26 7FCFB7DDA2BC68605A4EF61ECCA3D61C684B47FFB5887A3BEDE0B4D30E8EBABF 20980C23312618EB0EAF289B2924FF4A334B85D98FD68545FDADB47F991E7390 B10EE86A46A5AF8866C010225024D5E5862D49DEB5D8ECCB95D94283C50A363D 68A49071445610F03CE3600945118A6BC0B3AA4593104E727261C68C4A47F809 D77E4CF27B3681F6B6F3AC498E45361BF9E01FAF5527F5E3CC790D3084674B3E 26296F3E03321B5C555D2458578A89E72D3166A3C5D740B3ABB127CF420C316D F957873DA04CF0DB25A73574A4DE2E4F2D5D4E8E0B430654CF7F341A1BDB3E26 77C194764EAD58C585F49EF10843FE020F9FDFD9008D660DE50B9BD7A2A87299 BC319E66D781101BB956E30643A19B93C8967E1AE4719F300BFE5866F0D6DA5E C55E171A24D3B707EFA325D47F473764E99BC8B1108D815CF2ACADFA6C4663E8 30855D673CE98AB78F5F829F7FA226AB57F07B3E7D4E7CE30ED3B7EB0D3035C5 148DA8D9FA34483414FDA8E3DC9E6C479E3EEE9A11A0547FC9085FA4631AD19C E936E0598E3197207FA7BB6E55CFD5EF72AEC12D9A9675241C7A71316B2E148D E2A1732B3627109EA446CB320EBBE2E78281CDF0890E2E72B6711335857F1E23 337C75E729701E93D5BEC0630CDC7F4E957233EC09F917E5CA703C7E93841598 0E73843FC6619DE017C8473A6D1B2BE5142DEBA285B98FA1CC5E64D2ADB981E6 472971848451A245DDF6AA3B8225E9AC8E4630B0FF32D679EC27ACAD85C6394E A6F71023B660EE883D8B676837E9EBA4E42BA8F365433A900F1DC3A9F0E88A26 30F7B5CE2041568C18D8F66D36C31B003C916EC14620F67D695D846F2EF97CB8 0D569CB47D8939FE3C0009749B48D0D9856FA050F2D1BEBE2DD68DDBFEAFC2ED 7A7BA881DF4859A0F43EF10EF5DC41B5E82C630F2E3E435E37DCD10B63D3C96A 38C0C5AAE886D864E24FDD862D6957C084CC4A39623629F00DA0F035DACFEF70 4D8DF7C197095975D874B919691A7E03C56534645AB63E6B829038B435E1D2AC 2ACA8A5E4C2DBD300F7C786A9C196539C8BE8A6FFCC109193E97455DBB0B9E55 941992A110EA4BC1B01B59EA538E6AE0749C24D452C351F13B1F64EF2D199563 F88F92BB8C6C8EF4ADC5ECDA3C2BD22CCF84431E43BC5A630332184CE06454E5 0F3A369D5B7B134E0CF54E4804F28162048BA9B8A03FD837E2C37D146EB0F14E 7DD93363EA5C819AC95F2C1501909E9F4B3A09CCF2C609F0A6EE86D340A19408 6F985E999EAE40D936E3B0BF5D646941E5CE26E1AFAE1EF59329EA2E24EDBE17 8B9F15CEC308AB6169A683CB3D56DE572DA21974D80181D7BCC09E8E08FFE441 0F93897DC162D782209CC451E553232680F997451B1CB2D8AA0CBF5DBB7EF923 1C7AA87DDE43C47B188B502C42FD3F47D73811469BC954267ADDAA9CD18D49D3 2FB55FC5555338B4522F0A7309E487DBAE445E3FB3489EF7E396835B3FED2044 5CCCAC17D69B0A1434958B658891E8AB16A992B77357BD4BD58A9251F50AB71C B930D4652578C79C77D9083C420C895C83660D7FE13611BC7ABE5014C7CB5E37 62E71B7D3E215A8A7E51F9E4F3AAAB983FF93E49CBC1EFBBB2FD7150FA3E4745 5F8FC1DFD4A245586A56DE187584046746119E1F5770D83B0785427BDA36111A 881107BD4CDA253D2972687F010989B6FA7EED5836B377EA92906BFF453EA308 B4BF3287D966E98262724C896177F042966FA9666CD0C628C648AD6D8CBD23B6 6124005200490FB59E771E158055E93489A2D4D2447AF36988086AD21E8737E7 37B21FF521B78B92B5DAB8685B1249B8E82915B06DE48E1979EAEB8E02952345 53EA9181FD43C6F136FEE9286525F50ACC9236F602B542A36B51D511CE03EA9D 7F4E668FE9B7BB18A828DDD511C9AD2AF80B1D2F3D895D262C5FB883B36A4407 671EDDD228337CCE4DEEB68FFF6D46D9C87F577F60445962A97BD61549A5F2B4 F70E95DCCE8DA63DFB836F5A7901110B51B950872C8AFEC0495F51691B13DB31 B84E89B8C7E6D0132A26A348C2804887685803DB72B8C3223AB655830BCBAC24 2A3E989E13C38FD950B03977C2DE7BC27392A24DB30AD71D26E0969AE9D637C4 4247FF262AA189818067A8D3FE7F042E4DC47CF6D21504A9F06E440F79851826 ACDC43F89F482C220786BD85AF276D394B8D523C7675F57BE80E28F29A81EA0C 9875EE70C69D47EAF98963FC3DD370FC270A606BBD9FC16DC1B93B1179D810AC F634883A2661B3B2DD26E0C24A6D8B3AD223FDC7251296A614D88F8860EE5031 7E5CFCC7233D3397830A27DE6E5306EB074FA6698087E86A8E1F144F43FD3937 0006B492CB5455EBEF58A9AA34FE66F5FF36B04A7CFAFE68F490854E2ED08EC3 1E5DA648A76CF178AFC6C05813E88E1C84D9AF826DC9583A04EFEEBFCC351B65 1C79FF12BD7D2879D8F4521E448757B3B2B9E7265FCD9D57D24A633E04676DAB AC9B44A4406714856791692D23208139BC39147D57E4B1A9CC0CAFDBE4F2F6F8 87315413CC58B8ADA31B15A17226AE0AC8F047F7C7D9550D820B23994438FACB CC4C65A302F033D1ABF788848EE63E6DF1590B586DF40050A800AB7E535963A9 18CD7F6DA52414A4EBBEBC24B83F824C0B85C3BD21401722E16307553617B597 0DBDEFE85B9086F522FDA0C43FB27C14CB9621C75D8254B05E24C87D754B347C C9BEA9F2BCA71B37E3F6A67B0879BD67E8509B5786DBB025AE6159A7CE5143C8 0903EB0D6E6E40C36474093076EA17C554021D4C95A9B1AB6FDC30F5BAB2DC99 CF5699757E036207867F75F7FF2266A806E6581724493EF360694831C58925BB E271C8202068A9B9EECEFF854DB4D744102A902B913A1770A2A628B9B85048AF 697CB3CBEEF4F8064DC93E093A6D9637179265FD5ACDD5E3A9C406E8BE70F30D EDAF394FCB91BDA810D1C5E4B472F60E900DFEB45AAF82983A714E860548B737 BBE318EEBEE76B2063CEF47D7FA895A0237BA314DBF4E3A589B0DA21BD79F475 52E5F674985E38B21D07175B9CADCD3B5FF64E5A4ABC1D21D9E50B6C33A1828A 05E23D11398E7B56C1F8C5636575AB08CAD336F2DC2F9418BB0FBCC0166C5D85 FC062E82DC0E55C41C6C682ED75A78195C6FB552B19637B53467429726264132 943CA57A8C30D1E31A67387B679827443A52C4557DB9DD719D9FEC539CA09D07 47495060C8BFF195E7770D0B2F4DA353D7E755C853A7B9E9DDE5AED20A7DBECE 8569A8D9E5AF4D15388D65A10D055DE7EBC2E295073A86D082C2FFB2CCA7206A 7577BFD6E506D29F19452C3B2AF45D5531C0E1419B434F30ED32657A9DEE4C73 604C3E5F239137F49958F5CA638964DB763BBDE618818BD4EB23E57F1B250D11 B185093107056D2D4B6D53AD2BA245E121E3E206770CC01D0E07DDB5D00CF858 48F23AD1CCC23C42DD9F25AEDF3029ECFD31821A734F83B7C9F94AF3E6EBDEB5 686B484475F0AA7350856F9BFAFA0EEB9BFFA02E5CD0D8FDD562909539F89BA4 505A45D79CD2E7587EFC5E579EDFAD3661ABA956C7AABC46DED840EE00370EEF 87C3C48F109BF3FE0CCDD17E2B9974F817A08A8BEC4CDDEBC43F32F685F33D20 F3106584C83714D82D494C4721400FB88D7E5FACB331DFAA524553B401184571 E7F2C4F954D586D03F4685CA6ADC774B8E24FFCEF33094842A5F226E7D681B27 330F84BE13747EACEC6CA5D94F7A2C2E9C47EDD05B163A1A25FF78361F3FEB44 20D6BD2DE10AD0F093365AF1C00CC88D15443A21EEAC4EAF1F50D5ACA6ADCD81 D39D91A142999F33FCE4DC572BE9FBEA9F0BFA142976F2BCA7A6897135AC6E7E D0435DABB724E2193489F87A87D54384B3CBA6395E7DE36AF07DB326C77AC61B C9CD52C77A5A82A27C19D32D18B6FC17C1E6D38044A9DB4BCEFD8E05C1B5042B 4697173EA5ADCE6780871152B742AA7CEE0220663CC5C3AC3292C660FFF93286 1E50DB297296156955D18DA85931CCC9AB9E0BE2157ADC1343066050C7B735FE 130364B736F6521BC4560D44437C0D45427C207AB54F70E2FB9A0C2EA2436191 0F87B91BD3596F690335206069FA66A6BB08DE89C799966DA5C9857AC2F1339E E6EFF63FCAF48D50CC130AA95B9B1EDE2DE8E19A98E9A8C93E2EBF60889081E2 5C5D4C9AB8F800A784F1174595874A39239E74F3F5F8816E024F631CAF136E99 39FF5D4F7FB5A4CDE1B57DA67AEABD4A41FFFA0AA4B210351EC5EEC22B857397 9CC04CDAEA7D7FF4BB3C3D771AF80E630D7AB58097BDD1A037E40194452DDCD7 376AE54B39206F76767460B9AD86530743BC63884C46F4577ADC62F19D38232F 1D80EC752DA6B4C8455A26574DF01D2D9686B7E75F19BE1A5A8758AB7B827ACF 0F8D395E6C18A6D591E01863DDB7BB7179FAB3F2C82D24F46151CFB8AE22F53F 4177189C80B26FA893E006321BBC6D9AC9817A1FBE4918F8A1B8658C35AC32D5 335531F4F907143CF7F190991DB7E243F4CE9199E6E46F26F16E00325C395670 330829D5AEDEA76337D4A9AD1C3A30AA28E56B40019C0836B4FC6BC22097FE3E 86175F36C3A5A879B9C700C50FFFFB6B7BE1361211E1D3F3BEB39A2267875463 CDD79C44BEE54CC30F78BD48BC1D2B3C96C6D2D1D2A8484703C4727657E6C544 C27C4ECFCB7090EC465D3E0C34BED015A0B017EA94FE7903C021580B83AA25A8 307E13BE4FE137FD505749F447C2FF77F3039DDDFC476D9553BE3D3884E81C4C 03123E78FFAE5151D3CBB0473CDB4F083AA5FB0B1BA99A3AD5F49AA87B73282B 5084873CA47BAA9D1E0385C9D4EA3498AACECDF6A6A0EC09EE0520C9FDE792C3 07FABCBCEC2B7474A6241099D6362C9436F32FBAF1D6CC11D933D4A64E0CB9E2 0943E082F4335F23E7E2C719ABFB70D7C9F48C6B88E980CA8A980958A308E898 BCC7C4E085167F33BC36349C0CC23B004C805DF196581DB0C551C2B53C82E948 EFFC164541AD80E6014A723760ED548F3FB0C47F4459D855211824B04D28D3DC 18E204F3A43C5F8D489920CAEBE3FB9800061827656FEC3C43BAA4219978FBFF 85507FF60CD5020365D73914861254547B36171070053498052CA13E1CCE5C70 B9ED44737D747DC28DA6FBB7791082C572BF8362C3D3E34FFB285AAFFBC1311B ADF12AF9444E47D85B0169E851C2C35D8D089A5ACF6A2E9C94085ACDE361FAD2 B54B901EF8ADD09B1835B37CC6A5509872AE193541685EEA1EEA3770A1FD6318 DD7328E8CC51F099858659BFAA708541AB9E21CF1632458164B5E8659F6C23C6 88C0FFE47B820388404D0E9FE6CB06195BF2B2444582D4B7B38F45E18B604639 A0750219065C18492E2CDEF4BF96E2222A5D11DA68C6765565F9DBDED8F95F3E 7F2EB79DCE1C679D0743C5BDB832AD24C9B747AC4FA27D1279419E732DEEB543 BEE45F538A500AE50151C16C81346B88AC63D707E50958536C3CAE834A27E77B AD95CEBDCE16FAB65DF308A0D34EF798078BF8FB0D03DFC782449C0BEDBC4AD2 5FDDF493FBDA5CA3641F4392487887D324A047904B1E033027143232A40D5014 DE1EB3E58C535A317733EA1D93C33A252CF750A9EEAEDF6313B9CE44373A288C EA8DF423F248E3DAE7DC96A211659305C9B97946AFDB3ACFA2B79F05CCD03E05 2E372943C4F676BB72472D3EA1B0F566757FC5CFFF8F81F128995EEF12CBA8C3 5C0450BFF4B9C68E93C1638A70509FB6BD34ABFD2C0B7C0A238E98FD8FBEACC1 2539AA00D2B64D7C19AA45C3F1B17B9050546D751B2B346E19DE3359F02F5F1A 893148BA91ED8BD68A0BD5657F0001DB75E71F2A0160A7DDC39C773EBFB10458 A1BA0DA0CF4976AA41063B2FBE875FF0DA96FBAFD6AF0DF9652AA0EEBC1AA768 087B8CDD4883A044694186BBA78043EF79007FFCBCCA9606B0C132BBCF835ED5 2A7F459264147B460E5C9A487911146939166679E6A193A4AC979653DD2B8522 F6EB14CDED27F108C47D32E25D40FCCDA830D38B4AAEC9C6CDB212A1D8012AD8 17BDFEEDEA83194DB3369B8E0FF2BC5BF2FB83EDD20248820FEFB41278A7DC96 D47B40E6EE3F85FF38642B9C52CFA1F85FEF0DE3637BEBB66C1BDB2A8ACACB97 9CDABA4F994E1656812B0321D999339A2384E07D19388ACB8FB4A86FC98A2E73 3809461D8681C619766696A02A9099445CF756A6BD1ED778A4909D36839F7E91 153C0BC25297495E3EC490B189AA7C7B64480362764F6B89753B0EFEF35C86F4 65122B04CB43675EBE03A3026F4212D521AD81FC3E2D3575B1C6BBDF35E54199 0FAA02480892DAE8DEB52A4E1C8E5995A67D2B3652CAFC5FB0BB108A40019896 664ED1974AD21CABA4279BCC7D2E3DBFE7A70087CCBEA75FC65218C5ADF0D174 436BB02AAD79BF172589C03D0C1D4DECCD14F98AE90A86B4A7BEEC0F1CDF724E 0912CCC14AEDB5EC8E297CE357ECFAA0CE69B16F93EF2B214AA9BE98DED441D8 8DF022DD63C0AB8143A082073AE8FDD50DC7DD5BFF35F9BECE79C5188BF11056 D8D61F9D5FB03CAEFB421682269D8F6DC6637F277E0C97D7639553644B59FA30 DB3DF2B7B6633BA02AF683654FC048412F29BBA8872987BBF26FE15E4AAFD133 E2A61425C364F7A22C201039D5D765C1B14A06C1FB3C2BDC517FD2D0CD1280DE 6973B6365CB32BA2D5B60E1CA37398A37B7951E74D201140CC5DAE4FC0D66418 751EDA5A7D77D6CC9B4ED206B36A8CD4061E848500B284F1EFC5BC73CA717354 5F1C96C3B176937070F8DEDAC70ACA1504A0557C7BCE23A8FCD4E179AE4C3375 2A3099C9FAB588A0A47FA213030117F9455907169F00302E592A6B2D97CDF3F0 E0441B0DB0FF1324F99FCF21119336CB7570B488B31A0F8FD3DB110733DDDAC0 C9C994BD2AA5D5F4B3ED418205D8803C3EB6C591F7A5C34E00388A9E88DD8727 C76F347D5B35F5D59EAAA48B62D575ED3CE9F3F61170A376AAEB825ECA1A20A7 82C69F6BB354CA870717815F083067B7662A8950B85F64F693D58E17F1E35A39 44E491D46C73775BA837DE6498334594C554C7FDFECC828E3728057E3AD3FFC0 A1E63E94532B09CB28F5E50919A00A5AC50B0C6856A3697847314D8B9B8CCB52 76E4A1FD2A075CB2E9B9929D1EC55F5EF9518437738BEC7B300C19038AD2DD8C 6AC399A0D71867B943B1B197E884B9DA58D5C175E1AE398EBC0B5AEBCF2AB1FD A960D13F12E423B2DC17C8DA6DDD431219A0427EC28E1E4D708B4DB0C90B8A87 738A2E4C6B8C49BE14091797A5CCE7A081485EBB8B2C629842DCBE25F5EAD1A0 D546F57455B532A9DE145CDE4841B08B2DA52906FF16F53180FE42B2C53066DC 0926AE1BAEF441FEEFA91F722FE6CF5E0B2A0875F71DD42095DFEB5851C82792 C5574EA07DDBD8D702B6AC0C82311A0490D5B57463389672933EC83FE646DAE6 AE8BEBD6B5CBA53FA936F88A4E4F556CBC56B47B8393457C9D5E9FD8BBF800E9 87CBC0C77CDDD9EE7768EA4A23E2B92ADB37BE882CD842D55EF629F6AB8E9C80 13BB6E37014B2DA56FC65071B345789BA7D3C193D3579C6FD98DF997D8F1903E D53670E6030D2ABA91DB82DA54B97D0D8D3C56E08A3C21DFC15FCC12DAF6CECF 6D085C337F6CDCD044EB3E7F1D4C29344DE105C7CBA03E211E3244C2365A4ABA 88D9E17389FE2161A6D9A2BFB14554B0071614A301741D6F604EC3788236D782 152E3F41F8ACF4B04156EBA71CA125126C31FEDF066A474CCB8A76083B67EFA5 9C34E8BC213AA01B1862D866CA2C7F9CA3444464EAF496186CBAF607A0E7A60E 4D8959DE9DD6B42E3995F0D92A7AEF7C6E5C3BD7DB1DBCB1E6EA19B10709F709 40DC949106E454D9225606EEC9231D1694F71E350B8A8895016AAE4B44367EDA F9E9FE18A201A08368AC00409F5FAFCE72DF38D27462875F0586E8631ECC090F CE3DDB814193A5C154DDBCC1CCAAC3658BC4BE562DD1A5C3098BB32EA36D01E0 345A00F76E722736BE3762177A1EBC5390457316FC105A26440011C3A3505DAD DF4586C826B71A7E08291F1864BB50A422DCB42C15CC6EA2B93C5C8312EF4EAC 025AE0A87C6E8C824D6E0564037A3F2DF3507923D31501B9B8FDEE3A06761DA8 25D1F3E7E4BFB11DC9C1981C0B1E878DEECDA57A367FCDE89B88707A07F1017C CA88CB190F02CFD3541F27DE81A644E5B4318543740DF9D69CFA10EBAE0C487E 577ABD2155ADBAE841DA9C2FD0CB6D3FB4C8A109B7862A04B9976FE920B94318 21B7D6DF66D1812E0D07257A5E354946D59E9F162FA611B1CDC737E2B60D52B3 C82ADEAAC401B6C2D6DB473992B9E45B08A20744D53FC385E3F6D30C997F3FBB 7847C5B1ABB7AE53FD6616D7F23393E0AD34490AAFF9027168B5492145F5071F DE0E6DD8E31277B3D3588B36372E4EA4F0107CC391DD3D0D5FE8970AD5FC5789 17DCE9CA706164456BB7A18A68638403621251B60213B46971CE3434C70487E0 6CA529999AEF89CCEA57A711290764C6E168E75EB756E0337081EDD6CC70FFB2 9632D22FB3A400774642B85F576F1B73CA52E7F5A23591229C0B0AE6408059E1 0427DA5122C7BAAFABE4ACAEDF7F5BDC3FE21909E7B474A52EEF3D98BF267FF2 B3803AEE0D1392F5418E84759FCE4310048C9124824A5976B09B56F8BED6EC68 D640A56126260FB5BD6D5AC13BFD5D0B0AEF252CD5FC1FA48A926F55885C6382 99B48123231F416C19CC5FF196D13371DD5D33CDB23ECE5256EE5760471EDCE4 26AF7FA95D468F2609FD64C6DE142E4961EC3156ACE3DC207C04CB4019CDB4AC CE6013FD84D5B6887390A6C46F0F1A43FC0B1BA6AA6B5B44F23C9C360A20A1EF E94366DA2A92098D60AEBDACB8D7B4736E4E17C4818DBD5398D8384CBE7CC1D4 A28B28BA328202F087E841206B35D89E26C2FDEA77DA957A5759CDEA30AAEE94 F6F5FFC1B3820C5E907CD6587295DDE110226E4DB1E46BA8DAA93EA2D135B635 23F6B1A98F3F165C0EA13B809CCE4D64B942137BD1D3F98EC2AD678F26CAB779 D9F8291DD64A677011B4B9604B8E4AC1F22B96A98760DB2FF1F47EEFB880814F 1200A077279EDF1BE39867C45DEC3596E4ACBDB1E200C27126AEC4366CB1A354 F4660DF153B940679229990358B4942D6DFC7625273857445C967C24FC51C804 3EDA0EDE8841235AF5F78B50368F80B3497E39F3EB0094F139D42BAA0831D6A4 200538253A922BD5CD0FA548C2241F1442C1E35636014F7CE5C1D2294AEB4502 F5248606EDEF0F33F998D05D95196AAF94039803898A673AFBB9873A1CC11045 A01D174F8CCB0482F6EEF5D5879C16A4D7B573D84FD0CD5960672E6515CA1BC1 BA40AF1D76501C06548399DA7D2662A61D03BC3BD75D012B30621D0C6A052213 B3390976661462DA6E60DB0CEB9CA555AD3785E99AB8AEED42E70305BF90ABFC C56C390EFA417FBE2FB82E9AEA03B36811B408CD5F90D706EF81DE9A75ED5B15 6D726DCB2AFCE0E855DE25D23DF8E5D4EAA5364EBFF47C12481747F97B4826EA 2D639E00F037551E7A5EA6421BE789D54E1D5D30370196A35E65DF159E2C7FB3 8057ACF28035C9EFFD9907D566937228062B07CAE8E2B199512529B71EA8AC90 600AA84AEE684DD0EEB00CCE2355D089F6DFA6C0F18D138A7907615496D8A998 5974A956A524FD8EE5E6A82798C7FA1B71FB68271A0C0FB71CA17036064CA597 19F882FEE87C727ADF36872A0C05BA8D9FE0424CFFB637B1E85AA99B9572BEC8 031F44D8E24FCAD7833E27372F06233E805B8FA976FF30CBE858F5FE88FC54EA CD09B4F56E6A0A48049D84C1A124028072A0C6A1AD032F0D8194F5191F53DB6B 07B65F9EF3A59248C055EC60A2CF7CBEE5CFAD31E6C0B26937E7AD0991A1F0E1 EAE9EF6F0D70E6C8649C460161EF09754C7246658454E44337119681342D7CCC 6438CBDA49130D072E2F49F1ED66B3A3BE6FDC93E573DF56748FD2F12E031DCF 2B0AD2F85D92AA9F31CA398D81572A05198E18DFDA86B817CB5F244AAB2A0039 6FE7ABFD61675119D606D8432B84010B80ACFBD917782C45787C3F6E20616FA0 301164B4386BC5A0D43732238A26553222C130A5981415B8DFF4467AF95C9605 CF63D0DFAF6D7E2D05DB0FD260E5C28838B3D8AD910DFE029F3B1BF9D43C38F4 5A6E3FE7DF3C1467C1D5C902EF9123C05F46EAAA8F17C380DF04B3F164C2180D EA4EDE36FCF64AE318D8D13D0B307F668E3160A052639174F266116D4C6005C1 4588F003B07A68BEEA3B5719F331A58BC4DFAF393B487599A0307A37235D83AE DFC96552E2238FD4D4F1AC215A8ABD6F928C96EA7E1437230F12E7D6B0EC4B62 40494113CFC38EF265418F4495020007B8F997875368D2F7EF8446CB30D370EE DE8F36D195727C4A381F48F29B42AB70CC5211272822827868E958351B6E98F5 26576770A833A726586A6FA59A42D2780FFE5AC3DE9358953261B31DE9FE468F CC8DB501C0F41B8A218076D77579B4C437C564534EE5646151ECC37C58E1B32A 6BD702518C4A0BAD79B5CF825CAE60104D0838A4F15FB9E005507BAABABDDC2D F0E67F620F9920A83890DDF699308ED3BE657C51214DBDA6412EAB1906DAD9AD 0422DC9DE4648D9E106990EC08FCB54A09A931A7A91121C7E5AC976D56907E84 30B361DC13E62AA8CE37D255BA04EF9A2FC2D47484516B15C48BAF399DC489BA 68D0B7E973734FF9B17EF07AF4D5C93143EBE3E439717816F998A2AF4F7C684D 3CC1F9181C458A1D947F8A34C266882E62358F106EE81E02007C08C1A4F278A9 8AD244A30F74B17408244FB69ECD2238705F5C2927C51C8698AC10B593C4A651 04D5B601AB872D51288B5397165992E4CCB67B43F19E572472B6F804B309BA9A 1891C775EBC866CAE897FCBAA0DDB72469C51775E6C68EAEB4A0E0046F22013B 2E01213E604F9DE2DCE26273351A572C6408C264387CCEF8BE1CDE9DFA4E7F37 55B7BD1ACAFE9422AFC886D6A27C8F9BECFDD6612C29DDD4F45DE8C9C0582C8A 0406CA4253ABFD29307E143CD843C666B567AEFFB5D9B0FAD58AC3F7D1545075 8BFB2881035407A347E2CA572B4DF2266610A05B6FA34B59A54E0AD74A143F66 64B35A58DFE2A5351683243FBEE5CC314995BCD1F918F581304CBD363EF21C91 193428EB1CF98430D8BEB8D11E55E7A577B23BFA8609DA01593A6E53DB8756E6 8C3645521BA08AF58442946E70A655DF2D7A9C1CC40060F7D413D73B751D48E0 6D583969C3EA48526FC009311209D1600D9BEFCDC2F1A3F783D2A01B92F9F3DA 1BA6847BCE41847E6A991F54FEDE9D76DDF63E7D8312FDC6B308A6F5A1375EA2 2280F3C1480E3CB9C38CFC536FFFA3A357AAE845B00EF45230EA00CEC2FF06B3 670A87AC8CF3624898E4E240130AC15B8C573DCFB0B92E07D33B36CB5FFE70E1 9E14DE5562F968CDEBEA75721B8B087C698F009454DFCA91DD29C261D60871DC FF6142EB798849E9166F3D61E021CC30D4B5DF371400A697BDCB9A78ED973DB7 8D8EB2DD13995F13C8653BC197F7D37F80F81C441DBF046E9CFA444CC1E189F5 494BD128B24BFFC8F517A12CDC18846958B8C69D41FFCFBD2F5A09AD965EE8B1 9E542E5AC2F5ADAB6A2C6EF31485D656CFD0B50720C5F3DFA642BCC1667BC298 A76FAF7DB441D6877A8B53A450ABDD299B9315EBAD0DD48A933867DC86811DDE 0B5EED686655AB00EF4A6DF7B0EE644D578C6DEF011D47AFB8E8C9B8715BEA1A 20EFAC19F11808A6CF93074686496830676CDE3EF843A2D3EF68CB004C3CB472 99E4DA5F2733B314FF90701AEA65130D1A18FADC67424526368158AE2D82079A 7E8078D9CE0C77AB16E582C16D0E5ACD1E12CF70A4A20689E33F9045781111AC EDE1E3C25313D7DF52DBCC09303A0B2704C05CBB8F8C7226822F391C802BF293 106D58D1C37D35CF48F3518B25EDD50CFF51055D22778A7FC5FD0C62E9EF6B4A C43B814B5E0A12A49AAF20BE95F6FE037277FC4860A60714BC367D28C9B237FC 87E58A07AB03E869B9FA79989733DC3E929BF36ED0B71DD9A9D2614299426E5F 4EE3F63BF07C3186FE7FCF2E8041C0F685D01D7BC5CF84661899EA0AE20CB1A9 3E37F28A6366D87B43FA2B9D256528A3E3442FC1F4AC3EDF8F074F8DDA4DA417 4F7D9F14ECE3D16771406CBE27E7379B4DA0C2BEFB217BF112735F94E3A543FF F21CF6BE56DA34313D637F19FFDE7E1C9E84A4F24541307575D6C1B13A9BA39A 619A67E81A1B09B02D1BEA936EA12FC8F11247235211060F9F076DD604D307AB 3DA4D7A02A2E8443EB55EE6205DA626E163C51945990C2CE68D8DB41F361A2A4 1125C5C3CB75E039253C68EABD01F42012DEC2098B98EA479B510BE89967B61A 4AB9A5488A0FE103DA30872FF137B1D18DE85E083BF6D923D69A25FB315D432D FA0F0A283231B5FD23FCF4EFE5EAF45EAEE63FD98132D68779943FA2D1A45576 1118A3210CA455BE0CE81CD9BFF04B3D9B2DDFDC5A239757FBAB6A4FEE94ADEB F0466FE94E22680A09CC0A81D4CFCD3B9BBC91E4ED0A4AB0BAE58EAB103A6074 D0DA9D52DCE4931DDDD9451C1CB5B1669E518795C430C0AEFA33CB169692BBAA 4024E40CB5911215B4717530D9B2B937E8F86AB146A6C58B89F53403704ABA91 C860CE9916AB4CD468D10EE5ACDCCC8E75C8AFF0AEEEFDCA43682480BAD0DD2D B7D3DFAA55C59CDF224977840A8A7881FC89332DA667CA62C3804116E4E541C1 1F7889D1CF79277EA29712531AB02D539B1FE27206F688765EB81716C41A3799 FF72F5DAA298AB30152954822C77F3B66FC54A51D6BC7AB6AEFF7CD93FA94ED5 66F0124F219ECEA72E6AEB15D5DD7EAA366128A54E43350B006CF47642900E0B B4577DD12358BDF9C8E4C2C93444B9A29D442FEC36E40BF684D64594951EF807 D587786C2E636CBCC165B63D8DDE01A0EEA0FBE2DCA45C4EAA1A1CB164B05A3D 4B594249D0A0BF0CB2AEA95A71A483A179E77A11A49B73CA88C81F763950C6CB C4702FF7F4A58665C23D73F00F55C48527464B453150CA6E5B99D1BA08D3DDFB B5B304DE4E6CABFF791CF2FB9912908029A383E8EE39F7EA2CCEFE949B536D90 BC0D4D791582743075C21E37625DCD219364A71FB21476A2E559A9711F662F48 AEEEE7E73B1DDF6BBA199A66C60CC2166FF9B4C4309D096C0B13C011D3ED30B9 374210DC96CB26FB201EA9CDDF94DD9FAFF39732B4B6A71E86611FBDC8742D4A C7E661E18DDE503C94DE0E6DADBB1AD6C7771D1AF783D504F2513FFB87C4B3B3 90AFE5B8A8969CEDD65B59085A2C2D11E826D1AE484253E4B31EEE0C6583DFE4 D482EAF253505DF691DE72EC54913AB5EAD1F051204DAFC9C6720157B67D883E 0D04B4D7412F0F854EC44CC4D83F8EA2A7DBE940F580DF77FC0B7F1687EA5FF6 DC8AC26C07052E011A10738CC7FA1104FCC60AF85B66D2294484B391267CCACD 9F50661526250FAF134A8C487B1BE57F01D08E06AB5E1689CA9ECC8B6062B568 0E43EDCB4C74EAADDFC3BB1D309C2BF166BA3E2E3F276E99A288D291630EA951 E63D256587E54FC0E731E43AEEBF68ED71BD85D95C957FE1C2D78EB5CE3A2FC3 B31F528FEE1B2B9EABF43AB591749CDEDDE9D83C2238E5541061E88C5B3E56D6 3B5E1EDABC2C238682705B8BD673B383284AA5E8B4AFE1B05913D1BBE8ECE2AF E5B96CB431D77065D35AF5EA0FF1B84B47655A45286E4D6EEA94D0C7C1BA6BD7 9DD1943B5CA1D503CB10FC3F51FFC53E556893D280B1384F81599249F32BE524 9439734EA7DAD4A6C7C0CE41FBA832EC6D4B3E54EDF0AF02AC694949F425BE49 DAB43F2930D321A349023FBD4CFA05D9C8E1399E48F9EE7E3C61EF5833E89159 423F3A8155FE9441C9172E51C9552ADEEF047312BADE124C8BD0A0FD2A2E0DD1 A6F3D338598A3836AD46BEC0966499F558053D5DF15585DECA93339718037518 DD8DB8E9D7303BFFDE3AE50902CD27A97388460424CB79BB1348D2C0E6DD71DC 0147D980E94B4DD28F3BFFBFC356EDE6220076D2E0F9286D7E6E0ADFB03FD673 9095CB3696F5AB10F9CD2036CE9B88F51A3DE177DD9C6A82AD0D45DD6EA8B8AB D8B7D1D5AB032EE378E5FB62E5C967F170590B0A9AD94E038C621902C674F43E FC637BAD1B9EAC2206A29F6C7FD4448442BE438F688584192FDB60BB7524DEDF 0541CA37DC5E70A1776D62D5261425E17671E98C45070852192211D947627E8D 26195090547FAAC5D8763FA76353934B64DED4B01BB73A72131F60036CD7B86B 15B593959F997F7CB38189F00FD5BF1E90E7F419D163A57CEC5AF1ED84115741 3C176C863F8D53C6AB667E141B13B4D07C822D461840C8F7F8D2C46EF4D10F12 359C7C9EE4B4D7802C857544E4CCDEE30947593A474A87C81902983062345748 370F307C3D91785239E17215291863C565D2F737E4B1C2E44E85E098EACEAB72 0E31F40655E97175DF31035E66C73DD753561EB2F91FBAD13A4E1035775A4AA8 6E2994505069A011CB338779D4C3859CCB24EB8F787435C959AB36D83F04EEA6 50308A38CD3688C04A146DD15D2FE97716304CB6FECE9B748F9A5053DE280366 A94C14C0D642D169AB4185673C97C2F1D864E72C18A44D8D7D5498D3BD1F17D9 94A56AA314BB0BE57ACFEB16AE42FAA2DCD563CD67A9890B9AC072818838DB0A F4A099C2DD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMTT10 %!PS-AdobeFont-1.1: CMTT10 1.00B %%CreationDate: 1992 Apr 26 10:42:42 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.00B) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMTT10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle 0 def /isFixedPitch true def end readonly def /FontName /CMTT10 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 33 /exclam put dup 34 /quotedbl put dup 35 /numbersign put dup 36 /dollar put dup 37 /percent put dup 38 /ampersand put dup 39 /quoteright put dup 40 /parenleft put dup 41 /parenright put dup 42 /asterisk put dup 43 /plus put dup 44 /comma put dup 45 /hyphen put dup 46 /period put dup 47 /slash put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 55 /seven put dup 56 /eight put dup 57 /nine put dup 58 /colon put dup 59 /semicolon put dup 60 /less put dup 61 /equal put dup 62 /greater put dup 63 /question put dup 64 /at put dup 65 /A put dup 66 /B put dup 67 /C put dup 68 /D put dup 69 /E put dup 70 /F put dup 71 /G put dup 72 /H put dup 73 /I put dup 74 /J put dup 75 /K put dup 76 /L put dup 77 /M put dup 78 /N put dup 79 /O put dup 80 /P put dup 81 /Q put dup 82 /R put dup 83 /S put dup 84 /T put dup 85 /U put dup 86 /V put dup 87 /W put dup 88 /X put dup 89 /Y put dup 90 /Z put dup 91 /bracketleft put dup 92 /backslash put dup 93 /bracketright put dup 94 /asciicircum put dup 95 /underscore put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 102 /f put dup 103 /g put dup 104 /h put dup 105 /i put dup 106 /j put dup 107 /k put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 113 /q put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 118 /v put dup 119 /w put dup 120 /x put dup 121 /y put dup 122 /z put dup 123 /braceleft put dup 124 /bar put dup 125 /braceright put dup 126 /asciitilde put readonly def /FontBBox{-4 -235 731 800}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 2BDBF16FBC7512FAA308A093FE5F00F963068B8232429ED8B7CF6A3D879A2D19 38DD5C4467F9DD8C5D1A2000B3A6BF2F25629BAEC199AE8BD4BA6ED9BBF7DABF D0E153BAB1C17900D4FCE209622ACD19E7C74C2807D0397357ED07AB460D5204 EB3A45B7AC4D106B7303AD8348853032A745F417943F9B4FED652B835AA49727 A8B4117AFF1D4BCE831EB510B6851796D0BE6982B76620CB3CE0C22CACDD4593 F244C14EEC0E5A7C4AC42392F81C01BC4257FE12AF33F4BFEA9108FF11CF9714 4DD6EC70A2C4C1E4F328A1EB25E43525FB1E16C07E28CC359DF61F426B7D41EA 6A0C84DD63275395A503AAE908E1C82D389FD12A21E86999799E7F24A994472E A10EAE77096709BE0D11AAD24A30D96E15A51D720AFB3B10D2E0AC8DC1A1204B E8725E00D7E3A96F9978BC19377034D93D080C4391E579C34FF9FC2379CB119F 1E5BBEA91AE20F343C6420BE1E2BD0636B04FCCC0BEE0DC2D56D66F06DB22438 452822CBEAF03EE9EAA8398F276EC0D92A7FB978C17805DB2F4A7DFBA56FD6AF 8670EB364F01DE8FCAFBAF657D68C3A03112915736CEABAA8BA5C0AC25288369 5D49BD891FABEFE8699A0AE3ED85B48ACB22229E15623399C93DE7D935734ADA DA7A1462C111D44AD53EA35B57E5D0B5FC0B481820E43222DB8EFCD5D30E15F9 BA304FA879392EE0BCC0E1A61E74B3A1FC3A3D170218D7244580C7AA0DC65D19 741FA5FE6F8CBF60250ACC27454BBF0897CA4B909C83A56672958752ED4B5E79 E18660764F155E86F09EFA9F7685F2F5027EC85A775287B30E2069DE4E4D5712 E7D033481A53A2702BA7542C71062173039030CF28D8B9C63B5596A9B42B33E7 D922944A38713383D3648A4AF160A3B0C8F3379BA4372BE2E7EA49AABA75AEEE C5DDE1D8BF68483C3D21271280ABB91D54CC819680322EAB72E1250A760BC8DA 726405EFE420635B5B7F0B48752C06083E92BDE06401C42A2C528C8A60381227 CEBEF0C9440DC034DAD9C19FB27DB399BDAEE22053591D6538587C768C1B7B0B 7D1E222D2D8AF3A6473CC4C0D6C3E0DB49068CEB8C9BD1C5CD486A50DAA10BC7 7D6286142355E3F21DD254E27C00C442728A0BAEC9D3F17AE9CE320D365152E9 EB0D5E3874F2BCEDA98521D23FCFC30B4B69DAD2ADBE80E5964ED0ABEF6C73B6 DAD30E2C5061E3747FE536E1A5D190D028F2130AF608F5DDF9DDDF1E77DC8437 ECB3EC93B33505DF47884DDBD1DC6BBE4098DF04A29AF6FA3AE344600D0AAB53 B3820DD7ECB600A3B8001C51AF2CA7A39AE1485A087FD1752DF68F55B52B4DA7 48030F2AA7E570B3D56C4EAD367B9B73FBC0A7356253233006178B9A6BC19081 B815B5988AE76FE6FAFD7AC239072B1106A3F509381AAEE79B2F2154CAC4727B D199CDC8B4D05DF4BA006982512ABD7539E28D937B0F87FF79A3F84C29ECF943 A8DCB8BDF8EA9E7A0E7CD60BC2308C96B3E889C797D0FF28FF4847016B3DA141 E76FC6BE78A6EE9CE07E651FF86E720A1A1F075972D36E5C55162E3FE26BCE3A 814BFEB12D4C5FD24340CFFED499C7CA183E57EC4F12CFFBE3291D43F7270575 C6C3306F832EF182ADD0AA14C4D8669A17C09F632406AFA195F90C4DDC39779E EC0A77E590211592D6EE19563963225C06C2F13265EBB5A6CFB7C17D9E77650D 11958305727AF662AE73AD0E3ED5F7E7086C5A0C3548A8129575980B06C715AF DD55C8DF869BED0A7883491030B1A7E82C5EB04E5A7D952E716DD8F2EF6275EE 087614CFAB55FCE2BBECD7E8D9C90FD8359E929D5E0A416A23BD58158318B4FF 87B095EB63F7F052B3A77F136FD66EB2C52BD46CD7DB3091A4B78A607112B12C 4D171B2A00B78B0E1C44B0D90C20D9244281F5123DC1F6063F91E9E3E48DE78B C862D848BAD073A4FCB5EEC9FF54B5AB8E234CCC3C7439C62ABC4A13EF1B8897 ABBF21F900C564C9A305FC36FC7224932F766E6E72C2EBB55953DFE2AFC2E3FD 33A0C6F0FDFF086E9FD796E7242596AE85B877223532667625E371D2156E4C04 0D7FFCD3337B93DF066CB6FE1E13960719EB7CB409EE805C08ACD2C06303ED9C E34C898787A43C1B428B896551C6FEB50A831C6F8CE2073EFC662EC286CB7555 A3B42E58772E82FEE206948B8C439FEC5E4ECB9E11DC3A4CBC7611E30890E408 637A01A2118441B4F9467A98BB2A1B03BB2F5D8E3DB7D1D15C188D9E856088EC B762F07B1C06024F7EF53A2FBD60C0A1F4C0275D07164545250ECEEF8CB15B04 A2D8AC44DDE818C4E3CBD2A5FA0FE49750886CD7CFAAF8B780255F89DF7F4F5C BB594FE7C1597DA71813C2952AD3E811524459EB71D29696B450C924B6A5C843 8F36A0F1D7DFE796FB9564333666D74AE614D0D698FAFF20F83C86524C894BB0 272221C060544F3B653CB0E4E4F82B20D7530B3806E6A5830852C58070177815 E287C847F19F64E854F1463C23DDD80093D6FEB8BAA22C5F05C21F99FBA7193A EB7CD49CFDF4308C6C68CC955A45FCFB54FCADA9A3BFBDE086B057DE88BE335D 280F5338D7E66AD39FD08F9B55884F1F377FB6869FBABE3EAA4B7ACCD85BE672 724B4B8F236B0889B6E7049CBA558A89F17863E82DF145DB8C7ED1F36332DE23 3C0053B74E850FA14F9EC9EFC23AF18E153CC96FB0FFD910347370E57F0D81E9 4A83E2D189EE5635E85A2BEAB5B1CB974546BFB2FC2ABA1E15DC0EC1BB3AF1DB B2F93538B92F504CBD7AAFE36F5F3AD45EB16378F169B17869FE81464CB826CB 400D2F5441A496B6C60A4F15FD20ECCAC1F8F91015E7E1C1A10B7992A1554E52 9FBEE905A3005336E49CB04BA7223F1674C0BBDFA06ACA34F7BFDA56906E04A7 4DD79EC7E79B021A5008F3B1E04712D689366F520B0FA66A558F957011992728 561BF4B75C2BE07C4024C172085E51CCC5CFA439F570297154CDDBB3AA25CD6A 3004B936488851BA1E814260C06CD5479DCAB1A6AE21A5F4563024F973D738B4 0DDB6C6DD2E3AC21B4F6D95CF9AACA782919F5D3E613D61F3224A982AF485C8D EA0037410EB70AB7D3EC174C6D5DE5C9C5A1220EF7C2B74499ADCEEFF077D1D3 50C1124535F88C3C3F66477E42F1932665AD323E06B398D2805B9CEA632F5B1E 50FA587B102A35E2F15EC22DD66E4DF06A3F4BB717A3ED7FBBE2458EB4D896DD AF00D1BC71FE1CCA27890ECBF9F0AF01D3E65CAA29427FAF06B3BE1E640522E0 73B213D04491B93DB29113EF72211E31F4C5A7FD58451946CFC15FD805112FE2 547D1131A46710DFB75659A33695FFAF3CDD40AE5260AD6766DA81DAB0A6E96B E89D57AAEF32B5EDBBE9F7CC033BB2595CA3FEDA2ABAC8E5395EBC35BC112FE9 67EAF1F123228538091483050847F8FB5194203609502D3A09CDE811EADC18B9 F039593782C27EFA7697182D6367E88E326AD5622C5A457FE2644FEADA88615D 9DE3E483BFD9329667953CDB86F9D2F0D4F02DAB8A98FDEB1D17CAAED9B6E2E6 0C55C1FEE25AB98FF59FC235876029CE03E4A713B75B3163BE3B2DC0D4472DBC 473E10400C0F57E627AE97FD0C1CB0F78FD8E2FA831A3D2B1C2BB3F2D4E812A4 194C8732B0C525361DC8480CB27C30CD4DCFF01318D2EB4F5234B4A42EA8C23E 7B3EECA41B8E4F54D5458B37EF0FB2F49EB19F4EA8AD2B53820FA36E93DD309E 48847F5C01B1118ECE7D0186E6B8953344EB775D655AAAD7BCDA642EA2E39A15 855C027CBC0E3FA752900EEB464E2D39404D1B85072B40834748C6F9C74C5B6C 3CEDE988343FD984CFE4B856A481E60E2E65D3BB41BAF2FA80AC0BFE381071C4 573C6ED65C524FF777F34D82E9661E4A75E3878CC77BC59218244612219C5A92 E95B90EC2C38614665550026F1730D11162F19D841681C04C401E102C047541B 97B9264D86F47E25A347696AE5EF0FF3ECD9BA32C92901DEDD816F7D73ED1216 0A98771892472CD625A8F7F19DEFCF5CA2AE57F8AD3898F2C1005B187DEC6F2A A31C32720EBC934178E0E9979013B3C9AEDA4051DF63D8C903A399DC88F83DCB A73F1B2083819D1BBEA5235F8FE1D098F32A2BA6274424A99A4975FE4BFD59AD 79B40A8003CC0AA728EA79D6BDCBBD73DF45B7918BC099C5BE4A068BF64A30B1 C39442CED98AAE1BD495F6CA32D564A72E3BF753B49E4178927E4BBC0F06048F 96DE7C30AF580B0BFFDB330B3B87D7F6532A24F403680BD9F15E758CDF04EB94 E83C7E644FDE5BEE7CE73EFAC75669E41BDFB20A5B8ADE1137378DD8102A0DBE 19499A623770417CBF5211395A6BA9F4490F4707A46F1F9B3FBE642DEA0CA053 9ABC307B1E71DC2B069DDDBB4EAE378BCC75AD61DA900AF8BA6DF0E27A8D2258 DC80205305AB6ABFE3726703E60869BFAFF1874F3C0E05FAD9C05D7D89ECECA9 DD2AF5F777D7514208697E712B52448B364D3ECEFD8127043DDC9D0757B7CC37 5CDE8001D007A6E961EA24D7FFC92410F3B13A32946F12A50DFFA256249BC8D7 C1842FB84AD51B41008EC4604F6B70990510EE13E6DA34F864A572D99A13FFC7 3609EF2BB1FCDEDF37A6018248C545E086EAD1BA1143E74AC60B684E755E59E7 36557B915F92EF78FC177621D49F777A2AF39F3C2AA6EC74750AAAE08BCC21CA A71CCDC91DD45E6050D83ABA49ECE425B55EEE137C55619037F1C30530BD0A6E CD2004B6A040405064D7E87C55536680364E09248BFAA3FDF95CDA0708E55F4C F7D0A92A93DEE0C7B69638F171B28B7F854CCC6EBC6AEE14864BF5144EA36D46 A9C297225AB0325E28EF6BD06D7E40E3A724EA1E50C4C6163B195CFFD5DD291D D7BBE9AF4324A69394117EFD62F08D6BA6A8F0AC3E2353492999AF28FBA758C3 A50B6840CC72054355E6CBDBD86F683537A4115049BC1616BA35C2B0B6F5CC32 3F6831DE4E6029310738DE23D36D2C6E82F04EB675FB89789F74AFE3B8854250 51812FBEFBCF162947554324FADAB765C74B6DA89F60A734076D44BBE45263B1 3FEFEEA90EC7948F23F34D4049087AF6563692417DDBCDD5A9552A373C2528F8 0318D3C0669279F292127CBA40B0ABE08A1476BC9EBFA8BD5D622BC5CE7DBA20 C689BDAF50D5B1EAA89E296787CC53845DB2BA54FDE363DCC98A7BA256663869 E9E02E09077884DF1A2A41AA698B7EDE8DAFA621B552DDA91AD1E671D636FB36 91C62B4D2D4112F2C169E0023EB7521F570CECC54ECA5EBA462049AABBE2ADEF E3234BFD71B26DFDD9D34DFA69E5E80FD90406E6505A6798F030A4B5172A7BC2 C9B765A86ED55C0590E0432719BCD7BDE7CCC7F6B33BD467063D886276C8879D E04897A4623111C14A1EDBBF69E2FEDDFEAEB2A785C6D2F0711DF4B93AAA291E 7F4E0CF9CC3FF0D31953C594DAD014097DA02CBD5AE8828C7E7B5BDA09188B05 0D7263F164E1E78CC430ACAD1E8FA71001E9BCEFAE47C79846916A5F819CA366 5734089BCDD458CA1A9E8E17BFF357A91F9A7A8A6E1DEFB121353AA80F1906A5 AF7CD2E59EE6776FC0DA6574DA0DE522918CAC4E566F13FB9B64EFE79F3A3BC0 689E3B0676741C90FF3BF85C7A0FA9716F4ED0E329512B66BFB8AEB56C3DD6B2 24F8D6E23751A8485F7EB46719E9D22618FEE86D5E01ECCF4C6E74368A8E9B49 245D80E7484DFBC916FB2447852B36EF3F99A82B6C106F786707D7689DCD7AEC A0C51AC1A3F67034C16B74994403FAE7743BF02149BEBEF554814BEF31B79184 3FAB4D2C887E1BEE81B465D12DCDDAD03DE5ABE9E763C440B2CFD42FD16D96EB C21FE788C8C2688F79F148AA7090BE64B0EA710D376222FD1590301BA9A2E715 D33B8C1D95F2589AB0EE476F7046537E27DBBCDADEA1E7357C9D7FA92C2F93A6 7BDDF58A44966590821023380C97CDE37EF6D449E35EF32BCA6E69DC8458511E 8DC8AB63171A6018AC9A334829E5978484C4C6E917A5F1C254E6669F4037C691 36980250A80673E0F18C9E0FBA1E5CCA3BE30B8E7B7188062B25F8E1E16528A2 F217C18D6A1955482E5463FBF097ABAF7314E449C6FEE56E2695407A8AA9648C 61AC2BF3B2D9CB6317A9B16CE931D318C8BC9676CD908505568C197D90C2BB46 06431C999EB68C8216409E4CABACB2BB34A05B697B9DD1E91471A404B4969519 E25209EF4EDD420944BED17B18DB3566FCB8059699FE416789191EC2B35086AA 2E10C139E3C9FA0A535DEE9255A867A26656213E85851DE5F51F9780D3A6E572 F1F5CE64DA176CA810799DC1C60A8FD2A5ED42E613021A19928EC4572059B2C1 EE441E79CDF7DD4AF7B6E3D3230419ACAED329388044B107DCB4DE91B71EB838 904B1F969738BBDA064FFE75C6623639BE9924602DDF0C166B433B9D54ACDA5E 018680477FB8F10621FF32319E58DB672D744959A33E7314A1B3CDE0C038F7D6 0C8A195AF191E36B0325334A711CD8E25D9C1D257E46A734779E486567481108 E0281DE96907D460546578DE83A0A01A9ABF64402B48DEF739F4308E14145753 719CEF720FE5CF8DAD7845E74D502B69DC18D172C3A27411259B8042F3FF82C3 B157BE242C351830255CF0EDA96577375A70657BD9A2E9FFC54AF0AE563D73F2 E510279FEF48D79F5F7745DBB492F1D74DA738E6A4FE4364799B5BEC93B4CAF6 B06B9B8C8D164F8FA1FBBA693204064F2C1806C39910910E02ECA8D092558CB8 33338B359D56483B7B99A1D8137204EC1AE70ED3D75881FC3B00BB9349AD934C 81A9F285312FDDC77FA923B18B1873D288C2AAF2E6D0AF90BF25A982B843789D 5662D6A2DD58E065026885601ABED4B09CAAA3116DEE6B430B15BE0A121FC1BB FDEA5A501F0798CFFFFEAB5101E707F1A00C8E014A3561FD39972EA9AB108EBB 960AEA7FF60C301AD6CBFCAA7D35CBF6F8462A4D76C4FBA6F3DF6BB762DF7900 9F69529AB4EAF96C2866444B257160E8822533A7A1240C83EC18C364F577407B 4CB314678D2511735308A1660AD94B8B818CEA4A3DC00C5A1C978F8BB4E0491C 49328F6CDF95BF620AE53056364423841D84418B23C2A447B0CCF8D8633FE2E8 4A4AC1C6C74627EECDC994059F1BAE9E6B10FA80D767B3FE97BFFAD413DCB0A8 495039744B48266278194D60422D6E7C74D0DB45ACF217797D0C0678EEB60759 6231438CFEFB346553A7A447B50807EBB6E885B5A49CA9A350EC4A8C76EDFBB3 A4DA1C9E3EFA193CDF08553302998F20055C84420A4C5252F764CC4B7A4BEF6A A09170EC417B296DD9E2301CD8EABE4A087E648E0525A9FFAF26374C47FDC123 82F18C9884843864F418ACB08041E7896FDD395225532460A8194A8DB4DBD824 1C68C6665F85059E365EC0972EC6465E2D8867449907DA6692A021F026F437BD D02654BC11381BB6557663E0B0B8C4F2FF69E4776F4EABA69311BC1AF8155F7D 6D3A418BDC912CC7CF1A4BBC8A1376D8B4DEEB6585416959BCA4AA08D4520C33 EB054DE53140992D0707210593BE62B3659E3E493C4562C2E99CECA143791DAC 679896BCDA0699E405957E17DDBD243E65CDD7C9C8629F29A2078658746A7779 0F75BE24E2DDBB672B95F26366BAF036B3C23BE4132D7362E76D4183A469E0F7 29174711ECAF4FD9A923E72FE58DF2854C5537E3626317D471D1E8A922C9BBA4 CE9163A4086AC4A231C2BF35FBC39A5BBCFE41843CAC7D81A054509D31572BE1 596E0B0B563DF2BF0E57DB4943DAEE35CA26C8433FEE4FC61145C77F65DADE75 62DA18DFABC7F4194906F53884E62E77D8AB3E099776AB93B2B4D0C98FA44C71 597202A2643942795EE8CE098FE26F1AF8134F1E75FAE18D563B1FF43A511C9E EAFB9EFCF61490A1A4FD2CF354927B72C5EDD5D62B2F3F5006D6130562A13BCB 1B988A994A8D68B051A5A821CCD5D0F8D9D49FE7CD04EECCFD7A554CCDFFD77E 27AC4AB5BF9FE40F90EBD066C483796CE1A364E95C5E0CF2154834760522F128 B2DBD1F4F73347D42635B2875A23597C35A0823CC6F71E49598125411BC9B2C2 72470D36DD967C947AFB031BFCF770FE50551A134DF8C5D1AB1F09819569A57E E23D4E87C0B52CD02B0A2E3FAA7D27A94359E82AF047756BB769BC5950A75207 78ABD49D174F2F69810AFFA9336A52D6B93B004DCA5CDE58475C0210E0BA1D20 FD4FFD6838EC56A0922472D4C4EE0CC481574BC30618179E733EA40A48847E14 A75BE7717CC5DDCB5B0718074EAB6FF07CFFE794D335B3A13EB968EA8FC5B08A 13B38AD1C2C964E4B07E90B9732C458216B028E07DD593A5B767A2B415EFE7DA 951FC07800F11C7E2EF9BDD152BC6815B7F32117F49FE08BD79BEB949003512A 327F3F8FAE1767E7842348BA4373649F1A21DB2C56C081BCF9FA4EA86C8DFF00 FF45C4F1386CF8C2C4120F3F6019CEBB639F2D272D08C1763A470D4BF6330DC8 43C069A6333113C3A0C93471486EFE9BFC02B760C7CBB2E9156087D09EE8A178 5EF50B34994094C3F0015EA2ADB6C920F4302FDEF128711994875551C4E883E2 DDEFFAAE11F2234AFDD96400BB69C1B4E6EFD75734C586A10A54A98E7D790F28 DEF7C7DF61FB23BF91AA700AE585EBDE74E215DA49F4ED466F46129022722086 8884D8E026F35C4BEE7E866DF8E0846D5EC3534069B713FAB02D4B4EE3B44E1B 656F30D629D40AA1337786C1FDA08EA1217AFA4A6E2498B334DAB5461A70DFBB 5AA5686C89FFA4EE82D81CE2B28334DC5C032487CCE998616F48150BA1281911 076E626E5BFCC56A0A4CDC559F878F14C2BD7A5148C1D8CC303FF9EC473354D2 D4FB0F0F2AD0CF182A28074ED6552E179222570DE0E0D44E8FF4DB36C3AD6487 C4BA53C8548714A69FCF8E3E5202F09469D7447C6519AE902C1D611A720BAFB5 59E27A6DBA73624F44B4ABE0988BA3450F82E03521CCE8EDE8BE7EE1223B575A DF9A52650E85545525E6F121FF2D1531F156EA9D5594239AEA2CD09EE28ACB15 A445E11FD1C031188DB61881F474D49425C084489A88A47D681EA68E7FC4B1F9 DBB552063A02A0EB51125E9B2CC646B940D46FF457415F9565892DEAC030F08B E4C10DC38D825C7597394C844CB863CE6C843F67F2E1C42C4EF86AC7FB727BF0 224B5E91BAD99CC6638AB2C64469A81D8B1789981872ED037B3A34BDF3130137 80FE80FDA65EFBC11A08B98A1AE595F980B577E22D3CB7FED1D4016F5290ADF5 47D7D9BAFE39F294582F2C084003E9C83FDB9EBC87C8B477CB8BB359EDD9BBC9 9368D6605E1468A20909831BF602EFCEC0D5EBA99A2223E5A269275C8B221B3A F9226654185929F794E1979ED18B4CD36152F973433AC67BE24B9D953254FBBD B644CDF3BF0E29A2C72113DC486E46DED2CE8F8DFA8B0F8478D1F18C9AA8E054 A31C3DBE84ECEDD85DF6AF9467AC2990ECAA3384FBCA1BBE598AA0D6813C859E 1520B88BF30ADA910A6AC3068A5B8CFD76B7F0F6F4AF4C32450D628B5320C384 F23A2B5E8756895584155226A30F8B0437E028978491DCD00E79C0ED58DF261E 79B9DA17E57AEE03EE92102EAB2D63E69A88EE0B1E2087ED0C0CF6475EBDC3BE 0324D1FC8F7B90D8D807533E5436F2C2583B9629EC390403437FDAC908557894 03054A6DD6A3586043A9C8BFD0C7EDE1229DBB9F69F7A5D20F55664D061F6517 0051C6B3CD7338241FB403F2AF77DAB1A8EBE1650156D40863EC1957372BFDEA BA8D0BB1193CC5BEB5A68C8274802E14FFA3ADCEBE19070325B1BDB960CF2988 C0F5A9BFD843C515ADEC8B8AB02B2891EDD7502D9F28F4E58D8F67D1ACAFD0C3 3531E0C7D1554344CCF90AC8696E83A3F968252981CAC09653956F4343B99D3D 4F17CB8BBE4506B354439B70F2024871D16668F9DECD8EDB872BE5E6ACC406F1 1DF4E3ADF60EFED57D1C426292970199BB663405236C6A907B6891C6190E87F2 78D9142220FF295C7BF44AF61470798FB8CFBEE6973C69DA1CC24ECB058AA753 DDBFD92FBB15560EA19D5D92F0005B74F06F0EA5901D231996E0866389DCA433 E62BE48479687084C1D67BC592E592939F806FA8BF5F0D3F644B1FA6F056DE0D 51D3F212C6818CB6166317058C2A0C07AE2E324CD90D4EC83CF4819B10CC348C 6DBABA024A5FCDAE6E288F82DA060BCD16437F07DCA43BF1E5A1B402F16C78FC 075BEE900B4021A1019C4A5ADC33230047FF11FDE8FB775DDA267040A22B4E5D 6012F7E72B8BC8DD3A81369A08FB81C6C4873C2147D03D4181D6D8032DD2B610 9C44CAB50C5BD8F489EBF01C72D4198B66EEA4E976462F8874143640B82AE57C A51EDEDE75A9A55D31587C14F8DEFFE69F75EA7B95BF725CE9991FB2F07AF568 5AFEB39447B728B99BE0502BF28DE1D92B15926BE4E3DA2E7BB44A24836A97C6 EE3A2080E01DC6514180DAF9C055F4C94929D34F193920020505E62804461630 9F42C652F9D5681C91BE23DCB0C634247E739135F925EF3D5424767D5F5C5879 C46F2E32C7B3BE9E90FD6ABE693A6016AB77670129B58B8FE719FA97FE320842 6488CB85B6BCC0012975D22E75A2E086131DE676AB825A386C086FBE1B65DDDD A19F06AA4C1D3EC84751C649F4A62CFDC48A7CF88CFEC68B959C211B60DCB045 6BFF922FD7349B98E1769394E6CEA4F764AC4B6536AAE4E6BE69099A39A6A33C 97671C3AB4E7A94DCB829FBA97DFE5F71B1728FC81F826699DFDB0ACE9BC60E0 6EC15D35EC479F3F53EE4D0398BAC138FED504A84A13B78568E3F9C86BAE8B88 61830A80F8B994D0D66A8FA3FCD6C5099C29FC285ABF096EF9A3BFDBB522157C DCE9F0D6AAFB1F8D7B0A3C573D0C170357175DD56EAF37BAAEF4C92FBE17E26C 7D2BDAACB9B8F33D09651FBE0D49A8BE66B78D075485BCD38DED5056FCE48A12 D28E9670EC7CF4E9A277D6ABC2F7AB30BFF290B5452582F372FC9DE6CEA9EC0B 84328269F14FE7F47620B1042B283C54161AFCF84B46E6B1410587295E4F8958 C1800F120B59639C85D46D46A4C64309931A8C91F138EB52F779189EF75B9157 D624045F4B8846856ADF0AD735FC6FA41F7B6C002E9D1EBD92468E86C843AFB7 4D78E3D54D866029DE5DF865EE3F7313AC358EDA70A792E22F2F806EF86A6B57 64AAD565C57E64B1A6635B7394B4B5729189319FCAC8529ADE30633B9BDEE0D2 AF1F8944EFDC7C408FD8FC270822CC01E7BA355C856219B3AC5D05CA37EB0EF1 6766D62383AEDDA1F7CDAD1DF0172E766BB46C5FCCDDD61BB019D283EDEF312A B2DBA38C9BB0928FB93F50E8516AB353BE04403D132805B5AAAA17163AB9C847 F1B54946B0775FD21325C82E4EC7F2186C54B4396BC4B0B913A59E4444D11B39 8AB56F2FD5788A9BA45DA5499A50BA74D28707F62086907BF8342E0C753A31A8 DE293B592F51D74DECA52858CCF76C69BAF2224F640069BEF2604983FB478173 792D68030D7A6E3FE083AFFE9488D872897ABFC88CA8BFE484A75201D73058D4 72A8A26A50BA1F2B50CBF98D46DFED0BA057619BF370E435A0400147928D7C06 28DF2A03527E3BE925D6A664E4640E63BD22D54A038D934B3DB5B500E075B8AB 06DB5279274E65FF870F1E5106E190AB0FD8849EEE2D605FD4F0DED2C3F86831 4EECBFAAD8B2A895F08DBA692A8176F9080045519CC6C46B52F0F31DF112AD79 8E46B9899C5527A011AB63FA443ACE90F09434C295A5D9E6753AF2645407488E D29E7711546F87265C130B76B4632242E43962A5C886D4DB6316A2F3420FCAEA 3055AB5A9E1325EA870CE87F34BB2B3110E4919E1AFEE67606B00B03DD6824F0 20BA42968B81DAE198C88057438E36056D46C550E3E5E03A99BD4B07E66A2179 BBC5B3FB06D5D72022C53A3F3A1B759472D5A50D7F7A1F4E31D3F7A30EDC1D45 4B00AEB5DF680145A123CCA3BBD801CA64B2CBEEA99842720F8DCE432909AE78 5AD3F29AC69D302C62256CC4D47AC92EE11D2A3E1C666CEA24876491BB167548 9E3A990252DF8254CB5E7141F57B78FD1FEB38BE135815C6FC86EF81B5994711 E43083C3234C55DAD97CCCE4FF3F55C5A6C22ADD2C549513A465CFA3D8A9AEB6 331374DC05A4F496BE33F9263172FB6FE1CCD19EE9515C5155ABECA9492DC743 BE4142D63FB5E17D55C9FE642F07995502AECD9D555603D15B5BE420A65A6E98 4F341BA13E44DBBC1DC8CF0D561198A2B40FAF35F7ED5FEB4429BF71F5C88637 CB114F1377FD3227EDF592733EC68F4EFEAB14FE7C26DA7031075E04289FA6DC 8A79F81E4E18CAE8380CC585E7DA3DCDA3FCB53929AA8D772D53FC6D821EBB14 EB472017FB56CE9410FEEFF14EA69C188993922DAFEC805F4C8028537A9D6365 AE1A6BEF37CE8E02B995C41382984802AD3D12AA9FAA36837F9F9F8F60D16B81 474238F136F442CA9B14620F83E4046E41EB0FD02BD04DA7863DF26624B5489A B8BA35B0B3A8D128FA10E01DC9B622C26CC57CA79CCDEEB7E174698EFDCC0CBE 879AE1434B3EC5AF48E6C2EC5652DEFE0ECD7415FA46BC0C80FCC57CC808B3DE CBE4CC7B62AD3B092487F7A23C38A2D9102DEBB1CF4C1EE7FEDE1E8BBCDF7F73 54CAB1E591F9B3B3159D879A9492394B32F2CC43EE7EBA6E293AF12D7FC4ADF4 DAF8F2F48A777E927A915DE1FD9125B52D406BACB0BEA149F6F6D79D92D06413 5D68461A772D531F2E76D1947D2ED5BFFCD758E062B5435BFD180F7E3734D5DD ABD86A1C2BA643955A36C482BEBAC608F588C43E6EA7EA2AE01D0346D28F50CD BA8F9FD23674AB19A2B879E0DD19029EAC5D74D16B186CF4BE3382E74E361427 536A00347E536701808C1D31A617D1F9269110B76A0D59C7B84D98C8FE308733 C9497B807A77D244FEE03ED7FB5EB4D6ABB74A7129F23AF628BC01BEC6C43ED2 D62F4E2133006FDB94D33CD31F9FFE57C8C9E31DC6D7A81A2C6ABF1D971EE222 96A4D79F7232190EB796A43ECEB88F1C64A88A10C3AE8E98711EFDF984BF270B 55C5B9082D54DA7D32B168CE573597DC5A453D76953DBDDDBC1798F8A645AEB3 78B6B5BAF60C9AFA9D5F818740EDAA977EBEA0F68E531550E607E6FCB04F3E22 BC9D6440E1E153C8D780213DAB08CF8CFEB03018942AF980642745D711C7DB1D BEFD825627798897ED8185D80234B6C087FBB602ADB1263C2A2A0F59AFCA7B09 EA4ED3BCF936C2DAEA9C8DDAA90130C24AD1A1BA47711CC760FF72EB3F27C165 CA1FDCF1250C6CA4A788AAEEE08902AB4EB03C6EDF281CA2F5B074C859DE3963 27F7CFC53CC91C80F779ABB25F7A6601453DF5606B72EC562F615A92C1DCED58 3911BE7784B6E8B17F8993E4D5693A327F9C289701F39ADCF583BB4EFDE1F835 1A59BBC2E6B73CF422D877B0B423E4E8FD116F5C66A4BEB706A3D42E7EFBB5E5 E73CD03D7A91719337CC8E13F9D8DA255185FBE3F4FB6DBE8EA90AF036A09BE3 5047B59BC18C1C3658ACE003B6535E42043E4D7E6D79E0B48B3D0DCA36C046D1 D5ACE0B6F91CB78BCBD144F3FAA3D9D711C9D11EC30B6CCDBF43CD490E9AC229 9ED2CFAC4F53927040CC8FD26004450889A1167FA34247B7C283A46E4C0A8C20 AB43314A34EF0BC02C5558746D35F2315624FB9D4A8ED13E3D1A8B80B872798E CCB9775F985E31E8228B03949B4E35DCF7A41C834E53CE3C163EEECE81A8278C FEA3A9E3264627D33738170C12F4EB23EF8F00811723FA4FE56A0EFE8ED5EBE4 90455B690EAE1E8F1092C1AAC07FC418A6790C2DDA6DF739B9B586B68263EB63 718EAD2B11037C5D26FF31FB2E56AB82773921B00EF07DECAEE2A8FD71AB232C 86865012F1FCC80CBDC4B0E881819601CE2FC5AC36875F2FB5C088436BB11159 813020F0433EDF6D96FD162F5E3241F88BA7025F2B010208DD1DF737FFF1185B 812864C3049CE325E06610404C8DE9322187DAA7FD90FFDF2DF3C86D94E8E792 377C1C1F10FDC78E1FDEAF718A2857C4922FA300C8D3FAC136BA2957C675FBDD 21E3A9E29C797142BA6D30FABB0D5E97AABB49D113A55C4838B253AB8D7443E7 15596B3BDF01C88C17135A74AF78551CEB6B0041BD17ECAF89321E6948E1C531 B227A1F071FC3558501BFFC842A4F8B80C14D9213E0633485A66F899BCB473D7 3C72329610575B6279C781714761468C785E426DC9393564979B1D6A6D55AE9B 4954010208883EC964F35E8363129682AAFA2D40E1ED08A4A1DF27F3DB5474E2 92B917B45D9473AC94EE40662DF06AC9D004541B6F88DF5AA4A36756620CBE83 1254ED1C3C9CA39B09E0D4148DA552B00FC60FF68E7159F556998EB8A66C8EC3 3B7842ACEE888BCBD1FA183BAB95B06B245ACEA49F8CC51A2EB01053E99E9A87 A5198C2FC26E270961FFF61A093A084594E6C0298CF96B251C5F8395ACDA26FC 461E6DB774F6220F8FA04C68519E19CF69EFA73E9A1BDFFE833B228DC19571BA 34B7AC21EB2BF8B1876BD11E128F002AC9AD6A9785CBBFE2D5FBAC307BE7CE5B DDA7C12820028FBDBEF1343638CE166E43B95E6518A83828AA3C3628779FB2E4 CE32DED584715FD18C95D38FA85772DC8650EFC42F980A1ADC012ACD93B7E1E5 FA6453179ADC6F17C94FEA1F4CC2EF6A2A975C687ED81DEB7111F0897742B373 30720766409C534C5E0A42D7221337FF3C4C59BBD239518F3976DC55FDBB8C1C 8DB9CB4B05B1D9AFBAF0FA1D82B1564AD7FC92B6CB3582F7DA309403EB78916B BFDC6F918E26A39755E5AD6394D985C92F7927FB1287FAFF2F60248236F918DC 2E8557C6805B01090A037E8D5C529E2D70976A9CBF3785F4BAFAF9923DB40756 7B6CE8EE83559893E3930790E5917EC3421FEB042C0CBF6CE74F16C44FA08025 82EDA0833C0486CDA66ACB450094BB65F54C83829B47DAAAC9E4CF115FC275C8 6BE583008180F2E2C9B003712ECE32333199BBF9772A471EADE59355FF264DD7 ADFD42FECCD00892FB545DFE555AAA4B273B82BD2740CB8C9ACD144DEEA94188 D1AFEDFA1FC63557F9E527C00AE7D14762FEC2814487CB60E406F8D4A47365B1 F7B0E0A56CEF011CC11345674611EBFB5A7C587C34F786498FEE4F0F999AF42F D955CF2ECC5B64BB1C100310DE5B6C7D106A80FA4ACE0184A6E18FAC544EEDCF 307334E1C2A0CB6E488B21DA3BDDC5B593D5ABD6006D1E2BB56336EA88D56DAA 62DAFDDC379B06EF80E9F3661C6B7AA6787ADD06155F3DBCABAB6BA3A46C9047 5D295774447BC007D5423B9840E2ABACB5B811B30ABFF547A8A6E2C18A92DEF5 D30890D49388E80E6EC7626FE3236AABBF64B21E5525FFB7C802511129EBFAD3 D1E19814500A465DA92054F93FF77864698288510AB599237D0DBE1EECF81C46 F706515DF10A1D0FB06939473BC72429A42CE6E15BA2C97720756D80DDDC171E 7E8202D385C2E5B4A5A011933CE920E98A09527DDBF49FB4DAF2E736B1E42F57 354C91CAACB68BEE8FDD10F4DECF25ABA4EFFC4588DFDB9E98640737C015EA04 A33D5AAAF9AC4A7D288BC9D4A8AAB9B852516E215DF7614B10BEF003EE1D0572 E4654DBA4D71959D403B936339D41C381FC1A206BFA6505DF3082D9FF767EF67 437E8C2A14A8B6F0FB98C80DCC42A30C57C8AC3FE83570A1B4AB404374B85F45 A1056E389A7148CAF714CF6DC26A04E3DE8E2E7FD26F6CDE3E836AE65E593A9D 3FA7A24A32E3E99A152009C8713FF8960FC93A2E49B8F442B81A90F98B99E140 5F0E0253DE8ACE69F1248040510DEAEE069307FBD02B821D1DAEADE6C41111E8 37A80AB702B8D79977DD73429695C13DF81ED3B562FF4C168AE03ECD24909A41 22C579987CBB22700D1D34BB16E5D0B4BEDB4660D34EF5CF0A4FE507198EE14D 9FAF7C97CF769EA9159E1D8210B063141913DD402BAFD515CD746A7CBC061A74 CD6D6DF78AA722FF543C5379A1AF5102B75C06F73E075BD8531353892E1733D5 8143315C0C780BBB21D6954119C0AB1D4C89EA67C0AFDD4607AF07D509F481A9 9045776F08003CB429316307E66E1F9490E8547FE0336BDD8B070290558E0DCE DB08FCF371A8A9FE905E9C3BA4CBD4F12BB2F512838D395BBCAB1488C58122C0 CD6D3634C0F6E193E2F2E8C632BB9185B20D94503E02244938D4400F0DD8FB81 3AB0CBCF32E462A223F9680A14AC8876917ADEDCC9B181D584AA307CFF3B66B6 F59FC840A9E8D1BE101AA1DE41934C22A1017A8AF69D257433C2D2C5A0474F9D 362A669B4044B3990BF83E8906C5B7E2B45D688CF12CC1FF38F2EA47743676CB 55FCD3C6261C6F5AF002869128882E39E089A6FA108195A8B86CB07913FFFA6F 6D8F8D5C9E897D63C174825286953B9DCB09B8475D0675E09C1D26286107E89C C75F92D14002B1289A5E11F059F28FA27DF23FF395EEDFD5F22374FF67F0B60E 81D249898A228A6A89141B23918E977BA79C5F5E6CE84FD35F51B136D81428E4 E4D205612F6DEEC1CE6AE571B30A33DE004A8F096656A3BFAF8BAE8A2C73AA53 D7984D6777540082F3674304D2C3F17775BDF86A27563CC2BF95F190DB3E28E9 FBD0716C0F1B0D56A96E2E870882F03A3E160621FB469355859954858C9CC2AB 06EA8F87EA163B9ABC176D704D3C17A37508864381659070B071B80C79D6D60C 7858A32F5DE87B1F818E78048CE81E229FD7BD91286ECD773147F94E7A184450 D1060F0FBC5A8DB06BB4009B3F5F50EFEECEF8FE970E3FBFEB5ADEDE9EAC6A49 AECCEB5378A9CE274BC7F25D03CF477C2054D313FD988A4D913D20ED3981CE47 8674501E487FEFE5DD91CB0E5ED24BE1D2D45C88DBE1378B11F6B7076FE56BF4 8E8925E65FBF23330B9C4A943CD96EEC06A6073AED304CDF520CD2AC1CFFAC7A 6B8D8FFB7327834C9DADF578F250A51BE64D27A2B65A16DD0204635560B47075 3A054F7159EE483CA06345D3D55EFACD47AD32A9D7D7404ED0CB742A3AB8C47C 2C5CC71EA3E1405D6E114DD53D85C2350D46A8E4BDFD1667C65A8152D9F3331D 6235F40AE36EDB507325E21496725F3351C239207C0C4BBAEE2DC7D2797B8818 BEBAFCA4FEDBBBBBF3FDB633A0C21A8BBA856D4A3119394FB00AD092E314558B 99CD5B138D4A42BB7B621DFCC2A2E2AD262479E878D8F26195A643BA0D13F9C9 FCF3B6BE5774DE6F4564FB82BA3B2B9BA29A5F406F1A135D46DB10C80CA11E1C 39C9A74A18D8EEE86C85556F8B9203E00DE0B1A164134E48FCE7F37AAB98A79B EAD809EA81192ADD3D3C6B35E521AC99E190262E5454C7170B081CB8AE338D09 D489BB694D228CE9C05DA95297BF106A3B71A99A5F199F122971F5C4B0B9C53A 4344FD111B92AF456697E0B85142B71FA56802C392C886A408558A297EC3C717 FB803CA1002361034D40420699FFE3C149800137EBA3AD99AAAD74B471038675 8B073F692D278E0A088D3F51360C2C79A83FCDABE9963A4D636631310E7C6D35 EF02828CD45CEBF9892C2761D934E07AF32BE74852C13FE63BD3DFF3619CEFA1 25F5FAC01306FD99A573F0F5F29116967FFA22C9236EE8EB052488C4CC204855 EEDB80B30838AEF66DD960389684231FAAB83750575E4C9BAE860D9B0F838927 791AE22921BAF254FE561771B7A9164362D6BD462A82763F6D19737ADA1C2B92 BD72443D7521795F9D3702F83B04BCF992667CA255A3AA539CB71F25F2D0ED57 9E0B180D1C199211FBC17EE282E7CA9E078593E6340BA651AB949482A0760790 E4C3F1446653CFF964B9A3142FF4FBE8C75CFBAEFFEEE1810D38033CBDA2FE9F B42BBD97740EF0C118C7954FBE81FDDDC74608D036A3BBB75EEED4E1A4A56381 0F57C993C4651E4753A27684D170EBC495D09202AC0CDC5F10267EF26EF4E7D0 908F4524C91AD27F43737253BF0617559F2EB99EB26643D8C28B61F8968CEE7A A79A818887ED9BC3AECE4A35AB15752A368D09594F93B7A741282DB5C6E42144 EAD79AADE23733A43500563C3AD34E0421D1E3B4642EC1D70F0054E3DB6CC218 FF930B11B1CCC3E4C90BC523D4635161C89CD9FF8F2C4F6E4127ABF479914610 4D95589775902AE3993E1CE3D4868A1055BFF961CCB244AE25C76C4CE556B8AF 98129765EA10B35FFF3D24DE1CA68BA55E133084CD2562832630E302C3823EB2 5D7293D0C760EC1788BA6BC9ADB7AF6DA83C951E0A23AD98EFAD64AD387F7764 21320EAA8DD04EFC4C2BC011185DAC3DC1FEF1461F3F9ED515E2240433D855E2 0229E1D5269092D0FF790539D2946A608E82E1FCA5E3A1254B27AA134C300FFE C7C724824AE8B8436577129608078274BB69FB6A026D0CA48B97314F596EB375 390574158057D3E1C3EA4AC61BEC73F81C706A6C7A9B42EEACD6A4B5C4E69FD2 C68AB11CF02CE3D9B7148BAEC69F92FD7DAF6C9D772BE60AD4579BCE18396E4B 60EED65E6E2E62B283F135675C188F58C831B3A7ADCACACD39871EF8905B3264 567AEEE25FB31D64C6596D60597315F1AD8F74E5577E6C966F8F65B001850D1F 39F0234F0478F6DB136F17F20262CC072B25202BCC8A67EECB03A2834136EE5E 8FDF55397F3572922DF82D25376DA73083419420003E99A020198ED0ECA44A72 DCFF31392F59E14720BA027A5A5E81B3C32BE7DBEE039CEA50AFD5CF9CB9080B 3952949A3165C5AE1EF9D8C76E0C901DF5013469D55C8AFE1554A74D6C565533 FD00D77FAA0311910C9C191ECBE1A0FE30A4FCDC3909D4F6322DE2DE90865099 ABAA1A087DE9B4642DB649ECA28D40631EBA0B3902EA6D70F9260EA9DACBCE35 8EFFA26B2E8BF4567406788443950D8A71339F595C83E28111FC90181AF60EC8 9A7EDDE1989A2678B8C570F5D0BC178C4018626B9AC851604F03C98469EFDFCB BC34589B59973E918756A2C1BB7D1811BEAA17D193DEA92EB273D50AE5C0FC30 661B330B083311E5D971D70DE46E2239532FAC9A6D8FD913E6DD03F42ED6148C 4F04E6D136D41C24BD9B973109A9B63233E51176EE64D247DE1C5CBB43F568BC DBD5A6AEDFB68E5A0C8DC465E9949A96665AB78F41132F96F3680B5A9A79DC44 828FBDA04368F277C40F629961EAA9F3B253276EE252478A9F409C2FB6447C65 37AB9FC9A216970D7BF6912FAFC92BA0C000A58950291FB3E47F0DFD493EC7CC A99555CACEB7EC87F4250AB92E7136500138087A19053E9152B6F007B8D3DE8C 96224FF8D464BD3289C08AD1E05B9D063375F38FD42CE97ADAC4E5B83B8A88D2 B2634B95A0DC0AE6A407E62D153BFC434B42680FD0F62F5FCF0818182F182D1D 6B9EBD47149F8506CF38BA61D8AE460A8B660F40DEFBC9243154E5683EA8D574 8D48276FE5128F972D96E42D89E374F7D8C72E70F84F028263507BC96F6B2B92 EF4B992CA46361BA3EDB888A6E5C57688198EF10A616F7DCCA55B4E1645FFBEA C2201D5503101C400B147CA23A805AA95FF059120C677C32ADC486DCA6E775EC 23BB704624D3755E09505C395CC3AB83D68F10E2D6E1497BC179F3CA82A3DFC2 38275D10D3253264BA9C32DA47C0088660037C7A789C1DAF75D0476BA9ED5B62 CD30BA0E268DF3537F8298BDDCA16B1C970C2863B21CD839FF6B713438447A4C C58C1F0ECE39E126AAC2353E31B6FB808253501CF26AA3AC48433D4CE5A946BF 10347C814A195929213655345791FAEB7986B1DD4F2B0C9E7116B11A4F1157CB 933B48B488B7DFE700423AD4FAA7E26F003B87B6255BB607A3A639830D68D663 A3350CDD992B528E3D2176DAF79AC03F6455B1BD626ED15299042B46F03BB46B 992109329C6F67F1CD92A620FB4D806558D6CFDD75DE4F7D6C558CD5325302BF ABBF40001F90CC940511F63F32F112EB958944E37A603642C0CDFC7941D9EC65 F1F5B2805EC17A6662FABEAC3F1A7CE8A4958D64FCD57759F5CA294236B5834B 0071972DBCFAE0D89A1BA76FA1EEF2C8ACB12E45C8D8939B3EF1DA3970ECD2A3 30AE415757A89E44CED997FFF9F6378FDB532ADAFB25872A690137609D91405F 4FDA7B432D432325F1467A7C85363A9E2825F86D5B9F9523E53FC5B58D82CB28 90D43D172B2CBABDA71E5B83928A6271468C197108584BE45647AF5C9BD930E4 18E321AE20B3D28980B1CA53F8B2696043BCC4C925F218B0AFF8E8C2BC1B85A9 134BD28FC51E5F4E803761720601C5D9D87921116C342D832BB14EFA08032E5D 7C0C4F14F118883DBB1CA0313B6658E3BB5A7ABBA4970CAB64E66515031BEEA7 F0311CD7DF8CCADCB38103DBB1D60CE59FEF567B2755D0A65100C8F8EA622025 4AFEC5D179796C4F87808A76B3F420A228544CC12427AE7A5E2FB6CD76D4668D BD5A22FF8161EF3FB20EE9FE64EFC4D1E466DEF81D20A395B020BDB7358E80D0 6CCBBB8725B9AB973B060770E4CB902F429D75295D1E5ADA0BDC01D0DA7A4ED2 A21346CC735F3E6662B87BCDED41C39EB2174C5ABD9C89A4A6554B3523E08BAD F208FFE1095E6641C548DC0B7116851695AE8813E691347526DA61EC59DB43E1 03BD503968825F7EA207E22EA04656780C15E1E9D0A00CF8CEEC4D3FD48A4E93 7E82A2D0F952F5ED616618739ADDA48480DA4665526260E4269F135C89C2F28C 28B435A1A40C924B79934D6CC536A58D2F102CB46E4C3F6F5390008A7C7B5E28 4044E385A5D6FBE641B6FB074C4E15DB9D25152E503EB7DB52F45913FBD962C4 550310BC3592CF1C56A7E19A73261219812CA9A818856901E9F0FC46FA53FD67 20A7AF35375DC845C8A9BC82F46C061F46233CE3F963C6AC49CCE0936A1813CC F7904CBE756A07106AC3D9B58C28EB405FE50A12710C7FA7B4F6900E163125DC 43672E2C565C6959C412F7CC333F49E0FF5B1AE666E0770255C43E1779A67D7A BD794057140D8D1478B7B3C43C84C2C2E56DCA12A1A536F80B16BF9C5244FFB6 906F2729E0D6C3A6AE9A837CF39F81668CE7B299F4EC9825892A961935E4C81D 7A9FE5D9431283C53770E41DB77A70500A9B21D63B2F073D75D8E11579FF7C63 3D1BD1D11EA3C49A594D1D83A733ADB8D887AABCB81C32E3913FC4B2DD1DFF11 10C193CD5D5D5FDC8080F9B99C9B29A86ACFD94EAC9E052790D6A46E5A5E946F 6AB9541056CC23323C09CBA556F1B0F28BA2C30E039B3552DDBAC17B9311BF1F 648D3527E8650B3FC89CF81256E9A4A9054D9F1A9839BF7E0B875D25EAC8AFA8 2B5663DAD7CC7DED3206BF5957291DF837535DB23BA63F9F7ACA7141E1490A68 327E35FB7888C160C2D47BC4A7CD84194FF52646DF43AC83A51489481CBA4D20 1E5094E7AC3EE66A5828BF1D87A530D7786577F164AC3D5C0D624FC6CF1DDFFF C2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMSL10 %!PS-AdobeFont-1.1: CMSL10 1.0 %%CreationDate: 1991 Aug 20 16:40:20 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.0) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMSL10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle -9.46 def /isFixedPitch false def end readonly def /FontName /CMSL10 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 40 /parenleft put dup 41 /parenright put dup 45 /hyphen put dup 46 /period put dup 47 /slash put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 55 /seven put dup 56 /eight put dup 57 /nine put dup 65 /A put dup 66 /B put dup 67 /C put dup 68 /D put dup 69 /E put dup 70 /F put dup 71 /G put dup 72 /H put dup 73 /I put dup 75 /K put dup 76 /L put dup 77 /M put dup 78 /N put dup 79 /O put dup 80 /P put dup 82 /R put dup 83 /S put dup 84 /T put dup 85 /U put dup 86 /V put dup 87 /W put dup 88 /X put dup 89 /Y put dup 90 /Z put readonly def /FontBBox{-62 -250 1123 750}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA0529731C99A784CCBE85B4993B2EEBDE 3B12D472B7CF54651EF21185116A69AB1096ED4BAD2F646635E019B6417CC77B 532F85D811C70D1429A19A5307EF63EB5C5E02C89FC6C20F6D9D89E7D91FE470 B72BEFDA23F5DF76BE05AF4CE93137A219ED8A04A9D7D6FDF37E6B7FCDE0D90B 986423E5960A5D9FBB4C956556E8DF90CBFAEC476FA36FD9A5C8175C9AF513FE D919C2DDD26BDC0D99398B9F4D03D5993DFC0930297866E1CD0A319B6B1FD958 9429B9D40924DC059325D9D4CC0344F3F997A99E6CC0676735EBCD685AAC9142 08DAFEC78BB41AFC2F1C219910BDF41D6279284EF600B69776CA15BC8A34347C 30783C52AFA60FBE3E353E2AE354CF87B558776A22C776C7A0B5AB5CE1F941EF C2D9CAC37294BF407A671F10E4743BF842143F4F7DFEE643BA3BBD8BB9E3F24A BCCF7F0ADF8BA500620C81033EAE8C4EF2C1DEF13AC575F1B3BBB66F093D3B78 5412B82B67FFA087AF57182B2230F9F2137180CA58A7D9B2C822FF04BE6CD01D 43B2CA7058C7B953F6D9B5D6E91ECBAA5CDE1159B0E59C83DBAD96D6C8C8BAB1 374EF652D10C0F3EE7104472C98DD3572AAF2D45A70BF7061447E21EE3C3BF23 DF39C2D1B35B42CD5297BEBE6BC94F7C9DC6E61EC67E4F677256FED9064BD3E4 B51A71B1D27CA4E5AA9E1D8080E6DAB5310711EEF87C40859FA935B19524AE83 63B163FA8397BDFF443227FEDF7DB27DC35D89FB1C5E435DA0619A5C88AFC73B 89A2DF5E767C5B536BC7167A840A0C32BD57A14DE69A7D0D819AC36FF32F908A 5070F32983BB007437E3500799DF5E0AD3710A4C0000F0098D5BE99F2EB9C1C2 C444FD9552D0DCA098A94B3BF176F511CEE13DB7EFFAED7C47B5ADCF8D4700F5 7A5FD1B49560969BF5C44F3749370663A04776F749DDD7B50674D93254426C4B EFE264BEE7810EC93784B7C01A7F29EFD92547E13A2C7851A2E709FBD5B87850 4A44F08F56A542DBE072D2FBC58D9E6468E1AB858DC35240E30D31C7AC13D6C5 7D2BB634BEE96FA0E10F842B11A789F72A333DD6DDCB1BC23227EBC406E50B40 30AF0C48E6359AB0C46898CDAF1118E46BFF8B00F54EACBC2AC262AB898C42B9 2E080C10DE923C18AD2A2BE7ABFE6A00500618FACABBD844A515F5D7C7F7213D 7084E7361377127944EB80BD687ACC3F3400538570CFA3A299054F000E0390FF 5478FADAE4484DB8477D6E5E843DA9465F52C8CB88994A2DCD7BACB89D10EE84 516D7ABC25A54AC996D6EBDCA47306CE267AF8AD5BB041EEB9F4B2CE4EAACFD1 5D1DB53C1F07287450201D43E3AD980A644F39FB1FCDCE21711FD48169A9BA08 EC2A65050703540945FEFDD28556DDA2FC55F7D7CAE89F4D176FBCB9A08A7BB0 9F6F402A5087641EC7DB75D2CBCACADA9A373AC28AA030584C930A4F787C0D6A 2E1F7B837C949DDCF59E188349BEE6721335A3AA15FD72464171B978C66C24BA 5F94014AD374ACC4DB2D6C93D3C8FE5091397FBE134513AE4AC018EF044AD529 02E2336906FE185C146C54EDCB967A7619E4403F9CE78491DE897A99715E0724 028CB94B23C8141063150EE57F90A6BE0994D689C8545D763A8C60BF8A14AB1A 74FFD3FE096003CFD3A7C4BB8AF842BEBCF18CB9A22A575383956D85181EAB6E C2D44AAB62708F00DEDF1488344F09D1D08B3EDB11D617A161A473A7570E15D5 600868BFFFE8400320EF767806653ED6857CD72B6F038133C56AD7CD47A7B38C 9B2D909F4EAF9958CA3CDE2A6227254D968E72E24D3005E97C89927193F648D2 D2FE80F2845860B7C3B3F23570A2C1C5BD6348B905969E3322E72510696FCFF2 901F55946BB66CFD2472A24C3093964C546ECFDAD7FD28B24EFA1ACA58EC7BBF 470572D51E602B8AF8F42F8043D9A39D7598B61CFB7EC1E09E1FDE59A3AF2EE0 6E402EC1335C147FC7050081CB486676A355508563FCF063646D7AE6224E0C0F 397CDB78934CA760E52E113AEB044F20AF17AC32AA85C319A58541BB43313032 7374EFFD2DB344A77995A00ECB28192C3D65124F40A37E8CB3F6660204FBF2AB CD193C8A1F199F1E92196742CA88926F6CEB7F72BEA0182365AAAE458A163A41 3A9F6E8EC5AB9F8A73BBB46591F87371178741A97AE3B39EBD8280491FDF2584 1F412CC3BCC22F2F7892A194E548D4B5712F7AC3CA4C5D43088FAFF53ECA3892 65C6AD135E9D3B75B7606E259DEEA083CB2E9C3822B2B02C4A42A965DA50C3BD 7355FB5738E25881777111280AE04BC1273698F7BE40E33151055C8DB4E2F38D F6A6BA5DF17D13494B2739328FE2544C893A43759C9D615C41E85B423DAA600B 4DEBFAF52824B3D296E1F47B666E2326FBE1CE1802252939F6EF819BE3A9338A EF3DCC2B84E3DAF00E7C0D45E44840F8793BABB055C561E0928F7AA01B5955CE E3D94A281F2D47B024D2DDFD1BE0D39263D097FF18662A63EEA49594BCB4F66E 0AD12249D6FBD2F0B4B51411884C235A64AE1E698CDFEED19765749F1FC5C9E7 BFCDBCDD7F23D394EE73F2B73C65F0EE1C1FBB4000D63A2D1947CD869575A429 65A8B30EB7019F74B2B2048898B27B0650E2D291C8D3337EE09BEE0A8421E2DF 0D986E66F97EFCCA660606F0B0A7B18339FC44C75134D8630C74FD296232B686 47F3EFC94CBEE564EFA1CE4BD13947B32AE6C18C198FF5E3250F0BCE7A292004 6DF7BD82592128AF3EB9DA27AFEF27878C75AAC551A9DD748DB7F58160C33C51 3B28D39C1783DAB4696FD05D00D9A676083EA828D833649055CCBC47D14234AD F2CE3C0A887655FC28EEACA2EA3258DD0237E1693F9E6B59815639757EF4D63E 837AD18BDD32B8E75D6AA862A057AEEB7201F5FED012C2C1FB3D9CEC057D3E23 5723187BF8E37A6C8E7C0A4D19A78654D07C72725AABEB05958EC35617411FB0 E66D2BBB10216B9AAAAC186CAD162E0F9D9953871816F1FD1A5423F43B2BFB5E 1AAE96834566EF0297E2D69CD19D6232CA6D5B6E9E9B7855796817F0DDCBA391 B523F461C746120683CA7F7D123BC715A1D1C4567EBCB3B27CC2F66CC022555C 53AE7E06DE7B967D6F0708224EAF72EA3C4C349C6C1DBF4E3F9EEDD8D344FF26 E0587F50407EF2F96B9FE5D4D1EED501BBABB525E43B9E34B1ABE4B4EE73C296 CE2883BCDDADF33E48C8A879065E0079A820107AC5321F61F7A1BE6A9706EFB6 598C0FA5F0C81C9E48CA22F86A9F437068711CB834D90CF79515BC7074C0E2BA 30E0486B9EA0B3DA075D6FA4BA44ACE3031E166F9BC8D293683C1D3B94A2653F 442958E6508B00EE81D879DD8EA003AA418A09893AD298C4708BC328A0A21A55 62177339C36961B86AFC97EDB88206DA6712353887FC431D60344E483212AD4A DF9EA4632745674A51067E5F308343E5D1B5845FA6A623BF4ECD000B368BA9B5 9400034817AF11E3E4A5F8D00368A93E5D6F1FDBC3CC4B0065208B275B9858BB 40E57BF7C98A4E8158E84538E7541FD3FDFB11A015951187F875A0D8C9B7FDD1 BB3FDB57F4C1D89B547369E1D52CF180C7C57F1F4ED0F93E98BDD54DE02B2064 30D15CAC1DC1FB2ADA7D048AEFE4290B7F7E2AEBFB3C7D41EA1CFA52EA515C07 520A359529A88CCBCA53FEB15FB263D01CF5DAC4096A00E5C6482841CC42AF26 601A8101647FC35955587C768B7FBC7214098B01C53092C4869F65CD1E0E8616 D6166662CCD0E2DBCED327A7C8A65F2BE7A6F2F5AF70C6722D3717C150F4BEA2 C50CFD52C8473E80197084FD6220447C562981C6ACC17A833B6D88E3539D02EB 84AB15E42E4DDDC5A8F8EC091BA226888EBE1985A465DADE44B283B7EC620986 1D6C8B22D7D7B5FFD77185643146D49B6A5EC171969360AD890CBDA38F7DA67A AEB2ADDBA1EAACAF16A2C76080764DEC104C99359AC7B606197DEC3F91985097 0B173D6DA02759B3406B1F05DB46A51DCA1B6A4D1BB709F5EE1C071553478ABF AD71F1A99A6A8E488B32D0575ACA020AA97D9E107FCB5C7BA9428CCD04EDBB48 A1346168107718F3C98978CEC898A3494D96C724C355F01C04FD608CF1B9206E 8507257264443BEECE2C8AD2986A5ED9CF5BC20F779856E29BC9D0E44CECAF16 38483464B050DF21DB51C9AC852B60362F3FEE49F54152E794DA4BB628F1F1FC 0C7700599029ACDAC782DB220CFC678E82C09E51694EE72E821ED4CE5B524F38 05ADFD38982E5B91313757B55FF58873F8FF594E177301904C33BD54DBD196EC 437060F04CEFD4648EC5D6CC04522885ED6F1887393B6E6836F3768C9207EA1D 9CCA8B396BBF77D4FBFBCD401206B629AB96091B729FF137A152BBC0485E49C9 A0BA737BAFD17F53F319C202A90CC8153EDE244AB5EE452687C496C2E77FAD68 21DDA15C279714E0F6864882FB357599424BC7BE8695089F89C76F12818825AA 8E1BCE2EEB1E038B02ACDDDE39C803DF4C8C0D38228F852A1DCDCA97912C59B6 6C3CC7E533CCC630DA6920C04217E141E2F32AFEFC294A58AB3C95B326EF98EB 56E3F430BC78AF90D61BD5E810C9887877E93DC4D95DB2DC1D2C3C07D9BEF1CF EE6FE5786CA88765C0899133AED7429395326A22D822027A4BC0475FE2F74EB8 BDF61C69C950CB72F45A45F95920E2412B8D776C6E8BD6338D3AFBA07793F4D6 7AD4CEDA52B8CA8BB8CB29DB49F8D5A920D1E167242F26C7D51FEE79677FC4E7 0E711ED65A8FF70517BB5283E057D8C8B1175934F9567C4C7BF479839C2CFC76 D990522E64E93579625F51A8D85B5CA4E3DC5ADBFE802F0B835F664572A2AA40 2EBC631BF40F7F53C12E1156048ECAE68DEE3BFAAECB70013B7DC4C2ACD5DDE7 D64C094E0FAACAC86246C5B9D522F483189D359DD65337DDCC6C4438615A99DC 1936E0C20D2109B3E7023F019BE2F006D12B5AA643C7B5443D73B7A3F28B5B7A D8B8417E5B747A27FCF19B5263D542D6F2E02918E0B7A3574050641104FE2711 33E011619A91AC3D293D98EE25C2549C895FA14F749E76BD4E81F4FB055B8FD3 F2F65DA710EBEEA9AFFA46EBD7193F90D3112397A2AFAFE84CCF9DE1EA2147D1 907C47480FBECB6A6EE3BDE00C63187143E74F35C2027714B30FD5F09D80C412 BB820C5A8A30F3F11D395480FB43C20ABCCA913E6EDAACF7338A68EC3277A344 D571E1D2CA0675C197BFDE9B37EA3AE6A43DF326E0AFD91D9514A962E44617C9 AF848839DFEE22086E4EE1077403E9916D32348D4810FD973B7EBC4086700F29 2F62B0D59571A52A88E6E8A64193228349E288173F794312189F2BD2E1FDCC97 6881C1921FAB253BADE378D303BF2277DF8BE6D1C7A56C36C6CF3D74C6520AA2 37333C8C0F4A8F1BBDA2FE5920997235C8C8651519DE875BBEA6BA56C065AE5C 6F8C1C6227971E3DA49BE96C70263FE2173A3363585096B304DA49E46BBF6E34 715C7F41D56722C326CEA609CB72907D0732EBF080B538518CF0CB0635B0F97B 625F051EEDE437AD14A05A84DAD051E3425871065E4A2615874C30C0149837D6 B5A2893A49D062658008FAB040D27101F1571AC352ECD9672E2A30027E204EE9 433676723D012E8CC81569EC240B50C4902C5D4B30259BA95B69E82D1B81597F CC48B22EC65F7237AF0B0A1595707489AC4452D40456E1247080B58A98419EE4 4BC1937D64008ED2B1E7C13D7FD261BF3B63F65D7EBB05A00F057D78554AB6A0 9AD437F65A25158A55155A9CBB0866DE98A2EDD5550590EEF0E1333DF5A974CF 39E4A61FF9F8802F030DEBF5039F962133D952073494FDBDB161DE14A84C6B62 C54A5C749AE60EBD07A0C29842706B74B75BD54D5092694B1325A58D5CDED356 CC6C8F81133915F05995EE1885991D3B14CE0794804F3BF58D5CE83BAFA05D5E A005736C32E209E08555E88798A225113FAFB91F3946B290859B52D94C011F9A 295A554C3793C20ED3E3A6B5BE57B533E8FD92A5DB0F67A048743EF6C1BABD9B FE787A1282E24B098F1276CDE25C6686E5455C8C84B19BEC816D58A5642E1660 8DC4BF1D7EB903042F6B57687E6D9A25058DFFDD5A55D27B4E8E30ACA5C11A90 CBE71DCD014E3ECBA954DE2EAE0E96BA275E6D5FBB2114BBA5D4AB02F9693545 A2F3307783FC641D1767C8AC174B98876767E4ED9F6E22DEF90BF7BA35CE7173 C7471745C7E3FFC15D15C135A87F38E96ADBDF35A36E86A8C30BA572A4A22FB0 365A02B3EFFA2491C3A9CED6D76E9293AEC8724E46DA15312444FF8EEC21077A 26E54E8CD9B077C81EFD5745973DC67C072BE37D4B9B7C6C3E6DE4E74C035022 52ADA17568968E18CE102CC748D679219D070864B2A465D6F4A2A0A4A08887D2 BDF4865CEE5BBAE5C764373A5B44EC9B399387F79B84F5A85A5DAF403F64CD29 6497560F918AB1D65397363498FDE113D1C43085B70F3761D6CFF81C64343B55 113754EA46D2CC06ABA93EE3D388AD8514579CCE2CDE11E14C9C1FAD283F57AC 607BD42A8DBDFFBC679BC1B858A95F2A1F2BDF280E8A19C98EA5E5FFAD402AA3 F03F1806AF305F072CE35F644BB0C095D38FECCAE226C00B63D26E367234E1C2 12DD8D4D9CD3264A39749A76EAC7E03D389D6AE33B068B2D42A947C2CAA69295 CFC49CF12D9898F5A54F12525B668555F97EDCFB8B0701A14DD5EADC49BB8531 5D6D7A1A4C78C895154F4762BD3F34DA3A3836F1B52695A064530984FDBD32A1 D064359695307BD42FF880489735008C405B63214F58EE970DA4F171BA941499 EB22232F4EE7B4E3D6063CB4FD10DF9D6EABA14220B994E5BD8CF96E21F966B4 9CD5A96EA1DF4430C46B043BDA6DB7A3C581A67AAA1773E8208E45F43DE3AE95 8ECF8210DF6A0C3A69FDED35554CFAC2403BBF4BB808DE0DA9BC3EC57604F150 17169E5A4BA101C020203EBC7CB27168348087687BA16096105BBCC82A0529EB 6E39BEC21BB348A074A0F2532307ABE656A0051F1B87C2B762074F7EA6A2611C 42244AC5AC971E43753FBCA6C025A5B9C03E573E0A9B42B43C2CD0E9FAE39E49 62490710A8175427337E393F80DF3AC43BF179CB829DE6331AB86422FA498833 D1C14F83E443DE738C7A9BAF36531D6FE7274FCF51A152B6447B15275AC70345 A51815AEB0C014299B15E880D593BA8631D656F33A56B5FC851AFCE74EB8640C 0094ED50A6931FADB9C20C453690BA4D6EC88ED660AF05316DF2186757B7CDC6 FF37755B746DC9FE45100117F1B8093F96254973D54B9DC21AC8B430DB9A6A5D 6CD60B3C822958C48EAD747F3C8AB10F47B29382BECC04D96B24B343CE86E7BB C0926A6D6DED8F9F5E9B05F1CDFD07501315DBF2522EDB572B5724413A8051F5 D84DE87C7D8C505256194D083FA9887166547D96576ADCB15D9A6A1A5886CBA0 46372FCB670C6E95E2EA81DFB3511134C0CEC3C9280944958B7FA2B00D6A87C0 D28A8C30A8F6D5FD6C61B152DA5D43F5525FAD3A004055212BBB225AB5601B65 D684E9B4CB5DB6493BDF74B1F75B12F33ECDD0AD8103F865A36F2309ADDD8BE6 229CDB25B3A922B591322257AB8A5BD62312758C5185D34B109317A6893CCC3F BC668B9E0EDB1885D9EF6A6F1077CC9B025C66F4E20C0BD2326F82BC6097A63E E332543684D7433A7FA613E82CFBE7D081B484E71B5A938FEE191AC8C9C79A2A 929E58EAA236E4FCAF87EF1A1DDE828A84D5D43C25F0CCCF3977C79DCDFEC056 EFB75D03777F00F5AE7833F0EB91BBC1B6EE60B9CB8D6E774F72745D21FDC5D9 472332B20CE5A9887550310CBA5DD35532E4E7A5C810041165CA595B2285572B 29AAAAF676D81B1A028B7D9503BD9EB46B4C2FDF24CE4FD5926E4FE2E53A0D75 167FBF24100706E09CDA5B76C4650F9CF9A44E95560CFDF63672DEDCA589D737 F4E48F28CB42582D4ADB35494B41A4D37CD59986AE9298E1B191538253677D54 E0DE24266E195A6EDD88B9A5FF4C6A64B20194E86C551953458637878E41B944 8299B195E848D4A51EF3AAB030AC0048C780A12440CBFAF8531859586C97E826 9FFAF28E8BCF0AA7188CD31FA9F1A4C4D96B01C8F1E64895F16CA9EEDE3B1E05 963CC6B45F0E5C5C5C62BFE4522E30CA010DD477C61FA989F6D0F1D3A17ACC9F 5A43F41A6015A9F942DBF8FDDDCD7C27B4FAC601C0415982E6FE6CEFA3F7C1E5 9A182EB2235D4136F11D6F408BADA58654A928B58A24145E1F4B0B996D93635E AFCDA40907CC13D1C1199ABB4F08E015C8B204A3A6EBCA8EA9A2A7D3ABFB00B9 BBD42CCAB8753DB0CC5968081A27F638831E8A78EE7CD3FB1D74C9355517A1D9 3AE0BD6ED674F581B398F1ADAF2AC848413BD4AB04B606C7D45C55B736E3F7F0 17E77DE215FAD7AEFC628062E0E5513C9F7E629CFAB25E14B4E04C0E96689AA6 8F6034FDE0E206CBAA6ED4D0799A99B41105A5C136CE05CBE2700B7B0283D376 782D3518644FE0AAD2993CCA0CA08A70A6D42ABA5EEB4B0F8BC6F729608BAB40 9D046BE1BDA44A9FAE8D534C365D0B8E6F39092461029CE88B843E33F93DC572 B49C727AF0127907FCAA339808291BDD960A1D65F83A8AB8137D48BE5D0C7496 439E9952B2667D999916C770FF0F8833FF9FEFFA76FDBD8DBFBD8673D95CA735 28452636631B8717E5081A8B41A192836A9BE01B60D545EEAC2FFB961D0EB73E 7E0C5230E9AE38CF6754B6C6C9BCA4B819FA08CC989430B849FFA13260691523 A03EB48C15A50A3A044C29BE621C4F8C124B53B09425AB326CFCB449759EA353 B569DC0D6D1D7DC29C8B23A31F35A94CC47148033635C787E406037B1C618E31 E3B43A9402E60720457F60BB4D5A31FFE1777644B053CD2BAF0D55DEA14434B2 F230DD01934F90C7D3A20363058D96056ADE53FF93A84B6DCAD0CA78132BD6CB 8C3C2C02F569DE5FD19ECE80891582B445B9D2EBD93A8402948A2BCB5940C75A 9B7E35BA0A2F8D51F41D89D1D221887023521F707DBBFC51D3935137B07EBDB7 FFFD435DA22425413DF92F516AFEB3F40BDE4BF90556AEAA944DBC5D8F17BAEA 67DD983C2ADD85D37289932A6462B632725EA66E3A335AEFDC40C5533EEA296F CCA86531DB67AC517090633AB4DD8CBD7D8AA219FB1D58BE0B12E85D10E618CD 0FC6A362B042C6B9FCABAB9EFDCE81702A0F8AD3C64E4ADE4DF40E88197752C7 C89B8481FA463C3845A4226DC7E7F613197D689A6956906D487195C167EEDDA1 F4761DED3428B835AFC14E6683D7B4AB3CD54E3EF8D0CD312D29AABE4A31DA9A 1E488867F8B981E11207ECD854E55DB368A9A5BC9AB5FDCAAB67C9F0B5C27EC9 EE29FBA4B8E195B8CD9D53D9B24E1830494B6085540F5467341D23C581FEB427 52AF14F88D590F71F3A43407521FEB0F6F6D3885BDF79C8EE7414346853CECE8 1AB8B35728A13632371CF9456A68C760155FFCD23D2029770AFE5DFECABE6571 15FB24827CED98A2E39C9F3D3C6BC168191F0A32E1D4A3A6EFEFE5331555CE4B AEF8502F2D20F1B561AEF8DDF61FE9A9C0DE17E1847B8C18342682BCEA1481B4 2E03967B9393ED8F64262CE87F5732B2A8F5C8BBA53068CE14AC143A41AFE6FF 7D1BBD08CF1C89C3F9DA27436745AC6117B9C68A3410C1C0143A97F62FF7EE55 4D23E7ED7EE9C31EC1913BC091E45E29E2EE681FDE83C55EBEA07BA7BE6A8883 80E50B0820C2537995E2AFA62782DE1E30EA87A569AB931838BD7024D297A690 106179136110A244859F1D5ABC6DBA94EC87C9DB9DE843AD2F05840D4F90E9F1 91C41D5FD756E25FAD3492C463315A556A63D97F4CEE0971B8B9D1BB30A58665 FD37B4D59A10F5365E3455A3DD3A732E5734279B6FDA63FE903CD70BC04D1358 2AC8F9DBBAEEE92A8A933410493F9F186EC52F3304D50037C96A419A281541B2 ACC0E5A9BAC9B7FAA8E0BD99B5251259A1A6EC8D3BA47974B9613948516857BD A3B84DF70AFEB122B14982FB1C3E88F6EC2284DB4B4C943A2854FF29B4AF65E6 974332441DD5C83163CCC2F174AC761B7C702AB6C9754836E8BC1EF7B6A5E7FF 9A86F51EA594E2C7CB13DABD156B477FFEE840EEA55129C3994A424F69AF08B3 97D1663E33175B1159446831411E2F8C8CCD531FC46BDB0C1B590A396A3780F2 FC055C5C752BC9DD17B1A4962727D4D255E5D6080661263244E38E1BE17043CF 4DB4CCA19DA7CDDD94988886604746B49BC36C73E168FE7CC628C9F6376D3DCB B4DB779C0F29537FC2F22A5FF5DBDC8738D32973A64CDBDBD0FC8E956431E871 8DD8E33DF06557E28B064CE7A7342FB658016BD92EE67A6E1F5389E977A95AC7 29BA4581090B2E4D7D53B20F56FD9311D86A9CCD61D42CAAC4977674C8683193 948DEB37FE15675B798F176632D7ECC56D9D48CFBD3EF0DCCB540BC072F887E1 2BAF8767F80C248CA2843E9BD7D3ED9C693B6B2BF7769821A6E813518A810780 EE9E13CC85358098797A1B19CE476831D3775D0DF7C7B90A8754E3D91FDA2873 858030879318D96CBD2220402A008ED4040241138F4A7A0AB8E9356F6D53F819 DDEF5FA13FB03DCC0C82CAE070E54A17C72B04A66EED7E6CF236C9CEA7E0BBC0 29F6AC55678C3469F15189A585AE48156F620A2FA122B4F028E936CF5710591D 17C0BB7B6BC53208849952DC5184245FA6CDDB9AE599CA076F3AB8CE856E5B0E 9EEDE67AA13E8F5089C2130ED6A053979E0C62A104CACB2741089189F627099F 42C3B82D792D7ED93CD0D63C87F0FC5FBB74CE9AD5DE2D81CCBF067BBBD2C323 411F1845C287B87BCFC5CCD50DDFC6B906E8D89D4994C8188D1DC5A40B0AF52E 5E8FF0F22280DDB503EEFED2236826F2EB9F5C3A23F343DD129A3D534D28548B F2B08FCD34D33AA861266F62EBA0AA48C85A0D4869805F235278E49D9BCDDDB6 7C293B8BE5EABB67E64247AD01451912A522BA99F82A1C50087474F2C2020CED DED7584E3356566100B06A492BF76E6D0914D9A684ACF99AFDDF909DBCA11A87 72FDDAB73425D666F55884D53D8E6DA6B8C1D6842B809A01BD806B648652949E A7D352FCC8BCFEBCDD860DC736CFE87B09D47267912558F15560328573F1E163 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMBX10 %!PS-AdobeFont-1.1: CMBX10 1.00B %%CreationDate: 1992 Feb 19 19:54:06 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.00B) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMBX10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Bold) readonly def /ItalicAngle 0 def /isFixedPitch false def end readonly def /FontName /CMBX10 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 12 /fi put dup 45 /hyphen put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 55 /seven put dup 56 /eight put dup 57 /nine put dup 65 /A put dup 66 /B put dup 67 /C put dup 68 /D put dup 69 /E put dup 70 /F put dup 71 /G put dup 72 /H put dup 73 /I put dup 76 /L put dup 78 /N put dup 79 /O put dup 80 /P put dup 82 /R put dup 83 /S put dup 84 /T put dup 87 /W put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 102 /f put dup 103 /g put dup 104 /h put dup 105 /i put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 118 /v put dup 120 /x put dup 121 /y put dup 122 /z put readonly def /FontBBox{-301 -250 1164 946}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 2BDBF16FBC7512FAA308A093FE5F00F963068B8B731A88D7740B0DDAED1B3F82 7DB9DFB4372D3935C286E39EE7AC9FB6A9B5CE4D2FAE1BC0E55AE02BFC464378 77B9F65C23E3BAB41EFAE344DDC9AB1B3CCBC0618290D83DC756F9D5BEFECB18 2DB0E39997F264D408BD076F65A50E7E94C9C88D849AB2E92005CFA316ACCD91 FF524AAD7262B10351C50EBAD08FB4CD55D2E369F6E836C82C591606E1E5C73F DE3FA3CAD272C67C6CBF43B66FE4B8677DAFEEA19288428D07FEB1F4001BAA68 7AAD6DDBE432714E799CFA49D8A1A128F32E8B280524BC8041F1E64ECE4053C4 9F0AEC699A75B827002E9F95826DB3F643338F858011008E338A899020962176 CF66A62E3AEF046D91C88C87DEB03CE6CCDF4FB651990F0E86D17409F121773D 6877DF0085DFB269A3C07AA6660419BD0F0EF3C53DA2318BA1860AB34E28BAC6 E82DDB1C43E5203AC9DF9277098F2E42C0F7BD03C6D90B629DE97730245B8E8E 8903B9225098079C55A37E4E59AE2A9E36B6349FA2C09BB1F5F4433E4EEFC75E 3F9830EB085E7E6FBE2666AC5A398C2DF228062ACF9FCA5656390A15837C4A99 EC3740D873CFEF2E248B44CA134693A782594DD0692B4DBF1F16C4CDECA692C4 0E44FDBEF704101118BC53575BF22731E7F7717934AD715AC33B5D3679B784C9 4046E6CD3C0AD80ED1F65626B14E33CFDA6EB2825DC444FA6209615BC08173FF 1805BDFCCA4B11F50D6BD483FD8639F9E8D0245B463D65A0F12C26C8A8EE2910 757696C3F13144D8EA5649816AAD61A949C3A723ABB585990593F20A35CD6B7E 0FA0AD8551CEE41F61924DC36A464A10A1B14C33FAFB04862E30C66C1BC55665 6D07D93B8C0D596E109EE2B1AAB479F7FAA35279ADB468A624BE26D527BFF5ED E067598E1B8B78188FA4BCFB0B51692D07B0BEBB930C6F0997B437E2C51B876B 61A563A2673932C2045833FAA35DB22ADE12102335D5DC734AE3AC5EEE6658D7 92EB62131E1DFBA441F53EFF9021D9D4C491F26BE8F54C61165CAD778CE8695C EEAF70E3B20C64D4C2B34A084B5770BAB2A974E898F62BFE90F132A37E2DCA4F 43E13DB13C94DFA8ECE2B7374827AE168634FA007F8981ADA046CED3448BF453 FCD9A4F194FA648F9FC0971734BB69CB73439CB0DD021D44A7C11BF295E81733 4DFBA460FF3D654F9FB337E99E6D66FBA87A817EB9CA1536C84833870E3626DA 55D48DE850D3E6F6B29DA0E7C9D681283586F208DB8D58042E3A7CE55BE84822 C98237911453E479EAB65AFEBA3F61A763B40E74535BE56C9D8D06DDF9441741 5C9D9D917439368736619717FAB4F06E2C329AE0BA411F3FD522D9C33AD8369B D7DCC9DF993778482F35F965973DE876FA19E109AA198A00658AB3F0D8E3DDD1 08A573F2D525202AFC57E05D141E6C0BB811E1FE280EEA002B7A45BB363AD06C 318D320D2C81AA5DCC842CEF66E7DF7670588CB39C9F42EE7763A3A17372432A 173BDEF7ECCEA297CCDD76A835C36DCE9DB8F8CB66CC71B4920CF5BF055A5260 5B41A5373BA6E4F63C85671D979EA5EC30D22163E6D206168A3827F465279870 CA80E6632872F721BBCC622EE4214BF723551C846765495FA9921E11FE1A950A 53150C3F5D8595958A47E0B16064CC3AFD65DA294FFD111153F4F233BC5468AE 69585C16CFBFCA32C4B96C161F47B56661DF84FCD8ADD3EC086CFB6BB5179BC3 A5469A1CFBC8620BC711F42D0D3139BCE4E38698D9C574450DB43B5A19FA6D54 0368BA9F7A8DBF96DCD0B8968CD194264E6DD10A958846C278B8C2BAFE7AAF8B 44C84C955F1A89A13E62A054BC76CABBBF6296DE00A79CD7C8C61C70F127618E 9975B59A880685E126F57AD80F8F4D376E1B476BDFDAC868FB6AFAD9D694B561 001623C4D9F55366D053B52F2B09EC08B81901AE0986C5350312E626006038AD AC15FE313FCEE1A2E61F8992AC00CA7BB7F997707EA377D37EA6FF35BFBC2866 A572B31491F9B80445685DBA5E62F166E80589F768FC95BBC79158C23B2F1BD1 25816F1486A64F76D99A638AC0DC101FDF390811B3C118C2D972B2E7587F6F24 7F1DB2DD922D237A7D18FF08FD665355CFBBEE799D3BFF11CD94CFFDBA3E725E DCF4CDE4307E3B199D91893A365D04F43A5305BDD2538E28A0788E061F3A621A B4A04E5063B47F0109C1693A284FA43E8F1EA9B68145FF51C005D3FA40713BA8 1879BFC3CAA881B9D885A0C1AA8BB9A8C848963020A5B15F862E7DCC78F25D7C 56437215999EB78142C128C6CB1E6E75EBCBB1E4614E8516FEB1E68400C61326 D9F9E8A41216901F77D9466455E2A0B45FF50B27B55A1E1DD4F243C92BA6B175 8F7695CFA1E91CDD8651AEBA3D258FFABA6280BF2420A98FA7CECD552D152CFD A8CCC94C032087A28D68332769DD2CB4ECECB15717C245BA305CB616CC72644D C78326E77FA602364A7B1630CA0BD0282FA781E14282982C1AD13479B6178D28 1CAA541FD3F4316F4FF81C53496DCDF5F86E0D7C870FFCD85B36C936B1E08D78 CEF3823546BE4329B97EFA4E2880AF3361C0DD67F77C8BA6F1CE3822B7FBE567 064ED0477949BDA06483F8DD04F891473C8FBF73A61F7C06B20FB8B5F0BF4B77 1429190979A4BDB29D77E94D5FB486A93B8B61DBC84AE06B4E06CBDA3A942043 9F9926F541DDE4E9B73606C3DE3E4E957C91D74BAA629641A6BA8E053FFA10E5 581F14FAA575EEAFA39C6534A94D0B1BD7A8ADD7B219900B9F300BF1752C4236 81CA46AEF5361701257648AB2ACC9825BD79FD6663507BED21CC7724BE327C32 5223DCD4A92411BD7FEBC5C99BFD4C77DFE394FB6D190CBFF7C94837CF66EE0F 0D98EF9BF9CC9B14365F33C78320085E763FC27DA1E52B0006A0019F56E35236 C5D3C182F26D23353CBAB3DF0625BA335B5B965A15119F1240E2D757837B195F 5B089B39BC8AE493CA98A6151FF1228EF46924021498A17AC49B68B8B555FAED 73449B45A818BB4BBD8A0D5910790C9824F13F5A0D0C07634CBF077840537E38 E7B5D57B328D192C48DFDF345B485B9ABF6664FB147256268155E04BEB5E2D3C B3635D6821066F8118281285E3DE0E31DCD1DD130171BDA0792ED9E4588D5A33 E9703E3A82240D7CB225D971B91F4457AE9A119DCE5670CD46344C1E9367F1D1 CF9FB36C5541128BEA31BD0E609170433D0092487F28845A5B234434B01BB2C0 FA3F2E8562D927A5B25BE0DC8313029969C9AC313947C924800EC92FF63127F3 0AC6801EC1B0FCB6C82CBF7370973B21C9C77CBDE9226278A4B5CC752FFECF16 8CF30E7B81CE53C3933AC580D848F9CC7F3377E0BA5BD88905DAE82BFD42E1C1 069C8AE5FEA017F4C8C9AED30585050FBDE9F530EFF051A780E5A7F7897B12BB E968204D5654BF09156BAFB7DF7ADEB7AE2C0B05416D085ACAB40333D10926F3 F5734F57F0ABAE2ACFFDD09DB497EFC9E66BEBBEF18ECCD13B09650857925716 B4ACDABA324721422EEC2DF66005CA076F3657A12537DD5AA5E456FFFD52633F 12B352800E09339568D2F9BAC471B58E108C990AA8C481002C442932469EFA8D 67FD87C9F4DD28C62EDE5C0D58EA1E0911FDF9ED05E032E3D138D01B63F27988 471935C56A7C7E77DB9E6A3044FE2EF9F721486F229836C139FD92D82057EFD7 E7FBD5DCF2F9889F31ABF09F119DB6C0A9C2D56FAE51962FA345E78D873BA145 A1CD40DF061187115093C6DADAD21C1925A83BEBE4279DEA1B78A0183E68DB58 70409542168F86094825DE53480D281324FF58158658D21B48104B83D6347488 819B637A785A8D353B506DFC8D58F57ADABD4B70BE468558A73CFC5D0FCBD1D7 ECD18F93FB4B5125C5DA18FE220B12CBD50A1ADEA8158B4C48E2DB42DC80537E 4DA231CE0464C56CAB8F59FE60393C4C305F6E1724126F765B54652B93C96768 15F572F786700305087B798177719B112B67BDF3EF0E708A48E8D6296BF3B937 A9288AA57C8243C6D28DFA1B31C331FE72BECA3916FD0513E85709684D3C77C6 4392980F0F2859D40903C3AB70270ACDCF7644032510BFDF0965B30E5FA47CA6 61B6A7D3A467FFB5405A7FC00134B2D5570C74C1E27F5433FEDB15A29C7729C4 AE8C7F7517718CD8BA705D76008CB471D250A77F7529AD67103FA172B2B482D6 E6FBEB44DE62F956839E878A52588454DD72377A0CE7DF791C2EB04D559C0B4B 5BC9CD13D4B0082F29D8C2EBC6678050F0C6982DE10D3295086ECFE64255679F EF0C90170EEE04D0DBC091DAD7472590E5D471239B1E9B8477B0EAF113B6DEE6 54F55398F7DA7C64092F33FC1DBFADE12B23FE70BA4C9538DBF1C19F4B947603 6D0B7049820B90804D19A22B8A9C3452CA601AE21204DB55787A53AAD6D42AD4 9F2A2E849AB4B1F4FC726D0776520D3AF92AB14F3B76AD31E91D47E8FA5EF826 642BB26EB6FE1BC93675AA40494148AD957B2077BBE240C1DC145C43F53C6DAA 4C5EAB2C91D2D3C63956160CB99ABF21C74C7930D7C9207E4B515293DC8B4BC1 42DD53FB3DB8F793BC0298044BB2D9F7F8588F267646F0C72181B900B8840743 A87717DE9694EABF10976EA2FC141DF70BBDAA4E1AED08ABA4E2C386ED629E24 AB9157BBC4CA7AC1B4016F927473F787DDE44BEAB16319C8694BA592A1426213 4DFE7039D154E7A5A969FCC2799A7ACA0174CADD74EE4B85AC4D62E1965FB298 EACF6FCC737604E71381B924D00BF62CABE5421C98211C3C01CA517D4A3984D0 0F5A24306C30224967BCFF64516137BE52BA47B283A62816C84205A296DD2CA0 9F39B6FD01BD2AFBD06F66A45645662F5FFA5A3E0C35E6627211181152CCD857 B2037555F204FA5B7E321873BCF4D84B1FC7C2942EA9F943D199AB7C7B12692F 77D30BF33B3F90905C1CF6AA6CF7FE2D7E7ACD6C296FF0AC39F9EC0335D1B1DF B812CE8A9D64B833E0DD307DDAF65E9A2B4E7E03E79229F4E183540846A3C337 B00DD353ABF3538EE6AE68D4DD7BDD3DA51B5097331BD48AE31EB303B66689B8 2794A8D350F0B588B45632725BB6E7B14D89336E71D744C2E3E3453BA5407BB8 8E9898D3D4D24A3DA0962FAA7BB24A66379FFB6F0AA077E3B01F2612BDC8DEA3 CE1BCB25ACC872A6C0A98576F9EA016F723A0AE79BCC936BEDF4C091BA9F4764 4C7D026ECEE22AC2FAA631FE4EA642570CD3AA905DD810F08F7FC8A9C26F17CF 95C05142A1ECE12979BBCD0F52C0E6CE766C904C0B0F37ADDD3D97154A2B3728 F09C77809BF1CF46E09AFF024993E7C825A777815B420E3B8997B48E969DBDC7 4127CF29407C0089ECB3D63F6FA89AAEB2E4AD2D8622A3E245C854AF13062EFA C52C7929CC42FF622C13B8C13631D09E9BCA05B113896E559DE7CACDD2655C67 BD760BF29FA4C51BF674A0D5DCA5DA2EC73E6C6101149DF9FFCDC152E7142CA8 49F9A6277FAB6B35F42A35DB82A564EA0C5989282966A92EF9CD1A37264207BA 59EE7146905948A128002F70022748117950E2A706EA9851B337B3C54F6B948B B4E92AC726D48C214924C86F27AA8D054FE6C9C471B0D7140CE08319EFA54510 6DD42EA378FD0FFFCE2458630632AD8130DFD8701080D5F73A0CBE281EE5C3BD 81F49BCB11458164A061EFB788F7D2FBA00FC53E40A99CEBA0D4A6D1FA5D0FEE 07F08CF70575185902C77FF048E67B00440115054959D952CCD88580C590EA35 6A0EDB91E90F8E0AEE102C2A4AB460257090496809AB12276D3A262608F356B0 45D393DD4DF0031335BC278C2992866FFBF0CCCA02BC37C82680888C95E51917 368167ACAC86ED36FD3FB26B2D17E375089C699AEEDA5B0F68D87C8EB6BE46FE C4CB0F4FC636F6DFF435CFD510EAAFDD266D9BD57D33F71AE47584805E14979A 3A374DC19A43E1065D5E4ED4C2FBCCA6C3BCE0EE791BC30630E08AB40452DBF4 9D2A21B4B01F5F210F3BB42FF8C9F869115E7A0D78F9D2AF68C91F9BEA8DC210 03870231F666E31899B1A24A0757EFDCD4E16C2E383D690D04D3D57E1F2CC85F D23AF5BE23B1D4AFFEE6F66C684B93916B91B64DD85D1231E3D60C8E2FBEEAE7 81C58E0BE8A0016CE39EF705F76D628FB8C08013D25B925150B95F7D0B814D1A A25C71C654D4F1B5213E05CABDCAC794BA0A1B9251A123ED53C36AF2177EFDFC 6AE748CFAA85A25946B2A72D599A076F5A515E3D741BD7119FC61C2C75C8589D CCD57D7A9B15E7279ED49EE50A9B5AFA22B902074B5D471A8ED71187982AECA7 EA542C62EC41C509D2B13609A07CFB15FB2520D04D6EBC1BCA3B0DD51C1EDEF8 CCFE5B0B5123AE854AA7BE938A8F8D809047DF93499938EABC1614C7714600F8 862C14E0A4C1767686DFC884E39A1C63B17870FBB98FD39041539E12338EC4FA 0BB682BFBFA5B748CDF535DEBA2828BA26BEC55B96868BC4FA6E288F3E1ED920 EEFC42896CC017F618D19B63DF610CA08FF6721446B8AB73D536BD3F5BD1794E F89F380D0E3EB181E0A675230FC8353B32A1DF6E7DE4EECD1EA87DF72F3033A3 B48097F10AF413BB5BE98852AF7E62F088E885A86BB07C15B1A4497AB0C7E181 7BAF23D1B31696AD74AF642F36ADB05A14F004EDB1CE6734E7FFC8CA049AB6C9 5408F91DCDA00C4B5022C29DE7B6A2D1C41C244E771DA6D050B14C08A8E3C8B0 D089BB4B68164EF281EEA9B6CF58A7B74B598A1E30DAD1F73D05D1E77647A6D5 673C6B83A012B15F373079C30E72523B591D29CF5F7615DF4B5F6726915A5D03 6D8233D313B1F8DCEE93FA749EEC483DDD9AF0FC7EB8C879930BE3BC58515B84 BEFBD90CD57E8377E2EB2984DF2B1BDA6A6CB3926BA821F58F9BCBA8317C56D2 6D37DF6AE562900695DC31004AF4506FEFDF6E8D5804A63A59D176517910C784 BDD6B7729337C7668EC4E393FFE08A158F0592B746D6754F5A97E4312AA7D376 A29C7D43BBBB8DB4CAE338FD76D8139D6D97F97F95905909490B48D37B7BBBA8 D9A98555961E734822D846EBC665DE1792F0F0D942BD7DA2D8DD9AB29470AA75 7D3078C021DF4BD24F5CC9B12F0C3D1DEF9CC10B47B7A12AD9558742B47484F2 DEFA8B5077ED0191C15E89FE58490107733572AA95D643F4FBA761C5AF8E0D6C 3250D597317FE0BAAC5CE4072E688B388FFD7D7F6D1792985768AEDD8A20255B 44F26FB215A666FAE804204C23472876169608AFE831886F8EBBF3F84A9CB38C D80226FBBB3C2B60EEF75F0E2C9A9A30F5618D13F0DD84B36F4F30A211896FA5 858248862E9F422E9E31231DE72A628EA00EABA81C59567D86F0E66BBA8587D8 A3A0133BDB30C74F2652CF75C7F247C7F5B01ACB9E8F892676A67CB7FA879D9C 6034BD216AA626EEF69C718CF5AE2B9215D949FB4566E39169C803A4122D7D8A 2F5D2A7B903E7A5013EEFE0558D472CCEAB9827620333E4B44BF44ACC1CC0E8D 689C9202A9E972D34ACBF7A1C7C97EF057D5575957272934E0E5800153C8DB88 E771DC89C0407DD9C806EEBF6BAC5A15632C1A72EBB047F2C6C1583A2D4F8F08 58D680B3F48738CBDC2E4E81B0BCE80470960073B5B0F69C62435F10FDD73C06 80A0FCCD1B3BB0629A62F1EFC982C4328B6486FC222133091D4AC153D72C3A7F C1ACF5B02AF85F63590D95DFA6B1F887B96505AB280053663AA8E9A0A8D446F2 CEB9778334A1C8469F5DAA99734EA85DFF2929FC6C1CDA3D1984283D4F3C8E5A D3DE3D61040654C0958F49FE50F737312B1B8B53FD77EA34B8CBE290BF448661 F76CE5533613360094C37932A6A7AD06E63FD8D02B359688E345E548DF53DC86 B16692D707E2901C0721DB5BADBFB271A7BF00F2F3F0EF70918E322E4F343CEA D18FC6504C697E69EA7D6BEB73EA87AD51AB32BABF794F1B22A6955B6455C114 9A438671F30970682719974FD0B71B2B4A699D0430027B3D3E6D8478CE522408 BFC9FD0A559944D24955742BAFF646C98004AFBDD735D457CA34B400B5D5D14E 55466E7F6476C54F49D9C240917AC429E534C51C92A9B4E52F5CCA11E3E5D3EC 6A0A28B39C2C7AC684FA169914A7ADDA925851D8DE6C750222591B9D98E4A209 0ECCF91AA890AAB75CF3D8F0651DD9440C5123C7F81446112B4B556CF001682C C660950D870234A2E96B373C97AF166027AFEB6697748F952C87360540B26105 E958B8A1C306BC1CEA926496C9ED819AF00EC1DD7AAA64E6EE21BE8A65A99CF7 86746F3D155D79AC812E1F2A5CF3C6F5FB9716CA5C9A8AC7E580522C311B2990 E289ADEE82099F2187F37CAEE490F807BAA4B520977A62DD017A7CF836CDE5A5 6AA4A7862E11757B5D67A28BB35E3989BBDA1AE77AB80C7E33117D6A9A353593 687B60BAE871DDC7B0E9A10758CFC7E3E972B51A8F1DD50546AF7C498EA487DD FF5E9AC8D87F2485A4E680909C07CED7254B5FF9E5433C3CFC55286B1431E39D D4912DC8BECBBDCE1B7FA21AEF907D5CFC56685FC47116F7F20629747F766974 95D75B64D0A6657FD0CFE9B56B912E7FBA38AE10EDD1E8C427772EC42CC100BF 5ED34DFC3093EE90D7CFD9E2ACD55D1FF31118B86BFC8ADCB490499F71946C1F 57477E88574FAE17B4DAEBFC8E100BEECB1E473C5A2F882A63F61B7826C3CA7E 44363CB33E5D8BF5E88F27F626B3EBB0C313D34B0BC69CE395DF99983E35D77A 2193C441E0107DFCCF424F49E3C7995B8A2C6EED7ADA45A1A33895E07F9ECE8A DD91AA4F5758CC030D3BB0D7C2E86A1531E9F1EDE5AE52F12AF9E91EDF021030 6E69FFE765CE505C617E6ACAC1B3D2021F1DDF82B3CE0B7E9A68EECD246AA818 2BBC9992E440BF3B96384125EF21BF56BF673D0256BF647CBA2A538438CA8292 89464AA423C9438EE2235BFE98B57CF89B1B1CAAAC22343324A63F913D1432DD 44FDB2E1F60FB78653DAF52BA657E5A48DE5FA5B4A419B83D52EBDED19355B5C FE6A57303C33413039B9C074187F2ED11E52074A6EDE22482DF46B624FA64A70 B2FDCE4D657CD67EB327D5ACA3460815649AB144744DA5C51BC6EC5E94B3ED1E 4F88997E850E1ACC9544239CA85A7D5C28EE249B966081BCFDB0D51B81EE6D56 DCB2FA5AB76D47BA98896B0D52934577760E231FE276629D9BEEF1179CDAE173 BA3E480FD2E2D1AF8D73509D1AA108C56E668E8A7EBA8B6BD4FF4CA54FF2D202 DE60493D82588C215EEFE423619700C3FD2BB73DFDC0CE2EB6EFE7C2184657D7 33692854C0DB7DBC388D061CDC20060E4076889A01D0FC9D6368F0227FA1183C 3E68DD3AE54B28808C93FCEF4F7C0B3555234C1B700EF5F9906B871B2A33F656 74FF5C9BA74ADE3B7DD08EACFD8252E5F7E00349EF090A0CB375E8E16C035BB7 9C25D612AA75843EEC123998AD8AF43960D55DED6653D8E881C6D6B6DE9624C9 6E9FF1D74AF8B3BB39CEA0F74E13B65A171F1816FC514A32D56A0F6D2947EB44 FF916B467361A185C9D3337A26901BFB6137903D9A89359F3DFDCF4F74FE20ED C37A1B1FA70E64B910E9E234F92CC6AFB9CD343E14C360C9A4D8349C125ED130 EE506B5E53C74FD4DB539C4038A5E99CAA46429F02E3DD462F5D2A078E2E8880 3AC7B4618454A08C8B3C994489449A5DA7ECA6B80FC084053C65B4574A75A1A7 4A9E7F86FEBEAFAAE9EB8F10B6FD73DF6E6B1638CD6F73FA2B3AFA49EA56A2CE 751D167118B3073746FC301F5E5F97C0EAB8B7B5DF5BB27958312CE8792281B9 D62301C147101F32634E7730E1697F6C76FF342770D635F417B26682E70FE88E A5178BC9F1604681EF2E5BD37937B5EE0AFDAF9845F25A3454F30BE34BD516AC 7E104033A567B4445B5BD6ECB3D71EF454E349BAF12C059A90B9BED8A006CFC9 A927BFFE206AD54351CB3772A33A83EEFEAC789492C95A15CF6ED00C9016E642 3D474AAF77F5E968CED1637F7B96225C7D769FDDD18B385E78AA60089D2BE218 14F2E47DCB504026811C1E1966754072525FC8554943EC9817AD0A7511F21CBC 49BA61D493584866C5FE4BCB22000E1F72D6320C7A6449559A9E085C10C3C1C1 3C69C0C355385948C822CB4CE2726DB4A78BC3225FC1EDA373C64DFDD4F3A932 C99C34F0048A3C8412B0660BC8E435D8AA311487E6766F203149941CE19B48E8 724916A0250AEEB0EA527CB9D7DC48EC31BFD11190F329FD642D18A4BB0E01A2 E6C59C2AD964A3EDDAC052FB2479401777E6A5AD02BF93FB0D3D4C02B8771CFE 95502A45F1E36516BE1715B4AF4B73021771E4808E5C95CF68E472DA9DD4C429 936DE6A73825DBFB6CBFB3287A2922926B80CCB38D51612027440CC1CF53EAA5 278D9AA61490D705A0F4F912C72EBC8E8FCF6A51AD580D483E3C5B830AB6A41E 4DF559E9E61B92D183B62B7EE4DDFB9AD14F244B19F6467B2BF210327845F1C3 B77577E2E2A206913AA4FE0D5574230B54936A34ABDAF521F64DD42274A8DFC2 46896952479D9498448B59DF3B31A4BF20AB11B425DF82F11024A09AA89D9BA9 44E7E118D80E61DBB935B2EE788E0A79FC95BF18E264413186533EF5F24C4518 BC7C75E83E12660CE2B2087851BB4DEF2263D647BCB2383429FA0239DD08CC2F B60EBD65000D268A1EF12570FD0777405DB67FAB4529A3E4C4AF4093FD6A0A66 5684568035B9B6B39C8B7263AAB848007FD44692A4D9C1DC972CA488D8979F78 D984BBBBBA63594EAA2147190E82EBDE64C2B4116D43A9809A2133B6F79999B9 22FC69623EC865A27A601351B1CD9F2534FB692DC570611FA8C87EAA4380637F 7939E2ECF4DE7E78E253AB42DA597D724ADACD23163F41DC48ADFCE89E241923 4F45B563D56816079967D165BB8E6747CF9C2CAE63438D6EB7AFEFADA73C53A3 524B8F33D53205E2C22C857836E2C71A87C3CE545814EDFB4007A69E5786B8DB 54B91E072C602898DF9CF4D93AB699101220A7B7A68192BFCDAB82947F7E1A77 7B5D8B2CABE483B87D0DCE7C9AE04DBEB4EC3ED1C74BC5B4ACA1EE89E1F879F7 89D81AC3BE8A1F61C0F0316DBD0363D193149EBA185CE7C561DE05C3E3FBBA9B 9BBE1C82E1D4BFA1F38F7CA850D101BF3C4B6D26D981CC71C7C9035809D17297 3293D1C5030219DF943C42B8947D2D8DD8E1D63EA94F4E1429FA6AE178D317AF 242D813B967B677CBEA4197A3418D647A90BC15F13C5E448C74E6D3563D7399E 8EDA835684ED87775CD3955D69BA7E87A5DEDDEB53E898A30F9ACC5707067968 90091B8862F83E3214191165AC4FE1F820A8DC9301A12E0C9B1706F0E655AD9D 3863E0D6B5700C23E47F17ED9F8D99296D4B84CF381C5BA776D5C210D193D22B 43ECC441368D803F4DF51BB88721F2765FA2DDFE5227846AF185745222E10BE0 95C282B5BE11FD21DD470705221403C776CD2199AB378A1B808A8D8378B554C6 41FD8C08EF663DC9B69BE65E4DA7E784D5C009E5F5E339DE43ACEAA8606ED98E F88C13CF6B104463E048B405BC87A01C776CE1E6DD3BD14DCBF84C4F04F2DC70 90B8D8FB1A7C23829AF0B4AEF88FBD330B5CA2C122FF88D5308C003ABAB85CE4 283382B16DCBFAA56FC90BEC0390D4E9D159B27FC4359560F0B3F2D2A66E5957 451D6A81889B299614E39F6F5DC8D2CDCD2AD0B2045804304FE4093DB8024F49 095952867EE708A43684090C3C08325950E5B6E31614FCB9BE4530EA4F7C85AB CEB8DCC3CA496E59DEF5F4D159B576C67D0F4E261D67F8D63446643C4AFDD11F 2D0B1A625F93E45A43A507D6137AE4D25A6AB887BDF403CFCAA4BE8B4F3433B5 0492A4E82FCF71F0F81DF6CF1412420BF8B7B74C3510E4D057A6490BA235DBA7 E2EAF838F9F6338EB93F5A5EBAABCCC73612D0EE7CAA32FBBC06F269D44429FB 9C9F270E8A461ED57EFE97D5620F357B37031C17DD01C129E42B7C09BEF447D6 363162F1A326EF50C9339C532FCA859F155ADDA8A614EC8E083863D68084655B B9D22E3198EF1476E7179201594ABF6AB55D9C58D3C27AD95A6ED28D89E30A0F 00896350907820CFD6E25B7B6A8D45614E3D92AA93D6795ABF514A58F1512D31 C97E1588372BF8F0D3A25E86926EE1F546A1A9049F01186A2E057C26730B2DDE EC28EB6A9F6A29EB6F6888C822AD5A1413FDA1990737E554056ACAA6358B8894 26EE5AED75B3582E857A487A954390629DAFB8DDA976CA79970C1486F80C7C11 F4FC26EE0B8B18BD9AC1ABC684E546D2FA829DA2BC619EA1BDFC27492CC0CC28 C232399559A1D5706909228BF0CA06301B36B87C0B5C761B1AD05EBE4A7FC4DA BE7C55BD3ABAC5095192FFD33D441120A6560F12D886AE15B0B1FDAC9730A7EB E54A1FAD362ABFCF5B72EEB279A86A0495B78A8FE5338C3BCF5F0105C66C2674 1DC8919CC9BF9F6BDDB04F42D18965C6D1C525E3E45ECE744F722BD6EA835732 DD72EEC69CB42B634D5FAD83C295B184110CD718BE52B7BD4A170FCE27ABABA4 74B32012F20F359D3F3D0C1818AE641D5DC4722221609DC3A78E826D68061EB8 EC734E42B9469B715D78CB2BE74E1599A47ECAE1234F8D278633FB1EE2D83B52 A7AA6B7E588819CEE90BEC43EBAE93E511E4BE18436657F174C2ED5957590800 F35AD6671FC0A352B1562E042140D3668E1239C90FF717CFCA0EA4BBF2679B86 B179F2717C27263E31DCF3788EE038D4C6FEFBC918C5313546C8AEFA73FCAB0D FA055D120659BFD99937CCC34D533A10B67BF498E2A52E9DCCF38ED40F7FC380 9F869127773514D198C61031EC04E916126227BC4611B8528362C78429C897E5 8943F4B4DD8C590FC1AAABD603D9FF15133B1729FFBB1A2B0975BFDA92A30CDB 3C3A59B7A6B5255460A7AB1F01DB3C651DB95A3FA4D79E8EF704954A8F52343E DDF4AD0DC6FF258118274C23A470844E58385F135D812D1EDB742CE6E33855EC 53EBEE6F4BFFD48A2230CBA4F30DCFC8F86037F942E6A253F03C2711002FF4F4 7027D7D1C0475487527D316FA6AB9E1B1D04A56E818CCC1D106BD5D9D2858522 92E832FD5718FBF7EC656CA84FE2B2794DBEE834BA2145EB1148FC5D57E818B9 B7AFF6D2F2B0816C301175E6DAF7F276FF495C0D0E647F4028C94D9610EE2B7A A81E66E07D2A9726CD469EDA81858F8C269797EA3A8CC018B7A6C2DBDD71E261 90E903120EC01015CA59F444BA8D7137D57E68672C5CED88EAE80FCF9E67C3D7 9B86FD5734278233C8E264C53C88CB7BEFE88BCC5384095154E3FC528520B6E8 94BE6C714F9E8D97E2EE980FC6EC8AB86006D9F9D24F90D58BE98982ACB96F71 C2D5B94CBB00AB07A1B132606A87B1BF710C9419EE196753E24E544DF7EE0766 D2DCB7CF6A2934B96D66CDE5CDBDD23DD60F163217F3372138E7B8A7FD206843 CA23986600CB3CB287BAFEA5D94479FA9ED24AFA727EB872CDF44C43E870E43E 0C9688D426F0C86794ECE9D133A7C32229ED93313AD008730C3000D053962330 C8D100E7F5FE25E31D0C590010427CF42A6AA682AB43A082B52EA29C6C5BEE05 2D69BD0400954CEF43016B51ED03B80A28A8A427A89F099EB2162E688373D231 E7E9660ECAE039EF1F61CCE716589A9BC2DE32CDA7C2D72292608975DE5B5F5A 41F6169DC5A8097530BB4AB624ADCF9900247498756A91AF1257A7C980A5272A 3C6BD101D2706E53202682D16518C0B9B221A90EAA867ECA1FAEA87205AC8648 413801CA4376CE0C7EB38A816C54402513E68A0CC783B352F0D5ACEB7E7F344D 557C8E732E089D7329DD8ED63F2A22AF3E66914F8907789972E8D5CF72865E68 43783B11F75566F28081B5B74C56F44C05BE7DF015143E9F05ED154EB1CFDD7B A99F2F535A258A9C6C0E6E0A2D4B91DF0CA6284C5EEA3263C3BFEE493E21F66F A68B008DD39AEEB566C4F4FAB93E8172FD9EB0E00C93D057534C2FC2DFA4E92B BEB8F33F1B685044467019470184DDDC1EA9A16F63DF5BF240EFC7B3DC53D8F0 8C2C168C317757418EA33ECC81B136A3DAF4A7625DBB9DBA43D053364B910BAE 537FE379B65ABF70D6A5DE9613FAC4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMR10 %!PS-AdobeFont-1.1: CMR10 1.00B %%CreationDate: 1992 Feb 19 19:54:52 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.00B) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMR10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle 0 def /isFixedPitch false def end readonly def /FontName /CMR10 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 11 /ff put dup 12 /fi put dup 13 /fl put dup 14 /ffi put dup 15 /ffl put dup 33 /exclam put dup 34 /quotedblright put dup 35 /numbersign put dup 36 /dollar put dup 37 /percent put dup 38 /ampersand put dup 39 /quoteright put dup 40 /parenleft put dup 41 /parenright put dup 42 /asterisk put dup 43 /plus put dup 44 /comma put dup 45 /hyphen put dup 46 /period put dup 47 /slash put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 55 /seven put dup 56 /eight put dup 57 /nine put dup 58 /colon put dup 59 /semicolon put dup 61 /equal put dup 63 /question put dup 64 /at put dup 65 /A put dup 66 /B put dup 67 /C put dup 68 /D put dup 69 /E put dup 70 /F put dup 71 /G put dup 72 /H put dup 73 /I put dup 74 /J put dup 75 /K put dup 76 /L put dup 77 /M put dup 78 /N put dup 79 /O put dup 80 /P put dup 81 /Q put dup 82 /R put dup 83 /S put dup 84 /T put dup 85 /U put dup 86 /V put dup 87 /W put dup 88 /X put dup 89 /Y put dup 90 /Z put dup 91 /bracketleft put dup 92 /quotedblleft put dup 93 /bracketright put dup 96 /quoteleft put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 102 /f put dup 103 /g put dup 104 /h put dup 105 /i put dup 106 /j put dup 107 /k put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 113 /q put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 118 /v put dup 119 /w put dup 120 /x put dup 121 /y put dup 122 /z put dup 123 /endash put readonly def /FontBBox{-251 -250 1009 969}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 2BDBF16FBC7512FAA308A093FE5CF7158F1163BC1F3352E22A1452E73FECA8A4 87100FB1FFC4C8AF409B2067537220E605DA0852CA49839E1386AF9D7A1A455F D1F017CE45884D76EF2CB9BC5821FD25365DDEA6E45F332B5F68A44AD8A530F0 92A36FAC8D27F9087AFEEA2096F839A2BC4B937F24E080EF7C0F9374A18D565C 295A05210DB96A23175AC59A9BD0147A310EF49C551A417E0A22703F94FF7B75 409A5D417DA6730A69E310FA6A4229FC7E4F620B0FC4C63C50E99E179EB51E4C 4BC45217722F1E8E40F1E1428E792EAFE05C5A50D38C52114DFCD24D54027CBF 2512DD116F0463DE4052A7AD53B641A27E81E481947884CE35661B49153FA19E 0A2A860C7B61558671303DE6AE06A80E4E450E17067676E6BBB42A9A24ACBC3E B0CA7B7A3BFEA84FED39CCFB6D545BB2BCC49E5E16976407AB9D94556CD4F008 24EF579B6800B6DC3AAF840B3FC6822872368E3B4274DD06CA36AF8F6346C11B 43C772CC242F3B212C4BD7018D71A1A74C9A94ED0093A5FB6557F4E0751047AF D72098ECA301B8AE68110F983796E581F106144951DF5B750432A230FDA3B575 5A38B5E7972AABC12306A01A99FCF8189D71B8DBF49550BAEA9CF1B97CBFC7CC 96498ECC938B1A1710B670657DE923A659DB8757147B140A48067328E7E3F9C3 7D1888B284904301450CE0BC15EEEA00E48CCD6388F3FC3BEFD8D9C400015B65 0F2F536D035626B1FF0A69D732C7A1836D635C30C06BED4327737029E5BA5830 B9E88A4024C3326AD2F34F47B54739B48825AD6699F7D117EA4C4AEC4440BF6D AA0099DEFD326235965C63647921828BF269ECC87A2B1C8CAD6C78B6E561B007 97BE2BC7CA32B4534075F6491BE959D1F635463E71679E527F4F456F774B2AF8 FEF3D8C63B2F8B99FE0F73BA44B3CF15A613471EA3C7A1CD783D3EB41F4ACEE5 20759B6A4C4466E2D80EF7C7866BAD06E5DF0434D2C607FC82C9EBD4D8902EE4 0A7617C3AEACCB7CCE00319D0677AA6DB7E0250B51908F966977BD8C8D07FDBD F4D058444E7D7D91788DEA997CBE0545902E67194B7BA3CD0BF454FCA60B9A20 3E6BB526D2D21FBD6D78E21A936F2E123C0F6EF41AA2266CF51B513EBF49D4D9 2C0C93820A37010A4C8990B3D2551EEBA36E8B8DC122B1432A6BA9A8A674CA2D 5F3DE1AEC33589A13F6DBEAFAF69B753BC0DA94017AD3D1CE981FF38A306FE6B A6A35630A7D636C1FCDB936F6BF93040C2E147714DEA74B7E32E97D4A9A10944 1F389DAD067D206763C22156CACF1B820A6F71A5AEEB76D95A7BC008F0470EFF D7D7BAE7545D44A16A51FBE1975162DB333B696716F8978E6E9589A86B824A07 95F6BDDC7A0FB3D7EF795BFE39EA4885E6E3173C865CAAF8A0BCF4EC66FA0B06 A3E04E071686DD0C578DEC9EDFD2ECF8457E0BBB5591AF24A8ED3316CF401C81 EC70E8F0D3BF4A21529B5E42A049AF60AD5B7DCC6E9908902410779460D7BA86 5C9C6AEED7A598A024222D4131D025ECA5B3321E2E99BB5B451D663E5E06000E FF852435FA696BC421FB7B71F4AC3F060A4244F4405709FAE714D6AA3919B086 308294FACD400EB49591DDADD04F5B5EA452CFA1356624091215D04D9D086929 626217F6F167FD5FE4811A15068E576E95B795A7D58C9F45283714284A4F707D 03DB209B0E863AED1651B06C0C5C5724AE78785F5E53B44DB3512023D9C9F099 4D01D2A9E965FEDD523240FF4F6ED5767302E55364365DC3211967EEE2D1AC50 EAB6A0858F98FA558CD52801125FCE5AAEFF792DB7F0136E5933C9637A43446C 66440D8261366D37231AECCB3A698B06A710FB158506962A878E73666501B190 2F56955D3BA06250B07649EA1DA47DC3FBCAA5A30C660591F221D0151ADB4DC2 C46818A2303198B31801A280E4A11EED4850180894982876B3A8584593070EA5 F961147137F29D045457258BF18BCC391A19576D3109BD0E196817A78D644AC9 3C186C5D61871F9B990DEC2B37C42F545EA9394332C5E3D0703045A58A08618A 7F4F63575A2BFCBDC5A2EE53BFE40048BB6B9B5C4D965AD7A4AA724555AF912E 23831F300D9CECC1CEF0EA9555CA1499627A4ADCB469E474B04D7B31570E34EF DE736A27654BC2ED0944D0ED61182FA54E38F264C3FB64A8DD7089A77D455F89 E138660A52167BE25CBF95474A18AA51CBFDEA411CE8A715B0E10331BC9D294D AB1EC8F0C2B4AA56382543DA98E3EFB9F8BD51C8A9DEE1596B6F059FF7CB4463 440770329C5A76D56453CA3BAD039498DAD12005FA32C6E12D65C4367EC66D45 28536DD4FA0479979A64A0421ED987382C0BA2941A66E22CE58FEB41FB82A57C 2B9E87B17D39B03D2D140996B03E144207DC3FB89B16DA8AA6BF0335B1459F87 CBD5AFCCDF5778D1290B91DBF38FCE9009A72B6EC01E7B5A1BBC22C9A3DA10F0 955B51AF2CF6CDCC737F7A6A9AC8F43C313C12DE02D6D281AD503BF9EA7273CE E8B934C0238CD6D7CFBE61E649FC900D27981DF9FBD9FFCD66918147E883F119 FA4813CA2426E774AFCBBD227CB14FC2D801CF69AF76207507E59ADE2D16189C 1AF84339766A71803F1BB1196EF5ABF883224F00F91157ED18164D367C06C4CD C544C73C504AE636A10A25ACF8AB1444181F7EE62BB17F2AA1DE3757B5886094 ABC25D7F142C2F08895A4B06ED0445D46726A6D4518E002BA8F3FF2646E920A8 0B0274A17ACEAF889AC0F39A2FEDBB696783758D612268B74D8637CF00C7C14D 8D081011DAED60AABE95476AA9B0DCE3311955DFA2796DC14E2F310CB4AA4B85 7448394B86C9BE2D4126610FBF1F1B2F3746FB90A75F647974535DB5B45CEBC0 7576D5822804E254C7323CC6C277779781100F05835671D32EA6557C1CC603CC 552AF750697F26B3B746540BB6C5ADBB6A7F94560072FD8A1F0E8A352762F2D2 32C5942DA29F3B61E534A9684078C428EA682C6E9CCAACE2ED894282BE43797A A69BC6C5F064949128562CEC1E598673B0764CE69A26BF9941B78117A9A586D2 9E21F93EFACAA034EB1A17D6ADEDD5B511B1E60363D295E7431C9494980BC599 22E4BF0407E08A0D614C61743E667298A4F69D502859060637E4F59AD9688E3B 0EAB705CC3AE3A3B4DF0CCBB33A92D7235DFBC94DD373D1FF1D38C7F4A6F1669 BB49E93F55C5B890D295A3CA22212F061C7764929046892A1DBB9EE17E6CE5FB 0229D451CEB774874B705ABD2F1191262932D5ABDBBCC616ADB2931496918BEA 7281D46DAA22477876A2512F3FCBFA48AB0CD8CB6E2E3956636FB6D4394A9F46 A00398F18CAC9F515E18AB15D54CF94B26E0C292B747F825E49A3E8683F328DE 4B003D66FCC94F0369024127AFF4DFB89950EEB090DF2CCC172D9300E248755F A92E5A9660ED4D8D0F1D66EB214BD9EADFBBDE38EDA3EDA801B4E034CB60671C 664786BFE090822216662279921128301988D14684C8C2FF71BD04D40F912A96 AD2AC306FE3C4905C149A4090D146233579DAA74E462C695D674042DC6A72FA9 6DE2FD30CAFB11C08D6DE6572D5F5228EFEE40BBD76985DAFDD5854926608B03 01D505BCF417B30C8D2FB15A41D064B56082B2FC1AC51E13169F90DD6AF2F29A F684C1B64E498194A80963D7F89BA113A6DCB49406BB15DAF6CB95FCAD5328B8 D4A805FDA41E7FD6909E65BC96F4A2CE0051271880CD0D8EA0C689FC8BB39435 FA03784AB431ACE16CE411F48A98E560D942EAE4382B360AE1CEA85D392D806D C2CC7888FEA83D6F10DAF4866C57451E4399E6DC90307A2C2BBF452AD115FDC7 D55FCACFE385B9A99F156D472751F8156EB65C036BC28F0218705639FFD2E454 3751DD7E649982625D679900C8C36E76B9251447F31AF56901CD10076D565DCA C2D8503E604D9C5AC382CAC1891C973302645D026F2DFA71ECE722A456DD269C 2FA07856BB1D393E14A96B5A30076C4A31CAD65BAE381D9D673A97A847AEB26C EC7C12C64297F552051F3C8BCC430A9FF2DD7C91B9C903ACFF671C44D94B00F2 CD253449A091CA3F7336DA8A6B11DF877BD07806CA5C38F8D123C2C2609452FC 7285FC5EE7A9A4A41399ED327EDC582607614E24A8ACF7A8129AFED960CC1CFB 1F58B8E02F49963103AE56181CF2E88E783F4C387C4F49676721470D8B9D41FA 9876A906429572169D99C54AE768658514BA2FAFA2D83E425F62440BA958388D 600BA268E30681984CA3EDA2B23852D2EBEF85DB0308894E9E572489ABB1262B A847471BE73232FD38DD68DF2D2CA6D67EE09BA1F6B9C984E69CD00074D6B41F 401238F355B68FEE84B0C044B6692E24A6A3299F4928910E30E6B9B6962878AA 78C937243ED0E68E9995886B11BBBBF8F621080C0F7137735A22B88D25EF2AE6 BE2B76D67E7BF5E04EFC382D7EC65AC13387A2EBB6E3D1248343E79403E909B2 62D6FFE76181838C154E05133E92F8456943238C59B4802F094101D4BD5D30CC A3B0B03731634D4B5DA478752E468021C38400B22DD8855108070CBC141E38B0 216236362E0CF7C6C94F8E682BE7FE38E9496C718DA3B22C74F41A322A4CF1BD D51FB1DC2EF8DBF800E63A8EBC4461E019591C2FE5B8FB89D843D19F76E82E2A 91566F034F5544E40E485FA63DFB4A83DB0C4AE10CB64798086CB356D3E3A329 55C9B3DABCBBF25B603C48A50C7777F1A034B5864E9F23498963B5FC8ADB8CA2 650AD80AE033B4EFCFF15625BBA7F70C10D589FD9F87BB6E174058319137B101 F43DFD3385C77628FBFE8C0E13F17A3646AA6C0B02374C2AADC68F86327637CE B2F2C445EE8B4011ABB8DCB31113F0814616D93A5F310F1919C819128983D7D5 9DF0F434800761BC5F43C7B7E86A62A7BB4BB4C6657D653E5B3B46BFC073BF3E A92392EE5949A7FF9F1A1FCEB51E5EAB4D59278B866E520BA571C5C1839D8FBB 80E4AA2E51F2B1A5347218EABACD0083F803459E5A6D583D740FA82C445594AA CBA7D6576F39F040BE021734918E0AD2FC3C672DDEE53F5DA148C7A3B28A959D 7DF128379DD2C1C354DDFC00CD60AA72860DE96FB1ABC1CA06E6B6DA2FE8D343 184C7A03C32AC66B6CF68EF8364CD00593B50B567C686122E702196D3A2C8647 E2F02B2AE73371B062E15E565815C2CF90A1455CB2C322CCB91E7A13FFADE8EE 8F0EE48F2AA2791311A33C84E4266801361DAE9907A9B4C7A80549E59FEDBF93 D1573B24E86E8A4581305AA11D9CA399BB34BBEFF7FF2740044B9B07963F5C71 834B4A09BB5CCC60AD08AA084E97C1832A5AC2D850EF8F00349D7FF1882ACC9A C4000307DC71B0AC37CDB5FBED339C6C21287F79CFA6B6A5E062C33456E56EE5 D50677C739212A46718E2792AA09AC1344273F0F3A89A7D59131FEF172F59FCE D48BB833711498F998AE7D0CB480DE994B76A4B605AE9CEAABFDB2716F0E6BB6 EEC919349529943D629C243F8569DD70721E3445CCCF6DEE8070515FB32CB7A1 944A3C6F242605630194824B1BBD05D053B5FA2AE49B1D3BCCBE39C1411D8864 FF6FA8F82583CB0DF62303A438F15B98FEB403368EB37C34C5FE43FD1E829029 511DE455DA5672F39B98A7BDB2ECF99F2E484FF5153281C8AF121DBECF25ECE4 DD9E07C83D0E24C7F70FB41B6C1418B0472EBE2035B7B06516C4F51D635D1D2F 10AB3057A63EDC7C44E440C5DB32DD205693425F49AA1BDE0B737D6AF01F3918 087C4CD6D4E826739E4DC746A6A58B6A45FF9C9F2845DE409C8CB17599396DC5 BA8D641F9ACC7EAF3A82C1A39BB0B6C2B69BD2E09D034ACBA5E34C4751C1FAF5 B7D00A584C7DBA6F50357CDC09FA1C66C21B7B585C8C0C04C5515DBFEB96FF6A 389FDB0DB0193951EF119A7B5DC3317957AB0B235273B02426F6AF53A0C7FB1A 4F547F0CC735156414EB33CBBDC6247232885F6AD906B1A814F134DC815017FE EA6594BF84F14E5C507133722266882E1ACAC0B04E0B4447C49373D7F8D3823A D2A511A18AED5E1D21A231F9EE5608C587E7DE3D1B6F2C0BED81FE4B40A7B04C C0D964D9B421140EF9BFCE4100159B7A3766AE13A2D9B958DE1BF30D3C40DBF9 ECAB6670A885B45677CEE294F1CC9F89CFC73DA5BA644D98B4F02D49FA77E755 6E8740DCC22DCEC4DEFCBB895254F484DB325EF7AA7E7B4B5EA4538C201DC55D 60DB65291FA3C05D7985D3406CE451CAC888A6BE975C5C5730B064D732177ECC 731519E439D97D8E2893F040C8C5728A9E98C147B5C239C6A6394DECDCB46DBB 02C2A4D7C0AB670E65BECD8C420C5532FDD198EE4883E563E6D109917B56A028 7F2660487F2DC49B4E294FF93FE1722EFD9CAE7EA41AD461E32D54A40E4BD564 235D91A35B8CABE415F1332FE6FAAFA4844134E240E13017B36640DB65E09A84 9B4F80107A147B66C4C7A650630DAC27BD97E859D861296290D36398B13659ED 30786EA54A5DFC5C38932F6774EBF6553FBBA7BE160EBDF71ACB83CED3DDD6E1 69A9214B07838868D811B56D37602B97203E1F3BBFC892BE6412EC8A895195C7 18DD3878C25875C1C963A4E8CC4D170F03C3F9A2B25AFAEBAAA977587E996DB9 66B9F0B8101E72C9919BA0B8388B8A641E84D671C688772DB9EFCEC1A06D3B48 FBD5E5E2780B3AE9137E35EE4C8BCD971CEED1CC3866DE186315C9D0369F0BE6 FA27943AD63DFC9E37849FDA168E78815BE4A6030768BFC79B694BE50C9CE2B5 D3F0468F99B4179ED7E1D228222321C0BC48C8BAEBF20FD6AC4E2C4DFB48316C 32697765E4DEC4E2AF1AB1BD0BF993AE888F901AFBEAF5C848A2D6A3AA203240 AF089279CA0B323FC348EC8E04AD78F37DC30087E329544F47E37331CC328F9A 40C85BAA06CBD3758EF6D91B1D35FD7F49A7D046FC94988CEEA924A82BE61004 7A5AA85D5BB9B3EF81593F82E8B0CC490DABE4EBD4DE5409DEF4691175040B07 DEB329916F92FF6422442629F6BCBAE4D8A3F0AD2DA530CC67187A670116DEC2 ADB194B18F851F74E50A1BFD4B1F4CA4D80867B759B245A9B48D1BB0B50805F2 B04B079C214726BC5E00B603CD81C42583471CBE43265EBCC2E72B5616D0E367 8682148C8BBD49D65F78F665769733FAC90810FC3D939C809ED41F8F1B49B7FC FCC04063451F138B7178934E3B21443DE417F74180F426AEFA691136DF15EC5E 6C7156A505CCEFA3ECE87C9FA2DF0A9A08366867C114BDB0DC9AC620E07E2F7F F08100CA47EDADFEF9837AB60B0F3BBFF5E4D963E89737B3E9F8C2399D62A821 84D4294B78D690006DC5C4A235920524C22D4E2E75EF5510DF6B75279AF30956 E016D8E4DA40BF0892B68E95243648B50C587DF69DA328D21EDC15B10FB9019F 1C21F02BD2B07B4BB3B1BBBE7CAF299C4F53A7AF8B62CF737D2DC15AA490DB01 6A1A6E75EC9E1CF0458B63A0E0683FC4011903C08CB93D421DD51C423351748F 0E3E1E66BA6DB1B281BF1D83B87708D3C6342CE06BE403EF44E6BB7BAD058203 4010C606724D0FE02964F1F448EDC02D55F4D6302C47C2B5B28FE771C11CAA0F 8D0204954C0B8C0C65C63545FC0165AD0D326B779B4F95334655E0F1288A37C9 13EE3DF7E661457429ED6F40133601C4E69E8E7500E3661430F131D759C165FD 7570BD61795005AC92DAFA06318AC1509553AA05064CB4D5BC7CC0385C56D10B AEBD2804F5F361F203236817602CE01E6DCF2E0DBD39492E3D65E5D7309EB885 CF64095CA6906CCF815E3EAA30698A81228DF1DA07692D866DB201E00EAD4E48 E2575BA6B695A8E41F2581AE76844EDDCFA86ED1546CEF56374DAE1BC91BC29D 10347574F3AC6709F66799D1D88699A6AB790CA7EB749BF3011FC9A5843AE231 4AC4F5EA4E97901EE4270A5EB6C792F7A9B1923B48252F00F7E059FF12984C9A E5662EDB2F2CD4D59B30E50A97E0802753BDCE107FEBC5A348B36E0D36B233AC 72D837CD3F69922114E300B954F09180AF58AECC9540C34D9F4634423CCACF11 125E46D74B1676AE57939A83C77B1B46B90BA4CC1E75D0AAA4BE309C7D127E10 0CFE31D1ACBD46E4CD838EEF41380ECBB96C91918451A04CF1880DF394693E8A B2DA29B26797FF165570EF5B1700F42671A2553BBC97F765D3EC0B1B75F1BFFB 296677656105D98BFFAEEF5603F8C76E567F2F7681CAC59FE71D22B6EA92AA82 94797EEB2913F49CE74EB6B495CA774CE170B2908EAC858CAE67933CB8506B21 B3433DCD6ACE1CC826D48814BCD6BFF5C13E9F18FC2EF5907AA952B9B66C3459 5DC23BF793C9A63680C3475D32D0AF6F712446CD44ABCC7DCA4B53D046D0C8CB 1915A9024D24D304FBE47B6B75CBD7023927CC60F136588634A482ABDAB8B560 7BE700495E1BB55BC92109FBC90B9FB78A709F906AF69E084B8B76A3E900B241 A0E833CF71616F8FACCDD482748BCC9EED2D4D72DB7D3C2DCB07C3A9A72A2CF1 50E59E8B1679D6232D3DD0A5863D984AEA02DF2AEC816F4D1F31CDDD14C99E5C 39210C98A785289A7E9E23937A77AF4FDF1AE5AA02002FBA84FE94145AA40516 752D7D5B8F189C5B70E09990AA850B10A86F1E01B577BCBB025C19B4A20CAF8E A6D5C526DABC99ECF8F4A9C3AF463CCECAE7F6298300CD2A2186905AD0B90B0D 64465961B50B9E5B76C4D0C94BA3C2703436E39F0EA337A0DC33FC5207D764CF 9AFEF8CFCE78E25608F7BBCDF2DBCE86361805CD7534B1A793ABF37429CEEBE7 5F9D6811C64DA3EC9A472DD608FECAD87F30A836BCBDBB346256B9DDC45F4649 37F012265889CB110C5B89D1D1CB03D522E0241DAEEE4E7A0589940F7E292C05 EB685A7D259D2261203BF92E14AE0A5C4B8EE345B0EFF2D5AB6E63201D9B5859 22E64116D31D59AAF237D0FC26A3D77B2B38F605456AB970FB502C6DDE166B62 3EE4E3F18C52C4812BE4EBBDD89CBFA077E42B2F426C4A18684474A6CA6A5407 2535E1C1DB08E330C50080A1CD6BB6C6E4F7FBF442E3BCEB63FD3686F73DF2ED DB8C4FE417AA5DE4BA6E33CA35C735E55D0C4693F42AEE73AB32FE00821518D8 015CF13654D1C92241F47A58507AA5D072BC3E8245EFCC21D80EA2B36D6811AB 15F8151FA2F916BAEFF61EF58F8098897C91E2E1BB3738718B36D9AB951D72B7 3A7E1B049DD946F2C53B5FE3B9A44004AC29B9807A89DFE954F9F75DB949F7C2 E02A53C61A6C6304C18E327D8D17E502D7451440E02E17829C908B993893A8B5 E8DA8A8203F615839BC2E5C42CBA42EE835A1D76518058349073870B4CF80D57 7F0C6027CB34647A47A485B0626AEC308035CA5C6F41619122EF48B5D0CEAE1D F08FE2ACB687D893885CA077C05D30F4FA5F2692443C65E1872708346B5C7EF7 973EF391FDC9E176E88515B6F33A0FF5AA9B07E9030E362C7838A92A94A71A35 58C836D8D8D5565814533D21635090DC7FEB59F822F3928DCDE293A11E8C5498 876C93032117357B32ACAD3A71E184BCC86F0731F8DF6FFB4FF71CAC0585F10B 4264C52F74B1D7C9AB37C2CD8144CDB7479F2958FE214031D5E4658B35B0EC58 18B8A9D2685524FBD152CA7D02A890FA7F295D11CBCB0E1662158B13D0E3C979 FF1D130A96A1F1CAE3BB0427EFFCA53AD1730893A642D6C7913CC944E0AAE281 5C1FB34D8FE5BD0B65914B6758F3623901A9ADA112BF5D1AFD0362DD9B21F8E1 EAB590759CEEC9578B6B626B9BD221C89B48E9745A1E5DA37BF94EA1E81611AF D2EEE138CA0D776E2A65BDD918E11C3CF5B6D71B0BC0E58FF41DFE0482D0CCDB 8C2F9AC7AA93B9482A13FD9BABF7BB0BE01F3E5B90707337D23F1984AAD9D2D5 C883EE1A7DD2B0A84B02C73C86AF924263B78E38E6A5B98B433C406898CAB93A 0EA63BDCFAF4A368D136298012FC0B50253ADF38FA56780C68AFF5561D68ECE8 FCA27DE51A4360098B65ACE4105F122BBBEE1AB11A110F9070B6A017039D59BC F54F95FEBA8FA97179D619A76335E69F5BC41DD105FCF177567592561E51D3A5 FB0F9DCAC0EA94865AA42E2A56EBC88D1F7F8DEAA2537B917D0DC554CFAC55FF 6633558B152C4DF2AA2D5D55CE401B0B56317675EBF15C2A7D8EFD28AEDB6EAE 0B9E42D8CC8A73CEF8D005AC7B9D104B02E9FC5FF89875E8825BE8B03C1C3048 7B8579D3E4DC0883A28E0029909D5A5E70AB51E56382CD19796FAF5F5C2B7464 8D3F85E09195A8A8BCA4757CD7F4CBA5E0F17510315B5A26582F5439841E212A F62A5C34B0D85F37B3BA8DA132B6C468A7723C8E0BD02553D0D27759D0E2358C 22317EA7E8B7AD1000EE127F023A3683340492FE2523CA72114AF53DA436D2DF D5F142C55B8BF2B23FE158CDCB24D50C3D4A0BE642702C560D627238833D1525 E3E7FC448C1EC80F6A66A163AAC62CAFDD4D8B87E10940B3C75A14C64516F31C 43FD0F9879FB4491E2AD7D61D63BB643729CEF2A775FED235A8968A99D9720C6 23D0EF639E26128F393F4877E4590AA209C067EE8D242F32DFCCB6EF87DC4DEA 84D7D73BCCCCA56355523602A02A60CE2BA40E6421F851CB4C42ECF0DF344FFA 1350552004587E95F0D181C883EE2908A0F48A86059ADB746A1BE7CF9412EC1B 2ACA7DEF2CBBD1ABA060182D7456313B2A2776E6C12ABA26A82FE8CBBFA5E43D 38F335F0E46B66C1F33F25FD4EC7AABF5466C5F34C00BA7FED5785DF024A614D DB67101253EDEECBEC0BC7CC89B3309D27E0EDEE928FFBEC92EE835BD2A710AC 50E11EE5CFDB0805735476309209374D0DA0B3B8A8691EC1BA0B22DEE79B5874 FFD1169DFAF3317371D760162D2E5E1E73EA7961C05F5DCD360E4443ABCA9B6F F1C52B6F2170ECFAFC621B9B45E53F52B303869246487440F3D53F0D8237F0D3 21F2C6A1CCB0E778835F6ECBAE779B02A4B430EE90FC9E639B4F21EB3B8EFC70 1C3AC775BA52151982050E2D9078CABFB0E77BC1467D471D70BB4A81F2D8CE8F 110A35CD8F1B4E657CCE94A1FA11A68BE024EB644B132C316A09706B657102D3 C609D216BA0FEEC8705A3EC5C2FB2C97D06E0119FAD3E0C488B3B5ADB720519E 8D779F642BD1C1C5FC160B0F75FD0EACAA229465DBE958DAFB1DAF86BE7E06F7 CC8BD1D023696B692E9CD4A2C64364F598670F888A78C30712A68FFB2F50C08F 8CD4517F9ACC6E6274BF9527C25E59A1CC62510C3C159D8513707F1B5FACD0C9 81895C54192752B04FE92BB6DE1022C44FA2C6216925986DAF611A1C530F9D3A 8730F45CA4EA6B21B6CF4D44F6E3A10B637B3410F4F5537AFC5EA54218E5379E 958FB904E65DD78DF1CB9758A1E675522D38016154FFB4CCF8DA7419616427D4 D94A28F62C0F82704F4447A42E43E8BBC8AC451254EB898EB86135DF5DEFBC09 94CCAEFD5C62DF5922A669E29A06E55ADAE0CFA13C441278BC9F300C60A0D140 584AD7C102EA5BA4E140927DD70440CF0A04D4CEADE1F89935A05219D71B94D3 4BACE59B6ABDCB6EAC73BE0E2E0E2B3DCEC436D37C2B31D93BAC0835F6C6AE36 DA92DAA5DFEFF98AD88A3E39EA05C70517FD588FF595AC8ACEFD43DDA0EA0716 AB97DF6A66B63AEFCCA311C1FD313DC6F1DF3A28CAEB6E1A878AE8D2204F13C4 FF7F4BE6C7F6B1148D101EDA2E7EF5EF64358465A45FF5153097A0702C49FB5F E772C974962A409AED231EED738A8441B4B74B18FC5C3E0D5658627880D15E24 51C990612FC6EA4BCC7B19432120D109C7A0EFBCEE31CF2D0209EB582512B8DF 1EF478EE907A66ACFE0F0EB2367D30BEC512B3E13A77863F05DD3CEFD962EE21 BE78478EAEC1CD6A1430753DC40E2F443F8811F4981FF7102D5C01EA61D68CE1 70F92420E37FE3437858A9FF956DCCC9B991D9CDBAC0918FE8C8BFCB5EF28C3D 75BE99A302790CDB054BB82CD682D4A2F524371E3BDC71A910A873A7B5DA1748 4BE4D3B0E1EB80CC24992A57F83BE21BDFD31D9EC9D0CCDB014451739397A1F5 1F9C90F10457BE1731B9B53EE7F2CE5CABDC82B8B6077759101C5B04AC0F9FDA DF4802620ECB8C7170BA39F7709F9AFAE6241C61AC8832688DAED86B85988790 EC41B088CDA53DA646EC7D66ABBFD954E176F26E074A1EA2401A3EE979EEFCE7 52F7A151B1786CC4159D94985D8D6083C23CDCA11C30E0D3A7B07CE8C005634A 8A737B518C8C436702EBE49D0709B59FD366603B062A10F82AF3D2EDE0374987 4E14755E9BFBDB3D34A87F2C6659E7737B33A4368D556F1AE0FA06AAFD75BB54 8E69DA1B393D7A068985A537EA9B3046AE397BBEA8006912097A0FF7A8588BFF 9D306370D71E9FE625F0746E526444AFDAF8F166A336EA2C0E28298ED7E06A80 6F1785B62EC3DE9C104CCD52B318F2AE555A00719C43D68D70ED2451DF86AA08 650D28ACCD67CBD33738E7757E8E2B0CB0093CD2F99FC78F082F294BB4F0B99C F9231F11FBB3A1F2B5E12E7341CBBD518A1755F0BD5F99A1AB5558D08F531565 D8FC143D9BD83DFBADEBD5E592869F85CCB38513AB28E8DB8BB3571CC6E3CEE2 113B83F27568F2C06381E202A5DFD81182803EA2C9C5A42E025CCB47B9E28565 1DE94328117528A57CFE7A2F947D137963798BFC38697078108C2DB9CD1172D4 9C24A9E5CE4CC4C9588851EF85982ECC428B172FE186743B4EE44C89D2A8C5D4 684D87E2D3E10E71887716F92D393E197D04D0530D7FD4D38344A8EDA3EB656D 43E2F0969B674A3E39EA722AA7E0F0FC15F7D815ECE3C0A014E08259EF587C6F 102F09659DCFD708E8460D6C139F906538DC8016DC25992B79DE18A8F05FD56E BADFC6A1243D6F2B06B1A6714427A9D045DC87743ED9E41CE1ABA13060115199 66601D96EBDBCCC874EDB0A29C1730789168BA13E312860F6F86465783C6A7D1 603E86CAF75E0C43456D96124174117EC1007ECF9CC357F1315F74A733E787EF 9E3B8B0B75BE57C1CEFFD6B1B874D71EB8836894119991DCE9BEF9D8131CEBA6 EDCAFAA65297048EB2C7DBD0B7504397BCC1F9814637EF5B32E1460EF2F95BA2 27688CAAD92327EB9A0F938585F0C4E51A9A47983E8574836AA1D35FC57E139B B2C82C969C76E3DC60201C072108277DD312DC4CF49CF87155CF50393705EFCB 2C14FF684DF7ED87626156DC32C14F705AD1D0D211F915CC725936768787EE0D D642776251D24F43B3768D71DADC11E2AACB273F54C4F56099DF7F8A88B07516 6575E551FAB8B2DBA3C0C1E04B8A06F4A8BB65814BDF54BD6E3BC7814B08FBB7 456270E8C6AE4E821C7F2CFC2E5D63F5C1A11DD4C9E22DD675E80C52018F7499 E826AA4B0847AAD1A6DE07CE420915D8D6818FB18F2A9ED99D88926E51C63059 CB3953AE041479135B2E9B47BC35FDDC36FAA07882784CC78DA0D1A0C9A011CE 9FAF50F8F8ED0D2C9F7019A57B506845A95C8C5B84F758D82EAFD78EF15971FC 959C85DC40A32E9C92B313AE6C9B6A01363FC91D7820039F5C6F6C1F688198C5 13E8D588B4A71EDBBFB9E6C75D7162DD1791E120BD3A7F227A8DDC3CEEFE0070 8BA14D2D951331B13224D4CA86ECDC9F9A87B85B8B601B3C023490F8964B7340 BE5DFEB44D8129E4DF880C7DF46B8AD43AB8258815A9FD0161B2C714B2F070D6 A7C9C5DD73046F66812A64213663B22BCBE30E38EAE068CA839627F0FE89F632 02FB4569D8E8A6E59914F1E260A60BFAE9FCE805B4AC2715F06CDAB981611B52 32EF37F9856426422D99FD191A1EF1D7FC9ED28E0D6CC158B0B0A8F72B1E8883 7143CACDC1F27EE7A0C5903718DC849403863F1534A7E23EBD7AB5AE29EBF935 E959A974A941C1745C5770E6BBE7EC5FD30208774B8772016D316BD7690C6A39 E8E20CFA76F939AE4B221A169A00A5039FA47A7B48986DF2CA1079FCEBAE747D 7513FB5EF38DC36342D70A9FB49A0614E2BAA890C8D785611AE96FA89A6435BE 44B1BAD77748A9B60AB93323E2A1D3CCA01ABC0D6D96CF72BE10B771A08A7129 7FAB1C32C18830CDAB687B7D2052C021AD63857B72869941B712B26073AEA9D3 C4549815A3CA2185086AE255D46057E9313C7DFA2AA8B5BF9D81397B3BF0E764 6515C130474C7EEE18084EB0526182290F1DBEC691B8C91407C71F2A3E85D139 B3F9D99F4DDE8DC25D5FE1920C0B143C205F743CDB43A3229A1300097ECC7E46 036B57C6BF9E874A4F057629652A8120CCC58E9959E740D4DB634C6546DDDCF0 2DA9C6338F2ACEBABDEF4500005A99B2994DA9A5E0A3C08F7A632456A6483D4D 9DEF610FAB840D0F62D874776B5C97AA423B447CE40314ACD46AAED6A25C5CD9 8488212F7FB72A3955AAC14EB0C7615D40B8CA426A45777F9F93703C616D035F A8893F61E04B7563E499191BDB49453FEA2D0879280FBAC652D9ECD62062E10B 2ACB96844957A3A5AD5A83791BCEFECCCBBC0B6BA1A117BE2CB9A71DDF073411 AAB14A231355E9B0527A3C3EEC4D3DB9D735DAFCF970CB3F995DFC5875A489B9 A4E96CECB90A2482626FF34C78B3CCFA0317DE630A588E279BC76A61B78FC928 3D59E1D3D24211BB6EB15EFC7E8B9161510B5F0236B0AD1B67F3D088587FD0A2 DEBACC3D547E0C12CE9FA3706DC50DCAF98065832E0A8A169190B86076EB2AF5 25C8C3729E794BB0DCE5B4C9F11D740DCB0D0515ECDFDD48C47D3EA852DE75E7 F3DD2718CA6B094A53260A57344AD125174EA3399A5F22C6B11DAB632D362C37 EFB4A16A2B75AFE418BE039CDD72192BF9A58AD70FC104F589DC6023F37EABFF EE3F006D95FDA92FAE72CF092A6709E39B7EBADC93261FBFFD1896A2F1E0256E 912046D78ABC3F29C67E6E5FE61A4BD9B5768AD9C04D391C982C34E1A64A7C4D 78D2E6F3158996F1BAA8E4016B8A28FADE2F30B99D56FC8DA18E1B26FB9B64BE C64AC01227309C20FEC2826E4CA827DECDEC2DC1A3496813687176BA5A3D5A7F 932655878079E87BC60DE43BA4A5DDA07452BA34C90EB25ACBF6223117D2453E 469E1DD6A30013C02577C1988AE297C336BE4F1B2DAE1357DED4C281804A6428 4A5DD81EC58E0AE4F3C4FBCC5871C3E5D608475F820178F239D20CFE4E231C43 964D005E6C195073D311DC283EC992BBB401072FBCCC4DAB98176F964BD7BB62 16A81626B2702B535AAB78180A766267F272BCADAA5FC72431B484A55A6E7F9C 5B088F33F101783661FDD5A09E032EDFFBC01C84B6610F4B91568706ED5A5170 18A33B5477F84A6111FC62FBBEF6D5C81472649C512D4F2FFD5180F716AC3F4B 5614FA76EC6889E026DC2F3CCB57625A2640E9BDB0F65B0CBEEB39F0B52C0016 825C2ECAB8D9032B8CEBB878B6FA092BE3DB7E31BD8682E70D248BADD12044AB 0224ABE40A44B8FDA4DC83A9F2D2D160EF0129C080784A4DE95117ED716DDD43 12718062C87CC52DF973C4FA70F6AA8D618505C613321A4EA9FF19936D6D528B 4ED3A369F72E6286DACA19D79149584A0E801CF8D31F16452CFAD37F3021ADBC CEE4E44E510E11683CCFBF492F94053AE23EFDFF2161808A8549B323FA990E0B DB3943BFF22FC11B667A566E6AA953A16F5665C1801372F140867E4FB07E9669 EFFDC88C3EE832487A4F1188C5CCE060AD8C19E1E147A6DF06D860EB7231EE5A CE0E60D89DA003D46A4B0010514D8B80FBDA3B70E8DE17492CB746F9C082F69D A4016DFE38C223D0D747F869FDCFD4FC890A4CA1ED03A6824E9BD3A3A425086E 7539FC47C845D4AB453DF6D0244CA6BD39582044E57A68A8A2438B4551341355 630C439BE3347890E771980FC342679C4A0966EAC43627FFCC6DE49BE98A4CDC 0889B5005E7B092ECEF9089AA1BE5BDB65154D6A91CE4FF1DA94455DE9219C77 80F67BE96BFC01BF65B5BFD30B6D8B2A362F19E3C822762EB978D0D240524934 FF6674B1A8A82D4F91445F8A7C3E1EDF76C2E982473D8983E1A78DDFC92F2A44 601C75FE11876E16B5CDF51F2C83CD6105AD789C510FF8788F65EB276649518A C21E696A2230E409109227FBB7567875C1DA79283C403D427FB85E43DC1EFDAD 3C2431F18FFD7F0AF3CD7A374A90D822E290CDDDBB5375B2F8F572D8914F73A2 54A28EAFBE8E14A890CAC1D169A8B63A34452524BD16EA3EF971293AA6B6C9C4 183D333D4B5162B9072EDBC8059187FE1F442201A1EAEEE0ADAE144831093C93 C429DB3FE6CE765B9BB1EA433E465420C5E14895A66A335DB242F65C7E59F2AE 7D9383C11D7071009F3A33819274FBC5940BD7810905B2E03E296CB0426076F4 8D990685E417AA6F506F6F376B39BBCC77EF7C9E9BCA8FD86D1AD8C189ED73B4 45F86749BDAB86E6ADC9F0BAD2A53345EC67C39740B2FC90007C07F3D7A73DA9 002F0C14A1AD437ED53C620D2EF261EA7BB5CE7C8EDE7F3DA5098F95693275B9 FB4BC5E77D169043AD6D1A513F94BB1DDFE211DF215E4E361F8E4B6335FE0417 AA9424A8D18E814FC58DA5A396A84367751D40CBF433A2B2D199653076D96462 69437612EE5467879FF9525B3A883F73A4E6764AE567A7FF370EEF9C212B4992 B72168A66CAC4A3FD99CE692586F5B4B9D2B7D21B6554C0E465459DAF71A6790 306811839A44C1AD488D12DBCB8C92D43B063ADE522B5F8A8E084BFBCC285144 A046FBF740FF21BA2989FB62BA2963EB453D354C283AC28EF072D108421319C0 19BCCA5379CCD8DDC7D5B125F319296A8C21DBFE593983B535CC755C875DA4AF 3019EBBEEF27471D150ABC30169BD4A812D17674F1213973460CB3DED092B767 9E39F3ECC64AA8BBE99F8D1993AF8BBF23263869CEF635B1306583415B38C171 FFEE3C2308C045A2420768F8DB732C0609FC8FA70C05ED8F3F99345236FAC181 BC8999A8A905F7C36556FFE953C262375C74CA32F8DE7536951BADC2EE670CD1 4728D3422535D68025B8780282F8FDCAC51C9BA5C12905E70812E6D1F6784A17 811BFDBA1F876067DE0CE7D7828E57EA63FA1695DCB934870DFE60AA06873CCF E7FDBAEB63524C98DE54C571AA8B601FEF90E8644358FB58F5230EC403B854D8 C42A40CC1A10C4472579F3C3E021FA569FE7F95FBC924E5622994E56763B8323 30F135AC7A00F4FCE208C0EE882213C393B7BDBB3FFDD71F697C78FA1A04BD8F 90920E21A78873EC55EF3452EEB8DA6284FA050B690C786B9A7922AB97BF6E8A 7E6261DE73497A0C517544A767918FEDAF76EFF5B3B4DA485AC3E430DC92D3FF 3D9EE4026880D9518E81B7BAF9C40536EA9B8FB04E92B6757D96206C4C73B5B2 22E2A432BE7429E421FBEAE789154122B51033F44F79994E52010AE397C76BBE 1BE2CAB381B7D06E3E5B83B01636F1AADBCBCB635383759893DDE83EC09D2866 0A9800E85432C0416178143D39B91027F7AAD2A5929D4CC2424921B2D3D734D4 AFC2BCDCC61AE4D4BE4A371D158F1DEEDC8AAC215DB1F3FDDE37C7D591DA326F AA5CF06CDDD1D11CD0C8150227B98850A6CFA4CC750F4429BAB0B465065ABF5F F6D30344C9146538F55B5D04D25456FCF20F28543183547C9698DCFBA7CA76A4 FA0E21538F3757D249154FCA75DD1A0F2FA7B54E185ADA55910EF3BA1311931E 51B3D2D5669970E685D63436B4111B1930F50ED4596983DC7F24B6C1CD274709 3C5AD44D5F1F717F0827DDA6FC31779E03451CCE6581EA63906C5903ADB60FB5 58CF0EDFCDC734868F0FF52F6D50A3D00852F3437414981A061DE1A2810F6CD7 3FBB2992814DD9D07BBF47B6FF64D0CADEEC28809F0E14D26D11631B69E4E86F F61D5C222ABFB3DCAE4D0EB67883F010ECF1FDBA7389843B4F095151ADD31A3B 0CD56AC195E0DBA0923032149E8EDA1C50B3E0A425EE077B8A2A29599E4E2FB5 88AD74A4F775391403043020CF400E1DD5501E9997B53083A7E4CE64AC30108B 04D4BAAD9C844D73FE0CBDCF782941A00C97CA55238BE1B7058EFA8917743553 D4956EBC4E7B27DA51CF9F2F10E257DAB7C9887BC0A8F14C57AC90CA41684588 C09FA2470863F5D276D6C5ED760B77001CD09D838648FB5329E81AC30C12D170 57CD73A1B56AA117DA3219B65C9DD97FE44F096FBB39FCBEF43FC119CD2CE3BA 6F3596F09526A3DE25B1FD0DB419B54AB405942CB45E8638E741438FF46DE505 1B021D08D0BE0F1D8BBB382608F0315314311511D592C2E67CDB43F8F654F123 047C880153BED6DDCF16FEBDA6AA567BC4DDFDC051DD41D840627A88272AFCFB A3977038B42BB43F7AFF34F945ED97CD4CAA28400285E3C54E4B1032C4373F2D 6047C757C88E5666BA8D639B20959576CA6F2DE064C270EB5235B22F34F2B2E1 8203AC15DEC0FD4DAF4C7F3BBF81DEF38569BD14B6D2A255DC599ACEB73199A4 D7EC53B536510DCA20D410A662AFBC9D3AAB7A8E29D08EA1DEF9C0FFE4394532 E58D5EBA9D542398E959DFC18E372A412BD39F066DC861F34C2AFBF09B49B5F5 2A8EC0EEE77FDE43FCBB5A090D7A35A1B6A0A0817887D521EBBEC240369DA220 002585EF3EDFF284E701D458DBB45B2EBD4396792A1D39A235D4D6D83B3C92D2 D5A8F9F9E22FEE2E1F474B3AD49DB905F4BECA2FF798CAEDF46727E3D0694F8E 54A9B24BB9EDB35B7C98E9A5761F24448F61A4531499C23AE231C0ABD40CD036 059E3AAEB136C9B025AA6E6AD9DFB5C17305526A2693DBD1C87D8AA06436283A 64B8B097B6CB0AC6B42D18149FE0B634C0DF78B15F636B0A362873A6AABE22AA DE6EBD400396C61F7E0D84BF337098715A8405D42739C9A8DD911A638946F0B5 5AE24D47E0420776F0A51A1A3260C324D5B955F837081BD40467B43FF49A0F53 F658CD477E3D693822B73CDD1D652D62B229AB824BF7EF7859DE7B968BA04A61 09721624BFD14914375E77C6B446425778AC25E6D3CED4AB1CE48960DB110BC2 8533B3CF14AF449266F3EF4967FE45803C219D35945707AF991AB90DFA0555E2 624F635CFF4078F17E26267807256DE04D347BF3C3EAC4C98071E382BA24834B A854D5EBFD26AC126D7340535C4F4B5547E220779E3434C177D56ADE2F877D96 3E0031162A79E93E1B32A5D4A9B1E1B084DD40C0528CF9AF65ACF6E834925E8F E55F834BC5E66682D9A0D03B0FC3880AB92CE17A514A6C7EC7F2DBC7456BE9CA EF4158ED3EA6782150B8652BB2CD96831F23D8307449F656C524E13D58ACE7FC AE75E5E4BE00EA846D7FF44E459FE68A7668EC9BDF296BA04C9B66D9568CBAFA 8738509ECCFBF89027B516523B473D856FFF695566866A8C2913042097EEE2C1 5A71C0637F87F2F38966B1B2C58FEF7BF8B1D6530224CBA844F17C7BB9F3DF6F 3B6EC807C829954ECC2154DCAFA8D4D7B8329A811C535E00AEB710E52321B987 21AAC2B5539565BE2998C8E5BB6296C7E71B5D126A8D79CA73A7F62F43B30207 97C94BFB00EEDFA89950F54DF238B96F769B6371DBB0734C98661E47C60D02CC 589CEEE0909C749F652CA0E9A2677D0C2EDB5B649536A779FE24B05E4215F205 F530ED74402CFCBEBC403CC0193FDF5AC5CDE03D1066AE3429A4DE9C1C59A833 60A28D4D79FCDD3DFCCD26A44D5B05155E7B5835C6A3A9CE6DBC1AA914EB4488 69278FAB7C1BAE9CE7A5578CFE5D62E6F79B90D5D06BC7F8F774F8E2C656A588 C0DEFD1DC89F3EF374BEA792F3DB1059BE3D0641DDBDE8D2106F5F4759AFF313 04957B64AC47732ACD4A38FF44FE013E789C824ED88DED3677B04ABA725DE702 4BACAB52388AED136B0857883FE9ABAB90892B53E1B7E4EFDEB6FC1BCE2F5EAC 400AF075D169C0E8908B0C6DBD1E20F6EF411F2CFA165AA7E322D759A48A23E1 CCAC729AF13B5E0F1CCBD8F0F802AA29700D01B458DB10134F632C381FCA54DB E4A2DCD5E8238F43FA5B4AED32D96617990B1190A694BA4278AFEEF4141DA69F D5A608DE4CD199E707725DF2D3C2C73FC8371CE45D487DDBFF68E409408A1526 0414D8EED328047DE4C0167AA43BB59648C3D508192162311911CB8967648A80 FD49CDEE09F3BB1B2EC61EC04240A2A13C7C982D7BB3B0EC7A4293A1F59277E7 A2E37BC6D60B7C3E54F1EAD546C00886BE531D342FD87514E96AF0BF2A234B72 FC098986D17B15EE6E48473AC2C13809BC553F40CD996DA5097E51D0C672B9B9 9715336EDBE4DBC6BC13262B40632EDEA4B7009A8CCDCFDC2940AAD46B4866D1 F73A1BBE9924C27B26B47D099301831536E2F639BB5923B28F378FE54526C0E0 FC4BB97B82A7D2FB8FC026B94FB59E0C380E822219665658EE5FFFFE35E1A60E 76A38763E408652622F59663C28C1C54B1682BD65C8B6D361EFBDE7A0E66FC6F 280FE47903BF24384A4F6A0EFE626622674B39E339956FAA2100C2B1DF034255 EC78CA3AA823EC18F41F15F824FC4289E023C7F728E0BB9527DC9D7E0BC64054 5258C4F6022865AA71F385BDD97FFF354454BED8A0C7B2FD2D4500CB71D8C0F6 1C52D9BB9E3BF0E6C5AA89C8FE8E15D573868EC57A2EAE23B387EE619C3ECEA2 FE453FAE298F27505B35203DCA7DE015A38F81459B79E117C5D96530D6DEEF87 04A07821E02B8648EEEBAA121D5C70D85B870EBA691AAB08B5F8DDD1CB6EBF8B 8826EDB28C81ECDEE501651F4CF88C866F1650348263F427580D39E3CCA3A794 74567A537BE66020F3C4FF8539F5E8AAA79F9D9E22613B7E52561D39038CBE68 D9F848A182973C9FC2EE7E75EAEA13217CB7F607C41029E2B4B0DE86523222F7 0CE81FC1DB45737814A119C76234549F23B6202E67B8014F11E5F3A01F35195C 2A19A13318FC85C8FF881E72A143CF17767A320872D06426319CA23F6DA6A7DF EA5010078C939A8687F40BFD9510B69DF6F544CE8C2FA75D82F29A9AEF4AD59A ABC1E1CA00F79A40C6C71729F58FF5DCEB26A4C088539C7DC625C961F794BCE8 8431C1015078027BA87AAA95DA109CB9F467FFB69290FD7D36B055176A2561EC B9CD09C9781152A0428F28CA06CB762C54A84FCC6FE132C9F85243749D1F505B CFE451A2D1316A4D2A4F6E729D06E6AC1089344AB486BCDEE96A5BF3783380F5 4471203EB837ABB300AC692F16E88E959EC7E8C8C1CD3AAE3901C29E27EB73D6 84F066DA7BF5B3F02457F393AAAFA6BAEB747B9DA89577059EBB9216F9DCFEFD 796C7E3C10442EBF3353FA091AE5B3C46069851810B0681ADD3F7F4855381BD2 F6AFA687A77C84CECEE21F9AA3782EB7D94E5E8C418B451150A7AA5E501F6554 44FFFE8E759BD5D7407B7D99649CE27079960964C6EA21118C77149263BF0568 527E6700BB2325812F89C929C7509A91F8D4B96B7D3FF64822B0ABE4D55F48AE 435C1E7663775975A9E16EA3CBDE7E04D143051505540ED08F7FFB6C431EF0F0 1C37CE4452D4796F05C3F4BE838AAADB7EF6751EA917D14D9A7E58C9B526947E 00F69EA2B651F4A869E7B6F7AD075E3C1DDE7C256C4A38C25A0D2DAC8D72881D 766A39D877F0401F62B2A56DE81D6BAFDC95AE4B88126C184C3359172AADFD4F A0C0B7655F33F372A022D54FBE3B6AB4226A4967F0C1CC1CFDC757D1B88F63C6 337ACA3F14F6F45D395C1CA6B936A430502F991CA1941C0C63A85A4A2C48A209 B3095B7141F8A8FA520E919AB1DBCDB6A6AD556580688FD24CDD2116466D434E 47444EDBDC6EE3AAB18D1E5FB9C64A5D9AA510F186D81CD1DE38B50AF76B403A 375EBF0DF5502BB55B16C89CCAD06C1447534501B8D344CB30B4C50E29DC7488 1DBBB826274D1C8942D925B74BE59EEE00FF7D6D7B96CCF0EF6B5B277C38FA0E D60D470C7ECF349DEF56E05BDFA18EECF5E2FB9A621AF1B88660FE31F08D8474 7F618A7DDAA3C284BF789D65F5E6EBCE81C2CF36BF510F3230CD18921E14EF06 1DF24F6E8FD4A2E01539C09A27BE95F97474B2636E1D60995EF9BC1FE37A2F11 4F0500D496C347041B6DCC553DD6576A145C9ADDE6E7F9700D63AAA9B9AD4392 11706CA76123C09F00DCB7F959EB346F8B0B354B56FEA4515A588E03720E9BBA D8264BB8DBDF97F68A18B5C4F05490EB9D2EF35CE7814B8730BFE6E5A103F078 F5620B47F434DD3F4FED2BC571FD975B70CBA36A1BA851E2DEE332BE98FB0BE1 9A2E87AF124F21FF13F63D387F1497713BFA1719A76BB7AD34A0802525C2ADF4 83B7B1B6D7EF72443ADE9E57A1B7333F5124206EBF16C1EF65493E4F4D817806 BA91C0AC5FC6A398FC03EF4BC6EA0EE7E31D1A0274DD95EB9A0F44FBAA48A2DF 734320200436472EF4070CADCF16FE9355FF45EC9AB8825CB39192495785E774 F411087FD7029082E3F9BC29A501E8687060F4475A09BAD31B5DE608159FDEAC 7674A6BADF286CA4DBA4F243124C7D2D294D165EED41F699B6050352E34756F5 0796D45E4D60755D6E2187257E97A127713D5D5F433FE3F378E0635F5FAC70E5 FE8A8F2632F613016D4D96D20B9D63D381DC300C8CAAB2593D568D5C12D27E73 76B8B52FF36742CD36D176F396771902097606C99BADE74FFAA28D2A9643C4D1 C8E162E95CCE4F0A88B7D178EB271E1DB5A98F0C3D10B46AA67466E53CD0282D F799D0180755C1EA9E2946D515A35B4D138FEF636C1A4A1CF9E4B73AD4B5EBC1 001BF56354979A9C6911C04CD16DB92F928D3B25B3B2B978FA9F2CD022F32127 2C53468FF065ED789B8C05EC43BC579E3B839DB0DF526A38AC8D41F364D3DB51 38D156013444A422EF8E5108423FEF5579FF88AD4004FAAD6EC0D9F2D9380A67 9F3E4FC00987B4C679E1DEB71F8F0B32B7D572EC44DEF432EA9836FB28FFC7FE 5E6CACF5AC0EAE45D0E67B3FC8CD1DCEE671B6D45D988111E8076909842C3860 718C95AE0660034B46A690ADB37143538D463B9561EF91ECAAFED08BF5307B52 2B0A9F51B454ACF31A09FEA9CA44995857A50B3032CCEB393B8F15E0DF8816E4 D60595608354EC44E4507C5E664ADD338750A4CB8278F6AA3AF6EBE22A991AF0 E090D34BA8806915A8C68CD3B788DBD9387F0375B02073803E2D36604210BCF3 E17629931EA004F10AA5EE60033404771623012F70F357A26934A3FF15C43F22 431D98954F14AFCCF298AD43010C2B697C1A17A07A5E986DFD2A894573F8E337 ED8FEDF80CB5D6E2E8D0AAD7D06F75A71164B3A4A22DB28BBEA08501FF460B91 336CE3359D52C87C1340D6350F033BC838BF9BFE5782B53EDB3EB3535385FC5F 76B3CF48EFBEF9A7F498F02ADFABB7C14D067C9D2D1BF13190DE94E48FE09CC0 E154D3E40FF0A5A9BA1EFB244A2E6E9AB60EDE02C555AE301E9D000E7C9E0323 04925DD9B92820FC4282974DF466FCB385E9E304232D2A0868BBA516E88DAD68 5691106CE164363D596F9B77997212D26D9F7AB2D5DA099546C7A4E186630A99 F73A3D0FE1CEE30B5C1E00A38120343F9FBC50DFDB322CEB6E06385AE8AE7E99 8A3D6FB0E91DF07D9BA89405E3FBFCF261D216F50354961BE1DD91E096AEBE1A CAD955F991226AB4361D3034A3A38BC4F91C5D683204390D8AB0BBF0F1617BA4 60300C04D3C15E603247A98A8921A1965452930A9AB691BC5B59564E0E5B1D86 2280A11BCEA2AE406EBE3EE861178D863E2750C84E2C092E2F21D07D87CFC4F3 63E6067DFF6C1D02E6CB05520747FCF4A17D9AE3A5C1B5ADB879B1E9A864BABC B6248EF1C7EF10E58D9B04C3447F640B13D2D09BA4695DA2CB6B5894AF7F0883 D53F2B6556B8ED90BECE732B8B5CE8C180DB102EFD164D88ECEAF0731DB83173 1E02C85EE0291C791888C4C1C4EC556074D52518435B7E027D6438944B9CCE3F CDF05366304992A0A47FEBDA62C60C2D7C11D62FBE1E19820940F91132CA4893 0BA11E72291C4FFCEBF445BC14617D1FB6F7732D5EDD2A99D0A3B907DAAC260C 9CD53EBC5E56B2FA808FD204ED487F31BD7DBA40412EC3855B3C2B76F9316522 5D231BBF01E8254A8E30430D7A1BFC0AD8F9B88B3F44EDCCCA536FC8E9AD2A9E 3B724D88D2738C820D7799A8EDBF1DC11CE59A4CEBF07E20E7FE9B188819AEB0 1682C78A0A484DA5715C5556CC677D52C6F628D54985B5D8C886BCA2B6588115 C26CCB972D3EC0E4DCB5832E26843D8C6EA0D920F65EE83A4D7BD416D43A0331 B4698B5EDAB27B0DA06F813A5B48AA1F1AA3E2C5F1C70242062D29D19A864659 41556894BF4A1A900B3F71E3EE80BF4B332B87F7789D864314ED0EF05D73515D 6054E270398F154E60203BC73CEB70A4A12C227C3DF935EDA545593DB7E7E5FC 0CE52EE88171E8DB8F3AEBAB3854B6CE1A3F21A2A59B22614716FA5C0CBDDF01 2115F3326B2EAEBAE05B3BB8B56B082C9CAF7F948BFA435C99B45D6826F4F2E4 5633AC12BE23EFE1F7CE878B1B10B5819D1D5067286FC1B8ECA00339936AAC46 99D6DDBCAA2EADDB3151B0AF1B248BBBA1796E20EFF879FFD0FEA0A2E325EC6C CE411337A54880A2F9F0313BC7861FBB07BBF098CA9B25107BCF4F471E6FD3D6 18A80D73203C54B08541DD167B54B29E5E52CB811842259F32BC4BDD5399A9BF CF095D573A3CCE0FECE49FE859A13616816BC26C0AD16157B877E057662AB696 A5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMR12 %!PS-AdobeFont-1.1: CMR12 1.0 %%CreationDate: 1991 Aug 20 16:38:05 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.0) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMR12) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle 0 def /isFixedPitch false def end readonly def /FontName /CMR12 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 46 /period put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 55 /seven put dup 65 /A put dup 86 /V put dup 101 /e put dup 103 /g put dup 105 /i put dup 110 /n put dup 111 /o put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put readonly def /FontBBox{-34 -251 988 750}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 2BDBF16FBC7512FAA308A093FE5CF4E9D2405B169CD5365D6ECED5D768D66D6C 68618B8C482B341F8CA38E9BB9BAFCFAAD9C2F3FD033B62690986ED43D9C9361 3645B82392D5CAE11A7CB49D7E2E82DCD485CBA04C77322EB2E6A79D73DC194E 59C120A2DABB9BF72E2CF256DD6EB54EECBA588101ABD933B57CE8A3A0D16B28 51D7494F73096DF53BDC66BBF896B587DF9643317D5F610CD9088F9849126F23 DDE030F7B277DD99055C8B119CAE9C99158AC4E150CDFC2C66ED92EBB4CC092A AA078CE16247A1335AD332DAA950D20395A7384C33FF72EAA31A5B89766E635F 45C4C068AD7EE867398F0381B07CB94D29FF097D59FF9961D195A948E3D87C31 821E9295A56D21875B41988F7A16A1587050C3C71B4E4355BB37F255D6B237CE 96F25467F70FA19E0F85785FF49068949CCC79F2F8AE57D5F79BB9C5CF5EED5D 9857B9967D9B96CDCF73D5D65FF75AFABB66734018BAE264597220C89FD17379 26764A9302D078B4EB0E29178C878FD61007EEA2DDB119AE88C57ECFEF4B71E4 140A34951DDC3568A84CC92371A789021A103A1A347050FDA6ECF7903F67D213 1D0C7C474A9053866E9C88E65E6932BA87A73686EAB0019389F84D159809C498 1E7A30ED942EB211B00DBFF5BCC720F4E276C3339B31B6EABBB078430E6A09BB 377D3061A20B1EB98796B8607EECBC699445EAA866C38E02DF59F5EDD378303A 0733B90E7835C0AAF32BA04F1566D8161EA89CD4D14DDB953F8B910BFC8A7F03 5020F55EF8FC2640ADADA156F6CF8F2EB6610F7EE8874A26CBE7CD154469B9F4 ED76886B3FB679FFDEB59BB6C55AF7087BA48B75EE2FB374B19BCC421A963E15 FE05ECAAF9EECDF4B2715010A320102E6F8CCAA342FA11532671CEB0F7F496AD 7A919E031AC74FE7BEBA9DAFC47131F455CB283BA62B69289D1DF48B25ADF4ED C020D41214C500CDCE260B265E27DE5D1AE40D3908C74E9FF20C3ED9DE6E3AEE CC4AF295FB120326FC6BE58A62F703129456B41D0A472AC0B43692F1C6808880 F1872EEA64A8662291C39B5192A440987E07CA97485359206556CBBFCAB8D145 72A041E3545FBC1721DB9853AA921C1BA0BFAAC6E0FEE5ADE901853385DDC886 B618DB5F3672E6B8AF37AED22380D63139C6435A0CCB45A8DCB5C234DA2E6DEA 95D247D637F059E6397DBD1FF829BD0AF83745990A965DBD4521C412BDB73BE7 4ACB8FC7655D6A4B14420798CA1FCE1F2A4E5C4805DB2B2884D4A2B8B869695B 00D0772A9D1667D8D89D130FD1B7C9E23D6A5D9F4479D45089D4534A478A671A 9778ADD7E2248E27CF5EA78738313575D51BA6F19CD3404DC1DA4D6FF16DB1FC ED4FAFD5FCE7D972A56F87E153BF2B2F56E3429C0F90153B1AB993D686B803B5 136177EF755BF28DF0482726EBA06E838B5B6287E50AAF269178C40C329AFE60 305E5DBA73E3DB9A53B5DBFE35CF8E8E41F6720C7EF92A3940819C7B5CB2C662 57396428C1703B44183D8D3D65E307FCD2A9DF76C6345E7BA0B80C2F6803499C B648955B61858E16757C3EC802D1AB7131D96579E9081B4118FD2C981AFFD315 BD2D5C7506387A1EF8F731A2C5377366CC1224F67D5D6C7FC7C07AAE26F89968 045326419DA8FB6A2251C773343B136C66B65FD66A4F6E2E89E3ED66FF7CE6F3 85CB2E7255DD176F69E5AE950C1AFF902847333FBA9F371295D66640C838DE07 87D42B0040DF21AADA80FC1C29B2BC5F34B07CD2E7983D81736030F01BC96C43 1571E926D945186D2E831E0E5301B95779C2FAAD48BB6035C9AE2756784901C7 3A4B080C52A675C876BE7EA651AB24B1593A840C287C455A7DA15729D55925A4 7994B834B56A74DC4E41620CB2B50F32F8885DEF03682ECA8D899DE783F18014 2F17050545125536647AE64E7EE718D4EE1FCE7D144F26D894DDE34A12EF7649 5246E70B513BD0E9AD4D79A129B328FB51A48B0F4C127A34D473BD26402A81FB 745270D48D9674A8AC251EEF8A371DF384EBCD84D902DAD3A34AA02B40F1F29A 81E4AAFEE211269E3A5EB0344BD2188400B9BB5D36FE88BB5EF8E494DD00AC58 D6DC04B5BA56C3D4A1AF889CB09FEF1EE9621BAEF6D901DB25283CD1E5760D6B 73DFFC56F3B3B2AA38060E27CAA99213555CFB86A1D4ADC6AEF5177382C35E1F 85B326DE57C15645915D926E5E1AA264C1E79C5A496D69EF93C53AA958A53BA7 87F8A76DD1FBF463F2A5DECB23B7107F848489E39CCF9E84A26A4F529242DF00 90DC022BC9BF536AFC7C994652C42660076D93CC00EB916219F4EB483CE7D112 8C544CCCEB0AB78C80A8C25E10F0B59EB714CF61D4124817A9B210E9F9F13A31 6194244B8CEBC55FF831B0967977243B4D5DD52E85F079608F3CD0B3A153F91E 35EC8EA707374A4090E2B48794396AB8836024B17049578AEC19256FAF77FED0 D3194A43642AE5A5FEB00BB9C85EE35E5AAA9327885AFA8B785A5084EDEA3EC0 859B2F73B2929B938E70AE07629408222A9221F17E569D60AEE6C2D073EA6F0D A304747E803288D956466D5DEDA79BE454D7A5C2D363C134E14B833D0E17539F E8F8F1639C0D1FFAB71E57D3A6B48CD1EDA9C17BF5295092FFD4578D1CF8FE44 EE628073644663346C12B65C96EEFD5DD494F49215263A3A33845C1A91F67126 DF438F40CF838ECBA9EE4435ACD8365DBB7223710626859DE809BC8A725DC697 5DC52D969F199B8FD9B9A4AE8880C76F42BA0164882419A68F72B4756FB08174 8B94599F7EB79ACE996CDD70240FDE6E4F67D6E768CFB0A2A0C99FD73DDB5F0B E26A1E9ACE93578AF731986C0C27389D157D1E05BC2C5F91FDD76295FA359C9E B6D8F4AB7345FE994A3A80D4E5BDB16721384D012A7945B2200024A2F59292E4 8894AACB38983AD524132529458C9225009639EF8112F98744A05512DE4A83C4 4B465C986B4FBFF6B2AB4DFD4BF1F83DBC245F252E672E24A9ADFC8B52B69166 5706845E97F8F3E4469168B378EED88851BC75CF733B0271B3C04C82A00CC132 63AE26DDDD4D4A81CEAD7442D23981C19A9A553461EE8F19406A9C5EE91EFA55 E37938FFE61409483CE378A90E844BFC6C62A0956EDF1A892B309DDE048148D2 5E9D85A0DF7744BFA28C2C62AB99C376EAAEEE915471C564BF1E2F8F43E36FB9 7CC51FE567961D35136A41C5B84952AAB46848EFF1F043C792031C39822B3C3D C931AEF1F1661BDC45F7E2173CA8B679F03A9E9FB2F25545064A21C8AD6A0835 1F80C304E6DEBA4295F572451AA663FBD3EC065870A4BC374A7633725CC878EE 488510F45730821359143C850E2A8E0092F476BF46179128F7513B236B1B78C4 7DE5C601BB96F0415C2A804ED50EBCCE5AC8F840DE3865E471B0CEB74D58D300 0CCA8AB70BFB3568920C9FAF02593E7BBA9764E8F4CA4EC1DDC6EFAB8A43719B 734DDF21FC7FB53464C895BD45DD47B1D97E2D5A36F935F9818C0DB701FC2D0C BEB6A543377AD704C1341D8AD3CBC19860DFB42508AB335B9FB632C8494E3D26 3997C61ABF85EFEC8003EB2B2FF797EB44155F9CE7068A1D0110F2F1B9673520 0B489FEA9AEBCEF9492D5B6C6B86F632D65AC01014557532BE9F9D242C6029FB C0E0ECE388DEE76236D7B3B1BEB50E0F554B5D43A6ED6275FA92F6C7F431F393 19CB5AA671C6C2958D9A4A41C7649FF8959943F60D20440057E3AA329748EBFC B3A30891770A3DD25FBF6F0E8A2A02CD5AB1481D21962F351A03A3ABD006E5C0 89B4901F920C9C018DCD542C28B6362239EACBE966664977A3A8C3365A9AB4A6 E370F86F6C431D5E53EE2B0FBCCD31A7757AF28F514B1D0EA9B44B9BE8DCEF26 9B8DEBBDAC24C02BF1369A40E013E60FE14395B373EC103B5FFB14BB52B90819 5E764700191C6BF96D5555FF40ADFA7ECE723A4F81367F9267648FA0BCFD30EC 03BFFEF0A9B3BE3621DDDF833921F98F07D3C9DDF74D997F0FEC1528C0DA997C E07A0066D2AE73B4933B0F20060CE4B7440AC2844DB92C4081C534D684354EBF 9447F3A2F16E313DD01E8E9A795F6929D315B848681C6F4746725B195AADA835 D159F497263D5D313B0B846E39E8617EE6544860D6D8E3F303C5634DBCF7BA51 4BFF3BC909EA486CEFA579427C29B94D4DEA8F06871E9BE2C6F132A8AC7A5CAB 3A70A76A300AEC046C2E1171ED791E540D4879A964072DDF12BA2535CCDC5712 F21270AFAE78AFA36C1A2B8590500AE880B4483E687DCDFE398E82668B717FF3 7AEB3ED5861DE8C15BEAFEC60EFE3CD9FA64B94B3B6982B8AD624F6CDB37C161 F25C63D168962322469F58CD8E8BDC65BCC2263C8DB27562B44EA608A0FB7875 076B491C791CF94B949142C166C3A051507B26E39550DC15CCE4D352E819E63B 556D7C341B0B6036E7937E212093F5ED1CC07EEB8DDD4DAE2519C555AF6526AD 2CA6A09BA1476DE9D8EAEB323735A7B459FE7C3F520C48E15A138B99481B51BE D5E91CDF279527E42CC7AA1049060CA1FE415A3A7803D14917711D62EBABC6D4 B82F991A3552221B26D0C1FE69768FD95BD1C45D617A09C79AB743048C49D44C 4770C435F3F0B330A4EA4C3E82F9E3ABD11029EB3763C742260A346C46DBBB98 5961F9E93E749E35A354EA4F6CD91951A7974F5C7BC4C9D4C6CDAEB098D83163 4B956856BA24C611FE077DD63CA9EF6540FBE836B6C67BF0ECBF1DFDC9B55EF0 4577AA998BBF76F3E767E0E844BDD1B5394FDF517D1CE84F16C154D9DE37BD7E 4291B94A8F86CB2610CA7698DDCF6D7151E96296F5DA007FACC876C034D4C65F 7187F3BFA5673E33711783DB10B4776828DA89C282062C8DE92632936E5C95BA 0E3BEEAE1A416FB5A1F181B723D345028D2D4A81FA1EFD2BC7EFAE0BF373444B 77E54E1B1691788E3D91186EBA6A104E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont TeXDict begin 40258437 52099151 1000 600 600 (cfitsio.dvi) @start /Fa 138[49 30 37 38 1[46 46 51 74 23 2[28 1[42 1[42 2[42 46 11[68 12[68 3[69 68[{}17 90.9091 /CMTI10 rf /Fb 193[71 62[{}1 90.9091 /CMMI10 rf /Fc 149[25 2[45 45 86[45 15[{}4 90.9091 /CMSY10 rf /Fd 134[59 59 81 59 62 44 44 46 59 62 56 62 93 31 59 1[31 62 56 34 51 62 50 62 54 9[116 85 86 78 62 84 1[77 1[88 106 67 88 1[42 88 88 70 74 86 81 80 85 6[31 56 56 56 56 56 56 56 56 56 56 1[31 37 32[62 12[{}58 99.6264 /CMBX12 rf /Fe 129[48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 1[48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 33[{}93 90.9091 /CMTT10 rf /Ff 133[60 71 71 97 71 75 52 53 55 1[75 67 75 112 37 71 1[37 75 67 41 61 75 60 75 65 9[139 102 103 94 75 100 1[92 101 105 128 81 105 1[50 105 106 85 88 103 97 96 102 7[67 67 67 67 67 67 67 67 67 67 67 37 45 3[52 52 27[75 78 11[{}62 119.552 /CMBX12 rf /Fg 135[102 3[75 1[79 1[108 1[108 4[54 108 2[88 108 2[94 29[140 138 146 7[97 97 97 97 97 97 97 97 97 97 48[{}23 172.188 /CMBX12 rf /Fh 165[56 68 68 93 68 68 66 51 67 1[62 71 68 83 57 71 1[33 68 71 59 62 69 66 64 68 7[45 45 45 45 45 45 45 45 45 45 45 25 30 3[35 35 40[{}39 90.9091 /CMSL10 rf /Fi 133[46 55 55 1[55 58 41 41 43 1[58 52 58 87 29 2[29 58 52 32 48 58 46 58 51 9[108 2[73 58 78 1[71 79 82 1[63 2[40 82 82 66 69 80 76 74 79 7[52 52 52 52 52 52 52 52 52 52 2[35 32[58 12[{}51 90.9091 /CMBX10 rf /Fj 132[45 40 48 48 66 48 51 35 36 36 48 51 45 51 76 25 48 28 25 51 45 28 40 51 40 51 45 25 2[25 45 25 56 68 68 93 68 68 66 51 67 71 62 71 68 83 57 71 47 33 68 71 59 62 69 66 64 68 71 43 1[71 1[25 25 45 45 45 45 45 45 45 45 45 45 45 25 30 25 71 45 35 35 25 71 76 45 76 45 25 17[76 76 51 51 53 11[{}92 90.9091 /CMR10 rf /Fk 138[65 46 46 46 2[59 65 4[33 1[59 1[52 14[88 20[88 9[59 2[59 59 59 59 59 1[33 46[{}18 119.552 /CMR12 rf /Fl 139[63 64 66 2[81 90 134 45 2[45 1[81 49 74 1[72 1[78 12[112 90 2[110 6[60 2[101 2[117 1[122 65[{}20 143.462 /CMBX12 rf /Fm 133[103 123 123 1[123 129 90 92 95 1[129 116 129 194 65 2[65 129 116 71 106 129 103 129 113 9[240 1[179 162 129 173 1[159 175 182 1[140 2[87 182 183 146 153 178 168 165 175 25[65 26[129 12[{}42 206.559 /CMBX12 rf end %%EndProlog %%BeginSetup %%Feature: *Resolution 600dpi TeXDict begin %%BeginPaperSize: Letter letter %%EndPaperSize end %%EndSetup %%Page: 1 1 TeXDict begin 1 0 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 0 a SDict begin [ /Producer (dvips + Distiller) /Title () /Subject () /Creator (LaTeX with hyperref package) /Author () /Keywords () /DOCINFO pdfmark end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.i) cvn H.B /DEST pdfmark end 0 299 a 0 464 a SDict begin [ /Count -4 /Dest (chapter.1) cvn /Title (Introduction ) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.1.1) cvn /Title ( A Brief Overview) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.1.2) cvn /Title (Sources of FITS Software and Information) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.1.3) cvn /Title (Acknowledgments) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.1.4) cvn /Title (Legal Stuff) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -6 /Dest (chapter.2) cvn /Title ( Creating the CFITSIO Library ) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -4 /Dest (section.2.1) cvn /Title (Building the Library) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.2.1.1) cvn /Title (Unix Systems) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.2.1.2) cvn /Title (VMS) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.2.1.3) cvn /Title (Windows PCs) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.2.1.4) cvn /Title (Macintosh PCs) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.2.2) cvn /Title (Testing the Library) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.2.3) cvn /Title (Linking Programs with CFITSIO) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.2.4) cvn /Title (Using CFITSIO in Multi-threaded Environments) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.2.5) cvn /Title (Getting Started with CFITSIO) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.2.6) cvn /Title (Example Program) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (chapter.3) cvn /Title ( A FITS Primer ) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -13 /Dest (chapter.4) cvn /Title ( Programming Guidelines ) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.4.1) cvn /Title (CFITSIO Definitions) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.4.2) cvn /Title (Current Header Data Unit \(CHDU\)) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.4.3) cvn /Title (Function Names and Variable Datatypes) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.4.4) cvn /Title (Support for Unsigned Integers and Signed Bytes) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.4.5) cvn /Title (Dealing with Character Strings) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.4.6) cvn /Title (Implicit Data Type Conversion) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.4.7) cvn /Title (Data Scaling) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.4.8) cvn /Title (Support for IEEE Special Values) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.4.9) cvn /Title (Error Status Values and the Error Message Stack) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.4.10) cvn /Title (Variable-Length Arrays in Binary Tables) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.4.11) cvn /Title (Multiple Access to the Same FITS File) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.4.12) cvn /Title (When the Final Size of the FITS HDU is Unknown) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.4.13) cvn /Title (CFITSIO Size Limitations) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -8 /Dest (chapter.5) cvn /Title (Basic CFITSIO Interface Routines ) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.5.1) cvn /Title (CFITSIO Error Status Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.5.2) cvn /Title (FITS File Access Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.5.3) cvn /Title (HDU Access Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -2 /Dest (section.5.4) cvn /Title (Header Keyword Read/Write Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.5.4.1) cvn /Title (Keyword Reading Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.5.4.2) cvn /Title (Keyword Writing Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.5.5) cvn /Title (Primary Array or IMAGE Extension I/O Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.5.6) cvn /Title (Image Compression) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -6 /Dest (section.5.7) cvn /Title (ASCII and Binary Table Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.5.7.1) cvn /Title (Create New Table) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.5.7.2) cvn /Title (Column Information Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.5.7.3) cvn /Title (Routines to Edit Rows or Columns) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.5.7.4) cvn /Title (Read and Write Column Data Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.5.7.5) cvn /Title (Row Selection and Calculator Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.5.7.6) cvn /Title (Column Binning or Histogramming Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -3 /Dest (section.5.8) cvn /Title (Utility Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.5.8.1) cvn /Title (File Checksum Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.5.8.2) cvn /Title (Date and Time Utility Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.5.8.3) cvn /Title (General Utility Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -4 /Dest (chapter.6) cvn /Title ( The CFITSIO Iterator Function ) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.6.1) cvn /Title (The Iterator Work Function) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.6.2) cvn /Title (The Iterator Driver Function) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.6.3) cvn /Title (Guidelines for Using the Iterator Function) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.6.4) cvn /Title (Complete List of Iterator Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -1 /Dest (chapter.7) cvn /Title ( World Coordinate System Routines ) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.7.1) cvn /Title ( Self-contained WCS Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -2 /Dest (chapter.8) cvn /Title ( Hierarchical Grouping Routines ) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.8.1) cvn /Title (Grouping Table Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.8.2) cvn /Title (Group Member Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -6 /Dest (chapter.9) cvn /Title ( Specialized CFITSIO Interface Routines ) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.9.1) cvn /Title (FITS File Access Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.9.2) cvn /Title (HDU Access Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -7 /Dest (section.9.3) cvn /Title (Specialized Header Keyword Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.9.3.1) cvn /Title (Header Information Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.9.3.2) cvn /Title (Read and Write the Required Keywords) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.9.3.3) cvn /Title (Write Keyword Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.9.3.4) cvn /Title (Insert Keyword Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.9.3.5) cvn /Title (Read Keyword Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.9.3.6) cvn /Title (Modify Keyword Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.9.3.7) cvn /Title (Update Keyword Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.9.4) cvn /Title (Define Data Scaling and Undefined Pixel Parameters) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.9.5) cvn /Title (Specialized FITS Primary Array or IMAGE Extension I/O Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -4 /Dest (section.9.6) cvn /Title (Specialized FITS ASCII and Binary Table Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.9.6.1) cvn /Title (General Column Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.9.6.2) cvn /Title (Low-Level Table Access Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.9.6.3) cvn /Title (Write Column Data Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.9.6.4) cvn /Title (Read Column Data Routines) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -12 /Dest (chapter.10) cvn /Title ( Extended File Name Syntax ) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.10.1) cvn /Title (Overview) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -6 /Dest (section.10.2) cvn /Title (Filetype) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.10.2.1) cvn /Title (Notes about HTTP proxy servers) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.10.2.2) cvn /Title (Notes about HTTPS file access) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.10.2.3) cvn /Title (Notes about the stream filetype driver) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.10.2.4) cvn /Title (Notes about the gsiftp filetype) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.10.2.5) cvn /Title (Notes about the root filetype) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.10.2.6) cvn /Title (Notes about the shmem filetype:) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.10.3) cvn /Title (Base Filename) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.10.4) cvn /Title (Output File Name when Opening an Existing File) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.10.5) cvn /Title (Template File Name when Creating a New File) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.10.6) cvn /Title (Image Tile-Compression Specification) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.10.7) cvn /Title (HDU Location Specification) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.10.8) cvn /Title (Image Section) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.10.9) cvn /Title (Image Transform Filters) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.10.10) cvn /Title (Column and Keyword Filtering Specification) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -6 /Dest (section.10.11) cvn /Title (Row Filtering Specification) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.10.11.1) cvn /Title (General Syntax) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.10.11.2) cvn /Title (Bit Masks) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.10.11.3) cvn /Title (Vector Columns) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.10.11.4) cvn /Title (Good Time Interval Filtering) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.10.11.5) cvn /Title (Spatial Region Filtering) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (subsection.10.11.6) cvn /Title (Example Row Filters) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.10.12) cvn /Title ( Binning or Histogramming Specification) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -6 /Dest (chapter.11) cvn /Title (Template Files ) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.11.1) cvn /Title (Detailed Template Line Format) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.11.2) cvn /Title (Auto-indexing of Keywords) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.11.3) cvn /Title (Template Parser Directives) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.11.4) cvn /Title (Formal Template Syntax) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.11.5) cvn /Title (Errors) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.11.6) cvn /Title (Examples) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -6 /Dest (chapter.12) cvn /Title ( Local FITS Conventions ) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.12.1) cvn /Title (64-Bit Long Integers) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.12.2) cvn /Title (Long String Keyword Values.) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.12.3) cvn /Title (Arrays of Fixed-Length Strings in Binary Tables) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.12.4) cvn /Title (Keyword Units Strings) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.12.5) cvn /Title (HIERARCH Convention for Extended Keyword Names) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.12.6) cvn /Title (Tile-Compressed Image Format) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -2 /Dest (chapter.13) cvn /Title ( Optimizing Programs ) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.13.1) cvn /Title (How CFITSIO Manages Data I/O) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (section.13.2) cvn /Title (Optimization Strategies) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (appendix.A) cvn /Title (Index of Routines ) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (appendix.B) cvn /Title (Parameter Definitions ) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Count -0 /Dest (appendix.C) cvn /Title (CFITSIO Error Status Codes ) /OUT pdfmark end 0 464 a 0 464 a SDict begin [ /Page 1 /View [ /Fit ] /PageMode /UseOutlines /DOCVIEW pdfmark end 0 464 a 0 464 a SDict begin [ {Catalog} << >> /PUT pdfmark end 0 464 a 0 464 a SDict begin H.S end 0 464 a 0 464 a SDict begin 13.6 H.A end 0 464 a 0 464 a SDict begin [ /View [/XYZ H.V] /Dest (Doc-Start) cvn H.B /DEST pdfmark end 0 464 a 0 464 a SDict begin [ {Catalog} << /PageLabels << /Nums [0 << /S /r >> 4 << /S /D >> ] >> >> /PUT pdfmark end 0 464 a 240 1799 a Fm(CFITSIO)76 b(User's)g(Reference)i(Guide)727 2258 y Fl(An)53 b(In)l(terface)f(to)i(FITS)g(F)-13 b(ormat)54 b(Files)1263 2518 y(for)g(C)f(Programmers)1667 3013 y Fk(V)-10 b(ersion)38 b(3.4)1727 3916 y Fj(HEASAR)m(C)1764 4029 y(Co)s(de)30 b(662)1363 4142 y(Go)s(ddard)f(Space)i(Fligh)m(t)h (Cen)m(ter)1522 4255 y(Green)m(b)s(elt,)f(MD)h(20771)1857 4367 y(USA)1629 5227 y Fk(August)38 b(2017)p eop end %%Page: 2 2 TeXDict begin 2 1 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.ii) cvn H.B /DEST pdfmark end 0 299 a Fj(ii)p eop end %%Page: 3 3 TeXDict begin 3 2 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.iii) cvn H.B /DEST pdfmark end 0 299 a 968 x Fm(Con)-6 b(ten)g(ts)0 1599 y SDict begin H.S end 0 1599 a 0 1599 a SDict begin 13.6 H.A end 0 1599 a 0 1599 a SDict begin [ /View [/XYZ H.V] /Dest (chapter*.1) cvn H.B /DEST pdfmark end 0 1599 a 0 1858 a SDict begin H.S end 0 1858 a Fi(1)84 b(In)m(tro)s(duction)748 1858 y SDict begin 13.6 H.L end 748 1858 a 748 1858 a SDict begin [ /Subtype /Link /Dest (chapter.1) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 748 1858 a 3100 w Fi(1)136 2020 y SDict begin H.S end 136 2020 a Fj(1.1)125 b(A)30 b(Brief)h(Ov)m(erview)1069 2020 y SDict begin 13.6 H.L end 1069 2020 a 1069 2020 a SDict begin [ /Subtype /Link /Dest (section.1.1) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1069 2020 a 85 w Fj(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) f(.)131 b(1)136 2182 y SDict begin H.S end 136 2182 a Fj(1.2)94 b(Sources)30 b(of)h(FITS)f(Soft)m(w)m(are)h(and)f(Information)2035 2182 y SDict begin 13.6 H.L end 2035 2182 a 2035 2182 a SDict begin [ /Subtype /Link /Dest (section.1.2) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 2035 2182 a 38 w Fj(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)f(.)131 b(1)136 2344 y SDict begin H.S end 136 2344 a Fj(1.3)94 b(Ac)m(kno)m(wledgmen)m(ts)1053 2344 y SDict begin 13.6 H.L end 1053 2344 a 1053 2344 a SDict begin [ /Subtype /Link /Dest (section.1.3) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1053 2344 a 30 w Fj(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(2)136 2506 y SDict begin H.S end 136 2506 a Fj(1.4)94 b(Legal)32 b(Stu\013)779 2506 y SDict begin 13.6 H.L end 779 2506 a 779 2506 a SDict begin [ /Subtype /Link /Dest (section.1.4) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 779 2506 a 92 w Fj(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)f(.)131 b(4)0 2766 y SDict begin H.S end 0 2766 a Fi(2)119 b(Creating)34 b(the)h(CFITSIO)e(Library)1627 2766 y SDict begin 13.6 H.L end 1627 2766 a 1627 2766 a SDict begin [ /Subtype /Link /Dest (chapter.2) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1627 2766 a 2221 w Fi(5)136 2928 y SDict begin H.S end 136 2928 a Fj(2.1)94 b(Building)31 b(the)f(Library)1167 2928 y SDict begin 13.6 H.L end 1167 2928 a 1167 2928 a SDict begin [ /Subtype /Link /Dest (section.2.1) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1167 2928 a 58 w Fj(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.) 131 b(5)345 3090 y SDict begin H.S end 345 3090 a Fj(2.1.1)106 b(Unix)31 b(Systems)1181 3090 y SDict begin 13.6 H.L end 1181 3090 a 1181 3090 a SDict begin [ /Subtype /Link /Dest (subsection.2.1.1) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1181 3090 a 44 w Fj(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)f(.)131 b(5)345 3252 y SDict begin H.S end 345 3252 a Fj(2.1.2)106 b(VMS)838 3252 y SDict begin 13.6 H.L end 838 3252 a 838 3252 a SDict begin [ /Subtype /Link /Dest (subsection.2.1.2) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 838 3252 a 33 w Fj(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(7)345 3413 y SDict begin H.S end 345 3413 a Fj(2.1.3)106 b(Windo)m(ws)31 b(PCs)1195 3413 y SDict begin 13.6 H.L end 1195 3413 a 1195 3413 a SDict begin [ /Subtype /Link /Dest (subsection.2.1.3) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1195 3413 a 30 w Fj(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(7)345 3575 y SDict begin H.S end 345 3575 a Fj(2.1.4)106 b(Macin)m(tosh)32 b(PCs)1240 3575 y SDict begin 13.6 H.L end 1240 3575 a 1240 3575 a SDict begin [ /Subtype /Link /Dest (subsection.2.1.4) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1240 3575 a 55 w Fj(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(7)136 3737 y SDict begin H.S end 136 3737 a Fj(2.2)94 b(T)-8 b(esting)32 b(the)e(Library)1121 3737 y SDict begin 13.6 H.L end 1121 3737 a 1121 3737 a SDict begin [ /Subtype /Link /Dest (section.2.2) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1121 3737 a 33 w Fj(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)f(.)131 b(7)136 3899 y SDict begin H.S end 136 3899 a Fj(2.3)94 b(Linking)31 b(Programs)f(with)g(CFITSIO)1675 3899 y SDict begin 13.6 H.L end 1675 3899 a 1675 3899 a SDict begin [ /Subtype /Link /Dest (section.2.3) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1675 3899 a 45 w Fj(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(9)136 4061 y SDict begin H.S end 136 4061 a Fj(2.4)94 b(Using)31 b(CFITSIO)e(in)h(Multi-threaded) h(En)m(vironmen)m(ts)2294 4061 y SDict begin 13.6 H.L end 2294 4061 a 2294 4061 a SDict begin [ /Subtype /Link /Dest (section.2.4) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 2294 4061 a 62 w Fj(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(9)136 4223 y SDict begin H.S end 136 4223 a Fj(2.5)94 b(Getting)32 b(Started)f(with)f(CFITSIO)1589 4223 y SDict begin 13.6 H.L end 1589 4223 a 1589 4223 a SDict begin [ /Subtype /Link /Dest (section.2.5) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1589 4223 a 60 w Fj(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(9)136 4385 y SDict begin H.S end 136 4385 a Fj(2.6)94 b(Example)31 b(Program)1068 4385 y SDict begin 13.6 H.L end 1068 4385 a 1068 4385 a SDict begin [ /Subtype /Link /Dest (section.2.6) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1068 4385 a 86 w Fj(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) f(.)85 b(10)0 4645 y SDict begin H.S end 0 4645 a Fi(3)119 b(A)35 b(FITS)f(Primer)913 4645 y SDict begin 13.6 H.L end 913 4645 a 913 4645 a SDict begin [ /Subtype /Link /Dest (chapter.3) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 913 4645 a 2882 w Fi(13)0 4904 y SDict begin H.S end 0 4904 a Fi(4)119 b(Programming)37 b(Guidelines)1348 4904 y SDict begin 13.6 H.L end 1348 4904 a 1348 4904 a SDict begin [ /Subtype /Link /Dest (chapter.4) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1348 4904 a 2447 w Fi(15)136 5066 y SDict begin H.S end 136 5066 a Fj(4.1)94 b(CFITSIO)29 b(De\014nitions)1181 5066 y SDict begin 13.6 H.L end 1181 5066 a 1181 5066 a SDict begin [ /Subtype /Link /Dest (section.4.1) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1181 5066 a 44 w Fj(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.) 85 b(15)136 5228 y SDict begin H.S end 136 5228 a Fj(4.2)94 b(Curren)m(t)30 b(Header)h(Data)h(Unit)e(\(CHDU\))1774 5228 y SDict begin 13.6 H.L end 1774 5228 a 1774 5228 a SDict begin [ /Subtype /Link /Dest (section.4.2) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1774 5228 a 87 w Fj(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f (.)85 b(17)136 5390 y SDict begin H.S end 136 5390 a Fj(4.3)94 b(F)-8 b(unction)32 b(Names)e(and)g(V)-8 b(ariable)32 b(Datat)m(yp)s(es)1961 5390 y SDict begin 13.6 H.L end 1961 5390 a 1961 5390 a SDict begin [ /Subtype /Link /Dest (section.4.3) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1961 5390 a 41 w Fj(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(18)136 5552 y SDict begin H.S end 136 5552 a Fj(4.4)94 b(Supp)s(ort)29 b(for)h(Unsigned)g(In)m(tegers)h(and)f (Signed)g(Bytes)2270 5552 y SDict begin 13.6 H.L end 2270 5552 a 2270 5552 a SDict begin [ /Subtype /Link /Dest (section.4.4) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 2270 5552 a 86 w Fj(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(20)136 5714 y SDict begin H.S end 136 5714 a Fj(4.5)94 b(Dealing)33 b(with)d(Character)g(Strings)1588 5714 y SDict begin 13.6 H.L end 1588 5714 a 1588 5714 a SDict begin [ /Subtype /Link /Dest (section.4.5) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1588 5714 a 61 w Fj(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(22)1912 5942 y(iii)p eop end %%Page: 4 4 TeXDict begin 4 3 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.iv) cvn H.B /DEST pdfmark end 0 299 a Fj(iv)3311 b Fh(CONTENTS)136 555 y SDict begin H.S end 136 555 a Fj(4.6)94 b(Implicit)31 b(Data)h(T)m(yp)s(e)e(Con)m(v)m (ersion)1584 555 y SDict begin 13.6 H.L end 1584 555 a 1584 555 a SDict begin [ /Subtype /Link /Dest (section.4.6) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1584 555 a 65 w Fj(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(23)136 716 y SDict begin H.S end 136 716 a Fj(4.7)94 b(Data)32 b(Scaling)853 716 y SDict begin 13.6 H.L end 853 716 a 853 716 a SDict begin [ /Subtype /Link /Dest (section.4.7) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 853 716 a 89 w Fj(.)46 b(.)f(.)h(.)g(.)f(.)h (.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(23)136 876 y SDict begin H.S end 136 876 a Fj(4.8)94 b(Supp)s(ort)29 b(for)h(IEEE)g(Sp)s (ecial)g(V)-8 b(alues)1652 876 y SDict begin 13.6 H.L end 1652 876 a 1652 876 a SDict begin [ /Subtype /Link /Dest (section.4.8) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1652 876 a 68 w Fj(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(24)136 1037 y SDict begin H.S end 136 1037 a Fj(4.9)94 b(Error)30 b(Status)g(V)-8 b(alues)32 b(and)d(the)i(Error)e(Message)j(Stac)m(k)2312 1037 y SDict begin 13.6 H.L end 2312 1037 a 2312 1037 a SDict begin [ /Subtype /Link /Dest (section.4.9) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 2312 1037 a 44 w Fj(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)f(.)85 b(24)136 1197 y SDict begin H.S end 136 1197 a Fj(4.10)49 b(V)-8 b(ariable-Length)33 b(Arra)m(ys)d(in)g(Binary)h(T)-8 b(ables)1971 1197 y SDict begin 13.6 H.L end 1971 1197 a 1971 1197 a SDict begin [ /Subtype /Link /Dest (section.4.10) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1971 1197 a 31 w Fj(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(25)136 1358 y SDict begin H.S end 136 1358 a Fj(4.11)49 b(Multiple)32 b(Access)f(to)g(the)g(Same)f (FITS)g(File)1901 1358 y SDict begin 13.6 H.L end 1901 1358 a 1901 1358 a SDict begin [ /Subtype /Link /Dest (section.4.11) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1901 1358 a 31 w Fj(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(26)136 1518 y SDict begin H.S end 136 1518 a Fj(4.12)49 b(When)31 b(the)f(Final)h(Size)g (of)g(the)f(FITS)g(HDU)h(is)f(Unkno)m(wn)2393 1518 y SDict begin 13.6 H.L end 2393 1518 a 2393 1518 a SDict begin [ /Subtype /Link /Dest (section.4.12) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 2393 1518 a 34 w Fj(.)45 b(.)h(.)g(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(27)136 1678 y SDict begin H.S end 136 1678 a Fj(4.13)49 b(CFITSIO)29 b(Size)i (Limitations)1395 1678 y SDict begin 13.6 H.L end 1395 1678 a 1395 1678 a SDict begin [ /Subtype /Link /Dest (section.4.13) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1395 1678 a 42 w Fj(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)f(.)85 b(28)0 1931 y SDict begin H.S end 0 1931 a Fi(5)f(Basic)36 b(CFITSIO)d(In)m (terface)h(Routines)1757 1931 y SDict begin 13.6 H.L end 1757 1931 a 1757 1931 a SDict begin [ /Subtype /Link /Dest (chapter.5) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1757 1931 a 2038 w Fi(31)136 2092 y SDict begin H.S end 136 2092 a Fj(5.1)94 b(CFITSIO)29 b(Error)h(Status)g(Routines)1631 2092 y SDict begin 13.6 H.L end 1631 2092 a 1631 2092 a SDict begin [ /Subtype /Link /Dest (section.5.1) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1631 2092 a 89 w Fj(.)45 b(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)f(.)85 b(31)136 2252 y SDict begin H.S end 136 2252 a Fj(5.2)94 b(FITS)30 b(File)i(Access)f(Routines)1406 2252 y SDict begin 13.6 H.L end 1406 2252 a 1406 2252 a SDict begin [ /Subtype /Link /Dest (section.5.2) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1406 2252 a 31 w Fj(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(32)136 2412 y SDict begin H.S end 136 2412 a Fj(5.3)94 b(HDU)32 b(Access)f(Routines)1223 2412 y SDict begin 13.6 H.L end 1223 2412 a 1223 2412 a SDict begin [ /Subtype /Link /Dest (section.5.3) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1223 2412 a 72 w Fj(.)46 b(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(35)136 2573 y SDict begin H.S end 136 2573 a Fj(5.4)94 b(Header)31 b(Keyw)m(ord)f(Read/W)-8 b(rite)33 b(Routines)1892 2573 y SDict begin 13.6 H.L end 1892 2573 a 1892 2573 a SDict begin [ /Subtype /Link /Dest (section.5.4) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1892 2573 a 40 w Fj(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(37)345 2733 y SDict begin H.S end 345 2733 a Fj(5.4.1)106 b(Keyw)m(ord)30 b(Reading)h(Routines)1725 2733 y SDict begin 13.6 H.L end 1725 2733 a 1725 2733 a SDict begin [ /Subtype /Link /Dest (subsection.5.4.1) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1725 2733 a 65 w Fj(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(38)345 2894 y SDict begin H.S end 345 2894 a Fj(5.4.2)106 b(Keyw)m(ord)30 b(W)-8 b(riting)32 b(Routines)1704 2894 y SDict begin 13.6 H.L end 1704 2894 a 1704 2894 a SDict begin [ /Subtype /Link /Dest (subsection.5.4.2) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1704 2894 a 86 w Fj(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) f(.)85 b(40)136 3054 y SDict begin H.S end 136 3054 a Fj(5.5)94 b(Primary)30 b(Arra)m(y)h(or)f(IMA)m(GE)i(Extension)e(I/O)g(Routines)2373 3054 y SDict begin 13.6 H.L end 2373 3054 a 2373 3054 a SDict begin [ /Subtype /Link /Dest (section.5.5) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 2373 3054 a 54 w Fj(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f (.)85 b(43)136 3215 y SDict begin H.S end 136 3215 a Fj(5.6)94 b(Image)32 b(Compression)1123 3215 y SDict begin 13.6 H.L end 1123 3215 a 1123 3215 a SDict begin [ /Subtype /Link /Dest (section.5.6) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1123 3215 a 31 w Fj(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)f(.)85 b(47)136 3375 y SDict begin H.S end 136 3375 a Fj(5.7)94 b(ASCI)s(I)29 b(and)h(Binary)h(T)-8 b(able)31 b(Routines)1705 3375 y SDict begin 13.6 H.L end 1705 3375 a 1705 3375 a SDict begin [ /Subtype /Link /Dest (section.5.7) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1705 3375 a 85 w Fj(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(52)345 3536 y SDict begin H.S end 345 3536 a Fj(5.7.1)106 b(Create)32 b(New)e(T)-8 b(able)1353 3536 y SDict begin 13.6 H.L end 1353 3536 a 1353 3536 a SDict begin [ /Subtype /Link /Dest (subsection.5.7.1) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1353 3536 a 84 w Fj(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f (.)85 b(52)345 3696 y SDict begin H.S end 345 3696 a Fj(5.7.2)106 b(Column)30 b(Information)g(Routines)1830 3696 y SDict begin 13.6 H.L end 1830 3696 a 1830 3696 a SDict begin [ /Subtype /Link /Dest (subsection.5.7.2) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1830 3696 a 31 w Fj(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(53)345 3857 y SDict begin H.S end 345 3857 a Fj(5.7.3)106 b(Routines)31 b(to)g(Edit)f(Ro)m(ws)h(or)f(Columns)2034 3857 y SDict begin 13.6 H.L end 2034 3857 a 2034 3857 a SDict begin [ /Subtype /Link /Dest (subsection.5.7.3) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 2034 3857 a 39 w Fj(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(55)345 4017 y SDict begin H.S end 345 4017 a Fj(5.7.4)106 b(Read)31 b(and)f(W)-8 b(rite)31 b(Column)f(Data)i(Routines)2219 4017 y SDict begin 13.6 H.L end 2219 4017 a 2219 4017 a SDict begin [ /Subtype /Link /Dest (subsection.5.7.4) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 2219 4017 a 66 w Fj(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(57)345 4178 y SDict begin H.S end 345 4178 a Fj(5.7.5)106 b(Ro)m(w)31 b(Selection)h(and)e (Calculator)h(Routines)2197 4178 y SDict begin 13.6 H.L end 2197 4178 a 2197 4178 a SDict begin [ /Subtype /Link /Dest (subsection.5.7.5) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 2197 4178 a 88 w Fj(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(59)345 4338 y SDict begin H.S end 345 4338 a Fj(5.7.6)106 b(Column)30 b(Binning)g(or)g(Histogramming)i (Routines)2423 4338 y SDict begin 13.6 H.L end 2423 4338 a 2423 4338 a SDict begin [ /Subtype /Link /Dest (subsection.5.7.6) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 2423 4338 a 74 w Fj(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)f(.)85 b(61)136 4498 y SDict begin H.S end 136 4498 a Fj(5.8)94 b(Utilit)m(y)33 b(Routines)986 4498 y SDict begin 13.6 H.L end 986 4498 a 986 4498 a SDict begin [ /Subtype /Link /Dest (section.5.8) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 986 4498 a 27 w Fj(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(63)345 4659 y SDict begin H.S end 345 4659 a Fj(5.8.1)106 b(File)32 b(Chec)m(ksum)e(Routines)1602 4659 y SDict begin 13.6 H.L end 1602 4659 a 1602 4659 a SDict begin [ /Subtype /Link /Dest (subsection.5.8.1) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1602 4659 a 47 w Fj(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(63)345 4819 y SDict begin H.S end 345 4819 a Fj(5.8.2)106 b(Date)32 b(and)e(Time)g(Utilit)m(y)j (Routines)1912 4819 y SDict begin 13.6 H.L end 1912 4819 a 1912 4819 a SDict begin [ /Subtype /Link /Dest (subsection.5.8.2) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1912 4819 a 90 w Fj(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(65)345 4980 y SDict begin H.S end 345 4980 a Fj(5.8.3)106 b(General)32 b(Utilit)m(y)g(Routines)1616 4980 y SDict begin 13.6 H.L end 1616 4980 a 1616 4980 a SDict begin [ /Subtype /Link /Dest (subsection.5.8.3) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1616 4980 a 33 w Fj(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(66)0 5232 y SDict begin H.S end 0 5232 a Fi(6)119 b(The)35 b(CFITSIO)e(Iterator)g(F)-9 b(unction)1677 5232 y SDict begin 13.6 H.L end 1677 5232 a 1677 5232 a SDict begin [ /Subtype /Link /Dest (chapter.6) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1677 5232 a 2118 w Fi(77)136 5393 y SDict begin H.S end 136 5393 a Fj(6.1)94 b(The)30 b(Iterator)i(W)-8 b(ork)31 b(F)-8 b(unction)1463 5393 y SDict begin 13.6 H.L end 1463 5393 a 1463 5393 a SDict begin [ /Subtype /Link /Dest (section.6.1) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1463 5393 a 45 w Fj(.)45 b(.)h(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(78)136 5553 y SDict begin H.S end 136 5553 a Fj(6.2)94 b(The)30 b(Iterator)i(Driv)m(er)f(F)-8 b(unction)1500 5553 y SDict begin 13.6 H.L end 1500 5553 a 1500 5553 a SDict begin [ /Subtype /Link /Dest (section.6.2) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1500 5553 a 78 w Fj(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(80)136 5714 y SDict begin H.S end 136 5714 a Fj(6.3)94 b(Guidelines)31 b(for)f(Using)h(the)f(Iterator)i(F)-8 b(unction)2028 5714 y SDict begin 13.6 H.L end 2028 5714 a 2028 5714 a SDict begin [ /Subtype /Link /Dest (section.6.3) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 2028 5714 a 45 w Fj(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)f(.)85 b(81)p eop end %%Page: 5 5 TeXDict begin 5 4 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.v) cvn H.B /DEST pdfmark end 0 299 a Fh(CONTENTS)3334 b Fj(v)136 555 y SDict begin H.S end 136 555 a Fj(6.4)94 b(Complete)32 b(List)e(of)h(Iterator)g (Routines)1728 555 y SDict begin 13.6 H.L end 1728 555 a 1728 555 a SDict begin [ /Subtype /Link /Dest (section.6.4) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1728 555 a 62 w Fj(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(82)0 823 y SDict begin H.S end 0 823 a Fi(7)119 b(W)-9 b(orld)36 b(Co)s(ordinate)e (System)h(Routines)1839 823 y SDict begin 13.6 H.L end 1839 823 a 1839 823 a SDict begin [ /Subtype /Link /Dest (chapter.7) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1839 823 a 1956 w Fi(85)136 986 y SDict begin H.S end 136 986 a Fj(7.1)125 b(Self-con)m(tained) 32 b(W)m(CS)e(Routines)1549 986 y SDict begin 13.6 H.L end 1549 986 a 1549 986 a SDict begin [ /Subtype /Link /Dest (section.7.1) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1549 986 a 29 w Fj(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) f(.)85 b(86)0 1254 y SDict begin H.S end 0 1254 a Fi(8)119 b(Hierarc)m(hical)36 b(Grouping)g(Routines)1667 1254 y SDict begin 13.6 H.L end 1667 1254 a 1667 1254 a SDict begin [ /Subtype /Link /Dest (chapter.8) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1667 1254 a 2128 w Fi(89)136 1418 y SDict begin H.S end 136 1418 a Fj(8.1)94 b(Grouping)30 b(T)-8 b(able)31 b(Routines)1350 1418 y SDict begin 13.6 H.L end 1350 1418 a 1350 1418 a SDict begin [ /Subtype /Link /Dest (section.8.1) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1350 1418 a 87 w Fj(.)46 b(.)f(.)h(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(90)136 1581 y SDict begin H.S end 136 1581 a Fj(8.2)94 b(Group)30 b(Mem)m(b)s(er)g(Routines)1335 1581 y SDict begin 13.6 H.L end 1335 1581 a 1335 1581 a SDict begin [ /Subtype /Link /Dest (section.8.2) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1335 1581 a 31 w Fj(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(92)0 1849 y SDict begin H.S end 0 1849 a Fi(9)119 b(Sp)s(ecialized)36 b(CFITSIO)d(In)m (terface)h(Routines)2054 1849 y SDict begin 13.6 H.L end 2054 1849 a 2054 1849 a SDict begin [ /Subtype /Link /Dest (chapter.9) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 2054 1849 a 1741 w Fi(95)136 2013 y SDict begin H.S end 136 2013 a Fj(9.1)94 b(FITS)30 b(File)i(Access)f(Routines)1406 2013 y SDict begin 13.6 H.L end 1406 2013 a 1406 2013 a SDict begin [ /Subtype /Link /Dest (section.9.1) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1406 2013 a 31 w Fj(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(95)136 2176 y SDict begin H.S end 136 2176 a Fj(9.2)94 b(HDU)32 b(Access)f(Routines)1223 2176 y SDict begin 13.6 H.L end 1223 2176 a 1223 2176 a SDict begin [ /Subtype /Link /Dest (section.9.2) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1223 2176 a 72 w Fj(.)46 b(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(99)136 2340 y SDict begin H.S end 136 2340 a Fj(9.3)94 b(Sp)s(ecialized)32 b(Header)e(Keyw)m(ord)h (Routines)1858 2340 y SDict begin 13.6 H.L end 1858 2340 a 1858 2340 a SDict begin [ /Subtype /Link /Dest (section.9.3) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1858 2340 a 74 w Fj(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(102)345 2503 y SDict begin H.S end 345 2503 a Fj(9.3.1)106 b(Header)31 b(Information)f(Routines) 1797 2503 y SDict begin 13.6 H.L end 1797 2503 a 1797 2503 a SDict begin [ /Subtype /Link /Dest (subsection.9.3.1) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1797 2503 a 64 w Fj(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(102)345 2667 y SDict begin H.S end 345 2667 a Fj(9.3.2)106 b(Read)31 b(and)f(W)-8 b(rite)31 b(the)g(Required)f(Keyw)m(ords)2234 2667 y SDict begin 13.6 H.L end 2234 2667 a 2234 2667 a SDict begin [ /Subtype /Link /Dest (subsection.9.3.2) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 2234 2667 a 51 w Fj(.)46 b(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(102)345 2830 y SDict begin H.S end 345 2830 a Fj(9.3.3)106 b(W)-8 b(rite)32 b(Keyw)m(ord)e(Routines)1623 2830 y SDict begin 13.6 H.L end 1623 2830 a 1623 2830 a SDict begin [ /Subtype /Link /Dest (subsection.9.3.3) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1623 2830 a 26 w Fj(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)f(.)40 b(104)345 2994 y SDict begin H.S end 345 2994 a Fj(9.3.4)106 b(Insert)30 b(Keyw)m(ord)g(Routines)1631 2994 y SDict begin 13.6 H.L end 1631 2994 a 1631 2994 a SDict begin [ /Subtype /Link /Dest (subsection.9.3.4) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1631 2994 a 89 w Fj(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) f(.)40 b(106)345 3157 y SDict begin H.S end 345 3157 a Fj(9.3.5)106 b(Read)31 b(Keyw)m(ord)f(Routines)1604 3157 y SDict begin 13.6 H.L end 1604 3157 a 1604 3157 a SDict begin [ /Subtype /Link /Dest (subsection.9.3.5) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1604 3157 a 45 w Fj(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)f(.)40 b(107)345 3321 y SDict begin H.S end 345 3321 a Fj(9.3.6)106 b(Mo)s(dify)30 b(Keyw)m(ord)h(Routines)1684 3321 y SDict begin 13.6 H.L end 1684 3321 a 1684 3321 a SDict begin [ /Subtype /Link /Dest (subsection.9.3.6) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1684 3321 a 36 w Fj(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) f(.)40 b(108)345 3484 y SDict begin H.S end 345 3484 a Fj(9.3.7)106 b(Up)s(date)31 b(Keyw)m(ord)f(Routines)1694 3484 y SDict begin 13.6 H.L end 1694 3484 a 1694 3484 a SDict begin [ /Subtype /Link /Dest (subsection.9.3.7) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1694 3484 a 26 w Fj(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) f(.)40 b(110)136 3648 y SDict begin H.S end 136 3648 a Fj(9.4)94 b(De\014ne)31 b(Data)h(Scaling)f(and)f(Unde\014ned)f(Pixel)i(P)m(arameters)2454 3648 y SDict begin 13.6 H.L end 2454 3648 a 2454 3648 a SDict begin [ /Subtype /Link /Dest (section.9.4) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 2454 3648 a 43 w Fj(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(110)136 3811 y SDict begin H.S end 136 3811 a Fj(9.5)94 b(Sp)s(ecialized)32 b(FITS)d(Primary)h(Arra)m(y)h(or)f(IMA)m(GE)h(Extension)g(I/O)f (Routines)3079 3811 y SDict begin 13.6 H.L end 3079 3811 a 3079 3811 a SDict begin [ /Subtype /Link /Dest (section.9.5) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 3079 3811 a 55 w Fj(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(111)136 3975 y SDict begin H.S end 136 3975 a Fj(9.6)94 b(Sp)s(ecialized)32 b(FITS)d(ASCI)s(I)g (and)h(Binary)g(T)-8 b(able)31 b(Routines)2410 3975 y SDict begin 13.6 H.L end 2410 3975 a 2410 3975 a SDict begin [ /Subtype /Link /Dest (section.9.6) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 2410 3975 a 87 w Fj(.)46 b(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(115)345 4138 y SDict begin H.S end 345 4138 a Fj(9.6.1)106 b(General)32 b(Column)d(Routines)1669 4138 y SDict begin 13.6 H.L end 1669 4138 a 1669 4138 a SDict begin [ /Subtype /Link /Dest (subsection.9.6.1) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1669 4138 a 51 w Fj(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(115)345 4302 y SDict begin H.S end 345 4302 a Fj(9.6.2)106 b(Lo)m(w-Lev)m(el)33 b(T)-8 b(able)31 b(Access)g(Routines)1962 4302 y SDict begin 13.6 H.L end 1962 4302 a 1962 4302 a SDict begin [ /Subtype /Link /Dest (subsection.9.6.2) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1962 4302 a 40 w Fj(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(116)345 4465 y SDict begin H.S end 345 4465 a Fj(9.6.3)106 b(W)-8 b(rite)32 b(Column)e(Data)i(Routines)1809 4465 y SDict begin 13.6 H.L end 1809 4465 a 1809 4465 a SDict begin [ /Subtype /Link /Dest (subsection.9.6.3) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1809 4465 a 52 w Fj(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(117)345 4629 y SDict begin H.S end 345 4629 a Fj(9.6.4)106 b(Read)31 b(Column)e(Data)j (Routines)1789 4629 y SDict begin 13.6 H.L end 1789 4629 a 1789 4629 a SDict begin [ /Subtype /Link /Dest (subsection.9.6.4) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1789 4629 a 72 w Fj(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(118)0 4896 y SDict begin H.S end 0 4896 a Fi(10)67 b(Extended)35 b(File)f(Name)h(Syn)m(tax)1500 4896 y SDict begin 13.6 H.L end 1500 4896 a 1500 4896 a SDict begin [ /Subtype /Link /Dest (chapter.10) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1500 4896 a 2243 w Fi(123)136 5060 y SDict begin H.S end 136 5060 a Fj(10.1)49 b(Ov)m(erview)716 5060 y SDict begin 13.6 H.L end 716 5060 a 716 5060 a SDict begin [ /Subtype /Link /Dest (section.10.1) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 716 5060 a 84 w Fj(.)d(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(123)136 5223 y SDict begin H.S end 136 5223 a Fj(10.2)49 b(Filet)m(yp)s(e)668 5223 y SDict begin 13.6 H.L end 668 5223 a 668 5223 a SDict begin [ /Subtype /Link /Dest (section.10.2) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 668 5223 a 62 w Fj(.)c(.)h(.)g(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)f(.)40 b(126)345 5387 y SDict begin H.S end 345 5387 a Fj(10.2.1)61 b(Notes)32 b(ab)s(out)e(HTTP)g(pro)m(xy)g(serv)m(ers)1968 5387 y SDict begin 13.6 H.L end 1968 5387 a 1968 5387 a SDict begin [ /Subtype /Link /Dest (subsection.10.2.1) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1968 5387 a 34 w Fj(.)46 b(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) f(.)40 b(127)345 5550 y SDict begin H.S end 345 5550 a Fj(10.2.2)61 b(Notes)32 b(ab)s(out)e(HTTPS)f(\014le)i(access)1878 5550 y SDict begin 13.6 H.L end 1878 5550 a 1878 5550 a SDict begin [ /Subtype /Link /Dest (subsection.10.2.2) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1878 5550 a 54 w Fj(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) f(.)40 b(127)345 5714 y SDict begin H.S end 345 5714 a Fj(10.2.3)61 b(Notes)32 b(ab)s(out)e(the)h(stream)f(\014let)m(yp)s(e)h(driv)m(er)2161 5714 y SDict begin 13.6 H.L end 2161 5714 a 2161 5714 a SDict begin [ /Subtype /Link /Dest (subsection.10.2.3) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 2161 5714 a 54 w Fj(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)f(.)40 b(128)p eop end %%Page: 6 6 TeXDict begin 6 5 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.vi) cvn H.B /DEST pdfmark end 0 299 a Fj(vi)3311 b Fh(CONTENTS)345 555 y SDict begin H.S end 345 555 a Fj(10.2.4)61 b(Notes)32 b(ab)s(out)e(the)h(gsiftp)f (\014let)m(yp)s(e)1849 555 y SDict begin 13.6 H.L end 1849 555 a 1849 555 a SDict begin [ /Subtype /Link /Dest (subsection.10.2.4) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1849 555 a 83 w Fj(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(128)345 716 y SDict begin H.S end 345 716 a Fj(10.2.5)61 b(Notes)32 b(ab)s(out)e(the)h(ro)s(ot)f (\014let)m(yp)s(e)1793 716 y SDict begin 13.6 H.L end 1793 716 a 1793 716 a SDict begin [ /Subtype /Link /Dest (subsection.10.2.5) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1793 716 a 68 w Fj(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(129)345 876 y SDict begin H.S end 345 876 a Fj(10.2.6)61 b(Notes)32 b(ab)s(out)e(the)h (shmem)e(\014let)m(yp)s(e:)1932 876 y SDict begin 13.6 H.L end 1932 876 a 1932 876 a SDict begin [ /Subtype /Link /Dest (subsection.10.2.6) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1932 876 a 70 w Fj(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(131)136 1037 y SDict begin H.S end 136 1037 a Fj(10.3)49 b(Base)32 b(Filename)923 1037 y SDict begin 13.6 H.L end 923 1037 a 923 1037 a SDict begin [ /Subtype /Link /Dest (section.10.3) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 923 1037 a 90 w Fj(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)f(.)40 b(131)136 1197 y SDict begin H.S end 136 1197 a Fj(10.4)49 b(Output)30 b(File)h(Name)g(when)f(Op)s(ening)f(an)h(Existing)h(File) 2346 1197 y SDict begin 13.6 H.L end 2346 1197 a 2346 1197 a SDict begin [ /Subtype /Link /Dest (section.10.4) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 2346 1197 a 81 w Fj(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)f(.)40 b(133)136 1358 y SDict begin H.S end 136 1358 a Fj(10.5)49 b(T)-8 b(emplate)32 b(File)g(Name)f(when)e(Creating)i(a)g(New)f(File) 2228 1358 y SDict begin 13.6 H.L end 2228 1358 a 2228 1358 a SDict begin [ /Subtype /Link /Dest (section.10.5) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 2228 1358 a 57 w Fj(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)f(.)40 b(135)136 1518 y SDict begin H.S end 136 1518 a Fj(10.6)49 b(Image)32 b(Tile-Compression)e(Sp)s(eci\014cation)1841 1518 y SDict begin 13.6 H.L end 1841 1518 a 1841 1518 a SDict begin [ /Subtype /Link /Dest (section.10.6) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1841 1518 a 91 w Fj(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(135)136 1678 y SDict begin H.S end 136 1678 a Fj(10.7)49 b(HDU)32 b(Lo)s(cation)f(Sp)s(eci\014cation)1461 1678 y SDict begin 13.6 H.L end 1461 1678 a 1461 1678 a SDict begin [ /Subtype /Link /Dest (section.10.7) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1461 1678 a 47 w Fj(.)45 b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(135)136 1839 y SDict begin H.S end 136 1839 a Fj(10.8)49 b(Image)32 b(Section)903 1839 y SDict begin 13.6 H.L end 903 1839 a 903 1839 a SDict begin [ /Subtype /Link /Dest (section.10.8) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 903 1839 a 39 w Fj(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)f(.)40 b(137)136 1999 y SDict begin H.S end 136 1999 a Fj(10.9)49 b(Image)32 b(T)-8 b(ransform)29 b(Filters)1312 1999 y SDict begin 13.6 H.L end 1312 1999 a 1312 1999 a SDict begin [ /Subtype /Link /Dest (section.10.9) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1312 1999 a 54 w Fj(.)46 b(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(138)136 2160 y SDict begin H.S end 136 2160 a Fj(10.10)t(Column)30 b(and)g(Keyw)m(ord)g(Filtering)h (Sp)s(eci\014cation)2124 2160 y SDict begin 13.6 H.L end 2124 2160 a 2124 2160 a SDict begin [ /Subtype /Link /Dest (section.10.10) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 2124 2160 a 91 w Fj(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(139)136 2320 y SDict begin H.S end 136 2320 a Fj(10.11)t(Ro)m(w)31 b(Filtering)h(Sp)s (eci\014cation)1426 2320 y SDict begin 13.6 H.L end 1426 2320 a 1426 2320 a SDict begin [ /Subtype /Link /Dest (section.10.11) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1426 2320 a 82 w Fj(.)45 b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) f(.)40 b(142)345 2481 y SDict begin H.S end 345 2481 a Fj(10.11.1)16 b(General)32 b(Syn)m(tax)1251 2481 y SDict begin 13.6 H.L end 1251 2481 a 1251 2481 a SDict begin [ /Subtype /Link /Dest (subsection.10.11.1) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1251 2481 a 44 w Fj(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)f(.)40 b(142)345 2641 y SDict begin H.S end 345 2641 a Fj(10.11.2)16 b(Bit)32 b(Masks)1040 2641 y SDict begin 13.6 H.L end 1040 2641 a 1040 2641 a SDict begin [ /Subtype /Link /Dest (subsection.10.11.2) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1040 2641 a 43 w Fj(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(145)345 2802 y SDict begin H.S end 345 2802 a Fj(10.11.3)16 b(V)-8 b(ector)32 b(Columns)1274 2802 y SDict begin 13.6 H.L end 1274 2802 a 1274 2802 a SDict begin [ /Subtype /Link /Dest (subsection.10.11.3) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1274 2802 a 92 w Fj(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(146)345 2962 y SDict begin H.S end 345 2962 a Fj(10.11.4)16 b(Go)s(o)s(d)30 b(Time)h(In)m(terv)-5 b(al)31 b(Filtering)1799 2962 y SDict begin 13.6 H.L end 1799 2962 a 1799 2962 a SDict begin [ /Subtype /Link /Dest (subsection.10.11.4) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1799 2962 a 62 w Fj(.)46 b(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)f(.)40 b(147)345 3123 y SDict begin H.S end 345 3123 a Fj(10.11.5)16 b(Spatial)31 b(Region)h(Filtering)1590 3123 y SDict begin 13.6 H.L end 1590 3123 a 1590 3123 a SDict begin [ /Subtype /Link /Dest (subsection.10.11.5) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1590 3123 a 59 w Fj(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)f(.)40 b(148)345 3283 y SDict begin H.S end 345 3283 a Fj(10.11.6)16 b(Example)31 b(Ro)m(w)g(Filters)1476 3283 y SDict begin 13.6 H.L end 1476 3283 a 1476 3283 a SDict begin [ /Subtype /Link /Dest (subsection.10.11.6) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1476 3283 a 32 w Fj(.)45 b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)f(.)40 b(150)136 3444 y SDict begin H.S end 136 3444 a Fj(10.12)35 b(Binning)30 b(or)g(Histogramming)i(Sp)s(eci\014cation)1971 3444 y SDict begin 13.6 H.L end 1971 3444 a 1971 3444 a SDict begin [ /Subtype /Link /Dest (section.10.12) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1971 3444 a 31 w Fj(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(151)0 3696 y SDict begin H.S end 0 3696 a Fi(11)32 b(T)-9 b(emplate)35 b(Files)845 3696 y SDict begin 13.6 H.L end 845 3696 a 845 3696 a SDict begin [ /Subtype /Link /Dest (chapter.11) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 845 3696 a 2898 w Fi(155)136 3857 y SDict begin H.S end 136 3857 a Fj(11.1)49 b(Detailed)33 b(T)-8 b(emplate)31 b(Line)g(F)-8 b(ormat)1601 3857 y SDict begin 13.6 H.L end 1601 3857 a 1601 3857 a SDict begin [ /Subtype /Link /Dest (section.11.1) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1601 3857 a 48 w Fj(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(155)136 4017 y SDict begin H.S end 136 4017 a Fj(11.2)49 b(Auto-indexing)31 b(of)g(Keyw)m(ords)1435 4017 y SDict begin 13.6 H.L end 1435 4017 a 1435 4017 a SDict begin [ /Subtype /Link /Dest (section.11.2) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1435 4017 a 73 w Fj(.)45 b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)f(.)40 b(156)136 4178 y SDict begin H.S end 136 4178 a Fj(11.3)49 b(T)-8 b(emplate)32 b(P)m(arser)f(Directiv)m(es)1421 4178 y SDict begin 13.6 H.L end 1421 4178 a 1421 4178 a SDict begin [ /Subtype /Link /Dest (section.11.3) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1421 4178 a 87 w Fj(.)45 b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(157)136 4338 y SDict begin H.S end 136 4338 a Fj(11.4)49 b(F)-8 b(ormal)32 b(T)-8 b(emplate)32 b(Syn)m(tax)1332 4338 y SDict begin 13.6 H.L end 1332 4338 a 1332 4338 a SDict begin [ /Subtype /Link /Dest (section.11.4) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1332 4338 a 34 w Fj(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(158)136 4498 y SDict begin H.S end 136 4498 a Fj(11.5)49 b(Errors)596 4498 y SDict begin 13.6 H.L end 596 4498 a 596 4498 a SDict begin [ /Subtype /Link /Dest (section.11.5) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 596 4498 a 63 w Fj(.)d(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(158)136 4659 y SDict begin H.S end 136 4659 a Fj(11.6)49 b(Examples)728 4659 y SDict begin 13.6 H.L end 728 4659 a 728 4659 a SDict begin [ /Subtype /Link /Dest (section.11.6) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 728 4659 a 72 w Fj(.)d(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f (.)40 b(158)0 4912 y SDict begin H.S end 0 4912 a Fi(12)67 b(Lo)s(cal)35 b(FITS)g(Con)m(v)m(en)m(tions)1316 4912 y SDict begin 13.6 H.L end 1316 4912 a 1316 4912 a SDict begin [ /Subtype /Link /Dest (chapter.12) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1316 4912 a 2427 w Fi(161)136 5072 y SDict begin H.S end 136 5072 a Fj(12.1)49 b(64-Bit)33 b(Long)e(In)m(tegers)1164 5072 y SDict begin 13.6 H.L end 1164 5072 a 1164 5072 a SDict begin [ /Subtype /Link /Dest (section.12.1) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1164 5072 a 61 w Fj(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.) 40 b(161)136 5232 y SDict begin H.S end 136 5232 a Fj(12.2)49 b(Long)31 b(String)f(Keyw)m (ord)g(V)-8 b(alues.)1513 5232 y SDict begin 13.6 H.L end 1513 5232 a 1513 5232 a SDict begin [ /Subtype /Link /Dest (section.12.2) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1513 5232 a 65 w Fj(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)f(.)40 b(161)136 5393 y SDict begin H.S end 136 5393 a Fj(12.3)49 b(Arra)m(ys)31 b(of)f(Fixed-Length)i(Strings)d(in)h(Binary)h(T)-8 b(ables)2278 5393 y SDict begin 13.6 H.L end 2278 5393 a 2278 5393 a SDict begin [ /Subtype /Link /Dest (section.12.3) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 2278 5393 a 78 w Fj(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)f(.)40 b(163)136 5553 y SDict begin H.S end 136 5553 a Fj(12.4)49 b(Keyw)m(ord)31 b(Units)f(Strings)1254 5553 y SDict begin 13.6 H.L end 1254 5553 a 1254 5553 a SDict begin [ /Subtype /Link /Dest (section.12.4) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1254 5553 a 41 w Fj(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)f(.)40 b(163)136 5714 y SDict begin H.S end 136 5714 a Fj(12.5)49 b(HIERAR)m(CH)31 b(Con)m(v)m(en)m(tion)h(for)e(Extended)g(Keyw)m(ord)g (Names)2548 5714 y SDict begin 13.6 H.L end 2548 5714 a 2548 5714 a SDict begin [ /Subtype /Link /Dest (section.12.5) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 2548 5714 a 91 w Fj(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) f(.)40 b(163)p eop end %%Page: 7 7 TeXDict begin 7 6 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.vii) cvn H.B /DEST pdfmark end 0 299 a Fh(CONTENTS)3284 b Fj(vii)136 555 y SDict begin H.S end 136 555 a Fj(12.6)49 b(Tile-Compressed)31 b(Image)g(F)-8 b(ormat)1597 555 y SDict begin 13.6 H.L end 1597 555 a 1597 555 a SDict begin [ /Subtype /Link /Dest (section.12.6) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1597 555 a 52 w Fj(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(164)0 806 y SDict begin H.S end 0 806 a Fi(13)67 b(Optimizing)35 b(Programs)1191 806 y SDict begin 13.6 H.L end 1191 806 a 1191 806 a SDict begin [ /Subtype /Link /Dest (chapter.13) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1191 806 a 2552 w Fi(167)136 966 y SDict begin H.S end 136 966 a Fj(13.1)49 b(Ho)m(w)32 b(CFITSIO)c(Manages)k(Data)g (I/O)1712 966 y SDict begin 13.6 H.L end 1712 966 a 1712 966 a SDict begin [ /Subtype /Link /Dest (section.13.1) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1712 966 a 78 w Fj(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(167)136 1127 y SDict begin H.S end 136 1127 a Fj(13.2)49 b(Optimization)32 b(Strategies)1289 1127 y SDict begin 13.6 H.L end 1289 1127 a 1289 1127 a SDict begin [ /Subtype /Link /Dest (section.13.2) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1289 1127 a 77 w Fj(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(168)0 1378 y SDict begin H.S end 0 1378 a Fi(A)57 b(Index)35 b(of)g(Routines)990 1378 y SDict begin 13.6 H.L end 990 1378 a 990 1378 a SDict begin [ /Subtype /Link /Dest (appendix.A) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 990 1378 a 2753 w Fi(173)0 1629 y SDict begin H.S end 0 1629 a Fi(B)62 b(P)m(arameter)35 b(De\014nitions)1181 1629 y SDict begin 13.6 H.L end 1181 1629 a 1181 1629 a SDict begin [ /Subtype /Link /Dest (appendix.B) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1181 1629 a 2562 w Fi(179)0 1880 y SDict begin H.S end 0 1880 a Fi(C)60 b(CFITSIO)33 b(Error)i(Status)f(Co)s(des)1523 1880 y SDict begin 13.6 H.L end 1523 1880 a 1523 1880 a SDict begin [ /Subtype /Link /Dest (appendix.C) cvn /H /I /Border [0 0 12] /Color [1 0 0] H.B /ANN pdfmark end 1523 1880 a 2220 w Fi(185)p eop end %%Page: 8 8 TeXDict begin 8 7 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.viii) cvn H.B /DEST pdfmark end 0 299 a Fj(viii)3261 b Fh(CONTENTS)p eop end %%Page: 1 9 TeXDict begin 1 8 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.1) cvn H.B /DEST pdfmark end 0 299 a 0 464 a SDict begin H.S end 0 464 a 0 464 a SDict begin 13.6 H.A end 0 464 a 0 464 a SDict begin [ /View [/XYZ H.V] /Dest (chapter.1) cvn H.B /DEST pdfmark end 0 464 a 761 x Fg(Chapter)65 b(1)0 1687 y Fm(In)-6 b(tro)6 b(duction)0 2020 y SDict begin H.S end 0 2020 a 0 2020 a SDict begin 13.6 H.A end 0 2020 a 0 2020 a SDict begin [ /View [/XYZ H.V] /Dest (section.1.1) cvn H.B /DEST pdfmark end 0 2020 a 196 x Ff(1.1)180 b(A)45 b(Brief)g(Ov)l(erview)0 2495 y Fj(CFITSIO)22 b(is)h(a)g(mac)m(hine-indep)s(enden)m(t)g(library) g(of)g(routines)h(for)e(reading)i(and)e(writing)h(data)h(\014les)f(in)g (the)h(FITS)0 2608 y(\(Flexible)30 b(Image)e(T)-8 b(ransp)s(ort)27 b(System\))i(data)f(format.)40 b(It)29 b(can)f(also)h(read)f(IRAF)g (format)g(image)h(\014les)f(and)g(ra)m(w)0 2721 y(binary)39 b(data)i(arra)m(ys)g(b)m(y)f(con)m(v)m(erting)i(them)e(on)g(the)g (\015y)g(in)m(to)h(a)f(virtual)h(FITS)e(format)i(\014le.)70 b(This)39 b(library)0 2833 y(is)c(written)g(in)g(ANSI)f(C)h(and)f(pro)m (vides)h(a)h(p)s(o)m(w)m(erful)e(y)m(et)i(simple)f(in)m(terface)i(for)e (accessing)h(FITS)e(\014les)h(whic)m(h)0 2946 y(will)c(run)f(on)h(most) g(commonly)h(used)e(computers)h(and)f(w)m(orkstations.)44 b(CFITSIO)29 b(supp)s(orts)h(all)h(the)h(features)0 3059 y(describ)s(ed)39 b(in)g(the)h(o\016cial)i(de\014nition)d(of)h(the)g (FITS)f(format)i(and)e(can)h(read)g(and)f(write)h(all)h(the)f(curren)m (tly)0 3172 y(de\014ned)g(t)m(yp)s(es)h(of)g(extensions,)j(including)d (ASCI)s(I)e(tables)j(\(T)-8 b(ABLE\),)42 b(Binary)f(tables)h(\(BINT)-8 b(ABLE\))43 b(and)0 3285 y(IMA)m(GE)30 b(extensions.)41 b(The)28 b(CFITSIO)f(routines)i(insulate)h(the)f(programmer)f(from)h (ha)m(ving)g(to)h(deal)f(with)g(the)0 3398 y(complicated)36 b(formatting)g(details)g(in)e(the)h(FITS)f(\014le,)i(ho)m(w)m(ev)m(er,) h(it)e(is)g(assumed)f(that)h(users)f(ha)m(v)m(e)i(a)f(general)0 3511 y(kno)m(wledge)c(ab)s(out)f(the)h(structure)f(and)g(usage)h(of)f (FITS)g(\014les.)0 3671 y(CFITSIO)k(also)j(con)m(tains)h(a)e(set)h(of)f (F)-8 b(ortran)36 b(callable)i(wrapp)s(er)d(routines)g(whic)m(h)h(allo) m(w)i(F)-8 b(ortran)36 b(programs)0 3784 y(to)31 b(call)g(the)f (CFITSIO)e(routines.)41 b(See)30 b(the)g(companion)g(\\FITSIO)f(User's) h(Guide")g(for)g(the)g(de\014nition)g(of)g(the)0 3897 y(F)-8 b(ortran)39 b(subroutine)d(calling)k(sequences.)63 b(These)38 b(wrapp)s(ers)e(replace)j(the)f(older)g(F)-8 b(ortran)39 b(FITSIO)d(library)0 4010 y(whic)m(h)30 b(is)h(no)f(longer) h(supp)s(orted.)0 4170 y(The)20 b(CFITSIO)f(pac)m(k)-5 b(age)23 b(w)m(as)e(initially)i(dev)m(elop)s(ed)e(b)m(y)f(the)h(HEASAR) m(C)g(\(High)h(Energy)e(Astroph)m(ysics)h(Science)0 4283 y(Arc)m(hiv)m(e)35 b(Researc)m(h)g(Cen)m(ter\))f(at)h(the)f(NASA)g(Go)s (ddard)e(Space)j(Fligh)m(t)g(Cen)m(ter)f(to)h(con)m(v)m(ert)g(v)-5 b(arious)34 b(existing)0 4396 y(and)25 b(newly)h(acquired)g (astronomical)i(data)e(sets)h(in)m(to)g(FITS)e(format)h(and)f(to)i (further)e(analyze)i(data)g(already)f(in)0 4509 y(FITS)h(format.)41 b(New)28 b(features)g(con)m(tin)m(ue)h(to)g(b)s(e)e(added)h(to)g (CFITSIO)f(in)g(large)i(part)f(due)g(to)g(con)m(tributions)h(of)0 4622 y(ideas)k(or)g(actual)h(co)s(de)f(from)f(users)g(of)h(the)g(pac)m (k)-5 b(age.)49 b(The)33 b(In)m(tegral)h(Science)f(Data)h(Cen)m(ter)f (in)g(Switzerland,)0 4734 y(and)g(the)g(XMM/ESTEC)h(pro)5 b(ject)34 b(in)f(The)g(Netherlands)g(made)g(esp)s(ecially)i (signi\014can)m(t)f(con)m(tributions)g(that)0 4847 y(resulted)c(in)g (man)m(y)h(of)f(the)h(new)f(features)g(that)h(app)s(eared)f(in)g(v2.0)i (of)e(CFITSIO.)0 5143 y SDict begin H.S end 0 5143 a 0 5143 a SDict begin 13.6 H.A end 0 5143 a 0 5143 a SDict begin [ /View [/XYZ H.V] /Dest (section.1.2) cvn H.B /DEST pdfmark end 0 5143 a 179 x Ff(1.2)135 b(Sources)45 b(of)g(FITS)f(Soft)l(w)l (are)i(and)f(Information)0 5601 y Fj(The)22 b(latest)i(v)m(ersion)f(of) g(the)f(CFITSIO)f(source)i(co)s(de,)h(do)s(cumen)m(tation,)i(and)21 b(example)j(programs)e(are)h(a)m(v)-5 b(ailable)0 5714 y(on)30 b(the)h(W)-8 b(eb)31 b(or)f(via)h(anon)m(ymous)g(ftp)e(from:) 1927 5942 y(1)p eop end %%Page: 2 10 TeXDict begin 2 9 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.2) cvn H.B /DEST pdfmark end 0 299 a Fj(2)2452 b Fh(CHAPTER)30 b(1.)71 b(INTR)m(ODUCTION)382 555 y Fe(http://heasarc.gsfc.nasa)o(.go)o(v/fi)o (tsio)382 668 y(ftp://legacy.gsfc.nasa.g)o(ov/)o(soft)o(ware)o(/fi)o (tsio)o(/c)0 933 y Fj(An)m(y)28 b(questions,)g(bug)f(rep)s(orts,)h(or)f (suggested)i(enhancemen)m(ts)f(related)g(to)h(the)e(CFITSIO)f(pac)m(k) -5 b(age)30 b(should)d(b)s(e)0 1045 y(sen)m(t)k(to)g(the)g(FTOOLS)e (Help)h(Desk)h(at)g(the)g(HEASAR)m(C:)382 1310 y Fe (http://heasarc.gsfc.nasa)o(.go)o(v/cg)o(i-bi)o(n/f)o(tool)o(shel)o(p)0 1574 y Fj(This)40 b(User's)i(Guide)f(assumes)g(that)h(readers)f (already)g(ha)m(v)m(e)i(a)f(general)g(understanding)d(of)j(the)f (de\014nition)0 1687 y(and)31 b(structure)g(of)h(FITS)e(format)i (\014les.)44 b(F)-8 b(urther)32 b(information)f(ab)s(out)h(FITS)f (formats)g(is)h(a)m(v)-5 b(ailable)34 b(from)d(the)0 1800 y(FITS)37 b(Supp)s(ort)f(O\016ce)i(at)h Fe (http://fits.gsfc.nasa.g)o(ov)p Fj(.)57 b(In)37 b(particular,)j(the)e ('FITS)g(Standard')f(giv)m(es)0 1913 y(the)31 b(authoritativ)m(e)j (de\014nition)d(of)g(the)h(FITS)e(data)i(format.)43 b(Other)31 b(do)s(cumen)m(ts)g(a)m(v)-5 b(ailable)34 b(at)d(that)h(W)-8 b(eb)32 b(site)0 2026 y(pro)m(vide)e(additional)i(historical)f(bac)m (kground)g(and)e(practical)j(advice)g(on)e(using)g(FITS)f(\014les.)0 2186 y(The)d(HEASAR)m(C)f(also)i(pro)m(vides)f(a)h(v)m(ery)f (sophisticated)h(FITS)e(\014le)i(analysis)f(program)g(called)h(`Fv')g (whic)m(h)f(can)0 2299 y(b)s(e)31 b(used)f(to)i(displa)m(y)f(and)g (edit)g(the)h(con)m(ten)m(ts)g(of)g(an)m(y)f(FITS)g(\014le)g(as)g(w)m (ell)h(as)g(construct)f(new)g(FITS)f(\014les)h(from)0 2412 y(scratc)m(h.)56 b(Fv)36 b(is)f(freely)h(a)m(v)-5 b(ailable)37 b(for)e(most)h(Unix)f(platforms,)i(Mac)f(PCs,)g(and)f (Windo)m(ws)g(PCs.)54 b(CFITSIO)0 2525 y(users)29 b(ma)m(y)h(also)h(b)s (e)f(in)m(terested)g(in)g(the)g(FTOOLS)f(pac)m(k)-5 b(age)31 b(of)g(programs)e(that)h(can)h(b)s(e)e(used)g(to)i(manipulate)0 2638 y(and)f(analyze)i(FITS)d(format)i(\014les.)41 b(Fv)30 b(and)g(FTOOLS)f(are)i(a)m(v)-5 b(ailable)32 b(from)e(their)h(resp)s (ectiv)m(e)g(W)-8 b(eb)31 b(sites)g(at:)382 2902 y Fe (http://fv.gsfc.nasa.gov)382 3015 y(http://heasarc.gsfc.nasa)o(.go)o (v/ft)o(ools)0 3178 y SDict begin H.S end 0 3178 a 0 3178 a SDict begin 13.6 H.A end 0 3178 a 0 3178 a SDict begin [ /View [/XYZ H.V] /Dest (section.1.3) cvn H.B /DEST pdfmark end 0 3178 a 176 x Ff(1.3)135 b(Ac)l(kno)l(wledgmen)l(ts)0 3605 y Fj(The)27 b(dev)m(elopmen)m(t)h(of)g(the)f(man)m(y)g(p)s(o)m(w)m (erful)g(features)h(in)f(CFITSIO)e(w)m(as)j(made)f(p)s(ossible)g (through)f(collab)s(ora-)0 3718 y(tions)33 b(with)e(man)m(y)i(p)s (eople)f(or)g(organizations)i(from)e(around)f(the)h(w)m(orld.)46 b(The)32 b(follo)m(wing)h(in)f(particular)h(ha)m(v)m(e)0 3831 y(made)d(esp)s(ecially)i(signi\014can)m(t)f(con)m(tributions:)0 3991 y(Programmers)25 b(from)h(the)f(In)m(tegral)i(Science)g(Data)g (Cen)m(ter,)g(Switzerland)f(\(namely)-8 b(,)28 b(Jurek)c(Bork)m(o)m (wski,)29 b(Bruce)0 4104 y(O'Neel,)34 b(and)e(Don)h(Jennings\),)f (designed)g(the)h(concept)g(for)f(the)h(plug-in)f(I/O)g(driv)m(ers)g (that)h(w)m(as)g(in)m(tro)s(duced)0 4217 y(with)i(CFITSIO)e(2.0.)56 b(The)34 b(use)h(of)g(`driv)m(ers')g(greatly)h(simpli\014ed)f(the)g(lo) m(w-lev)m(el)j(I/O,)d(whic)m(h)f(in)h(turn)f(made)0 4330 y(other)40 b(new)f(features)i(in)e(CFITSIO)f(\(e.g.,)45 b(supp)s(ort)38 b(for)h(compressed)h(FITS)f(\014les)h(and)f(supp)s(ort) f(for)i(IRAF)0 4443 y(format)32 b(image)g(\014les\))g(m)m(uc)m(h)f (easier)i(to)f(implemen)m(t.)44 b(Jurek)31 b(Bork)m(o)m(wski)h(wrote)g (the)g(Shared)e(Memory)i(driv)m(er,)0 4556 y(and)23 b(Bruce)i(O'Neel)g (wrote)f(the)g(driv)m(ers)g(for)f(accessing)j(FITS)d(\014les)h(o)m(v)m (er)h(the)f(net)m(w)m(ork)h(using)e(the)i(FTP)-8 b(,)24 b(HTTP)-8 b(,)0 4669 y(and)26 b(R)m(OOT)g(proto)s(cols.)41 b(Also,)28 b(in)e(2009,)k(Bruce)d(O'Neel)h(w)m(as)f(the)g(k)m(ey)g(dev) m(elop)s(er)g(of)g(the)g(thread-safe)g(v)m(ersion)0 4782 y(of)k(CFITSIO.)0 4942 y(The)45 b(ISDC)g(also)h(pro)m(vided)f(the)h (template)h(parsing)e(routines)g(\(written)h(b)m(y)f(Jurek)g(Bork)m(o)m (wski\))i(and)e(the)0 5055 y(hierarc)m(hical)39 b(grouping)d(routines)h (\(written)h(b)m(y)f(Don)h(Jennings\).)60 b(The)37 b(ISDC)f(D)m(AL)i (\(Data)h(Access)f(La)m(y)m(er\))0 5168 y(routines)30 b(are)h(la)m(y)m(ered)h(on)e(top)h(of)f(CFITSIO)f(and)h(mak)m(e)h (extensiv)m(e)h(use)e(of)h(these)g(features.)0 5328 y(Giuliano)g(T)-8 b(a\013oni)31 b(and)f(Andrea)g(Barisani,)i(at)f(INAF,)g(Univ)m(ersit)m (y)h(of)e(T)-8 b(rieste,)32 b(Italy)-8 b(,)32 b(implemen)m(ted)e(the)h (I/O)0 5441 y(driv)m(er)f(routines)g(for)h(accessing)g(FITS)f(\014les)g (on)h(the)f(computational)i(grids)e(using)g(the)h(gridftp)e(proto)s (col.)0 5601 y(Uw)m(e)c(Lammers)e(\(XMM/ESA/ESTEC,)h(The)g (Netherlands\))g(designed)g(the)g(high-p)s(erformance)f(lexical)j (pars-)0 5714 y(ing)42 b(algorithm)h(that)f(is)g(used)f(to)i(do)e (on-the-\015y)h(\014ltering)g(of)g(FITS)f(tables.)76 b(This)41 b(algorithm)i(essen)m(tially)p eop end %%Page: 3 11 TeXDict begin 3 10 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.3) cvn H.B /DEST pdfmark end 0 299 a Fh(1.3.)72 b(A)m(CKNO)m(WLEDGMENTS)2623 b Fj(3)0 555 y(pre-compiles)36 b(the)g(user-supplied)e(selection)k (expression)d(in)m(to)i(a)f(form)g(that)g(can)g(b)s(e)f(rapidly)g(ev)-5 b(aluated)37 b(for)0 668 y(eac)m(h)31 b(ro)m(w.)40 b(P)m(eter)31 b(Wilson)f(\(RSTX,)f(NASA/GSF)m(C\))i(then)e(wrote)h(the)g(parsing)f (routines)g(used)g(b)m(y)g(CFITSIO)0 781 y(based)i(on)f(Lammers')h (design,)g(com)m(bined)g(with)g(other)g(tec)m(hniques)g(suc)m(h)g(as)g (the)g(CFITSIO)f(iterator)i(routine)0 894 y(to)g(further)e(enhance)h (the)h(data)g(pro)s(cessing)f(throughput.)42 b(This)31 b(e\013ort)h(also)g(b)s(ene\014ted)e(from)h(a)h(m)m(uc)m(h)f(earlier)0 1007 y(lexical)25 b(parsing)f(routine)f(that)h(w)m(as)g(dev)m(elop)s (ed)g(b)m(y)g(Ken)m(t)g(Blac)m(kburn)f(\(NASA/GSF)m(C\).)i(More)g (recen)m(tly)-8 b(,)27 b(Craig)0 1120 y(Markw)m(ardt)i(\(NASA/GSF)m (C\))g(implemen)m(ted)g(additional)g(functions)f(\(median,)h(a)m(v)m (erage,)j(stddev\))c(and)g(other)0 1233 y(enhancemen)m(ts)j(to)g(the)g (lexical)h(parser.)0 1393 y(The)40 b(CFITSIO)g(iterator)i(function)e (is)h(lo)s(osely)h(based)f(on)f(similar)i(ideas)f(dev)m(elop)s(ed)g (for)g(the)g(XMM)g(Data)0 1506 y(Access)31 b(La)m(y)m(er.)0 1666 y(P)m(eter)25 b(Wilson)g(\(RSTX,)f(NASA/GSF)m(C\))h(wrote)g(the)f (complete)i(set)e(of)h(F)-8 b(ortran-callable)27 b(wrapp)s(ers)22 b(for)i(all)h(the)0 1779 y(CFITSIO)k(routines,)h(whic)m(h)g(in)g(turn)g (rely)g(on)h(the)f(CF)m(OR)-8 b(TRAN)31 b(macro)g(dev)m(elop)s(ed)g(b)m (y)f(Burkhard)f(Buro)m(w.)0 1939 y(The)h(syn)m(tax)i(used)e(b)m(y)h (CFITSIO)f(for)g(\014ltering)i(or)f(binning)e(input)h(FITS)h(\014les)g (is)g(based)f(on)h(ideas)h(dev)m(elop)s(ed)0 2052 y(for)41 b(the)g(AXAF)h(Science)g(Cen)m(ter)g(Data)h(Mo)s(del)e(b)m(y)g (Jonathan)g(McDo)m(w)m(ell,)47 b(An)m(tonella)c(F)-8 b(ruscione,)45 b(Aneta)0 2165 y(Siemigino)m(wsk)-5 b(a)27 b(and)e(Bill)i(Jo)m(y)m(e.)41 b(See)26 b(h)m (ttp://heasarc.gsfc.nasa.go)m(v/do)s(cs/journal/axa)q(f7.h)m(t)q(ml)32 b(for)25 b(further)0 2278 y(description)30 b(of)h(the)g(AXAF)g(Data)h (Mo)s(del.)0 2438 y(The)j(\014le)g(decompression)g(co)s(de)g(w)m(ere)h (tak)m(en)g(directly)g(from)e(the)i(gzip)f(\(GNU)h(zip\))g(program)f (dev)m(elop)s(ed)g(b)m(y)0 2551 y(Jean-loup)30 b(Gailly)i(and)e (others.)0 2711 y(The)e(new)h(compressed)g(image)h(data)g(format)f (\(where)g(the)g(image)h(is)f(tiled)h(and)e(the)h(compressed)g(b)m(yte) h(stream)0 2824 y(from)k(eac)m(h)i(tile)h(is)d(stored)h(in)g(a)g (binary)f(table\))j(w)m(as)e(implemen)m(ted)g(in)g(collab)s(oration)i (with)d(Ric)m(hard)h(White)0 2937 y(\(STScI\),)30 b(P)m(erry)g (Green\014eld)h(\(STScI\))f(and)f(Doug)i(T)-8 b(o)s(dy)30 b(\(NO)m(A)m(O\).)0 3097 y(Doug)h(Mink)g(\(SA)m(O\))f(pro)m(vided)g (the)h(routines)f(for)g(con)m(v)m(erting)j(IRAF)d(format)h(images)g(in) m(to)h(FITS)d(format.)0 3257 y(Martin)k(Reinec)m(k)m(e)i(\(Max)f(Planc) m(k)f(Institute,)h(Garc)m(hing\)\))g(pro)m(vided)f(the)g(mo)s (di\014cations)f(to)i(cfortran.h)e(that)0 3370 y(are)d(necessary)h(to)f (supp)s(ort)e(64-bit)k(in)m(teger)f(v)-5 b(alues)29 b(when)f(calling)i (C)f(routines)g(from)f(fortran)h(programs.)39 b(The)0 3483 y(cfortran.h)30 b(macros)h(w)m(ere)g(originally)h(dev)m(elop)s(ed) e(b)m(y)h(Burkhard)e(Buro)m(w)h(\(CERN\).)0 3643 y(Julian)f(T)-8 b(a)m(ylor)31 b(\(ESO,)e(Garc)m(hing\))i(pro)m(vided)e(the)g(fast)h(b)m (yte-sw)m(apping)g(algorithms)h(that)f(use)f(the)h(SSE2)f(and)0 3756 y(SSSE3)g(mac)m(hine)i(instructions)f(a)m(v)-5 b(ailable)33 b(on)d(x86)p 1784 3756 28 4 v 34 w(64)h(CPUs.)0 3916 y(In)c(addition,)i(man)m(y)f(other)g(p)s(eople)g(ha)m(v)m(e)h(made)f(v) -5 b(aluable)29 b(con)m(tributions)f(to)h(the)f(dev)m(elopmen)m(t)h(of) f(CFITSIO.)0 4029 y(These)i(include)g(\(with)h(ap)s(ologies)h(to)f (others)f(that)h(ma)m(y)g(ha)m(v)m(e)h(inadv)m(erten)m(tly)g(b)s(een)d (omitted\):)0 4189 y(Stev)m(e)g(Allen,)g(Carl)f(Ak)m(erlof,)h(Keith)f (Arnaud,)g(Morten)g(Krabb)s(e)e(Barfo)s(ed,)j(Ken)m(t)f(Blac)m(kburn,)h (G)f(Bo)s(dammer,)0 4302 y(Romk)m(e)h(Bon)m(tek)m(o)s(e,)i(Lucio)d (Chiapp)s(etti,)g(Keith)g(Costorf,)g(Robin)g(Corb)s(et,)g(John)e(Da)m (vis,)k(Ric)m(hard)e(Fink,)h(Ning)0 4415 y(Gan,)i(Emily)f(Greene,)h (Gretc)m(hen)g(Green,)f(Jo)s(e)g(Harrington,)h(Cheng)f(Ho,)h(Phil)f(Ho) s(dge,)g(Jim)g(Ingham,)g(Y)-8 b(oshi-)0 4528 y(tak)j(a)44 b(Ishisaki,)i(Diab)e(Jerius,)h(Mark)f(Levine,)i(T)-8 b(o)s(dd)42 b(Karak)-5 b(askian,)47 b(Edw)m(ard)42 b(King,)k(Scott)e (Ko)s(c)m(h,)i(Claire)0 4641 y(Larkin,)32 b(Rob)g(Managan,)i(Eric)e (Mandel,)h(Ric)m(hard)f(Mathar,)h(John)e(Matto)m(x,)k(Carsten)d(Mey)m (er,)i(Emi)d(Miy)m(ata,)0 4754 y(Stefan)39 b(Mo)s(c)m(hnac)m(ki,)k(Mik) m(e)e(Noble,)h(Oliv)m(er)e(Ob)s(erdorf,)f(Cliv)m(e)i(P)m(age,)i(Arvind) 38 b(P)m(armar,)j(Je\013)f(P)m(edelt)m(y)-8 b(,)43 b(Tim)0 4867 y(P)m(earson,)d(Philipp)s(e)c(Prugniel,)j(Maren)e(Purv)m(es,)i (Scott)g(Randall,)g(Chris)d(Rogers,)k(Arnold)d(Rots,)i(Rob)e(Sea-)0 4979 y(man,)23 b(Barry)e(Sc)m(hlesinger,)i(Robin)e(Stebbins,)h(Andrew)d (Szymk)m(o)m(wiak,)25 b(Allyn)c(T)-8 b(ennan)m(t,)23 b(P)m(eter)f(T)-8 b(eub)s(en,)22 b(James)0 5092 y(Theiler,)k(Doug)g(T) -8 b(o)s(dy)g(,)25 b(Shiro)f(Ueno,)j(Stev)m(e)f(W)-8 b(alton,)28 b(Arc)m(hie)d(W)-8 b(arno)s(c)m(k,)27 b(Alan)e(W)-8 b(atson,)28 b(Dan)d(Whipple,)h(Wim)0 5205 y(Wimmers,)31 b(P)m(eter)g(Y)-8 b(oung,)31 b(Jianjun)e(Xu,)h(and)g(Nelson)h(Zarate.)p eop end %%Page: 4 12 TeXDict begin 4 11 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.4) cvn H.B /DEST pdfmark end 0 299 a Fj(4)2452 b Fh(CHAPTER)30 b(1.)71 b(INTR)m(ODUCTION)0 464 y SDict begin H.S end 0 464 a 0 464 a SDict begin 13.6 H.A end 0 464 a 0 464 a SDict begin [ /View [/XYZ H.V] /Dest (section.1.4) cvn H.B /DEST pdfmark end 0 464 a 91 x Ff(1.4)135 b(Legal)46 b(Stu\013)0 805 y Fj(Cop)m(yrigh)m(t)37 b(\(Unpublished{all)g(righ)m(ts)g(reserv)m (ed)g(under)e(the)i(cop)m(yrigh)m(t)h(la)m(ws)f(of)g(the)g(United)g (States\),)j(U.S.)0 918 y(Go)m(v)m(ernmen)m(t)30 b(as)g(represen)m(ted) e(b)m(y)h(the)g(Administrator)g(of)g(the)g(National)h(Aeronautics)g (and)e(Space)h(Adminis-)0 1031 y(tration.)42 b(No)31 b(cop)m(yrigh)m(t)g(is)g(claimed)g(in)f(the)h(United)f(States)h(under)e (Title)j(17,)f(U.S.)f(Co)s(de.)0 1191 y(P)m(ermission)g(to)g(freely)f (use,)h(cop)m(y)-8 b(,)31 b(mo)s(dify)-8 b(,)29 b(and)g(distribute)g (this)g(soft)m(w)m(are)i(and)e(its)h(do)s(cumen)m(tation)g(without)0 1304 y(fee)f(is)f(hereb)m(y)g(gran)m(ted,)i(pro)m(vided)e(that)h(this)f (cop)m(yrigh)m(t)i(notice)f(and)f(disclaimer)h(of)f(w)m(arran)m(t)m(y)i (app)s(ears)d(in)h(all)0 1417 y(copies.)0 1577 y(DISCLAIMER:)0 1737 y(THE)33 b(SOFTW)-10 b(ARE)32 b(IS)g(PR)m(O)m(VIDED)i('AS)f(IS')g (WITHOUT)f(ANY)i(W)-10 b(ARRANTY)33 b(OF)g(ANY)h(KIND,)f(EI-)0 1850 y(THER)42 b(EXPRESSED,)f(IMPLIED,)i(OR)e(ST)-8 b(A)g(TUTOR)g(Y,)43 b(INCLUDING,)f(BUT)h(NOT)e(LIMITED)h(TO,)0 1963 y(ANY)33 b(W)-10 b(ARRANTY)33 b(THA)-8 b(T)32 b(THE)g(SOFTW)-10 b(ARE)32 b(WILL)g(CONF)m(ORM)g(TO)g(SPECIFICA)-8 b(TIONS,)30 b(ANY)0 2076 y(IMPLIED)38 b(W)-10 b(ARRANTIES)37 b(OF)h(MER)m(CHANT)-8 b(ABILITY,)38 b(FITNESS)f(F)m(OR)h(A)g(P)-8 b(AR)g(TICULAR)38 b(PUR-)0 2189 y(POSE,)24 b(AND)i(FREEDOM)f(FR)m(OM)h(INFRINGEMENT,)g (AND)f(ANY)h(W)-10 b(ARRANTY)25 b(THA)-8 b(T)25 b(THE)g(DOC-)0 2302 y(UMENT)-8 b(A)g(TION)31 b(WILL)f(CONF)m(ORM)h(TO)e(THE)h(SOFTW) -10 b(ARE,)30 b(OR)g(ANY)h(W)-10 b(ARRANTY)31 b(THA)-8 b(T)30 b(THE)0 2415 y(SOFTW)-10 b(ARE)31 b(WILL)h(BE)g(ERR)m(OR)g (FREE.)g(IN)g(NO)g(EVENT)f(SHALL)g(NASA)h(BE)g(LIABLE)g(F)m(OR)g(ANY)0 2528 y(D)m(AMA)m(GES,)26 b(INCLUDING,)e(BUT)f(NOT)g(LIMITED)h(TO,)f (DIRECT,)g(INDIRECT,)g(SPECIAL)f(OR)h(CON-)0 2641 y(SEQUENTIAL)28 b(D)m(AMA)m(GES,)k(ARISING)d(OUT)g(OF,)h(RESUL)-8 b(TING)29 b(FR)m(OM,)h(OR)f(IN)h(ANY)g(W)-10 b(A)i(Y)30 b(CON-)0 2754 y(NECTED)25 b(WITH)g(THIS)f(SOFTW)-10 b(ARE,)25 b(WHETHER)g(OR)g(NOT)g(BASED)g(UPON)g(W)-10 b(ARRANTY,)26 b(CON-)0 2867 y(TRA)m(CT,)d(TOR)-8 b(T)23 b(,)g(OR)g(OTHER)-10 b(WISE,)22 b(WHETHER)i(OR)f(NOT)f(INJUR)-8 b(Y)24 b(W)-10 b(AS)23 b(SUST)-8 b(AINED)23 b(BY)h(PER-)0 2979 y(SONS)h(OR)i(PR)m (OPER)-8 b(TY)26 b(OR)g(OTHER)-10 b(WISE,)26 b(AND)h(WHETHER)g(OR)f (NOT)g(LOSS)f(W)-10 b(AS)26 b(SUST)-8 b(AINED)0 3092 y(FR)m(OM,)37 b(OR)e(AR)m(OSE)h(OUT)f(OF)h(THE)g(RESUL)-8 b(TS)35 b(OF,)h(OR)f(USE)h(OF,)g(THE)g(SOFTW)-10 b(ARE)35 b(OR)g(SER-)0 3205 y(VICES)29 b(PR)m(O)m(VIDED)j(HEREUNDER.")p eop end %%Page: 5 13 TeXDict begin 5 12 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.5) cvn H.B /DEST pdfmark end 0 299 a 0 464 a SDict begin H.S end 0 464 a 0 464 a SDict begin 13.6 H.A end 0 464 a 0 464 a SDict begin [ /View [/XYZ H.V] /Dest (chapter.2) cvn H.B /DEST pdfmark end 0 464 a 761 x Fg(Chapter)65 b(2)0 1687 y Fm(Creating)77 b(the)h(CFITSIO)e(Library)0 2060 y SDict begin H.S end 0 2060 a 0 2060 a SDict begin 13.6 H.A end 0 2060 a 0 2060 a SDict begin [ /View [/XYZ H.V] /Dest (section.2.1) cvn H.B /DEST pdfmark end 0 2060 a 156 x Ff(2.1)135 b(Building)45 b(the)h(Library)0 2467 y Fj(The)h(CFITSIO)f(co)s(de)h(is) h(con)m(tained)g(in)f(ab)s(out)g(40)h(C)f(source)h(\014les)f(\(*.c\))i (and)e(header)g(\014les)g(\(*.h\).)93 b(On)0 2580 y(V)-10 b(AX/VMS)31 b(systems)g(2)f(assem)m(bly-co)s(de)i(\014les)e (\(vmsieeed.mar)h(and)f(vmsieeer.mar\))i(are)e(also)i(needed.)0 2740 y(CFITSIO)22 b(is)h(written)g(in)g(ANCI)g(C)g(and)g(should)f(b)s (e)g(compatible)j(with)e(most)g(existing)i(C)d(and)h(C++)f(compilers.)0 2853 y(Cra)m(y)30 b(sup)s(ercomputers)f(are)i(curren)m(tly)f(not)h (supp)s(orted.)0 3003 y SDict begin H.S end 0 3003 a 0 3003 a SDict begin 13.6 H.A end 0 3003 a 0 3003 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.2.1.1) cvn H.B /DEST pdfmark end 0 3003 a 146 x Fd(2.1.1)112 b(Unix)39 b(Systems)0 3369 y Fj(The)30 b(CFITSIO)f(library)h(is)g(built)g(on)h(Unix)f (systems)g(b)m(y)g(t)m(yping:)48 3633 y Fe(>)95 b(./configure)45 b([--prefix=/target/insta)o(llat)o(ion)o(/pat)o(h])d ([--enable-reentrant])764 3746 y([--enable-sse2])h([--enable-ssse3])48 3859 y(>)95 b(make)476 b(\(or)95 b('make)46 b(shared'\))48 3971 y(>)95 b(make)47 b(install)93 b(\(this)46 b(step)h(is)g (optional\))0 4235 y Fj(at)24 b(the)g(op)s(erating)g(system)g(prompt.) 38 b(The)23 b(con\014gure)g(command)g(customizes)i(the)f(Mak)m(e\014le) h(for)f(the)g(particular)0 4348 y(system,)g(then)d(the)g(`mak)m(e')i (command)e(compiles)h(the)f(source)h(\014les)f(and)g(builds)f(the)h (library)-8 b(.)38 b(T)m(yp)s(e)21 b(`./con\014gure')0 4461 y(and)34 b(not)h(simply)f(`con\014gure')h(to)h(ensure)e(that)h (the)g(con\014gure)g(script)f(in)h(the)g(curren)m(t)f(directory)h(is)g (run)f(and)0 4574 y(not)29 b(some)g(other)g(system-wide)g(con\014gure)f (script.)40 b(The)29 b(optional)h('pre\014x')e(argumen)m(t)h(to)g (con\014gure)g(giv)m(es)h(the)0 4687 y(path)e(to)i(the)f(directory)g (where)f(the)h(CFITSIO)f(library)g(and)g(include)h(\014les)f(should)g (b)s(e)g(installed)i(via)f(the)g(later)0 4800 y('mak)m(e)j(install')f (command.)41 b(F)-8 b(or)31 b(example,)143 5064 y Fe(>)48 b(./configure)c(--prefix=/usr1/local)0 5328 y Fj(will)25 b(cause)h(the)f('mak)m(e)h(install')g(command)f(to)h(cop)m(y)g(the)f (CFITSIO)e(lib)s(c\014tsio)i(\014le)h(to)f(/usr1/lo)s(cal/lib)i(and)e (the)0 5441 y(necessary)33 b(include)e(\014les)i(to)f(/usr1/lo)s (cal/include)j(\(assuming)d(of)g(course)g(that)h(the)f(pro)s(cess)g (has)g(p)s(ermission)0 5554 y(to)f(write)g(to)g(these)g(directories\).) 0 5714 y(All)g(the)g(a)m(v)-5 b(ailable)32 b(con\014gure)e(options)h (can)g(b)s(e)f(seen)g(b)m(y)g(en)m(tering)i(the)e(command)1927 5942 y(5)p eop end %%Page: 6 14 TeXDict begin 6 13 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.6) cvn H.B /DEST pdfmark end 0 299 a Fj(6)1580 b Fh(CHAPTER)30 b(2.)112 b(CREA)-8 b(TING)30 b(THE)g(CFITSIO)f(LIBRAR)-8 b(Y)143 555 y Fe(>)48 b(./configure)c(--help)0 830 y Fj(Some)30 b(of)h(the)g(more)f(useful)g(options)g(are)h(describ)s(ed)e (b)s(elo)m(w:)0 990 y(The)j({enable-reen)m(tran)m(t)j(option)f(will)f (attempt)h(to)f(con\014gure)g(CFITSIO)e(so)i(that)g(it)g(can)h(b)s(e)e (used)g(in)g(m)m(ulti-)0 1103 y(threaded)c(programs.)39 b(See)29 b(the)f("Using)h(CFITSIO)d(in)i(Multi-threaded)h(En)m (vironmen)m(ts")f(section,)i(b)s(elo)m(w,)f(for)0 1216 y(more)i(details.)0 1376 y(The)24 b({enable-sse2)j(and)d({enable-ssse3) i(options)g(will)f(cause)g(con\014gure)g(to)g(attempt)h(to)f(build)f (CFITSIO)f(using)0 1489 y(faster)31 b(b)m(yte-sw)m(apping)h (algorithms.)42 b(See)31 b(the)g("Optimizing)h(Programs")f(c)m(hapter)h (of)e(this)h(man)m(ual)g(for)g(more)0 1602 y(information)g(ab)s(out)f (these)h(options.)0 1762 y(The)44 b({with-gsiftp-\015a)m(v)m(our)h(and) f({with-gsiftp)g(options)h(enable)f(supp)s(ort)e(for)i(the)h(Globus)e (T)-8 b(o)s(olkit)46 b(gsiftp)0 1875 y(proto)s(cal.)c(See)30 b(the)h("Extended)f(File)i(Name)f(Syn)m(tax")g(c)m(hapter)g(for)f(more) g(information.)0 2035 y(The)22 b({with-bzip2)h(option)h(enables)f(supp) s(ort)d(for)j(reading)g(FITS)f(\014les)g(that)i(ha)m(v)m(e)f(b)s(een)f (externally)i(compressed)0 2148 y(b)m(y)j(the)h(bzip2)f(algorithm.)41 b(This)27 b(requires)g(that)h(the)f(CFITSIO)f(library)-8 b(,)28 b(and)f(all)i(applications)f(program)f(that)0 2261 y(use)j(CFITSIO,)f(to)i(b)s(e)f(link)m(ed)h(to)g(include)f(the)g (libbz2)h(library)-8 b(.)0 2421 y(The)28 b('mak)m(e)h(shared')f(option) h(builds)e(a)i(shared)e(or)i(dynamic)f(v)m(ersion)h(of)f(the)h(CFITSIO) d(library)-8 b(.)40 b(When)28 b(using)0 2534 y(the)f(shared)f(library)h (the)g(executable)h(co)s(de)f(is)g(not)g(copied)g(in)m(to)h(y)m(our)f (program)g(at)g(link)g(time)g(and)g(instead)g(the)0 2647 y(program)g(lo)s(cates)i(the)f(necessary)g(library)f(co)s(de)h(at)g (run)e(time,)j(normally)f(through)e(LD)p 3065 2647 28 4 v 33 w(LIBRAR)-8 b(Y)p 3514 2647 V 34 w(P)g(A)g(TH)28 b(or)0 2760 y(some)j(other)f(metho)s(d.)41 b(The)29 b(adv)-5 b(an)m(tages)33 b(of)d(using)g(a)h(shared)e(library)h(are:)143 3035 y Fe(1.)95 b(Less)47 b(disk)f(space)h(if)g(you)g(build)f(more)h (than)f(1)i(program)143 3148 y(2.)95 b(Less)47 b(memory)f(if)h(more)g (than)f(one)h(copy)g(of)g(a)g(program)f(using)h(the)g(shared)334 3261 y(library)f(is)h(running)f(at)h(the)g(same)g(time)f(since)h(the)g (system)f(is)h(smart)334 3374 y(enough)f(to)h(share)g(copies)f(of)h (the)g(shared)f(library)g(at)h(run)g(time.)143 3487 y(3.)95 b(Possibly)46 b(easier)g(maintenance)e(since)j(a)g(new)g(version)f(of)h (the)g(shared)334 3600 y(library)f(can)h(be)g(installed)e(without)h (relinking)f(all)i(the)g(software)334 3713 y(that)g(uses)f(it)i(\(as)e (long)h(as)g(the)g(subroutine)e(names)i(and)f(calling)334 3825 y(sequences)f(remain)h(unchanged\).)143 3938 y(4.)95 b(No)47 b(run-time)f(penalty.)0 4213 y Fj(The)30 b(disadv)-5 b(an)m(tages)32 b(are:)143 4488 y Fe(1.)47 b(More)g(hassle)f(at)h (runtime.)94 b(You)46 b(have)h(to)g(either)f(build)h(the)g(programs)286 4601 y(specially)f(or)h(have)f(LD_LIBRARY_PATH)e(set)j(right.)143 4714 y(2.)g(There)g(may)g(be)g(a)g(slight)f(start)h(up)g(penalty,)e (depending)h(on)h(where)f(you)h(are)286 4827 y(reading)f(the)h(shared)f (library)g(and)h(the)g(program)f(from)g(and)h(if)g(your)g(CPU)g(is)286 4940 y(either)f(really)h(slow)f(or)h(really)f(heavily)g(loaded.)0 5215 y Fj(On)32 b(Mac)i(OS)e(X)i(platforms)f(the)g('mak)m(e)h(shared')f (command)f(w)m(orks)h(lik)m(e)i(on)e(other)g(UNIX)g(platforms,)h(but)f (a)0 5328 y(.dylib)f(\014le)g(will)g(b)s(e)f(created)i(instead)g(of)f (.so.)46 b(If)31 b(installed)i(in)f(a)g(nonstandard)f(lo)s(cation,)j (add)d(its)i(lo)s(cation)g(to)0 5441 y(the)e(D)m(YLD)p 422 5441 V 34 w(LIBRAR)-8 b(Y)p 872 5441 V 33 w(P)g(A)g(TH)31 b(en)m(vironmen)m(t)g(v)-5 b(ariable)31 b(so)g(that)g(the)f(library)g (can)h(b)s(e)f(found)f(at)i(run)e(time.)0 5601 y(On)h(HP/UX)i(systems,) g(the)f(en)m(vironmen)m(t)h(v)-5 b(ariable)32 b(CFLA)m(GS)f(should)f(b) s(e)h(set)g(to)h(-Ae)g(b)s(efore)f(running)e(con-)0 5714 y(\014gure)h(to)h(enable)g("extended)g(ANSI")f(features.)p eop end %%Page: 7 15 TeXDict begin 7 14 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.7) cvn H.B /DEST pdfmark end 0 299 a Fh(2.2.)72 b(TESTING)29 b(THE)h(LIBRAR)-8 b(Y)2555 b Fj(7)0 555 y(By)31 b(default,)h(a)f(set)h (of)f(F)-8 b(ortran-callable)34 b(wrapp)s(er)29 b(routines)i(are)g (also)h(built)f(and)f(included)h(in)f(the)h(CFITSIO)0 668 y(library)-8 b(.)70 b(If)40 b(these)g(wrapp)s(er)f(routines)h(are)g (not)h(needed)e(\(i.e.,)45 b(the)40 b(CFITSIO)f(library)g(will)i(not)f (b)s(e)g(link)m(ed)0 781 y(to)d(an)m(y)f(F)-8 b(ortran)37 b(applications)g(whic)m(h)f(call)h(FITSIO)e(subroutines\))g(then)h (they)g(ma)m(y)h(b)s(e)e(omitted)i(from)f(the)0 894 y(build)28 b(b)m(y)i(t)m(yping)g('mak)m(e)g(all-no\014tsio')i(instead)d(of)h (simply)f(t)m(yping)h('mak)m(e'.)42 b(This)28 b(will)i(reduce)f(the)h (size)g(of)g(the)0 1007 y(CFITSIO)f(library)h(sligh)m(tly)-8 b(.)0 1167 y(It)33 b(ma)m(y)g(not)g(b)s(e)f(p)s(ossible)g(to)h (statically)i(link)e(programs)f(that)h(use)g(CFITSIO)e(on)h(some)h (platforms)g(\(namely)-8 b(,)0 1280 y(on)28 b(Solaris)h(2.6\))h(due)e (to)h(the)g(net)m(w)m(ork)g(driv)m(ers)f(\(whic)m(h)h(pro)m(vide)g(FTP) f(and)g(HTTP)g(access)h(to)h(FITS)d(\014les\).)41 b(It)0 1393 y(is)33 b(p)s(ossible)f(to)i(mak)m(e)f(b)s(oth)g(a)g(dynamic)f (and)g(a)i(static)g(v)m(ersion)f(of)g(the)g(CFITSIO)e(library)-8 b(,)34 b(but)e(net)m(w)m(ork)i(\014le)0 1506 y(access)e(will)e(not)h(b) s(e)f(p)s(ossible)g(using)g(the)g(static)i(v)m(ersion.)0 1667 y SDict begin H.S end 0 1667 a 0 1667 a SDict begin 13.6 H.A end 0 1667 a 0 1667 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.2.1.2) cvn H.B /DEST pdfmark end 0 1667 a 146 x Fd(2.1.2)112 b(VMS)0 2035 y Fj(On)28 b(V)-10 b(AX/VMS)31 b(and)d(ALPHA/VMS)i(systems)f(the)h(mak)m(e)p 2100 2035 28 4 v 34 w(g\015oat.com)h(command)e(\014le)g(ma)m(y)h(b)s(e)f (executed)h(to)0 2148 y(build)35 b(the)i(c\014tsio.olb)g(ob)5 b(ject)37 b(library)f(using)g(the)g(default)h(G-\015oating)g(p)s(oin)m (t)g(option)f(for)g(double)g(v)-5 b(ariables.)0 2261 y(The)37 b(mak)m(e)p 405 2261 V 33 w(d\015oat.com)i(and)d(mak)m(e)p 1279 2261 V 34 w(ieee.com)j(\014les)f(ma)m(y)f(b)s(e)g(used)f(instead)i (to)g(build)e(the)h(library)g(with)g(the)0 2374 y(other)26 b(\015oating)i(p)s(oin)m(t)e(options.)39 b(Note)28 b(that)f(the)f (getcwd)h(function)f(that)h(is)f(used)f(in)h(the)h(group.c)f(mo)s(dule) f(ma)m(y)0 2487 y(require)44 b(that)i(programs)e(using)g(CFITSIO)f(b)s (e)h(link)m(ed)i(with)e(the)h(ALPHA$LIBRAR)-8 b(Y:V)e(AX)m(CR)i(TL.OLB) 0 2600 y(library)g(.)41 b(See)30 b(the)h(example)g(link)f(line)h(in)f (the)h(next)f(section)i(of)e(this)h(do)s(cumen)m(t.)0 2761 y SDict begin H.S end 0 2761 a 0 2761 a SDict begin 13.6 H.A end 0 2761 a 0 2761 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.2.1.3) cvn H.B /DEST pdfmark end 0 2761 a 146 x Fd(2.1.3)112 b(Windo)m(ws)38 b(PCs)0 3129 y Fj(A)j(precompiled)f(DLL) g(v)m(ersion)h(of)g(CFITSIO)e(\(not)i(necessarily)g(the)g(latest)h(v)m (ersion\))f(is)g(a)m(v)-5 b(ailable)42 b(on)f(the)0 3242 y(CFITSIO)26 b(w)m(eb)i(site.)41 b(The)27 b(CFITSIO)f(library)h(ma)m(y) i(also)g(b)s(e)e(built)g(from)h(the)g(source)f(co)s(de)h(using)g(the)g (CMak)m(e)0 3355 y(build)j(system.)44 b(See)32 b(the)g("README.win")h (\014le)f(in)f(the)h(CFITSIO)e(source)i(distribution)f(for)g(more)h (informa-)0 3468 y(tion.)0 3612 y SDict begin H.S end 0 3612 a 0 3612 a SDict begin 13.6 H.A end 0 3612 a 0 3612 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.2.1.4) cvn H.B /DEST pdfmark end 0 3612 a 163 x Fd(2.1.4)112 b(Macin)m(tosh)39 b(PCs)0 3998 y Fj(When)20 b(building)f(on)i(Mac)g(OS-X,)f(users)g (should)f(follo)m(w)i(the)g(Unix)f(instructions,)i(ab)s(o)m(v)m(e.)39 b(See)20 b(the)h(README.MacOS)0 4111 y(\014le)30 b(for)h(instructions)f (on)g(building)g(a)g(Univ)m(ersal)i(Binary)e(that)h(supp)s(orts)e(b)s (oth)g(In)m(tel)i(and)f(P)m(o)m(w)m(erPC)h(CPUs.)0 4282 y SDict begin H.S end 0 4282 a 0 4282 a SDict begin 13.6 H.A end 0 4282 a 0 4282 a SDict begin [ /View [/XYZ H.V] /Dest (section.2.2) cvn H.B /DEST pdfmark end 0 4282 a 179 x Ff(2.2)135 b(T)-11 b(esting)46 b(the)f(Library)0 4714 y Fj(The)40 b(CFITSIO)e(library)i(should)f(b)s(e)g(tested)i(b)m(y)f (building)f(and)g(running)g(the)h(testprog.c)h(program)f(that)h(is)0 4827 y(included)30 b(with)g(the)g(release.)42 b(On)30 b(Unix)g(systems,)h(t)m(yp)s(e:)191 5101 y Fe(\045)47 b(make)g(testprog)191 5214 y(\045)g(testprog)f(>)h(testprog.lis)191 5327 y(\045)g(diff)g(testprog.lis)d(testprog.out)191 5440 y(\045)j(cmp)g(testprog.fit)e(testprog.std)0 5714 y Fj(On)30 b(VMS)g(systems,)g(\(assuming)h(cc)g(is)f(the)h(name)f(of)h (the)f(C)g(compiler)h(command\),)g(t)m(yp)s(e:)p eop end %%Page: 8 16 TeXDict begin 8 15 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.8) cvn H.B /DEST pdfmark end 0 299 a Fj(8)1580 b Fh(CHAPTER)30 b(2.)112 b(CREA)-8 b(TING)30 b(THE)g(CFITSIO)f(LIBRAR)-8 b(Y)191 555 y Fe($)47 b(cc)h(testprog.c)191 668 y($)f(link)g(testprog,) e(cfitsio/lib,)g(alpha$library:vaxcrtl/l)o(ib)191 781 y($)i(run)g(testprog)0 1047 y Fj(The)42 b(test)h(program)f(should)f (pro)s(duce)g(a)i(FITS)e(\014le)i(called)g(`testprog.\014t')h(that)f (is)f(iden)m(tical)i(to)f(the)f(`test-)0 1160 y(prog.std')35 b(FITS)e(\014le)i(included)e(with)h(this)g(release.)54 b(The)34 b(diagnostic)i(messages)f(\(whic)m(h)g(w)m(ere)g(pip)s(ed)e (to)i(the)0 1273 y(\014le)h(testprog.lis)i(in)e(the)h(Unix)f(example\)) h(should)e(b)s(e)h(iden)m(tical)i(to)f(the)f(listing)h(con)m(tained)h (in)e(the)g(\014le)h(test-)0 1386 y(prog.out.)63 b(The)37 b('di\013)7 b(')38 b(and)f('cmp')h(commands)g(sho)m(wn)f(ab)s(o)m(v)m (e)i(should)d(not)i(rep)s(ort)f(an)m(y)h(di\013erences)g(in)g(the)0 1499 y(\014les.)65 b(\(There)38 b(ma)m(y)h(b)s(e)f(some)h(minor)f (format)h(di\013erences,)i(suc)m(h)d(as)h(the)g(presence)f(or)h (absence)g(of)f(leading)0 1612 y(zeros,)31 b(or)g(3)f(digit)i(exp)s (onen)m(ts)e(in)g(n)m(um)m(b)s(ers,)f(whic)m(h)h(can)h(b)s(e)f (ignored\).)0 1772 y(The)e(F)-8 b(ortran)30 b(wrapp)s(ers)d(in)h (CFITSIO)f(ma)m(y)j(b)s(e)e(tested)h(with)g(the)g(testf77)h(program)f (on)g(Unix)f(systems)h(with:)191 2038 y Fe(\045)47 b(f77)g(-o)g (testf77)f(testf77.f)g(-L.)g(-lcfitsio)g(-lnsl)g(-lsocket)95 2151 y(or)191 2264 y(\045)h(f77)g(-f)g(-o)h(testf77)d(testf77.f)h(-L.)h (-lcfitsio)188 b(\(under)46 b(SUN)h(O/S\))95 2377 y(or)191 2490 y(\045)g(f77)g(-o)g(testf77)f(testf77.f)g(-Wl,-L.)f(-lcfitsio)h (-lm)h(-lnsl)f(-lsocket)f(\(HP/UX\))191 2716 y(\045)i(testf77)f(>)i (testf77.lis)191 2829 y(\045)f(diff)g(testf77.lis)e(testf77.out)191 2942 y(\045)i(cmp)g(testf77.fit)e(testf77.std)0 3208 y Fj(On)31 b(mac)m(hines)h(running)f(SUN)g(O/S,)h(F)-8 b(ortran)33 b(programs)e(m)m(ust)h(b)s(e)f(compiled)h(with)g(the)g('-f) 7 b(')32 b(option)h(to)f(force)0 3321 y(double)25 b(precision)h(v)-5 b(ariables)26 b(to)g(b)s(e)f(aligned)h(on)g(8-b)m(yte)h(b)s(oundarys)c (to)j(mak)m(e)h(the)e(fortran-declared)h(v)-5 b(ariables)0 3434 y(compatible)34 b(with)e(C.)g(A)h(similar)g(compiler)g(option)g (ma)m(y)g(b)s(e)f(required)g(on)g(other)h(platforms.)48 b(F)-8 b(ailing)34 b(to)f(use)0 3547 y(this)26 b(option)g(ma)m(y)g (cause)h(the)f(program)f(to)i(crash)e(on)h(FITSIO)f(routines)g(that)i (read)f(or)f(write)h(double)g(precision)0 3659 y(v)-5 b(ariables.)0 3820 y(Also)31 b(note)g(that)f(on)g(some)h(systems,)f (the)h(output)e(listing)i(of)g(the)f(testf77)i(program)d(ma)m(y)i (di\013er)f(sligh)m(tly)h(from)0 3933 y(the)g(testf77.std)h(template,)g (if)f(leading)g(zeros)g(are)g(not)g(prin)m(ted)f(b)m(y)h(default)g(b)s (efore)f(the)h(decimal)g(p)s(oin)m(t)g(when)0 4045 y(using)f(F)h (format.)0 4206 y(A)37 b(few)f(other)g(utilit)m(y)i(programs)e(are)h (included)f(with)g(CFITSIO;)f(the)i(\014rst)e(four)h(of)g(this)h (programs)f(can)h(b)s(e)0 4319 y(compiled)e(an)g(link)m(ed)g(b)m(y)g(t) m(yping)g(`mak)m(e)h(program)p 1815 4319 28 4 v 33 w(name')f(where)f (`program)p 2746 4319 V 33 w(name')h(is)g(the)g(actual)h(name)f(of)0 4431 y(the)c(program:)191 4698 y Fe(speed)46 b(-)i(measures)d(the)i (maximum)f(throughput)f(\(in)i(MB)g(per)g(second\))668 4811 y(for)g(writing)f(and)h(reading)f(FITS)g(files)h(with)f(CFITSIO.) 191 5036 y(listhead)f(-)j(lists)e(all)h(the)g(header)f(keywords)g(in)h (any)g(FITS)f(file)191 5262 y(fitscopy)f(-)j(copies)e(any)h(FITS)g (file)f(\(especially)f(useful)h(in)h(conjunction)811 5375 y(with)g(the)g(CFITSIO's)e(extended)h(input)g(filename)g (syntax\).)191 5601 y(cookbook)f(-)j(a)f(sample)f(program)g(that)h (performs)e(common)i(read)f(and)811 5714 y(write)h(operations)e(on)i(a) g(FITS)g(file.)p eop end %%Page: 9 17 TeXDict begin 9 16 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.9) cvn H.B /DEST pdfmark end 0 299 a Fh(2.3.)72 b(LINKING)30 b(PR)m(OGRAMS)h(WITH)f(CFITSIO)1975 b Fj(9)191 668 y Fe(iter_a,)46 b(iter_b,)g(iter_c)g(-)h(examples)f(of)h(the)g(CFITSIO)f (iterator)f(routine)0 841 y SDict begin H.S end 0 841 a 0 841 a SDict begin 13.6 H.A end 0 841 a 0 841 a SDict begin [ /View [/XYZ H.V] /Dest (section.2.3) cvn H.B /DEST pdfmark end 0 841 a 176 x Ff(2.3)135 b(Linking)45 b(Programs)h(with)f (CFITSIO)0 1271 y Fj(When)25 b(linking)h(applications)h(soft)m(w)m(are) g(with)e(the)h(CFITSIO)e(library)-8 b(,)27 b(sev)m(eral)g(system)f (libraries)g(usually)f(need)0 1384 y(to)36 b(b)s(e)f(sp)s(eci\014ed)g (on)g(the)g(link)h(command)f(line.)56 b(On)34 b(Unix)i(systems,)h(the)e (most)h(reliable)g(w)m(a)m(y)h(to)f(determine)0 1497 y(what)26 b(libraries)h(are)f(required)g(is)g(to)h(t)m(yp)s(e)f('mak)m (e)i(testprog')f(and)f(see)h(what)f(libraries)h(the)f(con\014gure)g (script)g(has)0 1610 y(added.)39 b(The)25 b(t)m(ypical)j(libraries)e (that)g(need)g(to)g(b)s(e)g(added)f(are)h(-lm)h(\(the)f(math)g (library\))g(and)f(-lnsl)h(and)g(-lso)s(c)m(k)m(et)0 1722 y(\(needed)k(only)g(for)g(FTP)g(and)f(HTTP)g(\014le)h(access\).)43 b(These)30 b(latter)h(2)f(libraries)g(are)h(not)f(needed)g(on)g(VMS)g (and)0 1835 y(Windo)m(ws)g(platforms,)h(b)s(ecause)f(FTP)h(\014le)f (access)i(is)e(not)h(curren)m(tly)f(supp)s(orted)f(on)h(those)h (platforms.)0 1996 y(Note)i(that)g(when)e(upgrading)g(to)i(a)f(new)m (er)g(v)m(ersion)g(of)g(CFITSIO)f(it)h(is)g(usually)g(necessary)g(to)h (recompile,)h(as)0 2108 y(w)m(ell)d(as)g(relink,)g(the)f(programs)g (that)h(use)f(CFITSIO,)f(b)s(ecause)i(the)f(de\014nitions)g(in)g (\014tsio.h)h(often)f(c)m(hange.)0 2279 y SDict begin H.S end 0 2279 a 0 2279 a SDict begin 13.6 H.A end 0 2279 a 0 2279 a SDict begin [ /View [/XYZ H.V] /Dest (section.2.4) cvn H.B /DEST pdfmark end 0 2279 a 179 x Ff(2.4)135 b(Using)46 b(CFITSIO)e(in)h(Multi-threaded)g(En)l(vironmen)l(ts)0 2711 y Fj(CFITSIO)d(can)h(b)s(e)g(used)f(either)i(with)e(the)i(POSIX)e (pthreads)g(in)m(terface)j(or)e(the)h(Op)s(enMP)d(in)m(terface)k(for)0 2824 y(m)m(ulti-threaded)g(parallel)g(programs.)81 b(When)43 b(used)h(in)f(a)i(m)m(ulti-threaded)f(en)m(vironmen)m(t,)k(the)c (CFITSIO)0 2937 y(library)26 b(*m)m(ust*)h(b)s(e)e(built)h(using)g(the) g(-D)p 1426 2937 28 4 v 34 w(REENTRANT)f(compiler)i(directiv)m(e.)41 b(This)25 b(can)i(b)s(e)e(done)h(using)g(the)0 3050 y(follo)m(wing)32 b(build)d(commands:)95 3323 y Fe(>./configure)45 b(--enable-reentrant) 95 3436 y(>)j(make)0 3709 y Fj(A)32 b(function)g(called)i(\014ts)p 845 3709 V 32 w(is)p 938 3709 V 33 w(reen)m(tran)m(t)f(is)g(a)m(v)-5 b(ailable)34 b(to)f(test)h(whether)d(or)i(not)f(CFITSIO)f(w)m(as)h (compiled)h(with)0 3822 y(the)28 b(-D)p 258 3822 V 34 w(REENTRANT)f(directiv)m(e.)42 b(When)28 b(this)g(feature)g(is)g (enabled,)h(m)m(ultiple)g(threads)e(can)i(call)g(an)m(y)g(of)f(the)0 3935 y(CFITSIO)k(routines)h(to)h(sim)m(ultaneously)g(read)f(or)h(write) f(separate)h(FITS)f(\014les.)49 b(Multiple)34 b(threads)f(can)h(also)0 4048 y(read)29 b(data)h(from)e(the)h(same)h(FITS)e(\014le)h(sim)m (ultaneously)-8 b(,)31 b(as)e(long)h(as)f(the)g(\014le)g(w)m(as)h(op)s (ened)e(indep)s(enden)m(tly)g(b)m(y)0 4161 y(eac)m(h)37 b(thread.)58 b(This)35 b(relies)i(on)f(the)g(op)s(erating)h(system)f (to)h(correctly)g(deal)g(with)f(reading)g(the)g(same)h(\014le)f(b)m(y)0 4274 y(m)m(ultiple)30 b(pro)s(cesses.)41 b(Di\013eren)m(t)30 b(threads)g(should)e(not)i(share)f(the)h(same)g('\014ts\014le')g(p)s (oin)m(ter)f(to)i(read)e(an)h(op)s(ened)0 4386 y(FITS)40 b(\014le,)j(unless)d(lo)s(c)m(ks)h(are)g(placed)f(around)g(the)g(calls) i(to)f(the)g(CFITSIO)d(reading)j(routines.)71 b(Di\013eren)m(t)0 4499 y(threads)30 b(should)f(nev)m(er)i(try)f(to)h(write)g(to)g(the)g (same)f(FITS)g(\014le.)0 4670 y SDict begin H.S end 0 4670 a 0 4670 a SDict begin 13.6 H.A end 0 4670 a 0 4670 a SDict begin [ /View [/XYZ H.V] /Dest (section.2.5) cvn H.B /DEST pdfmark end 0 4670 a 179 x Ff(2.5)135 b(Getting)46 b(Started)g(with)f (CFITSIO)0 5102 y Fj(In)27 b(order)h(to)g(e\013ectiv)m(ely)j(use)d(the) g(CFITSIO)e(library)i(it)g(is)g(recommended)g(that)g(new)f(users)h(b)s (egin)f(b)m(y)h(reading)0 5215 y(the)g(\\CFITSIO)g(Quic)m(k)g(Start)g (Guide".)41 b(It)28 b(con)m(tains)h(all)h(the)e(basic)h(information)f (needed)g(to)h(write)f(programs)0 5328 y(that)c(p)s(erform)f(most)h(t)m (yp)s(es)g(of)g(op)s(erations)g(on)g(FITS)f(\014les.)39 b(The)23 b(set)i(of)f(example)g(FITS)g(utilit)m(y)h(programs)e(that)0 5441 y(are)29 b(a)m(v)-5 b(ailable)31 b(from)d(the)g(CFITSIO)f(w)m(eb)i (site)g(are)g(also)g(v)m(ery)g(useful)f(for)g(learning)h(ho)m(w)f(to)h (use)f(CFITSIO.)f(T)-8 b(o)0 5554 y(learn)23 b(ev)m(en)g(more)g(ab)s (out)f(the)h(capabilities)h(of)f(the)g(CFITSIO)e(library)h(the)h(follo) m(wing)h(steps)e(are)h(recommended:)0 5714 y(1.)41 b(Read)31 b(the)f(follo)m(wing)i(short)e(`FITS)g(Primer')g(c)m(hapter)h(for)f(an) h(o)m(v)m(erview)h(of)e(the)h(structure)f(of)g(FITS)g(\014les.)p eop end %%Page: 10 18 TeXDict begin 10 17 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.10) cvn H.B /DEST pdfmark end 0 299 a Fj(10)1535 b Fh(CHAPTER)30 b(2.)112 b(CREA)-8 b(TING)30 b(THE)g(CFITSIO)f(LIBRAR)-8 b(Y)0 555 y Fj(2.)40 b(Review)28 b(the)f(Programming)g(Guidelines)h(in) f(Chapter)f(4)i(to)g(b)s(ecome)f(familiar)h(with)f(the)h(con)m(v)m(en)m (tions)h(used)0 668 y(b)m(y)h(the)h(CFITSIO)e(in)m(terface.)0 828 y(3.)74 b(Refer)41 b(to)h(the)g(co)s(okb)s(o)s(ok.c,)j(listhead.c,) h(and)40 b(\014tscop)m(y)-8 b(.c)43 b(programs)e(that)h(are)g(included) e(with)h(this)h(re-)0 941 y(lease)g(for)e(examples)h(of)g(routines)f (that)h(p)s(erform)e(v)-5 b(arious)41 b(common)g(FITS)f(\014le)g(op)s (erations.)72 b(T)m(yp)s(e)40 b('mak)m(e)0 1054 y(program)p 339 1054 28 4 v 33 w(name')30 b(to)h(compile)h(and)d(link)i(these)g (programs)f(on)g(Unix)g(systems.)0 1214 y(4.)40 b(W)-8 b(rite)30 b(a)e(simple)g(program)g(to)g(read)g(or)g(write)g(a)h(FITS)e (\014le)h(using)g(the)g(Basic)h(In)m(terface)g(routines)f(describ)s(ed) 0 1327 y(in)i(Chapter)g(5.)0 1487 y(5.)79 b(Scan)43 b(through)f(the)h (more)g(sp)s(ecialized)i(routines)d(that)i(are)f(describ)s(ed)f(in)h (the)g(follo)m(wing)i(c)m(hapters)e(to)0 1600 y(b)s(ecome)31 b(familiar)g(with)f(the)h(functionalit)m(y)g(that)g(they)g(pro)m(vide.) 0 1785 y SDict begin H.S end 0 1785 a 0 1785 a SDict begin 13.6 H.A end 0 1785 a 0 1785 a SDict begin [ /View [/XYZ H.V] /Dest (section.2.6) cvn H.B /DEST pdfmark end 0 1785 a 179 x Ff(2.6)135 b(Example)46 b(Program)0 2220 y Fj(The)c(follo)m(wing) j(listing)f(sho)m(ws)e(an)h(example)h(of)f(ho)m(w)g(to)g(use)g(the)g (CFITSIO)f(routines)g(in)h(a)g(C)g(program.)0 2333 y(Refer)26 b(to)g(the)g(co)s(okb)s(o)s(ok.c)g(program)f(that)i(is)e(included)g (with)g(the)h(CFITSIO)e(distribution)h(for)g(other)h(example)0 2446 y(routines.)0 2606 y(This)38 b(program)h(creates)h(a)f(new)f(FITS) g(\014le,)k(con)m(taining)e(a)f(FITS)f(image.)68 b(An)38 b(`EXPOSURE')h(k)m(eyw)m(ord)g(is)0 2719 y(written)27 b(to)g(the)f(header,)i(then)e(the)h(image)g(data)h(are)f(written)f(to)h (the)g(FITS)f(\014le)g(b)s(efore)h(closing)g(the)g(FITS)f(\014le.)0 3004 y Fe(#include)46 b("fitsio.h")92 b(/*)47 b(required)f(by)h(every)g (program)e(that)i(uses)g(CFITSIO)93 b(*/)0 3117 y(main\(\))0 3230 y({)191 3343 y(fitsfile)45 b(*fptr;)333 b(/*)47 b(pointer)f(to)h(the)g(FITS)g(file;)f(defined)g(in)h(fitsio.h)f(*/)191 3456 y(int)h(status,)f(ii,)h(jj;)191 3569 y(long)94 b(fpixel)46 b(=)i(1,)f(naxis)f(=)i(2,)f(nelements,)e(exposure;)191 3681 y(long)i(naxes[2])e(=)j({)f(300,)g(200)g(};)142 b(/*)47 b(image)g(is)g(300)g(pixels)f(wide)h(by)g(200)g(rows)f(*/)191 3794 y(short)g(array[200][300];)191 4020 y(status)g(=)h(0;)429 b(/*)48 b(initialize)d(status)h(before)g(calling)g(fitsio)g(routines)f (*/)191 4133 y(fits_create_file\(&fptr,)c("testfile.fits",)j (&status\);)140 b(/*)48 b(create)e(new)h(file)f(*/)191 4359 y(/*)h(Create)f(the)h(primary)f(array)g(image)h(\(16-bit)e(short)i (integer)f(pixels)g(*/)191 4472 y(fits_create_img\(fptr,)c(SHORT_IMG,)j (naxis,)h(naxes,)g(&status\);)191 4698 y(/*)h(Write)f(a)i(keyword;)d (must)i(pass)g(the)g(ADDRESS)e(of)j(the)f(value)f(*/)191 4811 y(exposure)f(=)j(1500.;)191 4924 y(fits_update_key\(fptr,)42 b(TLONG,)k("EXPOSURE",)f(&exposure,)430 5036 y("Total)h(Exposure)f (Time",)h(&status\);)191 5262 y(/*)h(Initialize)e(the)i(values)f(in)h (the)g(image)g(with)f(a)i(linear)e(ramp)g(function)g(*/)191 5375 y(for)h(\(jj)g(=)g(0;)g(jj)h(<)f(naxes[1];)e(jj++\))382 5488 y(for)i(\(ii)g(=)g(0;)g(ii)g(<)h(naxes[0];)d(ii++\))573 5601 y(array[jj][ii])f(=)j(ii)h(+)f(jj;)p eop end %%Page: 11 19 TeXDict begin 11 18 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.11) cvn H.B /DEST pdfmark end 0 299 a Fh(2.6.)72 b(EXAMPLE)31 b(PR)m(OGRAM)2618 b Fj(11)191 555 y Fe(nelements)45 b(=)j(naxes[0])d(*) j(naxes[1];)474 b(/*)48 b(number)e(of)h(pixels)f(to)h(write)g(*/)191 781 y(/*)g(Write)f(the)h(array)g(of)g(integers)e(to)j(the)f(image)f(*/) 191 894 y(fits_write_img\(fptr,)c(TSHORT,)k(fpixel,)g(nelements,)f (array[0],)g(&status\);)191 1120 y(fits_close_file\(fptr,)d(&status\);) 570 b(/*)47 b(close)g(the)g(file)f(*/)191 1346 y (fits_report_error\(stderr)o(,)c(status\);)93 b(/*)47 b(print)g(out)g(any)f(error)h(messages)e(*/)191 1458 y(return\()h(status)g(\);)0 1571 y(})p eop end %%Page: 12 20 TeXDict begin 12 19 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.12) cvn H.B /DEST pdfmark end 0 299 a Fj(12)1535 b Fh(CHAPTER)30 b(2.)112 b(CREA)-8 b(TING)30 b(THE)g(CFITSIO)f(LIBRAR)-8 b(Y)p eop end %%Page: 13 21 TeXDict begin 13 20 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.13) cvn H.B /DEST pdfmark end 0 299 a 0 464 a SDict begin H.S end 0 464 a 0 464 a SDict begin 13.6 H.A end 0 464 a 0 464 a SDict begin [ /View [/XYZ H.V] /Dest (chapter.3) cvn H.B /DEST pdfmark end 0 464 a 761 x Fg(Chapter)65 b(3)0 1687 y Fm(A)78 b(FITS)f(Primer)0 2180 y Fj(This)36 b(section)h(giv)m(es)h(a) f(brief)f(o)m(v)m(erview)i(of)e(the)h(structure)f(of)h(FITS)e(\014les.) 59 b(Users)36 b(should)g(refer)g(to)h(the)g(do)s(c-)0 2293 y(umen)m(tation)i(a)m(v)-5 b(ailable)41 b(from)d(the)g(FITS)g (Supp)s(ort)e(OF\014ce,)41 b(as)d(describ)s(ed)g(in)g(the)g(in)m(tro)s (duction,)j(for)d(more)0 2406 y(detailed)31 b(information)g(on)f(FITS)g (formats.)0 2566 y(FITS)e(w)m(as)h(\014rst)g(dev)m(elop)s(ed)g(in)f (the)h(late)i(1970's)g(as)e(a)g(standard)f(data)i(in)m(terc)m(hange)g (format)f(b)s(et)m(w)m(een)h(v)-5 b(arious)0 2679 y(astronomical)36 b(observ)-5 b(atories.)52 b(Since)34 b(then)g(FITS)f(has)h(b)s(ecome)g (the)h(standard)e(data)i(format)f(supp)s(orted)e(b)m(y)0 2791 y(most)f(astronomical)h(data)f(analysis)g(soft)m(w)m(are)h(pac)m (k)-5 b(ages.)0 2952 y(A)34 b(FITS)f(\014le)g(consists)h(of)g(one)g(or) g(more)g(Header)g(+)f(Data)i(Units)f(\(HDUs\),)i(where)d(the)h(\014rst) f(HDU)h(is)g(called)0 3065 y(the)j(`Primary)f(HDU',)i(or)f(`Primary)f (Arra)m(y'.)60 b(The)36 b(primary)g(arra)m(y)h(con)m(tains)h(an)e (N-dimensional)i(arra)m(y)f(of)0 3177 y(pixels,)30 b(suc)m(h)g(as)g(a)h (1-D)g(sp)s(ectrum,)e(a)h(2-D)h(image,)h(or)e(a)g(3-D)i(data)e(cub)s (e.)40 b(Six)30 b(di\013eren)m(t)g(primary)f(data)i(t)m(yp)s(es)0 3290 y(are)j(supp)s(orted:)44 b(Unsigned)33 b(8-bit)h(b)m(ytes,)h (16-bit,)g(32-bit,)h(and)c(64-bit)j(signed)e(in)m(tegers,)i(and)e(32)h (and)f(64-bit)0 3403 y(\015oating)28 b(p)s(oin)m(t)e(reals.)40 b(FITS)27 b(also)g(has)g(a)g(con)m(v)m(en)m(tion)i(for)d(storing)i(16)f (and)f(32-bit)i(unsigned)e(in)m(tegers)i(\(see)g(the)0 3516 y(later)k(section)h(en)m(titled)g(`Unsigned)e(In)m(tegers')h(for)f (more)h(details\).)44 b(The)31 b(primary)g(HDU)h(ma)m(y)g(also)g (consist)g(of)0 3629 y(only)e(a)h(header)f(with)h(a)f(n)m(ull)h(arra)m (y)f(con)m(taining)i(no)f(data)g(pixels.)0 3789 y(An)m(y)i(n)m(um)m(b)s (er)e(of)h(additional)i(HDUs)f(ma)m(y)g(follo)m(w)h(the)e(primary)g (arra)m(y;)i(these)f(additional)h(HDUs)f(are)g(called)0 3902 y(FITS)d(`extensions'.)41 b(There)30 b(are)h(curren)m(tly)f(3)h(t) m(yp)s(es)g(of)f(extensions)h(de\014ned)e(b)m(y)h(the)h(FITS)f (standard:)136 4171 y Fc(\017)46 b Fj(Image)31 b(Extension)g(-)g(a)f (N-dimensional)h(arra)m(y)g(of)g(pixels,)g(lik)m(e)g(in)f(a)h(primary)e (arra)m(y)136 4368 y Fc(\017)46 b Fj(ASCI)s(I)29 b(T)-8 b(able)31 b(Extension)g(-)f(ro)m(ws)h(and)e(columns)h(of)h(data)g(in)f (ASCI)s(I)f(c)m(haracter)j(format)136 4564 y Fc(\017)46 b Fj(Binary)31 b(T)-8 b(able)31 b(Extension)f(-)h(ro)m(ws)f(and)g (columns)g(of)h(data)g(in)f(binary)f(represen)m(tation)0 4833 y(In)k(eac)m(h)i(case)g(the)f(HDU)h(consists)g(of)f(an)g(ASCI)s(I) e(Header)i(Unit)h(follo)m(w)m(ed)g(b)m(y)f(an)g(optional)h(Data)g (Unit.)52 b(F)-8 b(or)0 4946 y(historical)37 b(reasons,)g(eac)m(h)f (Header)g(or)g(Data)h(unit)e(m)m(ust)g(b)s(e)g(an)g(exact)i(m)m (ultiple)f(of)g(2880)h(8-bit)f(b)m(ytes)g(long.)0 5059 y(An)m(y)30 b(un)m(used)g(space)g(is)h(padded)e(with)h(\014ll)g(c)m (haracters)i(\(ASCI)s(I)d(blanks)h(or)h(zeros\).)0 5219 y(Eac)m(h)i(Header)f(Unit)h(consists)g(of)f(an)m(y)g(n)m(um)m(b)s(er)f (of)i(80-c)m(haracter)i(k)m(eyw)m(ord)d(records)g(or)g(`card)h(images') g(whic)m(h)0 5332 y(ha)m(v)m(e)f(the)e(general)i(form:)95 5601 y Fe(KEYNAME)46 b(=)i(value)e(/)i(comment)d(string)95 5714 y(NULLKEY)h(=)334 b(/)48 b(comment:)d(This)i(keyword)f(has)g(no)i (value)1905 5942 y Fj(13)p eop end %%Page: 14 22 TeXDict begin 14 21 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.14) cvn H.B /DEST pdfmark end 0 299 a Fj(14)2398 b Fh(CHAPTER)30 b(3.)112 b(A)30 b(FITS)g(PRIMER)0 555 y Fj(The)35 b(k)m(eyw)m(ord)i (names)f(ma)m(y)g(b)s(e)g(up)f(to)h(8)h(c)m(haracters)g(long)g(and)e (can)h(only)h(con)m(tain)g(upp)s(ercase)e(letters,)k(the)0 668 y(digits)25 b(0-9,)i(the)e(h)m(yphen,)g(and)f(the)h(underscore)e(c) m(haracter.)41 b(The)24 b(k)m(eyw)m(ord)h(name)g(is)f(\(usually\))h (follo)m(w)m(ed)i(b)m(y)d(an)0 781 y(equals)29 b(sign)g(and)f(a)g (space)i(c)m(haracter)g(\(=)e(\))h(in)f(columns)h(9)g(-)f(10)i(of)f (the)f(record,)h(follo)m(w)m(ed)i(b)m(y)d(the)h(v)-5 b(alue)29 b(of)g(the)0 894 y(k)m(eyw)m(ord)34 b(whic)m(h)g(ma)m(y)g(b)s (e)f(either)h(an)g(in)m(teger,)i(a)e(\015oating)g(p)s(oin)m(t)g(n)m(um) m(b)s(er,)g(a)g(c)m(haracter)h(string)e(\(enclosed)i(in)0 1007 y(single)28 b(quotes\),)i(or)e(a)g(b)s(o)s(olean)g(v)-5 b(alue)28 b(\(the)g(letter)h(T)f(or)f(F\).)i(A)f(k)m(eyw)m(ord)g(ma)m (y)h(also)f(ha)m(v)m(e)h(a)g(n)m(ull)e(or)h(unde\014ned)0 1120 y(v)-5 b(alue)31 b(if)f(there)h(is)f(no)g(sp)s(eci\014ed)g(v)-5 b(alue)31 b(string,)g(as)f(in)g(the)h(second)f(example,)i(ab)s(o)m(v)m (e)0 1280 y(The)26 b(last)h(k)m(eyw)m(ord)g(in)g(the)f(header)h(is)f (alw)m(a)m(ys)i(the)f(`END')g(k)m(eyw)m(ord)g(whic)m(h)g(has)f(no)g(v) -5 b(alue)27 b(or)g(commen)m(t)g(\014elds.)0 1393 y(There)k(are)g(man)m (y)g(rules)g(go)m(v)m(erning)h(the)g(exact)g(format)g(of)f(a)g(k)m(eyw) m(ord)h(record)f(\(see)h(the)f(FITS)f(Standard\))h(so)0 1506 y(it)i(is)f(b)s(etter)h(to)g(rely)g(on)f(standard)f(in)m(terface)j (soft)m(w)m(are)g(lik)m(e)g(CFITSIO)d(to)i(correctly)h(construct)f(or)f (to)h(parse)0 1619 y(the)e(k)m(eyw)m(ord)f(records)h(rather)f(than)g (try)g(to)h(deal)g(directly)g(with)f(the)h(ra)m(w)f(FITS)g(formats.)0 1779 y(Eac)m(h)37 b(Header)g(Unit)f(b)s(egins)g(with)g(a)g(series)h(of) f(required)g(k)m(eyw)m(ords)g(whic)m(h)g(dep)s(end)f(on)h(the)g(t)m(yp) s(e)h(of)f(HDU.)0 1892 y(These)31 b(required)g(k)m(eyw)m(ords)h(sp)s (ecify)g(the)f(size)i(and)e(format)h(of)g(the)g(follo)m(wing)h(Data)g (Unit.)45 b(The)31 b(header)g(ma)m(y)0 2005 y(con)m(tain)h(other)f (optional)g(k)m(eyw)m(ords)g(to)h(describ)s(e)e(other)g(asp)s(ects)h (of)g(the)g(data,)g(suc)m(h)g(as)g(the)f(units)g(or)h(scaling)0 2118 y(v)-5 b(alues.)44 b(Other)31 b(COMMENT)g(or)g(HISTOR)-8 b(Y)30 b(k)m(eyw)m(ords)i(are)g(also)g(frequen)m(tly)g(added)e(to)i (further)e(do)s(cumen)m(t)0 2230 y(the)h(data)g(\014le.)0 2391 y(The)36 b(optional)h(Data)h(Unit)f(immediately)g(follo)m(ws)h (the)e(last)h(2880-b)m(yte)i(blo)s(c)m(k)e(in)f(the)g(Header)h(Unit.)59 b(Some)0 2503 y(HDUs)31 b(do)f(not)h(ha)m(v)m(e)g(a)g(Data)h(Unit)f (and)f(only)g(consist)h(of)g(the)f(Header)h(Unit.)0 2664 y(If)24 b(there)i(is)f(more)g(than)f(one)h(HDU)h(in)f(the)g(FITS)f (\014le,)i(then)f(the)g(Header)h(Unit)f(of)g(the)g(next)g(HDU)h (immediately)0 2777 y(follo)m(ws)g(the)e(last)i(2880-b)m(yte)h(blo)s(c) m(k)e(of)g(the)f(previous)g(Data)j(Unit)d(\(or)h(Header)g(Unit)g(if)f (there)h(is)g(no)f(Data)i(Unit\).)0 2937 y(The)k(main)g(required)g(k)m (eyw)m(ords)g(in)g(FITS)g(primary)g(arra)m(ys)g(or)h(image)g (extensions)g(are:)136 3172 y Fc(\017)46 b Fj(BITPIX)32 b({)g(de\014nes)e(the)i(data)g(t)m(yp)s(e)g(of)g(the)g(arra)m(y:)43 b(8,)33 b(16,)g(32,)g(64,)g(-32,)g(-64)g(for)e(unsigned)f(8{bit)j(b)m (yte,)227 3284 y(16{bit)41 b(signed)f(in)m(teger,)j(32{bit)f(signed)d (in)m(teger,)44 b(32{bit)d(IEEE)e(\015oating)h(p)s(oin)m(t,)i(and)e (64{bit)h(IEEE)227 3397 y(double)30 b(precision)h(\015oating)g(p)s(oin) m(t,)g(resp)s(ectiv)m(ely)-8 b(.)136 3585 y Fc(\017)46 b Fj(NAXIS)30 b({)h(the)g(n)m(um)m(b)s(er)e(of)h(dimensions)g(in)g(the) h(arra)m(y)-8 b(,)31 b(usually)f(0,)h(1,)g(2,)g(3,)g(or)g(4.)136 3773 y Fc(\017)46 b Fj(NAXISn)30 b({)h(\(n)f(ranges)g(from)g(1)h(to)g (NAXIS\))g(de\014nes)e(the)i(size)g(of)g(eac)m(h)g(dimension.)0 4008 y(FITS)e(tables)i(start)g(with)f(the)g(k)m(eyw)m(ord)g(XTENSION)g (=)f(`T)-8 b(ABLE')31 b(\(for)f(ASCI)s(I)f(tables\))i(or)f(XTENSION)f (=)0 4120 y(`BINT)-8 b(ABLE')32 b(\(for)e(binary)g(tables\))h(and)f(ha) m(v)m(e)i(the)e(follo)m(wing)i(main)e(k)m(eyw)m(ords:)136 4355 y Fc(\017)46 b Fj(TFIELDS)30 b({)h(n)m(um)m(b)s(er)e(of)h (\014elds)g(or)h(columns)f(in)g(the)g(table)136 4543 y Fc(\017)46 b Fj(NAXIS2)31 b({)g(n)m(um)m(b)s(er)e(of)h(ro)m(ws)h(in)f (the)g(table)136 4731 y Fc(\017)46 b Fj(TTYPEn)29 b({)i(for)f(eac)m(h)i (column)e(\(n)g(ranges)h(from)f(1)g(to)h(TFIELDS\))g(giv)m(es)g(the)g (name)f(of)h(the)f(column)136 4918 y Fc(\017)46 b Fj(TF)m(ORMn)31 b({)f(the)h(data)g(t)m(yp)s(e)f(of)h(the)g(column)136 5106 y Fc(\017)46 b Fj(TUNITn)30 b({)g(the)h(ph)m(ysical)g(units)f(of)g (the)h(column)f(\(optional\))0 5341 y(Users)k(should)f(refer)h(to)h (the)f(FITS)g(Supp)s(ort)e(O\016ce)i(at)h Fe(http://fits.gsfc.nasa.gov) 27 b Fj(for)34 b(further)f(infor-)0 5454 y(mation)e(ab)s(out)f(the)h (FITS)e(format)i(and)f(related)h(soft)m(w)m(are)h(pac)m(k)-5 b(ages.)p eop end %%Page: 15 23 TeXDict begin 15 22 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.15) cvn H.B /DEST pdfmark end 0 299 a 0 464 a SDict begin H.S end 0 464 a 0 464 a SDict begin 13.6 H.A end 0 464 a 0 464 a SDict begin [ /View [/XYZ H.V] /Dest (chapter.4) cvn H.B /DEST pdfmark end 0 464 a 761 x Fg(Chapter)65 b(4)0 1687 y Fm(Programming)77 b(Guidelines)0 2060 y SDict begin H.S end 0 2060 a 0 2060 a SDict begin 13.6 H.A end 0 2060 a 0 2060 a SDict begin [ /View [/XYZ H.V] /Dest (section.4.1) cvn H.B /DEST pdfmark end 0 2060 a 156 x Ff(4.1)135 b(CFITSIO)44 b(De\014nitions)0 2466 y Fj(An)m(y)30 b(program)g(that)h(uses)f(the)h (CFITSIO)d(in)m(terface)k(m)m(ust)e(include)g(the)h(\014tsio.h)f (header)g(\014le)h(with)f(the)g(state-)0 2579 y(men)m(t)95 2818 y Fe(#include)46 b("fitsio.h")0 3057 y Fj(This)30 b(header)h(\014le)h(con)m(tains)g(the)f(protot)m(yp)s(es)h(for)f(all)h (the)f(CFITSIO)f(user)g(in)m(terface)j(routines)e(as)g(w)m(ell)h(as)g (the)0 3170 y(de\014nitions)g(of)g(v)-5 b(arious)32 b(constan)m(ts)h (used)e(in)h(the)h(in)m(terface.)47 b(It)32 b(also)h(de\014nes)e(a)i(C) f(structure)f(of)h(t)m(yp)s(e)h(`\014ts\014le')0 3283 y(that)j(is)g(used)f(b)m(y)g(CFITSIO)f(to)j(store)f(the)g(relev)-5 b(an)m(t)37 b(parameters)f(that)g(de\014ne)f(the)h(format)g(of)g(a)g (particular)0 3396 y(FITS)c(\014le.)48 b(Application)34 b(programs)f(m)m(ust)g(de\014ne)f(a)h(p)s(oin)m(ter)g(to)g(this)g (structure)g(for)f(eac)m(h)i(FITS)e(\014le)h(that)h(is)0 3508 y(to)i(b)s(e)f(op)s(ened.)56 b(This)35 b(structure)g(is)h (initialized)h(\(i.e.,)i(memory)c(is)h(allo)s(cated)h(for)f(the)g (structure\))f(when)g(the)0 3621 y(FITS)h(\014le)g(is)h(\014rst)e(op)s (ened)h(or)g(created)i(with)e(the)g(\014ts)p 1949 3621 28 4 v 33 w(op)s(en)p 2172 3621 V 32 w(\014le)g(or)h(\014ts)p 2596 3621 V 32 w(create)p 2864 3621 V 34 w(\014le)g(routines.)59 b(This)35 b(\014ts\014le)0 3734 y(p)s(oin)m(ter)c(is)h(then)f(passed)g (as)g(the)h(\014rst)e(argumen)m(t)i(to)g(ev)m(ery)g(other)g(CFITSIO)d (routine)j(that)g(op)s(erates)g(on)f(the)0 3847 y(FITS)h(\014le.)48 b(Application)34 b(programs)f(m)m(ust)g(not)g(directly)g(read)g(or)g (write)g(elemen)m(ts)h(in)f(this)g(\014ts\014le)f(structure)0 3960 y(b)s(ecause)e(the)h(de\014nition)f(of)h(the)f(structure)g(ma)m(y) h(c)m(hange)g(in)g(future)e(v)m(ersions)i(of)f(CFITSIO.)0 4120 y(A)45 b(n)m(um)m(b)s(er)e(of)i(sym)m(b)s(olic)g(constan)m(ts)h (are)f(also)g(de\014ned)f(in)g(\014tsio.h)h(for)f(the)h(con)m(v)m (enience)i(of)e(application)0 4233 y(programmers.)55 b(Use)35 b(of)h(these)f(sym)m(b)s(olic)h(constan)m(ts)g(rather)f(than)g (the)h(actual)g(n)m(umeric)f(v)-5 b(alue)36 b(will)f(help)g(to)0 4346 y(mak)m(e)c(the)g(source)f(co)s(de)h(more)g(readable)f(and)g (easier)i(for)e(others)g(to)h(understand.)0 4585 y Fe(String)46 b(Lengths,)g(for)h(use)f(when)h(allocating)e(character)g(arrays:)95 4811 y(#define)h(FLEN_FILENAME)e(1025)j(/*)g(max)g(length)f(of)h(a)h (filename)857 b(*/)95 4924 y(#define)46 b(FLEN_KEYWORD)140 b(72)95 b(/*)47 b(max)g(length)f(of)h(a)h(keyword)905 b(*/)95 5036 y(#define)46 b(FLEN_CARD)284 b(81)95 b(/*)47 b(max)g(length)f(of)h(a)h(FITS)f(header)f(card)476 b(*/)95 5149 y(#define)46 b(FLEN_VALUE)236 b(71)95 b(/*)47 b(max)g(length)f(of) h(a)h(keyword)e(value)g(string)285 b(*/)95 5262 y(#define)46 b(FLEN_COMMENT)140 b(73)95 b(/*)47 b(max)g(length)f(of)h(a)h(keyword)e (comment)g(string)189 b(*/)95 5375 y(#define)46 b(FLEN_ERRMSG)188 b(81)95 b(/*)47 b(max)g(length)f(of)h(a)h(CFITSIO)e(error)g(message)237 b(*/)95 5488 y(#define)46 b(FLEN_STATUS)188 b(31)95 b(/*)47 b(max)g(length)f(of)h(a)h(CFITSIO)e(status)g(text)g(string)h(*/)95 5714 y(Note)g(that)g(FLEN_KEYWORD)d(is)j(longer)f(than)h(the)g(nominal) f(8-character)f(keyword)1905 5942 y Fj(15)p eop end %%Page: 16 24 TeXDict begin 16 23 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.16) cvn H.B /DEST pdfmark end 0 299 a Fj(16)1763 b Fh(CHAPTER)29 b(4.)112 b(PR)m(OGRAMMING)32 b(GUIDELINES)95 555 y Fe(name)47 b(length)f(because)g(the)h(HIERARCH)e(convention)g(supports)h(longer)g (keyword)g(names.)0 781 y(Access)g(modes)g(when)h(opening)f(a)h(FITS)g (file:)95 1007 y(#define)f(READONLY)94 b(0)95 1120 y(#define)46 b(READWRITE)g(1)0 1346 y(BITPIX)g(data)h(type)f(code)h(values)f(for)h (FITS)g(images:)95 1571 y(#define)f(BYTE_IMG)284 b(8)96 b(/*)f(8-bit)46 b(unsigned)f(integers)h(*/)95 1684 y(#define)g (SHORT_IMG)189 b(16)95 b(/*)47 b(16-bit)141 b(signed)46 b(integers)g(*/)95 1797 y(#define)g(LONG_IMG)237 b(32)95 b(/*)47 b(32-bit)141 b(signed)46 b(integers)g(*/)95 1910 y(#define)g(LONGLONG_IMG)f(64)95 b(/*)47 b(64-bit)141 b(signed)46 b(integers)g(*/)95 2023 y(#define)g(FLOAT_IMG)141 b(-32)95 b(/*)47 b(32-bit)f(single)g(precision)f(floating)h(point)g(*/) 95 2136 y(#define)g(DOUBLE_IMG)93 b(-64)i(/*)47 b(64-bit)f(double)g (precision)f(floating)h(point)g(*/)95 2362 y(The)h(following)f(4)h (data)g(type)f(codes)h(are)g(also)f(supported)g(by)h(CFITSIO:)95 2475 y(#define)f(SBYTE_IMG)93 b(10)143 b(/*)95 b(8-bit)46 b(signed)g(integers,)g(equivalent)f(to)i(*/)1241 2588 y(/*)95 b(BITPIX)46 b(=)h(8,)h(BSCALE)e(=)h(1,)g(BZERO)g(=)g(-128)g(*/) 95 2700 y(#define)f(USHORT_IMG)93 b(20)i(/*)47 b(16-bit)f(unsigned)g (integers,)f(equivalent)g(to)i(*/)1241 2813 y(/*)95 b(BITPIX)46 b(=)h(16,)g(BSCALE)f(=)i(1,)f(BZERO)f(=)i(32768)e(*/)95 2926 y(#define)g(ULONG_IMG)141 b(40)95 b(/*)47 b(32-bit)f(unsigned)g (integers,)f(equivalent)g(to)i(*/)1241 3039 y(/*)95 b(BITPIX)46 b(=)h(32,)g(BSCALE)f(=)i(1,)f(BZERO)f(=)i(2147483648)d(*/)0 3265 y(Codes)h(for)h(the)g(data)g(type)f(of)i(binary)e(table)g(columns) g(and/or)g(for)h(the)0 3378 y(data)g(type)f(of)h(variables)f(when)g (reading)g(or)h(writing)f(keywords)g(or)h(data:)1432 3604 y(DATATYPE)714 b(TFORM)46 b(CODE)95 3717 y(#define)g(TBIT)476 b(1)96 b(/*)1335 b('X')47 b(*/)95 3830 y(#define)f(TBYTE)381 b(11)95 b(/*)47 b(8-bit)f(unsigned)g(byte,)332 b('B')47 b(*/)95 3942 y(#define)f(TLOGICAL)237 b(14)95 b(/*)47 b(logicals)e(\(int)i(for)g(keywords)236 b(*/)1289 4055 y(/*)95 b(and)46 b(char)h(for)g(table)f(cols)142 b('L')47 b(*/)95 4168 y(#define)f(TSTRING)285 b(16)95 b(/*)47 b(ASCII)f(string,)666 b('A')47 b(*/)95 4281 y(#define)f(TSHORT)333 b(21)95 b(/*)47 b(signed)f(short,)666 b('I')47 b(*/)95 4394 y(#define)f(TLONG)381 b(41)95 b(/*)47 b(signed)f(long,)905 b(*/)95 4507 y(#define)46 b(TLONGLONG)189 b(81)95 b(/*)47 b(64-bit)f(long)h(signed)f(integer)f('K')i(*/)95 4620 y(#define)f(TFLOAT)333 b(42)95 b(/*)47 b(single)f(precision)f(float,) 189 b('E')47 b(*/)95 4733 y(#define)f(TDOUBLE)285 b(82)95 b(/*)47 b(double)f(precision)f(float,)189 b('D')47 b(*/)95 4846 y(#define)f(TCOMPLEX)237 b(83)95 b(/*)47 b(complex)f(\(pair)g(of)h (floats\))141 b('C')47 b(*/)95 4959 y(#define)f(TDBLCOMPLEX)f(163)95 b(/*)47 b(double)f(complex)g(\(2)h(doubles\))e('M')i(*/)95 5185 y(The)g(following)f(data)g(type)h(codes)f(are)h(also)g(supported)e (by)i(CFITSIO:)95 5297 y(#define)f(TINT)429 b(31)95 b(/*)47 b(int)1335 b(*/)95 5410 y(#define)46 b(TSBYTE)333 b(12)95 b(/*)47 b(8-bit)f(signed)g(byte,)428 b('S')47 b(*/)95 5523 y(#define)f(TUINT)381 b(30)95 b(/*)47 b(unsigned)e(int)715 b('V')47 b(*/)95 5636 y(#define)f(TUSHORT)285 b(20)95 b(/*)47 b(unsigned)e(short)619 b('U')95 b(*/)p eop end %%Page: 17 25 TeXDict begin 17 24 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.17) cvn H.B /DEST pdfmark end 0 299 a Fh(4.2.)72 b(CURRENT)30 b(HEADER)h(D)m(A)-8 b(T)g(A)32 b(UNIT)e(\(CHDU\))1786 b Fj(17)95 555 y Fe(#define)46 b(TULONG)333 b(40)95 b(/*)47 b(unsigned)e(long)858 b(*/)95 781 y(The)47 b(following)f(data)g(type)h (code)g(is)g(only)f(for)h(use)g(with)g(fits\\_get\\_coltype)95 894 y(#define)f(TINT32BIT)189 b(41)95 b(/*)47 b(signed)f(32-bit)g(int,) 428 b('J')47 b(*/)0 1233 y(HDU)g(type)g(code)f(values)g(\(value)g (returned)g(when)h(moving)f(to)h(new)g(HDU\):)95 1458 y(#define)f(IMAGE_HDU)93 b(0)i(/*)48 b(Primary)d(Array)i(or)g(IMAGE)f (HDU)h(*/)95 1571 y(#define)f(ASCII_TBL)93 b(1)i(/*)48 b(ASCII)94 b(table)46 b(HDU)h(*/)95 1684 y(#define)f(BINARY_TBL)f(2)95 b(/*)48 b(Binary)e(table)g(HDU)h(*/)95 1797 y(#define)f(ANY_HDU)142 b(-1)94 b(/*)48 b(matches)d(any)i(type)g(of)g(HDU)g(*/)0 2023 y(Column)f(name)h(and)g(string)f(matching)f(case-sensitivity:)95 2249 y(#define)h(CASESEN)142 b(1)g(/*)48 b(do)f(case-sensitive)d (string)i(match)g(*/)95 2362 y(#define)g(CASEINSEN)g(0)142 b(/*)48 b(do)f(case-insensitive)c(string)j(match)h(*/)0 2588 y(Logical)f(states)g(\(if)h(TRUE)f(and)h(FALSE)g(are)g(not)g (already)e(defined\):)95 2813 y(#define)h(TRUE)h(1)95 2926 y(#define)f(FALSE)h(0)0 3152 y(Values)f(to)h(represent)f (undefined)f(floating)g(point)i(numbers:)95 3378 y(#define)f (FLOATNULLVALUE)92 b(-9.11912E-36F)95 3491 y(#define)46 b(DOUBLENULLVALUE)e(-9.1191291391491E-36)0 3717 y(Image)i(compression)f (algorithm)g(definitions)95 3942 y(#define)h(RICE_1)333 b(11)95 4055 y(#define)46 b(GZIP_1)333 b(21)95 4168 y(#define)46 b(GZIP_2)333 b(22)95 4281 y(#define)46 b(PLIO_1)333 b(31)95 4394 y(#define)46 b(HCOMPRESS_1)93 b(41)95 4507 y(#define)46 b(NOCOMPRESS)93 b(-1)95 4733 y(#define)46 b(NO_DITHER)g(-1)95 4846 y(#define)g(SUBTRACTIVE_DITHER_1)d(1)95 4959 y(#define)j (SUBTRACTIVE_DITHER_2)d(2)0 5153 y SDict begin H.S end 0 5153 a 0 5153 a SDict begin 13.6 H.A end 0 5153 a 0 5153 a SDict begin [ /View [/XYZ H.V] /Dest (section.4.2) cvn H.B /DEST pdfmark end 0 5153 a 188 x Ff(4.2)135 b(Curren)l(t)46 b(Header)f(Data)h(Unit)g(\(CHDU\))0 5601 y Fj(The)37 b(concept)h(of)g(the)f(Curren)m(t)g(Header)g(and)g(Data)i(Unit,)h(or)d (CHDU,)h(is)f(fundamen)m(tal)h(to)g(the)f(use)g(of)h(the)0 5714 y(CFITSIO)31 b(library)-8 b(.)46 b(A)32 b(simple)h(FITS)e(image)j (ma)m(y)f(only)f(con)m(tain)i(a)e(single)h(Header)g(and)f(Data)h(unit)f (\(HDU\),)p eop end %%Page: 18 26 TeXDict begin 18 25 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.18) cvn H.B /DEST pdfmark end 0 299 a Fj(18)1763 b Fh(CHAPTER)29 b(4.)112 b(PR)m(OGRAMMING)32 b(GUIDELINES)0 555 y Fj(but)39 b(in)g(general)i(FITS)e(\014les)h(can)g(con)m(tain)h(m)m(ultiple)g (Header)f(Data)h(Units)f(\(also)h(kno)m(wn)e(as)h(`extensions'\),)0 668 y(concatenated)c(one)f(after)f(the)h(other)f(in)g(the)g(\014le.)53 b(The)33 b(user)h(can)g(sp)s(ecify)g(whic)m(h)g(HDU)h(should)e(b)s(e)g (initially)0 781 y(op)s(ened)j(at)i(run)d(time)j(b)m(y)f(giving)h(the)f (HDU)h(name)f(or)g(n)m(um)m(b)s(er)f(after)h(the)g(ro)s(ot)h(\014le)f (name.)60 b(F)-8 b(or)38 b(example,)0 894 y('m)m(y\014le.\014ts[4]')i (op)s(ens)d(the)h(5th)h(HDU)g(in)f(the)g(\014le)g(\(note)h(that)g(the)f (n)m(um)m(b)s(ering)f(starts)i(with)f(0\),)j(and)c('m)m(y-)0 1007 y(\014le.\014ts[EVENTS])k(op)s(ens)f(the)h(HDU)h(with)e(the)h (name)g('EVENTS')g(\(as)g(de\014ned)f(b)m(y)h(the)g(EXTNAME)g(or)0 1120 y(HDUNAME)35 b(k)m(eyw)m(ords\).)50 b(If)33 b(no)g(HDU)h(is)f(sp)s (eci\014ed)g(then)g(CFITSIO)e(op)s(ens)i(the)g(\014rst)g(HDU)h(\(the)g (primary)0 1233 y(arra)m(y\))24 b(b)m(y)e(default.)39 b(The)22 b(CFITSIO)f(routines)i(whic)m(h)g(read)f(and)g(write)i(data)f (only)g(op)s(erate)g(within)g(the)g(op)s(ened)0 1346 y(HDU,)32 b(Other)e(CFITSIO)f(routines)i(are)g(pro)m(vided)f(to)i(mo)m (v)m(e)g(to)f(and)f(op)s(en)g(an)m(y)h(other)g(existing)h(HDU)f(within) 0 1458 y(the)g(FITS)e(\014le)i(or)f(to)h(app)s(end)e(or)h(insert)g(new) g(HDUs)h(in)f(the)h(FITS)f(\014le.)0 1657 y SDict begin H.S end 0 1657 a 0 1657 a SDict begin 13.6 H.A end 0 1657 a 0 1657 a SDict begin [ /View [/XYZ H.V] /Dest (section.4.3) cvn H.B /DEST pdfmark end 0 1657 a 179 x Ff(4.3)135 b(F)-11 b(unction)44 b(Names)i(and)f(V)-11 b(ariable)46 b(Datat)l(yp)t(es)0 2095 y Fj(Most)33 b(of)f(the)g(CFITSIO)f(routines)h (ha)m(v)m(e)h(b)s(oth)e(a)i(short)e(name)h(as)h(w)m(ell)g(as)f(a)g (longer)h(descriptiv)m(e)g(name.)45 b(The)0 2208 y(short)32 b(name)g(is)g(only)g(5)h(or)f(6)g(c)m(haracters)h(long)g(and)f(is)g (similar)g(to)h(the)f(subroutine)f(name)h(in)g(the)g(F)-8 b(ortran-77)0 2321 y(v)m(ersion)38 b(of)g(FITSIO.)f(The)h(longer)g (name)g(is)g(more)g(descriptiv)m(e)h(and)e(it)h(is)g(recommended)g (that)g(it)h(b)s(e)e(used)0 2434 y(instead)31 b(of)f(the)h(short)f (name)g(to)h(more)g(clearly)h(do)s(cumen)m(t)e(the)g(source)h(co)s(de.) 0 2594 y(Man)m(y)c(of)f(the)g(CFITSIO)f(routines)h(come)h(in)e (families)i(whic)m(h)f(di\013er)g(only)g(in)g(the)g(data)h(t)m(yp)s(e)f (of)g(the)g(asso)s(ciated)0 2707 y(parameter\(s\).)45 b(The)31 b(data)h(t)m(yp)s(e)g(of)g(these)g(routines)f(is)h(indicated)g (b)m(y)f(the)h(su\016x)e(of)i(the)g(routine)f(name.)44 b(The)0 2820 y(short)27 b(routine)h(names)g(ha)m(v)m(e)h(a)f(1)g(or)f (2)h(c)m(haracter)i(su\016x)c(\(e.g.,)31 b('j')c(in)h('\013pkyj'\))g (while)f(the)h(long)g(routine)g(names)0 2933 y(ha)m(v)m(e)k(a)e(4)h(c)m (haracter)h(or)e(longer)h(su\016x)f(as)g(sho)m(wn)g(in)g(the)h(follo)m (wing)h(table:)191 3230 y Fe(Long)285 b(Short)94 b(Data)191 3343 y(Names)237 b(Names)94 b(Type)191 3456 y(-----)237 b(-----)94 b(----)191 3569 y(_bit)381 b(x)190 b(bit)191 3681 y(_byt)381 b(b)190 b(unsigned)46 b(byte)191 3794 y(_sbyt)333 b(sb)142 b(signed)46 b(byte)191 3907 y(_sht)381 b(i)190 b(short)47 b(integer)191 4020 y(_lng)381 b(j)190 b(long)47 b(integer)191 4133 y(_lnglng)237 b(jj)142 b(8-byte)46 b(LONGLONG)g(integer)g(\(see)g(note)h(below\))191 4246 y(_usht)333 b(ui)142 b(unsigned)46 b(short)g(integer)191 4359 y(_ulng)333 b(uj)142 b(unsigned)46 b(long)g(integer)191 4472 y(_uint)333 b(uk)142 b(unsigned)46 b(int)h(integer)191 4585 y(_int)381 b(k)190 b(int)47 b(integer)191 4698 y(_flt)381 b(e)190 b(real)47 b(exponential)e(floating)g(point)i(\(float\))191 4811 y(_fixflt)237 b(f)190 b(real)47 b(fixed-decimal)d(format)i (floating)g(point)g(\(float\))191 4924 y(_dbl)381 b(d)190 b(double)46 b(precision)g(real)g(floating-point)e(\(double\))191 5036 y(_fixdbl)237 b(g)190 b(double)46 b(precision)g(fixed-format)e (floating)i(point)g(\(double\))191 5149 y(_cmp)381 b(c)190 b(complex)46 b(reals)g(\(pairs)h(of)g(float)f(values\))191 5262 y(_fixcmp)237 b(fc)142 b(complex)46 b(reals,)g(fixed-format)f (floating)g(point)191 5375 y(_dblcmp)237 b(m)190 b(double)46 b(precision)g(complex)f(\(pairs)i(of)g(double)f(values\))191 5488 y(_fixdblcmp)93 b(fm)142 b(double)46 b(precision)g(complex,)f (fixed-format)g(floating)g(point)191 5601 y(_log)381 b(l)190 b(logical)46 b(\(int\))191 5714 y(_str)381 b(s)190 b(character)46 b(string)p eop end %%Page: 19 27 TeXDict begin 19 26 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.19) cvn H.B /DEST pdfmark end 0 299 a Fh(4.3.)72 b(FUNCTION)30 b(NAMES)h(AND)g(V)-10 b(ARIABLE)30 b(D)m(A)-8 b(T)g(A)g(TYPES)1409 b Fj(19)0 555 y(The)32 b(logical)j(data)f(t)m(yp)s(e)f(corresp)s(onds)e (to)j(`in)m(t')f(for)g(logical)i(k)m(eyw)m(ord)e(v)-5 b(alues,)34 b(and)e(`b)m(yte')i(for)f(logical)i(binary)0 668 y(table)40 b(columns.)67 b(In)39 b(other)g(w)m(ords,)i(the)f(v)-5 b(alue)39 b(when)g(writing)g(a)h(logical)h(k)m(eyw)m(ord)f(m)m(ust)f(b) s(e)g(stored)g(in)g(an)0 781 y(`in)m(t')g(v)-5 b(ariable,)40 b(and)e(m)m(ust)f(b)s(e)g(stored)h(in)g(a)g(`c)m(har')h(arra)m(y)f (when)f(reading)h(or)f(writing)h(to)h(`L')f(columns)f(in)h(a)0 894 y(binary)c(table.)56 b(Implicit)35 b(data)h(t)m(yp)s(e)f(con)m(v)m (ersion)i(is)e(not)g(supp)s(orted)e(for)i(logical)j(table)e(columns,)g (but)e(is)h(for)0 1007 y(k)m(eyw)m(ords,)30 b(so)f(a)h(logical)h(k)m (eyw)m(ord)f(ma)m(y)f(b)s(e)g(read)f(and)h(cast)h(to)g(an)m(y)f(n)m (umerical)h(data)f(t)m(yp)s(e;)h(a)g(returned)d(v)-5 b(alue)0 1120 y(=)30 b(0)h(indicates)g(false,)g(and)f(an)m(y)h(other)f (v)-5 b(alue)31 b(=)f(true.)0 1280 y(The)24 b(`in)m(t')i(data)g(t)m(yp) s(e)f(ma)m(y)h(b)s(e)e(2)h(b)m(ytes)h(long)f(on)g(some)g(old)g(PC)g (compilers,)h(but)f(otherwise)g(it)g(is)g(nearly)g(alw)m(a)m(ys)0 1393 y(4)i(b)m(ytes)g(long.)40 b(Some)27 b(64-bit)h(mac)m(hines,)g(lik) m(e)g(the)f(Alpha/OSF,)g(de\014ne)f(the)h(`short',)h(`in)m(t',)h(and)d (`long')i(in)m(teger)0 1506 y(data)j(t)m(yp)s(es)f(to)i(b)s(e)d(2,)i (4,)g(and)f(8)h(b)m(ytes)g(long,)g(resp)s(ectiv)m(ely)-8 b(.)0 1666 y(Because)40 b(there)e(is)h(no)f(univ)m(ersal)h(C)f (compiler)g(standard)g(for)g(the)h(name)f(of)h(the)f(8-b)m(yte)i(in)m (teger)g(datat)m(yp)s(e,)0 1779 y(the)33 b(\014tsio.h)h(include)f (\014le)g(t)m(yp)s(edef)7 b('s)33 b('LONGLONG')h(to)g(b)s(e)e(equiv)-5 b(alen)m(t)35 b(to)f(an)f(appropriate)g(8-b)m(yte)i(in)m(teger)0 1892 y(data)c(t)m(yp)s(e)g(on)f(eac)m(h)i(supp)s(orted)d(platform.)41 b(F)-8 b(or)31 b(maxim)m(um)f(soft)m(w)m(are)i(p)s(ortabilit)m(y)g(it)f (is)f(recommended)g(that)0 2005 y(this)g(LONGLONG)g(datat)m(yp)s(e)h(b) s(e)e(used)g(to)i(de\014ne)e(8-b)m(yte)i(in)m(teger)h(v)-5 b(ariables)30 b(rather)g(than)g(using)f(the)i(nativ)m(e)0 2118 y(data)h(t)m(yp)s(e)g(name)f(on)h(a)f(particular)h(platform.)44 b(On)31 b(most)h(32-bit)g(Unix)g(and)e(Mac)j(OS-X)e(op)s(erating)h (systems)0 2230 y(LONGLONG)h(is)f(equiv)-5 b(alen)m(t)34 b(to)f(the)g(in)m(trinsic)g('long)g(long')h(8-b)m(yte)g(in)m(teger)f (datat)m(yp)s(e.)49 b(On)31 b(64-bit)j(systems)0 2343 y(\(whic)m(h)e(curren)m(tly)g(includes)f(Alpha)h(OSF/1,)g(64-bit)h(Sun) e(Solaris,)h(64-bit)h(SGI)f(MIPS,)f(and)g(64-bit)i(Itanium)0 2456 y(and)28 b(Opteron)g(PC)h(systems\),)g(LONGLONG)g(is)g(simply)f(t) m(yp)s(edef)7 b('ed)29 b(to)g(b)s(e)g(equiv)-5 b(alen)m(t)30 b(to)f('long'.)42 b(Microsoft)0 2569 y(Visual)33 b(C++)e(V)-8 b(ersion)33 b(6.0)g(do)s(es)f(not)g(de\014ne)g(a)h('long)g(long')g (data)g(t)m(yp)s(e,)g(so)f(LONGLONG)h(is)f(t)m(yp)s(edef)7 b('ed)32 b(to)0 2682 y(b)s(e)e(equiv)-5 b(alen)m(t)32 b(to)f(the)f(')p 853 2682 28 4 v 887 2682 V 66 w(in)m(t64')i(data)f(t)m (yp)s(e)g(on)f(32-bit)h(windo)m(ws)f(systems)h(when)e(using)h(Visual)h (C++.)0 2842 y(A)j(related)h(issue)e(that)i(a\013ects)g(the)f(p)s (ortabilit)m(y)g(of)g(soft)m(w)m(are)i(is)d(ho)m(w)h(to)h(prin)m(t)e (out)h(the)g(v)-5 b(alue)34 b(of)g(a)g('LONG-)0 2955 y(LONG')e(v)-5 b(ariable)32 b(with)f(prin)m(tf.)44 b(Dev)m(elop)s(ers) 33 b(ma)m(y)f(\014nd)e(it)i(con)m(v)m(enien)m(t)h(to)g(use)e(the)h (follo)m(wing)h(prepro)s(cessing)0 3068 y(statemen)m(ts)f(in)e(their)h (C)f(programs)g(to)h(handle)f(this)g(in)g(a)h(mac)m(hine-p)s(ortable)g (manner:)0 3310 y Fe(#if)47 b(defined\(_MSC_VER\))c(/*)k(Microsoft)e (Visual)i(C++)f(*/)477 3423 y(printf\("\045I64d",)e(longlongvalue\);)0 3649 y(#elif)i(\(USE_LL_SUFFIX)e(==)j(1\))477 3762 y (printf\("\045lld",)d(longlongvalue\);)0 3988 y(#else)477 4101 y(printf\("\045ld",)g(longlongvalue\);)0 4213 y(#endif)0 4456 y Fj(Similarly)-8 b(,)32 b(the)f(name)g(of)g(the)h(C)e(utilit)m(y) j(routine)e(that)g(con)m(v)m(erts)i(a)e(c)m(haracter)i(string)d(of)i (digits)f(in)m(to)h(a)g(8-b)m(yte)0 4568 y(in)m(teger)g(v)-5 b(alue)31 b(is)f(platform)g(dep)s(enden)m(t:)0 4811 y Fe(#if)47 b(defined\(_MSC_VER\))c(/*)k(Microsoft)e(Visual)i(C++)f(*/) 286 4924 y(/*)i(VC++)e(6.0)h(does)g(not)g(seem)f(to)h(have)g(an)g (8-byte)f(conversion)f(routine)h(*/)0 5149 y(#elif)g(\(USE_LL_SUFFIX)e (==)j(1\))477 5262 y(longlongvalue)d(=)k(atoll\(*string\);)0 5488 y(#else)477 5601 y(longlongvalue)c(=)k(atol\(*string\);)0 5714 y(#endif)p eop end %%Page: 20 28 TeXDict begin 20 27 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.20) cvn H.B /DEST pdfmark end 0 299 a Fj(20)1763 b Fh(CHAPTER)29 b(4.)112 b(PR)m(OGRAMMING)32 b(GUIDELINES)0 555 y Fj(When)23 b(dealing)h(with)f(the)h(FITS)f(b)m(yte)h(data)g(t)m(yp)s(e)f(it)h(is)g (imp)s(ortan)m(t)f(to)h(remem)m(b)s(er)f(that)h(the)g(ra)m(w)f(v)-5 b(alues)24 b(\(b)s(efore)0 668 y(an)m(y)h(scaling)g(b)m(y)f(the)h (BSCALE)e(and)h(BZER)m(O,)g(or)h(TSCALn)d(and)i(TZER)m(On)f(k)m(eyw)m (ord)i(v)-5 b(alues\))25 b(in)f(b)m(yte)h(arra)m(ys)0 781 y(\(BITPIX)37 b(=)f(8\))h(or)f(b)m(yte)i(columns)e(\(TF)m(ORMn)h(=) f('B'\))h(are)g(in)m(terpreted)g(as)g(unsigned)e(b)m(ytes)i(with)g(v)-5 b(alues)0 894 y(ranging)34 b(from)g(0)g(to)h(255.)53 b(Some)34 b(C)g(compilers)h(de\014ne)e(a)h('c)m(har')h(v)-5 b(ariable)35 b(as)g(signed,)g(so)f(it)h(is)f(imp)s(ortan)m(t)g(to)0 1007 y(explicitly)e(declare)f(a)g(n)m(umeric)f(c)m(har)h(v)-5 b(ariable)31 b(as)g('unsigned)e(c)m(har')i(to)g(a)m(v)m(oid)h(an)m(y)f (am)m(biguit)m(y)0 1167 y(One)22 b(feature)h(of)g(the)g(CFITSIO)e (routines)i(is)f(that)i(they)f(can)g(op)s(erate)g(on)f(a)h(`X')h (\(bit\))f(column)g(in)f(a)h(binary)f(table)0 1280 y(as)33 b(though)f(it)h(w)m(ere)g(a)g(`B')g(\(b)m(yte\))h(column.)47 b(F)-8 b(or)33 b(example)g(a)g(`11X')h(data)f(t)m(yp)s(e)g(column)f (can)h(b)s(e)f(in)m(terpreted)0 1393 y(the)c(same)h(as)f(a)g(`2B')i (column)e(\(i.e.,)i(2)e(unsigned)f(8-bit)i(b)m(ytes\).)41 b(In)27 b(some)i(instances,)g(it)f(can)h(b)s(e)e(more)h(e\016cien)m(t)0 1506 y(to)j(read)f(and)g(write)h(whole)f(b)m(ytes)h(at)g(a)g(time,)g (rather)g(than)f(reading)g(or)h(writing)f(eac)m(h)i(individual)d(bit.)0 1666 y(The)36 b(complex)i(and)e(double)h(precision)g(complex)h(data)g (t)m(yp)s(es)f(are)g(not)g(directly)h(supp)s(orted)d(in)i(ANSI)f(C)h (so)0 1779 y(these)g(data)g(t)m(yp)s(es)f(should)f(b)s(e)h(in)m (terpreted)h(as)f(pairs)g(of)h(\015oat)g(or)f(double)g(v)-5 b(alues,)38 b(resp)s(ectiv)m(ely)-8 b(,)40 b(where)c(the)0 1892 y(\014rst)30 b(v)-5 b(alue)30 b(in)h(eac)m(h)g(pair)f(is)h(the)f (real)h(part,)g(and)e(the)i(second)f(is)h(the)f(imaginary)h(part.)0 2046 y SDict begin H.S end 0 2046 a 0 2046 a SDict begin 13.6 H.A end 0 2046 a 0 2046 a SDict begin [ /View [/XYZ H.V] /Dest (section.4.4) cvn H.B /DEST pdfmark end 0 2046 a 179 x Ff(4.4)135 b(Supp)t(ort)44 b(for)h(Unsigned)h(In)l(tegers)g(and)f (Signed)g(Bytes)0 2475 y Fj(Although)33 b(FITS)f(do)s(es)g(not)h (directly)h(supp)s(ort)d(unsigned)g(in)m(tegers)j(as)f(one)g(of)g(its)h (fundamen)m(tal)e(data)i(t)m(yp)s(es,)0 2588 y(FITS)27 b(can)h(still)h(b)s(e)e(used)g(to)i(e\016cien)m(tly)h(store)e(unsigned) f(in)m(teger)i(data)g(v)-5 b(alues)28 b(in)g(images)h(and)e(binary)g (tables.)0 2701 y(The)42 b(con)m(v)m(en)m(tion)j(used)d(in)g(FITS)g (\014les)h(is)f(to)i(store)f(the)g(unsigned)e(in)m(tegers)j(as)f (signed)g(in)m(tegers)h(with)e(an)0 2814 y(asso)s(ciated)34 b(o\013set)f(\(sp)s(eci\014ed)f(b)m(y)g(the)g(BZER)m(O)g(or)g(TZER)m (On)f(k)m(eyw)m(ord\).)47 b(F)-8 b(or)33 b(example,)g(to)g(store)g (unsigned)0 2927 y(16-bit)g(in)m(teger)g(v)-5 b(alues)32 b(in)f(a)h(FITS)f(image)i(the)e(image)i(w)m(ould)f(b)s(e)e(de\014ned)h (as)h(a)g(signed)f(16-bit)i(in)m(teger)g(\(with)0 3040 y(BITPIX)c(k)m(eyw)m(ord)g(=)g(SHOR)-8 b(T)p 1132 3040 28 4 v 32 w(IMG)30 b(=)e(16\))j(with)d(the)i(k)m(eyw)m(ords)f(BSCALE)f (=)h(1.0)h(and)f(BZER)m(O)g(=)f(32768.)0 3152 y(Th)m(us)34 b(the)h(unsigned)f(v)-5 b(alues)35 b(of)g(0,)i(32768,)h(and)d(65535,)j (for)d(example,)i(are)e(ph)m(ysically)h(stored)f(in)g(the)g(FITS)0 3265 y(image)40 b(as)e(-32768,)43 b(0,)e(and)d(32767,)k(resp)s(ectiv)m (ely;)i(CFITSIO)37 b(automatically)k(adds)c(the)i(BZER)m(O)f(o\013set)h (to)0 3378 y(these)g(v)-5 b(alues)39 b(when)f(they)g(are)h(read.)65 b(Similarly)-8 b(,)42 b(in)c(the)h(case)h(of)e(unsigned)g(32-bit)i(in)m (tegers)f(the)g(BITPIX)0 3491 y(k)m(eyw)m(ord)c(w)m(ould)f(b)s(e)g (equal)h(to)h(LONG)p 1392 3491 V 32 w(IMG)f(=)g(32)g(and)f(BZER)m(O)g (w)m(ould)h(b)s(e)f(equal)h(to)g(2147483648)k(\(i.e.)55 b(2)0 3604 y(raised)30 b(to)h(the)g(31st)g(p)s(o)m(w)m(er\).)0 3764 y(The)j(CFITSIO)g(in)m(terface)i(routines)f(will)g(e\016cien)m (tly)i(and)d(transparen)m(tly)i(apply)e(the)h(appropriate)g(o\013set)h (in)0 3877 y(these)29 b(cases)h(so)f(in)g(general)h(application)g (programs)f(do)g(not)g(need)f(to)i(b)s(e)e(concerned)h(with)g(ho)m(w)g (the)g(unsigned)0 3990 y(v)-5 b(alues)44 b(are)h(actually)h(stored)e (in)f(the)i(FITS)e(\014le.)82 b(As)44 b(a)g(con)m(v)m(enience)j(for)c (users,)k(CFITSIO)c(has)h(sev)m(eral)0 4103 y(prede\014ned)19 b(constan)m(ts)j(for)f(the)g(v)-5 b(alue)21 b(of)g(BITPIX)g(\(USHOR)-8 b(T)p 2189 4103 V 33 w(IMG,)21 b(ULONG)p 2790 4103 V 33 w(IMG\))h(and)e(for)h(the)g(TF)m(ORMn)0 4216 y(v)-5 b(alue)36 b(in)f(the)h(case)g(of)g(binary)f(tables)h(\(`U')h(and)e (`V'\))h(whic)m(h)f(programmers)g(can)h(use)f(when)g(creating)i(FITS)0 4329 y(\014les)i(con)m(taining)h(unsigned)e(in)m(teger)i(v)-5 b(alues.)66 b(The)39 b(follo)m(wing)h(co)s(de)f(fragmen)m(t)g (illustrates)h(ho)m(w)f(to)h(write)f(a)0 4442 y(FITS)30 b(1-D)h(primary)f(arra)m(y)g(of)h(unsigned)e(16-bit)j(in)m(tegers:)286 4698 y Fe(unsigned)46 b(short)g(uarray[100];)286 4811 y(int)h(naxis,)f(status;)286 4924 y(long)h(naxes[10],)e(group,)h (firstelem,)f(nelements;)334 5036 y(...)286 5149 y(status)h(=)i(0;)286 5262 y(naxis)f(=)g(1;)286 5375 y(naxes[0])f(=)h(100;)286 5488 y(fits_create_img\(fptr,)42 b(USHORT_IMG,)j(naxis,)h(naxes,)g (&status\);)286 5714 y(firstelem)g(=)h(1;)p eop end %%Page: 21 29 TeXDict begin 21 28 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.21) cvn H.B /DEST pdfmark end 0 299 a Fh(4.4.)72 b(SUPPOR)-8 b(T)30 b(F)m(OR)g(UNSIGNED)h(INTEGERS)f(AND)h(SIGNED)f(BYTES)942 b Fj(21)286 555 y Fe(nelements)46 b(=)h(100;)286 668 y(fits_write_img\(fptr,)c(TUSHORT,)i(firstelem,)g(nelements,)1241 781 y(uarray,)h(&status\);)334 894 y(...)0 1135 y Fj(In)40 b(the)h(ab)s(o)m(v)m(e)i(example,)h(the)e(2nd)e(parameter)h(in)g (\014ts)p 1998 1135 28 4 v 33 w(create)p 2267 1135 V 34 w(img)g(tells)h(CFITSIO)e(to)i(write)f(the)g(header)0 1248 y(k)m(eyw)m(ords)34 b(appropriate)g(for)f(an)g(arra)m(y)i(of)e (16-bit)i(unsigned)e(in)m(tegers)i(\(i.e.,)h(BITPIX)d(=)g(16)i(and)e (BZER)m(O)g(=)0 1361 y(32768\).)41 b(Then)23 b(the)h(\014ts)p 834 1361 V 32 w(write)p 1068 1361 V 33 w(img)h(routine)f(writes)f(the)i (arra)m(y)f(of)g(unsigned)f(short)g(in)m(tegers)i(\(uarra)m(y\))g(in)m (to)g(the)0 1474 y(primary)f(arra)m(y)h(of)g(the)g(FITS)f(\014le.)39 b(Similarly)-8 b(,)27 b(a)e(32-bit)i(unsigned)c(in)m(teger)j(image)h (ma)m(y)e(b)s(e)f(created)i(b)m(y)f(setting)0 1587 y(the)34 b(second)f(parameter)h(in)f(\014ts)p 1130 1587 V 33 w(create)p 1399 1587 V 34 w(img)h(equal)g(to)g(`ULONG)p 2330 1587 V 33 w(IMG')g(and)f(b)m(y)h(calling)g(the)g(\014ts)p 3491 1587 V 33 w(write)p 3726 1587 V 33 w(img)0 1700 y(routine)j(with)f(the)h(second)f(parameter)h(=)f(TULONG)h(to)g(write)g (the)f(arra)m(y)h(of)g(unsigned)f(long)h(image)h(pixel)0 1812 y(v)-5 b(alues.)0 1973 y(An)27 b(analogous)h(set)f(of)g(routines)g (are)g(a)m(v)-5 b(ailable)30 b(for)c(reading)h(or)g(writing)g(unsigned) f(in)m(teger)i(v)-5 b(alues)28 b(and)e(signed)0 2086 y(b)m(yte)i(v)-5 b(alues)28 b(in)g(a)g(FITS)f(binary)g(table)i (extension.)40 b(When)28 b(sp)s(ecifying)f(the)h(TF)m(ORMn)g(k)m(eyw)m (ord)g(v)-5 b(alue)28 b(whic)m(h)0 2198 y(de\014nes)36 b(the)h(format)g(of)g(a)h(column,)g(CFITSIO)d(recognized)k(3)e (additional)h(data)f(t)m(yp)s(e)g(co)s(des)g(b)s(esides)f(those)0 2311 y(already)30 b(de\014ned)f(in)g(the)h(FITS)f(standard:)40 b(`U')30 b(meaning)g(a)g(16-bit)h(unsigned)e(in)m(teger)i(column,)f (`V')g(for)g(a)g(32-)0 2424 y(bit)c(unsigned)e(in)m(teger)j(column,)g (and)e('S')g(for)g(a)h(signed)g(b)m(yte)g(column.)39 b(These)25 b(non-standard)g(data)h(t)m(yp)s(e)g(co)s(des)0 2537 y(are)36 b(not)g(actually)i(written)e(in)m(to)g(the)g(FITS)g (\014le)f(but)h(instead)g(are)g(just)f(used)g(in)m(ternally)i(within)e (CFITSIO.)0 2650 y(The)30 b(follo)m(wing)i(co)s(de)e(fragmen)m(t)h (illustrates)h(ho)m(w)e(to)h(use)f(these)h(features:)286 2891 y Fe(unsigned)46 b(short)g(uarray[100];)286 3004 y(unsigned)g(int)95 b(varray[100];)286 3230 y(int)47 b(colnum,)f(tfields,)g(status;)286 3343 y(long)h(nrows,)f(firstrow,)f (firstelem,)g(nelements,)g(pcount;)286 3569 y(char)i(extname[])e(=)j ("Test_table";)521 b(/*)47 b(extension)f(name)g(*/)286 3794 y(/*)i(define)e(the)h(name,)f(data)h(type,)f(and)h(physical)e (units)i(for)g(the)g(2)g(columns)f(*/)286 3907 y(char)h(*ttype[])f(=)h ({)g("Col_1",)f("Col_2",)g("Col_3")f(};)286 4020 y(char)i(*tform[])f(=) h({)g("1U",)285 b("1V",)190 b("1S"};)94 b(/*)47 b(special)f(CFITSIO)g (codes)g(*/)286 4133 y(char)h(*tunit[])f(=)h({)g(")h(",)381 b(")48 b(",)190 b(")47 b(")h(};)334 4246 y(...)525 4472 y(/*)f(write)g(the)f(header)h(keywords)e(*/)286 4585 y(status)94 b(=)48 b(0;)286 4698 y(nrows)142 b(=)48 b(1;)286 4811 y(tfields)e(=)i(3)286 4924 y(pcount)94 b(=)48 b(0;)286 5036 y(fits_create_tbl\(fptr,)42 b(BINARY_TBL,)j(nrows,)h(tfields,)g (ttype,)g(tform,)764 5149 y(tunit,)g(extname,)f(&status\);)525 5375 y(/*)i(write)g(the)f(unsigned)g(shorts)g(to)h(the)g(1st)g(column)f (*/)286 5488 y(colnum)190 b(=)47 b(1;)286 5601 y(firstrow)94 b(=)47 b(1;)286 5714 y(firstelem)f(=)h(1;)p eop end %%Page: 22 30 TeXDict begin 22 29 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.22) cvn H.B /DEST pdfmark end 0 299 a Fj(22)1763 b Fh(CHAPTER)29 b(4.)112 b(PR)m(OGRAMMING)32 b(GUIDELINES)286 555 y Fe(nelements)46 b(=)h(100;)286 668 y(fits_write_col\(fptr,)c(TUSHORT,)i(colnum,)h (firstrow,)f(firstelem,)668 781 y(nelements,)g(uarray,)h(&status\);)525 1007 y(/*)h(now)g(write)f(the)h(unsigned)f(longs)g(to)h(the)g(2nd)g (column)f(*/)286 1120 y(colnum)190 b(=)47 b(2;)286 1233 y(fits_write_col\(fptr,)c(TUINT,)j(colnum,)g(firstrow,)f(firstelem,)668 1346 y(nelements,)g(varray,)h(&status\);)334 1458 y(...)0 1721 y Fj(Note)22 b(that)g(the)f(non-standard)f(TF)m(ORM)h(v)-5 b(alues)21 b(for)g(the)g(3)g(columns,)i(`U')e(and)g(`V',)h(tell)g (CFITSIO)d(to)j(write)f(the)0 1834 y(k)m(eyw)m(ords)27 b(appropriate)f(for)g(unsigned)f(16-bit)j(and)d(unsigned)h(32-bit)h(in) m(tegers,)i(resp)s(ectiv)m(ely)e(\(i.e.,)i(TF)m(ORMn)0 1947 y(=)39 b('1I')i(and)e(TZER)m(On)f(=)h(32768)j(for)e(unsigned)e (16-bit)j(in)m(tegers,)j(and)39 b(TF)m(ORMn)h(=)f('1J')h(and)f(TZER)m (On)0 2060 y(=)c(2147483648)40 b(for)35 b(unsigned)f(32-bit)i(in)m (tegers\).)57 b(The)35 b('S')g(TF)m(ORMn)g(v)-5 b(alue)36 b(tells)h(CFITSIO)c(to)j(write)g(the)0 2173 y(k)m(eyw)m(ords)30 b(appropriate)g(for)g(a)g(signed)g(8-bit)h(b)m(yte)f(column)g(with)f (TF)m(ORMn)h(=)g('1B')h(and)e(TZER)m(On)g(=)g(-128.)0 2285 y(The)h(calls)h(to)h(\014ts)p 628 2285 28 4 v 32 w(write)p 862 2285 V 33 w(col)f(then)f(write)h(the)g(arra)m(ys)f(of)h (unsigned)e(in)m(teger)j(v)-5 b(alues)31 b(to)g(the)f(columns.)0 2443 y SDict begin H.S end 0 2443 a 0 2443 a SDict begin 13.6 H.A end 0 2443 a 0 2443 a SDict begin [ /View [/XYZ H.V] /Dest (section.4.5) cvn H.B /DEST pdfmark end 0 2443 a 179 x Ff(4.5)135 b(Dealing)47 b(with)e(Character)h(Strings)0 2873 y Fj(The)36 b(c)m(haracter)j(string)d(v)-5 b(alues)38 b(in)e(a)h(FITS)f(header)h(or)g(in)f(an)h(ASCI)s(I)e(column)i(in)f(a)i (FITS)e(table)h(extension)0 2986 y(are)i(generally)i(padded)d(out)h (with)g(non-signi\014can)m(t)h(space)f(c)m(haracters)i(\(ASCI)s(I)d (32\))i(to)g(\014ll)f(up)f(the)h(header)0 3099 y(record)33 b(or)h(the)f(column)h(width.)49 b(When)33 b(reading)h(a)g(FITS)e (string)i(v)-5 b(alue,)35 b(the)e(CFITSIO)f(routines)i(will)f(strip)0 3212 y(o\013)38 b(these)f(non-signi\014can)m(t)h(trailing)g(spaces)f (and)g(will)g(return)f(a)i(n)m(ull-terminated)g(string)f(v)-5 b(alue)37 b(con)m(taining)0 3325 y(only)d(the)g(signi\014can)m(t)g(c)m (haracters.)52 b(Leading)34 b(spaces)g(in)g(a)g(FITS)f(string)g(are)h (considered)g(signi\014can)m(t.)52 b(If)33 b(the)0 3438 y(string)i(con)m(tains)h(all)g(blanks,)g(then)e(CFITSIO)g(will)h (return)f(a)h(single)g(blank)g(c)m(haracter,)j(i.e,)f(the)e(\014rst)f (blank)0 3550 y(is)c(considered)f(to)i(b)s(e)e(signi\014can)m(t,)i (since)f(it)g(distinguishes)g(the)g(string)f(from)h(a)g(n)m(ull)f(or)h (unde\014ned)e(string,)i(but)0 3663 y(the)h(remaining)f(trailing)h (spaces)g(are)g(not)g(signi\014can)m(t.)0 3823 y(Similarly)-8 b(,)41 b(when)c(writing)h(string)g(v)-5 b(alues)38 b(to)h(a)g(FITS)e (\014le)h(the)g(CFITSIO)f(routines)h(exp)s(ect)g(to)h(get)g(a)g(n)m (ull-)0 3936 y(terminated)33 b(string)g(as)g(input;)g(CFITSIO)e(will)i (pad)f(the)h(string)g(with)f(blanks)g(if)h(necessary)g(when)f(writing)g (it)0 4049 y(to)f(the)g(FITS)e(\014le.)0 4209 y(When)j(calling)i (CFITSIO)d(routines)i(that)g(return)e(a)i(c)m(haracter)h(string)f(it)g (is)f(vital)i(that)f(the)g(size)g(of)g(the)g(c)m(har)0 4322 y(arra)m(y)38 b(b)s(e)g(large)h(enough)e(to)i(hold)e(the)h(en)m (tire)h(string)f(of)g(c)m(haracters,)k(otherwise)c(CFITSIO)e(will)i(o)m (v)m(erwrite)0 4435 y(whatev)m(er)d(memory)e(lo)s(cations)i(follo)m(w)g (the)f(c)m(har)h(arra)m(y)-8 b(,)35 b(p)s(ossibly)e(causing)h(the)g (program)g(to)g(execute)h(incor-)0 4548 y(rectly)-8 b(.)42 b(This)30 b(t)m(yp)s(e)g(of)h(error)f(can)h(b)s(e)f(di\016cult)g(to)h (debug,)f(so)h(programmers)f(should)f(alw)m(a)m(ys)j(ensure)e(that)h (the)0 4661 y(c)m(har)c(arra)m(ys)g(are)g(allo)s(cated)i(enough)d (space)i(to)f(hold)g(the)f(longest)i(p)s(ossible)f(string,)g Fi(including)h Fj(the)f(terminat-)0 4774 y(ing)k(NULL)g(c)m(haracter.) 45 b(The)30 b(\014tsio.h)h(\014le)h(con)m(tains)g(the)f(follo)m(wing)i (de\014ned)d(constan)m(ts)i(whic)m(h)f(programmers)0 4887 y(are)g(strongly)g(encouraged)g(to)g(use)f(whenev)m(er)g(they)h (are)f(allo)s(cating)j(space)e(for)f(c)m(har)h(arra)m(ys:)0 5149 y Fe(#define)46 b(FLEN_FILENAME)e(1025)j(/*)g(max)g(length)f(of)h (a)g(filename)f(*/)0 5262 y(#define)g(FLEN_KEYWORD)140 b(72)95 b(/*)47 b(max)g(length)f(of)h(a)g(keyword)94 b(*/)0 5375 y(#define)46 b(FLEN_CARD)284 b(81)95 b(/*)47 b(length)f(of)h(a)h(FITS)e(header)g(card)h(*/)0 5488 y(#define)f(FLEN_VALUE)236 b(71)95 b(/*)47 b(max)g(length)f(of)h(a)g (keyword)f(value)h(string)f(*/)0 5601 y(#define)g(FLEN_COMMENT)140 b(73)95 b(/*)47 b(max)g(length)f(of)h(a)g(keyword)f(comment)g(string)g (*/)0 5714 y(#define)g(FLEN_ERRMSG)188 b(81)95 b(/*)47 b(max)g(length)f(of)h(a)g(CFITSIO)f(error)h(message)e(*/)p eop end %%Page: 23 31 TeXDict begin 23 30 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.23) cvn H.B /DEST pdfmark end 0 299 a Fh(4.6.)72 b(IMPLICIT)29 b(D)m(A)-8 b(T)g(A)32 b(TYPE)e(CONVERSION)1938 b Fj(23)0 555 y Fe(#define)46 b(FLEN_STATUS)188 b(31)95 b(/*)47 b(max)g(length)f(of)h(a)g(CFITSIO)f(status)g(text)h(string)f(*/)0 815 y Fj(F)-8 b(or)23 b(example,)h(when)d(declaring)i(a)f(c)m(har)g (arra)m(y)h(to)f(hold)g(the)g(v)-5 b(alue)22 b(string)g(of)g(FITS)f(k)m (eyw)m(ord,)k(use)c(the)h(follo)m(wing)0 928 y(statemen)m(t:)191 1188 y Fe(char)47 b(value[FLEN_VALUE];)0 1448 y Fj(Note)41 b(that)f(FLEN)p 686 1448 28 4 v 33 w(KEYW)m(ORD)g(is)f(longer)h(than)f (needed)g(for)g(the)h(nominal)f(8-c)m(haracter)j(k)m(eyw)m(ord)e(name)0 1561 y(b)s(ecause)30 b(the)h(HIERAR)m(CH)f(con)m(v)m(en)m(tion)j(supp)s (orts)28 b(longer)j(k)m(eyw)m(ord)g(names.)0 1715 y SDict begin H.S end 0 1715 a 0 1715 a SDict begin 13.6 H.A end 0 1715 a 0 1715 a SDict begin [ /View [/XYZ H.V] /Dest (section.4.6) cvn H.B /DEST pdfmark end 0 1715 a 179 x Ff(4.6)135 b(Implicit)46 b(Data)g(T)l(yp)t(e)f(Con)l(v)l(ersion)0 2145 y Fj(The)29 b(CFITSIO)e(routines)i(that)h(read)f(and)f(write)i(n)m (umerical)f(data)h(can)g(p)s(erform)d(implicit)j(data)g(t)m(yp)s(e)f (con)m(v)m(er-)0 2257 y(sion.)39 b(This)25 b(means)h(that)g(the)g(data) g(t)m(yp)s(e)g(of)g(the)g(v)-5 b(ariable)26 b(or)g(arra)m(y)g(in)f(the) h(program)g(do)s(es)f(not)h(need)f(to)i(b)s(e)e(the)0 2370 y(same)g(as)f(the)h(data)g(t)m(yp)s(e)g(of)f(the)h(v)-5 b(alue)25 b(in)f(the)g(FITS)g(\014le.)39 b(Data)26 b(t)m(yp)s(e)f(con)m (v)m(ersion)g(is)g(supp)s(orted)d(for)i(n)m(umerical)0 2483 y(and)37 b(string)g(data)g(t)m(yp)s(es)h(\(if)f(the)g(string)g (con)m(tains)i(a)e(v)-5 b(alid)38 b(n)m(um)m(b)s(er)e(enclosed)h(in)g (quotes\))h(when)e(reading)i(a)0 2596 y(FITS)30 b(header)h(k)m(eyw)m (ord)g(v)-5 b(alue)31 b(and)f(for)h(n)m(umeric)g(v)-5 b(alues)31 b(when)f(reading)h(or)f(writing)h(v)-5 b(alues)31 b(in)g(the)g(primary)0 2709 y(arra)m(y)24 b(or)g(a)h(table)f(column.)39 b(CFITSIO)22 b(returns)h(status)h(=)f(NUM)p 2267 2709 28 4 v 34 w(O)m(VERFLO)m(W)i(if)e(the)h(con)m(v)m(erted)i(data)e(v)-5 b(alue)0 2822 y(exceeds)33 b(the)g(range)g(of)g(the)f(output)g(data)i (t)m(yp)s(e.)47 b(Implicit)33 b(data)g(t)m(yp)s(e)g(con)m(v)m(ersion)h (is)e(not)h(supp)s(orted)d(within)0 2935 y(binary)g(tables)h(for)f (string,)g(logical,)k(complex,)d(or)f(double)g(complex)h(data)g(t)m(yp) s(es.)0 3095 y(In)g(addition,)h(an)m(y)f(table)h(column)f(ma)m(y)h(b)s (e)f(read)g(as)h(if)f(it)h(con)m(tained)g(string)f(v)-5 b(alues.)44 b(In)31 b(the)g(case)i(of)e(n)m(umeric)0 3208 y(columns)f(the)h(returned)e(string)h(will)h(b)s(e)f(formatted)h (using)e(the)i(TDISPn)e(displa)m(y)i(format)f(if)h(it)g(exists.)0 3363 y SDict begin H.S end 0 3363 a 0 3363 a SDict begin 13.6 H.A end 0 3363 a 0 3363 a SDict begin [ /View [/XYZ H.V] /Dest (section.4.7) cvn H.B /DEST pdfmark end 0 3363 a 179 x Ff(4.7)135 b(Data)46 b(Scaling)0 3792 y Fj(When)38 b(reading)f(n)m(umerical)i(data)f(v)-5 b(alues)38 b(in)f(the)h(primary) f(arra)m(y)h(or)g(a)g(table)h(column,)h(the)d(v)-5 b(alues)38 b(will)h(b)s(e)0 3905 y(scaled)f(automatically)j(b)m(y)c(the)g(BSCALE)g (and)g(BZER)m(O)g(\(or)h(TSCALn)e(and)h(TZER)m(On\))f(header)h(v)-5 b(alues)38 b(if)0 4018 y(they)31 b(are)f(presen)m(t)h(in)f(the)g (header.)41 b(The)30 b(scaled)h(data)g(that)g(is)f(returned)g(to)h(the) f(reading)h(program)f(will)h(ha)m(v)m(e)382 4278 y Fe(output)46 b(value)g(=)i(\(FITS)e(value\))g(*)i(BSCALE)e(+)h(BZERO)0 4538 y Fj(\(a)30 b(corresp)s(onding)e(form)m(ula)h(using)g(TSCALn)e (and)i(TZER)m(On)e(is)i(used)g(when)f(reading)h(from)g(table)h (columns\).)0 4650 y(In)h(the)i(case)g(of)f(in)m(teger)h(output)f(v)-5 b(alues)32 b(the)h(\015oating)g(p)s(oin)m(t)f(scaled)g(v)-5 b(alue)33 b(is)f(truncated)g(to)h(an)f(in)m(teger)h(\(not)0 4763 y(rounded)i(to)j(the)f(nearest)h(in)m(teger\).)62 b(The)36 b(\014ts)p 1673 4763 28 4 v 32 w(set)p 1816 4763 V 34 w(bscale)i(and)e(\014ts)p 2430 4763 V 32 w(set)p 2573 4763 V 34 w(tscale)i(routines)f(\(describ)s(ed)f(in)h(the)0 4876 y(`Adv)-5 b(anced')29 b(c)m(hapter\))h(ma)m(y)g(b)s(e)e(used)h(to) g(o)m(v)m(erride)i(the)e(scaling)h(parameters)f(de\014ned)f(in)h(the)g (header)g(\(e.g.,)i(to)0 4989 y(turn)e(o\013)i(the)g(scaling)g(so)g (that)g(the)f(program)g(can)h(read)f(the)h(ra)m(w)f(unscaled)h(v)-5 b(alues)30 b(from)g(the)h(FITS)e(\014le\).)0 5149 y(When)44 b(writing)h(n)m(umerical)g(data)g(to)g(the)g(primary)f(arra)m(y)h(or)f (to)h(a)g(table)h(column)e(the)h(data)g(v)-5 b(alues)45 b(will)0 5262 y(generally)29 b(b)s(e)f(automatically)j(in)m(v)m(ersely) f(scaled)f(b)m(y)f(the)g(v)-5 b(alue)29 b(of)f(the)h(BSCALE)e(and)h (BZER)m(O)g(\(or)h(TSCALn)0 5375 y(and)35 b(TZER)m(On\))f(k)m(eyw)m (ord)i(v)-5 b(alues)35 b(if)h(they)f(they)g(exist)i(in)e(the)g(header.) 55 b(These)35 b(k)m(eyw)m(ords)h(m)m(ust)f(ha)m(v)m(e)i(b)s(een)0 5488 y(written)31 b(to)h(the)g(header)f(b)s(efore)g(an)m(y)g(data)h(is) g(written)f(for)g(them)g(to)h(ha)m(v)m(e)h(an)m(y)e(immediate)i (e\013ect.)45 b(One)30 b(ma)m(y)0 5601 y(also)h(use)g(the)f(\014ts)p 623 5601 V 33 w(set)p 767 5601 V 33 w(bscale)i(and)d(\014ts)p 1367 5601 V 33 w(set)p 1511 5601 V 33 w(tscale)j(routines)f(to)g (de\014ne)f(or)g(o)m(v)m(erride)i(the)f(scaling)g(k)m(eyw)m(ords)g(in)0 5714 y(the)e(header)g(\(e.g.,)i(to)e(turn)f(o\013)h(the)g(scaling)h(so) f(that)h(the)f(program)f(can)h(write)g(the)g(ra)m(w)g(unscaled)g(v)-5 b(alues)29 b(in)m(to)p eop end %%Page: 24 32 TeXDict begin 24 31 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.24) cvn H.B /DEST pdfmark end 0 299 a Fj(24)1763 b Fh(CHAPTER)29 b(4.)112 b(PR)m(OGRAMMING)32 b(GUIDELINES)0 555 y Fj(the)26 b(FITS)g(\014le\).)40 b(If)25 b(scaling)i(is)g(p)s(erformed,)e(the)i (in)m(v)m(erse)g(scaled)g(output)e(v)-5 b(alue)27 b(that)g(is)f (written)g(in)m(to)h(the)g(FITS)0 668 y(\014le)j(will)h(ha)m(v)m(e)430 956 y Fe(FITS)46 b(value)h(=)g(\(\(input)f(value\))g(-)h(BZERO\))f(/)i (BSCALE)0 1244 y Fj(\(a)39 b(corresp)s(onding)d(form)m(ula)i(using)g (TSCALn)e(and)h(TZER)m(On)g(is)h(used)f(when)f(writing)i(to)h(table)g (columns\).)0 1357 y(Rounding)34 b(to)i(the)g(nearest)g(in)m(teger,)i (rather)d(than)g(truncation,)j(is)d(p)s(erformed)f(when)g(writing)h(in) m(teger)i(data)0 1469 y(t)m(yp)s(es)30 b(to)i(the)e(FITS)g(\014le.)0 1657 y SDict begin H.S end 0 1657 a 0 1657 a SDict begin 13.6 H.A end 0 1657 a 0 1657 a SDict begin [ /View [/XYZ H.V] /Dest (section.4.8) cvn H.B /DEST pdfmark end 0 1657 a 179 x Ff(4.8)135 b(Supp)t(ort)44 b(for)h(IEEE)h(Sp)t(ecial)f(V)-11 b(alues)0 2093 y Fj(The)26 b(ANSI/IEEE-754)h(\015oating-p)s(oin)m(t)h (n)m(um)m(b)s(er)d(standard)g(de\014nes)h(certain)h(sp)s(ecial)g(v)-5 b(alues)26 b(that)h(are)g(used)e(to)0 2206 y(represen)m(t)j(suc)m(h)g (quan)m(tities)h(as)f(Not-a-Num)m(b)s(er)h(\(NaN\),)h(denormalized,)f (under\015o)m(w,)e(o)m(v)m(er\015o)m(w,)j(and)d(in\014nit)m(y)-8 b(.)0 2319 y(\(See)31 b(the)g(App)s(endix)d(in)j(the)f(FITS)g(standard) f(or)i(the)g(FITS)e(User's)i(Guide)f(for)g(a)h(list)g(of)g(these)g(v)-5 b(alues\).)41 b(The)0 2432 y(CFITSIO)31 b(routines)i(that)g(read)f (\015oating)i(p)s(oin)m(t)f(data)g(in)f(FITS)g(\014les)h(recognize)h (these)f(IEEE)f(sp)s(ecial)i(v)-5 b(alues)0 2544 y(and)27 b(b)m(y)h(default)h(in)m(terpret)f(the)h(o)m(v)m(er\015o)m(w)g(and)f (in\014nit)m(y)f(v)-5 b(alues)29 b(as)f(b)s(eing)g(equiv)-5 b(alen)m(t)29 b(to)g(a)g(NaN,)g(and)e(con)m(v)m(ert)0 2657 y(the)37 b(under\015o)m(w)e(and)i(denormalized)g(v)-5 b(alues)37 b(in)m(to)h(zeros.)60 b(In)36 b(some)i(cases)f(programmers)g (ma)m(y)g(w)m(an)m(t)h(access)0 2770 y(to)d(the)g(ra)m(w)f(IEEE)g(v)-5 b(alues,)36 b(without)e(an)m(y)h(mo)s(di\014cation)g(b)m(y)f(CFITSIO.)f (This)h(can)h(b)s(e)e(done)i(b)m(y)f(calling)i(the)0 2883 y(\014ts)p 127 2883 28 4 v 32 w(read)p 331 2883 V 33 w(img)27 b(or)g(\014ts)p 767 2883 V 32 w(read)p 971 2883 V 33 w(col)g(routines)g(while)f(sp)s(ecifying)h(0.0)h(as)e (the)h(v)-5 b(alue)27 b(of)g(the)g(NULL)-10 b(V)g(AL)26 b(parameter.)0 2996 y(This)44 b(will)h(force)h(CFITSIO)d(to)i(simply)g (pass)f(the)h(IEEE)f(v)-5 b(alues)45 b(through)f(to)i(the)f (application)h(program)0 3109 y(without)38 b(an)m(y)h(mo)s (di\014cation.)65 b(This)37 b(is)h(not)h(fully)f(supp)s(orted)e(on)i(V) -10 b(AX/VMS)40 b(mac)m(hines,)h(ho)m(w)m(ev)m(er,)g(where)0 3222 y(there)34 b(is)f(no)g(easy)h(w)m(a)m(y)h(to)f(b)m(ypass)f(the)g (default)h(in)m(terpretation)h(of)e(the)h(IEEE)f(sp)s(ecial)h(v)-5 b(alues.)50 b(This)33 b(is)g(also)0 3335 y(not)e(supp)s(orted)e(when)h (reading)g(\015oating-p)s(oin)m(t)i(images)g(that)g(ha)m(v)m(e)g(b)s (een)e(compressed)g(with)g(the)h(FITS)f(tiled)0 3448 y(image)i(compression)f(con)m(v)m(en)m(tion)j(that)d(is)g(discussed)g (in)f(section)j(5.6;)f(the)g(pixels)f(v)-5 b(alues)31 b(in)g(tile)h(compressed)0 3561 y(images)42 b(are)f(represen)m(ted)f(b) m(y)h(scaled)h(in)m(tegers,)i(and)c(a)h(reserv)m(ed)g(in)m(teger)h(v)-5 b(alue)41 b(\(not)h(a)f(NaN\))h(is)e(used)g(to)0 3674 y(represen)m(t)30 b(unde\014ned)f(pixels.)0 3861 y SDict begin H.S end 0 3861 a 0 3861 a SDict begin 13.6 H.A end 0 3861 a 0 3861 a SDict begin [ /View [/XYZ H.V] /Dest (section.4.9) cvn H.B /DEST pdfmark end 0 3861 a 179 x Ff(4.9)135 b(Error)46 b(Status)f(V)-11 b(alues)45 b(and)g(the)g(Error)g(Message)h (Stac)l(k)0 4297 y Fj(Nearly)36 b(all)g(the)g(CFITSIO)e(routines)h (return)f(an)h(error)g(status)h(v)-5 b(alue)35 b(in)g(2)h(w)m(a)m(ys:) 51 b(as)36 b(the)f(v)-5 b(alue)36 b(of)g(the)f(last)0 4410 y(parameter)29 b(in)f(the)g(function)g(call,)j(and)d(as)g(the)h (returned)e(v)-5 b(alue)29 b(of)f(the)h(function)f(itself.)41 b(This)27 b(pro)m(vides)i(some)0 4523 y(\015exibilit)m(y)37 b(in)e(the)h(w)m(a)m(y)h(programmers)e(can)h(test)h(if)f(an)f(error)h (o)s(ccurred,)g(as)g(illustrated)h(in)e(the)h(follo)m(wing)i(2)0 4636 y(co)s(de)31 b(fragmen)m(ts:)191 4924 y Fe(if)47 b(\()h(fits_write_record\(fptr,)41 b(card,)46 b(&status\))g(\))430 5036 y(printf\(")f(Error)h(occurred)g(while)g(writing)g(keyword."\);)0 5262 y(or,)191 5488 y(fits_write_record\(fptr,)41 b(card,)47 b(&status\);)191 5601 y(if)g(\()h(status)e(\))430 5714 y(printf\(")f(Error)h(occurred)g(while)g(writing)g(keyword."\);)p eop end %%Page: 25 33 TeXDict begin 25 32 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.25) cvn H.B /DEST pdfmark end 0 299 a Fh(4.10.)73 b(V)-10 b(ARIABLE-LENGTH)31 b(ARRA)-8 b(YS)30 b(IN)g(BINAR)-8 b(Y)32 b(T)-8 b(ABLES)1327 b Fj(25)0 555 y(A)27 b(listing)h(of)g(all)g(the)f(CFITSIO)f(status)i (co)s(de)f(v)-5 b(alues)28 b(is)f(giv)m(en)h(at)g(the)g(end)e(of)i (this)f(do)s(cumen)m(t.)39 b(Programmers)0 668 y(are)33 b(encouraged)g(to)g(use)f(the)h(sym)m(b)s(olic)f(mnemonics)g (\(de\014ned)g(in)g(\014tsio.h\))h(rather)f(than)g(the)h(actual)h(in)m (teger)0 781 y(status)d(v)-5 b(alues)30 b(to)i(impro)m(v)m(e)f(the)f (readabilit)m(y)i(of)f(their)f(co)s(de.)0 941 y(The)i(CFITSIO)f (library)g(uses)h(an)g(`inherited)h(status')g(con)m(v)m(en)m(tion)h (for)e(the)h(status)f(parameter)h(whic)m(h)f(means)0 1054 y(that)37 b(if)f(a)h(routine)f(is)h(called)g(with)f(a)h(p)s (ositiv)m(e)g(input)f(v)-5 b(alue)36 b(of)h(the)g(status)f(parameter)h (as)g(input,)g(then)f(the)0 1167 y(routine)j(will)f(exit)i(immediately) g(without)e(c)m(hanging)i(the)e(v)-5 b(alue)39 b(of)g(the)g(status)g (parameter.)65 b(Th)m(us,)40 b(if)f(one)0 1280 y(passes)24 b(the)h(status)g(v)-5 b(alue)25 b(returned)f(from)g(eac)m(h)i(CFITSIO)d (routine)h(as)h(input)f(to)h(the)g(next)g(CFITSIO)e(routine,)0 1393 y(then)28 b(whenev)m(er)g(an)g(error)g(is)h(detected)g(all)h (further)d(CFITSIO)f(pro)s(cessing)i(will)h(cease.)42 b(This)27 b(con)m(v)m(en)m(tion)k(can)0 1506 y(simplify)h(the)h(error)f (c)m(hec)m(king)j(in)d(application)i(programs)e(b)s(ecause)h(it)g(is)g (not)g(necessary)g(to)g(c)m(hec)m(k)i(the)d(v)-5 b(alue)0 1619 y(of)30 b(the)g(status)h(parameter)f(after)h(ev)m(ery)g(single)f (CFITSIO)f(routine)h(call.)42 b(If)30 b(a)g(program)g(con)m(tains)h(a)g (sequence)0 1732 y(of)d(sev)m(eral)i(CFITSIO)d(calls,)j(one)e(can)h (just)e(c)m(hec)m(k)j(the)f(status)f(v)-5 b(alue)29 b(after)g(the)f (last)h(call.)41 b(Since)29 b(the)f(returned)0 1844 y(status)33 b(v)-5 b(alues)33 b(are)g(generally)h(distinctiv)m(e,)h(it)f(should)d (b)s(e)i(p)s(ossible)f(to)h(determine)g(whic)m(h)g(routine)g (originally)0 1957 y(returned)c(the)i(error)f(status.)0 2118 y(CFITSIO)c(also)i(main)m(tains)h(an)e(in)m(ternal)h(stac)m(k)h (of)f(error)f(messages)h(\(80-c)m(haracter)j(maxim)m(um)c(length\))h (whic)m(h)0 2230 y(in)36 b(man)m(y)g(cases)h(pro)m(vide)f(a)g(more)g (detailed)i(explanation)f(of)f(the)g(cause)h(of)f(the)g(error)g(than)f (is)h(pro)m(vided)g(b)m(y)0 2343 y(the)k(error)e(status)i(n)m(um)m(b)s (er)e(alone.)69 b(It)39 b(is)h(recommended)f(that)g(the)h(error)f (message)h(stac)m(k)h(b)s(e)e(prin)m(ted)g(out)0 2456 y(whenev)m(er)g(a)g(program)g(detects)h(a)f(CFITSIO)e(error.)66 b(The)38 b(function)h(\014ts)p 2653 2456 28 4 v 32 w(rep)s(ort)p 2931 2456 V 32 w(error)g(will)g(prin)m(t)g(out)g(the)0 2569 y(en)m(tire)31 b(error)e(message)h(stac)m(k,)i(or)d(alternativ)m (ely)k(one)d(ma)m(y)g(call)h(\014ts)p 2376 2569 V 32 w(read)p 2580 2569 V 33 w(errmsg)e(to)h(get)h(the)f(error)f(messages)0 2682 y(one)i(at)g(a)g(time.)0 2859 y SDict begin H.S end 0 2859 a 0 2859 a SDict begin 13.6 H.A end 0 2859 a 0 2859 a SDict begin [ /View [/XYZ H.V] /Dest (section.4.10) cvn H.B /DEST pdfmark end 0 2859 a 197 x Ff(4.10)136 b(V)-11 b(ariable-Length)45 b(Arra)l(ys)g(in)g(Binary)g(T)-11 b(ables)0 3314 y Fj(CFITSIO)33 b(pro)m(vides)i(easy-to-use)h(supp)s (ort)d(for)i(reading)g(and)f(writing)h(data)g(in)g(v)-5 b(ariable)35 b(length)g(\014elds)g(of)g(a)0 3427 y(binary)27 b(table.)40 b(The)27 b(v)-5 b(ariable)29 b(length)f(columns)f(ha)m(v)m (e)i(TF)m(ORMn)e(k)m(eyw)m(ord)h(v)-5 b(alues)28 b(of)g(the)f(form)g (`1Pt\(len\)')j(or)0 3540 y(`1Qt\(len\)')36 b(where)d(`t')h(is)g(the)g (data)g(t)m(yp)s(e)g(co)s(de)g(\(e.g.,)j(I,)c(J,)h(E,)g(D,)g(etc.\))52 b(and)33 b(`len')i(is)e(an)h(in)m(teger)h(sp)s(ecifying)0 3653 y(the)g(maxim)m(um)g(length)h(of)f(the)h(v)m(ector)h(in)d(the)i (table.)56 b(The)35 b('P')g(t)m(yp)s(e)g(v)-5 b(ariable)36 b(length)g(columns)f(use)g(32-bit)0 3766 y(arra)m(y)j(length)h(and)e(b) m(yte)h(o\013set)h(v)-5 b(alues,)41 b(whereas)c(the)h('Q')g(t)m(yp)s(e) g(columns)g(use)f(64-bit)i(v)-5 b(alues,)41 b(whic)m(h)c(ma)m(y)0 3878 y(b)s(e)31 b(required)h(when)f(dealing)i(with)f(large)h(arra)m (ys.)46 b(CFITSIO)31 b(supp)s(orts)f(a)i(lo)s(cal)i(con)m(v)m(en)m (tion)g(that)f(in)m(terprets)0 3991 y(the)41 b('P')g(t)m(yp)s(e)g (descriptors)g(as)g(unsigned)e(32-bit)j(in)m(tegers,)j(whic)m(h)c(pro)m (vides)g(a)g(factor)g(of)g(2)h(greater)g(range)0 4104 y(for)32 b(the)g(arra)m(y)h(length)g(or)f(heap)g(address)f(than)h(is)g (p)s(ossible)g(with)g(32-bit)h('signed')g(in)m(tegers.)47 b(Note,)34 b(ho)m(w)m(ev)m(er,)0 4217 y(that)i(other)g(soft)m(w)m(are)g (pac)m(k)-5 b(ages)38 b(ma)m(y)d(not)h(supp)s(ort)e(this)h(con)m(v)m (en)m(tion,)k(and)c(ma)m(y)h(b)s(e)e(unable)h(to)h(read)f(thees)0 4330 y(extended)30 b(range)h(v)-5 b(ariable)31 b(length)g(records.)0 4490 y(If)d(the)h(v)-5 b(alue)30 b(of)f(`len')g(is)g(not)g(sp)s (eci\014ed)f(when)g(the)h(table)h(is)e(created)i(\(e.g.,)h(if)e(the)g (TF)m(ORM)g(k)m(eyw)m(ord)h(v)-5 b(alue)29 b(is)0 4603 y(simply)j(sp)s(eci\014ed)f(as)h('1PE')h(instead)g(of)f('1PE\(400\))i (\),)g(then)d(CFITSIO)g(will)h(automatically)j(scan)e(the)f(table)0 4716 y(when)27 b(it)j(is)e(closed)h(to)h(determine)e(the)h(maxim)m(um)f (length)h(of)g(the)f(v)m(ector)j(and)c(will)i(app)s(end)e(this)i(v)-5 b(alue)29 b(to)g(the)0 4829 y(TF)m(ORMn)h(v)-5 b(alue.)0 4989 y(The)29 b(same)h(routines)g(that)g(read)f(and)g(write)h(data)g (in)g(an)f(ordinary)g(\014xed)g(length)h(binary)f(table)h(extension)h (are)0 5102 y(also)41 b(used)d(for)i(v)-5 b(ariable)40 b(length)g(\014elds,)h(ho)m(w)m(ev)m(er,)j(the)c(routine)f(parameters)h (tak)m(e)h(on)f(a)g(sligh)m(tly)g(di\013eren)m(t)0 5215 y(in)m(terpretation)32 b(as)e(describ)s(ed)g(b)s(elo)m(w.)0 5375 y(All)37 b(the)f(data)h(in)f(a)h(v)-5 b(ariable)37 b(length)f(\014eld)g(is)g(written)h(in)m(to)g(an)f(area)h(called)h(the) e(`heap')g(whic)m(h)g(follo)m(ws)i(the)0 5488 y(main)31 b(\014xed-length)h(FITS)e(binary)h(table.)44 b(The)31 b(size)h(of)f(the)h(heap,)f(in)g(b)m(ytes,)h(is)g(sp)s(eci\014ed)e(b)m (y)h(the)h(PCOUNT)0 5601 y(k)m(eyw)m(ord)21 b(in)f(the)h(FITS)f (header.)37 b(When)20 b(creating)i(a)f(new)f(binary)g(table,)j(the)e (initial)h(v)-5 b(alue)21 b(of)f(PCOUNT)g(should)0 5714 y(usually)27 b(b)s(e)h(set)g(to)g(zero.)41 b(CFITSIO)26 b(will)i(recompute)g(the)g(size)g(of)g(the)g(heap)g(as)g(the)g(data)g (is)g(written)f(and)h(will)p eop end %%Page: 26 34 TeXDict begin 26 33 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.26) cvn H.B /DEST pdfmark end 0 299 a Fj(26)1763 b Fh(CHAPTER)29 b(4.)112 b(PR)m(OGRAMMING)32 b(GUIDELINES)0 555 y Fj(automatically)c (up)s(date)c(the)i(PCOUNT)e(k)m(eyw)m(ord)h(v)-5 b(alue)26 b(when)e(the)h(table)h(is)f(closed.)40 b(When)25 b(writing)g(v)-5 b(ariable)0 668 y(length)34 b(data)g(to)g(a)g(table,)i(CFITSIO)c(will)h (automatically)k(extend)c(the)h(size)g(of)g(the)g(heap)f(area)h(if)g (necessary)-8 b(,)0 781 y(so)31 b(that)g(an)m(y)f(follo)m(wing)i(HDUs)f (do)f(not)h(get)h(o)m(v)m(erwritten.)0 941 y(By)e(default)f(the)h(heap) f(data)i(area)f(starts)g(immediately)h(after)f(the)f(last)i(ro)m(w)e (of)h(the)g(\014xed-length)f(table.)42 b(This)0 1054 y(default)27 b(starting)g(lo)s(cation)i(ma)m(y)e(b)s(e)f(o)m(v)m (erridden)h(b)m(y)g(the)g(THEAP)f(k)m(eyw)m(ord,)i(but)f(this)f(is)h (not)g(recommended.)0 1167 y(If)34 b(additional)h(ro)m(ws)f(of)g(data)h (are)g(added)e(to)i(the)f(table,)j(CFITSIO)32 b(will)j(automatically)i (shift)c(the)i(the)f(heap)0 1280 y(do)m(wn)g(to)i(mak)m(e)f(ro)s(om)g (for)f(the)h(new)f(ro)m(ws,)i(but)e(it)i(is)e(ob)m(viously)i(b)s(e)e (more)h(e\016cien)m(t)h(to)f(initially)h(create)h(the)0 1393 y(table)31 b(with)e(the)h(necessary)g(n)m(um)m(b)s(er)f(of)h (blank)f(ro)m(ws,)h(so)g(that)g(the)g(heap)g(do)s(es)f(not)h(needed)g (to)g(b)s(e)f(constan)m(tly)0 1506 y(mo)m(v)m(ed.)0 1666 y(When)36 b(writing)g(ro)m(w)g(of)h(data)f(to)h(a)g(v)-5 b(ariable)37 b(length)f(\014eld)g(the)g(en)m(tire)i(arra)m(y)e(of)g(v) -5 b(alues)37 b(for)f(a)g(giv)m(en)i(ro)m(w)e(of)0 1779 y(the)30 b(table)h(m)m(ust)e(b)s(e)h(written)g(with)f(a)h(single)h (call)g(to)f(\014ts)p 1986 1779 28 4 v 33 w(write)p 2221 1779 V 33 w(col.)42 b(The)29 b(total)i(length)g(of)f(the)g(arra)m(y)g (is)g(giv)m(en)0 1892 y(b)m(y)j(nelemen)m(ts)h(+)f(\014rstelem)g(-)g (1.)49 b(Additional)34 b(elemen)m(ts)h(cannot)e(b)s(e)g(app)s(ended)e (to)j(an)f(existing)h(v)m(ector)h(at)f(a)0 2005 y(later)c(time)g(since) g(an)m(y)g(attempt)g(to)g(do)g(so)f(will)h(simply)f(o)m(v)m(erwrite)i (all)f(the)f(previously)h(written)f(data)h(and)f(the)0 2118 y(new)36 b(data)h(will)g(b)s(e)f(written)g(to)h(a)g(new)f(area)h (of)g(the)g(heap.)58 b(The)36 b(\014ts)p 2496 2118 V 33 w(compress)p 2889 2118 V 32 w(heap)g(routine)h(is)f(pro)m(vided)0 2230 y(to)h(compress)g(the)g(heap)g(and)f(reco)m(v)m(er)i(an)m(y)f(un)m (used)f(space.)60 b(T)-8 b(o)37 b(a)m(v)m(oid)i(ha)m(ving)e(to)h(deal)f (with)f(this)h(issue,)h(it)0 2343 y(is)31 b(recommended)h(that)g(ro)m (ws)f(in)g(a)h(v)-5 b(ariable)32 b(length)g(\014eld)f(should)f(only)i (b)s(e)f(written)g(once.)45 b(An)31 b(exception)h(to)0 2456 y(this)e(general)h(rule)f(o)s(ccurs)g(when)f(setting)i(elemen)m (ts)h(of)e(an)g(arra)m(y)g(as)h(unde\014ned.)38 b(It)30 b(is)h(allo)m(w)m(ed)h(to)e(\014rst)g(write)0 2569 y(a)e(dumm)m(y)f(v) -5 b(alue)28 b(in)m(to)h(the)f(arra)m(y)h(with)e(\014ts)p 1534 2569 V 33 w(write)p 1769 2569 V 33 w(col,)j(and)d(then)g(call)j (\014ts)p 2632 2569 V 32 w(write)p 2866 2569 V 33 w(col)p 3009 2569 V 34 w(n)m(ul)d(to)i(\015ag)f(the)g(desired)0 2682 y(elemen)m(ts)h(as)f(unde\014ned.)38 b(Note)29 b(that)g(the)f(ro)m (ws)g(of)g(a)g(table,)i(whether)d(\014xed)g(or)h(v)-5 b(ariable)29 b(length,)g(do)f(not)g(ha)m(v)m(e)0 2795 y(to)j(b)s(e)f(written)g(consecutiv)m(ely)j(and)d(ma)m(y)h(b)s(e)e (written)i(in)f(an)m(y)h(order.)0 2955 y(When)40 b(writing)h(to)g(a)g (v)-5 b(ariable)41 b(length)g(ASCI)s(I)e(c)m(haracter)j(\014eld)e (\(e.g.,)45 b(TF)m(ORM)c(=)f('1P)-8 b(A'\))43 b(only)d(a)h(single)0 3068 y(c)m(haracter)22 b(string)e(can)h(b)s(e)e(written.)38 b(The)20 b(`\014rstelem')g(and)g(`nelemen)m(ts')i(parameter)e(v)-5 b(alues)21 b(in)f(the)g(\014ts)p 3526 3068 V 33 w(write)p 3761 3068 V 33 w(col)0 3181 y(routine)35 b(are)h(ignored)f(and)f(the)i (n)m(um)m(b)s(er)d(of)j(c)m(haracters)g(to)g(write)f(is)h(simply)e (determined)h(b)m(y)g(the)g(length)h(of)0 3294 y(the)31 b(input)e(n)m(ull-terminated)i(c)m(haracter)h(string.)0 3454 y(The)21 b(\014ts)p 305 3454 V 33 w(write)p 540 3454 V 33 w(descript)g(routine)h(is)f(useful)g(in)g(situations)i(where) e(m)m(ultiple)h(ro)m(ws)g(of)g(a)g(v)-5 b(ariable)22 b(length)g(column)0 3567 y(ha)m(v)m(e)32 b(the)e(iden)m(tical)i(arra)m (y)f(of)g(v)-5 b(alues.)41 b(One)30 b(can)g(simply)g(write)h(the)f (arra)m(y)h(once)g(for)g(the)f(\014rst)g(ro)m(w,)g(and)g(then)0 3680 y(use)c(\014ts)p 280 3680 V 32 w(write)p 514 3680 V 33 w(descript)g(to)g(write)g(the)g(same)h(descriptor)e(v)-5 b(alues)27 b(in)m(to)g(the)f(other)g(ro)m(ws;)h(all)g(the)f(ro)m(ws)g (will)g(then)0 3793 y(p)s(oin)m(t)k(to)h(the)g(same)g(storage)h(lo)s (cation)g(th)m(us)e(sa)m(ving)h(disk)f(space.)0 3953 y(When)35 b(reading)g(from)f(a)i(v)-5 b(ariable)35 b(length)h(arra)m(y) f(\014eld)g(one)g(can)g(only)h(read)e(as)i(man)m(y)f(elemen)m(ts)h(as)f (actually)0 4066 y(exist)i(in)e(that)i(ro)m(w)e(of)h(the)g(table;)k (reading)c(do)s(es)g(not)g(automatically)i(con)m(tin)m(ue)f(with)f(the) g(next)g(ro)m(w)g(of)g(the)0 4179 y(table)29 b(as)f(o)s(ccurs)g(when)f (reading)h(an)g(ordinary)g(\014xed)f(length)h(table)h(\014eld.)40 b(A)m(ttempts)29 b(to)g(read)f(more)g(than)g(this)0 4292 y(will)k(cause)h(an)e(error)h(status)g(to)g(b)s(e)f(returned.)44 b(One)32 b(can)g(determine)g(the)g(n)m(um)m(b)s(er)e(of)i(elemen)m(ts)h (in)f(eac)m(h)h(ro)m(w)0 4405 y(of)e(a)f(v)-5 b(ariable)31 b(column)g(with)f(the)g(\014ts)p 1329 4405 V 33 w(read)p 1534 4405 V 32 w(descript)h(routine.)0 4556 y SDict begin H.S end 0 4556 a 0 4556 a SDict begin 13.6 H.A end 0 4556 a 0 4556 a SDict begin [ /View [/XYZ H.V] /Dest (section.4.11) cvn H.B /DEST pdfmark end 0 4556 a 179 x Ff(4.11)136 b(Multiple)45 b(Access)g(to)g(the)g(Same)h(FITS)d(File)0 4986 y Fj(CFITSIO)29 b(supp)s(orts)g(sim)m(ultaneous)i(read)f(and)g (write)h(access)h(to)f(di\013eren)m(t)g(HDUs)g(in)f(the)h(same)g(FITS)f (\014le)g(in)0 5099 y(some)h(circumstances,)g(as)g(describ)s(ed)e(b)s (elo)m(w:)136 5341 y Fc(\017)46 b Fj(Multi-threaded)31 b(programs)227 5488 y(When)f(CFITSIO)f(is)h(compiled)h(with)e(the)i(-D) p 1842 5488 28 4 v 33 w(REENTRANT)f(directiv)m(e)h(\(as)g(can)f(b)s(e)g (tested)h(with)f(the)227 5601 y(\014ts)p 354 5601 V 33 w(is)p 448 5601 V 33 w(reen)m(tran)m(t)38 b(function\))f(di\013eren)m (t)h(threads)f(can)g(call)i(an)m(y)e(of)h(the)f(CFITSIO)f(routines)h (to)h(sim)m(ul-)227 5714 y(taneously)g(read)g(or)f(write)h(separate)h (FITS)d(\014les.)62 b(Multiple)39 b(threads)e(can)h(also)g(read)f(data) i(from)e(the)p eop end %%Page: 27 35 TeXDict begin 27 34 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.27) cvn H.B /DEST pdfmark end 0 299 a Fh(4.12.)73 b(WHEN)31 b(THE)f(FINAL)g (SIZE)f(OF)i(THE)f(FITS)f(HDU)i(IS)f(UNKNO)m(WN)978 b Fj(27)227 555 y(same)32 b(FITS)f(\014le)g(sim)m(ultaneously)-8 b(,)33 b(as)f(long)g(as)f(the)h(\014le)f(w)m(as)h(op)s(ened)f(indep)s (enden)m(tly)f(b)m(y)h(eac)m(h)i(thread.)227 668 y(This)g(relies)h(on)g (the)f(op)s(erating)h(system)g(to)g(correctly)h(deal)g(with)e(reading)g (the)h(same)g(\014le)g(b)m(y)f(m)m(ultiple)227 781 y(pro)s(cesses.)64 b(Di\013eren)m(t)40 b(threads)e(should)f(not)i(share)f(the)g(same)h ('\014ts\014le')f(p)s(oin)m(ter)g(to)h(read)g(an)f(op)s(ened)227 894 y(FITS)25 b(\014le,)i(unless)e(lo)s(c)m(ks)h(are)g(placed)g(around) e(the)i(calls)g(to)g(the)g(CFITSIO)e(reading)i(routines.)39 b(Di\013eren)m(t)227 1007 y(threads)30 b(should)g(nev)m(er)g(try)h(to)g (write)f(to)h(the)g(same)g(FITS)e(\014le.)136 1203 y Fc(\017)46 b Fj(Multiple)31 b(read)g(access)g(to)h(the)e(same)h(FITS)e (\014le)i(within)f(a)h(single)g(program/thread)227 1357 y(A)46 b(single)g(pro)s(cess)f(ma)m(y)h(op)s(en)f(the)g(same)h(FITS)f (\014le)g(with)g(READONL)-8 b(Y)46 b(access)h(m)m(ultiple)f(times,)227 1470 y(and)32 b(th)m(us)f(create)j(m)m(ultiple)f('\014ts\014le*')g(p)s (oin)m(ters)f(to)g(that)h(same)g(\014le)f(within)f(CFITSIO.)g(This)g (relies)i(on)227 1583 y(the)h(op)s(erating)g(system's)g(abilit)m(y)h (to)g(op)s(en)e(a)h(single)g(\014le)g(m)m(ultiple)g(times)g(and)f (correctly)i(manage)g(the)227 1696 y(subsequen)m(t)24 b(read)g(requests)g(directed)g(to)h(the)f(di\013eren)m(t)h(C)f ('\014le*')h(p)s(oin)m(ters,)g(whic)m(h)f(actually)i(all)f(p)s(oin)m(t) f(to)227 1809 y(the)32 b(same)h(\014le.)45 b(CFITSIO)30 b(simply)i(executes)h(the)f(read)g(requests)g(to)g(the)g(di\013ernet)g ('\014ts\014le*')h(p)s(oin)m(ters)227 1922 y(the)e(same)g(as)f(if)h (they)f(w)m(ere)h(ph)m(ysically)g(di\013eren)m(t)g(\014les.)136 2118 y Fc(\017)46 b Fj(Multiple)31 b(write)g(access)h(to)f(the)f(same)h (FITS)f(\014le)g(within)g(a)h(single)g(program/thread)227 2272 y(CFITSIO)22 b(supp)s(orts)g(op)s(ening)h(the)g(same)h(FITS)f (\014le)g(m)m(ultiple)i(times)f(with)f(WRITE)g(access,)j(but)d(it)h (only)227 2385 y(ph)m(ysically)j(op)s(ens)f(the)g(\014le)h(\(at)g(the)g (op)s(erating)f(system)h(lev)m(el\))h(once,)g(on)e(the)h(\014rst)e (call)j(to)f(\014ts)p 3509 2385 28 4 v 32 w(op)s(en)p 3731 2385 V 33 w(\014le.)227 2498 y(If)38 b(\014ts)p 453 2498 V 32 w(op)s(en)p 675 2498 V 32 w(\014le)g(is)g(subsequen)m (tly)f(called)i(to)g(op)s(en)e(the)h(same)g(\014le)g(again,)j(CFITSIO) 36 b(will)i(recognize)227 2611 y(that)c(the)f(\014le)g(is)g(already)g (op)s(en,)h(and)e(will)h(return)f(a)h(new)g('\014ts\014le*')g(p)s(oin)m (ter)g(that)h(logically)h(p)s(oin)m(ts)e(to)227 2724 y(the)i(\014rst)e('\014ts\014le*')i(p)s(oin)m(ter,)h(without)e (actually)i(op)s(ening)e(the)g(\014le)h(a)f(second)h(time.)53 b(The)34 b(application)227 2837 y(program)39 b(can)g(then)g(treat)h (the)f(2)g('\014ts\014le*')h(p)s(oin)m(ters)f(as)g(if)g(they)g(p)s(oin) m(t)g(to)h(di\013eren)m(t)f(\014les,)i(and)e(can)227 2950 y(seemingly)c(mo)m(v)m(e)g(to)g(and)e(write)h(data)h(to)g(2)f (di\013eren)m(t)g(HDUs)h(within)e(the)h(same)g(\014le.)52 b(Ho)m(w)m(ev)m(er,)37 b(eac)m(h)227 3063 y(time)31 b(the)g (application)g(program)g(switc)m(hes)g(whic)m(h)f('\014ts\014le*')h(p)s (oin)m(ter)f(it)h(is)f(writing)h(to,)g(CFITSIO)e(will)227 3176 y(\015ush)24 b(an)m(y)i(in)m(ternal)g(bu\013ers)e(that)i(con)m (tain)h(data)f(written)g(to)g(the)g(\014rst)e('\014ts\014le*')i(p)s (oin)m(ter,)h(then)e(mo)m(v)m(e)i(to)227 3288 y(the)j(HDU)g(that)g(the) g(other)f('\014ts\014le*')h(p)s(oin)m(ter)g(is)f(writing)h(to.)41 b(Ob)m(viously)-8 b(,)30 b(this)f(ma)m(y)h(add)f(a)h(signi\014can)m(t) 227 3401 y(amoun)m(t)h(of)f(computational)i(o)m(v)m(erhead)f(if)f(the)g (application)h(program)f(uses)g(this)g(feature)g(to)h(frequen)m(tly)227 3514 y(switc)m(h)25 b(bac)m(k)h(and)e(forth)g(b)s(et)m(w)m(een)i (writing)f(to)g(2)g(\(or)g(more\))g(HDUs)h(in)e(the)h(same)g(\014le,)h (so)f(this)g(capabilit)m(y)227 3627 y(should)30 b(b)s(e)f(used)h (judiciously)-8 b(.)227 3782 y(Note)26 b(that)f(CFITSIO)e(will)i(not)g (allo)m(w)h(a)e(FITS)g(\014le)h(to)g(b)s(e)f(op)s(ened)g(a)g(second)h (time)g(with)f(READ)m(WRITE)227 3895 y(access)32 b(if)e(it)h(w)m(as)g (op)s(ened)f(previously)g(with)g(READONL)-8 b(Y)31 b(access.)0 4059 y SDict begin H.S end 0 4059 a 0 4059 a SDict begin 13.6 H.A end 0 4059 a 0 4059 a SDict begin [ /View [/XYZ H.V] /Dest (section.4.12) cvn H.B /DEST pdfmark end 0 4059 a 179 x Ff(4.12)136 b(When)44 b(the)h(Final)h(Size)f(of)g(the)g(FITS)f(HDU)h (is)g(Unkno)l(wn)0 4490 y Fj(It)27 b(is)h(not)f(required)f(to)i(kno)m (w)f(the)h(total)h(size)f(of)f(a)h(FITS)e(data)i(arra)m(y)g(or)f(table) h(b)s(efore)f(b)s(eginning)f(to)i(write)g(the)0 4603 y(data)k(to)f(the)g(FITS)f(\014le.)43 b(In)30 b(the)h(case)h(of)f(the)g (primary)f(arra)m(y)h(or)g(an)f(image)j(extension,)e(one)h(should)d (initially)0 4716 y(create)i(the)e(arra)m(y)h(with)e(the)i(size)g(of)f (the)g(highest)g(dimension)g(\(largest)i(NAXISn)d(k)m(eyw)m(ord\))i (set)g(to)g(a)f(dumm)m(y)0 4829 y(v)-5 b(alue,)26 b(suc)m(h)e(as)g(1.) 39 b(Then)23 b(after)i(all)g(the)g(data)f(ha)m(v)m(e)i(b)s(een)d (written)h(and)g(the)g(true)g(dimensions)g(are)g(kno)m(wn,)h(then)0 4942 y(the)33 b(NAXISn)f(v)-5 b(alue)33 b(should)f(b)s(e)g(up)s(dated)g (using)g(the)h(\014ts)p 2069 4942 28 4 v 33 w(up)s(date)p 2378 4942 V 32 w(k)m(ey)g(routine)g(b)s(efore)g(mo)m(ving)g(to)h (another)0 5055 y(extension)d(or)f(closing)i(the)e(FITS)g(\014le.)0 5215 y(When)f(writing)g(to)g(FITS)g(tables,)h(CFITSIO)d(automatically) 32 b(k)m(eeps)e(trac)m(k)g(of)f(the)g(highest)h(ro)m(w)f(n)m(um)m(b)s (er)e(that)0 5328 y(is)32 b(written)g(to,)h(and)e(will)h(increase)h (the)f(size)h(of)f(the)g(table)g(if)g(necessary)-8 b(.)46 b(CFITSIO)30 b(will)i(also)h(automatically)0 5441 y(insert)j(space)h (in)f(the)g(FITS)f(\014le)i(if)f(necessary)-8 b(,)39 b(to)e(ensure)e(that)i(the)f(data)h('heap',)h(if)e(it)h(exists,)h (and/or)f(an)m(y)0 5554 y(additional)29 b(HDUs)g(that)g(follo)m(w)g (the)g(table)g(do)f(not)h(get)g(o)m(v)m(erwritten)h(as)e(new)g(ro)m(ws) g(are)h(written)f(to)h(the)g(table.)0 5714 y(As)37 b(a)h(general)g (rule)f(it)h(is)f(b)s(est)g(to)h(sp)s(ecify)f(the)h(initial)g(n)m(um)m (b)s(er)e(of)i(ro)m(ws)f(=)g(0)g(when)g(the)g(table)h(is)g(created,)p eop end %%Page: 28 36 TeXDict begin 28 35 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.28) cvn H.B /DEST pdfmark end 0 299 a Fj(28)1763 b Fh(CHAPTER)29 b(4.)112 b(PR)m(OGRAMMING)32 b(GUIDELINES)0 555 y Fj(then)38 b(let)h(CFITSIO)e(k)m(eep)i(trac)m(k)g(of)g(the)f(n)m(um)m(b)s(er)f(of) i(ro)m(ws)f(that)h(are)f(actually)i(written.)65 b(The)38 b(application)0 668 y(program)e(should)f(not)i(man)m(ually)g(up)s(date) e(the)i(n)m(um)m(b)s(er)e(of)h(ro)m(ws)g(in)g(the)h(table)g(\(as)g(giv) m(en)g(b)m(y)f(the)h(NAXIS2)0 781 y(k)m(eyw)m(ord\))j(since)f(CFITSIO)e (do)s(es)i(this)g(automatically)-8 b(.)69 b(If)38 b(a)i(table)f(is)g (initially)i(created)f(with)e(more)h(than)0 894 y(zero)i(ro)m(ws,)j (then)c(this)h(will)f(usually)h(b)s(e)f(considered)g(as)h(the)g(minim)m (um)f(size)h(of)g(the)g(table,)j(ev)m(en)d(if)g(few)m(er)0 1007 y(ro)m(ws)30 b(are)g(actually)h(written)f(to)h(the)f(table.)41 b(Th)m(us,)30 b(if)f(a)i(table)f(is)g(initially)h(created)g(with)f (NAXIS2)g(=)g(20,)h(and)0 1120 y(CFITSIO)g(only)i(writes)f(10)i(ro)m (ws)e(of)h(data)g(b)s(efore)f(closing)i(the)f(table,)h(then)e(NAXIS2)h (will)g(remain)f(equal)h(to)0 1233 y(20.)50 b(If)33 b(ho)m(w)m(ev)m (er,)i(30)g(ro)m(ws)e(of)g(data)h(are)g(written)f(to)h(this)f(table,)i (then)e(NAXIS2)h(will)f(b)s(e)g(increased)g(from)g(20)0 1346 y(to)f(30.)44 b(The)31 b(one)g(exception)i(to)f(this)f(automatic)i (up)s(dating)d(of)h(the)h(NAXIS2)f(k)m(eyw)m(ord)h(is)f(if)g(the)h (application)0 1458 y(program)c(directly)g(mo)s(di\014es)f(the)i(v)-5 b(alue)28 b(of)g(NAXIS2)g(\(up)f(or)h(do)m(wn\))g(itself)h(just)e(b)s (efore)h(closing)h(the)f(table.)41 b(In)0 1571 y(this)28 b(case,)i(CFITSIO)d(do)s(es)h(not)h(up)s(date)e(NAXIS2)i(again,)h (since)f(it)g(assumes)f(that)h(the)f(application)i(program)0 1684 y(m)m(ust)i(ha)m(v)m(e)h(had)f(a)g(go)s(o)s(d)g(reason)h(for)f(c)m (hanging)h(the)f(v)-5 b(alue)33 b(directly)-8 b(.)47 b(This)31 b(is)h(not)h(recommended,)f(ho)m(w)m(ev)m(er,)0 1797 y(and)j(is)h(only)g(pro)m(vided)g(for)f(bac)m(kw)m(ard)h (compatibilit)m(y)i(with)e(soft)m(w)m(are)h(that)g(initially)g(creates) g(a)f(table)h(with)0 1910 y(a)d(large)h(n)m(um)m(b)s(er)e(of)h(ro)m (ws,)h(than)f(decreases)g(the)h(NAXIS2)f(v)-5 b(alue)34 b(to)h(the)f(actual)h(smaller)g(v)-5 b(alue)34 b(just)f(b)s(efore)0 2023 y(closing)e(the)g(table.)0 2228 y SDict begin H.S end 0 2228 a 0 2228 a SDict begin 13.6 H.A end 0 2228 a 0 2228 a SDict begin [ /View [/XYZ H.V] /Dest (section.4.13) cvn H.B /DEST pdfmark end 0 2228 a 179 x Ff(4.13)136 b(CFITSIO)44 b(Size)h(Limitations)0 2668 y Fj(CFITSIO)29 b(places)j(v)m(ery)f(few)g (restrictions)g(on)g(the)g(size)g(of)g(FITS)f(\014les)h(that)g(it)h (reads)e(or)h(writes.)42 b(There)30 b(are)i(a)0 2781 y(few)e(limits,)h(ho)m(w)m(ev)m(er,)h(that)f(ma)m(y)g(a\013ect)h(some)f (extreme)g(cases:)0 2941 y(1.)43 b(The)31 b(maxim)m(um)g(n)m(um)m(b)s (er)f(of)h(FITS)f(\014les)h(that)h(ma)m(y)g(b)s(e)e(sim)m(ultaneously)i (op)s(ened)f(b)m(y)g(CFITSIO)e(is)i(set)h(b)m(y)0 3054 y(NMAXFILES,)e(as)f(de\014ned)f(in)h(\014tsio2.h.)41 b(The)29 b(curren)m(t)g(default)g(v)-5 b(alue)30 b(is)f(1000,)j(but)c (this)h(ma)m(y)h(b)s(e)f(increased)0 3167 y(if)40 b(necessary)-8 b(.)72 b(Note)42 b(that)f(CFITSIO)e(allo)s(cates)j(NIOBUF)f(*)g(2880)h (b)m(ytes)f(of)g(I/O)f(bu\013er)g(space)h(for)f(eac)m(h)0 3279 y(\014le)d(that)h(is)f(op)s(ened.)61 b(The)37 b(default)g(v)-5 b(alue)38 b(of)f(NIOBUF)h(is)f(40)h(\(de\014ned)f(in)f(\014tsio.h\),)k (so)e(this)f(amoun)m(ts)g(to)0 3392 y(more)31 b(than)g(115K)i(of)e (memory)g(for)g(eac)m(h)i(op)s(ened)d(\014le)i(\(or)f(115)i(MB)f(for)f (1000)i(op)s(ened)d(\014les\).)44 b(Note)33 b(that)f(the)0 3505 y(underlying)k(op)s(erating)i(system,)h(ma)m(y)e(ha)m(v)m(e)i(a)e (lo)m(w)m(er)i(limit)f(on)f(the)g(n)m(um)m(b)s(er)f(of)h(\014les)g (that)h(can)f(b)s(e)g(op)s(ened)0 3618 y(sim)m(ultaneously)-8 b(.)0 3778 y(2.)67 b(It)40 b(used)e(to)i(b)s(e)e(common)i(for)f (computer)g(systems)g(to)h(only)f(supp)s(ort)f(disk)g(\014les)h(up)f (to)i(2**31)i(b)m(ytes)d(=)0 3891 y(2.1)k(GB)g(in)f(size,)47 b(but)41 b(most)i(systems)f(no)m(w)g(supp)s(ort)f(larger)i(\014les.)76 b(CFITSIO)41 b(can)i(optionally)g(read)g(and)0 4004 y(write)37 b(these)h(so-called)h('large)f(\014les')g(that)f(are)h(greater)g(than)f (2.1)h(GB)g(on)f(platforms)g(where)g(they)g(are)h(sup-)0 4117 y(p)s(orted,)43 b(but)d(this)g(usually)h(requires)f(that)i(sp)s (ecial)f(compiler)g(option)g(\015ags)g(b)s(e)f(sp)s(eci\014ed)g(to)i (turn)d(on)i(this)0 4230 y(option.)69 b(On)39 b(lin)m(ux)h(and)f (solaris)i(systems)f(the)g(compiler)g(\015ags)g(are)g('-D)p 2617 4230 28 4 v 34 w(LAR)m(GEFILE)p 3184 4230 V 33 w(SOUR)m(CE')f(and) g(`-)0 4343 y(D)p 74 4343 V 33 w(FILE)p 318 4343 V 33 w(OFFSET)p 719 4343 V 32 w(BITS=64'.)i(These)29 b(\015ags)h(ma)m(y)g (also)h(w)m(ork)f(on)g(other)g(platforms)f(but)g(this)h(has)g(not)g(b)s (een)0 4456 y(tested.)43 b(Starting)31 b(with)f(v)m(ersion)h(3.0)h(of)f (CFITSIO,)f(the)h(default)f(Mak)m(e\014le)j(that)e(is)g(distributed)f (with)g(CFIT-)0 4569 y(SIO)h(will)h(include)g(these)g(2)g(compiler)h (\015ags)f(when)e(building)h(on)h(Solaris)g(and)g(Lin)m(ux)f(PC)g (systems.)45 b(Users)32 b(on)0 4682 y(other)g(platforms)g(will)g(need)f (to)i(add)e(these)h(compiler)h(\015ags)f(man)m(ually)g(if)g(they)g(w)m (an)m(t)g(to)h(supp)s(ort)d(large)j(\014les.)0 4795 y(In)j(most)i (cases)g(it)g(app)s(ears)e(that)i(it)g(is)f(not)h(necessary)f(to)h (include)f(these)h(compiler)g(\015ags)f(when)f(compiling)0 4907 y(application)c(co)s(de)e(that)h(call)h(the)e(CFITSIO)f(library)h (routines.)0 5068 y(When)i(CFITSIO)e(is)i(built)g(with)g(large)h (\014le)f(supp)s(ort)e(\(e.g.,)35 b(on)d(Solaris)g(and)f(Lin)m(ux)h(PC) f(system)h(b)m(y)g(default\))0 5181 y(then)e(it)h(can)g(read)f(and)g (write)g(FITS)g(data)h(\014les)f(on)h(disk)e(that)i(ha)m(v)m(e)h(an)m (y)f(of)f(these)h(conditions:)136 5483 y Fc(\017)46 b Fj(FITS)30 b(\014les)g(larger)h(than)f(2.1)i(GB)f(in)f(size)136 5714 y Fc(\017)46 b Fj(FITS)30 b(images)h(con)m(taining)h(greater)g (than)e(2.1)h(G)g(pixels)p eop end %%Page: 29 37 TeXDict begin 29 36 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.29) cvn H.B /DEST pdfmark end 0 299 a Fh(4.13.)73 b(CFITSIO)28 b(SIZE)h(LIMIT)-8 b(A)g(TIONS)2300 b Fj(29)136 555 y Fc(\017)46 b Fj(FITS)34 b(images)i(that)g(ha)m(v)m(e)g(one)f(dimension) f(with)g(more)h(than)g(2.1)h(G)f(pixels)g(\(as)g(giv)m(en)h(b)m(y)f (one)g(of)g(the)227 668 y(NAXISn)30 b(k)m(eyw)m(ord\))136 856 y Fc(\017)46 b Fj(FITS)26 b(tables)h(con)m(taining)g(more)g(than)f (2.1E09)i(ro)m(ws)e(\(giv)m(en)i(b)m(y)e(the)g(NAXIS2)h(k)m(eyw)m (ord\),)h(or)e(with)g(ro)m(ws)227 969 y(that)31 b(are)g(more)g(than)f (2.1)h(GB)g(wide)f(\(giv)m(en)i(b)m(y)e(the)h(NAXIS1)f(k)m(eyw)m(ord\)) 136 1156 y Fc(\017)46 b Fj(FITS)36 b(binary)f(tables)i(with)f(a)h(v)-5 b(ariable-length)38 b(arra)m(y)f(heap)f(that)h(is)f(larger)h(than)f (2.1)h(GB)g(\(giv)m(en)h(b)m(y)227 1269 y(the)31 b(PCOUNT)e(k)m(eyw)m (ord\))0 1529 y(The)c(curren)m(t)g(maxim)m(um)g(FITS)f(\014le)h(size)h (supp)s(orted)e(b)m(y)h(CFITSIO)e(is)j(ab)s(out)f(6)g(terab)m(ytes)i (\(con)m(taining)g(2**31)0 1642 y(FITS)d(blo)s(c)m(ks,)i(eac)m(h)g (2880)h(b)m(ytes)e(in)f(size\).)40 b(Curren)m(tly)-8 b(,)26 b(supp)s(ort)d(for)i(large)g(\014les)g(in)g(CFITSIO)e(has)h(b)s (een)g(tested)0 1755 y(on)30 b(the)h(Lin)m(ux,)f(Solaris,)h(and)f(IBM)g (AIX)h(op)s(erating)g(systems.)0 1915 y(Note)26 b(that)f(when)e (writing)h(application)i(programs)e(that)h(are)f(in)m(tended)g(to)h (supp)s(ort)e(large)i(\014les)g(it)f(is)h(imp)s(ortan)m(t)0 2028 y(to)31 b(use)g(64-bit)g(in)m(teger)h(v)-5 b(ariables)31 b(to)h(store)f(quan)m(tities)h(suc)m(h)e(as)h(the)f(dimensions)g(of)h (images,)h(or)f(the)f(n)m(um)m(b)s(er)0 2141 y(of)38 b(ro)m(ws)f(in)h(a)g(table.)63 b(These)38 b(programs)f(m)m(ust)g(also)i (call)g(the)f(sp)s(ecial)g(v)m(ersions)g(of)g(some)g(of)g(the)f (CFITSIO)0 2254 y(routines)28 b(that)h(ha)m(v)m(e)h(b)s(een)d(adapted)i (to)g(supp)s(ort)e(64-bit)i(in)m(tegers.)42 b(The)27 b(names)i(of)f(these)h(routines)f(end)g(in)g('ll')0 2367 y(\('el')k('el'\))g(to)f(distinguish)e(them)i(from)f(the)g(32-bit)i(in) m(teger)g(v)m(ersion)e(\(e.g.,)j(\014ts)p 2766 2367 28 4 v 32 w(get)p 2918 2367 V 34 w(n)m(um)p 3127 2367 V 32 w(ro)m(wsll\).)p eop end %%Page: 30 38 TeXDict begin 30 37 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.30) cvn H.B /DEST pdfmark end 0 299 a Fj(30)1763 b Fh(CHAPTER)29 b(4.)112 b(PR)m(OGRAMMING)32 b(GUIDELINES)p eop end %%Page: 31 39 TeXDict begin 31 38 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.31) cvn H.B /DEST pdfmark end 0 299 a 0 464 a SDict begin H.S end 0 464 a 0 464 a SDict begin 13.6 H.A end 0 464 a 0 464 a SDict begin [ /View [/XYZ H.V] /Dest (chapter.5) cvn H.B /DEST pdfmark end 0 464 a 761 x Fg(Chapter)65 b(5)0 1687 y Fm(Basic)77 b(CFITSIO)f(In)-6 b(terface)77 b(Routines)0 2180 y Fj(This)30 b(c)m(hapter)i(describ)s(es)e(the)i(basic)f(routines) g(in)g(the)g(CFITSIO)e(user)i(in)m(terface)h(that)g(pro)m(vide)f(all)h (the)g(func-)0 2293 y(tions)j(normally)g(needed)g(to)g(read)g(and)f (write)h(most)h(FITS)e(\014les.)54 b(It)35 b(is)g(recommended)f(that)i (these)f(routines)0 2406 y(b)s(e)d(used)g(for)g(most)h(applications)h (and)e(that)h(the)f(more)h(adv)-5 b(anced)33 b(routines)f(describ)s(ed) g(in)g(the)h(next)f(c)m(hapter)0 2518 y(only)e(b)s(e)g(used)g(in)g(sp)s (ecial)h(circumstances)g(when)e(necessary)-8 b(.)0 2679 y(The)30 b(follo)m(wing)i(con)m(v)m(en)m(tions)g(are)f(used)e(in)i (this)f(c)m(hapter)h(in)f(the)g(description)h(of)f(eac)m(h)i(function:) 0 2839 y(1.)39 b(Most)25 b(functions)e(ha)m(v)m(e)i(2)f(names:)37 b(a)24 b(long)h(descriptiv)m(e)f(name)g(and)f(a)i(short)e(concise)i (name.)38 b(Both)25 b(names)f(are)0 2952 y(listed)g(on)f(the)g(\014rst) f(line)i(of)f(the)h(follo)m(wing)g(descriptions,)h(separated)e(b)m(y)h (a)f(slash)g(\(/\))h(c)m(haracter.)40 b(Programmers)0 3065 y(ma)m(y)27 b(use)g(either)g(name)g(in)f(their)h(programs)g(but)f (the)h(long)g(names)g(are)g(recommended)f(to)i(help)e(do)s(cumen)m(t)h (the)0 3177 y(co)s(de)k(and)e(mak)m(e)j(it)f(easier)g(to)g(read.)0 3338 y(2.)42 b(A)30 b(righ)m(t)h(arro)m(w)g(sym)m(b)s(ol)f(\()p Fb(>)p Fj(\))h(is)g(used)f(in)g(the)h(function)f(descriptions)g(to)i (separate)f(the)g(input)f(parameters)0 3451 y(from)j(the)g(output)f (parameters)i(in)f(the)g(de\014nition)g(of)g(eac)m(h)h(routine.)49 b(This)32 b(sym)m(b)s(ol)h(is)g(not)g(actually)i(part)e(of)0 3563 y(the)e(C)f(calling)h(sequence.)0 3724 y(3.)41 b(The)30 b(function)g(parameters)h(are)g(de\014ned)e(in)h(more)g(detail)i(in)e (the)g(alphab)s(etical)i(listing)f(in)f(App)s(endix)f(B.)0 3884 y(4.)39 b(The)23 b(\014rst)g(argumen)m(t)g(in)h(almost)g(all)h (the)e(functions)g(is)h(a)g(p)s(oin)m(ter)f(to)h(a)g(structure)f(of)h (t)m(yp)s(e)g(`\014ts\014le'.)38 b(Memory)0 3997 y(for)26 b(this)g(structure)f(is)h(allo)s(cated)i(b)m(y)e(CFITSIO)e(when)h(the)h (FITS)g(\014le)g(is)g(\014rst)f(op)s(ened)g(or)h(created)h(and)e(is)h (freed)0 4110 y(when)j(the)i(FITS)f(\014le)g(is)g(closed.)0 4270 y(5.)53 b(The)34 b(last)h(argumen)m(t)f(in)g(almost)i(all)f(the)f (functions)g(is)g(the)h(error)f(status)g(parameter.)53 b(It)35 b(m)m(ust)f(b)s(e)f(equal)0 4383 y(to)k(0)g(on)f(input,)h (otherwise)g(the)f(function)g(will)h(immediately)g(exit)g(without)g (doing)f(an)m(ything.)59 b(A)36 b(non-zero)0 4496 y(output)27 b(v)-5 b(alue)27 b(indicates)i(that)e(an)g(error)g(o)s(ccurred)g(in)g (the)g(function.)39 b(In)27 b(most)g(cases)h(the)g(status)f(v)-5 b(alue)28 b(is)f(also)0 4608 y(returned)i(as)i(the)f(v)-5 b(alue)31 b(of)g(the)f(function)g(itself.)0 4739 y SDict begin H.S end 0 4739 a 0 4739 a SDict begin 13.6 H.A end 0 4739 a 0 4739 a SDict begin [ /View [/XYZ H.V] /Dest (section.5.1) cvn H.B /DEST pdfmark end 0 4739 a 196 x Ff(5.1)135 b(CFITSIO)44 b(Error)h(Status)h(Routines)0 5168 y Fi(1)81 b Fj(Return)27 b(a)j(descriptiv)m(e)f(text)h(string)e(\(30)i(c)m(har)f (max.\))41 b(corresp)s(onding)28 b(to)h(a)g(CFITSIO)e(error)h(status)h (co)s(de.)95 5385 y Fe(void)47 b(fits_get_errstatus)c(/)k(ffgerr)f (\(int)h(status,)f(>)h(char)g(*err_text\))0 5601 y Fi(2)81 b Fj(Return)35 b(the)h(top)g(\(oldest\))h(80-c)m(haracter)i(error)c (message)i(from)e(the)h(in)m(ternal)h(CFITSIO)d(stac)m(k)j(of)f(error) 227 5714 y(messages)45 b(and)e(shift)h(an)m(y)g(remaining)g(messages)h (on)f(the)g(stac)m(k)h(up)e(one)h(lev)m(el.)83 b(Call)44 b(this)g(routine)1905 5942 y(31)p eop end %%Page: 32 40 TeXDict begin 32 39 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.32) cvn H.B /DEST pdfmark end 0 299 a Fj(32)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)227 555 y Fj(rep)s(eatedly)c(to)h(get)g(eac)m(h)g (message)f(in)g(sequence.)39 b(The)26 b(function)f(returns)g(a)h(v)-5 b(alue)26 b(=)f(0)h(and)g(a)g(n)m(ull)f(error)227 668 y(message)32 b(when)d(the)i(error)f(stac)m(k)i(is)e(empt)m(y)-8 b(.)95 940 y Fe(int)47 b(fits_read_errmsg)d(/)j(ffgmsg)f(\(char)h (*err_msg\))0 1211 y Fi(3)81 b Fj(Prin)m(t)30 b(out)h(the)g(error)f (message)i(corresp)s(onding)e(to)h(the)g(input)f(status)h(v)-5 b(alue)31 b(and)f(all)i(the)f(error)f(messages)227 1324 y(on)d(the)h(CFITSIO)e(stac)m(k)j(to)f(the)f(sp)s(eci\014ed)g(\014le)g (stream)h(\(normally)g(to)g(stdout)f(or)g(stderr\).)40 b(If)26 b(the)i(input)227 1437 y(status)j(v)-5 b(alue)31 b(=)f(0)h(then)f(this)g(routine)g(do)s(es)g(nothing.)95 1709 y Fe(void)47 b(fits_report_error)c(/)48 b(ffrprt)e(\(FILE)g (*stream,)g(status\))0 1981 y Fi(4)81 b Fj(The)44 b(\014ts)p 461 1981 28 4 v 32 w(write)p 695 1981 V 33 w(errmark)g(routine)h(puts)f (an)h(in)m(visible)g(mark)m(er)g(on)g(the)g(CFITSIO)e(error)h(stac)m (k.)85 b(The)227 2094 y(\014ts)p 354 2094 V 33 w(clear)p 573 2094 V 34 w(errmark)31 b(routine)i(can)g(then)f(b)s(e)f(used)h(to)h (delete)h(an)m(y)f(more)f(recen)m(t)i(error)e(messages)h(on)g(the)227 2207 y(stac)m(k,)42 b(bac)m(k)c(to)g(the)g(p)s(osition)g(of)g(the)g (mark)m(er.)63 b(This)37 b(preserv)m(es)g(an)m(y)h(older)g(error)f (messages)i(on)f(the)227 2319 y(stac)m(k.)77 b(The)41 b(\014ts)p 855 2319 V 32 w(clear)p 1073 2319 V 34 w(errmsg)g(routine)h (simply)f(clears)i(all)g(the)f(messages)g(\(and)g(marks\))f(from)h(the) 227 2432 y(stac)m(k.)g(These)31 b(routines)f(are)h(called)g(without)g (an)m(y)f(argumen)m(ts.)95 2704 y Fe(void)47 b(fits_write_errmark)c(/)k (ffpmrk)f(\(void\))95 2817 y(void)h(fits_clear_errmark)c(/)k(ffcmrk)f (\(void\))95 2930 y(void)h(fits_clear_errmsg)c(/)48 b(ffcmsg)e (\(void\))0 3101 y SDict begin H.S end 0 3101 a 0 3101 a SDict begin 13.6 H.A end 0 3101 a 0 3101 a SDict begin [ /View [/XYZ H.V] /Dest (section.5.2) cvn H.B /DEST pdfmark end 0 3101 a 177 x Ff(5.2)135 b(FITS)44 b(File)i(Access)e(Routines)0 3527 y Fi(1)81 b Fj(Op)s(en)29 b(an)h(existing)h(data)g(\014le.)227 3794 y Fe(int)47 b(fits_open_file)d(/)k(ffopen)418 3907 y(\(fitsfile)d(**fptr,)h(char)h(*filename,)e(int)i(iomode,)f(>)h(int)g (*status\))227 4133 y(int)g(fits_open_diskfile)c(/)k(ffdkopen)418 4246 y(\(fitsfile)e(**fptr,)h(char)h(*filename,)e(int)i(iomode,)f(>)h (int)g(*status\))227 4472 y(int)g(fits_open_data)d(/)k(ffdopn)418 4585 y(\(fitsfile)d(**fptr,)h(char)h(*filename,)e(int)i(iomode,)f(>)h (int)g(*status\))227 4811 y(int)g(fits_open_table)d(/)j(fftopn)418 4924 y(\(fitsfile)e(**fptr,)h(char)h(*filename,)e(int)i(iomode,)f(>)h (int)g(*status\))227 5149 y(int)g(fits_open_image)d(/)j(ffiopn)418 5262 y(\(fitsfile)e(**fptr,)h(char)h(*filename,)e(int)i(iomode,)f(>)h (int)g(*status\))227 5488 y(int)g(fits_open_extlist)c(/)48 b(ffeopn)418 5601 y(\(fitsfile)d(**fptr,)h(char)h(*filename,)e(int)i (iomode,)f(char)g(*extlist,)418 5714 y(>)95 b(int)47 b(*hdutype,)f(int)g(*status\))p eop end %%Page: 33 41 TeXDict begin 33 40 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.33) cvn H.B /DEST pdfmark end 0 299 a Fh(5.2.)72 b(FITS)30 b(FILE)g(A)m(CCESS)f (R)m(OUTINES)2244 b Fj(33)227 555 y(The)41 b(iomo)s(de)h(parameter)g (determines)g(the)f(read/write)h(access)h(allo)m(w)m(ed)h(in)d(the)g (\014le)h(and)f(can)h(ha)m(v)m(e)227 668 y(v)-5 b(alues)32 b(of)g(READONL)-8 b(Y)32 b(\(0\))g(or)g(READ)m(WRITE)g(\(1\).)44 b(The)31 b(\014lename)h(parameter)g(giv)m(es)h(the)e(name)h(of)227 781 y(the)f(\014le)g(to)g(b)s(e)f(op)s(ened,)h(follo)m(w)m(ed)h(b)m(y)f (an)f(optional)i(argumen)m(t)f(giving)h(the)f(name)f(or)h(index)f(n)m (um)m(b)s(er)g(of)227 894 y(the)d(extension)g(within)g(the)f(FITS)g (\014le)h(that)g(should)f(b)s(e)g(mo)m(v)m(ed)i(to)f(and)f(op)s(ened)g (\(e.g.,)k Fe(myfile.fits+3)227 1007 y Fj(or)36 b Fe(myfile.fits[3])d Fj(mo)m(v)m(es)k(to)g(the)g(3rd)f(extension)g(within)g(the)h(\014le,)h (and)d Fe(myfile.fits[events])227 1120 y Fj(mo)m(v)m(es)d(to)f(the)g (extension)g(with)f(the)g(k)m(eyw)m(ord)h(EXTNAME)g(=)f('EVENTS'\).)227 1292 y(The)37 b(\014ts)p 548 1292 28 4 v 32 w(op)s(en)p 770 1292 V 32 w(disk\014le)g(routine)g(is)g(similar)g(to)h(the)f (\014ts)p 2241 1292 V 33 w(op)s(en)p 2464 1292 V 32 w(\014le)g(routine) g(except)h(that)f(it)h(do)s(es)f(not)227 1405 y(supp)s(ort)22 b(the)h(extended)h(\014lename)f(syn)m(tax)h(in)f(the)h(input)e(\014le)i (name.)38 b(This)23 b(routine)g(simply)g(tries)h(to)g(op)s(en)227 1518 y(the)36 b(sp)s(eci\014ed)e(input)h(\014le)g(on)g(magnetic)i (disk.)55 b(This)34 b(routine)h(is)h(mainly)f(for)g(use)g(in)g(cases)h (where)f(the)227 1631 y(\014lename)f(\(or)h(directory)f(path\))g(con)m (tains)h(square)f(or)g(curly)f(brac)m(k)m(et)j(c)m(haracters)f(that)f (w)m(ould)g(confuse)227 1744 y(the)d(extended)f(\014lename)h(parser.) 227 1916 y(The)i(\014ts)p 544 1916 V 32 w(op)s(en)p 766 1916 V 32 w(data)h(routine)e(is)h(similar)g(to)h(the)f(\014ts)p 2113 1916 V 32 w(op)s(en)p 2335 1916 V 33 w(\014le)f(routine)h(except)h (that)f(it)h(will)f(mo)m(v)m(e)h(to)227 2029 y(the)23 b(\014rst)f(HDU)h(con)m(taining)h(signi\014can)m(t)f(data,)i(if)e(a)g (HDU)g(name)f(or)h(n)m(um)m(b)s(er)e(to)i(op)s(en)f(w)m(as)h(not)f (explicitly)227 2142 y(sp)s(eci\014ed)37 b(as)g(part)h(of)f(the)h (\014lename.)61 b(In)37 b(this)g(case,)j(it)e(will)g(lo)s(ok)g(for)f (the)g(\014rst)g(IMA)m(GE)h(HDU)g(with)227 2255 y(NAXIS)29 b(greater)h(than)e(0,)i(or)f(the)f(\014rst)g(table)i(that)f(do)s(es)g (not)g(con)m(tain)h(the)f(strings)f(`GTI')h(\(Go)s(o)s(d)g(Time)227 2368 y(In)m(terv)-5 b(al)31 b(extension\))h(or)e(`OBST)-8 b(ABLE')31 b(in)f(the)h(EXTNAME)f(k)m(eyw)m(ord)h(v)-5 b(alue.)227 2540 y(The)25 b(\014ts)p 536 2540 V 32 w(op)s(en)p 758 2540 V 32 w(table)h(and)e(\014ts)p 1305 2540 V 33 w(op)s(en)p 1528 2540 V 32 w(image)i(routines)f(are)g(similar)h(to)f (\014ts)p 2828 2540 V 33 w(op)s(en)p 3051 2540 V 32 w(data)h(except)f (they)h(will)227 2653 y(mo)m(v)m(e)h(to)g(the)f(\014rst)f(signi\014can) m(t)h(table)h(HDU)f(or)g(image)h(HDU)f(in)f(the)h(\014le,)h(resp)s (ectiv)m(ely)-8 b(,)29 b(if)c(a)h(HDU)h(name)227 2766 y(or)k(n)m(um)m(b)s(er)e(is)h(not)h(sp)s(eci\014ed)e(as)i(part)f(of)h (the)f(\014lename.)227 2938 y(The)40 b(\014ts)p 551 2938 V 33 w(op)s(en)p 774 2938 V 32 w(extname)h(routine)g(op)s(ens)f(the)h (\014le)g(and)f(attempts)h(to)h(mo)m(v)m(e)g(to)f(a)g('useful')g(HDU.)g (If)227 3051 y(after)28 b(op)s(ening)f(the)h(\014le)f(CFITSIO)f(is)h(p) s(oin)m(ting)h(to)g(n)m(ull)f(primary)g(arra)m(y)-8 b(,)29 b(then)e(CFITSIO)f(will)i(attempt)227 3164 y(to)38 b(mo)m(v)m(e)g(to)f (the)g(\014rst)f(extension)h(that)g(has)f(an)h(EXTNAME)g(or)f(HDUNAME)i (k)m(eyw)m(ord)f(v)-5 b(alue)37 b(that)227 3277 y(matc)m(hes)28 b(one)f(of)g(the)g(names)f(in)h(the)g(input)f(extlist)i (space-delimited)g(list)f(of)g(names.)39 b(If)27 b(that)g(fails,)h (then)227 3390 y(CFITSIO)h(simply)h(mo)m(v)m(es)i(to)f(the)f(2nd)g(HDU) h(in)f(the)h(\014le.)227 3563 y(IRAF)26 b(images)g(\(.imh)g(format)g (\014les\))f(and)g(ra)m(w)h(binary)e(data)j(arra)m(ys)e(ma)m(y)h(also)h (b)s(e)e(op)s(ened)f(with)h(READ-)227 3675 y(ONL)-8 b(Y)37 b(access.)60 b(CFITSIO)35 b(will)i(automatically)i(test)f(if)e(the)h (input)e(\014le)i(is)f(an)h(IRAF)f(image,)k(and)c(if,)227 3788 y(so)c(will)g(con)m(v)m(ert)h(it)f(on)f(the)h(\015y)f(in)m(to)i(a) f(virtual)f(FITS)g(image)i(b)s(efore)e(it)h(is)g(op)s(ened)e(b)m(y)i (the)g(application)227 3901 y(program.)64 b(If)37 b(the)h(input)g (\014le)g(is)g(a)g(ra)m(w)g(binary)g(data)g(arra)m(y)h(of)f(n)m(um)m(b) s(ers,)h(then)e(the)i(data)f(t)m(yp)s(e)h(and)227 4014 y(dimensions)d(of)g(the)g(arra)m(y)h(m)m(ust)f(b)s(e)f(sp)s(eci\014ed)g (in)h(square)g(brac)m(k)m(ets)h(follo)m(wing)h(the)e(name)g(of)h(the)f (\014le)227 4127 y(\(e.g.)56 b('ra)m(w\014le.dat[i512,512]')40 b(op)s(ens)34 b(a)i(512)g(x)f(512)h(short)e(in)m(teger)j(image\).)56 b(See)35 b(the)g(`Extended)g(File)227 4240 y(Name)k(Syn)m(tax')g(c)m (hapter)g(for)e(more)i(details)g(on)f(ho)m(w)g(to)h(sp)s(ecify)f(the)g (ra)m(w)h(\014le)f(name.)64 b(The)38 b(ra)m(w)g(\014le)227 4353 y(is)k(con)m(v)m(erted)g(on)f(the)h(\015y)f(in)m(to)h(a)f(virtual) h(FITS)e(image)j(in)e(memory)g(that)h(is)f(then)g(op)s(ened)g(b)m(y)g (the)227 4466 y(application)32 b(program)e(with)g(READONL)-8 b(Y)31 b(access.)227 4638 y(Programs)g(can)g(read)f(the)h(input)e (\014le)i(from)f(the)h('stdin')f(\014le)h(stream)g(if)f(a)h(dash)f(c)m (haracter)i(\('-'\))g(is)f(giv)m(en)227 4751 y(as)36 b(the)g(\014lename.)58 b(Files)37 b(can)f(also)h(b)s(e)e(op)s(ened)g(o) m(v)m(er)i(the)f(net)m(w)m(ork)h(using)e(FTP)h(or)g(HTTP)f(proto)s (cols)227 4864 y(b)m(y)f(supplying)e(the)i(appropriate)f(URL)g(as)h (the)g(\014lename.)50 b(The)33 b(HTTPS)f(proto)s(col)j(is)e(also)i (supp)s(orted)227 4977 y(if)e(the)f(CFITSIO)f(build)g(includes)h(the)h (lib)s(curl)e(library)-8 b(.)47 b(\(If)32 b(the)g(CFITSIO)f ('con\014gure')i(script)f(\014nds)f(a)227 5090 y(usable)g(lib)s(curl)e (library)h(on)g(y)m(our)h(system,)f(it)h(will)g(automatically)i(b)s(e)d (included)g(in)g(the)g(build.\))227 5262 y(The)43 b(input)f(\014le)h (can)h(b)s(e)f(mo)s(di\014ed)f(in)g(v)-5 b(arious)44 b(w)m(a)m(ys)g(to)g(create)g(a)g(virtual)f(\014le)h(\(usually)f(stored) g(in)227 5375 y(memory\))31 b(that)g(is)g(then)f(op)s(ened)f(b)m(y)i (the)f(application)i(program)e(b)m(y)h(supplying)e(a)i(\014ltering)g (or)f(binning)227 5488 y(sp)s(eci\014er)e(in)g(square)g(brac)m(k)m(ets) h(follo)m(wing)h(the)e(\014lename.)40 b(Some)29 b(of)f(the)g(more)h (common)f(\014ltering)h(meth-)227 5601 y(o)s(ds)j(are)h(illustrated)h (in)e(the)h(follo)m(wing)i(paragraphs,)e(but)f(users)g(should)f(refer)i (to)g(the)g('Extended)g(File)227 5714 y(Name)e(Syn)m(tax')g(c)m(hapter) g(for)f(a)h(complete)h(description)e(of)h(the)f(full)h(\014le)f (\014ltering)h(syn)m(tax.)p eop end %%Page: 34 42 TeXDict begin 34 41 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.34) cvn H.B /DEST pdfmark end 0 299 a Fj(34)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)227 555 y Fj(When)d(op)s(ening)f(an)h(image,)h(a)g (rectangular)f(subset)f(of)h(the)g(ph)m(ysical)g(image)h(ma)m(y)g(b)s (e)e(op)s(ened)f(b)m(y)i(listing)227 668 y(the)k(\014rst)e(and)h(last)h (pixel)g(in)f(eac)m(h)i(dimension)e(\(and)g(optional)h(pixel)g (skipping)f(factor\):)227 895 y Fe(myimage.fits[101:200,301:)o(400])227 1123 y Fj(will)g(create)h(and)e(op)s(en)f(a)i(100x100)i(pixel)e (virtual)g(image)g(of)g(that)g(section)g(of)g(the)f(ph)m(ysical)h (image,)i(and)227 1235 y Fe(myimage.fits[*,-*])c Fj(op)s(ens)k(a)h (virtual)g(image)h(that)f(is)g(the)g(same)g(size)h(as)e(the)h(ph)m (ysical)h(image)g(but)227 1348 y(has)c(b)s(een)g(\015ipp)s(ed)f(in)h (the)g(v)m(ertical)j(direction.)227 1495 y(When)28 b(op)s(ening)g(a)g (table,)i(the)e(\014ltering)g(syn)m(tax)h(can)f(b)s(e)f(used)h(to)g (add)g(or)g(delete)h(columns)f(or)g(k)m(eyw)m(ords)227 1608 y(in)g(the)g(virtual)h(table:)40 b Fe(myfile.fits[events][col)i (!time;)k(PI)h(=)h(PHA*1.2])26 b Fj(op)s(ens)h(a)h(virtual)h(ta-)227 1721 y(ble)j(in)f(whic)m(h)g(the)h(TIME)f(column)g(has)g(b)s(een)g (deleted)h(and)f(a)g(new)g(PI)g(column)h(has)f(b)s(een)g(added)f(with) 227 1834 y(a)41 b(v)-5 b(alue)40 b(1.2)i(times)e(that)h(of)f(the)h(PHA) f(column.)70 b(Similarly)-8 b(,)43 b(one)e(can)f(\014lter)h(a)f(table)h (to)g(k)m(eep)g(only)227 1947 y(those)35 b(ro)m(ws)e(that)i(satisfy)f (a)g(selection)i(criterion:)48 b Fe(myfile.fits[events][pha)42 b(>)47 b(50])33 b Fj(creates)j(and)227 2060 y(op)s(ens)31 b(a)g(virtual)h(table)g(con)m(taining)h(only)e(those)h(ro)m(ws)f(with)g (a)g(PHA)h(v)-5 b(alue)31 b(greater)i(than)e(50.)44 b(A)31 b(large)227 2173 y(n)m(um)m(b)s(er)d(of)h(b)s(o)s(olean)h(and)e (mathematical)k(op)s(erators)d(can)g(b)s(e)g(used)f(in)h(the)g (selection)i(expression.)40 b(One)227 2286 y(can)25 b(also)g(\014lter)g (table)g(ro)m(ws)f(using)g('Go)s(o)s(d)h(Time)f(In)m(terv)-5 b(al')26 b(extensions,)g(and)e(spatial)h(region)g(\014lters)g(as)f(in) 227 2399 y Fe(myfile.fits[events][gtifi)o(lter)o(\(\)])14 b Fj(and)19 b Fe(myfile.fits[events][regfil)o(ter)o(\()42 b("stars.rng"\)])p Fj(.)227 2546 y(Finally)-8 b(,)34 b(table)e(columns)f(ma)m(y)h(b)s(e)f(binned)f(or)h(histogrammed)h(to)g (generate)h(a)e(virtual)h(image.)45 b(F)-8 b(or)32 b(ex-)227 2659 y(ample,)d Fe(myfile.fits[events][bin)41 b(\(X,Y\)=4])26 b Fj(will)h(result)h(in)f(a)h(2-dimensional)g(image)h(calculated)227 2771 y(b)m(y)35 b(binning)e(the)i(X)f(and)g(Y)h(columns)f(in)g(the)h (ev)m(en)m(t)h(table)f(with)f(a)h(bin)f(size)h(of)g(4)f(in)h(eac)m(h)g (dimension.)227 2884 y(The)30 b(TLMINn)g(and)f(TLMAXn)h(k)m(eyw)m(ords) h(will)g(b)s(e)e(used)h(b)m(y)g(default)h(to)g(determine)f(the)h(range) f(of)h(the)227 2997 y(image.)227 3144 y(A)j(single)g(program)f(can)g (op)s(en)g(the)h(same)f(FITS)g(\014le)g(more)h(than)f(once)h(and)f (then)g(treat)h(the)g(resulting)227 3257 y(\014ts\014le)c(p)s(oin)m (ters)g(as)g(though)g(they)g(w)m(ere)h(completely)h(indep)s(enden)m(t)d (FITS)g(\014les.)40 b(Using)31 b(this)f(facilit)m(y)-8 b(,)33 b(a)227 3370 y(program)f(can)f(op)s(en)g(a)h(FITS)f(\014le)g(t)m (wice,)j(mo)m(v)m(e)f(to)f(2)g(di\013eren)m(t)g(extensions)g(within)f (the)g(\014le,)h(and)f(then)227 3483 y(read)g(and)e(write)i(data)g(in)f (those)h(extensions)g(in)f(an)m(y)h(order.)0 3723 y Fi(2)81 b Fj(Create)31 b(and)f(op)s(en)f(a)i(new)f(empt)m(y)h(output)f(FITS)f (\014le.)227 3951 y Fe(int)47 b(fits_create_file)d(/)j(ffinit)418 4064 y(\(fitsfile)e(**fptr,)h(char)h(*filename,)e(>)i(int)g(*status\)) 227 4289 y(int)g(fits_create_diskfile)42 b(/)48 b(ffdkinit)418 4402 y(\(fitsfile)d(**fptr,)h(char)h(*filename,)e(>)i(int)g(*status\)) 227 4629 y Fj(An)36 b(error)h(will)g(b)s(e)f(returned)f(if)h(the)h(sp)s (eci\014ed)f(\014le)h(already)g(exists,)i(unless)d(the)h(\014lename)f (is)h(pre\014xed)227 4742 y(with)30 b(an)g(exclamation)i(p)s(oin)m(t)e (\(!\).)42 b(In)29 b(that)i(case)g(CFITSIO)d(will)j(o)m(v)m(erwrite)g (\(delete\))h(an)m(y)f(existing)g(\014le)227 4855 y(with)36 b(the)g(same)h(name.)57 b(Note)38 b(that)e(the)h(exclamation)h(p)s(oin) m(t)e(is)g(a)h(sp)s(ecial)f(UNIX)g(c)m(haracter)i(so)e(if)g(it)227 4968 y(is)d(used)e(on)h(the)h(command)f(line)h(it)g(m)m(ust)f(b)s(e)g (preceded)g(b)m(y)g(a)g(bac)m(kslash)h(to)h(force)e(the)h(UNIX)g(shell) f(to)227 5081 y(accept)g(the)f(c)m(haracter)h(as)e(part)g(of)h(the)g (\014lename.)227 5228 y(The)26 b(output)h(\014le)g(will)g(b)s(e)f (written)h(to)g(the)g('stdout')g(\014le)g(stream)g(if)g(a)g(dash)f(c)m (haracter)i(\('-'\))g(or)f(the)g(string)227 5341 y('stdout')34 b(is)f(giv)m(en)h(as)g(the)f(\014lename.)49 b(Similarly)-8 b(,)35 b('-.gz')g(or)e('stdout.gz')i(will)f(cause)f(the)h(\014le)f(to)h (b)s(e)e(gzip)227 5454 y(compressed)e(b)s(efore)g(it)h(is)g(written)f (out)h(to)g(the)f(stdout)h(stream.)227 5601 y(Optionally)-8 b(,)41 b(the)c(name)h(of)f(a)h(template)h(\014le)e(that)h(is)f(used)g (to)h(de\014ne)f(the)g(structure)g(of)g(the)h(new)f(\014le)227 5714 y(ma)m(y)i(b)s(e)f(sp)s(eci\014ed)f(in)h(paren)m(theses)h(follo)m (wing)g(the)g(output)e(\014le)i(name.)64 b(The)38 b(template)h(\014le)g (ma)m(y)g(b)s(e)p eop end %%Page: 35 43 TeXDict begin 35 42 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.35) cvn H.B /DEST pdfmark end 0 299 a Fh(5.3.)72 b(HDU)31 b(A)m(CCESS)e(R)m (OUTINES)2488 b Fj(35)227 555 y(another)32 b(FITS)e(\014le,)i(in)f (whic)m(h)g(case)i(the)e(new)g(\014le,)h(at)g(the)g(time)g(it)f(is)h (op)s(ened,)f(will)g(b)s(e)g(an)g(exact)i(cop)m(y)227 668 y(of)38 b(the)g(template)i(\014le)e(except)g(that)h(the)f(data)g (structures)g(\(images)h(and)e(tables\))i(will)f(b)s(e)g(\014lled)f (with)227 781 y(zeros.)k(Alternativ)m(ely)-8 b(,)32 b(the)d(template)i (\014le)e(ma)m(y)g(b)s(e)f(an)h(ASCI)s(I)e(format)i(text)h(\014le)f (con)m(taining)i(directiv)m(es)227 894 y(that)e(de\014ne)e(the)h(k)m (eyw)m(ords)g(to)g(b)s(e)g(created)h(in)e(eac)m(h)i(HDU)g(of)f(the)g (\014le.)40 b(See)28 b(the)g('Extended)f(File)i(Name)227 1007 y(Syn)m(tax')i(section)h(for)e(a)h(complete)g(description)g(of)f (the)h(template)h(\014le)e(syn)m(tax.)227 1156 y(The)f(\014ts)p 540 1156 28 4 v 33 w(create)p 809 1156 V 34 w(disk\014le)g(routine)h (is)g(similar)g(to)g(the)g(\014ts)p 2238 1156 V 32 w(create)p 2506 1156 V 34 w(\014le)g(routine)g(except)g(that)g(it)g(do)s(es)g(not) 227 1269 y(supp)s(ort)36 b(the)i(extended)g(\014lename)g(syn)m(tax)g (in)g(the)g(input)f(\014le)h(name.)63 b(This)37 b(routine)h(simply)f (tries)h(to)227 1382 y(create)e(the)e(sp)s(eci\014ed)f(\014le)h(on)f (magnetic)j(disk.)50 b(This)33 b(routine)h(is)g(mainly)g(for)g(use)f (in)h(cases)g(where)g(the)227 1495 y(\014lename)g(\(or)h(directory)f (path\))g(con)m(tains)h(square)f(or)g(curly)f(brac)m(k)m(et)j(c)m (haracters)f(that)f(w)m(ould)g(confuse)227 1608 y(the)d(extended)f (\014lename)h(parser.)0 1861 y Fi(3)81 b Fj(Close)28 b(a)f(previously)g(op)s(ened)g(FITS)g(\014le.)40 b(The)27 b(\014rst)f(routine)i(simply)f(closes)h(the)g(\014le,)g(whereas)f(the)h (second)227 1974 y(one)g(also)h(DELETES)e(the)g(\014le,)i(whic)m(h)e (can)h(b)s(e)g(useful)e(in)i(cases)g(where)g(a)g(FITS)f(\014le)g(has)h (b)s(een)f(partially)227 2086 y(created,)37 b(but)c(then)h(an)h(error)e (o)s(ccurs)h(whic)m(h)g(prev)m(en)m(ts)h(it)g(from)f(b)s(eing)g (completed.)53 b(Note)36 b(that)e(these)227 2199 y(routines)23 b(b)s(eha)m(v)m(e)g(di\013eren)m(tly)h(than)e(most)h(other)g(CFITSIO)e (routines)i(if)f(the)h(input)f(v)-5 b(alue)23 b(of)g(the)g(`status')227 2312 y(parameter)43 b(is)f(not)h(zero:)65 b(Instead)42 b(of)h(simply)f(returning)f(to)i(the)g(calling)g(program)g(without)f (doing)227 2425 y(an)m(ything,)30 b(these)f(routines)f(e\013ectiv)m (ely)k(ignore)d(the)f(input)g(status)h(v)-5 b(alue)29 b(and)f(still)h(attempt)h(to)f(close)h(or)227 2538 y(delete)i(the)e (\014le.)95 2791 y Fe(int)47 b(fits_close_file)d(/)j(ffclos)g (\(fitsfile)e(*fptr,)h(>)h(int)g(*status\))95 3017 y(int)g (fits_delete_file)d(/)j(ffdelt)f(\(fitsfile)g(*fptr,)g(>)h(int)g (*status\))0 3270 y Fi(4)81 b Fj(Return)21 b(the)i(name,)h(I/O)e(mo)s (de)g(\(READONL)-8 b(Y)24 b(or)e(READ)m(WRITE\),)i(and/or)e(the)g (\014le)h(t)m(yp)s(e)f(\(e.g.)40 b('\014le://',)227 3383 y('ftp://'\))32 b(of)f(the)f(op)s(ened)g(FITS)g(\014le.)95 3636 y Fe(int)47 b(fits_file_name)d(/)k(ffflnm)e(\(fitsfile)f(*fptr,)h (>)i(char)e(*filename,)f(int)i(*status\))95 3862 y(int)g (fits_file_mode)d(/)k(ffflmd)e(\(fitsfile)f(*fptr,)h(>)i(int)f (*iomode,)e(int)i(*status\))95 4088 y(int)g(fits_url_type)e(/)i(ffurlt) f(\(fitsfile)f(*fptr,)h(>)i(char)f(*urltype,)e(int)i(*status\))0 4244 y SDict begin H.S end 0 4244 a 0 4244 a SDict begin 13.6 H.A end 0 4244 a 0 4244 a SDict begin [ /View [/XYZ H.V] /Dest (section.5.3) cvn H.B /DEST pdfmark end 0 4244 a 176 x Ff(5.3)135 b(HDU)46 b(Access)e(Routines)0 4670 y Fj(The)30 b(follo)m(wing)i(functions)e(p)s(erform)f(op)s(erations)h(on)h (Header-Data)h(Units)f(\(HDUs\))h(as)e(a)h(whole.)0 4924 y Fi(1)81 b Fj(Mo)m(v)m(e)44 b(to)g(a)f(di\013eren)m(t)g(HDU)g(in)g (the)g(\014le.)77 b(The)43 b(\014rst)f(routine)g(mo)m(v)m(es)i(to)g(a)f (sp)s(eci\014ed)f(absolute)h(HDU)227 5036 y(n)m(um)m(b)s(er)f (\(starting)h(with)g(1)f(for)h(the)g(primary)e(arra)m(y\))j(in)e(the)h (FITS)f(\014le,)k(and)c(the)g(second)h(routine)227 5149 y(mo)m(v)m(es)35 b(a)e(relativ)m(e)i(n)m(um)m(b)s(er)d(HDUs)i(forw)m (ard)e(or)h(bac)m(kw)m(ard)h(from)f(the)g(curren)m(t)g(HDU.)h(A)f(n)m (ull)g(p)s(oin)m(ter)227 5262 y(ma)m(y)e(b)s(e)f(giv)m(en)h(for)f(the)g (hdut)m(yp)s(e)f(parameter)i(if)f(it's)h(v)-5 b(alue)31 b(is)f(not)h(needed.)40 b(The)30 b(third)f(routine)i(mo)m(v)m(es)227 5375 y(to)39 b(the)g(\(\014rst\))f(HDU)i(whic)m(h)e(has)g(the)h(sp)s (eci\014ed)e(extension)i(t)m(yp)s(e)g(and)f(EXTNAME)g(and)g(EXTVER)227 5488 y(k)m(eyw)m(ord)26 b(v)-5 b(alues)26 b(\(or)g(HDUNAME)h(and)e (HDUVER)h(k)m(eyw)m(ords\).)40 b(The)24 b(hdut)m(yp)s(e)h(parameter)h (ma)m(y)g(ha)m(v)m(e)227 5601 y(a)d(v)-5 b(alue)22 b(of)g(IMA)m(GE)p 935 5601 28 4 v 34 w(HDU,)h(ASCI)s(I)p 1476 5601 V 31 w(TBL,)f(BINAR)-8 b(Y)p 2101 5601 V 34 w(TBL,)22 b(or)g(ANY)p 2676 5601 V 34 w(HDU)g(where)g(ANY)p 3396 5601 V 33 w(HDU)h(means)227 5714 y(that)33 b(only)g(the)f(extname)i(and)d(extv)m(er)j(v)-5 b(alues)33 b(will)f(b)s(e)g(used)g(to)h(lo)s(cate)h(the)f(correct)g (extension.)48 b(If)32 b(the)p eop end %%Page: 36 44 TeXDict begin 36 43 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.36) cvn H.B /DEST pdfmark end 0 299 a Fj(36)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)227 555 y Fj(input)k(v)-5 b(alue)36 b(of)f(extv)m(er)h (is)f(0)h(then)e(the)i(EXTVER)e(k)m(eyw)m(ord)i(is)f(ignored)g(and)g (the)g(\014rst)f(HDU)i(with)f(a)227 668 y(matc)m(hing)28 b(EXTNAME)g(\(or)f(HDUNAME\))i(k)m(eyw)m(ord)e(will)g(b)s(e)g(found.)38 b(If)27 b(no)f(matc)m(hing)i(HDU)g(is)f(found)227 781 y(in)f(the)g(\014le)g(then)g(the)g(curren)m(t)g(HDU)g(will)h(remain)f (unc)m(hanged)f(and)h(a)g(status)g(=)g(BAD)p 3246 781 28 4 v 33 w(HDU)p 3484 781 V 34 w(NUM)h(will)227 894 y(b)s(e)j(returned.)95 1141 y Fe(int)47 b(fits_movabs_hdu)d(/)j(ffmahd) 286 1254 y(\(fitsfile)f(*fptr,)g(int)h(hdunum,)e(>)j(int)f(*hdutype,)e (int)i(*status\))95 1480 y(int)g(fits_movrel_hdu)d(/)j(ffmrhd)286 1593 y(\(fitsfile)f(*fptr,)g(int)h(nmove,)f(>)h(int)g(*hdutype,)e(int)i (*status\))95 1818 y(int)g(fits_movnam_hdu)d(/)j(ffmnhd)286 1931 y(\(fitsfile)f(*fptr,)g(int)h(hdutype,)e(char)i(*extname,)e(int)i (extver,)f(>)h(int)g(*status\))0 2178 y Fi(2)81 b Fj(Return)38 b(the)i(total)h(n)m(um)m(b)s(er)d(of)i(HDUs)g(in)f(the)h(FITS)f (\014le.)68 b(This)39 b(returns)f(the)h(n)m(um)m(b)s(er)g(of)g (completely)227 2291 y(de\014ned)30 b(HDUs)h(in)f(the)h(\014le.)42 b(If)30 b(a)h(new)f(HDU)h(has)g(just)f(b)s(een)g(added)f(to)j(the)f (FITS)f(\014le,)h(then)f(that)h(last)227 2404 y(HDU)f(will)f(only)g(b)s (e)g(coun)m(ted)g(if)g(it)h(has)e(b)s(een)h(closed,)h(or)f(if)g(data)h (has)e(b)s(een)h(written)g(to)g(the)g(HDU.)h(The)227 2517 y(curren)m(t)g(HDU)i(remains)e(unc)m(hanged)g(b)m(y)g(this)g (routine.)95 2764 y Fe(int)47 b(fits_get_num_hdus)c(/)48 b(ffthdu)286 2877 y(\(fitsfile)e(*fptr,)g(>)h(int)g(*hdunum,)f(int)h (*status\))0 3124 y Fi(3)81 b Fj(Return)31 b(the)h(n)m(um)m(b)s(er)f (of)h(the)h(curren)m(t)e(HDU)i(\(CHDU\))h(in)d(the)i(FITS)e(\014le)h (\(where)g(the)g(primary)g(arra)m(y)g(=)227 3237 y(1\).)42 b(This)29 b(function)h(returns)g(the)g(HDU)h(n)m(um)m(b)s(er)e(rather)h (than)h(a)f(status)h(v)-5 b(alue.)95 3484 y Fe(int)47 b(fits_get_hdu_num)d(/)j(ffghdn)286 3597 y(\(fitsfile)f(*fptr,)g(>)h (int)g(*hdunum\))0 3844 y Fi(4)81 b Fj(Return)38 b(the)h(t)m(yp)s(e)h (of)f(the)h(curren)m(t)f(HDU)h(in)f(the)g(FITS)g(\014le.)67 b(The)39 b(p)s(ossible)g(v)-5 b(alues)39 b(for)g(hdut)m(yp)s(e)f(are:) 227 3957 y(IMA)m(GE)p 546 3957 V 34 w(HDU,)31 b(ASCI)s(I)p 1095 3957 V 32 w(TBL,)f(or)g(BINAR)-8 b(Y)p 1840 3957 V 34 w(TBL.)95 4204 y Fe(int)47 b(fits_get_hdu_type)c(/)48 b(ffghdt)286 4317 y(\(fitsfile)e(*fptr,)g(>)h(int)g(*hdutype,)e(int)i (*status\))0 4564 y Fi(5)81 b Fj(Cop)m(y)24 b(all)h(or)f(part)g(of)g (the)g(HDUs)h(in)f(the)g(FITS)g(\014le)g(asso)s(ciated)h(with)f(infptr) f(and)h(app)s(end)e(them)i(to)h(the)g(end)227 4677 y(of)f(the)f(FITS)f (\014le)i(asso)s(ciated)g(with)f(outfptr.)38 b(If)23 b('previous')g(is)g(true)g(\(not)h(0\),)i(then)d(an)m(y)g(HDUs)h (preceding)227 4789 y(the)35 b(curren)m(t)f(HDU)g(in)g(the)h(input)e (\014le)h(will)h(b)s(e)e(copied)i(to)g(the)f(output)g(\014le.)52 b(Similarly)-8 b(,)36 b('curren)m(t')f(and)227 4902 y('follo)m(wing')c (determine)e(whether)f(the)h(curren)m(t)g(HDU,)g(and/or)g(an)m(y)g (follo)m(wing)h(HDUs)g(in)e(the)h(input)f(\014le)227 5015 y(will)i(b)s(e)f(copied)i(to)f(the)g(output)f(\014le.)41 b(Th)m(us,)29 b(if)g(all)i(3)f(parameters)g(are)g(true,)g(then)g(the)f (en)m(tire)i(input)e(\014le)227 5128 y(will)36 b(b)s(e)e(copied.)56 b(On)35 b(exit,)i(the)f(curren)m(t)f(HDU)h(in)e(the)i(input)e(\014le)i (will)f(b)s(e)g(unc)m(hanged,)h(and)f(the)g(last)227 5241 y(HDU)c(in)f(the)h(output)f(\014le)g(will)h(b)s(e)f(the)g(curren)m (t)h(HDU.)95 5488 y Fe(int)47 b(fits_copy_file)d(/)k(ffcpfl)286 5601 y(\(fitsfile)e(*infptr,)f(fitsfile)h(*outfptr,)f(int)i(previous,)e (int)i(current,)477 5714 y(int)g(following,)e(>)j(int)f(*status\))p eop end %%Page: 37 45 TeXDict begin 37 44 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.37) cvn H.B /DEST pdfmark end 0 299 a Fh(5.4.)72 b(HEADER)31 b(KEYW)m(ORD)g(READ/WRITE)g(R)m(OUTINES)1495 b Fj(37)0 555 y Fi(6)81 b Fj(Cop)m(y)34 b(the)h(curren)m(t)f(HDU)h(from)f(the)g (FITS)g(\014le)h(asso)s(ciated)g(with)g(infptr)e(and)h(app)s(end)e(it)j (to)g(the)g(end)f(of)227 668 y(the)39 b(FITS)e(\014le)h(asso)s(ciated)i (with)e(outfptr.)64 b(Space)38 b(ma)m(y)h(b)s(e)e(reserv)m(ed)i(for)f (MOREKEYS)f(additional)227 781 y(k)m(eyw)m(ords)31 b(in)f(the)h(output) f(header.)95 1032 y Fe(int)47 b(fits_copy_hdu)e(/)i(ffcopy)286 1144 y(\(fitsfile)f(*infptr,)f(fitsfile)h(*outfptr,)f(int)i(morekeys,)e (>)j(int)f(*status\))0 1395 y Fi(7)81 b Fj(W)-8 b(rite)31 b(the)g(curren)m(t)f(HDU)h(in)f(the)h(input)e(FITS)h(\014le)g(to)h(the) g(output)f(FILE)g(stream)h(\(e.g.,)h(to)f(stdout\).)95 1645 y Fe(int)47 b(fits_write_hdu)d(/)k(ffwrhdu)286 1758 y(\(fitsfile)e(*infptr,)f(FILE)i(*stream,)e(>)j(int)f(*status\))0 2009 y Fi(8)81 b Fj(Cop)m(y)43 b(the)h(header)g(\(and)f(not)h(the)g (data\))h(from)e(the)h(CHDU)g(asso)s(ciated)h(with)f(infptr)e(to)j(the) f(CHDU)227 2122 y(asso)s(ciated)28 b(with)e(outfptr.)39 b(If)26 b(the)h(curren)m(t)f(output)g(HDU)h(is)g(not)f(completely)i (empt)m(y)-8 b(,)29 b(then)d(the)h(CHDU)227 2235 y(will)35 b(b)s(e)f(closed)h(and)f(a)h(new)f(HDU)h(will)g(b)s(e)f(app)s(ended)e (to)j(the)g(output)f(\014le.)53 b(An)34 b(empt)m(y)h(output)f(data)227 2348 y(unit)c(will)h(b)s(e)f(created)h(with)f(all)h(v)-5 b(alues)31 b(initially)h(=)e(0\).)95 2598 y Fe(int)47 b(fits_copy_header)d(/)j(ffcphd)286 2711 y(\(fitsfile)f(*infptr,)f (fitsfile)h(*outfptr,)f(>)i(int)g(*status\))0 2962 y Fi(9)81 b Fj(Delete)35 b(the)e(CHDU)h(in)f(the)g(FITS)f(\014le.)50 b(An)m(y)33 b(follo)m(wing)i(HDUs)e(will)h(b)s(e)e(shifted)h(forw)m (ard)g(in)g(the)g(\014le,)h(to)227 3074 y(\014ll)k(in)f(the)g(gap)h (created)g(b)m(y)g(the)f(deleted)h(HDU.)h(In)d(the)i(case)g(of)g (deleting)g(the)g(primary)e(arra)m(y)i(\(the)227 3187 y(\014rst)30 b(HDU)h(in)f(the)h(\014le\))g(then)f(the)h(curren)m(t)f (primary)f(arra)m(y)i(will)g(b)s(e)f(replace)h(b)m(y)g(a)g(n)m(ull)f (primary)f(arra)m(y)227 3300 y(con)m(taining)k(the)f(minim)m(um)e(set)i (of)g(required)e(k)m(eyw)m(ords)i(and)e(no)i(data.)44 b(If)31 b(there)g(are)h(more)f(extensions)227 3413 y(in)f(the)g(\014le) g(follo)m(wing)i(the)e(one)g(that)h(is)f(deleted,)h(then)f(the)g(the)g (CHDU)h(will)f(b)s(e)g(rede\014ned)e(to)j(p)s(oin)m(t)f(to)227 3526 y(the)d(follo)m(wing)h(extension.)41 b(If)26 b(there)h(are)g(no)g (follo)m(wing)h(extensions)f(then)g(the)g(CHDU)g(will)g(b)s(e)f (rede\014ned)227 3639 y(to)36 b(p)s(oin)m(t)f(to)g(the)g(previous)f (HDU.)i(The)e(output)h(hdut)m(yp)s(e)e(parameter)i(returns)f(the)h(t)m (yp)s(e)g(of)f(the)h(new)227 3752 y(CHDU.)c(A)g(n)m(ull)f(p)s(oin)m (ter)g(ma)m(y)h(b)s(e)f(giv)m(en)i(for)e(hdut)m(yp)s(e)f(if)h(the)h (returned)e(v)-5 b(alue)31 b(is)f(not)h(needed.)95 4002 y Fe(int)47 b(fits_delete_hdu)d(/)j(ffdhdu)286 4115 y(\(fitsfile)f (*fptr,)g(>)h(int)g(*hdutype,)e(int)i(*status\))0 4271 y SDict begin H.S end 0 4271 a 0 4271 a SDict begin 13.6 H.A end 0 4271 a 0 4271 a SDict begin [ /View [/XYZ H.V] /Dest (section.5.4) cvn H.B /DEST pdfmark end 0 4271 a 177 x Ff(5.4)135 b(Header)46 b(Keyw)l(ord)g(Read/W)-11 b(rite)46 b(Routines)0 4698 y Fj(These)35 b(routines)g(read)f(or)h(write)h(k)m (eyw)m(ords)f(in)g(the)g(Curren)m(t)f(Header)h(Unit)g(\(CHU\).)h(Wild)g (card)e(c)m(haracters)0 4811 y(\(*,)28 b(?,)g(or)e(#\))h(ma)m(y)g(b)s (e)f(used)g(when)f(sp)s(ecifying)i(the)g(name)f(of)h(the)g(k)m(eyw)m (ord)g(to)g(b)s(e)f(read:)39 b(a)27 b(')10 b(?')39 b(will)27 b(matc)m(h)h(an)m(y)0 4924 y(single)35 b(c)m(haracter)g(at)g(that)f(p)s (osition)g(in)g(the)g(k)m(eyw)m(ord)h(name)f(and)f(a)h('*')h(will)g (matc)m(h)f(an)m(y)h(length)f(\(including)0 5036 y(zero\))c(string)f (of)g(c)m(haracters.)42 b(The)28 b('#')h(c)m(haracter)i(will)e(matc)m (h)h(an)m(y)f(consecutiv)m(e)i(string)e(of)g(decimal)h(digits)f(\(0)0 5149 y(-)35 b(9\).)55 b(When)35 b(a)g(wild)g(card)g(is)g(used)f(the)h (routine)g(will)g(only)g(searc)m(h)h(for)f(a)g(matc)m(h)h(from)e(the)h (curren)m(t)g(header)0 5262 y(p)s(osition)27 b(to)h(the)f(end)f(of)h (the)g(header)g(and)f(will)h(not)g(resume)g(the)g(searc)m(h)g(from)g (the)g(top)g(of)g(the)g(header)g(bac)m(k)g(to)0 5375 y(the)k(original)i(header)e(p)s(osition)g(as)h(is)f(done)g(when)f(no)h (wildcards)g(are)h(included)e(in)h(the)g(k)m(eyw)m(ord)h(name.)43 b(The)0 5488 y(\014ts)p 127 5488 28 4 v 32 w(read)p 331 5488 V 33 w(record)29 b(routine)h(ma)m(y)g(b)s(e)f(used)f(to)i(set)g (the)g(starting)g(p)s(osition)f(when)g(doing)g(wild)g(card)h(searc)m (hes.)41 b(A)0 5601 y(status)29 b(v)-5 b(alue)30 b(of)f(KEY)p 809 5601 V 32 w(NO)p 980 5601 V 33 w(EXIST)f(is)h(returned)e(if)i(the)g (sp)s(eci\014ed)f(k)m(eyw)m(ord)i(to)f(b)s(e)g(read)f(is)h(not)h(found) d(in)i(the)0 5714 y(header.)p eop end %%Page: 38 46 TeXDict begin 38 45 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.38) cvn H.B /DEST pdfmark end 0 299 a Fj(38)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)0 464 y SDict begin H.S end 0 464 a 0 464 a SDict begin 13.6 H.A end 0 464 a 0 464 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.5.4.1) cvn H.B /DEST pdfmark end 0 464 a 91 x Fd(5.4.1)112 b(Keyw)m(ord)38 b(Reading)g(Routines)0 764 y Fi(1)81 b Fj(Return)33 b(the)h(n)m(um)m(b)s(er)e(of)i(existing)h (k)m(eyw)m(ords)g(\(not)f(coun)m(ting)h(the)f(END)g(k)m(eyw)m(ord\))h (and)e(the)h(amoun)m(t)h(of)227 877 y(space)e(curren)m(tly)f(a)m(v)-5 b(ailable)34 b(for)e(more)g(k)m(eyw)m(ords.)46 b(It)32 b(returns)e(morek)m(eys)j(=)f(-1)g(if)g(the)g(header)g(has)g(not)227 990 y(y)m(et)27 b(b)s(een)d(closed.)40 b(Note)26 b(that)g(CFITSIO)d (will)j(dynamically)g(add)e(space)i(if)f(required)f(when)g(writing)h (new)227 1103 y(k)m(eyw)m(ords)32 b(to)g(a)f(header)g(so)h(in)f (practice)h(there)g(is)f(no)g(limit)h(to)g(the)f(n)m(um)m(b)s(er)f(of)i (k)m(eyw)m(ords)f(that)h(can)g(b)s(e)227 1216 y(added)e(to)h(a)f (header.)41 b(A)30 b(n)m(ull)g(p)s(oin)m(ter)h(ma)m(y)f(b)s(e)g(en)m (tered)h(for)f(the)g(morek)m(eys)h(parameter)g(if)f(it's)h(v)-5 b(alue)31 b(is)227 1329 y(not)g(needed.)95 1588 y Fe(int)47 b(fits_get_hdrspace)c(/)48 b(ffghsp)286 1701 y(\(fitsfile)e(*fptr,)g(>) h(int)g(*keysexist,)e(int)i(*morekeys,)e(int)i(*status\))0 1960 y Fi(2)81 b Fj(Return)28 b(the)h(sp)s(eci\014ed)f(k)m(eyw)m(ord.) 41 b(In)29 b(the)g(\014rst)f(routine,)i(the)f(datat)m(yp)s(e)h (parameter)g(sp)s(eci\014es)e(the)h(desired)227 2073 y(returned)e(data)h(t)m(yp)s(e)g(of)g(the)g(k)m(eyw)m(ord)h(v)-5 b(alue)28 b(and)f(can)h(ha)m(v)m(e)h(one)f(of)g(the)g(follo)m(wing)h (sym)m(b)s(olic)g(constan)m(t)227 2186 y(v)-5 b(alues:)47 b(TSTRING,)33 b(TLOGICAL)f(\(==)h(in)m(t\),)j(TBYTE,)d(TSHOR)-8 b(T,)33 b(TUSHOR)-8 b(T,)32 b(TINT,)h(TUINT,)227 2298 y(TLONG,)24 b(TULONG,)g(TLONGLONG,)g(TFLO)m(A)-8 b(T,)25 b(TDOUBLE,)f(TCOMPLEX,)f(and)h(TDBLCOM-)227 2411 y(PLEX.)j(Within)f (the)h(con)m(text)h(of)f(this)g(routine,)g(TSTRING)f(corresp)s(onds)f (to)i(a)g('c)m(har*')h(data)f(t)m(yp)s(e,)h(i.e.,)227 2524 y(a)k(p)s(oin)m(ter)g(to)g(a)g(c)m(haracter)i(arra)m(y)-8 b(.)45 b(Data)33 b(t)m(yp)s(e)f(con)m(v)m(ersion)h(will)f(b)s(e)f(p)s (erformed)f(for)i(n)m(umeric)f(v)-5 b(alues)32 b(if)227 2637 y(the)27 b(k)m(eyw)m(ord)g(v)-5 b(alue)27 b(do)s(es)f(not)h(ha)m (v)m(e)h(the)f(same)g(data)g(t)m(yp)s(e.)40 b(If)26 b(the)h(v)-5 b(alue)27 b(of)g(the)f(k)m(eyw)m(ord)i(is)e(unde\014ned)227 2750 y(\(i.e.,)31 b(the)e(v)-5 b(alue)30 b(\014eld)e(is)h(blank\))g (then)f(an)h(error)g(status)g(=)f(V)-10 b(ALUE)p 2627 2750 28 4 v 33 w(UNDEFINED)30 b(will)g(b)s(e)e(returned.)227 2900 y(The)c(second)f(routine)h(returns)f(the)h(k)m(eyw)m(ord)g(v)-5 b(alue)24 b(as)g(a)g(c)m(haracter)i(string)d(\(a)i(literal)g(cop)m(y)g (of)f(what)f(is)h(in)227 3013 y(the)j(v)-5 b(alue)26 b(\014eld\))g(regardless)h(of)f(the)g(in)m(trinsic)h(data)g(t)m(yp)s(e) f(of)g(the)g(k)m(eyw)m(ord.)40 b(The)26 b(third)f(routine)h(returns)227 3126 y(the)45 b(en)m(tire)h(80-c)m(haracter)i(header)c(record)h(of)g (the)g(k)m(eyw)m(ord,)k(with)c(an)m(y)g(trailing)h(blank)e(c)m (haracters)227 3239 y(stripp)s(ed)37 b(o\013.)64 b(The)38 b(fourth)f(routine)h(returns)f(the)h(\(next\))h(header)f(record)g(that) h(con)m(tains)g(the)f(literal)227 3352 y(string)31 b(of)f(c)m (haracters)i(sp)s(eci\014ed)e(b)m(y)g(the)g('string')h(argumen)m(t.)227 3502 y(If)f(a)h(NULL)f(commen)m(t)i(p)s(oin)m(ter)e(is)g(supplied)g (then)g(the)g(commen)m(t)i(string)e(will)h(not)f(b)s(e)g(returned.)95 3761 y Fe(int)47 b(fits_read_key)e(/)i(ffgky)286 3874 y(\(fitsfile)f(*fptr,)g(int)h(datatype,)e(char)i(*keyname,)e(>)i(DTYPE) g(*value,)334 3987 y(char)g(*comment,)e(int)i(*status\))95 4213 y(int)g(fits_read_keyword)c(/)48 b(ffgkey)286 4326 y(\(fitsfile)e(*fptr,)g(char)g(*keyname,)g(>)h(char)g(*value,)f(char)g (*comment,)334 4439 y(int)h(*status\))95 4664 y(int)g(fits_read_card)d (/)k(ffgcrd)286 4777 y(\(fitsfile)e(*fptr,)g(char)g(*keyname,)g(>)h (char)g(*card,)f(int)h(*status\))95 5003 y(int)g(fits_read_str)e(/)i (ffgstr)286 5116 y(\(fitsfile)f(*fptr,)g(char)g(*string,)g(>)h(char)g (*card,)f(int)h(*status\))0 5375 y Fi(3)81 b Fj(Read)22 b(a)g(string-v)-5 b(alued)23 b(k)m(eyw)m(ord)f(and)g(return)e(the)j (string)f(length,)i(the)e(v)-5 b(alue)23 b(string,)h(and/or)e(the)g (commen)m(t)227 5488 y(\014eld.)48 b(The)33 b(\014rst)f(routine,)i (\013gksl,)g(simply)e(returns)g(the)h(length)h(of)f(the)g(c)m(haracter) h(string)f(v)-5 b(alue)34 b(of)f(the)227 5601 y(sp)s(eci\014ed)g(k)m (eyw)m(ord.)50 b(The)32 b(second)i(routine,)g(\013gsky)-8 b(,)35 b(also)f(returns)e(up)g(to)i(maxc)m(har)g(c)m(haracters)g(of)g (the)227 5714 y(k)m(eyw)m(ord)d(v)-5 b(alue)31 b(string,)g(starting)g (with)g(the)f(\014rstc)m(har)g(c)m(haracter,)j(and)d(the)g(k)m(eyw)m (ord)h(commen)m(t)h(string)p eop end %%Page: 39 47 TeXDict begin 39 46 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.39) cvn H.B /DEST pdfmark end 0 299 a Fh(5.4.)72 b(HEADER)31 b(KEYW)m(ORD)g(READ/WRITE)g(R)m(OUTINES)1495 b Fj(39)227 555 y(\(unless)33 b(the)h(input)e(v)-5 b(alue)34 b(of)g(comm)f(=)g (NULL\).)h(The)f(v)-5 b(aluelen)34 b(argumen)m(t)g(returns)e(the)h (total)j(length)227 668 y(of)c(the)f(k)m(eyw)m(ord)h(v)-5 b(alue)32 b(string)f(regardless)h(of)f(ho)m(w)h(m)m(uc)m(h)f(of)h(the)f (string)g(is)h(actually)h(returned)d(\(whic)m(h)227 781 y(dep)s(ends)25 b(on)i(the)g(v)-5 b(alue)27 b(of)g(the)g(\014rstc)m (har)g(and)f(maxc)m(har)h(argumen)m(ts\).)40 b(Note)29 b(that)e(the)g(v)-5 b(alue)27 b(c)m(haracter)227 894 y(string)33 b(argumen)m(t)h(m)m(ust)f(b)s(e)f(allo)s(cated)j(large)g (enough)e(to)g(also)i(hold)d(the)i(n)m(ull)f(terminator)g(at)h(the)g (end)227 1007 y(of)41 b(the)f(returned)f(string.)69 b(These)40 b(routines)g(supp)s(ort)f(string)h(k)m(eyw)m(ords)g(that)h(use)e(the)i (CONTINUE)227 1120 y(con)m(v)m(en)m(tion)25 b(to)e(con)m(tin)m(ue)g (long)g(string)f(v)-5 b(alues)23 b(o)m(v)m(er)h(m)m(ultiple)f(FITS)e (header)h(records.)38 b(Normally)-8 b(,)26 b(string-)227 1233 y(v)-5 b(alued)40 b(k)m(eyw)m(ords)h(ha)m(v)m(e)g(a)g(maxim)m(um)f (length)h(of)f(68)h(c)m(haracters,)k(ho)m(w)m(ev)m(er,)f(CONTINUE'd)39 b(string)227 1346 y(k)m(eyw)m(ords)31 b(ma)m(y)g(b)s(e)f(arbitrarily)g (long.)95 1630 y Fe(int)47 b(fits_get_key_strlen)c(/)k(ffgksl)286 1742 y(\(fitsfile)f(*fptr,)g(const)g(char)h(*keyname,)e(int)i(*length,) e(int)i(*status\);)95 1968 y(int)g(fits_read_string_key)c(/)k(ffgsky) 334 2081 y(\(fitsfile)e(*fptr,)h(const)h(char)f(*keyname,)g(int)h (firstchar,)e(int)i(maxchar,)334 2194 y(char)g(*value,)f(int)g (*valuelen,)f(char)i(*comm,)f(int)h(*status\);)0 2478 y Fi(4)81 b Fj(Return)38 b(the)h(n)m(th)f(header)h(record)g(in)f(the)i (CHU.)f(The)f(\014rst)g(k)m(eyw)m(ord)i(in)e(the)h(header)g(is)g(at)g (k)m(eyn)m(um)g(=)227 2591 y(1;)53 b(if)45 b(k)m(eyn)m(um)g(=)f(0)h (then)g(these)g(routines)g(simply)f(reset)h(the)h(in)m(ternal)f (CFITSIO)e(p)s(oin)m(ter)i(to)h(the)227 2704 y(b)s(eginning)35 b(of)h(the)g(header)f(so)h(that)g(subsequen)m(t)f(k)m(eyw)m(ord)h(op)s (erations)g(will)g(start)g(at)g(the)g(top)g(of)g(the)227 2817 y(header)26 b(\(e.g.,)j(prior)c(to)h(searc)m(hing)h(for)f(k)m(eyw) m(ords)g(using)f(wild)g(cards)h(in)f(the)h(k)m(eyw)m(ord)h(name\).)39 b(The)26 b(\014rst)227 2930 y(routine)32 b(returns)e(the)i(en)m(tire)h (80-c)m(haracter)h(header)e(record)g(\(with)f(trailing)i(blanks)e (truncated\),)i(while)227 3043 y(the)41 b(second)f(routine)g(parses)g (the)g(record)h(and)e(returns)g(the)i(name,)i(v)-5 b(alue,)43 b(and)d(commen)m(t)h(\014elds)f(as)227 3156 y(separate)32 b(\(blank)f(truncated\))g(c)m(haracter)i(strings.)42 b(If)30 b(a)h(NULL)g(commen)m(t)h(p)s(oin)m(ter)f(is)g(giv)m(en)h(on)f (input,)227 3268 y(then)f(the)h(commen)m(t)g(string)g(will)f(not)h(b)s (e)f(returned.)95 3553 y Fe(int)47 b(fits_read_record)d(/)j(ffgrec)286 3665 y(\(fitsfile)f(*fptr,)g(int)h(keynum,)e(>)j(char)f(*card,)f(int)h (*status\))95 3891 y(int)g(fits_read_keyn)d(/)k(ffgkyn)286 4004 y(\(fitsfile)e(*fptr,)g(int)h(keynum,)e(>)j(char)f(*keyname,)e (char)h(*value,)334 4117 y(char)h(*comment,)e(int)i(*status\))0 4401 y Fi(5)81 b Fj(Return)44 b(the)i(next)g(k)m(eyw)m(ord)g(whose)f (name)h(matc)m(hes)g(one)g(of)g(the)f(strings)h(in)f('inclist')i(but)e (do)s(es)g(not)227 4514 y(matc)m(h)31 b(an)m(y)g(of)g(the)f(strings)g (in)g('exclist'.)43 b(The)30 b(strings)g(in)g(inclist)h(and)f(exclist)i (ma)m(y)e(con)m(tain)i(wild)e(card)227 4627 y(c)m(haracters)k(\(*,)f (?,)f(and)f(#\))h(as)g(describ)s(ed)f(at)i(the)f(b)s(eginning)f(of)h (this)g(section.)46 b(This)31 b(routine)h(searc)m(hes)227 4740 y(from)j(the)g(curren)m(t)g(header)g(p)s(osition)g(to)h(the)f(end) f(of)h(the)h(header,)g(only)-8 b(,)37 b(and)d(do)s(es)h(not)g(con)m (tin)m(ue)i(the)227 4853 y(searc)m(h)32 b(from)e(the)h(top)g(of)g(the)g (header)g(bac)m(k)g(to)h(the)f(original)h(p)s(osition.)42 b(The)31 b(curren)m(t)f(header)h(p)s(osition)227 4966 y(ma)m(y)e(b)s(e)e(reset)h(with)g(the)g(\013grec)g(routine.)40 b(Note)29 b(that)g(nexc)f(ma)m(y)g(b)s(e)f(set)h(=)g(0)g(if)g(there)g (are)g(no)g(k)m(eyw)m(ords)227 5079 y(to)h(b)s(e)f(excluded.)39 b(This)28 b(routine)g(returns)f(status)h(=)g(KEY)p 2268 5079 28 4 v 32 w(NO)p 2439 5079 V 33 w(EXIST)f(if)h(a)h(matc)m(hing)g (k)m(eyw)m(ord)g(is)f(not)227 5191 y(found.)95 5475 y Fe(int)47 b(fits_find_nextkey)c(/)48 b(ffgnxk)286 5588 y(\(fitsfile)e(*fptr,)g(char)g(**inclist,)f(int)i(ninc,)g(char)f (**exclist,)334 5701 y(int)h(nexc,)f(>)i(char)e(*card,)h(int)94 b(*status\))p eop end %%Page: 40 48 TeXDict begin 40 47 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.40) cvn H.B /DEST pdfmark end 0 299 a Fj(40)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)0 555 y Fi(6)81 b Fj(Return)25 b(the)h(ph)m(ysical)g (units)g(string)g(from)f(an)h(existing)h(k)m(eyw)m(ord.)39 b(This)26 b(routine)g(uses)f(a)h(lo)s(cal)i(con)m(v)m(en)m(tion,)227 668 y(sho)m(wn)d(in)g(the)g(follo)m(wing)i(example,)g(in)e(whic)m(h)g (the)h(k)m(eyw)m(ord)f(units)g(are)h(enclosed)g(in)f(square)g(brac)m(k) m(ets)h(in)227 781 y(the)k(b)s(eginning)f(of)h(the)g(k)m(eyw)m(ord)g (commen)m(t)g(\014eld.)40 b(A)30 b(n)m(ull)g(string)f(is)h(returned)e (if)i(no)f(units)g(are)h(de\014ned)227 894 y(for)g(the)h(k)m(eyw)m (ord.)239 1135 y Fe(VELOCITY=)809 b(12.3)46 b(/)i([km/s])e(orbital)g (speed)95 1361 y(int)h(fits_read_key_unit)c(/)48 b(ffgunt)286 1474 y(\(fitsfile)e(*fptr,)g(char)g(*keyname,)g(>)h(char)g(*unit,)f (int)h(*status\))0 1715 y Fi(7)81 b Fj(Concatenate)39 b(the)f(header)f(k)m(eyw)m(ords)h(in)g(the)f(CHDU)h(in)m(to)h(a)f (single)g(long)g(string)g(of)g(c)m(haracters.)64 b(This)227 1828 y(pro)m(vides)28 b(a)h(con)m(v)m(enien)m(t)h(w)m(a)m(y)f(of)g (passing)f(all)h(or)f(part)g(of)g(the)h(header)f(information)g(in)g(a)h (FITS)e(HDU)i(to)227 1941 y(other)i(subroutines.)39 b(Eac)m(h)31 b(80-c)m(haracter)h(\014xed-length)f(k)m(eyw)m(ord)f(record)g(is)g(app) s(ended)e(to)j(the)f(output)227 2054 y(c)m(haracter)j(string,)f(in)f (order,)g(with)g(no)g(in)m(terv)m(ening)i(separator)f(or)f(terminating) h(c)m(haracters.)45 b(The)31 b(last)227 2167 y(header)e(record)g(is)g (terminated)h(with)f(a)g(NULL)g(c)m(haracter.)42 b(These)29 b(routine)g(allo)s(cates)j(memory)d(for)g(the)227 2279 y(returned)k(c)m(haracter)j(arra)m(y)-8 b(,)37 b(so)d(the)h(calling)h (program)e(m)m(ust)g(free)g(the)h(memory)f(when)f(\014nished.)51 b(The)227 2392 y(cleanest)32 b(w)m(a)m(y)g(to)f(do)f(this)g(is)h(to)g (call)g(the)g(\014ts)p 1823 2392 28 4 v 32 w(free)p 1999 2392 V 33 w(memory)g(routine.)227 2540 y(There)38 b(are)h(2)g(related)g (routines:)57 b(\014ts)p 1581 2540 V 32 w(hdr2str)37 b(simply)h(concatenates)j(all)f(the)e(existing)i(k)m(eyw)m(ords)e(in) 227 2652 y(the)44 b(header;)51 b(\014ts)p 863 2652 V 33 w(con)m(v)m(ert)p 1185 2652 V 34 w(hdr2str)43 b(is)h(similar,)k (except)d(that)f(if)g(the)g(CHDU)h(is)f(a)g(tile)h(compressed)227 2765 y(image)c(\(stored)f(in)f(a)h(binary)e(table\))j(then)e(it)h(will) f(\014rst)g(con)m(v)m(ert)i(that)f(header)f(bac)m(k)h(to)g(that)g(of)g (the)227 2878 y(corresp)s(onding)30 b(normal)g(FITS)g(image)h(b)s (efore)f(concatenating)j(the)e(k)m(eyw)m(ords.)227 3025 y(Selected)f(k)m(eyw)m(ords)e(ma)m(y)h(b)s(e)e(excluded)h(from)g(the)g (returned)f(c)m(haracter)j(string.)40 b(If)27 b(the)i(second)f(param-) 227 3138 y(eter)h(\(no)s(commen)m(ts\))g(is)f(TR)m(UE)g(\(nonzero\))h (then)e(an)m(y)i(COMMENT,)f(HISTOR)-8 b(Y,)27 b(or)h(blank)g(k)m(eyw)m (ords)227 3251 y(in)i(the)h(header)f(will)h(not)f(b)s(e)g(copied)h(to)g (the)g(output)f(string.)227 3398 y(The)25 b('exclist')j(parameter)e(ma) m(y)g(b)s(e)f(used)g(to)h(supply)e(a)i(list)h(of)e(k)m(eyw)m(ords)h (that)h(are)f(to)g(b)s(e)f(excluded)g(from)227 3511 y(the)k(output)g(c) m(haracter)h(string.)41 b(Wild)29 b(card)g(c)m(haracters)h(\(*,)g(?,)f (and)g(#\))g(ma)m(y)g(b)s(e)f(used)g(in)h(the)g(excluded)227 3624 y(k)m(eyw)m(ord)h(names.)41 b(If)29 b(no)g(additional)i(k)m(eyw)m (ords)f(are)g(to)g(b)s(e)f(excluded,)h(then)f(set)h(nexc)g(=)f(0)h(and) f(sp)s(ecify)227 3737 y(NULL)i(for)f(the)g(the)h(**exclist)i (parameter.)95 3978 y Fe(int)47 b(fits_hdr2str)e(/)i(ffhdr2str)286 4091 y(\(fitsfile)f(*fptr,)g(int)h(nocomments,)d(char)j(**exclist,)e (int)i(nexc,)286 4204 y(>)h(char)e(**header,)g(int)h(*nkeys,)e(int)i (*status\))95 4430 y(int)g(fits_convert_hdr2str)c(/)k(ffcnvthdr2str)286 4543 y(\(fitsfile)f(*fptr,)g(int)h(nocomments,)d(char)j(**exclist,)e (int)i(nexc,)286 4656 y(>)h(char)e(**header,)g(int)h(*nkeys,)e(int)i (*status\))95 4882 y(int)g(fits_free_memory)d(/)j(fffree)286 4994 y(\(char)g(*header,)e(>)j(int)f(*status\);)0 5232 y SDict begin H.S end 0 5232 a 0 5232 a SDict begin 13.6 H.A end 0 5232 a 0 5232 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.5.4.2) cvn H.B /DEST pdfmark end 0 5232 a 163 x Fd(5.4.2)112 b(Keyw)m(ord)38 b(W)-9 b(riting)37 b(Routines)0 5601 y Fi(1)81 b Fj(W)-8 b(rite)32 b(a)g(k)m(eyw)m(ord)g(of)f(the)h (appropriate)f(data)h(t)m(yp)s(e)g(in)m(to)g(the)g(CHU.)f(The)g (\014rst)g(routine)g(simply)g(app)s(ends)227 5714 y(a)j(new)f(k)m(eyw)m (ord)h(whereas)f(the)g(second)h(routine)f(will)h(up)s(date)e(the)i(v)-5 b(alue)33 b(and)g(commen)m(t)h(\014elds)f(of)h(the)p eop end %%Page: 41 49 TeXDict begin 41 48 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.41) cvn H.B /DEST pdfmark end 0 299 a Fh(5.4.)72 b(HEADER)31 b(KEYW)m(ORD)g(READ/WRITE)g(R)m(OUTINES)1495 b Fj(41)227 555 y(k)m(eyw)m(ord)34 b(if)g(it)g(already)g(exists,)h(otherwise)f(it)g (app)s(ends)e(a)i(new)f(k)m(eyw)m(ord.)51 b(Note)35 b(that)f(the)g (address)e(to)227 668 y(the)37 b(v)-5 b(alue,)38 b(and)d(not)i(the)f(v) -5 b(alue)36 b(itself,)j(m)m(ust)d(b)s(e)f(en)m(tered.)59 b(The)35 b(datat)m(yp)s(e)i(parameter)g(sp)s(eci\014es)f(the)227 781 y(data)25 b(t)m(yp)s(e)f(of)g(the)g(k)m(eyw)m(ord)g(v)-5 b(alue)25 b(with)e(one)h(of)g(the)g(follo)m(wing)i(v)-5 b(alues:)37 b(TSTRING,)23 b(TLOGICAL)g(\(==)227 894 y(in)m(t\),)38 b(TBYTE,)d(TSHOR)-8 b(T,)34 b(TUSHOR)-8 b(T,)35 b(TINT,)f(TUINT,)h (TLONG,)g(TLONGLONG,)g(TULONG,)227 1007 y(TFLO)m(A)-8 b(T,)24 b(TDOUBLE.)f(Within)h(the)f(con)m(text)i(of)f(this)f(routine,)i (TSTRING)d(corresp)s(onds)g(to)i(a)g('c)m(har*')227 1120 y(data)j(t)m(yp)s(e,)h(i.e.,)g(a)f(p)s(oin)m(ter)f(to)i(a)e(c)m (haracter)i(arra)m(y)-8 b(.)41 b(A)26 b(n)m(ull)g(p)s(oin)m(ter)h(ma)m (y)g(b)s(e)e(en)m(tered)i(for)f(the)h(commen)m(t)227 1233 y(parameter)k(in)f(whic)m(h)g(case)i(the)e(k)m(eyw)m(ord)h(commen) m(t)h(\014eld)d(will)i(b)s(e)f(unmo)s(di\014ed)e(or)j(left)g(blank.)95 1515 y Fe(int)47 b(fits_write_key)d(/)k(ffpky)286 1628 y(\(fitsfile)e(*fptr,)g(int)h(datatype,)e(char)i(*keyname,)e(DTYPE)h (*value,)477 1741 y(char)h(*comment,)e(>)j(int)f(*status\))95 1967 y(int)g(fits_update_key)d(/)j(ffuky)286 2080 y(\(fitsfile)f (*fptr,)g(int)h(datatype,)e(char)i(*keyname,)e(DTYPE)h(*value,)477 2193 y(char)h(*comment,)e(>)j(int)f(*status\))0 2475 y Fi(2)81 b Fj(W)-8 b(rite)44 b(a)g(k)m(eyw)m(ord)f(with)g(a)h(n)m(ull) f(or)g(unde\014ned)e(v)-5 b(alue)43 b(\(i.e.,)48 b(the)c(v)-5 b(alue)43 b(\014eld)g(in)g(the)g(k)m(eyw)m(ord)h(is)f(left)227 2588 y(blank\).)70 b(The)40 b(\014rst)f(routine)h(simply)g(app)s(ends)e (a)j(new)e(k)m(eyw)m(ord)i(whereas)f(the)g(second)g(routine)h(will)227 2701 y(up)s(date)27 b(the)h(v)-5 b(alue)29 b(and)e(commen)m(t)i (\014elds)e(of)h(the)g(k)m(eyw)m(ord)g(if)g(it)g(already)h(exists,)g (otherwise)f(it)h(app)s(ends)227 2814 y(a)g(new)g(k)m(eyw)m(ord.)40 b(A)29 b(n)m(ull)g(p)s(oin)m(ter)g(ma)m(y)g(b)s(e)g(en)m(tered)g(for)g (the)g(commen)m(t)g(parameter)h(in)e(whic)m(h)h(case)h(the)227 2927 y(k)m(eyw)m(ord)h(commen)m(t)h(\014eld)d(will)i(b)s(e)f(unmo)s (di\014ed)e(or)j(left)g(blank.)95 3209 y Fe(int)47 b (fits_write_key_null)c(/)k(ffpkyu)286 3322 y(\(fitsfile)f(*fptr,)g (char)g(*keyname,)g(char)g(*comment,)g(>)h(int)g(*status\))95 3548 y(int)g(fits_update_key_null)c(/)k(ffukyu)286 3661 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(char)g(*comment,)g(>)h(int)g (*status\))0 3943 y Fi(3)81 b Fj(W)-8 b(rite)40 b(\(app)s(end\))e(a)h (COMMENT)g(or)g(HISTOR)-8 b(Y)38 b(k)m(eyw)m(ord)i(to)f(the)g(CHU.)h (The)e(commen)m(t)i(or)f(history)227 4056 y(string)31 b(will)f(b)s(e)g(con)m(tin)m(ued)h(o)m(v)m(er)h(m)m(ultiple)f(k)m(eyw)m (ords)g(if)f(it)h(is)f(longer)h(than)f(70)i(c)m(haracters.)95 4338 y Fe(int)47 b(fits_write_comment)c(/)48 b(ffpcom)286 4451 y(\(fitsfile)e(*fptr,)g(char)g(*comment,)g(>)h(int)g(*status\))95 4677 y(int)g(fits_write_history)c(/)48 b(ffphis)286 4790 y(\(fitsfile)e(*fptr,)g(char)g(*history,)g(>)h(int)g(*status\))0 5073 y Fi(4)81 b Fj(W)-8 b(rite)29 b(the)g(D)m(A)-8 b(TE)29 b(k)m(eyw)m(ord)g(to)g(the)g(CHU.)f(The)g(k)m(eyw)m(ord)h(v)-5 b(alue)29 b(will)f(con)m(tain)i(the)f(curren)m(t)f(system)g(date)227 5185 y(as)k(a)g(c)m(haracter)h(string)e(in)g('yyyy-mm-ddThh:mm:ss')e (format.)44 b(If)31 b(a)h(D)m(A)-8 b(TE)32 b(k)m(eyw)m(ord)g(already)g (exists)227 5298 y(in)c(the)f(header,)i(then)e(this)g(routine)h(will)g (simply)f(up)s(date)g(the)h(k)m(eyw)m(ord)g(v)-5 b(alue)28 b(with)f(the)h(curren)m(t)g(date.)95 5581 y Fe(int)47 b(fits_write_date)d(/)j(ffpdat)286 5694 y(\(fitsfile)f(*fptr,)g(>)h (int)g(*status\))p eop end %%Page: 42 50 TeXDict begin 42 49 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.42) cvn H.B /DEST pdfmark end 0 299 a Fj(42)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)0 555 y Fi(5)81 b Fj(W)-8 b(rite)34 b(a)g(user)f(sp)s (eci\014ed)g(k)m(eyw)m(ord)h(record)f(in)m(to)h(the)g(CHU.)g(This)e(is) i(a)g(lo)m(w{lev)m(el)i(routine)e(whic)m(h)f(can)h(b)s(e)227 668 y(used)f(to)h(write)f(an)m(y)h(arbitrary)f(record)g(in)m(to)i(the)e (header.)50 b(The)32 b(record)i(m)m(ust)f(conform)g(to)h(the)g(all)g (the)227 781 y(FITS)c(format)h(requiremen)m(ts.)95 1034 y Fe(int)47 b(fits_write_record)c(/)48 b(ffprec)286 1147 y(\(fitsfile)e(*fptr,)g(char)g(*card,)g(>)i(int)f(*status\))0 1401 y Fi(6)81 b Fj(Up)s(date)34 b(an)g(80-c)m(haracter)j(record)e(in)f (the)g(CHU.)h(If)f(a)h(k)m(eyw)m(ord)f(with)h(the)f(input)g(name)g (already)h(exists,)227 1514 y(then)e(it)h(is)f(o)m(v)m(erwritten)h(b)m (y)f(the)g(v)-5 b(alue)34 b(of)f(card.)49 b(This)32 b(could)h(mo)s (dify)f(the)i(k)m(eyw)m(ord)f(name)g(as)h(w)m(ell)g(as)227 1627 y(the)c(v)-5 b(alue)30 b(and)e(commen)m(t)j(\014elds.)40 b(If)29 b(the)g(k)m(eyw)m(ord)h(do)s(esn't)f(already)h(exist)g(then)g (a)f(new)g(k)m(eyw)m(ord)h(card)227 1739 y(is)h(app)s(ended)d(to)j(the) g(header.)95 1993 y Fe(int)47 b(fits_update_card)d(/)j(ffucrd)286 2106 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(char)g(*card,)g(>)i (int)f(*status\))0 2359 y Fi(7)81 b Fj(Mo)s(dify)30 b(\(o)m(v)m (erwrite\))i(the)f(commen)m(t)g(\014eld)f(of)h(an)f(existing)h(k)m(eyw) m(ord.)95 2613 y Fe(int)47 b(fits_modify_comment)c(/)k(ffmcom)286 2726 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(char)g(*comment,)g(>)h (int)g(*status\))0 2979 y Fi(8)81 b Fj(W)-8 b(rite)33 b(the)f(ph)m(ysical)h(units)f(string)g(in)m(to)h(an)f(existing)h(k)m (eyw)m(ord.)46 b(This)32 b(routine)g(uses)g(a)g(lo)s(cal)i(con)m(v)m (en)m(tion,)227 3092 y(sho)m(wn)e(in)g(the)h(follo)m(wing)h(example,)g (in)e(whic)m(h)g(the)h(k)m(eyw)m(ord)g(units)f(are)h(enclosed)g(in)f (square)g(brac)m(k)m(ets)227 3205 y(in)e(the)h(b)s(eginning)f(of)g(the) h(k)m(eyw)m(ord)g(commen)m(t)g(\014eld.)239 3458 y Fe(VELOCITY=)809 b(12.3)46 b(/)i([km/s])e(orbital)g(speed)95 3684 y(int)h (fits_write_key_unit)c(/)k(ffpunt)286 3797 y(\(fitsfile)f(*fptr,)g (char)g(*keyname,)g(char)g(*unit,)g(>)i(int)f(*status\))0 4050 y Fi(9)81 b Fj(Rename)30 b(an)h(existing)g(k)m(eyw)m(ord,)g (preserving)f(the)g(curren)m(t)h(v)-5 b(alue)30 b(and)g(commen)m(t)i (\014elds.)95 4304 y Fe(int)47 b(fits_modify_name)d(/)j(ffmnam)286 4417 y(\(fitsfile)f(*fptr,)g(char)g(*oldname,)g(char)g(*newname,)g(>)h (int)g(*status\))0 4670 y Fi(10)f Fj(Delete)37 b(a)e(k)m(eyw)m(ord)g (record.)54 b(The)34 b(space)i(o)s(ccupied)e(b)m(y)h(the)g(k)m(eyw)m (ord)g(is)g(reclaimed)h(b)m(y)e(mo)m(ving)i(all)g(the)227 4783 y(follo)m(wing)e(header)f(records)f(up)g(one)h(ro)m(w)f(in)h(the)f (header.)48 b(The)32 b(\014rst)g(routine)g(deletes)i(a)f(k)m(eyw)m(ord) g(at)h(a)227 4896 y(sp)s(eci\014ed)23 b(p)s(osition)h(in)g(the)g (header)f(\(the)i(\014rst)e(k)m(eyw)m(ord)h(is)g(at)g(p)s(osition)g (1\),)i(whereas)e(the)g(second)g(routine)227 5009 y(deletes)30 b(a)f(sp)s(eci\014cally)g(named)f(k)m(eyw)m(ord.)41 b(Wild)29 b(card)f(c)m(haracters)i(ma)m(y)f(b)s(e)f(used)g(when)f(sp)s(ecifying)i (the)227 5122 y(name)23 b(of)g(the)f(k)m(eyw)m(ord)h(to)h(b)s(e)e (deleted.)38 b(The)22 b(third)g(routine)h(deletes)g(the)g(\(next\))h(k) m(eyw)m(ord)f(that)g(con)m(tains)227 5235 y(the)31 b(literal)h(c)m (haracter)g(string)e(sp)s(eci\014ed)g(b)m(y)g(the)h('string')f(argumen) m(t.)95 5488 y Fe(int)47 b(fits_delete_record)c(/)48 b(ffdrec)286 5601 y(\(fitsfile)e(*fptr,)g(int)142 b(keynum,)94 b(>)47 b(int)g(*status\))p eop end %%Page: 43 51 TeXDict begin 43 50 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.43) cvn H.B /DEST pdfmark end 0 299 a Fh(5.5.)72 b(PRIMAR)-8 b(Y)31 b(ARRA)-8 b(Y)31 b(OR)f(IMA)m(GE)h(EXTENSION)f(I/O)g(R)m (OUTINES)1011 b Fj(43)95 555 y Fe(int)47 b(fits_delete_key)d(/)j (ffdkey)286 668 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(>)h(int)g (*status\))95 894 y(int)g(fits_delete_str)d(/)j(ffdstr)286 1007 y(\(fitsfile)f(*fptr,)g(char)g(*string,)g(>)h(int)g(*status\))0 1157 y SDict begin H.S end 0 1157 a 0 1157 a SDict begin 13.6 H.A end 0 1157 a 0 1157 a SDict begin [ /View [/XYZ H.V] /Dest (section.5.5) cvn H.B /DEST pdfmark end 0 1157 a 177 x Ff(5.5)135 b(Primary)46 b(Arra)l(y)f(or)g(IMA)l(GE)f(Extension)i(I/O) f(Routines)0 1584 y Fj(These)22 b(routines)g(read)h(or)f(write)h(data)g (v)-5 b(alues)23 b(in)f(the)g(primary)g(data)h(arra)m(y)g(\(i.e.,)j (the)c(\014rst)g(HDU)h(in)f(a)h(FITS)e(\014le\))0 1697 y(or)32 b(an)g(IMA)m(GE)h(extension.)47 b(There)31 b(are)i(also)g (routines)f(to)h(get)g(information)f(ab)s(out)g(the)g(data)h(t)m(yp)s (e)g(and)e(size)0 1810 y(of)c(the)g(image.)41 b(Users)27 b(should)f(also)i(read)f(the)g(follo)m(wing)h(c)m(hapter)g(on)f(the)g (CFITSIO)e(iterator)k(function)d(whic)m(h)0 1923 y(pro)m(vides)33 b(a)h(more)f(`ob)5 b(ject)35 b(orien)m(ted')f(metho)s(d)f(of)g(reading) g(and)g(writing)g(images.)51 b(The)32 b(iterator)j(function)e(is)0 2035 y(a)e(little)i(more)e(complicated)h(to)g(use,)f(but)f(the)h(adv)-5 b(an)m(tages)32 b(are)f(that)h(it)f(usually)g(tak)m(es)h(less)f(co)s (de)g(to)g(p)s(erform)0 2148 y(the)37 b(same)f(op)s(eration,)j(and)c (the)i(resulting)f(program)g(often)h(runs)e(faster)i(b)s(ecause)f(the)g (FITS)g(\014les)g(are)h(read)0 2261 y(and)30 b(written)g(using)g(the)h (most)f(e\016cien)m(t)i(blo)s(c)m(k)f(size.)0 2421 y(C)25 b(programmers)h(should)f(note)h(that)g(the)h(ordering)e(of)h(arra)m(ys) g(in)g(FITS)f(\014les,)i(and)e(hence)h(in)g(all)g(the)g(CFITSIO)0 2534 y(calls,)40 b(is)d(more)g(similar)h(to)f(the)h(dimensionalit)m(y)g (of)f(arra)m(ys)g(in)g(F)-8 b(ortran)38 b(rather)f(than)f(C.)h(F)-8 b(or)38 b(instance)g(if)f(a)0 2647 y(FITS)28 b(image)i(has)e(NAXIS1)h (=)f(100)i(and)e(NAXIS2)h(=)f(50,)i(then)e(a)h(2-D)h(arra)m(y)f(just)f (large)i(enough)e(to)i(hold)e(the)0 2760 y(image)k(should)d(b)s(e)h (declared)h(as)f(arra)m(y[50][100])k(and)c(not)h(as)f(arra)m (y[100][50].)0 2920 y(The)h(`datat)m(yp)s(e')h(parameter)g(sp)s (eci\014es)e(the)i(data)g(t)m(yp)s(e)f(of)g(the)g(`n)m(ulv)-5 b(al')32 b(and)f(`arra)m(y')h(p)s(oin)m(ters)f(and)f(can)i(ha)m(v)m(e)0 3033 y(one)h(of)g(the)g(follo)m(wing)h(v)-5 b(alues:)46 b(TBYTE,)33 b(TSBYTE,)f(TSHOR)-8 b(T,)32 b(TUSHOR)-8 b(T,)32 b(TINT,)h(TUINT,)f(TLONG,)0 3146 y(TLONGLONG,)26 b(TULONG,)g(TFLO)m(A)-8 b(T,)27 b(TDOUBLE.)f(Automatic)i(data)f(t)m(yp) s(e)g(con)m(v)m(ersion)g(is)f(p)s(erformed)f(if)0 3259 y(the)j(data)h(t)m(yp)s(e)f(of)f(the)i(FITS)e(arra)m(y)h(\(as)g (de\014ned)f(b)m(y)h(the)g(BITPIX)f(k)m(eyw)m(ord\))i(di\013ers)e(from) h(that)g(sp)s(eci\014ed)f(b)m(y)0 3372 y('datat)m(yp)s(e'.)54 b(The)34 b(data)h(v)-5 b(alues)35 b(are)f(also)i(automatically)h (scaled)e(b)m(y)f(the)h(BSCALE)f(and)f(BZER)m(O)h(k)m(eyw)m(ord)0 3485 y(v)-5 b(alues)31 b(as)f(they)h(are)g(b)s(eing)f(read)g(or)g (written)h(in)f(the)g(FITS)g(arra)m(y)-8 b(.)0 3701 y Fi(1)81 b Fj(Get)33 b(the)f(data)h(t)m(yp)s(e)f(or)g(equiv)-5 b(alen)m(t)34 b(data)f(t)m(yp)s(e)f(of)g(the)h(image.)47 b(The)32 b(\014rst)f(routine)h(returns)f(the)h(ph)m(ysical)227 3814 y(data)46 b(t)m(yp)s(e)f(of)h(the)f(FITS)f(image,)51 b(as)45 b(giv)m(en)h(b)m(y)f(the)g(BITPIX)g(k)m(eyw)m(ord,)50 b(with)44 b(allo)m(w)m(ed)j(v)-5 b(alues)46 b(of)227 3927 y(BYTE)p 492 3927 28 4 v 33 w(IMG)23 b(\(8\),)i(SHOR)-8 b(T)p 1215 3927 V 32 w(IMG)23 b(\(16\),)i(LONG)p 1934 3927 V 33 w(IMG)e(\(32\),)i(LONGLONG)p 2921 3927 V 33 w(IMG)e(\(64\),)i(FLO)m(A)-8 b(T)p 3684 3927 V 33 w(IMG)227 4040 y(\(-32\),)31 b(and)c(DOUBLE)p 1043 4040 V 33 w(IMG)h(\(-64\).)42 b(The)27 b(second)h(routine)f(is)h(similar,)h(except)g(that)f(if)g(the) g(image)h(pixel)227 4153 y(v)-5 b(alues)33 b(are)g(scaled,)g(with)f (non-default)h(v)-5 b(alues)32 b(for)g(the)h(BZER)m(O)f(and)g(BSCALE)f (k)m(eyw)m(ords,)j(then)e(the)227 4266 y(routine)j(will)g(return)e(the) i('equiv)-5 b(alen)m(t')36 b(data)f(t)m(yp)s(e)g(that)g(is)f(needed)h (to)g(store)g(the)g(scaled)g(v)-5 b(alues.)53 b(F)-8 b(or)227 4378 y(example,)29 b(if)e(BITPIX)g(=)g(16)h(and)f(BSCALE)f(=)h (0.1)h(then)f(the)h(equiv)-5 b(alen)m(t)28 b(data)g(t)m(yp)s(e)g(is)f (FLO)m(A)-8 b(T)p 3659 4378 V 33 w(IMG.)227 4491 y(Similarly)25 b(if)f(BITPIX)g(=)g(16,)i(BSCALE)e(=)g(1,)i(and)d(BZER)m(O)h(=)g (32768,)k(then)c(the)g(the)h(pixel)f(v)-5 b(alues)25 b(span)227 4604 y(the)31 b(range)g(of)f(an)g(unsigned)g(short)g(in)m (teger)h(and)f(the)h(returned)e(data)i(t)m(yp)s(e)g(will)f(b)s(e)g (USHOR)-8 b(T)p 3572 4604 V 32 w(IMG.)95 4820 y Fe(int)47 b(fits_get_img_type)c(/)48 b(ffgidt)286 4933 y(\(fitsfile)e(*fptr,)g(>) h(int)g(*bitpix,)f(int)h(*status\))95 5159 y(int)g (fits_get_img_equivtype)42 b(/)48 b(ffgiet)286 5272 y(\(fitsfile)e (*fptr,)g(>)h(int)g(*bitpix,)f(int)h(*status\))0 5488 y Fi(2)81 b Fj(Get)34 b(the)g(n)m(um)m(b)s(er)e(of)i(dimensions,)g (and/or)g(the)g(size)g(of)g(eac)m(h)h(dimension)e(in)g(the)h(image)h(.) 50 b(The)33 b(n)m(um)m(b)s(er)227 5601 y(of)h(axes)f(in)g(the)g(image)i (is)e(giv)m(en)h(b)m(y)f(naxis,)h(and)f(the)g(size)h(of)f(eac)m(h)i (dimension)d(is)h(giv)m(en)h(b)m(y)f(the)h(naxes)227 5714 y(arra)m(y)d(\(a)g(maxim)m(um)g(of)f(maxdim)g(dimensions)g(will)g (b)s(e)g(returned\).)p eop end %%Page: 44 52 TeXDict begin 44 51 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.44) cvn H.B /DEST pdfmark end 0 299 a Fj(44)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)95 555 y Fe(int)47 b(fits_get_img_dim)d(/)j(ffgidm)286 668 y(\(fitsfile)f(*fptr,)g(>)h(int)g(*naxis,)f(int)h(*status\))95 894 y(int)g(fits_get_img_size)c(/)48 b(ffgisz)286 1007 y(\(fitsfile)e(*fptr,)g(int)h(maxdim,)e(>)j(long)f(*naxes,)e(int)i (*status\))95 1233 y(int)g(fits_get_img_sizell)c(/)k(ffgiszll)286 1346 y(\(fitsfile)f(*fptr,)g(int)h(maxdim,)e(>)j(LONGLONG)d(*naxes,)h (int)h(*status\))95 1571 y(int)g(fits_get_img_param)c(/)48 b(ffgipr)286 1684 y(\(fitsfile)e(*fptr,)g(int)h(maxdim,)e(>)j(int)f (*bitpix,)e(int)i(*naxis,)f(long)h(*naxes,)334 1797 y(int)g(*status\)) 95 2023 y(int)g(fits_get_img_paramll)c(/)k(ffgiprll)286 2136 y(\(fitsfile)f(*fptr,)g(int)h(maxdim,)e(>)j(int)f(*bitpix,)e(int)i (*naxis,)f(LONGLONG)g(*naxes,)334 2249 y(int)h(*status\))0 2504 y Fi(3)81 b Fj(Create)23 b(a)f(new)g(primary)f(arra)m(y)i(or)f (IMA)m(GE)i(extension)e(with)g(a)h(sp)s(eci\014ed)f(data)h(t)m(yp)s(e)f (and)g(size.)38 b(If)22 b(the)h(FITS)227 2617 y(\014le)30 b(is)g(curren)m(tly)f(empt)m(y)h(then)g(a)g(primary)f(arra)m(y)h(is)g (created,)h(otherwise)f(a)g(new)f(IMA)m(GE)i(extension)f(is)227 2730 y(app)s(ended)f(to)i(the)g(\014le.)95 2985 y Fe(int)47 b(fits_create_img)d(/)j(ffcrim)286 3098 y(\()h(fitsfile)d(*fptr,)h(int) h(bitpix,)f(int)h(naxis,)f(long)h(*naxes,)f(>)h(int)g(*status\))95 3324 y(int)g(fits_create_imgll)c(/)48 b(ffcrimll)286 3437 y(\()g(fitsfile)d(*fptr,)h(int)h(bitpix,)f(int)h(naxis,)f (LONGLONG)g(*naxes,)g(>)h(int)g(*status\))0 3692 y Fi(4)81 b Fj(Cop)m(y)39 b(an)f(n-dimensional)h(image)h(in)f(a)g(particular)h (ro)m(w)f(and)f(column)h(of)g(a)g(binary)f(table)i(\(in)f(a)g(v)m (ector)227 3805 y(column\))31 b(to)g(or)f(from)g(a)h(primary)e(arra)m (y)i(or)g(image)g(extension.)227 3954 y(The)c('cell2image')k(routine)d (will)g(app)s(end)e(a)i(new)f(image)i(extension)f(\(or)g(primary)f (arra)m(y\))h(to)h(the)e(output)227 4067 y(\014le.)43 b(An)m(y)31 b(W)m(CS)g(k)m(eyw)m(ords)g(asso)s(ciated)h(with)f(the)g (input)f(column)h(image)h(will)f(b)s(e)f(translated)i(in)m(to)g(the)227 4180 y(appropriate)j(form)g(for)g(an)f(image)j(extension.)55 b(An)m(y)35 b(other)g(k)m(eyw)m(ords)g(in)g(the)g(table)h(header)f (that)h(are)227 4293 y(not)28 b(sp)s(eci\014cally)h(related)f(to)h (de\014ning)e(the)g(binary)g(table)i(structure)e(or)h(to)g(other)g (columns)g(in)f(the)h(table)227 4406 y(will)j(also)g(b)s(e)f(copied)h (to)g(the)g(header)f(of)g(the)h(output)f(image.)227 4555 y(The)i('image2cell')k(routine)c(will)h(cop)m(y)g(the)g(input)e(image)j (in)m(to)f(the)g(sp)s(eci\014ed)f(ro)m(w)g(and)g(column)g(of)h(the)227 4668 y(curren)m(t)e(binary)g(table)h(in)f(the)h(output)f(\014le.)44 b(The)31 b(binary)f(table)j(HDU)f(m)m(ust)f(exist)h(b)s(efore)f (calling)i(this)227 4781 y(routine,)h(but)f(it)h(ma)m(y)f(b)s(e)g(empt) m(y)-8 b(,)35 b(with)e(no)g(ro)m(ws)g(or)g(columns)g(of)g(data.)50 b(The)33 b(sp)s(eci\014ed)f(column)h(\(and)227 4894 y(ro)m(w\))e(will)h (b)s(e)e(created)h(if)g(it)g(do)s(es)g(not)g(already)g(exist.)43 b(The)30 b('cop)m(yk)m(ey\015ag')j(parameter)e(con)m(trols)h(whic)m(h) 227 5007 y(k)m(eyw)m(ords)26 b(are)g(copied)g(from)f(the)g(input)g (image)h(to)g(the)g(header)f(of)h(the)f(output)g(table:)39 b(0)26 b(=)f(no)h(k)m(eyw)m(ords)227 5120 y(will)k(b)s(e)g(copied,)g(1) h(=)e(all)i(k)m(eyw)m(ords)f(will)g(b)s(e)f(copied)h(\(except)i(those)e (k)m(eyw)m(ords)g(that)h(w)m(ould)e(b)s(e)g(in)m(v)-5 b(alid)227 5233 y(in)30 b(the)h(table)g(header\),)g(and)f(2)g(=)g(cop)m (y)i(only)e(the)h(W)m(CS)f(k)m(eyw)m(ords.)95 5488 y Fe(int)47 b(fits_copy_cell2image)286 5601 y(\(fitsfile)f(*infptr,)f (fitsfile)h(*outfptr,)f(char)i(*colname,)e(long)i(rownum,)334 5714 y(>)h(int)e(*status\))p eop end %%Page: 45 53 TeXDict begin 45 52 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.45) cvn H.B /DEST pdfmark end 0 299 a Fh(5.5.)72 b(PRIMAR)-8 b(Y)31 b(ARRA)-8 b(Y)31 b(OR)f(IMA)m(GE)h(EXTENSION)f(I/O)g(R)m (OUTINES)1011 b Fj(45)95 668 y Fe(int)47 b(fits_copy_image2cell)286 781 y(\(fitsfile)f(*infptr,)f(fitsfile)h(*outfptr,)f(char)i(*colname,)e (long)i(rownum,)334 894 y(int)g(copykeyflag)e(>)i(int)g(*status\))0 1135 y Fi(5)81 b Fj(W)-8 b(rite)40 b(a)f(rectangular)g(subimage)g(\(or) g(the)g(whole)g(image\))h(to)f(the)g(FITS)f(data)h(arra)m(y)-8 b(.)67 b(The)38 b(fpixel)h(and)227 1248 y(lpixel)30 b(arra)m(ys)g(giv)m (e)h(the)f(co)s(ordinates)g(of)f(the)h(\014rst)f(\(lo)m(w)m(er)i(left)f (corner\))g(and)f(last)h(\(upp)s(er)e(righ)m(t)i(corner\))227 1361 y(pixels)h(in)f(FITS)g(image)h(to)g(b)s(e)f(written)g(to.)95 1602 y Fe(int)47 b(fits_write_subset)c(/)48 b(ffpss)286 1715 y(\(fitsfile)e(*fptr,)g(int)h(datatype,)e(long)i(*fpixel,)e(long)i (*lpixel,)334 1828 y(DTYPE)f(*array,)g(>)i(int)f(*status\))0 2070 y Fi(6)81 b Fj(W)-8 b(rite)39 b(pixels)g(in)m(to)g(the)g(FITS)f (data)h(arra)m(y)-8 b(.)66 b('fpixel')39 b(is)f(an)g(arra)m(y)h(of)g (length)g(NAXIS)f(whic)m(h)g(giv)m(es)i(the)227 2183 y(co)s(ordinate)k(of)f(the)g(starting)g(pixel)g(to)h(b)s(e)e(written)h (to,)j(suc)m(h)d(that)g(fpixel[0])h(is)f(in)f(the)h(range)g(1)g(to)227 2295 y(NAXIS1,)34 b(fpixel[1])f(is)g(in)f(the)g(range)h(1)g(to)g (NAXIS2,)g(etc.)48 b(The)32 b(\014rst)g(pair)g(of)h(routines)f(simply)g (writes)227 2408 y(the)40 b(arra)m(y)g(of)g(pixels)f(to)i(the)e(FITS)g (\014le)h(\(doing)g(data)g(t)m(yp)s(e)g(con)m(v)m(ersion)h(if)e (necessary\))h(whereas)g(the)227 2521 y(second)c(routines)g(will)g (substitute)f(the)h(appropriate)g(FITS)f(n)m(ull)g(v)-5 b(alue)37 b(for)e(an)m(y)h(elemen)m(ts)h(whic)m(h)f(are)227 2634 y(equal)41 b(to)g(the)f(input)g(v)-5 b(alue)40 b(of)h(n)m(ulv)-5 b(al)40 b(\(note)h(that)g(this)f(parameter)h(giv)m(es)h(the)e(address)f (of)i(the)f(n)m(ull)227 2747 y(v)-5 b(alue,)36 b(not)f(the)f(n)m(ull)g (v)-5 b(alue)35 b(itself)7 b(\).)53 b(F)-8 b(or)35 b(in)m(teger)h(FITS) d(arra)m(ys,)j(the)f(FITS)e(n)m(ull)h(v)-5 b(alue)35 b(is)f(de\014ned)f(b)m(y)227 2860 y(the)26 b(BLANK)f(k)m(eyw)m(ord)h (\(an)g(error)f(is)g(returned)f(if)i(the)f(BLANK)h(k)m(eyw)m(ord)g(do)s (esn't)f(exist\).)40 b(F)-8 b(or)26 b(\015oating)227 2973 y(p)s(oin)m(t)g(FITS)f(arra)m(ys)h(the)g(sp)s(ecial)g(IEEE)f(NaN)i (\(Not-a-Num)m(b)s(er\))g(v)-5 b(alue)26 b(will)g(b)s(e)f(written)h(in) m(to)h(the)f(FITS)227 3086 y(\014le.)66 b(If)38 b(a)h(n)m(ull)f(p)s (oin)m(ter)h(is)f(en)m(tered)h(for)g(n)m(ulv)-5 b(al,)41 b(then)d(the)h(n)m(ull)f(v)-5 b(alue)39 b(is)g(ignored)g(and)e(this)i (routine)227 3199 y(b)s(eha)m(v)m(es)31 b(the)g(same)g(as)f(\014ts)p 1189 3199 28 4 v 33 w(write)p 1424 3199 V 33 w(pix.)95 3440 y Fe(int)47 b(fits_write_pix)d(/)k(ffppx)286 3553 y(\(fitsfile)e(*fptr,)g(int)h(datatype,)e(long)i(*fpixel,)e(LONGLONG)h (nelements,)334 3666 y(DTYPE)g(*array,)g(int)h(*status\);)95 3892 y(int)g(fits_write_pixll)d(/)j(ffppxll)286 4005 y(\(fitsfile)f(*fptr,)g(int)h(datatype,)e(LONGLONG)g(*fpixel,)h (LONGLONG)g(nelements,)334 4118 y(DTYPE)g(*array,)g(int)h(*status\);)95 4343 y(int)g(fits_write_pixnull)c(/)48 b(ffppxn)286 4456 y(\(fitsfile)e(*fptr,)g(int)h(datatype,)e(long)i(*fpixel,)e(LONGLONG)h (nelements,)334 4569 y(DTYPE)g(*array,)g(DTYPE)h(*nulval,)e(>)j(int)f (*status\);)95 4795 y(int)g(fits_write_pixnullll)c(/)k(ffppxnll)286 4908 y(\(fitsfile)f(*fptr,)g(int)h(datatype,)e(LONGLONG)g(*fpixel,)h (LONGLONG)g(nelements,)334 5021 y(DTYPE)g(*array,)g(DTYPE)h(*nulval,)e (>)j(int)f(*status\);)0 5262 y Fi(7)81 b Fj(Set)24 b(FITS)g(data)i (arra)m(y)f(elemen)m(ts)h(equal)f(to)g(the)g(appropriate)f(n)m(ull)h (pixel)g(v)-5 b(alue.)39 b(F)-8 b(or)25 b(in)m(teger)h(FITS)e(arra)m (ys,)227 5375 y(the)34 b(FITS)e(n)m(ull)h(v)-5 b(alue)34 b(is)f(de\014ned)f(b)m(y)h(the)h(BLANK)f(k)m(eyw)m(ord)h(\(an)f(error)g (is)g(returned)f(if)h(the)h(BLANK)227 5488 y(k)m(eyw)m(ord)23 b(do)s(esn't)g(exist\).)39 b(F)-8 b(or)23 b(\015oating)g(p)s(oin)m(t)g (FITS)f(arra)m(ys)g(the)h(sp)s(ecial)g(IEEE)f(NaN)h(\(Not-a-Num)m(b)s (er\))227 5601 y(v)-5 b(alue)34 b(will)f(b)s(e)g(written)g(in)m(to)h (the)g(FITS)e(\014le.)49 b(Note)34 b(that)g('\014rstelem')g(is)f(a)h (scalar)g(giving)g(the)f(o\013set)h(to)227 5714 y(the)d(\014rst)e (pixel)i(to)g(b)s(e)f(written)g(in)h(the)f(equiv)-5 b(alen)m(t)32 b(1-dimensional)f(arra)m(y)g(of)g(image)g(pixels.)p eop end %%Page: 46 54 TeXDict begin 46 53 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.46) cvn H.B /DEST pdfmark end 0 299 a Fj(46)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)95 555 y Fe(int)47 b(fits_write_null_img)c(/)k(ffpprn)286 668 y(\(fitsfile)f(*fptr,)g(LONGLONG)f(firstelem,)g(LONGLONG)h (nelements,)f(>)i(int)g(*status\))0 925 y Fi(8)81 b Fj(Read)33 b(a)h(rectangular)h(subimage)f(\(or)g(the)g(whole)g(image\))h(from)e (the)h(FITS)f(data)h(arra)m(y)-8 b(.)52 b(The)33 b(fpixel)h(and)227 1038 y(lpixel)c(arra)m(ys)g(giv)m(e)h(the)f(co)s(ordinates)g(of)f(the)h (\014rst)f(\(lo)m(w)m(er)i(left)f(corner\))g(and)f(last)h(\(upp)s(er)e (righ)m(t)i(corner\))227 1151 y(pixels)d(to)h(b)s(e)e(read)h(from)g (the)g(FITS)f(image.)41 b(Unde\014ned)25 b(FITS)h(arra)m(y)i(elemen)m (ts)g(will)f(b)s(e)f(returned)g(with)227 1263 y(a)k(v)-5 b(alue)30 b(=)e(*n)m(ullv)-5 b(al,)31 b(\(note)f(that)g(this)f (parameter)h(giv)m(es)g(the)g(address)e(of)h(the)h(n)m(ull)f(v)-5 b(alue,)30 b(not)g(the)f(n)m(ull)227 1376 y(v)-5 b(alue)36 b(itself)7 b(\))37 b(unless)e(n)m(ulv)-5 b(al)36 b(=)g(0)g(or)f(*n)m (ulv)-5 b(al)37 b(=)e(0,)j(in)d(whic)m(h)g(case)i(no)f(c)m(hec)m(ks)h (for)e(unde\014ned)f(pixels)227 1489 y(will)d(b)s(e)f(p)s(erformed.)95 1746 y Fe(int)47 b(fits_read_subset)d(/)j(ffgsv)286 1859 y(\(fitsfile)f(*fptr,)g(int)94 b(datatype,)46 b(long)g(*fpixel,)g(long) g(*lpixel,)g(long)h(*inc,)334 1972 y(DTYPE)f(*nulval,)g(>)h(DTYPE)g (*array,)f(int)h(*anynul,)e(int)i(*status\))0 2228 y Fi(9)81 b Fj(Read)32 b(pixels)h(from)f(the)g(FITS)g(data)h(arra)m(y)-8 b(.)48 b('fpixel')33 b(is)g(the)f(starting)h(pixel)g(lo)s(cation)h(and) e(is)h(an)f(arra)m(y)h(of)227 2341 y(length)h(NAXIS)f(suc)m(h)g(that)h (fpixel[0])g(is)f(in)g(the)h(range)f(1)h(to)g(NAXIS1,)g(fpixel[1])g(is) g(in)f(the)g(range)h(1)f(to)227 2454 y(NAXIS2,)c(etc.)41 b(The)28 b(nelemen)m(ts)h(parameter)f(sp)s(eci\014es)g(the)g(n)m(um)m (b)s(er)f(of)h(pixels)h(to)g(read.)39 b(If)28 b(fpixel)g(is)g(set)227 2567 y(to)36 b(the)f(\014rst)f(pixel,)j(and)e(nelemen)m(ts)g(is)g(set)h (equal)g(to)f(the)g(NAXIS1)h(v)-5 b(alue,)37 b(then)d(this)h(routine)g (w)m(ould)227 2680 y(read)28 b(the)g(\014rst)f(ro)m(w)h(of)g(the)h (image.)41 b(Alternativ)m(ely)-8 b(,)31 b(if)d(nelemen)m(ts)h(is)f(set) g(equal)h(to)f(NAXIS1)g(*)h(NAXIS2)227 2793 y(then)h(it)h(w)m(ould)f (read)h(an)f(en)m(tire)h(2D)g(image,)h(or)f(the)f(\014rst)g(plane)g(of) h(a)g(3-D)g(datacub)s(e.)227 2943 y(The)38 b(\014rst)g(2)h(routines)f (will)h(return)f(an)m(y)h(unde\014ned)d(pixels)j(in)f(the)h(FITS)e (arra)m(y)i(equal)g(to)h(the)e(v)-5 b(alue)227 3055 y(of)36 b(*n)m(ullv)-5 b(al)36 b(\(note)g(that)g(this)f(parameter)h(giv)m(es)g (the)g(address)e(of)i(the)f(n)m(ull)g(v)-5 b(alue,)37 b(not)f(the)f(n)m(ull)g(v)-5 b(alue)227 3168 y(itself)7 b(\))34 b(unless)d(n)m(ulv)-5 b(al)32 b(=)g(0)g(or)h(*n)m(ulv)-5 b(al)32 b(=)g(0,)h(in)f(whic)m(h)g(case)h(no)f(c)m(hec)m(ks)h(for)f (unde\014ned)e(pixels)i(will)h(b)s(e)227 3281 y(p)s(erformed.)42 b(The)31 b(second)h(2)f(routines)h(are)f(similar)h(except)g(that)g(an)m (y)g(unde\014ned)d(pixels)i(will)h(ha)m(v)m(e)h(the)227 3394 y(corresp)s(onding)d(n)m(ullarra)m(y)g(elemen)m(t)i(set)f(equal)g (to)g(TR)m(UE)g(\(=)f(1\).)95 3651 y Fe(int)47 b(fits_read_pix)e(/)i (ffgpxv)286 3764 y(\(fitsfile)f(*fptr,)g(int)94 b(datatype,)46 b(long)g(*fpixel,)g(LONGLONG)f(nelements,)334 3877 y(DTYPE)h(*nulval,)g (>)h(DTYPE)g(*array,)f(int)h(*anynul,)e(int)i(*status\))95 4102 y(int)g(fits_read_pixll)d(/)j(ffgpxvll)286 4215 y(\(fitsfile)f(*fptr,)g(int)94 b(datatype,)46 b(LONGLONG)f(*fpixel,)h (LONGLONG)f(nelements,)334 4328 y(DTYPE)h(*nulval,)g(>)h(DTYPE)g (*array,)f(int)h(*anynul,)e(int)i(*status\))95 4554 y(int)g (fits_read_pixnull)c(/)48 b(ffgpxf)286 4667 y(\(fitsfile)e(*fptr,)g (int)94 b(datatype,)46 b(long)g(*fpixel,)g(LONGLONG)f(nelements,)334 4780 y(>)j(DTYPE)e(*array,)g(char)g(*nullarray,)f(int)i(*anynul,)f(int) g(*status\))95 5006 y(int)h(fits_read_pixnullll)c(/)k(ffgpxfll)286 5119 y(\(fitsfile)f(*fptr,)g(int)94 b(datatype,)46 b(LONGLONG)f (*fpixel,)h(LONGLONG)f(nelements,)334 5231 y(>)j(DTYPE)e(*array,)g (char)g(*nullarray,)f(int)i(*anynul,)f(int)g(*status\))0 5488 y Fi(10)g Fj(Cop)m(y)36 b(a)g(rectangular)h(section)g(of)g(an)e (image)j(and)d(write)h(it)h(to)f(a)h(new)e(FITS)g(primary)g(image)j(or) e(image)227 5601 y(extension.)49 b(The)32 b(new)g(image)i(HDU)g(is)e (app)s(ended)f(to)j(the)f(end)f(of)h(the)g(output)f(\014le;)i(all)g (the)f(k)m(eyw)m(ords)227 5714 y(in)39 b(the)f(input)g(image)i(will)f (b)s(e)f(copied)h(to)g(the)g(output)f(image.)66 b(The)38 b(common)h(W)m(CS)g(k)m(eyw)m(ords)g(will)p eop end %%Page: 47 55 TeXDict begin 47 54 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.47) cvn H.B /DEST pdfmark end 0 299 a Fh(5.6.)72 b(IMA)m(GE)31 b(COMPRESSION)2567 b Fj(47)227 555 y(b)s(e)34 b(up)s(dated)f(if)i (necessary)g(to)g(corresp)s(ond)e(to)j(the)e(co)s(ordinates)h(of)g(the) g(section.)54 b(The)34 b(format)h(of)g(the)227 668 y(section)29 b(expression)e(is)g(same)g(as)h(sp)s(ecifying)f(an)g(image)h(section)h (using)d(the)i(extended)f(\014le)g(name)g(syn)m(tax)227 781 y(\(see)32 b("Image)f(Section")h(in)e(Chapter)g(10\).)42 b(\(Examples:)f("1:100,1:200",)36 b("1:100:2,)d(1:*:2",)g("*,)f(-*"\).) 95 996 y Fe(int)47 b(fits_copy_image_section)42 b(/)47 b(ffcpimg)286 1109 y(\(fitsfile)f(*infptr,)f(fitsfile)h(*outfptr,)f (char)i(*section,)e(int)i(*status\))0 1259 y SDict begin H.S end 0 1259 a 0 1259 a SDict begin 13.6 H.A end 0 1259 a 0 1259 a SDict begin [ /View [/XYZ H.V] /Dest (section.5.6) cvn H.B /DEST pdfmark end 0 1259 a 177 x Ff(5.6)135 b(Image)46 b(Compression)0 1686 y Fj(CFITSIO)29 b(transparen)m(tly)h (supp)s(orts)f(the)h(2)h(metho)s(ds)f(of)g(image)i(compression)e (describ)s(ed)g(b)s(elo)m(w.)0 1846 y(1\))45 b(The)f(en)m(tire)i(FITS)e (\014le)h(ma)m(y)g(b)s(e)f(externally)i(compressed)e(with)g(the)h(gzip) g(or)g(Unix)f(compress)h(utilit)m(y)0 1959 y(programs,)37 b(pro)s(ducing)d(a)j(*.gz)g(or)f(*.Z)g(\014le,)h(resp)s(ectiv)m(ely)-8 b(.)59 b(When)36 b(reading)g(compressed)f(\014les)h(of)g(this)g(t)m(yp) s(e,)0 2072 y(CFITSIO)43 b(\014rst)h(uncompresses)f(the)i(en)m(tire)g (\014le)g(in)m(to)g(memory)g(b)s(efore)f(p)s(erforming)f(the)i (requested)f(read)0 2185 y(op)s(erations.)c(Output)28 b(\014les)g(can)h(b)s(e)f(directly)i(written)e(in)g(the)h(gzip)g (compressed)g(format)g(if)f(the)h(user-sp)s(eci\014ed)0 2298 y(\014lename)35 b(ends)e(with)i(`.gz'.)54 b(In)34 b(this)g(case,)j(CFITSIO)c(initially)j(writes)e(the)h(uncompressed)e (\014le)i(in)f(memory)0 2411 y(and)j(then)g(compresses)g(it)h(and)f (writes)g(it)h(to)g(disk)f(when)f(the)i(FITS)f(\014le)g(is)g(closed,)k (th)m(us)36 b(sa)m(ving)j(user)d(disk)0 2524 y(space.)59 b(Read)36 b(and)g(write)h(access)g(to)g(these)g(compressed)f(FITS)g (\014les)g(is)g(generally)i(quite)e(fast)h(since)g(all)g(the)0 2636 y(I/O)28 b(is)g(p)s(erformed)e(in)i(memory;)h(the)f(main)g (limitation)i(with)e(this)f(tec)m(hnique)i(is)f(that)h(there)f(m)m(ust) g(b)s(e)f(enough)0 2749 y(a)m(v)-5 b(ailable)33 b(memory)d(\(or)h(sw)m (ap)f(space\))h(to)g(hold)f(the)h(en)m(tire)g(uncompressed)e(FITS)h (\014le.)0 2910 y(2\))42 b(CFITSIO)d(also)j(supp)s(orts)d(the)j(FITS)e (tiled)h(image)i(compression)e(con)m(v)m(en)m(tion)i(in)e(whic)m(h)f (the)i(image)g(is)0 3022 y(sub)s(divided)30 b(in)m(to)j(a)f(grid)g(of)g (rectangular)i(tiles,)f(and)f(eac)m(h)h(tile)g(of)g(pixels)f(is)g (individually)g(compressed.)45 b(The)0 3135 y(details)c(of)f(this)g (FITS)g(compression)g(con)m(v)m(en)m(tion)i(are)e(describ)s(ed)f(at)i (the)g(FITS)e(Supp)s(ort)f(O\016ce)i(w)m(eb)g(site)0 3248 y(at)c(h)m(ttp://\014ts.gsfc.nasa.go)m(v/\014ts)p 1230 3248 28 4 v 37 w(registry)-8 b(.h)m(tml,)38 b(and)d(in)g(the)g (fpac)m(kguide)h(p)s(df)e(\014le)h(that)h(is)g(included)e(with)0 3361 y(the)h(CFITSIO)f(source)h(\014le)h(distributions)e(Basically)-8 b(,)39 b(the)c(compressed)g(image)i(tiles)f(are)g(stored)f(in)g(ro)m (ws)g(of)0 3474 y(a)42 b(v)-5 b(ariable)42 b(length)g(arra)m(y)h (column)e(in)g(a)h(FITS)f(binary)g(table,)46 b(ho)m(w)m(ev)m(er)c (CFITSIO)f(recognizes)i(that)f(this)0 3587 y(binary)37 b(table)i(extension)f(con)m(tains)h(an)e(image)i(and)e(treats)i(it)f (as)g(if)g(it)g(w)m(ere)g(an)g(IMA)m(GE)g(extension.)64 b(This)0 3700 y(tile-compressed)37 b(format)f(is)f(esp)s(ecially)i(w)m (ell)g(suited)e(for)h(compressing)f(v)m(ery)h(large)h(images)g(b)s (ecause)e(a\))i(the)0 3813 y(FITS)28 b(header)h(k)m(eyw)m(ords)h (remain)f(uncompressed)e(for)i(rapid)g(read)g(access,)h(and)f(b)s (ecause)g(b\))g(it)g(is)h(p)s(ossible)e(to)0 3926 y(extract)f(and)e (uncompress)g(sections)i(of)f(the)g(image)h(without)e(ha)m(ving)i(to)f (uncompress)f(the)h(en)m(tire)g(image.)41 b(This)0 4039 y(format)34 b(is)g(also)h(m)m(uc)m(h)e(more)h(e\013ectiv)m(e)j(in)c (compressing)h(\015oating)h(p)s(oin)m(t)e(images)i(than)f(simply)f (compressing)0 4152 y(the)39 b(image)i(using)d(gzip)i(or)f(compress)g (b)s(ecause)g(it)h(appro)m(ximates)g(the)g(\015oating)g(p)s(oin)m(t)f (v)-5 b(alues)39 b(with)g(scaled)0 4264 y(in)m(tegers)32 b(whic)m(h)e(can)g(then)g(b)s(e)g(compressed)g(more)h(e\016cien)m(tly) -8 b(.)0 4425 y(Curren)m(tly)41 b(CFITSIO)e(supp)s(orts)h(3)h(general)i (purp)s(ose)c(compression)i(algorithms)i(plus)d(one)i(other)f(sp)s (ecial-)0 4538 y(purp)s(ose)31 b(compression)i(tec)m(hnique)h(that)f (is)g(designed)g(for)g(data)g(masks)g(with)g(p)s(ositiv)m(e)h(in)m (teger)g(pixel)f(v)-5 b(alues.)0 4650 y(The)40 b(3)g(general)h(purp)s (ose)e(algorithms)i(are)f(GZIP)-8 b(,)41 b(Rice,)j(and)39 b(HCOMPRESS,)g(and)h(the)g(sp)s(ecial)h(purp)s(ose)0 4763 y(algorithm)33 b(is)f(the)g(IRAF)g(pixel)g(list)h(compression)f (tec)m(hnique)g(\(PLIO\).)g(There)g(are)g(2)g(v)-5 b(arian)m(ts)33 b(of)f(the)g(GZIP)0 4876 y(algorithm:)46 b(GZIP)p 681 4876 V 33 w(1)33 b(compresses)f(the)h(arra)m(y)g(of)g(image)h(pixel)f (v)-5 b(alue)33 b(normally)g(with)g(the)f(GZIP)h(algorithm,)0 4989 y(while)26 b(GZIP)p 460 4989 V 32 w(2)g(\014rst)f(sh)m(u\017es)g (the)g(b)m(ytes)i(in)e(all)h(the)g(pixel)g(v)-5 b(alues)26 b(so)g(that)g(the)g(most-signi\014can)m(t)h(b)m(yte)f(of)g(ev)m(ery)0 5102 y(pixel)h(app)s(ears)e(\014rst,)i(follo)m(w)m(ed)h(b)m(y)e(the)g (less)h(signi\014can)m(t)g(b)m(ytes)g(in)f(sequence.)39 b(GZIP)p 2944 5102 V 33 w(2)26 b(ma)m(y)h(b)s(e)f(more)g(e\013ectiv)m (e)0 5215 y(in)36 b(cases)h(where)e(the)h(most)h(signi\014can)m(t)f(b)m (yte)h(in)f(most)g(of)g(the)g(image)i(pixel)e(v)-5 b(alues)36 b(con)m(tains)h(the)g(same)f(bit)0 5328 y(pattern.)41 b(In)29 b(principle,)h(an)m(y)g(n)m(um)m(b)s(er)f(of)h(other)g (compression)g(algorithms)h(could)f(also)h(b)s(e)e(supp)s(orted)f(b)m (y)i(the)0 5441 y(FITS)g(tiled)h(image)g(compression)g(con)m(v)m(en)m (tion.)0 5601 y(The)k(FITS)g(image)h(can)g(b)s(e)f(sub)s(divided)e(in)m (to)k(an)m(y)f(desired)f(rectangular)h(grid)f(of)h(compression)f (tiles.)57 b(With)0 5714 y(the)32 b(GZIP)-8 b(,)33 b(Rice,)h(and)e (PLIO)f(algorithms,)j(the)e(default)h(is)f(to)h(tak)m(e)h(eac)m(h)g(ro) m(w)e(of)h(the)f(image)i(as)e(a)h(tile.)47 b(The)p eop end %%Page: 48 56 TeXDict begin 48 55 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.48) cvn H.B /DEST pdfmark end 0 299 a Fj(48)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)0 555 y Fj(HCOMPRESS)25 b(algorithm)i(is)g(inheren)m(tly) f(2-dimensional)h(in)f(nature,)i(so)e(the)h(default)f(in)g(this)g(case) i(is)e(to)h(tak)m(e)0 668 y(16)h(ro)m(ws)g(of)f(the)h(image)h(p)s(er)d (tile.)41 b(In)27 b(most)h(cases)g(it)g(mak)m(es)h(little)g (di\013erence)f(what)f(tiling)i(pattern)f(is)f(used,)h(so)0 781 y(the)33 b(default)g(tiles)g(are)g(usually)g(adequate.)48 b(In)32 b(the)h(case)g(of)g(v)m(ery)g(small)g(images,)i(it)e(could)g(b) s(e)f(more)g(e\016cien)m(t)0 894 y(to)h(compress)f(the)h(whole)f(image) i(as)e(a)h(single)g(tile.)48 b(Note)34 b(that)f(the)f(image)i (dimensions)d(are)i(not)g(required)e(to)0 1007 y(b)s(e)d(an)g(in)m (teger)i(m)m(ultiple)f(of)f(the)h(tile)g(dimensions;)g(if)f(not,)i (then)e(the)g(tiles)i(at)f(the)f(edges)h(of)g(the)f(image)i(will)f(b)s (e)0 1120 y(smaller)i(than)f(the)h(other)f(tiles.)0 1280 y(The)41 b(4)g(supp)s(orted)f(image)i(compression)f(algorithms)h(are)g (all)g('loss-less')h(when)d(applied)h(to)h(in)m(teger)h(FITS)0 1393 y(images;)25 b(the)c(pixel)g(v)-5 b(alues)20 b(are)h(preserv)m(ed) f(exactly)j(with)d(no)g(loss)h(of)f(information)h(during)e(the)i (compression)g(and)0 1506 y(uncompression)34 b(pro)s(cess.)54 b(In)34 b(addition,)j(the)e(HCOMPRESS)f(algorithm)i(supp)s(orts)d(a)i ('lossy')h(compression)0 1619 y(mo)s(de)41 b(that)h(will)g(pro)s(duce)f (larger)h(amoun)m(t)g(of)g(image)h(compression.)74 b(This)41 b(is)g(ac)m(hiev)m(ed)j(b)m(y)d(sp)s(ecifying)h(a)0 1732 y(non-zero)32 b(v)-5 b(alue)32 b(for)f(the)g(HCOMPRESS)f(\\scale")k (parameter.)44 b(Since)31 b(the)g(amoun)m(t)h(of)g(compression)f(that)h (is)0 1844 y(ac)m(hiev)m(ed)g(dep)s(ends)d(directly)i(on)f(the)h(RMS)f (noise)h(in)f(the)h(image,)h(it)f(is)g(usually)f(more)g(con)m(v)m(en)m (tion)j(to)e(sp)s(ecify)0 1957 y(the)f(HCOMPRESS)e(scale)i(factor)h (relativ)m(e)g(to)f(the)g(RMS)f(noise.)41 b(Setting)30 b(s)f(=)g(2.5)i(means)e(use)g(a)h(scale)h(factor)0 2070 y(that)h(is)f(2.5)i(times)e(the)h(calculated)h(RMS)e(noise)h(in)f(the)g (image)i(tile.)44 b(In)31 b(some)g(cases)h(it)g(ma)m(y)g(b)s(e)f (desirable)g(to)0 2183 y(sp)s(ecify)h(the)g(exact)i(scaling)f(to)g(b)s (e)e(used,)h(instead)h(of)f(sp)s(ecifying)g(it)g(relativ)m(e)j(to)d (the)h(calculated)h(noise)e(v)-5 b(alue.)0 2296 y(This)37 b(ma)m(y)h(b)s(e)f(done)g(b)m(y)h(sp)s(ecifying)f(the)h(negativ)m(e)i (of)d(desired)g(scale)i(v)-5 b(alue)38 b(\(t)m(ypically)i(in)d(the)h (range)g(-2)g(to)0 2409 y(-100\).)0 2569 y(V)-8 b(ery)43 b(high)g(compression)f(factors)i(\(of)f(100)h(or)f(more\))g(can)g(b)s (e)f(ac)m(hiev)m(ed)j(b)m(y)d(using)h(large)g(HCOMPRESS)0 2682 y(scale)31 b(v)-5 b(alues,)31 b(ho)m(w)m(ev)m(er,)h(this)e(can)g (pro)s(duce)f(undesirable)g(\\blo)s(c)m(ky")j(artifacts)f(in)f(the)g (compressed)g(image.)42 b(A)0 2795 y(v)-5 b(ariation)27 b(of)g(the)f(HCOMPRESS)f(algorithm)i(\(called)h(HSCOMPRESS\))c(can)i(b) s(e)g(used)f(in)h(this)g(case)h(to)g(apply)0 2908 y(a)f(small)h(amoun)m (t)f(of)h(smo)s(othing)f(of)g(the)g(image)h(when)e(it)i(is)f (uncompressed)f(to)h(help)g(co)m(v)m(er)i(up)d(these)h(artifacts.)0 3021 y(This)36 b(smo)s(othing)h(is)g(purely)f(cosmetic)j(and)d(do)s(es) h(not)g(cause)g(an)m(y)h(signi\014can)m(t)g(c)m(hange)g(to)f(the)g (image)i(pixel)0 3134 y(v)-5 b(alues.)0 3294 y(Floating)34 b(p)s(oin)m(t)f(FITS)e(images)j(\(whic)m(h)e(ha)m(v)m(e)i(BITPIX)e(=)g (-32)h(or)g(-64\))g(usually)f(con)m(tain)i(to)s(o)f(m)m(uc)m(h)g (\\noise")0 3407 y(in)k(the)g(least)i(signi\014can)m(t)f(bits)f(of)h (the)f(man)m(tissa)h(of)g(the)f(pixel)h(v)-5 b(alues)37 b(to)h(b)s(e)f(e\013ectiv)m(ely)j(compressed)d(with)0 3520 y(an)m(y)d(lossless)g(algorithm.)52 b(Consequen)m(tly)-8 b(,)35 b(\015oating)g(p)s(oin)m(t)e(images)i(are)f(\014rst)f(quan)m (tized)h(in)m(to)h(scaled)g(in)m(teger)0 3633 y(pixel)26 b(v)-5 b(alues)25 b(\(and)g(th)m(us)g(thro)m(wing)h(a)m(w)m(a)m(y)h(m)m (uc)m(h)e(of)h(the)f(noise\))h(b)s(efore)f(b)s(eing)g(compressed)g (with)g(the)h(sp)s(eci\014ed)0 3745 y(algorithm)d(\(either)g(GZIP)-8 b(,)23 b(Rice,)i(or)d(HCOMPRESS\).)f(This)h(tec)m(hnique)h(pro)s(duces) e(m)m(uc)m(h)h(higher)g(compression)0 3858 y(factors)33 b(than)e(simply)g(using)g(the)h(GZIP)g(utilit)m(y)h(to)f(externally)h (compress)f(the)f(whole)h(FITS)f(\014le,)i(but)e(it)h(also)0 3971 y(means)d(that)h(the)g(original)g(\015oating)g(v)-5 b(alue)30 b(pixel)f(v)-5 b(alues)30 b(are)g(not)f(exactly)i(preserv)m (ed.)40 b(When)29 b(done)g(prop)s(erly)-8 b(,)0 4084 y(this)33 b(in)m(teger)h(scaling)f(tec)m(hnique)h(will)f(only)f (discard)h(the)f(insigni\014can)m(t)i(noise)f(while)g(still)g (preserving)f(all)i(the)0 4197 y(real)43 b(information)f(in)g(the)h (image.)77 b(The)42 b(amoun)m(t)g(of)h(precision)f(that)h(is)f (retained)h(in)e(the)i(pixel)f(v)-5 b(alues)43 b(is)0 4310 y(con)m(trolled)37 b(b)m(y)d(the)i("quan)m(tization)h(lev)m(el")g (parameter,)g(q.)54 b(Larger)35 b(v)-5 b(alues)36 b(of)f(q)f(will)i (result)f(in)f(compressed)0 4423 y(images)h(whose)e(pixels)h(more)f (closely)i(matc)m(h)g(the)e(\015oating)i(p)s(oin)m(t)e(pixel)h(v)-5 b(alues,)35 b(but)e(at)h(the)g(same)g(time)g(the)0 4536 y(amoun)m(t)j(of)f(compression)g(that)h(is)f(ac)m(hiev)m(ed)i(will)f(b) s(e)e(reduced.)58 b(Users)36 b(should)f(exp)s(erimen)m(t)i(with)e (di\013eren)m(t)0 4649 y(v)-5 b(alues)25 b(for)g(this)g(parameter)g(to) h(determine)f(the)g(optimal)h(v)-5 b(alue)25 b(that)h(preserv)m(es)f (all)h(the)f(useful)f(information)h(in)0 4762 y(the)k(image,)h(without) f(needlessly)g(preserving)f(all)h(the)g(\\noise")h(whic)m(h)e(will)h(h) m(urt)f(the)h(compression)f(e\016ciency)-8 b(.)0 4922 y(The)38 b(default)g(v)-5 b(alue)38 b(for)g(the)g(quan)m(tization)i (scale)g(factor)f(is)f(4.0,)j(whic)m(h)d(means)g(that)g(scaled)h(in)m (teger)h(pixel)0 5035 y(v)-5 b(alues)41 b(will)h(b)s(e)e(quan)m(tized)i (suc)m(h)f(that)h(the)f(di\013erence)h(b)s(et)m(w)m(een)f(adjacen)m(t)i (in)m(teger)f(v)-5 b(alues)42 b(will)f(b)s(e)g(1/4th)0 5148 y(of)35 b(the)h(noise)f(lev)m(el)i(in)e(the)g(image)h(bac)m (kground.)55 b(CFITSIO)34 b(uses)g(an)h(optimized)h(algorithm)g(to)g (accurately)0 5261 y(estimate)41 b(the)e(noise)h(in)f(the)g(image.)68 b(As)39 b(an)g(example,)k(if)c(the)g(RMS)g(noise)g(in)g(the)h(bac)m (kground)e(pixels)i(of)0 5373 y(an)35 b(image)h(=)f(32.0,)j(then)d(the) h(spacing)f(b)s(et)m(w)m(een)h(adjacen)m(t)g(scaled)g(in)m(teger)h (pixel)e(v)-5 b(alues)36 b(will)f(equal)h(8.0)g(b)m(y)0 5486 y(default.)63 b(Note)38 b(that)h(the)e(RMS)h(noise)g(is)f(indep)s (enden)m(tly)g(calculated)j(for)d(eac)m(h)i(tile)f(of)g(the)g(image,)j (so)d(the)0 5599 y(resulting)24 b(in)m(teger)i(scaling)f(factor)g(ma)m (y)g(\015uctuate)g(sligh)m(tly)g(for)f(eac)m(h)i(tile.)40 b(In)23 b(some)i(cases)g(it)f(ma)m(y)h(b)s(e)f(desirable)0 5712 y(to)29 b(sp)s(ecify)f(the)h(exact)h(quan)m(tization)h(lev)m(el)f (to)f(b)s(e)f(used,)g(instead)h(of)g(sp)s(ecifying)f(it)h(relativ)m(e)i (to)e(the)g(calculated)p eop end %%Page: 49 57 TeXDict begin 49 56 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.49) cvn H.B /DEST pdfmark end 0 299 a Fh(5.6.)72 b(IMA)m(GE)31 b(COMPRESSION)2567 b Fj(49)0 555 y(noise)27 b(v)-5 b(alue.)40 b(This)27 b(ma)m(y)g(b)s(e)g(done)f(b)m(y)h(sp)s(ecifying)g(the)g (negativ)m(e)i(of)f(desired)e(quan)m(tization)j(lev)m(el)g(for)d(the)h (v)-5 b(alue)0 668 y(of)29 b(q.)40 b(In)28 b(the)i(previous)e(example,) i(one)f(could)g(sp)s(ecify)g(q)g(=)f(-8.0)j(so)e(that)h(the)f(quan)m (tized)g(in)m(teger)i(lev)m(els)f(di\013er)0 781 y(b)m(y)k(exactly)j (8.0.)54 b(Larger)35 b(negativ)m(e)i(v)-5 b(alues)35 b(for)f(q)h(means)f(that)h(the)g(lev)m(els)h(are)f(more)g(coarsely)h (spaced,)g(and)0 894 y(will)31 b(pro)s(duce)e(higher)h(compression)g (factors.)0 1054 y(When)h(\015oating)g(p)s(oin)m(t)g(images)h(are)f(b)s (eing)g(quan)m(tized,)h(one)f(m)m(ust)g(also)h(sp)s(ecify)e(what)h (quan)m(tization)h(metho)s(d)0 1167 y(is)g(to)h(b)s(e)e(used.)44 b(The)32 b(default)g(algorithm)g(is)g(called)h(\\SUBTRA)m(CTIVE)p 2567 1167 28 4 v 33 w(DITHER)p 2965 1167 V 33 w(1".)46 b(A)32 b(second)g(v)-5 b(ariation)0 1280 y(called)30 b(\\SUBTRA)m(CTIVE)p 982 1280 V 33 w(DITHER)p 1380 1280 V 33 w(2")g(is)f(also)h(a)m(v)-5 b(ailable,)32 b(whic)m(h)d(do)s(es)g (the)h(same)f(thing)h(except)g(that)g(an)m(y)0 1393 y(pixels)g(with)g (a)g(v)-5 b(alue)31 b(of)f(0.0)h(are)f(not)g(dithered)g(and)f(instead)h (the)g(zero)h(v)-5 b(alues)30 b(are)h(exactly)g(preserv)m(ed)f(in)g (the)0 1506 y(compressed)35 b(image.)58 b(One)35 b(ma)m(y)h(also)h (turn)d(o\013)i(dithering)g(completely)h(with)e(the)h(\\NO)p 3148 1506 V 33 w(DITHER")g(option,)0 1619 y(but)30 b(this)g(is)g(not)h (recommended)f(b)s(ecause)g(it)h(can)g(cause)g(larger)g(systematic)h (errors)e(in)g(measuremen)m(ts)g(of)h(the)0 1732 y(p)s(osition)f(or)h (brigh)m(tness)f(of)g(ob)5 b(jects)32 b(in)e(the)g(compressed)g(image.) 0 1892 y(There)37 b(are)g(3)h(metho)s(ds)e(for)h(sp)s(ecifying)g(all)h (the)g(parameters)f(needed)g(to)h(write)f(a)h(FITS)e(image)j(in)d(the)i (tile)0 2005 y(compressed)28 b(format.)41 b(The)28 b(parameters)g(ma)m (y)h(either)g(b)s(e)f(sp)s(eci\014ed)g(at)h(run)e(time)i(as)g(part)f (of)h(the)g(\014le)f(name)h(of)0 2118 y(the)e(output)f(compressed)h (FITS)e(\014le,)j(or)f(the)g(writing)f(program)h(ma)m(y)g(call)h(a)f (set)g(of)g(help)s(er)f(CFITSIO)f(subrou-)0 2230 y(tines)36 b(that)g(are)g(pro)m(vided)f(for)h(sp)s(ecifying)f(the)h(parameter)g(v) -5 b(alues,)37 b(or)f(\\compression)g(directiv)m(e")i(k)m(eyw)m(ords)0 2343 y(ma)m(y)c(b)s(e)e(added)h(to)g(the)h(header)f(of)g(eac)m(h)h (image)h(HDU)e(to)h(sp)s(ecify)f(the)g(compression)g(parameters.)50 b(These)33 b(3)0 2456 y(metho)s(ds)d(are)g(describ)s(ed)g(b)s(elo)m(w.) 0 2616 y(1\))23 b(A)m(t)g(run)e(time,)k(when)c(sp)s(ecifying)h(the)h (name)f(of)g(the)h(output)f(FITS)f(\014le)i(to)g(b)s(e)e(created,)k (the)e(user)e(can)i(indicate)0 2729 y(that)32 b(images)g(should)e(b)s (e)h(written)g(in)g(tile-compressed)i(format)e(b)m(y)h(enclosing)g(the) f(compression)h(parameters)0 2842 y(in)e(square)g(brac)m(k)m(ets)i (follo)m(wing)g(the)e(ro)s(ot)h(disk)f(\014le)g(name)h(in)f(the)h (follo)m(wing)g(format:)191 3100 y Fe([compress)45 b(NAME)i(T1,T2;)f (q[z])h(QLEVEL,)e(s)j(HSCALE])0 3359 y Fj(where)191 3617 y Fe(NAME)142 b(=)47 b(algorithm)f(name:)94 b(GZIP,)46 b(Rice,)h(HCOMPRESS,)e(HSCOMPRSS)g(or)i(PLIO)620 3730 y(may)g(be)h(abbreviated)c(to)j(the)g(first)g(letter)f(\(or)h(HS)g(for) g(HSCOMPRESS\))191 3843 y(T1,T2)94 b(=)47 b(tile)g(dimension)e(\(e.g.)i (100,100)f(for)g(square)h(tiles)f(100)h(pixels)f(wide\))191 3955 y(QLEVEL)g(=)h(quantization)e(level)h(for)h(floating)f(point)g (FITS)h(images)191 4068 y(HSCALE)f(=)h(HCOMPRESS)f(scale)g(factor;)g (default)g(=)h(0)h(which)e(is)h(lossless.)0 4327 y Fj(Here)31 b(are)g(a)f(few)h(examples)f(of)h(this)f(extended)h(syn)m(tax:)191 4585 y Fe(myfile.fit[compress])185 b(-)48 b(use)f(the)g(default)e (compression)g(algorithm)g(\(Rice\))1432 4698 y(and)i(the)g(default)e (tile)i(size)g(\(row)f(by)i(row\))191 4924 y(myfile.fit[compress)42 b(G])48 b(-)f(use)g(the)g(specified)e(compression)g(algorithm;)191 5036 y(myfile.fit[compress)d(R])239 b(only)46 b(the)h(first)f(letter)h (of)g(the)g(algorithm)191 5149 y(myfile.fit[compress)42 b(P])239 b(should)46 b(be)h(given.)191 5262 y(myfile.fit[compress)42 b(H])191 5488 y(myfile.fit[compress)g(R)48 b(100,100])141 b(-)47 b(use)g(Rice)g(and)g(100)g(x)g(100)g(pixel)f(tiles)191 5714 y(myfile.fit[compress)c(R;)48 b(q)f(10.0])f(-)i(quantization)c (level)j(=)g(\(RMS-noise\))e(/)i(10.)p eop end %%Page: 50 58 TeXDict begin 50 57 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.50) cvn H.B /DEST pdfmark end 0 299 a Fj(50)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)191 555 y Fe(myfile.fit[compress)42 b(R;)48 b(qz)f(10.0])f(-)i(quantization)c(level)i(=)i(\(RMS-noise\))d(/)i(10.) 1050 668 y(also)g(use)g(the)f(SUBTRACTIVE_DITHER_2)d(quantization)h (method)191 781 y(myfile.fit[compress)e(HS;)47 b(s)h(2.0])94 b(-)h(HSCOMPRESS)45 b(\(with)i(smoothing\))2005 894 y(and)f(scale)h(=)g (2.0)g(*)h(RMS-noise)0 1116 y Fj(2\))29 b(Before)g(calling)g(the)f (CFITSIO)e(routine)i(to)h(write)f(the)g(image)h(header)f(k)m(eyw)m (ords)g(\(e.g.,)j(\014ts)p 3335 1116 28 4 v 32 w(create)p 3603 1116 V 34 w(image\))0 1228 y(the)37 b(programmer)g(can)g(call)i (the)e(routines)g(describ)s(ed)f(b)s(elo)m(w)h(to)h(sp)s(ecify)f(the)g (compression)g(algorithm)i(and)0 1341 y(the)g(tiling)h(pattern)f(that)g (is)g(to)g(b)s(e)f(used.)65 b(There)38 b(are)i(routines)e(for)h(sp)s (ecifying)f(the)h(v)-5 b(arious)39 b(compression)0 1454 y(parameters)31 b(and)e(similar)i(routines)f(to)i(return)d(the)h (curren)m(t)h(v)-5 b(alues)30 b(of)h(the)f(parameters:)95 1676 y Fe(int)47 b(fits_set_compression_type\()o(fit)o(sfil)o(e)42 b(*fptr,)k(int)h(comptype,)e(int)i(*status\))95 1789 y(int)g(fits_set_tile_dim\(fitsfile)41 b(*fptr,)46 b(int)h(ndim,)f (long)h(*tilesize,)e(int)i(*status\))95 1902 y(int)g (fits_set_quantize_level\(fi)o(tsf)o(ile)41 b(*fptr,)46 b(float)h(qlevel,)f(int)h(*status\))95 2015 y(int)g (fits_set_quantize_method\(f)o(its)o(file)41 b(*fptr,)46 b(int)h(method,)f(int)h(*status\))95 2128 y(int)g (fits_set_quantize_dither\(f)o(its)o(file)41 b(*fptr,)46 b(int)h(dither,)f(int)h(*status\))95 2240 y(int)g (fits_set_dither_seed\(fitsf)o(ile)41 b(*fptr,)46 b(int)h(seed,)g(int)f (*status\))95 2353 y(int)h(fits_set_dither_offset\(fit)o(sfi)o(le)42 b(*fptr,)k(int)h(offset,)e(int)i(*status\))95 2466 y(int)g (fits_set_lossy_int\(fitsfil)o(e)42 b(*fptr,)k(int)h(lossy_int,)e(int)i (*status\))286 2579 y(this)g(forces)f(integer)g(image)g(to)h(be)h (converted)d(to)i(floats,)f(then)h(quantized)95 2692 y(int)g(fits_set_huge_hdu\(fitsfile)41 b(*fptr,)46 b(int)h(huge,)f(int) h(*status\);)286 2805 y(this)g(should)f(be)h(called)f(when)h(the)g (compressed)e(image)h(size)h(is)g(more)g(than)f(4)i(GB.)95 2918 y(int)f(fits_set_hcomp_scale\(fitsf)o(ile)41 b(*fptr,)46 b(float)h(scale,)f(int)h(*status\))95 3031 y(int)g (fits_set_hcomp_smooth\(fits)o(fil)o(e)42 b(*fptr,)k(int)h(smooth,)f (int)h(*status\))668 3144 y(Set)g(smooth)f(=)i(1)f(to)g(apply)g (smoothing)e(when)i(uncompressing)d(the)j(image)95 3370 y(int)g(fits_get_compression_type\()o(fit)o(sfil)o(e)42 b(*fptr,)k(int)h(*comptype,)e(int)i(*status\))95 3482 y(int)g(fits_get_tile_dim\(fitsfile)41 b(*fptr,)46 b(int)h(ndim,)f (long)h(*tilesize,)e(int)i(*status\))95 3595 y(int)g (fits_get_quantize_level\(fi)o(tsf)o(ile)41 b(*fptr,)46 b(float)h(*level,)f(int)h(*status\))95 3708 y(int)g (fits_get_hcomp_scale\(fitsf)o(ile)41 b(*fptr,)46 b(float)h(*scale,)e (int)i(*status\))0 3930 y Fj(Sev)m(eral)33 b(sym)m(b)s(olic)f(constan)m (ts)h(are)f(de\014ned)e(for)i(use)f(as)h(the)g(v)-5 b(alue)33 b(of)f(the)f(`compt)m(yp)s(e')i(parameter:)44 b(GZIP)p 3802 3930 V 32 w(1,)0 4043 y(GZIP)p 227 4043 V 32 w(2,)j(RICE)p 604 4043 V 32 w(1,)f(HCOMPRESS)p 1333 4043 V 32 w(1)d(or)g(PLIO)p 1800 4043 V 32 w(1.)78 b(En)m(tering)43 b(NULL)g(for)g(compt)m(yp)s(e)g (will)g(turn)f(o\013)h(the)0 4156 y(tile-compression)32 b(and)e(cause)h(normal)f(FITS)g(images)h(to)g(b)s(e)f(written.)0 4316 y(There)20 b(are)g(also)i(de\014ned)d(sym)m(b)s(olic)h(constan)m (ts)i(for)e(the)g(quan)m(tization)i(metho)s(d:)36 b(\\SUBTRA)m(CTIVE)p 3507 4316 V 32 w(DITHER)p 3904 4316 V 33 w(1",)0 4429 y(\\SUBTRA)m(CTIVE)p 726 4429 V 33 w(DITHER)p 1124 4429 V 32 w(2",)c(and)e(\\NO)p 1664 4429 V 33 w(DITHER".)0 4589 y(3\))g(CFITSIO)e(will)i(uses)f(the)h(v)-5 b(alues)29 b(of)h(the)g(follo)m(wing)g(k)m(eyw)m(ords,)h(if)e(they)h(are)g(presen) m(t)f(in)g(the)h(header)f(of)h(the)0 4702 y(image)k(HDU,)g(to)g (determine)f(ho)m(w)g(to)h(compress)f(that)g(HDU.)h(These)f(k)m(eyw)m (ords)g(o)m(v)m(erride)i(an)m(y)e(compression)0 4815 y(parameters)e(that)g(w)m(ere)g(sp)s(eci\014ed)e(with)h(the)h(previous) f(2)g(metho)s(ds.)95 5036 y Fe(FZALGOR)94 b(-)47 b('RICE_1')f(,)h ('GZIP_1',)f('GZIP_2',)f('HCOMPRESS_1',)f('PLIO_1',)h('NONE')95 5149 y(FZTILE)142 b(-)47 b('ROW',)g('WHOLE',)e(or)i('\(n,m\)')95 5262 y(FZQVALUE)f(-)h(float)g(value)f(\(default)g(=)h(4.0\))95 5375 y(FZQMETHD)f(-)h('SUBTRACTIVE_DITHER_1',)42 b ('SUBTRACTIVE_DITHER_2',)f('NO_DITHER')95 5488 y(FZDTHRSD)46 b(-)h('CLOCK',)f('CHECKSUM',)f(1)i(-)h(10000)95 5601 y(FZINT2F)94 b(-)h(T,)47 b(or)h(F:)94 b(Convert)46 b(integers)g(to)h (floats,)f(then)g(quantize?)95 5714 y(FZHSCALE)g(-)h(float)g(value)f (\(default)g(=)h(0\).)95 b(Hcompress)45 b(scale)h(value.)p eop end %%Page: 51 59 TeXDict begin 51 58 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.51) cvn H.B /DEST pdfmark end 0 299 a Fh(5.6.)72 b(IMA)m(GE)31 b(COMPRESSION)2567 b Fj(51)0 555 y(No)23 b(sp)s(ecial)f(action)i(is)e (required)f(b)m(y)h(soft)m(w)m(are)i(when)d(read)h(tile-compressed)h (images)g(b)s(ecause)f(all)h(the)f(CFITSIO)0 668 y(routines)35 b(that)g(read)g(normal)g(uncompressed)f(FITS)g(images)i(also)g (transparen)m(tly)g(read)e(images)j(in)d(the)h(tile-)0 781 y(compressed)28 b(format;)h(CFITSIO)e(essen)m(tially)j(treats)f (the)f(binary)g(table)h(that)f(con)m(tains)i(the)e(compressed)g(tiles)0 894 y(as)j(if)f(it)h(w)m(ere)g(an)f(IMA)m(GE)h(extension.)0 1054 y(The)f(follo)m(wing)i(2)e(routines)h(are)f(a)m(v)-5 b(ailable)33 b(for)d(compressing)h(or)f(or)g(decompressing)h(an)f (image:)95 1309 y Fe(int)47 b(fits_img_compress\(fitsfile)41 b(*infptr,)46 b(fitsfile)f(*outfptr,)g(int)i(*status\);)95 1421 y(int)g(fits_img_decompress)c(\(fitsfile)i(*infptr,)h(fitsfile)f (*outfptr,)h(int)g(*status\);)0 1676 y Fj(Before)30 b(calling)h(the)f (compression)f(routine,)h(the)g(compression)f(parameters)h(m)m(ust)f (\014rst)g(b)s(e)g(de\014ned)f(in)h(one)h(of)0 1789 y(the)e(3)h(w)m(a)m (y)g(describ)s(ed)e(in)h(the)g(previous)g(paragraphs.)39 b(There)28 b(is)g(also)h(a)f(routine)h(to)f(determine)h(if)f(the)g (curren)m(t)0 1902 y(HDU)j(con)m(tains)h(a)e(tile)i(compressed)e(image) i(\(it)f(returns)e(1)i(or)f(0\):)95 2156 y Fe(int)47 b(fits_is_compressed_image\(f)o(its)o(file)41 b(*fptr,)46 b(int)h(*status\);)0 2411 y Fj(A)30 b(small)g(example)g(program)f (called)i('imcop)m(y')f(is)g(included)f(with)g(CFITSIO)f(that)i(can)f (b)s(e)g(used)g(to)h(compress)0 2524 y(\(or)44 b(uncompress\))g(an)m(y) g(FITS)g(image.)83 b(This)43 b(program)h(can)h(b)s(e)e(used)h(to)g(exp) s(erimen)m(t)h(with)f(the)g(v)-5 b(arious)0 2637 y(compression)30 b(options)h(on)f(existing)i(FITS)d(images)j(as)e(sho)m(wn)g(in)g(these) h(examples:)0 2891 y Fe(1\))95 b(imcopy)46 b(infile.fit)f ('outfile.fit[compress]')334 3117 y(This)i(will)f(use)h(the)g(default)f (compression)f(algorithm)g(\(Rice\))h(and)h(the)334 3230 y(default)f(tile)h(size)f(\(row)h(by)g(row\))0 3456 y(2\))95 b(imcopy)46 b(infile.fit)f('outfile.fit[compress)d(GZIP]')334 3681 y(This)47 b(will)f(use)h(the)g(GZIP)g(compression)e(algorithm)g (and)i(the)g(default)334 3794 y(tile)g(size)f(\(row)h(by)g(row\).)94 b(The)47 b(allowed)f(compression)f(algorithms)g(are)334 3907 y(Rice,)h(GZIP,)h(and)g(PLIO.)94 b(Only)46 b(the)h(first)g(letter) f(of)h(the)g(algorithm)334 4020 y(name)g(needs)f(to)h(be)g(specified.)0 4246 y(3\))95 b(imcopy)46 b(infile.fit)f('outfile.fit[compress)d(G)47 b(100,100]')334 4472 y(This)g(will)f(use)h(the)g(GZIP)g(compression)e (algorithm)g(and)i(100)g(X)g(100)g(pixel)334 4585 y(tiles.)0 4811 y(4\))95 b(imcopy)46 b(infile.fit)f('outfile.fit[compress)d(R)47 b(100,100;)f(qz)h(10.0]')334 5036 y(This)g(will)f(use)h(the)g(Rice)g (compression)e(algorithm,)g(100)h(X)i(100)f(pixel)334 5149 y(tiles,)f(and)h(quantization)e(level)h(=)h(RMSnoise)f(/)h(10.0)g (\(assuming)e(the)334 5262 y(input)h(image)h(has)g(a)g(floating)f (point)g(data)h(type\).)f(By)h(specifying)334 5375 y(qz)g(instead)f(of) h(q,)g(this)g(means)f(use)h(the)g(subtractive)e(dither2)334 5488 y(quantization)g(method.)0 5714 y(5\))95 b(imcopy)46 b(infile.fit)f(outfile.fit)p eop end %%Page: 52 60 TeXDict begin 52 59 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.52) cvn H.B /DEST pdfmark end 0 299 a Fj(52)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)334 668 y Fe(If)47 b(the)g(input)g(file)f(is)h(in)h (tile-compressed)43 b(format,)j(then)h(it)g(will)f(be)334 781 y(uncompressed)f(to)i(the)g(output)f(file.)94 b(Otherwise,)45 b(it)i(simply)f(copies)334 894 y(the)h(input)f(image)h(to)g(the)g (output)f(image.)0 1120 y(6\))95 b(imcopy)46 b ('infile.fit[1001:1500,20)o(01:2)o(500])o(')89 b(outfile.fit)334 1346 y(This)47 b(extracts)e(a)j(500)f(X)g(500)g(pixel)f(section)g(of)h (the)g(much)g(larger)334 1458 y(input)f(image)h(\(which)f(may)h(be)g (in)g(tile-compressed)d(format\).)93 b(The)334 1571 y(output)46 b(is)h(a)h(normal)e(uncompressed)e(FITS)j(image.)0 1797 y(7\))95 b(imcopy)46 b('infile.fit[1001:1500,20)o(01:2)o(500])o(')89 b(outfile.fit.gz)334 2023 y(Same)47 b(as)g(above,)f(except)g(the)h (output)f(file)h(is)g(externally)e(compressed)334 2136 y(using)h(the)h(gzip)g(algorithm.)0 2397 y SDict begin H.S end 0 2397 a 0 2397 a SDict begin 13.6 H.A end 0 2397 a 0 2397 a SDict begin [ /View [/XYZ H.V] /Dest (section.5.7) cvn H.B /DEST pdfmark end 0 2397 a 197 x Ff(5.7)135 b(ASCI)t(I)45 b(and)f(Binary)h(T)-11 b(able)45 b(Routines)0 2846 y Fj(These)36 b(routines)g(p)s(erform)f(read)i(and)e(write)i(op)s (erations)g(on)f(columns)g(of)h(data)g(in)f(FITS)g(ASCI)s(I)e(or)j (Binary)0 2959 y(tables.)47 b(Note)33 b(that)g(in)e(the)i(follo)m(wing) g(discussions,)f(the)g(\014rst)g(ro)m(w)g(and)f(column)h(in)g(a)g (table)h(is)g(at)f(p)s(osition)h(1)0 3072 y(not)e(0.)0 3232 y(Users)k(should)g(also)i(read)e(the)h(follo)m(wing)h(c)m(hapter)g (on)e(the)h(CFITSIO)e(iterator)j(function)f(whic)m(h)f(pro)m(vides)h(a) 0 3345 y(more)i(`ob)5 b(ject)39 b(orien)m(ted')g(metho)s(d)f(of)g (reading)g(and)g(writing)g(table)h(columns.)63 b(The)37 b(iterator)j(function)d(is)i(a)0 3458 y(little)e(more)f(complicated)h (to)f(use,)h(but)e(the)g(adv)-5 b(an)m(tages)38 b(are)d(that)i(it)f (usually)f(tak)m(es)i(less)e(co)s(de)h(to)g(p)s(erform)0 3571 y(the)h(same)f(op)s(eration,)j(and)c(the)i(resulting)f(program)g (often)h(runs)e(faster)i(b)s(ecause)f(the)g(FITS)g(\014les)g(are)h (read)0 3684 y(and)30 b(written)g(using)g(the)h(most)f(e\016cien)m(t)i (blo)s(c)m(k)f(size.)0 3840 y SDict begin H.S end 0 3840 a 0 3840 a SDict begin 13.6 H.A end 0 3840 a 0 3840 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.5.7.1) cvn H.B /DEST pdfmark end 0 3840 a 146 x Fd(5.7.1)112 b(Create)38 b(New)f(T)-9 b(able)0 4202 y Fi(1)81 b Fj(Create)40 b(a)f(new)g(ASCI)s(I)e(or)i(bin) m(table)h(table)g(extension.)68 b(If)39 b(the)g(FITS)g(\014le)g(is)g (curren)m(tly)g(empt)m(y)h(then)f(a)227 4315 y(dumm)m(y)25 b(primary)f(arra)m(y)i(will)g(b)s(e)f(created)i(b)s(efore)e(app)s (ending)f(the)i(table)g(extension)h(to)f(it.)40 b(The)25 b(tblt)m(yp)s(e)227 4428 y(parameter)39 b(de\014nes)e(the)h(t)m(yp)s(e) h(of)f(table)h(and)e(can)i(ha)m(v)m(e)g(v)-5 b(alues)39 b(of)f(ASCI)s(I)p 2924 4428 28 4 v 31 w(TBL)g(or)g(BINAR)-8 b(Y)p 3659 4428 V 34 w(TBL.)227 4541 y(The)29 b(naxis2)g(parameter)h (giv)m(es)g(the)g(initial)g(n)m(um)m(b)s(er)e(of)h(ro)m(ws)g(to)h(b)s (e)f(created)h(in)f(the)g(table,)h(and)f(should)227 4654 y(normally)h(b)s(e)f(set)h(=)g(0.)40 b(CFITSIO)29 b(will)h (automatically)i(increase)f(the)e(size)i(of)f(the)g(table)g(as)g (additional)227 4767 y(ro)m(ws)d(are)g(written.)40 b(A)27 b(non-zero)g(n)m(um)m(b)s(er)f(of)h(ro)m(ws)g(ma)m(y)g(b)s(e)f(sp)s (eci\014ed)g(to)i(reserv)m(e)f(space)h(for)e(that)i(man)m(y)227 4880 y(ro)m(ws,)41 b(ev)m(en)e(if)g(a)g(few)m(er)g(n)m(um)m(b)s(er)e (of)i(ro)m(ws)f(will)h(b)s(e)f(written.)66 b(The)38 b(tunit)g(and)g (extname)i(parameters)227 4993 y(are)e(optional)g(and)f(a)h(n)m(ull)f (p)s(oin)m(ter)g(ma)m(y)h(b)s(e)f(giv)m(en)h(if)g(they)f(are)h(not)f (de\014ned.)61 b(The)37 b(FITS)f(Standard)227 5106 y(recommends)29 b(that)h(only)g(letters,)h(digits,)g(and)e(the)g(underscore)g(c)m (haracter)i(b)s(e)e(used)g(in)g(column)g(names)227 5219 y(\(the)c(tt)m(yp)s(e)g(parameter\))g(with)e(no)h(em)m(b)s(edded)f (spaces.)40 b(T)-8 b(railing)24 b(blank)g(c)m(haracters)i(are)e(not)h (signi\014can)m(t.)95 5601 y Fe(int)47 b(fits_create_tbl)d(/)j(ffcrtb) 286 5714 y(\(fitsfile)f(*fptr,)g(int)h(tbltype,)e(LONGLONG)h(naxis2,)g (int)g(tfields,)g(char)h(*ttype[],)p eop end %%Page: 53 61 TeXDict begin 53 60 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.53) cvn H.B /DEST pdfmark end 0 299 a Fh(5.7.)72 b(ASCI)s(I)29 b(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(R)m(OUTINES)1864 b Fj(53)334 555 y Fe(char)47 b(*tform[],)e(char)i(*tunit[],)e(char)i (*extname,)e(int)i(*status\))0 693 y SDict begin H.S end 0 693 a 0 693 a SDict begin 13.6 H.A end 0 693 a 0 693 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.5.7.2) cvn H.B /DEST pdfmark end 0 693 a 151 x Fd(5.7.2)112 b(Column)39 b(Information)f(Routines)0 1050 y Fi(1)81 b Fj(Get)30 b(the)g(n)m(um)m(b)s(er)e(of)i(ro)m(ws)g(or)f(columns)g(in)h(the)g (curren)m(t)f(FITS)g(table.)41 b(The)29 b(n)m(um)m(b)s(er)f(of)i(ro)m (ws)g(is)f(giv)m(en)i(b)m(y)227 1163 y(the)j(NAXIS2)f(k)m(eyw)m(ord)h (and)e(the)i(n)m(um)m(b)s(er)e(of)h(columns)g(is)g(giv)m(en)h(b)m(y)f (the)h(TFIELDS)e(k)m(eyw)m(ord)i(in)f(the)227 1276 y(header)d(of)h(the) g(table.)95 1521 y Fe(int)47 b(fits_get_num_rows)c(/)48 b(ffgnrw)286 1634 y(\(fitsfile)e(*fptr,)g(>)h(long)g(*nrows,)f(int)h (*status\);)95 1860 y(int)g(fits_get_num_rowsll)c(/)k(ffgnrwll)286 1973 y(\(fitsfile)f(*fptr,)g(>)h(LONGLONG)f(*nrows,)g(int)g(*status\);) 95 2199 y(int)h(fits_get_num_cols)c(/)48 b(ffgncl)286 2312 y(\(fitsfile)e(*fptr,)g(>)h(int)g(*ncols,)f(int)h(*status\);)0 2557 y Fi(2)81 b Fj(Get)25 b(the)f(table)i(column)e(n)m(um)m(b)s(er)f (\(and)h(name\))h(of)f(the)h(column)f(whose)g(name)g(matc)m(hes)i(an)e (input)g(template)227 2670 y(name.)48 b(If)32 b(casesen)i(=)e(CASESEN)g (then)g(the)h(column)f(name)h(matc)m(h)h(will)f(b)s(e)f(case-sensitiv)m (e,)k(whereas)227 2783 y(if)27 b(casesen)h(=)e(CASEINSEN)g(then)h(the)g (case)h(will)f(b)s(e)f(ignored.)40 b(As)27 b(a)g(general)h(rule,)f(the) g(column)g(names)227 2895 y(should)j(b)s(e)f(treated)j(as)e(case)i (INsensitiv)m(e.)227 3043 y(The)26 b(input)g(column)g(name)g(template)i (ma)m(y)f(b)s(e)f(either)h(the)g(exact)h(name)e(of)h(the)f(column)g(to) i(b)s(e)d(searc)m(hed)227 3156 y(for,)k(or)f(it)h(ma)m(y)g(con)m(tain)h (wild)e(card)g(c)m(haracters)i(\(*,)g(?,)f(or)f(#\),)h(or)f(it)h(ma)m (y)g(con)m(tain)h(the)e(in)m(teger)i(n)m(um)m(b)s(er)227 3269 y(of)j(the)f(desired)f(column)h(\(with)g(the)h(\014rst)e(column)h (=)g(1\).)46 b(The)32 b(`*')h(wild)f(card)g(c)m(haracter)h(matc)m(hes)h (an)m(y)227 3382 y(sequence)h(of)g(c)m(haracters)h(\(including)f(zero)g (c)m(haracters\))i(and)d(the)h(`?')53 b(c)m(haracter)36 b(matc)m(hes)g(an)m(y)f(single)227 3495 y(c)m(haracter.)42 b(The)29 b(#)h(wildcard)f(will)h(matc)m(h)h(an)m(y)e(consecutiv)m(e)j (string)e(of)f(decimal)i(digits)f(\(0-9\).)43 b(If)29 b(more)227 3608 y(than)43 b(one)f(column)h(name)f(in)g(the)h(table)h (matc)m(hes)f(the)g(template)h(string,)i(then)c(the)h(\014rst)e(matc)m (h)j(is)227 3721 y(returned)28 b(and)h(the)g(status)h(v)-5 b(alue)30 b(will)f(b)s(e)g(set)h(to)g(COL)p 2171 3721 28 4 v 32 w(NOT)p 2408 3721 V 32 w(UNIQUE)f(as)h(a)f(w)m(arning)g(that) h(a)g(unique)227 3834 y(matc)m(h)e(w)m(as)g(not)f(found.)39 b(T)-8 b(o)27 b(\014nd)f(the)h(other)g(cases)h(that)g(matc)m(h)g(the)g (template,)h(call)f(the)g(routine)f(again)227 3947 y(lea)m(ving)g(the)e (input)f(status)h(v)-5 b(alue)26 b(equal)f(to)h(COL)p 1950 3947 V 32 w(NOT)p 2187 3947 V 32 w(UNIQUE)f(and)f(the)h(next)h (matc)m(hing)g(name)f(will)227 4059 y(then)30 b(b)s(e)g(returned.)40 b(Rep)s(eat)30 b(this)h(pro)s(cess)f(un)m(til)g(a)h(status)g(=)f(COL)p 2628 4059 V 32 w(NOT)p 2865 4059 V 32 w(F)m(OUND)i(is)e(returned.)227 4207 y(The)36 b(FITS)g(Standard)g(recommends)g(that)i(only)e(letters,)k (digits,)f(and)d(the)h(underscore)f(c)m(haracter)j(b)s(e)227 4320 y(used)31 b(in)g(column)g(names)g(\(with)h(no)f(em)m(b)s(edded)f (spaces\).)45 b(T)-8 b(railing)32 b(blank)f(c)m(haracters)i(are)e(not)h (signi\014-)227 4433 y(can)m(t.)95 4678 y Fe(int)47 b(fits_get_colnum)d (/)j(ffgcno)286 4791 y(\(fitsfile)f(*fptr,)g(int)h(casesen,)e(char)i (*templt,)e(>)j(int)f(*colnum,)334 4904 y(int)g(*status\))95 5130 y(int)g(fits_get_colname)d(/)j(ffgcnn)286 5243 y(\(fitsfile)f (*fptr,)g(int)h(casesen,)e(char)i(*templt,)e(>)j(char)e(*colname,)334 5356 y(int)h(*colnum,)f(int)g(*status\))0 5601 y Fi(3)81 b Fj(Return)30 b(the)i(data)g(t)m(yp)s(e,)h(v)m(ector)g(rep)s(eat)f(v) -5 b(alue,)32 b(and)f(the)h(width)f(in)g(b)m(ytes)h(of)g(a)g(column)f (in)g(an)h(ASCI)s(I)e(or)227 5714 y(binary)35 b(table.)56 b(Allo)m(w)m(ed)37 b(v)-5 b(alues)36 b(for)f(the)h(data)g(t)m(yp)s(e)f (in)g(ASCI)s(I)f(tables)i(are:)51 b(TSTRING,)35 b(TSHOR)-8 b(T,)p eop end %%Page: 54 62 TeXDict begin 54 61 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.54) cvn H.B /DEST pdfmark end 0 299 a Fj(54)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)227 555 y Fj(TLONG,)36 b(TFLO)m(A)-8 b(T,)36 b(and)f(TDOUBLE.)i(Binary)e(tables)i(also)g(supp)s(ort)d(these)i(t)m (yp)s(es:)52 b(TLOGICAL,)227 668 y(TBIT,)38 b(TBYTE,)h(TCOMPLEX)e(and)h (TDBLCOMPLEX.)h(The)f(negativ)m(e)i(of)f(the)g(data)g(t)m(yp)s(e)g(co)s (de)227 781 y(v)-5 b(alue)32 b(is)f(returned)f(if)h(it)g(is)h(a)f(v)-5 b(ariable)32 b(length)f(arra)m(y)h(column.)43 b(Note)32 b(that)g(in)e(the)i(case)g(of)f(a)g('J')h(32-bit)227 894 y(in)m(teger)g(binary)d(table)i(column,)f(this)g(routine)g(will)g (return)f(data)i(t)m(yp)s(e)f(=)g(TINT32BIT)g(\(whic)m(h)g(in)g(fact) 227 1007 y(is)36 b(equiv)-5 b(alen)m(t)37 b(to)g(TLONG\).)f(With)g (most)g(curren)m(t)g(C)f(compilers,)j(a)f(v)-5 b(alue)36 b(in)f(a)i('J')f(column)f(has)h(the)227 1120 y(same)29 b(size)g(as)g(an)f('in)m(t')i(v)-5 b(ariable,)30 b(and)d(ma)m(y)j(not)e (b)s(e)g(equiv)-5 b(alen)m(t)30 b(to)f(a)g('long')g(v)-5 b(ariable,)30 b(whic)m(h)e(is)h(64-bits)227 1233 y(long)i(on)g(an)f (increasing)h(n)m(um)m(b)s(er)e(of)h(compilers.)227 1400 y(The)22 b('rep)s(eat')h(parameter)g(returns)f(the)g(v)m(ector)i(rep)s (eat)f(coun)m(t)g(on)f(the)h(binary)f(table)h(TF)m(ORMn)f(k)m(eyw)m (ord)227 1513 y(v)-5 b(alue.)60 b(\(ASCI)s(I)35 b(table)j(columns)e (alw)m(a)m(ys)i(ha)m(v)m(e)g(rep)s(eat)e(=)g(1\).)60 b(The)36 b('width')g(parameter)h(returns)f(the)227 1626 y(width)30 b(in)g(b)m(ytes)h(of)g(a)f(single)h(column)g(elemen)m(t)h (\(e.g.,)g(a)f('10D')h(binary)e(table)h(column)f(will)h(ha)m(v)m(e)h (width)227 1739 y(=)d(8,)i(an)e(ASCI)s(I)f(table)i('F12.2')i(column)e (will)g(ha)m(v)m(e)g(width)f(=)g(12,)i(and)e(a)h(binary)e(table'60A')k (c)m(haracter)227 1852 y(string)44 b(column)g(will)g(ha)m(v)m(e)h (width)e(=)h(60\);)52 b(Note)45 b(that)f(CFITSIO)f(supp)s(orts)f(the)i (lo)s(cal)h(con)m(v)m(en)m(tion)227 1965 y(for)d(sp)s(ecifying)f(arra)m (ys)i(of)f(\014xed)f(length)h(strings)f(within)h(a)g(binary)f(table)h (c)m(haracter)i(column)d(using)227 2078 y(the)g(syn)m(tax)g(TF)m(ORM)g (=)g('rAw')f(where)g('r')h(is)g(the)g(total)h(n)m(um)m(b)s(er)d(of)i(c) m(haracters)h(\(=)f(the)g(width)f(of)227 2191 y(the)f(column\))g(and)e ('w')i(is)f(the)h(width)f(of)g(a)h(unit)f(string)g(within)g(the)h (column.)65 b(Th)m(us)37 b(if)h(the)h(column)227 2304 y(has)34 b(TF)m(ORM)h(=)f('60A12')j(then)d(this)g(means)g(that)h(eac)m (h)g(ro)m(w)g(of)f(the)h(table)g(con)m(tains)g(5)g(12-c)m(haracter)227 2416 y(substrings)23 b(within)h(the)g(60-c)m(haracter)j(\014eld,)f(and) d(th)m(us)h(in)g(this)g(case)h(this)g(routine)f(will)g(return)f(t)m(yp) s(eco)s(de)227 2529 y(=)f(TSTRING,)g(rep)s(eat)g(=)g(60,)j(and)d(width) f(=)h(12.)39 b(\(The)22 b(TDIMn)g(k)m(eyw)m(ord)h(ma)m(y)g(also)g(b)s (e)f(used)f(to)i(sp)s(ecify)227 2642 y(the)29 b(unit)e(string)h (length;)i(The)e(pair)g(of)g(k)m(eyw)m(ords)g(TF)m(ORMn)g(=)g('60A')i (and)e(TDIMn)f(=)h('\(12,5\)')j(w)m(ould)227 2755 y(ha)m(v)m(e)g(the)f (same)g(e\013ect)h(as)e(TF)m(ORMn)h(=)f('60A12'\).)43 b(The)29 b(n)m(um)m(b)s(er)f(of)i(substrings)e(in)h(an)m(y)h(binary)f (table)227 2868 y(c)m(haracter)36 b(string)e(\014eld)f(can)h(b)s(e)g (calculated)i(b)m(y)d(\(rep)s(eat/width\).)53 b(A)34 b(n)m(ull)f(p)s(oin)m(ter)h(ma)m(y)h(b)s(e)e(giv)m(en)i(for)227 2981 y(an)m(y)c(of)g(the)f(output)g(parameters)h(that)g(are)g(not)f (needed.)227 3149 y(The)46 b(second)g(routine,)k(\014t)p 1188 3149 28 4 v 33 w(get)p 1341 3149 V 34 w(eqcolt)m(yp)s(e)d(is)f (similar)h(except)g(that)f(in)g(the)g(case)i(of)e(scaled)h(in)m(teger) 227 3262 y(columns)35 b(it)g(returns)f(the)h('equiv)-5 b(alen)m(t')37 b(data)f(t)m(yp)s(e)f(that)h(is)f(needed)f(to)i(store)g (the)f(scaled)h(v)-5 b(alues,)37 b(and)227 3374 y(not)28 b(necessarily)h(the)f(ph)m(ysical)g(data)g(t)m(yp)s(e)g(of)g(the)g (unscaled)f(v)-5 b(alues)29 b(as)e(stored)h(in)g(the)f(FITS)g(table.)41 b(F)-8 b(or)227 3487 y(example)38 b(if)g(a)g('1I')g(column)f(in)g(a)h (binary)f(table)h(has)g(TSCALn)d(=)j(1)f(and)g(TZER)m(On)f(=)i(32768,)j (then)227 3600 y(this)29 b(column)f(e\013ectiv)m(ely)k(con)m(tains)d (unsigned)f(short)g(in)m(teger)i(v)-5 b(alues,)29 b(and)f(th)m(us)h (the)f(returned)g(v)-5 b(alue)29 b(of)227 3713 y(t)m(yp)s(eco)s(de)34 b(will)f(b)s(e)g(TUSHOR)-8 b(T,)32 b(not)h(TSHOR)-8 b(T.)33 b(Similarly)-8 b(,)34 b(if)f(a)h(column)f(has)f(TTYPEn)g(=)h('1I')h (and)227 3826 y(TSCALn)29 b(=)h(0.12,)i(then)e(the)h(returned)e(t)m(yp) s(eco)s(de)i(will)f(b)s(e)g(TFLO)m(A)-8 b(T.)95 4121 y Fe(int)47 b(fits_get_coltype)d(/)j(ffgtcl)286 4233 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(>)j(int)f(*typecode,)e(long)h (*repeat,)334 4346 y(long)h(*width,)f(int)g(*status\))95 4572 y(int)h(fits_get_coltypell)c(/)48 b(ffgtclll)286 4685 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(>)j(int)f(*typecode,)e (LONGLONG)g(*repeat,)334 4798 y(LONGLONG)h(*width,)f(int)i(*status\))95 5024 y(int)g(fits_get_eqcoltype)c(/)48 b(ffeqty)286 5137 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(>)j(int)f(*typecode,)e(long)h (*repeat,)334 5250 y(long)h(*width,)f(int)g(*status\))95 5475 y(int)h(fits_get_eqcoltypell)c(/)k(ffeqtyll)286 5588 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(>)j(int)f(*typecode,)e (LONGLONG)g(*repeat,)334 5701 y(LONGLONG)h(*width,)f(int)i(*status\))p eop end %%Page: 55 63 TeXDict begin 55 62 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.55) cvn H.B /DEST pdfmark end 0 299 a Fh(5.7.)72 b(ASCI)s(I)29 b(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(R)m(OUTINES)1864 b Fj(55)0 555 y Fi(4)81 b Fj(Return)29 b(the)h(displa)m(y)g(width)f(of) h(a)h(column.)40 b(This)29 b(is)h(the)g(length)h(of)f(the)g(string)g (that)h(will)f(b)s(e)f(returned)g(b)m(y)227 668 y(the)34 b(\014ts)p 514 668 28 4 v 32 w(read)p 718 668 V 33 w(col)g(routine)f (when)f(reading)h(the)h(column)e(as)i(a)f(formatted)h(string.)49 b(The)32 b(displa)m(y)i(width)227 781 y(is)29 b(determined)g(b)m(y)g (the)g(TDISPn)f(k)m(eyw)m(ord,)i(if)f(presen)m(t,)h(otherwise)f(b)m(y)g (the)g(data)h(t)m(yp)s(e)f(of)h(the)f(column.)95 1125 y Fe(int)47 b(fits_get_col_display_width)41 b(/)47 b(ffgcdw)286 1238 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(>)j(int)f(*dispwidth,)e (int)h(*status\))0 1470 y Fi(5)81 b Fj(Return)27 b(the)i(n)m(um)m(b)s (er)e(of)i(and)e(size)j(of)e(the)h(dimensions)f(of)g(a)h(table)g (column)g(in)f(a)g(binary)g(table.)41 b(Normally)227 1583 y(this)28 b(information)h(is)f(giv)m(en)h(b)m(y)f(the)h(TDIMn)f(k) m(eyw)m(ord,)h(but)e(if)i(this)f(k)m(eyw)m(ord)g(is)g(not)h(presen)m(t) f(then)g(this)227 1695 y(routine)j(returns)e(naxis)h(=)g(1)h(and)f (naxes[0])h(equal)g(to)g(the)g(rep)s(eat)f(coun)m(t)h(in)f(the)h(TF)m (ORM)g(k)m(eyw)m(ord.)95 1927 y Fe(int)47 b(fits_read_tdim)d(/)k (ffgtdm)286 2040 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(int)i(maxdim,) f(>)i(int)f(*naxis,)334 2153 y(long)g(*naxes,)f(int)g(*status\))95 2378 y(int)h(fits_read_tdimll)d(/)j(ffgtdmll)286 2491 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(int)i(maxdim,)f(>)i(int)f (*naxis,)334 2604 y(LONGLONG)f(*naxes,)f(int)i(*status\))0 2836 y Fi(6)81 b Fj(Deco)s(de)33 b(the)g(input)f(TDIMn)h(k)m(eyw)m(ord) g(string)f(\(e.g.)50 b('\(100,200\)'\))37 b(and)32 b(return)g(the)h(n)m (um)m(b)s(er)e(of)i(and)f(size)227 2949 y(of)c(the)g(dimensions)f(of)h (a)g(binary)f(table)h(column.)40 b(If)27 b(the)h(input)f(tdimstr)g(c)m (haracter)i(string)f(is)g(n)m(ull,)g(then)227 3061 y(this)d(routine)f (returns)f(naxis)h(=)h(1)f(and)g(naxes[0])i(equal)e(to)i(the)e(rep)s (eat)h(coun)m(t)g(in)f(the)g(TF)m(ORM)h(k)m(eyw)m(ord.)227 3174 y(This)30 b(routine)g(is)h(called)g(b)m(y)f(\014ts)p 1350 3174 V 33 w(read)p 1555 3174 V 33 w(tdim.)95 3406 y Fe(int)47 b(fits_decode_tdim)d(/)j(ffdtdm)286 3519 y(\(fitsfile)f(*fptr,)g(char)g(*tdimstr,)g(int)h(colnum,)e(int)i (maxdim,)f(>)i(int)e(*naxis,)334 3632 y(long)h(*naxes,)f(int)g (*status\))95 3857 y(int)h(fits_decode_tdimll)c(/)48 b(ffdtdmll)286 3970 y(\(fitsfile)e(*fptr,)g(char)g(*tdimstr,)g(int)h (colnum,)e(int)i(maxdim,)f(>)i(int)e(*naxis,)334 4083 y(LONGLONG)g(*naxes,)f(int)i(*status\))0 4315 y Fi(7)81 b Fj(W)-8 b(rite)23 b(a)g(TDIMn)f(k)m(eyw)m(ord)h(whose)f(v)-5 b(alue)23 b(has)g(the)f(form)g('\(l,m,n...\)')40 b(where)22 b(l,)i(m,)g(n...)38 b(are)23 b(the)g(dimensions)227 4427 y(of)31 b(a)g(m)m(ultidimensional)g(arra)m(y)g(column)f(in)g(a)h (binary)e(table.)95 4659 y Fe(int)47 b(fits_write_tdim)d(/)j(ffptdm)286 4772 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(int)i(naxis,)f(long)h (*naxes,)f(>)h(int)g(*status\))95 4998 y(int)g(fits_write_tdimll)c(/)48 b(ffptdmll)286 5110 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(int)i (naxis,)f(LONGLONG)g(*naxes,)g(>)h(int)g(*status\))0 5253 y SDict begin H.S end 0 5253 a 0 5253 a SDict begin 13.6 H.A end 0 5253 a 0 5253 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.5.7.3) cvn H.B /DEST pdfmark end 0 5253 a 144 x Fd(5.7.3)112 b(Routines)38 b(to)f(Edit)g(Ro)m(ws)g(or)g(Columns)0 5601 y Fi(1)81 b Fj(Insert)32 b(or)h(delete)i(ro)m(ws)e(in)g(an)g(ASCI) s(I)f(or)h(binary)f(table.)50 b(When)33 b(inserting)h(ro)m(ws)f(all)h (the)f(ro)m(ws)g(follo)m(wing)227 5714 y(ro)m(w)24 b(FR)m(O)m(W)i(are)e (shifted)f(do)m(wn)h(b)m(y)g(NR)m(O)m(WS)g(ro)m(ws;)j(if)c(FR)m(O)m(W)j (=)d(0)i(then)e(the)h(blank)g(ro)m(ws)g(are)g(inserted)p eop end %%Page: 56 64 TeXDict begin 56 63 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.56) cvn H.B /DEST pdfmark end 0 299 a Fj(56)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)227 555 y Fj(at)h(the)e(b)s(eginning)g(of)h(the)f(table.) 42 b(Note)31 b(that)f(it)g(is)f(*not*)i(necessary)f(to)g(insert)f(ro)m (ws)h(in)f(a)h(table)g(b)s(efore)227 668 y(writing)g(data)g(to)g(those) h(ro)m(ws)e(\(indeed,)h(it)g(w)m(ould)f(b)s(e)g(ine\016cien)m(t)i(to)f (do)g(so\).)41 b(Instead)29 b(one)h(ma)m(y)g(simply)227 781 y(write)h(data)g(to)g(an)m(y)g(ro)m(w)f(of)h(the)f(table,)i (whether)e(that)h(ro)m(w)f(of)h(data)g(already)g(exists)g(or)f(not.)227 927 y(The)40 b(\014rst)g(delete)i(routine)e(deletes)i(NR)m(O)m(WS)f (consecutiv)m(e)h(ro)m(ws)f(starting)g(with)f(ro)m(w)g(FIRSTR)m(O)m(W.) 227 1040 y(The)d(second)g(delete)h(routine)f(tak)m(es)h(an)f(input)f (string)h(that)h(lists)f(the)g(ro)m(ws)g(or)g(ro)m(w)g(ranges)g (\(e.g.,)k('5-)227 1153 y(10,12,20-30'\),)32 b(whereas)26 b(the)g(third)g(delete)h(routine)f(tak)m(es)h(an)f(input)f(in)m(teger)j (arra)m(y)e(that)h(sp)s(eci\014es)f(eac)m(h)227 1266 y(individual)35 b(ro)m(w)h(to)g(b)s(e)f(deleted.)58 b(In)35 b(b)s(oth)f(latter)j(cases,)i(the)c(input)g(list)h(of)g(ro)m(ws)g(to)g (delete)h(m)m(ust)f(b)s(e)227 1379 y(sorted)i(in)g(ascending)g(order.) 62 b(These)38 b(routines)f(up)s(date)g(the)h(NAXIS2)g(k)m(eyw)m(ord)h (to)f(re\015ect)g(the)g(new)227 1492 y(n)m(um)m(b)s(er)29 b(of)i(ro)m(ws)f(in)g(the)h(table.)95 1729 y Fe(int)47 b(fits_insert_rows)d(/)j(ffirow)286 1842 y(\(fitsfile)f(*fptr,)g (LONGLONG)f(firstrow,)h(LONGLONG)f(nrows,)h(>)i(int)f(*status\))95 2068 y(int)g(fits_delete_rows)d(/)j(ffdrow)286 2181 y(\(fitsfile)f (*fptr,)g(LONGLONG)f(firstrow,)h(LONGLONG)f(nrows,)h(>)i(int)f (*status\))95 2406 y(int)g(fits_delete_rowrange)c(/)k(ffdrrg)286 2519 y(\(fitsfile)f(*fptr,)g(char)g(*rangelist,)f(>)j(int)e(*status\)) 95 2745 y(int)h(fits_delete_rowlist)c(/)k(ffdrws)286 2858 y(\(fitsfile)f(*fptr,)g(long)g(*rowlist,)g(long)g(nrows,)g(>)i (int)f(*status\))95 3084 y(int)g(fits_delete_rowlistll)42 b(/)48 b(ffdrwsll)286 3197 y(\(fitsfile)e(*fptr,)g(LONGLONG)f (*rowlist,)h(LONGLONG)f(nrows,)h(>)i(int)f(*status\))0 3434 y Fi(2)81 b Fj(Insert)36 b(or)h(delete)i(column\(s\))e(in)g(an)g (ASCI)s(I)f(or)h(binary)f(table.)62 b(When)37 b(inserting,)i(COLNUM)e (sp)s(eci\014es)227 3546 y(the)28 b(column)g(n)m(um)m(b)s(er)f(that)h (the)g(\(\014rst\))g(new)f(column)h(should)f(o)s(ccup)m(y)h(in)g(the)g (table.)41 b(NCOLS)26 b(sp)s(eci\014es)227 3659 y(ho)m(w)35 b(man)m(y)g(columns)f(are)h(to)g(b)s(e)f(inserted.)53 b(An)m(y)35 b(existing)h(columns)e(from)g(this)h(p)s(osition)f(and)g (higher)227 3772 y(are)c(shifted)f(o)m(v)m(er)h(to)g(allo)m(w)g(ro)s (om)f(for)g(the)h(new)e(column\(s\).)41 b(The)29 b(index)f(n)m(um)m(b)s (er)g(on)h(all)h(the)f(follo)m(wing)227 3885 y(k)m(eyw)m(ords)34 b(will)f(b)s(e)g(incremen)m(ted)h(or)f(decremen)m(ted)h(if)f(necessary) h(to)g(re\015ect)g(the)f(new)g(p)s(osition)g(of)h(the)227 3998 y(column\(s\))26 b(in)f(the)h(table:)39 b(TBCOLn,)26 b(TF)m(ORMn,)h(TTYPEn,)e(TUNITn,)h(TNULLn,)g(TSCALn,)f(TZE-)227 4111 y(R)m(On,)43 b(TDISPn,)g(TDIMn,)g(TLMINn,)g(TLMAXn,)g(TDMINn,)g (TDMAXn,)h(TCTYPn,)e(TCRPXn,)227 4224 y(TCR)-10 b(VLn,)29 b(TCDL)-8 b(Tn,)30 b(TCR)m(OTn,)f(and)h(TCUNIn.)95 4461 y Fe(int)47 b(fits_insert_col)d(/)j(fficol)286 4574 y(\(fitsfile)f (*fptr,)g(int)h(colnum,)e(char)i(*ttype,)f(char)h(*tform,)334 4687 y(>)h(int)e(*status\))95 4912 y(int)h(fits_insert_cols)d(/)j (fficls)286 5025 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(int)i(ncols,)f (char)h(**ttype,)334 5138 y(char)g(**tform,)e(>)j(int)f(*status\))95 5364 y(int)g(fits_delete_col)d(/)j(ffdcol\(fitsfile)d(*fptr,)i(int)h (colnum,)f(>)h(int)g(*status\))0 5601 y Fi(3)81 b Fj(Cop)m(y)32 b(a)h(column)g(from)f(one)h(HDU)g(to)h(another)e(\(or)h(to)h(the)f (same)g(HDU\).)h(If)e(create)p 3129 5601 28 4 v 34 w(col)i(=)e(TR)m (UE,)h(then)227 5714 y(a)40 b(new)e(column)h(will)g(b)s(e)g(inserted)g (in)f(the)h(output)g(table,)j(at)e(p)s(osition)f(`outcolumn',)j (otherwise)e(the)p eop end %%Page: 57 65 TeXDict begin 57 64 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.57) cvn H.B /DEST pdfmark end 0 299 a Fh(5.7.)72 b(ASCI)s(I)29 b(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(R)m(OUTINES)1864 b Fj(57)227 555 y(existing)39 b(output)f(column)f(will)i(b)s(e)e(o)m(v) m(erwritten)i(\(in)f(whic)m(h)g(case)h(it)f(m)m(ust)g(ha)m(v)m(e)h(a)f (compatible)h(data)227 668 y(t)m(yp)s(e\).)i(If)29 b(outcoln)m(um)h(is) f(greater)i(than)e(the)h(n)m(um)m(b)s(er)e(of)h(column)g(in)g(the)h (table,)h(then)e(the)g(new)g(column)227 781 y(will)j(b)s(e)f(app)s (ended)f(to)j(the)f(end)f(of)g(the)h(table.)46 b(Note)33 b(that)f(the)g(\014rst)f(column)g(in)h(a)g(table)g(is)g(at)h(coln)m(um) 227 894 y(=)j(1.)58 b(The)36 b(standard)f(indexed)g(k)m(eyw)m(ords)i (that)f(related)h(to)g(the)f(column)g(\(e.g.,)j(TDISPn,)e(TUNITn,)227 1007 y(TCRPXn,)30 b(TCDL)-8 b(Tn,)29 b(etc.\))43 b(will)30 b(also)i(b)s(e)d(copied.)95 1254 y Fe(int)47 b(fits_copy_col)e(/)i (ffcpcl)286 1367 y(\(fitsfile)f(*infptr,)f(fitsfile)h(*outfptr,)f(int)i (incolnum,)e(int)i(outcolnum,)334 1480 y(int)g(create_col,)e(>)i(int)g (*status\);)0 1727 y Fi(4)81 b Fj(Cop)m(y)30 b('nro)m(ws')g(consecutiv) m(e)j(ro)m(ws)d(from)g(one)h(table)g(to)g(another,)g(b)s(eginning)f (with)g(ro)m(w)g('\014rstro)m(w'.)41 b(These)227 1840 y(ro)m(ws)31 b(will)h(b)s(e)e(app)s(ended)g(to)i(an)m(y)f(existing)h (ro)m(ws)g(in)e(the)i(output)e(table.)44 b(Note)33 b(that)f(the)f (\014rst)f(ro)m(w)i(in)f(a)227 1952 y(table)h(is)e(at)h(ro)m(w)g(=)f (1.)95 2199 y Fe(int)47 b(fits_copy_rows)d(/)k(ffcprw)286 2312 y(\(fitsfile)e(*infptr,)f(fitsfile)h(*outfptr,)f(LONGLONG)h (firstrow,)334 2425 y(LONGLONG)g(nrows,)g(>)h(int)g(*status\);)0 2672 y Fi(5)81 b Fj(Mo)s(dify)37 b(the)g(v)m(ector)i(length)f(of)f(a)h (binary)e(table)i(column)f(\(e.g.,)k(c)m(hange)e(a)e(column)g(from)g (TF)m(ORMn)g(=)227 2785 y('1E')31 b(to)h('20E'\).)g(The)e(v)m(ector)i (length)e(ma)m(y)h(b)s(e)f(increased)h(or)f(decreased)h(from)f(the)g (curren)m(t)h(v)-5 b(alue.)95 3032 y Fe(int)47 b (fits_modify_vector_len)42 b(/)48 b(ffmvec)286 3145 y(\(fitsfile)e (*fptr,)g(int)h(colnum,)e(LONGLONG)h(newveclen,)f(>)i(int)g(*status\))0 3291 y SDict begin H.S end 0 3291 a 0 3291 a SDict begin 13.6 H.A end 0 3291 a 0 3291 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.5.7.4) cvn H.B /DEST pdfmark end 0 3291 a 143 x Fd(5.7.4)112 b(Read)38 b(and)h(W)-9 b(rite)36 b(Column)j(Data)e (Routines)0 3653 y Fj(The)e(follo)m(wing)h(routines)g(write)f(or)g (read)g(data)h(v)-5 b(alues)36 b(in)f(the)g(curren)m(t)g(ASCI)s(I)f(or) h(binary)g(table)h(extension.)0 3766 y(If)d(a)g(write)g(op)s(eration)h (extends)f(b)s(ey)m(ond)f(the)h(curren)m(t)g(size)h(of)f(the)g(table,)i (then)e(the)g(n)m(um)m(b)s(er)f(of)h(ro)m(ws)g(in)g(the)0 3878 y(table)i(will)g(automatically)i(b)s(e)c(increased)i(and)e(the)i (NAXIS2)f(k)m(eyw)m(ord)h(v)-5 b(alue)35 b(will)f(b)s(e)g(up)s(dated.) 51 b(A)m(ttempts)0 3991 y(to)31 b(read)f(b)s(ey)m(ond)g(the)h(end)e(of) i(the)f(table)i(will)e(result)h(in)f(an)g(error.)0 4152 y(Automatic)d(data)e(t)m(yp)s(e)g(con)m(v)m(ersion)h(is)f(p)s(erformed) f(for)g(n)m(umerical)i(data)f(t)m(yp)s(es)g(\(only\))h(if)f(the)g(data) h(t)m(yp)s(e)f(of)g(the)0 4264 y(column)34 b(\(de\014ned)f(b)m(y)h(the) g(TF)m(ORMn)g(k)m(eyw)m(ord\))h(di\013ers)f(from)g(the)g(data)h(t)m(yp) s(e)f(of)g(the)h(arra)m(y)f(in)g(the)g(calling)0 4377 y(routine.)65 b(ASCI)s(I)37 b(and)h(binary)f(tables)i(supp)s(ort)e(the) i(follo)m(wing)g(data)h(t)m(yp)s(e)e(v)-5 b(alues:)57 b(TSTRING,)38 b(TBYTE,)0 4490 y(TSBYTE,)28 b(TSHOR)-8 b(T,)27 b(TUSHOR)-8 b(T,)28 b(TINT,)g(TUINT,)g(TLONG,)g(TLONGLONG,)g (TULONG,)g(TFLO)m(A)-8 b(T,)0 4603 y(or)25 b(TDOUBLE.)g(Binary)f (tables)i(also)f(supp)s(ort)e(TLOGICAL)h(\(in)m(ternally)i(mapp)s(ed)d (to)i(the)g(`c)m(har')h(data)f(t)m(yp)s(e\),)0 4716 y(TCOMPLEX,)30 b(and)f(TDBLCOMPLEX.)0 4876 y(Note)d(that)g(it)g(is)f(*not*)h (necessary)f(to)h(insert)f(ro)m(ws)g(in)g(a)g(table)h(b)s(efore)f (writing)g(data)h(to)g(those)f(ro)m(ws)g(\(indeed,)h(it)0 4989 y(w)m(ould)h(b)s(e)g(ine\016cien)m(t)i(to)f(do)f(so\).)41 b(Instead,)28 b(one)g(ma)m(y)g(simply)f(write)g(data)h(to)h(an)m(y)e (ro)m(w)h(of)g(the)f(table,)j(whether)0 5102 y(that)h(ro)m(w)f(of)h (data)g(already)g(exists)g(or)f(not.)0 5262 y(Individual)g(bits)i(in)f (a)h(binary)e(table)i('X')g(or)g('B')g(column)f(ma)m(y)h(b)s(e)f (read/written)h(to/from)g(a)g(*c)m(har)g(arra)m(y)g(b)m(y)0 5375 y(sp)s(ecifying)k(the)f(TBIT)h(datat)m(yp)s(e.)57 b(The)35 b(*c)m(har)i(arra)m(y)f(will)g(b)s(e)f(in)m(terpreted)h(as)g (an)g(arra)m(y)g(of)g(logical)i(TR)m(UE)0 5488 y(\(1\))d(or)g(F)-10 b(ALSE)34 b(\(0\))h(v)-5 b(alues)35 b(that)g(corresp)s(ond)e(to)i(the)g (v)-5 b(alue)35 b(of)f(eac)m(h)i(bit)e(in)g(the)h(FITS)e('X')i(or)g ('B')g(column.)0 5601 y(Alternativ)m(ely)-8 b(,)30 b(the)c(v)-5 b(alues)27 b(in)e(a)i(binary)e(table)i('X')g(column)f(ma)m(y)h(b)s(e)e (read/written)i(8)f(bits)g(at)h(a)f(time)h(to/from)0 5714 y(an)j(arra)m(y)h(of)g(8-bit)g(in)m(tegers)g(b)m(y)g(sp)s (ecifying)f(the)h(TBYTE)f(datat)m(yp)s(e.)p eop end %%Page: 58 66 TeXDict begin 58 65 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.58) cvn H.B /DEST pdfmark end 0 299 a Fj(58)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)0 555 y Fj(Note)25 b(that)g(within)e(the)h(con)m(text)i (of)e(these)g(routines,)i(the)e(TSTRING)f(data)h(t)m(yp)s(e)g(corresp)s (onds)f(to)h(a)h(C)e('c)m(har**')0 668 y(data)35 b(t)m(yp)s(e,)h(i.e.,) h(a)e(p)s(oin)m(ter)f(to)i(an)e(arra)m(y)h(of)g(p)s(oin)m(ters)f(to)h (an)g(arra)m(y)g(of)g(c)m(haracters.)54 b(This)34 b(is)g(di\013eren)m (t)h(from)0 781 y(the)d(k)m(eyw)m(ord)h(reading)f(and)f(writing)h (routines)g(where)g(TSTRING)f(corresp)s(onds)g(to)h(a)h(C)e('c)m(har*') j(data)f(t)m(yp)s(e,)0 894 y(i.e.,)g(a)e(single)h(p)s(oin)m(ter)f(to)h (an)f(arra)m(y)g(of)g(c)m(haracters.)45 b(When)30 b(reading)i(strings)e (from)h(a)g(table,)i(the)e(c)m(har)h(arra)m(ys)0 1007 y(ob)m(viously)f(m)m(ust)f(ha)m(v)m(e)i(b)s(een)e(allo)s(cated)i(long)f (enough)f(to)h(hold)f(the)h(whole)f(FITS)g(table)h(string.)0 1167 y(Numerical)i(data)g(v)-5 b(alues)33 b(are)g(automatically)j (scaled)d(b)m(y)f(the)h(TSCALn)e(and)h(TZER)m(On)f(k)m(eyw)m(ord)i(v)-5 b(alues)33 b(\(if)0 1280 y(they)e(exist\).)0 1440 y(In)25 b(the)g(case)i(of)e(binary)g(tables)h(with)f(v)m(ector)i(elemen)m(ts,)h (the)e('felem')g(parameter)g(de\014nes)f(the)g(starting)h(elemen)m(t)0 1553 y(\(b)s(eginning)h(with)g(1,)h(not)g(0\))g(within)f(the)g(cell)i (\(a)f(cell)g(is)f(de\014ned)f(as)i(the)f(in)m(tersection)i(of)f(a)f (ro)m(w)h(and)e(a)i(column)0 1666 y(and)e(ma)m(y)h(con)m(tain)h(a)g (single)f(v)-5 b(alue)27 b(or)g(a)g(v)m(ector)h(of)f(v)-5 b(alues\).)40 b(The)26 b(felem)i(parameter)f(is)g(ignored)f(when)g (dealing)0 1779 y(with)34 b(ASCI)s(I)e(tables.)52 b(Similarly)-8 b(,)36 b(in)d(the)i(case)f(of)h(binary)e(tables)h(the)h('nelemen)m(ts') g(parameter)f(sp)s(eci\014es)g(the)0 1892 y(total)28 b(n)m(um)m(b)s(er)d(of)h(v)m(ector)i(v)-5 b(alues)27 b(to)g(b)s(e)e(read)h(or)h(written)f(\(con)m(tin)m(uing)i(on)e (subsequen)m(t)f(ro)m(ws)i(if)f(required\))g(and)0 2005 y(not)31 b(the)f(n)m(um)m(b)s(er)f(of)i(table)g(cells.)0 2254 y Fi(1)81 b Fj(W)-8 b(rite)31 b(elemen)m(ts)h(in)m(to)f(an)g(ASCI) s(I)e(or)h(binary)f(table)j(column.)0 2504 y(The)38 b(\014rst)f (routine)h(simply)g(writes)g(the)g(arra)m(y)h(of)f(v)-5 b(alues)39 b(to)g(the)f(FITS)g(\014le)g(\(doing)g(data)h(t)m(yp)s(e)g (con)m(v)m(ersion)0 2617 y(if)h(necessary\))h(whereas)f(the)h(second)f (routine)h(will)f(substitute)h(the)f(appropriate)g(FITS)g(n)m(ull)g(v) -5 b(alue)41 b(for)f(all)0 2730 y(elemen)m(ts)34 b(whic)m(h)f(are)g (equal)h(to)f(the)g(input)f(v)-5 b(alue)34 b(of)f(n)m(ulv)-5 b(al)33 b(\(note)h(that)f(this)g(parameter)g(giv)m(es)i(the)e(address)0 2843 y(of)40 b(n)m(ulv)-5 b(al,)44 b(not)c(the)g(n)m(ull)g(v)-5 b(alue)41 b(itself)7 b(\).)72 b(F)-8 b(or)40 b(in)m(teger)i(columns)e (the)g(FITS)g(n)m(ull)g(v)-5 b(alue)40 b(is)h(de\014ned)e(b)m(y)h(the)0 2956 y(TNULLn)32 b(k)m(eyw)m(ord)i(\(an)g(error)e(is)i(returned)e(if)h (the)h(k)m(eyw)m(ord)f(do)s(esn't)g(exist\).)51 b(F)-8 b(or)34 b(\015oating)g(p)s(oin)m(t)f(columns)0 3069 y(the)h(sp)s(ecial) h(IEEE)f(NaN)h(\(Not-a-Num)m(b)s(er\))h(v)-5 b(alue)35 b(will)f(b)s(e)g(written)g(in)m(to)i(the)e(FITS)g(\014le.)52 b(If)34 b(a)h(n)m(ull)f(p)s(oin)m(ter)0 3182 y(is)f(en)m(tered)g(for)g (n)m(ulv)-5 b(al,)34 b(then)f(the)g(n)m(ull)g(v)-5 b(alue)33 b(is)g(ignored)g(and)g(this)g(routine)f(b)s(eha)m(v)m(es)i(the)f(same)g (as)h(the)f(\014rst)0 3295 y(routine.)41 b(The)29 b(third)g(routine)h (simply)f(writes)h(unde\014ned)d(pixel)k(v)-5 b(alues)30 b(to)g(the)g(column.)41 b(The)29 b(fourth)g(routine)0 3408 y(\014lls)e(ev)m(ery)i(column)e(in)h(the)g(table)g(with)g(n)m(ull) f(v)-5 b(alues,)29 b(in)e(the)h(sp)s(eci\014ed)f(ro)m(ws)h(\(ignoring)g (an)m(y)g(columns)g(that)g(do)0 3521 y(not)j(ha)m(v)m(e)g(a)g (de\014ned)e(n)m(ull)h(v)-5 b(alue\).)95 3770 y Fe(int)47 b(fits_write_col)d(/)k(ffpcl)286 3883 y(\(fitsfile)e(*fptr,)g(int)h (datatype,)e(int)i(colnum,)f(LONGLONG)f(firstrow,)334 3996 y(LONGLONG)h(firstelem,)f(LONGLONG)g(nelements,)g(DTYPE)i(*array,) e(>)j(int)f(*status\))95 4222 y(int)g(fits_write_colnull)c(/)48 b(ffpcn)286 4335 y(\(fitsfile)e(*fptr,)g(int)h(datatype,)e(int)i (colnum,)f(LONGLONG)f(firstrow,)286 4448 y(LONGLONG)h(firstelem,)f (LONGLONG)g(nelements,)g(DTYPE)i(*array,)f(DTYPE)g(*nulval,)286 4561 y(>)i(int)f(*status\))143 4787 y(int)g(fits_write_col_null)c(/)k (ffpclu)334 4899 y(\(fitsfile)e(*fptr,)h(int)h(colnum,)f(LONGLONG)g (firstrow,)f(LONGLONG)h(firstelem,)382 5012 y(LONGLONG)f(nelements,)g (>)j(int)f(*status\))143 5238 y(int)g(fits_write_nullrows)c(/)k(ffprwu) 334 5351 y(\(fitsfile)e(*fptr,)h(LONGLONG)g(firstrow,)f(LONGLONG)h (nelements,)f(>)i(int)g(*status\))0 5601 y Fi(2)81 b Fj(Read)33 b(elemen)m(ts)i(from)e(an)g(ASCI)s(I)f(or)i(binary)e(table)i (column.)50 b(The)33 b(data)h(t)m(yp)s(e)g(parameter)g(sp)s(eci\014es)f (the)227 5714 y(data)28 b(t)m(yp)s(e)g(of)g(the)f(`n)m(ulv)-5 b(al')29 b(and)e(`arra)m(y')h(p)s(oin)m(ters;)h(Unde\014ned)c(arra)m(y) j(elemen)m(ts)h(will)f(b)s(e)f(returned)f(with)p eop end %%Page: 59 67 TeXDict begin 59 66 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.59) cvn H.B /DEST pdfmark end 0 299 a Fh(5.7.)72 b(ASCI)s(I)29 b(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(R)m(OUTINES)1864 b Fj(59)227 555 y(a)30 b(v)-5 b(alue)30 b(=)e(*n)m(ullv)-5 b(al,)31 b(\(note)f(that)g(this)f(parameter)h(giv)m(es)g(the)g(address) e(of)h(the)h(n)m(ull)f(v)-5 b(alue,)30 b(not)g(the)f(n)m(ull)227 668 y(v)-5 b(alue)31 b(itself)7 b(\))32 b(unless)e(n)m(ulv)-5 b(al)32 b(=)e(0)h(or)g(*n)m(ulv)-5 b(al)31 b(=)g(0,)g(in)f(whic)m(h)h (case)h(no)e(c)m(hec)m(king)j(for)d(unde\014ned)f(pixels)227 781 y(will)34 b(b)s(e)f(p)s(erformed.)48 b(The)33 b(second)g(routine)h (is)f(similar)h(except)g(that)g(an)m(y)g(unde\014ned)d(pixels)j(will)g (ha)m(v)m(e)227 894 y(the)d(corresp)s(onding)e(n)m(ullarra)m(y)i (elemen)m(t)h(set)f(equal)g(to)g(TR)m(UE)f(\(=)h(1\).)227 1039 y(An)m(y)c(column,)g(regardless)f(of)g(it's)h(in)m(trinsic)g(data) g(t)m(yp)s(e,)g(ma)m(y)g(b)s(e)e(read)i(as)f(a)g(string.)40 b(It)26 b(should)f(b)s(e)h(noted)227 1152 y(ho)m(w)m(ev)m(er)32 b(that)f(reading)f(a)h(n)m(umeric)f(column)g(as)h(a)g(string)f(is)g(10) i(-)e(100)i(times)f(slo)m(w)m(er)g(than)f(reading)h(the)227 1265 y(same)22 b(column)g(as)f(a)h(n)m(um)m(b)s(er)e(due)h(to)i(the)e (large)i(o)m(v)m(erhead)g(in)e(constructing)h(the)g(formatted)g (strings.)37 b(The)227 1378 y(displa)m(y)26 b(format)g(of)f(the)h (returned)e(strings)h(will)h(b)s(e)f(determined)g(b)m(y)g(the)h(TDISPn) e(k)m(eyw)m(ord,)j(if)e(it)h(exists,)227 1491 y(otherwise)32 b(b)m(y)f(the)g(data)h(t)m(yp)s(e)f(of)g(the)g(column.)43 b(The)30 b(length)i(of)f(the)g(returned)f(strings)h(\(not)g(including) 227 1604 y(the)26 b(n)m(ull)f(terminating)i(c)m(haracter\))g(can)f(b)s (e)f(determined)g(with)g(the)h(\014ts)p 2703 1604 28 4 v 32 w(get)p 2855 1604 V 34 w(col)p 2999 1604 V 34 w(displa)m(y)p 3311 1604 V 33 w(width)f(routine.)227 1717 y(The)30 b(follo)m(wing)i(TDISPn)d(displa)m(y)i(formats)f(are)h (curren)m(tly)f(supp)s(orted:)418 1933 y Fe(Iw.m)142 b(Integer)418 2046 y(Ow.m)g(Octal)47 b(integer)418 2159 y(Zw.m)142 b(Hexadecimal)45 b(integer)418 2272 y(Fw.d)142 b(Fixed)47 b(floating)e(point)418 2385 y(Ew.d)142 b(Exponential)45 b(floating)h(point)418 2498 y(Dw.d)142 b(Exponential)45 b(floating)h(point)418 2611 y(Gw.d)142 b(General;)46 b(uses)g(Fw.d)h(if)g(significance)e(not)i(lost,)f(else)h(Ew.d)227 2827 y Fj(where)24 b(w)h(is)f(the)h(width)f(in)g(c)m(haracters)i(of)f (the)g(displa)m(y)m(ed)g(v)-5 b(alues,)27 b(m)d(is)h(the)f(minim)m(um)g (n)m(um)m(b)s(er)g(of)g(digits)227 2940 y(displa)m(y)m(ed,)29 b(and)e(d)g(is)h(the)f(n)m(um)m(b)s(er)g(of)g(digits)i(to)f(the)g(righ) m(t)g(of)f(the)h(decimal.)41 b(The)27 b(.m)g(\014eld)g(is)h(optional.) 95 3171 y Fe(int)47 b(fits_read_col)e(/)i(ffgcv)286 3284 y(\(fitsfile)f(*fptr,)g(int)h(datatype,)e(int)i(colnum,)f(LONGLONG)f (firstrow,)g(LONGLONG)h(firstelem,)334 3397 y(LONGLONG)g(nelements,)f (DTYPE)h(*nulval,)g(DTYPE)g(*array,)g(int)h(*anynul,)e(int)i(*status\)) 95 3623 y(int)g(fits_read_colnull)c(/)48 b(ffgcf)286 3736 y(\(fitsfile)e(*fptr,)g(int)h(datatype,)e(int)i(colnum,)f (LONGLONG)f(firstrow,)g(LONGLONG)h(firstelem,)286 3849 y(LONGLONG)g(nelements,)f(DTYPE)h(*array,)g(char)h(*nullarray,)d(int)j (*anynul,)f(int)h(*status\))0 3992 y SDict begin H.S end 0 3992 a 0 3992 a SDict begin 13.6 H.A end 0 3992 a 0 3992 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.5.7.5) cvn H.B /DEST pdfmark end 0 3992 a 143 x Fd(5.7.5)112 b(Ro)m(w)37 b(Selection)h(and)h(Calculator)f(Routines)0 4354 y Fj(These)21 b(routines)f(all)i(parse)f(and)f(ev)-5 b(aluate)23 b(an)d(input)g (string)h(con)m(taining)i(a)e(user)f(de\014ned)g(arithmetic)i (expression.)0 4467 y(The)29 b(\014rst)f(3)i(routines)f(select)i(ro)m (ws)e(in)g(a)h(FITS)e(table,)j(based)e(on)g(whether)g(the)g(expression) g(ev)-5 b(aluates)31 b(to)f(true)0 4580 y(\(not)e(equal)f(to)h(zero\))g (or)f(false)h(\(zero\).)41 b(The)27 b(other)g(routines)g(ev)-5 b(aluate)29 b(the)e(expression)g(and)f(calculate)k(a)d(v)-5 b(alue)0 4692 y(for)26 b(eac)m(h)i(ro)m(w)f(of)g(the)g(table.)40 b(The)26 b(allo)m(w)m(ed)j(expression)d(syn)m(tax)i(is)e(describ)s(ed)g (in)g(the)h(ro)m(w)g(\014lter)g(section)g(in)g(the)0 4805 y(`Extended)32 b(File)h(Name)g(Syn)m(tax')g(c)m(hapter)g(of)f (this)g(do)s(cumen)m(t.)46 b(The)32 b(expression)g(ma)m(y)h(also)g(b)s (e)e(written)i(to)g(a)0 4918 y(text)h(\014le,)h(and)e(the)h(name)f(of)h (the)f(\014le,)i(prep)s(ended)c(with)i(a)h('@')g(c)m(haracter)h(ma)m(y) f(b)s(e)f(supplied)f(for)h(the)h('expr')0 5031 y(parameter)d(\(e.g.)42 b('@\014lename.txt'\).)g(The)30 b(expression)g(in)g(the)g(\014le)h(can) f(b)s(e)g(arbitrarily)g(complex)h(and)f(extend)0 5144 y(o)m(v)m(er)35 b(m)m(ultiple)g(lines)g(of)f(the)g(\014le.)53 b(Lines)33 b(that)i(b)s(egin)f(with)g(2)g(slash)g(c)m(haracters)i (\('//'\))g(will)f(b)s(e)e(ignored)i(and)0 5257 y(ma)m(y)c(b)s(e)f (used)f(to)i(add)f(commen)m(ts)h(to)h(the)e(\014le.)0 5488 y Fi(1)81 b Fj(Ev)-5 b(aluate)38 b(a)f(b)s(o)s(olean)g(expression) g(o)m(v)m(er)h(the)g(indicated)f(ro)m(ws,)i(returning)d(an)h(arra)m(y)h (of)f(\015ags)g(indicating)227 5601 y(whic)m(h)31 b(ro)m(ws)g(ev)-5 b(aluated)32 b(to)f(TR)m(UE/F)-10 b(ALSE.)31 b(Up)s(on)f(return,)g(*n)p 2518 5601 28 4 v 33 w(go)s(o)s(d)p 2743 5601 V 33 w(ro)m(ws)g(con)m (tains)i(the)f(n)m(um)m(b)s(er)f(of)227 5714 y(ro)m(ws)h(that)g(ev)-5 b(aluate)32 b(to)f(TR)m(UE.)p eop end %%Page: 60 68 TeXDict begin 60 67 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.60) cvn H.B /DEST pdfmark end 0 299 a Fj(60)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)95 555 y Fe(int)47 b(fits_find_rows)d(/)k(fffrow)286 668 y(\(fitsfile)e(*fptr,)93 b(char)47 b(*expr,)f(long)h(firstrow,)e (long)i(nrows,)286 781 y(>)h(long)e(*n_good_rows,)f(char)h (*row_status,)92 b(int)47 b(*status\))0 1015 y Fi(2)81 b Fj(Find)29 b(the)i(\014rst)f(ro)m(w)g(whic)m(h)g(satis\014es)h(the)g (input)e(b)s(o)s(olean)h(expression)95 1250 y Fe(int)47 b(fits_find_first_row)c(/)k(ffffrw)286 1363 y(\(fitsfile)f(*fptr,)93 b(char)47 b(*expr,)f(>)i(long)e(*rownum,)g(int)h(*status\))0 1597 y Fi(3)81 b Fj(Ev)-5 b(aluate)35 b(an)f(expression)h(on)f(all)h (ro)m(ws)g(of)f(a)h(table.)54 b(If)34 b(the)g(input)g(and)g(output)g (\014les)g(are)h(not)g(the)f(same,)227 1710 y(cop)m(y)i(the)g(TR)m(UE)f (ro)m(ws)g(to)h(the)f(output)g(\014le;)j(if)d(the)g(output)g(table)h (is)f(not)h(empt)m(y)-8 b(,)37 b(then)e(this)g(routine)227 1823 y(will)28 b(app)s(end)e(the)i(new)f(selected)i(ro)m(ws)e(after)h (the)g(existing)h(ro)m(ws.)39 b(If)27 b(the)h(\014les)g(are)f(the)h (same,)h(delete)g(the)227 1936 y(F)-10 b(ALSE)30 b(ro)m(ws)h(\(preserv) m(e)f(the)h(TR)m(UE)f(ro)m(ws\).)95 2170 y Fe(int)47 b(fits_select_rows)d(/)j(ffsrow)286 2283 y(\(fitsfile)f(*infptr,)f (fitsfile)h(*outfptr,)93 b(char)46 b(*expr,)94 b(>)48 b(int)f(*status)e(\))0 2518 y Fi(4)81 b Fj(Calculate)28 b(an)f(expression)f(for)h(the)f(indicated)i(ro)m(ws)e(of)h(a)g(table,)i (returning)d(the)h(results,)g(cast)h(as)f(datat)m(yp)s(e)227 2631 y(\(TSHOR)-8 b(T,)32 b(TDOUBLE,)h(etc\),)h(in)e(arra)m(y)-8 b(.)48 b(If)31 b(n)m(ulv)-5 b(al==NULL,)33 b(UNDEFs)g(will)f(b)s(e)g (zero)s(ed)g(out.)47 b(F)-8 b(or)227 2744 y(v)m(ector)37 b(results,)f(the)f(n)m(um)m(b)s(er)e(of)i(elemen)m(ts)i(returned)c(ma)m (y)j(b)s(e)e(less)h(than)g(nelemen)m(ts)g(if)g(nelemen)m(ts)h(is)227 2857 y(not)c(an)g(ev)m(en)h(m)m(ultiple)f(of)g(the)g(result)g (dimension.)44 b(Call)33 b(\014ts)p 2392 2857 28 4 v 32 w(test)p 2570 2857 V 34 w(expr)e(to)h(obtain)h(the)f(dimensions)f (of)227 2969 y(the)g(results.)95 3204 y Fe(int)47 b(fits_calc_rows)d(/) k(ffcrow)286 3317 y(\(fitsfile)e(*fptr,)93 b(int)47 b(datatype,)f(char) g(*expr,)g(long)h(firstrow,)334 3430 y(long)g(nelements,)e(void)h (*nulval,)g(>)h(void)g(*array,)94 b(int)46 b(*anynul,)g(int)h (*status\))0 3664 y Fi(5)81 b Fj(Ev)-5 b(aluate)33 b(an)g(expression)f (and)h(write)f(the)h(result)g(either)g(to)h(a)f(column)f(\(if)h(the)g (expression)f(is)h(a)g(function)227 3777 y(of)d(other)g(columns)g(in)f (the)h(table\))h(or)f(to)g(a)h(k)m(eyw)m(ord)f(\(if)g(the)g(expression) f(ev)-5 b(aluates)32 b(to)e(a)g(constan)m(t)i(and)227 3890 y(is)f(not)f(a)h(function)f(of)h(other)f(columns)h(in)f(the)g (table\).)42 b(In)30 b(the)h(former)e(case,)j(the)f(parName)f (parameter)227 4003 y(is)40 b(the)g(name)f(of)h(the)g(column)f(\(whic)m (h)h(ma)m(y)g(or)f(ma)m(y)h(not)g(already)g(exist\))h(in)m(to)f(whic)m (h)g(to)g(write)g(the)227 4116 y(results,)e(and)f(parInfo)e(con)m (tains)j(an)f(optional)g(TF)m(ORM)g(k)m(eyw)m(ord)g(v)-5 b(alue)38 b(if)e(a)h(new)f(column)h(is)f(b)s(eing)227 4229 y(created.)42 b(If)28 b(a)h(TF)m(ORM)h(v)-5 b(alue)29 b(is)g(not)g(sp)s(eci\014ed)g(then)f(a)i(default)f(format)g(will)h(b)s (e)e(used,)h(dep)s(ending)e(on)227 4342 y(the)35 b(expression.)54 b(If)34 b(the)h(expression)f(ev)-5 b(aluates)37 b(to)e(a)g(constan)m (t,)i(then)e(the)g(result)f(will)h(b)s(e)f(written)h(to)227 4455 y(the)28 b(k)m(eyw)m(ord)g(name)f(giv)m(en)h(b)m(y)g(the)f (parName)h(parameter,)h(and)d(the)i(parInfo)e(parameter)i(ma)m(y)g(b)s (e)f(used)227 4568 y(to)k(supply)e(an)h(optional)i(commen)m(t)f(for)f (the)g(k)m(eyw)m(ord.)42 b(If)29 b(the)i(k)m(eyw)m(ord)g(do)s(es)f(not) g(already)h(exist,)g(then)227 4680 y(the)f(name)f(of)h(the)g(k)m(eyw)m (ord)g(m)m(ust)f(b)s(e)g(preceded)g(with)g(a)h('#')f(c)m(haracter,)j (otherwise)e(the)f(result)h(will)g(b)s(e)227 4793 y(written)h(to)g(a)g (column)f(with)g(that)h(name.)95 5028 y Fe(int)47 b(fits_calculator)d (/)j(ffcalc)286 5141 y(\(fitsfile)f(*infptr,)f(char)i(*expr,)f (fitsfile)f(*outfptr,)h(char)g(*parName,)334 5254 y(char)h(*parInfo,)e (>)95 b(int)47 b(*status\))0 5488 y Fi(6)81 b Fj(This)38 b(calculator)k(routine)e(is)f(similar)h(to)g(the)g(previous)f(routine,) j(except)f(that)f(the)g(expression)f(is)h(only)227 5601 y(ev)-5 b(aluated)42 b(o)m(v)m(er)f(the)f(sp)s(eci\014ed)g(ro)m(w)g (ranges.)70 b(nranges)39 b(sp)s(eci\014es)h(the)g(n)m(um)m(b)s(er)f(of) h(ro)m(w)h(ranges,)i(and)227 5714 y(\014rstro)m(w)30 b(and)g(lastro)m(w)h(giv)m(e)h(the)f(starting)g(and)f(ending)g(ro)m(w)g (n)m(um)m(b)s(er)f(of)i(eac)m(h)g(range.)p eop end %%Page: 61 69 TeXDict begin 61 68 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.61) cvn H.B /DEST pdfmark end 0 299 a Fh(5.7.)72 b(ASCI)s(I)29 b(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(R)m(OUTINES)1864 b Fj(61)95 555 y Fe(int)47 b(fits_calculator_rng)c(/)k(ffcalc_rng)286 668 y(\(fitsfile)f(*infptr,)f(char)i(*expr,)f(fitsfile)f(*outfptr,)h (char)g(*parName,)334 781 y(char)h(*parInfo,)e(int)i(nranges,)e(long)i (*firstrow,)e(long)i(*lastrow)334 894 y(>)95 b(int)47 b(*status\))0 1159 y Fi(7)81 b Fj(Ev)-5 b(aluate)36 b(the)f(giv)m(en)h (expression)f(and)g(return)f(dimension)g(and)h(t)m(yp)s(e)g (information)g(on)g(the)h(result.)54 b(The)227 1272 y(returned)37 b(dimensions)f(corresp)s(ond)g(to)j(a)e(single)i(ro)m(w)e(en)m(try)h (of)f(the)h(requested)f(expression,)j(and)d(are)227 1385 y(equiv)-5 b(alen)m(t)26 b(to)f(the)g(result)f(of)g(\014ts)p 1380 1385 28 4 v 33 w(read)p 1585 1385 V 32 w(tdim\(\).)40 b(Note)25 b(that)g(strings)f(are)h(considered)f(to)h(b)s(e)f(one)g (elemen)m(t)227 1498 y(regardless)31 b(of)g(string)f(length.)41 b(If)30 b(maxdim)g(==)g(0,)h(then)f(naxes)g(is)h(optional.)95 1763 y Fe(int)47 b(fits_test_expr)d(/)k(fftexp)286 1876 y(\(fitsfile)e(*fptr,)g(char)g(*expr,)g(int)h(maxdim)f(>)i(int)f (*datatype,)e(long)h(*nelem,)g(int)h(*naxis,)334 1989 y(long)g(*naxes,)f(int)g(*status\))0 2143 y SDict begin H.S end 0 2143 a 0 2143 a SDict begin 13.6 H.A end 0 2143 a 0 2143 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.5.7.6) cvn H.B /DEST pdfmark end 0 2143 a 143 x Fd(5.7.6)112 b(Column)39 b(Binning)f(or)f(Histogramming)i(Routines)0 2506 y Fj(The)30 b(follo)m(wing)j(routines)e(ma)m(y)g(b)s(e)g(useful)f (when)g(p)s(erforming)g(histogramming)h(op)s(erations)h(on)e (column\(s\))i(of)0 2619 y(a)f(table)g(to)g(generate)h(an)e(image)i(in) e(a)h(primary)e(arra)m(y)i(or)f(image)i(extension.)0 2884 y Fi(1)81 b Fj(Calculate)27 b(the)e(histogramming)h(parameters)g (\(min,)h(max,)f(and)f(bin)g(size)h(for)f(eac)m(h)i(axis)f(of)f(the)h (histogram,)227 2997 y(based)38 b(on)g(a)g(v)-5 b(ariet)m(y)39 b(of)f(p)s(ossible)g(input)f(parameters.)64 b(If)37 b(the)h(input)f (names)h(of)g(the)g(columns)g(to)h(b)s(e)227 3110 y(binned)d(are)i(n)m (ull,)h(then)e(the)h(routine)f(will)h(\014rst)f(lo)s(ok)h(for)f(the)h (CPREF)f(=)g("NAME1,)j(NAME2,)h(...")227 3223 y(k)m(eyw)m(ord)34 b(whic)m(h)f(lists)h(the)g(preferred)e(columns.)50 b(If)32 b(not)i(presen)m(t,)h(then)e(the)g(routine)h(will)g(assume)f(the)227 3336 y(column)d(names)h(X,)f(Y,)h(Z,)f(and)g(T)g(for)g(up)g(to)h(4)f (axes)h(\(as)g(sp)s(eci\014ed)f(b)m(y)g(the)h(NAXIS)f(parameter\).)227 3489 y(MININ)39 b(and)f(MAXIN)h(are)g(input)e(arra)m(ys)i(that)g(giv)m (e)h(the)f(minim)m(um)e(and)h(maxim)m(um)h(v)-5 b(alue)39 b(for)f(the)227 3602 y(histogram,)30 b(along)f(eac)m(h)g(axis.)40 b(Alternativ)m(ely)-8 b(,)32 b(the)c(name)g(of)h(k)m(eyw)m(ords)f(that) h(giv)m(e)g(the)f(min,)h(max,)g(and)227 3715 y(binsize)f(ma)m(y)g(b)s (e)f(giv)m(e)h(with)f(the)h(MINNAME,)h(MAXNAME,)f(and)f(BINNAME)h(arra) m(y)g(parameters.)40 b(If)227 3828 y(the)33 b(v)-5 b(alue)34 b(=)e(DOUBLENULL)-10 b(V)g(ALUE)33 b(and)g(no)f(k)m(eyw)m(ord)i(names)e (are)h(giv)m(en,)i(then)e(the)g(routine)g(will)227 3941 y(use)i(the)f(TLMINn)g(and)g(TLMAXn)g(k)m(eyw)m(ords,)j(if)d(presen)m (t,)i(or)f(the)f(actual)i(min)e(and/or)h(max)g(v)-5 b(alues)227 4054 y(in)30 b(the)h(column.)227 4207 y(BINSIZEIN)j(is)h(an)g(arra)m(y) g(giving)h(the)f(binsize)g(along)h(eac)m(h)g(axis.)55 b(If)34 b(the)h(v)-5 b(alue)36 b(=)e(DOUBLENULL-)227 4320 y(V)-10 b(ALUE,)38 b(and)e(a)i(k)m(eyw)m(ord)f(name)g(is)h(not)f (sp)s(eci\014ed)f(with)h(BINNAME,)h(then)f(this)g(routine)g(will)h (\014rst)227 4432 y(lo)s(ok)d(for)f(the)g(TDBINn)g(k)m(eyw)m(ord,)i(or) f(else)g(will)f(use)g(a)h(binsize)f(=)g(1,)h(or)g(a)f(binsize)g(that)h (pro)s(duces)e(10)227 4545 y(histogram)e(bins,)f(whic)m(h)g(ev)m(er)h (is)g(smaller.)95 4811 y Fe(int)47 b(fits_calc_binning)143 4924 y(Input)g(parameters:)239 5036 y(\(fitsfile)e(*fptr,)94 b(/*)47 b(IO)g(-)h(pointer)d(to)j(table)e(to)h(be)g(binned)667 b(*/)286 5149 y(int)47 b(naxis,)333 b(/*)47 b(I)g(-)h(number)e(of)h (axes/columns)e(in)i(the)g(binned)f(image)94 b(*/)286 5262 y(char)47 b(colname[4][FLEN_VALUE],)137 b(/*)47 b(I)h(-)f(optional)f(column)g(names)428 b(*/)286 5375 y(double)46 b(*minin,)237 b(/*)47 b(I)h(-)f(optional)f(lower)g(bound)h (value)f(for)h(each)f(axis)95 b(*/)286 5488 y(double)46 b(*maxin,)237 b(/*)47 b(I)h(-)f(optional)f(upper)g(bound)h(value,)f (for)h(each)f(axis)h(*/)286 5601 y(double)f(*binsizein,)f(/*)i(I)h(-)f (optional)f(bin)h(size)f(along)h(each)f(axis)429 b(*/)286 5714 y(char)47 b(minname[4][FLEN_VALUE],)41 b(/*)48 b(I)f(-)h(optional) d(keywords)h(for)h(min)333 b(*/)p eop end %%Page: 62 70 TeXDict begin 62 69 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.62) cvn H.B /DEST pdfmark end 0 299 a Fj(62)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)286 555 y Fe(char)47 b(maxname[4][FLEN_VALUE],)41 b(/*)48 b(I)f(-)h(optional)d(keywords)h(for)h(max)333 b(*/)286 668 y(char)47 b(binname[4][FLEN_VALUE],)41 b(/*)48 b(I)f(-)h(optional)d(keywords)h(for)h(binsize)141 b(*/)143 781 y(Output)46 b(parameters:)286 894 y(int)h(*colnum,)237 b(/*)47 b(O)g(-)h(column)e(numbers,)f(to)j(be)f(binned)f(*/)286 1007 y(long)h(*naxes,)237 b(/*)47 b(O)g(-)h(number)e(of)h(bins)g(in)g (each)g(histogram)e(axis)h(*/)286 1120 y(float)h(*amin,)237 b(/*)47 b(O)g(-)h(lower)e(bound)h(of)g(the)g(histogram)e(axes)i(*/)286 1233 y(float)g(*amax,)237 b(/*)47 b(O)g(-)h(upper)e(bound)h(of)g(the)g (histogram)e(axes)i(*/)286 1346 y(float)g(*binsize,)93 b(/*)47 b(O)g(-)h(width)e(of)h(histogram)f(bins/pixels)e(on)k(each)e (axis)h(*/)286 1458 y(int)g(*status\))0 1697 y Fi(2)81 b Fj(Cop)m(y)26 b(the)h(relev)-5 b(an)m(t)28 b(k)m(eyw)m(ords)f(from)g (the)g(header)f(of)h(the)g(table)h(that)f(is)g(b)s(eing)f(binned,)h(to) g(the)g(the)g(header)227 1810 y(of)e(the)h(output)e(histogram)i(image.) 40 b(This)24 b(will)i(not)f(cop)m(y)h(the)f(table)h(structure)f(k)m (eyw)m(ords)g(\(e.g.,)j(NAXIS,)227 1923 y(TF)m(ORMn,)j(TTYPEn,)f (etc.\))44 b(nor)31 b(will)g(it)g(cop)m(y)h(the)f(k)m(eyw)m(ords)g (that)h(apply)e(to)i(other)f(columns)g(of)g(the)227 2036 y(table)g(that)g(are)f(not)h(used)e(to)i(create)g(the)f(histogram.)42 b(This)29 b(routine)h(will)g(translate)h(the)g(names)f(of)g(the)227 2149 y(W)-8 b(orld)27 b(Co)s(ordinate)e(System)h(\(W)m(CS\))g(k)m(eyw)m (ords)g(for)g(the)g(binned)e(columns)h(in)m(to)i(the)f(form)f(that)h (is)g(need)227 2262 y(for)h(a)g(FITS)g(image)h(\(e.g.,)h(the)e(TCTYPn)f (table)i(k)m(eyw)m(ord)f(will)g(b)s(e)g(translated)g(to)h(the)f(CTYPEn) f(image)227 2375 y(k)m(eyw)m(ord\).)95 2613 y Fe(int)47 b(fits_copy_pixlist2image)286 2726 y(\(fitsfile)f(*infptr,)141 b(/*)47 b(I)g(-)h(pointer)e(to)h(input)f(HDU)h(*/)334 2839 y(fitsfile)f(*outfptr,)93 b(/*)47 b(I)g(-)h(pointer)e(to)h(output) f(HDU)h(*/)334 2952 y(int)g(firstkey,)332 b(/*)47 b(I)g(-)h(first)e (HDU)h(keyword)f(to)h(start)f(with)h(*/)334 3065 y(int)g(naxis,)476 b(/*)47 b(I)g(-)h(number)e(of)h(axes)g(in)g(the)g(image)f(*/)334 3178 y(int)h(*colnum,)380 b(/*)47 b(I)g(-)h(numbers)e(of)h(the)g (columns)e(to)j(be)f(binned)94 b(*/)334 3291 y(int)47 b(*status\))380 b(/*)47 b(IO)g(-)g(error)g(status)f(*/)0 3530 y Fi(3)81 b Fj(W)-8 b(rite)36 b(a)f(set)h(of)f(default)h(W)m(CS)f (k)m(eyw)m(ords)g(to)h(the)f(histogram)h(header,)g(IF)f(the)g(W)m(CS)g (k)m(eyw)m(ords)h(do)f(not)227 3643 y(already)40 b(exist.)69 b(This)38 b(will)i(create)h(a)e(linear)h(W)m(CS)f(where)g(the)h(co)s (ordinate)g(t)m(yp)s(es)f(are)h(equal)g(to)g(the)227 3756 y(original)32 b(column)e(names.)95 3994 y Fe(int)47 b(fits_write_keys_histo)239 4107 y(\(fitsfile)e(*fptr,)237 b(/*)47 b(I)h(-)f(pointer)f(to)h(table)f(to)i(be)f(binned)666 b(*/)286 4220 y(fitsfile)46 b(*histptr,)93 b(/*)47 b(I)h(-)f(pointer)f (to)h(output)f(histogram)f(image)i(HDU)285 b(*/)286 4333 y(int)47 b(naxis,)476 b(/*)47 b(I)h(-)f(number)f(of)h(axes)g(in)g(the)g (histogram)e(image)285 b(*/)286 4446 y(int)47 b(*colnum,)380 b(/*)47 b(I)h(-)f(column)f(numbers)g(of)h(the)g(binned)f(columns)332 b(*/)286 4559 y(int)47 b(*status\))0 4798 y Fi(4)81 b Fj(Up)s(date)29 b(the)i(W)m(CS)f(k)m(eyw)m(ords)g(in)g(a)g(histogram)h (image)g(header)f(that)h(giv)m(e)g(the)f(lo)s(cation)i(of)e(the)g (reference)227 4911 y(pixel)h(\(CRPIXn\),)f(and)g(the)h(pixel)f(size)h (\(CDEL)-8 b(Tn\),)31 b(in)f(the)h(binned)e(image.)95 5149 y Fe(int)47 b(fits_rebin_wcs)239 5262 y(\(fitsfile)e(*fptr,)237 b(/*)47 b(I)h(-)f(pointer)f(to)h(table)f(to)i(be)f(binned)523 b(*/)286 5375 y(int)47 b(naxis,)476 b(/*)47 b(I)h(-)f(number)f(of)h (axes)g(in)g(the)g(histogram)e(image)142 b(*/)286 5488 y(float)47 b(*amin,)380 b(/*)47 b(I)h(-)f(first)f(pixel)h(include)f(in) h(each)f(axis)381 b(*/)286 5601 y(float)47 b(*binsize,)236 b(/*)47 b(I)h(-)f(binning)f(factor)g(for)h(each)f(axis)572 b(*/)286 5714 y(int)47 b(*status\))p eop end %%Page: 63 71 TeXDict begin 63 70 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.63) cvn H.B /DEST pdfmark end 0 299 a Fh(5.8.)72 b(UTILITY)30 b(R)m(OUTINES)2693 b Fj(63)0 555 y Fi(5)81 b Fj(Bin)33 b(the)h(v)-5 b(alues)35 b(in)e(the)h(input)f(table)h(columns,)h(and)e (write)h(the)g(histogram)h(arra)m(y)f(to)g(the)g(output)g(FITS)227 668 y(image)e(\(histptr\).)95 951 y Fe(int)47 b(fits_make_hist)143 1064 y(\(fitsfile)e(*fptr,)190 b(/*)47 b(I)g(-)h(pointer)e(to)h(table)f (with)h(X)g(and)g(Y)h(cols;)285 b(*/)191 1177 y(fitsfile)45 b(*histptr,)h(/*)h(I)g(-)h(pointer)e(to)h(output)f(FITS)h(image)619 b(*/)191 1290 y(int)47 b(bitpix,)380 b(/*)47 b(I)g(-)h(datatype)d(for)i (image:)f(16,)h(32,)g(-32,)g(etc)238 b(*/)191 1403 y(int)47 b(naxis,)428 b(/*)47 b(I)g(-)h(number)e(of)h(axes)g(in)g(the)g (histogram)e(image)190 b(*/)191 1516 y(long)47 b(*naxes,)332 b(/*)47 b(I)g(-)h(size)e(of)i(axes)e(in)h(the)g(histogram)f(image)285 b(*/)191 1628 y(int)47 b(*colnum,)332 b(/*)47 b(I)g(-)h(column)e (numbers)g(\(array)g(length)g(=)h(naxis\))190 b(*/)191 1741 y(float)46 b(*amin,)333 b(/*)47 b(I)g(-)h(minimum)e(histogram)f (value,)h(for)h(each)g(axis)142 b(*/)191 1854 y(float)46 b(*amax,)333 b(/*)47 b(I)g(-)h(maximum)e(histogram)f(value,)h(for)h (each)g(axis)142 b(*/)191 1967 y(float)46 b(*binsize,)189 b(/*)47 b(I)g(-)h(bin)f(size)f(along)h(each)f(axis)811 b(*/)191 2080 y(float)46 b(weight,)285 b(/*)47 b(I)g(-)h(binning)e (weighting)f(factor)h(\(FLOATNULLVALUE)e(*/)1098 2193 y(/*)238 b(for)47 b(no)g(weighting\))1143 b(*/)191 2306 y(int)47 b(wtcolnum,)284 b(/*)47 b(I)g(-)h(keyword)e(or)h(col)g(for)g (weight)284 b(\(or)47 b(NULL\))g(*/)191 2419 y(int)g(recip,)428 b(/*)47 b(I)g(-)h(use)f(reciprocal)e(of)i(the)g(weight?)f(0)h(or)g(1) 239 b(*/)191 2532 y(char)47 b(*selectrow,)140 b(/*)47 b(I)g(-)h(optional)d(array)i(\(length)f(=)h(no.)g(of)477 b(*/)1098 2645 y(/*)47 b(rows)g(in)g(the)g(table\).)93 b(If)47 b(the)g(element)f(is)h(true)95 b(*/)1098 2758 y(/*)47 b(then)g(the)f(corresponding)f(row)i(of)g(the)g(table)f(will)h (*/)1098 2870 y(/*)g(be)g(included)f(in)h(the)g(histogram,)e(otherwise) g(the)95 b(*/)1098 2983 y(/*)47 b(row)g(will)f(be)i(skipped.)93 b(Ingnored)45 b(if)j(*selectrow)d(*/)1098 3096 y(/*)i(is)g(equal)f(to)i (NULL.)1335 b(*/)191 3209 y(int)47 b(*status\))0 3381 y SDict begin H.S end 0 3381 a 0 3381 a SDict begin 13.6 H.A end 0 3381 a 0 3381 a SDict begin [ /View [/XYZ H.V] /Dest (section.5.8) cvn H.B /DEST pdfmark end 0 3381 a 189 x Ff(5.8)135 b(Utilit)l(y)47 b(Routines)0 3689 y SDict begin H.S end 0 3689 a 0 3689 a SDict begin 13.6 H.A end 0 3689 a 0 3689 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.5.8.1) cvn H.B /DEST pdfmark end 0 3689 a 140 x Fd(5.8.1)112 b(File)39 b(Chec)m(ksum)f(Routines)0 4053 y Fj(The)33 b(follo)m(wing)h(routines)f(either)h(compute)f(or)h(v)-5 b(alidate)34 b(the)g(c)m(hec)m(ksums)f(for)g(the)h(CHDU.)g(The)e(D)m(A) -8 b(T)g(ASUM)0 4166 y(k)m(eyw)m(ord)33 b(is)f(used)f(to)i(store)f(the) h(n)m(umerical)f(v)-5 b(alue)33 b(of)f(the)g(32-bit,)i(1's)f(complemen) m(t)g(c)m(hec)m(ksum)g(for)f(the)g(data)0 4279 y(unit)26 b(alone.)40 b(If)25 b(there)h(is)h(no)e(data)i(unit)f(then)f(the)h(v)-5 b(alue)27 b(is)f(set)g(to)h(zero.)40 b(The)26 b(n)m(umerical)g(v)-5 b(alue)27 b(is)f(stored)g(as)g(an)0 4392 y(ASCI)s(I)20 b(string)i(of)h(digits,)h(enclosed)f(in)e(quotes,)k(b)s(ecause)d(the)g (v)-5 b(alue)23 b(ma)m(y)f(b)s(e)f(to)s(o)i(large)g(to)g(represen)m(t)f (as)g(a)h(32-bit)0 4505 y(signed)28 b(in)m(teger.)41 b(The)27 b(CHECKSUM)g(k)m(eyw)m(ord)i(is)f(used)f(to)h(store)h(the)f (ASCI)s(I)e(enco)s(ded)i(COMPLEMENT)f(of)0 4618 y(the)f(c)m(hec)m(ksum) h(for)f(the)h(en)m(tire)g(HDU.)g(Storing)f(the)h(complemen)m(t,)h (rather)e(than)g(the)h(actual)g(c)m(hec)m(ksum,)h(forces)0 4731 y(the)k(c)m(hec)m(ksum)h(for)f(the)h(whole)f(HDU)h(to)g(equal)g (zero.)47 b(If)31 b(the)i(\014le)f(has)g(b)s(een)f(mo)s(di\014ed)g (since)i(the)f(c)m(hec)m(ksums)0 4844 y(w)m(ere)39 b(computed,)i(then)e (the)g(HDU)g(c)m(hec)m(ksum)h(will)f(usually)f(not)h(equal)h(zero.)66 b(These)39 b(c)m(hec)m(ksum)g(k)m(eyw)m(ord)0 4957 y(con)m(v)m(en)m (tions)34 b(are)f(based)f(on)g(a)g(pap)s(er)f(b)m(y)h(Rob)g(Seaman)g (published)f(in)h(the)g(pro)s(ceedings)g(of)g(the)h(AD)m(ASS)f(IV)0 5070 y(conference)h(in)e(Baltimore)j(in)d(No)m(v)m(em)m(b)s(er)i(1994)h (and)d(a)h(later)h(revision)f(in)f(June)g(1995.)47 b(See)32 b(App)s(endix)e(B)i(for)0 5182 y(the)f(de\014nition)f(of)g(the)h (parameters)f(used)g(in)g(these)h(routines.)0 5465 y Fi(1)81 b Fj(Compute)33 b(and)g(write)h(the)g(D)m(A)-8 b(T)g(ASUM)35 b(and)e(CHECKSUM)g(k)m(eyw)m(ord)h(v)-5 b(alues)34 b(for)f(the)h(CHDU)g(in)m(to)h(the)227 5578 y(curren)m(t)d(header.)46 b(If)32 b(the)g(k)m(eyw)m(ords)h(already)g (exist,)g(their)g(v)-5 b(alues)32 b(will)h(b)s(e)e(up)s(dated)g(only)h (if)h(necessary)227 5691 y(\(i.e.,)f(if)f(the)f(\014le)h(has)f(b)s(een) f(mo)s(di\014ed)h(since)g(the)h(original)h(k)m(eyw)m(ord)e(v)-5 b(alues)31 b(w)m(ere)g(computed\).)p eop end %%Page: 64 72 TeXDict begin 64 71 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.64) cvn H.B /DEST pdfmark end 0 299 a Fj(64)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)95 555 y Fe(int)47 b(fits_write_chksum)c(/)48 b(ffpcks)286 668 y(\(fitsfile)e(*fptr,)g(>)h(int)g(*status\))0 945 y Fi(2)81 b Fj(Up)s(date)28 b(the)h(CHECKSUM)e(k)m(eyw)m(ord)i(v)-5 b(alue)29 b(in)f(the)h(CHDU,)g(assuming)f(that)h(the)f(D)m(A)-8 b(T)g(ASUM)30 b(k)m(eyw)m(ord)227 1058 y(exists)36 b(and)f(already)h (has)f(the)h(correct)g(v)-5 b(alue.)56 b(This)35 b(routine)g (calculates)j(the)e(new)f(c)m(hec)m(ksum)h(for)f(the)227 1171 y(curren)m(t)40 b(header)g(unit,)j(adds)c(it)i(to)g(the)f(data)h (unit)f(c)m(hec)m(ksum,)k(enco)s(des)c(the)g(v)-5 b(alue)41 b(in)m(to)g(an)f(ASCI)s(I)227 1284 y(string,)31 b(and)f(writes)g(the)h (string)f(to)h(the)g(CHECKSUM)e(k)m(eyw)m(ord.)95 1560 y Fe(int)47 b(fits_update_chksum)c(/)48 b(ffupck)286 1673 y(\(fitsfile)e(*fptr,)g(>)h(int)g(*status\))0 1950 y Fi(3)81 b Fj(V)-8 b(erify)35 b(the)f(CHDU)h(b)m(y)g(computing)f(the)h (c)m(hec)m(ksums)g(and)f(comparing)h(them)f(with)g(the)h(k)m(eyw)m (ords.)53 b(The)227 2063 y(data)34 b(unit)f(is)g(v)m(eri\014ed)g (correctly)h(if)f(the)h(computed)f(c)m(hec)m(ksum)g(equals)h(the)f(v)-5 b(alue)34 b(of)f(the)g(D)m(A)-8 b(T)g(ASUM)227 2176 y(k)m(eyw)m(ord.)64 b(The)37 b(c)m(hec)m(ksum)i(for)f(the)g(en)m(tire)g(HDU)h(\(header)f (plus)f(data)i(unit\))e(is)h(correct)h(if)f(it)h(equals)227 2289 y(zero.)47 b(The)32 b(output)f(D)m(A)-8 b(T)g(A)m(OK)34 b(and)d(HDUOK)i(parameters)f(in)g(this)g(routine)g(are)g(in)m(tegers)i (whic)m(h)e(will)227 2402 y(ha)m(v)m(e)k(a)f(v)-5 b(alue)35 b(=)f(1)h(if)f(the)h(data)g(or)f(HDU)h(is)g(v)m(eri\014ed)f(correctly) -8 b(,)38 b(a)d(v)-5 b(alue)35 b(=)f(0)h(if)f(the)h(D)m(A)-8 b(T)g(ASUM)36 b(or)227 2515 y(CHECKSUM)29 b(k)m(eyw)m(ord)g(is)h(not)f (presen)m(t,)h(or)f(v)-5 b(alue)30 b(=)f(-1)h(if)f(the)h(computed)f(c)m (hec)m(ksum)h(is)f(not)h(correct.)95 2904 y Fe(int)47 b(fits_verify_chksum)c(/)48 b(ffvcks)286 3017 y(\(fitsfile)e(*fptr,)g (>)h(int)g(*dataok,)f(int)h(*hduok,)e(int)i(*status\))0 3294 y Fi(4)81 b Fj(Compute)40 b(and)g(return)g(the)h(c)m(hec)m(ksum)g (v)-5 b(alues)41 b(for)g(the)g(CHDU)g(without)g(creating)h(or)f(mo)s (difying)f(the)227 3407 y(CHECKSUM)33 b(and)h(D)m(A)-8 b(T)g(ASUM)35 b(k)m(eyw)m(ords.)52 b(This)33 b(routine)h(is)g(used)f (in)m(ternally)i(b)m(y)f(\013v)m(c)m(ks,)i(but)d(ma)m(y)227 3520 y(b)s(e)d(useful)g(in)g(other)g(situations)h(as)g(w)m(ell.)95 3796 y Fe(int)47 b(fits_get_chksum/)d(/ffgcks)286 3909 y(\(fitsfile)i(*fptr,)g(>)h(unsigned)f(long)g(*datasum,)g(unsigned)f (long)i(*hdusum,)334 4022 y(int)g(*status\))0 4299 y Fi(5)81 b Fj(Enco)s(de)23 b(a)h(c)m(hec)m(ksum)g(v)-5 b(alue)24 b(in)m(to)g(a)g(16-c)m(haracter)j(string.)38 b(If)23 b(complm)h(is)f(non-zero)i(\(true\))f(then)f(the)h(32-bit)227 4412 y(sum)30 b(v)-5 b(alue)31 b(will)f(b)s(e)g(complemen)m(ted)h(b)s (efore)f(enco)s(ding.)95 4689 y Fe(int)47 b(fits_encode_chksum)c(/)48 b(ffesum)286 4801 y(\(unsigned)e(long)g(sum,)h(int)g(complm,)f(>)h (char)g(*ascii\);)0 5078 y Fi(6)81 b Fj(Deco)s(de)24 b(a)f(16-c)m(haracter)j(c)m(hec)m(ksum)e(string)f(in)m(to)g(a)h (unsigned)e(long)h(v)-5 b(alue.)39 b(If)23 b(is)g(non-zero)g(\(true\).) 39 b(then)23 b(the)227 5191 y(32-bit)33 b(sum)d(v)-5 b(alue)32 b(will)g(b)s(e)f(complemen)m(ted)h(after)g(deco)s(ding.)44 b(The)31 b(c)m(hec)m(ksum)h(v)-5 b(alue)32 b(is)g(also)g(returned)227 5304 y(as)f(the)f(v)-5 b(alue)31 b(of)g(the)f(function.)95 5581 y Fe(unsigned)46 b(long)h(fits_decode_chksum)42 b(/)48 b(ffdsum)525 5694 y(\(char)e(*ascii,)g(int)h(complm,)f(>)h (unsigned)f(long)h(*sum\);)p eop end %%Page: 65 73 TeXDict begin 65 72 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.65) cvn H.B /DEST pdfmark end 0 299 a Fh(5.8.)72 b(UTILITY)30 b(R)m(OUTINES)2693 b Fj(65)0 464 y SDict begin H.S end 0 464 a 0 464 a SDict begin 13.6 H.A end 0 464 a 0 464 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.5.8.2) cvn H.B /DEST pdfmark end 0 464 a 91 x Fd(5.8.2)112 b(Date)38 b(and)g(Time)g (Utilit)m(y)f(Routines)0 774 y Fj(The)29 b(follo)m(wing)i(routines)f (help)f(to)i(construct)f(or)f(parse)h(the)g(FITS)f(date/time)i (strings.)41 b(Starting)30 b(in)f(the)h(y)m(ear)0 887 y(2000,)k(the)d(FITS)g(D)m(A)-8 b(TE)32 b(k)m(eyw)m(ord)g(v)-5 b(alues)31 b(\(and)h(the)f(v)-5 b(alues)32 b(of)f(other)h(`D)m(A)-8 b(TE-')33 b(k)m(eyw)m(ords\))f(m)m(ust)f(ha)m(v)m(e)i(the)0 1000 y(form)j('YYYY-MM-DD')k(\(date)e(only\))f(or)g ('YYYY-MM-DDThh:mm:ss.ddd...')61 b(\(date)38 b(and)e(time\))h(where)0 1113 y(the)30 b(n)m(um)m(b)s(er)f(of)i(decimal)g(places)g(in)f(the)g (seconds)g(v)-5 b(alue)31 b(is)f(optional.)42 b(These)30 b(times)h(are)f(in)g(UTC.)g(The)g(older)0 1226 y('dd/mm/yy')d(date)g (format)g(ma)m(y)h(not)f(b)s(e)f(used)g(for)h(dates)h(after)f(01)h(Jan) m(uary)e(2000.)42 b(See)27 b(App)s(endix)e(B)i(for)g(the)0 1339 y(de\014nition)j(of)h(the)f(parameters)h(used)e(in)h(these)h (routines.)0 1597 y Fi(1)81 b Fj(Get)23 b(the)f(curren)m(t)f(system)i (date.)38 b(C)22 b(already)g(pro)m(vides)g(standard)f(library)h (routines)g(for)f(getting)j(the)e(curren)m(t)227 1710 y(date)k(and)e(time,)j(but)d(this)h(routine)g(is)g(pro)m(vided)g(for)f (compatibilit)m(y)k(with)c(the)h(F)-8 b(ortran)26 b(FITSIO)e(library)-8 b(.)227 1823 y(The)30 b(returned)f(y)m(ear)j(has)e(4)g(digits)h (\(1999,)i(2000,)g(etc.\))95 2081 y Fe(int)47 b (fits_get_system_date/ffgsd)o(t)286 2194 y(\()h(>)f(int)g(*day,)g(int)f (*month,)g(int)h(*year,)f(int)h(*status)f(\))0 2452 y Fi(2)81 b Fj(Get)34 b(the)g(curren)m(t)g(system)f(date)i(and)e(time)h (string)g(\('YYYY-MM-DDThh:mm:ss'\).)53 b(The)33 b(time)i(will)f(b)s(e) 227 2565 y(in)26 b(UTC/GMT)g(if)g(a)m(v)-5 b(ailable,)29 b(as)e(indicated)f(b)m(y)g(a)g(returned)f(timeref)h(v)-5 b(alue)27 b(=)e(0.)40 b(If)26 b(the)g(returned)e(v)-5 b(alue)227 2678 y(of)31 b(timeref)g(=)g(1)g(then)f(this)h(indicates)g (that)h(it)f(w)m(as)g(not)g(p)s(ossible)f(to)h(con)m(v)m(ert)i(the)d (lo)s(cal)i(time)g(to)f(UTC,)227 2791 y(and)f(th)m(us)g(the)h(lo)s(cal) g(time)g(w)m(as)g(returned.)95 3049 y Fe(int)47 b (fits_get_system_time/ffgst)o(m)286 3162 y(\(>)h(char)e(*datestr,)f (int)95 b(*timeref,)45 b(int)i(*status\))0 3421 y Fi(3)81 b Fj(Construct)26 b(a)i(date)g(string)f(from)g(the)g(input)f(date)i(v) -5 b(alues.)40 b(If)27 b(the)g(y)m(ear)h(is)g(b)s(et)m(w)m(een)f(1900)i (and)e(1998,)j(inclu-)227 3534 y(siv)m(e,)38 b(then)c(the)i(returned)d (date)j(string)f(will)g(ha)m(v)m(e)i(the)e(old)g(FITS)f(format)i (\('dd/mm/yy'\),)h(otherwise)227 3647 y(the)32 b(date)f(string)g(will)h (ha)m(v)m(e)g(the)g(new)e(FITS)h(format)g(\('YYYY-MM-DD'\).)36 b(Use)31 b(\014ts)p 3229 3647 28 4 v 33 w(time2str)h(instead)227 3759 y(to)f(alw)m(a)m(ys)h(return)e(a)g(date)h(string)g(using)f(the)g (new)g(FITS)g(format.)95 4018 y Fe(int)47 b(fits_date2str/ffdt2s)286 4131 y(\(int)g(year,)f(int)h(month,)f(int)h(day,)g(>)g(char)g (*datestr,)e(int)i(*status\))0 4389 y Fi(4)81 b Fj(Construct)34 b(a)i(new-format)f(date)h(+)f(time)h(string)f (\('YYYY-MM-DDThh:mm:ss.ddd...'\).)57 b(If)34 b(the)i(y)m(ear,)227 4502 y(mon)m(th,)d(and)e(da)m(y)h(v)-5 b(alues)32 b(all)h(=)e(0)h(then) g(only)g(the)g(time)g(is)g(enco)s(ded)f(with)h(format)g ('hh:mm:ss.ddd...'.)227 4615 y(The)j(decimals)h(parameter)g(sp)s (eci\014es)e(ho)m(w)i(man)m(y)f(decimal)h(places)g(of)f(fractional)i (seconds)e(to)h(include)227 4728 y(in)30 b(the)h(string.)41 b(If)29 b(`decimals')j(is)f(negativ)m(e,)h(then)f(only)f(the)h(date)g (will)f(b)s(e)g(return)f(\('YYYY-MM-DD'\).)95 4986 y Fe(int)47 b(fits_time2str/fftm2s)286 5099 y(\(int)g(year,)f(int)h (month,)f(int)h(day,)g(int)g(hour,)f(int)h(minute,)f(double)g(second,) 286 5212 y(int)h(decimals,)f(>)h(char)g(*datestr,)e(int)i(*status\))0 5470 y Fi(5)81 b Fj(Return)44 b(the)g(date)i(as)f(read)f(from)h(the)g (input)e(string,)49 b(where)44 b(the)h(string)g(ma)m(y)g(b)s(e)f(in)h (either)g(the)g(old)227 5583 y(\('dd/mm/yy'\))29 b(or)f(new)f (\('YYYY-MM-DDThh:mm:ss')k(or)d('YYYY-MM-DD'\))j(FITS)d(format.)40 b(Null)227 5696 y(p)s(oin)m(ters)31 b(ma)m(y)f(b)s(e)g(supplied)f(for)h (an)m(y)h(un)m(w)m(an)m(ted)g(output)f(date)h(parameters.)p eop end %%Page: 66 74 TeXDict begin 66 73 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.66) cvn H.B /DEST pdfmark end 0 299 a Fj(66)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)95 555 y Fe(int)47 b(fits_str2date/ffs2dt)286 668 y(\(char)g(*datestr,)e(>)i(int)g(*year,)f(int)h(*month,)f(int)h (*day,)f(int)h(*status\))0 917 y Fi(6)81 b Fj(Return)30 b(the)h(date)h(and)f(time)h(as)f(read)g(from)g(the)h(input)e(string,)h (where)g(the)h(string)f(ma)m(y)h(b)s(e)e(in)h(either)h(the)227 1030 y(old)d(or)f(new)g(FITS)g(format.)40 b(The)28 b(returned)f(hours,) h(min)m(utes,)h(and)f(seconds)g(v)-5 b(alues)29 b(will)f(b)s(e)g(set)h (to)g(zero)227 1142 y(if)k(the)h(input)e(string)h(do)s(es)g(not)h (include)f(the)g(time)h(\('dd/mm/yy')f(or)h('YYYY-MM-DD'\))j(.)c (Similarly)-8 b(,)227 1255 y(the)36 b(returned)e(y)m(ear,)j(mon)m(th,)g (and)d(date)i(v)-5 b(alues)36 b(will)f(b)s(e)g(set)h(to)g(zero)g(if)f (the)g(date)h(is)f(not)h(included)e(in)227 1368 y(the)29 b(input)f(string)h(\('hh:mm:ss.ddd...'\).)40 b(Null)29 b(p)s(oin)m(ters)f(ma)m(y)i(b)s(e)e(supplied)f(for)i(an)m(y)g(un)m(w)m (an)m(ted)g(output)227 1481 y(date)i(and)f(time)h(parameters.)95 1730 y Fe(int)47 b(fits_str2time/ffs2tm)286 1843 y(\(char)g(*datestr,)e (>)i(int)g(*year,)f(int)h(*month,)f(int)h(*day,)f(int)h(*hour,)286 1956 y(int)g(*minute,)f(double)g(*second,)f(int)i(*status\))0 2094 y SDict begin H.S end 0 2094 a 0 2094 a SDict begin 13.6 H.A end 0 2094 a 0 2094 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.5.8.3) cvn H.B /DEST pdfmark end 0 2094 a 150 x Fd(5.8.3)112 b(General)39 b(Utilit)m(y)e(Routines)0 2463 y Fj(The)30 b(follo)m(wing)i(utilit)m(y)f(routines)g(ma)m(y)g(b)s (e)e(useful)h(for)g(certain)h(applications.)0 2712 y Fi(1)81 b Fj(Return)30 b(the)h(revision)g(n)m(um)m(b)s(er)f(of)h(the)g (CFITSIO)f(library)-8 b(.)42 b(The)31 b(revision)g(n)m(um)m(b)s(er)f (will)h(b)s(e)f(incremen)m(ted)227 2825 y(with)g(eac)m(h)i(new)e (release)h(of)g(CFITSIO.)95 3073 y Fe(float)47 b(fits_get_version)c(/) 48 b(ffvers)e(\()h(>)h(float)e(*version\))0 3322 y Fi(2)81 b Fj(W)-8 b(rite)34 b(an)g(80-c)m(haracter)i(message)e(to)g(the)g (CFITSIO)e(error)h(stac)m(k.)51 b(Application)34 b(programs)f(should)g (not)227 3435 y(normally)e(write)f(to)i(the)e(stac)m(k,)i(but)e(there)g (ma)m(y)h(b)s(e)f(some)h(situations)g(where)f(this)g(is)h(desirable.)95 3683 y Fe(void)47 b(fits_write_errmsg)c(/)48 b(ffpmsg)e(\(char)g (*err_msg\))0 3932 y Fi(3)81 b Fj(Con)m(v)m(ert)31 b(a)g(c)m(haracter)h (string)e(to)h(upp)s(ercase)e(\(op)s(erates)j(in)e(place\).)95 4180 y Fe(void)47 b(fits_uppercase)d(/)j(ffupch)g(\(char)f(*string\))0 4429 y Fi(4)81 b Fj(Compare)43 b(the)i(input)e(template)i(string)f (against)h(the)g(reference)f(string)g(to)h(see)g(if)f(they)g(matc)m(h.) 82 b(The)227 4542 y(template)36 b(string)f(ma)m(y)g(con)m(tain)g (wildcard)f(c)m(haracters:)51 b('*')35 b(will)g(matc)m(h)g(an)m(y)g (sequence)g(of)f(c)m(haracters)227 4655 y(\(including)j(zero)h(c)m (haracters\))g(and)e(')10 b(?')60 b(will)38 b(matc)m(h)f(an)m(y)g (single)h(c)m(haracter)g(in)f(the)g(reference)g(string.)227 4768 y(The)e('#')h(c)m(haracter)h(will)f(matc)m(h)g(an)m(y)g (consecutiv)m(e)h(string)f(of)f(decimal)i(digits)f(\(0)g(-)f(9\).)57 b(If)35 b(casesen)h(=)227 4881 y(CASESEN)c(=)h(TR)m(UE)h(then)f(the)g (matc)m(h)i(will)e(b)s(e)g(case)h(sensitiv)m(e,)i(otherwise)e(the)f (case)i(of)e(the)h(letters)227 4993 y(will)g(b)s(e)f(ignored)h(if)g (casesen)g(=)g(CASEINSEN)e(=)h(F)-10 b(ALSE.)34 b(The)f(returned)f(MA) -8 b(TCH)34 b(parameter)h(will)227 5106 y(b)s(e)30 b(TR)m(UE)g(if)g (the)g(2)h(strings)f(matc)m(h,)h(and)f(EXA)m(CT)g(will)g(b)s(e)g(TR)m (UE)g(if)g(the)g(matc)m(h)h(is)f(exact)i(\(i.e.,)g(if)e(no)227 5219 y(wildcard)k(c)m(haracters)i(w)m(ere)f(used)e(in)h(the)h(matc)m (h\).)53 b(Both)35 b(strings)g(m)m(ust)f(b)s(e)f(68)j(c)m(haracters)f (or)g(less)f(in)227 5332 y(length.)95 5581 y Fe(void)47 b(fits_compare_str)c(/)48 b(ffcmps)334 5694 y(\(char)e(*templt,)g(char) h(*string,)e(int)i(casesen,)f(>)h(int)g(*match,)f(int)h(*exact\))p eop end %%Page: 67 75 TeXDict begin 67 74 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.67) cvn H.B /DEST pdfmark end 0 299 a Fh(5.8.)72 b(UTILITY)30 b(R)m(OUTINES)2693 b Fj(67)0 555 y Fi(5)81 b Fj(Split)30 b(a)i(string)f(con)m(taining)h(a)g(list)f(of)g(names)g(\(t)m(ypically)j (\014le)d(names)g(or)g(column)f(names\))i(in)m(to)g(individual)227 668 y(name)23 b(tok)m(ens)g(b)m(y)g(a)g(sequence)g(of)g(calls)g(to)h (\014ts)p 1814 668 28 4 v 32 w(split)p 2018 668 V 33 w(names.)38 b(The)22 b(names)h(in)f(the)h(list)g(m)m(ust)f(b)s(e)g (delimited)227 781 y(b)m(y)45 b(a)f(comma)i(and/or)e(spaces.)83 b(This)44 b(routine)g(ignores)h(spaces)g(and)f(commas)h(that)g(o)s (ccur)f(within)227 894 y(paren)m(theses,)36 b(brac)m(k)m(ets,)h(or)e (curly)f(brac)m(k)m(ets.)54 b(It)35 b(also)g(strips)f(an)m(y)h(leading) g(and)f(trailing)h(blanks)f(from)227 1007 y(the)d(returned)e(name.)227 1156 y(This)h(routine)g(is)h(similar)f(to)h(the)g(ANSI)f(C)g('strtok')h (function:)227 1305 y(The)37 b(\014rst)f(call)i(to)g(\014ts)p 1033 1305 V 32 w(split)p 1237 1305 V 33 w(names)f(has)g(a)g(non-n)m (ull)f(input)g(string.)61 b(It)37 b(\014nds)e(the)i(\014rst)f(name)h (in)g(the)227 1418 y(string)26 b(and)f(terminates)h(it)h(b)m(y)e(o)m(v) m(erwriting)i(the)f(next)g(c)m(haracter)h(of)f(the)g(string)f(with)h(a) g(n)m(ull)f(terminator)227 1530 y(and)31 b(returns)g(a)h(p)s(oin)m(ter) f(to)i(the)e(name.)45 b(Eac)m(h)32 b(subsequen)m(t)f(call,)j(indicated) e(b)m(y)f(a)h(NULL)g(v)-5 b(alue)32 b(of)g(the)227 1643 y(input)f(string,)i(returns)e(the)h(next)h(name,)f(searc)m(hing)h(from) f(just)g(past)g(the)g(end)f(of)i(the)f(previous)g(name.)227 1756 y(It)f(returns)e(NULL)h(when)g(no)g(further)f(names)h(are)h (found.)143 2008 y Fe(char)47 b(*fits_split_names\(char)42 b(*namelist\))0 2259 y Fj(The)30 b(follo)m(wing)i(example)f(sho)m(ws)f (ho)m(w)g(a)h(string)f(w)m(ould)h(b)s(e)e(split)i(in)m(to)g(3)g(names:) 191 2511 y Fe(myfile[1][bin)44 b(\(x,y\)=4],)h(file2.fits)93 b(file3.fits)191 2624 y(^^^^^^^^^^^^^^^^^^^^^^)c(^^^^^^^^^^)k (^^^^^^^^^^)382 2737 y(1st)47 b(name)619 b(2nd)47 b(name)190 b(3rd)47 b(name)0 2988 y Fi(6)81 b Fj(T)-8 b(est)34 b(that)g(the)g(k)m (eyw)m(ord)g(name)f(con)m(tains)i(only)e(legal)j(c)m(haracters)f (\(A-Z,0-9,)h(h)m(yphen,)d(and)g(underscore\))227 3101 y(or)e(that)g(the)f(k)m(eyw)m(ord)h(record)f(con)m(tains)i(only)e (legal)i(prin)m(table)f(ASCI)s(I)e(c)m(haracters)95 3353 y Fe(int)47 b(fits_test_keyword)c(/)48 b(fftkey)e(\(char)g(*keyname,)g (>)h(int)g(*status\))95 3579 y(int)g(fits_test_record)d(/)j(fftrec)f (\(char)h(*card,)f(>)h(int)g(*status\))0 3830 y Fi(7)81 b Fj(T)-8 b(est)25 b(whether)f(the)h(curren)m(t)f(header)h(con)m(tains) g(an)m(y)g(NULL)g(\(ASCI)s(I)e(0\))j(c)m(haracters.)40 b(These)24 b(c)m(haracters)j(are)227 3943 y(illegal)37 b(in)d(the)h(header,)g(but)f(they)g(will)h(go)g(undetected)g(b)m(y)f (most)h(of)g(the)f(CFITSIO)f(k)m(eyw)m(ord)i(header)227 4056 y(routines,)29 b(b)s(ecause)f(the)h(n)m(ull)f(is)g(in)m(terpreted) g(as)h(the)f(normal)g(end-of-string)h(terminator.)41 b(This)27 b(routine)227 4169 y(returns)h(the)g(p)s(osition)h(of)g(the)g (\014rst)f(n)m(ull)g(c)m(haracter)i(in)f(the)f(header,)h(or)g(zero)g (if)g(there)g(are)g(no)f(n)m(ulls.)40 b(F)-8 b(or)227 4282 y(example)37 b(a)f(returned)f(v)-5 b(alue)37 b(of)f(110)h(w)m (ould)f(indicate)h(that)g(the)f(\014rst)f(NULL)h(is)g(lo)s(cated)h(in)f (the)g(30th)227 4395 y(c)m(haracter)28 b(of)f(the)g(second)f(k)m(eyw)m (ord)h(in)f(the)h(header)f(\(recall)i(that)f(eac)m(h)h(header)e(record) h(is)f(80)h(c)m(haracters)227 4508 y(long\).)45 b(Note)33 b(that)f(this)g(is)f(one)h(of)g(the)g(few)f(CFITSIO)f(routines)h(in)h (whic)m(h)f(the)h(returned)e(v)-5 b(alue)32 b(is)g(not)227 4620 y(necessarily)g(equal)e(to)i(the)e(status)h(v)-5 b(alue\).)95 4872 y Fe(int)47 b(fits_null_check)d(/)j(ffnchk)g(\(char)f (*card,)g(>)h(int)g(*status\))0 5124 y Fi(8)81 b Fj(P)m(arse)25 b(a)g(header)g(k)m(eyw)m(ord)g(record)g(and)f(return)g(the)h(name)g(of) g(the)g(k)m(eyw)m(ord,)i(and)d(the)h(length)h(of)f(the)g(name.)227 5237 y(The)34 b(k)m(eyw)m(ord)h(name)f(normally)h(o)s(ccupies)f(the)h (\014rst)e(8)i(c)m(haracters)g(of)g(the)f(record,)i(except)f(under)e (the)227 5349 y(HIERAR)m(CH)e(con)m(v)m(en)m(tion)h(where)e(the)h(name) f(can)h(b)s(e)f(up)f(to)i(70)g(c)m(haracters)h(in)e(length.)95 5601 y Fe(int)47 b(fits_get_keyname)d(/)j(ffgknm)286 5714 y(\(char)g(*card,)f(>)h(char)g(*keyname,)e(int)i(*keylength,)e (int)i(*status\))p eop end %%Page: 68 76 TeXDict begin 68 75 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.68) cvn H.B /DEST pdfmark end 0 299 a Fj(68)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)0 555 y Fi(9)81 b Fj(P)m(arse)29 b(a)h(header)f(k)m(eyw)m (ord)h(record,)f(returning)g(the)g(v)-5 b(alue)30 b(\(as)g(a)f(literal) i(c)m(haracter)g(string\))e(and)g(commen)m(t)227 668 y(strings.)40 b(If)27 b(the)g(k)m(eyw)m(ord)h(has)f(no)g(v)-5 b(alue)28 b(\(columns)f(9-10)i(not)f(equal)f(to)h('=)g('\),)g(then)f(a) h(n)m(ull)f(v)-5 b(alue)28 b(string)227 781 y(is)j(returned)e(and)h (the)g(commen)m(t)i(string)e(is)g(set)h(equal)g(to)g(column)f(9)h(-)g (80)g(of)g(the)f(input)g(string.)95 1034 y Fe(int)47 b(fits_parse_value)d(/)j(ffpsvc)286 1147 y(\(char)g(*card,)f(>)h(char)g (*value,)f(char)g(*comment,)g(int)h(*status\))0 1401 y Fi(10)f Fj(Construct)40 b(a)g(prop)s(erly)f(formated)i(80-c)m (haracter)i(header)d(k)m(eyw)m(ord)g(record)g(from)g(the)g(input)f(k)m (eyw)m(ord)227 1514 y(name,)25 b(k)m(eyw)m(ord)f(v)-5 b(alue,)25 b(and)e(k)m(eyw)m(ord)h(commen)m(t)g(strings.)38 b(Hierarc)m(hical)26 b(k)m(eyw)m(ord)e(names)f(\(e.g.,)j("ESO)227 1627 y(TELE)e(CAM"\))i(are)f(supp)s(orted.)37 b(The)25 b(v)-5 b(alue)25 b(string)g(ma)m(y)h(con)m(tain)g(an)f(in)m(teger,)i (\015oating)f(p)s(oin)m(t,)g(logical,)227 1739 y(or)31 b(quoted)f(c)m(haracter)i(string)e(\(e.g.,)j("12",)f("15.7",)h("T",)e (or)g("'NGC)g(1313'"\).)143 1993 y Fe(int)47 b(fits_make_key)d(/)k (ffmkky)334 2106 y(\(const)e(char)h(*keyname,)e(const)h(char)h(*value,) f(const)g(char)h(*comment,)430 2219 y(>)g(char)g(*card,)f(int)h (*status\))0 2472 y Fi(11)f Fj(Construct)26 b(an)h(arra)m(y)g(indexed)f (k)m(eyw)m(ord)h(name)f(\(R)m(OOT)g(+)h(nnn\).)38 b(This)26 b(routine)g(app)s(ends)f(the)i(sequence)227 2585 y(n)m(um)m(b)s(er)i (to)i(the)g(ro)s(ot)g(string)f(to)h(create)h(a)f(k)m(eyw)m(ord)g(name)f (\(e.g.,)i('NAXIS')f(+)f(2)h(=)f('NAXIS2'\))95 2838 y Fe(int)47 b(fits_make_keyn)d(/)k(ffkeyn)286 2951 y(\(char)f(*keyroot,)e (int)i(value,)f(>)h(char)g(*keyname,)e(int)i(*status\))0 3205 y Fi(12)f Fj(Construct)41 b(a)h(sequence)f(k)m(eyw)m(ord)h(name)g (\(n)f(+)g(R)m(OOT\).)g(This)g(routine)g(concatenates)j(the)e(sequence) 227 3318 y(n)m(um)m(b)s(er)20 b(to)j(the)e(fron)m(t)h(of)g(the)f(ro)s (ot)h(string)g(to)g(create)h(a)f(k)m(eyw)m(ord)g(name)g(\(e.g.,)j(1)d (+)f('CTYP')g(=)g('1CTYP'\))95 3684 y Fe(int)47 b(fits_make_nkey)d(/)k (ffnkey)286 3797 y(\(int)f(value,)f(char)h(*keyroot,)e(>)i(char)g (*keyname,)e(int)i(*status\))0 4050 y Fi(13)f Fj(Determine)41 b(the)g(data)f(t)m(yp)s(e)h(of)f(a)h(k)m(eyw)m(ord)f(v)-5 b(alue)41 b(string.)70 b(This)39 b(routine)i(parses)e(the)i(k)m(eyw)m (ord)f(v)-5 b(alue)227 4163 y(string)28 b(to)h(determine)f(its)g(data)h (t)m(yp)s(e.)40 b(Returns)27 b('C',)h('L',)h('I',)f('F')h(or)f('X',)g (for)g(c)m(haracter)i(string,)e(logical,)227 4276 y(in)m(teger,)k (\015oating)g(p)s(oin)m(t,)e(or)h(complex,)g(resp)s(ectiv)m(ely)-8 b(.)95 4530 y Fe(int)47 b(fits_get_keytype)d(/)j(ffdtyp)286 4642 y(\(char)g(*value,)f(>)h(char)g(*dtype,)e(int)i(*status\))0 4896 y Fi(14)f Fj(Determine)39 b(the)f(in)m(teger)h(data)g(t)m(yp)s(e)f (of)g(an)g(in)m(teger)h(k)m(eyw)m(ord)f(v)-5 b(alue)39 b(string.)63 b(The)37 b(returned)g(datat)m(yp)s(e)227 5009 y(v)-5 b(alue)36 b(is)f(the)g(minim)m(um)f(in)m(teger)i(datat)m (yp)s(e)g(\(starting)g(from)f(top)g(of)g(the)g(follo)m(wing)i(list)e (and)g(w)m(orking)227 5122 y(do)m(wn\))c(required)e(to)i(store)g(the)g (in)m(teger)h(v)-5 b(alue:)191 5375 y Fe(Data)47 b(Type)285 b(Range)239 5488 y(TSBYTE:)236 b(-128)47 b(to)g(127)239 5601 y(TBYTE:)332 b(128)47 b(to)g(255)239 5714 y(TSHORT:)236 b(-32768)46 b(to)i(32767)p eop end %%Page: 69 77 TeXDict begin 69 76 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.69) cvn H.B /DEST pdfmark end 0 299 a Fh(5.8.)72 b(UTILITY)30 b(R)m(OUTINES)2693 b Fj(69)239 555 y Fe(TUSHORT:)236 b(32768)46 b(to)i(65535)239 668 y(TINT)380 b(-2147483648)45 b(to)i(2147483647)239 781 y(TUINT)380 b(2147483648)45 b(to)i(4294967295)239 894 y(TLONGLONG)140 b(-9223372036854775808)43 b(to)k(9223372036854775807)80 1162 y Fj(The)30 b(*neg)h(parameter)g (returns)e(1)i(if)f(the)h(input)e(v)-5 b(alue)31 b(is)g(negativ)m(e)h (and)e(returns)f(0)i(if)f(it)h(is)g(non-negativ)m(e.)95 1431 y Fe(int)47 b(fits_get_inttype)d(/)j(ffinttyp)286 1544 y(\(char)g(*value,)f(>)h(int)g(*datatype,)e(int)i(*neg,)f(int)h (*status\))0 1812 y Fi(15)f Fj(Return)35 b(the)g(class)h(of)g(an)f (input)g(header)g(record.)56 b(The)35 b(record)g(is)g(classi\014ed)h (in)m(to)h(one)e(of)h(the)f(follo)m(wing)227 1925 y(categories)d(\(the) e(class)g(v)-5 b(alues)30 b(are)f(de\014ned)f(in)h(\014tsio.h\).)41 b(Note)31 b(that)e(this)h(is)f(one)h(of)f(the)g(few)g(CFITSIO)227 2038 y(routines)i(that)f(do)s(es)h(not)f(return)f(a)i(status)g(v)-5 b(alue.)334 2306 y Fe(Class)94 b(Value)619 b(Keywords)95 2419 y(TYP_STRUC_KEY)92 b(10)j(SIMPLE,)46 b(BITPIX,)g(NAXIS,)g(NAXISn,) g(EXTEND,)g(BLOCKED,)1002 2532 y(GROUPS,)g(PCOUNT,)g(GCOUNT,)g(END)1002 2645 y(XTENSION,)g(TFIELDS,)f(TTYPEn,)h(TBCOLn,)g(TFORMn,)g(THEAP,)1002 2758 y(and)h(the)g(first)f(4)i(COMMENT)e(keywords)f(in)i(the)g(primary) f(array)1002 2871 y(that)h(define)f(the)h(FITS)g(format.)95 2984 y(TYP_CMPRS_KEY)92 b(20)j(The)47 b(keywords)f(used)g(in)i(the)e (compressed)f(image)i(or)g(table)1002 3097 y(format,)f(including)f (ZIMAGE,)h(ZCMPTYPE,)f(ZNAMEn,)h(ZVALn,)1002 3210 y(ZTILEn,)g(ZBITPIX,) g(ZNAXISn,)f(ZSCALE,)h(ZZERO,)g(ZBLANK)95 3323 y(TYP_SCAL_KEY)140 b(30)95 b(BSCALE,)46 b(BZERO,)g(TSCALn,)g(TZEROn)95 3435 y(TYP_NULL_KEY)140 b(40)95 b(BLANK,)46 b(TNULLn)95 3548 y(TYP_DIM_KEY)188 b(50)95 b(TDIMn)95 3661 y(TYP_RANG_KEY)140 b(60)95 b(TLMINn,)46 b(TLMAXn,)g(TDMINn,)g(TDMAXn,)g(DATAMIN,)f (DATAMAX)95 3774 y(TYP_UNIT_KEY)140 b(70)95 b(BUNIT,)46 b(TUNITn)95 3887 y(TYP_DISP_KEY)140 b(80)95 b(TDISPn)95 4000 y(TYP_HDUID_KEY)d(90)j(EXTNAME,)46 b(EXTVER,)g(EXTLEVEL,)f (HDUNAME,)g(HDUVER,)h(HDULEVEL)95 4113 y(TYP_CKSUM_KEY)f(100)94 b(CHECKSUM,)46 b(DATASUM)95 4226 y(TYP_WCS_KEY)141 b(110)94 b(WCS)47 b(keywords)f(defined)g(in)h(the)g(the)g(WCS)f(papers,)g (including:)1002 4339 y(CTYPEn,)g(CUNITn,)g(CRVALn,)g(CRPIXn,)g (CROTAn,)f(CDELTn)1002 4452 y(CDj_is,)h(PVj_ms,)g(LONPOLEs,)f(LATPOLEs) 1002 4565 y(TCTYPn,)h(TCTYns,)g(TCUNIn,)g(TCUNns,)g(TCRVLn,)f(TCRVns,)h (TCRPXn,)1002 4677 y(TCRPks,)g(TCDn_k,)g(TCn_ks,)g(TPVn_m,)g(TPn_ms,)f (TCDLTn,)h(TCROTn)1002 4790 y(jCTYPn,)g(jCTYns,)g(jCUNIn,)g(jCUNns,)g (jCRVLn,)f(jCRVns,)h(iCRPXn,)1002 4903 y(iCRPns,)g(jiCDn,)94 b(jiCDns,)46 b(jPVn_m,)g(jPn_ms,)f(jCDLTn,)h(jCROTn)1002 5016 y(\(i,j,m,n)g(are)h(integers,)e(s)i(is)h(any)f(letter\))95 5129 y(TYP_REFSYS_KEY)d(120)j(EQUINOXs,)f(EPOCH,)g(MJD-OBSs,)f (RADECSYS,)g(RADESYSs,)g(DATE-OBS)95 5242 y(TYP_COMM_KEY)140 b(130)47 b(COMMENT,)f(HISTORY,)f(\(blank)h(keyword\))95 5355 y(TYP_CONT_KEY)140 b(140)47 b(CONTINUE)95 5468 y(TYP_USER_KEY)140 b(150)47 b(all)g(other)g(keywords)95 5694 y(int)g(fits_get_keyclass)c (/)48 b(ffgkcl)e(\(char)g(*card\))p eop end %%Page: 70 78 TeXDict begin 70 77 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.70) cvn H.B /DEST pdfmark end 0 299 a Fj(70)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)0 555 y Fi(16)46 b Fj(P)m(arse)28 b(the)g('TF)m(ORM')g (binary)f(table)h(column)g(format)f(string.)40 b(This)27 b(routine)g(parses)g(the)h(input)f(TF)m(ORM)227 668 y(c)m(haracter)38 b(string)d(and)g(returns)g(the)g(in)m(teger)i(data)g(t)m(yp)s(e)f(co)s (de,)h(the)f(rep)s(eat)g(coun)m(t)g(of)g(the)f(\014eld,)i(and,)227 781 y(in)e(the)f(case)i(of)f(c)m(haracter)h(string)f(\014elds,)g(the)g (length)g(of)g(the)g(unit)f(string.)54 b(See)34 b(App)s(endix)f(B)i (for)g(the)227 894 y(allo)m(w)m(ed)41 b(v)-5 b(alues)38 b(for)h(the)f(returned)g(t)m(yp)s(eco)s(de)h(parameter.)65 b(A)39 b(n)m(ull)f(p)s(oin)m(ter)h(ma)m(y)g(b)s(e)f(giv)m(en)h(for)g (an)m(y)227 1007 y(output)30 b(parameters)h(that)g(are)g(not)f(needed.) 143 1261 y Fe(int)47 b(fits_binary_tform)c(/)48 b(ffbnfm)334 1374 y(\(char)e(*tform,)g(>)i(int)f(*typecode,)e(long)h(*repeat,)g (long)g(*width,)382 1487 y(int)h(*status\))143 1713 y(int)g (fits_binary_tformll)c(/)k(ffbnfmll)334 1826 y(\(char)f(*tform,)g(>)i (int)f(*typecode,)e(LONGLONG)g(*repeat,)h(long)g(*width,)382 1939 y(int)h(*status\))0 2194 y Fi(17)f Fj(P)m(arse)38 b(the)f('TF)m(ORM')h(k)m(eyw)m(ord)g(v)-5 b(alue)37 b(that)h(de\014nes) e(the)h(column)g(format)h(in)e(an)h(ASCI)s(I)f(table.)62 b(This)227 2307 y(routine)29 b(parses)g(the)g(input)f(TF)m(ORM)h(c)m (haracter)h(string)f(and)g(returns)e(the)i(data)h(t)m(yp)s(e)f(co)s (de,)h(the)f(width)227 2419 y(of)f(the)f(column,)h(and)f(\(if)h(it)g (is)f(a)h(\015oating)g(p)s(oin)m(t)g(column\))f(the)h(n)m(um)m(b)s(er)e (of)h(decimal)i(places)f(to)g(the)f(righ)m(t)227 2532 y(of)39 b(the)f(decimal)h(p)s(oin)m(t.)65 b(The)38 b(returned)f(data)i (t)m(yp)s(e)f(co)s(des)g(are)h(the)g(same)f(as)h(for)f(the)g(binary)g (table,)227 2645 y(with)26 b(the)h(follo)m(wing)h(additional)f(rules:) 38 b(in)m(teger)28 b(columns)e(that)h(are)f(b)s(et)m(w)m(een)h(1)g(and) f(4)g(c)m(haracters)i(wide)227 2758 y(are)i(de\014ned)e(to)j(b)s(e)d (short)i(in)m(tegers)g(\(co)s(de)g(=)g(TSHOR)-8 b(T\).)29 b(Wider)g(in)m(teger)i(columns)e(are)h(de\014ned)e(to)j(b)s(e)227 2871 y(regular)39 b(in)m(tegers)g(\(co)s(de)g(=)f(TLONG\).)h(Similarly) -8 b(,)41 b(Fixed)e(decimal)g(p)s(oin)m(t)f(columns)g(\(with)h(TF)m (ORM)227 2984 y(=)c('Fw.d'\))g(are)h(de\014ned)d(to)j(b)s(e)e(single)i (precision)f(reals)h(\(co)s(de)f(=)g(TFLO)m(A)-8 b(T\))35 b(if)g(w)g(is)g(b)s(et)m(w)m(een)g(1)h(and)227 3097 y(7)42 b(c)m(haracters)h(wide,)h(inclusiv)m(e.)75 b(Wider)41 b('F')h(columns)f(will)h(return)e(a)i(double)f(precision)h(data)g(co)s (de)227 3210 y(\(=)32 b(TDOUBLE\).)h('Ew.d')f(format)g(columns)g(will)g (ha)m(v)m(e)i(dataco)s(de)f(=)e(TFLO)m(A)-8 b(T,)33 b(and)e('Dw.d')i (format)227 3323 y(columns)45 b(will)h(ha)m(v)m(e)h(dataco)s(de)f(=)f (TDOUBLE.)g(A)h(n)m(ull)f(p)s(oin)m(ter)h(ma)m(y)f(b)s(e)g(giv)m(en)i (for)e(an)m(y)g(output)227 3436 y(parameters)31 b(that)g(are)g(not)f (needed.)95 3690 y Fe(int)47 b(fits_ascii_tform)d(/)j(ffasfm)286 3803 y(\(char)g(*tform,)f(>)h(int)g(*typecode,)e(long)i(*width,)e(int)i (*decimals,)334 3916 y(int)g(*status\))0 4171 y Fi(18)f Fj(Calculate)32 b(the)f(starting)g(column)g(p)s(ositions)f(and)g(total) i(ASCI)s(I)d(table)j(width)d(based)i(on)f(the)h(input)e(arra)m(y)227 4284 y(of)e(ASCI)s(I)e(table)i(TF)m(ORM)g(v)-5 b(alues.)40 b(The)26 b(SP)-8 b(A)m(CE)27 b(input)e(parameter)i(de\014nes)f(ho)m(w)h (man)m(y)f(blank)h(spaces)227 4397 y(to)40 b(lea)m(v)m(e)i(b)s(et)m(w)m (een)e(eac)m(h)g(column)g(\(it)g(is)f(recommended)g(to)h(ha)m(v)m(e)h (one)e(space)h(b)s(et)m(w)m(een)g(columns)f(for)227 4509 y(b)s(etter)31 b(h)m(uman)e(readabilit)m(y\).)95 4764 y Fe(int)47 b(fits_get_tbcol)d(/)k(ffgabc)286 4877 y(\(int)f(tfields,)f (char)g(**tform,)g(int)h(space,)f(>)h(long)g(*rowlen,)334 4990 y(long)g(*tbcol,)f(int)g(*status\))0 5245 y Fi(19)g Fj(P)m(arse)27 b(a)g(template)h(header)e(record)g(and)g(return)g(a)g (formatted)h(80-c)m(haracter)j(string)c(suitable)h(for)f(app)s(end-)227 5357 y(ing)40 b(to)f(\(or)h(deleting)g(from\))f(a)g(FITS)g(header)g (\014le.)67 b(This)38 b(routine)h(is)g(useful)g(for)f(parsing)h(lines)g (from)227 5470 y(an)33 b(ASCI)s(I)f(template)i(\014le)f(and)g (reformatting)h(them)f(in)m(to)h(legal)h(FITS)d(header)h(records.)49 b(The)32 b(format-)227 5583 y(ted)i(string)g(ma)m(y)g(then)f(b)s(e)g (passed)h(to)g(the)g(\014ts)p 1880 5583 28 4 v 32 w(write)p 2114 5583 V 33 w(record,)h(\013mcrd,)f(or)g(\014ts)p 3007 5583 V 32 w(delete)p 3270 5583 V 34 w(k)m(ey)h(routines)e(to)227 5696 y(app)s(end)c(or)h(mo)s(dify)g(a)h(FITS)e(header)h(record.)p eop end %%Page: 71 79 TeXDict begin 71 78 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.71) cvn H.B /DEST pdfmark end 0 299 a Fh(5.8.)72 b(UTILITY)30 b(R)m(OUTINES)2693 b Fj(71)95 555 y Fe(int)47 b(fits_parse_template)c (/)k(ffgthd)286 668 y(\(char)g(*templt,)e(>)j(char)e(*card,)g(int)h (*keytype,)f(int)h(*status\))0 932 y Fj(The)31 b(input)g(templt)h(c)m (haracter)h(string)f(generally)h(should)d(con)m(tain)j(3)f(tok)m(ens:) 44 b(\(1\))33 b(the)f(KEYNAME,)g(\(2\))h(the)0 1045 y(V)-10 b(ALUE,)37 b(and)f(\(3\))i(the)f(COMMENT)g(string.)59 b(The)37 b(TEMPLA)-8 b(TE)36 b(string)h(m)m(ust)f(adhere)h(to)h(the)e (follo)m(wing)0 1158 y(format:)0 1421 y Fi(-)80 b Fj(The)32 b(KEYNAME)h(tok)m(en)h(m)m(ust)f(b)s(egin)f(in)h(columns)f(1-8)i(and)e (b)s(e)g(a)h(maxim)m(um)g(of)g(8)g(c)m(haracters)h(long.)49 b(A)227 1534 y(legal)30 b(FITS)e(k)m(eyw)m(ord)h(name)f(ma)m(y)h(only)f (con)m(tain)i(the)f(c)m(haracters)g(A-Z,)g(0-9,)h(and)e('-')h(\(min)m (us)f(sign\))h(and)227 1647 y(underscore.)40 b(This)27 b(routine)i(will)g(automatically)i(con)m(v)m(ert)f(an)m(y)f(lo)m(w)m (ercase)i(c)m(haracters)f(to)g(upp)s(ercase)d(in)227 1760 y(the)k(output)f(string.)42 b(If)30 b(the)h(\014rst)f(8)h(c)m (haracters)h(of)f(the)g(template)h(line)f(are)g(blank)f(then)h(the)g (remainder)227 1873 y(of)g(the)f(line)h(is)g(considered)f(to)h(b)s(e)f (a)g(FITS)g(commen)m(t)h(\(with)g(a)g(blank)f(k)m(eyw)m(ord)g(name\).)0 2137 y Fi(-)80 b Fj(The)26 b(V)-10 b(ALUE)26 b(tok)m(en)h(m)m(ust)e(b)s (e)h(separated)g(from)f(the)i(KEYNAME)f(tok)m(en)h(b)m(y)f(one)g(or)g (more)g(spaces)g(and/or)227 2250 y(an)g('=')g(c)m(haracter.)41 b(The)25 b(data)h(t)m(yp)s(e)g(of)g(the)g(V)-10 b(ALUE)26 b(tok)m(en)g(\(n)m(umeric,)h(logical,)j(or)c(c)m(haracter)h(string\))f (is)227 2363 y(automatically)35 b(determined)c(and)h(the)g(output)f (CARD)h(string)g(is)g(formatted)g(accordingly)-8 b(.)47 b(The)31 b(v)-5 b(alue)227 2476 y(tok)m(en)34 b(ma)m(y)f(b)s(e)f (forced)g(to)i(b)s(e)e(in)m(terpreted)g(as)h(a)g(string)g(\(e.g.)48 b(if)33 b(it)g(is)f(a)h(string)g(of)f(n)m(umeric)h(digits\))g(b)m(y)227 2588 y(enclosing)g(it)f(in)f(single)h(quotes.)45 b(If)31 b(the)h(v)-5 b(alue)32 b(tok)m(en)g(is)g(a)g(c)m(haracter)h(string)e (that)i(con)m(tains)f(1)g(or)g(more)227 2701 y(em)m(b)s(edded)39 b(blank)g(space)h(c)m(haracters)h(or)e(slash)h(\('/'\))h(c)m(haracters) g(then)e(the)g(en)m(tire)i(c)m(haracter)g(string)227 2814 y(m)m(ust)31 b(b)s(e)e(enclosed)i(in)f(single)h(quotes.)0 3078 y Fi(-)80 b Fj(The)28 b(COMMENT)g(tok)m(en)h(is)f(optional,)i(but) e(if)g(presen)m(t)g(m)m(ust)g(b)s(e)g(separated)g(from)g(the)h(V)-10 b(ALUE)28 b(tok)m(en)h(b)m(y)227 3191 y(a)i(blank)f(space)h(or)f(a)h ('/')g(c)m(haracter.)0 3455 y Fi(-)80 b Fj(One)29 b(exception)h(to)f (the)g(ab)s(o)m(v)m(e)i(rules)d(is)h(that)g(if)g(the)g(\014rst)g (non-blank)f(c)m(haracter)i(in)f(the)g(\014rst)f(8)h(c)m(haracters)227 3568 y(of)24 b(the)h(template)g(string)f(is)g(a)g(min)m(us)g(sign)g (\('-'\))h(follo)m(w)m(ed)h(b)m(y)e(a)g(single)h(tok)m(en,)h(or)e(a)h (single)f(tok)m(en)h(follo)m(w)m(ed)227 3681 y(b)m(y)k(an)g(equal)h (sign,)g(then)f(it)g(is)h(in)m(terpreted)f(as)h(the)f(name)g(of)h(a)f (k)m(eyw)m(ord)h(whic)m(h)f(is)g(to)h(b)s(e)e(deleted)i(from)227 3793 y(the)h(FITS)e(header.)0 4057 y Fi(-)80 b Fj(The)32 b(second)g(exception)h(is)f(that)h(if)f(the)g(template)h(string)f (starts)h(with)e(a)i(min)m(us)e(sign)h(and)f(is)h(follo)m(w)m(ed)i(b)m (y)227 4170 y(2)f(tok)m(ens)g(\(without)g(an)f(equals)h(sign)g(b)s(et)m (w)m(een)g(them\))f(then)g(the)h(second)f(tok)m(en)i(is)e(in)m (terpreted)h(as)g(the)227 4283 y(new)f(name)h(for)f(the)h(k)m(eyw)m (ord)g(sp)s(eci\014ed)f(b)m(y)h(\014rst)f(tok)m(en.)48 b(In)32 b(this)g(case)i(the)f(old)g(k)m(eyw)m(ord)g(name)f(\(\014rst) 227 4396 y(tok)m(en\))c(is)e(returned)e(in)i(c)m(haracters)h(1-8)g(of)g (the)f(returned)e(CARD)j(string,)g(and)e(the)h(new)f(k)m(eyw)m(ord)i (name)227 4509 y(\(the)35 b(second)e(tok)m(en\))j(is)e(returned)e(in)i (c)m(haracters)h(41-48)h(of)e(the)g(returned)e(CARD)i(string.)51 b(These)34 b(old)227 4622 y(and)i(new)f(names)h(ma)m(y)h(then)f(b)s(e)f (passed)g(to)i(the)f(\013mnam)g(routine)g(whic)m(h)g(will)g(c)m(hange)h (the)f(k)m(eyw)m(ord)227 4735 y(name.)0 4998 y(The)30 b(k)m(eyt)m(yp)s(e)h(output)f(parameter)h(indicates)g(ho)m(w)g(the)f (returned)g(CARD)g(string)g(should)g(b)s(e)f(in)m(terpreted:)382 5262 y Fe(keytype)857 b(interpretation)382 5375 y(-------)475 b(-------------------------)o(----)o(---)o(----)o(----)o(---)o(----)o (--)525 5488 y(-2)572 b(Rename)46 b(the)h(keyword)f(with)h(name)f(=)i (the)f(first)f(8)h(characters)e(of)j(CARD)1193 5601 y(to)f(the)g(new)g (name)g(given)f(in)h(characters)e(41)j(-)f(48)g(of)g(CARD.)p eop end %%Page: 72 80 TeXDict begin 72 79 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.72) cvn H.B /DEST pdfmark end 0 299 a Fj(72)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)525 555 y Fe(-1)572 b(delete)46 b(the)h(keyword)f(with)h (this)f(name)h(from)g(the)f(FITS)h(header.)573 781 y(0)572 b(append)46 b(the)h(CARD)g(string)f(to)h(the)g(FITS)g(header)f(if)h (the)1193 894 y(keyword)f(does)h(not)g(already)e(exist,)h(otherwise)g (update)1193 1007 y(the)h(keyword)f(value)g(and/or)g(comment)g(field)h (if)g(is)g(already)f(exists.)573 1233 y(1)572 b(This)47 b(is)g(a)g(HISTORY)f(or)h(COMMENT)f(keyword;)g(append)g(it)h(to)g(the)g (header)573 1458 y(2)572 b(END)47 b(record;)f(do)h(not)g(explicitly)e (write)h(it)i(to)f(the)g(FITS)f(file.)0 1708 y Fj(EXAMPLES:)30 b(The)g(follo)m(wing)i(lines)e(illustrate)i(v)-5 b(alid)31 b(input)e(template)j(strings:)286 1958 y Fe(INTVAL)46 b(7)i(/)f(This)g(is)g(an)g(integer)f(keyword)286 2071 y(RVAL)524 b(34.6)142 b(/)239 b(This)46 b(is)i(a)f(floating)f(point)g (keyword)286 2184 y(EVAL=-12.45E-03)92 b(/)47 b(This)g(is)g(a)g (floating)f(point)g(keyword)g(in)h(exponential)e(notation)286 2296 y(lval)i(F)g(/)h(This)f(is)g(a)g(boolean)f(keyword)859 2409 y(This)h(is)g(a)g(comment)f(keyword)g(with)h(a)g(blank)f(keyword)g (name)286 2522 y(SVAL1)h(=)g('Hello)f(world')142 b(/)95 b(this)47 b(is)g(a)g(string)f(keyword)286 2635 y(SVAL2)94 b('123.5')g(this)47 b(is)g(also)f(a)i(string)e(keyword)286 2748 y(sval3)94 b(123+)h(/)g(this)47 b(is)g(also)f(a)i(string)e (keyword)g(with)g(the)h(value)g('123+)189 b(')286 2861 y(#)48 b(the)f(following)e(template)h(line)g(deletes)g(the)h(DATE)g (keyword)286 2974 y(-)h(DATE)286 3087 y(#)g(the)f(following)e(template) h(line)g(modifies)g(the)h(NAME)f(keyword)g(to)h(OBJECT)286 3200 y(-)h(NAME)e(OBJECT)0 3449 y Fi(20)g Fj(T)-8 b(ranslate)32 b(a)g(k)m(eyw)m(ord)g(name)f(in)m(to)h(a)g(new)f(name,)h(based)f(on)g (a)h(set)f(of)h(patterns.)43 b(This)31 b(routine)g(is)h(useful)227 3562 y(for)j(translating)h(k)m(eyw)m(ords)g(in)e(cases)i(suc)m(h)f(as)h (adding)e(or)h(deleting)h(columns)f(in)g(a)g(table,)j(or)d(cop)m(ying) 227 3675 y(a)41 b(column)g(from)f(one)h(table)g(to)g(another,)j(or)c (extracting)j(an)d(arra)m(y)h(from)f(a)h(cell)h(in)e(a)h(binary)f (table)227 3788 y(column)31 b(in)m(to)g(an)g(image)g(extension.)42 b(In)30 b(these)h(cases,)h(it)f(is)g(necessary)g(to)g(translate)h(the)f (names)f(of)h(the)227 3901 y(k)m(eyw)m(ords)f(asso)s(ciated)i(with)d (the)h(original)h(table)g(column\(s\))f(in)m(to)g(the)g(appropriate)g (k)m(eyw)m(ord)g(name)g(in)227 4014 y(the)37 b(\014nal)f(\014le.)58 b(F)-8 b(or)37 b(example,)i(if)d(column)h(2)f(is)h(deleted)g(from)e(a)i (table,)i(then)d(the)h(v)-5 b(alue)36 b(of)h('n')f(in)g(all)227 4127 y(the)c(TF)m(ORMn)g(and)f(TTYPEn)f(k)m(eyw)m(ords)i(for)g(columns) f(3)h(and)f(higher)h(m)m(ust)f(b)s(e)g(decremen)m(ted)i(b)m(y)e(1.)227 4240 y(Ev)m(en)j(more)g(complex)h(translations)f(are)h(sometimes)f (needed)g(to)h(con)m(v)m(ert)g(the)f(W)m(CS)g(k)m(eyw)m(ords)g(when)227 4353 y(extracting)e(an)f(image)g(out)g(of)f(a)h(table)g(column)g(cell)g (in)m(to)h(a)e(separate)i(image)f(extension.)227 4501 y(The)g(user)f(passes)i(an)f(arra)m(y)g(of)h(patterns)f(to)h(b)s(e)e (matc)m(hed.)44 b(Input)30 b(pattern)h(n)m(um)m(b)s(er)f(i)i(is)f (pattern[i][0],)227 4614 y(and)j(output)f(pattern)h(n)m(um)m(b)s(er)f (i)h(is)g(pattern[i][1].)53 b(Keyw)m(ords)34 b(are)g(matc)m(hed)h (against)g(the)f(input)f(pat-)227 4727 y(terns.)41 b(If)30 b(a)g(matc)m(h)i(is)e(found)f(then)h(the)h(k)m(eyw)m(ord)g(is)f (re-written)h(according)g(to)g(the)g(output)f(pattern.)227 4876 y(Order)41 b(is)h(imp)s(ortan)m(t.)76 b(The)41 b(\014rst)h(matc)m (h)h(is)f(accepted.)77 b(The)41 b(fastest)i(matc)m(h)g(will)f(b)s(e)g (made)g(when)227 4989 y(templates)32 b(with)e(the)h(same)f(\014rst)g(c) m(haracter)i(are)f(group)s(ed)e(together.)227 5137 y(Sev)m(eral)j(c)m (haracters)f(ha)m(v)m(e)h(sp)s(ecial)f(meanings:)466 5375 y Fe(i,j)47 b(-)g(single)f(digits,)g(preserved)f(in)j(output)e (template)466 5488 y(n)h(-)h(column)e(number)g(of)h(one)g(or)g(more)g (digits,)f(preserved)f(in)i(output)f(template)466 5601 y(m)h(-)h(generic)e(number)g(of)h(one)g(or)g(more)g(digits,)e (preserved)h(in)h(output)f(template)466 5714 y(a)h(-)h(coordinate)d (designator,)g(preserved)g(in)i(output)f(template)p eop end %%Page: 73 81 TeXDict begin 73 80 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.73) cvn H.B /DEST pdfmark end 0 299 a Fh(5.8.)72 b(UTILITY)30 b(R)m(OUTINES)2693 b Fj(73)466 555 y Fe(#)47 b(-)h(number)e(of)h(one)g (or)g(more)g(digits)466 668 y(?)g(-)h(any)f(character)466 781 y(*)g(-)h(only)e(allowed)g(in)h(first)g(character)e(position,)g(to) j(match)e(all)657 894 y(keywords;)f(only)i(useful)f(as)h(last)g (pattern)e(in)j(the)f(list)227 1133 y Fj(i,)31 b(j,)f(n,)g(and)g(m)g (are)h(returned)e(b)m(y)i(the)f(routine.)227 1282 y(F)-8 b(or)27 b(example,)g(the)f(input)f(pattern)h("iCTYPn")g(will)g(matc)m (h)h("1CTYP5")g(\(if)f(n)p 3003 1282 28 4 v 32 w(v)-5 b(alue)26 b(is)g(5\);)i(the)e(output)227 1395 y(pattern)31 b("CTYPEi")f(will)h(b)s(e)f(re-written)h(as)f("CTYPE1".)42 b(Notice)32 b(that)f("i")g(is)g(preserv)m(ed.)227 1544 y(The)f(follo)m(wing)i(output)e(patterns)g(are)h(sp)s(ecial:)227 1693 y("-")h(-)e(do)h(not)f(cop)m(y)h(a)g(k)m(eyw)m(ord)g(that)g(matc)m (hes)g(the)g(corresp)s(onding)e(input)h(pattern)227 1841 y("+")h(-)g(cop)m(y)g(the)f(input)g(unc)m(hanged)227 1990 y(The)f(inrec)h(string)g(could)g(b)s(e)f(just)g(the)h(8-c)m(har)h (k)m(eyw)m(ord)f(name,)g(or)f(the)h(en)m(tire)h(80-c)m(har)g(header)f (record.)227 2103 y(Characters)h(9)g(-)f(80)h(in)g(the)f(input)g (string)g(simply)g(get)h(app)s(ended)e(to)i(the)g(translated)g(k)m(eyw) m(ord)f(name.)227 2252 y(If)h(n)p 375 2252 V 33 w(range)g(=)g(0,)i (then)e(only)h(k)m(eyw)m(ords)f(with)h('n')f(equal)h(to)g(n)p 2410 2252 V 32 w(v)-5 b(alue)32 b(will)g(b)s(e)f(considered)g(as)h(a)g (pattern)227 2365 y(matc)m(h.)70 b(If)39 b(n)p 722 2365 V 32 w(range)h(=)f(+1,)j(then)e(all)g(v)-5 b(alues)40 b(of)g('n')f(greater)i(than)e(or)h(equal)g(to)g(n)p 3269 2365 V 33 w(v)-5 b(alue)40 b(will)g(b)s(e)f(a)227 2478 y(matc)m(h,)32 b(and)e(if)g(-1,)h(then)f(v)-5 b(alues)31 b(of)g('n')f(less)g(than)h(or)f(equal)h(to)g(n)p 2530 2478 V 32 w(v)-5 b(alue)31 b(will)g(matc)m(h.)0 2728 y Fe(int)47 b(fits_translate_keyword\()286 2841 y(char)g(*inrec,)380 b(/*)47 b(I)h(-)f(input)f(string)g(*/)286 2954 y(char)h(*outrec,)332 b(/*)47 b(O)h(-)f(output)f(converted)f(string,)h(or)h(*/)1241 3067 y(/*)238 b(a)47 b(null)g(string)f(if)h(input)g(does)f(not)95 b(*/)1241 3180 y(/*)238 b(match)46 b(any)h(of)g(the)g(patterns)f(*/)286 3293 y(char)h(*patterns[][2],/*)c(I)48 b(-)f(pointer)f(to)h(input)f(/)i (output)e(string)g(*/)1241 3406 y(/*)238 b(templates)45 b(*/)286 3519 y(int)i(npat,)524 b(/*)47 b(I)h(-)f(number)f(of)h (templates)f(passed)g(*/)286 3632 y(int)h(n_value,)380 b(/*)47 b(I)h(-)f(base)g('n')g(template)e(value)h(of)i(interest)d(*/) 286 3745 y(int)i(n_offset,)332 b(/*)47 b(I)h(-)f(offset)f(to)h(be)g (applied)f(to)h(the)g('n')g(*/)1241 3857 y(/*)238 b(value)46 b(in)i(the)e(output)h(string)f(*/)286 3970 y(int)h(n_range,)380 b(/*)47 b(I)h(-)f(controls)f(range)g(of)h('n')g(template)f(*/)1241 4083 y(/*)238 b(values)46 b(of)h(interest)f(\(-1,0,)g(or)h(+1\))g(*/) 286 4196 y(int)g(*pat_num,)332 b(/*)47 b(O)h(-)f(matched)f(pattern)g (number)g(\(0)h(based\))f(or)h(-1)g(*/)286 4309 y(int)g(*i,)620 b(/*)47 b(O)h(-)f(value)f(of)i(i,)f(if)g(any,)g(else)f(0)i(*/)286 4422 y(int)f(*j,)620 b(/*)47 b(O)h(-)f(value)f(of)i(j,)f(if)g(any,)g (else)f(0)i(*/)286 4535 y(int)f(*m,)620 b(/*)47 b(O)h(-)f(value)f(of)i (m,)f(if)g(any,)g(else)f(0)i(*/)286 4648 y(int)f(*n,)620 b(/*)47 b(O)h(-)f(value)f(of)i(n,)f(if)g(any,)g(else)f(0)i(*/)286 4761 y(int)f(*status\))380 b(/*)47 b(IO)g(-)h(error)e(status)g(*/)80 5011 y Fj(Here)25 b(is)f(an)g(example)g(of)g(some)h(of)f(the)g (patterns)g(used)f(to)i(con)m(v)m(ert)g(the)f(k)m(eyw)m(ords)h(asso)s (ciated)g(with)f(an)g(image)227 5124 y(in)30 b(a)h(cell)h(of)e(a)h (table)g(column)f(in)m(to)i(the)e(k)m(eyw)m(ords)h(appropriate)f(for)h (an)f(IMA)m(GE)h(extension:)191 5375 y Fe(char)47 b(*patterns[][2])c(=) 48 b({{"TSCALn",)92 b("BSCALE")i(},)h(/*)47 b(Standard)e(FITS)i (keywords)e(*/)143 5488 y({"TZEROn",)93 b("BZERO")141 b(},)143 5601 y({"TUNITn",)93 b("BUNIT")141 b(},)143 5714 y({"TNULLn",)93 b("BLANK")141 b(},)p eop end %%Page: 74 82 TeXDict begin 74 81 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.74) cvn H.B /DEST pdfmark end 0 299 a Fj(74)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)143 555 y Fe({"TDMINn",)93 b("DATAMIN")45 b(},)143 668 y({"TDMAXn",)93 b("DATAMAX")45 b(},)143 781 y({"iCTYPn",)93 b("CTYPEi")g(},)i(/*)47 b(Coordinate)e(labels)h(*/) 143 894 y({"iCTYna",)93 b("CTYPEia")45 b(},)143 1007 y({"iCUNIn",)93 b("CUNITi")g(},)i(/*)47 b(Coordinate)e(units)i(*/)143 1120 y({"iCUNna",)93 b("CUNITia")45 b(},)143 1233 y({"iCRVLn",)93 b("CRVALi")g(},)i(/*)47 b(WCS)g(keywords)f(*/)143 1346 y({"iCRVna",)93 b("CRVALia")45 b(},)143 1458 y({"iCDLTn",)93 b("CDELTi")g(},)143 1571 y({"iCDEna",)g("CDELTia")45 b(},)143 1684 y({"iCRPXn",)93 b("CRPIXi")g(},)143 1797 y({"iCRPna",)g("CRPIXia")45 b(},)143 1910 y({"ijPCna",)93 b("PCi_ja")g(},)143 2023 y({"ijCDna",)g("CDi_ja")g(},)143 2136 y({"iVn_ma",)g("PVi_ma")g(},)143 2249 y({"iSn_ma",)g("PSi_ma")g (},)143 2362 y({"iCRDna",)g("CRDERia")45 b(},)143 2475 y({"iCSYna",)93 b("CSYERia")45 b(},)143 2588 y({"iCROTn",)93 b("CROTAi")g(},)143 2700 y({"WCAXna",)g("WCSAXESa"},)143 2813 y({"WCSNna",)g("WCSNAMEa"}};)0 3065 y Fi(21)46 b Fj(T)-8 b(ranslate)26 b(the)f(k)m(eyw)m(ords)g(in)g(the)g(input)e(HDU)j (in)m(to)g(the)f(k)m(eyw)m(ords)g(that)h(are)f(appropriate)g(for)f(the) h(output)227 3178 y(HDU.)32 b(This)d(is)i(a)f(driv)m(er)h(routine)f (that)h(calls)g(the)g(previously)f(describ)s(ed)f(routine.)0 3430 y Fe(int)47 b(fits_translate_keywords\()143 3543 y(fitsfile)f(*infptr,)141 b(/*)47 b(I)g(-)h(pointer)e(to)h(input)f(HDU) h(*/)143 3656 y(fitsfile)f(*outfptr,)93 b(/*)47 b(I)g(-)h(pointer)e(to) h(output)f(HDU)h(*/)143 3768 y(int)g(firstkey,)332 b(/*)47 b(I)g(-)h(first)e(HDU)h(record)f(number)g(to)h(start)g(with)f(*/)143 3881 y(char)h(*patterns[][2],/*)c(I)k(-)h(pointer)e(to)h(input)f(/)i (output)e(keyword)g(templates)f(*/)143 3994 y(int)i(npat,)524 b(/*)47 b(I)g(-)h(number)e(of)h(templates)e(passed)h(*/)143 4107 y(int)h(n_value,)380 b(/*)47 b(I)g(-)h(base)e('n')h(template)f (value)g(of)h(interest)f(*/)143 4220 y(int)h(n_offset,)332 b(/*)47 b(I)g(-)h(offset)e(to)h(be)g(applied)f(to)h(the)g('n')g(*/)1193 4333 y(/*)238 b(value)47 b(in)g(the)g(output)f(string)g(*/)143 4446 y(int)h(n_range,)380 b(/*)47 b(I)g(-)h(controls)d(range)i(of)g ('n')g(template)e(*/)1098 4559 y(/*)238 b(values)46 b(of)h(interest)f (\(-1,0,)g(or)h(+1\))g(*/)143 4672 y(int)g(*status\))380 b(/*)47 b(IO)g(-)h(error)e(status)g(*/)0 4924 y Fi(22)g Fj(P)m(arse)35 b(the)g(input)f(string)h(con)m(taining)h(a)f(list)h(of)f (ro)m(ws)f(or)h(ro)m(w)g(ranges,)h(and)e(return)g(in)m(teger)i(arra)m (ys)f(con-)227 5036 y(taining)27 b(the)f(\014rst)f(and)g(last)i(ro)m(w) f(in)f(eac)m(h)i(range.)40 b(F)-8 b(or)26 b(example,)i(if)d(ro)m(wlist) i(=)e("3-5,)k(6,)e(8-9")h(then)d(it)i(will)227 5149 y(return)34 b(n)m(umranges)h(=)g(3,)h(rangemin)f(=)g(3,)i(6,)g(8)e(and)g(rangemax)g (=)g(5,)i(6,)g(9.)55 b(A)m(t)36 b(most,)h('maxranges')227 5262 y(n)m(um)m(b)s(er)31 b(of)h(ranges)f(will)h(b)s(e)g(returned.)43 b('maxro)m(ws')32 b(is)g(the)g(maxim)m(um)g(n)m(um)m(b)s(er)e(of)i(ro)m (ws)g(in)f(the)h(table;)227 5375 y(an)m(y)e(ro)m(ws)f(or)g(ranges)g (larger)h(than)f(this)g(will)g(b)s(e)g(ignored.)40 b(The)29 b(ro)m(ws)g(m)m(ust)g(b)s(e)f(sp)s(eci\014ed)h(in)f(increasing)227 5488 y(order,)33 b(and)f(the)g(ranges)h(m)m(ust)f(not)g(o)m(v)m(erlap.) 48 b(A)33 b(min)m(us)e(sign)i(ma)m(y)g(b)s(e)e(use)h(to)h(sp)s(ecify)f (all)h(the)g(ro)m(ws)f(to)227 5601 y(the)h(upp)s(er)d(or)j(lo)m(w)m(er) h(b)s(ound,)d(so)i("50-")h(means)e(all)i(the)f(ro)m(ws)f(from)g(50)h (to)h(the)e(end)g(of)h(the)f(table,)j(and)227 5714 y("-")d(means)e(all) h(the)g(ro)m(ws)f(in)g(the)h(table,)g(from)f(1)h(-)g(maxro)m(ws.)p eop end %%Page: 75 83 TeXDict begin 75 82 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.75) cvn H.B /DEST pdfmark end 0 299 a Fh(5.8.)72 b(UTILITY)30 b(R)m(OUTINES)2693 b Fj(75)191 555 y Fe(int)47 b(fits_parse_range)c(/) 48 b(ffrwrg\(char)c(*rowlist,)i(LONGLONG)f(maxrows,)h(int)h(maxranges,) e(>)334 668 y(int)i(*numranges,)e(long)h(*rangemin,)f(long)i (*rangemax,)e(int)i(*status\))191 894 y(int)g(fits_parse_rangell)c(/)k (ffrwrgll\(char)d(*rowlist,)i(LONGLONG)f(maxrows,)h(int)h(maxranges,)e (>)334 1007 y(int)i(*numranges,)e(LONGLONG)g(*rangemin,)g(LONGLONG)h (*rangemax,)f(int)i(*status\))0 1267 y Fi(23)f Fj(Chec)m(k)37 b(that)g(the)g(Header)g(\014ll)g(b)m(ytes)g(\(if)g(an)m(y\))g(are)g (all)h(blank.)59 b(These)36 b(are)h(the)g(b)m(ytes)g(that)g(ma)m(y)h (follo)m(w)227 1380 y(END)e(k)m(eyw)m(ord)g(and)f(b)s(efore)g(the)h(b)s (eginning)f(of)h(data)g(unit,)g(or)g(the)g(end)f(of)g(the)h(HDU)g(if)g (there)f(is)h(no)227 1492 y(data)31 b(unit.)191 1752 y Fe(int)47 b(ffchfl\(fitsfile)c(*fptr,)k(>)g(int)g(*status\))0 2012 y Fi(24)f Fj(Chec)m(k)30 b(that)g(the)f(Data)i(\014ll)e(b)m(ytes)h (\(if)g(an)m(y\))g(are)g(all)g(zero)g(\(for)f(IMA)m(GE)i(or)e(BINAR)-8 b(Y)30 b(T)-8 b(able)30 b(HDU\))h(or)e(all)227 2125 y(blanks)g(\(for)g (ASCI)s(I)f(table)i(HDU\).)g(These)f(\014le)g(b)m(ytes)h(ma)m(y)f(b)s (e)g(lo)s(cated)h(after)g(the)f(last)h(v)-5 b(alid)29 b(data)h(b)m(yte)227 2238 y(in)g(the)h(HDU)g(and)f(b)s(efore)g(the)g (ph)m(ysical)h(end)f(of)h(the)f(HDU.)191 2498 y Fe(int)47 b(ffcdfl\(fitsfile)c(*fptr,)k(>)g(int)g(*status\))0 2757 y Fi(25)f Fj(Estimate)35 b(the)e(ro)s(ot-mean-squared)h(\(RMS\))f (noise)h(in)f(an)g(image.)51 b(These)33 b(routines)g(are)h(mainly)f (for)g(use)227 2870 y(with)25 b(the)g(Hcompress)g(image)i(compression)e (algorithm.)40 b(They)24 b(return)g(an)h(estimate)i(of)e(the)h(RMS)f (noise)227 2983 y(in)38 b(the)f(bac)m(kground)h(pixels)f(of)h(the)g (image.)64 b(This)36 b(robust)h(algorithm)i(\(written)f(b)m(y)f(Ric)m (hard)h(White,)227 3096 y(STScI\))e(\014rst)f(attempts)i(to)g(estimate) h(the)f(RMS)e(v)-5 b(alue)37 b(as)g(1.68)g(times)g(the)f(median)g(of)h (the)f(absolute)227 3209 y(di\013erences)26 b(b)s(et)m(w)m(een)h (successiv)m(e)g(pixels)f(in)g(the)g(image.)41 b(If)25 b(the)h(median)g(=)f(0,)j(then)d(the)h(algorithm)h(falls)227 3322 y(bac)m(k)h(to)f(computing)g(the)g(RMS)f(of)h(the)g(di\013erence)g (b)s(et)m(w)m(een)h(successiv)m(e)g(pixels,)f(after)h(sev)m(eral)g (N-sigma)227 3435 y(rejection)e(cycles)g(to)g(remo)m(v)m(e)g(extreme)g (v)-5 b(alues.)39 b(The)25 b(input)e(parameters)j(are:)38 b(the)25 b(arra)m(y)g(of)g(image)i(pixel)227 3548 y(v)-5 b(alues)30 b(\(either)h(\015oat)f(or)g(short)f(v)-5 b(alues\),)31 b(the)f(n)m(um)m(b)s(er)e(of)i(v)-5 b(alues)30 b(in)g(the)g(arra)m(y)-8 b(,)31 b(the)f(v)-5 b(alue)30 b(that)g(is)g(used)227 3661 y(to)h(represen)m(t)g(n)m(ull)f(pixels)h(\(en)m(ter)g(a)g(v)m(ery) g(large)g(n)m(um)m(b)s(er)e(if)h(there)h(are)g(no)f(n)m(ull)g (pixels\).)191 3920 y Fe(int)47 b(fits_rms_float)d(\(float)i(fdata[],)f (int)i(npix,)g(float)f(in_null_value,)907 4033 y(>)h(double)f(*rms,)h (int)g(*status\))191 4146 y(int)g(fits_rms_short)d(\(short)i(fdata[],)f (int)i(npix,)g(short)f(in_null_value,)907 4259 y(>)h(double)f(*rms,)h (int)g(*status\))0 4519 y Fi(26)f Fj(W)-8 b(as)33 b(CFITSIO)d(compiled) h(with)h(the)f(-D)p 1612 4519 28 4 v 34 w(REENTRANT)g(directiv)m(e)i (so)e(that)h(it)g(ma)m(y)h(b)s(e)d(safely)j(used)d(in)227 4632 y(m)m(ulti-threaded)d(en)m(vironmen)m(ts?)40 b(The)26 b(follo)m(wing)i(function)e(returns)f(1)i(if)f(y)m(es,)i(0)f(if)f(no.) 40 b(Note,)28 b(ho)m(w)m(ev)m(er,)227 4745 y(that)35 b(ev)m(en)g(if)g(the)f(-D)p 991 4745 V 34 w(REENTRANT)f(directiv)m(e)j (w)m(as)f(sp)s(eci\014ed,)g(this)f(do)s(es)g(not)h(guaran)m(tee)h(that) f(the)227 4858 y(CFITSIO)29 b(routines)h(are)h(thread-safe,)g(b)s (ecause)g(some)f(compilers)h(ma)m(y)g(not)g(supp)s(ort)d(this)j (feature.)0 5117 y Fe(int)47 b(fits_is_reentrant\(void\))p eop end %%Page: 76 84 TeXDict begin 76 83 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.76) cvn H.B /DEST pdfmark end 0 299 a Fj(76)1379 b Fh(CHAPTER)30 b(5.)71 b(BASIC)30 b(CFITSIO)f(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)p eop end %%Page: 77 85 TeXDict begin 77 84 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.77) cvn H.B /DEST pdfmark end 0 299 a 0 464 a SDict begin H.S end 0 464 a 0 464 a SDict begin 13.6 H.A end 0 464 a 0 464 a SDict begin [ /View [/XYZ H.V] /Dest (chapter.6) cvn H.B /DEST pdfmark end 0 464 a 761 x Fg(Chapter)65 b(6)0 1687 y Fm(The)77 b(CFITSIO)f(Iterator)i(F)-19 b(unction)0 2180 y Fj(The)41 b(\014ts)p 325 2180 28 4 v 33 w(iterate)p 614 2180 V 34 w(data)i(function)e(in)h(CFITSIO)e(pro)m(vides)i(a)g (unique)e(metho)s(d)i(of)g(executing)h(an)e(arbitrary)0 2293 y(user-supplied)35 b(`w)m(ork')i(function)f(that)h(op)s(erates)g (on)g(ro)m(ws)f(of)h(data)g(in)f(FITS)g(tables)h(or)f(on)h(pixels)f(in) h(FITS)0 2406 y(images.)i(Rather)24 b(than)e(explicitly)j(reading)e (and)g(writing)g(the)g(FITS)g(images)h(or)f(columns)g(of)g(data,)i(one) f(instead)0 2518 y(calls)36 b(the)g(CFITSIO)d(iterator)k(routine,)g (passing)e(to)h(it)g(the)f(name)g(of)h(the)f(user's)g(w)m(ork)g (function)g(that)h(is)f(to)0 2631 y(b)s(e)30 b(executed)h(along)g(with) f(a)h(list)g(of)f(all)h(the)f(table)i(columns)e(or)g(image)h(arra)m(ys) g(that)g(are)f(to)h(b)s(e)f(passed)g(to)h(the)0 2744 y(w)m(ork)37 b(function.)61 b(The)37 b(CFITSIO)e(iterator)k(function)e (then)g(do)s(es)g(all)h(the)f(w)m(ork)g(of)h(allo)s(cating)h(memory)e (for)0 2857 y(the)28 b(arra)m(ys,)h(reading)f(the)g(input)e(data)j (from)e(the)h(FITS)f(\014le,)h(passing)g(them)g(to)g(the)g(w)m(ork)g (function,)g(and)f(then)0 2970 y(writing)36 b(an)m(y)h(output)f(data)h (bac)m(k)h(to)f(the)f(FITS)g(\014le)g(after)h(the)g(w)m(ork)g(function) f(exits.)59 b(Because)38 b(it)f(is)g(often)0 3083 y(more)g(e\016cien)m (t)i(to)f(pro)s(cess)f(only)g(a)h(subset)f(of)g(the)g(total)i(table)g (ro)m(ws)e(at)h(one)f(time,)j(the)e(iterator)g(function)0 3196 y(can)31 b(determine)f(the)h(optim)m(um)f(amoun)m(t)h(of)f(data)h (to)g(pass)f(in)g(eac)m(h)i(iteration)f(and)f(rep)s(eatedly)h(call)g (the)g(w)m(ork)0 3309 y(function)f(un)m(til)h(the)f(en)m(tire)i(table)f (b)s(een)e(pro)s(cessed.)0 3469 y(F)-8 b(or)37 b(man)m(y)f (applications)h(this)e(single)i(CFITSIO)d(iterator)k(function)d(can)h (e\013ectiv)m(ely)j(replace)e(all)g(the)f(other)0 3582 y(CFITSIO)g(routines)i(for)f(reading)h(or)f(writing)h(data)g(in)f(FITS) g(images)i(or)e(tables.)64 b(Using)37 b(the)h(iterator)h(has)0 3695 y(sev)m(eral)32 b(imp)s(ortan)m(t)e(adv)-5 b(an)m(tages)32 b(o)m(v)m(er)g(the)f(traditional)g(metho)s(d)f(of)h(reading)f(and)g (writing)g(FITS)g(data)h(\014les:)136 3961 y Fc(\017)46 b Fj(It)33 b(cleanly)h(separates)g(the)f(data)h(I/O)f(from)f(the)h (routine)g(that)h(op)s(erates)f(on)g(the)g(data.)49 b(This)32 b(leads)h(to)227 4074 y(a)e(more)g(mo)s(dular)e(and)h(`ob)5 b(ject)31 b(orien)m(ted')h(programming)e(st)m(yle.)136 4268 y Fc(\017)46 b Fj(It)27 b(simpli\014es)f(the)h(application)h (program)f(b)m(y)f(eliminating)i(the)f(need)g(to)g(allo)s(cate)i (memory)e(for)f(the)h(data)227 4381 y(arra)m(ys)e(and)f(eliminates)i (most)e(of)h(the)f(calls)i(to)f(the)g(CFITSIO)d(routines)j(that)g (explicitly)h(read)e(and)g(write)227 4494 y(the)31 b(data.)136 4689 y Fc(\017)46 b Fj(It)32 b(ensures)e(that)i(the)g(data)g(are)g(pro) s(cessed)f(as)h(e\016cien)m(tly)h(as)e(p)s(ossible.)44 b(This)31 b(is)g(esp)s(ecially)i(imp)s(ortan)m(t)227 4801 y(when)44 b(pro)s(cessing)g(tabular)h(data)h(since)f(the)g (iterator)h(function)e(will)h(calculate)i(the)e(most)g(e\016cien)m(t) 227 4914 y(n)m(um)m(b)s(er)36 b(of)i(ro)m(ws)g(in)f(the)h(table)g(to)g (b)s(e)f(passed)g(at)i(one)e(time)i(to)f(the)g(user's)e(w)m(ork)i (function)f(on)h(eac)m(h)227 5027 y(iteration.)136 5222 y Fc(\017)46 b Fj(Mak)m(es)39 b(it)e(p)s(ossible)g(for)g(larger)h(pro)5 b(jects)37 b(to)h(dev)m(elop)g(a)g(library)e(of)i(w)m(ork)f(functions)f (that)i(all)g(ha)m(v)m(e)h(a)227 5335 y(uniform)29 b(calling)j (sequence)f(and)f(are)h(all)g(indep)s(enden)m(t)e(of)i(the)f(details)i (of)e(the)h(FITS)e(\014le)i(format.)0 5601 y(There)f(are)h(basically)h (2)g(steps)e(in)h(using)f(the)h(CFITSIO)e(iterator)j(function.)42 b(The)30 b(\014rst)g(step)h(is)g(to)g(design)g(the)0 5714 y(w)m(ork)26 b(function)f(itself)h(whic)m(h)f(m)m(ust)h(ha)m(v)m (e)g(a)g(prescrib)s(ed)e(set)i(of)g(input)f(parameters.)39 b(One)25 b(of)h(these)g(parameters)1905 5942 y(77)p eop end %%Page: 78 86 TeXDict begin 78 85 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.78) cvn H.B /DEST pdfmark end 0 299 a Fj(78)1455 b Fh(CHAPTER)30 b(6.)112 b(THE)30 b(CFITSIO)e(ITERA)-8 b(TOR)30 b(FUNCTION)0 555 y Fj(is)f(a)g(structure)g(con)m(taining)i(p)s(oin)m(ters)d(to)i (the)f(arra)m(ys)h(of)f(data;)h(the)f(w)m(ork)h(function)e(can)i(p)s (erform)d(an)m(y)i(desired)0 668 y(op)s(erations)k(on)h(these)f(arra)m (ys)h(and)e(do)s(es)h(not)g(need)g(to)h(w)m(orry)f(ab)s(out)g(ho)m(w)g (the)h(input)e(data)i(w)m(ere)f(read)g(from)0 781 y(the)e(\014le)f(or)g (ho)m(w)h(the)f(output)g(data)h(get)h(written)e(bac)m(k)h(to)h(the)e (\014le.)0 941 y(The)24 b(second)h(step)g(is)f(to)i(design)e(the)h (driv)m(er)g(routine)f(that)i(op)s(ens)e(all)h(the)g(necessary)g(FITS)f (\014les)h(and)f(initializes)0 1054 y(the)41 b(input)g(parameters)g(to) h(the)g(iterator)g(function.)73 b(The)41 b(driv)m(er)g(program)g(calls) h(the)g(CFITSIO)e(iterator)0 1167 y(function)30 b(whic)m(h)g(then)g (reads)g(the)h(data)g(and)f(passes)g(it)h(to)g(the)g(user's)e(w)m(ork)i (function.)0 1327 y(The)20 b(follo)m(wing)i(2)f(sections)g(describ)s(e) f(these)h(steps)g(in)f(more)g(detail.)39 b(There)20 b(are)h(also)g(sev) m(eral)h(example)f(programs)0 1440 y(included)30 b(with)g(the)g (CFITSIO)f(distribution)h(whic)m(h)g(illustrate)i(ho)m(w)e(to)h(use)f (the)h(iterator)g(function.)0 1593 y SDict begin H.S end 0 1593 a 0 1593 a SDict begin 13.6 H.A end 0 1593 a 0 1593 a SDict begin [ /View [/XYZ H.V] /Dest (section.6.1) cvn H.B /DEST pdfmark end 0 1593 a 196 x Ff(6.1)135 b(The)45 b(Iterator)h(W)-11 b(ork)45 b(F)-11 b(unction)0 2043 y Fj(The)42 b(user-supplied)f(iterator)j(w)m(ork)f(function)f(m)m(ust)g (ha)m(v)m(e)i(the)f(follo)m(wing)h(set)f(of)g(input)e(parameters)i (\(the)0 2156 y(function)30 b(can)h(b)s(e)e(giv)m(en)j(an)m(y)f (desired)e(name\):)95 2429 y Fe(int)47 b(user_fn\()f(long)h(totaln,)e (long)i(offset,)f(long)g(firstn,)g(long)h(nvalues,)716 2542 y(int)g(narrays,)e(iteratorCol)g(*data,)94 b(void)47 b(*userPointer)d(\))136 2815 y Fc(\017)i Fj(totaln)24 b({)f(the)f(total)j(n)m(um)m(b)s(er)c(of)h(table)i(ro)m(ws)e(or)g (image)i(pixels)f(that)g(will)f(b)s(e)g(passed)g(to)h(the)g(w)m(ork)f (function)227 2928 y(during)29 b(1)i(or)g(more)f(iterations.)136 3129 y Fc(\017)46 b Fj(o\013set)d({)f(the)h(o\013set)f(applied)g(to)h (the)f(\014rst)f(table)i(ro)m(w)f(or)g(image)h(pixel)f(to)h(b)s(e)e (passed)g(to)i(the)f(w)m(ork)227 3241 y(function.)55 b(In)34 b(other)i(w)m(ords,)g(this)f(is)g(the)g(n)m(um)m(b)s(er)f(of)h (ro)m(ws)h(or)f(pixels)g(that)h(are)f(skipp)s(ed)f(o)m(v)m(er)i(b)s (efore)227 3354 y(starting)30 b(the)g(iterations.)42 b(If)28 b(o\013set)j(=)e(0,)h(then)f(all)h(the)f(table)i(ro)m(ws)e(or)g (image)i(pixels)e(will)h(b)s(e)e(passed)h(to)227 3467 y(the)i(w)m(ork)f(function.)136 3668 y Fc(\017)46 b Fj(\014rstn)26 b({)i(the)f(n)m(um)m(b)s(er)f(of)i(the)f(\014rst)g(table)h(ro)m(w)f(or) g(image)i(pixel)e(\(starting)i(with)e(1\))h(that)f(is)h(b)s(eing)e (passed)227 3781 y(in)k(this)h(particular)f(call)i(to)f(the)g(w)m(ork)f (function.)136 3982 y Fc(\017)46 b Fj(n)m(v)-5 b(alues)35 b({)g(the)f(n)m(um)m(b)s(er)g(of)g(table)h(ro)m(ws)g(or)f(image)i (pixels)e(that)h(are)g(b)s(eing)f(passed)g(in)g(this)h(particular)227 4095 y(call)h(to)g(the)f(w)m(ork)f(function.)54 b(n)m(v)-5 b(alues)35 b(will)g(alw)m(a)m(ys)h(b)s(e)e(less)h(than)f(or)h(equal)g (to)h(totaln)g(and)e(will)h(ha)m(v)m(e)227 4208 y(the)f(same)f(v)-5 b(alue)34 b(on)f(eac)m(h)h(iteration,)i(except)e(p)s(ossibly)f(on)g (the)g(last)h(call)h(whic)m(h)e(ma)m(y)g(ha)m(v)m(e)i(a)e(smaller)227 4321 y(v)-5 b(alue.)136 4522 y Fc(\017)46 b Fj(narra)m(ys)31 b({)g(the)g(n)m(um)m(b)s(er)f(of)h(arra)m(ys)g(of)g(data)h(that)f(are)g (b)s(eing)g(passed)f(to)i(the)f(w)m(ork)g(function.)42 b(There)30 b(is)227 4635 y(one)h(arra)m(y)g(for)f(eac)m(h)i(image)f(or) f(table)i(column.)136 4835 y Fc(\017)46 b Fj(*data)31 b({)e(arra)m(y)h(of)f(structures,)g(one)h(for)f(eac)m(h)h(column)f(or)g (image.)42 b(Eac)m(h)29 b(structure)g(con)m(tains)h(a)g(p)s(oin)m(ter) 227 4948 y(to)h(the)g(arra)m(y)g(of)f(data)h(as)g(w)m(ell)g(as)g(other) g(descriptiv)m(e)g(parameters)g(ab)s(out)f(that)h(arra)m(y)-8 b(.)136 5149 y Fc(\017)46 b Fj(*userP)m(oin)m(ter)26 b({)g(a)f(user)f(supplied)g(p)s(oin)m(ter)h(that)h(can)f(b)s(e)f(used)h (to)g(pass)g(ancillary)h(information)f(from)g(the)227 5262 y(driv)m(er)h(function)g(to)g(the)g(w)m(ork)g(function.)39 b(This)25 b(p)s(oin)m(ter)h(is)g(passed)g(to)g(the)h(CFITSIO)d (iterator)j(function)227 5375 y(whic)m(h)37 b(then)f(passes)g(it)h(on)g (to)g(the)f(w)m(ork)h(function)f(without)h(an)m(y)g(mo)s(di\014cation.) 59 b(It)37 b(ma)m(y)g(p)s(oin)m(t)f(to)i(a)227 5488 y(single)29 b(n)m(um)m(b)s(er,)f(to)h(an)f(arra)m(y)h(of)g(v)-5 b(alues,)29 b(to)g(a)g(structure)f(con)m(taining)i(an)e(arbitrary)g(set)h(of)g (parameters)227 5601 y(of)e(di\013eren)m(t)h(t)m(yp)s(es,)g(or)f(it)h (ma)m(y)f(b)s(e)g(a)g(n)m(ull)g(p)s(oin)m(ter)g(if)g(it)h(is)f(not)g (needed.)40 b(The)26 b(w)m(ork)h(function)g(m)m(ust)g(cast)227 5714 y(this)k(p)s(oin)m(ter)f(to)h(the)g(appropriate)f(data)h(t)m(yp)s (e)g(b)s(efore)f(using)f(it)i(it.)p eop end %%Page: 79 87 TeXDict begin 79 86 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.79) cvn H.B /DEST pdfmark end 0 299 a Fh(6.1.)72 b(THE)30 b(ITERA)-8 b(TOR)30 b(W)m(ORK)g(FUNCTION)2021 b Fj(79)0 555 y(The)23 b(totaln,)k(o\013set,)g(narra)m(ys,)e(data,)h(and)d(userP)m(oin)m(ter)i (parameters)f(are)g(guaran)m(teed)h(to)g(ha)m(v)m(e)g(the)f(same)g(v)-5 b(alue)0 668 y(on)35 b(eac)m(h)i(iteration.)57 b(Only)34 b(\014rstn,)i(n)m(v)-5 b(alues,)37 b(and)d(the)i(arra)m(ys)f(of)h(data) g(p)s(oin)m(ted)f(to)h(b)m(y)f(the)h(data)g(structures)0 781 y(ma)m(y)31 b(c)m(hange)g(on)g(eac)m(h)g(iterativ)m(e)i(call)f(to)f (the)f(w)m(ork)h(function.)0 941 y(Note)43 b(that)g(the)f(iterator)h (treats)g(an)f(image)h(as)f(a)g(long)h(1-D)g(arra)m(y)f(of)h(pixels)f (regardless)g(of)g(it's)h(in)m(trinsic)0 1054 y(dimensionalit)m(y)-8 b(.)52 b(The)33 b(total)j(n)m(um)m(b)s(er)c(of)i(pixels)g(is)g(just)f (the)h(pro)s(duct)e(of)i(the)g(size)h(of)e(eac)m(h)i(dimension,)g(and)0 1167 y(the)e(order)g(of)g(the)g(pixels)g(is)g(the)g(same)g(as)g(the)h (order)e(that)h(they)h(are)f(stored)g(in)g(the)g(FITS)f(\014le.)48 b(If)33 b(the)g(w)m(ork)0 1280 y(function)27 b(needs)g(to)h(kno)m(w)f (the)h(n)m(um)m(b)s(er)e(and)h(size)h(of)g(the)f(image)i(dimensions)d (then)h(these)h(parameters)g(can)g(b)s(e)0 1393 y(passed)i(via)h(the)f (userP)m(oin)m(ter)i(structure.)0 1553 y(The)e(iteratorCol)i(structure) e(is)g(curren)m(tly)h(de\014ned)e(as)h(follo)m(ws:)0 1780 y Fe(typedef)46 b(struct)94 b(/*)47 b(structure)e(for)i(the)g (iterator)e(function)h(column)g(information)f(*/)0 1893 y({)143 2005 y(/*)i(structure)f(elements)f(required)h(as)h(input)f(to)h (fits_iterate_data:)c(*/)95 2231 y(fitsfile)j(*fptr;)332 b(/*)48 b(pointer)d(to)j(the)f(HDU)f(containing)f(the)i(column)f(or)i (image)e(*/)95 2344 y(int)286 b(colnum;)e(/*)48 b(column)e(number)g(in) h(the)g(table;)f(ignored)g(for)h(images)189 b(*/)95 2457 y(char)238 b(colname[70];)44 b(/*)k(name)e(\(TTYPEn\))g(of)h(the)g (column;)f(null)g(for)h(images)285 b(*/)95 2570 y(int)h(datatype;)188 b(/*)48 b(output)e(data)g(type)h(\(converted)e(if)i(necessary\))e(*/)95 2683 y(int)286 b(iotype;)e(/*)48 b(type:)e(InputCol,)f(InputOutputCol,) f(or)j(OutputCol)e(*/)95 2909 y(/*)j(output)e(structure)f(elements)h (that)g(may)h(be)g(useful)f(for)h(the)g(work)g(function:)e(*/)95 3135 y(void)238 b(*array;)189 b(/*)47 b(pointer)f(to)h(the)g(array)f (\(and)h(the)g(null)g(value\))f(*/)95 3247 y(long)238 b(repeat;)189 b(/*)47 b(binary)f(table)h(vector)f(repeat)g(value;)g (set)238 b(*/)1050 3360 y(/*)g(equal)46 b(to)i(1)f(for)g(images)810 b(*/)95 3473 y(long)238 b(tlmin;)f(/*)47 b(legal)g(minimum)e(data)i (value,)f(if)h(any)477 b(*/)95 3586 y(long)238 b(tlmax;)f(/*)47 b(legal)g(maximum)e(data)i(value,)f(if)h(any)477 b(*/)95 3699 y(char)238 b(unit[70];)93 b(/*)47 b(physical)f(unit)g(string)g (\(BUNIT)h(or)g(TUNITn\))189 b(*/)95 3812 y(char)238 b(tdisp[70];)45 b(/*)i(suggested)e(display)h(format;)g(null)h(if)g (none)190 b(*/)0 4038 y(})47 b(iteratorCol;)0 4264 y Fj(Instead)34 b(of)g(directly)g(reading)g(or)g(writing)g(the)f(elemen)m (ts)j(in)d(this)h(structure,)g(it)h(is)e(recommended)h(that)g(pro-)0 4377 y(grammers)c(use)g(the)h(access)h(functions)d(that)i(are)g(pro)m (vided)f(for)g(this)h(purp)s(ose.)0 4538 y(The)25 b(\014rst)g(\014v)m (e)h(elemen)m(ts)h(in)f(this)f(structure)h(m)m(ust)f(b)s(e)g(initially) j(de\014ned)c(b)m(y)i(the)g(driv)m(er)f(routine)h(b)s(efore)f(calling)0 4650 y(the)f(iterator)h(routine.)38 b(The)23 b(CFITSIO)f(iterator)j (routine)f(uses)f(this)g(information)h(to)g(determine)g(what)f(column)0 4763 y(or)32 b(arra)m(y)h(to)h(pass)e(to)h(the)g(w)m(ork)f(function,)h (and)f(whether)g(the)g(arra)m(y)h(is)g(to)g(b)s(e)f(input)g(to)h(the)f (w)m(ork)h(function,)0 4876 y(output)g(from)g(the)h(w)m(ork)f (function,)h(or)g(b)s(oth.)49 b(The)33 b(CFITSIO)f(iterator)i(function) f(\014lls)h(in)f(the)g(v)-5 b(alues)34 b(of)g(the)0 4989 y(remaining)c(structure)g(elemen)m(ts)i(b)s(efore)e(passing)g(it)h(to)g (the)g(w)m(ork)f(function.)0 5149 y(The)d(arra)m(y)g(structure)g (elemen)m(t)i(is)e(a)g(p)s(oin)m(ter)g(to)h(the)g(actual)g(data)g(arra) m(y)g(and)e(it)i(m)m(ust)f(b)s(e)f(cast)j(to)e(the)h(correct)0 5262 y(data)k(t)m(yp)s(e)f(b)s(efore)f(it)i(is)f(used.)41 b(The)31 b(`rep)s(eat')g(structure)g(elemen)m(t)h(giv)m(e)g(the)g(n)m (um)m(b)s(er)d(of)i(data)h(v)-5 b(alues)31 b(in)g(eac)m(h)0 5375 y(ro)m(w)f(of)g(the)g(table,)i(so)e(that)h(the)f(total)i(n)m(um)m (b)s(er)c(of)i(data)h(v)-5 b(alues)30 b(in)g(the)g(arra)m(y)h(is)f(giv) m(en)h(b)m(y)f(rep)s(eat)g(*)g(n)m(v)-5 b(alues.)0 5488 y(In)36 b(the)g(case)i(of)e(image)i(arra)m(ys)f(and)e(ASCI)s(I)g (tables,)k(rep)s(eat)e(will)g(alw)m(a)m(ys)g(b)s(e)f(equal)h(to)g(1.)59 b(When)37 b(the)f(data)0 5601 y(t)m(yp)s(e)k(is)f(a)h(c)m(haracter)h (string,)h(the)e(arra)m(y)g(p)s(oin)m(ter)f(is)h(actually)h(a)f(p)s (oin)m(ter)f(to)i(an)e(arra)m(y)h(of)g(string)f(p)s(oin)m(ters)0 5714 y(\(i.e.,)31 b(c)m(har)e(**arra)m(y\).)42 b(The)29 b(other)g(output)g(structure)f(elemen)m(ts)j(are)e(pro)m(vided)g(for)f (con)m(v)m(enience)k(in)c(case)i(that)p eop end %%Page: 80 88 TeXDict begin 80 87 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.80) cvn H.B /DEST pdfmark end 0 299 a Fj(80)1455 b Fh(CHAPTER)30 b(6.)112 b(THE)30 b(CFITSIO)e(ITERA)-8 b(TOR)30 b(FUNCTION)0 555 y Fj(information)36 b(is)g(needed)f(within)g(the)h(w)m(ork)g (function.)56 b(An)m(y)35 b(other)h(information)g(ma)m(y)g(b)s(e)f (passed)h(from)f(the)0 668 y(driv)m(er)30 b(routine)h(to)g(the)f(w)m (ork)h(function)f(via)h(the)f(userP)m(oin)m(ter)h(parameter.)0 828 y(Up)s(on)g(completion,)j(the)e(w)m(ork)h(routine)f(m)m(ust)g (return)f(an)h(in)m(teger)h(status)f(v)-5 b(alue,)34 b(with)d(0)i(indicating)g(success)0 941 y(and)e(an)m(y)g(other)g(v)-5 b(alue)32 b(indicating)g(an)f(error)g(whic)m(h)g(will)g(cause)h(the)f (iterator)i(function)e(to)h(immediately)g(exit)0 1054 y(at)27 b(that)f(p)s(oin)m(t.)39 b(Return)25 b(status)i(v)-5 b(alues)26 b(in)f(the)h(range)h(1)f({)g(1000)i(should)c(b)s(e)i(a)m(v)m (oided)h(since)f(these)h(are)f(reserv)m(ed)0 1167 y(for)d(use)g(b)m(y)h (CFITSIO.)e(A)i(return)e(status)i(v)-5 b(alue)24 b(of)g(-1)g(ma)m(y)g (b)s(e)f(used)f(to)j(force)f(the)f(CFITSIO)f(iterator)j(function)0 1280 y(to)i(stop)g(at)g(that)h(p)s(oin)m(t)e(and)g(return)g(con)m(trol) i(to)f(the)g(driv)m(er)f(routine)h(after)g(writing)f(an)m(y)h(output)f (arra)m(ys)h(to)h(the)0 1393 y(FITS)e(\014le.)40 b(CFITSIO)26 b(do)s(es)g(not)i(considered)f(this)g(to)h(b)s(e)e(an)h(error)g (condition,)i(so)e(an)m(y)g(further)f(pro)s(cessing)h(b)m(y)0 1506 y(the)k(application)g(program)f(will)h(con)m(tin)m(ue)h(normally) -8 b(.)0 1658 y SDict begin H.S end 0 1658 a 0 1658 a SDict begin 13.6 H.A end 0 1658 a 0 1658 a SDict begin [ /View [/XYZ H.V] /Dest (section.6.2) cvn H.B /DEST pdfmark end 0 1658 a 179 x Ff(6.2)135 b(The)45 b(Iterator)h(Driv)l(er)g(F)-11 b(unction)0 2087 y Fj(The)33 b(iterator)h(driv)m(er)f(function)g(m)m (ust)h(op)s(en)e(the)i(necessary)f(FITS)g(\014les)g(and)g(p)s(osition)g (them)g(to)h(the)g(correct)0 2200 y(HDU.)23 b(It)f(m)m(ust)g(also)i (initialize)g(the)e(follo)m(wing)i(parameters)e(in)g(the)h(iteratorCol) h(structure)d(\(de\014ned)g(ab)s(o)m(v)m(e\))j(for)0 2313 y(eac)m(h)31 b(column)f(or)g(image)h(b)s(efore)e(calling)j(the)e (CFITSIO)e(iterator)j(function.)40 b(Sev)m(eral)31 b(`constructor')g (routines)0 2426 y(are)g(pro)m(vided)f(in)g(CFITSIO)f(for)h(this)g (purp)s(ose.)136 2670 y Fc(\017)46 b Fj(*fptr)30 b({)h(The)f (\014ts\014le)g(p)s(oin)m(ter)g(to)i(the)e(table)h(or)g(image.)136 2853 y Fc(\017)46 b Fj(coln)m(um)30 b({)f(the)h(n)m(um)m(b)s(er)e(of)h (the)h(column)f(in)g(the)g(table.)42 b(This)28 b(v)-5 b(alue)30 b(is)f(ignored)g(in)g(the)h(case)g(of)g(images.)227 2966 y(If)j(coln)m(um)h(equals)g(0,)g(then)g(the)f(column)g(name)h (will)f(b)s(e)g(used)g(to)h(iden)m(tify)g(the)f(column)h(to)g(b)s(e)e (passed)227 3079 y(to)f(the)g(w)m(ork)f(function.)136 3261 y Fc(\017)46 b Fj(colname)32 b({)e(the)g(name)h(\(TTYPEn)e(k)m (eyw)m(ord\))i(of)f(the)h(column.)40 b(This)29 b(is)i(only)f(required)f (if)h(coln)m(um)h(=)f(0)227 3374 y(and)g(is)g(ignored)h(for)f(images.) 136 3556 y Fc(\017)46 b Fj(datat)m(yp)s(e)29 b({)g(The)e(desired)h (data)g(t)m(yp)s(e)g(of)h(the)f(arra)m(y)g(to)h(b)s(e)e(passed)h(to)h (the)f(w)m(ork)g(function.)40 b(F)-8 b(or)28 b(n)m(umer-)227 3669 y(ical)h(data)f(the)f(data)h(t)m(yp)s(e)g(do)s(es)f(not)g(need)g (to)h(b)s(e)f(the)g(same)h(as)f(the)h(actual)g(data)g(t)m(yp)s(e)g(in)f (the)g(FITS)g(\014le,)227 3782 y(in)h(whic)m(h)h(case)g(CFITSIO)e(will) i(do)g(the)f(con)m(v)m(ersion.)42 b(Allo)m(w)m(ed)30 b(v)-5 b(alues)29 b(are:)40 b(TSTRING,)28 b(TLOGICAL,)227 3895 y(TBYTE,)37 b(TSBYTE,)f(TSHOR)-8 b(T,)36 b(TUSHOR)-8 b(T,)37 b(TINT,)f(TLONG,)h(TULONG,)f(TFLO)m(A)-8 b(T,)38 b(TDOU-)227 4008 y(BLE.)33 b(If)g(the)g(input)f(v)-5 b(alue)33 b(of)g(data)h(t)m(yp)s(e)f(equals)g(0,)i(then)d(the)h (existing)h(data)g(t)m(yp)s(e)f(of)g(the)g(column)g(or)227 4121 y(image)f(will)f(b)s(e)e(used)h(without)g(an)m(y)h(con)m(v)m (ersion.)136 4303 y Fc(\017)46 b Fj(iot)m(yp)s(e)37 b({)f(de\014nes)e (whether)h(the)h(data)g(arra)m(y)g(is)g(to)g(b)s(e)f(input)g(to)h(the)g (w)m(ork)f(function)h(\(i.e,)i(read)d(from)227 4416 y(the)42 b(FITS)e(\014le\),)k(or)d(output)g(from)g(the)g(w)m(ork)g(function)g (\(i.e.,)k(written)c(to)h(the)f(FITS)g(\014le\))g(or)g(b)s(oth.)227 4529 y(Allo)m(w)m(ed)30 b(v)-5 b(alues)29 b(are)f(InputCol,)g (OutputCol,)h(or)f(InputOutputCol.)38 b(V)-8 b(ariable-length)30 b(arra)m(y)f(columns)227 4642 y(are)h(supp)s(orted)e(as)i(InputCol)e (or)i(InputOutputCol)d(t)m(yp)s(es,)j(but)f(ma)m(y)h(not)g(b)s(e)e (used)h(for)g(an)h(OutputCol)227 4755 y(t)m(yp)s(e.)0 4999 y(After)h(the)f(driv)m(er)g(routine)g(has)g(initialized)j(all)e (these)f(parameters,)h(it)g(can)g(then)f(call)h(the)g(CFITSIO)e (iterator)0 5112 y(function:)95 5357 y Fe(int)47 b (fits_iterate_data\(int)42 b(narrays,)k(iteratorCol)f(*data,)h(long)g (offset,)286 5470 y(long)h(nPerLoop,)e(int)i(\(*workFn\)\()e(\),)i (void)g(*userPointer,)d(int)j(*status\);)136 5714 y Fc(\017)f Fj(narra)m(ys)31 b({)f(the)h(n)m(um)m(b)s(er)e(of)h(columns)g(or)h (images)g(that)g(are)g(to)g(b)s(e)f(passed)g(to)h(the)f(w)m(ork)h (function.)p eop end %%Page: 81 89 TeXDict begin 81 88 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.81) cvn H.B /DEST pdfmark end 0 299 a Fh(6.3.)72 b(GUIDELINES)30 b(F)m(OR)h(USING)f(THE)g(ITERA)-8 b(TOR)30 b(FUNCTION)1200 b Fj(81)136 555 y Fc(\017)46 b Fj(*data)32 b({)f(p)s(oin)m(ter)f(to)h (arra)m(y)g(of)f(structures)g(con)m(taining)i(information)f(ab)s(out)f (eac)m(h)h(column)g(or)f(image.)136 736 y Fc(\017)46 b Fj(o\013set)31 b({)f(if)f(p)s(ositiv)m(e,)i(this)f(n)m(um)m(b)s(er)e (of)i(ro)m(ws)f(at)h(the)g(b)s(eginning)f(of)h(the)f(table)i(\(or)f (pixels)f(in)h(the)f(image\))227 849 y(will)i(b)s(e)f(skipp)s(ed)f(and) g(will)i(not)g(b)s(e)e(passed)h(to)h(the)g(w)m(ork)f(function.)136 1030 y Fc(\017)46 b Fj(nP)m(erLo)s(op)38 b(-)h(sp)s(eci\014es)e(the)i (n)m(um)m(b)s(er)e(of)h(table)h(ro)m(ws)g(\(or)f(n)m(um)m(b)s(er)f(of)i (image)g(pixels\))g(that)g(are)g(to)g(b)s(e)227 1143 y(passed)29 b(to)h(the)f(w)m(ork)h(function)e(on)h(eac)m(h)i (iteration.)42 b(If)28 b(nP)m(erLo)s(op)h(=)g(0)g(then)g(CFITSIO)f (will)i(calculate)227 1256 y(the)22 b(optim)m(um)g(n)m(um)m(b)s(er)e (for)h(greatest)j(e\016ciency)-8 b(.)39 b(If)21 b(nP)m(erLo)s(op)g(is)h (negativ)m(e,)k(then)21 b(all)i(the)f(ro)m(ws)f(or)h(pixels)227 1368 y(will)36 b(b)s(e)f(passed)g(at)h(one)g(time,)i(and)c(the)i(w)m (ork)g(function)f(will)h(only)f(b)s(e)g(called)i(once.)56 b(If)35 b(an)m(y)h(v)-5 b(ariable)227 1481 y(length)33 b(arra)m(ys)g(are)g(b)s(eing)f(pro)s(cessed,)h(then)g(the)f(nP)m(erLo)s (op)h(v)-5 b(alue)33 b(is)f(ignored,)i(and)e(the)h(iterator)h(will)227 1594 y(alw)m(a)m(ys)e(pro)s(cess)e(one)h(ro)m(w)f(of)h(the)f(table)i (at)f(a)g(time.)136 1775 y Fc(\017)46 b Fj(*w)m(orkFn)f(-)f(the)h(name) f(\(actually)i(the)f(address\))f(of)g(the)g(w)m(ork)h(function)f(that)h (is)f(to)h(b)s(e)f(called)h(b)m(y)227 1888 y(\014ts)p 354 1888 28 4 v 33 w(iterate)p 643 1888 V 34 w(data.)136 2069 y Fc(\017)h Fj(*userP)m(oin)m(ter)34 b(-)f(this)g(is)g(a)g(user)f (supplied)g(p)s(oin)m(ter)h(that)g(can)g(b)s(e)g(used)f(to)h(pass)g (ancillary)h(information)227 2182 y(from)f(the)g(driv)m(er)g(routine)g (to)h(the)f(w)m(ork)g(function.)48 b(It)33 b(ma)m(y)h(p)s(oin)m(t)f(to) h(a)f(single)h(n)m(um)m(b)s(er,)e(an)h(arra)m(y)-8 b(,)35 b(or)227 2295 y(to)c(a)g(structure)f(con)m(taining)i(an)e(arbitrary)g (set)h(of)g(parameters.)136 2476 y Fc(\017)46 b Fj(*status)30 b(-)f(The)f(CFITSIO)f(error)h(status.)41 b(Should)27 b(=)h(0)h(on)g(input;)f(a)h(non-zero)h(output)e(v)-5 b(alue)29 b(indicates)227 2588 y(an)i(error.)0 2828 y(When)f(\014ts)p 392 2828 V 32 w(iterate)p 680 2828 V 35 w(data)h(is)f(called)h(it)f (\014rst)g(allo)s(cates)i(memory)e(to)h(hold)e(all)i(the)f(requested)g (columns)g(of)g(data)0 2941 y(or)f(image)i(pixel)e(arra)m(ys.)41 b(It)29 b(then)g(reads)g(the)h(input)e(data)i(from)f(the)g(FITS)f (tables)i(or)g(images)g(in)m(to)g(the)g(arra)m(ys)0 3054 y(then)h(passes)h(the)g(structure)f(with)g(p)s(oin)m(ters)h(to)g(these) g(data)h(arra)m(ys)f(to)g(the)g(w)m(ork)g(function.)44 b(After)32 b(the)g(w)m(ork)0 3167 y(function)37 b(returns,)g(the)h (iterator)g(function)f(writes)g(an)m(y)g(output)g(columns)f(of)h(data)h (or)f(images)h(bac)m(k)g(to)g(the)0 3279 y(FITS)31 b(\014les.)46 b(It)32 b(then)g(rep)s(eats)g(this)g(pro)s(cess)g(for)f(an)m(y)i (remaining)f(sets)g(of)h(ro)m(ws)f(or)g(image)h(pixels)f(un)m(til)h(it) f(has)0 3392 y(pro)s(cessed)27 b(the)i(en)m(tire)g(table)f(or)g(image)i (or)e(un)m(til)g(the)g(w)m(ork)g(function)g(returns)f(a)h(non-zero)h (status)f(v)-5 b(alue.)40 b(The)0 3505 y(iterator)33 b(then)f(frees)g(the)h(memory)e(that)i(it)g(initially)g(allo)s(cated)h (and)e(returns)f(con)m(trol)i(to)g(the)f(driv)m(er)g(routine)0 3618 y(that)f(called)h(it.)0 3752 y SDict begin H.S end 0 3752 a 0 3752 a SDict begin 13.6 H.A end 0 3752 a 0 3752 a SDict begin [ /View [/XYZ H.V] /Dest (section.6.3) cvn H.B /DEST pdfmark end 0 3752 a 197 x Ff(6.3)135 b(Guidelines)46 b(for)f(Using)h(the)f(Iterator)h(F)-11 b(unction)0 4199 y Fj(The)34 b(totaln,)i(o\013set,)h(\014rstn,)d(and)f(n)m(v)-5 b(alues)35 b(parameters)f(that)h(are)f(passed)g(to)h(the)f(w)m(ork)g (function)g(are)h(useful)0 4312 y(for)f(determining)g(ho)m(w)g(m)m(uc)m (h)g(of)h(the)f(data)h(has)f(b)s(een)f(pro)s(cessed)h(and)f(ho)m(w)h(m) m(uc)m(h)g(remains)g(left)h(to)g(do.)52 b(On)0 4425 y(the)36 b(v)m(ery)h(\014rst)f(call)h(to)g(the)f(w)m(ork)h(function)f(\014rstn)f (will)h(b)s(e)g(equal)h(to)g(o\013set)g(+)f(1;)k(the)c(w)m(ork)g (function)g(ma)m(y)0 4538 y(need)31 b(to)g(p)s(erform)f(v)-5 b(arious)31 b(initialization)i(tasks)f(b)s(efore)e(starting)i(to)f(pro) s(cess)g(the)g(data.)43 b(Similarly)-8 b(,)32 b(\014rstn)d(+)0 4650 y(n)m(v)-5 b(alues)29 b(-)f(1)h(will)f(b)s(e)g(equal)g(to)h (totaln)h(on)e(the)g(last)h(iteration,)i(at)e(whic)m(h)f(p)s(oin)m(t)g (the)g(w)m(ork)h(function)e(ma)m(y)i(need)0 4763 y(to)k(p)s(erform)f (some)h(clean)h(up)d(op)s(erations)i(b)s(efore)g(exiting)h(for)e(the)h (last)h(time.)48 b(The)33 b(w)m(ork)f(function)h(can)g(also)0 4876 y(force)e(an)f(early)h(termination)g(of)g(the)g(iterations)g(b)m (y)g(returning)e(a)i(status)g(v)-5 b(alue)30 b(=)g(-1.)0 5036 y(The)f(narra)m(ys)g(and)g(iteratorCol.datat)m(yp)s(e)j(argumen)m (ts)e(allo)m(w)g(the)g(w)m(ork)f(function)g(to)h(double)f(c)m(hec)m(k)i (that)f(the)0 5149 y(n)m(um)m(b)s(er)k(of)i(input)f(arra)m(ys)h(and)f (their)g(data)i(t)m(yp)s(es)e(ha)m(v)m(e)i(the)f(exp)s(ected)g(v)-5 b(alues.)57 b(The)35 b(iteratorCol.fptr)i(and)0 5262 y(iteratorCol.coln)m(um)d(structure)d(elemen)m(ts)h(can)g(b)s(e)f(used) f(if)i(the)f(w)m(ork)h(function)f(needs)g(to)h(read)f(or)g(write)h(the) 0 5375 y(v)-5 b(alues)31 b(of)g(other)g(k)m(eyw)m(ords)g(in)g(the)g (FITS)f(\014le)h(asso)s(ciated)h(with)f(the)g(arra)m(y)-8 b(.)43 b(This)30 b(should)g(generally)i(only)f(b)s(e)0 5488 y(done)j(during)e(the)i(initialization)j(step)c(or)h(during)f(the) h(clean)g(up)f(step)h(after)g(the)g(last)h(set)f(of)g(data)g(has)g(b)s (een)0 5601 y(pro)s(cessed.)40 b(Extra)29 b(FITS)f(\014le)h(I/O)g (during)e(the)i(main)g(pro)s(cessing)g(lo)s(op)g(of)g(the)g(w)m(ork)g (function)g(can)g(seriously)0 5714 y(degrade)i(the)f(sp)s(eed)g(of)g (the)h(program.)p eop end %%Page: 82 90 TeXDict begin 82 89 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.82) cvn H.B /DEST pdfmark end 0 299 a Fj(82)1455 b Fh(CHAPTER)30 b(6.)112 b(THE)30 b(CFITSIO)e(ITERA)-8 b(TOR)30 b(FUNCTION)0 555 y Fj(If)i(v)-5 b(ariable-length)35 b(arra)m(y)e(columns)g(are)g(b)s (eing)f(pro)s(cessed,)h(then)g(the)g(iterator)h(will)f(op)s(erate)h(on) f(one)g(ro)m(w)g(of)0 668 y(the)j(table)g(at)g(a)g(time.)57 b(In)34 b(this)i(case)g(the)g(the)f(rep)s(eat)h(elemen)m(t)h(in)e(the)h (in)m(teratorCol)h(structure)e(will)h(b)s(e)e(set)0 781 y(equal)d(to)g(the)g(n)m(um)m(b)s(er)e(of)h(elemen)m(ts)i(in)e(the)h (curren)m(t)f(ro)m(w)g(that)h(is)g(b)s(eing)f(pro)s(cessed.)0 941 y(One)j(imp)s(ortan)m(t)g(feature)h(of)f(the)h(iterator)h(is)e (that)h(the)f(\014rst)g(elemen)m(t)i(in)e(eac)m(h)h(arra)m(y)g(that)g (is)f(passed)g(to)h(the)0 1054 y(w)m(ork)f(function)g(giv)m(es)h(the)f (v)-5 b(alue)33 b(that)h(is)f(used)f(to)h(represen)m(t)g(n)m(ull)g(or)g (unde\014ned)d(v)-5 b(alues)34 b(in)e(the)h(arra)m(y)-8 b(.)49 b(The)0 1167 y(real)41 b(data)g(then)g(b)s(egins)f(with)g(the)g (second)h(elemen)m(t)h(of)f(the)f(arra)m(y)h(\(i.e.,)k(arra)m(y[1],)g (not)c(arra)m(y[0]\).)73 b(If)40 b(the)0 1280 y(\014rst)e(arra)m(y)h (elemen)m(t)h(is)f(equal)g(to)g(zero,)j(then)c(this)g(indicates)i(that) f(all)h(the)e(arra)m(y)h(elemen)m(ts)h(ha)m(v)m(e)g(de\014ned)0 1393 y(v)-5 b(alues)33 b(and)f(there)h(are)g(no)g(unde\014ned)d(v)-5 b(alues.)48 b(If)33 b(arra)m(y[0])h(is)f(not)g(equal)g(to)g(zero,)i (then)d(this)h(indicates)g(that)0 1506 y(some)h(of)g(the)g(data)h(v)-5 b(alues)34 b(are)g(unde\014ned)d(and)j(this)f(v)-5 b(alue)35 b(\(arra)m(y[0]\))h(is)d(used)g(to)i(represen)m(t)f(them.)51 b(In)33 b(the)0 1619 y(case)i(of)e(output)g(arra)m(ys)h(\(i.e.,)i (those)e(arra)m(ys)g(that)g(will)g(b)s(e)f(written)g(bac)m(k)h(to)h (the)e(FITS)g(\014le)g(b)m(y)h(the)g(iterator)0 1732 y(function)h(after)i(the)f(w)m(ork)f(function)h(exits\))h(the)f(w)m (ork)g(function)f(m)m(ust)h(set)g(the)g(\014rst)f(arra)m(y)h(elemen)m (t)h(to)g(the)0 1844 y(desired)g(n)m(ull)g(v)-5 b(alue)37 b(if)g(necessary)-8 b(,)40 b(otherwise)e(the)f(\014rst)g(elemen)m(t)h (should)e(b)s(e)h(set)g(to)h(zero)g(to)g(indicate)g(that)0 1957 y(there)30 b(are)h(no)e(n)m(ull)h(v)-5 b(alues)31 b(in)e(the)h(output)g(arra)m(y)-8 b(.)42 b(CFITSIO)28 b(de\014nes)h(2)h(v)-5 b(alues,)31 b(FLO)m(A)-8 b(TNULL)e(V)g(ALUE)31 b(and)0 2070 y(DOUBLENULL)-10 b(V)g(ALUE,)37 b(that)f(can)h(b)s(e)e (used)g(as)i(default)f(n)m(ull)g(v)-5 b(alues)36 b(for)g(\015oat)h(and) e(double)h(data)h(t)m(yp)s(es,)0 2183 y(resp)s(ectiv)m(ely)-8 b(.)60 b(In)35 b(the)i(case)g(of)f(c)m(haracter)i(string)e(data)h(t)m (yp)s(es,)h(a)e(n)m(ull)h(string)f(is)g(alw)m(a)m(ys)i(used)d(to)i (represen)m(t)0 2296 y(unde\014ned)28 b(strings.)0 2456 y(In)33 b(some)h(applications)g(it)g(ma)m(y)g(b)s(e)f(necessary)h(to)g (recursiv)m(ely)g(call)h(the)f(iterator)h(function.)50 b(An)33 b(example)h(of)0 2569 y(this)27 b(is)g(giv)m(en)h(b)m(y)f(one)h (of)f(the)h(example)f(programs)g(that)h(is)f(distributed)f(with)h (CFITSIO:)f(it)i(\014rst)e(calls)i(a)g(w)m(ork)0 2682 y(function)38 b(that)g(writes)h(out)f(a)g(2D)h(histogram)g(image.)65 b(That)38 b(w)m(ork)g(function)g(in)f(turn)g(calls)j(another)e(w)m(ork) 0 2795 y(function)29 b(that)h(reads)g(the)f(`X')i(and)e(`Y')h(columns)f (in)g(a)h(table)h(to)f(calculate)i(the)d(v)-5 b(alue)31 b(of)e(eac)m(h)i(2D)f(histogram)0 2908 y(image)i(pixel.)41 b(Graphically)-8 b(,)32 b(the)e(program)g(structure)g(can)h(b)s(e)f (describ)s(ed)f(as:)48 3153 y Fe(driver)46 b(-->)h(iterator)e(-->)i (work1_fn)f(-->)h(iterator)e(-->)i(work2_fn)0 3399 y Fj(Finally)-8 b(,)42 b(it)d(should)e(b)s(e)h(noted)g(that)h(the)g (table)g(columns)f(or)g(image)i(arra)m(ys)f(that)g(are)f(passed)g(to)h (the)g(w)m(ork)0 3512 y(function)c(do)h(not)g(all)g(ha)m(v)m(e)h(to)f (come)h(from)e(the)h(same)g(FITS)f(\014le)g(and)g(instead)h(ma)m(y)g (come)h(from)e(an)m(y)h(com-)0 3625 y(bination)d(of)g(sources)g(as)h (long)f(as)h(they)f(ha)m(v)m(e)h(the)f(same)h(length.)49 b(The)32 b(length)i(of)f(the)g(\014rst)f(table)i(column)f(or)0 3738 y(image)f(arra)m(y)f(is)f(used)f(b)m(y)i(the)f(iterator)i(if)e (they)h(do)f(not)h(all)g(ha)m(v)m(e)h(the)e(same)h(length.)0 3890 y SDict begin H.S end 0 3890 a 0 3890 a SDict begin 13.6 H.A end 0 3890 a 0 3890 a SDict begin [ /View [/XYZ H.V] /Dest (section.6.4) cvn H.B /DEST pdfmark end 0 3890 a 179 x Ff(6.4)135 b(Complete)47 b(List)e(of)g(Iterator)i(Routines)0 4319 y Fj(All)36 b(of)f(the)g(iterator)h(routines)f(are)g(listed)h(b)s (elo)m(w.)54 b(Most)36 b(of)f(these)h(routines)e(do)h(not)g(ha)m(v)m(e) i(a)e(corresp)s(onding)0 4432 y(short)30 b(function)g(name.)0 4678 y Fi(1)81 b Fj(Iterator)32 b(`constructor')h(functions)e(that)i (set)f(the)g(v)-5 b(alue)32 b(of)g(elemen)m(ts)h(in)f(the)g (iteratorCol)h(structure)e(that)227 4791 y(de\014ne)k(the)h(columns)f (or)h(arra)m(ys.)56 b(These)36 b(set)g(the)g(\014ts\014le)f(p)s(oin)m (ter,)i(column)e(name,)j(column)d(n)m(um)m(b)s(er,)227 4904 y(datat)m(yp)s(e,)28 b(and)e(iot)m(yp)s(e,)i(resp)s(ectiv)m(ely)-8 b(.)41 b(The)25 b(last)i(2)g(routines)f(allo)m(w)h(all)g(the)f (parameters)h(to)f(b)s(e)g(set)g(with)227 5017 y(one)31 b(function)f(call)i(\(one)f(supplies)e(the)i(column)f(name,)h(the)f (other)h(the)f(column)g(n)m(um)m(b)s(er\).)95 5262 y Fe(int)47 b(fits_iter_set_file\(iterato)o(rCo)o(l)42 b(*col,)k(fitsfile)g(*fptr\);)95 5488 y(int)h (fits_iter_set_colname\(iter)o(ato)o(rCol)41 b(*col,)46 b(char)h(*colname\);)95 5714 y(int)g(fits_iter_set_colnum\(itera)o(tor) o(Col)41 b(*col,)47 b(int)g(colnum\);)p eop end %%Page: 83 91 TeXDict begin 83 90 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.83) cvn H.B /DEST pdfmark end 0 299 a Fh(6.4.)72 b(COMPLETE)29 b(LIST)g(OF)i(ITERA)-8 b(TOR)29 b(R)m(OUTINES)1638 b Fj(83)95 668 y Fe(int)47 b(fits_iter_set_datatype\(ite)o(rat)o(orCo)o (l)42 b(*col,)k(int)h(datatype\);)95 894 y(int)g (fits_iter_set_iotype\(itera)o(tor)o(Col)41 b(*col,)47 b(int)g(iotype\);)95 1120 y(int)g(fits_iter_set_by_name\(iter)o(ato)o (rCol)41 b(*col,)46 b(fitsfile)g(*fptr,)477 1233 y(char)h(*colname,)e (int)i(datatype,)93 b(int)47 b(iotype\);)95 1458 y(int)g (fits_iter_set_by_num\(itera)o(tor)o(Col)41 b(*col,)47 b(fitsfile)e(*fptr,)477 1571 y(int)i(colnum,)f(int)h(datatype,)93 b(int)47 b(iotype\);)0 1820 y Fi(2)81 b Fj(Iterator)38 b(`accessor')h(functions)e(that)g(return)g(the)g(v)-5 b(alue)38 b(of)f(the)g(elemen)m(t)i(in)e(the)g(iteratorCol)i(structure) 227 1933 y(that)31 b(describ)s(es)f(a)h(particular)f(data)h(column)g (or)f(arra)m(y)95 2181 y Fe(fitsfile)46 b(*)h (fits_iter_get_file\(iterato)o(rCol)41 b(*col\);)95 2407 y(char)47 b(*)h(fits_iter_get_colname\(i)o(ter)o(ator)o(Col)41 b(*col\);)95 2633 y(int)47 b(fits_iter_get_colnum\(itera)o(tor)o(Col)41 b(*col\);)95 2858 y(int)47 b(fits_iter_get_datatype\(ite)o(rat)o(orCo)o (l)42 b(*col\);)95 3084 y(int)47 b(fits_iter_get_iotype\(itera)o(tor)o (Col)41 b(*col\);)95 3310 y(void)47 b(*)h(fits_iter_get_array\(ite)o (rat)o(orCo)o(l)42 b(*col\);)95 3536 y(long)47 b (fits_iter_get_tlmin\(itera)o(tor)o(Col)41 b(*col\);)95 3762 y(long)47 b(fits_iter_get_tlmax\(itera)o(tor)o(Col)41 b(*col\);)95 3987 y(long)47 b(fits_iter_get_repeat\(iter)o(ato)o(rCol) 41 b(*col\);)95 4213 y(char)47 b(*)h(fits_iter_get_tunit\(ite)o(rat)o (orCo)o(l)42 b(*col\);)95 4439 y(char)47 b(*)h (fits_iter_get_tdisp\(ite)o(rat)o(orCo)o(l)42 b(*col\);)0 4687 y Fi(3)81 b Fj(The)29 b(CFITSIO)g(iterator)j(function)95 4936 y Fe(int)47 b(fits_iterate_data\(int)42 b(narrays,)94 b(iteratorCol)44 b(*data,)i(long)h(offset,)573 5049 y(long)f(nPerLoop,) 573 5161 y(int)h(\(*workFn\)\()e(long)h(totaln,)g(long)h(offset,)f (long)g(firstn,)1289 5274 y(long)g(nvalues,)g(int)h(narrays,)e (iteratorCol)g(*data,)1289 5387 y(void)h(*userPointer\),)573 5500 y(void)g(*userPointer,)573 5613 y(int)h(*status\);)p eop end %%Page: 84 92 TeXDict begin 84 91 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.84) cvn H.B /DEST pdfmark end 0 299 a Fj(84)1455 b Fh(CHAPTER)30 b(6.)112 b(THE)30 b(CFITSIO)e(ITERA)-8 b(TOR)30 b(FUNCTION)p eop end %%Page: 85 93 TeXDict begin 85 92 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.85) cvn H.B /DEST pdfmark end 0 299 a 0 464 a SDict begin H.S end 0 464 a 0 464 a SDict begin 13.6 H.A end 0 464 a 0 464 a SDict begin [ /View [/XYZ H.V] /Dest (chapter.7) cvn H.B /DEST pdfmark end 0 464 a 761 x Fg(Chapter)65 b(7)0 1687 y Fm(W)-19 b(orld)77 b(Co)6 b(ordinate)78 b(System)f(Routines)0 2180 y Fj(The)36 b(FITS)g(comm)m(unit)m(y)h(has)f(adopted)h(a)g(set)g (of)g(k)m(eyw)m(ord)g(con)m(v)m(en)m(tions)h(that)f(de\014ne)f(the)h (transformations)0 2293 y(needed)30 b(to)i(con)m(v)m(ert)g(b)s(et)m(w)m (een)f(pixel)g(lo)s(cations)h(in)e(an)h(image)h(and)e(the)g(corresp)s (onding)g(celestial)j(co)s(ordinates)0 2406 y(on)25 b(the)h(sky)-8 b(,)27 b(or)e(more)g(generally)-8 b(,)29 b(that)d(de\014ne)e(w)m(orld)h (co)s(ordinates)i(that)e(are)h(to)g(b)s(e)f(asso)s(ciated)i(with)e(an)m (y)h(pixel)0 2518 y(lo)s(cation)h(in)e(an)h(n-dimensional)f(FITS)g (arra)m(y)-8 b(.)40 b(CFITSIO)24 b(is)h(distributed)g(with)g(a)h(a)g (few)f(self-con)m(tained)i(W)-8 b(orld)0 2631 y(Co)s(ordinate)30 b(System)g(\(W)m(CS\))g(routines,)g(ho)m(w)m(ev)m(er,)i(these)e (routines)g(DO)f(NOT)h(supp)s(ort)e(all)j(the)f(latest)h(W)m(CS)0 2744 y(con)m(v)m(en)m(tions,)38 b(so)c(it)h(is)g(STR)m(ONGL)-8 b(Y)34 b(RECOMMENDED)h(that)g(soft)m(w)m(are)h(dev)m(elop)s(ers)e(use)g (a)h(more)g(robust)0 2857 y(external)c(W)m(CS)g(library)-8 b(.)40 b(Sev)m(eral)32 b(recommended)e(libraries)g(are:)95 3138 y Fe(WCSLIB)47 b(-)95 b(supported)45 b(by)i(Mark)g(Calabretta)95 3251 y(WCSTools)f(-)h(supported)f(by)h(Doug)g(Mink)95 3364 y(AST)g(library)f(-)i(developed)d(by)i(the)g(U.K.)g(Starlink)e (project)0 3644 y Fj(More)30 b(information)f(ab)s(out)g(the)g(W)m(CS)g (k)m(eyw)m(ord)h(con)m(v)m(en)m(tions)h(and)d(links)h(to)h(all)g(of)f (these)g(W)m(CS)g(libraries)h(can)0 3757 y(b)s(e)g(found)f(on)h(the)h (FITS)e(Supp)s(ort)g(O\016ce)h(w)m(eb)g(site)i(at)f(h)m (ttp://\014ts.gsfc.nasa.go)m(v)j(under)29 b(the)h(W)m(CS)h(link.)0 3917 y(The)40 b(functions)h(pro)m(vided)g(in)f(these)i(external)f(W)m (CS)g(libraries)h(will)f(need)g(access)h(to)f(the)h(W)m(CS)f(k)m(eyw)m (ords)0 4030 y(con)m(tained)36 b(in)f(the)h(FITS)e(\014le)i(headers.)55 b(One)35 b(con)m(v)m(enien)m(t)i(w)m(a)m(y)f(to)g(pass)f(this)g (information)h(to)g(the)f(external)0 4143 y(library)c(is)f(to)i(use)f (the)g(\014ts)p 942 4143 28 4 v 32 w(hdr2str)f(routine)h(in)g(CFITSIO)e (\(de\014ned)h(b)s(elo)m(w\))h(to)h(cop)m(y)g(the)f(header)g(k)m(eyw)m (ords)0 4256 y(in)m(to)k(one)e(long)i(string,)f(and)f(then)g(pass)g (this)h(string)f(to)i(an)e(in)m(terface)i(routine)f(in)f(the)h (external)g(library)f(that)0 4369 y(will)d(extract)h(the)f(necessary)f (W)m(CS)h(information)g(\(e.g.,)h(the)f('w)m(cspih')g(routine)f(in)g (the)h(W)m(CSLIB)f(library)h(and)0 4482 y(the)h('astFitsChan')g(and)f ('astPutCards')g(functions)g(in)g(the)h(AST)e(library\).)0 4763 y Fi(1)81 b Fj(Concatenate)38 b(the)f(header)f(k)m(eyw)m(ords)h (in)f(the)g(CHDU)h(in)m(to)h(a)f(single)g(long)g(string)f(of)h(c)m (haracters.)60 b(Eac)m(h)227 4876 y(80-c)m(haracter)28 b(\014xed-length)c(k)m(eyw)m(ord)h(record)g(is)g(app)s(ended)d(to)k (the)f(output)f(c)m(haracter)i(string,)g(in)e(order,)227 4989 y(with)h(no)f(in)m(terv)m(ening)i(separator)f(or)g(terminating)h (c)m(haracters.)40 b(The)24 b(last)i(header)e(record)h(is)f(terminated) 227 5101 y(with)33 b(a)g(NULL)f(c)m(haracter.)49 b(This)32 b(routine)h(allo)s(cates)i(memory)d(for)h(the)g(returned)e(c)m (haracter)j(arra)m(y)-8 b(,)35 b(so)227 5214 y(the)c(calling)h(program) e(m)m(ust)g(free)h(the)f(memory)g(when)g(\014nished.)227 5375 y(There)c(are)h(2)f(related)h(routines:)39 b(\014ts)p 1514 5375 V 32 w(hdr2str)25 b(simply)h(concatenates)j(all)e(the)f (existing)h(k)m(eyw)m(ords)g(in)f(the)227 5488 y(header;)40 b(\014ts)p 682 5488 V 32 w(con)m(v)m(ert)p 1003 5488 V 34 w(hdr2str)35 b(is)i(similar,)h(except)f(that)g(if)f(the)h(CHDU)f (is)h(a)f(tile)i(compressed)e(image)227 5601 y(\(stored)28 b(in)g(a)f(binary)g(table\))i(then)e(it)h(will)g(\014rst)f(con)m(v)m (ert)i(that)f(header)g(bac)m(k)g(to)g(that)g(of)g(a)g(normal)g(FITS)227 5714 y(image)k(b)s(efore)e(concatenating)j(the)d(k)m(eyw)m(ords.)1905 5942 y(85)p eop end %%Page: 86 94 TeXDict begin 86 93 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.86) cvn H.B /DEST pdfmark end 0 299 a Fj(86)1169 b Fh(CHAPTER)29 b(7.)112 b(W)m(ORLD)31 b(COORDINA)-8 b(TE)30 b(SYSTEM)f(R)m(OUTINES)227 555 y Fj(Selected)h(k)m(eyw)m(ords)e(ma)m(y)h(b)s(e)e(excluded)h(from)g (the)g(returned)f(c)m(haracter)j(string.)40 b(If)27 b(the)i(second)f (param-)227 668 y(eter)h(\(no)s(commen)m(ts\))g(is)f(TR)m(UE)g (\(nonzero\))h(then)e(an)m(y)i(COMMENT,)f(HISTOR)-8 b(Y,)27 b(or)h(blank)g(k)m(eyw)m(ords)227 781 y(in)i(the)h(header)f(will)h(not) f(b)s(e)g(copied)h(to)g(the)g(output)f(string.)227 924 y(The)25 b('exclist')j(parameter)e(ma)m(y)g(b)s(e)f(used)g(to)h(supply) e(a)i(list)h(of)e(k)m(eyw)m(ords)h(that)h(are)f(to)g(b)s(e)f(excluded)g (from)227 1037 y(the)k(output)g(c)m(haracter)h(string.)41 b(Wild)29 b(card)g(c)m(haracters)h(\(*,)g(?,)f(and)g(#\))g(ma)m(y)g(b)s (e)f(used)g(in)h(the)g(excluded)227 1150 y(k)m(eyw)m(ord)h(names.)41 b(If)29 b(no)g(additional)i(k)m(eyw)m(ords)f(are)g(to)g(b)s(e)f (excluded,)h(then)f(set)h(nexc)g(=)f(0)h(and)f(sp)s(ecify)227 1263 y(NULL)i(for)f(the)g(the)h(**exclist)i(parameter.)95 1478 y Fe(int)47 b(fits_hdr2str)286 1591 y(\(fitsfile)f(*fptr,)g(int)h (nocomments,)d(char)j(**exclist,)e(int)i(nexc,)286 1704 y(>)h(char)e(**header,)g(int)h(*nkeys,)e(int)i(*status\))95 1930 y(int)g(fits_convert_hdr2str)c(/)k(ffcnvthdr2str)286 2043 y(\(fitsfile)f(*fptr,)g(int)h(nocomments,)d(char)j(**exclist,)e (int)i(nexc,)286 2155 y(>)h(char)e(**header,)g(int)h(*nkeys,)e(int)i (*status\))0 2371 y Fi(2)81 b Fj(The)24 b(follo)m(wing)j(CFITSIO)d (routine)i(is)f(sp)s(eci\014cally)h(designed)f(for)h(use)f(in)g (conjunction)g(with)g(the)h(W)m(CSLIB)227 2484 y(library)-8 b(.)40 b(It)27 b(is)h(not)f(exp)s(ected)h(that)g(applications)g (programmers)f(will)h(call)g(this)f(routine)h(directly)-8 b(,)29 b(but)d(it)227 2597 y(is)33 b(do)s(cumen)m(ted)g(here)g(for)g (completeness.)50 b(This)33 b(routine)g(extracts)h(arra)m(ys)g(from)e (a)i(binary)e(table)i(that)227 2710 y(con)m(tain)i(W)m(CS)e (information)h(using)f(the)g(-T)-8 b(AB)36 b(table)f(lo)s(okup)f(con)m (v)m(en)m(tion.)55 b(See)35 b(the)f(do)s(cumen)m(tation)227 2822 y(pro)m(vided)c(with)g(the)h(W)m(CSLIB)f(library)g(for)g(more)h (information.)95 3038 y Fe(int)47 b(fits_read_wcstab)334 3151 y(\(fitsfile)e(*fptr,)h(int)h(nwtb,)g(wtbarr)f(*wtb,)g(int)h (*status\);)0 3301 y SDict begin H.S end 0 3301 a 0 3301 a SDict begin 13.6 H.A end 0 3301 a 0 3301 a SDict begin [ /View [/XYZ H.V] /Dest (section.7.1) cvn H.B /DEST pdfmark end 0 3301 a 176 x Ff(7.1)180 b(Self-con)l(tained)46 b(W)l(CS)f(Routines) 0 3728 y Fj(The)21 b(follo)m(wing)i(routines)e(DO)g(NOT)g(supp)s(ort)f (the)h(more)h(recen)m(t)g(W)m(CS)f(con)m(v)m(en)m(tions)j(that)d(ha)m (v)m(e)i(b)s(een)e(appro)m(v)m(ed)0 3841 y(as)34 b(part)g(of)g(the)g (FITS)f(standard.)50 b(Consequen)m(tly)-8 b(,)35 b(the)f(follo)m(wing)i (routines)d(ARE)h(NO)m(W)h(DEPRECA)-8 b(TED.)0 3953 y(It)30 b(is)g(STR)m(ONGL)-8 b(Y)30 b(RECOMMENDED)h(that)g(soft)m(w)m(are)g (dev)m(elop)s(ers)f(not)h(use)f(these)g(routines,)g(and)g(instead)0 4066 y(use)g(an)g(external)i(W)m(CS)e(library)-8 b(,)31 b(as)f(describ)s(ed)f(in)i(the)f(previous)g(section.)0 4227 y(These)21 b(routines)g(are)g(included)f(mainly)h(for)g(bac)m(kw)m (ard)g(compatibilit)m(y)j(with)c(existing)i(soft)m(w)m(are.)39 b(They)21 b(supp)s(ort)0 4339 y(the)30 b(follo)m(wing)i(standard)d(map) g(pro)5 b(jections:)41 b(-SIN,)30 b(-T)-8 b(AN,)31 b(-AR)m(C,)g(-NCP)-8 b(,)30 b(-GLS,)g(-MER,)h(and)e(-AIT)h(\(these)0 4452 y(are)f(the)g(legal)h(v)-5 b(alues)29 b(for)f(the)h(co)s(ordt)m(yp)s(e) f(parameter\).)41 b(These)28 b(routines)h(are)g(based)f(on)g(similar)h (functions)f(in)0 4565 y(Classic)j(AIPS.)f(All)h(the)g(angular)f(quan)m (tities)i(are)f(giv)m(en)g(in)f(units)g(of)g(degrees.)0 4781 y Fi(1)81 b Fj(Get)41 b(the)f(v)-5 b(alues)41 b(of)g(the)f(basic)h (set)g(of)f(standard)g(FITS)f(celestial)k(co)s(ordinate)e(system)g(k)m (eyw)m(ords)f(from)227 4894 y(the)33 b(header)f(of)h(a)f(FITS)g(image)i (\(i.e.,)g(the)f(primary)f(arra)m(y)g(or)h(an)f(IMA)m(GE)i (extension\).)47 b(These)33 b(v)-5 b(alues)227 5006 y(ma)m(y)35 b(then)f(b)s(e)g(passed)f(to)i(the)g(\014ts)p 1462 5006 28 4 v 32 w(pix)p 1618 5006 V 32 w(to)p 1730 5006 V 34 w(w)m(orld)f(and)g(\014ts)p 2321 5006 V 32 w(w)m(orld)p 2573 5006 V 33 w(to)p 2686 5006 V 33 w(pix)g(routines)g(that)h(p)s (erform)e(the)227 5119 y(co)s(ordinate)f(transformations.)42 b(If)30 b(an)m(y)h(or)f(all)i(of)f(the)g(W)m(CS)f(k)m(eyw)m(ords)h(are) g(not)g(presen)m(t,)g(then)g(default)227 5232 y(v)-5 b(alues)26 b(will)f(b)s(e)f(returned.)38 b(If)24 b(the)i(\014rst)e(co)s (ordinate)i(axis)f(is)g(the)g(declination-lik)m(e)j(co)s(ordinate,)f (then)e(this)227 5345 y(routine)31 b(will)f(sw)m(ap)h(them)f(so)h(that) g(the)f(longitudinal-lik)m(e)j(co)s(ordinate)e(is)f(returned)g(as)g (the)h(\014rst)e(axis.)227 5488 y(The)34 b(\014rst)g(routine)h (\(\013gics\))h(returns)e(the)h(primary)f(W)m(CS,)g(whereas)h(the)g (second)g(routine)f(returns)g(the)227 5601 y(particular)24 b(v)m(ersion)h(of)f(the)g(W)m(CS)f(sp)s(eci\014ed)g(b)m(y)h(the)g('v)m (ersion')h(parameter,)h(whic)m(h)d(m)m(uc)m(h)h(b)s(e)f(a)h(c)m (haracter)227 5714 y(ranging)31 b(from)f('A')h(to)g('Z')f(\(or)h(a)g (blank)f(c)m(haracter,)i(whic)m(h)e(is)g(equiv)-5 b(alen)m(t)32 b(to)f(calling)h(\013gics\).)p eop end %%Page: 87 95 TeXDict begin 87 94 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.87) cvn H.B /DEST pdfmark end 0 299 a Fh(7.1.)113 b(SELF-CONT)-8 b(AINED)30 b(W)m(CS)g(R)m(OUTINES)1984 b Fj(87)227 555 y(If)35 b(the)h(\014le)f(uses)g(the)g(new)m(er)h('CDj)p 1454 555 28 4 v 32 w(i')g(W)m(CS)f(transformation)h(matrix)g(k)m(eyw)m (ords)f(instead)h(of)f(old)h(st)m(yle)227 668 y('CDEL)-8 b(Tn')37 b(and)f('CR)m(OT)-8 b(A2')38 b(k)m(eyw)m(ords,)h(then)e(this)f (routine)h(will)g(calculate)j(and)c(return)g(the)h(v)-5 b(alues)227 781 y(of)33 b(the)g(equiv)-5 b(alen)m(t)35 b(old-st)m(yle)f(k)m(eyw)m(ords.)49 b(Note)34 b(that)g(the)f(con)m(v)m (ersion)h(from)e(the)i(new-st)m(yle)g(k)m(eyw)m(ords)227 894 y(to)e(the)f(old-st)m(yle)h(v)-5 b(alues)31 b(is)g(sometimes)g (only)g(an)g(appro)m(ximation,)h(so)e(if)h(the)g(appro)m(ximation)h(is) e(larger)227 1007 y(than)37 b(an)h(in)m(ternally)g(de\014ned)e (threshold)h(lev)m(el,)k(then)c(CFITSIO)f(will)i(still)g(return)e(the)i (appro)m(ximate)227 1120 y(W)m(CS)32 b(k)m(eyw)m(ord)h(v)-5 b(alues,)33 b(but)e(will)h(also)h(return)e(with)h(status)g(=)f(APPR)m (O)m(X)p 2908 1120 V 34 w(W)m(CS)p 3149 1120 V 33 w(KEY,)g(to)i(w)m (arn)f(the)227 1233 y(calling)k(program)e(that)h(appro)m(ximations)g (ha)m(v)m(e)g(b)s(een)f(made.)52 b(It)35 b(is)f(then)g(up)f(to)i(the)f (calling)i(program)227 1346 y(to)30 b(decide)g(whether)e(the)h(appro)m (ximations)h(are)g(su\016cien)m(tly)f(accurate)i(for)e(the)g (particular)g(application,)227 1458 y(or)46 b(whether)e(more)i(precise) g(W)m(CS)f(transformations)h(m)m(ust)f(b)s(e)g(p)s(erformed)f(using)g (new-st)m(yle)j(W)m(CS)227 1571 y(k)m(eyw)m(ords)31 b(directly)-8 b(.)95 1824 y Fe(int)47 b(fits_read_img_coord)c(/)k(ffgics)286 1937 y(\(fitsfile)f(*fptr,)g(>)h(double)f(*xrefval,)g(double)g (*yrefval,)334 2050 y(double)g(*xrefpix,)f(double)i(*yrefpix,)e(double) h(*xinc,)g(double)g(*yinc,)334 2163 y(double)g(*rot,)h(char)f (*coordtype,)f(int)i(*status\))95 2389 y(int)g (fits_read_img_coord_versio)o(n)42 b(/)47 b(ffgicsa)286 2502 y(\(fitsfile)f(*fptr,)g(char)g(version,)g(>)h(double)f(*xrefval,)g (double)g(*yrefval,)334 2615 y(double)g(*xrefpix,)f(double)i(*yrefpix,) e(double)h(*xinc,)g(double)g(*yinc,)334 2728 y(double)g(*rot,)h(char)f (*coordtype,)f(int)i(*status\))0 2981 y Fi(2)81 b Fj(Get)30 b(the)f(v)-5 b(alues)30 b(of)f(the)h(standard)e(FITS)h(celestial)j(co)s (ordinate)e(system)f(k)m(eyw)m(ords)h(from)f(the)g(header)g(of)h(a)227 3094 y(FITS)23 b(table)i(where)e(the)h(X)g(and)g(Y)g(\(or)g(RA)g(and)f (DEC\))h(co)s(ordinates)h(are)f(stored)g(in)f(2)h(separate)h(columns) 227 3207 y(of)30 b(the)f(table)h(\(as)g(in)f(the)h(Ev)m(en)m(t)g(List)g (table)g(format)f(that)h(is)g(often)f(used)g(b)m(y)g(high)g(energy)g (astroph)m(ysics)227 3320 y(missions\).)71 b(These)40 b(v)-5 b(alues)40 b(ma)m(y)h(then)f(b)s(e)f(passed)h(to)h(the)f(\014ts) p 2511 3320 V 33 w(pix)p 2668 3320 V 32 w(to)p 2780 3320 V 34 w(w)m(orld)g(and)g(\014ts)p 3383 3320 V 32 w(w)m(orld)p 3635 3320 V 33 w(to)p 3748 3320 V 33 w(pix)227 3432 y(routines)31 b(that)f(p)s(erform)f(the)i(co)s(ordinate)g(transformations.)95 3685 y Fe(int)47 b(fits_read_tbl_coord)c(/)k(ffgtcs)286 3798 y(\(fitsfile)f(*fptr,)g(int)h(xcol,)f(int)h(ycol,)f(>)i(double)e (*xrefval,)334 3911 y(double)g(*yrefval,)f(double)i(*xrefpix,)e(double) h(*yrefpix,)f(double)h(*xinc,)334 4024 y(double)g(*yinc,)g(double)g (*rot,)h(char)f(*coordtype,)f(int)i(*status\))0 4277 y Fi(3)81 b Fj(Calculate)42 b(the)g(celestial)h(co)s(ordinate)f (corresp)s(onding)e(to)i(the)f(input)f(X)h(and)g(Y)g(pixel)g(lo)s (cation)i(in)e(the)227 4390 y(image.)95 4643 y Fe(int)47 b(fits_pix_to_world)c(/)48 b(ffwldp)286 4756 y(\(double)e(xpix,)h (double)f(ypix,)g(double)g(xrefval,)g(double)g(yrefval,)334 4869 y(double)g(xrefpix,)g(double)g(yrefpix,)f(double)h(xinc,)h(double) f(yinc,)334 4982 y(double)g(rot,)h(char)f(*coordtype,)f(>)j(double)e (*xpos,)g(double)g(*ypos,)334 5095 y(int)h(*status\))0 5348 y Fi(4)81 b Fj(Calculate)42 b(the)g(X)f(and)f(Y)h(pixel)h(lo)s (cation)g(corresp)s(onding)e(to)i(the)f(input)f(celestial)k(co)s (ordinate)e(in)f(the)227 5461 y(image.)95 5714 y Fe(int)47 b(fits_world_to_pix)c(/)48 b(ffxypx)p eop end %%Page: 88 96 TeXDict begin 88 95 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.88) cvn H.B /DEST pdfmark end 0 299 a Fj(88)1169 b Fh(CHAPTER)29 b(7.)112 b(W)m(ORLD)31 b(COORDINA)-8 b(TE)30 b(SYSTEM)f(R)m(OUTINES)286 555 y Fe(\(double)46 b(xpos,)h(double)f(ypos,)g(double)g(xrefval,)g (double)g(yrefval,)334 668 y(double)g(xrefpix,)g(double)g(yrefpix,)f (double)h(xinc,)h(double)f(yinc,)334 781 y(double)g(rot,)h(char)f (*coordtype,)f(>)j(double)e(*xpix,)g(double)g(*ypix,)334 894 y(int)h(*status\))p eop end %%Page: 89 97 TeXDict begin 89 96 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.89) cvn H.B /DEST pdfmark end 0 299 a 0 464 a SDict begin H.S end 0 464 a 0 464 a SDict begin 13.6 H.A end 0 464 a 0 464 a SDict begin [ /View [/XYZ H.V] /Dest (chapter.8) cvn H.B /DEST pdfmark end 0 464 a 761 x Fg(Chapter)65 b(8)0 1687 y Fm(Hierarc)-6 b(hical)76 b(Grouping)h(Routines)0 2180 y Fj(These)34 b(functions)h(allo)m(w)h(for)e(the)h(creation)h(and)e (manipulation)h(of)g(FITS)f(HDU)h(Groups,)h(as)f(de\014ned)e(in)h("A)0 2293 y(Hierarc)m(hical)f(Grouping)c(Con)m(v)m(en)m(tion)j(for)e(FITS")h (b)m(y)f(Jennings,)g(P)m(ence,)h(F)-8 b(olk)32 b(and)e(Sc)m(hlesinger:) 0 2453 y(h)m(ttps://\014ts.gsfc.nasa.go)m (v/registry/grouping/grouping.p)s(df)0 2613 y(A)38 b(group)g(is)g(a)g (collection)j(of)d(HDUs)h(whose)f(asso)s(ciation)h(is)g(de\014ned)d(b)m (y)i(a)h Fa(gr)-5 b(ouping)40 b(table)p Fj(.)65 b(HDUs)38 b(whic)m(h)0 2726 y(are)46 b(part)f(of)g(a)g(group)g(are)h(referred)e (to)i(as)f Fa(memb)-5 b(er)47 b(HDUs)d Fj(or)h(simply)g(as)g Fa(memb)-5 b(ers)p Fj(.)86 b(Grouping)45 b(table)0 2839 y(mem)m(b)s(er)40 b(HDUs)i(ma)m(y)f(themselv)m(es)h(b)s(e)f(grouping)f (tables,)45 b(th)m(us)40 b(allo)m(wing)j(for)e(the)g(construction)g(of) g(op)s(en-)0 2952 y(ended)30 b(hierarc)m(hies)h(of)f(HDUs.)0 3112 y(Grouping)c(tables)i(con)m(tain)g(one)f(ro)m(w)g(for)f(eac)m(h)i (mem)m(b)s(er)e(HDU.)i(The)e(grouping)g(table)i(columns)e(pro)m(vide)h (iden-)0 3225 y(ti\014cation)i(information)f(that)g(allo)m(ws)h (applications)f(to)g(reference)g(or)g("p)s(oin)m(t)g(to")g(the)g(mem)m (b)s(er)f(HDUs.)40 b(Mem-)0 3338 y(b)s(er)27 b(HDUs)h(are)g(exp)s (ected,)h(but)e(not)h(required,)f(to)i(con)m(tain)g(a)f(set)g(of)g (GRPIDn/GRPLCn)f(k)m(eyw)m(ords)h(in)f(their)0 3451 y(headers)j(for)h (eac)m(h)g(grouping)g(table)g(that)g(they)g(are)g(referenced)g(b)m(y)-8 b(.)41 b(In)30 b(this)h(sense,)g(the)g(GRPIDn/GRPLCn)0 3563 y(k)m(eyw)m(ords)d("link")g(the)g(mem)m(b)s(er)f(HDU)h(bac)m(k)g (to)g(its)g(Grouping)f(table.)41 b(Note)29 b(that)f(a)f(mem)m(b)s(er)g (HDU)h(need)g(not)0 3676 y(reside)i(in)g(the)g(same)g(FITS)f(\014le)i (as)f(its)g(grouping)g(table,)h(and)e(that)i(a)f(giv)m(en)h(HDU)g(ma)m (y)g(b)s(e)e(referenced)h(b)m(y)g(up)0 3789 y(to)h(999)h(grouping)e (tables)h(sim)m(ultaneously)-8 b(.)0 3949 y(Grouping)22 b(tables)i(are)f(implemen)m(ted)g(as)g(FITS)f(binary)g(tables)h(with)g (up)e(to)j(six)e(pre-de\014ned)g(column)g(TTYPEn)0 4062 y(v)-5 b(alues:)36 b('MEMBER)p 752 4062 28 4 v 34 w(XTENSION',)20 b('MEMBER)p 1789 4062 V 33 w(NAME',)h('MEMBER)p 2620 4062 V 34 w(VERSION',)f('MEMBER)p 3590 4062 V 34 w(POSITION',)0 4175 y('MEMBER)p 451 4175 V 34 w(URI)p 653 4175 V 32 w(TYPE')g(and)g('MEMBER)p 1601 4175 V 34 w(LOCA)-8 b(TION'.)20 b(The)f(\014rst)h(three)g(columns)g(allo)m(w)i(mem)m(b)s(er)e(HDUs)0 4288 y(to)28 b(b)s(e)f(iden)m(ti\014ed)g(b)m(y)g(reference)h(to)g (their)f(XTENSION,)g(EXTNAME)g(and)g(EXTVER)g(k)m(eyw)m(ord)g(v)-5 b(alues.)40 b(The)0 4401 y(fourth)29 b(column)h(allo)m(ws)i(mem)m(b)s (er)d(HDUs)i(to)g(b)s(e)f(iden)m(ti\014ed)g(b)m(y)g(HDU)h(p)s(osition)f (within)g(their)g(FITS)g(\014le.)40 b(The)0 4514 y(last)f(t)m(w)m(o)g (columns)e(iden)m(tify)h(the)g(FITS)f(\014le)h(in)f(whic)m(h)h(the)g (mem)m(b)s(er)f(HDU)h(resides,)i(if)d(di\013eren)m(t)i(from)e(the)0 4627 y(grouping)30 b(table)h(FITS)f(\014le.)0 4787 y(Additional)25 b(user)f(de\014ned)f("auxiliary")j(columns)e(ma)m(y)h(also)g(b)s(e)f (included)g(with)g(an)m(y)h(grouping)f(table.)39 b(When)25 b(a)0 4900 y(grouping)i(table)i(is)f(copied)g(or)f(mo)s(di\014ed)g(the) h(presence)g(of)f(auxiliary)i(columns)e(is)h(alw)m(a)m(ys)h(tak)m(en)g (in)m(to)f(accoun)m(t)0 5013 y(b)m(y)j(the)g(grouping)g(supp)s(ort)f (functions;)h(ho)m(w)m(ev)m(er,)i(the)e(grouping)g(supp)s(ort)f (functions)g(cannot)i(directly)g(mak)m(e)0 5126 y(use)e(of)h(this)f (data.)0 5286 y(If)44 b(a)h(grouping)f(table)h(column)f(is)h(de\014ned) e(but)h(the)g(corresp)s(onding)g(mem)m(b)s(er)f(HDU)j(information)e(is) h(un-)0 5399 y(a)m(v)-5 b(ailable)41 b(then)c(a)i(n)m(ull)f(v)-5 b(alue)39 b(of)f(the)g(appropriate)h(data)f(t)m(yp)s(e)h(is)f(inserted) g(in)g(the)g(column)g(\014eld.)64 b(In)m(teger)0 5512 y(columns)26 b(\(MEMBER)p 811 5512 V 34 w(POSITION,)f(MEMBER)p 1771 5512 V 34 w(VERSION\))h(are)h(de\014ned)f(with)g(a)h(TNULLn)f(v)-5 b(alue)27 b(of)g(zero)0 5625 y(\(0\).)41 b(Character)27 b(\014eld)f(columns)h(\(MEMBER)p 1607 5625 V 34 w(XTENSION,)f(MEMBER)p 2600 5625 V 33 w(NAME,)i(MEMBER)p 3388 5625 V 34 w(URI)p 3590 5625 V 32 w(TYPE,)1905 5942 y(89)p eop end %%Page: 90 98 TeXDict begin 90 97 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.90) cvn H.B /DEST pdfmark end 0 299 a Fj(90)1338 b Fh(CHAPTER)29 b(8.)112 b(HIERAR)m(CHICAL)30 b(GR)m(OUPING)h(R)m(OUTINES)0 555 y Fj(MEMBER)p 426 555 28 4 v 33 w(LOCA)-8 b(TION\))30 b(utilize)i(an)e(ASCI)s(I)f(n)m(ull)h(c)m(haracter)i(to)f(denote)g(a)g (n)m(ull)f(\014eld)g(v)-5 b(alue.)0 715 y(The)23 b(grouping)g(supp)s (ort)f(functions)h(b)s(elong)h(to)g(t)m(w)m(o)h(basic)f(categories:)40 b(those)24 b(that)h(w)m(ork)e(with)h(grouping)f(table)0 828 y(HDUs)j(\(\013gt**\))j(and)c(those)h(that)h(w)m(ork)f(with)f(mem)m (b)s(er)h(HDUs)g(\(\013gm**\).)41 b(Tw)m(o)26 b(functions,)h(\014ts)p 3360 828 V 32 w(cop)m(y)p 3573 828 V 34 w(group\(\))0 941 y(and)40 b(\014ts)p 314 941 V 33 w(remo)m(v)m(e)p 626 941 V 34 w(group\(\),)k(ha)m(v)m(e)e(the)f(option)g(to)h(recursiv)m (ely)f(cop)m(y/delete)j(en)m(tire)e(groups.)71 b(Care)41 b(should)0 1054 y(b)s(e)33 b(tak)m(en)h(when)f(emplo)m(ying)h(these)g (functions)f(in)g(recursiv)m(e)h(mo)s(de)f(as)g(p)s(o)s(orly)g (de\014ned)f(groups)h(could)g(cause)0 1167 y(unpredictable)25 b(results.)39 b(The)25 b(problem)g(of)h(a)g(grouping)f(table)i (directly)f(or)g(indirectly)g(referencing)g(itself)g(\(th)m(us)0 1280 y(creating)41 b(an)f(in\014nite)f(lo)s(op\))i(is)e(protected)i (against;)46 b(in)39 b(fact,)44 b(neither)39 b(function)h(will)g (attempt)h(to)f(cop)m(y)h(or)0 1393 y(delete)32 b(an)e(HDU)h(t)m(wice.) 0 1548 y SDict begin H.S end 0 1548 a 0 1548 a SDict begin 13.6 H.A end 0 1548 a 0 1548 a SDict begin [ /View [/XYZ H.V] /Dest (section.8.1) cvn H.B /DEST pdfmark end 0 1548 a 197 x Ff(8.1)135 b(Grouping)45 b(T)-11 b(able)45 b(Routines)0 1997 y Fi(1)81 b Fj(Create)34 b(\(app)s(end\))f(a)h(grouping)f(table)i (at)f(the)g(end)f(of)h(the)g(curren)m(t)f(FITS)g(\014le)h(p)s(oin)m (ted)g(to)g(b)m(y)g(fptr.)49 b(The)227 2110 y(grpname)28 b(parameter)h(pro)m(vides)g(the)g(grouping)f(table)h(name)g(\(GRPNAME)g (k)m(eyw)m(ord)g(v)-5 b(alue\))29 b(and)f(ma)m(y)227 2223 y(b)s(e)42 b(set)h(to)g(NULL)f(if)g(no)g(group)g(name)g(is)h(to)g (b)s(e)e(sp)s(eci\014ed.)76 b(The)42 b(groupt)m(yp)s(e)g(parameter)g (sp)s(eci\014es)227 2336 y(the)c(desired)g(structure)f(of)h(the)g (grouping)f(table)i(and)e(ma)m(y)i(tak)m(e)g(on)f(the)g(v)-5 b(alues:)56 b(GT)p 3355 2336 28 4 v 33 w(ID)p 3490 2336 V 33 w(ALL)p 3705 2336 V 32 w(URI)227 2449 y(\(all)35 b(columns)e(created\),)j(GT)p 1274 2449 V 33 w(ID)p 1409 2449 V 33 w(REF)d(\(ID)h(b)m(y)g(reference)g(columns\),)g(GT)p 2904 2449 V 33 w(ID)p 3039 2449 V 33 w(POS)e(\(ID)i(b)m(y)g(p)s (osition)227 2562 y(columns\),)48 b(GT)p 801 2562 V 32 w(ID)p 935 2562 V 33 w(ALL)c(\(ID)g(b)m(y)f(reference)i(and)e(p)s (osition)g(columns\),)48 b(GT)p 3028 2562 V 32 w(ID)p 3162 2562 V 33 w(REF)p 3383 2562 V 33 w(URI)c(\(ID)g(b)m(y)227 2674 y(reference)35 b(and)e(FITS)g(\014le)i(URI)e(columns\),)j(and)d (GT)p 2129 2674 V 33 w(ID)p 2264 2674 V 33 w(POS)p 2481 2674 V 32 w(URI)h(\(ID)g(b)m(y)g(p)s(osition)g(and)g(FITS)f(\014le)227 2787 y(URI)e(columns\).)95 3063 y Fe(int)47 b(fits_create_group)c(/)48 b(ffgtcr)286 3176 y(\(fitsfile)e(*fptr,)g(char)g(*grpname,)g(int)h (grouptype,)e(>)i(int)g(*status\))0 3451 y Fi(2)81 b Fj(Create)26 b(\(insert\))g(a)f(grouping)g(table)h(just)f(after)h(the)f (CHDU)h(of)g(the)f(curren)m(t)g(FITS)g(\014le)g(p)s(oin)m(ted)g(to)h(b) m(y)g(fptr.)227 3564 y(All)k(HDUs)f(b)s(elo)m(w)g(the)g(the)g (insertion)g(p)s(oin)m(t)f(will)i(b)s(e)e(shifted)g(do)m(wn)m(w)m(ards) g(to)i(mak)m(e)g(ro)s(om)e(for)g(the)h(new)227 3677 y(HDU.)23 b(The)e(grpname)h(parameter)g(pro)m(vides)f(the)h(grouping)g(table)g (name)g(\(GRPNAME)h(k)m(eyw)m(ord)f(v)-5 b(alue\))227 3790 y(and)25 b(ma)m(y)i(b)s(e)e(set)h(to)h(NULL)e(if)h(no)g(group)f (name)h(is)g(to)g(b)s(e)f(sp)s(eci\014ed.)39 b(The)25 b(groupt)m(yp)s(e)h(parameter)g(sp)s(eci-)227 3903 y(\014es)g(the)h (desired)f(structure)g(of)h(the)f(grouping)g(table)i(and)e(ma)m(y)h (tak)m(e)h(on)e(the)h(v)-5 b(alues:)39 b(GT)p 3355 3903 V 33 w(ID)p 3490 3903 V 33 w(ALL)p 3705 3903 V 32 w(URI)227 4016 y(\(all)c(columns)e(created\),)j(GT)p 1274 4016 V 33 w(ID)p 1409 4016 V 33 w(REF)d(\(ID)h(b)m(y)g(reference)g (columns\),)g(GT)p 2904 4016 V 33 w(ID)p 3039 4016 V 33 w(POS)e(\(ID)i(b)m(y)g(p)s(osition)227 4129 y(columns\),)29 b(GT)p 782 4129 V 33 w(ID)p 917 4129 V 33 w(ALL)f(\(ID)g(b)m(y)g (reference)h(and)e(p)s(osition)h(columns\),)h(GT)p 2897 4129 V 33 w(ID)p 3032 4129 V 33 w(REF)p 3253 4129 V 32 w(URI)f(\(ID)h(b)m(y)f(ref-)227 4242 y(erence)g(and)e(FITS)h(\014le)g (URI)g(columns\),)h(and)e(GT)p 1976 4242 V 33 w(ID)p 2111 4242 V 33 w(POS)p 2328 4242 V 32 w(URI)h(\(ID)g(b)m(y)g(p)s (osition)g(and)g(FITS)f(\014le)h(URI)227 4355 y(columns\))k(.)95 4630 y Fe(int)47 b(fits_insert_group)c(/)48 b(ffgtis)286 4743 y(\(fitsfile)e(*fptr,)g(char)g(*grpname,)g(int)h(grouptype,)e(>)i (int)g(*status\))0 5019 y Fi(3)81 b Fj(Change)20 b(the)h(structure)f (of)h(an)g(existing)g(grouping)g(table)g(p)s(oin)m(ted)g(to)g(b)m(y)g (gfptr.)37 b(The)20 b(groupt)m(yp)s(e)g(parameter)227 5132 y(\(see)27 b(\014ts)p 532 5132 V 32 w(create)p 800 5132 V 35 w(group\(\))e(for)h(v)-5 b(alid)26 b(parameter)g(v)-5 b(alues\))26 b(sp)s(eci\014es)g(the)f(new)g(structure)h(of)f(the)h (grouping)227 5245 y(table.)44 b(This)30 b(function)h(only)g(adds)g(or) g(remo)m(v)m(es)h(grouping)f(table)h(columns,)f(it)h(do)s(es)f(not)g (add)g(or)g(delete)227 5357 y(group)26 b(mem)m(b)s(ers)f(\(i.e.,)k (table)e(ro)m(ws\).)40 b(If)26 b(the)g(grouping)g(table)h(already)g (has)f(the)h(desired)e(structure)h(then)227 5470 y(no)35 b(op)s(erations)f(are)h(p)s(erformed)e(and)h(function)g(simply)h (returns)e(with)h(a)h(\(0\))g(success)g(status)g(co)s(de.)53 b(If)227 5583 y(the)32 b(requested)g(structure)g(c)m(hange)h(creates)g (new)f(grouping)g(table)h(columns,)f(then)g(the)g(column)g(v)-5 b(alues)227 5696 y(for)30 b(all)i(existing)f(mem)m(b)s(ers)f(will)g(b)s (e)g(\014lled)g(with)g(the)h(n)m(ull)f(v)-5 b(alues)31 b(appropriate)f(to)h(the)g(column)f(t)m(yp)s(e.)p eop end %%Page: 91 99 TeXDict begin 91 98 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.91) cvn H.B /DEST pdfmark end 0 299 a Fh(8.1.)72 b(GR)m(OUPING)31 b(T)-8 b(ABLE)31 b(R)m(OUTINES)2235 b Fj(91)95 555 y Fe(int)47 b(fits_change_group)c(/)48 b(ffgtch)286 668 y(\(fitsfile)e(*gfptr,)f(int)i(grouptype,)e(>)j(int)f(*status\))0 905 y Fi(4)81 b Fj(Remo)m(v)m(e)41 b(the)e(group)g(de\014ned)f(b)m(y)h (the)h(grouping)f(table)h(p)s(oin)m(ted)f(to)h(b)m(y)g(gfptr,)h(and)e (optionally)i(all)f(the)227 1018 y(group)29 b(mem)m(b)s(er)f(HDUs.)41 b(The)28 b(rmopt)h(parameter)g(sp)s(eci\014es)g(the)g(action)h(to)g(b)s (e)e(tak)m(en)i(for)f(all)h(mem)m(b)s(ers)227 1131 y(of)d(the)g(group)g (de\014ned)e(b)m(y)i(the)g(grouping)g(table.)40 b(V)-8 b(alid)28 b(v)-5 b(alues)27 b(are:)40 b(OPT)p 2848 1131 28 4 v 32 w(RM)p 3030 1131 V 33 w(GPT)26 b(\(delete)j(only)e(the)227 1244 y(grouping)33 b(table\))i(and)e(OPT)p 1259 1244 V 32 w(RM)p 1441 1244 V 33 w(ALL)g(\(recursiv)m(ely)h(delete)h(all)f (HDUs)g(that)g(b)s(elong)f(to)h(the)g(group\).)227 1357 y(An)m(y)d(groups)g(con)m(taining)i(the)e(grouping)g(table)h(gfptr)e (as)i(a)f(mem)m(b)s(er)g(are)g(up)s(dated,)f(and)h(if)g(rmopt)g(==)227 1470 y(OPT)p 431 1470 V 32 w(RM)p 613 1470 V 33 w(GPT)21 b(all)h(mem)m(b)s(ers)f(ha)m(v)m(e)h(their)f(GRPIDn)g(and)g(GRPLCn)f(k) m(eyw)m(ords)h(up)s(dated)f(accordingly)-8 b(.)227 1582 y(If)36 b(rmopt)g(==)g(OPT)p 985 1582 V 32 w(RM)p 1167 1582 V 33 w(ALL,)g(then)g(other)h(groups)e(that)i(con)m(tain)h(the)e (deleted)h(mem)m(b)s(ers)f(of)g(gfptr)227 1695 y(are)31 b(up)s(dated)e(to)i(re\015ect)g(the)g(deletion)g(accordingly)-8 b(.)95 1932 y Fe(int)47 b(fits_remove_group)c(/)48 b(ffgtrm)286 2045 y(\(fitsfile)e(*gfptr,)f(int)i(rmopt,)f(>)i(int)f(*status\))0 2282 y Fi(5)81 b Fj(Cop)m(y)28 b(\(app)s(end\))g(the)h(group)f (de\014ned)g(b)m(y)h(the)f(grouping)h(table)h(p)s(oin)m(ted)e(to)i(b)m (y)e(infptr,)h(and)f(optionally)i(all)227 2395 y(group)g(mem)m(b)s(er)h (HDUs,)g(to)h(the)f(FITS)f(\014le)g(p)s(oin)m(ted)h(to)h(b)m(y)e (outfptr.)41 b(The)31 b(cp)s(opt)f(parameter)h(sp)s(eci\014es)227 2508 y(the)c(action)h(to)f(b)s(e)f(tak)m(en)h(for)g(all)g(mem)m(b)s (ers)f(of)g(the)h(group)f(infptr.)38 b(V)-8 b(alid)28 b(v)-5 b(alues)26 b(are:)40 b(OPT)p 3443 2508 V 32 w(GCP)p 3674 2508 V 32 w(GPT)227 2621 y(\(cop)m(y)d(only)g(the)f(grouping)g (table\))h(and)e(OPT)p 1887 2621 V 32 w(GCP)p 2118 2621 V 33 w(ALL)h(\(recursiv)m(ely)h(cop)m(y)g(ALL)e(the)i(HDUs)f(that)227 2734 y(b)s(elong)24 b(to)g(the)g(group)f(de\014ned)g(b)m(y)g(infptr\).) 38 b(If)23 b(the)h(cp)s(opt)g(==)f(OPT)p 2618 2734 V 32 w(GCP)p 2849 2734 V 32 w(GPT)h(then)f(the)h(mem)m(b)s(ers)f(of)227 2847 y(infptr)i(ha)m(v)m(e)h(their)g(GRPIDn)f(and)g(GRPLCn)g(k)m(eyw)m (ords)h(up)s(dated)e(to)i(re\015ect)g(the)g(existence)h(of)f(the)f(new) 227 2960 y(grouping)f(table)g(outfptr,)h(since)f(they)g(no)m(w)g(b)s (elong)g(to)g(the)g(new)g(group.)38 b(If)23 b(cp)s(opt)h(==)f(OPT)p 3460 2960 V 32 w(GCP)p 3691 2960 V 32 w(ALL)227 3073 y(then)29 b(the)g(new)g(grouping)g(table)h(outfptr)e(only)h(con)m (tains)i(p)s(oin)m(ters)e(to)h(the)f(copied)g(mem)m(b)s(er)g(HDUs)h (and)227 3185 y(not)38 b(the)g(original)g(mem)m(b)s(er)f(HDUs)h(of)g (infptr.)61 b(Note)39 b(that,)h(when)d(cp)s(opt)g(==)g(OPT)p 3301 3185 V 32 w(GCP)p 3532 3185 V 33 w(ALL,)g(all)227 3298 y(mem)m(b)s(ers)h(of)h(the)f(group)g(de\014ned)f(b)m(y)i(infptr)e (will)i(b)s(e)e(copied)i(to)g(a)g(single)g(FITS)f(\014le)h(p)s(oin)m (ted)f(to)h(b)m(y)227 3411 y(outfptr)30 b(regardless)h(of)f(their)h (\014le)f(distribution)g(in)g(the)h(original)g(group.)95 3648 y Fe(int)47 b(fits_copy_group)d(/)j(ffgtcp)286 3761 y(\(fitsfile)f(*infptr,)f(fitsfile)h(*outfptr,)f(int)i(cpopt,)f(>)h (int)g(*status\))0 3998 y Fi(6)81 b Fj(Merge)40 b(the)f(t)m(w)m(o)h (groups)e(de\014ned)g(b)m(y)h(the)g(grouping)g(table)g(HDUs)h(infptr)e (and)g(outfptr)h(b)m(y)f(com)m(bining)227 4111 y(their)30 b(mem)m(b)s(ers)f(in)m(to)i(a)f(single)g(grouping)f(table.)42 b(All)30 b(mem)m(b)s(er)f(HDUs)h(\(ro)m(ws\))h(are)f(copied)g(from)f (infptr)227 4224 y(to)f(outfptr.)39 b(If)26 b(mgopt)i(==)e(OPT)p 1419 4224 V 32 w(MR)m(G)p 1669 4224 V 34 w(COPY)g(then)g(infptr)g(con)m (tin)m(ues)i(to)g(exist)g(unaltered)e(after)i(the)227 4337 y(merge.)57 b(If)36 b(the)f(mgopt)i(==)e(OPT)p 1474 4337 V 31 w(MR)m(G)p 1723 4337 V 34 w(MO)m(V)i(then)e(infptr)f(is)i (deleted)h(after)f(the)g(merge.)57 b(In)35 b(b)s(oth)227 4450 y(cases,)d(the)e(GRPIDn)h(and)e(GRPLCn)h(k)m(eyw)m(ords)g(of)h (the)g(mem)m(b)s(er)e(HDUs)i(are)g(up)s(dated)e(accordingly)-8 b(.)95 4687 y Fe(int)47 b(fits_merge_groups)c(/)48 b(ffgtmg)286 4799 y(\(fitsfile)e(*infptr,)f(fitsfile)h(*outfptr,)f(int)i(mgopt,)f(>) h(int)g(*status\))0 5036 y Fi(7)81 b Fj("Compact")24 b(the)f(group)g(de\014ned)f(b)m(y)h(grouping)f(table)i(p)s(oin)m(ted)f (to)h(b)m(y)f(gfptr.)38 b(The)22 b(compaction)j(is)e(ac)m(hiev)m(ed)227 5149 y(b)m(y)37 b(merging)h(\(via)g(\014ts)p 1034 5149 V 32 w(merge)p 1303 5149 V 34 w(groups\(\)\))f(all)h(direct)g(mem)m(b)s (er)f(HDUs)g(of)h(gfptr)e(that)i(are)g(themselv)m(es)227 5262 y(grouping)i(tables.)70 b(The)40 b(cmopt)g(parameter)h(de\014nes)e (whether)g(the)i(merged)f(grouping)f(table)i(HDUs)227 5375 y(remain)j(after)h(merging)f(\(cmopt)h(==)f(OPT)p 1852 5375 V 32 w(CMT)p 2099 5375 V 32 w(MBR\))h(or)f(if)g(they)h(are)f (deleted)h(after)g(merging)227 5488 y(\(cmopt)31 b(==)f(OPT)p 916 5488 V 32 w(CMT)p 1163 5488 V 32 w(MBR)p 1409 5488 V 34 w(DEL\).)g(If)g(the)h(grouping)e(table)j(con)m(tains)f(no)f (direct)h(mem)m(b)s(er)e(HDUs)227 5601 y(that)i(are)f(themselv)m(es)h (grouping)e(tables)i(then)e(this)h(function)f(do)s(es)h(nothing.)40 b(Note)31 b(that)g(this)e(function)227 5714 y(is)i(not)f(recursiv)m(e,) h(i.e.,)h(only)f(the)f(direct)h(mem)m(b)s(er)f(HDUs)h(of)f(gfptr)g(are) h(considered)f(for)g(merging.)p eop end %%Page: 92 100 TeXDict begin 92 99 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.92) cvn H.B /DEST pdfmark end 0 299 a Fj(92)1338 b Fh(CHAPTER)29 b(8.)112 b(HIERAR)m(CHICAL)30 b(GR)m(OUPING)h(R)m(OUTINES)95 555 y Fe(int)47 b(fits_compact_group)c(/)48 b(ffgtcm)286 668 y(\(fitsfile)e(*gfptr,)f(int)i(cmopt,)f(>)i(int)f(*status\))0 945 y Fi(8)81 b Fj(V)-8 b(erify)21 b(the)h(in)m(tegrit)m(y)h(of)e(the)g (grouping)g(table)h(p)s(oin)m(ted)f(to)h(b)m(y)f(gfptr)g(to)h(mak)m(e)g (sure)e(that)i(all)g(group)f(mem)m(b)s(ers)227 1058 y(are)31 b(accessible)i(and)d(that)h(all)g(links)g(to)g(other)g(grouping)f (tables)i(are)f(v)-5 b(alid.)42 b(The)30 b(\014rstfailed)g(parameter) 227 1171 y(returns)c(the)i(mem)m(b)s(er)e(ID)h(\(ro)m(w)h(n)m(um)m(b)s (er\))e(of)i(the)f(\014rst)f(mem)m(b)s(er)h(HDU)h(to)g(fail)g(v)m (eri\014cation)g(\(if)g(p)s(ositiv)m(e)227 1284 y(v)-5 b(alue\))36 b(or)e(the)h(\014rst)e(group)h(link)g(to)i(fail)f(\(if)f (negativ)m(e)j(v)-5 b(alue\).)54 b(If)34 b(gfptr)g(is)g(successfully)h (v)m(eri\014ed)f(then)227 1397 y(\014rstfailed)d(con)m(tains)g(a)g (return)e(v)-5 b(alue)31 b(of)g(0.)95 1673 y Fe(int)47 b(fits_verify_group)c(/)48 b(ffgtvf)286 1786 y(\(fitsfile)e(*gfptr,)f (>)j(long)f(*firstfailed,)d(int)j(*status\))0 2063 y Fi(9)81 b Fj(Op)s(en)23 b(a)j(grouping)f(table)h(that)g(con)m(tains)g (the)g(mem)m(b)s(er)e(HDU)i(p)s(oin)m(ted)f(to)h(b)m(y)f(mfptr.)38 b(The)25 b(grouping)g(table)227 2176 y(to)39 b(op)s(en)e(is)h (de\014ned)f(b)m(y)h(the)g(grpid)f(parameter,)j(whic)m(h)e(con)m(tains) h(the)f(k)m(eyw)m(ord)h(index)e(v)-5 b(alue)39 b(of)f(the)227 2289 y(GRPIDn/GRPLCn)d(k)m(eyw)m(ord\(s\))g(that)h(link)f(the)g(mem)m (b)s(er)f(HDU)h(mfptr)f(to)i(the)f(grouping)f(table.)55 b(If)227 2402 y(the)30 b(grouping)f(table)h(resides)f(in)h(a)f(\014le)h (other)f(than)h(the)f(mem)m(b)s(er)g(HDUs)h(\014le)f(then)g(an)h (attempt)g(is)g(\014rst)227 2515 y(made)f(to)h(op)s(en)e(the)h(\014le)g (readwrite,)h(and)e(failing)i(that)g(readonly)-8 b(.)40 b(A)29 b(p)s(oin)m(ter)g(to)h(the)f(op)s(ened)f(grouping)227 2628 y(table)k(HDU)f(is)f(returned)f(in)h(gfptr.)227 2786 y(Note)35 b(that)g(it)f(is)g(p)s(ossible,)g(although)h(unlik)m (ely)f(and)f(undesirable,)h(for)g(the)g(GRPIDn/GRPLCn)f(k)m(ey-)227 2899 y(w)m(ords)k(in)g(a)g(mem)m(b)s(er)g(HDU)h(header)f(to)h(b)s(e)e (non-con)m(tin)m(uous,)k(e.g.,)g(GRPID1,)g(GRPID2,)g(GRPID5,)227 3012 y(GRPID6.)i(In)29 b(suc)m(h)g(cases,)i(the)f(grpid)f(index)g(v)-5 b(alue)31 b(sp)s(eci\014ed)e(in)g(the)h(function)f(call)j(shall)e(iden) m(tify)g(the)227 3125 y(\(grpid\)th)36 b(GRPID)f(v)-5 b(alue.)57 b(In)34 b(the)i(ab)s(o)m(v)m(e)h(example,)g(if)f(grpid)e(==) h(3,)j(then)d(the)g(group)g(sp)s(eci\014ed)g(b)m(y)227 3238 y(GRPID5)c(w)m(ould)g(b)s(e)e(op)s(ened.)95 3515 y Fe(int)47 b(fits_open_group)d(/)j(ffgtop)286 3628 y(\(fitsfile)f (*mfptr,)f(int)i(grpid,)f(>)i(fitsfile)d(**gfptr,)h(int)h(*status\))0 3905 y Fi(10)f Fj(Add)38 b(a)h(mem)m(b)s(er)f(HDU)i(to)f(an)g(existing) g(grouping)g(table)h(p)s(oin)m(ted)e(to)i(b)m(y)e(gfptr.)66 b(The)38 b(mem)m(b)s(er)g(HDU)227 4017 y(ma)m(y)30 b(either)g(b)s(e)f (p)s(oin)m(ted)g(to)h(mfptr)f(\(whic)m(h)g(m)m(ust)h(b)s(e)e(p)s (ositioned)i(to)g(the)f(mem)m(b)s(er)g(HDU\))i(or,)f(if)f(mfptr)227 4130 y(==)36 b(NULL,)g(iden)m(ti\014ed)g(b)m(y)g(the)g(hdup)s(os)e (parameter)i(\(the)h(HDU)g(p)s(osition)f(n)m(um)m(b)s(er,)g(Primary)f (arra)m(y)227 4243 y(==)f(1\))i(if)f(b)s(oth)f(the)h(grouping)g(table)g (and)g(the)g(mem)m(b)s(er)f(HDU)h(reside)g(in)g(the)g(same)g(FITS)f (\014le.)54 b(The)227 4356 y(new)27 b(mem)m(b)s(er)f(HDU)h(shall)g(ha)m (v)m(e)h(the)f(appropriate)g(GRPIDn)f(and)g(GRPLCn)g(k)m(eyw)m(ords)h (created)h(in)f(its)227 4469 y(header.)44 b(Note)33 b(that)f(if)g(the)g (mem)m(b)s(er)e(HDU)j(is)e(already)h(a)g(mem)m(b)s(er)f(of)h(the)g (group)f(then)g(it)h(will)g(not)g(b)s(e)227 4582 y(added)e(a)h(second)f (time.)95 4859 y Fe(int)47 b(fits_add_group_member)42 b(/)48 b(ffgtam)286 4972 y(\(fitsfile)e(*gfptr,)f(fitsfile)h(*mfptr,)g (int)h(hdupos,)f(>)h(int)g(*status\))0 5149 y SDict begin H.S end 0 5149 a 0 5149 a SDict begin 13.6 H.A end 0 5149 a 0 5149 a SDict begin [ /View [/XYZ H.V] /Dest (section.8.2) cvn H.B /DEST pdfmark end 0 5149 a 176 x Ff(8.2)135 b(Group)45 b(Mem)l(b)t(er)f(Routines)0 5578 y Fi(1)81 b Fj(Return)28 b(the)i(n)m(um)m(b)s(er)e(of)h(mem)m(b)s(er)g(HDUs)h(in) f(a)h(grouping)f(table)h(gfptr.)40 b(The)29 b(n)m(um)m(b)s(er)f(of)i (mem)m(b)s(er)e(HDUs)227 5691 y(is)j(just)e(the)i(NAXIS2)g(v)-5 b(alue)31 b(\(n)m(um)m(b)s(er)e(of)h(ro)m(ws\))h(of)g(the)f(grouping)g (table.)p eop end %%Page: 93 101 TeXDict begin 93 100 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.93) cvn H.B /DEST pdfmark end 0 299 a Fh(8.2.)72 b(GR)m(OUP)31 b(MEMBER)g(R)m(OUTINES)2295 b Fj(93)95 555 y Fe(int)47 b(fits_get_num_members)c(/)k(ffgtnm)286 668 y(\(fitsfile)f(*gfptr,)f(>) j(long)f(*nmembers,)e(int)h(*status\))0 945 y Fi(2)81 b Fj(Return)34 b(the)h(n)m(um)m(b)s(er)f(of)i(groups)e(to)i(whic)m(h)f (the)g(HDU)h(p)s(oin)m(ted)f(to)h(b)m(y)f(mfptr)f(is)i(link)m(ed,)h(as) e(de\014ned)f(b)m(y)227 1058 y(the)27 b(n)m(um)m(b)s(er)f(of)h (GRPIDn/GRPLCn)f(k)m(eyw)m(ord)i(records)e(that)i(app)s(ear)e(in)g(its) i(header.)39 b(Note)28 b(that)g(eac)m(h)227 1171 y(time)37 b(this)g(function)f(is)g(called,)k(the)c(indices)h(of)g(the)f (GRPIDn/GRPLCn)g(k)m(eyw)m(ords)h(are)g(c)m(hec)m(k)m(ed)h(to)227 1284 y(mak)m(e)29 b(sure)e(they)g(are)h(con)m(tin)m(uous)g(\(ie)h(no)e (gaps\))h(and)f(are)h(re-en)m(umerated)g(to)h(eliminate)g(gaps)f(if)f (found.)95 1674 y Fe(int)47 b(fits_get_num_groups)c(/)k(ffgmng)286 1787 y(\(fitsfile)f(*mfptr,)f(>)j(long)f(*nmembers,)e(int)h(*status\))0 2063 y Fi(3)81 b Fj(Op)s(en)26 b(a)i(mem)m(b)s(er)f(of)h(the)f (grouping)h(table)g(p)s(oin)m(ted)g(to)g(b)m(y)g(gfptr.)39 b(The)27 b(mem)m(b)s(er)g(to)i(op)s(en)e(is)g(iden)m(ti\014ed)h(b)m(y) 227 2176 y(its)i(ro)m(w)g(n)m(um)m(b)s(er)e(within)h(the)g(grouping)h (table)g(as)g(giv)m(en)g(b)m(y)g(the)f(parameter)h('mem)m(b)s(er')f (\(\014rst)h(mem)m(b)s(er)227 2289 y(==)g(1\))g(.)41 b(A)30 b(\014ts\014le)f(p)s(oin)m(ter)h(to)h(the)f(op)s(ened)f(mem)m(b) s(er)g(HDU)i(is)f(returned)f(as)h(mfptr.)39 b(Note)31 b(that)g(if)f(the)227 2402 y(mem)m(b)s(er)e(HDU)h(resides)g(in)f(a)h (FITS)f(\014le)g(di\013eren)m(t)h(from)f(the)h(grouping)f(table)h(HDU)h (then)e(the)h(mem)m(b)s(er)227 2515 y(\014le)i(is)f(\014rst)g(op)s (ened)f(readwrite)i(and,)f(failing)h(this,)g(op)s(ened)e(readonly)-8 b(.)95 2792 y Fe(int)47 b(fits_open_member)d(/)j(ffgmop)286 2905 y(\(fitsfile)f(*gfptr,)f(long)i(member,)f(>)h(fitsfile)f(**mfptr,) f(int)i(*status\))0 3182 y Fi(4)81 b Fj(Cop)m(y)27 b(\(app)s(end\))f(a) i(mem)m(b)s(er)f(HDU)h(of)f(the)h(grouping)e(table)j(p)s(oin)m(ted)e (to)h(b)m(y)f(gfptr.)39 b(The)27 b(mem)m(b)s(er)g(HDU)h(is)227 3295 y(iden)m(ti\014ed)33 b(b)m(y)g(its)h(ro)m(w)f(n)m(um)m(b)s(er)e (within)i(the)g(grouping)g(table)g(as)h(giv)m(en)g(b)m(y)e(the)i (parameter)f('mem)m(b)s(er')227 3408 y(\(\014rst)j(mem)m(b)s(er)f(==)g (1\).)58 b(The)35 b(cop)m(y)i(of)f(the)g(group)f(mem)m(b)s(er)g(HDU)i (will)f(b)s(e)f(app)s(ended)f(to)j(the)f(FITS)227 3521 y(\014le)29 b(p)s(oin)m(ted)g(to)g(b)m(y)f(mfptr,)h(and)f(up)s(on)f (return)g(mfptr)h(shall)h(p)s(oin)m(t)f(to)i(the)f(copied)g(mem)m(b)s (er)f(HDU.)h(The)227 3633 y(cp)s(opt)e(parameter)h(ma)m(y)g(tak)m(e)h (on)e(the)g(follo)m(wing)i(v)-5 b(alues:)40 b(OPT)p 2465 3633 28 4 v 32 w(MCP)p 2708 3633 V 32 w(ADD)29 b(whic)m(h)e(adds)f(a)i (new)f(en)m(try)227 3746 y(in)d(gfptr)g(for)f(the)i(copied)f(mem)m(b)s (er)g(HDU,)h(OPT)p 1907 3746 V 31 w(MCP)p 2149 3746 V 33 w(NADD)g(whic)m(h)f(do)s(es)g(not)g(add)f(an)h(en)m(try)h(in)e (gfptr)227 3859 y(for)i(the)h(copied)f(mem)m(b)s(er,)h(and)f(OPT)p 1536 3859 V 32 w(MCP)p 1779 3859 V 32 w(REPL)g(whic)m(h)g(replaces)h (the)f(original)h(mem)m(b)s(er)f(en)m(try)g(with)227 3972 y(the)31 b(copied)g(mem)m(b)s(er)e(en)m(try)-8 b(.)95 4249 y Fe(int)47 b(fits_copy_member)d(/)j(ffgmcp)286 4362 y(\(fitsfile)f(*gfptr,)f(fitsfile)h(*mfptr,)g(long)g(member,)g (int)h(cpopt,)f(>)i(int)f(*status\))0 4639 y Fi(5)81 b Fj(T)-8 b(ransfer)34 b(a)i(group)f(mem)m(b)s(er)f(HDU)i(from)f(the)h (grouping)f(table)h(p)s(oin)m(ted)f(to)h(b)m(y)f(infptr)g(to)h(the)f (grouping)227 4752 y(table)i(p)s(oin)m(ted)f(to)h(b)m(y)f(outfptr.)58 b(The)35 b(mem)m(b)s(er)h(HDU)h(to)f(transfer)g(is)g(iden)m(ti\014ed)g (b)m(y)g(its)h(ro)m(w)f(n)m(um)m(b)s(er)227 4865 y(within)42 b(infptr)f(as)i(sp)s(eci\014ed)f(b)m(y)g(the)h(parameter)g('mem)m(b)s (er')f(\(\014rst)g(mem)m(b)s(er)g(==)f(1\).)78 b(If)42 b(tfopt)h(==)227 4978 y(OPT)p 431 4978 V 32 w(MCP)p 674 4978 V 33 w(ADD)26 b(then)f(the)h(mem)m(b)s(er)e(HDU)i(is)g(made)f(a)h (mem)m(b)s(er)f(of)g(outfptr)g(and)g(remains)g(a)h(mem)m(b)s(er)227 5091 y(of)34 b(infptr.)51 b(If)34 b(tfopt)g(==)g(OPT)p 1339 5091 V 32 w(MCP)p 1582 5091 V 32 w(MO)m(V)h(then)f(the)g(mem)m(b)s (er)f(HDU)i(is)f(deleted)h(from)e(infptr)g(after)227 5204 y(the)e(transfer)f(to)h(outfptr.)95 5480 y Fe(int)47 b(fits_transfer_member)c(/)k(ffgmtf)286 5593 y(\(fitsfile)f(*infptr,)f (fitsfile)h(*outfptr,)f(long)i(member,)e(int)i(tfopt,)334 5706 y(>)h(int)e(*status\))p eop end %%Page: 94 102 TeXDict begin 94 101 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.94) cvn H.B /DEST pdfmark end 0 299 a Fj(94)1338 b Fh(CHAPTER)29 b(8.)112 b(HIERAR)m(CHICAL)30 b(GR)m(OUPING)h(R)m(OUTINES)0 555 y Fi(6)81 b Fj(Remo)m(v)m(e)31 b(a)e(mem)m(b)s(er)g(HDU)h(from)f (the)h(grouping)f(table)h(p)s(oin)m(ted)f(to)h(b)m(y)g(gfptr.)40 b(The)29 b(mem)m(b)s(er)f(HDU)i(to)h(b)s(e)227 668 y(deleted)37 b(is)e(iden)m(ti\014ed)h(b)m(y)f(its)h(ro)m(w)g(n)m(um)m(b)s(er)f(in)g (the)h(grouping)f(table)h(as)g(sp)s(eci\014ed)f(b)m(y)h(the)f (parameter)227 781 y('mem)m(b)s(er')41 b(\(\014rst)g(mem)m(b)s(er)g(==) f(1\).)74 b(The)41 b(rmopt)g(parameter)h(ma)m(y)f(tak)m(e)i(on)e(the)h (follo)m(wing)g(v)-5 b(alues:)227 894 y(OPT)p 431 894 28 4 v 32 w(RM)p 613 894 V 33 w(ENTR)d(Y)34 b(whic)m(h)e(remo)m(v)m(es) j(the)e(mem)m(b)s(er)g(HDU)h(en)m(try)f(from)g(the)g(grouping)g(table)h (and)f(up-)227 1007 y(dates)40 b(the)f(mem)m(b)s(er's)f(GRPIDn/GRPLCn)g (k)m(eyw)m(ords,)k(and)c(OPT)p 2687 1007 V 32 w(RM)p 2869 1007 V 33 w(MBR)h(whic)m(h)g(remo)m(v)m(es)h(the)227 1120 y(mem)m(b)s(er)30 b(HDU)h(en)m(try)g(from)f(the)g(grouping)g (table)i(and)d(deletes)j(the)e(mem)m(b)s(er)g(HDU)h(itself.)95 1380 y Fe(int)47 b(fits_remove_member)c(/)48 b(ffgmrm)286 1492 y(\(fitsfile)e(*gfptr,)f(long)i(member,)f(int)h(rmopt,)f(>)h(int)g (*status\))p eop end %%Page: 95 103 TeXDict begin 95 102 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.95) cvn H.B /DEST pdfmark end 0 299 a 0 464 a SDict begin H.S end 0 464 a 0 464 a SDict begin 13.6 H.A end 0 464 a 0 464 a SDict begin [ /View [/XYZ H.V] /Dest (chapter.9) cvn H.B /DEST pdfmark end 0 464 a 761 x Fg(Chapter)65 b(9)0 1687 y Fm(Sp)6 b(ecialized)77 b(CFITSIO)f(In)-6 b(terface)0 1937 y(Routines)0 2429 y Fj(The)28 b(basic)h(in)m(terface)i(routines)e (describ)s(ed)e(previously)i(are)g(recommended)f(for)h(most)g(uses,)g (but)f(the)h(routines)0 2542 y(describ)s(ed)h(in)g(this)h(c)m(hapter)g (are)h(also)f(a)m(v)-5 b(ailable)34 b(if)c(necessary)-8 b(.)43 b(Some)31 b(of)g(these)g(routines)g(p)s(erform)e(more)i(sp)s(e-) 0 2655 y(cialized)e(function)d(that)i(cannot)f(easily)h(b)s(e)e(done)h (with)f(the)h(basic)h(in)m(terface)g(routines)f(while)f(others)h (duplicate)0 2767 y(the)j(functionalit)m(y)i(of)e(the)g(basic)h (routines)f(but)f(ha)m(v)m(e)i(a)g(sligh)m(tly)g(di\013eren)m(t)g (calling)g(sequence.)41 b(See)31 b(App)s(endix)0 2880 y(B)g(for)f(the)g(de\014nition)g(of)h(eac)m(h)h(function)e(parameter.)0 3031 y SDict begin H.S end 0 3031 a 0 3031 a SDict begin 13.6 H.A end 0 3031 a 0 3031 a SDict begin [ /View [/XYZ H.V] /Dest (section.9.1) cvn H.B /DEST pdfmark end 0 3031 a 179 x Ff(9.1)135 b(FITS)44 b(File)i(Access)e(Routines)0 3446 y Fi(1)81 b Fj(Op)s(en)37 b(an)i(existing)i(FITS)d(\014le)h(residing)g (in)g(core)h(computer)f(memory)-8 b(.)68 b(This)38 b(routine)h(is)h (analogous)g(to)227 3559 y(\014ts)p 354 3559 28 4 v 33 w(op)s(en)p 577 3559 V 32 w(\014le.)55 b(The)35 b('\014lename')g(is)g (curren)m(tly)h(ignored)f(b)m(y)g(this)g(routine)g(and)g(ma)m(y)g(b)s (e)g(an)m(y)g(arbitrary)227 3672 y(string.)78 b(In)42 b(general,)47 b(the)c(application)h(m)m(ust)f(ha)m(v)m(e)h(preallo)s (cated)g(an)e(initial)i(blo)s(c)m(k)g(of)f(memory)f(to)227 3785 y(hold)i(the)h(FITS)f(\014le)h(prior)f(to)h(calling)h(this)e (routine:)70 b('memptr')44 b(p)s(oin)m(ts)g(to)i(the)e(starting)i (address)227 3898 y(and)39 b('memsize')i(giv)m(es)g(the)f(initial)h (size)f(of)g(the)g(blo)s(c)m(k)g(of)g(memory)-8 b(.)69 b('mem)p 2958 3898 V 33 w(reallo)s(c')41 b(is)f(a)g(p)s(oin)m(ter)f(to) 227 4011 y(an)c(optional)i(function)d(that)i(CFITSIO)e(can)h(call)h(to) g(allo)s(cate)i(additional)e(memory)-8 b(,)37 b(if)e(needed)f(\(only) 227 4124 y(if)41 b(mo)s(de)e(=)h(READ)m(WRITE\),)i(and)e(is)g(mo)s (deled)g(after)h(the)f(standard)g(C)g('reallo)s(c')i(function;)j(a)c(n) m(ull)227 4237 y(p)s(oin)m(ter)g(ma)m(y)g(b)s(e)f(giv)m(en)i(if)e(the)h (initial)h(allo)s(cation)h(of)e(memory)f(is)h(all)g(that)g(will)g(b)s (e)f(required)g(\(e.g.,)227 4350 y(if)35 b(the)g(\014le)g(is)g(op)s (ened)f(with)h(mo)s(de)f(=)h(READONL)-8 b(Y\).)36 b(The)e('deltasize')j (parameter)e(ma)m(y)h(b)s(e)e(used)g(to)227 4463 y(suggest)g(a)f(minim) m(um)f(amoun)m(t)h(of)g(additional)h(memory)f(that)g(should)f(b)s(e)g (allo)s(cated)j(during)d(eac)m(h)i(call)227 4575 y(to)d(the)f(memory)f (reallo)s(cation)j(function.)40 b(By)30 b(default,)g(CFITSIO)e(will)i (reallo)s(cate)j(enough)c(additional)227 4688 y(space)44 b(to)g(hold)f(the)h(en)m(tire)g(curren)m(tly)f(de\014ned)g(FITS)f (\014le)i(\(as)f(giv)m(en)i(b)m(y)e(the)h(NAXISn)e(k)m(eyw)m(ords\))227 4801 y(or)g(1)f(FITS)g(blo)s(c)m(k)h(\(=)f(2880)i(b)m(ytes\),)i(whic)m (h)d(ev)m(er)g(is)f(larger.)74 b(V)-8 b(alues)43 b(of)e(deltasize)i (less)f(than)f(2880)227 4914 y(will)31 b(b)s(e)f(ignored.)42 b(Since)31 b(the)g(memory)g(reallo)s(cation)i(op)s(eration)e(can)g(b)s (e)f(computationally)i(exp)s(ensiv)m(e,)227 5027 y(allo)s(cating)27 b(a)e(larger)g(initial)h(blo)s(c)m(k)f(of)g(memory)-8 b(,)26 b(and/or)f(sp)s(ecifying)f(a)h(larger)h(deltasize)g(v)-5 b(alue)25 b(ma)m(y)g(help)227 5140 y(to)i(reduce)f(the)g(n)m(um)m(b)s (er)e(of)i(reallo)s(cation)i(calls)f(and)f(mak)m(e)h(the)f(application) h(program)f(run)e(faster.)40 b(Note)227 5253 y(that)29 b(v)-5 b(alues)29 b(of)f(the)h(memptr)f(and)f(memsize)j(p)s(oin)m(ters) e(will)h(b)s(e)e(up)s(dated)g(b)m(y)i(CFITSIO)d(if)j(the)f(lo)s(cation) 227 5366 y(or)j(size)g(of)f(the)h(FITS)f(\014le)g(in)g(memory)g(should) g(c)m(hange)h(as)g(a)g(result)f(of)g(allo)s(cating)j(more)e(memory)-8 b(.)95 5601 y Fe(int)47 b(fits_open_memfile)c(/)48 b(ffomem)286 5714 y(\(fitsfile)e(**fptr,)f(const)i(char)f(*filename,)f(int)i(mode,)g (void)f(**memptr,)1905 5942 y Fj(95)p eop end %%Page: 96 104 TeXDict begin 96 103 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.96) cvn H.B /DEST pdfmark end 0 299 a Fj(96)1003 b Fh(CHAPTER)30 b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)334 555 y Fe(size_t)46 b(*memsize,)f(size_t)i(deltasize,) 334 668 y(void)g(*\(*mem_realloc\)\(void)42 b(*p,)47 b(size_t)f(newsize\),)f(int)i(*status\))0 927 y Fi(2)81 b Fj(Create)49 b(a)g(new)f(FITS)g(\014le)h(residing)f(in)h(core)g (computer)g(memory)-8 b(.)96 b(This)48 b(routine)g(is)h(analogous)h(to) 227 1040 y(\014ts)p 354 1040 28 4 v 33 w(create)p 623 1040 V 34 w(\014le.)40 b(In)29 b(general,)i(the)e(application)h(m)m (ust)f(ha)m(v)m(e)i(preallo)s(cated)g(an)e(initial)h(blo)s(c)m(k)g(of)f (memory)227 1152 y(to)38 b(hold)e(the)h(FITS)f(\014le)h(prior)f(to)h (calling)i(this)d(routine:)54 b('memptr')36 b(p)s(oin)m(ts)h(to)g(the)g (starting)h(address)227 1265 y(and)h('memsize')i(giv)m(es)g(the)f (initial)h(size)f(of)g(the)g(blo)s(c)m(k)g(of)g(memory)-8 b(.)69 b('mem)p 2958 1265 V 33 w(reallo)s(c')41 b(is)f(a)g(p)s(oin)m (ter)f(to)227 1378 y(an)f(optional)g(function)f(that)h(CFITSIO)e(can)i (call)h(to)f(allo)s(cate)i(additional)e(memory)-8 b(,)40 b(if)d(needed,)j(and)227 1491 y(is)34 b(mo)s(deled)f(after)h(the)g (standard)f(C)g('reallo)s(c')i(function;)g(a)f(n)m(ull)f(p)s(oin)m(ter) h(ma)m(y)g(b)s(e)f(giv)m(en)h(if)g(the)g(initial)227 1604 y(allo)s(cation)i(of)d(memory)g(is)h(all)g(that)g(will)f(b)s(e)g (required.)48 b(The)33 b('deltasize')j(parameter)d(ma)m(y)h(b)s(e)f (used)f(to)227 1717 y(suggest)i(a)f(minim)m(um)f(amoun)m(t)h(of)g (additional)h(memory)f(that)g(should)f(b)s(e)g(allo)s(cated)j(during)d (eac)m(h)i(call)227 1830 y(to)d(the)f(memory)f(reallo)s(cation)j (function.)40 b(By)30 b(default,)g(CFITSIO)e(will)i(reallo)s(cate)j (enough)c(additional)227 1943 y(space)41 b(to)g(hold)e(1)i(FITS)e(blo)s (c)m(k)h(\(=)g(2880)i(b)m(ytes\))f(and)e(v)-5 b(alues)41 b(of)f(deltasize)h(less)g(than)f(2880)h(will)g(b)s(e)227 2056 y(ignored.)f(Since)28 b(the)f(memory)h(reallo)s(cation)i(op)s (eration)e(can)g(b)s(e)f(computationally)i(exp)s(ensiv)m(e,)g(allo)s (cat-)227 2169 y(ing)36 b(a)f(larger)h(initial)h(blo)s(c)m(k)e(of)h (memory)-8 b(,)37 b(and/or)e(sp)s(ecifying)g(a)h(larger)g(deltasize)h (v)-5 b(alue)36 b(ma)m(y)f(help)g(to)227 2282 y(reduce)f(the)g(n)m(um)m (b)s(er)e(of)i(reallo)s(cation)i(calls)f(and)e(mak)m(e)i(the)f (application)h(program)f(run)e(faster.)52 b(Note)227 2395 y(that)29 b(v)-5 b(alues)29 b(of)f(the)h(memptr)f(and)f(memsize)j (p)s(oin)m(ters)e(will)h(b)s(e)e(up)s(dated)g(b)m(y)i(CFITSIO)d(if)j (the)f(lo)s(cation)227 2507 y(or)j(size)g(of)f(the)h(FITS)f(\014le)g (in)g(memory)g(should)g(c)m(hange)h(as)g(a)g(result)f(of)g(allo)s (cating)j(more)e(memory)-8 b(.)95 2766 y Fe(int)47 b (fits_create_memfile)c(/)k(ffimem)286 2879 y(\(fitsfile)f(**fptr,)f (void)i(**memptr,)334 2992 y(size_t)f(*memsize,)f(size_t)i(deltasize,) 334 3105 y(void)g(*\(*mem_realloc\)\(void)42 b(*p,)47 b(size_t)f(newsize\),)f(int)i(*status\))0 3363 y Fi(3)81 b Fj(Reop)s(en)34 b(a)i(FITS)e(\014le)h(that)h(w)m(as)f(previously)g (op)s(ened)g(with)f(\014ts)p 2414 3363 V 33 w(op)s(en)p 2637 3363 V 32 w(\014le)h(or)g(\014ts)p 3058 3363 V 33 w(create)p 3327 3363 V 34 w(\014le.)55 b(The)34 b(new)227 3476 y(\014ts\014le)i(p)s(oin)m(ter)h(ma)m(y)g(then)f(b)s(e)f(treated)j (as)e(a)h(separate)g(\014le,)h(and)e(one)h(ma)m(y)g(sim)m(ultaneously)g (read)f(or)227 3589 y(write)e(to)h(2)f(\(or)g(more\))g(di\013eren)m(t)g (extensions)g(in)g(the)g(same)g(\014le.)51 b(The)33 b(\014ts)p 2886 3589 V 32 w(op)s(en)p 3108 3589 V 32 w(\014le)h(routine)g(\(ab)s (o)m(v)m(e\))227 3702 y(automatically)k(detects)f(cases)f(where)e(a)i (previously)f(op)s(ened)f(\014le)i(is)f(b)s(eing)g(op)s(ened)f(again,)k (and)c(then)227 3815 y(in)m(ternally)e(call)f(\014ts)p 930 3815 V 33 w(reop)s(en)p 1229 3815 V 32 w(\014le,)g(so)f(programs)g (should)g(rarely)g(need)g(to)h(explicitly)h(call)g(this)e(routine.)95 4073 y Fe(int)47 b(fits_reopen_file)d(/)j(ffreopen)286 4186 y(\(fitsfile)f(*openfptr,)f(fitsfile)g(**newfptr,)g(>)j(int)f (*status\))0 4445 y Fi(4)81 b Fj(Create)24 b(a)g(new)f(FITS)g(\014le,)i (using)e(a)h(template)h(\014le)e(to)i(de\014ne)d(its)i(initial)h(size)g (and)e(structure.)37 b(The)24 b(template)227 4558 y(ma)m(y)i(b)s(e)f (another)g(FITS)g(HDU)h(or)f(an)g(ASCI)s(I)f(template)j(\014le.)39 b(If)25 b(the)g(input)g(template)h(\014le)g(name)f(p)s(oin)m(ter)227 4671 y(is)j(n)m(ull,)h(then)e(this)h(routine)f(b)s(eha)m(v)m(es)i(the)f (same)g(as)g(\014ts)p 2160 4671 V 32 w(create)p 2428 4671 V 35 w(\014le.)40 b(The)27 b(curren)m(tly)h(supp)s(orted)e(format) 227 4784 y(of)33 b(the)g(ASCI)s(I)e(template)j(\014le)e(is)h(describ)s (ed)e(under)g(the)i(\014ts)p 2350 4784 V 33 w(parse)p 2591 4784 V 32 w(template)h(routine)f(\(in)f(the)h(general)227 4897 y(Utilities)g(section\))95 5155 y Fe(int)47 b (fits_create_template)c(/)k(fftplt)286 5268 y(\(fitsfile)f(**fptr,)f (char)i(*filename,)e(char)i(*tpltfile)e(>)i(int)g(*status\))0 5527 y Fi(5)81 b Fj(P)m(arse)31 b(the)f(input)g(\014lename)g(or)g(URL)h (in)m(to)g(its)g(comp)s(onen)m(t)f(parts,)h(namely:)336 5714 y Fc(\017)46 b Fj(the)31 b(\014le)f(t)m(yp)s(e)h(\(\014le://,)h (ftp://,)f(h)m(ttp://,)h(etc\),)p eop end %%Page: 97 105 TeXDict begin 97 104 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.97) cvn H.B /DEST pdfmark end 0 299 a Fh(9.1.)72 b(FITS)30 b(FILE)g(A)m(CCESS)f(R)m(OUTINES)2244 b Fj(97)336 555 y Fc(\017)46 b Fj(the)31 b(base)f(input)g(\014le)g(name,)336 702 y Fc(\017)46 b Fj(the)31 b(name)f(of)h(the)f(output)g(\014le)h (that)g(the)f(input)g(\014le)g(is)h(to)g(b)s(e)e(copied)i(to)g(prior)f (to)h(op)s(ening,)336 848 y Fc(\017)46 b Fj(the)31 b(HDU)g(or)f (extension)h(sp)s(eci\014cation,)336 995 y Fc(\017)46 b Fj(the)31 b(\014ltering)f(sp)s(eci\014er,)336 1141 y Fc(\017)46 b Fj(the)31 b(binning)e(sp)s(eci\014er,)336 1288 y Fc(\017)46 b Fj(the)31 b(column)f(sp)s(eci\014er,)336 1434 y Fc(\017)46 b Fj(and)30 b(the)h(image)g(pixel)g(\014ltering)g(sp) s(eci\014er.)227 1623 y(A)k(n)m(ull)g(p)s(oin)m(ter)f(\(0\))i(ma)m(y)g (b)s(e)e(b)s(e)g(sp)s(eci\014ed)g(for)g(an)m(y)h(of)g(the)g(output)g (string)f(argumen)m(ts)h(that)h(are)f(not)227 1736 y(needed.)52 b(Null)34 b(strings)g(will)g(b)s(e)g(returned)f(for)h(an)m(y)g(comp)s (onen)m(ts)g(that)h(are)f(not)h(presen)m(t)f(in)g(the)g(input)227 1849 y(\014le)28 b(name.)39 b(The)27 b(calling)i(routine)e(m)m(ust)g (allo)s(cate)j(su\016cien)m(t)d(memory)g(to)h(hold)f(the)g(returned)f (c)m(haracter)227 1962 y(strings.)52 b(Allo)s(cating)37 b(the)d(string)g(lengths)h(equal)g(to)g(FLEN)p 2362 1962 28 4 v 33 w(FILENAME)f(is)g(guaran)m(teed)i(to)f(b)s(e)e(safe.)227 2075 y(These)d(routines)h(are)f(mainly)h(for)f(in)m(ternal)h(use)f(b)m (y)h(other)f(CFITSIO)f(routines.)95 2335 y Fe(int)47 b(fits_parse_input_url)c(/)k(ffiurl)286 2448 y(\(char)g(*filename,)e(>) i(char)g(*filetype,)e(char)h(*infile,)g(char)h(*outfile,)e(char)334 2561 y(*extspec,)g(char)i(*filter,)f(char)g(*binspec,)f(char)i (*colspec,)e(int)i(*status\))95 2787 y(int)g(fits_parse_input_filename) 41 b(/)48 b(ffifile)286 2900 y(\(char)f(*filename,)e(>)i(char)g (*filetype,)e(char)h(*infile,)g(char)h(*outfile,)e(char)334 3013 y(*extspec,)g(char)i(*filter,)f(char)g(*binspec,)f(char)i (*colspec,)e(char)i(*pixspec,)334 3125 y(int)g(*status\))0 3386 y Fi(6)81 b Fj(P)m(arse)33 b(the)f(input)g(\014lename)h(and)e (return)h(the)h(HDU)g(n)m(um)m(b)s(er)e(that)i(w)m(ould)f(b)s(e)g(mo)m (v)m(ed)i(to)f(if)f(the)h(\014le)f(w)m(ere)227 3499 y(op)s(ened)h(with) g(\014ts)p 878 3499 V 32 w(op)s(en)p 1100 3499 V 32 w(\014le.)49 b(The)33 b(returned)f(HDU)i(n)m(um)m(b)s(er)e(b)s(egins)h(with)g(1)g (for)g(the)g(primary)g(arra)m(y)-8 b(,)227 3612 y(so)40 b(for)f(example,)k(if)c(the)h(input)e(\014lename)i(=)f(`m)m (y\014le.\014ts[2]')i(then)e(hdun)m(um)e(=)i(3)h(will)g(b)s(e)f (returned.)227 3725 y(CFITSIO)j(do)s(es)i(not)g(op)s(en)f(the)g(\014le) h(to)h(c)m(hec)m(k)g(if)e(the)h(extension)h(actually)g(exists)f(if)g (an)f(extension)227 3838 y(n)m(um)m(b)s(er)e(is)i(sp)s(eci\014ed.)75 b(If)42 b(an)g(extension)h(name)f(is)h(included)e(in)h(the)h(\014le)f (name)g(sp)s(eci\014cation)h(\(e.g.)227 3951 y(`m)m (y\014le.\014ts[EVENTS]')i(then)e(this)h(routine)g(will)h(ha)m(v)m(e)g (to)f(op)s(en)g(the)g(FITS)f(\014le)h(and)f(lo)s(ok)i(for)f(the)227 4064 y(p)s(osition)31 b(of)f(the)h(named)f(extension,)i(then)e(close)i (\014le)e(again.)42 b(This)30 b(is)g(not)h(p)s(ossible)f(if)h(the)f (\014le)h(is)f(b)s(eing)227 4176 y(read)k(from)f(the)h(stdin)f(stream,) i(and)f(an)f(error)g(will)i(b)s(e)e(returned)f(in)i(this)f(case.)52 b(If)33 b(the)h(\014lename)g(do)s(es)227 4289 y(not)42 b(sp)s(ecify)g(an)g(explicit)h(extension)g(\(e.g.)76 b('m)m(y\014le.\014ts'\))43 b(then)f(hdun)m(um)e(=)h(-99)i(will)g(b)s (e)e(returned,)227 4402 y(whic)m(h)35 b(is)g(functionally)h(equiv)-5 b(alen)m(t)36 b(to)g(hdun)m(um)d(=)h(1.)55 b(This)34 b(routine)h(is)g(mainly)h(used)e(for)g(bac)m(kw)m(ard)227 4515 y(compatibilit)m(y)39 b(in)e(the)f(fto)s(ols)i(soft)m(w)m(are)g (pac)m(k)-5 b(age)39 b(and)d(is)g(not)h(recommended)g(for)f(general)i (use.)59 b(It)37 b(is)227 4628 y(generally)k(b)s(etter)e(and)g(more)g (e\016cien)m(t)i(to)f(\014rst)e(op)s(en)h(the)g(FITS)g(\014le)g(with)g (\014ts)p 3125 4628 V 32 w(op)s(en)p 3347 4628 V 33 w(\014le,)i(then)e (use)227 4741 y(\014ts)p 354 4741 V 33 w(get)p 507 4741 V 34 w(hdu)p 694 4741 V 31 w(n)m(um)c(to)i(determine)g(whic)m(h)f(HDU)h (in)f(the)h(\014le)f(has)g(b)s(een)g(op)s(ened,)h(rather)f(than)g (calling)227 4854 y(\014ts)p 354 4854 V 33 w(parse)p 595 4854 V 32 w(input)p 840 4854 V 32 w(url)30 b(follo)m(w)m(ed)i(b)m (y)e(a)h(call)g(to)h(\014ts)p 1967 4854 V 32 w(op)s(en)p 2189 4854 V 32 w(\014le.)143 5115 y Fe(int)47 b(fits_parse_extnum)c(/) 48 b(ffextn)334 5227 y(\(char)e(*filename,)f(>)j(int)f(*hdunum,)e(int)i (*status\))0 5488 y Fi(7)81 b Fj(P)m(arse)45 b(the)g(input)e(\014le)i (name)g(and)f(return)f(the)i(ro)s(ot)g(\014le)g(name.)83 b(The)44 b(ro)s(ot)h(name)g(includes)f(the)h(\014le)227 5601 y(t)m(yp)s(e)35 b(if)g(sp)s(eci\014ed,)h(\(e.g.)56 b('ftp://')37 b(or)e('h)m(ttp://'\))i(and)d(the)h(full)g(path)g(name,)h (to)g(the)f(exten)m(t)i(that)e(it)h(is)227 5714 y(sp)s(eci\014ed)26 b(in)f(the)i(input)e(\014lename.)39 b(It)26 b(do)s(es)g(not)g(include)g (the)g(HDU)h(name)f(or)g(n)m(um)m(b)s(er,)g(or)g(an)m(y)h(\014ltering)p eop end %%Page: 98 106 TeXDict begin 98 105 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.98) cvn H.B /DEST pdfmark end 0 299 a Fj(98)1003 b Fh(CHAPTER)30 b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)227 555 y Fj(sp)s(eci\014cations.)86 b(The)45 b(calling)h(routine)g(m)m(ust)f(allo)s(cate)i(su\016cien)m(t)f(memory)f (to)h(hold)f(the)g(returned)227 668 y(ro)s(otname)33 b(c)m(haracter)g(string.)46 b(Allo)s(cating)34 b(the)f(length)f(equal)h (to)f(FLEN)p 2817 668 28 4 v 33 w(FILENAME)h(is)f(guaran)m(teed)227 781 y(to)f(b)s(e)f(safe.)143 1022 y Fe(int)47 b(fits_parse_rootname)c (/)k(ffrtnm)334 1135 y(\(char)f(*filename,)f(>)j(char)f(*rootname,)e (int)h(*status\);)0 1375 y Fi(8)81 b Fj(T)-8 b(est)37 b(if)f(the)h(input)f(\014le)h(or)f(a)h(compressed)g(v)m(ersion)g(of)g (the)g(\014le)f(\(with)h(a)g(.gz,)j(.Z,)c(.z,)j(or)e(.zip)g (extension\))227 1488 y(exists)i(on)f(disk.)63 b(The)37 b(returned)g(v)-5 b(alue)38 b(of)g(the)h('exists')g(parameter)f(will)g (ha)m(v)m(e)i(1)e(of)g(the)g(4)g(follo)m(wing)227 1601 y(v)-5 b(alues:)370 1829 y Fe(2:)95 b(the)47 b(file)g(does)g(not)f (exist,)h(but)f(a)i(compressed)d(version)h(does)g(exist)370 1942 y(1:)95 b(the)47 b(disk)g(file)g(does)f(exist)370 2054 y(0:)95 b(neither)46 b(the)h(file)g(nor)g(a)g(compressed)e (version)h(of)h(the)g(file)g(exist)323 2167 y(-1:)94 b(the)47 b(input)g(file)f(name)h(is)g(not)g(a)g(disk)g(file)g(\(could)f (be)h(a)g(ftp,)g(http,)561 2280 y(smem,)g(or)g(mem)g(file,)f(or)h(a)h (file)e(piped)h(in)g(on)g(the)g(STDIN)f(stream\))143 2601 y(int)h(fits_file_exists)c(/)48 b(ffexist)334 2714 y(\(char)e(*filename,)f(>)j(int)f(*exists,)e(int)i(*status\);)0 2955 y Fi(9)81 b Fj(Flush)36 b(an)m(y)i(in)m(ternal)g(bu\013ers)e(of)i (data)g(to)g(the)f(output)g(FITS)g(\014le.)62 b(These)37 b(routines)g(rarely)g(need)g(to)i(b)s(e)227 3068 y(called,)i(but)36 b(can)i(b)s(e)f(useful)f(in)h(cases)i(where)d(other)i(pro)s(cesses)f (need)g(to)h(access)h(the)f(same)f(FITS)g(\014le)227 3181 y(in)j(real)i(time,)h(either)e(on)g(disk)f(or)g(in)g(memory)-8 b(.)71 b(These)41 b(routines)f(also)h(help)f(to)i(ensure)d(that)i(if)g (the)227 3294 y(application)c(program)d(subsequen)m(tly)h(ab)s(orts)f (then)h(the)g(FITS)f(\014le)h(will)g(ha)m(v)m(e)i(b)s(een)d(closed)h (prop)s(erly)-8 b(.)227 3407 y(The)43 b(\014rst)g(routine,)k(\014ts)p 1110 3407 V 33 w(\015ush)p 1332 3407 V 31 w(\014le)c(is)h(more)f (rigorous)h(and)f(completely)i(closes,)j(then)c(reop)s(ens,)i(the)227 3520 y(curren)m(t)31 b(HDU,)h(b)s(efore)e(\015ushing)g(the)h(in)m (ternal)g(bu\013ers,)f(th)m(us)h(ensuring)f(that)h(the)g(output)g(FITS) f(\014le)h(is)227 3632 y(iden)m(tical)38 b(to)e(what)f(w)m(ould)h(b)s (e)f(pro)s(duced)f(if)h(the)h(FITS)f(w)m(as)h(closed)g(at)g(that)g(p)s (oin)m(t)g(\(i.e.,)i(with)e(a)g(call)227 3745 y(to)g(\014ts)p 470 3745 V 33 w(close)p 689 3745 V 34 w(\014le\).)56 b(The)35 b(second)g(routine,)i(\014ts)p 1912 3745 V 33 w(\015ush)p 2134 3745 V 31 w(bu\013er)d(simply)h(\015ushes)f(the)h(in)m (ternal)h(CFITSIO)227 3858 y(bu\013ers)28 b(of)h(data)h(to)f(the)h (output)e(FITS)g(\014le,)i(without)f(up)s(dating)f(and)g(closing)i(the) f(curren)m(t)g(HDU.)h(This)227 3971 y(is)37 b(m)m(uc)m(h)g(faster,)i (but)e(there)g(ma)m(y)g(b)s(e)f(circumstances)i(where)e(the)h (\015ushed)f(\014le)h(do)s(es)f(not)h(completely)227 4084 y(re\015ect)31 b(the)g(\014nal)f(state)i(of)e(the)h(\014le)f(as)h (it)g(will)f(exist)i(when)d(the)h(\014le)h(is)f(actually)i(closed.)227 4231 y(A)f(t)m(ypical)h(use)e(of)h(these)g(routines)f(w)m(ould)g(b)s(e) g(to)h(\015ush)e(the)h(state)i(of)f(a)g(FITS)e(table)j(to)f(disk)f (after)h(eac)m(h)227 4344 y(ro)m(w)36 b(of)f(the)h(table)g(is)f (written.)55 b(It)36 b(is)f(recommend)g(that)h(\014ts)p 2392 4344 V 32 w(\015ush)p 2613 4344 V 32 w(\014le)f(b)s(e)g(called)h (after)g(the)f(\014rst)g(ro)m(w)227 4457 y(is)k(written,)i(then)d (\014ts)p 1023 4457 V 32 w(\015ush)p 1244 4457 V 31 w(bu\013er)g(ma)m (y)h(b)s(e)f(called)h(after)g(eac)m(h)h(subsequen)m(t)e(ro)m(w)g(is)h (written.)65 b(Note)227 4570 y(that)40 b(this)f(latter)h(routine)f (will)g(not)g(automatically)j(up)s(date)c(the)h(NAXIS2)g(k)m(eyw)m(ord) h(whic)m(h)e(records)227 4683 y(the)c(n)m(um)m(b)s(er)d(of)i(ro)m(ws)h (of)f(data)g(in)g(the)g(table,)i(so)f(this)f(k)m(eyw)m(ord)g(m)m(ust)g (b)s(e)f(explicitly)j(up)s(dated)d(b)m(y)h(the)227 4796 y(application)f(program)e(after)h(eac)m(h)h(ro)m(w)e(is)g(written.)95 5036 y Fe(int)47 b(fits_flush_file)d(/)j(ffflus)286 5149 y(\(fitsfile)f(*fptr,)g(>)h(int)g(*status\))95 5375 y(int)g (fits_flush_buffer)c(/)48 b(ffflsh)286 5488 y(\(fitsfile)e(*fptr,)g(0,) h(>)g(int)g(*status\))286 5714 y(\(Note:)94 b(The)47 b(second)f(argument)g(must)g(be)i(0\).)p eop end %%Page: 99 107 TeXDict begin 99 106 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.99) cvn H.B /DEST pdfmark end 0 299 a Fh(9.2.)72 b(HDU)31 b(A)m(CCESS)e(R)m (OUTINES)2488 b Fj(99)0 555 y Fi(10)81 b Fj(W)-8 b(rapp)s(er)30 b(function)h(for)g(global)h(initialization)i(of)e(the)f(lib)s(curl)f (library)h(used)f(when)h(accessing)h(\014les)f(with)227 668 y(the)45 b(HTTPS)e(proto)s(col.)83 b(If)44 b(an)g(HTTPS)f(\014le)h (transfer)g(is)g(to)h(b)s(e)f(p)s(erformed,)i(it)f(is)f(recommended)227 781 y(that)34 b(y)m(ou)f(call)h(this)f(once)h(near)e(the)h(start)h(of)f (y)m(our)g(program)f(b)s(efore)h(an)m(y)g(\014le)p 2997 781 28 4 v 33 w(op)s(en)f(calls,)j(and)d(b)s(efore)227 894 y(creating)e(an)m(y)e(threads.)40 b(This)27 b(is)h(NOT)f (THREAD-SAFE.)i(Returns)e(0)i(if)f(initialization)j(succeeded.)40 b(A)227 1007 y(corresp)s(onding)30 b(call)h(to)g(\014ts)p 1216 1007 V 33 w(clean)m(up)p 1549 1007 V 33 w(h)m(ttps)f(should)g(b)s (e)g(made)g(later.)95 1273 y Fe(int)47 b(fits_init_https)d(/)j(ffihtps) 286 1386 y(\(\))0 1652 y Fi(11)81 b Fj(W)-8 b(rapp)s(er)33 b(function)h(for)g(global)i(clean)m(up)e(of)g(the)h(lib)s(curl)e (library)h(used)f(when)g(accessing)j(\014les)e(with)g(the)227 1765 y(HTTPS)26 b(proto)s(col.)40 b(This)26 b(is)g(mean)m(t)h(to)h(b)s (e)d(used)h(in)g(com)m(bination)i(with)e(\014ts)p 2895 1765 V 33 w(init)p 3064 1765 V 33 w(h)m(ttps,)h(and)f(should)g(b)s(e) 227 1878 y(called)32 b(after)f(all)h(HTTPS)d(\014le)i(accessing)h(is)f (completed,)g(and)f(after)i(all)f(threads)f(are)h(completed.)43 b(This)227 1991 y(is)31 b(NOT)f(THREAD-SAFE.)h(Returns)e(0)i(up)s(on)e (successful)h(clean)m(up.)143 2257 y Fe(int)47 b(fits_cleanup_https)c (/)k(ffchtps)334 2370 y(\(\))0 2636 y Fi(12)81 b Fj(T)-8 b(oggle)45 b(the)e(v)m(erb)s(osit)m(y)h(of)f(the)g(lib)s(curl)f (library)h(diagnostic)h(output)f(when)f(accessing)i(\014les)f(with)g (the)227 2749 y(HTTPS)34 b(proto)s(col.)54 b('\015ag')36 b(=)e(1)h(turns)e(the)i(output)f(on,)i(0)f(turns)f(it)h(o\013)g(\(the)g (default\).)54 b(This)34 b(is)g(NOT)227 2862 y(THREAD-SAFE.)143 3128 y Fe(void)47 b(fits_verbose_https)c(/)k(ffvhtps)382 3241 y(\(int)f(flag\))0 3405 y SDict begin H.S end 0 3405 a 0 3405 a SDict begin 13.6 H.A end 0 3405 a 0 3405 a SDict begin [ /View [/XYZ H.V] /Dest (section.9.2) cvn H.B /DEST pdfmark end 0 3405 a 177 x Ff(9.2)135 b(HDU)46 b(Access)e(Routines)0 3827 y Fi(1)81 b Fj(Get)28 b(the)f(b)m(yte)h(o\013sets)g(in)f(the)g (FITS)f(\014le)i(to)f(the)h(start)g(of)f(the)g(header)g(and)g(the)g (start)h(and)e(end)h(of)g(the)g(data)227 3940 y(in)34 b(the)g(CHDU.)g(The)f(di\013erence)h(b)s(et)m(w)m(een)h(headstart)f (and)f(dataend)h(equals)g(the)g(size)g(of)g(the)g(CHDU.)227 4053 y(If)e(the)h(CHDU)f(is)h(the)f(last)h(HDU)g(in)f(the)h(\014le,)g (then)f(dataend)g(is)g(also)i(equal)e(to)h(the)g(size)g(of)g(the)f(en)m (tire)227 4165 y(FITS)i(\014le.)55 b(Null)35 b(p)s(oin)m(ters)g(ma)m(y) g(b)s(e)f(input)g(for)h(an)m(y)g(of)g(the)g(address)f(parameters)i(if)e (their)h(v)-5 b(alues)36 b(are)227 4278 y(not)31 b(needed.)95 4544 y Fe(int)47 b(fits_get_hduaddr)d(/)j(ffghad)94 b(\(only)46 b(supports)g(files)g(up)h(to)h(2.1)f(GB)g(in)g(size\))334 4657 y(\(fitsfile)e(*fptr,)h(>)i(long)f(*headstart,)d(long)j (*datastart,)e(long)h(*dataend,)382 4770 y(int)h(*status\))95 4996 y(int)g(fits_get_hduaddrll)c(/)48 b(ffghadll)93 b(\(supports)45 b(large)i(files\))334 5109 y(\(fitsfile)e(*fptr,)h(>)i (LONGLONG)d(*headstart,)g(LONGLONG)h(*datastart,)382 5222 y(LONGLONG)f(*dataend,)h(int)h(*status\))0 5488 y Fi(2)81 b Fj(Create)31 b(\(app)s(end\))f(a)i(new)e(empt)m(y)i(HDU)f (at)h(the)f(end)f(of)i(the)f(FITS)f(\014le.)42 b(This)31 b(is)g(no)m(w)g(the)g(CHDU)g(but)f(it)227 5601 y(is)i(completely)g (empt)m(y)g(and)f(has)g(no)g(header)g(k)m(eyw)m(ords.)43 b(It)32 b(is)f(recommended)g(that)h(\014ts)p 3344 5601 28 4 v 32 w(create)p 3612 5601 V 34 w(img)g(or)227 5714 y(\014ts)p 354 5714 V 33 w(create)p 623 5714 V 34 w(tbl)e(b)s(e)g(used) g(instead)g(of)h(this)f(routine.)p eop end %%Page: 100 108 TeXDict begin 100 107 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.100) cvn H.B /DEST pdfmark end 0 299 a Fj(100)958 b Fh(CHAPTER)30 b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)95 555 y Fe(int)47 b(fits_create_hdu)d(/)j(ffcrhd)286 668 y(\(fitsfile)f(*fptr,)g(>)h(int)g(*status\))0 932 y Fi(3)81 b Fj(Insert)22 b(a)h(new)g(IMA)m(GE)h(extension)f (immediately)i(follo)m(wing)f(the)f(CHDU,)h(or)f(insert)g(a)g(new)f (Primary)h(Arra)m(y)227 1045 y(at)30 b(the)e(b)s(eginning)g(of)h(the)g (\014le.)40 b(An)m(y)29 b(follo)m(wing)h(extensions)f(in)g(the)f (\014le)h(will)g(b)s(e)f(shifted)g(do)m(wn)h(to)g(mak)m(e)227 1158 y(ro)s(om)36 b(for)h(the)f(new)g(extension.)59 b(If)36 b(the)h(CHDU)g(is)f(the)h(last)g(HDU)g(in)f(the)h(\014le)f(then)g(the)h (new)f(image)227 1271 y(extension)31 b(will)g(simply)e(b)s(e)h(app)s (ended)e(to)j(the)f(end)g(of)g(the)g(\014le.)41 b(One)30 b(can)g(force)h(a)g(new)e(primary)g(arra)m(y)227 1384 y(to)35 b(b)s(e)d(inserted)i(at)g(the)g(b)s(eginning)f(of)g(the)h(FITS) f(\014le)g(b)m(y)h(setting)h(status)e(=)h(PREPEND)p 3432 1384 28 4 v 32 w(PRIMAR)-8 b(Y)227 1497 y(prior)25 b(to)g(calling)i (the)e(routine.)38 b(In)25 b(this)f(case)i(the)f(old)g(primary)f(arra)m (y)i(will)f(b)s(e)f(con)m(v)m(erted)j(to)e(an)g(IMA)m(GE)227 1610 y(extension.)49 b(The)32 b(new)g(extension)i(\(or)f(primary)f (arra)m(y\))h(will)h(b)s(ecome)f(the)g(CHDU.)g(Refer)g(to)h(Chapter)227 1722 y(9)d(for)f(a)h(list)g(of)f(pre-de\014ned)f(bitpix)i(v)-5 b(alues.)95 1986 y Fe(int)47 b(fits_insert_img)d(/)j(ffiimg)286 2099 y(\(fitsfile)f(*fptr,)g(int)h(bitpix,)e(int)i(naxis,)f(long)h (*naxes,)f(>)h(int)g(*status\))95 2325 y(int)g(fits_insert_imgll)c(/)48 b(ffiimgll)286 2438 y(\(fitsfile)e(*fptr,)g(int)h(bitpix,)e(int)i (naxis,)f(LONGLONG)g(*naxes,)g(>)h(int)g(*status\))0 2702 y Fi(4)81 b Fj(Insert)30 b(a)g(new)g(ASCI)s(I)f(or)i(binary)f (table)h(extension)g(immediately)h(follo)m(wing)g(the)f(CHDU.)g(An)m(y) f(follo)m(wing)227 2815 y(extensions)36 b(will)g(b)s(e)f(shifted)g(do)m (wn)g(to)h(mak)m(e)g(ro)s(om)g(for)f(the)g(new)g(extension.)57 b(If)35 b(there)h(are)f(no)h(other)227 2928 y(follo)m(wing)c (extensions)g(then)e(the)h(new)f(table)h(extension)h(will)f(simply)f(b) s(e)g(app)s(ended)f(to)i(the)g(end)f(of)h(the)227 3041 y(\014le.)42 b(If)30 b(the)h(FITS)f(\014le)g(is)h(curren)m(tly)g(empt)m (y)g(then)f(this)g(routine)h(will)g(create)h(a)f(dumm)m(y)f(primary)f (arra)m(y)227 3154 y(b)s(efore)i(app)s(ending)f(the)i(table)h(to)f(it.) 44 b(The)31 b(new)g(extension)i(will)e(b)s(ecome)h(the)g(CHDU.)g(The)f (tunit)h(and)227 3267 y(extname)39 b(parameters)g(are)f(optional)i(and) e(a)g(n)m(ull)g(p)s(oin)m(ter)h(ma)m(y)f(b)s(e)g(giv)m(en)h(if)f(they)h (are)f(not)h(de\014ned.)227 3379 y(When)32 b(inserting)g(an)g(ASCI)s(I) f(table)i(with)e(\014ts)p 1847 3379 V 33 w(insert)p 2103 3379 V 33 w(atbl,)i(a)f(n)m(ull)g(p)s(oin)m(ter)g(ma)m(y)h(giv)m(en)g (for)f(the)g(*tb)s(col)227 3492 y(parameter)23 b(in)f(whic)m(h)h(case)g (eac)m(h)h(column)e(of)h(the)g(table)g(will)g(b)s(e)f(separated)h(b)m (y)f(a)h(single)g(space)g(c)m(haracter.)227 3605 y(Similarly)-8 b(,)29 b(if)d(the)h(input)f(v)-5 b(alue)27 b(of)g(ro)m(wlen)g(is)f(0,)i (then)f(CFITSIO)e(will)i(calculate)i(the)e(default)f(ro)m(wlength)227 3718 y(based)39 b(on)g(the)g(tb)s(col)h(and)e(tt)m(yp)s(e)h(v)-5 b(alues.)67 b(Under)39 b(normal)g(circumstances,)j(the)d(nro)m(ws)f (paramen)m(ter)227 3831 y(should)31 b(ha)m(v)m(e)i(a)f(v)-5 b(alue)32 b(of)f(0;)i(CFITSIO)d(will)i(automatically)j(up)s(date)30 b(the)i(n)m(um)m(b)s(er)e(of)i(ro)m(ws)g(as)g(data)g(is)227 3944 y(written)26 b(to)h(the)f(table.)40 b(When)25 b(inserting)h(a)h (binary)e(table)h(with)g(\014ts)p 2596 3944 V 32 w(insert)p 2851 3944 V 33 w(btbl,)g(if)g(there)g(are)g(follo)m(wing)227 4057 y(extensions)f(in)f(the)h(\014le)f(and)g(if)g(the)h(table)g(con)m (tains)g(v)-5 b(ariable)25 b(length)g(arra)m(y)g(columns)f(then)g(p)s (coun)m(t)g(m)m(ust)227 4170 y(sp)s(ecify)30 b(the)h(exp)s(ected)g (\014nal)f(size)h(of)f(the)h(data)g(heap,)f(otherwise)h(p)s(coun)m(t)f (m)m(ust)h(=)f(0.)95 4434 y Fe(int)47 b(fits_insert_atbl)d(/)j(ffitab) 286 4547 y(\(fitsfile)f(*fptr,)g(LONGLONG)f(rowlen,)h(LONGLONG)g (nrows,)g(int)h(tfields,)e(char)i(*ttype[],)334 4660 y(long)g(*tbcol,)f(char)g(*tform[],)f(char)i(*tunit[],)e(char)i (*extname,)e(>)j(int)f(*status\))95 4885 y(int)g(fits_insert_btbl)d(/)j (ffibin)286 4998 y(\(fitsfile)f(*fptr,)g(LONGLONG)f(nrows,)h(int)h (tfields,)f(char)g(**ttype,)286 5111 y(char)h(**tform,)f(char)g (**tunit,)g(char)g(*extname,)g(long)g(pcount,)g(>)i(int)e(*status\))0 5375 y Fi(5)81 b Fj(Mo)s(dify)27 b(the)h(size,)h(dimensions,)f(and/or)f (data)i(t)m(yp)s(e)f(of)f(the)h(curren)m(t)g(primary)e(arra)m(y)i(or)g (image)h(extension.)227 5488 y(If)39 b(the)h(new)e(image,)44 b(as)39 b(sp)s(eci\014ed)g(b)m(y)g(the)g(input)g(argumen)m(ts,)j(is)d (larger)h(than)f(the)h(curren)m(t)f(existing)227 5601 y(image)30 b(in)e(the)g(FITS)g(\014le)g(then)g(zero)h(\014ll)f(data)h (will)g(b)s(e)f(inserted)g(at)h(the)f(end)g(of)g(the)h(curren)m(t)f (image)i(and)227 5714 y(an)m(y)35 b(follo)m(wing)h(extensions)f(will)g (b)s(e)f(mo)m(v)m(ed)i(further)d(bac)m(k)i(in)g(the)f(\014le.)54 b(Similarly)-8 b(,)36 b(if)f(the)g(new)f(image)p eop end %%Page: 101 109 TeXDict begin 101 108 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.101) cvn H.B /DEST pdfmark end 0 299 a Fh(9.2.)72 b(HDU)31 b(A)m(CCESS)e(R)m (OUTINES)2443 b Fj(101)227 555 y(is)37 b(smaller)g(than)g(the)f(curren) m(t)h(image)h(then)e(an)m(y)h(follo)m(wing)h(extensions)f(will)g(b)s(e) f(shifted)h(up)e(to)m(w)m(ards)227 668 y(the)h(b)s(eginning)f(of)h(the) g(FITS)f(\014le)h(and)f(the)h(image)h(data)f(will)h(b)s(e)e(truncated)g (to)i(the)f(new)f(size.)58 b(This)227 781 y(routine)27 b(rewrites)g(the)h(BITPIX,)f(NAXIS,)g(and)f(NAXISn)g(k)m(eyw)m(ords)i (with)f(the)g(appropriate)g(v)-5 b(alues)27 b(for)227 894 y(the)k(new)f(image.)95 1225 y Fe(int)47 b(fits_resize_img)d(/)j (ffrsim)286 1338 y(\(fitsfile)f(*fptr,)g(int)h(bitpix,)e(int)i(naxis,)f (long)h(*naxes,)f(>)h(int)g(*status\))95 1563 y(int)g (fits_resize_imgll)c(/)48 b(ffrsimll)286 1676 y(\(fitsfile)e(*fptr,)g (int)h(bitpix,)e(int)i(naxis,)f(LONGLONG)g(*naxes,)g(>)h(int)g (*status\))0 2007 y Fi(6)81 b Fj(Cop)m(y)43 b(the)h(data)h(\(and)e(not) h(the)g(header\))g(from)f(the)h(CHDU)g(asso)s(ciated)h(with)f(infptr)e (to)j(the)f(CHDU)227 2120 y(asso)s(ciated)34 b(with)e(outfptr.)47 b(This)32 b(will)g(o)m(v)m(erwrite)i(an)m(y)f(data)g(previously)g(in)f (the)h(output)f(CHDU.)h(This)227 2233 y(lo)m(w)39 b(lev)m(el)h(routine) e(is)g(used)f(b)m(y)h(\014ts)p 1510 2233 28 4 v 33 w(cop)m(y)p 1724 2233 V 33 w(hdu,)h(but)e(it)i(ma)m(y)f(also)h(b)s(e)f(useful)f(in) h(certain)h(application)227 2346 y(programs)30 b(that)h(w)m(an)m(t)g (to)g(cop)m(y)g(the)f(data)h(from)f(one)h(FITS)e(\014le)i(to)g(another) f(but)f(also)j(w)m(an)m(t)f(to)g(mo)s(dify)227 2459 y(the)h(header)g(k) m(eyw)m(ords.)46 b(The)32 b(required)f(FITS)g(header)h(k)m(eyw)m(ords)g (whic)m(h)g(de\014ne)f(the)h(structure)g(of)g(the)227 2572 y(HDU)f(m)m(ust)g(b)s(e)e(written)i(to)g(the)f(output)g(CHDU)h(b)s (efore)f(calling)i(this)e(routine.)95 2903 y Fe(int)47 b(fits_copy_data)d(/)k(ffcpdt)286 3015 y(\(fitsfile)e(*infptr,)f (fitsfile)h(*outfptr,)f(>)i(int)g(*status\))0 3346 y Fi(7)81 b Fj(Read)30 b(or)g(write)g(a)h(sp)s(eci\014ed)e(n)m(um)m(b)s (er)g(of)i(b)m(ytes)f(starting)h(at)g(the)g(sp)s(eci\014ed)e(b)m(yte)i (o\013set)g(from)f(the)g(start)h(of)227 3459 y(the)c(extension)g(data)f (unit.)39 b(These)26 b(lo)m(w)h(lev)m(el)h(routine)e(are)h(in)m(tended) f(mainly)g(for)g(accessing)i(the)e(data)h(in)227 3572 y(non-standard,)h(conforming)g(extensions,)h(and)e(should)g(not)h(b)s (e)g(used)f(for)g(standard)g(IMA)m(GE,)i(T)-8 b(ABLE,)227 3685 y(or)31 b(BINT)-8 b(ABLE)31 b(extensions.)95 4016 y Fe(int)47 b(fits_read_ext)e(/)i(ffgextn)286 4129 y(\(fitsfile)f (*fptr,)g(LONGLONG)f(offset,)h(LONGLONG)g(nbytes,)f(void)i(*buffer\))95 4242 y(int)g(fits_write_ext)d(/)k(ffpextn)286 4355 y(\(fitsfile)e (*fptr,)g(LONGLONG)f(offset,)h(LONGLONG)g(nbytes,)f(void)i(*buffer\))0 4685 y Fi(8)81 b Fj(This)34 b(routine)g(forces)h(CFITSIO)f(to)h(rescan) g(the)g(curren)m(t)g(header)f(k)m(eyw)m(ords)h(that)g(de\014ne)f(the)h (structure)227 4798 y(of)f(the)f(HDU)h(\(suc)m(h)g(as)f(the)h(NAXIS)f (and)g(BITPIX)g(k)m(eyw)m(ords\))h(so)f(that)h(it)g(reinitializes)i (the)d(in)m(ternal)227 4911 y(bu\013ers)26 b(that)h(describ)s(e)g(the)g (HDU)g(structure.)39 b(This)26 b(routine)h(is)g(useful)f(for)g (reinitializing)j(the)e(structure)227 5024 y(of)34 b(an)f(HDU)h(if)f (an)m(y)h(of)g(the)f(required)g(k)m(eyw)m(ords)g(\(e.g.,)j(NAXISn\))d (ha)m(v)m(e)i(b)s(een)e(mo)s(di\014ed.)48 b(In)33 b(practice)227 5137 y(it)e(should)e(rarely)h(b)s(e)f(necessary)h(to)h(call)g(this)f (routine)g(b)s(ecause)f(CFITSIO)g(in)m(ternally)i(calls)g(it)f(in)g (most)227 5250 y(situations.)95 5581 y Fe(int)47 b(fits_set_hdustruc)c (/)48 b(ffrdef)286 5694 y(\(fitsfile)e(*fptr,)g(>)h(int)g(*status\))141 b(\(DEPRECATED\))p eop end %%Page: 102 110 TeXDict begin 102 109 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.102) cvn H.B /DEST pdfmark end 0 299 a Fj(102)958 b Fh(CHAPTER)30 b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)0 464 y SDict begin H.S end 0 464 a 0 464 a SDict begin 13.6 H.A end 0 464 a 0 464 a SDict begin [ /View [/XYZ H.V] /Dest (section.9.3) cvn H.B /DEST pdfmark end 0 464 a 91 x Ff(9.3)135 b(Sp)t(ecialized)46 b(Header)g(Keyw)l(ord)f (Routines)0 668 y SDict begin H.S end 0 668 a 0 668 a SDict begin 13.6 H.A end 0 668 a 0 668 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.9.3.1) cvn H.B /DEST pdfmark end 0 668 a 141 x Fd(9.3.1)112 b(Header)38 b(Information)h(Routines)0 1016 y Fi(1)81 b Fj(Reserv)m(e)29 b(space)g(in)e(the)i(CHU)f(for)g (MOREKEYS)f(more)h(header)g(k)m(eyw)m(ords.)41 b(This)27 b(routine)h(ma)m(y)h(b)s(e)f(called)227 1129 y(to)34 b(allo)s(cate)h(space)e(for)f(additional)i(k)m(eyw)m(ords)f(at)g(the)g (time)g(the)g(header)f(is)h(created)g(\(prior)g(to)g(writing)227 1242 y(an)m(y)h(data\).)51 b(CFITSIO)32 b(can)i(dynamically)g(add)f (more)g(space)h(to)g(the)g(header)f(when)f(needed,)j(ho)m(w)m(ev)m(er) 227 1355 y(it)c(is)g(more)f(e\016cien)m(t)i(to)f(preallo)s(cate)h(the)f (required)f(space)h(if)f(the)g(size)i(is)e(kno)m(wn)g(in)g(adv)-5 b(ance.)95 1606 y Fe(int)47 b(fits_set_hdrsize)d(/)j(ffhdef)286 1719 y(\(fitsfile)f(*fptr,)g(int)h(morekeys,)e(>)i(int)g(*status\))0 1970 y Fi(2)81 b Fj(Return)26 b(the)h(n)m(um)m(b)s(er)e(of)j(k)m(eyw)m (ords)f(in)f(the)h(header)g(\(not)h(coun)m(ting)g(the)f(END)g(k)m(eyw)m (ord\))h(and)e(the)h(curren)m(t)227 2083 y(p)s(osition)34 b(in)g(the)g(header.)50 b(The)34 b(p)s(osition)f(is)h(the)g(n)m(um)m(b) s(er)f(of)h(the)g(k)m(eyw)m(ord)g(record)f(that)i(will)f(b)s(e)f(read) 227 2195 y(next)k(\(or)g(one)f(greater)i(than)e(the)h(p)s(osition)f(of) h(the)g(last)g(k)m(eyw)m(ord)g(that)g(w)m(as)g(read\).)59 b(A)37 b(v)-5 b(alue)36 b(of)h(1)g(is)227 2308 y(returned)29 b(if)i(the)f(p)s(oin)m(ter)h(is)f(p)s(ositioned)h(at)g(the)f(b)s (eginning)g(of)g(the)h(header.)95 2559 y Fe(int)47 b(fits_get_hdrpos)d (/)j(ffghps)286 2672 y(\(fitsfile)f(*fptr,)g(>)h(int)g(*keysexist,)e (int)i(*keynum,)e(int)i(*status\))0 2818 y SDict begin H.S end 0 2818 a 0 2818 a SDict begin 13.6 H.A end 0 2818 a 0 2818 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.9.3.2) cvn H.B /DEST pdfmark end 0 2818 a 143 x Fd(9.3.2)112 b(Read)38 b(and)h(W)-9 b(rite)36 b(the)h(Required)h(Keyw)m(ords)0 3169 y Fi(1)81 b Fj(W)-8 b(rite)34 b(the)f(required)g(extension)h (header)e(k)m(eyw)m(ords)i(in)m(to)g(the)f(CHU.)h(These)f(routines)g (are)g(not)g(required,)227 3282 y(and)g(instead)g(the)g(appropriate)g (header)g(ma)m(y)g(b)s(e)g(constructed)g(b)m(y)g(writing)g(eac)m(h)h (individual)e(k)m(eyw)m(ord)227 3395 y(in)e(the)h(prop)s(er)e (sequence.)227 3544 y(The)21 b(simpler)g(\014ts)p 842 3544 28 4 v 33 w(write)p 1077 3544 V 33 w(imghdr)f(routine)i(is)f (equiv)-5 b(alen)m(t)23 b(to)f(calling)h(\014ts)p 2727 3544 V 32 w(write)p 2961 3544 V 33 w(grphdr)d(with)h(the)h(default)227 3656 y(v)-5 b(alues)37 b(of)f(simple)g(=)g(TR)m(UE,)g(p)s(coun)m(t)g(=) g(0,)i(gcoun)m(t)f(=)f(1,)i(and)e(extend)g(=)f(TR)m(UE.)i(The)e (PCOUNT,)227 3769 y(GCOUNT)43 b(and)g(EXTEND)g(k)m(eyw)m(ords)g(are)h (not)f(required)f(in)h(the)h(primary)e(header)h(and)f(are)i(only)227 3882 y(written)38 b(if)f(p)s(coun)m(t)g(is)g(not)h(equal)f(to)i(zero,)h (gcoun)m(t)e(is)f(not)h(equal)g(to)g(zero)g(or)f(one,)j(and)c(if)i (extend)f(is)227 3995 y(TR)m(UE,)k(resp)s(ectiv)m(ely)-8 b(.)74 b(When)41 b(writing)g(to)h(an)e(IMA)m(GE)i(extension,)i(the)e (SIMPLE)e(and)g(EXTEND)227 4108 y(parameters)c(are)f(ignored.)56 b(It)35 b(is)g(recommended)g(that)h(\014ts)p 2342 4108 V 32 w(create)p 2610 4108 V 35 w(image)g(or)f(\014ts)p 3150 4108 V 33 w(create)p 3419 4108 V 34 w(tbl)g(b)s(e)g(used)227 4221 y(instead)26 b(of)f(these)h(routines)g(to)g(write)f(the)h (required)e(header)i(k)m(eyw)m(ords.)39 b(The)25 b(general)h(\014ts)p 3377 4221 V 33 w(write)p 3612 4221 V 33 w(exthdr)227 4334 y(routine)31 b(ma)m(y)g(b)s(e)e(used)h(to)h(write)g(the)f(header)g (of)h(an)m(y)g(conforming)f(FITS)g(extension.)95 4585 y Fe(int)47 b(fits_write_imghdr)c(/)48 b(ffphps)286 4698 y(\(fitsfile)e(*fptr,)g(int)h(bitpix,)e(int)i(naxis,)f(long)h(*naxes,)f (>)h(int)g(*status\))95 4924 y(int)g(fits_write_imghdrll)c(/)k (ffphpsll)286 5036 y(\(fitsfile)f(*fptr,)g(int)h(bitpix,)e(int)i (naxis,)f(LONGLONG)g(*naxes,)g(>)h(int)g(*status\))95 5262 y(int)g(fits_write_grphdr)c(/)48 b(ffphpr)286 5375 y(\(fitsfile)e(*fptr,)g(int)h(simple,)e(int)i(bitpix,)f(int)h(naxis,)f (long)h(*naxes,)334 5488 y(LONGLONG)f(pcount,)f(LONGLONG)h(gcount,)g (int)h(extend,)f(>)h(int)g(*status\))95 5714 y(int)g (fits_write_grphdrll)c(/)k(ffphprll)p eop end %%Page: 103 111 TeXDict begin 103 110 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.103) cvn H.B /DEST pdfmark end 0 299 a Fh(9.3.)72 b(SPECIALIZED)29 b(HEADER)i(KEYW)m(ORD)g(R)m(OUTINES)1465 b Fj(103)286 555 y Fe(\(fitsfile)46 b(*fptr,)g(int)h(simple,)e(int)i(bitpix,)f(int)h (naxis,)f(LONGLONG)g(*naxes,)334 668 y(LONGLONG)g(pcount,)f(LONGLONG)h (gcount,)g(int)h(extend,)f(>)h(int)g(*status\))95 894 y(int)g(fits_write_exthdr)c(/ffphext)286 1007 y(\(fitsfile)j(*fptr,)g (char)g(*xtension,)f(int)i(bitpix,)f(int)h(naxis,)f(long)h(*naxes,)334 1120 y(LONGLONG)f(pcount,)f(LONGLONG)h(gcount,)g(>)h(int)g(*status\))0 1490 y Fi(2)81 b Fj(W)-8 b(rite)30 b(the)g(ASCI)s(I)d(table)k(header)e (k)m(eyw)m(ords)g(in)m(to)i(the)e(CHU.)h(The)e(optional)j(TUNITn)d(and) h(EXTNAME)227 1603 y(k)m(eyw)m(ords)f(are)h(written)e(only)h(if)g(the)g (input)f(p)s(oin)m(ters)h(are)g(not)g(n)m(ull.)40 b(A)27 b(n)m(ull)h(p)s(oin)m(ter)g(ma)m(y)g(giv)m(en)h(for)f(the)227 1716 y(*tb)s(col)37 b(parameter)g(in)f(whic)m(h)g(case)i(a)e(single)h (space)g(will)g(b)s(e)f(inserted)g(b)s(et)m(w)m(een)h(eac)m(h)g(column) f(of)h(the)227 1829 y(table.)57 b(Similarly)-8 b(,)37 b(if)f(ro)m(wlen)f(is)h(giv)m(en)g(=)f(0,)i(then)e(CFITSIO)f(will)i (calculate)h(the)f(default)f(ro)m(wlength)227 1942 y(based)30 b(on)h(the)f(tb)s(col)h(and)f(tt)m(yp)s(e)h(v)-5 b(alues.)95 2199 y Fe(int)47 b(fits_write_atblhdr)c(/)48 b(ffphtb)286 2312 y(\(fitsfile)e(*fptr,)g(LONGLONG)f(rowlen,)h(LONGLONG)g(nrows,)g (int)h(tfields,)e(char)i(**ttype,)334 2425 y(long)g(*tbcol,)f(char)g (**tform,)g(char)g(**tunit,)g(char)h(*extname,)e(>)i(int)g(*status\))0 2683 y Fi(3)81 b Fj(W)-8 b(rite)30 b(the)f(binary)g(table)h(header)e(k) m(eyw)m(ords)i(in)m(to)g(the)f(CHU.)g(The)g(optional)h(TUNITn)e(and)h (EXTNAME)227 2796 y(k)m(eyw)m(ords)35 b(are)g(written)g(only)g(if)f (the)h(input)f(p)s(oin)m(ters)g(are)h(not)g(n)m(ull.)53 b(The)35 b(p)s(coun)m(t)f(parameter,)i(whic)m(h)227 2909 y(sp)s(eci\014es)h(the)g(size)g(of)g(the)g(v)-5 b(ariable)38 b(length)f(arra)m(y)g(heap,)h(should)e(initially)i(=)f(0;)j(CFITSIO)c (will)h(au-)227 3022 y(tomatically)d(up)s(date)d(the)g(PCOUNT)f(k)m (eyw)m(ord)i(v)-5 b(alue)32 b(if)f(an)m(y)g(v)-5 b(ariable)32 b(length)g(arra)m(y)g(data)g(is)f(written)227 3135 y(to)g(the)e(heap.) 41 b(The)29 b(TF)m(ORM)g(k)m(eyw)m(ord)h(v)-5 b(alue)30 b(for)g(v)-5 b(ariable)30 b(length)g(v)m(ector)h(columns)e(should)g(ha) m(v)m(e)i(the)227 3247 y(form)c('Pt\(len\)')j(or)d('1Pt\(len\)')j (where)d(`t')h(is)g(the)g(data)g(t)m(yp)s(e)g(co)s(de)f(letter)i (\(A,I,J,E,D,)g(etc.\))42 b(and)27 b(`len')h(is)227 3360 y(an)g(in)m(teger)i(sp)s(ecifying)e(the)g(maxim)m(um)g(length)g(of)h (the)f(v)m(ectors)h(in)f(that)h(column)f(\(len)g(m)m(ust)g(b)s(e)g (greater)227 3473 y(than)36 b(or)g(equal)h(to)g(the)f(longest)i(v)m (ector)f(in)f(the)h(column\).)58 b(If)36 b(`len')g(is)h(not)f(sp)s (eci\014ed)g(when)f(the)h(table)227 3586 y(is)c(created)g(\(e.g.,)h (the)f(input)e(TF)m(ORMn)h(v)-5 b(alue)32 b(is)f(just)g('1Pt'\))i(then) e(CFITSIO)f(will)h(scan)h(the)f(column)227 3699 y(when)f(the)h(table)h (is)f(\014rst)f(closed)h(and)g(will)g(app)s(end)e(the)i(maxim)m(um)g (length)g(to)g(the)g(TF)m(ORM)g(k)m(eyw)m(ord)227 3812 y(v)-5 b(alue.)41 b(Note)30 b(that)f(if)f(the)h(table)g(is)g(subsequen) m(tly)f(mo)s(di\014ed)f(to)j(increase)f(the)g(maxim)m(um)f(length)h(of) g(the)227 3925 y(v)m(ectors)39 b(then)e(the)g(mo)s(difying)g(program)g (is)g(resp)s(onsible)g(for)g(also)h(up)s(dating)e(the)i(TF)m(ORM)f(k)m (eyw)m(ord)227 4038 y(v)-5 b(alue.)95 4295 y Fe(int)47 b(fits_write_btblhdr)c(/)48 b(ffphbn)286 4408 y(\(fitsfile)e(*fptr,)g (LONGLONG)f(nrows,)h(int)h(tfields,)f(char)g(**ttype,)334 4521 y(char)h(**tform,)e(char)i(**tunit,)e(char)i(*extname,)e(LONGLONG) h(pcount,)g(>)h(int)g(*status\))0 4779 y Fi(4)81 b Fj(Read)30 b(the)h(required)e(k)m(eyw)m(ords)i(from)f(the)h(CHDU)f(\(image)j(or)d (table\).)42 b(When)30 b(reading)h(from)f(an)g(IMA)m(GE)227 4892 y(extension)24 b(the)g(SIMPLE)e(and)h(EXTEND)g(parameters)h(are)f (ignored.)39 b(A)23 b(n)m(ull)g(p)s(oin)m(ter)h(ma)m(y)g(b)s(e)e (supplied)227 5005 y(for)30 b(an)m(y)h(of)g(the)f(returned)f (parameters)i(that)g(are)g(not)f(needed.)95 5262 y Fe(int)47 b(fits_read_imghdr)d(/)j(ffghpr)286 5375 y(\(fitsfile)f(*fptr,)g(int)h (maxdim,)e(>)j(int)f(*simple,)e(int)i(*bitpix,)f(int)h(*naxis,)334 5488 y(long)g(*naxes,)f(long)g(*pcount,)g(long)g(*gcount,)g(int)h (*extend,)e(int)i(*status\))95 5714 y(int)g(fits_read_imghdrll)c(/)48 b(ffghprll)p eop end %%Page: 104 112 TeXDict begin 104 111 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.104) cvn H.B /DEST pdfmark end 0 299 a Fj(104)958 b Fh(CHAPTER)30 b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)286 555 y Fe(\(fitsfile)46 b(*fptr,)g(int)h(maxdim,)e(>)j (int)f(*simple,)e(int)i(*bitpix,)f(int)h(*naxis,)334 668 y(LONGLONG)f(*naxes,)f(long)i(*pcount,)f(long)g(*gcount,)g(int)h (*extend,)e(int)i(*status\))95 894 y(int)g(fits_read_atblhdr)c(/)48 b(ffghtb)286 1007 y(\(fitsfile)e(*fptr,int)f(maxdim,)h(>)h(long)g (*rowlen,)e(long)i(*nrows,)334 1120 y(int)g(*tfields,)e(char)i (**ttype,)e(LONGLONG)h(*tbcol,)g(char)g(**tform,)g(char)h(**tunit,)334 1233 y(char)g(*extname,)93 b(int)47 b(*status\))95 1458 y(int)g(fits_read_atblhdrll)c(/)k(ffghtbll)286 1571 y(\(fitsfile)f (*fptr,int)f(maxdim,)h(>)h(LONGLONG)f(*rowlen,)f(LONGLONG)h(*nrows,)334 1684 y(int)h(*tfields,)e(char)i(**ttype,)e(long)i(*tbcol,)f(char)h (**tform,)e(char)i(**tunit,)334 1797 y(char)g(*extname,)93 b(int)47 b(*status\))95 2023 y(int)g(fits_read_btblhdr)c(/)48 b(ffghbn)286 2136 y(\(fitsfile)e(*fptr,)g(int)h(maxdim,)e(>)j(long)f (*nrows,)e(int)i(*tfields,)334 2249 y(char)g(**ttype,)e(char)i (**tform,)e(char)i(**tunit,)f(char)g(*extname,)334 2362 y(long)h(*pcount,)e(int)i(*status\))95 2588 y(int)g (fits_read_btblhdrll)c(/)k(ffghbnll)286 2700 y(\(fitsfile)f(*fptr,)g (int)h(maxdim,)e(>)j(LONGLONG)d(*nrows,)h(int)h(*tfields,)334 2813 y(char)g(**ttype,)e(char)i(**tform,)e(char)i(**tunit,)f(char)g (*extname,)334 2926 y(long)h(*pcount,)e(int)i(*status\))0 3070 y SDict begin H.S end 0 3070 a 0 3070 a SDict begin 13.6 H.A end 0 3070 a 0 3070 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.9.3.3) cvn H.B /DEST pdfmark end 0 3070 a 143 x Fd(9.3.3)112 b(W)-9 b(rite)37 b(Keyw)m(ord)g(Routines)0 3432 y Fj(These)32 b(routines)h(simply)f(app)s(end)f(a)h(new)g(k)m(eyw) m(ord)h(to)h(the)e(header)h(and)f(do)g(not)h(c)m(hec)m(k)h(to)f(see)g (if)g(a)f(k)m(eyw)m(ord)0 3545 y(with)d(the)g(same)h(name)f(already)h (exists.)41 b(In)28 b(general)i(it)g(is)f(preferable)g(to)h(use)f(the)h (\014ts)p 3009 3545 28 4 v 32 w(up)s(date)p 3317 3545 V 32 w(k)m(ey)g(routine)f(to)0 3658 y(ensure)34 b(that)h(the)g(same)g (k)m(eyw)m(ord)g(is)f(not)h(written)g(more)g(than)f(once)h(to)h(the)e (header.)54 b(See)34 b(App)s(endix)f(B)i(for)0 3771 y(the)c (de\014nition)f(of)g(the)h(parameters)f(used)g(in)g(these)h(routines.)0 4009 y Fi(1)81 b Fj(W)-8 b(rite)30 b(\(app)s(end\))f(a)g(new)g(k)m(eyw) m(ord)h(of)g(the)f(appropriate)g(data)h(t)m(yp)s(e)g(in)m(to)g(the)g (CHU.)f(A)h(n)m(ull)f(p)s(oin)m(ter)g(ma)m(y)227 4121 y(b)s(e)35 b(en)m(tered)h(for)f(the)h(commen)m(t)h(parameter,)g(whic)m (h)e(will)h(cause)g(the)g(commen)m(t)g(\014eld)f(of)h(the)f(k)m(eyw)m (ord)227 4234 y(to)43 b(b)s(e)e(left)i(blank.)76 b(The)41 b(\015t,)k(dbl,)f(cmp,)h(and)d(dblcmp)f(v)m(ersions)h(of)g(this)g (routine)g(ha)m(v)m(e)h(the)g(added)227 4347 y(feature)33 b(that)g(if)g(the)f('decimals')i(parameter)f(is)g(negativ)m(e,)i(then)d (the)h('G')g(displa)m(y)g(format)g(rather)f(then)227 4460 y(the)i('E')f(format)h(will)f(b)s(e)g(used)f(when)g(constructing)i (the)g(k)m(eyw)m(ord)f(v)-5 b(alue,)35 b(taking)f(the)g(absolute)f(v)-5 b(alue)227 4573 y(of)34 b('decimals')h(for)e(the)h(precision.)51 b(This)33 b(will)h(suppress)d(trailing)k(zeros,)g(and)e(will)h(use)g(a) g(\014xed)f(format)227 4686 y(rather)e(than)f(an)g(exp)s(onen)m(tial)h (format,)g(dep)s(ending)e(on)h(the)h(magnitude)f(of)h(the)g(v)-5 b(alue.)95 4924 y Fe(int)47 b(fits_write_key_str)c(/)48 b(ffpkys)286 5036 y(\(fitsfile)e(*fptr,)g(char)g(*keyname,)g(char)g (*value,)g(char)h(*comment,)334 5149 y(>)h(int)e(*status\))95 5375 y(int)h(fits_write_key_[log,)c(lng])j(/)95 b(ffpky[lj])286 5488 y(\(fitsfile)46 b(*fptr,)g(char)g(*keyname,)g(DTYPE)g(numval,)g (char)g(*comment,)334 5601 y(>)i(int)e(*status\))p eop end %%Page: 105 113 TeXDict begin 105 112 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.105) cvn H.B /DEST pdfmark end 0 299 a Fh(9.3.)72 b(SPECIALIZED)29 b(HEADER)i(KEYW)m(ORD)g(R)m(OUTINES)1465 b Fj(105)95 555 y Fe(int)47 b(fits_write_key_[flt,)c(dbl,)j(fixflg,)g(fixdbl])g(/)h (ffpky[edfg])286 668 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(DTYPE)g (numval,)g(int)h(decimals,)286 781 y(char)g(*comment,)e(>)j(int)f (*status\))95 1007 y(int)g(fits_write_key_[cmp,)c(dblcmp,)i(fixcmp,)h (fixdblcmp])f(/)j(ffpk[yc,ym,fc,fm])286 1120 y(\(fitsfile)e(*fptr,)g (char)g(*keyname,)g(DTYPE)g(*numval,)g(int)g(decimals,)286 1233 y(char)h(*comment,)e(>)j(int)f(*status\))0 1503 y Fi(2)81 b Fj(W)-8 b(rite)30 b(\(app)s(end\))e(a)i(string)f(v)-5 b(alued)29 b(k)m(eyw)m(ord)h(in)m(to)g(the)f(CHU)h(whic)m(h)e(ma)m(y)i (b)s(e)f(longer)h(than)e(68)i(c)m(haracters)227 1616 y(in)43 b(length.)80 b(This)42 b(uses)h(the)g(Long)h(String)e(Keyw)m (ord)h(con)m(v)m(en)m(tion)j(that)d(is)h(describ)s(ed)e(in)h(the`Lo)s (cal)227 1729 y(FITS)38 b(Con)m(v)m(en)m(tions')i(section)g(in)f (Chapter)f(4.)66 b(Since)38 b(this)h(uses)f(a)h(non-standard)f(FITS)g (con)m(v)m(en)m(tion)227 1842 y(to)45 b(enco)s(de)f(the)g(long)h(k)m (eyw)m(ord)f(string,)k(programs)43 b(whic)m(h)h(use)g(this)g(routine)g (should)f(also)h(call)i(the)227 1955 y(\014ts)p 354 1955 28 4 v 33 w(write)p 589 1955 V 33 w(k)m(ey)p 755 1955 V 33 w(longw)m(arn)26 b(routine)f(to)h(add)f(some)h(COMMENT)f(k)m(eyw)m (ords)g(to)h(w)m(arn)f(users)g(of)g(the)h(FITS)227 2068 y(\014le)43 b(that)h(this)e(con)m(v)m(en)m(tion)j(is)e(b)s(eing)f (used.)78 b(The)42 b(\014ts)p 2220 2068 V 32 w(write)p 2454 2068 V 33 w(k)m(ey)p 2620 2068 V 34 w(longw)m(arn)h(routine)g (also)h(writes)f(a)227 2180 y(k)m(eyw)m(ord)29 b(called)g(LONGSTRN)e (to)i(record)f(the)g(v)m(ersion)h(of)f(the)g(longstring)h(con)m(v)m(en) m(tion)h(that)f(has)f(b)s(een)227 2293 y(used,)35 b(in)f(case)i(a)f (new)e(con)m(v)m(en)m(tion)k(is)e(adopted)f(at)h(some)g(p)s(oin)m(t)f (in)h(the)f(future.)52 b(If)34 b(the)h(LONGSTRN)227 2406 y(k)m(eyw)m(ord)43 b(is)g(already)g(presen)m(t)g(in)g(the)f(header,)k (then)d(\014ts)p 2332 2406 V 32 w(write)p 2566 2406 V 33 w(k)m(ey)p 2732 2406 V 34 w(longw)m(arn)g(will)g(simply)f(return)227 2519 y(without)31 b(doing)f(an)m(ything.)95 2789 y Fe(int)47 b(fits_write_key_longstr)42 b(/)48 b(ffpkls)286 2902 y(\(fitsfile)e(*fptr,)g(char)g(*keyname,)g(char)g(*longstr,)g(char)g (*comment,)334 3015 y(>)i(int)e(*status\))95 3241 y(int)h (fits_write_key_longwarn)42 b(/)47 b(ffplsw)286 3354 y(\(fitsfile)f(*fptr,)g(>)h(int)g(*status\))0 3624 y Fi(3)81 b Fj(W)-8 b(rite)38 b(\(app)s(end\))d(a)i(n)m(um)m(b)s(ered)e (sequence)i(of)g(k)m(eyw)m(ords)g(in)m(to)g(the)g(CHU.)g(The)f (starting)h(index)f(n)m(um)m(b)s(er)227 3737 y(\(nstart\))30 b(m)m(ust)e(b)s(e)g(greater)i(than)f(0.)40 b(One)28 b(ma)m(y)i(app)s (end)d(the)h(same)i(commen)m(t)f(to)h(ev)m(ery)f(k)m(eyw)m(ord)g(\(and) 227 3850 y(eliminate)35 b(the)f(need)f(to)h(ha)m(v)m(e)g(an)f(arra)m(y) h(of)f(iden)m(tical)j(commen)m(t)e(strings,)g(one)f(for)h(eac)m(h)g(k)m (eyw)m(ord\))g(b)m(y)227 3963 y(including)24 b(the)h(amp)s(ersand)e(c)m (haracter)j(as)e(the)h(last)g(non-blank)f(c)m(haracter)i(in)e(the)g (\(\014rst\))h(COMMENTS)227 4076 y(string)e(parameter.)38 b(This)22 b(same)h(string)f(will)h(then)f(b)s(e)g(used)f(for)h(the)h (commen)m(t)g(\014eld)f(in)g(all)i(the)e(k)m(eyw)m(ords.)227 4189 y(One)32 b(ma)m(y)h(also)g(en)m(ter)f(a)h(n)m(ull)f(p)s(oin)m(ter) g(for)g(the)g(commen)m(t)h(parameter)g(to)f(lea)m(v)m(e)j(the)d(commen) m(t)h(\014eld)f(of)227 4302 y(the)f(k)m(eyw)m(ord)g(blank.)95 4572 y Fe(int)47 b(fits_write_keys_str)c(/)k(ffpkns)286 4685 y(\(fitsfile)f(*fptr,)g(char)g(*keyroot,)g(int)h(nstart,)e(int)i (nkeys,)334 4798 y(char)g(**value,)e(char)i(**comment,)e(>)i(int)g (*status\))95 5024 y(int)g(fits_write_keys_[log,)42 b(lng])47 b(/)g(ffpkn[lj])286 5137 y(\(fitsfile)f(*fptr,)g(char)g(*keyroot,)g (int)h(nstart,)e(int)i(nkeys,)334 5250 y(DTYPE)f(*numval,)g(char)h (**comment,)e(int)i(*status\))95 5475 y(int)g(fits_write_keys_[flt,)42 b(dbl,)47 b(fixflg,)f(fixdbl])g(/)h(ffpkne[edfg])286 5588 y(\(fitsfile)f(*fptr,)g(char)g(*keyroot,)g(int)h(nstart,)e(int)i (nkey,)334 5701 y(DTYPE)f(*numval,)g(int)h(decimals,)e(char)i (**comment,)e(>)i(int)g(*status\))p eop end %%Page: 106 114 TeXDict begin 106 113 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.106) cvn H.B /DEST pdfmark end 0 299 a Fj(106)958 b Fh(CHAPTER)30 b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)0 555 y Fi(4)81 b Fj(Cop)m(y)21 b(an)h(indexed)f(k)m(eyw) m(ord)i(from)e(one)h(HDU)h(to)f(another,)i(mo)s(difying)e(the)g(index)f (n)m(um)m(b)s(er)f(of)i(the)g(k)m(eyw)m(ord)227 668 y(name)37 b(in)f(the)g(pro)s(cess.)58 b(F)-8 b(or)37 b(example,)i(this)d(routine) h(could)f(read)g(the)h(TLMIN3)f(k)m(eyw)m(ord)h(from)f(the)227 781 y(input)30 b(HDU)h(\(b)m(y)g(giving)h(k)m(eyro)s(ot)f(=)g(`TLMIN')g (and)f(inn)m(um)f(=)h(3\))i(and)e(write)h(it)g(to)g(the)g(output)f(HDU) 227 894 y(with)36 b(the)g(k)m(eyw)m(ord)h(name)f(TLMIN4)g(\(b)m(y)g (setting)i(outn)m(um)d(=)h(4\).)58 b(If)36 b(the)g(input)f(k)m(eyw)m (ord)i(do)s(es)f(not)227 1007 y(exist,)c(then)e(this)g(routine)g (simply)g(returns)f(without)i(indicating)g(an)f(error.)95 1263 y Fe(int)47 b(fits_copy_key)e(/)i(ffcpky)286 1376 y(\(fitsfile)f(*infptr,)f(fitsfile)h(*outfptr,)f(int)i(innum,)f(int)h (outnum,)334 1489 y(char)g(*keyroot,)e(>)i(int)g(*status\))0 1746 y Fi(5)81 b Fj(W)-8 b(rite)30 b(\(app)s(end\))f(a)h(`triple)f (precision')h(k)m(eyw)m(ord)g(in)m(to)g(the)g(CHU)f(in)g(F28.16)j (format.)41 b(The)29 b(\015oating)h(p)s(oin)m(t)227 1859 y(k)m(eyw)m(ord)g(v)-5 b(alue)30 b(is)f(constructed)h(b)m(y)f (concatenating)j(the)d(input)g(in)m(teger)i(v)-5 b(alue)29 b(with)g(the)h(input)e(double)227 1972 y(precision)35 b(fraction)f(v)-5 b(alue)35 b(\(whic)m(h)f(m)m(ust)g(ha)m(v)m(e)i(a)e (v)-5 b(alue)35 b(b)s(et)m(w)m(een)f(0.0)i(and)d(1.0\).)53 b(The)34 b(\013gkyt)h(routine)227 2085 y(should)d(b)s(e)h(used)f(to)i (read)f(this)g(k)m(eyw)m(ord)h(v)-5 b(alue,)35 b(b)s(ecause)e(the)g (other)h(k)m(eyw)m(ord)f(reading)h(routines)f(will)227 2197 y(not)e(preserv)m(e)f(the)h(full)f(precision)h(of)f(the)h(v)-5 b(alue.)95 2454 y Fe(int)47 b(fits_write_key_triple)42 b(/)48 b(ffpkyt)286 2567 y(\(fitsfile)e(*fptr,)g(char)g(*keyname,)g (long)g(intval,)g(double)g(frac,)334 2680 y(char)h(*comment,)e(>)i(int) g(*status\))0 2936 y Fi(6)81 b Fj(W)-8 b(rite)37 b(k)m(eyw)m(ords)f(to) h(the)f(CHDU)g(that)h(are)f(de\014ned)f(in)h(an)g(ASCI)s(I)e(template)j (\014le.)58 b(The)35 b(format)i(of)f(the)227 3049 y(template)c(\014le)f (is)f(describ)s(ed)f(under)g(the)i(\014ts)p 1788 3049 28 4 v 32 w(parse)p 2028 3049 V 33 w(template)g(routine.)95 3306 y Fe(int)47 b(fits_write_key_template)42 b(/)47 b(ffpktp)286 3419 y(\(fitsfile)f(*fptr,)g(const)g(char)h(*filename,)e (>)i(int)g(*status\))0 3566 y SDict begin H.S end 0 3566 a 0 3566 a SDict begin 13.6 H.A end 0 3566 a 0 3566 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.9.3.4) cvn H.B /DEST pdfmark end 0 3566 a 143 x Fd(9.3.4)112 b(Insert)38 b(Keyw)m(ord)f (Routines)0 3928 y Fj(These)42 b(insert)h(routines)f(are)h(somewhat)g (less)f(e\016cien)m(t)i(than)f(the)f(`up)s(date')g(or)h(`write')g(k)m (eyw)m(ord)g(routines)0 4041 y(b)s(ecause)30 b(the)g(follo)m(wing)i(k)m (eyw)m(ords)e(in)g(the)g(header)g(m)m(ust)g(b)s(e)f(shifted)h(do)m(wn)f (to)i(mak)m(e)g(ro)s(om)f(for)g(the)g(inserted)0 4154 y(k)m(eyw)m(ord.)41 b(See)31 b(App)s(endix)d(B)j(for)f(the)h (de\014nition)f(of)g(the)h(parameters)g(used)e(in)h(these)h(routines.)0 4410 y Fi(1)81 b Fj(Insert)26 b(a)h(new)f(k)m(eyw)m(ord)h(record)g(in)m (to)g(the)g(CHU)g(at)g(the)g(sp)s(eci\014ed)f(p)s(osition)h(\(i.e.,)i (immediately)f(preceding)227 4523 y(the)j(\(k)m(eyn)m(um\)th)g(k)m(eyw) m(ord)g(in)f(the)g(header.\))95 4780 y Fe(int)47 b(fits_insert_record)c (/)48 b(ffirec)286 4893 y(\(fitsfile)e(*fptr,)g(int)h(keynum,)e(char)i (*card,)f(>)i(int)f(*status\))0 5149 y Fi(2)81 b Fj(Insert)24 b(a)h(new)g(k)m(eyw)m(ord)g(in)m(to)h(the)f(CHU.)g(The)g(new)f(k)m(eyw) m(ord)i(is)f(inserted)f(immediately)j(follo)m(wing)f(the)f(last)227 5262 y(k)m(eyw)m(ord)i(that)f(has)f(b)s(een)h(read)f(from)h(the)g (header.)39 b(The)25 b(`longstr')i(v)m(ersion)f(has)f(the)h(same)g (functionalit)m(y)227 5375 y(as)33 b(the)g(`str')f(v)m(ersion)h(except) h(that)f(it)g(also)g(supp)s(orts)e(the)h(lo)s(cal)i(long)f(string)g(k)m (eyw)m(ord)g(con)m(v)m(en)m(tion)h(for)227 5488 y(strings)29 b(longer)g(than)g(68)h(c)m(haracters.)41 b(A)29 b(n)m(ull)g(p)s(oin)m (ter)g(ma)m(y)g(b)s(e)g(en)m(tered)g(for)g(the)g(commen)m(t)g (parameter)227 5601 y(whic)m(h)d(will)f(cause)h(the)g(commen)m(t)h (\014eld)e(to)h(b)s(e)f(left)h(blank.)39 b(The)25 b(\015t,)h(dbl,)g (cmp,)h(and)e(dblcmp)f(v)m(ersions)i(of)227 5714 y(this)k(routine)g(ha) m(v)m(e)h(the)e(added)g(feature)i(that)f(if)g(the)g('decimals')h (parameter)f(is)g(negativ)m(e,)i(then)d(the)h('G')p eop end %%Page: 107 115 TeXDict begin 107 114 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.107) cvn H.B /DEST pdfmark end 0 299 a Fh(9.3.)72 b(SPECIALIZED)29 b(HEADER)i(KEYW)m(ORD)g(R)m(OUTINES)1465 b Fj(107)227 555 y(displa)m(y)30 b(format)g(rather)f(then)g(the)h('E')f(format)h (will)g(b)s(e)f(used)f(when)h(constructing)h(the)f(k)m(eyw)m(ord)h(v)-5 b(alue,)227 668 y(taking)27 b(the)g(absolute)g(v)-5 b(alue)26 b(of)h('decimals')g(for)f(the)h(precision.)39 b(This)26 b(will)g(suppress)e(trailing)k(zeros,)g(and)227 781 y(will)37 b(use)g(a)g(\014xed)f(format)h(rather)g(than)f(an)h(exp)s(onen)m(tial)g (format,)i(dep)s(ending)c(on)i(the)g(magnitude)g(of)227 894 y(the)31 b(v)-5 b(alue.)95 1147 y Fe(int)47 b(fits_insert_card)d(/) j(ffikey)286 1259 y(\(fitsfile)f(*fptr,)g(char)g(*card,)g(>)i(int)f (*status\))95 1485 y(int)g(fits_insert_key_[str,)42 b(longstr])k(/)h (ffi[kys,)f(kls])286 1598 y(\(fitsfile)g(*fptr,)g(char)g(*keyname,)g (char)g(*value,)g(char)h(*comment,)334 1711 y(>)h(int)e(*status\))95 1937 y(int)h(fits_insert_key_[log,)42 b(lng])47 b(/)g(ffiky[lj])286 2050 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(DTYPE)g(numval,)g(char) g(*comment,)334 2163 y(>)i(int)e(*status\))95 2389 y(int)h (fits_insert_key_[flt,)42 b(fixflt,)k(dbl,)h(fixdbl])f(/)h(ffiky[edfg]) 286 2501 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(DTYPE)g(numval,)g (int)h(decimals,)334 2614 y(char)g(*comment,)e(>)i(int)g(*status\))95 2840 y(int)g(fits_insert_key_[cmp,)42 b(dblcmp,)k(fixcmp,)g(fixdblcmp]) f(/)i(ffik[yc,ym,fc,fm])286 2953 y(\(fitsfile)f(*fptr,)g(char)g (*keyname,)g(DTYPE)g(*numval,)g(int)g(decimals,)334 3066 y(char)h(*comment,)e(>)i(int)g(*status\))0 3319 y Fi(3)81 b Fj(Insert)32 b(a)i(new)f(k)m(eyw)m(ord)h(with)f(an)h(unde\014ned,)e (or)h(n)m(ull,)h(v)-5 b(alue)34 b(in)m(to)h(the)e(CHU.)h(The)f(v)-5 b(alue)34 b(string)f(of)h(the)227 3431 y(k)m(eyw)m(ord)d(is)g(left)g (blank)f(in)g(this)g(case.)95 3684 y Fe(int)47 b(fits_insert_key_null)c (/)k(ffikyu)286 3797 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(char)g (*comment,)g(>)h(int)g(*status\))0 3943 y SDict begin H.S end 0 3943 a 0 3943 a SDict begin 13.6 H.A end 0 3943 a 0 3943 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.9.3.5) cvn H.B /DEST pdfmark end 0 3943 a 144 x Fd(9.3.5)112 b(Read)38 b(Keyw)m(ord)g(Routines)0 4305 y Fj(Wild)31 b(card)f(c)m(haracters)i(ma)m(y)f(b)s(e)f(used)f(when)h(sp)s(ecifying)g (the)g(name)h(of)f(the)h(k)m(eyw)m(ord)g(to)g(b)s(e)f(read.)0 4558 y Fi(1)81 b Fj(Read)43 b(a)h(k)m(eyw)m(ord)g(v)-5 b(alue)43 b(\(with)h(the)f(appropriate)h(data)g(t)m(yp)s(e\))g(and)e (commen)m(t)j(from)e(the)g(CHU.)h(If)f(a)227 4671 y(NULL)32 b(commen)m(t)h(p)s(oin)m(ter)f(is)h(giv)m(en)g(on)f(input,)f(then)h (the)g(commen)m(t)i(string)e(will)g(not)g(b)s(e)g(returned.)44 b(If)227 4784 y(the)32 b(v)-5 b(alue)33 b(of)f(the)g(k)m(eyw)m(ord)g (is)g(not)h(de\014ned)d(\(i.e.,)k(the)e(v)-5 b(alue)33 b(\014eld)e(is)h(blank\))g(then)g(an)g(error)f(status)h(=)227 4897 y(V)-10 b(ALUE)p 545 4897 28 4 v 33 w(UNDEFINED)29 b(will)f(b)s(e)g(returned)e(and)h(the)h(input)f(v)-5 b(alue)28 b(will)h(not)f(b)s(e)f(c)m(hanged)h(\(except)h(that)227 5010 y(\013gkys)i(will)g(reset)g(the)f(v)-5 b(alue)31 b(to)g(a)g(n)m(ull)f(string\).)95 5262 y Fe(int)47 b(fits_read_key_str) c(/)48 b(ffgkys)286 5375 y(\(fitsfile)e(*fptr,)g(char)g(*keyname,)g(>)h (char)g(*value,)f(char)g(*comment,)334 5488 y(int)h(*status\);)95 5714 y(NOTE:)g(after)f(calling)g(the)h(following)e(routine,)h(programs) f(must)i(explicitly)e(free)p eop end %%Page: 108 116 TeXDict begin 108 115 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.108) cvn H.B /DEST pdfmark end 0 299 a Fj(108)958 b Fh(CHAPTER)30 b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)382 555 y Fe(the)47 b(memory)f(allocated)f(for)i ('longstr')e(after)i(it)g(is)g(no)g(longer)f(needed)g(by)382 668 y(calling)g(fits_free_memory.)95 894 y(int)h(fits_read_key_longstr) 42 b(/)48 b(ffgkls)286 1007 y(\(fitsfile)e(*fptr,)g(char)g(*keyname,)g (>)h(char)g(**longstr,)e(char)h(*comment,)620 1120 y(int)h(*status\))95 1346 y(int)g(fits_free_memory)d(/)j(fffree)286 1458 y(\(char)g (*longstr,)e(>)i(int)g(*status\);)95 1684 y(int)g(fits_read_key_[log,)c (lng,)k(flt,)f(dbl,)h(cmp,)f(dblcmp])g(/)i(ffgky[ljedcm])286 1797 y(\(fitsfile)e(*fptr,)g(char)g(*keyname,)g(>)h(DTYPE)f(*numval,)g (char)h(*comment,)334 1910 y(int)g(*status\))95 2136 y(int)g(fits_read_key_lnglng)c(/)k(ffgkyjj)286 2249 y(\(fitsfile)f (*fptr,)g(char)g(*keyname,)g(>)h(LONGLONG)f(*numval,)f(char)i (*comment,)334 2362 y(int)g(*status\))0 2594 y Fi(2)81 b Fj(Read)36 b(a)h(sequence)f(of)h(indexed)e(k)m(eyw)m(ord)i(v)-5 b(alues)37 b(\(e.g.,)i(NAXIS1,)g(NAXIS2,)f(...\).)59 b(The)36 b(input)f(starting)227 2707 y(index)j(n)m(um)m(b)s(er)e (\(nstart\))j(m)m(ust)f(b)s(e)f(greater)i(than)e(0.)64 b(If)37 b(the)h(v)-5 b(alue)38 b(of)g(an)m(y)h(of)f(the)g(k)m(eyw)m (ords)g(is)g(not)227 2819 y(de\014ned)c(\(i.e.,)j(the)e(v)-5 b(alue)35 b(\014eld)f(is)h(blank\))g(then)f(an)g(error)h(status)g(=)f (V)-10 b(ALUE)p 3009 2819 28 4 v 33 w(UNDEFINED)36 b(will)f(b)s(e)227 2932 y(returned)21 b(and)h(the)h(input)e(v)-5 b(alue)23 b(for)f(the)g(unde\014ned)e(k)m(eyw)m(ord\(s\))k(will)e(not)h(b)s(e)e (c)m(hanged.)39 b(These)22 b(routines)227 3045 y(do)j(not)h(supp)s(ort) d(wild)i(card)h(c)m(haracters)g(in)f(the)h(ro)s(ot)f(name.)39 b(If)25 b(there)h(are)f(no)g(indexed)g(k)m(eyw)m(ords)h(in)f(the)227 3158 y(header)35 b(with)f(the)h(input)e(ro)s(ot)i(name)g(then)f(these)h (routines)g(do)f(not)h(return)e(a)i(non-zero)h(status)e(v)-5 b(alue)227 3271 y(and)30 b(instead)h(simply)f(return)f(nfound)f(=)i(0.) 95 3503 y Fe(int)47 b(fits_read_keys_str)c(/)48 b(ffgkns)286 3616 y(\(fitsfile)e(*fptr,)g(char)g(*keyname,)g(int)h(nstart,)e(int)i (nkeys,)334 3729 y(>)h(char)e(**value,)g(int)h(*nfound,)93 b(int)47 b(*status\))95 3955 y(int)g(fits_read_keys_[log,)c(lng,)j (flt,)h(dbl])g(/)g(ffgkn[ljed])286 4068 y(\(fitsfile)f(*fptr,)g(char)g (*keyname,)g(int)h(nstart,)e(int)i(nkeys,)334 4180 y(>)h(DTYPE)e (*numval,)f(int)i(*nfound,)f(int)h(*status\))0 4412 y Fi(3)81 b Fj(Read)37 b(the)h(v)-5 b(alue)38 b(of)g(a)g(\015oating)g(p)s (oin)m(t)g(k)m(eyw)m(ord,)i(returning)d(the)h(in)m(teger)h(and)e (fractional)i(parts)e(of)h(the)227 4525 y(v)-5 b(alue)35 b(in)e(separate)i(routine)f(argumen)m(ts.)52 b(This)33 b(routine)h(ma)m(y)g(b)s(e)f(used)h(to)g(read)g(an)m(y)g(k)m(eyw)m(ord) h(but)e(is)227 4638 y(esp)s(ecially)f(useful)d(for)i(reading)f(the)h ('triple)g(precision')f(k)m(eyw)m(ords)h(written)g(b)m(y)f(\013pkyt.)95 4870 y Fe(int)47 b(fits_read_key_triple)c(/)k(ffgkyt)286 4983 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(>)h(long)g(*intval,)e (double)h(*frac,)334 5096 y(char)h(*comment,)e(int)i(*status\))0 5231 y SDict begin H.S end 0 5231 a 0 5231 a SDict begin 13.6 H.A end 0 5231 a 0 5231 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.9.3.6) cvn H.B /DEST pdfmark end 0 5231 a 151 x Fd(9.3.6)112 b(Mo)s(dify)39 b(Keyw)m(ord)e(Routines)0 5601 y Fj(These)31 b(routines)h(mo)s(dify)f(the)h(v)-5 b(alue)32 b(of)g(an)g(existing)g(k)m(eyw)m(ord.)46 b(An)31 b(error)g(is)h(returned)e(if)i(the)g(k)m(eyw)m(ord)g(do)s(es)0 5714 y(not)43 b(exist.)77 b(Wild)43 b(card)g(c)m(haracters)h(ma)m(y)f (b)s(e)f(used)f(when)h(sp)s(ecifying)g(the)h(name)f(of)h(the)f(k)m(eyw) m(ord)h(to)h(b)s(e)p eop end %%Page: 109 117 TeXDict begin 109 116 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.109) cvn H.B /DEST pdfmark end 0 299 a Fh(9.3.)72 b(SPECIALIZED)29 b(HEADER)i(KEYW)m(ORD)g(R)m(OUTINES)1465 b Fj(109)0 555 y(mo)s(di\014ed.)40 b(See)30 b(App)s(endix)f(B)i(for)f(the)g (de\014nition)g(of)h(the)f(parameters)h(used)f(in)g(these)h(routines.)0 788 y Fi(1)81 b Fj(Mo)s(dify)30 b(\(o)m(v)m(erwrite\))i(the)f(n)m(th)f (80-c)m(haracter)j(header)d(record)h(in)f(the)g(CHU.)95 1021 y Fe(int)47 b(fits_modify_record)c(/)48 b(ffmrec)286 1134 y(\(fitsfile)e(*fptr,)g(int)h(keynum,)e(char)i(*card,)f(>)i(int)f (*status\))0 1367 y Fi(2)81 b Fj(Mo)s(dify)37 b(\(o)m(v)m(erwrite\))j (the)e(80-c)m(haracter)j(header)c(record)h(for)f(the)h(named)f(k)m(eyw) m(ord)h(in)g(the)g(CHU.)g(This)227 1480 y(can)31 b(b)s(e)f(used)f(to)i (o)m(v)m(erwrite)h(the)f(name)f(of)h(the)f(k)m(eyw)m(ord)h(as)g(w)m (ell)g(as)g(its)g(v)-5 b(alue)30 b(and)g(commen)m(t)i(\014elds.)95 1713 y Fe(int)47 b(fits_modify_card)d(/)j(ffmcrd)286 1826 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(char)g(*card,)g(>)i (int)f(*status\))0 2059 y Fi(5)81 b Fj(Mo)s(dify)30 b(the)g(v)-5 b(alue)31 b(and)e(commen)m(t)i(\014elds)f(of)g(an)g(existing)h(k)m(eyw) m(ord)g(in)f(the)g(CHU.)h(The)e(`longstr')i(v)m(ersion)227 2172 y(has)41 b(the)h(same)f(functionalit)m(y)i(as)e(the)h(`str')f(v)m (ersion)h(except)g(that)g(it)g(also)g(supp)s(orts)d(the)j(lo)s(cal)g (long)227 2285 y(string)29 b(k)m(eyw)m(ord)h(con)m(v)m(en)m(tion)h(for) e(strings)f(longer)i(than)f(68)h(c)m(haracters.)41 b(Optionally)-8 b(,)31 b(one)e(ma)m(y)h(mo)s(dify)227 2398 y(only)e(the)g(v)-5 b(alue)28 b(\014eld)g(and)f(lea)m(v)m(e)j(the)e(commen)m(t)h(\014eld)e (unc)m(hanged)h(b)m(y)g(setting)g(the)g(input)f(COMMENT)227 2511 y(parameter)c(equal)h(to)f(the)g(amp)s(ersand)e(c)m(haracter)j (\(&\))f(or)g(b)m(y)g(en)m(tering)g(a)g(n)m(ull)g(p)s(oin)m(ter)g(for)f (the)h(commen)m(t)227 2624 y(parameter.)40 b(The)24 b(\015t,)i(dbl,)g (cmp,)f(and)g(dblcmp)e(v)m(ersions)j(of)f(this)g(routine)g(ha)m(v)m(e)h (the)f(added)f(feature)h(that)227 2736 y(if)h(the)h('decimals')g (parameter)g(is)f(negativ)m(e,)k(then)c(the)g('G')h(displa)m(y)f (format)h(rather)f(then)g(the)g('E')h(format)227 2849 y(will)i(b)s(e)f(used)f(when)h(constructing)h(the)f(k)m(eyw)m(ord)h(v) -5 b(alue,)30 b(taking)f(the)g(absolute)g(v)-5 b(alue)29 b(of)f('decimals')i(for)227 2962 y(the)37 b(precision.)60 b(This)35 b(will)i(suppress)e(trailing)i(zeros,)i(and)d(will)h(use)g(a) g(\014xed)e(format)i(rather)g(than)f(an)227 3075 y(exp)s(onen)m(tial)c (format,)f(dep)s(ending)d(on)j(the)f(magnitude)h(of)f(the)h(v)-5 b(alue.)95 3308 y Fe(int)47 b(fits_modify_key_[str,)42 b(longstr])k(/)h(ffm[kys,)f(kls])286 3421 y(\(fitsfile)g(*fptr,)g(char) g(*keyname,)g(char)g(*value,)g(char)h(*comment,)334 3534 y(>)h(int)e(*status\);)95 3760 y(int)h(fits_modify_key_[log,)42 b(lng])47 b(/)g(ffmky[lj])286 3873 y(\(fitsfile)f(*fptr,)g(char)g (*keyname,)g(DTYPE)g(numval,)g(char)g(*comment,)334 3986 y(>)i(int)e(*status\))95 4211 y(int)h(fits_modify_key_[flt,)42 b(dbl,)47 b(fixflt,)f(fixdbl])g(/)h(ffmky[edfg])286 4324 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(DTYPE)g(numval,)g(int)h (decimals,)334 4437 y(char)g(*comment,)e(>)i(int)g(*status\))95 4663 y(int)g(fits_modify_key_[cmp,)42 b(dblcmp,)k(fixcmp,)g(fixdblcmp]) f(/)i(ffmk[yc,ym,fc,fm])286 4776 y(\(fitsfile)f(*fptr,)g(char)g (*keyname,)g(DTYPE)g(*numval,)g(int)g(decimals,)334 4889 y(char)h(*comment,)e(>)i(int)g(*status\))0 5122 y Fi(6)81 b Fj(Mo)s(dify)22 b(the)g(v)-5 b(alue)23 b(of)f(an)g(existing)i(k)m (eyw)m(ord)e(to)h(b)s(e)f(unde\014ned,)g(or)g(n)m(ull.)38 b(The)22 b(v)-5 b(alue)22 b(string)h(of)f(the)g(k)m(eyw)m(ord)227 5235 y(is)30 b(set)h(to)g(blank.)40 b(Optionally)-8 b(,)31 b(one)f(ma)m(y)h(lea)m(v)m(e)h(the)f(commen)m(t)g(\014eld)e(unc)m (hanged)h(b)m(y)g(setting)h(the)f(input)227 5348 y(COMMENT)f(parameter) g(equal)g(to)g(the)g(amp)s(ersand)e(c)m(haracter)k(\(&\))e(or)f(b)m(y)h (en)m(tering)g(a)g(n)m(ull)g(p)s(oin)m(ter.)95 5581 y Fe(int)47 b(fits_modify_key_null)c(/)k(ffmkyu)286 5694 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(char)g(*comment,)g(>)h(int)g (*status\))p eop end %%Page: 110 118 TeXDict begin 110 117 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.110) cvn H.B /DEST pdfmark end 0 299 a Fj(110)958 b Fh(CHAPTER)30 b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)0 464 y SDict begin H.S end 0 464 a 0 464 a SDict begin 13.6 H.A end 0 464 a 0 464 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.9.3.7) cvn H.B /DEST pdfmark end 0 464 a 91 x Fd(9.3.7)112 b(Up)s(date)39 b(Keyw)m(ord)e(Routines)0 757 y Fi(1)81 b Fj(These)29 b(up)s(date)g(routines)h(mo)s(dify)f(the)g (v)-5 b(alue,)31 b(and)e(optionally)i(the)f(commen)m(t)h(\014eld,)f(of) g(the)g(k)m(eyw)m(ord)g(if)f(it)227 870 y(already)34 b(exists,)g(otherwise)f(the)g(new)f(k)m(eyw)m(ord)h(is)f(app)s(ended)f (to)j(the)f(header.)47 b(A)33 b(separate)g(routine)g(is)227 982 y(pro)m(vided)c(for)g(eac)m(h)h(k)m(eyw)m(ord)f(data)h(t)m(yp)s(e.) 41 b(The)28 b(`longstr')i(v)m(ersion)g(has)e(the)i(same)f(functionalit) m(y)h(as)g(the)227 1095 y(`str')h(v)m(ersion)g(except)h(that)g(it)f (also)h(supp)s(orts)c(the)j(lo)s(cal)h(long)g(string)e(k)m(eyw)m(ord)i (con)m(v)m(en)m(tion)h(for)d(strings)227 1208 y(longer)i(than)f(68)h(c) m(haracters.)45 b(A)31 b(n)m(ull)g(p)s(oin)m(ter)h(ma)m(y)f(b)s(e)g(en) m(tered)h(for)f(the)g(commen)m(t)i(parameter)e(whic)m(h)227 1321 y(will)i(lea)m(v)m(e)h(the)f(commen)m(t)g(\014eld)f(unc)m(hanged)g (or)g(blank.)46 b(The)31 b(\015t,)i(dbl,)f(cmp,)h(and)e(dblcmp)g(v)m (ersions)i(of)227 1434 y(this)d(routine)g(ha)m(v)m(e)h(the)e(added)g (feature)i(that)f(if)g(the)g('decimals')h(parameter)f(is)g(negativ)m (e,)i(then)d(the)h('G')227 1547 y(displa)m(y)g(format)g(rather)f(then)g (the)h('E')f(format)h(will)g(b)s(e)f(used)f(when)h(constructing)h(the)f (k)m(eyw)m(ord)h(v)-5 b(alue,)227 1660 y(taking)27 b(the)g(absolute)g (v)-5 b(alue)26 b(of)h('decimals')g(for)f(the)h(precision.)39 b(This)26 b(will)g(suppress)e(trailing)k(zeros,)g(and)227 1773 y(will)37 b(use)g(a)g(\014xed)f(format)h(rather)g(than)f(an)h(exp) s(onen)m(tial)g(format,)i(dep)s(ending)c(on)i(the)g(magnitude)g(of)227 1886 y(the)31 b(v)-5 b(alue.)95 2100 y Fe(int)47 b (fits_update_key_[str,)42 b(longstr])k(/)h(ffu[kys,)f(kls])286 2213 y(\(fitsfile)g(*fptr,)g(char)g(*keyname,)g(char)g(*value,)g(char)h (*comment,)334 2326 y(>)h(int)e(*status\))95 2552 y(int)h (fits_update_key_[log,)42 b(lng])47 b(/)g(ffuky[lj])286 2665 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(DTYPE)g(numval,)g(char) g(*comment,)334 2778 y(>)i(int)e(*status\))95 3003 y(int)h (fits_update_key_[flt,)42 b(dbl,)47 b(fixflt,)f(fixdbl])g(/)h (ffuky[edfg])286 3116 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(DTYPE) g(numval,)g(int)h(decimals,)334 3229 y(char)g(*comment,)e(>)i(int)g (*status\))95 3455 y(int)g(fits_update_key_[cmp,)42 b(dblcmp,)k (fixcmp,)g(fixdblcmp])f(/)i(ffuk[yc,ym,fc,fm])286 3568 y(\(fitsfile)f(*fptr,)g(char)g(*keyname,)g(DTYPE)g(*numval,)g(int)g (decimals,)334 3681 y(char)h(*comment,)e(>)i(int)g(*status\))0 3823 y SDict begin H.S end 0 3823 a 0 3823 a SDict begin 13.6 H.A end 0 3823 a 0 3823 a SDict begin [ /View [/XYZ H.V] /Dest (section.9.4) cvn H.B /DEST pdfmark end 0 3823 a 184 x Ff(9.4)135 b(De\014ne)45 b(Data)h(Scaling)g(and)e(Unde\014ned)h (Pixel)h(P)l(arameters)0 4258 y Fj(These)37 b(routines)g(set)h(or)f(mo) s(dify)g(the)g(in)m(ternal)h(parameters)g(used)e(b)m(y)i(CFITSIO)d(to)j (either)g(scale)h(the)e(data)0 4370 y(or)f(to)h(represen)m(t)f (unde\014ned)d(pixels.)58 b(Generally)37 b(CFITSIO)d(will)j(scale)g (the)f(data)h(according)g(to)f(the)h(v)-5 b(alues)0 4483 y(of)35 b(the)f(BSCALE)g(and)g(BZER)m(O)h(\(or)g(TSCALn)d(and)i(TZER)m (On\))g(k)m(eyw)m(ords,)i(ho)m(w)m(ev)m(er)g(these)f(routines)f(ma)m(y) 0 4596 y(b)s(e)e(used)h(to)h(o)m(v)m(erride)g(the)f(k)m(eyw)m(ord)h(v) -5 b(alues.)49 b(This)32 b(ma)m(y)i(b)s(e)f(useful)f(when)g(one)i(w)m (an)m(ts)f(to)h(read)f(or)g(write)h(the)0 4709 y(ra)m(w)e(unscaled)g(v) -5 b(alues)33 b(in)f(the)g(FITS)f(\014le.)47 b(Similarly)-8 b(,)33 b(CFITSIO)e(generally)i(uses)f(the)g(v)-5 b(alue)33 b(of)f(the)h(BLANK)0 4822 y(or)40 b(TNULLn)f(k)m(eyw)m(ord)h(to)h (signify)e(an)h(unde\014ned)e(pixel,)43 b(but)c(these)h(routines)g(ma)m (y)g(b)s(e)f(used)g(to)i(o)m(v)m(erride)0 4935 y(this)32 b(v)-5 b(alue.)48 b(These)32 b(routines)g(do)h(not)f(create)i(or)f(mo)s (dify)e(the)i(corresp)s(onding)e(header)i(k)m(eyw)m(ord)f(v)-5 b(alues.)48 b(See)0 5048 y(App)s(endix)29 b(B)h(for)h(the)f (de\014nition)g(of)h(the)f(parameters)h(used)e(in)i(these)f(routines.)0 5262 y Fi(1)81 b Fj(Reset)26 b(the)g(scaling)g(factors)g(in)f(the)h (primary)f(arra)m(y)h(or)f(image)i(extension;)h(do)s(es)d(not)g(c)m (hange)i(the)f(BSCALE)227 5375 y(and)i(BZER)m(O)g(k)m(eyw)m(ord)h(v)-5 b(alues)28 b(and)g(only)g(a\013ects)i(the)e(automatic)j(scaling)e(p)s (erformed)e(when)g(the)h(data)227 5488 y(elemen)m(ts)f(are)f (written/read)g(to/from)g(the)g(FITS)f(\014le.)39 b(When)25 b(reading)h(from)f(a)h(FITS)f(\014le)g(the)h(returned)227 5601 y(data)i(v)-5 b(alue)28 b(=)f(\(the)h(v)-5 b(alue)28 b(giv)m(en)h(in)e(the)g(FITS)g(arra)m(y\))h(*)g(BSCALE)f(+)g(BZER)m(O.) g(The)g(in)m(v)m(erse)i(form)m(ula)227 5714 y(is)i(used)e(when)h (writing)g(data)h(v)-5 b(alues)31 b(to)g(the)f(FITS)g(\014le.)p eop end %%Page: 111 119 TeXDict begin 111 118 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.111) cvn H.B /DEST pdfmark end 0 299 a Fh(9.5.)72 b(SPECIALIZED)29 b(FITS)g(PRIMAR)-8 b(Y)31 b(ARRA)-8 b(Y)32 b(OR)d(IMA)m(GE)j(EXTENSION) d(I/O)h(R)m(OUTINES)80 b Fj(111)95 555 y Fe(int)47 b(fits_set_bscale)d (/)j(ffpscl)286 668 y(\(fitsfile)f(*fptr,)g(double)g(scale,)g(double)g (zero,)g(>)i(int)f(*status\))0 925 y Fi(2)81 b Fj(Reset)39 b(the)f(scaling)i(parameters)e(for)h(a)f(table)h(column;)k(do)s(es)38 b(not)g(c)m(hange)i(the)e(TSCALn)f(or)h(TZER)m(On)227 1038 y(k)m(eyw)m(ord)29 b(v)-5 b(alues)29 b(and)e(only)i(a\013ects)g (the)g(automatic)h(scaling)f(p)s(erformed)e(when)g(the)i(data)g(elemen) m(ts)h(are)227 1151 y(written/read)i(to/from)g(the)g(FITS)f(\014le.)44 b(When)31 b(reading)g(from)g(a)h(FITS)f(\014le)g(the)h(returned)e(data) i(v)-5 b(alue)227 1264 y(=)25 b(\(the)i(v)-5 b(alue)26 b(giv)m(en)g(in)f(the)h(FITS)f(arra)m(y\))h(*)g(TSCAL)e(+)i(TZER)m(O.)e (The)h(in)m(v)m(erse)i(form)m(ula)f(is)f(used)g(when)227 1377 y(writing)31 b(data)g(v)-5 b(alues)30 b(to)i(the)e(FITS)g(\014le.) 95 1633 y Fe(int)47 b(fits_set_tscale)d(/)j(fftscl)286 1746 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(double)i(scale,)f(double)g (zero,)334 1859 y(>)i(int)e(*status\))0 2116 y Fi(3)81 b Fj(De\014ne)36 b(the)g(in)m(teger)i(v)-5 b(alue)36 b(to)h(b)s(e)e(used)h(to)h(signify)f(unde\014ned)e(pixels)i(in)g(the)g (primary)f(arra)m(y)i(or)f(image)227 2229 y(extension.)54 b(This)34 b(is)g(only)h(used)f(if)g(BITPIX)g(=)h(8,)h(16,)g(or)f(32.)54 b(This)34 b(do)s(es)g(not)h(create)h(or)e(c)m(hange)i(the)227 2342 y(v)-5 b(alue)31 b(of)g(the)f(BLANK)h(k)m(eyw)m(ord)g(in)f(the)g (header.)95 2599 y Fe(int)47 b(fits_set_imgnull)d(/)j(ffpnul)286 2712 y(\(fitsfile)f(*fptr,)g(LONGLONG)f(nulval,)h(>)i(int)e(*status\))0 2969 y Fi(4)81 b Fj(De\014ne)36 b(the)g(string)g(to)g(b)s(e)f(used)g (to)i(signify)f(unde\014ned)e(pixels)i(in)f(a)h(column)g(in)g(an)f (ASCI)s(I)g(table.)58 b(This)227 3081 y(do)s(es)30 b(not)h(create)h(or) e(c)m(hange)i(the)e(v)-5 b(alue)31 b(of)g(the)f(TNULLn)g(k)m(eyw)m (ord.)95 3338 y Fe(int)47 b(fits_set_atblnull)c(/)48 b(ffsnul)286 3451 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(char)i (*nulstr,)f(>)h(int)g(*status\))0 3708 y Fi(5)81 b Fj(De\014ne)34 b(the)h(v)-5 b(alue)34 b(to)h(b)s(e)f(used)g(to)h(signify)f (unde\014ned)e(pixels)j(in)f(an)g(in)m(teger)i(column)e(in)g(a)g (binary)g(table)227 3821 y(\(where)29 b(TF)m(ORMn)f(=)g('B',)i('I',)f (or)f('J'\).)i(This)d(do)s(es)i(not)f(create)j(or)d(c)m(hange)i(the)e (v)-5 b(alue)29 b(of)g(the)g(TNULLn)227 3934 y(k)m(eyw)m(ord.)95 4191 y Fe(int)47 b(fits_set_btblnull)c(/)48 b(fftnul)286 4304 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(LONGLONG)h(nulval,)g(>)h (int)g(*status\))0 4460 y SDict begin H.S end 0 4460 a 0 4460 a SDict begin 13.6 H.A end 0 4460 a 0 4460 a SDict begin [ /View [/XYZ H.V] /Dest (section.9.5) cvn H.B /DEST pdfmark end 0 4460 a 177 x Ff(9.5)135 b(Sp)t(ecialized)61 b(FITS)e(Primary)i(Arra)l(y)f(or)h(IMA)l(GE)e(Extension)j(I/O)306 4786 y(Routines)0 5036 y Fj(These)27 b(routines)h(read)f(or)h(write)g (data)g(v)-5 b(alues)28 b(in)g(the)f(primary)g(data)h(arra)m(y)h (\(i.e.,)g(the)f(\014rst)f(HDU)i(in)e(the)h(FITS)0 5149 y(\014le\))37 b(or)g(an)f(IMA)m(GE)h(extension.)60 b(Automatic)39 b(data)e(t)m(yp)s(e)g(con)m(v)m(ersion)g(is)g(p)s(erformed)e(for)h(if)h (the)g(data)g(t)m(yp)s(e)0 5262 y(of)c(the)g(FITS)f(arra)m(y)h(\(as)g (de\014ned)f(b)m(y)g(the)h(BITPIX)g(k)m(eyw)m(ord\))g(di\013ers)g(from) f(the)h(data)g(t)m(yp)s(e)g(of)g(the)g(arra)m(y)g(in)0 5375 y(the)c(calling)i(routine.)40 b(The)28 b(data)i(v)-5 b(alues)29 b(are)h(automatically)i(scaled)d(b)m(y)g(the)h(BSCALE)e(and) g(BZER)m(O)h(header)0 5488 y(v)-5 b(alues)25 b(as)h(they)f(are)g(b)s (eing)g(written)g(or)g(read)f(from)h(the)g(FITS)f(arra)m(y)-8 b(.)40 b(Unlik)m(e)26 b(the)f(basic)h(routines)e(describ)s(ed)g(in)0 5601 y(the)31 b(previous)g(c)m(hapter,)i(most)e(of)h(these)g(routines)f (sp)s(eci\014cally)h(supp)s(ort)d(the)j(FITS)e(random)h(groups)f (format.)0 5714 y(See)h(App)s(endix)d(B)j(for)f(the)h(de\014nition)f (of)g(the)h(parameters)g(used)e(in)h(these)h(routines.)p eop end %%Page: 112 120 TeXDict begin 112 119 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.112) cvn H.B /DEST pdfmark end 0 299 a Fj(112)958 b Fh(CHAPTER)30 b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)0 555 y Fj(The)24 b(more)h(primitiv)m(e)h(reading)f(and)f (writing)h(routines)f(\(i.)40 b(e.,)26 b(\013ppr)p 2364 555 28 4 v 32 w(,)g(\013ppn)p 2653 555 V 31 w(,)g(\013ppn,)f(\013gp)m (v)p 3185 555 V 33 w(,)h(or)f(\013gpf)p 3552 555 V 32 w(\))g(simply)0 668 y(treat)g(the)g(primary)e(arra)m(y)i(as)f(a)h(long) g(1-dimensional)g(arra)m(y)g(of)f(pixels,)i(ignoring)f(the)f(in)m (trinsic)h(dimensionalit)m(y)0 781 y(of)30 b(the)g(arra)m(y)-8 b(.)42 b(When)30 b(dealing)h(with)e(a)i(2D)g(image,)g(for)f(example,)h (the)f(application)i(program)e(m)m(ust)g(calculate)0 894 y(the)i(pixel)g(o\013set)g(in)f(the)h(1-D)h(arra)m(y)f(that)g (corresp)s(onds)e(to)i(an)m(y)g(particular)g(X,)g(Y)f(co)s(ordinate)i (in)e(the)g(image.)0 1007 y(C)25 b(programmers)h(should)f(note)h(that)g (the)h(ordering)e(of)h(arra)m(ys)g(in)g(FITS)f(\014les,)i(and)e(hence)h (in)g(all)g(the)g(CFITSIO)0 1120 y(calls,)40 b(is)d(more)g(similar)h (to)f(the)h(dimensionalit)m(y)g(of)f(arra)m(ys)g(in)g(F)-8 b(ortran)38 b(rather)f(than)f(C.)h(F)-8 b(or)38 b(instance)g(if)f(a)0 1233 y(FITS)28 b(image)i(has)e(NAXIS1)h(=)f(100)i(and)e(NAXIS2)h(=)f (50,)i(then)e(a)h(2-D)h(arra)m(y)f(just)f(large)i(enough)e(to)i(hold)e (the)0 1346 y(image)k(should)d(b)s(e)h(declared)h(as)f(arra)m (y[50][100])k(and)c(not)h(as)f(arra)m(y[100][50].)0 1506 y(F)-8 b(or)30 b(con)m(v)m(enience,)i(higher-lev)m(el)g(routines)d(are) h(also)h(pro)m(vided)e(to)h(sp)s(eci\014cally)h(deal)f(with)f(2D)i (images)f(\(\013p2d)p 3872 1506 V 0 1619 a(and)c(\013g2d)p 372 1619 V 33 w(\))h(and)f(3D)i(data)f(cub)s(es)f(\(\013p3d)p 1467 1619 V 59 w(and)g(\013g3d)p 1893 1619 V 33 w(\).)40 b(The)26 b(dimensionalit)m(y)i(of)f(the)g(FITS)f(image)i(is)e(passed)0 1732 y(b)m(y)36 b(the)h(naxis1,)h(naxis2,)h(and)d(naxis3)h(parameters)f (and)g(the)h(declared)f(dimensions)g(of)h(the)f(program)g(arra)m(y)0 1844 y(are)30 b(passed)g(in)f(the)h(dim1)g(and)f(dim2)h(parameters.)41 b(Note)31 b(that)f(the)g(dimensions)f(of)h(the)g(program)g(arra)m(y)g (ma)m(y)0 1957 y(b)s(e)35 b(larger)h(than)f(the)h(dimensions)f(of)h (the)g(FITS)e(arra)m(y)-8 b(.)58 b(F)-8 b(or)36 b(example)g(if)g(a)g (FITS)e(image)j(with)e(NAXIS1)h(=)0 2070 y(NAXIS2)g(=)g(400)h(is)f (read)g(in)m(to)h(a)g(program)f(arra)m(y)g(whic)m(h)g(is)g(dimensioned) f(as)i(512)g(x)f(512)h(pixels,)h(then)e(the)0 2183 y(image)g(will)f (just)f(\014ll)g(the)h(lo)m(w)m(er)h(left)f(corner)f(of)h(the)g(arra)m (y)g(with)f(pixels)h(in)f(the)h(range)g(1)g(-)g(400)g(in)g(the)f(X)h (an)0 2296 y(Y)g(directions.)54 b(This)34 b(has)h(the)g(e\013ect)h(of)f (taking)g(a)h(con)m(tiguous)f(set)h(of)f(pixel)g(v)-5 b(alue)35 b(in)f(the)h(FITS)f(arra)m(y)i(and)0 2409 y(writing)30 b(them)g(to)h(a)f(non-con)m(tiguous)h(arra)m(y)g(in)e(program)h(memory) g(\(i.e.,)i(there)e(are)h(no)m(w)f(some)g(blank)g(pixels)0 2522 y(around)f(the)i(edge)g(of)g(the)f(image)i(in)e(the)g(program)g (arra)m(y\).)0 2682 y(The)k(most)i(general)f(set)h(of)f(routines)f (\(\013pss)p 1560 2682 V 33 w(,)i(\013gsv)p 1836 2682 V 33 w(,)g(and)e(\013gsf)p 2273 2682 V 33 w(\))h(ma)m(y)h(b)s(e)e(used) g(to)h(transfer)g(a)g(rectangular)0 2795 y(subset)27 b(of)h(the)g(pixels)f(in)h(a)g(FITS)f(N-dimensional)h(image)h(to)f(or)g (from)f(an)g(arra)m(y)i(whic)m(h)e(has)g(b)s(een)g(declared)h(in)0 2908 y(the)h(calling)h(program.)40 b(The)28 b(fpixel)h(and)f(lpixel)h (parameters)g(are)g(in)m(teger)h(arra)m(ys)f(whic)m(h)f(sp)s(ecify)g (the)h(starting)0 3021 y(and)k(ending)f(pixel)i(co)s(ordinate)g(in)f (eac)m(h)h(dimension)f(\(starting)h(with)f(1,)h(not)g(0\))g(of)f(the)g (FITS)g(image)h(that)g(is)0 3134 y(to)f(b)s(e)e(read)g(or)h(written.)45 b(It)32 b(is)g(imp)s(ortan)m(t)g(to)h(note)f(that)h(these)f(are)g(the)g (starting)h(and)e(ending)g(pixels)h(in)g(the)0 3247 y(FITS)i(image,)k (not)d(in)f(the)h(declared)h(arra)m(y)f(in)f(the)h(program.)54 b(The)35 b(arra)m(y)g(parameter)g(in)g(these)g(routines)g(is)0 3360 y(treated)f(simply)e(as)h(a)f(large)i(one-dimensional)g(arra)m(y)f (of)f(the)h(appropriate)g(data)g(t)m(yp)s(e)g(con)m(taining)h(the)f (pixel)0 3472 y(v)-5 b(alues;)37 b(The)d(pixel)h(v)-5 b(alues)35 b(in)g(the)f(FITS)g(arra)m(y)h(are)g(read/written)g(from/to) h(this)e(program)h(arra)m(y)g(in)f(strict)0 3585 y(sequence)d(without)f (an)m(y)h(gaps;)g(it)g(is)f(up)f(to)j(the)e(calling)i(routine)e(to)i (correctly)f(in)m(terpret)g(the)g(dimensionalit)m(y)0 3698 y(of)d(this)f(arra)m(y)-8 b(.)41 b(The)27 b(t)m(w)m(o)i(FITS)e (reading)h(routines)f(\(\013gsv)p 2018 3698 V 61 w(and)g(\013gsf)p 2415 3698 V 61 w(\))h(also)g(ha)m(v)m(e)h(an)f(`inc')g(parameter)g (whic)m(h)0 3811 y(de\014nes)33 b(the)h(data)h(sampling)f(in)m(terv)-5 b(al)36 b(in)d(eac)m(h)j(dimension)d(of)h(the)h(FITS)e(arra)m(y)-8 b(.)53 b(F)-8 b(or)35 b(example,)h(if)e(inc[0]=2)0 3924 y(and)i(inc[1]=3)j(when)d(reading)h(a)g(2-dimensional)h(FITS)e(image,) 41 b(then)36 b(only)h(ev)m(ery)h(other)f(pixel)h(in)e(the)i(\014rst)0 4037 y(dimension)30 b(and)g(ev)m(ery)h(3rd)f(pixel)g(in)g(the)h(second) f(dimension)g(will)h(b)s(e)f(returned)f(to)i(the)f('arra)m(y')i (parameter.)0 4197 y(Tw)m(o)d(t)m(yp)s(es)h(of)f(routines)g(are)h(pro)m (vided)e(to)i(read)f(the)h(data)g(arra)m(y)f(whic)m(h)g(di\013er)g(in)g (the)h(w)m(a)m(y)g(unde\014ned)d(pixels)0 4310 y(are)38 b(handled.)60 b(The)37 b(\014rst)g(t)m(yp)s(e)g(of)g(routines)h (\(e.g.,)i(\013gp)m(v)p 2059 4310 V 34 w(\))d(simply)g(return)f(an)h (arra)m(y)h(of)g(data)g(elemen)m(ts)g(in)0 4423 y(whic)m(h)30 b(unde\014ned)f(pixels)h(are)h(set)g(equal)g(to)h(a)f(v)-5 b(alue)31 b(sp)s(eci\014ed)e(b)m(y)i(the)g(user)e(in)i(the)f(`n)m(ulv) -5 b(al')32 b(parameter.)41 b(An)0 4536 y(additional)30 b(feature)f(of)g(these)h(routines)e(is)h(that)h(if)f(the)g(user)f(sets) h(n)m(ulv)-5 b(al)29 b(=)g(0,)h(then)e(no)h(c)m(hec)m(ks)h(for)f (unde\014ned)0 4649 y(pixels)c(will)g(b)s(e)g(p)s(erformed,)f(th)m(us)h (reducing)f(the)h(amoun)m(t)h(of)f(CPU)f(pro)s(cessing.)39 b(The)24 b(second)h(t)m(yp)s(e)g(of)g(routines)0 4762 y(\(e.g.,)36 b(\013gpf)p 413 4762 V 32 w(\))e(returns)e(the)i(data)g (elemen)m(t)g(arra)m(y)g(and,)g(in)f(addition,)h(a)g(c)m(har)g(arra)m (y)f(that)h(indicates)h(whether)0 4875 y(the)f(v)-5 b(alue)34 b(of)g(the)f(corresp)s(onding)g(data)h(pixel)g(is)g(unde\014ned)d(\(=)j (1\))g(or)g(de\014ned)e(\(=)i(0\).)51 b(The)33 b(latter)i(t)m(yp)s(e)f (of)0 4988 y(routines)d(ma)m(y)h(b)s(e)e(more)i(con)m(v)m(enien)m(t)h (to)f(use)f(in)g(some)g(circumstances,)i(ho)m(w)m(ev)m(er,)g(it)e (requires)g(an)g(additional)0 5100 y(arra)m(y)g(of)f(logical)j(v)-5 b(alues)31 b(whic)m(h)f(can)h(b)s(e)e(un)m(wieldy)h(when)g(w)m(orking)g (with)g(large)i(data)f(arra)m(ys.)0 5351 y Fi(1)81 b Fj(W)-8 b(rite)31 b(elemen)m(ts)h(in)m(to)f(the)g(FITS)f(data)h(arra)m (y)-8 b(.)95 5601 y Fe(int)47 b(fits_write_img)d(/)k(ffppr)286 5714 y(\(fitsfile)e(*fptr,)g(int)h(datatype,)e(LONGLONG)g(firstelem,)g (LONGLONG)h(nelements,)p eop end %%Page: 113 121 TeXDict begin 113 120 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.113) cvn H.B /DEST pdfmark end 0 299 a Fh(9.5.)72 b(SPECIALIZED)29 b(FITS)g(PRIMAR)-8 b(Y)31 b(ARRA)-8 b(Y)32 b(OR)d(IMA)m(GE)j(EXTENSION) d(I/O)h(R)m(OUTINES)80 b Fj(113)334 555 y Fe(DTYPE)46 b(*array,)g(int)h(*status\);)95 781 y(int)g(fits_write_img_[byt,)c (sht,)j(usht,)h(int,)f(uint,)h(lng,)f(ulng,)h(lnglng,)e(flt,)i(dbl])g (/)286 894 y(ffppr[b,i,ui,k,uk,j,uj,jj,)o(e,d)o(])286 1007 y(\(fitsfile)f(*fptr,)g(long)g(group,)g(LONGLONG)g(firstelem,)f (LONGLONG)h(nelements,)334 1120 y(DTYPE)g(*array,)g(>)i(int)f (*status\);)95 1346 y(int)g(fits_write_imgnull)c(/)48 b(ffppn)286 1458 y(\(fitsfile)e(*fptr,)g(int)h(datatype,)e(LONGLONG)g (firstelem,)g(LONGLONG)h(nelements,)334 1571 y(DTYPE)g(*array,)g(DTYPE) h(*nulval,)e(>)j(int)f(*status\);)95 1797 y(int)g (fits_write_imgnull_[byt,)42 b(sht,)k(usht,)h(int,)f(uint,)h(lng,)f (ulng,)h(lnglng,)e(flt,)i(dbl])g(/)286 1910 y (ffppn[b,i,ui,k,uk,j,uj,jj,)o(e,d)o(])286 2023 y(\(fitsfile)f(*fptr,)g (long)g(group,)g(LONGLONG)g(firstelem,)525 2136 y(LONGLONG)g (nelements,)f(DTYPE)h(*array,)g(DTYPE)g(nulval,)g(>)h(int)g(*status\);) 0 2403 y Fi(2)81 b Fj(Set)30 b(data)h(arra)m(y)g(elemen)m(ts)h(as)e (unde\014ned.)95 2669 y Fe(int)47 b(fits_write_img_null)c(/)k(ffppru) 286 2782 y(\(fitsfile)f(*fptr,)g(long)g(group,)g(LONGLONG)g(firstelem,) f(LONGLONG)h(nelements,)334 2895 y(>)i(int)e(*status\))0 3162 y Fi(3)81 b Fj(W)-8 b(rite)32 b(v)-5 b(alues)30 b(in)m(to)i(group)e(parameters.)42 b(This)30 b(routine)g(only)h (applies)g(to)g(the)g(`Random)f(Group)s(ed')g(FITS)227 3275 y(format)22 b(whic)m(h)f(has)g(b)s(een)f(used)h(for)g (applications)h(in)f(radio)h(in)m(terferometry)-8 b(,)25 b(but)20 b(is)h(o\016cially)i(deprecated)227 3388 y(for)30 b(future)g(use.)95 3654 y Fe(int)47 b(fits_write_grppar_[byt,)42 b(sht,)k(usht,)h(int,)f(uint,)h(lng,)f(ulng,)h(lnglng,)f(flt,)g(dbl])h (/)286 3767 y(ffpgp[b,i,ui,k,uk,j,uj,jj,)o(e,d)o(])286 3880 y(\(fitsfile)f(*fptr,)g(long)g(group,)g(long)h(firstelem,)e(long)i (nelements,)334 3993 y(>)h(DTYPE)e(*array,)g(int)h(*status\))0 4260 y Fi(4)81 b Fj(W)-8 b(rite)31 b(a)g(2-D)h(or)e(3-D)h(image)h(in)m (to)f(the)g(data)g(arra)m(y)-8 b(.)95 4526 y Fe(int)47 b(fits_write_2d_[byt,)c(sht,)k(usht,)f(int,)h(uint,)f(lng,)h(ulng,)f (lnglng,)g(flt,)g(dbl])h(/)286 4639 y(ffp2d[b,i,ui,k,uk,j,uj,jj,)o(e,d) o(])286 4752 y(\(fitsfile)f(*fptr,)g(long)g(group,)g(LONGLONG)g(dim1,)g (LONGLONG)g(naxis1,)334 4865 y(LONGLONG)g(naxis2,)f(DTYPE)i(*array,)f (>)h(int)g(*status\))95 5091 y(int)g(fits_write_3d_[byt,)c(sht,)k (usht,)f(int,)h(uint,)f(lng,)h(ulng,)f(lnglng,)g(flt,)g(dbl])h(/)286 5204 y(ffp3d[b,i,ui,k,uk,j,uj,jj,)o(e,d)o(])286 5317 y(\(fitsfile)f(*fptr,)g(long)g(group,)g(LONGLONG)g(dim1,)g(LONGLONG)g (dim2,)g(LONGLONG)g(naxis1,)334 5430 y(LONGLONG)g(naxis2,)f(LONGLONG)h (naxis3,)g(DTYPE)g(*array,)g(>)h(int)g(*status\))0 5696 y Fi(5)81 b Fj(W)-8 b(rite)31 b(an)g(arbitrary)f(data)h(subsection)f (in)m(to)i(the)e(data)h(arra)m(y)-8 b(.)p eop end %%Page: 114 122 TeXDict begin 114 121 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.114) cvn H.B /DEST pdfmark end 0 299 a Fj(114)958 b Fh(CHAPTER)30 b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)95 555 y Fe(int)47 b(fits_write_subset_[byt,)42 b(sht,)k(usht,)h(int,)f(uint,)h(lng,)f(ulng,)h(lnglng,)f(flt,)g(dbl])h (/)286 668 y(ffpss[b,i,ui,k,uk,j,uj,jj,)o(e,d)o(])286 781 y(\(fitsfile)f(*fptr,)g(long)g(group,)g(long)h(naxis,)f(long)h (*naxes,)334 894 y(long)g(*fpixel,)e(long)i(*lpixel,)e(DTYPE)i(*array,) f(>)h(int)g(*status\))0 1152 y Fi(6)81 b Fj(Read)30 b(elemen)m(ts)i (from)e(the)g(FITS)g(data)h(arra)m(y)-8 b(.)95 1409 y Fe(int)47 b(fits_read_img)e(/)i(ffgpv)286 1522 y(\(fitsfile)f(*fptr,)g (int)94 b(datatype,)46 b(long)g(firstelem,)f(long)i(nelements,)334 1635 y(DTYPE)f(*nulval,)g(>)h(DTYPE)g(*array,)f(int)h(*anynul,)e(int)i (*status\))95 1861 y(int)g(fits_read_img_[byt,)c(sht,)k(usht,)f(int,)h (uint,)f(lng,)h(ulng,)f(lnglng,)g(flt,)g(dbl])h(/)286 1974 y(ffgpv[b,i,ui,k,uk,j,uj,jj,)o(e,d)o(])286 2087 y(\(fitsfile)f(*fptr,)g(long)g(group,)g(long)h(firstelem,)e(long)i (nelements,)334 2199 y(DTYPE)f(nulval,)g(>)i(DTYPE)e(*array,)g(int)h (*anynul,)e(int)i(*status\))95 2425 y(int)g(fits_read_imgnull)c(/)48 b(ffgpf)286 2538 y(\(fitsfile)e(*fptr,)g(int)94 b(datatype,)46 b(long)g(firstelem,)f(long)i(nelements,)334 2651 y(>)h(DTYPE)e(*array,) g(char)g(*nullarray,)f(int)i(*anynul,)f(int)g(*status\))95 2877 y(int)95 b(fits_read_imgnull_[byt,)42 b(sht,)k(usht,)h(int,)f (uint,)h(lng,)f(ulng,)h(flt,)f(dbl])h(/)334 2990 y (ffgpf[b,i,ui,k,uk,j,uj,jj)o(,e,)o(d])334 3103 y(\(fitsfile)e(*fptr,)h (long)h(group,)f(long)h(firstelem,)e(long)h(nelements,)334 3216 y(>)i(DTYPE)e(*array,)g(char)g(*nullarray,)f(int)i(*anynul,)f(int) g(*status\))0 3473 y Fi(7)81 b Fj(Read)29 b(v)-5 b(alues)31 b(from)e(group)g(parameters.)41 b(This)29 b(routine)g(only)h(applies)g (to)h(the)e(`Random)h(Group)s(ed')f(FITS)227 3586 y(format)22 b(whic)m(h)f(has)g(b)s(een)f(used)h(for)g(applications)h(in)f(radio)h (in)m(terferometry)-8 b(,)25 b(but)20 b(is)h(o\016cially)i(deprecated) 227 3699 y(for)30 b(future)g(use.)95 3957 y Fe(int)95 b(fits_read_grppar_[byt,)42 b(sht,)k(usht,)h(int,)f(uint,)h(lng,)f (ulng,)h(lnglng,)f(flt,)g(dbl])h(/)334 4070 y (ffggp[b,i,ui,k,uk,j,uj,jj)o(,e,)o(d])334 4183 y(\(fitsfile)e(*fptr,)h (long)h(group,)f(long)h(firstelem,)e(long)h(nelements,)334 4295 y(>)i(DTYPE)e(*array,)g(int)h(*status\))0 4553 y Fi(8)81 b Fj(Read)37 b(2-D)h(or)g(3-D)g(image)g(from)f(the)g(data)h (arra)m(y)-8 b(.)62 b(Unde\014ned)36 b(pixels)i(in)e(the)i(arra)m(y)g (will)f(b)s(e)g(set)g(equal)227 4666 y(to)32 b(the)g(v)-5 b(alue)31 b(of)h('n)m(ulv)-5 b(al',)32 b(unless)f(n)m(ulv)-5 b(al=0)31 b(in)g(whic)m(h)g(case)h(no)f(testing)i(for)e(unde\014ned)e (pixels)i(will)h(b)s(e)227 4779 y(p)s(erformed.)95 5036 y Fe(int)95 b(fits_read_2d_[byt,)43 b(sht,)k(usht,)f(int,)h(uint,)f (lng,)h(ulng,)f(lnglng,)g(flt,)g(dbl])h(/)334 5149 y (ffg2d[b,i,ui,k,uk,j,uj,jj)o(,e,)o(d])334 5262 y(\(fitsfile)e(*fptr,)h (long)h(group,)f(DTYPE)h(nulval,)e(LONGLONG)h(dim1,)g(LONGLONG)g (naxis1,)334 5375 y(LONGLONG)g(naxis2,)f(>)j(DTYPE)e(*array,)g(int)h (*anynul,)f(int)g(*status\))95 5601 y(int)95 b(fits_read_3d_[byt,)43 b(sht,)k(usht,)f(int,)h(uint,)f(lng,)h(ulng,)f(lnglng,)g(flt,)g(dbl])h (/)334 5714 y(ffg3d[b,i,ui,k,uk,j,uj,jj)o(,e,)o(d])p eop end %%Page: 115 123 TeXDict begin 115 122 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.115) cvn H.B /DEST pdfmark end 0 299 a Fh(9.6.)72 b(SPECIALIZED)29 b(FITS)g(ASCI)s(I)g(AND)i(BINAR)-8 b(Y)32 b(T)-8 b(ABLE)30 b(R)m(OUTINES)933 b Fj(115)334 555 y Fe(\(fitsfile)45 b(*fptr,)h(long)h(group,)f(DTYPE)h(nulval,)e(LONGLONG)h(dim1,)334 668 y(LONGLONG)g(dim2,)g(LONGLONG)g(naxis1,)f(LONGLONG)h(naxis2,)g (LONGLONG)f(naxis3,)334 781 y(>)j(DTYPE)e(*array,)g(int)h(*anynul,)e (int)i(*status\))0 1053 y Fi(9)81 b Fj(Read)30 b(an)g(arbitrary)h(data) g(subsection)f(from)g(the)g(data)i(arra)m(y)-8 b(.)95 1325 y Fe(int)95 b(fits_read_subset_[byt,)42 b(sht,)k(usht,)h(int,)f (uint,)h(lng,)f(ulng,)h(lnglng,)f(flt,)g(dbl])h(/)334 1438 y(ffgsv[b,i,ui,k,uk,j,uj,jj)o(,e,)o(d])334 1551 y(\(fitsfile)e(*fptr,)h(int)h(group,)f(int)h(naxis,)f(long)h(*naxes,) 334 1664 y(long)g(*fpixel,)e(long)i(*lpixel,)e(long)i(*inc,)f(DTYPE)h (nulval,)334 1777 y(>)h(DTYPE)e(*array,)g(int)h(*anynul,)e(int)i (*status\))95 2002 y(int)95 b(fits_read_subsetnull_[byt)o(,)42 b(sht,)k(usht,)h(int,)f(uint,)h(lng,)f(ulng,)h(lnglng,)f(flt,)g(dbl])h (/)334 2115 y(ffgsf[b,i,ui,k,uk,j,uj,jj)o(,e,)o(d])334 2228 y(\(fitsfile)e(*fptr,)h(int)h(group,)f(int)h(naxis,)f(long)h (*naxes,)334 2341 y(long)g(*fpixel,)e(long)i(*lpixel,)e(long)i(*inc,)f (>)i(DTYPE)e(*array,)334 2454 y(char)h(*nullarray,)d(int)j(*anynul,)f (int)h(*status\))0 2626 y SDict begin H.S end 0 2626 a 0 2626 a SDict begin 13.6 H.A end 0 2626 a 0 2626 a SDict begin [ /View [/XYZ H.V] /Dest (section.9.6) cvn H.B /DEST pdfmark end 0 2626 a 176 x Ff(9.6)135 b(Sp)t(ecialized)46 b(FITS)e(ASCI)t(I)g(and)g(Binary)h(T)-11 b(able)45 b(Routines)0 2918 y SDict begin H.S end 0 2918 a 0 2918 a SDict begin 13.6 H.A end 0 2918 a 0 2918 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.9.6.1) cvn H.B /DEST pdfmark end 0 2918 a 140 x Fd(9.6.1)112 b(General)39 b(Column)f(Routines)0 3276 y Fi(1)81 b Fj(Get)31 b(information)f(ab)s(out)g(an)g(existing)h(ASCI)s (I)d(or)i(binary)f(table)i(column.)41 b(A)30 b(n)m(ull)g(p)s(oin)m(ter) g(ma)m(y)h(b)s(e)e(giv)m(en)227 3389 y(for)40 b(an)m(y)h(of)f(the)h (output)f(parameters)g(that)h(are)g(not)f(needed.)70 b(D)m(A)-8 b(T)g(A)g(TYPE)42 b(is)e(a)h(c)m(haracter)h(string)227 3502 y(whic)m(h)d(returns)e(the)i(data)g(t)m(yp)s(e)g(of)g(the)f (column)h(as)g(de\014ned)e(b)m(y)i(the)f(TF)m(ORMn)h(k)m(eyw)m(ord)g (\(e.g.,)j('I',)227 3615 y('J','E',)28 b('D',)g(etc.\).)41 b(In)27 b(the)g(case)g(of)g(an)g(ASCI)s(I)f(c)m(haracter)i(column,)g(t) m(yp)s(eco)s(de)f(will)g(ha)m(v)m(e)h(a)f(v)-5 b(alue)28 b(of)f(the)227 3728 y(form)g('An')g(where)f('n')h(is)g(an)g(in)m(teger) i(expressing)d(the)h(width)g(of)g(the)g(\014eld)g(in)f(c)m(haracters.) 41 b(F)-8 b(or)28 b(example,)227 3841 y(if)g(TF)m(ORM)h(=)e('160A8')k (then)d(\013gb)s(cl)g(will)g(return)f(t)m(yp)s(ec)m(har='A8')j(and)d (rep)s(eat=20.)41 b(All)29 b(the)f(returned)227 3954 y(parameters)j(are)g(scalar)g(quan)m(tities.)95 4226 y Fe(int)47 b(fits_get_acolparms)c(/)48 b(ffgacl)191 4339 y(\(fitsfile)d(*fptr,)h(int)h(colnum,)f(>)h(char)g(*ttype,)f(long) h(*tbcol,)239 4452 y(char)f(*tunit,)g(char)h(*tform,)f(double)g (*scale,)f(double)i(*zero,)239 4565 y(char)f(*nulstr,)g(char)g(*tdisp,) g(int)h(*status\))95 4790 y(int)g(fits_get_bcolparms)c(/)48 b(ffgbcl)286 4903 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(>)j(char)f (*ttype,)e(char)i(*tunit,)334 5016 y(char)g(*typechar,)e(long)h (*repeat,)g(double)g(*scale,)g(double)g(*zero,)334 5129 y(long)h(*nulval,)e(char)i(*tdisp,)f(int)94 b(*status\))95 5355 y(int)47 b(fits_get_bcolparmsll)c(/)k(ffgbclll)286 5468 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(>)j(char)f(*ttype,)e(char) i(*tunit,)334 5581 y(char)g(*typechar,)e(LONGLONG)g(*repeat,)h(double)g (*scale,)g(double)g(*zero,)334 5694 y(LONGLONG)g(*nulval,)f(char)i (*tdisp,)f(int)94 b(*status\))p eop end %%Page: 116 124 TeXDict begin 116 123 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.116) cvn H.B /DEST pdfmark end 0 299 a Fj(116)958 b Fh(CHAPTER)30 b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)0 555 y Fi(2)81 b Fj(Return)27 b(optimal)i(n)m(um)m(b)s (er)e(of)h(ro)m(ws)g(to)h(read)f(or)g(write)g(at)h(one)f(time)h(for)f (maxim)m(um)g(I/O)f(e\016ciency)-8 b(.)42 b(Refer)227 668 y(to)25 b(the)g(\\Optimizing)g(Co)s(de")f(section)i(in)e(Chapter)g (5)g(for)g(more)h(discussion)f(on)g(ho)m(w)g(to)h(use)f(this)h (routine.)95 1026 y Fe(int)47 b(fits_get_rowsize)d(/)j(ffgrsz)286 1139 y(\(fitsfile)f(*fptr,)g(long)g(*nrows,)g(*status\))0 1384 y Fi(3)81 b Fj(De\014ne)22 b(the)g(zero)i(indexed)d(b)m(yte)i (o\013set)g(of)g(the)f('heap')h(measured)e(from)h(the)h(start)g(of)f (the)g(binary)g(table)h(data.)227 1497 y(By)30 b(default)g(the)f(heap)h (is)f(assumed)g(to)h(start)g(immediately)h(follo)m(wing)g(the)f (regular)f(table)i(data,)f(i.e.,)h(at)227 1610 y(lo)s(cation)38 b(NAXIS1)f(x)g(NAXIS2.)59 b(This)36 b(routine)g(is)h(only)f(relev)-5 b(an)m(t)38 b(for)e(binary)g(tables)h(whic)m(h)g(con)m(tain)227 1723 y(v)-5 b(ariable)25 b(length)g(arra)m(y)g(columns)f(\(with)g(TF)m (ORMn)g(=)g('Pt'\).)40 b(This)23 b(routine)i(also)g(automatically)i (writes)227 1836 y(the)35 b(v)-5 b(alue)35 b(of)g(theap)f(to)h(a)g(k)m (eyw)m(ord)g(in)g(the)f(extension)h(header.)53 b(This)34 b(routine)g(m)m(ust)h(b)s(e)f(called)h(after)227 1949 y(the)c(required)e(k)m(eyw)m(ords)h(ha)m(v)m(e)i(b)s(een)d(written)h (\(with)g(\013ph)m(bn\))f(but)h(b)s(efore)f(an)m(y)i(data)g(is)f (written)g(to)h(the)227 2062 y(table.)95 2307 y Fe(int)47 b(fits_write_theap)d(/)j(ffpthp)286 2420 y(\(fitsfile)f(*fptr,)g(long)g (theap,)g(>)i(int)f(*status\))0 2665 y Fi(4)81 b Fj(T)-8 b(est)37 b(the)f(con)m(ten)m(ts)i(of)f(the)g(binary)e(table)j(v)-5 b(ariable)37 b(arra)m(y)g(heap,)h(returning)e(the)g(size)h(of)g(the)g (heap,)h(the)227 2778 y(n)m(um)m(b)s(er)30 b(of)h(un)m(used)e(b)m(ytes) j(that)f(are)g(not)g(curren)m(tly)g(p)s(oin)m(ted)g(to)h(b)m(y)e(an)m (y)i(of)f(the)g(descriptors,)g(and)f(the)227 2891 y(n)m(um)m(b)s(er)d (of)h(b)m(ytes)h(whic)m(h)f(are)g(p)s(oin)m(ted)g(to)h(b)m(y)f(m)m (ultiple)h(descriptors.)40 b(It)28 b(also)h(returns)e(v)-5 b(alid)29 b(=)e(F)-10 b(ALSE)227 3003 y(if)31 b(an)m(y)f(of)h(the)f (descriptors)h(p)s(oin)m(t)f(to)h(in)m(v)-5 b(alid)31 b(addresses)f(out)g(of)h(range)g(of)f(the)h(heap.)95 3249 y Fe(int)47 b(fits_test_heap)d(/)k(fftheap)286 3361 y(\(fitsfile)e(*fptr,)g(>)h(LONGLONG)f(*heapsize,)f(LONGLONG)g (*unused,)h(LONGLONG)f(*overlap,)334 3474 y(int)i(*validheap,)e(int)i (*status\))0 3720 y Fi(5)81 b Fj(Re-pac)m(k)33 b(the)f(v)m(ectors)h(in) e(the)h(binary)f(table)i(v)-5 b(ariable)32 b(arra)m(y)g(heap)g(to)g (reco)m(v)m(er)i(an)m(y)e(un)m(used)e(space.)45 b(Nor-)227 3832 y(mally)-8 b(,)40 b(when)d(a)g(v)m(ector)i(in)e(a)g(v)-5 b(ariable)38 b(length)g(arra)m(y)f(column)g(is)g(rewritten)h(the)f (previously)g(written)227 3945 y(arra)m(y)d(remains)e(in)h(the)g(heap)f (as)h(w)m(asted)h(un)m(used)d(space.)49 b(This)32 b(routine)g(will)i (repac)m(k)f(the)g(arra)m(ys)g(that)227 4058 y(are)h(still)g(in)f(use,) h(th)m(us)f(eliminating)h(an)m(y)g(b)m(ytes)g(in)f(the)g(heap)g(that)h (are)g(no)f(longer)h(in)f(use.)49 b(Note)34 b(that)227 4171 y(if)f(sev)m(eral)h(v)m(ectors)g(p)s(oin)m(t)e(to)i(the)e(same)h (b)m(ytes)g(in)g(the)f(heap,)i(then)e(this)g(routine)h(will)g(mak)m(e)g (duplicate)227 4284 y(copies)e(of)g(the)g(b)m(ytes)f(for)h(eac)m(h)g(v) m(ector,)h(whic)m(h)e(will)h(actually)h(expand)e(the)g(size)i(of)e(the) h(heap.)95 4529 y Fe(int)47 b(fits_compress_heap)c(/)48 b(ffcmph)286 4642 y(\(fitsfile)e(*fptr,)g(>)h(int)g(*status\))0 4787 y SDict begin H.S end 0 4787 a 0 4787 a SDict begin 13.6 H.A end 0 4787 a 0 4787 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.9.6.2) cvn H.B /DEST pdfmark end 0 4787 a 143 x Fd(9.6.2)112 b(Lo)m(w-Lev)m(el)39 b(T)-9 b(able)38 b(Access)f(Routines)0 5149 y Fj(The)g(follo)m(wing)j(2)e(routines)f (pro)m(vide)h(lo)m(w-lev)m(el)j(access)e(to)g(the)f(data)g(in)g(ASCI)s (I)e(or)i(binary)f(tables)h(and)g(are)0 5262 y(mainly)29 b(useful)f(as)i(an)f(e\016cien)m(t)h(w)m(a)m(y)g(to)g(cop)m(y)g(all)g (or)f(part)g(of)g(a)g(table)h(from)f(one)g(lo)s(cation)i(to)f(another.) 40 b(These)0 5375 y(routines)24 b(simply)g(read)g(or)h(write)f(the)h (sp)s(eci\014ed)e(n)m(um)m(b)s(er)g(of)i(consecutiv)m(e)h(b)m(ytes)f (in)f(an)g(ASCI)s(I)f(or)h(binary)g(table,)0 5488 y(without)g(regard)g (for)f(column)h(b)s(oundaries)e(or)i(the)g(ro)m(w)g(length)g(in)f(the)h (table.)40 b(These)23 b(routines)h(do)f(not)h(p)s(erform)0 5601 y(an)m(y)36 b(mac)m(hine)h(dep)s(enden)m(t)e(data)i(con)m(v)m (ersion)g(or)g(b)m(yte)f(sw)m(apping.)58 b(See)36 b(App)s(endix)e(B)j (for)f(the)g(de\014nition)g(of)0 5714 y(the)31 b(parameters)f(used)g (in)g(these)h(routines.)p eop end %%Page: 117 125 TeXDict begin 117 124 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.117) cvn H.B /DEST pdfmark end 0 299 a Fh(9.6.)72 b(SPECIALIZED)29 b(FITS)g(ASCI)s(I)g(AND)i(BINAR)-8 b(Y)32 b(T)-8 b(ABLE)30 b(R)m(OUTINES)933 b Fj(117)0 555 y Fi(1)81 b Fj(Read)30 b(or)h(write)f(a)h(consecutiv)m(e)h(arra)m(y)f(of)g(b)m(ytes)f(from)g (an)h(ASCI)s(I)d(or)j(binary)e(table)95 817 y Fe(int)47 b(fits_read_tblbytes)c(/)48 b(ffgtbb)286 930 y(\(fitsfile)e(*fptr,)g (LONGLONG)f(firstrow,)h(LONGLONG)f(firstchar,)g(LONGLONG)h(nchars,)334 1043 y(>)i(unsigned)d(char)i(*values,)e(int)i(*status\))95 1269 y(int)g(fits_write_tblbytes)c(/)k(ffptbb)286 1382 y(\(fitsfile)f(*fptr,)g(LONGLONG)f(firstrow,)h(LONGLONG)f(firstchar,)g (LONGLONG)h(nchars,)334 1494 y(unsigned)g(char)g(*values,)g(>)h(int)g (*status\))0 1644 y SDict begin H.S end 0 1644 a 0 1644 a SDict begin 13.6 H.A end 0 1644 a 0 1644 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.9.6.3) cvn H.B /DEST pdfmark end 0 1644 a 143 x Fd(9.6.3)112 b(W)-9 b(rite)37 b(Column)h(Data)g (Routines)0 1998 y Fi(1)81 b Fj(W)-8 b(rite)28 b(elemen)m(ts)h(in)m(to) f(an)g(ASCI)s(I)d(or)j(binary)e(table)j(column)e(\(in)g(the)h(CDU\).)g (The)f(data)h(t)m(yp)s(e)f(of)h(the)f(arra)m(y)227 2111 y(is)k(implied)f(b)m(y)g(the)h(su\016x)e(of)i(the)f(routine)h(name.)95 2373 y Fe(int)47 b(fits_write_col_str)c(/)48 b(ffpcls)286 2486 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(LONGLONG)h(firstrow,)f (LONGLONG)h(firstelem,)334 2598 y(LONGLONG)g(nelements,)f(char)h (**array,)g(>)h(int)g(*status\))95 2824 y(int)g (fits_write_col_[log,byt,sh)o(t,u)o(sht,)o(int,)o(uin)o(t,ln)o(g,ul)o (ng,)o(lngl)o(ng,f)o(lt,)o(dbl,)o(cmp,)o(dbl)o(cmp])41 b(/)286 2937 y(ffpcl[l,b,i,ui,k,uk,j,uj,j)o(j,e)o(,d,c)o(,m])286 3050 y(\(fitsfile)46 b(*fptr,)g(int)h(colnum,)e(LONGLONG)h(firstrow,) 525 3163 y(LONGLONG)g(firstelem,)f(LONGLONG)g(nelements,)g(DTYPE)h (*array,)g(>)i(int)f(*status\))0 3425 y Fi(2)81 b Fj(W)-8 b(rite)36 b(elemen)m(ts)h(in)m(to)g(an)e(ASCI)s(I)f(or)i(binary)e (table)j(column)e(substituting)g(the)h(appropriate)f(FITS)g(n)m(ull)227 3538 y(v)-5 b(alue)31 b(for)f(an)m(y)h(elemen)m(ts)h(that)f(are)f (equal)h(to)g(the)g(n)m(ulv)-5 b(al)31 b(parameter.)95 3799 y Fe(int)47 b(fits_write_colnull_[log,)42 b(byt,)k(sht,)h(usht,)f (int,)h(uint,)f(lng,)h(ulng,)f(lnglng,)g(flt,)h(dbl])f(/)286 3912 y(ffpcn[l,b,i,ui,k,uk,j,uj,j)o(j,e)o(,d])286 4025 y(\(fitsfile)g(*fptr,)g(int)h(colnum,)e(LONGLONG)h(firstrow,)f (LONGLONG)h(firstelem,)334 4138 y(LONGLONG)g(nelements,)f(DTYPE)h (*array,)g(DTYPE)g(nulval,)g(>)h(int)g(*status\))0 4400 y Fi(3)81 b Fj(W)-8 b(rite)27 b(string)g(elemen)m(ts)h(in)m(to)f(a)g (binary)f(table)h(column)f(\(in)h(the)f(CDU\))i(substituting)e(the)g (FITS)g(n)m(ull)g(v)-5 b(alue)227 4513 y(for)30 b(an)m(y)h(elemen)m(ts) h(that)f(are)g(equal)f(to)i(the)e(n)m(ulstr)g(string.)95 4775 y Fe(int)47 b(fits_write_colnull_str)42 b(/)48 b(ffpcns)286 4888 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(LONGLONG)h(firstrow,)f (LONGLONG)h(firstelem,)334 5000 y(LONGLONG)g(nelements,)f(char)h (**array,)g(char)g(*nulstr,)g(>)h(int)g(*status\))0 5262 y Fi(4)81 b Fj(W)-8 b(rite)34 b(bit)f(v)-5 b(alues)33 b(in)m(to)h(a)g(binary)e(b)m(yte)h(\('B'\))i(or)e(bit)g(\('X'\))h (table)g(column)f(\(in)g(the)g(CDU\).)h(Larra)m(y)f(is)g(an)227 5375 y(arra)m(y)25 b(of)g(c)m(haracters)h(corresp)s(onding)e(to)h(the)g (sequence)g(of)f(bits)h(to)g(b)s(e)f(written.)39 b(If)24 b(an)g(elemen)m(t)i(of)f(larra)m(y)227 5488 y(is)k(true)g(\(not)h (equal)f(to)h(zero\))g(then)f(the)g(corresp)s(onding)f(bit)h(in)g(the)g (FITS)f(table)i(is)f(set)h(to)g(1,)g(otherwise)227 5601 y(the)37 b(bit)g(is)g(set)g(to)g(0.)60 b(The)37 b('X')g(column)f(in)h (a)g(FITS)f(table)h(is)g(alw)m(a)m(ys)h(padded)e(out)h(to)g(a)g(m)m (ultiple)h(of)227 5714 y(8)f(bits)f(where)g(the)g(bit)h(arra)m(y)f (starts)h(with)f(the)h(most)f(signi\014can)m(t)h(bit)g(of)f(the)h(b)m (yte)g(and)e(w)m(orks)h(do)m(wn)p eop end %%Page: 118 126 TeXDict begin 118 125 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.118) cvn H.B /DEST pdfmark end 0 299 a Fj(118)958 b Fh(CHAPTER)30 b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)227 555 y Fj(to)m(w)m(ards)37 b(the)g(1's)f(bit.)59 b(F)-8 b(or)37 b(example,)i(a)d('4X')h(arra)m(y)-8 b(,)39 b(with)d(the)h(\014rst)e(bit)i(=)e(1)i(and)f(the)g(remaining)h(3)227 668 y(bits)31 b(=)g(0)h(is)f(equiv)-5 b(alen)m(t)33 b(to)f(the)g(8-bit) g(unsigned)e(b)m(yte)i(decimal)g(v)-5 b(alue)32 b(of)g(128)g(\('1000)i (0000B'\).)g(In)d(the)227 781 y(case)h(of)f('X')g(columns,)g(CFITSIO)f (can)h(write)g(to)g(all)h(8)f(bits)g(of)g(eac)m(h)h(b)m(yte)f(whether)f (they)h(are)g(formally)227 894 y(v)-5 b(alid)34 b(or)f(not.)50 b(Th)m(us)32 b(if)i(the)f(column)g(is)h(de\014ned)e(as)h('4X',)i(and)e (one)g(calls)i(\013p)s(clx)e(with)g(\014rstbit=1)g(and)227 1007 y(n)m(bits=8,)i(then)f(all)g(8)h(bits)e(will)h(b)s(e)g(written)g (in)m(to)g(the)g(\014rst)f(b)m(yte)i(\(as)f(opp)s(osed)f(to)i(writing)e (the)h(\014rst)g(4)227 1120 y(bits)28 b(in)m(to)h(the)e(\014rst)g(ro)m (w)h(and)f(then)h(the)g(next)g(4)g(bits)f(in)m(to)i(the)f(next)g(ro)m (w\),)h(ev)m(en)f(though)f(the)h(last)h(4)f(bits)227 1233 y(of)j(eac)m(h)g(b)m(yte)g(are)f(formally)h(not)f(de\014ned)f(and) h(should)f(all)i(b)s(e)e(set)i(=)f(0.)41 b(It)30 b(should)f(also)j(b)s (e)d(noted)h(that)227 1346 y(it)k(is)e(more)h(e\016cien)m(t)i(to)e (write)g('X')h(columns)e(an)h(en)m(tire)h(b)m(yte)f(at)h(a)f(time,)h (instead)f(of)g(bit)g(b)m(y)g(bit.)48 b(An)m(y)227 1458 y(of)31 b(the)g(CFITSIO)e(routines)h(that)i(write)f(to)g(columns)f (\(e.g.)43 b(\014ts)p 2481 1458 28 4 v 33 w(write)p 2716 1458 V 33 w(col)p 2859 1458 V 33 w(b)m(yt\))32 b(ma)m(y)f(b)s(e)f(used) g(for)g(this)227 1571 y(purp)s(ose.)60 b(These)36 b(routines)i(will)f (in)m(terpret)h('X')f(columns)g(as)g(though)g(they)h(w)m(ere)f('B')h (columns)f(\(e.g.,)227 1684 y('1X')32 b(through)d('8X')j(is)e(equiv)-5 b(alen)m(t)32 b(to)f('1B',)h(and)e('9X')h(through)f('16X')i(is)e(equiv) -5 b(alen)m(t)32 b(to)f('2B'\).)95 1932 y Fe(int)47 b (fits_write_col_bit)c(/)48 b(ffpclx)286 2045 y(\(fitsfile)e(*fptr,)g (int)h(colnum,)e(LONGLONG)h(firstrow,)f(long)i(firstbit,)334 2158 y(long)g(nbits,)f(char)g(*larray,)g(>)h(int)g(*status\))0 2405 y Fi(5)81 b Fj(W)-8 b(rite)35 b(the)f(descriptor)g(for)f(a)h(v)-5 b(ariable)35 b(length)f(column)g(in)f(a)i(binary)e(table.)52 b(This)33 b(routine)g(can)i(b)s(e)e(used)227 2518 y(in)h(conjunction)g (with)f(\013gdes)h(to)h(enable)f(2)g(or)g(more)g(arra)m(ys)h(to)f(p)s (oin)m(t)g(to)h(the)f(same)g(storage)h(lo)s(cation)227 2631 y(to)c(sa)m(v)m(e)h(storage)g(space)f(if)f(the)h(arra)m(ys)g(are)g (iden)m(tical.)191 2879 y Fe(int)47 b(fits_write_descript)42 b(/)48 b(ffpdes)382 2992 y(\(fitsfile)d(*fptr,)h(int)h(colnum,)f (LONGLONG)f(rownum,)h(LONGLONG)g(repeat,)430 3105 y(LONGLONG)f(offset,) h(>)h(int)g(*status\))0 3243 y SDict begin H.S end 0 3243 a 0 3243 a SDict begin 13.6 H.A end 0 3243 a 0 3243 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.9.6.4) cvn H.B /DEST pdfmark end 0 3243 a 151 x Fd(9.6.4)112 b(Read)38 b(Column)h(Data)f (Routines)0 3612 y Fj(Tw)m(o)28 b(t)m(yp)s(es)f(of)h(routines)f(are)h (pro)m(vided)f(to)h(get)h(the)e(column)h(data)g(whic)m(h)f(di\013er)g (in)g(the)h(w)m(a)m(y)h(unde\014ned)c(pixels)0 3725 y(are)40 b(handled.)66 b(The)39 b(\014rst)g(set)h(of)f(routines)g(\(\013gcv\))i (simply)e(return)f(an)h(arra)m(y)h(of)g(data)g(elemen)m(ts)g(in)f(whic) m(h)0 3838 y(unde\014ned)28 b(pixels)j(are)g(set)g(equal)g(to)g(a)g(v) -5 b(alue)31 b(sp)s(eci\014ed)f(b)m(y)h(the)f(user)g(in)g(the)h('n)m (ullv)-5 b(al')32 b(parameter.)41 b(If)30 b(n)m(ullv)-5 b(al)0 3951 y(=)22 b(0,)j(then)d(no)g(c)m(hec)m(ks)i(for)e(unde\014ned) e(pixels)j(will)g(b)s(e)f(p)s(erformed,)g(th)m(us)g(increasing)i(the)e (sp)s(eed)g(of)g(the)h(program.)0 4064 y(The)36 b(second)g(set)g(of)h (routines)e(\(\013gcf)7 b(\))38 b(returns)d(the)h(data)h(elemen)m(t)g (arra)m(y)g(and)e(in)h(addition)g(a)h(logical)h(arra)m(y)0 4177 y(of)33 b(\015ags)f(whic)m(h)g(de\014nes)g(whether)g(the)g (corresp)s(onding)g(data)h(pixel)f(is)h(unde\014ned.)44 b(See)33 b(App)s(endix)e(B)i(for)f(the)0 4290 y(de\014nition)e(of)h (the)f(parameters)h(used)e(in)h(these)h(routines.)0 4450 y(An)m(y)39 b(column,)h(regardless)f(of)g(it's)g(in)m(trinsic)g(data)h (t)m(yp)s(e,)h(ma)m(y)e(b)s(e)f(read)g(as)h(a)g(string.)66 b(It)38 b(should)g(b)s(e)g(noted)0 4563 y(ho)m(w)m(ev)m(er)32 b(that)f(reading)f(a)h(n)m(umeric)f(column)g(as)h(a)f(string)h(is)f(10) h(-)g(100)g(times)g(slo)m(w)m(er)h(than)e(reading)g(the)h(same)0 4676 y(column)g(as)h(a)g(n)m(um)m(b)s(er)e(due)h(to)h(the)g(large)h(o)m (v)m(erhead)f(in)g(constructing)g(the)g(formatted)g(strings.)44 b(The)31 b(displa)m(y)0 4789 y(format)26 b(of)g(the)h(returned)d (strings)i(will)g(b)s(e)g(determined)f(b)m(y)h(the)g(TDISPn)f(k)m(eyw)m (ord,)j(if)d(it)i(exists,)h(otherwise)e(b)m(y)0 4902 y(the)h(data)g(t)m(yp)s(e)f(of)h(the)f(column.)39 b(The)26 b(length)h(of)g(the)f(returned)f(strings)h(\(not)h(including)f(the)h(n) m(ull)f(terminating)0 5015 y(c)m(haracter\))38 b(can)e(b)s(e)g (determined)f(with)h(the)g(\014ts)p 1722 5015 28 4 v 33 w(get)p 1875 5015 V 34 w(col)p 2019 5015 V 33 w(displa)m(y)p 2330 5015 V 33 w(width)g(routine.)57 b(The)36 b(follo)m(wing)h(TDISPn)0 5127 y(displa)m(y)31 b(formats)f(are)h(curren)m(tly)f(supp)s(orted:)191 5375 y Fe(Iw.m)142 b(Integer)191 5488 y(Ow.m)g(Octal)46 b(integer)191 5601 y(Zw.m)142 b(Hexadecimal)45 b(integer)191 5714 y(Fw.d)142 b(Fixed)46 b(floating)g(point)p eop end %%Page: 119 127 TeXDict begin 119 126 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.119) cvn H.B /DEST pdfmark end 0 299 a Fh(9.6.)72 b(SPECIALIZED)29 b(FITS)g(ASCI)s(I)g(AND)i(BINAR)-8 b(Y)32 b(T)-8 b(ABLE)30 b(R)m(OUTINES)933 b Fj(119)191 555 y Fe(Ew.d)142 b(Exponential)45 b(floating)g(point)191 668 y(Dw.d)142 b(Exponential)45 b(floating)g(point)191 781 y(Gw.d)142 b(General;)46 b(uses)g(Fw.d)h(if) g(significance)d(not)j(lost,)g(else)f(Ew.d)0 1020 y Fj(where)37 b(w)h(is)g(the)g(width)f(in)h(c)m(haracters)h(of)f(the)h(displa)m(y)m (ed)f(v)-5 b(alues,)41 b(m)c(is)h(the)g(minim)m(um)g(n)m(um)m(b)s(er)e (of)i(digits)0 1133 y(displa)m(y)m(ed,)31 b(and)f(d)g(is)g(the)h(n)m (um)m(b)s(er)e(of)h(digits)h(to)g(the)g(righ)m(t)g(of)g(the)f(decimal.) 42 b(The)30 b(.m)g(\014eld)g(is)g(optional.)0 1371 y Fi(1)81 b Fj(Read)29 b(elemen)m(ts)i(from)e(an)g(ASCI)s(I)f(or)i (binary)f(table)h(column)f(\(in)h(the)f(CDU\).)i(These)e(routines)g (return)g(the)227 1484 y(v)-5 b(alues)30 b(of)g(the)g(table)h(column)f (arra)m(y)g(elemen)m(ts.)42 b(Unde\014ned)28 b(arra)m(y)j(elemen)m(ts)g (will)f(b)s(e)f(returned)g(with)h(a)227 1597 y(v)-5 b(alue)30 b(=)e(n)m(ulv)-5 b(al,)30 b(unless)e(n)m(ulv)-5 b(al)29 b(=)f(0)i(\(or)f(=)f(')h(')g(for)g(\013gcvs\))g(in)g(whic)m(h)f(case)i (no)f(c)m(hec)m(king)i(for)d(unde\014ned)227 1710 y(v)-5 b(alues)28 b(will)g(b)s(e)f(p)s(erformed.)38 b(The)27 b(an)m(yn)m(ul)h(parameter)g(is)g(set)g(to)g(true)f(if)h(an)m(y)g(of)f (the)h(returned)f(elemen)m(ts)227 1823 y(are)k(unde\014ned.)95 2062 y Fe(int)47 b(fits_read_col_str)c(/)48 b(ffgcvs)286 2175 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(LONGLONG)h(firstrow,)f (LONGLONG)h(firstelem,)334 2288 y(LONGLONG)g(nelements,)f(char)h (*nulstr,)g(>)h(char)g(**array,)e(int)i(*anynul,)334 2401 y(int)g(*status\))95 2626 y(int)g(fits_read_col_[log,byt,sht)o (,us)o(ht,i)o(nt,u)o(int)o(,lng)o(,uln)o(g,)41 b(lnglng,)46 b(flt,)h(dbl,)g(cmp,)f(dblcmp])g(/)286 2739 y (ffgcv[l,b,i,ui,k,uk,j,uj,j)o(j,e)o(,d,c)o(,m])286 2852 y(\(fitsfile)g(*fptr,)g(int)h(colnum,)e(LONGLONG)h(firstrow,)f (LONGLONG)h(firstelem,)334 2965 y(LONGLONG)g(nelements,)f(DTYPE)h (nulval,)g(>)h(DTYPE)g(*array,)e(int)i(*anynul,)334 3078 y(int)g(*status\))0 3317 y Fi(2)81 b Fj(Read)39 b(elemen)m(ts)i(and)e (n)m(ull)h(\015ags)g(from)f(an)g(ASCI)s(I)g(or)g(binary)g(table)i (column)e(\(in)h(the)g(CHDU\).)g(These)227 3430 y(routines)29 b(return)e(the)i(v)-5 b(alues)29 b(of)g(the)g(table)h(column)e(arra)m (y)i(elemen)m(ts.)41 b(An)m(y)29 b(unde\014ned)d(arra)m(y)k(elemen)m (ts)227 3543 y(will)k(ha)m(v)m(e)h(the)f(corresp)s(onding)e(n)m (ullarra)m(y)i(elemen)m(t)h(set)f(equal)g(to)g(TR)m(UE.)g(The)f(an)m (yn)m(ul)h(parameter)g(is)227 3656 y(set)d(to)g(true)f(if)h(an)m(y)g (of)f(the)h(returned)e(elemen)m(ts)j(are)e(unde\014ned.)95 3894 y Fe(int)47 b(fits_read_colnull_str)42 b(/)48 b(ffgcfs)286 4007 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(LONGLONG)h(firstrow,)f (LONGLONG)h(firstelem,)334 4120 y(LONGLONG)g(nelements,)f(>)i(char)g (**array,)e(char)i(*nullarray,)e(int)i(*anynul,)334 4233 y(int)g(*status\))95 4459 y(int)g(fits_read_colnull_[log,byt)o(,sh)o (t,us)o(ht,i)o(nt,)o(uint)o(,lng)o(,ul)o(ng,l)o(ngln)o(g,f)o(lt,d)o (bl,c)o(mp,)o(dblc)o(mp])41 b(/)286 4572 y(ffgcf[l,b,i,ui,k,uk,j,uj,j)o (j,e)o(,d,c)o(,m])286 4685 y(\(fitsfile)46 b(*fptr,)g(int)h(colnum,)e (LONGLONG)h(firstrow,)334 4798 y(LONGLONG)g(firstelem,)f(LONGLONG)g (nelements,)g(>)j(DTYPE)e(*array,)334 4911 y(char)h(*nullarray,)d(int)j (*anynul,)f(int)h(*status\))0 5149 y Fi(3)81 b Fj(Read)24 b(an)g(arbitrary)g(data)h(subsection)f(from)g(an)g(N-dimensional)h (arra)m(y)g(in)f(a)g(binary)g(table)h(v)m(ector)h(column.)227 5262 y(Unde\014ned)21 b(pixels)i(in)f(the)h(arra)m(y)g(will)g(b)s(e)f (set)h(equal)h(to)f(the)g(v)-5 b(alue)23 b(of)g('n)m(ulv)-5 b(al',)25 b(unless)d(n)m(ulv)-5 b(al=0)23 b(in)f(whic)m(h)227 5375 y(case)37 b(no)e(testing)h(for)f(unde\014ned)e(pixels)i(will)h(b)s (e)f(p)s(erformed.)53 b(The)35 b(\014rst)g(and)f(last)i(ro)m(ws)g(in)f (the)g(table)227 5488 y(to)30 b(b)s(e)e(read)h(are)g(sp)s(eci\014ed)g (b)m(y)g(fpixel\(naxis+1\))g(and)g(lpixel\(naxis+1\),)i(and)d(hence)h (are)h(treated)g(as)f(the)227 5601 y(next)38 b(higher)f(dimension)g(of) h(the)f(FITS)g(N-dimensional)h(arra)m(y)-8 b(.)63 b(The)37 b(INC)h(parameter)g(sp)s(eci\014es)f(the)227 5714 y(sampling)31 b(in)m(terv)-5 b(al)31 b(in)f(eac)m(h)i(dimension)e(b)s(et)m(w)m(een)h (the)f(data)h(elemen)m(ts)h(that)f(will)g(b)s(e)e(returned.)p eop end %%Page: 120 128 TeXDict begin 120 127 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.120) cvn H.B /DEST pdfmark end 0 299 a Fj(120)958 b Fh(CHAPTER)30 b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)95 555 y Fe(int)47 b(fits_read_subset_[byt,)42 b(sht,)47 b(usht,)f(int,)h(uint,)f(lng,)h(ulng,)f(lnglng,)g(flt,)h (dbl])f(/)286 668 y(ffgsv[b,i,ui,k,uk,j,uj,jj,)o(e,d)o(])286 781 y(\(fitsfile)g(*fptr,)g(int)h(colnum,)e(int)i(naxis,)f(long)h (*naxes,)f(long)h(*fpixel,)334 894 y(long)g(*lpixel,)e(long)i(*inc,)f (DTYPE)h(nulval,)e(>)j(DTYPE)e(*array,)g(int)h(*anynul,)334 1007 y(int)g(*status\))0 1227 y Fi(4)81 b Fj(Read)24 b(an)g(arbitrary)g(data)h(subsection)f(from)g(an)g(N-dimensional)h (arra)m(y)g(in)f(a)g(binary)g(table)h(v)m(ector)h(column.)227 1340 y(An)m(y)34 b(Unde\014ned)e(pixels)i(in)g(the)f(arra)m(y)i(will)f (ha)m(v)m(e)h(the)f(corresp)s(onding)e('n)m(ullarra)m(y')j(elemen)m(t)g (set)f(equal)227 1453 y(to)40 b(TR)m(UE.)e(The)h(\014rst)e(and)h(last)i (ro)m(ws)e(in)h(the)f(table)i(to)f(b)s(e)f(read)h(are)g(sp)s(eci\014ed) e(b)m(y)i(fpixel\(naxis+1\))227 1566 y(and)i(lpixel\(naxis+1\),)47 b(and)41 b(hence)h(are)g(treated)g(as)g(the)g(next)g(higher)g (dimension)f(of)h(the)g(FITS)f(N-)227 1678 y(dimensional)i(arra)m(y)-8 b(.)78 b(The)41 b(INC)h(parameter)h(sp)s(eci\014es)f(the)h(sampling)f (in)m(terv)-5 b(al)44 b(in)e(eac)m(h)i(dimension)227 1791 y(b)s(et)m(w)m(een)31 b(the)g(data)g(elemen)m(ts)h(that)f(will)f (b)s(e)g(returned.)95 2011 y Fe(int)47 b(fits_read_subsetnull_[byt,)41 b(sht,)47 b(usht,)f(int,)h(uint,)f(lng,)h(ulng,)f(lnglng,)g(flt,)g (dbl])h(/)286 2124 y(ffgsf[b,i,ui,k,uk,j,uj,jj,)o(e,d)o(])286 2237 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(int)i(naxis,)f(long)h (*naxes,)334 2350 y(long)g(*fpixel,)e(long)i(*lpixel,)e(long)i(*inc,)f (>)i(DTYPE)e(*array,)334 2463 y(char)h(*nullarray,)d(int)j(*anynul,)f (int)h(*status\))0 2683 y Fi(5)81 b Fj(Read)35 b(bit)g(v)-5 b(alues)35 b(from)g(a)g(b)m(yte)h(\('B'\))g(or)f(bit)g(\(`X`\))h(table) g(column)f(\(in)g(the)g(CDU\).)h(Larra)m(y)g(is)f(an)f(arra)m(y)227 2796 y(of)g(logical)i(v)-5 b(alues)34 b(corresp)s(onding)f(to)h(the)g (sequence)g(of)g(bits)g(to)g(b)s(e)f(read.)51 b(If)33 b(larra)m(y)h(is)g(true)f(then)h(the)227 2909 y(corresp)s(onding)i(bit) h(w)m(as)g(set)h(to)f(1,)j(otherwise)d(the)g(bit)g(w)m(as)g(set)h(to)f (0.)61 b(The)37 b('X')g(column)g(in)f(a)i(FITS)227 3022 y(table)e(is)e(alw)m(a)m(ys)i(padded)e(out)h(to)g(a)g(m)m(ultiple)g(of) g(8)g(bits)f(where)g(the)h(bit)g(arra)m(y)g(starts)g(with)f(the)h(most) 227 3135 y(signi\014can)m(t)j(bit)e(of)h(the)g(b)m(yte)g(and)f(w)m (orks)g(do)m(wn)h(to)m(w)m(ards)g(the)g(1's)g(bit.)59 b(F)-8 b(or)37 b(example,)i(a)e('4X')h(arra)m(y)-8 b(,)227 3247 y(with)33 b(the)h(\014rst)e(bit)i(=)f(1)h(and)e(the)i(remaining)f (3)h(bits)f(=)g(0)h(is)f(equiv)-5 b(alen)m(t)35 b(to)f(the)g(8-bit)g (unsigned)e(b)m(yte)227 3360 y(v)-5 b(alue)31 b(of)f(128.)42 b(Note)31 b(that)g(in)e(the)i(case)g(of)f('X')g(columns,)g(CFITSIO)f (can)h(read)g(all)h(8)f(bits)g(of)g(eac)m(h)h(b)m(yte)227 3473 y(whether)h(they)h(are)g(formally)g(v)-5 b(alid)33 b(or)f(not.)48 b(Th)m(us)31 b(if)i(the)f(column)h(is)f(de\014ned)f(as)i ('4X',)h(and)e(one)h(calls)227 3586 y(\013gcx)d(with)f(\014rstbit=1)f (and)h(n)m(bits=8,)g(then)g(all)h(8)f(bits)g(will)g(b)s(e)g(read)g (from)f(the)h(\014rst)g(b)m(yte)g(\(as)h(opp)s(osed)227 3699 y(to)39 b(reading)f(the)g(\014rst)g(4)g(bits)g(from)g(the)g (\014rst)f(ro)m(w)h(and)g(then)f(the)i(\014rst)e(4)h(bits)g(from)g(the) g(next)g(ro)m(w\),)227 3812 y(ev)m(en)g(though)f(the)g(last)i(4)e(bits) g(of)h(eac)m(h)g(b)m(yte)g(are)f(formally)h(not)g(de\014ned.)60 b(It)37 b(should)f(also)i(b)s(e)f(noted)227 3925 y(that)f(it)f(is)h (more)f(e\016cien)m(t)h(to)g(read)f('X')h(columns)e(an)h(en)m(tire)h(b) m(yte)g(at)g(a)f(time,)i(instead)e(of)h(bit)f(b)m(y)g(bit.)227 4038 y(An)m(y)29 b(of)g(the)h(CFITSIO)d(routines)i(that)g(read)g (columns)g(\(e.g.)42 b(\014ts)p 2520 4038 28 4 v 32 w(read)p 2724 4038 V 33 w(col)p 2867 4038 V 34 w(b)m(yt\))29 b(ma)m(y)h(b)s(e)e (used)g(for)h(this)227 4151 y(purp)s(ose.)60 b(These)36 b(routines)i(will)f(in)m(terpret)h('X')f(columns)g(as)g(though)g(they)h (w)m(ere)f('B')h(columns)f(\(e.g.,)227 4264 y('8X')32 b(is)e(equiv)-5 b(alen)m(t)32 b(to)f('1B',)h(and)e('16X')i(is)e(equiv) -5 b(alen)m(t)32 b(to)f('2B'\).)95 4484 y Fe(int)47 b (fits_read_col_bit)c(/)48 b(ffgcx)286 4597 y(\(fitsfile)e(*fptr,)g(int) h(colnum,)e(LONGLONG)h(firstrow,)f(LONGLONG)h(firstbit,)334 4709 y(LONGLONG)g(nbits,)g(>)h(char)g(*larray,)e(int)i(*status\))0 4929 y Fi(6)81 b Fj(Read)31 b(an)m(y)h(consecutiv)m(e)i(set)e(of)g (bits)f(from)h(an)f('X')h(or)g('B')h(column)e(and)g(in)m(terpret)h (them)g(as)f(an)h(unsigned)227 5042 y(n-bit)h(in)m(teger.)48 b(n)m(bits)33 b(m)m(ust)f(b)s(e)g(less)h(than)g(16)g(or)g(32)g(in)f (\013gcxui)i(and)d(\013gcxuk,)j(resp)s(ectiv)m(ely)-8 b(.)49 b(If)32 b(nro)m(ws)227 5155 y(is)c(greater)h(than)f(1,)h(then)e (the)h(same)h(set)f(of)g(bits)g(will)g(b)s(e)f(read)h(from)f(eac)m(h)i (ro)m(w,)g(starting)g(with)e(\014rstro)m(w.)227 5268 y(The)j(bits)g(are)h(n)m(um)m(b)s(ered)e(with)h(1)h(=)f(the)h(most)f (signi\014can)m(t)i(bit)e(of)h(the)f(\014rst)g(elemen)m(t)i(of)e(the)h (column.)95 5488 y Fe(int)47 b(fits_read_col_bit_[usht,)42 b(uint])k(/)h(ffgcx[ui,uk])286 5601 y(\(fitsfile)f(*fptr,)g(int)h (colnum,)e(LONGLONG)h(firstrow,)f(LONGLONG,)h(nrows,)334 5714 y(long)h(firstbit,)e(long)i(nbits,)f(>)h(DTYPE)g(*array,)e(int)i (*status\))p eop end %%Page: 121 129 TeXDict begin 121 128 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.121) cvn H.B /DEST pdfmark end 0 299 a Fh(9.6.)72 b(SPECIALIZED)29 b(FITS)g(ASCI)s(I)g(AND)i(BINAR)-8 b(Y)32 b(T)-8 b(ABLE)30 b(R)m(OUTINES)933 b Fj(121)0 555 y Fi(7)81 b Fj(Return)27 b(the)i(descriptor)f(for)h(a)g(v)-5 b(ariable)29 b(length)g(column)f (in)h(a)g(binary)e(table.)41 b(The)28 b(descriptor)h(consists)g(of)227 668 y(2)j(in)m(teger)g(parameters:)42 b(the)31 b(n)m(um)m(b)s(er)f(of)h (elemen)m(ts)i(in)d(the)h(arra)m(y)h(and)e(the)h(starting)h(o\013set)g (relativ)m(e)h(to)227 781 y(the)c(start)h(of)e(the)h(heap.)40 b(The)29 b(\014rst)f(pair)g(of)h(routine)g(returns)e(a)i(single)h (descriptor)e(whereas)h(the)g(second)227 894 y(pair)34 b(of)h(routine)f(returns)g(the)g(descriptors)g(for)g(a)h(range)g(of)f (ro)m(ws)h(in)f(the)g(table.)54 b(The)34 b(only)g(di\013erence)227 1007 y(b)s(et)m(w)m(een)42 b(the)f(2)g(routines)f(in)h(eac)m(h)h(pair)e (is)h(that)g(one)g(returns)f(the)h(parameters)g(as)g('long')g(in)m (tegers,)227 1120 y(whereas)30 b(the)h(other)g(returns)e(the)h(v)-5 b(alues)31 b(as)g(64-bit)g('LONGLONG')g(in)m(tegers.)95 1380 y Fe(int)47 b(fits_read_descript)c(/)48 b(ffgdes)286 1492 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e(LONGLONG)h(rownum,)g(>)h (long)g(*repeat,)525 1605 y(long)g(*offset,)e(int)i(*status\))95 1831 y(int)g(fits_read_descriptll)c(/)k(ffgdesll)286 1944 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(LONGLONG)h(rownum,)g(>)h (LONGLONG)f(*repeat,)525 2057 y(LONGLONG)g(*offset,)f(int)i(*status\)) 95 2283 y(int)g(fits_read_descripts)c(/)k(ffgdess)286 2396 y(\(fitsfile)f(*fptr,)g(int)h(colnum,)e(LONGLONG)h(firstrow,)f (LONGLONG)h(nrows)334 2509 y(>)i(long)e(*repeat,)g(long)g(*offset,)g (int)h(*status\))95 2734 y(int)g(fits_read_descriptsll)42 b(/)48 b(ffgdessll)286 2847 y(\(fitsfile)e(*fptr,)g(int)h(colnum,)e (LONGLONG)h(firstrow,)f(LONGLONG)h(nrows)334 2960 y(>)i(LONGLONG)d (*repeat,)h(LONGLONG)f(*offset,)h(int)h(*status\))p eop end %%Page: 122 130 TeXDict begin 122 129 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.122) cvn H.B /DEST pdfmark end 0 299 a Fj(122)958 b Fh(CHAPTER)30 b(9.)112 b(SPECIALIZED)28 b(CFITSIO)h(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)p eop end %%Page: 123 131 TeXDict begin 123 130 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.123) cvn H.B /DEST pdfmark end 0 299 a 0 464 a SDict begin H.S end 0 464 a 0 464 a SDict begin 13.6 H.A end 0 464 a 0 464 a SDict begin [ /View [/XYZ H.V] /Dest (chapter.10) cvn H.B /DEST pdfmark end 0 464 a 761 x Fg(Chapter)65 b(10)0 1687 y Fm(Extended)77 b(File)g(Name)g(Syn)-6 b(tax)0 2060 y SDict begin H.S end 0 2060 a 0 2060 a SDict begin 13.6 H.A end 0 2060 a 0 2060 a SDict begin [ /View [/XYZ H.V] /Dest (section.10.1) cvn H.B /DEST pdfmark end 0 2060 a 156 x Ff(10.1)136 b(Ov)l(erview)0 2466 y Fj(CFITSIO)30 b(supp)s(orts)f(an)j (extended)f(syn)m(tax)h(when)f(sp)s(ecifying)g(the)h(name)f(of)h(the)g (data)g(\014le)f(to)h(b)s(e)f(op)s(ened)g(or)0 2579 y(created)g(that)g (includes)f(the)h(follo)m(wing)h(features:)136 2813 y Fc(\017)46 b Fj(CFITSIO)40 b(can)i(read)f(IRAF)h(format)g(images)g (whic)m(h)f(ha)m(v)m(e)i(header)e(\014le)h(names)f(that)h(end)f(with)g (the)227 2926 y('.imh')d(extension,)i(as)e(w)m(ell)g(as)g(reading)f (and)g(writing)g(FITS)g(\014les,)i(This)e(feature)h(is)f(implemen)m (ted)h(in)227 3039 y(CFITSIO)29 b(b)m(y)i(\014rst)e(con)m(v)m(erting)k (the)d(IRAF)h(image)h(in)m(to)f(a)g(temp)s(orary)f(FITS)g(format)h (\014le)f(in)g(memory)-8 b(,)227 3152 y(then)35 b(op)s(ening)f(the)h (FITS)f(\014le.)54 b(An)m(y)35 b(of)g(the)g(usual)f(CFITSIO)g(routines) g(then)h(ma)m(y)g(b)s(e)f(used)g(to)i(read)227 3265 y(the)31 b(image)g(header)f(or)h(data.)41 b(Similarly)-8 b(,)31 b(ra)m(w)f(binary)g(data)h(arra)m(ys)f(can)h(b)s(e)f(read)g(b)m(y)g (con)m(v)m(erting)i(them)227 3378 y(on)f(the)f(\015y)g(in)m(to)h (virtual)g(FITS)f(images.)136 3557 y Fc(\017)46 b Fj(FITS)f(\014les)h (on)f(the)h(In)m(ternet)g(can)g(b)s(e)f(read)g(\(and)g(sometimes)i (written\))f(using)f(the)h(FTP)-8 b(,)46 b(HTTP)-8 b(,)227 3670 y(HTTPS,)30 b(or)g(R)m(OOT)g(proto)s(cols.)136 3849 y Fc(\017)46 b Fj(FITS)30 b(\014les)g(can)h(b)s(e)f(pip)s(ed)f(b)s(et)m (w)m(een)i(tasks)f(on)h(the)f(stdin)g(and)g(stdout)g(streams.)136 4028 y Fc(\017)46 b Fj(FITS)36 b(\014les)h(can)g(b)s(e)f(read)h(and)f (written)h(in)g(shared)f(memory)-8 b(.)60 b(This)36 b(can)h(p)s(oten)m (tially)i(ac)m(hiev)m(e)g(b)s(etter)227 4141 y(data)26 b(I/O)e(p)s(erformance)g(compared)h(to)h(reading)f(and)f(writing)g(the) h(same)h(FITS)e(\014les)g(on)h(magnetic)h(disk.)136 4320 y Fc(\017)46 b Fj(Compressed)30 b(FITS)f(\014les)i(in)f(gzip)h(or)f (Unix)g(COMPRESS)f(format)h(can)h(b)s(e)f(directly)h(read.)136 4499 y Fc(\017)46 b Fj(Output)28 b(FITS)h(\014les)g(can)g(b)s(e)g (written)g(directly)h(in)e(compressed)h(gzip)h(format,)g(th)m(us)e(sa)m (ving)i(disk)f(space.)136 4678 y Fc(\017)46 b Fj(FITS)26 b(table)h(columns)f(can)h(b)s(e)f(created,)i(mo)s(di\014ed,)f(or)f (deleted)h('on-the-\015y')g(as)g(the)g(table)g(is)f(op)s(ened)g(b)m(y) 227 4791 y(CFITSIO.)32 b(This)h(creates)i(a)e(virtual)h(FITS)f(\014le)g (con)m(taining)i(the)f(mo)s(di\014cations)f(that)h(is)g(then)f(op)s (ened)227 4904 y(b)m(y)e(the)f(application)i(program.)136 5083 y Fc(\017)46 b Fj(T)-8 b(able)29 b(ro)m(ws)e(ma)m(y)i(b)s(e)e (selected,)j(or)e(\014ltered)g(out,)g(on)g(the)g(\015y)f(when)g(the)h (table)h(is)f(op)s(ened)f(b)m(y)g(CFITSIO,)227 5196 y(based)22 b(on)f(an)g(user-sp)s(eci\014ed)g(expression.)38 b(Only)21 b(ro)m(ws)g(for)g(whic)m(h)h(the)g(expression)f(ev)-5 b(aluates)23 b(to)f('TR)m(UE')227 5309 y(are)31 b(retained)g(in)f(the)g (cop)m(y)i(of)e(the)h(table)g(that)g(is)f(op)s(ened)g(b)m(y)g(the)h (application)g(program.)136 5488 y Fc(\017)46 b Fj(Histogram)28 b(images)g(ma)m(y)f(b)s(e)f(created)h(on)f(the)h(\015y)f(b)m(y)g (binning)g(the)g(v)-5 b(alues)27 b(in)f(table)i(columns,)f(resulting) 227 5601 y(in)36 b(a)g(virtual)h(N-dimensional)f(FITS)g(image.)59 b(The)35 b(application)i(program)f(then)g(only)g(sees)g(the)h(FITS)227 5714 y(image)32 b(\(in)e(the)h(primary)e(arra)m(y\))j(instead)e(of)h (the)f(original)i(FITS)d(table.)1882 5942 y(123)p eop end %%Page: 124 132 TeXDict begin 124 131 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.124) cvn H.B /DEST pdfmark end 0 299 a Fj(124)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fj(The)39 b(latter)i(3)f(table)h(\014ltering)f(features)g(in)f (particular)h(add)f(v)m(ery)h(p)s(o)m(w)m(erful)f(data)i(pro)s(cessing) e(capabilities)0 668 y(directly)33 b(in)m(to)g(CFITSIO,)e(and)h(hence)h (in)m(to)g(ev)m(ery)g(task)g(that)g(uses)f(CFITSIO)f(to)i(read)f(or)h (write)f(FITS)g(\014les.)0 781 y(F)-8 b(or)29 b(example,)g(these)f (features)h(transform)e(a)h(v)m(ery)g(simple)g(program)g(that)g(just)g (copies)g(an)g(input)f(FITS)g(\014le)h(to)0 894 y(a)c(new)f(output)h (\014le)g(\(lik)m(e)h(the)f(`\014tscop)m(y')h(program)e(that)i(is)e (distributed)g(with)h(CFITSIO\))e(in)m(to)j(a)f(m)m(ultipurp)s(ose)0 1007 y(FITS)33 b(\014le)g(pro)s(cessing)g(to)s(ol.)51 b(By)33 b(app)s(ending)f(fairly)i(simple)f(quali\014ers)g(on)m(to)h (the)g(name)f(of)h(the)f(input)g(FITS)0 1120 y(\014le,)45 b(the)d(user)f(can)h(p)s(erform)e(quite)i(complex)h(table)f(editing)h (op)s(erations)f(\(e.g.,)k(create)d(new)e(columns,)k(or)0 1233 y(\014lter)32 b(out)h(ro)m(ws)f(in)g(a)g(table\))i(or)e(create)i (FITS)d(images)j(b)m(y)e(binning)f(or)h(histogramming)h(the)g(v)-5 b(alues)32 b(in)g(table)0 1346 y(columns.)47 b(In)32 b(addition,)h(these)g(functions)f(ha)m(v)m(e)i(b)s(een)e(co)s(ded)g (using)g(new)g(state-of-the)j(art)e(algorithms)g(that)0 1458 y(are,)e(in)f(some)h(cases,)g(10)h(-)e(100)i(times)f(faster)g (than)f(previous)g(widely)g(used)f(implemen)m(tations.)0 1619 y(Before)34 b(describing)f(the)h(complete)h(syn)m(tax)f(for)f(the) h(extended)f(FITS)g(\014le)g(names)g(in)g(the)h(next)g(section,)h(here) 0 1732 y(are)c(a)g(few)f(examples)h(of)f(FITS)g(\014le)g(names)h(that)f (giv)m(e)i(a)f(quic)m(k)g(o)m(v)m(erview)h(of)f(the)f(allo)m(w)m(ed)i (syn)m(tax:)136 2005 y Fc(\017)46 b Fe(myfile.fits)p Fj(:)38 b(the)30 b(simplest)h(case)g(of)g(a)g(FITS)e(\014le)i(on)f (disk)g(in)g(the)h(curren)m(t)f(directory)-8 b(.)136 2207 y Fc(\017)46 b Fe(myfile.imh)p Fj(:)i(op)s(ens)34 b(an)h(IRAF)g(format)g(image)i(\014le)e(and)f(con)m(v)m(erts)j(it)e(on) g(the)g(\015y)g(in)m(to)h(a)f(temp)s(orary)227 2320 y(FITS)30 b(format)h(image)g(in)f(memory)h(whic)m(h)f(can)g(then)g(b)s(e)g(read)g (with)g(an)m(y)h(other)g(CFITSIO)e(routine.)136 2521 y Fc(\017)46 b Fe(rawfile.dat[i512,512])p Fj(:)35 b(op)s(ens)30 b(a)g(ra)m(w)h(binary)e(data)i(arra)m(y)g(\(a)g(512)g(x)f(512)i(short)e (in)m(teger)h(arra)m(y)g(in)227 2634 y(this)i(case\))i(and)d(con)m(v)m (erts)j(it)e(on)g(the)g(\015y)g(in)m(to)h(a)f(temp)s(orary)g(FITS)f (format)h(image)i(in)d(memory)h(whic)m(h)227 2747 y(can)e(then)f(b)s(e) g(read)g(with)g(an)m(y)h(other)f(CFITSIO)f(routine.)136 2948 y Fc(\017)46 b Fe(myfile.fits.gz)p Fj(:)d(if)33 b(this)g(is)g(the)g(name)g(of)h(a)f(new)g(output)g(\014le,)h(the)f ('.gz')i(su\016x)d(will)h(cause)h(it)g(to)g(b)s(e)227 3061 y(compressed)c(in)g(gzip)h(format)g(when)e(it)i(is)g(written)f(to) h(disk.)136 3263 y Fc(\017)46 b Fe(myfile.fits.gz[events,)c(2])p Fj(:)35 b(op)s(ens)20 b(and)f(uncompresses)g(the)i(gzipp)s(ed)f(\014le) g(m)m(y\014le.\014ts)h(then)f(mo)m(v)m(es)227 3376 y(to)31 b(the)g(extension)g(with)f(the)h(k)m(eyw)m(ords)f(EXTNAME)h(=)f ('EVENTS')g(and)g(EXTVER)g(=)g(2.)136 3577 y Fc(\017)46 b Fe(-)p Fj(:)40 b(a)30 b(dash)f(\(min)m(us)g(sign\))h(signi\014es)g (that)g(the)g(input)f(\014le)g(is)h(to)g(b)s(e)f(read)h(from)f(the)h (stdin)f(\014le)h(stream,)g(or)227 3690 y(that)d(the)g(output)f(\014le) h(is)f(to)h(b)s(e)f(written)h(to)g(the)g(stdout)f(stream.)40 b(See)27 b(also)g(the)g(stream://)h(driv)m(er)e(whic)m(h)227 3803 y(pro)m(vides)37 b(a)f(more)h(e\016cien)m(t,)i(but)d(more)g (restricted)h(metho)s(d)f(of)h(reading)f(or)g(writing)h(to)g(the)f (stdin)g(or)227 3916 y(stdout)31 b(streams.)136 4117 y Fc(\017)46 b Fe(ftp://legacy.gsfc.nasa.go)o(v/te)o(st/v)o(ela)o(.fit) o(s)p Fj(:)k(FITS)37 b(\014les)h(in)g(an)m(y)h(ftp)e(arc)m(hiv)m(e)j (site)f(on)f(the)227 4230 y(In)m(ternet)31 b(ma)m(y)g(b)s(e)f(directly) h(op)s(ened)e(with)h(read-only)h(access.)136 4432 y Fc(\017)46 b Fe(http://legacy.gsfc.nasa.g)o(ov/s)o(oftw)o(are)o(/tes)o(t.fi)o(ts)p Fj(:)33 b(an)m(y)27 b(v)-5 b(alid)28 b(URL)f(to)h(a)g(FITS)e(\014le)i (on)f(the)227 4545 y(W)-8 b(eb)31 b(ma)m(y)g(b)s(e)f(op)s(ened)g(with)g (read-only)g(access.)136 4746 y Fc(\017)46 b Fe (root://legacy.gsfc.nasa.g)o(ov/t)o(est/)o(vel)o(a.fi)o(ts)p Fj(:)e(similar)36 b(to)g(ftp)f(access)i(except)f(that)g(it)g(pro-)227 4859 y(vides)30 b(write)h(as)f(w)m(ell)h(as)g(read)f(access)h(to)g(the) f(\014les)h(across)f(the)h(net)m(w)m(ork.)41 b(This)29 b(uses)h(the)h(ro)s(ot)f(proto)s(col)227 4972 y(dev)m(elop)s(ed)h(at)g (CERN.)136 5174 y Fc(\017)46 b Fe(shmem://h2[events])p Fj(:)j(op)s(ens)36 b(the)i(FITS)e(\014le)h(in)g(a)g(shared)f(memory)h (segmen)m(t)h(and)f(mo)m(v)m(es)h(to)g(the)227 5287 y(EVENTS)30 b(extension.)136 5488 y Fc(\017)46 b Fe(mem://)p Fj(:)65 b(creates)44 b(a)g(scratc)m(h)g(output)f(\014le)g(in)g(core)h(computer) f(memory)-8 b(.)79 b(The)43 b(resulting)g('\014le')h(will)227 5601 y(disapp)s(ear)25 b(when)f(the)i(program)f(exits,)i(so)f(this)f (is)h(mainly)f(useful)g(for)g(testing)i(purp)s(oses)c(when)i(one)g(do)s (es)227 5714 y(not)31 b(w)m(an)m(t)g(a)g(p)s(ermanen)m(t)f(cop)m(y)h (of)f(the)h(output)f(\014le.)p eop end %%Page: 125 133 TeXDict begin 125 132 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.125) cvn H.B /DEST pdfmark end 0 299 a Fh(10.1.)73 b(O)m(VER)-10 b(VIEW)2995 b Fj(125)136 555 y Fc(\017)46 b Fe(myfile.fits[3;)e (Images\(10\)])p Fj(:)c(op)s(ens)30 b(a)i(cop)m(y)g(of)g(the)g(image)g (con)m(tained)h(in)e(the)h(10th)g(ro)m(w)f(of)h(the)227 668 y('Images')38 b(column)f(in)g(the)g(binary)f(table)i(in)e(the)h (3th)g(extension)h(of)f(the)g(FITS)f(\014le.)60 b(The)37 b(virtual)g(\014le)227 781 y(that)31 b(is)g(op)s(ened)e(b)m(y)i(the)f (application)i(just)e(con)m(tains)h(this)f(single)h(image)h(in)e(the)h (primary)e(arra)m(y)-8 b(.)136 973 y Fc(\017)46 b Fe (myfile.fits[1:512:2,)d(1:512:2])p Fj(:)c(op)s(ens)30 b(a)h(section)h(of)g(the)f(input)f(image)i(ranging)f(from)f(the)h(1st) 227 1086 y(to)k(the)f(512th)h(pixel)f(in)g(X)g(and)g(Y,)g(and)f (selects)j(ev)m(ery)e(second)g(pixel)h(in)e(b)s(oth)g(dimensions,)i (resulting)227 1198 y(in)30 b(a)h(256)h(x)e(256)i(pixel)e(input)g (image)h(in)g(this)f(case.)136 1390 y Fc(\017)46 b Fe (myfile.fits[EVENTS][col)c(Rad)47 b(=)g(sqrt\(X**2)e(+)j(Y**2\)])p Fj(:)36 b(creates)27 b(and)d(op)s(ens)h(a)g(virtual)h(\014le)f(on)227 1503 y(the)h(\015y)f(that)i(is)f(iden)m(tical)h(to)g(m)m (y\014le.\014ts)f(except)g(that)h(it)f(will)g(con)m(tain)h(a)f(new)g (column)f(in)h(the)g(EVENTS)227 1616 y(extension)41 b(called)h('Rad')f (whose)f(v)-5 b(alue)41 b(is)g(computed)f(using)h(the)f(indicated)h (expression)g(whic)m(h)f(is)h(a)227 1729 y(function)30 b(of)h(the)f(v)-5 b(alues)31 b(in)f(the)h(X)f(and)g(Y)h(columns.)136 1920 y Fc(\017)46 b Fe(myfile.fits[EVENTS][PHA)c(>)47 b(5])p Fj(:)41 b(creates)33 b(and)d(op)s(ens)g(a)i(virtual)f(FITS)f (\014les)h(that)g(is)g(iden)m(tical)i(to)227 2033 y('m)m (y\014le.\014ts')40 b(except)h(that)f(the)f(EVENTS)g(table)h(will)g (only)f(con)m(tain)i(the)e(ro)m(ws)h(that)g(ha)m(v)m(e)g(v)-5 b(alues)40 b(of)227 2146 y(the)34 b(PHA)g(column)g(greater)h(than)e(5.) 52 b(In)33 b(general,)j(an)m(y)e(arbitrary)g(b)s(o)s(olean)f (expression)h(using)f(a)i(C)e(or)227 2259 y(F)-8 b(ortran-lik)m(e)31 b(syn)m(tax,)e(whic)m(h)f(ma)m(y)h(com)m(bine)g(AND)g(and)f(OR)f(op)s (erators,)i(ma)m(y)g(b)s(e)f(used)f(to)i(select)h(ro)m(ws)227 2372 y(from)g(a)h(table.)136 2564 y Fc(\017)46 b Fe (myfile.fits[EVENTS][bin)c(\(X,Y\)=1,2048,4])p Fj(:)34 b(creates)26 b(a)g(temp)s(orary)f(FITS)g(primary)f(arra)m(y)i(im-)227 2677 y(age)38 b(whic)m(h)e(is)h(computed)f(on)g(the)h(\015y)f(b)m(y)g (binning)f(\(i.e,)40 b(computing)c(the)h(2-dimensional)g(histogram\)) 227 2789 y(of)d(the)f(v)-5 b(alues)34 b(in)f(the)h(X)g(and)e(Y)i (columns)f(of)h(the)f(EVENTS)g(extension.)50 b(In)33 b(this)g(case)i(the)e(X)h(and)f(Y)227 2902 y(co)s(ordinates)h(range)g (from)f(1)h(to)g(2048)h(and)e(the)h(image)g(pixel)g(size)g(is)g(4)f (units)g(in)g(b)s(oth)g(dimensions,)h(so)227 3015 y(the)d(resulting)f (image)i(is)e(512)i(x)e(512)i(pixels)f(in)f(size.)136 3207 y Fc(\017)46 b Fj(The)31 b(\014nal)g(example)i(com)m(bines)f(man)m (y)f(of)h(these)g(feature)g(in)m(to)g(one)g(complex)g(expression)f (\(it)i(is)e(brok)m(en)227 3320 y(in)m(to)h(sev)m(eral)f(lines)g(for)f (clarit)m(y\):)370 3576 y Fe(ftp://legacy.gsfc.nasa.gov)o(/dat)o(a/s)o (ampl)o(e.fi)o(ts.)o(gz[E)o(VENT)o(S])370 3689 y([col)47 b(phacorr)f(=)h(pha)g(*)h(1.1)f(-)g(0.3][phacorr)e(>=)i(5.0)g(&&)g (phacorr)f(<=)h(14.0])370 3801 y([bin)g(\(X,Y\)=32])227 4057 y Fj(In)37 b(this)h(case,)j(CFITSIO)36 b(\(1\))j(copies)g(and)e (uncompresses)g(the)h(FITS)f(\014le)h(from)f(the)h(ftp)f(site)i(on)f (the)227 4170 y(legacy)g(mac)m(hine,)h(\(2\))e(mo)m(v)m(es)g(to)g(the)g ('EVENTS')f(extension,)i(\(3\))f(calculates)i(a)d(new)g(column)g (called)227 4283 y('phacorr',)30 b(\(4\))f(selects)h(the)f(ro)m(ws)g (in)f(the)h(table)h(that)f(ha)m(v)m(e)h(phacorr)e(in)g(the)h(range)g(5) g(to)h(14,)g(and)e(\014nally)227 4396 y(\(5\))35 b(bins)d(the)h (remaining)g(ro)m(ws)g(on)h(the)f(X)g(and)g(Y)g(column)g(co)s (ordinates,)i(using)d(a)i(pixel)f(size)h(=)f(32)h(to)227 4509 y(create)d(a)f(2D)g(image.)42 b(All)30 b(this)f(pro)s(cessing)g (is)h(completely)h(transparen)m(t)e(to)i(the)e(application)i(program,) 227 4622 y(whic)m(h)f(simply)g(sees)h(the)g(\014nal)f(2-D)h(image)h(in) e(the)g(primary)g(arra)m(y)h(of)f(the)h(op)s(ened)f(\014le.)0 4886 y(The)c(full)h(extended)g(CFITSIO)e(FITS)h(\014le)h(name)g(can)g (con)m(tain)h(sev)m(eral)g(di\013eren)m(t)g(comp)s(onen)m(ts)f(dep)s (ending)e(on)0 4998 y(the)31 b(con)m(text.)42 b(These)30 b(comp)s(onen)m(ts)h(are)g(describ)s(ed)e(in)h(the)g(follo)m(wing)i (sections:)0 5262 y Fe(When)47 b(creating)e(a)j(new)f(file:)143 5375 y(filetype://BaseFilename\(t)o(empl)o(ate)o(Name)o(\)[co)o(mpr)o (ess])0 5601 y(When)g(opening)e(an)j(existing)d(primary)h(array)g(or)i (image)e(HDU:)143 5714 y(filetype://BaseFilename\(o)o(utNa)o(me\))o ([HDU)o(loca)o(tio)o(n][I)o(mage)o(Sec)o(tion)o(][pi)o(xFi)o(lter)o(])p eop end %%Page: 126 134 TeXDict begin 126 133 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.126) cvn H.B /DEST pdfmark end 0 299 a Fj(126)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 668 y Fe(When)47 b(opening)e(an)j(existing)d(table)i(HDU:)143 781 y(filetype://BaseFilename\(o)o(utNa)o(me\))o([HDU)o(loca)o(tio)o (n][c)o(olFi)o(lte)o(r][r)o(owFi)o(lte)o(r][b)o(inSp)o(ec])0 1082 y Fj(The)35 b(\014let)m(yp)s(e,)j(BaseFilename,)h(outName,)g (HDUlo)s(cation,)g(ImageSection,)g(and)c(pixFilter)i(comp)s(onen)m(ts,) g(if)0 1195 y(presen)m(t,)27 b(m)m(ust)f(b)s(e)g(giv)m(en)h(in)f(that)g (order,)h(but)e(the)i(colFilter,)i(ro)m(wFilter,)g(and)c(binSp)s(ec)g (sp)s(eci\014ers)g(ma)m(y)i(follo)m(w)0 1308 y(in)j(an)m(y)h(order.)42 b(Regardless)31 b(of)g(the)g(order,)f(ho)m(w)m(ev)m(er,)i(the)f (colFilter)i(sp)s(eci\014er,)e(if)f(presen)m(t,)h(will)g(b)s(e)f(pro)s (cessed)0 1421 y(\014rst)g(b)m(y)g(CFITSIO,)f(follo)m(w)m(ed)j(b)m(y)e (the)h(ro)m(wFilter)h(sp)s(eci\014er,)e(and)f(\014nally)i(b)m(y)f(the)g (binSp)s(ec)f(sp)s(eci\014er.)0 1624 y SDict begin H.S end 0 1624 a 0 1624 a SDict begin 13.6 H.A end 0 1624 a 0 1624 a SDict begin [ /View [/XYZ H.V] /Dest (section.10.2) cvn H.B /DEST pdfmark end 0 1624 a 179 x Ff(10.2)136 b(Filet)l(yp)t(e)0 2063 y Fj(The)37 b(t)m(yp)s(e)g(of)g(\014le)g(determines)g(the)g (medium)f(on)h(whic)m(h)g(the)g(\014le)g(is)h(lo)s(cated)g(\(e.g.,)i (disk)d(or)g(net)m(w)m(ork\))h(and,)0 2176 y(hence,)f(whic)m(h)e(in)m (ternal)h(device)g(driv)m(er)f(is)g(used)f(b)m(y)h(CFITSIO)f(to)i(read) f(and/or)g(write)g(the)g(\014le.)56 b(Curren)m(tly)0 2289 y(supp)s(orted)29 b(t)m(yp)s(es)h(are)382 2590 y Fe(file://)93 b(-)48 b(file)e(on)i(local)e(magnetic)g(disk)g (\(default\))430 2703 y(ftp://)93 b(-)48 b(a)f(readonly)f(file)g (accessed)g(with)h(the)g(anonymous)e(FTP)i(protocol.)907 2816 y(It)g(also)g(supports)93 b(ftp://username:password@)o(host)o(nam) o(e/..)o(.)907 2929 y(for)47 b(accessing)e(password-protected)e(ftp)k (sites.)382 3042 y(http://)93 b(-)48 b(a)f(readonly)f(file)g(accessed)g (with)h(the)g(HTTP)f(protocol.)93 b(It)907 3155 y(supports)45 b(username:password)e(just)k(like)g(the)g(ftp)g(driver.)907 3267 y(Proxy)f(HTTP)h(servers)f(are)h(supported)e(using)h(the)h (http_proxy)907 3380 y(environment)e(variable)g(\(see)i(following)e (note\).)334 3493 y(https://)93 b(-)48 b(a)f(readonly)f(file)g (accessed)g(with)h(the)g(HTTPS)f(protocol.)93 b(This)907 3606 y(is)47 b(available)e(only)i(if)g(CFITSIO)f(was)h(built)f(with)h (the)g(libcurl)907 3719 y(library)f(\(see)g(the)h(following)e(note\).) 286 3832 y(stream://)93 b(-)48 b(special)e(driver)g(to)h(read)g(an)g (input)f(FITS)h(file)f(from)h(the)g(stdin)907 3945 y(stream,)f(and/or)g (write)g(an)h(output)f(FITS)h(file)g(to)g(the)g(stdout)143 4058 y(stream.)94 b(This)46 b(driver)g(is)i(fragile)d(and)i(has)g (limited)143 4171 y(functionality)d(\(see)j(the)g(following)e(note\).) 286 4284 y(gsiftp://)93 b(-)48 b(access)e(files)g(on)h(a)h (computational)c(grid)j(using)f(the)h(gridftp)907 4397 y(protocol)e(in)j(the)e(Globus)h(toolkit)e(\(see)i(following)e(note\).) 382 4510 y(root://)93 b(-)48 b(uses)e(the)h(CERN)g(root)g(protocol)e (for)i(writing)f(as)h(well)g(as)907 4622 y(reading)f(files)g(over)h (the)g(network)e(\(see)i(following)e(note\).)334 4735 y(shmem://)93 b(-)48 b(opens)e(or)h(creates)f(a)i(file)e(which)h (persists)e(in)i(the)g(computer's)907 4848 y(shared)f(memory)g(\(see)h (following)e(note\).)430 4961 y(mem://)93 b(-)48 b(opens)e(a)i (temporary)d(file)i(in)g(core)f(memory.)94 b(The)47 b(file)907 5074 y(disappears)e(when)h(the)h(program)f(exits)h(so)g(this)f(is)i (mainly)907 5187 y(useful)e(for)h(test)f(purposes)g(when)h(a)g (permanent)e(output)h(file)907 5300 y(is)h(not)g(desired.)0 5601 y Fj(If)35 b(the)h(\014let)m(yp)s(e)g(is)f(not)h(sp)s(eci\014ed,)h (then)e(t)m(yp)s(e)h(\014le://)h(is)e(assumed.)56 b(The)35 b(double)g(slashes)h('//')h(are)f(optional)0 5714 y(and)30 b(ma)m(y)h(b)s(e)e(omitted)j(in)e(most)h(cases.)p eop end %%Page: 127 135 TeXDict begin 127 134 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.127) cvn H.B /DEST pdfmark end 0 299 a Fh(10.2.)73 b(FILETYPE)3037 b Fj(127)0 464 y SDict begin H.S end 0 464 a 0 464 a SDict begin 13.6 H.A end 0 464 a 0 464 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.10.2.1) cvn H.B /DEST pdfmark end 0 464 a 91 x Fd(10.2.1)113 b(Notes)36 b(ab)s(out)j(HTTP)d(pro)m(xy)i(serv)m (ers)0 805 y Fj(A)32 b(pro)m(xy)g(HTTP)f(serv)m(er)h(ma)m(y)h(b)s(e)e (used)g(b)m(y)h(de\014ning)f(the)h(address)f(\(URL\))i(and)e(p)s(ort)g (n)m(um)m(b)s(er)g(of)h(the)g(pro)m(xy)0 918 y(serv)m(er)f(with)f(the)g (h)m(ttp)p 801 918 28 4 v 33 w(pro)m(xy)g(en)m(vironmen)m(t)h(v)-5 b(ariable.)42 b(F)-8 b(or)31 b(example)191 1311 y Fe(setenv)46 b(http_proxy)f(http://heasarc.gsfc.nasa)o(.gov)o(:312)o(8)0 1703 y Fj(will)38 b(cause)g(CFITSIO)f(to)h(use)g(p)s(ort)f(3128)i(on)f (the)g(heasarc)g(pro)m(xy)g(serv)m(er)g(whenev)m(er)g(reading)g(a)g (FITS)f(\014le)0 1816 y(with)30 b(HTTP)-8 b(.)0 2100 y SDict begin H.S end 0 2100 a 0 2100 a SDict begin 13.6 H.A end 0 2100 a 0 2100 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.10.2.2) cvn H.B /DEST pdfmark end 0 2100 a 163 x Fd(10.2.2)113 b(Notes)36 b(ab)s(out)j(HTTPS)d(\014le)i(access)0 2513 y Fj(CFITSIO)22 b(dep)s(ends)g(up)s(on)f(the)j(a)m(v)-5 b(ailabilit)m(y)27 b(of)d(the)f(lib)s(curl)g(library)g(in)g(order)g(to) h(p)s(erform)f(HTTPS)f(\014le)h(access.)0 2626 y(\(This)j(should)g(b)s (e)f(the)i(dev)m(elopmen)m(t)h(v)m(ersion)f(of)g(the)f(library)-8 b(,)28 b(as)f(it)g(con)m(tains)g(the)g(curl.h)f(header)g(\014le)h (required)0 2739 y(b)m(y)g(the)g(CFITSIO)e(co)s(de.\))41 b(The)26 b(CFITSIO)g('con\014gure')h(script)g(will)g(searc)m(h)h(for)e (this)h(library)g(on)g(y)m(our)g(system,)0 2852 y(and)j(if)g(it)h (\014nds)e(it)i(it)g(will)f(automatically)j(b)s(e)d(incorp)s(orated)h (in)m(to)g(the)f(build.)0 3012 y(Note)43 b(that)g(if)f(y)m(ou)g(ha)m(v) m(e)i(this)e(library)f(pac)m(k)-5 b(age)44 b(on)e(y)m(our)g(system,)k (y)m(ou)c(will)h(also)g(ha)m(v)m(e)g(the)f('curl-con\014g')0 3125 y(executable.)i(Y)-8 b(ou)31 b(can)h(run)d(the)i('curl-con\014g')h (executable)g(with)f(v)-5 b(arious)31 b(options)g(to)h(learn)f(more)g (ab)s(out)g(the)0 3238 y(features)g(of)f(y)m(our)h(lib)s(curl)e (installation.)0 3398 y(If)20 b(the)g(CFITSIO)f('con\014gure')i (succeeded)f(in)g(\014nding)f(a)i(usable)f(lib)s(curl,)i(y)m(ou)e(will) h(see)g(the)f(\015ag)h('-DCFITSIO)p 3766 3398 28 4 v 32 w(HA)-10 b(VE)p 4054 3398 V 33 w(CURL=1')0 3511 y(in)34 b(the)g(CFITSIO)f(Mak)m(e\014le)j(and)e(in)f(the)i(compilation)h (output.)52 b(If)33 b('con\014gure')i(is)f(unable)g(to)h(\014nd)d(a)j (usable)0 3624 y(lib)s(curl,)30 b(CFITSIO)f(will)h(still)i(build)d(but) h(it)h(w)m(on't)g(ha)m(v)m(e)g(HTTPS)e(capabilit)m(y)-8 b(.)0 3784 y(The)32 b(lib)s(curl)g(pac)m(k)-5 b(age)34 b(is)f(normally)g(included)e(as)i(part)g(of)f(Xco)s(de)h(on)g(Macs.)48 b(Ho)m(w)m(ev)m(er)35 b(on)d(Lin)m(ux)g(platforms)0 3897 y(y)m(ou)f(ma)m(y)g(need)f(to)h(man)m(ually)h(install)f(it.)42 b(This)29 b(can)i(b)s(e)f(easily)i(done)e(on)g(Ubun)m(tu)g(Lin)m(ux)g (using)g(the)h('apt)g(get')0 4010 y(command)f(to)h(retriev)m(e)h(the)f (lib)s(curl4-op)s(enssl-dev)f(or)g(the)g(lib)s(curl4-gn)m(utls-dev)h (pac)m(k)-5 b(ages.)0 4170 y(When)27 b(accessing)i(a)f(\014le)f(with)g (HTTPS,)f(the)i(default)f(CFITSIO)f(b)s(eha)m(vior)i(is)f(to)h(attempt) g(to)g(v)m(erify)g(b)s(oth)f(the)0 4283 y(host)k(name)h(and)f(the)g (SSL)f(certi\014cate.)46 b(If)31 b(it)h(cannot,)g(it)g(will)g(still)g (p)s(erform)e(the)i(\014le)f(access)i(but)e(will)g(issue)h(a)0 4396 y(w)m(arning)e(to)h(the)g(terminal)g(windo)m(w.)0 4556 y(The)36 b(user)f(can)i(o)m(v)m(erride)g(this)f(b)s(eha)m(vior)h (to)g(force)f(CFITSIO)f(to)i(only)f(allo)m(w)i(\014le)f(transfers)e (when)g(the)i(host)0 4669 y(name)47 b(and)e(SSL)h(certi\014cate)i(ha)m (v)m(e)g(b)s(een)e(successfully)g(v)m(eri\014ed.)89 b(This)46 b(is)g(done)h(b)m(y)f(setting)i(the)e(CFIT-)0 4782 y(SIO)p 160 4782 V 32 w(VERIFY)p 549 4782 V 33 w(HTTPS)29 b(en)m(vironmen)m(t)i (v)-5 b(ariable)31 b(to)g('T)-8 b(rue'.)41 b(ie.)g(in)30 b(a)h(csh)f(shell:)0 4942 y(seten)m(v)h(CFITSIO)p 662 4942 V 32 w(VERIFY)p 1051 4942 V 33 w(HTTPS)e(T)-8 b(rue)0 5102 y(the)31 b(default)f(setting)i(for)e(this)g(is)g('F)-8 b(alse'.)0 5262 y(CFITSIO)19 b(has)h(3)g(functions)g(whic)m(h)g(apply)g (sp)s(eci\014cally)h(to)g(HTTPS)e(access:)37 b(\014ts)p 2796 5262 V 33 w(init)p 2965 5262 V 33 w(h)m(ttps,)22 b(\014ts)p 3372 5262 V 33 w(clean)m(up)p 3705 5262 V 33 w(h)m(ttps,)0 5375 y(and)37 b(\014ts)p 311 5375 V 33 w(v)m(erb)s(ose)p 640 5375 V 32 w(h)m(ttps.)63 b(It)38 b(is)f(recommended)h(that)g(y)m(ou)g(call)h(the)f(init)g(and)f(clean)m (up)h(functions)f(near)h(the)0 5488 y(b)s(eginning)k(and)g(end)g(of)h (y)m(our)g(program)f(resp)s(ectiv)m(ely)-8 b(.)80 b(F)-8 b(or)44 b(more)e(information)h(ab)s(out)g(these)g(functions,)0 5601 y(please)30 b(see)f(the)g('FITS)f(File)i(Access)g(Routines')g (section)f(in)g(the)g(preceding)g(c)m(hapter)g(\('Sp)s(ecialized)h (CFITSIO)0 5714 y(In)m(terface)i(Routines'\).)p eop end %%Page: 128 136 TeXDict begin 128 135 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.128) cvn H.B /DEST pdfmark end 0 299 a Fj(128)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 464 y SDict begin H.S end 0 464 a 0 464 a SDict begin 13.6 H.A end 0 464 a 0 464 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.10.2.3) cvn H.B /DEST pdfmark end 0 464 a 91 x Fd(10.2.3)113 b(Notes)36 b(ab)s(out)j(the)e(stream)h(\014let)m(yp)s(e)g(driv)m(er)0 774 y Fj(The)e(stream)h(driv)m(er)f(can)h(b)s(e)f(used)g(to)h (e\016cien)m(tly)i(read)d(a)h(FITS)f(\014le)h(from)f(the)h(stdin)f (\014le)g(stream)h(or)g(write)0 887 y(a)44 b(FITS)e(to)i(the)g(stdout)f (\014le)g(stream.)80 b(Ho)m(w)m(ev)m(er,)49 b(b)s(ecause)43 b(these)h(input)e(and)h(output)g(streams)g(m)m(ust)h(b)s(e)0 1000 y(accessed)30 b(sequen)m(tially)-8 b(,)31 b(the)e(FITS)f(\014le)g (reading)h(or)f(writing)h(application)h(m)m(ust)e(also)i(read)e(and)g (write)h(the)g(\014le)0 1113 y(sequen)m(tially)-8 b(,)33 b(at)e(least)g(within)f(the)h(tolerances)h(describ)s(ed)d(b)s(elo)m(w.) 0 1273 y(CFITSIO)34 b(supp)s(orts)f(2)j(di\013eren)m(t)f(metho)s(ds)g (for)g(accessing)i(FITS)d(\014les)h(on)h(the)f(stdin)g(and)f(stdout)h (streams.)0 1386 y(The)c(original)i(metho)s(d,)f(whic)m(h)f(is)h(in)m (v)m(ok)m(ed)h(b)m(y)f(sp)s(ecifying)f(a)h(dash)f(c)m(haracter,)j("-",) g(as)d(the)h(name)g(of)g(the)g(\014le)0 1499 y(when)g(op)s(ening)g(or)h (creating)h(it,)g(w)m(orks)e(b)m(y)h(storing)g(a)g(complete)h(cop)m(y)g (of)f(the)g(en)m(tire)g(FITS)f(\014le)h(in)f(memory)-8 b(.)0 1612 y(In)35 b(this)g(case,)k(when)34 b(reading)i(from)f(stdin,)i (CFITSIO)d(will)i(cop)m(y)h(the)e(en)m(tire)i(stream)f(in)m(to)h (memory)e(b)s(efore)0 1725 y(doing)c(an)m(y)h(pro)s(cessing)f(of)h(the) f(\014le.)44 b(Similarly)-8 b(,)32 b(when)f(writing)g(to)h(stdout,)g (CFITSIO)d(will)j(create)h(a)f(cop)m(y)g(of)0 1837 y(the)h(en)m(tire)g (FITS)f(\014le)g(in)h(memory)-8 b(,)33 b(b)s(efore)f(\014nally)h (\015ushing)e(it)i(out)f(to)i(the)e(stdout)h(stream)g(when)e(the)i (FITS)0 1950 y(\014le)g(is)g(closed.)49 b(Bu\013ering)33 b(the)g(en)m(tire)h(FITS)e(\014le)h(in)g(this)f(w)m(a)m(y)i(allo)m(ws)g (the)f(application)i(to)e(randomly)g(access)0 2063 y(an)m(y)h(part)f (of)h(the)f(FITS)g(\014le,)i(in)e(an)m(y)h(order,)f(but)g(it)h(also)h (requires)e(that)h(the)f(user)g(ha)m(v)m(e)i(su\016cien)m(t)f(a)m(v)-5 b(ailable)0 2176 y(memory)30 b(\(or)g(virtual)g(memory\))g(to)h(store)f (the)g(en)m(tire)h(\014le,)f(whic)m(h)f(ma)m(y)i(not)f(b)s(e)f(p)s (ossible)g(in)h(the)g(case)h(of)f(v)m(ery)0 2289 y(large)h(\014les.)0 2449 y(The)e(new)m(er)g(stream)h(\014let)m(yp)s(e)g(pro)m(vides)f(a)h (more)f(memory-e\016cien)m(t)i(metho)s(d)e(of)h(accessing)h(FITS)d (\014les)h(on)h(the)0 2562 y(stdin)37 b(or)h(stdout)g(streams.)64 b(Instead)38 b(of)g(storing)g(a)g(cop)m(y)h(of)f(the)g(en)m(tire)h (FITS)e(\014le)h(in)g(memory)-8 b(,)40 b(CFITSIO)0 2675 y(only)32 b(uses)g(a)g(set)h(of)f(in)m(ternal)h(bu\013er)e(whic)m(h)h (b)m(y)g(default)g(can)g(store)h(40)g(FITS)e(blo)s(c)m(ks,)i(or)g(ab)s (out)e(100K)i(b)m(ytes)0 2788 y(of)f(the)f(FITS)g(\014le.)43 b(The)31 b(application)i(program)e(m)m(ust)g(pro)s(cess)g(the)h(FITS)e (\014le)i(sequen)m(tially)h(from)e(b)s(eginning)0 2901 y(to)h(end,)e(within)g(this)h(100K)h(bu\013er.)41 b(Generally)32 b(sp)s(eaking)f(the)g(application)h(program)f(m)m(ust)f(conform)h(to)h (the)0 3014 y(follo)m(wing)g(restrictions:)136 3265 y Fc(\017)46 b Fj(The)36 b(program)f(m)m(ust)h(\014nish)e(reading)i(or)g (writing)f(the)h(header)g(k)m(eyw)m(ords)g(b)s(efore)f(reading)h(or)g (writing)227 3378 y(an)m(y)31 b(data)g(in)f(the)h(HDU.)136 3563 y Fc(\017)46 b Fj(The)24 b(HDU)h(can)f(con)m(tain)i(at)e(most)h (ab)s(out)f(1400)h(header)f(k)m(eyw)m(ords.)39 b(This)24 b(is)g(the)g(maxim)m(um)g(that)h(can)f(\014t)227 3676 y(in)g(the)g(nominal)h(40)g(FITS)e(blo)s(c)m(k)i(bu\013er.)37 b(In)24 b(principle,)h(this)f(limit)h(could)f(b)s(e)g(increased)g(b)m (y)g(recompiling)227 3789 y(CFITSIO)29 b(with)h(a)h(larger)g(bu\013er)e (limit,)j(whic)m(h)e(is)g(set)h(b)m(y)f(the)h(NIOBUF)g(parameter)g(in)f (\014tsio2.h.)136 3974 y Fc(\017)46 b Fj(The)32 b(program)g(m)m(ust)f (read)h(or)g(write)h(the)f(data)g(in)g(a)g(sequen)m(tial)i(manner)d (from)h(the)g(b)s(eginning)f(to)i(the)227 4087 y(end)26 b(of)g(the)h(HDU.)g(Note)h(that)f(CFITSIO's)e(in)m(ternal)i(100K)g (bu\013er)e(allo)m(ws)j(a)e(little)j(latitude)e(in)f(meeting)227 4199 y(this)31 b(requiremen)m(t.)136 4384 y Fc(\017)46 b Fj(The)30 b(program)g(cannot)h(mo)m(v)m(e)h(bac)m(k)f(to)g(a)g (previous)f(HDU)h(in)f(the)h(FITS)e(\014le.)136 4569 y Fc(\017)46 b Fj(Reading)c(or)f(writing)f(of)h(v)-5 b(ariable)42 b(length)f(arra)m(y)h(columns)e(in)h(binary)f(tables)i(is) f(not)g(supp)s(orted)e(on)227 4682 y(streams,)29 b(b)s(ecause)f(this)g (requires)g(mo)m(ving)g(bac)m(k)h(and)f(forth)f(b)s(et)m(w)m(een)i(the) f(\014xed-length)g(p)s(ortion)g(of)g(the)227 4795 y(binary)i(table)h (and)f(the)g(follo)m(wing)i(heap)e(area)i(where)e(the)g(arra)m(ys)h (are)g(actually)h(stored.)136 4980 y Fc(\017)46 b Fj(Reading)25 b(or)g(writing)f(of)h(tile-compressed)h(images)g(is)e(not)h(supp)s (orted)e(on)h(streams,)i(b)s(ecause)f(the)g(images)227 5093 y(are)31 b(in)m(ternally)g(stored)g(using)f(v)-5 b(ariable)31 b(length)g(arra)m(ys.)0 5236 y SDict begin H.S end 0 5236 a 0 5236 a SDict begin 13.6 H.A end 0 5236 a 0 5236 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.10.2.4) cvn H.B /DEST pdfmark end 0 5236 a 146 x Fd(10.2.4)113 b(Notes)36 b(ab)s(out)j(the)e(gsiftp)h(\014let)m(yp)s(e)0 5601 y Fj(DEPENDENCIES:)c(Globus)h(to)s(olkit)h(\(2.4.3)g(or)f (higher\))f(\(GT\))h(should)f(b)s(e)g(installed.)53 b(There)34 b(are)h(t)m(w)m(o)h(dif-)0 5714 y(feren)m(t)31 b(w)m(a)m(ys)g(to)g (install)g(GT:)p eop end %%Page: 129 137 TeXDict begin 129 136 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.129) cvn H.B /DEST pdfmark end 0 299 a Fh(10.2.)73 b(FILETYPE)3037 b Fj(129)0 555 y(1\))43 b(goto)h(the)f(globus)f(to)s(olkit)i(w)m(eb)e (page)i(www.globus.org)e(and)g(follo)m(w)h(the)g(do)m(wnload)g(and)e (compilation)0 668 y(instructions;)0 828 y(2\))j(goto)i(the)d(Virtual)i (Data)g(T)-8 b(o)s(olkit)45 b(w)m(eb)e(page)i(h)m (ttp://vdt.cs.wisc.edu/)g(and)e(follo)m(w)i(the)f(instructions)0 941 y(\(STR)m(ONGL)-8 b(Y)31 b(SUGGESTED\);)0 1101 y(Once)23 b(a)h(globus)f(clien)m(t)h(has)f(b)s(een)g(installed)h(in)e(y)m(our)i (system)f(with)g(a)g(sp)s(eci\014c)g(\015a)m(v)m(our)h(it)f(is)g(p)s (ossible)g(to)h(compile)0 1214 y(and)30 b(install)h(the)g(CFITSIO)d (libraries.)41 b(Sp)s(eci\014c)30 b(con\014guration)h(\015ags)f(m)m (ust)h(b)s(e)e(used:)0 1374 y(1\))21 b({with-gsiftp[[=P)-8 b(A)g(TH]])22 b(Enable)f(Globus)f(T)-8 b(o)s(olkit)21 b(gsiftp)g(proto)s(col)g(supp)s(ort)d(P)-8 b(A)g(TH=GLOBUS)p 3532 1374 28 4 v 33 w(LOCA)g(TION)0 1487 y(i.e.)42 b(the)30 b(lo)s(cation)i(of)f(y)m(our)f(globus)g(installation)0 1647 y(2\))h({with-gsiftp-\015a)m(v)m(our[[=P)-8 b(A)g(TH])33 b(de\014nes)d(the)g(sp)s(eci\014c)g(Globus)h(\015a)m(v)m(our)f(ex.)41 b(gcc32)0 1808 y(Both)31 b(the)g(\015ags)f(m)m(ust)g(b)s(e)g(used)g (and)f(it)i(is)g(mandatory)f(to)h(set)g(b)s(oth)f(the)g(P)-8 b(A)g(TH)31 b(and)f(the)h(\015a)m(v)m(our.)0 1968 y(USA)m(GE:)g(T)-8 b(o)31 b(access)h(\014les)e(on)g(a)h(gridftp)f(serv)m(er)g(it)h(is)g (necessary)f(to)i(use)e(a)g(gsiftp)h(pre\014x:)0 2128 y(example:)41 b(gsiftp://remote)p 1003 2128 V 35 w(serv)m(er)p 1271 2128 V 34 w(fqhn/directory/\014lename)0 2288 y(The)f(gridftp)g (driv)m(er)g(uses)g(a)g(lo)s(cal)i(bu\013er)d(on)i(a)f(temp)s(orary)g (\014le)h(the)f(\014le)h(is)f(lo)s(cated)i(in)e(the)g(/tmp)h(direc-)0 2401 y(tory)-8 b(.)73 b(If)40 b(y)m(ou)h(ha)m(v)m(e)h(sp)s(ecial)g(p)s (ermissions)d(on)i(/tmp)g(or)g(y)m(ou)g(do)f(not)i(ha)m(v)m(e)g(a)f (/tmp)g(directory)-8 b(,)44 b(it)e(is)e(p)s(os-)0 2514 y(sible)d(to)h(force)g(another)g(lo)s(cation)g(setting)h(the)e(GSIFTP)p 2068 2514 V 32 w(TMPFILE)g(en)m(vironmen)m(t)h(v)-5 b(ariable)38 b(\(ex.)62 b(exp)s(ort)0 2627 y(GSIFTP)p 347 2627 V 32 w(TMPFILE=/y)m(our/lo)s(cation/y)m(ourtmp\014le\).)0 2787 y(Grid)34 b(FTP)g(supp)s(orts)f(m)m(ulti)h(c)m(hannel)h(transfer.) 52 b(By)35 b(default)f(a)h(single)g(c)m(hannel)g(transmission)f(is)g(a) m(v)-5 b(ailable.)0 2900 y(Ho)m(w)m(ev)m(er,)34 b(it)d(is)h(p)s (ossible)e(to)i(mo)s(dify)e(this)i(b)s(eha)m(vior)f(setting)h(the)f (GSIFTP)p 2691 2900 V 33 w(STREAMS)f(en)m(vironmen)m(t)h(v)-5 b(ari-)0 3013 y(able)31 b(\(ex.)41 b(exp)s(ort)30 b(GSIFTP)p 1016 3013 V 33 w(STREAMS=8\).)0 3182 y SDict begin H.S end 0 3182 a 0 3182 a SDict begin 13.6 H.A end 0 3182 a 0 3182 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.10.2.5) cvn H.B /DEST pdfmark end 0 3182 a 140 x Fd(10.2.5)113 b(Notes)36 b(ab)s(out)j(the)e(ro)s(ot)g(\014let)m(yp)s(e)0 3545 y Fj(The)20 b(original)j(ro)s(otd)d(serv)m(er)h(can)h(b)s(e)e(obtained) h(from:)36 b Fe(ftp://root.cern.ch/root)o(/roo)o(td.t)o(ar.)o(gz)15 b Fj(but,)22 b(for)0 3658 y(it)33 b(to)h(w)m(ork)f(correctly)h(with)e (CFITSIO)g(one)h(has)f(to)i(use)e(a)i(mo)s(di\014ed)d(v)m(ersion)j (whic)m(h)e(supp)s(orts)f(a)i(command)0 3771 y(to)41 b(return)d(the)j(length)f(of)g(the)g(\014le.)70 b(This)39 b(mo)s(di\014ed)f(v)m(ersion)j(is)f(a)m(v)-5 b(ailable)42 b(in)e(ro)s(otd)f(sub)s(directory)g(in)h(the)0 3884 y(CFITSIO)29 b(ftp)h(area)h(at)286 4159 y Fe(ftp://legacy.gsfc.nasa.gov)o(/so)o (ftwa)o(re/f)o(its)o(io/c)o(/roo)o(t/r)o(ootd)o(.tar)o(.gz)o(.)0 4435 y Fj(This)j(small)g(serv)m(er)h(is)g(started)f(either)h(b)m(y)g (inetd)f(when)f(a)i(clien)m(t)h(requests)e(a)h(connection)h(to)f(a)f (ro)s(otd)h(serv)m(er)0 4548 y(or)30 b(b)m(y)g(hand)f(\(i.e.)42 b(from)30 b(the)g(command)g(line\).)42 b(The)29 b(ro)s(otd)h(serv)m(er) h(w)m(orks)f(with)g(the)g(R)m(OOT)g(TNetFile)i(class.)0 4661 y(It)e(allo)m(ws)g(remote)h(access)f(to)h(R)m(OOT)e(database)h (\014les)f(in)g(either)h(read)g(or)f(write)h(mo)s(de.)40 b(By)30 b(default)f(TNetFile)0 4774 y(assumes)38 b(p)s(ort)g(432)h (\(whic)m(h)f(requires)g(ro)s(otd)g(to)h(b)s(e)f(started)h(as)f(ro)s (ot\).)65 b(T)-8 b(o)39 b(run)e(ro)s(otd)h(via)h(inetd)f(add)g(the)0 4887 y(follo)m(wing)32 b(line)f(to)g(/etc/services:)95 5162 y Fe(rootd)238 b(432/tcp)0 5438 y Fj(and)30 b(to)h (/etc/inetd.conf,)i(add)d(the)g(follo)m(wing)i(line:)95 5714 y Fe(rootd)47 b(stream)f(tcp)h(nowait)f(root)h (/user/rdm/root/bin/root)o(d)42 b(rootd)k(-i)p eop end %%Page: 130 138 TeXDict begin 130 137 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.130) cvn H.B /DEST pdfmark end 0 299 a Fj(130)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fj(F)g(orce)30 b(inetd)e(to)h(reread)f(its)h(conf)f(\014le)g (with)g Fe(kill)47 b(-HUP)g()p Fj(.)39 b(Y)-8 b(ou)28 b(can)h(also)g(start)g(ro)s(otd)f(b)m(y)g(hand)0 668 y(running)35 b(directly)i(under)d(y)m(our)j(priv)-5 b(ate)37 b(accoun)m(t)g(\(no)g(ro)s(ot)g(system)f(privileges)h (needed\).)59 b(F)-8 b(or)37 b(example)g(to)0 781 y(start)e(ro)s(otd)g (listening)g(on)g(p)s(ort)f(5151)j(just)d(t)m(yp)s(e:)49 b Fe(rootd)e(-p)g(5151)33 b Fj(Notice)k(that)f(no)e(&)h(is)f(needed.)54 b(Ro)s(otd)0 894 y(will)31 b(go)g(in)m(to)g(bac)m(kground)f(b)m(y)h (itself.)95 1139 y Fe(Rootd)47 b(arguments:)191 1252 y(-i)763 b(says)47 b(we)g(were)f(started)g(by)h(inetd)191 1365 y(-p)g(port#)476 b(specifies)45 b(a)j(different)d(port)i(to)g (listen)f(on)191 1478 y(-d)h(level)476 b(level)46 b(of)i(debug)e(info)h (written)e(to)j(syslog)1050 1591 y(0)f(=)h(no)f(debug)f(\(default\)) 1050 1704 y(1)h(=)h(minimum)1050 1817 y(2)f(=)h(medium)1050 1930 y(3)f(=)h(maximum)0 2175 y Fj(Ro)s(otd)29 b(can)f(also)h(b)s(e)f (con\014gured)g(for)g(anon)m(ymous)g(usage)h(\(lik)m(e)h(anon)m(ymous)e (ftp\).)40 b(T)-8 b(o)29 b(setup)f(ro)s(otd)g(to)h(accept)0 2288 y(anon)m(ymous)h(logins)h(do)g(the)f(follo)m(wing)i(\(while)f(b)s (eing)f(logged)i(in)e(as)g(ro)s(ot\):)143 2533 y Fe(-)48 b(Add)f(the)f(following)g(line)g(to)i(/etc/passwd:)239 2759 y(rootd:*:71:72:Anonymous)41 b(rootd:/var/spool/rootd:/b)o(in/)o (fals)o(e)239 2985 y(where)46 b(you)h(may)g(modify)f(the)h(uid,)f(gid)h (\(71,)g(72\))g(and)g(the)g(home)f(directory)239 3098 y(to)h(suite)f(your)h(system.)143 3323 y(-)h(Add)f(the)f(following)g (line)g(to)i(/etc/group:)239 3549 y(rootd:*:72:rootd)239 3775 y(where)e(the)h(gid)g(must)f(match)h(the)g(gid)g(in)g (/etc/passwd.)143 4001 y(-)h(Create)e(the)h(directories:)239 4227 y(mkdir)f(/var/spool/rootd)239 4340 y(mkdir)g (/var/spool/rootd/tmp)239 4452 y(chmod)g(777)h(/var/spool/rootd/tmp)239 4678 y(Where)f(/var/spool/rootd)d(must)k(match)f(the)h(rootd)g(home)f (directory)g(as)239 4791 y(specified)f(in)i(the)g(rootd)f(/etc/passwd)f (entry.)143 5017 y(-)j(To)f(make)f(writeable)g(directories)e(for)j (anonymous)f(do,)h(for)f(example:)239 5243 y(mkdir)g (/var/spool/rootd/pub)239 5356 y(chown)g(rootd:rootd)f (/var/spool/rootd/pub)0 5601 y Fj(That's)d(all.)76 b(Sev)m(eral)43 b(additional)g(remarks:)64 b(y)m(ou)42 b(can)g(login)h(to)g(an)f(anon)m (ymous)f(serv)m(er)i(either)f(with)g(the)0 5714 y(names)31 b("anon)m(ymous")h(or)f("ro)s(otd".)43 b(The)31 b(passw)m(ord)f(should) g(b)s(e)h(of)g(t)m(yp)s(e)g(user@host.do.main.)43 b(Only)30 b(the)h(@)p eop end %%Page: 131 139 TeXDict begin 131 138 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.131) cvn H.B /DEST pdfmark end 0 299 a Fh(10.3.)73 b(BASE)30 b(FILENAME)2739 b Fj(131)0 555 y(is)29 b(enforced)f(for)h(the)f(time)i (b)s(eing.)39 b(In)28 b(anon)m(ymous)h(mo)s(de)f(the)g(top)h(of)g(the)g (\014le)f(tree)i(is)e(set)h(to)h(the)e(ro)s(otd)h(home)0 668 y(directory)-8 b(,)39 b(therefore)e(only)f(\014les)h(b)s(elo)m(w)f (the)h(home)f(directory)h(can)f(b)s(e)g(accessed.)60 b(Anon)m(ymous)36 b(mo)s(de)g(only)0 781 y(w)m(orks)30 b(when)g(the)g(serv)m(er)h(is)f(started)h(via)g(inetd.)0 938 y SDict begin H.S end 0 938 a 0 938 a SDict begin 13.6 H.A end 0 938 a 0 938 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.10.2.6) cvn H.B /DEST pdfmark end 0 938 a 164 x Fd(10.2.6)113 b(Notes)36 b(ab)s(out)j(the)e(shmem)i(\014let)m(yp)s(e:)0 1327 y Fj(Shared)34 b(memory)h(\014les)g(are)g(curren)m(tly)g(supp)s (orted)e(on)i(most)h(Unix)f(platforms,)h(where)f(the)g(shared)f(memory) 0 1440 y(segmen)m(ts)d(are)g(managed)g(b)m(y)f(the)g(op)s(erating)h (system)g(k)m(ernel)f(and)g(`liv)m(e')i(indep)s(enden)m(tly)d(of)i(pro) s(cesses.)40 b(They)0 1553 y(are)34 b(not)g(deleted)h(\(b)m(y)f (default\))g(when)f(the)h(pro)s(cess)f(whic)m(h)h(created)h(them)f (terminates,)h(although)g(they)f(will)0 1665 y(disapp)s(ear)e(if)h(the) h(system)f(is)g(reb)s(o)s(oted.)49 b(Applications)34 b(can)g(create)h(shared)d(memory)h(\014les)g(in)g(CFITSIO)f(b)m(y)0 1778 y(calling:)143 2064 y Fe(fit_create_file\(&fitsfile)o(ptr,)41 b("shmem://h2",)j(&status\);)0 2349 y Fj(where)25 b(the)g(ro)s(ot)h (`\014le')f(names)h(are)f(curren)m(tly)g(restricted)h(to)g(b)s(e)f ('h0',)i('h1',)g('h2',)g('h3',)f(etc.,)i(up)d(to)g(a)h(maxim)m(um)0 2462 y(n)m(um)m(b)s(er)20 b(de\014ned)f(b)m(y)i(the)g(the)g(v)-5 b(alue)22 b(of)f(SHARED)p 1746 2462 28 4 v 33 w(MAXSEG)g(\(equal)h(to)f (16)h(b)m(y)f(default\).)38 b(This)20 b(is)h(a)g(protot)m(yp)s(e)0 2575 y(implemen)m(tation)30 b(of)f(the)g(shared)f(memory)g(in)m (terface)i(and)e(a)h(more)g(robust)f(in)m(terface,)j(whic)m(h)d(will)h (ha)m(v)m(e)h(few)m(er)0 2688 y(restrictions)h(on)f(the)h(n)m(um)m(b)s (er)e(of)i(\014les)f(and)g(on)g(their)g(names,)h(ma)m(y)g(b)s(e)f(dev)m (elop)s(ed)g(in)g(the)h(future.)0 2848 y(When)23 b(op)s(ening)h(an)f (already)h(existing)h(FITS)e(\014le)h(in)f(shared)g(memory)h(one)g (calls)g(the)g(usual)g(CFITSIO)e(routine:)143 3133 y Fe(fits_open_file\(&fitsfilep)o(tr,)41 b("shmem://h7",)j(mode,)j (&status\))0 3419 y Fj(The)26 b(\014le)h(mo)s(de)g(can)g(b)s(e)f(READ)m (WRITE)h(or)g(READONL)-8 b(Y)28 b(just)e(as)h(with)f(disk)h(\014les.)39 b(More)28 b(than)e(one)h(pro)s(cess)0 3532 y(can)35 b(op)s(erate)g(on)f (READONL)-8 b(Y)35 b(mo)s(de)f(\014les)h(at)g(the)f(same)h(time.)54 b(CFITSIO)33 b(supp)s(orts)f(prop)s(er)h(\014le)i(lo)s(c)m(king)0 3644 y(\(b)s(oth)27 b(in)h(READONL)-8 b(Y)29 b(and)e(READ)m(WRITE)h(mo) s(des\),)h(so)f(calls)h(to)f(\014ts)p 2572 3644 V 33 w(op)s(en)p 2795 3644 V 32 w(\014le)g(ma)m(y)g(b)s(e)f(lo)s(c)m(k)m(ed) j(out)e(un)m(til)0 3757 y(another)j(other)f(pro)s(cess)g(closes)i(the)e (\014le.)0 3918 y(When)g(an)g(application)i(is)e(\014nished)f (accessing)j(a)e(FITS)g(\014le)g(in)g(a)h(shared)e(memory)h(segmen)m (t,)i(it)f(ma)m(y)g(close)g(it)0 4030 y(\(and)j(the)g(\014le)g(will)g (remain)f(in)h(the)g(system\))g(with)g(\014ts)p 1955 4030 V 32 w(close)p 2173 4030 V 34 w(\014le,)h(or)f(delete)h(it)g(with) e(\014ts)p 3191 4030 V 33 w(delete)p 3455 4030 V 34 w(\014le.)51 b(Ph)m(ys-)0 4143 y(ical)36 b(deletion)g(is)f(p)s(ostp)s(oned)e(un)m (til)j(the)f(last)g(pro)s(cess)g(calls)h(\013clos/\013delt.)56 b(\014ts)p 2801 4143 V 32 w(delete)p 3064 4143 V 34 w(\014le)35 b(tries)h(to)f(obtain)h(a)0 4256 y(READ)m(WRITE)e(lo)s(c)m(k)g(on)f (the)g(\014le)h(to)g(b)s(e)e(deleted,)j(th)m(us)e(it)h(can)f(b)s(e)g (blo)s(c)m(k)m(ed)h(if)f(the)h(ob)5 b(ject)34 b(w)m(as)f(not)h(op)s (ened)0 4369 y(in)c(READ)m(WRITE)h(mo)s(de.)0 4529 y(A)i(shared)f (memory)h(managemen)m(t)h(utilit)m(y)g(program)f(called)h(`smem',)f(is) g(included)f(with)h(the)g(CFITSIO)e(dis-)0 4642 y(tribution.)39 b(It)27 b(can)g(b)s(e)f(built)h(b)m(y)g(t)m(yping)g(`mak)m(e)h(smem';)g (then)f(t)m(yp)s(e)g(`smem)f(-h')h(to)h(get)g(a)f(list)g(of)g(v)-5 b(alid)27 b(options.)0 4755 y(Executing)37 b(smem)f(without)g(an)m(y)h (options)g(causes)f(it)h(to)g(list)g(all)g(the)g(shared)e(memory)i (segmen)m(ts)g(curren)m(tly)0 4868 y(residing)c(in)g(the)g(system)h (and)e(managed)i(b)m(y)f(the)h(shared)e(memory)h(driv)m(er.)49 b(T)-8 b(o)34 b(get)g(a)g(list)g(of)f(all)h(the)g(shared)0 4981 y(memory)c(ob)5 b(jects,)32 b(run)d(the)h(system)h(utilit)m(y)g (program)f(`ip)s(cs)h([-a]'.)0 5171 y SDict begin H.S end 0 5171 a 0 5171 a SDict begin 13.6 H.A end 0 5171 a 0 5171 a SDict begin [ /View [/XYZ H.V] /Dest (section.10.3) cvn H.B /DEST pdfmark end 0 5171 a 174 x Ff(10.3)136 b(Base)45 b(Filename)0 5601 y Fj(The)31 b(base)g(\014lename)h(is)f(the)h(name)f (of)h(the)f(\014le)h(optionally)g(including)f(the)h(director/sub)s (directory)f(path,)h(and)0 5714 y(in)e(the)h(case)g(of)g(`ftp',)f(`h)m (ttp',)i(and)d(`ro)s(ot')j(\014let)m(yp)s(es,)e(the)h(mac)m(hine)g (iden)m(ti\014er.)41 b(Examples:)p eop end %%Page: 132 140 TeXDict begin 132 139 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.132) cvn H.B /DEST pdfmark end 0 299 a Fj(132)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)191 555 y Fe(myfile.fits)191 668 y(!data.fits)191 781 y(/data/myfile.fits) 191 894 y(fits.gsfc.nasa.gov/ftp/s)o(ampl)o(eda)o(ta/m)o(yfil)o(e.f)o (its.)o(gz)0 1120 y Fj(When)29 b(creating)h(a)f(new)f(output)h(\014le)g (on)g(magnetic)h(disk)e(\(of)i(t)m(yp)s(e)f(\014le://\))h(if)f(the)g (base)g(\014lename)g(b)s(egins)f(with)0 1233 y(an)34 b(exclamation)j(p)s(oin)m(t)d(\(!\))54 b(then)34 b(an)m(y)g(existing)i (\014le)e(with)g(that)h(same)g(basename)g(will)g(b)s(e)e(deleted)i (prior)f(to)0 1346 y(creating)h(the)f(new)g(FITS)f(\014le.)51 b(Otherwise)34 b(if)g(the)g(\014le)g(to)g(b)s(e)g(created)h(already)f (exists,)i(then)d(CFITSIO)g(will)0 1459 y(return)g(an)h(error)f(and)g (will)i(not)f(o)m(v)m(erwrite)h(the)f(existing)h(\014le.)52 b(Note)35 b(that)g(the)f(exclamation)i(p)s(oin)m(t,)f(')10 b(!',)36 b(is)e(a)0 1572 y(sp)s(ecial)28 b(UNIX)g(c)m(haracter,)j(so)d (if)f(it)i(is)f(used)f(on)g(the)h(command)g(line)g(rather)g(than)f(en)m (tered)h(at)h(a)f(task)h(prompt,)0 1685 y(it)j(m)m(ust)f(b)s(e)g (preceded)g(b)m(y)h(a)g(bac)m(kslash)g(to)g(force)g(the)g(UNIX)g(shell) f(to)h(pass)f(it)i(v)m(erbatim)f(to)g(the)g(application)0 1798 y(program.)0 1958 y(If)24 b(the)i(output)e(disk)h(\014le)g(name)g (ends)f(with)g(the)h(su\016x)f('.gz',)k(then)d(CFITSIO)e(will)i (compress)g(the)g(\014le)g(using)g(the)0 2071 y(gzip)g(compression)f (algorithm)h(b)s(efore)f(writing)g(it)h(to)g(disk.)38 b(This)23 b(can)i(reduce)f(the)g(amoun)m(t)h(of)f(disk)g(space)h(used)0 2184 y(b)m(y)34 b(the)h(\014le.)53 b(Note)36 b(that)f(this)g(feature)g (requires)f(that)h(the)f(uncompressed)g(\014le)g(b)s(e)g(constructed)h (in)f(memory)0 2297 y(b)s(efore)c(it)h(is)f(compressed)g(and)g(written) h(to)g(disk,)f(so)g(it)h(can)g(fail)g(if)f(there)h(is)f(insu\016cien)m (t)h(a)m(v)-5 b(ailable)33 b(memory)-8 b(.)0 2457 y(An)45 b(input)g(FITS)f(\014le)i(ma)m(y)g(b)s(e)f(compressed)g(with)h(the)f (gzip)h(or)g(Unix)f(compress)h(algorithms,)k(in)45 b(whic)m(h)0 2570 y(case)38 b(CFITSIO)e(will)i(uncompress)e(the)i(\014le)g(on)f(the) h(\015y)e(in)m(to)j(a)f(temp)s(orary)f(\014le)g(\(in)h(memory)f(or)g (on)h(disk\).)0 2683 y(Compressed)32 b(\014les)i(ma)m(y)g(only)f(b)s(e) g(op)s(ened)f(with)h(read-only)h(p)s(ermission.)49 b(When)33 b(sp)s(ecifying)g(the)h(name)f(of)h(a)0 2796 y(compressed)h(FITS)g (\014le)h(it)g(is)g(not)g(necessary)g(to)g(app)s(end)e(the)i(\014le)g (su\016x)e(\(e.g.,)39 b(`.gz')e(or)f(`.Z'\).)g(If)f(CFITSIO)0 2908 y(cannot)24 b(\014nd)e(the)h(input)f(\014le)i(name)f(without)g (the)g(su\016x,)h(then)f(it)h(will)g(automatically)i(searc)m(h)e(for)f (a)g(compressed)0 3021 y(\014le)36 b(with)f(the)h(same)g(ro)s(ot)g (name.)57 b(In)35 b(the)h(case)h(of)f(reading)g(ftp)f(and)g(h)m(ttp)h (t)m(yp)s(e)g(\014les,)h(CFITSIO)e(generally)0 3134 y(lo)s(oks)j(for)g (a)g(compressed)g(v)m(ersion)g(of)g(the)g(\014le)g(\014rst,)h(b)s (efore)e(trying)h(to)h(op)s(en)e(the)h(uncompressed)e(\014le.)64 b(By)0 3247 y(default,)37 b(CFITSIO)e(copies)h(\(and)g(uncompressed)e (if)i(necessary\))g(the)g(ftp)f(or)h(h)m(ttp)g(FITS)f(\014le)g(in)m(to) i(memory)0 3360 y(on)f(the)g(lo)s(cal)h(mac)m(hine)f(b)s(efore)g(op)s (ening)f(it.)58 b(This)35 b(will)h(fail)g(if)g(the)g(lo)s(cal)h(mac)m (hine)g(do)s(es)e(not)h(ha)m(v)m(e)h(enough)0 3473 y(memory)g(to)h (hold)f(the)g(whole)h(FITS)e(\014le,)k(so)d(in)g(this)g(case,)k(the)c (output)g(\014lename)g(sp)s(eci\014er)g(\(see)h(the)g(next)0 3586 y(section\))32 b(can)f(b)s(e)e(used)h(to)h(further)e(con)m(trol)j (ho)m(w)e(CFITSIO)f(reads)h(ftp)g(and)g(h)m(ttp)g(\014les.)0 3746 y(If)i(the)h(input)f(\014le)h(is)g(an)g(IRAF)g(image)h(\014le)f (\(*.imh)g(\014le\))h(then)e(CFITSIO)f(will)j(automatically)h(con)m(v)m (ert)g(it)e(on)0 3859 y(the)27 b(\015y)g(in)m(to)h(a)g(virtual)f(FITS)f (image)j(b)s(efore)e(it)g(is)g(op)s(ened)g(b)m(y)g(the)g(application)i (program.)39 b(IRAF)27 b(images)i(can)0 3972 y(only)h(b)s(e)g(op)s (ened)g(with)g(READONL)-8 b(Y)31 b(\014le)f(access.)0 4132 y(Similarly)-8 b(,)32 b(if)f(the)g(input)f(\014le)i(is)f(a)g(ra)m (w)g(binary)f(data)i(arra)m(y)-8 b(,)33 b(then)d(CFITSIO)g(will)h(con)m (v)m(ert)i(it)e(on)g(the)h(\015y)e(in)m(to)0 4245 y(a)38 b(virtual)g(FITS)g(image)h(with)e(the)h(basic)h(set)f(of)g(required)f (header)h(k)m(eyw)m(ords)g(b)s(efore)g(it)g(is)g(op)s(ened)f(b)m(y)h (the)0 4358 y(application)32 b(program)f(\(with)g(READONL)-8 b(Y)31 b(access\).)44 b(In)30 b(this)h(case)h(the)f(data)g(t)m(yp)s(e)g (and)g(dimensions)f(of)h(the)0 4471 y(image)d(m)m(ust)f(b)s(e)f(sp)s (eci\014ed)g(in)h(square)g(brac)m(k)m(ets)h(follo)m(wing)g(the)f (\014lename)g(\(e.g.)41 b(ra)m(w\014le.dat[ib512,512]\).)j(The)0 4584 y(\014rst)30 b(c)m(haracter)i(\(case)f(insensitiv)m(e\))h (de\014nes)e(the)g(data)h(t)m(yp)s(e)g(of)f(the)h(arra)m(y:)239 4810 y Fe(b)429 b(8-bit)46 b(unsigned)g(byte)239 4923 y(i)381 b(16-bit)46 b(signed)g(integer)239 5036 y(u)381 b(16-bit)46 b(unsigned)g(integer)239 5149 y(j)381 b(32-bit)46 b(signed)g(integer)239 5262 y(r)h(or)g(f)143 b(32-bit)46 b(floating)g(point)239 5375 y(d)381 b(64-bit)46 b(floating)g(point)0 5601 y Fj(An)40 b(optional)h(second)f(c)m(haracter)i(sp)s(eci\014es)e (the)h(b)m(yte)f(order)g(of)g(the)h(arra)m(y)g(v)-5 b(alues:)60 b(b)40 b(or)g(B)h(indicates)g(big)0 5714 y(endian)30 b(\(as)g(in)g(FITS)f(\014les)h(and)f(the)h(nativ)m(e)i(format)e(of)g (SUN)g(UNIX)g(w)m(orkstations)h(and)f(Mac)h(PCs\))e(and)h(l)g(or)p eop end %%Page: 133 141 TeXDict begin 133 140 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.133) cvn H.B /DEST pdfmark end 0 299 a Fh(10.4.)73 b(OUTPUT)29 b(FILE)h(NAME)h(WHEN)g(OPENING)f(AN)h(EXISTING)f(FILE)876 b Fj(133)0 555 y(L)27 b(indicates)i(little)g(endian)e(\(nativ)m(e)j (format)d(of)h(DEC)g(OSF)f(w)m(orkstations)h(and)f(IBM)h(PCs\).)40 b(If)27 b(this)g(c)m(haracter)0 668 y(is)f(omitted)g(then)f(the)h(arra) m(y)g(is)g(assumed)f(to)h(ha)m(v)m(e)h(the)f(nativ)m(e)g(b)m(yte)h (order)e(of)h(the)f(lo)s(cal)i(mac)m(hine.)40 b(These)25 b(data)0 781 y(t)m(yp)s(e)35 b(c)m(haracters)h(are)g(then)e(follo)m(w)m (ed)j(b)m(y)d(a)i(series)f(of)g(one)g(or)g(more)g(in)m(teger)h(v)-5 b(alues)35 b(separated)h(b)m(y)e(commas)0 894 y(whic)m(h)41 b(de\014ne)f(the)h(size)h(of)f(eac)m(h)h(dimension)f(of)g(the)g(ra)m(w) g(arra)m(y)-8 b(.)74 b(Arra)m(ys)41 b(with)f(up)g(to)i(5)f(dimensions)g (are)0 1007 y(curren)m(tly)31 b(supp)s(orted.)41 b(Finally)-8 b(,)33 b(a)e(b)m(yte)h(o\013set)g(to)g(the)f(p)s(osition)h(of)f(the)g (\014rst)f(pixel)i(in)f(the)g(data)h(\014le)f(ma)m(y)h(b)s(e)0 1120 y(sp)s(eci\014ed)h(b)m(y)g(separating)i(it)f(with)f(a)h(':')48 b(from)33 b(the)h(last)g(dimension)f(v)-5 b(alue.)51 b(If)33 b(omitted,)j(it)e(is)f(assumed)g(that)0 1233 y(the)i(o\013set)h(=)f(0.)54 b(This)35 b(parameter)g(ma)m(y)h(b)s(e)e (used)g(to)i(skip)e(o)m(v)m(er)i(an)m(y)g(header)e(information)i(in)e (the)h(\014le)g(that)0 1346 y(precedes)30 b(the)h(binary)f(data.)41 b(F)-8 b(urther)30 b(examples:)95 1603 y Fe(raw.dat[b10000])521 b(1-dimensional)45 b(10000)h(pixel)g(byte)h(array)95 1715 y(raw.dat[rb400,400,12])233 b(3-dimensional)45 b(floating)g(point) h(big-endian)f(array)95 1828 y(img.fits[ib512,512:2880])89 b(reads)47 b(the)g(512)g(x)g(512)g(short)f(integer)g(array)g(in)1336 1941 y(a)i(FITS)e(file,)h(skipping)e(over)i(the)g(2880)g(byte)f(header) 0 2198 y Fj(One)25 b(sp)s(ecial)g(case)h(of)f(input)f(\014le)h(is)g (where)g(the)g(\014lename)g(=)g(`-')h(\(a)f(dash)g(or)g(min)m(us)f (sign\))h(or)g('stdin')g(or)g('stdout',)0 2311 y(whic)m(h)d (signi\014es)h(that)h(the)f(input)e(\014le)i(is)g(to)h(b)s(e)e(read)g (from)h(the)g(stdin)f(stream,)j(or)e(written)f(to)i(the)f(stdout)g (stream)0 2424 y(if)34 b(a)g(new)g(output)f(\014le)h(is)g(b)s(eing)g (created.)52 b(In)33 b(the)h(case)h(of)f(reading)h(from)e(stdin,)h (CFITSIO)f(\014rst)g(copies)i(the)0 2537 y(whole)g(stream)h(in)m(to)g (a)f(temp)s(orary)g(FITS)f(\014le)i(\(in)f(memory)g(or)g(on)g(disk\),)h (and)f(subsequen)m(t)f(reading)h(of)h(the)0 2650 y(FITS)c(\014le)h(o)s (ccurs)g(in)f(this)h(cop)m(y)-8 b(.)49 b(When)33 b(writing)g(to)g (stdout,)h(CFITSIO)d(\014rst)h(constructs)h(the)g(whole)g(\014le)g(in)0 2763 y(memory)h(\(since)i(random)d(access)j(is)e(required\),)i(then)e (\015ushes)f(it)i(out)g(to)g(the)f(stdout)h(stream)g(when)e(the)i (\014le)0 2876 y(is)30 b(closed.)42 b(In)29 b(addition,)i(if)f(the)g (output)g(\014lename)g(=)g('-.gz')i(or)e('stdout.gz')h(then)f(it)h (will)f(b)s(e)g(gzip)g(compressed)0 2989 y(b)s(efore)g(b)s(eing)g (written)g(to)h(stdout.)0 3149 y(This)25 b(abilit)m(y)j(to)e(read)g (and)f(write)h(on)g(the)g(stdin)g(and)f(stdout)h(steams)g(allo)m(ws)i (FITS)d(\014les)h(to)g(b)s(e)g(pip)s(ed)e(b)s(et)m(w)m(een)0 3262 y(tasks)42 b(in)f(memory)g(rather)g(than)h(ha)m(ving)g(to)g (create)h(temp)s(orary)e(in)m(termediate)i(FITS)d(\014les)i(on)f(disk.) 73 b(F)-8 b(or)0 3375 y(example)28 b(if)e(task1)i(creates)h(an)e (output)f(FITS)g(\014le,)i(and)f(task2)g(reads)g(an)g(input)f(FITS)g (\014le,)i(the)f(FITS)f(\014le)h(ma)m(y)0 3487 y(b)s(e)j(pip)s(ed)f(b)s (et)m(w)m(een)i(the)f(2)h(tasks)g(b)m(y)f(sp)s(ecifying)143 3744 y Fe(task1)47 b(-)g(|)g(task2)g(-)0 4001 y Fj(where)30 b(the)h(v)m(ertical)i(bar)e(is)f(the)h(Unix)g(piping)f(sym)m(b)s(ol.)42 b(This)30 b(assumes)g(that)i(the)f(2)g(tasks)g(read)g(the)g(name)g(of)0 4114 y(the)g(FITS)e(\014le)i(o\013)f(of)h(the)g(command)f(line.)0 4251 y SDict begin H.S end 0 4251 a 0 4251 a SDict begin 13.6 H.A end 0 4251 a 0 4251 a SDict begin [ /View [/XYZ H.V] /Dest (section.10.4) cvn H.B /DEST pdfmark end 0 4251 a 197 x Ff(10.4)136 b(Output)44 b(File)i(Name)f(when)g(Op)t(ening)g(an)g (Existing)h(File)0 4698 y Fj(An)36 b(optional)i(output)e(\014lename)h (ma)m(y)h(b)s(e)e(sp)s(eci\014ed)g(in)g(paren)m(theses)h(immediately)h (follo)m(wing)g(the)f(base)g(\014le)0 4811 y(name)28 b(to)h(b)s(e)f(op)s(ened.)39 b(This)28 b(is)g(mainly)g(useful)g(in)g (those)g(cases)i(where)d(CFITSIO)g(creates)j(a)e(temp)s(orary)g(cop)m (y)0 4924 y(of)i(the)f(input)g(FITS)f(\014le)i(b)s(efore)f(it)h(is)f (op)s(ened)g(and)f(passed)h(to)h(the)g(application)h(program.)40 b(This)28 b(happ)s(ens)g(b)m(y)0 5036 y(default)i(when)g(op)s(ening)g (a)g(net)m(w)m(ork)h(FTP)g(or)f(HTTP-t)m(yp)s(e)g(\014le,)h(when)e (reading)h(a)h(compressed)f(FITS)g(\014le)g(on)0 5149 y(a)36 b(lo)s(cal)h(disk,)g(when)e(reading)h(from)g(the)g(stdin)f (stream,)j(or)d(when)g(a)i(column)e(\014lter,)j(ro)m(w)e(\014lter,)h (or)f(binning)0 5262 y(sp)s(eci\014er)29 b(is)g(included)g(as)h(part)f (of)g(the)h(input)f(\014le)g(sp)s(eci\014cation.)41 b(By)30 b(default)g(this)f(temp)s(orary)g(\014le)g(is)h(created)0 5375 y(in)g(memory)-8 b(.)41 b(If)29 b(there)h(is)g(not)g(enough)g (memory)g(to)h(create)g(the)g(\014le)f(cop)m(y)-8 b(,)31 b(then)f(CFITSIO)e(will)i(exit)h(with)f(an)0 5488 y(error.)45 b(In)32 b(these)g(cases)h(one)g(can)f(force)h(a)f(p)s(ermanen)m(t)g (\014le)g(to)h(b)s(e)e(created)i(on)f(disk,)g(instead)h(of)f(a)g(temp)s (orary)0 5601 y(\014le)38 b(in)f(memory)-8 b(,)40 b(b)m(y)d(supplying)f (the)i(name)g(in)f(paren)m(theses)h(immediately)h(follo)m(wing)g(the)e (base)h(\014le)g(name.)0 5714 y(The)30 b(output)g(\014lename)g(can)h (include)f(the)h(')10 b(!')41 b(clobb)s(er)30 b(\015ag.)p eop end %%Page: 134 142 TeXDict begin 134 141 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.134) cvn H.B /DEST pdfmark end 0 299 a Fj(134)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fj(Th)m(us,)48 b(if)d(the)g(input)f(\014lename)h(to)g(CFITSIO)f (is:)70 b Fe(file1.fits.gz\(file2.fit)o(s\))39 b Fj(then)44 b(CFITSIO)g(will)0 668 y(uncompress)39 b(`\014le1.\014ts.gz')j(in)m(to) f(the)f(lo)s(cal)h(disk)e(\014le)h(`\014le2.\014ts')h(b)s(efore)f(op)s (ening)f(it.)70 b(CFITSIO)38 b(do)s(es)i(not)0 781 y(automatically)33 b(delete)f(the)e(output)g(\014le,)h(so)g(it)g(will)f(still)i(exist)f (after)g(the)f(application)i(program)e(exits.)0 941 y(The)i(output)h (\014lename)g("mem://")i(is)e(also)h(allo)m(w)m(ed,)i(whic)m(h)c(will)i (write)f(the)g(output)f(\014le)h(in)m(to)h(memory)-8 b(,)35 b(and)0 1054 y(also)28 b(allo)m(w)g(write)f(access)h(to)g(the)f (\014le.)39 b(This)26 b('\014le')i(will)f(disapp)s(ear)f(when)g(it)h (is)g(closed,)h(but)e(this)h(ma)m(y)h(b)s(e)e(useful)0 1167 y(for)k(some)h(applications)g(whic)m(h)g(only)f(need)g(to)h(mo)s (dify)f(a)h(temp)s(orary)f(cop)m(y)h(of)f(the)h(\014le.)0 1327 y(In)k(some)i(cases,)h(sev)m(eral)f(di\013eren)m(t)g(temp)s(orary) e(FITS)h(\014les)g(will)g(b)s(e)f(created)i(in)f(sequence,)i(for)e (instance,)i(if)0 1440 y(one)f(op)s(ens)g(a)g(remote)h(\014le)f(using)g (FTP)-8 b(,)37 b(then)g(\014lters)g(ro)m(ws)g(in)g(a)h(binary)e(table)i (extension,)i(then)c(create)j(an)0 1553 y(image)f(b)m(y)f(binning)f(a)h (pair)g(of)g(columns.)60 b(In)36 b(this)h(case,)j(the)d(remote)h (\014le)f(will)g(b)s(e)f(copied)h(to)h(a)f(temp)s(orary)0 1666 y(lo)s(cal)j(\014le,)h(then)d(a)h(second)f(temp)s(orary)h(\014le)f (will)h(b)s(e)f(created)i(con)m(taining)g(the)e(\014ltered)h(ro)m(ws)f (of)h(the)g(table,)0 1779 y(and)c(\014nally)g(a)h(third)e(temp)s(orary) h(\014le)h(con)m(taining)g(the)g(binned)e(image)i(will)g(b)s(e)f (created.)57 b(In)34 b(cases)i(lik)m(e)h(this)0 1892 y(where)28 b(m)m(ultiple)h(\014les)f(are)h(created,)h(the)e(out\014le)h (sp)s(eci\014er)f(will)g(b)s(e)g(in)m(terpreted)h(the)f(name)g(of)h (the)f(\014nal)g(\014le)h(as)0 2005 y(describ)s(ed)g(b)s(elo)m(w,)i(in) f(descending)g(priorit)m(y:)136 2266 y Fc(\017)46 b Fj(as)29 b(the)g(name)g(of)g(the)g(\014nal)f(image)i(\014le)f(if)f(an)h(image)h (within)e(a)h(single)g(binary)f(table)i(cell)g(is)e(op)s(ened)g(or)h (if)227 2379 y(an)i(image)g(is)g(created)g(b)m(y)f(binning)g(a)g(table) i(column.)136 2568 y Fc(\017)46 b Fj(as)33 b(the)f(name)h(of)f(the)h (\014le)f(con)m(taining)i(the)e(\014ltered)g(table)i(if)e(a)h(column)f (\014lter)g(and/or)g(a)h(ro)m(w)f(\014lter)h(are)227 2681 y(sp)s(eci\014ed.)136 2870 y Fc(\017)46 b Fj(as)31 b(the)f(name)h(of)f(the)h(lo)s(cal)h(cop)m(y)f(of)f(the)h(remote)g(FTP) f(or)h(HTTP)e(\014le.)136 3059 y Fc(\017)46 b Fj(as)31 b(the)g(name)g(of)g(the)f(uncompressed)g(v)m(ersion)h(of)g(the)f(FITS)g (\014le,)h(if)g(a)g(compressed)f(FITS)g(\014le)h(on)g(lo)s(cal)227 3172 y(disk)f(has)g(b)s(een)g(op)s(ened.)136 3361 y Fc(\017)46 b Fj(otherwise,)31 b(the)g(output)f(\014lename)g(is)h(ignored.)0 3622 y(The)e(output)f(\014le)h(sp)s(eci\014er)g(is)g(useful)f(when)g (reading)h(FTP)g(or)g(HTTP-t)m(yp)s(e)g(FITS)f(\014les)h(since)g(it)h (can)f(b)s(e)g(used)0 3735 y(to)34 b(create)i(a)e(lo)s(cal)h(disk)e (cop)m(y)i(of)f(the)g(\014le)f(that)i(can)f(b)s(e)f(reused)g(in)g(the)h (future.)50 b(If)33 b(the)h(output)g(\014le)f(name)h(=)0 3848 y(`*')i(then)e(a)i(lo)s(cal)g(\014le)f(with)g(the)g(same)g(name)g (as)g(the)h(net)m(w)m(ork)f(\014le)g(will)h(b)s(e)e(created.)56 b(Note)36 b(that)f(CFITSIO)0 3961 y(will)30 b(b)s(eha)m(v)m(e)g (di\013eren)m(tly)h(dep)s(ending)d(on)i(whether)f(the)h(remote)g (\014le)g(is)g(compressed)f(or)h(not)g(as)g(sho)m(wn)f(b)m(y)h(the)0 4074 y(follo)m(wing)i(examples:)136 4309 y Fc(\017)46 b Fe(ftp://remote.machine/tmp/)o(myfi)o(le.f)o(its)o(.gz\()o(*\))28 b Fj(-)35 b(the)g(remote)h(compressed)e(\014le)h(is)g(copied)g(to)227 4422 y(the)d(lo)s(cal)h(compressed)f(\014le)g(`m)m(y\014le.\014ts.gz',) i(whic)m(h)d(is)h(then)g(uncompressed)e(in)i(lo)s(cal)h(memory)e(b)s (efore)227 4535 y(b)s(eing)f(op)s(ened)g(and)g(passed)f(to)j(the)e (application)i(program.)136 4724 y Fc(\017)46 b Fe (ftp://remote.machine/tmp/)o(myfi)o(le.f)o(its)o(.gz\()o(myfi)o(le.)o (fits)o(\))33 b Fj(-)39 b(the)g(remote)h(compressed)f(\014le)227 4837 y(is)d(copied)g(and)f(uncompressed)g(in)m(to)h(the)g(lo)s(cal)h (\014le)f(`m)m(y\014le.\014ts'.)57 b(This)35 b(example)h(requires)g (less)g(lo)s(cal)227 4950 y(memory)21 b(than)g(the)g(previous)f (example)i(since)f(the)g(\014le)g(is)g(uncompressed)e(on)i(disk)g (instead)g(of)g(in)f(memory)-8 b(.)136 5139 y Fc(\017)46 b Fe(ftp://remote.machine/tmp/)o(myfi)o(le.f)o(its)o(\(myf)o(ile.)o (fit)o(s.gz)o(\))24 b Fj(-)30 b(this)g(will)g(usually)g(pro)s(duce)f (an)227 5252 y(error)h(since)h(CFITSIO)e(itself)i(cannot)g(compress)f (\014les.)0 5488 y(The)36 b(exact)i(b)s(eha)m(vior)e(of)h(CFITSIO)e(in) h(the)h(latter)g(case)h(dep)s(ends)c(on)j(the)f(t)m(yp)s(e)h(of)g(ftp)f (serv)m(er)g(running)f(on)0 5601 y(the)c(remote)g(mac)m(hine)g(and)f (ho)m(w)g(it)h(is)f(con\014gured.)40 b(In)30 b(some)h(cases,)g(if)f (the)h(\014le)f(`m)m(y\014le.\014ts.gz')j(exists)e(on)f(the)0 5714 y(remote)38 b(mac)m(hine,)h(then)e(the)g(serv)m(er)g(will)h(cop)m (y)f(it)h(to)f(the)h(lo)s(cal)g(mac)m(hine.)61 b(In)36 b(other)h(cases)h(the)f(ftp)g(serv)m(er)p eop end %%Page: 135 143 TeXDict begin 135 142 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.135) cvn H.B /DEST pdfmark end 0 299 a Fh(10.5.)73 b(TEMPLA)-8 b(TE)30 b(FILE)g(NAME)h(WHEN)g(CREA)-8 b(TING)30 b(A)g(NEW)h(FILE)997 b Fj(135)0 555 y(will)36 b(automatically)j(create)e(and)f(transmit)g(a) g(compressed)g(v)m(ersion)g(of)g(the)g(\014le)g(if)g(only)g(the)g (uncompressed)0 668 y(v)m(ersion)27 b(exists.)41 b(This)26 b(can)h(get)h(rather)f(confusing,)h(so)f(users)f(should)g(use)h(a)g (certain)h(amoun)m(t)g(of)f(caution)h(when)0 781 y(using)34 b(the)h(output)f(\014le)h(sp)s(eci\014er)f(with)h(FTP)f(or)h(HTTP)f (\014le)h(t)m(yp)s(es,)h(to)f(mak)m(e)h(sure)e(they)h(get)h(the)f(b)s (eha)m(vior)0 894 y(that)c(they)g(exp)s(ect.)0 1071 y SDict begin H.S end 0 1071 a 0 1071 a SDict begin 13.6 H.A end 0 1071 a 0 1071 a SDict begin [ /View [/XYZ H.V] /Dest (section.10.5) cvn H.B /DEST pdfmark end 0 1071 a 179 x Ff(10.5)136 b(T)-11 b(emplate)45 b(File)h(Name)g(when)e(Creating)j(a)e(New)g(File)0 1504 y Fj(When)38 b(a)h(new)f(FITS)g(\014le)h(is)g(created)g(with)g(a)f (call)i(to)g(\014ts)p 2101 1504 28 4 v 32 w(create)p 2369 1504 V 35 w(\014le,)g(the)f(name)g(of)g(a)g(template)h(\014le)e (ma)m(y)0 1617 y(b)s(e)h(supplied)g(in)h(paren)m(theses)g(immediately)h (follo)m(wing)g(the)g(name)f(of)g(the)g(new)f(\014le)h(to)h(b)s(e)e (created.)71 b(This)0 1730 y(template)27 b(is)e(used)g(to)h(de\014ne)f (the)h(structure)f(of)h(one)f(or)h(more)g(HDUs)g(in)f(the)h(new)f (\014le.)39 b(The)25 b(template)i(\014le)e(ma)m(y)0 1843 y(b)s(e)32 b(another)h(FITS)f(\014le,)i(in)f(whic)m(h)f(case)i(the)f (newly)g(created)h(\014le)f(will)g(ha)m(v)m(e)h(exactly)h(the)e(same)g (k)m(eyw)m(ords)g(in)0 1956 y(eac)m(h)25 b(HDU)g(as)g(in)f(the)g (template)i(FITS)d(\014le,)j(but)d(all)j(the)e(data)h(units)e(will)i(b) s(e)f(\014lled)g(with)f(zeros.)40 b(The)24 b(template)0 2069 y(\014le)i(ma)m(y)h(also)g(b)s(e)e(an)h(ASCI)s(I)e(text)j(\014le,) g(where)f(eac)m(h)h(line)f(\(in)g(general\))i(describ)s(es)d(one)h (FITS)f(k)m(eyw)m(ord)i(record.)0 2182 y(The)j(format)h(of)f(the)h (ASCI)s(I)e(template)i(\014le)g(is)f(describ)s(ed)f(in)i(the)f(follo)m (wing)i(T)-8 b(emplate)31 b(Files)h(c)m(hapter.)0 2359 y SDict begin H.S end 0 2359 a 0 2359 a SDict begin 13.6 H.A end 0 2359 a 0 2359 a SDict begin [ /View [/XYZ H.V] /Dest (section.10.6) cvn H.B /DEST pdfmark end 0 2359 a 179 x Ff(10.6)136 b(Image)46 b(Tile-Compression)g(Sp)t(eci\014cation)0 2792 y Fj(When)28 b(sp)s(ecifying)g(the)h(name)g(of)f(the)h(output)f (FITS)g(\014le)g(to)h(b)s(e)f(created,)i(the)f(user)f(can)g(indicate)i (that)f(images)0 2905 y(should)d(b)s(e)h(written)g(in)g (tile-compressed)h(format)g(\(see)g(section)g(5.5,)h(\\Primary)e(Arra)m (y)h(or)f(IMA)m(GE)h(Extension)0 3018 y(I/O)f(Routines"\))i(b)m(y)e (enclosing)h(the)g(compression)f(parameters)h(in)f(square)g(brac)m(k)m (ets)i(follo)m(wing)g(the)f(ro)s(ot)f(disk)0 3131 y(\014le)j(name.)41 b(Here)31 b(are)g(some)g(examples)g(of)f(the)h(syn)m(tax)g(for)f(sp)s (ecifying)g(tile-compressed)i(output)e(images:)191 3410 y Fe(myfile.fit[compress])185 b(-)48 b(use)f(Rice)f(algorithm)g(and)h (default)e(tile)i(size)191 3636 y(myfile.fit[compress)42 b(GZIP])47 b(-)g(use)g(the)g(specified)e(compression)g(algorithm;)191 3748 y(myfile.fit[compress)d(Rice])238 b(only)46 b(the)h(first)g (letter)f(of)h(the)g(algorithm)191 3861 y(myfile.fit[compress)42 b(PLIO])238 b(name)46 b(is)i(required.)191 4087 y(myfile.fit[compress) 42 b(Rice)47 b(100,100])141 b(-)48 b(use)e(100)h(x)h(100)f(pixel)f (tile)h(size)191 4200 y(myfile.fit[compress)42 b(Rice)47 b(100,100;2])e(-)j(as)f(above,)f(and)h(use)g(noisebits)e(=)i(2)0 4379 y SDict begin H.S end 0 4379 a 0 4379 a SDict begin 13.6 H.A end 0 4379 a 0 4379 a SDict begin [ /View [/XYZ H.V] /Dest (section.10.7) cvn H.B /DEST pdfmark end 0 4379 a 177 x Ff(10.7)136 b(HDU)45 b(Lo)t(cation)g(Sp)t(eci\014cation)0 4811 y Fj(The)c(optional)h(HDU)h(lo)s(cation)g(sp)s(eci\014er)d (de\014nes)h(whic)m(h)g(HDU)h(\(Header-Data)i(Unit,)h(also)d(kno)m(wn)f (as)h(an)0 4924 y(`extension'\))36 b(within)d(the)i(FITS)e(\014le)h(to) h(initially)h(op)s(en.)51 b(It)34 b(m)m(ust)g(immediately)i(follo)m(w)f (the)f(base)h(\014le)f(name)0 5036 y(\(or)g(the)g(output)g(\014le)g (name)f(if)h(presen)m(t\).)52 b(If)33 b(it)h(is)g(not)g(sp)s(eci\014ed) g(then)f(the)h(\014rst)f(HDU)i(\(the)f(primary)f(arra)m(y\))0 5149 y(is)g(op)s(ened.)46 b(The)32 b(HDU)h(lo)s(cation)h(sp)s (eci\014er)e(is)h(required)f(if)g(the)h(colFilter,)i(ro)m(wFilter,)g (or)e(binSp)s(ec)e(sp)s(eci\014ers)0 5262 y(are)f(presen)m(t,)f(b)s (ecause)h(the)f(primary)f(arra)m(y)i(is)f(not)h(a)f(v)-5 b(alid)30 b(HDU)g(for)f(these)g(op)s(erations.)41 b(The)29 b(HDU)h(ma)m(y)g(b)s(e)0 5375 y(sp)s(eci\014ed)e(either)i(b)m(y)e (absolute)i(p)s(osition)f(n)m(um)m(b)s(er,)f(starting)i(with)e(0)i(for) e(the)h(primary)f(arra)m(y)-8 b(,)31 b(or)e(b)m(y)f(reference)0 5488 y(to)h(the)g(HDU)g(name,)g(and)f(optionally)-8 b(,)31 b(the)e(v)m(ersion)g(n)m(um)m(b)s(er)e(and)h(the)h(HDU)g(t)m(yp)s(e)g (of)f(the)h(desired)f(extension.)0 5601 y(The)k(lo)s(cation)h(of)f(an)g (image)i(within)d(a)i(single)f(cell)i(of)e(a)g(binary)g(table)h(ma)m(y) f(also)h(b)s(e)f(sp)s(eci\014ed,)g(as)g(describ)s(ed)0 5714 y(b)s(elo)m(w.)p eop end %%Page: 136 144 TeXDict begin 136 143 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.136) cvn H.B /DEST pdfmark end 0 299 a Fj(136)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fj(The)26 b(absolute)h(p)s(osition)f(of)g(the)h(extension)g(is)f (sp)s(eci\014ed)f(either)i(b)m(y)f(enclosed)h(the)g(n)m(um)m(b)s(er)e (in)h(square)f(brac)m(k)m(ets)0 668 y(\(e.g.,)k(`[1]')g(=)d(the)h (\014rst)f(extension)h(follo)m(wing)i(the)e(primary)e(arra)m(y\))j(or)f (b)m(y)f(preceded)h(the)g(n)m(um)m(b)s(er)e(with)i(a)g(plus)0 781 y(sign)37 b(\(`+1'\).)63 b(T)-8 b(o)38 b(sp)s(ecify)f(the)g(HDU)h (b)m(y)g(name,)h(giv)m(e)g(the)e(name)h(of)f(the)h(desired)f(HDU)h (\(the)f(v)-5 b(alue)38 b(of)g(the)0 894 y(EXTNAME)e(or)g(HDUNAME)h(k)m (eyw)m(ord\))g(and)f(optionally)h(the)f(extension)h(v)m(ersion)f(n)m (um)m(b)s(er)f(\(v)-5 b(alue)37 b(of)f(the)0 1007 y(EXTVER)27 b(k)m(eyw)m(ord\))i(and)e(the)h(extension)h(t)m(yp)s(e)e(\(v)-5 b(alue)29 b(of)f(the)g(XTENSION)f(k)m(eyw)m(ord:)40 b(IMA)m(GE,)29 b(ASCI)s(I)d(or)0 1120 y(T)-8 b(ABLE,)36 b(or)f(BINT)-8 b(ABLE\),)36 b(separated)f(b)m(y)g(commas)h(and)e(all)i(enclosed)g(in)f (square)g(brac)m(k)m(ets.)56 b(If)34 b(the)h(v)-5 b(alue)0 1233 y(of)34 b(EXTVER)f(and)f(XTENSION)h(are)h(not)f(sp)s(eci\014ed,)h (then)f(the)h(\014rst)e(extension)j(with)e(the)g(correct)i(v)-5 b(alue)34 b(of)0 1346 y(EXTNAME)39 b(is)g(op)s(ened.)67 b(The)38 b(extension)i(name)f(and)f(t)m(yp)s(e)i(are)f(not)h(case)g (sensitiv)m(e,)j(and)38 b(the)h(extension)0 1458 y(t)m(yp)s(e)29 b(ma)m(y)g(b)s(e)f(abbreviated)h(to)g(a)g(single)g(letter)h(\(e.g.,)h (I)d(=)g(IMA)m(GE)i(extension)f(or)f(primary)g(arra)m(y)-8 b(,)30 b(A)f(or)f(T)g(=)0 1571 y(ASCI)s(I)d(table)i(extension,)h(and)e (B)h(=)f(binary)g(table)h(BINT)-8 b(ABLE)27 b(extension\).)41 b(If)26 b(the)g(HDU)h(lo)s(cation)i(sp)s(eci\014er)0 1684 y(is)h(equal)h(to)g(`[PRIMAR)-8 b(Y]')32 b(or)f(`[P]',)g(then)f (the)h(primary)e(arra)m(y)i(\(the)g(\014rst)f(HDU\))h(will)g(b)s(e)f (op)s(ened.)0 1844 y(An)36 b(optional)j(p)s(ound)34 b(sign)j(c)m (haracter)i(\("#"\))f(ma)m(y)f(b)s(e)g(app)s(ended)e(to)i(the)g (extension)h(name)f(or)g(n)m(um)m(b)s(er)e(to)0 1957 y(signify)e(that)h(an)m(y)g(other)f(extensions)h(in)f(the)g(\014le)g (should)g(b)s(e)f(ignored)h(during)f(an)m(y)i(subsequen)m(t)e(\014le)i (\014ltering)0 2070 y(op)s(erations.)83 b(F)-8 b(or)45 b(example,)k(when)43 b(doing)i(ro)m(w)f(\014ltering)h(op)s(erations)f (on)h(a)f(table)i(extension,)i(CFITSIO)0 2183 y(normally)27 b(creates)i(a)e(cop)m(y)h(of)f(the)g(\014ltered)g(table)h(in)f(memory) -8 b(,)28 b(along)h(with)d(a)i(v)m(erbatim)f(cop)m(y)h(of)f(all)h(the)g (other)0 2296 y(extensions)h(in)g(the)g(input)f(FITS)g(\014le.)41 b(If)28 b(the)h(p)s(ound)e(sign)i(is)g(app)s(ended)e(to)j(the)f(table)h (extension)g(name,)f(then)0 2409 y(only)34 b(that)g(extension,)i(and)d (none)h(of)g(the)g(other)g(extensions)g(in)f(the)h(\014le,)h(will)g(b)m (y)e(copied)h(to)h(memory)-8 b(,)35 b(as)f(in)0 2522 y(the)d(follo)m(wing)g(example:)143 2773 y Fe(myfile.fit[events#][TIME) 41 b(>)48 b(10000])0 3024 y Fj(FITS)34 b(images)i(are)f(most)h (commonly)f(stored)g(in)g(the)g(primary)f(arra)m(y)h(or)g(an)g(image)h (extension,)h(but)d(images)0 3137 y(can)d(also)h(b)s(e)e(stored)h(as)h (a)f(v)m(ector)h(in)f(a)g(single)h(cell)g(of)f(a)h(binary)e(table)i (\(i.e.)43 b(eac)m(h)32 b(ro)m(w)f(of)g(the)h(v)m(ector)g(column)0 3250 y(con)m(tains)d(a)g(di\013eren)m(t)f(image\).)42 b(Suc)m(h)27 b(an)h(image)i(can)e(b)s(e)g(op)s(ened)f(with)h(CFITSIO)e (b)m(y)i(sp)s(ecifying)g(the)g(desired)0 3363 y(column)k(name)g(and)f (the)h(ro)m(w)g(n)m(um)m(b)s(er)f(after)h(the)g(binary)f(table)i(HDU)g (sp)s(eci\014er)e(as)h(sho)m(wn)g(in)f(the)h(follo)m(wing)0 3476 y(examples.)71 b(The)40 b(column)g(name)h(is)f(separated)h(from)f (the)h(HDU)g(sp)s(eci\014er)f(b)m(y)g(a)h(semicolon)g(and)f(the)h(ro)m (w)0 3589 y(n)m(um)m(b)s(er)29 b(is)h(enclosed)h(in)e(paren)m(theses.) 41 b(In)30 b(this)g(case)h(CFITSIO)d(copies)j(the)f(image)i(from)d(the) i(table)g(cell)g(in)m(to)0 3702 y(a)h(temp)s(orary)e(primary)h(arra)m (y)g(b)s(efore)g(it)h(is)f(op)s(ened.)43 b(The)30 b(application)j (program)e(then)g(just)g(sees)g(the)h(image)0 3815 y(in)i(the)h (primary)e(arra)m(y)-8 b(,)37 b(without)d(an)m(y)h(extensions.)53 b(The)34 b(particular)g(ro)m(w)h(to)g(b)s(e)e(op)s(ened)h(ma)m(y)h(b)s (e)f(sp)s(eci\014ed)0 3927 y(either)28 b(b)m(y)f(giving)h(an)f (absolute)h(in)m(teger)h(ro)m(w)f(n)m(um)m(b)s(er)e(\(starting)i(with)f (1)h(for)f(the)g(\014rst)g(ro)m(w\),)i(or)e(b)m(y)g(sp)s(ecifying)0 4040 y(a)33 b(b)s(o)s(olean)f(expression)g(that)h(ev)-5 b(aluates)34 b(to)f(TR)m(UE)g(for)f(the)g(desired)g(ro)m(w.)47 b(The)32 b(\014rst)f(ro)m(w)i(that)g(satis\014es)g(the)0 4153 y(expression)28 b(will)g(b)s(e)g(used.)39 b(The)28 b(ro)m(w)g(selection)i(expression)e(has)g(the)g(same)g(syn)m(tax)h(as)f (describ)s(ed)f(in)h(the)g(Ro)m(w)0 4266 y(Filter)k(Sp)s(eci\014er)d (section,)j(b)s(elo)m(w.)0 4426 y(Examples:)143 4677 y Fe(myfile.fits[3])44 b(-)k(open)e(the)h(3rd)g(HDU)g(following)e(the)i (primary)f(array)143 4790 y(myfile.fits+3)92 b(-)48 b(same)e(as)h (above,)f(but)h(using)g(the)g(FTOOLS-style)d(notation)143 4903 y(myfile.fits[EVENTS])f(-)k(open)g(the)g(extension)e(that)i(has)g (EXTNAME)e(=)j('EVENTS')143 5016 y(myfile.fits[EVENTS,)43 b(2])95 b(-)47 b(same)g(as)g(above,)f(but)h(also)g(requires)e(EXTVER)h (=)i(2)143 5129 y(myfile.fits[events,2,b])42 b(-)47 b(same,)f(but)h (also)g(requires)f(XTENSION)f(=)j('BINTABLE')143 5242 y(myfile.fits[3;)c(images\(17\)])h(-)i(opens)g(the)g(image)f(in)h(row)g (17)g(of)g(the)g('images')1527 5355 y(column)f(in)i(the)e(3rd)h (extension)f(of)h(the)g(file.)143 5468 y(myfile.fits[3;)d (images\(exposure)g(>)j(100\)])g(-)g(as)g(above,)f(but)h(opens)g(the)f (image)907 5581 y(in)h(the)g(first)f(row)h(that)g(has)g(an)g ('exposure')e(column)h(value)907 5694 y(greater)g(than)g(100.)p eop end %%Page: 137 145 TeXDict begin 137 144 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.137) cvn H.B /DEST pdfmark end 0 299 a Fh(10.8.)73 b(IMA)m(GE)31 b(SECTION)2744 b Fj(137)0 464 y SDict begin H.S end 0 464 a 0 464 a SDict begin 13.6 H.A end 0 464 a 0 464 a SDict begin [ /View [/XYZ H.V] /Dest (section.10.8) cvn H.B /DEST pdfmark end 0 464 a 91 x Ff(10.8)136 b(Image)46 b(Section)0 811 y Fj(A)41 b(virtual)g(\014le)f(con)m(taining)i(a)f(rectangular)h (subsection)e(of)h(an)g(image)g(can)g(b)s(e)f(extracted)i(and)e(op)s (ened)g(b)m(y)0 924 y(sp)s(ecifying)32 b(the)h(range)g(of)g(pixels)g (\(start:end\))g(along)h(eac)m(h)g(axis)f(to)g(b)s(e)f(extracted)i (from)e(the)h(original)g(image.)0 1037 y(One)d(can)h(also)h(sp)s(ecify) e(an)h(optional)h(pixel)f(incremen)m(t)g(\(start:end:step\))h(for)f (eac)m(h)h(axis)f(of)g(the)g(input)e(image.)0 1149 y(A)f(pixel)f(step)h (=)f(1)h(will)g(b)s(e)f(assumed)f(if)i(it)g(is)f(not)h(sp)s(eci\014ed.) 39 b(If)27 b(the)h(start)g(pixel)g(is)f(larger)i(then)e(the)h(end)e (pixel,)0 1262 y(then)32 b(the)g(image)h(will)f(b)s(e)f(\015ipp)s(ed)f (\(pro)s(ducing)h(a)h(mirror)g(image\))h(along)g(that)f(dimension.)45 b(An)32 b(asterisk,)h('*',)0 1375 y(ma)m(y)39 b(b)s(e)e(used)h(to)h(sp) s(ecify)f(the)g(en)m(tire)h(range)g(of)f(an)h(axis,)i(and)c('-*')j (will)e(\015ip)g(the)g(en)m(tire)h(axis.)65 b(The)38 b(input)0 1488 y(image)31 b(can)f(b)s(e)f(in)g(the)h(primary)f(arra)m (y)-8 b(,)31 b(in)e(an)g(image)i(extension,)g(or)f(con)m(tained)g(in)g (a)g(v)m(ector)h(cell)g(of)f(a)g(binary)0 1601 y(table.)40 b(In)25 b(the)h(later)h(2)f(cases)h(the)f(extension)h(name)f(or)f(n)m (um)m(b)s(er)g(m)m(ust)h(b)s(e)f(sp)s(eci\014ed)g(b)s(efore)h(the)g (image)h(section)0 1714 y(sp)s(eci\014er.)0 1874 y(Examples:)95 2157 y Fe(myfile.fits[1:512:2,)43 b(2:512:2])i(-)95 b(open)47 b(a)h(256x256)d(pixel)i(image)668 2270 y(consisting)e(of)i(the)g(odd)g (numbered)f(columns)g(\(1st)g(axis\))h(and)668 2383 y(the)g(even)g (numbered)e(rows)i(\(2nd)g(axis\))f(of)h(the)g(image)f(in)i(the)668 2496 y(primary)e(array)g(of)i(the)e(file.)95 2721 y(myfile.fits[*,)e (512:256])i(-)h(open)g(an)g(image)g(consisting)e(of)i(all)g(the)g (columns)668 2834 y(in)g(the)g(input)g(image,)f(but)h(only)f(rows)h (256)g(through)f(512.)668 2947 y(The)h(image)f(will)h(be)g(flipped)f (along)g(the)h(2nd)g(axis)g(since)668 3060 y(the)g(starting)f(pixel)g (is)h(greater)f(than)h(the)g(ending)f(pixel.)95 3286 y(myfile.fits[*:2,)e(512:256:2])h(-)i(same)g(as)g(above)f(but)h (keeping)f(only)668 3399 y(every)h(other)f(row)h(and)g(column)f(in)h (the)g(input)f(image.)95 3625 y(myfile.fits[-*,)e(*])j(-)h(copy)e(the)h (entire)f(image,)g(flipping)g(it)h(along)668 3738 y(the)g(first)f (axis.)95 3963 y(myfile.fits[3][1:256,1:256)o(])c(-)47 b(opens)g(a)g(subsection)e(of)i(the)g(image)g(that)668 4076 y(is)g(in)h(the)e(3rd)h(extension)f(of)h(the)g(file.)95 4302 y(myfile.fits[4;)d(images\(12\)][1:10,1:10])e(-)48 b(open)e(an)h(image)g(consisting)286 4415 y(of)h(the)e(first)h(10)g (pixels)f(in)h(both)g(dimensions.)e(The)i(original)286 4528 y(image)g(resides)f(in)h(the)g(12th)f(row)h(of)g(the)g('images')f (vector)286 4641 y(column)g(in)i(the)f(table)f(in)h(the)g(4th)g (extension)e(of)i(the)g(file.)0 4924 y Fj(When)23 b(CFITSIO)f(op)s(ens) h(an)g(image)h(section)h(it)f(\014rst)f(creates)h(a)g(temp)s(orary)f (\014le)h(con)m(taining)h(the)e(image)i(section)0 5036 y(plus)30 b(a)h(cop)m(y)h(of)f(an)m(y)g(other)g(HDUs)g(in)g(the)g (\014le.)42 b(\(If)31 b(a)g(`#')g(c)m(haracter)h(is)f(app)s(ended)e(to) j(the)f(name)f(or)h(n)m(um)m(b)s(er)0 5149 y(of)i(the)g(image)i(HDU,)e (as)h(in)e("m)m(y\014le.\014ts[1#][1:200,1:200)q(]",)40 b(then)33 b(the)g(other)g(HDUs)h(in)e(the)h(input)g(\014le)g(will)0 5262 y(not)j(b)s(e)f(copied)i(in)m(to)f(memory\).)58 b(This)35 b(temp)s(orary)g(\014le)h(is)g(then)f(op)s(ened)h(b)m(y)f (the)h(application)h(program,)h(so)0 5375 y(it)32 b(is)g(not)f(p)s (ossible)h(to)g(write)g(to)g(or)f(mo)s(dify)g(the)h(input)e(\014le)i (when)f(sp)s(ecifying)g(an)g(image)i(section.)45 b(Note)33 b(that)0 5488 y(CFITSIO)27 b(automatically)32 b(up)s(dates)c(the)h(w)m (orld)f(co)s(ordinate)i(system)f(k)m(eyw)m(ords)g(in)f(the)h(header)g (of)g(the)g(image)0 5601 y(section,)h(if)f(they)g(exist,)h(so)f(that)g (the)g(co)s(ordinate)h(asso)s(ciated)g(with)e(eac)m(h)i(pixel)f(in)g (the)g(image)h(section)g(will)f(b)s(e)0 5714 y(computed)h(correctly)-8 b(.)p eop end %%Page: 138 146 TeXDict begin 138 145 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.138) cvn H.B /DEST pdfmark end 0 299 a Fj(138)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 464 y SDict begin H.S end 0 464 a 0 464 a SDict begin 13.6 H.A end 0 464 a 0 464 a SDict begin [ /View [/XYZ H.V] /Dest (section.10.9) cvn H.B /DEST pdfmark end 0 464 a 91 x Ff(10.9)136 b(Image)46 b(T)-11 b(ransform)44 b(Filters)0 807 y Fj(CFITSIO)33 b(can)h(apply)g(a)h(user-sp)s(eci\014ed)e(mathematical)j(function)e(to) h(the)g(v)-5 b(alue)34 b(of)h(ev)m(ery)g(pixel)f(in)g(a)h(FITS)0 920 y(image,)29 b(th)m(us)e(creating)h(a)g(new)e(virtual)h(image)i(in)d (computer)h(memory)g(that)h(is)f(then)f(op)s(ened)h(and)f(read)h(b)m(y) g(the)0 1033 y(application)32 b(program.)40 b(The)30 b(original)i(FITS)d(image)j(is)e(not)h(mo)s(di\014ed)e(b)m(y)h(this)h (pro)s(cess.)0 1193 y(The)20 b(image)j(transformation)e(sp)s(eci\014er) f(is)h(app)s(ended)e(to)j(the)f(input)f(FITS)h(\014le)g(name)g(and)f (is)h(enclosed)h(in)e(square)0 1306 y(brac)m(k)m(ets.)42 b(It)29 b(b)s(egins)f(with)h(the)g(letters)i('PIX')e(to)h(distinguish)e (it)i(from)e(other)i(t)m(yp)s(es)f(of)g(FITS)f(\014le)h(\014lters)g (that)0 1419 y(are)36 b(recognized)i(b)m(y)e(CFITSIO.)e(The)i(image)h (transforming)f(function)f(ma)m(y)i(use)f(an)m(y)g(of)g(the)h (mathematical)0 1532 y(op)s(erators)44 b(listed)h(in)f(the)h(follo)m (wing)h('Ro)m(w)f(Filtering)g(Sp)s(eci\014cation')g(section)h(of)e (this)h(do)s(cumen)m(t.)82 b(Some)0 1645 y(examples)31 b(of)f(image)i(transform)e(\014lters)g(are:)48 1913 y Fe([pix)46 b(X)i(*)f(2.0])715 b(-)48 b(multiply)d(each)i(pixel)f(by)h (2.0)48 2026 y([pix)f(sqrt\(X\)])714 b(-)48 b(take)e(the)h(square)f (root)h(of)g(each)g(pixel)48 2139 y([pix)f(X)i(+)f(#ZEROPT)571 b(-)48 b(add)e(the)h(value)g(of)g(the)g(ZEROPT)f(keyword)48 2252 y([pix)g(X>0)h(?)h(log10\(X\))d(:)j(-99.])e(-)i(if)f(the)g(pixel)f (value)g(is)i(greater)1480 2365 y(than)e(0,)h(compute)f(the)h(base)g (10)g(log,)1480 2478 y(else)f(set)h(the)g(pixel)f(=)i(-99.)0 2746 y Fj(Use)24 b(the)g(letter)h('X')f(in)f(the)h(expression)g(to)g (represen)m(t)g(the)g(curren)m(t)f(pixel)h(v)-5 b(alue)24 b(in)f(the)h(image.)40 b(The)23 b(expression)0 2859 y(is)38 b(ev)-5 b(aluated)39 b(indep)s(enden)m(tly)e(for)g(eac)m(h)i(pixel)f (in)g(the)g(image)h(and)e(ma)m(y)h(b)s(e)g(a)g(function)f(of)h(1\))h (the)f(original)0 2971 y(pixel)32 b(v)-5 b(alue,)32 b(2\))g(the)f(v)-5 b(alue)32 b(of)f(other)h(pixels)f(in)g(the)g(image)i(at)f(a)f(giv)m(en) i(relativ)m(e)g(o\013set)f(from)f(the)g(p)s(osition)h(of)0 3084 y(the)d(pixel)f(that)h(is)g(b)s(eing)f(ev)-5 b(aluated,)30 b(and)e(3\))h(the)g(v)-5 b(alue)29 b(of)f(an)m(y)h(header)f(k)m(eyw)m (ords.)41 b(Header)29 b(k)m(eyw)m(ord)g(v)-5 b(alues)0 3197 y(are)31 b(represen)m(ted)f(b)m(y)g(the)h(name)f(of)h(the)f(k)m (eyw)m(ord)h(preceded)f(b)m(y)h(the)f('#')h(sign.)0 3357 y(T)-8 b(o)35 b(access)h(the)f(the)g(v)-5 b(alue)35 b(of)g(adjacen)m(t) h(pixels)f(in)f(the)h(image,)i(sp)s(ecify)e(the)g(\(1-D\))h(o\013set)g (from)e(the)h(curren)m(t)0 3470 y(pixel)c(in)f(curly)g(brac)m(k)m(ets.) 42 b(F)-8 b(or)31 b(example)48 3738 y Fe([pix)94 b(\(x{-1})46 b(+)i(x)f(+)h(x{+1}\))e(/)h(3])0 4006 y Fj(will)25 b(replace)g(eac)m(h) h(pixel)f(v)-5 b(alue)25 b(with)f(the)h(running)e(mean)i(of)f(the)h(v) -5 b(alues)25 b(of)g(that)g(pixel)g(and)f(it's)h(2)g(neigh)m(b)s(oring) 0 4119 y(pixels.)40 b(Note)30 b(that)g(in)e(this)g(notation)i(the)f (image)h(is)f(treated)g(as)g(a)g(1-D)h(arra)m(y)-8 b(,)30 b(where)e(eac)m(h)i(ro)m(w)f(of)g(the)g(image)0 4232 y(\(or)c(higher)f(dimensional)g(cub)s(e\))h(is)f(app)s(ended)f(one)h (after)h(another)g(in)f(one)h(long)g(arra)m(y)g(of)f(pixels.)39 b(It)25 b(is)f(p)s(ossible)0 4345 y(to)35 b(refer)f(to)h(pixels)f(in)g (the)g(ro)m(ws)g(ab)s(o)m(v)m(e)h(or)g(b)s(elo)m(w)f(the)g(curren)m(t)g (pixel)h(b)m(y)f(using)f(the)h(v)-5 b(alue)35 b(of)f(the)h(NAXIS1)0 4458 y(header)30 b(k)m(eyw)m(ord.)41 b(F)-8 b(or)32 b(example)48 4726 y Fe([pix)46 b(\(x{-#NAXIS1})f(+)i(x)h(+)f(x{#NAXIS1}\))e(/)i(3])0 4994 y Fj(will)34 b(compute)f(the)h(mean)f(of)g(eac)m(h)i(image)f (pixel)g(and)e(the)i(pixels)f(immediately)i(ab)s(o)m(v)m(e)f(and)f(b)s (elo)m(w)g(it)h(in)f(the)0 5107 y(adjacen)m(t)27 b(ro)m(ws)f(of)g(the)f (image.)41 b(The)25 b(follo)m(wing)i(more)f(complex)h(example)f (creates)h(a)f(smo)s(othed)g(virtual)g(image)0 5220 y(where)k(eac)m(h)h (pixel)g(is)g(a)f(3)h(x)f(3)h(b)s(o)m(xcar)g(a)m(v)m(erage)i(of)d(the)h (input)e(image)j(pixels:)95 5488 y Fe([pix)47 b(\(X)g(+)h(X{-1})e(+)i (X{+1})286 5601 y(+)g(X{-#NAXIS1})d(+)i(X{-#NAXIS1)e(-)i(1})h(+)f (X{-#NAXIS1)e(+)j(1})286 5714 y(+)g(X{#NAXIS1})d(+)i(X{#NAXIS1)f(-)h (1})g(+)h(X{#NAXIS1)d(+)i(1}\))g(/)h(9.])p eop end %%Page: 139 147 TeXDict begin 139 146 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.139) cvn H.B /DEST pdfmark end 0 299 a Fh(10.10.)73 b(COLUMN)30 b(AND)h(KEYW)m(ORD)g(FIL)-8 b(TERING)31 b(SPECIFICA)-8 b(TION)984 b Fj(139)0 555 y(If)31 b(the)h(pixel)g(o\013set)h(extends)f (b)s(ey)m(ond)f(the)h(\014rst)f(or)h(last)h(pixel)f(in)f(the)h(image,)i (the)e(function)g(will)g(ev)-5 b(aluate)33 b(to)0 668 y(unde\014ned,)28 b(or)j(NULL.)0 828 y(F)-8 b(or)39 b(complex)g(or)g (commonly)g(used)e(image)j(\014ltering)f(op)s(erations,)i(one)d(can)h (write)g(the)f(expression)h(in)m(to)g(an)0 941 y(external)i(text)h (\014le)f(and)f(then)g(imp)s(ort)g(it)h(in)m(to)h(the)e(\014lter)h (using)f(the)h(syn)m(tax)g('[pix)g(@\014lename.txt]'.)72 b(The)0 1054 y(mathematical)29 b(expression)e(can)g(extend)g(o)m(v)m (er)i(m)m(ultiple)e(lines)g(of)h(text)g(in)e(the)h(\014le.)40 b(An)m(y)27 b(lines)g(in)g(the)g(external)0 1167 y(text)h(\014le)e (that)i(b)s(egin)e(with)g(2)h(slash)f(c)m(haracters)i(\('//'\))h(will)e (b)s(e)f(ignored)h(and)f(ma)m(y)h(b)s(e)f(used)g(to)h(add)f(commen)m (ts)0 1280 y(in)m(to)31 b(the)g(\014le.)0 1440 y(By)c(default,)g(the)f (datat)m(yp)s(e)i(of)e(the)g(resulting)h(image)g(will)g(b)s(e)e(the)i (same)f(as)h(the)f(original)i(image,)g(but)e(one)g(ma)m(y)0 1553 y(force)31 b(a)g(di\013eren)m(t)g(datat)m(yp)s(e)g(b)m(y)f(app)s (ended)f(a)h(co)s(de)h(letter)h(to)f(the)f('pix')h(k)m(eyw)m(ord:)286 1786 y Fe(pixb)95 b(-)g(8-bit)46 b(byte)190 b(image)46 b(with)h(BITPIX)f(=)143 b(8)286 1898 y(pixi)95 b(-)47 b(16-bit)f(integer)g(image)g(with)h(BITPIX)f(=)95 b(16)286 2011 y(pixj)g(-)47 b(32-bit)f(integer)g(image)g(with)h(BITPIX)f(=)95 b(32)286 2124 y(pixr)g(-)47 b(32-bit)f(float)142 b(image)46 b(with)h(BITPIX)f(=)i(-32)286 2237 y(pixd)95 b(-)47 b(64-bit)f(float) 142 b(image)46 b(with)h(BITPIX)f(=)i(-64)0 2470 y Fj(Also)23 b(b)m(y)f(default,)j(an)m(y)d(other)h(HDUs)g(in)f(the)g(input)g(\014le) g(will)h(b)s(e)e(copied)i(without)g(c)m(hange)g(to)g(the)g(output)f (virtual)0 2583 y(FITS)k(\014le,)h(but)f(one)g(ma)m(y)h(discard)f(the)h (other)f(HDUs)h(b)m(y)f(adding)g(the)h(n)m(um)m(b)s(er)e('1')i(to)g (the)g('pix')f(k)m(eyw)m(ord)h(\(and)0 2696 y(follo)m(wing)32 b(an)m(y)f(optional)g(datat)m(yp)s(e)g(co)s(de)g(letter\).)42 b(F)-8 b(or)32 b(example:)239 2928 y Fe(myfile.fits[3][pixr1)90 b(sqrt\(X\)])0 3161 y Fj(will)23 b(create)i(a)e(virtual)g(FITS)f (\014le)h(con)m(taining)h(only)f(a)g(primary)f(arra)m(y)i(image)g(with) e(32-bit)i(\015oating)g(p)s(oin)m(t)f(pixels)0 3274 y(that)29 b(ha)m(v)m(e)h(a)f(v)-5 b(alue)30 b(equal)f(to)g(the)g(square)g(ro)s (ot)g(of)g(the)g(pixels)f(in)h(the)g(image)h(that)f(is)g(in)f(the)h (3rd)f(extension)i(of)0 3387 y(the)h('m)m(y\014le.\014ts')g(\014le.)0 3537 y SDict begin H.S end 0 3537 a 0 3537 a SDict begin 13.6 H.A end 0 3537 a 0 3537 a SDict begin [ /View [/XYZ H.V] /Dest (section.10.10) cvn H.B /DEST pdfmark end 0 3537 a 179 x Ff(10.10)136 b(Column)45 b(and)g(Keyw)l(ord)g(Filtering)h(Sp)t (eci\014cation)0 3966 y Fj(The)27 b(optional)i(column/k)m(eyw)m(ord)g (\014ltering)f(sp)s(eci\014er)f(is)h(used)f(to)i(mo)s(dify)e(the)h (column)g(structure)f(and/or)h(the)0 4079 y(header)38 b(k)m(eyw)m(ords)h(in)f(the)h(HDU)g(that)h(w)m(as)f(selected)h(with)e (the)h(previous)f(HDU)h(lo)s(cation)h(sp)s(eci\014er.)65 b(This)0 4192 y(\014ltering)42 b(sp)s(eci\014er)f(m)m(ust)h(b)s(e)f (enclosed)i(in)e(square)h(brac)m(k)m(ets)h(and)e(can)h(b)s(e)f (distinguished)g(from)h(a)g(general)0 4305 y(ro)m(w)d(\014lter)g(sp)s (eci\014er)f(\(describ)s(ed)g(b)s(elo)m(w\))h(b)m(y)g(the)g(fact)h (that)f(it)g(b)s(egins)f(with)h(the)g(string)g('col)h(')f(and)f(is)h (not)0 4418 y(immediately)30 b(follo)m(w)m(ed)g(b)m(y)e(an)g(equals)h (sign.)40 b(The)28 b(original)h(\014le)f(is)h(not)f(c)m(hanged)h(b)m(y) f(this)h(\014ltering)f(op)s(eration,)0 4531 y(and)c(instead)h(the)g(mo) s(di\014cations)g(are)g(made)g(on)f(a)h(cop)m(y)h(of)e(the)h(input)f (FITS)g(\014le)h(\(usually)g(in)f(memory\),)i(whic)m(h)0 4644 y(also)31 b(con)m(tains)g(a)g(cop)m(y)g(of)f(all)h(the)f(other)g (HDUs)h(in)f(the)g(\014le.)41 b(\(If)30 b(a)g(`#')h(c)m(haracter)g(is)f (app)s(ended)f(to)i(the)f(name)0 4757 y(or)d(n)m(um)m(b)s(er)e(of)i (the)g(table)g(HDU)h(then)e(only)h(the)g(primary)f(arra)m(y)-8 b(,)28 b(and)e(none)h(of)g(the)f(other)h(HDUs)h(in)e(the)h(input)0 4869 y(\014le)i(will)f(b)s(e)g(copied)h(in)m(to)g(memory\).)41 b(This)27 b(temp)s(orary)h(\014le)h(is)f(passed)g(to)h(the)g (application)h(program)e(and)g(will)0 4982 y(p)s(ersist)e(only)i(un)m (til)f(the)g(\014le)g(is)h(closed)f(or)g(un)m(til)h(the)f(program)g (exits,)i(unless)d(the)h(out\014le)h(sp)s(eci\014er)e(\(see)i(ab)s(o)m (v)m(e\))0 5095 y(is)i(also)i(supplied.)0 5255 y(The)f(column/k)m(eyw)m (ord)h(\014lter)f(can)g(b)s(e)g(used)f(to)i(p)s(erform)e(the)i(follo)m (wing)g(op)s(erations.)44 b(More)32 b(than)f(one)g(op)s(er-)0 5368 y(ation)g(ma)m(y)g(b)s(e)f(sp)s(eci\014ed)g(b)m(y)g(separating)h (them)f(with)h(commas)f(or)h(semi-colons.)136 5601 y Fc(\017)46 b Fj(Cop)m(y)36 b(only)g(a)g(sp)s(eci\014ed)g(list)g(of)g (columns)g(columns)f(to)i(the)f(\014ltered)g(input)f(\014le.)57 b(The)36 b(list)g(of)g(column)227 5714 y(name)41 b(should)e(b)s(e)g (separated)i(b)m(y)f(commas)h(or)f(semi-colons.)72 b(Wild)41 b(card)f(c)m(haracters)h(ma)m(y)g(b)s(e)f(used)p eop end %%Page: 140 148 TeXDict begin 140 147 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.140) cvn H.B /DEST pdfmark end 0 299 a Fj(140)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)227 555 y Fj(in)38 b(the)f(column)h(names)g(to)g(matc)m(h)g(m)m(ultiple)h (columns.)62 b(If)37 b(the)h(expression)g(con)m(tains)g(b)s(oth)f(a)h (list)h(of)227 668 y(columns)29 b(to)h(b)s(e)f(included)g(and)g (columns)g(to)h(b)s(e)e(deleted,)j(then)e(all)h(the)g(columns)f(in)g (the)h(original)g(table)227 781 y(except)36 b(the)e(explicitly)i (deleted)f(columns)f(will)h(app)s(ear)e(in)h(the)h(\014ltered)f(table)h (\(i.e.,)i(there)e(is)f(no)g(need)227 894 y(to)d(explicitly)h(list)f (the)g(columns)f(to)h(b)s(e)f(included)f(if)i(an)m(y)f(columns)h(are)f (b)s(eing)g(deleted\).)136 1084 y Fc(\017)46 b Fj(Delete)32 b(a)d(column)g(or)g(k)m(eyw)m(ord)h(b)m(y)f(listing)h(the)f(name)g (preceded)g(b)m(y)g(a)g(min)m(us)g(sign)g(or)g(an)g(exclamation)227 1197 y(mark)c(\(!\),)h(e.g.,)i('-TIME')d(will)g(delete)h(the)e(TIME)h (column)f(if)g(it)i(exists,)g(otherwise)f(the)g(TIME)f(k)m(eyw)m(ord.) 227 1310 y(An)35 b(error)f(is)h(returned)e(if)i(neither)f(a)i(column)e (nor)g(k)m(eyw)m(ord)h(with)g(this)f(name)h(exists.)54 b(Note)36 b(that)g(the)227 1422 y(exclamation)27 b(p)s(oin)m(t,)g(')10 b(!',)27 b(is)e(a)g(sp)s(ecial)h(UNIX)f(c)m(haracter,)j(so)d(if)g(it)h (is)f(used)f(on)h(the)g(command)g(line)g(rather)227 1535 y(than)33 b(en)m(tered)h(at)g(a)g(task)g(prompt,)f(it)h(m)m(ust)f(b)s (e)g(preceded)g(b)m(y)g(a)h(bac)m(kslash)g(to)g(force)g(the)f(UNIX)h (shell)227 1648 y(to)d(ignore)g(it.)136 1838 y Fc(\017)46 b Fj(Rename)29 b(an)g(existing)g(column)f(or)h(k)m(eyw)m(ord)g(with)f (the)h(syn)m(tax)g('NewName)h(==)e(OldName'.)40 b(An)28 b(error)227 1951 y(is)j(returned)e(if)h(neither)h(a)f(column)g(nor)g(k) m(eyw)m(ord)h(with)f(this)h(name)f(exists.)136 2141 y Fc(\017)46 b Fj(App)s(end)37 b(a)j(new)f(column)f(or)i(k)m(eyw)m(ord)f (to)h(the)f(table.)68 b(T)-8 b(o)40 b(create)g(a)g(column,)h(giv)m(e)g (the)e(new)g(name,)227 2254 y(optionally)c(follo)m(w)m(ed)f(b)m(y)f (the)g(data)h(t)m(yp)s(e)f(in)f(paren)m(theses,)i(follo)m(w)m(ed)h(b)m (y)e(a)g(single)h(equals)f(sign)g(and)f(an)227 2366 y(expression)j(to)h (b)s(e)e(used)g(to)i(compute)f(the)g(v)-5 b(alue)35 b(\(e.g.,)j('new)m (col\(1J\))f(=)e(0')g(will)h(create)g(a)f(new)g(32-bit)227 2479 y(in)m(teger)i(column)d(called)j('new)m(col')f(\014lled)f(with)g (zeros\).)55 b(The)35 b(data)g(t)m(yp)s(e)h(is)f(sp)s(eci\014ed)f (using)g(the)i(same)227 2592 y(syn)m(tax)j(that)g(is)f(allo)m(w)m(ed)i (for)e(the)g(v)-5 b(alue)39 b(of)f(the)g(FITS)f(TF)m(ORMn)h(k)m(eyw)m (ord)h(\(e.g.,)j('I',)d('J',)f('E',)h('D',)227 2705 y(etc.)66 b(for)38 b(binary)f(tables,)42 b(and)37 b('I8',)k(F12.3',)i('E20.12',)g (etc.)65 b(for)38 b(ASCI)s(I)f(tables\).)66 b(If)37 b(the)i(data)g(t)m (yp)s(e)227 2818 y(is)c(not)g(sp)s(eci\014ed)f(then)g(an)g(appropriate) h(data)g(t)m(yp)s(e)g(will)g(b)s(e)f(c)m(hosen)h(dep)s(ending)e(on)h (the)h(form)f(of)h(the)227 2931 y(expression)44 b(\(ma)m(y)g(b)s(e)f(a) h(c)m(haracter)i(string,)h(logical,)j(bit,)d(long)d(in)m(teger,)49 b(or)43 b(double)h(column\).)80 b(An)227 3044 y(appropriate)39 b(v)m(ector)i(coun)m(t)e(\(in)g(the)g(case)h(of)f(binary)f(tables\))i (will)f(also)h(b)s(e)e(added)g(if)h(not)g(explicitly)227 3157 y(sp)s(eci\014ed.)227 3308 y(When)26 b(creating)h(a)f(new)f(k)m (eyw)m(ord,)j(the)e(k)m(eyw)m(ord)g(name)g(m)m(ust)g(b)s(e)f(preceded)g (b)m(y)h(a)g(p)s(ound)e(sign)h('#',)j(and)227 3421 y(the)h(expression)f (m)m(ust)g(ev)-5 b(aluate)30 b(to)f(a)g(scalar)g(\(i.e.,)h(cannot)f(ha) m(v)m(e)h(a)f(column)f(name)g(in)g(the)h(expression\).)227 3534 y(The)j(commen)m(t)i(string)f(for)f(the)h(k)m(eyw)m(ord)h(ma)m(y)f (b)s(e)f(sp)s(eci\014ed)g(in)g(paren)m(theses)h(immediately)h(follo)m (wing)227 3647 y(the)27 b(k)m(eyw)m(ord)g(name)f(\(instead)h(of)g (supplying)e(a)i(data)g(t)m(yp)s(e)g(as)f(in)g(the)h(case)g(of)g (creating)h(a)f(new)f(column\).)227 3760 y(If)e(the)h(k)m(eyw)m(ord)g (name)f(ends)g(with)g(a)h(p)s(ound)d(sign)i('#',)i(then)e(c\014tsio)i (will)e(substitute)h(the)f(n)m(um)m(b)s(er)f(of)i(the)227 3873 y(most)31 b(recen)m(tly)h(referenced)e(column)h(for)f(the)h(#)f(c) m(haracter)i(.)41 b(This)29 b(is)i(esp)s(ecially)h(useful)d(when)h (writing)227 3986 y(a)c(column-related)g(k)m(eyw)m(ord)g(lik)m(e)g (TUNITn)e(for)h(a)h(newly)f(created)h(column,)g(as)g(sho)m(wn)e(in)h (the)g(follo)m(wing)227 4099 y(examples.)227 4250 y(COMMENT)30 b(and)g(HISTOR)-8 b(Y)30 b(k)m(eyw)m(ords)g(ma)m(y)h(also)h(b)s(e)e (created)h(with)f(the)h(follo)m(wing)g(syn)m(tax:)370 4503 y Fe(#COMMENT)46 b(=)h('This)g(is)g(a)g(comment)f(keyword')370 4616 y(#HISTORY)g(=)h('This)g(is)g(a)g(history)f(keyword')227 4869 y Fj(Note)d(that)f(the)f(equal)h(sign)f(and)f(the)i(quote)f(c)m (haracters)i(will)f(b)s(e)e(remo)m(v)m(ed,)45 b(so)d(that)f(the)h (resulting)227 4982 y(header)30 b(k)m(eyw)m(ords)h(in)f(these)h(cases)g (will)g(lo)s(ok)g(lik)m(e)h(this:)370 5235 y Fe(COMMENT)46 b(This)h(is)g(a)h(comment)d(keyword)370 5348 y(HISTORY)h(This)h(is)g(a) h(history)d(keyword)227 5601 y Fj(These)29 b(t)m(w)m(o)h(sp)s(ecial)f (k)m(eyw)m(ords)h(are)f(alw)m(a)m(ys)h(app)s(ended)d(to)j(the)f(end)f (of)h(the)g(header)g(and)f(will)h(not)g(a\013ect)227 5714 y(an)m(y)i(previously)f(existing)h(COMMENT)f(or)h(HISTOR)-8 b(Y)30 b(k)m(eyw)m(ords.)p eop end %%Page: 141 149 TeXDict begin 141 148 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.141) cvn H.B /DEST pdfmark end 0 299 a Fh(10.10.)73 b(COLUMN)30 b(AND)h(KEYW)m(ORD)g(FIL)-8 b(TERING)31 b(SPECIFICA)-8 b(TION)984 b Fj(141)136 555 y Fc(\017)46 b Fj(Recompute)f(\(o)m(v)m (erwrite\))i(the)d(v)-5 b(alues)44 b(in)g(an)g(existing)i(column)e(or)g (k)m(eyw)m(ord)g(b)m(y)g(giving)i(the)e(name)227 668 y(follo)m(w)m(ed)32 b(b)m(y)f(an)f(equals)h(sign)f(and)g(an)g (arithmetic)i(expression.)0 918 y(The)23 b(expression)g(that)i(is)e (used)g(when)g(app)s(ending)f(or)h(recomputing)h(columns)f(or)h(k)m (eyw)m(ords)g(can)g(b)s(e)f(arbitrarily)0 1031 y(complex)36 b(and)g(ma)m(y)g(b)s(e)f(a)h(function)g(of)g(other)g(header)g(k)m(eyw)m (ord)g(v)-5 b(alues)36 b(and)f(other)h(columns)g(\(in)g(the)g(same)0 1144 y(ro)m(w\).)63 b(The)37 b(full)g(syn)m(tax)i(and)e(a)m(v)-5 b(ailable)40 b(functions)d(for)g(the)h(expression)f(are)h(describ)s(ed) f(b)s(elo)m(w)h(in)f(the)h(ro)m(w)0 1257 y(\014lter)30 b(sp)s(eci\014cation)i(section.)0 1417 y(If)27 b(the)h(expression)g (con)m(tains)g(b)s(oth)f(a)h(list)h(of)f(columns)f(to)h(b)s(e)g (included)e(and)i(columns)f(to)h(b)s(e)f(deleted,)j(then)d(all)0 1530 y(the)34 b(columns)g(in)g(the)g(original)h(table)g(except)g(the)f (explicitly)i(deleted)f(columns)e(will)i(app)s(ear)e(in)h(the)g (\014ltered)0 1643 y(table.)40 b(If)26 b(no)g(columns)f(to)i(b)s(e)f (deleted)g(are)h(sp)s(eci\014ed,)f(then)g(only)g(the)h(columns)e(that)i (are)f(explicitly)i(listed)f(will)0 1756 y(b)s(e)k(included)g(in)g(the) h(\014ltered)f(output)h(table.)45 b(T)-8 b(o)32 b(include)f(all)i(the)e (columns,)h(add)f(the)h('*')g(wildcard)g(sp)s(eci\014er)0 1869 y(at)f(the)g(end)e(of)i(the)f(list,)i(as)e(sho)m(wn)g(in)g(the)h (examples.)0 2029 y(F)-8 b(or)33 b(complex)f(or)g(commonly)h(used)e(op) s(erations,)i(one)f(can)h(place)g(the)f(op)s(erations)g(in)m(to)h(an)f (external)h(text)g(\014le)0 2142 y(and)39 b(imp)s(ort)h(it)g(in)m(to)h (the)f(column)g(\014lter)g(using)f(the)h(syn)m(tax)h('[col)g (@\014lename.txt]'.)71 b(The)39 b(op)s(erations)i(can)0 2255 y(extend)35 b(o)m(v)m(er)h(m)m(ultiple)g(lines)f(of)g(the)g (\014le,)h(but)e(m)m(ultiple)i(op)s(erations)f(m)m(ust)f(still)i(b)s(e) e(separated)i(b)m(y)e(commas)0 2368 y(or)e(semi-colons.)47 b(An)m(y)32 b(lines)h(in)f(the)g(external)h(text)g(\014le)f(that)h(b)s (egin)e(with)h(2)h(slash)e(c)m(haracters)j(\('//'\))g(will)f(b)s(e)0 2481 y(ignored)d(and)g(ma)m(y)h(b)s(e)f(used)g(to)h(add)e(commen)m(ts)j (in)m(to)f(the)g(\014le.)0 2641 y(Examples:)143 2891 y Fe([col)47 b(Time,)f(rate])667 b(-)47 b(only)g(the)g(Time)g(and)g (rate)f(columns)g(will)1670 3004 y(appear)h(in)g(the)g(filtered)e (input)i(file.)143 3230 y([col)g(Time,)f(*raw])667 b(-)47 b(include)f(the)h(Time)g(column)f(and)h(any)g(other)1670 3343 y(columns)f(whose)h(name)f(ends)h(with)g('raw'.)143 3569 y([col)g(-TIME,)f(Good)h(==)g(STATUS])141 b(-)47 b(deletes)f(the)h(TIME)g(column)f(and)1670 3681 y(renames)g(the)h (status)f(column)g(to)i('Good')143 3907 y([col)f(PI=PHA)f(*)h(1.1)g(+)h (0.2;)e(#TUNIT#\(column)e(units\))i(=)i('counts';*])1575 4020 y(-)f(creates)f(new)h(PI)g(column)f(from)h(PHA)g(values)1670 4133 y(and)g(also)g(writes)f(the)h(TUNITn)f(keyword)1670 4246 y(for)h(the)g(new)g(column.)94 b(The)47 b(final)f('*')1670 4359 y(expression)f(means)i(preserve)e(all)i(the)1670 4472 y(columns)f(in)h(the)g(input)g(table)f(in)h(the)1670 4585 y(virtual)f(output)g(table;)94 b(without)46 b(the)h('*')1670 4698 y(the)g(output)f(table)h(would)f(only)h(contain)1670 4811 y(the)g(single)f('PI')h(column.)143 5036 y([col)g(rate)f(=)i (rate/exposure;)c(TUNIT#\(&\))h(=)j('counts/s';*])1575 5149 y(-)f(recomputes)e(the)i(rate)g(column)f(by)h(dividing)1670 5262 y(it)h(by)f(the)g(EXPOSURE)e(keyword)h(value.)g(This)1670 5375 y(also)h(modifies)f(the)h(value)f(of)h(the)g(TUNITn)1670 5488 y(keyword)f(for)h(this)g(column.)f(The)h(use)f(of)i(the)1670 5601 y('&')f(character)f(for)h(the)f(keyword)g(comment)1670 5714 y(string)h(means)f(preserve)f(the)i(existing)p eop end %%Page: 142 150 TeXDict begin 142 149 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.142) cvn H.B /DEST pdfmark end 0 299 a Fj(142)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)1670 555 y Fe(comment)46 b(string)g(for)h(that)g(keyword.)e(The)1670 668 y(final)i('*')g(preserves)e(all)i(the)g(columns)1670 781 y(in)h(the)f(input)f(table)g(in)h(the)g(virtual)1670 894 y(output)g(table.)0 1086 y SDict begin H.S end 0 1086 a 0 1086 a SDict begin 13.6 H.A end 0 1086 a 0 1086 a SDict begin [ /View [/XYZ H.V] /Dest (section.10.11) cvn H.B /DEST pdfmark end 0 1086 a 177 x Ff(10.11)136 b(Ro)l(w)46 b(Filtering)g(Sp)t (eci\014cation)0 1520 y Fj(When)29 b(en)m(tering)h(the)f(name)g(of)g(a) g(FITS)f(table)i(that)g(is)e(to)i(b)s(e)e(op)s(ened)h(b)m(y)f(a)i (program,)f(an)g(optional)h(ro)m(w)f(\014lter)0 1633 y(ma)m(y)i(b)s(e)g(sp)s(eci\014ed)f(to)h(select)h(a)g(subset)e(of)h (the)g(ro)m(ws)f(in)h(the)g(table.)43 b(A)31 b(temp)s(orary)f(new)g (FITS)g(\014le)h(is)g(created)0 1746 y(on)40 b(the)f(\015y)g(whic)m(h)h (con)m(tains)h(only)e(those)h(ro)m(ws)g(for)f(whic)m(h)h(the)g(ro)m(w)f (\014lter)h(expression)f(ev)-5 b(aluates)42 b(to)e(true.)0 1859 y(The)29 b(primary)f(arra)m(y)i(and)f(an)m(y)g(other)h(extensions) g(in)f(the)g(input)g(\014le)g(are)h(also)g(copied)g(to)g(the)g(temp)s (orary)f(\014le.)0 1972 y(\(If)35 b(a)h(`#')f(c)m(haracter)i(is)e(app)s (ended)e(to)j(the)g(name)f(or)g(n)m(um)m(b)s(er)f(of)h(the)g(table)h (HDU)g(then)f(only)g(the)h(primary)0 2085 y(arra)m(y)-8 b(,)37 b(and)d(none)h(of)g(the)g(other)g(HDUs)h(in)e(the)i(input)e (\014le)g(will)i(b)s(e)e(copied)h(in)m(to)h(the)f(temp)s(orary)g (\014le\).)54 b(The)0 2198 y(original)30 b(FITS)f(\014le)g(is)g(closed) h(and)e(the)i(new)e(virtual)i(\014le)f(is)g(op)s(ened)f(b)m(y)h(the)h (application)g(program.)40 b(The)29 b(ro)m(w)0 2310 y(\014lter)37 b(expression)g(is)h(enclosed)g(in)f(square)g(brac)m(k)m(ets)i(follo)m (wing)g(the)e(\014le)h(name)f(and)g(extension)h(name)f(\(e.g.,)0 2423 y('\014le.\014ts[ev)m(en)m(ts][GRADE==50]')29 b(selects)d(only)f (those)h(ro)m(ws)f(where)f(the)h(GRADE)h(column)f(v)-5 b(alue)25 b(equals)g(50\).)0 2536 y(When)33 b(dealing)h(with)f(tables)g (where)g(eac)m(h)h(ro)m(w)f(has)g(an)g(asso)s(ciated)i(time)f(and/or)f (2D)g(spatial)i(p)s(osition,)f(the)0 2649 y(ro)m(w)e(\014lter)h (expression)e(can)i(also)g(b)s(e)f(used)f(to)i(select)h(ro)m(ws)e (based)g(on)g(the)g(times)h(in)f(a)g(Go)s(o)s(d)g(Time)g(In)m(terv)-5 b(als)0 2762 y(\(GTI\))31 b(extension,)g(or)f(on)h(spatial)g(p)s (osition)g(as)f(giv)m(en)i(in)e(a)g(SA)m(O-st)m(yle)i(region)f(\014le.) 0 2947 y SDict begin H.S end 0 2947 a 0 2947 a SDict begin 13.6 H.A end 0 2947 a 0 2947 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.10.11.1) cvn H.B /DEST pdfmark end 0 2947 a 141 x Fd(10.11.1)113 b(General)38 b(Syn)m(tax)0 3314 y Fj(The)32 b(ro)m(w)h(\014ltering)g(expression)g(can)g(b)s(e)f(an)h (arbitrarily)g(complex)g(series)g(of)g(op)s(erations)g(p)s(erformed)f (on)g(con-)0 3427 y(stan)m(ts,)39 b(k)m(eyw)m(ord)e(v)-5 b(alues,)38 b(and)e(column)g(data)i(tak)m(en)f(from)f(the)h(sp)s (eci\014ed)e(FITS)h(T)-8 b(ABLE)37 b(extension.)59 b(The)0 3540 y(expression)37 b(m)m(ust)h(ev)-5 b(aluate)39 b(to)g(a)f(b)s(o)s (olean)g(v)-5 b(alue)38 b(for)f(eac)m(h)i(ro)m(w)f(of)g(the)f(table,)k (where)c(a)h(v)-5 b(alue)39 b(of)e(F)-10 b(ALSE)0 3653 y(means)30 b(that)h(the)g(ro)m(w)f(will)h(b)s(e)f(excluded.)0 3813 y(F)-8 b(or)34 b(complex)g(or)g(commonly)f(used)g(\014lters,)h (one)g(can)g(place)g(the)g(expression)f(in)m(to)h(a)g(text)g(\014le)g (and)f(imp)s(ort)f(it)0 3926 y(in)m(to)38 b(the)e(ro)m(w)h(\014lter)g (using)f(the)h(syn)m(tax)g('[@\014lename.txt]'.)61 b(The)36 b(expression)h(can)f(b)s(e)g(arbitrarily)h(complex)0 4039 y(and)27 b(extend)i(o)m(v)m(er)g(m)m(ultiple)g(lines)f(of)g(the)h (\014le.)40 b(An)m(y)28 b(lines)g(in)g(the)g(external)h(text)g(\014le)f (that)h(b)s(egin)f(with)g(2)g(slash)0 4152 y(c)m(haracters)k(\('//'\))g (will)f(b)s(e)f(ignored)g(and)g(ma)m(y)h(b)s(e)f(used)f(to)i(add)f (commen)m(ts)h(in)m(to)h(the)e(\014le.)0 4312 y(Keyw)m(ord)37 b(and)f(column)g(data)i(are)f(referenced)g(b)m(y)g(name.)60 b(An)m(y)37 b(string)f(of)h(c)m(haracters)i(not)e(surrounded)d(b)m(y)0 4425 y(quotes)41 b(\(ie,)j(a)d(constan)m(t)h(string\))f(or)f(follo)m(w) m(ed)i(b)m(y)f(an)f(op)s(en)g(paren)m(theses)h(\(ie,)j(a)d(function)f (name\))h(will)g(b)s(e)0 4538 y(initially)d(in)m(terpreted)e(as)h(a)g (column)f(name)g(and)g(its)h(con)m(ten)m(ts)h(for)e(the)h(curren)m(t)f (ro)m(w)g(inserted)g(in)m(to)i(the)e(ex-)0 4650 y(pression.)k(If)28 b(no)h(suc)m(h)g(column)g(exists,)h(a)g(k)m(eyw)m(ord)f(of)h(that)f (name)g(will)h(b)s(e)e(searc)m(hed)i(for)f(and)f(its)i(v)-5 b(alue)29 b(used,)0 4763 y(if)36 b(found.)55 b(T)-8 b(o)36 b(force)g(the)g(name)g(to)h(b)s(e)e(in)m(terpreted)h(as)g(a)g(k)m(eyw)m (ord)g(\(in)g(case)g(there)g(is)g(b)s(oth)f(a)h(column)g(and)0 4876 y(k)m(eyw)m(ord)41 b(with)e(the)i(same)f(name\),)j(precede)d(the)h (k)m(eyw)m(ord)f(name)g(with)g(a)h(single)f(p)s(ound)e(sign,)43 b('#',)g(as)d(in)0 4989 y('#NAXIS2'.)g(Due)27 b(to)g(the)f (generalities)j(of)d(FITS)g(column)g(and)g(k)m(eyw)m(ord)h(names,)g(if) f(the)h(column)f(or)g(k)m(eyw)m(ord)0 5102 y(name)33 b(con)m(tains)h(a)f(space)h(or)f(a)g(c)m(haracter)h(whic)m(h)f(migh)m (t)h(app)s(ear)e(as)h(an)g(arithmetic)h(term)f(then)g(enclose)h(the)0 5215 y(name)c(in)g('$')i(c)m(haracters)g(as)e(in)g($MAX)i(PHA$)f(or)f (#$MAX-PHA$.)43 b(Names)31 b(are)f(case)i(insensitiv)m(e.)0 5375 y(T)-8 b(o)32 b(access)g(a)g(table)g(en)m(try)g(in)f(a)h(ro)m(w)f (other)h(than)f(the)g(curren)m(t)g(one,)h(follo)m(w)h(the)e(column's)h (name)f(with)g(a)h(ro)m(w)0 5488 y(o\013set)37 b(within)e(curly)g (braces.)57 b(F)-8 b(or)36 b(example,)i('PHA)p Fc(f)p Fj(-3)p Fc(g)p Fj(')g(will)e(ev)-5 b(aluate)38 b(to)e(the)g(v)-5 b(alue)36 b(of)g(column)f(PHA,)i(3)0 5601 y(ro)m(ws)28 b(ab)s(o)m(v)m(e)i(the)e(ro)m(w)h(curren)m(tly)f(b)s(eing)g(pro)s (cessed.)40 b(One)28 b(cannot)h(sp)s(ecify)f(an)g(absolute)h(ro)m(w)f (n)m(um)m(b)s(er,)g(only)h(a)0 5714 y(relativ)m(e)j(o\013set.)42 b(Ro)m(ws)31 b(that)g(fall)g(outside)g(the)f(table)h(will)g(b)s(e)f (treated)h(as)g(unde\014ned,)d(or)j(NULLs.)p eop end %%Page: 143 151 TeXDict begin 143 150 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.143) cvn H.B /DEST pdfmark end 0 299 a Fh(10.11.)73 b(R)m(O)m(W)31 b(FIL)-8 b(TERING)31 b(SPECIFICA)-8 b(TION)1936 b Fj(143)0 555 y(Bo)s(olean)32 b(op)s(erators)f(can)g(b)s(e)f(used)f(in)i(the)f (expression)h(in)f(either)h(their)g(F)-8 b(ortran)31 b(or)f(C)h(forms.)40 b(The)30 b(follo)m(wing)0 668 y(b)s(o)s(olean)g (op)s(erators)h(are)g(a)m(v)-5 b(ailable:)191 918 y Fe("equal")428 b(.eq.)46 b(.EQ.)h(==)95 b("not)46 b(equal")476 b(.ne.)94 b(.NE.)h(!=)191 1031 y("less)46 b(than")238 b(.lt.)46 b(.LT.)h(<)143 b("less)46 b(than/equal")188 b(.le.)94 b(.LE.)h(<=)47 b(=<)191 1144 y("greater)e(than")95 b(.gt.)46 b(.GT.)h(>)143 b("greater)45 b(than/equal")g(.ge.)94 b(.GE.)h(>=)47 b(=>)191 1257 y("or")572 b(.or.)46 b(.OR.)h(||)95 b("and")762 b(.and.)46 b(.AND.)h(&&)191 1370 y("negation")236 b(.not.)46 b(.NOT.)h(!)95 b("approx.)45 b(equal\(1e-7\)")92 b(~)0 1619 y Fj(Note)32 b(that)g(the)f(exclamation)i(p)s(oin)m(t,)e(') 10 b(!',)33 b(is)e(a)g(sp)s(ecial)g(UNIX)h(c)m(haracter,)h(so)e(if)g (it)g(is)g(used)f(on)h(the)g(command)0 1732 y(line)i(rather)f(than)h (en)m(tered)g(at)g(a)g(task)g(prompt,)g(it)g(m)m(ust)f(b)s(e)g (preceded)h(b)m(y)f(a)h(bac)m(kslash)g(to)h(force)f(the)g(UNIX)0 1845 y(shell)e(to)g(ignore)g(it.)0 2005 y(The)h(expression)g(ma)m(y)i (also)f(include)f(arithmetic)i(op)s(erators)f(and)f(functions.)47 b(T)-8 b(rigonometric)34 b(functions)e(use)0 2118 y(radians,)23 b(not)g(degrees.)38 b(The)22 b(follo)m(wing)h(arithmetic)g(op)s (erators)g(and)e(functions)g(can)i(b)s(e)e(used)g(in)h(the)g (expression)0 2231 y(\(function)38 b(names)f(are)h(case)g(insensitiv)m (e\).)64 b(A)37 b(n)m(ull)h(v)-5 b(alue)38 b(will)f(b)s(e)g(returned)g (in)g(case)h(of)g(illegal)i(op)s(erations)0 2344 y(suc)m(h)30 b(as)h(divide)f(b)m(y)g(zero,)i(sqrt\(negativ)m(e\))h(log\(negativ)m (e\),)h(log10\(negativ)m(e\),)i(arccos\(.gt.)43 b(1\),)32 b(arcsin\(.gt.)42 b(1\).)191 2594 y Fe("addition")474 b(+)j("subtraction")d(-)191 2707 y("multiplication")186 b(*)477 b("division")618 b(/)191 2820 y("negation")474 b(-)j("exponentiation")330 b(**)143 b(^)191 2933 y("absolute)45 b(value")189 b(abs\(x\))237 b("cosine")762 b(cos\(x\))191 3046 y("sine")666 b(sin\(x\))237 b("tangent")714 b(tan\(x\))191 3159 y("arc)47 b(cosine")379 b(arccos\(x\))93 b("arc)47 b(sine")667 b(arcsin\(x\))191 3271 y("arc)47 b(tangent")331 b(arctan\(x\))93 b("arc)47 b(tangent")523 b(arctan2\(y,x\))191 3384 y("hyperbolic)45 b(cos")189 b(cosh\(x\))g("hyperbolic)45 b(sin")381 b(sinh\(x\))191 3497 y("hyperbolic)45 b(tan")189 b(tanh\(x\))g("round)47 b(to)g(nearest)f(int")94 b(round\(x\))191 3610 y("round)46 b(down)h(to)g(int")f(floor\(x\))141 b("round)47 b(up)g(to)g(int")333 b(ceil\(x\))191 3723 y("exponential")d(exp\(x\))237 b("square)46 b(root")524 b(sqrt\(x\))191 3836 y("natural)45 b(log")333 b(log\(x\))237 b("common)46 b(log")572 b(log10\(x\))191 3949 y("modulus")522 b(x)48 b(\045)f(y)286 b("random)46 b(#)i([0.0,1.0\)")188 b(random\(\))191 4062 y("random)46 b(Gaussian")140 b(randomn\(\))93 b("random)46 b(Poisson")380 b(randomp\(x\))191 4175 y("minimum")522 b(min\(x,y\))141 b("maximum")714 b(max\(x,y\))191 4288 y("cumulative)45 b(sum")189 b(accum\(x\))141 b("sequential)45 b(difference")g(seqdiff\(x\))191 4401 y("if-then-else")282 b(b?x:y)191 4513 y("angular)45 b(separation")93 b (angsep\(ra1,dec1,ra2,de2\))41 b(\(all)47 b(in)g(degrees\))191 4626 y("substring")283 b(strmid\(s,p,n\))44 b("string)i(search")428 b(strstr\(s,r\))0 4876 y Fj(Three)30 b(di\013eren)m(t)h(random)f(n)m (um)m(b)s(er)f(functions)h(are)h(pro)m(vided:)41 b(random\(\),)30 b(with)h(no)f(argumen)m(ts,)h(pro)s(duces)f(a)0 4989 y(uniform)g(random)f(deviate)k(b)s(et)m(w)m(een)e(0)g(and)f(1;)i (randomn\(\),)e(also)i(with)e(no)h(argumen)m(ts,)g(pro)s(duces)f(a)h (normal)0 5102 y(\(Gaussian\))k(random)e(deviate)j(with)e(zero)h(mean)f (and)g(unit)f(standard)h(deviation;)j(randomp\(x\))d(pro)s(duces)f(a)0 5215 y(P)m(oisson)27 b(random)f(deviate)h(whose)f(exp)s(ected)h(n)m(um) m(b)s(er)e(of)h(coun)m(ts)h(is)g(X.)f(X)h(ma)m(y)g(b)s(e)e(an)m(y)i(p)s (ositiv)m(e)g(real)g(n)m(um)m(b)s(er)0 5328 y(of)k(exp)s(ected)f(coun)m (ts,)h(including)f(fractional)i(v)-5 b(alues,)31 b(but)f(the)g(return)g (v)-5 b(alue)31 b(is)f(an)g(in)m(teger.)0 5488 y(When)d(the)g(random)g (functions)f(are)i(used)e(in)h(a)h(v)m(ector)g(expression,)g(b)m(y)f (default)h(the)f(same)h(random)e(v)-5 b(alue)28 b(will)0 5601 y(b)s(e)g(used)f(when)h(ev)-5 b(aluating)30 b(eac)m(h)f(elemen)m (t)h(of)f(the)g(v)m(ector.)41 b(If)28 b(di\013eren)m(t)h(random)f(n)m (um)m(b)s(ers)f(are)i(desired,)f(then)0 5714 y(the)37 b(name)g(of)g(a)g(v)m(ector)i(column)e(should)e(b)s(e)i(supplied)e(as)i (the)h(single)f(argumen)m(t)g(to)h(the)f(random)f(function)p eop end %%Page: 144 152 TeXDict begin 144 151 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.144) cvn H.B /DEST pdfmark end 0 299 a Fj(144)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fj(\(e.g.,)31 b("\015ux)c(+)h(0.1)h(*)g(random\(\015ux\)",)f (where)g("\015ux')g(is)g(the)g(name)h(of)f(a)h(v)m(ector)h(column\).)40 b(This)27 b(will)i(create)h(a)0 668 y(v)m(ector)d(of)f(random)f(n)m(um) m(b)s(ers)f(that)i(will)g(b)s(e)f(used)f(in)i(sequence)g(when)e(ev)-5 b(aluating)27 b(eac)m(h)g(elemen)m(t)g(of)f(the)f(v)m(ector)0 781 y(expression.)0 941 y(An)31 b(alternate)i(syn)m(tax)f(for)f(the)g (min)g(and)g(max)g(functions)g(has)g(only)g(a)h(single)g(argumen)m(t)g (whic)m(h)f(should)f(b)s(e)h(a)0 1054 y(v)m(ector)g(v)-5 b(alue)30 b(\(see)g(b)s(elo)m(w\).)41 b(The)29 b(result)g(will)h(b)s(e) e(the)i(minim)m(um/maxim)m(um)f(elemen)m(t)h(con)m(tained)h(within)e (the)0 1167 y(v)m(ector.)0 1327 y(The)35 b(accum\(x\))i(function)f (forms)f(the)h(cum)m(ulativ)m(e)i(sum)d(of)h(x,)h(elemen)m(t)h(b)m(y)e (elemen)m(t.)58 b(V)-8 b(ector)38 b(columns)e(are)0 1440 y(supp)s(orted)h(simply)h(b)m(y)g(p)s(erforming)f(the)i(summation)g (pro)s(cess)f(through)f(all)j(the)f(v)-5 b(alues.)65 b(Null)39 b(v)-5 b(alues)39 b(are)0 1553 y(treated)30 b(as)f(0.)41 b(The)29 b(seqdi\013\(x\))h(function)e(forms)h(the)g (sequen)m(tial)i(di\013erence)e(of)h(x,)f(elemen)m(t)i(b)m(y)e(elemen)m (t.)41 b(The)0 1666 y(\014rst)36 b(v)-5 b(alue)38 b(of)f(seqdi\013)g (is)g(the)g(\014rst)g(v)-5 b(alue)37 b(of)g(x.)61 b(A)37 b(single)h(n)m(ull)f(v)-5 b(alue)38 b(in)e(x)h(causes)h(a)f(pair)g(of)g (n)m(ulls)g(in)g(the)0 1779 y(output.)55 b(The)35 b(seqdi\013)g(and)g (accum)g(functions)g(are)h(functional)f(in)m(v)m(erses,)j(i.e.,)g (seqdi\013\(accum\(x\)\))f(==)e(x)g(as)0 1892 y(long)c(as)g(no)f(n)m (ull)g(v)-5 b(alues)31 b(are)g(presen)m(t.)0 2052 y(In)36 b(the)h(if-then-else)i(expression,)f("b?x:y",)i(b)c(is)h(an)g(explicit) h(b)s(o)s(olean)f(v)-5 b(alue)37 b(or)g(expression.)61 b(There)36 b(is)h(no)0 2165 y(automatic)d(t)m(yp)s(e)e(con)m(v)m (ersion)h(from)e(n)m(umeric)h(to)g(b)s(o)s(olean)g(v)-5 b(alues,)33 b(so)f(one)g(needs)f(to)i(use)e("iV)-8 b(al!=0")35 b(instead)0 2278 y(of)30 b(merely)g("iV)-8 b(al")32 b(as)e(the)g(b)s(o) s(olean)g(argumen)m(t.)41 b(x)30 b(and)f(y)h(can)g(b)s(e)f(an)m(y)h (scalar)h(data)g(t)m(yp)s(e)f(\(including)f(string\).)0 2438 y(The)22 b(angsep)g(function)f(computes)i(the)f(angular)g (separation)h(in)e(degrees)i(b)s(et)m(w)m(een)g(2)f(celestial)j(p)s (ositions,)e(where)0 2551 y(the)36 b(\014rst)f(2)h(parameters)g(giv)m (e)h(the)f(RA-lik)m(e)i(and)d(Dec-lik)m(e)j(co)s(ordinates)f(\(in)f (decimal)g(degrees\))h(of)f(the)g(\014rst)0 2664 y(p)s(osition,)31 b(and)e(the)i(3rd)f(and)g(4th)g(parameters)h(giv)m(e)h(the)e(co)s (ordinates)i(of)e(the)h(second)f(p)s(osition.)0 2824 y(The)38 b(substring)f(function)i(strmid\(S,P)-8 b(,N\))39 b(extracts)g(a)g(substring)f(from)g(S,)g(starting)h(at)g(string)g(p)s (osition)f(P)-8 b(,)0 2937 y(with)33 b(a)h(substring)f(length)h(N.)g (The)f(\014rst)g(c)m(haracter)j(p)s(osition)d(in)h(S)f(is)h(lab)s(eled) g(as)g(1.)51 b(If)33 b(P)g(is)h(0,)h(or)f(refers)f(to)0 3050 y(a)i(p)s(osition)g(b)s(ey)m(ond)f(the)h(end)e(of)i(S,)g(then)f (the)h(extracted)h(substring)d(will)i(b)s(e)f(NULL.)h(S,)f(P)-8 b(,)36 b(and)e(N)g(ma)m(y)i(b)s(e)0 3163 y(functions)30 b(of)g(other)h(columns.)0 3323 y(The)39 b(string)h(searc)m(h)h (function)e(strstr\(S,R\))h(searc)m(hes)h(for)f(the)g(\014rst)f(o)s (ccurrence)h(of)g(the)g(substring)f(R)h(in)f(S.)0 3436 y(The)c(result)h(is)f(an)h(in)m(teger,)i(indicating)f(the)e(c)m (haracter)i(p)s(osition)f(of)g(the)g(\014rst)e(matc)m(h)j(\(where)e(1)h (is)g(the)g(\014rst)0 3548 y(c)m(haracter)c(p)s(osition)e(of)h(S\).)f (If)g(no)h(matc)m(h)g(is)f(found,)g(then)g(strstr\(\))g(returns)f(a)i (NULL)f(v)-5 b(alue.)0 3709 y(The)38 b(follo)m(wing)i(t)m(yp)s(e)f (casting)h(op)s(erators)f(are)g(a)m(v)-5 b(ailable,)44 b(where)38 b(the)h(inclosing)h(paren)m(theses)f(are)g(required)0 3822 y(and)30 b(tak)m(en)h(from)f(the)h(C)f(language)h(usage.)42 b(Also,)31 b(the)g(in)m(teger)g(to)h(real)f(casts)g(v)-5 b(alues)30 b(to)i(double)e(precision:)764 4085 y Fe("real)46 b(to)h(integer")189 b(\(int\))46 b(x)239 b(\(INT\))46 b(x)764 4198 y("integer)f(to)i(real")190 b(\(float\))46 b(i)143 b(\(FLOAT\))45 b(i)0 4462 y Fj(In)30 b(addition,)g(sev)m(eral)i (constan)m(ts)g(are)f(built)f(in)g(for)g(use)g(in)g(n)m(umerical)h (expressions:)382 4725 y Fe(#pi)667 b(3.1415...)284 b(#e)620 b(2.7182...)382 4838 y(#deg)f(#pi/180)380 b(#row)524 b(current)46 b(row)h(number)382 4951 y(#null)428 b(undefined)45 b(value)142 b(#snull)428 b(undefined)45 b(string)0 5215 y Fj(A)40 b(string)f(constan)m(t)i(m)m(ust)e(b)s(e)g(enclosed)h(in)g (quotes)g(as)f(in)h('Crab'.)67 b(The)39 b("n)m(ull")i(constan)m(ts)f (are)g(useful)f(for)0 5328 y(conditionally)g(setting)g(table)g(v)-5 b(alues)38 b(to)g(a)g(NULL,)g(or)g(unde\014ned,)f(v)-5 b(alue)39 b(\(eg.,)i("col1==-99)f(?)62 b(#NULL)38 b(:)0 5441 y(col1"\).)0 5601 y(There)27 b(is)g(also)i(a)e(function)g(for)h (testing)g(if)f(t)m(w)m(o)i(v)-5 b(alues)28 b(are)g(close)g(to)h(eac)m (h)f(other,)h(i.e.,)g(if)e(they)h(are)g("near")g(eac)m(h)0 5714 y(other)c(to)h(within)e(a)h(user)g(sp)s(eci\014ed)f(tolerance.)40 b(The)24 b(argumen)m(ts,)h(v)-5 b(alue)p 2502 5714 28 4 v 34 w(1)24 b(and)f(v)-5 b(alue)p 2979 5714 V 33 w(2)25 b(can)f(b)s(e)f(in)m(teger)i(or)f(real)p eop end %%Page: 145 153 TeXDict begin 145 152 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.145) cvn H.B /DEST pdfmark end 0 299 a Fh(10.11.)73 b(R)m(O)m(W)31 b(FIL)-8 b(TERING)31 b(SPECIFICA)-8 b(TION)1936 b Fj(145)0 555 y(and)32 b(represen)m(t)h(the)g(t)m(w)m(o)h(v)-5 b(alues)33 b(who's)f(pro)m(ximit)m(y)i(is)f(b)s(eing)f(tested)h(to)h(b) s(e)e(within)g(the)h(sp)s(eci\014ed)f(tolerance,)0 668 y(also)f(an)g(in)m(teger)g(or)g(real:)955 950 y Fe(near\(value_1,)44 b(value_2,)h(tolerance\))0 1232 y Fj(When)24 b(a)i(NULL,)e(or)h (unde\014ned,)f(v)-5 b(alue)25 b(is)g(encoun)m(tered)g(in)g(the)f(FITS) g(table,)j(the)e(expression)g(will)g(ev)-5 b(aluate)26 b(to)0 1345 y(NULL)31 b(unless)f(the)h(unde\014ned)e(v)-5 b(alue)31 b(is)g(not)g(actually)h(required)e(for)h(ev)-5 b(aluation,)33 b(e.g.)43 b("TR)m(UE)31 b(.or.)43 b(NULL")0 1458 y(ev)-5 b(aluates)32 b(to)f(TR)m(UE.)g(The)f(follo)m(wing)h(t)m(w) m(o)h(functions)e(allo)m(w)i(some)f(NULL)f(detection)i(and)e(handling:) 430 1740 y Fe("a)47 b(null)f(value?")667 b(ISNULL\(x\))430 1853 y("define)45 b(a)j(value)e(for)h(null")190 b(DEFNULL\(x,y\))0 2135 y Fj(The)36 b(former)h(returns)e(a)i(b)s(o)s(olean)g(v)-5 b(alue)37 b(of)g(TR)m(UE)g(if)g(the)g(argumen)m(t)g(x)g(is)g(NULL.)g (The)f(later)i("de\014nes")f(a)0 2248 y(v)-5 b(alue)35 b(to)g(b)s(e)e(substituted)h(for)g(NULL)g(v)-5 b(alues;)37 b(it)e(returns)e(the)h(v)-5 b(alue)35 b(of)f(x)g(if)g(x)h(is)f(not)g (NULL,)h(otherwise)f(it)0 2361 y(returns)29 b(the)i(v)-5 b(alue)31 b(of)f(y)-8 b(.)0 2532 y SDict begin H.S end 0 2532 a 0 2532 a SDict begin 13.6 H.A end 0 2532 a 0 2532 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.10.11.2) cvn H.B /DEST pdfmark end 0 2532 a 146 x Fd(10.11.2)113 b(Bit)36 b(Masks)0 2902 y Fj(Bit)g(masks)f(can)h(b)s(e)f(used)f(to)i(select)h (out)e(ro)m(ws)h(from)e(bit)i(columns)f(\(TF)m(ORMn)g(=)g(#X\))h(in)f (FITS)f(\014les.)55 b(T)-8 b(o)0 3015 y(represen)m(t)30 b(the)h(mask,)g(binary)-8 b(,)30 b(o)s(ctal,)i(and)e(hex)g(formats)g (are)h(allo)m(w)m(ed:)811 3297 y Fe(binary:)142 b (b0110xx1010000101xxxx00)o(01)811 3410 y(octal:)190 b(o720x1)46 b(->)h(\(b111010000xxx001\))811 3522 y(hex:)286 b(h0FxD)94 b(->)47 b(\(b00001111xxxx1101\))0 3804 y Fj(In)22 b(all)i(the)f (represen)m(tations,)j(an)c(x)h(or)g(X)g(is)g(allo)m(w)m(ed)i(in)d(the) h(mask)g(as)g(a)h(wild)e(card.)38 b(Note)25 b(that)e(the)g(x)g (represen)m(ts)0 3917 y(a)k(di\013eren)m(t)h(n)m(um)m(b)s(er)e(of)h (wild)f(card)h(bits)g(in)g(eac)m(h)h(represen)m(tation.)41 b(All)27 b(represen)m(tations)h(are)g(case)g(insensitiv)m(e.)0 4077 y(T)-8 b(o)28 b(construct)g(the)g(b)s(o)s(olean)f(expression)h (using)f(the)h(mask)f(as)h(the)g(b)s(o)s(olean)f(equal)h(op)s(erator)g (describ)s(ed)f(ab)s(o)m(v)m(e)0 4190 y(on)34 b(a)h(bit)g(table)h (column.)53 b(F)-8 b(or)35 b(example,)i(if)d(y)m(ou)h(had)f(a)h(7)g (bit)g(column)f(named)g(\015ags)h(in)f(a)h(FITS)f(table)i(and)0 4303 y(w)m(an)m(ted)31 b(all)g(ro)m(ws)g(ha)m(ving)g(the)f(bit)h (pattern)f(0010011,)k(the)c(selection)j(expression)d(w)m(ould)g(b)s(e:) 1336 4585 y Fe(flags)47 b(==)g(b0010011)191 4698 y(or)1336 4811 y(flags)g(.eq.)f(b10011)0 5093 y Fj(It)35 b(is)g(also)h(p)s (ossible)e(to)i(test)g(if)f(a)g(range)g(of)g(bits)g(is)g(less)g(than,)h (less)f(than)g(equal,)i(greater)f(than)e(and)h(greater)0 5206 y(than)30 b(equal)h(to)g(a)g(particular)g(b)s(o)s(olean)f(v)-5 b(alue:)1336 5488 y Fe(flags)47 b(<=)g(bxxx010xx)1336 5601 y(flags)g(.gt.)f(bxxx100xx)1336 5714 y(flags)h(.le.)f(b1xxxxxxx)p eop end %%Page: 146 154 TeXDict begin 146 153 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.146) cvn H.B /DEST pdfmark end 0 299 a Fj(146)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fj(Notice)32 b(the)f(use)f(of)h(the)f(x)g(bit)h(v)-5 b(alue)31 b(to)g(limit)g(the)f(range)h(of)g(bits)f(b)s(eing)g (compared.)0 715 y(It)i(is)h(not)f(necessary)h(to)g(sp)s(ecify)f(the)h (leading)g(\(most)g(signi\014can)m(t\))h(zero)f(\(0\))g(bits)f(in)g (the)h(mask,)g(as)g(sho)m(wn)e(in)0 828 y(the)g(second)f(expression)g (ab)s(o)m(v)m(e.)0 988 y(Bit)44 b(wise)f(AND,)h(OR)e(and)g(NOT)h(op)s (erations)g(are)g(also)h(p)s(ossible)e(on)h(t)m(w)m(o)h(or)f(more)g (bit)g(\014elds)f(using)h(the)0 1101 y('&'\(AND\),)35 b(')p Fc(j)p Fj('\(OR\),)g(and)e(the)h(')10 b(!'\(NOT\))34 b(op)s(erators.)51 b(All)34 b(of)f(these)h(op)s(erators)g(result)f(in)h (a)g(bit)f(\014eld)g(whic)m(h)0 1214 y(can)e(then)f(b)s(e)f(used)h (with)g(the)h(equal)g(op)s(erator.)41 b(F)-8 b(or)31 b(example:)1241 1484 y Fe(\(!flags\))45 b(==)j(b1101100)1241 1597 y(\(flags)e(&)h(b1000001\))f(==)h(bx000001)0 1867 y Fj(Bit)35 b(\014elds)f(can)g(b)s(e)f(app)s(ended)g(as)h(w)m(ell)h (using)f(the)g('+')g(op)s(erator.)53 b(Strings)33 b(can)i(b)s(e)e (concatenated)j(this)e(w)m(a)m(y)-8 b(,)0 1980 y(to)s(o.)0 2119 y SDict begin H.S end 0 2119 a 0 2119 a SDict begin 13.6 H.A end 0 2119 a 0 2119 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.10.11.3) cvn H.B /DEST pdfmark end 0 2119 a 164 x Fd(10.11.3)113 b(V)-9 b(ector)36 b(Columns)0 2504 y Fj(V)-8 b(ector)37 b(columns)e(can)h(also)g(b)s(e)f(used)f(in)h (building)g(the)g(expression.)56 b(No)36 b(sp)s(ecial)g(syn)m(tax)f(is) h(required)e(if)i(one)0 2617 y(w)m(an)m(ts)46 b(to)f(op)s(erate)h(on)f (all)h(elemen)m(ts)g(of)f(the)h(v)m(ector.)86 b(Simply)44 b(use)h(the)g(column)g(name)g(as)g(for)g(a)g(scalar)0 2730 y(column.)d(V)-8 b(ector)32 b(columns)f(can)g(b)s(e)f(freely)h(in) m(termixed)h(with)e(scalar)i(columns)e(or)h(constan)m(ts)h(in)f (virtually)g(all)0 2843 y(expressions.)40 b(The)29 b(result)g(will)g(b) s(e)g(of)g(the)g(same)h(dimension)e(as)i(the)f(v)m(ector.)42 b(Tw)m(o)29 b(v)m(ectors)i(in)e(an)g(expression,)0 2956 y(though,)h(need)g(to)i(ha)m(v)m(e)f(the)g(same)g(n)m(um)m(b)s(er)e(of) h(elemen)m(ts)i(and)e(ha)m(v)m(e)h(the)g(same)g(dimensions.)0 3116 y(Arithmetic)24 b(and)e(logical)k(op)s(erations)d(are)h(all)g(p)s (erformed)d(on)i(an)g(elemen)m(t)h(b)m(y)f(elemen)m(t)i(basis.)38 b(Comparing)23 b(t)m(w)m(o)0 3229 y(v)m(ector)32 b(columns,)e(eg)h ("COL1)f(==)g(COL2",)g(th)m(us)g(results)g(in)g(another)g(v)m(ector)i (of)e(b)s(o)s(olean)h(v)-5 b(alues)30 b(indicating)0 3342 y(whic)m(h)g(elemen)m(ts)i(of)e(the)h(t)m(w)m(o)h(v)m(ectors)f (are)g(equal.)0 3502 y(Eigh)m(t)g(functions)f(are)h(a)m(v)-5 b(ailable)33 b(that)e(op)s(erate)g(on)f(a)h(v)m(ector)h(and)d(return)h (a)g(scalar)i(result:)191 3772 y Fe("minimum")284 b(MIN\(V\))475 b("maximum")714 b(MAX\(V\))191 3885 y("average")284 b(AVERAGE\(V\))f ("median")762 b(MEDIAN\(V\))191 3998 y("summation")188 b(SUM\(V\))475 b("standard)46 b(deviation")188 b(STDDEV\(V\))191 4110 y("#)47 b(of)g(values")94 b(NELEM\(V\))379 b("#)48 b(of)f(non-null)e(values")94 b(NVALID\(V\))0 4380 y Fj(where)40 b(V)h(represen)m(ts)g(the)g(name)g(of)h(a)f(v)m(ector)h(column)f(or)g (a)h(man)m(ually)f(constructed)g(v)m(ector)i(using)d(curly)0 4493 y(brac)m(k)m(ets)27 b(as)f(describ)s(ed)e(b)s(elo)m(w.)39 b(The)25 b(\014rst)g(6)h(of)g(these)g(functions)f(ignore)h(an)m(y)g(n)m (ull)f(v)-5 b(alues)26 b(in)f(the)h(v)m(ector)h(when)0 4606 y(computing)k(the)f(result.)41 b(The)30 b(STDDEV\(\))h(function)g (computes)f(the)h(sample)g(standard)e(deviation,)j(i.e.)42 b(it)31 b(is)0 4719 y(prop)s(ortional)f(to)h(1/SQR)-8 b(T\(N-1\))32 b(instead)f(of)g(1/SQR)-8 b(T\(N\),)31 b(where)f(N)h(is)f(NV)-10 b(ALID\(V\).)0 4879 y(The)31 b(SUM)h(function)f(literally)j(sums)d(all)h(the)g(elemen)m(ts)h(in)f (x,)g(returning)f(a)h(scalar)h(v)-5 b(alue.)45 b(If)31 b(V)h(is)g(a)g(b)s(o)s(olean)0 4992 y(v)m(ector,)40 b(SUM)c(returns)f (the)h(n)m(um)m(b)s(er)f(of)i(TR)m(UE)f(elemen)m(ts.)60 b(The)36 b(NELEM)g(function)g(returns)f(the)h(n)m(um)m(b)s(er)0 5105 y(of)h(elemen)m(ts)g(in)g(v)m(ector)h(V)e(whereas)h(NV)-10 b(ALID)36 b(return)g(the)h(n)m(um)m(b)s(er)e(of)h(non-n)m(ull)g(elemen) m(ts)i(in)e(the)h(v)m(ector.)0 5218 y(\(NELEM)28 b(also)h(op)s(erates)f (on)g(bit)f(and)g(string)h(columns,)g(returning)f(their)h(column)f (widths.\))40 b(As)27 b(an)h(example,)0 5331 y(to)42 b(test)g(whether)f(all)h(elemen)m(ts)h(of)f(t)m(w)m(o)g(v)m(ectors)h (satisfy)f(a)g(giv)m(en)g(logical)i(comparison,)g(one)e(can)g(use)f (the)0 5444 y(expression)668 5714 y Fe(SUM\()47 b(COL1)f(>)i(COL2)f(\)) g(==)g(NELEM\()f(COL1)h(\))p eop end %%Page: 147 155 TeXDict begin 147 154 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.147) cvn H.B /DEST pdfmark end 0 299 a Fh(10.11.)73 b(R)m(O)m(W)31 b(FIL)-8 b(TERING)31 b(SPECIFICA)-8 b(TION)1936 b Fj(147)0 555 y(whic)m(h)32 b(will)g(return)f(TR)m(UE)h(if)g(all)h(elemen)m(ts)g (of)f(COL1)g(are)g(greater)h(than)f(their)g(corresp)s(onding)f(elemen)m (ts)i(in)0 668 y(COL2.)0 828 y(T)-8 b(o)32 b(sp)s(ecify)f(a)i(single)f (elemen)m(t)h(of)f(a)g(v)m(ector,)i(giv)m(e)f(the)f(column)f(name)h (follo)m(w)m(ed)h(b)m(y)f(a)g(comma-separated)h(list)0 941 y(of)c(co)s(ordinates)g(enclosed)h(in)e(square)h(brac)m(k)m(ets.)41 b(F)-8 b(or)30 b(example,)g(if)e(a)h(v)m(ector)i(column)d(named)h(PHAS) f(exists)h(in)0 1054 y(the)e(table)g(as)g(a)g(one)g(dimensional,)h(256) g(comp)s(onen)m(t)f(list)g(of)g(n)m(um)m(b)s(ers)e(from)h(whic)m(h)h(y) m(ou)g(w)m(an)m(ted)g(to)g(select)i(the)0 1167 y(57th)j(comp)s(onen)m (t)g(for)f(use)g(in)g(the)h(expression,)f(then)h(PHAS[57])g(w)m(ould)f (do)h(the)f(tric)m(k.)45 b(Higher)32 b(dimensional)0 1280 y(arra)m(ys)41 b(of)h(data)f(ma)m(y)h(app)s(ear)f(in)f(a)i (column.)73 b(But)41 b(in)g(order)f(to)i(in)m(terpret)f(them,)j(the)e (TDIMn)e(k)m(eyw)m(ord)0 1393 y(m)m(ust)34 b(app)s(ear)g(in)g(the)g (header.)52 b(Assuming)34 b(that)h(a)f(\(4,4,4,4\))k(arra)m(y)c(is)h (pac)m(k)m(ed)g(in)m(to)g(eac)m(h)h(ro)m(w)e(of)g(a)h(column)0 1506 y(named)26 b(ARRA)-8 b(Y4D,)28 b(the)f(\(1,2,3,4\))i(comp)s(onen)m (t)e(elemen)m(t)g(of)g(eac)m(h)g(ro)m(w)g(is)f(accessed)i(b)m(y)e(ARRA) -8 b(Y4D[1,2,3,4].)0 1619 y(Arra)m(ys)33 b(up)e(to)j(dimension)e(5)h (are)f(curren)m(tly)h(supp)s(orted.)46 b(Eac)m(h)33 b(v)m(ector)h (index)e(can)h(itself)g(b)s(e)f(an)h(expression,)0 1732 y(although)39 b(it)g(m)m(ust)g(ev)-5 b(aluate)40 b(to)f(an)g(in)m (teger)h(v)-5 b(alue)39 b(within)f(the)h(b)s(ounds)d(of)j(the)g(v)m (ector.)67 b(V)-8 b(ector)40 b(columns)0 1844 y(whic)m(h)31 b(con)m(tain)h(spaces)g(or)f(arithmetic)h(op)s(erators)g(m)m(ust)f(ha)m (v)m(e)h(their)f(names)g(enclosed)h(in)f("$")h(c)m(haracters)h(as)0 1957 y(with)d($ARRA)-8 b(Y-4D$[1,2,3,4].)0 2118 y(A)45 b(more)f(C-lik)m(e)i(syn)m(tax)g(for)e(sp)s(ecifying)g(v)m(ector)j (indices)d(is)h(also)h(a)m(v)-5 b(ailable.)85 b(The)45 b(elemen)m(t)h(used)d(in)i(the)0 2230 y(preceding)28 b(example)h(alternativ)m(ely)i(could)d(b)s(e)g(sp)s(eci\014ed)g(with)f (the)i(syn)m(tax)g(ARRA)-8 b(Y4D[4][3][2][1].)45 b(Note)30 b(the)0 2343 y(rev)m(erse)40 b(order)f(of)h(indices)f(\(as)h(in)f(C\),) h(as)f(w)m(ell)i(as)e(the)h(fact)g(that)g(the)g(v)-5 b(alues)40 b(are)f(still)i(ones-based)e(\(as)h(in)0 2456 y(F)-8 b(ortran)39 b({)g(adopted)g(to)g(a)m(v)m(oid)h(am)m(biguit)m(y)g (for)f(1D)g(v)m(ectors\).)67 b(With)39 b(this)g(syn)m(tax,)i(one)e(do)s (es)f(not)h(need)f(to)0 2569 y(sp)s(ecify)30 b(all)h(of)g(the)f (indices.)41 b(T)-8 b(o)31 b(extract)h(a)f(3D)g(slice)g(of)g(this)f(4D) h(arra)m(y)-8 b(,)32 b(use)e(ARRA)-8 b(Y4D[4].)0 2729 y(V)g(ariable-length)33 b(v)m(ector)f(columns)e(are)g(not)h(supp)s (orted.)0 2889 y(V)-8 b(ectors)24 b(can)e(b)s(e)f(man)m(ually)h (constructed)h(within)e(the)h(expression)g(using)f(a)h(comma-separated) i(list)f(of)f(elemen)m(ts)0 3002 y(surrounded)35 b(b)m(y)j(curly)g (braces)h(\(')p Fc(fg)p Fj('\).)66 b(F)-8 b(or)38 b(example,)j(')p Fc(f)p Fj(1,3,6,1)p Fc(g)p Fj(')h(is)d(a)f(4-elemen)m(t)i(v)m(ector)g (con)m(taining)g(the)0 3115 y(v)-5 b(alues)26 b(1,)h(3,)g(6,)g(and)e (1.)40 b(The)25 b(v)m(ector)i(can)f(con)m(tain)h(only)f(b)s(o)s(olean,) g(in)m(teger,)j(and)c(real)h(v)-5 b(alues)26 b(\(or)g(expressions\).)0 3228 y(The)c(elemen)m(ts)i(will)f(b)s(e)f(promoted)h(to)g(the)g (highest)g(data)g(t)m(yp)s(e)g(presen)m(t.)38 b(An)m(y)22 b(elemen)m(ts)i(whic)m(h)f(are)g(themselv)m(es)0 3341 y(v)m(ectors,)40 b(will)d(b)s(e)f(expanded)g(out)h(with)g(eac)m(h)g(of) g(its)g(elemen)m(ts)i(b)s(ecoming)d(an)h(elemen)m(t)h(in)f(the)g (constructed)0 3454 y(v)m(ector.)0 3580 y SDict begin H.S end 0 3580 a 0 3580 a SDict begin 13.6 H.A end 0 3580 a 0 3580 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.10.11.4) cvn H.B /DEST pdfmark end 0 3580 a 164 x Fd(10.11.4)113 b(Go)s(o)s(d)38 b(Time)g(In)m(terv)-6 b(al)37 b(Filtering)0 3963 y Fj(A)44 b(common)g(\014ltering)h(metho)s(d)e(in)m(v)m(olv)m(es)j (selecting)g(ro)m(ws)e(whic)m(h)f(ha)m(v)m(e)j(a)e(time)h(v)-5 b(alue)44 b(whic)m(h)g(lies)g(within)0 4076 y(what)37 b(is)g(called)i(a)f(Go)s(o)s(d)f(Time)g(In)m(terv)-5 b(al)38 b(or)f(GTI.)g(The)g(time)h(in)m(terv)-5 b(als)38 b(are)g(de\014ned)e(in)h(a)g(separate)i(FITS)0 4189 y(table)i (extension)g(whic)m(h)e(con)m(tains)i(2)g(columns)f(giving)g(the)h (start)f(and)g(stop)g(time)g(of)g(eac)m(h)i(go)s(o)s(d)e(in)m(terv)-5 b(al.)0 4301 y(The)34 b(\014ltering)h(op)s(eration)h(accepts)g(only)e (those)i(ro)m(ws)e(of)h(the)g(input)f(table)i(whic)m(h)e(ha)m(v)m(e)i (an)f(asso)s(ciated)h(time)0 4414 y(whic)m(h)f(falls)i(within)e(one)h (of)g(the)g(time)g(in)m(terv)-5 b(als)37 b(de\014ned)e(in)g(the)h(GTI)g (extension.)57 b(A)36 b(high)g(lev)m(el)h(function,)0 4527 y(gti\014lter\(a,b,c,d\),)44 b(is)c(a)m(v)-5 b(ailable)42 b(whic)m(h)d(ev)-5 b(aluates)41 b(eac)m(h)g(ro)m(w)e(of)h(the)f(input)g (table)h(and)f(returns)f(TR)m(UE)i(or)0 4640 y(F)-10 b(ALSE)30 b(dep)s(ending)f(whether)h(the)g(ro)m(w)h(is)f(inside)g(or)g (outside)h(the)g(go)s(o)s(d)f(time)h(in)m(terv)-5 b(al.)42 b(The)30 b(syn)m(tax)h(is)286 4895 y Fe(gtifilter\()45 b([)j("gtifile")d([,)i(expr)g([,)g("STARTCOL",)e("STOPCOL")g(])j(])f(]) g(\))191 5008 y(or)286 5121 y(gtifilter\()e([)j('gtifile')d([,)i(expr)g ([,)g('STARTCOL',)e('STOPCOL')g(])j(])f(])g(\))0 5375 y Fj(where)20 b(eac)m(h)h("[]")h(demarks)e(optional)h(parameters.)38 b(Note)21 b(that)g(the)g(quotes)f(around)g(the)g(gti\014le)i(and)d(ST) -8 b(AR)g(T/STOP)0 5488 y(column)33 b(are)h(required.)50 b(Either)34 b(single)g(or)g(double)f(quotes)h(ma)m(y)g(b)s(e)f(used.)50 b(In)33 b(cases)h(where)g(this)f(expression)0 5601 y(is)d(en)m(tered)g (on)g(the)g(Unix)g(command)g(line,)g(enclose)h(the)f(en)m(tire)h (expression)f(in)f(double)h(quotes,)g(and)g(then)f(use)0 5714 y(single)c(quotes)g(within)e(the)i(expression)f(to)h(enclose)g (the)g('gti\014le')h(and)d(other)i(terms.)38 b(It)25 b(is)f(also)h(usually)f(p)s(ossible)p eop end %%Page: 148 156 TeXDict begin 148 155 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.148) cvn H.B /DEST pdfmark end 0 299 a Fj(148)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fj(to)38 b(do)e(the)h(rev)m(erse,)j(and)c(enclose)i(the)f(whole)g (expression)g(in)f(single)i(quotes)f(and)f(then)h(use)f(double)g (quotes)0 668 y(within)d(the)g(expression.)50 b(The)33 b(gti\014le,)i(if)f(sp)s(eci\014ed,)f(can)h(b)s(e)f(blank)g(\(""\))i (whic)m(h)e(will)g(mean)h(to)g(use)f(the)h(\014rst)0 781 y(extension)g(with)g(the)f(name)h("*GTI*")h(in)f(the)f(curren)m(t)h (\014le,)h(a)f(plain)f(extension)h(sp)s(eci\014er)f(\(eg,)j("+2",)g ("[2]",)0 894 y(or)30 b("[STDGTI]"\))i(whic)m(h)e(will)h(b)s(e)f(used)f (to)j(select)g(an)e(extension)h(in)f(the)h(curren)m(t)f(\014le,)h(or)f (a)h(regular)g(\014lename)0 1007 y(with)f(or)h(without)f(an)h (extension)g(sp)s(eci\014er)f(whic)m(h)g(in)g(the)h(latter)h(case)f (will)g(mean)f(to)i(use)e(the)h(\014rst)e(extension)0 1120 y(with)37 b(an)g(extension)g(name)h("*GTI*".)62 b(Expr)36 b(can)h(b)s(e)g(an)m(y)g(arithmetic)i(expression,)f (including)f(simply)g(the)0 1233 y(time)f(column)g(name.)57 b(A)36 b(v)m(ector)h(time)g(expression)e(will)h(pro)s(duce)f(a)h(v)m (ector)h(b)s(o)s(olean)f(result.)57 b(ST)-8 b(AR)g(TCOL)0 1346 y(and)27 b(STOPCOL)f(are)i(the)g(names)g(of)g(the)g(ST)-8 b(AR)g(T/STOP)26 b(columns)i(in)f(the)h(GTI)g(extension.)41 b(If)27 b(one)h(of)g(them)0 1458 y(is)i(sp)s(eci\014ed,)g(they)h(b)s (oth)f(m)m(ust)g(b)s(e.)0 1619 y(In)21 b(its)h(simplest)g(form,)i(no)d (parameters)h(need)g(to)h(b)s(e)e(pro)m(vided)g({)h(default)g(v)-5 b(alues)22 b(will)h(b)s(e)e(used.)37 b(The)21 b(expression)0 1732 y("gti\014lter\(\)")33 b(is)e(equiv)-5 b(alen)m(t)31 b(to)334 1988 y Fe(gtifilter\()45 b("",)i(TIME,)f("*START*",)f ("*STOP*")h(\))0 2244 y Fj(This)31 b(will)g(searc)m(h)h(the)g(curren)m (t)f(\014le)g(for)g(a)h(GTI)f(extension,)h(\014lter)g(the)f(TIME)g (column)g(in)g(the)h(curren)m(t)f(table,)0 2357 y(using)j(ST)-8 b(AR)g(T/STOP)34 b(times)i(tak)m(en)f(from)g(columns)f(in)h(the)g(GTI)g (extension)g(with)g(names)f(con)m(taining)j(the)0 2470 y(strings)32 b("ST)-8 b(AR)g(T")33 b(and)e("STOP".)46 b(The)32 b(wildcards)f(\('*'\))j(allo)m(w)g(sligh)m(t)f(v)-5 b(ariations)33 b(in)f(naming)g(con)m(v)m(en)m(tions)0 2583 y(suc)m(h)38 b(as)g("TST)-8 b(AR)g(T")39 b(or)f("ST)-8 b(AR)g(TTIME".)65 b(The)37 b(same)i(default)g(v)-5 b(alues)38 b(apply)g(for)g(unsp)s(eci\014ed)f(parame-)0 2696 y(ters)f(when)f(the)h (\014rst)f(one)i(or)f(t)m(w)m(o)h(parameters)f(are)h(sp)s(eci\014ed.)56 b(The)36 b(function)f(automatically)k(searc)m(hes)e(for)0 2808 y(TIMEZER)m(O/I/F)g(k)m(eyw)m(ords)f(in)g(the)h(curren)m(t)f(and)g (GTI)g(extensions,)i(applying)f(a)f(relativ)m(e)j(time)e(o\013set,)i (if)0 2921 y(necessary)-8 b(.)0 3066 y SDict begin H.S end 0 3066 a 0 3066 a SDict begin 13.6 H.A end 0 3066 a 0 3066 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.10.11.5) cvn H.B /DEST pdfmark end 0 3066 a 145 x Fd(10.11.5)113 b(Spatial)38 b(Region)g(Filtering)0 3430 y Fj(Another)g(common)g(\014ltering)g (metho)s(d)f(selects)i(ro)m(ws)f(based)g(on)f(whether)h(the)g(spatial)h (p)s(osition)e(asso)s(ciated)0 3543 y(with)32 b(eac)m(h)i(ro)m(w)e(is)h (lo)s(cated)h(within)e(a)h(giv)m(en)g(2-dimensional)g(region.)48 b(The)32 b(syn)m(tax)h(for)f(this)h(high-lev)m(el)h(\014lter)0 3656 y(is)334 3912 y Fe(regfilter\()45 b("regfilename")f([)k(,)f (Xexpr,)f(Yexpr)h([)g(,)h("wcs)e(cols")h(])g(])g(\))0 4168 y Fj(where)22 b(eac)m(h)i("[]")g(demarks)e(optional)i(parameters.) 38 b(The)22 b(region)h(\014le)g(name)f(is)h(required)f(and)g(m)m(ust)g (b)s(e)g(enclosed)0 4281 y(in)34 b(quotes.)51 b(The)33 b(remaining)h(parameters)h(are)f(optional.)52 b(There)33 b(are)i(2)f(supp)s(orted)e(formats)i(for)f(the)h(region)0 4394 y(\014le:)62 b(ASCI)s(I)39 b(\014le)h(or)h(FITS)f(binary)g(table.) 73 b(The)40 b(region)h(\014le)g(con)m(tains)h(a)f(list)g(of)g(one)g(or) g(more)g(geometric)0 4507 y(shap)s(es)30 b(\(circle,)j(ellipse,)g(b)s (o)m(x,)e(etc.\))44 b(whic)m(h)31 b(de\014nes)f(a)i(region)g(on)f(the)g (celestial)j(sphere)c(or)h(an)g(area)h(within)f(a)0 4620 y(particular)36 b(2D)g(image.)57 b(The)35 b(region)h(\014le)f(is)g(t)m (ypically)j(generated)e(using)f(an)g(image)i(displa)m(y)e(program)g (suc)m(h)0 4733 y(as)e(fv/PO)m(W)g(\(distribute)f(b)m(y)h(the)f(HEASAR) m(C\),)h(or)g(ds9)f(\(distributed)g(b)m(y)g(the)h(Smithsonian)f (Astroph)m(ysical)0 4846 y(Observ)-5 b(atory\).)69 b(Users)39 b(should)g(refer)g(to)h(the)g(do)s(cumen)m(tation)h(pro)m(vided)e(with) g(these)h(programs)f(for)h(more)0 4959 y(details)29 b(on)f(the)g(syn)m (tax)h(used)e(in)h(the)h(region)f(\014les.)40 b(The)28 b(FITS)f(region)i(\014le)f(format)h(is)f(de\014ned)f(in)h(a)g(do)s (cumen)m(t)0 5072 y(a)m(v)-5 b(ailable)33 b(from)d(the)g(FITS)g(Supp)s (ort)e(O\016ce)j(at)g(h)m(ttp://\014ts.gsfc.nasa.go)m(v/)k(registry/)c (region.h)m(tml)0 5232 y(In)21 b(its)h(simplest)g(form,)i(\(e.g.,)h (reg\014lter\("region.reg"\))h(\))c(the)g(co)s(ordinates)g(in)g(the)g (default)g('X')h(and)e('Y')h(columns)0 5345 y(will)43 b(b)s(e)g(used)f(to)i(determine)f(if)g(eac)m(h)h(ro)m(w)f(is)g(inside)g (or)g(outside)g(the)g(area)h(sp)s(eci\014ed)e(in)h(the)g(region)h (\014le.)0 5458 y(Alternate)32 b(p)s(osition)e(column)g(names,)h(or)f (expressions,)h(ma)m(y)g(b)s(e)e(en)m(tered)i(if)g(needed,)f(as)h(in) 382 5714 y Fe(regfilter\("region.reg",)41 b(XPOS,)47 b(YPOS\))p eop end %%Page: 149 157 TeXDict begin 149 156 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.149) cvn H.B /DEST pdfmark end 0 299 a Fh(10.11.)73 b(R)m(O)m(W)31 b(FIL)-8 b(TERING)31 b(SPECIFICA)-8 b(TION)1936 b Fj(149)0 555 y(Region)37 b(\014ltering)f(can)g(b)s(e)f(applied)g(most)h(unam)m (biguously)f(if)h(the)g(p)s(ositions)g(in)f(the)h(region)g(\014le)g (and)f(in)h(the)0 668 y(table)g(to)g(b)s(e)e(\014ltered)h(are)h(b)s (oth)e(giv)m(e)j(in)e(terms)g(of)g(absolute)h(celestial)i(co)s (ordinate)e(units.)54 b(In)35 b(this)g(case)h(the)0 781 y(lo)s(cations)26 b(and)d(sizes)i(of)g(the)f(geometric)i(shap)s(es)e (in)g(the)g(region)h(\014le)f(are)h(sp)s(eci\014ed)f(in)g(angular)g (units)g(on)g(the)g(sky)0 894 y(\(e.g.,)32 b(p)s(ositions)e(giv)m(en)i (in)e(R.A.)g(and)g(Dec.)42 b(and)30 b(sizes)h(in)f(arcseconds)g(or)h (arcmin)m(utes\).)41 b(Similarly)-8 b(,)31 b(eac)m(h)h(ro)m(w)0 1007 y(of)h(the)h(\014ltered)f(table)h(will)f(ha)m(v)m(e)i(a)e (celestial)j(co)s(ordinate)e(asso)s(ciated)g(with)f(it.)50 b(This)32 b(asso)s(ciation)j(is)e(usually)0 1120 y(implemen)m(ted)39 b(using)e(a)i(set)g(of)f(so-called)i('W)-8 b(orld)39 b(Co)s(ordinate)g(System')f(\(or)h(W)m(CS\))f(FITS)g(k)m(eyw)m(ords)g (that)0 1233 y(de\014ne)27 b(the)g(co)s(ordinate)h(transformation)g (that)g(m)m(ust)f(b)s(e)f(applied)h(to)h(the)g(v)-5 b(alues)27 b(in)g(the)h('X')g(and)e('Y')i(columns)0 1346 y(to)j(calculate)i(the)d (co)s(ordinate.)0 1506 y(Alternativ)m(ely)-8 b(,)30 b(one)d(can)g(p)s (erform)e(spatial)j(\014ltering)e(using)g(unitless)h('pixel')g(co)s (ordinates)h(for)e(the)h(regions)g(and)0 1619 y(ro)m(w)33 b(p)s(ositions.)49 b(In)33 b(this)g(case)h(the)f(user)g(m)m(ust)g(b)s (e)f(careful)h(to)h(ensure)f(that)g(the)h(p)s(ositions)f(in)g(the)g(2)g (\014les)h(are)0 1732 y(self-consisten)m(t.)54 b(A)34 b(t)m(ypical)i(problem)d(is)h(that)h(the)f(region)h(\014le)f(ma)m(y)h (b)s(e)e(generated)j(using)d(a)i(binned)d(image,)0 1844 y(but)g(the)h(un)m(binned)e(co)s(ordinates)i(are)g(giv)m(en)h(in)e(the) h(ev)m(en)m(t)i(table.)48 b(The)32 b(R)m(OSA)-8 b(T)33 b(ev)m(en)m(ts)h(\014les,)g(for)e(example,)0 1957 y(ha)m(v)m(e)f(X)f (and)f(Y)g(pixel)h(co)s(ordinates)g(that)h(range)f(from)f(1)h(-)g (15360.)42 b(These)30 b(co)s(ordinates)g(are)g(t)m(ypically)h(binned)0 2070 y(b)m(y)i(a)h(factor)g(of)f(32)h(to)g(pro)s(duce)e(a)i(480x480)i (pixel)d(image.)51 b(If)32 b(one)i(then)f(uses)g(a)g(region)h(\014le)f (generated)h(from)0 2183 y(this)c(image)i(\(in)f(image)g(pixel)g (units\))g(to)g(\014lter)f(the)h(R)m(OSA)-8 b(T)30 b(ev)m(en)m(ts)i (\014le,)f(then)f(the)h(X)g(and)f(Y)g(column)h(v)-5 b(alues)0 2296 y(m)m(ust)30 b(b)s(e)g(con)m(v)m(erted)i(to)f(corresp)s(onding)e (pixel)i(units)f(as)g(in:)382 2562 y Fe(regfilter\("rosat.reg",)42 b(X/32.+.5,)j(Y/32.+.5\))0 2829 y Fj(Note)h(that)f(this)f(binning)f (con)m(v)m(ersion)j(is)e(not)h(necessary)g(if)f(the)h(region)g(\014le)f (is)h(sp)s(eci\014ed)e(using)h(celestial)0 2942 y(co)s(ordinate)h (units)f(instead)g(of)g(pixel)h(units)f(b)s(ecause)g(CFITSIO)e(is)j (then)e(able)i(to)g(directly)g(compare)g(the)0 3054 y(celestial)30 b(co)s(ordinate)f(of)e(eac)m(h)i(ro)m(w)f(in)f(the)h(table)g(with)g (the)f(celestial)k(co)s(ordinates)d(in)f(the)h(region)g(\014le)g (without)0 3167 y(ha)m(ving)j(to)g(kno)m(w)f(an)m(ything)h(ab)s(out)f (ho)m(w)h(the)f(image)i(ma)m(y)f(ha)m(v)m(e)g(b)s(een)f(binned.)0 3328 y(The)f(last)h("w)m(cs)g(cols")h(parameter)f(should)e(rarely)h(b)s (e)g(needed.)40 b(If)29 b(supplied,)f(this)i(string)f(con)m(tains)i (the)e(names)0 3440 y(of)37 b(the)g(2)h(columns)f(\(space)h(or)f(comma) g(separated\))h(whic)m(h)f(ha)m(v)m(e)h(the)g(asso)s(ciated)g(W)m(CS)f (k)m(eyw)m(ords.)61 b(If)37 b(not)0 3553 y(supplied,)f(the)g(\014lter)g (will)h(scan)f(the)g(X)g(and)f(Y)h(expressions)g(for)g(column)f(names.) 58 b(If)35 b(only)h(one)h(is)f(found)e(in)0 3666 y(eac)m(h)e (expression,)e(those)h(columns)f(will)h(b)s(e)e(used,)h(otherwise)h(an) f(error)g(will)h(b)s(e)f(returned.)0 3826 y(These)g(region)h(shap)s(es) f(are)g(supp)s(orted)f(\(names)h(are)h(case)h(insensitiv)m(e\):)334 4093 y Fe(Point)428 b(\()48 b(X1,)f(Y1)g(\))715 b(<-)48 b(One)f(pixel)f(square)g(region)334 4206 y(Line)476 b(\()48 b(X1,)f(Y1,)g(X2,)f(Y2)i(\))333 b(<-)48 b(One)f(pixel)f(wide)h(region) 334 4319 y(Polygon)332 b(\()48 b(X1,)f(Y1,)g(X2,)f(Y2,)h(...)g(\))95 b(<-)48 b(Rest)e(are)h(interiors)e(with)334 4431 y(Rectangle)236 b(\()48 b(X1,)f(Y1,)g(X2,)f(Y2,)h(A)h(\))334 b(|)47 b(boundaries)e (considered)334 4544 y(Box)524 b(\()48 b(Xc,)f(Yc,)g(Wdth,)f(Hght,)g(A) i(\))143 b(V)47 b(within)f(the)h(region)334 4657 y(Diamond)332 b(\()48 b(Xc,)f(Yc,)g(Wdth,)f(Hght,)g(A)i(\))334 4770 y(Circle)380 b(\()48 b(Xc,)f(Yc,)g(R)g(\))334 4883 y(Annulus)332 b(\()48 b(Xc,)f(Yc,)g(Rin,)f(Rout)h(\))334 4996 y(Ellipse)332 b(\()48 b(Xc,)f(Yc,)g(Rx,)f(Ry,)h(A)h(\))334 5109 y(Elliptannulus)c(\() k(Xc,)f(Yc,)g(Rinx,)f(Riny,)g(Routx,)g(Routy,)g(Ain,)h(Aout)g(\))334 5222 y(Sector)380 b(\()48 b(Xc,)f(Yc,)g(Amin,)f(Amax)h(\))0 5488 y Fj(where)28 b(\(Xc,Yc\))j(is)d(the)h(co)s(ordinate)h(of)e(the)h (shap)s(e's)f(cen)m(ter;)j(\(X#,Y#\))e(are)g(the)g(co)s(ordinates)g(of) g(the)g(shap)s(e's)0 5601 y(edges;)39 b(Rxxx)c(are)g(the)h(shap)s(es')f (v)-5 b(arious)35 b(Radii)h(or)f(semima)5 b(jor/minor)36 b(axes;)i(and)d(Axxx)g(are)h(the)g(angles)g(of)0 5714 y(rotation)d(\(or)e(b)s(ounding)f(angles)i(for)f(Sector\))h(in)f (degrees.)44 b(F)-8 b(or)32 b(rotated)h(shap)s(es,)e(the)g(rotation)i (angle)f(can)g(b)s(e)p eop end %%Page: 150 158 TeXDict begin 150 157 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.150) cvn H.B /DEST pdfmark end 0 299 a Fj(150)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fj(left)32 b(o\013,)h(indicating)f(no)f(rotation.)46 b(Common)31 b(alternate)i(names)e(for)h(the)f(regions)h(can)g(also)h(b) s(e)d(used:)43 b(rotb)s(o)m(x)0 668 y(=)29 b(b)s(o)m(x;)g(rotrectangle) i(=)e(rectangle;)i(\(rot\)rhom)m(bus)e(=)f(\(rot\)diamond;)j(and)d(pie) h(=)f(sector.)42 b(When)28 b(a)i(shap)s(e's)0 781 y(name)e(is)g (preceded)f(b)m(y)h(a)g(min)m(us)g(sign,)g('-',)i(the)e(de\014ned)e (region)j(is)f(instead)g(the)g(area)h(*outside*)g(its)f(b)s(oundary)0 894 y(\(ie,)36 b(the)e(region)h(is)f(in)m(v)m(erted\).)53 b(All)34 b(the)g(shap)s(es)f(within)h(a)g(single)h(region)f(\014le)h (are)f(OR'd)f(together)j(to)e(create)0 1007 y(the)29 b(region,)i(and)d(the)i(order)f(is)g(signi\014can)m(t.)41 b(The)29 b(o)m(v)m(erall)i(w)m(a)m(y)g(of)e(lo)s(oking)h(at)g(region)g (\014les)f(is)g(that)h(if)f(the)h(\014rst)0 1120 y(region)f(is)g(an)g (excluded)g(region)g(then)f(a)i(dumm)m(y)d(included)h(region)i(of)f (the)g(whole)g(detector)h(is)f(inserted)f(in)h(the)0 1233 y(fron)m(t.)40 b(Then)25 b(eac)m(h)j(region)f(sp)s(eci\014cation)h (as)f(it)g(is)g(pro)s(cessed)f(o)m(v)m(errides)h(an)m(y)g(selections)i (inside)d(of)h(that)g(region)0 1346 y(sp)s(eci\014ed)36 b(b)m(y)g(previous)g(regions.)59 b(Another)37 b(w)m(a)m(y)g(of)g (thinking)f(ab)s(out)g(this)g(is)h(that)g(if)f(a)h(previous)f(excluded) 0 1458 y(region)31 b(is)f(completely)i(inside)f(of)f(a)h(subsequen)m(t) e(included)h(region)h(the)g(excluded)f(region)h(is)f(ignored.)0 1619 y(The)44 b(p)s(ositional)i(co)s(ordinates)g(ma)m(y)f(b)s(e)g(giv)m (en)h(either)f(in)g(pixel)g(units,)j(decimal)e(degrees)g(or)f (hh:mm:ss.s,)0 1732 y(dd:mm:ss.s)25 b(units.)38 b(The)26 b(shap)s(e)f(sizes)i(ma)m(y)f(b)s(e)g(giv)m(en)h(in)e(pixels,)j (degrees,)f(arcmin)m(utes,)h(or)e(arcseconds.)40 b(Lo)s(ok)0 1844 y(at)31 b(examples)g(of)f(region)h(\014le)g(pro)s(duced)d(b)m(y)i (fv/PO)m(W)h(or)g(ds9)f(for)g(further)f(details)i(of)g(the)f(region)h (\014le)f(format.)0 2005 y(There)h(are)g(three)h(lo)m(w-lev)m(el)i (functions)d(that)g(are)h(primarily)f(for)g(use)g(with)g(reg\014lter)g (function,)h(but)e(they)i(can)0 2118 y(b)s(e)j(called)i(directly)-8 b(.)59 b(They)35 b(return)g(a)h(b)s(o)s(olean)g(true)g(or)g(false)h (dep)s(ending)d(on)i(whether)f(a)i(t)m(w)m(o)g(dimensional)0 2230 y(p)s(oin)m(t)30 b(is)h(in)f(the)g(region)h(or)g(not.)41 b(The)30 b(p)s(ositional)h(co)s(ordinates)g(m)m(ust)f(b)s(e)g(giv)m(en) h(in)f(pixel)h(units:)191 2492 y Fe("point)46 b(in)h(a)h(circular)d (region")477 2605 y(circle\(xcntr,ycntr,radius)o(,Xco)o(lumn)o(,Yc)o (olum)o(n\))191 2831 y("point)h(in)h(an)g(elliptical)e(region")430 2944 y(ellipse\(xcntr,ycntr,xhl)o(f_w)o(dth,)o(yhlf)o(_wd)o(th,r)o (otat)o(ion)o(,Xco)o(lumn)o(,Yc)o(olum)o(n\))191 3169 y("point)h(in)h(a)h(rectangular)c(region")620 3282 y (box\(xcntr,ycntr,xfll_wdth,)o(yfll)o(_wd)o(th,r)o(otat)o(ion)o(,Xco)o (lumn)o(,Yc)o(olum)o(n\))191 3508 y(where)334 3621 y(\(xcntr,ycntr\))g (are)j(the)g(\(x,y\))f(position)g(of)h(the)g(center)f(of)h(the)g (region)334 3734 y(\(xhlf_wdth,yhlf_wdth\))42 b(are)47 b(the)g(\(x,y\))f(half)h(widths)f(of)h(the)g(region)334 3847 y(\(xfll_wdth,yfll_wdth\))42 b(are)47 b(the)g(\(x,y\))f(full)h (widths)f(of)h(the)g(region)334 3960 y(\(radius\))f(is)h(half)f(the)h (diameter)f(of)h(the)g(circle)334 4073 y(\(rotation\))e(is)i(the)g (angle\(degrees\))d(that)j(the)g(region)f(is)h(rotated)f(with)620 4186 y(respect)g(to)h(\(xcntr,ycntr\))334 4299 y(\(Xcoord,Ycoord\))d (are)j(the)g(\(x,y\))f(coordinates)f(to)i(test,)f(usually)g(column)620 4411 y(names)334 4524 y(NOTE:)g(each)h(parameter)e(can)i(itself)f(be)i (an)f(expression,)d(not)j(merely)f(a)620 4637 y(column)h(name)f(or)h (constant.)0 4767 y SDict begin H.S end 0 4767 a 0 4767 a SDict begin 13.6 H.A end 0 4767 a 0 4767 a SDict begin [ /View [/XYZ H.V] /Dest (subsection.10.11.6) cvn H.B /DEST pdfmark end 0 4767 a 163 x Fd(10.11.6)113 b(Example)38 b(Ro)m(w)f(Filters)191 5149 y Fe([)47 b(binary)f(&&)i(mag)f(<=)g(5.0])380 b(-)48 b(Extract)e(all)h(binary)f(stars)g(brighter)1766 5262 y(than)94 b(fifth)47 b(magnitude)e(\(note)h(that)1766 5375 y(the)h(initial)f(space)g(is)h(necessary)e(to)1766 5488 y(prevent)h(it)h(from)g(being)f(treated)g(as)h(a)1766 5601 y(binning)f(specification\))p eop end %%Page: 151 159 TeXDict begin 151 158 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.151) cvn H.B /DEST pdfmark end 0 299 a Fh(10.12.)113 b(BINNING)32 b(OR)e(HISTOGRAMMING)g(SPECIFICA)-8 b(TION)1223 b Fj(151)191 555 y Fe([#row)46 b(>=)h(125)g(&&)h(#row)e(<=)h(175])142 b(-)48 b(Extract)e(row)h(numbers)e(125)i(through)f(175)191 781 y([IMAGE[4,5])f(.gt.)h(100])476 b(-)48 b(Extract)e(all)h(rows)f (that)h(have)g(the)1766 894 y(\(4,5\))f(component)g(of)h(the)g(IMAGE)f (column)1766 1007 y(greater)g(than)g(100)191 1233 y([abs\(sin\(theta)e (*)j(#deg\)\))f(<)i(0.5])e(-)i(Extract)e(all)h(rows)f(having)g(the)1766 1346 y(absolute)f(value)i(of)g(the)g(sine)g(of)g(theta)1766 1458 y(less)94 b(than)47 b(a)g(half)g(where)f(the)h(angles)1766 1571 y(are)g(tabulated)e(in)i(degrees)191 1797 y([SUM\()f(SPEC)h(>)g (3*BACKGRND)e(\)>=1])94 b(-)48 b(Extract)e(all)h(rows)f(containing)f(a) 1766 1910 y(spectrum,)g(held)i(in)g(vector)f(column)1766 2023 y(SPEC,)g(with)h(at)g(least)f(one)h(value)g(3)1766 2136 y(times)f(greater)g(than)h(the)g(background)1766 2249 y(level)f(held)h(in)g(a)h(keyword,)d(BACKGRND)191 2475 y([VCOL=={1,4,2}])759 b(-)48 b(Extract)e(all)h(rows)f(whose)h (vector)f(column)1766 2588 y(VCOL)h(contains)e(the)i(3-elements)e(1,)i (4,)g(and)1766 2700 y(2.)191 2926 y([@rowFilter.txt])711 b(-)48 b(Extract)e(rows)g(using)h(the)g(expression)1766 3039 y(contained)e(within)h(the)h(text)g(file)1766 3152 y(rowFilter.txt)191 3378 y([gtifilter\(\)])855 b(-)48 b(Search)e(the)h(current)f(file)g(for)h(a)h(GTI)239 3491 y(extension,)92 b(filter)i(the)47 b(TIME)239 3604 y(column)f(in)h(the)g (current)f(table,)g(using)239 3717 y(START/STOP)f(times)h(taken)g(from) 239 3830 y(columns)f(in)j(the)f(GTI)94 b(extension)191 4055 y([regfilter\("pow.reg"\)])423 b(-)48 b(Extract)e(rows)g(which)h (have)f(a)i(coordinate)1766 4168 y(\(as)f(given)f(in)h(the)g(X)h(and)f (Y)g(columns\))1766 4281 y(within)f(the)h(spatial)f(region)g(specified) 1766 4394 y(in)h(the)g(pow.reg)f(region)g(file.)191 4620 y([regfilter\("pow.reg",)c(Xs,)47 b(Ys\)])f(-)i(Same)f(as)g(above,)f (except)g(that)h(the)1766 4733 y(Xs)g(and)g(Ys)g(columns)f(will)h(be)g (used)f(to)1766 4846 y(determine)f(the)i(coordinate)e(of)i(each)1766 4959 y(row)g(in)g(the)g(table.)0 5144 y SDict begin H.S end 0 5144 a 0 5144 a SDict begin 13.6 H.A end 0 5144 a 0 5144 a SDict begin [ /View [/XYZ H.V] /Dest (section.10.12) cvn H.B /DEST pdfmark end 0 5144 a 197 x Ff(10.12)181 b(Binning)44 b(or)h(Histogramming)i(Sp)t(eci\014cation)0 5601 y Fj(The)22 b(optional)i(binning)e(sp)s(eci\014er)g(is)h(enclosed)h(in)f(square)f (brac)m(k)m(ets)j(and)d(can)h(b)s(e)f(distinguished)g(from)h(a)g (general)0 5714 y(ro)m(w)32 b(\014lter)h(sp)s(eci\014cation)g(b)m(y)f (the)h(fact)g(that)g(it)g(b)s(egins)f(with)g(the)g(k)m(eyw)m(ord)h ('bin')f(not)h(immediately)g(follo)m(w)m(ed)p eop end %%Page: 152 160 TeXDict begin 152 159 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.152) cvn H.B /DEST pdfmark end 0 299 a Fj(152)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fj(b)m(y)41 b(an)f(equals)i(sign.)72 b(When)41 b(binning)e(is)i(sp)s(eci\014ed,)i(a)e(temp)s(orary)g(N-dimensional)g (FITS)f(primary)g(arra)m(y)0 668 y(is)j(created)h(b)m(y)f(computing)h (the)f(histogram)h(of)f(the)g(v)-5 b(alues)44 b(in)e(the)i(sp)s (eci\014ed)e(columns)h(of)g(a)h(FITS)e(table)0 781 y(extension.)f (After)30 b(the)f(histogram)h(is)g(computed)f(the)h(input)e(FITS)h (\014le)h(con)m(taining)h(the)e(table)i(is)e(then)g(closed)0 894 y(and)34 b(the)h(temp)s(orary)f(FITS)g(primary)g(arra)m(y)h(is)g (op)s(ened)f(and)g(passed)g(to)h(the)g(application)h(program.)54 b(Th)m(us,)0 1007 y(the)39 b(application)h(program)f(nev)m(er)g(sees)g (the)g(original)h(FITS)e(table)i(and)e(only)h(sees)h(the)f(image)h(in)e (the)h(new)0 1120 y(temp)s(orary)32 b(\014le)h(\(whic)m(h)g(has)f(no)h (additional)g(extensions\).)49 b(Ob)m(viously)-8 b(,)34 b(the)f(application)h(program)e(m)m(ust)h(b)s(e)0 1233 y(exp)s(ecting)e(to)g(op)s(en)f(a)h(FITS)e(image)j(and)e(not)g(a)h (FITS)f(table)h(in)f(this)g(case.)0 1393 y(The)g(data)h(t)m(yp)s(e)f (of)h(the)f(FITS)g(histogram)g(image)i(ma)m(y)f(b)s(e)f(sp)s(eci\014ed) f(b)m(y)h(app)s(ending)f('b')h(\(for)h(8-bit)g(b)m(yte\),)g('i')0 1506 y(\(for)g(16-bit)g(in)m(tegers\),)h('j')f(\(for)g(32-bit)g(in)m (teger\),)i('r')d(\(for)h(32-bit)g(\015oating)h(p)s(oin)m(ts\),)e(or)h ('d')f(\(for)h(64-bit)g(double)0 1619 y(precision)j(\015oating)i(p)s (oin)m(t\))e(to)h(the)g('bin')f(k)m(eyw)m(ord)h(\(e.g.)54 b('[binr)33 b(X]')i(creates)h(a)f(real)g(\015oating)g(p)s(oin)m(t)f (image\).)0 1732 y(If)g(the)i(data)f(t)m(yp)s(e)g(is)g(not)h (explicitly)g(sp)s(eci\014ed)e(then)h(a)g(32-bit)i(in)m(teger)f(image)g (will)f(b)s(e)g(created)h(b)m(y)e(default,)0 1844 y(unless)24 b(the)i(w)m(eigh)m(ting)g(option)g(is)f(also)h(sp)s(eci\014ed)e(in)h (whic)m(h)g(case)h(the)f(image)i(will)e(ha)m(v)m(e)h(a)g(32-bit)g (\015oating)g(p)s(oin)m(t)0 1957 y(data)31 b(t)m(yp)s(e)g(b)m(y)f (default.)0 2118 y(The)24 b(histogram)g(image)i(ma)m(y)f(ha)m(v)m(e)g (from)f(1)g(to)h(4)g(dimensions)e(\(axes\),)k(dep)s(ending)c(on)h(the)g (n)m(um)m(b)s(er)f(of)h(columns)0 2230 y(that)31 b(are)g(sp)s (eci\014ed.)40 b(The)30 b(general)h(form)f(of)g(the)h(binning)e(sp)s (eci\014cation)i(is:)48 2457 y Fe([bin{bijrd})92 b (Xcol=min:max:binsize,)42 b(Ycol=)47 b(...,)f(Zcol=...,)f(Tcol=...;)h (weight])0 2683 y Fj(in)39 b(whic)m(h)g(up)f(to)i(4)g(columns,)h(eac)m (h)f(corresp)s(onding)e(to)i(an)g(axis)f(of)h(the)f(image,)k(are)d (listed.)67 b(The)39 b(column)0 2796 y(names)27 b(are)h(case)h (insensitiv)m(e,)g(and)e(the)h(column)f(n)m(um)m(b)s(er)f(ma)m(y)i(b)s (e)f(giv)m(en)h(instead)g(of)g(the)g(name,)g(preceded)f(b)m(y)0 2909 y(a)32 b(p)s(ound)e(sign)i(\(e.g.,)i([bin)d(#4=1:512]\).)47 b(If)31 b(the)h(column)g(name)g(is)f(not)h(sp)s(eci\014ed,)g(then)f (CFITSIO)g(will)h(\014rst)0 3022 y(try)37 b(to)h(use)f(the)g ('preferred)f(column')i(as)f(sp)s(eci\014ed)g(b)m(y)g(the)g(CPREF)g(k)m (eyw)m(ord)h(if)f(it)g(exists)h(\(e.g.,)j('CPREF)0 3135 y(=)i('DETX,DETY'\),)h(otherwise)g(column)f(names)g('X',)h('Y',)g('Z',) f(and)f('T')i(will)f(b)s(e)f(assumed)h(for)g(eac)m(h)h(of)0 3247 y(the)37 b(4)h(axes,)i(resp)s(ectiv)m(ely)-8 b(.)62 b(In)37 b(cases)h(where)e(the)i(column)f(name)g(could)g(b)s(e)f (confused)h(with)g(an)g(arithmetic)0 3360 y(expression,)30 b(enclose)i(the)f(column)f(name)g(in)g(paren)m(theses)h(to)g(force)g (the)f(name)h(to)g(b)s(e)f(in)m(terpreted)g(literally)-8 b(.)0 3521 y(Eac)m(h)33 b(column)f(name)g(ma)m(y)h(b)s(e)f(follo)m(w)m (ed)h(b)m(y)g(an)f(equals)g(sign)h(and)e(then)h(the)g(lo)m(w)m(er)i (and)e(upp)s(er)e(range)i(of)h(the)0 3633 y(histogram,)f(and)e(the)h (size)h(of)f(the)g(histogram)h(bins,)e(separated)h(b)m(y)g(colons.)43 b(Spaces)31 b(are)g(allo)m(w)m(ed)i(b)s(efore)e(and)0 3746 y(after)e(the)g(equals)g(sign)f(but)g(not)h(within)f(the)h ('min:max:binsize')g(string.)40 b(The)29 b(min,)f(max)h(and)f(binsize)h (v)-5 b(alues)0 3859 y(ma)m(y)32 b(b)s(e)e(in)m(teger)i(or)f (\015oating)h(p)s(oin)m(t)f(n)m(um)m(b)s(ers,)f(or)h(they)g(ma)m(y)g(b) s(e)g(the)g(names)g(of)g(k)m(eyw)m(ords)g(in)g(the)g(header)g(of)0 3972 y(the)g(table.)41 b(If)30 b(the)h(latter,)h(then)e(the)g(v)-5 b(alue)31 b(of)g(that)g(k)m(eyw)m(ord)f(is)h(substituted)f(in)m(to)h (the)g(expression.)0 4132 y(Default)37 b(v)-5 b(alues)36 b(for)g(the)g(min,)h(max)f(and)g(binsize)g(quan)m(tities)h(will)f(b)s (e)f(used)h(if)f(not)i(explicitly)g(giv)m(en)g(in)f(the)0 4245 y(binning)29 b(expression)h(as)h(sho)m(wn)f(in)g(these)h (examples:)191 4471 y Fe([bin)47 b(x)g(=)g(:512:2])94 b(-)47 b(use)g(default)f(minimum)g(value)191 4584 y([bin)h(x)g(=)g (1::2])190 b(-)47 b(use)g(default)f(maximum)g(value)191 4697 y([bin)h(x)g(=)g(1:512])142 b(-)47 b(use)g(default)f(bin)h(size) 191 4810 y([bin)g(x)g(=)g(1:])286 b(-)47 b(use)g(default)f(maximum)g (value)g(and)h(bin)g(size)191 4923 y([bin)g(x)g(=)g(:512])190 b(-)47 b(use)g(default)f(minimum)g(value)g(and)h(bin)g(size)191 5036 y([bin)g(x)g(=)g(2])334 b(-)47 b(use)g(default)f(minimum)g(and)h (maximum)f(values)191 5149 y([bin)h(x])524 b(-)47 b(use)g(default)f (minimum,)g(maximum)g(and)g(bin)h(size)191 5262 y([bin)g(4])524 b(-)47 b(default)f(2-D)h(image,)f(bin)h(size)g(=)g(4)h(in)f(both)g (axes)191 5375 y([bin])619 b(-)47 b(default)f(2-D)h(image)0 5601 y Fj(CFITSIO)31 b(will)i(use)f(the)h(v)-5 b(alue)33 b(of)g(the)g(TLMINn,)f(TLMAXn,)h(and)f(TDBINn)h(k)m(eyw)m(ords,)h(if)e (they)h(exist,)h(for)0 5714 y(the)j(default)f(min,)i(max,)g(and)e (binsize,)i(resp)s(ectiv)m(ely)-8 b(.)61 b(If)36 b(they)h(do)f(not)h (exist)g(then)f(CFITSIO)f(will)i(use)f(the)p eop end %%Page: 153 161 TeXDict begin 153 160 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.153) cvn H.B /DEST pdfmark end 0 299 a Fh(10.12.)113 b(BINNING)32 b(OR)e(HISTOGRAMMING)g(SPECIFICA)-8 b(TION)1223 b Fj(153)0 555 y(actual)33 b(minim)m(um)e(and)h(maxim)m(um)g(v)-5 b(alues)32 b(in)g(the)g(column)f(for)h(the)g(histogram)h(min)e(and)h (max)g(v)-5 b(alues.)45 b(The)0 668 y(default)34 b(binsize)f(will)h(b)s (e)f(set)h(to)h(1,)g(or)e(\(max)h(-)g(min\))f(/)h(10.,)i(whic)m(hev)m (er)e(is)g(smaller,)h(so)e(that)i(the)e(histogram)0 781 y(will)e(ha)m(v)m(e)g(at)g(least)h(10)f(bins)f(along)h(eac)m(h)h(axis.) 0 941 y(A)41 b(shortcut)g(notation)h(is)f(allo)m(w)m(ed)i(if)e(all)h (the)f(columns/axes)h(ha)m(v)m(e)g(the)f(same)g(binning)f(sp)s (eci\014cation.)74 b(In)0 1054 y(this)33 b(case)g(all)h(the)f(column)f (names)h(ma)m(y)g(b)s(e)f(listed)h(within)f(paren)m(theses,)i(follo)m (w)m(ed)h(b)m(y)d(the)h(\(single\))h(binning)0 1167 y(sp)s (eci\014cation,)d(as)g(in:)191 1431 y Fe([bin)47 b(\(X,Y\)=1:512:2])191 1544 y([bin)g(\(X,Y\))f(=)h(5])0 1808 y Fj(The)31 b(optional)i(w)m (eigh)m(ting)h(factor)e(is)g(the)g(last)g(item)h(in)e(the)h(binning)f (sp)s(eci\014er)g(and,)h(if)f(presen)m(t,)i(is)e(separated)0 1921 y(from)38 b(the)g(list)h(of)f(columns)g(b)m(y)g(a)h(semi-colon.)65 b(As)39 b(the)f(histogram)h(is)f(accum)m(ulated,)k(this)c(w)m(eigh)m(t) i(is)e(used)0 2034 y(to)d(incremen)m(ted)f(the)g(v)-5 b(alue)35 b(of)f(the)g(appropriated)f(bin)h(in)f(the)h(histogram.)52 b(If)34 b(the)g(w)m(eigh)m(ting)i(factor)f(is)f(not)0 2147 y(sp)s(eci\014ed,)24 b(then)f(the)g(default)g(w)m(eigh)m(t)i(=)d (1)i(is)f(assumed.)37 b(The)23 b(w)m(eigh)m(ting)i(factor)f(ma)m(y)f(b) s(e)g(a)g(constan)m(t)i(in)m(teger)f(or)0 2260 y(\015oating)30 b(p)s(oin)m(t)f(n)m(um)m(b)s(er,)f(or)h(the)g(name)g(of)g(a)g(k)m(eyw)m (ord)h(con)m(taining)g(the)g(w)m(eigh)m(ting)g(v)-5 b(alue.)41 b(Or)28 b(the)h(w)m(eigh)m(ting)0 2372 y(factor)g(ma)m(y)g(b)s(e)e(the) h(name)g(of)h(a)f(table)h(column)f(in)g(whic)m(h)f(case)j(the)e(v)-5 b(alue)28 b(in)g(that)h(column,)f(on)g(a)h(ro)m(w)f(b)m(y)g(ro)m(w)0 2485 y(basis,)i(will)h(b)s(e)f(used.)0 2646 y(In)35 b(some)h(cases,)i (the)d(column)h(or)f(k)m(eyw)m(ord)h(ma)m(y)g(giv)m(e)h(the)f(recipro)s (cal)g(of)g(the)g(actual)h(w)m(eigh)m(t)g(v)-5 b(alue)36 b(that)g(is)0 2758 y(needed.)49 b(In)32 b(this)h(case,)i(precede)e(the) h(w)m(eigh)m(t)g(k)m(eyw)m(ord)g(or)f(column)g(name)g(b)m(y)g(a)g (slash)g('/')h(to)g(tell)g(CFITSIO)0 2871 y(to)d(use)f(the)h(recipro)s (cal)g(of)f(the)h(v)-5 b(alue)31 b(when)e(constructing)i(the)g (histogram.)0 3032 y(F)-8 b(or)25 b(complex)g(or)f(commonly)g(used)g (histograms,)i(one)e(can)h(also)g(place)g(its)f(description)g(in)m(to)h (a)g(text)g(\014le)f(and)g(im-)0 3144 y(p)s(ort)e(it)g(in)m(to)h(the)g (binning)e(sp)s(eci\014cation)i(using)e(the)i(syn)m(tax)f([bin)g (@\014lename.txt].)39 b(The)22 b(\014le's)g(con)m(ten)m(ts)i(can)e(ex-) 0 3257 y(tend)h(o)m(v)m(er)i(m)m(ultiple)f(lines,)h(although)f(it)g(m)m (ust)f(still)h(conform)f(to)h(the)g(no-spaces)g(rule)f(for)g(the)h (min:max:binsize)0 3370 y(syn)m(tax)35 b(and)f(eac)m(h)h(axis)g(sp)s (eci\014cation)h(m)m(ust)e(still)h(b)s(e)f(comma-separated.)55 b(An)m(y)34 b(lines)h(in)f(the)h(external)g(text)0 3483 y(\014le)27 b(that)g(b)s(egin)g(with)f(2)i(slash)e(c)m(haracters)j (\('//'\))g(will)e(b)s(e)f(ignored)h(and)f(ma)m(y)i(b)s(e)e(used)g(to)i (add)e(commen)m(ts)i(in)m(to)0 3596 y(the)j(\014le.)0 3756 y(Examples:)191 4020 y Fe([bini)46 b(detx,)h(dety])762 b(-)47 b(2-D,)g(16-bit)f(integer)g(histogram)1861 4133 y(of)i(DETX)e(and)h(DETY)g(columns,)e(using)1861 4246 y(default)h(values)g(for)h(the)g(histogram)1861 4359 y(range)g(and)g(binsize)191 4585 y([bin)g(\(detx,)f(dety\)=16;)f (/exposure])g(-)i(2-D,)g(32-bit)f(real)h(histogram)e(of)i(DETX)1861 4698 y(and)g(DETY)g(columns)f(with)g(a)i(bin)f(size)f(=)i(16)1861 4811 y(in)g(both)e(axes.)h(The)f(histogram)g(values)1861 4924 y(are)h(divided)f(by)h(the)g(EXPOSURE)f(keyword)1861 5036 y(value.)191 5262 y([bin)h(time=TSTART:TSTOP:0.1])280 b(-)47 b(1-D)g(lightcurve,)e(range)h(determined)f(by)1861 5375 y(the)i(TSTART)f(and)h(TSTOP)g(keywords,)1861 5488 y(with)g(0.1)g(unit)g(size)f(bins.)191 5714 y([bin)h(pha,)f (time=8000.:8100.:0.1])90 b(-)47 b(2-D)g(image)g(using)f(default)g (binning)p eop end %%Page: 154 162 TeXDict begin 154 161 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.154) cvn H.B /DEST pdfmark end 0 299 a Fj(154)1528 b Fh(CHAPTER)29 b(10.)113 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)1861 555 y Fe(of)48 b(the)e(PHA)h(column)f(for)h(the)g(X)h(axis,)1861 668 y(and)f(1000)g(bins)g(in)g(the)g(range)1861 781 y(8000.)g(to)g (8100.)f(for)h(the)g(Y)h(axis.)191 1007 y([bin)f(@binFilter.txt])616 b(-)47 b(Use)g(the)g(contents)f(of)h(the)g(text)f(file)1861 1120 y(binFilter.txt)f(for)h(the)h(binning)1861 1233 y(specifications.)p eop end %%Page: 155 163 TeXDict begin 155 162 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.155) cvn H.B /DEST pdfmark end 0 299 a 0 464 a SDict begin H.S end 0 464 a 0 464 a SDict begin 13.6 H.A end 0 464 a 0 464 a SDict begin [ /View [/XYZ H.V] /Dest (chapter.11) cvn H.B /DEST pdfmark end 0 464 a 761 x Fg(Chapter)65 b(11)0 1687 y Fm(T)-19 b(emplate)76 b(Files)0 2180 y Fj(When)38 b(a)h(new)f(FITS)g(\014le)h(is)g(created)g(with)g(a)f(call)i(to)g (\014ts)p 2101 2180 28 4 v 32 w(create)p 2369 2180 V 35 w(\014le,)g(the)f(name)g(of)g(a)g(template)h(\014le)e(ma)m(y)0 2293 y(b)s(e)h(supplied)g(in)h(paren)m(theses)g(immediately)h(follo)m (wing)g(the)g(name)f(of)g(the)g(new)f(\014le)h(to)h(b)s(e)e(created.)71 b(This)0 2406 y(template)27 b(is)e(used)g(to)h(de\014ne)f(the)h (structure)f(of)h(one)f(or)h(more)g(HDUs)g(in)f(the)h(new)f(\014le.)39 b(The)25 b(template)i(\014le)e(ma)m(y)0 2518 y(b)s(e)32 b(another)h(FITS)f(\014le,)i(in)f(whic)m(h)f(case)i(the)f(newly)g (created)h(\014le)f(will)g(ha)m(v)m(e)h(exactly)h(the)e(same)g(k)m(eyw) m(ords)g(in)0 2631 y(eac)m(h)25 b(HDU)g(as)g(in)f(the)g(template)i (FITS)d(\014le,)j(but)d(all)j(the)e(data)h(units)e(will)i(b)s(e)f (\014lled)g(with)f(zeros.)40 b(The)24 b(template)0 2744 y(\014le)i(ma)m(y)h(also)g(b)s(e)e(an)h(ASCI)s(I)e(text)j(\014le,)g (where)f(eac)m(h)h(line)f(\(in)g(general\))i(describ)s(es)d(one)h(FITS) f(k)m(eyw)m(ord)i(record.)0 2857 y(The)j(format)h(of)f(the)h(ASCI)s(I)e (template)i(\014le)g(is)f(describ)s(ed)f(in)i(the)f(follo)m(wing)i (sections.)0 3009 y SDict begin H.S end 0 3009 a 0 3009 a SDict begin 13.6 H.A end 0 3009 a 0 3009 a SDict begin [ /View [/XYZ H.V] /Dest (section.11.1) cvn H.B /DEST pdfmark end 0 3009 a 179 x Ff(11.1)136 b(Detailed)46 b(T)-11 b(emplate)46 b(Line)f(F)-11 b(ormat)0 3438 y Fj(The)30 b(format)h(of)f(eac)m(h)i (ASCI)s(I)c(template)k(line)f(closely)h(follo)m(ws)f(the)g(format)g(of) f(a)h(FITS)f(k)m(eyw)m(ord)g(record:)95 3682 y Fe(KEYWORD)46 b(=)i(KEYVALUE)d(/)j(COMMENT)0 3926 y Fj(except)22 b(that)g(free)g (format)f(ma)m(y)h(b)s(e)f(used)f(\(e.g.,)25 b(the)d(equals)f(sign)h (ma)m(y)f(app)s(ear)g(at)h(an)m(y)g(p)s(osition)f(in)g(the)h(line\))g (and)0 4039 y(T)-8 b(AB)34 b(c)m(haracters)g(are)g(allo)m(w)m(ed)h(and) e(are)g(treated)h(the)g(same)f(as)h(space)f(c)m(haracters.)51 b(The)33 b(KEYV)-10 b(ALUE)33 b(and)0 4152 y(COMMENT)d(\014elds)g(are)h (optional.)43 b(The)30 b(equals)h(sign)f(c)m(haracter)j(is)d(also)i (optional,)g(but)e(it)h(is)f(recommended)0 4264 y(that)42 b(it)f(b)s(e)g(included)f(for)h(clarit)m(y)-8 b(.)75 b(An)m(y)41 b(template)i(line)e(that)h(b)s(egins)f(with)f(the)i(p)s (ound)d('#')i(c)m(haracter)i(is)0 4377 y(ignored)30 b(b)m(y)h(the)f (template)i(parser)e(and)g(ma)m(y)h(b)s(e)e(use)h(to)h(insert)g(commen) m(ts)g(in)m(to)g(the)g(template)h(\014le)e(itself.)0 4538 y(The)c(KEYW)m(ORD)g(name)g(\014eld)g(is)g(limited)h(to)g(8)f(c)m (haracters)h(in)f(length)h(and)e(only)h(the)g(letters)i(A-Z,)e(digits)h (0-9,)0 4650 y(and)h(the)g(h)m(yphen)f(and)h(underscore)g(c)m (haracters)h(ma)m(y)g(b)s(e)f(used,)g(without)h(an)m(y)f(em)m(b)s (edded)g(spaces.)40 b(Lo)m(w)m(ercase)0 4763 y(letters)22 b(in)f(the)h(template)g(k)m(eyw)m(ord)g(name)f(will)g(b)s(e)g(con)m(v)m (erted)i(to)f(upp)s(ercase.)36 b(Leading)22 b(spaces)f(in)g(the)h (template)0 4876 y(line)k(preceding)g(the)f(k)m(eyw)m(ord)h(name)g(are) g(generally)h(ignored,)g(except)f(if)g(the)g(\014rst)f(8)h(c)m (haracters)h(of)f(a)g(template)0 4989 y(line)f(are)h(all)g(blank,)g (then)f(the)g(en)m(tire)h(line)g(is)f(treated)h(as)f(a)h(FITS)e(commen) m(t)i(k)m(eyw)m(ord)g(\(with)f(a)h(blank)e(k)m(eyw)m(ord)0 5102 y(name\))31 b(and)f(is)g(copied)h(v)m(erbatim)g(in)m(to)g(the)g (FITS)e(header.)0 5262 y(The)37 b(KEYV)-10 b(ALUE)37 b(\014eld)g(ma)m(y)h(ha)m(v)m(e)g(an)m(y)g(allo)m(w)m(ed)h(FITS)e(data) h(t)m(yp)s(e:)54 b(c)m(haracter)39 b(string,)h(logical,)h(in)m(teger,)0 5375 y(real,)28 b(complex)g(in)m(teger,)h(or)d(complex)i(real.)40 b(In)m(teger)28 b(v)-5 b(alues)27 b(m)m(ust)f(b)s(e)g(within)g(the)h (allo)m(w)m(ed)i(range)e(of)g(a)g('signed)0 5488 y(long')h(v)-5 b(ariable;)29 b(some)f(C)e(compilers)i(only)f(suppp)s(ort)e(4-b)m(yte)j (long)g(in)m(tegers)g(with)f(a)g(range)h(from)e(-2147483648)0 5601 y(to)31 b(+2147483647,)k(whereas)30 b(other)h(C)f(compilers)h (supp)s(ort)e(8-b)m(yte)j(in)m(tegers)f(with)f(a)h(range)g(of)g(plus)e (or)i(min)m(us)0 5714 y(2**63.)1882 5942 y(155)p eop end %%Page: 156 164 TeXDict begin 156 163 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.156) cvn H.B /DEST pdfmark end 0 299 a Fj(156)2250 b Fh(CHAPTER)29 b(11.)72 b(TEMPLA)-8 b(TE)30 b(FILES)0 555 y Fj(The)23 b(c)m(haracter)h(string)f(v)-5 b(alues)24 b(need)f(not)g(b)s(e)g (enclosed)g(in)g(single)h(quote)g(c)m(haracters)g(unless)f(they)g(are)h (necessary)0 668 y(to)37 b(distinguish)e(the)i(string)f(from)f(a)i (di\013eren)m(t)g(data)f(t)m(yp)s(e)h(\(e.g.)59 b(2.0)38 b(is)e(a)g(real)h(but)f('2.0')h(is)f(a)h(string\).)58 b(The)0 781 y(k)m(eyw)m(ord)38 b(has)g(an)g(unde\014ned)d(\(n)m(ull\))k (v)-5 b(alue)38 b(if)g(the)g(template)h(record)f(only)g(con)m(tains)h (blanks)e(follo)m(wing)j(the)0 894 y("=")31 b(or)f(b)s(et)m(w)m(een)h (the)g("=")g(and)f(the)g("/")i(commen)m(t)f(\014eld)f(delimiter.)0 1054 y(String)c(k)m(eyw)m(ord)h(v)-5 b(alues)27 b(longer)g(than)f(68)h (c)m(haracters)h(\(the)f(maxim)m(um)f(length)h(that)g(will)g(\014t)f (in)g(a)h(single)g(FITS)0 1167 y(k)m(eyw)m(ord)41 b(record\))g(are)g(p) s(ermitted)f(using)g(the)h(CFITSIO)e(long)i(string)g(con)m(v)m(en)m (tion.)74 b(They)40 b(can)h(either)g(b)s(e)0 1280 y(sp)s(eci\014ed)28 b(as)i(a)f(single)h(long)f(line)h(in)e(the)i(template,)h(or)e(b)m(y)f (using)h(m)m(ultiple)h(lines)f(where)f(the)i(con)m(tin)m(uing)g(lines)0 1393 y(con)m(tain)i(the)e('CONTINUE')g(k)m(eyw)m(ord,)h(as)g(in)f(this) g(example:)95 1657 y Fe(LONGKEY)46 b(=)i('This)e(is)h(a)h(long)e (string)g(value)h(that)f(is)i(contin&')95 1770 y(CONTINUE)94 b('ued)46 b(over)h(2)g(records')f(/)h(comment)f(field)h(goes)f(here)0 2035 y Fj(The)29 b(format)h(of)g(template)h(lines)e(with)h(CONTINUE)e (k)m(eyw)m(ord)i(is)g(v)m(ery)g(strict:)41 b(3)30 b(spaces)g(m)m(ust)f (follo)m(w)i(CON-)0 2147 y(TINUE)f(and)g(the)g(rest)h(of)f(the)h(line)g (is)f(copied)h(v)m(erbatim)g(to)g(the)g(FITS)e(\014le.)0 2308 y(The)i(start)h(of)g(the)f(optional)i(COMMENT)e(\014eld)g(m)m(ust) h(b)s(e)e(preceded)i(b)m(y)f("/",)i(whic)m(h)e(is)h(used)f(to)h (separate)g(it)0 2421 y(from)e(the)g(k)m(eyw)m(ord)h(v)-5 b(alue)30 b(\014eld.)41 b(Exceptions)30 b(are)h(if)f(the)h(KEYW)m(ORD)g (name)f(\014eld)g(con)m(tains)h(COMMENT,)0 2533 y(HISTOR)-8 b(Y,)30 b(CONTINUE,)g(or)g(if)g(the)h(\014rst)f(8)g(c)m(haracters)i(of) f(the)f(template)i(line)f(are)g(blanks.)0 2694 y(More)c(than)f(one)h (Header-Data)i(Unit)e(\(HDU\))g(ma)m(y)g(b)s(e)f(de\014ned)f(in)h(the)h (template)h(\014le.)39 b(The)26 b(start)h(of)g(an)f(HDU)0 2806 y(de\014nition)k(is)g(denoted)h(with)f(a)h(SIMPLE)e(or)i(XTENSION) e(template)j(line:)0 2967 y(1\))i(SIMPLE)f(b)s(egins)g(a)h(Primary)g (HDU)g(de\014nition.)50 b(SIMPLE)33 b(ma)m(y)h(only)g(app)s(ear)f(as)h (the)g(\014rst)f(k)m(eyw)m(ord)h(in)0 3080 y(the)e(template)i(\014le.) 45 b(If)32 b(the)g(template)i(\014le)e(b)s(egins)f(with)h(XTENSION)f (instead)h(of)g(SIMPLE,)g(then)f(a)i(default)0 3192 y(empt)m(y)d (Primary)e(HDU)i(is)g(created,)h(and)d(the)i(template)h(is)e(then)g (assumed)f(to)i(de\014ne)f(the)h(k)m(eyw)m(ords)f(starting)0 3305 y(with)h(the)h(\014rst)e(extension)i(follo)m(wing)h(the)f(Primary) f(HDU.)0 3466 y(2\))35 b(XTENSION)e(marks)g(the)i(b)s(eginning)e(of)h (a)h(new)e(extension)i(HDU)f(de\014nition.)52 b(The)33 b(previous)h(HDU)h(will)0 3578 y(b)s(e)30 b(closed)h(at)g(this)f(p)s (oin)m(t)h(and)e(pro)s(cessing)i(of)f(the)h(next)f(extension)h(b)s (egins.)0 3739 y SDict begin H.S end 0 3739 a 0 3739 a SDict begin 13.6 H.A end 0 3739 a 0 3739 a SDict begin [ /View [/XYZ H.V] /Dest (section.11.2) cvn H.B /DEST pdfmark end 0 3739 a 179 x Ff(11.2)136 b(Auto-indexing)45 b(of)g(Keyw)l(ords)0 4169 y Fj(If)31 b(a)h(template)g(k)m(eyw)m(ord)g(name)f(ends)g(with)g (a)g("#")h(c)m(haracter,)i(it)e(is)f(said)g(to)h(b)s(e)f ('auto-indexed'.)44 b(Eac)m(h)32 b("#")0 4282 y(c)m(haracter)i(will)f (b)s(e)f(replaced)i(b)m(y)e(the)h(curren)m(t)g(in)m(teger)h(index)e(v) -5 b(alue,)34 b(whic)m(h)f(gets)g(reset)h(=)e(1)h(at)h(the)e(start)i (of)0 4395 y(eac)m(h)h(new)f(HDU)g(in)g(the)g(\014le)g(\(or)g(7)h(in)e (the)h(sp)s(ecial)h(case)g(of)f(a)g(GR)m(OUP)h(de\014nition\).)51 b(The)33 b(FIRST)g(indexed)0 4508 y(k)m(eyw)m(ord)c(in)f(eac)m(h)h (template)h(HDU)f(de\014nition)f(is)g(used)f(as)i(the)f('incremen)m (tor';)j(eac)m(h)e(subsequen)m(t)f(o)s(ccurrence)0 4620 y(of)k(this)f(SAME)g(k)m(eyw)m(ord)h(will)g(cause)g(the)g(index)f(v)-5 b(alue)32 b(to)g(b)s(e)f(incremen)m(ted.)44 b(This)31 b(b)s(eha)m(vior)g(can)h(b)s(e)f(rather)0 4733 y(subtle,)d(as)g (illustrated)h(in)e(the)h(follo)m(wing)h(examples)f(in)f(whic)m(h)h (the)g(TTYPE)e(k)m(eyw)m(ord)i(is)g(the)g(incremen)m(tor)g(in)0 4846 y(b)s(oth)i(cases:)95 5111 y Fe(TTYPE#)47 b(=)g(TIME)95 5224 y(TFORM#)g(=)g(1D)95 5337 y(TTYPE#)g(=)g(RATE)95 5449 y(TFORM#)g(=)g(1E)0 5714 y Fj(will)26 b(create)i(TTYPE1,)e(TF)m (ORM1,)i(TTYPE2,)f(and)e(TF)m(ORM2)i(k)m(eyw)m(ords.)40 b(But)26 b(if)g(the)g(template)h(lo)s(oks)f(lik)m(e,)p eop end %%Page: 157 165 TeXDict begin 157 164 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.157) cvn H.B /DEST pdfmark end 0 299 a Fh(11.3.)73 b(TEMPLA)-8 b(TE)30 b(P)-8 b(ARSER)30 b(DIRECTIVES)1982 b Fj(157)95 555 y Fe(TTYPE#)47 b(=)g(TIME)95 668 y(TTYPE#)g(=)g(RATE)95 781 y(TFORM#)g(=)g(1D)95 894 y(TFORM#)g(=)g(1E)0 1202 y Fj(this)31 b(results)f(in)h(a)g(FITS)f(\014les)h(with)f(TTYPE1,)h (TTYPE2,)g(TF)m(ORM2,)h(and)e(TF)m(ORM2,)i(whic)m(h)f(is)g(probably)0 1315 y(not)g(what)f(w)m(as)h(in)m(tended!)0 1509 y SDict begin H.S end 0 1509 a 0 1509 a SDict begin 13.6 H.A end 0 1509 a 0 1509 a SDict begin [ /View [/XYZ H.V] /Dest (section.11.3) cvn H.B /DEST pdfmark end 0 1509 a 197 x Ff(11.3)136 b(T)-11 b(emplate)45 b(P)l(arser)h(Directiv)l(es)0 1968 y Fj(In)29 b(addition)i(to)f(the)g(template)i(lines)e(whic)m(h)g (de\014ne)f(individual)h(k)m(eyw)m(ords,)g(the)g(template)i(parser)d (recognizes)0 2081 y(3)h(sp)s(ecial)h(directiv)m(es)g(whic)m(h)f(are)g (eac)m(h)h(preceded)f(b)m(y)f(the)h(bac)m(kslash)h(c)m(haracter:)90 b Fe(\\include,)45 b(\\group)p Fj(,)29 b(and)48 2194 y Fe(\\end)p Fj(.)0 2354 y(The)37 b('include')h(directiv)m(e)i(m)m(ust) d(b)s(e)h(follo)m(w)m(ed)h(b)m(y)f(a)g(\014lename.)63 b(It)38 b(forces)g(the)g(parser)f(to)i(temp)s(orarily)f(stop)0 2467 y(reading)d(the)g(curren)m(t)g(template)h(\014le)f(and)f(b)s(egin) h(reading)g(the)g(include)f(\014le.)55 b(Once)35 b(the)g(parser)f(reac) m(hes)i(the)0 2579 y(end)f(of)h(the)g(include)f(\014le)h(it)g(con)m (tin)m(ues)g(parsing)g(the)f(curren)m(t)h(template)h(\014le.)56 b(Include)35 b(\014les)h(can)g(b)s(e)f(nested,)0 2692 y(and)30 b(HDU)h(de\014nitions)f(can)g(span)g(m)m(ultiple)h(template)h (\014les.)0 2853 y(The)f(start)h(of)g(a)g(GR)m(OUP)h(de\014nition)e(is) h(denoted)g(with)f(the)h('group')g(directiv)m(e,)h(and)f(the)f(end)h (of)f(a)i(GR)m(OUP)0 2965 y(de\014nition)k(is)h(denoted)f(with)g(the)h ('end')f(directiv)m(e.)63 b(Eac)m(h)39 b(GR)m(OUP)e(con)m(tains)i(0)f (or)f(more)h(mem)m(b)s(er)f(blo)s(c)m(ks)0 3078 y(\(HDUs)44 b(or)f(GR)m(OUPs\).)79 b(Mem)m(b)s(er)42 b(blo)s(c)m(ks)i(of)f(t)m(yp)s (e)g(GR)m(OUP)g(can)g(con)m(tain)h(their)f(o)m(wn)g(mem)m(b)s(er)f(blo) s(c)m(ks.)0 3191 y(The)32 b(GR)m(OUP)g(de\014nition)g(itself)h(o)s (ccupies)g(one)f(FITS)g(\014le)g(HDU)h(of)f(sp)s(ecial)h(t)m(yp)s(e)f (\(GR)m(OUP)h(HDU\),)h(so)e(if)h(a)0 3304 y(template)f(sp)s(eci\014es)e (1)h(group)e(with)h(1)h(mem)m(b)s(er)f(HDU)h(lik)m(e:)0 3613 y Fe(\\group)0 3725 y(grpdescr)46 b(=)h('demo')0 3838 y(xtension)f(bintable)0 3951 y(#)h(this)g(bintable)f(has)h(0)g (cols,)f(0)i(rows)0 4064 y(\\end)0 4373 y Fj(then)30 b(the)h(parser)e(creates)j(a)f(FITS)f(\014le)g(with)g(3)h(HDUs)g(:)0 4681 y Fe(1\))47 b(dummy)g(PHDU)0 4794 y(2\))g(GROUP)g(HDU)f(\(has)h(1) h(member,)d(which)i(is)g(bintable)e(in)j(HDU)f(number)f(3\))0 4907 y(3\))h(bintable)f(\(member)g(of)h(GROUP)f(in)h(HDU)g(number)f (2\))0 5215 y Fj(T)-8 b(ec)m(hnically)32 b(sp)s(eaking,)e(the)f(GR)m (OUP)i(HDU)f(is)g(a)g(BINT)-8 b(ABLE)30 b(with)g(6)g(columns.)40 b(Applications)31 b(can)f(de\014ne)0 5328 y(additional)23 b(columns)f(in)f(a)i(GR)m(OUP)f(HDU)h(using)f(TF)m(ORMn)f(and)h(TTYPEn) f(\(where)g(n)h(is)g(7,)i(8,)h(....\))39 b(k)m(eyw)m(ords)0 5441 y(or)30 b(their)h(auto-indexing)g(equiv)-5 b(alen)m(ts.)0 5601 y(F)d(or)26 b(a)f(more)g(complicated)h(example)f(of)g(a)h (template)g(\014le)f(using)f(the)h(group)f(directiv)m(es,)k(lo)s(ok)d (at)g(the)g(sample.tpl)0 5714 y(\014le)30 b(that)h(is)g(included)e(in)i (the)f(CFITSIO)f(distribution.)p eop end %%Page: 158 166 TeXDict begin 158 165 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.158) cvn H.B /DEST pdfmark end 0 299 a Fj(158)2250 b Fh(CHAPTER)29 b(11.)72 b(TEMPLA)-8 b(TE)30 b(FILES)0 464 y SDict begin H.S end 0 464 a 0 464 a SDict begin 13.6 H.A end 0 464 a 0 464 a SDict begin [ /View [/XYZ H.V] /Dest (section.11.4) cvn H.B /DEST pdfmark end 0 464 a 91 x Ff(11.4)136 b(F)-11 b(ormal)45 b(T)-11 b(emplate)46 b(Syn)l(tax)0 805 y Fj(The)30 b(template)i(syn)m(tax)f(can)f(formally)h(b)s(e)f(de\014ned)f(as)i (follo)m(ws:)191 1063 y Fe(TEMPLATE)45 b(=)j(BLOCK)e([)i(BLOCK)e(...)h (])334 1289 y(BLOCK)f(=)i({)f(HDU)g(|)h(GROUP)e(})334 1515 y(GROUP)g(=)i(\\GROUP)e([)h(BLOCK)g(...)g(])g(\\END)430 1741 y(HDU)f(=)i(XTENSION)d([)j(LINE)f(...)f(])i({)f(XTENSION)f(|)h (\\GROUP)f(|)i(\\END)f(|)g(EOF)g(})382 1967 y(LINE)f(=)i([)f(KEYWORD)f ([)i(=)f(])h(])f([)g(VALUE)g(])g([)h(/)f(COMMENT)f(])191 2192 y(X)h(...)238 b(-)48 b(X)f(can)g(be)g(present)f(1)h(or)h(more)e (times)191 2305 y({)h(X)h(|)f(Y)h(})f(-)h(X)f(or)g(Y)191 2418 y([)g(X)h(])238 b(-)48 b(X)f(is)g(optional)0 2676 y Fj(A)m(t)34 b(the)f(topmost)g(lev)m(el,)i(the)e(template)i(de\014nes) c(1)j(or)e(more)h(template)h(blo)s(c)m(ks.)49 b(Blo)s(c)m(ks)34 b(can)f(b)s(e)f(either)h(HDU)0 2789 y(\(Header)27 b(Data)h(Unit\))g(or) e(a)h(GR)m(OUP)-8 b(.)28 b(F)-8 b(or)27 b(eac)m(h)g(blo)s(c)m(k)g(the)g (parser)f(creates)i(1)f(\(or)g(more)f(for)h(GR)m(OUPs\))g(FITS)0 2902 y(\014le)j(HDUs.)0 3039 y SDict begin H.S end 0 3039 a 0 3039 a SDict begin 13.6 H.A end 0 3039 a 0 3039 a SDict begin [ /View [/XYZ H.V] /Dest (section.11.5) cvn H.B /DEST pdfmark end 0 3039 a 196 x Ff(11.5)136 b(Errors)0 3485 y Fj(In)24 b(general)h(the)f(\014ts)p 692 3485 28 4 v 33 w(execute)p 1019 3485 V 34 w(template\(\))i(function)e(tries)h(to)g (b)s(e)f(as)g(atomic)i(as)f(p)s(ossible,)g(so)f(either)h(ev)m(erything) 0 3598 y(is)f(done)g(or)g(nothing)f(is)h(done.)39 b(If)23 b(an)h(error)f(o)s(ccurs)h(during)f(parsing)g(of)h(the)g(template,)j (\014ts)p 3125 3598 V 33 w(execute)p 3452 3598 V 34 w(template\(\))0 3711 y(will)k(\(try)g(to\))h(delete)g(the)f(top)g(lev)m(el)h(BLOCK)e (\(with)h(all)g(its)h(c)m(hildren)e(if)h(an)m(y\))g(in)g(whic)m(h)f (the)h(error)f(o)s(ccurred,)0 3824 y(then)g(it)h(will)g(stop)f(reading) h(the)f(template)i(\014le)e(and)g(it)h(will)g(return)e(with)h(an)g (error.)0 3979 y SDict begin H.S end 0 3979 a 0 3979 a SDict begin 13.6 H.A end 0 3979 a 0 3979 a SDict begin [ /View [/XYZ H.V] /Dest (section.11.6) cvn H.B /DEST pdfmark end 0 3979 a 179 x Ff(11.6)136 b(Examples)0 4408 y Fj(1.)54 b(This)34 b(template)i(\014le)f(will)g(create)h(a)f(200)h(x)e(300)i (pixel)f(image,)j(with)c(4-b)m(yte)i(in)m(teger)g(pixel)f(v)-5 b(alues,)36 b(in)f(the)0 4521 y(primary)29 b(HDU:)95 4779 y Fe(SIMPLE)47 b(=)g(T)95 4891 y(BITPIX)g(=)g(32)95 5004 y(NAXIS)g(=)g(2)239 b(/)47 b(number)f(of)h(dimensions)95 5117 y(NAXIS1)g(=)g(100)95 b(/)47 b(length)f(of)h(first)g(axis)95 5230 y(NAXIS2)g(=)g(200)95 b(/)47 b(length)f(of)h(second)f(axis)95 5343 y(OBJECT)h(=)g(NGC)g(253)g(/)g(name)g(of)g(observed)f(object)0 5601 y Fj(The)35 b(allo)m(w)m(ed)i(v)-5 b(alues)36 b(of)f(BITPIX)g(are) h(8,)h(16,)h(32,)g(-32,)g(or)d(-64,)j(represen)m(ting,)f(resp)s(ectiv)m (ely)-8 b(,)39 b(8-bit)d(in)m(teger,)0 5714 y(16-bit)c(in)m(teger,)g (32-bit)f(in)m(teger,)h(32-bit)g(\015oating)f(p)s(oin)m(t,)g(or)f(64)h (bit)g(\015oating)g(p)s(oin)m(t)f(pixels.)p eop end %%Page: 159 167 TeXDict begin 159 166 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.159) cvn H.B /DEST pdfmark end 0 299 a Fh(11.6.)73 b(EXAMPLES)2993 b Fj(159)0 555 y(2.)39 b(T)-8 b(o)23 b(create)h(a)f(FITS)e(table,)26 b(the)c(template)i(\014rst)e(needs)g(to)i(include)e(XTENSION)g(=)g(T)-8 b(ABLE)23 b(or)f(BINT)-8 b(ABLE)0 668 y(to)31 b(de\014ne)e(whether)g (it)h(is)g(an)f(ASCI)s(I)g(or)g(binary)g(table,)i(and)f(NAXIS2)g(to)g (de\014ne)f(the)h(n)m(um)m(b)s(er)f(of)h(ro)m(ws)f(in)h(the)0 781 y(table.)50 b(Tw)m(o)34 b(template)g(lines)g(are)g(then)f(needed)f (to)i(de\014ne)f(the)g(name)h(\(TTYPEn\))e(and)h(FITS)g(data)h(format)0 894 y(\(TF)m(ORMn\))d(of)f(the)h(columns,)f(as)h(in)f(this)g(example:) 95 1154 y Fe(xtension)46 b(=)h(bintable)95 1267 y(naxis2)g(=)g(40)95 1380 y(ttype#)g(=)g(Name)95 1492 y(tform#)g(=)g(10a)95 1605 y(ttype#)g(=)g(Npoints)95 1718 y(tform#)g(=)g(j)95 1831 y(ttype#)g(=)g(Rate)95 1944 y(tunit#)g(=)g(counts/s)95 2057 y(tform#)g(=)g(e)0 2317 y Fj(The)26 b(ab)s(o)m(v)m(e)j(example)e (de\014nes)f(a)i(n)m(ull)f(primary)f(arra)m(y)h(follo)m(w)m(ed)i(b)m(y) e(a)g(40-ro)m(w)h(binary)e(table)i(extension)g(with)f(3)0 2430 y(columns)h(called)h('Name',)h('Np)s(oin)m(ts',)f(and)f('Rate',)i (with)e(data)h(formats)f(of)g('10A')i(\(ASCI)s(I)d(c)m(haracter)i (string\),)0 2543 y('1J')k(\(in)m(teger\))i(and)d('1E')i(\(\015oating)f (p)s(oin)m(t\),)h(resp)s(ectiv)m(ely)-8 b(.)50 b(Note)34 b(that)f(the)g(other)g(required)f(FITS)g(k)m(eyw)m(ords)0 2655 y(\(BITPIX,)37 b(NAXIS,)g(NAXIS1,)h(PCOUNT,)e(GCOUNT,)h(TFIELDS,)f (and)g(END\))h(do)g(not)g(need)f(to)h(b)s(e)f(ex-)0 2768 y(plicitly)j(de\014ned)d(in)i(the)f(template)i(b)s(ecause)f(their)g(v) -5 b(alues)38 b(can)g(b)s(e)f(inferred)f(from)i(the)f(other)h(k)m(eyw)m (ords)g(in)0 2881 y(the)d(template.)55 b(This)34 b(example)i(also)g (illustrates)f(that)h(the)f(templates)h(are)f(generally)h (case-insensitiv)m(e)h(\(the)0 2994 y(k)m(eyw)m(ord)29 b(names)g(and)g(TF)m(ORMn)f(v)-5 b(alues)30 b(are)f(con)m(v)m(erted)i (to)e(upp)s(er-case)g(in)f(the)h(FITS)g(\014le\))g(and)f(that)i(string) 0 3107 y(k)m(eyw)m(ord)h(v)-5 b(alues)31 b(generally)g(do)f(not)h(need) f(to)h(b)s(e)f(enclosed)h(in)f(quotes.)p eop end %%Page: 160 168 TeXDict begin 160 167 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.160) cvn H.B /DEST pdfmark end 0 299 a Fj(160)2250 b Fh(CHAPTER)29 b(11.)72 b(TEMPLA)-8 b(TE)30 b(FILES)p eop end %%Page: 161 169 TeXDict begin 161 168 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.161) cvn H.B /DEST pdfmark end 0 299 a 0 464 a SDict begin H.S end 0 464 a 0 464 a SDict begin 13.6 H.A end 0 464 a 0 464 a SDict begin [ /View [/XYZ H.V] /Dest (chapter.12) cvn H.B /DEST pdfmark end 0 464 a 761 x Fg(Chapter)65 b(12)0 1687 y Fm(Lo)6 b(cal)78 b(FITS)e(Con)-6 b(v)g(en)g(tions)0 2180 y Fj(CFITSIO)29 b(supp)s(orts)g(sev)m(eral)j(lo)s(cal)g(FITS)e (con)m(v)m(en)m(tions)i(whic)m(h)f(are)g(not)g(de\014ned)e(in)i(the)f (o\016cial)j(FITS)d(stan-)0 2293 y(dard)43 b(and)g(whic)m(h)g(are)h (not)g(necessarily)g(recognized)h(or)f(supp)s(orted)e(b)m(y)h(other)h (FITS)f(soft)m(w)m(are)i(pac)m(k)-5 b(ages.)0 2406 y(Programmers)36 b(should)f(b)s(e)g(cautious)i(ab)s(out)e(using)h(these)g(features,)i (esp)s(ecially)f(if)f(the)g(FITS)f(\014les)h(that)h(are)0 2518 y(pro)s(duced)31 b(are)i(exp)s(ected)g(to)g(b)s(e)f(pro)s(cessed)g (b)m(y)h(other)f(soft)m(w)m(are)i(systems)f(whic)m(h)f(do)h(not)f(use)h (the)f(CFITSIO)0 2631 y(in)m(terface.)0 2794 y SDict begin H.S end 0 2794 a 0 2794 a SDict begin 13.6 H.A end 0 2794 a 0 2794 a SDict begin [ /View [/XYZ H.V] /Dest (section.12.1) cvn H.B /DEST pdfmark end 0 2794 a 196 x Ff(12.1)136 b(64-Bit)45 b(Long)g(In)l(tegers)0 3246 y Fj(CFITSIO)37 b(supp)s(orts)g(reading)i(and)f(writing)h(FITS)f(images)i(or)f(table)h (columns)e(con)m(taining)i(64-bit)h(in)m(teger)0 3359 y(data)26 b(v)-5 b(alues.)40 b(Supp)s(ort)23 b(for)i(64-bit)i(in)m (tegers)g(w)m(as)f(added)e(to)j(the)e(o\016cial)i(FITS)e(Standard)f(in) i(Decem)m(b)s(er)g(2005.)0 3472 y(FITS)g(64-bit)i(images)g(ha)m(v)m(e)g (BITPIX)e(=)h(64,)h(and)e(the)h(64-bit)h(binary)e(table)i(columns)f(ha) m(v)m(e)h(TF)m(ORMn)e(=)h('K'.)0 3584 y(CFITSIO)35 b(also)i(supp)s (orts)e(the)i('Q')f(v)-5 b(ariable-length)38 b(arra)m(y)f(table)h (column)e(format)h(whic)m(h)f(is)g(analogous)i(to)0 3697 y(the)31 b('P')f(column)g(format)h(except)g(that)g(the)g(arra)m(y)g (descriptor)f(is)h(stored)f(as)h(a)f(pair)h(of)f(64-bit)i(in)m(tegers.) 0 3858 y(F)-8 b(or)33 b(the)f(con)m(v)m(enience)i(of)f(C)e (programmers,)h(the)h(\014tsio.h)f(include)g(\014le)g(de\014nes)f (\(with)h(a)h(t)m(yp)s(edef)f(statemen)m(t\))0 3970 y(the)39 b('LONGLONG')g(datat)m(yp)s(e)h(to)f(b)s(e)f(equiv)-5 b(alen)m(t)40 b(to)f(an)g(appropriate)g(64-bit)h(in)m(teger)g(datat)m (yp)s(e)f(on)g(eac)m(h)0 4083 y(platform.)g(Since)27 b(there)f(is)g(curren)m(tly)g(no)g(univ)m(ersal)h(standard)e(for)h(the) g(name)g(of)h(the)f(64-bit)h(in)m(teger)h(datat)m(yp)s(e)0 4196 y(\(it)33 b(migh)m(t)f(b)s(e)f(de\014ned)g(as)h('long)g(long',)i ('long',)f(or)f(')p 1832 4196 28 4 v 1865 4196 V 66 w(in)m(t64')h(dep)s (ending)d(on)i(the)g(platform\))g(C)g(programmers)0 4309 y(ma)m(y)24 b(prefer)f(to)i(use)e(the)h('LONGLONG')h(datat)m(yp)s(e)f (when)f(declaring)i(or)e(allo)s(cating)j(64-bit)f(in)m(teger)h(quan)m (tities)0 4422 y(when)33 b(writing)h(co)s(de)g(whic)m(h)f(needs)h(to)h (run)d(on)i(m)m(ultiple)g(platforms.)52 b(Note)35 b(that)f(CFITSIO)f (will)h(implicitly)0 4535 y(con)m(v)m(ert)h(the)e(datat)m(yp)s(e)h (when)f(reading)g(or)g(writing)h(FITS)e(64-bit)j(in)m(teger)f(images)h (and)d(columns)h(with)g(data)0 4648 y(arra)m(ys)40 b(of)h(a)f (di\013eren)m(t)h(in)m(teger)g(or)f(\015oating)h(p)s(oin)m(t)f(datat)m (yp)s(e,)k(but)c(there)g(is)g(an)g(increased)g(risk)g(of)g(loss)h(of)0 4761 y(n)m(umerical)31 b(precision)f(or)h(n)m(umerical)g(o)m(v)m (er\015o)m(w)h(in)e(this)g(case.)0 4941 y SDict begin H.S end 0 4941 a 0 4941 a SDict begin 13.6 H.A end 0 4941 a 0 4941 a SDict begin [ /View [/XYZ H.V] /Dest (section.12.2) cvn H.B /DEST pdfmark end 0 4941 a 179 x Ff(12.2)136 b(Long)44 b(String)i(Keyw)l(ord)f(V)-11 b(alues.)0 5375 y Fj(The)43 b(length)i(of)f(a)g(standard)g(FITS)f(string)h(k)m(eyw)m(ord)g(is)g (limited)h(to)g(68)f(c)m(haracters)i(b)s(ecause)e(it)g(m)m(ust)g(\014t) 0 5488 y(en)m(tirely)35 b(within)e(a)h(single)h(FITS)e(header)g(k)m (eyw)m(ord)i(record.)50 b(In)33 b(some)i(instances)f(it)g(is)g (necessary)g(to)h(enco)s(de)0 5601 y(strings)29 b(longer)i(than)e(this) g(limit,)i(so)f(CFITSIO)e(supp)s(orts)g(a)h(lo)s(cal)i(con)m(v)m(en)m (tion)h(in)d(whic)m(h)h(the)f(string)h(v)-5 b(alue)30 b(is)0 5714 y(con)m(tin)m(ued)36 b(o)m(v)m(er)g(m)m(ultiple)f(k)m(eyw)m (ords.)55 b(This)34 b(con)m(tin)m(uation)i(con)m(v)m(en)m(tion)h(uses)e (an)f(amp)s(ersand)g(c)m(haracter)i(at)1882 5942 y(161)p eop end %%Page: 162 170 TeXDict begin 162 169 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.162) cvn H.B /DEST pdfmark end 0 299 a Fj(162)1741 b Fh(CHAPTER)30 b(12.)112 b(LOCAL)29 b(FITS)h(CONVENTIONS)0 555 y Fj(the)c(end)f(of)h (eac)m(h)g(substring)f(to)h(indicate)h(that)f(it)h(is)e(con)m(tin)m (ued)i(on)e(the)h(next)g(k)m(eyw)m(ord,)h(and)e(the)h(con)m(tin)m (uation)0 668 y(k)m(eyw)m(ords)40 b(all)h(ha)m(v)m(e)g(the)f(name)g (CONTINUE)f(without)h(an)g(equal)g(sign)g(in)g(column)g(9.)69 b(The)40 b(string)f(v)-5 b(alue)0 781 y(ma)m(y)33 b(b)s(e)f(con)m(tin)m (ued)h(in)g(this)f(w)m(a)m(y)h(o)m(v)m(er)h(as)f(man)m(y)g(additional)g (CONTINUE)f(k)m(eyw)m(ords)h(as)f(is)h(required.)46 b(The)0 894 y(follo)m(wing)37 b(lines)e(illustrate)h(this)f(con)m(tin)m(uation) i(con)m(v)m(en)m(tion)h(whic)m(h)c(is)i(used)e(in)h(the)g(v)-5 b(alue)36 b(of)f(the)g(STRKEY)0 1007 y(k)m(eyw)m(ord:)0 1297 y Fe(LONGSTRN=)45 b('OGIP)i(1.0')189 b(/)48 b(The)f(OGIP)f(Long)h (String)f(Convention)f(may)i(be)g(used.)0 1410 y(STRKEY)94 b(=)47 b('This)g(is)g(a)g(very)g(long)g(string)f(keyword&')93 b(/)47 b(Optional)f(Comment)0 1523 y(CONTINUE)93 b(')48 b(value)e(that)h(is)g(continued)e(over)i(3)g(keywords)f(in)h(the)g(&)95 b(')0 1636 y(CONTINUE)e('FITS)47 b(header.')e(/)j(This)e(is)h(another)f (optional)g(comment.)0 1926 y Fj(It)29 b(is)g(recommended)f(that)h(the) g(LONGSTRN)f(k)m(eyw)m(ord,)i(as)f(sho)m(wn)f(here,)h(alw)m(a)m(ys)i(b) s(e)d(included)g(in)g(an)m(y)h(HDU)0 2039 y(that)i(uses)f(this)g (longstring)h(con)m(v)m(en)m(tion)i(as)e(a)f(w)m(arning)h(to)g(an)m(y)g (soft)m(w)m(are)g(that)g(m)m(ust)g(read)f(the)h(k)m(eyw)m(ords.)41 b(A)0 2152 y(routine)d(called)g(\014ts)p 712 2152 28 4 v 33 w(write)p 947 2152 V 33 w(k)m(ey)p 1113 2152 V 33 w(longw)m(arn)g(has)f(b)s(een)g(pro)m(vided)g(in)h(CFITSIO)d(to)k (write)e(this)h(k)m(eyw)m(ord)g(if)f(it)0 2265 y(do)s(es)30 b(not)h(already)g(exist.)0 2425 y(This)f(long)h(string)f(con)m(v)m(en)m (tion)i(is)f(supp)s(orted)d(b)m(y)j(the)f(follo)m(wing)i(CFITSIO)d (routines:)191 2716 y Fe(fits_write_key_longstr)89 b(-)48 b(write)e(a)i(long)e(string)g(keyword)g(value)191 2829 y(fits_insert_key_longstr)41 b(-)48 b(insert)e(a)h(long)g(string)f (keyword)g(value)191 2942 y(fits_modify_key_longstr)41 b(-)48 b(modify)e(a)h(long)g(string)f(keyword)g(value)191 3054 y(fits_update_key_longstr)41 b(-)48 b(modify)e(a)h(long)g(string)f (keyword)g(value)191 3167 y(fits_read_key_longstr)137 b(-)48 b(read)94 b(a)48 b(long)e(string)g(keyword)g(value)191 3280 y(fits_delete_key)425 b(-)48 b(delete)e(a)h(keyword)0 3571 y Fj(The)36 b(\014ts)p 320 3571 V 32 w(read)p 524 3571 V 33 w(k)m(ey)p 690 3571 V 34 w(longstr)g(routine)h(is)f(unique)f (among)i(all)h(the)e(CFITSIO)f(routines)h(in)g(that)h(it)g(in)m (ternally)0 3684 y(allo)s(cates)f(memory)d(for)h(the)f(long)h(string)g (v)-5 b(alue;)36 b(all)e(the)g(other)g(CFITSIO)e(routines)h(that)h (deal)g(with)g(arra)m(ys)0 3797 y(require)39 b(that)h(the)g(calling)h (program)e(pre-allo)s(cate)j(adequate)e(space)g(to)g(hold)f(the)h(arra) m(y)g(of)f(data.)69 b(Conse-)0 3909 y(quen)m(tly)-8 b(,)31 b(programs)f(whic)m(h)g(use)g(the)g(\014ts)p 1443 3909 V 32 w(read)p 1647 3909 V 33 w(k)m(ey)p 1813 3909 V 34 w(longstr)g(routine)g(m)m(ust)g(b)s(e)g(careful)g(to)h(free)g(the)f (allo)s(cated)0 4022 y(memory)g(for)g(the)h(string)f(when)g(it)h(is)f (no)g(longer)h(needed.)0 4183 y(The)f(follo)m(wing)i(2)e(routines)h (also)g(ha)m(v)m(e)h(limited)f(supp)s(ort)d(for)i(this)h(long)g(string) f(con)m(v)m(en)m(tion,)286 4473 y Fe(fits_modify_key_str)43 b(-)k(modify)f(an)i(existing)d(string)h(keyword)g(value)286 4586 y(fits_update_key_str)d(-)k(update)f(a)i(string)e(keyword)g(value) 0 4876 y Fj(in)24 b(that)h(they)f(will)h(correctly)g(o)m(v)m(erwrite)h (an)e(existing)h(long)g(string)f(v)-5 b(alue,)27 b(but)c(the)h(new)g (string)g(v)-5 b(alue)25 b(is)f(limited)0 4989 y(to)31 b(a)g(maxim)m(um)f(of)h(68)g(c)m(haracters)h(in)e(length.)0 5149 y(The)f(more)h(commonly)h(used)e(CFITSIO)f(routines)i(to)g(write)g (string)g(v)-5 b(alued)30 b(k)m(eyw)m(ords)g(\(\014ts)p 3254 5149 V 33 w(up)s(date)p 3563 5149 V 32 w(k)m(ey)h(and)0 5262 y(\014ts)p 127 5262 V 32 w(write)p 361 5262 V 33 w(k)m(ey\))j(do)e(not)h(supp)s(ort)d(this)i(long)h(string)g(con)m(v)m (en)m(tion)h(and)e(only)g(supp)s(ort)f(strings)h(up)f(to)i(68)g(c)m (har-)0 5375 y(acters)g(in)f(length.)48 b(This)31 b(has)h(b)s(een)g (done)g(delib)s(erately)h(to)g(prev)m(en)m(t)g(programs)f(from)g(inadv) m(erten)m(tly)i(writing)0 5488 y(k)m(eyw)m(ords)25 b(using)f(this)h (non-standard)e(con)m(v)m(en)m(tion)k(without)e(the)g(explicit)h(in)m (ten)m(t)g(of)f(the)f(programmer)h(or)f(user.)0 5601 y(The)36 b(\014ts)p 320 5601 V 32 w(write)p 554 5601 V 33 w(k)m(ey)p 720 5601 V 34 w(longstr)h(routine)f(m)m(ust)h(b)s(e)f (called)i(instead)e(to)i(write)e(long)h(strings.)59 b(This)36 b(routine)h(can)0 5714 y(also)31 b(b)s(e)f(used)g(to)h(write)f (ordinary)g(string)g(v)-5 b(alues)31 b(less)g(than)f(68)h(c)m (haracters)h(in)e(length.)p eop end %%Page: 163 171 TeXDict begin 163 170 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.163) cvn H.B /DEST pdfmark end 0 299 a Fh(12.3.)73 b(ARRA)-8 b(YS)30 b(OF)h(FIXED-LENGTH)g(STRINGS)e(IN)h(BINAR)-8 b(Y)32 b(T)-8 b(ABLES)871 b Fj(163)0 464 y SDict begin H.S end 0 464 a 0 464 a SDict begin 13.6 H.A end 0 464 a 0 464 a SDict begin [ /View [/XYZ H.V] /Dest (section.12.3) cvn H.B /DEST pdfmark end 0 464 a 91 x Ff(12.3)136 b(Arra)l(ys)45 b(of)g(Fixed-Length)g(Strings)g(in)g(Binary)f(T)-11 b(ables)0 807 y Fj(CFITSIO)25 b(supp)s(orts)g(2)i(w)m(a)m(ys)g(to)g(sp)s(ecify)f (that)i(a)f(c)m(haracter)h(column)e(in)g(a)h(binary)f(table)i(con)m (tains)f(an)g(arra)m(y)g(of)0 920 y(\014xed-length)32 b(strings.)46 b(The)32 b(\014rst)f(w)m(a)m(y)-8 b(,)34 b(whic)m(h)e(is)g(o\016cially)i(supp)s(orted)c(b)m(y)i(the)h(FITS)e (Standard)g(do)s(cumen)m(t,)0 1033 y(uses)38 b(the)g(TDIMn)g(k)m(eyw)m (ord.)65 b(F)-8 b(or)39 b(example,)i(if)d(TF)m(ORMn)g(=)g('60A')h(and)f (TDIMn)g(=)g('\(12,5\)')i(then)e(that)0 1146 y(column)30 b(will)h(b)s(e)f(in)m(terpreted)g(as)h(con)m(taining)h(an)e(arra)m(y)h (of)g(5)f(strings,)h(eac)m(h)g(12)g(c)m(haracters)h(long.)0 1306 y(CFITSIO)j(also)j(supp)s(orts)c(a)j(lo)s(cal)h(con)m(v)m(en)m (tion)h(for)d(the)h(format)g(of)g(the)f(TF)m(ORMn)h(k)m(eyw)m(ord)g(v) -5 b(alue)37 b(of)g(the)0 1419 y(form)42 b('rAw')g(where)g('r')g(is)h (an)f(in)m(teger)i(sp)s(ecifying)e(the)g(total)j(width)c(in)h(c)m (haracters)i(of)f(the)f(column,)k(and)0 1532 y('w')36 b(is)g(an)g(in)m(teger)h(sp)s(ecifying)f(the)g(\(\014xed\))g(length)h (of)f(an)g(individual)f(unit)h(string)f(within)h(the)g(v)m(ector.)59 b(F)-8 b(or)0 1644 y(example,)29 b(TF)m(ORM1)f(=)f('120A10')j(w)m(ould) d(indicate)h(that)g(the)f(binary)g(table)h(column)f(is)g(120)i(c)m (haracters)f(wide)0 1757 y(and)42 b(consists)h(of)f(12)h(10-c)m (haracter)i(length)e(strings.)77 b(This)41 b(con)m(v)m(en)m(tion)k(is)d (recognized)i(b)m(y)e(the)g(CFITSIO)0 1870 y(routines)26 b(that)h(read)e(or)h(write)h(strings)e(in)h(binary)f(tables.)40 b(The)26 b(Binary)g(T)-8 b(able)27 b(de\014nition)e(do)s(cumen)m(t)h (sp)s(eci\014es)0 1983 y(that)i(other)f(optional)h(c)m(haracters)h(ma)m (y)e(follo)m(w)i(the)e(data)h(t)m(yp)s(e)f(co)s(de)g(in)g(the)g(TF)m (ORM)h(k)m(eyw)m(ord,)g(so)g(this)f(lo)s(cal)0 2096 y(con)m(v)m(en)m (tion)f(is)d(in)h(compliance)h(with)e(the)h(FITS)e(standard)h(although) h(other)g(FITS)f(readers)g(ma)m(y)h(not)g(recognize)0 2209 y(this)30 b(con)m(v)m(en)m(tion.)0 2353 y SDict begin H.S end 0 2353 a 0 2353 a SDict begin 13.6 H.A end 0 2353 a 0 2353 a SDict begin [ /View [/XYZ H.V] /Dest (section.12.4) cvn H.B /DEST pdfmark end 0 2353 a 197 x Ff(12.4)136 b(Keyw)l(ord)45 b(Units)h(Strings)0 2801 y Fj(One)37 b(limitation)j(of)d(the)h(curren)m(t)g(FITS)e(Standard)h(is)h(that)g (it)g(do)s(es)f(not)h(de\014ne)f(a)h(sp)s(eci\014c)f(con)m(v)m(en)m (tion)j(for)0 2914 y(recording)30 b(the)g(ph)m(ysical)h(units)f(of)g(a) g(k)m(eyw)m(ord)h(v)-5 b(alue.)41 b(The)30 b(TUNITn)f(k)m(eyw)m(ord)h (can)g(b)s(e)g(used)f(to)i(sp)s(ecify)f(the)0 3027 y(ph)m(ysical)36 b(units)f(of)g(the)h(v)-5 b(alues)36 b(in)f(a)g(table)i(column,)f(but)f (there)g(is)h(no)f(analogous)i(con)m(v)m(en)m(tion)g(for)e(k)m(eyw)m (ord)0 3140 y(v)-5 b(alues.)42 b(The)30 b(commen)m(t)h(\014eld)g(of)f (the)h(k)m(eyw)m(ord)g(is)g(often)g(used)f(for)g(this)g(purp)s(ose,)g (but)f(the)i(units)f(are)h(usually)0 3253 y(not)g(sp)s(eci\014ed)e(in)h (a)h(w)m(ell)g(de\014ned)f(format)g(that)h(FITS)f(readers)g(can)h (easily)g(recognize)h(and)e(extract.)0 3413 y(T)-8 b(o)27 b(solv)m(e)i(this)d(problem,)i(CFITSIO)d(uses)i(a)g(lo)s(cal)h(con)m(v) m(en)m(tion)h(in)e(whic)m(h)f(the)i(k)m(eyw)m(ord)f(units)f(are)i (enclosed)f(in)0 3526 y(square)20 b(brac)m(k)m(ets)j(as)e(the)f (\014rst)g(tok)m(en)i(in)f(the)f(k)m(eyw)m(ord)i(commen)m(t)f(\014eld;) j(more)d(sp)s(eci\014cally)-8 b(,)24 b(the)d(op)s(ening)f(square)0 3639 y(brac)m(k)m(et)28 b(immediately)g(follo)m(ws)f(the)g(slash)f('/') h(commen)m(t)h(\014eld)e(delimiter)h(and)f(a)g(single)h(space)g(c)m (haracter.)41 b(The)0 3752 y(follo)m(wing)32 b(examples)f(illustrate)g (k)m(eyw)m(ords)g(that)g(use)f(this)g(con)m(v)m(en)m(tion:)0 4018 y Fe(EXPOSURE=)713 b(1800.0)47 b(/)g([s])g(elapsed)f(exposure)f (time)0 4131 y(V_HELIO)h(=)763 b(16.23)47 b(/)g([km)g(s**\(-1\)])e (heliocentric)g(velocity)0 4244 y(LAMBDA)94 b(=)763 b(5400.)47 b(/)g([angstrom])e(central)h(wavelength)0 4357 y(FLUX)190 b(=)47 b(4.9033487787637465E-30)42 b(/)47 b([J/cm**2/s])e(average)h (flux)0 4622 y Fj(In)28 b(general,)h(the)g(units)e(named)h(in)g(the)h (IA)m(U\(1988\))i(St)m(yle)e(Guide)f(are)h(recommended,)f(with)g(the)h (main)f(excep-)0 4735 y(tion)j(that)g(the)f(preferred)g(unit)f(for)i (angle)g(is)f('deg')i(for)e(degrees.)0 4896 y(The)38 b(\014ts)p 322 4896 28 4 v 33 w(read)p 527 4896 V 33 w(k)m(ey)p 693 4896 V 33 w(unit)h(and)f(\014ts)p 1234 4896 V 32 w(write)p 1468 4896 V 33 w(k)m(ey)p 1634 4896 V 34 w(unit)g(routines)h(in)g(CFITSIO)e(read)i(and)f(write,)k(resp)s (ectiv)m(ely)-8 b(,)0 5008 y(the)31 b(k)m(eyw)m(ord)f(unit)g(strings)h (in)f(an)g(existing)h(k)m(eyw)m(ord.)0 5170 y SDict begin H.S end 0 5170 a 0 5170 a SDict begin 13.6 H.A end 0 5170 a 0 5170 a SDict begin [ /View [/XYZ H.V] /Dest (section.12.5) cvn H.B /DEST pdfmark end 0 5170 a 179 x Ff(12.5)136 b(HIERAR)l(CH)46 b(Con)l(v)l(en)l(tion)g(for)f(Extended)h(Keyw)l(ord)f (Names)0 5601 y Fj(CFITSIO)c(supp)s(orts)g(the)i(HIERAR)m(CH)g(k)m(eyw) m(ord)g(con)m(v)m(en)m(tion)i(whic)m(h)e(allo)m(ws)h(k)m(eyw)m(ord)f (names)g(that)h(are)0 5714 y(longer)34 b(then)e(8)i(c)m(haracters)g (and)f(ma)m(y)h(con)m(tain)g(the)f(full)g(range)g(of)h(prin)m(table)f (ASCI)s(I)e(text)j(c)m(haracters.)51 b(This)p eop end %%Page: 164 172 TeXDict begin 164 171 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.164) cvn H.B /DEST pdfmark end 0 299 a Fj(164)1741 b Fh(CHAPTER)30 b(12.)112 b(LOCAL)29 b(FITS)h(CONVENTIONS)0 555 y Fj(con)m(v)m(en)m (tion)39 b(w)m(as)f(dev)m(elop)s(ed)f(at)h(the)f(Europ)s(ean)f (Southern)g(Observ)-5 b(atory)37 b(\(ESO\))f(to)i(supp)s(ort)d(hierarc) m(hical)0 668 y(FITS)30 b(k)m(eyw)m(ord)g(suc)m(h)h(as:)0 925 y Fe(HIERARCH)46 b(ESO)g(INS)h(FOCU)g(POS)g(=)g(-0.00002500)e(/)j (Focus)e(position)0 1182 y Fj(Basically)-8 b(,)55 b(this)47 b(con)m(v)m(en)m(tion)j(uses)d(the)h(FITS)f(k)m(eyw)m(ord)h('HIERAR)m (CH')h(to)f(indicate)h(that)f(this)f(con)m(v)m(en-)0 1295 y(tion)e(is)f(b)s(eing)g(used,)j(then)d(the)g(actual)i(k)m(eyw)m (ord)e(name)h(\()p Fe('ESO)i(INS)f(FOCU)h(POS')c Fj(in)h(this)g (example\))h(b)s(e-)0 1408 y(gins)40 b(in)f(column)g(10)i(and)e(can)h (con)m(tain)g(an)m(y)g(prin)m(table)g(ASCI)s(I)e(text)j(c)m(haracters,) i(including)d(spaces.)68 b(The)0 1521 y(equals)44 b(sign)h(marks)e(the) h(end)g(of)g(the)g(k)m(eyw)m(ord)h(name)f(and)f(is)i(follo)m(w)m(ed)g (b)m(y)f(the)g(usual)g(v)-5 b(alue)45 b(and)e(com-)0 1634 y(men)m(t)31 b(\014elds)f(just)g(as)h(in)f(standard)g(FITS)g(k)m (eyw)m(ords.)41 b(F)-8 b(urther)30 b(details)i(of)f(this)f(con)m(v)m (en)m(tion)j(are)e(describ)s(ed)e(at)0 1747 y(h)m (ttp://\014ts.gsfc.nasa.go)m(v/registry/hierarc)m(h)p 1659 1747 28 4 v 38 w(k)m(eyw)m(ord.h)m(tml)f(and)f(in)g(Section)g(4.4) h(of)g(the)f(ESO)f(Data)j(In)m(ter-)0 1859 y(face)c(Con)m(trol)f(Do)s (cumen)m(t)h(that)g(is)f(link)m(ed)g(to)g(from)g(h)m(ttp://arc)m(hiv)m (e.eso.org/cms/to)s(ols-)q(do)s(cumen)m(tati)q(on/eso)q(-)0 1972 y(data-in)m(terface-con)m(trol.h)m(tml.)0 2133 y(This)43 b(con)m(v)m(en)m(tion)k(allo)m(ws)f(a)e(m)m(uc)m(h)h(broader)e(range)i (of)f(k)m(eyw)m(ord)h(names)f(than)h(is)f(allo)m(w)m(ed)i(b)m(y)e(the)h (FITS)0 2245 y(Standard.)40 b(Here)30 b(are)h(more)g(examples)g(of)f (suc)m(h)g(k)m(eyw)m(ords:)0 2502 y Fe(HIERARCH)46 b(LongKeyword)e(=)k (47.5)e(/)i(Keyword)e(has)h(>)g(8)g(characters,)e(and)i(mixed)f(case)0 2615 y(HIERARCH)g(XTE$TEMP)f(=)j(98.6)e(/)i(Keyword)d(contains)h(the)h ('$')g(character)0 2728 y(HIERARCH)f(Earth)g(is)h(a)h(star)e(=)i(F)f(/) h(Keyword)d(contains)h(embedded)f(spaces)0 2985 y Fj(CFITSIO)40 b(will)i(transparen)m(tly)g(read)g(and)f(write)g(these)i(k)m(eyw)m (ords,)i(so)d(application)h(programs)e(do)g(not)h(in)0 3098 y(general)33 b(need)f(to)h(kno)m(w)f(an)m(ything)h(ab)s(out)f(the) g(sp)s(eci\014c)g(implemen)m(tation)i(details)f(of)g(the)f(HIERAR)m(CH) g(con-)0 3211 y(v)m(en)m(tion.)50 b(In)32 b(particular,)j(application)f (programs)e(do)h(not)h(need)e(to)i(sp)s(ecify)f(the)g(`HIERAR)m(CH')h (part)f(of)g(the)0 3324 y(k)m(eyw)m(ord)g(name)f(when)g(reading)g(or)g (writing)h(k)m(eyw)m(ords)f(\(although)h(it)g(ma)m(y)g(b)s(e)f (included)f(if)i(desired\).)46 b(When)0 3437 y(writing)35 b(a)g(k)m(eyw)m(ord,)h(CFITSIO)d(\014rst)h(c)m(hec)m(ks)i(to)f(see)g (if)g(the)g(k)m(eyw)m(ord)g(name)f(is)h(legal)h(as)f(a)g(standard)f (FITS)0 3550 y(k)m(eyw)m(ord)k(\(no)g(more)f(than)h(8)g(c)m(haracters)h (long)f(and)f(con)m(taining)i(only)e(letters,)k(digits,)f(or)e(a)g(min) m(us)e(sign)i(or)0 3663 y(underscore\).)68 b(If)39 b(so)h(it)g(writes)g (it)g(as)f(a)h(standard)f(FITS)g(k)m(eyw)m(ord,)k(otherwise)d(it)g (uses)f(the)h(hierarc)m(h)f(con-)0 3776 y(v)m(en)m(tion)34 b(to)f(write)g(the)f(k)m(eyw)m(ord.)48 b(The)32 b(maxim)m(um)g(k)m(eyw) m(ord)h(name)f(length)h(is)g(67)g(c)m(haracters,)i(whic)m(h)d(lea)m(v)m (es)0 3888 y(only)c(1)h(space)g(for)f(the)h(v)-5 b(alue)29 b(\014eld.)39 b(A)29 b(more)f(practical)i(limit)f(is)g(ab)s(out)f(40)h (c)m(haracters,)i(whic)m(h)d(lea)m(v)m(es)i(enough)0 4001 y(ro)s(om)e(for)h(most)f(k)m(eyw)m(ord)h(v)-5 b(alues.)41 b(CFITSIO)27 b(returns)g(an)h(error)h(if)f(there)h(is)f(not)h(enough)f (ro)s(om)h(for)f(b)s(oth)g(the)0 4114 y(k)m(eyw)m(ord)k(name)f(and)f (the)i(k)m(eyw)m(ord)f(v)-5 b(alue)32 b(on)f(the)h(80-c)m(haracter)h (card,)f(except)g(for)f(string-v)-5 b(alued)32 b(k)m(eyw)m(ords)0 4227 y(whic)m(h)h(are)g(simply)f(truncated)h(so)g(that)h(the)f(closing) h(quote)g(c)m(haracter)g(falls)f(in)g(column)g(80.)49 b(In)32 b(the)h(curren)m(t)0 4340 y(implemen)m(tation,)e(CFITSIO)c (preserv)m(es)i(the)g(case)h(of)f(the)g(letters)h(when)e(writing)h(the) g(k)m(eyw)m(ord)g(name,)g(but)f(it)0 4453 y(is)d(case-insensitiv)m(e)i (when)d(reading)h(or)g(searc)m(hing)h(for)f(a)g(k)m(eyw)m(ord.)40 b(The)24 b(curren)m(t)h(implemen)m(tation)h(allo)m(ws)h(an)m(y)0 4566 y(ASCI)s(I)i(text)j(c)m(haracter)h(\(ASCI)s(I)c(32)j(to)f(ASCI)s (I)f(126\))i(in)f(the)g(k)m(eyw)m(ord)g(name)g(except)h(for)e(the)h ('=')g(c)m(haracter.)0 4679 y(A)f(space)h(is)g(also)g(required)f(on)g (either)h(side)f(of)h(the)f(equal)h(sign.)0 4833 y SDict begin H.S end 0 4833 a 0 4833 a SDict begin 13.6 H.A end 0 4833 a 0 4833 a SDict begin [ /View [/XYZ H.V] /Dest (section.12.6) cvn H.B /DEST pdfmark end 0 4833 a 179 x Ff(12.6)136 b(Tile-Compressed)46 b(Image)g(F)-11 b(ormat)0 5262 y Fj(CFITSIO)36 b(supp)s(orts)f(a)j(con)m(v)m(en)m(tion)i(for)d (compressing)h(n-dimensional)f(images)h(and)f(storing)h(the)g (resulting)0 5375 y(b)m(yte)i(stream)g(in)f(a)h(v)-5 b(ariable-length)41 b(column)e(in)g(a)h(FITS)f(binary)f(table.)69 b(The)39 b(general)i(principle)e(used)f(in)0 5488 y(this)c(con)m(v)m (en)m(tion)j(is)d(to)h(\014rst)f(divide)g(the)h(n-dimensional)f(image)i (in)m(to)f(a)g(rectangular)g(grid)f(of)h(subimages)f(or)0 5601 y(`tiles'.)57 b(Eac)m(h)35 b(tile)i(is)e(then)g(compressed)g(as)g (a)h(con)m(tin)m(uous)g(blo)s(c)m(k)f(of)h(data,)h(and)e(the)g (resulting)g(compressed)0 5714 y(b)m(yte)i(stream)h(is)f(stored)g(in)f (a)h(ro)m(w)g(of)g(a)h(v)-5 b(ariable)37 b(length)g(column)g(in)g(a)g (FITS)f(binary)g(table.)61 b(By)37 b(dividing)p eop end %%Page: 165 173 TeXDict begin 165 172 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.165) cvn H.B /DEST pdfmark end 0 299 a Fh(12.6.)73 b(TILE-COMPRESSED)28 b(IMA)m(GE)j(F)m(ORMA)-8 b(T)1838 b Fj(165)0 555 y(the)40 b(image)g(in)m(to)g(tiles)h(it)f(is)f(generally)i(p)s(ossible)e(to)h (extract)h(and)d(uncompress)g(subsections)i(of)f(the)h(image)0 668 y(without)d(ha)m(ving)h(to)g(uncompress)e(the)h(whole)g(image.)62 b(The)37 b(default)g(tiling)h(pattern)g(treats)g(eac)m(h)g(ro)m(w)f(of) h(a)0 781 y(2-dimensional)e(image)g(\(or)f(higher)f(dimensional)h(cub)s (e\))g(as)g(a)g(tile,)j(suc)m(h)c(that)i(eac)m(h)g(tile)g(con)m(tains)g (NAXIS1)0 894 y(pixels)29 b(\(except)h(the)f(default)g(with)g(the)g (HCOMPRESS)e(algorithm)j(is)f(to)h(compress)f(the)g(whole)g(2D)h(image) g(as)0 1007 y(a)35 b(single)g(tile\).)56 b(An)m(y)34 b(other)h(rectangular)h(tiling)g(pattern)f(ma)m(y)g(also)h(b)s(e)e (de\014ned.)52 b(In)34 b(the)h(case)h(of)f(relativ)m(ely)0 1120 y(small)25 b(images)h(it)f(ma)m(y)g(b)s(e)f(su\016cien)m(t)h(to)h (compress)e(the)h(en)m(tire)g(image)h(as)f(a)g(single)h(tile,)h (resulting)d(in)h(an)f(output)0 1233 y(binary)29 b(table)i(with)f(1)g (ro)m(w.)41 b(In)29 b(the)h(case)h(of)f(3-dimensional)h(data)g(cub)s (es,)e(it)i(ma)m(y)f(b)s(e)f(adv)-5 b(an)m(tageous)32 b(to)f(treat)0 1346 y(eac)m(h)i(plane)f(of)g(the)g(cub)s(e)f(as)h(a)g (separate)h(tile)g(if)f(application)h(soft)m(w)m(are)h(t)m(ypically)f (needs)f(to)g(access)i(the)e(cub)s(e)0 1458 y(on)e(a)h(plane)f(b)m(y)h (plane)f(basis.)0 1619 y(See)41 b(section)g(5.6)h(\\Image)f (Compression")f(for)g(more)h(information)g(on)f(using)g(this)g (tile-compressed)i(image)0 1732 y(format.)p eop end %%Page: 166 174 TeXDict begin 166 173 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.166) cvn H.B /DEST pdfmark end 0 299 a Fj(166)1741 b Fh(CHAPTER)30 b(12.)112 b(LOCAL)29 b(FITS)h(CONVENTIONS)p eop end %%Page: 167 175 TeXDict begin 167 174 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.167) cvn H.B /DEST pdfmark end 0 299 a 0 464 a SDict begin H.S end 0 464 a 0 464 a SDict begin 13.6 H.A end 0 464 a 0 464 a SDict begin [ /View [/XYZ H.V] /Dest (chapter.13) cvn H.B /DEST pdfmark end 0 464 a 761 x Fg(Chapter)65 b(13)0 1687 y Fm(Optimizing)76 b(Programs)0 2180 y Fj(CFITSIO)22 b(has)h(b)s(een)f(carefully)i(designed)f(to)h(obtain)g(the)f(highest)h (p)s(ossible)e(sp)s(eed)h(when)f(reading)h(and)g(writing)0 2293 y(FITS)33 b(\014les.)51 b(In)33 b(order)h(to)g(ac)m(hiev)m(e)i (the)e(b)s(est)g(p)s(erformance,)g(ho)m(w)m(ev)m(er,)i(application)g (programmers)d(m)m(ust)h(b)s(e)0 2406 y(careful)24 b(to)h(call)g(the)f (CFITSIO)f(routines)g(appropriately)i(and)e(in)h(an)f(e\016cien)m(t)j (sequence;)h(inappropriate)c(usage)0 2518 y(of)31 b(CFITSIO)d(routines) j(can)f(greatly)i(slo)m(w)f(do)m(wn)f(the)h(execution)g(sp)s(eed)f(of)g (a)h(program.)0 2679 y(The)f(maxim)m(um)h(p)s(ossible)f(I/O)h(sp)s(eed) f(of)h(CFITSIO)e(dep)s(ends)g(of)i(course)g(on)f(the)h(t)m(yp)s(e)g(of) g(computer)g(system)0 2791 y(that)j(it)g(is)g(running)d(on.)50 b(T)-8 b(o)34 b(get)h(a)f(general)g(idea)g(of)g(what)f(data)i(I/O)e(sp) s(eeds)f(are)i(p)s(ossible)f(on)h(a)g(particular)0 2904 y(mac)m(hine,)j(build)e(the)g(sp)s(eed.c)g(program)g(that)h(is)g (distributed)e(with)h(CFITSIO)f(\(t)m(yp)s(e)i('mak)m(e)g(sp)s(eed')f (in)g(the)0 3017 y(CFITSIO)e(directory\).)54 b(This)33 b(diagnostic)j(program)e(measures)h(the)f(sp)s(eed)g(of)g(writing)h (and)f(reading)g(bac)m(k)i(a)0 3130 y(test)31 b(FITS)f(image,)i(a)f (binary)e(table,)j(and)d(an)i(ASCI)s(I)e(table.)0 3290 y(The)k(follo)m(wing)h(2)g(sections)g(pro)m(vide)g(some)f(bac)m (kground)g(on)h(ho)m(w)f(CFITSIO)f(in)m(ternally)i(manages)g(the)f (data)0 3403 y(I/O)g(and)g(describ)s(es)f(some)i(strategies)h(that)f (ma)m(y)g(b)s(e)e(used)h(to)h(optimize)g(the)g(pro)s(cessing)f(sp)s (eed)f(of)h(soft)m(w)m(are)0 3516 y(that)e(uses)f(CFITSIO.)0 3735 y SDict begin H.S end 0 3735 a 0 3735 a SDict begin 13.6 H.A end 0 3735 a 0 3735 a SDict begin [ /View [/XYZ H.V] /Dest (section.13.1) cvn H.B /DEST pdfmark end 0 3735 a 197 x Ff(13.1)136 b(Ho)l(w)45 b(CFITSIO)f(Manages)i(Data)g(I/O)0 4199 y Fj(Man)m(y)22 b(CFITSIO)e(op)s(erations)i(in)m(v)m(olv)m(e)i (transferring)d(only)h(a)g(small)g(n)m(um)m(b)s(er)f(of)h(b)m(ytes)g (to)g(or)g(from)f(the)h(FITS)f(\014le)0 4312 y(\(e.g,)31 b(reading)e(a)g(k)m(eyw)m(ord,)h(or)f(writing)g(a)g(ro)m(w)g(in)f(a)h (table\);)i(it)f(w)m(ould)e(b)s(e)g(v)m(ery)i(ine\016cien)m(t)g(to)f (ph)m(ysically)h(read)0 4425 y(or)i(write)h(suc)m(h)f(small)g(blo)s(c)m (ks)h(of)f(data)h(directly)g(in)f(the)g(FITS)g(\014le)g(on)g(disk,)h (therefore)f(CFITSIO)f(main)m(tains)0 4538 y(a)38 b(set)g(of)g(in)m (ternal)h(Input{Output)c(\(IO\))j(bu\013ers)f(in)g(RAM)h(memory)g(that) g(eac)m(h)h(con)m(tain)g(one)f(FITS)f(blo)s(c)m(k)0 4650 y(\(2880)27 b(b)m(ytes\))f(of)f(data.)40 b(Whenev)m(er)25 b(CFITSIO)f(needs)g(to)i(access)g(data)g(in)f(the)g(FITS)f(\014le,)j (it)e(\014rst)f(transfers)h(the)0 4763 y(FITS)30 b(blo)s(c)m(k)h(con)m (taining)h(those)f(b)m(ytes)g(in)m(to)g(one)g(of)f(the)h(IO)f (bu\013ers)f(in)h(memory)-8 b(.)42 b(The)30 b(next)g(time)h(CFITSIO)0 4876 y(needs)36 b(to)g(access)i(b)m(ytes)e(in)g(the)g(same)h(blo)s(c)m (k)f(it)h(can)f(then)g(go)h(to)f(the)h(fast)f(IO)f(bu\013er)g(rather)h (than)g(using)g(a)0 4989 y(m)m(uc)m(h)c(slo)m(w)m(er)i(system)e(disk)g (access)h(routine.)46 b(The)32 b(n)m(um)m(b)s(er)f(of)h(a)m(v)-5 b(ailable)35 b(IO)d(bu\013ers)f(is)h(determined)g(b)m(y)g(the)0 5102 y(NIOBUF)f(parameter)g(\(in)f(\014tsio2.h\))h(and)f(is)h(curren)m (tly)f(set)h(to)g(40)g(b)m(y)g(default.)0 5262 y(Whenev)m(er)24 b(CFITSIO)f(reads)g(or)h(writes)g(data)g(it)h(\014rst)e(c)m(hec)m(ks)i (to)g(see)f(if)g(that)g(blo)s(c)m(k)h(of)f(the)g(FITS)f(\014le)g(is)h (already)0 5375 y(loaded)33 b(in)m(to)g(one)f(of)g(the)g(IO)g (bu\013ers.)44 b(If)32 b(not,)h(and)e(if)h(there)g(is)g(an)g(empt)m(y)h (IO)e(bu\013er)g(a)m(v)-5 b(ailable,)35 b(then)d(it)h(will)0 5488 y(load)g(that)h(blo)s(c)m(k)f(in)m(to)g(the)g(IO)g(bu\013er)e (\(when)h(reading)h(a)g(FITS)f(\014le\))h(or)g(will)g(initialize)i(a)e (new)f(blo)s(c)m(k)i(\(when)0 5601 y(writing)j(to)h(a)g(FITS)f (\014le\).)62 b(If)37 b(all)h(the)g(IO)e(bu\013ers)h(are)g(already)h (full,)h(it)f(m)m(ust)g(decide)f(whic)m(h)g(one)h(to)g(reuse)0 5714 y(\(generally)c(the)f(one)g(that)g(has)f(b)s(een)g(accessed)i (least)f(recen)m(tly\),)i(and)d(\015ush)f(the)i(con)m(ten)m(ts)h(bac)m (k)g(to)f(disk)f(if)g(it)1882 5942 y(167)p eop end %%Page: 168 176 TeXDict begin 168 175 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.168) cvn H.B /DEST pdfmark end 0 299 a Fj(168)1876 b Fh(CHAPTER)30 b(13.)112 b(OPTIMIZING)29 b(PR)m(OGRAMS)0 555 y Fj(has)h(b)s(een)g(mo)s (di\014ed)f(b)s(efore)h(loading)h(the)g(new)f(blo)s(c)m(k.)0 715 y(The)g(one)g(ma)5 b(jor)30 b(exception)i(to)f(the)f(ab)s(o)m(v)m (e)h(pro)s(cess)f(o)s(ccurs)g(whenev)m(er)g(a)g(large)i(con)m(tiguous)f (set)g(of)f(b)m(ytes)h(are)0 828 y(accessed,)37 b(as)d(migh)m(t)i(o)s (ccur)e(when)f(reading)i(or)f(writing)g(a)h(FITS)f(image.)54 b(In)34 b(this)g(case)h(CFITSIO)e(b)m(ypasses)0 941 y(the)i(in)m (ternal)h(IO)f(bu\013ers)f(and)g(simply)h(reads)g(or)g(writes)h(the)f (desired)g(b)m(ytes)g(directly)h(in)f(the)g(disk)g(\014le)g(with)0 1054 y(a)i(single)g(call)g(to)g(a)g(lo)m(w-lev)m(el)i(\014le)d(read)g (or)h(write)f(routine.)58 b(The)36 b(minim)m(um)g(threshold)f(for)h (the)h(n)m(um)m(b)s(er)e(of)0 1167 y(b)m(ytes)27 b(to)g(read)f(or)g (write)g(this)g(w)m(a)m(y)i(is)e(set)g(b)m(y)h(the)f(MINDIRECT)g (parameter)g(and)g(is)g(curren)m(tly)g(set)h(to)g(3)g(FITS)0 1280 y(blo)s(c)m(ks)36 b(=)g(8640)i(b)m(ytes.)58 b(This)35 b(is)h(the)g(most)g(e\016cien)m(t)i(w)m(a)m(y)f(to)g(read)e(or)h(write) h(large)g(c)m(h)m(unks)e(of)h(data.)59 b(Note)0 1393 y(that)34 b(this)f(fast)h(direct)g(IO)f(pro)s(cess)f(is)i(not)f (applicable)i(when)d(accessing)j(columns)e(of)h(data)g(in)f(a)g(FITS)g (table)0 1506 y(b)s(ecause)f(the)h(b)m(ytes)g(are)g(generally)g(not)g (con)m(tiguous)g(since)g(they)g(are)f(in)m(terlea)m(v)m(ed)j(b)m(y)e (the)f(other)h(columns)f(of)0 1619 y(data)i(in)e(the)h(table.)49 b(This)33 b(explains)g(wh)m(y)f(the)h(sp)s(eed)f(for)h(accessing)h (FITS)e(tables)i(is)f(generally)h(slo)m(w)m(er)g(than)0 1732 y(accessing)e(FITS)e(images.)0 1892 y(Giv)m(en)i(this)g(bac)m (kground)f(information,)h(the)g(general)g(strategy)h(for)e(e\016cien)m (tly)i(accessing)g(FITS)e(\014les)g(should)0 2005 y(b)s(e)e(apparen)m (t:)41 b(when)28 b(dealing)j(with)e(FITS)g(images,)i(read)e(or)h(write) g(large)g(c)m(h)m(unks)g(of)g(data)g(at)g(a)g(time)g(so)g(that)0 2118 y(the)25 b(direct)g(IO)f(mec)m(hanism)g(will)h(b)s(e)f(in)m(v)m (ok)m(ed;)k(when)c(accessing)i(FITS)e(headers)g(or)g(FITS)g(tables,)j (on)d(the)h(other)0 2230 y(hand,)35 b(once)g(a)g(particular)g(FITS)f (blo)s(c)m(k)i(has)e(b)s(een)g(loading)i(in)m(to)f(one)g(of)g(the)g(IO) f(bu\013ers,)h(try)g(to)g(access)h(all)0 2343 y(the)30 b(needed)g(information)g(in)g(that)g(blo)s(c)m(k)h(b)s(efore)f(it)g (gets)h(\015ushed)d(out)j(of)f(the)g(IO)f(bu\013er.)40 b(It)30 b(is)g(imp)s(ortan)m(t)g(to)0 2456 y(a)m(v)m(oid)e(the)f (situation)g(where)f(the)h(same)g(FITS)e(blo)s(c)m(k)i(is)g(b)s(eing)f (read)g(then)g(\015ushed)f(from)h(a)h(IO)f(bu\013er)f(m)m(ultiple)0 2569 y(times.)0 2729 y(The)30 b(follo)m(wing)i(section)f(giv)m(es)h (more)e(sp)s(eci\014c)h(suggestions)g(for)f(optimizing)i(the)e(use)g (of)h(CFITSIO.)0 2916 y SDict begin H.S end 0 2916 a 0 2916 a SDict begin 13.6 H.A end 0 2916 a 0 2916 a SDict begin [ /View [/XYZ H.V] /Dest (section.13.2) cvn H.B /DEST pdfmark end 0 2916 a 179 x Ff(13.2)136 b(Optimization)46 b(Strategies)0 3352 y Fj(1.)d(Because)32 b(the)f(data)g(in)g(FITS)f(\014les)h(is)g (alw)m(a)m(ys)h(stored)f(in)g("big-endian")h(b)m(yte)f(order,)g(where)f (the)h(\014rst)f(b)m(yte)0 3465 y(of)g(n)m(umeric)h(v)-5 b(alues)30 b(con)m(tains)i(the)e(most)h(signi\014can)m(t)g(bits)f(and)g (the)g(last)i(b)m(yte)e(con)m(tains)i(the)e(least)i(signi\014can)m(t)0 3578 y(bits,)e(CFITSIO)f(m)m(ust)h(sw)m(ap)g(the)g(order)f(of)h(the)h (b)m(ytes)f(when)f(reading)h(or)g(writing)g(FITS)g(\014les)g(when)f (running)0 3690 y(on)k(little-endian)i(mac)m(hines)f(\(e.g.,)i(Lin)m (ux)d(and)g(Microsoft)i(Windo)m(ws)e(op)s(erating)h(systems)g(running)d (on)j(PCs)0 3803 y(with)c(x86)h(CPUs\).)0 3963 y(On)21 b(relativ)m(ely)k(new)d(CPUs)g(that)h(supp)s(ort)d("SSSE3")i(mac)m (hine)h(instructions)f(\(e.g.,)k(starting)d(with)f(In)m(tel)h(Core)g(2) 0 4076 y(CPUs)e(in)h(2007,)j(and)d(in)f(AMD)i(CPUs)e(b)s(eginning)g(in) h(2011\))i(signi\014can)m(tly)f(faster)f(4-b)m(yte)h(and)e(8-b)m(yte)i (sw)m(apping)0 4189 y(algorithms)k(are)g(a)m(v)-5 b(ailable.)42 b(These)26 b(faster)h(b)m(yte)g(sw)m(apping)f(functions)g(are)h(not)g (used)e(b)m(y)i(default)f(in)g(CFITSIO)0 4302 y(\(b)s(ecause)33 b(of)g(p)s(oten)m(tial)h(co)s(de)f(p)s(ortablilit)m(y)h(issues\),)g (but)e(users)g(can)h(enable)g(them)f(on)h(supp)s(orted)e(platforms)0 4415 y(b)m(y)38 b(adding)f(the)h(appropriate)f(compiler)i(\015ags)e (\(-mssse3)i(with)e(gcc)i(or)f(icc)g(on)g(lin)m(ux\))g(when)e (compiling)j(the)0 4528 y(sw)m(appro)s(c.c)30 b(source)g(\014le,)g (whic)m(h)g(will)g(allo)m(w)i(the)e(compiler)g(to)h(generate)h(co)s(de) e(using)f(the)h(SSSE3)f(instruction)0 4641 y(set.)41 b(A)28 b(con)m(v)m(enien)m(t)i(w)m(a)m(y)f(to)g(do)g(this)f(is)g(to)h (con\014gure)f(the)g(CFITSIO)f(library)h(with)g(the)g(follo)m(wing)i (command:)95 4928 y Fe(>)96 b(./configure)44 b(--enable-ssse3)0 5215 y Fj(Note,)37 b(ho)m(w)m(ev)m(er,)h(that)d(a)g(binary)f (executable)j(\014le)e(that)g(is)g(created)h(using)e(these)h(faster)g (functions)g(will)g(only)0 5328 y(run)29 b(on)h(mac)m(hines)h(that)g (supp)s(ort)e(the)h(SSSE3)f(mac)m(hine)i(instructions.)0 5488 y(F)-8 b(or)36 b(faster)f(2-b)m(yte)i(sw)m(aps)e(on)g(virtually)g (all)h(x86-64)h(CPUs)e(\(ev)m(en)h(those)g(that)f(do)g(not)h(supp)s (ort)d(SSSE3\),)j(a)0 5601 y(v)-5 b(arian)m(t)26 b(using)e(only)g(SSE2) g(instructions)h(exists.)39 b(SSE2)24 b(is)h(enabled)f(b)m(y)h(default) g(on)f(x86)p 3066 5601 28 4 v 34 w(64)h(CPUs)f(with)h(64-bit)0 5714 y(op)s(erating)30 b(systems)f(\(and)g(is)g(also)i(automatically)h (enabled)d(b)m(y)g(the)g({enable-ssse3)i(\015ag\).)41 b(When)30 b(running)d(on)p eop end %%Page: 169 177 TeXDict begin 169 176 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.169) cvn H.B /DEST pdfmark end 0 299 a Fh(13.2.)73 b(OPTIMIZA)-8 b(TION)29 b(STRA)-8 b(TEGIES)2186 b Fj(169)0 555 y(x86)p 143 555 28 4 v 34 w(64)31 b(CPUs)g(with)f(32-bit)i(op)s(erating)g (systems,)f(these)g(faster)h(2-b)m(yte)g(sw)m(apping)f(algorithms)g (are)h(not)f(used)0 668 y(b)m(y)f(default)h(in)f(CFITSIO,)f(but)h(can)g (b)s(e)g(enabled)g(explicitly)i(with:)0 951 y Fe(./configure)45 b(--enable-sse2)0 1234 y Fj(Preliminary)f(testing)h(indicates)g(that)g (these)f(SSSE3)f(and)g(SSE2)g(based)h(b)m(yte-sw)m(apping)h(algorithms) g(can)0 1347 y(b)s(o)s(ost)31 b(the)h(CFITSIO)e(p)s(erformance)h(when)f (reading)i(or)f(writing)h(FITS)f(images)h(b)m(y)g(20\045)g(-)g(30\045)g (or)f(more.)45 b(It)0 1460 y(is)36 b(imp)s(ortan)m(t)g(to)g(note,)i(ho) m(w)m(ev)m(er,)h(that)d(compiler)g(optimization)i(m)m(ust)e(b)s(e)f (turned)f(on)i(\(e.g.,)j(b)m(y)d(using)f(the)0 1573 y(-O1)f(or)g(-O2)g (\015ags)g(in)g(gcc\))h(when)e(building)g(programs)h(that)g(use)g (these)g(fast)g(b)m(yte-sw)m(apping)h(algorithms)f(in)0 1686 y(order)d(to)h(reap)f(the)h(full)f(b)s(ene\014t)g(of)g(the)h (SSSE3)e(and)h(SSE2)g(instructions;)h(without)f(optimization,)j(the)e (co)s(de)0 1799 y(ma)m(y)f(actually)h(run)d(slo)m(w)m(er)i(than)f(when) g(using)g(more)g(traditional)i(b)m(yte-sw)m(apping)f(tec)m(hniques.)0 1959 y(2.)54 b(When)34 b(dealing)h(with)g(a)g(FITS)e(primary)h(arra)m (y)h(or)g(IMA)m(GE)g(extension,)i(it)e(is)f(more)h(e\016cien)m(t)h(to)f (read)g(or)0 2072 y(write)c(large)g(c)m(h)m(unks)f(of)g(the)h(image)g (at)h(a)e(time)h(\(at)h(least)f(3)g(FITS)f(blo)s(c)m(ks)g(=)g(8640)i(b) m(ytes\))f(so)g(that)g(the)f(direct)0 2185 y(IO)j(mec)m(hanism)h(will)f (b)s(e)g(used)g(as)g(describ)s(ed)g(in)g(the)g(previous)g(section.)51 b(Smaller)34 b(c)m(h)m(unks)f(of)g(data)h(are)g(read)0 2298 y(or)d(written)g(via)h(the)f(IO)f(bu\013ers,)g(whic)m(h)h(is)g (somewhat)g(less)g(e\016cien)m(t)i(b)s(ecause)e(of)g(the)g(extra)h(cop) m(y)f(op)s(eration)0 2411 y(and)26 b(additional)h(b)s(o)s(okk)m(eeping) g(steps)g(that)g(are)g(required.)39 b(In)26 b(principle)g(it)h(is)g (more)f(e\016cien)m(t)i(to)g(read)e(or)h(write)0 2524 y(as)i(big)g(an)g(arra)m(y)h(of)f(image)h(pixels)f(at)h(one)f(time)g (as)h(p)s(ossible,)f(ho)m(w)m(ev)m(er,)h(if)f(the)h(arra)m(y)f(b)s (ecomes)g(so)g(large)h(that)0 2636 y(the)i(op)s(erating)g(system)f (cannot)h(store)g(it)g(all)h(in)e(RAM,)h(then)f(the)h(p)s(erformance)f (ma)m(y)h(b)s(e)f(degraded)g(b)s(ecause)0 2749 y(of)g(the)f(increased)h (sw)m(apping)f(of)g(virtual)h(memory)f(to)h(disk.)0 2910 y(3.)51 b(When)33 b(dealing)i(with)e(FITS)g(tables,)j(the)e(most)g(imp) s(ortan)m(t)g(e\016ciency)g(factor)h(in)e(the)h(soft)m(w)m(are)h (design)f(is)0 3022 y(to)j(read)f(or)g(write)g(the)g(data)h(in)f(the)g (FITS)g(\014le)g(in)g(a)g(single)h(pass)f(through)f(the)h(\014le.)58 b(An)36 b(example)h(of)f(p)s(o)s(or)0 3135 y(program)g(design)h(w)m (ould)f(b)s(e)g(to)h(read)g(a)f(large,)k(3-column)d(table)g(b)m(y)g (sequen)m(tially)h(reading)f(the)f(en)m(tire)i(\014rst)0 3248 y(column,)25 b(then)f(going)h(bac)m(k)f(to)h(read)e(the)h(2nd)g (column,)h(and)e(\014nally)h(the)g(3rd)f(column;)j(this)e(ob)m(viously) g(requires)0 3361 y(3)j(passes)g(through)g(the)g(\014le)g(whic)m(h)g (could)g(triple)g(the)h(execution)g(time)g(of)f(an)g(IO)f(limited)i (program.)40 b(F)-8 b(or)27 b(small)0 3474 y(tables)k(this)f(is)h(not)f (imp)s(ortan)m(t,)h(but)f(when)f(reading)h(m)m(ulti-megab)m(yte)j (sized)e(tables)g(these)g(ine\016ciencies)h(can)0 3587 y(b)s(ecome)d(signi\014can)m(t.)41 b(The)28 b(more)h(e\016cien)m(t)h (pro)s(cedure)d(in)i(this)f(case)i(is)e(to)i(read)e(or)h(write)g(only)f (as)h(man)m(y)g(ro)m(ws)0 3700 y(of)j(the)g(table)g(as)g(will)g(\014t)g (in)m(to)g(the)g(a)m(v)-5 b(ailable)34 b(in)m(ternal)e(IO)f(bu\013ers,) h(then)f(access)i(all)f(the)g(necessary)g(columns)0 3813 y(of)f(data)h(within)e(that)i(range)f(of)g(ro)m(ws.)43 b(Then)29 b(after)j(the)f(program)g(is)g(completely)h(\014nished)e (with)g(the)i(data)f(in)0 3926 y(those)i(ro)m(ws)e(it)i(can)f(mo)m(v)m (e)i(on)e(to)g(the)h(next)f(range)g(of)g(ro)m(ws)g(that)h(will)f(\014t) g(in)g(the)g(bu\013ers,)f(con)m(tin)m(uing)i(in)f(this)0 4039 y(w)m(a)m(y)c(un)m(til)f(the)f(en)m(tire)i(\014le)f(has)f(b)s(een) g(pro)s(cessed.)39 b(By)27 b(using)f(this)h(pro)s(cedure)e(of)i (accessing)h(all)g(the)e(columns)h(of)0 4152 y(a)j(table)g(in)f (parallel)h(rather)f(than)g(sequen)m(tially)-8 b(,)32 b(eac)m(h)e(blo)s(c)m(k)g(of)g(the)f(FITS)g(\014le)g(will)g(only)h(b)s (e)e(read)i(or)f(written)0 4264 y(once.)0 4425 y(The)g(optimal)h(n)m (um)m(b)s(er)e(of)i(ro)m(ws)f(to)i(read)e(or)g(write)h(at)g(one)g(time) g(in)f(a)h(giv)m(en)g(table)h(dep)s(ends)c(on)j(the)f(width)g(of)0 4538 y(the)c(table)h(ro)m(w)f(and)f(on)h(the)g(n)m(um)m(b)s(er)e(of)i (IO)g(bu\013ers)e(that)j(ha)m(v)m(e)g(b)s(een)e(allo)s(cated)j(in)e (CFITSIO.)e(The)h(CFITSIO)0 4650 y(Iterator)h(routine)f(will)g (automatically)j(use)c(the)h(optimal-sized)i(bu\013er,)e(but)g(there)g (is)g(also)g(a)h(CFITSIO)d(routine)0 4763 y(that)31 b(will)g(return)f (the)h(optimal)h(n)m(um)m(b)s(er)d(of)i(ro)m(ws)g(for)f(a)h(giv)m(en)h (table:)43 b(\014ts)p 2629 4763 V 32 w(get)p 2781 4763 V 34 w(ro)m(wsize.)g(It)31 b(is)g(not)g(critical)h(to)0 4876 y(use)h(exactly)j(the)e(v)-5 b(alue)34 b(of)g(nro)m(ws)f(returned) f(b)m(y)i(this)g(routine,)g(as)g(long)h(as)f(one)g(do)s(es)f(not)h (exceed)h(it.)51 b(Using)0 4989 y(a)37 b(v)m(ery)g(small)g(v)-5 b(alue)37 b(ho)m(w)m(ev)m(er)h(can)f(also)g(lead)g(to)h(p)s(o)s(or)d(p) s(erformance)h(b)s(ecause)g(of)h(the)g(o)m(v)m(erhead)h(from)e(the)0 5102 y(larger)31 b(n)m(um)m(b)s(er)e(of)i(subroutine)e(calls.)0 5262 y(The)36 b(optimal)h(n)m(um)m(b)s(er)e(of)h(ro)m(ws)g(returned)f (b)m(y)i(\014ts)p 1829 5262 V 32 w(get)p 1981 5262 V 34 w(ro)m(wsize)g(is)g(v)-5 b(alid)36 b(only)g(as)h(long)g(as)f(the)h (application)0 5375 y(program)27 b(is)g(only)g(reading)h(or)f(writing)g (data)h(in)f(the)g(sp)s(eci\014ed)f(table.)41 b(An)m(y)27 b(other)g(calls)i(to)f(access)g(data)g(in)f(the)0 5488 y(table)i(header)f(w)m(ould)f(cause)i(additional)g(blo)s(c)m(ks)f(of)g (data)g(to)h(b)s(e)e(loaded)i(in)m(to)g(the)f(IO)f(bu\013ers)g (displacing)h(data)0 5601 y(from)34 b(the)h(original)h(table,)h(and)d (should)f(b)s(e)h(a)m(v)m(oided)i(during)e(the)h(critical)h(p)s(erio)s (d)e(while)g(the)h(table)h(is)e(b)s(eing)0 5714 y(read)c(or)h(written.) p eop end %%Page: 170 178 TeXDict begin 170 177 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.170) cvn H.B /DEST pdfmark end 0 299 a Fj(170)1876 b Fh(CHAPTER)30 b(13.)112 b(OPTIMIZING)29 b(PR)m(OGRAMS)0 555 y Fj(4.)39 b(Use)25 b(the)g(CFITSIO)e(Iterator)j(routine.)39 b(This)24 b(routine)h(pro)m(vides)f(a)i(more)e(`ob)5 b(ject)26 b(orien)m(ted')g(w)m(a)m(y)g(of)f(reading)0 668 y(and)34 b(writing)g(FITS)g(\014les)g(whic)m(h)h(automatically)i(uses)d(the)g (most)h(appropriate)g(data)g(bu\013er)e(size)i(to)h(ac)m(hiev)m(e)0 781 y(the)31 b(maxim)m(um)f(I/O)g(throughput.)0 941 y(5.)39 b(Use)24 b(binary)f(table)h(extensions)g(rather)f(than)h(ASCI)s(I)e (table)i(extensions)g(for)f(b)s(etter)h(e\016ciency)h(when)d(dealing)0 1054 y(with)37 b(tabular)h(data.)62 b(The)37 b(I/O)g(to)h(ASCI)s(I)e (tables)i(is)g(slo)m(w)m(er)g(b)s(ecause)g(of)f(the)h(o)m(v)m(erhead)h (in)e(formatting)h(or)0 1167 y(parsing)32 b(the)g(ASCI)s(I)f(data)i (\014elds)f(and)g(b)s(ecause)g(ASCI)s(I)f(tables)i(are)g(ab)s(out)f(t)m (wice)i(as)f(large)g(as)g(binary)e(tables)0 1280 y(that)g(ha)m(v)m(e)h (the)e(same)h(information)g(con)m(ten)m(t.)0 1440 y(6.)64 b(Design)39 b(soft)m(w)m(are)g(so)g(that)f(it)h(reads)f(the)g(FITS)f (header)h(k)m(eyw)m(ords)g(in)g(the)g(same)h(order)e(in)h(whic)m(h)g (they)0 1553 y(o)s(ccur)28 b(in)h(the)g(\014le.)40 b(When)28 b(reading)h(k)m(eyw)m(ords,)h(CFITSIO)d(searc)m(hes)i(forw)m(ard)g (starting)g(from)f(the)h(p)s(osition)g(of)0 1666 y(the)g(last)i(k)m (eyw)m(ord)e(that)h(w)m(as)g(read.)40 b(If)29 b(it)g(reac)m(hes)i(the)e (end)g(of)g(the)h(header)f(without)g(\014nding)f(the)h(k)m(eyw)m(ord,)h (it)0 1779 y(then)j(go)s(es)h(bac)m(k)g(to)h(the)e(start)h(of)g(the)g (header)f(and)g(con)m(tin)m(ues)h(the)g(searc)m(h)g(do)m(wn)f(to)h(the) g(p)s(osition)f(where)g(it)0 1892 y(started.)41 b(In)30 b(practice,)i(as)e(long)h(as)g(the)f(en)m(tire)i(FITS)d(header)h(can)h (\014t)f(at)h(one)g(time)g(in)f(the)g(a)m(v)-5 b(ailable)33 b(in)m(ternal)0 2005 y(IO)23 b(bu\013ers,)i(then)e(the)i(header)e(k)m (eyw)m(ord)i(access)g(will)f(b)s(e)g(relativ)m(ely)i(fast)e(and)g(it)g (mak)m(es)h(little)h(di\013erence)e(whic)m(h)0 2118 y(order)30 b(they)g(are)h(accessed.)0 2278 y(7.)40 b(Av)m(oid)29 b(the)e(use)h(of)f(scaling)i(\(b)m(y)f(using)f(the)h(BSCALE)e(and)h (BZER)m(O)h(or)f(TSCAL)g(and)g(TZER)m(O)f(k)m(eyw)m(ords\))0 2391 y(in)35 b(FITS)f(\014les)g(since)i(the)f(scaling)h(op)s(erations)f (add)f(to)i(the)f(pro)s(cessing)f(time)i(needed)e(to)i(read)f(or)g (write)g(the)0 2503 y(data.)k(In)24 b(some)h(cases)h(it)f(ma)m(y)g(b)s (e)f(more)g(e\016cien)m(t)i(to)g(temp)s(orarily)e(turn)g(o\013)h(the)f (scaling)i(\(using)e(\014ts)p 3490 2503 28 4 v 33 w(set)p 3634 2503 V 33 w(bscale)0 2616 y(or)30 b(\014ts)p 238 2616 V 33 w(set)p 382 2616 V 33 w(tscale\))j(and)c(then)h(read)h(or)f (write)h(the)f(ra)m(w)h(unscaled)f(v)-5 b(alues)31 b(in)f(the)g(FITS)g (\014le.)0 2777 y(8.)77 b(Av)m(oid)43 b(using)f(the)h(`implicit)g(data) h(t)m(yp)s(e)e(con)m(v)m(ersion')i(capabilit)m(y)g(in)e(CFITSIO.)f(F)-8 b(or)44 b(instance,)i(when)0 2889 y(reading)28 b(a)g(FITS)f(image)i (with)e(BITPIX)h(=)f(-32)i(\(32-bit)g(\015oating)g(p)s(oin)m(t)f (pixels\),)h(read)e(the)h(data)g(in)m(to)h(a)f(single)0 3002 y(precision)40 b(\015oating)h(p)s(oin)m(t)f(data)h(arra)m(y)f(in)g (the)g(program.)69 b(F)-8 b(orcing)41 b(CFITSIO)e(to)i(con)m(v)m(ert)g (the)f(data)h(to)g(a)0 3115 y(di\013eren)m(t)31 b(data)g(t)m(yp)s(e)f (can)h(slo)m(w)g(the)g(program.)0 3275 y(9.)57 b(Where)36 b(feasible,)i(design)e(FITS)f(binary)g(tables)h(using)f(v)m(ector)j (column)d(elemen)m(ts)i(so)f(that)g(the)g(data)h(are)0 3388 y(written)30 b(as)g(a)g(con)m(tiguous)h(set)f(of)g(b)m(ytes,)g (rather)g(than)f(as)h(single)g(elemen)m(ts)h(in)f(m)m(ultiple)g(ro)m (ws.)41 b(F)-8 b(or)30 b(example,)0 3501 y(it)36 b(is)g(faster)g(to)g (access)h(the)f(data)h(in)e(a)h(table)h(that)f(con)m(tains)h(a)f (single)g(ro)m(w)g(and)f(2)h(columns)f(with)h(TF)m(ORM)0 3614 y(k)m(eyw)m(ords)d(equal)h(to)g('10000E')h(and)e('10000J',)j(than) d(it)g(is)g(to)h(access)g(the)g(same)f(amoun)m(t)h(of)f(data)h(in)f(a)g (table)0 3727 y(with)40 b(10000)j(ro)m(ws)d(whic)m(h)h(has)f(columns)g (with)g(the)h(TF)m(ORM)g(k)m(eyw)m(ords)g(equal)g(to)g('1E')h(and)e ('1J'.)h(In)f(the)0 3840 y(former)27 b(case)i(the)f(10000)i(\015oating) f(p)s(oin)m(t)f(v)-5 b(alues)28 b(in)g(the)g(\014rst)f(column)h(are)g (all)h(written)f(in)f(a)h(con)m(tiguous)h(blo)s(c)m(k)0 3953 y(of)d(the)f(\014le)h(whic)m(h)f(can)h(b)s(e)f(read)g(or)g (written)h(quic)m(kly)-8 b(,)28 b(whereas)d(in)g(the)h(second)f(case)i (eac)m(h)g(\015oating)f(p)s(oin)m(t)f(v)-5 b(alue)0 4066 y(in)34 b(the)g(\014rst)f(column)g(is)h(in)m(terlea)m(v)m(ed)j(with)c (the)h(in)m(teger)i(v)-5 b(alue)34 b(in)g(the)g(second)g(column)f(of)h (the)g(same)h(ro)m(w)f(so)0 4179 y(CFITSIO)29 b(has)h(to)h(explicitly)h (mo)m(v)m(e)g(to)f(the)g(p)s(osition)f(of)h(eac)m(h)g(elemen)m(t)h(to)f (b)s(e)f(read)g(or)g(written.)0 4339 y(10.)45 b(Av)m(oid)33 b(the)f(use)f(of)h(v)-5 b(ariable)32 b(length)g(v)m(ector)h(columns)f (in)f(binary)g(tables,)i(since)f(an)m(y)g(reading)f(or)h(writing)0 4452 y(of)h(these)g(data)g(requires)f(that)h(CFITSIO)f(\014rst)f(lo)s (ok)j(up)d(or)i(compute)g(the)f(starting)i(address)e(of)g(eac)m(h)i(ro) m(w)f(of)0 4565 y(data)e(in)f(the)h(heap.)40 b(In)30 b(practice,)i(this)e(is)g(probably)g(not)h(a)f(signi\014can)m(t)i (e\016ciency)f(issue.)0 4725 y(11.)73 b(When)40 b(cop)m(ying)i(data)g (from)e(one)h(FITS)f(table)i(to)f(another,)j(it)e(is)e(faster)i(to)f (transfer)g(the)f(ra)m(w)h(b)m(ytes)0 4838 y(instead)28 b(of)h(reading)f(then)g(writing)g(eac)m(h)h(column)f(of)g(the)g(table.) 41 b(The)28 b(CFITSIO)e(routines)i(\014ts)p 3349 4838 V 33 w(read)p 3554 4838 V 32 w(tblb)m(ytes)0 4951 y(and)36 b(\014ts)p 310 4951 V 32 w(write)p 544 4951 V 33 w(tblb)m(ytes)i(will)f (p)s(erform)e(lo)m(w-lev)m(el)k(reads)e(or)f(writes)h(of)g(an)m(y)g (con)m(tiguous)g(range)g(of)g(b)m(ytes)g(in)0 5064 y(a)d(table)g (extension.)51 b(These)33 b(routines)h(can)f(b)s(e)g(used)g(to)h(read)f (or)h(write)g(a)f(whole)h(ro)m(w)g(\(or)g(m)m(ultiple)g(ro)m(ws)f(for)0 5176 y(ev)m(en)e(greater)h(e\016ciency\))h(of)e(a)g(table)h(with)e(a)h (single)h(function)e(call.)43 b(These)31 b(routines)g(are)g(fast)g(b)s (ecause)g(they)0 5289 y(b)m(ypass)36 b(all)h(the)g(usual)f(data)h (scaling,)i(error)d(c)m(hec)m(king)i(and)e(mac)m(hine)h(dep)s(enden)m (t)e(data)i(con)m(v)m(ersion)h(that)f(is)0 5402 y(normally)g(done)g(b)m (y)f(CFITSIO,)g(and)g(they)h(allo)m(w)h(the)g(program)e(to)i(write)f (the)g(data)g(to)h(the)f(output)f(\014le)h(in)0 5515 y(exactly)30 b(the)e(same)h(b)m(yte)g(order.)40 b(F)-8 b(or)29 b(these)f(same)h(reasons,)g(these)g(routines)f(can)g(corrupt)g (the)g(FITS)g(data)h(\014le)0 5628 y(if)36 b(used)e(incorrectly)j(b)s (ecause)f(no)f(v)-5 b(alidation)37 b(or)f(mac)m(hine)g(dep)s(enden)m(t) e(con)m(v)m(ersion)j(is)f(p)s(erformed)e(b)m(y)h(these)p eop end %%Page: 171 179 TeXDict begin 171 178 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.171) cvn H.B /DEST pdfmark end 0 299 a Fh(13.2.)73 b(OPTIMIZA)-8 b(TION)29 b(STRA)-8 b(TEGIES)2186 b Fj(171)0 555 y(routines.)55 b(These)35 b(routines)g(are)h(only)f(recommended)g(for)g(optimizing)h (critical)h(pieces)f(of)g(co)s(de)f(and)g(should)0 668 y(only)e(b)s(e)g(used)g(b)m(y)g(programmers)g(who)g(thoroughly)g (understand)e(the)j(in)m(ternal)g(format)g(of)f(the)h(FITS)e(tables)0 781 y(they)f(are)f(reading)h(or)f(writing.)0 941 y(12.)41 b(Another)30 b(strategy)g(for)g(impro)m(ving)f(the)h(sp)s(eed)e(of)i (writing)g(a)f(FITS)g(table,)i(similar)f(to)g(the)f(previous)g(one,)0 1054 y(is)j(to)g(directly)h(construct)f(the)f(en)m(tire)i(b)m(yte)f (stream)g(for)g(a)g(whole)g(table)g(ro)m(w)g(\(or)g(m)m(ultiple)h(ro)m (ws\))f(within)f(the)0 1167 y(application)g(program)e(and)g(then)h (write)g(it)g(to)g(the)g(FITS)f(\014le)h(with)f(\014ts)p 2520 1167 28 4 v 32 w(write)p 2754 1167 V 33 w(tblb)m(ytes.)41 b(This)29 b(a)m(v)m(oids)i(all)g(the)0 1280 y(o)m(v)m(erhead)f (normally)g(presen)m(t)f(in)g(the)h(column-orien)m(ted)g(CFITSIO)e (write)h(routines.)40 b(This)29 b(tec)m(hnique)h(should)0 1393 y(only)35 b(b)s(e)e(used)h(for)g(critical)i(applications)g(b)s (ecause)e(it)h(mak)m(es)h(the)e(co)s(de)h(more)f(di\016cult)h(to)g (understand)e(and)0 1506 y(main)m(tain,)38 b(and)d(it)h(mak)m(es)g(the) g(co)s(de)f(more)h(system)g(dep)s(enden)m(t)e(\(e.g.,)39 b(do)c(the)h(b)m(ytes)g(need)f(to)h(b)s(e)f(sw)m(app)s(ed)0 1619 y(b)s(efore)30 b(writing)g(to)h(the)g(FITS)f(\014le?\).)0 1779 y(13.)40 b(Finally)-8 b(,)29 b(external)e(factors)g(suc)m(h)e(as)i (the)f(sp)s(eed)f(of)i(the)f(data)h(storage)g(device,)h(the)f(size)g (of)f(the)g(data)h(cac)m(he,)0 1892 y(the)34 b(amoun)m(t)h(of)f(disk)g (fragmen)m(tation,)j(and)c(the)i(amoun)m(t)f(of)h(RAM)f(a)m(v)-5 b(ailable)37 b(on)d(the)g(system)g(can)h(all)g(ha)m(v)m(e)0 2005 y(a)k(signi\014can)m(t)g(impact)g(on)f(o)m(v)m(erall)j(I/O)d (e\016ciency)-8 b(.)66 b(F)-8 b(or)39 b(critical)h(applications,)i(the) c(en)m(tire)i(hardw)m(are)e(and)0 2118 y(soft)m(w)m(are)32 b(system)e(should)g(b)s(e)f(review)m(ed)i(to)h(iden)m(tify)e(an)m(y)h (p)s(oten)m(tial)h(I/O)e(b)s(ottlenec)m(ks.)p eop end %%Page: 172 180 TeXDict begin 172 179 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.172) cvn H.B /DEST pdfmark end 0 299 a Fj(172)1876 b Fh(CHAPTER)30 b(13.)112 b(OPTIMIZING)29 b(PR)m(OGRAMS)p eop end %%Page: 173 181 TeXDict begin 173 180 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.173) cvn H.B /DEST pdfmark end 0 299 a 0 464 a SDict begin H.S end 0 464 a 0 464 a SDict begin 13.6 H.A end 0 464 a 0 464 a SDict begin [ /View [/XYZ H.V] /Dest (appendix.A) cvn H.B /DEST pdfmark end 0 464 a 761 x Fg(App)5 b(endix)64 b(A)0 1687 y Fm(Index)77 b(of)h(Routines)50 2154 y Fj(\014ts)p 177 2154 28 4 v 32 w(add)p 356 2154 V 32 w(group)p 616 2154 V 33 w(mem)m(b)s(er)1208 2154 y SDict begin H.S end 1208 2154 a Fj(92)1299 2096 y SDict begin H.R end 1299 2096 a 1299 2154 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.1) cvn H.B /ANN pdfmark end 1299 2154 a 50 2267 a Fj(\014ts)p 177 2267 28 4 v 32 w(ascii)p 380 2267 V 34 w(tform)1208 2267 y SDict begin H.S end 1208 2267 a Fj(70)1299 2208 y SDict begin H.R end 1299 2208 a 1299 2267 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 1299 2267 a 50 2380 a Fj(\014ts)p 177 2380 28 4 v 32 w(binary)p 465 2380 V 32 w(tform)1208 2380 y SDict begin H.S end 1208 2380 a Fj(70)1299 2321 y SDict begin H.R end 1299 2321 a 1299 2380 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 1299 2380 a 50 2493 a Fj(\014ts)p 177 2493 28 4 v 32 w(calculator)1208 2493 y SDict begin H.S end 1208 2493 a Fj(60)1299 2434 y SDict begin H.R end 1299 2434 a 1299 2493 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.5) cvn H.B /ANN pdfmark end 1299 2493 a 50 2606 a Fj(\014ts)p 177 2606 28 4 v 32 w(calculator)p 596 2606 V 35 w(rng)1208 2606 y SDict begin H.S end 1208 2606 a Fj(60)1299 2547 y SDict begin H.R end 1299 2547 a 1299 2606 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.5) cvn H.B /ANN pdfmark end 1299 2606 a 50 2719 a Fj(\014ts)p 177 2719 28 4 v 32 w(calc)p 359 2719 V 35 w(binning)1208 2719 y SDict begin H.S end 1208 2719 a Fj(61)1299 2660 y SDict begin H.R end 1299 2660 a 1299 2719 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.6) cvn H.B /ANN pdfmark end 1299 2719 a 50 2832 a Fj(\014ts)p 177 2832 28 4 v 32 w(calc)p 359 2832 V 35 w(ro)m(ws)1208 2832 y SDict begin H.S end 1208 2832 a Fj(60)1299 2773 y SDict begin H.R end 1299 2773 a 1299 2832 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.5) cvn H.B /ANN pdfmark end 1299 2832 a 50 2945 a Fj(\014ts)p 177 2945 28 4 v 32 w(c)m(hange)p 478 2945 V 34 w(group)1208 2945 y SDict begin H.S end 1208 2945 a Fj(90)1299 2886 y SDict begin H.R end 1299 2886 a 1299 2945 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.1) cvn H.B /ANN pdfmark end 1299 2945 a 50 3057 a Fj(\014ts)p 177 3057 28 4 v 32 w(clean)m(up)p 509 3057 V 33 w(h)m(ttps)1208 3057 y SDict begin H.S end 1208 3057 a Fj(99)1299 2999 y SDict begin H.R end 1299 2999 a 1299 3057 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.1) cvn H.B /ANN pdfmark end 1299 3057 a 50 3170 a Fj(\014ts)p 177 3170 28 4 v 32 w(clear)p 395 3170 V 34 w(errmark)1208 3170 y SDict begin H.S end 1208 3170 a Fj(32)1299 3112 y SDict begin H.R end 1299 3112 a 1299 3170 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.1) cvn H.B /ANN pdfmark end 1299 3170 a 50 3283 a Fj(\014ts)p 177 3283 28 4 v 32 w(clear)p 395 3283 V 34 w(errmsg)1208 3283 y SDict begin H.S end 1208 3283 a Fj(32)1299 3225 y SDict begin H.R end 1299 3225 a 1299 3283 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.1) cvn H.B /ANN pdfmark end 1299 3283 a 50 3396 a Fj(\014ts)p 177 3396 28 4 v 32 w(close)p 395 3396 V 34 w(\014le)1208 3396 y SDict begin H.S end 1208 3396 a Fj(35)1299 3338 y SDict begin H.R end 1299 3338 a 1299 3396 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.2) cvn H.B /ANN pdfmark end 1299 3396 a 50 3509 a Fj(\014ts)p 177 3509 28 4 v 32 w(compact)p 541 3509 V 34 w(group)1208 3509 y SDict begin H.S end 1208 3509 a Fj(91)1299 3450 y SDict begin H.R end 1299 3450 a 1299 3509 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.1) cvn H.B /ANN pdfmark end 1299 3509 a 50 3622 a Fj(\014ts)p 177 3622 28 4 v 32 w(compare)p 542 3622 V 34 w(str)1208 3622 y SDict begin H.S end 1208 3622 a Fj(66)1299 3563 y SDict begin H.R end 1299 3563 a 1299 3622 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 1299 3622 a 50 3735 a Fj(\014ts)p 177 3735 28 4 v 32 w(compress)p 569 3735 V 33 w(heap)1163 3735 y SDict begin H.S end 1163 3735 a Fj(116)1299 3676 y SDict begin H.R end 1299 3676 a 1299 3735 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.1) cvn H.B /ANN pdfmark end 1299 3735 a 50 3848 a Fj(\014ts)p 177 3848 28 4 v 32 w(con)m(v)m(ert)p 498 3848 V 35 w(hdr2str)1062 3848 y SDict begin H.S end 1062 3848 a Fj(40)1153 3789 y SDict begin H.R end 1153 3789 a 1153 3848 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.1) cvn H.B /ANN pdfmark end 1153 3848 a Fj(,)1208 3848 y SDict begin H.S end 1208 3848 a Fj(86)1299 3789 y SDict begin H.R end 1299 3789 a 1299 3848 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (chapter.7) cvn H.B /ANN pdfmark end 1299 3848 a 50 3961 a Fj(\014ts)p 177 3961 28 4 v 32 w(cop)m(y)p 390 3961 V 34 w(cell2image)1208 3961 y SDict begin H.S end 1208 3961 a Fj(44)1299 3902 y SDict begin H.R end 1299 3902 a 1299 3961 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 1299 3961 a 50 4074 a Fj(\014ts)p 177 4074 28 4 v 32 w(cop)m(y)p 390 4074 V 34 w(col)1208 4074 y SDict begin H.S end 1208 4074 a Fj(57)1299 4015 y SDict begin H.R end 1299 4015 a 1299 4074 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.3) cvn H.B /ANN pdfmark end 1299 4074 a 50 4187 a Fj(\014ts)p 177 4187 28 4 v 32 w(cop)m(y)p 390 4187 V 34 w(data)1163 4187 y SDict begin H.S end 1163 4187 a Fj(101)1299 4128 y SDict begin H.R end 1299 4128 a 1299 4187 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.2) cvn H.B /ANN pdfmark end 1299 4187 a 50 4299 a Fj(\014ts)p 177 4299 28 4 v 32 w(cop)m(y)p 390 4299 V 34 w(\014le)1208 4299 y SDict begin H.S end 1208 4299 a Fj(36)1299 4241 y SDict begin H.R end 1299 4241 a 1299 4299 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.3) cvn H.B /ANN pdfmark end 1299 4299 a 50 4412 a Fj(\014ts)p 177 4412 28 4 v 32 w(cop)m(y)p 390 4412 V 34 w(group)1208 4412 y SDict begin H.S end 1208 4412 a Fj(91)1299 4354 y SDict begin H.R end 1299 4354 a 1299 4412 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.1) cvn H.B /ANN pdfmark end 1299 4412 a 50 4525 a Fj(\014ts)p 177 4525 28 4 v 32 w(cop)m(y)p 390 4525 V 34 w(hdu)1208 4525 y SDict begin H.S end 1208 4525 a Fj(37)1299 4467 y SDict begin H.R end 1299 4467 a 1299 4525 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.3) cvn H.B /ANN pdfmark end 1299 4525 a 50 4638 a Fj(\014ts)p 177 4638 28 4 v 32 w(cop)m(y)p 390 4638 V 34 w(header)1208 4638 y SDict begin H.S end 1208 4638 a Fj(37)1299 4580 y SDict begin H.R end 1299 4580 a 1299 4638 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.3) cvn H.B /ANN pdfmark end 1299 4638 a 50 4751 a Fj(\014ts)p 177 4751 28 4 v 32 w(cop)m(y)p 390 4751 V 34 w(image2cell)1208 4751 y SDict begin H.S end 1208 4751 a Fj(44)1299 4692 y SDict begin H.R end 1299 4692 a 1299 4751 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 1299 4751 a 50 4864 a Fj(\014ts)p 177 4864 28 4 v 32 w(cop)m(y)p 390 4864 V 34 w(image)p 655 4864 V 34 w(section)1208 4864 y SDict begin H.S end 1208 4864 a Fj(47)1299 4805 y SDict begin H.R end 1299 4805 a 1299 4864 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 1299 4864 a 50 4977 a Fj(\014ts)p 177 4977 28 4 v 32 w(cop)m(y)p 390 4977 V 34 w(k)m(ey)1163 4977 y SDict begin H.S end 1163 4977 a Fj(106)1299 4918 y SDict begin H.R end 1299 4918 a 1299 4977 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.3) cvn H.B /ANN pdfmark end 1299 4977 a 50 5090 a Fj(\014ts)p 177 5090 28 4 v 32 w(cop)m(y)p 390 5090 V 34 w(mem)m(b)s(er)1208 5090 y SDict begin H.S end 1208 5090 a Fj(93)1299 5031 y SDict begin H.R end 1299 5031 a 1299 5090 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.2) cvn H.B /ANN pdfmark end 1299 5090 a 50 5203 a Fj(\014ts)p 177 5203 28 4 v 32 w(cop)m(y)p 390 5203 V 34 w(pixlist2image)1208 5203 y SDict begin H.S end 1208 5203 a Fj(62)1299 5144 y SDict begin H.R end 1299 5144 a 1299 5203 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.6) cvn H.B /ANN pdfmark end 1299 5203 a 50 5316 a Fj(\014ts)p 177 5316 28 4 v 32 w(cop)m(y)p 390 5316 V 34 w(ro)m(ws)1208 5316 y SDict begin H.S end 1208 5316 a Fj(57)1299 5257 y SDict begin H.R end 1299 5257 a 1299 5316 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.3) cvn H.B /ANN pdfmark end 1299 5316 a 50 5429 a Fj(\014ts)p 177 5429 28 4 v 32 w(create)p 445 5429 V 35 w(disk\014le)1208 5429 y SDict begin H.S end 1208 5429 a Fj(34)1299 5370 y SDict begin H.R end 1299 5370 a 1299 5429 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.2) cvn H.B /ANN pdfmark end 1299 5429 a 50 5541 a Fj(\014ts)p 177 5541 28 4 v 32 w(create)p 445 5541 V 35 w(\014le)1208 5541 y SDict begin H.S end 1208 5541 a Fj(34)1299 5483 y SDict begin H.R end 1299 5483 a 1299 5541 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.2) cvn H.B /ANN pdfmark end 1299 5541 a 50 5654 a Fj(\014ts)p 177 5654 28 4 v 32 w(create)p 445 5654 V 35 w(group)1208 5654 y SDict begin H.S end 1208 5654 a Fj(90)1299 5596 y SDict begin H.R end 1299 5596 a 1299 5654 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.1) cvn H.B /ANN pdfmark end 1299 5654 a 1419 2154 a Fj(\014ts)p 1546 2154 28 4 v 32 w(create)p 1814 2154 V 35 w(hdu)2701 2154 y SDict begin H.S end 2701 2154 a Fj(99)2792 2096 y SDict begin H.R end 2792 2096 a 2792 2154 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.2) cvn H.B /ANN pdfmark end 2792 2154 a 1419 2267 a Fj(\014ts)p 1546 2267 28 4 v 32 w(create)p 1814 2267 V 35 w(img)2701 2267 y SDict begin H.S end 2701 2267 a Fj(44)2792 2208 y SDict begin H.R end 2792 2208 a 2792 2267 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 2792 2267 a 1419 2380 a Fj(\014ts)p 1546 2380 28 4 v 32 w(create)p 1814 2380 V 35 w(mem\014le)2701 2380 y SDict begin H.S end 2701 2380 a Fj(96)2792 2321 y SDict begin H.R end 2792 2321 a 2792 2380 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.1) cvn H.B /ANN pdfmark end 2792 2380 a 1419 2493 a Fj(\014ts)p 1546 2493 28 4 v 32 w(create)p 1814 2493 V 35 w(tbl)2701 2493 y SDict begin H.S end 2701 2493 a Fj(52)2792 2434 y SDict begin H.R end 2792 2434 a 2792 2493 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.1) cvn H.B /ANN pdfmark end 2792 2493 a 1419 2606 a Fj(\014ts)p 1546 2606 28 4 v 32 w(create)p 1814 2606 V 35 w(template)2701 2606 y SDict begin H.S end 2701 2606 a Fj(96)2792 2547 y SDict begin H.R end 2792 2547 a 2792 2606 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.1) cvn H.B /ANN pdfmark end 2792 2606 a 1419 2719 a Fj(\014ts)p 1546 2719 28 4 v 32 w(date2str)2701 2719 y SDict begin H.S end 2701 2719 a Fj(65)2792 2660 y SDict begin H.R end 2792 2660 a 2792 2719 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.2) cvn H.B /ANN pdfmark end 2792 2719 a 1419 2832 a Fj(\014ts)p 1546 2832 28 4 v 32 w(deco)s(de)p 1848 2832 V 33 w(c)m(hksum)2701 2832 y SDict begin H.S end 2701 2832 a Fj(64)2792 2773 y SDict begin H.R end 2792 2773 a 2792 2832 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.1) cvn H.B /ANN pdfmark end 2792 2832 a 1419 2945 a Fj(\014ts)p 1546 2945 28 4 v 32 w(deco)s(de)p 1848 2945 V 33 w(tdim)2701 2945 y SDict begin H.S end 2701 2945 a Fj(55)2792 2886 y SDict begin H.R end 2792 2886 a 2792 2945 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.2) cvn H.B /ANN pdfmark end 2792 2945 a 1419 3057 a Fj(\014ts)p 1546 3057 28 4 v 32 w(delete)p 1809 3057 V 34 w(col)2701 3057 y SDict begin H.S end 2701 3057 a Fj(56)2792 2999 y SDict begin H.R end 2792 2999 a 2792 3057 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.3) cvn H.B /ANN pdfmark end 2792 3057 a 1419 3170 a Fj(\014ts)p 1546 3170 28 4 v 32 w(delete)p 1809 3170 V 34 w(\014le)2701 3170 y SDict begin H.S end 2701 3170 a Fj(35)2792 3112 y SDict begin H.R end 2792 3112 a 2792 3170 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.2) cvn H.B /ANN pdfmark end 2792 3170 a 1419 3283 a Fj(\014ts)p 1546 3283 28 4 v 32 w(delete)p 1809 3283 V 34 w(hdu)2701 3283 y SDict begin H.S end 2701 3283 a Fj(37)2792 3225 y SDict begin H.R end 2792 3225 a 2792 3283 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.3) cvn H.B /ANN pdfmark end 2792 3283 a 1419 3396 a Fj(\014ts)p 1546 3396 28 4 v 32 w(delete)p 1809 3396 V 34 w(k)m(ey)2701 3396 y SDict begin H.S end 2701 3396 a Fj(42)2792 3338 y SDict begin H.R end 2792 3338 a 2792 3396 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 2792 3396 a 1419 3509 a Fj(\014ts)p 1546 3509 28 4 v 32 w(delete)p 1809 3509 V 34 w(record)2701 3509 y SDict begin H.S end 2701 3509 a Fj(42)2792 3450 y SDict begin H.R end 2792 3450 a 2792 3509 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 2792 3509 a 1419 3622 a Fj(\014ts)p 1546 3622 28 4 v 32 w(delete)p 1809 3622 V 34 w(ro)m(wlist)2701 3622 y SDict begin H.S end 2701 3622 a Fj(56)2792 3563 y SDict begin H.R end 2792 3563 a 2792 3622 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.3) cvn H.B /ANN pdfmark end 2792 3622 a 1419 3735 a Fj(\014ts)p 1546 3735 28 4 v 32 w(delete)p 1809 3735 V 34 w(ro)m(wrange)2701 3735 y SDict begin H.S end 2701 3735 a Fj(56)2792 3676 y SDict begin H.R end 2792 3676 a 2792 3735 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.3) cvn H.B /ANN pdfmark end 2792 3735 a 1419 3848 a Fj(\014ts)p 1546 3848 28 4 v 32 w(delete)p 1809 3848 V 34 w(ro)m(ws)2701 3848 y SDict begin H.S end 2701 3848 a Fj(56)2792 3789 y SDict begin H.R end 2792 3789 a 2792 3848 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.3) cvn H.B /ANN pdfmark end 2792 3848 a 1419 3961 a Fj(\014ts)p 1546 3961 28 4 v 32 w(delete)p 1809 3961 V 34 w(str)2701 3961 y SDict begin H.S end 2701 3961 a Fj(42)2792 3902 y SDict begin H.R end 2792 3902 a 2792 3961 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 2792 3961 a 1419 4074 a Fj(\014ts)p 1546 4074 28 4 v 32 w(enco)s(de)p 1848 4074 V 33 w(c)m(hksum)2701 4074 y SDict begin H.S end 2701 4074 a Fj(64)2792 4015 y SDict begin H.R end 2792 4015 a 2792 4074 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.1) cvn H.B /ANN pdfmark end 2792 4074 a 1419 4187 a Fj(\014ts)p 1546 4187 28 4 v 32 w(\014le)p 1694 4187 V 33 w(exists)2701 4187 y SDict begin H.S end 2701 4187 a Fj(98)2792 4128 y SDict begin H.R end 2792 4128 a 2792 4187 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.1) cvn H.B /ANN pdfmark end 2792 4187 a 1419 4299 a Fj(\014ts)p 1546 4299 28 4 v 32 w(\014le)p 1694 4299 V 33 w(mo)s(de)2701 4299 y SDict begin H.S end 2701 4299 a Fj(35)2792 4241 y SDict begin H.R end 2792 4241 a 2792 4299 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.2) cvn H.B /ANN pdfmark end 2792 4299 a 1419 4412 a Fj(\014ts)p 1546 4412 28 4 v 32 w(\014le)p 1694 4412 V 33 w(name)2701 4412 y SDict begin H.S end 2701 4412 a Fj(35)2792 4354 y SDict begin H.R end 2792 4354 a 2792 4412 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.2) cvn H.B /ANN pdfmark end 2792 4412 a 1419 4525 a Fj(\014ts)p 1546 4525 28 4 v 32 w(\014nd)p 1731 4525 V 32 w(\014rst)p 1921 4525 V 32 w(ro)m(w)2701 4525 y SDict begin H.S end 2701 4525 a Fj(60)2792 4467 y SDict begin H.R end 2792 4467 a 2792 4525 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.5) cvn H.B /ANN pdfmark end 2792 4525 a 1419 4638 a Fj(\014ts)p 1546 4638 28 4 v 32 w(\014nd)p 1731 4638 V 32 w(nextk)m(ey)2701 4638 y SDict begin H.S end 2701 4638 a Fj(39)2792 4580 y SDict begin H.R end 2792 4580 a 2792 4638 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.1) cvn H.B /ANN pdfmark end 2792 4638 a 1419 4751 a Fj(\014ts)p 1546 4751 28 4 v 32 w(\014nd)p 1731 4751 V 32 w(ro)m(ws)2701 4751 y SDict begin H.S end 2701 4751 a Fj(59)2792 4692 y SDict begin H.R end 2792 4692 a 2792 4751 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.5) cvn H.B /ANN pdfmark end 2792 4751 a 1419 4864 a Fj(\014ts)p 1546 4864 28 4 v 32 w(\015ush)p 1767 4864 V 32 w(bu\013er)2701 4864 y SDict begin H.S end 2701 4864 a Fj(98)2792 4805 y SDict begin H.R end 2792 4805 a 2792 4864 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.1) cvn H.B /ANN pdfmark end 2792 4864 a 1419 4977 a Fj(\014ts)p 1546 4977 28 4 v 32 w(\015ush)p 1767 4977 V 32 w(\014le)2701 4977 y SDict begin H.S end 2701 4977 a Fj(98)2792 4918 y SDict begin H.R end 2792 4918 a 2792 4977 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.1) cvn H.B /ANN pdfmark end 2792 4977 a 1419 5090 a Fj(\014ts)p 1546 5090 28 4 v 32 w(free)p 1722 5090 V 33 w(memory)2509 5090 y SDict begin H.S end 2509 5090 a Fj(107)2645 5031 y SDict begin H.R end 2645 5031 a 2645 5090 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.5) cvn H.B /ANN pdfmark end 2645 5090 a Fj(,)2701 5090 y SDict begin H.S end 2701 5090 a Fj(40)2792 5031 y SDict begin H.R end 2792 5031 a 2792 5090 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.1) cvn H.B /ANN pdfmark end 2792 5090 a 1419 5203 a Fj(\014ts)p 1546 5203 28 4 v 32 w(get)p 1698 5203 V 34 w(acolparms)2656 5203 y SDict begin H.S end 2656 5203 a Fj(115)2792 5144 y SDict begin H.R end 2792 5144 a 2792 5203 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.1) cvn H.B /ANN pdfmark end 2792 5203 a 1419 5316 a Fj(\014ts)p 1546 5316 28 4 v 32 w(get)p 1698 5316 V 34 w(b)s(colparms)2656 5316 y SDict begin H.S end 2656 5316 a Fj(115)2792 5257 y SDict begin H.R end 2792 5257 a 2792 5316 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.1) cvn H.B /ANN pdfmark end 2792 5316 a 1419 5429 a Fj(\014ts)p 1546 5429 28 4 v 32 w(get)p 1698 5429 V 34 w(c)m(hksum)2701 5429 y SDict begin H.S end 2701 5429 a Fj(64)2792 5370 y SDict begin H.R end 2792 5370 a 2792 5429 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.1) cvn H.B /ANN pdfmark end 2792 5429 a 1419 5541 a Fj(\014ts)p 1546 5541 28 4 v 32 w(get)p 1698 5541 V 34 w(col)p 1842 5541 V 34 w(displa)m(y)p 2154 5541 V 33 w(width)2701 5541 y SDict begin H.S end 2701 5541 a Fj(55)2792 5483 y SDict begin H.R end 2792 5483 a 2792 5541 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.2) cvn H.B /ANN pdfmark end 2792 5541 a 1419 5654 a Fj(\014ts)p 1546 5654 28 4 v 32 w(get)p 1698 5654 V 34 w(colname)2701 5654 y SDict begin H.S end 2701 5654 a Fj(53)2792 5596 y SDict begin H.R end 2792 5596 a 2792 5654 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.2) cvn H.B /ANN pdfmark end 2792 5654 a 2912 2154 a Fj(\014ts)p 3039 2154 28 4 v 32 w(get)p 3191 2154 V 34 w(coln)m(um)4053 2154 y SDict begin H.S end 4053 2154 a Fj(53)4144 2096 y SDict begin H.R end 4144 2096 a 4144 2154 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.2) cvn H.B /ANN pdfmark end 4144 2154 a 2912 2267 a Fj(\014ts)p 3039 2267 28 4 v 32 w(get)p 3191 2267 V 34 w(colt)m(yp)s(e)4053 2267 y SDict begin H.S end 4053 2267 a Fj(54)4144 2208 y SDict begin H.R end 4144 2208 a 4144 2267 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.2) cvn H.B /ANN pdfmark end 4144 2267 a 2912 2380 a Fj(\014ts)p 3039 2380 28 4 v 32 w(get)p 3191 2380 V 34 w(compression)p 3706 2380 V 33 w(t)m(yp)s(e)4053 2380 y SDict begin H.S end 4053 2380 a Fj(50)4144 2321 y SDict begin H.R end 4144 2321 a 4144 2380 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.6) cvn H.B /ANN pdfmark end 4144 2380 a 2912 2493 a Fj(\014ts)p 3039 2493 28 4 v 32 w(get)p 3191 2493 V 34 w(eqcolt)m(yp)s(e)4053 2493 y SDict begin H.S end 4053 2493 a Fj(54)4144 2434 y SDict begin H.R end 4144 2434 a 4144 2493 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.2) cvn H.B /ANN pdfmark end 4144 2493 a 2912 2606 a Fj(\014ts)p 3039 2606 28 4 v 32 w(get)p 3191 2606 V 34 w(errstatus)4053 2606 y SDict begin H.S end 4053 2606 a Fj(31)4144 2547 y SDict begin H.R end 4144 2547 a 4144 2606 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.1) cvn H.B /ANN pdfmark end 4144 2606 a 2912 2719 a Fj(\014ts)p 3039 2719 28 4 v 32 w(get)p 3191 2719 V 34 w(hdrp)s(os)4008 2719 y SDict begin H.S end 4008 2719 a Fj(102)4144 2660 y SDict begin H.R end 4144 2660 a 4144 2719 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.1) cvn H.B /ANN pdfmark end 4144 2719 a 2912 2832 a Fj(\014ts)p 3039 2832 28 4 v 32 w(get)p 3191 2832 V 34 w(hdrspace)4053 2832 y SDict begin H.S end 4053 2832 a Fj(38)4144 2773 y SDict begin H.R end 4144 2773 a 4144 2832 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.1) cvn H.B /ANN pdfmark end 4144 2832 a 2912 2945 a Fj(\014ts)p 3039 2945 28 4 v 32 w(get)p 3191 2945 V 34 w(hdu)p 3378 2945 V 31 w(n)m(um)4053 2945 y SDict begin H.S end 4053 2945 a Fj(36)4144 2886 y SDict begin H.R end 4144 2886 a 4144 2945 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.3) cvn H.B /ANN pdfmark end 4144 2945 a 2912 3057 a Fj(\014ts)p 3039 3057 28 4 v 32 w(get)p 3191 3057 V 34 w(hdu)p 3378 3057 V 31 w(t)m(yp)s(e)4053 3057 y SDict begin H.S end 4053 3057 a Fj(36)4144 2999 y SDict begin H.R end 4144 2999 a 4144 3057 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.3) cvn H.B /ANN pdfmark end 4144 3057 a 2912 3170 a Fj(\014ts)p 3039 3170 28 4 v 32 w(get)p 3191 3170 V 34 w(hduaddr)4053 3170 y SDict begin H.S end 4053 3170 a Fj(99)4144 3112 y SDict begin H.R end 4144 3112 a 4144 3170 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.2) cvn H.B /ANN pdfmark end 4144 3170 a 2912 3283 a Fj(\014ts)p 3039 3283 28 4 v 32 w(get)p 3191 3283 V 34 w(hduaddrll)4053 3283 y SDict begin H.S end 4053 3283 a Fj(99)4144 3225 y SDict begin H.R end 4144 3225 a 4144 3283 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.2) cvn H.B /ANN pdfmark end 4144 3283 a 2912 3396 a Fj(\014ts)p 3039 3396 28 4 v 32 w(get)p 3191 3396 V 34 w(img)p 3371 3396 V 33 w(dim)4053 3396 y SDict begin H.S end 4053 3396 a Fj(43)4144 3338 y SDict begin H.R end 4144 3338 a 4144 3396 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 4144 3396 a 2912 3509 a Fj(\014ts)p 3039 3509 28 4 v 32 w(get)p 3191 3509 V 34 w(img)p 3371 3509 V 33 w(equivt)m(yp)s(e)4053 3509 y SDict begin H.S end 4053 3509 a Fj(43)4144 3450 y SDict begin H.R end 4144 3450 a 4144 3509 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 4144 3509 a 2912 3622 a Fj(\014ts)p 3039 3622 28 4 v 32 w(get)p 3191 3622 V 34 w(img)p 3371 3622 V 33 w(param)4053 3622 y SDict begin H.S end 4053 3622 a Fj(43)4144 3563 y SDict begin H.R end 4144 3563 a 4144 3622 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 4144 3622 a 2912 3735 a Fj(\014ts)p 3039 3735 28 4 v 32 w(get)p 3191 3735 V 34 w(img)p 3371 3735 V 33 w(size)4053 3735 y SDict begin H.S end 4053 3735 a Fj(43)4144 3676 y SDict begin H.R end 4144 3676 a 4144 3735 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 4144 3735 a 2912 3848 a Fj(\014ts)p 3039 3848 28 4 v 32 w(get)p 3191 3848 V 34 w(img)p 3371 3848 V 33 w(t)m(yp)s(e)4053 3848 y SDict begin H.S end 4053 3848 a Fj(43)4144 3789 y SDict begin H.R end 4144 3789 a 4144 3848 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 4144 3848 a 2912 3961 a Fj(\014ts)p 3039 3961 28 4 v 32 w(get)p 3191 3961 V 34 w(in)m(tt)m(yp)s(e)4053 3961 y SDict begin H.S end 4053 3961 a Fj(69)4144 3902 y SDict begin H.R end 4144 3902 a 4144 3961 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 4144 3961 a 2912 4074 a Fj(\014ts)p 3039 4074 28 4 v 32 w(get)p 3191 4074 V 34 w(k)m(ey)p 3358 4074 V 34 w(strlen)4053 4074 y SDict begin H.S end 4053 4074 a Fj(39)4144 4015 y SDict begin H.R end 4144 4015 a 4144 4074 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.1) cvn H.B /ANN pdfmark end 4144 4074 a 2912 4187 a Fj(\014ts)p 3039 4187 28 4 v 32 w(get)p 3191 4187 V 34 w(k)m(eyclass)4053 4187 y SDict begin H.S end 4053 4187 a Fj(69)4144 4128 y SDict begin H.R end 4144 4128 a 4144 4187 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 4144 4187 a 2912 4299 a Fj(\014ts)p 3039 4299 28 4 v 32 w(get)p 3191 4299 V 34 w(k)m(eyname)4053 4299 y SDict begin H.S end 4053 4299 a Fj(67)4144 4241 y SDict begin H.R end 4144 4241 a 4144 4299 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 4144 4299 a 2912 4412 a Fj(\014ts)p 3039 4412 28 4 v 32 w(get)p 3191 4412 V 34 w(k)m(eyt)m(yp)s(e)4053 4412 y SDict begin H.S end 4053 4412 a Fj(68)4144 4354 y SDict begin H.R end 4144 4354 a 4144 4412 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 4144 4412 a 2912 4525 a Fj(\014ts)p 3039 4525 28 4 v 32 w(get)p 3191 4525 V 34 w(noise)p 3422 4525 V 33 w(bits)4053 4525 y SDict begin H.S end 4053 4525 a Fj(50)4144 4467 y SDict begin H.R end 4144 4467 a 4144 4525 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.6) cvn H.B /ANN pdfmark end 4144 4525 a 2912 4638 a Fj(\014ts)p 3039 4638 28 4 v 32 w(get)p 3191 4638 V 34 w(n)m(um)p 3400 4638 V 32 w(cols)4053 4638 y SDict begin H.S end 4053 4638 a Fj(53)4144 4580 y SDict begin H.R end 4144 4580 a 4144 4638 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.2) cvn H.B /ANN pdfmark end 4144 4638 a 2912 4751 a Fj(\014ts)p 3039 4751 28 4 v 32 w(get)p 3191 4751 V 34 w(n)m(um)p 3400 4751 V 32 w(groups)4053 4751 y SDict begin H.S end 4053 4751 a Fj(93)4144 4692 y SDict begin H.R end 4144 4692 a 4144 4751 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.2) cvn H.B /ANN pdfmark end 4144 4751 a 2912 4864 a Fj(\014ts)p 3039 4864 28 4 v 32 w(get)p 3191 4864 V 34 w(n)m(um)p 3400 4864 V 32 w(hdus)4053 4864 y SDict begin H.S end 4053 4864 a Fj(36)4144 4805 y SDict begin H.R end 4144 4805 a 4144 4864 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.3) cvn H.B /ANN pdfmark end 4144 4864 a 2912 4977 a Fj(\014ts)p 3039 4977 28 4 v 32 w(get)p 3191 4977 V 34 w(n)m(um)p 3400 4977 V 32 w(mem)m(b)s(ers)4053 4977 y SDict begin H.S end 4053 4977 a Fj(92)4144 4918 y SDict begin H.R end 4144 4918 a 4144 4977 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.2) cvn H.B /ANN pdfmark end 4144 4977 a 2912 5090 a Fj(\014ts)p 3039 5090 28 4 v 32 w(get)p 3191 5090 V 34 w(n)m(um)p 3400 5090 V 32 w(ro)m(ws)4053 5090 y SDict begin H.S end 4053 5090 a Fj(53)4144 5031 y SDict begin H.R end 4144 5031 a 4144 5090 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.2) cvn H.B /ANN pdfmark end 4144 5090 a 2912 5203 a Fj(\014ts)p 3039 5203 28 4 v 32 w(get)p 3191 5203 V 34 w(ro)m(wsize)4008 5203 y SDict begin H.S end 4008 5203 a Fj(116)4144 5144 y SDict begin H.R end 4144 5144 a 4144 5203 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.1) cvn H.B /ANN pdfmark end 4144 5203 a 2912 5316 a Fj(\014ts)p 3039 5316 28 4 v 32 w(get)p 3191 5316 V 34 w(system)p 3496 5316 V 33 w(time)4053 5316 y SDict begin H.S end 4053 5316 a Fj(65)4144 5257 y SDict begin H.R end 4144 5257 a 4144 5316 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.2) cvn H.B /ANN pdfmark end 4144 5316 a 2912 5429 a Fj(\014ts)p 3039 5429 28 4 v 32 w(get)p 3191 5429 V 34 w(tile)p 3350 5429 V 34 w(dim)4053 5429 y SDict begin H.S end 4053 5429 a Fj(50)4144 5370 y SDict begin H.R end 4144 5370 a 4144 5429 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.6) cvn H.B /ANN pdfmark end 4144 5429 a 2912 5541 a Fj(\014ts)p 3039 5541 28 4 v 32 w(get)p 3191 5541 V 34 w(tb)s(col)4053 5541 y SDict begin H.S end 4053 5541 a Fj(70)4144 5483 y SDict begin H.R end 4144 5483 a 4144 5541 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 4144 5541 a 2912 5654 a Fj(\014ts)p 3039 5654 28 4 v 32 w(get)p 3191 5654 V 34 w(v)m(ersion)4053 5654 y SDict begin H.S end 4053 5654 a Fj(66)4144 5596 y SDict begin H.R end 4144 5596 a 4144 5654 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 4144 5654 a 1882 5942 a Fj(173)p eop end %%Page: 174 182 TeXDict begin 174 181 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.174) cvn H.B /DEST pdfmark end 0 299 a Fj(174)2084 b Fh(APPENDIX)31 b(A.)61 b(INDEX)31 b(OF)f(R)m(OUTINES)50 543 y Fj(\014ts)p 177 543 28 4 v 32 w(hdr2str)1118 543 y SDict begin H.S end 1118 543 a Fj(40)1208 484 y SDict begin H.R end 1208 484 a 1208 543 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.1) cvn H.B /ANN pdfmark end 1208 543 a Fj(,)1264 543 y SDict begin H.S end 1264 543 a Fj(86)1355 484 y SDict begin H.R end 1355 484 a 1355 543 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (chapter.7) cvn H.B /ANN pdfmark end 1355 543 a 50 656 a Fj(\014ts)p 177 656 28 4 v 32 w(init)p 345 656 V 33 w(h)m(ttps)1264 656 y SDict begin H.S end 1264 656 a Fj(99)1355 597 y SDict begin H.R end 1355 597 a 1355 656 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.1) cvn H.B /ANN pdfmark end 1355 656 a 50 769 a Fj(\014ts)p 177 769 28 4 v 32 w(insert)p 432 769 V 33 w(atbl)1219 769 y SDict begin H.S end 1219 769 a Fj(100)1355 710 y SDict begin H.R end 1355 710 a 1355 769 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.2) cvn H.B /ANN pdfmark end 1355 769 a 50 882 a Fj(\014ts)p 177 882 28 4 v 32 w(insert)p 432 882 V 33 w(btbl)1219 882 y SDict begin H.S end 1219 882 a Fj(100)1355 823 y SDict begin H.R end 1355 823 a 1355 882 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.2) cvn H.B /ANN pdfmark end 1355 882 a 50 995 a Fj(\014ts)p 177 995 28 4 v 32 w(insert)p 432 995 V 33 w(col)1264 995 y SDict begin H.S end 1264 995 a Fj(56)1355 936 y SDict begin H.R end 1355 936 a 1355 995 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.3) cvn H.B /ANN pdfmark end 1355 995 a 50 1107 a Fj(\014ts)p 177 1107 28 4 v 32 w(insert)p 432 1107 V 33 w(cols)1264 1107 y SDict begin H.S end 1264 1107 a Fj(56)1355 1049 y SDict begin H.R end 1355 1049 a 1355 1107 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.3) cvn H.B /ANN pdfmark end 1355 1107 a 50 1220 a Fj(\014ts)p 177 1220 28 4 v 32 w(insert)p 432 1220 V 33 w(group)1264 1220 y SDict begin H.S end 1264 1220 a Fj(90)1355 1162 y SDict begin H.R end 1355 1162 a 1355 1220 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.1) cvn H.B /ANN pdfmark end 1355 1220 a 50 1333 a Fj(\014ts)p 177 1333 28 4 v 32 w(insert)p 432 1333 V 33 w(img)1219 1333 y SDict begin H.S end 1219 1333 a Fj(100)1355 1275 y SDict begin H.R end 1355 1275 a 1355 1333 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.2) cvn H.B /ANN pdfmark end 1355 1333 a 50 1446 a Fj(\014ts)p 177 1446 28 4 v 32 w(insert)p 432 1446 V 33 w(k)m(ey)p 598 1446 V 34 w(n)m(ull)1219 1446 y SDict begin H.S end 1219 1446 a Fj(107)1355 1388 y SDict begin H.R end 1355 1388 a 1355 1446 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.4) cvn H.B /ANN pdfmark end 1355 1446 a 50 1559 a Fj(\014ts)p 177 1559 28 4 v 32 w(insert)p 432 1559 V 33 w(k)m(ey)p 598 1559 V 34 w(TYP)1219 1559 y SDict begin H.S end 1219 1559 a Fj(107)1355 1501 y SDict begin H.R end 1355 1501 a 1355 1559 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.4) cvn H.B /ANN pdfmark end 1355 1559 a 50 1672 a Fj(\014ts)p 177 1672 28 4 v 32 w(insert)p 432 1672 V 33 w(record)1219 1672 y SDict begin H.S end 1219 1672 a Fj(106)1355 1613 y SDict begin H.R end 1355 1613 a 1355 1672 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.4) cvn H.B /ANN pdfmark end 1355 1672 a 50 1785 a Fj(\014ts)p 177 1785 28 4 v 32 w(insert)p 432 1785 V 33 w(ro)m(ws)1264 1785 y SDict begin H.S end 1264 1785 a Fj(56)1355 1726 y SDict begin H.R end 1355 1726 a 1355 1785 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.3) cvn H.B /ANN pdfmark end 1355 1785 a 50 1898 a Fj(\014ts)p 177 1898 28 4 v 32 w(is)p 270 1898 V 33 w(reen)m(tran)m(t)1264 1898 y SDict begin H.S end 1264 1898 a Fj(75)1355 1839 y SDict begin H.R end 1355 1839 a 1355 1898 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 1355 1898 a 50 2011 a Fj(\014ts)p 177 2011 28 4 v 32 w(iterate)p 465 2011 V 35 w(data)1264 2011 y SDict begin H.S end 1264 2011 a Fj(83)1355 1952 y SDict begin H.R end 1355 1952 a 1355 2011 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.6.4) cvn H.B /ANN pdfmark end 1355 2011 a 50 2124 a Fj(\014ts)p 177 2124 28 4 v 32 w(mak)m(e)p 415 2124 V 34 w(hist)1264 2124 y SDict begin H.S end 1264 2124 a Fj(63)1355 2065 y SDict begin H.R end 1355 2065 a 1355 2124 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.6) cvn H.B /ANN pdfmark end 1355 2124 a 50 2237 a Fj(\014ts)p 177 2237 28 4 v 32 w(mak)m(e)p 415 2237 V 34 w(k)m(ey)1264 2237 y SDict begin H.S end 1264 2237 a Fj(68)1355 2178 y SDict begin H.R end 1355 2178 a 1355 2237 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 1355 2237 a 50 2349 a Fj(\014ts)p 177 2349 28 4 v 32 w(mak)m(e)p 415 2349 V 34 w(k)m(eyn)1264 2349 y SDict begin H.S end 1264 2349 a Fj(68)1355 2291 y SDict begin H.R end 1355 2291 a 1355 2349 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 1355 2349 a 50 2462 a Fj(\014ts)p 177 2462 28 4 v 32 w(mak)m(e)p 415 2462 V 34 w(nk)m(ey)1264 2462 y SDict begin H.S end 1264 2462 a Fj(68)1355 2404 y SDict begin H.R end 1355 2404 a 1355 2462 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 1355 2462 a 50 2575 a Fj(\014ts)p 177 2575 28 4 v 32 w(merge)p 446 2575 V 34 w(groups)1264 2575 y SDict begin H.S end 1264 2575 a Fj(91)1355 2517 y SDict begin H.R end 1355 2517 a 1355 2575 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.1) cvn H.B /ANN pdfmark end 1355 2575 a 50 2688 a Fj(\014ts)p 177 2688 28 4 v 32 w(mo)s(dify)p 485 2688 V 32 w(card)1219 2688 y SDict begin H.S end 1219 2688 a Fj(109)1355 2630 y SDict begin H.R end 1355 2630 a 1355 2688 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.6) cvn H.B /ANN pdfmark end 1355 2688 a 50 2801 a Fj(\014ts)p 177 2801 28 4 v 32 w(mo)s(dify)p 485 2801 V 32 w(commen)m(t)1264 2801 y SDict begin H.S end 1264 2801 a Fj(42)1355 2743 y SDict begin H.R end 1355 2743 a 1355 2801 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 1355 2801 a 50 2914 a Fj(\014ts)p 177 2914 28 4 v 32 w(mo)s(dify)p 485 2914 V 32 w(k)m(ey)p 650 2914 V 34 w(n)m(ull)1219 2914 y SDict begin H.S end 1219 2914 a Fj(109)1355 2855 y SDict begin H.R end 1355 2855 a 1355 2914 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.6) cvn H.B /ANN pdfmark end 1355 2914 a 50 3027 a Fj(\014ts)p 177 3027 28 4 v 32 w(mo)s(dify)p 485 3027 V 32 w(k)m(ey)p 650 3027 V 34 w(TYP)1219 3027 y SDict begin H.S end 1219 3027 a Fj(109)1355 2968 y SDict begin H.R end 1355 2968 a 1355 3027 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.6) cvn H.B /ANN pdfmark end 1355 3027 a 50 3140 a Fj(\014ts)p 177 3140 28 4 v 32 w(mo)s(dify)p 485 3140 V 32 w(name)1264 3140 y SDict begin H.S end 1264 3140 a Fj(42)1355 3081 y SDict begin H.R end 1355 3081 a 1355 3140 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 1355 3140 a 50 3253 a Fj(\014ts)p 177 3253 28 4 v 32 w(mo)s(dify)p 485 3253 V 32 w(record)1219 3253 y SDict begin H.S end 1219 3253 a Fj(109)1355 3194 y SDict begin H.R end 1355 3194 a 1355 3253 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.6) cvn H.B /ANN pdfmark end 1355 3253 a 50 3366 a Fj(\014ts)p 177 3366 28 4 v 32 w(mo)s(dify)p 485 3366 V 32 w(v)m(ector)p 758 3366 V 35 w(len)1264 3366 y SDict begin H.S end 1264 3366 a Fj(57)1355 3307 y SDict begin H.R end 1355 3307 a 1355 3366 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.3) cvn H.B /ANN pdfmark end 1355 3366 a 50 3479 a Fj(\014ts)p 177 3479 28 4 v 32 w(mo)m(v)-5 b(abs)p 502 3479 V 33 w(hdu)1264 3479 y SDict begin H.S end 1264 3479 a Fj(36)1355 3420 y SDict begin H.R end 1355 3420 a 1355 3479 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.3) cvn H.B /ANN pdfmark end 1355 3479 a 50 3591 a Fj(\014ts)p 177 3591 28 4 v 32 w(mo)m(vnam)p 547 3591 V 33 w(hdu)1264 3591 y SDict begin H.S end 1264 3591 a Fj(36)1355 3533 y SDict begin H.R end 1355 3533 a 1355 3591 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.3) cvn H.B /ANN pdfmark end 1355 3591 a 50 3704 a Fj(\014ts)p 177 3704 28 4 v 32 w(mo)m(vrel)p 476 3704 V 34 w(hdu)1264 3704 y SDict begin H.S end 1264 3704 a Fj(36)1355 3646 y SDict begin H.R end 1355 3646 a 1355 3704 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.3) cvn H.B /ANN pdfmark end 1355 3704 a 50 3817 a Fj(\014ts)p 177 3817 28 4 v 32 w(n)m(ull)p 358 3817 V 33 w(c)m(hec)m(k)1264 3817 y SDict begin H.S end 1264 3817 a Fj(67)1355 3759 y SDict begin H.R end 1355 3759 a 1355 3817 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 1355 3817 a 50 3930 a Fj(\014ts)p 177 3930 28 4 v 32 w(op)s(en)p 399 3930 V 32 w(data)1264 3930 y SDict begin H.S end 1264 3930 a Fj(32)1355 3872 y SDict begin H.R end 1355 3872 a 1355 3930 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.2) cvn H.B /ANN pdfmark end 1355 3930 a 50 4043 a Fj(\014ts)p 177 4043 28 4 v 32 w(op)s(en)p 399 4043 V 32 w(disk\014le)1264 4043 y SDict begin H.S end 1264 4043 a Fj(32)1355 3985 y SDict begin H.R end 1355 3985 a 1355 4043 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.2) cvn H.B /ANN pdfmark end 1355 4043 a 50 4156 a Fj(\014ts)p 177 4156 28 4 v 32 w(op)s(en)p 399 4156 V 32 w(extlist)1264 4156 y SDict begin H.S end 1264 4156 a Fj(32)1355 4097 y SDict begin H.R end 1355 4097 a 1355 4156 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.2) cvn H.B /ANN pdfmark end 1355 4156 a 50 4269 a Fj(\014ts)p 177 4269 28 4 v 32 w(op)s(en)p 399 4269 V 32 w(\014le)1264 4269 y SDict begin H.S end 1264 4269 a Fj(32)1355 4210 y SDict begin H.R end 1355 4210 a 1355 4269 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.2) cvn H.B /ANN pdfmark end 1355 4269 a 50 4382 a Fj(\014ts)p 177 4382 28 4 v 32 w(op)s(en)p 399 4382 V 32 w(image)1264 4382 y SDict begin H.S end 1264 4382 a Fj(32)1355 4323 y SDict begin H.R end 1355 4323 a 1355 4382 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.2) cvn H.B /ANN pdfmark end 1355 4382 a 50 4495 a Fj(\014ts)p 177 4495 28 4 v 32 w(op)s(en)p 399 4495 V 32 w(table)1264 4495 y SDict begin H.S end 1264 4495 a Fj(32)1355 4436 y SDict begin H.R end 1355 4436 a 1355 4495 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.2) cvn H.B /ANN pdfmark end 1355 4495 a 50 4608 a Fj(\014ts)p 177 4608 28 4 v 32 w(op)s(en)p 399 4608 V 32 w(group)1264 4608 y SDict begin H.S end 1264 4608 a Fj(92)1355 4549 y SDict begin H.R end 1355 4549 a 1355 4608 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.1) cvn H.B /ANN pdfmark end 1355 4608 a 50 4721 a Fj(\014ts)p 177 4721 28 4 v 32 w(op)s(en)p 399 4721 V 32 w(mem)m(b)s(er)1264 4721 y SDict begin H.S end 1264 4721 a Fj(93)1355 4662 y SDict begin H.R end 1355 4662 a 1355 4721 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.2) cvn H.B /ANN pdfmark end 1355 4721 a 50 4833 a Fj(\014ts)p 177 4833 28 4 v 32 w(op)s(en)p 399 4833 V 32 w(mem\014le)1264 4833 y SDict begin H.S end 1264 4833 a Fj(95)1355 4775 y SDict begin H.R end 1355 4775 a 1355 4833 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.1) cvn H.B /ANN pdfmark end 1355 4833 a 50 4946 a Fj(\014ts)p 177 4946 28 4 v 32 w(parse)p 417 4946 V 33 w(extn)m(um)1264 4946 y SDict begin H.S end 1264 4946 a Fj(97)1355 4888 y SDict begin H.R end 1355 4888 a 1355 4946 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.1) cvn H.B /ANN pdfmark end 1355 4946 a 50 5059 a Fj(\014ts)p 177 5059 28 4 v 32 w(parse)p 417 5059 V 33 w(input)p 663 5059 V 32 w(\014lename)1264 5059 y SDict begin H.S end 1264 5059 a Fj(97)1355 5001 y SDict begin H.R end 1355 5001 a 1355 5059 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.1) cvn H.B /ANN pdfmark end 1355 5059 a 50 5172 a Fj(\014ts)p 177 5172 28 4 v 32 w(parse)p 417 5172 V 33 w(input)p 663 5172 V 32 w(url)1264 5172 y SDict begin H.S end 1264 5172 a Fj(97)1355 5114 y SDict begin H.R end 1355 5114 a 1355 5172 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.1) cvn H.B /ANN pdfmark end 1355 5172 a 50 5285 a Fj(\014ts)p 177 5285 28 4 v 32 w(parse)p 417 5285 V 33 w(range)1264 5285 y SDict begin H.S end 1264 5285 a Fj(74)1355 5227 y SDict begin H.R end 1355 5227 a 1355 5285 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 1355 5285 a 50 5398 a Fj(\014ts)p 177 5398 28 4 v 32 w(parse)p 417 5398 V 33 w(ro)s(otname)1264 5398 y SDict begin H.S end 1264 5398 a Fj(98)1355 5339 y SDict begin H.R end 1355 5339 a 1355 5398 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.1) cvn H.B /ANN pdfmark end 1355 5398 a 50 5511 a Fj(\014ts)p 177 5511 28 4 v 32 w(parse)p 417 5511 V 33 w(template)1264 5511 y SDict begin H.S end 1264 5511 a Fj(70)1355 5452 y SDict begin H.R end 1355 5452 a 1355 5511 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 1355 5511 a 50 5624 a Fj(\014ts)p 177 5624 28 4 v 32 w(parse)p 417 5624 V 33 w(v)g(alue)1264 5624 y SDict begin H.S end 1264 5624 a Fj(68)1355 5565 y SDict begin H.R end 1355 5565 a 1355 5624 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 1355 5624 a 50 5737 a Fj(\014ts)p 177 5737 28 4 v 32 w(pix)p 333 5737 V 33 w(to)p 446 5737 V 33 w(w)m(orld)1264 5737 y SDict begin H.S end 1264 5737 a Fj(87)1355 5678 y SDict begin H.R end 1355 5678 a 1355 5737 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.7.1) cvn H.B /ANN pdfmark end 1355 5737 a 50 5850 a Fj(\014ts)p 177 5850 28 4 v 32 w(read)p 381 5850 V 33 w(2d)p 510 5850 V 33 w(TYP)1219 5850 y SDict begin H.S end 1219 5850 a Fj(114)1355 5791 y SDict begin H.R end 1355 5791 a 1355 5850 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 1355 5850 a 1475 543 a Fj(\014ts)p 1602 543 28 4 v 32 w(read)p 1806 543 V 33 w(3d)p 1935 543 V 33 w(TYP)2726 543 y SDict begin H.S end 2726 543 a Fj(114)2862 484 y SDict begin H.R end 2862 484 a 2862 543 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 2862 543 a 1475 656 a Fj(\014ts)p 1602 656 28 4 v 32 w(read)p 1806 656 V 33 w(atblhdr)2726 656 y SDict begin H.S end 2726 656 a Fj(103)2862 597 y SDict begin H.R end 2862 597 a 2862 656 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.2) cvn H.B /ANN pdfmark end 2862 656 a 1475 769 a Fj(\014ts)p 1602 769 28 4 v 32 w(read)p 1806 769 V 33 w(btblhdr)2726 769 y SDict begin H.S end 2726 769 a Fj(103)2862 710 y SDict begin H.R end 2862 710 a 2862 769 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.2) cvn H.B /ANN pdfmark end 2862 769 a 1475 882 a Fj(\014ts)p 1602 882 28 4 v 32 w(read)p 1806 882 V 33 w(card)2772 882 y SDict begin H.S end 2772 882 a Fj(38)2862 823 y SDict begin H.R end 2862 823 a 2862 882 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.1) cvn H.B /ANN pdfmark end 2862 882 a 1475 995 a Fj(\014ts)p 1602 995 28 4 v 32 w(read)p 1806 995 V 33 w(col)2772 995 y SDict begin H.S end 2772 995 a Fj(59)2862 936 y SDict begin H.R end 2862 936 a 2862 995 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.4) cvn H.B /ANN pdfmark end 2862 995 a 1475 1107 a Fj(\014ts)p 1602 1107 28 4 v 32 w(read)p 1806 1107 V 33 w(col)p 1949 1107 V 34 w(bit)p 2094 1107 V 2726 1107 a SDict begin H.S end 2726 1107 a Fj(120)2862 1049 y SDict begin H.R end 2862 1049 a 2862 1107 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.4) cvn H.B /ANN pdfmark end 2862 1107 a 1475 1220 a Fj(\014ts)p 1602 1220 28 4 v 32 w(read)p 1806 1220 V 33 w(col)p 1949 1220 V 34 w(TYP)2726 1220 y SDict begin H.S end 2726 1220 a Fj(119)2862 1162 y SDict begin H.R end 2862 1162 a 2862 1220 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.4) cvn H.B /ANN pdfmark end 2862 1220 a 1475 1333 a Fj(\014ts)p 1602 1333 28 4 v 32 w(read)p 1806 1333 V 33 w(coln)m(ull)2772 1333 y SDict begin H.S end 2772 1333 a Fj(59)2862 1275 y SDict begin H.R end 2862 1275 a 2862 1333 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.4) cvn H.B /ANN pdfmark end 2862 1333 a 1475 1446 a Fj(\014ts)p 1602 1446 28 4 v 32 w(read)p 1806 1446 V 33 w(coln)m(ull)p 2098 1446 V 34 w(TYP)2726 1446 y SDict begin H.S end 2726 1446 a Fj(119)2862 1388 y SDict begin H.R end 2862 1388 a 2862 1446 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.4) cvn H.B /ANN pdfmark end 2862 1446 a 1475 1559 a Fj(\014ts)p 1602 1559 28 4 v 32 w(read)p 1806 1559 V 33 w(descript)2726 1559 y SDict begin H.S end 2726 1559 a Fj(121)2862 1501 y SDict begin H.R end 2862 1501 a 2862 1559 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.4) cvn H.B /ANN pdfmark end 2862 1559 a 1475 1672 a Fj(\014ts)p 1602 1672 28 4 v 32 w(read)p 1806 1672 V 33 w(descripts)2726 1672 y SDict begin H.S end 2726 1672 a Fj(121)2862 1613 y SDict begin H.R end 2862 1613 a 2862 1672 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.4) cvn H.B /ANN pdfmark end 2862 1672 a 1475 1785 a Fj(\014ts)p 1602 1785 28 4 v 32 w(read)p 1806 1785 V 33 w(errmsg)2772 1785 y SDict begin H.S end 2772 1785 a Fj(32)2862 1726 y SDict begin H.R end 2862 1726 a 2862 1785 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.1) cvn H.B /ANN pdfmark end 2862 1785 a 1475 1898 a Fj(\014ts)p 1602 1898 28 4 v 32 w(read)p 1806 1898 V 33 w(ext)2726 1898 y SDict begin H.S end 2726 1898 a Fj(101)2862 1839 y SDict begin H.R end 2862 1839 a 2862 1898 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.2) cvn H.B /ANN pdfmark end 2862 1898 a 1475 2011 a Fj(\014ts)p 1602 2011 28 4 v 32 w(read)p 1806 2011 V 33 w(grppar)p 2103 2011 V 32 w(TYP)2726 2011 y SDict begin H.S end 2726 2011 a Fj(114)2862 1952 y SDict begin H.R end 2862 1952 a 2862 2011 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 2862 2011 a 1475 2124 a Fj(\014ts)p 1602 2124 28 4 v 32 w(read)p 1806 2124 V 33 w(img)2726 2124 y SDict begin H.S end 2726 2124 a Fj(114)2862 2065 y SDict begin H.R end 2862 2065 a 2862 2124 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 2862 2124 a 1475 2237 a Fj(\014ts)p 1602 2237 28 4 v 32 w(read)p 1806 2237 V 33 w(img)p 1985 2237 V 33 w(co)s(ord)2772 2237 y SDict begin H.S end 2772 2237 a Fj(87)2862 2178 y SDict begin H.R end 2862 2178 a 2862 2237 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.7.1) cvn H.B /ANN pdfmark end 2862 2237 a 1475 2349 a Fj(\014ts)p 1602 2349 28 4 v 32 w(read)p 1806 2349 V 33 w(img)p 1985 2349 V 33 w(TYP)2726 2349 y SDict begin H.S end 2726 2349 a Fj(114)2862 2291 y SDict begin H.R end 2862 2291 a 2862 2349 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 2862 2349 a 1475 2462 a Fj(\014ts)p 1602 2462 28 4 v 32 w(read)p 1806 2462 V 33 w(imghdr)2726 2462 y SDict begin H.S end 2726 2462 a Fj(103)2862 2404 y SDict begin H.R end 2862 2404 a 2862 2462 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.2) cvn H.B /ANN pdfmark end 2862 2462 a 1475 2575 a Fj(\014ts)p 1602 2575 28 4 v 32 w(read)p 1806 2575 V 33 w(imgn)m(ull)2726 2575 y SDict begin H.S end 2726 2575 a Fj(114)2862 2517 y SDict begin H.R end 2862 2517 a 2862 2575 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 2862 2575 a 1475 2688 a Fj(\014ts)p 1602 2688 28 4 v 32 w(read)p 1806 2688 V 33 w(imgn)m(ull)p 2134 2688 V 33 w(TYP)2726 2688 y SDict begin H.S end 2726 2688 a Fj(114)2862 2630 y SDict begin H.R end 2862 2630 a 2862 2688 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 2862 2688 a 1475 2801 a Fj(\014ts)p 1602 2801 28 4 v 32 w(read)p 1806 2801 V 33 w(k)m(ey)2772 2801 y SDict begin H.S end 2772 2801 a Fj(38)2862 2743 y SDict begin H.R end 2862 2743 a 2862 2801 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.1) cvn H.B /ANN pdfmark end 2862 2801 a 1475 2914 a Fj(\014ts)p 1602 2914 28 4 v 32 w(read)p 1806 2914 V 33 w(k)m(ey)p 1972 2914 V 33 w(longstr)2726 2914 y SDict begin H.S end 2726 2914 a Fj(107)2862 2855 y SDict begin H.R end 2862 2855 a 2862 2914 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.5) cvn H.B /ANN pdfmark end 2862 2914 a 1475 3027 a Fj(\014ts)p 1602 3027 28 4 v 32 w(read)p 1806 3027 V 33 w(k)m(ey)p 1972 3027 V 33 w(triple)2726 3027 y SDict begin H.S end 2726 3027 a Fj(108)2862 2968 y SDict begin H.R end 2862 2968 a 2862 3027 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.5) cvn H.B /ANN pdfmark end 2862 3027 a 1475 3140 a Fj(\014ts)p 1602 3140 28 4 v 32 w(read)p 1806 3140 V 33 w(k)m(ey)p 1972 3140 V 33 w(unit)2772 3140 y SDict begin H.S end 2772 3140 a Fj(40)2862 3081 y SDict begin H.R end 2862 3081 a 2862 3140 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.1) cvn H.B /ANN pdfmark end 2862 3140 a 1475 3253 a Fj(\014ts)p 1602 3253 28 4 v 32 w(read)p 1806 3253 V 33 w(k)m(ey)p 1972 3253 V 33 w(TYP)2726 3253 y SDict begin H.S end 2726 3253 a Fj(107)2862 3194 y SDict begin H.R end 2862 3194 a 2862 3253 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.5) cvn H.B /ANN pdfmark end 2862 3253 a 1475 3366 a Fj(\014ts)p 1602 3366 28 4 v 32 w(read)p 1806 3366 V 33 w(k)m(eyn)2772 3366 y SDict begin H.S end 2772 3366 a Fj(39)2862 3307 y SDict begin H.R end 2862 3307 a 2862 3366 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.1) cvn H.B /ANN pdfmark end 2862 3366 a 1475 3479 a Fj(\014ts)p 1602 3479 28 4 v 32 w(read)p 1806 3479 V 33 w(k)m(eys)p 2008 3479 V 33 w(TYP)2726 3479 y SDict begin H.S end 2726 3479 a Fj(108)2862 3420 y SDict begin H.R end 2862 3420 a 2862 3479 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.5) cvn H.B /ANN pdfmark end 2862 3479 a 1475 3591 a Fj(\014ts)p 1602 3591 28 4 v 32 w(read)p 1806 3591 V 33 w(k)m(eyw)m(ord)2772 3591 y SDict begin H.S end 2772 3591 a Fj(38)2862 3533 y SDict begin H.R end 2862 3533 a 2862 3591 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.1) cvn H.B /ANN pdfmark end 2862 3591 a 1475 3704 a Fj(\014ts)p 1602 3704 28 4 v 32 w(read)p 1806 3704 V 33 w(pix)2772 3704 y SDict begin H.S end 2772 3704 a Fj(46)2862 3646 y SDict begin H.R end 2862 3646 a 2862 3704 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 2862 3704 a 1475 3817 a Fj(\014ts)p 1602 3817 28 4 v 32 w(read)p 1806 3817 V 33 w(pixn)m(ull)2772 3817 y SDict begin H.S end 2772 3817 a Fj(46)2862 3759 y SDict begin H.R end 2862 3759 a 2862 3817 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 2862 3817 a 1475 3930 a Fj(\014ts)p 1602 3930 28 4 v 32 w(read)p 1806 3930 V 33 w(record)2772 3930 y SDict begin H.S end 2772 3930 a Fj(39)2862 3872 y SDict begin H.R end 2862 3872 a 2862 3930 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.1) cvn H.B /ANN pdfmark end 2862 3930 a 1475 4043 a Fj(\014ts)p 1602 4043 28 4 v 32 w(read)p 1806 4043 V 33 w(str)2772 4043 y SDict begin H.S end 2772 4043 a Fj(38)2862 3985 y SDict begin H.R end 2862 3985 a 2862 4043 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.1) cvn H.B /ANN pdfmark end 2862 4043 a 1475 4156 a Fj(\014ts)p 1602 4156 28 4 v 32 w(read)p 1806 4156 V 33 w(string)p 2067 4156 V 33 w(k)m(ey)2772 4156 y SDict begin H.S end 2772 4156 a Fj(39)2862 4097 y SDict begin H.R end 2862 4097 a 2862 4156 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.1) cvn H.B /ANN pdfmark end 2862 4156 a 1475 4269 a Fj(\014ts)p 1602 4269 28 4 v 32 w(read)p 1806 4269 V 33 w(subset)2772 4269 y SDict begin H.S end 2772 4269 a Fj(46)2862 4210 y SDict begin H.R end 2862 4210 a 2862 4269 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 2862 4269 a 1475 4382 a Fj(\014ts)p 1602 4382 28 4 v 32 w(read)p 1806 4382 V 33 w(subset)p 2088 4382 V 32 w(TYP)2559 4382 y SDict begin H.S end 2559 4382 a Fj(115)2696 4323 y SDict begin H.R end 2696 4323 a 2696 4382 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 2696 4382 a 2726 4382 a SDict begin H.S end 2726 4382 a Fj(119)2862 4323 y SDict begin H.R end 2862 4323 a 2862 4382 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.4) cvn H.B /ANN pdfmark end 2862 4382 a 1475 4495 a Fj(\014ts)p 1602 4495 28 4 v 32 w(read)p 1806 4495 V 33 w(subsetn)m(ull)p 2237 4495 V 32 w(TYP)2559 4495 y SDict begin H.S end 2559 4495 a Fj(115)2696 4436 y SDict begin H.R end 2696 4436 a 2696 4495 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 2696 4495 a 2726 4495 a SDict begin H.S end 2726 4495 a Fj(120)2862 4436 y SDict begin H.R end 2862 4436 a 2862 4495 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.4) cvn H.B /ANN pdfmark end 2862 4495 a 1475 4608 a Fj(\014ts)p 1602 4608 28 4 v 32 w(read)p 1806 4608 V 33 w(tbl)p 1950 4608 V 33 w(co)s(ord)2772 4608 y SDict begin H.S end 2772 4608 a Fj(87)2862 4549 y SDict begin H.R end 2862 4549 a 2862 4608 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.7.1) cvn H.B /ANN pdfmark end 2862 4608 a 1475 4721 a Fj(\014ts)p 1602 4721 28 4 v 32 w(read)p 1806 4721 V 33 w(tblb)m(ytes)2726 4721 y SDict begin H.S end 2726 4721 a Fj(117)2862 4662 y SDict begin H.R end 2862 4662 a 2862 4721 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.2) cvn H.B /ANN pdfmark end 2862 4721 a 1475 4833 a Fj(\014ts)p 1602 4833 28 4 v 32 w(read)p 1806 4833 V 33 w(tdim)2772 4833 y SDict begin H.S end 2772 4833 a Fj(55)2862 4775 y SDict begin H.R end 2862 4775 a 2862 4833 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.2) cvn H.B /ANN pdfmark end 2862 4833 a 1475 4946 a Fj(\014ts)p 1602 4946 28 4 v 32 w(read)p 1806 4946 V 33 w(w)m(cstab)2772 4946 y SDict begin H.S end 2772 4946 a Fj(86)2862 4888 y SDict begin H.R end 2862 4888 a 2862 4946 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (chapter.7) cvn H.B /ANN pdfmark end 2862 4946 a 1475 5059 a Fj(\014ts)p 1602 5059 28 4 v 32 w(rebin)p 1837 5059 V 32 w(w)m(cs)2772 5059 y SDict begin H.S end 2772 5059 a Fj(62)2862 5001 y SDict begin H.R end 2862 5001 a 2862 5059 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.6) cvn H.B /ANN pdfmark end 2862 5059 a 1475 5172 a Fj(\014ts)p 1602 5172 28 4 v 32 w(remo)m(v)m(e)p 1913 5172 V 35 w(group)2772 5172 y SDict begin H.S end 2772 5172 a Fj(91)2862 5114 y SDict begin H.R end 2862 5114 a 2862 5172 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.1) cvn H.B /ANN pdfmark end 2862 5172 a 1475 5285 a Fj(\014ts)p 1602 5285 28 4 v 32 w(remo)m(v)m(e)p 1913 5285 V 35 w(mem)m(b)s(er)2772 5285 y SDict begin H.S end 2772 5285 a Fj(94)2862 5227 y SDict begin H.R end 2862 5227 a 2862 5285 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.2) cvn H.B /ANN pdfmark end 2862 5285 a 1475 5398 a Fj(\014ts)p 1602 5398 28 4 v 32 w(reop)s(en)p 1900 5398 V 32 w(\014le)2772 5398 y SDict begin H.S end 2772 5398 a Fj(96)2862 5339 y SDict begin H.R end 2862 5339 a 2862 5398 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.1) cvn H.B /ANN pdfmark end 2862 5398 a 1475 5511 a Fj(\014ts)p 1602 5511 28 4 v 32 w(rep)s(ort)p 1880 5511 V 32 w(error)2772 5511 y SDict begin H.S end 2772 5511 a Fj(32)2862 5452 y SDict begin H.R end 2862 5452 a 2862 5511 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.1) cvn H.B /ANN pdfmark end 2862 5511 a 1475 5624 a Fj(\014ts)p 1602 5624 28 4 v 32 w(resize)p 1851 5624 V 34 w(img)2726 5624 y SDict begin H.S end 2726 5624 a Fj(101)2862 5565 y SDict begin H.R end 2862 5565 a 2862 5624 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.2) cvn H.B /ANN pdfmark end 2862 5624 a 1475 5737 a Fj(\014ts)p 1602 5737 28 4 v 32 w(rms)p 1782 5737 V 32 w(\015oat)2772 5737 y SDict begin H.S end 2772 5737 a Fj(75)2862 5678 y SDict begin H.R end 2862 5678 a 2862 5737 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 2862 5737 a 1475 5850 a Fj(\014ts)p 1602 5850 28 4 v 32 w(rms)p 1782 5850 V 32 w(short)2772 5850 y SDict begin H.S end 2772 5850 a Fj(75)2862 5791 y SDict begin H.R end 2862 5791 a 2862 5850 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 2862 5850 a 2982 543 a Fj(\014ts)p 3109 543 28 4 v 33 w(select)p 3358 543 V 34 w(ro)m(ws)4114 543 y SDict begin H.S end 4114 543 a Fj(60)4205 484 y SDict begin H.R end 4205 484 a 4205 543 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.5) cvn H.B /ANN pdfmark end 4205 543 a 2982 656 a Fj(\014ts)p 3109 656 28 4 v 33 w(set)p 3253 656 V 33 w(atbln)m(ull)4069 656 y SDict begin H.S end 4069 656 a Fj(111)4205 597 y SDict begin H.R end 4205 597 a 4205 656 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.4) cvn H.B /ANN pdfmark end 4205 656 a 2982 769 a Fj(\014ts)p 3109 769 28 4 v 33 w(set)p 3253 769 V 33 w(bscale)4069 769 y SDict begin H.S end 4069 769 a Fj(110)4205 710 y SDict begin H.R end 4205 710 a 4205 769 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.4) cvn H.B /ANN pdfmark end 4205 769 a 2982 882 a Fj(\014ts)p 3109 882 28 4 v 33 w(set)p 3253 882 V 33 w(btbln)m(ull)4069 882 y SDict begin H.S end 4069 882 a Fj(111)4205 823 y SDict begin H.R end 4205 823 a 4205 882 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.4) cvn H.B /ANN pdfmark end 4205 882 a 2982 995 a Fj(\014ts)p 3109 995 28 4 v 33 w(set)p 3253 995 V 33 w(compression)p 3767 995 V 33 w(t)m(yp)s(e)4114 995 y SDict begin H.S end 4114 995 a Fj(50)4205 936 y SDict begin H.R end 4205 936 a 4205 995 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.6) cvn H.B /ANN pdfmark end 4205 995 a 2982 1107 a Fj(\014ts)p 3109 1107 28 4 v 33 w(set)p 3253 1107 V 33 w(hdrsize)4069 1107 y SDict begin H.S end 4069 1107 a Fj(102)4205 1049 y SDict begin H.R end 4205 1049 a 4205 1107 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.1) cvn H.B /ANN pdfmark end 4205 1107 a 2982 1220 a Fj(\014ts)p 3109 1220 28 4 v 33 w(set)p 3253 1220 V 33 w(hdustruc)4069 1220 y SDict begin H.S end 4069 1220 a Fj(101)4205 1162 y SDict begin H.R end 4205 1162 a 4205 1220 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.2) cvn H.B /ANN pdfmark end 4205 1220 a 2982 1333 a Fj(\014ts)p 3109 1333 28 4 v 33 w(set)p 3253 1333 V 33 w(imgn)m(ull)4069 1333 y SDict begin H.S end 4069 1333 a Fj(111)4205 1275 y SDict begin H.R end 4205 1275 a 4205 1333 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.4) cvn H.B /ANN pdfmark end 4205 1333 a 2982 1446 a Fj(\014ts)p 3109 1446 28 4 v 33 w(set)p 3253 1446 V 33 w(noise)p 3483 1446 V 33 w(bits)4114 1446 y SDict begin H.S end 4114 1446 a Fj(50)4205 1388 y SDict begin H.R end 4205 1388 a 4205 1446 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.6) cvn H.B /ANN pdfmark end 4205 1446 a 2982 1559 a Fj(\014ts)p 3109 1559 28 4 v 33 w(set)p 3253 1559 V 33 w(tile)p 3411 1559 V 34 w(dim)4114 1559 y SDict begin H.S end 4114 1559 a Fj(50)4205 1501 y SDict begin H.R end 4205 1501 a 4205 1559 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.6) cvn H.B /ANN pdfmark end 4205 1559 a 2982 1672 a Fj(\014ts)p 3109 1672 28 4 v 33 w(set)p 3253 1672 V 33 w(tscale)4069 1672 y SDict begin H.S end 4069 1672 a Fj(111)4205 1613 y SDict begin H.R end 4205 1613 a 4205 1672 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.4) cvn H.B /ANN pdfmark end 4205 1672 a 2982 1785 a Fj(\014ts)p 3109 1785 28 4 v 33 w(split)p 3314 1785 V 33 w(names)4114 1785 y SDict begin H.S end 4114 1785 a Fj(67)4205 1726 y SDict begin H.R end 4205 1726 a 4205 1785 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 4205 1785 a 2982 1898 a Fj(\014ts)p 3109 1898 28 4 v 33 w(str2date)4114 1898 y SDict begin H.S end 4114 1898 a Fj(65)4205 1839 y SDict begin H.R end 4205 1839 a 4205 1898 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.2) cvn H.B /ANN pdfmark end 4205 1898 a 2982 2011 a Fj(\014ts)p 3109 2011 28 4 v 33 w(str2time)4114 2011 y SDict begin H.S end 4114 2011 a Fj(65)4205 1952 y SDict begin H.R end 4205 1952 a 4205 2011 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.2) cvn H.B /ANN pdfmark end 4205 2011 a 2982 2124 a Fj(\014ts)p 3109 2124 28 4 v 33 w(test)p 3288 2124 V 33 w(expr)4114 2124 y SDict begin H.S end 4114 2124 a Fj(61)4205 2065 y SDict begin H.R end 4205 2065 a 4205 2124 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.5) cvn H.B /ANN pdfmark end 4205 2124 a 2982 2237 a Fj(\014ts)p 3109 2237 28 4 v 33 w(test)p 3288 2237 V 33 w(heap)4069 2237 y SDict begin H.S end 4069 2237 a Fj(116)4205 2178 y SDict begin H.R end 4205 2178 a 4205 2237 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.1) cvn H.B /ANN pdfmark end 4205 2237 a 2982 2349 a Fj(\014ts)p 3109 2349 28 4 v 33 w(test)p 3288 2349 V 33 w(k)m(eyw)m(ord)4114 2349 y SDict begin H.S end 4114 2349 a Fj(67)4205 2291 y SDict begin H.R end 4205 2291 a 4205 2349 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 4205 2349 a 2982 2462 a Fj(\014ts)p 3109 2462 28 4 v 33 w(test)p 3288 2462 V 33 w(record)4114 2462 y SDict begin H.S end 4114 2462 a Fj(67)4205 2404 y SDict begin H.R end 4205 2404 a 4205 2462 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 4205 2462 a 2982 2575 a Fj(\014ts)p 3109 2575 28 4 v 33 w(time2str)4114 2575 y SDict begin H.S end 4114 2575 a Fj(65)4205 2517 y SDict begin H.R end 4205 2517 a 4205 2575 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.2) cvn H.B /ANN pdfmark end 4205 2575 a 2982 2688 a Fj(\014ts)p 3109 2688 28 4 v 33 w(transfer)p 3449 2688 V 32 w(mem)m(b)s(er)4114 2688 y SDict begin H.S end 4114 2688 a Fj(93)4205 2630 y SDict begin H.R end 4205 2630 a 4205 2688 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.2) cvn H.B /ANN pdfmark end 4205 2688 a 2982 2801 a Fj(\014ts)p 3109 2801 28 4 v 33 w(translate)p 3490 2801 V 34 w(k)m(eyw)m(ord)4114 2801 y SDict begin H.S end 4114 2801 a Fj(73)4205 2743 y SDict begin H.R end 4205 2743 a 4205 2801 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 4205 2801 a 2982 2914 a Fj(\014ts)p 3109 2914 28 4 v 33 w(up)s(date)p 3418 2914 V 32 w(card)4114 2914 y SDict begin H.S end 4114 2914 a Fj(42)4205 2855 y SDict begin H.R end 4205 2855 a 4205 2914 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 4205 2914 a 2982 3027 a Fj(\014ts)p 3109 3027 28 4 v 33 w(up)s(date)p 3418 3027 V 32 w(c)m(hksum)4114 3027 y SDict begin H.S end 4114 3027 a Fj(64)4205 2968 y SDict begin H.R end 4205 2968 a 4205 3027 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.1) cvn H.B /ANN pdfmark end 4205 3027 a 2982 3140 a Fj(\014ts)p 3109 3140 28 4 v 33 w(up)s(date)p 3418 3140 V 32 w(k)m(ey)4114 3140 y SDict begin H.S end 4114 3140 a Fj(41)4205 3081 y SDict begin H.R end 4205 3081 a 4205 3140 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 4205 3140 a 2982 3253 a Fj(\014ts)p 3109 3253 28 4 v 33 w(up)s(date)p 3418 3253 V 32 w(k)m(ey)p 3583 3253 V 33 w(longstr)4069 3253 y SDict begin H.S end 4069 3253 a Fj(110)4205 3194 y SDict begin H.R end 4205 3194 a 4205 3253 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.7) cvn H.B /ANN pdfmark end 4205 3253 a 2982 3366 a Fj(\014ts)p 3109 3366 28 4 v 33 w(up)s(date)p 3418 3366 V 32 w(k)m(ey)p 3583 3366 V 33 w(n)m(ull)4114 3366 y SDict begin H.S end 4114 3366 a Fj(41)4205 3307 y SDict begin H.R end 4205 3307 a 4205 3366 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 4205 3366 a 2982 3479 a Fj(\014ts)p 3109 3479 28 4 v 33 w(up)s(date)p 3418 3479 V 32 w(k)m(ey)p 3583 3479 V 33 w(TYP)4069 3479 y SDict begin H.S end 4069 3479 a Fj(110)4205 3420 y SDict begin H.R end 4205 3420 a 4205 3479 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.7) cvn H.B /ANN pdfmark end 4205 3479 a 2982 3591 a Fj(\014ts)p 3109 3591 28 4 v 33 w(upp)s(ercase)4114 3591 y SDict begin H.S end 4114 3591 a Fj(66)4205 3533 y SDict begin H.R end 4205 3533 a 4205 3591 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 4205 3591 a 2982 3704 a Fj(\014ts)p 3109 3704 28 4 v 33 w(url)p 3254 3704 V 32 w(t)m(yp)s(e)4114 3704 y SDict begin H.S end 4114 3704 a Fj(35)4205 3646 y SDict begin H.R end 4205 3646 a 4205 3704 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.2) cvn H.B /ANN pdfmark end 4205 3704 a 2982 3817 a Fj(\014ts)p 3109 3817 28 4 v 33 w(v)m(erb)s(ose)p 3438 3817 V 33 w(h)m(ttps)4114 3817 y SDict begin H.S end 4114 3817 a Fj(99)4205 3759 y SDict begin H.R end 4205 3759 a 4205 3817 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.1) cvn H.B /ANN pdfmark end 4205 3817 a 2982 3930 a Fj(\014ts)p 3109 3930 28 4 v 33 w(v)m(erify)p 3364 3930 V 33 w(c)m(hksum)4114 3930 y SDict begin H.S end 4114 3930 a Fj(64)4205 3872 y SDict begin H.R end 4205 3872 a 4205 3930 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.1) cvn H.B /ANN pdfmark end 4205 3930 a 2982 4043 a Fj(\014ts)p 3109 4043 28 4 v 33 w(v)m(erify)p 3364 4043 V 33 w(group)4114 4043 y SDict begin H.S end 4114 4043 a Fj(92)4205 3985 y SDict begin H.R end 4205 3985 a 4205 4043 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.1) cvn H.B /ANN pdfmark end 4205 4043 a 2982 4156 a Fj(\014ts)p 3109 4156 28 4 v 33 w(w)m(orld)p 3362 4156 V 32 w(to)p 3474 4156 V 34 w(pix)4114 4156 y SDict begin H.S end 4114 4156 a Fj(87)4205 4097 y SDict begin H.R end 4205 4097 a 4205 4156 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.7.1) cvn H.B /ANN pdfmark end 4205 4156 a 2982 4269 a Fj(\014ts)p 3109 4269 28 4 v 33 w(write)p 3344 4269 V 33 w(2d)p 3473 4269 V 32 w(TYP)4069 4269 y SDict begin H.S end 4069 4269 a Fj(113)4205 4210 y SDict begin H.R end 4205 4210 a 4205 4269 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 4205 4269 a 2982 4382 a Fj(\014ts)p 3109 4382 28 4 v 33 w(write)p 3344 4382 V 33 w(3d)p 3473 4382 V 32 w(TYP)4069 4382 y SDict begin H.S end 4069 4382 a Fj(113)4205 4323 y SDict begin H.R end 4205 4323 a 4205 4382 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 4205 4382 a 2982 4495 a Fj(\014ts)p 3109 4495 28 4 v 33 w(write)p 3344 4495 V 33 w(atblhdr)4069 4495 y SDict begin H.S end 4069 4495 a Fj(103)4205 4436 y SDict begin H.R end 4205 4436 a 4205 4495 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.2) cvn H.B /ANN pdfmark end 4205 4495 a 2982 4608 a Fj(\014ts)p 3109 4608 28 4 v 33 w(write)p 3344 4608 V 33 w(btblhdr)4069 4608 y SDict begin H.S end 4069 4608 a Fj(103)4205 4549 y SDict begin H.R end 4205 4549 a 4205 4608 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.2) cvn H.B /ANN pdfmark end 4205 4608 a 2982 4721 a Fj(\014ts)p 3109 4721 28 4 v 33 w(write)p 3344 4721 V 33 w(c)m(hksum)4114 4721 y SDict begin H.S end 4114 4721 a Fj(63)4205 4662 y SDict begin H.R end 4205 4662 a 4205 4721 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.1) cvn H.B /ANN pdfmark end 4205 4721 a 2982 4833 a Fj(\014ts)p 3109 4833 28 4 v 33 w(write)p 3344 4833 V 33 w(col)4114 4833 y SDict begin H.S end 4114 4833 a Fj(58)4205 4775 y SDict begin H.R end 4205 4775 a 4205 4833 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.4) cvn H.B /ANN pdfmark end 4205 4833 a 2982 4946 a Fj(\014ts)p 3109 4946 28 4 v 33 w(write)p 3344 4946 V 33 w(col)p 3487 4946 V 34 w(bit)4069 4946 y SDict begin H.S end 4069 4946 a Fj(118)4205 4888 y SDict begin H.R end 4205 4888 a 4205 4946 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.3) cvn H.B /ANN pdfmark end 4205 4946 a 2982 5059 a Fj(\014ts)p 3109 5059 28 4 v 33 w(write)p 3344 5059 V 33 w(col)p 3487 5059 V 34 w(TYP)4069 5059 y SDict begin H.S end 4069 5059 a Fj(117)4205 5001 y SDict begin H.R end 4205 5001 a 4205 5059 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.3) cvn H.B /ANN pdfmark end 4205 5059 a 2982 5172 a Fj(\014ts)p 3109 5172 28 4 v 33 w(write)p 3344 5172 V 33 w(col)p 3487 5172 V 34 w(n)m(ull)4114 5172 y SDict begin H.S end 4114 5172 a Fj(58)4205 5114 y SDict begin H.R end 4205 5114 a 4205 5172 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.4) cvn H.B /ANN pdfmark end 4205 5172 a 2982 5285 a Fj(\014ts)p 3109 5285 28 4 v 33 w(write)p 3344 5285 V 33 w(coln)m(ull)4114 5285 y SDict begin H.S end 4114 5285 a Fj(58)4205 5227 y SDict begin H.R end 4205 5227 a 4205 5285 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.4) cvn H.B /ANN pdfmark end 4205 5285 a 2982 5398 a Fj(\014ts)p 3109 5398 28 4 v 33 w(write)p 3344 5398 V 33 w(coln)m(ull)p 3636 5398 V 34 w(TYP)4069 5398 y SDict begin H.S end 4069 5398 a Fj(117)4205 5339 y SDict begin H.R end 4205 5339 a 4205 5398 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.3) cvn H.B /ANN pdfmark end 4205 5398 a 2982 5511 a Fj(\014ts)p 3109 5511 28 4 v 33 w(write)p 3344 5511 V 33 w(commen)m(t)4114 5511 y SDict begin H.S end 4114 5511 a Fj(41)4205 5452 y SDict begin H.R end 4205 5452 a 4205 5511 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 4205 5511 a 2982 5624 a Fj(\014ts)p 3109 5624 28 4 v 33 w(write)p 3344 5624 V 33 w(date)4114 5624 y SDict begin H.S end 4114 5624 a Fj(41)4205 5565 y SDict begin H.R end 4205 5565 a 4205 5624 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 4205 5624 a 2982 5737 a Fj(\014ts)p 3109 5737 28 4 v 33 w(write)p 3344 5737 V 33 w(descript)4069 5737 y SDict begin H.S end 4069 5737 a Fj(118)4205 5678 y SDict begin H.R end 4205 5678 a 4205 5737 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.3) cvn H.B /ANN pdfmark end 4205 5737 a 2982 5850 a Fj(\014ts)p 3109 5850 28 4 v 33 w(write)p 3344 5850 V 33 w(errmark)4114 5850 y SDict begin H.S end 4114 5850 a Fj(32)4205 5791 y SDict begin H.R end 4205 5791 a 4205 5850 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.1) cvn H.B /ANN pdfmark end 4205 5850 a eop end %%Page: 175 183 TeXDict begin 175 182 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.175) cvn H.B /DEST pdfmark end 0 299 a 3764 w Fj(175)50 543 y(\014ts)p 177 543 28 4 v 32 w(write)p 411 543 V 33 w(errmsg)1112 543 y SDict begin H.S end 1112 543 a Fj(66)1203 484 y SDict begin H.R end 1203 484 a 1203 543 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 1203 543 a 50 656 a Fj(\014ts)p 177 656 28 4 v 32 w(write)p 411 656 V 33 w(ext)1067 656 y SDict begin H.S end 1067 656 a Fj(101)1203 597 y SDict begin H.R end 1203 597 a 1203 656 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.2) cvn H.B /ANN pdfmark end 1203 656 a 50 769 a Fj(\014ts)p 177 769 28 4 v 32 w(write)p 411 769 V 33 w(exthdr)1067 769 y SDict begin H.S end 1067 769 a Fj(102)1203 710 y SDict begin H.R end 1203 710 a 1203 769 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.2) cvn H.B /ANN pdfmark end 1203 769 a 50 882 a Fj(\014ts)p 177 882 28 4 v 32 w(write)p 411 882 V 33 w(grphdr)1067 882 y SDict begin H.S end 1067 882 a Fj(102)1203 823 y SDict begin H.R end 1203 823 a 1203 882 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.2) cvn H.B /ANN pdfmark end 1203 882 a 50 995 a Fj(\014ts)p 177 995 28 4 v 32 w(write)p 411 995 V 33 w(grppar)p 708 995 V 32 w(TYP)1067 995 y SDict begin H.S end 1067 995 a Fj(113)1203 936 y SDict begin H.R end 1203 936 a 1203 995 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 1203 995 a 50 1107 a Fj(\014ts)p 177 1107 28 4 v 32 w(write)p 411 1107 V 33 w(hdu)1112 1107 y SDict begin H.S end 1112 1107 a Fj(37)1203 1049 y SDict begin H.R end 1203 1049 a 1203 1107 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.3) cvn H.B /ANN pdfmark end 1203 1107 a 50 1220 a Fj(\014ts)p 177 1220 28 4 v 32 w(write)p 411 1220 V 33 w(history)1112 1220 y SDict begin H.S end 1112 1220 a Fj(41)1203 1162 y SDict begin H.R end 1203 1162 a 1203 1220 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 1203 1220 a 50 1333 a Fj(\014ts)p 177 1333 28 4 v 32 w(write)p 411 1333 V 33 w(img)1067 1333 y SDict begin H.S end 1067 1333 a Fj(112)1203 1275 y SDict begin H.R end 1203 1275 a 1203 1333 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 1203 1333 a 50 1446 a Fj(\014ts)p 177 1446 28 4 v 32 w(write)p 411 1446 V 33 w(img)p 590 1446 V 33 w(n)m(ull)1067 1446 y SDict begin H.S end 1067 1446 a Fj(113)1203 1388 y SDict begin H.R end 1203 1388 a 1203 1446 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 1203 1446 a 50 1559 a Fj(\014ts)p 177 1559 28 4 v 32 w(write)p 411 1559 V 33 w(img)p 590 1559 V 33 w(TYP)1067 1559 y SDict begin H.S end 1067 1559 a Fj(112)1203 1501 y SDict begin H.R end 1203 1501 a 1203 1559 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 1203 1559 a 50 1672 a Fj(\014ts)p 177 1672 28 4 v 32 w(write)p 411 1672 V 33 w(imghdr)1067 1672 y SDict begin H.S end 1067 1672 a Fj(102)1203 1613 y SDict begin H.R end 1203 1613 a 1203 1672 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.2) cvn H.B /ANN pdfmark end 1203 1672 a 50 1785 a Fj(\014ts)p 177 1785 28 4 v 32 w(write)p 411 1785 V 33 w(imgn)m(ull)1067 1785 y SDict begin H.S end 1067 1785 a Fj(112)1203 1726 y SDict begin H.R end 1203 1726 a 1203 1785 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 1203 1785 a 50 1898 a Fj(\014ts)p 177 1898 28 4 v 32 w(write)p 411 1898 V 33 w(imgn)m(ull)p 739 1898 V 33 w(TYP)1067 1898 y SDict begin H.S end 1067 1898 a Fj(112)1203 1839 y SDict begin H.R end 1203 1839 a 1203 1898 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 1203 1898 a 50 2011 a Fj(\014ts)p 177 2011 28 4 v 32 w(write)p 411 2011 V 33 w(k)m(ey)1112 2011 y SDict begin H.S end 1112 2011 a Fj(41)1203 1952 y SDict begin H.R end 1203 1952 a 1203 2011 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 1203 2011 a 50 2124 a Fj(\014ts)p 177 2124 28 4 v 32 w(write)p 411 2124 V 33 w(k)m(ey)p 577 2124 V 34 w(longstr)1067 2124 y SDict begin H.S end 1067 2124 a Fj(105)1203 2065 y SDict begin H.R end 1203 2065 a 1203 2124 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.3) cvn H.B /ANN pdfmark end 1203 2124 a 50 2237 a Fj(\014ts)p 177 2237 28 4 v 32 w(write)p 411 2237 V 33 w(k)m(ey)p 577 2237 V 34 w(longw)m(arn)1067 2237 y SDict begin H.S end 1067 2237 a Fj(105)1203 2178 y SDict begin H.R end 1203 2178 a 1203 2237 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.3) cvn H.B /ANN pdfmark end 1203 2237 a 50 2349 a Fj(\014ts)p 177 2349 28 4 v 32 w(write)p 411 2349 V 33 w(k)m(ey)p 577 2349 V 34 w(n)m(ull)1112 2349 y SDict begin H.S end 1112 2349 a Fj(41)1203 2291 y SDict begin H.R end 1203 2291 a 1203 2349 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 1203 2349 a 50 2462 a Fj(\014ts)p 177 2462 28 4 v 32 w(write)p 411 2462 V 33 w(k)m(ey)p 577 2462 V 34 w(template)1067 2462 y SDict begin H.S end 1067 2462 a Fj(106)1203 2404 y SDict begin H.R end 1203 2404 a 1203 2462 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.3) cvn H.B /ANN pdfmark end 1203 2462 a 50 2575 a Fj(\014ts)p 177 2575 28 4 v 32 w(write)p 411 2575 V 33 w(k)m(ey)p 577 2575 V 34 w(triple)1067 2575 y SDict begin H.S end 1067 2575 a Fj(106)1203 2517 y SDict begin H.R end 1203 2517 a 1203 2575 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.3) cvn H.B /ANN pdfmark end 1203 2575 a 50 2688 a Fj(\014ts)p 177 2688 28 4 v 32 w(write)p 411 2688 V 33 w(k)m(ey)p 577 2688 V 34 w(unit)1112 2688 y SDict begin H.S end 1112 2688 a Fj(42)1203 2630 y SDict begin H.R end 1203 2630 a 1203 2688 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 1203 2688 a 50 2801 a Fj(\014ts)p 177 2801 28 4 v 32 w(write)p 411 2801 V 33 w(k)m(ey)p 577 2801 V 34 w(TYP)1067 2801 y SDict begin H.S end 1067 2801 a Fj(104)1203 2743 y SDict begin H.R end 1203 2743 a 1203 2801 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.3) cvn H.B /ANN pdfmark end 1203 2801 a 50 2914 a Fj(\014ts)p 177 2914 28 4 v 32 w(write)p 411 2914 V 33 w(k)m(eys)p 613 2914 V 34 w(TYP)1067 2914 y SDict begin H.S end 1067 2914 a Fj(105)1203 2855 y SDict begin H.R end 1203 2855 a 1203 2914 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.3) cvn H.B /ANN pdfmark end 1203 2914 a 50 3027 a Fj(\014ts)p 177 3027 28 4 v 32 w(write)p 411 3027 V 33 w(k)m(eys)p 613 3027 V 34 w(histo)1112 3027 y SDict begin H.S end 1112 3027 a Fj(62)1203 2968 y SDict begin H.R end 1203 2968 a 1203 3027 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.6) cvn H.B /ANN pdfmark end 1203 3027 a 50 3140 a Fj(\014ts)p 177 3140 28 4 v 32 w(write)p 411 3140 V 33 w(n)m(ull)p 593 3140 V 33 w(img)1112 3140 y SDict begin H.S end 1112 3140 a Fj(45)1203 3081 y SDict begin H.R end 1203 3081 a 1203 3140 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 1203 3140 a 50 3253 a Fj(\014ts)p 177 3253 28 4 v 32 w(write)p 411 3253 V 33 w(n)m(ullro)m(ws)1112 3253 y SDict begin H.S end 1112 3253 a Fj(58)1203 3194 y SDict begin H.R end 1203 3194 a 1203 3253 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.4) cvn H.B /ANN pdfmark end 1203 3253 a 50 3366 a Fj(\014ts)p 177 3366 28 4 v 32 w(write)p 411 3366 V 33 w(pix)1112 3366 y SDict begin H.S end 1112 3366 a Fj(45)1203 3307 y SDict begin H.R end 1203 3307 a 1203 3366 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 1203 3366 a 50 3479 a Fj(\014ts)p 177 3479 28 4 v 32 w(write)p 411 3479 V 33 w(pixn)m(ull)1112 3479 y SDict begin H.S end 1112 3479 a Fj(45)1203 3420 y SDict begin H.R end 1203 3420 a 1203 3479 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 1203 3479 a 50 3591 a Fj(\014ts)p 177 3591 28 4 v 32 w(write)p 411 3591 V 33 w(record)1112 3591 y SDict begin H.S end 1112 3591 a Fj(42)1203 3533 y SDict begin H.R end 1203 3533 a 1203 3591 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 1203 3591 a 50 3704 a Fj(\014ts)p 177 3704 28 4 v 32 w(write)p 411 3704 V 33 w(subset)1112 3704 y SDict begin H.S end 1112 3704 a Fj(45)1203 3646 y SDict begin H.R end 1203 3646 a 1203 3704 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 1203 3704 a 50 3817 a Fj(\014ts)p 177 3817 28 4 v 32 w(write)p 411 3817 V 33 w(subset)p 693 3817 V 32 w(TYP)1067 3817 y SDict begin H.S end 1067 3817 a Fj(113)1203 3759 y SDict begin H.R end 1203 3759 a 1203 3817 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 1203 3817 a 50 3930 a Fj(\014ts)p 177 3930 28 4 v 32 w(write)p 411 3930 V 33 w(tblb)m(ytes)1067 3930 y SDict begin H.S end 1067 3930 a Fj(117)1203 3872 y SDict begin H.R end 1203 3872 a 1203 3930 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.2) cvn H.B /ANN pdfmark end 1203 3930 a 50 4043 a Fj(\014ts)p 177 4043 28 4 v 32 w(write)p 411 4043 V 33 w(tdim)1112 4043 y SDict begin H.S end 1112 4043 a Fj(55)1203 3985 y SDict begin H.R end 1203 3985 a 1203 4043 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.2) cvn H.B /ANN pdfmark end 1203 4043 a 50 4156 a Fj(\014ts)p 177 4156 28 4 v 32 w(write)p 411 4156 V 33 w(theap)1067 4156 y SDict begin H.S end 1067 4156 a Fj(116)1203 4097 y SDict begin H.R end 1203 4097 a 1203 4156 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.1) cvn H.B /ANN pdfmark end 1203 4156 a eop end %%Page: 176 184 TeXDict begin 176 183 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.176) cvn H.B /DEST pdfmark end 0 299 a Fj(176)2084 b Fh(APPENDIX)31 b(A.)61 b(INDEX)31 b(OF)f(R)m(OUTINES)50 543 y Fj(\013asfm)564 543 y SDict begin H.S end 564 543 a Fj(70)655 484 y SDict begin H.R end 655 484 a 655 543 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 655 543 a 50 656 a Fj(\013bnfm)564 656 y SDict begin H.S end 564 656 a Fj(70)655 597 y SDict begin H.R end 655 597 a 655 656 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 655 656 a 50 769 a Fj(\013calc)564 769 y SDict begin H.S end 564 769 a Fj(60)655 710 y SDict begin H.R end 655 710 a 655 769 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.5) cvn H.B /ANN pdfmark end 655 769 a 50 882 a Fj(\013calc)p 258 882 28 4 v 34 w(rng)564 882 y SDict begin H.S end 564 882 a Fj(60)655 823 y SDict begin H.R end 655 823 a 655 882 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.5) cvn H.B /ANN pdfmark end 655 882 a 50 995 a Fj(\013c)m(h)m(tps)564 995 y SDict begin H.S end 564 995 a Fj(99)655 936 y SDict begin H.R end 655 936 a 655 995 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.1) cvn H.B /ANN pdfmark end 655 995 a 50 1107 a Fj(\013clos)564 1107 y SDict begin H.S end 564 1107 a Fj(35)655 1049 y SDict begin H.R end 655 1049 a 655 1107 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.2) cvn H.B /ANN pdfmark end 655 1107 a 50 1220 a Fj(\013cmph)518 1220 y SDict begin H.S end 518 1220 a Fj(116)655 1162 y SDict begin H.R end 655 1162 a 655 1220 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.1) cvn H.B /ANN pdfmark end 655 1220 a 50 1333 a Fj(\013cmps)564 1333 y SDict begin H.S end 564 1333 a Fj(66)655 1275 y SDict begin H.R end 655 1275 a 655 1333 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 655 1333 a 50 1446 a Fj(\013cmrk)564 1446 y SDict begin H.S end 564 1446 a Fj(32)655 1388 y SDict begin H.R end 655 1388 a 655 1446 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.1) cvn H.B /ANN pdfmark end 655 1446 a 50 1559 a Fj(\013cmsg)564 1559 y SDict begin H.S end 564 1559 a Fj(32)655 1501 y SDict begin H.R end 655 1501 a 655 1559 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.1) cvn H.B /ANN pdfmark end 655 1559 a 50 1672 a Fj(\013cop)m(y)564 1672 y SDict begin H.S end 564 1672 a Fj(37)655 1613 y SDict begin H.R end 655 1613 a 655 1672 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.3) cvn H.B /ANN pdfmark end 655 1672 a 50 1785 a Fj(\013cp)s(cl)564 1785 y SDict begin H.S end 564 1785 a Fj(57)655 1726 y SDict begin H.R end 655 1726 a 655 1785 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.3) cvn H.B /ANN pdfmark end 655 1785 a 50 1898 a Fj(\013cp)s(dt)518 1898 y SDict begin H.S end 518 1898 a Fj(101)655 1839 y SDict begin H.R end 655 1839 a 655 1898 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.2) cvn H.B /ANN pdfmark end 655 1898 a 50 2011 a Fj(\013cp\015)564 2011 y SDict begin H.S end 564 2011 a Fj(36)655 1952 y SDict begin H.R end 655 1952 a 655 2011 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.3) cvn H.B /ANN pdfmark end 655 2011 a 50 2124 a Fj(\013cphd)564 2124 y SDict begin H.S end 564 2124 a Fj(37)655 2065 y SDict begin H.R end 655 2065 a 655 2124 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.3) cvn H.B /ANN pdfmark end 655 2124 a 50 2237 a Fj(\013cpimg)564 2237 y SDict begin H.S end 564 2237 a Fj(47)655 2178 y SDict begin H.R end 655 2178 a 655 2237 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 655 2237 a 50 2349 a Fj(\013cpky)518 2349 y SDict begin H.S end 518 2349 a Fj(106)655 2291 y SDict begin H.R end 655 2291 a 655 2349 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.3) cvn H.B /ANN pdfmark end 655 2349 a 50 2462 a Fj(\013cprw)564 2462 y SDict begin H.S end 564 2462 a Fj(57)655 2404 y SDict begin H.R end 655 2404 a 655 2462 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.3) cvn H.B /ANN pdfmark end 655 2462 a 50 2575 a Fj(\013crhd)564 2575 y SDict begin H.S end 564 2575 a Fj(99)655 2517 y SDict begin H.R end 655 2517 a 655 2575 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.2) cvn H.B /ANN pdfmark end 655 2575 a 50 2688 a Fj(\013crim)564 2688 y SDict begin H.S end 564 2688 a Fj(44)655 2630 y SDict begin H.R end 655 2630 a 655 2688 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 655 2688 a 50 2801 a Fj(\013cro)m(w)564 2801 y SDict begin H.S end 564 2801 a Fj(60)655 2743 y SDict begin H.R end 655 2743 a 655 2801 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.5) cvn H.B /ANN pdfmark end 655 2801 a 50 2914 a Fj(\013crtb)564 2914 y SDict begin H.S end 564 2914 a Fj(52)655 2855 y SDict begin H.R end 655 2855 a 655 2914 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.1) cvn H.B /ANN pdfmark end 655 2914 a 50 3027 a Fj(\013dcol)564 3027 y SDict begin H.S end 564 3027 a Fj(56)655 2968 y SDict begin H.R end 655 2968 a 655 3027 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.3) cvn H.B /ANN pdfmark end 655 3027 a 50 3140 a Fj(\013delt)564 3140 y SDict begin H.S end 564 3140 a Fj(35)655 3081 y SDict begin H.R end 655 3081 a 655 3140 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.2) cvn H.B /ANN pdfmark end 655 3140 a 50 3253 a Fj(\013dhdu)564 3253 y SDict begin H.S end 564 3253 a Fj(37)655 3194 y SDict begin H.R end 655 3194 a 655 3253 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.3) cvn H.B /ANN pdfmark end 655 3253 a 50 3366 a Fj(\013dk)m(ey)564 3366 y SDict begin H.S end 564 3366 a Fj(42)655 3307 y SDict begin H.R end 655 3307 a 655 3366 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 655 3366 a 50 3479 a Fj(\013dkinit)564 3479 y SDict begin H.S end 564 3479 a Fj(34)655 3420 y SDict begin H.R end 655 3420 a 655 3479 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.2) cvn H.B /ANN pdfmark end 655 3479 a 50 3591 a Fj(\013dk)m(op)s(en) 564 3591 y SDict begin H.S end 564 3591 a Fj(32)655 3533 y SDict begin H.R end 655 3533 a 655 3591 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.2) cvn H.B /ANN pdfmark end 655 3591 a 50 3704 a Fj(\013dopn)564 3704 y SDict begin H.S end 564 3704 a Fj(32)655 3646 y SDict begin H.R end 655 3646 a 655 3704 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.2) cvn H.B /ANN pdfmark end 655 3704 a 50 3817 a Fj(\013drec)564 3817 y SDict begin H.S end 564 3817 a Fj(42)655 3759 y SDict begin H.R end 655 3759 a 655 3817 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 655 3817 a 50 3930 a Fj(\013dro)m(w)564 3930 y SDict begin H.S end 564 3930 a Fj(56)655 3872 y SDict begin H.R end 655 3872 a 655 3930 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.3) cvn H.B /ANN pdfmark end 655 3930 a 50 4043 a Fj(\013drrg)564 4043 y SDict begin H.S end 564 4043 a Fj(56)655 3985 y SDict begin H.R end 655 3985 a 655 4043 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.3) cvn H.B /ANN pdfmark end 655 4043 a 50 4156 a Fj(\013drws)564 4156 y SDict begin H.S end 564 4156 a Fj(56)655 4097 y SDict begin H.R end 655 4097 a 655 4156 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.3) cvn H.B /ANN pdfmark end 655 4156 a 50 4269 a Fj(\013dstr)564 4269 y SDict begin H.S end 564 4269 a Fj(42)655 4210 y SDict begin H.R end 655 4210 a 655 4269 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 655 4269 a 50 4382 a Fj(\013dsum)564 4382 y SDict begin H.S end 564 4382 a Fj(64)655 4323 y SDict begin H.R end 655 4323 a 655 4382 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.1) cvn H.B /ANN pdfmark end 655 4382 a 50 4495 a Fj(\013dt2s)564 4495 y SDict begin H.S end 564 4495 a Fj(65)655 4436 y SDict begin H.R end 655 4436 a 655 4495 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.2) cvn H.B /ANN pdfmark end 655 4495 a 50 4608 a Fj(\013dtdm)564 4608 y SDict begin H.S end 564 4608 a Fj(55)655 4549 y SDict begin H.R end 655 4549 a 655 4608 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.2) cvn H.B /ANN pdfmark end 655 4608 a 50 4721 a Fj(\013dt)m(yp)564 4721 y SDict begin H.S end 564 4721 a Fj(68)655 4662 y SDict begin H.R end 655 4662 a 655 4721 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 655 4721 a 50 4833 a Fj(\013eopn)564 4833 y SDict begin H.S end 564 4833 a Fj(32)655 4775 y SDict begin H.R end 655 4775 a 655 4833 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.2) cvn H.B /ANN pdfmark end 655 4833 a 50 4946 a Fj(\013eqt)m(y)564 4946 y SDict begin H.S end 564 4946 a Fj(54)655 4888 y SDict begin H.R end 655 4888 a 655 4946 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.2) cvn H.B /ANN pdfmark end 655 4946 a 50 5059 a Fj(\013esum)564 5059 y SDict begin H.S end 564 5059 a Fj(64)655 5001 y SDict begin H.R end 655 5001 a 655 5059 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.1) cvn H.B /ANN pdfmark end 655 5059 a 50 5172 a Fj(\013exest)564 5172 y SDict begin H.S end 564 5172 a Fj(98)655 5114 y SDict begin H.R end 655 5114 a 655 5172 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.1) cvn H.B /ANN pdfmark end 655 5172 a 50 5285 a Fj(\013extn)564 5285 y SDict begin H.S end 564 5285 a Fj(97)655 5227 y SDict begin H.R end 655 5227 a 655 5285 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.1) cvn H.B /ANN pdfmark end 655 5285 a 50 5398 a Fj(\013\013rw)564 5398 y SDict begin H.S end 564 5398 a Fj(60)655 5339 y SDict begin H.R end 655 5339 a 655 5398 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.5) cvn H.B /ANN pdfmark end 655 5398 a 50 5511 a Fj(\013\015md)564 5511 y SDict begin H.S end 564 5511 a Fj(35)655 5452 y SDict begin H.R end 655 5452 a 655 5511 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.2) cvn H.B /ANN pdfmark end 655 5511 a 50 5624 a Fj(\013\015nm)564 5624 y SDict begin H.S end 564 5624 a Fj(35)655 5565 y SDict begin H.R end 655 5565 a 655 5624 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.2) cvn H.B /ANN pdfmark end 655 5624 a 50 5737 a Fj(\013\015sh)564 5737 y SDict begin H.S end 564 5737 a Fj(98)655 5678 y SDict begin H.R end 655 5678 a 655 5737 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.1) cvn H.B /ANN pdfmark end 655 5737 a 50 5850 a Fj(\013\015us)564 5850 y SDict begin H.S end 564 5850 a Fj(98)655 5791 y SDict begin H.R end 655 5791 a 655 5850 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.1) cvn H.B /ANN pdfmark end 655 5850 a 785 543 a Fj(\013free)1157 543 y SDict begin H.S end 1157 543 a Fj(107)1293 484 y SDict begin H.R end 1293 484 a 1293 543 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.5) cvn H.B /ANN pdfmark end 1293 543 a Fj(,)1349 543 y SDict begin H.S end 1349 543 a Fj(40)1440 484 y SDict begin H.R end 1440 484 a 1440 543 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.1) cvn H.B /ANN pdfmark end 1440 543 a 785 656 a Fj(\013fro)m(w)1349 656 y SDict begin H.S end 1349 656 a Fj(59)1440 597 y SDict begin H.R end 1440 597 a 1440 656 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.5) cvn H.B /ANN pdfmark end 1440 656 a 785 769 a Fj(\013g2d)p 984 769 28 4 v 1303 769 a SDict begin H.S end 1303 769 a Fj(114)1440 710 y SDict begin H.R end 1440 710 a 1440 769 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 1440 769 a 785 882 a Fj(\013g3d)p 984 882 28 4 v 1303 882 a SDict begin H.S end 1303 882 a Fj(114)1440 823 y SDict begin H.R end 1440 823 a 1440 882 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 1440 882 a 785 995 a Fj(\013gab)s(c)1349 995 y SDict begin H.S end 1349 995 a Fj(70)1440 936 y SDict begin H.R end 1440 936 a 1440 995 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 1440 995 a 785 1107 a Fj(\013gacl)1303 1107 y SDict begin H.S end 1303 1107 a Fj(115)1440 1049 y SDict begin H.R end 1440 1049 a 1440 1107 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.1) cvn H.B /ANN pdfmark end 1440 1107 a 785 1220 a Fj(\013gb)s(cl)1303 1220 y SDict begin H.S end 1303 1220 a Fj(115)1440 1162 y SDict begin H.R end 1440 1162 a 1440 1220 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.1) cvn H.B /ANN pdfmark end 1440 1220 a 785 1333 a Fj(\013gcdw)1349 1333 y SDict begin H.S end 1349 1333 a Fj(55)1440 1275 y SDict begin H.R end 1440 1275 a 1440 1333 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.2) cvn H.B /ANN pdfmark end 1440 1333 a 785 1446 a Fj(\013gcf)1349 1446 y SDict begin H.S end 1349 1446 a Fj(59)1440 1388 y SDict begin H.R end 1440 1388 a 1440 1446 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.4) cvn H.B /ANN pdfmark end 1440 1446 a 785 1559 a Fj(\013gcf)p 956 1559 28 4 v 1303 1559 a SDict begin H.S end 1303 1559 a Fj(119)1440 1501 y SDict begin H.R end 1440 1501 a 1440 1559 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.4) cvn H.B /ANN pdfmark end 1440 1559 a 785 1672 a Fj(\013gc)m(ks)1349 1672 y SDict begin H.S end 1349 1672 a Fj(64)1440 1613 y SDict begin H.R end 1440 1613 a 1440 1672 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.1) cvn H.B /ANN pdfmark end 1440 1672 a 785 1785 a Fj(\013gcnn)1349 1785 y SDict begin H.S end 1349 1785 a Fj(53)1440 1726 y SDict begin H.R end 1440 1726 a 1440 1785 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.2) cvn H.B /ANN pdfmark end 1440 1785 a 785 1898 a Fj(\013gcno)1349 1898 y SDict begin H.S end 1349 1898 a Fj(53)1440 1839 y SDict begin H.R end 1440 1839 a 1440 1898 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.2) cvn H.B /ANN pdfmark end 1440 1898 a 785 2011 a Fj(\013gcrd)1349 2011 y SDict begin H.S end 1349 2011 a Fj(38)1440 1952 y SDict begin H.R end 1440 1952 a 1440 2011 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.1) cvn H.B /ANN pdfmark end 1440 2011 a 785 2124 a Fj(\013gcv)1349 2124 y SDict begin H.S end 1349 2124 a Fj(59)1440 2065 y SDict begin H.R end 1440 2065 a 1440 2124 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.4) cvn H.B /ANN pdfmark end 1440 2124 a 785 2237 a Fj(\013gcv)p 976 2237 28 4 v 1303 2237 a SDict begin H.S end 1303 2237 a Fj(119)1440 2178 y SDict begin H.R end 1440 2178 a 1440 2237 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.4) cvn H.B /ANN pdfmark end 1440 2237 a 785 2349 a Fj(\013gcx)1303 2349 y SDict begin H.S end 1303 2349 a Fj(120)1440 2291 y SDict begin H.R end 1440 2291 a 1440 2349 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.4) cvn H.B /ANN pdfmark end 1440 2349 a 785 2462 a Fj(\013gdes)1303 2462 y SDict begin H.S end 1303 2462 a Fj(121)1440 2404 y SDict begin H.R end 1440 2404 a 1440 2462 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.4) cvn H.B /ANN pdfmark end 1440 2462 a 785 2575 a Fj(\013gdess)1303 2575 y SDict begin H.S end 1303 2575 a Fj(121)1440 2517 y SDict begin H.R end 1440 2517 a 1440 2575 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.4) cvn H.B /ANN pdfmark end 1440 2575 a 785 2688 a Fj(\013gerr)1349 2688 y SDict begin H.S end 1349 2688 a Fj(31)1440 2630 y SDict begin H.R end 1440 2630 a 1440 2688 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.1) cvn H.B /ANN pdfmark end 1440 2688 a 785 2801 a Fj(\013gextn)1303 2801 y SDict begin H.S end 1303 2801 a Fj(101)1440 2743 y SDict begin H.R end 1440 2743 a 1440 2801 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.2) cvn H.B /ANN pdfmark end 1440 2801 a 785 2914 a Fj(\013ggp)p 984 2914 28 4 v 1303 2914 a SDict begin H.S end 1303 2914 a Fj(114)1440 2855 y SDict begin H.R end 1440 2855 a 1440 2914 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 1440 2914 a 785 3027 a Fj(\013ghad)1349 3027 y SDict begin H.S end 1349 3027 a Fj(99)1440 2968 y SDict begin H.R end 1440 2968 a 1440 3027 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.2) cvn H.B /ANN pdfmark end 1440 3027 a 785 3140 a Fj(\013gh)m(bn)1303 3140 y SDict begin H.S end 1303 3140 a Fj(103)1440 3081 y SDict begin H.R end 1440 3081 a 1440 3140 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.2) cvn H.B /ANN pdfmark end 1440 3140 a 785 3253 a Fj(\013ghdn)1349 3253 y SDict begin H.S end 1349 3253 a Fj(36)1440 3194 y SDict begin H.R end 1440 3194 a 1440 3253 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.3) cvn H.B /ANN pdfmark end 1440 3253 a 785 3366 a Fj(\013ghdt)1349 3366 y SDict begin H.S end 1349 3366 a Fj(36)1440 3307 y SDict begin H.R end 1440 3307 a 1440 3366 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.3) cvn H.B /ANN pdfmark end 1440 3366 a 785 3479 a Fj(\013ghpr)1303 3479 y SDict begin H.S end 1303 3479 a Fj(103)1440 3420 y SDict begin H.R end 1440 3420 a 1440 3479 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.2) cvn H.B /ANN pdfmark end 1440 3479 a 785 3591 a Fj(\013ghps)1303 3591 y SDict begin H.S end 1303 3591 a Fj(102)1440 3533 y SDict begin H.R end 1440 3533 a 1440 3591 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.1) cvn H.B /ANN pdfmark end 1440 3591 a 785 3704 a Fj(\013ghsp)1349 3704 y SDict begin H.S end 1349 3704 a Fj(38)1440 3646 y SDict begin H.R end 1440 3646 a 1440 3704 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.1) cvn H.B /ANN pdfmark end 1440 3704 a 785 3817 a Fj(\013gh)m(tb)1303 3817 y SDict begin H.S end 1303 3817 a Fj(103)1440 3759 y SDict begin H.R end 1440 3759 a 1440 3817 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.2) cvn H.B /ANN pdfmark end 1440 3817 a 785 3930 a Fj(\013gics)1349 3930 y SDict begin H.S end 1349 3930 a Fj(87)1440 3872 y SDict begin H.R end 1440 3872 a 1440 3930 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.7.1) cvn H.B /ANN pdfmark end 1440 3930 a 785 4043 a Fj(\013gidm)1349 4043 y SDict begin H.S end 1349 4043 a Fj(43)1440 3985 y SDict begin H.R end 1440 3985 a 1440 4043 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 1440 4043 a 785 4156 a Fj(\013gidt)1349 4156 y SDict begin H.S end 1349 4156 a Fj(43)1440 4097 y SDict begin H.R end 1440 4097 a 1440 4156 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 1440 4156 a 785 4269 a Fj(\013giet)1349 4269 y SDict begin H.S end 1349 4269 a Fj(43)1440 4210 y SDict begin H.R end 1440 4210 a 1440 4269 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 1440 4269 a 785 4382 a Fj(\013gipr)1349 4382 y SDict begin H.S end 1349 4382 a Fj(43)1440 4323 y SDict begin H.R end 1440 4323 a 1440 4382 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 1440 4382 a 785 4495 a Fj(\013gisz)1349 4495 y SDict begin H.S end 1349 4495 a Fj(43)1440 4436 y SDict begin H.R end 1440 4436 a 1440 4495 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 1440 4495 a 785 4608 a Fj(\013gk)m(cl)1349 4608 y SDict begin H.S end 1349 4608 a Fj(69)1440 4549 y SDict begin H.R end 1440 4549 a 1440 4608 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 1440 4608 a 785 4721 a Fj(\013gk)m(ey)1349 4721 y SDict begin H.S end 1349 4721 a Fj(38)1440 4662 y SDict begin H.R end 1440 4662 a 1440 4721 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.1) cvn H.B /ANN pdfmark end 1440 4721 a 785 4833 a Fj(\013gkls)1303 4833 y SDict begin H.S end 1303 4833 a Fj(107)1440 4775 y SDict begin H.R end 1440 4775 a 1440 4833 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.5) cvn H.B /ANN pdfmark end 1440 4833 a 785 4946 a Fj(\013gksl)1349 4946 y SDict begin H.S end 1349 4946 a Fj(39)1440 4888 y SDict begin H.R end 1440 4888 a 1440 4946 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.1) cvn H.B /ANN pdfmark end 1440 4946 a 785 5059 a Fj(\013gkn)p 987 5059 28 4 v 1303 5059 a SDict begin H.S end 1303 5059 a Fj(108)1440 5001 y SDict begin H.R end 1440 5001 a 1440 5059 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.5) cvn H.B /ANN pdfmark end 1440 5059 a 785 5172 a Fj(\013gknm)1349 5172 y SDict begin H.S end 1349 5172 a Fj(67)1440 5114 y SDict begin H.R end 1440 5114 a 1440 5172 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 1440 5172 a 785 5285 a Fj(\013gky)1349 5285 y SDict begin H.S end 1349 5285 a Fj(38)1440 5227 y SDict begin H.R end 1440 5227 a 1440 5285 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.1) cvn H.B /ANN pdfmark end 1440 5285 a 785 5398 a Fj(\013gkyn)1349 5398 y SDict begin H.S end 1349 5398 a Fj(39)1440 5339 y SDict begin H.R end 1440 5339 a 1440 5398 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.1) cvn H.B /ANN pdfmark end 1440 5398 a 785 5511 a Fj(\013gkyt)1303 5511 y SDict begin H.S end 1303 5511 a Fj(108)1440 5452 y SDict begin H.R end 1440 5452 a 1440 5511 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.5) cvn H.B /ANN pdfmark end 1440 5511 a 785 5624 a Fj(\013gky)p 984 5624 28 4 v 1303 5624 a SDict begin H.S end 1303 5624 a Fj(107)1440 5565 y SDict begin H.R end 1440 5565 a 1440 5624 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.5) cvn H.B /ANN pdfmark end 1440 5624 a 785 5737 a Fj(\013gmcp)1349 5737 y SDict begin H.S end 1349 5737 a Fj(93)1440 5678 y SDict begin H.R end 1440 5678 a 1440 5737 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.2) cvn H.B /ANN pdfmark end 1440 5737 a 785 5850 a Fj(\013gmng)1349 5850 y SDict begin H.S end 1349 5850 a Fj(93)1440 5791 y SDict begin H.R end 1440 5791 a 1440 5850 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.2) cvn H.B /ANN pdfmark end 1440 5850 a 1570 543 a Fj(\013gmop)2167 543 y SDict begin H.S end 2167 543 a Fj(93)2258 484 y SDict begin H.R end 2258 484 a 2258 543 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.2) cvn H.B /ANN pdfmark end 2258 543 a 1570 656 a Fj(\013gmrm)2167 656 y SDict begin H.S end 2167 656 a Fj(94)2258 597 y SDict begin H.R end 2258 597 a 2258 656 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.2) cvn H.B /ANN pdfmark end 2258 656 a 1570 769 a Fj(\013gmsg)2167 769 y SDict begin H.S end 2167 769 a Fj(32)2258 710 y SDict begin H.R end 2258 710 a 2258 769 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.1) cvn H.B /ANN pdfmark end 2258 769 a 1570 882 a Fj(\013gm)m(tf)2167 882 y SDict begin H.S end 2167 882 a Fj(93)2258 823 y SDict begin H.R end 2258 823 a 2258 882 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.2) cvn H.B /ANN pdfmark end 2258 882 a 1570 995 a Fj(\013gncl)2167 995 y SDict begin H.S end 2167 995 a Fj(53)2258 936 y SDict begin H.R end 2258 936 a 2258 995 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.2) cvn H.B /ANN pdfmark end 2258 995 a 1570 1107 a Fj(\013gnrw)2167 1107 y SDict begin H.S end 2167 1107 a Fj(53)2258 1049 y SDict begin H.R end 2258 1049 a 2258 1107 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.2) cvn H.B /ANN pdfmark end 2258 1107 a 1570 1220 a Fj(\013gnxk)2167 1220 y SDict begin H.S end 2167 1220 a Fj(39)2258 1162 y SDict begin H.R end 2258 1162 a 2258 1220 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.1) cvn H.B /ANN pdfmark end 2258 1220 a 1570 1333 a Fj(\013gpf)2122 1333 y SDict begin H.S end 2122 1333 a Fj(114)2258 1275 y SDict begin H.R end 2258 1275 a 2258 1333 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 2258 1333 a 1570 1446 a Fj(\013gpf)p 1752 1446 28 4 v 2122 1446 a SDict begin H.S end 2122 1446 a Fj(114)2258 1388 y SDict begin H.R end 2258 1388 a 2258 1446 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 2258 1446 a 1570 1559 a Fj(\013gp)m(v)2122 1559 y SDict begin H.S end 2122 1559 a Fj(114)2258 1501 y SDict begin H.R end 2258 1501 a 2258 1559 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 2258 1559 a 1570 1672 a Fj(\013gp)m(v)p 1769 1672 28 4 v 2122 1672 a SDict begin H.S end 2122 1672 a Fj(114)2258 1613 y SDict begin H.R end 2258 1613 a 2258 1672 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 2258 1672 a 1570 1785 a Fj(\013gp)m(xv)2167 1785 y SDict begin H.S end 2167 1785 a Fj(46)2258 1726 y SDict begin H.R end 2258 1726 a 2258 1785 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 2258 1785 a 1570 1898 a Fj(\013gp)m(xf)2167 1898 y SDict begin H.S end 2167 1898 a Fj(46)2258 1839 y SDict begin H.R end 2258 1839 a 2258 1898 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 2258 1898 a 1570 2011 a Fj(\013grec)2167 2011 y SDict begin H.S end 2167 2011 a Fj(39)2258 1952 y SDict begin H.R end 2258 1952 a 2258 2011 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.1) cvn H.B /ANN pdfmark end 2258 2011 a 1570 2124 a Fj(\013grsz)2122 2124 y SDict begin H.S end 2122 2124 a Fj(116)2258 2065 y SDict begin H.R end 2258 2065 a 2258 2124 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.1) cvn H.B /ANN pdfmark end 2258 2124 a 1570 2237 a Fj(\013gsdt)2167 2237 y SDict begin H.S end 2167 2237 a Fj(65)2258 2178 y SDict begin H.R end 2258 2178 a 2258 2237 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.2) cvn H.B /ANN pdfmark end 2258 2237 a 1570 2349 a Fj(\013gsf)p 1737 2349 28 4 v 1955 2349 a SDict begin H.S end 1955 2349 a Fj(115)2091 2291 y SDict begin H.R end 2091 2291 a 2091 2349 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 2091 2349 a 2122 2349 a SDict begin H.S end 2122 2349 a Fj(120)2258 2291 y SDict begin H.R end 2258 2291 a 2258 2349 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.4) cvn H.B /ANN pdfmark end 2258 2349 a 1570 2462 a Fj(\013gsky)2167 2462 y SDict begin H.S end 2167 2462 a Fj(39)2258 2404 y SDict begin H.R end 2258 2404 a 2258 2462 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.1) cvn H.B /ANN pdfmark end 2258 2462 a 1570 2575 a Fj(\013gstm)2167 2575 y SDict begin H.S end 2167 2575 a Fj(65)2258 2517 y SDict begin H.R end 2258 2517 a 2258 2575 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.2) cvn H.B /ANN pdfmark end 2258 2575 a 1570 2688 a Fj(\013gstr)2167 2688 y SDict begin H.S end 2167 2688 a Fj(38)2258 2630 y SDict begin H.R end 2258 2630 a 2258 2688 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.1) cvn H.B /ANN pdfmark end 2258 2688 a 1570 2801 a Fj(\013gsv)2167 2801 y SDict begin H.S end 2167 2801 a Fj(46)2258 2743 y SDict begin H.R end 2258 2743 a 2258 2801 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 2258 2801 a 1570 2914 a Fj(\013gsv)p 1757 2914 28 4 v 1955 2914 a SDict begin H.S end 1955 2914 a Fj(115)2091 2855 y SDict begin H.R end 2091 2855 a 2091 2914 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 2091 2914 a 2122 2914 a SDict begin H.S end 2122 2914 a Fj(119)2258 2855 y SDict begin H.R end 2258 2855 a 2258 2914 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.4) cvn H.B /ANN pdfmark end 2258 2914 a 1570 3027 a Fj(\013gtam)2167 3027 y SDict begin H.S end 2167 3027 a Fj(92)2258 2968 y SDict begin H.R end 2258 2968 a 2258 3027 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.1) cvn H.B /ANN pdfmark end 2258 3027 a 1570 3140 a Fj(\013gtbb)2122 3140 y SDict begin H.S end 2122 3140 a Fj(117)2258 3081 y SDict begin H.R end 2258 3081 a 2258 3140 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.2) cvn H.B /ANN pdfmark end 2258 3140 a 1570 3253 a Fj(\013gtc)m(h)2167 3253 y SDict begin H.S end 2167 3253 a Fj(90)2258 3194 y SDict begin H.R end 2258 3194 a 2258 3253 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.1) cvn H.B /ANN pdfmark end 2258 3253 a 1570 3366 a Fj(\013gtcl)2167 3366 y SDict begin H.S end 2167 3366 a Fj(54)2258 3307 y SDict begin H.R end 2258 3307 a 2258 3366 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.2) cvn H.B /ANN pdfmark end 2258 3366 a 1570 3479 a Fj(\013gtcm)2167 3479 y SDict begin H.S end 2167 3479 a Fj(91)2258 3420 y SDict begin H.R end 2258 3420 a 2258 3479 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.1) cvn H.B /ANN pdfmark end 2258 3479 a 1570 3591 a Fj(\013gtcp)2167 3591 y SDict begin H.S end 2167 3591 a Fj(91)2258 3533 y SDict begin H.R end 2258 3533 a 2258 3591 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.1) cvn H.B /ANN pdfmark end 2258 3591 a 1570 3704 a Fj(\013gtcr)2167 3704 y SDict begin H.S end 2167 3704 a Fj(90)2258 3646 y SDict begin H.R end 2258 3646 a 2258 3704 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.1) cvn H.B /ANN pdfmark end 2258 3704 a 1570 3817 a Fj(\013gtcs)2167 3817 y SDict begin H.S end 2167 3817 a Fj(87)2258 3759 y SDict begin H.R end 2258 3759 a 2258 3817 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.7.1) cvn H.B /ANN pdfmark end 2258 3817 a 1570 3930 a Fj(\013gtdm)2167 3930 y SDict begin H.S end 2167 3930 a Fj(55)2258 3872 y SDict begin H.R end 2258 3872 a 2258 3930 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.2) cvn H.B /ANN pdfmark end 2258 3930 a 1570 4043 a Fj(\013gthd)2167 4043 y SDict begin H.S end 2167 4043 a Fj(70)2258 3985 y SDict begin H.R end 2258 3985 a 2258 4043 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 2258 4043 a 1570 4156 a Fj(\013gtis)2167 4156 y SDict begin H.S end 2167 4156 a Fj(90)2258 4097 y SDict begin H.R end 2258 4097 a 2258 4156 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.1) cvn H.B /ANN pdfmark end 2258 4156 a 1570 4269 a Fj(\013gtmg)2167 4269 y SDict begin H.S end 2167 4269 a Fj(91)2258 4210 y SDict begin H.R end 2258 4210 a 2258 4269 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.1) cvn H.B /ANN pdfmark end 2258 4269 a 1570 4382 a Fj(\013gtnm)2167 4382 y SDict begin H.S end 2167 4382 a Fj(92)2258 4323 y SDict begin H.R end 2258 4323 a 2258 4382 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.2) cvn H.B /ANN pdfmark end 2258 4382 a 1570 4495 a Fj(\013gtop)2167 4495 y SDict begin H.S end 2167 4495 a Fj(92)2258 4436 y SDict begin H.R end 2258 4436 a 2258 4495 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.1) cvn H.B /ANN pdfmark end 2258 4495 a 1570 4608 a Fj(\013gtrm)2167 4608 y SDict begin H.S end 2167 4608 a Fj(91)2258 4549 y SDict begin H.R end 2258 4549 a 2258 4608 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.1) cvn H.B /ANN pdfmark end 2258 4608 a 1570 4721 a Fj(\013gtvf)2167 4721 y SDict begin H.S end 2167 4721 a Fj(92)2258 4662 y SDict begin H.R end 2258 4662 a 2258 4721 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.8.1) cvn H.B /ANN pdfmark end 2258 4721 a 1570 4833 a Fj(\013gun)m(t)2167 4833 y SDict begin H.S end 2167 4833 a Fj(40)2258 4775 y SDict begin H.R end 2258 4775 a 2258 4833 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.1) cvn H.B /ANN pdfmark end 2258 4833 a 1570 4946 a Fj(\013hdef)2122 4946 y SDict begin H.S end 2122 4946 a Fj(102)2258 4888 y SDict begin H.R end 2258 4888 a 2258 4946 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.1) cvn H.B /ANN pdfmark end 2258 4946 a 1570 5059 a Fj(\016bin)2122 5059 y SDict begin H.S end 2122 5059 a Fj(100)2258 5001 y SDict begin H.R end 2258 5001 a 2258 5059 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.2) cvn H.B /ANN pdfmark end 2258 5059 a 1570 5172 a Fj(\016cls)2167 5172 y SDict begin H.S end 2167 5172 a Fj(56)2258 5114 y SDict begin H.R end 2258 5114 a 2258 5172 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.3) cvn H.B /ANN pdfmark end 2258 5172 a 1570 5285 a Fj(\016col)2167 5285 y SDict begin H.S end 2167 5285 a Fj(56)2258 5227 y SDict begin H.R end 2258 5227 a 2258 5285 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.3) cvn H.B /ANN pdfmark end 2258 5285 a 1570 5398 a Fj(\016\014le)2167 5398 y SDict begin H.S end 2167 5398 a Fj(97)2258 5339 y SDict begin H.R end 2258 5339 a 2258 5398 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.1) cvn H.B /ANN pdfmark end 2258 5398 a 1570 5511 a Fj(\016h)m(tps)2167 5511 y SDict begin H.S end 2167 5511 a Fj(99)2258 5452 y SDict begin H.R end 2258 5452 a 2258 5511 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.1) cvn H.B /ANN pdfmark end 2258 5511 a 1570 5624 a Fj(\016img)2122 5624 y SDict begin H.S end 2122 5624 a Fj(100)2258 5565 y SDict begin H.R end 2258 5565 a 2258 5624 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.2) cvn H.B /ANN pdfmark end 2258 5624 a 1570 5737 a Fj(\016kls)2122 5737 y SDict begin H.S end 2122 5737 a Fj(107)2258 5678 y SDict begin H.R end 2258 5678 a 2258 5737 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.4) cvn H.B /ANN pdfmark end 2258 5737 a 1570 5850 a Fj(\016kyu)2122 5850 y SDict begin H.S end 2122 5850 a Fj(107)2258 5791 y SDict begin H.R end 2258 5791 a 2258 5850 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.4) cvn H.B /ANN pdfmark end 2258 5850 a 2388 543 a Fj(\016ky)p 2565 543 28 4 v 2788 543 a SDict begin H.S end 2788 543 a Fj(107)2924 484 y SDict begin H.R end 2924 484 a 2924 543 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.4) cvn H.B /ANN pdfmark end 2924 543 a 2388 656 a Fj(\016mem)2833 656 y SDict begin H.S end 2833 656 a Fj(96)2924 597 y SDict begin H.R end 2924 597 a 2924 656 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.1) cvn H.B /ANN pdfmark end 2924 656 a 2388 769 a Fj(\016nit)2833 769 y SDict begin H.S end 2833 769 a Fj(34)2924 710 y SDict begin H.R end 2924 710 a 2924 769 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.2) cvn H.B /ANN pdfmark end 2924 769 a 2388 882 a Fj(\016n)m(tt)m(yp) 2833 882 y SDict begin H.S end 2833 882 a Fj(69)2924 823 y SDict begin H.R end 2924 823 a 2924 882 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 2924 882 a 2388 995 a Fj(\016opn)2833 995 y SDict begin H.S end 2833 995 a Fj(32)2924 936 y SDict begin H.R end 2924 936 a 2924 995 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.2) cvn H.B /ANN pdfmark end 2924 995 a 2388 1107 a Fj(\016rec)2788 1107 y SDict begin H.S end 2788 1107 a Fj(106)2924 1049 y SDict begin H.R end 2924 1049 a 2924 1107 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.4) cvn H.B /ANN pdfmark end 2924 1107 a 2388 1220 a Fj(\016ro)m(w)2833 1220 y SDict begin H.S end 2833 1220 a Fj(56)2924 1162 y SDict begin H.R end 2924 1162 a 2924 1220 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.3) cvn H.B /ANN pdfmark end 2924 1220 a 2388 1333 a Fj(\016tab)2788 1333 y SDict begin H.S end 2788 1333 a Fj(100)2924 1275 y SDict begin H.R end 2924 1275 a 2924 1333 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.2) cvn H.B /ANN pdfmark end 2924 1333 a 2388 1446 a Fj(\016ter)2833 1446 y SDict begin H.S end 2833 1446 a Fj(83)2924 1388 y SDict begin H.R end 2924 1388 a 2924 1446 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.6.4) cvn H.B /ANN pdfmark end 2924 1446 a 2388 1559 a Fj(\016url)2833 1559 y SDict begin H.S end 2833 1559 a Fj(97)2924 1501 y SDict begin H.R end 2924 1501 a 2924 1559 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.1) cvn H.B /ANN pdfmark end 2924 1559 a 2388 1672 a Fj(\013k)m(eyn)2833 1672 y SDict begin H.S end 2833 1672 a Fj(68)2924 1613 y SDict begin H.R end 2924 1613 a 2924 1672 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 2924 1672 a 2388 1785 a Fj(\013mahd)2833 1785 y SDict begin H.S end 2833 1785 a Fj(36)2924 1726 y SDict begin H.R end 2924 1726 a 2924 1785 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.3) cvn H.B /ANN pdfmark end 2924 1785 a 2388 1898 a Fj(\013mcom)2833 1898 y SDict begin H.S end 2833 1898 a Fj(42)2924 1839 y SDict begin H.R end 2924 1839 a 2924 1898 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 2924 1898 a 2388 2011 a Fj(\013mcrd)2788 2011 y SDict begin H.S end 2788 2011 a Fj(109)2924 1952 y SDict begin H.R end 2924 1952 a 2924 2011 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.6) cvn H.B /ANN pdfmark end 2924 2011 a 2388 2124 a Fj(\013mkky)2833 2124 y SDict begin H.S end 2833 2124 a Fj(68)2924 2065 y SDict begin H.R end 2924 2065 a 2924 2124 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 2924 2124 a 2388 2237 a Fj(\013mkls)2788 2237 y SDict begin H.S end 2788 2237 a Fj(109)2924 2178 y SDict begin H.R end 2924 2178 a 2924 2237 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.6) cvn H.B /ANN pdfmark end 2924 2237 a 2388 2349 a Fj(\013mkyu)2788 2349 y SDict begin H.S end 2788 2349 a Fj(109)2924 2291 y SDict begin H.R end 2924 2291 a 2924 2349 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.6) cvn H.B /ANN pdfmark end 2924 2349 a 2388 2462 a Fj(\013mky)p 2618 2462 28 4 v 2788 2462 a SDict begin H.S end 2788 2462 a Fj(109)2924 2404 y SDict begin H.R end 2924 2404 a 2924 2462 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.6) cvn H.B /ANN pdfmark end 2924 2462 a 2388 2575 a Fj(\013mnam)2833 2575 y SDict begin H.S end 2833 2575 a Fj(42)2924 2517 y SDict begin H.R end 2924 2517 a 2924 2575 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 2924 2575 a 2388 2688 a Fj(\013mnhd)2833 2688 y SDict begin H.S end 2833 2688 a Fj(36)2924 2630 y SDict begin H.R end 2924 2630 a 2924 2688 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.3) cvn H.B /ANN pdfmark end 2924 2688 a 2388 2801 a Fj(\013mrec)2788 2801 y SDict begin H.S end 2788 2801 a Fj(109)2924 2743 y SDict begin H.R end 2924 2743 a 2924 2801 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.6) cvn H.B /ANN pdfmark end 2924 2801 a 2388 2914 a Fj(\013mrhd)2833 2914 y SDict begin H.S end 2833 2914 a Fj(36)2924 2855 y SDict begin H.R end 2924 2855 a 2924 2914 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.3) cvn H.B /ANN pdfmark end 2924 2914 a 2388 3027 a Fj(\013m)m(v)m(ec) 2833 3027 y SDict begin H.S end 2833 3027 a Fj(57)2924 2968 y SDict begin H.R end 2924 2968 a 2924 3027 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.3) cvn H.B /ANN pdfmark end 2924 3027 a 2388 3140 a Fj(\013nc)m(hk)2833 3140 y SDict begin H.S end 2833 3140 a Fj(67)2924 3081 y SDict begin H.R end 2924 3081 a 2924 3140 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 2924 3140 a 2388 3253 a Fj(\013nk)m(ey)2833 3253 y SDict begin H.S end 2833 3253 a Fj(68)2924 3194 y SDict begin H.R end 2924 3194 a 2924 3253 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 2924 3253 a 2388 3366 a Fj(\013omem)2833 3366 y SDict begin H.S end 2833 3366 a Fj(95)2924 3307 y SDict begin H.R end 2924 3307 a 2924 3366 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.1) cvn H.B /ANN pdfmark end 2924 3366 a 2388 3479 a Fj(\013op)s(en)2833 3479 y SDict begin H.S end 2833 3479 a Fj(32)2924 3420 y SDict begin H.R end 2924 3420 a 2924 3479 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.2) cvn H.B /ANN pdfmark end 2924 3479 a 2388 3591 a Fj(\013p2d)p 2593 3591 28 4 v 2788 3591 a SDict begin H.S end 2788 3591 a Fj(113)2924 3533 y SDict begin H.R end 2924 3533 a 2924 3591 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 2924 3591 a 2388 3704 a Fj(\013p3d)p 2593 3704 28 4 v 2788 3704 a SDict begin H.S end 2788 3704 a Fj(113)2924 3646 y SDict begin H.R end 2924 3646 a 2924 3704 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 2924 3704 a 2388 3817 a Fj(\013p)s(c)m(ks)2833 3817 y SDict begin H.S end 2833 3817 a Fj(63)2924 3759 y SDict begin H.R end 2924 3759 a 2924 3817 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.1) cvn H.B /ANN pdfmark end 2924 3817 a 2388 3930 a Fj(\013p)s(cl)2833 3930 y SDict begin H.S end 2833 3930 a Fj(58)2924 3872 y SDict begin H.R end 2924 3872 a 2924 3930 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.4) cvn H.B /ANN pdfmark end 2924 3930 a 2388 4043 a Fj(\013p)s(cls)2788 4043 y SDict begin H.S end 2788 4043 a Fj(117)2924 3985 y SDict begin H.R end 2924 3985 a 2924 4043 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.3) cvn H.B /ANN pdfmark end 2924 4043 a 2388 4156 a Fj(\013p)s(cl)p 2565 4156 28 4 v 2788 4156 a SDict begin H.S end 2788 4156 a Fj(118)2924 4097 y SDict begin H.R end 2924 4097 a 2924 4156 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.3) cvn H.B /ANN pdfmark end 2924 4156 a 2388 4269 a Fj(\013p)s(clu)2833 4269 y SDict begin H.S end 2833 4269 a Fj(58)2924 4210 y SDict begin H.R end 2924 4210 a 2924 4269 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.4) cvn H.B /ANN pdfmark end 2924 4269 a 2388 4382 a Fj(\013p)s(cn)2833 4382 y SDict begin H.S end 2833 4382 a Fj(58)2924 4323 y SDict begin H.R end 2924 4323 a 2924 4382 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.4) cvn H.B /ANN pdfmark end 2924 4382 a 2388 4495 a Fj(\013p)s(cn)p 2591 4495 28 4 v 2788 4495 a SDict begin H.S end 2788 4495 a Fj(117)2924 4436 y SDict begin H.R end 2924 4436 a 2924 4495 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.3) cvn H.B /ANN pdfmark end 2924 4495 a 2388 4608 a Fj(\013p)s(com)2833 4608 y SDict begin H.S end 2833 4608 a Fj(41)2924 4549 y SDict begin H.R end 2924 4549 a 2924 4608 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 2924 4608 a 2388 4721 a Fj(\013p)s(dat)2833 4721 y SDict begin H.S end 2833 4721 a Fj(41)2924 4662 y SDict begin H.R end 2924 4662 a 2924 4721 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 2924 4721 a 2388 4833 a Fj(\013p)s(des)2788 4833 y SDict begin H.S end 2788 4833 a Fj(118)2924 4775 y SDict begin H.R end 2924 4775 a 2924 4833 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.3) cvn H.B /ANN pdfmark end 2924 4833 a 2388 4946 a Fj(\013p)s(extn)2788 4946 y SDict begin H.S end 2788 4946 a Fj(101)2924 4888 y SDict begin H.R end 2924 4888 a 2924 4946 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.2) cvn H.B /ANN pdfmark end 2924 4946 a 2388 5059 a Fj(\013pgp)p 2593 5059 28 4 v 2788 5059 a SDict begin H.S end 2788 5059 a Fj(113)2924 5001 y SDict begin H.R end 2924 5001 a 2924 5059 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 2924 5059 a 2388 5172 a Fj(\013ph)m(bn)2788 5172 y SDict begin H.S end 2788 5172 a Fj(103)2924 5114 y SDict begin H.R end 2924 5114 a 2924 5172 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.2) cvn H.B /ANN pdfmark end 2924 5172 a 2388 5285 a Fj(\013phext)2788 5285 y SDict begin H.S end 2788 5285 a Fj(102)2924 5227 y SDict begin H.R end 2924 5227 a 2924 5285 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.2) cvn H.B /ANN pdfmark end 2924 5285 a 2388 5398 a Fj(\013phis)2833 5398 y SDict begin H.S end 2833 5398 a Fj(41)2924 5339 y SDict begin H.R end 2924 5339 a 2924 5398 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 2924 5398 a 2388 5511 a Fj(\013phpr)2788 5511 y SDict begin H.S end 2788 5511 a Fj(102)2924 5452 y SDict begin H.R end 2924 5452 a 2924 5511 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.2) cvn H.B /ANN pdfmark end 2924 5511 a 2388 5624 a Fj(\013phps)2788 5624 y SDict begin H.S end 2788 5624 a Fj(102)2924 5565 y SDict begin H.R end 2924 5565 a 2924 5624 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.2) cvn H.B /ANN pdfmark end 2924 5624 a 2388 5737 a Fj(\013ph)m(tb)2788 5737 y SDict begin H.S end 2788 5737 a Fj(103)2924 5678 y SDict begin H.R end 2924 5678 a 2924 5737 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.2) cvn H.B /ANN pdfmark end 2924 5737 a 2388 5850 a Fj(\013pkls)2788 5850 y SDict begin H.S end 2788 5850 a Fj(105)2924 5791 y SDict begin H.R end 2924 5791 a 2924 5850 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.3) cvn H.B /ANN pdfmark end 2924 5850 a 3054 543 a Fj(\013pkn)p 3262 543 28 4 v 3472 543 a SDict begin H.S end 3472 543 a Fj(105)3609 484 y SDict begin H.R end 3609 484 a 3609 543 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.3) cvn H.B /ANN pdfmark end 3609 543 a 3054 656 a Fj(\013pktp)3472 656 y SDict begin H.S end 3472 656 a Fj(106)3609 597 y SDict begin H.R end 3609 597 a 3609 656 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.3) cvn H.B /ANN pdfmark end 3609 656 a 3054 769 a Fj(\013pky)3518 769 y SDict begin H.S end 3518 769 a Fj(41)3609 710 y SDict begin H.R end 3609 710 a 3609 769 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 3609 769 a 3054 882 a Fj(\013pkyt)3472 882 y SDict begin H.S end 3472 882 a Fj(106)3609 823 y SDict begin H.R end 3609 823 a 3609 882 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.3) cvn H.B /ANN pdfmark end 3609 882 a 3054 995 a Fj(\013pkyu)3518 995 y SDict begin H.S end 3518 995 a Fj(41)3609 936 y SDict begin H.R end 3609 936 a 3609 995 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 3609 995 a 3054 1107 a Fj(\013pky)p 3259 1107 28 4 v 3472 1107 a SDict begin H.S end 3472 1107 a Fj(104)3609 1049 y SDict begin H.R end 3609 1049 a 3609 1107 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.3) cvn H.B /ANN pdfmark end 3609 1107 a 3054 1220 a Fj(\013plsw)3472 1220 y SDict begin H.S end 3472 1220 a Fj(105)3609 1162 y SDict begin H.R end 3609 1162 a 3609 1220 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.3) cvn H.B /ANN pdfmark end 3609 1220 a 3054 1333 a Fj(\013pmrk)3518 1333 y SDict begin H.S end 3518 1333 a Fj(32)3609 1275 y SDict begin H.R end 3609 1275 a 3609 1333 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.1) cvn H.B /ANN pdfmark end 3609 1333 a 3054 1446 a Fj(\013pmsg)3518 1446 y SDict begin H.S end 3518 1446 a Fj(66)3609 1388 y SDict begin H.R end 3609 1388 a 3609 1446 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 3609 1446 a 3054 1559 a Fj(\013pn)m(ul)3472 1559 y SDict begin H.S end 3472 1559 a Fj(111)3609 1501 y SDict begin H.R end 3609 1501 a 3609 1559 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.4) cvn H.B /ANN pdfmark end 3609 1559 a 3054 1672 a Fj(\013ppn)3472 1672 y SDict begin H.S end 3472 1672 a Fj(112)3609 1613 y SDict begin H.R end 3609 1613 a 3609 1672 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 3609 1672 a 3054 1785 a Fj(\013ppn)p 3265 1785 28 4 v 3472 1785 a SDict begin H.S end 3472 1785 a Fj(112)3609 1726 y SDict begin H.R end 3609 1726 a 3609 1785 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 3609 1785 a 3054 1898 a Fj(\013ppr)3472 1898 y SDict begin H.S end 3472 1898 a Fj(112)3609 1839 y SDict begin H.R end 3609 1839 a 3609 1898 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 3609 1898 a 3054 2011 a Fj(\013pprn)3518 2011 y SDict begin H.S end 3518 2011 a Fj(45)3609 1952 y SDict begin H.R end 3609 1952 a 3609 2011 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 3609 2011 a 3054 2124 a Fj(\013ppru)3472 2124 y SDict begin H.S end 3472 2124 a Fj(113)3609 2065 y SDict begin H.R end 3609 2065 a 3609 2124 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 3609 2124 a 3054 2237 a Fj(\013ppr)p 3250 2237 28 4 v 3472 2237 a SDict begin H.S end 3472 2237 a Fj(112)3609 2178 y SDict begin H.R end 3609 2178 a 3609 2237 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 3609 2237 a 3054 2349 a Fj(\013pp)m(x)3518 2349 y SDict begin H.S end 3518 2349 a Fj(45)3609 2291 y SDict begin H.R end 3609 2291 a 3609 2349 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 3609 2349 a 3054 2462 a Fj(\013pp)m(xn)3518 2462 y SDict begin H.S end 3518 2462 a Fj(45)3609 2404 y SDict begin H.R end 3609 2404 a 3609 2462 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 3609 2462 a 3054 2575 a Fj(\013prec)3518 2575 y SDict begin H.S end 3518 2575 a Fj(42)3609 2517 y SDict begin H.R end 3609 2517 a 3609 2575 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 3609 2575 a 3054 2688 a Fj(\013prwu)3518 2688 y SDict begin H.S end 3518 2688 a Fj(58)3609 2630 y SDict begin H.R end 3609 2630 a 3609 2688 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.4) cvn H.B /ANN pdfmark end 3609 2688 a 3054 2801 a Fj(\013pscl)3472 2801 y SDict begin H.S end 3472 2801 a Fj(110)3609 2743 y SDict begin H.R end 3609 2743 a 3609 2801 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.4) cvn H.B /ANN pdfmark end 3609 2801 a 3054 2914 a Fj(\013pss)3518 2914 y SDict begin H.S end 3518 2914 a Fj(45)3609 2855 y SDict begin H.R end 3609 2855 a 3609 2914 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.5) cvn H.B /ANN pdfmark end 3609 2914 a 3054 3027 a Fj(\013pss)p 3235 3027 28 4 v 3472 3027 a SDict begin H.S end 3472 3027 a Fj(113)3609 2968 y SDict begin H.R end 3609 2968 a 3609 3027 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.5) cvn H.B /ANN pdfmark end 3609 3027 a 3054 3140 a Fj(\013psv)m(c)3518 3140 y SDict begin H.S end 3518 3140 a Fj(68)3609 3081 y SDict begin H.R end 3609 3081 a 3609 3140 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 3609 3140 a 3054 3253 a Fj(\013ptbb)3472 3253 y SDict begin H.S end 3472 3253 a Fj(117)3609 3194 y SDict begin H.R end 3609 3194 a 3609 3253 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.2) cvn H.B /ANN pdfmark end 3609 3253 a 3054 3366 a Fj(\013ptdm)3518 3366 y SDict begin H.S end 3518 3366 a Fj(55)3609 3307 y SDict begin H.R end 3609 3307 a 3609 3366 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.2) cvn H.B /ANN pdfmark end 3609 3366 a 3054 3479 a Fj(\013pthp)3472 3479 y SDict begin H.S end 3472 3479 a Fj(116)3609 3420 y SDict begin H.R end 3609 3420 a 3609 3479 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.1) cvn H.B /ANN pdfmark end 3609 3479 a 3054 3591 a Fj(\013pun)m(t)3518 3591 y SDict begin H.S end 3518 3591 a Fj(42)3609 3533 y SDict begin H.R end 3609 3533 a 3609 3591 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 3609 3591 a 3054 3704 a Fj(\013rdef)3472 3704 y SDict begin H.S end 3472 3704 a Fj(101)3609 3646 y SDict begin H.R end 3609 3646 a 3609 3704 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.2) cvn H.B /ANN pdfmark end 3609 3704 a 3054 3817 a Fj(\013reop)s(en)3518 3817 y SDict begin H.S end 3518 3817 a Fj(96)3609 3759 y SDict begin H.R end 3609 3759 a 3609 3817 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.1) cvn H.B /ANN pdfmark end 3609 3817 a 3054 3930 a Fj(\013rprt)3518 3930 y SDict begin H.S end 3518 3930 a Fj(32)3609 3872 y SDict begin H.R end 3609 3872 a 3609 3930 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.1) cvn H.B /ANN pdfmark end 3609 3930 a 3054 4043 a Fj(\013rsim)3472 4043 y SDict begin H.S end 3472 4043 a Fj(101)3609 3985 y SDict begin H.R end 3609 3985 a 3609 4043 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.2) cvn H.B /ANN pdfmark end 3609 4043 a 3054 4156 a Fj(\013rtnm)3518 4156 y SDict begin H.S end 3518 4156 a Fj(98)3609 4097 y SDict begin H.R end 3609 4097 a 3609 4156 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.1) cvn H.B /ANN pdfmark end 3609 4156 a 3054 4269 a Fj(\013rwrg)3518 4269 y SDict begin H.S end 3518 4269 a Fj(74)3609 4210 y SDict begin H.R end 3609 4210 a 3609 4269 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 3609 4269 a 3054 4382 a Fj(\013s2dt)3518 4382 y SDict begin H.S end 3518 4382 a Fj(65)3609 4323 y SDict begin H.R end 3609 4323 a 3609 4382 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.2) cvn H.B /ANN pdfmark end 3609 4382 a 3054 4495 a Fj(\013s2tm)3518 4495 y SDict begin H.S end 3518 4495 a Fj(65)3609 4436 y SDict begin H.R end 3609 4436 a 3609 4495 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.2) cvn H.B /ANN pdfmark end 3609 4495 a 3054 4608 a Fj(\013sn)m(ul)3472 4608 y SDict begin H.S end 3472 4608 a Fj(111)3609 4549 y SDict begin H.R end 3609 4549 a 3609 4608 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.4) cvn H.B /ANN pdfmark end 3609 4608 a 3054 4721 a Fj(\013sro)m(w)3518 4721 y SDict begin H.S end 3518 4721 a Fj(60)3609 4662 y SDict begin H.R end 3609 4662 a 3609 4721 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.5) cvn H.B /ANN pdfmark end 3609 4721 a 3054 4833 a Fj(\013texp)3518 4833 y SDict begin H.S end 3518 4833 a Fj(61)3609 4775 y SDict begin H.R end 3609 4775 a 3609 4833 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.7.5) cvn H.B /ANN pdfmark end 3609 4833 a 3054 4946 a Fj(\013thdu)3518 4946 y SDict begin H.S end 3518 4946 a Fj(36)3609 4888 y SDict begin H.R end 3609 4888 a 3609 4946 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.3) cvn H.B /ANN pdfmark end 3609 4946 a 3054 5059 a Fj(\013theap)3472 5059 y SDict begin H.S end 3472 5059 a Fj(116)3609 5001 y SDict begin H.R end 3609 5001 a 3609 5059 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.6.1) cvn H.B /ANN pdfmark end 3609 5059 a 3054 5172 a Fj(\013tk)m(ey)3518 5172 y SDict begin H.S end 3518 5172 a Fj(67)3609 5114 y SDict begin H.R end 3609 5114 a 3609 5172 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 3609 5172 a 3054 5285 a Fj(\013tm2s)3518 5285 y SDict begin H.S end 3518 5285 a Fj(65)3609 5227 y SDict begin H.R end 3609 5227 a 3609 5285 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.2) cvn H.B /ANN pdfmark end 3609 5285 a 3054 5398 a Fj(\013tn)m(ul)3472 5398 y SDict begin H.S end 3472 5398 a Fj(111)3609 5339 y SDict begin H.R end 3609 5339 a 3609 5398 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.4) cvn H.B /ANN pdfmark end 3609 5398 a 3054 5511 a Fj(\013topn)3518 5511 y SDict begin H.S end 3518 5511 a Fj(32)3609 5452 y SDict begin H.R end 3609 5452 a 3609 5511 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.2) cvn H.B /ANN pdfmark end 3609 5511 a 3054 5624 a Fj(\013tplt)3518 5624 y SDict begin H.S end 3518 5624 a Fj(96)3609 5565 y SDict begin H.R end 3609 5565 a 3609 5624 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.1) cvn H.B /ANN pdfmark end 3609 5624 a 3054 5737 a Fj(\013trec)3518 5737 y SDict begin H.S end 3518 5737 a Fj(67)3609 5678 y SDict begin H.R end 3609 5678 a 3609 5737 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 3609 5737 a 3054 5850 a Fj(\013tscl)3472 5850 y SDict begin H.S end 3472 5850 a Fj(111)3609 5791 y SDict begin H.R end 3609 5791 a 3609 5850 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.4) cvn H.B /ANN pdfmark end 3609 5850 a eop end %%Page: 177 185 TeXDict begin 177 184 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.177) cvn H.B /DEST pdfmark end 0 299 a 3764 w Fj(177)50 543 y(\013ucrd)501 543 y SDict begin H.S end 501 543 a Fj(42)592 484 y SDict begin H.R end 592 484 a 592 543 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 592 543 a 50 656 a Fj(\013ukls)455 656 y SDict begin H.S end 455 656 a Fj(110)592 597 y SDict begin H.R end 592 597 a 592 656 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.7) cvn H.B /ANN pdfmark end 592 656 a 50 769 a Fj(\013uky)501 769 y SDict begin H.S end 501 769 a Fj(41)592 710 y SDict begin H.R end 592 710 a 592 769 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 592 769 a 50 882 a Fj(\013ukyu)501 882 y SDict begin H.S end 501 882 a Fj(41)592 823 y SDict begin H.R end 592 823 a 592 882 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.4.2) cvn H.B /ANN pdfmark end 592 882 a 50 995 a Fj(\013uky)p 255 995 28 4 v 455 995 a SDict begin H.S end 455 995 a Fj(110)592 936 y SDict begin H.R end 592 936 a 592 995 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.9.3.7) cvn H.B /ANN pdfmark end 592 995 a 50 1107 a Fj(\013up)s(c)m(h)501 1107 y SDict begin H.S end 501 1107 a Fj(66)592 1049 y SDict begin H.R end 592 1049 a 592 1107 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 592 1107 a 50 1220 a Fj(\013up)s(c)m(k)501 1220 y SDict begin H.S end 501 1220 a Fj(64)592 1162 y SDict begin H.R end 592 1162 a 592 1220 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.1) cvn H.B /ANN pdfmark end 592 1220 a 50 1333 a Fj(\013urlt)501 1333 y SDict begin H.S end 501 1333 a Fj(35)592 1275 y SDict begin H.R end 592 1275 a 592 1333 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.2) cvn H.B /ANN pdfmark end 592 1333 a 50 1446 a Fj(\013v)m(c)m(ks)501 1446 y SDict begin H.S end 501 1446 a Fj(64)592 1388 y SDict begin H.R end 592 1388 a 592 1446 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.1) cvn H.B /ANN pdfmark end 592 1446 a 50 1559 a Fj(\013v)m(ers)501 1559 y SDict begin H.S end 501 1559 a Fj(66)592 1501 y SDict begin H.R end 592 1501 a 592 1559 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (subsection.5.8.3) cvn H.B /ANN pdfmark end 592 1559 a 50 1672 a Fj(\013vh)m(tps)501 1672 y SDict begin H.S end 501 1672 a Fj(99)592 1613 y SDict begin H.R end 592 1613 a 592 1672 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.9.1) cvn H.B /ANN pdfmark end 592 1672 a 50 1785 a Fj(\013wldp)501 1785 y SDict begin H.S end 501 1785 a Fj(87)592 1726 y SDict begin H.R end 592 1726 a 592 1785 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.7.1) cvn H.B /ANN pdfmark end 592 1785 a 50 1898 a Fj(\013wrhdu)501 1898 y SDict begin H.S end 501 1898 a Fj(37)592 1839 y SDict begin H.R end 592 1839 a 592 1898 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.5.3) cvn H.B /ANN pdfmark end 592 1898 a 50 2011 a Fj(\013xyp)m(x)501 2011 y SDict begin H.S end 501 2011 a Fj(87)592 1952 y SDict begin H.R end 592 1952 a 592 2011 a SDict begin [ /Color [1 0 0] /H /I /Border [0 0 12] /Subtype /Link /Dest (section.7.1) cvn H.B /ANN pdfmark end 592 2011 a eop end %%Page: 178 186 TeXDict begin 178 185 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.178) cvn H.B /DEST pdfmark end 0 299 a Fj(178)2084 b Fh(APPENDIX)31 b(A.)61 b(INDEX)31 b(OF)f(R)m(OUTINES)p eop end %%Page: 179 187 TeXDict begin 179 186 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.179) cvn H.B /DEST pdfmark end 0 299 a 0 464 a SDict begin H.S end 0 464 a 0 464 a SDict begin 13.6 H.A end 0 464 a 0 464 a SDict begin [ /View [/XYZ H.V] /Dest (appendix.B) cvn H.B /DEST pdfmark end 0 464 a 761 x Fg(App)5 b(endix)64 b(B)0 1687 y Fm(P)-6 b(arameter)77 b(De\014nitions)0 2180 y Fe(anynul)142 b(-)47 b(set)g(to)g(TRUE)g(\(=1\))f(if)i(any)e(returned)g (values)g(are)h(undefined,)e(else)i(FALSE)0 2293 y(array)190 b(-)47 b(array)f(of)i(numerical)d(data)h(values)h(to)g(read)f(or)i (write)0 2406 y(ascii)190 b(-)47 b(encoded)f(checksum)f(string)0 2518 y(binspec)94 b(-)47 b(the)g(input)f(table)h(binning)e(specifier)0 2631 y(bitpix)142 b(-)47 b(bits)g(per)g(pixel.)f(The)h(following)e (symbolic)g(mnemonics)h(are)h(predefined:)716 2744 y(BYTE_IMG)141 b(=)i(8)47 b(\(unsigned)f(char\))716 2857 y(SHORT_IMG)93 b(=)i(16)47 b(\(signed)f(short)g(integer\))716 2970 y(LONG_IMG)141 b(=)95 b(32)47 b(\(signed)f(long)h(integer\))716 3083 y(LONGLONG_IMG)d(=)96 b(64)47 b(\(signed)f(long)g(64-bit)g(integer\)) 716 3196 y(FLOAT_IMG)93 b(=)47 b(-32)g(\(float\))716 3309 y(DOUBLE_IMG)e(=)i(-64)g(\(double\).)525 3422 y(Two)g(additional)e (values,)h(USHORT_IMG)f(and)i(ULONG_IMG)e(are)i(also)f(available)525 3535 y(for)h(creating)e(unsigned)h(integer)g(images.)93 b(These)47 b(are)g(equivalent)e(to)525 3648 y(creating)h(a)h(signed)f (integer)g(image)g(with)h(BZERO)f(offset)g(keyword)g(values)525 3760 y(of)h(32768)g(or)g(2147483648,)d(respectively,)h(which)h(is)h (the)g(convention)e(that)525 3873 y(FITS)i(uses)f(to)h(store)g (unsigned)e(integers.)0 3986 y(card)238 b(-)47 b(header)f(record)g(to)h (be)h(read)e(or)h(written)f(\(80)h(char)g(max,)f(null-terminated\))0 4099 y(casesen)94 b(-)47 b(CASESEN)f(\(=1\))g(for)h(case-sensitive)d (string)i(matching,)g(else)g(CASEINSEN)g(\(=0\))0 4212 y(cmopt)190 b(-)47 b(grouping)f(table)g("compact")f(option)h (parameter.)f(Allowed)h(values)g(are:)525 4325 y(OPT_CMT_MBR)f(and)i (OPT_CMT_MBR_DEL.)0 4438 y(colname)94 b(-)47 b(name)g(of)g(the)g (column)f(\(null-terminated\))0 4551 y(colnum)142 b(-)47 b(column)f(number)g(\(first)g(column)g(=)i(1\))0 4664 y(colspec)94 b(-)47 b(the)g(input)f(file)h(column)f(specification;)e (used)j(to)g(delete,)f(create,)f(or)j(rename)525 4777 y(table)e(columns)0 4890 y(comment)94 b(-)47 b(the)g(keyword)f(comment) g(field)g(\(72)h(char)f(max,)h(null-terminated\))0 5002 y(complm)142 b(-)47 b(should)f(the)h(checksum)f(be)h(complemented?)0 5115 y(comptype)f(-)h(compression)e(algorithm)g(to)i(use:)g(GZIP_1,)f (RICE_1,)f(HCOMPRESS_1,)g(or)i(PLIO_1)0 5228 y(coordtype-)e(type)i(of)g (coordinate)e(projection)g(\(-SIN,)h(-TAN,)g(-ARC,)h(-NCP,)525 5341 y(-GLS,)f(-MER,)h(or)g(-AIT\))0 5454 y(cpopt)190 b(-)47 b(grouping)f(table)g(copy)h(option)f(parameter.)f(Allowed)g (values)i(are:)525 5567 y(OPT_GCP_GPT,)d(OPT_GCP_MBR,)h(OPT_GCP_ALL,)f (OPT_MCP_ADD,)h(OPT_MCP_NADD,)525 5680 y(OPT_MCP_REPL,)f(amd)j (OPT_MCP_MOV.)1882 5942 y Fj(179)p eop end %%Page: 180 188 TeXDict begin 180 187 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.180) cvn H.B /DEST pdfmark end 0 299 a Fj(180)1822 b Fh(APPENDIX)31 b(B.)61 b(P)-8 b(ARAMETER)30 b(DEFINITIONS)0 555 y Fe(create_col-)45 b(If)i(TRUE,)f(then)h(insert)f(a)h(new)g(column)f(in)i(the)f(table,)f (otherwise)525 668 y(overwrite)f(the)i(existing)f(column.)0 781 y(current)94 b(-)47 b(if)g(TRUE,)g(then)f(the)h(current)f(HDU)h (will)f(be)i(copied)0 894 y(dataok)142 b(-)47 b(was)g(the)g(data)f (unit)h(verification)e(successful)g(\(=1\))h(or)525 1007 y(not)h(\(=)g(-1\).)94 b(Equals)47 b(zero)f(if)h(the)g(DATASUM)f (keyword)g(is)h(not)g(present.)0 1120 y(datasum)94 b(-)47 b(32-bit)f(1's)h(complement)e(checksum)h(for)g(the)h(data)g(unit)0 1233 y(dataend)94 b(-)47 b(address)f(\(in)h(bytes\))f(of)h(the)g(end)g (of)g(the)g(HDU)0 1346 y(datastart-)e(address)h(\(in)h(bytes\))f(of)h (the)g(start)f(of)h(the)g(data)g(unit)0 1458 y(datatype)f(-)h (specifies)e(the)i(data)g(type)f(of)i(the)f(value.)93 b(Allowed)46 b(value)h(are:)94 b(TSTRING,)525 1571 y(TLOGICAL,)45 b(TBYTE,)h(TSBYTE,)g(TSHORT,)g(TUSHORT,)g(TINT,)g(TUINT,)g(TLONG,)g (TULONG,)525 1684 y(TFLOAT,)g(TDOUBLE,)f(TCOMPLEX,)h(and)h(TDBLCOMPLEX) 0 1797 y(datestr)94 b(-)47 b(FITS)g(date/time)e(string:)h ('YYYY-MM-DDThh:mm:ss.dd)o(d',)41 b('YYYY-MM-dd',)525 1910 y(or)47 b('dd/mm/yy')0 2023 y(day)286 b(-)47 b(calendar)f(day)g (\(UTC\))h(\(1-31\))0 2136 y(decimals)f(-)h(number)f(of)h(decimal)f (places)g(to)h(be)h(displayed)0 2249 y(deltasize)d(-)j(increment)d(for) i(allocating)e(more)i(memory)0 2362 y(dim1)238 b(-)47 b(declared)f(size)g(of)h(the)g(first)g(dimension)e(of)i(the)g(image)f (or)i(cube)e(array)0 2475 y(dim2)238 b(-)47 b(declared)f(size)g(of)h (the)g(second)f(dimension)g(of)h(the)g(data)f(cube)h(array)0 2588 y(dispwidth)e(-)j(display)e(width)g(of)h(a)h(column)e(=)h(length)f (of)h(string)f(that)h(will)g(be)g(read)0 2700 y(dtype)190 b(-)47 b(data)g(type)f(of)h(the)g(keyword)f(\('C',)h('L',)f('I',)h('F') g(or)g('X'\))764 2813 y(C)g(=)h(character)d(string)764 2926 y(L)i(=)h(logical)764 3039 y(I)f(=)h(integer)764 3152 y(F)f(=)h(floating)d(point)h(number)764 3265 y(X)h(=)h(complex,)d (e.g.,)h("\(1.23,)g(-4.56\)")0 3378 y(err_msg)94 b(-)47 b(error)f(message)g(on)h(the)g(internal)f(stack)g(\(80)h(chars)f(max\)) 0 3491 y(err_text)g(-)h(error)f(message)g(string)g(corresponding)e(to)k (error)e(number)g(\(30)h(chars)f(max\))0 3604 y(exact)190 b(-)47 b(TRUE)g(\(=1\))f(if)h(the)g(strings)f(match)h(exactly;)525 3717 y(FALSE)f(\(=0\))h(if)g(wildcards)e(are)i(used)0 3830 y(exclist)94 b(-)47 b(array)f(of)i(pointers)d(to)i(keyword)f (names)g(to)i(be)f(excluded)e(from)i(search)0 3942 y(exists)142 b(-)47 b(flag)g(indicating)e(whether)g(the)i(file)g(or)g(compressed)e (file)i(exists)f(on)h(disk)0 4055 y(expr)238 b(-)47 b(boolean)f(or)h (arithmetic)e(expression)0 4168 y(extend)142 b(-)47 b(TRUE)g(\(=1\))f (if)h(FITS)g(file)g(may)g(have)f(extensions,)f(else)i(FALSE)f(\(=0\))0 4281 y(extname)94 b(-)47 b(value)f(of)i(the)e(EXTNAME)g(keyword)g (\(null-terminated\))0 4394 y(extspec)94 b(-)47 b(the)g(extension)e(or) i(HDU)g(specifier;)e(a)j(number)e(or)h(name,)f(version,)g(and)h(type)0 4507 y(extver)142 b(-)47 b(value)f(of)i(the)e(EXTVER)h(keyword)e(=)j (integer)e(version)f(number)0 4620 y(filename)h(-)h(full)g(name)f(of)h (the)g(FITS)g(file,)f(including)g(optional)f(HDU)i(and)g(filtering)e (specs)0 4733 y(filetype)h(-)h(type)g(of)g(file)f(\(file://,)g(ftp://,) g(http://,)f(etc.\))0 4846 y(filter)142 b(-)47 b(the)g(input)f(file)h (filtering)e(specifier)0 4959 y(firstchar-)g(starting)h(byte)g(in)h (the)g(row)g(\(first)f(byte)h(of)g(row)g(=)g(1\))0 5072 y(firstfailed)e(-)i(member)f(HDU)h(ID)g(\(if)g(positive\))f(or)h (grouping)e(table)i(GRPIDn)f(index)525 5185 y(value)g(\(if)h (negative\))f(that)g(failed)g(grouping)g(table)g(verification.)0 5297 y(firstelem-)f(first)h(element)g(in)h(a)h(vector)e(\(ignored)f (for)i(ASCII)g(tables\))0 5410 y(firstrow)f(-)h(starting)f(row)g (number)h(\(first)f(row)h(of)g(table)f(=)i(1\))0 5523 y(following-)d(if)i(TRUE,)g(any)f(HDUs)h(following)e(the)i(current)f (HDU)h(will)g(be)g(copied)0 5636 y(fpixel)142 b(-)47 b(coordinate)e(of)i(the)g(first)f(pixel)h(to)g(be)g(read)g(or)g (written)f(in)h(the)p eop end %%Page: 181 189 TeXDict begin 181 188 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.181) cvn H.B /DEST pdfmark end 0 299 a 3764 w Fj(181)525 555 y Fe(FITS)47 b(array.)93 b(The)47 b(array)g(must)f(be)i(of)f(length)f (NAXIS)g(and)h(have)g(values)f(such)525 668 y(that)h(fpixel[0])e(is)i (in)g(the)g(range)g(1)g(to)g(NAXIS1,)f(fpixel[1])f(is)i(in)h(the)525 781 y(range)e(1)i(to)f(NAXIS2,)f(etc.)0 894 y(fptr)238 b(-)47 b(pointer)f(to)h(a)g('fitsfile')e(structure)h(describing)f(the)i (FITS)f(file.)0 1007 y(frac)238 b(-)47 b(factional)e(part)i(of)g(the)g (keyword)f(value)0 1120 y(gcount)142 b(-)47 b(number)f(of)h(groups)f (in)i(the)e(primary)g(array)h(\(usually)e(=)j(1\))0 1233 y(gfptr)190 b(-)47 b(fitsfile*)e(pointer)h(to)h(a)h(grouping)d(table)i (HDU.)0 1346 y(group)190 b(-)47 b(GRPIDn/GRPLCn)d(index)j(value)f (identifying)f(a)i(grouping)f(table)g(HDU,)h(or)525 1458 y(data)g(group)f(number)g(\(=0)h(for)g(non-grouped)e(data\))0 1571 y(grouptype)g(-)j(Grouping)d(table)i(parameter)e(that)i(specifies) e(the)i(columns)f(to)h(be)525 1684 y(created)f(in)h(a)g(grouping)f (table)g(HDU.)h(Allowed)f(values)g(are:)h(GT_ID_ALL_URI,)525 1797 y(GT_ID_REF,)e(GT_ID_POS,)g(GT_ID_ALL,)g(GT_ID_REF_URI,)f(and)j (GT_ID_POS_URI.)0 1910 y(grpname)94 b(-)47 b(value)f(to)i(use)e(for)h (the)g(GRPNAME)f(keyword)g(value.)0 2023 y(hdunum)142 b(-)47 b(sequence)f(number)g(of)h(the)g(HDU)g(\(Primary)e(array)i(=)g (1\))0 2136 y(hduok)190 b(-)47 b(was)g(the)g(HDU)g(verification)d (successful)h(\(=1\))i(or)525 2249 y(not)g(\(=)g(-1\).)94 b(Equals)47 b(zero)f(if)h(the)g(CHECKSUM)f(keyword)g(is)h(not)g (present.)0 2362 y(hdusum)142 b(-)47 b(32)g(bit)g(1's)g(complement)e (checksum)h(for)g(the)h(entire)f(CHDU)0 2475 y(hdutype)94 b(-)47 b(HDU)g(type:)f(IMAGE_HDU)g(\(0\),)g(ASCII_TBL)f(\(1\),)i (BINARY_TBL)e(\(2\),)i(ANY_HDU)f(\(-1\))0 2588 y(header)142 b(-)47 b(returned)f(character)f(string)h(containing)f(all)i(the)g (keyword)f(records)0 2700 y(headstart-)f(starting)h(address)f(\(in)i (bytes\))f(of)i(the)e(CHDU)0 2813 y(heapsize)g(-)h(size)g(of)g(the)g (binary)f(table)g(heap,)h(in)g(bytes)0 2926 y(history)94 b(-)47 b(the)g(HISTORY)f(keyword)g(comment)f(string)h(\(70)h(char)g (max,)g(null-terminated\))0 3039 y(hour)238 b(-)47 b(hour)g(within)f (day)h(\(UTC\))f(\(0)h(-)h(23\))0 3152 y(inc)286 b(-)47 b(sampling)f(interval)f(for)i(pixels)f(in)h(each)g(FITS)g(dimension)0 3265 y(inclist)94 b(-)47 b(array)f(of)i(pointers)d(to)i(matching)f (keyword)g(names)0 3378 y(incolnum)g(-)h(input)f(column)g(number;)g (range)h(=)g(1)h(to)f(TFIELDS)0 3491 y(infile)142 b(-)47 b(the)g(input)f(filename,)g(including)f(path)h(if)i(specified)0 3604 y(infptr)142 b(-)47 b(pointer)f(to)h(a)g('fitsfile')e(structure)h (describing)f(the)i(input)f(FITS)h(file.)0 3717 y(intval)142 b(-)47 b(integer)f(part)g(of)i(the)f(keyword)e(value)0 3830 y(iomode)142 b(-)47 b(file)g(access)f(mode:)g(either)g(READONLY)g (\(=0\))g(or)i(READWRITE)d(\(=1\))0 3942 y(keyname)94 b(-)47 b(name)g(of)g(a)g(keyword)f(\(8)h(char)g(max,)g (null-terminated\))0 4055 y(keynum)142 b(-)47 b(position)f(of)h (keyword)f(in)h(header)f(\(1st)g(keyword)g(=)i(1\))0 4168 y(keyroot)94 b(-)47 b(root)g(string)f(for)h(the)g(keyword)e(name)i (\(5)g(char)g(max,)f(null-terminated\))0 4281 y(keysexist-)f(number)h (of)h(existing)f(keyword)g(records)f(in)j(the)f(CHU)0 4394 y(keytype)94 b(-)47 b(header)f(record)g(type:)h(-1=delete;)92 b(0=append)46 b(or)h(replace;)907 4507 y(1=append;)e(2=this)h(is)h(the) g(END)g(keyword)0 4620 y(longstr)94 b(-)47 b(arbitrarily)e(long)h (string)g(keyword)g(value)h(\(null-terminated\))0 4733 y(lpixel)142 b(-)47 b(coordinate)e(of)i(the)g(last)g(pixel)f(to)h(be)g (read)g(or)g(written)f(in)h(the)525 4846 y(FITS)g(array.)93 b(The)47 b(array)g(must)f(be)i(of)f(length)f(NAXIS)g(and)h(have)g (values)f(such)525 4959 y(that)h(lpixel[0])e(is)i(in)g(the)g(range)g(1) g(to)g(NAXIS1,)f(lpixel[1])f(is)i(in)h(the)525 5072 y(range)e(1)i(to)f (NAXIS2,)f(etc.)0 5185 y(match)190 b(-)47 b(TRUE)g(\(=1\))f(if)h(the)g (2)h(strings)e(match,)g(else)g(FALSE)h(\(=0\))0 5297 y(maxdim)142 b(-)47 b(maximum)f(number)g(of)h(values)f(to)h(return)0 5410 y(member)142 b(-)47 b(row)g(number)f(of)h(a)h(grouping)d(table)i (member)f(HDU.)0 5523 y(memptr)142 b(-)47 b(pointer)f(to)h(the)g(a)g (FITS)g(file)g(in)g(memory)0 5636 y(mem_realloc)e(-)i(pointer)f(to)h(a) h(function)d(for)i(reallocating)e(more)h(memory)p eop end %%Page: 182 190 TeXDict begin 182 189 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.182) cvn H.B /DEST pdfmark end 0 299 a Fj(182)1822 b Fh(APPENDIX)31 b(B.)61 b(P)-8 b(ARAMETER)30 b(DEFINITIONS)0 555 y Fe(memsize)94 b(-)47 b(size)g(of)g(the)g(memory)f(block)g(allocated)f(for)i(the)g (FITS)g(file)0 668 y(mfptr)190 b(-)47 b(fitsfile*)e(pointer)h(to)h(a)h (grouping)d(table)i(member)f(HDU.)0 781 y(mgopt)190 b(-)47 b(grouping)f(table)g(merge)g(option)g(parameter.)f(Allowed)h(values)g (are:)525 894 y(OPT_MRG_COPY,)e(and)j(OPT_MRG_MOV.)0 1007 y(minute)142 b(-)47 b(minute)f(within)g(hour)h(\(UTC\))f(\(0)h(-)h (59\))0 1120 y(month)190 b(-)47 b(calendar)f(month)g(\(UTC\))g(\(1)h(-) h(12\))0 1233 y(morekeys)e(-)h(space)f(in)i(the)e(header)h(for)f(this)h (many)g(more)f(keywords)0 1346 y(n_good_rows)f(-)i(number)f(of)h(rows)g (evaluating)e(to)i(TRUE)0 1458 y(namelist)f(-)h(string)f(containing)f (a)j(comma)e(or)h(space)f(delimited)g(list)g(of)i(names)0 1571 y(naxes)190 b(-)47 b(size)g(of)g(each)f(dimension)g(in)h(the)g (FITS)f(array)0 1684 y(naxis)190 b(-)47 b(number)f(of)h(dimensions)e (in)i(the)g(FITS)g(array)0 1797 y(naxis1)142 b(-)47 b(length)f(of)h (the)g(X/first)f(axis)h(of)g(the)g(FITS)f(array)0 1910 y(naxis2)142 b(-)47 b(length)f(of)h(the)g(Y/second)f(axis)g(of)i(the)e (FITS)h(array)0 2023 y(naxis3)142 b(-)47 b(length)f(of)h(the)g(Z/third) f(axis)h(of)g(the)g(FITS)f(array)0 2136 y(nbytes)142 b(-)47 b(number)f(of)h(bytes)g(or)g(characters)e(to)i(read)g(or)g (write)0 2249 y(nchars)142 b(-)47 b(number)f(of)h(characters)e(to)i (read)g(or)g(write)0 2362 y(nelements-)e(number)h(of)h(data)g(elements) e(to)j(read)e(or)h(write)0 2475 y(newfptr)94 b(-)47 b(returned)f (pointer)f(to)j(the)e(reopened)g(file)0 2588 y(newveclen-)f(new)i (value)f(for)h(the)g(column)f(vector)g(repeat)g(parameter)0 2700 y(nexc)238 b(-)47 b(number)f(of)h(names)g(in)g(the)g(exclusion)e (list)i(\(may)f(=)i(0\))0 2813 y(nfound)142 b(-)47 b(number)f(of)h (keywords)f(found)g(\(highest)g(keyword)g(number\))0 2926 y(nkeys)190 b(-)47 b(number)f(of)h(keywords)f(in)h(the)g(sequence) 0 3039 y(ninc)238 b(-)47 b(number)f(of)h(names)g(in)g(the)g(inclusion)e (list)0 3152 y(nmembers)h(-)h(Number)f(of)h(grouping)f(table)g(members) g(\(NAXIS2)g(value\).)0 3265 y(nmove)190 b(-)47 b(number)f(of)h(HDUs)g (to)g(move)g(\(+)g(or)g(-\),)g(relative)f(to)h(current)f(position)0 3378 y(nocomments)f(-)i(if)h(equal)e(to)h(TRUE,)g(then)f(no)h (commentary)e(keywords)h(will)h(be)g(copied)0 3491 y(noisebits-)e (number)h(of)h(bits)g(to)g(ignore)f(when)h(compressing)e(floating)g (point)h(images)0 3604 y(nrows)190 b(-)47 b(number)f(of)h(rows)g(in)g (the)g(table)0 3717 y(nstart)142 b(-)47 b(first)f(integer)g(value)0 3830 y(nullarray-)f(set)i(to)g(TRUE)g(\(=1\))f(if)i(corresponding)c (data)i(element)g(is)h(undefined)0 3942 y(nulval)142 b(-)47 b(numerical)e(value)i(to)g(represent)e(undefined)g(pixels)0 4055 y(nulstr)142 b(-)47 b(character)e(string)h(used)h(to)g(represent)e (undefined)h(values)g(in)h(ASCII)f(table)0 4168 y(numval)142 b(-)47 b(numerical)e(data)i(value,)f(of)h(the)g(appropriate)e(data)h (type)0 4281 y(offset)142 b(-)47 b(byte)g(offset)f(in)h(the)g(heap)f (or)i(data)e(unit)h(to)g(the)g(first)f(element)g(of)h(the)g(vector)0 4394 y(openfptr)f(-)h(pointer)f(to)h(a)g(currently)f(open)g(FITS)h (file)0 4507 y(overlap)94 b(-)47 b(number)f(of)h(bytes)g(in)g(the)g (binary)f(table)g(heap)h(pointed)f(to)h(by)g(more)g(than)f(1)525 4620 y(descriptor)0 4733 y(outcolnum-)f(output)h(column)g(number;)g (range)g(=)i(1)f(to)g(TFIELDS)f(+)i(1)0 4846 y(outfile)94 b(-)47 b(and)g(optional)e(output)i(filename;)e(the)i(input)f(file)h (will)f(be)i(copied)e(to)h(this)f(prior)525 4959 y(to)h(opening)f(the)h (file)0 5072 y(outfptr)94 b(-)47 b(pointer)f(to)h(a)g('fitsfile')e (structure)h(describing)f(the)i(output)f(FITS)g(file.)0 5185 y(pcount)142 b(-)47 b(value)f(of)i(the)e(PCOUNT)h(keyword)e(=)j (size)e(of)i(binary)e(table)g(heap)0 5297 y(previous)g(-)h(if)g(TRUE,)g (any)f(previous)g(HDUs)h(in)g(the)g(input)f(file)h(will)f(be)i(copied.) 0 5410 y(repeat)142 b(-)47 b(length)f(of)h(column)f(vector)g(\(e.g.)h (12J\);)f(==)h(1)h(for)f(ASCII)f(table)0 5523 y(rmopt)190 b(-)47 b(grouping)f(table)g(remove)g(option)g(parameter.)f(Allowed)h (values)g(are:)525 5636 y(OPT_RM_GPT,)f(OPT_RM_ENTRY,)f(OPT_RM_MBR,)h (and)i(OPT_RM_ALL.)p eop end %%Page: 183 191 TeXDict begin 183 190 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.183) cvn H.B /DEST pdfmark end 0 299 a 3764 w Fj(183)0 555 y Fe(rootname)46 b(-)h(root)g(filename,)e(minus)h(any)h(extension)e(or)j (filtering)d(specifications)0 668 y(rot)286 b(-)47 b(celestial)e (coordinate)g(rotation)h(angle)g(\(degrees\))0 781 y(rowlen)142 b(-)47 b(length)f(of)h(a)h(table)e(row,)h(in)g(characters)e(or)i(bytes) 0 894 y(rowlist)94 b(-)47 b(sorted)f(list)h(of)g(row)g(numbers)f(to)h (be)g(deleted)f(from)g(the)h(table)0 1007 y(rownum)142 b(-)47 b(number)f(of)h(the)g(row)g(\(first)f(row)h(=)h(1\))0 1120 y(rowrange)e(-)h(list)g(of)g(rows)f(or)i(row)f(ranges:)e ('3,6-8,12,56-80')f(or)j('500-')0 1233 y(row_status)e(-)i(array)g(of)g (True/False)e(results)h(for)h(each)f(row)h(that)g(was)g(evaluated)0 1346 y(scale)190 b(-)47 b(linear)f(scaling)g(factor;)g(true)g(value)h (=)g(\(FITS)g(value\))f(*)h(scale)f(+)i(zero)0 1458 y(second)142 b(-)47 b(second)f(within)g(minute)g(\(0)h(-)h(60.9999999999\))c(\(leap) i(second!\))0 1571 y(section)94 b(-)47 b(section)f(of)h(image)f(to)i (be)f(copied)f(\(e.g.)g(21:80,101:200\))0 1684 y(simple)142 b(-)47 b(TRUE)g(\(=1\))f(if)h(FITS)g(file)g(conforms)e(to)i(the)g (Standard,)f(else)g(FALSE)h(\(=0\))0 1797 y(space)190 b(-)47 b(number)f(of)h(blank)g(spaces)f(to)h(leave)f(between)g(ASCII)g (table)h(columns)0 1910 y(status)142 b(-)47 b(returned)f(error)g (status)g(code)h(\(0)g(=)g(OK\))0 2023 y(sum)286 b(-)47 b(32)g(bit)g(unsigned)f(checksum)f(value)0 2136 y(tbcol)190 b(-)47 b(byte)g(position)e(in)i(row)g(to)g(start)g(of)g(column)f(\(1st) h(col)g(has)g(tbcol)f(=)h(1\))0 2249 y(tdisp)190 b(-)47 b(Fortran)f(style)g(display)g(format)g(for)h(the)g(table)f(column)0 2362 y(tdimstr)94 b(-)47 b(the)g(value)f(of)h(the)g(TDIMn)g(keyword)0 2475 y(templt)142 b(-)47 b(template)f(string)g(used)g(in)h(comparison)e (\(null-terminated\))0 2588 y(tfields)94 b(-)47 b(number)f(of)h(fields) f(\(columns\))g(in)h(the)g(table)0 2700 y(tfopt)190 b(-)47 b(grouping)f(table)g(member)g(transfer)g(option)g(parameter.)f(Allowed) g(values)i(are:)525 2813 y(OPT_MCP_ADD,)d(and)j(OPT_MCP_MOV.)0 2926 y(tform)190 b(-)47 b(format)f(of)h(the)g(column)f (\(null-terminated\);)d(allowed)j(values)g(are:)525 3039 y(ASCII)g(tables:)94 b(Iw,)47 b(Aw,)g(Fww.dd,)f(Eww.dd,)f(or)j(Dww.dd) 525 3152 y(Binary)e(tables:)g(rL,)h(rX,)g(rB,)g(rI,)g(rJ,)f(rA,)h(rAw,) g(rE,)g(rD,)g(rC,)g(rM)525 3265 y(where)f('w'=width)g(of)h(the)g (field,)f('d'=no.)g(of)h(decimals,)e('r'=repeat)g(count.)525 3378 y(Variable)h(length)g(array)g(columns)g(are)h(denoted)f(by)h(a)g ('1P')g(before)f(the)h(data)f(type)525 3491 y(character)f(\(e.g.,)h ('1PJ'\).)94 b(When)47 b(creating)e(a)j(binary)e(table,)g(2)h(addition) f(tform)525 3604 y(data)h(type)f(codes)h(are)g(recognized)e(by)i (CFITSIO:)e('rU')i(and)g('rV')f(for)h(unsigned)525 3717 y(16-bit)f(and)h(unsigned)f(32-bit)g(integer,)f(respectively.)0 3942 y(theap)190 b(-)47 b(zero)g(indexed)e(byte)i(offset)f(of)h (starting)f(address)g(of)h(the)g(heap)525 4055 y(relative)f(to)h(the)g (beginning)e(of)i(the)g(binary)f(table)g(data)0 4168 y(tilesize)g(-)h(array)f(of)i(length)e(NAXIS)g(that)h(specifies)e(the)i (dimensions)e(of)525 4281 y(the)i(image)f(compression)f(tiles)0 4394 y(ttype)190 b(-)47 b(label)f(or)i(name)e(for)h(table)f(column)h (\(null-terminated\))0 4507 y(tunit)190 b(-)47 b(physical)f(unit)g(for) h(table)f(column)h(\(null-terminated\))0 4620 y(typechar)f(-)h (symbolic)f(code)g(of)h(the)g(table)g(column)f(data)g(type)0 4733 y(typecode)g(-)h(data)g(type)f(code)h(of)g(the)g(table)f(column.) 94 b(The)47 b(negative)e(of)525 4846 y(the)i(value)f(indicates)g(a)h (variable)f(length)g(array)g(column.)764 4959 y(Datatype)618 b(typecode)189 b(Mnemonic)764 5072 y(bit,)46 b(X)907 b(1)381 b(TBIT)764 5185 y(byte,)46 b(B)811 b(11)381 b(TBYTE)764 5297 y(logical,)45 b(L)668 b(14)381 b(TLOGICAL)764 5410 y(ASCII)46 b(character,)f(A)286 b(16)381 b(TSTRING)764 5523 y(short)46 b(integer,)g(I)381 b(21)g(TSHORT)764 5636 y(integer,)45 b(J)668 b(41)381 b(TINT32BIT)46 b(\(same)g(as)h (TLONG\))p eop end %%Page: 184 192 TeXDict begin 184 191 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.184) cvn H.B /DEST pdfmark end 0 299 a Fj(184)1822 b Fh(APPENDIX)31 b(B.)61 b(P)-8 b(ARAMETER)30 b(DEFINITIONS)764 555 y Fe(long)46 b(long)h(integer,)e(K)191 b(81)381 b(TLONGLONG)764 668 y(real,)46 b(E)811 b(42)381 b(TFLOAT)764 781 y(double)46 b(precision,)f(D)238 b(82)381 b(TDOUBLE)764 894 y(complex,)45 b(C)668 b(83)381 b(TCOMPLEX)764 1007 y(double)46 b(complex,)f(M)286 b(163)381 b(TDBLCOMPLEX)0 1120 y(unit)238 b(-)47 b(the)g(physical)e (unit)i(string)f(\(e.g.,)g('km/s'\))g(for)h(a)g(keyword)0 1233 y(unused)142 b(-)47 b(number)f(of)h(unused)f(bytes)h(in)g(the)g (binary)f(table)g(heap)0 1346 y(urltype)94 b(-)47 b(the)g(file)g(type)f (of)h(the)g(FITS)g(file)g(\(file://,)e(ftp://,)h(mem://,)f(etc.\))0 1458 y(validheap-)g(returned)h(value)g(=)h(FALSE)g(if)g(any)g(of)g(the) g(variable)e(length)i(array)525 1571 y(address)f(are)h(outside)f(the)g (valid)h(range)f(of)h(addresses)f(in)h(the)g(heap)0 1684 y(value)190 b(-)47 b(the)g(keyword)f(value)g(string)g(\(70)h(char)g (max,)f(null-terminated\))0 1797 y(version)94 b(-)47 b(current)f(version)g(number)g(of)h(the)g(CFITSIO)f(library)0 1910 y(width)190 b(-)47 b(width)f(of)i(the)e(character)g(string)g (field)0 2023 y(xcol)238 b(-)47 b(number)f(of)h(the)g(column)f (containing)f(the)i(X)h(coordinate)d(values)0 2136 y(xinc)238 b(-)47 b(X)g(axis)g(coordinate)e(increment)g(at)j(reference)d(pixel)h (\(deg\))0 2249 y(xpix)238 b(-)47 b(X)g(axis)g(pixel)f(location)0 2362 y(xpos)238 b(-)47 b(X)g(axis)g(celestial)e(coordinate)g(\(usually) h(RA\))h(\(deg\))0 2475 y(xrefpix)94 b(-)47 b(X)g(axis)g(reference)e (pixel)i(array)f(location)0 2588 y(xrefval)94 b(-)47 b(X)g(axis)g(coordinate)e(value)h(at)i(the)f(reference)e(pixel)h (\(deg\))0 2700 y(ycol)238 b(-)47 b(number)f(of)h(the)g(column)f (containing)f(the)i(X)h(coordinate)d(values)0 2813 y(year)238 b(-)47 b(calendar)f(year)g(\(e.g.)h(1999,)f(2000,)g(etc\))0 2926 y(yinc)238 b(-)47 b(Y)g(axis)g(coordinate)e(increment)g(at)j (reference)d(pixel)h(\(deg\))0 3039 y(ypix)238 b(-)47 b(y)g(axis)g(pixel)f(location)0 3152 y(ypos)238 b(-)47 b(y)g(axis)g(celestial)e(coordinate)g(\(usually)h(DEC\))h(\(deg\))0 3265 y(yrefpix)94 b(-)47 b(Y)g(axis)g(reference)e(pixel)i(array)f (location)0 3378 y(yrefval)94 b(-)47 b(Y)g(axis)g(coordinate)e(value)h (at)i(the)f(reference)e(pixel)h(\(deg\))0 3491 y(zero)238 b(-)47 b(scaling)f(offset;)g(true)g(value)h(=)g(\(FITS)f(value\))h(*)g (scale)f(+)i(zero)p eop end %%Page: 185 193 TeXDict begin 185 192 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.185) cvn H.B /DEST pdfmark end 0 299 a 0 464 a SDict begin H.S end 0 464 a 0 464 a SDict begin 13.6 H.A end 0 464 a 0 464 a SDict begin [ /View [/XYZ H.V] /Dest (appendix.C) cvn H.B /DEST pdfmark end 0 464 a 761 x Fg(App)5 b(endix)64 b(C)0 1687 y Fm(CFITSIO)76 b(Error)h(Status)h(Co)6 b(des)0 2180 y Fj(The)28 b(follo)m(wing)h(table)g(lists)g(all)g(the)f(error)g (status)g(co)s(des)g(used)f(b)m(y)h(CFITSIO.)f(Programmers)h(are)g (encouraged)0 2293 y(to)37 b(use)e(the)h(sym)m(b)s(olic)h(mnemonics)e (\(de\014ned)g(in)h(the)g(\014le)g(\014tsio.h\))h(rather)e(than)h(the)g (actual)h(in)m(teger)h(status)0 2406 y(v)-5 b(alues)31 b(to)g(impro)m(v)m(e)g(the)g(readabilit)m(y)g(of)g(their)f(co)s(de.)48 2665 y Fe(Symbolic)45 b(Const)190 b(Value)237 b(Meaning)48 2778 y(--------------)187 b(-----)94 b(------------------------)o(----) o(---)o(----)o(----)o(--)1002 2891 y(0)191 b(OK,)47 b(no)g(error)48 3004 y(SAME_FILE)427 b(101)190 b(input)46 b(and)h(output)f(files)h(are) g(the)f(same)48 3117 y(TOO_MANY_FILES)187 b(103)j(tried)46 b(to)h(open)g(too)g(many)g(FITS)f(files)h(at)g(once)48 3230 y(FILE_NOT_OPENED)139 b(104)190 b(could)46 b(not)h(open)g(the)g (named)f(file)48 3343 y(FILE_NOT_CREATED)91 b(105)190 b(could)46 b(not)h(create)f(the)h(named)g(file)48 3456 y(WRITE_ERROR)331 b(106)190 b(error)46 b(writing)g(to)h(FITS)g(file)48 3569 y(END_OF_FILE)331 b(107)190 b(tried)46 b(to)h(move)g(past)g(end)g (of)g(file)48 3681 y(READ_ERROR)379 b(108)190 b(error)46 b(reading)g(from)h(FITS)f(file)48 3794 y(FILE_NOT_CLOSED)139 b(110)190 b(could)46 b(not)h(close)g(the)f(file)48 3907 y(ARRAY_TOO_BIG)235 b(111)190 b(array)46 b(dimensions)f(exceed)h (internal)g(limit)48 4020 y(READONLY_FILE)235 b(112)190 b(Cannot)46 b(write)g(to)i(readonly)d(file)48 4133 y(MEMORY_ALLOCATION) e(113)190 b(Could)46 b(not)h(allocate)f(memory)48 4246 y(BAD_FILEPTR)331 b(114)190 b(invalid)46 b(fitsfile)f(pointer)48 4359 y(NULL_INPUT_PTR)187 b(115)j(NULL)47 b(input)f(pointer)g(to)h (routine)48 4472 y(SEEK_ERROR)379 b(116)190 b(error)46 b(seeking)g(position)g(in)h(file)48 4698 y(BAD_URL_PREFIX)235 b(121)142 b(invalid)46 b(URL)h(prefix)f(on)h(file)g(name)48 4811 y(TOO_MANY_DRIVERS)139 b(122)j(tried)46 b(to)h(register)f(too)h (many)g(IO)g(drivers)48 4924 y(DRIVER_INIT_FAILED)c(123)142 b(driver)46 b(initialization)e(failed)48 5036 y(NO_MATCHING_DRIVER)f (124)142 b(matching)45 b(driver)i(is)g(not)g(registered)48 5149 y(URL_PARSE_ERROR)187 b(125)142 b(failed)46 b(to)h(parse)g(input)f (file)h(URL)48 5262 y(RANGE_PARSE_ERROR)91 b(126)142 b(parse)46 b(error)h(in)g(range)f(list)48 5488 y(SHARED_BADARG)235 b(151)190 b(bad)47 b(argument)e(in)j(shared)e(memory)g(driver)48 5601 y(SHARED_NULPTR)235 b(152)190 b(null)47 b(pointer)e(passed)h(as)i (an)f(argument)48 5714 y(SHARED_TABFULL)187 b(153)j(no)47 b(more)g(free)f(shared)g(memory)h(handles)1882 5942 y Fj(185)p eop end %%Page: 186 194 TeXDict begin 186 193 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.186) cvn H.B /DEST pdfmark end 0 299 a Fj(186)1589 b Fh(APPENDIX)31 b(C.)61 b(CFITSIO)29 b(ERR)m(OR)h(ST)-8 b(A)g(TUS)30 b(CODES)48 555 y Fe(SHARED_NOTINIT)187 b(154)j(shared)46 b(memory)g(driver)g(is)h(not)g(initialized)48 668 y(SHARED_IPCERR)235 b(155)190 b(IPC)47 b(error)f(returned)g(by)h(a)g(system)f(call)48 781 y(SHARED_NOMEM)283 b(156)190 b(no)47 b(memory)f(in)h(shared)f (memory)h(driver)48 894 y(SHARED_AGAIN)283 b(157)190 b(resource)45 b(deadlock)h(would)g(occur)48 1007 y(SHARED_NOFILE)235 b(158)190 b(attempt)46 b(to)h(open/create)e(lock)h(file)h(failed)48 1120 y(SHARED_NORESIZE)139 b(159)190 b(shared)46 b(memory)g(block)g (cannot)h(be)g(resized)f(at)h(the)g(moment)48 1346 y(HEADER_NOT_EMPTY) 91 b(201)190 b(header)46 b(already)g(contains)f(keywords)48 1458 y(KEY_NO_EXIST)283 b(202)190 b(keyword)46 b(not)h(found)f(in)h (header)48 1571 y(KEY_OUT_BOUNDS)187 b(203)j(keyword)46 b(record)g(number)g(is)h(out)g(of)g(bounds)48 1684 y(VALUE_UNDEFINED) 139 b(204)190 b(keyword)46 b(value)g(field)g(is)i(blank)48 1797 y(NO_QUOTE)475 b(205)190 b(string)46 b(is)h(missing)f(the)h (closing)f(quote)48 1910 y(BAD_INDEX_KEY)235 b(206)190 b(illegal)46 b(indexed)g(keyword)f(name)i(\(e.g.)f('TFORM1000'\))48 2023 y(BAD_KEYCHAR)331 b(207)190 b(illegal)46 b(character)f(in)i (keyword)f(name)h(or)g(card)48 2136 y(BAD_ORDER)427 b(208)190 b(required)45 b(keywords)h(out)h(of)g(order)48 2249 y(NOT_POS_INT)331 b(209)190 b(keyword)46 b(value)g(is)h(not)g(a)h(positive)d(integer)48 2362 y(NO_END)571 b(210)190 b(couldn't)45 b(find)i(END)g(keyword)48 2475 y(BAD_BITPIX)379 b(211)190 b(illegal)46 b(BITPIX)g(keyword)g (value)48 2588 y(BAD_NAXIS)427 b(212)190 b(illegal)46 b(NAXIS)g(keyword)g(value)48 2700 y(BAD_NAXES)427 b(213)190 b(illegal)46 b(NAXISn)g(keyword)g(value)48 2813 y(BAD_PCOUNT)379 b(214)190 b(illegal)46 b(PCOUNT)g(keyword)g(value)48 2926 y(BAD_GCOUNT)379 b(215)190 b(illegal)46 b(GCOUNT)g(keyword)g (value)48 3039 y(BAD_TFIELDS)331 b(216)190 b(illegal)46 b(TFIELDS)g(keyword)f(value)48 3152 y(NEG_WIDTH)427 b(217)190 b(negative)45 b(table)i(row)g(size)48 3265 y(NEG_ROWS)475 b(218)190 b(negative)45 b(number)i(of)g(rows)f(in)i(table)48 3378 y(COL_NOT_FOUND)235 b(219)190 b(column)46 b(with)h(this)f(name)h (not)g(found)f(in)h(table)48 3491 y(BAD_SIMPLE)379 b(220)190 b(illegal)46 b(value)g(of)h(SIMPLE)f(keyword)48 3604 y(NO_SIMPLE)427 b(221)190 b(Primary)46 b(array)g(doesn't)g(start)g (with)h(SIMPLE)48 3717 y(NO_BITPIX)427 b(222)190 b(Second)46 b(keyword)g(not)h(BITPIX)48 3830 y(NO_NAXIS)475 b(223)190 b(Third)46 b(keyword)g(not)h(NAXIS)48 3942 y(NO_NAXES)475 b(224)190 b(Couldn't)45 b(find)i(all)g(the)g(NAXISn)f(keywords)48 4055 y(NO_XTENSION)331 b(225)190 b(HDU)47 b(doesn't)f(start)g(with)h (XTENSION)e(keyword)48 4168 y(NOT_ATABLE)379 b(226)190 b(the)47 b(CHDU)f(is)i(not)f(an)g(ASCII)f(table)g(extension)48 4281 y(NOT_BTABLE)379 b(227)190 b(the)47 b(CHDU)f(is)i(not)f(a)g (binary)f(table)g(extension)48 4394 y(NO_PCOUNT)427 b(228)190 b(couldn't)45 b(find)i(PCOUNT)f(keyword)48 4507 y(NO_GCOUNT)427 b(229)190 b(couldn't)45 b(find)i(GCOUNT)f(keyword)48 4620 y(NO_TFIELDS)379 b(230)190 b(couldn't)45 b(find)i(TFIELDS)f (keyword)48 4733 y(NO_TBCOL)475 b(231)190 b(couldn't)45 b(find)i(TBCOLn)f(keyword)48 4846 y(NO_TFORM)475 b(232)190 b(couldn't)45 b(find)i(TFORMn)f(keyword)48 4959 y(NOT_IMAGE)427 b(233)190 b(the)47 b(CHDU)f(is)i(not)f(an)g(IMAGE)f(extension)48 5072 y(BAD_TBCOL)427 b(234)190 b(TBCOLn)46 b(keyword)g(value)g(<)i(0)f (or)g(>)h(rowlength)48 5185 y(NOT_TABLE)427 b(235)190 b(the)47 b(CHDU)f(is)i(not)f(a)g(table)48 5297 y(COL_TOO_WIDE)283 b(236)190 b(column)46 b(is)h(too)g(wide)g(to)g(fit)g(in)g(table)48 5410 y(COL_NOT_UNIQUE)187 b(237)j(more)47 b(than)f(1)i(column)e(name)g (matches)g(template)48 5523 y(BAD_ROW_WIDTH)235 b(241)190 b(sum)47 b(of)g(column)f(widths)g(not)h(=)h(NAXIS1)48 5636 y(UNKNOWN_EXT)331 b(251)190 b(unrecognizable)44 b(FITS)i(extension)g(type)p eop end %%Page: 187 195 TeXDict begin 187 194 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.187) cvn H.B /DEST pdfmark end 0 299 a 3764 w Fj(187)48 555 y Fe(UNKNOWN_REC)331 b(252)190 b(unknown)46 b(record;)g(1st)g(keyword)g (not)h(SIMPLE)f(or)h(XTENSION)48 668 y(END_JUNK)475 b(253)190 b(END)47 b(keyword)f(is)h(not)g(blank)48 781 y(BAD_HEADER_FILL)139 b(254)190 b(Header)46 b(fill)h(area)f(contains)g(non-blank)f(chars)48 894 y(BAD_DATA_FILL)235 b(255)190 b(Illegal)46 b(data)g(fill)h(bytes)f (\(not)h(zero)g(or)g(blank\))48 1007 y(BAD_TFORM)427 b(261)190 b(illegal)46 b(TFORM)g(format)g(code)48 1120 y(BAD_TFORM_DTYPE)139 b(262)190 b(unrecognizable)44 b(TFORM)i(data)h (type)f(code)48 1233 y(BAD_TDIM)475 b(263)190 b(illegal)46 b(TDIMn)g(keyword)g(value)48 1346 y(BAD_HEAP_PTR)283 b(264)190 b(invalid)46 b(BINTABLE)f(heap)i(pointer)f(is)h(out)g(of)g (range)48 1571 y(BAD_HDU_NUM)331 b(301)190 b(HDU)47 b(number)f(<)h(1)48 1684 y(BAD_COL_NUM)331 b(302)190 b(column)46 b(number)g(<)i(1)f(or)g(>) h(tfields)48 1797 y(NEG_FILE_POS)283 b(304)190 b(tried)46 b(to)h(move)g(to)g(negative)f(byte)g(location)g(in)h(file)48 1910 y(NEG_BYTES)427 b(306)190 b(tried)46 b(to)h(read)g(or)g(write)g (negative)e(number)h(of)h(bytes)48 2023 y(BAD_ROW_NUM)331 b(307)190 b(illegal)46 b(starting)f(row)i(number)f(in)h(table)48 2136 y(BAD_ELEM_NUM)283 b(308)190 b(illegal)46 b(starting)f(element)h (number)g(in)h(vector)48 2249 y(NOT_ASCII_COL)235 b(309)190 b(this)47 b(is)g(not)g(an)g(ASCII)f(string)g(column)48 2362 y(NOT_LOGICAL_COL)139 b(310)190 b(this)47 b(is)g(not)g(a)g (logical)f(data)h(type)f(column)48 2475 y(BAD_ATABLE_FORMAT)d(311)190 b(ASCII)46 b(table)h(column)f(has)h(wrong)f(format)48 2588 y(BAD_BTABLE_FORMAT)d(312)190 b(Binary)46 b(table)g(column)g(has)h (wrong)g(format)48 2700 y(NO_NULL)523 b(314)190 b(null)47 b(value)f(has)h(not)g(been)f(defined)48 2813 y(NOT_VARI_LEN)283 b(317)190 b(this)47 b(is)g(not)g(a)g(variable)f(length)g(column)48 2926 y(BAD_DIMEN)427 b(320)190 b(illegal)46 b(number)g(of)h(dimensions) e(in)i(array)48 3039 y(BAD_PIX_NUM)331 b(321)190 b(first)46 b(pixel)h(number)f(greater)g(than)g(last)h(pixel)48 3152 y(ZERO_SCALE)379 b(322)190 b(illegal)46 b(BSCALE)g(or)h(TSCALn)f (keyword)g(=)h(0)48 3265 y(NEG_AXIS)475 b(323)190 b(illegal)46 b(axis)g(length)g(<)i(1)48 3491 y(NOT_GROUP_TABLE)330 b(340)142 b(Grouping)46 b(function)f(error)48 3604 y (HDU_ALREADY_MEMBER)186 b(341)48 3717 y(MEMBER_NOT_FOUND)282 b(342)48 3830 y(GROUP_NOT_FOUND)330 b(343)48 3942 y(BAD_GROUP_ID)474 b(344)48 4055 y(TOO_MANY_HDUS_TRACKED)42 b(345)48 4168 y(HDU_ALREADY_TRACKED)138 b(346)48 4281 y(BAD_OPTION)570 b(347)48 4394 y(IDENTICAL_POINTERS)186 b(348)48 4507 y(BAD_GROUP_ATTACH)282 b(349)48 4620 y(BAD_GROUP_DETACH)g(350)48 4846 y(NGP_NO_MEMORY)426 b(360)238 b(malloc)46 b(failed)48 4959 y(NGP_READ_ERR)474 b(361)238 b(read)46 b(error)h(from)f(file)48 5072 y(NGP_NUL_PTR)522 b(362)238 b(null)46 b(pointer)g(passed)g(as)h (an)g(argument.)1575 5185 y(Passing)f(null)g(pointer)g(as)h(a)h(name)f (of)1575 5297 y(template)f(file)g(raises)g(this)h(error)48 5410 y(NGP_EMPTY_CURLINE)234 b(363)k(line)46 b(read)h(seems)f(to)h(be)h (empty)e(\(used)1575 5523 y(internally\))48 5636 y (NGP_UNREAD_QUEUE_FULL)c(364)238 b(cannot)46 b(unread)g(more)g(then)h (1)g(line)g(\(or)g(single)p eop end %%Page: 188 196 TeXDict begin 188 195 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 0 299 a SDict begin H.S end 0 299 a 0 299 a SDict begin H.R end 0 299 a 0 299 a SDict begin [ /View [/XYZ H.V] /Dest (page.188) cvn H.B /DEST pdfmark end 0 299 a Fj(188)1589 b Fh(APPENDIX)31 b(C.)61 b(CFITSIO)29 b(ERR)m(OR)h(ST)-8 b(A)g(TUS)30 b(CODES)1575 555 y Fe(line)47 b(twice\))48 668 y(NGP_INC_NESTING)330 b(365)238 b(too)46 b(deep)h(include)f(file)h(nesting)e(\(infinite)1575 781 y(loop,)h(template)g(includes)f(itself)i(?\))48 894 y(NGP_ERR_FOPEN)426 b(366)238 b(fopen\(\))45 b(failed,)h(cannot)g(open) h(template)e(file)48 1007 y(NGP_EOF)714 b(367)238 b(end)46 b(of)i(file)e(encountered)f(and)i(not)g(expected)48 1120 y(NGP_BAD_ARG)522 b(368)238 b(bad)46 b(arguments)g(passed.)g(Usually)f (means)1575 1233 y(internal)h(parser)g(error.)g(Should)g(not)h(happen) 48 1346 y(NGP_TOKEN_NOT_EXPECT)90 b(369)238 b(token)46 b(not)h(expected)e(here)48 1571 y(BAD_I2C)523 b(401)190 b(bad)47 b(int)g(to)g(formatted)e(string)h(conversion)48 1684 y(BAD_F2C)523 b(402)190 b(bad)47 b(float)f(to)h(formatted)f (string)g(conversion)48 1797 y(BAD_INTKEY)379 b(403)190 b(can't)46 b(interpret)g(keyword)f(value)i(as)g(integer)48 1910 y(BAD_LOGICALKEY)187 b(404)j(can't)46 b(interpret)g(keyword)f (value)i(as)g(logical)48 2023 y(BAD_FLOATKEY)283 b(405)190 b(can't)46 b(interpret)g(keyword)f(value)i(as)g(float)48 2136 y(BAD_DOUBLEKEY)235 b(406)190 b(can't)46 b(interpret)g(keyword)f (value)i(as)g(double)48 2249 y(BAD_C2I)523 b(407)190 b(bad)47 b(formatted)e(string)h(to)h(int)g(conversion)48 2362 y(BAD_C2F)523 b(408)190 b(bad)47 b(formatted)e(string)h(to)h (float)g(conversion)48 2475 y(BAD_C2D)523 b(409)190 b(bad)47 b(formatted)e(string)h(to)h(double)f(conversion)48 2588 y(BAD_DATATYPE)283 b(410)190 b(illegal)46 b(datatype)f(code)i(value)48 2700 y(BAD_DECIM)427 b(411)190 b(bad)47 b(number)f(of)h(decimal)f (places)g(specified)48 2813 y(NUM_OVERFLOW)283 b(412)190 b(overflow)45 b(during)i(data)f(type)h(conversion)48 2926 y(DATA_COMPRESSION_ERR)137 b(413)95 b(error)46 b(compressing)f (image)48 3039 y(DATA_DECOMPRESSION_ERR)c(414)95 b(error)46 b(uncompressing)f(image)48 3265 y(BAD_DATE)475 b(420)190 b(error)46 b(in)h(date)g(or)g(time)g(conversion)48 3491 y(PARSE_SYNTAX_ERR)91 b(431)190 b(syntax)46 b(error)g(in)i(parser)e (expression)48 3604 y(PARSE_BAD_TYPE)187 b(432)j(expression)45 b(did)i(not)g(evaluate)e(to)i(desired)f(type)48 3717 y(PARSE_LRG_VECTOR)91 b(433)190 b(vector)46 b(result)g(too)h(large)f (to)i(return)e(in)h(array)48 3830 y(PARSE_NO_OUTPUT)139 b(434)190 b(data)47 b(parser)f(failed)g(not)h(sent)f(an)h(out)g(column) 48 3942 y(PARSE_BAD_COL)235 b(435)190 b(bad)47 b(data)f(encounter)g (while)g(parsing)g(column)48 4055 y(PARSE_BAD_OUTPUT)91 b(436)190 b(Output)46 b(file)h(not)g(of)g(proper)f(type)48 4281 y(ANGLE_TOO_BIG)235 b(501)190 b(celestial)45 b(angle)i(too)f (large)h(for)g(projection)48 4394 y(BAD_WCS_VAL)331 b(502)190 b(bad)47 b(celestial)e(coordinate)g(or)i(pixel)g(value)48 4507 y(WCS_ERROR)427 b(503)190 b(error)46 b(in)h(celestial)f (coordinate)f(calculation)48 4620 y(BAD_WCS_PROJ)283 b(504)190 b(unsupported)45 b(type)h(of)h(celestial)f(projection)48 4733 y(NO_WCS_KEY)379 b(505)190 b(celestial)45 b(coordinate)g(keywords) h(not)h(found)48 4846 y(APPROX_WCS_KEY)187 b(506)j(approximate)45 b(wcs)i(keyword)e(values)h(were)h(returned)p eop end %%Trailer userdict /end-hook known{end-hook}if %%EOF cfitsio/docs/cfitsio.tex0000644000225700000360000171057213246025103015127 0ustar cagordonlhea\documentclass[11pt]{book} \input{html.sty} \htmladdtonavigation {\begin{rawhtml} FITSIO Home \end{rawhtml}} \oddsidemargin=0.00in \evensidemargin=0.00in \textwidth=6.5in %\topmargin=0.0in \textheight=8.75in \parindent=0cm \parskip=0.2cm \begin{document} \pagenumbering{roman} \begin{titlepage} \normalsize \vspace*{4.0cm} \begin{center} {\Huge \bf CFITSIO User's Reference Guide}\\ \end{center} \medskip \medskip \begin{center} {\LARGE \bf An Interface to FITS Format Files}\\ \end{center} \begin{center} {\LARGE \bf for C Programmers}\\ \end{center} \medskip \medskip \begin{center} {\Large Version 3.4 \\} \end{center} \bigskip \vskip 2.5cm \begin{center} {HEASARC\\ Code 662\\ Goddard Space Flight Center\\ Greenbelt, MD 20771\\ USA} \end{center} \vfill \bigskip \begin{center} {\Large August 2017\\} \end{center} \vfill \end{titlepage} \clearpage \tableofcontents \chapter{Introduction } \pagenumbering{arabic} \section{ A Brief Overview} CFITSIO is a machine-independent library of routines for reading and writing data files in the FITS (Flexible Image Transport System) data format. It can also read IRAF format image files and raw binary data arrays by converting them on the fly into a virtual FITS format file. This library is written in ANSI C and provides a powerful yet simple interface for accessing FITS files which will run on most commonly used computers and workstations. CFITSIO supports all the features described in the official definition of the FITS format and can read and write all the currently defined types of extensions, including ASCII tables (TABLE), Binary tables (BINTABLE) and IMAGE extensions. The CFITSIO routines insulate the programmer from having to deal with the complicated formatting details in the FITS file, however, it is assumed that users have a general knowledge about the structure and usage of FITS files. CFITSIO also contains a set of Fortran callable wrapper routines which allow Fortran programs to call the CFITSIO routines. See the companion ``FITSIO User's Guide'' for the definition of the Fortran subroutine calling sequences. These wrappers replace the older Fortran FITSIO library which is no longer supported. The CFITSIO package was initially developed by the HEASARC (High Energy Astrophysics Science Archive Research Center) at the NASA Goddard Space Flight Center to convert various existing and newly acquired astronomical data sets into FITS format and to further analyze data already in FITS format. New features continue to be added to CFITSIO in large part due to contributions of ideas or actual code from users of the package. The Integral Science Data Center in Switzerland, and the XMM/ESTEC project in The Netherlands made especially significant contributions that resulted in many of the new features that appeared in v2.0 of CFITSIO. \section{Sources of FITS Software and Information} The latest version of the CFITSIO source code, documentation, and example programs are available on the Web or via anonymous ftp from: \begin{verbatim} http://heasarc.gsfc.nasa.gov/fitsio ftp://legacy.gsfc.nasa.gov/software/fitsio/c \end{verbatim} Any questions, bug reports, or suggested enhancements related to the CFITSIO package should be sent to the FTOOLS Help Desk at the HEASARC: \begin{verbatim} http://heasarc.gsfc.nasa.gov/cgi-bin/ftoolshelp \end{verbatim} This User's Guide assumes that readers already have a general understanding of the definition and structure of FITS format files. Further information about FITS formats is available from the FITS Support Office at {\tt http://fits.gsfc.nasa.gov}. In particular, the 'FITS Standard' gives the authoritative definition of the FITS data format. Other documents available at that Web site provide additional historical background and practical advice on using FITS files. The HEASARC also provides a very sophisticated FITS file analysis program called `Fv' which can be used to display and edit the contents of any FITS file as well as construct new FITS files from scratch. Fv is freely available for most Unix platforms, Mac PCs, and Windows PCs. CFITSIO users may also be interested in the FTOOLS package of programs that can be used to manipulate and analyze FITS format files. Fv and FTOOLS are available from their respective Web sites at: \begin{verbatim} http://fv.gsfc.nasa.gov http://heasarc.gsfc.nasa.gov/ftools \end{verbatim} \section{Acknowledgments} The development of the many powerful features in CFITSIO was made possible through collaborations with many people or organizations from around the world. The following in particular have made especially significant contributions: Programmers from the Integral Science Data Center, Switzerland (namely, Jurek Borkowski, Bruce O'Neel, and Don Jennings), designed the concept for the plug-in I/O drivers that was introduced with CFITSIO 2.0. The use of `drivers' greatly simplified the low-level I/O, which in turn made other new features in CFITSIO (e.g., support for compressed FITS files and support for IRAF format image files) much easier to implement. Jurek Borkowski wrote the Shared Memory driver, and Bruce O'Neel wrote the drivers for accessing FITS files over the network using the FTP, HTTP, and ROOT protocols. Also, in 2009, Bruce O'Neel was the key developer of the thread-safe version of CFITSIO. The ISDC also provided the template parsing routines (written by Jurek Borkowski) and the hierarchical grouping routines (written by Don Jennings). The ISDC DAL (Data Access Layer) routines are layered on top of CFITSIO and make extensive use of these features. Giuliano Taffoni and Andrea Barisani, at INAF, University of Trieste, Italy, implemented the I/O driver routines for accessing FITS files on the computational grids using the gridftp protocol. Uwe Lammers (XMM/ESA/ESTEC, The Netherlands) designed the high-performance lexical parsing algorithm that is used to do on-the-fly filtering of FITS tables. This algorithm essentially pre-compiles the user-supplied selection expression into a form that can be rapidly evaluated for each row. Peter Wilson (RSTX, NASA/GSFC) then wrote the parsing routines used by CFITSIO based on Lammers' design, combined with other techniques such as the CFITSIO iterator routine to further enhance the data processing throughput. This effort also benefited from a much earlier lexical parsing routine that was developed by Kent Blackburn (NASA/GSFC). More recently, Craig Markwardt (NASA/GSFC) implemented additional functions (median, average, stddev) and other enhancements to the lexical parser. The CFITSIO iterator function is loosely based on similar ideas developed for the XMM Data Access Layer. Peter Wilson (RSTX, NASA/GSFC) wrote the complete set of Fortran-callable wrappers for all the CFITSIO routines, which in turn rely on the CFORTRAN macro developed by Burkhard Burow. The syntax used by CFITSIO for filtering or binning input FITS files is based on ideas developed for the AXAF Science Center Data Model by Jonathan McDowell, Antonella Fruscione, Aneta Siemiginowska and Bill Joye. See http://heasarc.gsfc.nasa.gov/docs/journal/axaf7.html for further description of the AXAF Data Model. The file decompression code were taken directly from the gzip (GNU zip) program developed by Jean-loup Gailly and others. The new compressed image data format (where the image is tiled and the compressed byte stream from each tile is stored in a binary table) was implemented in collaboration with Richard White (STScI), Perry Greenfield (STScI) and Doug Tody (NOAO). Doug Mink (SAO) provided the routines for converting IRAF format images into FITS format. Martin Reinecke (Max Planck Institute, Garching)) provided the modifications to cfortran.h that are necessary to support 64-bit integer values when calling C routines from fortran programs. The cfortran.h macros were originally developed by Burkhard Burow (CERN). Julian Taylor (ESO, Garching) provided the fast byte-swapping algorithms that use the SSE2 and SSSE3 machine instructions available on x86\_64 CPUs. In addition, many other people have made valuable contributions to the development of CFITSIO. These include (with apologies to others that may have inadvertently been omitted): Steve Allen, Carl Akerlof, Keith Arnaud, Morten Krabbe Barfoed, Kent Blackburn, G Bodammer, Romke Bontekoe, Lucio Chiappetti, Keith Costorf, Robin Corbet, John Davis, Richard Fink, Ning Gan, Emily Greene, Gretchen Green, Joe Harrington, Cheng Ho, Phil Hodge, Jim Ingham, Yoshitaka Ishisaki, Diab Jerius, Mark Levine, Todd Karakaskian, Edward King, Scott Koch, Claire Larkin, Rob Managan, Eric Mandel, Richard Mathar, John Mattox, Carsten Meyer, Emi Miyata, Stefan Mochnacki, Mike Noble, Oliver Oberdorf, Clive Page, Arvind Parmar, Jeff Pedelty, Tim Pearson, Philippe Prugniel, Maren Purves, Scott Randall, Chris Rogers, Arnold Rots, Rob Seaman, Barry Schlesinger, Robin Stebbins, Andrew Szymkowiak, Allyn Tennant, Peter Teuben, James Theiler, Doug Tody, Shiro Ueno, Steve Walton, Archie Warnock, Alan Watson, Dan Whipple, Wim Wimmers, Peter Young, Jianjun Xu, and Nelson Zarate. \section{Legal Stuff} Copyright (Unpublished--all rights reserved under the copyright laws of the United States), U.S. Government as represented by the Administrator of the National Aeronautics and Space Administration. No copyright is claimed in the United States under Title 17, U.S. Code. Permission to freely use, copy, modify, and distribute this software and its documentation without fee is hereby granted, provided that this copyright notice and disclaimer of warranty appears in all copies. DISCLAIMER: THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT SHALL NASA BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT , OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER." \chapter{ Creating the CFITSIO Library } \section{Building the Library} The CFITSIO code is contained in about 40 C source files (*.c) and header files (*.h). On VAX/VMS systems 2 assembly-code files (vmsieeed.mar and vmsieeer.mar) are also needed. CFITSIO is written in ANCI C and should be compatible with most existing C and C++ compilers. Cray supercomputers are currently not supported. \subsection{Unix Systems} The CFITSIO library is built on Unix systems by typing: \begin{verbatim} > ./configure [--prefix=/target/installation/path] [--enable-reentrant] [--enable-sse2] [--enable-ssse3] > make (or 'make shared') > make install (this step is optional) \end{verbatim} at the operating system prompt. The configure command customizes the Makefile for the particular system, then the `make' command compiles the source files and builds the library. Type `./configure' and not simply `configure' to ensure that the configure script in the current directory is run and not some other system-wide configure script. The optional 'prefix' argument to configure gives the path to the directory where the CFITSIO library and include files should be installed via the later 'make install' command. For example, \begin{verbatim} > ./configure --prefix=/usr1/local \end{verbatim} will cause the 'make install' command to copy the CFITSIO libcfitsio file to /usr1/local/lib and the necessary include files to /usr1/local/include (assuming of course that the process has permission to write to these directories). All the available configure options can be seen by entering the command \begin{verbatim} > ./configure --help \end{verbatim} Some of the more useful options are described below: The --enable-reentrant option will attempt to configure CFITSIO so that it can be used in multi-threaded programs. See the "Using CFITSIO in Multi-threaded Environments" section, below, for more details. The --enable-sse2 and --enable-ssse3 options will cause configure to attempt to build CFITSIO using faster byte-swapping algorithms. See the "Optimizing Programs" chapter of this manual for more information about these options. The --with-gsiftp-flavour and --with-gsiftp options enable support for the Globus Toolkit gsiftp protocal. See the "Extended File Name Syntax" chapter for more information. The --with-bzip2 option enables support for reading FITS files that have been externally compressed by the bzip2 algorithm. This requires that the CFITSIO library, and all applications program that use CFITSIO, to be linked to include the libbz2 library. The 'make shared' option builds a shared or dynamic version of the CFITSIO library. When using the shared library the executable code is not copied into your program at link time and instead the program locates the necessary library code at run time, normally through LD\_LIBRARY\_PATH or some other method. The advantages of using a shared library are: \begin{verbatim} 1. Less disk space if you build more than 1 program 2. Less memory if more than one copy of a program using the shared library is running at the same time since the system is smart enough to share copies of the shared library at run time. 3. Possibly easier maintenance since a new version of the shared library can be installed without relinking all the software that uses it (as long as the subroutine names and calling sequences remain unchanged). 4. No run-time penalty. \end{verbatim} The disadvantages are: \begin{verbatim} 1. More hassle at runtime. You have to either build the programs specially or have LD_LIBRARY_PATH set right. 2. There may be a slight start up penalty, depending on where you are reading the shared library and the program from and if your CPU is either really slow or really heavily loaded. \end{verbatim} On Mac OS X platforms the 'make shared' command works like on other UNIX platforms, but a .dylib file will be created instead of .so. If installed in a nonstandard location, add its location to the DYLD\_LIBRARY\_PATH environment variable so that the library can be found at run time. On HP/UX systems, the environment variable CFLAGS should be set to -Ae before running configure to enable "extended ANSI" features. By default, a set of Fortran-callable wrapper routines are also built and included in the CFITSIO library. If these wrapper routines are not needed (i.e., the CFITSIO library will not be linked to any Fortran applications which call FITSIO subroutines) then they may be omitted from the build by typing 'make all-nofitsio' instead of simply typing 'make'. This will reduce the size of the CFITSIO library slightly. It may not be possible to statically link programs that use CFITSIO on some platforms (namely, on Solaris 2.6) due to the network drivers (which provide FTP and HTTP access to FITS files). It is possible to make both a dynamic and a static version of the CFITSIO library, but network file access will not be possible using the static version. \subsection{VMS} On VAX/VMS and ALPHA/VMS systems the make\_gfloat.com command file may be executed to build the cfitsio.olb object library using the default G-floating point option for double variables. The make\_dfloat.com and make\_ieee.com files may be used instead to build the library with the other floating point options. Note that the getcwd function that is used in the group.c module may require that programs using CFITSIO be linked with the ALPHA\$LIBRARY:VAXCRTL.OLB library. See the example link line in the next section of this document. \subsection{Windows PCs} A precompiled DLL version of CFITSIO (not necessarily the latest version) is available on the CFITSIO web site. The CFITSIO library may also be built from the source code using the CMake build system. See the "README.win" file in the CFITSIO source distribution for more information. \subsection{Macintosh PCs} When building on Mac OS-X, users should follow the Unix instructions, above. See the README.MacOS file for instructions on building a Universal Binary that supports both Intel and PowerPC CPUs. \section{Testing the Library} The CFITSIO library should be tested by building and running the testprog.c program that is included with the release. On Unix systems, type: \begin{verbatim} % make testprog % testprog > testprog.lis % diff testprog.lis testprog.out % cmp testprog.fit testprog.std \end{verbatim} On VMS systems, (assuming cc is the name of the C compiler command), type: \begin{verbatim} $ cc testprog.c $ link testprog, cfitsio/lib, alpha$library:vaxcrtl/lib $ run testprog \end{verbatim} The test program should produce a FITS file called `testprog.fit' that is identical to the `testprog.std' FITS file included with this release. The diagnostic messages (which were piped to the file testprog.lis in the Unix example) should be identical to the listing contained in the file testprog.out. The 'diff' and 'cmp' commands shown above should not report any differences in the files. (There may be some minor format differences, such as the presence or absence of leading zeros, or 3 digit exponents in numbers, which can be ignored). The Fortran wrappers in CFITSIO may be tested with the testf77 program on Unix systems with: \begin{verbatim} % f77 -o testf77 testf77.f -L. -lcfitsio -lnsl -lsocket or % f77 -f -o testf77 testf77.f -L. -lcfitsio (under SUN O/S) or % f77 -o testf77 testf77.f -Wl,-L. -lcfitsio -lm -lnsl -lsocket (HP/UX) % testf77 > testf77.lis % diff testf77.lis testf77.out % cmp testf77.fit testf77.std \end{verbatim} On machines running SUN O/S, Fortran programs must be compiled with the '-f' option to force double precision variables to be aligned on 8-byte boundarys to make the fortran-declared variables compatible with C. A similar compiler option may be required on other platforms. Failing to use this option may cause the program to crash on FITSIO routines that read or write double precision variables. Also note that on some systems, the output listing of the testf77 program may differ slightly from the testf77.std template, if leading zeros are not printed by default before the decimal point when using F format. A few other utility programs are included with CFITSIO; the first four of this programs can be compiled an linked by typing `make program\_name' where `program\_name' is the actual name of the program: \begin{verbatim} speed - measures the maximum throughput (in MB per second) for writing and reading FITS files with CFITSIO. listhead - lists all the header keywords in any FITS file fitscopy - copies any FITS file (especially useful in conjunction with the CFITSIO's extended input filename syntax). cookbook - a sample program that performs common read and write operations on a FITS file. iter_a, iter_b, iter_c - examples of the CFITSIO iterator routine \end{verbatim} \section{Linking Programs with CFITSIO} When linking applications software with the CFITSIO library, several system libraries usually need to be specified on the link command line. On Unix systems, the most reliable way to determine what libraries are required is to type 'make testprog' and see what libraries the configure script has added. The typical libraries that need to be added are -lm (the math library) and -lnsl and -lsocket (needed only for FTP and HTTP file access). These latter 2 libraries are not needed on VMS and Windows platforms, because FTP file access is not currently supported on those platforms. Note that when upgrading to a newer version of CFITSIO it is usually necessary to recompile, as well as relink, the programs that use CFITSIO, because the definitions in fitsio.h often change. \section{Using CFITSIO in Multi-threaded Environments} CFITSIO can be used either with the POSIX pthreads interface or the OpenMP interface for multi-threaded parallel programs. When used in a multi-threaded environment, the CFITSIO library *must* be built using the -D\_REENTRANT compiler directive. This can be done using the following build commands: \begin{verbatim} >./configure --enable-reentrant > make \end{verbatim} A function called fits\_is\_reentrant is available to test whether or not CFITSIO was compiled with the -D\_REENTRANT directive. When this feature is enabled, multiple threads can call any of the CFITSIO routines to simultaneously read or write separate FITS files. Multiple threads can also read data from the same FITS file simultaneously, as long as the file was opened independently by each thread. This relies on the operating system to correctly deal with reading the same file by multiple processes. Different threads should not share the same 'fitsfile' pointer to read an opened FITS file, unless locks are placed around the calls to the CFITSIO reading routines. Different threads should never try to write to the same FITS file. \section{Getting Started with CFITSIO} In order to effectively use the CFITSIO library it is recommended that new users begin by reading the ``CFITSIO Quick Start Guide''. It contains all the basic information needed to write programs that perform most types of operations on FITS files. The set of example FITS utility programs that are available from the CFITSIO web site are also very useful for learning how to use CFITSIO. To learn even more about the capabilities of the CFITSIO library the following steps are recommended: 1. Read the following short `FITS Primer' chapter for an overview of the structure of FITS files. 2. Review the Programming Guidelines in Chapter 4 to become familiar with the conventions used by the CFITSIO interface. 3. Refer to the cookbook.c, listhead.c, and fitscopy.c programs that are included with this release for examples of routines that perform various common FITS file operations. Type 'make program\_name' to compile and link these programs on Unix systems. 4. Write a simple program to read or write a FITS file using the Basic Interface routines described in Chapter 5. 5. Scan through the more specialized routines that are described in the following chapters to become familiar with the functionality that they provide. \section{Example Program} The following listing shows an example of how to use the CFITSIO routines in a C program. Refer to the cookbook.c program that is included with the CFITSIO distribution for other example routines. This program creates a new FITS file, containing a FITS image. An `EXPOSURE' keyword is written to the header, then the image data are written to the FITS file before closing the FITS file. \begin{verbatim} #include "fitsio.h" /* required by every program that uses CFITSIO */ main() { fitsfile *fptr; /* pointer to the FITS file; defined in fitsio.h */ int status, ii, jj; long fpixel = 1, naxis = 2, nelements, exposure; long naxes[2] = { 300, 200 }; /* image is 300 pixels wide by 200 rows */ short array[200][300]; status = 0; /* initialize status before calling fitsio routines */ fits_create_file(&fptr, "testfile.fits", &status); /* create new file */ /* Create the primary array image (16-bit short integer pixels */ fits_create_img(fptr, SHORT_IMG, naxis, naxes, &status); /* Write a keyword; must pass the ADDRESS of the value */ exposure = 1500.; fits_update_key(fptr, TLONG, "EXPOSURE", &exposure, "Total Exposure Time", &status); /* Initialize the values in the image with a linear ramp function */ for (jj = 0; jj < naxes[1]; jj++) for (ii = 0; ii < naxes[0]; ii++) array[jj][ii] = ii + jj; nelements = naxes[0] * naxes[1]; /* number of pixels to write */ /* Write the array of integers to the image */ fits_write_img(fptr, TSHORT, fpixel, nelements, array[0], &status); fits_close_file(fptr, &status); /* close the file */ fits_report_error(stderr, status); /* print out any error messages */ return( status ); } \end{verbatim} \chapter{ A FITS Primer } This section gives a brief overview of the structure of FITS files. Users should refer to the documentation available from the FITS Support OFfice, as described in the introduction, for more detailed information on FITS formats. FITS was first developed in the late 1970's as a standard data interchange format between various astronomical observatories. Since then FITS has become the standard data format supported by most astronomical data analysis software packages. A FITS file consists of one or more Header + Data Units (HDUs), where the first HDU is called the `Primary HDU', or `Primary Array'. The primary array contains an N-dimensional array of pixels, such as a 1-D spectrum, a 2-D image, or a 3-D data cube. Six different primary data types are supported: Unsigned 8-bit bytes, 16-bit, 32-bit, and 64-bit signed integers, and 32 and 64-bit floating point reals. FITS also has a convention for storing 16 and 32-bit unsigned integers (see the later section entitled `Unsigned Integers' for more details). The primary HDU may also consist of only a header with a null array containing no data pixels. Any number of additional HDUs may follow the primary array; these additional HDUs are called FITS `extensions'. There are currently 3 types of extensions defined by the FITS standard: \begin{itemize} \item Image Extension - a N-dimensional array of pixels, like in a primary array \item ASCII Table Extension - rows and columns of data in ASCII character format \item Binary Table Extension - rows and columns of data in binary representation \end{itemize} In each case the HDU consists of an ASCII Header Unit followed by an optional Data Unit. For historical reasons, each Header or Data unit must be an exact multiple of 2880 8-bit bytes long. Any unused space is padded with fill characters (ASCII blanks or zeros). Each Header Unit consists of any number of 80-character keyword records or `card images' which have the general form: \begin{verbatim} KEYNAME = value / comment string NULLKEY = / comment: This keyword has no value \end{verbatim} The keyword names may be up to 8 characters long and can only contain uppercase letters, the digits 0-9, the hyphen, and the underscore character. The keyword name is (usually) followed by an equals sign and a space character (= ) in columns 9 - 10 of the record, followed by the value of the keyword which may be either an integer, a floating point number, a character string (enclosed in single quotes), or a boolean value (the letter T or F). A keyword may also have a null or undefined value if there is no specified value string, as in the second example, above The last keyword in the header is always the `END' keyword which has no value or comment fields. There are many rules governing the exact format of a keyword record (see the FITS Standard) so it is better to rely on standard interface software like CFITSIO to correctly construct or to parse the keyword records rather than try to deal directly with the raw FITS formats. Each Header Unit begins with a series of required keywords which depend on the type of HDU. These required keywords specify the size and format of the following Data Unit. The header may contain other optional keywords to describe other aspects of the data, such as the units or scaling values. Other COMMENT or HISTORY keywords are also frequently added to further document the data file. The optional Data Unit immediately follows the last 2880-byte block in the Header Unit. Some HDUs do not have a Data Unit and only consist of the Header Unit. If there is more than one HDU in the FITS file, then the Header Unit of the next HDU immediately follows the last 2880-byte block of the previous Data Unit (or Header Unit if there is no Data Unit). The main required keywords in FITS primary arrays or image extensions are: \begin{itemize} \item BITPIX -- defines the data type of the array: 8, 16, 32, 64, -32, -64 for unsigned 8--bit byte, 16--bit signed integer, 32--bit signed integer, 32--bit IEEE floating point, and 64--bit IEEE double precision floating point, respectively. \item NAXIS -- the number of dimensions in the array, usually 0, 1, 2, 3, or 4. \item NAXISn -- (n ranges from 1 to NAXIS) defines the size of each dimension. \end{itemize} FITS tables start with the keyword XTENSION = `TABLE' (for ASCII tables) or XTENSION = `BINTABLE' (for binary tables) and have the following main keywords: \begin{itemize} \item TFIELDS -- number of fields or columns in the table \item NAXIS2 -- number of rows in the table \item TTYPEn -- for each column (n ranges from 1 to TFIELDS) gives the name of the column \item TFORMn -- the data type of the column \item TUNITn -- the physical units of the column (optional) \end{itemize} Users should refer to the FITS Support Office at {\tt http://fits.gsfc.nasa.gov} for further information about the FITS format and related software packages. \chapter{ Programming Guidelines } \section{CFITSIO Definitions} Any program that uses the CFITSIO interface must include the fitsio.h header file with the statement \begin{verbatim} #include "fitsio.h" \end{verbatim} This header file contains the prototypes for all the CFITSIO user interface routines as well as the definitions of various constants used in the interface. It also defines a C structure of type `fitsfile' that is used by CFITSIO to store the relevant parameters that define the format of a particular FITS file. Application programs must define a pointer to this structure for each FITS file that is to be opened. This structure is initialized (i.e., memory is allocated for the structure) when the FITS file is first opened or created with the fits\_open\_file or fits\_create\_file routines. This fitsfile pointer is then passed as the first argument to every other CFITSIO routine that operates on the FITS file. Application programs must not directly read or write elements in this fitsfile structure because the definition of the structure may change in future versions of CFITSIO. A number of symbolic constants are also defined in fitsio.h for the convenience of application programmers. Use of these symbolic constants rather than the actual numeric value will help to make the source code more readable and easier for others to understand. \begin{verbatim} String Lengths, for use when allocating character arrays: #define FLEN_FILENAME 1025 /* max length of a filename */ #define FLEN_KEYWORD 72 /* max length of a keyword */ #define FLEN_CARD 81 /* max length of a FITS header card */ #define FLEN_VALUE 71 /* max length of a keyword value string */ #define FLEN_COMMENT 73 /* max length of a keyword comment string */ #define FLEN_ERRMSG 81 /* max length of a CFITSIO error message */ #define FLEN_STATUS 31 /* max length of a CFITSIO status text string */ Note that FLEN_KEYWORD is longer than the nominal 8-character keyword name length because the HIERARCH convention supports longer keyword names. Access modes when opening a FITS file: #define READONLY 0 #define READWRITE 1 BITPIX data type code values for FITS images: #define BYTE_IMG 8 /* 8-bit unsigned integers */ #define SHORT_IMG 16 /* 16-bit signed integers */ #define LONG_IMG 32 /* 32-bit signed integers */ #define LONGLONG_IMG 64 /* 64-bit signed integers */ #define FLOAT_IMG -32 /* 32-bit single precision floating point */ #define DOUBLE_IMG -64 /* 64-bit double precision floating point */ The following 4 data type codes are also supported by CFITSIO: #define SBYTE_IMG 10 /* 8-bit signed integers, equivalent to */ /* BITPIX = 8, BSCALE = 1, BZERO = -128 */ #define USHORT_IMG 20 /* 16-bit unsigned integers, equivalent to */ /* BITPIX = 16, BSCALE = 1, BZERO = 32768 */ #define ULONG_IMG 40 /* 32-bit unsigned integers, equivalent to */ /* BITPIX = 32, BSCALE = 1, BZERO = 2147483648 */ Codes for the data type of binary table columns and/or for the data type of variables when reading or writing keywords or data: DATATYPE TFORM CODE #define TBIT 1 /* 'X' */ #define TBYTE 11 /* 8-bit unsigned byte, 'B' */ #define TLOGICAL 14 /* logicals (int for keywords */ /* and char for table cols 'L' */ #define TSTRING 16 /* ASCII string, 'A' */ #define TSHORT 21 /* signed short, 'I' */ #define TLONG 41 /* signed long, */ #define TLONGLONG 81 /* 64-bit long signed integer 'K' */ #define TFLOAT 42 /* single precision float, 'E' */ #define TDOUBLE 82 /* double precision float, 'D' */ #define TCOMPLEX 83 /* complex (pair of floats) 'C' */ #define TDBLCOMPLEX 163 /* double complex (2 doubles) 'M' */ The following data type codes are also supported by CFITSIO: #define TINT 31 /* int */ #define TSBYTE 12 /* 8-bit signed byte, 'S' */ #define TUINT 30 /* unsigned int 'V' */ #define TUSHORT 20 /* unsigned short 'U' */ #define TULONG 40 /* unsigned long */ The following data type code is only for use with fits\_get\_coltype #define TINT32BIT 41 /* signed 32-bit int, 'J' */ HDU type code values (value returned when moving to new HDU): #define IMAGE_HDU 0 /* Primary Array or IMAGE HDU */ #define ASCII_TBL 1 /* ASCII table HDU */ #define BINARY_TBL 2 /* Binary table HDU */ #define ANY_HDU -1 /* matches any type of HDU */ Column name and string matching case-sensitivity: #define CASESEN 1 /* do case-sensitive string match */ #define CASEINSEN 0 /* do case-insensitive string match */ Logical states (if TRUE and FALSE are not already defined): #define TRUE 1 #define FALSE 0 Values to represent undefined floating point numbers: #define FLOATNULLVALUE -9.11912E-36F #define DOUBLENULLVALUE -9.1191291391491E-36 Image compression algorithm definitions #define RICE_1 11 #define GZIP_1 21 #define GZIP_2 22 #define PLIO_1 31 #define HCOMPRESS_1 41 #define NOCOMPRESS -1 #define NO_DITHER -1 #define SUBTRACTIVE_DITHER_1 1 #define SUBTRACTIVE_DITHER_2 2 \end{verbatim} \section{Current Header Data Unit (CHDU)} The concept of the Current Header and Data Unit, or CHDU, is fundamental to the use of the CFITSIO library. A simple FITS image may only contain a single Header and Data unit (HDU), but in general FITS files can contain multiple Header Data Units (also known as `extensions'), concatenated one after the other in the file. The user can specify which HDU should be initially opened at run time by giving the HDU name or number after the root file name. For example, 'myfile.fits[4]' opens the 5th HDU in the file (note that the numbering starts with 0), and 'myfile.fits[EVENTS] opens the HDU with the name 'EVENTS' (as defined by the EXTNAME or HDUNAME keywords). If no HDU is specified then CFITSIO opens the first HDU (the primary array) by default. The CFITSIO routines which read and write data only operate within the opened HDU, Other CFITSIO routines are provided to move to and open any other existing HDU within the FITS file or to append or insert new HDUs in the FITS file. \section{Function Names and Variable Datatypes} Most of the CFITSIO routines have both a short name as well as a longer descriptive name. The short name is only 5 or 6 characters long and is similar to the subroutine name in the Fortran-77 version of FITSIO. The longer name is more descriptive and it is recommended that it be used instead of the short name to more clearly document the source code. Many of the CFITSIO routines come in families which differ only in the data type of the associated parameter(s). The data type of these routines is indicated by the suffix of the routine name. The short routine names have a 1 or 2 character suffix (e.g., 'j' in 'ffpkyj') while the long routine names have a 4 character or longer suffix as shown in the following table: \begin{verbatim} Long Short Data Names Names Type ----- ----- ---- _bit x bit _byt b unsigned byte _sbyt sb signed byte _sht i short integer _lng j long integer _lnglng jj 8-byte LONGLONG integer (see note below) _usht ui unsigned short integer _ulng uj unsigned long integer _uint uk unsigned int integer _int k int integer _flt e real exponential floating point (float) _fixflt f real fixed-decimal format floating point (float) _dbl d double precision real floating-point (double) _fixdbl g double precision fixed-format floating point (double) _cmp c complex reals (pairs of float values) _fixcmp fc complex reals, fixed-format floating point _dblcmp m double precision complex (pairs of double values) _fixdblcmp fm double precision complex, fixed-format floating point _log l logical (int) _str s character string \end{verbatim} The logical data type corresponds to `int' for logical keyword values, and `byte' for logical binary table columns. In other words, the value when writing a logical keyword must be stored in an `int' variable, and must be stored in a `char' array when reading or writing to `L' columns in a binary table. Implicit data type conversion is not supported for logical table columns, but is for keywords, so a logical keyword may be read and cast to any numerical data type; a returned value = 0 indicates false, and any other value = true. The `int' data type may be 2 bytes long on some old PC compilers, but otherwise it is nearly always 4 bytes long. Some 64-bit machines, like the Alpha/OSF, define the `short', `int', and `long' integer data types to be 2, 4, and 8 bytes long, respectively. Because there is no universal C compiler standard for the name of the 8-byte integer datatype, the fitsio.h include file typedef's 'LONGLONG' to be equivalent to an appropriate 8-byte integer data type on each supported platform. For maximum software portability it is recommended that this LONGLONG datatype be used to define 8-byte integer variables rather than using the native data type name on a particular platform. On most 32-bit Unix and Mac OS-X operating systems LONGLONG is equivalent to the intrinsic 'long long' 8-byte integer datatype. On 64-bit systems (which currently includes Alpha OSF/1, 64-bit Sun Solaris, 64-bit SGI MIPS, and 64-bit Itanium and Opteron PC systems), LONGLONG is simply typedef'ed to be equivalent to 'long'. Microsoft Visual C++ Version 6.0 does not define a 'long long' data type, so LONGLONG is typedef'ed to be equivalent to the '\_\_int64' data type on 32-bit windows systems when using Visual C++. A related issue that affects the portability of software is how to print out the value of a 'LONGLONG' variable with printf. Developers may find it convenient to use the following preprocessing statements in their C programs to handle this in a machine-portable manner: \begin{verbatim} #if defined(_MSC_VER) /* Microsoft Visual C++ */ printf("%I64d", longlongvalue); #elif (USE_LL_SUFFIX == 1) printf("%lld", longlongvalue); #else printf("%ld", longlongvalue); #endif \end{verbatim} Similarly, the name of the C utility routine that converts a character string of digits into a 8-byte integer value is platform dependent: \begin{verbatim} #if defined(_MSC_VER) /* Microsoft Visual C++ */ /* VC++ 6.0 does not seem to have an 8-byte conversion routine */ #elif (USE_LL_SUFFIX == 1) longlongvalue = atoll(*string); #else longlongvalue = atol(*string); #endif \end{verbatim} When dealing with the FITS byte data type it is important to remember that the raw values (before any scaling by the BSCALE and BZERO, or TSCALn and TZEROn keyword values) in byte arrays (BITPIX = 8) or byte columns (TFORMn = 'B') are interpreted as unsigned bytes with values ranging from 0 to 255. Some C compilers define a 'char' variable as signed, so it is important to explicitly declare a numeric char variable as 'unsigned char' to avoid any ambiguity One feature of the CFITSIO routines is that they can operate on a `X' (bit) column in a binary table as though it were a `B' (byte) column. For example a `11X' data type column can be interpreted the same as a `2B' column (i.e., 2 unsigned 8-bit bytes). In some instances, it can be more efficient to read and write whole bytes at a time, rather than reading or writing each individual bit. The complex and double precision complex data types are not directly supported in ANSI C so these data types should be interpreted as pairs of float or double values, respectively, where the first value in each pair is the real part, and the second is the imaginary part. \section{Support for Unsigned Integers and Signed Bytes} Although FITS does not directly support unsigned integers as one of its fundamental data types, FITS can still be used to efficiently store unsigned integer data values in images and binary tables. The convention used in FITS files is to store the unsigned integers as signed integers with an associated offset (specified by the BZERO or TZEROn keyword). For example, to store unsigned 16-bit integer values in a FITS image the image would be defined as a signed 16-bit integer (with BITPIX keyword = SHORT\_IMG = 16) with the keywords BSCALE = 1.0 and BZERO = 32768. Thus the unsigned values of 0, 32768, and 65535, for example, are physically stored in the FITS image as -32768, 0, and 32767, respectively; CFITSIO automatically adds the BZERO offset to these values when they are read. Similarly, in the case of unsigned 32-bit integers the BITPIX keyword would be equal to LONG\_IMG = 32 and BZERO would be equal to 2147483648 (i.e. 2 raised to the 31st power). The CFITSIO interface routines will efficiently and transparently apply the appropriate offset in these cases so in general application programs do not need to be concerned with how the unsigned values are actually stored in the FITS file. As a convenience for users, CFITSIO has several predefined constants for the value of BITPIX (USHORT\_IMG, ULONG\_IMG) and for the TFORMn value in the case of binary tables (`U' and `V') which programmers can use when creating FITS files containing unsigned integer values. The following code fragment illustrates how to write a FITS 1-D primary array of unsigned 16-bit integers: \begin{verbatim} unsigned short uarray[100]; int naxis, status; long naxes[10], group, firstelem, nelements; ... status = 0; naxis = 1; naxes[0] = 100; fits_create_img(fptr, USHORT_IMG, naxis, naxes, &status); firstelem = 1; nelements = 100; fits_write_img(fptr, TUSHORT, firstelem, nelements, uarray, &status); ... \end{verbatim} In the above example, the 2nd parameter in fits\_create\_img tells CFITSIO to write the header keywords appropriate for an array of 16-bit unsigned integers (i.e., BITPIX = 16 and BZERO = 32768). Then the fits\_write\_img routine writes the array of unsigned short integers (uarray) into the primary array of the FITS file. Similarly, a 32-bit unsigned integer image may be created by setting the second parameter in fits\_create\_img equal to `ULONG\_IMG' and by calling the fits\_write\_img routine with the second parameter = TULONG to write the array of unsigned long image pixel values. An analogous set of routines are available for reading or writing unsigned integer values and signed byte values in a FITS binary table extension. When specifying the TFORMn keyword value which defines the format of a column, CFITSIO recognized 3 additional data type codes besides those already defined in the FITS standard: `U' meaning a 16-bit unsigned integer column, `V' for a 32-bit unsigned integer column, and 'S' for a signed byte column. These non-standard data type codes are not actually written into the FITS file but instead are just used internally within CFITSIO. The following code fragment illustrates how to use these features: \begin{verbatim} unsigned short uarray[100]; unsigned int varray[100]; int colnum, tfields, status; long nrows, firstrow, firstelem, nelements, pcount; char extname[] = "Test_table"; /* extension name */ /* define the name, data type, and physical units for the 2 columns */ char *ttype[] = { "Col_1", "Col_2", "Col_3" }; char *tform[] = { "1U", "1V", "1S"}; /* special CFITSIO codes */ char *tunit[] = { " ", " ", " " }; ... /* write the header keywords */ status = 0; nrows = 1; tfields = 3 pcount = 0; fits_create_tbl(fptr, BINARY_TBL, nrows, tfields, ttype, tform, tunit, extname, &status); /* write the unsigned shorts to the 1st column */ colnum = 1; firstrow = 1; firstelem = 1; nelements = 100; fits_write_col(fptr, TUSHORT, colnum, firstrow, firstelem, nelements, uarray, &status); /* now write the unsigned longs to the 2nd column */ colnum = 2; fits_write_col(fptr, TUINT, colnum, firstrow, firstelem, nelements, varray, &status); ... \end{verbatim} Note that the non-standard TFORM values for the 3 columns, `U' and `V', tell CFITSIO to write the keywords appropriate for unsigned 16-bit and unsigned 32-bit integers, respectively (i.e., TFORMn = '1I' and TZEROn = 32768 for unsigned 16-bit integers, and TFORMn = '1J' and TZEROn = 2147483648 for unsigned 32-bit integers). The 'S' TFORMn value tells CFITSIO to write the keywords appropriate for a signed 8-bit byte column with TFORMn = '1B' and TZEROn = -128. The calls to fits\_write\_col then write the arrays of unsigned integer values to the columns. \section{Dealing with Character Strings} The character string values in a FITS header or in an ASCII column in a FITS table extension are generally padded out with non-significant space characters (ASCII 32) to fill up the header record or the column width. When reading a FITS string value, the CFITSIO routines will strip off these non-significant trailing spaces and will return a null-terminated string value containing only the significant characters. Leading spaces in a FITS string are considered significant. If the string contains all blanks, then CFITSIO will return a single blank character, i.e, the first blank is considered to be significant, since it distinguishes the string from a null or undefined string, but the remaining trailing spaces are not significant. Similarly, when writing string values to a FITS file the CFITSIO routines expect to get a null-terminated string as input; CFITSIO will pad the string with blanks if necessary when writing it to the FITS file. When calling CFITSIO routines that return a character string it is vital that the size of the char array be large enough to hold the entire string of characters, otherwise CFITSIO will overwrite whatever memory locations follow the char array, possibly causing the program to execute incorrectly. This type of error can be difficult to debug, so programmers should always ensure that the char arrays are allocated enough space to hold the longest possible string, {\bf including} the terminating NULL character. The fitsio.h file contains the following defined constants which programmers are strongly encouraged to use whenever they are allocating space for char arrays: \begin{verbatim} #define FLEN_FILENAME 1025 /* max length of a filename */ #define FLEN_KEYWORD 72 /* max length of a keyword */ #define FLEN_CARD 81 /* length of a FITS header card */ #define FLEN_VALUE 71 /* max length of a keyword value string */ #define FLEN_COMMENT 73 /* max length of a keyword comment string */ #define FLEN_ERRMSG 81 /* max length of a CFITSIO error message */ #define FLEN_STATUS 31 /* max length of a CFITSIO status text string */ \end{verbatim} For example, when declaring a char array to hold the value string of FITS keyword, use the following statement: \begin{verbatim} char value[FLEN_VALUE]; \end{verbatim} Note that FLEN\_KEYWORD is longer than needed for the nominal 8-character keyword name because the HIERARCH convention supports longer keyword names. \section{Implicit Data Type Conversion} The CFITSIO routines that read and write numerical data can perform implicit data type conversion. This means that the data type of the variable or array in the program does not need to be the same as the data type of the value in the FITS file. Data type conversion is supported for numerical and string data types (if the string contains a valid number enclosed in quotes) when reading a FITS header keyword value and for numeric values when reading or writing values in the primary array or a table column. CFITSIO returns status = NUM\_OVERFLOW if the converted data value exceeds the range of the output data type. Implicit data type conversion is not supported within binary tables for string, logical, complex, or double complex data types. In addition, any table column may be read as if it contained string values. In the case of numeric columns the returned string will be formatted using the TDISPn display format if it exists. \section{Data Scaling} When reading numerical data values in the primary array or a table column, the values will be scaled automatically by the BSCALE and BZERO (or TSCALn and TZEROn) header values if they are present in the header. The scaled data that is returned to the reading program will have \begin{verbatim} output value = (FITS value) * BSCALE + BZERO \end{verbatim} (a corresponding formula using TSCALn and TZEROn is used when reading from table columns). In the case of integer output values the floating point scaled value is truncated to an integer (not rounded to the nearest integer). The fits\_set\_bscale and fits\_set\_tscale routines (described in the `Advanced' chapter) may be used to override the scaling parameters defined in the header (e.g., to turn off the scaling so that the program can read the raw unscaled values from the FITS file). When writing numerical data to the primary array or to a table column the data values will generally be automatically inversely scaled by the value of the BSCALE and BZERO (or TSCALn and TZEROn) keyword values if they they exist in the header. These keywords must have been written to the header before any data is written for them to have any immediate effect. One may also use the fits\_set\_bscale and fits\_set\_tscale routines to define or override the scaling keywords in the header (e.g., to turn off the scaling so that the program can write the raw unscaled values into the FITS file). If scaling is performed, the inverse scaled output value that is written into the FITS file will have \begin{verbatim} FITS value = ((input value) - BZERO) / BSCALE \end{verbatim} (a corresponding formula using TSCALn and TZEROn is used when writing to table columns). Rounding to the nearest integer, rather than truncation, is performed when writing integer data types to the FITS file. \section{Support for IEEE Special Values} The ANSI/IEEE-754 floating-point number standard defines certain special values that are used to represent such quantities as Not-a-Number (NaN), denormalized, underflow, overflow, and infinity. (See the Appendix in the FITS standard or the FITS User's Guide for a list of these values). The CFITSIO routines that read floating point data in FITS files recognize these IEEE special values and by default interpret the overflow and infinity values as being equivalent to a NaN, and convert the underflow and denormalized values into zeros. In some cases programmers may want access to the raw IEEE values, without any modification by CFITSIO. This can be done by calling the fits\_read\_img or fits\_read\_col routines while specifying 0.0 as the value of the NULLVAL parameter. This will force CFITSIO to simply pass the IEEE values through to the application program without any modification. This is not fully supported on VAX/VMS machines, however, where there is no easy way to bypass the default interpretation of the IEEE special values. This is also not supported when reading floating-point images that have been compressed with the FITS tiled image compression convention that is discussed in section 5.6; the pixels values in tile compressed images are represented by scaled integers, and a reserved integer value (not a NaN) is used to represent undefined pixels. \section{Error Status Values and the Error Message Stack} Nearly all the CFITSIO routines return an error status value in 2 ways: as the value of the last parameter in the function call, and as the returned value of the function itself. This provides some flexibility in the way programmers can test if an error occurred, as illustrated in the following 2 code fragments: \begin{verbatim} if ( fits_write_record(fptr, card, &status) ) printf(" Error occurred while writing keyword."); or, fits_write_record(fptr, card, &status); if ( status ) printf(" Error occurred while writing keyword."); \end{verbatim} A listing of all the CFITSIO status code values is given at the end of this document. Programmers are encouraged to use the symbolic mnemonics (defined in fitsio.h) rather than the actual integer status values to improve the readability of their code. The CFITSIO library uses an `inherited status' convention for the status parameter which means that if a routine is called with a positive input value of the status parameter as input, then the routine will exit immediately without changing the value of the status parameter. Thus, if one passes the status value returned from each CFITSIO routine as input to the next CFITSIO routine, then whenever an error is detected all further CFITSIO processing will cease. This convention can simplify the error checking in application programs because it is not necessary to check the value of the status parameter after every single CFITSIO routine call. If a program contains a sequence of several CFITSIO calls, one can just check the status value after the last call. Since the returned status values are generally distinctive, it should be possible to determine which routine originally returned the error status. CFITSIO also maintains an internal stack of error messages (80-character maximum length) which in many cases provide a more detailed explanation of the cause of the error than is provided by the error status number alone. It is recommended that the error message stack be printed out whenever a program detects a CFITSIO error. The function fits\_report\_error will print out the entire error message stack, or alternatively one may call fits\_read\_errmsg to get the error messages one at a time. \section{Variable-Length Arrays in Binary Tables} CFITSIO provides easy-to-use support for reading and writing data in variable length fields of a binary table. The variable length columns have TFORMn keyword values of the form `1Pt(len)' or `1Qt(len)' where `t' is the data type code (e.g., I, J, E, D, etc.) and `len' is an integer specifying the maximum length of the vector in the table. The 'P' type variable length columns use 32-bit array length and byte offset values, whereas the 'Q' type columns use 64-bit values, which may be required when dealing with large arrays. CFITSIO supports a local convention that interprets the 'P' type descriptors as unsigned 32-bit integers, which provides a factor of 2 greater range for the array length or heap address than is possible with 32-bit 'signed' integers. Note, however, that other software packages may not support this convention, and may be unable to read thees extended range variable length records. If the value of `len' is not specified when the table is created (e.g., if the TFORM keyword value is simply specified as '1PE' instead of '1PE(400) ), then CFITSIO will automatically scan the table when it is closed to determine the maximum length of the vector and will append this value to the TFORMn value. The same routines that read and write data in an ordinary fixed length binary table extension are also used for variable length fields, however, the routine parameters take on a slightly different interpretation as described below. All the data in a variable length field is written into an area called the `heap' which follows the main fixed-length FITS binary table. The size of the heap, in bytes, is specified by the PCOUNT keyword in the FITS header. When creating a new binary table, the initial value of PCOUNT should usually be set to zero. CFITSIO will recompute the size of the heap as the data is written and will automatically update the PCOUNT keyword value when the table is closed. When writing variable length data to a table, CFITSIO will automatically extend the size of the heap area if necessary, so that any following HDUs do not get overwritten. By default the heap data area starts immediately after the last row of the fixed-length table. This default starting location may be overridden by the THEAP keyword, but this is not recommended. If additional rows of data are added to the table, CFITSIO will automatically shift the the heap down to make room for the new rows, but it is obviously be more efficient to initially create the table with the necessary number of blank rows, so that the heap does not needed to be constantly moved. When writing row of data to a variable length field the entire array of values for a given row of the table must be written with a single call to fits\_write\_col. The total length of the array is given by nelements + firstelem - 1. Additional elements cannot be appended to an existing vector at a later time since any attempt to do so will simply overwrite all the previously written data and the new data will be written to a new area of the heap. The fits\_compress\_heap routine is provided to compress the heap and recover any unused space. To avoid having to deal with this issue, it is recommended that rows in a variable length field should only be written once. An exception to this general rule occurs when setting elements of an array as undefined. It is allowed to first write a dummy value into the array with fits\_write\_col, and then call fits\_write\_col\_nul to flag the desired elements as undefined. Note that the rows of a table, whether fixed or variable length, do not have to be written consecutively and may be written in any order. When writing to a variable length ASCII character field (e.g., TFORM = '1PA') only a single character string can be written. The `firstelem' and `nelements' parameter values in the fits\_write\_col routine are ignored and the number of characters to write is simply determined by the length of the input null-terminated character string. The fits\_write\_descript routine is useful in situations where multiple rows of a variable length column have the identical array of values. One can simply write the array once for the first row, and then use fits\_write\_descript to write the same descriptor values into the other rows; all the rows will then point to the same storage location thus saving disk space. When reading from a variable length array field one can only read as many elements as actually exist in that row of the table; reading does not automatically continue with the next row of the table as occurs when reading an ordinary fixed length table field. Attempts to read more than this will cause an error status to be returned. One can determine the number of elements in each row of a variable column with the fits\_read\_descript routine. \section{Multiple Access to the Same FITS File} CFITSIO supports simultaneous read and write access to different HDUs in the same FITS file in some circumstances, as described below: \begin{itemize} \item Multi-threaded programs When CFITSIO is compiled with the -D\_REENTRANT directive (as can be tested with the fits\_is\_reentrant function) different threads can call any of the CFITSIO routines to simultaneously read or write separate FITS files. Multiple threads can also read data from the same FITS file simultaneously, as long as the file was opened independently by each thread. This relies on the operating system to correctly deal with reading the same file by multiple processes. Different threads should not share the same 'fitsfile' pointer to read an opened FITS file, unless locks are placed around the calls to the CFITSIO reading routines. Different threads should never try to write to the same FITS file. \item Multiple read access to the same FITS file within a single program/thread A single process may open the same FITS file with READONLY access multiple times, and thus create multiple 'fitsfile*' pointers to that same file within CFITSIO. This relies on the operating system's ability to open a single file multiple times and correctly manage the subsequent read requests directed to the different C 'file*' pointers, which actually all point to the same file. CFITSIO simply executes the read requests to the differnet 'fitsfile*' pointers the same as if they were physically different files. \item Multiple write access to the same FITS file within a single program/thread CFITSIO supports opening the same FITS file multiple times with WRITE access, but it only physically opens the file (at the operating system level) once, on the first call to fits\_open\_file. If fits\_open\_file is subsequently called to open the same file again, CFITSIO will recognize that the file is already open, and will return a new 'fitsfile*' pointer that logically points to the first 'fitsfile*' pointer, without actually opening the file a second time. The application program can then treat the 2 'fitsfile*' pointers as if they point to different files, and can seemingly move to and write data to 2 different HDUs within the same file. However, each time the application program switches which 'fitsfile*' pointer it is writing to, CFITSIO will flush any internal buffers that contain data written to the first 'fitsfile*' pointer, then move to the HDU that the other 'fitsfile*' pointer is writing to. Obviously, this may add a significant amount of computational overhead if the application program uses this feature to frequently switch back and forth between writing to 2 (or more) HDUs in the same file, so this capability should be used judiciously. Note that CFITSIO will not allow a FITS file to be opened a second time with READWRITE access if it was opened previously with READONLY access. \end{itemize} \section{When the Final Size of the FITS HDU is Unknown} It is not required to know the total size of a FITS data array or table before beginning to write the data to the FITS file. In the case of the primary array or an image extension, one should initially create the array with the size of the highest dimension (largest NAXISn keyword) set to a dummy value, such as 1. Then after all the data have been written and the true dimensions are known, then the NAXISn value should be updated using the fits\_update\_key routine before moving to another extension or closing the FITS file. When writing to FITS tables, CFITSIO automatically keeps track of the highest row number that is written to, and will increase the size of the table if necessary. CFITSIO will also automatically insert space in the FITS file if necessary, to ensure that the data 'heap', if it exists, and/or any additional HDUs that follow the table do not get overwritten as new rows are written to the table. As a general rule it is best to specify the initial number of rows = 0 when the table is created, then let CFITSIO keep track of the number of rows that are actually written. The application program should not manually update the number of rows in the table (as given by the NAXIS2 keyword) since CFITSIO does this automatically. If a table is initially created with more than zero rows, then this will usually be considered as the minimum size of the table, even if fewer rows are actually written to the table. Thus, if a table is initially created with NAXIS2 = 20, and CFITSIO only writes 10 rows of data before closing the table, then NAXIS2 will remain equal to 20. If however, 30 rows of data are written to this table, then NAXIS2 will be increased from 20 to 30. The one exception to this automatic updating of the NAXIS2 keyword is if the application program directly modifies the value of NAXIS2 (up or down) itself just before closing the table. In this case, CFITSIO does not update NAXIS2 again, since it assumes that the application program must have had a good reason for changing the value directly. This is not recommended, however, and is only provided for backward compatibility with software that initially creates a table with a large number of rows, than decreases the NAXIS2 value to the actual smaller value just before closing the table. \section{CFITSIO Size Limitations} CFITSIO places very few restrictions on the size of FITS files that it reads or writes. There are a few limits, however, that may affect some extreme cases: 1. The maximum number of FITS files that may be simultaneously opened by CFITSIO is set by NMAXFILES, as defined in fitsio2.h. The current default value is 1000, but this may be increased if necessary. Note that CFITSIO allocates NIOBUF * 2880 bytes of I/O buffer space for each file that is opened. The default value of NIOBUF is 40 (defined in fitsio.h), so this amounts to more than 115K of memory for each opened file (or 115 MB for 1000 opened files). Note that the underlying operating system, may have a lower limit on the number of files that can be opened simultaneously. 2. It used to be common for computer systems to only support disk files up to 2**31 bytes = 2.1 GB in size, but most systems now support larger files. CFITSIO can optionally read and write these so-called 'large files' that are greater than 2.1 GB on platforms where they are supported, but this usually requires that special compiler option flags be specified to turn on this option. On linux and solaris systems the compiler flags are '-D\_LARGEFILE\_SOURCE' and `-D\_FILE\_OFFSET\_BITS=64'. These flags may also work on other platforms but this has not been tested. Starting with version 3.0 of CFITSIO, the default Makefile that is distributed with CFITSIO will include these 2 compiler flags when building on Solaris and Linux PC systems. Users on other platforms will need to add these compiler flags manually if they want to support large files. In most cases it appears that it is not necessary to include these compiler flags when compiling application code that call the CFITSIO library routines. When CFITSIO is built with large file support (e.g., on Solaris and Linux PC system by default) then it can read and write FITS data files on disk that have any of these conditions: \begin{itemize} \item FITS files larger than 2.1 GB in size \item FITS images containing greater than 2.1 G pixels \item FITS images that have one dimension with more than 2.1 G pixels (as given by one of the NAXISn keyword) \item FITS tables containing more than 2.1E09 rows (given by the NAXIS2 keyword), or with rows that are more than 2.1 GB wide (given by the NAXIS1 keyword) \item FITS binary tables with a variable-length array heap that is larger than 2.1 GB (given by the PCOUNT keyword) \end{itemize} The current maximum FITS file size supported by CFITSIO is about 6 terabytes (containing 2**31 FITS blocks, each 2880 bytes in size). Currently, support for large files in CFITSIO has been tested on the Linux, Solaris, and IBM AIX operating systems. Note that when writing application programs that are intended to support large files it is important to use 64-bit integer variables to store quantities such as the dimensions of images, or the number of rows in a table. These programs must also call the special versions of some of the CFITSIO routines that have been adapted to support 64-bit integers. The names of these routines end in 'll' ('el' 'el') to distinguish them from the 32-bit integer version (e.g., fits\_get\_num\_rowsll). \chapter{Basic CFITSIO Interface Routines } This chapter describes the basic routines in the CFITSIO user interface that provide all the functions normally needed to read and write most FITS files. It is recommended that these routines be used for most applications and that the more advanced routines described in the next chapter only be used in special circumstances when necessary. The following conventions are used in this chapter in the description of each function: 1. Most functions have 2 names: a long descriptive name and a short concise name. Both names are listed on the first line of the following descriptions, separated by a slash (/) character. Programmers may use either name in their programs but the long names are recommended to help document the code and make it easier to read. 2. A right arrow symbol ($>$) is used in the function descriptions to separate the input parameters from the output parameters in the definition of each routine. This symbol is not actually part of the C calling sequence. 3. The function parameters are defined in more detail in the alphabetical listing in Appendix B. 4. The first argument in almost all the functions is a pointer to a structure of type `fitsfile'. Memory for this structure is allocated by CFITSIO when the FITS file is first opened or created and is freed when the FITS file is closed. 5. The last argument in almost all the functions is the error status parameter. It must be equal to 0 on input, otherwise the function will immediately exit without doing anything. A non-zero output value indicates that an error occurred in the function. In most cases the status value is also returned as the value of the function itself. \section{CFITSIO Error Status Routines} \begin{description} \item[1 ] Return a descriptive text string (30 char max.) corresponding to a CFITSIO error status code.\label{ffgerr} \end{description} \begin{verbatim} void fits_get_errstatus / ffgerr (int status, > char *err_text) \end{verbatim} \begin{description} \item[2 ] Return the top (oldest) 80-character error message from the internal CFITSIO stack of error messages and shift any remaining messages on the stack up one level. Call this routine repeatedly to get each message in sequence. The function returns a value = 0 and a null error message when the error stack is empty. \label{ffgmsg} \end{description} \begin{verbatim} int fits_read_errmsg / ffgmsg (char *err_msg) \end{verbatim} \begin{description} \item[3 ] Print out the error message corresponding to the input status value and all the error messages on the CFITSIO stack to the specified file stream (normally to stdout or stderr). If the input status value = 0 then this routine does nothing. \label{ffrprt} \end{description} \begin{verbatim} void fits_report_error / ffrprt (FILE *stream, status) \end{verbatim} \begin{description} \item[4 ]The fits\_write\_errmark routine puts an invisible marker on the CFITSIO error stack. The fits\_clear\_errmark routine can then be used to delete any more recent error messages on the stack, back to the position of the marker. This preserves any older error messages on the stack. The fits\_clear\_errmsg routine simply clears all the messages (and marks) from the stack. These routines are called without any arguments. \label{ffpmrk} \label{ffcmsg} \end{description} \begin{verbatim} void fits_write_errmark / ffpmrk (void) void fits_clear_errmark / ffcmrk (void) void fits_clear_errmsg / ffcmsg (void) \end{verbatim} \section{FITS File Access Routines} \begin{description} \item[1 ] Open an existing data file. \label{ffopen} \begin{verbatim} int fits_open_file / ffopen (fitsfile **fptr, char *filename, int iomode, > int *status) int fits_open_diskfile / ffdkopen (fitsfile **fptr, char *filename, int iomode, > int *status) int fits_open_data / ffdopn (fitsfile **fptr, char *filename, int iomode, > int *status) int fits_open_table / fftopn (fitsfile **fptr, char *filename, int iomode, > int *status) int fits_open_image / ffiopn (fitsfile **fptr, char *filename, int iomode, > int *status) int fits_open_extlist / ffeopn (fitsfile **fptr, char *filename, int iomode, char *extlist, > int *hdutype, int *status) \end{verbatim} The iomode parameter determines the read/write access allowed in the file and can have values of READONLY (0) or READWRITE (1). The filename parameter gives the name of the file to be opened, followed by an optional argument giving the name or index number of the extension within the FITS file that should be moved to and opened (e.g., \verb-myfile.fits+3- or \verb-myfile.fits[3]- moves to the 3rd extension within the file, and \verb-myfile.fits[events]- moves to the extension with the keyword EXTNAME = 'EVENTS'). The fits\_open\_diskfile routine is similar to the fits\_open\_file routine except that it does not support the extended filename syntax in the input file name. This routine simply tries to open the specified input file on magnetic disk. This routine is mainly for use in cases where the filename (or directory path) contains square or curly bracket characters that would confuse the extended filename parser. The fits\_open\_data routine is similar to the fits\_open\_file routine except that it will move to the first HDU containing significant data, if a HDU name or number to open was not explicitly specified as part of the filename. In this case, it will look for the first IMAGE HDU with NAXIS greater than 0, or the first table that does not contain the strings `GTI' (Good Time Interval extension) or `OBSTABLE' in the EXTNAME keyword value. The fits\_open\_table and fits\_open\_image routines are similar to fits\_open\_data except they will move to the first significant table HDU or image HDU in the file, respectively, if a HDU name or number is not specified as part of the filename. The fits\_open\_extname routine opens the file and attempts to move to a 'useful' HDU. If after opening the file CFITSIO is pointing to null primary array, then CFITSIO will attempt to move to the first extension that has an EXTNAME or HDUNAME keyword value that matches one of the names in the input extlist space-delimited list of names. If that fails, then CFITSIO simply moves to the 2nd HDU in the file. IRAF images (.imh format files) and raw binary data arrays may also be opened with READONLY access. CFITSIO will automatically test if the input file is an IRAF image, and if, so will convert it on the fly into a virtual FITS image before it is opened by the application program. If the input file is a raw binary data array of numbers, then the data type and dimensions of the array must be specified in square brackets following the name of the file (e.g. 'rawfile.dat[i512,512]' opens a 512 x 512 short integer image). See the `Extended File Name Syntax' chapter for more details on how to specify the raw file name. The raw file is converted on the fly into a virtual FITS image in memory that is then opened by the application program with READONLY access. Programs can read the input file from the 'stdin' file stream if a dash character ('-') is given as the filename. Files can also be opened over the network using FTP or HTTP protocols by supplying the appropriate URL as the filename. The HTTPS protocol is also supported if the CFITSIO build includes the libcurl library. (If the CFITSIO 'configure' script finds a usable libcurl library on your system, it will automatically be included in the build.) The input file can be modified in various ways to create a virtual file (usually stored in memory) that is then opened by the application program by supplying a filtering or binning specifier in square brackets following the filename. Some of the more common filtering methods are illustrated in the following paragraphs, but users should refer to the 'Extended File Name Syntax' chapter for a complete description of the full file filtering syntax. When opening an image, a rectangular subset of the physical image may be opened by listing the first and last pixel in each dimension (and optional pixel skipping factor): \begin{verbatim} myimage.fits[101:200,301:400] \end{verbatim} will create and open a 100x100 pixel virtual image of that section of the physical image, and \verb+myimage.fits[*,-*]+ opens a virtual image that is the same size as the physical image but has been flipped in the vertical direction. When opening a table, the filtering syntax can be used to add or delete columns or keywords in the virtual table: \verb-myfile.fits[events][col !time; PI = PHA*1.2]- opens a virtual table in which the TIME column has been deleted and a new PI column has been added with a value 1.2 times that of the PHA column. Similarly, one can filter a table to keep only those rows that satisfy a selection criterion: \verb-myfile.fits[events][pha > 50]- creates and opens a virtual table containing only those rows with a PHA value greater than 50. A large number of boolean and mathematical operators can be used in the selection expression. One can also filter table rows using 'Good Time Interval' extensions, and spatial region filters as in \verb-myfile.fits[events][gtifilter()]- and \verb-myfile.fits[events][regfilter( "stars.rng")]-. Finally, table columns may be binned or histogrammed to generate a virtual image. For example, \verb-myfile.fits[events][bin (X,Y)=4]- will result in a 2-dimensional image calculated by binning the X and Y columns in the event table with a bin size of 4 in each dimension. The TLMINn and TLMAXn keywords will be used by default to determine the range of the image. A single program can open the same FITS file more than once and then treat the resulting fitsfile pointers as though they were completely independent FITS files. Using this facility, a program can open a FITS file twice, move to 2 different extensions within the file, and then read and write data in those extensions in any order. \end{description} \begin{description} \item[2 ] Create and open a new empty output FITS file. \label{ffinit} \begin{verbatim} int fits_create_file / ffinit (fitsfile **fptr, char *filename, > int *status) int fits_create_diskfile / ffdkinit (fitsfile **fptr, char *filename, > int *status) \end{verbatim} An error will be returned if the specified file already exists, unless the filename is prefixed with an exclamation point (!). In that case CFITSIO will overwrite (delete) any existing file with the same name. Note that the exclamation point is a special UNIX character so if it is used on the command line it must be preceded by a backslash to force the UNIX shell to accept the character as part of the filename. The output file will be written to the 'stdout' file stream if a dash character ('-') or the string 'stdout' is given as the filename. Similarly, '-.gz' or 'stdout.gz' will cause the file to be gzip compressed before it is written out to the stdout stream. Optionally, the name of a template file that is used to define the structure of the new file may be specified in parentheses following the output file name. The template file may be another FITS file, in which case the new file, at the time it is opened, will be an exact copy of the template file except that the data structures (images and tables) will be filled with zeros. Alternatively, the template file may be an ASCII format text file containing directives that define the keywords to be created in each HDU of the file. See the 'Extended File Name Syntax' section for a complete description of the template file syntax. The fits\_create\_diskfile routine is similar to the fits\_create\_file routine except that it does not support the extended filename syntax in the input file name. This routine simply tries to create the specified file on magnetic disk. This routine is mainly for use in cases where the filename (or directory path) contains square or curly bracket characters that would confuse the extended filename parser. \end{description} \begin{description} \item[3 ] Close a previously opened FITS file. The first routine simply closes the file, whereas the second one also DELETES the file, which can be useful in cases where a FITS file has been partially created, but then an error occurs which prevents it from being completed. Note that these routines behave differently than most other CFITSIO routines if the input value of the `status' parameter is not zero: Instead of simply returning to the calling program without doing anything, these routines effectively ignore the input status value and still attempt to close or delete the file. \label{ffclos} \label{ffdelt} \end{description} \begin{verbatim} int fits_close_file / ffclos (fitsfile *fptr, > int *status) int fits_delete_file / ffdelt (fitsfile *fptr, > int *status) \end{verbatim} \begin{description} \item[4 ]Return the name, I/O mode (READONLY or READWRITE), and/or the file type (e.g. 'file://', 'ftp://') of the opened FITS file. \label{ffflnm} \label{ffflmd} \label{ffurlt} \end{description} \begin{verbatim} int fits_file_name / ffflnm (fitsfile *fptr, > char *filename, int *status) int fits_file_mode / ffflmd (fitsfile *fptr, > int *iomode, int *status) int fits_url_type / ffurlt (fitsfile *fptr, > char *urltype, int *status) \end{verbatim} \section{HDU Access Routines} The following functions perform operations on Header-Data Units (HDUs) as a whole. \begin{description} \item[1 ] Move to a different HDU in the file. The first routine moves to a specified absolute HDU number (starting with 1 for the primary array) in the FITS file, and the second routine moves a relative number HDUs forward or backward from the current HDU. A null pointer may be given for the hdutype parameter if it's value is not needed. The third routine moves to the (first) HDU which has the specified extension type and EXTNAME and EXTVER keyword values (or HDUNAME and HDUVER keywords). The hdutype parameter may have a value of IMAGE\_HDU, ASCII\_TBL, BINARY\_TBL, or ANY\_HDU where ANY\_HDU means that only the extname and extver values will be used to locate the correct extension. If the input value of extver is 0 then the EXTVER keyword is ignored and the first HDU with a matching EXTNAME (or HDUNAME) keyword will be found. If no matching HDU is found in the file then the current HDU will remain unchanged and a status = BAD\_HDU\_NUM will be returned. \label{ffmahd} \label{ffmrhd} \label{ffmnhd} \end{description} \begin{verbatim} int fits_movabs_hdu / ffmahd (fitsfile *fptr, int hdunum, > int *hdutype, int *status) int fits_movrel_hdu / ffmrhd (fitsfile *fptr, int nmove, > int *hdutype, int *status) int fits_movnam_hdu / ffmnhd (fitsfile *fptr, int hdutype, char *extname, int extver, > int *status) \end{verbatim} \begin{description} \item[2 ] Return the total number of HDUs in the FITS file. This returns the number of completely defined HDUs in the file. If a new HDU has just been added to the FITS file, then that last HDU will only be counted if it has been closed, or if data has been written to the HDU. The current HDU remains unchanged by this routine. \label{ffthdu} \end{description} \begin{verbatim} int fits_get_num_hdus / ffthdu (fitsfile *fptr, > int *hdunum, int *status) \end{verbatim} \begin{description} \item[3 ] Return the number of the current HDU (CHDU) in the FITS file (where the primary array = 1). This function returns the HDU number rather than a status value. \label{ffghdn} \end{description} \begin{verbatim} int fits_get_hdu_num / ffghdn (fitsfile *fptr, > int *hdunum) \end{verbatim} \begin{description} \item[4 ] Return the type of the current HDU in the FITS file. The possible values for hdutype are: IMAGE\_HDU, ASCII\_TBL, or BINARY\_TBL. \label{ffghdt} \end{description} \begin{verbatim} int fits_get_hdu_type / ffghdt (fitsfile *fptr, > int *hdutype, int *status) \end{verbatim} \begin{description} \item[5 ] Copy all or part of the HDUs in the FITS file associated with infptr and append them to the end of the FITS file associated with outfptr. If 'previous' is true (not 0), then any HDUs preceding the current HDU in the input file will be copied to the output file. Similarly, 'current' and 'following' determine whether the current HDU, and/or any following HDUs in the input file will be copied to the output file. Thus, if all 3 parameters are true, then the entire input file will be copied. On exit, the current HDU in the input file will be unchanged, and the last HDU in the output file will be the current HDU. \label{ffcpfl} \end{description} \begin{verbatim} int fits_copy_file / ffcpfl (fitsfile *infptr, fitsfile *outfptr, int previous, int current, int following, > int *status) \end{verbatim} \begin{description} \item[6 ] Copy the current HDU from the FITS file associated with infptr and append it to the end of the FITS file associated with outfptr. Space may be reserved for MOREKEYS additional keywords in the output header. \label{ffcopy} \end{description} \begin{verbatim} int fits_copy_hdu / ffcopy (fitsfile *infptr, fitsfile *outfptr, int morekeys, > int *status) \end{verbatim} \begin{description} \item[7 ] Write the current HDU in the input FITS file to the output FILE stream (e.g., to stdout). \label{ffwrhdu} \end{description} \begin{verbatim} int fits_write_hdu / ffwrhdu (fitsfile *infptr, FILE *stream, > int *status) \end{verbatim} \begin{description} \item[8 ] Copy the header (and not the data) from the CHDU associated with infptr to the CHDU associated with outfptr. If the current output HDU is not completely empty, then the CHDU will be closed and a new HDU will be appended to the output file. An empty output data unit will be created with all values initially = 0). \label{ffcphd} \end{description} \begin{verbatim} int fits_copy_header / ffcphd (fitsfile *infptr, fitsfile *outfptr, > int *status) \end{verbatim} \begin{description} \item[9 ] Delete the CHDU in the FITS file. Any following HDUs will be shifted forward in the file, to fill in the gap created by the deleted HDU. In the case of deleting the primary array (the first HDU in the file) then the current primary array will be replace by a null primary array containing the minimum set of required keywords and no data. If there are more extensions in the file following the one that is deleted, then the the CHDU will be redefined to point to the following extension. If there are no following extensions then the CHDU will be redefined to point to the previous HDU. The output hdutype parameter returns the type of the new CHDU. A null pointer may be given for hdutype if the returned value is not needed. \label{ffdhdu} \end{description} \begin{verbatim} int fits_delete_hdu / ffdhdu (fitsfile *fptr, > int *hdutype, int *status) \end{verbatim} \section{Header Keyword Read/Write Routines} These routines read or write keywords in the Current Header Unit (CHU). Wild card characters (*, ?, or \#) may be used when specifying the name of the keyword to be read: a '?' will match any single character at that position in the keyword name and a '*' will match any length (including zero) string of characters. The '\#' character will match any consecutive string of decimal digits (0 - 9). When a wild card is used the routine will only search for a match from the current header position to the end of the header and will not resume the search from the top of the header back to the original header position as is done when no wildcards are included in the keyword name. The fits\_read\_record routine may be used to set the starting position when doing wild card searches. A status value of KEY\_NO\_EXIST is returned if the specified keyword to be read is not found in the header. \subsection{Keyword Reading Routines} \begin{description} \item[1 ] Return the number of existing keywords (not counting the END keyword) and the amount of space currently available for more keywords. It returns morekeys = -1 if the header has not yet been closed. Note that CFITSIO will dynamically add space if required when writing new keywords to a header so in practice there is no limit to the number of keywords that can be added to a header. A null pointer may be entered for the morekeys parameter if it's value is not needed. \label{ffghsp} \end{description} \begin{verbatim} int fits_get_hdrspace / ffghsp (fitsfile *fptr, > int *keysexist, int *morekeys, int *status) \end{verbatim} \begin{description} \item[2 ] Return the specified keyword. In the first routine, the datatype parameter specifies the desired returned data type of the keyword value and can have one of the following symbolic constant values: TSTRING, TLOGICAL (== int), TBYTE, TSHORT, TUSHORT, TINT, TUINT, TLONG, TULONG, TLONGLONG, TFLOAT, TDOUBLE, TCOMPLEX, and TDBLCOMPLEX. Within the context of this routine, TSTRING corresponds to a 'char*' data type, i.e., a pointer to a character array. Data type conversion will be performed for numeric values if the keyword value does not have the same data type. If the value of the keyword is undefined (i.e., the value field is blank) then an error status = VALUE\_UNDEFINED will be returned. The second routine returns the keyword value as a character string (a literal copy of what is in the value field) regardless of the intrinsic data type of the keyword. The third routine returns the entire 80-character header record of the keyword, with any trailing blank characters stripped off. The fourth routine returns the (next) header record that contains the literal string of characters specified by the 'string' argument. If a NULL comment pointer is supplied then the comment string will not be returned. \label{ffgky} \label{ffgkey} \label{ffgcrd} \end{description} \begin{verbatim} int fits_read_key / ffgky (fitsfile *fptr, int datatype, char *keyname, > DTYPE *value, char *comment, int *status) int fits_read_keyword / ffgkey (fitsfile *fptr, char *keyname, > char *value, char *comment, int *status) int fits_read_card / ffgcrd (fitsfile *fptr, char *keyname, > char *card, int *status) int fits_read_str / ffgstr (fitsfile *fptr, char *string, > char *card, int *status) \end{verbatim} \begin{description} \item[3 ] Read a string-valued keyword and return the string length, the value string, and/or the comment field. The first routine, ffgksl, simply returns the length of the character string value of the specified keyword. The second routine, ffgsky, also returns up to maxchar characters of the keyword value string, starting with the firstchar character, and the keyword comment string (unless the input value of comm = NULL). The valuelen argument returns the total length of the keyword value string regardless of how much of the string is actually returned (which depends on the value of the firstchar and maxchar arguments). Note that the value character string argument must be allocated large enough to also hold the null terminator at the end of the returned string. These routines support string keywords that use the CONTINUE convention to continue long string values over multiple FITS header records. Normally, string-valued keywords have a maximum length of 68 characters, however, CONTINUE'd string keywords may be arbitrarily long. \label{ffgksl} \label{ffgsky} \end{description} \begin{verbatim} int fits_get_key_strlen / ffgksl (fitsfile *fptr, const char *keyname, int *length, int *status); int fits_read_string_key / ffgsky (fitsfile *fptr, const char *keyname, int firstchar, int maxchar, char *value, int *valuelen, char *comm, int *status); \end{verbatim} \begin{description} \item[4 ] Return the nth header record in the CHU. The first keyword in the header is at keynum = 1; if keynum = 0 then these routines simply reset the internal CFITSIO pointer to the beginning of the header so that subsequent keyword operations will start at the top of the header (e.g., prior to searching for keywords using wild cards in the keyword name). The first routine returns the entire 80-character header record (with trailing blanks truncated), while the second routine parses the record and returns the name, value, and comment fields as separate (blank truncated) character strings. If a NULL comment pointer is given on input, then the comment string will not be returned. \label{ffgrec} \label{ffgkyn} \end{description} \begin{verbatim} int fits_read_record / ffgrec (fitsfile *fptr, int keynum, > char *card, int *status) int fits_read_keyn / ffgkyn (fitsfile *fptr, int keynum, > char *keyname, char *value, char *comment, int *status) \end{verbatim} \begin{description} \item[5 ] Return the next keyword whose name matches one of the strings in 'inclist' but does not match any of the strings in 'exclist'. The strings in inclist and exclist may contain wild card characters (*, ?, and \#) as described at the beginning of this section. This routine searches from the current header position to the end of the header, only, and does not continue the search from the top of the header back to the original position. The current header position may be reset with the ffgrec routine. Note that nexc may be set = 0 if there are no keywords to be excluded. This routine returns status = KEY\_NO\_EXIST if a matching keyword is not found. \label{ffgnxk} \end{description} \begin{verbatim} int fits_find_nextkey / ffgnxk (fitsfile *fptr, char **inclist, int ninc, char **exclist, int nexc, > char *card, int *status) \end{verbatim} \begin{description} \item[6 ] Return the physical units string from an existing keyword. This routine uses a local convention, shown in the following example, in which the keyword units are enclosed in square brackets in the beginning of the keyword comment field. A null string is returned if no units are defined for the keyword. \label{ffgunt} \end{description} \begin{verbatim} VELOCITY= 12.3 / [km/s] orbital speed int fits_read_key_unit / ffgunt (fitsfile *fptr, char *keyname, > char *unit, int *status) \end{verbatim} \begin{description} \item[7 ] Concatenate the header keywords in the CHDU into a single long string of characters. This provides a convenient way of passing all or part of the header information in a FITS HDU to other subroutines. Each 80-character fixed-length keyword record is appended to the output character string, in order, with no intervening separator or terminating characters. The last header record is terminated with a NULL character. These routine allocates memory for the returned character array, so the calling program must free the memory when finished. The cleanest way to do this is to call the fits\_free\_memory routine. There are 2 related routines: fits\_hdr2str simply concatenates all the existing keywords in the header; fits\_convert\_hdr2str is similar, except that if the CHDU is a tile compressed image (stored in a binary table) then it will first convert that header back to that of the corresponding normal FITS image before concatenating the keywords. Selected keywords may be excluded from the returned character string. If the second parameter (nocomments) is TRUE (nonzero) then any COMMENT, HISTORY, or blank keywords in the header will not be copied to the output string. The 'exclist' parameter may be used to supply a list of keywords that are to be excluded from the output character string. Wild card characters (*, ?, and \#) may be used in the excluded keyword names. If no additional keywords are to be excluded, then set nexc = 0 and specify NULL for the the **exclist parameter. \label{ffhdr2str} \end{description} \begin{verbatim} int fits_hdr2str / ffhdr2str (fitsfile *fptr, int nocomments, char **exclist, int nexc, > char **header, int *nkeys, int *status) int fits_convert_hdr2str / ffcnvthdr2str (fitsfile *fptr, int nocomments, char **exclist, int nexc, > char **header, int *nkeys, int *status) int fits_free_memory / fffree (char *header, > int *status); \end{verbatim} \subsection{Keyword Writing Routines} \begin{description} \item[1 ] Write a keyword of the appropriate data type into the CHU. The first routine simply appends a new keyword whereas the second routine will update the value and comment fields of the keyword if it already exists, otherwise it appends a new keyword. Note that the address to the value, and not the value itself, must be entered. The datatype parameter specifies the data type of the keyword value with one of the following values: TSTRING, TLOGICAL (== int), TBYTE, TSHORT, TUSHORT, TINT, TUINT, TLONG, TLONGLONG, TULONG, TFLOAT, TDOUBLE. Within the context of this routine, TSTRING corresponds to a 'char*' data type, i.e., a pointer to a character array. A null pointer may be entered for the comment parameter in which case the keyword comment field will be unmodified or left blank. \label{ffpky} \label{ffuky} \end{description} \begin{verbatim} int fits_write_key / ffpky (fitsfile *fptr, int datatype, char *keyname, DTYPE *value, char *comment, > int *status) int fits_update_key / ffuky (fitsfile *fptr, int datatype, char *keyname, DTYPE *value, char *comment, > int *status) \end{verbatim} \begin{description} \item[2 ] Write a keyword with a null or undefined value (i.e., the value field in the keyword is left blank). The first routine simply appends a new keyword whereas the second routine will update the value and comment fields of the keyword if it already exists, otherwise it appends a new keyword. A null pointer may be entered for the comment parameter in which case the keyword comment field will be unmodified or left blank. \label{ffpkyu} \label{ffukyu} \end{description} \begin{verbatim} int fits_write_key_null / ffpkyu (fitsfile *fptr, char *keyname, char *comment, > int *status) int fits_update_key_null / ffukyu (fitsfile *fptr, char *keyname, char *comment, > int *status) \end{verbatim} \begin{description} \item[3 ] Write (append) a COMMENT or HISTORY keyword to the CHU. The comment or history string will be continued over multiple keywords if it is longer than 70 characters. \label{ffpcom} \label{ffphis} \end{description} \begin{verbatim} int fits_write_comment / ffpcom (fitsfile *fptr, char *comment, > int *status) int fits_write_history / ffphis (fitsfile *fptr, char *history, > int *status) \end{verbatim} \begin{description} \item[4 ] Write the DATE keyword to the CHU. The keyword value will contain the current system date as a character string in 'yyyy-mm-ddThh:mm:ss' format. If a DATE keyword already exists in the header, then this routine will simply update the keyword value with the current date. \label{ffpdat} \end{description} \begin{verbatim} int fits_write_date / ffpdat (fitsfile *fptr, > int *status) \end{verbatim} \begin{description} \item[5 ]Write a user specified keyword record into the CHU. This is a low--level routine which can be used to write any arbitrary record into the header. The record must conform to the all the FITS format requirements. \label{ffprec} \end{description} \begin{verbatim} int fits_write_record / ffprec (fitsfile *fptr, char *card, > int *status) \end{verbatim} \begin{description} \item[6 ]Update an 80-character record in the CHU. If a keyword with the input name already exists, then it is overwritten by the value of card. This could modify the keyword name as well as the value and comment fields. If the keyword doesn't already exist then a new keyword card is appended to the header. \label{ffucrd} \end{description} \begin{verbatim} int fits_update_card / ffucrd (fitsfile *fptr, char *keyname, char *card, > int *status) \end{verbatim} \begin{description} \item[7 ] Modify (overwrite) the comment field of an existing keyword. \label{ffmcom} \end{description} \begin{verbatim} int fits_modify_comment / ffmcom (fitsfile *fptr, char *keyname, char *comment, > int *status) \end{verbatim} \begin{description} \item[8 ] Write the physical units string into an existing keyword. This routine uses a local convention, shown in the following example, in which the keyword units are enclosed in square brackets in the beginning of the keyword comment field. \label{ffpunt} \end{description} \begin{verbatim} VELOCITY= 12.3 / [km/s] orbital speed int fits_write_key_unit / ffpunt (fitsfile *fptr, char *keyname, char *unit, > int *status) \end{verbatim} \begin{description} \item[9 ] Rename an existing keyword, preserving the current value and comment fields. \label{ffmnam} \end{description} \begin{verbatim} int fits_modify_name / ffmnam (fitsfile *fptr, char *oldname, char *newname, > int *status) \end{verbatim} \begin{description} \item[10] Delete a keyword record. The space occupied by the keyword is reclaimed by moving all the following header records up one row in the header. The first routine deletes a keyword at a specified position in the header (the first keyword is at position 1), whereas the second routine deletes a specifically named keyword. Wild card characters may be used when specifying the name of the keyword to be deleted. The third routine deletes the (next) keyword that contains the literal character string specified by the 'string' argument.\label{ffdrec} \label{ffdkey} \end{description} \begin{verbatim} int fits_delete_record / ffdrec (fitsfile *fptr, int keynum, > int *status) int fits_delete_key / ffdkey (fitsfile *fptr, char *keyname, > int *status) int fits_delete_str / ffdstr (fitsfile *fptr, char *string, > int *status) \end{verbatim} \section{Primary Array or IMAGE Extension I/O Routines} These routines read or write data values in the primary data array (i.e., the first HDU in a FITS file) or an IMAGE extension. There are also routines to get information about the data type and size of the image. Users should also read the following chapter on the CFITSIO iterator function which provides a more `object oriented' method of reading and writing images. The iterator function is a little more complicated to use, but the advantages are that it usually takes less code to perform the same operation, and the resulting program often runs faster because the FITS files are read and written using the most efficient block size. C programmers should note that the ordering of arrays in FITS files, and hence in all the CFITSIO calls, is more similar to the dimensionality of arrays in Fortran rather than C. For instance if a FITS image has NAXIS1 = 100 and NAXIS2 = 50, then a 2-D array just large enough to hold the image should be declared as array[50][100] and not as array[100][50]. The `datatype' parameter specifies the data type of the `nulval' and `array' pointers and can have one of the following values: TBYTE, TSBYTE, TSHORT, TUSHORT, TINT, TUINT, TLONG, TLONGLONG, TULONG, TFLOAT, TDOUBLE. Automatic data type conversion is performed if the data type of the FITS array (as defined by the BITPIX keyword) differs from that specified by 'datatype'. The data values are also automatically scaled by the BSCALE and BZERO keyword values as they are being read or written in the FITS array. \begin{description} \item[1 ] Get the data type or equivalent data type of the image. The first routine returns the physical data type of the FITS image, as given by the BITPIX keyword, with allowed values of BYTE\_IMG (8), SHORT\_IMG (16), LONG\_IMG (32), LONGLONG\_IMG (64), FLOAT\_IMG (-32), and DOUBLE\_IMG (-64). The second routine is similar, except that if the image pixel values are scaled, with non-default values for the BZERO and BSCALE keywords, then the routine will return the 'equivalent' data type that is needed to store the scaled values. For example, if BITPIX = 16 and BSCALE = 0.1 then the equivalent data type is FLOAT\_IMG. Similarly if BITPIX = 16, BSCALE = 1, and BZERO = 32768, then the the pixel values span the range of an unsigned short integer and the returned data type will be USHORT\_IMG. \label{ffgidt} \end{description} \begin{verbatim} int fits_get_img_type / ffgidt (fitsfile *fptr, > int *bitpix, int *status) int fits_get_img_equivtype / ffgiet (fitsfile *fptr, > int *bitpix, int *status) \end{verbatim} \begin{description} \item[2 ] Get the number of dimensions, and/or the size of each dimension in the image . The number of axes in the image is given by naxis, and the size of each dimension is given by the naxes array (a maximum of maxdim dimensions will be returned). \label{ffgidm} \label{ffgisz} \label{ffgipr} \end{description} \begin{verbatim} int fits_get_img_dim / ffgidm (fitsfile *fptr, > int *naxis, int *status) int fits_get_img_size / ffgisz (fitsfile *fptr, int maxdim, > long *naxes, int *status) int fits_get_img_sizell / ffgiszll (fitsfile *fptr, int maxdim, > LONGLONG *naxes, int *status) int fits_get_img_param / ffgipr (fitsfile *fptr, int maxdim, > int *bitpix, int *naxis, long *naxes, int *status) int fits_get_img_paramll / ffgiprll (fitsfile *fptr, int maxdim, > int *bitpix, int *naxis, LONGLONG *naxes, int *status) \end{verbatim} \begin{description} \item[3 ]Create a new primary array or IMAGE extension with a specified data type and size. If the FITS file is currently empty then a primary array is created, otherwise a new IMAGE extension is appended to the file. \label{ffcrim} \end{description} \begin{verbatim} int fits_create_img / ffcrim ( fitsfile *fptr, int bitpix, int naxis, long *naxes, > int *status) int fits_create_imgll / ffcrimll ( fitsfile *fptr, int bitpix, int naxis, LONGLONG *naxes, > int *status) \end{verbatim} \begin{description} \item[4 ] Copy an n-dimensional image in a particular row and column of a binary table (in a vector column) to or from a primary array or image extension. The 'cell2image' routine will append a new image extension (or primary array) to the output file. Any WCS keywords associated with the input column image will be translated into the appropriate form for an image extension. Any other keywords in the table header that are not specifically related to defining the binary table structure or to other columns in the table will also be copied to the header of the output image. The 'image2cell' routine will copy the input image into the specified row and column of the current binary table in the output file. The binary table HDU must exist before calling this routine, but it may be empty, with no rows or columns of data. The specified column (and row) will be created if it does not already exist. The 'copykeyflag' parameter controls which keywords are copied from the input image to the header of the output table: 0 = no keywords will be copied, 1 = all keywords will be copied (except those keywords that would be invalid in the table header), and 2 = copy only the WCS keywords. \label{copycell} \end{description} \begin{verbatim} int fits_copy_cell2image (fitsfile *infptr, fitsfile *outfptr, char *colname, long rownum, > int *status) int fits_copy_image2cell (fitsfile *infptr, fitsfile *outfptr, char *colname, long rownum, int copykeyflag > int *status) \end{verbatim} \begin{description} \item[5 ] Write a rectangular subimage (or the whole image) to the FITS data array. The fpixel and lpixel arrays give the coordinates of the first (lower left corner) and last (upper right corner) pixels in FITS image to be written to. \label{ffpss} \end{description} \begin{verbatim} int fits_write_subset / ffpss (fitsfile *fptr, int datatype, long *fpixel, long *lpixel, DTYPE *array, > int *status) \end{verbatim} \begin{description} \item[6 ] Write pixels into the FITS data array. 'fpixel' is an array of length NAXIS which gives the coordinate of the starting pixel to be written to, such that fpixel[0] is in the range 1 to NAXIS1, fpixel[1] is in the range 1 to NAXIS2, etc. The first pair of routines simply writes the array of pixels to the FITS file (doing data type conversion if necessary) whereas the second routines will substitute the appropriate FITS null value for any elements which are equal to the input value of nulval (note that this parameter gives the address of the null value, not the null value itself). For integer FITS arrays, the FITS null value is defined by the BLANK keyword (an error is returned if the BLANK keyword doesn't exist). For floating point FITS arrays the special IEEE NaN (Not-a-Number) value will be written into the FITS file. If a null pointer is entered for nulval, then the null value is ignored and this routine behaves the same as fits\_write\_pix. \label{ffppx} \label{ffppxn} \end{description} \begin{verbatim} int fits_write_pix / ffppx (fitsfile *fptr, int datatype, long *fpixel, LONGLONG nelements, DTYPE *array, int *status); int fits_write_pixll / ffppxll (fitsfile *fptr, int datatype, LONGLONG *fpixel, LONGLONG nelements, DTYPE *array, int *status); int fits_write_pixnull / ffppxn (fitsfile *fptr, int datatype, long *fpixel, LONGLONG nelements, DTYPE *array, DTYPE *nulval, > int *status); int fits_write_pixnullll / ffppxnll (fitsfile *fptr, int datatype, LONGLONG *fpixel, LONGLONG nelements, DTYPE *array, DTYPE *nulval, > int *status); \end{verbatim} \begin{description} \item[7 ] Set FITS data array elements equal to the appropriate null pixel value. For integer FITS arrays, the FITS null value is defined by the BLANK keyword (an error is returned if the BLANK keyword doesn't exist). For floating point FITS arrays the special IEEE NaN (Not-a-Number) value will be written into the FITS file. Note that 'firstelem' is a scalar giving the offset to the first pixel to be written in the equivalent 1-dimensional array of image pixels. \label{ffpprn} \end{description} \begin{verbatim} int fits_write_null_img / ffpprn (fitsfile *fptr, LONGLONG firstelem, LONGLONG nelements, > int *status) \end{verbatim} \begin{description} \item[8 ] Read a rectangular subimage (or the whole image) from the FITS data array. The fpixel and lpixel arrays give the coordinates of the first (lower left corner) and last (upper right corner) pixels to be read from the FITS image. Undefined FITS array elements will be returned with a value = *nullval, (note that this parameter gives the address of the null value, not the null value itself) unless nulval = 0 or *nulval = 0, in which case no checks for undefined pixels will be performed. \label{ffgsv} \end{description} \begin{verbatim} int fits_read_subset / ffgsv (fitsfile *fptr, int datatype, long *fpixel, long *lpixel, long *inc, DTYPE *nulval, > DTYPE *array, int *anynul, int *status) \end{verbatim} \begin{description} \item[9 ] Read pixels from the FITS data array. 'fpixel' is the starting pixel location and is an array of length NAXIS such that fpixel[0] is in the range 1 to NAXIS1, fpixel[1] is in the range 1 to NAXIS2, etc. The nelements parameter specifies the number of pixels to read. If fpixel is set to the first pixel, and nelements is set equal to the NAXIS1 value, then this routine would read the first row of the image. Alternatively, if nelements is set equal to NAXIS1 * NAXIS2 then it would read an entire 2D image, or the first plane of a 3-D datacube. The first 2 routines will return any undefined pixels in the FITS array equal to the value of *nullval (note that this parameter gives the address of the null value, not the null value itself) unless nulval = 0 or *nulval = 0, in which case no checks for undefined pixels will be performed. The second 2 routines are similar except that any undefined pixels will have the corresponding nullarray element set equal to TRUE (= 1). \label{ffgpxv} \label{ffgpxf} \end{description} \begin{verbatim} int fits_read_pix / ffgpxv (fitsfile *fptr, int datatype, long *fpixel, LONGLONG nelements, DTYPE *nulval, > DTYPE *array, int *anynul, int *status) int fits_read_pixll / ffgpxvll (fitsfile *fptr, int datatype, LONGLONG *fpixel, LONGLONG nelements, DTYPE *nulval, > DTYPE *array, int *anynul, int *status) int fits_read_pixnull / ffgpxf (fitsfile *fptr, int datatype, long *fpixel, LONGLONG nelements, > DTYPE *array, char *nullarray, int *anynul, int *status) int fits_read_pixnullll / ffgpxfll (fitsfile *fptr, int datatype, LONGLONG *fpixel, LONGLONG nelements, > DTYPE *array, char *nullarray, int *anynul, int *status) \end{verbatim} \begin{description} \item[10] Copy a rectangular section of an image and write it to a new FITS primary image or image extension. The new image HDU is appended to the end of the output file; all the keywords in the input image will be copied to the output image. The common WCS keywords will be updated if necessary to correspond to the coordinates of the section. The format of the section expression is same as specifying an image section using the extended file name syntax (see "Image Section" in Chapter 10). (Examples: "1:100,1:200", "1:100:2, 1:*:2", "*, -*"). \label{ffcpimg} \end{description} \begin{verbatim} int fits_copy_image_section / ffcpimg (fitsfile *infptr, fitsfile *outfptr, char *section, int *status) \end{verbatim} \section{Image Compression} CFITSIO transparently supports the 2 methods of image compression described below. 1) The entire FITS file may be externally compressed with the gzip or Unix compress utility programs, producing a *.gz or *.Z file, respectively. When reading compressed files of this type, CFITSIO first uncompresses the entire file into memory before performing the requested read operations. Output files can be directly written in the gzip compressed format if the user-specified filename ends with `.gz'. In this case, CFITSIO initially writes the uncompressed file in memory and then compresses it and writes it to disk when the FITS file is closed, thus saving user disk space. Read and write access to these compressed FITS files is generally quite fast since all the I/O is performed in memory; the main limitation with this technique is that there must be enough available memory (or swap space) to hold the entire uncompressed FITS file. 2) CFITSIO also supports the FITS tiled image compression convention in which the image is subdivided into a grid of rectangular tiles, and each tile of pixels is individually compressed. The details of this FITS compression convention are described at the FITS Support Office web site at http://fits.gsfc.nasa.gov/fits\_registry.html, and in the fpackguide pdf file that is included with the CFITSIO source file distributions Basically, the compressed image tiles are stored in rows of a variable length array column in a FITS binary table, however CFITSIO recognizes that this binary table extension contains an image and treats it as if it were an IMAGE extension. This tile-compressed format is especially well suited for compressing very large images because a) the FITS header keywords remain uncompressed for rapid read access, and because b) it is possible to extract and uncompress sections of the image without having to uncompress the entire image. This format is also much more effective in compressing floating point images than simply compressing the image using gzip or compress because it approximates the floating point values with scaled integers which can then be compressed more efficiently. Currently CFITSIO supports 3 general purpose compression algorithms plus one other special-purpose compression technique that is designed for data masks with positive integer pixel values. The 3 general purpose algorithms are GZIP, Rice, and HCOMPRESS, and the special purpose algorithm is the IRAF pixel list compression technique (PLIO). There are 2 variants of the GZIP algorithm: GZIP\_1 compresses the array of image pixel value normally with the GZIP algorithm, while GZIP\_2 first shuffles the bytes in all the pixel values so that the most-significant byte of every pixel appears first, followed by the less significant bytes in sequence. GZIP\_2 may be more effective in cases where the most significant byte in most of the image pixel values contains the same bit pattern. In principle, any number of other compression algorithms could also be supported by the FITS tiled image compression convention. The FITS image can be subdivided into any desired rectangular grid of compression tiles. With the GZIP, Rice, and PLIO algorithms, the default is to take each row of the image as a tile. The HCOMPRESS algorithm is inherently 2-dimensional in nature, so the default in this case is to take 16 rows of the image per tile. In most cases it makes little difference what tiling pattern is used, so the default tiles are usually adequate. In the case of very small images, it could be more efficient to compress the whole image as a single tile. Note that the image dimensions are not required to be an integer multiple of the tile dimensions; if not, then the tiles at the edges of the image will be smaller than the other tiles. The 4 supported image compression algorithms are all 'loss-less' when applied to integer FITS images; the pixel values are preserved exactly with no loss of information during the compression and uncompression process. In addition, the HCOMPRESS algorithm supports a 'lossy' compression mode that will produce larger amount of image compression. This is achieved by specifying a non-zero value for the HCOMPRESS ``scale'' parameter. Since the amount of compression that is achieved depends directly on the RMS noise in the image, it is usually more convention to specify the HCOMPRESS scale factor relative to the RMS noise. Setting s = 2.5 means use a scale factor that is 2.5 times the calculated RMS noise in the image tile. In some cases it may be desirable to specify the exact scaling to be used, instead of specifying it relative to the calculated noise value. This may be done by specifying the negative of desired scale value (typically in the range -2 to -100). Very high compression factors (of 100 or more) can be achieved by using large HCOMPRESS scale values, however, this can produce undesirable ``blocky'' artifacts in the compressed image. A variation of the HCOMPRESS algorithm (called HSCOMPRESS) can be used in this case to apply a small amount of smoothing of the image when it is uncompressed to help cover up these artifacts. This smoothing is purely cosmetic and does not cause any significant change to the image pixel values. Floating point FITS images (which have BITPIX = -32 or -64) usually contain too much ``noise'' in the least significant bits of the mantissa of the pixel values to be effectively compressed with any lossless algorithm. Consequently, floating point images are first quantized into scaled integer pixel values (and thus throwing away much of the noise) before being compressed with the specified algorithm (either GZIP, Rice, or HCOMPRESS). This technique produces much higher compression factors than simply using the GZIP utility to externally compress the whole FITS file, but it also means that the original floating value pixel values are not exactly preserved. When done properly, this integer scaling technique will only discard the insignificant noise while still preserving all the real information in the image. The amount of precision that is retained in the pixel values is controlled by the "quantization level" parameter, q. Larger values of q will result in compressed images whose pixels more closely match the floating point pixel values, but at the same time the amount of compression that is achieved will be reduced. Users should experiment with different values for this parameter to determine the optimal value that preserves all the useful information in the image, without needlessly preserving all the ``noise'' which will hurt the compression efficiency. The default value for the quantization scale factor is 4.0, which means that scaled integer pixel values will be quantized such that the difference between adjacent integer values will be 1/4th of the noise level in the image background. CFITSIO uses an optimized algorithm to accurately estimate the noise in the image. As an example, if the RMS noise in the background pixels of an image = 32.0, then the spacing between adjacent scaled integer pixel values will equal 8.0 by default. Note that the RMS noise is independently calculated for each tile of the image, so the resulting integer scaling factor may fluctuate slightly for each tile. In some cases it may be desirable to specify the exact quantization level to be used, instead of specifying it relative to the calculated noise value. This may be done by specifying the negative of desired quantization level for the value of q. In the previous example, one could specify q = -8.0 so that the quantized integer levels differ by exactly 8.0. Larger negative values for q means that the levels are more coarsely spaced, and will produce higher compression factors. When floating point images are being quantized, one must also specify what quantization method is to be used. The default algorithm is called ``SUBTRACTIVE\_DITHER\_1''. A second variation called ``SUBTRACTIVE\_DITHER\_2'' is also available, which does the same thing except that any pixels with a value of 0.0 are not dithered and instead the zero values are exactly preserved in the compressed image. One may also turn off dithering completely with the ``NO\_DITHER'' option, but this is not recommended because it can cause larger systematic errors in measurements of the position or brightness of objects in the compressed image. There are 3 methods for specifying all the parameters needed to write a FITS image in the tile compressed format. The parameters may either be specified at run time as part of the file name of the output compressed FITS file, or the writing program may call a set of helper CFITSIO subroutines that are provided for specifying the parameter values, or ``compression directive'' keywords may be added to the header of each image HDU to specify the compression parameters. These 3 methods are described below. 1) At run time, when specifying the name of the output FITS file to be created, the user can indicate that images should be written in tile-compressed format by enclosing the compression parameters in square brackets following the root disk file name in the following format: \begin{verbatim} [compress NAME T1,T2; q[z] QLEVEL, s HSCALE] \end{verbatim} where \begin{verbatim} NAME = algorithm name: GZIP, Rice, HCOMPRESS, HSCOMPRSS or PLIO may be abbreviated to the first letter (or HS for HSCOMPRESS) T1,T2 = tile dimension (e.g. 100,100 for square tiles 100 pixels wide) QLEVEL = quantization level for floating point FITS images HSCALE = HCOMPRESS scale factor; default = 0 which is lossless. \end{verbatim} Here are a few examples of this extended syntax: \begin{verbatim} myfile.fit[compress] - use the default compression algorithm (Rice) and the default tile size (row by row) myfile.fit[compress G] - use the specified compression algorithm; myfile.fit[compress R] only the first letter of the algorithm myfile.fit[compress P] should be given. myfile.fit[compress H] myfile.fit[compress R 100,100] - use Rice and 100 x 100 pixel tiles myfile.fit[compress R; q 10.0] - quantization level = (RMS-noise) / 10. myfile.fit[compress R; qz 10.0] - quantization level = (RMS-noise) / 10. also use the SUBTRACTIVE_DITHER_2 quantization method myfile.fit[compress HS; s 2.0] - HSCOMPRESS (with smoothing) and scale = 2.0 * RMS-noise \end{verbatim} 2) Before calling the CFITSIO routine to write the image header keywords (e.g., fits\_create\_image) the programmer can call the routines described below to specify the compression algorithm and the tiling pattern that is to be used. There are routines for specifying the various compression parameters and similar routines to return the current values of the parameters: \label{ffsetcomp} \label{ffgetcomp} \begin{verbatim} int fits_set_compression_type(fitsfile *fptr, int comptype, int *status) int fits_set_tile_dim(fitsfile *fptr, int ndim, long *tilesize, int *status) int fits_set_quantize_level(fitsfile *fptr, float qlevel, int *status) int fits_set_quantize_method(fitsfile *fptr, int method, int *status) int fits_set_quantize_dither(fitsfile *fptr, int dither, int *status) int fits_set_dither_seed(fitsfile *fptr, int seed, int *status) int fits_set_dither_offset(fitsfile *fptr, int offset, int *status) int fits_set_lossy_int(fitsfile *fptr, int lossy_int, int *status) this forces integer image to be converted to floats, then quantized int fits_set_huge_hdu(fitsfile *fptr, int huge, int *status); this should be called when the compressed image size is more than 4 GB. int fits_set_hcomp_scale(fitsfile *fptr, float scale, int *status) int fits_set_hcomp_smooth(fitsfile *fptr, int smooth, int *status) Set smooth = 1 to apply smoothing when uncompressing the image int fits_get_compression_type(fitsfile *fptr, int *comptype, int *status) int fits_get_tile_dim(fitsfile *fptr, int ndim, long *tilesize, int *status) int fits_get_quantize_level(fitsfile *fptr, float *level, int *status) int fits_get_hcomp_scale(fitsfile *fptr, float *scale, int *status) \end{verbatim} Several symbolic constants are defined for use as the value of the `comptype' parameter: GZIP\_1, GZIP\_2, RICE\_1, HCOMPRESS\_1 or PLIO\_1. Entering NULL for comptype will turn off the tile-compression and cause normal FITS images to be written. There are also defined symbolic constants for the quantization method: ``SUBTRACTIVE\_DITHER\_1'', ``SUBTRACTIVE\_DITHER\_2'', and ``NO\_DITHER''. 3) CFITSIO will uses the values of the following keywords, if they are present in the header of the image HDU, to determine how to compress that HDU. These keywords override any compression parameters that were specified with the previous 2 methods. \begin{verbatim} FZALGOR - 'RICE_1' , 'GZIP_1', 'GZIP_2', 'HCOMPRESS_1', 'PLIO_1', 'NONE' FZTILE - 'ROW', 'WHOLE', or '(n,m)' FZQVALUE - float value (default = 4.0) FZQMETHD - 'SUBTRACTIVE_DITHER_1', 'SUBTRACTIVE_DITHER_2', 'NO_DITHER' FZDTHRSD - 'CLOCK', 'CHECKSUM', 1 - 10000 FZINT2F - T, or F: Convert integers to floats, then quantize? FZHSCALE - float value (default = 0). Hcompress scale value. \end{verbatim} No special action is required by software when read tile-compressed images because all the CFITSIO routines that read normal uncompressed FITS images also transparently read images in the tile-compressed format; CFITSIO essentially treats the binary table that contains the compressed tiles as if it were an IMAGE extension. The following 2 routines are available for compressing or or decompressing an image: \begin{verbatim} int fits_img_compress(fitsfile *infptr, fitsfile *outfptr, int *status); int fits_img_decompress (fitsfile *infptr, fitsfile *outfptr, int *status); \end{verbatim} Before calling the compression routine, the compression parameters must first be defined in one of the 3 way described in the previous paragraphs. There is also a routine to determine if the current HDU contains a tile compressed image (it returns 1 or 0): \begin{verbatim} int fits_is_compressed_image(fitsfile *fptr, int *status); \end{verbatim} A small example program called 'imcopy' is included with CFITSIO that can be used to compress (or uncompress) any FITS image. This program can be used to experiment with the various compression options on existing FITS images as shown in these examples: \begin{verbatim} 1) imcopy infile.fit 'outfile.fit[compress]' This will use the default compression algorithm (Rice) and the default tile size (row by row) 2) imcopy infile.fit 'outfile.fit[compress GZIP]' This will use the GZIP compression algorithm and the default tile size (row by row). The allowed compression algorithms are Rice, GZIP, and PLIO. Only the first letter of the algorithm name needs to be specified. 3) imcopy infile.fit 'outfile.fit[compress G 100,100]' This will use the GZIP compression algorithm and 100 X 100 pixel tiles. 4) imcopy infile.fit 'outfile.fit[compress R 100,100; qz 10.0]' This will use the Rice compression algorithm, 100 X 100 pixel tiles, and quantization level = RMSnoise / 10.0 (assuming the input image has a floating point data type). By specifying qz instead of q, this means use the subtractive dither2 quantization method. 5) imcopy infile.fit outfile.fit If the input file is in tile-compressed format, then it will be uncompressed to the output file. Otherwise, it simply copies the input image to the output image. 6) imcopy 'infile.fit[1001:1500,2001:2500]' outfile.fit This extracts a 500 X 500 pixel section of the much larger input image (which may be in tile-compressed format). The output is a normal uncompressed FITS image. 7) imcopy 'infile.fit[1001:1500,2001:2500]' outfile.fit.gz Same as above, except the output file is externally compressed using the gzip algorithm. \end{verbatim} \section{ASCII and Binary Table Routines} These routines perform read and write operations on columns of data in FITS ASCII or Binary tables. Note that in the following discussions, the first row and column in a table is at position 1 not 0. Users should also read the following chapter on the CFITSIO iterator function which provides a more `object oriented' method of reading and writing table columns. The iterator function is a little more complicated to use, but the advantages are that it usually takes less code to perform the same operation, and the resulting program often runs faster because the FITS files are read and written using the most efficient block size. \subsection{Create New Table} \begin{description} \item[1 ]Create a new ASCII or bintable table extension. If the FITS file is currently empty then a dummy primary array will be created before appending the table extension to it. The tbltype parameter defines the type of table and can have values of ASCII\_TBL or BINARY\_TBL. The naxis2 parameter gives the initial number of rows to be created in the table, and should normally be set = 0. CFITSIO will automatically increase the size of the table as additional rows are written. A non-zero number of rows may be specified to reserve space for that many rows, even if a fewer number of rows will be written. The tunit and extname parameters are optional and a null pointer may be given if they are not defined. The FITS Standard recommends that only letters, digits, and the underscore character be used in column names (the ttype parameter) with no embedded spaces. Trailing blank characters are not significant. \label{ffcrtb} \end{description} \begin{verbatim} int fits_create_tbl / ffcrtb (fitsfile *fptr, int tbltype, LONGLONG naxis2, int tfields, char *ttype[], char *tform[], char *tunit[], char *extname, int *status) \end{verbatim} \subsection{Column Information Routines} \begin{description} \item[1 ] Get the number of rows or columns in the current FITS table. The number of rows is given by the NAXIS2 keyword and the number of columns is given by the TFIELDS keyword in the header of the table. \label{ffgnrw} \end{description} \begin{verbatim} int fits_get_num_rows / ffgnrw (fitsfile *fptr, > long *nrows, int *status); int fits_get_num_rowsll / ffgnrwll (fitsfile *fptr, > LONGLONG *nrows, int *status); int fits_get_num_cols / ffgncl (fitsfile *fptr, > int *ncols, int *status); \end{verbatim} \begin{description} \item[2 ] Get the table column number (and name) of the column whose name matches an input template name. If casesen = CASESEN then the column name match will be case-sensitive, whereas if casesen = CASEINSEN then the case will be ignored. As a general rule, the column names should be treated as case INsensitive. The input column name template may be either the exact name of the column to be searched for, or it may contain wild card characters (*, ?, or \#), or it may contain the integer number of the desired column (with the first column = 1). The `*' wild card character matches any sequence of characters (including zero characters) and the `?' character matches any single character. The \# wildcard will match any consecutive string of decimal digits (0-9). If more than one column name in the table matches the template string, then the first match is returned and the status value will be set to COL\_NOT\_UNIQUE as a warning that a unique match was not found. To find the other cases that match the template, call the routine again leaving the input status value equal to COL\_NOT\_UNIQUE and the next matching name will then be returned. Repeat this process until a status = COL\_NOT\_FOUND is returned. The FITS Standard recommends that only letters, digits, and the underscore character be used in column names (with no embedded spaces). Trailing blank characters are not significant. \label{ffgcno} \label{ffgcnn} \end{description} \begin{verbatim} int fits_get_colnum / ffgcno (fitsfile *fptr, int casesen, char *templt, > int *colnum, int *status) int fits_get_colname / ffgcnn (fitsfile *fptr, int casesen, char *templt, > char *colname, int *colnum, int *status) \end{verbatim} \begin{description} \item[3 ] Return the data type, vector repeat value, and the width in bytes of a column in an ASCII or binary table. Allowed values for the data type in ASCII tables are: TSTRING, TSHORT, TLONG, TFLOAT, and TDOUBLE. Binary tables also support these types: TLOGICAL, TBIT, TBYTE, TCOMPLEX and TDBLCOMPLEX. The negative of the data type code value is returned if it is a variable length array column. Note that in the case of a 'J' 32-bit integer binary table column, this routine will return data type = TINT32BIT (which in fact is equivalent to TLONG). With most current C compilers, a value in a 'J' column has the same size as an 'int' variable, and may not be equivalent to a 'long' variable, which is 64-bits long on an increasing number of compilers. The 'repeat' parameter returns the vector repeat count on the binary table TFORMn keyword value. (ASCII table columns always have repeat = 1). The 'width' parameter returns the width in bytes of a single column element (e.g., a '10D' binary table column will have width = 8, an ASCII table 'F12.2' column will have width = 12, and a binary table'60A' character string column will have width = 60); Note that CFITSIO supports the local convention for specifying arrays of fixed length strings within a binary table character column using the syntax TFORM = 'rAw' where 'r' is the total number of characters (= the width of the column) and 'w' is the width of a unit string within the column. Thus if the column has TFORM = '60A12' then this means that each row of the table contains 5 12-character substrings within the 60-character field, and thus in this case this routine will return typecode = TSTRING, repeat = 60, and width = 12. (The TDIMn keyword may also be used to specify the unit string length; The pair of keywords TFORMn = '60A' and TDIMn = '(12,5)' would have the same effect as TFORMn = '60A12'). The number of substrings in any binary table character string field can be calculated by (repeat/width). A null pointer may be given for any of the output parameters that are not needed. The second routine, fit\_get\_eqcoltype is similar except that in the case of scaled integer columns it returns the 'equivalent' data type that is needed to store the scaled values, and not necessarily the physical data type of the unscaled values as stored in the FITS table. For example if a '1I' column in a binary table has TSCALn = 1 and TZEROn = 32768, then this column effectively contains unsigned short integer values, and thus the returned value of typecode will be TUSHORT, not TSHORT. Similarly, if a column has TTYPEn = '1I' and TSCALn = 0.12, then the returned typecode will be TFLOAT. \label{ffgtcl} \end{description} \begin{verbatim} int fits_get_coltype / ffgtcl (fitsfile *fptr, int colnum, > int *typecode, long *repeat, long *width, int *status) int fits_get_coltypell / ffgtclll (fitsfile *fptr, int colnum, > int *typecode, LONGLONG *repeat, LONGLONG *width, int *status) int fits_get_eqcoltype / ffeqty (fitsfile *fptr, int colnum, > int *typecode, long *repeat, long *width, int *status) int fits_get_eqcoltypell / ffeqtyll (fitsfile *fptr, int colnum, > int *typecode, LONGLONG *repeat, LONGLONG *width, int *status) \end{verbatim} \begin{description} \item[4 ] Return the display width of a column. This is the length of the string that will be returned by the fits\_read\_col routine when reading the column as a formatted string. The display width is determined by the TDISPn keyword, if present, otherwise by the data type of the column. \label{ffgcdw} \end{description} \begin{verbatim} int fits_get_col_display_width / ffgcdw (fitsfile *fptr, int colnum, > int *dispwidth, int *status) \end{verbatim} \begin{description} \item[5 ] Return the number of and size of the dimensions of a table column in a binary table. Normally this information is given by the TDIMn keyword, but if this keyword is not present then this routine returns naxis = 1 and naxes[0] equal to the repeat count in the TFORM keyword. \label{ffgtdm} \end{description} \begin{verbatim} int fits_read_tdim / ffgtdm (fitsfile *fptr, int colnum, int maxdim, > int *naxis, long *naxes, int *status) int fits_read_tdimll / ffgtdmll (fitsfile *fptr, int colnum, int maxdim, > int *naxis, LONGLONG *naxes, int *status) \end{verbatim} \begin{description} \item[6 ] Decode the input TDIMn keyword string (e.g. '(100,200)') and return the number of and size of the dimensions of a binary table column. If the input tdimstr character string is null, then this routine returns naxis = 1 and naxes[0] equal to the repeat count in the TFORM keyword. This routine is called by fits\_read\_tdim. \label{ffdtdm} \end{description} \begin{verbatim} int fits_decode_tdim / ffdtdm (fitsfile *fptr, char *tdimstr, int colnum, int maxdim, > int *naxis, long *naxes, int *status) int fits_decode_tdimll / ffdtdmll (fitsfile *fptr, char *tdimstr, int colnum, int maxdim, > int *naxis, LONGLONG *naxes, int *status) \end{verbatim} \begin{description} \item[7 ] Write a TDIMn keyword whose value has the form '(l,m,n...)' where l, m, n... are the dimensions of a multidimensional array column in a binary table. \label{ffptdm} \end{description} \begin{verbatim} int fits_write_tdim / ffptdm (fitsfile *fptr, int colnum, int naxis, long *naxes, > int *status) int fits_write_tdimll / ffptdmll (fitsfile *fptr, int colnum, int naxis, LONGLONG *naxes, > int *status) \end{verbatim} \subsection{Routines to Edit Rows or Columns} \begin{description} \item[1 ] Insert or delete rows in an ASCII or binary table. When inserting rows all the rows following row FROW are shifted down by NROWS rows; if FROW = 0 then the blank rows are inserted at the beginning of the table. Note that it is *not* necessary to insert rows in a table before writing data to those rows (indeed, it would be inefficient to do so). Instead one may simply write data to any row of the table, whether that row of data already exists or not. The first delete routine deletes NROWS consecutive rows starting with row FIRSTROW. The second delete routine takes an input string that lists the rows or row ranges (e.g., '5-10,12,20-30'), whereas the third delete routine takes an input integer array that specifies each individual row to be deleted. In both latter cases, the input list of rows to delete must be sorted in ascending order. These routines update the NAXIS2 keyword to reflect the new number of rows in the table. \label{ffirow} \label{ffdrow} \label{ffdrws} \label{ffdrrg} \end{description} \begin{verbatim} int fits_insert_rows / ffirow (fitsfile *fptr, LONGLONG firstrow, LONGLONG nrows, > int *status) int fits_delete_rows / ffdrow (fitsfile *fptr, LONGLONG firstrow, LONGLONG nrows, > int *status) int fits_delete_rowrange / ffdrrg (fitsfile *fptr, char *rangelist, > int *status) int fits_delete_rowlist / ffdrws (fitsfile *fptr, long *rowlist, long nrows, > int *status) int fits_delete_rowlistll / ffdrwsll (fitsfile *fptr, LONGLONG *rowlist, LONGLONG nrows, > int *status) \end{verbatim} \begin{description} \item[2 ] Insert or delete column(s) in an ASCII or binary table. When inserting, COLNUM specifies the column number that the (first) new column should occupy in the table. NCOLS specifies how many columns are to be inserted. Any existing columns from this position and higher are shifted over to allow room for the new column(s). The index number on all the following keywords will be incremented or decremented if necessary to reflect the new position of the column(s) in the table: TBCOLn, TFORMn, TTYPEn, TUNITn, TNULLn, TSCALn, TZEROn, TDISPn, TDIMn, TLMINn, TLMAXn, TDMINn, TDMAXn, TCTYPn, TCRPXn, TCRVLn, TCDLTn, TCROTn, and TCUNIn. \label{fficol} \label{fficls} \label{ffdcol} \end{description} \begin{verbatim} int fits_insert_col / fficol (fitsfile *fptr, int colnum, char *ttype, char *tform, > int *status) int fits_insert_cols / fficls (fitsfile *fptr, int colnum, int ncols, char **ttype, char **tform, > int *status) int fits_delete_col / ffdcol(fitsfile *fptr, int colnum, > int *status) \end{verbatim} \begin{description} \item[3 ] Copy a column from one HDU to another (or to the same HDU). If create\_col = TRUE, then a new column will be inserted in the output table, at position `outcolumn', otherwise the existing output column will be overwritten (in which case it must have a compatible data type). If outcolnum is greater than the number of column in the table, then the new column will be appended to the end of the table. Note that the first column in a table is at colnum = 1. The standard indexed keywords that related to the column (e.g., TDISPn, TUNITn, TCRPXn, TCDLTn, etc.) will also be copied. \label{ffcpcl} \end{description} \begin{verbatim} int fits_copy_col / ffcpcl (fitsfile *infptr, fitsfile *outfptr, int incolnum, int outcolnum, int create_col, > int *status); \end{verbatim} \begin{description} \item[4 ] Copy 'nrows' consecutive rows from one table to another, beginning with row 'firstrow'. These rows will be appended to any existing rows in the output table. Note that the first row in a table is at row = 1. \label{ffcprw} \end{description} \begin{verbatim} int fits_copy_rows / ffcprw (fitsfile *infptr, fitsfile *outfptr, LONGLONG firstrow, LONGLONG nrows, > int *status); \end{verbatim} \begin{description} \item[5 ] Modify the vector length of a binary table column (e.g., change a column from TFORMn = '1E' to '20E'). The vector length may be increased or decreased from the current value. \label{ffmvec} \end{description} \begin{verbatim} int fits_modify_vector_len / ffmvec (fitsfile *fptr, int colnum, LONGLONG newveclen, > int *status) \end{verbatim} \subsection{Read and Write Column Data Routines} The following routines write or read data values in the current ASCII or binary table extension. If a write operation extends beyond the current size of the table, then the number of rows in the table will automatically be increased and the NAXIS2 keyword value will be updated. Attempts to read beyond the end of the table will result in an error. Automatic data type conversion is performed for numerical data types (only) if the data type of the column (defined by the TFORMn keyword) differs from the data type of the array in the calling routine. ASCII and binary tables support the following data type values: TSTRING, TBYTE, TSBYTE, TSHORT, TUSHORT, TINT, TUINT, TLONG, TLONGLONG, TULONG, TFLOAT, or TDOUBLE. Binary tables also support TLOGICAL (internally mapped to the `char' data type), TCOMPLEX, and TDBLCOMPLEX. Note that it is *not* necessary to insert rows in a table before writing data to those rows (indeed, it would be inefficient to do so). Instead, one may simply write data to any row of the table, whether that row of data already exists or not. Individual bits in a binary table 'X' or 'B' column may be read/written to/from a *char array by specifying the TBIT datatype. The *char array will be interpreted as an array of logical TRUE (1) or FALSE (0) values that correspond to the value of each bit in the FITS 'X' or 'B' column. Alternatively, the values in a binary table 'X' column may be read/written 8 bits at a time to/from an array of 8-bit integers by specifying the TBYTE datatype. Note that within the context of these routines, the TSTRING data type corresponds to a C 'char**' data type, i.e., a pointer to an array of pointers to an array of characters. This is different from the keyword reading and writing routines where TSTRING corresponds to a C 'char*' data type, i.e., a single pointer to an array of characters. When reading strings from a table, the char arrays obviously must have been allocated long enough to hold the whole FITS table string. Numerical data values are automatically scaled by the TSCALn and TZEROn keyword values (if they exist). In the case of binary tables with vector elements, the 'felem' parameter defines the starting element (beginning with 1, not 0) within the cell (a cell is defined as the intersection of a row and a column and may contain a single value or a vector of values). The felem parameter is ignored when dealing with ASCII tables. Similarly, in the case of binary tables the 'nelements' parameter specifies the total number of vector values to be read or written (continuing on subsequent rows if required) and not the number of table cells. \begin{description} \item[1 ] Write elements into an ASCII or binary table column. \end{description} The first routine simply writes the array of values to the FITS file (doing data type conversion if necessary) whereas the second routine will substitute the appropriate FITS null value for all elements which are equal to the input value of nulval (note that this parameter gives the address of nulval, not the null value itself). For integer columns the FITS null value is defined by the TNULLn keyword (an error is returned if the keyword doesn't exist). For floating point columns the special IEEE NaN (Not-a-Number) value will be written into the FITS file. If a null pointer is entered for nulval, then the null value is ignored and this routine behaves the same as the first routine. The third routine simply writes undefined pixel values to the column. The fourth routine fills every column in the table with null values, in the specified rows (ignoring any columns that do not have a defined null value). \label{ffpcl} \label{ffpcn} \label{ffpclu} \begin{verbatim} int fits_write_col / ffpcl (fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelements, DTYPE *array, > int *status) int fits_write_colnull / ffpcn (fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelements, DTYPE *array, DTYPE *nulval, > int *status) int fits_write_col_null / ffpclu (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelements, > int *status) int fits_write_nullrows / ffprwu (fitsfile *fptr, LONGLONG firstrow, LONGLONG nelements, > int *status) \end{verbatim} \begin{description} \item[2 ] Read elements from an ASCII or binary table column. The data type parameter specifies the data type of the `nulval' and `array' pointers; Undefined array elements will be returned with a value = *nullval, (note that this parameter gives the address of the null value, not the null value itself) unless nulval = 0 or *nulval = 0, in which case no checking for undefined pixels will be performed. The second routine is similar except that any undefined pixels will have the corresponding nullarray element set equal to TRUE (= 1). Any column, regardless of it's intrinsic data type, may be read as a string. It should be noted however that reading a numeric column as a string is 10 - 100 times slower than reading the same column as a number due to the large overhead in constructing the formatted strings. The display format of the returned strings will be determined by the TDISPn keyword, if it exists, otherwise by the data type of the column. The length of the returned strings (not including the null terminating character) can be determined with the fits\_get\_col\_display\_width routine. The following TDISPn display formats are currently supported: \begin{verbatim} Iw.m Integer Ow.m Octal integer Zw.m Hexadecimal integer Fw.d Fixed floating point Ew.d Exponential floating point Dw.d Exponential floating point Gw.d General; uses Fw.d if significance not lost, else Ew.d \end{verbatim} where w is the width in characters of the displayed values, m is the minimum number of digits displayed, and d is the number of digits to the right of the decimal. The .m field is optional. \label{ffgcv} \label{ffgcf} \end{description} \begin{verbatim} int fits_read_col / ffgcv (fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelements, DTYPE *nulval, DTYPE *array, int *anynul, int *status) int fits_read_colnull / ffgcf (fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelements, DTYPE *array, char *nullarray, int *anynul, int *status) \end{verbatim} \subsection{Row Selection and Calculator Routines} These routines all parse and evaluate an input string containing a user defined arithmetic expression. The first 3 routines select rows in a FITS table, based on whether the expression evaluates to true (not equal to zero) or false (zero). The other routines evaluate the expression and calculate a value for each row of the table. The allowed expression syntax is described in the row filter section in the `Extended File Name Syntax' chapter of this document. The expression may also be written to a text file, and the name of the file, prepended with a '@' character may be supplied for the 'expr' parameter (e.g. '@filename.txt'). The expression in the file can be arbitrarily complex and extend over multiple lines of the file. Lines that begin with 2 slash characters ('//') will be ignored and may be used to add comments to the file. \begin{description} \item[1 ] Evaluate a boolean expression over the indicated rows, returning an array of flags indicating which rows evaluated to TRUE/FALSE. Upon return, *n\_good\_rows contains the number of rows that evaluate to TRUE. \label{fffrow} \end{description} \begin{verbatim} int fits_find_rows / fffrow (fitsfile *fptr, char *expr, long firstrow, long nrows, > long *n_good_rows, char *row_status, int *status) \end{verbatim} \begin{description} \item[2 ] Find the first row which satisfies the input boolean expression \label{ffffrw} \end{description} \begin{verbatim} int fits_find_first_row / ffffrw (fitsfile *fptr, char *expr, > long *rownum, int *status) \end{verbatim} \begin{description} \item[3 ]Evaluate an expression on all rows of a table. If the input and output files are not the same, copy the TRUE rows to the output file; if the output table is not empty, then this routine will append the new selected rows after the existing rows. If the files are the same, delete the FALSE rows (preserve the TRUE rows). \label{ffsrow} \end{description} \begin{verbatim} int fits_select_rows / ffsrow (fitsfile *infptr, fitsfile *outfptr, char *expr, > int *status ) \end{verbatim} \begin{description} \item[4 ] Calculate an expression for the indicated rows of a table, returning the results, cast as datatype (TSHORT, TDOUBLE, etc), in array. If nulval==NULL, UNDEFs will be zeroed out. For vector results, the number of elements returned may be less than nelements if nelements is not an even multiple of the result dimension. Call fits\_test\_expr to obtain the dimensions of the results. \label{ffcrow} \end{description} \begin{verbatim} int fits_calc_rows / ffcrow (fitsfile *fptr, int datatype, char *expr, long firstrow, long nelements, void *nulval, > void *array, int *anynul, int *status) \end{verbatim} \begin{description} \item[5 ]Evaluate an expression and write the result either to a column (if the expression is a function of other columns in the table) or to a keyword (if the expression evaluates to a constant and is not a function of other columns in the table). In the former case, the parName parameter is the name of the column (which may or may not already exist) into which to write the results, and parInfo contains an optional TFORM keyword value if a new column is being created. If a TFORM value is not specified then a default format will be used, depending on the expression. If the expression evaluates to a constant, then the result will be written to the keyword name given by the parName parameter, and the parInfo parameter may be used to supply an optional comment for the keyword. If the keyword does not already exist, then the name of the keyword must be preceded with a '\#' character, otherwise the result will be written to a column with that name. \label{ffcalc} \end{description} \begin{verbatim} int fits_calculator / ffcalc (fitsfile *infptr, char *expr, fitsfile *outfptr, char *parName, char *parInfo, > int *status) \end{verbatim} \begin{description} \item[6 ] This calculator routine is similar to the previous routine, except that the expression is only evaluated over the specified row ranges. nranges specifies the number of row ranges, and firstrow and lastrow give the starting and ending row number of each range. \label{ffcalcrng} \end{description} \begin{verbatim} int fits_calculator_rng / ffcalc_rng (fitsfile *infptr, char *expr, fitsfile *outfptr, char *parName, char *parInfo, int nranges, long *firstrow, long *lastrow > int *status) \end{verbatim} \begin{description} \item[7 ]Evaluate the given expression and return dimension and type information on the result. The returned dimensions correspond to a single row entry of the requested expression, and are equivalent to the result of fits\_read\_tdim(). Note that strings are considered to be one element regardless of string length. If maxdim == 0, then naxes is optional. \label{fftexp} \end{description} \begin{verbatim} int fits_test_expr / fftexp (fitsfile *fptr, char *expr, int maxdim > int *datatype, long *nelem, int *naxis, long *naxes, int *status) \end{verbatim} \subsection{Column Binning or Histogramming Routines} The following routines may be useful when performing histogramming operations on column(s) of a table to generate an image in a primary array or image extension. \begin{description} \item[1 ] Calculate the histogramming parameters (min, max, and bin size for each axis of the histogram, based on a variety of possible input parameters. If the input names of the columns to be binned are null, then the routine will first look for the CPREF = "NAME1, NAME2, ..." keyword which lists the preferred columns. If not present, then the routine will assume the column names X, Y, Z, and T for up to 4 axes (as specified by the NAXIS parameter). MININ and MAXIN are input arrays that give the minimum and maximum value for the histogram, along each axis. Alternatively, the name of keywords that give the min, max, and binsize may be give with the MINNAME, MAXNAME, and BINNAME array parameters. If the value = DOUBLENULLVALUE and no keyword names are given, then the routine will use the TLMINn and TLMAXn keywords, if present, or the actual min and/or max values in the column. BINSIZEIN is an array giving the binsize along each axis. If the value = DOUBLENULLVALUE, and a keyword name is not specified with BINNAME, then this routine will first look for the TDBINn keyword, or else will use a binsize = 1, or a binsize that produces 10 histogram bins, which ever is smaller. \label{calcbinning} \end{description} \begin{verbatim} int fits_calc_binning Input parameters: (fitsfile *fptr, /* IO - pointer to table to be binned */ int naxis, /* I - number of axes/columns in the binned image */ char colname[4][FLEN_VALUE], /* I - optional column names */ double *minin, /* I - optional lower bound value for each axis */ double *maxin, /* I - optional upper bound value, for each axis */ double *binsizein, /* I - optional bin size along each axis */ char minname[4][FLEN_VALUE], /* I - optional keywords for min */ char maxname[4][FLEN_VALUE], /* I - optional keywords for max */ char binname[4][FLEN_VALUE], /* I - optional keywords for binsize */ Output parameters: int *colnum, /* O - column numbers, to be binned */ long *naxes, /* O - number of bins in each histogram axis */ float *amin, /* O - lower bound of the histogram axes */ float *amax, /* O - upper bound of the histogram axes */ float *binsize, /* O - width of histogram bins/pixels on each axis */ int *status) \end{verbatim} \begin{description} \item[2 ] Copy the relevant keywords from the header of the table that is being binned, to the the header of the output histogram image. This will not copy the table structure keywords (e.g., NAXIS, TFORMn, TTYPEn, etc.) nor will it copy the keywords that apply to other columns of the table that are not used to create the histogram. This routine will translate the names of the World Coordinate System (WCS) keywords for the binned columns into the form that is need for a FITS image (e.g., the TCTYPn table keyword will be translated to the CTYPEn image keyword). \label{copypixlist2image} \end{description} \begin{verbatim} int fits_copy_pixlist2image (fitsfile *infptr, /* I - pointer to input HDU */ fitsfile *outfptr, /* I - pointer to output HDU */ int firstkey, /* I - first HDU keyword to start with */ int naxis, /* I - number of axes in the image */ int *colnum, /* I - numbers of the columns to be binned */ int *status) /* IO - error status */ \end{verbatim} \begin{description} \item[3 ] Write a set of default WCS keywords to the histogram header, IF the WCS keywords do not already exist. This will create a linear WCS where the coordinate types are equal to the original column names. \label{writekeyshisto} \end{description} \begin{verbatim} int fits_write_keys_histo (fitsfile *fptr, /* I - pointer to table to be binned */ fitsfile *histptr, /* I - pointer to output histogram image HDU */ int naxis, /* I - number of axes in the histogram image */ int *colnum, /* I - column numbers of the binned columns */ int *status) \end{verbatim} \begin{description} \item[4 ] Update the WCS keywords in a histogram image header that give the location of the reference pixel (CRPIXn), and the pixel size (CDELTn), in the binned image. \label{rebinwcs} \end{description} \begin{verbatim} int fits_rebin_wcs (fitsfile *fptr, /* I - pointer to table to be binned */ int naxis, /* I - number of axes in the histogram image */ float *amin, /* I - first pixel include in each axis */ float *binsize, /* I - binning factor for each axis */ int *status) \end{verbatim} \begin{description} \item[5 ] Bin the values in the input table columns, and write the histogram array to the output FITS image (histptr). \label{makehist} \end{description} \begin{verbatim} int fits_make_hist (fitsfile *fptr, /* I - pointer to table with X and Y cols; */ fitsfile *histptr, /* I - pointer to output FITS image */ int bitpix, /* I - datatype for image: 16, 32, -32, etc */ int naxis, /* I - number of axes in the histogram image */ long *naxes, /* I - size of axes in the histogram image */ int *colnum, /* I - column numbers (array length = naxis) */ float *amin, /* I - minimum histogram value, for each axis */ float *amax, /* I - maximum histogram value, for each axis */ float *binsize, /* I - bin size along each axis */ float weight, /* I - binning weighting factor (FLOATNULLVALUE */ /* for no weighting) */ int wtcolnum, /* I - keyword or col for weight (or NULL) */ int recip, /* I - use reciprocal of the weight? 0 or 1 */ char *selectrow, /* I - optional array (length = no. of */ /* rows in the table). If the element is true */ /* then the corresponding row of the table will */ /* be included in the histogram, otherwise the */ /* row will be skipped. Ingnored if *selectrow */ /* is equal to NULL. */ int *status) \end{verbatim} \section{Utility Routines} \subsection{File Checksum Routines} The following routines either compute or validate the checksums for the CHDU. The DATASUM keyword is used to store the numerical value of the 32-bit, 1's complement checksum for the data unit alone. If there is no data unit then the value is set to zero. The numerical value is stored as an ASCII string of digits, enclosed in quotes, because the value may be too large to represent as a 32-bit signed integer. The CHECKSUM keyword is used to store the ASCII encoded COMPLEMENT of the checksum for the entire HDU. Storing the complement, rather than the actual checksum, forces the checksum for the whole HDU to equal zero. If the file has been modified since the checksums were computed, then the HDU checksum will usually not equal zero. These checksum keyword conventions are based on a paper by Rob Seaman published in the proceedings of the ADASS IV conference in Baltimore in November 1994 and a later revision in June 1995. See Appendix B for the definition of the parameters used in these routines. \begin{description} \item[1 ] Compute and write the DATASUM and CHECKSUM keyword values for the CHDU into the current header. If the keywords already exist, their values will be updated only if necessary (i.e., if the file has been modified since the original keyword values were computed). \label{ffpcks} \end{description} \begin{verbatim} int fits_write_chksum / ffpcks (fitsfile *fptr, > int *status) \end{verbatim} \begin{description} \item[2 ] Update the CHECKSUM keyword value in the CHDU, assuming that the DATASUM keyword exists and already has the correct value. This routine calculates the new checksum for the current header unit, adds it to the data unit checksum, encodes the value into an ASCII string, and writes the string to the CHECKSUM keyword. \label{ffupck} \end{description} \begin{verbatim} int fits_update_chksum / ffupck (fitsfile *fptr, > int *status) \end{verbatim} \begin{description} \item[3 ] Verify the CHDU by computing the checksums and comparing them with the keywords. The data unit is verified correctly if the computed checksum equals the value of the DATASUM keyword. The checksum for the entire HDU (header plus data unit) is correct if it equals zero. The output DATAOK and HDUOK parameters in this routine are integers which will have a value = 1 if the data or HDU is verified correctly, a value = 0 if the DATASUM or CHECKSUM keyword is not present, or value = -1 if the computed checksum is not correct. \label{ffvcks} \end{description} \begin{verbatim} int fits_verify_chksum / ffvcks (fitsfile *fptr, > int *dataok, int *hduok, int *status) \end{verbatim} \begin{description} \item[4 ] Compute and return the checksum values for the CHDU without creating or modifying the CHECKSUM and DATASUM keywords. This routine is used internally by ffvcks, but may be useful in other situations as well. \label{ffgcks} \end{description} \begin{verbatim} int fits_get_chksum/ /ffgcks (fitsfile *fptr, > unsigned long *datasum, unsigned long *hdusum, int *status) \end{verbatim} \begin{description} \item[5 ] Encode a checksum value into a 16-character string. If complm is non-zero (true) then the 32-bit sum value will be complemented before encoding. \label{ffesum} \end{description} \begin{verbatim} int fits_encode_chksum / ffesum (unsigned long sum, int complm, > char *ascii); \end{verbatim} \begin{description} \item[6 ] Decode a 16-character checksum string into a unsigned long value. If is non-zero (true). then the 32-bit sum value will be complemented after decoding. The checksum value is also returned as the value of the function. \label{ffdsum} \end{description} \begin{verbatim} unsigned long fits_decode_chksum / ffdsum (char *ascii, int complm, > unsigned long *sum); \end{verbatim} \subsection{Date and Time Utility Routines} The following routines help to construct or parse the FITS date/time strings. Starting in the year 2000, the FITS DATE keyword values (and the values of other `DATE-' keywords) must have the form 'YYYY-MM-DD' (date only) or 'YYYY-MM-DDThh:mm:ss.ddd...' (date and time) where the number of decimal places in the seconds value is optional. These times are in UTC. The older 'dd/mm/yy' date format may not be used for dates after 01 January 2000. See Appendix B for the definition of the parameters used in these routines. \begin{description} \item[1 ] Get the current system date. C already provides standard library routines for getting the current date and time, but this routine is provided for compatibility with the Fortran FITSIO library. The returned year has 4 digits (1999, 2000, etc.) \label{ffgsdt} \end{description} \begin{verbatim} int fits_get_system_date/ffgsdt ( > int *day, int *month, int *year, int *status ) \end{verbatim} \begin{description} \item[2 ] Get the current system date and time string ('YYYY-MM-DDThh:mm:ss'). The time will be in UTC/GMT if available, as indicated by a returned timeref value = 0. If the returned value of timeref = 1 then this indicates that it was not possible to convert the local time to UTC, and thus the local time was returned. \end{description} \begin{verbatim} int fits_get_system_time/ffgstm (> char *datestr, int *timeref, int *status) \end{verbatim} \begin{description} \item[3 ] Construct a date string from the input date values. If the year is between 1900 and 1998, inclusive, then the returned date string will have the old FITS format ('dd/mm/yy'), otherwise the date string will have the new FITS format ('YYYY-MM-DD'). Use fits\_time2str instead to always return a date string using the new FITS format. \label{ffdt2s} \end{description} \begin{verbatim} int fits_date2str/ffdt2s (int year, int month, int day, > char *datestr, int *status) \end{verbatim} \begin{description} \item[4 ] Construct a new-format date + time string ('YYYY-MM-DDThh:mm:ss.ddd...'). If the year, month, and day values all = 0 then only the time is encoded with format 'hh:mm:ss.ddd...'. The decimals parameter specifies how many decimal places of fractional seconds to include in the string. If `decimals' is negative, then only the date will be return ('YYYY-MM-DD'). \end{description} \begin{verbatim} int fits_time2str/fftm2s (int year, int month, int day, int hour, int minute, double second, int decimals, > char *datestr, int *status) \end{verbatim} \begin{description} \item[5 ] Return the date as read from the input string, where the string may be in either the old ('dd/mm/yy') or new ('YYYY-MM-DDThh:mm:ss' or 'YYYY-MM-DD') FITS format. Null pointers may be supplied for any unwanted output date parameters. \end{description} \begin{verbatim} int fits_str2date/ffs2dt (char *datestr, > int *year, int *month, int *day, int *status) \end{verbatim} \begin{description} \item[6 ] Return the date and time as read from the input string, where the string may be in either the old or new FITS format. The returned hours, minutes, and seconds values will be set to zero if the input string does not include the time ('dd/mm/yy' or 'YYYY-MM-DD') . Similarly, the returned year, month, and date values will be set to zero if the date is not included in the input string ('hh:mm:ss.ddd...'). Null pointers may be supplied for any unwanted output date and time parameters. \end{description} \begin{verbatim} int fits_str2time/ffs2tm (char *datestr, > int *year, int *month, int *day, int *hour, int *minute, double *second, int *status) \end{verbatim} \subsection{General Utility Routines} The following utility routines may be useful for certain applications. \begin{description} \item[1 ] Return the revision number of the CFITSIO library. The revision number will be incremented with each new release of CFITSIO. \label{ffvers} \end{description} \begin{verbatim} float fits_get_version / ffvers ( > float *version) \end{verbatim} \begin{description} \item[2 ] Write an 80-character message to the CFITSIO error stack. Application programs should not normally write to the stack, but there may be some situations where this is desirable. \label{ffpmsg} \end{description} \begin{verbatim} void fits_write_errmsg / ffpmsg (char *err_msg) \end{verbatim} \begin{description} \item[3 ] Convert a character string to uppercase (operates in place). \label{ffupch} \end{description} \begin{verbatim} void fits_uppercase / ffupch (char *string) \end{verbatim} \begin{description} \item[4 ] Compare the input template string against the reference string to see if they match. The template string may contain wildcard characters: '*' will match any sequence of characters (including zero characters) and '?' will match any single character in the reference string. The '\#' character will match any consecutive string of decimal digits (0 - 9). If casesen = CASESEN = TRUE then the match will be case sensitive, otherwise the case of the letters will be ignored if casesen = CASEINSEN = FALSE. The returned MATCH parameter will be TRUE if the 2 strings match, and EXACT will be TRUE if the match is exact (i.e., if no wildcard characters were used in the match). Both strings must be 68 characters or less in length. \label{ffcmps} \end{description} \begin{verbatim} void fits_compare_str / ffcmps (char *templt, char *string, int casesen, > int *match, int *exact) \end{verbatim} \begin{description} \item[5 ]Split a string containing a list of names (typically file names or column names) into individual name tokens by a sequence of calls to fits\_split\_names. The names in the list must be delimited by a comma and/or spaces. This routine ignores spaces and commas that occur within parentheses, brackets, or curly brackets. It also strips any leading and trailing blanks from the returned name. This routine is similar to the ANSI C 'strtok' function: The first call to fits\_split\_names has a non-null input string. It finds the first name in the string and terminates it by overwriting the next character of the string with a null terminator and returns a pointer to the name. Each subsequent call, indicated by a NULL value of the input string, returns the next name, searching from just past the end of the previous name. It returns NULL when no further names are found. \label{splitnames} \end{description} \begin{verbatim} char *fits_split_names(char *namelist) \end{verbatim} The following example shows how a string would be split into 3 names: \begin{verbatim} myfile[1][bin (x,y)=4], file2.fits file3.fits ^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^ 1st name 2nd name 3rd name \end{verbatim} \begin{description} \item[6 ] Test that the keyword name contains only legal characters (A-Z,0-9, hyphen, and underscore) or that the keyword record contains only legal printable ASCII characters \label{fftkey} \label{fftrec} \end{description} \begin{verbatim} int fits_test_keyword / fftkey (char *keyname, > int *status) int fits_test_record / fftrec (char *card, > int *status) \end{verbatim} \begin{description} \item[7 ] Test whether the current header contains any NULL (ASCII 0) characters. These characters are illegal in the header, but they will go undetected by most of the CFITSIO keyword header routines, because the null is interpreted as the normal end-of-string terminator. This routine returns the position of the first null character in the header, or zero if there are no nulls. For example a returned value of 110 would indicate that the first NULL is located in the 30th character of the second keyword in the header (recall that each header record is 80 characters long). Note that this is one of the few CFITSIO routines in which the returned value is not necessarily equal to the status value). \label{ffnchk} \end{description} \begin{verbatim} int fits_null_check / ffnchk (char *card, > int *status) \end{verbatim} \begin{description} \item[8 ] Parse a header keyword record and return the name of the keyword, and the length of the name. The keyword name normally occupies the first 8 characters of the record, except under the HIERARCH convention where the name can be up to 70 characters in length. \label{ffgknm} \end{description} \begin{verbatim} int fits_get_keyname / ffgknm (char *card, > char *keyname, int *keylength, int *status) \end{verbatim} \begin{description} \item[9 ] Parse a header keyword record, returning the value (as a literal character string) and comment strings. If the keyword has no value (columns 9-10 not equal to '= '), then a null value string is returned and the comment string is set equal to column 9 - 80 of the input string. \label{ffpsvc} \end{description} \begin{verbatim} int fits_parse_value / ffpsvc (char *card, > char *value, char *comment, int *status) \end{verbatim} \begin{description} \item[10] Construct a properly formated 80-character header keyword record from the input keyword name, keyword value, and keyword comment strings. Hierarchical keyword names (e.g., "ESO TELE CAM") are supported. The value string may contain an integer, floating point, logical, or quoted character string (e.g., "12", "15.7", "T", or "'NGC 1313'"). \label{ffmkky} \end{description} \begin{verbatim} int fits_make_key / ffmkky (const char *keyname, const char *value, const char *comment, > char *card, int *status) \end{verbatim} \begin{description} \item[11] Construct an array indexed keyword name (ROOT + nnn). This routine appends the sequence number to the root string to create a keyword name (e.g., 'NAXIS' + 2 = 'NAXIS2') \label{ffkeyn} \end{description} \begin{verbatim} int fits_make_keyn / ffkeyn (char *keyroot, int value, > char *keyname, int *status) \end{verbatim} \begin{description} \item[12] Construct a sequence keyword name (n + ROOT). This routine concatenates the sequence number to the front of the root string to create a keyword name (e.g., 1 + 'CTYP' = '1CTYP') \label{ffnkey} \end{description} \begin{verbatim} int fits_make_nkey / ffnkey (int value, char *keyroot, > char *keyname, int *status) \end{verbatim} \begin{description} \item[13] Determine the data type of a keyword value string. This routine parses the keyword value string to determine its data type. Returns 'C', 'L', 'I', 'F' or 'X', for character string, logical, integer, floating point, or complex, respectively. \label{ffdtyp} \end{description} \begin{verbatim} int fits_get_keytype / ffdtyp (char *value, > char *dtype, int *status) \end{verbatim} \begin{description} \item[14] Determine the integer data type of an integer keyword value string. The returned datatype value is the minimum integer datatype (starting from top of the following list and working down) required to store the integer value: \end{description} \begin{verbatim} Data Type Range TSBYTE: -128 to 127 TBYTE: 128 to 255 TSHORT: -32768 to 32767 TUSHORT: 32768 to 65535 TINT -2147483648 to 2147483647 TUINT 2147483648 to 4294967295 TLONGLONG -9223372036854775808 to 9223372036854775807 \end{verbatim} \begin{description} \item[ ] The *neg parameter returns 1 if the input value is negative and returns 0 if it is non-negative.\label{ffinttyp} \end{description} \begin{verbatim} int fits_get_inttype / ffinttyp (char *value, > int *datatype, int *neg, int *status) \end{verbatim} \begin{description} \item[15] Return the class of an input header record. The record is classified into one of the following categories (the class values are defined in fitsio.h). Note that this is one of the few CFITSIO routines that does not return a status value. \label{ffgkcl} \end{description} \begin{verbatim} Class Value Keywords TYP_STRUC_KEY 10 SIMPLE, BITPIX, NAXIS, NAXISn, EXTEND, BLOCKED, GROUPS, PCOUNT, GCOUNT, END XTENSION, TFIELDS, TTYPEn, TBCOLn, TFORMn, THEAP, and the first 4 COMMENT keywords in the primary array that define the FITS format. TYP_CMPRS_KEY 20 The keywords used in the compressed image or table format, including ZIMAGE, ZCMPTYPE, ZNAMEn, ZVALn, ZTILEn, ZBITPIX, ZNAXISn, ZSCALE, ZZERO, ZBLANK TYP_SCAL_KEY 30 BSCALE, BZERO, TSCALn, TZEROn TYP_NULL_KEY 40 BLANK, TNULLn TYP_DIM_KEY 50 TDIMn TYP_RANG_KEY 60 TLMINn, TLMAXn, TDMINn, TDMAXn, DATAMIN, DATAMAX TYP_UNIT_KEY 70 BUNIT, TUNITn TYP_DISP_KEY 80 TDISPn TYP_HDUID_KEY 90 EXTNAME, EXTVER, EXTLEVEL, HDUNAME, HDUVER, HDULEVEL TYP_CKSUM_KEY 100 CHECKSUM, DATASUM TYP_WCS_KEY 110 WCS keywords defined in the the WCS papers, including: CTYPEn, CUNITn, CRVALn, CRPIXn, CROTAn, CDELTn CDj_is, PVj_ms, LONPOLEs, LATPOLEs TCTYPn, TCTYns, TCUNIn, TCUNns, TCRVLn, TCRVns, TCRPXn, TCRPks, TCDn_k, TCn_ks, TPVn_m, TPn_ms, TCDLTn, TCROTn jCTYPn, jCTYns, jCUNIn, jCUNns, jCRVLn, jCRVns, iCRPXn, iCRPns, jiCDn, jiCDns, jPVn_m, jPn_ms, jCDLTn, jCROTn (i,j,m,n are integers, s is any letter) TYP_REFSYS_KEY 120 EQUINOXs, EPOCH, MJD-OBSs, RADECSYS, RADESYSs, DATE-OBS TYP_COMM_KEY 130 COMMENT, HISTORY, (blank keyword) TYP_CONT_KEY 140 CONTINUE TYP_USER_KEY 150 all other keywords int fits_get_keyclass / ffgkcl (char *card) \end{verbatim} \begin{description} \item[16] Parse the 'TFORM' binary table column format string. This routine parses the input TFORM character string and returns the integer data type code, the repeat count of the field, and, in the case of character string fields, the length of the unit string. See Appendix B for the allowed values for the returned typecode parameter. A null pointer may be given for any output parameters that are not needed. \label{ffbnfm} \end{description} \begin{verbatim} int fits_binary_tform / ffbnfm (char *tform, > int *typecode, long *repeat, long *width, int *status) int fits_binary_tformll / ffbnfmll (char *tform, > int *typecode, LONGLONG *repeat, long *width, int *status) \end{verbatim} \begin{description} \item[17] Parse the 'TFORM' keyword value that defines the column format in an ASCII table. This routine parses the input TFORM character string and returns the data type code, the width of the column, and (if it is a floating point column) the number of decimal places to the right of the decimal point. The returned data type codes are the same as for the binary table, with the following additional rules: integer columns that are between 1 and 4 characters wide are defined to be short integers (code = TSHORT). Wider integer columns are defined to be regular integers (code = TLONG). Similarly, Fixed decimal point columns (with TFORM = 'Fw.d') are defined to be single precision reals (code = TFLOAT) if w is between 1 and 7 characters wide, inclusive. Wider 'F' columns will return a double precision data code (= TDOUBLE). 'Ew.d' format columns will have datacode = TFLOAT, and 'Dw.d' format columns will have datacode = TDOUBLE. A null pointer may be given for any output parameters that are not needed. \label{ffasfm} \end{description} \begin{verbatim} int fits_ascii_tform / ffasfm (char *tform, > int *typecode, long *width, int *decimals, int *status) \end{verbatim} \begin{description} \item[18] Calculate the starting column positions and total ASCII table width based on the input array of ASCII table TFORM values. The SPACE input parameter defines how many blank spaces to leave between each column (it is recommended to have one space between columns for better human readability). \label{ffgabc} \end{description} \begin{verbatim} int fits_get_tbcol / ffgabc (int tfields, char **tform, int space, > long *rowlen, long *tbcol, int *status) \end{verbatim} \begin{description} \item[19] Parse a template header record and return a formatted 80-character string suitable for appending to (or deleting from) a FITS header file. This routine is useful for parsing lines from an ASCII template file and reformatting them into legal FITS header records. The formatted string may then be passed to the fits\_write\_record, ffmcrd, or fits\_delete\_key routines to append or modify a FITS header record. \label{ffgthd} \end{description} \begin{verbatim} int fits_parse_template / ffgthd (char *templt, > char *card, int *keytype, int *status) \end{verbatim} The input templt character string generally should contain 3 tokens: (1) the KEYNAME, (2) the VALUE, and (3) the COMMENT string. The TEMPLATE string must adhere to the following format: \begin{description} \item[- ] The KEYNAME token must begin in columns 1-8 and be a maximum of 8 characters long. A legal FITS keyword name may only contain the characters A-Z, 0-9, and '-' (minus sign) and underscore. This routine will automatically convert any lowercase characters to uppercase in the output string. If the first 8 characters of the template line are blank then the remainder of the line is considered to be a FITS comment (with a blank keyword name). \end{description} \begin{description} \item[- ] The VALUE token must be separated from the KEYNAME token by one or more spaces and/or an '=' character. The data type of the VALUE token (numeric, logical, or character string) is automatically determined and the output CARD string is formatted accordingly. The value token may be forced to be interpreted as a string (e.g. if it is a string of numeric digits) by enclosing it in single quotes. If the value token is a character string that contains 1 or more embedded blank space characters or slash ('/') characters then the entire character string must be enclosed in single quotes. \end{description} \begin{description} \item[- ] The COMMENT token is optional, but if present must be separated from the VALUE token by a blank space or a '/' character. \end{description} \begin{description} \item[- ] One exception to the above rules is that if the first non-blank character in the first 8 characters of the template string is a minus sign ('-') followed by a single token, or a single token followed by an equal sign, then it is interpreted as the name of a keyword which is to be deleted from the FITS header. \end{description} \begin{description} \item[- ] The second exception is that if the template string starts with a minus sign and is followed by 2 tokens (without an equals sign between them) then the second token is interpreted as the new name for the keyword specified by first token. In this case the old keyword name (first token) is returned in characters 1-8 of the returned CARD string, and the new keyword name (the second token) is returned in characters 41-48 of the returned CARD string. These old and new names may then be passed to the ffmnam routine which will change the keyword name. \end{description} The keytype output parameter indicates how the returned CARD string should be interpreted: \begin{verbatim} keytype interpretation ------- ------------------------------------------------- -2 Rename the keyword with name = the first 8 characters of CARD to the new name given in characters 41 - 48 of CARD. -1 delete the keyword with this name from the FITS header. 0 append the CARD string to the FITS header if the keyword does not already exist, otherwise update the keyword value and/or comment field if is already exists. 1 This is a HISTORY or COMMENT keyword; append it to the header 2 END record; do not explicitly write it to the FITS file. \end{verbatim} EXAMPLES: The following lines illustrate valid input template strings: \begin{verbatim} INTVAL 7 / This is an integer keyword RVAL 34.6 / This is a floating point keyword EVAL=-12.45E-03 / This is a floating point keyword in exponential notation lval F / This is a boolean keyword This is a comment keyword with a blank keyword name SVAL1 = 'Hello world' / this is a string keyword SVAL2 '123.5' this is also a string keyword sval3 123+ / this is also a string keyword with the value '123+ ' # the following template line deletes the DATE keyword - DATE # the following template line modifies the NAME keyword to OBJECT - NAME OBJECT \end{verbatim} \begin{description} \item[20] Translate a keyword name into a new name, based on a set of patterns. This routine is useful for translating keywords in cases such as adding or deleting columns in a table, or copying a column from one table to another, or extracting an array from a cell in a binary table column into an image extension. In these cases, it is necessary to translate the names of the keywords associated with the original table column(s) into the appropriate keyword name in the final file. For example, if column 2 is deleted from a table, then the value of 'n' in all the TFORMn and TTYPEn keywords for columns 3 and higher must be decremented by 1. Even more complex translations are sometimes needed to convert the WCS keywords when extracting an image out of a table column cell into a separate image extension. The user passes an array of patterns to be matched. Input pattern number i is pattern[i][0], and output pattern number i is pattern[i][1]. Keywords are matched against the input patterns. If a match is found then the keyword is re-written according to the output pattern. Order is important. The first match is accepted. The fastest match will be made when templates with the same first character are grouped together. Several characters have special meanings: \begin{verbatim} i,j - single digits, preserved in output template n - column number of one or more digits, preserved in output template m - generic number of one or more digits, preserved in output template a - coordinate designator, preserved in output template # - number of one or more digits ? - any character * - only allowed in first character position, to match all keywords; only useful as last pattern in the list \end{verbatim} i, j, n, and m are returned by the routine. For example, the input pattern "iCTYPn" will match "1CTYP5" (if n\_value is 5); the output pattern "CTYPEi" will be re-written as "CTYPE1". Notice that "i" is preserved. The following output patterns are special: "-" - do not copy a keyword that matches the corresponding input pattern "+" - copy the input unchanged The inrec string could be just the 8-char keyword name, or the entire 80-char header record. Characters 9 - 80 in the input string simply get appended to the translated keyword name. If n\_range = 0, then only keywords with 'n' equal to n\_value will be considered as a pattern match. If n\_range = +1, then all values of 'n' greater than or equal to n\_value will be a match, and if -1, then values of 'n' less than or equal to n\_value will match.\label{translatekey} \end{description} \begin{verbatim} int fits_translate_keyword( char *inrec, /* I - input string */ char *outrec, /* O - output converted string, or */ /* a null string if input does not */ /* match any of the patterns */ char *patterns[][2],/* I - pointer to input / output string */ /* templates */ int npat, /* I - number of templates passed */ int n_value, /* I - base 'n' template value of interest */ int n_offset, /* I - offset to be applied to the 'n' */ /* value in the output string */ int n_range, /* I - controls range of 'n' template */ /* values of interest (-1,0, or +1) */ int *pat_num, /* O - matched pattern number (0 based) or -1 */ int *i, /* O - value of i, if any, else 0 */ int *j, /* O - value of j, if any, else 0 */ int *m, /* O - value of m, if any, else 0 */ int *n, /* O - value of n, if any, else 0 */ int *status) /* IO - error status */ \end{verbatim} \begin{description} \item[ ] Here is an example of some of the patterns used to convert the keywords associated with an image in a cell of a table column into the keywords appropriate for an IMAGE extension: \end{description} \begin{verbatim} char *patterns[][2] = {{"TSCALn", "BSCALE" }, /* Standard FITS keywords */ {"TZEROn", "BZERO" }, {"TUNITn", "BUNIT" }, {"TNULLn", "BLANK" }, {"TDMINn", "DATAMIN" }, {"TDMAXn", "DATAMAX" }, {"iCTYPn", "CTYPEi" }, /* Coordinate labels */ {"iCTYna", "CTYPEia" }, {"iCUNIn", "CUNITi" }, /* Coordinate units */ {"iCUNna", "CUNITia" }, {"iCRVLn", "CRVALi" }, /* WCS keywords */ {"iCRVna", "CRVALia" }, {"iCDLTn", "CDELTi" }, {"iCDEna", "CDELTia" }, {"iCRPXn", "CRPIXi" }, {"iCRPna", "CRPIXia" }, {"ijPCna", "PCi_ja" }, {"ijCDna", "CDi_ja" }, {"iVn_ma", "PVi_ma" }, {"iSn_ma", "PSi_ma" }, {"iCRDna", "CRDERia" }, {"iCSYna", "CSYERia" }, {"iCROTn", "CROTAi" }, {"WCAXna", "WCSAXESa"}, {"WCSNna", "WCSNAMEa"}}; \end{verbatim} \begin{description} \item[21] Translate the keywords in the input HDU into the keywords that are appropriate for the output HDU. This is a driver routine that calls the previously described routine. \end{description} \begin{verbatim} int fits_translate_keywords( fitsfile *infptr, /* I - pointer to input HDU */ fitsfile *outfptr, /* I - pointer to output HDU */ int firstkey, /* I - first HDU record number to start with */ char *patterns[][2],/* I - pointer to input / output keyword templates */ int npat, /* I - number of templates passed */ int n_value, /* I - base 'n' template value of interest */ int n_offset, /* I - offset to be applied to the 'n' */ /* value in the output string */ int n_range, /* I - controls range of 'n' template */ /* values of interest (-1,0, or +1) */ int *status) /* IO - error status */ \end{verbatim} \begin{description} \item[22] Parse the input string containing a list of rows or row ranges, and return integer arrays containing the first and last row in each range. For example, if rowlist = "3-5, 6, 8-9" then it will return numranges = 3, rangemin = 3, 6, 8 and rangemax = 5, 6, 9. At most, 'maxranges' number of ranges will be returned. 'maxrows' is the maximum number of rows in the table; any rows or ranges larger than this will be ignored. The rows must be specified in increasing order, and the ranges must not overlap. A minus sign may be use to specify all the rows to the upper or lower bound, so "50-" means all the rows from 50 to the end of the table, and "-" means all the rows in the table, from 1 - maxrows. \label{ffrwrg} \end{description} \begin{verbatim} int fits_parse_range / ffrwrg(char *rowlist, LONGLONG maxrows, int maxranges, > int *numranges, long *rangemin, long *rangemax, int *status) int fits_parse_rangell / ffrwrgll(char *rowlist, LONGLONG maxrows, int maxranges, > int *numranges, LONGLONG *rangemin, LONGLONG *rangemax, int *status) \end{verbatim} \begin{description} \item[23] Check that the Header fill bytes (if any) are all blank. These are the bytes that may follow END keyword and before the beginning of data unit, or the end of the HDU if there is no data unit. \label{ffchfl} \end{description} \begin{verbatim} int ffchfl(fitsfile *fptr, > int *status) \end{verbatim} \begin{description} \item[24] Check that the Data fill bytes (if any) are all zero (for IMAGE or BINARY Table HDU) or all blanks (for ASCII table HDU). These file bytes may be located after the last valid data byte in the HDU and before the physical end of the HDU. \label{ffcdfl} \end{description} \begin{verbatim} int ffcdfl(fitsfile *fptr, > int *status) \end{verbatim} \begin{description} \item[25] Estimate the root-mean-squared (RMS) noise in an image. These routines are mainly for use with the Hcompress image compression algorithm. They return an estimate of the RMS noise in the background pixels of the image. This robust algorithm (written by Richard White, STScI) first attempts to estimate the RMS value as 1.68 times the median of the absolute differences between successive pixels in the image. If the median = 0, then the algorithm falls back to computing the RMS of the difference between successive pixels, after several N-sigma rejection cycles to remove extreme values. The input parameters are: the array of image pixel values (either float or short values), the number of values in the array, the value that is used to represent null pixels (enter a very large number if there are no null pixels). \label{imageRMS} \end{description} \begin{verbatim} int fits_rms_float (float fdata[], int npix, float in_null_value, > double *rms, int *status) int fits_rms_short (short fdata[], int npix, short in_null_value, > double *rms, int *status) \end{verbatim} \begin{description} \item[26] Was CFITSIO compiled with the -D\_REENTRANT directive so that it may be safely used in multi-threaded environments? The following function returns 1 if yes, 0 if no. Note, however, that even if the -D\_REENTRANT directive was specified, this does not guarantee that the CFITSIO routines are thread-safe, because some compilers may not support this feature.\label{reentrant} \end{description} \begin{verbatim} int fits_is_reentrant(void) \end{verbatim} \chapter{ The CFITSIO Iterator Function } The fits\_iterate\_data function in CFITSIO provides a unique method of executing an arbitrary user-supplied `work' function that operates on rows of data in FITS tables or on pixels in FITS images. Rather than explicitly reading and writing the FITS images or columns of data, one instead calls the CFITSIO iterator routine, passing to it the name of the user's work function that is to be executed along with a list of all the table columns or image arrays that are to be passed to the work function. The CFITSIO iterator function then does all the work of allocating memory for the arrays, reading the input data from the FITS file, passing them to the work function, and then writing any output data back to the FITS file after the work function exits. Because it is often more efficient to process only a subset of the total table rows at one time, the iterator function can determine the optimum amount of data to pass in each iteration and repeatedly call the work function until the entire table been processed. For many applications this single CFITSIO iterator function can effectively replace all the other CFITSIO routines for reading or writing data in FITS images or tables. Using the iterator has several important advantages over the traditional method of reading and writing FITS data files: \begin{itemize} \item It cleanly separates the data I/O from the routine that operates on the data. This leads to a more modular and `object oriented' programming style. \item It simplifies the application program by eliminating the need to allocate memory for the data arrays and eliminates most of the calls to the CFITSIO routines that explicitly read and write the data. \item It ensures that the data are processed as efficiently as possible. This is especially important when processing tabular data since the iterator function will calculate the most efficient number of rows in the table to be passed at one time to the user's work function on each iteration. \item Makes it possible for larger projects to develop a library of work functions that all have a uniform calling sequence and are all independent of the details of the FITS file format. \end{itemize} There are basically 2 steps in using the CFITSIO iterator function. The first step is to design the work function itself which must have a prescribed set of input parameters. One of these parameters is a structure containing pointers to the arrays of data; the work function can perform any desired operations on these arrays and does not need to worry about how the input data were read from the file or how the output data get written back to the file. The second step is to design the driver routine that opens all the necessary FITS files and initializes the input parameters to the iterator function. The driver program calls the CFITSIO iterator function which then reads the data and passes it to the user's work function. The following 2 sections describe these steps in more detail. There are also several example programs included with the CFITSIO distribution which illustrate how to use the iterator function. \section{The Iterator Work Function} The user-supplied iterator work function must have the following set of input parameters (the function can be given any desired name): \begin{verbatim} int user_fn( long totaln, long offset, long firstn, long nvalues, int narrays, iteratorCol *data, void *userPointer ) \end{verbatim} \begin{itemize} \item totaln -- the total number of table rows or image pixels that will be passed to the work function during 1 or more iterations. \item offset -- the offset applied to the first table row or image pixel to be passed to the work function. In other words, this is the number of rows or pixels that are skipped over before starting the iterations. If offset = 0, then all the table rows or image pixels will be passed to the work function. \item firstn -- the number of the first table row or image pixel (starting with 1) that is being passed in this particular call to the work function. \item nvalues -- the number of table rows or image pixels that are being passed in this particular call to the work function. nvalues will always be less than or equal to totaln and will have the same value on each iteration, except possibly on the last call which may have a smaller value. \item narrays -- the number of arrays of data that are being passed to the work function. There is one array for each image or table column. \item *data -- array of structures, one for each column or image. Each structure contains a pointer to the array of data as well as other descriptive parameters about that array. \item *userPointer -- a user supplied pointer that can be used to pass ancillary information from the driver function to the work function. This pointer is passed to the CFITSIO iterator function which then passes it on to the work function without any modification. It may point to a single number, to an array of values, to a structure containing an arbitrary set of parameters of different types, or it may be a null pointer if it is not needed. The work function must cast this pointer to the appropriate data type before using it it. \end{itemize} The totaln, offset, narrays, data, and userPointer parameters are guaranteed to have the same value on each iteration. Only firstn, nvalues, and the arrays of data pointed to by the data structures may change on each iterative call to the work function. Note that the iterator treats an image as a long 1-D array of pixels regardless of it's intrinsic dimensionality. The total number of pixels is just the product of the size of each dimension, and the order of the pixels is the same as the order that they are stored in the FITS file. If the work function needs to know the number and size of the image dimensions then these parameters can be passed via the userPointer structure. The iteratorCol structure is currently defined as follows: \begin{verbatim} typedef struct /* structure for the iterator function column information */ { /* structure elements required as input to fits_iterate_data: */ fitsfile *fptr; /* pointer to the HDU containing the column or image */ int colnum; /* column number in the table; ignored for images */ char colname[70]; /* name (TTYPEn) of the column; null for images */ int datatype; /* output data type (converted if necessary) */ int iotype; /* type: InputCol, InputOutputCol, or OutputCol */ /* output structure elements that may be useful for the work function: */ void *array; /* pointer to the array (and the null value) */ long repeat; /* binary table vector repeat value; set */ /* equal to 1 for images */ long tlmin; /* legal minimum data value, if any */ long tlmax; /* legal maximum data value, if any */ char unit[70]; /* physical unit string (BUNIT or TUNITn) */ char tdisp[70]; /* suggested display format; null if none */ } iteratorCol; \end{verbatim} Instead of directly reading or writing the elements in this structure, it is recommended that programmers use the access functions that are provided for this purpose. The first five elements in this structure must be initially defined by the driver routine before calling the iterator routine. The CFITSIO iterator routine uses this information to determine what column or array to pass to the work function, and whether the array is to be input to the work function, output from the work function, or both. The CFITSIO iterator function fills in the values of the remaining structure elements before passing it to the work function. The array structure element is a pointer to the actual data array and it must be cast to the correct data type before it is used. The `repeat' structure element give the number of data values in each row of the table, so that the total number of data values in the array is given by repeat * nvalues. In the case of image arrays and ASCII tables, repeat will always be equal to 1. When the data type is a character string, the array pointer is actually a pointer to an array of string pointers (i.e., char **array). The other output structure elements are provided for convenience in case that information is needed within the work function. Any other information may be passed from the driver routine to the work function via the userPointer parameter. Upon completion, the work routine must return an integer status value, with 0 indicating success and any other value indicating an error which will cause the iterator function to immediately exit at that point. Return status values in the range 1 -- 1000 should be avoided since these are reserved for use by CFITSIO. A return status value of -1 may be used to force the CFITSIO iterator function to stop at that point and return control to the driver routine after writing any output arrays to the FITS file. CFITSIO does not considered this to be an error condition, so any further processing by the application program will continue normally. \section{The Iterator Driver Function} The iterator driver function must open the necessary FITS files and position them to the correct HDU. It must also initialize the following parameters in the iteratorCol structure (defined above) for each column or image before calling the CFITSIO iterator function. Several `constructor' routines are provided in CFITSIO for this purpose. \begin{itemize} \item *fptr -- The fitsfile pointer to the table or image. \item colnum -- the number of the column in the table. This value is ignored in the case of images. If colnum equals 0, then the column name will be used to identify the column to be passed to the work function. \item colname -- the name (TTYPEn keyword) of the column. This is only required if colnum = 0 and is ignored for images. \item datatype -- The desired data type of the array to be passed to the work function. For numerical data the data type does not need to be the same as the actual data type in the FITS file, in which case CFITSIO will do the conversion. Allowed values are: TSTRING, TLOGICAL, TBYTE, TSBYTE, TSHORT, TUSHORT, TINT, TLONG, TULONG, TFLOAT, TDOUBLE. If the input value of data type equals 0, then the existing data type of the column or image will be used without any conversion. \item iotype -- defines whether the data array is to be input to the work function (i.e, read from the FITS file), or output from the work function (i.e., written to the FITS file) or both. Allowed values are InputCol, OutputCol, or InputOutputCol. Variable-length array columns are supported as InputCol or InputOutputCol types, but may not be used for an OutputCol type. \end{itemize} After the driver routine has initialized all these parameters, it can then call the CFITSIO iterator function: \begin{verbatim} int fits_iterate_data(int narrays, iteratorCol *data, long offset, long nPerLoop, int (*workFn)( ), void *userPointer, int *status); \end{verbatim} \begin{itemize} \item narrays -- the number of columns or images that are to be passed to the work function. \item *data -- pointer to array of structures containing information about each column or image. \item offset -- if positive, this number of rows at the beginning of the table (or pixels in the image) will be skipped and will not be passed to the work function. \item nPerLoop - specifies the number of table rows (or number of image pixels) that are to be passed to the work function on each iteration. If nPerLoop = 0 then CFITSIO will calculate the optimum number for greatest efficiency. If nPerLoop is negative, then all the rows or pixels will be passed at one time, and the work function will only be called once. If any variable length arrays are being processed, then the nPerLoop value is ignored, and the iterator will always process one row of the table at a time. \item *workFn - the name (actually the address) of the work function that is to be called by fits\_iterate\_data. \item *userPointer - this is a user supplied pointer that can be used to pass ancillary information from the driver routine to the work function. It may point to a single number, an array, or to a structure containing an arbitrary set of parameters. \item *status - The CFITSIO error status. Should = 0 on input; a non-zero output value indicates an error. \end{itemize} When fits\_iterate\_data is called it first allocates memory to hold all the requested columns of data or image pixel arrays. It then reads the input data from the FITS tables or images into the arrays then passes the structure with pointers to these data arrays to the work function. After the work function returns, the iterator function writes any output columns of data or images back to the FITS files. It then repeats this process for any remaining sets of rows or image pixels until it has processed the entire table or image or until the work function returns a non-zero status value. The iterator then frees the memory that it initially allocated and returns control to the driver routine that called it. \section{Guidelines for Using the Iterator Function} The totaln, offset, firstn, and nvalues parameters that are passed to the work function are useful for determining how much of the data has been processed and how much remains left to do. On the very first call to the work function firstn will be equal to offset + 1; the work function may need to perform various initialization tasks before starting to process the data. Similarly, firstn + nvalues - 1 will be equal to totaln on the last iteration, at which point the work function may need to perform some clean up operations before exiting for the last time. The work function can also force an early termination of the iterations by returning a status value = -1. The narrays and iteratorCol.datatype arguments allow the work function to double check that the number of input arrays and their data types have the expected values. The iteratorCol.fptr and iteratorCol.colnum structure elements can be used if the work function needs to read or write the values of other keywords in the FITS file associated with the array. This should generally only be done during the initialization step or during the clean up step after the last set of data has been processed. Extra FITS file I/O during the main processing loop of the work function can seriously degrade the speed of the program. If variable-length array columns are being processed, then the iterator will operate on one row of the table at a time. In this case the the repeat element in the interatorCol structure will be set equal to the number of elements in the current row that is being processed. One important feature of the iterator is that the first element in each array that is passed to the work function gives the value that is used to represent null or undefined values in the array. The real data then begins with the second element of the array (i.e., array[1], not array[0]). If the first array element is equal to zero, then this indicates that all the array elements have defined values and there are no undefined values. If array[0] is not equal to zero, then this indicates that some of the data values are undefined and this value (array[0]) is used to represent them. In the case of output arrays (i.e., those arrays that will be written back to the FITS file by the iterator function after the work function exits) the work function must set the first array element to the desired null value if necessary, otherwise the first element should be set to zero to indicate that there are no null values in the output array. CFITSIO defines 2 values, FLOATNULLVALUE and DOUBLENULLVALUE, that can be used as default null values for float and double data types, respectively. In the case of character string data types, a null string is always used to represent undefined strings. In some applications it may be necessary to recursively call the iterator function. An example of this is given by one of the example programs that is distributed with CFITSIO: it first calls a work function that writes out a 2D histogram image. That work function in turn calls another work function that reads the `X' and `Y' columns in a table to calculate the value of each 2D histogram image pixel. Graphically, the program structure can be described as: \begin{verbatim} driver --> iterator --> work1_fn --> iterator --> work2_fn \end{verbatim} Finally, it should be noted that the table columns or image arrays that are passed to the work function do not all have to come from the same FITS file and instead may come from any combination of sources as long as they have the same length. The length of the first table column or image array is used by the iterator if they do not all have the same length. \section{Complete List of Iterator Routines} All of the iterator routines are listed below. Most of these routines do not have a corresponding short function name. \begin{description} \item[1 ] Iterator `constructor' functions that set the value of elements in the iteratorCol structure that define the columns or arrays. These set the fitsfile pointer, column name, column number, datatype, and iotype, respectively. The last 2 routines allow all the parameters to be set with one function call (one supplies the column name, the other the column number). \label{ffiterset} \end{description} \begin{verbatim} int fits_iter_set_file(iteratorCol *col, fitsfile *fptr); int fits_iter_set_colname(iteratorCol *col, char *colname); int fits_iter_set_colnum(iteratorCol *col, int colnum); int fits_iter_set_datatype(iteratorCol *col, int datatype); int fits_iter_set_iotype(iteratorCol *col, int iotype); int fits_iter_set_by_name(iteratorCol *col, fitsfile *fptr, char *colname, int datatype, int iotype); int fits_iter_set_by_num(iteratorCol *col, fitsfile *fptr, int colnum, int datatype, int iotype); \end{verbatim} \begin{description} \item[2 ] Iterator `accessor' functions that return the value of the element in the iteratorCol structure that describes a particular data column or array \label{ffiterget} \end{description} \begin{verbatim} fitsfile * fits_iter_get_file(iteratorCol *col); char * fits_iter_get_colname(iteratorCol *col); int fits_iter_get_colnum(iteratorCol *col); int fits_iter_get_datatype(iteratorCol *col); int fits_iter_get_iotype(iteratorCol *col); void * fits_iter_get_array(iteratorCol *col); long fits_iter_get_tlmin(iteratorCol *col); long fits_iter_get_tlmax(iteratorCol *col); long fits_iter_get_repeat(iteratorCol *col); char * fits_iter_get_tunit(iteratorCol *col); char * fits_iter_get_tdisp(iteratorCol *col); \end{verbatim} \begin{description} \item[3 ] The CFITSIO iterator function \label{ffiter} \end{description} \begin{verbatim} int fits_iterate_data(int narrays, iteratorCol *data, long offset, long nPerLoop, int (*workFn)( long totaln, long offset, long firstn, long nvalues, int narrays, iteratorCol *data, void *userPointer), void *userPointer, int *status); \end{verbatim} \chapter{ World Coordinate System Routines } The FITS community has adopted a set of keyword conventions that define the transformations needed to convert between pixel locations in an image and the corresponding celestial coordinates on the sky, or more generally, that define world coordinates that are to be associated with any pixel location in an n-dimensional FITS array. CFITSIO is distributed with a a few self-contained World Coordinate System (WCS) routines, however, these routines DO NOT support all the latest WCS conventions, so it is STRONGLY RECOMMENDED that software developers use a more robust external WCS library. Several recommended libraries are: \begin{verbatim} WCSLIB - supported by Mark Calabretta WCSTools - supported by Doug Mink AST library - developed by the U.K. Starlink project \end{verbatim} More information about the WCS keyword conventions and links to all of these WCS libraries can be found on the FITS Support Office web site at http://fits.gsfc.nasa.gov under the WCS link. The functions provided in these external WCS libraries will need access to the WCS keywords contained in the FITS file headers. One convenient way to pass this information to the external library is to use the fits\_hdr2str routine in CFITSIO (defined below) to copy the header keywords into one long string, and then pass this string to an interface routine in the external library that will extract the necessary WCS information (e.g., the 'wcspih' routine in the WCSLIB library and the 'astFitsChan' and 'astPutCards' functions in the AST library). \begin{description} \item[1 ] Concatenate the header keywords in the CHDU into a single long string of characters. Each 80-character fixed-length keyword record is appended to the output character string, in order, with no intervening separator or terminating characters. The last header record is terminated with a NULL character. This routine allocates memory for the returned character array, so the calling program must free the memory when finished. There are 2 related routines: fits\_hdr2str simply concatenates all the existing keywords in the header; fits\_convert\_hdr2str is similar, except that if the CHDU is a tile compressed image (stored in a binary table) then it will first convert that header back to that of a normal FITS image before concatenating the keywords. Selected keywords may be excluded from the returned character string. If the second parameter (nocomments) is TRUE (nonzero) then any COMMENT, HISTORY, or blank keywords in the header will not be copied to the output string. The 'exclist' parameter may be used to supply a list of keywords that are to be excluded from the output character string. Wild card characters (*, ?, and \#) may be used in the excluded keyword names. If no additional keywords are to be excluded, then set nexc = 0 and specify NULL for the the **exclist parameter. \label{hdr2str} \end{description} \begin{verbatim} int fits_hdr2str (fitsfile *fptr, int nocomments, char **exclist, int nexc, > char **header, int *nkeys, int *status) int fits_convert_hdr2str / ffcnvthdr2str (fitsfile *fptr, int nocomments, char **exclist, int nexc, > char **header, int *nkeys, int *status) \end{verbatim} \begin{description} \item[2 ] The following CFITSIO routine is specifically designed for use in conjunction with the WCSLIB library. It is not expected that applications programmers will call this routine directly, but it is documented here for completeness. This routine extracts arrays from a binary table that contain WCS information using the -TAB table lookup convention. See the documentation provided with the WCSLIB library for more information. \label{wcstab} \end{description} \begin{verbatim} int fits_read_wcstab (fitsfile *fptr, int nwtb, wtbarr *wtb, int *status); \end{verbatim} \section{ Self-contained WCS Routines} The following routines DO NOT support the more recent WCS conventions that have been approved as part of the FITS standard. Consequently, the following routines ARE NOW DEPRECATED. It is STRONGLY RECOMMENDED that software developers not use these routines, and instead use an external WCS library, as described in the previous section. These routines are included mainly for backward compatibility with existing software. They support the following standard map projections: -SIN, -TAN, -ARC, -NCP, -GLS, -MER, and -AIT (these are the legal values for the coordtype parameter). These routines are based on similar functions in Classic AIPS. All the angular quantities are given in units of degrees. \begin{description} \item[1 ] Get the values of the basic set of standard FITS celestial coordinate system keywords from the header of a FITS image (i.e., the primary array or an IMAGE extension). These values may then be passed to the fits\_pix\_to\_world and fits\_world\_to\_pix routines that perform the coordinate transformations. If any or all of the WCS keywords are not present, then default values will be returned. If the first coordinate axis is the declination-like coordinate, then this routine will swap them so that the longitudinal-like coordinate is returned as the first axis. The first routine (ffgics) returns the primary WCS, whereas the second routine returns the particular version of the WCS specified by the 'version' parameter, which much be a character ranging from 'A' to 'Z' (or a blank character, which is equivalent to calling ffgics). If the file uses the newer 'CDj\_i' WCS transformation matrix keywords instead of old style 'CDELTn' and 'CROTA2' keywords, then this routine will calculate and return the values of the equivalent old-style keywords. Note that the conversion from the new-style keywords to the old-style values is sometimes only an approximation, so if the approximation is larger than an internally defined threshold level, then CFITSIO will still return the approximate WCS keyword values, but will also return with status = APPROX\_WCS\_KEY, to warn the calling program that approximations have been made. It is then up to the calling program to decide whether the approximations are sufficiently accurate for the particular application, or whether more precise WCS transformations must be performed using new-style WCS keywords directly. \label{ffgics} \end{description} \begin{verbatim} int fits_read_img_coord / ffgics (fitsfile *fptr, > double *xrefval, double *yrefval, double *xrefpix, double *yrefpix, double *xinc, double *yinc, double *rot, char *coordtype, int *status) int fits_read_img_coord_version / ffgicsa (fitsfile *fptr, char version, > double *xrefval, double *yrefval, double *xrefpix, double *yrefpix, double *xinc, double *yinc, double *rot, char *coordtype, int *status) \end{verbatim} \begin{description} \item[2 ] Get the values of the standard FITS celestial coordinate system keywords from the header of a FITS table where the X and Y (or RA and DEC) coordinates are stored in 2 separate columns of the table (as in the Event List table format that is often used by high energy astrophysics missions). These values may then be passed to the fits\_pix\_to\_world and fits\_world\_to\_pix routines that perform the coordinate transformations. \label{ffgtcs} \end{description} \begin{verbatim} int fits_read_tbl_coord / ffgtcs (fitsfile *fptr, int xcol, int ycol, > double *xrefval, double *yrefval, double *xrefpix, double *yrefpix, double *xinc, double *yinc, double *rot, char *coordtype, int *status) \end{verbatim} \begin{description} \item[3 ] Calculate the celestial coordinate corresponding to the input X and Y pixel location in the image. \label{ffwldp} \end{description} \begin{verbatim} int fits_pix_to_world / ffwldp (double xpix, double ypix, double xrefval, double yrefval, double xrefpix, double yrefpix, double xinc, double yinc, double rot, char *coordtype, > double *xpos, double *ypos, int *status) \end{verbatim} \begin{description} \item[4 ] Calculate the X and Y pixel location corresponding to the input celestial coordinate in the image. \label{ffxypx} \end{description} \begin{verbatim} int fits_world_to_pix / ffxypx (double xpos, double ypos, double xrefval, double yrefval, double xrefpix, double yrefpix, double xinc, double yinc, double rot, char *coordtype, > double *xpix, double *ypix, int *status) \end{verbatim} \chapter{ Hierarchical Grouping Routines } These functions allow for the creation and manipulation of FITS HDU Groups, as defined in "A Hierarchical Grouping Convention for FITS" by Jennings, Pence, Folk and Schlesinger: https://fits.gsfc.nasa.gov/registry/grouping/grouping.pdf A group is a collection of HDUs whose association is defined by a {\it grouping table}. HDUs which are part of a group are referred to as {\it member HDUs} or simply as {\it members}. Grouping table member HDUs may themselves be grouping tables, thus allowing for the construction of open-ended hierarchies of HDUs. Grouping tables contain one row for each member HDU. The grouping table columns provide identification information that allows applications to reference or "point to" the member HDUs. Member HDUs are expected, but not required, to contain a set of GRPIDn/GRPLCn keywords in their headers for each grouping table that they are referenced by. In this sense, the GRPIDn/GRPLCn keywords "link" the member HDU back to its Grouping table. Note that a member HDU need not reside in the same FITS file as its grouping table, and that a given HDU may be referenced by up to 999 grouping tables simultaneously. Grouping tables are implemented as FITS binary tables with up to six pre-defined column TTYPEn values: 'MEMBER\_XTENSION', 'MEMBER\_NAME', 'MEMBER\_VERSION', 'MEMBER\_POSITION', 'MEMBER\_URI\_TYPE' and 'MEMBER\_LOCATION'. The first three columns allow member HDUs to be identified by reference to their XTENSION, EXTNAME and EXTVER keyword values. The fourth column allows member HDUs to be identified by HDU position within their FITS file. The last two columns identify the FITS file in which the member HDU resides, if different from the grouping table FITS file. Additional user defined "auxiliary" columns may also be included with any grouping table. When a grouping table is copied or modified the presence of auxiliary columns is always taken into account by the grouping support functions; however, the grouping support functions cannot directly make use of this data. If a grouping table column is defined but the corresponding member HDU information is unavailable then a null value of the appropriate data type is inserted in the column field. Integer columns (MEMBER\_POSITION, MEMBER\_VERSION) are defined with a TNULLn value of zero (0). Character field columns (MEMBER\_XTENSION, MEMBER\_NAME, MEMBER\_URI\_TYPE, MEMBER\_LOCATION) utilize an ASCII null character to denote a null field value. The grouping support functions belong to two basic categories: those that work with grouping table HDUs (ffgt**) and those that work with member HDUs (ffgm**). Two functions, fits\_copy\_group() and fits\_remove\_group(), have the option to recursively copy/delete entire groups. Care should be taken when employing these functions in recursive mode as poorly defined groups could cause unpredictable results. The problem of a grouping table directly or indirectly referencing itself (thus creating an infinite loop) is protected against; in fact, neither function will attempt to copy or delete an HDU twice. \section{Grouping Table Routines} \begin{description} \item[1 ]Create (append) a grouping table at the end of the current FITS file pointed to by fptr. The grpname parameter provides the grouping table name (GRPNAME keyword value) and may be set to NULL if no group name is to be specified. The grouptype parameter specifies the desired structure of the grouping table and may take on the values: GT\_ID\_ALL\_URI (all columns created), GT\_ID\_REF (ID by reference columns), GT\_ID\_POS (ID by position columns), GT\_ID\_ALL (ID by reference and position columns), GT\_ID\_REF\_URI (ID by reference and FITS file URI columns), and GT\_ID\_POS\_URI (ID by position and FITS file URI columns). \label{ffgtcr} \end{description} \begin{verbatim} int fits_create_group / ffgtcr (fitsfile *fptr, char *grpname, int grouptype, > int *status) \end{verbatim} \begin{description} \item[2 ]Create (insert) a grouping table just after the CHDU of the current FITS file pointed to by fptr. All HDUs below the the insertion point will be shifted downwards to make room for the new HDU. The grpname parameter provides the grouping table name (GRPNAME keyword value) and may be set to NULL if no group name is to be specified. The grouptype parameter specifies the desired structure of the grouping table and may take on the values: GT\_ID\_ALL\_URI (all columns created), GT\_ID\_REF (ID by reference columns), GT\_ID\_POS (ID by position columns), GT\_ID\_ALL (ID by reference and position columns), GT\_ID\_REF\_URI (ID by reference and FITS file URI columns), and GT\_ID\_POS\_URI (ID by position and FITS file URI columns) \label{ffgtis}. \end{description} \begin{verbatim} int fits_insert_group / ffgtis (fitsfile *fptr, char *grpname, int grouptype, > int *status) \end{verbatim} \begin{description} \item[3 ]Change the structure of an existing grouping table pointed to by gfptr. The grouptype parameter (see fits\_create\_group() for valid parameter values) specifies the new structure of the grouping table. This function only adds or removes grouping table columns, it does not add or delete group members (i.e., table rows). If the grouping table already has the desired structure then no operations are performed and function simply returns with a (0) success status code. If the requested structure change creates new grouping table columns, then the column values for all existing members will be filled with the null values appropriate to the column type. \label{ffgtch} \end{description} \begin{verbatim} int fits_change_group / ffgtch (fitsfile *gfptr, int grouptype, > int *status) \end{verbatim} \begin{description} \item[4 ]Remove the group defined by the grouping table pointed to by gfptr, and optionally all the group member HDUs. The rmopt parameter specifies the action to be taken for all members of the group defined by the grouping table. Valid values are: OPT\_RM\_GPT (delete only the grouping table) and OPT\_RM\_ALL (recursively delete all HDUs that belong to the group). Any groups containing the grouping table gfptr as a member are updated, and if rmopt == OPT\_RM\_GPT all members have their GRPIDn and GRPLCn keywords updated accordingly. If rmopt == OPT\_RM\_ALL, then other groups that contain the deleted members of gfptr are updated to reflect the deletion accordingly. \label{ffgtrm} \end{description} \begin{verbatim} int fits_remove_group / ffgtrm (fitsfile *gfptr, int rmopt, > int *status) \end{verbatim} \begin{description} \item[5 ]Copy (append) the group defined by the grouping table pointed to by infptr, and optionally all group member HDUs, to the FITS file pointed to by outfptr. The cpopt parameter specifies the action to be taken for all members of the group infptr. Valid values are: OPT\_GCP\_GPT (copy only the grouping table) and OPT\_GCP\_ALL (recursively copy ALL the HDUs that belong to the group defined by infptr). If the cpopt == OPT\_GCP\_GPT then the members of infptr have their GRPIDn and GRPLCn keywords updated to reflect the existence of the new grouping table outfptr, since they now belong to the new group. If cpopt == OPT\_GCP\_ALL then the new grouping table outfptr only contains pointers to the copied member HDUs and not the original member HDUs of infptr. Note that, when cpopt == OPT\_GCP\_ALL, all members of the group defined by infptr will be copied to a single FITS file pointed to by outfptr regardless of their file distribution in the original group. \label{ffgtcp} \end{description} \begin{verbatim} int fits_copy_group / ffgtcp (fitsfile *infptr, fitsfile *outfptr, int cpopt, > int *status) \end{verbatim} \begin{description} \item[6 ] Merge the two groups defined by the grouping table HDUs infptr and outfptr by combining their members into a single grouping table. All member HDUs (rows) are copied from infptr to outfptr. If mgopt == OPT\_MRG\_COPY then infptr continues to exist unaltered after the merge. If the mgopt == OPT\_MRG\_MOV then infptr is deleted after the merge. In both cases, the GRPIDn and GRPLCn keywords of the member HDUs are updated accordingly. \label{ffgtmg} \end{description} \begin{verbatim} int fits_merge_groups / ffgtmg (fitsfile *infptr, fitsfile *outfptr, int mgopt, > int *status) \end{verbatim} \begin{description} \item[7 ]"Compact" the group defined by grouping table pointed to by gfptr. The compaction is achieved by merging (via fits\_merge\_groups()) all direct member HDUs of gfptr that are themselves grouping tables. The cmopt parameter defines whether the merged grouping table HDUs remain after merging (cmopt == OPT\_CMT\_MBR) or if they are deleted after merging (cmopt == OPT\_CMT\_MBR\_DEL). If the grouping table contains no direct member HDUs that are themselves grouping tables then this function does nothing. Note that this function is not recursive, i.e., only the direct member HDUs of gfptr are considered for merging. \label{ffgtcm} \end{description} \begin{verbatim} int fits_compact_group / ffgtcm (fitsfile *gfptr, int cmopt, > int *status) \end{verbatim} \begin{description} \item[8 ]Verify the integrity of the grouping table pointed to by gfptr to make sure that all group members are accessible and that all links to other grouping tables are valid. The firstfailed parameter returns the member ID (row number) of the first member HDU to fail verification (if positive value) or the first group link to fail (if negative value). If gfptr is successfully verified then firstfailed contains a return value of 0. \label{ffgtvf} \end{description} \begin{verbatim} int fits_verify_group / ffgtvf (fitsfile *gfptr, > long *firstfailed, int *status) \end{verbatim} \begin{description} \item[9 ] Open a grouping table that contains the member HDU pointed to by mfptr. The grouping table to open is defined by the grpid parameter, which contains the keyword index value of the GRPIDn/GRPLCn keyword(s) that link the member HDU mfptr to the grouping table. If the grouping table resides in a file other than the member HDUs file then an attempt is first made to open the file readwrite, and failing that readonly. A pointer to the opened grouping table HDU is returned in gfptr. Note that it is possible, although unlikely and undesirable, for the GRPIDn/GRPLCn keywords in a member HDU header to be non-continuous, e.g., GRPID1, GRPID2, GRPID5, GRPID6. In such cases, the grpid index value specified in the function call shall identify the (grpid)th GRPID value. In the above example, if grpid == 3, then the group specified by GRPID5 would be opened. \label{ffgtop} \end{description} \begin{verbatim} int fits_open_group / ffgtop (fitsfile *mfptr, int grpid, > fitsfile **gfptr, int *status) \end{verbatim} \begin{description} \item[10] Add a member HDU to an existing grouping table pointed to by gfptr. The member HDU may either be pointed to mfptr (which must be positioned to the member HDU) or, if mfptr == NULL, identified by the hdupos parameter (the HDU position number, Primary array == 1) if both the grouping table and the member HDU reside in the same FITS file. The new member HDU shall have the appropriate GRPIDn and GRPLCn keywords created in its header. Note that if the member HDU is already a member of the group then it will not be added a second time. \label{ffgtam} \end{description} \begin{verbatim} int fits_add_group_member / ffgtam (fitsfile *gfptr, fitsfile *mfptr, int hdupos, > int *status) \end{verbatim} \section{Group Member Routines} \begin{description} \item[1 ] Return the number of member HDUs in a grouping table gfptr. The number of member HDUs is just the NAXIS2 value (number of rows) of the grouping table. \label{ffgtnm} \end{description} \begin{verbatim} int fits_get_num_members / ffgtnm (fitsfile *gfptr, > long *nmembers, int *status) \end{verbatim} \begin{description} \item[2 ] Return the number of groups to which the HDU pointed to by mfptr is linked, as defined by the number of GRPIDn/GRPLCn keyword records that appear in its header. Note that each time this function is called, the indices of the GRPIDn/GRPLCn keywords are checked to make sure they are continuous (ie no gaps) and are re-enumerated to eliminate gaps if found. \label{ffgmng} \end{description} \begin{verbatim} int fits_get_num_groups / ffgmng (fitsfile *mfptr, > long *nmembers, int *status) \end{verbatim} \begin{description} \item[3 ] Open a member of the grouping table pointed to by gfptr. The member to open is identified by its row number within the grouping table as given by the parameter 'member' (first member == 1) . A fitsfile pointer to the opened member HDU is returned as mfptr. Note that if the member HDU resides in a FITS file different from the grouping table HDU then the member file is first opened readwrite and, failing this, opened readonly. \label{ffgmop} \end{description} \begin{verbatim} int fits_open_member / ffgmop (fitsfile *gfptr, long member, > fitsfile **mfptr, int *status) \end{verbatim} \begin{description} \item[4 ]Copy (append) a member HDU of the grouping table pointed to by gfptr. The member HDU is identified by its row number within the grouping table as given by the parameter 'member' (first member == 1). The copy of the group member HDU will be appended to the FITS file pointed to by mfptr, and upon return mfptr shall point to the copied member HDU. The cpopt parameter may take on the following values: OPT\_MCP\_ADD which adds a new entry in gfptr for the copied member HDU, OPT\_MCP\_NADD which does not add an entry in gfptr for the copied member, and OPT\_MCP\_REPL which replaces the original member entry with the copied member entry. \label{ffgmcp} \end{description} \begin{verbatim} int fits_copy_member / ffgmcp (fitsfile *gfptr, fitsfile *mfptr, long member, int cpopt, > int *status) \end{verbatim} \begin{description} \item[5 ]Transfer a group member HDU from the grouping table pointed to by infptr to the grouping table pointed to by outfptr. The member HDU to transfer is identified by its row number within infptr as specified by the parameter 'member' (first member == 1). If tfopt == OPT\_MCP\_ADD then the member HDU is made a member of outfptr and remains a member of infptr. If tfopt == OPT\_MCP\_MOV then the member HDU is deleted from infptr after the transfer to outfptr. \label{ffgmtf} \end{description} \begin{verbatim} int fits_transfer_member / ffgmtf (fitsfile *infptr, fitsfile *outfptr, long member, int tfopt, > int *status) \end{verbatim} \begin{description} \item[6 ]Remove a member HDU from the grouping table pointed to by gfptr. The member HDU to be deleted is identified by its row number in the grouping table as specified by the parameter 'member' (first member == 1). The rmopt parameter may take on the following values: OPT\_RM\_ENTRY which removes the member HDU entry from the grouping table and updates the member's GRPIDn/GRPLCn keywords, and OPT\_RM\_MBR which removes the member HDU entry from the grouping table and deletes the member HDU itself. \label{ffgmrm} \end{description} \begin{verbatim} int fits_remove_member / ffgmrm (fitsfile *gfptr, long member, int rmopt, > int *status) \end{verbatim} \chapter{ Specialized CFITSIO Interface Routines } The basic interface routines described previously are recommended for most uses, but the routines described in this chapter are also available if necessary. Some of these routines perform more specialized function that cannot easily be done with the basic interface routines while others duplicate the functionality of the basic routines but have a slightly different calling sequence. See Appendix B for the definition of each function parameter. \section{FITS File Access Routines} \begin{description} \item[1 ] Open an existing FITS file residing in core computer memory. This routine is analogous to fits\_open\_file. The 'filename' is currently ignored by this routine and may be any arbitrary string. In general, the application must have preallocated an initial block of memory to hold the FITS file prior to calling this routine: 'memptr' points to the starting address and 'memsize' gives the initial size of the block of memory. 'mem\_realloc' is a pointer to an optional function that CFITSIO can call to allocate additional memory, if needed (only if mode = READWRITE), and is modeled after the standard C 'realloc' function; a null pointer may be given if the initial allocation of memory is all that will be required (e.g., if the file is opened with mode = READONLY). The 'deltasize' parameter may be used to suggest a minimum amount of additional memory that should be allocated during each call to the memory reallocation function. By default, CFITSIO will reallocate enough additional space to hold the entire currently defined FITS file (as given by the NAXISn keywords) or 1 FITS block (= 2880 bytes), which ever is larger. Values of deltasize less than 2880 will be ignored. Since the memory reallocation operation can be computationally expensive, allocating a larger initial block of memory, and/or specifying a larger deltasize value may help to reduce the number of reallocation calls and make the application program run faster. Note that values of the memptr and memsize pointers will be updated by CFITSIO if the location or size of the FITS file in memory should change as a result of allocating more memory. \label{ffomem} \end{description} \begin{verbatim} int fits_open_memfile / ffomem (fitsfile **fptr, const char *filename, int mode, void **memptr, size_t *memsize, size_t deltasize, void *(*mem_realloc)(void *p, size_t newsize), int *status) \end{verbatim} \begin{description} \item[2 ] Create a new FITS file residing in core computer memory. This routine is analogous to fits\_create\_file. In general, the application must have preallocated an initial block of memory to hold the FITS file prior to calling this routine: 'memptr' points to the starting address and 'memsize' gives the initial size of the block of memory. 'mem\_realloc' is a pointer to an optional function that CFITSIO can call to allocate additional memory, if needed, and is modeled after the standard C 'realloc' function; a null pointer may be given if the initial allocation of memory is all that will be required. The 'deltasize' parameter may be used to suggest a minimum amount of additional memory that should be allocated during each call to the memory reallocation function. By default, CFITSIO will reallocate enough additional space to hold 1 FITS block (= 2880 bytes) and values of deltasize less than 2880 will be ignored. Since the memory reallocation operation can be computationally expensive, allocating a larger initial block of memory, and/or specifying a larger deltasize value may help to reduce the number of reallocation calls and make the application program run faster. Note that values of the memptr and memsize pointers will be updated by CFITSIO if the location or size of the FITS file in memory should change as a result of allocating more memory. \label{ffimem} \end{description} \begin{verbatim} int fits_create_memfile / ffimem (fitsfile **fptr, void **memptr, size_t *memsize, size_t deltasize, void *(*mem_realloc)(void *p, size_t newsize), int *status) \end{verbatim} \begin{description} \item[3 ] Reopen a FITS file that was previously opened with fits\_open\_file or fits\_create\_file. The new fitsfile pointer may then be treated as a separate file, and one may simultaneously read or write to 2 (or more) different extensions in the same file. The fits\_open\_file routine (above) automatically detects cases where a previously opened file is being opened again, and then internally call fits\_reopen\_file, so programs should rarely need to explicitly call this routine. \label{ffreopen} \end{description} \begin{verbatim} int fits_reopen_file / ffreopen (fitsfile *openfptr, fitsfile **newfptr, > int *status) \end{verbatim} \begin{description} \item[4 ] Create a new FITS file, using a template file to define its initial size and structure. The template may be another FITS HDU or an ASCII template file. If the input template file name pointer is null, then this routine behaves the same as fits\_create\_file. The currently supported format of the ASCII template file is described under the fits\_parse\_template routine (in the general Utilities section) \label{fftplt} \end{description} \begin{verbatim} int fits_create_template / fftplt (fitsfile **fptr, char *filename, char *tpltfile > int *status) \end{verbatim} \begin{description} \item[5 ] Parse the input filename or URL into its component parts, namely: \begin{itemize} \item the file type (file://, ftp://, http://, etc), \item the base input file name, \item the name of the output file that the input file is to be copied to prior to opening, \item the HDU or extension specification, \item the filtering specifier, \item the binning specifier, \item the column specifier, \item and the image pixel filtering specifier. \end{itemize} A null pointer (0) may be be specified for any of the output string arguments that are not needed. Null strings will be returned for any components that are not present in the input file name. The calling routine must allocate sufficient memory to hold the returned character strings. Allocating the string lengths equal to FLEN\_FILENAME is guaranteed to be safe. These routines are mainly for internal use by other CFITSIO routines. \label{ffiurl} \end{description} \begin{verbatim} int fits_parse_input_url / ffiurl (char *filename, > char *filetype, char *infile, char *outfile, char *extspec, char *filter, char *binspec, char *colspec, int *status) int fits_parse_input_filename / ffifile (char *filename, > char *filetype, char *infile, char *outfile, char *extspec, char *filter, char *binspec, char *colspec, char *pixspec, int *status) \end{verbatim} \begin{description} \item[6 ] Parse the input filename and return the HDU number that would be moved to if the file were opened with fits\_open\_file. The returned HDU number begins with 1 for the primary array, so for example, if the input filename = `myfile.fits[2]' then hdunum = 3 will be returned. CFITSIO does not open the file to check if the extension actually exists if an extension number is specified. If an extension name is included in the file name specification (e.g. `myfile.fits[EVENTS]' then this routine will have to open the FITS file and look for the position of the named extension, then close file again. This is not possible if the file is being read from the stdin stream, and an error will be returned in this case. If the filename does not specify an explicit extension (e.g. 'myfile.fits') then hdunum = -99 will be returned, which is functionally equivalent to hdunum = 1. This routine is mainly used for backward compatibility in the ftools software package and is not recommended for general use. It is generally better and more efficient to first open the FITS file with fits\_open\_file, then use fits\_get\_hdu\_num to determine which HDU in the file has been opened, rather than calling fits\_parse\_input\_url followed by a call to fits\_open\_file. \label{ffextn} \end{description} \begin{verbatim} int fits_parse_extnum / ffextn (char *filename, > int *hdunum, int *status) \end{verbatim} \begin{description} \item[7 ]Parse the input file name and return the root file name. The root name includes the file type if specified, (e.g. 'ftp://' or 'http://') and the full path name, to the extent that it is specified in the input filename. It does not include the HDU name or number, or any filtering specifications. The calling routine must allocate sufficient memory to hold the returned rootname character string. Allocating the length equal to FLEN\_FILENAME is guaranteed to be safe. \label{ffrtnm} \end{description} \begin{verbatim} int fits_parse_rootname / ffrtnm (char *filename, > char *rootname, int *status); \end{verbatim} \begin{description} \item[8 ]Test if the input file or a compressed version of the file (with a .gz, .Z, .z, or .zip extension) exists on disk. The returned value of the 'exists' parameter will have 1 of the 4 following values: \begin{verbatim} 2: the file does not exist, but a compressed version does exist 1: the disk file does exist 0: neither the file nor a compressed version of the file exist -1: the input file name is not a disk file (could be a ftp, http, smem, or mem file, or a file piped in on the STDIN stream) \end{verbatim} \label{ffexist} \end{description} \begin{verbatim} int fits_file_exists / ffexist (char *filename, > int *exists, int *status); \end{verbatim} \begin{description} \item[9 ]Flush any internal buffers of data to the output FITS file. These routines rarely need to be called, but can be useful in cases where other processes need to access the same FITS file in real time, either on disk or in memory. These routines also help to ensure that if the application program subsequently aborts then the FITS file will have been closed properly. The first routine, fits\_flush\_file is more rigorous and completely closes, then reopens, the current HDU, before flushing the internal buffers, thus ensuring that the output FITS file is identical to what would be produced if the FITS was closed at that point (i.e., with a call to fits\_close\_file). The second routine, fits\_flush\_buffer simply flushes the internal CFITSIO buffers of data to the output FITS file, without updating and closing the current HDU. This is much faster, but there may be circumstances where the flushed file does not completely reflect the final state of the file as it will exist when the file is actually closed. A typical use of these routines would be to flush the state of a FITS table to disk after each row of the table is written. It is recommend that fits\_flush\_file be called after the first row is written, then fits\_flush\_buffer may be called after each subsequent row is written. Note that this latter routine will not automatically update the NAXIS2 keyword which records the number of rows of data in the table, so this keyword must be explicitly updated by the application program after each row is written. \label{ffflus} \end{description} \begin{verbatim} int fits_flush_file / ffflus (fitsfile *fptr, > int *status) int fits_flush_buffer / ffflsh (fitsfile *fptr, 0, > int *status) (Note: The second argument must be 0). \end{verbatim} \begin{description} \item[10 ] Wrapper function for global initialization of the libcurl library used when accessing files with the HTTPS protocol. If an HTTPS file transfer is to be performed, it is recommended that you call this once near the start of your program before any file\_open calls, and before creating any threads. This is NOT THREAD-SAFE. Returns 0 if initialization succeeded. A corresponding call to fits\_cleanup\_https should be made later. \label{ffihtps} \end{description} \begin{verbatim} int fits_init_https / ffihtps () \end{verbatim} \begin{description} \item[11 ] Wrapper function for global cleanup of the libcurl library used when accessing files with the HTTPS protocol. This is meant to be used in combination with fits\_init\_https, and should be called after all HTTPS file accessing is completed, and after all threads are completed. This is NOT THREAD-SAFE. Returns 0 upon successful cleanup. \label{ffchtps} \end{description} \begin{verbatim} int fits_cleanup_https / ffchtps () \end{verbatim} \begin{description} \item[12 ] Toggle the verbosity of the libcurl library diagnostic output when accessing files with the HTTPS protocol. 'flag' = 1 turns the output on, 0 turns it off (the default). This is NOT THREAD-SAFE. \label{ffvhtps} \end{description} \begin{verbatim} void fits_verbose_https / ffvhtps (int flag) \end{verbatim} \section{HDU Access Routines} \begin{description} \item[1 ] Get the byte offsets in the FITS file to the start of the header and the start and end of the data in the CHDU. The difference between headstart and dataend equals the size of the CHDU. If the CHDU is the last HDU in the file, then dataend is also equal to the size of the entire FITS file. Null pointers may be input for any of the address parameters if their values are not needed. \label{ffghad} \end{description} \begin{verbatim} int fits_get_hduaddr / ffghad (only supports files up to 2.1 GB in size) (fitsfile *fptr, > long *headstart, long *datastart, long *dataend, int *status) int fits_get_hduaddrll / ffghadll (supports large files) (fitsfile *fptr, > LONGLONG *headstart, LONGLONG *datastart, LONGLONG *dataend, int *status) \end{verbatim} \begin{description} \item[2 ] Create (append) a new empty HDU at the end of the FITS file. This is now the CHDU but it is completely empty and has no header keywords. It is recommended that fits\_create\_img or fits\_create\_tbl be used instead of this routine. \label{ffcrhd} \end{description} \begin{verbatim} int fits_create_hdu / ffcrhd (fitsfile *fptr, > int *status) \end{verbatim} \begin{description} \item[3 ] Insert a new IMAGE extension immediately following the CHDU, or insert a new Primary Array at the beginning of the file. Any following extensions in the file will be shifted down to make room for the new extension. If the CHDU is the last HDU in the file then the new image extension will simply be appended to the end of the file. One can force a new primary array to be inserted at the beginning of the FITS file by setting status = PREPEND\_PRIMARY prior to calling the routine. In this case the old primary array will be converted to an IMAGE extension. The new extension (or primary array) will become the CHDU. Refer to Chapter 9 for a list of pre-defined bitpix values. \label{ffiimg} \end{description} \begin{verbatim} int fits_insert_img / ffiimg (fitsfile *fptr, int bitpix, int naxis, long *naxes, > int *status) int fits_insert_imgll / ffiimgll (fitsfile *fptr, int bitpix, int naxis, LONGLONG *naxes, > int *status) \end{verbatim} \begin{description} \item[4 ] Insert a new ASCII or binary table extension immediately following the CHDU. Any following extensions will be shifted down to make room for the new extension. If there are no other following extensions then the new table extension will simply be appended to the end of the file. If the FITS file is currently empty then this routine will create a dummy primary array before appending the table to it. The new extension will become the CHDU. The tunit and extname parameters are optional and a null pointer may be given if they are not defined. When inserting an ASCII table with fits\_insert\_atbl, a null pointer may given for the *tbcol parameter in which case each column of the table will be separated by a single space character. Similarly, if the input value of rowlen is 0, then CFITSIO will calculate the default rowlength based on the tbcol and ttype values. Under normal circumstances, the nrows paramenter should have a value of 0; CFITSIO will automatically update the number of rows as data is written to the table. When inserting a binary table with fits\_insert\_btbl, if there are following extensions in the file and if the table contains variable length array columns then pcount must specify the expected final size of the data heap, otherwise pcount must = 0. \label{ffitab} \label{ffibin} \end{description} \begin{verbatim} int fits_insert_atbl / ffitab (fitsfile *fptr, LONGLONG rowlen, LONGLONG nrows, int tfields, char *ttype[], long *tbcol, char *tform[], char *tunit[], char *extname, > int *status) int fits_insert_btbl / ffibin (fitsfile *fptr, LONGLONG nrows, int tfields, char **ttype, char **tform, char **tunit, char *extname, long pcount, > int *status) \end{verbatim} \begin{description} \item[5 ] Modify the size, dimensions, and/or data type of the current primary array or image extension. If the new image, as specified by the input arguments, is larger than the current existing image in the FITS file then zero fill data will be inserted at the end of the current image and any following extensions will be moved further back in the file. Similarly, if the new image is smaller than the current image then any following extensions will be shifted up towards the beginning of the FITS file and the image data will be truncated to the new size. This routine rewrites the BITPIX, NAXIS, and NAXISn keywords with the appropriate values for the new image. \label{ffrsim} \end{description} \begin{verbatim} int fits_resize_img / ffrsim (fitsfile *fptr, int bitpix, int naxis, long *naxes, > int *status) int fits_resize_imgll / ffrsimll (fitsfile *fptr, int bitpix, int naxis, LONGLONG *naxes, > int *status) \end{verbatim} \begin{description} \item[6 ] Copy the data (and not the header) from the CHDU associated with infptr to the CHDU associated with outfptr. This will overwrite any data previously in the output CHDU. This low level routine is used by fits\_copy\_hdu, but it may also be useful in certain application programs that want to copy the data from one FITS file to another but also want to modify the header keywords. The required FITS header keywords which define the structure of the HDU must be written to the output CHDU before calling this routine. \label{ffcpdt} \end{description} \begin{verbatim} int fits_copy_data / ffcpdt (fitsfile *infptr, fitsfile *outfptr, > int *status) \end{verbatim} \begin{description} \item[7 ] Read or write a specified number of bytes starting at the specified byte offset from the start of the extension data unit. These low level routine are intended mainly for accessing the data in non-standard, conforming extensions, and should not be used for standard IMAGE, TABLE, or BINTABLE extensions. \label{ffgextn} \end{description} \begin{verbatim} int fits_read_ext / ffgextn (fitsfile *fptr, LONGLONG offset, LONGLONG nbytes, void *buffer) int fits_write_ext / ffpextn (fitsfile *fptr, LONGLONG offset, LONGLONG nbytes, void *buffer) \end{verbatim} \begin{description} \item[8 ] This routine forces CFITSIO to rescan the current header keywords that define the structure of the HDU (such as the NAXIS and BITPIX keywords) so that it reinitializes the internal buffers that describe the HDU structure. This routine is useful for reinitializing the structure of an HDU if any of the required keywords (e.g., NAXISn) have been modified. In practice it should rarely be necessary to call this routine because CFITSIO internally calls it in most situations. \label{ffrdef} \end{description} \begin{verbatim} int fits_set_hdustruc / ffrdef (fitsfile *fptr, > int *status) (DEPRECATED) \end{verbatim} \section{Specialized Header Keyword Routines} \subsection{Header Information Routines} \begin{description} \item[1 ] Reserve space in the CHU for MOREKEYS more header keywords. This routine may be called to allocate space for additional keywords at the time the header is created (prior to writing any data). CFITSIO can dynamically add more space to the header when needed, however it is more efficient to preallocate the required space if the size is known in advance. \label{ffhdef} \end{description} \begin{verbatim} int fits_set_hdrsize / ffhdef (fitsfile *fptr, int morekeys, > int *status) \end{verbatim} \begin{description} \item[2 ] Return the number of keywords in the header (not counting the END keyword) and the current position in the header. The position is the number of the keyword record that will be read next (or one greater than the position of the last keyword that was read). A value of 1 is returned if the pointer is positioned at the beginning of the header. \label{ffghps} \end{description} \begin{verbatim} int fits_get_hdrpos / ffghps (fitsfile *fptr, > int *keysexist, int *keynum, int *status) \end{verbatim} \subsection{Read and Write the Required Keywords} \begin{description} \item[1 ] Write the required extension header keywords into the CHU. These routines are not required, and instead the appropriate header may be constructed by writing each individual keyword in the proper sequence. The simpler fits\_write\_imghdr routine is equivalent to calling fits\_write\_grphdr with the default values of simple = TRUE, pcount = 0, gcount = 1, and extend = TRUE. The PCOUNT, GCOUNT and EXTEND keywords are not required in the primary header and are only written if pcount is not equal to zero, gcount is not equal to zero or one, and if extend is TRUE, respectively. When writing to an IMAGE extension, the SIMPLE and EXTEND parameters are ignored. It is recommended that fits\_create\_image or fits\_create\_tbl be used instead of these routines to write the required header keywords. The general fits\_write\_exthdr routine may be used to write the header of any conforming FITS extension. \label{ffphpr} \label{ffphps} \end{description} \begin{verbatim} int fits_write_imghdr / ffphps (fitsfile *fptr, int bitpix, int naxis, long *naxes, > int *status) int fits_write_imghdrll / ffphpsll (fitsfile *fptr, int bitpix, int naxis, LONGLONG *naxes, > int *status) int fits_write_grphdr / ffphpr (fitsfile *fptr, int simple, int bitpix, int naxis, long *naxes, LONGLONG pcount, LONGLONG gcount, int extend, > int *status) int fits_write_grphdrll / ffphprll (fitsfile *fptr, int simple, int bitpix, int naxis, LONGLONG *naxes, LONGLONG pcount, LONGLONG gcount, int extend, > int *status) int fits_write_exthdr /ffphext (fitsfile *fptr, char *xtension, int bitpix, int naxis, long *naxes, LONGLONG pcount, LONGLONG gcount, > int *status) \end{verbatim} \begin{description} \item[2 ] Write the ASCII table header keywords into the CHU. The optional TUNITn and EXTNAME keywords are written only if the input pointers are not null. A null pointer may given for the *tbcol parameter in which case a single space will be inserted between each column of the table. Similarly, if rowlen is given = 0, then CFITSIO will calculate the default rowlength based on the tbcol and ttype values. \label{ffphtb} \end{description} \begin{verbatim} int fits_write_atblhdr / ffphtb (fitsfile *fptr, LONGLONG rowlen, LONGLONG nrows, int tfields, char **ttype, long *tbcol, char **tform, char **tunit, char *extname, > int *status) \end{verbatim} \begin{description} \item[3 ] Write the binary table header keywords into the CHU. The optional TUNITn and EXTNAME keywords are written only if the input pointers are not null. The pcount parameter, which specifies the size of the variable length array heap, should initially = 0; CFITSIO will automatically update the PCOUNT keyword value if any variable length array data is written to the heap. The TFORM keyword value for variable length vector columns should have the form 'Pt(len)' or '1Pt(len)' where `t' is the data type code letter (A,I,J,E,D, etc.) and `len' is an integer specifying the maximum length of the vectors in that column (len must be greater than or equal to the longest vector in the column). If `len' is not specified when the table is created (e.g., the input TFORMn value is just '1Pt') then CFITSIO will scan the column when the table is first closed and will append the maximum length to the TFORM keyword value. Note that if the table is subsequently modified to increase the maximum length of the vectors then the modifying program is responsible for also updating the TFORM keyword value. \label{ffphbn} \end{description} \begin{verbatim} int fits_write_btblhdr / ffphbn (fitsfile *fptr, LONGLONG nrows, int tfields, char **ttype, char **tform, char **tunit, char *extname, LONGLONG pcount, > int *status) \end{verbatim} \begin{description} \item[4 ] Read the required keywords from the CHDU (image or table). When reading from an IMAGE extension the SIMPLE and EXTEND parameters are ignored. A null pointer may be supplied for any of the returned parameters that are not needed. \label{ffghpr} \label{ffghtb} \label{ffghbn} \end{description} \begin{verbatim} int fits_read_imghdr / ffghpr (fitsfile *fptr, int maxdim, > int *simple, int *bitpix, int *naxis, long *naxes, long *pcount, long *gcount, int *extend, int *status) int fits_read_imghdrll / ffghprll (fitsfile *fptr, int maxdim, > int *simple, int *bitpix, int *naxis, LONGLONG *naxes, long *pcount, long *gcount, int *extend, int *status) int fits_read_atblhdr / ffghtb (fitsfile *fptr,int maxdim, > long *rowlen, long *nrows, int *tfields, char **ttype, LONGLONG *tbcol, char **tform, char **tunit, char *extname, int *status) int fits_read_atblhdrll / ffghtbll (fitsfile *fptr,int maxdim, > LONGLONG *rowlen, LONGLONG *nrows, int *tfields, char **ttype, long *tbcol, char **tform, char **tunit, char *extname, int *status) int fits_read_btblhdr / ffghbn (fitsfile *fptr, int maxdim, > long *nrows, int *tfields, char **ttype, char **tform, char **tunit, char *extname, long *pcount, int *status) int fits_read_btblhdrll / ffghbnll (fitsfile *fptr, int maxdim, > LONGLONG *nrows, int *tfields, char **ttype, char **tform, char **tunit, char *extname, long *pcount, int *status) \end{verbatim} \subsection{Write Keyword Routines} These routines simply append a new keyword to the header and do not check to see if a keyword with the same name already exists. In general it is preferable to use the fits\_update\_key routine to ensure that the same keyword is not written more than once to the header. See Appendix B for the definition of the parameters used in these routines. \begin{description} \item[1 ] Write (append) a new keyword of the appropriate data type into the CHU. A null pointer may be entered for the comment parameter, which will cause the comment field of the keyword to be left blank. The flt, dbl, cmp, and dblcmp versions of this routine have the added feature that if the 'decimals' parameter is negative, then the 'G' display format rather then the 'E' format will be used when constructing the keyword value, taking the absolute value of 'decimals' for the precision. This will suppress trailing zeros, and will use a fixed format rather than an exponential format, depending on the magnitude of the value. \label{ffpkyx} \end{description} \begin{verbatim} int fits_write_key_str / ffpkys (fitsfile *fptr, char *keyname, char *value, char *comment, > int *status) int fits_write_key_[log, lng] / ffpky[lj] (fitsfile *fptr, char *keyname, DTYPE numval, char *comment, > int *status) int fits_write_key_[flt, dbl, fixflg, fixdbl] / ffpky[edfg] (fitsfile *fptr, char *keyname, DTYPE numval, int decimals, char *comment, > int *status) int fits_write_key_[cmp, dblcmp, fixcmp, fixdblcmp] / ffpk[yc,ym,fc,fm] (fitsfile *fptr, char *keyname, DTYPE *numval, int decimals, char *comment, > int *status) \end{verbatim} \begin{description} \item[2 ] Write (append) a string valued keyword into the CHU which may be longer than 68 characters in length. This uses the Long String Keyword convention that is described in the`Local FITS Conventions' section in Chapter 4. Since this uses a non-standard FITS convention to encode the long keyword string, programs which use this routine should also call the fits\_write\_key\_longwarn routine to add some COMMENT keywords to warn users of the FITS file that this convention is being used. The fits\_write\_key\_longwarn routine also writes a keyword called LONGSTRN to record the version of the longstring convention that has been used, in case a new convention is adopted at some point in the future. If the LONGSTRN keyword is already present in the header, then fits\_write\_key\_longwarn will simply return without doing anything. \label{ffpkls} \label{ffplsw} \end{description} \begin{verbatim} int fits_write_key_longstr / ffpkls (fitsfile *fptr, char *keyname, char *longstr, char *comment, > int *status) int fits_write_key_longwarn / ffplsw (fitsfile *fptr, > int *status) \end{verbatim} \begin{description} \item[3 ] Write (append) a numbered sequence of keywords into the CHU. The starting index number (nstart) must be greater than 0. One may append the same comment to every keyword (and eliminate the need to have an array of identical comment strings, one for each keyword) by including the ampersand character as the last non-blank character in the (first) COMMENTS string parameter. This same string will then be used for the comment field in all the keywords. One may also enter a null pointer for the comment parameter to leave the comment field of the keyword blank. \label{ffpknx} \end{description} \begin{verbatim} int fits_write_keys_str / ffpkns (fitsfile *fptr, char *keyroot, int nstart, int nkeys, char **value, char **comment, > int *status) int fits_write_keys_[log, lng] / ffpkn[lj] (fitsfile *fptr, char *keyroot, int nstart, int nkeys, DTYPE *numval, char **comment, int *status) int fits_write_keys_[flt, dbl, fixflg, fixdbl] / ffpkne[edfg] (fitsfile *fptr, char *keyroot, int nstart, int nkey, DTYPE *numval, int decimals, char **comment, > int *status) \end{verbatim} \begin{description} \item[4 ]Copy an indexed keyword from one HDU to another, modifying the index number of the keyword name in the process. For example, this routine could read the TLMIN3 keyword from the input HDU (by giving keyroot = `TLMIN' and innum = 3) and write it to the output HDU with the keyword name TLMIN4 (by setting outnum = 4). If the input keyword does not exist, then this routine simply returns without indicating an error. \label{ffcpky} \end{description} \begin{verbatim} int fits_copy_key / ffcpky (fitsfile *infptr, fitsfile *outfptr, int innum, int outnum, char *keyroot, > int *status) \end{verbatim} \begin{description} \item[5 ]Write (append) a `triple precision' keyword into the CHU in F28.16 format. The floating point keyword value is constructed by concatenating the input integer value with the input double precision fraction value (which must have a value between 0.0 and 1.0). The ffgkyt routine should be used to read this keyword value, because the other keyword reading routines will not preserve the full precision of the value. \label{ffpkyt} \end{description} \begin{verbatim} int fits_write_key_triple / ffpkyt (fitsfile *fptr, char *keyname, long intval, double frac, char *comment, > int *status) \end{verbatim} \begin{description} \item[6 ]Write keywords to the CHDU that are defined in an ASCII template file. The format of the template file is described under the fits\_parse\_template routine. \label{ffpktp} \end{description} \begin{verbatim} int fits_write_key_template / ffpktp (fitsfile *fptr, const char *filename, > int *status) \end{verbatim} \subsection{Insert Keyword Routines} These insert routines are somewhat less efficient than the `update' or `write' keyword routines because the following keywords in the header must be shifted down to make room for the inserted keyword. See Appendix B for the definition of the parameters used in these routines. \begin{description} \item[1 ] Insert a new keyword record into the CHU at the specified position (i.e., immediately preceding the (keynum)th keyword in the header.) \label{ffirec} \end{description} \begin{verbatim} int fits_insert_record / ffirec (fitsfile *fptr, int keynum, char *card, > int *status) \end{verbatim} \begin{description} \item[2 ] Insert a new keyword into the CHU. The new keyword is inserted immediately following the last keyword that has been read from the header. The `longstr' version has the same functionality as the `str' version except that it also supports the local long string keyword convention for strings longer than 68 characters. A null pointer may be entered for the comment parameter which will cause the comment field to be left blank. The flt, dbl, cmp, and dblcmp versions of this routine have the added feature that if the 'decimals' parameter is negative, then the 'G' display format rather then the 'E' format will be used when constructing the keyword value, taking the absolute value of 'decimals' for the precision. This will suppress trailing zeros, and will use a fixed format rather than an exponential format, depending on the magnitude of the value. \label{ffikyx} \end{description} \begin{verbatim} int fits_insert_card / ffikey (fitsfile *fptr, char *card, > int *status) int fits_insert_key_[str, longstr] / ffi[kys, kls] (fitsfile *fptr, char *keyname, char *value, char *comment, > int *status) int fits_insert_key_[log, lng] / ffiky[lj] (fitsfile *fptr, char *keyname, DTYPE numval, char *comment, > int *status) int fits_insert_key_[flt, fixflt, dbl, fixdbl] / ffiky[edfg] (fitsfile *fptr, char *keyname, DTYPE numval, int decimals, char *comment, > int *status) int fits_insert_key_[cmp, dblcmp, fixcmp, fixdblcmp] / ffik[yc,ym,fc,fm] (fitsfile *fptr, char *keyname, DTYPE *numval, int decimals, char *comment, > int *status) \end{verbatim} \begin{description} \item[3 ] Insert a new keyword with an undefined, or null, value into the CHU. The value string of the keyword is left blank in this case. \label{ffikyu} \end{description} \begin{verbatim} int fits_insert_key_null / ffikyu (fitsfile *fptr, char *keyname, char *comment, > int *status) \end{verbatim} \subsection{Read Keyword Routines} Wild card characters may be used when specifying the name of the keyword to be read. \begin{description} \item[1 ] Read a keyword value (with the appropriate data type) and comment from the CHU. If a NULL comment pointer is given on input, then the comment string will not be returned. If the value of the keyword is not defined (i.e., the value field is blank) then an error status = VALUE\_UNDEFINED will be returned and the input value will not be changed (except that ffgkys will reset the value to a null string). \label{ffgkyx} \label{ffgkls} \end{description} \begin{verbatim} int fits_read_key_str / ffgkys (fitsfile *fptr, char *keyname, > char *value, char *comment, int *status); NOTE: after calling the following routine, programs must explicitly free the memory allocated for 'longstr' after it is no longer needed by calling fits_free_memory. int fits_read_key_longstr / ffgkls (fitsfile *fptr, char *keyname, > char **longstr, char *comment, int *status) int fits_free_memory / fffree (char *longstr, > int *status); int fits_read_key_[log, lng, flt, dbl, cmp, dblcmp] / ffgky[ljedcm] (fitsfile *fptr, char *keyname, > DTYPE *numval, char *comment, int *status) int fits_read_key_lnglng / ffgkyjj (fitsfile *fptr, char *keyname, > LONGLONG *numval, char *comment, int *status) \end{verbatim} \begin{description} \item[2 ] Read a sequence of indexed keyword values (e.g., NAXIS1, NAXIS2, ...). The input starting index number (nstart) must be greater than 0. If the value of any of the keywords is not defined (i.e., the value field is blank) then an error status = VALUE\_UNDEFINED will be returned and the input value for the undefined keyword(s) will not be changed. These routines do not support wild card characters in the root name. If there are no indexed keywords in the header with the input root name then these routines do not return a non-zero status value and instead simply return nfound = 0. \label{ffgknx} \end{description} \begin{verbatim} int fits_read_keys_str / ffgkns (fitsfile *fptr, char *keyname, int nstart, int nkeys, > char **value, int *nfound, int *status) int fits_read_keys_[log, lng, flt, dbl] / ffgkn[ljed] (fitsfile *fptr, char *keyname, int nstart, int nkeys, > DTYPE *numval, int *nfound, int *status) \end{verbatim} \begin{description} \item[3 ] Read the value of a floating point keyword, returning the integer and fractional parts of the value in separate routine arguments. This routine may be used to read any keyword but is especially useful for reading the 'triple precision' keywords written by ffpkyt. \label{ffgkyt} \end{description} \begin{verbatim} int fits_read_key_triple / ffgkyt (fitsfile *fptr, char *keyname, > long *intval, double *frac, char *comment, int *status) \end{verbatim} \subsection{Modify Keyword Routines} These routines modify the value of an existing keyword. An error is returned if the keyword does not exist. Wild card characters may be used when specifying the name of the keyword to be modified. See Appendix B for the definition of the parameters used in these routines. \begin{description} \item[1 ] Modify (overwrite) the nth 80-character header record in the CHU. \label{ffmrec} \end{description} \begin{verbatim} int fits_modify_record / ffmrec (fitsfile *fptr, int keynum, char *card, > int *status) \end{verbatim} \begin{description} \item[2 ] Modify (overwrite) the 80-character header record for the named keyword in the CHU. This can be used to overwrite the name of the keyword as well as its value and comment fields. \label{ffmcrd} \end{description} \begin{verbatim} int fits_modify_card / ffmcrd (fitsfile *fptr, char *keyname, char *card, > int *status) \end{verbatim} \begin{description} \item[5 ] Modify the value and comment fields of an existing keyword in the CHU. The `longstr' version has the same functionality as the `str' version except that it also supports the local long string keyword convention for strings longer than 68 characters. Optionally, one may modify only the value field and leave the comment field unchanged by setting the input COMMENT parameter equal to the ampersand character (\&) or by entering a null pointer for the comment parameter. The flt, dbl, cmp, and dblcmp versions of this routine have the added feature that if the 'decimals' parameter is negative, then the 'G' display format rather then the 'E' format will be used when constructing the keyword value, taking the absolute value of 'decimals' for the precision. This will suppress trailing zeros, and will use a fixed format rather than an exponential format, depending on the magnitude of the value. \label{ffmkyx} \end{description} \begin{verbatim} int fits_modify_key_[str, longstr] / ffm[kys, kls] (fitsfile *fptr, char *keyname, char *value, char *comment, > int *status); int fits_modify_key_[log, lng] / ffmky[lj] (fitsfile *fptr, char *keyname, DTYPE numval, char *comment, > int *status) int fits_modify_key_[flt, dbl, fixflt, fixdbl] / ffmky[edfg] (fitsfile *fptr, char *keyname, DTYPE numval, int decimals, char *comment, > int *status) int fits_modify_key_[cmp, dblcmp, fixcmp, fixdblcmp] / ffmk[yc,ym,fc,fm] (fitsfile *fptr, char *keyname, DTYPE *numval, int decimals, char *comment, > int *status) \end{verbatim} \begin{description} \item[6 ] Modify the value of an existing keyword to be undefined, or null. The value string of the keyword is set to blank. Optionally, one may leave the comment field unchanged by setting the input COMMENT parameter equal to the ampersand character (\&) or by entering a null pointer. \label{ffmkyu} \end{description} \begin{verbatim} int fits_modify_key_null / ffmkyu (fitsfile *fptr, char *keyname, char *comment, > int *status) \end{verbatim} \subsection{Update Keyword Routines} \begin{description} \item[1 ] These update routines modify the value, and optionally the comment field, of the keyword if it already exists, otherwise the new keyword is appended to the header. A separate routine is provided for each keyword data type. The `longstr' version has the same functionality as the `str' version except that it also supports the local long string keyword convention for strings longer than 68 characters. A null pointer may be entered for the comment parameter which will leave the comment field unchanged or blank. The flt, dbl, cmp, and dblcmp versions of this routine have the added feature that if the 'decimals' parameter is negative, then the 'G' display format rather then the 'E' format will be used when constructing the keyword value, taking the absolute value of 'decimals' for the precision. This will suppress trailing zeros, and will use a fixed format rather than an exponential format, depending on the magnitude of the value. \label{ffukyx} \end{description} \begin{verbatim} int fits_update_key_[str, longstr] / ffu[kys, kls] (fitsfile *fptr, char *keyname, char *value, char *comment, > int *status) int fits_update_key_[log, lng] / ffuky[lj] (fitsfile *fptr, char *keyname, DTYPE numval, char *comment, > int *status) int fits_update_key_[flt, dbl, fixflt, fixdbl] / ffuky[edfg] (fitsfile *fptr, char *keyname, DTYPE numval, int decimals, char *comment, > int *status) int fits_update_key_[cmp, dblcmp, fixcmp, fixdblcmp] / ffuk[yc,ym,fc,fm] (fitsfile *fptr, char *keyname, DTYPE *numval, int decimals, char *comment, > int *status) \end{verbatim} \section{Define Data Scaling and Undefined Pixel Parameters} These routines set or modify the internal parameters used by CFITSIO to either scale the data or to represent undefined pixels. Generally CFITSIO will scale the data according to the values of the BSCALE and BZERO (or TSCALn and TZEROn) keywords, however these routines may be used to override the keyword values. This may be useful when one wants to read or write the raw unscaled values in the FITS file. Similarly, CFITSIO generally uses the value of the BLANK or TNULLn keyword to signify an undefined pixel, but these routines may be used to override this value. These routines do not create or modify the corresponding header keyword values. See Appendix B for the definition of the parameters used in these routines. \begin{description} \item[1 ] Reset the scaling factors in the primary array or image extension; does not change the BSCALE and BZERO keyword values and only affects the automatic scaling performed when the data elements are written/read to/from the FITS file. When reading from a FITS file the returned data value = (the value given in the FITS array) * BSCALE + BZERO. The inverse formula is used when writing data values to the FITS file. \label{ffpscl} \end{description} \begin{verbatim} int fits_set_bscale / ffpscl (fitsfile *fptr, double scale, double zero, > int *status) \end{verbatim} \begin{description} \item[2 ] Reset the scaling parameters for a table column; does not change the TSCALn or TZEROn keyword values and only affects the automatic scaling performed when the data elements are written/read to/from the FITS file. When reading from a FITS file the returned data value = (the value given in the FITS array) * TSCAL + TZERO. The inverse formula is used when writing data values to the FITS file. \label{fftscl} \end{description} \begin{verbatim} int fits_set_tscale / fftscl (fitsfile *fptr, int colnum, double scale, double zero, > int *status) \end{verbatim} \begin{description} \item[3 ] Define the integer value to be used to signify undefined pixels in the primary array or image extension. This is only used if BITPIX = 8, 16, or 32. This does not create or change the value of the BLANK keyword in the header. \label{ffpnul} \end{description} \begin{verbatim} int fits_set_imgnull / ffpnul (fitsfile *fptr, LONGLONG nulval, > int *status) \end{verbatim} \begin{description} \item[4 ] Define the string to be used to signify undefined pixels in a column in an ASCII table. This does not create or change the value of the TNULLn keyword. \label{ffsnul} \end{description} \begin{verbatim} int fits_set_atblnull / ffsnul (fitsfile *fptr, int colnum, char *nulstr, > int *status) \end{verbatim} \begin{description} \item[5 ] Define the value to be used to signify undefined pixels in an integer column in a binary table (where TFORMn = 'B', 'I', or 'J'). This does not create or change the value of the TNULLn keyword. \label{fftnul} \end{description} \begin{verbatim} int fits_set_btblnull / fftnul (fitsfile *fptr, int colnum, LONGLONG nulval, > int *status) \end{verbatim} \section{Specialized FITS Primary Array or IMAGE Extension I/O Routines} These routines read or write data values in the primary data array (i.e., the first HDU in the FITS file) or an IMAGE extension. Automatic data type conversion is performed for if the data type of the FITS array (as defined by the BITPIX keyword) differs from the data type of the array in the calling routine. The data values are automatically scaled by the BSCALE and BZERO header values as they are being written or read from the FITS array. Unlike the basic routines described in the previous chapter, most of these routines specifically support the FITS random groups format. See Appendix B for the definition of the parameters used in these routines. The more primitive reading and writing routines (i. e., ffppr\_, ffppn\_, ffppn, ffgpv\_, or ffgpf\_) simply treat the primary array as a long 1-dimensional array of pixels, ignoring the intrinsic dimensionality of the array. When dealing with a 2D image, for example, the application program must calculate the pixel offset in the 1-D array that corresponds to any particular X, Y coordinate in the image. C programmers should note that the ordering of arrays in FITS files, and hence in all the CFITSIO calls, is more similar to the dimensionality of arrays in Fortran rather than C. For instance if a FITS image has NAXIS1 = 100 and NAXIS2 = 50, then a 2-D array just large enough to hold the image should be declared as array[50][100] and not as array[100][50]. For convenience, higher-level routines are also provided to specifically deal with 2D images (ffp2d\_ and ffg2d\_) and 3D data cubes (ffp3d\_ and ffg3d\_). The dimensionality of the FITS image is passed by the naxis1, naxis2, and naxis3 parameters and the declared dimensions of the program array are passed in the dim1 and dim2 parameters. Note that the dimensions of the program array may be larger than the dimensions of the FITS array. For example if a FITS image with NAXIS1 = NAXIS2 = 400 is read into a program array which is dimensioned as 512 x 512 pixels, then the image will just fill the lower left corner of the array with pixels in the range 1 - 400 in the X an Y directions. This has the effect of taking a contiguous set of pixel value in the FITS array and writing them to a non-contiguous array in program memory (i.e., there are now some blank pixels around the edge of the image in the program array). The most general set of routines (ffpss\_, ffgsv\_, and ffgsf\_) may be used to transfer a rectangular subset of the pixels in a FITS N-dimensional image to or from an array which has been declared in the calling program. The fpixel and lpixel parameters are integer arrays which specify the starting and ending pixel coordinate in each dimension (starting with 1, not 0) of the FITS image that is to be read or written. It is important to note that these are the starting and ending pixels in the FITS image, not in the declared array in the program. The array parameter in these routines is treated simply as a large one-dimensional array of the appropriate data type containing the pixel values; The pixel values in the FITS array are read/written from/to this program array in strict sequence without any gaps; it is up to the calling routine to correctly interpret the dimensionality of this array. The two FITS reading routines (ffgsv\_ and ffgsf\_ ) also have an `inc' parameter which defines the data sampling interval in each dimension of the FITS array. For example, if inc[0]=2 and inc[1]=3 when reading a 2-dimensional FITS image, then only every other pixel in the first dimension and every 3rd pixel in the second dimension will be returned to the 'array' parameter. Two types of routines are provided to read the data array which differ in the way undefined pixels are handled. The first type of routines (e.g., ffgpv\_) simply return an array of data elements in which undefined pixels are set equal to a value specified by the user in the `nulval' parameter. An additional feature of these routines is that if the user sets nulval = 0, then no checks for undefined pixels will be performed, thus reducing the amount of CPU processing. The second type of routines (e.g., ffgpf\_) returns the data element array and, in addition, a char array that indicates whether the value of the corresponding data pixel is undefined (= 1) or defined (= 0). The latter type of routines may be more convenient to use in some circumstances, however, it requires an additional array of logical values which can be unwieldy when working with large data arrays. \begin{description} \item[1 ] Write elements into the FITS data array. \label{ffppr} \label{ffpprx} \label{ffppn} \label{ffppnx} \end{description} \begin{verbatim} int fits_write_img / ffppr (fitsfile *fptr, int datatype, LONGLONG firstelem, LONGLONG nelements, DTYPE *array, int *status); int fits_write_img_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / ffppr[b,i,ui,k,uk,j,uj,jj,e,d] (fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelements, DTYPE *array, > int *status); int fits_write_imgnull / ffppn (fitsfile *fptr, int datatype, LONGLONG firstelem, LONGLONG nelements, DTYPE *array, DTYPE *nulval, > int *status); int fits_write_imgnull_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / ffppn[b,i,ui,k,uk,j,uj,jj,e,d] (fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelements, DTYPE *array, DTYPE nulval, > int *status); \end{verbatim} \begin{description} \item[2 ]Set data array elements as undefined. \label{ffppru} \end{description} \begin{verbatim} int fits_write_img_null / ffppru (fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelements, > int *status) \end{verbatim} \begin{description} \item[3 ] Write values into group parameters. This routine only applies to the `Random Grouped' FITS format which has been used for applications in radio interferometry, but is officially deprecated for future use. \label{ffpgpx} \end{description} \begin{verbatim} int fits_write_grppar_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / ffpgp[b,i,ui,k,uk,j,uj,jj,e,d] (fitsfile *fptr, long group, long firstelem, long nelements, > DTYPE *array, int *status) \end{verbatim} \begin{description} \item[4 ] Write a 2-D or 3-D image into the data array. \label{ffp2dx} \label{ffp3dx} \end{description} \begin{verbatim} int fits_write_2d_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / ffp2d[b,i,ui,k,uk,j,uj,jj,e,d] (fitsfile *fptr, long group, LONGLONG dim1, LONGLONG naxis1, LONGLONG naxis2, DTYPE *array, > int *status) int fits_write_3d_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / ffp3d[b,i,ui,k,uk,j,uj,jj,e,d] (fitsfile *fptr, long group, LONGLONG dim1, LONGLONG dim2, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, DTYPE *array, > int *status) \end{verbatim} \begin{description} \item[5 ] Write an arbitrary data subsection into the data array. \label{ffpssx} \end{description} \begin{verbatim} int fits_write_subset_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / ffpss[b,i,ui,k,uk,j,uj,jj,e,d] (fitsfile *fptr, long group, long naxis, long *naxes, long *fpixel, long *lpixel, DTYPE *array, > int *status) \end{verbatim} \begin{description} \item[6 ] Read elements from the FITS data array. \label{ffgpv} \label{ffgpvx} \label{ffgpf} \label{ffgpfx} \end{description} \begin{verbatim} int fits_read_img / ffgpv (fitsfile *fptr, int datatype, long firstelem, long nelements, DTYPE *nulval, > DTYPE *array, int *anynul, int *status) int fits_read_img_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / ffgpv[b,i,ui,k,uk,j,uj,jj,e,d] (fitsfile *fptr, long group, long firstelem, long nelements, DTYPE nulval, > DTYPE *array, int *anynul, int *status) int fits_read_imgnull / ffgpf (fitsfile *fptr, int datatype, long firstelem, long nelements, > DTYPE *array, char *nullarray, int *anynul, int *status) int fits_read_imgnull_[byt, sht, usht, int, uint, lng, ulng, flt, dbl] / ffgpf[b,i,ui,k,uk,j,uj,jj,e,d] (fitsfile *fptr, long group, long firstelem, long nelements, > DTYPE *array, char *nullarray, int *anynul, int *status) \end{verbatim} \begin{description} \item[7 ] Read values from group parameters. This routine only applies to the `Random Grouped' FITS format which has been used for applications in radio interferometry, but is officially deprecated for future use. \label{ffggpx} \end{description} \begin{verbatim} int fits_read_grppar_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / ffggp[b,i,ui,k,uk,j,uj,jj,e,d] (fitsfile *fptr, long group, long firstelem, long nelements, > DTYPE *array, int *status) \end{verbatim} \begin{description} \item[8 ] Read 2-D or 3-D image from the data array. Undefined pixels in the array will be set equal to the value of 'nulval', unless nulval=0 in which case no testing for undefined pixels will be performed. \label{ffg2dx} \label{ffg3dx} \end{description} \begin{verbatim} int fits_read_2d_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / ffg2d[b,i,ui,k,uk,j,uj,jj,e,d] (fitsfile *fptr, long group, DTYPE nulval, LONGLONG dim1, LONGLONG naxis1, LONGLONG naxis2, > DTYPE *array, int *anynul, int *status) int fits_read_3d_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / ffg3d[b,i,ui,k,uk,j,uj,jj,e,d] (fitsfile *fptr, long group, DTYPE nulval, LONGLONG dim1, LONGLONG dim2, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, > DTYPE *array, int *anynul, int *status) \end{verbatim} \begin{description} \item[9 ] Read an arbitrary data subsection from the data array. \label{ffgsvx} \label{ffgsfx} \end{description} \begin{verbatim} int fits_read_subset_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / ffgsv[b,i,ui,k,uk,j,uj,jj,e,d] (fitsfile *fptr, int group, int naxis, long *naxes, long *fpixel, long *lpixel, long *inc, DTYPE nulval, > DTYPE *array, int *anynul, int *status) int fits_read_subsetnull_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / ffgsf[b,i,ui,k,uk,j,uj,jj,e,d] (fitsfile *fptr, int group, int naxis, long *naxes, long *fpixel, long *lpixel, long *inc, > DTYPE *array, char *nullarray, int *anynul, int *status) \end{verbatim} \section{Specialized FITS ASCII and Binary Table Routines} \subsection{General Column Routines} \begin{description} \item[1 ] Get information about an existing ASCII or binary table column. A null pointer may be given for any of the output parameters that are not needed. DATATYPE is a character string which returns the data type of the column as defined by the TFORMn keyword (e.g., 'I', 'J','E', 'D', etc.). In the case of an ASCII character column, typecode will have a value of the form 'An' where 'n' is an integer expressing the width of the field in characters. For example, if TFORM = '160A8' then ffgbcl will return typechar='A8' and repeat=20. All the returned parameters are scalar quantities. \label{ffgacl} \label{ffgbcl} \end{description} \begin{verbatim} int fits_get_acolparms / ffgacl (fitsfile *fptr, int colnum, > char *ttype, long *tbcol, char *tunit, char *tform, double *scale, double *zero, char *nulstr, char *tdisp, int *status) int fits_get_bcolparms / ffgbcl (fitsfile *fptr, int colnum, > char *ttype, char *tunit, char *typechar, long *repeat, double *scale, double *zero, long *nulval, char *tdisp, int *status) int fits_get_bcolparmsll / ffgbclll (fitsfile *fptr, int colnum, > char *ttype, char *tunit, char *typechar, LONGLONG *repeat, double *scale, double *zero, LONGLONG *nulval, char *tdisp, int *status) \end{verbatim} \begin{description} \item[2 ] Return optimal number of rows to read or write at one time for maximum I/O efficiency. Refer to the ``Optimizing Code'' section in Chapter 5 for more discussion on how to use this routine. \label{ffgrsz} \end{description} \begin{verbatim} int fits_get_rowsize / ffgrsz (fitsfile *fptr, long *nrows, *status) \end{verbatim} \begin{description} \item[3 ] Define the zero indexed byte offset of the 'heap' measured from the start of the binary table data. By default the heap is assumed to start immediately following the regular table data, i.e., at location NAXIS1 x NAXIS2. This routine is only relevant for binary tables which contain variable length array columns (with TFORMn = 'Pt'). This routine also automatically writes the value of theap to a keyword in the extension header. This routine must be called after the required keywords have been written (with ffphbn) but before any data is written to the table. \label{ffpthp} \end{description} \begin{verbatim} int fits_write_theap / ffpthp (fitsfile *fptr, long theap, > int *status) \end{verbatim} \begin{description} \item[4 ] Test the contents of the binary table variable array heap, returning the size of the heap, the number of unused bytes that are not currently pointed to by any of the descriptors, and the number of bytes which are pointed to by multiple descriptors. It also returns valid = FALSE if any of the descriptors point to invalid addresses out of range of the heap. \label{fftheap} \end{description} \begin{verbatim} int fits_test_heap / fftheap (fitsfile *fptr, > LONGLONG *heapsize, LONGLONG *unused, LONGLONG *overlap, int *validheap, int *status) \end{verbatim} \begin{description} \item[5 ] Re-pack the vectors in the binary table variable array heap to recover any unused space. Normally, when a vector in a variable length array column is rewritten the previously written array remains in the heap as wasted unused space. This routine will repack the arrays that are still in use, thus eliminating any bytes in the heap that are no longer in use. Note that if several vectors point to the same bytes in the heap, then this routine will make duplicate copies of the bytes for each vector, which will actually expand the size of the heap. \label{ffcmph} \end{description} \begin{verbatim} int fits_compress_heap / ffcmph (fitsfile *fptr, > int *status) \end{verbatim} \subsection{Low-Level Table Access Routines} The following 2 routines provide low-level access to the data in ASCII or binary tables and are mainly useful as an efficient way to copy all or part of a table from one location to another. These routines simply read or write the specified number of consecutive bytes in an ASCII or binary table, without regard for column boundaries or the row length in the table. These routines do not perform any machine dependent data conversion or byte swapping. See Appendix B for the definition of the parameters used in these routines. \begin{description} \item[1 ] Read or write a consecutive array of bytes from an ASCII or binary table \label{ffgtbb} \label{ffptbb} \end{description} \begin{verbatim} int fits_read_tblbytes / ffgtbb (fitsfile *fptr, LONGLONG firstrow, LONGLONG firstchar, LONGLONG nchars, > unsigned char *values, int *status) int fits_write_tblbytes / ffptbb (fitsfile *fptr, LONGLONG firstrow, LONGLONG firstchar, LONGLONG nchars, unsigned char *values, > int *status) \end{verbatim} \subsection{Write Column Data Routines} \begin{description} \item[1 ] Write elements into an ASCII or binary table column (in the CDU). The data type of the array is implied by the suffix of the routine name. \label{ffpcls} \end{description} \begin{verbatim} int fits_write_col_str / ffpcls (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelements, char **array, > int *status) int fits_write_col_[log,byt,sht,usht,int,uint,lng,ulng,lnglng,flt,dbl,cmp,dblcmp] / ffpcl[l,b,i,ui,k,uk,j,uj,jj,e,d,c,m] (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelements, DTYPE *array, > int *status) \end{verbatim} \begin{description} \item[2 ] Write elements into an ASCII or binary table column substituting the appropriate FITS null value for any elements that are equal to the nulval parameter. \label{ffpcnx} \end{description} \begin{verbatim} int fits_write_colnull_[log, byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / ffpcn[l,b,i,ui,k,uk,j,uj,jj,e,d] (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelements, DTYPE *array, DTYPE nulval, > int *status) \end{verbatim} \begin{description} \item[3 ] Write string elements into a binary table column (in the CDU) substituting the FITS null value for any elements that are equal to the nulstr string. \label{ffpcns} \end{description} \begin{verbatim} int fits_write_colnull_str / ffpcns (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelements, char **array, char *nulstr, > int *status) \end{verbatim} \begin{description} \item[4 ] Write bit values into a binary byte ('B') or bit ('X') table column (in the CDU). Larray is an array of characters corresponding to the sequence of bits to be written. If an element of larray is true (not equal to zero) then the corresponding bit in the FITS table is set to 1, otherwise the bit is set to 0. The 'X' column in a FITS table is always padded out to a multiple of 8 bits where the bit array starts with the most significant bit of the byte and works down towards the 1's bit. For example, a '4X' array, with the first bit = 1 and the remaining 3 bits = 0 is equivalent to the 8-bit unsigned byte decimal value of 128 ('1000 0000B'). In the case of 'X' columns, CFITSIO can write to all 8 bits of each byte whether they are formally valid or not. Thus if the column is defined as '4X', and one calls ffpclx with firstbit=1 and nbits=8, then all 8 bits will be written into the first byte (as opposed to writing the first 4 bits into the first row and then the next 4 bits into the next row), even though the last 4 bits of each byte are formally not defined and should all be set = 0. It should also be noted that it is more efficient to write 'X' columns an entire byte at a time, instead of bit by bit. Any of the CFITSIO routines that write to columns (e.g. fits\_write\_col\_byt) may be used for this purpose. These routines will interpret 'X' columns as though they were 'B' columns (e.g., '1X' through '8X' is equivalent to '1B', and '9X' through '16X' is equivalent to '2B'). \label{ffpclx} \end{description} \begin{verbatim} int fits_write_col_bit / ffpclx (fitsfile *fptr, int colnum, LONGLONG firstrow, long firstbit, long nbits, char *larray, > int *status) \end{verbatim} \begin{description} \item[5 ] Write the descriptor for a variable length column in a binary table. This routine can be used in conjunction with ffgdes to enable 2 or more arrays to point to the same storage location to save storage space if the arrays are identical. \label{ffpdes} \end{description} \begin{verbatim} int fits_write_descript / ffpdes (fitsfile *fptr, int colnum, LONGLONG rownum, LONGLONG repeat, LONGLONG offset, > int *status) \end{verbatim} \subsection{Read Column Data Routines} Two types of routines are provided to get the column data which differ in the way undefined pixels are handled. The first set of routines (ffgcv) simply return an array of data elements in which undefined pixels are set equal to a value specified by the user in the 'nullval' parameter. If nullval = 0, then no checks for undefined pixels will be performed, thus increasing the speed of the program. The second set of routines (ffgcf) returns the data element array and in addition a logical array of flags which defines whether the corresponding data pixel is undefined. See Appendix B for the definition of the parameters used in these routines. Any column, regardless of it's intrinsic data type, may be read as a string. It should be noted however that reading a numeric column as a string is 10 - 100 times slower than reading the same column as a number due to the large overhead in constructing the formatted strings. The display format of the returned strings will be determined by the TDISPn keyword, if it exists, otherwise by the data type of the column. The length of the returned strings (not including the null terminating character) can be determined with the fits\_get\_col\_display\_width routine. The following TDISPn display formats are currently supported: \begin{verbatim} Iw.m Integer Ow.m Octal integer Zw.m Hexadecimal integer Fw.d Fixed floating point Ew.d Exponential floating point Dw.d Exponential floating point Gw.d General; uses Fw.d if significance not lost, else Ew.d \end{verbatim} where w is the width in characters of the displayed values, m is the minimum number of digits displayed, and d is the number of digits to the right of the decimal. The .m field is optional. \begin{description} \item[1 ] Read elements from an ASCII or binary table column (in the CDU). These routines return the values of the table column array elements. Undefined array elements will be returned with a value = nulval, unless nulval = 0 (or = ' ' for ffgcvs) in which case no checking for undefined values will be performed. The anynul parameter is set to true if any of the returned elements are undefined. \label{ffgcvx} \end{description} \begin{verbatim} int fits_read_col_str / ffgcvs (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelements, char *nulstr, > char **array, int *anynul, int *status) int fits_read_col_[log,byt,sht,usht,int,uint,lng,ulng, lnglng, flt, dbl, cmp, dblcmp] / ffgcv[l,b,i,ui,k,uk,j,uj,jj,e,d,c,m] (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelements, DTYPE nulval, > DTYPE *array, int *anynul, int *status) \end{verbatim} \begin{description} \item[2 ] Read elements and null flags from an ASCII or binary table column (in the CHDU). These routines return the values of the table column array elements. Any undefined array elements will have the corresponding nullarray element set equal to TRUE. The anynul parameter is set to true if any of the returned elements are undefined. \label{ffgcfx} \end{description} \begin{verbatim} int fits_read_colnull_str / ffgcfs (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelements, > char **array, char *nullarray, int *anynul, int *status) int fits_read_colnull_[log,byt,sht,usht,int,uint,lng,ulng,lnglng,flt,dbl,cmp,dblcmp] / ffgcf[l,b,i,ui,k,uk,j,uj,jj,e,d,c,m] (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelements, > DTYPE *array, char *nullarray, int *anynul, int *status) \end{verbatim} \begin{description} \item[3 ] Read an arbitrary data subsection from an N-dimensional array in a binary table vector column. Undefined pixels in the array will be set equal to the value of 'nulval', unless nulval=0 in which case no testing for undefined pixels will be performed. The first and last rows in the table to be read are specified by fpixel(naxis+1) and lpixel(naxis+1), and hence are treated as the next higher dimension of the FITS N-dimensional array. The INC parameter specifies the sampling interval in each dimension between the data elements that will be returned. \label{ffgsvx2} \end{description} \begin{verbatim} int fits_read_subset_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / ffgsv[b,i,ui,k,uk,j,uj,jj,e,d] (fitsfile *fptr, int colnum, int naxis, long *naxes, long *fpixel, long *lpixel, long *inc, DTYPE nulval, > DTYPE *array, int *anynul, int *status) \end{verbatim} \begin{description} \item[4 ] Read an arbitrary data subsection from an N-dimensional array in a binary table vector column. Any Undefined pixels in the array will have the corresponding 'nullarray' element set equal to TRUE. The first and last rows in the table to be read are specified by fpixel(naxis+1) and lpixel(naxis+1), and hence are treated as the next higher dimension of the FITS N-dimensional array. The INC parameter specifies the sampling interval in each dimension between the data elements that will be returned. \label{ffgsfx2} \end{description} \begin{verbatim} int fits_read_subsetnull_[byt, sht, usht, int, uint, lng, ulng, lnglng, flt, dbl] / ffgsf[b,i,ui,k,uk,j,uj,jj,e,d] (fitsfile *fptr, int colnum, int naxis, long *naxes, long *fpixel, long *lpixel, long *inc, > DTYPE *array, char *nullarray, int *anynul, int *status) \end{verbatim} \begin{description} \item[5 ] Read bit values from a byte ('B') or bit (`X`) table column (in the CDU). Larray is an array of logical values corresponding to the sequence of bits to be read. If larray is true then the corresponding bit was set to 1, otherwise the bit was set to 0. The 'X' column in a FITS table is always padded out to a multiple of 8 bits where the bit array starts with the most significant bit of the byte and works down towards the 1's bit. For example, a '4X' array, with the first bit = 1 and the remaining 3 bits = 0 is equivalent to the 8-bit unsigned byte value of 128. Note that in the case of 'X' columns, CFITSIO can read all 8 bits of each byte whether they are formally valid or not. Thus if the column is defined as '4X', and one calls ffgcx with firstbit=1 and nbits=8, then all 8 bits will be read from the first byte (as opposed to reading the first 4 bits from the first row and then the first 4 bits from the next row), even though the last 4 bits of each byte are formally not defined. It should also be noted that it is more efficient to read 'X' columns an entire byte at a time, instead of bit by bit. Any of the CFITSIO routines that read columns (e.g. fits\_read\_col\_byt) may be used for this purpose. These routines will interpret 'X' columns as though they were 'B' columns (e.g., '8X' is equivalent to '1B', and '16X' is equivalent to '2B'). \label{ffgcx} \end{description} \begin{verbatim} int fits_read_col_bit / ffgcx (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstbit, LONGLONG nbits, > char *larray, int *status) \end{verbatim} \begin{description} \item[6 ] Read any consecutive set of bits from an 'X' or 'B' column and interpret them as an unsigned n-bit integer. nbits must be less than 16 or 32 in ffgcxui and ffgcxuk, respectively. If nrows is greater than 1, then the same set of bits will be read from each row, starting with firstrow. The bits are numbered with 1 = the most significant bit of the first element of the column. \label{ffgcxui} \end{description} \begin{verbatim} int fits_read_col_bit_[usht, uint] / ffgcx[ui,uk] (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG, nrows, long firstbit, long nbits, > DTYPE *array, int *status) \end{verbatim} \begin{description} \item[7 ] Return the descriptor for a variable length column in a binary table. The descriptor consists of 2 integer parameters: the number of elements in the array and the starting offset relative to the start of the heap. The first pair of routine returns a single descriptor whereas the second pair of routine returns the descriptors for a range of rows in the table. The only difference between the 2 routines in each pair is that one returns the parameters as 'long' integers, whereas the other returns the values as 64-bit 'LONGLONG' integers. \label{ffgdes} \end{description} \begin{verbatim} int fits_read_descript / ffgdes (fitsfile *fptr, int colnum, LONGLONG rownum, > long *repeat, long *offset, int *status) int fits_read_descriptll / ffgdesll (fitsfile *fptr, int colnum, LONGLONG rownum, > LONGLONG *repeat, LONGLONG *offset, int *status) int fits_read_descripts / ffgdess (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG nrows > long *repeat, long *offset, int *status) int fits_read_descriptsll / ffgdessll (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG nrows > LONGLONG *repeat, LONGLONG *offset, int *status) \end{verbatim} \chapter{ Extended File Name Syntax } \section{Overview} CFITSIO supports an extended syntax when specifying the name of the data file to be opened or created that includes the following features: \begin{itemize} \item CFITSIO can read IRAF format images which have header file names that end with the '.imh' extension, as well as reading and writing FITS files, This feature is implemented in CFITSIO by first converting the IRAF image into a temporary FITS format file in memory, then opening the FITS file. Any of the usual CFITSIO routines then may be used to read the image header or data. Similarly, raw binary data arrays can be read by converting them on the fly into virtual FITS images. \item FITS files on the Internet can be read (and sometimes written) using the FTP, HTTP, HTTPS, or ROOT protocols. \item FITS files can be piped between tasks on the stdin and stdout streams. \item FITS files can be read and written in shared memory. This can potentially achieve better data I/O performance compared to reading and writing the same FITS files on magnetic disk. \item Compressed FITS files in gzip or Unix COMPRESS format can be directly read. \item Output FITS files can be written directly in compressed gzip format, thus saving disk space. \item FITS table columns can be created, modified, or deleted 'on-the-fly' as the table is opened by CFITSIO. This creates a virtual FITS file containing the modifications that is then opened by the application program. \item Table rows may be selected, or filtered out, on the fly when the table is opened by CFITSIO, based on an user-specified expression. Only rows for which the expression evaluates to 'TRUE' are retained in the copy of the table that is opened by the application program. \item Histogram images may be created on the fly by binning the values in table columns, resulting in a virtual N-dimensional FITS image. The application program then only sees the FITS image (in the primary array) instead of the original FITS table. \end{itemize} The latter 3 table filtering features in particular add very powerful data processing capabilities directly into CFITSIO, and hence into every task that uses CFITSIO to read or write FITS files. For example, these features transform a very simple program that just copies an input FITS file to a new output file (like the `fitscopy' program that is distributed with CFITSIO) into a multipurpose FITS file processing tool. By appending fairly simple qualifiers onto the name of the input FITS file, the user can perform quite complex table editing operations (e.g., create new columns, or filter out rows in a table) or create FITS images by binning or histogramming the values in table columns. In addition, these functions have been coded using new state-of-the art algorithms that are, in some cases, 10 - 100 times faster than previous widely used implementations. Before describing the complete syntax for the extended FITS file names in the next section, here are a few examples of FITS file names that give a quick overview of the allowed syntax: \begin{itemize} \item {\tt myfile.fits}: the simplest case of a FITS file on disk in the current directory. \item {\tt myfile.imh}: opens an IRAF format image file and converts it on the fly into a temporary FITS format image in memory which can then be read with any other CFITSIO routine. \item {\tt rawfile.dat[i512,512]}: opens a raw binary data array (a 512 x 512 short integer array in this case) and converts it on the fly into a temporary FITS format image in memory which can then be read with any other CFITSIO routine. \item {\tt myfile.fits.gz}: if this is the name of a new output file, the '.gz' suffix will cause it to be compressed in gzip format when it is written to disk. \item {\tt myfile.fits.gz[events, 2]}: opens and uncompresses the gzipped file myfile.fits then moves to the extension with the keywords EXTNAME = 'EVENTS' and EXTVER = 2. \item {\tt -}: a dash (minus sign) signifies that the input file is to be read from the stdin file stream, or that the output file is to be written to the stdout stream. See also the stream:// driver which provides a more efficient, but more restricted method of reading or writing to the stdin or stdout streams. \item {\tt ftp://legacy.gsfc.nasa.gov/test/vela.fits}: FITS files in any ftp archive site on the Internet may be directly opened with read-only access. \item {\tt http://legacy.gsfc.nasa.gov/software/test.fits}: any valid URL to a FITS file on the Web may be opened with read-only access. \item {\tt root://legacy.gsfc.nasa.gov/test/vela.fits}: similar to ftp access except that it provides write as well as read access to the files across the network. This uses the root protocol developed at CERN. \item {\tt shmem://h2[events]}: opens the FITS file in a shared memory segment and moves to the EVENTS extension. \item {\tt mem://}: creates a scratch output file in core computer memory. The resulting 'file' will disappear when the program exits, so this is mainly useful for testing purposes when one does not want a permanent copy of the output file. \item {\tt myfile.fits[3; Images(10)]}: opens a copy of the image contained in the 10th row of the 'Images' column in the binary table in the 3th extension of the FITS file. The virtual file that is opened by the application just contains this single image in the primary array. \item {\tt myfile.fits[1:512:2, 1:512:2]}: opens a section of the input image ranging from the 1st to the 512th pixel in X and Y, and selects every second pixel in both dimensions, resulting in a 256 x 256 pixel input image in this case. \item {\tt myfile.fits[EVENTS][col Rad = sqrt(X**2 + Y**2)]}: creates and opens a virtual file on the fly that is identical to myfile.fits except that it will contain a new column in the EVENTS extension called 'Rad' whose value is computed using the indicated expression which is a function of the values in the X and Y columns. \item {\tt myfile.fits[EVENTS][PHA > 5]}: creates and opens a virtual FITS files that is identical to 'myfile.fits' except that the EVENTS table will only contain the rows that have values of the PHA column greater than 5. In general, any arbitrary boolean expression using a C or Fortran-like syntax, which may combine AND and OR operators, may be used to select rows from a table. \item {\tt myfile.fits[EVENTS][bin (X,Y)=1,2048,4]}: creates a temporary FITS primary array image which is computed on the fly by binning (i.e, computing the 2-dimensional histogram) of the values in the X and Y columns of the EVENTS extension. In this case the X and Y coordinates range from 1 to 2048 and the image pixel size is 4 units in both dimensions, so the resulting image is 512 x 512 pixels in size. \item The final example combines many of these feature into one complex expression (it is broken into several lines for clarity): \begin{verbatim} ftp://legacy.gsfc.nasa.gov/data/sample.fits.gz[EVENTS] [col phacorr = pha * 1.1 - 0.3][phacorr >= 5.0 && phacorr <= 14.0] [bin (X,Y)=32] \end{verbatim} In this case, CFITSIO (1) copies and uncompresses the FITS file from the ftp site on the legacy machine, (2) moves to the 'EVENTS' extension, (3) calculates a new column called 'phacorr', (4) selects the rows in the table that have phacorr in the range 5 to 14, and finally (5) bins the remaining rows on the X and Y column coordinates, using a pixel size = 32 to create a 2D image. All this processing is completely transparent to the application program, which simply sees the final 2-D image in the primary array of the opened file. \end{itemize} The full extended CFITSIO FITS file name can contain several different components depending on the context. These components are described in the following sections: \begin{verbatim} When creating a new file: filetype://BaseFilename(templateName)[compress] When opening an existing primary array or image HDU: filetype://BaseFilename(outName)[HDUlocation][ImageSection][pixFilter] When opening an existing table HDU: filetype://BaseFilename(outName)[HDUlocation][colFilter][rowFilter][binSpec] \end{verbatim} The filetype, BaseFilename, outName, HDUlocation, ImageSection, and pixFilter components, if present, must be given in that order, but the colFilter, rowFilter, and binSpec specifiers may follow in any order. Regardless of the order, however, the colFilter specifier, if present, will be processed first by CFITSIO, followed by the rowFilter specifier, and finally by the binSpec specifier. \section{Filetype} The type of file determines the medium on which the file is located (e.g., disk or network) and, hence, which internal device driver is used by CFITSIO to read and/or write the file. Currently supported types are \begin{verbatim} file:// - file on local magnetic disk (default) ftp:// - a readonly file accessed with the anonymous FTP protocol. It also supports ftp://username:password@hostname/... for accessing password-protected ftp sites. http:// - a readonly file accessed with the HTTP protocol. It supports username:password just like the ftp driver. Proxy HTTP servers are supported using the http_proxy environment variable (see following note). https:// - a readonly file accessed with the HTTPS protocol. This is available only if CFITSIO was built with the libcurl library (see the following note). stream:// - special driver to read an input FITS file from the stdin stream, and/or write an output FITS file to the stdout stream. This driver is fragile and has limited functionality (see the following note). gsiftp:// - access files on a computational grid using the gridftp protocol in the Globus toolkit (see following note). root:// - uses the CERN root protocol for writing as well as reading files over the network (see following note). shmem:// - opens or creates a file which persists in the computer's shared memory (see following note). mem:// - opens a temporary file in core memory. The file disappears when the program exits so this is mainly useful for test purposes when a permanent output file is not desired. \end{verbatim} If the filetype is not specified, then type file:// is assumed. The double slashes '//' are optional and may be omitted in most cases. \subsection{Notes about HTTP proxy servers} A proxy HTTP server may be used by defining the address (URL) and port number of the proxy server with the http\_proxy environment variable. For example \begin{verbatim} setenv http_proxy http://heasarc.gsfc.nasa.gov:3128 \end{verbatim} will cause CFITSIO to use port 3128 on the heasarc proxy server whenever reading a FITS file with HTTP. \subsection{Notes about HTTPS file access} CFITSIO depends upon the availability of the libcurl library in order to perform HTTPS file access. (This should be the development version of the library, as it contains the curl.h header file required by the CFITSIO code.) The CFITSIO 'configure' script will search for this library on your system, and if it finds it it will automatically be incorporated into the build. Note that if you have this library package on your system, you will also have the 'curl-config' executable. You can run the 'curl-config' executable with various options to learn more about the features of your libcurl installation. If the CFITSIO 'configure' succeeded in finding a usable libcurl, you will see the flag '-DCFITSIO\_HAVE\_CURL=1' in the CFITSIO Makefile and in the compilation output. If 'configure' is unable to find a usable libcurl, CFITSIO will still build but it won't have HTTPS capability. The libcurl package is normally included as part of Xcode on Macs. However on Linux platforms you may need to manually install it. This can be easily done on Ubuntu Linux using the 'apt get' command to retrieve the libcurl4-openssl-dev or the libcurl4-gnutls-dev packages. When accessing a file with HTTPS, the default CFITSIO behavior is to attempt to verify both the host name and the SSL certificate. If it cannot, it will still perform the file access but will issue a warning to the terminal window. The user can override this behavior to force CFITSIO to only allow file transfers when the host name and SSL certificate have been successfully verified. This is done by setting the CFITSIO\_VERIFY\_HTTPS environment variable to 'True'. ie. in a csh shell: setenv CFITSIO\_VERIFY\_HTTPS True the default setting for this is 'False'. CFITSIO has 3 functions which apply specifically to HTTPS access: fits\_init\_https, fits\_cleanup\_https, and fits\_verbose\_https. It is recommended that you call the init and cleanup functions near the beginning and end of your program respectively. For more information about these functions, please see the 'FITS File Access Routines' section in the preceding chapter ('Specialized CFITSIO Interface Routines'). \subsection{Notes about the stream filetype driver} The stream driver can be used to efficiently read a FITS file from the stdin file stream or write a FITS to the stdout file stream. However, because these input and output streams must be accessed sequentially, the FITS file reading or writing application must also read and write the file sequentially, at least within the tolerances described below. CFITSIO supports 2 different methods for accessing FITS files on the stdin and stdout streams. The original method, which is invoked by specifying a dash character, "-", as the name of the file when opening or creating it, works by storing a complete copy of the entire FITS file in memory. In this case, when reading from stdin, CFITSIO will copy the entire stream into memory before doing any processing of the file. Similarly, when writing to stdout, CFITSIO will create a copy of the entire FITS file in memory, before finally flushing it out to the stdout stream when the FITS file is closed. Buffering the entire FITS file in this way allows the application to randomly access any part of the FITS file, in any order, but it also requires that the user have sufficient available memory (or virtual memory) to store the entire file, which may not be possible in the case of very large files. The newer stream filetype provides a more memory-efficient method of accessing FITS files on the stdin or stdout streams. Instead of storing a copy of the entire FITS file in memory, CFITSIO only uses a set of internal buffer which by default can store 40 FITS blocks, or about 100K bytes of the FITS file. The application program must process the FITS file sequentially from beginning to end, within this 100K buffer. Generally speaking the application program must conform to the following restrictions: \begin{itemize} \item The program must finish reading or writing the header keywords before reading or writing any data in the HDU. \item The HDU can contain at most about 1400 header keywords. This is the maximum that can fit in the nominal 40 FITS block buffer. In principle, this limit could be increased by recompiling CFITSIO with a larger buffer limit, which is set by the NIOBUF parameter in fitsio2.h. \item The program must read or write the data in a sequential manner from the beginning to the end of the HDU. Note that CFITSIO's internal 100K buffer allows a little latitude in meeting this requirement. \item The program cannot move back to a previous HDU in the FITS file. \item Reading or writing of variable length array columns in binary tables is not supported on streams, because this requires moving back and forth between the fixed-length portion of the binary table and the following heap area where the arrays are actually stored. \item Reading or writing of tile-compressed images is not supported on streams, because the images are internally stored using variable length arrays. \end{itemize} \subsection{Notes about the gsiftp filetype} DEPENDENCIES: Globus toolkit (2.4.3 or higher) (GT) should be installed. There are two different ways to install GT: 1) goto the globus toolkit web page www.globus.org and follow the download and compilation instructions; 2) goto the Virtual Data Toolkit web page http://vdt.cs.wisc.edu/ and follow the instructions (STRONGLY SUGGESTED); Once a globus client has been installed in your system with a specific flavour it is possible to compile and install the CFITSIO libraries. Specific configuration flags must be used: 1) --with-gsiftp[[=PATH]] Enable Globus Toolkit gsiftp protocol support PATH=GLOBUS\_LOCATION i.e. the location of your globus installation 2) --with-gsiftp-flavour[[=PATH] defines the specific Globus flavour ex. gcc32 Both the flags must be used and it is mandatory to set both the PATH and the flavour. USAGE: To access files on a gridftp server it is necessary to use a gsiftp prefix: example: gsiftp://remote\_server\_fqhn/directory/filename The gridftp driver uses a local buffer on a temporary file the file is located in the /tmp directory. If you have special permissions on /tmp or you do not have a /tmp directory, it is possible to force another location setting the GSIFTP\_TMPFILE environment variable (ex. export GSIFTP\_TMPFILE=/your/location/yourtmpfile). Grid FTP supports multi channel transfer. By default a single channel transmission is available. However, it is possible to modify this behavior setting the GSIFTP\_STREAMS environment variable (ex. export GSIFTP\_STREAMS=8). \subsection{Notes about the root filetype} The original rootd server can be obtained from: \verb-ftp://root.cern.ch/root/rootd.tar.gz- but, for it to work correctly with CFITSIO one has to use a modified version which supports a command to return the length of the file. This modified version is available in rootd subdirectory in the CFITSIO ftp area at \begin{verbatim} ftp://legacy.gsfc.nasa.gov/software/fitsio/c/root/rootd.tar.gz. \end{verbatim} This small server is started either by inetd when a client requests a connection to a rootd server or by hand (i.e. from the command line). The rootd server works with the ROOT TNetFile class. It allows remote access to ROOT database files in either read or write mode. By default TNetFile assumes port 432 (which requires rootd to be started as root). To run rootd via inetd add the following line to /etc/services: \begin{verbatim} rootd 432/tcp \end{verbatim} and to /etc/inetd.conf, add the following line: \begin{verbatim} rootd stream tcp nowait root /user/rdm/root/bin/rootd rootd -i \end{verbatim} Force inetd to reread its conf file with \verb+kill -HUP +. You can also start rootd by hand running directly under your private account (no root system privileges needed). For example to start rootd listening on port 5151 just type: \verb+rootd -p 5151+ Notice that no \& is needed. Rootd will go into background by itself. \begin{verbatim} Rootd arguments: -i says we were started by inetd -p port# specifies a different port to listen on -d level level of debug info written to syslog 0 = no debug (default) 1 = minimum 2 = medium 3 = maximum \end{verbatim} Rootd can also be configured for anonymous usage (like anonymous ftp). To setup rootd to accept anonymous logins do the following (while being logged in as root): \begin{verbatim} - Add the following line to /etc/passwd: rootd:*:71:72:Anonymous rootd:/var/spool/rootd:/bin/false where you may modify the uid, gid (71, 72) and the home directory to suite your system. - Add the following line to /etc/group: rootd:*:72:rootd where the gid must match the gid in /etc/passwd. - Create the directories: mkdir /var/spool/rootd mkdir /var/spool/rootd/tmp chmod 777 /var/spool/rootd/tmp Where /var/spool/rootd must match the rootd home directory as specified in the rootd /etc/passwd entry. - To make writeable directories for anonymous do, for example: mkdir /var/spool/rootd/pub chown rootd:rootd /var/spool/rootd/pub \end{verbatim} That's all. Several additional remarks: you can login to an anonymous server either with the names "anonymous" or "rootd". The password should be of type user@host.do.main. Only the @ is enforced for the time being. In anonymous mode the top of the file tree is set to the rootd home directory, therefore only files below the home directory can be accessed. Anonymous mode only works when the server is started via inetd. \subsection{Notes about the shmem filetype:} Shared memory files are currently supported on most Unix platforms, where the shared memory segments are managed by the operating system kernel and `live' independently of processes. They are not deleted (by default) when the process which created them terminates, although they will disappear if the system is rebooted. Applications can create shared memory files in CFITSIO by calling: \begin{verbatim} fit_create_file(&fitsfileptr, "shmem://h2", &status); \end{verbatim} where the root `file' names are currently restricted to be 'h0', 'h1', 'h2', 'h3', etc., up to a maximum number defined by the the value of SHARED\_MAXSEG (equal to 16 by default). This is a prototype implementation of the shared memory interface and a more robust interface, which will have fewer restrictions on the number of files and on their names, may be developed in the future. When opening an already existing FITS file in shared memory one calls the usual CFITSIO routine: \begin{verbatim} fits_open_file(&fitsfileptr, "shmem://h7", mode, &status) \end{verbatim} The file mode can be READWRITE or READONLY just as with disk files. More than one process can operate on READONLY mode files at the same time. CFITSIO supports proper file locking (both in READONLY and READWRITE modes), so calls to fits\_open\_file may be locked out until another other process closes the file. When an application is finished accessing a FITS file in a shared memory segment, it may close it (and the file will remain in the system) with fits\_close\_file, or delete it with fits\_delete\_file. Physical deletion is postponed until the last process calls ffclos/ffdelt. fits\_delete\_file tries to obtain a READWRITE lock on the file to be deleted, thus it can be blocked if the object was not opened in READWRITE mode. A shared memory management utility program called `smem', is included with the CFITSIO distribution. It can be built by typing `make smem'; then type `smem -h' to get a list of valid options. Executing smem without any options causes it to list all the shared memory segments currently residing in the system and managed by the shared memory driver. To get a list of all the shared memory objects, run the system utility program `ipcs [-a]'. \section{Base Filename} The base filename is the name of the file optionally including the director/subdirectory path, and in the case of `ftp', `http', and `root' filetypes, the machine identifier. Examples: \begin{verbatim} myfile.fits !data.fits /data/myfile.fits fits.gsfc.nasa.gov/ftp/sampledata/myfile.fits.gz \end{verbatim} When creating a new output file on magnetic disk (of type file://) if the base filename begins with an exclamation point (!) then any existing file with that same basename will be deleted prior to creating the new FITS file. Otherwise if the file to be created already exists, then CFITSIO will return an error and will not overwrite the existing file. Note that the exclamation point, '!', is a special UNIX character, so if it is used on the command line rather than entered at a task prompt, it must be preceded by a backslash to force the UNIX shell to pass it verbatim to the application program. If the output disk file name ends with the suffix '.gz', then CFITSIO will compress the file using the gzip compression algorithm before writing it to disk. This can reduce the amount of disk space used by the file. Note that this feature requires that the uncompressed file be constructed in memory before it is compressed and written to disk, so it can fail if there is insufficient available memory. An input FITS file may be compressed with the gzip or Unix compress algorithms, in which case CFITSIO will uncompress the file on the fly into a temporary file (in memory or on disk). Compressed files may only be opened with read-only permission. When specifying the name of a compressed FITS file it is not necessary to append the file suffix (e.g., `.gz' or `.Z'). If CFITSIO cannot find the input file name without the suffix, then it will automatically search for a compressed file with the same root name. In the case of reading ftp and http type files, CFITSIO generally looks for a compressed version of the file first, before trying to open the uncompressed file. By default, CFITSIO copies (and uncompressed if necessary) the ftp or http FITS file into memory on the local machine before opening it. This will fail if the local machine does not have enough memory to hold the whole FITS file, so in this case, the output filename specifier (see the next section) can be used to further control how CFITSIO reads ftp and http files. If the input file is an IRAF image file (*.imh file) then CFITSIO will automatically convert it on the fly into a virtual FITS image before it is opened by the application program. IRAF images can only be opened with READONLY file access. Similarly, if the input file is a raw binary data array, then CFITSIO will convert it on the fly into a virtual FITS image with the basic set of required header keywords before it is opened by the application program (with READONLY access). In this case the data type and dimensions of the image must be specified in square brackets following the filename (e.g. rawfile.dat[ib512,512]). The first character (case insensitive) defines the data type of the array: \begin{verbatim} b 8-bit unsigned byte i 16-bit signed integer u 16-bit unsigned integer j 32-bit signed integer r or f 32-bit floating point d 64-bit floating point \end{verbatim} An optional second character specifies the byte order of the array values: b or B indicates big endian (as in FITS files and the native format of SUN UNIX workstations and Mac PCs) and l or L indicates little endian (native format of DEC OSF workstations and IBM PCs). If this character is omitted then the array is assumed to have the native byte order of the local machine. These data type characters are then followed by a series of one or more integer values separated by commas which define the size of each dimension of the raw array. Arrays with up to 5 dimensions are currently supported. Finally, a byte offset to the position of the first pixel in the data file may be specified by separating it with a ':' from the last dimension value. If omitted, it is assumed that the offset = 0. This parameter may be used to skip over any header information in the file that precedes the binary data. Further examples: \begin{verbatim} raw.dat[b10000] 1-dimensional 10000 pixel byte array raw.dat[rb400,400,12] 3-dimensional floating point big-endian array img.fits[ib512,512:2880] reads the 512 x 512 short integer array in a FITS file, skipping over the 2880 byte header \end{verbatim} One special case of input file is where the filename = `-' (a dash or minus sign) or 'stdin' or 'stdout', which signifies that the input file is to be read from the stdin stream, or written to the stdout stream if a new output file is being created. In the case of reading from stdin, CFITSIO first copies the whole stream into a temporary FITS file (in memory or on disk), and subsequent reading of the FITS file occurs in this copy. When writing to stdout, CFITSIO first constructs the whole file in memory (since random access is required), then flushes it out to the stdout stream when the file is closed. In addition, if the output filename = '-.gz' or 'stdout.gz' then it will be gzip compressed before being written to stdout. This ability to read and write on the stdin and stdout steams allows FITS files to be piped between tasks in memory rather than having to create temporary intermediate FITS files on disk. For example if task1 creates an output FITS file, and task2 reads an input FITS file, the FITS file may be piped between the 2 tasks by specifying \begin{verbatim} task1 - | task2 - \end{verbatim} where the vertical bar is the Unix piping symbol. This assumes that the 2 tasks read the name of the FITS file off of the command line. \section{Output File Name when Opening an Existing File} An optional output filename may be specified in parentheses immediately following the base file name to be opened. This is mainly useful in those cases where CFITSIO creates a temporary copy of the input FITS file before it is opened and passed to the application program. This happens by default when opening a network FTP or HTTP-type file, when reading a compressed FITS file on a local disk, when reading from the stdin stream, or when a column filter, row filter, or binning specifier is included as part of the input file specification. By default this temporary file is created in memory. If there is not enough memory to create the file copy, then CFITSIO will exit with an error. In these cases one can force a permanent file to be created on disk, instead of a temporary file in memory, by supplying the name in parentheses immediately following the base file name. The output filename can include the '!' clobber flag. Thus, if the input filename to CFITSIO is: \verb+file1.fits.gz(file2.fits)+ then CFITSIO will uncompress `file1.fits.gz' into the local disk file `file2.fits' before opening it. CFITSIO does not automatically delete the output file, so it will still exist after the application program exits. The output filename "mem://" is also allowed, which will write the output file into memory, and also allow write access to the file. This 'file' will disappear when it is closed, but this may be useful for some applications which only need to modify a temporary copy of the file. In some cases, several different temporary FITS files will be created in sequence, for instance, if one opens a remote file using FTP, then filters rows in a binary table extension, then create an image by binning a pair of columns. In this case, the remote file will be copied to a temporary local file, then a second temporary file will be created containing the filtered rows of the table, and finally a third temporary file containing the binned image will be created. In cases like this where multiple files are created, the outfile specifier will be interpreted the name of the final file as described below, in descending priority: \begin{itemize} \item as the name of the final image file if an image within a single binary table cell is opened or if an image is created by binning a table column. \item as the name of the file containing the filtered table if a column filter and/or a row filter are specified. \item as the name of the local copy of the remote FTP or HTTP file. \item as the name of the uncompressed version of the FITS file, if a compressed FITS file on local disk has been opened. \item otherwise, the output filename is ignored. \end{itemize} The output file specifier is useful when reading FTP or HTTP-type FITS files since it can be used to create a local disk copy of the file that can be reused in the future. If the output file name = `*' then a local file with the same name as the network file will be created. Note that CFITSIO will behave differently depending on whether the remote file is compressed or not as shown by the following examples: \begin{itemize} \item \verb+ftp://remote.machine/tmp/myfile.fits.gz(*)+ - the remote compressed file is copied to the local compressed file `myfile.fits.gz', which is then uncompressed in local memory before being opened and passed to the application program. \item \verb+ftp://remote.machine/tmp/myfile.fits.gz(myfile.fits)+ - the remote compressed file is copied and uncompressed into the local file `myfile.fits'. This example requires less local memory than the previous example since the file is uncompressed on disk instead of in memory. \item \verb+ftp://remote.machine/tmp/myfile.fits(myfile.fits.gz)+ - this will usually produce an error since CFITSIO itself cannot compress files. \end{itemize} The exact behavior of CFITSIO in the latter case depends on the type of ftp server running on the remote machine and how it is configured. In some cases, if the file `myfile.fits.gz' exists on the remote machine, then the server will copy it to the local machine. In other cases the ftp server will automatically create and transmit a compressed version of the file if only the uncompressed version exists. This can get rather confusing, so users should use a certain amount of caution when using the output file specifier with FTP or HTTP file types, to make sure they get the behavior that they expect. \section{Template File Name when Creating a New File} When a new FITS file is created with a call to fits\_create\_file, the name of a template file may be supplied in parentheses immediately following the name of the new file to be created. This template is used to define the structure of one or more HDUs in the new file. The template file may be another FITS file, in which case the newly created file will have exactly the same keywords in each HDU as in the template FITS file, but all the data units will be filled with zeros. The template file may also be an ASCII text file, where each line (in general) describes one FITS keyword record. The format of the ASCII template file is described in the following Template Files chapter. \section{Image Tile-Compression Specification} When specifying the name of the output FITS file to be created, the user can indicate that images should be written in tile-compressed format (see section 5.5, ``Primary Array or IMAGE Extension I/O Routines'') by enclosing the compression parameters in square brackets following the root disk file name. Here are some examples of the syntax for specifying tile-compressed output images: \begin{verbatim} myfile.fit[compress] - use Rice algorithm and default tile size myfile.fit[compress GZIP] - use the specified compression algorithm; myfile.fit[compress Rice] only the first letter of the algorithm myfile.fit[compress PLIO] name is required. myfile.fit[compress Rice 100,100] - use 100 x 100 pixel tile size myfile.fit[compress Rice 100,100;2] - as above, and use noisebits = 2 \end{verbatim} \section{HDU Location Specification} The optional HDU location specifier defines which HDU (Header-Data Unit, also known as an `extension') within the FITS file to initially open. It must immediately follow the base file name (or the output file name if present). If it is not specified then the first HDU (the primary array) is opened. The HDU location specifier is required if the colFilter, rowFilter, or binSpec specifiers are present, because the primary array is not a valid HDU for these operations. The HDU may be specified either by absolute position number, starting with 0 for the primary array, or by reference to the HDU name, and optionally, the version number and the HDU type of the desired extension. The location of an image within a single cell of a binary table may also be specified, as described below. The absolute position of the extension is specified either by enclosed the number in square brackets (e.g., `[1]' = the first extension following the primary array) or by preceded the number with a plus sign (`+1'). To specify the HDU by name, give the name of the desired HDU (the value of the EXTNAME or HDUNAME keyword) and optionally the extension version number (value of the EXTVER keyword) and the extension type (value of the XTENSION keyword: IMAGE, ASCII or TABLE, or BINTABLE), separated by commas and all enclosed in square brackets. If the value of EXTVER and XTENSION are not specified, then the first extension with the correct value of EXTNAME is opened. The extension name and type are not case sensitive, and the extension type may be abbreviated to a single letter (e.g., I = IMAGE extension or primary array, A or T = ASCII table extension, and B = binary table BINTABLE extension). If the HDU location specifier is equal to `[PRIMARY]' or `[P]', then the primary array (the first HDU) will be opened. An optional pound sign character ("\#") may be appended to the extension name or number to signify that any other extensions in the file should be ignored during any subsequent file filtering operations. For example, when doing row filtering operations on a table extension, CFITSIO normally creates a copy of the filtered table in memory, along with a verbatim copy of all the other extensions in the input FITS file. If the pound sign is appended to the table extension name, then only that extension, and none of the other extensions in the file, will by copied to memory, as in the following example: \begin{verbatim} myfile.fit[events#][TIME > 10000] \end{verbatim} FITS images are most commonly stored in the primary array or an image extension, but images can also be stored as a vector in a single cell of a binary table (i.e. each row of the vector column contains a different image). Such an image can be opened with CFITSIO by specifying the desired column name and the row number after the binary table HDU specifier as shown in the following examples. The column name is separated from the HDU specifier by a semicolon and the row number is enclosed in parentheses. In this case CFITSIO copies the image from the table cell into a temporary primary array before it is opened. The application program then just sees the image in the primary array, without any extensions. The particular row to be opened may be specified either by giving an absolute integer row number (starting with 1 for the first row), or by specifying a boolean expression that evaluates to TRUE for the desired row. The first row that satisfies the expression will be used. The row selection expression has the same syntax as described in the Row Filter Specifier section, below. Examples: \begin{verbatim} myfile.fits[3] - open the 3rd HDU following the primary array myfile.fits+3 - same as above, but using the FTOOLS-style notation myfile.fits[EVENTS] - open the extension that has EXTNAME = 'EVENTS' myfile.fits[EVENTS, 2] - same as above, but also requires EXTVER = 2 myfile.fits[events,2,b] - same, but also requires XTENSION = 'BINTABLE' myfile.fits[3; images(17)] - opens the image in row 17 of the 'images' column in the 3rd extension of the file. myfile.fits[3; images(exposure > 100)] - as above, but opens the image in the first row that has an 'exposure' column value greater than 100. \end{verbatim} \section{Image Section} A virtual file containing a rectangular subsection of an image can be extracted and opened by specifying the range of pixels (start:end) along each axis to be extracted from the original image. One can also specify an optional pixel increment (start:end:step) for each axis of the input image. A pixel step = 1 will be assumed if it is not specified. If the start pixel is larger then the end pixel, then the image will be flipped (producing a mirror image) along that dimension. An asterisk, '*', may be used to specify the entire range of an axis, and '-*' will flip the entire axis. The input image can be in the primary array, in an image extension, or contained in a vector cell of a binary table. In the later 2 cases the extension name or number must be specified before the image section specifier. Examples: \begin{verbatim} myfile.fits[1:512:2, 2:512:2] - open a 256x256 pixel image consisting of the odd numbered columns (1st axis) and the even numbered rows (2nd axis) of the image in the primary array of the file. myfile.fits[*, 512:256] - open an image consisting of all the columns in the input image, but only rows 256 through 512. The image will be flipped along the 2nd axis since the starting pixel is greater than the ending pixel. myfile.fits[*:2, 512:256:2] - same as above but keeping only every other row and column in the input image. myfile.fits[-*, *] - copy the entire image, flipping it along the first axis. myfile.fits[3][1:256,1:256] - opens a subsection of the image that is in the 3rd extension of the file. myfile.fits[4; images(12)][1:10,1:10] - open an image consisting of the first 10 pixels in both dimensions. The original image resides in the 12th row of the 'images' vector column in the table in the 4th extension of the file. \end{verbatim} When CFITSIO opens an image section it first creates a temporary file containing the image section plus a copy of any other HDUs in the file. (If a `\#' character is appended to the name or number of the image HDU, as in "myfile.fits[1\#][1:200,1:200]", then the other HDUs in the input file will not be copied into memory). This temporary file is then opened by the application program, so it is not possible to write to or modify the input file when specifying an image section. Note that CFITSIO automatically updates the world coordinate system keywords in the header of the image section, if they exist, so that the coordinate associated with each pixel in the image section will be computed correctly. \section{Image Transform Filters} CFITSIO can apply a user-specified mathematical function to the value of every pixel in a FITS image, thus creating a new virtual image in computer memory that is then opened and read by the application program. The original FITS image is not modified by this process. The image transformation specifier is appended to the input FITS file name and is enclosed in square brackets. It begins with the letters 'PIX' to distinguish it from other types of FITS file filters that are recognized by CFITSIO. The image transforming function may use any of the mathematical operators listed in the following 'Row Filtering Specification' section of this document. Some examples of image transform filters are: \begin{verbatim} [pix X * 2.0] - multiply each pixel by 2.0 [pix sqrt(X)] - take the square root of each pixel [pix X + #ZEROPT - add the value of the ZEROPT keyword [pix X>0 ? log10(X) : -99.] - if the pixel value is greater than 0, compute the base 10 log, else set the pixel = -99. \end{verbatim} Use the letter 'X' in the expression to represent the current pixel value in the image. The expression is evaluated independently for each pixel in the image and may be a function of 1) the original pixel value, 2) the value of other pixels in the image at a given relative offset from the position of the pixel that is being evaluated, and 3) the value of any header keywords. Header keyword values are represented by the name of the keyword preceded by the '\#' sign. To access the the value of adjacent pixels in the image, specify the (1-D) offset from the current pixel in curly brackets. For example \begin{verbatim} [pix (x{-1} + x + x{+1}) / 3] \end{verbatim} will replace each pixel value with the running mean of the values of that pixel and it's 2 neighboring pixels. Note that in this notation the image is treated as a 1-D array, where each row of the image (or higher dimensional cube) is appended one after another in one long array of pixels. It is possible to refer to pixels in the rows above or below the current pixel by using the value of the NAXIS1 header keyword. For example \begin{verbatim} [pix (x{-#NAXIS1} + x + x{#NAXIS1}) / 3] \end{verbatim} will compute the mean of each image pixel and the pixels immediately above and below it in the adjacent rows of the image. The following more complex example creates a smoothed virtual image where each pixel is a 3 x 3 boxcar average of the input image pixels: \begin{verbatim} [pix (X + X{-1} + X{+1} + X{-#NAXIS1} + X{-#NAXIS1 - 1} + X{-#NAXIS1 + 1} + X{#NAXIS1} + X{#NAXIS1 - 1} + X{#NAXIS1 + 1}) / 9.] \end{verbatim} If the pixel offset extends beyond the first or last pixel in the image, the function will evaluate to undefined, or NULL. For complex or commonly used image filtering operations, one can write the expression into an external text file and then import it into the filter using the syntax '[pix @filename.txt]'. The mathematical expression can extend over multiple lines of text in the file. Any lines in the external text file that begin with 2 slash characters ('//') will be ignored and may be used to add comments into the file. By default, the datatype of the resulting image will be the same as the original image, but one may force a different datatype by appended a code letter to the 'pix' keyword: \begin{verbatim} pixb - 8-bit byte image with BITPIX = 8 pixi - 16-bit integer image with BITPIX = 16 pixj - 32-bit integer image with BITPIX = 32 pixr - 32-bit float image with BITPIX = -32 pixd - 64-bit float image with BITPIX = -64 \end{verbatim} Also by default, any other HDUs in the input file will be copied without change to the output virtual FITS file, but one may discard the other HDUs by adding the number '1' to the 'pix' keyword (and following any optional datatype code letter). For example: \begin{verbatim} myfile.fits[3][pixr1 sqrt(X)] \end{verbatim} will create a virtual FITS file containing only a primary array image with 32-bit floating point pixels that have a value equal to the square root of the pixels in the image that is in the 3rd extension of the 'myfile.fits' file. \section{Column and Keyword Filtering Specification} The optional column/keyword filtering specifier is used to modify the column structure and/or the header keywords in the HDU that was selected with the previous HDU location specifier. This filtering specifier must be enclosed in square brackets and can be distinguished from a general row filter specifier (described below) by the fact that it begins with the string 'col ' and is not immediately followed by an equals sign. The original file is not changed by this filtering operation, and instead the modifications are made on a copy of the input FITS file (usually in memory), which also contains a copy of all the other HDUs in the file. (If a `\#' character is appended to the name or number of the table HDU then only the primary array, and none of the other HDUs in the input file will be copied into memory). This temporary file is passed to the application program and will persist only until the file is closed or until the program exits, unless the outfile specifier (see above) is also supplied. The column/keyword filter can be used to perform the following operations. More than one operation may be specified by separating them with commas or semi-colons. \begin{itemize} \item Copy only a specified list of columns columns to the filtered input file. The list of column name should be separated by commas or semi-colons. Wild card characters may be used in the column names to match multiple columns. If the expression contains both a list of columns to be included and columns to be deleted, then all the columns in the original table except the explicitly deleted columns will appear in the filtered table (i.e., there is no need to explicitly list the columns to be included if any columns are being deleted). \item Delete a column or keyword by listing the name preceded by a minus sign or an exclamation mark (!), e.g., '-TIME' will delete the TIME column if it exists, otherwise the TIME keyword. An error is returned if neither a column nor keyword with this name exists. Note that the exclamation point, '!', is a special UNIX character, so if it is used on the command line rather than entered at a task prompt, it must be preceded by a backslash to force the UNIX shell to ignore it. \item Rename an existing column or keyword with the syntax 'NewName == OldName'. An error is returned if neither a column nor keyword with this name exists. \item Append a new column or keyword to the table. To create a column, give the new name, optionally followed by the data type in parentheses, followed by a single equals sign and an expression to be used to compute the value (e.g., 'newcol(1J) = 0' will create a new 32-bit integer column called 'newcol' filled with zeros). The data type is specified using the same syntax that is allowed for the value of the FITS TFORMn keyword (e.g., 'I', 'J', 'E', 'D', etc. for binary tables, and 'I8', F12.3', 'E20.12', etc. for ASCII tables). If the data type is not specified then an appropriate data type will be chosen depending on the form of the expression (may be a character string, logical, bit, long integer, or double column). An appropriate vector count (in the case of binary tables) will also be added if not explicitly specified. When creating a new keyword, the keyword name must be preceded by a pound sign '\#', and the expression must evaluate to a scalar (i.e., cannot have a column name in the expression). The comment string for the keyword may be specified in parentheses immediately following the keyword name (instead of supplying a data type as in the case of creating a new column). If the keyword name ends with a pound sign '\#', then cfitsio will substitute the number of the most recently referenced column for the \# character . This is especially useful when writing a column-related keyword like TUNITn for a newly created column, as shown in the following examples. COMMENT and HISTORY keywords may also be created with the following syntax: \begin{verbatim} #COMMENT = 'This is a comment keyword' #HISTORY = 'This is a history keyword' \end{verbatim} Note that the equal sign and the quote characters will be removed, so that the resulting header keywords in these cases will look like this: \begin{verbatim} COMMENT This is a comment keyword HISTORY This is a history keyword \end{verbatim} These two special keywords are always appended to the end of the header and will not affect any previously existing COMMENT or HISTORY keywords. \item Recompute (overwrite) the values in an existing column or keyword by giving the name followed by an equals sign and an arithmetic expression. \end{itemize} The expression that is used when appending or recomputing columns or keywords can be arbitrarily complex and may be a function of other header keyword values and other columns (in the same row). The full syntax and available functions for the expression are described below in the row filter specification section. If the expression contains both a list of columns to be included and columns to be deleted, then all the columns in the original table except the explicitly deleted columns will appear in the filtered table. If no columns to be deleted are specified, then only the columns that are explicitly listed will be included in the filtered output table. To include all the columns, add the '*' wildcard specifier at the end of the list, as shown in the examples. For complex or commonly used operations, one can place the operations into an external text file and import it into the column filter using the syntax '[col @filename.txt]'. The operations can extend over multiple lines of the file, but multiple operations must still be separated by commas or semi-colons. Any lines in the external text file that begin with 2 slash characters ('//') will be ignored and may be used to add comments into the file. Examples: \begin{verbatim} [col Time, rate] - only the Time and rate columns will appear in the filtered input file. [col Time, *raw] - include the Time column and any other columns whose name ends with 'raw'. [col -TIME, Good == STATUS] - deletes the TIME column and renames the status column to 'Good' [col PI=PHA * 1.1 + 0.2; #TUNIT#(column units) = 'counts';*] - creates new PI column from PHA values and also writes the TUNITn keyword for the new column. The final '*' expression means preserve all the columns in the input table in the virtual output table; without the '*' the output table would only contain the single 'PI' column. [col rate = rate/exposure; TUNIT#(&) = 'counts/s';*] - recomputes the rate column by dividing it by the EXPOSURE keyword value. This also modifies the value of the TUNITn keyword for this column. The use of the '&' character for the keyword comment string means preserve the existing comment string for that keyword. The final '*' preserves all the columns in the input table in the virtual output table. \end{verbatim} \section{Row Filtering Specification} When entering the name of a FITS table that is to be opened by a program, an optional row filter may be specified to select a subset of the rows in the table. A temporary new FITS file is created on the fly which contains only those rows for which the row filter expression evaluates to true. The primary array and any other extensions in the input file are also copied to the temporary file. (If a `\#' character is appended to the name or number of the table HDU then only the primary array, and none of the other HDUs in the input file will be copied into the temporary file). The original FITS file is closed and the new virtual file is opened by the application program. The row filter expression is enclosed in square brackets following the file name and extension name (e.g., 'file.fits[events][GRADE==50]' selects only those rows where the GRADE column value equals 50). When dealing with tables where each row has an associated time and/or 2D spatial position, the row filter expression can also be used to select rows based on the times in a Good Time Intervals (GTI) extension, or on spatial position as given in a SAO-style region file. \subsection{General Syntax} The row filtering expression can be an arbitrarily complex series of operations performed on constants, keyword values, and column data taken from the specified FITS TABLE extension. The expression must evaluate to a boolean value for each row of the table, where a value of FALSE means that the row will be excluded. For complex or commonly used filters, one can place the expression into a text file and import it into the row filter using the syntax '[@filename.txt]'. The expression can be arbitrarily complex and extend over multiple lines of the file. Any lines in the external text file that begin with 2 slash characters ('//') will be ignored and may be used to add comments into the file. Keyword and column data are referenced by name. Any string of characters not surrounded by quotes (ie, a constant string) or followed by an open parentheses (ie, a function name) will be initially interpreted as a column name and its contents for the current row inserted into the expression. If no such column exists, a keyword of that name will be searched for and its value used, if found. To force the name to be interpreted as a keyword (in case there is both a column and keyword with the same name), precede the keyword name with a single pound sign, '\#', as in '\#NAXIS2'. Due to the generalities of FITS column and keyword names, if the column or keyword name contains a space or a character which might appear as an arithmetic term then enclose the name in '\$' characters as in \$MAX PHA\$ or \#\$MAX-PHA\$. Names are case insensitive. To access a table entry in a row other than the current one, follow the column's name with a row offset within curly braces. For example, 'PHA\{-3\}' will evaluate to the value of column PHA, 3 rows above the row currently being processed. One cannot specify an absolute row number, only a relative offset. Rows that fall outside the table will be treated as undefined, or NULLs. Boolean operators can be used in the expression in either their Fortran or C forms. The following boolean operators are available: \begin{verbatim} "equal" .eq. .EQ. == "not equal" .ne. .NE. != "less than" .lt. .LT. < "less than/equal" .le. .LE. <= =< "greater than" .gt. .GT. > "greater than/equal" .ge. .GE. >= => "or" .or. .OR. || "and" .and. .AND. && "negation" .not. .NOT. ! "approx. equal(1e-7)" ~ \end{verbatim} Note that the exclamation point, '!', is a special UNIX character, so if it is used on the command line rather than entered at a task prompt, it must be preceded by a backslash to force the UNIX shell to ignore it. The expression may also include arithmetic operators and functions. Trigonometric functions use radians, not degrees. The following arithmetic operators and functions can be used in the expression (function names are case insensitive). A null value will be returned in case of illegal operations such as divide by zero, sqrt(negative) log(negative), log10(negative), arccos(.gt. 1), arcsin(.gt. 1). \begin{verbatim} "addition" + "subtraction" - "multiplication" * "division" / "negation" - "exponentiation" ** ^ "absolute value" abs(x) "cosine" cos(x) "sine" sin(x) "tangent" tan(x) "arc cosine" arccos(x) "arc sine" arcsin(x) "arc tangent" arctan(x) "arc tangent" arctan2(y,x) "hyperbolic cos" cosh(x) "hyperbolic sin" sinh(x) "hyperbolic tan" tanh(x) "round to nearest int" round(x) "round down to int" floor(x) "round up to int" ceil(x) "exponential" exp(x) "square root" sqrt(x) "natural log" log(x) "common log" log10(x) "modulus" x % y "random # [0.0,1.0)" random() "random Gaussian" randomn() "random Poisson" randomp(x) "minimum" min(x,y) "maximum" max(x,y) "cumulative sum" accum(x) "sequential difference" seqdiff(x) "if-then-else" b?x:y "angular separation" angsep(ra1,dec1,ra2,de2) (all in degrees) "substring" strmid(s,p,n) "string search" strstr(s,r) \end{verbatim} Three different random number functions are provided: random(), with no arguments, produces a uniform random deviate between 0 and 1; randomn(), also with no arguments, produces a normal (Gaussian) random deviate with zero mean and unit standard deviation; randomp(x) produces a Poisson random deviate whose expected number of counts is X. X may be any positive real number of expected counts, including fractional values, but the return value is an integer. When the random functions are used in a vector expression, by default the same random value will be used when evaluating each element of the vector. If different random numbers are desired, then the name of a vector column should be supplied as the single argument to the random function (e.g., "flux + 0.1 * random(flux)", where "flux' is the name of a vector column). This will create a vector of random numbers that will be used in sequence when evaluating each element of the vector expression. An alternate syntax for the min and max functions has only a single argument which should be a vector value (see below). The result will be the minimum/maximum element contained within the vector. The accum(x) function forms the cumulative sum of x, element by element. Vector columns are supported simply by performing the summation process through all the values. Null values are treated as 0. The seqdiff(x) function forms the sequential difference of x, element by element. The first value of seqdiff is the first value of x. A single null value in x causes a pair of nulls in the output. The seqdiff and accum functions are functional inverses, i.e., seqdiff(accum(x)) == x as long as no null values are present. In the if-then-else expression, "b?x:y", b is an explicit boolean value or expression. There is no automatic type conversion from numeric to boolean values, so one needs to use "iVal!=0" instead of merely "iVal" as the boolean argument. x and y can be any scalar data type (including string). The angsep function computes the angular separation in degrees between 2 celestial positions, where the first 2 parameters give the RA-like and Dec-like coordinates (in decimal degrees) of the first position, and the 3rd and 4th parameters give the coordinates of the second position. The substring function strmid(S,P,N) extracts a substring from S, starting at string position P, with a substring length N. The first character position in S is labeled as 1. If P is 0, or refers to a position beyond the end of S, then the extracted substring will be NULL. S, P, and N may be functions of other columns. The string search function strstr(S,R) searches for the first occurrence of the substring R in S. The result is an integer, indicating the character position of the first match (where 1 is the first character position of S). If no match is found, then strstr() returns a NULL value. The following type casting operators are available, where the inclosing parentheses are required and taken from the C language usage. Also, the integer to real casts values to double precision: \begin{verbatim} "real to integer" (int) x (INT) x "integer to real" (float) i (FLOAT) i \end{verbatim} In addition, several constants are built in for use in numerical expressions: \begin{verbatim} #pi 3.1415... #e 2.7182... #deg #pi/180 #row current row number #null undefined value #snull undefined string \end{verbatim} A string constant must be enclosed in quotes as in 'Crab'. The "null" constants are useful for conditionally setting table values to a NULL, or undefined, value (eg., "col1==-99 ? \#NULL : col1"). There is also a function for testing if two values are close to each other, i.e., if they are "near" each other to within a user specified tolerance. The arguments, value\_1 and value\_2 can be integer or real and represent the two values who's proximity is being tested to be within the specified tolerance, also an integer or real: \begin{verbatim} near(value_1, value_2, tolerance) \end{verbatim} When a NULL, or undefined, value is encountered in the FITS table, the expression will evaluate to NULL unless the undefined value is not actually required for evaluation, e.g. "TRUE .or. NULL" evaluates to TRUE. The following two functions allow some NULL detection and handling: \begin{verbatim} "a null value?" ISNULL(x) "define a value for null" DEFNULL(x,y) \end{verbatim} The former returns a boolean value of TRUE if the argument x is NULL. The later "defines" a value to be substituted for NULL values; it returns the value of x if x is not NULL, otherwise it returns the value of y. \subsection{Bit Masks} Bit masks can be used to select out rows from bit columns (TFORMn = \#X) in FITS files. To represent the mask, binary, octal, and hex formats are allowed: \begin{verbatim} binary: b0110xx1010000101xxxx0001 octal: o720x1 -> (b111010000xxx001) hex: h0FxD -> (b00001111xxxx1101) \end{verbatim} In all the representations, an x or X is allowed in the mask as a wild card. Note that the x represents a different number of wild card bits in each representation. All representations are case insensitive. To construct the boolean expression using the mask as the boolean equal operator described above on a bit table column. For example, if you had a 7 bit column named flags in a FITS table and wanted all rows having the bit pattern 0010011, the selection expression would be: \begin{verbatim} flags == b0010011 or flags .eq. b10011 \end{verbatim} It is also possible to test if a range of bits is less than, less than equal, greater than and greater than equal to a particular boolean value: \begin{verbatim} flags <= bxxx010xx flags .gt. bxxx100xx flags .le. b1xxxxxxx \end{verbatim} Notice the use of the x bit value to limit the range of bits being compared. It is not necessary to specify the leading (most significant) zero (0) bits in the mask, as shown in the second expression above. Bit wise AND, OR and NOT operations are also possible on two or more bit fields using the '\&'(AND), '$|$'(OR), and the '!'(NOT) operators. All of these operators result in a bit field which can then be used with the equal operator. For example: \begin{verbatim} (!flags) == b1101100 (flags & b1000001) == bx000001 \end{verbatim} Bit fields can be appended as well using the '+' operator. Strings can be concatenated this way, too. \subsection{Vector Columns} Vector columns can also be used in building the expression. No special syntax is required if one wants to operate on all elements of the vector. Simply use the column name as for a scalar column. Vector columns can be freely intermixed with scalar columns or constants in virtually all expressions. The result will be of the same dimension as the vector. Two vectors in an expression, though, need to have the same number of elements and have the same dimensions. Arithmetic and logical operations are all performed on an element by element basis. Comparing two vector columns, eg "COL1 == COL2", thus results in another vector of boolean values indicating which elements of the two vectors are equal. Eight functions are available that operate on a vector and return a scalar result: \begin{verbatim} "minimum" MIN(V) "maximum" MAX(V) "average" AVERAGE(V) "median" MEDIAN(V) "summation" SUM(V) "standard deviation" STDDEV(V) "# of values" NELEM(V) "# of non-null values" NVALID(V) \end{verbatim} where V represents the name of a vector column or a manually constructed vector using curly brackets as described below. The first 6 of these functions ignore any null values in the vector when computing the result. The STDDEV() function computes the sample standard deviation, i.e. it is proportional to 1/SQRT(N-1) instead of 1/SQRT(N), where N is NVALID(V). The SUM function literally sums all the elements in x, returning a scalar value. If V is a boolean vector, SUM returns the number of TRUE elements. The NELEM function returns the number of elements in vector V whereas NVALID return the number of non-null elements in the vector. (NELEM also operates on bit and string columns, returning their column widths.) As an example, to test whether all elements of two vectors satisfy a given logical comparison, one can use the expression \begin{verbatim} SUM( COL1 > COL2 ) == NELEM( COL1 ) \end{verbatim} which will return TRUE if all elements of COL1 are greater than their corresponding elements in COL2. To specify a single element of a vector, give the column name followed by a comma-separated list of coordinates enclosed in square brackets. For example, if a vector column named PHAS exists in the table as a one dimensional, 256 component list of numbers from which you wanted to select the 57th component for use in the expression, then PHAS[57] would do the trick. Higher dimensional arrays of data may appear in a column. But in order to interpret them, the TDIMn keyword must appear in the header. Assuming that a (4,4,4,4) array is packed into each row of a column named ARRAY4D, the (1,2,3,4) component element of each row is accessed by ARRAY4D[1,2,3,4]. Arrays up to dimension 5 are currently supported. Each vector index can itself be an expression, although it must evaluate to an integer value within the bounds of the vector. Vector columns which contain spaces or arithmetic operators must have their names enclosed in "\$" characters as with \$ARRAY-4D\$[1,2,3,4]. A more C-like syntax for specifying vector indices is also available. The element used in the preceding example alternatively could be specified with the syntax ARRAY4D[4][3][2][1]. Note the reverse order of indices (as in C), as well as the fact that the values are still ones-based (as in Fortran -- adopted to avoid ambiguity for 1D vectors). With this syntax, one does not need to specify all of the indices. To extract a 3D slice of this 4D array, use ARRAY4D[4]. Variable-length vector columns are not supported. Vectors can be manually constructed within the expression using a comma-separated list of elements surrounded by curly braces ('\{\}'). For example, '\{1,3,6,1\}' is a 4-element vector containing the values 1, 3, 6, and 1. The vector can contain only boolean, integer, and real values (or expressions). The elements will be promoted to the highest data type present. Any elements which are themselves vectors, will be expanded out with each of its elements becoming an element in the constructed vector. \subsection{Good Time Interval Filtering} A common filtering method involves selecting rows which have a time value which lies within what is called a Good Time Interval or GTI. The time intervals are defined in a separate FITS table extension which contains 2 columns giving the start and stop time of each good interval. The filtering operation accepts only those rows of the input table which have an associated time which falls within one of the time intervals defined in the GTI extension. A high level function, gtifilter(a,b,c,d), is available which evaluates each row of the input table and returns TRUE or FALSE depending whether the row is inside or outside the good time interval. The syntax is \begin{verbatim} gtifilter( [ "gtifile" [, expr [, "STARTCOL", "STOPCOL" ] ] ] ) or gtifilter( [ 'gtifile' [, expr [, 'STARTCOL', 'STOPCOL' ] ] ] ) \end{verbatim} where each "[]" demarks optional parameters. Note that the quotes around the gtifile and START/STOP column are required. Either single or double quotes may be used. In cases where this expression is entered on the Unix command line, enclose the entire expression in double quotes, and then use single quotes within the expression to enclose the 'gtifile' and other terms. It is also usually possible to do the reverse, and enclose the whole expression in single quotes and then use double quotes within the expression. The gtifile, if specified, can be blank ("") which will mean to use the first extension with the name "*GTI*" in the current file, a plain extension specifier (eg, "+2", "[2]", or "[STDGTI]") which will be used to select an extension in the current file, or a regular filename with or without an extension specifier which in the latter case will mean to use the first extension with an extension name "*GTI*". Expr can be any arithmetic expression, including simply the time column name. A vector time expression will produce a vector boolean result. STARTCOL and STOPCOL are the names of the START/STOP columns in the GTI extension. If one of them is specified, they both must be. In its simplest form, no parameters need to be provided -- default values will be used. The expression "gtifilter()" is equivalent to \begin{verbatim} gtifilter( "", TIME, "*START*", "*STOP*" ) \end{verbatim} This will search the current file for a GTI extension, filter the TIME column in the current table, using START/STOP times taken from columns in the GTI extension with names containing the strings "START" and "STOP". The wildcards ('*') allow slight variations in naming conventions such as "TSTART" or "STARTTIME". The same default values apply for unspecified parameters when the first one or two parameters are specified. The function automatically searches for TIMEZERO/I/F keywords in the current and GTI extensions, applying a relative time offset, if necessary. \subsection{Spatial Region Filtering} Another common filtering method selects rows based on whether the spatial position associated with each row is located within a given 2-dimensional region. The syntax for this high-level filter is \begin{verbatim} regfilter( "regfilename" [ , Xexpr, Yexpr [ , "wcs cols" ] ] ) \end{verbatim} where each "[]" demarks optional parameters. The region file name is required and must be enclosed in quotes. The remaining parameters are optional. There are 2 supported formats for the region file: ASCII file or FITS binary table. The region file contains a list of one or more geometric shapes (circle, ellipse, box, etc.) which defines a region on the celestial sphere or an area within a particular 2D image. The region file is typically generated using an image display program such as fv/POW (distribute by the HEASARC), or ds9 (distributed by the Smithsonian Astrophysical Observatory). Users should refer to the documentation provided with these programs for more details on the syntax used in the region files. The FITS region file format is defined in a document available from the FITS Support Office at http://fits.gsfc.nasa.gov/ registry/ region.html In its simplest form, (e.g., regfilter("region.reg") ) the coordinates in the default 'X' and 'Y' columns will be used to determine if each row is inside or outside the area specified in the region file. Alternate position column names, or expressions, may be entered if needed, as in \begin{verbatim} regfilter("region.reg", XPOS, YPOS) \end{verbatim} Region filtering can be applied most unambiguously if the positions in the region file and in the table to be filtered are both give in terms of absolute celestial coordinate units. In this case the locations and sizes of the geometric shapes in the region file are specified in angular units on the sky (e.g., positions given in R.A. and Dec. and sizes in arcseconds or arcminutes). Similarly, each row of the filtered table will have a celestial coordinate associated with it. This association is usually implemented using a set of so-called 'World Coordinate System' (or WCS) FITS keywords that define the coordinate transformation that must be applied to the values in the 'X' and 'Y' columns to calculate the coordinate. Alternatively, one can perform spatial filtering using unitless 'pixel' coordinates for the regions and row positions. In this case the user must be careful to ensure that the positions in the 2 files are self-consistent. A typical problem is that the region file may be generated using a binned image, but the unbinned coordinates are given in the event table. The ROSAT events files, for example, have X and Y pixel coordinates that range from 1 - 15360. These coordinates are typically binned by a factor of 32 to produce a 480x480 pixel image. If one then uses a region file generated from this image (in image pixel units) to filter the ROSAT events file, then the X and Y column values must be converted to corresponding pixel units as in: \begin{verbatim} regfilter("rosat.reg", X/32.+.5, Y/32.+.5) \end{verbatim} Note that this binning conversion is not necessary if the region file is specified using celestial coordinate units instead of pixel units because CFITSIO is then able to directly compare the celestial coordinate of each row in the table with the celestial coordinates in the region file without having to know anything about how the image may have been binned. The last "wcs cols" parameter should rarely be needed. If supplied, this string contains the names of the 2 columns (space or comma separated) which have the associated WCS keywords. If not supplied, the filter will scan the X and Y expressions for column names. If only one is found in each expression, those columns will be used, otherwise an error will be returned. These region shapes are supported (names are case insensitive): \begin{verbatim} Point ( X1, Y1 ) <- One pixel square region Line ( X1, Y1, X2, Y2 ) <- One pixel wide region Polygon ( X1, Y1, X2, Y2, ... ) <- Rest are interiors with Rectangle ( X1, Y1, X2, Y2, A ) | boundaries considered Box ( Xc, Yc, Wdth, Hght, A ) V within the region Diamond ( Xc, Yc, Wdth, Hght, A ) Circle ( Xc, Yc, R ) Annulus ( Xc, Yc, Rin, Rout ) Ellipse ( Xc, Yc, Rx, Ry, A ) Elliptannulus ( Xc, Yc, Rinx, Riny, Routx, Routy, Ain, Aout ) Sector ( Xc, Yc, Amin, Amax ) \end{verbatim} where (Xc,Yc) is the coordinate of the shape's center; (X\#,Y\#) are the coordinates of the shape's edges; Rxxx are the shapes' various Radii or semimajor/minor axes; and Axxx are the angles of rotation (or bounding angles for Sector) in degrees. For rotated shapes, the rotation angle can be left off, indicating no rotation. Common alternate names for the regions can also be used: rotbox = box; rotrectangle = rectangle; (rot)rhombus = (rot)diamond; and pie = sector. When a shape's name is preceded by a minus sign, '-', the defined region is instead the area *outside* its boundary (ie, the region is inverted). All the shapes within a single region file are OR'd together to create the region, and the order is significant. The overall way of looking at region files is that if the first region is an excluded region then a dummy included region of the whole detector is inserted in the front. Then each region specification as it is processed overrides any selections inside of that region specified by previous regions. Another way of thinking about this is that if a previous excluded region is completely inside of a subsequent included region the excluded region is ignored. The positional coordinates may be given either in pixel units, decimal degrees or hh:mm:ss.s, dd:mm:ss.s units. The shape sizes may be given in pixels, degrees, arcminutes, or arcseconds. Look at examples of region file produced by fv/POW or ds9 for further details of the region file format. There are three low-level functions that are primarily for use with regfilter function, but they can be called directly. They return a boolean true or false depending on whether a two dimensional point is in the region or not. The positional coordinates must be given in pixel units: \begin{verbatim} "point in a circular region" circle(xcntr,ycntr,radius,Xcolumn,Ycolumn) "point in an elliptical region" ellipse(xcntr,ycntr,xhlf_wdth,yhlf_wdth,rotation,Xcolumn,Ycolumn) "point in a rectangular region" box(xcntr,ycntr,xfll_wdth,yfll_wdth,rotation,Xcolumn,Ycolumn) where (xcntr,ycntr) are the (x,y) position of the center of the region (xhlf_wdth,yhlf_wdth) are the (x,y) half widths of the region (xfll_wdth,yfll_wdth) are the (x,y) full widths of the region (radius) is half the diameter of the circle (rotation) is the angle(degrees) that the region is rotated with respect to (xcntr,ycntr) (Xcoord,Ycoord) are the (x,y) coordinates to test, usually column names NOTE: each parameter can itself be an expression, not merely a column name or constant. \end{verbatim} \subsection{Example Row Filters} \begin{verbatim} [ binary && mag <= 5.0] - Extract all binary stars brighter than fifth magnitude (note that the initial space is necessary to prevent it from being treated as a binning specification) [#row >= 125 && #row <= 175] - Extract row numbers 125 through 175 [IMAGE[4,5] .gt. 100] - Extract all rows that have the (4,5) component of the IMAGE column greater than 100 [abs(sin(theta * #deg)) < 0.5] - Extract all rows having the absolute value of the sine of theta less than a half where the angles are tabulated in degrees [SUM( SPEC > 3*BACKGRND )>=1] - Extract all rows containing a spectrum, held in vector column SPEC, with at least one value 3 times greater than the background level held in a keyword, BACKGRND [VCOL=={1,4,2}] - Extract all rows whose vector column VCOL contains the 3-elements 1, 4, and 2. [@rowFilter.txt] - Extract rows using the expression contained within the text file rowFilter.txt [gtifilter()] - Search the current file for a GTI extension, filter the TIME column in the current table, using START/STOP times taken from columns in the GTI extension [regfilter("pow.reg")] - Extract rows which have a coordinate (as given in the X and Y columns) within the spatial region specified in the pow.reg region file. [regfilter("pow.reg", Xs, Ys)] - Same as above, except that the Xs and Ys columns will be used to determine the coordinate of each row in the table. \end{verbatim} \section{ Binning or Histogramming Specification} The optional binning specifier is enclosed in square brackets and can be distinguished from a general row filter specification by the fact that it begins with the keyword 'bin' not immediately followed by an equals sign. When binning is specified, a temporary N-dimensional FITS primary array is created by computing the histogram of the values in the specified columns of a FITS table extension. After the histogram is computed the input FITS file containing the table is then closed and the temporary FITS primary array is opened and passed to the application program. Thus, the application program never sees the original FITS table and only sees the image in the new temporary file (which has no additional extensions). Obviously, the application program must be expecting to open a FITS image and not a FITS table in this case. The data type of the FITS histogram image may be specified by appending 'b' (for 8-bit byte), 'i' (for 16-bit integers), 'j' (for 32-bit integer), 'r' (for 32-bit floating points), or 'd' (for 64-bit double precision floating point) to the 'bin' keyword (e.g. '[binr X]' creates a real floating point image). If the data type is not explicitly specified then a 32-bit integer image will be created by default, unless the weighting option is also specified in which case the image will have a 32-bit floating point data type by default. The histogram image may have from 1 to 4 dimensions (axes), depending on the number of columns that are specified. The general form of the binning specification is: \begin{verbatim} [bin{bijrd} Xcol=min:max:binsize, Ycol= ..., Zcol=..., Tcol=...; weight] \end{verbatim} in which up to 4 columns, each corresponding to an axis of the image, are listed. The column names are case insensitive, and the column number may be given instead of the name, preceded by a pound sign (e.g., [bin \#4=1:512]). If the column name is not specified, then CFITSIO will first try to use the 'preferred column' as specified by the CPREF keyword if it exists (e.g., 'CPREF = 'DETX,DETY'), otherwise column names 'X', 'Y', 'Z', and 'T' will be assumed for each of the 4 axes, respectively. In cases where the column name could be confused with an arithmetic expression, enclose the column name in parentheses to force the name to be interpreted literally. Each column name may be followed by an equals sign and then the lower and upper range of the histogram, and the size of the histogram bins, separated by colons. Spaces are allowed before and after the equals sign but not within the 'min:max:binsize' string. The min, max and binsize values may be integer or floating point numbers, or they may be the names of keywords in the header of the table. If the latter, then the value of that keyword is substituted into the expression. Default values for the min, max and binsize quantities will be used if not explicitly given in the binning expression as shown in these examples: \begin{verbatim} [bin x = :512:2] - use default minimum value [bin x = 1::2] - use default maximum value [bin x = 1:512] - use default bin size [bin x = 1:] - use default maximum value and bin size [bin x = :512] - use default minimum value and bin size [bin x = 2] - use default minimum and maximum values [bin x] - use default minimum, maximum and bin size [bin 4] - default 2-D image, bin size = 4 in both axes [bin] - default 2-D image \end{verbatim} CFITSIO will use the value of the TLMINn, TLMAXn, and TDBINn keywords, if they exist, for the default min, max, and binsize, respectively. If they do not exist then CFITSIO will use the actual minimum and maximum values in the column for the histogram min and max values. The default binsize will be set to 1, or (max - min) / 10., whichever is smaller, so that the histogram will have at least 10 bins along each axis. A shortcut notation is allowed if all the columns/axes have the same binning specification. In this case all the column names may be listed within parentheses, followed by the (single) binning specification, as in: \begin{verbatim} [bin (X,Y)=1:512:2] [bin (X,Y) = 5] \end{verbatim} The optional weighting factor is the last item in the binning specifier and, if present, is separated from the list of columns by a semi-colon. As the histogram is accumulated, this weight is used to incremented the value of the appropriated bin in the histogram. If the weighting factor is not specified, then the default weight = 1 is assumed. The weighting factor may be a constant integer or floating point number, or the name of a keyword containing the weighting value. Or the weighting factor may be the name of a table column in which case the value in that column, on a row by row basis, will be used. In some cases, the column or keyword may give the reciprocal of the actual weight value that is needed. In this case, precede the weight keyword or column name by a slash '/' to tell CFITSIO to use the reciprocal of the value when constructing the histogram. For complex or commonly used histograms, one can also place its description into a text file and import it into the binning specification using the syntax [bin @filename.txt]. The file's contents can extend over multiple lines, although it must still conform to the no-spaces rule for the min:max:binsize syntax and each axis specification must still be comma-separated. Any lines in the external text file that begin with 2 slash characters ('//') will be ignored and may be used to add comments into the file. Examples: \begin{verbatim} [bini detx, dety] - 2-D, 16-bit integer histogram of DETX and DETY columns, using default values for the histogram range and binsize [bin (detx, dety)=16; /exposure] - 2-D, 32-bit real histogram of DETX and DETY columns with a bin size = 16 in both axes. The histogram values are divided by the EXPOSURE keyword value. [bin time=TSTART:TSTOP:0.1] - 1-D lightcurve, range determined by the TSTART and TSTOP keywords, with 0.1 unit size bins. [bin pha, time=8000.:8100.:0.1] - 2-D image using default binning of the PHA column for the X axis, and 1000 bins in the range 8000. to 8100. for the Y axis. [bin @binFilter.txt] - Use the contents of the text file binFilter.txt for the binning specifications. \end{verbatim} \chapter{Template Files } When a new FITS file is created with a call to fits\_create\_file, the name of a template file may be supplied in parentheses immediately following the name of the new file to be created. This template is used to define the structure of one or more HDUs in the new file. The template file may be another FITS file, in which case the newly created file will have exactly the same keywords in each HDU as in the template FITS file, but all the data units will be filled with zeros. The template file may also be an ASCII text file, where each line (in general) describes one FITS keyword record. The format of the ASCII template file is described in the following sections. \section{Detailed Template Line Format} The format of each ASCII template line closely follows the format of a FITS keyword record: \begin{verbatim} KEYWORD = KEYVALUE / COMMENT \end{verbatim} except that free format may be used (e.g., the equals sign may appear at any position in the line) and TAB characters are allowed and are treated the same as space characters. The KEYVALUE and COMMENT fields are optional. The equals sign character is also optional, but it is recommended that it be included for clarity. Any template line that begins with the pound '\#' character is ignored by the template parser and may be use to insert comments into the template file itself. The KEYWORD name field is limited to 8 characters in length and only the letters A-Z, digits 0-9, and the hyphen and underscore characters may be used, without any embedded spaces. Lowercase letters in the template keyword name will be converted to uppercase. Leading spaces in the template line preceding the keyword name are generally ignored, except if the first 8 characters of a template line are all blank, then the entire line is treated as a FITS comment keyword (with a blank keyword name) and is copied verbatim into the FITS header. The KEYVALUE field may have any allowed FITS data type: character string, logical, integer, real, complex integer, or complex real. Integer values must be within the allowed range of a 'signed long' variable; some C compilers only suppport 4-byte long integers with a range from -2147483648 to +2147483647, whereas other C compilers support 8-byte integers with a range of plus or minus 2**63. The character string values need not be enclosed in single quote characters unless they are necessary to distinguish the string from a different data type (e.g. 2.0 is a real but '2.0' is a string). The keyword has an undefined (null) value if the template record only contains blanks following the "=" or between the "=" and the "/" comment field delimiter. String keyword values longer than 68 characters (the maximum length that will fit in a single FITS keyword record) are permitted using the CFITSIO long string convention. They can either be specified as a single long line in the template, or by using multiple lines where the continuing lines contain the 'CONTINUE' keyword, as in this example: \begin{verbatim} LONGKEY = 'This is a long string value that is contin&' CONTINUE 'ued over 2 records' / comment field goes here \end{verbatim} The format of template lines with CONTINUE keyword is very strict: 3 spaces must follow CONTINUE and the rest of the line is copied verbatim to the FITS file. The start of the optional COMMENT field must be preceded by "/", which is used to separate it from the keyword value field. Exceptions are if the KEYWORD name field contains COMMENT, HISTORY, CONTINUE, or if the first 8 characters of the template line are blanks. More than one Header-Data Unit (HDU) may be defined in the template file. The start of an HDU definition is denoted with a SIMPLE or XTENSION template line: 1) SIMPLE begins a Primary HDU definition. SIMPLE may only appear as the first keyword in the template file. If the template file begins with XTENSION instead of SIMPLE, then a default empty Primary HDU is created, and the template is then assumed to define the keywords starting with the first extension following the Primary HDU. 2) XTENSION marks the beginning of a new extension HDU definition. The previous HDU will be closed at this point and processing of the next extension begins. \section{Auto-indexing of Keywords} If a template keyword name ends with a "\#" character, it is said to be 'auto-indexed'. Each "\#" character will be replaced by the current integer index value, which gets reset = 1 at the start of each new HDU in the file (or 7 in the special case of a GROUP definition). The FIRST indexed keyword in each template HDU definition is used as the 'incrementor'; each subsequent occurrence of this SAME keyword will cause the index value to be incremented. This behavior can be rather subtle, as illustrated in the following examples in which the TTYPE keyword is the incrementor in both cases: \begin{verbatim} TTYPE# = TIME TFORM# = 1D TTYPE# = RATE TFORM# = 1E \end{verbatim} will create TTYPE1, TFORM1, TTYPE2, and TFORM2 keywords. But if the template looks like, \begin{verbatim} TTYPE# = TIME TTYPE# = RATE TFORM# = 1D TFORM# = 1E \end{verbatim} this results in a FITS files with TTYPE1, TTYPE2, TFORM2, and TFORM2, which is probably not what was intended! \section{Template Parser Directives} In addition to the template lines which define individual keywords, the template parser recognizes 3 special directives which are each preceded by the backslash character: \verb+ \include, \group+, and \verb+ \end+. The 'include' directive must be followed by a filename. It forces the parser to temporarily stop reading the current template file and begin reading the include file. Once the parser reaches the end of the include file it continues parsing the current template file. Include files can be nested, and HDU definitions can span multiple template files. The start of a GROUP definition is denoted with the 'group' directive, and the end of a GROUP definition is denoted with the 'end' directive. Each GROUP contains 0 or more member blocks (HDUs or GROUPs). Member blocks of type GROUP can contain their own member blocks. The GROUP definition itself occupies one FITS file HDU of special type (GROUP HDU), so if a template specifies 1 group with 1 member HDU like: \begin{verbatim} \group grpdescr = 'demo' xtension bintable # this bintable has 0 cols, 0 rows \end \end{verbatim} then the parser creates a FITS file with 3 HDUs : \begin{verbatim} 1) dummy PHDU 2) GROUP HDU (has 1 member, which is bintable in HDU number 3) 3) bintable (member of GROUP in HDU number 2) \end{verbatim} Technically speaking, the GROUP HDU is a BINTABLE with 6 columns. Applications can define additional columns in a GROUP HDU using TFORMn and TTYPEn (where n is 7, 8, ....) keywords or their auto-indexing equivalents. For a more complicated example of a template file using the group directives, look at the sample.tpl file that is included in the CFITSIO distribution. \section{Formal Template Syntax} The template syntax can formally be defined as follows: \begin{verbatim} TEMPLATE = BLOCK [ BLOCK ... ] BLOCK = { HDU | GROUP } GROUP = \GROUP [ BLOCK ... ] \END HDU = XTENSION [ LINE ... ] { XTENSION | \GROUP | \END | EOF } LINE = [ KEYWORD [ = ] ] [ VALUE ] [ / COMMENT ] X ... - X can be present 1 or more times { X | Y } - X or Y [ X ] - X is optional \end{verbatim} At the topmost level, the template defines 1 or more template blocks. Blocks can be either HDU (Header Data Unit) or a GROUP. For each block the parser creates 1 (or more for GROUPs) FITS file HDUs. \section{Errors} In general the fits\_execute\_template() function tries to be as atomic as possible, so either everything is done or nothing is done. If an error occurs during parsing of the template, fits\_execute\_template() will (try to) delete the top level BLOCK (with all its children if any) in which the error occurred, then it will stop reading the template file and it will return with an error. \section{Examples} 1. This template file will create a 200 x 300 pixel image, with 4-byte integer pixel values, in the primary HDU: \begin{verbatim} SIMPLE = T BITPIX = 32 NAXIS = 2 / number of dimensions NAXIS1 = 100 / length of first axis NAXIS2 = 200 / length of second axis OBJECT = NGC 253 / name of observed object \end{verbatim} The allowed values of BITPIX are 8, 16, 32, -32, or -64, representing, respectively, 8-bit integer, 16-bit integer, 32-bit integer, 32-bit floating point, or 64 bit floating point pixels. 2. To create a FITS table, the template first needs to include XTENSION = TABLE or BINTABLE to define whether it is an ASCII or binary table, and NAXIS2 to define the number of rows in the table. Two template lines are then needed to define the name (TTYPEn) and FITS data format (TFORMn) of the columns, as in this example: \begin{verbatim} xtension = bintable naxis2 = 40 ttype# = Name tform# = 10a ttype# = Npoints tform# = j ttype# = Rate tunit# = counts/s tform# = e \end{verbatim} The above example defines a null primary array followed by a 40-row binary table extension with 3 columns called 'Name', 'Npoints', and 'Rate', with data formats of '10A' (ASCII character string), '1J' (integer) and '1E' (floating point), respectively. Note that the other required FITS keywords (BITPIX, NAXIS, NAXIS1, PCOUNT, GCOUNT, TFIELDS, and END) do not need to be explicitly defined in the template because their values can be inferred from the other keywords in the template. This example also illustrates that the templates are generally case-insensitive (the keyword names and TFORMn values are converted to upper-case in the FITS file) and that string keyword values generally do not need to be enclosed in quotes. \chapter{ Local FITS Conventions } CFITSIO supports several local FITS conventions which are not defined in the official FITS standard and which are not necessarily recognized or supported by other FITS software packages. Programmers should be cautious about using these features, especially if the FITS files that are produced are expected to be processed by other software systems which do not use the CFITSIO interface. \section{64-Bit Long Integers} CFITSIO supports reading and writing FITS images or table columns containing 64-bit integer data values. Support for 64-bit integers was added to the official FITS Standard in December 2005. FITS 64-bit images have BITPIX = 64, and the 64-bit binary table columns have TFORMn = 'K'. CFITSIO also supports the 'Q' variable-length array table column format which is analogous to the 'P' column format except that the array descriptor is stored as a pair of 64-bit integers. For the convenience of C programmers, the fitsio.h include file defines (with a typedef statement) the 'LONGLONG' datatype to be equivalent to an appropriate 64-bit integer datatype on each platform. Since there is currently no universal standard for the name of the 64-bit integer datatype (it might be defined as 'long long', 'long', or '\_\_int64' depending on the platform) C programmers may prefer to use the 'LONGLONG' datatype when declaring or allocating 64-bit integer quantities when writing code which needs to run on multiple platforms. Note that CFITSIO will implicitly convert the datatype when reading or writing FITS 64-bit integer images and columns with data arrays of a different integer or floating point datatype, but there is an increased risk of loss of numerical precision or numerical overflow in this case. \section{Long String Keyword Values.} The length of a standard FITS string keyword is limited to 68 characters because it must fit entirely within a single FITS header keyword record. In some instances it is necessary to encode strings longer than this limit, so CFITSIO supports a local convention in which the string value is continued over multiple keywords. This continuation convention uses an ampersand character at the end of each substring to indicate that it is continued on the next keyword, and the continuation keywords all have the name CONTINUE without an equal sign in column 9. The string value may be continued in this way over as many additional CONTINUE keywords as is required. The following lines illustrate this continuation convention which is used in the value of the STRKEY keyword: \begin{verbatim} LONGSTRN= 'OGIP 1.0' / The OGIP Long String Convention may be used. STRKEY = 'This is a very long string keyword&' / Optional Comment CONTINUE ' value that is continued over 3 keywords in the & ' CONTINUE 'FITS header.' / This is another optional comment. \end{verbatim} It is recommended that the LONGSTRN keyword, as shown here, always be included in any HDU that uses this longstring convention as a warning to any software that must read the keywords. A routine called fits\_write\_key\_longwarn has been provided in CFITSIO to write this keyword if it does not already exist. This long string convention is supported by the following CFITSIO routines: \begin{verbatim} fits_write_key_longstr - write a long string keyword value fits_insert_key_longstr - insert a long string keyword value fits_modify_key_longstr - modify a long string keyword value fits_update_key_longstr - modify a long string keyword value fits_read_key_longstr - read a long string keyword value fits_delete_key - delete a keyword \end{verbatim} The fits\_read\_key\_longstr routine is unique among all the CFITSIO routines in that it internally allocates memory for the long string value; all the other CFITSIO routines that deal with arrays require that the calling program pre-allocate adequate space to hold the array of data. Consequently, programs which use the fits\_read\_key\_longstr routine must be careful to free the allocated memory for the string when it is no longer needed. The following 2 routines also have limited support for this long string convention, \begin{verbatim} fits_modify_key_str - modify an existing string keyword value fits_update_key_str - update a string keyword value \end{verbatim} in that they will correctly overwrite an existing long string value, but the new string value is limited to a maximum of 68 characters in length. The more commonly used CFITSIO routines to write string valued keywords (fits\_update\_key and fits\_write\_key) do not support this long string convention and only support strings up to 68 characters in length. This has been done deliberately to prevent programs from inadvertently writing keywords using this non-standard convention without the explicit intent of the programmer or user. The fits\_write\_key\_longstr routine must be called instead to write long strings. This routine can also be used to write ordinary string values less than 68 characters in length. \section{Arrays of Fixed-Length Strings in Binary Tables} CFITSIO supports 2 ways to specify that a character column in a binary table contains an array of fixed-length strings. The first way, which is officially supported by the FITS Standard document, uses the TDIMn keyword. For example, if TFORMn = '60A' and TDIMn = '(12,5)' then that column will be interpreted as containing an array of 5 strings, each 12 characters long. CFITSIO also supports a local convention for the format of the TFORMn keyword value of the form 'rAw' where 'r' is an integer specifying the total width in characters of the column, and 'w' is an integer specifying the (fixed) length of an individual unit string within the vector. For example, TFORM1 = '120A10' would indicate that the binary table column is 120 characters wide and consists of 12 10-character length strings. This convention is recognized by the CFITSIO routines that read or write strings in binary tables. The Binary Table definition document specifies that other optional characters may follow the data type code in the TFORM keyword, so this local convention is in compliance with the FITS standard although other FITS readers may not recognize this convention. \section{Keyword Units Strings} One limitation of the current FITS Standard is that it does not define a specific convention for recording the physical units of a keyword value. The TUNITn keyword can be used to specify the physical units of the values in a table column, but there is no analogous convention for keyword values. The comment field of the keyword is often used for this purpose, but the units are usually not specified in a well defined format that FITS readers can easily recognize and extract. To solve this problem, CFITSIO uses a local convention in which the keyword units are enclosed in square brackets as the first token in the keyword comment field; more specifically, the opening square bracket immediately follows the slash '/' comment field delimiter and a single space character. The following examples illustrate keywords that use this convention: \begin{verbatim} EXPOSURE= 1800.0 / [s] elapsed exposure time V_HELIO = 16.23 / [km s**(-1)] heliocentric velocity LAMBDA = 5400. / [angstrom] central wavelength FLUX = 4.9033487787637465E-30 / [J/cm**2/s] average flux \end{verbatim} In general, the units named in the IAU(1988) Style Guide are recommended, with the main exception that the preferred unit for angle is 'deg' for degrees. The fits\_read\_key\_unit and fits\_write\_key\_unit routines in CFITSIO read and write, respectively, the keyword unit strings in an existing keyword. \section{HIERARCH Convention for Extended Keyword Names} CFITSIO supports the HIERARCH keyword convention which allows keyword names that are longer than 8 characters. This convention was developed at the European Southern Observatory (ESO) and allows characters consisting of digits 0-9, upper case letters A-Z, the dash '-' and the underscore '_'. The components of hierarchical keywords are separated by a single ASCII space charater. For instance: \begin{verbatim} HIERARCH ESO INS FOCU POS = -0.00002500 / Focus position \end{verbatim} Basically, this convention uses the FITS keyword 'HIERARCH' to indicate that this convention is being used, then the actual keyword name ({\tt'ESO INS FOCU POS'} in this example) begins in column 10. The equals sign marks the end of the keyword name and is followed by the usual value and comment fields just as in standard FITS keywords. Further details of this convention are described at http://fits.gsfc.nasa.gov/registry/hierarch\_keyword.html and in Section 4.4 of the ESO Data Interface Control Document that is linked to from http://archive.eso.org/cms/tools-documentation/eso-data-interface-control.html. This convention allows a broader range of keyword names than is allowed by the FITS Standard. Here are more examples of such keywords: \begin{verbatim} HIERARCH LONGKEYWORD = 47.5 / Keyword has > 8 characters HIERARCH LONG-KEY_WORD2 = 52.3 / Long keyword with hyphen, underscore and digit HIERARCH EARTH IS A STAR = F / Keyword contains embedded spaces \end{verbatim} CFITSIO will transparently read and write these keywords, so application programs do not in general need to know anything about the specific implementation details of the HIERARCH convention. In particular, application programs do not need to specify the `HIERARCH' part of the keyword name when reading or writing keywords (although it may be included if desired). When writing a keyword, CFITSIO first checks to see if the keyword name is legal as a standard FITS keyword (no more than 8 characters long and containing only letters, digits, or a minus sign or underscore). If so it writes it as a standard FITS keyword, otherwise it uses the hierarch convention to write the keyword. The maximum keyword name length is 67 characters, which leaves only 1 space for the value field. A more practical limit is about 40 characters, which leaves enough room for most keyword values. CFITSIO returns an error if there is not enough room for both the keyword name and the keyword value on the 80-character card, except for string-valued keywords which are simply truncated so that the closing quote character falls in column 80. A space is also required on either side of the equal sign. \section{Tile-Compressed Image Format} CFITSIO supports a convention for compressing n-dimensional images and storing the resulting byte stream in a variable-length column in a FITS binary table. The general principle used in this convention is to first divide the n-dimensional image into a rectangular grid of subimages or `tiles'. Each tile is then compressed as a continuous block of data, and the resulting compressed byte stream is stored in a row of a variable length column in a FITS binary table. By dividing the image into tiles it is generally possible to extract and uncompress subsections of the image without having to uncompress the whole image. The default tiling pattern treats each row of a 2-dimensional image (or higher dimensional cube) as a tile, such that each tile contains NAXIS1 pixels (except the default with the HCOMPRESS algorithm is to compress the whole 2D image as a single tile). Any other rectangular tiling pattern may also be defined. In the case of relatively small images it may be sufficient to compress the entire image as a single tile, resulting in an output binary table with 1 row. In the case of 3-dimensional data cubes, it may be advantageous to treat each plane of the cube as a separate tile if application software typically needs to access the cube on a plane by plane basis. See section 5.6 ``Image Compression'' for more information on using this tile-compressed image format. \chapter{ Optimizing Programs } CFITSIO has been carefully designed to obtain the highest possible speed when reading and writing FITS files. In order to achieve the best performance, however, application programmers must be careful to call the CFITSIO routines appropriately and in an efficient sequence; inappropriate usage of CFITSIO routines can greatly slow down the execution speed of a program. The maximum possible I/O speed of CFITSIO depends of course on the type of computer system that it is running on. To get a general idea of what data I/O speeds are possible on a particular machine, build the speed.c program that is distributed with CFITSIO (type 'make speed' in the CFITSIO directory). This diagnostic program measures the speed of writing and reading back a test FITS image, a binary table, and an ASCII table. The following 2 sections provide some background on how CFITSIO internally manages the data I/O and describes some strategies that may be used to optimize the processing speed of software that uses CFITSIO. \section{How CFITSIO Manages Data I/O} Many CFITSIO operations involve transferring only a small number of bytes to or from the FITS file (e.g, reading a keyword, or writing a row in a table); it would be very inefficient to physically read or write such small blocks of data directly in the FITS file on disk, therefore CFITSIO maintains a set of internal Input--Output (IO) buffers in RAM memory that each contain one FITS block (2880 bytes) of data. Whenever CFITSIO needs to access data in the FITS file, it first transfers the FITS block containing those bytes into one of the IO buffers in memory. The next time CFITSIO needs to access bytes in the same block it can then go to the fast IO buffer rather than using a much slower system disk access routine. The number of available IO buffers is determined by the NIOBUF parameter (in fitsio2.h) and is currently set to 40 by default. Whenever CFITSIO reads or writes data it first checks to see if that block of the FITS file is already loaded into one of the IO buffers. If not, and if there is an empty IO buffer available, then it will load that block into the IO buffer (when reading a FITS file) or will initialize a new block (when writing to a FITS file). If all the IO buffers are already full, it must decide which one to reuse (generally the one that has been accessed least recently), and flush the contents back to disk if it has been modified before loading the new block. The one major exception to the above process occurs whenever a large contiguous set of bytes are accessed, as might occur when reading or writing a FITS image. In this case CFITSIO bypasses the internal IO buffers and simply reads or writes the desired bytes directly in the disk file with a single call to a low-level file read or write routine. The minimum threshold for the number of bytes to read or write this way is set by the MINDIRECT parameter and is currently set to 3 FITS blocks = 8640 bytes. This is the most efficient way to read or write large chunks of data. Note that this fast direct IO process is not applicable when accessing columns of data in a FITS table because the bytes are generally not contiguous since they are interleaved by the other columns of data in the table. This explains why the speed for accessing FITS tables is generally slower than accessing FITS images. Given this background information, the general strategy for efficiently accessing FITS files should be apparent: when dealing with FITS images, read or write large chunks of data at a time so that the direct IO mechanism will be invoked; when accessing FITS headers or FITS tables, on the other hand, once a particular FITS block has been loading into one of the IO buffers, try to access all the needed information in that block before it gets flushed out of the IO buffer. It is important to avoid the situation where the same FITS block is being read then flushed from a IO buffer multiple times. The following section gives more specific suggestions for optimizing the use of CFITSIO. \section{Optimization Strategies} 1. Because the data in FITS files is always stored in "big-endian" byte order, where the first byte of numeric values contains the most significant bits and the last byte contains the least significant bits, CFITSIO must swap the order of the bytes when reading or writing FITS files when running on little-endian machines (e.g., Linux and Microsoft Windows operating systems running on PCs with x86 CPUs). On relatively new CPUs that support "SSSE3" machine instructions (e.g., starting with Intel Core 2 CPUs in 2007, and in AMD CPUs beginning in 2011) significantly faster 4-byte and 8-byte swapping algorithms are available. These faster byte swapping functions are not used by default in CFITSIO (because of potential code portablility issues), but users can enable them on supported platforms by adding the appropriate compiler flags (-mssse3 with gcc or icc on linux) when compiling the swapproc.c source file, which will allow the compiler to generate code using the SSSE3 instruction set. A convenient way to do this is to configure the CFITSIO library with the following command: \begin{verbatim} > ./configure --enable-ssse3 \end{verbatim} Note, however, that a binary executable file that is created using these faster functions will only run on machines that support the SSSE3 machine instructions. For faster 2-byte swaps on virtually all x86-64 CPUs (even those that do not support SSSE3), a variant using only SSE2 instructions exists. SSE2 is enabled by default on x86\_64 CPUs with 64-bit operating systems (and is also automatically enabled by the --enable-ssse3 flag). When running on x86\_64 CPUs with 32-bit operating systems, these faster 2-byte swapping algorithms are not used by default in CFITSIO, but can be enabled explicitly with: \begin{verbatim} ./configure --enable-sse2 \end{verbatim} Preliminary testing indicates that these SSSE3 and SSE2 based byte-swapping algorithms can boost the CFITSIO performance when reading or writing FITS images by 20\% - 30\% or more. It is important to note, however, that compiler optimization must be turned on (e.g., by using the -O1 or -O2 flags in gcc) when building programs that use these fast byte-swapping algorithms in order to reap the full benefit of the SSSE3 and SSE2 instructions; without optimization, the code may actually run slower than when using more traditional byte-swapping techniques. 2. When dealing with a FITS primary array or IMAGE extension, it is more efficient to read or write large chunks of the image at a time (at least 3 FITS blocks = 8640 bytes) so that the direct IO mechanism will be used as described in the previous section. Smaller chunks of data are read or written via the IO buffers, which is somewhat less efficient because of the extra copy operation and additional bookkeeping steps that are required. In principle it is more efficient to read or write as big an array of image pixels at one time as possible, however, if the array becomes so large that the operating system cannot store it all in RAM, then the performance may be degraded because of the increased swapping of virtual memory to disk. 3. When dealing with FITS tables, the most important efficiency factor in the software design is to read or write the data in the FITS file in a single pass through the file. An example of poor program design would be to read a large, 3-column table by sequentially reading the entire first column, then going back to read the 2nd column, and finally the 3rd column; this obviously requires 3 passes through the file which could triple the execution time of an IO limited program. For small tables this is not important, but when reading multi-megabyte sized tables these inefficiencies can become significant. The more efficient procedure in this case is to read or write only as many rows of the table as will fit into the available internal IO buffers, then access all the necessary columns of data within that range of rows. Then after the program is completely finished with the data in those rows it can move on to the next range of rows that will fit in the buffers, continuing in this way until the entire file has been processed. By using this procedure of accessing all the columns of a table in parallel rather than sequentially, each block of the FITS file will only be read or written once. The optimal number of rows to read or write at one time in a given table depends on the width of the table row and on the number of IO buffers that have been allocated in CFITSIO. The CFITSIO Iterator routine will automatically use the optimal-sized buffer, but there is also a CFITSIO routine that will return the optimal number of rows for a given table: fits\_get\_rowsize. It is not critical to use exactly the value of nrows returned by this routine, as long as one does not exceed it. Using a very small value however can also lead to poor performance because of the overhead from the larger number of subroutine calls. The optimal number of rows returned by fits\_get\_rowsize is valid only as long as the application program is only reading or writing data in the specified table. Any other calls to access data in the table header would cause additional blocks of data to be loaded into the IO buffers displacing data from the original table, and should be avoided during the critical period while the table is being read or written. 4. Use the CFITSIO Iterator routine. This routine provides a more `object oriented' way of reading and writing FITS files which automatically uses the most appropriate data buffer size to achieve the maximum I/O throughput. 5. Use binary table extensions rather than ASCII table extensions for better efficiency when dealing with tabular data. The I/O to ASCII tables is slower because of the overhead in formatting or parsing the ASCII data fields and because ASCII tables are about twice as large as binary tables that have the same information content. 6. Design software so that it reads the FITS header keywords in the same order in which they occur in the file. When reading keywords, CFITSIO searches forward starting from the position of the last keyword that was read. If it reaches the end of the header without finding the keyword, it then goes back to the start of the header and continues the search down to the position where it started. In practice, as long as the entire FITS header can fit at one time in the available internal IO buffers, then the header keyword access will be relatively fast and it makes little difference which order they are accessed. 7. Avoid the use of scaling (by using the BSCALE and BZERO or TSCAL and TZERO keywords) in FITS files since the scaling operations add to the processing time needed to read or write the data. In some cases it may be more efficient to temporarily turn off the scaling (using fits\_set\_bscale or fits\_set\_tscale) and then read or write the raw unscaled values in the FITS file. 8. Avoid using the `implicit data type conversion' capability in CFITSIO. For instance, when reading a FITS image with BITPIX = -32 (32-bit floating point pixels), read the data into a single precision floating point data array in the program. Forcing CFITSIO to convert the data to a different data type can slow the program. 9. Where feasible, design FITS binary tables using vector column elements so that the data are written as a contiguous set of bytes, rather than as single elements in multiple rows. For example, it is faster to access the data in a table that contains a single row and 2 columns with TFORM keywords equal to '10000E' and '10000J', than it is to access the same amount of data in a table with 10000 rows which has columns with the TFORM keywords equal to '1E' and '1J'. In the former case the 10000 floating point values in the first column are all written in a contiguous block of the file which can be read or written quickly, whereas in the second case each floating point value in the first column is interleaved with the integer value in the second column of the same row so CFITSIO has to explicitly move to the position of each element to be read or written. 10. Avoid the use of variable length vector columns in binary tables, since any reading or writing of these data requires that CFITSIO first look up or compute the starting address of each row of data in the heap. In practice, this is probably not a significant efficiency issue. 11. When copying data from one FITS table to another, it is faster to transfer the raw bytes instead of reading then writing each column of the table. The CFITSIO routines fits\_read\_tblbytes and fits\_write\_tblbytes will perform low-level reads or writes of any contiguous range of bytes in a table extension. These routines can be used to read or write a whole row (or multiple rows for even greater efficiency) of a table with a single function call. These routines are fast because they bypass all the usual data scaling, error checking and machine dependent data conversion that is normally done by CFITSIO, and they allow the program to write the data to the output file in exactly the same byte order. For these same reasons, these routines can corrupt the FITS data file if used incorrectly because no validation or machine dependent conversion is performed by these routines. These routines are only recommended for optimizing critical pieces of code and should only be used by programmers who thoroughly understand the internal format of the FITS tables they are reading or writing. 12. Another strategy for improving the speed of writing a FITS table, similar to the previous one, is to directly construct the entire byte stream for a whole table row (or multiple rows) within the application program and then write it to the FITS file with fits\_write\_tblbytes. This avoids all the overhead normally present in the column-oriented CFITSIO write routines. This technique should only be used for critical applications because it makes the code more difficult to understand and maintain, and it makes the code more system dependent (e.g., do the bytes need to be swapped before writing to the FITS file?). 13. Finally, external factors such as the speed of the data storage device, the size of the data cache, the amount of disk fragmentation, and the amount of RAM available on the system can all have a significant impact on overall I/O efficiency. For critical applications, the entire hardware and software system should be reviewed to identify any potential I/O bottlenecks. \appendix \chapter{Index of Routines } \begin{tabular}{lr} fits\_add\_group\_member & \pageref{ffgtam} \\ fits\_ascii\_tform & \pageref{ffasfm} \\ fits\_binary\_tform & \pageref{ffbnfm} \\ fits\_calculator & \pageref{ffcalc} \\ fits\_calculator\_rng & \pageref{ffcalcrng} \\ fits\_calc\_binning & \pageref{calcbinning} \\ fits\_calc\_rows & \pageref{ffcrow} \\ fits\_change\_group & \pageref{ffgtch} \\ fits\_cleanup\_https & \pageref{ffchtps} \\ fits\_clear\_errmark & \pageref{ffpmrk} \\ fits\_clear\_errmsg & \pageref{ffcmsg} \\ fits\_close\_file & \pageref{ffclos} \\ fits\_compact\_group & \pageref{ffgtcm} \\ fits\_compare\_str & \pageref{ffcmps} \\ fits\_compress\_heap & \pageref{ffcmph} \\ fits\_convert\_hdr2str & \pageref{ffhdr2str}, \pageref{hdr2str} \\ fits\_copy\_cell2image & \pageref{copycell} \\ fits\_copy\_col & \pageref{ffcpcl} \\ fits\_copy\_data & \pageref{ffcpdt} \\ fits\_copy\_file & \pageref{ffcpfl} \\ fits\_copy\_group & \pageref{ffgtcp} \\ fits\_copy\_hdu & \pageref{ffcopy} \\ fits\_copy\_header & \pageref{ffcphd} \\ fits\_copy\_image2cell & \pageref{copycell} \\ fits\_copy\_image\_section & \pageref{ffcpimg} \\ fits\_copy\_key & \pageref{ffcpky} \\ fits\_copy\_member & \pageref{ffgmcp} \\ fits\_copy\_pixlist2image & \pageref{copypixlist2image} \\ fits\_copy\_rows & \pageref{ffcprw} \\ fits\_create\_diskfile & \pageref{ffinit} \\ fits\_create\_file & \pageref{ffinit} \\ fits\_create\_group & \pageref{ffgtcr} \\ \end{tabular} \begin{tabular}{lr} fits\_create\_hdu & \pageref{ffcrhd} \\ fits\_create\_img & \pageref{ffcrim} \\ fits\_create\_memfile & \pageref{ffimem} \\ fits\_create\_tbl & \pageref{ffcrtb} \\ fits\_create\_template & \pageref{fftplt} \\ fits\_date2str & \pageref{ffdt2s} \\ fits\_decode\_chksum & \pageref{ffdsum} \\ fits\_decode\_tdim & \pageref{ffdtdm} \\ fits\_delete\_col & \pageref{ffdcol} \\ fits\_delete\_file & \pageref{ffdelt} \\ fits\_delete\_hdu & \pageref{ffdhdu} \\ fits\_delete\_key & \pageref{ffdkey} \\ fits\_delete\_record & \pageref{ffdrec} \\ fits\_delete\_rowlist & \pageref{ffdrws} \\ fits\_delete\_rowrange & \pageref{ffdrrg} \\ fits\_delete\_rows & \pageref{ffdrow} \\ fits\_delete\_str & \pageref{ffdkey} \\ fits\_encode\_chksum & \pageref{ffesum} \\ fits\_file\_exists & \pageref{ffexist} \\ fits\_file\_mode & \pageref{ffflmd} \\ fits\_file\_name & \pageref{ffflnm} \\ fits\_find\_first\_row & \pageref{ffffrw} \\ fits\_find\_nextkey & \pageref{ffgnxk} \\ fits\_find\_rows & \pageref{fffrow} \\ fits\_flush\_buffer & \pageref{ffflus} \\ fits\_flush\_file & \pageref{ffflus} \\ fits\_free\_memory & \pageref{ffgkls}, \pageref{ffhdr2str} \\ fits\_get\_acolparms & \pageref{ffgacl} \\ fits\_get\_bcolparms & \pageref{ffgbcl} \\ fits\_get\_chksum & \pageref{ffgcks} \\ fits\_get\_col\_display\_width & \pageref{ffgcdw} \\ fits\_get\_colname & \pageref{ffgcnn} \\ \end{tabular} \begin{tabular}{lr} fits\_get\_colnum & \pageref{ffgcno} \\ fits\_get\_coltype & \pageref{ffgtcl} \\ fits\_get\_compression\_type & \pageref{ffgetcomp} \\ fits\_get\_eqcoltype & \pageref{ffgtcl} \\ fits\_get\_errstatus & \pageref{ffgerr} \\ fits\_get\_hdrpos & \pageref{ffghps} \\ fits\_get\_hdrspace & \pageref{ffghsp} \\ fits\_get\_hdu\_num & \pageref{ffghdn} \\ fits\_get\_hdu\_type & \pageref{ffghdt} \\ fits\_get\_hduaddr & \pageref{ffghad} \\ fits\_get\_hduaddrll & \pageref{ffghad} \\ fits\_get\_img\_dim & \pageref{ffgidm} \\ fits\_get\_img\_equivtype & \pageref{ffgidt} \\ fits\_get\_img\_param & \pageref{ffgipr} \\ fits\_get\_img\_size & \pageref{ffgisz} \\ fits\_get\_img\_type & \pageref{ffgidt} \\ fits\_get\_inttype & \pageref{ffinttyp} \\ fits\_get\_key\_strlen & \pageref{ffgksl} \\ fits\_get\_keyclass & \pageref{ffgkcl} \\ fits\_get\_keyname & \pageref{ffgknm} \\ fits\_get\_keytype & \pageref{ffdtyp} \\ fits\_get\_noise\_bits & \pageref{ffgetcomp} \\ fits\_get\_num\_cols & \pageref{ffgnrw} \\ fits\_get\_num\_groups & \pageref{ffgmng} \\ fits\_get\_num\_hdus & \pageref{ffthdu} \\ fits\_get\_num\_members & \pageref{ffgtnm} \\ fits\_get\_num\_rows & \pageref{ffgnrw} \\ fits\_get\_rowsize & \pageref{ffgrsz} \\ fits\_get\_system\_time & \pageref{ffdt2s} \\ fits\_get\_tile\_dim & \pageref{ffgetcomp} \\ fits\_get\_tbcol & \pageref{ffgabc} \\ fits\_get\_version & \pageref{ffvers} \\ \end{tabular} \newpage \begin{tabular}{lr} fits\_hdr2str & \pageref{ffhdr2str}, \pageref{hdr2str} \\ fits\_init\_https & \pageref{ffihtps} \\ fits\_insert\_atbl & \pageref{ffitab} \\ fits\_insert\_btbl & \pageref{ffibin} \\ fits\_insert\_col & \pageref{fficol} \\ fits\_insert\_cols & \pageref{fficls} \\ fits\_insert\_group & \pageref{ffgtis} \\ fits\_insert\_img & \pageref{ffiimg} \\ fits\_insert\_key\_null & \pageref{ffikyu} \\ fits\_insert\_key\_TYP & \pageref{ffikyx} \\ fits\_insert\_record & \pageref{ffirec} \\ fits\_insert\_rows & \pageref{ffirow} \\ fits\_is\_reentrant & \pageref{reentrant} \\ fits\_iterate\_data & \pageref{ffiter} \\ fits\_make\_hist & \pageref{makehist} \\ fits\_make\_key & \pageref{ffmkky} \\ fits\_make\_keyn & \pageref{ffkeyn} \\ fits\_make\_nkey & \pageref{ffnkey} \\ fits\_merge\_groups & \pageref{ffgtmg} \\ fits\_modify\_card & \pageref{ffmcrd} \\ fits\_modify\_comment & \pageref{ffmcom} \\ fits\_modify\_key\_null & \pageref{ffmkyu} \\ fits\_modify\_key\_TYP & \pageref{ffmkyx} \\ fits\_modify\_name & \pageref{ffmnam} \\ fits\_modify\_record & \pageref{ffmrec} \\ fits\_modify\_vector\_len & \pageref{ffmvec} \\ fits\_movabs\_hdu & \pageref{ffmahd} \\ fits\_movnam\_hdu & \pageref{ffmnhd} \\ fits\_movrel\_hdu & \pageref{ffmrhd} \\ fits\_null\_check & \pageref{ffnchk} \\ fits\_open\_data & \pageref{ffopen} \\ fits\_open\_diskfile & \pageref{ffopen} \\ fits\_open\_extlist & \pageref{ffopen} \\ fits\_open\_file & \pageref{ffopen} \\ fits\_open\_image & \pageref{ffopen} \\ fits\_open\_table & \pageref{ffopen} \\ fits\_open\_group & \pageref{ffgtop} \\ fits\_open\_member & \pageref{ffgmop} \\ fits\_open\_memfile & \pageref{ffomem} \\ fits\_parse\_extnum & \pageref{ffextn} \\ fits\_parse\_input\_filename & \pageref{ffiurl} \\ fits\_parse\_input\_url & \pageref{ffiurl} \\ fits\_parse\_range & \pageref{ffrwrg} \\ fits\_parse\_rootname & \pageref{ffrtnm} \\ fits\_parse\_template & \pageref{ffgthd} \\ fits\_parse\_value & \pageref{ffpsvc} \\ fits\_pix\_to\_world & \pageref{ffwldp} \\ fits\_read\_2d\_TYP & \pageref{ffg2dx} \\ \end{tabular} \begin{tabular}{lr} fits\_read\_3d\_TYP & \pageref{ffg3dx} \\ fits\_read\_atblhdr & \pageref{ffghtb} \\ fits\_read\_btblhdr & \pageref{ffghbn} \\ fits\_read\_card & \pageref{ffgcrd} \\ fits\_read\_col & \pageref{ffgcv} \\ fits\_read\_col\_bit\_ & \pageref{ffgcx} \\ fits\_read\_col\_TYP & \pageref{ffgcvx} \\ fits\_read\_colnull & \pageref{ffgcf} \\ fits\_read\_colnull\_TYP & \pageref{ffgcfx} \\ fits\_read\_descript & \pageref{ffgdes} \\ fits\_read\_descripts & \pageref{ffgdes} \\ fits\_read\_errmsg & \pageref{ffgmsg} \\ fits\_read\_ext & \pageref{ffgextn} \\ fits\_read\_grppar\_TYP & \pageref{ffggpx} \\ fits\_read\_img & \pageref{ffgpv} \\ fits\_read\_img\_coord & \pageref{ffgics} \\ fits\_read\_img\_TYP & \pageref{ffgpvx} \\ fits\_read\_imghdr & \pageref{ffghpr} \\ fits\_read\_imgnull & \pageref{ffgpf} \\ fits\_read\_imgnull\_TYP & \pageref{ffgpfx} \\ fits\_read\_key & \pageref{ffgky} \\ fits\_read\_key\_longstr & \pageref{ffgkls} \\ fits\_read\_key\_triple & \pageref{ffgkyt} \\ fits\_read\_key\_unit & \pageref{ffgunt} \\ fits\_read\_key\_TYP & \pageref{ffgkyx} \\ fits\_read\_keyn & \pageref{ffgkyn} \\ fits\_read\_keys\_TYP & \pageref{ffgknx} \\ fits\_read\_keyword & \pageref{ffgkey} \\ fits\_read\_pix & \pageref{ffgpxv} \\ fits\_read\_pixnull & \pageref{ffgpxf} \\ fits\_read\_record & \pageref{ffgrec} \\ fits\_read\_str & \pageref{ffgcrd} \\ fits\_read\_string\_key & \pageref{ffgsky} \\ fits\_read\_subset & \pageref{ffgsv} \\ fits\_read\_subset\_TYP & \pageref{ffgsvx} \pageref{ffgsvx2}\\ fits\_read\_subsetnull\_TYP & \pageref{ffgsfx} \pageref{ffgsfx2} \\ fits\_read\_tbl\_coord & \pageref{ffgtcs} \\ fits\_read\_tblbytes & \pageref{ffgtbb} \\ fits\_read\_tdim & \pageref{ffgtdm} \\ fits\_read\_wcstab & \pageref{wcstab} \\ fits\_rebin\_wcs & \pageref{rebinwcs} \\ fits\_remove\_group & \pageref{ffgtrm} \\ fits\_remove\_member & \pageref{ffgmrm} \\ fits\_reopen\_file & \pageref{ffreopen} \\ fits\_report\_error & \pageref{ffrprt} \\ fits\_resize\_img & \pageref{ffrsim} \\ fits\_rms\_float & \pageref{imageRMS} \\ fits\_rms\_short & \pageref{imageRMS} \\ \end{tabular} \begin{tabular}{lr} fits\_select\_rows & \pageref{ffsrow} \\ fits\_set\_atblnull & \pageref{ffsnul} \\ fits\_set\_bscale & \pageref{ffpscl} \\ fits\_set\_btblnull & \pageref{fftnul} \\ fits\_set\_compression\_type & \pageref{ffsetcomp} \\ fits\_set\_hdrsize & \pageref{ffhdef} \\ fits\_set\_hdustruc & \pageref{ffrdef} \\ fits\_set\_imgnull & \pageref{ffpnul} \\ fits\_set\_noise\_bits & \pageref{ffsetcomp} \\ fits\_set\_tile\_dim & \pageref{ffsetcomp} \\ fits\_set\_tscale & \pageref{fftscl} \\ fits\_split\_names & \pageref{splitnames} \\ fits\_str2date & \pageref{ffdt2s} \\ fits\_str2time & \pageref{ffdt2s} \\ fits\_test\_expr & \pageref{fftexp} \\ fits\_test\_heap & \pageref{fftheap} \\ fits\_test\_keyword & \pageref{fftkey} \\ fits\_test\_record & \pageref{fftrec} \\ fits\_time2str & \pageref{ffdt2s} \\ fits\_transfer\_member & \pageref{ffgmtf} \\ fits\_translate\_keyword & \pageref{translatekey} \\ fits\_update\_card & \pageref{ffucrd} \\ fits\_update\_chksum & \pageref{ffupck} \\ fits\_update\_key & \pageref{ffuky} \\ fits\_update\_key\_longstr & \pageref{ffukyx} \\ fits\_update\_key\_null & \pageref{ffukyu} \\ fits\_update\_key\_TYP & \pageref{ffukyx} \\ fits\_uppercase & \pageref{ffupch} \\ fits\_url\_type & \pageref{ffurlt} \\ fits\_verbose\_https & \pageref{ffvhtps} \\ fits\_verify\_chksum & \pageref{ffvcks} \\ fits\_verify\_group & \pageref{ffgtvf} \\ fits\_world\_to\_pix & \pageref{ffxypx} \\ fits\_write\_2d\_TYP & \pageref{ffp2dx} \\ fits\_write\_3d\_TYP & \pageref{ffp3dx} \\ fits\_write\_atblhdr & \pageref{ffphtb} \\ fits\_write\_btblhdr & \pageref{ffphbn} \\ fits\_write\_chksum & \pageref{ffpcks} \\ fits\_write\_col & \pageref{ffpcl} \\ fits\_write\_col\_bit & \pageref{ffpclx} \\ fits\_write\_col\_TYP & \pageref{ffpcls} \\ fits\_write\_col\_null & \pageref{ffpclu} \\ fits\_write\_colnull & \pageref{ffpcn} \\ fits\_write\_colnull\_TYP & \pageref{ffpcnx} \\ fits\_write\_comment & \pageref{ffpcom} \\ fits\_write\_date & \pageref{ffpdat} \\ fits\_write\_descript & \pageref{ffpdes} \\ fits\_write\_errmark & \pageref{ffpmrk} \\ \end{tabular} \newpage \begin{tabular}{lr} fits\_write\_errmsg & \pageref{ffpmsg} \\ fits\_write\_ext & \pageref{ffgextn} \\ fits\_write\_exthdr & \pageref{ffphps} \\ fits\_write\_grphdr & \pageref{ffphpr} \\ fits\_write\_grppar\_TYP & \pageref{ffpgpx} \\ fits\_write\_hdu & \pageref{ffwrhdu} \\ fits\_write\_history & \pageref{ffphis} \\ fits\_write\_img & \pageref{ffppr} \\ fits\_write\_img\_null & \pageref{ffppru} \\ fits\_write\_img\_TYP & \pageref{ffpprx} \\ fits\_write\_imghdr & \pageref{ffphps} \\ fits\_write\_imgnull & \pageref{ffppn} \\ fits\_write\_imgnull\_TYP & \pageref{ffppnx} \\ fits\_write\_key & \pageref{ffpky} \\ fits\_write\_key\_longstr & \pageref{ffpkls} \\ fits\_write\_key\_longwarn & \pageref{ffplsw} \\ fits\_write\_key\_null & \pageref{ffpkyu} \\ fits\_write\_key\_template & \pageref{ffpktp} \\ fits\_write\_key\_triple & \pageref{ffpkyt} \\ fits\_write\_key\_unit & \pageref{ffpunt} \\ fits\_write\_key\_TYP & \pageref{ffpkyx} \\ fits\_write\_keys\_TYP & \pageref{ffpknx} \\ fits\_write\_keys\_histo & \pageref{writekeyshisto} \\ fits\_write\_null\_img & \pageref{ffpprn} \\ fits\_write\_nullrows & \pageref{ffpclu} \\ fits\_write\_pix & \pageref{ffppx} \\ fits\_write\_pixnull & \pageref{ffppxn} \\ fits\_write\_record & \pageref{ffprec} \\ fits\_write\_subset & \pageref{ffpss} \\ fits\_write\_subset\_TYP & \pageref{ffpssx} \\ fits\_write\_tblbytes & \pageref{ffptbb} \\ fits\_write\_tdim & \pageref{ffptdm} \\ fits\_write\_theap & \pageref{ffpthp} \\ \end{tabular} \newpage \begin{tabular}{lr} ffasfm & \pageref{ffasfm} \\ ffbnfm & \pageref{ffbnfm} \\ ffcalc & \pageref{ffcalc} \\ ffcalc\_rng & \pageref{ffcalcrng} \\ ffchtps & \pageref{ffchtps} \\ ffclos & \pageref{ffclos} \\ ffcmph & \pageref{ffcmph} \\ ffcmps & \pageref{ffcmps} \\ ffcmrk & \pageref{ffpmrk} \\ ffcmsg & \pageref{ffcmsg} \\ ffcopy & \pageref{ffcopy} \\ ffcpcl & \pageref{ffcpcl} \\ ffcpdt & \pageref{ffcpdt} \\ ffcpfl & \pageref{ffcpfl} \\ ffcphd & \pageref{ffcphd} \\ ffcpimg & \pageref{ffcpimg} \\ ffcpky & \pageref{ffcpky} \\ ffcprw & \pageref{ffcprw} \\ ffcrhd & \pageref{ffcrhd} \\ ffcrim & \pageref{ffcrim} \\ ffcrow & \pageref{ffcrow} \\ ffcrtb & \pageref{ffcrtb} \\ ffdcol & \pageref{ffdcol} \\ ffdelt & \pageref{ffdelt} \\ ffdhdu & \pageref{ffdhdu} \\ ffdkey & \pageref{ffdkey} \\ ffdkinit & \pageref{ffinit} \\ ffdkopen & \pageref{ffopen} \\ ffdopn & \pageref{ffopen} \\ ffdrec & \pageref{ffdrec} \\ ffdrow & \pageref{ffdrow} \\ ffdrrg & \pageref{ffdrrg} \\ ffdrws & \pageref{ffdrws} \\ ffdstr & \pageref{ffdkey} \\ ffdsum & \pageref{ffdsum} \\ ffdt2s & \pageref{ffdt2s} \\ ffdtdm & \pageref{ffdtdm} \\ ffdtyp & \pageref{ffdtyp} \\ ffeopn & \pageref{ffopen} \\ ffeqty & \pageref{ffgtcl} \\ ffesum & \pageref{ffesum} \\ ffexest & \pageref{ffexist} \\ ffextn & \pageref{ffextn} \\ ffffrw & \pageref{ffffrw} \\ ffflmd & \pageref{ffflmd} \\ ffflnm & \pageref{ffflnm} \\ ffflsh & \pageref{ffflus} \\ ffflus & \pageref{ffflus} \\ \end{tabular} \begin{tabular}{lr} fffree & \pageref{ffgkls}, \pageref{ffhdr2str} \\ fffrow & \pageref{fffrow} \\ ffg2d\_ & \pageref{ffg2dx} \\ ffg3d\_ & \pageref{ffg3dx} \\ ffgabc & \pageref{ffgabc} \\ ffgacl & \pageref{ffgacl} \\ ffgbcl & \pageref{ffgbcl} \\ ffgcdw & \pageref{ffgcdw} \\ ffgcf & \pageref{ffgcf} \\ ffgcf\_ & \pageref{ffgcfx} \\ ffgcks & \pageref{ffgcks} \\ ffgcnn & \pageref{ffgcnn} \\ ffgcno & \pageref{ffgcno} \\ ffgcrd & \pageref{ffgcrd} \\ ffgcv & \pageref{ffgcv} \\ ffgcv\_ & \pageref{ffgcvx} \\ ffgcx & \pageref{ffgcx} \\ ffgdes & \pageref{ffgdes} \\ ffgdess & \pageref{ffgdes} \\ ffgerr & \pageref{ffgerr} \\ ffgextn & \pageref{ffgextn} \\ ffggp\_ & \pageref{ffggpx} \\ ffghad & \pageref{ffghad} \\ ffghbn & \pageref{ffghbn} \\ ffghdn & \pageref{ffghdn} \\ ffghdt & \pageref{ffghdt} \\ ffghpr & \pageref{ffghpr} \\ ffghps & \pageref{ffghps} \\ ffghsp & \pageref{ffghsp} \\ ffghtb & \pageref{ffghtb} \\ ffgics & \pageref{ffgics} \\ ffgidm & \pageref{ffgidm} \\ ffgidt & \pageref{ffgidt} \\ ffgiet & \pageref{ffgidt} \\ ffgipr & \pageref{ffgipr} \\ ffgisz & \pageref{ffgisz} \\ ffgkcl & \pageref{ffgkcl} \\ ffgkey & \pageref{ffgkey} \\ ffgkls & \pageref{ffgkls} \\ ffgksl & \pageref{ffgksl} \\ ffgkn\_ & \pageref{ffgknx} \\ ffgknm & \pageref{ffgknm} \\ ffgky & \pageref{ffgky} \\ ffgkyn & \pageref{ffgkyn} \\ ffgkyt & \pageref{ffgkyt} \\ ffgky\_ & \pageref{ffgkyx} \\ ffgmcp & \pageref{ffgmcp} \\ ffgmng & \pageref{ffgmng} \\ \end{tabular} \begin{tabular}{lr} ffgmop & \pageref{ffgmop} \\ ffgmrm & \pageref{ffgmrm} \\ ffgmsg & \pageref{ffgmsg} \\ ffgmtf & \pageref{ffgmtf} \\ ffgncl & \pageref{ffgnrw} \\ ffgnrw & \pageref{ffgnrw} \\ ffgnxk & \pageref{ffgnxk} \\ ffgpf & \pageref{ffgpf} \\ ffgpf\_ & \pageref{ffgpfx} \\ ffgpv & \pageref{ffgpv} \\ ffgpv\_ & \pageref{ffgpvx} \\ ffgpxv & \pageref{ffgpxv} \\ ffgpxf & \pageref{ffgpxf} \\ ffgrec & \pageref{ffgrec} \\ ffgrsz & \pageref{ffgrsz} \\ ffgsdt & \pageref{ffdt2s} \\ ffgsf\_ & \pageref{ffgsfx} \pageref{ffgsfx2} \\ ffgsky & \pageref{ffgsky} \\ ffgstm & \pageref{ffdt2s} \\ ffgstr & \pageref{ffgcrd} \\ ffgsv & \pageref{ffgsv} \\ ffgsv\_ & \pageref{ffgsvx} \pageref{ffgsvx2}\\ ffgtam & \pageref{ffgtam} \\ ffgtbb & \pageref{ffgtbb} \\ ffgtch & \pageref{ffgtch} \\ ffgtcl & \pageref{ffgtcl} \\ ffgtcm & \pageref{ffgtcm} \\ ffgtcp & \pageref{ffgtcp} \\ ffgtcr & \pageref{ffgtcr} \\ ffgtcs & \pageref{ffgtcs} \\ ffgtdm & \pageref{ffgtdm} \\ ffgthd & \pageref{ffgthd} \\ ffgtis & \pageref{ffgtis} \\ ffgtmg & \pageref{ffgtmg} \\ ffgtnm & \pageref{ffgtnm} \\ ffgtop & \pageref{ffgtop} \\ ffgtrm & \pageref{ffgtrm} \\ ffgtvf & \pageref{ffgtvf} \\ ffgunt & \pageref{ffgunt} \\ ffhdef & \pageref{ffhdef} \\ ffibin & \pageref{ffibin} \\ fficls & \pageref{fficls} \\ fficol & \pageref{fficol} \\ ffifile & \pageref{ffiurl} \\ ffihtps & \pageref{ffihtps} \\ ffiimg & \pageref{ffiimg} \\ ffikls & \pageref{ffikyx} \\ ffikyu & \pageref{ffikyu} \\ \end{tabular} \begin{tabular}{lr} ffiky\_ & \pageref{ffikyx} \\ ffimem & \pageref{ffimem} \\ ffinit & \pageref{ffinit} \\ ffinttyp & \pageref{ffinttyp} \\ ffiopn & \pageref{ffopen} \\ ffirec & \pageref{ffirec} \\ ffirow & \pageref{ffirow} \\ ffitab & \pageref{ffitab} \\ ffiter & \pageref{ffiter} \\ ffiurl & \pageref{ffiurl} \\ ffkeyn & \pageref{ffkeyn} \\ ffmahd & \pageref{ffmahd} \\ ffmcom & \pageref{ffmcom} \\ ffmcrd & \pageref{ffmcrd} \\ ffmkky & \pageref{ffmkky} \\ ffmkls & \pageref{ffmkyx} \\ ffmkyu & \pageref{ffmkyu} \\ ffmky\_ & \pageref{ffmkyx} \\ ffmnam & \pageref{ffmnam} \\ ffmnhd & \pageref{ffmnhd} \\ ffmrec & \pageref{ffmrec} \\ ffmrhd & \pageref{ffmrhd} \\ ffmvec & \pageref{ffmvec} \\ ffnchk & \pageref{ffnchk} \\ ffnkey & \pageref{ffnkey} \\ ffomem & \pageref{ffomem} \\ ffopen & \pageref{ffopen} \\ ffp2d\_ & \pageref{ffp2dx} \\ ffp3d\_ & \pageref{ffp3dx} \\ ffpcks & \pageref{ffpcks} \\ ffpcl & \pageref{ffpcl} \\ ffpcls & \pageref{ffpcls} \\ ffpcl\_ & \pageref{ffpclx} \\ ffpclu & \pageref{ffpclu} \\ ffpcn & \pageref{ffpcn} \\ ffpcn\_ & \pageref{ffpcnx} \\ ffpcom & \pageref{ffpcom} \\ ffpdat & \pageref{ffpdat} \\ ffpdes & \pageref{ffpdes} \\ ffpextn & \pageref{ffgextn} \\ ffpgp\_ & \pageref{ffpgpx} \\ ffphbn & \pageref{ffphbn} \\ ffphext & \pageref{ffphpr} \\ ffphis & \pageref{ffphis} \\ ffphpr & \pageref{ffphpr} \\ ffphps & \pageref{ffphps} \\ ffphtb & \pageref{ffphtb} \\ ffpkls & \pageref{ffpkls} \\ \end{tabular} \begin{tabular}{lr} ffpkn\_ & \pageref{ffpknx} \\ ffpktp & \pageref{ffpktp} \\ ffpky & \pageref{ffpky} \\ ffpkyt & \pageref{ffpkyt} \\ ffpkyu & \pageref{ffpkyu} \\ ffpky\_ & \pageref{ffpkyx} \\ ffplsw & \pageref{ffplsw} \\ ffpmrk & \pageref{ffpmrk} \\ ffpmsg & \pageref{ffpmsg} \\ ffpnul & \pageref{ffpnul} \\ ffppn & \pageref{ffppn} \\ ffppn\_ & \pageref{ffppnx} \\ ffppr & \pageref{ffppr} \\ ffpprn & \pageref{ffpprn} \\ ffppru & \pageref{ffppru} \\ ffppr\_ & \pageref{ffpprx} \\ ffppx & \pageref{ffppx} \\ ffppxn & \pageref{ffppxn} \\ ffprec & \pageref{ffprec} \\ ffprwu & \pageref{ffpclu} \\ ffpscl & \pageref{ffpscl} \\ ffpss & \pageref{ffpss} \\ ffpss\_ & \pageref{ffpssx} \\ ffpsvc & \pageref{ffpsvc} \\ ffptbb & \pageref{ffptbb} \\ ffptdm & \pageref{ffptdm} \\ ffpthp & \pageref{ffpthp} \\ ffpunt & \pageref{ffpunt} \\ ffrdef & \pageref{ffrdef} \\ ffreopen & \pageref{ffreopen} \\ ffrprt & \pageref{ffrprt} \\ ffrsim & \pageref{ffrsim} \\ ffrtnm & \pageref{ffrtnm} \\ ffrwrg & \pageref{ffrwrg} \\ ffs2dt & \pageref{ffdt2s} \\ ffs2tm & \pageref{ffdt2s} \\ ffsnul & \pageref{ffsnul} \\ ffsrow & \pageref{ffsrow} \\ fftexp & \pageref{fftexp} \\ ffthdu & \pageref{ffthdu} \\ fftheap & \pageref{fftheap} \\ fftkey & \pageref{fftkey} \\ fftm2s & \pageref{ffdt2s} \\ fftnul & \pageref{fftnul} \\ fftopn & \pageref{ffopen} \\ fftplt & \pageref{fftplt} \\ fftrec & \pageref{fftrec} \\ fftscl & \pageref{fftscl} \\ \end{tabular} \newpage \begin{tabular}{lr} ffucrd & \pageref{ffucrd} \\ ffukls & \pageref{ffukyx} \\ ffuky & \pageref{ffuky} \\ ffukyu & \pageref{ffukyu} \\ ffuky\_ & \pageref{ffukyx} \\ ffupch & \pageref{ffupch} \\ ffupck & \pageref{ffupck} \\ ffurlt & \pageref{ffurlt} \\ ffvcks & \pageref{ffvcks} \\ ffvers & \pageref{ffvers} \\ ffvhtps & \pageref{ffvhtps} \\ ffwldp & \pageref{ffwldp} \\ ffwrhdu & \pageref{ffwrhdu} \\ ffxypx & \pageref{ffxypx} \\ \end{tabular} \chapter{Parameter Definitions } \begin{verbatim} anynul - set to TRUE (=1) if any returned values are undefined, else FALSE array - array of numerical data values to read or write ascii - encoded checksum string binspec - the input table binning specifier bitpix - bits per pixel. The following symbolic mnemonics are predefined: BYTE_IMG = 8 (unsigned char) SHORT_IMG = 16 (signed short integer) LONG_IMG = 32 (signed long integer) LONGLONG_IMG = 64 (signed long 64-bit integer) FLOAT_IMG = -32 (float) DOUBLE_IMG = -64 (double). Two additional values, USHORT_IMG and ULONG_IMG are also available for creating unsigned integer images. These are equivalent to creating a signed integer image with BZERO offset keyword values of 32768 or 2147483648, respectively, which is the convention that FITS uses to store unsigned integers. card - header record to be read or written (80 char max, null-terminated) casesen - CASESEN (=1) for case-sensitive string matching, else CASEINSEN (=0) cmopt - grouping table "compact" option parameter. Allowed values are: OPT_CMT_MBR and OPT_CMT_MBR_DEL. colname - name of the column (null-terminated) colnum - column number (first column = 1) colspec - the input file column specification; used to delete, create, or rename table columns comment - the keyword comment field (72 char max, null-terminated) complm - should the checksum be complemented? comptype - compression algorithm to use: GZIP_1, RICE_1, HCOMPRESS_1, or PLIO_1 coordtype- type of coordinate projection (-SIN, -TAN, -ARC, -NCP, -GLS, -MER, or -AIT) cpopt - grouping table copy option parameter. Allowed values are: OPT_GCP_GPT, OPT_GCP_MBR, OPT_GCP_ALL, OPT_MCP_ADD, OPT_MCP_NADD, OPT_MCP_REPL, amd OPT_MCP_MOV. create_col- If TRUE, then insert a new column in the table, otherwise overwrite the existing column. current - if TRUE, then the current HDU will be copied dataok - was the data unit verification successful (=1) or not (= -1). Equals zero if the DATASUM keyword is not present. datasum - 32-bit 1's complement checksum for the data unit dataend - address (in bytes) of the end of the HDU datastart- address (in bytes) of the start of the data unit datatype - specifies the data type of the value. Allowed value are: TSTRING, TLOGICAL, TBYTE, TSBYTE, TSHORT, TUSHORT, TINT, TUINT, TLONG, TULONG, TFLOAT, TDOUBLE, TCOMPLEX, and TDBLCOMPLEX datestr - FITS date/time string: 'YYYY-MM-DDThh:mm:ss.ddd', 'YYYY-MM-dd', or 'dd/mm/yy' day - calendar day (UTC) (1-31) decimals - number of decimal places to be displayed deltasize - increment for allocating more memory dim1 - declared size of the first dimension of the image or cube array dim2 - declared size of the second dimension of the data cube array dispwidth - display width of a column = length of string that will be read dtype - data type of the keyword ('C', 'L', 'I', 'F' or 'X') C = character string L = logical I = integer F = floating point number X = complex, e.g., "(1.23, -4.56)" err_msg - error message on the internal stack (80 chars max) err_text - error message string corresponding to error number (30 chars max) exact - TRUE (=1) if the strings match exactly; FALSE (=0) if wildcards are used exclist - array of pointers to keyword names to be excluded from search exists - flag indicating whether the file or compressed file exists on disk expr - boolean or arithmetic expression extend - TRUE (=1) if FITS file may have extensions, else FALSE (=0) extname - value of the EXTNAME keyword (null-terminated) extspec - the extension or HDU specifier; a number or name, version, and type extver - value of the EXTVER keyword = integer version number filename - full name of the FITS file, including optional HDU and filtering specs filetype - type of file (file://, ftp://, http://, etc.) filter - the input file filtering specifier firstchar- starting byte in the row (first byte of row = 1) firstfailed - member HDU ID (if positive) or grouping table GRPIDn index value (if negative) that failed grouping table verification. firstelem- first element in a vector (ignored for ASCII tables) firstrow - starting row number (first row of table = 1) following- if TRUE, any HDUs following the current HDU will be copied fpixel - coordinate of the first pixel to be read or written in the FITS array. The array must be of length NAXIS and have values such that fpixel[0] is in the range 1 to NAXIS1, fpixel[1] is in the range 1 to NAXIS2, etc. fptr - pointer to a 'fitsfile' structure describing the FITS file. frac - factional part of the keyword value gcount - number of groups in the primary array (usually = 1) gfptr - fitsfile* pointer to a grouping table HDU. group - GRPIDn/GRPLCn index value identifying a grouping table HDU, or data group number (=0 for non-grouped data) grouptype - Grouping table parameter that specifies the columns to be created in a grouping table HDU. Allowed values are: GT_ID_ALL_URI, GT_ID_REF, GT_ID_POS, GT_ID_ALL, GT_ID_REF_URI, and GT_ID_POS_URI. grpname - value to use for the GRPNAME keyword value. hdunum - sequence number of the HDU (Primary array = 1) hduok - was the HDU verification successful (=1) or not (= -1). Equals zero if the CHECKSUM keyword is not present. hdusum - 32 bit 1's complement checksum for the entire CHDU hdutype - HDU type: IMAGE_HDU (0), ASCII_TBL (1), BINARY_TBL (2), ANY_HDU (-1) header - returned character string containing all the keyword records headstart- starting address (in bytes) of the CHDU heapsize - size of the binary table heap, in bytes history - the HISTORY keyword comment string (70 char max, null-terminated) hour - hour within day (UTC) (0 - 23) inc - sampling interval for pixels in each FITS dimension inclist - array of pointers to matching keyword names incolnum - input column number; range = 1 to TFIELDS infile - the input filename, including path if specified infptr - pointer to a 'fitsfile' structure describing the input FITS file. intval - integer part of the keyword value iomode - file access mode: either READONLY (=0) or READWRITE (=1) keyname - name of a keyword (8 char max, null-terminated) keynum - position of keyword in header (1st keyword = 1) keyroot - root string for the keyword name (5 char max, null-terminated) keysexist- number of existing keyword records in the CHU keytype - header record type: -1=delete; 0=append or replace; 1=append; 2=this is the END keyword longstr - arbitrarily long string keyword value (null-terminated) lpixel - coordinate of the last pixel to be read or written in the FITS array. The array must be of length NAXIS and have values such that lpixel[0] is in the range 1 to NAXIS1, lpixel[1] is in the range 1 to NAXIS2, etc. match - TRUE (=1) if the 2 strings match, else FALSE (=0) maxdim - maximum number of values to return member - row number of a grouping table member HDU. memptr - pointer to the a FITS file in memory mem_realloc - pointer to a function for reallocating more memory memsize - size of the memory block allocated for the FITS file mfptr - fitsfile* pointer to a grouping table member HDU. mgopt - grouping table merge option parameter. Allowed values are: OPT_MRG_COPY, and OPT_MRG_MOV. minute - minute within hour (UTC) (0 - 59) month - calendar month (UTC) (1 - 12) morekeys - space in the header for this many more keywords n_good_rows - number of rows evaluating to TRUE namelist - string containing a comma or space delimited list of names naxes - size of each dimension in the FITS array naxis - number of dimensions in the FITS array naxis1 - length of the X/first axis of the FITS array naxis2 - length of the Y/second axis of the FITS array naxis3 - length of the Z/third axis of the FITS array nbytes - number of bytes or characters to read or write nchars - number of characters to read or write nelements- number of data elements to read or write newfptr - returned pointer to the reopened file newveclen- new value for the column vector repeat parameter nexc - number of names in the exclusion list (may = 0) nfound - number of keywords found (highest keyword number) nkeys - number of keywords in the sequence ninc - number of names in the inclusion list nmembers - Number of grouping table members (NAXIS2 value). nmove - number of HDUs to move (+ or -), relative to current position nocomments - if equal to TRUE, then no commentary keywords will be copied noisebits- number of bits to ignore when compressing floating point images nrows - number of rows in the table nstart - first integer value nullarray- set to TRUE (=1) if corresponding data element is undefined nulval - numerical value to represent undefined pixels nulstr - character string used to represent undefined values in ASCII table numval - numerical data value, of the appropriate data type offset - byte offset in the heap or data unit to the first element of the vector openfptr - pointer to a currently open FITS file overlap - number of bytes in the binary table heap pointed to by more than 1 descriptor outcolnum- output column number; range = 1 to TFIELDS + 1 outfile - and optional output filename; the input file will be copied to this prior to opening the file outfptr - pointer to a 'fitsfile' structure describing the output FITS file. pcount - value of the PCOUNT keyword = size of binary table heap previous - if TRUE, any previous HDUs in the input file will be copied. repeat - length of column vector (e.g. 12J); == 1 for ASCII table rmopt - grouping table remove option parameter. Allowed values are: OPT_RM_GPT, OPT_RM_ENTRY, OPT_RM_MBR, and OPT_RM_ALL. rootname - root filename, minus any extension or filtering specifications rot - celestial coordinate rotation angle (degrees) rowlen - length of a table row, in characters or bytes rowlist - sorted list of row numbers to be deleted from the table rownum - number of the row (first row = 1) rowrange - list of rows or row ranges: '3,6-8,12,56-80' or '500-' row_status - array of True/False results for each row that was evaluated scale - linear scaling factor; true value = (FITS value) * scale + zero second - second within minute (0 - 60.9999999999) (leap second!) section - section of image to be copied (e.g. 21:80,101:200) simple - TRUE (=1) if FITS file conforms to the Standard, else FALSE (=0) space - number of blank spaces to leave between ASCII table columns status - returned error status code (0 = OK) sum - 32 bit unsigned checksum value tbcol - byte position in row to start of column (1st col has tbcol = 1) tdisp - Fortran style display format for the table column tdimstr - the value of the TDIMn keyword templt - template string used in comparison (null-terminated) tfields - number of fields (columns) in the table tfopt - grouping table member transfer option parameter. Allowed values are: OPT_MCP_ADD, and OPT_MCP_MOV. tform - format of the column (null-terminated); allowed values are: ASCII tables: Iw, Aw, Fww.dd, Eww.dd, or Dww.dd Binary tables: rL, rX, rB, rI, rJ, rA, rAw, rE, rD, rC, rM where 'w'=width of the field, 'd'=no. of decimals, 'r'=repeat count. Variable length array columns are denoted by a '1P' before the data type character (e.g., '1PJ'). When creating a binary table, 2 addition tform data type codes are recognized by CFITSIO: 'rU' and 'rV' for unsigned 16-bit and unsigned 32-bit integer, respectively. theap - zero indexed byte offset of starting address of the heap relative to the beginning of the binary table data tilesize - array of length NAXIS that specifies the dimensions of the image compression tiles ttype - label or name for table column (null-terminated) tunit - physical unit for table column (null-terminated) typechar - symbolic code of the table column data type typecode - data type code of the table column. The negative of the value indicates a variable length array column. Datatype typecode Mnemonic bit, X 1 TBIT byte, B 11 TBYTE logical, L 14 TLOGICAL ASCII character, A 16 TSTRING short integer, I 21 TSHORT integer, J 41 TINT32BIT (same as TLONG) long long integer, K 81 TLONGLONG real, E 42 TFLOAT double precision, D 82 TDOUBLE complex, C 83 TCOMPLEX double complex, M 163 TDBLCOMPLEX unit - the physical unit string (e.g., 'km/s') for a keyword unused - number of unused bytes in the binary table heap urltype - the file type of the FITS file (file://, ftp://, mem://, etc.) validheap- returned value = FALSE if any of the variable length array address are outside the valid range of addresses in the heap value - the keyword value string (70 char max, null-terminated) version - current version number of the CFITSIO library width - width of the character string field xcol - number of the column containing the X coordinate values xinc - X axis coordinate increment at reference pixel (deg) xpix - X axis pixel location xpos - X axis celestial coordinate (usually RA) (deg) xrefpix - X axis reference pixel array location xrefval - X axis coordinate value at the reference pixel (deg) ycol - number of the column containing the X coordinate values year - calendar year (e.g. 1999, 2000, etc) yinc - Y axis coordinate increment at reference pixel (deg) ypix - y axis pixel location ypos - y axis celestial coordinate (usually DEC) (deg) yrefpix - Y axis reference pixel array location yrefval - Y axis coordinate value at the reference pixel (deg) zero - scaling offset; true value = (FITS value) * scale + zero \end{verbatim} \chapter{CFITSIO Error Status Codes } The following table lists all the error status codes used by CFITSIO. Programmers are encouraged to use the symbolic mnemonics (defined in the file fitsio.h) rather than the actual integer status values to improve the readability of their code. \begin{verbatim} Symbolic Const Value Meaning -------------- ----- ----------------------------------------- 0 OK, no error SAME_FILE 101 input and output files are the same TOO_MANY_FILES 103 tried to open too many FITS files at once FILE_NOT_OPENED 104 could not open the named file FILE_NOT_CREATED 105 could not create the named file WRITE_ERROR 106 error writing to FITS file END_OF_FILE 107 tried to move past end of file READ_ERROR 108 error reading from FITS file FILE_NOT_CLOSED 110 could not close the file ARRAY_TOO_BIG 111 array dimensions exceed internal limit READONLY_FILE 112 Cannot write to readonly file MEMORY_ALLOCATION 113 Could not allocate memory BAD_FILEPTR 114 invalid fitsfile pointer NULL_INPUT_PTR 115 NULL input pointer to routine SEEK_ERROR 116 error seeking position in file BAD_URL_PREFIX 121 invalid URL prefix on file name TOO_MANY_DRIVERS 122 tried to register too many IO drivers DRIVER_INIT_FAILED 123 driver initialization failed NO_MATCHING_DRIVER 124 matching driver is not registered URL_PARSE_ERROR 125 failed to parse input file URL RANGE_PARSE_ERROR 126 parse error in range list SHARED_BADARG 151 bad argument in shared memory driver SHARED_NULPTR 152 null pointer passed as an argument SHARED_TABFULL 153 no more free shared memory handles SHARED_NOTINIT 154 shared memory driver is not initialized SHARED_IPCERR 155 IPC error returned by a system call SHARED_NOMEM 156 no memory in shared memory driver SHARED_AGAIN 157 resource deadlock would occur SHARED_NOFILE 158 attempt to open/create lock file failed SHARED_NORESIZE 159 shared memory block cannot be resized at the moment HEADER_NOT_EMPTY 201 header already contains keywords KEY_NO_EXIST 202 keyword not found in header KEY_OUT_BOUNDS 203 keyword record number is out of bounds VALUE_UNDEFINED 204 keyword value field is blank NO_QUOTE 205 string is missing the closing quote BAD_INDEX_KEY 206 illegal indexed keyword name (e.g. 'TFORM1000') BAD_KEYCHAR 207 illegal character in keyword name or card BAD_ORDER 208 required keywords out of order NOT_POS_INT 209 keyword value is not a positive integer NO_END 210 couldn't find END keyword BAD_BITPIX 211 illegal BITPIX keyword value BAD_NAXIS 212 illegal NAXIS keyword value BAD_NAXES 213 illegal NAXISn keyword value BAD_PCOUNT 214 illegal PCOUNT keyword value BAD_GCOUNT 215 illegal GCOUNT keyword value BAD_TFIELDS 216 illegal TFIELDS keyword value NEG_WIDTH 217 negative table row size NEG_ROWS 218 negative number of rows in table COL_NOT_FOUND 219 column with this name not found in table BAD_SIMPLE 220 illegal value of SIMPLE keyword NO_SIMPLE 221 Primary array doesn't start with SIMPLE NO_BITPIX 222 Second keyword not BITPIX NO_NAXIS 223 Third keyword not NAXIS NO_NAXES 224 Couldn't find all the NAXISn keywords NO_XTENSION 225 HDU doesn't start with XTENSION keyword NOT_ATABLE 226 the CHDU is not an ASCII table extension NOT_BTABLE 227 the CHDU is not a binary table extension NO_PCOUNT 228 couldn't find PCOUNT keyword NO_GCOUNT 229 couldn't find GCOUNT keyword NO_TFIELDS 230 couldn't find TFIELDS keyword NO_TBCOL 231 couldn't find TBCOLn keyword NO_TFORM 232 couldn't find TFORMn keyword NOT_IMAGE 233 the CHDU is not an IMAGE extension BAD_TBCOL 234 TBCOLn keyword value < 0 or > rowlength NOT_TABLE 235 the CHDU is not a table COL_TOO_WIDE 236 column is too wide to fit in table COL_NOT_UNIQUE 237 more than 1 column name matches template BAD_ROW_WIDTH 241 sum of column widths not = NAXIS1 UNKNOWN_EXT 251 unrecognizable FITS extension type UNKNOWN_REC 252 unknown record; 1st keyword not SIMPLE or XTENSION END_JUNK 253 END keyword is not blank BAD_HEADER_FILL 254 Header fill area contains non-blank chars BAD_DATA_FILL 255 Illegal data fill bytes (not zero or blank) BAD_TFORM 261 illegal TFORM format code BAD_TFORM_DTYPE 262 unrecognizable TFORM data type code BAD_TDIM 263 illegal TDIMn keyword value BAD_HEAP_PTR 264 invalid BINTABLE heap pointer is out of range BAD_HDU_NUM 301 HDU number < 1 BAD_COL_NUM 302 column number < 1 or > tfields NEG_FILE_POS 304 tried to move to negative byte location in file NEG_BYTES 306 tried to read or write negative number of bytes BAD_ROW_NUM 307 illegal starting row number in table BAD_ELEM_NUM 308 illegal starting element number in vector NOT_ASCII_COL 309 this is not an ASCII string column NOT_LOGICAL_COL 310 this is not a logical data type column BAD_ATABLE_FORMAT 311 ASCII table column has wrong format BAD_BTABLE_FORMAT 312 Binary table column has wrong format NO_NULL 314 null value has not been defined NOT_VARI_LEN 317 this is not a variable length column BAD_DIMEN 320 illegal number of dimensions in array BAD_PIX_NUM 321 first pixel number greater than last pixel ZERO_SCALE 322 illegal BSCALE or TSCALn keyword = 0 NEG_AXIS 323 illegal axis length < 1 NOT_GROUP_TABLE 340 Grouping function error HDU_ALREADY_MEMBER 341 MEMBER_NOT_FOUND 342 GROUP_NOT_FOUND 343 BAD_GROUP_ID 344 TOO_MANY_HDUS_TRACKED 345 HDU_ALREADY_TRACKED 346 BAD_OPTION 347 IDENTICAL_POINTERS 348 BAD_GROUP_ATTACH 349 BAD_GROUP_DETACH 350 NGP_NO_MEMORY 360 malloc failed NGP_READ_ERR 361 read error from file NGP_NUL_PTR 362 null pointer passed as an argument. Passing null pointer as a name of template file raises this error NGP_EMPTY_CURLINE 363 line read seems to be empty (used internally) NGP_UNREAD_QUEUE_FULL 364 cannot unread more then 1 line (or single line twice) NGP_INC_NESTING 365 too deep include file nesting (infinite loop, template includes itself ?) NGP_ERR_FOPEN 366 fopen() failed, cannot open template file NGP_EOF 367 end of file encountered and not expected NGP_BAD_ARG 368 bad arguments passed. Usually means internal parser error. Should not happen NGP_TOKEN_NOT_EXPECT 369 token not expected here BAD_I2C 401 bad int to formatted string conversion BAD_F2C 402 bad float to formatted string conversion BAD_INTKEY 403 can't interpret keyword value as integer BAD_LOGICALKEY 404 can't interpret keyword value as logical BAD_FLOATKEY 405 can't interpret keyword value as float BAD_DOUBLEKEY 406 can't interpret keyword value as double BAD_C2I 407 bad formatted string to int conversion BAD_C2F 408 bad formatted string to float conversion BAD_C2D 409 bad formatted string to double conversion BAD_DATATYPE 410 illegal datatype code value BAD_DECIM 411 bad number of decimal places specified NUM_OVERFLOW 412 overflow during data type conversion DATA_COMPRESSION_ERR 413 error compressing image DATA_DECOMPRESSION_ERR 414 error uncompressing image BAD_DATE 420 error in date or time conversion PARSE_SYNTAX_ERR 431 syntax error in parser expression PARSE_BAD_TYPE 432 expression did not evaluate to desired type PARSE_LRG_VECTOR 433 vector result too large to return in array PARSE_NO_OUTPUT 434 data parser failed not sent an out column PARSE_BAD_COL 435 bad data encounter while parsing column PARSE_BAD_OUTPUT 436 Output file not of proper type ANGLE_TOO_BIG 501 celestial angle too large for projection BAD_WCS_VAL 502 bad celestial coordinate or pixel value WCS_ERROR 503 error in celestial coordinate calculation BAD_WCS_PROJ 504 unsupported type of celestial projection NO_WCS_KEY 505 celestial coordinate keywords not found APPROX_WCS_KEY 506 approximate wcs keyword values were returned \end{verbatim} \end{document} cfitsio/docs/cfitsio.toc0000644000225700000360000002576113246025103015112 0ustar cagordonlhea\contentsline {chapter}{\numberline {1}Introduction }{1}{chapter.1} \contentsline {section}{\numberline {1.1} A Brief Overview}{1}{section.1.1} \contentsline {section}{\numberline {1.2}Sources of FITS Software and Information}{1}{section.1.2} \contentsline {section}{\numberline {1.3}Acknowledgments}{2}{section.1.3} \contentsline {section}{\numberline {1.4}Legal Stuff}{4}{section.1.4} \contentsline {chapter}{\numberline {2} Creating the CFITSIO Library }{5}{chapter.2} \contentsline {section}{\numberline {2.1}Building the Library}{5}{section.2.1} \contentsline {subsection}{\numberline {2.1.1}Unix Systems}{5}{subsection.2.1.1} \contentsline {subsection}{\numberline {2.1.2}VMS}{7}{subsection.2.1.2} \contentsline {subsection}{\numberline {2.1.3}Windows PCs}{7}{subsection.2.1.3} \contentsline {subsection}{\numberline {2.1.4}Macintosh PCs}{7}{subsection.2.1.4} \contentsline {section}{\numberline {2.2}Testing the Library}{7}{section.2.2} \contentsline {section}{\numberline {2.3}Linking Programs with CFITSIO}{9}{section.2.3} \contentsline {section}{\numberline {2.4}Using CFITSIO in Multi-threaded Environments}{9}{section.2.4} \contentsline {section}{\numberline {2.5}Getting Started with CFITSIO}{9}{section.2.5} \contentsline {section}{\numberline {2.6}Example Program}{10}{section.2.6} \contentsline {chapter}{\numberline {3} A FITS Primer }{13}{chapter.3} \contentsline {chapter}{\numberline {4} Programming Guidelines }{15}{chapter.4} \contentsline {section}{\numberline {4.1}CFITSIO Definitions}{15}{section.4.1} \contentsline {section}{\numberline {4.2}Current Header Data Unit (CHDU)}{17}{section.4.2} \contentsline {section}{\numberline {4.3}Function Names and Variable Datatypes}{18}{section.4.3} \contentsline {section}{\numberline {4.4}Support for Unsigned Integers and Signed Bytes}{20}{section.4.4} \contentsline {section}{\numberline {4.5}Dealing with Character Strings}{22}{section.4.5} \contentsline {section}{\numberline {4.6}Implicit Data Type Conversion}{23}{section.4.6} \contentsline {section}{\numberline {4.7}Data Scaling}{23}{section.4.7} \contentsline {section}{\numberline {4.8}Support for IEEE Special Values}{24}{section.4.8} \contentsline {section}{\numberline {4.9}Error Status Values and the Error Message Stack}{24}{section.4.9} \contentsline {section}{\numberline {4.10}Variable-Length Arrays in Binary Tables}{25}{section.4.10} \contentsline {section}{\numberline {4.11}Multiple Access to the Same FITS File}{26}{section.4.11} \contentsline {section}{\numberline {4.12}When the Final Size of the FITS HDU is Unknown}{27}{section.4.12} \contentsline {section}{\numberline {4.13}CFITSIO Size Limitations}{28}{section.4.13} \contentsline {chapter}{\numberline {5}Basic CFITSIO Interface Routines }{31}{chapter.5} \contentsline {section}{\numberline {5.1}CFITSIO Error Status Routines}{31}{section.5.1} \contentsline {section}{\numberline {5.2}FITS File Access Routines}{32}{section.5.2} \contentsline {section}{\numberline {5.3}HDU Access Routines}{35}{section.5.3} \contentsline {section}{\numberline {5.4}Header Keyword Read/Write Routines}{37}{section.5.4} \contentsline {subsection}{\numberline {5.4.1}Keyword Reading Routines}{38}{subsection.5.4.1} \contentsline {subsection}{\numberline {5.4.2}Keyword Writing Routines}{40}{subsection.5.4.2} \contentsline {section}{\numberline {5.5}Primary Array or IMAGE Extension I/O Routines}{43}{section.5.5} \contentsline {section}{\numberline {5.6}Image Compression}{47}{section.5.6} \contentsline {section}{\numberline {5.7}ASCII and Binary Table Routines}{52}{section.5.7} \contentsline {subsection}{\numberline {5.7.1}Create New Table}{52}{subsection.5.7.1} \contentsline {subsection}{\numberline {5.7.2}Column Information Routines}{53}{subsection.5.7.2} \contentsline {subsection}{\numberline {5.7.3}Routines to Edit Rows or Columns}{55}{subsection.5.7.3} \contentsline {subsection}{\numberline {5.7.4}Read and Write Column Data Routines}{57}{subsection.5.7.4} \contentsline {subsection}{\numberline {5.7.5}Row Selection and Calculator Routines}{59}{subsection.5.7.5} \contentsline {subsection}{\numberline {5.7.6}Column Binning or Histogramming Routines}{61}{subsection.5.7.6} \contentsline {section}{\numberline {5.8}Utility Routines}{63}{section.5.8} \contentsline {subsection}{\numberline {5.8.1}File Checksum Routines}{63}{subsection.5.8.1} \contentsline {subsection}{\numberline {5.8.2}Date and Time Utility Routines}{65}{subsection.5.8.2} \contentsline {subsection}{\numberline {5.8.3}General Utility Routines}{66}{subsection.5.8.3} \contentsline {chapter}{\numberline {6} The CFITSIO Iterator Function }{77}{chapter.6} \contentsline {section}{\numberline {6.1}The Iterator Work Function}{78}{section.6.1} \contentsline {section}{\numberline {6.2}The Iterator Driver Function}{80}{section.6.2} \contentsline {section}{\numberline {6.3}Guidelines for Using the Iterator Function}{81}{section.6.3} \contentsline {section}{\numberline {6.4}Complete List of Iterator Routines}{82}{section.6.4} \contentsline {chapter}{\numberline {7} World Coordinate System Routines }{85}{chapter.7} \contentsline {section}{\numberline {7.1} Self-contained WCS Routines}{86}{section.7.1} \contentsline {chapter}{\numberline {8} Hierarchical Grouping Routines }{89}{chapter.8} \contentsline {section}{\numberline {8.1}Grouping Table Routines}{90}{section.8.1} \contentsline {section}{\numberline {8.2}Group Member Routines}{92}{section.8.2} \contentsline {chapter}{\numberline {9} Specialized CFITSIO Interface Routines }{95}{chapter.9} \contentsline {section}{\numberline {9.1}FITS File Access Routines}{95}{section.9.1} \contentsline {section}{\numberline {9.2}HDU Access Routines}{99}{section.9.2} \contentsline {section}{\numberline {9.3}Specialized Header Keyword Routines}{102}{section.9.3} \contentsline {subsection}{\numberline {9.3.1}Header Information Routines}{102}{subsection.9.3.1} \contentsline {subsection}{\numberline {9.3.2}Read and Write the Required Keywords}{102}{subsection.9.3.2} \contentsline {subsection}{\numberline {9.3.3}Write Keyword Routines}{104}{subsection.9.3.3} \contentsline {subsection}{\numberline {9.3.4}Insert Keyword Routines}{106}{subsection.9.3.4} \contentsline {subsection}{\numberline {9.3.5}Read Keyword Routines}{107}{subsection.9.3.5} \contentsline {subsection}{\numberline {9.3.6}Modify Keyword Routines}{108}{subsection.9.3.6} \contentsline {subsection}{\numberline {9.3.7}Update Keyword Routines}{110}{subsection.9.3.7} \contentsline {section}{\numberline {9.4}Define Data Scaling and Undefined Pixel Parameters}{110}{section.9.4} \contentsline {section}{\numberline {9.5}Specialized FITS Primary Array or IMAGE Extension I/O Routines}{111}{section.9.5} \contentsline {section}{\numberline {9.6}Specialized FITS ASCII and Binary Table Routines}{115}{section.9.6} \contentsline {subsection}{\numberline {9.6.1}General Column Routines}{115}{subsection.9.6.1} \contentsline {subsection}{\numberline {9.6.2}Low-Level Table Access Routines}{116}{subsection.9.6.2} \contentsline {subsection}{\numberline {9.6.3}Write Column Data Routines}{117}{subsection.9.6.3} \contentsline {subsection}{\numberline {9.6.4}Read Column Data Routines}{118}{subsection.9.6.4} \contentsline {chapter}{\numberline {10} Extended File Name Syntax }{123}{chapter.10} \contentsline {section}{\numberline {10.1}Overview}{123}{section.10.1} \contentsline {section}{\numberline {10.2}Filetype}{126}{section.10.2} \contentsline {subsection}{\numberline {10.2.1}Notes about HTTP proxy servers}{127}{subsection.10.2.1} \contentsline {subsection}{\numberline {10.2.2}Notes about HTTPS file access}{127}{subsection.10.2.2} \contentsline {subsection}{\numberline {10.2.3}Notes about the stream filetype driver}{128}{subsection.10.2.3} \contentsline {subsection}{\numberline {10.2.4}Notes about the gsiftp filetype}{128}{subsection.10.2.4} \contentsline {subsection}{\numberline {10.2.5}Notes about the root filetype}{129}{subsection.10.2.5} \contentsline {subsection}{\numberline {10.2.6}Notes about the shmem filetype:}{131}{subsection.10.2.6} \contentsline {section}{\numberline {10.3}Base Filename}{131}{section.10.3} \contentsline {section}{\numberline {10.4}Output File Name when Opening an Existing File}{133}{section.10.4} \contentsline {section}{\numberline {10.5}Template File Name when Creating a New File}{135}{section.10.5} \contentsline {section}{\numberline {10.6}Image Tile-Compression Specification}{135}{section.10.6} \contentsline {section}{\numberline {10.7}HDU Location Specification}{135}{section.10.7} \contentsline {section}{\numberline {10.8}Image Section}{137}{section.10.8} \contentsline {section}{\numberline {10.9}Image Transform Filters}{138}{section.10.9} \contentsline {section}{\numberline {10.10}Column and Keyword Filtering Specification}{139}{section.10.10} \contentsline {section}{\numberline {10.11}Row Filtering Specification}{142}{section.10.11} \contentsline {subsection}{\numberline {10.11.1}General Syntax}{142}{subsection.10.11.1} \contentsline {subsection}{\numberline {10.11.2}Bit Masks}{145}{subsection.10.11.2} \contentsline {subsection}{\numberline {10.11.3}Vector Columns}{146}{subsection.10.11.3} \contentsline {subsection}{\numberline {10.11.4}Good Time Interval Filtering}{147}{subsection.10.11.4} \contentsline {subsection}{\numberline {10.11.5}Spatial Region Filtering}{148}{subsection.10.11.5} \contentsline {subsection}{\numberline {10.11.6}Example Row Filters}{150}{subsection.10.11.6} \contentsline {section}{\numberline {10.12} Binning or Histogramming Specification}{151}{section.10.12} \contentsline {chapter}{\numberline {11}Template Files }{155}{chapter.11} \contentsline {section}{\numberline {11.1}Detailed Template Line Format}{155}{section.11.1} \contentsline {section}{\numberline {11.2}Auto-indexing of Keywords}{156}{section.11.2} \contentsline {section}{\numberline {11.3}Template Parser Directives}{157}{section.11.3} \contentsline {section}{\numberline {11.4}Formal Template Syntax}{158}{section.11.4} \contentsline {section}{\numberline {11.5}Errors}{158}{section.11.5} \contentsline {section}{\numberline {11.6}Examples}{158}{section.11.6} \contentsline {chapter}{\numberline {12} Local FITS Conventions }{161}{chapter.12} \contentsline {section}{\numberline {12.1}64-Bit Long Integers}{161}{section.12.1} \contentsline {section}{\numberline {12.2}Long String Keyword Values.}{161}{section.12.2} \contentsline {section}{\numberline {12.3}Arrays of Fixed-Length Strings in Binary Tables}{163}{section.12.3} \contentsline {section}{\numberline {12.4}Keyword Units Strings}{163}{section.12.4} \contentsline {section}{\numberline {12.5}HIERARCH Convention for Extended Keyword Names}{163}{section.12.5} \contentsline {section}{\numberline {12.6}Tile-Compressed Image Format}{164}{section.12.6} \contentsline {chapter}{\numberline {13} Optimizing Programs }{167}{chapter.13} \contentsline {section}{\numberline {13.1}How CFITSIO Manages Data I/O}{167}{section.13.1} \contentsline {section}{\numberline {13.2}Optimization Strategies}{168}{section.13.2} \contentsline {chapter}{\numberline {A}Index of Routines }{173}{appendix.A} \contentsline {chapter}{\numberline {B}Parameter Definitions }{179}{appendix.B} \contentsline {chapter}{\numberline {C}CFITSIO Error Status Codes }{185}{appendix.C} cfitsio/docs/cfortran.doc0000644000225700000360000027237313246025103015253 0ustar cagordonlhea/* cfortran.doc 4.3 */ /* www-zeus.desy.de/~burow OR anonymous ftp@zebra.desy.de */ /* Burkhard Burow burow@desy.de 1990 - 1998. */ See Licensing information at the end of this file. cfortran.h : Interfacing C or C++ and FORTRAN Supports: Alpha and VAX VMS, Alpha OSF, DECstation and VAX Ultrix, IBM RS/6000, Silicon Graphics, Sun, CRAY, Apollo, HP9000, LynxOS, Convex, Absoft, f2c, g77, NAG f90, PowerStation Fortran with Visual C++, NEC SX-4, Portland Group. C and C++ are generally equivalent as far as cfortran.h is concerned. Unless explicitly noted otherwise, mention of C implicitly includes C++. C++ compilers tested include: SunOS> CC +p +w # Clean compiles. IRIX> CC # Clean compiles. IRIX> CC -fullwarn # Still some warnings to be overcome. GNU> g++ -Wall # Compiles are clean, other than warnings for unused # cfortran.h static routines. N.B.: The best documentation on interfacing C or C++ and Fortran is in the chapter named something like 'Interfacing C and Fortran' to be found in the user's guide of almost every Fortran compiler. Understanding this information for one or more Fortran compilers greatly clarifies the aims and actions of cfortran.h. Such a chapter generally also addresses issues orthogonal to cfortran.h, for example the order of array indices, the index of the first element, as well as compiling and linking issues. 0 Short Summary of the Syntax Required to Create the Interface -------------------------------------------------------------- e.g. Prototyping a FORTRAN subroutine for C: /* PROTOCCALLSFSUBn is optional for C, but mandatory for C++. */ PROTOCCALLSFSUB2(SUB_NAME,sub_name,STRING,PINT) #define SUB_NAME(A,B) CCALLSFSUB2(SUB_NAME,sub_name,STRING,PINT, A,B) ^ - - number of arguments _____| | STRING BYTE PBYTE BYTEV(..)| / | STRINGV DOUBLE PDOUBLE DOUBLEV(..)| / | PSTRING FLOAT PFLOAT FLOATV(..)| types of arguments ____ / | PNSTRING INT PINT INTV(..)| \ | PPSTRING LOGICAL PLOGICAL LOGICALV(..)| \ | PSTRINGV LONG PLONG LONGV(..)| \ | ZTRINGV SHORT PSHORT SHORTV(..)| | PZTRINGV ROUTINE PVOID SIMPLE | - - e.g. Prototyping a FORTRAN function for C: /* PROTOCCALLSFFUNn is mandatory for both C and C++. */ PROTOCCALLSFFUN1(INT,FUN_NAME,fun_name,STRING) #define FUN_NAME(A) CCALLSFFUN1(FUN_NAME,fun_name,STRING, A) e.g. calling FUN_NAME from C: {int a; a = FUN_NAME("hello");} e.g. Creating a FORTRAN-callable wrapper for a C function returning void, with a 7 dimensional integer array argument: [Not supported from C++.] FCALLSCSUB1(csub_name,CSUB_NAME,csub_name,INTVVVVVVV) e.g. Creating a FORTRAN-callable wrapper for other C functions: FCALLSCFUN1(STRING,cfun_name,CFUN_NAME,cfun_name,INT) [ ^-- BYTE, DOUBLE, FLOAT, INT, LOGICAL, LONG, SHORT, VOID are other types returned by functions. ] e.g. COMMON BLOCKs: FORTRAN: common /fcb/ v,w,x character *(13) v, w(4), x(3,2) C: typedef struct { char v[13],w[4][13],x[2][3][13]; } FCB_DEF; #define FCB COMMON_BLOCK(FCB,fcb) COMMON_BLOCK_DEF(FCB_DEF,FCB); FCB_DEF FCB; /* Define, i.e. allocate memory, in exactly one *.c file. */ e.g. accessing FCB in C: printf("%.13s",FCB.v); I Introduction -------------- cfortran.h is an easy-to-use powerful bridge between C and FORTRAN. It provides a completely transparent, machine independent interface between C and FORTRAN routines (= subroutines and/or functions) and global data, i.e. structures and COMMON blocks. The complete cfortran.h package consists of 4 files: the documentation in cfortran.doc, the engine cfortran.h, examples in cfortest.c and cfortex.f/or. [cfortex.for under VMS, cfortex.f on other machines.] The cfortran.h package continues to be developed. The most recent version is available via www at http://www-zeus.desy.de/~burow or via anonymous ftp at zebra.desy.de (131.169.2.244). The examples may be run using one of the following sets of instructions: N.B. Unlike earlier versions, cfortran.h 3.0 and later versions automatically uses the correct ANSI ## or pre-ANSI /**/ preprocessor operator as required by the C compiler. N.B. As a general rule when trying to determine how to link C and Fortran, link a trivial Fortran program using the Fortran compilers verbose option, in order to see how the Fortran compiler drives the linker. e.g. unix> cat f.f END unix> f77 -v f.f .. lots of info. follows ... N.B. If using a C main(), i.e. Fortran PROGRAM is not entry of the executable, and if the link bombs with a complaint about a missing "MAIN" (e.g. MAIN__, MAIN_, f90_main or similar), then Fortran has hijacked the entry point to the executable and wishes to call the rest of the executable via "MAIN". This can usually be satisfied by doing e.g. 'cc -Dmain=MAIN__ ...' but often kills the command line arguments in argv and argc. The f77 verbose option, usually -v, may point to a solution. RS/6000> # Users are strongly urged to use f77 -qextname and cc -Dextname RS/6000> # Use -Dextname=extname if extname is a symbol used in the C code. RS/6000> xlf -c -qextname cfortex.f RS/6000> cc -c -Dextname cfortest.c RS/6000> xlf -o cfortest cfortest.o cfortex.o && cfortest DECFortran> #Only DECstations with DECFortran for Ultrix RISC Systems. DECFortran> cc -c -DDECFortran cfortest.c DECFortran> f77 -o cfortest cfortest.o cfortex.f && cfortest IRIX xxxxxx 5.2 02282015 IP20 mips MIPS> # DECstations and Silicon Graphics using the MIPS compilers. MIPS> cc -o cfortest cfortest.c cfortex.f -lI77 -lU77 -lF77 && cfortest MIPS> # Can also let f77 drive linking, e.g. MIPS> cc -c cfortest.c MIPS> f77 -o cfortest cfortest.o cfortex.f && cfortest Apollo> # Some 'C compiler 68K Rev6.8' break. [See Section II o) Notes: Apollo] Apollo> f77 -c cfortex.f && cc -o cfortest cfortest.c cfortex.o && cfortest VMS> define lnk$library sys$library:vaxcrtl VMS> cc cfortest.c VMS> fortran cfortex.for VMS> link/exec=cfortest cfortest,cfortex VMS> run cfortest OSF1 xxxxxx V3.0 347 alpha Alpha/OSF> # Probably better to let cc drive linking, e.g. Alpha/OSF> f77 -c cfortex.f Alpha/OSF> cc -o cfortest cfortest.c cfortex.o -lUfor -lfor -lFutil -lots -lm Alpha/OSF> cfortest Alpha/OSF> # Else may need 'cc -Dmain=MAIN__' to let f77 drive linking. Sun> # Some old cc(1) need a little help. [See Section II o) Notes: Sun] Sun> f77 -o cfortest cfortest.c cfortex.f -lc -lm && cfortest Sun> # Some older f77 may require 'cc -Dmain=MAIN_'. CRAY> cft77 cfortex.f CRAY> cc -c cfortest.c CRAY> segldr -o cfortest.e cfortest.o cfortex.o CRAY> ./cfortest.e NEC> cc -c -Xa cfortest.c NEC> f77 -o cfortest cfortest.o cfortex.f && cfortest VAX/Ultrix/cc> # For cc on VAX Ultrix only, do the following once to cfortran.h. VAX/Ultrix/cc> mv cfortran.h cftmp.h && grep -v "^#pragma" cfortran.h VAX/Ultrix/f77> # In the following, 'CC' is either 'cc' or 'gcc -ansi'. NOT'vcc' VAX/Ultrix/f77> CC -c -Dmain=MAIN_ cfortest.c VAX/Ultrix/f77> f77 -o cfortest cfortex.f cfortest.o && cfortest LynxOS> # In the following, 'CC' is either 'cc' or 'gcc -ansi'. LynxOS> # Unfortunately cc is easily overwhelmed by cfortran.h, LynxOS> # and won't compile some of the cfortest.c demos. LynxOS> f2c -R cfortex.f LynxOS> CC -Dlynx -o cfortest cfortest.c cfortex.c -lf2c && cfortest HP9000> # Tested with HP-UX 7.05 B 9000/380 and with A.08.07 A 9000/730 HP9000> # CC may be either 'c89 -Aa' or 'cc -Aa' HP9000> # Depending on the compiler version, you may need to include the HP9000> # option '-tp,/lib/cpp' or worse, you'll have to stick to the K&R C. HP9000> # [See Section II o) Notes: HP9000] HP9000> # Users are strongly urged to use f77 +ppu and cc -Dextname HP9000> # Use -Dextname=extname if extname is a symbol used in the C code. HP9000> CC -Dextname -c cfortest.c HP9000> f77 +ppu cfortex.f -o cfortest cfortest.o && cfortest HP9000> # Older f77 may need HP9000> f77 -c cfortex.f HP9000> CC -o cfortest cfortest.c cfortex.o -lI77 -lF77 && cfortest HP0000> # If old-style f77 +800 compiled objects are required: HP9000> # #define hpuxFortran800 HP9000> cc -c -Aa -DhpuxFortran800 cfortest.c HP9000> f77 +800 -o cfortest cfortest.o cfortex.f f2c> # In the following, 'CC' is any C compiler. f2c> f2c -R cfortex.f f2c> CC -o cfortest -Df2cFortran cfortest.c cfortex.c -lf2c && cfortest Portland Group $ # Presumably other C compilers also work. Portland Group $ pgcc -DpgiFortran -c cfortest.c Portland Group $ pgf77 -o cfortest cfortex.f cfortest.o && cfortest NAGf90> # cfortex.f is distributed with Fortran 77 style comments. NAGf90> # To convert to f90 style comments do the following once to cfortex.f: NAGf90> mv cfortex.f cf_temp.f && sed 's/^C/\!/g' cf_temp.f > cfortex.f NAGf90> # In the following, 'CC' is any C compiler. NAGf90> CC -c -DNAGf90Fortran cfortest.c NAGf90> f90 -o cfortest cfortest.o cfortex.f && cfortest PC> # On a PC with PowerStation Fortran and Visual_C++ PC> cl /c cftest.c PC> fl32 cftest.obj cftex.for GNU> # GNU Fortran GNU> # See Section VI caveat on using 'gcc -traditional'. GNU> gcc -ansi -Wall -O -c -Df2cFortran cfortest.c GNU> g77 -ff2c -o cfortest cfortest.o cfortex.f && cfortest AbsoftUNIX> # Absoft Fortran for all UNIX based operating systems. AbsoftUNIX> # e.g. Linux or Next on Intel or Motorola68000. AbsoftUNIX> # Absoft f77 -k allows Fortran routines to be safely called from C. AbsoftUNIX> gcc -ansi -Wall -O -c -DAbsoftUNIXFortran cfortest.c AbsoftUNIX> f77 -k -o cfortest cfortest.o cfortex.f && cfortest AbsoftPro> # Absoft Pro Fortran for MacOS AbsoftPro> # Use #define AbsoftProFortran CLIPPER> # INTERGRAPH CLIX using CLIPPER C and Fortran compilers. CLIPPER> # N.B. - User, not cfortran.h, is responsible for CLIPPER> # f77initio() and f77uninitio() if required. CLIPPER> # - LOGICAL values are not mentioned in CLIPPER doc.s, CLIPPER> # so they may not yet be correct in cfortran.h. CLIPPER> # - K&R mode (-knr or Ac=knr) breaks FLOAT functions CLIPPER> # (see CLIPPER doc.s) and cfortran.h does not fix it up. CLIPPER> # [cfortran.h ok for old sun C which made the same mistake.] CLIPPER> acc cfortest.c -c -DCLIPPERFortran CLIPPER> af77 cfortex.f cfortest.o -o cfortest By changing the SELECTion ifdef of cfortest.c and recompiling one can try out a few dozen different few-line examples. The benefits of using cfortran.h include: 1. Machine/OS/compiler independent mixing of C and FORTRAN. 2. Identical (within syntax) calls across languages, e.g. C FORTRAN CALL HBOOK1(1,'pT spectrum of pi+',100,0.,5.,0.) /* C*/ HBOOK1(1,"pT spectrum of pi+",100,0.,5.,0.); 3. Each routine need only be set up once in its lifetime. e.g. /* Setting up a FORTRAN routine to be called by C. ID,...,VMX are merely the names of arguments. These tags must be unique w.r.t. each other but are otherwise arbitrary. */ PROTOCCALLSFSUB6(HBOOK1,hbook1,INT,STRING,INT,FLOAT,FLOAT,FLOAT) #define HBOOK1(ID,CHTITLE,NX,XMI,XMA,VMX) \ CCALLSFSUB6(HBOOK1,hbook1,INT,STRING,INT,FLOAT,FLOAT,FLOAT, \ ID,CHTITLE,NX,XMI,XMA,VMX) 4. Source code is NOT required for the C routines exported to FORTRAN, nor for the FORTRAN routines imported to C. In fact, routines are most easily prototyped using the information in the routines' documentation. 5. Routines, and the code calling them, can be coded naturally in the language of choice. C routines may be coded with the natural assumption of being called only by C code. cfortran.h does all the required work for FORTRAN code to call C routines. Similarly it also does all the work required for C to call FORTRAN routines. Therefore: - C programmers need not embed FORTRAN argument passing mechanisms into their code. - FORTRAN code need not be converted into C code. i.e. The honed and time-honored FORTRAN routines are called by C. 6. cfortran.h is a single ~1700 line C include file; portable to most remaining, if not all, platforms. 7. STRINGS and VECTORS of STRINGS along with the usual simple arguments to routines are supported as are functions returning STRINGS or numbers. Arrays of pointers to strings and values of structures as C arguments, will soon be implemented. After learning the machinery of cfortran.h, users can expand it to create custom types of arguments. [This requires no modification to cfortran.h, all the preprocessor directives required to implement the custom types can be defined outside cfortran.h] 8. cfortran.h requires each routine to be exported to be explicitly set up. While is usually only be done once in a header file it would be best if applications were required to do no work at all in order to cross languages. cfortran.h's simple syntax could be a convenient back-end for a program which would export FORTRAN or C routines directly from the source code. ----- Example 1 - cfortran.h has been used to make the C header file hbook.h, which then gives any C programmer, e.g. example.c, full and completely transparent access to CERN's HBOOK library of routines. Each HBOOK routine required about 3 lines of simple code in hbook.h. The example also demonstrates how FORTRAN common blocks are defined and used. /* hbook.h */ #include "cfortran.h" : PROTOCCALLSFSUB6(HBOOK1,hbook1,INT,STRING,INT,FLOAT,FLOAT,FLOAT) #define HBOOK1(ID,CHTITLE,NX,XMI,XMA,VMX) \ CCALLSFSUB6(HBOOK1,hbook1,INT,STRING,INT,FLOAT,FLOAT,FLOAT, \ ID,CHTITLE,NX,XMI,XMA,VMX) : /* end hbook.h */ /* example.c */ #include "hbook.h" : typedef struct { int lines; int status[SIZE]; float p[SIZE]; /* momentum */ } FAKE_DEF; #define FAKE COMMON_BLOCK(FAKE,fake) COMMON_BLOCK_DEF(FAKE_DEF,FAKE); : main () { : HBOOK1(1,"pT spectrum of pi+",100,0.,5.,0.); /* c.f. the call in FORTRAN: CALL HBOOK1(1,'pT spectrum of pi+',100,0.,5.,0.) */ : FAKE.p[7]=1.0; : } N.B. i) The routine is language independent. ii) hbook.h is machine independent. iii) Applications using routines via cfortran.h are machine independent. ----- Example 2 - Many VMS System calls are most easily called from FORTRAN, but cfortran.h now gives that ease in C. #include "cfortran.h" PROTOCCALLSFSUB3(LIB$SPAWN,lib$spawn,STRING,STRING,STRING) #define LIB$SPAWN(command,input_file,output_file) \ CCALLSFSUB3(LIB$SPAWN,lib$spawn,STRING,STRING,STRING, \ command,input_file,output_file) main () { LIB$SPAWN("set term/width=132","",""); } Obviously the cfortran.h command above could be put into a header file along with the description of the other system calls, but as this example shows, it's not much hassle to set up cfortran.h for even a single call. ----- Example 3 - cfortran.h and the source cstring.c create the cstring.obj library which gives FORTRAN access to all the functions in C's system library described by the system's C header file string.h. C EXAMPLE.FOR PROGRAM EXAMPLE DIMENSION I(20), J(30) : CALL MEMCPY(I,J,7) : END /* cstring.c */ #include /* string.h prototypes memcpy() */ #include "cfortran.h" : FCALLSCSUB3(memcpy,MEMCPY,memcpy,PVOID,PVOID,INT) : The simplicity exhibited in the above example exists for many but not all machines. Note 4. of Section II ii) details the limitations and describes tools which try to maintain the best possible interface when FORTRAN calls C routines. ----- II Using cfortran.h ------------------- The user is asked to look at the source files cfortest.c and cfortex.f for clarification by example. o) Notes: o Specifying the Fortran compiler cfortran.h generates interfaces for the default Fortran compiler. The default can be overridden by defining, . in the code, e.g.: #define NAGf90Fortran OR . in the compile directive, e.g.: unix> cc -DNAGf90Fortran one of the following before including cfortran.h: NAGf90Fortran f2cFortran hpuxFortran apolloFortran sunFortran IBMR2Fortran CRAYFortran mipsFortran DECFortran vmsFortran CONVEXFortran PowerStationFortran AbsoftUNIXFortran SXFortran pgiFortran AbsoftProFortran This also allows crosscompilation. If wanted, NAGf90Fortran, f2cFortran, DECFortran, AbsoftUNIXFortran, AbsoftProFortran and pgiFortran must be requested by the user. o /**/ cfortran.h (ab)uses the comment kludge /**/ when the ANSI C preprocessor catenation operator ## doesn't exist. In at least MIPS C, this kludge is sensitive to blanks surrounding arguments to macros. Therefore, for applications using non-ANSI C compilers, the argtype_i, routine_name, routine_type and common_block_name arguments to the PROTOCCALLSFFUNn, CCALLSFSUB/FUNn, FCALLSCSUB/FUNn and COMMON_BLOCK macros --- MUST NOT --- be followed by any white space characters such as blanks, tabs or newlines. o LOGICAL FORTRAN LOGICAL values of .TRUE. and .FALSE. do not agree with the C representation of TRUE and FALSE on all machines. cfortran.h does the conversion for LOGICAL and PLOGICAL arguments and for functions returning LOGICAL. Users must convert arrays of LOGICALs from C to FORTRAN with the C2FLOGICALV(array_name, elements_in_array); macro. Similarly, arrays of LOGICAL values may be converted from the FORTRAN into C representation by using F2CLOGICALV(array_name, elements_in_array); When C passes or returns LOGICAL values to FORTRAN, by default cfortran.h only makes the minimal changes required to the value. [e.g. Set/Unset the single relevant bit or do nothing for FORTRAN compilers which use 0 as FALSE and treat all other values as TRUE.] Therefore cfortran.h will pass LOGICALs to FORTRAN which do not have an identical representation to .TRUE. or .FALSE. This is fine except for abuses of FORTRAN/77 in the style of: logical l if (l .eq. .TRUE.) ! (1) instead of the correct: if (l .eqv. .TRUE.) ! (2) or: if (l) ! (3) For FORTRAN code which treats LOGICALs from C in the method of (1), LOGICAL_STRICT must be defined before including cfortran.h, either in the code, "#define LOGICAL_STRICT", or compile with "cc -DLOGICAL_STRICT". There is no reason to use LOGICAL_STRICT for FORTRAN code which does not do (1). At least the IBM's xlf and the Apollo's f77 do not even allow code along the lines of (1). DECstations' DECFortran and MIPS FORTRAN compilers use different internal representations for LOGICAL values. [Both compilers are usually called f77, although when both are installed on a single machine the MIPS' one is usually renamed. (e.g. f772.1 for version 2.10.)] cc doesn't know which FORTRAN compiler is present, so cfortran.h assumes MIPS f77. To use cc with DECFortran define the preprocessor constant 'DECFortran'. e.g. i) cc -DDECFortran -c the_code.c or ii) #define DECFortran /* in the C code or add to cfortran.h. */ MIPS f77 [SGI and DECstations], f2c, and f77 on VAX Ultrix treat .eqv./.neqv. as .eq./.ne.. Therefore, for these compilers, LOGICAL_STRICT is defined by default in cfortran.h. [The Sun and HP compilers have not been tested, so they may also require LOGICAL_STRICT as the default.] o SHORT and BYTE They are irrelevant for the CRAY where FORTRAN has no equivalent to C's short. Similarly BYTE is irrelevant for f2c and for VAX Ultrix f77 and fort. The author has tested SHORT and BYTE with a modified cfortest.c/cfortex.f on all machines supported except for the HP9000 and the Sun. BYTE is a signed 8-bit quantity, i.e. values are -128 to 127, on all machines except for the SGI [at least for MIPS Computer Systems 2.0.] On the SGI it is an unsigned 8-bit quantity, i.e. values are 0 to 255, although the SGI 'FORTRAN 77 Programmers Guide' claims BYTE is signed. Perhaps MIPS 2.0 is dated, since the DECstations using MIPS 2.10 f77 have a signed BYTE. To minimize the difficulties of signed and unsigned BYTE, cfortran.h creates the type 'INTEGER_BYTE' to agree with FORTRAN's BYTE. Users may define SIGNED_BYTE or UNSIGNED_BYTE, before including cfortran.h, to specify FORTRAN's BYTE. If neither is defined, cfortran.h assumes SIGNED_BYTE. o CRAY The type DOUBLE in cfortran.h corresponds to FORTRAN's DOUBLE PRECISION. The type FLOAT in cfortran.h corresponds to FORTRAN's REAL. On a classic CRAY [i.e. all models except for the t3e]: ( 64 bit) C float == C double == Fortran REAL (128 bit) C long double == Fortran DOUBLE PRECISION Therefore when moving a mixed C and FORTRAN app. to/from a classic CRAY, either the C code will have to change, or the FORTRAN code and cfortran.h declarations will have to change. DOUBLE_PRECISION is a cfortran.h macro which provides the former option, i.e. the C code is automatically changed. DOUBLE_PRECISION is 'long double' on classic CRAY and 'double' elsewhere. DOUBLE_PRECISION thus corresponds to FORTRAN's DOUBLE PRECISION on all machines, including classic CRAY. On a classic CRAY with the fortran compiler flag '-dp': Fortran DOUBLE PRECISION thus is also the faster 64bit type. (This switch is often used since the application is usually satisfied by 64 bit precision and the application needs the speed.) DOUBLE_PRECISION is thus not required in this case, since the classic CRAY behaves like all other machines. If DOUBLE_PRECISION is used nonetheless, then on the classic CRAY the default cfortran.h behavior must be overridden, for example by the C compiler option '-DDOUBLE_PRECISION=double'. On a CRAY t3e: (32 bit) C float == Fortran Unavailable (64 bit) C double == C long double == Fortran REAL == Fortran DOUBLE PRECISION Notes: - (32 bit) is available as Fortran REAL*4 and (64 bit) is available as Fortran REAL*8. Since cfortran.h is all about more portability, not about less portability, the use of the nonstandard REAL*4 and REAL*8 is strongly discouraged. - Fortran DOUBLE PRECISION is folded to REAL with the following warning: 'DOUBLE PRECISION is not supported on this platform. REAL will be used.' Similarly, Fortran REAL*16 is mapped to REAL*8 with a warning. This behavior differs from that of other machines, including the classic CRAY. FORTRAN_REAL is thus introduced for the t3e, just as DOUBLE_PRECISION is introduced for the classic CRAY. FORTRAN_REAL is 'double' on t3e and 'float' elsewhere. FORTRAN_REAL thus corresponds to FORTRAN's REAL on all machines, including t3e. o f2c f2c, by default promotes REAL functions to double. cfortran.h does not (yet) support this, so the f2c -R option must be used to turn this promotion off. o f2c [Thanks to Dario Autiero for pointing out the following.] f2c has a strange feature in that either one or two underscores are appended to a Fortran name of a routine or common block, depending on whether or not the original name contains an underscore. S.I. Feldman et al., "A fortran to C converter", Computing Science Technical Report No. 149. page 2, chapter 2: INTERLANGUAGE conventions ........... To avoid conflict with the names of library routines and with names that f2c generates, Fortran names may have one or two underscores appended. Fortran names are forced to lower case (unless the -U option described in Appendix B is in effect); external names, i.e. the names of fortran procedures and common blocks, have a single underscore appended if they do not contain any underscore and have a pair of underscores appended if they do contain underscores. Thus fortran subroutines names ABC, A_B_C and A_B_C_ result in C functions named abc_, a_b_c__ and a_b_c___. ........... cfortran.h is unable to change the naming convention on a name by name basis. Fortran routine and common block names which do not contain an underscore are unaffected by this feature. Names which do contain an underscore may use the following work-around: /* First 2 lines are a completely standard cfortran.h interface to the Fortran routine E_ASY . */ PROTOCCALLSFSUB2(E_ASY,e_asy, PINT, INT) #define E_ASY(A,B) CCALLSFSUB2(E_ASY,e_asy, PINT, INT, A, B) #ifdef f2cFortran #define e_asy_ e_asy__ #endif /* Last three lines are a work-around for the strange f2c naming feature. */ o NAG f90 The Fortran 77 subset of Fortran 90 is supported. Extending cfortran.h to interface C with all of Fortran 90 has not yet been examined. The NAG f90 library hijacks the main() of any program and starts the user's program with a call to: void f90_main(void); While this in itself is only a minor hassle, a major problem arises because NAG f90 provides no mechanism to access command line arguments. At least version 'NAGWare f90 compiler Version 1.1(334)' appended _CB to common block names instead of the usual _. To fix, add this to cfortran.h: #ifdef old_NAG_f90_CB_COMMON #define COMMON_BLOCK CFC_ /* for all other Fortran compilers */ #else #define COMMON_BLOCK(UN,LN) _(LN,_CB) #endif o RS/6000 Using "xlf -qextname ...", which appends an underscore, '_', to all FORTRAN external references, requires "cc -Dextname ..." so that cfortran.h also generates these underscores. Use -Dextname=extname if extname is a symbol used in the C code. The use of "xlf -qextname" is STRONGLY ENCOURAGED, since it allows for transparent naming schemes when mixing C and Fortran. o HP9000 Using "f77 +ppu ...", which appends an underscore, '_', to all FORTRAN external references, requires "cc -Dextname ..." so that cfortran.h also generates these underscores. Use -Dextname=extname if extname is a symbol used in the C code. The use of "f77 +ppu" is STRONGLY ENCOURAGED, since it allows for transparent naming schemes when mixing C and Fortran. At least one release of the HP /lib/cpp.ansi preprocessor is broken and will go into an infinite loop when trying to process cfortran.h with the ## catenation operator. The K&R version of cfortran.h must then be used and the K&R preprocessor must be specified. e.g. HP9000> cc -Aa -tp,/lib/cpp -c source.c The same problem with a similar solution exists on the Apollo. An irrelevant error message '0: extraneous name /usr/include' will appear for each source file due to another HP bug, and can be safely ignored. e.g. 'cc -v -c -Aa -tp,/lib/cpp cfortest.c' will show that the driver passes '-I /usr/include' instead of '-I/usr/include' to /lib/cpp On some machines the above error causes compilation to stop; one must then use K&R C, as with old HP compilers which don't support function prototyping. cfortran.h has to be informed that K&R C is to being used, e.g. HP9000> cc -D__CF__KnR -c source.c o AbsoftUNIXFortran By default, cfortran.h follows the default AbsoftUNIX/ProFortran and prepends _C to each COMMON BLOCK name. To override the cfortran.h behavior #define COMMON_BLOCK(UN,LN) before #including cfortran.h. [Search for COMMON_BLOCK in cfortran.h for examples.] o Apollo On at least one release, 'C compiler 68K Rev6.8(168)', the default C preprocessor, from cc -A xansi or cc -A ansi, enters an infinite loop when using cfortran.h. This Apollo bug can be circumvented by using: . cc -DANSI_C_preprocessor=0 to force use of /**/, instead of '##'. AND . The pre-ANSI preprocessor, i.e. use cc -Yp,/usr/lib The same problem with a similar solution exists on the HP. o Sun Old versions of cc(1), say <~1986, may require help for cfortran.h applications: . #pragma may not be understood, hence cfortran.h and cfortest.c may require sun> mv cfortran.h cftmp.h && grep -v "^#pragma" cfortran.h sun> mv cfortest.c cftmp.c && grep -v "^#pragma" cfortest.c . Old copies of math.h may not include the following from a newer math.h. [For an ancient math.h on a 386 or sparc, get similar from a new math.h.] #ifdef mc68000 /* 5 lines Copyright (c) 1988 by Sun Microsystems, Inc. */ #define FLOATFUNCTIONTYPE int #define RETURNFLOAT(x) return (*(int *)(&(x))) #define ASSIGNFLOAT(x,y) *(int *)(&x) = y #endif o CRAY, Sun, Apollo [pre 6.8 cc], VAX Ultrix and HP9000 Only FORTRAN routines with less than 15 arguments can be prototyped for C, since these compilers don't allow more than 31 arguments to a C macro. This can be overcome, [see Section IV], with access to any C compiler without this limitation, e.g. gcc, on ANY machine. o VAX Ultrix vcc (1) with f77 is not supported. Although: VAXUltrix> f77 -c cfortex.f VAXUltrix> vcc -o cfortest cfortest.c cfortex.o -lI77 -lU77 -lF77 && cfortest will link and run. However, the FORTRAN standard I/O is NOT merged with the stdin and stdout of C, and instead uses the files fort.6 and fort.5. For vcc, f77 can't drive the linking, as for gcc and cc, since vcc objects must be linked using lk (1). f77 -v doesn't tell much, and without VAX Ultrix manuals, the author can only wait for the info. required. fort (1) is not supported. Without VAX Ultrix manuals the author cannot convince vcc/gcc/cc and fort to generate names of routines and COMMON blocks that match at the linker, lk (1). i.e. vcc/gcc/cc prepend a single underscore to external references, e.g. NAME becomes _NAME, while fort does not modify the references. So ... either fort has prepend an underscore to external references, or vcc/gcc/cc have to generate unmodified names. man 1 fort mentions JBL, is JBL the only way? o VAX VMS C The compiler 'easily' exhausts its table space and generates: %CC-F-BUGCHECK, Compiler bug check during parser phase . Submit an SPR with a problem description. At line number 777 in DISK:[DIR]FILE.C;1. where the line given, '777', includes a call across C and FORTRAN via cfortran.h, usually with >7 arguments and/or very long argument expressions. This SPR can be staved off, with the simple modification to cfortran.h, such that the relevant CCALLSFSUBn (or CCALLSFFUNn or FCALLSCFUNn) is not cascaded up to CCALLSFSUB14, and instead has its own copy of the contents of CCALLSFSUB14. [If these instructions are not obvious after examining cfortran.h please contact the author.] [Thanks go to Mark Kyprianou (kyp@stsci.edu) for this solution.] o Mips compilers e.g. DECstations and SGI, require applications with a C main() and calls to GETARG(3F), i.e. FORTRAN routines returning the command line arguments, to use two macros as shown: : CF_DECLARE_GETARG; /* This must be external to all routines. */ : main(int argc, char *argv[]) { : CF_SET_GETARG(argc,argv); /* This must precede any calls to GETARG(3F). */ : } The macros are null and benign on all other systems. Sun's GETARG(3F) also doesn't work with a generic C main() and perhaps a workaround similar to the Mips' one exists. o Alpha/OSF Using the DEC Fortran and the DEC C compilers of DEC OSF/1 [RT] V1.2 (Rev. 10), Fortran, when called from C, has occasional trouble using a routine received as a dummy argument. e.g. In the following the Fortran routine 'e' will crash when it tries to use the C routine 'c' or the Fortran routine 'f'. The example works on other systems. C FORTRAN /* C */ integer function f() #include f = 2 int f_(); return int e_(int (*u)()); end int c(){ return 1;} integer function e(u) int d (int (*u)()) { return u();} integer u external u main() e=u() { /* Calls to d work. */ return printf("d (c ) returns %d.\n",d (c )); end printf("d (f_) returns %d.\n",d (f_)); /* Calls to e_ crash. */ printf("e_(c ) returns %d.\n",e_(c )); printf("e_(f_) returns %d.\n",e_(f_)); } Solutions to the problem are welcomed! A kludge which allows the above example to work correctly, requires an extra argument to be given when calling the dummy argument function. i.e. Replacing 'e=u()' by 'e=u(1)' allows the above example to work. o The FORTRAN routines are called using macro expansions, therefore the usual caveats for expressions in arguments apply. The expressions to the routines may be evaluated more than once, leading to lower performance and in the worst case bizarre bugs. o For those who wish to use cfortran.h in large applications. [See Section IV.] This release is intended to make it easy to get applications up and running. This implies that applications are not as efficient as they could be: - The current mechanism is inefficient if a single header file is used to describe a large library of FORTRAN functions. Code for a static wrapper fn. is generated in each piece of C source code for each FORTRAN function specified with the CCALLSFFUNn statement, irrespective of whether or not the function is ever called. - Code for several static utility routines internal to cfortran.h is placed into any source code which #includes cfortran.h. These routines should probably be in a library. i) Calling FORTRAN routines from C: -------------------------------- The FORTRAN routines are defined by one of the following two instructions: for a SUBROUTINE: /* PROTOCCALLSFSUBn is optional for C, but mandatory for C++. */ PROTOCCALLSFSUBn(ROUTINE_NAME,routine_name,argtype_1,...,argtype_n) #define Routine_name(argname_1,..,argname_n) \ CCALLSFSUBn(ROUTINE_NAME,routine_name,argtype_1,...,argtype_n, \ argname_1,..,argname_n) for a FUNCTION: PROTOCCALLSFFUNn(routine_type,ROUTINE_NAME,routine_name,argtype_1,...,argtype_n) #define Routine_name(argname_1,..,argname_n) \ CCALLSFFUNn(ROUTINE_NAME,routine_name,argtype_1,...,argtype_n, \ argname_1,..,argname_n) Where: 'n' = 0->14 [SUBROUTINE's ->27] (easily expanded in cfortran.h to > 14 [27]) is the number of arguments to the routine. Routine_name = C name of the routine (IN UPPER CASE LETTERS).[see 2.below] ROUTINE_NAME = FORTRAN name of the routine (IN UPPER CASE LETTERS). routine_name = FORTRAN name of the routine (IN lower case LETTERS). routine_type = the type of argument returned by FORTRAN functions. = BYTE, DOUBLE, FLOAT, INT, LOGICAL, LONG, SHORT, STRING, VOID. [Instead of VOID one would usually use CCALLSFSUBn. VOID forces a wrapper function to be used.] argtype_i = the type of argument passed to the FORTRAN routine and must be consistent in the definition and prototyping of the routine s.a. = BYTE, DOUBLE, FLOAT, INT, LOGICAL, LONG, SHORT, STRING. For vectors, i.e. 1 dim. arrays use = BYTEV, DOUBLEV, FLOATV, INTV, LOGICALV, LONGV, SHORTV, STRINGV, ZTRINGV. For vectors of vectors, i.e. 2 dim. arrays use = BYTEVV, DOUBLEVV, FLOATVV, INTVV, LOGICALVV, LONGVV, SHORTVV. For n-dim. arrays, 1<=n<=7 [7 is the maximum in Fortran 77], = BYTEV..nV's..V, DOUBLEV..V, FLOATV..V, INTV..V, LOGICALV..V, LONGV..V, SHORTV..V. N.B. Array dimensions and types are checked by the C compiler. For routines changing the values of an argument, the keyword is prepended by a 'P'. = PBYTE, PDOUBLE, PFLOAT, PINT, PLOGICAL, PLONG, PSHORT, PSTRING, PSTRINGV, PZTRINGV. For EXTERNAL procedures passed as arguments use = ROUTINE. For exceptional arguments which require no massaging to fit the argument passing mechanisms use = PVOID. The argument is cast and passed as (void *). Although PVOID could be used to describe all array arguments on most (all?) machines , it shouldn't be because the C compiler can no longer check the type and dimension of the array. argname_i = any valid unique C tag, but must be consistent in the definition as shown. Notes: 1. cfortran.h may be expanded to handle a more argument type. To suppport new arguments requiring complicated massaging when passed between Fortran and C, the user will have to understand cfortran.h and follow its code and mechanisms. To define types requiring little or no massaging when passed between Fortran and C, the pseudo argument type SIMPLE may be used. For a user defined type called 'newtype', the definitions required are: /* The following 7 lines are required verbatim. 'newtype' is the name of the new user defined argument type. */ #define newtype_cfV( T,A,B,F) SIMPLE_cfV(T,A,B,F) #define newtype_cfSEP(T, B) SIMPLE_cfSEP(T,B) #define newtype_cfINT(N,A,B,X,Y,Z) SIMPLE_cfINT(N,A,B,X,Y,Z) #define newtype_cfSTR(N,T,A,B,C,D,E) SIMPLE_cfSTR(N,T,A,B,C,D,E) #define newtype_cfCC( T,A,B) SIMPLE_cfCC(T,A,B) #define newtype_cfAA( T,A,B) newtype_cfB(T,A) /* Argument B not used. */ #define newtype_cfU( T,A) newtype_cfN(T,A) /* 'parameter_type(A)' is a declaration for 'A' and describes the type of the parameter expected by the Fortran function. This type will be used in the prototype for the function, if using ANSI C, and to declare the argument used by the intermediate function if calling a Fortran FUNCTION. Valid 'parameter_type(A)' include: int A void (*A)() double A[17] */ #define newtype_cfN( T,A) parameter_type(A) /* Argument T not used. */ /* Before any argument of the new type is passed to the Fortran routine, it may be massaged as given by 'massage(A)'. */ #define newtype_cfB( T,A) massage(A) /* Argument T not used. */ An example of a simple user defined type is given cfortex.f and cfortest.c. Two uses of SIMPLE user defined types are [don't show the 7 verbatim #defines]: /* Pass the address of a structure, using a type called PSTRUCT */ #define PSTRUCT_cfN( T,A) void *A #define PSTRUCT_cfB( T,A) (void *) &(A) /* Pass an integer by value, (not standard F77 ), using a type called INTVAL */ #define INTVAL_cfN( T,A) int A #define INTVAL_cfB( T,A) (A) [If using VAX VMS, surrounding the #defines with "#pragma (no)standard" allows the %CC-I-PARAMNOTUSED messages to be avoided.] Upgrades to cfortran.h try to be, and have been, backwards compatible. This compatibility cannot be offered to user defined types. SIMPLE user defined types are less of a risk since they require so little effort in their creation. If a user defined type is required in more than one C header file of interfaces to libraries of Fortran routines, good programming practice, and ease of code maintenance, suggests keeping any user defined type within a single file which is #included as required. To date, changes to the SIMPLE macros were introduced in versions 2.6, 3.0 and 3.2 of cfortran.h. 2. Routine_name is the name of the macro which the C programmer will use in order to call a FORTRAN routine. In theory Routine_name could be any valid and unique name, but in practice, the name of the FORTRAN routine in UPPER CASE works everywhere and would seem to be an obvious choice. 3. cfortran.h encourages the exact specification of the type and dimension of array parameters because it allows the C compiler to detect errors in the arguments when calling the routine. cfortran.h does not strictly require the exact specification since the argument is merely the address of the array and is passed on to the calling routine. Any array parameter could be declared as PVOID, but this circumvents C's compiletime ability to check the correctness of arguments and is therefore discouraged. Passing the address of these arguments implies that PBYTEV, PFLOATV, ... , PDOUBLEVV, ... don't exist in cfortran.h, since by default the routine and the calling code share the same array, i.e. the same values at the same memory location. These comments do NOT apply to arrays of (P)S/ZTRINGV. For these parameters, cfortran.h passes a massaged copy of the array to the routine. When the routine returns, S/ZTRINGV ignores the copy, while PS/ZTRINGV replaces the calling code's original array with copy, which may have been modified by the called routine. 4. (P)STRING(V): - STRING - If the argument is a fixed length character array, e.g. char ar[8];, the string is blank, ' ', padded on the right to fill out the array before being passed to the FORTRAN routine. The useful size of the string is the same in both languages, e.g. ar[8] is passed as character*7. If the argument is a pointer, the string cannot be blank padded, so the length is passed as strlen(argument). On return from the FORTRAN routine, pointer arguments are not disturbed, but arrays have the terminating '\0' replaced to its original position. i.e. The padding blanks are never visible to the C code. - PSTRING - The argument is massaged as with STRING before being passed to the FORTRAN routine. On return, the argument has all trailing blanks removed, regardless of whether the argument was a pointer or an array. - (P)STRINGV - Passes a 1- or 2-dimensional char array. e.g. char a[7],b[6][8]; STRINGV may thus also pass a string constant, e.g. "hiho". (P)STRINGV does NOT pass a pointer, e.g. char *, to either a 1- or a 2-dimensional array, since it cannot determine the array dimensions. A pointer can only be passed using (P)ZTRINGV. N.B. If a C routine receives a character array argument, e.g. char a[2][3], such an argument is actually a pointer and my thus not be passed by (P)STRINGV. Instead (P)ZTRINGV must be used. - STRINGV - The elements of the argument are copied into space malloc'd, and each element is padded with blanks. The useful size of each element is the same in both languages. Therefore char bb[6][8]; is equivalent to character*7 bb(6). On return from the routine the malloc'd space is simply released. - PSTRINGV - Since FORTRAN has no trailing '\0', elements in an array of strings are contiguous. Therefore each element of the C array is padded with blanks and strip out C's trailing '\0'. After returning from the routine, the trailing '\0' is reinserted and kill the trailing blanks in each element. - SUMMARY: STRING(V) arguments are blank padded during the call to the FORTRAN routine, but remain original in the C code. (P)STRINGV arguments are blank padded for the FORTRAN call, and after returning from FORTRAN trailing blanks are stripped off. 5. (P)ZTRINGV: - (P)ZTRINGV - is identical to (P)STRINGV, except that the dimensions of the array of strings is explicitly specified, which thus also allows a pointer to be passed. (P)ZTRINGV can thus pass a 1- or 2-dimensional char array, e.g. char b[6][8], or it can pass a pointer to such an array, e.g. char *p;. ZTRINGV may thus also pass a string constant, e.g. "hiho". If passing a 1-dimensional array, routine_name_ELEMS_j (see below) must be 1. [Users of (P)ZTRINGV should examine cfortest.c for examples.]: - (P)ZTRINGV must thus be used instead of (P)STRINGV whenever sizeof() can't be used to determine the dimensions of the array of string or strings. e.g. when calling FORTRAN from C with a char * received by C as an argument. - There is no (P)ZTRING type, since (P)ZTRINGV can pass a 1-dimensional array or a pointer to such an array, e.g. char a[7], *b; If passing a 1-dimensional array, routine_name_ELEMS_j (see below) must be 1. - To specify the numbers of elements, routine_name_ELEMS_j and routine_name_ELEMLEN_j must be defined as shown below before interfacing the routine with CCALLSFSUBn, PROTOCCALLSFFUNn, etc. #define routine_name_ELEMS_j ZTRINGV_ARGS(k) [..ARGS for subroutines, ..ARGF for functions.] or #define routine_name_ELEMS_j ZTRINGV_NUM(l) Where: routine_name is as above. j [1-n], is the argument being specifying. k [1-n], the value of the k'th argument is the dynamic number of elements for argument j. The k'th argument must be of type BYTE, DOUBLE, FLOAT, INT, LONG or SHORT. l the number of elements for argument j. This must be an integer constant available at compile time. i.e. it is static. - Similarly to specify the useful length, [i.e. don't count C's trailing '\0',] of each element: #define routine_name_ELEMLEN_j ZTRINGV_ARGS(m) [..ARGS for subroutines, ..ARGF for functions.] or #define routine_name_ELEMLEN_j ZTRINGV_NUM(q) Where: m [1-n], as for k but this is the length of each element. q as for l but this is the length of each element. 6. ROUTINE The argument is an EXTERNAL procedure. When C passes a routine to Fortran, the language of the function must be specified as follows: [The case of some_*_function must be given as shown.] When C passes a C routine to a Fortran: FORTRAN_ROUTINE(arg1, .... , C_FUNCTION(SOME_C_FUNCTION,some_c_function), ...., argn); and similarly when C passes a Fortran routine to Fortran: FORTRAN_ROUTINE(arg1, .... , FORTRAN_FUNCTION(SOME_FORT_FUNCTION,some_fort_function), ...., argn); If fcallsc has been redefined; the same definition of fcallsc used when creating the wrapper for 'some_c_function' must also be defined when C_FUNCTION is used. See ii) 4. of this section for when and how to redefine fcallsc. ROUTINE was introduced with cfortran.h version 2.6. Earlier versions of cfortran.h used PVOID to pass external procedures as arguments. Using PVOID for this purpose is no longer recommended since it won't work 'as is' for apolloFortran, hpuxFortran800, AbsoftUNIXFortran, AbsoftProFortran. 7. CRAY only: In a given piece of source code, where FFUNC is any FORTRAN routine, FORTRAN_FUNCTION(FFUNC,ffunc) disallows a previous #define FFUNC(..) CCALLSFSUBn(FFUNC,ffunc,...) [ or CCALLSFFUNn] in order to make the UPPER CASE FFUNC callable from C. #define Ffunc(..) ... is OK though, as are obviously any other names. ii) Calling C routines from FORTRAN: -------------------------------- Each of the following two statements to export a C routine to FORTRAN create FORTRAN 'wrappers', written in C, which must be compiled and linked along with the original C routines and with the FORTRAN calling code. FORTRAN callable 'wrappers' may also be created for C macros. i.e. in this section, the term 'C function' may be replaced by 'C macro'. for C functions returning void: FCALLSCSUBn( Routine_name,ROUTINE_NAME,routine_name,argtype_1,...,argtype_n) for all other C functions: FCALLSCFUNn(routine_type,Routine_name,ROUTINE_NAME,routine_name,argtype_1,...,argtype_n) Where: 'n' = 0->27 (easily expanded to > 27) stands for the number of arguments to the routine. Routine_name = the C name of the routine. [see 9. below] ROUTINE_NAME = the FORTRAN name of the routine (IN UPPER CASE LETTERS). routine_name = the FORTRAN name of the routine (IN lower case LETTERS). routine_type = the type of argument returned by C functions. = BYTE, DOUBLE, FLOAT, INT, LOGICAL, LONG, SHORT, STRING, VOID. [Instead of VOID, FCALLSCSUBn is recommended.] argtype_i = the type of argument passed to the FORTRAN routine and must be consistent in the definition and prototyping of the routine = BYTE, DOUBLE, FLOAT, INT, LOGICAL, LONG, SHORT, STRING. For vectors, i.e. 1 dim. arrays use = BYTEV, DOUBLEV, FLOATV, INTV, LOGICALV, LONGV, SHORTV, STRINGV. For vectors of vectors, 2 dim. arrays use = BYTEVV, DOUBLEVV, FLOATVV, INTVV, LOGICALVV, LONGVV, SHORTVV. For n-dim. arrays use = BYTEV..nV's..V, DOUBLEV..V, FLOATV..V, INTV..V, LOGICALV..V, LONGV..V, SHORTV..V. For routines changing the values of an argument, the keyword is prepended by a 'P'. = PBYTE, PDOUBLE, PFLOAT, PINT, PLOGICAL, PLONG, PSHORT, PSTRING, PNSTRING, PPSTRING, PSTRINGV. For EXTERNAL procedures passed as arguments use = ROUTINE. For exceptional arguments which require no massaging to fit the argument passing mechanisms use = PVOID. The argument is cast and passed as (void *). Notes: 0. For Fortran calling C++ routines, C++ does NOT easily allow support for: STRINGV. BYTEVV, DOUBLEVV, FLOATVV, INTVV, LOGICALVV, LONGVV, SHORTVV. BYTEV..V, DOUBLEV..V, FLOATV..V, INTV..V, LOGICALV..V, LONGV..V, SHORTV..V. Though there are ways to get around this restriction, the restriction is not serious since these types are unlikely to be used as arguments for a C++ routine. 1. FCALLSCSUB/FUNn expect that the routine to be 'wrapped' has been properly prototyped, or at least declared. 2. cfortran.h may be expanded to handle a new argument type not already among the above. 3. cfortran.h encourages the exact specification of the type and dimension of array parameters because it allows the C compiler to detect errors in the arguments when declaring the routine using FCALLSCSUB/FUNn, assuming the routine to be 'wrapped' has been properly prototyped. cfortran.h does not strictly require the exact specification since the argument is merely the address of the array and is passed on to the calling routine. Any array parameter could be declared as PVOID, but this circumvents C's compiletime ability to check the correctness of arguments and is therefore discouraged. Passing the address of these arguments implies that PBYTEV, PFLOATV, ... , PDOUBLEVV, ... don't exist in cfortran.h, since by default the routine and the calling code share the same array, i.e. the same values at the same memory location. These comments do NOT apply to arrays of (P)STRINGV. For these parameters, cfortran.h passes a massaged copy of the array to the routine. When the routine returns, STRINGV ignores the copy, while PSTRINGV replaces the calling code's original array with copy, which may have been modified by the called routine. 4. (P(N))STRING arguments have any trailing blanks removed before being passed to C, the same holds true for each element in (P)STRINGV. Space is malloc'd in all cases big enough to hold the original string (elements) as well as C's terminating '\0'. i.e. The useful size of the string (elements) is the same in both languages. P(N)STRING(V) => the string (elements) will be copied from the malloc'd space back into the FORTRAN bytes. If one of the two escape mechanisms mentioned below for PNSTRING has been used, the copying back to FORTRAN is obviously not relevant. 5. (PN)STRING's, [NOT PSTRING's nor (P)STRINGV's,] behavior may be overridden in two cases. In both cases PNSTRING and STRING behave identically. a) If a (PN)STRING argument's first 4 bytes are all the NUL character, i.e. '\0\0\0\0' the NULL pointer is passed to the C routine. b) If the characters of a (PN)STRING argument contain at least one HEX-00, i.e. the NUL character, i.e. C strings' terminating '\0', the address of the string is simply passed to the C routine. i.e. The argument is treated in this case as it would be with PPSTRING, to which we refer the reader for more detail. Mechanism a) overrides b). Therefore, to use this mechanism to pass the NULL string, "", to C, the first character of the string must obviously be the NUL character, but of the first 4 characters in the string, at least one must not be HEX-00. Example: C FORTRAN /* C */ character*40 str #include "cfortran.h" C Set up a NULL as : void cs(char *s) {if (s) printf("%s.\n",s);} C i) 4 NUL characters. FCALLSCSUB1(cs,CS,cs,STRING) C ii) NULL pointer. character*4 NULL NULL = CHAR(0)//CHAR(0)//CHAR(0)//CHAR(0) data str/'just some string'/ C Passing the NULL pointer to cs. call cs(NULL) C Passing a copy of 'str' to cs. call cs(str) C Passing address of 'str' to cs. Trailing blanks NOT killed. str(40:) = NULL call cs(str) end Strings passed from Fortran to C via (PN)STRING must not have undefined contents, otherwise undefined behavior will result, since one of the above two escape mechanisms may occur depending on the contents of the string. This is not be a problem for STRING arguments, which are read-only in the C routine and hence must have a well defined value when being passed in. PNSTRING arguments require special care. Even if they are write-only in the C routine, PNSTRING's above two escape mechanisms require that the value of the argument be well defined when being passed in from Fortran to C. Therefore, unless one or both of PNSTRING's escape mechanisms are required, PSTRING should be used instead of PNSTRING. Prior to version 2.8, PSTRING did have the above two escape mechanisms, but they were removed from PSTRING to allow strings with undefined contents to be passed in. PNSTRING behaves like the old PSTRING. [Thanks go to Paul Dubois (dubios@icf.llnl.gov) for pointing out that PSTRING must allow for strings with undefined contents to be passed in.] Example: C FORTRAN /* C */ character*10 s,sn #include "cfortran.h" void ps(char *s) {strcpy(s,"hello");} C Can call ps with undef. s. FCALLSCSUB1(ps,PS,ps,PSTRING) call ps(s) FCALLSCSUB1(ps,PNS,pns,PNSTRING) print *,s,'=s' C Can't call pns with undef. s. C e.g. If first 4 bytes of s were C "\0\0\0\0", ps would try C to copy to NULL because C of PNSTRING mechanism. sn = "" call pns(sn) print *,sn,'=sn' end 6. PPSTRING The address of the string argument is simply passed to the C routine. Therefore the C routine and the FORTRAN calling code share the same string at the same memory location. If the C routine modifies the string, the string will also be modified for the FORTRAN calling code. The user is responsible for negociating the differences in representation of a string in Fortran and in C, i.e. the differences are not automatically resolved as they are for (P(N)STRING(V). This mechanism is provided for two reasons: - Some C routines require the string to exist at the given memory location, after the C routine has exited. Recall that for the usual (P(N)STRING(V) mechanism, a copy of the FORTRAN string is given to the C routine, and this copy ceases to exist after returning to the FORTRAN calling code. - This mechanism can save runtime CPU cycles over (P(N)STRING(V), since it does not perform their malloc, copy and kill trailing blanks of the string to be passed. Only in a small minority of cases does the potential benefit of the saved CPU cycles outweigh the programming effort required to manually resolve the differences in representation of a string in Fortran and in C. For arguments passed via PPSTRING, the argument passed may also be an array of strings. 7. ROUTINE ANSI C requires that the type of the value returned by the routine be known, For all ROUTINE arguments passed from Fortran to C, the type of ROUTINE is specified by defining a cast as follows: #undef ROUTINE_j #define ROUTINE_j (cast) where: j [1-n], is the argument being specifying. (cast) is a cast matching that of the argument expected by the C function protoytpe for which a wrapper is being defined. e.g. To create a Fortran wrapper for qsort(3C): #undef ROUTINE_4 #define ROUTINE_4 (int (*)(void *,void *)) FCALLSCSUB4(qsort,FQSORT,fqsort,PVOID,INT,INT,ROUTINE) In order to maintain backward compatibility, cfortran.h defines a generic cast for ROUTINE_1, ROUTINE_2, ..., ROUTINE_27. The user's definition is therefore strictly required only for DEC C, which at the moment is the only compiler which insists on the correct cast for pointers to functions. When using the ROUTINE argument inside some Fortran code: - it is difficult to pass a C routine as the parameter, since in many Fortran implementations, Fortran has no access to the normal C namespace. e.g. For most UNIX, Fortran implicitly only has access to C routines ending in _. If the calling Fortran code receives the routine as a parameter it can of course easily pass it along. - if a Fortran routine is passed directly as the parameter, the called C routine must call the parameter routine using the Fortran argument passing conventions. - if a Fortran routine is to be passed as the parameter, but if Fortran can be made to pass a C routine as the parameter, then it may be best to pass a C-callable wrapper for the Fortran routine. The called C routine is thus spared all Fortran argument passing conventions. cfortran.h can be used to create such a C-callable wrapper to the parameter Fortran routine. ONLY PowerStationFortran: This Fortran provides no easy way to pass a Fortran routine as an argument to a C routine. The problem arises because in Fortran the stack is cleared by the called routine, while in C/C++ it is cleared by the caller. The C/C++ stack clearing behavior can be changed to that of Fortran by using stdcall__ in the function prototype. The stdcall__ cannot be applied in this case since the called C routine expects the ROUTINE parameter to be a C routine and does not know that it should apply stdcall__. In principle the cfortran.h generated Fortran callable wrapper for the called C routine should be able to massage the ROUTINE argument such that stdcall__ is performed, but it is not yet known how this could be easily done. 8. THE FOLLOWING INSTRUCTIONS ARE NOT REQUIRED FOR VAX VMS ------------ (P)STRINGV information [NOT required for VAX VMS]: cfortran.h cannot convert the FORTRAN vector of STRINGS to the required C vector of STRINGS without explicitly knowing the number of elements in the vector. The application must do one of the following for each (P)STRINGV argument in a routine before that routine's FCALLSCFUNn/SUBn is called: #define routine_name_STRV_Ai NUM_ELEMS(j) or #define routine_name_STRV_Ai NUM_ELEM_ARG(k) or #define routine_name_STRV_Ai TERM_CHARS(l,m) where: routine_name is as above. i [i=1->n.] specifies the argument number of a STRING VECTOR. j would specify a fixed number of elements. k [k=1->n. k!=i] would specify an integer argument which specifies the number of elements. l [char] the terminating character at the beginning of an element, indicating to cfortran.h that the preceding elements in the vector are the valid ones. m [m=1-...] the number of terminating characters required to appear at the beginning of the terminating string element. The terminating element is NOT passed on to the C routine. e.g. #define ce_STRV_A1 TERM_CHARS(' ',2) FCALLSCSUB1(ce,CE,ce,STRINGV) cfortran.h will pass on all elements, in the 1st and only argument to the C routine ce, of the STRING VECTOR until, but not including, the first string element beginning with 2 blank, ' ', characters. 9. INSTRUCTIONS REQUIRED ONLY FOR FORTRAN COMPILERS WHICH GENERATE ------------- ROUTINE NAMES WHICH ARE UNDISTINGUISHABLE FROM C ROUTINE NAMES i.e. VAX VMS AbsoftUNIXFortran (AbsoftProFortran ok, since it uses Uppercase names.) HP9000 if not using the +ppu option of f77 IBM RS/6000 if not using the -qextname option of xlf Call them the same_namespace compilers. FCALLSCSUBn(...) and FCALLSCFUNn(...), when compiled, are expanded into 'wrapper' functions, so called because they wrap around the original C functions and interface the format of the original C functions' arguments and return values with the format of the FORTRAN call. Ideally one wants to be able to call the C routine from FORTRAN using the same name as the original C name. This is not a problem for FORTRAN compilers which append an underscore, '_', to the names of routines, since the original C routine has the name 'name', and the FORTRAN wrapper is called 'name_'. Similarly, if the FORTRAN compiler generates upper case names for routines, the original C routine 'name' can have a wrapper called 'NAME', [Assuming the C routine name is not in upper case.] For these compilers, e.g. Mips, CRAY, IBM RS/6000 'xlf -qextname', HP-UX 'f77 +ppu', the naming of the wrappers is done automatically. For same_namespace compilers things are not as simple, but cfortran.h tries to provide tools and guidelines to minimize the costs involved in meeting their constraints. The following two options can provide same_namespace compilers with distinct names for the wrapper and the original C function. These compilers are flagged by cfortran.h with the CF_SAME_NAMESPACE constant, so that the change in the C name occurs only when required. For the remainder of the discussion, routine names generated by FORTRAN compilers are referred to in lower case, these names should be read as upper case for the appropriate compilers. HP9000: (When f77 +ppu is not used.) f77 has a -U option which forces uppercase external names to be generated. Unfortunately, cc does not handle recursive macros. Hence, if one wished to use -U for separate C and FORTRAN namespaces, one would have to adopt a different convention of naming the macros which allow C to call FORTRAN subroutines. (Functions are not a problem.) The macros are currently the uppercase of the original FORTRAN name, and would have to be changed to lower case or mixed case, or to a different name. (Lower case would of course cause conflicts on many other machines.) Therefore, it is suggested that f77 -U not be used, and instead that Option a) or Option b) outlined below be used. VAX/VMS: For the name used by FORTRAN in calling a C routine to be the same as that of the C routine, the source code of the C routine is required. A preprocessor directive can then force the C compiler to generate a different name for the C routine. e.g. #if defined(vms) #define name name_ #endif void name() {printf("name: was called.\n");} FCALLSCSUB0(name,NAME,name) In the above, the C compiler generates the original routine with the name 'name_' and a wrapper called 'NAME'. This assumes that the name of the routine, as seen by the C programmer, is not in upper case. The VAX VMS linker is not case sensitive, allowing cfortran.h to export the upper case name as the wrapper, which then doesn't conflict with the routine name in C. Since the IBM, HP and AbsoftUNIXFortran platforms have case sensitive linkers this technique is not available to them. The above technique is required even if the C name is in mixed case, see Option a) for the other compilers, but is obviously not required when Option b) is used. Option a) Mixed Case names for the C routines to be called by FORTRAN. If the original C routines have mixed case names, there are no name space conflicts. Nevertheless for VAX/VMS, the technique outlined above must also used. Option b) Modifying the names of C routines when used by FORTRAN: The more robust naming mechanism, which guarantees portability to all machines, 'renames' C routines when called by FORTRAN. Indeed, one must change the names on same_namespace compilers when FORTRAN calls C routines for which the source is unavailable. [Even when the source is available, renaming may be preferable to Option a) for large libraries of C routines.] Obviously, if done for a single type of machine, it must be done for all machines since the names of routines used in FORTRAN code cannot be easily redefined for different machines. The simplest way to achieve this end is to do explicitly give the modified FORTRAN name in the FCALLSCSUBn(...) and FCALLSCFUNn(...) declarations. e.g. FCALLSCSUB0(name,CFNAME,cfname) This allows FORTRAN to call the C routine 'name' as 'cfname'. Any name can of course be used for a given routine when it is called from FORTRAN, although this is discouraged due to the confusion it is sure to cause. e.g. Bizarre, but valid and allowing C's 'call_back' routine to be called from FORTRAN as 'abcd': FCALLSCSUB0(call_back,ABCD,abcd) cfortran.h also provides preprocessor directives for a systematic 'renaming' of the C routines when they are called from FORTRAN. This is done by redefining the fcallsc macro before the FCALLSCSUB/FUN/n declarations as follows: #undef fcallsc #define fcallsc(UN,LN) preface_fcallsc(CF,cf,UN,LN) FCALLSCSUB0(hello,HELLO,hello) Will cause C's routine 'hello' to be known in FORTRAN as 'cfhello'. Similarly all subsequent FCALLSCSUB/FUN/n declarations will generate wrappers to allow FORTRAN to call C with the C routine's name prefaced by 'cf'. The following has the same effect, with subsequent FCALLSCSUB/FUN/n's appending the modifier to the original C routines name. #undef fcallsc #define fcallsc(UN,LN) append_fcallsc(Y,y,UN,LN) FCALLSCSUB0(Xroutine,ROUTINE,routine) Hence, C's Xroutine is called from FORTRAN as: CALL XROUTINEY() The original behavior of FCALLSCSUB/FUN/n, where FORTRAN routine names are left identical to those of C, is returned using: #undef fcallsc #define fcallsc(UN,LN) orig_fcallsc(UN,LN) In C, when passing a C routine, i.e. its wrapper, as an argument to a FORTRAN routine, the FORTRAN name declared is used and the correct fcallsc must be in effect. E.g. Passing 'name' and 'routine' of the above examples to the FORTRAN routines, FT1 and FT2, respectively: /* This might not be needed if fcallsc is already orig_fcallsc. */ #undef fcallsc #define fcallsc(UN,LN) orig_fcallsc(UN,LN) FT1(C_FUNCTION(CFNAME,cfname)); #undef fcallsc #define fcallsc(UN,LN) append_fcallsc(Y,y,UN,LN) FT1(C_FUNCTION(XROUTINE,xroutine)); If the names of C routines are modified when used by FORTRAN, fcallsc would usually be defined once in a header_file.h for the application. This definition would then be used and be valid for the entire application and fcallsc would at no point need to be redefined. ONCE AGAIN: THE DEFINITIONS, INSTRUCTIONS, DECLARATIONS AND DIFFICULTIES DESCRIBED HERE, NOTE 9. of II ii), APPLY ONLY FOR VAX VMS, IBM RS/6000 WITHOUT THE -qextname OPTION FOR xlf, OR HP-UX WITHOUT THE +ppu OPTION FOR f77 AbsoftUNIXFortran AND APPLY ONLY WHEN CREATING WRAPPERS WHICH ENABLE FORTRAN TO CALL C ROUTINES. iii) Using C to manipulate FORTRAN COMMON BLOCKS: ------------------------------------------------------- FORTRAN common blocks are set up with the following three constructs: 1. #define Common_block_name COMMON_BLOCK(COMMON_BLOCK_NAME,common_block_name) Common_block_name is in UPPER CASE. COMMON_BLOCK_NAME is in UPPER CASE. common_block_name is in lower case. [Common_block_name actually follows the same 'rules' as Routine_name in Note 2. of II i).] This construct exists to ensure that C code accessing the common block is machine independent. 2. COMMON_BLOCK_DEF(TYPEDEF_OF_STRUCT, Common_block_name); where typedef { ... } TYPEDEF_OF_STRUCT; declares the structure which maps on to the common block. The #define of Common_block_name must come before the use of COMMON_BLOCK_DEF. 3. In exactly one of the C source files, storage should be set aside for the common block with the definition: TYPEDEF_OF_STRUCT Common_block_name; The above definition may have to be omitted on some machines for a common block which is initialized by Fortran BLOCK DATA or is declared with a smaller size in the C routines than in the Fortran routines. The rules for common blocks are not well defined when linking/loading a mixture of C and Fortran, but the following information may help resolve problems. From the 2nd or ANSI ed. of K&R C, p.31, last paragraph: i) An external variable must be defined, exactly once, outside of any function; this sets aside storage for it. ii) The variable must also be declared in each function that wants to access it; ... The declaration ... may be implicit from context. In Fortran, every routine says 'common /bar/ foo', i.e. part ii) of the above, but there's no part i) requirement. cc/ld on some machines don't require i) either. Therefore, when handling Fortran, and sometimes C, the loader/linker must automagically set aside storage for common blocks. Some loaders, including at least one for the CRAY, turn off the 'automagically set aside storage' capability for Fortran common blocks, if any C object declares that common block. Therefore, C code should define, i.e. set aside storage, for the the common block as shown above. e.g. C Fortran common /fcb/ v,w,x character *(13) v, w(4), x(3,2) /* C */ typedef struct { char v[13],w[4][13],x[2][3][13]; } FCB_DEF; #define Fcb COMMON_BLOCK(FCB,fcb) COMMON_BLOCK_DEF(FCB_DEF,Fcb); FCB_DEF Fcb; /* Definition, which sets aside storage for Fcb, */ /* may appear in at most one C source file. */ C programs can place a string (or a multidimensional array of strings) into a FORTRAN common block using the following call: C2FCBSTR( CSTR, FSTR,DIMENSIONS); where: CSTR is a pointer to the first element of C's copy of the string (array). The C code must use a duplicate of, not the original, common block string, because the FORTRAN common block does not allocate space for C strings' terminating '\0'. FSTR is a pointer to the first element of the string (array) in the common block. DIMENSIONS is the number of dimensions of string array. e.g. char a[10] has DIMENSIONS=0. char aa[10][17] has DIMENSIONS=1. etc... C2FCBSTR will copy the string (array) from CSTR to FSTR, padding with blanks, ' ', the trailing characters as required. C2FCBSTR uses DIMENSIONS and FSTR to determine the lengths of the individual string elements and the total number of elements in the string array. Note that: - the number of string elements in CSTR and FSTR are identical. - for arrays of strings, the useful lengths of strings in CSTR and FSTR must be the same. i.e. CSTR elements each have 1 extra character to accommodate the terminating '\0'. - On most non-ANSI compilers, the DIMENSION argument cannot be prepended by any blanks. FCB2CSTR( FSTR, CSTR,DIMENSIONS) is the inverse of C2FCBSTR, and shares the same arguments and caveats. FCB2CSTR copies each string element of FSTR to CSTR, minus FORTRAN strings' trailing blanks. cfortran.h USERS ARE STRONGLY URGED TO EXAMINE THE COMMON BLOCK EXAMPLES IN cfortest.c AND cfortex.f. The use of strings in common blocks is demonstrated, along with a suggested way for C to imitate FORTRAN EQUIVALENCE'd variables. ===> USERS OF CFORTRAN.H NEED READ NO FURTHER <=== III Some Musings ---------------- cfortran.h is simple enough to be used by the most basic of applications, i.e. making a single C/FORTRAN routine available to the FORTRAN/C programmers. Yet cfortran.h is powerful enough to easily make entire C/FORTRAN libraries available to FORTRAN/C programmers. cfortran.h is the ideal tool for FORTRAN libraries which are being (re)written in C, but are to (continue to) support FORTRAN users. It allows the routines to be written in 'natural C', without having to consider the FORTRAN argument passing mechanisms of any machine. It also allows C code accessing these rewritten routines, to use the C entry point. Without cfortran.h, one risks the perverse practice of C code calling a C function using FORTRAN argument passing mechanisms! Perhaps the philosophy and mechanisms of cfortran.h could be used and extended to create other language bridges such as ADAFORTRAN, CPASCAL, COCCAM, etc. The code generation machinery inside cfortran.h, i.e. the global structure is quite good, being clean and workable as seen by its ability to meet the needs and constraints of many different compilers. Though the individual instructions of the A..., C..., T..., R... and K... tables deserve to be cleaned up. IV Getting Serious with cfortran.h ----------------------------------- cfortran.h is set up to be as simple as possible for the casual user. While this ease of use will always be present, 'hooks', i.e. preprocessor directives, are required in cfortran.h so that some of the following 'inefficiencies' can be eliminated if they cause difficulties: o cfortran.h contains a few small routines for string manipulation. These routines are declared static and are included and compiled in all source code which uses cfortran.h. Hooks should be provided in cfortran.h to create an object file of these routines, allowing cfortran.h to merely prototypes these routines in the application source code. This is the only 'problem' which afflicts both halves of cfortran.h. The remaining discussion refers to the C calls FORTRAN half only. o Similar to the above routines, cfortran.h generates code for a 'wrapper' routine for each FUNCTION exported from FORTRAN. Again cfortran.h needs preprocessor directives to create a single object file of these routines, and to merely prototype them in the applications. o Libraries often contain hundreds of routines. While the preprocessor makes quick work of generating the required interface code from cfortran.h and the application.h's, it may be convenient for very large stable libraries to have final_application.h's which already contain the interface code, i.e. these final_application.h's would not require cfortran.h. [The convenience can be imagined for the VAX VMS CC compiler which has a fixed amount of memory for preprocessor directives. Not requiring cfortran.h, with its hundreds of directives, could help prevent this compiler from choking on its internal limits quite so often.] With a similar goal in mind, cfortran.h defines 100's of preprocessor directives. There is always the potential that these will clash with other tags in the users code, so final_applications.h, which don't require cfortran.h, also provide the solution. In the same vein, routines with more than 14 arguments can not be interfaced by cfortran.h with compilers which limit C macros to 31 arguments. To resolve this difficulty, final_application.h's can be created on a compiler without this limitation. Therefore, new machinery is required to do: application.h + cfortran.h => final_application.h The following example may help clarify the means and ends: If the following definition of the HBOOK1 routine, the /*commented_out_part*/, is passed through the preprocessor [perhaps #undefing and #defining preprocessor constants if creating an application.h for compiler other than that of the preprocessor being used, e.g. cpp -Umips -DCRAY ... ] : #include "cfortran.h" PROTOCCALLSFSUB6(HBOOK1,hbook1,INT,STRING,INT,FLOAT,FLOAT,FLOAT) /*#define HBOOK1(ID,CHTITLE,NX,XMI,XMA,VMX) \*/ CCALLSFSUB6(HBOOK1,hbook1,INT,STRING,INT,FLOAT,FLOAT,FLOAT, \ ID,CHTITLE,NX,XMI,XMA,VMX) A function prototype is produced by the PROTOCCALLSFSUB6(...). Interface code is produced, based on the 'variables', ID,CHTITLE,NX,XMI,XMA,VMX, which will correctly massage a HBOOK1 call. Therefore, adding the #define line: 'prototype code' #define HBOOK1(ID,CHTITLE,NX,XMI,XMA,VMX) \ 'interface code'(ID,CHTITLE,NX,XMI,XMA,VMX) which is placed into final_application.h. The only known limitation of the above method does not allow the 'variable' names to include B1,B2,...,B9,BA,BB,... Obviously the machinery to automatically generate final_applications.h from cfortran.h and applications.h needs more than just some preprocessor directives, but a fairly simple unix shell script should be sufficient. Any takers? V Machine Dependencies of cfortran.h ------------------------------------ Porting cfortran.h applications, e.g. the hbook.h and cstring.c mentioned above, to other machines is trivial since they are machine independent. Porting cfortran.h requires a solid knowledge of the new machines C preprocessor, and its FORTRAN argument passing mechanisms. Logically cfortran.h exists as two halves, a "C CALLS FORTRAN" and a "FORTRAN CALLS C" utility. In some cases it may be perfectly reasonable to port only 'one half' of cfortran.h onto a new system. The lucky programmer porting cfortran.h to a new machine, must discover the FORTRAN argument passing mechanisms. A safe starting point is to assume that variables and arrays are simply passed by reference, but nothing is guaranteed. Strings, and n-dimensional arrays of strings are a different story. It is doubtful that any systems do it quite like VAX VMS does it, so that a UNIX or f2c versions may provide an easier starting point. cfortran.h uses and abuses the preprocessor's ## operator. Although the ## operator does not exist in many compilers, many kludges do. cfortran.h uses /**/ with no space allowed between the slashes, '/', and the macros or tags to be concatenated. e.g. #define concat(a,b) a/**/b /* works*/ main() { concat(pri,ntf)("hello"); /* e.g. */ } N.B. On some compilers without ##, /**/ may also not work. The author may be able to offer alternate kludges. VI Bugs in vendors C compilers and other curiosities ---------------------------------------------------- 1. ULTRIX xxxxxx 4.3 1 RISC Condolences to long suffering ultrix users! DEC supplies a working C front end for alpha/OSF, but not for ultrix. From K&R ANSI C p. 231: ultrix> cat cat.c #define cat(x, y) x ## y #define xcat(x,y) cat(x,y) cat(cat(1,2),3) xcat(xcat(1,2),3) ultrix> cc -E cat.c 123 <---- Should be: cat(1,2)3 123 <---- Correct. ultrix> The problem for cfortran.h, preventing use of -std and -std1: ultrix> cat c.c #define cat(x, y) x ## y #define xcat(x,y) cat(x,y) #define AB(X) X+X #define C(E,F,G) cat(E,F)(G) #define X(E,F,G) xcat(E,F)(G) C(A,B,2) X(A,B,2) ultrix> cc -std1 -E c.c 2+2 AB (2) <---- ????????????? ultrix> ultrix> cc -std0 -E c.c 2+2 AB(2) <---- ????????????? ultrix> Due to further ultrix preprocessor problems, for all definitions of definitions with arguments, cfortran.h >= 3.0 includes the arguments and recommends the same, even though it is not required by ANSI C. e.g. Users are advised to do #define fcallsc(UN,LN) orig_fcallsc(UN,LN) instead of #define fcallsc orig_fcallsc since ultrix fails to properly preprocess the latter example. CRAY used to (still does?) occasionally trip up on this problem. 2. ConvexOS convex C210 11.0 convex In a program with a C main, output to LUN=6=* from Fortran goes into $pwd/fort.6 instead of stdout. Presumably, a magic incantation can be called from the C main in order to properly initialize the Fortran I/O. 3. SunOS 5.3 Generic_101318-69 sun4m sparc The default data and code alignments produced by cc, gcc and f77 are compatible. If deviating from the defaults, consistent alignment options must be used across all objects compiled by cc and f77. [Does gcc provide such options?] 4. SunOS 5.3 Generic_101318-69 sun4m sparc with cc: SC3.0.1 13 Jul 1994 or equivalently ULTRIX 4.4 0 RISC using cc -oldc are K&R C preprocessors that suffer from infinite loop macros, e.g. zedy03> cat src.c #include "cfortran.h" PROTOCCALLSFFUN1(INT,FREV,frev, INTV) #define FREV(A1) CCALLSFFUN1( FREV,frev, INTV, A1) /* To avoid the problem, deletete these ---^^^^--- spaces. */ main() { static int a[] = {1,2}; FREV(a); return EXIT_SUCCESS; } zedy03> cc -c -Xs -v -DMAX_PREPRO_ARGS=31 -D__CF__KnR src.c "src.c", line 4: FREV: actuals too long "src.c", line 4: FREV: actuals too long .... 3427 more lines of the same message "src.c", line 4: FREV: actuals too long cc : Fatal error in /usr/ccs/lib/cpp Segmentation fault (core dumped) 5. Older sun C compilers To link to f77 objects, older sun C compilers require the math.h macros: #define RETURNFLOAT(x) { union {double _d; float _f; } _kluge; \ _kluge._f = (x); return _kluge._d; } #define ASSIGNFLOAT(x,y) { union {double _d; float _f; } _kluge; \ _kluge._d = (y); x = _kluge._f; } Unfortunately, in at least some copies of the sun math.h, the semi-colon for 'float _f;' is left out, leading to compiler warnings. The solution is to correct math.h, or to change cfortran.h to #define RETURNFLOAT(x) and ASSIGNFLOAT(x,y) instead of including math.h. 6. gcc version 2.6.3 and probably all other versions as well Unlike all other C compilers supported by cfortran.h, 'gcc -traditional' promotes to double all functions returning float as demonstrated bu the following example. /* m.c */ #include int main() { FLOAT_FUNCTION d(); float f; f = d(); printf("%f\n",f); return 0; } /* d.c */ float d() { return -123.124; } burow[29] gcc -c -traditional d.c burow[30] gcc -DFLOAT_FUNCTION=float m.c d.o && a.out 0.000000 burow[31] gcc -DFLOAT_FUNCTION=double m.c d.o && a.out -123.124001 burow[32] Thus, 'gcc -traditional' is not supported by cfortran.h. Support would require the same RETURNFLOAT, etc. macro machinery present in old sun math.h, before sun gave up the same promotion. 7. CRAY At least some versions of the t3e and t3d C preprocessor are broken in the fashion described below. At least some versions of the t90 C preprocessor do not have this problem. On the CRAY, all Fortran names are converted to uppercase. Generally the uppercase name is also used for the macro interface created by cfortran.h. For example, in the following interface, EASY is both the name of the macro in the original C code and EASY is the name of the resulting function to be called. #define EASY(A,B) CCALLSFSUB2(EASY,easy, PINT, INTV, A, B) The fact that a macro called EASY() expands to a function called EASY() is not a problem for a working C preprocessor. From Kernighan and Ritchie, 2nd edition, p.230: In both kinds of macro, the replacement token sequence is repeatedly rescanned for more identifiers. However, once a given identifier has been replaced in a given expansion, it is not replaced if it turns up again during rescanning; instead it is left unchanged. Unfortunately, some CRAY preprocessors are broken and don't obey the above rule. A work-around is for the user to NOT use the uppercase name of the name of the macro interface provided by cfortran.h. For example: #define Easy(A,B) CCALLSFSUB2(EASY,easy, PINT, INTV, A, B) Luckily, the above work-around is not required since the following work-around within cfortran.h also circumvents the bug: /* (UN), not UN, is required in order to get around CRAY preprocessor bug.*/ #define CFC_(UN,LN) (UN) /* Uppercase FORTRAN symbols. */ Aside: The Visual C++ compiler is happy with UN, but barfs on (UN), so either (UN) causes nonstandard C/C++ or Visual C++ is broken. VII History and Acknowledgements -------------------------------- 1.0 - Supports VAX VMS using C 3.1 and FORTRAN 5.4. Oct. '90. 1.0 - Supports Silicon Graphics w. Mips Computer 2.0 f77 and cc. Feb. '91. [Port of C calls FORTRAN half only.] 1.1 - Supports Mips Computer System 2.0 f77 and cc. Mar. '91. [Runs on at least: Silicon Graphics IRIX 3.3.1 DECstations with Ultrix V4.1] 1.2 - Internals made simpler, smaller, faster, stronger. May '91. - Mips version works on IBM RS/6000, this is now called the unix version. 1.3 - UNIX and VAX VMS versions are merged into a single cfortran.h. July '91. - C can help manipulate (arrays of) strings in FORTRAN common blocks. - Dimensions of string arrays arguments can be explicit. - Supports Apollo DomainOS 10.2 (sys5.3) with f77 10.7 and cc 6.7. 2.0 - Improved code generation machinery creates K&R or ANSI C. Aug. '91. - Supports Sun, CRAY. f2c with vcc on VAX Ultrix. - cfortran.h macros now require routine and COMMON block names in both upper and lower case. No changes required to applications though. - PROTOCCALLSFSUBn is eliminated, with no loss to cfortran.h performance. - Improved tools and guidelines for naming C routines called by FORTRAN. 2.1 - LOGICAL correctly supported across all machines. Oct. '91. - Improved support for DOUBLE PRECISION on the CRAY. - HP9000 fully supported. - VAX Ultrix cc or gcc with f77 now supported. 2.2 - SHORT, i.e. INTEGER*2, and BYTE now supported. Dec. '91. - LOGICAL_STRICT introduced. More compact and robust internal tables. - typeV and typeVV for type = BYTE, DOUBLE, FLOAT, INT, LOGICAL, LONG,SHORT. - FORTRAN passing strings and NULL pointer to C routines improved. 2.3 - Extraneous arguments removed from many internal tables. May '92. - Introduce pseudo argument type SIMPLE for user defined types. - LynxOS using f2c supported. (Tested with LynxOS 2.0 386/AT.) 2.4 - Separation of internal C and Fortran compilation directives. Oct. '92. - f2c and NAG f90 supported on all machines. 2.5 - Minor mod.s to source and/or doc for HP9000, f2c, and NAG f90. Nov. '92. 2.6 - Support external procedures as arguments with type ROUTINE. Dec. '92. 2.7 - Support Alpha VMS. Support HP9000 f77 +ppu Jan. '93. - Support arrays with up to 7 dimensions. - Minor mod. of Fortran NULL to C via (P)STRING. - Specify the type of ROUTINE passed from Fortran to C [ANSI C requirement.] - Macros never receive a null parameter [RS/6000 requirement.] 2.8 - PSTRING for Fortran calls C no longer provides escape to pass April'93. NULL pointer nor to pass address of original string. PNSTRING introduced with old PSTRING's behavior. PPSTRING introduced to always pass original address of string. - Support Alpha/OSF. - Document that common blocks used in C should be declared AND defined. 3.0 - Automagic handling of ANSI ## versus K&R /**/ preprocessor op. March'95. - Less chance of name space collisions between cfortran.h and other codes. - SIMPLE macros, supporting user defined types, have changed names. 3.1 - Internal macro name _INT not used. Conflicted with IRIX 5.3. May '95. - SunOS, all versions, should work out of the box. - ZTRINGV_ARGS|F(k) may no longer point to a PDOUBLE or PFLOAT argument. - ConvexOS 11.0 supported. 3.2 - __hpux no longer needs to be restricted to MAX_PREPRO_ARGS=31. Oct. '95. - PSTRING bug fixed. - ZTRINGV_ARGS|F(k) may not point to a PBYTE,PINT,PLONG or PSHORT argument. - (P)ZTRINGV machinery improved. Should lead to fewer compiler warnings. (P)ZTRINGV no longer limits recursion or the nesting of routines. - SIMPLE macros, supporting user defined types, have changed slightly. 3.3 - Supports PowerStation Fortran with Visual C++. Nov. '95. - g77 should work using f2cFortran, though no changes made for it. - (PROTO)CCALLSFFUN10 extended to (PROTO)CCALLSFFUN14. - FCALLSCFUN10 and SUB10 extended to FCALLSCFUN14 and SUB14. 3.4 - C++ supported, Dec. '95. but it required the reintroduction of PROTOCCALLSFSUBn for users. - HP-UX f77 +800 supported. 3.5 - Absoft UNIX Fortran supported. Sept.'96. 3.6 - Minor corrections to cfortran.doc. Oct. '96. - Fixed bug for 15th argument. [Thanks to Tom Epperly at Aspen Tech.] - For AbsoftUNIXFortran, obey default of prepending _C to COMMON BLOCK name. - Fortran calling C with ROUTINE argument fixed and cleaned up. 3.7 - Circumvent IBM and HP "null argument" preprocessor warning. Oct. '96 3.8 - (P)STRINGV and (P)ZTRINGV can pass a 1- or 2-dim. char array. Feb. '97 (P)ZTRINGV thus effectively also provides (P)ZTRING. - (P)ZTRINGV accepts a (char *) pointer. 3.9 - Bug fixed for *VVVVV. May '97 - f2c: Work-around for strange underscore-dependent naming feature. - NEC SX-4 supported. - CRAY: LOGICAL conversion uses _btol and _ltob from CRAY's fortran.h. - CRAY: Avoid bug of some versions of the C preprocessor. - CRAY T3E: FORTRAN_REAL introduced. 4.0 - new/delete now used for C++. malloc/free still used for C. Jan. '98 - FALSE no longer is defined by cfortran.h . - Absoft Pro Fortran for MacOS supported. 4.1 - COMMA and COLON no longer are defined by cfortran.h . April'98 - Bug fixed when 10th arg. or beyond is a string. [Rob Lucchesi of NASA-Goddard pointed out this bug.] - CCALLSFSUB/FUN extended from 14 to 27 arguments. - Workaround SunOS CC 4.2 cast bug. [Thanks to Savrak SAR of CERN.] 4.2 - Portland Group needs -DpgiFortran . [Thank George Lai of NASA.] June '98 4.3 - (PROTO)CCALLSFSUB extended from 20 to 27 arguments. July '98 ['Support' implies these and more recent releases of the respective OS/compilers/linkers can be used with cfortran.h. Earlier releases may also work.] Acknowledgements: - CERN very generously sponsored a week in 1994 for me to work on cfortran.h. - M.L.Luvisetto (Istituto Nazionale Fisica Nucleare - Centro Nazionale Analisi Fotogrammi, Bologna, Italy) provided all the support for the port to the CRAY. Marisa's encouragement and enthusiasm was also much appreciated. - J.Bunn (CERN) supported the port to PowerStation Fortran with Visual C++. - Paul Schenk (UC Riverside, CERN PPE/OPAL) in June 1993 extended cfortran.h 2.7 to have C++ call Fortran. This was the starting point for full C++ in 3.4. - Glenn P.Davis of University Corp. for Atmospheric Research (UCAR) / Unidata supported the NEC SX-4 port and helped understand the CRAY. - Tony Goelz of Absoft Corporation ported cfortran.h to Absoft. - Though cfortran.h has been created in my 'copious' free time, I thank NSERC for their generous support of my grad. student and postdoc years. - Univ.Toronto, DESY, CERN and others have provided time on their computers. THIS PACKAGE, I.E. CFORTRAN.H, THIS DOCUMENT, AND THE CFORTRAN.H EXAMPLE PROGRAMS ARE PROPERTY OF THE AUTHOR WHO RESERVES ALL RIGHTS. THIS PACKAGE AND THE CODE IT PRODUCES MAY BE FREELY DISTRIBUTED WITHOUT FEES, SUBJECT TO THE FOLLOWING RESTRICTIONS: - YOU MUST ACCOMPANY ANY COPIES OR DISTRIBUTION WITH THIS (UNALTERED) NOTICE. - YOU MAY NOT RECEIVE MONEY FOR THE DISTRIBUTION OR FOR ITS MEDIA (E.G. TAPE, DISK, COMPUTER, PAPER.) - YOU MAY NOT PREVENT OTHERS FROM COPYING IT FREELY. - YOU MAY NOT DISTRIBUTE MODIFIED VERSIONS WITHOUT CLEARLY DOCUMENTING YOUR CHANGES AND NOTIFYING THE AUTHOR. - YOU MAY NOT MISREPRESENTED THE ORIGIN OF THIS SOFTWARE, EITHER BY EXPLICIT CLAIM OR BY OMISSION. THE INTENT OF THE ABOVE TERMS IS TO ENSURE THAT THE CFORTRAN.H PACKAGE NOT BE USED FOR PROFIT MAKING ACTIVITIES UNLESS SOME ROYALTY ARRANGEMENT IS ENTERED INTO WITH ITS AUTHOR. THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. THE AUTHOR IS NOT RESPONSIBLE FOR ANY SUPPORT OR SERVICE OF THE CFORTRAN.H PACKAGE. Burkhard Burow burow@desy.de P.S. Your comments and questions are welcomed and usually promptly answered. VAX VMS and Ultrix, Alpha, OSF, Silicon Graphics (SGI), DECstation, Mips RISC, Sun, CRAY, Convex, IBM RS/6000, Apollo DomainOS, HP, LynxOS, f2c, NAG, Absoft, NEC SX-4, PowerStation and Visual C++ are registered trademarks of their respective owners. ============================================================================ ADDITIONAL LICENSING INFORMATION (added by W D Pence on 4 October 2007) The author of cfortran has subsequently stated that cfortran.h may optionally be used and distributed under the GNU Library General Public License (LGPL). This statement was made in an email to Kevin McCarty, which is reproduced below: ---------------------------------------- Date: Tue, 22 Oct 2002 12:48:00 -0400 From: Burkhard D Steinmacher-burow To: Kevin B. McCarty Subject: Re: CFortran licensing question Kevin, [Just noticed that I didn't send this yesterady.] I have no time right now to read through licenses. IIRC, library GPL is fairly unrestrictive, so I'll choose that. So..... You may consider this e-mail as a notice that as an alternative to any other cfortran licenses, I hereby relase all versions and all parts of cfortran under the the Library GPL license. From among these licenses, the user is free to choose the license or licenses under which cfortran is used. Contact me if you'd like to be able to choose another license. Burkhard steinmac@us.ibm.com, (914)945-3756, Fax 3684, Tieline 862 ------------------------------------------ /* end: cfortran.doc */ cfitsio/docs/changes.txt0000644000225700000360000062415213246025103015113 0ustar cagordonlhea Log of Changes Made to CFITSIO Version 3.43 - March 2018 - Calls to https driver functions in cfileio.c need to be macro- protected by the HAVE_NET_SERVICES variable (as are the http and ftp driver function calls). Otherwise CMake builds on native Windows will fail since drvrnet.o is left empty. - Bug fix to ffmvec function. Should be resetting a local colptr variable after making a call to ffiblk (which can reallocate Ftpr-> tableptr). Originally reported by Willem van Straten. - Ignore any attempted request to not quantize an image before compressing it if the image has integer datatype pixels. - Improved error message construction throughout CFITSIO. Version 3.42 - August 2017 (Stand-alone release) - added https support to the collection of drivers handled in cfileio.c and drvrnet.c. This also handles the case where http transfers are rerouted to https. Note that this enhancement introduces a dependency on the libcurl development package. If this package is absent, CFITSIO will still build but will not have https capability. - made fix to imcomp_init_table function in imcompress.c. It now writes ZSIMPLE keyword only to a compressed image that will be placed in the primary header. - fix made to fits_get_col_display_width for case of a vector column of strings. Version 3.42 - March 2017 (Ftools release only) - in ftp_open_network and in ftp_file_exist, added code to repeatedly attempt to make a ftp connection if the ftp server does not respond to the first request. (some ftp servers don't appear to be 100% reliable). - in drvrnet.c added many calls to 'fclose' to close unneeded files, to avoid exceeding the maximum allowed number of files that can be open at once. - made substantial changes to the ftp_checkfile and http_checkfile routines to streamline the process of checking for the existence of a .gz or .Z compressed version of the file before opening the uncompressed file (when using http or ftp to open the file). - modified the code in ftp_open_network to send "\r\n" as end-of-line characters instead of just "\n". Some ftp servers (in particular, at heasarc.gsfc.nasa.gov) now require both characters, otherwise the network connection simply hangs. - modified the http_open_network routine to handle HTTP 301 or 302 redirects to a FTP url. This is needed to support the new configuration on the heasarc HTTP server which sometimes redirects http URLS to a ftp URL. Version 3.41 - November 2016 - The change made in version 3.40 to include strings.h caused problems on Windows (and other) platforms, so this change was backed out. The reason for including it was to define the strcasecmp and strcasencmp functions, so as an alternative, new equivalent functions called fits_strcasecmp and fits_strncasecmp have been added to CFITSIO.as a substitute. All the previous calls to the str[n]casecmp functions have been changed to now call fits_str[n]casecmp. In addition, the previously defined ngp_strcasecmp function (in grparser.c) has been removed and the calls to it have been changed to fits_strcasecmp. - The speed.c utility program was changed to correctly call the gettimeofday function with a NULL second arguement. Version 3.40 - October 2016 - fixed a bug when writing long string keywords with the CONTINUE convention which caused the CONTINUE'd strings to only be 16 characters long, instead of using up all the available space in the 80-character header record. - fixed a missing 'defined' keyword in fitsio.h. - replaced all calls to strtok (which is not threadsafe) with a new ffstrtok function which internally calls the threadsafe strtok_r function. One byproduct of this change is that must also be included in several of the C source code files. - modified the ffphbn function in putkey.c to support TFORM specifiers that use lowercase 'p' (instead of uppercase) when referring to a variable-length array column. - modified the lexical parser in eval.y and eval_y.c to support bit array columns (with TFORMn = 'X') with greater than 256 elements. Fix to bitcmp function: The internal 'stream' array is now allocated dynamically rather than statically fixed at size 256. This was failing when users attempted a row filtering of a bitcol that was wider than 256X. In bitlgte, bitand, and bitor functions, replaced static stream[256] array allocation with dynamic allocation. - modified the ffiter function in putcol.c to fix a problem which could cause the iterator function to incorrectly deal with null values. This only affected TLONG type columns in cases where sizeof(long) = 8, as well as for TLONGLONG type columns. - Fix made to uncompress2mem function in zcomprss.c for case where output uncompressed file expands to over the 2^32 (4Gb) limit. It now checks for this case at the start, and implements a 4Gb paging system through the output buffer. The problem was specifically caused by the d_stream.avail_out member being of 4-byte type uInt, and thus unable to handle any memory position values above 4Gb. - fixed a bug in fpackutil.c when using the -i2f (integer to float) option in fpack to compress an integer image that is scaled with non-default values for BSCALE and BZERO. This required an additional call to ffrhdu to reset the internal structures that describe the input FITS file. - modified fits_uncompress_table in imcompress.c to silently ignore the ZTILELEN keyword value if it larger than the number of rows in the table - Tweak strcasecmp/strncasecmp ifdefs to exclude 64-bit MINGW environment, as it does not lack those functions. (eval_l.c, fitsio2.h) - CMakeLists.txt: Set M_LIB to "" for MINGW build environment (in addition to MSVC). - Makefile.in: Add *.dSYM (non-XCode gcc leftovers on Macs) to clean list. Install libs by name rather than using a wildcard. - configure: Fix rpath token usage for XCode vs. non-XCode gcc on Macs. Version 3.39 - April 2016 - added 2 new routines suggested by Eric Mandel: ffhisto3 is similar to ffhisto2, except that it does not close the original file. fits_open_extlist is similar to fits_open_data except that it opens the FITS file and then moves to the first extension in the user-input list of 'interesting' extensions. - in ffpsvc and ffprec, it is necessary to treat CONTINUE, COMMENT, HISTORY, and blank name keywords as a special case which must be treated differently from other keywords because they have no value field and, by definition, have keyword names that are strictly limited in length. - added the Fortran wrapper routines for the 2 new string keyword reading routines (FTGSKY and FTGKSL), and documented all the routines in the FITSIO and CFITSIO users guides. - in ffinttyp, added explicit initialization of the input 'negative' argument to 0. - added new routine to return the length of the keyword value string: fits_get_key_strlen / ffgksl. This is primarily intended for use with string keywords that use the CONTINUE convention to continue the value over multiple header records, but this routine can be used to get the length of the value string for any type keyword. - added new routine to read string-valued keywords: fits_read_string_key / ffgsky This routine supports normal string keywords as well as long string keywords that use the CONTINUE convention. In many cases this routine may be more convenient to use then the older fits_read_key_longstr routine. - changed the prototype of fits_register_driver in fitsio2.h so that the pointer definition argument does not have the same name as the pointer itself (to work around a bug in the pgcc compiler). - added the missing FTDTDM fortran wrapper definition to f77_wrap3.c. - modified Makefile.in and configure.in to add LDFLAGS_BIN for task linker flages, which will be the same as LDFLAGS except on newer Mac OS X where an rpath flag is added. - modified Makefile.in to add a new "make utils" command which will build fpack, funpack, cookbook, fitscopy, imcopy, smem, speed, and testprog. These programs will be installed into $prfix/bin. - fixed a bug when attempting to modify the values in a variable-length bit ("X") column in a binary table. - reinstated the ability to write HIERARCH keywords that contain characters that would not be allowed in a normal 8-character keyword name, which had been disabled in the previous release. Version 3.38 - February 2016 - CRITICAL BUG FIX: The Intel 15 and 16 compilers (and potentially other compilers) may silently produce incorrect assembly code when compiling CFITSIO with the -O2 (or higher) optimization flag. In particular, this problem could cause CFITSIO to incorrectly read the values of arrays of 32-bit integers in a FITS file (i.e., images with BITPIX = 32 or table columns with TFORM = 'J') when the array is being read into a 'long' integer array in cases where the long array elements are 8 bytes long. One way to test if a particular system is affected by this problem is to compile CFITSIO V3.37 (or earlier) with optimization enabled, and then compare the output of the testprog.c program with the testprog.out file that is distributed with CFITSIO. If there are any differences in the files, then this system might be affected by this bug. Further tests should be performed to determine the exact cause. The root cause of this problem was traced to the fact that CFITSIO was aliasing an array of 32-bit integers and an array of 64-bit integers to the same memory location in order to obtain better data I/O efficiency when reading FITS files. When CFITSIO modified the values in these arrays, it was essential that the processing be done in strict sequential order from one end of the array to the other end, as was implicit in the C code algorithm. In this case, however, the compiler adopted certain loop optimization techniques that produced assembly code that violated this assumption. Technically, the CFITSIO code violates the "strict aliasing" assumption in ANSI C99, therefore the affected CFITSIO routines have been modified so that the aliasing of different data types to the same memory location no longer occurs. - fixed problem in configure and configure.in which caused the programs that are distributed with CFITSIO (most notably, fack and funpack) to be build without using any compiler optimization options, which could make them run more slowly than expected. - in imcompress.c, fixed bug where the rowspertile variable (declared as 'long') was mistakenly declared as a TLONGLONG variable in a call to fits_write_key. This could have caused the ZTILELEN keyword to be written incorrectly in the header of tile-compressed FITS tables on systems where sizeof(long) = 4. - in imcompress.c, implemented a new set of routines that safely convert shorter integer arrays into a longer integer arrays (e.g. short to int) where both arrays are aliased to the same memory location. These special routines were needed to guard against certain compiler optimization techniques that could produce incorrect code. - modified the 4 FnNoise5_(type) routines in quantize.c to correctly count the number of non-null pixels in the input array. Previously the count could be inaccurate if the image mainly consisted of null pixels. This could have caused certain floating point image tiles to be quantized during the image compression process, when in fact the tile did not satisfy all the criteria to be safely quantized. - in imcomp_copy_comp2img, added THEAP to the list of binary table keywords that may be present in the header of a compressed image and should not be copied to the uncompressed image header. - modified fits_copy_col to check that when copying a vector column, the vector length in the output column is the same as in the input column. Also modified the code to support the case where a column is being copied to an earlier position in the same table (which shifts the input column over 1 space). - added configure option (--with-bzip2) to support reading bzip2 compressed FITS files. This also required modifications to drvrmem.c and drvrfile.c This depends on having the bzlib library installed on the local machine. This patch was submitted by Dustin Lang. - replaced calls to 'memcpy' by 'memmove' in getcolb.c, getcold.c, getcole.c, and getcoli.c to support cases where the 2 memory areas overlap. (submitted by Aurelien Jarno) - modified the FITS keyword reading and writing routines to potentially support keywords with names longer than 8-characters. This was implemented in anticipation of a new experimental FITS convention which allows longer keyword names. - in fits_quantize_double in quantize.c, test if iseed == N_RANDOM, to avoid the (unlikely) possibility of overflowing the random number array bounds. (The corresponding fits_quantize_float routine already performed this test). - in the FnNoise5_short routine in quantize.c, change the first 'if' statement from "if (nx < 5)" to "if )nx < 9)", in order to support the (very rare) case where the tile is from 5 to 8 pixels wide. Also make the same change in the 3 other similar FnNoise5_* routines. - in the qtree_bitins64 routine in fits_hdecompress.c, must declare the plane_val variable as 'LONGLONG' instead of int. This bug could have caused integer overflow errors when uncompressing integer*4 images that had been compressed with the Hcompress algorithm, but only in cases where the image contains large regions of pixels whose values are close to the maximum integer*4 value of 2**31. - in fits_hcompress.c, call the calloc function instead of malloc when allocating the signbits array, to eliminate the need to individually set each byte to zero. - in the ffinit routine, and in a couple other routines that call ffinit, initialize the *fptr input parameter to NULL, even if the input status parameter value is greater than zero. This helps prevent errors later on if that fptr value is passed to ffclos. - modified ftcopy, in edithdu.c, to only abort if status > 0 rather than if status != 0. This had caused a problem in funpack in rare circumstances. - in imcompress.c changed all the calls to ffgdes to ffgdesll, to support compressed files greater than 2.1 GB in size. - fixed bug in ffeqtyll when it is called with 4th and 5th arguments set to NULL. - in fitsio.h, added the standard C++ guard around the declaration of the function fits_read_wcstab. (reported by Tammo Jan Dijkema, Astron.) - in fitsio.h, changed the prototype variable name "zero" to "zeroval" to avoid conflict in code that uses a literal definition of 'zero' to mean 0. - tweaked Makefile.in and configure.in to use LDFLAGS instead of CFLAGS for linking, use Macros for library name, and let fpack and funpack link with shared library. - modified an 'ifdef' statement in cfileio.c to test for '__GLIBC__' instead of 'linux' when initializing support for multi-threading. - modified ffeqtyll to return an effective column data type of TDOUBLE in the case of a 'K' (64-bit integer) column that has non-integer TSCALn or TZEROn keywords. - modified ffgcls (which returns the value in a column as a formatted string) so that when reading a 'K' (TLONGLONG) column it returns a long long integer value if the column is not scaled, but returns a double floating point value if the column has non-integer TSCALn or TZEROn values. - modified fitsio.h to correctly define "OFF_T long long" when using the Borland compiler - converted the 'end of line' characters in simplerng.c file to the unix style, instead of PC DOS. - updated CMakeLists.txt CMake build file which is primarily used to build CFITSIO on Windows machines. - modified fits_get_keyclass to recognize ZQUANTIZ and ZDITHER0 as TYP_CMPRS_KEY type keywords, i.e., keywords used in tile compressed image files. - added test to see if HAVE_UNISTD_H is defined, as a condition for including unistd.h in drvrfile.c drvrnet.c, drvrsmem.c, and group.c. - modified the CMakelist.txt file to fix several issues (primarily for building CFITSIO on Windows machines).. - fixed bug when reading tile-compressed images that were compressed with the IRAF PLIO algorithm. This bug did not affect fpack or funpack, but other software that reads the compressed image could be affected. The bug would cause the data values to be offset by 32768 from the actual pixel values. Version 3.37 - 3 June 2014 - replaced the random Gaussian and Poissonian distribution functions with new code written by Craig Markwardt derived from public domain C++ functions written by John D Cook. - patched fitsio2.h to support CFITSIO on AArch64 (64-bit ARM) architecture (both big and little endian). Supplied by Marcin Juszkiewicz and Sergio Pascual Ramirez, with further update by Michel Normand. - fixed bug in fpackutil.c that caused fpack to exit prematurely if the FZALGOR directive keyword was present in the HDU header. Version 3.36 - 6 December 2013 - added 9 Dec: small change to the fileseek function in drvrfile.c to support large files > 2 GB when building CFITSIO with MinGW on Windows - reorganized the CFITSIO code directory structure; added a 'docs' subdirectory for all the documentation, and a 'zlib' directory for the zlib/gzip file compression code. - made major changes to the compression code for FITS binary table to support all types of columns, including variable-length arrays. This code is mainly used via the fpack and funpack programs. - increased the number of FITS files that can be opened as one time to 1000, as defined by NMAXFILES in fitsio2.h. - made small configuration changes to configure.in, configure, fitsio.h, and drvrfile.c to support large files (64-bit file offsets} when using the mingw-w64 compiler (provided by Benjamin Gilbert). - made small change to fits_delete_file to more completely ignore any non-zero input status value. - fixed a logic error in a 'if' test when parsing a keyword name in the ngp_keyword_is_write function in grparser.c (provided by David Binderman). - when specifying the image compression parameters as part of the compressed image file name (using the "[compress]" qualifier after the name of the file), the quantization level value, if specified, was not being recognized by the CFITSIO compression routines. The image would always be compressed with the default quantization level of 4.0, regardless of what was specified. This affected the imcopy program, and potentially other user-generated application programs that used this method to specify the compression parameters. This bug did not affect fpack or funpack. This was fixed in the imcomp_get_compressed_image_par routine in the imcompress.c file. (reported by Sean Peters) - defined a new CFITS_API macro in fitsio.h which is used to export the public symbols when building CFITSIO on Windows systems with CMake. This works in conjunction with the new Windows CMake build procedure that is described in the README.win32 file. This complete revamping of the way CFITSIO is built under Windows now supports building 64-bit versions of the library. Thanks to Daniel Kaneider (Luminance HDR Team) for providing these new CMake build procedures. - modified the way that the low-level file_create routine works when running in the Hera environment to ensure that the FITS file that is created is within the allow user data disk area. - modified fits_get_compression_type so that it does not return an error if the HDU is a normal FITS IMAGE extension, and is not a tile-compressed image. - modified the low-level ffgcl* and ffpcl* routines to ensure that they never try ro read or write more than 2**31 bytes from disk at one time, as might happen with very large images, to avoid integer overflow errors. Fix kindly provided by Fred Gutsche at NanoFocus AG (www.nanofocus.de). - modified Makefile.in so that doing 'make distclean' does not delete new config.sub and config.guess files that were recently added. - adopted a patch from Debian in zcompress.c to "define" the values of GZBUFSIZE and BUFFINCR, instead of exporting the symbols as 'int's. Version 3.35 - 26 June 2013 (1st beta release was on 24 May) - fixed problem with the default tile size when compressing images with fpack using the Hcompress algorithm. - fixed returned value ("status" instead of "*status") - in imcompress.c, declared some arrays that are used to store the dimensions of the image from 'int' to 'long', to support very large images (at least on systems where sizeof(long) = 8), - modified the routines that convert a string value to a float or double to prevent them from returning a NaN or Inf value if the string is "NaN" or "Inf" (as can happen with gcc implementation of the strtod function). - removed/replaced the use of the assert() functions when locking or unlocking threads because they did not work correctly if NDEBUG is defined. - made modifications to the way the command-line file filters are parsed to 1) remove the 1024-character limit when specifying a column filter, 2) fixed a potential character buffer-overflow risk in fits_get_token, and 3) improved the parsing logic to remove any possible of confusing 2 slash characters ("//") in the string as the beginning of a comment string. - modified configure and Makefile.in so that when building CFITSIO as a shared library on linux or Mac platforms, it will use the SONAME convention to indicate whether each new release of the CFITSIO library is binary-compatible with the previous version. Application programs that link with the shared library will not need to be recompiled as long as the versions are compatible. In practice, this means that the shared library binary file that is created (on Linux systems) will have a name like 'libcfitsio.so.I.J.K', where I is the SONAME version number, J is the major CFITSIO version number (e.g. 3), and K is the minor CFITSIO version number (e.g., 34). Two link files will also be created such that libcfitsio.so -> libcfitsio.so.I, and libcfitsio.so.I -> libcfitsio.I.J.K Application programs will still run correctly with the new version of CFITSIO as long as the 'I' version number remains the same, but the applications will fail to run if the 'I' number changes, thus alerting the user that the application must be rebuilt. - fixed bug in fits_insert_col when computing the new table row width when inserting a '1Q' variable length array column. - modified the image compression routines so that the output compressed image (stored in a FITS binary table) uses the '1Q' variable length array format (instead of '1P') when the input file is larger than 4 GB. - added support for "compression directive" keywords which indicate how that HDU should be compressed (e.g., which compression algorithm to use, what tiling pattern to use, etc.). The values of these keywords will override the compression parameters that were specified on the command line when running the fpack FITS file compression program. - globally changed the variable and/or subroutine name "dither_offset" to "dither_seed" and "quantize_dither" to "quantize_method" so that the names more accurately reflects their purpose. - added support for a new SUBTRACTIVE_DITHER_2 method when compressing floating point images. The only difference with the previous method is that pixels with a value exactly equal to 0.0 will not be dithered, and instead will be exactly preserved when the image is compressed. - added support for an alias of "RICE_ONE" for "RICE_1" as the value of the ZCMPTYPE keyword, which gives the name of the image compression algorithm. This alias is used if the new SUBTRACTIVE_DITHER_2 option is used, to prevent old versions of funpack from creating a corrupted uncompressed image file. Only newer versions of funpack will recognize this alias and be able to uncompress the image. - made performance improvement to fits_read_compressed_img so that when reading a section of an compressed image that includes only every nth pixel in some dimension, it will only uncompressed a tile if there are actually any pixels of interest in that tile. - fixed several issues with the beta FITS binary table compression code that is used by fpack: added support for zero-length vector columns, made improvements to the output report when using the -T option in fpack, changed the default table compression method to 'Rice' instead of 'Best', and now writes the 'ZTILELEN' keyword to document the number of table rows in each tile. - fixed error in ffbinit in calculating the total length of the binary table extension if the THEAP keyword was used to override the default starting location of the heap. Version 3.34 - 20 March 2013 - modified configure and configure.in to support cross-compiled cfitsio as a static library for Windows on a Linux platform using MXE (http://mxe.cc) - a build environment for mingw32. (contributed by Niels Kristian Bech Jensen) - added conditional compilation statementsfor the mingw32 environment in drvrfile.c because mingw32 does not include the ftello and fseeko functions. (contributed by Niels Kristian Bech Jensen) - fixed a potential bug in ffcpcl (routine to copy a column from one table to another table) when dealing with the rare case of a '0X' column (zero length bit column). - fixed an issue in the routines that update or modify string-valued keyword values, as a result of the change to ffc2s in the previous release. These routines would exit with a 204 error status if the current value of the keyword to be updated or modified is null. - fixed typo in the previous modification that was intended to ignore numerical overflows in Hcompress when decompressing an image. - moved the 'startcol' static variable out of the ffgcnn routine and instead added it as a member of the 'FITSfile' structure that is defined in fitsio.h. This removes a possible race condition in ffgcnn in multi-threaded environments. Version 3.33 - 14 Feb 2013 - modified the imcomp_decompress_tile routine to ignore any numerical overflows that might occur when using Hcompress to decompress the image. If Hcompress is used in its 'lossy' mode, the uncompressed image pixel values may slightly exceed the range of an integer*2 variable. This is generally of no consequence, so we can safely ignore any overflows in this case and just clip the values to the legal range. - the default tiling pattern when writing a tile-compressed image has been changed. The old behavior was to compress the whole image as one single large tile. This is often not optimal when dealing with large images, so the new default behavior is to treat each row of the image as one tile. This is the same default behavior as in the standalone fpack program. The default tile size can be overridden by calling fits_set_tile_dim. - fixed bug that resulted in a corrupted output FITS image when attempting to write a float or double array of values to a tile-compressed integer data type image. CFITSIO does not support implicit data type conversion in this case and now correctly returns an appropriate error status. - modified ricecomp.c to define the nonzero_count lookup table as an external variable, rather then dynamically allocating it within the 3 routines that use it. This simplifies the code and eliminates the need for special thread locking and unlocking statements. (Thanks to Lars Kr. Lundin for this suggestion). - modified how the uncompressed size of a gzipped file is computed in the mem_compress_open routine in drvrmem.c. Since gzip only uses 4 bytes in the compressed file header to store the original file size, one may need to apply a modulo 2^32 byte correction in some cases. The logic here was modified to allow for corner cases (e.g., very small files, and when running on 32-bit platforms that do not support files larger than 2^31 bytes in size). - added new public routine to construct a 80 keyword record from the 3 input component strings, i.e, the keyword name string, the value string, and the comment string: fits_make_key/ffmkky. (This was already an undocumented internal routine in previous versions of CFITSIO). - modified ffc2s so that if the input keyword value string is a null string, then it will return a VALUE_UNDEFINED (204) status value. This makes it consistent with the behavior when attempting to read a null keyword (which has no value) as a logical or as a number (which also returns the 204 error). This should only affect cases where the header keyword does not have an equal sign followed by a space character in columns 9 and 10 of the header record. - Changed the "char *" parameter declarations to "const char *" in many of the routines (mainly the routines that modify or update keywords) to avoid compiler warnings or errors from C++ programs that tend to be more rigorous about using "const char *" when appropriate. - added support for caching uncompressed image tiles, so that the tile does not need to be uncompressed again if the application program wants to read more data from the same tile. This required changes to the main FITS file structure that is defined in fitsio.h, as well as changes to imcompress.c. - enhanced the previous modification to drvrfile.c to handle additional user cases when running in the HEASARC's Hera environment. Version 3.32 - Oct 2012 - fixed flaw in the way logical columns (TFORM = 'L') in binary tables were read which caused an illegal value of 1 in the column to be interpreted as a 'T' (TRUE) value. - extended the column filtering syntax in the CFITSIO file name parser to enable users and scripts to append new COMMENT or HISTORY keyword into the header of the filtered file (provided by Craig Markwardt). For example, fcopy "infile.fits[col #HISTORY='Processed on 2012-10-05']" outfile.fits will append this header keyword: "HISTORY Processed on 2012-10-05" - small change to the code that opens and reads an ASCII region file to return an error if the file is empty. - fixed obscure sign propagation error when attempting to read the uncompressed size of a gzipped FITS file. This resulted in a memory allocation error if the gzipped file had an uncompressed file size between 2^31 and 2^32 bytes. Fix supplied by Gudlaugur Johannesson (Stanford). Version 3.31 - 18 July 2012 - enhanced the CFITSIO column filtering syntax to allow the comma, in addition to the semi-colon, to be used to separate clauses, for example: [col X,Y;Z = max(X,Y)]. This was done because users are not allowed to enter the semi-colon character in the on-line Hera data processing system due to computer security concerns. - enhanced the CFITSIO extended filename syntax to allow specifying image compression parameters (e.g. '[compress Rice]') when opening an existing FITS file with write access. The specified compression parameters will be used by default if more images are appended to the existing file. - modified drvrfile.c to do additional file security checks when CFITSIO is running within the HEASARC's Hera software system. In this case CFITSIO will not allow FITS files to be created outside of the user's individual Hera data directory area. - fixed an issue in fpack and funpack on Windows machines, caused by the fact that the 'rename' function behaves differently on Windows in that it does not clobber an existing file, as it does on Unix platforms. - fixed bug in the way byte-swapping was being performed when writing integer*8 null values to an image or binary table column. - added the missing macro definition for fffree to fitsio.h. - modified the low level table read and write functions in getcol*.c and putcol*.c to remove the 32-bit limitation on the number of elements. These routines now support reading and writing more than 2**31 elements at one time. Thanks to Keh-Cheng Chu (Stanford U.) for the patch. - modified Makefile.in so that the shared libcfitsio.so is linked against pthreads and libm. Version 3.30 - 11 April 2012 Enhancements - Added new routine called fits_is_reentrant which returns 1 or 0 depending on whether or not CFITSIO was compiled with the -D_REENTRANT directive. This can be used to determine if it is safe to use CFITSIO in multi-threaded programs. - Implemented much faster byte-swapping algorithms in swapproc.c based on code provided by Julian Taylor at ESO, Garching. These routines significantly improve the FITS image read and write speed (by more than a factor of 2 in some cases) on little-endian machines (e.g., Linux and Microsoft Windows and Macs running on x86 CPUs) where byte-swapping is required when reading and writing data in FITS files. This has no effect on big-endian machines (e.g. Motorola CPUs and some IBM systems). Even faster byte-swapping performance can be achieved in some cases by invoking the new "--enable-sse2" or "--enable-ssse3" configure options when building CFITSIO on machines that have CPUs and compilers that support the SSE2 and SSSE3 machine instructions. - added additional support for implicit data type conversion in cases where the floating point image has been losslessly compressed with gzip. The pixels in these compressed images can now be read back as arrays of short, int, and long integers as well as single and double precision floating-point. - modified fitsio2.h and f77_wrap.h to recognize IBM System z mainframes by testing if __s390x__ or __s390__ is defined. - small change to ffgcrd in getkey.c so that it supports reading a blank keyword (e.g., a keyword whose name simply contains 8 space characters). Bug Fixes - fixed a bug in imcomp_decompress_tile that caused the tile-compressed image to be uncompressed incorrectly (even though the tile-compressed image itself was written correctly) under the following specific conditions: - the original FITS image has a "float" datatype (R*4) - one or more of the image tiles cannot be compressed using the standard quantization method and instead are losslessly compressed with gzip - the pixels in these tiles are not all equal to zero (this bug does affect tiles where all the pixels are equal to zero) - the program that is reading the compressed image uses CFITSIO's "implicit datatype conversion" feature to read the "float" image back into an array of "double" pixel values. If all these conditions are met, then the returned pixel values in the affected image tiles will be garbage, with values often ranging up to 10**34. Note that this bug does not affect the fpack/funpack programs, because funpack does not use CFITSIO's implicit datatype conversion feature when uncompressing the image. Version 3.29 - 2 December 2011 Enhancements - modified Makefile.in to allow configure to override the lib and include destination directories. - added (or restored actually) support for tile compression of 1-byte integer images in imcomp_compress_tile. Support for that data type was overlooked during recent updates to this routine. - modified the fits_get_token command-line parsing routine to perform more rigorous checks to determine if the token can be interpreted as a number or not. - made small modification to fpack.c to not allow the -i2f option (convert image from integer to floating point) with the "-g -q 0" option (do lossless gzip compression). It is more efficient to simply use the -g option alone. - made modifications to fitsio.h and drvrfile.c to support reading and writing large FITS files (> 2.1 GB) when building CFITSIO using Microsoft Visual C++ on Windows platforms. - added new WCS routine (ffgicsa) which returns the WCS keyword values for a particular WCS version ('A' - 'Z'). Bug Fixes - fixed a problem with multi-threaded apps that open/close FITS files simultaneously by putting mutex locks around the call to fits_already_open and in fits_clear_Fptr. - fixed a bug when using the 'regfilter' function to select a subset of the rows in a FITS table that have coordinates that lie within a specified spatial region on the sky. This bug only affects the rarely used panda (and epanda and bpanda) region shapes in which the region is defined by the intersection of an annulus and a pie-shaped wedge. The previous code (starting with version 3.181 of CFITSIO where support for the panda region was first introduced) only worked correctly if the 2 angles that define the wedge have values between -180 and +180. If not, then fewer rows than expected may have been selected from the table. - fixed the extended filename parser so that when creating a histogram by binning 2 table columns, if a keyword or column name is given as the weighting factor, then the output histogram image will have a floating point datatype, not the default integer datatype as is the case when no weight is specified (e.g. with a filename like "myfile.fits[bin x,y; weight_column]" - added fix to the code in imcompress.c to work around a problem with dereferencing the value of a pointer, in cases where the address of that pointer has not been defined (e.g., the nulval variable). - modified the byte shuffling algorithm in fits_shuffle_8bytes to work around a strange bug in the proprietary SunStudioExpress C compiler under OpenSolaris. - removed spurious messages on the CFITSIO error stack when opening a FITS file with FTP (in drvrnet.c); Version 3.28 - 12 May 2011 - added an enhancement to the tiled-image compression method when compressing floating-point image using the standard (lossy) quantization method. In cases where an image tile cannot be quantized, The floating-point pixel values will be losslessly compressed with gzip before writing them to the tile- compressed file. Previously, the uncompressed pixel values would have been written to the file, which obviously requires more disk space. - made significant internal changes to the structure of the tile compression and uncompression routines in imcompress.c to make them more modular and easier to maintain. - modified configure.in and configure to force it to build a Universal binary on Mac OS X. - modified the ffiter function in putcol.c to properly clean up allocated memory if an error occurs. - in quantize.c, when searching for the min and max values in a float array, initialize the max value to -FLT_MAX instead of FLT_MIN (and similarly for double array). Version 3.27 - 3 March 2011 Enhancements - added new routines fits_read_str and fits_delete_str which read or delete, respectively, a header keyword record that contains a specified character string. - added a new routine called fits_free_memory which frees the memory that fits_read_key_longstr allocated for the long string keyword value. - enhanced the ffmkky routine in fitscore.c to not put a space before the equals sign when writing long string-valued keywords using the ESO HIERARCH keyword convention, if that extra character is needed to fit the length of the keyword name + value string within the 80-character FITS keyword record. - made small change to fits_translate_keyword to support translation of blank keywords (where the name = 8 blank characters) - modified fpack so that it uses the minimum of the 2nd, 3rd, and 5th order MAD noise values when quantizing and compressing a floating point image. This is more conservative than just using the 3rd order MAD value alone. - added new routine imcomp_copy_prime2img to imcompress.c that is used by funpack to copy any keywords that may have been added to the primary array of the compressed image file (a null image) back into the header of the uncompressed image. - enhanced the fits_quantize_float and fits_quantize_double routines in quantize.c to also compress the tile if it is completely filled with null values. Previously, this type of tile would have been written to the output compressed image without any compression. - enhanced imcomp_decompress_tile to support implicit datatype conversion when reading a losslessly compressed (with gzip) real*4 image into an array of real*8 values. - in imcompress.c, removed possible attempt to free memory that had not been allocated. Version 3.26 - 30 December 2010 Enhancements - defined 2 new macros in fitsio.h: #define CFITSIO_MAJOR 3 #define CFITSIO_MINOR 26 These may be used within other macros to detect the CFITSIO version number at compile time. - modified group.c to initialize the output URL to a null string in fits_url2relurl. Also added more robust tests to see if 2 file pointers point to the same file. - enhanced the template keyword parsing code in grparser.c to support the 'D' exponent character in the ASCII representation of floating point keyword values (as in TVAL = 1.23D03). Previously, the parser would have written this keyword with a string value (TVAL = '1.23D03'). - modified the low-level routines that write a keyword record to a FITS header so that they silently replace any illegal characters (ASCII values less than 32 or greater than 126) with an ASCII space character. Previously, these routines would have returned with an error when encountering these illegal characters in the keyword record (most commonly tab, carriage return, and line feed characters). - made substantial internal changes to imcompress.c in preparation for possible future support for compression methods for FITS tables analogous to the tiled image compression method. - replaced all the source code in CFITSIO that was distributed under the GNU General Public License with freely available code. In particular, the gzip file compression and uncompression code was replaced by the zlib compression library. Thus, beginning with this version 3.26 of CFITSIO, other software applications may freely use CFITSIO without necessarily incurring any GNU licensing requirement. See the License.txt file for the CFITSIO licensing requirements. - added support for using cfitsio in different 'locales' which use a comma, not a period, as the decimal point character in ASCII representation of a floating point number (e.g., France). This affects how floating point keyword values and floating point numbers in ASCII tables are read and written with the 'printf' and 'strtod' functions. - added a new utility routine called fits_copy_rows/ffcprw that copies a specified range of rows from one table to another. - enhanced the test for illegal ASCII characters in a header (fftrec) to print out the name of the offending character (e.g TAB or Line Feed) as well as the Hex value of the character. - modified ffgtbc (in fitscore.c) to support nonstandard vector variable length array columns in binary tables (e.g. with TFORMn = 2000PE(500)'). - modified the configure file to add "-lm" when linking CFITSIO on Solaris machines. - added new routine, fits_get_inttype, to parse an integer keyword value string and return the minimum integer datatype (TBYTE, TSHORT, TLONG, TLONGLONG) required to store the integer value. - added new routine, fits_convert_hdr2str, which is similar to fits_hdr2str except that if the input HDU is a tile compressed image (stored in a binary table) then it will first convert that header back to that of a normal uncompressed FITS image before concatenating the header keyword records. - modified the file template reading routine (ngp_line_from_file in grparser.c) so that it ignores any carriage return characters (\r) in the line, that might be present, e.g. if the file was created on a Windows machine that uses \r\n as end of line characters. - modified the ffoptplt routine in cfileio.c to check if the PCOUNT keyword in the template file has a non-zero value, and if so, resets it to zero in the newly created file. Bug Fixes - fixed a bug when uncompressing floating-point images that contain Nan values on some 64-bit platforms. - fixed a bug when updating the value of the CRPIXn world coordinate system keywords when extracting a subimage from larger FITS image, using the extended CFITSIO syntax (e.g. myimage[1:500:2, 1:500:2]). This bug only affects cases where the pixel increment value is not equal to 1, and caused the coordinate grid to be shifted by between 0.25 pixels (in the case of a pixel increment of 2) and 0.5 pixels (for large pixel increment values). - fixed a potential string buffer overflow error in the ffmkls routine that modifies the value and comment strings in a keyword that uses the HEASARC long string keyword convention. - fixed a bug in imcompress.c that could cause programs to abort on 64-bit machines when using gzip to tile-compress images. Changed the declaration of clen in imcomp_compress_tile from int to size_t. Version 3.25 - 9 June 2010 - fixed bug that was introduced in version 3.13 that broke the ability to reverse an image section along the y-axis with an image section specifier like this: myimage.fits[*,-*]. This bug caused the output image to be filled with zeros. - fixed typo in the definition of the ftgprh Fortran wrapper routine in f77_wrap3.c. - modified the cfitsio.pc.in configuration file to make the lib path a variable instead of hard coding the path. The provides more flexibility for projects such as suse and fedora when building CFITSIO. - fixed bug in imcomp_compress_tile in imcompress.c which caused null pixel values to be written incorrectly in the rare case where the floating-point tile of pixels could not be quantized into integers. - modified imcompress.c to add a new specialized routine to uncompress an input image and then write it to a output image on a tile by tile basis. This appears to be faster than the old method of uncompressing the whole image into memory before writing it out. It also supports large images with more than 2**31 pixels. - made trivial changes to 2 statements in drvrfile.c to suppress nuisance compiler warnings. - some compilers define CLOCKS_PER_SEC as a double instead of an integer, so added an explicit integer type conversion to 2 statements in imcompress.c that used this macro. - removed debugging printf statements in drvrnet.c (15 July) Version 3.24 - 26 January 2010 - modified fits_translate_keywords so that it silently ignores any illegal ASCII characters in the value or comment fields of the input FITS file. Otherwise, fpack would abort without compressing input files that contained this minor violation of the FITS rules. - added support for Super H cpu in fitsio2.h - updated funpack to correctly handle the -S option, and to use a more robust algorithm for creating temporary output files. - modified the imcomp_compress_tile routine to support the NOCOMPRESS debugging option for real*4 images. Version 3.23 - 7 January 2010 - reduced the default value for the floating point image quantization parameter (q) from 16 to 4. This parameter is used when tile compressing floating point images. This change will increase the average compression ratio for floating point images from about 4.6 to about 6.5 without losing any significant information in the image. - enhanced the template keyword parsing routine to reject a header template string that only contains a sequence of dashes. - enhanced the ASCII region file reading routine to allow tabs as well as spaces between fields in the file. - got rid of bogus error message when calling fits_update_key_longstr - Made the error message more explicit when CFITSIO tries to write to a GZIP compressed file. Instead of just stating "cannot write to a READONLY file", it will say "cannot write to a GZIP compressed file". Version 3.22 - 28 October 2009 - added an option (in imcompress.c) to losslessly compress floating point images, rather than using the default integer scaling method. This option is almost never useful in practice for astronomical images (because the amount of compression is so poor), but it has been added for test comparison purposes. - enhanced the dithering option when quantizing and compressing floating point images so that a random dithering starting point is used, so that the same dithering pattern does not get used for every image. - modified the architecture setup section of fitsio2.h to support the 64-core 8x8-architecture Tile64 platform (thanks to Ken Mighell, NOAO) Fixes - fixed a problem that was introduced in version 3.13 of CFITSIO in cases where a program writes it own END keyword to the header instead of letting CFITSIO do it, as is strongly recommended. In one case this caused CFITSIO to rewrite the END keyword and any blank fill keywords in the header many times, causing a noticeable slow-down in the FITS file writing speed. Version 3.21 - 24 September 2009 - fixed bug in cfileio.c that caused CFITSIO to crash with a bus error on Mac OS X if CFITSIO was compiled with multi-threaded support (with the --enable-reentrant configure option). The Mac requires an additional thread initialization step that is not required on Linux machines. Even with this fix, occasional bus errors have been seen on some Mac platforms, The bus errors are seen when running the thread_test.c program. The bus errors are very intermittent, and occur less than about 1% of the time, on the affected platforms. These bus errors have not been seen on Linux platforms. - fixed invalid C comment delimiter ("//*" should have been "/*") in imcompress.c. - Increased the CFITSIO version number string length in fpackutil.c, to fix problem on some platforms when running fpack -V or funpack -V. Also modified the output format of the fpack -L command. Version 3.20 - 31 August 2009 - modified configure.in and configure so that it will build the Fortran interface routines by default, even if no Fortran compiler is found in the user's path. Building the interface routines may be disabled by specifying FC="none". This was done at the request of users who obtained CFITSIO from some other standard linux distributions, where CFITSIO was apparently built in an environment that had no Fortran compiler and hence did not build the Fortran wrappers. - modified ffchdu (close HDU) so that it calls the routine to update the maximum length of variable length table columns in the TFORM values in all cases where the values may have changed. Previously it would not update the values if a value was already specified in the TFORM value. - added 2 new string manipulation functions to the CFITSIO parser (contributed by Craig Markwardt): strmid extracts a substring from a string, and strstr searches for a substring within a string. - removed the code in quantize.c that treated "floating-point integer" images as a special case (it would just do a datatype conversion from float to int, and not otherwise quantize the pixel values). This caused complications with the new subtractive dithering feature. - enhanced the code for converting floating point images to quantized scaled integer prior to tile-compressing them, to apply a random subtractive dithering, which improves the photometric accuracy of the compressed images. - added new internal routine, iraf_delete_file, for use by fpack to delete a pair of IRAF format header and pixel files. - small change in cfileio.c in the way it recognizes an IRAF format .imh file. Instead of just requiring that the filename contain the ".imh" string, that string must occur at the end of the file name. - fixed bug in the code that is used when tile-compressing real*4 FITS images, which quantizes the floating point pixel values into integer levels. The bug would only appear in the fairly rare circumstance of tile compressing a floating point image that contains null pixels (NaNs) and only when using the lossy Hcompress algorithm (with the s parameter not equal to 1). This could cause underflow of low valued pixels, causing them to appear as very large pixel values (e.g., > 10**30) in the compressed image - changed the "if defined" blocks in fitsio.h, fitsio2.h and f77_wrap.h to correctly set the length of long variables on sparc64 machines. Patch contributed by Matthew Truch (U. Penn). - modified the HTTP file access code in drvrnet.c to support basic HTTP authentication, where the user supplies a user name and password. The CFITSIO filename format in this case is: "http://username:password@hostname/..." Thanks to Jochen Liske (ESO) for the suggestion and the code. Version 3.181 (BETA) - 12 May 2009 - modified region.c and region.h to add support for additional types of region shapes that are supported by ds9: panda, epanda, and bpanda. - fixed compiler error when using the new _REENTRANT flag, having to do with the an attempted static definition of Fitsio_Lock in several source files, after declaring it to be non-static in fitsio2.h. Version 3.18 (BETA) - 10 April 2009 - Made extensive changes to make CFITSIO thread safe. Previously, all opened FITS files shared a common pool of memory to store the most recently read or written FITS records in the files. In a multi-threaded environment different threads could simultaneously read or write to this common area causing unpredictable results. This was changed so that every opened FITS file has its own private memory area for buffering the file. Most of the changes were in buffers.c, fitsio.h, and fitsio2.h. Additional changes were made to cfileio.c, mainly to put locks around small sections of code when setting up the low-level drivers to read or write the FITS file. Also, locks were needed around the GZIP compression and uncompression code in compress.c., the error message stack access routine in fitscore.c, the encode and decode routines in fits_hcompress.c and fits_hdecompress.c, in ricecomp.c, and the table row selection and table calculator functions. Also, removed the 'static' declaration of the local variables in pliocomp.c which did not appeared to be required and prevented the routines from being thread safe. As a consequence of having a separate memory buffer for every FITS file (by default, about 115 kB per file), CFITSIO may now allocate more memory than previously when an application program opens multiple FITS files at once. The read and write speed may also be slightly faster, since the buffers are not shared between files. - Added new families of Fortran wrapper routines to read and write values to large tables that have more than 2**31 rows. The arguments that define the first row and first element to read or write must be I*8 integers, not ordinary I*4 integers. The names of these new routines have 'LL' appended to them, so for example, ftgcvb becomes ftgcvbll. Fixes - Corrected an obscure bug in imcompress.c that would have incorrectly written the null values only in the rare case of writing a signed byte array that is then tile compressed using the Hcompress or PLIO algorithm. Version 3.14 - 18 March 2009 Enhancements - modified the tiled-image compression and uncompression code to support compressing unsigned 16-bit integer images with PLIO. FITS unsigned integer arrays are offset by -32768, but the PLIO algorithm does not work with negative integer values. In this case, an offset of 32768 is added to the array before compression, and then subtracted again when reading the compressed array. IMPORTANT NOTE: This change is not backward compatible, so these PLIO compressed unsigned 16-bit integer images will not be read correctly by previous versions of CFITSIO; the pixel values will have an offset of +32768. - minor changes to the fpack utility to print out more complete version information with the -V option, and format the report produced by the -T option more compactly. Fixes - Modified imcomp_compress_image (which is called by fpack) so that it will preserve any null values (NaNs) if the input image has a floating point datatype (BITPIX = -32 or -64). Null values in integer datatype images are handled correctly. - Modified imcomp_copy_comp2img so that it does not copy the ZBLANK keyword, if present, from the compressed image header when uncompressing the image. - Fixed typo in the Fortran wrapper macro for the ftexist function. Version 3.13 - 5 January 2009 Enhancements - updated the typedef of LONGLONG in fitsio.h and cfortran.h to support the Borland compiler which uses the __int64 data type. - added new feature to the extended filename syntax so that when performing a filtering operation on specified HDU, if you add a '#' character after the name or number of the HDU, then ONLY that HDU (and the primary array if the HDU is a table) will be copied into the filtered version of the file in memory. Otherwise, by default CFITSIO copies all the HDUs from the input file into memory. - when specifying a section, if the specified number of dimensions is less than the number of dimensions in the image, then CFITSIO will use the entire dimension, as if a '*' had been specified. Thus [1:100] is equivalent to [1:100,*] when specifying a section of 2 dimensional image. - modified fits_copy_image_section to read/write the section 1 row at a time, instead of the whole section, to reduce memory usage. - added new stream:// drivers for reading/writing to stdin/stdout. This driver is somewhat fragile, but for simple FITS read and write operations this driver streams the FITS file on stdin or stdout without first copying the entire file in memory, as is done when specifying the file name as "-". - slight modification to ffcopy to make sure that the END keyword is correctly written before copying the data. This is required by the new stream driver. - modified ffgcprll, so that when writing data to an HDU, it first checks that the END keyword has been written to the correct place. This is required by the new stream driver. Fixes - fixed bug in ffgcls2 when reading an ASCII string column in binary tables in cases where the width of the column is greater than 2880 characters and when reading more than 1 row at a time. Similar change was made to ffpcls to fix same problem with writing to columns wider than 2880 characters. - updated the source files listed in makepc.bat so that it can be used to build CFITSIO with the Borland C++ compiler. - fixed overflow error in ffiblk that could cause writing to Large Files (> 2.1 GB) to fail with an error status. - fixed a bug in the spatial region code (region.c) with the annulus region. This bug only affected specialized applications which directly use the internal region structure; it does not affect any CFITSIO functions directly. - fixed memory corruption bug in region.c that was triggered if the region file contained a large number of excluded regions. - got rid of a harmless error message that would appear if filtering a FITS table with a GTI file that has zero rows. (eval_f.c) - modified fits_read_rgnfile so that it removes the error messages from the error stack if it is unable to open the region file as a FITS file. (region.c) Version 3.12 - 8 October 2008 - modified the histogramming code so that the first pixel in the binned array is chosen as the reference pixel by default, if no other value is previously defined. - modified ffitab and ffibin to allow a null pointer to the EXTNAME string, when inserting a table with no name. Version 3.11 - 19 September 2008 - optimized the code when tile compressing real*4 images (which get scaled to integers). This produced a modest speed increase. For best performance, one must specify the absolute q quantization parameter, rather than relative to the noise in the tile (which is expensive to compute). - modified the FITS region file reading code to check for NaN values, which signify the end of the array of points in a polygon region. - removed the test for LONGSIZE == 64 from fitsio.h, since it may not be defined. - modified imcompress.c to support unconventional floating point FITS images that also have BSCALE and BZERO keywords. The compressed floating point images are linearly scaled twice in this case. Version 3.10 - 20 August 2008 - fixed a number of cases, mainly dealing with long input file names (> 1024 char), where unsafe usage of strcat and strcpy could have caused buffer overflows. These buffer overflows could cause the application to crash, and at least theoretically, could be exploited by a malicious user to execute arbitrary code. There are no known instances of this type of malicious attack on CFITSIO applications, and the likelihood of such an attack seems remote. None the less, it would be prudent for CFITSIO users to upgrade to this new version to guard against this possibility. - modified some of the routines to define input character string parameters as "const char *" rather than just "char *" to eliminate some compiler warnings when the calling routine passes a constant string to the CFITSIO routine. Most of the changes were to the keyword name argument in the many routines that read or write keywords. - fixed bug when tile-compressing a FITS image which caused all the completely blank keywords in the input header to be deleted from the output compressed image. Also added a feature to preserve any empty FITS blocks in the header (reserved space for future keywords) when compressing or uncompressing an image. - fixed small bug in the way the default tile size is set in imcompress.c. (Fix sent in by Paul Price). - added support for reading FITS format region files (in addition to the ASCII format that was previously supported). Thanks to Keith Arnaud for modifying region.c to do this. Version 3.09 - 12 June 2008 - fixed bug in the calculator function, parse_data, that evaluates expressions then selecting rows or modifying values in table columns. This bug only appeared in unusual circumstances where the calculated value has a null value (= TNULLn). The bug could cause elements to not be flagged as having a null value, or in rare cases could cause valid elements to be flagged as null. This only appears to have affected 64-bit platforms (where size(long) = 8). - fixed typo in imcomp_decompress_tile: call to fffi2r8 should have been to fffi4r8. - in the imcopy_copy_comp2img routine, moved the call to fits_translate_keywords outside of the 'if' statement. This could affect reading compressed images that did not have a EXTNAME keyword in the header. - fixed imcomp_compress_tile in imcompress.c to properly support writing unsigned integers, in place, to tile compressed images. - modified fits_read_compressed_img so that if the calling routine specifies nullval = 0, then it will not check for null-valued pixels in the compressed FITS image. This mimics the same behavior when reading normal uncompressed FITS images. Version 3.08 - 15 April 2008 - fixed backwards compatibility issue when uncompressing a Rice compressed image that was created with previous versions of CFITSIO (this late fix was added on May 18). - small change to cfortran.h to add "extern" to the common block definition. This was done for compatibility with the version of cfortran.h that is distributed by the Debian project. - relaxed the requirement that a string valued keyword must have a closing quote character. If the quote is missing, CFITSIO will silently append a quote at the end of the keyword record. This change was made because otherwise it is very difficult to correct the keyword because CFITSIO would exit with an error before making the fix. - added a new BYTEPIX compression parameter when tile-compressing images with the Rice algorithm. - cached the NAXIS and NAXISn keyword values in the fitsio structure for efficiency, to eliminate duplicates reads of these keywords. - added variants of the Rice compression and uncompression routines to support short int images (in addition to the routines that support int). - moved the definition of LONGLONG_MIN and LONGLONG_MAX from fitsio2.h to fitsio.h, to make it accessible to application programs. - make efficiency improvements to fitscore.c, to avoid needless searches through the entire header when reading the required keywords that must be near the beginning of the header. - made several improvements to getcol.c to optimize reading of compressed and uncompressed images. - changed the compression level in the gzip code from 6 to 1. In most cases this will provide nearly the same amount of compression, but is significantly faster in some cases. - added new "helper routines' to imcompress.c to allow applications to specified the "quantize level" and Hcompress scaling and smoothing parameters - modified the extended filename syntax to support the "quantize level" and Hcompress scaling and smoothing parameters. The parser in cfileio.c was extensively modified. - extensive changes to quantize.c: - replace the "nbits" parameter with "quantize level" - the quantize level is now relative to the RMS noise in the image - the HCOMPRESS scale factor is now relative to the RMS noise - added routines to calculate RMS noise in image (these changes require a change to the main file structure in fitsio.h) - initialize errno = 0 before the call to strtol in ffext, in case errno has previously been set by an unrelated error condition. - added the corresponding long name for the ffgkyjj routine to longnam.h. - changed imcomp_copy_comp2img (in imcompress.c) to not require the presence of the EXTNAME keyword in the input compressed image header. - modified imcompress.c to only write the UNCOMPRESSED_DATA column in tile-compressed images if it is actually needed. This eliminates the need to subsequently delete the column if it is not used (which is almost always the case). - found that it is necessary to seek to the EOF of a file after truncating the size of the file, to reestablish a definite current location in the file. The required small changes to 3 routines: file_truncate (to seek to EOF) and fftrun (to set io_pos) and the truncation routine in drvrmem.c. - improved the efficiency when compressing integer images with gzip. Previously, the image was always represented using integer*4 pixels, which were then compressed. Now, if the range of pixel values can be represented with integer*2 pixels or integer*1 pixels, then that is used. This change is backward compatible with any compressed images that used the previous method. - changed the default tiling pattern when using Hcompress from large squares (200 to 600 pixels wide) to 16 rows of the image. This generally requires less memory, compresses faster, and is more consistent with the default row by row tiling when using the other compression methods. - modified imcomp_init_table in imcompress.c to enforce a restriction when using the Hcompress algorithm that the 1st 2 dimensions of sll image tiles must be at least 4 pixels long. Hcompress becomes very inefficient for smaller dimensions, and does not work at all with 1D images. - fixed bug in the Hcompress compression algorithm that could affect compression of I*4 images, using non-square compression tiles (in the encode64 routine). Version 3.07 - 6 December 2007 (internal release) - fixed bug with the PLIO image compression routine which silently produced a corrupted compressed image if the uncompressed image pixels were not all in the range 0 to 2**24. (fixed in November) - fixed several 'for' loops in imcompress.c which were exceeding the bounds of an array by 1. (fixed in November) - fixed a possible, but unlikely, memory overflow issue in iraffits.c. - added a clarification to the cfortran.doc file that cfortran.h may be used and distributed under the terms of the GNU Library General Public License. - fixed bug in the fits_modify_vector_len routine when modifying the vector length of a 'X' bit column. Version 3.06 - 27 August 2007 - modified the imcopy.c utility program (to tile-compress images) so that it writes the default EXTNAME = 'COMPRESSED_IMAGE' keyword in the compressed images, to preserve the behavior of earlier versions of imcopy. - modified the angsep function in the FITS calculator (in eval.y) to use haversines, instead of the 'law of cosines', to provide more precision at small angles (< 0.1 arcsec). Version 3.05 - July 2007 (internal release only) - extensive changes to imcompress.c to fully support implicit data type conversion when reading and writing arrays of data to FITS images, where the data type of the array is not the same as the data type of the FITS image. This includes support for null pixels, and data scaling via the BSCALE and BZERO keywords. - rewrote the fits_read_tbl_coord routine in wcssub.c, that gets the standard set of WCS keywords appropriate to a pair of columns in a table, to better support the full set of officially approved WCS keywords. - made significant changes to histo.c, which creates an image by binning columns of a table, to better translate the WCS keywords in the table header into the WCS keywords that are appropriate for an image HDU. - modified imcompress.c so that when pixels are written to a tile-compressed image, the appropriate BSCALE and BZERO values of that image are applied. This fixes a bug in which writing to an unsigned integer datatype image (with BZERO = 32768) was not done correctly. Version 3.04 - 3 April 2007 - The various table calculator routines (fits_select_rows, etc.) implicitly assumed that the input table has not been modified immediately prior to the call. To cover cases where the table has been modified a call to ffrdef has been added to ffprs. IN UNUSUAL CASES THIS CHANGE COULD CAUSE CFITSIO TO BEHAVE DIFFERENTLY THAN IN PREVIOUS VERSIONS. For example, opening a FITS table with this column-editing virtual file expression: myfile.fits[3][col A==X; B = sqrt(X)] no longer works, because the X column does not exist when the sqrt expression is evaluated. The correct expression in this case is myfile.fits[3][col A==X; B = sqrt(A)] - modified putkey.c to support USHORT_IMG when calling fits_create_img to create a signed byte datatype image. - enhanced the column histogramming function to propagate any TCn_k and TPn_k keywords in the table header to the corresponding CDi_j and PCi_j keywords in the image header. - enhanced the random, randomn, and randomp functions in the lexical parser to take a vector column name argument to specify the length of the vector of random numbers that should be generated (provided by Craig Markwardt, GSFC) - enhanced the ffmcrd routine (to modify an existing header card) to support long string keywords so that any CONTINUE keywords associated with the previous keyword will be deleted. - modified the ffgtbp routine to recognize the TDIMn keyword for ASCII string columns in a binary table. The first dimension is taken to be the size of a unit string. (The TFORMn = 'rAw' syntax may also be used to specify the unit string size). - in fits_img_decompress, the fits_get_img_param function was called with an invalid dimension size, which caused a fatal error on at least 1 platform. - in ffopentest, set the status value before returning in case of error. - in the drvrnet.c file, the string terminators needed to be changed from "\n" to "\r\n" to support the strict interpretation of the http and ftp standard that is enforced by some newer web servers. Version 3.03 - 11 December 2006 New Routine - fits_write_hdu writes the current HDU to a FILE stream (e.g. stdout). Changes - modified the region parsing code to support region files where the keyword "physical" is on a separate line preceding the region shape token. (However, "physical" coordinates are not fully supported, and are treated identically to "image" coordinates). - enhanced the iterator routines to support calculations on 64-bit integer columns and images. Currently, the values are cast to double precision when doing the calculations, which can cause a loss of precision for integer values greater than about 2**52. - added support for accessing FITS files on the computational grid. Giuliano Taffoni and Andrea Barisani, at INAF, University of Trieste, Italy, implemented the necessary I/O driver routines in drvrgsiftp.c. - modified the tiled image compression/uncompression routines to preserve/restore the original CHECKSUM and DATASUM keywords if they exist. (saved as ZHECKSUM and ZDATASUM in the compressed image) - split fits_select_image_section into 2 routines: a higher level routine that creates the output file and copies other HDUs from the input file to the output file, and a lower level routine that extracts the image section from the input image into an output image HDU. - Improved the error messages that get generated if one tries to use the lexical parser to perform calculations on variable-length array columns. - added "#define MACHINE NATIVE" in fitsio2.h for all machines where BYTESWAPPED == FALSE. This may improve the file writing performance by eliminating the need to allocate a temporary buffer in some cases. - modified the configure.in and configure script to fix problems with testing if network services are available, which affects the definition of the HAVE_NET_SERVICES flag. - added explicit type casting to all malloc statements, and deleted declarations of unreferenced variables in the image compression code to suppress compiler warnings. - fixed incorrect logic in fitsio2.h in the way it determined if numerical values are byteswapped or not on MIPS and ARM architectures. - added __BORLANDC__ to the list of environments in fitsio.h that don't use %lld in printf for longlong integers - added "#if defined(unix)" around "#include " statements in several C source files, to make them compatible with Windows. Version 3.02 - 18 Sept 2006 - applied the security patch to the gzip code, available at http://security.FreeBSD.org/patches/SA-06:21/gzip.patch The insufficient bounds checks in buffer use can cause gzip to crash, and may permit the execution of arbitrary code. The NULL pointer deference can cause gzip to crash. The infinite loop can cause a Denial-of-Service situation where gzip uses all available CPU time. - added HCOMPRESS as one of the compression algorithm options in the tiled image compression code. (code provided by Richard White (STScI)) Made other improvements to preserve the exact header structure in the compressed image file so that the compressed-and-then-uncompressed FITS image will be as identical as possible to the original FITS image file. New Routines - the following new routines were added to support reading and writing non-standard extension types: fits_write_exthdr - write required keywords for a conforming extension fits_write_ext - write data to the extension fits_read_ext - read data from the extension - added new routines to compute the RMS noise in the background pixels of an image: fits_rms_float and fits_rms_short (take an input array of floats or shorts, respectively). Fixes - added the missing 64-bit integer case to set of "if (datatype)" statements in the routine that returns information about a particular column (ffgbclll). - fixed a parsing error in ffexts in cases where an extension number is followed by a semi-colon and then the column and row number of an array in a binary table. Also removed an extraneous HISTORY keyword that was being written when specifying an input image in a table cel. - modified the routine that reads a table column returning a string value (ffgcls) so that if the displayed numerical value is too wide to fit in the specified length string, then it will return a string of "*" characters instead of the number string. - small change to fitsio.h to support a particular Fortran and C compiler combination on a SGI Altix system - added a test in the gunzip code to prevent seg. fault when trying to uncompress a corrupted file (at least in some cases). - fixed a rarely-occurring bug in the routine that copies a table cell into an image; had to call the ffflsh call a few lines earlier. Version 3.01 - (in FTOOLS 6.1 release) - modified fits_copy_image2cell to correctly copy all the appropriate header keywords when copying an image into a table cell - in eval.y, explicitly included the code for the lgamma function instead of assuming it is available in a system library (e.g., the lgamma function is currently not included in MS Visual++ libraries) - modified the logic in fits_pixel_filter so that the default data type of the output image will be promoted to at least BITPIX = -32 (a single precision floating point) if the expression that is being evaluated resolves to a floating point result. If the expression resolves to an integer result, the output image will have the same BITPIX as the input image. - in fits_copy_cell2image, added 5 more WCS keywords to the list of keywords related to other columns that should be deleted in the output image header. - disabled code in cfileio.c that would write HISTORY keywords to the output file in fits_copy_image2cell and cell2image, because some tasks would not want these extraneous HISTORY keywords. - added 2 new random number functions to the CFITSIO parser RANDOMN() - produces a normal deviate (mean=0, stddev=1) RANDOMP(X) - produces a Poisson deviate for an expected # of counts X - in f77_wrap.h, removed the restriction that "g77Fortran" must be defined on 64-bit Itanium machines before assuming that sizeof(long) = 8. It appears that "long"s are always 8 bytes long on this machine, regardless of what compilers are used. - added test in fitsio.h so that LONGLONG cannot be multiply defined - modified longnam.h so that both "fits_write_nulrows" and "fits_write_nullrows" get replace by the string "ffprwu". This fixes a documentation error regarding the long name of this routine. Bug fixes - fixed a potential null character string dereferencing error in the the ffphtb and ffphbn routines that write the FITS table keywords. This concerned the optional TUNITn keywords. - fixed a few issues in fits_copy_cell2image and fits_copy_image2cell related to converting some WCS keyword between the image extension form and the table cell form of the keyword. (cfileio.c) - fixed bug in fits_translate_keyword (fitscore.c) that, e.g., caused 'EQUINOX' to be translated to EQUINOXA' if the pattern is 'EQUINOXa' - fixed 2 bugs that could affect 'tile compressed' floating point images that contain NaN pixels (null pixels). First, the ZBLANK keyword was not being written, and second, an integer overflow could occur when computing the BZERO offset in the compressed array. (quantize.c and imcompress.c) Version 3.006 - 20 February 2006 -(first full release of v3) - enhanced the 'col' extended filename syntax to support keyword name expressions like [col error=sqrt(rate); #TUNIT# = 'counts/s'], in which the trailing '#' will be replaced by the column number of the most recently referenced column. - fixed bug in the parse_data iterator work function that caused it to fail to return a value of -1 in cases where only a selected set of rows were to be processed. (affected Fv) - added code to fitsio.h and cfortran.h to typedef LONGLONG to the appropriate 8-byte integer data type. Most compilers now support the 'long long' data type, but older MS Visual C++ compilers used '__int64' instead. - made several small changes based on testing by Martin Reinecke: o in eval.y, change 'int undef' to 'long undef' o in getcold.c and getcole.c, fixed a couple format conversion specifiers when displaying the value of long long variables. o in fitsio.h, modified the definition of USE_LL_SUFFIX in the case of Athon64 machines. o in fitsio2.h, defined BYTESWAPPED in the case of SGI machines. o in group.c, added 'include unistd.h' to get rid of compiler warning. Version 3.005 - 20 December 2005 (beta) - cfortran.h has been enhanced to support 64-bit integer parameters when calling C routines from Fortran. This modification was kindly provided by Martin Reinecke (MPE, Garching). - Many new Fortran wrapper routines have been added to support reading and writing 64-bit integer values in FITS files. These new routines are documented in the updated version of the 'FITSIO User's Guide' for Fortran programmers. - fixed a problem in the fits_get_keyclass routine that caused it to not recognize the special COMMENT keywords at the beginning of most FITS files that defines the FITS format. - added a new check to the ffifile routine that parses the input extended file name, to distinguish between a FITS extension name that begins with 'pix', and a pixel filtering operator that begins with the 'pix' keyword. - small change to the WCSLIB interface routine, fits_read_wcstab, to be more permissive in allowing the TDIMn keyword to be omitted for degenerate coordinate array. Version 3.004 - 16 September 2005 (3rd public beta release) - a major enhancement to the CFITSIO virtual file parser was provided by Robert Wiegand (GSFC). One can now specify filtering operations that will be applied on the fly to the pixel values in a FITS image. For example [pix sqrt(X)] will create a virtual FITS image where the pixel values are the square root of the input image pixels. - modified region.c so that it interprets the position angles of regions in a SAO style region file in the same way as DS9. In particular, if the region parameters are given in WCS units, then the position angle should be relative to the WCS coordinates of the image (increasing CCW from West) instead of relative to the X/Y pixel coordinate system. This only affects rotated images (e.g. with non-zero CROTA2 keyword) with elliptical or rectangular regions. - cleaned up fitsio.h and fitsio2.h to make the definition of LONGLONG and BYTESWAPPED and MACHINE more logical. - removed HAVE_LONGLONG everywhere since it is no longer needed (the compiler now must have an 8-byte integer datatype to build CFITSIO). - added support for the 64-bit IBM AIX platform - modified eval.y so that the circle, ellipse, box, and near functions can operate on vectors as well as scalars. This allows region filtering on images that are stored in a vector cell in a binary table. (provided by Craig Markwardt, GSFC) New Routines - added new fits_read_wcstab routine that serves as an interface to Mark Calabretta's wcslib library for reading WCS information when the -TAB table lookup convention is used in the FITS file. - added new fits_write_nullrows routine, which writes null values into every column of a specified range of rows in a FITS table. - added the fits_translate_keyword and fits_translate_keywords utility routines for converting the names of keywords when moving columns and images around. - added fits_copy_cell2image and fits_copy_image2cell routines for copying an image extension (or primary array) to or from a cell in a binary table vector column. Bug fixes - fixed a memory leak in eval.y; was fixed by changing a call to malloc to cmalloc instead. - changed the definition of several global variables at the beginning of buffers.c to make them 'static' and thus invisible to applications programs. - in fits_copy_image_cell, added a call to flush the internal buffers before reading from the file, in case any records had been modified. Version 3.003 - 28 July 2005 - 2nd public beta release (used in HEASOFT) Enhancements - enhanced the string column reading routing fits_get_col_str to support cases where the user enters a null pointer (rather than a null string) as the nulval parameter. - modified the low level ffread and ffwrite routines that physically read and write data from the FITS file so that they write the name of the file to the CFITSIO error stack if an error occurs. - changed the definition of fits_open_file into a macro that will test that the version of the fitsio.h include file that was used to build the CFITSIO library is the same version as included when compiling the application program. - made a simple modification to region.c to support regions files of type "linear", for compatibility with ds9 and fv. - modified the internal ffgpr routine (and renamed it ffgprll) so that it returns the TNULL value as a LONGLONG parameter instead of 'long'. - in fits_get_col_display_width, added support for TFORM = 'k' - modified fitsio.h, fitsio2.h, and f77_wrap.h to add test for (_SX) to identify NEC SX supercomputers. - modified eval_f.c to treat table columns of TULONG (unsigned long) as a double. Also added support for TLONGLONG (8-byte integers) as a double, which is only a temporary fix, since doubles only have about 52 bits of precision. - changed the 'blank' parameter in the internal ffgphd function to to type LONGLONG to support integer*8 FITS images. - when reading the TNULL keyword value, now use ffc2jj instead of ffc2ii, to support integer*8 values. Bug fixes - fixed a significant bug when writing character strings to a variable length array column of a binary table. This bug would result in some unused space in the variable length heap, making the heap somewhat larger than necessary. This in itself is usually a minor issue, since the FITS files are perfectly valid, and other software should have no problems reading back the characters strings. In some cases, however, this problem could cause the program that is writing the table to exit with a status = 108 disk read error. - modified the standalone imcopy.c utility program to fix a memory allocation bug when running on 64-bit platforms where sizeof(long) = 8 bytes. - added an immediate 'return' statement to ffgtcl if the input status >0, to prevent a segfault on some platforms. Version 3.002 - 15 April 2005 - first public beta release - in drvrfile.c, if it fails to open the file for some reason, then it should reset file_outfile to a null string, to avoid errors on a subsequent call to open a file. - updated fits_get_keyclass to recognize most of the WCS keywords defined in the WCS Papers I and II. Version 3.001 - 15 March 2005 - released with HEASOFT 6.0 - numerous minor changes to the code to get rid of compiler warning messages, mainly dealing with numerical data type casting and the subsequent possible loss of precision in the result. Version 3.000 - 1 March 2005 (internal beta release) Enhancements: - Made major changes to many of the CFITSIO routines to more generally support Large Files (> 2.1 GB). These changes are intended to be 100% backward compatible with software that used the previous versions of CFITSIO. The datatype of many of the integer parameters in the CFITSIO functions has been changed from 'long' to 'LONGLONG', which is typedef'ed to be equivalent to an 8-byte integer datatype on each platform. With these changes, CFITSIO supports the following: - integer FITS keywords with absolute values > 2**31 - FITS files with total sizes > 2**31 bytes - FITS tables in which the number of rows, the row width, or the size of the heap is > 2**31 bytes - FITS images with dimensions > 2**31 bytes (support is still somewhat limited, with full support to be added later). - added another lexical parser function (thanks to Craig Markwardt, GSFC): angsep computes the angular separation between 2 positions on the celestial sphere. - modified the image subset extraction code (e.g., when specifying an image subregion when opening the file, such as 'myimage.fits[21:40, 81:90]') so that in addition to updating the values of the primary WCS keywords CRPIXk, CDELTi, and CDj_i in the extracted/binned image, it also looks for and updates any secondary WCS keywords (e.g., 'CRPIX1P'). - made cosmetic change to group.c, so that when a group table is copied, any extra columns will be appended after the last existing column, instead of being inserted before the last column. - modified the routines that read tile compressed images to support NULL as the input value for the 'anynul' parameter (meaning the calling program does not want the value of 'anynul' returned to it). - when constructing or parsing a year/month/day character string, (e.g, when writing the DATE keyword) the routines now rigorously verify that the input day value is valid for the given month (including leap years). - added some checks in cfileio.c to detect if some vital parameters that are stored in memory have been corrupted. This can occur if a user's program writes to areas of memory that it did not allocate. - added the wcsutil_alternate.c source code file which contains non-working stubs for the 2 Classic AIPS world coordinate conversion routines that are distributed under the GNU General Public License. Users who are unwilling or unable to distribute their software under the General Public License may use this alternate source file which has no GPL restrictions, instead of wcsutil.c. This will have no effect on programs that use CFITSIO as long as they do not call the fits_pix_to_world/ffwldp or fits_world_to_pix/ffxypx routines. Bug Fixes - in ffdtdm (which parses the TDIMn keyword value), the check for consistency between the length of the array defined by TDIMn and the size of the TFORMn repeat value, is now not performed for variable length array columns (which always have repeat = 1). - fixed byteswapping problem when writing null values to non-standard long integer FITS images with BITPIX = 64 and FITS table columns with TFORMn = 'K'. - fixed buffer overflow problem in fits_parse_template/ffgthd that occurred only if the input template keyword value string was much longer than can fit in an 80-char header record. Version 2.510 - 2 December 2004 New Routines: - added fits_open_diskfile and fits_create_diskfile routines that simply open or create a FITS file with a specified name. CFITSIO does not try to parse the name using the extended filename syntax. - 2 new C functions, CFITS2Unit and CUnit2FITS, were added to convert between the C fitsfile pointer value and the Fortran unit number. These functions may be useful in mixed language C and Fortran programs. Enhancements: - added the ability to recognize and open a compressed FITS file (compressed with gzip or unix compress) on the stdin standard input stream. - Craig Markwardt (GSFC) provided 2 more lexical parser functions: accum(x) and seqdiff(x) that compute the cumulative sum and the sequential difference of the values of x. - modified putcole.c and putcold.c so that when writing arrays of pixels to the FITS image or column that contain null values, and there are also numerical overflows when converting some of the non-null values to the FITS values, CFITSIO will now ignore the overflow error until after all the data have been written. Previously, in some circumstances CFITSIO would have simply stopped writing any data after the first overflow error. - modified fitsio2.h to try to eliminate compiler warning messages on some platforms about the use of 'long long' constants when defining the value of LONGLONG_MAX (whether to use L or LL suffix). - modified region.c to support 'physical' regions in addition to 'image', 'fk4', etc. - modified ffiurl (input filename parsing routine) to increase the maximum allowed extension number that can be specified from 9999 to 99999 (e.g. 'myfile.fits+99999') Bug Fixes: - added check to fits_create_template to force it to start with the primary array in the template file, in case an extension number was specified as part of the template FITS file name. Version 2.500 - 28 & 30 July 2004 New Routine: - fits_file_exists tests whether the specified input file, or a compressed version of the file, exists on disk. Enhancements: - modified the way CFITSIO reads and writes data in COMPLEX ('C') and DBLCOMPLEX 'M' columns. Now, in all cases, when referring to the number of elements in the vector, or the value of the offset to a particular element within the vector, CFITSIO considers each pair of numbers (the imaginary and real parts) as a single element instead of treating each single number as an element. In particular, this changes the behavior of fits_write_col_null when writing to complex columns. It also changes the length of the 'nullarray' vector in the fits_read_colnull routine; it is now only 1/2 as long as before. Each element of the nullarray is set = 1 if either the real or imaginary parts of the corresponding complex value have a null value.(this change was added to version 2.500 on 30 July). - Craig Markwardt, at GSFC, provided a number of significant enhancements to the CFITSIO lexical parser that is used to evaluate expressions: - the parser now can operate on bit columns ('X') in a similar way as for other numeric columns (e.g., 'B' or 'I' columns) - range checking has been implemented, so that the following conditions return a Null value, rather than returning an error: divide by zero, sqrt(negative), arccos(>1), arcsin(>1), log(negative), log10(negative) - new vector functions: MEDIAN, AVERAGE, STDDEV, and NVALID (returns the number of non-null values in the vector) - all the new functions (and SUM, MIN and MAX) ignore null values - modified the iterator to support variable-length array columns - modified configure to support AIX systems that have flock in a non- standard location. - modified configure to remove the -D_FILE_OFFSET_BITS flag when running on Mac Darwin systems. This caused conflicts with the Fortran wrappers, and should only be needed in any case when using CFITSIO to read/write FITS files greater than 2.1 GB in size. - modified fitsio2.h to support compilers that define LONG_LONG_MAX. - modified ffrsim (resize an existing image) so that it supports changing the datatype to an unsigned integer image using the USHORT_IMG and ULONG_IMG definitions. - modified the disk file driver (drvrfile.c) so that if an output file is specified when opening an ordinary file (e.g. with the syntax 'myfile.fits(outputfile.fits)' then it will make a copy of the file, close the original file and open the copy. Previously, the specified output file would be ignored unless the file was compressed. - modified f77_wrap.h and f77_wrap3.c to support the Fortran wrappers on 64-bit AMD Opteron machines Bug fixes: - made small change to ffsrow in eval_f.c to avoid potential array bounds overflow. - made small change to group.c to fix problem where an 'int' was incorrectly being cast to a 'long'. - corrected a memory allocation error in the new fits_hdr2str routine that was added in version 2.48 - The on-the-fly row-selection filtering would fail with a segfault if the length of a table row (NAXIS1 value) was greater than 500000 bytes. A small change to eval_f.c was required to fix this. Version 2.490 - 11 February 2004 Bug fixes: - fixed a bug that was introduced in the previous release, which caused the CFITSIO parser to no longer move to a named extension when opening a FITS file, e.g., when opening myfile.fit[events] CFITSIO would just open the primary array instead of moving to the EVENTS extension. - new group.c file from the INTEGRAL Science Data Center. It fixes a problem when you attach a child to a parent and they are both is the same file, but, that parent contains groups in other files. In certain cases the attach would not happen because it seemed that the new child was already in the parent group. - fixed bug in fits_calculator_rng when performing a calculation on a range of rows in a table, so that it does not reset the value in all the other rows that are not in the range = 0. - modified fits_write_chksum so that it updates the TFORMn keywords for any variable length vector table columns BEFORE calculating the CHECKSUM values. Otherwise the CHECKSUM value is invalidated when the HDU is subsequently closed. Version 2.480 - 28 January 2004 New Routines: - fits_get_img_equivtype - just like fits_get_img_type, except in the case of scaled integer images, it returns the 'equivalent' data type that is necessary to store the scaled data values. - fits_hdr2str copies all the header keywords in the current HDU into a single long character string. This is a convenient method of passing the header information to other subroutines. The user may exclude any specified keywords from the list. Enhancements: - modified the filename parser so that it accepts extension names that begin with digits, as in 'myfile.fits[123TEST]'. In this case CFITSIO will try to open the extension with EXTNAME = '123TEST' instead of trying to move to the 123rd extension in the file. - the template keyword parser now preserves the comments on the the mandatory FITS keywords if present, otherwise a standard default comment is provided. - modified the ftp driver file (drvrnet.c) to overcome a timeout or hangup problem caused by some firewall software at the user's end (Thanks to Bruce O'Neel for this fix). - modified iraffits.c to incorporate Doug Mink's latest changes to his wcstools library routines. The biggest change is that now the actual image dimensions, rather than the physically stored dimensions, are used when converting an IRAF file to FITS. Bug fixes: - when writing to ASCII FITS tables, the 'elemnum' parameter was supposed to be ignored if it did not have the default value of 1. In some cases however setting elemnum to a value other than 1 could cause the wrong number of rows to be produced in the output table. - If a cfitsio calculator expression was imported from a text file (e.g. using the extended filename syntax 'file.fits[col @file.calc]') and if any individual lines in that text file were greater than 255 characters long, then a space character would be inserted after the 255th character. This could corrupt the line if the space was inserted within a column name or keyword name token. Version 2.480beta (used in the FTOOLS 5.3 release, 1 Nov 2003) New Routines: - fits_get_eqcoltype - just like fits_get_coltype, except in the case of scaled integer columns, it returns the 'equivalent' data type that is necessary to store the scaled data values. - fits_split_names - splits an input string containing a comma or space delimited list of names (typically file names or column names) into individual name tokens. Enhancements: - changed fhist in histo.c so that it can make histograms of ASCII table columns as well as binary table columns (as long as they contain numeric data). Bug fixes: - removed an erroneous reference to listhead.c in makefile.vcc, that is used to build the cfitsio dll under Windows. This caused a 'main' routine to be added to the library, which causes problems when linking fortran programs to cfitsio under windows. - if an error occurs when opening for a 2nd time (with ffopen) a file that is already open (e.g., the specified extension doesn't exist), and if the file had been modified before attempting to reopen it, then the modified buffers may not get written to disk and the internal state of the file may become corrupted. ffclos was modified to always set status=0 before calling ffflsh if the file has been concurrently opened more than once. Version 2.470 - 18 August 2003 Enhancements: - defined 'TSBYTE' to represent the 'signed char' datatype (similar to 'TBYTE' that represents the 'unsigned char' datatype) and added support for this datatype to all the routines that read or write data to a FITS image or table. This was implemented by adding 2 new C source code files to the package: getcolsb.c and putcolsb.c. - Defined a new '1S' shorthand data code for a signed byte column in a binary table. CFITSIO will write TFORMn = '1B' and TZEROn = -128 in this case, which is the convention used to store signed byte values in a 'B' type column. - in fitsio2.h, added test of whether `__x86_64__` is defined, to support the new AMD Opteron 64-bit processor - modified configure to not use the -fast compiler flag on Solaris platforms when using the proprietary Solaris cc compiler. This flag causes compilation problems in eval_y.c (compiler just hangs forever). Bug fixes: - In the special case of writing 0 elements to a vector table column that contains 0 rows, ffgcpr no longer adds a blank row to the table. - added error checking code for cases where a ASCII string column in a binary table is greater than 28800 characters wide, to avoid going into an infinite loop. - the fits_get_col_display_width routine was incorrectly returning width = 0 for a 'A' binary table column that did not have an explicit vector length character. Version 2.460 - 20 May 2003 Enhancements: - modified the HTTP driver in drvrnet.c so that CFITSIO can read FITS files via a proxy HTTP server. (This code was contributed by Philippe Prugniel, Obs. de Lyon). To use this feature, the 'http_proxy' environment variable must be defined with the address (URL) and port number of the proxy server, i.e., > setenv http_proxy http://heasarc.gsfc.nasa.gov:3128 will use port 3128 on heasarc.gsfc.nasa.gov - suppressed some compiler warnings by casting a variable of type 'size_t' to type 'int' in fftkey (in fitscore.c) and iraftofits and irafrdimge (in iraffits.c). Version 2.450 - 30 April 2003 Enhancements: - modified the WCS keyword reading routine (ffgics) to support cases where some of the CDi_j keywords are omitted (with an assumed value = 0). - Made a change to http_open_network in drvrnet.c to add a 'Host: ' string to the open request. This is required by newer HTTP 1.1 servers (so-called virtual servers). - modified ffgcll (read logical table column) to return the illegal character value itself if the FITS file contains a logical value that is not equal to T, F or zero. Previously it treated this case the same as if the FITS file value was = 0. - modified fits_movnam_hdu (ffmnhd) so that it will move to a tile- compressed image (that is stored in a binary table) if the input desired HDU type is BINARY_TBL as well as if the HDU type = IMAGE_HDU. Bug fixes: - in the routine that checks the data fill bytes (ffcdfl), the call to ffmbyt should not ignore an EOF error when trying to read the bytes. This is a little-used routine that is not called by any other CFITSIO routine. - fits_copy_file was not reporting an error if it hit the End Of File while copying the last extension in the input file to the output file. - fixed inconsistencies in the virtual file column filter parser (ffedit_columns) to properly support expressions which create or modify a keyword, instead of a column. Previously it was only possible to modify keywords in a table extension (not an image), and the keyword filtering could cause some of the table columns to not get propagated into the virtual file. Also, spaces are now allowed within the specified keyword comment field. - ffdtyp was incorrectly returning the data type of FITS keyword values of the form '1E-09' (i.e., an exponential value without a decimal point) as integer rather than floating point. - The enhancement in the previous 2.440 release to allow more files to be opened at one time introduced a bug: if ffclos is called with a non-zero status value, then any subsequent call to ffopen will likely cause a segmentation fault. The fits_clear_Fptr routine was modified to fix this. - rearranged the order of some computations in fits_resize_img so as to not exceed the range of a 32-bit integer when dealing with large images. - the template parser routine, ngp_read_xtension, was testing for "ASCIITABLE" instead of "TABLE" as the XTENSION value of an ASCII table, and it did not allow for optional trailing spaces in the IMAGE" or "TABLE" string value. Version 2.440 - 8 January 2003 Enhancements: - modified the iterator function, ffiter, to operate on random groups files. - decoupled the NIOBUF (= 40) parameter from the limit on the number FITS files that can be opened, so that more files may be opened without the overhead of having to increase the number of NIOBUF buffers. A new NMAXFILES parameter is defined in fitsio2.h which sets the maximum number of opened FITS files. It is set = 300 by default. Note however, that the underlying compiler or operating system may not allow this many files to be opened at one time. - updated the version of cfortran.h that is distributed with CFITSIO from version 3.9 to version 4.4. This required changes to f77_wrap.h and f77_wrap3.c. The original cfortran.h v4.4 file was modified slightly to support CFITSIO and ftools (see comments in the header of cfortran.h). - modified ffhist so that it copies all the non-structural keywords from the original binary table header to the binned image header. - modified fits_get_keyclass so that it recognizes EXTNAME = COMPRESSED_IMAGE as a special tile compression keyword. - modified Makefile.in to support the standard --prefix convention for specifying the install target directory. Bug fixes: - in fits_decompress_img, needed to add a call to ffpscl to turn off the BZERO and BSCALE scaling when reading the compressed image. Version 2.430 - 4 November 2002 Enhancements: - modified fits_create_hdu/ffcrhd so that it returns without doing anything and does not generate an error if the current HDU is already an empty HDU. There is no need in this case to append a new empty HDU to the file. - new version of group.c (supplied by B. O'Neel at the ISDC) fixes 2 limitations: 1 - Groups now have 256 characters rather than 160 for the path lengths in the group tables. - ISDC SPR 1720. 2 - Groups now can have backpointers longer than 68 chars using the long string convention. - ISDC SPR 1738. - small change to f77_wrap.h and f77_wrap3.c to support the fortran wrappers on SUN solaris 64-bit sparc systems (see also change to v2.033) - small change to find_column in eval_f.c to support unsigned long columns in binary tables (with TZEROn = 2147483648.0) - small modification to cfortran.h to support Mac OS-X, (Darwin) Bug fixes: - When reading tile-compress images, the BSCALE and BZERO scaling keywords were not being applied, if present. - Previous changes to the error message stack code caused the tile compressed image routines to not clean up spurious error messages properly. - fits_open_image was not skipping over null primary arrays. Version 2.420 - 19 July 2002 Enhancements: - modified the virtual filename parser to support exponential notation when specifying the min, max or binsize in a binning specifier, as in: myfile.fits[binr X=1:10:1.0E-01, Y=1:10:1.0E-01] - removed the limitation on the maximum number of HDUs in a FITS file (limit used to be 1000 HDUs per file). Now any number of HDUs can be written/read in a FITS file. (BUT files that have huge numbers of HDUs can be difficult to manage and are not recommended); - modified grparser.c to support HIERARCH keywords, based on code supplied by Richard Mathar (Max-Planck) - moved the ffflsh (fits_flush_buffer) from the private to the public interface, since this routine may be useful for some applications. It is much faster than ffflus. - small change to the definition of OFF_T in fitsio.h to support large files on IBM AIX operating systems. Bug fixes: - fixed potential problem reading beyond array bounds in ffpkls. This would not have affected the content of any previously generated FITS files. - in the net driver code in drvrnet.c, the requested protocol string was changed from "http/1.0" to "HTTP/1.0" to support apache 1.3.26. - When using the virtual file syntax to open a vector cell in a binary table as if it were a primary array image, there was a bug in fits_copy_image_cell which garbled the data if the vector was more than 30000 bytes long. - fixed problem that caused fits_report_error to crash under Visual C++ on Windows systems. The fix is to use the '/MD' switch on the cl command line, or, in Visual Studio, under project settings / C++ select use runtime library multithreaded DLL - modified ffpscl so it does not attempt to reset the scaling values in the internal structure if the image is tile-compressed. - fixed multiple bugs in mem_rawfile_open which affected the case where a raw binary file is read and converted on the fly into a FITS file. - several small changes to group.c to suppress compiler warnings. Version 2.410 - 22 April 2002 (used in the FTOOLS 5.2 release) New Routines: - fits_open_data behaves similarly to fits_open_file except that it also will move to the first HDU containing significant data if and an explicit HDU name or number to open was not specified. This is useful for automatically skipping over a null primary array when opening the file. - fits_open_table and fits_open_image behaves similarly to fits_open_data, except they move to the first table or image HDU in the file, respectively. - fits_write_errmark and fits_clear_errmark routines can be use to write an invisible marker to the CFITSIO error stack, and then clear any more recent messages on the stack, back to that mark. This preserves any older messages on the stack. - fits_parse_range utility routine parses a row list string and returns integer arrays giving the min and max row in each range. - fits_delete_rowrange deletes a specified list of rows or row ranges. - fits_copy_file copies all or part of the HDUs in the input file to the output file. - added fits_insert_card/ffikey to the publicly defined set of routines (previously, it was a private routine). Enhancements: - changed the default numeric display format in ffgkys from 'E' format to 'G' format, and changed the format for 'X' columns to a string of 8 1s or 0s representing each bit value. - modified ffflsh so the system 'fflush' call is not made in cases where the file was opened with 'READONLY' access. - modified the output filename parser so the "-.gz", and "stdout.gz" now cause the output file to be initially created in memory, and then compressed and written out to the stdout stream when the file is closed. - modified the routines that delete rows from a table to also update the variable length array heap, to remove any orphaned data from the heap. - modified ffedit_columns so that wild card characters may be used when specifying column names in the 'col' file filter specifier (e.g., file.fits[col TIME; *RAW] will create a virtual table contain only the TIME column and any other columns whose name ends with 'RAW'). - modified the keyword classifier utility, fits_get_keyclass, to support cases where the input string is just the keyword name, not the entire 80-character card. - modified configure.in and configure to see if a proprietary C compiler is available (e.g. 'cc'), and only use 'gcc' if not. - modified ffcpcl (copy columns from one table to another) so that it also copies any WCS keywords related to that column. - included an alternate source file that can be used to replace compress.c, which is distributed under the GNU General Public License. The alternate file contains non-functional stubs for the compression routines, which can be used to make a version of CFITSIO that does not have the GPL restrictions (and is also less functional since it cannot read or write compressed FITS files). - modifications to the iterator routine (ffiter) to support writing tile compressed output images. - modified ffourl to support the [compress] qualifier when specifying the optional output file name. E.g., file.fit(out.file[compress])[3] - modified imcomp_compress_tile to fully support implicit data type conversion when writing to tile-compressed images. Previously, one could not write a floating point array to an integer compressed image. - increased the number of internal 2880-byte I/O buffers allocated by CFITSIO from 25 to 40, in recognition of the larger amount of memory available on typical machines today compared with a few years ago. The number of buffers can be set by the user with the NIOBUF parameter in fitsio2.h. (Setting this too large can actually hurt performance). - modified the #if statements in fitsio2.h, f77_wrap.h and f77_wrap1.c to support the new Itanium 64-bit Intel PC. - a couple minor modifications to fitsio.h needed to support the off_t datatype on Debian linux systems. - increased internal buffer sizes in ffshft and ffsrow to improve the I/O performance. Bug fixes: - fits_get_keyclass could sometimes try to append to an unterminated string, causing an overflow of a string array. - fits_create_template no longer worked because of improvements made to other routines. Had to modify ffghdt to not try to rescan the header keywords if the file is still empty and contains no keywords yet. - ffrtnm, which returns the root filename, sometimes did not work properly when testing if the 'filename+n' convention was used for specifying an extension number. - fixed minor problem in the keyword template parsing routine, ffgthd which in rare cases could cause an improperly terminated string to be returned. - the routine to compare 2 strings, ffcmps, failed to find a match in comparing strings like "*R" and "ERROR" where the match occurs on the last character, but where the same matching character occurs previously in the 2nd string. - the region file reading routine (ffrrgn) did not work correctly if the region file (created by POW and perhaps other programs) had an 'exclude' region (beginning with a '-' sign) as the first region in the file. In this case all points outside the excluded region should be accepted, but in fact no points were being accepted in this case. Version 2.401 - 28 Jan 2002 - added the imcopy example program to the release (and Makefile) Bug fixes: - fixed typo in the imcompress code which affected compression of 3D datacubes. - made small change to fficls (insert column) to allow colums with TFORMn = '1PU' and '1PV' to be inserted in a binary table. The 'U' and 'V' are codes only used within CFITSIO to represent unsigned 16-bit and 32-bit integers; They get replaced by '1PI' and '1PJ' respectively in the FITS table header, along with the appropriate TZEROn keyword. Version 2.400 - 18 Jan 2002 (N.B.: Application programs must be recompiled, not just relinked with the new CFITSIO library because of changes made to fitsio.h) New Routines: - fits_write_subset/ffpss writes a rectangular subset (or the whole image) to a FITS image. - added a whole new family of routines to read and write arrays of 'long long' integers (64-bit) to FITS images or table columns. The new routine names all end in 'jj': ffpprjj, ffppnjj, ffp2djj, ffp3djj, ffppssjj, ffpgpjj, ffpcljj, ffpcnjj. ffgpvjj, ffgpfjj, ffg2djj, ffg3djj, ffgsvjj, ffgsfjj, ffggpjj, ffgcvjj, and ffgcfjj. - added a set of helper routines that are used in conjunction with the new support for tiled image compression. 3 routines set the parameters that should be used when CFITSIO compresses an image: fits_set_compression_type fits_set_tile_dim fits_set_noise_bits 3 corresponding routines report back the current settings: fits_get_compression_type fits_get_tile_dim fits_get_noise_bits Enhancements: - major enhancement was made to support writing to tile-compressed images. In this format, the image is divided up into a rectangular grid of tiles, and each tile of pixels is compressed individually and stored in a row of a variable-length array column in a binary table. CFITSIO has been able to transparently read this compressed image format ever since version 2.1. Now all the CFITSIO image writing routines also transparently support this format. There are 2 ways to force CFITSIO to write compressed images: 1) call the fits_set_compression_type routine before writing the image header keywords, or 2), specify that the image should be compressed when entering the name of the output FITS file, using a new extended filename syntax. (examples: "myfile.fits[compress]" will use the default compression parameters, and "myfile.fits[compress GZIP 100,100] will use the GZIP compression algorithm with 100 x 100 pixel tiles. - added new driver to support creating output .gz compressed fits files. If the name of the output FITS file to be created ends with '.gz' then CFITSIO will initially write the FITS file in memory and then, when the FITS file is closed, CFITSIO will gzip the entire file before writing it out to disk. - when over-writing vectors in a variable length array in a binary table, if the new vector to be written is less than or equal to the length of the previously written vector, then CFITSIO will now reuse the existing space in the heap, rather than always appending the new array to the end of the heap. - modified configure.in to support building cfitsio as a dynamic library on Mac OS X. Use 'make shared' like on other UNIX platforms, but a .dylib file will be created instead of .so. If installed in a nonstandard location, add its location to the DYLD_LIBRARY_PATH environment variable so that the library can be found at run time. - made various modifications to better support the 8-byte long integer datatype on more platforms. The 'LONGLONG' datatype is typedef'ed to equal 'long long' on most Unix platforms and MacOS, and equal to '__int64' on Windows machines. - modified configure.in and makefile.in to better support cases where the system has no Fortran compiler and thus the f77 wrapper routines should not be compiled. - made small modification to eval.y and eval_y.f to get rid of warning on some platforms about redefinition of the 'alloca'. Bug fixes: - other recent bug fixes in ffdblk (delete blocks) caused ffdhdu (delete HDU) to fail when trying to replace the primary array with a null primary array. - fixed bug that prevented inserting a new variable length column into a table that already contained variable length data. - modified fits_delete_file so that it will delete the file even if the input status value is not equal to zero. - in fits_resize_image, it was sometimes necessary to call ffrdef to force the image structure to be defined. - modified the filename parser to support input files with names like: "myfile.fits.gz(mem://tmp)" in which the url type is specified for the output file but not for the input file itself. This required modifications to ffiurl and ffrtnm. Version 2.301 - 7 Dec 2001 Enhancements: - modified the http file driver so that if the filename to be opened contains a '?' character (most likely a cgi related string) then it will not attempt to append a .gz or .Z as it would normally do. - added support for the '!' clobber character when specifying the output disk file name in CFITSIO's extended filename syntax, e.g., 'http://a.b.c.d/myfile.fits.gz(!outfile.fits)' - added new device driver which is used when opening a compressed FITS file on disk by uncompressing it into memory with READWRITE access. This happens when specifying an output filename 'mem://'. - added 2 other device drivers to open http and ftp files in memory with write access. - improved the error trapping and reporting in cases where program attempts to write to a READONLY file (especially in cases where the 'file' resides in memory, as is the case when opening an ftp or http file. - modified the extended filename parser so that it is does not confuse the bracket character '[' which is sometimes used in the root name of files of type 'http://', as the start of an extname or row filter expression. If the file is of type 'http://', the parser now checks to see if the last character in the extended file name is a ')' or ']'. If not, it does not try to parse the file name any further. - improved the efficiency when writing FITS files in memory, by initially allocating enough memory for the entire HDU when it is created, rather than incrementally reallocing memory 2880 bytes at a time (modified ffrhdu and mem_truncate). This change also means that the program will fail much sooner if it cannot allocate enough memory to hold the entire FITS HDU. Bug fixes: - There was an error in the definition of the Fortran ftphtb wrapper routine (writes required ASCII table header keywords) that caused it to fail on DEC OSF and other platforms where sizeof(long) = 8. Version 2.300 - 23 Oct 2001 New Routines: - fits_comp_img and fits_decomp_img are now fully supported and documented. These routine compress and decompress, respective, a FITS image using a new algorithm in which the image is first divided into a grid of rectangular tiles, then the compressed byte stream from each tile is stored in a row of a binary table. CFITSIO can transparently read FITS images stored in this compressed format. Compression ratios of 3 - 6 are typically achieved. Large compression ratios are achieved for floating point images by throwing away non-significant noise bits in the pixel values. - fits_test_heap tests the integrity of the binary table heap and returns statistics on the amount of unused space in the heap and the amount of space that is pointed to by more than 1 descriptor. - fits_compress_heap which will reorder the arrays in the binary table heap, recovering any unused space. Enhancements: - made substantial internal changes to the code to support FITS files containing 64-bit integer data values. These files have BITPIX = 64 or TFORMn = 'K'. This new feature in CFITSIO is currently only enabled if SUPPORT_64BIT_INTEGERS is defined = 1 in the beginning of the fitsio2.h file. By default support for 64-bit integers is not enabled. - improved the ability to read and return a table column value as a formatted string by supporting quasi-legal TDISPn values which have a lowercase format code letter, and by completely ignoring other unrecognizable TDISPn values. Previously, unrecognized TDISPn values could cause zero length strings to be returned. - made fits_write_key_longstr more efficient when writing keywords using the long string CONTINUE convention. It previously did not use all the available space on each card when the string to be written contained many single quote characters. - added a new "CFITSIO Quick Start Guide" which provides all the basic information needed to write C programs using CFITSIO. - updated the standard COMMENT keywords that are written at the beginning of every primary array to refer to the newly published FITS Standard document in Astronomy and Astrophysics. Note: because of this change, any FITS file created with this version of CFITSIO will not be identical to the same file written with a previous version of CFITSIO. - replaced the 2 routines in pliocomp.c with new versions provided by D Tody and N Zarate. These routines compress/uncompress image pixels using the IRAF pixel list compression algorithm. - modified fits_copy_hdu so that when copying a Primary Array to an Image extension, the COMMENT cards which give the reference to the A&A journal article about FITS are not copied. In the inverse case the COMMENT keywords are inserted in the header. - modified configure and Makefile.in to add capability to build a shared version of the CFITSIO library. Type 'make shared' or 'make libcfitsio.so' to invoke this option. - disabled some uninformative error messages on the error stack: 1) when calling ffclos (and then ffchdu) with input status > 0 2) when ffmahd tries to move beyond the end of file. The returned status value remains the same as before, but the annoying error messages no longer get written to the error stack. - The syntax for column filtering has been modified so that if one only specifies a list of column names, then only those columns will be copied into the output file. This provides a simple way to make a copy of a table containing only a specified list of columns. If the column specifier explicitly deletes a column, however, than all the other columns will be copied to the filtered input file, regardless of whether the columns were listed or not. Similarly, if the expression specifies only a column to be modified or created, then all the other columns in the table will be copied. mytable.fit[1][col Time;Rate] - only the Time and Rate columns will be copied to the filtered input file. mytable.fit[1][col -Time ] - all but the Time column are copied to the filtered input file. mytable.fit[1][col Rate;-Time] - same as above. - changed a '#if defined' statement in f77_wrap.h and f77_wrap1.c to support the fortran wrappers on 64-bit IBM/RS6000 systems - modified group.c so that when attaching one group (the child) to another (the parent), check in each file for the existence of a pointer to the other before adding the link. This is to prevent multiple links from forming under all circumstances. - modified the filename parser to accept 'STDIN', 'stdin', 'STDOUT' and 'stdout' in addition to '-' to mean read the file from standard input or write to standard output. - Added support for reversing an axis when reading a subsection of a compressed image using the extended filename syntax, as in myfile.fits+1[-*, *] or myfile.fits+1[600:501,501:600] - When copying a compressed image to a uncompressed image, the EXTNAME keyword is no longer copied if the value is equal to 'COMPRESSED_IMAGE'. - slight change to the comment field of the DATE keyword to reflect the fact that the Unix system date and time is not true UTC time. Bug fixes: - fits_write_key_longstr was not writing the keyword if a null input string value was given. - writing data to a variable length column, if that binary table is not the last HDU in the FITS file, might overwrite the following HDU. Fixed this by changing the order of a couple operations in ffgcpr. - deleting a column from a table containing variable length columns could cause the last few FITS blocks of the file to be reset = 0. This bug occurred as a result of modifications to ffdblk in v2.202. This mainly affects users of the 'compress_fits' utility program. - fixed obscure problem when writing bits to a variable length 'B' column. - when reading a subsection of an image, the BSCALE and BZERO pixel scaling may not have been applied when reading image pixel values (even though the scaling keywords were properly written in the header). - fits_get_keyclass was not returning 'TYP_STRUCT_KEY' for the END keyword. Version 2.204 - 26 July 2001 Bug fixes: - Re-write of fits_clean_url in group.c to solve various problems with invalid bounds checking. Version 2.203 - 19 July 2001 (version in FTOOLS v5.1) Enhancements: - When a row selection or calculator expression is written in an external file (and read by CFITSIO with the '@filename' syntax) the file can now contain comment lines. The comment line must begin with 2 slash characters as the first 2 characters on the line. CFITSIO will ignore the entire line when reading the expression. Bug fixes: - With previous versions of CFITSIO, the pixel values in a FITS image could be read incorrectly in the following case: when opening a subset of a FITS image (using the 'filename.fits[Xmin:Xmax,Ymin:Ymax]' notation) on a PC linux, PC Windows, or DEC OSF machine (but not on a SUN or Mac). This problem only occurs when reading more than 8640 bytes of data (2160 4-byte integers) at a time, and usually only occurs if the reading program reads the pixel data immediately after opening the file, without first reading any header keywords. This error would cause strips of zero valued pixels to appear at semi-random positions in the image, where each strip usually would be 2880 bytes long. This problem does not affect cases where the input subsetted image is simply copied to a new output FITS file. Version 2.202 - 22 May 2001 Enhancements: - revised the logic in the routine that tests if a point is within a region: if the first region is an excluded region, then it implicitly assumes a prior include region covering the entire detector. It also now supports cases where a smaller include region is within a prior exclude region. - made enhancement to ffgclb (read bytes) so that it can also read values from a logical column, returning an array of 1s and 0s. - defined 2 new grouping error status values (349, 350) in cfitsio.h and made minor changes to group.c to use these new status values. - modified fits_open_file so that if it encounters an error while trying to move to a user-specified extension (or select a subset of the rows in an input table, or make a histogram of the column values) it will close the input file instead of leaving it open. - when using the extended filename syntax to filter the rows in an input table, or create a histogram image from the values in a table column, CFITSIO now writes HISTORY keywords in the output file to document the filtering expression that was used. Bug fixes: - ffdblk (called by ffdrow) could overwrite the last FITS block(s) in the file in some cases where one writes data to a variable length column and then calls ffdrow to delete rows in the table. This bug was similar to the ffiblk bug that was fixed in v2.033. - modified fits_write_col_null to fix a problem which under unusual circumstances would cause a End-of-File error when trying to read back the value in an ASCII string column, after initializing if by writing a null value to it. - fixed obscure bug in the calculator function that caused an error when trying to modify the value of a keyword in a HDU that does not have a NAXIS2 keyword (e.g., a null primary array). - the iterator function (in putcol.c) had a bug when calculating the optimum number rows to process in the case where the table has very wide rows (>33120 bytes) and the calculator expression involves columns from more than one FITS table. This could cause an infinite loop in calls to the ffcalc calculator function. - fixed bug in ffmvec, which modifies the length of an existing vector column in a binary table. If the vector was reduced in length, the FITS file could sometimes be left in a corrupted state, and in all cases the values in the remaining vector elements of that column would be altered. - in drvrfile.c, replaced calls to fsetpos and fgetpos with fseek and ftell (or fseeko and ftello) because the fpos_t filetype used in fsetpos is incompatible with the off_t filetype used in fseek, at least on some platforms (Linux 7.0). (This fix was inserted into the V2.201 release on April 4). - added "#define fits_write_pixnull ffppxn" to longnam.h Version 2.201 - 15 March 2001 Enhancements - enhanced the keyword reading routines so that they will do implicit datatype conversion from a string keyword value to a numeric keyword value, if the string consist of a valid number enclosed in quotes. For example, the keyword mykey = '37.5' can be read by ffgkye. - modified ffiimg so that it is possible to insert a new primary array at the beginning of the file. The original primary array is then converted into an IMAGE extension. - modified ffcpdt (copy data unit) to support the case where the data unit is being copied between 2 HDUs in the same file. - enhanced the fits_read_pix and fits_read_pixnull routines so that they support the tiled image compression format that the other image reading routines also support. - modified the Extended File Name syntax to also accept a minus sign (-) as well as an exclamation point (!) as the leading character when specifying a column or or keyword to be deleted, as in [col -time] will delete the TIME column. - now completely support reading subimages, including pixel increments in each dimension, for tile-compressed images (where the compressed image tiles are stored in a binary table). Bug fixes: - fixed confusion in the use of the fpos_t and off_t datatypes in the fgetpos and fsetpos routines in drvrfile.c which caused problems with the Windows VC++ compiler. (fpos_t is not necessarily identical to off_t) - fixed a typo in the fits_get_url function in group.c which caused problems when determining the relative URL to a compressed FITS file. - included fitsio.h in the shared memory utility program, smem.c, in order to define OFF_T. - fixed typo in the datatype of 'nullvalue' in ffgsvi, which caused attempts to read subsections of a short integer tiled compressed image to fail with a bus error. - fixed bug in ffdkey which sometimes worked incorrectly if one tried to delete a nonexistent keyword beyond the end of the header. - fixed problem in fits_select_image_section when it writes a dummy value to the last pixel of the section. If the image contains scaled integer pixels, then in some cases the pixel value could end up out of range. - fixed obscure bug in the ffpcn_ family of routines which gave a floating exception when trying to write zero number of pixels to a zero length array (why would anyone do this?) Version 2.200 - 26 Jan 2001 Enhancements - updated the region filtering code to support the latest region file formats that are generated by the POW, SAOtng and ds9 programs. Region positions may now be given in HH:MM:SS.s, DD:MM:SS.s format, and region sizes may be given arcsec or arcmin instead of only in pixel units. Also changed the logic so that if multiple 'include' regions are specified in the region file, they are ORed together, instead of ANDed, so that the filtering keeps points that are located within any of the 'include' regions, not just the intersection of the regions. - added support for reading raw binary data arrays by converting them on the fly into virtual FITS files. - modified ffpmsg, which writes error messages to CFITSIO's internal error stack, so that messages > 80 characters long will be wrapped around into multiple 80 character messages, instead of just being truncated at 80 characters. - modified the CFITSIO parser so that expression which involve scaled integer columns get cast to double rather than int. - Modified the keyword template parsing routine, ffgthd, to support the HIERARCH keyword. - modified ffainit and ffbinit so that they don't unnecessarily allocate 0 bytes of memory if there are no columns (TFIELDS = 0) in the table that is being opened. - modified fitsio2.h to support NetBSD on Alpha OSF platforms (NetBSD does not define the '__unix__' symbol). - changed the way OFF_T is defined in fitsio.h for greater portability. - changed drvrsmem.c so it is compiled only when HAVE_SHMEM_SERVICES is defined in order to removed the conditional logic from the Makefile - reorganized the CFITSIO User's guide to make it clearer and easier for new users to learn the basic routines. - fixed ffhdef (which reserves space for more header keywords) so that is also updates the start position of the next HDU. This affected the offset values returned by ffghof. Version 2.100 - 18 Oct 2000 Enhancements - made substantial modification to the code to support Large files, i.e., files larger than 2**31 bytes = 2.1GB. FITS files up to 6 terabytes in size may now be read and written on platforms that support Large files (currently only Solaris). - modified ffpcom and ffphis, which write COMMENT and HISTORY keywords, respectively, so that they now use columns 9 - 80, instead of only columns 11 - 80. Previously, these routines avoided using columns 9 and 10, but this is was unnecessarily restrictive. - modified ffdhdu so that instead of refusing to delete the primary array, it will replace the current primary array with a null primary array containing the bare minimum of required keywords and no data. New Routines - fits_read_pix, fits_read_pixnull, fits_read_subset, and fits_write_pix routines were added to enable reading and writing of Large images, with more than 2.1e9 pixels. These new routines are now recommended as the basic routines for reading and writing all images. - fits_get_hduoff returns the byte offset in the file to the start and end of the current HDU. This routine replaces the now obsolete fits_get_hduaddr routine; it uses 'off_t' instead of 'long' as the datatype of the arguments and can support offsets in files greater than 2.1GB in size. Bug fixes: - fixed bug in fits_select_image_section that caused an integer overflow when reading very large image sections (bigger than 8192 x 8192 4-byte pixels). - improved ffptbb, the low-level table writing routine, so that it will insert additional rows in the table if the table is not already big enough. Previously it would have just over- written any HDUs following the table in the FITS file. - fixed a bug in the fits_write_col_bit/ffpclx routine which could not write to a bit 'X' column if that was the first column in the table to be written to. This bug would not appear if any other datatype column was written to first. - non-sensible (but still formally legal) binary table TFORM values such as '8A15', or '1A8' or 'A8' would confuse CFITSIO and cause it to return a 308 error. When parsing the TFORMn = 'rAw' value, the ffbnfm routine has been modified to ignore the 'w' value in cases where w > r. - fixed bug in the blsearch routine in iraffits.c which sometimes caused an out-of-bounds string pointer to be returned when searching for blank space in the header just before the 'END' keyword. - fixed minor problem in ffgtcr in group.c, which sometimes failed while trying to move to the end of file before appending a grouping table. - on Solaris, with Sun CC 5.0, one must check for '__unix' rather than '__unix__' or 'unix' as it's symbol. Needed to modify this in drvrfile.c in 3 places. - in ffextn, the FITS file would be left open if the named extension doesn't exist, thus preventing the file from being opened again later with write access. - fixed bug in ffiimg that would cause attempts to insert a new image extension following a table extension, and in front of any other type of extension, to fail. Version 2.037 - 6 July 2000 Enhancements - added support in the extended filename syntax for flipping an image along any axis either by specifying a starting section pixel number greater than the ending pixel number, or by using '-*' to flip the whole axis. Examples: "myfile.fits[1:100, 50:10]" or "myfile.fits[-*,*]". - when reading a section of an image with the extended filename syntax (e.g. image.fits[1:100:2, 1:100:2), any CDi_j WCS keywords will be updated if necessary to transfer the world coordinate system from the input image to the output image section. - on UNIX platforms, added support for filenames that begin with "~/" or "~user/". The "~" symbol will get expanded into a string that gives the user's home directory. - changed the filename parser to support disk file names that begin with a minus sign. Previously, the leading minus sign would cause CFITSIO to try to read/write the file from/to stdin/stdout. - modified the general fits_update_key routine, which writes or updates a keyword value, to use the 'G' display format instead of the 'E' format for floating point keyword values. This will eliminate trailing zeros from appearing in the value. - added support for the "-CAR" celestial coordinate projection in the ffwldp and ffxypx routines. The "-CAR" projection is the default simplest possible linear projection. - added new fits_create_memfile/ffimem routine to create a new fits file at a designated memory location. - ported f77_wrap.h and f77_wrap1.c so that the Fortran interface wrappers work correctly on 64-bit SGI operating systems. In this environment, C 'long's are 8-bytes long, but Fortran 'integers' are still only 4-bytes long, so the words have to be converted by the wrappers. - minor modification to cfortran.h to automatically detect when it is running on a linux platform, and then define f2cFortran in that case. This eliminates the need to define -Df2cFortran on the command line. - modified group.c to support multiple "/" characters in the path name of the file to be opened/created. - minor modifications to the parser (eval.y, eval_f.c, eval_y.c) to a) add the unary '+' operator, and b) support copying the TDIMn keyword from the input to the output image under certain circumstances. - modified the lexical parser in eval_l.y and eval_l.c to support #NULL and #SNULL constants which act to set the value to Null. Support was also added for the C-conditional expression: 'Boolean ? trueVal : falseVal'. - small modification to eval_f.c to write an error message to the error stack if numerical overflow occurs when evaluating an expression. - configure and configure.in now support the egcs g77 compiler on Linux platforms. Bug fixes: - fixed a significant bug when using the extended filename binning syntax to generate a 2-dimensional image from a histogram of the values in 2 table columns. This bug would cause table events that should have been located in the row just below the bottom row of the image (and thus should have been excluded from the histogram) to be instead added into the first row of the image. Similarly, the first plane of a 3-D or 4-D data cube would include the events that should have been excluded as falling in the previous plane of the cube. - fixed minor bug when parsing an extended filename that contains nested pairs of square brackets (e.g., '[col newcol=oldcol[9]]'). - fixed bug when reading unsigned integer values from a table or image with fits_read_col_uint/ffgcvuk. This bug only occurred on systems like Digital Unix (now Tru64 Unix) in which 'long' integers are 8 bytes long, and only when reading more than 7200 elements at a time. This bug would generally cause the program to crash with a segmentation fault. - modified ffgcpr to update 'heapstart' as well as 'numrows' when writing more rows beyond the end of the table. heapstart is needed to calculate if more space needs to be inserted in the table when inserting columns into the table. - modified fficls (insert column), ffmvec, ffdrow and ffdcol to not use the value of the NAXIS2 keyword as the number of rows in the table, and instead use the value that is stored in an internal structure, because the keyword value may not be up to date. - Fixed bug in the iterator function that affected the handling of null values in string columns in ASCII and binary tables. - Reading a subsample of pixels in very large images, (e.g., file = myfile.fits[1:10000:10,1:10000:10], could cause a long integer overflow (value > 2**31) in the computation of the starting byte offset in the file, and cause a return error status = 304 (negative byte address). This was fixed by changing the order of the arithmetic operations in calculating the value of 'readptr' in the ffgcli, ffgclj, ffgcle, ffgcld, etc. routines. - In version 2.031, a fix to prevent compressed files from being opened with write privilege was implemented incorrectly. The fix was intended to not allow a compressed FITS file to be opened except when a local uncompressed copy of the file is being produced (then the copy is opened with write access), but in fact the opposite behavior occurred: Compressed files could be opened with write access, EXCEPT when a local copy is produced. This has been fixed in the mem_compress_open and file_compress_open routines. - in iraffits.c, a global variable called 'val' caused multiply defined symbols warning when linking cfitsio and IRAF libraries. This was fixed by making 'val' a local variable within the routine. Version 2.036 - 1 Feb 2000 - added 2 new generic routines, ffgpf and ffgcf which are analogous to ffgpv and ffgcv but return an array of null flag values instead of setting null pixels to a reserved value. - minor change to eval_y.c and eval.y to "define alloca malloc" on all platforms, not just VMS. - added support for the unsigned int datatype (TUINT) in the generic ffuky routine and changed ffpky so that unsigned ints are cast to double instead of long before being written to the header. - modified ffs2c so that if a null string is given as input then a null FITS string (2 successive single quotes) will be returned. Previously this routine would just return a string with a single quote, which could cause an illegal keyword record to be written. - The file flush operation on Windows platforms apparently changes the internal file position pointer (!) in violation of the C standard. Put a patch into the file_flush routine to explicitly seek back to the original file position. - changed the name of imcomp_get_compressed_image_parms to imcomp_get_compressed_image_par to not exceed the 31 character limit on some compilers. - modified the filename parser (which is used when moving to a named HDU) to support EXTNAME values which contain embedded blanks. - modified drvrnet.c to deal with ftp compressed files better so that even fits files returned from cgi queries which have the wrong mime types and/or wrong types of file names should still decompress. - modified ffgics to reduce the tolerance for acceptable skewness between the axes, and added a new warning return status = APPROX_WCS_KEY in cases where there is significant skewness between the axes. - fixed bug in ffgics that affected cases where the first coordinate axis was DEC, not RA, and the image was a mirror image of the sky. - fixed bug in ffhist when trying to read the default binning factor keyword, TDBIN. - modified ffhist so that is correctly computes the rotation angle in a 2-D image if the first histogram column has a CROTA type keyword but the 2nd column does not. - modified ffcpcl so that it preserves the comment fields on the TTYPE and TFORM keywords when the column is copied to a new file. - make small change to configure.in to support FreeBSD Linux by setting CFLAGS = -Df2cFortran instead of -Dg77Fortran. Then regenerated configure with autoconf 2.13 instead of 2.12. Version 2.035 - 7 Dec 1999 (internal release only, FTOOLS 5.0.2) - added new routine called fits_get_keyclass/ffgkcl that returns the general class of the keyword, e.g., required structural keyword, WCS keyword, Comment keyword, etc. 15 classes of keywords have been defined in fitsio.h - added new routine called fits_get_img_parm/ffgipr that is similar to ffgphd but it only return the bitpix, naxis, and naxisn values. - added 3 new routines that support the long string keyword convention: fits_insert_key_longstr, fits_modify_key_longstr fits_update_key_longstr. - modified ffgphd which reads image header keywords to support the new experimental compressed image format. - when opening a .Z compressed file, CFITSIO tries to allocate memory equal to 3 times the file size, which may be excessive in some cases. This was changed so that if the allocation fails, then CFITSIO will try again to allocate only enough memory equal to 1 times the file size. More memory will be allocated later if this turns out to be too small. - improved the error checking in the fits_insert_key routine to check for illegal characters in the keyword. Version 2.034 - 23 Nov 1999 - enhanced support for the new 'CD' matrix world coordinate system keywords in the ffigics routine. This routine has been enhanced to look for the new 'CD' keywords, if present, and convert them back to the old CDELTn and CROTAn values, which are then returned. The routine will also swap the WCS parameters for the 2 axes if the declination-like axis is the first WCS axis. - modified ffphbn in putkey.c to support the 'U' and 'V" TFORM characters (which represent unsigned short and unsigned int columns) in variable length array columns. (previously only supported these types in fixed length columns). - added checks when reading gzipped files to detect unexpected EOF. Previously, the 'inflate_codes' routine would just sit in an infinite loop if the file ended unexpectedly. - modified fits_verify_chksum/ffvcks so that checksum keywords with a blank value string are treated as undefined, the same as if the keyword did not exist at all. - fixed ffghtb and ffghbn so that they return the extname value in cases where there are no columns in the table. - fixed bug in the ffgtwcs routine (this is a little utility routine to aid in interfacing to Doug Mink's WCS routines); it was not correctly padding the length of string-valued keywords in the returned string. - fixed bug in 'iraffits.c' that prevented Type-2 IRAF images from being correctly byte-swapped on PCs and DEC-OSF machines. - fixed tiny memory leak in irafncmp in iraffits.c. Only relevant when reading IRAF .imh files. - fixed a bug (introduced in version 2.027) that caused the keyword reading routines to sometimes not find a matching keyword if the input name template used the '*' wildcard as the last character. (e.g., if input name = 'COMMENT*' then it would not find the 'COMMENT' keywords. (It would have found longer keywords like 'COMMENTX' correctly). The fix required a minor change to ffgcrd in getkey.c - modified the routine (ffswap8) that does byteswapping of double precision numbers. Some linux systems have reported floating point exceptions because they were trying to interpret the bytes as a double before the bytes had been swapped. - fixed bug in the calculation of the position of the last byte in the string of bits to be read in ffgcxuk and ffgcxui. This bug generally caused no harm, but could cause the routine to exit with an invalid error message about trying to read beyond the size of the field. - If a unix machine did not have '__unix__', 'unix', or '__unix' C preprocessor symbols defined, then CFITSIO would correctly open one FITS file, but would not correctly open subsequent files. Instead it would think that the same file was being opened multiple times. This problem has only been seen on an IBM/AIX machine. The fits_path2url and fits_url2path routines in group.c were modified to fix the problem. - fixed bug in group.c, which affected WINDOWS platforms only, that caused programs to go into infinite loop when trying to open certain files. - the ftrsim Fortran wrapper routine to ffrsim was not defined correctly, which caused the naxis(2) value to be passed incorrectly on Dec OSF machines, where sizeof(long) != sizeof(int). Version 2.033 - 17 Sept 1999 - New Feature: enhanced the row selection parser so that comparisons between values in different rows of the table are allowed, and the string comparisons with <, >, <=, and >= are supported. - added new routine the returns the name of the keyword in the input keyword record string. The name is usually the first 8 characters of the record, except if the HIERARCH convention is being used in which case the name may be up to 67 characters long. - added new routine called fits_null_check/ffnchk that checks to see if the current header contains any null (ASCII 0) characters. These characters are illegal in FITS headers, but they go undetected by the other CFITSIO routines that read the header keywords. - the group.c file has been replaced with a new version as supplied by the ISDC. The changes are mainly to support partial URLs and absolute URLs more robustly. Host dependent directory paths are now converted to true URLs before being read from/written to grouping tables. - modified ffnmhd slightly so that it will move to the first extension in which either the EXTNAME or the HDUNAME keyword is equal to the user-specified name. Previously, it only checked for HDUNAME if the EXTNAME keyword did not exist. - made small change to drvrnet.c so that it uncompress files which end in .Z and .gz just as for ftp files. - rewrote ffcphd (copy header) to handle the case where the input and output HDU are in the same physical FITS file. - fixed bug in how long string keyword values (using the CONTINUE convention) were read. If the string keyword value ended in an '&' character, then fits_read_key_longstr, fits_modify_key_str, and fits_delete_key would interpret the following keyword as a continuation, regardless of whether that keyword name was 'CONTINUE' as required by this convention. There was also a bug in that if the string keyword value was all blanks, then fits_modify_key_str could in certain unusual cases think that the keyword ended in an '&' and go into an infinite loop. - modified ffgpv so that it calls the higher level ffgpv_ routine rather than directly calling the lower level ffgcl_ routine. This change is needed to eventually support reading compressed images. - added 3 new routines to get the image datatype, image dimensions, and image axes length. These support the case where the image is compressed and stored in a binary table. - fixed bug in ffiblk that could sometimes cause it to insert a new block in a file somewhere in the middle of the data, instead of at the end of the HDU. This fortunately is a rare problem, mainly only occurring in certain cases when inserting rows in a binary table that contains variable length array data (i.e., has a heap). - modified fits_write_tdim so that it double checks the TFORMn value directly if the column repeat count stored in the internal structure is not equal to the product of all the dimensions. - fixed bug that prevented ffitab or ffibin from inserting a new table after a null primary array (can't read NAXIS2 keyword). Required a small change to ffrdef. - modified testprog.c so that it will continue to run even if it cannot open or process the template file testprog.tpt. - modified the logic in lines 1182-1185 of grparser.c so that it returns the correct status value in case of an error. - added test in fitsio2.h to see if __sparcv9 is defined; this identifies a machine running Solaris 7 in 64-bit mode where long integers are 64 bits long. Version 2.032 - 25 May 1999 - the distribution .tar file was changed so that all the files will be untarred into a subdirectory by default instead of into the current directory. - modified ffclos so that it always frees the space allocated by the fptr pointer, even when another fptr points to the same file. - plugged a potential (but rare in practice) memory leak in ffpinit - fixed bug in all the ffp3d_ and ffg3d_ routines in cases where the data cube that has been allocated in memory has more planes than the data cube in the FITS file. - modified drvrsmem.c so that it allocates a small shared memory segment only if CFITSIO tries to read or write a FITS file in shared memory. Previously it always allocated the segment whether it was needed or not. Also, this small segment is removed if 0 shared memory segments remain in the system. - put "static" in front of 7 DECLARE macros in compress.c because these global variables were causing conflicts with other applications programs that had variables with the same names. - modified ffasfm to return datatype = TDOUBLE instead of TFLOAT if the ASCII table column has TFORMn = 'Ew.d' with d > 6. - modified the column reading routines to a) print out the offending entry if an error occurs when trying to read a numeric ASCII table column, and b) print out the column number that had the error (the messages are written to CFITSIOs error stack) - major updates to the Fortran FITSIO User's Guide to include many new functions that have been added to CFITSIO in the past year. - modified fitsio2.h so that the test for __D_FLOAT etc. is only made on Alpha VMS machines, to avoid syntax errors on some other platforms. - modified ffgthd so that it recognizes a floating point value that uses the 'd' or 'D' exponent character. - removed the range check in fftm2s that returned an error if 'decimals' was less than zero. A negative value is OK and is used to return only the date and not the time in the string. Version 2.031 - 31 Mar 1999 - moved the code that updates the NAXIS2 and PCOUNT keywords from ffchdu into the lower lever ffrdef routine. This ensures that other routines which call ffrdef will correctly update these 2 keywords if required. Otherwise, for instance, calling fits_write_checksum before closing the HDU could cause the NAXIS2 keyword (number of rows in the table) to not be updated. - fixed bug (introduced in version 2.030) when writing null values to a primary array or image extension. If trying to set more than 1 pixel to null at a time, then typically only 1 null would be written. Also fixed related bug when writing null values to rows in a table that are beyond the currently defined size of the table (the size of the table was not being expanded properly). - enhanced the extended filename parser to support '*' in image section specifiers, to mean use the whole range of the axis. myfile.fits[*,1:100] means use the whole range of the first axis and pixels 1 to 100 in the second axis. Also supports an increment, as in myfile.fits[*:2, *:2] to use just the odd numbered rows and columns. - modified fitscore.c to set the initial max size of the header, when first reading it, to the current size of the file, rather than to 2 x 10**9 to avoid rare cases where CFITSIO ends up writing a huge file to disk. - modified file_compress_open so that it will not allow a compressed FITS file to be opened with write access. Otherwise, a program could write to the temporary copy of the uncompressed file, but the modification would be lost when the program exits. Version 2.030 - 24 Feb 1999 - fixed bug in ffpclu when trying to write a null value to a row beyond the current size of the table (wouldn't append new rows like it should). - major new feature: enhanced the routines that read ASCII string columns in tables so that they can read any table column, including logical and numeric valued columns. The column values are returned as a formatted string. The format is determined by the TDISPn keyword if present, otherwise a default format based on the datatype of the column is used. - new routine: fits_get_col_display_width/ffgcdw returns the length of the formatted strings that will be returned by the routines that read table columns as strings. - major new feature: added support for specifying an 'image section' when opening an image: e.g, myfile.fits[1:512:2,2:512:2] to open a 256x256 pixel image consisting of the odd columns and the even numbered rows of the input image. - added supporting project files and instructions for building CFITSIO under Windows NT with the Microsoft Visual C++ compiler. - changed the variable 'template' to 'templt' in testprog.c since it conflicted with a reserved word on some compilers. - modified group.c to conditionally include sys/stat.h only on unix platforms - fixed bug in the ffiter iterator function that caused it to always pass 'firstn' = 1 to the work function when reading from the primary array or IMAGE extension. It worked correctly for tables. - fixed bug in the template header keyword parser (ffgthd) in cases where the input template line contains a logical valued keyword (T or F) without any following comment string. It was previously interpreting this as a string-valued keyword. - modified ffrhdu that reads and opens a new HDU, so that it ignores any leading blank characters in the XTENSION name, e.g., XTENSION= ' BINTABLE' will not cause any errors, even though this technically violates the FITS Standard. - modified ffgtbp that reads the required table keywords to make it more lenient and not exit with an error if the THEAP keyword in binary tables cannot be read as an integer. Now it will simply ignore this keyword if it cannot be read. - added test for 'WIN32' as well as '__WIN32__' in fitsio2.h, eval.l and eval_l.c in a preprocessor statement. - changed definition of strcasecmp and strncasecmp in fitsio2.h, eval.l and eval_l.c to conform to the function prototypes under the Alpha VMS v7.1 compiler. - corrected the long function names in longnam.h for the new WCS utility functions in wcssubs.c Version 2.029 - 11 Feb 1999 - fixed bug in the way NANs and underflows were being detected on VAX and Alpha VMS machines. - enhanced the filename parser to distinguish between a VMS-style directory name (e.g. disk:[directory]myfile.fits) and a CFITSIO filter specifier at the end of the name. - modified ffgthd to support the HIERARCH convention for keyword names that are longer than 8 characters or contain characters that would be illegal in standard FITS keyword names. - modified the include statements in grparser.c so that malloc.h and memory.h are only included on the few platforms that really need them. - modified the file_read routine in drvrfile.c to ignore the last record in the FITS file it it only contains a single character that is equal to 0, 10 or 32. Text editors sometimes append a character like this to the end of the file, so CFITSIO will ignore it and treat it as if it had reached the end of file. - minor modifications to fitsio.h to help support the ROOT environment. - installed new version of group.c and group.h; the main change is to support relative paths (e.g. "../filename") in the URLs - modified the histogramming routines so that it looks for the default preferred column axes in a keyword of the form CPREF = 'Xcol, Ycol' instead of separate keywords of the form CPREF1 = 'Xcol' CPREF2 = 'Ycol' - fixed bug so that if the binning spec is just a single integer, as in [bin 4] then this will be interpreted as meaning to make a 2D histogram using the preferred or default axes, with the integer taken as the binning factor in both axes. Version 2.028 - 27 Jan 1999 - if the TNULLn keyword value was outside the range of a 'I' or 'B' column, an overflow would occur when setting the short or char to the TNULLn value, leading to incorrect values being flagged as being undefined. This has been fixed so that CFITSIO will ignore TNULLn values that are beyond the range of the column data type. - changed a few instances of the string {"\0"} to {'\0'} in the file groups.c - installed new version of the grparser.c file from the ISDC - added new WCS support routines (in wcssub.c) which make it easier to call Doug Mink's WCSlib routines for converting between plate and sky coordinates. The CFITSIO routines themselves never call a WCSlib routine, so CFITSIO is not dependent on WCSlib. - modified ffopen so that if you use the extended filename syntax to both select rows in a table and then bin columns into a histogram, then CFITSIO will simply construct an array listing the good row numbers to be used when making the histogram, instead of making a whole new temporary FITS file containing the selected rows. - modified ffgphd which parses the primary array header keywords when opening a file, to not choke on minor format errors in optional keywords. Otherwise, this prevents CFITSIO from even opening the file. - changed a few more variable declarations in compress.c from global to static. Version 2.027 - 12 Jan 1999 - modified the usage of the output filename specifier so that it, a) gives the name of the binned image, if specified, else, b) gives the name of column filtered and/or row filtered table, if specified, else c) is the name for a local copy of the ftp or http file, else, d) is the name for the local uncompressed version of the compressed FITS file, else, e) the output filename is ignored. - fixed minor bug in ffcmps, when comparing 2 strings while using a '*' wild card character. - fixed bug in ftgthd that affected cases where the template string started with a minus sign and contained 2 tokens (to rename a keyword). - added support for the HIERARCH keyword convention for reading and writing keywords longer than 8 characters or that contain ASCII characters not allowed in normal FITS keywords. - modified the extended filename syntax to support opening images that are contained in a single cell of a binary table with syntax: filename.fits[extname; col_name(row_expression)] Version 2.026 - 23 Dec 1998 - modified the group parser to: a) support CFITSIO_INCLUDE_FILES environment variable, which can point to the location of template files, and, b) the FITS file parameter passed to the parser no longer has to point to an empty file. If there are already HDUs in the file, then the parser appends new HDUs to the end of the file. - make a small change to the drvrnet.c file to accommodate creating a static version of the CFITSIO library. - added 2 new routines to read consecutive bits as an unsigned integer from a Bit 'X' or Byte 'B' column (ffgcxui and ffgcxuk). - modified the logic for determining histogram boundaries in ffhisto to add one more bin by default, to catch values that are right on the upper boundary of the histogram, or are in the last partial bin. - modified cfitsio2.h to support the new Solaris 7 64-bit mode operating system. - Add utility routine, CFits2Unit, to the Fortran wrappers which searches the gFitsFiles array for a fptr, returning its element (Fortran unit number), or allocating a new element if one doesn't already exists... for C calling Fortran calling CFITSIO. - modified configure so that it does not use the compiler optimizer when using gcc 2.8.x on Linux - (re)added the fitsio.* documentation files that describe the Fortran-callable FITSIO interface to the C routines. - modified the lexical parser in eval_f.c to fix bug in null detections and bug in ffsrow when nrows = 0. - modified ffcalc so that it creates a TNULLn keyword if appropriate when a new column is created. Also fixed detection of OVERFLOWs so that it ignores null values. - added hyperbolic trig and rounding functions to the lexical parser in the eval* files. - improved error message that gets written when the group number is out of range when reading a 'random groups' array. - added description of shared memory, grouping, and template parsing error messages to ffgerr and to the User's Guide. Moved the error code definitions from drvsmem.h to fitsio.h. - modified grparser.c to compile correctly on Alpha/OSF machines - modified drvrnet.c to eliminate compiler warnings - Modified Makefile.in to include targets for building all the sample programs that are included with CFITSIO. Version 2.025 - 1 Dec 1998 - modified ffgphd and ffgtbp so that they ignores BLANK and TNULLn keywords that do not have a valid integer value. Also, any error while reading the BSCALE, BZERO, TSCALn, or TZEROn keywords will be ignored. Previously, CFITSIO would have simply refused to read an HDU that had such an invalid keyword. - modified the parser in eval_f.c to accept out of order times in GTIs - updated cfitsio_mac.sit.hqx to fix bad target parameters for Mac's speed test program - modified template parser in grparser.c to: 1) not write GRPNAME keyword twice, and 2) assign correct value for EXTVERS keyword. - fixed minor bugs in group.c; mainly would only affect users of the INTEGRAL Data Access Layer. - temporarily removed the prototype for ffiwcs from fitsio.h until full WCS support is added to CFITSIO in the near future. - modified the HTTP driver to send a User-Agent string: HEASARC/CFITSIO/ - declared local variables in compress.c as 'static' to avoid conflicts with other libraries. Version 2.024 - 9 Nov 1998 - added new function fits_url_type which returns the driver prefix string associated with a particular FITS file pointer. Version 2.023 - 1 Nov 1998 - first full release of CFITSIO 2.0 - slightly modified the way real keyword values are formatted, to ensure that it includes a decimal point. E.g., '1.0E-09' instead of '1E-09' - added new function to support template files when creating new FITS files. - support the TCROTn WCS keyword in tables, when reading the WCS keywords. - modified the iterator to support null values in logical columns in binary tables. - fixed bug in iterator to support null values in integer columns in ASCII tables. - changed the values for FLOATNULLVALUE and DOUBLENULLVALUE to make them less likely to duplicate actual values in the data. - fixed major bug when freeing memory in the iterator function. It caused mysterious crashes on a few platforms, but had no effect on most others. - added support for reading IRAF format image (.imh files) - added more error checking to return an error if the size of the FITS file exceeds the largest value of a long integer (2.1 GB on 32-bit platforms). - CFITSIO now will automatically insert space for additional table rows or add space to the data heap, if one writes beyond the current end of the table or heap. This prevents any HDUs which might follow the current HDU from being overwritten. It is thus no longer necessary to explicitly call fits_insert_rows before writing new rows of data to the FITS file. - CFITSIO now automatically keeps track of the number of rows that have been written to a FITS table, and updates the NAXIS2 keyword accordingly when the table is closed. It is no longer necessary for the application program to updated NAXIS2. - When reading from a FITS table, CFITSIO will now return an error if the application tries to read beyond the end of the table. - added 2 routines to get the number of rows or columns in a table. - improved the undocumented feature that allows a '20A' column to be read as though it were a '20B' column by fits_read_col_byt. - added overflow error checking when reading keywords. Previously, the returned value could be silently truncated to the maximum allowed value for that data type. Now an error status is returned whenever an overflow occurs. - added new set of routines dealing with hierarchical groups of files. These were provided by Don Jennings of the INTEGRAL Science Data Center. - added new URL parsing routines. - changed the calling sequence to ffghad (get HDU address) from ffghad(fitsfile *fptr, > long *headstart, long *dataend) to ffghad(fitsfile *fptr, > long *headstart, long datastart, long *dataend, int *status) - major modification to support opening the same FITS file more than once. Now one can open the same file multiple times and read and write simultaneously to different HDUs within the file. fits_open_file automatically detects if the file is already opened. - added the ability to clobber/overwrite an existing file with the same name when creating a new output file. Just precede the output file name with '!' (an exclamation mark) - changed the ffpdat routine which writes the DATE keyword to use the new 'YYYY-MM-DDThh:mm:ss' format. - added several new routines to create or parse the new date/time format string. - changed ifdef for DECFortran in f77_wrap.h and f77_wrap1.c: expanded to recognize Linux/Alpha - added new lexical parsing routines (from Peter Wilson): eval_l.c, eval_y.c, eval_f.c, eval_defs.h, and eval_tab.h. These are used when doing on-the-fly table row selections. - added new family of routines to support reading and writing 'unsigned int' data type values in keywords, images or tables. - restructured all the putcol and getcol routines to provide simpler and more robust support for machines which have sizeof(long) = 8. Defined a new datatype INT32BIT which is always 32 bits long (platform independent) and is used internally in CFITSIO when reading or writing BITPIX = 32 images or 'J' columns. This eliminated the need for specialize routines like ffswaplong, ffunswaplong, and ffpacklong. - overhauled cfileio.c (and other files) to use loadable drivers for doing data I/O to different devices. Now CFITSIO support network access to ftp:// and http:// files, and to shared memory files. - removed the ffsmem routine and replaced it with ffomem. This will only affect software that reads an existing file in core memory. (written there by some other process). - modified all the ffgkn[] routines (get an array of keywords) so that the 'nfound' parameter is = the number of keywords returned, not the highest index value on the returned keywords. This makes no difference if the starting index value to look for = 1. This change is not backward compatible with previous versions of CFITSIO, but is the way that FITSIO behaved. - added new error code = 1 for any application error external to CFITSIO. Also reports "unknown error status" if the value doesn't match a known CFITSIO error. Version 1.42 - 30 April 1998 (included in FTOOLS 4.1 release) - modified the routines which read a FITS float values into a float array, or read FITS double values into a double array, so that the array value is also explicitly set in addition to setting the array of flag values, if the FITS value is a NaN. This ensures that no NaN values get passed back to the calling program, which can cause serious problems on some platforms (OSF). - added calls to ffrdef at the beginning of the insert or delete rows or columns routines in editcol.c to make sure that CFITSIO has correctly initialized the HDU information. - added new routine ffdrws to delete a list of rows in a table - added ffcphd to copy the header keywords from one hdu to another - made the anynul parameter in the ffgcl* routines optional by first checking to see if the pointer is not null before initializing it. - modified ffbinit and ffainit to ignore minor format errors in header keywords so that cfitsio can at least move to an extension that contains illegal keywords. - modified all the ffgcl* routines to simply return without error if nelem = 0. - added check to ffclose to check the validity of the fitsfile pointer before closing it. This should prevent program crashes when someone tries to close the same file more than once. - replaced calls to strcmp and strncmp with macros FSTRCMP and FSTRNCMP in a few places to improve performance when reading header keywords (suggested by Mike Noble) Bug Fixes: - fixed typo in macro definition of error 504 in the file fitsio.h. - in ffopen, reserved space for 4 more characters in the input file name in case a '.zip' suffix needs to be added. - small changes to ffpclx to fix problems when writing bit (X) data columns beyond the current end of file. - fixed small bug in ffcrhd where a dummy pointer was not initialized - initialized the dummy variable in ffgcfe and ffgcfd which was causing crashes under OSF in some cases. - increased the length of the allocated string ffgkls by 2 to support the case of reading a numeric keyword as a string which doesn't have the enclosing quote characters. Version 1.4 - 6 Feb 1998 - major restructuring of the CFITSIO User's Guide - added the new 'iterator' function. The fortran wrapper is in f77_iter.c for now. - enhanced ffcrtb so that it writes a dummy primary array if none currently exists before appending the table. - removed the ffgcl routine and replaced it with ffgcvl - modified ffpcnl to just take a single input null value instead of an entire array of null value flags. - modified ffcmps and ffgnxk so that, for example, the string 'rate' is not considered a match to the string 'rate2', and 'rate*' is a match to the string 'rate'. - modified ffgrsz to also work with images, in which case it returns the optimum number of pixels to process at one time. - modified ffgthd to support null valued keywords - added a new source file 'f77_wrap.c' that includes all the Fortran77 wrapper routines for calling CFITSIO. This will eventually replace the Fortran FITSIO library. - added new routines: ffppn - generic write primary array with null values ffpprn - write null values to primary array ffuky - 'update' a keyword value, with any specified datatype. ffrprt - write out report of error status and error messages ffiter - apply a user function iteratively to all the rows of a table ffpkyc - write complex-valued keyword ffpkym - write double complex-valued keyword ffpkfc - write complex-valued keyword in fixed format ffpkfm - write double complex-valued keyword in fixed format ffgkyc - read complex-valued keyword ffgkym - read double complex-valued keyword ffmkyc - modify complex-valued keyword ffmkym - modify double complex-valued keyword ffmkfc - modify complex-valued keyword in fixed format ffmkfm - modify double complex-valued keyword in fixed format ffukyc - update complex-valued keyword ffukym - update double complex-valued keyword ffukfc - update complex-valued keyword in fixed format ffukfm - update double complex-valued keyword in fixed format ffikyc - insert complex-valued keyword ffikym - insert double complex-valued keyword ffikfc - insert complex-valued keyword in fixed format ffikfm - insert double complex-valued keyword in fixed format ffpktp - write or modify keywords using ASCII template file ffcpcl - copy a column from one table to another ffcpky - copy an indexed keyword from one HDU to another ffpcnl - write logical values, including nulls, to binary table ffpcns - write string values, including nulls, to table ffmnhd - move to HDU with given exttype, EXTNAME and EXTVERS values ffthdu - return the total number of HDUs in the file ffghdt - return the type of the CHDU ffflnm - return the name of the open FITS file ffflmd - return the mode of the file (READONLY or READWRITE) - modified ffmahd and ffmrhd (to move to a new extension) so that a null pointer may be given for the returned HDUTYPE argument. - worked around a bug in the Mac CWpro2 compiler by changing all the statements like "#if BYTESWAPPED == TRUE" to "if BYTESWAPPED". - modified ffitab (insert new ASCII table) to allow tables with zero number of columns - modified Makefile.in and configure to define the -Dg77Fortran CFLAGS variable on Linux platforms. This is needed to compile the new f77_wrap.c file (which includes cfortran.h) Bug Fixes: - fixed small bug in ffgrz (get optimum row size) which sometimes caused it to return slightly less than the maximum optimum size. This bug would have done no harm to application programs. - fixed bug in ffpclk and ffgclk to add an 'else' case if size of int is not equal to size of short or size of long. - added test to ffgkls to check if the input string is not null before allocating memory for it. Version 1.32 - 21 November 1997 (internal release only) - fixed bug in the memory deallocation (free) statements in the ffopen routine in the cfileio.c file. - modified ffgphd to tolerate minor violations of the FITS standard in the format of the XTENSION = 'IMAGE ' keyword when reading FITS files. Extra trailing spaces are now allowed in the keyword value. (FITS standard will be changed so that this is not a violation). Version 1.31 - 4 November 1997 (internal release only) Enhancements: - added support for directly reading compressed FITS files by copying the algorithms from the gzip program. This supports the Unix compress, gzip and pkzip algorithms. - modified ffiimg, ffitab, and ffibin (insert HDUs into a FITS file) so that if the inserted HDU is at the end of the FITS file, then it simply appends a new empty HDU and writes the required keywords. This allows space to be reserved for additional keywords in the header if desired. - added the ffchfl and ffcdfl routines to check the header and data fill values, for compatibility with the Fortran FITSIO library. - added the ffgsdt routine to return the system date for compatibility with the Fortran FITSIO library. - added a diagnostic error message (written to the error stack) if the routines that read data from image or column fail. - modified ffgclb so that it simply copies the bytes from an ASCII 'nA' or 'An' format column into the user's byte array. Previously, CFITSIO would return an error when trying to read an 'A' column with ffgclb. - modified ffpclb so that it simply copies the input array of bytes to an ASCII 'nA' or 'An' format column. Previously, CFITSIO would return an error when trying to write to an 'A' column with ffpclb. Bug Fixes: - ffgkls was allocating one too few bytes when reading continued string keyword values. - in testprog.c added code to properly free the memory that had been allocated for string arrays. - corrected typographical errors in the User's Guide. Version 1.30 - 11 September 1997 - major overhaul to support reading and writing FITS files in memory. The new routines fits_set_mem_buff and fits_write_mem_buff have been added to initialize and copy out the memory buffer, respectively. - added support for reading FITS files piped in on 'stdin' and piped out on 'stdout'. Just specify the file name as '-' when opening or creating the FITS file. - added support for 64-bit SGI IRIX machines. This required adding routines to pack and unpack 32-bit integers into 64-bit integers. - cleaned up the code that supports G_FLOAT and IEEE_FLOAT on Alpha VMS systems. Now, the type of float is determined at compile time, not run time. Bug Fixes: - replaced the malloc calls in the error message stack routines with a static fixed size array. The malloc's cause more problems than they solved, and were prone to cause memory leaks if users don't clear the error message stack when closing the FITS file. - when writing float or double keywords, test that the value is not a special IEEE value such as a NaN. Some compilers would write the string 'NaN' in this case into the output value string. - fixed bug in ffiblk, to ignore EOF status return if it is inserting blocks at the end of the file. - removed the 'l' from printf format string that is constructed in the ffcfmt routine. This 'l' is non-standard and causes problems with the Metrowerks compiler on a Mac. - the default null value in images was mistakenly being set equal to NO_NULL = 314, rather than NULL_UNDEFINED = 1234554321 in the ffgphd routine. - check status value in ffgkls to make sure the keyword exists before allocating memory for the value string. - fixed the support for writing and reading unsigned long integer keyword values in ffpky and ffgky by internally treating the values as doubles. This required changes to ffc2r and ffc2d as well. - added explicit cast to 'double' in one place in putcolb.c and 6 places in pubcolui.c, to get rid of warning messages issued by one compiler. - in ffbinit and ffainit, it is necessary to test that tfield > 0 before trying to allocate memory with calloc. Otherwise, some compilers return a null pointer which CFITSIO interprets to mean the memory allocation failed. - had to explicitly cast the null buffer pointer to a char pointer (cptr = (char *)buffer;) in 4 places in the buffers.c file to satisfy a picky C++ compiler. - changed the test for an ALPHA VMS system to see if '__VMS' is defined, rather than 'VMS'. The latter is not defined by at least one C++ compiler. - modified ffpcls so that it can write a null string to a variable length string column, without going into an infinite loop. - fixed bug in ffgcfl that caused the 'next' variable to be incremented twice. - fixed bug in ffgcpr that caused it write 2x the number of complex elements into the descriptor when writing to a complex or double complex variable length array column. - added call to ffrdef at the end of ffrsim to ensure that the internal structures are updated to correspond to the modified header keywords Version 1.25 - 7 July 1997 - improved the efficiency of the ffiblk routine, when inserting more than one block into the file. - fixed bug in ffwend that in rare instances caused the beginning of the following extension to be overwritten by blank fill. - added new routine to modify the size of an existing primary array or image extension: fits_resize_img/ffrsim. - added support for null-valued keywords, e.g., keywords that have no defined value. These keywords have an equal sign and space in columns 9-10, but have not value string. Example: KEYNAME = / null-valued keyword Support for this feature required the following changes: - modified ffpsvc to return a null value string without error - modified ffc2[ilrd] to return error VALUE_UNDEFINED in this case - modified ffgkn[sljed] to continue reading additional keywords even if one or more keywords have undefined values. - added 4 new routines: ffpkyu, ffikyu, ffmkyu, ffukyu to write, insert, modify, or update an undefined keyword - a new makefile.os2 file was added, for building CFITSIO on OS/2 systems. - modified ffgtkn so that if it finds an unexpected keyword name, the returned error status = BAD_ORDER instead of NOT_POS_INT. - added 2 new routines, fits_write_key_unit/ffpunt and fits_read_key_unit/ffgunt to write/read the physical units of a keyword value. These routines use a local FITS convention for storing the units in square brackets following the '/' comment field separator, as in: VELOCITY= 12 / [km/s] orbit speed The testprog.c program was modified to test these new routines. - in the test of Alpha OSF/1 machines in fitsio2.h, change 'defined(unix)' to 'defined(__unix__)' which appears to be a more robust test. - remove test for linux environment variable from fitsio2.h Version 1.24 - 2 May 1997 - fixed bug in ffpbyt that incorrectly computed the current location in the FITS file when writing > 10000 bytes. - changed the datatype of the 'nbytes' parameter in ffpbyt from 'int' to 'long'. Made corresponding datatype change to some internal variables in ffshft. - changed '(unsigned short *)' to '(short *)' in getcolui.c, and changed '(unsigned long *)' to '(long *)' in getcoluj.c, to work around problem with the VAX/VMS cc compiler. Version 1.23 - 24 April 1997 - modified ffcins and ffdins (in editcol.c) to simply return without error if there are no (zero) rows in the table. Version 1.22 - 18 April 1997 - fixed bug in ffgcpr that caused it to think that all values were undefined in ASCII tables columns that have TNULLn = ' ' (i.e., the TNULLn keyword value is a string of blanks. - fixed bug in the ffgcl[bdeijk,ui,uj] family of routines when parsing a numeric value in an ASCII table. The returned values would have the decimal place shifted to the left if the table field contained an explicit decimal point followed by blanks. Example: in an F5.2 column, the value '16. ' would be returned as 0.16. If the trailing zeros were present, then cfitsio returned the correct value (e.g., '16.00' returns 16.). - fixed another bug in the ffgcl[bdeijk,ui,uj] family of routines that caused them to misread values in an ASCII table in rows following an undefined value when all the values were read at once in a single call to the routine. Version 1.21 - 26 March 1997 - added general support for reading and writing unsigned integer keywords, images, and binary table column values. - fixed bug in the way the column number was used in ffgsve and similar routines. This bug caused cfitsio to read (colnum - 1) rather than the desired column. - fixed a bug in ftgkls that prevented it from reading more than one continuation line of a long string keyword value. - fixed the definition of fits_write_longwarn in longnam.h Version 1.20 - 29 Jan 1997 - when creating a binary table with variable length vector columns, if the calling routine does not specify a value for the maximum length of the vector (e.g., TFORMn = '1PE(400)') then cfitsio will automatically calculate the maximum value and append it to the TFORM value when the binary table is first closed. - added the set of routines to do coordinate system transformations - added support for wildcards ('*', '?', and '#') in the input keyword name when reading, modifying, or deleting keywords. - added new general keyword reading routine, ffgnxk, to return the next keyword whose name matches a list of template names, but does not match any names on a second template list. - modified ftgrec so that it simply moves to the beginning of the header if the input keyword number = 0 - added check in ffdelt to make sure the input fits file pointer is not already null - added check in ffcopy to make sure the output HDU does not already contain any keywords (it must be empty). - modified ffgcls so that it does not test if each string column value equals the null string value if the null string value is longer than the width of the column. - fixed bug in ftgtdm that caused it to fail if the TDIMn keyword did not exist in the FITS file - modified testprog.c to include tests of keyword wildcards and the WCS coordinate transformation routines. - added a test for 'EMX' in fitsio2.h so that cfitsio builds correctly on a PC running OS/2. Version 1.11 - 04 Dec 1996 - modified the testprog.c program that is included with the distribution, so that the output FITS file is identical to that produced by the Fortran FITSIO test program. - changed all instances of the 'extname' variable to 'extnm' to avoid a conflict with the -Dextname switch in cfortran.h on HP machines. - in all the routines like ffi4fi1, which convert an array of values to integers just prior to writing them to the FITS file, the integer value is now rounded to the nearest integer rather than truncated. (ffi4fi1, ffi4fi2, ffi4fi4, etc) - changed ffgcfl (and hence ffgcl) so that the input value of the logical array element is not changed if the corresponding FITS value is undefined. - in ffgacl, the returned value of TBCOL was off by 1 (too small) - fixed the comment of EXTNAME keyword to read 'binary table' instead of 'ASCII table' in the header of binary tables. Version 1.101 - 17 Nov 1996 - Made major I/O efficiency improvements by adding internal buffers rather than directly reading or writing to disk. Access to columns in binary tables is now 50 - 150 times faster. Access to FITS image is also slightly faster. - made significant speed improvements when reading numerical data in FITS ASCII tables by writing my own number parsing routines rather than using the sscanf C library routine. This change requires that the -lm argument now be included when linking a program that calls cfitsio (under UNIX). - regrouped the source files into logically related sets of routines. The Makefile now runs much faster since every single routine is not split into a separate file. - now use the memcpy function, rather than a 'for' loop in several places for added efficiency - redesigned the low-level binary table read and write routines (ffpbytoff and ffgbytoff) for greater efficiency. - added a new error status: 103 = too many open FITS files. - added a 'extern "C"' statement around the function prototypes in fitsio.h, to support use of cfitsio by C++ compilers. - fixed routines for writing or reading fixed-length substrings within a binary table ASCII column, with TFORM values of of the form 'rAw' where 'r' is the total width of the ASCII column and 'w' is the width of a substring within the column. - no longer automatically rewrite the END card and following fill values if they are already correct. - all the 'get keyword value and comment' routines have been changed so that the comment is not returned if the input pointer is NULL. - added new routine to return the optimum number of tables rows that should be read or written at one time for optimum efficiency. - modified the way numerical values in ASCII tables are parsed so that embedded spaces in the value are ignored, and implicit decimal points are now supported. (e.g, the string '123E 12' in a 'E10.2' format column will be interpreted as 1.23 * 10**12). - modified ffpcl and ffgcl to support binary table columns of all datatype (added logical, bit, complex, and double complex) - when writing numerical data to ASCII table columns, the ffpcl_ routines now return an overflow error if a value is too large to be expressed in the column format. - closed small memory leak in ffpcls. - initialized the 'incre' variable in ffgcpr to eliminate compiler warning. Version 1.04 - 17 Sept 1996 - added README.MacOS and cfitsio_mac.sit.hqx to the distribution to support the Mac platforms. - fixed bug in ffpdfl that caused an EOF error (107) when a program creates a new extension that is an exact multiple of 2880 bytes long, AND the program does not write a value to the last element in the table or image. - fixed bug in all the ffgsf* and ffgcv* routines which caused core dumps when reading null values in a table. Version 1.03 - 20 August 1996 - added full support for reading and writing the C 'int' data type. This was a problem on Alpha/OSF where short, int, and long datatypes are 2, 4, and 8 bytes long, respectively. - cleaned up the code in the byte-swapping routines. - renamed the file 'longname.h' to 'longnam.h' to avoid conflict with a file with the same name in another unrelated package. Version 1.02 - 15 August 1996 - ffgtbp was not correctly reading the THEAP keyword, hence would not correctly read variable length data in binary tables if the heap was not at the default starting location (i.e., starting immediately after the fixed length table). - now force the cbuff variable in ffpcl_ and ffgcl_ to be aligned on a double word boundary. Non-alignment can cause program to crash on some systems. Version 1.01 - 12 August 1996 - initial public release cfitsio/docs/fitsio.doc0000644000225700000360000117537513246025103014737 0ustar cagordonlhea FITSIO - An Interface to FITS Format Files for Fortran Programmers William D Pence, HEASARC, NASA/GSFC Version 3.0 [Note: This file contains various formatting command symbols in the first column which are used when generating the LATeX version of this document.] *I. Introduction This document describes the Fortran-callable subroutine interface that is provided as part of the CFITSIO library (which is written in ANSI C). This is a companion document to the CFITSIO User's Guide which should be consulted for further information about the underlying CFITSIO library. In the remainder of this document, the terms FITSIO and CFITSIO are interchangeable and refer to the same library. FITSIO/CFITSIO is a machine-independent library of routines for reading and writing data files in the FITS (Flexible Image Transport System) data format. It can also read IRAF format image files and raw binary data arrays by converting them on the fly into a virtual FITS format file. This library was written to provide a powerful yet simple interface for accessing FITS files which will run on most commonly used computers and workstations. FITSIO supports all the features described in the official definition of the FITS format and can read and write all the currently defined types of extensions, including ASCII tables (TABLE), Binary tables (BINTABLE) and IMAGE extensions. The FITSIO subroutines insulate the programmer from having to deal with the complicated formatting details in the FITS file, however, it is assumed that users have a general knowledge about the structure and usage of FITS files. The CFITSIO package was initially developed by the HEASARC (High Energy Astrophysics Science Archive Research Center) at the NASA Goddard Space Flight Center to convert various existing and newly acquired astronomical data sets into FITS format and to further analyze data already in FITS format. New features continue to be added to CFITSIO in large part due to contributions of ideas or actual code from users of the package. The Integral Science Data Center in Switzerland, and the XMM/ESTEC project in The Netherlands made especially significant contributions that resulted in many of the new features that appeared in v2.0 of CFITSIO. The latest version of the CFITSIO source code, documentation, and example programs are available on the World-Wide Web or via anonymous ftp from: - http://heasarc.gsfc.nasa.gov/fitsio ftp://legacy.gsfc.nasa.gov/software/fitsio/c - \newpage Any questions, bug reports, or suggested enhancements related to the CFITSIO package should be sent to the FTOOLS Help Desk at the HEASARC: - http://heasarc.gsfc.nasa.gov/cgi-bin/ftoolshelp - This User's Guide assumes that readers already have a general understanding of the definition and structure of FITS format files. Further information about FITS formats is available from the FITS Support Office at {\tt http://fits.gsfc.nasa.gov}. In particular, the 'FITS Standard' gives the authoritative definition of the FITS data format. Other documents available at that Web site provide additional historical background and practical advice on using FITS files. The HEASARC also provides a very sophisticated FITS file analysis program called `Fv' which can be used to display and edit the contents of any FITS file as well as construct new FITS files from scratch. Fv is freely available for most Unix platforms, Mac PCs, and Windows PCs. CFITSIO users may also be interested in the FTOOLS package of programs that can be used to manipulate and analyze FITS format files. Fv and FTOOLS are available from their respective Web sites at: - http://fv.gsfc.nasa.gov http://heasarc.gsfc.nasa.gov/ftools - *II. Creating FITSIO/CFITSIO **A. Building the Library To use the FITSIO subroutines one must first build the CFITSIO library, which requires a C compiler. gcc is ideal, or most other ANSI-C compilers will also work. The CFITSIO code is contained in about 40 C source files (*.c) and header files (*.h). On VAX/VMS systems 2 assembly-code files (vmsieeed.mar and vmsieeer.mar) are also needed. The Fortran interface subroutines to the C CFITSIO routines are located in the f77\_wrap1.c, through f77\_wrap4.c files. These are relatively simple 'wrappers' that translate the arguments in the Fortran subroutine into the appropriate format for the corresponding C routine. This translation is performed transparently to the user by a set of C macros located in the cfortran.h file. Unfortunately cfortran.h does not support every combination of C and Fortran compilers so the Fortran interface is not supported on all platforms. (see further notes below). A standard combination of C and Fortran compilers will be assumed by default, but one may also specify a particular Fortran compiler by doing: - > setenv CFLAGS -DcompilerName=1 - (where 'compilerName' is the name of the compiler) before running the configure command. The currently recognized compiler names are: - g77Fortran IBMR2Fortran CLIPPERFortran pgiFortran NAGf90Fortran f2cFortran hpuxFortran apolloFortran sunFortran CRAYFortran mipsFortran DECFortran vmsFortran CONVEXFortran PowerStationFortran AbsoftUNIXFortran AbsoftProFortran SXFortran - Alternatively, one may edit the CFLAGS line in the Makefile to add the '-DcompilerName' flag after running the './configure' command. The CFITSIO library is built on Unix systems by typing: - > ./configure [--prefix=/target/installation/path] [--enable-sse2] [--enable-ssse3] > make (or 'make shared') > make install (this step is optional) - at the operating system prompt. The configure command customizes the Makefile for the particular system, then the `make' command compiles the source files and builds the library. Type `./configure' and not simply `configure' to ensure that the configure script in the current directory is run and not some other system-wide configure script. The optional 'prefix' argument to configure gives the path to the directory where the CFITSIO library and include files should be installed via the later 'make install' command. For example, - > ./configure --prefix=/usr1/local - will cause the 'make install' command to copy the CFITSIO libcfitsio file to /usr1/local/lib and the necessary include files to /usr1/local/include (assuming of course that the process has permission to write to these directories). The optional --enable-sse2 and --enable-ssse3 flags will cause configure to attempt to build CFITSIO using faster byte-swapping algorithms. See the "Optimizing Programs" section of this manual for more information about these options. By default, the Makefile will be configured to build the set of Fortran-callable wrapper routines whose calling sequences are described later in this document. The 'make shared' option builds a shared or dynamic version of the CFITSIO library. When using the shared library the executable code is not copied into your program at link time and instead the program locates the necessary library code at run time, normally through LD\_LIBRARY\_PATH or some other method. The advantages of using a shared library are: - 1. Less disk space if you build more than 1 program 2. Less memory if more than one copy of a program using the shared library is running at the same time since the system is smart enough to share copies of the shared library at run time. 3. Possibly easier maintenance since a new version of the shared library can be installed without relinking all the software that uses it (as long as the subroutine names and calling sequences remain unchanged). 4. No run-time penalty. - The disadvantages are: - 1. More hassle at runtime. You have to either build the programs specially or have LD_LIBRARY_PATH set right. 2. There may be a slight start up penalty, depending on where you are reading the shared library and the program from and if your CPU is either really slow or really heavily loaded. - On HP/UX systems, the environment variable CFLAGS should be set to -Ae before running configure to enable "extended ANSI" features. It may not be possible to statically link programs that use CFITSIO on some platforms (namely, on Solaris 2.6) due to the network drivers (which provide FTP and HTTP access to FITS files). It is possible to make both a dynamic and a static version of the CFITSIO library, but network file access will not be possible using the static version. On VAX/VMS and ALPHA/VMS systems the make\_gfloat.com command file may be executed to build the cfitsio.olb object library using the default G-floating point option for double variables. The make\_dfloat.com and make\_ieee.com files may be used instead to build the library with the other floating point options. Note that the getcwd function that is used in the group.c module may require that programs using CFITSIO be linked with the ALPHA\$LIBRARY:VAXCRTL.OLB library. See the example link line in the next section of this document. On Windows IBM-PC type platforms the situation is more complicated because of the wide variety of Fortran compilers that are available and because of the inherent complexities of calling the CFITSIO C routines from Fortran. Two different versions of the CFITSIO dll library are available, compiled with the Borland C++ compiler and the Microsoft Visual C++ compiler, respectively, in the files cfitsiodll\_2xxx\_borland.zip and cfitsiodll\_3xxx\_vcc.zip, where '3xxx' represents the current release number. Both these dll libraries contain a set of Fortran wrapper routines which may be compatible with some, but probably not all, available Fortran compilers. To test if they are compatible, compile the program testf77.f and try linking to these dll libraries. If these libraries do not work with a particular Fortran compiler, then it may be necessary to modify the file "cfortran.h" to support that particular combination of C and Fortran compilers, and then rebuild the CFITSIO dll library. This will require, however, some expertise in mixed language programming. CFITSIO should be compatible with most current ANCI C and C++ compilers: Cray supercomputers are currently not supported. **B. Testing the Library The CFITSIO library should be tested by building and running the testprog.c program that is included with the release. On Unix systems type: - % make testprog % testprog > testprog.lis % diff testprog.lis testprog.out % cmp testprog.fit testprog.std - On VMS systems, (assuming cc is the name of the C compiler command), type: - $ cc testprog.c $ link testprog, cfitsio/lib, alpha$library:vaxcrtl/lib $ run testprog - The testprog program should produce a FITS file called `testprog.fit' that is identical to the `testprog.std' FITS file included with this release. The diagnostic messages (which were piped to the file testprog.lis in the Unix example) should be identical to the listing contained in the file testprog.out. The 'diff' and 'cmp' commands shown above should not report any differences in the files. (There may be some minor formatting differences, such as the presence or absence of leading zeros, or 3 digit exponents in numbers, which can be ignored). The Fortran wrappers in CFITSIO may be tested with the testf77 program. On Unix systems the fortran compilation and link command may be called 'f77' or 'g77', depending on the system. - % f77 -o testf77 testf77.f -L. -lcfitsio -lnsl -lsocket or % f77 -f -o testf77 testf77.f -L. -lcfitsio (under SUN O/S) or % f77 -o testf77 testf77.f -Wl,-L. -lcfitsio -lm -lnsl -lsocket (HP/UX) or % g77 -o testf77 -s testf77.f -lcfitsio -lcc_dynamic -lncurses (Mac OS-X) % testf77 > testf77.lis % diff testf77.lis testf77.out % cmp testf77.fit testf77.std - On machines running SUN O/S, Fortran programs must be compiled with the '-f' option to force double precision variables to be aligned on 8-byte boundaries to make the fortran-declared variables compatible with C. A similar compiler option may be required on other platforms. Failing to use this option may cause the program to crash on FITSIO routines that read or write double precision variables. On Windows platforms, linking Fortran programs with a C library often depends on the particular compilers involved. Some users have found the following commands work when using the Intel Fortran compiler: - ifort /libs.dll cfitsio.lib /MD testf77.f /Gm or possibly, ifort /libs:dll cfitsio.lib /MD /fpp /extfpp:cfortran.h,fitsio.h /iface:cvf testf77.f - Also note that on some systems the output listing of the testf77 program may differ slightly from the testf77.std template if leading zeros are not printed by default before the decimal point when using F format. A few other utility programs are included with CFITSIO: - speed - measures the maximum throughput (in MB per second) for writing and reading FITS files with CFITSIO listhead - lists all the header keywords in any FITS file fitscopy - copies any FITS file (especially useful in conjunction with the CFITSIO's extended input filename syntax) cookbook - a sample program that performs common read and write operations on a FITS file. iter_a, iter_b, iter_c - examples of the CFITSIO iterator routine - The first 4 of these utility programs can be compiled and linked by typing - % make program_name - **C. Linking Programs with FITSIO When linking applications software with the FITSIO library, several system libraries usually need to be specified on the link command line. On Unix systems, the most reliable way to determine what libraries are required is to type 'make testprog' and see what libraries the configure script has added. The typical libraries that may need to be added are -lm (the math library) and -lnsl and -lsocket (needed only for FTP and HTTP file access). These latter 2 libraries are not needed on VMS and Windows platforms, because FTP file access is not currently supported on those platforms. Note that when upgrading to a newer version of CFITSIO it is usually necessary to recompile, as well as relink, the programs that use CFITSIO, because the definitions in fitsio.h often change. **D. Getting Started with FITSIO In order to effectively use the FITSIO library as quickly as possible, it is recommended that new users follow these steps: 1. Read the following `FITS Primer' chapter for a brief overview of the structure of FITS files. This is especially important for users who have not previously dealt with the FITS table and image extensions. 2. Write a simple program to read or write a FITS file using the Basic Interface routines. 3. Refer to the cookbook.f program that is included with this release for examples of routines that perform various common FITS file operations. 4. Read Chapters 4 and 5 to become familiar with the conventions and advanced features of the FITSIO interface. 5. Scan through the more extensive set of routines that are provided in the `Advanced Interface'. These routines perform more specialized functions than are provided by the Basic Interface routines. **E. Example Program The following listing shows an example of how to use the FITSIO routines in a Fortran program. Refer to the cookbook.f program that is included with the FITSIO distribution for examples of other FITS programs. - program writeimage C Create a FITS primary array containing a 2-D image integer status,unit,blocksize,bitpix,naxis,naxes(2) integer i,j,group,fpixel,nelements,array(300,200) character filename*80 logical simple,extend status=0 C Name of the FITS file to be created: filename='ATESTFILE.FITS' C Get an unused Logical Unit Number to use to create the FITS file call ftgiou(unit,status) C create the new empty FITS file blocksize=1 call ftinit(unit,filename,blocksize,status) C initialize parameters about the FITS image (300 x 200 16-bit integers) simple=.true. bitpix=16 naxis=2 naxes(1)=300 naxes(2)=200 extend=.true. C write the required header keywords call ftphpr(unit,simple,bitpix,naxis,naxes,0,1,extend,status) C initialize the values in the image with a linear ramp function do j=1,naxes(2) do i=1,naxes(1) array(i,j)=i+j end do end do C write the array to the FITS file group=1 fpixel=1 nelements=naxes(1)*naxes(2) call ftpprj(unit,group,fpixel,nelements,array,status) C write another optional keyword to the header call ftpkyj(unit,'EXPOSURE',1500,'Total Exposure Time',status) C close the file and free the unit number call ftclos(unit, status) call ftfiou(unit, status) end - **F. Legal Stuff Copyright (Unpublished--all rights reserved under the copyright laws of the United States), U.S. Government as represented by the Administrator of the National Aeronautics and Space Administration. No copyright is claimed in the United States under Title 17, U.S. Code. Permission to freely use, copy, modify, and distribute this software and its documentation without fee is hereby granted, provided that this copyright notice and disclaimer of warranty appears in all copies. DISCLAIMER: THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT SHALL NASA BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT , OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER." **G. Acknowledgments The development of many of the powerful features in CFITSIO was made possible through collaborations with many people or organizations from around the world. The following, in particular, have made especially significant contributions: Programmers from the Integral Science Data Center, Switzerland (namely, Jurek Borkowski, Bruce O'Neel, and Don Jennings), designed the concept for the plug-in I/O drivers that was introduced with CFITSIO 2.0. The use of `drivers' greatly simplified the low-level I/O, which in turn made other new features in CFITSIO (e.g., support for compressed FITS files and support for IRAF format image files) much easier to implement. Jurek Borkowski wrote the Shared Memory driver, and Bruce O'Neel wrote the drivers for accessing FITS files over the network using the FTP, HTTP, and ROOT protocols. The ISDC also provided the template parsing routines (written by Jurek Borkowski) and the hierarchical grouping routines (written by Don Jennings). The ISDC DAL (Data Access Layer) routines are layered on top of CFITSIO and make extensive use of these features. Uwe Lammers (XMM/ESA/ESTEC, The Netherlands) designed the high-performance lexical parsing algorithm that is used to do on-the-fly filtering of FITS tables. This algorithm essentially pre-compiles the user-supplied selection expression into a form that can be rapidly evaluated for each row. Peter Wilson (RSTX, NASA/GSFC) then wrote the parsing routines used by CFITSIO based on Lammers' design, combined with other techniques such as the CFITSIO iterator routine to further enhance the data processing throughput. This effort also benefited from a much earlier lexical parsing routine that was developed by Kent Blackburn (NASA/GSFC). More recently, Craig Markwardt (NASA/GSFC) implemented additional functions (median, average, stddev) and other enhancements to the lexical parser. The CFITSIO iterator function is loosely based on similar ideas developed for the XMM Data Access Layer. Peter Wilson (RSTX, NASA/GSFC) wrote the complete set of Fortran-callable wrappers for all the CFITSIO routines, which in turn rely on the CFORTRAN macro developed by Burkhard Burow. The syntax used by CFITSIO for filtering or binning input FITS files is based on ideas developed for the AXAF Science Center Data Model by Jonathan McDowell, Antonella Fruscione, Aneta Siemiginowska and Bill Joye. See http://heasarc.gsfc.nasa.gov/docs/journal/axaf7.html for further description of the AXAF Data Model. The file decompression code were taken directly from the gzip (GNU zip) program developed by Jean-loup Gailly and others. Doug Mink, SAO, provided the routines for converting IRAF format images into FITS format. Martin Reinecke (Max Planck Institute, Garching)) provided the modifications to cfortran.h that are necessary to support 64-bit integer values when calling C routines from fortran programs. The cfortran.h macros were originally developed by Burkhard Burow (CERN). Julian Taylor (ESO, Garching) provided the fast byte-swapping algorithms that use the SSE2 and SSSE3 machine instructions available on x86\_64 CPUs. In addition, many other people have made valuable contributions to the development of CFITSIO. These include (with apologies to others that may have inadvertently been omitted): Steve Allen, Carl Akerlof, Keith Arnaud, Morten Krabbe Barfoed, Kent Blackburn, G Bodammer, Romke Bontekoe, Lucio Chiappetti, Keith Costorf, Robin Corbet, John Davis, Richard Fink, Ning Gan, Emily Greene, Joe Harrington, Cheng Ho, Phil Hodge, Jim Ingham, Yoshitaka Ishisaki, Diab Jerius, Mark Levine, Todd Karakaskian, Edward King, Scott Koch, Claire Larkin, Rob Managan, Eric Mandel, John Mattox, Carsten Meyer, Emi Miyata, Stefan Mochnacki, Mike Noble, Oliver Oberdorf, Clive Page, Arvind Parmar, Jeff Pedelty, Tim Pearson, Maren Purves, Scott Randall, Chris Rogers, Arnold Rots, Barry Schlesinger, Robin Stebbins, Andrew Szymkowiak, Allyn Tennant, Peter Teuben, James Theiler, Doug Tody, Shiro Ueno, Steve Walton, Archie Warnock, Alan Watson, Dan Whipple, Wim Wimmers, Peter Young, Jianjun Xu, and Nelson Zarate. *III. A FITS Primer This section gives a brief overview of the structure of FITS files. Users should refer to the documentation available from the FITS Support Office, as described in the introduction, for more detailed information on FITS formats. FITS was first developed in the late 1970's as a standard data interchange format between various astronomical observatories. Since then FITS has become the defacto standard data format supported by most astronomical data analysis software packages. A FITS file consists of one or more Header + Data Units (HDUs), where the first HDU is called the `Primary HDU', or `Primary Array'. The primary array contains an N-dimensional array of pixels, such as a 1-D spectrum, a 2-D image, or a 3-D data cube. Six different primary datatypes are supported: Unsigned 8-bit bytes, 16, 32, and 64-bit signed integers, and 32 and 64-bit floating point reals. FITS also has a convention for storing unsigned integers (see the later section entitled `Unsigned Integers' for more details). The primary HDU may also consist of only a header with a null array containing no data pixels. Any number of additional HDUs may follow the primary array; these additional HDUs are called FITS `extensions'. There are currently 3 types of extensions defined by the FITS standard: \begin{itemize} \item Image Extension - a N-dimensional array of pixels, like in a primary array \item ASCII Table Extension - rows and columns of data in ASCII character format \item Binary Table Extension - rows and columns of data in binary representation \end{itemize} In each case the HDU consists of an ASCII Header Unit followed by an optional Data Unit. For historical reasons, each Header or Data unit must be an exact multiple of 2880 8-bit bytes long. Any unused space is padded with fill characters (ASCII blanks or zeros). Each Header Unit consists of any number of 80-character keyword records or `card images' which have the general form: - KEYNAME = value / comment string NULLKEY = / comment: This keyword has no value - The keyword names may be up to 8 characters long and can only contain uppercase letters, the digits 0-9, the hyphen, and the underscore character. The keyword name is (usually) followed by an equals sign and a space character (= ) in columns 9 - 10 of the record, followed by the value of the keyword which may be either an integer, a floating point number, a character string (enclosed in single quotes), or a boolean value (the letter T or F). A keyword may also have a null or undefined value if there is no specified value string, as in the second example. The last keyword in the header is always the `END' keyword which has no value or comment fields. There are many rules governing the exact format of a keyword record (see the FITS Standard) so it is better to rely on standard interface software like FITSIO to correctly construct or to parse the keyword records rather than try to deal directly with the raw FITS formats. Each Header Unit begins with a series of required keywords which depend on the type of HDU. These required keywords specify the size and format of the following Data Unit. The header may contain other optional keywords to describe other aspects of the data, such as the units or scaling values. Other COMMENT or HISTORY keywords are also frequently added to further document the data file. The optional Data Unit immediately follows the last 2880-byte block in the Header Unit. Some HDUs do not have a Data Unit and only consist of the Header Unit. If there is more than one HDU in the FITS file, then the Header Unit of the next HDU immediately follows the last 2880-byte block of the previous Data Unit (or Header Unit if there is no Data Unit). The main required keywords in FITS primary arrays or image extensions are: \begin{itemize} \item BITPIX -- defines the datatype of the array: 8, 16, 32, 64, -32, -64 for unsigned 8--bit byte, 16--bit signed integer, 32--bit signed integer, 64--bit signed integer, 32--bit IEEE floating point, and 64--bit IEEE double precision floating point, respectively. \item NAXIS -- the number of dimensions in the array, usually 0, 1, 2, 3, or 4. \item NAXISn -- (n ranges from 1 to NAXIS) defines the size of each dimension. \end{itemize} FITS tables start with the keyword XTENSION = `TABLE' (for ASCII tables) or XTENSION = `BINTABLE' (for binary tables) and have the following main keywords: \begin{itemize} \item TFIELDS -- number of fields or columns in the table \item NAXIS2 -- number of rows in the table \item TTYPEn -- for each column (n ranges from 1 to TFIELDS) gives the name of the column \item TFORMn -- the datatype of the column \item TUNITn -- the physical units of the column (optional) \end{itemize} Users should refer to the FITS Support Office at {\tt http://fits.gsfc.nasa.gov} for further information about the FITS format and related software packages. *V. FITSIO Conventions and Guidelines **A. CFITSIO Size Limitations CFITSIO places few restrictions on the size of FITS files that it reads or writes. There are a few limits, however, which may affect some extreme cases: 1. The maximum number of FITS files that may be simultaneously opened by CFITSIO is set by NMAXFILES, as defined in fitsio2.h. The current default value is 1000, but this may be increased if necessary. Note that CFITSIO allocates NIOBUF * 2880 bytes of I/O buffer space for each file that is opened. The default value of NIOBUF is 40 (defined in fitsio.h), so this amounts to more than 115K of memory for each opened file (or 115 MB for 1000 opened files). Note that the underlying operating system, may have a lower limit on the number of files that can be opened simultaneously. 2. By default, CFITSIO can handle FITS files up to 2.1 GB in size (2**31 bytes). This file size limit is often imposed by 32-bit operating systems. More recently, as 64-bit operating systems become more common, an industry-wide standard (at least on Unix systems) has been developed to support larger sized files (see http://ftp.sas.com/standards/large.file/). Starting with version 2.1 of CFITSIO, larger FITS files up to 6 terabytes in size may be read and written on supported platforms. In order to support these larger files, CFITSIO must be compiled with the '-D\_LARGEFILE\_SOURCE' and `-D\_FILE\_OFFSET\_BITS=64' compiler flags. Some platforms may also require the `-D\_LARGE\_FILES' compiler flag. This causes the compiler to allocate 8-bytes instead of 4-bytes for the `off\_t' datatype which is used to store file offset positions. It appears that in most cases it is not necessary to also include these compiler flags when compiling programs that link to the CFITSIO library. If CFITSIO is compiled with the -D\_LARGEFILE\_SOURCE and -D\_FILE\_OFFSET\_BITS=64 flags on a platform that supports large files, then it can read and write FITS files that contain up to 2**31 2880-byte FITS records, or approximately 6 terabytes in size. It is still required that the value of the NAXISn and PCOUNT keywords in each extension be within the range of a signed 4-byte integer (max value = 2,147,483,648). Thus, each dimension of an image (given by the NAXISn keywords), the total width of a table (NAXIS1 keyword), the number of rows in a table (NAXIS2 keyword), and the total size of the variable-length array heap in binary tables (PCOUNT keyword) must be less than this limit. Currently, support for large files within CFITSIO has been tested on the Linux, Solaris, and IBM AIX operating systems. **B. Multiple Access to the Same FITS File CFITSIO supports simultaneous read and write access to multiple HDUs in the same FITS file. Thus, one can open the same FITS file twice within a single program and move to 2 different HDUs in the file, and then read and write data or keywords to the 2 extensions just as if one were accessing 2 completely separate FITS files. Since in general it is not possible to physically open the same file twice and then expect to be able to simultaneously (or in alternating succession) write to 2 different locations in the file, CFITSIO recognizes when the file to be opened (in the call to fits\_open\_file) has already been opened and instead of actually opening the file again, just logically links the new file to the old file. (This only applies if the file is opened more than once within the same program, and does not prevent the same file from being simultaneously opened by more than one program). Then before CFITSIO reads or writes to either (logical) file, it makes sure that any modifications made to the other file have been completely flushed from the internal buffers to the file. Thus, in principle, one could open a file twice, in one case pointing to the first extension and in the other pointing to the 2nd extension and then write data to both extensions, in any order, without danger of corrupting the file, There may be some efficiency penalties in doing this however, since CFITSIO has to flush all the internal buffers related to one file before switching to the other, so it would still be prudent to minimize the number of times one switches back and forth between doing I/O to different HDUs in the same file. **C. Current Header Data Unit (CHDU) In general, a FITS file can contain multiple Header Data Units, also called extensions. CFITSIO only operates within one HDU at any given time, and the currently selected HDU is called the Current Header Data Unit (CHDU). When a FITS file is first created or opened the CHDU is automatically defined to be the first HDU (i.e., the primary array). CFITSIO routines are provided to move to and open any other existing HDU within the FITS file or to append or insert a new HDU in the FITS file which then becomes the CHDU. **D. Subroutine Names All FITSIO subroutine names begin with the letters 'ft' to distinguish them from other subroutines and are 5 or 6 characters long. Users should not name their own subroutines beginning with 'ft' to avoid conflicts. (The SPP interface routines all begin with 'fs'). Subroutines which read or get information from the FITS file have names beginning with 'ftg...'. Subroutines which write or put information into the FITS file have names beginning with 'ftp...'. **E. Subroutine Families and Datatypes Many of the subroutines come in families which differ only in the datatype of the associated parameter(s) . The datatype of these subroutines is indicated by the last letter of the subroutine name (e.g., 'j' in 'ftpkyj') as follows: - x - bit b - character*1 (unsigned byte) i - short integer (I*2) j - integer (I*4, 32-bit integer) k - long long integer (I*8, 64-bit integer) e - real exponential floating point (R*4) f - real fixed-format floating point (R*4) d - double precision real floating-point (R*8) g - double precision fixed-format floating point (R*8) c - complex reals (pairs of R*4 values) m - double precision complex (pairs of R*8 values) l - logical (L*4) s - character string - When dealing with the FITS byte datatype, it is important to remember that the raw values (before any scaling by the BSCALE and BZERO, or TSCALn and TZEROn keyword values) in byte arrays (BITPIX = 8) or byte columns (TFORMn = 'B') are interpreted as unsigned bytes with values ranging from 0 to 255. Some Fortran compilers support a non-standard byte datatype such as INTEGER*1, LOGICAL*1, or BYTE, which can sometimes be used instead of CHARACTER*1 variables. Many machines permit passing a numeric datatype (such as INTEGER*1) to the FITSIO subroutines which are expecting a CHARACTER*1 datatype, but this technically violates the Fortran-77 standard and is not supported on all machines (e.g., on a VAX/VMS machine one must use the VAX-specific \%DESCR function). One feature of the CFITSIO routines is that they can operate on a `X' (bit) column in a binary table as though it were a `B' (byte) column. For example a `11X' datatype column can be interpreted the same as a `2B' column (i.e., 2 unsigned 8-bit bytes). In some instances, it can be more efficient to read and write whole bytes at a time, rather than reading or writing each individual bit. The double precision complex datatype is not a standard Fortran-77 datatype. If a particular Fortran compiler does not directly support this datatype, then one may instead pass an array of pairs of double precision values to these subroutines. The first value in each pair is the real part, and the second is the imaginary part. **F. Implicit Data Type Conversion The FITSIO routines that read and write numerical data can perform implicit data type conversion. This means that the data type of the variable or array in the program does not need to be the same as the data type of the value in the FITS file. Data type conversion is supported for numerical and string data types (if the string contains a valid number enclosed in quotes) when reading a FITS header keyword value and for numeric values when reading or writing values in the primary array or a table column. CFITSIO returns status = NUM\_OVERFLOW if the converted data value exceeds the range of the output data type. Implicit data type conversion is not supported within binary tables for string, logical, complex, or double complex data types. In addition, any table column may be read as if it contained string values. In the case of numeric columns the returned string will be formatted using the TDISPn display format if it exists. **G. Data Scaling When reading numerical data values in the primary array or a table column, the values will be scaled automatically by the BSCALE and BZERO (or TSCALn and TZEROn) header keyword values if they are present in the header. The scaled data that is returned to the reading program will have - output value = (FITS value) * BSCALE + BZERO - (a corresponding formula using TSCALn and TZEROn is used when reading from table columns). In the case of integer output values the floating point scaled value is truncated to an integer (not rounded to the nearest integer). The ftpscl and fttscl subroutines may be used to override the scaling parameters defined in the header (e.g., to turn off the scaling so that the program can read the raw unscaled values from the FITS file). When writing numerical data to the primary array or to a table column the data values will generally be automatically inversely scaled by the value of the BSCALE and BZERO (or TSCALn and TZEROn) header keyword values if they they exist in the header. These keywords must have been written to the header before any data is written for them to have any effect. Otherwise, one may use the ftpscl and fttscl subroutines to define or override the scaling keywords in the header (e.g., to turn off the scaling so that the program can write the raw unscaled values into the FITS file). If scaling is performed, the inverse scaled output value that is written into the FITS file will have - FITS value = ((input value) - BZERO) / BSCALE - (a corresponding formula using TSCALn and TZEROn is used when writing to table columns). Rounding to the nearest integer, rather than truncation, is performed when writing integer datatypes to the FITS file. **H. Error Status Values and the Error Message Stack The last parameter in nearly every FITSIO subroutine is the error status value which is both an input and an output parameter. A returned positive value for this parameter indicates an error was detected. A listing of all the FITSIO status code values is given at the end of this document. The FITSIO library uses an `inherited status' convention for the status parameter which means that if a subroutine is called with a positive input value of the status parameter, then the subroutine will exit immediately without changing the value of the status parameter. Thus, if one passes the status value returned from each FITSIO routine as input to the next FITSIO subroutine, then whenever an error is detected all further FITSIO processing will cease. This convention can simplify the error checking in application programs because it is not necessary to check the value of the status parameter after every single FITSIO subroutine call. If a program contains a sequence of several FITSIO calls, one can just check the status value after the last call. Since the returned status values are generally distinctive, it should be possible to determine which subroutine originally returned the error status. FITSIO also maintains an internal stack of error messages (80-character maximum length) which in many cases provide a more detailed explanation of the cause of the error than is provided by the error status number alone. It is recommended that the error message stack be printed out whenever a program detects a FITSIO error. To do this, call the FTGMSG routine repeatedly to get the successive messages on the stack. When the stack is empty FTGMSG will return a blank string. Note that this is a `First In -- First Out' stack, so the oldest error message is returned first by ftgmsg. **I. Variable-Length Array Facility in Binary Tables FITSIO provides easy-to-use support for reading and writing data in variable length fields of a binary table. The variable length columns have TFORMn keyword values of the form `1Pt(len)' or `1Qt(len)' where `t' is the datatype code (e.g., I, J, E, D, etc.) and `len' is an integer specifying the maximum length of the vector in the table. If the value of `len' is not specified when the table is created (e.g., if the TFORM keyword value is simply specified as '1PE' instead of '1PE(400) ), then FITSIO will automatically scan the table when it is closed to determine the maximum length of the vector and will append this value to the TFORMn value. The same routines which read and write data in an ordinary fixed length binary table extension are also used for variable length fields, however, the subroutine parameters take on a slightly different interpretation as described below. All the data in a variable length field is written into an area called the `heap' which follows the main fixed-length FITS binary table. The size of the heap, in bytes, is specified with the PCOUNT keyword in the FITS header. When creating a new binary table, the initial value of PCOUNT should usually be set to zero. FITSIO will recompute the size of the heap as the data is written and will automatically update the PCOUNT keyword value when the table is closed. When writing variable length data to a table, CFITSIO will automatically extend the size of the heap area if necessary, so that any following HDUs do not get overwritten. By default the heap data area starts immediately after the last row of the fixed-length table. This default starting location may be overridden by the THEAP keyword, but this is not recommended. If additional rows of data are added to the table, CFITSIO will automatically shift the the heap down to make room for the new rows, but it is obviously be more efficient to initially create the table with the necessary number of blank rows, so that the heap does not needed to be constantly moved. When writing to a variable length field, the entire array of values for a given row of the table must be written with a single call to FTPCLx. The total length of the array is calculated from (NELEM+FELEM-1). One cannot append more elements to an existing field at a later time; any attempt to do so will simply overwrite all the data which was previously written. Note also that the new data will be written to a new area of the heap and the heap space used by the previous write cannot be reclaimed. For this reason it is advised that each row of a variable length field only be written once. An exception to this general rule occurs when setting elements of an array as undefined. One must first write a dummy value into the array with FTPCLx, and then call FTPCLU to flag the desired elements as undefined. (Do not use the FTPCNx family of routines with variable length fields). Note that the rows of a table, whether fixed or variable length, do not have to be written consecutively and may be written in any order. When writing to a variable length ASCII character field (e.g., TFORM = '1PA') only a single character string written. FTPCLS writes the whole length of the input string (minus any trailing blank characters), thus the NELEM and FELEM parameters are ignored. If the input string is completely blank then FITSIO will write one blank character to the FITS file. Similarly, FTGCVS and FTGCFS read the entire string (truncated to the width of the character string argument in the subroutine call) and also ignore the NELEM and FELEM parameters. The FTPDES subroutine is useful in situations where multiple rows of a variable length column have the identical array of values. One can simply write the array once for the first row, and then use FTPDES to write the same descriptor values into the other rows (use the FTGDES routine to read the first descriptor value); all the rows will then point to the same storage location thus saving disk space. When reading from a variable length array field one can only read as many elements as actually exist in that row of the table; reading does not automatically continue with the next row of the table as occurs when reading an ordinary fixed length table field. Attempts to read more than this will cause an error status to be returned. One can determine the number of elements in each row of a variable column with the FTGDES subroutine. **I. Support for IEEE Special Values The ANSI/IEEE-754 floating-point number standard defines certain special values that are used to represent such quantities as Not-a-Number (NaN), denormalized, underflow, overflow, and infinity. (See the Appendix in the FITS standard or the FITS User's Guide for a list of these values). The FITSIO subroutines that read floating point data in FITS files recognize these IEEE special values and by default interpret the overflow and infinity values as being equivalent to a NaN, and convert the underflow and denormalized values into zeros. In some cases programmers may want access to the raw IEEE values, without any modification by FITSIO. This can be done by calling the FTGPVx or FTGCVx routines while specifying 0.0 as the value of the NULLVAL parameter. This will force FITSIO to simply pass the IEEE values through to the application program, without any modification. This does not work for double precision values on VAX/VMS machines, however, where there is no easy way to bypass the default interpretation of the IEEE special values. This is also not supported when reading floating-point images that have been compressed with the FITS tiled image compression convention that is discussed in section 5.6; the pixels values in tile compressed images are represented by scaled integers, and a reserved integer value (not a NaN) is used to represent undefined pixels. **J. When the Final Size of the FITS HDU is Unknown It is not required to know the total size of a FITS data array or table before beginning to write the data to the FITS file. In the case of the primary array or an image extension, one should initially create the array with the size of the highest dimension (largest NAXISn keyword) set to a dummy value, such as 1. Then after all the data have been written and the true dimensions are known, then the NAXISn value should be updated using the fits\_ update\_key routine before moving to another extension or closing the FITS file. When writing to FITS tables, CFITSIO automatically keeps track of the highest row number that is written to, and will increase the size of the table if necessary. CFITSIO will also automatically insert space in the FITS file if necessary, to ensure that the data 'heap', if it exists, and/or any additional HDUs that follow the table do not get overwritten as new rows are written to the table. As a general rule it is best to specify the initial number of rows = 0 when the table is created, then let CFITSIO keep track of the number of rows that are actually written. The application program should not manually update the number of rows in the table (as given by the NAXIS2 keyword) since CFITSIO does this automatically. If a table is initially created with more than zero rows, then this will usually be considered as the minimum size of the table, even if fewer rows are actually written to the table. Thus, if a table is initially created with NAXIS2 = 20, and CFITSIO only writes 10 rows of data before closing the table, then NAXIS2 will remain equal to 20. If however, 30 rows of data are written to this table, then NAXIS2 will be increased from 20 to 30. The one exception to this automatic updating of the NAXIS2 keyword is if the application program directly modifies the value of NAXIS2 (up or down) itself just before closing the table. In this case, CFITSIO does not update NAXIS2 again, since it assumes that the application program must have had a good reason for changing the value directly. This is not recommended, however, and is only provided for backward compatibility with software that initially creates a table with a large number of rows, than decreases the NAXIS2 value to the actual smaller value just before closing the table. **K. Local FITS Conventions supported by FITSIO CFITSIO supports several local FITS conventions which are not defined in the official FITS standard and which are not necessarily recognized or supported by other FITS software packages. Programmers should be cautious about using these features, especially if the FITS files that are produced are expected to be processed by other software systems which do not use the CFITSIO interface. ***1. Support for Long String Keyword Values. The length of a standard FITS string keyword is limited to 68 characters because it must fit entirely within a single FITS header keyword record. In some instances it is necessary to encode strings longer than this limit, so FITSIO supports a local convention in which the string value is continued over multiple keywords. This continuation convention uses an ampersand character at the end of each substring to indicate that it is continued on the next keyword, and the continuation keywords all have the name CONTINUE without an equal sign in column 9. The string value may be continued in this way over as many additional CONTINUE keywords as is required. The following lines illustrate this continuation convention which is used in the value of the STRKEY keyword: - LONGSTRN= 'OGIP 1.0' / The OGIP Long String Convention may be used. STRKEY = 'This is a very long string keyword&' / Optional Comment CONTINUE ' value that is continued over 3 keywords in the & ' CONTINUE 'FITS header.' / This is another optional comment. - It is recommended that the LONGSTRN keyword, as shown here, always be included in any HDU that uses this longstring convention. A subroutine called FTPLSW has been provided in CFITSIO to write this keyword if it does not already exist. This long string convention is supported by the following FITSIO subroutines that deal with string-valued keywords: - ftgkys - read a string keyword ftpkls - write (append) a string keyword ftikls - insert a string keyword ftmkls - modify the value of an existing string keyword ftukls - update an existing keyword, or write a new keyword ftdkey - delete a keyword - These routines will transparently read, write, or delete a long string value in the FITS file, so programmers in general do not have to be concerned about the details of the convention that is used to encode the long string in the FITS header. When reading a long string, one must ensure that the character string parameter used in these subroutine calls has been declared long enough to hold the entire string, otherwise the returned string value will be truncated. Note that the more commonly used FITSIO subroutine to write string valued keywords (FTPKYS) does NOT support this long string convention and only supports strings up to 68 characters in length. This has been done deliberately to prevent programs from inadvertently writing keywords using this non-standard convention without the explicit intent of the programmer or user. The FTPKLS subroutine must be called instead to write long strings. This routine can also be used to write ordinary string values less than 68 characters in length. ***2. Arrays of Fixed-Length Strings in Binary Tables CFITSIO supports 2 ways to specify that a character column in a binary table contains an array of fixed-length strings. The first way, which is officially supported by the FITS Standard document, uses the TDIMn keyword. For example, if TFORMn = '60A' and TDIMn = '(12,5)' then that column will be interpreted as containing an array of 5 strings, each 12 characters long. FITSIO also supports a local convention for the format of the TFORMn keyword value of the form 'rAw' where 'r' is an integer specifying the total width in characters of the column, and 'w' is an integer specifying the (fixed) length of an individual unit string within the vector. For example, TFORM1 = '120A10' would indicate that the binary table column is 120 characters wide and consists of 12 10-character length strings. This convention is recognized by the FITSIO subroutines that read or write strings in binary tables. The Binary Table definition document specifies that other optional characters may follow the datatype code in the TFORM keyword, so this local convention is in compliance with the FITS standard, although other FITS readers are not required to recognize this convention. ***3. Keyword Units Strings One deficiency of the current FITS Standard is that it does not define a specific convention for recording the physical units of a keyword value. The TUNITn keyword can be used to specify the physical units of the values in a table column, but there is no analogous convention for keyword values. The comment field of the keyword is often used for this purpose, but the units are usually not specified in a well defined format that FITS readers can easily recognize and extract. To solve this deficiency, FITSIO uses a local convention in which the keyword units are enclosed in square brackets as the first token in the keyword comment field; more specifically, the opening square bracket immediately follows the slash '/' comment field delimiter and a single space character. The following examples illustrate keywords that use this convention: - EXPOSURE= 1800.0 / [s] elapsed exposure time V_HELIO = 16.23 / [km s**(-1)] heliocentric velocity LAMBDA = 5400. / [angstrom] central wavelength FLUX = 4.9033487787637465E-30 / [J/cm**2/s] average flux - In general, the units named in the IAU(1988) Style Guide are recommended, with the main exception that the preferred unit for angle is 'deg' for degrees. The FTPUNT and FTGUNT subroutines in FITSIO write and read, respectively, the keyword unit strings in an existing keyword. ***4. HIERARCH Convention for Extended Keyword Names CFITSIO supports the HIERARCH keyword convention which allows keyword names that are longer then 8 characters and may contain the full range of printable ASCII text characters. This convention was developed at the European Southern Observatory (ESO) to support hierarchical FITS keyword such as: - HIERARCH ESO INS FOCU POS = -0.00002500 / Focus position - Basically, this convention uses the FITS keyword 'HIERARCH' to indicate that this convention is being used, then the actual keyword name ({\tt'ESO INS FOCU POS'} in this example) begins in column 10 and can contain any printable ASCII text characters, including spaces. The equals sign marks the end of the keyword name and is followed by the usual value and comment fields just as in standard FITS keywords. Further details of this convention are described at http://fits.gsfc.nasa.gov/registry/hierarch\_keyword.html and in Section 4.4 of the ESO Data Interface Control Document that is linked to from http://archive.eso.org/cms/tools-documentation/eso-data-interface-control.html. This convention allows a much broader range of keyword names than is allowed by the FITS Standard. Here are more examples of such keywords: - HIERARCH LongKeyword = 47.5 / Keyword has > 8 characters, and mixed case HIERARCH XTE$TEMP = 98.6 / Keyword contains the '$' character HIERARCH Earth is a star = F / Keyword contains embedded spaces - CFITSIO will transparently read and write these keywords, so application programs do not in general need to know anything about the specific implementation details of the HIERARCH convention. In particular, application programs do not need to specify the `HIERARCH' part of the keyword name when reading or writing keywords (although it may be included if desired). When writing a keyword, CFITSIO first checks to see if the keyword name is legal as a standard FITS keyword (no more than 8 characters long and containing only letters, digits, or a minus sign or underscore). If so it writes it as a standard FITS keyword, otherwise it uses the hierarch convention to write the keyword. The maximum keyword name length is 67 characters, which leaves only 1 space for the value field. A more practical limit is about 40 characters, which leaves enough room for most keyword values. CFITSIO returns an error if there is not enough room for both the keyword name and the keyword value on the 80-character card, except for string-valued keywords which are simply truncated so that the closing quote character falls in column 80. In the current implementation, CFITSIO preserves the case of the letters when writing the keyword name, but it is case-insensitive when reading or searching for a keyword. The current implementation allows any ASCII text character (ASCII 32 to ASCII 126) in the keyword name except for the '=' character. A space is also required on either side of the equal sign. **L. Optimizing Code for Maximum Processing Speed CFITSIO has been carefully designed to obtain the highest possible speed when reading and writing FITS files. In order to achieve the best performance, however, application programmers must be careful to call the CFITSIO routines appropriately and in an efficient sequence; inappropriate usage of CFITSIO routines can greatly slow down the execution speed of a program. The maximum possible I/O speed of CFITSIO depends of course on the type of computer system that it is running on. To get a general idea of what data I/O speeds are possible on a particular machine, build the speed.c program that is distributed with CFITSIO (type 'make speed' in the CFITSIO directory). This diagnostic program measures the speed of writing and reading back a test FITS image, a binary table, and an ASCII table. The following 2 sections provide some background on how CFITSIO internally manages the data I/O and describes some strategies that may be used to optimize the processing speed of software that uses CFITSIO. ***1. Background Information: How CFITSIO Manages Data I/O Many CFITSIO operations involve transferring only a small number of bytes to or from the FITS file (e.g, reading a keyword, or writing a row in a table); it would be very inefficient to physically read or write such small blocks of data directly in the FITS file on disk, therefore CFITSIO maintains a set of internal Input--Output (IO) buffers in RAM memory that each contain one FITS block (2880 bytes) of data. Whenever CFITSIO needs to access data in the FITS file, it first transfers the FITS block containing those bytes into one of the IO buffers in memory. The next time CFITSIO needs to access bytes in the same block it can then go to the fast IO buffer rather than using a much slower system disk access routine. The number of available IO buffers is determined by the NIOBUF parameter (in fitsio2.h) and is currently set to 40. Whenever CFITSIO reads or writes data it first checks to see if that block of the FITS file is already loaded into one of the IO buffers. If not, and if there is an empty IO buffer available, then it will load that block into the IO buffer (when reading a FITS file) or will initialize a new block (when writing to a FITS file). If all the IO buffers are already full, it must decide which one to reuse (generally the one that has been accessed least recently), and flush the contents back to disk if it has been modified before loading the new block. The one major exception to the above process occurs whenever a large contiguous set of bytes are accessed, as might occur when reading or writing a FITS image. In this case CFITSIO bypasses the internal IO buffers and simply reads or writes the desired bytes directly in the disk file with a single call to a low-level file read or write routine. The minimum threshold for the number of bytes to read or write this way is set by the MINDIRECT parameter and is currently set to 3 FITS blocks = 8640 bytes. This is the most efficient way to read or write large chunks of data. Note that this fast direct IO process is not applicable when accessing columns of data in a FITS table because the bytes are generally not contiguous since they are interleaved by the other columns of data in the table. This explains why the speed for accessing FITS tables is generally slower than accessing FITS images. Given this background information, the general strategy for efficiently accessing FITS files should now be apparent: when dealing with FITS images, read or write large chunks of data at a time so that the direct IO mechanism will be invoked; when accessing FITS headers or FITS tables, on the other hand, once a particular FITS block has been loading into one of the IO buffers, try to access all the needed information in that block before it gets flushed out of the IO buffer. It is important to avoid the situation where the same FITS block is being read then flushed from a IO buffer multiple times. The following section gives more specific suggestions for optimizing the use of CFITSIO. ***2. Optimization Strategies 1. Because the data in FITS files is always stored in "big-endian" byte order, where the first byte of numeric values contains the most significant bits and the last byte contains the least significant bits, CFITSIO must swap the order of the bytes when reading or writing FITS files when running on little-endian machines (e.g., Linux and Microsoft Windows operating systems running on PCs with x86 CPUs). On fairly new CPUs that support "SSSE3" machine instructions (e.g., starting with Intel Core 2 CPUs in 2007, and in AMD CPUs beginning in 2011) significantly faster 4-byte and 8-byte swapping algorithms are available. These faster byte swapping functions are not used by default in CFITSIO (because of the potential code portablility issues), but users can enable them on supported platforms by adding the appropriate compiler flags (-mssse3 with gcc or icc on linux) when compiling the swapproc.c source file, which will allow the compiler to generate code using the SSSE3 instruction set. A convenient way to do this is to configure the CFITSIO library with the following command: - > ./configure --enable-ssse3 - Note, however, that a binary executable file that is created using these faster functions will only run on machines that support the SSSE3 machine instructions. It will crash on machines that do not support them. For faster 2-byte swaps on virtually all x86-64 CPUs (even those that do not support SSSE3), a variant using only SSE2 instructions exists. SSE2 is enabled by default on x86\_64 CPUs with 64-bit operating systems (and is also automatically enabled by the --enable-ssse3 flag). When running on x86\_64 CPUs with 32-bit operating systems, these faster 2-byte swapping algorithms are not used by default in CFITSIO, but can be enabled explicitly with: - ./configure --enable-sse2 - Preliminary testing indicates that these SSSE3 and SSE2 based byte-swapping algorithms can boost the CFITSIO performance when reading or writing FITS images by 20\% - 30\% or more. It is important to note, however, that compiler optimization must be turned on (e.g., by using the -O1 or -O2 flags in gcc) when building programs that use these fast byte-swapping algorithms in order to reap the full benefit of the SSSE3 and SSE2 instructions; without optimization, the code may actually run slower than when using more traditional byte-swapping techniques. 2. When dealing with a FITS primary array or IMAGE extension, it is more efficient to read or write large chunks of the image at a time (at least 3 FITS blocks = 8640 bytes) so that the direct IO mechanism will be used as described in the previous section. Smaller chunks of data are read or written via the IO buffers, which is somewhat less efficient because of the extra copy operation and additional bookkeeping steps that are required. In principle it is more efficient to read or write as big an array of image pixels at one time as possible, however, if the array becomes so large that the operating system cannot store it all in RAM, then the performance may be degraded because of the increased swapping of virtual memory to disk. 3. When dealing with FITS tables, the most important efficiency factor in the software design is to read or write the data in the FITS file in a single pass through the file. An example of poor program design would be to read a large, 3-column table by sequentially reading the entire first column, then going back to read the 2nd column, and finally the 3rd column; this obviously requires 3 passes through the file which could triple the execution time of an I/O limited program. For small tables this is not important, but when reading multi-megabyte sized tables these inefficiencies can become significant. The more efficient procedure in this case is to read or write only as many rows of the table as will fit into the available internal I/O buffers, then access all the necessary columns of data within that range of rows. Then after the program is completely finished with the data in those rows it can move on to the next range of rows that will fit in the buffers, continuing in this way until the entire file has been processed. By using this procedure of accessing all the columns of a table in parallel rather than sequentially, each block of the FITS file will only be read or written once. The optimal number of rows to read or write at one time in a given table depends on the width of the table row, on the number of I/O buffers that have been allocated in FITSIO, and also on the number of other FITS files that are open at the same time (since one I/O buffer is always reserved for each open FITS file). Fortunately, a FITSIO routine is available that will return the optimal number of rows for a given table: call ftgrsz(unit, nrows, status). It is not critical to use exactly the value of nrows returned by this routine, as long as one does not exceed it. Using a very small value however can also lead to poor performance because of the overhead from the larger number of subroutine calls. The optimal number of rows returned by ftgrsz is valid only as long as the application program is only reading or writing data in the specified table. Any other calls to access data in the table header would cause additional blocks of data to be loaded into the I/O buffers displacing data from the original table, and should be avoided during the critical period while the table is being read or written. 4. Use binary table extensions rather than ASCII table extensions for better efficiency when dealing with tabular data. The I/O to ASCII tables is slower because of the overhead in formatting or parsing the ASCII data fields, and because ASCII tables are about twice as large as binary tables with the same information content. 5. Design software so that it reads the FITS header keywords in the same order in which they occur in the file. When reading keywords, FITSIO searches forward starting from the position of the last keyword that was read. If it reaches the end of the header without finding the keyword, it then goes back to the start of the header and continues the search down to the position where it started. In practice, as long as the entire FITS header can fit at one time in the available internal I/O buffers, then the header keyword access will be very fast and it makes little difference which order they are accessed. 6. Avoid the use of scaling (by using the BSCALE and BZERO or TSCAL and TZERO keywords) in FITS files since the scaling operations add to the processing time needed to read or write the data. In some cases it may be more efficient to temporarily turn off the scaling (using ftpscl or fttscl) and then read or write the raw unscaled values in the FITS file. 7. Avoid using the 'implicit datatype conversion' capability in FITSIO. For instance, when reading a FITS image with BITPIX = -32 (32-bit floating point pixels), read the data into a single precision floating point data array in the program. Forcing FITSIO to convert the data to a different datatype can significantly slow the program. 8. Where feasible, design FITS binary tables using vector column elements so that the data are written as a contiguous set of bytes, rather than as single elements in multiple rows. For example, it is faster to access the data in a table that contains a single row and 2 columns with TFORM keywords equal to '10000E' and '10000J', than it is to access the same amount of data in a table with 10000 rows which has columns with the TFORM keywords equal to '1E' and '1J'. In the former case the 10000 floating point values in the first column are all written in a contiguous block of the file which can be read or written quickly, whereas in the second case each floating point value in the first column is interleaved with the integer value in the second column of the same row so CFITSIO has to explicitly move to the position of each element to be read or written. 9. Avoid the use of variable length vector columns in binary tables, since any reading or writing of these data requires that CFITSIO first look up or compute the starting address of each row of data in the heap. In practice, this is probably not a significant efficiency issue. 10. When copying data from one FITS table to another, it is faster to transfer the raw bytes instead of reading then writing each column of the table. The FITSIO subroutines FTGTBS and FTPTBS (for ASCII tables), and FTGTBB and FTPTBB (for binary tables) will perform low-level reads or writes of any contiguous range of bytes in a table extension. These routines can be used to read or write a whole row (or multiple rows) of a table with a single subroutine call. These routines are fast because they bypass all the usual data scaling, error checking and machine dependent data conversion that is normally done by FITSIO, and they allow the program to write the data to the output file in exactly the same byte order. For these same reasons, use of these routines can be somewhat risky because no validation or machine dependent conversion is performed by these routines. In general these routines are only recommended for optimizing critical pieces of code and should only be used by programmers who thoroughly understand the internal byte structure of the FITS tables they are reading or writing. 11. Another strategy for improving the speed of writing a FITS table, similar to the previous one, is to directly construct the entire byte stream for a whole table row (or multiple rows) within the application program and then write it to the FITS file with ftptbb. This avoids all the overhead normally present in the column-oriented CFITSIO write routines. This technique should only be used for critical applications, because it makes the code more difficult to understand and maintain, and it makes the code more system dependent (e.g., do the bytes need to be swapped before writing to the FITS file?). 12. Finally, external factors such as the type of magnetic disk controller (SCSI or IDE), the size of the disk cache, the average seek speed of the disk, the amount of disk fragmentation, and the amount of RAM available on the system can all have a significant impact on overall I/O efficiency. For critical applications, a system administrator should review the proposed system hardware to identify any potential I/O bottlenecks. *VII. Basic Interface Routines This section defines a basic set of subroutines that can be used to perform the most common types of read and write operations on FITS files. New users should start with these subroutines and then, as needed, explore the more advance routines described in the following chapter to perform more complex or specialized operations. A right arrow symbol ($>$) is used to separate the input parameters from the output parameters in the definition of each routine. This symbol is not actually part of the calling sequence. Note that the status parameter is both an input and an output parameter and must be initialized = 0 prior to calling the FITSIO subroutines. Refer to Chapter 9 for the definition of all the parameters used by these interface routines. **A. FITSIO Error Status Routines \label{FTVERS} >1 Return the current version number of the fitsio library. The version number will be incremented with each new > release of CFITSIO. - FTVERS( > version) - >2 Return the descriptive text string corresponding to a FITSIO error status code. The 30-character length string contains a brief > description of the cause of the error. - FTGERR(status, > errtext) - >3 Return the top (oldest) 80-character error message from the internal FITSIO stack of error messages and shift any remaining messages on the stack up one level. Any FITSIO error will generate one or more messages on the stack. Call this routine repeatedly to get each message in sequence. The error stack is empty > when a blank string is returned. - FTGMSG( > errmsg) - >4 The FTPMRK routine puts an invisible marker on the CFITSIO error stack. The FTCMRK routine can then be used to delete any more recent error messages on the stack, back to the position of the marker. This preserves any older error messages on the stack. FTCMSG simply clears the entire error message stack. > These routines are called without any arguments. - FTPMRK FTCMRK FTCMSG - >5 Print out the error message corresponding to the input status value and all the error messages on the FITSIO stack to the specified file stream (stream can be either the string 'STDOUT' or 'STDERR'). > If the input status value = 0 then this routine does nothing. - FTRPRT (stream, > status) - >6 Write an 80-character message to the FITSIO error stack. Application programs should not normally write to the stack, but there may be > some situations where this is desirable. - FTPMSG(errmsg) - **B. File I/O Routines >1 Open an existing FITS file with readonly or readwrite access. This routine always opens the primary array (the first HDU) of the file, and does not move to a following extension, if one was specified as part of the filename. Use the FTNOPN routine to automatically move to the extension. This routine will also open IRAF images (.imh format files) and raw binary data arrays with READONLY access by first converting them on the fly into virtual FITS images. See the `Extended File Name Syntax' chapter for more details. The FTDKOPN routine simply opens the specified file without trying to interpret the filename using the extended > filename syntax. - FTOPEN(unit,filename,rwmode, > blocksize,status) FTDKOPN(unit,filename,rwmode, > blocksize,status) - >2 Open an existing FITS file with readonly or readwrite access and move to a following extension, if one was specified as part of the filename. (e.g., 'filename.fits+2' or 'filename.fits[2]' will move to the 3rd HDU in the file). Note that this routine differs from FTOPEN in that it does not > have the redundant blocksize argument. - FTNOPN(unit,filename,rwmode, > status) - >3 Open an existing FITS file with readonly or readwrite access and then move to the first HDU containing significant data, if a) an HDU name or number to open was not explicitly specified as part of the filename, and b) if the FITS file contains a null primary array (i.e., NAXIS = 0). In this case, it will look for the first IMAGE HDU with NAXIS > 0, or the first table that does not contain the strings `GTI' (Good Time Interval) or `OBSTABLE' in the EXTNAME keyword value. FTTOPN is similar, except it will move to the first significant table HDU (skipping over any image HDUs) in the file if a specific HDU name or number is not specified. FTIOPN will move to the first non-null > image HDU, skipping over any tables. - FTDOPN(unit,filename,rwmode, > status) FTTOPN(unit,filename,rwmode, > status) FTIOPN(unit,filename,rwmode, > status) - >4 Open and initialize a new empty FITS file. A template file may also be specified to define the structure of the new file (see section 4.2.4). The FTDKINIT routine simply creates the specified file without trying to interpret the filename using the extended > filename syntax. - FTINIT(unit,filename,blocksize, > status) FTDKINIT(unit,filename,blocksize, > status) - >>5 Close a FITS file previously opened with ftopen or ftinit - FTCLOS(unit, > status) - >6 Move to a specified (absolute) HDU in the FITS file (nhdu = 1 for the > FITS primary array) - FTMAHD(unit,nhdu, > hdutype,status) - >7 Create a primary array (if none already exists), or insert a new IMAGE extension immediately following the CHDU, or insert a new Primary Array at the beginning of the file. Any following extensions in the file will be shifted down to make room for the new extension. If the CHDU is the last HDU in the file then the new image extension will simply be appended to the end of the file. One can force a new primary array to be inserted at the beginning of the FITS file by setting status = -9 prior to calling the routine. In this case the existing primary array will be converted to an IMAGE extension. The new extension (or primary array) will become the CHDU. The FTIIMGLL routine is identical to the FTIIMG routine except that the 4th parameter (the length of each axis) is an array of 64-bit integers rather than an array > of 32-bit integers. - FTIIMG(unit,bitpix,naxis,naxes, > status) FTIIMGLL(unit,bitpix,naxis,naxesll, > status) - >8 Insert a new ASCII TABLE extension immediately following the CHDU. Any following extensions will be shifted down to make room for the new extension. If there are no other following extensions then the new table extension will simply be appended to the end of the file. The new extension will become the CHDU. The FTITABLL routine is identical to the FTITAB routine except that the 2nd and 3rd parameters (that give the size of the table) are 64-bit integers rather than 32-bit integers. Under normal circumstances, the nrows and nrowsll paramenters should have a value of 0; CFITSIO will automatically update > the number of rows as data is written to the table. - FTITAB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > status) FTITABLL(unit,rowlenll,nrowsll,tfields,ttype,tbcol,tform,tunit,extname, > status) - >9 Insert a new binary table extension immediately following the CHDU. Any following extensions will be shifted down to make room for the new extension. If there are no other following extensions then the new bintable extension will simply be appended to the end of the file. The new extension will become the CHDU. The FTIBINLL routine is identical to the FTIBIN routine except that the 2nd parameter (that gives the length of the table) is a 64-bit integer rather than a 32-bit integer. Under normal circumstances, the nrows and nrowsll paramenters should have a value of 0; CFITSIO will automatically update > the number of rows as data is written to the table. - FTIBIN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat > status) FTIBINLL(unit,nrowsll,tfields,ttype,tform,tunit,extname,varidat > status) - **C. Keyword I/O Routines >>1 Put (append) an 80-character record into the CHU. - FTPREC(unit,card, > status) - >2 Put (append) a new keyword of the appropriate datatype into the CHU. The E and D versions of this routine have the added feature that if the 'decimals' parameter is negative, then the 'G' display format rather then the 'E' format will be used when constructing the keyword value, taking the absolute value of 'decimals' for the precision. This will suppress trailing zeros, and will use a fixed format rather than an exponential format, > depending on the magnitude of the value. - FTPKY[JKLS](unit,keyword,keyval,comment, > status) FTPKY[EDFG](unit,keyword,keyval,decimals,comment, > status) - >3 Get the nth 80-character header record from the CHU. The first keyword in the header is at key\_no = 1; if key\_no = 0 then this subroutine simple moves the internal pointer to the beginning of the header so that subsequent keyword operations will start at the top of > the header; it also returns a blank card value in this case. - FTGREC(unit,key_no, > card,status) - >4 Get a keyword value (with the appropriate datatype) and comment from > the CHU - FTGKY[EDJKLS](unit,keyword, > keyval,comment,status) - >>5 Delete an existing keyword record. - FTDKEY(unit,keyword, > status) - **D. Data I/O Routines The following routines read or write data values in the current HDU of the FITS file. Automatic datatype conversion will be attempted for numerical datatypes if the specified datatype is different from the actual datatype of the FITS array or table column. >>1 Write elements into the primary data array or image extension. - FTPPR[BIJKED](unit,group,fpixel,nelements,values, > status) - >2 Read elements from the primary data array or image extension. Undefined array elements will be returned with a value = nullval, unless nullval = 0 in which case no checks for undefined pixels will be performed. The anyf parameter is set to true (= .true.) if any of the returned > elements were undefined. - FTGPV[BIJKED](unit,group,fpixel,nelements,nullval, > values,anyf,status) - >3 Write elements into an ASCII or binary table column. The `felem' parameter applies only to vector columns in binary tables and is > ignored when writing to ASCII tables. - FTPCL[SLBIJKEDCM](unit,colnum,frow,felem,nelements,values, > status) - >4 Read elements from an ASCII or binary table column. Undefined array elements will be returned with a value = nullval, unless nullval = 0 (or = ' ' for ftgcvs) in which case no checking for undefined values will be performed. The ANYF parameter is set to true if any of the returned elements are undefined. Any column, regardless of it's intrinsic datatype, may be read as a string. It should be noted however that reading a numeric column as a string is 10 - 100 times slower than reading the same column as a number due to the large overhead in constructing the formatted strings. The display format of the returned strings will be determined by the TDISPn keyword, if it exists, otherwise by the datatype of the column. The length of the returned strings can be determined with the ftgcdw routine. The following TDISPn display formats are currently supported: - Iw.m Integer Ow.m Octal integer Zw.m Hexadecimal integer Fw.d Fixed floating point Ew.d Exponential floating point Dw.d Exponential floating point Gw.d General; uses Fw.d if significance not lost, else Ew.d - where w is the width in characters of the displayed values, m is the minimum number of digits displayed, and d is the number of digits to the right of the > decimal. The .m field is optional. - FTGCV[SBIJKEDCM](unit,colnum,frow,felem,nelements,nullval, > values,anyf,status) - >5 Get the table column number and full name of the column whose name matches the input template string. See the `Advanced Interface Routines' > chapter for a full description of this routine. - FTGCNN(unit,casesen,coltemplate, > colname,colnum,status) - *VIII Advanced Interface Subroutines This chapter defines all the available subroutines in the FITSIO user interface. For completeness, the basic subroutines described in the previous chapter are also repeated here. A right arrow symbol is used here to separate the input parameters from the output parameters in the definition of each subroutine. This symbol is not actually part of the calling sequence. An alphabetical list and definition of all the parameters is given at the end of this section. **A. FITS File Open and Close Subroutines: \label{FTOPEN} >1 Open an existing FITS file with readonly or readwrite access. The FTDKOPN routine simply opens the specified file without trying to interpret the filename using the extended filename syntax. FTDOPN opens the file and also moves to the first HDU containing significant data, if no specific HDU is specified as part of the filename. FTTOPN and FTIOPN are similar except that they will move to the first table HDU or image HDU, respectively, >if a HDU name or number is not specified as part of the filename. - FTOPEN(unit,filename,rwmode, > blocksize,status) FTDKOPN(unit,filename,rwmode, > blocksize,status) FTDOPN(unit,filename,rwmode, > status) FTTOPN(unit,filename,rwmode, > status) FTIOPN(unit,filename,rwmode, > status) - >2 Open an existing FITS file with readonly or readwrite access and move to a following extension, if one was specified as part of the filename. (e.g., 'filename.fits+2' or 'filename.fits[2]' will move to the 3rd HDU in the file). Note that this routine differs from FTOPEN in that it does not > have the redundant blocksize argument. - FTNOPN(unit,filename,rwmode, > status) - >3 Reopen a FITS file that was previously opened with FTOPEN, FTNOPN, or FTINIT. The newunit number may then be treated as a separate file, and one may simultaneously read or write to 2 (or more) different extensions in the same file. The FTOPEN and FTNOPN routines (above) automatically detects cases where a previously opened file is being opened again, and then internally call FTREOPEN, so programs should rarely > need to explicitly call this routine. - FTREOPEN(unit, > newunit, status) - >4 Open and initialize a new empty FITS file. The FTDKINIT routine simply creates the specified file without trying to interpret the filename using the extended > filename syntax. - FTINIT(unit,filename,blocksize, > status) FTDKINIT(unit,filename,blocksize, > status) - >5 Create a new FITS file, using a template file to define its initial size and structure. The template may be another FITS HDU or an ASCII template file. If the input template file name is blank, then this routine behaves the same as FTINIT. The currently supported format of the ASCII template file is described under the fits\_parse\_template routine (in the general Utilities section), but this may change slightly later releases of > CFITSIO. - FTTPLT(unit, filename, tplfilename, > status) - >6 Flush internal buffers of data to the output FITS file previously opened with ftopen or ftinit. The routine usually never needs to be called, but doing so will ensure that if the program subsequently aborts, then the FITS file will > have at least been closed properly. - FTFLUS(unit, > status) - >>7 Close a FITS file previously opened with ftopen or ftinit - FTCLOS(unit, > status) - >8 Close and DELETE a FITS file previously opened with ftopen or ftinit. This routine may be useful in cases where a FITS file is created, but > an error occurs which prevents the complete file from being written. - FTDELT(unit, > status) - >9 Get the value of an unused I/O unit number which may then be used as input to FTOPEN or FTINIT. This routine searches for the first unused unit number in the range from with 99 down to 50. This routine just keeps an internal list of the allocated unit numbers and does not physically check that the Fortran unit is available (to be compatible with the SPP version of FITSIO). Thus users must not independently allocate any unit numbers in the range 50 - 99 if this routine is also to be used in the same program. This routine is provided for convenience only, and it is not required > that the unit numbers used by FITSIO be allocated by this routine. - FTGIOU( > iounit, status) - >10 Free (deallocate) an I/O unit number which was previously allocated with FTGIOU. All previously allocated unit numbers may be > deallocated at once by calling FTFIOU with iounit = -1. - FTFIOU(iounit, > status) - >11 Return the Fortran unit number that corresponds to the C fitsfile pointer value, or vice versa. These 2 C routines may be useful in mixed language programs where both C and Fortran subroutines need to access the same file. For example, if a FITS file is opened with unit 12 by a Fortran subroutine, then a C routine within the same program could get the fitfile pointer value to access the same file by calling 'fptr = CUnit2FITS(12)'. These routines return a value >of zero if an error occurs. - int CFITS2Unit(fitsfile *ptr); fitsfile* CUnit2FITS(int unit); - >11 Parse the input filename and return the HDU number that would be moved to if the file were opened with FTNOPN. The returned HDU number begins with 1 for the primary array, so for example, if the input filename = `myfile.fits[2]' then hdunum = 3 will be returned. FITSIO does not open the file to check if the extension actually exists if an extension number is specified. If an extension *name* is included in the file name specification (e.g. `myfile.fits[EVENTS]' then this routine will have to open the FITS file and look for the position of the named extension, then close file again. This is not possible if the file is being read from the stdin stream, and an error will be returned in this case. If the filename does not specify an explicit extension (e.g. 'myfile.fits') then hdunum = -99 will be returned, which is functionally equivalent to hdunum = 1. This routine is mainly used for backward compatibility in the ftools software package and is not recommended for general use. It is generally better and more efficient to first open the FITS file with FTNOPN, then use FTGHDN to determine which HDU in the file has been opened, rather than calling > FTEXTN followed by a call to FTNOPN. - FTEXTN(filename, > nhdu, status) - >>12 Return the name of the opened FITS file. - FTFLNM(unit, > filename, status) - >>13 Return the I/O mode of the open FITS file (READONLY = 0, READWRITE = 1). - FTFLMD(unit, > iomode, status) - >14 Return the file type of the opened FITS file (e.g. 'file://', 'ftp://', > etc.). - FTURLT(unit, > urltype, status) - >15 Parse the input filename or URL into its component parts: the file type (file://, ftp://, http://, etc), the base input file name, the name of the output file that the input file is to be copied to prior to opening, the HDU or extension specification, the filtering specifier, the binning specifier, and the column specifier. Blank strings will be returned for any components that are not present >in the input file name. - FTIURL(filename, > filetype, infile, outfile, extspec, filter, binspec, colspec, status) - >16 Parse the input file name and return the root file name. The root name includes the file type if specified, (e.g. 'ftp://' or 'http://') and the full path name, to the extent that it is specified in the input filename. It does not include the HDU name or number, or any filtering >specifications. - FTRTNM(filename, > rootname, status) - >16 Test if the input file or a compressed version of the file (with a .gz, .Z, .z, or .zip extension) exists on disk. The returned value of the 'exists' parameter will have 1 of the 4 following values: - 2: the file does not exist, but a compressed version does exist 1: the disk file does exist 0: neither the file nor a compressed version of the file exist -1: the input file name is not a disk file (could be a ftp, http, smem, or mem file, or a file piped in on the STDIN stream) - > - FTEXIST(filename, > exists, status); - **B. HDU-Level Operations \label{FTMAHD} When a FITS file is first opened or created, the internal buffers in FITSIO automatically point to the first HDU in the file. The following routines may be used to move to another HDU in the file. Note that the HDU numbering convention used in FITSIO denotes the primary array as the first HDU, the first extension in a FITS file is the second HDU, and so on. >1 Move to a specified (absolute) HDU in the FITS file (nhdu = 1 for the > FITS primary array) - FTMAHD(unit,nhdu, > hdutype,status) - >>2 Move to a new (existing) HDU forward or backwards relative to the CHDU - FTMRHD(unit,nmove, > hdutype,status) - >3 Move to the (first) HDU which has the specified extension type and EXTNAME (or HDUNAME) and EXTVER keyword values. The hdutype parameter may have a value of IMAGE\_HDU (0), ASCII\_TBL (1), BINARY\_TBL (2), or ANY\_HDU (-1) where ANY\_HDU means that only the extname and extver values will be used to locate the correct extension. If the input value of extver is 0 then the EXTVER keyword is ignored and the first HDU with a matching EXTNAME (or HDUNAME) keyword will be found. If no matching HDU is found in the file then the current HDU will remain unchanged > and a status = BAD\_HDU\_NUM (301) will be returned. - FTMNHD(unit, hdutype, extname, extver, > status) - >>4 Get the number of the current HDU in the FITS file (primary array = 1) - FTGHDN(unit, > nhdu) - >5 Return the type of the current HDU in the FITS file. The possible > values for hdutype are IMAGE\_HDU (0), ASCII\_TBL (1), or BINARY\_TBL (2). - FTGHDT(unit, > hdutype, status) - >6 Return the total number of HDUs in the FITS file. > The CHDU remains unchanged. - FTTHDU(unit, > hdunum, status) - >7 Create (append) a new empty HDU at the end of the FITS file. This new HDU becomes the Current HDU, but it is completely empty and contains no header keywords or data. It is recommended that FTIIMG, FTITAB or > FTIBIN be used instead of this routine. - FTCRHD(unit, > status) - >8 Create a primary array (if none already exists), or insert a new IMAGE extension immediately following the CHDU, or insert a new Primary Array at the beginning of the file. Any following extensions in the file will be shifted down to make room for the new extension. If the CHDU is the last HDU in the file then the new image extension will simply be appended to the end of the file. One can force a new primary array to be inserted at the beginning of the FITS file by setting status = -9 prior to calling the routine. In this case the existing primary array will be converted to an IMAGE extension. The new extension (or primary array) will become the CHDU. The FTIIMGLL routine is identical to the FTIIMG routine except that the 4th parameter (the length of each axis) is an array of 64-bit integers rather than an array > of 32-bit integers. - FTIIMG(unit,bitpix,naxis,naxes, > status) FTIIMGLL(unit,bitpix,naxis,naxesll, > status) - >9 Insert a new ASCII TABLE extension immediately following the CHDU. Any following extensions will be shifted down to make room for the new extension. If there are no other following extensions then the new table extension will simply be appended to the end of the file. The new extension will become the CHDU. The FTITABLL routine is identical to the FTITAB routine except that the 2nd and 3rd parameters (that give the size of the table) are 64-bit integers rather than > 32-bit integers. - FTITAB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > status) FTITABLL(unit,rowlenll,nrowsll,tfields,ttype,tbcol,tform,tunit,extname, > status) - >10 Insert a new binary table extension immediately following the CHDU. Any following extensions will be shifted down to make room for the new extension. If there are no other following extensions then the new bintable extension will simply be appended to the end of the file. The new extension will become the CHDU. The FTIBINLL routine is identical to the FTIBIN routine except that the 2nd parameter (that gives the length of the table) is a 64-bit integer rather than > a 32-bit integer. - FTIBIN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat > status) FTIBINLL(unit,nrowsll,tfields,ttype,tform,tunit,extname,varidat > status) - >11 Resize an image by modifing the size, dimensions, and/or datatype of the current primary array or image extension. If the new image, as specified by the input arguments, is larger than the current existing image in the FITS file then zero fill data will be inserted at the end of the current image and any following extensions will be moved further back in the file. Similarly, if the new image is smaller than the current image then any following extensions will be shifted up towards the beginning of the FITS file and the image data will be truncated to the new size. This routine rewrites the BITPIX, NAXIS, and NAXISn keywords with the appropriate values for new image. The FTRSIMLL routine is identical to the FTRSIM routine except that the 4th parameter (the length of each axis) is an array of 64-bit integers rather than an array > of 32-bit integers. - FTRSIM(unit,bitpix,naxis,naxes,status) FTRSIMLL(unit,bitpix,naxis,naxesll,status) - >12 Delete the CHDU in the FITS file. Any following HDUs will be shifted forward in the file, to fill in the gap created by the deleted HDU. In the case of deleting the primary array (the first HDU in the file) then the current primary array will be replace by a null primary array containing the minimum set of required keywords and no data. If there are more extensions in the file following the one that is deleted, then the the CHDU will be redefined to point to the following extension. If there are no following extensions then the CHDU will be redefined to point to the previous HDU. The output HDUTYPE parameter indicates the type of the new CHDU after > the previous CHDU has been deleted. - FTDHDU(unit, > hdutype,status) - >13 Copy all or part of the input FITS file and append it to the end of the output FITS file. If 'previous' (an integer parameter) is not equal to 0, then any HDUs preceding the current HDU in the input file will be copied to the output file. Similarly, 'current' and 'following' determine whether the current HDU, and/or any following HDUs in the input file will be copied to the output file. If all 3 parameters are not equal to zero, then the entire input file will be copied. On return, the current HDU in the input file will be unchanged, and the last copied HDU will be the > current HDU in the output file. - FTCPFL(iunit, ounit, previous, current, following, > status) - >14 Copy the entire CHDU from the FITS file associated with IUNIT to the CHDU of the FITS file associated with OUNIT. The output HDU must be empty and not already contain any keywords. Space will be reserved for MOREKEYS additional keywords in the output header if there is not already enough > space. - FTCOPY(iunit,ounit,morekeys, > status) - >15 Copy the header (and not the data) from the CHDU associated with inunit to the CHDU associated with outunit. If the current output HDU is not completely empty, then the CHDU will be closed and a new HDU will be appended to the output file. This routine will automatically transform the necessary keywords when copying a primary array to and image extension, or an image extension to a primary array. > An empty output data unit will be created (all values = 0). - FTCPHD(inunit, outunit, > status) - >16 Copy just the data from the CHDU associated with IUNIT to the CHDU associated with OUNIT. This will overwrite any data previously in the OUNIT CHDU. This low level routine is used by FTCOPY, but it may also be useful in certain application programs which want to copy the data from one FITS file to another but also want to modify the header keywords in the process. all the required header keywords must be written to the OUNIT CHDU before calling > this routine - FTCPDT(iunit,ounit, > status) - **C. Define or Redefine the structure of the CHDU \label{FTRDEF} It should rarely be necessary to call the subroutines in this section. FITSIO internally calls these routines whenever necessary, so any calls to these routines by application programs will likely be redundant. >1 This routine forces FITSIO to scan the current header keywords that define the structure of the HDU (such as the NAXISn, PCOUNT and GCOUNT keywords) so that it can initialize the internal buffers that describe the HDU structure. This routine may be used instead of the more complicated calls to ftpdef, ftadef or ftbdef. This routine is also very useful for reinitializing the structure of an HDU, if the number of rows in a table, as specified by the NAXIS2 keyword, > has been modified from its initial value. - FTRDEF(unit, > status) (DEPRECATED) - >2 Define the structure of the primary array or IMAGE extension. When writing GROUPed FITS files that by convention set the NAXIS1 keyword equal to 0, ftpdef must be called with naxes(1) = 1, NOT 0, otherwise FITSIO will report an error status=308 when trying to write data to a group. Note: it is usually simpler to call FTRDEF rather > than this routine. - FTPDEF(unit,bitpix,naxis,naxes,pcount,gcount, > status) (DEPRECATED) - >3 Define the structure of an ASCII table (TABLE) extension. Note: it > is usually simpler to call FTRDEF rather than this routine. - FTADEF(unit,rowlen,tfields,tbcol,tform,nrows > status) (DEPRECATED) - >4 Define the structure of a binary table (BINTABLE) extension. Note: it > is usually simpler to call FTRDEF rather than this routine. - FTBDEF(unit,tfields,tform,varidat,nrows > status) (DEPRECATED) - >5 Define the size of the Current Data Unit, overriding the length of the data unit as previously defined by ftpdef, ftadef, or ftbdef. This is useful if one does not know the total size of the data unit until after the data have been written. The size (in bytes) of an ASCII or Binary table is given by NAXIS1 * NAXIS2. (Note that to determine the value of NAXIS1 it is often more convenient to read the value of the NAXIS1 keyword from the output file, rather than computing the row length directly from all the TFORM keyword values). Note: it > is usually simpler to call FTRDEF rather than this routine. - FTDDEF(unit,bytlen, > status) (DEPRECATED) - >6 Define the zero indexed byte offset of the 'heap' measured from the start of the binary table data. By default the heap is assumed to start immediately following the regular table data, i.e., at location NAXIS1 x NAXIS2. This routine is only relevant for binary tables which contain variable length array columns (with TFORMn = 'Pt'). This subroutine also automatically writes the value of theap to a keyword in the extension header. This subroutine must be called after the required keywords have been written (with ftphbn) and after the table structure has been defined > (with ftbdef) but before any data is written to the table. - FTPTHP(unit,theap, > status) - **D. FITS Header I/O Subroutines ***1. Header Space and Position Routines \label{FTHDEF} >1 Reserve space in the CHU for MOREKEYS more header keywords. This subroutine may be called to reserve space for keywords which are to be written at a later time, after the data unit or subsequent extensions have been written to the FITS file. If this subroutine is not explicitly called, then the initial size of the FITS header will be limited to the space available at the time that the first data is written to the associated data unit. FITSIO has the ability to dynamically add more space to the header if needed, however it is more efficient > to preallocate the required space if the size is known in advance. - FTHDEF(unit,morekeys, > status) - >2 Return the number of existing keywords in the CHU (NOT including the END keyword which is not considered a real keyword) and the remaining space available to write additional keywords in the CHU. (returns KEYSADD = -1 if the header has not yet been closed). Note that FITSIO will attempt to dynamically add space for more > keywords if required when appending new keywords to a header. - FTGHSP(iunit, > keysexist,keysadd,status) - >3 Return the number of keywords in the header and the current position in the header. This returns the number of the keyword record that will be read next (or one greater than the position of the last keyword that was read or written). A value of 1 is returned if the pointer is > positioned at the beginning of the header. - FTGHPS(iunit, > keysexist,key_no,status) - ***2. Read or Write Standard Header Routines \label{FTPHPR} These subroutines provide a simple method of reading or writing most of the keyword values that are normally required in a FITS files. These subroutines are provided for convenience only and are not required to be used. If preferred, users may call the lower-level subroutines described in the previous section to individually read or write the required keywords. Note that in most cases, the required keywords such as NAXIS, TFIELD, TTYPEn, etc, which define the structure of the HDU must be written to the header before any data can be written to the image or table. >1 Put the primary header or IMAGE extension keywords into the CHU. There are 2 available routines: The simpler FTPHPS routine is equivalent to calling ftphpr with the default values of SIMPLE = true, pcount = 0, gcount = 1, and EXTEND = true. PCOUNT, GCOUNT and EXTEND keywords are not required in the primary header and are only written if pcount is not equal to zero, gcount is not equal to zero or one, and if extend is TRUE, respectively. When writing to an IMAGE extension, the >SIMPLE and EXTEND parameters are ignored. - FTPHPS(unit,bitpix,naxis,naxes, > status) FTPHPR(unit,simple,bitpix,naxis,naxes,pcount,gcount,extend, > status) - >2 Get primary header or IMAGE extension keywords from the CHU. When reading from an IMAGE extension the SIMPLE and EXTEND parameters are > ignored. - FTGHPR(unit,maxdim, > simple,bitpix,naxis,naxes,pcount,gcount,extend, status) - >3 Put the ASCII table header keywords into the CHU. The optional TUNITn and EXTNAME keywords are written only if the input string >values are not blank. - FTPHTB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > status) - >>4 Get the ASCII table header keywords from the CHU - FTGHTB(unit,maxdim, > rowlen,nrows,tfields,ttype,tbcol,tform,tunit, extname,status) - >5 Put the binary table header keywords into the CHU. The optional TUNITn and EXTNAME keywords are written only if the input string values are not blank. The pcount parameter, which specifies the size of the variable length array heap, should initially = 0; FITSIO will automatically update the PCOUNT keyword value if any variable length array data is written to the heap. The TFORM keyword value for variable length vector columns should have the form 'Pt(len)' or '1Pt(len)' where `t' is the data type code letter (A,I,J,E,D, etc.) and `len' is an integer specifying the maximum length of the vectors in that column (len must be greater than or equal to the longest vector in the column). If `len' is not specified when the table is created (e.g., the input TFORMn value is just '1Pt') then FITSIO will scan the column when the table is first closed and will append the maximum length to the TFORM keyword value. Note that if the table is subsequently modified to increase the maximum length of the vectors then the modifying program is responsible for also updating the TFORM > keyword value. - FTPHBN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat, > status) - >>6 Get the binary table header keywords from the CHU - FTGHBN(unit,maxdim, > nrows,tfields,ttype,tform,tunit,extname,varidat, status) - ***3. Write Keyword Subroutines \label{FTPREC} >>1 Put (append) an 80-character record into the CHU. - FTPREC(unit,card, > status) - >2 Put (append) a COMMENT keyword into the CHU. Multiple COMMENT keywords > will be written if the input comment string is longer than 72 characters. - FTPCOM(unit,comment, > status) - >3 Put (append) a HISTORY keyword into the CHU. Multiple HISTORY keywords > will be written if the input history string is longer than 72 characters. - FTPHIS(unit,history, > status) - >4 Put (append) the DATE keyword into the CHU. The keyword value will contain the current system date as a character string in 'dd/mm/yy' format. If a DATE keyword already exists in the header, then this subroutine will > simply update the keyword value in-place with the current date. - FTPDAT(unit, > status) - >5 Put (append) a new keyword of the appropriate datatype into the CHU. Note that FTPKYS will only write string values up to 68 characters in length; longer strings will be truncated. The FTPKLS routine can be used to write longer strings, using a non-standard FITS convention. The E and D versions of this routine have the added feature that if the 'decimals' parameter is negative, then the 'G' display format rather then the 'E' format will be used when constructing the keyword value, taking the absolute value of 'decimals' for the precision. This will suppress trailing zeros, and will use a fixed format rather than an exponential format, > depending on the magnitude of the value. - FTPKY[JKLS](unit,keyword,keyval,comment, > status) FTPKY[EDFG](unit,keyword,keyval,decimals,comment, > status) - >6 Put (append) a string valued keyword into the CHU which may be longer than 68 characters in length. This uses the Long String Keyword convention that is described in the "Usage Guidelines and Suggestions" section of this document. Since this uses a non-standard FITS convention to encode the long keyword string, programs which use this routine should also call the FTPLSW routine to add some COMMENT keywords to warn users of the FITS file that this convention is being used. FTPLSW also writes a keyword called LONGSTRN to record the version of the longstring convention that has been used, in case a new convention is adopted at some point in the future. If the LONGSTRN keyword is already present in the header, then FTPLSW will > simply return and will not write duplicate keywords. - FTPKLS(unit,keyword,keyval,comment, > status) FTPLSW(unit, > status) - >7 Put (append) a new keyword with an undefined, or null, value into the CHU. > The value string of the keyword is left blank in this case. - FTPKYU(unit,keyword,comment, > status) - >8 Put (append) a numbered sequence of keywords into the CHU. One may append the same comment to every keyword (and eliminate the need to have an array of identical comment strings, one for each keyword) by including the ampersand character as the last non-blank character in the (first) COMMENTS string parameter. This same string will then be used for the comment field in all the keywords. (Note that the SPP version of these routines only supports a single comment > string). - FTPKN[JKLS](unit,keyroot,startno,no_keys,keyvals,comments, > status) FTPKN[EDFG](unit,keyroot,startno,no_keys,keyvals,decimals,comments, > status) - >9 Copy an indexed keyword from one HDU to another, modifying the index number of the keyword name in the process. For example, this routine could read the TLMIN3 keyword from the input HDU (by giving keyroot = "TLMIN" and innum = 3) and write it to the output HDU with the keyword name TLMIN4 (by setting outnum = 4). If the input keyword does not exist, then this routine simply > returns without indicating an error. - FTCPKY(inunit, outunit, innum, outnum, keyroot, > status) - >10 Put (append) a 'triple precision' keyword into the CHU in F28.16 format. The floating point keyword value is constructed by concatenating the input integer value with the input double precision fraction value (which must have a value between 0.0 and 1.0). The FTGKYT routine should be used to read this keyword value, because the other keyword reading > subroutines will not preserve the full precision of the value. - FTPKYT(unit,keyword,intval,dblval,comment, > status) - >11 Write keywords to the CHDU that are defined in an ASCII template file. The format of the template file is described under the ftgthd > routine below. - FTPKTP(unit, filename, > status) - >12 Append the physical units string to an existing keyword. This routine uses a local convention, shown in the following example, in which the keyword units are enclosed in square brackets in the > beginning of the keyword comment field. - VELOCITY= 12.3 / [km/s] orbital speed FTPUNT(unit,keyword,units, > status) - ***4. Insert Keyword Subroutines \label{FTIREC} >1 Insert a new keyword record into the CHU at the specified position (i.e., immediately preceding the (keyno)th keyword in the header.) This 'insert record' subroutine is somewhat less efficient then the 'append record' subroutine (FTPREC) described above because > the remaining keywords in the header have to be shifted down one slot. - FTIREC(unit,key_no,card, > status) - >2 Insert a new keyword into the CHU. The new keyword is inserted immediately following the last keyword that has been read from the header. The FTIKLS subroutine works the same as the FTIKYS subroutine, except it also supports long string values greater than 68 characters in length. These 'insert keyword' subroutines are somewhat less efficient then the 'append keyword' subroutines described above because the remaining > keywords in the header have to be shifted down one slot. - FTIKEY(unit, card, > status) FTIKY[JKLS](unit,keyword,keyval,comment, > status) FTIKLS(unit,keyword,keyval,comment, > status) FTIKY[EDFG](unit,keyword,keyval,decimals,comment, > status) - >3 Insert a new keyword with an undefined, or null, value into the CHU. > The value string of the keyword is left blank in this case. - FTIKYU(unit,keyword,comment, > status) - ***5. Read Keyword Subroutines \label{FTGREC} These routines return the value of the specified keyword(s). Wild card characters (*, ?, or \#) may be used when specifying the name of the keyword to be read: a '?' will match any single character at that position in the keyword name and a '*' will match any length (including zero) string of characters. The '\#' character will match any consecutive string of decimal digits (0 - 9). Note that when a wild card is used in the input keyword name, the routine will only search for a match from the current header position to the end of the header. It will not resume the search from the top of the header back to the original header position as is done when no wildcards are included in the keyword name. If the desired keyword string is 8-characters long (the maximum length of a keyword name) then a '*' may be appended as the ninth character of the input name to force the keyword search to stop at the end of the header (e.g., 'COMMENT *' will search for the next COMMENT keyword). The ffgrec routine may be used to set the starting position when doing wild card searches. >1 Get the nth 80-character header record from the CHU. The first keyword in the header is at key\_no = 1; if key\_no = 0 then this subroutine simple moves the internal pointer to the beginning of the header so that subsequent keyword operations will start at the top of > the header; it also returns a blank card value in this case. - FTGREC(unit,key_no, > card,status) - >2 Get the name, value (as a string), and comment of the nth keyword in CHU. This routine also checks that the returned keyword name (KEYWORD) contains only legal ASCII characters. Call FTGREC and FTPSVC to bypass this error > check. - FTGKYN(unit,key_no, > keyword,value,comment,status) - >>3 Get the 80-character header record for the named keyword - FTGCRD(unit,keyword, > card,status) - >4 Get the next keyword whose name matches one of the strings in 'inclist' but does not match any of the strings in 'exclist'. The strings in inclist and exclist may contain wild card characters (*, ?, and \#) as described at the beginning of this section. This routine searches from the current header position to the end of the header, only, and does not continue the search from the top of the header back to the original position. The current header position may be reset with the ftgrec routine. Note that nexc may be set = 0 if there are no keywords to be excluded. This routine returns status = 202 if a matching > keyword is not found. - FTGNXK(unit,inclist,ninc,exclist,nexc, > card,status) - >5 Get the literal keyword value as a character string. Regardless of the datatype of the keyword, this routine simply returns the string of characters in the value field of the keyword along with > the comment field. - FTGKEY(unit,keyword, > value,comment,status) - >6 Get a keyword value (with the appropriate datatype) and comment from > the CHU - FTGKY[EDJKLS](unit,keyword, > keyval,comment,status) - >7 Read a string-valued keyword and return the string length, the value string, and/or the comment field. The first routine, FTGKSL, simply returns the length of the character string value of the specified keyword. The second routine, FTGSKY, also returns up to maxchar characters of the keyword value string, starting with the firstchar character, and the keyword comment string. The length argument returns the total length of the keyword value string regardless of how much of the string is actually returned (which depends on the value of the firstchar and maxchar arguments). These routines support string keywords that use the CONTINUE convention to continue long string values over multiple FITS header records. Normally, string-valued keywords have a maximum length of 68 characters, however, > CONTINUE'd string keywords may be arbitrarily long. - FTGKSL(unit,keyword, > length,status) FTGSKY(unit,keyword,firstchar,maxchar,> keyval,length,comment,status) - >8 Get a sequence of numbered keyword values. These > routines do not support wild card characters in the root name. - FTGKN[EDJKLS](unit,keyroot,startno,max_keys, > keyvals,nfound,status) - >9 Get the value of a floating point keyword, returning the integer and fractional parts of the value in separate subroutine arguments. This subroutine may be used to read any keyword but is especially > useful for reading the 'triple precision' keywords written by FTPKYT. - FTGKYT(unit,keyword, > intval,dblval,comment,status) - >10 Get the physical units string in an existing keyword. This routine uses a local convention, shown in the following example, in which the keyword units are enclosed in square brackets in the beginning of the keyword comment field. A blank string is returned if no units are defined > for the keyword. - VELOCITY= 12.3 / [km/s] orbital speed FTGUNT(unit,keyword, > units,status) - ***6. Modify Keyword Subroutines \label{FTMREC} Wild card characters, as described in the Read Keyword section, above, may be used when specifying the name of the keyword to be modified. >>1 Modify (overwrite) the nth 80-character header record in the CHU - FTMREC(unit,key_no,card, > status) - >2 Modify (overwrite) the 80-character header record for the named keyword in the CHU. This can be used to overwrite the name of the keyword as > well as its value and comment fields. - FTMCRD(unit,keyword,card, > status) - >3 Modify (overwrite) the name of an existing keyword in the CHU > preserving the current value and comment fields. - FTMNAM(unit,oldkey,keyword, > status) - >>4 Modify (overwrite) the comment field of an existing keyword in the CHU - FTMCOM(unit,keyword,comment, > status) - >5 Modify the value and comment fields of an existing keyword in the CHU. The FTMKLS subroutine works the same as the FTMKYS subroutine, except it also supports long string values greater than 68 characters in length. Optionally, one may modify only the value field and leave the comment field unchanged by setting the input COMMENT parameter equal to the ampersand character (\&). The E and D versions of this routine have the added feature that if the 'decimals' parameter is negative, then the 'G' display format rather then the 'E' format will be used when constructing the keyword value, taking the absolute value of 'decimals' for the precision. This will suppress trailing zeros, and will use a fixed format rather than an exponential format, > depending on the magnitude of the value. - FTMKY[JKLS](unit,keyword,keyval,comment, > status) FTMKLS(unit,keyword,keyval,comment, > status) FTMKY[EDFG](unit,keyword,keyval,decimals,comment, > status) - >6 Modify the value of an existing keyword to be undefined, or null. The value string of the keyword is set to blank. Optionally, one may leave the comment field unchanged by setting the > input COMMENT parameter equal to the ampersand character (\&). - FTMKYU(unit,keyword,comment, > status) - ***7. Update Keyword Subroutines \label{FTUCRD} >1 Update an 80-character record in the CHU. If the specified keyword already exists then that header record will be replaced with the input CARD string. If it does not exist then the new record will be added to the header. The FTUKLS subroutine works the same as the FTUKYS subroutine, except > it also supports long string values greater than 68 characters in length. - FTUCRD(unit,keyword,card, > status) - >2 Update the value and comment fields of a keyword in the CHU. The specified keyword is modified if it already exists (by calling FTMKYx) otherwise a new keyword is created by calling FTPKYx. The E and D versions of this routine have the added feature that if the 'decimals' parameter is negative, then the 'G' display format rather then the 'E' format will be used when constructing the keyword value, taking the absolute value of 'decimals' for the precision. This will suppress trailing zeros, and will use a fixed format rather than an exponential format, > depending on the magnitude of the value. - FTUKY[JKLS](unit,keyword,keyval,comment, > status) FTUKLS(unit,keyword,keyval,comment, > status) FTUKY[EDFG](unit,keyword,keyval,decimals,comment, > status) - >3 Update the value of an existing keyword to be undefined, or null, or insert a new undefined-value keyword if it doesn't already exist. > The value string of the keyword is left blank in this case. - FTUKYU(unit,keyword,comment, > status) - ***8. Delete Keyword Subroutines \label{FTDREC} >1 Delete an existing keyword record. The space previously occupied by the keyword is reclaimed by moving all the following header records up one row in the header. The first routine deletes a keyword at a specified position in the header (the first keyword is at position 1), whereas the second routine deletes a specifically named keyword. Wild card characters, as described in the Read Keyword section, above, may be used when specifying the name of the keyword to be deleted > (be careful!). - FTDREC(unit,key_no, > status) FTDKEY(unit,keyword, > status) - **F. Data Scaling and Undefined Pixel Parameters \label{FTPSCL} These subroutines define or modify the internal parameters used by FITSIO to either scale the data or to represent undefined pixels. Generally FITSIO will scale the data according to the values of the BSCALE and BZERO (or TSCALn and TZEROn) keywords, however these subroutines may be used to override the keyword values. This may be useful when one wants to read or write the raw unscaled values in the FITS file. Similarly, FITSIO generally uses the value of the BLANK or TNULLn keyword to signify an undefined pixel, but these routines may be used to override this value. These subroutines do not create or modify the corresponding header keyword values. >1 Reset the scaling factors in the primary array or image extension; does not change the BSCALE and BZERO keyword values and only affects the automatic scaling performed when the data elements are written/read to/from the FITS file. When reading from a FITS file the returned data value = (the value given in the FITS array) * BSCALE + BZERO. The inverse formula is used when writing data values to the FITS file. (NOTE: BSCALE and BZERO must be declared as Double Precision > variables). - FTPSCL(unit,bscale,bzero, > status) - >2 Reset the scaling parameters for a table column; does not change the TSCALn or TZEROn keyword values and only affects the automatic scaling performed when the data elements are written/read to/from the FITS file. When reading from a FITS file the returned data value = (the value given in the FITS array) * TSCAL + TZERO. The inverse formula is used when writing data values to the FITS file. (NOTE: TSCAL and TZERO must be declared as Double Precision > variables). - FTTSCL(unit,colnum,tscal,tzero, > status) - >3 Define the integer value to be used to signify undefined pixels in the primary array or image extension. This is only used if BITPIX = 8, 16, 32. or 64 This does not create or change the value of the BLANK keyword in the header. FTPNULLL is identical to FTPNUL except that the blank > value is a 64-bit integer instead of a 32-bit integer. - FTPNUL(unit,blank, > status) FTPNULLL(unit,blankll, > status) - >4 Define the string to be used to signify undefined pixels in a column in an ASCII table. This does not create or change the value > of the TNULLn keyword. - FTSNUL(unit,colnum,snull > status) - >5 Define the value to be used to signify undefined pixels in an integer column in a binary table (where TFORMn = 'B', 'I', 'J', or 'K'). This does not create or change the value of the TNULLn keyword. FTTNULLL is identical to FTTNUL except that the tnull > value is a 64-bit integer instead of a 32-bit integer. - FTTNUL(unit,colnum,tnull > status) FTTNULLL(unit,colnum,tnullll > status) - **G. FITS Primary Array or IMAGE Extension I/O Subroutines \label{FTPPR} These subroutines put or get data values in the primary data array (i.e., the first HDU in the FITS file) or an IMAGE extension. The data array is represented as a single one-dimensional array of pixels regardless of the actual dimensionality of the array, and the FPIXEL parameter gives the position within this 1-D array of the first pixel to read or write. Automatic data type conversion is performed for numeric data (except for complex data types) if the data type of the primary array (defined by the BITPIX keyword) differs from the data type of the array in the calling subroutine. The data values are also scaled by the BSCALE and BZERO header values as they are being written or read from the FITS array. The ftpscl subroutine MUST be called to define the scaling parameters when writing data to the FITS array or to override the default scaling value given in the header when reading the FITS array. Two sets of subroutines are provided to read the data array which differ in the way undefined pixels are handled. The first set of routines (FTGPVx) simply return an array of data elements in which undefined pixels are set equal to a value specified by the user in the 'nullval' parameter. An additional feature of these subroutines is that if the user sets nullval = 0, then no checks for undefined pixels will be performed, thus increasing the speed of the program. The second set of routines (FTGPFx) returns the data element array and, in addition, a logical array which defines whether the corresponding data pixel is undefined. The latter set of subroutines may be more convenient to use in some circumstances, however, it requires an additional array of logical values which can be unwieldy when working with large data arrays. Also for programmer convenience, sets of subroutines to directly read or write 2 and 3 dimensional arrays have been provided, as well as a set of subroutines to read or write any contiguous rectangular subset of pixels within the n-dimensional array. >1 Get the data type of the image (= BITPIX value). Possible returned values are: 8, 16, 32, 64, -32, or -64 corresponding to unsigned byte, signed 2-byte integer, signed 4-byte integer, signed 8-byte integer, real, and double. The second subroutine is similar to FTGIDT, except that if the image pixel values are scaled, with non-default values for the BZERO and BSCALE keywords, then this routine will return the 'equivalent' data type that is needed to store the scaled values. For example, if BITPIX = 16 and BSCALE = 0.1 then the equivalent data type is floating point, and -32 will be returned. There are 2 special cases: if the image contains unsigned 2-byte integer values, with BITPIX = 16, BSCALE = 1, and BZERO = 32768, then this routine will return a non-standard value of 20 for the bitpix value. Similarly if the image contains unsigned 4-byte integers, then bitpix will > be returned with a value of 40. - FTGIDT(unit, > bitpix,status) FTGIET(unit, > bitpix,status) - >>2 Get the dimension (number of axes = NAXIS) of the image - FTGIDM(unit, > naxis,status) - >3 Get the size of all the dimensions of the image. The FTGISZLL > routine returns an array of 64-bit integers instead of 32-bit integers. - FTGISZ(unit, maxdim, > naxes,status) FTGISZLL(unit, maxdim, > naxesll,status) - >4 Get the parameters that define the type and size of the image. This routine simply combines calls to the above 3 routines. The FTGIPRLL > routine returns an array of 64-bit integers instead of 32-bit integers. - FTGIPR(unit, maxdim, > bitpix, naxis, naxes, int *status) FTGIPRLL(unit, maxdim, > bitpix, naxis, naxesll, int *status) - >>5 Put elements into the data array - FTPPR[BIJKED](unit,group,fpixel,nelements,values, > status) - >6 Put elements into the data array, substituting the appropriate FITS null value for all elements which are equal to the value of NULLVAL. For integer FITS arrays, the null value defined by the previous call to FTPNUL will be substituted; for floating point FITS arrays (BITPIX = -32 or -64) then the special IEEE NaN (Not-a-Number) value will be > substituted. - FTPPN[BIJKED](unit,group,fpixel,nelements,values,nullval > status) - >>7 Set data array elements as undefined - FTPPRU(unit,group,fpixel,nelements, > status) - >8 Get elements from the data array. Undefined array elements will be returned with a value = nullval, unless nullval = 0 in which case no > checks for undefined pixels will be performed. - FTGPV[BIJKED](unit,group,fpixel,nelements,nullval, > values,anyf,status) - >9 Get elements and nullflags from data array. Any undefined array elements will have the corresponding flagvals element > set equal to .TRUE. - FTGPF[BIJKED](unit,group,fpixel,nelements, > values,flagvals,anyf,status) - >>10 Put values into group parameters - FTPGP[BIJKED](unit,group,fparm,nparm,values, > status) - >>11 Get values from group parameters - FTGGP[BIJKED](unit,group,fparm,nparm, > values,status) - The following 4 subroutines transfer FITS images with 2 or 3 dimensions to or from a data array which has been declared in the calling program. The dimensionality of the FITS image is passed by the naxis1, naxis2, and naxis3 parameters and the declared dimensions of the program array are passed in the dim1 and dim2 parameters. Note that the program array does not have to have the same dimensions as the FITS array, but must be at least as big. For example if a FITS image with NAXIS1 = NAXIS2 = 400 is read into a program array which is dimensioned as 512 x 512 pixels, then the image will just fill the lower left corner of the array with pixels in the range 1 - 400 in the X an Y directions. This has the effect of taking a contiguous set of pixel value in the FITS array and writing them to a non-contiguous array in program memory (i.e., there are now some blank pixels around the edge of the image in the program array). >>11 Put 2-D image into the data array - FTP2D[BIJKED](unit,group,dim1,naxis1,naxis2,image, > status) - >>12 Put 3-D cube into the data array - FTP3D[BIJKED](unit,group,dim1,dim2,naxis1,naxis2,naxis3,cube, > status) - >13 Get 2-D image from the data array. Undefined pixels in the array will be set equal to the value of 'nullval', unless nullval=0 in which case no testing for undefined pixels will > be performed. - FTG2D[BIJKED](unit,group,nullval,dim1,naxis1,naxis2, > image,anyf,status) - >14 Get 3-D cube from the data array. Undefined pixels in the array will be set equal to the value of 'nullval', unless nullval=0 in which case no testing for undefined pixels will > be performed. - FTG3D[BIJKED](unit,group,nullval,dim1,dim2,naxis1,naxis2,naxis3, > cube,anyf,status) - The following subroutines transfer a rectangular subset of the pixels in a FITS N-dimensional image to or from an array which has been declared in the calling program. The fpixels and lpixels parameters are integer arrays which specify the starting and ending pixels in each dimension of the FITS image that are to be read or written. (Note that these are the starting and ending pixels in the FITS image, not in the declared array). The array parameter is treated simply as a large one-dimensional array of the appropriate datatype containing the pixel values; The pixel values in the FITS array are read/written from/to this program array in strict sequence without any gaps; it is up to the calling routine to correctly interpret the dimensionality of this array. The two families of FITS reading routines (FTGSVx and FTGSFx subroutines) also have an 'incs' parameter which defines the data sampling interval in each dimension of the FITS array. For example, if incs(1)=2 and incs(2)=3 when reading a 2-dimensional FITS image, then only every other pixel in the first dimension and every 3rd pixel in the second dimension will be returned in the 'array' parameter. [Note: the FTGSSx family of routines which were present in previous versions of FITSIO have been superseded by the more general FTGSVx family of routines.] >>15 Put an arbitrary data subsection into the data array. - FTPSS[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,array, > status) - >16 Get an arbitrary data subsection from the data array. Undefined pixels in the array will be set equal to the value of 'nullval', unless nullval=0 in which case no testing for undefined pixels will > be performed. - FTGSV[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,incs,nullval, > array,anyf,status) - >17 Get an arbitrary data subsection from the data array. Any Undefined pixels in the array will have the corresponding 'flagvals' > element set equal to .TRUE. - FTGSF[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,incs, > array,flagvals,anyf,status) - **H. FITS ASCII and Binary Table Data I/O Subroutines ***1. Column Information Subroutines \label{FTGCNO} >1 Get the number of rows or columns in the current FITS table. The number of rows is given by the NAXIS2 keyword and the number of columns is given by the TFIELDS keyword in the header of the table. The FTGNRWLL routine is identical to FTGNRW except that the number of rows is returned as a 64-bit integer rather > than a 32-bit integer. - FTGNRW(unit, > nrows, status) FTGNRWLL(unit, > nrowsll, status) FTGNCL(unit, > ncols, status) - >2 Get the table column number (and name) of the column whose name matches an input template name. The table column names are defined by the TTYPEn keywords in the FITS header. If a column does not have a TTYPEn keyword, then these routines assume that the name consists of all blank characters. These 2 subroutines perform the same function except that FTGCNO only returns the number of the matching column whereas FTGCNN also returns the name of the column. If CASESEN = .true. then the column name match will be case-sensitive. The input column name template (COLTEMPLATE) is (1) either the exact name of the column to be searched for, or (2) it may contain wild cards characters (*, ?, or \#), or (3) it may contain the number of the desired column (where the number is expressed as ASCII digits). The first 2 wild cards behave similarly to UNIX filename matching: the '*' character matches any sequence of characters (including zero characters) and the '?' character matches any single character. The \# wildcard will match any consecutive string of decimal digits (0-9). As an example, the template strings 'AB?DE', 'AB*E', and 'AB*CDE' will all match the string 'ABCDE'. If more than one column name in the table matches the template string, then the first match is returned and the status value will be set to 237 as a warning that a unique match was not found. To find the other cases that match the template, simply call the subroutine again leaving the input status value equal to 237 and the next matching name will then be returned. Repeat this process until a status = 219 (column name not found) is returned. If these subroutines fail to match the template to any of the columns in the table, they lastly check if the template can be interpreted as a simple positive integer (e.g., '7', or '512') and if so, they return that column number. If no matches are found then a status = 219 error is returned. Note that the FITS Standard recommends that only letters, digits, and the underscore character be used in column names (with no embedded >spaces in the name). Trailing blank characters are not significant. - FTGCNO(unit,casesen,coltemplate, > colnum,status) FTGCNN(unit,casesen,coltemplate, > colname,colnum,status) - >3 Get the datatype of a column in an ASCII or binary table. This routine returns an integer code value corresponding to the datatype of the column. (See the FTBNFM and FTASFM subroutines in the Utilities section of this document for a list of the code values). The vector repeat count (which is alway 1 for ASCII table columns) is also returned. If the specified column has an ASCII character datatype (code = 16) then the width of a unit string in the column is also returned. Note that this routine supports the local convention for specifying arrays of strings within a binary table character column, using the syntax TFORM = 'rAw' where 'r' is the total number of characters (= the width of the column) and 'w' is the width of a unit string within the column. Thus if the column has TFORM = '60A12' then this routine will return datacode = 16, repeat = 60, and width = 12. (The TDIMn keyword may also be used to specify the unit string length; The pair of keywords TFORMn = '60A' and TDIMn = '(12,5)' would have the same effect as TFORMn = '60A12'). The second routine, FTEQTY is similar except that in the case of scaled integer columns it returns the 'equivalent' data type that is needed to store the scaled values, and not necessarily the physical data type of the unscaled values as stored in the FITS table. For example if a '1I' column in a binary table has TSCALn = 1 and TZEROn = 32768, then this column effectively contains unsigned short integer values, and thus the returned value of typecode will be the code for an unsigned short integer, not a signed short integer. Similarly, if a column has TTYPEn = '1I' and TSCALn = 0.12, then the returned typecode > will be the code for a 'real' column. - FTGTCL(unit,colnum, > datacode,repeat,width,status) FTEQTY(unit,colnum, > datacode,repeat,width,status) - >4 Return the display width of a column. This is the length of the string that will be returned when reading the column as a formatted string. The display width is determined by the TDISPn keyword, if present, otherwise by the data > type of the column. - FTGCDW(unit, colnum, > dispwidth, status) - >5 Get information about an existing ASCII table column. (NOTE: TSCAL and TZERO must be declared as Double Precision variables). All the > returned parameters are scalar quantities. - FTGACL(unit,colnum, > ttype,tbcol,tunit,tform,tscal,tzero,snull,tdisp,status) - >6 Get information about an existing binary table column. (NOTE: TSCAL and TZERO must be declared as Double Precision variables). DATATYPE is a character string which returns the datatype of the column as defined by the TFORMn keyword (e.g., 'I', 'J','E', 'D', etc.). In the case of an ASCII character column, DATATYPE will have a value of the form 'An' where 'n' is an integer expressing the width of the field in characters. For example, if TFORM = '160A8' then FTGBCL will return DATATYPE='A8' and REPEAT=20. All the returned parameters are scalar > quantities. - FTGBCL(unit,colnum, > ttype,tunit,datatype,repeat,tscal,tzero,tnull,tdisp,status) - >7 Put (append) a TDIMn keyword whose value has the form '(l,m,n...)' where l, m, n... are the dimensions of a multidimensional array > column in a binary table. - FTPTDM(unit,colnum,naxis,naxes, > status) - >8 Return the number of and size of the dimensions of a table column. Normally this information is given by the TDIMn keyword, but if this keyword is not present then this routine returns NAXIS = 1 > and NAXES(1) equal to the repeat count in the TFORM keyword. - FTGTDM(unit,colnum,maxdim, > naxis,naxes,status) - >9 Decode the input TDIMn keyword string (e.g. '(100,200)') and return the number of and size of the dimensions of a binary table column. If the input tdimstr character string is null, then this routine returns naxis = 1 and naxes[0] equal to the repeat count in the TFORM keyword. This routine > is called by FTGTDM. - FTDTDM(unit,tdimstr,colnum,maxdim, > naxis,naxes, status) - >10 Return the optimal number of rows to read or write at one time for maximum I/O efficiency. Refer to the ``Optimizing Code'' section > in Chapter 5 for more discussion on how to use this routine. - FTGRSZ(unit, > nrows,status) - ***2. Low-Level Table Access Subroutines \label{FTGTBS} The following subroutines provide low-level access to the data in ASCII or binary tables and are mainly useful as an efficient way to copy all or part of a table from one location to another. These routines simply read or write the specified number of consecutive bytes in an ASCII or binary table, without regard for column boundaries or the row length in the table. The first two subroutines read or write consecutive bytes in a table to or from a character string variable, while the last two subroutines read or write consecutive bytes to or from a variable declared as a numeric data type (e.g., INTEGER, INTEGER*2, REAL, DOUBLE PRECISION). These routines do not perform any machine dependent data conversion or byte swapping, except that conversion to/from ASCII format is performed by the FTGTBS and FTPTBS routines on machines which do not use ASCII character codes in the internal data representations (e.g., on IBM mainframe computers). >1 Read a consecutive string of characters from an ASCII table into a character variable (spanning columns and multiple rows if necessary) This routine should not be used with binary tables because of > complications related to passing string variables between C and Fortran. - FTGTBS(unit,frow,startchar,nchars, > string,status) - >2 Write a consecutive string of characters to an ASCII table from a character variable (spanning columns and multiple rows if necessary) This routine should not be used with binary tables because of > complications related to passing string variables between C and Fortran. - FTPTBS(unit,frow,startchar,nchars,string, > status) - >3 Read a consecutive array of bytes from an ASCII or binary table into a numeric variable (spanning columns and multiple rows if necessary). The array parameter may be declared as any numerical datatype as long as the array is at least 'nchars' bytes long, e.g., if nchars = 17, > then declare the array as INTEGER*4 ARRAY(5). - FTGTBB(unit,frow,startchar,nchars, > array,status) - >4 Write a consecutive array of bytes to an ASCII or binary table from a numeric variable (spanning columns and multiple rows if necessary) The array parameter may be declared as any numerical datatype as long as the array is at least 'nchars' bytes long, e.g., if nchars = 17, > then declare the array as INTEGER*4 ARRAY(5). - FTPTBB(unit,frow,startchar,nchars,array, > status) - ***3. Edit Rows or Columns \label{FTIROW} >1 Insert blank rows into an existing ASCII or binary table (in the CDU). All the rows FOLLOWING row FROW are shifted down by NROWS rows. If FROW or FROWLL equals 0 then the blank rows are inserted at the beginning of the table. These routines modify the NAXIS2 keyword to reflect the new number of rows in the table. Note that it is *not* necessary to insert rows in a table before writing data to those rows (indeed, it would be inefficient to do so). Instead, one may simply write data to any row of the table, whether that > row of data already exists or not. - FTIROW(unit,frow,nrows, > status) FTIROWLL(unit,frowll,nrowsll, > status) - >2 Delete rows from an existing ASCII or binary table (in the CDU). The NROWS (or NROWSLL) is the number of rows are deleted, starting with row FROW (or FROWLL), and any remaining rows in the table are shifted up to fill in the space. These routines modify the NAXIS2 keyword to reflect the new number > of rows in the table. - FTDROW(unit,frow,nrows, > status) FTDROWLL(unit,frowll,nrowsll, > status) - >3 Delete a list of rows from an ASCII or binary table (in the CDU). In the first routine, 'rowrange' is a character string listing the rows or row ranges to delete (e.g., '2-4, 5, 8-9'). In the second routine, 'rowlist' is an integer array of row numbers to be deleted from the table. nrows is the number of row numbers in the list. The first row in the table is 1 not 0. The list of row numbers > must be sorted in ascending order. - FTDRRG(unit,rowrange, > status) FTDRWS(unit,rowlist,nrows, > status) - >4 Insert a blank column (or columns) into an existing ASCII or binary table (in the CDU). COLNUM specifies the column number that the (first) new column should occupy in the table. NCOLS specifies how many columns are to be inserted. Any existing columns from this position and higher are moved over to allow room for the new column(s). The index number on all the following keywords will be incremented if necessary to reflect the new position of the column(s) in the table: TBCOLn, TFORMn, TTYPEn, TUNITn, TNULLn, TSCALn, TZEROn, TDISPn, TDIMn, TLMINn, TLMAXn, TDMINn, TDMAXn, TCTYPn, TCRPXn, TCRVLn, TCDLTn, TCROTn, > and TCUNIn. - FTICOL(unit,colnum,ttype,tform, > status) FTICLS(unit,colnum,ncols,ttype,tform, > status) - >5 Modify the vector length of a binary table column (e.g., change a column from TFORMn = '1E' to '20E'). The vector > length may be increased or decreased from the current value. - FTMVEC(unit,colnum,newveclen, > status) - >6 Delete a column from an existing ASCII or binary table (in the CDU). The index number of all the keywords listed above (for FTICOL) will be decremented if necessary to reflect the new position of the column(s) in the table. Those index keywords that refer to the deleted column will also be deleted. Note that the physical size of the FITS file will not be reduced by this operation, and the empty FITS blocks if any > at the end of the file will be padded with zeros. - FTDCOL(unit,colnum, > status) - >7 Copy a column from one HDU to another (or to the same HDU). If createcol = TRUE, then a new column will be inserted in the output table, at position `outcolumn', otherwise the existing output column will be overwritten (in which case it must have a compatible datatype). > Note that the first column in a table is at colnum = 1. - FTCPCL(inunit,outunit,incolnum,outcolnum,createcol, > status); - ***4. Read and Write Column Data Routines \label{FTPCLS} These subroutines put or get data values in the current ASCII or Binary table extension. Automatic data type conversion is performed for numerical data types (B,I,J,E,D) if the data type of the column (defined by the TFORM keyword) differs from the data type of the calling subroutine. The data values are also scaled by the TSCALn and TZEROn header values as they are being written to or read from the FITS array. The fttscl subroutine MUST be used to define the scaling parameters when writing data to the table or to override the default scaling values given in the header when reading from the table. Note that it is *not* necessary to insert rows in a table before writing data to those rows (indeed, it would be inefficient to do so). Instead, one may simply write data to any row of the table, whether that row of data already exists or not. In the case of binary tables with vector elements, the 'felem' parameter defines the starting pixel within the element vector. This parameter is ignored with ASCII tables. Similarly, in the case of binary tables the 'nelements' parameter specifies the total number of vector values read or written (continuing on subsequent rows if required) and not the number of table elements. Two sets of subroutines are provided to get the column data which differ in the way undefined pixels are handled. The first set of routines (FTGCV) simply return an array of data elements in which undefined pixels are set equal to a value specified by the user in the 'nullval' parameter. An additional feature of these subroutines is that if the user sets nullval = 0, then no checks for undefined pixels will be performed, thus increasing the speed of the program. The second set of routines (FTGCF) returns the data element array and in addition a logical array of flags which defines whether the corresponding data pixel is undefined. Any column, regardless of it's intrinsic datatype, may be read as a string. It should be noted however that reading a numeric column as a string is 10 - 100 times slower than reading the same column as a number due to the large overhead in constructing the formatted strings. The display format of the returned strings will be determined by the TDISPn keyword, if it exists, otherwise by the datatype of the column. The length of the returned strings can be determined with the ftgcdw routine. The following TDISPn display formats are currently supported: - Iw.m Integer Ow.m Octal integer Zw.m Hexadecimal integer Fw.d Fixed floating point Ew.d Exponential floating point Dw.d Exponential floating point Gw.d General; uses Fw.d if significance not lost, else Ew.d - where w is the width in characters of the displayed values, m is the minimum number of digits displayed, and d is the number of digits to the right of the decimal. The .m field is optional. >1 Put elements into an ASCII or binary table column (in the CDU). (The SPP FSPCLS routine has an additional integer argument after the VALUES character string which specifies the size of the 1st dimension of this 2-D CHAR array). The alternate version of these routines, whose names end in 'LL' after the datatype character, support large tables with more then 2*31 rows. When calling these routines, the frow and felem parameters > *must* be 64-bit integer*8 variables, instead of normal 4-byte integers. - FTPCL[SLBIJKEDCM](unit,colnum,frow,felem,nelements,values, > status) FTPCL[LBIJKEDCM]LL(unit,colnum,frow,felem,nelements,values, > status) - >2 Put elements into an ASCII or binary table column (in the CDU) substituting the appropriate FITS null value for any elements that are equal to NULLVAL. For ASCII TABLE extensions, the null value defined by the previous call to FTSNUL will be substituted; For integer FITS columns, in a binary table the null value defined by the previous call to FTTNUL will be substituted; For floating point FITS columns a special IEEE NaN (Not-a-Number) value will be substituted. The alternate version of these routines, whose names end in 'LL' after the datatype character, support large tables with more then 2*31 rows. When calling these routines, the frow and felem parameters > *must* be 64-bit integer*8 variables, instead of normal 4-byte integers. - FTPCN[SBIJKED](unit,colnum,frow,felem,nelements,values,nullval > status) FTPCN[SBIJKED]LL(unit,colnum,(I*8) frow,(I*8) felem,nelements,values, nullval > status) - >3 Put bit values into a binary byte ('B') or bit ('X') table column (in the CDU). LRAY is an array of logical values corresponding to the sequence of bits to be written. If LRAY is true then the corresponding bit is set to 1, otherwise the bit is set to 0. Note that in the case of 'X' columns, FITSIO will write to all 8 bits of each byte whether they are formally valid or not. Thus if the column is defined as '4X', and one calls FTPCLX with fbit=1 and nbit=8, then all 8 bits will be written into the first byte (as opposed to writing the first 4 bits into the first row and then the next 4 bits into the next row), even though the last 4 bits of each byte are formally > not defined. - FTPCLX(unit,colnum,frow,fbit,nbit,lray, > status) - >>4 Set table elements in a column as undefined - FTPCLU(unit,colnum,frow,felem,nelements, > status) - >5 Get elements from an ASCII or binary table column (in the CDU). These routines return the values of the table column array elements. Undefined array elements will be returned with a value = nullval, unless nullval = 0 (or = ' ' for ftgcvs) in which case no checking for undefined values will be performed. The ANYF parameter is set to true if any of the returned elements are undefined. (Note: the ftgcl routine simple gets an array of logical data values without any checks for undefined values; use the ftgcfl routine to check for undefined logical elements). (The SPP FSGCVS routine has an additional integer argument after the VALUES character string which specifies the size of the 1st dimension of this 2-D CHAR array). The alternate version of these routines, whose names end in 'LL' after the datatype character, support large tables with more then 2*31 rows. When calling these routines, the frow and felem parameters > *must* be 64-bit integer*8 variables, instead of normal 4-byte integers. - FTGCL(unit,colnum,frow,felem,nelements, > values,status) FTGCV[SBIJKEDCM](unit,colnum,frow,felem,nelements,nullval, > values,anyf,status) FTGCV[BIJKEDCM]LL(unit,colnum,(I*8) frow, (I*8) felem, nelements, nullval, > values,anyf,status) - >6 Get elements and null flags from an ASCII or binary table column (in the CHDU). These routines return the values of the table column array elements. Any undefined array elements will have the corresponding flagvals element set equal to .TRUE. The ANYF parameter is set to true if any of the returned elements are undefined. (The SPP FSGCFS routine has an additional integer argument after the VALUES character string which specifies the size of the 1st dimension of this 2-D CHAR array). The alternate version of these routines, whose names end in 'LL' after the datatype character, support large tables with more then 2*31 rows. When calling these routines, the frow and felem parameters > *must* be 64-bit integer*8 variables, instead of normal 4-byte integers. - FTGCF[SLBIJKEDCM](unit,colnum,frow,felem,nelements, > values,flagvals,anyf,status) FTGCF[BIJKED]LL(unit,colnum, (I*8) frow, (I*8) felem,nelements, > values,flagvals,anyf,status) - >7 Get an arbitrary data subsection from an N-dimensional array in a binary table vector column. Undefined pixels in the array will be set equal to the value of 'nullval', unless nullval=0 in which case no testing for undefined pixels will be performed. The first and last rows in the table to be read are specified by fpixels(naxis+1) and lpixels(naxis+1), and hence are treated as the next higher dimension of the FITS N-dimensional array. The INCS parameter specifies the sampling interval in > each dimension between the data elements that will be returned. - FTGSV[BIJKED](unit,colnum,naxis,naxes,fpixels,lpixels,incs,nullval, > array,anyf,status) - >8 Get an arbitrary data subsection from an N-dimensional array in a binary table vector column. Any Undefined pixels in the array will have the corresponding 'flagvals' element set equal to .TRUE. The first and last rows in the table to be read are specified by fpixels(naxis+1) and lpixels(naxis+1), and hence are treated as the next higher dimension of the FITS N-dimensional array. The INCS parameter specifies the sampling interval in each dimension between the data elements that will be > returned. - FTGSF[BIJKED](unit,colnum,naxis,naxes,fpixels,lpixels,incs, > array,flagvals,anyf,status) - >9 Get bit values from a byte ('B') or bit (`X`) table column (in the CDU). LRAY is an array of logical values corresponding to the sequence of bits to be read. If LRAY is true then the corresponding bit was set to 1, otherwise the bit was set to 0. Note that in the case of 'X' columns, FITSIO will read all 8 bits of each byte whether they are formally valid or not. Thus if the column is defined as '4X', and one calls FTGCX with fbit=1 and nbit=8, then all 8 bits will be read from the first byte (as opposed to reading the first 4 bits from the first row and then the first 4 bits from the next row), even though the last 4 bits of > each byte are formally not defined. - FTGCX(unit,colnum,frow,fbit,nbit, > lray,status) - >10 Read any consecutive set of bits from an 'X' or 'B' column and interpret them as an unsigned n-bit integer. NBIT must be less than or equal to 16 when calling FTGCXI, and less than or equal to 32 when calling FTGCXJ; there is no limit on the value of NBIT for FTGCXD, but the returned double precision value only has 48 bits of precision on most 32-bit word machines. The NBITS bits are interpreted as an unsigned integer unless NBITS = 16 (in FTGCXI) or 32 (in FTGCXJ) in which case the string of bits are interpreted as 16-bit or 32-bit 2's complement signed integers. If NROWS is greater than 1 then the same set of bits will be read from sequential rows in the table starting with row FROW. Note that the numbering convention used here for the FBIT parameter adopts 1 for the first element of the > vector of bits; this is the Most Significant Bit of the integer value. - FTGCX[IJD](unit,colnum,frow,nrows,fbit,nbit, > array,status) - >11 Get the descriptor for a variable length column in a binary table. The descriptor consists of 2 integer parameters: the number of elements in the array and the starting offset relative to the start of the heap. The first routine returns a single descriptor whereas the second routine > returns the descriptors for a range of rows in the table. - FTGDES(unit,colnum,rownum, > nelements,offset,status) FTGDESLL(unit,colnum,rownum, > nelementsll,offsetll,status) FTGDESS(unit,colnum,firstrow,nrows > nelements,offset, status) FTGDESSLL(unit,colnum,firstrow,nrows > nelementsll,offsetll, status) - >12 Write the descriptor for a variable length column in a binary table. These subroutines can be used in conjunction with FTGDES to enable 2 or more arrays to point to the same storage location to save > storage space if the arrays are identical. - FTPDES(unit,colnum,rownum,nelements,offset, > status) FTPDESLL(unit,colnum,rownum,nelementsll,offsetll, > status) - **I. Row Selection and Calculator Routines \label{FTFROW} These routines all parse and evaluate an input string containing a user defined arithmetic expression. The first 3 routines select rows in a FITS table, based on whether the expression evaluates to true (not equal to zero) or false (zero). The other routines evaluate the expression and calculate a value for each row of the table. The allowed expression syntax is described in the row filter section in the earlier `Extended File Name Syntax' chapter of this document. The expression may also be written to a text file, and the name of the file, prepended with a '@' character may be supplied for the 'expr' parameter (e.g. '@filename.txt'). The expression in the file can be arbitrarily complex and extend over multiple lines of the file. Lines that begin with 2 slash characters ('//') will be ignored and may be used to add comments to the file. >1 Evaluate a boolean expression over the indicated rows, returning an > array of flags indicating which rows evaluated to TRUE/FALSE - FTFROW(unit,expr,firstrow, nrows, > n_good_rows, row_status, status) - >>2 Find the first row which satisfies the input boolean expression - FTFFRW(unit, expr, > rownum, status) - >3 Evaluate an expression on all rows of a table. If the input and output files are not the same, copy the TRUE rows to the output file; if the output table is not empty, then this routine will append the new selected rows after the existing rows. If the >files are the same, delete the FALSE rows (preserve the TRUE rows). - FTSROW(inunit, outunit, expr, > status) - >4 Calculate an expression for the indicated rows of a table, returning the results, cast as datatype (TSHORT, TDOUBLE, etc), in array. If nulval==NULL, UNDEFs will be zeroed out. For vector results, the number of elements returned may be less than nelements if nelements is not an even multiple of the result dimension. Call FTTEXP to obtain >the dimensions of the results. - FTCROW(unit,datatype,expr,firstrow,nelements,nulval, > array,anynul,status) - >5 Evaluate an expression and write the result either to a column (if the expression is a function of other columns in the table) or to a keyword (if the expression evaluates to a constant and is not a function of other columns in the table). In the former case, the parName parameter is the name of the column (which may or may not already exist) into which to write the results, and parInfo contains an optional TFORM keyword value if a new column is being created. If a TFORM value is not specified then a default format will be used, depending on the expression. If the expression evaluates to a constant, then the result will be written to the keyword name given by the parName parameter, and the parInfo parameter may be used to supply an optional comment for the keyword. If the keyword does not already exist, then the name of the keyword must be preceded with a '\#' character, >otherwise the result will be written to a column with that name. - FTCALC(inunit, expr, outunit, parName, parInfo, > status) - >6 This calculator routine is similar to the previous routine, except that the expression is only evaluated over the specified row ranges. nranges specifies the number of row ranges, and firstrow >and lastrow give the starting and ending row number of each range. - FTCALC_RNG(inunit, expr, outunit, parName, parInfo, nranges, firstrow, lastrow, > status) - >7 Evaluate the given expression and return dimension and type information on the result. The returned dimensions correspond to a single row entry of the requested expression, and are equivalent to the result of fits\_read\_tdim(). Note that strings are considered to be one element regardless of string length. >If maxdim == 0, then naxes is optional. - FTTEXP(unit, expr, maxdim > datatype, nelem, naxis, naxes, status) - **J. Celestial Coordinate System Subroutines \label{FTGICS} The FITS community has adopted a set of keyword conventions that define the transformations needed to convert between pixel locations in an image and the corresponding celestial coordinates on the sky, or more generally, that define world coordinates that are to be associated with any pixel location in an n-dimensional FITS array. CFITSIO is distributed with a couple of self-contained World Coordinate System (WCS) routines, however, these routines DO NOT support all the latest WCS conventions, so it is STRONGLY RECOMMENDED that software developers use a more robust external WCS library. Several recommended libraries are: - WCSLIB - supported by Mark Calabretta WCSTools - supported by Doug Mink AST library - developed by the U.K. Starlink project - More information about the WCS keyword conventions and links to all of these WCS libraries can be found on the FITS Support Office web site at http://fits.gsfc.nasa.gov under the WCS link. The functions provided in these external WCS libraries will need access to the WCS information contained in the FITS file headers. One convenient way to pass this information to the external library is to use FITSIO to copy the header keywords into one long character string, and then pass this string to an interface routine in the external library that will extract the necessary WCS information (e.g., see the astFitsChan and astPutCards routines in the Starlink AST library). The following FITSIO routines DO NOT support the more recent WCS conventions that have been approved as part of the FITS standard. Consequently, the following routines ARE NOW DEPRECATED. It is STRONGLY RECOMMENDED that software developers not use these routines, and instead use an external WCS library, as described above. These routines are included mainly for backward compatibility with existing software. They support the following standard map projections: -SIN, -TAN, -ARC, -NCP, -GLS, -MER, and -AIT (these are the legal values for the coordtype parameter). These routines are based on similar functions in Classic AIPS. All the angular quantities are given in units of degrees. >1 Get the values of all the standard FITS celestial coordinate system keywords from the header of a FITS image (i.e., the primary array or an image extension). These values may then be passed to the subroutines that perform the coordinate transformations. If any or all of the WCS keywords are not present, then default values will be returned. If the first coordinate axis is the declination-like coordinate, then this routine will swap them so that the longitudinal-like coordinate is returned as the first axis. If the file uses the newer 'CDj\_i' WCS transformation matrix keywords instead of old style 'CDELTn' and 'CROTA2' keywords, then this routine will calculate and return the values of the equivalent old-style keywords. Note that the conversion from the new-style keywords to the old-style values is sometimes only an approximation, so if the approximation is larger than an internally defined threshold level, then CFITSIO will still return the approximate WCS keyword values, but will also return with status = 506, to warn the calling program that approximations have been made. It is then up to the calling program to decide whether the approximations are sufficiently accurate for the particular application, or whether more precise WCS transformations must be > performed using new-style WCS keywords directly. - FTGICS(unit, > xrval,yrval,xrpix,yrpix,xinc,yinc,rot,coordtype,status) - >2 Get the values of all the standard FITS celestial coordinate system keywords from the header of a FITS table where the X and Y (or RA and DEC coordinates are stored in 2 separate columns of the table. These values may then be passed to the subroutines that perform the > coordinate transformations. - FTGTCS(unit,xcol,ycol, > xrval,yrval,xrpix,yrpix,xinc,yinc,rot,coordtype,status) - >3 Calculate the celestial coordinate corresponding to the input > X and Y pixel location in the image. - FTWLDP(xpix,ypix,xrval,yrval,xrpix,yrpix,xinc,yinc,rot, coordtype, > xpos,ypos,status) - >4 Calculate the X and Y pixel location corresponding to the input > celestial coordinate in the image. - FTXYPX(xpos,ypos,xrval,yrval,xrpix,yrpix,xinc,yinc,rot, coordtype, > xpix,ypix,status) - **K. File Checksum Subroutines \label{FTPCKS} The following routines either compute or validate the checksums for the CHDU. The DATASUM keyword is used to store the numerical value of the 32-bit, 1's complement checksum for the data unit alone. If there is no data unit then the value is set to zero. The numerical value is stored as an ASCII string of digits, enclosed in quotes, because the value may be too large to represent as a 32-bit signed integer. The CHECKSUM keyword is used to store the ASCII encoded COMPLEMENT of the checksum for the entire HDU. Storing the complement, rather than the actual checksum, forces the checksum for the whole HDU to equal zero. If the file has been modified since the checksums were computed, then the HDU checksum will usually not equal zero. These checksum keyword conventions are based on a paper by Rob Seaman published in the proceedings of the ADASS IV conference in Baltimore in November 1994 and a later revision in June 1995. >1 Compute and write the DATASUM and CHECKSUM keyword values for the CHDU into the current header. The DATASUM value is the 32-bit checksum for the data unit, expressed as a decimal integer enclosed in single quotes. The CHECKSUM keyword value is a 16-character string which is the ASCII-encoded value for the complement of the checksum for the whole HDU. If these keywords already exist, their values will be updated only if necessary (i.e., if the file has been modified > since the original keyword values were computed). - FTPCKS(unit, > status) - >2 Update the CHECKSUM keyword value in the CHDU, assuming that the DATASUM keyword exists and already has the correct value. This routine calculates the new checksum for the current header unit, adds it to the data unit checksum, encodes the value into an ASCII string, and writes > the string to the CHECKSUM keyword. - FTUCKS(unit, > status) - >3 Verify the CHDU by computing the checksums and comparing them with the keywords. The data unit is verified correctly if the computed checksum equals the value of the DATASUM keyword. The checksum for the entire HDU (header plus data unit) is correct if it equals zero. The output DATAOK and HDUOK parameters in this subroutine are integers which will have a value = 1 if the data or HDU is verified correctly, a value = 0 if the DATASUM or CHECKSUM keyword is not present, or value = -1 > if the computed checksum is not correct. - FTVCKS(unit, > dataok,hduok,status) - >4 Compute and return the checksum values for the CHDU (as double precision variables) without creating or modifying the CHECKSUM and DATASUM keywords. This routine is used internally by > FTVCKS, but may be useful in other situations as well. - FTGCKS(unit, > datasum,hdusum,status) - >5 Encode a checksum value (stored in a double precision variable) into a 16-character string. If COMPLEMENT = .true. then the 32-bit > sum value will be complemented before encoding. - FTESUM(sum,complement, > checksum) - >6 Decode a 16 character checksum string into a double precision value. If COMPLEMENT = .true. then the 32-bit sum value will be complemented > after decoding. - FTDSUM(checksum,complement, > sum) - **L. Date and Time Utility Routines \label{FTGSDT} The following routines help to construct or parse the FITS date/time strings. Starting in the year 2000, the FITS DATE keyword values (and the values of other `DATE-' keywords) must have the form 'YYYY-MM-DD' (date only) or 'YYYY-MM-DDThh:mm:ss.ddd...' (date and time) where the number of decimal places in the seconds value is optional. These times are in UTC. The older 'dd/mm/yy' date format may not be used for dates after 01 January 2000. >1 Get the current system date. The returned year has 4 digits > (1999, 2000, etc.) - FTGSDT( > day, month, year, status ) - >2 Get the current system date and time string ('YYYY-MM-DDThh:mm:ss'). The time will be in UTC/GMT if available, as indicated by a returned timeref value = 0. If the returned value of timeref = 1 then this indicates that it was not possible to convert the local time to UTC, and thus the local >time was returned. - FTGSTM(> datestr, timeref, status) - >3 Construct a date string from the input date values. If the year is between 1900 and 1998, inclusive, then the returned date string will have the old FITS format ('dd/mm/yy'), otherwise the date string will have the new FITS format ('YYYY-MM-DD'). Use FTTM2S instead > to always return a date string using the new FITS format. - FTDT2S( year, month, day, > datestr, status) - >4 Construct a new-format date + time string ('YYYY-MM-DDThh:mm:ss.ddd...'). If the year, month, and day values all = 0 then only the time is encoded with format 'hh:mm:ss.ddd...'. The decimals parameter specifies how many decimal places of fractional seconds to include in the string. If `decimals' > is negative, then only the date will be return ('YYYY-MM-DD'). - FTTM2S( year, month, day, hour, minute, second, decimals, > datestr, status) - >5 Return the date as read from the input string, where the string may be in either the old ('dd/mm/yy') or new ('YYYY-MM-DDThh:mm:ss' or >'YYYY-MM-DD') FITS format. - FTS2DT(datestr, > year, month, day, status) - >6 Return the date and time as read from the input string, where the string may be in either the old or new FITS format. The returned hours, minutes, and seconds values will be set to zero if the input string does not include the time ('dd/mm/yy' or 'YYYY-MM-DD') . Similarly, the returned year, month, and date values will be set to zero if the >date is not included in the input string ('hh:mm:ss.ddd...'). - FTS2TM(datestr, > year, month, day, hour, minute, second, status) - **M. General Utility Subroutines \label{FTGHAD} The following utility subroutines may be useful for certain applications: >>1 Return the starting byte address of the CHDU and the next HDU. - FTGHAD(iunit, > curaddr, nextaddr) - >>2 Convert a character string to uppercase (operates in place). - FTUPCH(string) - >3 Compare the input template string against the reference string to see if they match. The template string may contain wildcard characters: '*' will match any sequence of characters (including zero characters) and '?' will match any single character in the reference string. The '\#' character will match any consecutive string of decimal digits (0 - 9). If CASESN = .true. then the match will be case sensitive. The returned MATCH parameter will be .true. if the 2 strings match, and EXACT will be .true. if the match is exact (i.e., if no wildcard characters were used in the match). > Both strings must be 68 characters or less in length. - FTCMPS(str_template, string, casesen, > match, exact) - >4 Test that the keyword name contains only legal characters: A-Z,0-9, > hyphen, and underscore. - FTTKEY(keyword, > status) - >5 Test that the keyword record contains only legal printable ASCII > characters - FTTREC(card, > status) - >6 Test whether the current header contains any NULL (ASCII 0) characters. These characters are illegal in the header, but they will go undetected by most of the CFITSIO keyword header routines, because the null is interpreted as the normal end-of-string terminator. This routine returns the position of the first null character in the header, or zero if there are no nulls. For example a returned value of 110 would indicate that the first NULL is located in the 30th character of the second keyword in the header (recall that each header record is 80 characters long). Note that this is one of the few FITSIO routines in which the returned > value is not necessarily equal to the status value). - FTNCHK(unit, > status) - >7 Parse a header keyword record and return the name of the keyword and the length of the name. The keyword name normally occupies the first 8 characters of the record, except under the HIERARCH convention where the name can > be up to 70 characters in length. - FTGKNM(card, > keyname, keylength, staThe '\#' character will match any consecutive string of decimal digits (0 - 9). tus) - >8 Parse a header keyword record. This subroutine parses the input header record to return the value (as a character string) and comment strings. If the keyword has no value (columns 9-10 not equal to '= '), then the value string is returned blank and the comment string is set equal to column 9 - 80 of the > input string. - FTPSVC(card, > value,comment,status) - >9 Construct a properly formated 80-character header keyword record from the input keyword name, keyword value, and keyword comment strings. Hierarchical keyword names (e.g., "ESO TELE CAM") are supported. The value string may contain an integer, floating point, logical, or quoted character string (e.g., "12", "15.7", "T", > or "'NGC 1313'"). - FTMKKY(keyname, value, comment, > card, status) - >10 Construct a sequence keyword name (ROOT + nnn). This subroutine appends the sequence number to the root string to create > a keyword name (e.g., 'NAXIS' + 2 = 'NAXIS2') - FTKEYN(keyroot,seq_no, > keyword,status) - >11 Construct a sequence keyword name (n + ROOT). This subroutine concatenates the sequence number to the front of the > root string to create a keyword name (e.g., 1 + 'CTYP' = '1CTYP') - FTNKEY(seq_no,keyroot, > keyword,status) - >12 Determine the datatype of a keyword value string. This subroutine parses the keyword value string (usually columns 11-30 > of the header record) to determine its datatype. - FTDTYP(value, > dtype,status) - >13 Return the class of input header record. The record is classified into one of the following categories (the class values are defined in fitsio.h). Note that this is one of the few FITSIO > routines that does not return a status value. - Class Value Keywords TYP_STRUC_KEY 10 SIMPLE, BITPIX, NAXIS, NAXISn, EXTEND, BLOCKED, GROUPS, PCOUNT, GCOUNT, END XTENSION, TFIELDS, TTYPEn, TBCOLn, TFORMn, THEAP, and the first 4 COMMENT keywords in the primary array that define the FITS format. TYP_CMPRS_KEY 20 The keywords used in the compressed image or table format, including ZIMAGE, ZCMPTYPE, ZNAMEn, ZVALn, ZTILEn, ZBITPIX, ZNAXISn, ZSCALE, ZZERO, ZBLANK TYP_SCAL_KEY 30 BSCALE, BZERO, TSCALn, TZEROn TYP_NULL_KEY 40 BLANK, TNULLn TYP_DIM_KEY 50 TDIMn TYP_RANG_KEY 60 TLMINn, TLMAXn, TDMINn, TDMAXn, DATAMIN, DATAMAX TYP_UNIT_KEY 70 BUNIT, TUNITn TYP_DISP_KEY 80 TDISPn TYP_HDUID_KEY 90 EXTNAME, EXTVER, EXTLEVEL, HDUNAME, HDUVER, HDULEVEL TYP_CKSUM_KEY 100 CHECKSUM, DATASUM TYP_WCS_KEY 110 CTYPEn, CUNITn, CRVALn, CRPIXn, CROTAn, CDELTn CDj_is, PVj_ms, LONPOLEs, LATPOLEs TCTYPn, TCTYns, TCUNIn, TCUNns, TCRVLn, TCRVns, TCRPXn, TCRPks, TCDn_k, TCn_ks, TPVn_m, TPn_ms, TCDLTn, TCROTn jCTYPn, jCTYns, jCUNIn, jCUNns, jCRVLn, jCRVns, iCRPXn, iCRPns, jiCDn, jiCDns, jPVn_m, jPn_ms, jCDLTn, jCROTn (i,j,m,n are integers, s is any letter) TYP_REFSYS_KEY 120 EQUINOXs, EPOCH, MJD-OBSs, RADECSYS, RADESYSs TYP_COMM_KEY 130 COMMENT, HISTORY, (blank keyword) TYP_CONT_KEY 140 CONTINUE TYP_USER_KEY 150 all other keywords class = FTGKCL (char *card) - >14 Parse the 'TFORM' binary table column format string. This subroutine parses the input TFORM character string and returns the integer datatype code, the repeat count of the field, and, in the case of character string fields, the length of the unit string. The following datatype codes are returned (the negative of the value is returned > if the column contains variable-length arrays): - Datatype DATACODE value bit, X 1 byte, B 11 logical, L 14 ASCII character, A 16 short integer, I 21 integer, J 41 real, E 42 double precision, D 82 complex 83 double complex 163 FTBNFM(tform, > datacode,repeat,width,status) - >15 Parse the 'TFORM' keyword value that defines the column format in an ASCII table. This routine parses the input TFORM character string and returns the datatype code, the width of the column, and (if it is a floating point column) the number of decimal places to the right of the decimal point. The returned datatype codes are the same as for the binary table, listed above, with the following additional rules: integer columns that are between 1 and 4 characters wide are defined to be short integers (code = 21). Wider integer columns are defined to be regular integers (code = 41). Similarly, Fixed decimal point columns (with TFORM = 'Fw.d') are defined to be single precision reals (code = 42) if w is between 1 and 7 characters wide, inclusive. Wider 'F' columns will return a double precision data code (= 82). 'Ew.d' format columns will have datacode = 42, > and 'Dw.d' format columns will have datacode = 82. - FTASFM(tform, > datacode,width,decimals,status) - >16 Calculate the starting column positions and total ASCII table width based on the input array of ASCII table TFORM values. The SPACE input parameter defines how many blank spaces to leave between each column (it is recommended to have one space between columns for better human > readability). - FTGABC(tfields,tform,space, > rowlen,tbcol,status) - >17 Parse a template string and return a formatted 80-character string suitable for appending to (or deleting from) a FITS header file. This subroutine is useful for parsing lines from an ASCII template file and reformatting them into legal FITS header records. The formatted string may then be passed to the FTPREC, FTMCRD, or FTDKEY subroutines > to append or modify a FITS header record. - FTGTHD(template, > card,hdtype,status) - The input TEMPLATE character string generally should contain 3 tokens: (1) the KEYNAME, (2) the VALUE, and (3) the COMMENT string. The TEMPLATE string must adhere to the following format: >- The KEYNAME token must begin in columns 1-8 and be a maximum of 8 characters long. If the first 8 characters of the template line are blank then the remainder of the line is considered to be a FITS comment (with a blank keyword name). A legal FITS keyword name may only contain the characters A-Z, 0-9, and '-' (minus sign) and underscore. This subroutine will automatically convert any lowercase characters to uppercase in the output string. If KEYNAME = 'COMMENT' or 'HISTORY' then the remainder of the line is considered to be a FITS > COMMENT or HISTORY record, respectively. >- The VALUE token must be separated from the KEYNAME token by one or more spaces and/or an '=' character. The datatype of the VALUE token (numeric, logical, or character string) is automatically determined and the output CARD string is formatted accordingly. The value token may be forced to be interpreted as a string (e.g. if it is a string of numeric digits) by enclosing it in single quotes. If the value token is a character string that contains 1 or more embedded blank space characters or slash ('/') characters then the > entire character string must be enclosed in single quotes. >- The COMMENT token is optional, but if present must be separated from > the VALUE token by a blank space or a '/' character. >- One exception to the above rules is that if the first non-blank character in the template string is a minus sign ('-') followed by a single token, or a single token followed by an equal sign, then it is interpreted as the name of a keyword which is to be > deleted from the FITS header. >- The second exception is that if the template string starts with a minus sign and is followed by 2 tokens then the second token is interpreted as the new name for the keyword specified by first token. In this case the old keyword name (first token) is returned in characters 1-8 of the returned CARD string, and the new keyword name (the second token) is returned in characters 41-48 of the returned CARD string. These old and new names may then be passed to the FTMNAM subroutine which will change > the keyword name. The HDTYPE output parameter indicates how the returned CARD string should be interpreted: - hdtype interpretation ------ ------------------------------------------------- -2 Modify the name of the keyword given in CARD(1:8) to the new name given in CARD(41:48) -1 CARD(1:8) contains the name of a keyword to be deleted from the FITS header. 0 append the CARD string to the FITS header if the keyword does not already exist, otherwise update the value/comment if the keyword is already present in the header. 1 simply append this keyword to the FITS header (CARD is either a HISTORY or COMMENT keyword). 2 This is a FITS END record; it should not be written to the FITS header because FITSIO automatically appends the END record when the header is closed. - EXAMPLES: The following lines illustrate valid input template strings: - INTVAL 7 This is an integer keyword RVAL 34.6 / This is a floating point keyword EVAL=-12.45E-03 This is a floating point keyword in exponential notation lval F This is a boolean keyword This is a comment keyword with a blank keyword name SVAL1 = 'Hello world' / this is a string keyword SVAL2 '123.5' this is also a string keyword sval3 123+ / this is also a string keyword with the value '123+ ' # the following template line deletes the DATE keyword - DATE # the following template line modifies the NAME keyword to OBJECT - NAME OBJECT - >18 Parse the input string containing a list of rows or row ranges, and return integer arrays containing the first and last row in each range. For example, if rowlist = "3-5, 6, 8-9" then it will return numranges = 3, rangemin = 3, 6, 8 and rangemax = 5, 6, 9. At most, 'maxranges' number of ranges will be returned. 'maxrows' is the maximum number of rows in the table; any rows or ranges larger than this will be ignored. The rows must be specified in increasing order, and the ranges must not overlap. A minus sign may be use to specify all the rows to the upper or lower bound, so "50-" means all the rows from 50 to the end of the table, and "-" > means all the rows in the table, from 1 - maxrows. - FTRWRG(rowlist, maxrows, maxranges, > numranges, rangemin, rangemax, status) - *VI. The CFITSIO Iterator Function The fits\_iterate\_data function in CFITSIO provides a unique method of executing an arbitrary user-supplied `work' function that operates on rows of data in FITS tables or on pixels in FITS images. Rather than explicitly reading and writing the FITS images or columns of data, one instead calls the CFITSIO iterator routine, passing to it the name of the user's work function that is to be executed along with a list of all the table columns or image arrays that are to be passed to the work function. The CFITSIO iterator function then does all the work of allocating memory for the arrays, reading the input data from the FITS file, passing them to the work function, and then writing any output data back to the FITS file after the work function exits. Because it is often more efficient to process only a subset of the total table rows at one time, the iterator function can determine the optimum amount of data to pass in each iteration and repeatedly call the work function until the entire table been processed. For many applications this single CFITSIO iterator function can effectively replace all the other CFITSIO routines for reading or writing data in FITS images or tables. Using the iterator has several important advantages over the traditional method of reading and writing FITS data files: \begin{itemize} \item It cleanly separates the data I/O from the routine that operates on the data. This leads to a more modular and `object oriented' programming style. \item It simplifies the application program by eliminating the need to allocate memory for the data arrays and eliminates most of the calls to the CFITSIO routines that explicitly read and write the data. \item It ensures that the data are processed as efficiently as possible. This is especially important when processing tabular data since the iterator function will calculate the most efficient number of rows in the table to be passed at one time to the user's work function on each iteration. \item Makes it possible for larger projects to develop a library of work functions that all have a uniform calling sequence and are all independent of the details of the FITS file format. \end{itemize} There are basically 2 steps in using the CFITSIO iterator function. The first step is to design the work function itself which must have a prescribed set of input parameters. One of these parameters is a structure containing pointers to the arrays of data; the work function can perform any desired operations on these arrays and does not need to worry about how the input data were read from the file or how the output data get written back to the file. The second step is to design the driver routine that opens all the necessary FITS files and initializes the input parameters to the iterator function. The driver program calls the CFITSIO iterator function which then reads the data and passes it to the user's work function. Further details on using the iterator function can be found in the companion CFITSIO User's Guide, and in the iter\_a.f, iter\_b.f and iter\_c.f example programs. *IV. Extended File Name Syntax **A. Overview CFITSIO supports an extended syntax when specifying the name of the data file to be opened or created that includes the following features: \begin{itemize} \item CFITSIO can read IRAF format images which have header file names that end with the '.imh' extension, as well as reading and writing FITS files, This feature is implemented in CFITSIO by first converting the IRAF image into a temporary FITS format file in memory, then opening the FITS file. Any of the usual CFITSIO routines then may be used to read the image header or data. Similarly, raw binary data arrays can be read by converting them on the fly into virtual FITS images. \item FITS files on the Internet can be read (and sometimes written) using the FTP, HTTP, or ROOT protocols. \item FITS files can be piped between tasks on the stdin and stdout streams. \item FITS files can be read and written in shared memory. This can potentially achieve much better data I/O performance compared to reading and writing the same FITS files on magnetic disk. \item Compressed FITS files in gzip or Unix COMPRESS format can be directly read. \item Output FITS files can be written directly in compressed gzip format, thus saving disk space. \item FITS table columns can be created, modified, or deleted 'on-the-fly' as the table is opened by CFITSIO. This creates a virtual FITS file containing the modifications that is then opened by the application program. \item Table rows may be selected, or filtered out, on the fly when the table is opened by CFITSIO, based on an arbitrary user-specified expression. Only rows for which the expression evaluates to 'TRUE' are retained in the copy of the table that is opened by the application program. \item Histogram images may be created on the fly by binning the values in table columns, resulting in a virtual N-dimensional FITS image. The application program then only sees the FITS image (in the primary array) instead of the original FITS table. \end{itemize} The latter 3 features in particular add very powerful data processing capabilities directly into CFITSIO, and hence into every task that uses CFITSIO to read or write FITS files. For example, these features transform a very simple program that just copies an input FITS file to a new output file (like the `fitscopy' program that is distributed with CFITSIO) into a multipurpose FITS file processing tool. By appending fairly simple qualifiers onto the name of the input FITS file, the user can perform quite complex table editing operations (e.g., create new columns, or filter out rows in a table) or create FITS images by binning or histogramming the values in table columns. In addition, these functions have been coded using new state-of-the art algorithms that are, in some cases, 10 - 100 times faster than previous widely used implementations. Before describing the complete syntax for the extended FITS file names in the next section, here are a few examples of FITS file names that give a quick overview of the allowed syntax: \begin{itemize} \item {\tt 'myfile.fits'}: the simplest case of a FITS file on disk in the current directory. \item {\tt 'myfile.imh'}: opens an IRAF format image file and converts it on the fly into a temporary FITS format image in memory which can then be read with any other CFITSIO routine. \item {\tt rawfile.dat[i512,512]}: opens a raw binary data array (a 512 x 512 short integer array in this case) and converts it on the fly into a temporary FITS format image in memory which can then be read with any other CFITSIO routine. \item {\tt myfile.fits.gz}: if this is the name of a new output file, the '.gz' suffix will cause it to be compressed in gzip format when it is written to disk. \item {\tt 'myfile.fits.gz[events, 2]'}: opens and uncompresses the gzipped file myfile.fits then moves to the extension which has the keywords EXTNAME = 'EVENTS' and EXTVER = 2. \item {\tt '-'}: a dash (minus sign) signifies that the input file is to be read from the stdin file stream, or that the output file is to be written to the stdout stream. \item {\tt 'ftp://legacy.gsfc.nasa.gov/test/vela.fits'}: FITS files in any ftp archive site on the Internet may be directly opened with read-only access. \item {\tt 'http://legacy.gsfc.nasa.gov/software/test.fits'}: any valid URL to a FITS file on the Web may be opened with read-only access. \item {\tt 'root://legacy.gsfc.nasa.gov/test/vela.fits'}: similar to ftp access except that it provides write as well as read access to the files across the network. This uses the root protocol developed at CERN. \item {\tt 'shmem://h2[events]'}: opens the FITS file in a shared memory segment and moves to the EVENTS extension. \item {\tt 'mem://'}: creates a scratch output file in core computer memory. The resulting 'file' will disappear when the program exits, so this is mainly useful for testing purposes when one does not want a permanent copy of the output file. \item {\tt 'myfile.fits[3; Images(10)]'}: opens a copy of the image contained in the 10th row of the 'Images' column in the binary table in the 3th extension of the FITS file. The application just sees this single image as the primary array. \item {\tt 'myfile.fits[1:512:2, 1:512:2]'}: opens a section of the input image ranging from the 1st to the 512th pixel in X and Y, and selects every second pixel in both dimensions, resulting in a 256 x 256 pixel image in this case. \item {\tt 'myfile.fits[EVENTS][col Rad = sqrt(X**2 + Y**2)]'}: creates and opens a temporary file on the fly (in memory or on disk) that is identical to myfile.fits except that it will contain a new column in the EVENTS extension called 'Rad' whose value is computed using the indicated expression which is a function of the values in the X and Y columns. \item {\tt 'myfile.fits[EVENTS][PHA > 5]'}: creates and opens a temporary FITS files that is identical to 'myfile.fits' except that the EVENTS table will only contain the rows that have values of the PHA column greater than 5. In general, any arbitrary boolean expression using a C or Fortran-like syntax, which may combine AND and OR operators, may be used to select rows from a table. \item {\tt 'myfile.fits[EVENTS][bin (X,Y)=1,2048,4]'}: creates a temporary FITS primary array image which is computed on the fly by binning (i.e, computing the 2-dimensional histogram) of the values in the X and Y columns of the EVENTS extension. In this case the X and Y coordinates range from 1 to 2048 and the image pixel size is 4 units in both dimensions, so the resulting image is 512 x 512 pixels in size. \item The final example combines many of these feature into one complex expression (it is broken into several lines for clarity): - 'ftp://legacy.gsfc.nasa.gov/data/sample.fits.gz[EVENTS] [col phacorr = pha * 1.1 - 0.3][phacorr >= 5.0 && phacorr <= 14.0] [bin (X,Y)=32]' - In this case, CFITSIO (1) copies and uncompresses the FITS file from the ftp site on the legacy machine, (2) moves to the 'EVENTS' extension, (3) calculates a new column called 'phacorr', (4) selects the rows in the table that have phacorr in the range 5 to 14, and finally (5) bins the remaining rows on the X and Y column coordinates, using a pixel size = 32 to create a 2D image. All this processing is completely transparent to the application program, which simply sees the final 2-D image in the primary array of the opened file. \end{itemize} The full extended CFITSIO FITS file name can contain several different components depending on the context. These components are described in the following sections: - When creating a new file: filetype://BaseFilename(templateName) When opening an existing primary array or image HDU: filetype://BaseFilename(outName)[HDUlocation][ImageSection] When opening an existing table HDU: filetype://BaseFilename(outName)[HDUlocation][colFilter][rowFilter][binSpec] - The filetype, BaseFilename, outName, HDUlocation, and ImageSection components, if present, must be given in that order, but the colFilter, rowFilter, and binSpec specifiers may follow in any order. Regardless of the order, however, the colFilter specifier, if present, will be processed first by CFITSIO, followed by the rowFilter specifier, and finally by the binSpec specifier. **A. Filetype The type of file determines the medium on which the file is located (e.g., disk or network) and, hence, which internal device driver is used by CFITSIO to read and/or write the file. Currently supported types are - file:// - file on local magnetic disk (default) ftp:// - a readonly file accessed with the anonymous FTP protocol. It also supports ftp://username:password@hostname/... for accessing password-protected ftp sites. http:// - a readonly file accessed with the HTTP protocol. It supports username:password just like the ftp driver. Proxy HTTP servers are supported using the http_proxy environment variable (see following note). stream:// - special driver to read an input FITS file from the stdin stream, and/or write an output FITS file to the stdout stream. This driver is fragile and has limited functionality (see the following note). gsiftp:// - access files on a computational grid using the gridftp protocol in the Globus toolkit (see following note). root:// - uses the CERN root protocol for writing as well as reading files over the network. shmem:// - opens or creates a file which persists in the computer's shared memory. mem:// - opens a temporary file in core memory. The file disappears when the program exits so this is mainly useful for test purposes when a permanent output file is not desired. - If the filetype is not specified, then type file:// is assumed. The double slashes '//' are optional and may be omitted in most cases. ***1. Notes about HTTP proxy servers A proxy HTTP server may be used by defining the address (URL) and port number of the proxy server with the http\_proxy environment variable. For example - setenv http_proxy http://heasarc.gsfc.nasa.gov:3128 - will cause CFITSIO to use port 3128 on the heasarc proxy server whenever reading a FITS file with HTTP. ***2. Notes about the stream filetype driver The stream driver can be used to efficiently read a FITS file from the stdin file stream or write a FITS to the stdout file stream. However, because these input and output streams must be accessed sequentially, the FITS file reading or writing application must also read and write the file sequentially, at least within the tolerances described below. CFITSIO supports 2 different methods for accessing FITS files on the stdin and stdout streams. The original method, which is invoked by specifying a dash character, "-", as the name of the file when opening or creating it, works by storing a complete copy of the entire FITS file in memory. In this case, when reading from stdin, CFITSIO will copy the entire stream into memory before doing any processing of the file. Similarly, when writing to stdout, CFITSIO will create a copy of the entire FITS file in memory, before finally flushing it out to the stdout stream when the FITS file is closed. Buffering the entire FITS file in this way allows the application to randomly access any part of the FITS file, in any order, but it also requires that the user have sufficient available memory (or virtual memory) to store the entire file, which may not be possible in the case of very large files. The newer stream filetype provides a more memory-efficient method of accessing FITS files on the stdin or stdout streams. Instead of storing a copy of the entire FITS file in memory, CFITSIO only uses a set of internal buffer which by default can store 40 FITS blocks, or about 100K bytes of the FITS file. The application program must process the FITS file sequentially from beginning to end, within this 100K buffer. Generally speaking the application program must conform to the following restrictions: \begin{itemize} \item The program must finish reading or writing the header keywords before reading or writing any data in the HDU. \item The HDU can contain at most about 1400 header keywords. This is the maximum that can fit in the nominal 40 FITS block buffer. In principle, this limit could be increased by recompiling CFITSIO with a larger buffer limit, which is set by the NIOBUF parameter in fitsio2.h. \item The program must read or write the data in a sequential manner from the beginning to the end of the HDU. Note that CFITSIO's internal 100K buffer allows a little latitude in meeting this requirement. \item The program cannot move back to a previous HDU in the FITS file. \item Reading or writing of variable length array columns in binary tables is not supported on streams, because this requires moving back and forth between the fixed-length portion of the binary table and the following heap area where the arrays are actually stored. \item Reading or writing of tile-compressed images is not supported on streams, because the images are internally stored using variable length arrays. \end{itemize} ***3. Notes about the gsiftp filetype DEPENDENCIES: Globus toolkit (2.4.3 or higher) (GT) should be installed. There are two different ways to install GT: 1) goto the globus toolkit web page www.globus.org and follow the download and compilation instructions; 2) goto the Virtual Data Toolkit web page http://vdt.cs.wisc.edu/ and follow the instructions (STRONGLY SUGGESTED); Once a globus client has been installed in your system with a specific flavour it is possible to compile and install the CFITSIO libraries. Specific configuration flags must be used: 1) --with-gsiftp[[=PATH]] Enable Globus Toolkit gsiftp protocol support PATH=GLOBUS\_LOCATION i.e. the location of your globus installation 2) --with-gsiftp-flavour[[=PATH] defines the specific Globus flavour ex. gcc32 Both the flags must be used and it is mandatory to set both the PATH and the flavour. USAGE: To access files on a gridftp server it is necessary to use a gsiftp prefix: example: gsiftp://remote\_server\_fqhn/directory/filename The gridftp driver uses a local buffer on a temporary file the file is located in the /tmp directory. If you have special permissions on /tmp or you do not have a /tmp directory, it is possible to force another location setting the GSIFTP\_TMPFILE environment variable (ex. export GSIFTP\_TMPFILE=/your/location/yourtmpfile). Grid FTP supports multi channel transfer. By default a single channel transmission is available. However, it is possible to modify this behavior setting the GSIFTP\_STREAMS environment variable (ex. export GSIFTP\_STREAMS=8). ***4. Notes about the root filetype The original rootd server can be obtained from: \verb-ftp://root.cern.ch/root/rootd.tar.gz- but, for it to work correctly with CFITSIO one has to use a modified version which supports a command to return the length of the file. This modified version is available in rootd subdirectory in the CFITSIO ftp area at - ftp://legacy.gsfc.nasa.gov/software/fitsio/c/root/rootd.tar.gz. - This small server is started either by inetd when a client requests a connection to a rootd server or by hand (i.e. from the command line). The rootd server works with the ROOT TNetFile class. It allows remote access to ROOT database files in either read or write mode. By default TNetFile assumes port 432 (which requires rootd to be started as root). To run rootd via inetd add the following line to /etc/services: - rootd 432/tcp - and to /etc/inetd.conf, add the following line: - rootd stream tcp nowait root /user/rdm/root/bin/rootd rootd -i - Force inetd to reread its conf file with "kill -HUP ". You can also start rootd by hand running directly under your private account (no root system privileges needed). For example to start rootd listening on port 5151 just type: \verb+rootd -p 5151+ Notice: no \& is needed. Rootd will go into background by itself. - Rootd arguments: -i says we were started by inetd -p port# specifies a different port to listen on -d level level of debug info written to syslog 0 = no debug (default) 1 = minimum 2 = medium 3 = maximum - Rootd can also be configured for anonymous usage (like anonymous ftp). To setup rootd to accept anonymous logins do the following (while being logged in as root): - - Add the following line to /etc/passwd: rootd:*:71:72:Anonymous rootd:/var/spool/rootd:/bin/false where you may modify the uid, gid (71, 72) and the home directory to suite your system. - Add the following line to /etc/group: rootd:*:72:rootd where the gid must match the gid in /etc/passwd. - Create the directories: mkdir /var/spool/rootd mkdir /var/spool/rootd/tmp chmod 777 /var/spool/rootd/tmp Where /var/spool/rootd must match the rootd home directory as specified in the rootd /etc/passwd entry. - To make writeable directories for anonymous do, for example: mkdir /var/spool/rootd/pub chown rootd:rootd /var/spool/rootd/pub - That's all. Several additional remarks: you can login to an anonymous server either with the names "anonymous" or "rootd". The password should be of type user@host.do.main. Only the @ is enforced for the time being. In anonymous mode the top of the file tree is set to the rootd home directory, therefore only files below the home directory can be accessed. Anonymous mode only works when the server is started via inetd. ***5. Notes about the shmem filetype: Shared memory files are currently supported on most Unix platforms, where the shared memory segments are managed by the operating system kernel and `live' independently of processes. They are not deleted (by default) when the process which created them terminates, although they will disappear if the system is rebooted. Applications can create shared memory files in CFITSIO by calling: - fit_create_file(&fitsfileptr, "shmem://h2", &status); - where the root `file' names are currently restricted to be 'h0', 'h1', 'h2', 'h3', etc., up to a maximum number defined by the the value of SHARED\_MAXSEG (equal to 16 by default). This is a prototype implementation of the shared memory interface and a more robust interface, which will have fewer restrictions on the number of files and on their names, may be developed in the future. When opening an already existing FITS file in shared memory one calls the usual CFITSIO routine: - fits_open_file(&fitsfileptr, "shmem://h7", mode, &status) - The file mode can be READWRITE or READONLY just as with disk files. More than one process can operate on READONLY mode files at the same time. CFITSIO supports proper file locking (both in READONLY and READWRITE modes), so calls to fits\_open\_file may be locked out until another other process closes the file. When an application is finished accessing a FITS file in a shared memory segment, it may close it (and the file will remain in the system) with fits\_close\_file, or delete it with fits\_delete\_file. Physical deletion is postponed until the last process calls ffclos/ffdelt. fits\_delete\_file tries to obtain a READWRITE lock on the file to be deleted, thus it can be blocked if the object was not opened in READWRITE mode. A shared memory management utility program called `smem', is included with the CFITSIO distribution. It can be built by typing `make smem'; then type `smem -h' to get a list of valid options. Executing smem without any options causes it to list all the shared memory segments currently residing in the system and managed by the shared memory driver. To get a list of all the shared memory objects, run the system utility program `ipcs [-a]'. **B. Base Filename The base filename is the name of the file optionally including the director/subdirectory path, and in the case of `ftp', `http', and `root' filetypes, the machine identifier. Examples: - myfile.fits !data.fits /data/myfile.fits fits.gsfc.nasa.gov/ftp/sampledata/myfile.fits.gz - When creating a new output file on magnetic disk (of type file://) if the base filename begins with an exclamation point (!) then any existing file with that same basename will be deleted prior to creating the new FITS file. Otherwise if the file to be created already exists, then CFITSIO will return an error and will not overwrite the existing file. Note that the exclamation point, '!', is a special UNIX character, so if it is used on the command line rather than entered at a task prompt, it must be preceded by a backslash to force the UNIX shell to pass it verbatim to the application program. If the output disk file name ends with the suffix '.gz', then CFITSIO will compress the file using the gzip compression algorithm before writing it to disk. This can reduce the amount of disk space used by the file. Note that this feature requires that the uncompressed file be constructed in memory before it is compressed and written to disk, so it can fail if there is insufficient available memory. An input FITS file may be compressed with the gzip or Unix compress algorithms, in which case CFITSIO will uncompress the file on the fly into a temporary file (in memory or on disk). Compressed files may only be opened with read-only permission. When specifying the name of a compressed FITS file it is not necessary to append the file suffix (e.g., `.gz' or `.Z'). If CFITSIO cannot find the input file name without the suffix, then it will automatically search for a compressed file with the same root name. In the case of reading ftp and http type files, CFITSIO generally looks for a compressed version of the file first, before trying to open the uncompressed file. By default, CFITSIO copies (and uncompressed if necessary) the ftp or http FITS file into memory on the local machine before opening it. This will fail if the local machine does not have enough memory to hold the whole FITS file, so in this case, the output filename specifier (see the next section) can be used to further control how CFITSIO reads ftp and http files. If the input file is an IRAF image file (*.imh file) then CFITSIO will automatically convert it on the fly into a virtual FITS image before it is opened by the application program. IRAF images can only be opened with READONLY file access. Similarly, if the input file is a raw binary data array, then CFITSIO will convert it on the fly into a virtual FITS image with the basic set of required header keywords before it is opened by the application program (with READONLY access). In this case the data type and dimensions of the image must be specified in square brackets following the filename (e.g. rawfile.dat[ib512,512]). The first character (case insensitive) defines the datatype of the array: - b 8-bit unsigned byte i 16-bit signed integer u 16-bit unsigned integer j 32-bit signed integer r or f 32-bit floating point d 64-bit floating point - An optional second character specifies the byte order of the array values: b or B indicates big endian (as in FITS files and the native format of SUN UNIX workstations and Mac PCs) and l or L indicates little endian (native format of DEC OSF workstations and IBM PCs). If this character is omitted then the array is assumed to have the native byte order of the local machine. These datatype characters are then followed by a series of one or more integer values separated by commas which define the size of each dimension of the raw array. Arrays with up to 5 dimensions are currently supported. Finally, a byte offset to the position of the first pixel in the data file may be specified by separating it with a ':' from the last dimension value. If omitted, it is assumed that the offset = 0. This parameter may be used to skip over any header information in the file that precedes the binary data. Further examples: - raw.dat[b10000] 1-dimensional 10000 pixel byte array raw.dat[rb400,400,12] 3-dimensional floating point big-endian array img.fits[ib512,512:2880] reads the 512 x 512 short integer array in a FITS file, skipping over the 2880 byte header - One special case of input file is where the filename = `-' (a dash or minus sign) or 'stdin' or 'stdout', which signifies that the input file is to be read from the stdin stream, or written to the stdout stream if a new output file is being created. In the case of reading from stdin, CFITSIO first copies the whole stream into a temporary FITS file (in memory or on disk), and subsequent reading of the FITS file occurs in this copy. When writing to stdout, CFITSIO first constructs the whole file in memory (since random access is required), then flushes it out to the stdout stream when the file is closed. In addition, if the output filename = '-.gz' or 'stdout.gz' then it will be gzip compressed before being written to stdout. This ability to read and write on the stdin and stdout steams allows FITS files to be piped between tasks in memory rather than having to create temporary intermediate FITS files on disk. For example if task1 creates an output FITS file, and task2 reads an input FITS file, the FITS file may be piped between the 2 tasks by specifying - task1 - | task2 - - where the vertical bar is the Unix piping symbol. This assumes that the 2 tasks read the name of the FITS file off of the command line. **C. Output File Name when Opening an Existing File An optional output filename may be specified in parentheses immediately following the base file name to be opened. This is mainly useful in those cases where CFITSIO creates a temporary copy of the input FITS file before it is opened and passed to the application program. This happens by default when opening a network FTP or HTTP-type file, when reading a compressed FITS file on a local disk, when reading from the stdin stream, or when a column filter, row filter, or binning specifier is included as part of the input file specification. By default this temporary file is created in memory. If there is not enough memory to create the file copy, then CFITSIO will exit with an error. In these cases one can force a permanent file to be created on disk, instead of a temporary file in memory, by supplying the name in parentheses immediately following the base file name. The output filename can include the '!' clobber flag. Thus, if the input filename to CFITSIO is: \verb+file1.fits.gz(file2.fits)+ then CFITSIO will uncompress `file1.fits.gz' into the local disk file `file2.fits' before opening it. CFITSIO does not automatically delete the output file, so it will still exist after the application program exits. In some cases, several different temporary FITS files will be created in sequence, for instance, if one opens a remote file using FTP, then filters rows in a binary table extension, then create an image by binning a pair of columns. In this case, the remote file will be copied to a temporary local file, then a second temporary file will be created containing the filtered rows of the table, and finally a third temporary file containing the binned image will be created. In cases like this where multiple files are created, the outfile specifier will be interpreted the name of the final file as described below, in descending priority: \begin{itemize} \item as the name of the final image file if an image within a single binary table cell is opened or if an image is created by binning a table column. \item as the name of the file containing the filtered table if a column filter and/or a row filter are specified. \item as the name of the local copy of the remote FTP or HTTP file. \item as the name of the uncompressed version of the FITS file, if a compressed FITS file on local disk has been opened. \item otherwise, the output filename is ignored. \end{itemize} The output file specifier is useful when reading FTP or HTTP-type FITS files since it can be used to create a local disk copy of the file that can be reused in the future. If the output file name = `*' then a local file with the same name as the network file will be created. Note that CFITSIO will behave differently depending on whether the remote file is compressed or not as shown by the following examples: \begin{itemize} \item `ftp://remote.machine/tmp/myfile.fits.gz(*)' - the remote compressed file is copied to the local compressed file `myfile.fits.gz', which is then uncompressed in local memory before being opened and passed to the application program. \item `ftp://remote.machine/tmp/myfile.fits.gz(myfile.fits)' - the remote compressed file is copied and uncompressed into the local file `myfile.fits'. This example requires less local memory than the previous example since the file is uncompressed on disk instead of in memory. \item `ftp://remote.machine/tmp/myfile.fits(myfile.fits.gz)' - this will usually produce an error since CFITSIO itself cannot compress files. \end{itemize} The exact behavior of CFITSIO in the latter case depends on the type of ftp server running on the remote machine and how it is configured. In some cases, if the file `myfile.fits.gz' exists on the remote machine, then the server will copy it to the local machine. In other cases the ftp server will automatically create and transmit a compressed version of the file if only the uncompressed version exists. This can get rather confusing, so users should use a certain amount of caution when using the output file specifier with FTP or HTTP file types, to make sure they get the behavior that they expect. **D. Template File Name when Creating a New File When a new FITS file is created with a call to fits\_create\_file, the name of a template file may be supplied in parentheses immediately following the name of the new file to be created. This template is used to define the structure of one or more HDUs in the new file. The template file may be another FITS file, in which case the newly created file will have exactly the same keywords in each HDU as in the template FITS file, but all the data units will be filled with zeros. The template file may also be an ASCII text file, where each line (in general) describes one FITS keyword record. The format of the ASCII template file is described below. **E. Image Tile-Compression Specification When specifying the name of the output FITS file to be created, the user can indicate that images should be written in tile-compressed format (see section 5.5, ``Primary Array or IMAGE Extension I/O Routines'') by enclosing the compression parameters in square brackets following the root disk file name. Here are some examples of the syntax for specifying tile-compressed output images: - myfile.fit[compress] - use Rice algorithm and default tile size myfile.fit[compress GZIP] - use the specified compression algorithm; myfile.fit[compress Rice] only the first letter of the algorithm myfile.fit[compress PLIO] name is required. myfile.fit[compress Rice 100,100] - use 100 x 100 pixel tile size myfile.fit[compress Rice 100,100;2] - as above, and use noisebits = 2 - **F. HDU Location Specification The optional HDU location specifier defines which HDU (Header-Data Unit, also known as an `extension') within the FITS file to initially open. It must immediately follow the base file name (or the output file name if present). If it is not specified then the first HDU (the primary array) is opened. The HDU location specifier is required if the colFilter, rowFilter, or binSpec specifiers are present, because the primary array is not a valid HDU for these operations. The HDU may be specified either by absolute position number, starting with 0 for the primary array, or by reference to the HDU name, and optionally, the version number and the HDU type of the desired extension. The location of an image within a single cell of a binary table may also be specified, as described below. The absolute position of the extension is specified either by enclosed the number in square brackets (e.g., `[1]' = the first extension following the primary array) or by preceded the number with a plus sign (`+1'). To specify the HDU by name, give the name of the desired HDU (the value of the EXTNAME or HDUNAME keyword) and optionally the extension version number (value of the EXTVER keyword) and the extension type (value of the XTENSION keyword: IMAGE, ASCII or TABLE, or BINTABLE), separated by commas and all enclosed in square brackets. If the value of EXTVER and XTENSION are not specified, then the first extension with the correct value of EXTNAME is opened. The extension name and type are not case sensitive, and the extension type may be abbreviated to a single letter (e.g., I = IMAGE extension or primary array, A or T = ASCII table extension, and B = binary table BINTABLE extension). If the HDU location specifier is equal to `[PRIMARY]' or `[P]', then the primary array (the first HDU) will be opened. FITS images are most commonly stored in the primary array or an image extension, but images can also be stored as a vector in a single cell of a binary table (i.e. each row of the vector column contains a different image). Such an image can be opened with CFITSIO by specifying the desired column name and the row number after the binary table HDU specifier as shown in the following examples. The column name is separated from the HDU specifier by a semicolon and the row number is enclosed in parentheses. In this case CFITSIO copies the image from the table cell into a temporary primary array before it is opened. The application program then just sees the image in the primary array, without any extensions. The particular row to be opened may be specified either by giving an absolute integer row number (starting with 1 for the first row), or by specifying a boolean expression that evaluates to TRUE for the desired row. The first row that satisfies the expression will be used. The row selection expression has the same syntax as described in the Row Filter Specifier section, below. Examples: - myfile.fits[3] - open the 3rd HDU following the primary array myfile.fits+3 - same as above, but using the FTOOLS-style notation myfile.fits[EVENTS] - open the extension that has EXTNAME = 'EVENTS' myfile.fits[EVENTS, 2] - same as above, but also requires EXTVER = 2 myfile.fits[events,2,b] - same, but also requires XTENSION = 'BINTABLE' myfile.fits[3; images(17)] - opens the image in row 17 of the 'images' column in the 3rd extension of the file. myfile.fits[3; images(exposure > 100)] - as above, but opens the image in the first row that has an 'exposure' column value greater than 100. - **G. Image Section A virtual file containing a rectangular subsection of an image can be extracted and opened by specifying the range of pixels (start:end) along each axis to be extracted from the original image. One can also specify an optional pixel increment (start:end:step) for each axis of the input image. A pixel step = 1 will be assumed if it is not specified. If the start pixel is larger then the end pixel, then the image will be flipped (producing a mirror image) along that dimension. An asterisk, '*', may be used to specify the entire range of an axis, and '-*' will flip the entire axis. The input image can be in the primary array, in an image extension, or contained in a vector cell of a binary table. In the later 2 cases the extension name or number must be specified before the image section specifier. Examples: - myfile.fits[1:512:2, 2:512:2] - open a 256x256 pixel image consisting of the odd numbered columns (1st axis) and the even numbered rows (2nd axis) of the image in the primary array of the file. myfile.fits[*, 512:256] - open an image consisting of all the columns in the input image, but only rows 256 through 512. The image will be flipped along the 2nd axis since the starting pixel is greater than the ending pixel. myfile.fits[*:2, 512:256:2] - same as above but keeping only every other row and column in the input image. myfile.fits[-*, *] - copy the entire image, flipping it along the first axis. myfile.fits[3][1:256,1:256] - opens a subsection of the image that is in the 3rd extension of the file. myfile.fits[4; images(12)][1:10,1:10] - open an image consisting of the first 10 pixels in both dimensions. The original image resides in the 12th row of the 'images' vector column in the table in the 4th extension of the file. - When CFITSIO opens an image section it first creates a temporary file containing the image section plus a copy of any other HDUs in the file. This temporary file is then opened by the application program, so it is not possible to write to or modify the input file when specifying an image section. Note that CFITSIO automatically updates the world coordinate system keywords in the header of the image section, if they exist, so that the coordinate associated with each pixel in the image section will be computed correctly. **H. Image Transform Filters CFITSIO can apply a user-specified mathematical function to the value of every pixel in a FITS image, thus creating a new virtual image in computer memory that is then opened and read by the application program. The original FITS image is not modified by this process. The image transformation specifier is appended to the input FITS file name and is enclosed in square brackets. It begins with the letters 'PIX' to distinguish it from other types of FITS file filters that are recognized by CFITSIO. The image transforming function may use any of the mathematical operators listed in the following 'Row Filtering Specification' section of this document. Some examples of image transform filters are: - [pix X * 2.0] - multiply each pixel by 2.0 [pix sqrt(X)] - take the square root of each pixel [pix X + #ZEROPT - add the value of the ZEROPT keyword [pix X>0 ? log10(X) : -99.] - if the pixel value is greater than 0, compute the base 10 log, else set the pixel = -99. - Use the letter 'X' in the expression to represent the current pixel value in the image. The expression is evaluated independently for each pixel in the image and may be a function of 1) the original pixel value, 2) the value of other pixels in the image at a given relative offset from the position of the pixel that is being evaluated, and 3) the value of any header keywords. Header keyword values are represented by the name of the keyword preceded by the '\#' sign. To access the the value of adjacent pixels in the image, specify the (1-D) offset from the current pixel in curly brackets. For example - [pix (x{-1} + x + x{+1}) / 3] - will replace each pixel value with the running mean of the values of that pixel and it's 2 neighboring pixels. Note that in this notation the image is treated as a 1-D array, where each row of the image (or higher dimensional cube) is appended one after another in one long array of pixels. It is possible to refer to pixels in the rows above or below the current pixel by using the value of the NAXIS1 header keyword. For example - [pix (x{-#NAXIS1} + x + x{#NAXIS1}) / 3] - will compute the mean of each image pixel and the pixels immediately above and below it in the adjacent rows of the image. The following more complex example creates a smoothed virtual image where each pixel is a 3 x 3 boxcar average of the input image pixels: - [pix (X + X{-1} + X{+1} + X{-#NAXIS1} + X{-#NAXIS1 - 1} + X{-#NAXIS1 + 1} + X{#NAXIS1} + X{#NAXIS1 - 1} + X{#NAXIS1 + 1}) / 9.] - If the pixel offset extends beyond the first or last pixel in the image, the function will evaluate to undefined, or NULL. For complex or commonly used image filtering operations, one can write the expression into an external text file and then import it into the filter using the syntax '[pix @filename.txt]'. The mathematical expression can extend over multiple lines of text in the file. Any lines in the external text file that begin with 2 slash characters ('//') will be ignored and may be used to add comments into the file. By default, the datatype of the resulting image will be the same as the original image, but one may force a different datatype by appended a code letter to the 'pix' keyword: - pixb - 8-bit byte image with BITPIX = 8 pixi - 16-bit integer image with BITPIX = 16 pixj - 32-bit integer image with BITPIX = 32 pixr - 32-bit float image with BITPIX = -32 pixd - 64-bit float image with BITPIX = -64 - Also by default, any other HDUs in the input file will be copied without change to the output virtual FITS file, but one may discard the other HDUs by adding the number '1' to the 'pix' keyword (and following any optional datatype code letter). For example: - myfile.fits[3][pixr1 sqrt(X)] - will create a virtual FITS file containing only a primary array image with 32-bit floating point pixels that have a value equal to the square root of the pixels in the image that is in the 3rd extension of the 'myfile.fits' file. **I. Column and Keyword Filtering Specification The optional column/keyword filtering specifier is used to modify the column structure and/or the header keywords in the HDU that was selected with the previous HDU location specifier. This filtering specifier must be enclosed in square brackets and can be distinguished from a general row filter specifier (described below) by the fact that it begins with the string 'col ' and is not immediately followed by an equals sign. The original file is not changed by this filtering operation, and instead the modifications are made on a copy of the input FITS file (usually in memory), which also contains a copy of all the other HDUs in the file. This temporary file is passed to the application program and will persist only until the file is closed or until the program exits, unless the outfile specifier (see above) is also supplied. The column/keyword filter can be used to perform the following operations. More than one operation may be specified by separating them with commas or semi-colons. \begin{itemize} \item Copy only a specified list of columns columns to the filtered input file. The list of column name should be separated by commas or semi-colons. Wild card characters may be used in the column names to match multiple columns. If the expression contains both a list of columns to be included and columns to be deleted, then all the columns in the original table except the explicitly deleted columns will appear in the filtered table (i.e., there is no need to explicitly list the columns to be included if any columns are being deleted). \item Delete a column or keyword by listing the name preceded by a minus sign or an exclamation mark (!), e.g., '-TIME' will delete the TIME column if it exists, otherwise the TIME keyword. An error is returned if neither a column nor keyword with this name exists. Note that the exclamation point, '!', is a special UNIX character, so if it is used on the command line rather than entered at a task prompt, it must be preceded by a backslash to force the UNIX shell to ignore it. \item Rename an existing column or keyword with the syntax 'NewName == OldName'. An error is returned if neither a column nor keyword with this name exists. \item Append a new column or keyword to the table. To create a column, give the new name, optionally followed by the datatype in parentheses, followed by a single equals sign and an expression to be used to compute the value (e.g., 'newcol(1J) = 0' will create a new 32-bit integer column called 'newcol' filled with zeros). The datatype is specified using the same syntax that is allowed for the value of the FITS TFORMn keyword (e.g., 'I', 'J', 'E', 'D', etc. for binary tables, and 'I8', F12.3', 'E20.12', etc. for ASCII tables). If the datatype is not specified then an appropriate datatype will be chosen depending on the form of the expression (may be a character string, logical, bit, long integer, or double column). An appropriate vector count (in the case of binary tables) will also be added if not explicitly specified. When creating a new keyword, the keyword name must be preceded by a pound sign '\#', and the expression must evaluate to a scalar (i.e., cannot have a column name in the expression). The comment string for the keyword may be specified in parentheses immediately following the keyword name (instead of supplying a datatype as in the case of creating a new column). If the keyword name ends with a pound sign '\#', then cfitsio will substitute the number of the most recently referenced column for the \# character . This is especially useful when writing a column-related keyword like TUNITn for a newly created column, as shown in the following examples. COMMENT and HISTORY keywords may also be created with the following syntax: - #COMMENT = 'This is a comment keyword' #HISTORY = 'This is a history keyword' - Note that the equal sign and the quote characters will be removed, so that the resulting header keywords in these cases will look like this: - COMMENT This is a comment keyword HISTORY This is a history keyword - These two special keywords are always appended to the end of the header and will not affect any previously existing COMMENT or HISTORY keywords. \item Recompute (overwrite) the values in an existing column or keyword by giving the name followed by an equals sign and an arithmetic expression. \end{itemize} The expression that is used when appending or recomputing columns or keywords can be arbitrarily complex and may be a function of other header keyword values and other columns (in the same row). The full syntax and available functions for the expression are described below in the row filter specification section. If the expression contains both a list of columns to be included and columns to be deleted, then all the columns in the original table except the explicitly deleted columns will appear in the filtered table. If no columns to be deleted are specified, then only the columns that are explicitly listed will be included in the filtered output table. To include all the columns, add the '*' wildcard specifier at the end of the list, as shown in the examples. For complex or commonly used operations, one can also place the operations into an external text file and import it into the column filter using the syntax '[col @filename.txt]'. The operations can extend over multiple lines of the file, but multiple operations must still be separated by commas or semi-colons. Any lines in the external text file that begin with 2 slash characters ('//') will be ignored and may be used to add comments into the file. Examples: - [col Time, rate] - only the Time and rate columns will appear in the filtered input file. [col Time, *raw] - include the Time column and any other columns whose name ends with 'raw'. [col -TIME; Good == STATUS] - deletes the TIME column and renames the status column to 'Good' [col PI=PHA * 1.1 + 0.2; #TUNIT#(column units) = 'counts';*] - creates new PI column from PHA values and also writes the TUNITn keyword for the new column. The final '*' expression means preserve all the columns in the input table in the virtual output table; without the '*' the output table would only contain the single 'PI' column. [col rate = rate/exposure, TUNIT#(&) = 'counts/s';*] - recomputes the rate column by dividing it by the EXPOSURE keyword value. This also modifies the value of the TUNITn keyword for this column. The use of the '&' character for the keyword comment string means preserve the existing comment string for that keyword. The final '*' preserves all the columns in the input table in the virtual output table. - **J. Row Filtering Specification When entering the name of a FITS table that is to be opened by a program, an optional row filter may be specified to select a subset of the rows in the table. A temporary new FITS file is created on the fly which contains only those rows for which the row filter expression evaluates to true. (The primary array and any other extensions in the input file are also copied to the temporary file). The original FITS file is closed and the new virtual file is opened by the application program. The row filter expression is enclosed in square brackets following the file name and extension name (e.g., 'file.fits[events][GRADE==50]' selects only those rows where the GRADE column value equals 50). When dealing with tables where each row has an associated time and/or 2D spatial position, the row filter expression can also be used to select rows based on the times in a Good Time Intervals (GTI) extension, or on spatial position as given in a SAO-style region file. ***1. General Syntax The row filtering expression can be an arbitrarily complex series of operations performed on constants, keyword values, and column data taken from the specified FITS TABLE extension. The expression must evaluate to a boolean value for each row of the table, where a value of FALSE means that the row will be excluded. For complex or commonly used filters, one can place the expression into a text file and import it into the row filter using the syntax '[@filename.txt]'. The expression can be arbitrarily complex and extend over multiple lines of the file. Any lines in the external text file that begin with 2 slash characters ('//') will be ignored and may be used to add comments into the file. Keyword and column data are referenced by name. Any string of characters not surrounded by quotes (ie, a constant string) or followed by an open parentheses (ie, a function name) will be initially interpreted as a column name and its contents for the current row inserted into the expression. If no such column exists, a keyword of that name will be searched for and its value used, if found. To force the name to be interpreted as a keyword (in case there is both a column and keyword with the same name), precede the keyword name with a single pound sign, '\#', as in '\#NAXIS2'. Due to the generalities of FITS column and keyword names, if the column or keyword name contains a space or a character which might appear as an arithmetic term then enclose the name in '\$' characters as in \$MAX PHA\$ or \#\$MAX-PHA\$. Names are case insensitive. To access a table entry in a row other than the current one, follow the column's name with a row offset within curly braces. For example, 'PHA\{-3\}' will evaluate to the value of column PHA, 3 rows above the row currently being processed. One cannot specify an absolute row number, only a relative offset. Rows that fall outside the table will be treated as undefined, or NULLs. Boolean operators can be used in the expression in either their Fortran or C forms. The following boolean operators are available: - "equal" .eq. .EQ. == "not equal" .ne. .NE. != "less than" .lt. .LT. < "less than/equal" .le. .LE. <= =< "greater than" .gt. .GT. > "greater than/equal" .ge. .GE. >= => "or" .or. .OR. || "and" .and. .AND. && "negation" .not. .NOT. ! "approx. equal(1e-7)" ~ - Note that the exclamation point, '!', is a special UNIX character, so if it is used on the command line rather than entered at a task prompt, it must be preceded by a backslash to force the UNIX shell to ignore it. The expression may also include arithmetic operators and functions. Trigonometric functions use radians, not degrees. The following arithmetic operators and functions can be used in the expression (function names are case insensitive). A null value will be returned in case of illegal operations such as divide by zero, sqrt(negative) log(negative), log10(negative), arccos(.gt. 1), arcsin(.gt. 1). - "addition" + "subtraction" - "multiplication" * "division" / "negation" - "exponentiation" ** ^ "absolute value" abs(x) "cosine" cos(x) "sine" sin(x) "tangent" tan(x) "arc cosine" arccos(x) "arc sine" arcsin(x) "arc tangent" arctan(x) "arc tangent" arctan2(y,x) "hyperbolic cos" cosh(x) "hyperbolic sin" sinh(x) "hyperbolic tan" tanh(x) "round to nearest int" round(x) "round down to int" floor(x) "round up to int" ceil(x) "exponential" exp(x) "square root" sqrt(x) "natural log" log(x) "common log" log10(x) "modulus" x % y "random # [0.0,1.0)" random() "random Gaussian" randomn() "random Poisson" randomp(x) "minimum" min(x,y) "maximum" max(x,y) "cumulative sum" accum(x) "sequential difference" seqdiff(x) "if-then-else" b?x:y "angular separation" angsep(ra1,dec1,ra2,de2) (all in degrees) "substring" strmid(s,p,n) "string search" strstr(s,r) - Three different random number functions are provided: random(), with no arguments, produces a uniform random deviate between 0 and 1; randomn(), also with no arguments, produces a normal (Gaussian) random deviate with zero mean and unit standard deviation; randomp(x) produces a Poisson random deviate whose expected number of counts is X. X may be any positive real number of expected counts, including fractional values, but the return value is an integer. When the random functions are used in a vector expression, by default the same random value will be used when evaluating each element of the vector. If different random numbers are desired, then the name of a vector column should be supplied as the single argument to the random function (e.g., "flux + 0.1 * random(flux)", where "flux' is the name of a vector column). This will create a vector of random numbers that will be used in sequence when evaluating each element of the vector expression. An alternate syntax for the min and max functions has only a single argument which should be a vector value (see below). The result will be the minimum/maximum element contained within the vector. The accum(x) function forms the cumulative sum of x, element by element. Vector columns are supported simply by performing the summation process through all the values. Null values are treated as 0. The seqdiff(x) function forms the sequential difference of x, element by element. The first value of seqdiff is the first value of x. A single null value in x causes a pair of nulls in the output. The seqdiff and accum functions are functional inverses, i.e., seqdiff(accum(x)) == x as long as no null values are present. In the if-then-else expression, "b?x:y", b is an explicit boolean value or expression. There is no automatic type conversion from numeric to boolean values, so one needs to use "iVal!=0" instead of merely "iVal" as the boolean argument. x and y can be any scalar data type (including string). The angsep function computes the angular separation in degrees between 2 celestial positions, where the first 2 parameters give the RA-like and Dec-like coordinates (in decimal degrees) of the first position, and the 3rd and 4th parameters give the coordinates of the second position. The substring function strmid(S,P,N) extracts a substring from S, starting at string position P, with a substring length N. The first character position in S is labeled as 1. If P is 0, or refers to a position beyond the end of S, then the extracted substring will be NULL. S, P, and N may be functions of other columns. The string search function strstr(S,R) searches for the first occurrence of the substring R in S. The result is an integer, indicating the character position of the first match (where 1 is the first character position of S). If no match is found, then strstr() returns a NULL value. The following type casting operators are available, where the enclosing parentheses are required and taken from the C language usage. Also, the integer to real casts values to double precision: - "real to integer" (int) x (INT) x "integer to real" (float) i (FLOAT) i - In addition, several constants are built in for use in numerical expressions: - #pi 3.1415... #e 2.7182... #deg #pi/180 #row current row number #null undefined value #snull undefined string - A string constant must be enclosed in quotes as in 'Crab'. The "null" constants are useful for conditionally setting table values to a NULL, or undefined, value (eg., "col1==-99 ? \#NULL : col1"). There is also a function for testing if two values are close to each other, i.e., if they are "near" each other to within a user specified tolerance. The arguments, value\_1 and value\_2 can be integer or real and represent the two values who's proximity is being tested to be within the specified tolerance, also an integer or real: - near(value_1, value_2, tolerance) - When a NULL, or undefined, value is encountered in the FITS table, the expression will evaluate to NULL unless the undefined value is not actually required for evaluation, e.g. "TRUE .or. NULL" evaluates to TRUE. The following two functions allow some NULL detection and handling: - "a null value?" ISNULL(x) "define a value for null" DEFNULL(x,y) - The former returns a boolean value of TRUE if the argument x is NULL. The later "defines" a value to be substituted for NULL values; it returns the value of x if x is not NULL, otherwise it returns the value of y. ***2. Bit Masks Bit masks can be used to select out rows from bit columns (TFORMn = \#X) in FITS files. To represent the mask, binary, octal, and hex formats are allowed: - binary: b0110xx1010000101xxxx0001 octal: o720x1 -> (b111010000xxx001) hex: h0FxD -> (b00001111xxxx1101) - In all the representations, an x or X is allowed in the mask as a wild card. Note that the x represents a different number of wild card bits in each representation. All representations are case insensitive. To construct the boolean expression using the mask as the boolean equal operator described above on a bit table column. For example, if you had a 7 bit column named flags in a FITS table and wanted all rows having the bit pattern 0010011, the selection expression would be: - flags == b0010011 or flags .eq. b10011 - It is also possible to test if a range of bits is less than, less than equal, greater than and greater than equal to a particular boolean value: - flags <= bxxx010xx flags .gt. bxxx100xx flags .le. b1xxxxxxx - Notice the use of the x bit value to limit the range of bits being compared. It is not necessary to specify the leading (most significant) zero (0) bits in the mask, as shown in the second expression above. Bit wise AND, OR and NOT operations are also possible on two or more bit fields using the '\&'(AND), '$|$'(OR), and the '!'(NOT) operators. All of these operators result in a bit field which can then be used with the equal operator. For example: - (!flags) == b1101100 (flags & b1000001) == bx000001 - Bit fields can be appended as well using the '+' operator. Strings can be concatenated this way, too. ***3. Vector Columns Vector columns can also be used in building the expression. No special syntax is required if one wants to operate on all elements of the vector. Simply use the column name as for a scalar column. Vector columns can be freely intermixed with scalar columns or constants in virtually all expressions. The result will be of the same dimension as the vector. Two vectors in an expression, though, need to have the same number of elements and have the same dimensions. The only places a vector column cannot be used (for now, anyway) are the SAO region functions and the NEAR boolean function. Arithmetic and logical operations are all performed on an element by element basis. Comparing two vector columns, eg "COL1 == COL2", thus results in another vector of boolean values indicating which elements of the two vectors are equal. Eight functions are available that operate on a vector and return a scalar result: - "minimum" MIN(V) "maximum" MAX(V) "average" AVERAGE(V) "median" MEDIAN(V) "summation" SUM(V) "standard deviation" STDDEV(V) "# of values" NELEM(V) "# of non-null values" NVALID(V) - where V represents the name of a vector column or a manually constructed vector using curly brackets as described below. The first 6 of these functions ignore any null values in the vector when computing the result. The STDDEV() function computes the sample standard deviation, i.e. it is proportional to 1/SQRT(N-1) instead of 1/SQRT(N), where N is NVALID(V). The SUM function literally sums all the elements in x, returning a scalar value. If x is a boolean vector, SUM returns the number of TRUE elements. The NELEM function returns the number of elements in vector x whereas NVALID return the number of non-null elements in the vector. (NELEM also operates on bit and string columns, returning their column widths.) As an example, to test whether all elements of two vectors satisfy a given logical comparison, one can use the expression - SUM( COL1 > COL2 ) == NELEM( COL1 ) - which will return TRUE if all elements of COL1 are greater than their corresponding elements in COL2. To specify a single element of a vector, give the column name followed by a comma-separated list of coordinates enclosed in square brackets. For example, if a vector column named PHAS exists in the table as a one dimensional, 256 component list of numbers from which you wanted to select the 57th component for use in the expression, then PHAS[57] would do the trick. Higher dimensional arrays of data may appear in a column. But in order to interpret them, the TDIMn keyword must appear in the header. Assuming that a (4,4,4,4) array is packed into each row of a column named ARRAY4D, the (1,2,3,4) component element of each row is accessed by ARRAY4D[1,2,3,4]. Arrays up to dimension 5 are currently supported. Each vector index can itself be an expression, although it must evaluate to an integer value within the bounds of the vector. Vector columns which contain spaces or arithmetic operators must have their names enclosed in "\$" characters as with \$ARRAY-4D\$[1,2,3,4]. A more C-like syntax for specifying vector indices is also available. The element used in the preceding example alternatively could be specified with the syntax ARRAY4D[4][3][2][1]. Note the reverse order of indices (as in C), as well as the fact that the values are still ones-based (as in Fortran -- adopted to avoid ambiguity for 1D vectors). With this syntax, one does not need to specify all of the indices. To extract a 3D slice of this 4D array, use ARRAY4D[4]. Variable-length vector columns are not supported. Vectors can be manually constructed within the expression using a comma-separated list of elements surrounded by curly braces ('\{\}'). For example, '\{1,3,6,1\}' is a 4-element vector containing the values 1, 3, 6, and 1. The vector can contain only boolean, integer, and real values (or expressions). The elements will be promoted to the highest datatype present. Any elements which are themselves vectors, will be expanded out with each of its elements becoming an element in the constructed vector. ***4. Good Time Interval Filtering A common filtering method involves selecting rows which have a time value which lies within what is called a Good Time Interval or GTI. The time intervals are defined in a separate FITS table extension which contains 2 columns giving the start and stop time of each good interval. The filtering operation accepts only those rows of the input table which have an associated time which falls within one of the time intervals defined in the GTI extension. A high level function, gtifilter(a,b,c,d), is available which evaluates each row of the input table and returns TRUE or FALSE depending whether the row is inside or outside the good time interval. The syntax is - gtifilter( [ "gtifile" [, expr [, "STARTCOL", "STOPCOL" ] ] ] ) - where each "[]" demarks optional parameters. Note that the quotes around the gtifile and START/STOP column are required. Either single or double quotes may be used. In cases where this expression is entered on the Unix command line, enclose the entire expression in double quotes, and then use single quotes within the expression to enclose the 'gtifile' and other terms. It is also usually possible to do the reverse, and enclose the whole expression in single quotes and then use double quotes within the expression. The gtifile, if specified, can be blank ("") which will mean to use the first extension with the name "*GTI*" in the current file, a plain extension specifier (eg, "+2", "[2]", or "[STDGTI]") which will be used to select an extension in the current file, or a regular filename with or without an extension specifier which in the latter case will mean to use the first extension with an extension name "*GTI*". Expr can be any arithmetic expression, including simply the time column name. A vector time expression will produce a vector boolean result. STARTCOL and STOPCOL are the names of the START/STOP columns in the GTI extension. If one of them is specified, they both must be. In its simplest form, no parameters need to be provided -- default values will be used. The expression "gtifilter()" is equivalent to - gtifilter( "", TIME, "*START*", "*STOP*" ) - This will search the current file for a GTI extension, filter the TIME column in the current table, using START/STOP times taken from columns in the GTI extension with names containing the strings "START" and "STOP". The wildcards ('*') allow slight variations in naming conventions such as "TSTART" or "STARTTIME". The same default values apply for unspecified parameters when the first one or two parameters are specified. The function automatically searches for TIMEZERO/I/F keywords in the current and GTI extensions, applying a relative time offset, if necessary. ***5. Spatial Region Filtering Another common filtering method selects rows based on whether the spatial position associated with each row is located within a given 2-dimensional region. The syntax for this high-level filter is - regfilter( "regfilename" [ , Xexpr, Yexpr [ , "wcs cols" ] ] ) - where each "[]" demarks optional parameters. The region file name is required and must be enclosed in quotes. The remaining parameters are optional. There are 2 supported formats for the region file: ASCII file or FITS binary table. The region file contains a list of one or more geometric shapes (circle, ellipse, box, etc.) which defines a region on the celestial sphere or an area within a particular 2D image. The region file is typically generated using an image display program such as fv/POW (distribute by the HEASARC), or ds9 (distributed by the Smithsonian Astrophysical Observatory). Users should refer to the documentation provided with these programs for more details on the syntax used in the region files. The FITS region file format is defined in a document available from the FITS Support Office at http://fits.gsfc.nasa.gov/ registry/ region.html In its simplest form, (e.g., regfilter("region.reg") ) the coordinates in the default 'X' and 'Y' columns will be used to determine if each row is inside or outside the area specified in the region file. Alternate position column names, or expressions, may be entered if needed, as in - regfilter("region.reg", XPOS, YPOS) - Region filtering can be applied most unambiguously if the positions in the region file and in the table to be filtered are both give in terms of absolute celestial coordinate units. In this case the locations and sizes of the geometric shapes in the region file are specified in angular units on the sky (e.g., positions given in R.A. and Dec. and sizes in arcseconds or arcminutes). Similarly, each row of the filtered table will have a celestial coordinate associated with it. This association is usually implemented using a set of so-called 'World Coordinate System' (or WCS) FITS keywords that define the coordinate transformation that must be applied to the values in the 'X' and 'Y' columns to calculate the coordinate. Alternatively, one can perform spatial filtering using unitless 'pixel' coordinates for the regions and row positions. In this case the user must be careful to ensure that the positions in the 2 files are self-consistent. A typical problem is that the region file may be generated using a binned image, but the unbinned coordinates are given in the event table. The ROSAT events files, for example, have X and Y pixel coordinates that range from 1 - 15360. These coordinates are typically binned by a factor of 32 to produce a 480x480 pixel image. If one then uses a region file generated from this image (in image pixel units) to filter the ROSAT events file, then the X and Y column values must be converted to corresponding pixel units as in: - regfilter("rosat.reg", X/32.+.5, Y/32.+.5) - Note that this binning conversion is not necessary if the region file is specified using celestial coordinate units instead of pixel units because CFITSIO is then able to directly compare the celestial coordinate of each row in the table with the celestial coordinates in the region file without having to know anything about how the image may have been binned. The last "wcs cols" parameter should rarely be needed. If supplied, this string contains the names of the 2 columns (space or comma separated) which have the associated WCS keywords. If not supplied, the filter will scan the X and Y expressions for column names. If only one is found in each expression, those columns will be used, otherwise an error will be returned. These region shapes are supported (names are case insensitive): - Point ( X1, Y1 ) <- One pixel square region Line ( X1, Y1, X2, Y2 ) <- One pixel wide region Polygon ( X1, Y1, X2, Y2, ... ) <- Rest are interiors with Rectangle ( X1, Y1, X2, Y2, A ) | boundaries considered Box ( Xc, Yc, Wdth, Hght, A ) V within the region Diamond ( Xc, Yc, Wdth, Hght, A ) Circle ( Xc, Yc, R ) Annulus ( Xc, Yc, Rin, Rout ) Ellipse ( Xc, Yc, Rx, Ry, A ) Elliptannulus ( Xc, Yc, Rinx, Riny, Routx, Routy, Ain, Aout ) Sector ( Xc, Yc, Amin, Amax ) - where (Xc,Yc) is the coordinate of the shape's center; (X\#,Y\#) are the coordinates of the shape's edges; Rxxx are the shapes' various Radii or semi-major/minor axes; and Axxx are the angles of rotation (or bounding angles for Sector) in degrees. For rotated shapes, the rotation angle can be left off, indicating no rotation. Common alternate names for the regions can also be used: rotbox = box; rotrectangle = rectangle; (rot)rhombus = (rot)diamond; and pie = sector. When a shape's name is preceded by a minus sign, '-', the defined region is instead the area *outside* its boundary (ie, the region is inverted). All the shapes within a single region file are OR'd together to create the region, and the order is significant. The overall way of looking at region files is that if the first region is an excluded region then a dummy included region of the whole detector is inserted in the front. Then each region specification as it is processed overrides any selections inside of that region specified by previous regions. Another way of thinking about this is that if a previous excluded region is completely inside of a subsequent included region the excluded region is ignored. The positional coordinates may be given either in pixel units, decimal degrees or hh:mm:ss.s, dd:mm:ss.s units. The shape sizes may be given in pixels, degrees, arcminutes, or arcseconds. Look at examples of region file produced by fv/POW or ds9 for further details of the region file format. There are three functions that are primarily for use with SAO region files and the FSAOI task, but they can be used directly. They return a boolean true or false depending on whether a two dimensional point is in the region or not: - "point in a circular region" circle(xcntr,ycntr,radius,Xcolumn,Ycolumn) "point in an elliptical region" ellipse(xcntr,ycntr,xhlf_wdth,yhlf_wdth,rotation,Xcolumn,Ycolumn) "point in a rectangular region" box(xcntr,ycntr,xfll_wdth,yfll_wdth,rotation,Xcolumn,Ycolumn) where (xcntr,ycntr) are the (x,y) position of the center of the region (xhlf_wdth,yhlf_wdth) are the (x,y) half widths of the region (xfll_wdth,yfll_wdth) are the (x,y) full widths of the region (radius) is half the diameter of the circle (rotation) is the angle(degrees) that the region is rotated with respect to (xcntr,ycntr) (Xcoord,Ycoord) are the (x,y) coordinates to test, usually column names NOTE: each parameter can itself be an expression, not merely a column name or constant. - ***5. Example Row Filters - [ binary && mag <= 5.0] - Extract all binary stars brighter than fifth magnitude (note that the initial space is necessary to prevent it from being treated as a binning specification) [#row >= 125 && #row <= 175] - Extract row numbers 125 through 175 [IMAGE[4,5] .gt. 100] - Extract all rows that have the (4,5) component of the IMAGE column greater than 100 [abs(sin(theta * #deg)) < 0.5] - Extract all rows having the absolute value of the sine of theta less than a half where the angles are tabulated in degrees [SUM( SPEC > 3*BACKGRND )>=1] - Extract all rows containing a spectrum, held in vector column SPEC, with at least one value 3 times greater than the background level held in a keyword, BACKGRND [VCOL=={1,4,2}] - Extract all rows whose vector column VCOL contains the 3-elements 1, 4, and 2. [@rowFilter.txt] - Extract rows using the expression contained within the text file rowFilter.txt [gtifilter()] - Search the current file for a GTI extension, filter the TIME column in the current table, using START/STOP times taken from columns in the GTI extension [regfilter("pow.reg")] - Extract rows which have a coordinate (as given in the X and Y columns) within the spatial region specified in the pow.reg region file. [regfilter("pow.reg", Xs, Ys)] - Same as above, except that the Xs and Ys columns will be used to determine the coordinate of each row in the table. - **K. Binning or Histogramming Specification The optional binning specifier is enclosed in square brackets and can be distinguished from a general row filter specification by the fact that it begins with the keyword 'bin' not immediately followed by an equals sign. When binning is specified, a temporary N-dimensional FITS primary array is created by computing the histogram of the values in the specified columns of a FITS table extension. After the histogram is computed the input FITS file containing the table is then closed and the temporary FITS primary array is opened and passed to the application program. Thus, the application program never sees the original FITS table and only sees the image in the new temporary file (which has no additional extensions). Obviously, the application program must be expecting to open a FITS image and not a FITS table in this case. The data type of the FITS histogram image may be specified by appending 'b' (for 8-bit byte), 'i' (for 16-bit integers), 'j' (for 32-bit integer), 'r' (for 32-bit floating points), or 'd' (for 64-bit double precision floating point) to the 'bin' keyword (e.g. '[binr X]' creates a real floating point image). If the datatype is not explicitly specified then a 32-bit integer image will be created by default, unless the weighting option is also specified in which case the image will have a 32-bit floating point data type by default. The histogram image may have from 1 to 4 dimensions (axes), depending on the number of columns that are specified. The general form of the binning specification is: - [bin{bijrd} Xcol=min:max:binsize, Ycol= ..., Zcol=..., Tcol=...; weight] - in which up to 4 columns, each corresponding to an axis of the image, are listed. The column names are case insensitive, and the column number may be given instead of the name, preceded by a pound sign (e.g., [bin \#4=1:512]). If the column name is not specified, then CFITSIO will first try to use the 'preferred column' as specified by the CPREF keyword if it exists (e.g., 'CPREF = 'DETX,DETY'), otherwise column names 'X', 'Y', 'Z', and 'T' will be assumed for each of the 4 axes, respectively. In cases where the column name could be confused with an arithmetic expression, enclose the column name in parentheses to force the name to be interpreted literally. Each column name may be followed by an equals sign and then the lower and upper range of the histogram, and the size of the histogram bins, separated by colons. Spaces are allowed before and after the equals sign but not within the 'min:max:binsize' string. The min, max and binsize values may be integer or floating point numbers, or they may be the names of keywords in the header of the table. If the latter, then the value of that keyword is substituted into the expression. Default values for the min, max and binsize quantities will be used if not explicitly given in the binning expression as shown in these examples: - [bin x = :512:2] - use default minimum value [bin x = 1::2] - use default maximum value [bin x = 1:512] - use default bin size [bin x = 1:] - use default maximum value and bin size [bin x = :512] - use default minimum value and bin size [bin x = 2] - use default minimum and maximum values [bin x] - use default minimum, maximum and bin size [bin 4] - default 2-D image, bin size = 4 in both axes [bin] - default 2-D image - CFITSIO will use the value of the TLMINn, TLMAXn, and TDBINn keywords, if they exist, for the default min, max, and binsize, respectively. If they do not exist then CFITSIO will use the actual minimum and maximum values in the column for the histogram min and max values. The default binsize will be set to 1, or (max - min) / 10., whichever is smaller, so that the histogram will have at least 10 bins along each axis. A shortcut notation is allowed if all the columns/axes have the same binning specification. In this case all the column names may be listed within parentheses, followed by the (single) binning specification, as in: - [bin (X,Y)=1:512:2] [bin (X,Y) = 5] - The optional weighting factor is the last item in the binning specifier and, if present, is separated from the list of columns by a semi-colon. As the histogram is accumulated, this weight is used to incremented the value of the appropriated bin in the histogram. If the weighting factor is not specified, then the default weight = 1 is assumed. The weighting factor may be a constant integer or floating point number, or the name of a keyword containing the weighting value. Or the weighting factor may be the name of a table column in which case the value in that column, on a row by row basis, will be used. In some cases, the column or keyword may give the reciprocal of the actual weight value that is needed. In this case, precede the weight keyword or column name by a slash '/' to tell CFITSIO to use the reciprocal of the value when constructing the histogram. For complex or commonly used histograms, one can also place its description into a text file and import it into the binning specification using the syntax '[bin @filename.txt]'. The file's contents can extend over multiple lines, although it must still conform to the no-spaces rule for the min:max:binsize syntax and each axis specification must still be comma-separated. Any lines in the external text file that begin with 2 slash characters ('//') will be ignored and may be used to add comments into the file. Examples: - [bini detx, dety] - 2-D, 16-bit integer histogram of DETX and DETY columns, using default values for the histogram range and binsize [bin (detx, dety)=16; /exposure] - 2-D, 32-bit real histogram of DETX and DETY columns with a bin size = 16 in both axes. The histogram values are divided by the EXPOSURE keyword value. [bin time=TSTART:TSTOP:0.1] - 1-D lightcurve, range determined by the TSTART and TSTOP keywords, with 0.1 unit size bins. [bin pha, time=8000.:8100.:0.1] - 2-D image using default binning of the PHA column for the X axis, and 1000 bins in the range 8000. to 8100. for the Y axis. [bin @binFilter.txt] - Use the contents of the text file binFilter.txt for the binning specifications. - *V. Template Files When a new FITS file is created with a call to fits\_create\_file, the name of a template file may be supplied in parentheses immediately following the name of the new file to be created. This template is used to define the structure of one or more HDUs in the new file. The template file may be another FITS file, in which case the newly created file will have exactly the same keywords in each HDU as in the template FITS file, but all the data units will be filled with zeros. The template file may also be an ASCII text file, where each line (in general) describes one FITS keyword record. The format of the ASCII template file is described in the following sections. **A Detailed Template Line Format The format of each ASCII template line closely follows the format of a FITS keyword record: - KEYWORD = KEYVALUE / COMMENT - except that free format may be used (e.g., the equals sign may appear at any position in the line) and TAB characters are allowed and are treated the same as space characters. The KEYVALUE and COMMENT fields are optional. The equals sign character is also optional, but it is recommended that it be included for clarity. Any template line that begins with the pound '\#' character is ignored by the template parser and may be use to insert comments into the template file itself. The KEYWORD name field is limited to 8 characters in length and only the letters A-Z, digits 0-9, and the hyphen and underscore characters may be used, without any embedded spaces. Lowercase letters in the template keyword name will be converted to uppercase. Leading spaces in the template line preceding the keyword name are generally ignored, except if the first 8 characters of a template line are all blank, then the entire line is treated as a FITS comment keyword (with a blank keyword name) and is copied verbatim into the FITS header. The KEYVALUE field may have any allowed FITS data type: character string, logical, integer, real, complex integer, or complex real. Integer values must be within the allowed range of a 'signed long' variable; some C compilers only suppport 4-byte long integers with a range from -2147483648 to +2147483647, whereas other C compilers support 8-byte integers with a range of plus or minus 2**63. The character string values need not be enclosed in single quote characters unless they are necessary to distinguish the string from a different data type (e.g. 2.0 is a real but '2.0' is a string). The keyword has an undefined (null) value if the template record only contains blanks following the "=" or between the "=" and the "/" comment field delimiter. String keyword values longer than 68 characters (the maximum length that will fit in a single FITS keyword record) are permitted using the CFITSIO long string convention. They can either be specified as a single long line in the template, or by using multiple lines where the continuing lines contain the 'CONTINUE' keyword, as in this example: - LONGKEY = 'This is a long string value that is contin&' CONTINUE 'ued over 2 records' / comment field goes here - The format of template lines with CONTINUE keyword is very strict: 3 spaces must follow CONTINUE and the rest of the line is copied verbatim to the FITS file. The start of the optional COMMENT field must be preceded by "/", which is used to separate it from the keyword value field. Exceptions are if the KEYWORD name field contains COMMENT, HISTORY, CONTINUE, or if the first 8 characters of the template line are blanks. More than one Header-Data Unit (HDU) may be defined in the template file. The start of an HDU definition is denoted with a SIMPLE or XTENSION template line: 1) SIMPLE begins a Primary HDU definition. SIMPLE may only appear as the first keyword in the template file. If the template file begins with XTENSION instead of SIMPLE, then a default empty Primary HDU is created, and the template is then assumed to define the keywords starting with the first extension following the Primary HDU. 2) XTENSION marks the beginning of a new extension HDU definition. The previous HDU will be closed at this point and processing of the next extension begins. **B Auto-indexing of Keywords If a template keyword name ends with a "\#" character, it is said to be 'auto-indexed'. Each "\#" character will be replaced by the current integer index value, which gets reset = 1 at the start of each new HDU in the file (or 7 in the special case of a GROUP definition). The FIRST indexed keyword in each template HDU definition is used as the 'incrementor'; each subsequent occurrence of this SAME keyword will cause the index value to be incremented. This behavior can be rather subtle, as illustrated in the following examples in which the TTYPE keyword is the incrementor in both cases: - TTYPE# = TIME TFORM# = 1D TTYPE# = RATE TFORM# = 1E - will create TTYPE1, TFORM1, TTYPE2, and TFORM2 keywords. But if the template looks like, - TTYPE# = TIME TTYPE# = RATE TFORM# = 1D TFORM# = 1E - this results in a FITS files with TTYPE1, TTYPE2, TFORM2, and TFORM2, which is probably not what was intended! **C Template Parser Directives In addition to the template lines which define individual keywords, the template parser recognizes 3 special directives which are each preceded by the backslash character: \verb+ \include, \group+, and \verb+ \end+. The 'include' directive must be followed by a filename. It forces the parser to temporarily stop reading the current template file and begin reading the include file. Once the parser reaches the end of the include file it continues parsing the current template file. Include files can be nested, and HDU definitions can span multiple template files. The start of a GROUP definition is denoted with the 'group' directive, and the end of a GROUP definition is denoted with the 'end' directive. Each GROUP contains 0 or more member blocks (HDUs or GROUPs). Member blocks of type GROUP can contain their own member blocks. The GROUP definition itself occupies one FITS file HDU of special type (GROUP HDU), so if a template specifies 1 group with 1 member HDU like: - \group grpdescr = 'demo' xtension bintable # this bintable has 0 cols, 0 rows \end - then the parser creates a FITS file with 3 HDUs : - 1) dummy PHDU 2) GROUP HDU (has 1 member, which is bintable in HDU number 3) 3) bintable (member of GROUP in HDU number 2) - Technically speaking, the GROUP HDU is a BINTABLE with 6 columns. Applications can define additional columns in a GROUP HDU using TFORMn and TTYPEn (where n is 7, 8, ....) keywords or their auto-indexing equivalents. For a more complicated example of a template file using the group directives, look at the sample.tpl file that is included in the CFITSIO distribution. **D Formal Template Syntax The template syntax can formally be defined as follows: - TEMPLATE = BLOCK [ BLOCK ... ] BLOCK = { HDU | GROUP } GROUP = \GROUP [ BLOCK ... ] \END HDU = XTENSION [ LINE ... ] { XTENSION | \GROUP | \END | EOF } LINE = [ KEYWORD [ = ] ] [ VALUE ] [ / COMMENT ] X ... - X can be present 1 or more times { X | Y } - X or Y [ X ] - X is optional - At the topmost level, the template defines 1 or more template blocks. Blocks can be either HDU (Header Data Unit) or a GROUP. For each block the parser creates 1 (or more for GROUPs) FITS file HDUs. **E Errors In general the fits\_execute\_template() function tries to be as atomic as possible, so either everything is done or nothing is done. If an error occurs during parsing of the template, fits\_execute\_template() will (try to) delete the top level BLOCK (with all its children if any) in which the error occurred, then it will stop reading the template file and it will return with an error. **F Examples 1. This template file will create a 200 x 300 pixel image, with 4-byte integer pixel values, in the primary HDU: - SIMPLE = T BITPIX = 32 NAXIS = 2 / number of dimensions NAXIS1 = 100 / length of first axis NAXIS2 = 200 / length of second axis OBJECT = NGC 253 / name of observed object - The allowed values of BITPIX are 8, 16, 32, -32, or -64, representing, respectively, 8-bit integer, 16-bit integer, 32-bit integer, 32-bit floating point, or 64 bit floating point pixels. 2. To create a FITS table, the template first needs to include XTENSION = TABLE or BINTABLE to define whether it is an ASCII or binary table, and NAXIS2 to define the number of rows in the table. Two template lines are then needed to define the name (TTYPEn) and FITS data format (TFORMn) of the columns, as in this example: - xtension = bintable naxis2 = 40 ttype# = Name tform# = 10a ttype# = Npoints tform# = j ttype# = Rate tunit# = counts/s tform# = e - The above example defines a null primary array followed by a 40-row binary table extension with 3 columns called 'Name', 'Npoints', and 'Rate', with data formats of '10A' (ASCII character string), '1J' (integer) and '1E' (floating point), respectively. Note that the other required FITS keywords (BITPIX, NAXIS, NAXIS1, PCOUNT, GCOUNT, TFIELDS, and END) do not need to be explicitly defined in the template because their values can be inferred from the other keywords in the template. This example also illustrates that the templates are generally case-insensitive (the keyword names and TFORMn values are converted to upper-case in the FITS file) and that string keyword values generally do not need to be enclosed in quotes. *IX Summary of all FITSIO User-Interface Subroutines Error Status Routines page~\pageref{FTVERS} - FTVERS( > version) FTGERR(status, > errtext) FTGMSG( > errmsg) FTRPRT (stream, > status) FTPMSG(errmsg) FTPMRK FTCMSG FTCMRK - FITS File Open and Close Subroutines: page~\pageref{FTOPEN} - FTOPEN(unit,filename,rwmode, > blocksize,status) FTDKOPN(unit,filename,rwmode, > blocksize,status) FTNOPN(unit,filename,rwmode, > status) FTDOPN(unit,filename,rwmode, > status) FTTOPN(unit,filename,rwmode, > status) FTIOPN(unit,filename,rwmode, > status) FTREOPEN(unit, > newunit, status) FTINIT(unit,filename,blocksize, > status) FTDKINIT(unit,filename,blocksize, > status) FTTPLT(unit, filename, tplfilename, > status) FTFLUS(unit, > status) FTCLOS(unit, > status) FTDELT(unit, > status) FTGIOU( > iounit, status) FTFIOU(iounit, > status) CFITS2Unit(fitsfile *ptr) (C routine) CUnit2FITS(int unit) (C routine) FTEXTN(filename, > nhdu, status) FTFLNM(unit, > filename, status) FTFLMD(unit, > iomode, status) FTURLT(unit, > urltype, status) FTIURL(filename, > filetype, infile, outfile, extspec, filter, binspec, colspec, status) FTRTNM(filename, > rootname, status) FTEXIST(filename, > exist, status) - HDU-Level Operations: page~\pageref{FTMAHD} - FTMAHD(unit,nhdu, > hdutype,status) FTMRHD(unit,nmove, > hdutype,status) FTGHDN(unit, > nhdu) FTMNHD(unit, hdutype, extname, extver, > status) FTGHDT(unit, > hdutype, status) FTTHDU(unit, > hdunum, status) FTCRHD(unit, > status) FTIIMG(unit,bitpix,naxis,naxes, > status) FTITAB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > status) FTIBIN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat > status) FTRSIM(unit,bitpix,naxis,naxes,status) FTDHDU(unit, > hdutype,status) FTCPFL(iunit,ounit,previous, current, following, > status) FTCOPY(iunit,ounit,morekeys, > status) FTCPHD(inunit, outunit, > status) FTCPDT(iunit,ounit, > status) - Subroutines to specify or modify the structure of the CHDU: page~\pageref{FTRDEF} - FTRDEF(unit, > status) (DEPRECATED) FTPDEF(unit,bitpix,naxis,naxes,pcount,gcount, > status) (DEPRECATED) FTADEF(unit,rowlen,tfields,tbcol,tform,nrows > status) (DEPRECATED) FTBDEF(unit,tfields,tform,varidat,nrows > status) (DEPRECATED) FTDDEF(unit,bytlen, > status) (DEPRECATED) FTPTHP(unit,theap, > status) - Header Space and Position Subroutines: page~\pageref{FTHDEF} - FTHDEF(unit,morekeys, > status) FTGHSP(iunit, > keysexist,keysadd,status) FTGHPS(iunit, > keysexist,key_no,status) - Read or Write Standard Header Subroutines: page~\pageref{FTPHPR} - FTPHPS(unit,bitpix,naxis,naxes, > status) FTPHPR(unit,simple,bitpix,naxis,naxes,pcount,gcount,extend, > status) FTGHPR(unit,maxdim, > simple,bitpix,naxis,naxes,pcount,gcount,extend, status) FTPHTB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > status) FTGHTB(unit,maxdim, > rowlen,nrows,tfields,ttype,tbcol,tform,tunit, extname,status) FTPHBN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat > status) FTGHBN(unit,maxdim, > nrows,tfields,ttype,tform,tunit,extname,varidat, status) - Write Keyword Subroutines: page~\pageref{FTPREC} - FTPREC(unit,card, > status) FTPCOM(unit,comment, > status) FTPHIS(unit,history, > status) FTPDAT(unit, > status) FTPKY[JKLS](unit,keyword,keyval,comment, > status) FTPKY[EDFG](unit,keyword,keyval,decimals,comment, > status) FTPKLS(unit,keyword,keyval,comment, > status) FTPLSW(unit, > status) FTPKYU(unit,keyword,comment, > status) FTPKN[JKLS](unit,keyroot,startno,no_keys,keyvals,comments, > status) FTPKN[EDFG](unit,keyroot,startno,no_keys,keyvals,decimals,comments, > status) FTCPKYinunit, outunit, innum, outnum, keyroot, > status) FTPKYT(unit,keyword,intval,dblval,comment, > status) FTPKTP(unit, filename, > status) FTPUNT(unit,keyword,units, > status) - Insert Keyword Subroutines: page~\pageref{FTIREC} - FTIREC(unit,key_no,card, > status) FTIKY[JKLS](unit,keyword,keyval,comment, > status) FTIKLS(unit,keyword,keyval,comment, > status) FTIKY[EDFG](unit,keyword,keyval,decimals,comment, > status) FTIKYU(unit,keyword,comment, > status) - Read Keyword Subroutines: page~\pageref{FTGREC} - FTGREC(unit,key_no, > card,status) FTGKYN(unit,key_no, > keyword,value,comment,status) FTGCRD(unit,keyword, > card,status) FTGNXK(unit,inclist,ninc,exclist,nexc, > card,status) FTGKEY(unit,keyword, > value,comment,status) FTGKY[EDJKLS](unit,keyword, > keyval,comment,status) FTGKSL(unit,keyword, > length,status) FTGSKY(unit,keyword,firstchar,maxchar,> keyval,length,comment,status) FTGKN[EDJKLS](unit,keyroot,startno,max_keys, > keyvals,nfound,status) FTGKYT(unit,keyword, > intval,dblval,comment,status) FTGUNT(unit,keyword, > units,status) - Modify Keyword Subroutines: page~\pageref{FTMREC} - FTMREC(unit,key_no,card, > status) FTMCRD(unit,keyword,card, > status) FTMNAM(unit,oldkey,keyword, > status) FTMCOM(unit,keyword,comment, > status) FTMKY[JKLS](unit,keyword,keyval,comment, > status) FTMKLS(unit,keyword,keyval,comment, > status) FTMKY[EDFG](unit,keyword,keyval,decimals,comment, > status) FTMKYU(unit,keyword,comment, > status) - Update Keyword Subroutines: page~\pageref{FTUCRD} - FTUCRD(unit,keyword,card, > status) FTUKY[JKLS](unit,keyword,keyval,comment, > status) FTUKLS(unit,keyword,keyval,comment, > status) FTUKY[EDFG](unit,keyword,keyval,decimals,comment, > status) FTUKYU(unit,keyword,comment, > status) - Delete Keyword Subroutines: page~\pageref{FTDREC} - FTDREC(unit,key_no, > status) FTDKEY(unit,keyword, > status) - Define Data Scaling Parameters and Undefined Pixel Flags: page~\pageref{FTPSCL} - FTPSCL(unit,bscale,bzero, > status) FTTSCL(unit,colnum,tscal,tzero, > status) FTPNUL(unit,blank, > status) FTSNUL(unit,colnum,snull > status) FTTNUL(unit,colnum,tnull > status) - FITS Primary Array or IMAGE Extension I/O Subroutines: page~\pageref{FTPPR} - FTGIDT(unit, > bitpix,status) FTGIET(unit, > bitpix,status) FTGIDM(unit, > naxis,status) FTGISZ(unit, maxdim, > naxes,status) FTGIPR(unit, maxdim, > bitpix,naxis,naxes,status) FTPPR[BIJKED](unit,group,fpixel,nelements,values, > status) FTPPN[BIJKED](unit,group,fpixel,nelements,values,nullval > status) FTPPRU(unit,group,fpixel,nelements, > status) FTGPV[BIJKED](unit,group,fpixel,nelements,nullval, > values,anyf,status) FTGPF[BIJKED](unit,group,fpixel,nelements, > values,flagvals,anyf,status) FTPGP[BIJKED](unit,group,fparm,nparm,values, > status) FTGGP[BIJKED](unit,group,fparm,nparm, > values,status) FTP2D[BIJKED](unit,group,dim1,naxis1,naxis2,image, > status) FTP3D[BIJKED](unit,group,dim1,dim2,naxis1,naxis2,naxis3,cube, > status) FTG2D[BIJKED](unit,group,nullval,dim1,naxis1,naxis2, > image,anyf,status) FTG3D[BIJKED](unit,group,nullval,dim1,dim2,naxis1,naxis2,naxis3, > cube,anyf,status) FTPSS[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,array, > status) FTGSV[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,incs,nullval, > array,anyf,status) FTGSF[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,incs, > array,flagvals,anyf,status) - Table Column Information Subroutines: page~\pageref{FTGCNO} - FTGNRW(unit, > nrows, status) FTGNCL(unit, > ncols, status) FTGCNO(unit,casesen,coltemplate, > colnum,status) FTGCNN(unit,casesen,coltemplate, > colnam,colnum,status) FTGTCL(unit,colnum, > datacode,repeat,width,status) FTEQTY(unit,colnum, > datacode,repeat,width,status) FTGCDW(unit,colnum, > dispwidth,status) FTGACL(unit,colnum, > ttype,tbcol,tunit,tform,tscal,tzero,snull,tdisp,status) FTGBCL(unit,colnum, > ttype,tunit,datatype,repeat,tscal,tzero,tnull,tdisp,status) FTPTDM(unit,colnum,naxis,naxes, > status) FTGTDM(unit,colnum,maxdim, > naxis,naxes,status) FTDTDM(unit,tdimstr,colnum,maxdim, > naxis,naxes, status) FTGRSZ(unit, > nrows,status) - Low-Level Table Access Subroutines: page~\pageref{FTGTBS} - FTGTBS(unit,frow,startchar,nchars, > string,status) FTPTBS(unit,frow,startchar,nchars,string, > status) FTGTBB(unit,frow,startchar,nchars, > array,status) FTPTBB(unit,frow,startchar,nchars,array, > status) - Edit Rows or Columns page~\pageref{FTIROW} - FTIROW(unit,frow,nrows, > status) FTDROW(unit,frow,nrows, > status) FTDRRG(unit,rowrange, > status) FTDRWS(unit,rowlist,nrows, > status) FTICOL(unit,colnum,ttype,tform, > status) FTICLS(unit,colnum,ncols,ttype,tform, > status) FTMVEC(unit,colnum,newveclen, > status) FTDCOL(unit,colnum, > status) FTCPCL(inunit,outunit,incolnum,outcolnum,createcol, > status); - Read and Write Column Data Routines page~\pageref{FTPCLS} - FTPCL[SLBIJKEDCM](unit,colnum,frow,felem,nelements,values, > status) FTPCN[BIJKED](unit,colnum,frow,felem,nelements,values,nullval > status) FTPCLX(unit,colnum,frow,fbit,nbit,lray, > status) FTPCLU(unit,colnum,frow,felem,nelements, > status) FTGCL(unit,colnum,frow,felem,nelements, > values,status) FTGCV[SBIJKEDCM](unit,colnum,frow,felem,nelements,nullval, > values,anyf,status) FTGCF[SLBIJKEDCM](unit,colnum,frow,felem,nelements, > values,flagvals,anyf,status) FTGSV[BIJKED](unit,colnum,naxis,naxes,fpixels,lpixels,incs,nullval, > array,anyf,status) FTGSF[BIJKED](unit,colnum,naxis,naxes,fpixels,lpixels,incs, > array,flagvals,anyf,status) FTGCX(unit,colnum,frow,fbit,nbit, > lray,status) FTGCX[IJD](unit,colnum,frow,nrows,fbit,nbit, > array,status) FTGDES(unit,colnum,rownum, > nelements,offset,status) FTPDES(unit,colnum,rownum,nelements,offset, > status) - Row Selection and Calculator Routines: page~\pageref{FTFROW} - FTFROW(unit,expr,firstrow, nrows, > n_good_rows, row_status, status) FTFFRW(unit, expr, > rownum, status) FTSROW(inunit, outunit, expr, > status ) FTCROW(unit,datatype,expr,firstrow,nelements,nulval, > array,anynul,status) FTCALC(inunit, expr, outunit, parName, parInfo, > status) FTCALC_RNG(inunit, expr, outunit, parName, parInfo, nranges, firstrow, lastrow, > status) FTTEXP(unit, expr, > datatype, nelem, naxis, naxes, status) - Celestial Coordinate System Subroutines: page~\pageref{FTGICS} - FTGICS(unit, > xrval,yrval,xrpix,yrpix,xinc,yinc,rot,coordtype,status) FTGTCS(unit,xcol,ycol, > xrval,yrval,xrpix,yrpix,xinc,yinc,rot,coordtype,status) FTWLDP(xpix,ypix,xrval,yrval,xrpix,yrpix,xinc,yinc,rot, coordtype, > xpos,ypos,status) FTXYPX(xpos,ypos,xrval,yrval,xrpix,yrpix,xinc,yinc,rot, coordtype, > xpix,ypix,status) - File Checksum Subroutines: page~\pageref{FTPCKS} - FTPCKS(unit, > status) FTUCKS(unit, > status) FTVCKS(unit, > dataok,hduok,status) FTGCKS(unit, > datasum,hdusum,status) FTESUM(sum,complement, > checksum) FTDSUM(checksum,complement, > sum) - Time and Date Utility Subroutines: page~\pageref{FTGSDT} - FTGSDT( > day, month, year, status ) FTGSTM(> datestr, timeref, status) FTDT2S( year, month, day, > datestr, status) FTTM2S( year, month, day, hour, minute, second, decimals, > datestr, status) FTS2DT(datestr, > year, month, day, status) FTS2TM(datestr, > year, month, day, hour, minute, second, status) - General Utility Subroutines: page~\pageref{FTGHAD} - FTGHAD(unit, > curaddr,nextaddr) FTUPCH(string) FTCMPS(str_template,string,casesen, > match,exact) FTTKEY(keyword, > status) FTTREC(card, > status) FTNCHK(unit, > status) FTGKNM(unit, > keyword, keylength, status) FTMKKY(keyword, value,comment, > card, status) FTPSVC(card, > value,comment,status) FTKEYN(keyroot,seq_no, > keyword,status) FTNKEY(seq_no,keyroot, > keyword,status) FTDTYP(value, > dtype,status) class = FTGKCL(card) FTASFM(tform, > datacode,width,decimals,status) FTBNFM(tform, > datacode,repeat,width,status) FTGABC(tfields,tform,space, > rowlen,tbcol,status) FTGTHD(template, > card,hdtype,status) FTRWRG(rowlist, maxrows, maxranges, > numranges, rangemin, rangemax, status) - *X. Parameter Definitions - anyf - (logical) set to TRUE if any of the returned data values are undefined array - (any datatype except character) array of bytes to be read or written. bitpix - (integer) bits per pixel: 8, 16, 32, -32, or -64 blank - (integer) value used for undefined pixels in integer primary array blank - (integer*8) value used for undefined pixels in integer primary array blocksize - (integer) 2880-byte logical record blocking factor (if 0 < blocksize < 11) or the actual block size in bytes (if 10 < blocksize < 28800). As of version 3.3 of FITSIO, blocksizes greater than 2880 are no longer supported. bscale - (double precision) scaling factor for the primary array bytlen - (integer) length of the data unit, in bytes bzero - (double precision) zero point for primary array scaling card - (character*80) header record to be read or written casesen - (logical) will string matching be case sensitive? checksum - (character*16) encoded checksum string colname - (character) ASCII name of the column colnum - (integer) number of the column (first column = 1) coltemplate - (character) template string to be matched to column names comment - (character) the keyword comment field comments - (character array) keyword comment fields compid - (integer) the type of computer that the program is running on complement - (logical) should the checksum be complemented? coordtype - (character) type of coordinate projection (-SIN, -TAN, -ARC, -NCP, -GLS, -MER, or -AIT) cube - 3D data cube of the appropriate datatype curaddr - (integer) starting address (in bytes) of the CHDU current - (integer) if not equal to 0, copy the current HDU datacode - (integer) symbolic code of the binary table column datatype dataok - (integer) was the data unit verification successful (=1) or not (= -1). Equals zero if the DATASUM keyword is not present. datasum - (double precision) 32-bit 1's complement checksum for the data unit datatype - (character) datatype (format) of the binary table column datestr - (string) FITS date/time string: 'YYYY-MM-DDThh:mm:ss.ddd', 'YYYY-MM-dd', or 'dd/mm/yy' day - (integer) current day of the month dblval - (double precision) fractional part of the keyword value decimals - (integer) number of decimal places to be displayed dim1 - (integer) actual size of the first dimension of the image or cube array dim2 - (integer) actual size of the second dimension of the cube array dispwidth - (integer) - the display width (length of string) for a column dtype - (character) datatype of the keyword ('C', 'L', 'I', or 'F') C = character string L = logical I = integer F = floating point number errmsg - (character*80) oldest error message on the internal stack errtext - (character*30) descriptive error message corresponding to error number casesen - (logical) true if column name matching is case sensitive exact - (logical) do the strings match exactly, or were wildcards used? exclist (character array) list of names to be excluded from search exists - flag indicating whether the file or compressed file exists on disk extend - (logical) true if there may be extensions following the primary data extname - (character) value of the EXTNAME keyword (if not blank) fbit - (integer) first bit in the field to be read or written felem - (integer) first pixel of the element vector (ignored for ASCII tables) filename - (character) name of the FITS file flagvals - (logical array) True if corresponding data element is undefined following - (integer) if not equal to 0, copy all following HDUs in the input file fparm - (integer) sequence number of the first group parameter to read or write fpixel - (integer) the first pixel position fpixels - (integer array) the first included pixel in each dimension frow - (integer) beginning row number (first row of table = 1) frowll - (integer*8) beginning row number (first row of table = 1) gcount - (integer) value of the GCOUNT keyword (usually = 1) group - (integer) sequence number of the data group (=0 for non-grouped data) hdtype - (integer) header record type: -1=delete; 0=append or replace; 1=append; 2=this is the END keyword hduok - (integer) was the HDU verification successful (=1) or not (= -1). Equals zero if the CHECKSUM keyword is not present. hdusum - (double precision) 32 bit 1's complement checksum for the entire CHDU hdutype - (integer) type of HDU: 0 = primary array or IMAGE, 1 = ASCII table, 2 = binary table, -1 = any HDU type or unknown type history - (character) the HISTORY keyword comment string hour - (integer) hour from 0 - 23 image - 2D image of the appropriate datatype inclist (character array) list of names to be included in search incs - (integer array) sampling interval for pixels in each FITS dimension intval - (integer) integer part of the keyword value iounit - (integer) value of an unused I/O unit number iunit - (integer) logical unit number associated with the input FITS file, 1-300 key_no - (integer) sequence number (starting with 1) of the keyword record keylength - (integer) length of the keyword name keyroot - (character) root string for the keyword name keysadd -(integer) number of new keyword records which can fit in the CHU keysexist - (integer) number of existing keyword records in the CHU keyval - value of the keyword in the appropriate datatype keyvals - (array) value of the keywords in the appropriate datatype keyword - (character*8) name of a keyword lray - (logical array) array of logical values corresponding to the bit array lpixels - (integer array) the last included pixel in each dimension match - (logical) do the 2 strings match? maxdim - (integer) dimensioned size of the NAXES, TTYPE, TFORM or TUNIT arrays max_keys - (integer) maximum number of keywords to search for minute - (integer) minute of an hour (0 - 59) month - (integer) current month of the year (1 - 12) morekeys - (integer) will leave space in the header for this many more keywords naxes - (integer array) size of each dimension in the FITS array naxesll - (integer*8 array) size of each dimension in the FITS array naxis - (integer) number of dimensions in the FITS array naxis1 - (integer) length of the X/first axis of the FITS array naxis2 - (integer) length of the Y/second axis of the FITS array naxis3 - (integer) length of the Z/third axis of the FITS array nbit - (integer) number of bits in the field to read or write nchars - (integer) number of characters to read and return ncols - (integer) number of columns nelements - (integer) number of data elements to read or write nelementsll - (integer*8) number of data elements to read or write nexc (integer) number of names in the exclusion list (may = 0) nhdu - (integer) absolute number of the HDU (1st HDU = 1) ninc (integer) number of names in the inclusion list nmove - (integer) number of HDUs to move (+ or -), relative to current position nfound - (integer) number of keywords found (highest keyword number) no_keys - (integer) number of keywords to write in the sequence nparm - (integer) number of group parameters to read or write nrows - (integer) number of rows in the table nrowsll - (integer*8) number of rows in the table nullval - value to represent undefined pixels, of the appropriate datatype nextaddr - (integer) starting address (in bytes) of the HDU following the CHDU offset - (integer) byte offset in the heap to the first element of the array offsetll - (integer*8) byte offset in the heap to the first element of the array oldkey - (character) old name of keyword to be modified ounit - (integer) logical unit number associated with the output FITS file 1-300 pcount - (integer) value of the PCOUNT keyword (usually = 0) previous - (integer) if not equal to 0, copy all previous HDUs in the input file repeat - (integer) length of element vector (e.g. 12J); ignored for ASCII table rot - (double precision) celestial coordinate rotation angle (degrees) rowlen - (integer) length of a table row, in characters or bytes rowlenll - (integer*8) length of a table row, in characters or bytes rowlist - (integer array) list of row numbers to be deleted in increasing order rownum - (integer) number of the row (first row = 1) rowrange- (string) list of rows or row ranges to be deleted rwmode - (integer) file access mode: 0 = readonly, 1 = readwrite second (double)- second within minute (0 - 60.9999999999) (leap second!) seq_no - (integer) the sequence number to append to the keyword root name simple - (logical) does the FITS file conform to all the FITS standards snull - (character) value used to represent undefined values in ASCII table space - (integer) number of blank spaces to leave between ASCII table columns startchar - (integer) first character in the row to be read startno - (integer) value of the first keyword sequence number (usually 1) status - (integer) returned error status code (0 = OK) str_template (character) template string to be matched to reference string stream - (character) output stream for the report: either 'STDOUT' or 'STDERR' string - (character) character string sum - (double precision) 32 bit unsigned checksum value tbcol - (integer array) column number of the first character in the field(s) tdisp - (character) Fortran type display format for the table column template-(character) template string for a FITS header record tfields - (integer) number of fields (columns) in the table tform - (character array) format of the column(s); allowed values are: For ASCII tables: Iw, Aw, Fww.dd, Eww.dd, or Dww.dd For binary tables: rL, rX, rB, rI, rJ, rA, rAw, rE, rD, rC, rM where 'w'=width of the field, 'd'=no. of decimals, 'r'=repeat count Note that the 'rAw' form is non-standard extension to the TFORM keyword syntax that is not specifically defined in the Binary Tables definition document. theap - (integer) zero indexed byte offset of starting address of the heap relative to the beginning of the binary table data tnull - (integer) value used to represent undefined values in binary table tnullll - (integer*8) value used to represent undefined values in binary table ttype - (character array) label for table column(s) tscal - (double precision) scaling factor for table column tunit - (character array) physical unit for table column(s) tzero - (double precision) scaling zero point for table column unit - (integer) logical unit number associated with the FITS file (1-300) units - (character) the keyword units string (e.g., 'km/s') value - (character) the keyword value string values - array of data values of the appropriate datatype varidat - (integer) size in bytes of the 'variable length data area' following the binary table data (usually = 0) version - (real) current revision number of the library width - (integer) width of the character string field xcol - (integer) number of the column containing the X coordinate values xinc - (double precision) X axis coordinate increment at reference pixel (deg) xpix - (double precision) X axis pixel location xpos - (double precision) X axis celestial coordinate (usually RA) (deg) xrpix - (double precision) X axis reference pixel array location xrval - (double precision) X axis coordinate value at the reference pixel (deg) ycol - (integer) number of the column containing the X coordinate values year - (integer) last 2 digits of the year (00 - 99) yinc - (double precision) Y axis coordinate increment at reference pixel (deg) ypix - (double precision) y axis pixel location ypos - (double precision) y axis celestial coordinate (usually DEC) (deg) yrpix - (double precision) Y axis reference pixel array location yrval - (double precision) Y axis coordinate value at the reference pixel (deg) - *XI. FITSIO Error Status Codes - Status codes in the range -99 to -999 and 1 to 999 are reserved for future FITSIO use. 0 OK, no error 101 input and output files are the same 103 too many FITS files open at once; all internal buffers full 104 error opening existing file 105 error creating new FITS file; (does a file with this name already exist?) 106 error writing record to FITS file 107 end-of-file encountered while reading record from FITS file 108 error reading record from file 110 error closing FITS file 111 internal array dimensions exceeded 112 Cannot modify file with readonly access 113 Could not allocate memory 114 illegal logical unit number; must be between 1 - 300, inclusive 115 NULL input pointer to routine 116 error seeking position in file 121 invalid URL prefix on file name 122 tried to register too many IO drivers 123 driver initialization failed 124 matching driver is not registered 125 failed to parse input file URL 126 parse error in range list 151 bad argument in shared memory driver 152 null pointer passed as an argument 153 no more free shared memory handles 154 shared memory driver is not initialized 155 IPC error returned by a system call 156 no memory in shared memory driver 157 resource deadlock would occur 158 attempt to open/create lock file failed 159 shared memory block cannot be resized at the moment 201 header not empty; can't write required keywords 202 specified keyword name was not found in the header 203 specified header record number is out of bounds 204 keyword value field is blank 205 keyword value string is missing the closing quote character 206 illegal indexed keyword name (e.g. 'TFORM1000') 207 illegal character in keyword name or header record 208 keyword does not have expected name. Keyword out of sequence? 209 keyword does not have expected integer value 210 could not find the required END header keyword 211 illegal BITPIX keyword value 212 illegal NAXIS keyword value 213 illegal NAXISn keyword value: must be 0 or positive integer 214 illegal PCOUNT keyword value 215 illegal GCOUNT keyword value 216 illegal TFIELDS keyword value 217 negative ASCII or binary table width value (NAXIS1) 218 negative number of rows in ASCII or binary table (NAXIS2) 219 column name (TTYPE keyword) not found 220 illegal SIMPLE keyword value 221 could not find the required SIMPLE header keyword 222 could not find the required BITPIX header keyword 223 could not find the required NAXIS header keyword 224 could not find all the required NAXISn keywords in the header 225 could not find the required XTENSION header keyword 226 the CHDU is not an ASCII table extension 227 the CHDU is not a binary table extension 228 could not find the required PCOUNT header keyword 229 could not find the required GCOUNT header keyword 230 could not find the required TFIELDS header keyword 231 could not find all the required TBCOLn keywords in the header 232 could not find all the required TFORMn keywords in the header 233 the CHDU is not an IMAGE extension 234 illegal TBCOL keyword value; out of range 235 this operation only allowed for ASCII or BINARY table extension 236 column is too wide to fit within the specified width of the ASCII table 237 the specified column name template matched more than one column name 241 binary table row width is not equal to the sum of the field widths 251 unrecognizable type of FITS extension 252 unrecognizable FITS record 253 END keyword contains non-blank characters in columns 9-80 254 Header fill area contains non-blank characters 255 Data fill area contains non-blank on non-zero values 261 unable to parse the TFORM keyword value string 262 unrecognizable TFORM datatype code 263 illegal TDIMn keyword value 301 illegal HDU number; less than 1 or greater than internal buffer size 302 column number out of range (1 - 999) 304 attempt to move to negative file record number 306 attempted to read or write a negative number of bytes in the FITS file 307 illegal starting row number for table read or write operation 308 illegal starting element number for table read or write operation 309 attempted to read or write character string in non-character table column 310 attempted to read or write logical value in non-logical table column 311 illegal ASCII table TFORM format code for attempted operation 312 illegal binary table TFORM format code for attempted operation 314 value for undefined pixels has not been defined 317 attempted to read or write descriptor in a non-descriptor field 320 number of array dimensions out of range 321 first pixel number is greater than the last pixel number 322 attempt to set BSCALE or TSCALn scaling parameter = 0 323 illegal axis length less than 1 340 NOT_GROUP_TABLE 340 Grouping function error 341 HDU_ALREADY_MEMBER 342 MEMBER_NOT_FOUND 343 GROUP_NOT_FOUND 344 BAD_GROUP_ID 345 TOO_MANY_HDUS_TRACKED 346 HDU_ALREADY_TRACKED 347 BAD_OPTION 348 IDENTICAL_POINTERS 349 BAD_GROUP_ATTACH 350 BAD_GROUP_DETACH 360 NGP_NO_MEMORY malloc failed 361 NGP_READ_ERR read error from file 362 NGP_NUL_PTR null pointer passed as an argument. Passing null pointer as a name of template file raises this error 363 NGP_EMPTY_CURLINE line read seems to be empty (used internally) 364 NGP_UNREAD_QUEUE_FULL cannot unread more then 1 line (or single line twice) 365 NGP_INC_NESTING too deep include file nesting (infinite loop, template includes itself ?) 366 NGP_ERR_FOPEN fopen() failed, cannot open template file 367 NGP_EOF end of file encountered and not expected 368 NGP_BAD_ARG bad arguments passed. Usually means internal parser error. Should not happen 369 NGP_TOKEN_NOT_EXPECT token not expected here 401 error attempting to convert an integer to a formatted character string 402 error attempting to convert a real value to a formatted character string 403 cannot convert a quoted string keyword to an integer 404 attempted to read a non-logical keyword value as a logical value 405 cannot convert a quoted string keyword to a real value 406 cannot convert a quoted string keyword to a double precision value 407 error attempting to read character string as an integer 408 error attempting to read character string as a real value 409 error attempting to read character string as a double precision value 410 bad keyword datatype code 411 illegal number of decimal places while formatting floating point value 412 numerical overflow during implicit datatype conversion 413 error compressing image 414 error uncompressing image 420 error in date or time conversion 431 syntax error in parser expression 432 expression did not evaluate to desired type 433 vector result too large to return in array 434 data parser failed not sent an out column 435 bad data encounter while parsing column 436 parse error: output file not of proper type 501 celestial angle too large for projection 502 bad celestial coordinate or pixel value 503 error in celestial coordinate calculation 504 unsupported type of celestial projection 505 required celestial coordinate keywords not found 506 approximate wcs keyword values were returned - \end{document} cfitsio/docs/fitsio.pdf0000644000225700000360000250615413246025103014735 0ustar cagordonlhea%PDF-1.4 %Çì¢ 5 0 obj <> stream xœuUM5½Ï¯è¶D;.—Ëe$$DX&\‡°»Y²»$þ?¯ìéiFcÙõõ^½ªù°Ä@K´Ïé÷úþðìJ—»§C\^á{wøp n°œ~®ï—¯Ž0ªKÊA«Òr|wδJà´äª!-Çûïî¥%Qrßù5…‹Vwô+…ªÊÉýŒ÷\c‘r6HÍýèWÖR&÷Æl[«YÝ“KÆû-¼ˆ¹ »~E„T³d÷…E mÝ”K ¢ê^u¯FTÜß{²?Ϧ7ý2•T¦°¿¿ï @H²a\K eYEB¬¨o€î¹Õ “R9snHs>þ¾{¡RX)»Çž=6™m? x±Zq„∛{ï9¡¸•¥†©T¨½' ’Oî·æ#Aú)i6ƒw9[Qro=#|)â®G'²¶_Aµ¤)Ôã¸tN’DæôGOA£f1ü¬5(ZöÒ7†Ð œm•Tu÷•… „QIèÍ?æ-ÏD¼ß¾§N´j «ªµfe2ùYƒN˜7«ö>°–€Îÿ»Îí¹·)F™x˜owö; J_%i¹0âÞý‡Š)X)¹Ðt:!…/œ.P?»ÂdR†HJ2*œ¹U(ú§Ö¿øŠ6`5‘'B›˜­ I=¡þœ[#ã<[ÀîcçÖ„ Ñr(uÛâ)à_¡÷ÁQd½Ži$ÞÛ u2ÕlƒpV?Jì§T¡«i"^?áóšlŠòendstream endobj 6 0 obj 839 endobj 17 0 obj <> stream xœ+T0Ð3T0A(œË¥d®^Ìe àÄé\…\†` P*9WÁ)¨ÈÐ(¢gi`i¨’ÆÑm¨`n¤`fa¢” ÉåŠÖÈÔ4Ò3777†3bC¼¸\C¸”Eendstream endobj 18 0 obj 99 endobj 22 0 obj <> stream xœíšYsݶÇß•/qÉÎ\ÀÁú˜8[;i›Æ×íC’GªO,)±›¶é§ïÿ€q¸ÜE¶å-F ðãÿ,À/ÕéâŸáïùåÙ½oÂæÉ‹3µù¿OÎ~9Ó¹Âføs~¹ùd‡JqclbЛÝã³þa½ fã|è’ßì.Ͼmî·[ÕEã£Íu«º¤ƒ¦¹jMêYjþÕj´‘´oþ‰bMÖZ?›Dñ‹v«;o‰Ò÷»?¡wc1ž.©”»ÜtJ›ÝWg»?|Ûèv› n%jþØn©‹)·J¸ŠÞ£UÜ ÑRlž£W¯¬±ãÛ’ê”ò®¹ÀÝa¿ÖËóÖuZ%ãdOQn­Š_ð¸Öè©<Ãcµïà1;»‹3šÁ¸0 .Úe[ÒéË Þ“”Cž<×YGd‡azyž0¥Év¡yÄ“’B²aÏêHš'¨ÀÓ„&>o·¦#<ÆéQ¶Ùá²yð†dÉ_y Ú(k›{-•q™KKX†YKÃKko9?$ççÞ7ÚÈeÞZ‹žíf«¿á8e®éðXxéµ>J7Ÿ´¶#Ì“Ç"òˆ­M“3T|V..V ¯ê=ž7òh—=dtóc-Çzqs¦ù ï]Ûø¡ÖyÞny(6,ÙøoÖ¿µ[O±3¸ìp7™Î`®péá®Ûy´î«WxQ­0»¹~9Ve^(‚« K7k´–k›—,ºü•–f3v„‹%v¦b·k£í·h4šÕ˹à€hN>ðL› ‘ðºiƒÊ1mä©ÐöÖP¸ïx~ ¼u½£ Þ!a?±É0ÆxX„#÷5ƒ • FbtÝr¥Y—¬óÞÇÍ3¤\êæ?Ù…”á=ˈY&BǤa<¸^ðÙ i”ÇHÙ ÁŽma;ÆŠ 0Öbî`è~‡ØeØ‚ï|Hë°½w¡p7ôp@ðlåî ^GàBUÁ«âu²Þ‰å®Ï̬Ԯ.¸ ÏÉ€^ÔŠn =¯â zwÞ:…ëêç*…ŸUåú¯Ð;¡SÁÛæçŠ^ïÆl§³þ¹`o¬ -ë;súÚÌé)æÖ"&€Û|ÌÜ âTy쀬ù™9­2ÃëÏ‹þŒå&AÖë× ØGÜ–FÔú.¬Ç»ØÛÛFi¦hXh'©Z¢”F”úºP ¥[Óœ·¥‰7vUºnÑCÎ>+6©sWçDÛj«Ö„ÎùIÈ*<´wdù?XزyLì­Ãt¬¥DùJcyUÏÛ<ß•¥L±”aIUTº$OÆäÑÇXnÄ¡.ÎöÀÈR§ÁÒ×9¹e\É59òAf’.[“)±$ ŒÓg\7@d.]Ӕζ¯$2^¶&놡F'óv'd“(àkã"3…ÏiÈøã›·d»äŒŒ¾–ïMèÉ Aã‹%ñ•KCÓE?å*E¸Äò¨ä¹X4Üç£õÓÙ|Vkô•IÍÚ¬û=À#NñÀĻù4‚6ÍÌîɥݯšÔûÎÞ®q‚zíjùƒ*P¢¯’1ÙwvsôÒÿ7jWqƬ›´BéVœ{˜fN¾Fyo¬ÆþÛ µø&y!­'t1—€;M»=ï^ˆš;èàÛ=yµ?c]½·0"ûlJÂ$Ì\øúÙŽæxÓY;å‚ݹp%kÇß¾59ïV{ºîJV®I”)“uåI@ùhnµûŒ*•惨U— íÒ-´ÿ½#2³çRÜö^ƹ; ä˜oz> ‰´ª‰Âë1¢¸\øfY¨°ò¾ÓXÙ/[Y… ¹•‚çL¡ëȤæSÜ…°Ç\[ê`Ά$ôù&òo“t3…t½§æ»f|ü~MÞ}9>Þ÷å`‹bœßµ˜;¯Á„PüÖòº¯ŒâjCË´O¤Ø„|ÔÖsþlìD¥ýù·"Qn"™¿´f©MB cPàönçà¶ãÓìÐ)øzO‚ãTÄJ#Ô̽YÄ>oïç[=miÄž.#_¶Ážê5OtÁž·±ü’B«æº˜ÿó4$Þãqƒg7‘·%U$ØÍ.bt¹¯÷ÆÞœ"Ô¢×éÊÝ€Å1—; ‚Y¤|RcÁ¢H½‰¸Aì1ý¼âö˜Tÿmbá( ª «Ö²ß^¬%ûYè;oÛþ&4Muë5J+Ù‡lÒmà03÷­Iâ³þä<4 ˆ€íÍóÈï‚b ;3‰1nÁ¡»W¤ìN F(æùÄw[ÒyÕʯ Øw{±ß[´^ ˜ì*´o,LЊ«;UË`w9¯û­&Üçû7FWwJž­ÿ½Mj ¤ˆœ§vþ<ûvûíê±wx)²Qošù üR†:DÒC4~§FWÄÛåòѰù6†î+;/ÅÂ÷Ivcñp>‡“^7ŠYºxiÌ ”ë¶íl!qØSqäC,Ó(Y|ÿ‡v-ƒR¸Ùbê‰øçl«l¢v³cs¬ÂÖõÙ—uPåfù¸ÁS(ž£+Ë\9à8fo/©þ…ž©Èýa€8œ4>®º¯³ùÇTÎy¹ÉTMœ“ Ù&‚Ýð ™¹SS¹àîí훳l˜ #?`|û펭Á³ã BÝ„(\³ëé±ã§]N¬¦äé% )gÛ,zµ.Šå]á±lÃ3äõ9AŠN‚M%ìøÀlô›Ï홺ƒvJn Ô•À`YBˆ0È?Î×jP¹|îh4ŽûjÖ-“} è ç€÷o0!Âä2Ðy”!Ýk¡ó N:óT²ËóÔ_ð©yØýÖqXbOy5Ù8lukæYܾf+ÊAž¼ê·ñx:?\õŒûåÐT³‰½f3²6úó(*ž²3—Ý9/Sרš°¶êØÎ¯¬p%…'¤nÐoÞ…y—…~—~ª2²+ª‰­Lmcˉ…—?Ð’ÃâÌc±[’Å ÅÔ™£Ù˜7E¢†+è7[Ì(˜Dñé—*üÈg»³¿áçÿ[\Žendstream endobj 23 0 obj 2270 endobj 29 0 obj <> stream xœíœËrܸ†÷ªM½)bºGìÉ9ðU„DàbxCL&™; øK†d©bÊB½ ñ Ç`:ùúøBBôs W@†ÓfƒA¿{ÅÐüÈ€1Eq÷eÎ ÀÝ1 ŠÒ4â-6f©–VvÑbä„IÆY«:Ï¡Yšá\ä„‘Î@b5&ŒqCã®ÃN™¡rÁ !ý÷P>„‹”žÓÓmx.Î4>}ª†”ÐÂ«è‘æs–q2'–w“­ÅD ƒXâ{ OܵÇä5#ñd8„ ñ¤É Нtù‚›‘æÜÐhj¾É°ƒa¢çÈ(«9é=@ÎÀ;!gw‡Üü„ßC—óMøÑr°Ä[,nNïd†íf±#jhQÔ}·DIÀáìÎp&r¦2g½Ù7ÚÆ¶ÁìËFJ…GrAÓNU틊…®hŠ pƒû¸d‚—œqÁŠcÞnì‚MvÁOÑJJ«QœXÀ›Æv^é䌭WÉh'|+TXN7³)(ô6ùû¡µ³~5ìK5Ê!ýÉð’+Ic&fïï[È}rÒª‰“–CÁz©“ÎNÆn¦C8æKMO9ƒ.C^øž_£³V!Ð5ŠE¼Žg¤§±w4†B"ooú(êÅ4£Œ_åÁªÿ)§Üóê4Šþ}Õ®]=Ý=‰~Rì;«O•»•y¦¼N5“!ÈÌøjÌcäaó]ÕÜ)RÔ'$<§¦è¦­X˜ãí‚°_‡j( ØÿÜù­.çËàs kãæ­™±Ð™©LÀ¯rß/|/*Jiá ‡“K™$¢êE›pSLnø2Ó?©º›jHr¦"_IäÜ4Ô?YÔ°«9DŒs´:dž_àƒvön€˜’³¢ˆ]à]œ«Û2⪃F\”Ã7EH¹ŠBª4@êççy§!CÞ$÷ókÖƒ Z)šß îù‘UM‡Ñüòþ\•i̤h}Î-§2?Vñu1§þ¼ÅبŠ)´ZuËZ‚>–q¤¨ª1äß{_qàxѶâ!'YÛšÒ‚£Ø‹Ï“ðµÁÿ0I¼C 7na ŸäÚ™ìS± pú·pÀ%ªwù¬‡éÊ‚qwÍ!{³B5JŸJi0ù>‰øÞ+ã×»=Öq~ãeE5¼bÉ[FÜ‚0’ˆ K…ÞãfÀ ù”Û±œÈˆ™åD{IÓÓÁ æäèî ¥Óû·I1‹ÿ$ÃçB.í–æþVrhº¢(V·HÑHnŠl(ª…Ý0Q,r˜Š”©Ã  i÷PŽŠôYÇÉÎüÚŸŒ)e3‚þ¦²>ÿQ,Ƹ)1i©´²tJKàI¡µtÑ–üSÁÚ330o·bjÔØ9ô銮e0õcð"Ûu¬ô¸Ø¾¥ä.ñ”ã‡iUÄÉäØÚ³ÍÙ_àçÿÑ>ôendstream endobj 30 0 obj 2776 endobj 36 0 obj <> stream xœíœK“Û¸ÇïSù:’añ~äèÄÙõîf“Ør.©â׬k={½±½ß>ÝA4)ˆâŒ£x¦¦\¦D‰ÿèn4ôaÁ™XpüëþyuñÍS·¸üxÁß¿ˋ"Xtÿ½¼Zq굌|hã?€ïç‚ÕJZ­´j~IøHë囌÷$5Xí‹òíA¨ñÒb/ÃÇ¡„Y''‚k=“.Ü€Ü[áè2Ž]sª‰< "gš?ØÂ@™BA$V¦Y©±jjiô<hˆ™w6Ö¡l”ºçm3ÃÃ{G.‡BJy‰’¨Lzúš{ˆº±ÄŠ8_!ÎØ­ (‹~‹ (‚öDÍÖ5‰#R”gfâó)D æï­DY Ôi$Ð:á¿/xç†cH@~ó¼âç ¨d¨‚Î¥Ž9˜%'©L°<«Q¶<œQ8ÃÀé<ÌÙ k*@•ÍT=4×éÒgåRr ½5x/ÀI¾ý-)¦VH>ˆZJ¸qf¹~æ0}´Ë…­E¼8BDÜ6åt)Xf…:y| D<òÚz0 òhiK ˜Åþå¢ĸ¯{kX6ƒbdv ,U|ÇG­ŽAq!+Oyù@ë¹þåºíã°•„|8ë Ñ͘7ó<8‹§pý œEÛÇ%x1éë¡®¾HŒ¾¨ñâ*ÂMï\f¶sÄMäòÙÏŃè[Ö—ugaÙA;)ÒÆ‹æëkk—pP Ñ:/¹¥tŸ|”öß´¯¤ê€lkî‹,éé`jÎæÚ Ü>Lè)L®Z¯™äá"ؼ/œV’Šè²* 27 ` O7 ϸZ+iRÔVçt><Ä‘Ît0^J]Ø-…Ás· 4+%z°w§‰ ÄÀœÙÛøŸ‰_ˆé ¿Ôò¶ð÷_tïC1 p½BMme¾’ µ„±QJöpx)t4õ6¡&±Ëõ(C¨Ÿš[zM¤l˜|RÕÈ’¡××@LÁ—»`íZœ[hî¬'èå€~Ëx2Sw&ægWXüt©d> stream xœíX[o\5~_ñ#öÑF:®=¾Œý%E@E¡Yž%i¢JÙ-í–ÿžo|ÎY{ÓÝ’ ¢Ufí¹yæóŒg_-­qK+Óÿ³õâÁS^^nvù%>—‹W W–Ó¿³õòó˜aÅ[Üru±¥Ý’i™r0Ø\­?ª·z°†ˆœcõB“afÿÓêkˆ{׋›ŒÍа:‡ÔC=xÙ\PO„$—]VßjR«¶s¢gBˆLÝsbuª‡ˆvy4µïéàs1œ–ƒ·†])£É¢£2“ƒÊAµ¥b¬S_è`rN1«ç BpDêö²FN=ƒÔ|,u5óN¥lB‚{ˆ Ù@ÝîZdRâÔ/£Ëɦ¦F”7SÏ¡Ê'±ñXN^J¥ßìμã„ÚGº8„+zõÊ^ë!ïCÙ3=š"!k«i%ä¼HŸ¿¶z†C™o ×)ÐÜ—v-t‹ýàY(‡èZ|€/±8Ì&W €5è}Tÿ:¦5” ’Ëß¼'Oï@@0tÞÄÜ~Ÿîbb~GH8/7À Õ¾oB$õM½„L“:òAý1ªó\’úMÃe,†ë8ëÙê!Û`b¤»Á½EÞur2i„w½ ~#ô&C=¸ðù†¾;)XQ†’úN{gb˜X:xl¥’Ř9tV^‹`4¦[õݶ“nX<ÛQ£}ö¾I¼Õ¾R®€á³‘æñßã?X§ÏÊ`h@œzXpGzXæTau%°‘*t§Ð=m¬/xM²_zÀ‰ÔXÏb¼|Èüß[´d­ÌѸ’Á¿6šÑ6i?†¶ØÐÖ½*;¨Md²{ N¾¢€Â½ÈÑÇhíCÃëû–Œ¸˜Ã#ðšEŽÁ+„Wÿ“Òñ¾ •÷j0ÇÅ£o¾§È|¼ùþ]·B׃§öÆ×€7zà\çW·{Æ9íñÐЇð€÷h[VzL¶ö' ‹kíPµ`¾£žÕY’K`T5k’4ZGU³IG_G”ÐD¡ç¿63×Þ˾§Æ¬¾’±!—€2)ÓùìRÐíÈ€Ï Úî@8;´Î-@âZê,‹£YŸ'ÿRÈ Ó¼À]¡Ü«Úh9½Å­y3þLüQ ²œ§úz3e‹ût¦Ñ)l¡Xß8s¡Òù=3‡”ÕÏ»ÅNëK8ŽÁTÇÙ9ó¢…l³“=DªÏa´2ùœ55*V zjÇœ³ÿx±útÌ¿kùÇ‹;Ø¡# îŽ> stream xœÅ\Ys]Å~W¹òô–{SÖñ™}&oÆBŠ@Å(Eª Â’—`KÆF&ίOwÏÖ³œ{eC%¸ù,³ôôòõ×}ôÓ麈Óÿ¤ÿ?yuòà±;}ööd=ýþ}vòÓ‰ NÓÿž¼:ýäò§r]¬•öôüéI|Yœ:yjœ:=uòÝîÑþl]ŒÕÎÛÝóý™\¤Jí.öëìj×°{®¹ûy/– ƒ»«=\Sƈݛý™rvñ;#y圴ÿ<ÿKœ[/Î;s³hüéù—'çøn÷ ºZ£w×{#½¢áÂâ ë¢¥ÚînàQ¿©üîV¥½°€[ú°»'ðš2JI6À _øUx¶"l0S~'.PH×ÖWaW™Wxû‚ÁĪP.°z­ƒqåâœS»·pÛêÅ «*·ãZ×Õáª4\RÂRËýW¸,k=Ü¿*÷AÒÖ¦¼X`ƒ|Ðú$L*àIï4d¥¥4œOYÝ8\¨ömZ²50‘Z¼·Rð½]áý€ãï>Û”¤Q°#Ãgˆ/:Ðvñž¹®ãœÁ3ppq‘Rizäe^]ù¯þ_tÂ×ë°-Ôb´Ê[v¶‘#{‰­×ʪk-r¹nwk|µi ÏÉXš^·Mi=lS¹%Píwh&R*øûIu¤iÅ«ÀkðÔ¢M<Šéõ¨q\›³ìS\ª[´ÍJ`àÆóúvž Ey–dy†‡hÐê/£«ÉõŒb:±ø°‚'a÷MS|Àøñk\‘[ÐUá*Ÿ_I›°«æ{ÂÃz›0‹ñý®ØÀ/ƒ©Ûr 0ò”·VšîÂÑ®ZGPUtÇÁÑL²jÁL¥®ÓئUWÀgÁ†¢ë <ßW{ÙÉGyð¿0é£:ÿ÷û2Å‚ƒ(p¶!I˜Øòi0”ábeÛ»ˆ« A1-GÕH^ÍYÕ)ë÷5Y–àUŠe•¡o¢Û ]k—Õu)»Q“ýhðm½æSÂUONT¹êD SÔ›8O€(·¡½ðB“¥è%8áAM•ÊjJW¿©°PMAżðd i÷d _Pß7Þüª÷樻¿gg ..ì>lj±âv¢©MЈ.âÓ©·Â…îvÙ;ƒ}Éæ…Å“ž¦Èc¤-Kp²Óæ…çîýåh2ÕP.Ó*­à¾7Ç))Õ8åÛÁ/´qìyh³Ç‘”Ǝɼi\f Ñ¿Sd v‘~Sÿq3*ä`˜¥Çdúõ3 S ÚÔ_-5ÅnöÒu—£§æÎþe‰ï§1庾þ MIþæf’„„f"ÊjÓÍ'ä‰ËGàÄÜ7‡¢5öf…/Gß*å¶Ê¶–ùloê»SDŒ36ð*‰¥ )lؤ)`„U˜e$]tžû°VA3Œ›8ÆýMkQÚ°q±ïÒ3% áˆÆndÔ ºKzeÁµ¤lwD•(ö@ôCRZ»{3(Õš„ŽãadìPªÖ„RG ö„¢ ïXAó»`‘”þ6s׳8US­>¨ú||åu 1¡Ÿ›Ž«w°|È”¥»Ó9æô°Ãà$®Dñ‚Îr=½k*C«Y¬ÙCÔg¤gÑšœ°}{ÎTYµÑóo¸Õáâ“r6@.ŽÚ:^õ›sÌó$?Ç*ò‹iÁïîrÌ.S¬RkH“v(˜¬sY'Ñx²-q¡¡ «a W}+®Õk]ÿ= Vµ8M ´£0Ífï‚st¯ÑCL<ØæjIZx¼ÉZÔ*G&½4£ÉV9zbÎp8™õC¶µÄ0û«‡íˆ’‹nR˜ÀŸ, ÔÚC€Ã“Š–À›fÃÁÝ€÷"t¤ Ó…†Ã‰›³2æVqaº›,¤¡Yh0rÓÝÇĆÕÁ¶î)pÌ´C¯¹£ ;Œ _¹iuÏð›ôŸöÞÒ÷ª‚3 cäüòà†€´†4*…$é—Ö¨ïš+qï¯1ˆŒŽRË@ØuªhI1ÀØÜ½=¬ £N=iGוá Ωáðô}Ζy·W´t1‡Y7L@VaŽ¥`¯pgNQ”DI˘©è“¾ÓØ#ÉãDJÀ™)ªäAoh¤(Y³A±54YöÆ·­›~‰`êq’fLI ù0½×àÒå8ìú—|)"Ç´ëÖóßë6d*¿†w£˜րDZjYxÈDI3–‚Ó‘g¨òõ'N¡Ç°Û$t7¹C†Äi©dl©›Bd±Žn¸ŽZ³uE˜®lЧ‹Âf÷~b^™Š•<¦”uŽô[O¦ÓÚŸSÓ— [øpž$'·‘V}4²üÐÁ &Ã'°È¯ ê ‰<šUÌòÝqt“UÏAÛóLd™dù\Š(3»b:]dϪ ‰—õ\á™R\'Î^˜É`vâ7{ÉDÔ” AS<«u-HWÖ†öŠ|Ìêù‚ØÙ4t\\eÏòÍYá)¨Df£ŸDÜ( Á¬­B?b-<êI¹É–AY©)où,ÑÚ€¢³Í|·ëàB˜æßV}cf< (Ÿx?T1jkV1ÁyŠŽõÔ°ÀÓ ·!¼áúf0¯î$±Þ(œa]ò¢¯i ?Ö4›0­if2X·ˆ*_Ûâ+"Tˆ"ý]ÕÓº€2XŽä&wžÒz÷›Âç¶–e;åÁ \ÇεOÜ%S€éG›¾MõdHö&¸Œ1ˆ¤ >+&sÞ~@Æœ…¡í¨ñ1ÍÙÖø,ÅYe‰M;Óñ7­tlð)sžLÅÑF„© ŒúÓÞÏÂ3´)»„u-™¦ÄÜüõÌ4ßIÆõ @\SmdWužƒÌœå}˜Í *´ÎÒ€ªH%äÜ6·•&å„¶¬"ʼ,#‚±0ª4/bý ^ëÿ礣´ÅÃ+Åb|¯uŸì³U} Vµûå9Ÿö˜ÙGg²iܯþ$¾YÕ¼Ó$!4{qèc<Ù¾Wgfè kË|ƒ’=ƶf !g¡-2‹N"‘Õ´÷60þõ¯°$k5,éáLu¬rú@óaùù¤µâ…¢lqL‰0C/Å€ óõA¡ŸSr¿yc ç@.˜=8® U !e¬`íf|Êô­l Óÿh ÞÏÖÐñp).ïÇ V,®( §ð²4Ý14öªÆmë.Dɸ­¤¾©ÉÐfו—[ojÿìšš‚òŽWð`6‹`Ï{#!‘´Áb‹|•.6l"ü×UcÇ„½¾ÕRIM¼‘!¶¢$ëà6ðC¦Ygùù$AMÅœVZ=fMoqû–•ãâ𬲾Q5£Èü]  Ò½w08ÜÇ}Ä®6Ó cýF`ΜQ±ÒjP¤â¶ ˆmæ´Œ´¦$HÌœç–=k›¹Ìûèf­7¤¹›†„!l+ŸyqNo™`•ÅnßâVà ÚŠèõÄÔ˜¹7ð/¦âQ–m¼Ié ¦ã+Ò6qX¦>9ìËjO¼œP;'MÑQ'Zßmf"“Êi}tÎ T®Oλ\J¡fšB§êð<ÁïK')nbµNÅ,å¦K?òˆ)5¸Vv·›pQc„!±è)¼sµV I!¿ë]«åØ÷Fc;‰çR‘f TBSªºgÞïPN8o‘Ì'Mô3SíÈ+^â}É‘#)…–*]î_ÊHBnºQiio.ЗaÝ) G ù×(„vx\0=È’ hÄža:n ŠÓudòÒ|È6ñ øbÞ’ u 6†ÎŽù¬$®<èó(™¼gd§+Ö¦óXÈMÊí#:g¨c F4ð#4Àí0ïu G E„IG¨m?´Ðß6¦zõŒ˜WI“EX’)Ifˆ}g»ž£t6"Õ?‘൨çc´;Ö’ôUј‡m_ìCR‚sçM“¬gê²q†×e¢8?ø ΄£t5o‰XÔhb‚æ{eÉëU"Tƒ4âT9Ï:w2bõkÕ«Ã…¼6€³ÖôwÿcÏTuf59gšA±¬ŸšÝG›Ü`þM¢U\‰ïšŸe""”ç§õ–*äõXQQbéæíÄ—íU C'ÂëXxïrÒÏwؽ~Pqâêv d¼=¥ïë“躂§oZ(bõQÜŽx4ŽáCˆH )T$"sqÊ™P­€Ûm~º¼;vo|È€Òw )aªØrŽ1:ˆy誇UÄ8p¨{ŸY…ê<ÐE‘ ¬(«›K©I¡àZ$|‡&9µÆ^îHþX› rIÕÐâ„Xp^6lcÁÙֺп¬êÆ[m S’$ß¼mc‰Ð]{ëM¼ˆ™AÛÐN‡ª?ŽÍ¦9 ±›¹yUÔþw¨iSöµÆ6™´®L Rïfþ1„ÈÅkÞAËŽ1ü´ÿÃß­‚”åêÌþUÜ–±¢ ?i¯!h êBÿP'hZáÇ8ÁügŽ?¿k,ß.%¦(E’ µšë¡ûmJÑófÓV·µìâÅT³¿ÆFk©ê† ¶L¬åæÒ ¤¹ 2ãG”Ǫ´]]•º9îÔ„Î>“›çGàfùQžð!Ójãã£Ò¸ê÷…–ë<Ûý¥L´ß¤¼b]\aÜ«“x1æŸÓº[ןöXFp6̺/åCtÅ¢6Ì44fRžÆS‹Qaˆ‡r5t^3Iþ¨šÖŒc†¢6?'JÊÚ|û:o»fßNtØhâ _3ý”öcÇåL[¬C ~ ¥±!2©Ü˜ú¦d†éUÕPÖró„ƒnÚ©«Iþ?Â}þæ°±ó2H&mÒ±Mr?Ãm5™î‹64˜&WÈMÒ³ìN Jˆ'£é»Ž™;Æ5Å¢ Д"jfø4$'UÍ·øF^zR‚ªA?~†²†èX™]O•·Ã.-ÎJ\æL|¼Ø#÷¦pŒ»åçzá=*%ª‚š>¥ïJºLû,~¹²Ý~‰hS9ò¢Ó˜q)Mzy&m¤Rú¿c]ÔF¥‰Í”<³úXŽÖéô¡ogî,3ä¥l|YǪ7ßW±xMŒl›Ì¡¯áXÑ7XÿfßÕmv˜ÅŠdIz’Ô²ÂÒ"ˆ´åD.'UXõkÝ%yþj •‹\DYl7åÚ»úàƒ"¶·“3±ý\ÄöËlÂ7åâUyðÁìè_” ŠçIs$ý/žb¶óø‰Tˆê-"!ýéùÉßàϘ´˜µendstream endobj 47 0 obj 4589 endobj 53 0 obj <> stream xœåZÝsÇW¹ò7Ü»)ß²ó=Ã[Bˆ“Ž1Èå—«rèŒDtÂlå¯OwÏWÏÞÜI`Þ…tÌÎöôôt÷ï×=÷n5Ob5ãßôûìòäás·:¿9™WßÀ¿ó“w'‚&¬Ò¯³ËÕ_Oa’02…9ˆÕé«“ø¶X9¹²^Oððôòä§AŽæçÓÁl%ølÂd5¼pº…Iǵšœ A ÿÅ‚×aøË(‡gãZLZ'‡Sšã¥ÐÓ:úFˆÄh†i\;ç')ÔðOœâƒRbø÷˜_vÎ:xCÉIí†ïpPJiíð·QOÞ;†`öã:›­ÊDÆ7…¥ÇýµÖX§ ®A9'BˆûÄ-]ÒMÆ 3Ü‚”Õ5ûq=£*B¸áø6°;Ì𠨥µr¸ÁÅñNïGºZ)†×£D5Õ°ƒÍ_Õ×Òdgåð5®a@´^Ö i ;Ûá|Uå4Ïnøu\ëI)$[øx4¶§UØœªS®¬'ót5‹I5:± žñ_\O*ÍçÅœRìñJølmý¢~Ü´F9+Óë‹—°ùÉÚà}#(h¦À î#À¨Ù·¾ó6ŸÄfDo^MÖgï>´¡ð Øãj:‹:xÁÝÎ ýþqõË¿ÙY™‡2‡8pÖÖ…¥S<áüMv6*7iéìðf4z‚ƒˆãñ˜ÀúÌŽÉÊ9d¥t䪸h•`âvg9iåÐ Ñ¡Œ´É³@“­“ÍÖ`cgMÇ<«ºd< íÐtýns¶¢uެ¨ $Å\´µ¢R˜d:kLŽs1+žÒGRŸ¢&11½H>hd++Å ®£ 8#f£mßÇßÀL-&©ÈÆe?æ DÕ5Ë“)*í!¿0óK˜tjÒc©öQR7æ/íyþÒfò*Àq(P.žè¡HÃø÷®*Pü÷aùAóPSØÒ:†}Š“1#€Á `úA•=¹Tšóªž•Á©^•ÁMïõÍèáƒT:•1¶ÎntSðNúcyü°·â9Éqm[׉/Ëàë2ñª'ñUYð}y¼ãúäÁ·ENÝÌEøKgb9….uN‘9:s¬‚$°0ø2¤EHØ?–ð÷¬¢Ôô •àŽ fÊÛÆ›á!D»%çgQÁ–e`‘²µ³ºFÈ%0YöC&…àP’Æa<âœíuñ›]Ö 4½„ú}Þâ»pà‘fŠüB‚*’&È$Ö“7ø’… vWwh!™¤ÖŒAoQ¤{ÈüÌ¢LÔ¶¦íœ–³Pi=Ï÷ÑÌfañ½m‚×%ó³çƒ +n™€âîWrLäW#º‡Ö]循«±5êÂUfc< Þ#ØÉv"Ü1+d.¶3cÁ¨¢m‡‡¹âTvnÜõ¬øh…!ö˜½”Óº‘Ù0Êà» "tû¬zQ†’&ŠvK¢–âèm ù#ølCT§8t¦ ‘jlA¥ `uXq3•²(¬§–U[+ˆÅ’˜¦]X8¶þ.0úã.ò2KœN '1®© ‘³@ÕI!gd Ì K"/^$Ùà}51Pºj¢bJ×@´e‰ƒÓ&¥8¡–8望+J{ÛçYèI6 ƒf½’\=Ôö5²eÅgeÑXZåèØcœ¶ ¯¿‡<ç! ®ëhª/€ ï×klWpBö§êÊ5¼0QÄèe&‡hëñ!–Ç=¶®v˦QH®œKÕ  ,¹Ê'ëønz…ašµøúÐI9ì}jHXN<ªLâèùGª ¼>Zñz¨ eˆ( p6m|³'`tFE„®Êñ<¡UÅÏV2];P.*ô0Ê¿©Õ>ÙK´Y‹*P!¨ ‘:!êl¥-9Âma¸}UWc‰»³R71k[0üM¢m¨„vD„î“– %׷ňM7‹ÏBD?7yjzFôæ@üv jEÜ¢TF†±xÛŽ=¶[{Fñ–/!MMêûÑÈ(‚èc@ApZÅ÷…«ì‰Xd¨-'š«‘ëêÿéäŒFTC*¤ÁWiËš#‡u0Ì’¤o;ÅÊñVNµì[)KªýÖÝ¡8­¨–%Éb&|Ùº6ïÒÐŽ• 1 1©¬³ÏöMZ<ÀÞ† <Á7Õo¥MõÜ6J${S$8=;DÂG¶ƒŽ˜œ LÉ#íÊó­1ªºd•©òÀSŸwËJ6¡æNȉnMFOì8=Ž›v·áxÑí<kmì#±®6¶lú°ƒ#Gqm%ÊÚ¥¦®0SÄŠ#Œ%`vúEzݯôt Øt+Ó%Ò-JÑ[|ÇRd4Ú5j‰,ït±CíUê7ŠûÀ‡ô3U[ýr¨ô\¡km=ât˼¹ç–ÙŽèýÛ¥f+cD›ÈÚ¥òjsüÍüüÛÜ^-ÛÁÿé0%xFâúã·jÖÛ­ ;æ¨+.¢# ••jä¥ÍÓØM¸T¿ŒÝä¬Y Ì‰Û õ¡I¥”ËзÇÓïuç|2é&¦va»y²Q¢Cz"HÞIfªëÆdFìYu¸÷´Œ{­‚M#¯îèªÚþÏùg!ÜDB‚› W¹¼–CˆiÖ%ÑgiK[”l»w„䀅Çê•Åïò Ç%•@@ŸÖÀˆÂ¾Azøä@¶pêx±h\Œ…d‘ƒ×•0~Ã8;¤éªé&b½2‘ZÕ¦6¸ƒ%âÊãAy 7Á[FM7ªÖí͆הңHÛ$'`Þ˾sé9&×}Z®|öÜÐò]Û&ÎX÷‡róÑ«I~Gi†ŠÙ~à(r¯¡½b¥2¼èÛÛ*à߉&EÚoÁ4%žÕÛv‡·¸± Tcô’Q¤6ø#œŒs†÷;ûÕ뮜ÑoÍjäÄ삽¯ø• ‚\èKÜ9¦kóÄð£eZd¸ ˜§â>äLØÔn¹¯Ž¾ªbÝv„)ÑeaºÏa„U‚ œN¶Ù¡§{'rÇ¥}Í|CZ3½=%¤'6Éðx§·y‰Ÿ‚u*³•ËÞÍ]W¾„Î˲ý^ä%W — g•PÈÇgÜvæÊRZºá]R B-%–ç&4HtüšwCŒ¨ÎáÃn޽€«bç ‘Ú û@q›-ÑÂ@çÖ|Aô©gr™[ÆàÿË›¢±j’÷ºD ïT|Ú5ܧÝ!hOÈÑPP ÑÙ÷²]ÚýðôEk²a3_½2­c˜ÑCôz9ùòU'l¾+2å±ÒÌý¬t’<'A½B47Óë<2†´!ÖÜ<Æ8W‡Z8)ÜîÙÃáì¨ „G¼Z^öç×àÆŸó¥LLäLåkjÑ`g_:øÌ†zçî¾|ƒ÷RbùéÉéŸÿo¾/Q//Þ—o%ìz¶zÛ15šíÉéÉ÷ð÷`aŒ endstream endobj 54 0 obj 2697 endobj 58 0 obj <> stream xœ½ZYsÉöóÄþˆ~£{ƒiÕ}8ÂŽvåàX`¼¶ÃøAH )¬ƒs×ø×;³Î¬>Ä€±!4ju]YY™_~™5o;6òŽáÿôûørsðÌv§ï7¬û~N7o7«`78šS®¿¶Ê8XPánÁvÚÚ{GkÇ ‰´ö° 9:gÇM`Wåui7ÎNŽÖ­ñd༜‡öªÓ:ÎÐ$ʨØÁsØïœ@ƒá˼¬5" žjÈÃ`èO.r=èÜ [¢l<êTmÁTð$ª ž„T¸„ÒpÐŽ3\µ±wÝ_ /É­¡+á>à$n„óî¿[.õõN—¾à'd#dÞ"ïE~8AXÜ=ÙÖ’Ê5ºêÜ{ž´oÁl‰rwµ}¦}ø'Aûh. õˆÂºÝ `U”Äk•„ç$¼“HP[,û¶ŸgG ŽÜ߆î üüø·hèiÂr2óñ a³àÚgxnTZÒ9ãÙ1Þ¿E x”Å:P˜:ÏÒptaæ8¾…ÐŒRA ƒ?-CÍAhÇ0Ò•¦q‚Pµ4P„€ØK¡zÁ¸ÞcGàÿE_\á{XbÌë¬/Ü#ð#÷Cô€»¯ÂÝ/úvŸùs²n@TðÙ}$…€‰qzMÒ³`ë¹Ñd[‘sW°Y%L‹'ìÞyUÿeà|ÜQ_ÿ+øú¬ñ ²'¼¯$jÏó[bb‘D'!o£!iæ+F [ñà‹&G¦ @æÀˆ ˆCãT cD–ˆLŒ¹àQEëÀ?õ-” i›Œ¾µ~P8ü=vä¡c:(äN¿Y@åàLíÖå²÷ëTKOÄŠÊÁ“ Sh– @[É3•S…"´Þ,„j>ŸáÒSòVÊ]ЇÀ[ƒ«Ošˆ†›(×Â4ÊïYæyõiÑÙÝ¡%p@úÊŽ e°.t ìÁà1MRœò¶|Êé¥aªh\ bâ]_æ¯Q‡ˆq>ÌuLlHV šÿ/êì¢sÖ!×(ä^®sUÔ B&à݈óÚ ²Xˆëþ›l,0®Á3\Î-2o£¢ ‡Ž “j0íMÀ!ޝ¢ê”tdÄYÃÓšÉà—…à%¾¿Û<Ý¼í¤ (Ï:ÖuÊ€*×Iñß8,aÜ=Ü>ê>¼ûøjsð—Žo~»?߃_‡?t¿ÛÜ?ìž®–6ÚL2×6”÷£¸ :V8ÏŸdoê¦x S‘ú'ýÜί*q¹[X®ä¬bqZH‡LVÓ™6æÚÊ ' *o?«AŒ5'ÑcÙÿNƒ\bÌ„e`5Õ¨‘g „"«–“À1=¿‰5¤`”ã ÆŽ·X…:âó9‘E&p ³àA3y›')ÒTçhœò×A““niÌ'd€(ìrDšg5ò‡ý¡oåw$a âN”ü&2T)V‘å¬8 ŠO 0î:ÑZx ÔÌy,Ül"ÆUÍí©¸3ŘÄpõ*ŒäÓ™dë§Õcp-¢Ê‚[1FaÉÜ™)Û‚Yp5³&Dœ0åÛ,“.R- ©hüÕ퉯'- CêW?ìTCïrŒˆºÕþæ°}eñάÉTpž¹­IÌ™´œ/û.àP”,LÈÉ„Š}¨)Ì|Œ°U½ÓãnÜ$¥'‹½Kf>”­|U²Ÿ11­Çжt4§53„E¬£†}ÝvµÈ6øNl³äEL¯äòM*EƒHðån|NhE *½Øõü=*· ’ojb=£’èM$ Nülæý9•ç ësj;A+t&â‡oZü# ÕÙ—<©Á}HžÄÔÍ„¾‘lB^ò†åÂm›m  ˜ÂË"®)Xª•¥Ç£÷H,žEE¢^‘ßép›BÁkâqÇK$å„@¬R–ýÏÈe.¤ìWÕŠm“Ù$ nŠ/B¢¹®¶º¡œÄRÑ}Îàѧ*Å;K‹ Ÿ J›š7ÞX‰éÿ<ê=Ë¢àªUâîDŒ6>- „Ü7Õ¢ZÛàT3®uÿ™Å)šúMÓtPŠÄºœ¹täÌš–·IæCø¾¢]€K¦Bþ¼è —ó”B—ñ>«QddÖòeòó WÆ:ÖtóÅÉË›Ñ{… fèÃÊ„áÙ³$YfY‚]ªf \j™‰„^Øh^.Å&Ø5S4ßÕ… W_QªnŒ™Ø( €Š¶ÀCý‚I¬¤­²6Éc92íhV…žùaN·®’uÉ6àµ`Û8™5Y¸tš`ã-ƒKºkc½Âu/]|³Ég~­`±§ÉÎË%'ùì|cDÒµ¤ |ïÂU Yj!AÁÙ÷¢Rdˆ`*&¤0»>H…‹¬B‚Ö¢á®]ÌH!G)ü *=$ÔKªxÿùrÊš¼ëz)ü|éÅ‚$ÌÖgßɰ–4¶mcE Ûï „.\©,´½RX&~“D3²–³Û¹=pí«=àîèxëšqG–ˆ.f¨7Q÷‚)oÊ8÷m/ÆÂùîq1&Ð;ˆ¨“rEbº©FÆ8½'&×°3ú˜¸HØ¢Ò-É’hÌ·V g&øóq‰3T»ýYÒÂÃý·¡°Ç<Í/2ŠXÎlxà“wV9U  AZŽ3¦›4^/ k ¶ž° ·BV5ár<„^àò2^¥Z7pÑuZ½`Õu+X‡Ø!U¸øªšvtý- 8È1eãéNZ\[Nuÿ{‚CÏ”£E7 „œqÓ5T2èpDL!4Ç 6L&> stream xœµ\ëo·ïgÁÄ!_|WäVË7Y ìÄŽ]$­+M‹8@ô²,Øzز»ýç;ÃçË=lµA×ç]rHçñ›áÐoãÀ#þÿ<<ÛÙýÑ,N®vÆÅ·ðÿ“·;Ì7XÄ?Ï÷ ãðfp£c‹½—;¡7[¾ÐVðqïlç—¥\©_÷þ­£­¹àƒãÐaï}½Z‹ÁçØòÉŠ ÎYé–V|ùlµfƒ”Êðå^ió(¼Ò.„·È.ùJ-xÏ™8§¡É8XÇ”´çƒ•#QË™\>ÅOþ'–‡‘¿EÂfà@àñ Imb'£=Ÿ¯Ö ˆrÃhƒ`ιÖË]˜[œR ôstÌ)=Ã,mPè~JKù¹æÜ L/ÖÀ Ü |=ƒ>ËS|\âã ñqwøxŸíããHŸ‰Aéöð»½?ÿ²ü¿=ÂÇ×ÛÓÀŽ¿ã‹³[Žý8¸fØ xü3Oà_7ÒÆ‘±ŠØ³Üü|çæÏsïýüë47>ÏÄnž·o—Æ{€oòª}Ç—¹ãOyUO§ ãÝÄÍ<Ë/¦Ì l ý|;.ç>­!á5zô²È¢¡,¢:¿YqÔ$%@¬µ1°dÊe9¡G‰¤Q¤S0”J­9ƒ½‰~_ ÿ‹™úÇ•5áã—@S¹Ö¡(]é…\£xòAk£%Œ:ï¬â@¾ƒ)ašŒpTúŸ–¥@C´w,ÎÓ±|U4òM1JŦ|‡*ž,žPÃȸë#PÁLÁnH.€–.ëËcŸw‡¡Ÿ}_%nœÚ÷ð]k¡„gøkÏ]-Òöp!—÷J¿<$Àå ”%\¬P*0¤ Yx¤J¸w„Lãdfjtifh÷òî¨å}?˜Sr¹†–`ìa/¿YÁ`Ú-ýüFæ·—läe¡uš ¼É¿ŽS·(t\[oõ÷ ÁLivš¡7ixñ®Ææ'ÁÁ­Ó‚×8oålY÷K$ˆë6sr/¤Bɧ*p]˜uÞýÙ 5̦!Aà љzÃW0=٠݇ô½ÔažU£.d÷aÁiv8fœ³ÉŠ‚Âr½':bIâËf‹*µ«;*N³ó> 99¤è.ÙØ ´_ŸLþÖ7hý·uДx^C ïá|àÂvï ŒIö —ÿ*7!ˆMPhrG4×h£4;[i tK»"¤$`ŒŸ2Xê Æ‡8>(Ì®K)£ý¬àÆiúºèoÙE²CiÞ€¡V5”E^ ðâ¦ÁÀR)ýËyqM’ô²Á-¨¡ŽD[Ð-¯R…IÒ‚¡DÀ‡r ÃÚžg‡è½9ê29º/´. èå/ø÷u~\Öø¸">|@¦Ó­^~•_î–—ïóËýò²8Þ“üë¸×‡:¥«I/¯¨O/÷Wè´¸q 3éóú¹ô±h$#Ä/JÃsOG§áóåf:¯ò»_sCÜJ«‡0t$n]Ãíãz¿ö3¨yÓcÒ:¿¼êñƒ´ätRÒ€ê0åÇ/×=šÇ” < œ½õäÈ˲h1ûużìJˆÜŸev½Ž|T\8üòbI1[j?tÖÛÎ×ÕìÔhá/’ÌþU¯Ó»Þ’ŽÊË2æ‹ÅÇMdqêÆýýi›îV*¤lD+™xàÑê«Zw¯ÒêD_‘ÊB.Óà¦éŽ/™$¦æ²§Æ§åee”¦l|S±‰HÁFX]¬aÀÇk®!~ç_D¯ˆŽÅ@0H’÷hã,@/®§àÝÖ â®aW™[9$UFC)Ô\‹¥.‚xÒ>šÃFÅO ˆ•wo$7P£’…ë®Aȸ†Ì&àš@HŠOD3È-)("up îôŽU'·ã?™Tñ×heÀÚ)= ÷ƒØ÷Yíƒ Ý+Œ‚f ?"ùˆh­8M¶HÏ,šO\NÐÂïÒ³@ Œî¯{ó© ˜…†SŠd8#ƒ­‘IF9pO^÷`9ÙÐ/q} e{V§N¨â„¤žÅßlâÓßÒF6‚6à K¨ÞGþœUô­åç$ͼôö€‰ò¨€Iï“æ%̯OR©¾˜U¬C"Ä0IƒfM:1«˜®E€;ð2©Ëc÷—xT©#ÈH¹¹qE‹ÈI%ÂMDÕxŒŒ Ô¸dÄF$3J´­µyZü–Çò¯¿Åpø¼Lå^IQ3×L’D»‘¦×©ÈÑÉÞ£‹þÁlaš–¾½¾IX6°ÑP‘8m¤by*ƒ$“t¥×¼¬07ŨÁCõbTôn•V ‹^ev×ÂÞ³‘;ïÚê)ùµÐΧTºÒ³OY2o§…}ŒøÙ~ËÒ•:šdÞyCˆ~ýÏ8ˆ©ÿ9œÂßnµ'b7I Œ•0ÆÔÜxfÄ6œ¦оõä7X|ÊE«€0;P;¦)„„6èiz]Tçã`”KÚ2±;$‘Šsþ¶†!2Bs4¢'hÓH„c(„•ttÕ¥ŠóJøsZð3Dà› ¶hN›YItÍfxCÃèbÛjsY†Ä$!¶ˆð$}yásóyO¿á®›Â'GÑ…âf É‹Õ$Á‡II.’’|$ún|•ä\͸ˆiPŠ1DÄN^Ô\PZšrÈ2å8l‡¡(ŽhÆÄd¢ +°á\‡@B3<Íö·Œ°æâ¬š™’ÔOiÝb€ÞXëÒýpqmHçÇ“ÆÃÚÞvNƒ%Î(–N¹ÿ-¢„}ýÜ?þD;.­W¯Ç+ÇpžYý‰Iö](›÷WsÑMGž¾Üfx¨<ô9ãLÎÄ)Pâgd j8kšä3ÉWÉç”8ú?U^–líu/ùH2u,¿,}H¦¸Lÿp&Wµ)AU1+'¨ˆeœÆ]HÑp¿ÅEVökˆ@D# @ÎÊÌâ!C¡ÜDà{ñu ¦øH<·‚Hü­óC€”1>¯|‰"V“¼¤§/dˆÏî^ÜáJϹ‘|ì0f«}Ø‚[õÁ ?Ýið¯FwJÊÔ`‡ÝÚØÒZ2h´[™lߨËÈrmÔëöU€Á8¦x¦1@ØÇíçW¨"B‡”wI6Ë‚QL;®[cÉPߢº­ƒFäÒ8h¡}¥Ä|j&ÎJhZ  “?­tVÓ­jbéz«ÐØXA6 ‰KЈ ÒÆÝUÿñV@#Vhðb™eÇ 3í'ˆr÷Ï93Bq7jÐ9I…6^Igk]ŸÆI¸¯q ˆ’ÓV3¹ª”mP®tp’0œSô{KT”„|Ì’a„¯B- ¡9—¾LŽ*àB«.ªˆœŒQÛŒ ÅTƒbÖÖè§Ž—¡]%Ž)ÎCI[öÆÇAª—„Ð Qyí¿¥»ŒCN»º˜Øõb•÷½©¦¾Pð†‚Š¹çýH¹:!êGÊÁ3ÚåWM¢œ¶;(–'h©•ÔÞ•da&Ybiɽ«è¹X‰G¦Ñ¤öÈ4f€âdÄ  6N&„Dqä©r(v„kåS/¼PJö¯2¨É¶dÓB@Àç©6¯]p•tâ“)Ç<žZZ>01uê$‰N2½B®|¸æRÅæ©6Tìú·“ [R±Ë,±$ÁÀ"¢!¹.šøàÖæãç“ ê˜s!õ_7éåà0¬%àgUiãϭЄõ:uEó  "¢&º{Y´mÖ]™Ú»¢dÌY®ë©k‡’Š@¸¤F_ÆL‘fÑâfs#ñû+Ek¬7'ñzºœ &x B¬™kÓ“óv¹«Ç‰j\Uލ…|h¢P²3_„eŒ9÷ë]ܦüõÄç mq¹þ¯@˜¾¯SÜ2œžM/k®Â5)Ù)QŽDçØ—ž½F¶ÕIï’n =ÐÏWØ“A¢3¤#zÆfÞó~Èç_bÞŠä{`‹ëØ|ÉdÇ¥’Éß:LÈPwŒ>øáÊó“…êãSØ 'Ô1AcQ®[ïY!¬æ$NœÆÌ©:TH­hY@U&2W Ü뇣Î6ûæŸíŸRo,-Ys0u戕;·8öt¶(žî:þ\žTTŽÎcüDZ>vÐæúèÆ¶–›Ô,‰7K9ôL[ç Š#­J:$¨‰ÒŽó4×$.¨N£ ˆÀ$ŸXEâ»{–Œ¬¥‰*•±¨:p©öÂÓd{Jû6XkM›Zšæoæ ¯ìÍ·Ä#ýë"Ü™>Yâ&n'EÚG=¹épÌÐZãƒv³¢zÃHÊš‹­ëIžµ:÷ý»j1©t–’.ÃG“ˆŠhñÑÃÉéV@éÁ-K4Óã¾bE×±Ñ:G7Øv¾X|Û' }:^Wg¨ä¨g²‰;#éˆotÛGS‚Kn?±’ÅY/Hûå°fÒ¨Ôò‚é.‘±?bUê„17!UyF΃£iO›ƒÞ~¦0†§Œ ,ÔÒ„ »¡6a‹¶mƒnñ ð®ªðäš/n|Ul(9î çXšÍ¤>»66]T ¬šK4u£.˜(bWûB3‘yî*÷.-m{w‚;“®ô3ý~n4UòØä^åºU¸t”×ûã¹`}…Å›/&Ûˆ0^™?¯|¦ò±ðƒ;À =-èáMQUþ*ˆu Ó ÎǬ\Á+ªÜöR¡€Ç…BŠN%.nDŒnZ‚jí(vªkYW ˆ¾ŽËdÔµ/‰«ÓL{`ëÑ=²=¦ )QÈ…šsõ‘eu²žT'°¦aW’ìÌ.V§´£,Õ¥à£7åc“[ï83]àíNê\ÚÄ8…zNpë‚ ÊnEJŽ!¥®Gé5…ЫoÆy;Saô^ÐOO{ÁvjŸHkô’ qVŠy4½Âcü)‚$e]Ó(Y Ë«d.%Þåñz£à?ÚÛùaçíB@hæoØ!»14Ðda+ô³xiÿáÓݧß/Þ¿»>ÞÙýyÁvvŸàãᳯá§ß,þ´óèéâ‡[^æ—”ZãÍ}=hnôû)£VmÓM{ŠܬGÅñþ=¸·ÑÃÿ½Ú°"'üÿ÷93Yѳ–ýIÍ'ÿ(À“€Ø\¿H…`:Òª}éæj>’6Ø¢šOH¾'’\Nk:E`ߦ08D,¹®¹¤ûûJÑÑÑ÷|MÊb×Å9x¨UÎL ´Ônæä¯ ½Pñz°ýrÊò ¸¢rŸSúä¯ob’%&‰/íÛt™ÑÖKÙ”’`A†ÿw+F‰Ç›¨\ñÚáU|¤;PG¹–Äy™T—âÓX<â¯CÒ «.¾\åKLóKr ð:vr‚Üy#u%…)A©‰×ÆÎzD«ª–t±ª\—ê^0;O+”È¥TpSÝМ֭œôÆ$×øòì:WÑøÖ{q–¿ø_Í¿Ûð1N<Þ+W¹ùñ¥{·ì¸làao/ ?–1/zò±ïÞ˽lXŸ(™^ˆìÞs=I¢+éý¼WÓUZGiÕ ÃŸ¾ êk0—DOÆŠðÒÛ—˜íVº1êo²öù ªÕBÙv›µ­Ü Qs¨þ:O|OP´Ë޼¢·móŽtEƒløÕÌl²Ó¹–QÈ®z-Ë;{2#Ã݉~앬uïdž%½Rt&™Í•Pͽ«I6ÝC’vþFas±endstream endobj 64 0 obj 4486 endobj 68 0 obj <> stream xœ½\isÇ‘ÝÏXýˆ ÅFìÌšÓì:»ÊßHJ–¸!ɔ۫°6 @‚´p8(qýfÖ™U=P¤­09¬î®3óåË£ûíjÄjÄÿÒßÇç˜V§×ãê+øÿéÁÛnX¥¿ŽÏWá&% eð£«Ã—ñi±šäÊ:=¹:çè\ â Ð?qÀtEá§›áÏ uC{ÉË®ãí³IõNB˜*|Ýr ;k¡$AÍ> |33Ä” Þœ²7$^aÞÈÌ‚ÎëVQ•Vƒ—¢ãራzo| '|Vþx_­K–œ|öUhÞQ)ÁÿJ]~QçþÒøMm|ZׯJã£òë‡z¹ŠÊ?jã3úLn<,_#‚¬_SÁ¡Ä#Í'.§ÜyÖCîu·»HÙ©ãa±ð™£Ï³bÂA,°¹D•¯Ë¡Ué$bTµè¦ ÷âw5ß!GíΛºš7ܶ²fúŒ³â÷ƒlå*Ô¼Ï=pJÚ2œ ¥šP‹ºŒ_› ë;ªXËã[Œ~ŸsœÎzÙYræ° (®u½âVb$âdÓ(n0“§Õ¸¡âE ÚR0@}j÷ºc]w¤Úo¸þ/7Œ„_qÒv^gòrwOçU4öÍ™ìIq.šq nÙÉ–ê …®™³ø—*/d¨ÝÃ-Ƽ(\ª?èd©wAýQöÿÊéÎÕ†‰™¼àăõ"ß×)½Úýø»=Ö—ˆëåÔžN9›7îf xY`¿ ƒü3>#¥´‹0A%BPñ²D Ž@ì±ÃPåÿ ×+Ñ9ä“E ÙŽÐ…š¼¥Í•4V"L¾µ“Õ”„ra$%šU6ÐÙÚS%§ïÈð¯sÄ•ÐÐË@eKod ±7©tî-ò î]âÂVºž×–A°ýyíù,·ã„Á—0°§Op{§É{±þÓMvB‘ï6°ã£€A¾ÂËÂk·þ·ƒnv“ì.è–ö$ŸÑðü’69éJ* ÍŽ…Iå~ëàÒ‘Ó‚ )ìeœ âò•Bóöh#ËoÃÞF# Z;÷?톡óiÂØ©u6¯GN"ŸÕ$\þ‰­qÓ½Ñô:²¡ƒç‘Éqã-eÖzâ6´ØóYõ‘NÛ­M´£.>ÕD…ô2î8"+•Ìò<;ÚV@pàçç3õ[”ei§‰ÕÒ÷Ií·^?I¢£ ñcîàÇú`Lx›öyXT>,±Ypîq “R̦Tï&5glA ¥qG=gã1Ú¬Ž½Gb\.p* ¨$,]ðe˜P|6¥‘º(‹:²¹ÔŠ÷“i¼) ¼KyïÚ¸`,f‡ÛÓnVéÿ¸ÙÍ2Dù u¯4•gÉÊIû£ Ì9\&¯œ4á€ioÁ6/]+2ÏW­¤–Í¥§Ý@EØÜ™Ö¾ŒèÚe|!"vXïœÉ üO¤5½Îª«ÌTÁÏÊ€Be1JLe"Väý@M?+QO!,I7l4…"Ö)«Q>0ø˜%8rÔO!ÁMõ=fÒ&o°g©-bNÜš–ç¥B£6*o BÐe•”`ü*Òóö‚çÙd-ü#À¤H+‰íÜRÀ€Y)FƘ.ša¡ÃC´µÚ€47I KLtE7…!A9:1δ¾Û(7³@îÃåû"Ç…òük•52o¢0\”ÀØ$vk ±È ϳ‹“ù®Kªž}"É#t¢Kä㨥$'I@è¿.¨MúHQ> çù,.d2tR¬^ùQ“¨O–€¼Ô²ö×I'¥UªÉÈú£¦l'[]ëÆ @˜GJ ,NÜÒþË,’‚ÄÍi­r#ꨚÖ. ;BúïFw[²Œp bèbZ4`Nì—΢Qe]Pè£j0ˆ°P¦ÜÑ20Ø8ÙZí$Q2dKPä¦)<†umšÄ¢®å^ËÓ¾pµ*â3:©Ö 1‡ÄX˜Ú¬GÐ  ‹NÌ‘·È‰$ëAD²RÅçUb =j­@Äm Ž~È$ 3GŸ$Ô4yB*jŠ ìA@ p‚ù*³[¢b¤jMGÕ{d|õW’'zì¾µ C®àõŒ‰ ç .Ðå0œ.$ÃÆ$•˜5Ï;zJ”™¿4)·· ma†âÞZ‘4îõ"Ïa$À«߬ÿºB„Üî£àaGoû¯ð÷·0?`‘ZoX H¦Õ?ÄqG?þQé2›–¶c˜Çzܯº#…j¬Ìò‘ì@ÙÔ1îÙ—‡ß¼])*Æì½[ç¡ï•ôh5–m=~zððé·«›«Ûÿ¶¿Æ??{=ýbõo_>]}¿XÎÕ†Ir9jƒ†a`¤%]Ȱ¾jµ£•£aNüuQæBÞ‡nKˆ¨Ÿ$²ʶ‰—¹¶“àMMÁè€ 3õ*ŒOYÂe#çþbÆ,Ìö½Ü–ƒzj8†‰‰Wcp3[ÿ¼rÞ[†­5a ?¢G°DK50S±ð³z½>ÄÒ%%Ï„z¨‚®‚f]F7ÞŽhÝäúŸÑ¡Ð~"˜[ǾÁ ©À¾ç^Ýs–nv&<1oŒï ˆ^öÎh\G¹a¯YI àh!¾”†±±¬Šñ©$£xöÒ)â2KÀì4%ÖItf…Ü]sÒe6xq«üU& $:u\x àv?oöCâl(ôÏ—”·ÕZ>^ˆ6¿Î‚ă°ÇEXûÐx‘i[*°˜þaí> q]Zô%­*3~: 25x‹ÃÀ„"ÐÍB…^k‹·¨ÑC)i¨ê—pU+1Xc{d`ïÖì²ARÂIÛO¿5@Dû­y]YSÖ\îײ! û$ø3–‰‘pž~Á¦˜€PzœÐVt6%ž^bru€|†G‚=¬#U­Àïà~Ô[.qÞ*ÐBžÁW]¬ÊGæR¡ãå÷ÉÂü.'#n˜*<ëÚI3p°;³þ*E,"4¾‚ÂÞ‰&þé4å5¡ÅMú?ż0˜WËä•m±Õ¨î†ÖÒÉA„¢ë&ê Ðñhb·1œ mˆ„~WèìeÃÁJlkg Sz°ÐrÙVJme­uJ!®twÕ+t:I±$bN‰*E3ö ½¡ü›dI‘æ³_^›à#¸Š;h£tc oMž¥N€W é£Zœ¶ÂÞNbš‹M ÅÓNôF ÓžXBaC|˛̭œÀݰ‹¬7sÙd?q÷ZíhÒ;Ù~¼M)!¦ŠPßQÉêôCßœ ¡¥¥7gd|gøý´þi“‹Q$Ñ•Gúê“+¯t”Å'ñÓ££¤1Ö0rU'NÄ·yP$™N*¸óï+îü Ü""¸]V!EÀ¤)áZa¨0Tå(>¼\tÆæ©zšÔì„û͎䨑û³bÁ¯Ý}[™R«)±ÒaG¬2=æ:¨£|““-žÇÖ»}Žåæ8ª’ÁÝgçFð=ZŒGf9&Ì9CédÉ‚쨃0ŠÆÞ ãmcfw^AíˆYÿ ú„i‚°q‡B’×—âäŠ(³í‚§fï²á{s1‚¥}ªÿIÂ^X¤À19c²T([„ †‰°(¡Š±q#]Dª ð³Þ¥¶ZÄ–“ äy½àœz6龯Ìò3Æ@EcûÓëÚeïã<87¡Sи%‘ƒz”õ,p ©nŽ´çP¥â+FJœ‰„Ðø· èdò“¢ 0jc–ùIÚf–rŸTVQvÂÜÅ‹gâý=ÛÈ»4gã/ÑpFèùÓèx¯=Äãº{¤19²hÖñá™ÃË@ê<–VA¹ e†1-Ô_%£m,¼˜UùÕ˜×9*ªÜîâ|;*§²EgwQr&=-Ìvá«V~ÂTïb‘^¤• ‹J IPëg"ˆäÄF ;ExGœö³«\šäB è·Y^ºu#q ¯ê (C£­¤¿Ñ½:çí¶!G¤gHÞæ²â–µ|åIEü7Å:!ßšsS´FDp!ñ$þ„»ûÊRø°Û›m2hÁþÔP!F{;Þ~ÈZ™Uy^ñ0SåÌð›<ÑVã{ÝÊQ2SˆBFC>†"³†üû— ˜Ó\úÚ­Ö÷*U9þÞ4WÙ+ß²l´*pï«KÜÇû»(ó,0˜õA¶ñ[*È!~*G^¦ïÁ‘Ά÷÷»+ÄÐìFÀV§.”T´uDq÷¶!Û—- k\Ãdvb’›n¬Aˆ,ç`BÌ(`åhQk°¿Ë`¦  ‘ƒ?TRù‡Hæ¤w¢)KëM‚9u%=3‹fŒChHò”á>òíɪ1ÄJ4ôQºk^¶£öxƒ-V¦#ƒ˜°MÈêíÞ6éïba8-rHdýAVȹ…k‹€2Åö‚áxœê‘ˆ)®Ã‹R¥‚dR±5¶·5 aÐ’“&UÀ|@¿°:þAYF8 ŠÞ³RÐå4ŒQa1Mí§L˯Á0CÎ5`a!õÝ~/OÝÅÊÇO>u‡ÃÒ™wZD+w P_¶±þ¿rúå ߤ\¼åøi¸¢<ƒ™€ ¬ð&õƒÀÓý+$&šmVU@M¿Ò¦ßZh¡–Û…€`<ŹfêlŽbäC*ï­L ¥§ î@ªwëÿÌ.ì$ù-¼’p? Ò]} žïçÒ–<’¦¦#cÝŽ|X;8¤£PÜ,Òˆ’Ô‰Dzƒï ö5"l„ž!2Gm5h Ì Bz›Ø—Ò,5ãKv¾1ps§bé}ËlœòEnÔ•åuž(¯ôÐåBhóN$Lš½¿I‡ÐlK£ú×üsyõB^‡7vqÞÝ{Í;DÑ­m=L3s"¿‘ÕØå(Å$€¤JF$먭þȼc”-1N¼y°KSqœ„«òÄ´* I\éÇ¥RÅyx{+D/Š;3+—šåÙõÂ@\k&ÞLÒ2JÉ^ ¦©UÏr³2Q•z|ÜÑQ¾¥ö1VMI.S–ùôó–ϼ§øJML´3u¬q€iáeœ5÷ñqY*b$'ú_gª¢ÙO5û\Ÿûøæe­­õc8—ÃÓ¹f¹TQ0•~¤D ÷Tà7ïÈШôs»ƒBá l÷8Íýi7J;Õrù;¸½÷z"¦JÄú‚ °2oÖt±«w&„±ÎÍägá}ˆ8qv¶j†¤,&èb¢˜kcBö%¯œ•Î ¹Ã«kó×gf$IÔ‚f€ÝVåKƒ—Ñ-Ÿ`ýrfíä Œk ùeëº;ÄÇV‰J¨“ž†¨^Æ£CÏa·^tùK£C÷ [ñsE­BÖV;F…‹ÐŸ‹ê',•Ê,Mo:hǼë%µ oì-éò.‹TñmãN•gÙ‘&†[u•«[MÏKmÔ´‹¸O¬6ÌPÛÊ=?À€µ *´G¶/â¶Ðž€Žùƒ¥½°û³=pÙ±6ª‰zG‹$àØKmY]'«bégü"]V9XjB$ª-Î˧»·ä§±'9h†½‚c"•_tLiBHy©R>_Ç×®‹ó²ü²z¦#œ„4u@ÈèT>ÏÚ”¶u)uYñø/DŠßTÍ#Ië™ä‚(‰Pr¾+ƒ"Ž-ÁúHº…︢nõFÝ,1YJ‘8+°'»â*5„ê£/‚aÏq&ϯÌý ¼LÎRïÐõ¨1–|RáŽJO's 5-Í߸=¶"§þ ïð“Ró[NµšØ0â2kë’5ÁçÙñîhhý±vн²Ë›’†Øù'Ègëæ¯¨q%gó:§œ3oH Sç4¯¡o˜]†LòÎ/ÐÍ’o´¬•þ–‡ÍØ=HñžzÑ›É(__3¬ÏìI葘ï·Å‚ ôA ÿ4&5s²»QeîZúüW’už ›Fâ"•ûæï(åÚ’ôÛR„·û´GýaúV‹£Abº ÍlÈ·f¯î’ÈêÞi¡ÜµˆjŒNM)¢ú™ðø"l³ÓD¢w}5ß-Ô¶=,áÝ/ÄМùÒëžøâq‰0ì¨þLŸÁéJ˜7'~²Bh¾Èˆä kJ<#ˇÚ/§ì~ôX›bÎMcdÀržS*ç[JÌÅTßr­’ž#[óGŒ› ’ Ý8 ùä{+Ĺo+¸g¹<2*·TŒîÛ;ª¯‡"ܦ‰er4‹È"¦g@¶¶‡wRœÊ’Ò ÑI 4ŸjÑ‚+…úÏöý{ñ„mØ\ä#mô0•8¤R¾?øY‰tÑendstream endobj 69 0 obj 5771 endobj 73 0 obj <> stream xœÕÙr\Åõ]á#ô@Ê3)Ïõí½Û©")I!X©‚TÐfÉekÁ’çësN¯§—;É@\ŒF}»OwŸ}»ú~žØþŒÿâÏ㋽'_™ý³›½yÿøÿlïû=æ'ìÇÇû8€IŒÃÈäfÇö^ì…Õlßð}må.ö¾YéµúçÁ_`¶`t6|rœÀ¤?®7b2Æ9¶útÍ&ç¬t«Ö|õåzÃ&)•᫃2çã0*¤]}£À®øZ­&çÌNœSˆ0ež¬ãNJºò£µ›#PË™\ýYøO¬¾€?AÀfâàOke´‰sœŒ®|¶Þ(Ê £þŠ8çZ¯žÀÙâJ€'˜£{öð ³tBði÷™œ„Ôѹ‰øÜ. s. •¯ù49KÀŒ˜fÆ8âi?Íû¬­˜|uŠ5œôf=Opçôê+É¥Z½Ì‹/×{r ÎÇòI;2ñ¼<>…ÇFLB­>Ã+èYÌ&šG~¦pN®Þ y”ÜšÕ!L`ÆÎéè;ü΄”2ܼæ;<ôÙÞÁï¾I(d³À“ ¥Sx)œ0ÑÀO4ÐJ%;˜JDèYÓ @ÉÙÄg·z ·r ¸TürTö„Óm„Ì®ó¯Òq¼‹”óÄâà*e4OÇÅÝ®`þÛ)lã”\à=ä$5ĤâÚߎKÀ”:8¦%ò£tÑc„©4ÀÀJÂÍÓ …¡7"GÊÎ(8<¼,L|Î8³€Ë2;ÝI8Š#²r¹¼ Ž­‘9@¨,é•rçC(Ÿ«ÙEœÌ,bL#‰ËÓë"áñœ†Ryµ“htŒ¸Ó°\§%xò¸„k›—(ˆ’ \Âd8Ùô¼@À9·8ÇL³sñþ¸a9-Þ~“®¿a~Î<`¡EÞüØß—¦ÌT|[Ñ%M<ÍOP#°«‹ dàáàš3<¸Ÿ(X=H 8€SªŸö'*Cˆ€ÈËÖHò`BvÀ­Tß^–<ÏædÄ??ëÁgK%Åëàô]tzLk£=)@íƒ Iœ©A?q)¨ë µbæÀÓx” Ù¤­l$¨tÔånáÎjþîÁgÜYZàã~œúÑi†›ÜÆß…?’ÿÆó@Œ `Cø@ ŽÛf^ Z4¿dÖßßgG’XíOOeðu|YoÒ ˜œyç‰Õ‹øñ,àöÂo`Á i N'ëN§ÁÇið:¾)ƒWypx×òøm¼]¸ë1Í“u Hºsâ×|‘¯‰Å™ ð/{Í! zÍÖ¨oƼ?–ñ¿ƒ»ö9§ÖÌà³ò`W™FýTTJ-ÓIå.Zåp´¨(ó2Xf~¸` úÞäÁÃÑà»2ø4þ0ZóS<ºè DCÐT³¡§§ËÛHχ(ﻵdö÷ã  ù)RÐÆ­7TŠ×EKO-8±^ÙÌÕ¡'qOãé⺨ŠPáhmÿâŸ~Çp,@E˜¢f 8£F;,Š· ñ!yð}ùêƒöpFP5YvÂë¾Þ¢ñBÊ`ðõ]íCïÂ]{þâ g&'QêÈÉ ŸøŠê, !EÀƒfª7$öÀdH{{$ÈàIY˜uëeˆ- n^’˜)N øÚ÷€;¯ÈÜ«B§atD°ÿ]»kh·oÌÖP£>~Ê^Çu‰†"Ž•´Môìs2þE‚;¢¹áh„vÉ>pí5¸CÌFÂË¡Ê× Õ$´‹û…ÈÎçÍ^ö\yç 7v¨¯Â º/¶ñ©âиRå†x˜‰b‘`­Ù>Ø0q EPtUïu¤É€Ó`“4ååh,ó1}åG ä3~uV¥M£V³9„H»èF"þX4Íyñi¨Œ¤à™ Ä\sÚY‰ÂàD N fÐh"¢Œ.º¬>)°+Ù8‹r÷ Š¥(ì8V@n˜Øb‡ˆ™»LÌÔ)ÙŠ=ºm%*õ=ûô„¿è9D y®¥Ïâ•“ÿ\LŽ>\ô‹œ¾+œ’OlV£˜øµ3Š!ñÆ•õœQç½ÛA*}Í$"Œ„ÞK¨³ë¼pï:ŒÊò¤Õ‚HÔ÷¬lÚ´F0°x•ÒMúœƒØˆ½Oá<ùwFÌu-t9Á¾ó1¢­Ð` M4ÿó¤säj¼·²˜$[*@#Þ˜„ns×–[¼§§iPTG©©šZ¹¼!ñΜàcG8+²ÅRêÈ“¨¬º¿|mÖÇæY·•¦¯|à—7¶¯oÔÖ9?ЧúäЃŽüÑÇGdÞ«ˆÛ­ÂûÃM”¼§€D v¿œ&j¸N*vUþÿ”säÅæ  ·ð$$6ÁçKü|……èã”(4ãÐv”àWކá"š\`(ô$®j޸˵}O֯º®…‰¨Y6e(,c œ‹å?R•aë¾€ÄÔrÕ¡^=[¸¾ÌNuy¡)ƒ&Nn(B)–0øYY3Õgí*FÇR_{Z*bÅoW£Ý ôËq¾Y¿yƒ…LÄè ã7ÁRvI‰qv óM bó¿Âí–£ ­Cˆ? E®?¤ü3š&«¬ ÌýÀÛ·&bAçž­Œ¡'‘áÛM9}Üöóä. _ (áe9ú™ÕM8)OI?ÊËs£ 2´Áb¥‘9ŽRëµÚ\ìW¹•«À¤.H FëVpJP|w¡+í°±˜BnjcGåI×Ï"ÕB¡¿ˆ@ÉÌŒŠÈmÎ%ö´ü°Vr‚ç¶}§j9*Ò1x4´”O,€7¥wi=åªTÉR¸ângŸ¥§‡_íZEâs_ç'/êä–Vš;Œí*²®jªÁk5¤”šZ…I^ðe,ác¢œõìŽWUIšîŒiRQ¯|%ÕŠRHW´`Xh_æÃ¶M“äoаLOηdN.™æî]SŒrc6 ˆ¢PŽÊ†‹µÍüÂNÂníMó`7®kZµÉF+ùç‚ÔÝ/îx½$hN~JÊÞ¬>Zû¬𑨑Rå0= ùGh3 î~–NòŠè?\5¨ŽVêO/§Bµð½½@…,Ÿbó=ÅÑ›r ežP”äEXš,Ö±S`X5(Õ?!©î¯ÙºÈK”)a«â²pÿÎC¬¾+®àbÙÌ·6e§Å4ªÆ@Ø6ÆFù‹„«…êj¬Qzü,5ŽŠ•©é+’¼cŠQzÞ÷-óW“ÓÞ–ÃZ¡Vï¦0îûÛËPA­Ýîh mu w>rTò›žÊódcLumÑ¿â¼ðJr_wó}}\´ç»U‡ð&‹ƒ”Û_àŒÉÜ ð<ÌX¸b]=µzEvÇ6)`xêŸÃ2rÕµLU¦oº²ŽF¢— ñÒ» ½9½×Ù»oq×,R¶ö#ZªØG©‘ÃÓ¸bƒ÷–*ÏM”3s_1þ@Àli‡ô>¡0©ÓŠX%R*5MÖfo¹Ê7Ög¶Ì¨ÏäÀ3«‹mY/õÖÌÂk°‡…?!D~Ÿð+d*£n[õ÷’á ›xf´íó<7rP«·ØƒDÎ$Üé_gÇ–y.\êuI¥¾Q5;_}øšÀî%»¤àã Õ ¬Úò~À,|©ŸH"¹IíU^Mx»d[ €(Žs íàÍ-¹8}ŒÕ½¥+¦ô+^ÑЃ¶1’~ÿ´5Øxƒ:.N”|ßÖþ†‚\³»>2þÀ„è\VkïdW«KÿÞ|ÅA[cØ‹|ù ÿ^_»F-4”¢ZÞ¥2þí»ÖaM e"'F·–ቷãQ£i㓽ŠˆÛ…÷¨”„?£À<ª%ç ±ˆ¹Ú%±IX$Ö$ð›æf5(dgáÈíe¢íJv# 3ð%›¦éaCY¢/Þ|°÷7ø÷n~ÿØendstream endobj 74 0 obj 4179 endobj 78 0 obj <> stream xœÍ[Ys·~gô#ø’ònJ;Ü€ßl'’•Ø‘c3Ƀr­–⋇xXV~}ºqucCŠ’ª’r™ÚÅÙhôñu7öÍþ8ˆýÿËÿîÎöž|ïö¯÷ÆýgðÿñÞ›=ìçvgû_À % ecûG{i¶Øwrßz=¹p¶÷ãJ®ÍjXËÁ9§V*~Ù89úÕ7ë\=_oÄà}fõ×µ\ýe½Qƒ”ÒÚÜÄèbÏ3è‘vN¯¾Ã­“«ï×JBذzA3Ÿ­Õà„Wº7#®n¼[}‹| =Ö*£V?Àpm­ÄêŸk ô_hñ^­p5çB«¯qc?Œ£X=Å…³n>ÔK¡qQ„i8 @”ýëàÏÀ8à cœ¶r°ÀºƒC`—[›4F{>f“mÔç !=…eWGøçÿ\០`ôCjõ¿¿Æ?qàK$Î V×øuÀ?‡uÈkœ†Q˜Õ®.{šWäóNë~Cí€É¶ôÞÆîÔûio‡Ojã·4ò°£‘RÚâõ_ׯj<ªŽ]m$’ŽÊy4ÛýÍ9+Èmé@‚«ßìüáÇÊM#ǸÀe=òu¼ÊÝÄÉwøç1üÁ•q¹º¦Ïÿ®‰ú¨ÿ²6^fŽºÒHv¡¿Ý}¡—½5?¯Ÿv½9ÔxÕ[·õÓ9ukN¨ññ/NI1¨ª•G=ÎÝ4Â@ýh)œnˆècÞI+Ûldð`/ö7B ÆŽ2m÷¤Þ`¼ß-g‚B–f¹ˆ_ÍãtH&ꦎ¹nå"®åêŸ!ÏË„õ,ÓFB'*ÆFšÁ'ÚЈ¾.öümœÛª£¬9E99'#xÿl&l £0(ãá –5žÐèm ëxp!N>Ç)nжì嬌gH¹µÞÙ¸¬vqY6èZ~)• MsÚØ)䑆}¥Òe-guä™–ƒqŠd$–½\¢â–zhø%56ýé``P*ÿN'Œl ¬½Œ¡Çiÿ¼'îwjðæ^r{ïn{@;X-˜_Šbw¼áGÓƒR:$ޝ›¦mº*$Ò‚ƒeœÞ®®åL´˜Fâ]¡¥ÃuÁwçÓ£W¿[°š±¡RŽš­ 4ç3X9†ÌWœB“‘ž“5Xxƒä¤Sšf,noÁ? ›ÔAk¯d9ƒ´ž‹žÕ6q'ê­ Y7²P;W®ÀAW X:‡r~¨™\f<ÃPLçhz˜$u+›0¶ç›³£%1ÜδԆi¯Èä¬Î"1Âù‡$Kr ÷ÿŸ:‡fO5ÐjBð…ÏêÈmAYiøm…÷~%Læ&;É=N××™ƒäÓN°‚[°ÆHœw ãô°/¢·µñ¸¤„ÁçݶüiÕ#ïœÎômíÿ²ŸfÑÀMºîõïzä3ì~HZ7˜ ŠÔ`ZZÓ`eç·õÆ&1TüÊv;&fw#‰CZóªwš-—©y(ÑßéiíNýµñ qz×òºGÈu&–Û›ÔˆRYþ«Úø”F>¯ÔøCÓ_>¾hcžzAÒ¥»¡èw²•ɪvHÅôqqö5©oœ^#èYÚ© SГ÷¾I2W™k`´~éMWßRãŸÎDŠŸ#´âRt«+ïè /CùæØ!:)“6Á4zWÕ.ØwÝœ :åŒSùø‘¥Û‰Z>ì 99q¿²–0s×ML]ö$`×Spº¦×½= [`Ï[~íóÕY&â–¯Y8Ô’]#jcŠwûïfU3!öXÁͺiNº¼C™„¨ áÄ0¿mEç¤\yÍŽj>È"ÍåâEmüŒ³ ^Œn‰Ý¿õ,ã«æ„wYƒÃŽæÎ“\­¯M&ë!6ýœ‹Ù3$æâô®+ì:[@²àg7Pñl ²tdMŽÈ¾œutìÀ6Þ}2ãQÕÏŠM¨r®ª~‚°SÏU#sˆsµÀ¢;)í Y%03×Ï®U?kå-± ‹uhäYoͤÞï6Š1Ûöô²ˆm¾Òt£sõìA¤¢ U]‹xµÀÒ¹™lŽÇìmÁŸÓã—ƒ!'>¥˜%ˆ—äì֫§´ÈÏU†)³÷Œ~yïèBÖÏÜÙeØ$6tm±ÉR£Wó[˨ƒX~D,¿9}¼y.ŠÙM·¿¿h]y»"}k¬EñqÖw{Ÿ‹;oHaú3K +k±lGéó\+ã,M cŒ6«G”ì`!~“%Ü(a±Òë?#¿K*Ž¡¼/+Á2ˆ%üoãúHPh1tów§…1?läù‰]“UD×V3r,a–ØÕ o³´œ”ù!æ)?£Ê~,¹ó*tÏÆý‚hç#BN‰ó0É2…½”"w†¹ÄÅ0 ÛÔ+.)‘Ƴo5¯w¼P%–^ÆìZ“Þø=\÷ˆYG‘üé¶x樱k]V3ýó1×0îŒÎœ·UuL4IpÍÚÊH’s‰Îd£³›N5: ’=€¬ÁTV èh]5> ƒU´¥?jÒR¤~H¿ýH¿C*dz+0J`žeÄRV¨øHQ"-Ú–~%c˜¯á|@¦ƒu£C)S²àPàu!`Ôh%fÒ„‰¡£óƒƒý£_òÂ(|^0ÎHáu²ÞZ­RÌ B˼€£ÖÙ³,j,¡Wz¼à´o‹EÙ«ùûÄ8ŠŸÄêÄ´‹ÇdmPQ˜zõ* u…]%¤Í¿Ö¤u¸BÉþëÆæeûVrãÉôàý۵ħ$Y{'yÍœ¿? ‰ü±«ÅZÎ~øÛ¥@×{üÙµ—“£”„¬.fßèôˆ†±‰ÌÚ¯Ì(uê,%áoÑÍ‹¦"¨â%b]*5­–¼5¢[u{I¶Š1ØÁœ°lx]¶”_M(þ—`²Ötˆ²D[ÏCw¼a&³nQ?V#›+‘Á-ú¥Š" ŸÂ”ÖI7Fz‘¹€¢gŠHšP¯ÿQÏ;¦ÐeÝH_‹ Ð/"t¸O¿¥·±Š@”L|fSm¶þ;X;<:ð%ë6¿åµÁŸ}Š| B.ƒ†eÅ¢n&æ7uå\Cdp ½¢¾5³ºF=Í6AÂD¨¨ÓS†!€:_p+¤b'úøÄ¦=(CADpß+ÒuÔŒ);â ¤Š[â†]¨ÈåÇ‘êS+mævT¤Ä¹¶2ÎA8ËjâMk‘Ë7It^í-9‡zE³›ÌŠ“-9V͉æµr8Æç8&¢¯Ñaî/«¯ªšÕŸ•E'ZÂñ_ªO?ä±Å1#“A†PyqógÙRçJí£¦#w½@ß vÜ(äÔ)©DòTž•Êñ ŒŠ¼ï…J‹åÙ1‘Se}"§åªlãºvM"¾¤•Øóœ“Öǰ'Aì¡örík½ v°¥Ã{“&tŠäÙÿøye¼„¢ ¨®Ý¼ÐhFôkÆò½.µoùRYÜ(­á/YºÏ·$È*²qþÖÇD§ ßáÕœ÷¼_™Iã£$ÁA jR¾câ…uR¼ÉS”¥ u\Y…jŒ Y³ÚÀž .Š1„ñ<ˆÐO«JÒ¢k2aêšçá倯sä(‡š„x(F$_Ó´ñš˜6 lÚRçóaè÷zêM& eÉDsüÀå˜Fô×f°² Ñ$'Ëé¸ö5V’”û`\O ók-dl둘‰1ĺœŽ?cïJdÀ§h6ÇÖžÐùnA¤¶3~:¾^7¶ ;™¡ÂØÈN–rÇŒ}ÇѰ EòÐ0˜cLrÐõ ³µrU$"MË@S+Ñ=¯‡ùÃrú+üùxOÃÄ7´è_Òà¤I¨ÄµfŸ78&úÒÍÍ1uYÊⵚÅÆ¯WÿQi Ò F#ÓÕŸ¸€§Ÿ t±s*a2˜7A`åø­/¹œI{óòϹ"ï&ˆ9‡E€®T’£Ùs¶6ä™<ˆ›d cêS/*¦‘« Š‘âsó`Å(N½‡;ï ¥³dÙº·]‰e(Ž6Nç¬äÏë(}:sY~/¿ ÓQNºqÕ+é‚Qó,$È‹)ÓË+ß÷^“Š%‰-dçIˆÐXg!RÞp‘}!Ê:5 1 oòvüéÏE#¦g/eº ª/BëE–rÇXbž!3=®§Ô×Ì&ÝñÚu’,k°K‰;¶iËOÍÌN (…œØQcern‡Üæ$·ÃX;M²Å—ôYØ‹ÞOòúNk|Ç3lõ©k£` 8Ùƒo Û–`ϱPÕ˜Fuði¤²]Œ°›…™kŒè„yŒꪲÝËíÍTœoÅR*Š zû T§ÎGSŠÏoGSbŽL\ ©s¦•Ù˜uÐ<ÉÄX”L³°M £u?v^L¡4óÔðcZw)•J3½§Ø|¬úÖ‰­c·RlVv+Ÿòq)_¤LW÷w[½Z&-›Óň8²P´áKÊJƒ®ZÂb/-×ù%ÉE @XÝ­ÁÅ;<âñqÑ„™ÁIõ' ø­$Õâ©{ß(!÷3’Å“œa!ž:·qÓÒSfVž¤*¸¿WyÒTyŠ?T>H$ú­q&×u"ÀÅR›åªD/6”š6Ò*)åB“0ñÉOéOÚôôü Âÿq™ LYUF#ªQ~ gvyþnÝ ¤_µé7›Bx™~â#1´êÁÇNÝ(yAÛàÍÆ/„˜|]A„e+–iòáUc¢GüàªOúU’Õ€»Tò~ÃbýÛŽÚ'%Ârå/ldçcj¨,Œ7kÚß}kÃy¨²w¨N™½¸7Ñ7TÉ)ƒD{—eÞcúÓIøÄƒ7e}4QÝÔ4 ²‹.rJD#§½‘YïóÖFAØ hŠí,í0‡=Ö_¢X·$Ãw¿÷èþðŒ&1üËFòWüé`ïoðß"b“Vendstream endobj 79 0 obj 4071 endobj 83 0 obj <> stream xœµZYs·~gùGðM3.íhp©ÊƒäHŠ\*'‘˜ÊƒªpyG$Wæ!1úõéÆÙ˜ÁpIm•É%Ðh4úüØßwÇíŽø/þ>¸ØyñÁìž\oáÿ“ßw˜'Ø¿.v_íã02¸Ñ±Ý½ã°ší¾«­`rïbç×Îöêß{?µ`”š >8 öè§~%cœcÝ_{68g¥ë^ö¼û{¿bƒ”Êðn¯Ð¼£BÚîŒ `Ûñ^uŒsfÎ)G 븓’®|Ù»12µœÉîNYøOt¿ÀÎo‘±80xÓ#+£M¤qB0ºòc¿RÀ”F þ†œs­» [¹~‚9ºçœŸa–~AŸµöWQ¡+P†aν² mÜÀG›41šQwG½„=˜±Ý>ö+ÉÅ …ín@:k5gÝiC:Ô+9òAÙ÷+îGM·•ç=Çc‰òaÓ—¯á8lÝYš¸ ü4ì~ösNtÿIÓA-Z©tj×j‘ ¶&¹šñ F°Óe£ Qk£e<&2JÇ»gxéUrЃ‘¥«Ó¢F>—?ƒFŒnœ‚»¤=:¯<l`ðf«»uáFäȾǸÆÁ!¹×ã02)º/½ð„¬}œ/=z„û80| ©o°‰DF6X·â#±¹‚œßC›31(­ºkÔ·Ò i”€kÛÝ–U~»‘ÂÛÄZÀ^8àªD%|H¸%?ø¡ìÜÏ©dr H­Œæq5µJªZùã`”³AwÅ¥ï‚ö9c&9Ÿ1d>n¯TJ •¤²ÓeÓï†H‚B0(b»{ïwö~ü5U{)¡Ø3Õý«wžŽ'çÐcbo%L:Òø:¶^ùD6œš5šúÞyɪ+Á0 ×ÄÝ7QÄ[Q³¸+06´¬lŠ(MçŽZH=Hˆ ÈXꀭÒB‹WYVgŸº]Œ ©„ýá=€eÛ™cZýÑOÂ"¨mu¨´Jô’¾ µ l¯mŠYTGk‡ƒ¸LÑ ÙOsC¢&W’ÌbF6”ÿ\Æ’Ç(E©IfÁ²VX—º¤Q¾µ"…®‚ã!Eíámè…ÆZ‚ }꣨ãU¾î“¾²•Ú„¹;Â<ì§á×ëPx÷Q¥ÐE!÷(~!‹ß*€p6½d?T uU” •œ© ËA«ìÄÄs›¹c ʶ¦{OQÚ™ÈèK‘SÄ­›¡>‡q÷'a=¯êÞxqÀ;R&£Ž1Ë –+ì2–‚h¢hÍÛTˆ§‰ ˜WIÕ.’ÁÐq"”£ ¸¿E<¤¸®ƒ!eäIãBf.Âi ÛŽPrµ†][ •;™¤ëàQ´¤’ZKOåRg=ÏwgßMèYj L…¢HôËG–_,»2$%¥ÐO‚aŽˆ/…Õ¨¶f‹*ôÄt(8*À™‚^ZÂGØ~ 61t…¶>ø*bœTXX·TÂÄlGa+L$$²ök¢¬Ål” Õc Ú€¬·§Ž(ýbM´£7u-p„÷c»M,³MÇâ*¦SªA8ã1ÎCa36I3!~ 3Ó%¤ ÆÙGrñµ4UUQ¿ØC’bu•ž WÃô´» ¶ç¯±í ŠÑñcA´„ïh ÷磣¥§¶À¢“O|¬d“B=Gã‘…Ë "TYí ”ñi¤‰&¸•ÔC¬Ë§1_e×là‡ªI`Lr,)ëAFñNZŽZ·,í¬”U[õž»áí®q‚rаe÷ÐÊß|L`Èí4%UñrÙèz ]‡ßSÈa¿8)+Ip=GáF”“;Õosí^w¸ Ý«K°ÔK±­ÉãÕ®Á»ØÃ‚!Êm[£Ü»{ZT?<Ë"N¯x¼îrÃ3»¹ÁÞûga¼»¶]‹X‰†e‰|ñz É} e’æ … pxK”y±µ¾÷ª.{ík¨<ú-VŽÅžCP‰Iô4÷ƒ°‡×Ô´4Ò`ºDß ÏbɃjca]Šš¥Žã»bÉo IcS:ÞIî¯èïwD¦W}º--^ó  7ëéÓv°ž«4`ûâƒÝ…*u‚‡çˆ`…•µ# Æà°b4rÄ`Ð52îªÁo30|œÁ®u4.Ô Éb-ÀJ@MýèQ´óÍŠïp¥‡M¬³~ª}’ 2)°¤”7Š-&*§£›Üߢ÷–Ö­„ ^H5Åî}ý¨#Iýè爔¨ ø¥mæ‹ÒV¥–céÉrñæeõIÙWŒÆ0aá> r>…ÍÔgøã&S屋¼yù Ot™@пéðÐ/á68J|Â7q <$Þ­~wÄ¿‚ÀÔ;ü:õþ ÌÆÑ’Ã%ÑðíŒF_•A„PåáÙž¿ÊƒûÕ"±ï ÀäùM™¿¤G˜oÖ¢<ËŸ.Ë4~íÂYö‡ç#@²D¶*d‰ò8AØ4O~R++UFâ£HßIXù¤&²) ›h­«â(×™p¿v”[üÓÏ>Ç·™ëYKOÏóຠžS5ÇOeúS¼.ƒ…û·Æ©qŸ4¸nXá¦÷‡ ïö3ÃÝ>h #1æ>%ô¨h¤§½nö2ó)æºk ~ ëò /”¿õÔ²¹Òèû8“že£ý7}"Ô%…x“~®IŽ‹D[4X„8o+¦¡„óÖàEkc2éuË hü' /„2)1€(óc3£ç-Kµkë¡É0Åø;½W•HáµØ2Ò% 0=Xð¼6õ%MótâÇ"š%¢¥ÁèNG³;WU„¸øAÞã|’!JÅ(n‘ Îæ?ÝͪÍú3þ@+Ô•ªªû¤Rý2S\ª:^Çño.ƒÍŽJn^.ZÇ­9§gF•䬆Ð44%‘˜$•éªÄŸ›J>̃jŠªƒxŒ«¥?Ã/“.ñ먕¨Ÿ¢®÷E¬×™z(ƒoòà»2Xø~ÌŸžUþ²jW=bð·Yè›bÆý˜B“­K=ËŽEÒa¨Ûïg’ä,vÚ¯lŸ`É?[‰°ªœÁ‹ŒwÏìá‰ò"®[npUàUíZÑ‹nóàuµ<)£¹è;]o.Èé|OëÐÜi´¶7~Äû¾E'ÇTgÞ-4m¼|,/:šø^LܼJj!³‘A?Ƀ¥<úZ1?aÉó–Žo¨ºæ(©i—ºvlGÞ©žlCÞÍtv™~-ƒGìNÄ&Èy{Цœ·=;õ“ø:ͤ8è§\ ¼=¾ÕYŠÅÒy½/y‹d U€e˜xˆ·"½uâ6æ¼hQnÅÕˆ@3µrá59I‚*ßîߦàÔ›–7E=Ò—gn|6×%Qz±SeáÔW}Î4¹ûÍ`²äþfâ$º!]Ú\É¥e¹­â;E½ù.ↇEÊ£º¿´ýv›ùß•œÓy²( Íʨ.W%ß®ûif6|ù!è&e5é—‰ç©{rDÒÅ'Ú‰‹U)_Øù €Y}ªr_åø.Þ2ÄD‚Ùc]G}ÕEØ›“ê./,`ê®.2Ëòeò£š<¤!¿‡µ°^ôû?†Ÿ°ãmv¯÷vþÿþ.ï$Kendstream endobj 84 0 obj 3313 endobj 88 0 obj <> stream xœÅ[ÛvÅ}W~Bož!ÖdúÞµx0¾p °Ž€,ȃ‘d[D–„%ü|ªªoÕ3}dÉ$+x!{úR]½k×®>G¿îΓØñOúûðõÎ_ž¹Ý——;óî§ðÿË_wuØM¾Þýd”€–)ÌAìn^ìÄÑb×É]ëõ$äîæõ΃Í0rrΩÁÒ?öœ“œýðå¸'‡Ç㞘´ÖvøtT“^ÙáÁ(ñ¥RrØ÷ ¾fØ@Ëä¼z8€O°»sÖ¥'kÌ?6_€]°4³K[9Y°lsÖ„1õÑž÷ÙÓÒOÒïî©,!v>†õ†·øã à?§yb8ÃáñÇTº¼Á×mg|‹kî)=)œ{OºI”E‚¬SÂð{™â$ϧ€ÉŒSð6.ó*­@!!kÍÄ'eÆãd²^yš¢L.a“?/Gµ±î&2s€g7ü³7ü]iü½6žóá¹ñ¨4^æ'tQñP“±³Œ:DÓÑ´á4ý0à/ÜÄ‹âø‹ì–8ëEÙ÷OC9’³Æ³Ã}nC6ì¤4¾æ“å×§½m׉~îMtU/ØÁà1á_±í~íxVŸSG§ëxR;^²Ñ¹#\:¾àÇÌ™—½=ÌežÚ&z;–]qØäÏF<[ À3%šñQ+å)¯PæÇ«Úõºte»øi,Ï1├¼ßp'kX°¸©£þ+…QŒ ÑÄßšq²ë^,]ÖXªPSŒðl™-¯šá0¨é:v_¶ˆ8‘Ë >Í*dpës´b¦íœö ¨Ë3–xÓCbX1’Fr~ݬ”Ïûp…‚eDÈ[gh×Ag 8h5ÙÅ_¨pLt¼~)´.Z–8+Gû¶êe¥I#§3 ‹¯é¬,ˆ[&‚ë-îÛeå¬hY­ò>ŸJ|“ç˼«Sžd¢ê´hßšÙþ\áìq êÆK´Õ€ÉÞPeàÚc·ø¿Ë­7ùÍÌžú\5Gª·ošóIyÿy}¿)ûM\¬°—…Vé³üe±ý<§B–$ ðp‚âõ/w6ýÓëEñÙ[¾lbÆf8Ž9+P=ÍO5Ÿ²“¼*hþ¸´Ußn¼â?|ÄCeMDo·ðnzÂIó{‰ÙDï¡„;ºµü¨ÙýM ¡[ÈÆ×•0«lb|XW`Z¡B䢤]/œùq¿çÃeGL³ÍI®;žñÔÝÓY 4‰b½ïªwÞõ6[ïªt|ÎÚXÉ ^väÇMB‰ëCØãy9äó¶OfS£§Þç6WiÚµ`î¢ú´jø?.£5Ž{ûÀb aÕLu뀫ûw§€»W-{\(OßÔ×_sNÎ¥ñYo¢{õUAç€3¥m®g†õ ë{¥mÓ;ÈþF!î™=o{üqÞ ©ë^@&ÍY³ƒê뱃€{Q“„;Å[ÁYžÝ(òR [/ȺDþaAÒyN(·Ëü/ ~r*‹ Ù°P?j»¯bì¸Y-%õ÷VMÑŒš‚2Kõ³ÞÙÕSùùn!x·’»øµ&,ž­·„ öŽª'NäòhA°Î'–¦Ë‰2“¯ÿ&7ºVÅ{)¿+àD´•t-UNGÃ,EÑÉQNù³¦Q¡n‘a°ãü ! ñâLLvV€´c|o3 2p 9`±š„óèBy19í#½)-u€}ÈÉÀ“‰˜Š‚A^¹ônØ X´Y3>ÄM:/f 7Œ6í(/Í“”Rª acÊÂNèjÐk ˆìn=9_Ï`<0,î­tíwV//â£Éå¹õçúxš/OòÃ%:Çï4•¼©ßñ¨áIHIÿ=b¤³I^gM7—i:È:uÝ€ÆG›¢5¤Yã$W”Jg‹œå©§vømqâ¬rì5^ä 9éfßÌ1iNø4H²Yùª™uÀPI†–•Ø!‘¾‹ZÊI"“û;°”„x%ìª3†¨¹µŠ7Î… Н¬¥…_à?n$YŒ™èß[±˜!C:‘ F³Ñ³(Þƒíï×ÉjG<ôÎ0vPËù5„r G6LeáýjMiŒEnr_K¹éòœx>*Ò®>=üÇÊb‡8irkÕ¬ëY<aˆÊ¤…ü¨isÈd ÷"ÖÄ,®ºïWe«QìæxmâJ¡Ê3 â³Â ñ£€°‘ pá:<ò(PÑQw×yÌ)Ë G{ë:lgõÀñ"cEªI‘¨¤Äˆ÷ú´ÚÎZŒ9Oõˆfúè¬Â02,˜^¯û^‘ƒ&¬{|݃t‡ÃÂÉTfC>,­y€\´ëæ¸(›×ô¹ÍQí¶:4€­SÙ íÑJAâŽÁýÔÆJ˜k2Iu7¾Hîö–»=¡FÌ)8)I@YRe‡«K΋‰k±Ü ‰ x{³kði¦ÓlÆ„ ª«@Nt’éžÃ\)Ø“òÛ Ã% „z±QG·ëáä ØÇoµg‹ì&•Ñ>ºk^J±¶I±añøK‹ëp—ÚQ`“ƒÿ±æ‚Ì"…½‰K|%½‚Ÿ)bMDUš^Û9¯H<Ú¸‡ôíüf¤`rªOÖ=®bb„c SÎY[F«ˆZiâ¥9:¶f]ýx5k¦\ÑHfHt?yiö7Ähc°Up·³f—:Ëi»l0mÀA¥™À~œIX PÆJ ¼î¡;ó™5ýÐb+Z›lA+³"%޼C˜ËN>h¼M’˜ôLÜa“aKÐnÛ»íJ›’Ї.t!k–Ò9)á*Èc7Êm•CuyO ¡ßk$õL|UÃï|K–ŠÝÙÞa3¤sxÇsÒ-ðædWÞwã$ eFÇQü²=šx¸_ œ¼\asÎÄV¶tTxÔÄo,¹”M--ÏœLj‹VЧ}@\ õ^äF7ƒÔ'Ë” öv ? ÌF€÷P]’é¦ç)˜<^Ͳ(I’>“°°«³ß2Ã΢¤ Î,÷ ¾…0ì†*²Iz”Ö3h¤¸Á0Ÿ ˜ 4R—‹FIWjŒæbÂb~¼8±j¤Sѵ0ŧmnŠN\^é´NÆ`P•ÒJàc>Èßݡχ(ÙÅBÿt†s…hÿ;û0‘s,NË.èk>( cOp޾X÷ÀNê÷ž!ä`"2í¯í²t ’VÞÔ™?éûCÊjr +ts‹ðuì{Bì DßP aN$ÃøÊ8Ÿ‰Nföîc«#¢û&Œ¢ãhBØëP~vø®È­4܃*ŒÞ2Úæí*`›Ghy€ñf¸—ÑYõ>®h%ÙŒ€’’íï‡íLéùû·AÄVÜÔªú³2gòŠ´–©Bìi oÙê(Žÿ/œ¤Ïä.+Yî4þŒÅáÉt<Îd_?%îJÿ²œþFd ¥™lù\Ÿí {Gª¤Sв8&9 Ò⢢H³¶Ñ±ÆT=â=üÞ—±Ö Sƒܾ1¼;­ýZ°)ˆl¼FÐ»Ž J„-Fáļ±ša†ó¹ˆæuÜŒA·„ö{u^C¶Â³ 3N‹‘ÔØLç©Ò pv¹g^@Ãp‹'ö°ÎA[8¹Á‹Îñ:$@”ÜO›ÔÃ'cæÜƒˆ/í,̨iD´KxàW|c($`%Bœs#ÂEô®P¼¶ñ+LˆŸ/XÎ!lÅû ãrígZã€UüÌ!‡”Z1Ðö`"€¦`Z@öÁèCÔ9žƒí“@!8ß!Ì›-aÒøL˜v ”Ye—ŽèR:Žú2öD<ìª^¡<Ádê×-ß4}4z3R’‰ID&`ÂBþ3§uØÏÁ`}°nÖœ‡‡ŠWÐ:þLÃG0YüZðÓ¦hC5# Ÿà;À>CiMECe›^‹/ðÛž/ù •*¢±Õ_(Á³¿¬â¢ƒ„¯óoùäÞO ©Œœž7·j¢å·Šá]š:b¼2΃Q¥S-%ú¥Yfð¶ôª á˜éŠZ· A.†ÔßaÊùqëºEš\·t*óü>è-j¦&§~½ßj> Åj¾~ ‡Vš™ª«e-FÓrzd@c’m‘ q2á–I¶[çm‰æuFIyî5WüÖ¿ ôÌ º‹ºÏàÇßËh–F‘\cCY¡‡›Y©dG ˾fú–ß¿ð_}ëÊlUþU8¿ÌÔ…»5wƒ;1O£K¶è#6¬¹~ÉÃ>éÂDßö«%Èλ~B,5ÚfA”¼ œYÝE°[ ºh”õ #w•#ºÏ8Ç‹±‰0yg8»=}qåHRQ¨ü•ÇFÌŸôÑ‹nr0HüFÜ`7;ߟÿÚùendstream endobj 89 0 obj 3848 endobj 93 0 obj <> stream xœµ]Y“]·q~gô#¦òâ{]œ«ƒõy“Q²#+ 5Š•²R•ËyÈpÉ\$ê×»»±u8w†KìritÖF/_/€>[êlÁÿæ^>¿÷éÃõìúå½åì øßõ½Ÿï)jp–ÿqùüìÐHiøå—¨Î.þv/õVg«>óÁàãÅó{Ý©½Û-{÷?‚FñÚèCÔÐéâ þëþÜÖ5Fµûr¯1wŸíõî›ý¹:XëV½»hm>O¿váWÃî4Ìu€ßµ ­ùˆÐd9„¨£µ¼çgû¸äAƒVv÷Güà?f÷5Ìü¼4 ð`C­~Ím¢1Š÷üvî`P½*Þà?°ÖÚûݧ°¶¼ %gTäsŽã­*ðm¼DOyç™ ç@ŒUŘèŠù¼‘0­!¨¥N‡æÖïþm®WàevÙ[XcX*]bt|_bS1Ì—0k ›Ð>,P"ïǯyf]UÙÉþe¯Nìáx äó[ÖÅóó»+Ð8X^¬ ´ÖD¬WPâ!vv0ª8§ú+²@™ž}¿ÀïFÜýf4Fû@\ÊŒÍ^©évßIVfC~vË{÷šÆä»æã7<Ö‹=²Õîàªý7üŽd 0ºñå¸qûiF`…Øùhb³ã<r®ÌÁùE§±ØÉ–é•]azc1­Gf‰pz·àæøìØîà 4ñ‘¨é<´ˆµ—YûãpøÉv‡09Ô¤ Ôª±“ƃŒ p^0î=yÈÛÑ¢Ý6YÇ싲PËJ‡ò'lÜ ý1jY#+LCßñʘ cœ¡ïaYœVüÇ‹=¨e½8Cý˜–ú:±Ñ_Ca£´G·hba@Ÿ¯ŒãËr¢å<- ƒüâT8-ÍCœæbHÓåe:×計 ¸½°à§žÀq%²ÃçýGlÅšn-«…öÂMI>Ãy‚‡yúã-Õó` á™ÎÃí#ñ£æc½kâ2P.ïh“5CÄ©v_ÁŸü3qõTÖ 7F²$[ìX4Öb «àËÒs#H[X}¬Z ’Z«bˆ%:!œ†ÏÞ[ïêÄŒÊw2ÁÝ’F¦BU:’Â'kd€Ìƒ~·Oº/ ¥Ó?ÀöšÔÍÑxffóð\á,_íá8A->Ü·8ÈB†WL]s¿ZÄlç¸þ²ɰyi· *v¦[GÁÌ54tÑ Çº§†][£åò‰·¬>ÀÄ…¹F³Ì´ Öi§Ü]ª§ÿjŒ‰š:›½Ø_ŒÑØTo)%QP<Ž`RâiïÄAò]I펂Ýó…M×$: é¬ïpríxÙ2›Ý?lÎ€ÚÆzP¬8 Ê¯î]üþ¯¬AŽVèg€Û”Ž»†Õ@ó|†ôðnv»Üup«‰»§8›2ÆmjÆÖ°²›½A¤JäX­2«·»g4(ê°ñ/ï@û\µ.×4»ƒÑŸïݰÆ5·„c3*М¯ ™³Øï%4C=eÝ &Ãyxƒ'›öÆ ÀãÆë?¯@‡yÕlÓ@Vààã7x¬k0!ÿ† xVhzXÿ§6ÖsÜ .Û³Æ/ö@;çàX^!ßxàKÿ†N‡6Š¥#’è_R`º·¸8€,Kì{¼Ú#ìXÍ|/We²¨ÇƒIqü‚ŒI ¸íïï A,lÔ8¼&ew¯Û ÏpPpoýq½m1¬¸µ~‰$Xh…O _dq²Ž;rƒ†ò(5_™©ó›”e{E–0 4p5@¸V\r®S=Õ¯šÙ«„´’Ô:{<‘ô§C‹˜ö¡ù£¦†žÕËp¶ÊA÷Ç­e&â-œãuûr ÿú{ÔÆ—DÇEQ«6|û ·ÁV 5^¦…´¡8RžÞ/ü4=À÷'œÏ_4‚¿Lj¤È\…ª¶ÎÀ!àÒWô O³8Ø"ô©›øt"VEi .'¨î²pÆèÀ·„̇$<Êõוþ¶ÁƧ6Wš” › Û?ÇMûƒ_Ó¼ÝW&!là+ÜM C·)Ùa!®ÍŒ xÆT_°Ûr%ÒUá½´Œf<–;,-«MïߥÀãc(íM4jt ˆÝ$™lJ}æt0 /³¹×šáh–pÍk ¶µOž¼l¡Éϛ엀jé9A ØvÓJô sç :ùCXµg~ÄàŒSiVÿLãõÌÖ }@übÔ›âIìç‡j&¢Ù7˜ŸuÖ§(‰Wä˹×<ӹќKO¡›Z£øÀ“±Â´ã¢E9+ÁÁ)`´a#÷“gÅd®ÅW^ ¸Á5ŸL®Ù¸Pâ#Û×Å)îÕ,?B37愵¹e!K³µ áF Ê›dÑ"‹1pƒWiPôŽ·ÄÝ- ›Ì‚c·XºcoœJ‘:Ö¸K0(¶Å¦HÓeY{KÔæ$•1&D^à¡óÍíܘMb{¯²QħQÒqF¥(Zô¨úóoqÆ”ïy§uRÿ8DOdN-jB‰EtÜR ÂQ"bl¦žŒ.ïSÄG‰b³‚!ë—¹¡¯©“/ݹáŒ5Pä~š %­„A ëߤ¤ïÞœÆÂZK Äúû±Ö(lèÉiCéDÉPËJoáï­£Ö`¨» $ ¥ãùJ&ŠÌ‚’ ”Žal–¢îá’$ŸÅà˜Ù–Ž>jÄÂ,,î0Xûúì3*‚ý,ÈÙ… È‡Mƒ6]ƒ¿±µ…Öɇ©±12&„U`{A"©(,åÄ"ØÑ·U¼f0ÓæÝŽEw&gPVBU3['|JÝûAg"r6žì S½E ôkïrB”ðv j“• Â@’¿^ܧ®,ã£0hæ,öžm~ç0>e‘§D®âeênC¨º¢oñr2ÔL¢Ž)\¬Axyj d ù'o‚fË^Z`½öÊ}’ÛYD`æ ±ØÁ¡óUÒbÏSòŒõU YRBu9²@ˆ°Ê©t#2:âcg‰c³È" }¿×¬8±ý…ÁyýJ0ûŠ5^ìëxY¢ÕÿÓ¯*¿­žŠÏÓJËä>uh³Êƒ‘y' ƒ6Wûå >NN‡® xµµ\bNÿ^xsfUsÅMá¦ZBSÃKq®3€m2*_fY *½v^ÍÂc¿NË%—„g¥®x=QPÁ¤ « JT‘˜e¦‹{‚‚\”“ ‰ÖEVæÕ@…Ü@ ÚfŠ=‡Ê¬Ãp •¡ò†B$[™¦Ì­óÒ¹Áþd8Ëá¯Ö‘cÑ¥ùZÄÿh ø{ûŽØÄ'm>s¤oɶoÀ3:¥šëSlû.ÑX¤‡pd޹JN¼­9ÄG“¥N¥ò°?ÆP¢x^SÔ¸µæ}`œƒ:ÖAi½¸ƒVÞ™ê÷!| Ÿs ¦YÙ€m¹^5PÅ.×Ï%*IXóS“†ã6ÆNõÜq¬G>õ¦â³í²PN‚n“ Ædm}cn¢sfî$J|Õ’KÓ\„§.'¦¦¯",oý²¹c‚c+LVàæÏ¼ðlÆR¨›„úDß*K©oŒf–É«ÁÂÀˆuEseRÒQSz /ÛBú{ÄË$Sž×sñ9¶ŠI)ƒ,È+¸œê/ í¾Ù;ºéÑËêkiZš0ñH40,NÍR-É%!‘Oš™‹Hίsާ+†hOpš‡u1O€79^BgÁ š•faV´¿ÑŠ]„Q¢šsÉ OÍÚ÷éÚû(Ïà»[˜ _ù€Àï Tî*JÜ÷#¡°ávP(€,t‹Í*…×&Þ9}‘ë7+Wt ŸŠn%fKK$nʰhzi‰Tùá8ØŸés67Tw¾Úˆ°È¥Q´Œ1”:|vÏòÄUaúu¸ÚË® cê?c¯D ) šUai¹ ‚8$£·úž® ¯è ƒ»†L™IÙÂå÷ófHI—¼ä£‰ÑÛ,ÖÊÛ<]hX´„ïøvËg!¡wS–U_yçY˜ègf‚^ÏæAƳšJå…}M)’À®Åçâk¸º+RVŸ–; ~ØÃœ&ù36s|¤%à%nV}¸äæœJ¯5bh–†=³–Q·Æ’-˜Ö/²"¬ÎÃiJ:¿Q(¹ý+©'[ócjƒŽÖÙð<Íû$‹†……b&aÊXÛéæ$çÊ‹òešƒ@£ìRñæ<þÀý;âuÏqÞ?íAg¥)ƒ›Á‘52T±tþ©L"Ê U]…Ñx|2ãÚ!ùîäé®ô* Z­ãL))·ˆÒôrgŒûÀ-ë„}M5±Œ»¬ÁfÑf‡yÌt¶c(ÉÙ~t¤4õB>ææ_•Ô-Œš½îۢܲؤ5vÏ•7ÝXÐã!{Ÿ2½î“GÊçvu—3Hq“C6ÊI3’‚ê@¸*3Óëhw°(eó2øm–îÅX°™ ¯,»NWÔx®ˆ5ªvëx9ų yì*xÒ®YÏö;?:Á,fƒÞ2(˜Ñgä@—þë¾^“¸CÍAºˆÑ(¦{(†ïJu%Üg—À(piõG¬4 @ÙRaaɒݺ?QN)ò:vÚ{+–˜žNÒw¹»ì‡+’pë† Õ Ééðü9)”ÀNƒLs¯"˜ÇnNϼ÷‚…yœl&\‡Ò&wÕ,z†šÄ]Î Qc}ŸÌƒTž£µŸ¯ïš Þ"2µ—cE R€ÉGïžx›Á¸;õô…õ”'Î0׸änäÂÖ)Çbj›2`²ÐØÉ+hÝÃ&03ÊK0£é(üó¢`öÀ–ÓT}CÝ7µôvöj×øNÌýÄö ª ÀSÊJMóÒ—nÕÖâX)L-®À4Ã4Kè°øEE`O³eâ)’îÆÆ¼Ü±ÉÄ÷ ]n>,:á¼™Ww½Ÿë/þ´²"ÓôO©0"y‚éE•0$‚®š¿Ì›r¾÷2ð•òü‹òœŸ¶\ t»8q¥r\âÚ÷‚À-Ö`u+í/¦cË<äˆ|ÚÒ:räNóuý’­°Ñ6K ’°ÉI—.˜ %þ|Ûd†|ßCËpا2(™%«E.¹î/[Âæÿ'M꼦˜q¨„î8B† uGl#>6Ë<€µîû=fzN€qþW E3ó"ÈŸ_æË~§ _¢º4ÃãˆÜ›WüÊ W¶O£ ÎCWO3-ߎðuF‰r jÔ pQ¿“AÈK½sL/½¿á ú@º5ٯϹéy…Å´Tß·:Uæ6†WN–¹%¦©ñ·«qôêÜɧ#kí¡,.uìZ–¼Æ“kÙfQö©·6‹4õnÏòm:vy hÚ³UŒ‰Ëm7Ýî7°DZ‹ã´”Úw8ª%‡í·Ñ*²X…ïséû¹Ë#_KÍ›k|ðq¿ê‰ ËK"þÈrØL©&&Ï?uÙ€É#*]uÁOM4’÷³êØá™<5³ÇåÞŒ¼êºU2I` —Å>ã4%î2å ù’™hiÃÊà ÜZ-µÊô«AçÅÓÍ%Ž¢>òØBðÛ*Œ>Ê•Ót‹k=áÃn=Hا×:5tz Õ£ üJ–|í£Èm5$N®²¼½9-?é"8ìÅÓo}°"ÅÁ½„ÅÒ_wø¿+)OCläŽëné{Æ÷Ÿ_ÜûOøï?–l…Äendstream endobj 94 0 obj 6240 endobj 98 0 obj <> stream xœ¥Z[—·Îó$?b»Ïñ4­»”7ƒ‰/‰1ëC.ÎÃšÝ ° ˜“_Ÿ*ݪ¤ÖâÌЕTú¾ª¯Jýz¿.b¿âùï'/ww~pû‹_vëþKøs±{½ñ}þëÉËýÝ3xH ¸²„5ˆýÙ³]z[ìÜ[¯!÷g/wÿ˜äl¦e–‹sNM.þãà|Xäê§Ïge¦{óA-΋UMßàO)•sÓŸg9ýe–aqVÚéñ¬a¿êéÛù §ûóA,Z'§/àŽ÷ΆéˆAûé;øe­2ª<¨-Œ'–¼ÓY´çBÓ£ù`ðv0ÿ<ûsf ‚ñ—ÕÚΎ°S‡?øà!ß9¨-†ô@²ª­™ÎáÑ7óA/JY˜ò[¸á½…E]?\ì_´ Óóa]|XÝj§§°­…”Í“yŠìî“Y9ü9=ŸU|NÀ̓òëb`ÄŸ¦dPŠnN¿Â3N£ƒ§ïɃ/Š)|$›“0"3“…}vz€¯ù VÇ'ö ^5v*¯Õ)E+ K·ô ]L«’JOŸáôDœí%ó¥eåJ«é’9ëÞûi®Và' /¿¢§ØÈ782€"LïpG…ÁÒÐG¾éº ãHJK»äï”ñ‹x †MqVƒÍƒô˺:ËÇO6 Ìô|7ÐM«ˆI&Ìò³ÁàXu÷œð¸'@ØÉž¾ÁY4Hã=Ãéh핌CdHëÙ{ù¢œ·f–jÿ ÂÞÁ^¼¤'›yGeLÓ®29²ãúMèëlÕÑ0¡ ‡®e8z§92; }€¾r-†t¹IÖÐ?ìÍ [ÛBç (÷ý<À0Y¸£áÏL€SÁÇ?`ûç¾CYºÅèU ©‚覽Á÷Áºô€]£1d&WjßöQ_CˆH bzO1ñrô(Æ+Ø&­óxc¡þ“11FÀÔ c0ìKxÔ·$4ã(q:ò•ÀŽ383(ã¸/q ëb½ü˜Wí™ugâ‚+ïe¶+Q erµ´d|NG^ ]\/]Aø*2Q¢ã"QLðÉO*Þójtp|5mæaƒÑ‹57#•ADó…O“)6 šB¿k£Ú{ÌÕrÕ’‘m,òXY´éÙRw7Úæ1Ì¿FFþGx3£Wž]«/ã2´ì‰cñ¢¢) yIMwç²Û·ÃòœeŽËvì©c†‰)V–T6ÙÉC4Gª*$«*‰ùqÌÄ×(¨rB49p'„%»{˜l QCF‰-Ç93,@t_ÄÀù ¾]…ŽÎC—Haã ZÚ ˜¸`a“'qB0êBim ˜;4 ÍÿU$Äè+€‹ÿ¿2à@B§yZļæ }-lÊù܉)ÄÂ.„u£Ô@©†”Ø©tâs“ÅRdö‹×¢ànì*˜‹=µ-!Ñ…§½ÑÙXl)ᣊ¦¡dH>ß6ê¦,­zRyš&Žø}DWÑ„ädÎÿ[s¬Ï爜Öj—GD^v•™R$56ÑÑ+­þzm¬RL=‘t™ "…ö‰…0 ðôä'+³Š›¦Dô'±¼•W›hW™ò©×™,ÎfJøý•ÁÜÃ-›J¯ûg»‡»×{€6–›°¿—Þb^ß› Ì+Ø»vw|·ûæöéîÎã½ØÝù ÿw÷û{ð׃/ö¿Ûݰx²²m ÁRÙJ([E3‹ÉÕmxqÖ!4a˜UX?Î KÆMHÇd‘7×X+8ý±Êèôà‘´)*Ý>¶w%xC:Ðe¹éb²[},önªbÇ17º0gx%d â›|Š÷oÚhÓìûªâ¾7y²$¹wM]‹ôn 'æM×(Ž>A ‹1¦qoÈ7…;6( Uokb'í;ÚŸR´­€1dz+JN¦’ìË#{¹¾ËBÈÒ•MÍÈÔ,Óªõá´x£\ŒÄÂ,e[Ÿ%9 )å)Ø?aJvκ‚b¥á‚WYf¤ô.<¯'«,Ùß3ê 1Éâ^‰ý'"$…½'H–_y¦UÞÓDD9­-Ê¢óVmÞp\–ªáŠPÈ‹¬à7`ȱ†è¹+ JKØn2FeuhõÂJŸ@Zœû½coz^é¬`°<Ò;5rÑÍM‘ #9Ûð´ òZÜÝÌM ¡þ ‰ úU yÀ5ö;0§e±PϤ•j„äL]( ÚéóYÊ!z‰ù™ieÖdíÄò Õu:umÅÙ4Àe…'3õ ‰uÚ¥A7ð2÷4®©4g™©0,‚Û%ÆÙkÖõÝôcF¨IÆ!c°ù²—X–Àh•áÙ÷ rcXõÖUxÏ2Ž ¦ö cìõa!ù4ŽÛÍ’jìÁŒóÔ_R«Žý%šuÒ¬¦$ý™PÊkX°îo™õ/“½Æ\^wMÒéŒG•)¬còYG“„WÔ¼€eÌô§Jpn¤ù cYÞ¶žGe5µÎsu,ÝÆõ«¤ƒâ‘ÃP-³<…I@žž0™\5Û3h#JÍöš;è€ÈCJþ Tc õ¦¯6)Éth®jµ½ÙÆZkmÊÞî›é}mwŽ1t[wmNàP¬Ö»ÆÎk<ðaçB©JY”ï8Iæ4˜‘²=–¡gsgAöU*Cõ‘Z¥¤†—”95«27±Q³y)y‘OŸ²×ZU”š!>G®A ³òs“âºÞš .zšz,MS¾`˜vZåzƒm°­ŠV°öÕÜ4ç1Ôu×¶iÑ:^/ÃÜ©®vÙ‹ \²„¹”D„£Öé»RÍ)pÄeô躸+˜Dù)⋦EÙ¶îYÔ¯ª£¾Œ$IMëB’ñ ÜÅlz1Çv¸&I;ým+#~lF³æÌHîà`ÏcU•ŽQj5Â<ãÐÆ=ıh- ‡ÈAq¤—Y®ž‘·›d"²gÚ”QݸÑ/Ý«Nè£ôb‹úÃãÜÜ䢖3×kÔëüø.ÚÑ!2Œš¦,±SÚò,Üwsê÷¨ ìÏG]ËA”ÐéPþ>A¥öÔA”°²A7;Õ9lz§X[ü«<ïµå6O~àéB†ŽL@ÂõT>;MQÙ@œ½lW„¦r,¼¨g«Ô¨Bt±^Šø÷·‹M[ovaº®ÑŽ’d<#Õ^bsê~ž ®ÿØj¥äˆ÷%¸Sølðþ®‰tÜ"ûºõ7¥1¬K+׆ª›6î\£‘Ô¯jã‡­Ôæ‹”Aní#w·Œk(8Oéú4Çêºý!«F7 ‹dœI´d,È‘4xŒh½¦8OÃ_QÞ,£Ÿ78>OÈ‹SŽ#´„î<à:'Ë’/ujŽÙ° +"ެª_Æ(ÆIj4'|ÒÝçÌy”ëQ¬0ù‡v¨©¢¿B'ð£zll»UD½ómùUü°A³ˆÔæD`‘u,sK5‹QÎo¿ø!c¢—ÃOk°Ï¢sŒ¥tŸã~áÛl^ËèU ³a…ýÕÅ€ßd¦®AÚ[@n®Ïˆ¸ß#ªÁ­ÍØÃ"up– ¶‹w ->ÌÞ¥ŠŠ-“}mÅt ¬Å/X™ìm_b¿ÖüûìÓcF'Ëy¯'Eˆæ#¨m=Œ/¥ýµžµŠ˜’)N…¥³¾fý°†rYjñ£×d…“ÇL¬}¼xÁ8ÚgÝC³-AÙ‰f“°+èRc³ÏU-p·8×K1 ÛÃùº¥YEK1P¦7H™a`¡9|ïÒ}Õ’œnôEݾmö6%-? +êÒ—ã5|w5^sþ;ý ½XðÀÛÒÿ”,JŠVäÊÌhÛªuA´ãŠ&å ̩̚Œ£coƶ›Ô`AøcÅô¦¨/‘§6´\K9^¯ ;”ŽØÍôx8ëºÀÌ?®ìû"aÌ,6bø¢æì°V®ŸJéÎè¸Q›ú)Yüi½é*áâeǨ¶æÈ‰$ú¢M$Ù¾“\Ä;Ç+æÁ s,l3R¬ñõ#!¬U`ßr6ú5>8æ%tæØH RÀ廯77 m6 Ú›ñXškבj…ojã…qætq¼íu¥Ú¿¨HhL_–É鯕·Û8"±´ˆ 8é.‡t]”øƒ³cæ™¶Ázú;zÏÔšk?]®c6g¾ñ‡»ÿgî:@endstream endobj 99 0 obj 3362 endobj 103 0 obj <> stream xœe=o! †w~£ÎÁ†;ã1‰Ò´ú‘°UR5Ó Qÿ¿TÓ;)H!Kæy#n>"ùØöZ/³ÛœÄ_\ôG;Wwsôøµ\f¿«[5*ùúí–4ya?•ŒvYg÷Fà0~ÖgK$꜕-T¿ ܇!¡ˆ*Ác T-YaÞÂ@˜ó( õΖnÊNÖM¦ms­ÏT¹7±(kÎ}r4®Ò”á©][ ^lò±‰Ù¡©d’•Ñ”¨OžÃ0š”…zàµÌ> stream xœÍ[Ys·~g\É_Ø7Ï&Ú1îC©<ØŽ+q”ĦRVªLŠ2©Eɺ•_Ÿnœ f¹”˜J¤¢´Ä`€F£¯ýeÃf¾aø7ýÿðéÑgßÙÍùË#¶ùüœýrÄÄMúïáÓÍÇ0Ém›fsüóQ|™o¬Øh+7ÇO~œ¾ÜîØ¬²ÎLÛ˜…àRN'[6{à óÓó4êÅôjËg/¼òÓ£-ŒI­ùôb»“ÖÌn’¸’“Ö ó¯ã?ǽÕl帷ֳ’ÞmŽ¿=:þíÓçø–ž%“Ó×°•Ô‚‹é^؉ë¦ãíŽÏÎZ)¦ïq*Œ{>ýG…bZã¶lVÂ)­¦Çø·ÞNOq‚ñŽ ¸%¥×’Δq|š=ó‘4?sÃD& ¶–@6Ò€!@¶R^Ãb¶@Ïô6ÓjÖZàGœU°›‚‰BªéaøÄrKÎÎÁëË϶zº‚<Ÿ•™Î·dÝ7[>ñ´®€{oa ¸øÈ¦ÓJœJÍR¦ê"õÕŸ‘L˜ª=l*Ý̸Zîô¦e\ïä“ÒzÓ/‰3ßÂ’ÎÏù¸ƒ1p«<ÔʆcÅøÄ(k™J6~ß²Ü%öávuæëÅ¡ñ%\_¹Y[Qȱ¦(‰´‹bd¾VÁJ”Ð(Ÿ>Ù¢@€d€€jŸF\.ON蟮KjúµÁ;Ðò|ÈX¼G£{V$^ ¸<aB$ÁƒhŸá›>\cZÏr“6a<>I§ëØ <•Ê÷¢Ê@Ÿ:pQwËep·<ˆ/€Ô0%V&>Å‘ÜÖ¯êãì#%cÙ»KüÝq 'G€lNÚa-ˆ¶&¿õº" Ü”F‹T¥ôè›e~¹7%zBîs'áÚµ1™o LQ#Ü&•D“Iô·•j˜wNŒÜbòiùÔe“ SqÑK<ƒá §Íî-ÆÅẄGv½éŒÀM¶˜Ê‚` `q”½©Ã1ê뢲˜UeÊ3³Öiy0Œ‚méRT@«’RQ?~Š °ÒG]øGQ!PWµ?=úhõ ‹{©÷Î&棭"Js֪ђ¢ß²ŸD Rø÷&ê–ÞŽ¨0²• F†È%"nK „Î.%.—@) _c…%X®-œ÷è¶ Ð‘¶÷ëdw„]`x¸p·¯uxIëJã cÛØQô±h´;ûWH ¿'¡¡•F­’Ç9n¨)Š Ú;hª½;ÙöAW„¿*_J&¥Úé')¨²DúqF´ÒCý¯î—ÞÛ¶Iî}|=¤ ¢ë:„œqý£  šÀîöˆP.àeÌbèc*·îVÄ]M´áYZ,Õ+È2³:¼Ã§oJ¤ù¨ ¡¡È‹ú.f}ú#<ÕS=Cñr Ü´%áìÕÀ7¸- Õƒ©ŒVãVÖøq€ü`[ÞAèí!¢a(p#H7YfH|LƒÛÇ›ÔbZ k#ÿ\%Ö©1’°–Ÿ9°á›­hŽ’OÈŸ Þ ª®Ê¸Ý Ä“¶ ÁÕàT(§Ÿòe„<<.Œ²@Ù%SÐôù õ˜ôüVä”âËs>ƒ¬.ö·bèäÇû㔺ÿçE6Ècò±†ûÔ´2 †Bš¤ûÖûEœîy`1T{¨õ.Xz¸jîšh³ÐlûÓ´äZ8÷8]1‹w  …ÄpãŽñeHÜä2®ð¯ ^ñhcîÃ¥`IÂG"©ä&Fiš…§ÄÇ¢DpÑ[¢NCø ¡ßÈÖñ_¸ð.Þ¼à%ËÔÄ^ÄLç|kΔ„a&y'©ä’ 9É¿xÃ`ô1\EÎ ‰j óK@DiŽ’¿Ë<'^+‘º’ð”1¢¯*Yë\qIƒ§¸mPƒÉúr±¾²Áî…"ÈF³´äH§=Gðùœ¤¾ ‡»ó 0pV‘ü–à^®x‚"Ú5¨„_ŒÓ,‘Ö¡Žt8ø}" Ðã¬n²Â4¶Š¤ô Õå$Up èì5[{‘qúx3dœuãn þ†¢¸÷Ȇbí8â“kdët'¼Fj€yáÞ(+@´¯èŒÊjà'ñ(Û" %³°Lndbñ]u‚Gøú¼xáôl¹¯aM“bš­ÍíË‚´:ÝÖ(#ðˆ¢9"Êi‰}2?Šê¯Olyš~:ÒǬ]ÂN^К¾ÒfkÒœj5€dÓžµ.‘ê6fÄE‹–Û|ÆÒG`åˆF?~Hb9b†‹ÅÈ©„eËL,Àv4˜B/`@>Ǩ7ˆa²Vr¹e+¹láv]f-%C´â< °ËP³4ÞéFôh"2EÅ>jæ ì¹’»HbèIš®XÐÕ(«¯*jo…˜ºœP|¸Õ!U‡`t„»¬å[uìú"³¸-³ÌNL;ÊæM{¬}‰”®‡þ¥^]—0$š«TƒòA¬¼˜•ø˜úF+Çqð ´i3‰IÑJXê»ëEÚö ÌC•GÏ;˜Îk ¢l§EE'0‹mj‹"vg³ã1¾4I½‚·A(£åçªd<æ¾u6TyÍt ^’Y^¶*H‚hÆ,ôÐûÛš¬iÉEö±å©Ž†li}LUº×U#.«„€´>”¾í€®÷Ð'”ZÍ6‚¯yý²ót] Mf1¸&dá!9Ãçƒ=Þ˜UÕe$141»vQ{<¸‘O †Æ¤ˆ•Ë”y² ÙšfQÒøL÷©-U»tÔ¨”™§æ«å!Átm~JšXX[ÕµpTÓ{ÝË…]Áv› §Ö‚¤^[ô¾#¢E´%'ÊÕÿ>3Ç95±È¾­6 ”ô›§÷•ðä2q@%¾¹1½HĉzKM&†æþˆ”\<~ë>É6§xñ´UÄsSz#'yM¨µn›i,‚Z7è[3ÌŒ}ð£ˆó´Ý—߯øK«xůFX"÷´H‘ /²z‚={Ư‰ž“øålM6R„æ¨:çÝ5Aä>gWx!«˜Êê·^C¤Ö°€P9ú !W¢VÁiº… þ훂 ŠÖ]Hñ/?¹›u&uMrFÛ&C÷Ÿ× W 0¡øô›èvûKüˆÕœÄM#»þTÊdž{ýªfšoG™r¾‹ñ¼19J»_œAMœ ¼ç"¥z°Pu•»˜­HZî2Ø%>ÒÁ“œIy\–yBâÓt! PÉmBÕ=O…oì©Èw}x… çܰˆ/lüZª9u,¤’ÓT›DƦ$›RD;$[ùeU¶{Èÿ›îÅh¥÷xëTí@Zk@L½ƒÿU¹Š2þYA2okPCLÚ ;–Êæm¤P޲Ìdã]¶¤†ÝØ^b­#1«£Å¥„ã /%æý‘Š.Mó"A= E‹Ôƒ ¾‰C0.Íö< Äî [cA<µ`ò&âùÅ·äÚ #ŠAá-eØÿwrZÓDáNÁV+|ˆ°¦ŒÏz*÷ÿGXG)äý·ƒFO¨‹Å°$® òçÕ… ‹Fô’a2¶oF½‘§J5XÎèä­·Ô},œ;´%…Ú¢Ág`PîY`KÛuÖEŽ‘bþ í:5Pô•kxqz¯‹bMhtùQg!HÍIàÀÉ„ðôf†HÃúþƒ;8®kÊ’ùÌÁ–¶}Œ5A‹òWjt-Bµ*DÐRçkÆŠ×H l†=N„ ³Æv‹Î²Ø’âiÎr-š„H›ØCõõÖslÔ¥´#wx¼6 Dš,ú6WN„Ö®K<îé¡Ä\“­$¥q=¸»“âfŸJå.T‡vÚšL)†éWŽ~åûZƒB»p[·Þ#†X‹9nM×ÁJš­óÔ&)”´¿±²ÁÇuÕQÇDo¶“¤î6$ä²R¼(®ËJs©‹D›à]HwbyÑ¥V«kåsoñÌ‹kKŸ ò@Ûäm0—+Æ:DN3Øv™%­Ø/“x)%¹Ð”Ïs|pm+pö¾ºoŽ y¸ª(9ó ÚÖºÕw=…$ó7lÍÏ8U{ =k#ŒšKÆw/`$aY+~{û×_F€ž”ª>ÌŽ°Z†ž4} Q/@uÑ Z^åÿ÷àËC k´7ÕI¢Ým%-n²‹ßÞÀ2r䆨.;«ówº°]9SŒ¸[ˆ¾A¡1AØÀwKM˜e$I&’—¾j\#f^­b–þÎN¾K›ˆ£I¡ ·&”ÒùðÅÀ'ƒÒ35A©“VVääýP÷°JÜݲ#~œ`"ºÑö)ýTŒ\“Îm¿ƒ¤HQ\·ÚÕBc¬;bw°žÔ“.F@#‰­ Y¹$ð5m²˜Š\:p¥ÊoKÒ¿”¢I§gƸhu_=Öd›ZTí%?ð«XwIeç³ï”kâLÐÛ.«÷X5ZNÿÄîã?Ø“=ý5=ÐÌÿ÷øb¹ 7øÁ\  5¿ÄC6)L‡9ŸÕéqV·ÂW0#­`!]DñÍ«:ˆ_Ýñ˜ŠYáøüU}þ¢ >®ƒWeð¼ †ïœeÿ¿vއÅômù§á9­iƒ…>î$i±|l°;.ƒuæã2GÖ"¶m?¡|Í3ß—Á·uðY|QÏòi¢aŽÏOês܉y¹gxP@pà“ߌ^¸,ƒ¯å5·X¡øå¬JØÔ%cä«ã£ÀßÿK¤ÅÌendstream endobj 109 0 obj 4104 endobj 115 0 obj <> stream xœÅ\YÇ‘~'ï_˜7uêRå)Àö®|,dyWœ$X<äX¤ k†5ÔÊþóŽÈ3"3« K جÊ32Ž/ެ×Wë"®Vü?ÿýüÛ'~æ®^¼y²^ýþ¼xòú‰ˆ ®ò_Ï¿½úÍ54ž,a âêú«'©·¸ròÊz½ÀËëoŸüy'öf§÷æ/×ÿ =” =dð‹±Ðéúþçþ çB»ßïÅ‚×a÷ë½ÜýÏþ ­“»ëØÆK¡w·§ŸÁSÃî̵Às)Ã"t>(é—U¨Ýo÷8¶³n÷ìçƒR‚Žö‡0‹6l:x…¶«[-í÷GÌZõãiÓ´UNœCÞëÖéDiËybU»—ûL¯u0»¿ÁS¿.F›Ý7{%qÝjx ;Ûýˆ3I)-<ýa;•ÆìîaëßízQJ¹»…ŸBÂ~Ôî®|¾Ý$¬Þ;KÆ|S ¬ïÕÐ\¹%xçTÁ.RížáâN6®3ˆ&hS¼Â‡ë¢Lß™¼wJÁââÃÔÎÃÂV8]owÏqxmàL^ò%’}à?ŸÇeJ¥Éˆ«ÏHã786ü÷}¤›Št!xM$°Dš‰¼¹m oæ6¸b|Ñ V'ù›8`9KúÞï‘«¤ …ÉïöȬáÀÓ^Ìâ$_Ç¡‚Ñq:<9[¨ê„GªâOéD$0P>a…®ÎÏpÔ7ÈŸÆ8+SÙ¼lœ«ÐÓ~ÍF'~O%°„ФÏ˶äÒ‰p(T8L¶ÊDŒÛÔÚ‘÷¤|Q‰á Ñabé,Lv+´8À ¥¤’»ÿ‚¥È ¹úÒ„Ÿ ”tkìü²ÒŸŠÑ«Ö6w³+ræ8—“ÐQMHÚ€'Cøt¶ Oå…À‰§¡éœø”˘¼à$ÚGA~çâšUÃØ²jΨ«»š°àyÅ…LŠ Á"XUÅ _¹`‹ƒcu˜–2lè0ÔQ…ª–ˆ2‹5øìË]eM"M„ä)ÜD£ý¢kýrÓ‰E€þø &¼ßèz¿W>ïo5ªIêš5Êø3ÊÒ"ÊX°°(@…~Q€Lð‰ŒC_gn•=á1´=4¡’—H*ÆJLòî°‰Ž<”\’â)ÐÊN‘%öV®·Y”Ý_”¬2YV@¸›£ ./(ØS…Ž,TV9Æ 9úËïÚ*b8i–JUÊz€wº “©=]!¬EálϘìBÔ!Í"AV¡è6Z9庑Á-Ÿ{J뉶a(ˆbåCÔ5I×YÉ@ŠA¸2’ÆoÀ"‰-ªÃ“–uTJ;G¤¡ªÓI«¨ ±¸ÁÈ£yÐaóƒ$ ±è'@M¯ VzàÜј—yeÐÅå=8RD8WiI Ê3Ê?‡è¼iÅu›§ˆCVì3åÃ;Q¹ÄrœÒÎÝÌÜ,m(‰ÕD VÉùŠnøð¢9¤™D8Ä’u¸rÑw]Mt™(–*Sl¨ˆµ‚ šÉ 1â›ÚK„ŠAþNUáýû|X«ábÇpN¡­6izØãM3˜ƒÔcwj£–W—æwÍ@3ÈÇ{íõÝäõm} U&7*™™”:ÊLÊF7½ÊZ3…nw8¦Õ‘wó©ØU×Ñ®6”ˆPúŽ \„gÈy¡Ì ·ÐÆ>Ú™÷fë¸Í°øçÉOÜ2C~M«õê%)C, ¼Šº@%W"û©e· ±Å…ùm×Ò$„c¦ÉâÀ–ÊÓÿg/,‡/‚ÓyÄIœh„%?Êh=Žs@Y:é‘^Ä“¯Cv~û÷( ÌeôÀ%Á ènn¾³ ²é2ãÊ´™³/®òv ­ †S–1³ô.ã¬@A}dUO²Å þ¤ÞÖÑ2ÈÃo-cæœÒ~÷i"þ,,/löý¬^„¹H­n‘ó‡©üu‚+«Å h…ðB&ÊwNP!šûäÃ>ÎD×…$ÜÞTxqϹ:ÿTÂQT‚*Ú€*Ü×”*Ó¤m M§R[±”÷ ’$‚pD²%Gô¤µ½ÏHT1³k¦XM›Žî!é÷аþ^ ûi!£ûÊ£o'‚HF½£œ0Ó‚0¬ÛVjÚÅ㣺©1eïCs¿ÓÙé³ÑB3âtÉ}ÖÐü/­bàû&)ÆK!Ç ÆEÙø.Kà‚*[ê¹]P fÂT•û±6ýÒl!.ÿ?mðíttþyà ôbõ?™, ‘0uŸ0 ÞW£!y‘Ì7*,Øù ”7UÐÞ,'4—¦Ò‡¸eHîlM³ `K¨…¢uËÔ\F$®‰q¾ ¢¥?Ó£%‹%|Ïe£ O'é"3Ë—.0¸nÐÙ¢A·ôŽ@]æ7 ìb3˜®g6øOqf‹XÃ9êÍ’¦ÚG!‡J>ªMÑÎ ZcgÜŒ±å¹… új8bâ÷âñ=4¹ žt¶¡3Cm²¡W›âÄÄ>Y6¶¤Š qß] U’KIƒÚ¤,ÂøáÚ!Ö9À/žz(ÁN½áQ8cø)/¶OªŽ¡²¶Ÿ¹1LJßNŒÚYü†sQ=W‰]¡S Ë6qÜRg(1¨l§gñdÈž°[j~ù´X¦Ø70ØÜ˜"CÆtb 8êIk ®@I‹bÍ#0T1J•3¿ßSþšbí‚9ˆüü¿ýw µ©<´Ò†`é¶.Ø=yP1;šÒ9É;uÈfÎa{[s·¡Â’W;ç²×Œ<œËš·u­Á7=‰¬ånÀ$~?$—¬òp¶kÍòjew–WeW"€2m]ÛDB˜©×ºX¼À÷[’Êk´w˜!Gg‰„‰\™<)gCä¸ßÓèüÙŸ ÀŸ*ÚI’…é§šò~Œÿ\æÂC7*f/ŽE`¸"¤á¡¢WP †×n+¸1¼QGúÃ9&e|')»´óÇ8'2'Ý6E‰B¶âžjHaFLAº¥K,MÓq{“ƒëÞQý‡@¤…Å[kL_Ìܪõ_¶N5gf¸‚ªaéxñ…ÒfA¡ƒª0‘³oÄJ M8†èÑ/rçM§©£›e»ü– ˜øš„±Z¿¯Û© Éöà¸+AEmF¯Úv`X«‚¦`dZú@0h]ÿ3¦ÈDð„H÷Ie9TΜî6nÙ™.µ?˜´×Eˆ£}Jà¹ÃDšß¤b—‚Éæ` <Ú1TNæ– «NŠ}ÓHdH5µÏ„ªàZWAsd5ÉÂ@¬&©ùCî 'y‘ÝãD;nJΉÉOÌ ¾1æ÷'|dÖIØsÄÝQªe.LŒ,÷WÀë©PƒÚm¿H=à§ûT­¨5*šž8­À‘`ѧmDA‘%¶÷t3hã/ö¹²ñqaL*“&¥ú&ÞoÖð}-Is©c“U0Ïúj¤ŠW;%Ň¾Ó÷ Ga…™ŒH1ž¹ë–£AA“€?w?³Æ!õDŒˆv9êoVÍ!]HÎ^®F7ö'[>vÍ&\•ˆpˆ™»b0šaxÙÊ}FRŠ€¨I~lœ$„&áOšÑïEŪÕOž\ÿòXÝjHÙŒŸjhôªcÜ#Y|k|ç"ß$ ÄãùˆÕµgc¼;•ŽÇ LSJœl­ñPõ©‡ñ4ÚAwG„hœ6­AFìG2Cq£Òí$¼ñù/¤U< •ú¯E·wÐàü]F®(ÜìhÕî7yÿRqU~®+Ò¼Üãè*ù¸êLŒŠ8&ПRY43Ëh,$ —*††x: q^bÛ‰Þ$ùX–¥M@c¿ô<6DM*þD¥äúj~'ßC!§]…T±åÀ¾/$ŠŒ—6fÖ˜ûÇÌ/œ)IBT™è)¼ð‘žÂƈü¯j¢?g$psܱ©tN4•BRvO%ñtR¦Íÿ›%Ú ‡ CôBˆí½õÔ8ÝÚ™½jκ45é@Û3RlXÂpäYÉ>]œÆÝÂ’X±Õ³ß7Ù R,÷¨BŽâ¥Ÿ yƒêøâÈÑ©IçZc6<†(î-îú´mšØïw ‡+®,a?©ÇwÌyÌçAb<Ñ]3ëñ°ÕQ ™h9§Ÿ|Éì ÁÓŸíðKß“B~Z3Q¬ñ¿ŸÂºPDlH ü þu»,;ÚÖïðp¬»­˜ùeö™\'Ê LO³u©˜"†ù$¾NÚ¯¨¹Øs^6Á×Ò̱5Á.ÚCn%À‚X»–A›oÏo@ô7;é¶½é;oº%Ór%—ÈΠ˶Ù»²/»ž5½ûK¦á™8jÚÄ«¸ÀÉ­êå§»8hÇ‹Û7[ed‰ÎØÈÏr³f¹† ¦Qý rT_»ÄÊj.­?ù‰ÚÿgU˜—üt/7R1KœIZöµ»v=ºf‡ÄxM/¹Ñšp))iæ hZMLîð©ŒmßõÒC™è®iA" ·M ó»ö‰–|»‹þ<O¹F¬Ýdébþè"œ‰9+‚qIõqW@q ~_i3%LT+·³øÙ(MVT§~=™RÝ$ëR¡Ѫü+ E+©ìpk 9;ª?~ÑŽ’_æµéË‚,˜›I{öUY½¶Kh1`–®¤¢Mð6Nœ¾j?ª?l?¬¿ª¿¾ž ô¦=\êÃíá›É@ÏYŸòó®ý¼aý»§h†I72×}ûù¶þœªMC2“„`äŸð. ¤1µ¨&%ÿØ0¯<+9ÀqS~<©ä{·xÝ]œ)Ÿ³e—i]Åà¾]XOæ'c?â z!V[#œ8¥E§ÞÏ4â4¶#·¯â¦W¹¶ŠB˜‹³U´Üî‚=ú2|¾ðŠëÊ„9¥Ãkvô+%,“/6}|ýäáÿc˜'Rendstream endobj 116 0 obj 5166 endobj 120 0 obj <> stream xœ½<Ù’\Ev~nóõFA_å¾8Â# ƒeÏÆÐÄ8bp„[jh–º%!ÁÀ×ûœ“Ûɼy«J 1º«òfž}Ïûj'¹øÿüïÓþæw·ß_ˆÝçðs{ñêBÒ‚]þçé‹ÝÃ+XvJ,Î)·»úö"=,w^í¬×»«ÿØ?:\ŠÅ:ãƒÛ?;\ªE)©õþú –è„qÿ2ÕþÍA.QE÷ßà3m­Ü¿>\jï–°7¸SÐÞ+÷?Wÿ™Î6‹^âÙÖ.Fǰ»úãÅÕ'ÿØÿö×Voöiá¬Ù_.å¼×jÿ%,0AJ8«,ðaÿH¡ð›÷  ü(@ȯÚ÷€)ˆ²1Ñæ!¯H c@M4êKYðƒ½PrìþéÁÀÇR) Fù„Ë,Ö†ý·:>æÙ÷?â÷nAh@Ï€Ñ@Àáy‰O{$0+8%ùÊï íð´ÎŠ˜¿DîÝxw l/C…Ê«òva1 |éaâYÃyk<-ÏðxÇŽþ™ŽVÚÐBT%À÷ŒµÅïìŠèð?]ˆŽþ—z° ~ÿÑ„¼ßÔ#A§°"#ÞP"@]á3°‡W7`+´oð¤¸€Š¬)Žà7m?<Ïj8/J¯“F€"ë2ôy#Eê]hÞø6둨ç|¶Àå‰S!㡼lÏä½½t•Ëu‚…cl _l—%.hÕ¶KP#'F—™H—Rgë´ªd¯D{;9§c¡>“ÑOawÀqxΓûƒ#,Ò Ì³†‹øM[Jöã ni"mùcSÒ¼;80®%ÈзZ£? r4‚׌ŸpO {ÿ]•Cã™<­¿¡À˜°€ÁãÒÂÀöF€É±¬þÝ X #×Tê&[Y‚ÉïÔ¡|øo™ÈW-c,ÖOÂã p=+ÐñjEǢ兎h¶à¡œ÷\$4Í€}Ûöx´Ò‹ ä‰AT œÑ})`ÑX‰&‡|c;4û»Á¢³ìr–ž¶F–GìGâ8˜ˆMñ±Š|A‡Æ¥V–,ÓÌJ6ÔßNl°\7S¸R Gмí žµ]~J†O9ˆd±|øÜË‘Ú` ˜?¨Ÿa¤c, €Yá_Ó–Gà+/ ”BŸ~Ùvg Ћ* , 3”…%ÆqYabÜè`*ª•ìXÆ ™%¿¨ÿù ö@!Äý÷a"Kèß!hQûÏðopW^ñ(-œ›­B !7²ùfdÊðGÍ2­Øˆß#‰ÉÚÊ&è€Ur”LzW¶“'d«"½Î0!F]7h†+K"DVƒ®Kô¢’&\ÌFu^¦,MÊí€%Èi;kjàÂì‚0͸îå÷9wÈi‡-’ÖÖoùÆÉ³[ Ìʳ3ΠÁì§8`Ê“&˜o›»E „#ï˜ß~Ö–öÒJ§È‰qð–´E';;$¸ól+¦Ow¡DÕ€fý{͸©ðg_Ndé}y¥Î·(À ˹ˆB“Ë1zeÞ=;A{ €üt¸5Š„ð@å@šw°,h €bQðÒ>\^ Ç"†ëRx.Õëp]£ÑÐÄ^–ž7õ¹T%éÁÍ6­ëè` õB»ðgÌcHY+;M“ƒtû‡‡Â¾¯êÊ?$´dLŸà¯>פ¼!ÿ$d,ÁÍm\U²ñ¤¹¢8$`Oñ›Ë«-·½”Ń ú =XÅBY$MòÊL _¶‡Zò#Ÿ †–ÇŸ9v¦}ŒêE;Åmó1…ËFìmúGMx™{¿4‚;uŒTžµ…E¶@µÎbj´ò’¨ [F¼yzŒ7â*\P€áø&b1œe#QM¹@É·üRÙÅù#IQQLæ ñôOò&OX­Í±”dRßžx¢$\~£ÖÝ'×H´mÕOŒ²]-½=ÿsËB:ç”îÓ™UnJÝDŒ}øk©IUÌUу™W¸K†43Ó›ŒÉ-“U‘7g´7+A¢ªÎ¥ ËÚzéÖ“&q*6ùóÍØjê,Q:Fg‰;£³·ƒ?Ûaöi5#[‰U U`á×d–$Ón4qžf/¤Xh¬^Ï€ì%z^ôá1Uys&qÝíüi*½…<™æ  *;[î„×®»mU$B=¹MX Ù•ƒÁeÔŠ:ÑÎ)¹³ËR¥rÔ<Ö´Bÿ´ó=C×Â&_ç 3édv~^5Ÿvd²ôJ,"6ub­¾zTçKÇf*ðÛhèâÝ”&¨ä†¹Äâ^`3ñ4Cs¨68ÇÞîWI)$,T,£^ŠæöÆ$þ¥R†î A%Ý¡±ŽîJä˜%'L:µŒÒa)bìÁæ5¶´¯í“´ Q¦÷- »O‘8&,˜ë};wó¹²\Ȱ*²` n<ÈÂ/”Bõ9âÞû‘ƒ›d–1ÄØŽPòl‘©[ÏÄmÚfd5¥gÕ5 o¿1”~$4GéDœ?°0ËkÍoèÆJ[ŒÉ܃Qz-DF+¯A;ŠÌÕ9q³2¸ãƒƒ=ƒwYvņ.‹Á ûhÉÛ”:²ZS4v$Vꎸ |î6å91NŒX?¤ð,gDV®:ò½£Ú,²Ýõê”ÉÜ;•1Æ5QԜϧŽý{ÉrE}8Xtçë[”Å£‡çLÀxTòÓ‰€ñɾõÆ‚žî’k41Ì£‰qí×Yè4jOJD³Õ3àÀD‡ó€Ó$Pì¼ÑØ÷ LˆÉfU#JÌžäl£À.Ã:§Y7sZ~S¨b¸×DAfßœ?x3qOˆlÀ¬•8:ÜÉ­±‚íËB ÷rR1‰™˜—BŸæGzKí<Y·fÊZFÁÒŒaëÍ0:PÞ¸üÞå#ukiôê©6ºŸ^J]ª²óÖŽiV¡PGX¢ãêÒdÆ¥4Ý9ú\ôÄ{Bख–CÀhX‘(÷¨õya`\œÕ´8ïerÙGÆjòH àR¢6Ž—ê`0j%kð}¬%×´aâqŠ.A„p†S •çÔ€YQã§ ©[4ý{xØ- >õÙÕův ©Ž†—aÕâp²é§¡>¾xðøO»7¯ß~sñàï;yñà?ð?ÿúþyüûÝ¿\|öx÷Åæ”t?ZƤ£H3¢ŠÚsi\šæ@pRäoè¥~µú ›™z>DbÜ&z]ØE|xü¤ÅJd‡Îì&5˜¤¯:|™fœ]i«µ±„& ‰Þÿï·ír(ªß‚ gQ;jL‹}œ‰Ú„m°¶d°ƒNÊÐàfNC¡ýƘÜð`&j%­Ð}x”´–#J­÷¼Yw-8ý{þTbP8ópãffp®u,.BÀ¯_÷©êí˜\Ðd¥$ÕÙ±šÆ(RÔãºX¢Û×}²—×Ár‰qÒvõFZº1iµÌŸŠÏTšÏ醺±VLrç³è¯X7ŽUûk 8ÔçÇ"˜¡u”¿ß4ÞÅm qŠþ ‘<ų Ñ.^á1sï ÕÔ;lÛ œB3nˆ]@€Üç:®b¨OÒR´rJŸºÒÑ$°*=H ¢N%×¾M'/$¥»óQÅ®ìNå 5Ll­Ë{«éòàF“Z¬6üêÈŠ!ËG9jᨩ]¿ÁjMÈÁ0 Ú‚ÆÐ¼Ø%… —có±bµêÖ()ý4ÿ@ÂKm¯Yuz÷¤=]ò5ʦZç68ú³ÕÇS?b„ !™íZT;Ëx05¯±è¤³ÓjSð¹6Ò¶­–&xRKo)ùpˆÂ’ˆÄJ‡IšÙPù8lè±$Õ×°à/·ÏõYžõ UUˆ?רîÂñÑ úæÓäÁ) c EŸ&F1/Æ1ß–&]3ëÌfÛ¯°¶çèœ40n¢B›1Ÿö OÜ—Bïïí€ñ¤ J6[Y÷HjD©|@Ù!_jbŒíËÚ÷ÓƒJ1/ºº«0™MÕþaœÜ$5z1J炼ºèÓ$+Òw7©L ©ÄnÛê<R½ïlj¦\ͦO“rÖ¸ Á˜Ê yx„Ó ŽÂ¡±nÒXí‘€‡†½D˜ÚÀÕlÔ²ëQi9¢‰.EwªkÐ|šsï%~¥+jÛñ+qŽbÉÿìæY#«©_Ü(I§ÉÆL«Þy1 aS÷vVôÆ,+-ON—ƒ¬ðÖËŒãÿWæ÷ÙF÷i‡1¶ÂYj»U1z§ÉõtE&Nàd}ý¡¼È—fùÑו©v÷ý¬N7RÞýšìºö®¤¢Ú· мÄf×÷å$Ÿ˜´¬@áè ú)vp¸“˜™£´;6º!ôN• (å—(»áÆ †òc8ýHÉ<ÊHöïêpöñ,$³E Û茄E —­Œ±‘-†ñºT…ÿWä™Î}†Œ•4žµ®R)e©ðÿ.,×Q˜Ì‹K€¨—è:œJÚ¬Øæ$<á·Õ¢LöyÅ)ôLT[¥g%!`ø PòrDi,N±Ë޼8…npUœ"©CÏq¼˜”*è1âÑý ®Ò¦Ê®Û`à¯likŽ;LšUX·yÐPŸ9ïP6g‘Ç{7uªø]:6¥\q"æª#¢²‹cËíš¾°À¨~ìU´ÆMìM9‰¥a¯ó 5€&ï&h[šô„9:.‚ÉJ¹  ›æQw–ÓClÓôê±ä/˜ ’nÝ]d“À @’;ÔÙÞ÷;\r ¿„õ{7š|œ2hó3—ÎzÞèRmÒV)‡+äå Õt:m–œ‰okò}õ£G(\ìÒ-åýqí£Ú¼˜ÅnØ»{–_rêÓËh[—ôïھÅp‘ %?æY|aÖ1Ÿ0˜/ˆéíâvbn‡»Áâ&4ùòKz+nчÚm¿Y§ ´nZ:Ï$tÇ™ãSµëKå‰*cmïšúzòj¼KÅd~óÈ#®^¿îDyK-‰³nÛª IØ ô·CÏ¡§ú´¹¥&¥çšìÇ4ÿ°´3C DÆ—«|C‹$[åyqöSD"M¯x“]`Ú3ó-òNÖKòn%µY𕋘”{Þ“c½fßšù‘%B®ô­—‹QÀo»Ðc2¯x×pëd*1Ölê I—ãv¯ÿ*É=Ë`šØ'{ˆÑÛëbÒxç…Kw6i«‹´l k}¯¦Ü©Â—Z¨ÓU)^Êâ%©Ncõý –Æ9w£;%½n'Ž·…¯ÇRYé[<™ó³k¹Í1$L.­3‡$Ó˜þ>œS»úæ©í†S¢¯ÉƒÅ8åjäsÞkr¼5}íQ×ÿ¿¯oae[Ö!è]Bv8+n”¸]XéoWõìÀåçê‚*a}¢BoØßƒ ’/ìÆ,’ bicµk(æú”NàÚ‰VÓØ=ØE3­ÅÆâïvÝ1[³ÞµÌ^é·­5EpZ4ù²»©e{xR·ªw?%’î©@/èI“ôØg(Ÿ²»ý ÅfŠ×n†¹ªcOÌõámi®Šé&“âc!© 2ä”*QÊü~eO`ó“æ$ßã)ÁPìÏ3ñ¾6ìÙ¨̓zǯ—NÍþÓë­0'Ÿ½n,Î å}çìd±šŒ¡ëïé$ÀçÞ(/Ûñf„Ra?‰/p­~2¿ˆ¢Öÿ¾¸øF¥endstream endobj 121 0 obj 5393 endobj 125 0 obj <> stream xœÅ\Y“Çqöóš¡ß0o˜qp]G×ñháeR\ZŠõ°ØwaàÿzgÖ™Y]Õ3 B”V=ÕudåñåÕßíæIìfüOú÷æåÅã?ÛÝÝ›‹y÷øÿ»‹ï.D°KÿܼÜ}tƒ„„'“Ÿ½Ø]}{ß;+wÆé ~¼zyñ·½8,{sXþ~õ_ð†ì £§YÃKW·0ðãÃ¥š¬õ^ì?;ˆÉ{§ýþ?rÿÅáRLZ/Vî¯ê˜OãS¥ÝþÏðTx˜Öî5¬6.­ó“œÝþ÷nÝ?ÁáþO¥IœzÿÕárI´_è€ÿ†RNRÐ=áÃIJiÌþOe{ÿSþ"ÛùÓAÒ5š‰ËršçÖø WÓð®§Å·?GÊLb^öÀˆeû¯ËqF¯”€‘æ†Ýæ •þx¸”tNI~N‡–VÄKá×x™nåRͰ°÷ôrœ˜ÕþÇJ³ï—z‚ΚþùìN{zuvZŒ×ûàÎØü 8\‰Ú¿=8‹‰ý‡x\ô6û7¸Íe±FæuÌlö¯ë’ð' ÕJ¨ýñPv ½„%€ –IÉ¿„ñ6RzÁÝÕÕ¯ùËwð?Ÿá0دÕûê‚åx,©4nRi ÕþçÊ ÏóÀxV«Ôþ¾NS~}…‡…§†qW˨^3nßfTåéRx4²Å§‘b‹4äõ¯¼åÈÆŸ5¤_&™Å“Ü —§¹…i ËÄ{ÁYµÁ{J£—¹ìÑ h ¾h¹5’Ç/:ñÌ¢lfþËárþðJf‘…‘q®ù¢ÌA.WG&‡06Sæ±aø«:×m¢ˆôTˆ>:äé>‡#’è2ÒèR(˜v–‘T(ÆäÿŠ·ä@v#7¾nï%…°" å›,w‘x³ÐôVÞIe½Y_NUW{‰òaŒ5eL?¥¥¢Vp;;ÒF¢RX–Éí®þxqõ zÈê_P° t’0‹€{ƒ}ŽL»€¼y¼@ SHP/ÊÐàõEïÔBŽtÖ è‚œ f?'²&.»{ݵReŸEE”`GQ¶d¦v#I6v˜×JªD‘I™Àêâkät(G^a=]Œ-®RUx$&Àž)? ê6“"(ÜÅ»HÂë÷Á|èJÏeEÉÁ  öµ z2Û©Êj—Àøðn¾]Ô”‰q4¨à–¡úÆ!šQdåûîÜ„7õlÔ>€ÏÂÕ[ÃzÀý}¨’– ÀË€ ¦ U(óÂ!‘O—wÃ4a;å+:ÓU„Þw‡ÎŽ9W‘DÒßEi€ vÅkà†Œ¬p¨l`h¤}Ƕãöôâ(åeaË ?”Œ 4߆6D Žõt2žÙƒR¿­óWúw0#ŒW•—Óf­0õYÄ;zVu™Èéñ˜Y|œƒ ÌÀI˜A²&är1ƒG± ¹QÉ%èÎ1ÐE¶FŒÛ@`¾Ö a åGKÑÈ#·uÄ +ý¿ôUu8žÖùf2*®c®ã®ðö²‡ `Jÿ ÷H¡ÕÏé5ÚÖÞ2ã.…më¶Õ—¤g‰³çi>³¶Ä³ë€ëV~![©|I¸)ûvTMW®ªÚƒîÄm‚J²¾9PŒÄAèDgÓýMR¼Xɶ¿$Ù4á˜íƒÊþUJ*6Ã?½ºøòâ»Ç-¤’à’ÝÎYXÅíÀgŸñß›—=¹xüäóÝßÿøìâñ_vââñgø_}ñ1üóä“Ý¿]|úd÷å“V¨ÚÜ,v:P;f®¶¼ýt¡Ãm ¯™þ¾…4 Ù¶·]:Ô}9MÒÉ̾·òòJܲr¹­€õmLÁÉ³Ò èÐ¥<ÁоChH<Á±ØÃ§'Ùÿ >j„UèÅHQÜQŠòû?rÒZ1s F]žw̾gs0@{“ÌPZ“k5¥•߯“jÄ»¸xüâAá fjïØìç€Ú Õ¢þPDé2\i¶¬…®-¥P¡ü#N›¶Õ-õDÏ4zYÅH܊ͯÑ€([3ÖÛéõj1|Xqh.ÓKGÊ,%ì1Z+s :c‹o±±˜½  B4&Ÿ1©!z¹”DüW£Ÿ¯7FÖ(¿¢ôhb“ƒXGIý(‚SYrÒÓ4dˆXhýú#eõXäe KèÈôE-ižw’3&vå&áMñ:TÍÅ’ÑMúˆ,ÅYݪµ·š‚Ü8Õ,Æ›­Ó„O bjürP[B’ùûI‡ OI5ˆeÊqÑa7ÂbÄAÏ-Ňa‰•+çCªâÜ{éUUfÈm|cR hhR W®ý <£ò„;×WÀõz?dÕšÕ\¤Õñ¼BÄל²ƒ$[ö ŠŠpR±UQ‘]m=We¨ÇcÛõv¯g¶xÏLÛñlPQx´œ¦ñºÓV0J¹%D_8G3S9¿k…>lJ×"i8ë¥G»«Fý¢—lc¨¹V(ÜÈŠ„›Ø£œÒÚp^^î@x˜²ökº…ÊÒQ Z»àÒÎI¢Ù1ŠWÐz­J2xNÓ3è™1º¢Î¬‚Öå%Â1 jËé¶ÉßÕß«E!A³hVüdMqÙ»ey[ž oR±•«©×!Íó%žÇ ¡ElU}’è02ù]<ö,y#Vh/­ T¼§ç:»N ÐOMáÕ–,e2 ¶‰ê¬Ê¨Íª¤×eÔÈØMupªÍF>…•äòv@{r˜2×ÝçÂÓf¢ :«ÙÚD'ݺ›w%o×Ðj¢ VH¼™/—ä€ÛÐ :°ŽœQg +5l"Ç$XÀm²#W„#À™~^ysÀßÖ$È D¥-µ>ɤbd¦î½AÀ4SWh¸¤©¹ˆéÀC€˜Î±2¬«À9F+WŠC±:JÙ$­Ã psε‘s20#g!Uzv{TžW'¼Ž}:p”&1²£06Yü¶5¤5Í‘0±hø+¥tˆÚïi“ ã¼£WJë "‚7C„VòUVÉ)jP7ê@¢s9…¹J´[–¬Íå茜"žÓ˜X&^Zõxl׋'–תˉ¼OFµâ{`D0½²TªãxDÍ`6ä”CLÞíŠzð7A¥ëžqêŨ ôᘎDЈ'âJ”¸K’ä˜1y|ˆEëFè¦o;¼÷®uDAn-)+7`¬rYyJ³­:Y§`Ÿƒ·*)Òw*çõ»Ñ kl4¤©Úöñ`²ÂµI?Ú÷èZ€ÊFÞI‹%i± [c^ÂëÀ±ÖÎ-5j™UºrwØ-m$K¿¢Xò@ÖO°7Lhü xÇÍAó!‘exʺ·ÀÀÛjŽ S*dÊç¥I¬ì'dƒs[<¦±>n¨*Ò’9¾ÎùÍ!¿3è2“Ê—f?ÒP–ýå¿‚åW€ÌÇ K®›]8q*Ž;zåµ7«©üºu'²ñ@VÕ¢¦8Õ¢µR¯ƒ¾¬ìB×¾¬aê…ëuë‚Ó%tI`÷2ˆG:~]¦îY¨úÊ›¢Üka5ÞŒ-j¶lœ9A!Br² ƒ%3§~‚§ ‘ªÎ ÿÜèC OI1õ…#Z~U&ݤ_-ÿ»û\`ñ‡÷û² ¹V1¶$¨!)ôXG–Œ ÇN›[8ǨA^´ÀL>ç–´ 9ôULD#éyv­uâ’¿ öÒ,õ·E°KO»A‰A8Ø8ЕŽG=êõ' Hp£6ÄÍæN£×Q,š{ w\>YØ´pqGnÎh™þ6õÏIO;¼èmXî[k‹B$мCq3ùÏQͯÿDb%Ù-%\wáQønCE'\\®Cß`€,}¬gBZ–Nu¿4Rµ+N–²ü8zª¼øcmi¬"«Äјk@âç´q¢dŒ«K`ÞÛW´³„ÜßÎ9¿DñÙ[" ÃÌ*h†ýÇ3„‰}RßdÆ×:öË=° $œW³ùÀD…vÈ>©_;ù:–^TŸƒÝ!Õ†£ðBÂëê˜òZdásÃÜ6GýªÏÔâÕå說îV"„\\Óôr¬QÔ&N¹øM²[2Š4s`”MÀF!D¡DŠ Q¦Ã¼—Àí<öò.ûÅ^=÷º¶ÃŽQS+‰%uÏŨP¨è6 Göñ¬+«ûPܳݺp.œ =r6tÇ$F‚pçDo ä¦ÐjÓ&˜‰ÉÚψ+|,gþ‰œ¹®ÖKgÔ°p E‚rÓÀû^RΌ֖Ĉ»kÚ«gIÚ¤§ç6©q7ØVY>mQâ œÐútfHh~¢Ï~Y‘‹ãqÂ7'MFˆkÆH€}ǯ á™ÊWîF;Ã…©Æß¨yÙh)àÓéãAËtrR_Œ\™.P«¾Å( TSÌ kHkdcÕNËs¹cJFŸ3í¨'[5|›,H8âv~O²ˆè*P2®?ÇñÅ׉j ÖfÙóXîD‡fŠS¬¶rÖ4ñ˜"«Ã‡ŒÎe¿âEºÆƒ¾ªQ zÚ Ã\‹tl ÚÔo½ª?çOI¾ãEƒ­>\tÆ—ðóR4<޶Y¾ÃW€BÑ(š&ëB´±ÿ §]³LlÚ®¬(Fž…%H`ÐYÙ&d*éós8KóŒï–„\Ú\rQQnÖáÈž‘l×£< ©¨«o?J÷&›¬Vn gQÞØÜkv[_c}e…”w÷¬×}%áŠ4L;âm9Ìëh¼Œx¥Ö⥞—ˆŠ% ¬€‰€¢§ õœ–iüƒDQ®Ý îHå.Ñ1°• ³ƒ=”û%Ö¶ä"i ×)üèex5ï²,mz¸‰V×¢ â,ÚUW9µ‰ñà¥c8ÌÇjÄ\Ê5û*»´Åã*–×C:A÷‘Ú9ðãgB¨ð笓5ÍwRa`Rùø25?9¿úŽØS¼o&S“BDÝ,šÞ8‚AÈ\£Þx e£»vº§(ƒ§Gåg"°udù9¢D«-lŸj¯ Å3¢·¼èŽD~yqá\ÿЕµ4Ÿ%ñ’vÂá€QûE¬Ù4ì&äk²_Dt‚•¯“ Z7‰æúp­³ÖM”ö@-~]J];¹ÌžÌE°}™íK yÞÊç<{vŒÜHù¹ññ–À¸Êÿ3%.$®=•Œng­¿È$é}”+7ˆ¢Ù±`!Ù/Í-&Å´‰‚^Ëj¿ámAÓ$1n°ÈØœLÕ´ñaÁ¾ A“ßÀI0þŒæ ”I½m Úš;¨zhÙ–Ri阥 A€^ð«”÷Í¿•ÅÞ…Írñ4x¿'‡þ¬.$¹œ-GZžïRýËäèu)æ“n GôGí“òAŽ//þB¾ ­endstream endobj 126 0 obj 5544 endobj 130 0 obj <> stream xœÕ\YoÇ~WŒü¾Ù5¼“¾y°ã3p.YqœØBñ’l^–¨Xþ÷©ª¾ªgz–KK"—³==Ýu×WÕóý‘˜ä‘Àÿóï“«G¿yì.^>GŸÀ¿‹Gß?’4à(ÿ:¹:úà Ò®LQDyôäüQº[yuä‚™¤:zrõèëÙÚÍ´U“÷^o,ý±ó!NJ„ÍÛŒ1Ñnþ¶U›¶fÒZZ·y¼Õ fÐnóçíNOJ)çhÈüÓ)ôæ³íNN!D¸ùOðÍGð–“q›·R ¿y.ÿq«'猳|üçÛÊG)<Þ wmhIZâ´„Ûåc0‘æÿ¿pÿp«=ÜIC¢€5Áv•°ºü‰Kô1ÊÍ?ê iOȳ^±ýÿëÉ€ @3FP2‰4}r t”@:¿ÍÑR§pÜ.Üi1yco€æÂa€àzRªäßÁo?IƒV0ƒ‚µ½jŸ¶/¶;1Y§ 0á†æ²°a6ö.Zød7Ïë®Û×g@¯'­0$„I†`7Ç0R÷åæj+&ç…‰1ß.ŒÙ\Ò'Ë{^?á'¾„ ÐèܦÉ”ÎlNñaò„”0Þä'á[o»ýn ¼ŽDñGÜ®ÔÊë°¹…™ì„Pùé |/aJ£`Ò!«40éóGOÞýšÉÛ10ìz Ô¶NZœß ’švsކÉX\—±tJnž5u8Ãï%¬×â¾áƒõ°…Wi€9UƧPoLT45Ô¦~^4ðš?ÃÀ'©> ‘›“zçºBò:ç¡I  ˆm7™ºÍÎq$>5ÒÆÙuôeùP¯¤(mpV©ì懦>Œõ–Ô=Ð#MßJIšz:ø `%={ ’*F¸ni{Œuq•Qz¸Ï»-ò_+„-ª9â›)‹ò2E/l¦üå¦à•K‚OóÑ‘àPh¼4H{'/|¢gí g¸1AÄé“Ì8%"Ÿ`JÈE&¢5³õ•m¸ç]ÞôŒ«uB¥½ß¦1åÁY­ \ ‚bÂÖ„²]c"üͦ~Ÿ—¼Ù|³Eí …Ë2ÞaîàY{4=õÎqÉh›Ä¹ÀÈd&(^£g‚v&²… ÚÙ,8‘׺g>çBtœÃø#4ïzÚ¸8ÖdÔž·®ÉùÁ`~AKÙ@¼æ íbtóHyNꄉNÈsGí‘hw Ýš;#H‹´Ç-Ý©U\Ѽ"†LrïpL–³!U6›¸÷ErEÍ ß̪°§gâƒÉpH¹À9„ß´©›^]·9ÊÚH“2)I“l ‰¢×½&õ¦W+K΀iGÓž^]ðXë=Ü5Hµö›_—kß&+m"^ƒI=}Í¥"?¡ÝrÞniÚsÛ8ù³_\ºGå¹H‹Á~KUÍÆl¸eæ?°— §q³…U1çÀ”é·yLòÌ&ôAÔtLÁ‘®Vë5¬_‰Í~Áõ5òU~ ØáL•9ɱ?]Ür‚£ŸácüB7 ˆƒÒŸ'e.b}»yHt¶nŠÁ#7Ë=XA¬q!]|Ù.>¯/F#Ïê'Tg!x2´§tñÇvÏ¿§\$ÆÐUÜ9n÷ùb»/ëvoúíÞ%ß„cˆ€×ÝÎë¢5à‹|OO„ÏÚ€wëEµo™ß.–yït{¸KÇçfæ˜ö°÷ʶÌF³«ŸŽØt—ù <»x}.F¥ûýƒ€‚EQE@¿[â²2‹èqQ$ÃŽ¾ç.À£òý¤eÊÒ0¤²«ß›Ÿ•¹8[PùE•+ÒûËFeºøÜz׿[†K}Þ.׋—áÒës~±Œl³ß3g³I"huéÂ͈Æý ·xlö©íù¨x^-óë^¡1ð ùHÎcN†íâÕ mÀ9Ñ^Þ&A‰I"<¨2ÎçáD=]õ´ªù+üñ”oS§#éÎmuQgÅw-v9tFL9ƒeªt¶"ÉÉÚø·Jøüi×¾~ È'G{/ Â>\ü\Xp>ºýõˆ/§#Êfÿ¿Ò§ûŒ~Ä0wÆÍü¹°ódó;¯Š]ïÙIVªDK£Æ89XãíH]ašb½l‚Óèzž \ÄãzñÝv»É†öñŸ3.ëEžñg®KþÕÏEòOFrr5"qÛîY§#ƒ(æ̘ð?dÌåž°ð¢¸Ö4ÏIï~y„üùv!/öò“¤ÄFŸ²»…× ÓÝ9<»ãY Ò%ãþ;dÐ7šPÐLD[Z&Ŭ(0ˆ¤}}ÌÓÔ9°‚0ÔEºu<å­„SÕ‘îK2n³+Ïúx‹ù¯³]9ƒ¡`_ä©tÅÔ ½1eR;ÆÈpÈ@e‚ÞCx1a>l“;å¶ëà(egp;òÔÆ&„…Abý´n<{Dp“6‡ ÷"WÑMf‰]u K»¨ :&“E½ë!de=9ÆhR"ZZ’Ôã1•¡u^¢eÑ$û„+뀥ìÐÊ;˜¼!´ôŠÏ–a/¤¬K0~Ɖð¹‹]ˆŠ¶­8‘Õêq*¢Zø2Ú'ÙRÞ"æÃÑÚ“‡)‰½´*‡èn\W/OmõBVHü}S¬ÿQ©ï£$rQ÷°ÿ)>-Ò7i6¤Á?‘¨ZšWSMR‚ıš$ʼ“T-È„T>ÕXp¹:,låÕ• !Zã¤\_"›s¹F¬ÌÐE4–¯ñº™—ïð{`dÍõú‡TÝÙ4ée‚RŠË iòPÙ,pZ^-‹ÈX)mÓØ½¦+á¼I/9àÚ˜'eŠ2vs´U¤ŠFÚhÈÕû"²‹¨³¶i”gæø+X…°”»þÆÆHÂ`©¸sØp(V² °5J.÷L *¯•ì -SÍJtU»Xµ€™5&HèR£'ÍÉ{DSÉdêc´õ,-žÇ¸šUÁLµM ëÂxK‚±šo±â¼M•:è·.…å\C»Ž[‹Êb!÷X¼Œ—ofH4„6ttûi^½ö…&¡#)ª‹`"Ì@|Vh‚{ÑÔ•ýÿFT€@7-1"—h–¢=«ó&‰ò'ªaR€´éÞÂg::±0E¸Õ¹Goƒiš¶›*°?›'×’–HåFÀGc)>l~C“l µù¶Šø…å6tY˜Æ‡cÉõãm”@3«×Cv1oWbœd5¯Ù˜ˆ-kÙC¡D6Zµ§æwÛXÃB©Å¢ÅØHƒ±2’溧ûsû…Óª³ô¬>=œê³O›Ø÷aªˆ&3sˆ5&ú{ýæ%oðQTò×árí_‘ð›T§êk†I¨Óæ{¡füO­HÏÝç']Ë ]ïSц‘ d@–q°¶LÁ(À`3Í!`` F£ d>eŒ sÚIdê 8K/—Í3(w³pcÑýˆ`%BAÛºÑ6ÃÍvÞÜ´ñGzœ_Ó-†Çdšôž#½Æóøµà®æ±³®¼aàè©¿‚'M°ï‘–¦9fþgbÀdA‚(×—HmÚ å³ÝB„œQù7‹£‡)`B1j( 7âª:À ‘rÈä1¸»HÈeö¸ÈEkm³O¿Û÷Sî²C)/b¿hèÂŽ­Œ5]',a°_n¥”TAµÿ þýÆ~Yš HBŠiËfÍý·½õ Öåºô\'xBR\BL9}‚Se á}Èr EPž¨ž‹ëQn††2cs>,],Ð8"jO|ͧYÓ3ËYª›©@A/¶æc½RBæ,í;ÒBÕŸ™G« +³St +»¥*kx¨|ÃT_u¡åu†‰u˜£#tòÀw2Þƒâóž÷"ñ·M˜x×:??éwdHÒ;áU+R´Íüè ]~8E‹tª‚.•‹óBnS?¼ì|ê ÀþX *S…ªxS“¨~-Ã,Õ–7öÈ H"5ácOBÐ}<ÄÁ,Œ»´¤’P‹CXÔà:’ûëùƒÃ']°3`@±RË0ƒøjßC~Éi ÷/Š1æçÈ.b»ò\U`T DHÇŽ&$+E4<.õG™)Õ ¹þPüÙG·‹Zw _ë2~ÙFJÕaYã"|M4[ÓìºÑ¶4¼¶p‰W§Û|c:•£© žA…]ÙâÓUH£Ó¥Q›xräÈúûБ´[ó2ÏýX1²xˆñÐjt3 ¤Ð½ðÖf%ä*¢’ عVwNCõ° RHH—…‰<ˆpS´±h ÃáÙcfÌÙƒë¤è&l-)ËÀEFï‡((«é´ïÇ+×¼êçˬkÑV“ƒ©\KŽ#Sb—ò ¤Æòˆ^ù©ÖÓŠF³°ivÆ•‹(wÆ,zYúí•i¹1#3OœŒóä.VÀÞ¶…ÍÃÅʧHrßK¸¡ï×M Ö"IÀ˜'к1z33Á³s³ˆù4M„ÔØSQM’_¥~YX]ŘÔ1¡DoT.Ìêž-h,dhŽ)Ÿã&4Å[ ½íÉœÁèü^õ,¤ë½6A–ÿø6Ð9 mê&Ԓд9õ§ÎçÎ`vÏÞ“£ã];/;zAŽk/Èù ß!c• &½«Æ}:’Þ7sYïjï¿9¡øÃkÇ_ŠsW`9•_LÒNÝÞõ%4íÅ4äjm@ [OˆJ­¿™&½_GcÕܳFÄ6½¨G¢Xt¨J‡Q’«ÓËlò»}´¢ƒåÅ6ì¥;i¬ µììïÍj˜_Š ‹Î (–p>ÞÅ œoì8ÿ¯¹Ip¾ËlÝ›½9"¡ÒvS—V냳Àz#¾q¯ [d† ðÈ™MpìžèÆì©?tµ‡ ű-Ÿ½ÄaÖôcÌ„o‚Y9ôQÒÏ_âð">µtk”F¤š(ÑÅYϺRÉÊô°ncÉf½ó=溈J‹Ôú\9S±OÆjÔŸ¼#YYˆEÁ˜á®ÃW oEàÁ:­›qÒ{¨ö¼J‡j鑎^b|ý:4_}1 Ö{Û[°–o‰IO7³€`¤Q¬¤3ýhߎhÄÔs?›©Ë`Y`‹ÑëìmP¥wà¾UwÁfR09ùÙŠ‹~;÷àðý(mã0da°S\În[ñ¤Á†}—:uX{ÜdŽæ÷¢0L5»XíËÛfí»¬ ë«¸jy-cyÀ¨–Ü2”Ée‡Ô^ ÷Š%÷"Ü#–RW$˜¬cd7¹êqX Jƒgjê7Y• Ü=1w›ðŸž5Ôÿ¡ð·úÆQ»gjO°¹Û¥s8W ʼnbroL$Dª/®ÌE“|BÌkê¼H¯Ù׳ùWhÜ#~/vàå°1ŒéÁòpœ †_úçYoäV;ÊRk‘ìŒvàfH‰´Ú 9Ä‘Vi`r”f¯ëŒ‹‡è ÇòËÅF…6ÌØ½ã9ÉR“üˆK‡.ªËžß´©u1ìaž•‚U¾ ( _Ñì:Ai$·z-nþ'eôê9RJ3g Q¹»íæ²ö…ÃýÆj«|®2wÆ&/ô{¦ÌLinº°iV’# kïßëN&=ks°ÒXm°_K…‡5Š1WCï-F‚}ôäÑ_áÿÿYVendstream endobj 131 0 obj 5357 endobj 135 0 obj <> stream xœÅ\Y“·‘öóØ?bÞ¶Ûv 7êÁ¢DÙtH–DŽí[±äðÂäŒ.šÖ¿w&ÎLPÝ=C{¥Ø¬BáHäñå|9OârÆÓŸ×o/ÚËÝ—ûƒ˜´6Nî®j›Gñ©Ò~÷žŠºu; £MûƒóË$g¿ûtÍu»ÇØÜÃ?*uâ¥Ð»§ûƒNôbhƒ/ ”“tNøp’RZ»ûS™Þ_Ê/2?í%£é¸ô!§y60ÆSM÷"¬¿þ);‰Ùì~+f»?—/b‹RZjèf›'€Túl´vI^§EK'â¦ðm<¤]9¨^–¸9ßÄoŒ»—û0YòûE¥`}ñÌ_›IiµûÇ^IÜúÝÏûÃÈàÜîý^ÂVIcv·Ð|¨'¥ô"±c¥í¤íîŸ{£'g¥¾Ù‡þÔî9ÐËhšÜÔ7µ—W@”ðÐå‘`˜¢„æÒÁ·3ëò-6·ÖY&.•ÎÓsÂî¾ÍÓ¸NcCÃS&š»ú'&'ïßW&û¦×ôG€ÇVPúÔ÷Í6”™2¼Ž“œA$òâq€—Þï‘ Ô °"‹"¦ôö0¢÷N©cô¨°Éà„Osž&Tø¶4ÌëU> jæ%S&~v[ᆱOÓœ¥õ¤+²‹Ï*{a›Ÿ±“eœ¼À%mží•ñKæXå‹ä:dz„‚?gÉ–9XCrÏá§2ñßq´ç•n…I`Q œ@ •åvÀFiYÞYº¨÷¬›`–Ioy<U 5EÃ-Ðôª¾OÚÀζÑTWª¥Ïs•È´É´~D2ˆÉ?ñ0é)Òí.kÿRGƒJ_ˆò…¸û>´V…Ûòèêâ«‹ï/< ¶fãáouiAÀ§Ù£y{øøâÁãÏ/úáÝË‹½þ€ÿ{øåÇðÇãO.qñèñåWgš=X7°Â¥UËäu4}_ nƒÅÚ¾x‚LåÁjé«¡ú Ķñ{/Ýî¯H ÛAxûÒDM “‡b¢AŒPe_gy» Ú1«»6ºyt k§å-h ¦È ªˆ3×û¾>h‚ UÒ$a*³ø(TÕlü+™ !‘‘—_/)0h¦h0+5{PÆÃ°–2:±"(¯÷µ¡Y_a¿TIuúÕQž±9aëÊëßÕ‡ì=|é'ЬƒKÉ3}Á6‹((ìVy˜ÙL”ƒ:€¢„ À%¢¿ë(%bär?Ä=€yn{š@3´ 'L5"`~™íPv›q‰mÆÝ#j¦ŠKìáÃÂxôrÈ‘qeË‘1o÷¦.1õhQÿ¼+è‰Z²[nOúb ؈÷'Ö­Äcö1 ›lQ 7EÏ+^ë™kbó쬫1´„™Ç–*‹±Þ#t¥Ö:û&c÷Ñ„Ùýaq´fehìßuø’!.üÖ T—œƒŽ°{e¦ÅÎ`o‘8ti Õß72>°ðJš@­Óf…»+hýâ"± ¢]“âˆô)ÔÄöEAX}Ê,µsœÊ<­ÄdI‘ÌÀd7 gÐ&pÔTCÁie„oéÖ‹D×訤‹³èÿœ®NâÔ¢ƒOÆT¸ y1Fq‰hЛà¿(#ÃäžG°ñ–šM”ž¼ü[Q<e£YÑhÔ%×´`æÅ"GS=‘ªÁIVÇd3ª_ð1õ¦@tdýî\ПG«¤=²±¦þja¦Ž*l€‚lA3ë³nеÖ+­¼=ì1m³qêA¡ª{¯)^ÉÔâ€åtø.˜ k3Šäã®ø «½«bDZ®x!¥{hyád=TÚ ÛGœØÒòMýU(lL#0¨Á1HæÃÎKh<¸Êèõgmd%?‚Ã5Âd“>{„×4ü/F[ §žF½€¢ôY†¾¬€ÿ&QœªžV$ó$È¢Ê( Oô_¢™W r ßº¢ kPî=d‰ Àã€nŒ˜‰´RSÈ@çÑ‘éxðÄ_ DV†S"Ð\%ígé¤1¼åôŒP5!9èæüõÉÃQ e¨;Õ$P†ô¡eû[Áà°‰Oqõ€KÀº[㨓ބî#âÊÝÔo^ÇyhÛ Ž)ØÔÏ.®~ýwðÈ4îìj74G¢¦ï +±‘(¦ÙÒóvp ýt[)ëk6✔ b¸4HÃ(³ÎÒ P–éb`h¤ÁH®tÀ¬†ÂžÞ*Òrfs^Qõü3’ ¡"ŵØóèH,G †ç´ ›_Ö.t6‡àS ‹mÅn@®qñÌÓîšAbjˆú-:븄±ÉnXáLS›·¥ëi¼!¿"oˆFESs—¨Á=¤ <YŒa‹º˜ƒT$´rŠÑäDŒü]¹“ÁÅÁPån²‰øø9ÅŽOä89òá>+S’" Ù€J@‡ÄkaÿuA' DìlíùoÈS<*¾-8ÿ.ÄàdPõ_ïŠ5,K,Òj¢a¯1¥@¦ˆ&h™a"zcŠW‘ù:Ï#ÍÕÙ…fÂ\çE²ÌÆMõY¿Þ#E@ñJÅ™™€¶µ9ƒ^B ðXåà-uaRúÀ¹Öí®ÝFÞ ‹á@- RÍcý–]] #™…cu£Ãv؉$<‚à l«¡Høi­v±)d“KíŒ ‘h¬à8@ý±Žþ‘ì'ºù&Ö’ãJ’¡£|âgà¸s(B5Û¶Š„—Öë‹­£_3Ov.ŠœB®ì‚Ý'Ì͘7ƒPªÉoÓLņG“ÜÒûHNz¡ cAiô3"9pB:Võ,Ø¢äÏD*qÿ¾æ 6=ÃAÕUn#uÀ³WiOq•6“W —àæštDª!ᣠÂhüEyTLÞç!rC˜Ox¾Ä6>¤`~?Õ~‚:Í >E €jôǧ‡WõáÓ܃Ä÷Ïêû7tNùáËò`žä¯ë–OëW—‡Õ‡Ÿ•‡jO¿Ÿr&½ü­~ð¨<|R~‘v¾”ø6R>œ˜°B/­ñj‰‚:¦«rI°O²8G0:ØH¯ut±º‡@R¥¥Z¸ç.ôÝ|Á»XÖgÙKA'¯ô¹6þÄ ‚Eá5ôlW\rÀ®¿:®IÃør˜i*R"o.YEÞDJè^𠔈I|ÕF+½ÅÙ‰É:žC*@›»À%d  @:óˆ<Ô™iÁa?ÜYS»Ì,f#U¶C¥MQ%4A8“ø`T!‹Y)Zsa]…Ý„~û]•8’Æ §s+ÐvÚ t‘lÚ×?ðH97ã#á7%­‚®Èí~@˜=^ÄH Ș/°à´B“´¦†¨k"†–Pš°! \rDÝ”ëȤd¼£òÇY†uZ9&‚ìÌ0IÝcÛU ,½ˆ)€D/Ž£‰h8ïf•¨Q’¤šR”„ú˜¶;h!¥=g6i­®=ú û°-NÉβR­Á¾Ià~çÚ Øï! Ž1AƒÝ\p—³®z~›Šæ¥Ûqý5ìäGr"­SYPâÒo“ü’­í渷s$>±Î´€I@]Ï! ÈÇ–ÖQu¿2~©`AEÛǤ9ìv¯‚(«ƒè‘ò‡—±6£êÁ¶§%‘bç†P½¥"õ:v´¯„{ 0¿Ö²ñ|A7„˜†µk›þªš’afA‹jÜQÄF-†ˆq´³ýQ%d(º"¡Züfð:”‡’,qJìÖéÜÆ9 ÌÞrþRF%C$Ô{¿Ä¿úÉ=Z]59YdŽ›¬aÚ7ÞÑnÜZes9 ˜z5âÕ²ç:’ \ KqY¶P2‚šã~-11€ 1VÊË0~®g x*Ôĺc’oWÄE.;cɆQ'c¤q…Dc0‘x*Ä;Çb‘@ï õÌqšE@ÌtÅ·Hþ˜Û?9Ãá—@!è% ;áÛ&ϱÌÓ|è\Ç"ƒåØÌuÀjfR0ŸqÊb™ÃN|€”…× {˜ÂÞÌY€åÀÕdØ{heÖÖΜµnŸšûÕV'¸Taÿ™im2‰V›µ‚aÄÙY%JþѬsë`­ºrêfÅçη¶´I5x£»(8J´ÙíYÑÿÏç:r-PÑž^+÷’€BÒ5†I}vð6…'ØÏ(@áâs]þtªäçeLȵ šN@uL„«6uH:£§¡N~Ô£rs'“JŽåÇgYN&¸».ŽPw‹Éìûë”rùÂBÄ"õJ¹Œ˜,-%ú¦j«ÂRbAÕ”ýfÕÞç4ê-9ÇŠ­ðÿ\Òômi}S² ±ü0Ô‰ùî[ÂuØßµðŠuó`ßJ°ô°[ÎU6 Òñr.Ìâ4þJº¿GIW>ŸpVYÖ6/Ë ¦AÞ±ŸÍ‚é;Öuå¨~ qkËãÅ"“íº. ¦ö¤¬+,§fmpÍÝwUW£ê®LSžZ—4{z¬šë¾ç&NªæŠà›^¾@ –1¥Jgtx•ó³œ5ÇÝR²+?Vè¶>â»O‹Ä3Q<ŸvZ¡XcöSH R‹ÄK µTñ~Ÿ¡õ½‰¤¨ù!R…ìm-‹J8#¥Í:®r¢Èë˜=•¤ˆÔ´±Bg =N:†È$¤'¤9ÖÈ\¾›ÜR~±“\â/ pD™­¤\ø›¼“G΋³¨oÂÞ£ô= ¥ËéŸpoMÈ1ÙL7uš;ËùØðî@ôõâ£=¹™](ˆÅÊ©•e¿oóÑÁ[ñxÁ’£ÇéqE~„1Ö˜ävRžµr»¿ì1Ï j¯{€1}#WÂCA{øØÑOnjÃp°ÂON»4¶!|Q;‚÷ 8DÄ+¬}O«Æ—+é]Z1Ȱb8×.»Ïq“ŒÂˆBœUXè`é½vé§Œ åÔeß‹ÉÍ>“gÕ#ÝõÏK;I˜’PVh¹}j“ðO'&8ô‰˜òýpµV¸Š[–pæåDëPÍd¶*êÞqùÊ7÷¹%ÏÚvþÆAûõ¶.:Â6ÖÖˆ‹“€K3«• ßyZHQÕ$)ëÍ3Ò'†X€•ba±Ý›^®ÑùB£ñMDò‹kpXKs9¬h—~dzÕ%ÀâdŒÚmhŠ]NB™Xd";ž2TåM:|Fez ¤N’:£)³÷²EÄÓŸökð4(Þ2 ãèàTÜ÷¶3A"hÓ–±÷¼•ŽDö*ÖÒ5<ý»*ÈG…Wx&ßõççí* æÌ«ó‰Í]z]½Ç²X«“ÒõáM÷LɱZù2ÉÊnè㨣õ¼<Pnöó3p˜B˜µÏv!‘ºeí=u½i ˆßœî*p¥ô!T²Iv¯ë,ñ’¡ùM(«j¢N1l?¼xßKUϾ0fÿ-+P;È”±zÁç˜ %ï\’kt]­#Ê7³Á/ŸêØš6 H1oÜd™&L]" ùž°æ›noÜ2àŒ5+TOD›©D¹':†Bin…J´"×B A–T1®¼ t"¬Z_IY(4ø] Öâð|¥—³iàGêXº®Äœ4ñ·¥‰Ç5²3«Ã¶þßVaöÈYÞLQoÒø`îÏ–Üú’#\nH<íî¼ÞER­¯-}´e̦DÛMÖx% ‚¨¡‘z•ø=m‘qCØå8÷2Dižç€°°AüZ0–î%ùiœ°VÁ(m”ã³ÓU‘ÜòК4imÂTÐv¦ŒÛ¿z®ºÑ(l—dã&™…_v€Ë±†ÄêÆõ¨Ì¬É%ZâÞ)r"“6žöO‹û ºY]H“—8LEI žäi(+÷Ÿt3nŸÞ¸j!’´)WËäiMÞPœ¥G3$FRÚëPÕŠ%¹Áø™aé‘"q¬ Æ|™í•™kŸ0ã0b‰6B`1ª±ê¬> stream xœ­]ë“$Åqÿ~VøoØoÌ8n[]ïî B–¬åpGp·{Z0Üîa8àäÞ™õ̬Îꙹ%„æfº««³òñËç~5OêjÆÿåÿ¿}ýì·Ÿ‡«ûžÍWŸÀ÷Ͼ¦âWùÿn__}xßL뼪«›¿?Kw«« ¯üb'¥¯n^?û¯ƒ=ºÃtÔSÁÖøë°¬“ž—ÃߎJ©i]ÜáwG}øüx=OË:‡Ùþp¼VÓ²¬kúéãŒQÎþt¼Ö‡ßã¯ÖZ¸>øAÍ~pAþ ·}¿µÚåps¼†‹Vöð)|4 <ÕÃÒðôu±+{6ýü»ã:O³ÒËá?ñ¶ušaÛöaµ àgãŵúª¼íUÍ÷S'ßÞ´kqA½Àâž^ðç¶»ôÒÚ/…Ëbà÷²*Ýü€ÞÆÓMÞáôì ¹0­hWN-ôùâxíà£ê¿oþG §GŽ:Í œîÍœ¨‚C„ƒÄ ¯ó/×fFB¯é‚Wðk•Ö‡_”Zk¥Âá›Â?³ Ví»×ðÝä}ð¶|\‚' Ý¥ýYà‡zÏ ØÇpÂËâa©víwå‚w°Rpð|sø9¿š ÝG¹÷ë´º‡„Eß¶‡á^ƒšðÍíÑ„É:çÊåø;îá¡ýóþHöǾ‡WVñ\ÒSƒ1t™Wð»['ç–ÃOGg§àãpíú.oùÅaŽãnÿŽÿ ¸ýñÚùòðÀƒÕÉ¥Œø/òœðFo|Cß^/nAÏñ¿ÇëÂX¸9Ìt*ÚXòˆö]¾/€€V°ÚOÚ*«_u˜®›÷{‹ç¸E 'œ©¾:Ûè‘ÈóÐn$T~Ӿœ%ÓG¯ç5otV”é5üú5_IìéÝíÊFaü×Û*jäê(L™¨× \œŸu¢mæ‡|P~0vg=ˆ&Ïß6>'W>Ð¥ˆÀ ÿý¿‡r—Ÿm¤ík|2õJîÄm2Y1 #€9?Fe<|GÔ9ë/Ú6ÈÁ}À +ºãÖ’dÉ£Ý䲯š«ZV¼šp:W ˆ'´íaøöT« ^|°S[#÷gåhÂêã€dJi 2ƒ™ÃT5îû l aFÂt/ßf’¢‰!$Å_»6ÁzhkTÉxŽO p<~$ù‡D,«×¢‹“|o—|îþélBÚWMwDÙIôŠ¢ãÖ%‘-+g0pˆ ‹6Î]ÖøO‚Ú& #ÜÏñNÉÝîþz‡+ÂBFq¡þ¿_€šŽ ,µ–£ªØ^2 ^ðáR>²ZÁ^• &„ °ò‹âÛ³7Ú4~ì¥ øb"ü¹!£o=aLb3éI®£]Z‘"8íDÎG,@0!;n€3¨No ³%Cm ˆÄ3mùQ’œl‡,lϼ.[4òÂBåµÝ›©i瀄û®þÎ š=Ãﮀ±ÛËdv2͸Ý9SZ€&ã”ŒŽ¨<àÏÁ·úFP `úsT&Yë7u²Q™¥ÞvËlRÄzA>—h ÀBø<á:ä¬ËRMŠCÝ àÝ:í ëÝ2>å«G±ááÓdfΜÅzš=]¹z^WÙÚÜVÜæ·Ò±•XIØ.@VÊ€µw¸šh 3#€¶‘Ì@æÀöÀÆ›=Ë‘Q!12ü[ñꌉ5È'2bóÕÉ\„æâEcÂ6‹ ИЙ°€hÅ»ˆ5Ø¿¸}×+)"ÉÈÂxŒD³ìéh”«{j¡pË ÷ÞfÅ8ôÉÓ¡ØÂ“÷B|ÔqÐì}·1,`œOÁâ„#ûxX-!|Dº3ƒÅبêõ®…¸·m†ÛÎwÀ•}³$†%;’|•ï£~U«Ñ\>¶èªš¡WiEâPš€–ʈHŒµx Šq­ÖEõNMÏ;ë ¤¾i>úM†ÈAÿÍPTûö\;qEï@üAæu¯Ýzp‚ hü‡1G®c4cÇ& Lt_ LØ¡çPÕË]v`6Ä.çÅòSˆŽñUn|uVÔd'÷\Vb†DÒ)sŽœF¨ Õ+’ðS®N²CP6L¸2µ¨þÉ…’7¸^ƒâé$ç<³ ^ŸgìZ\"Ó2[£Hè­DÊ:H$*TVÍ6ˆQr£p.‹MH\/|O)F—w¸+á¯Í±qkX¯ËÁç%`ÄÓª'U5cä2£©¯ƒÁŽuѵÁ%[—ÂEåÛG)\ÄçKáe±`:ØÏEØ´ñ,OÄÌмúM’4à¡•㑯xê.P?Kò~’’ð#7HŽv-õû2]u¿³|µËï%£ˆ7siŸOþŠ’ß(IZ"47j™qCE¾h¾ÒÜó¨JD­xTvÝj~ îÈÈ©d[p§ °ÍÕÍŸžÝüËŒnl]’<ð1âöm8&Jy:¡{ I Ìñ¶š$ôÍüƒýj³9%dÙ´q@5*‚‡¡MåÞ Âã  4‹ü¬©â)ú0½Ê±ð¡»…¼ž].vµ À´‡/u¿K† °I[$~†ZFlã‰Rtõ¶Ó7Ž¢=¼vž'TÝùþÒ€&V¼Øª öTH%Dzü5”Ã/È…+@?¶-d ¦‰­Ï@4’ŠË,eBØL Ï4íEƒé‹Š.Ó-G‹Ì/?`i^àIRX!I;l4?j!"ÂìAVÞkÄþÙ`Óx×v¾àÆÙBÁÄçÿ—廆^Kä“Y㑽Gžö$È,]mÁ¢E'Êå]KUˆœ™w‰.Óˆ{ù™m UÌí³ÀEÍ{è­ÅbŽul²Áª ;n3­Öa±ÃÚVƒá÷a "¸dæŠÐpD“$  À}Ù"1ˆý@eƒÇÙ|ϒƺ˜EBm} gìÀ0lŽ ÷OL:¡žq&j?²•÷Ý“èóQÍî/*&%[]ÊcÛyÅJ^å ½k™C<ðTؘ‚Ì]Ôúël-üdb-Jì°‰dŒRI‘Vû7øä½ùEã²OðöeÒ-WޝOXõõŽODƒÓÞ$÷%û¢Öïx`AðZ¸wdfÔ)Þ{Ìõ<™Ü:ð@ÁŠÕ\¸àñ8D>NðQßß Ë€ÓžoÅm5õ9¼zh³†ÈBMg‘ë¼æù q5Máó܈jº1Ô ª“»ÿL‚',;0j¼…-÷<™œgaY$t³<}ìë* Úª"DgÁü´„ÕTÞËHÔgÈ0¯øFðã‹ÐjYÎðãQ¿Ø3Ϫæ¥$³â"ßn0S" ÷¶±­P¥Ó=½ƒ‹ÂqŸ c–ßÄÅÇ®Š­Êþ¦<`€˜”¯`‡l/t)ßåĆv‡¯ÊOí$ëÕDŸó¨mI4ø„ÄŽõBëáÿZ2ð¢E±ÀÔZ™èy9ãóA.9™…ɾ3ÁµÌcÚùNOr´áMÜJ1Ów¢¯&øøåÀô¾Ý,–у~‹úÉõÎFW†—fÖ}\ }O……ý4UHG»Ên2¾‘”âU?©,ôñ£âÑ™•¦.Èsºzî®( èn_ƒ¤÷É[źû»Þ°6Š6E³kÉstbÒxÙô&{&gÙúKƒ¡±L  Ñ·õ¾¶‰ ÕJ¶P"_ð= ÛÈcUû>&ú² €tT]B1ªGêxJ¬G΂.äUÊÊÙ#…ø¤ÒD$7;zò~UŽ-(Ÿµ^Ÿ¶zNàÇ}éúòX/ü€Õ«špxBss ‚5ãFþÚN¨±PÞ ƒÀý¤¼*o¤ [³ÄøÊ6•dB¨ä"õí_qUˆ/h™æÉ‰ º¤p}GCVP{ÆdÄ€o†—>]Ç®'»ÉqäG’Ùæ½SŒW=¯Þ*5éÒþˆdÄ`)~§Rééz*WüëÑ!jåç¹he!‰5)yr»Ý¦©,¸æóºf,âe³6ÞgÑrtJÉP¾ärel!å•eõ-ø‘%PIðºaªe5£zc!EAü†ûbpYÏLœgŽà ¹_$x•óŽÎwš9¶§TJK2ȵ–„DSUµ¬‚ží¾´lk.yŽ€Ö}8Jz©ÎùTG —ı­Í p˜×¾Èß« ‰J;«–¬\ÜÑì«V ×êò÷qe|/ê,""¥ð9‡.ça KUQåšYSK¼R ;¯’ ƒP¬(¿Œ›¡m†SY™—\úμ°¶4±U 49!ÅC‰!SK¡^8@!‰aBÌë]‚k\cÊKžÇÃ9®*EJ¥h4Á~›æŒÐ¥†yc…5Ý"ª‰ºøo²ó²N‚ºËAb׺Úò>? Ø„€$ÒýA¬ÎËV[w–‚Éî\$¬iõ1 Mí<Ÿ 4lŸó±ÊcÁraKñÙó®žéq–!šÞÄDŸÛ6!b‡ùÖùo‰¯¨*‘CçyØH̲L³›r©Ô&zYÜuÒá;ZHÞx/ ˆëö]‰åY¥idUÕmà(d/öÙÅëÔ ]Ð)^D«î^Õ*·V·@^üÂHWÜ4Á¤Ãjki›ö”1 ½z§´¿ †X9*gФâ¶3·MáR£\[‘àÇÌÄ1W%²èD=Ÿ”ØãMp«ÉÑMb:3 °×Kӭؘ€Éèg !Z®M-U¢XL'ÌŠ›RÜþ"}Dõö$ÍTJª/469©pR3åë‚‹åÒö|».Ik)9·~̶ï2•! •€.I>W%üm6Ð`«æ‘¹m­½ÊPh P ¥{¢Ñv¢¯¿šƒ¸¤s¢¼n—˜‘Ú­åéÚ˜vTëÞ´$f›#‘¸»Â¾ p­=ÿÐp0“×µ-9~¡ÍÏ:#dPñœ¥NúÍ<…܈¯ÌL\ÒÍQäq&òÔ¯º«Ô•ðÂUÇ‚Æ2MlM­ÏÃ6ß äDï¿sá°ùûnŒÚ£Á²Žäá/¤AøÝrîZ»quÅ}½èrðÑO ˆ,Ö+2Oœ0h!¤&q±Ú¢ÉMT \ûïÇ4°•Uf×~)-¾­n½à *ïÈä½õ‚_ja²O£÷c¹°P,Ó9G.p)7¨¦'U!ÃÜæT ¢>]3fiªqXŒ"bEZ‹¢±Àqލ —Å:±•ägü^Øû=Ù &J½žãt¥KÄþy6,âjÓPLµN9Û«™ÉÍ’Ú d—&Ûá+åaE…èTgr ›GBòb¥ºn©Þ%Û“HnOGÖ ßŽ£¬ˆ¥a'][xtWXì•×ÇÛeÂÒ?)«ñ£Eï[SÚ%jõë¾SãÔ\­{»¬Ái;&¯õØä˜J*C»|fS&[§RnÏò §×-Íf<Î6*{ÉÅyÈc•†±Ý¼ âVñ®‹éšYbê }‰}Mm%9·ëXen%K¿ Ì“€ØJPDˆˆ™hÍY gišÈ‚Â4§â^xXB¼C†ŒiÚ¤IÜ®¾‰ÑפoÊ<\Ô:>ÀUOÊ0ôwÞÄ• žÎÈ¢Ä4fܦZðÝŽI"dëdÊãM‡™˜í RhXÐè6fºÏ—'b… ¤AÌPÞÇ×b!&sC"‘¸Ùû ¥•ƒyéÀ(1!µçšãœnò('2Õé’2ÊçÙ»:}ÄrëC£qz4— §F쥓³œ¥À¥K‚ HãŒ,g™ã!·Ÿ<|šŠã#V&CÅå°T(Ê¬ÓæH𔥯f#_¾ã©§ ; a'ÖXPeñâ«2¤K˜J¦ µÚÌAÛ‘¿w8I<øEm’î‘\Ãþ§MÓf¸"mKØ7Dæ* >E– ±–Ndë’!QúÔ}ªìó.Mb黦ÓÜ4«Ø*çR,8Â<,õk1¿‘ðmè*Ч“¡«²±QÚ/OŒWºÒt®v•—DB!fA>|Aåâ`³SuoCÿîMKÓïjÅÌ;{±µr>Þ/Ö©P~(Qá@XeÛ§Ï£übàœ«0!hYœ…Ä짇©¥üÐΊœ¦è‡©­ª ð”»ò˜3Ñò6q,thŠ‹Õ4Ž ×HH„Ô1H-Æ)ІnóÉÚN;wu‘QìE•rx¸ä§²©ñBp³ŸÜéÈÚ’‚×䓉:/vR ñ‡£/H¢c?{~£DTåÕ‚é³Úêä#1\8Ckªç^mÄ…î|m&Eß ;ˆ%8%acÄ” ±nŽ›‘`ç§Æ“Šîö·.>Kq@x Û—ÚºP¥iã“xfŒXkKëí¬ ô È2*Cç/¢­uùxÙ¥…ƒبj23Zê %™õ;;0`ÏQ@$ɤG®`’\AÄIª€³/‰—G°‰§&ŒõZÆ¥‘ŸÔ gp¶k{µ£]ÙØžÚ›Òµ¯f·”zH^4´Ìc ï×Sþ›LQ ù³3›–ÆîOͼ'Þ/I¬Ö;WN#Oz½ ûsgŽ A?1ÅO Šu:ÅŽeËçúÈÎ#ŽnÛCGx¿ð*íÅ]¤qv2²#`Ra‹!ûïì|´sðõïrÄž)±0%MŠbºLQ¼Ûð‚Ý“ÆÈGÝx–5E#·J31,;Çþí0Ï®Ž/JxR‰/ÉDþ¾ÿ$kyÚ:mi¤[àEà…œÂµÜž˜Ë±Àx¸:SéŸÛBš©/³H͵éuiÒ4+1²*ÙªøÂšX ÙçäeR¾? ûh(%b4`Œè8¢ÈŸ±9ùךxíïØ1‹w¦ÎÃbxÒ&9UëÅƒÊ èǹÆõ\Òù]a#ŽqQiÄÑ…’·•qjâEñÖsWÍ©¢­A¸dªÚ$¾7ÇZäÊ}X’·‡Û}¤À‡„bXgnÀ«NÈ´ë€JÃȺ¿RŸ'vH´°ŸNÆÄ¯,3×a|Õv´P{3? )^BCÀ@@ŠÂ»Ð ‹bÆfr.jÄCÙi]×¾õ]Ðò1-ž0Uýø´b#+–Až,6r—•A"¸ óîXö2Fn`[=$ »Á›]J!u`•‡eè#¢Ÿ4%¶î»•²ü¡(Û6í׋ciŽK…ð kóÅzj|ô²øwo®­Ó²Ø›È¶!r—Ûõì5ü¸_®øò~¹D†^”P#« ÖòÆ„e²ºzéå?\Õ狇ÔbWªÆø:²EËodÀ«‰fQÎRL$•åÇàYå¶¼¥Ôº‰#ï>kî5Iª‘¿o™Cò µ5ÎuÐ6Êа0©Œdà>wƒÈN/“ú„ÅLzE‡5í}íÊëº8< sñœi[}7ÓuàÝÔ¯ÅR†t5«•¦ð2G§DÛ*à÷7Ïþ ÿûß÷endstream endobj 141 0 obj 6657 endobj 145 0 obj <> stream xœµ]Y“$Er~ãGÌÛVItmÆa˜Vˆ=dì 1ÃHfBÍ44ØÂt;Àê×Ë=N÷Ϭªi £:+32?>?ëûçËI=_ðßòÿ×ß=ûí§áùýÏ–ç€ÿîŸ}ÿL¥ž—ÿ½þîù¿¾„›”†+§¸DõüåWÏòÓêyÐÏýjOðåËïžýÏAÝa9ºÿ}ùïð„Qì oO‹…‡^ÞÁoÌ)„ÕáGuŠqµñð»£>|r¼Q'k]Ї—ýžòUc×çpUE6,¼ít¼ k<ée=üþˆ·ÂÛWøÇ”AV­ìáÅñÆÁ 6:zÃÀ ZŸ´¢s‹'­µ÷‡¿´é½jŸÈtþrÔôÃÀm }Zïxo³ð¬J«Å§ÿ .R‹;üW Ü¢Ÿµ'òˆÑwZf['€»ôññFÓ›pHòuY´* ?Æ›r*7fǘçóÌc]}ãhéeåoë†û¼·Þþ9/ÖÀ#ý6Ä¿û“7ðÉmôAÁq~~̯†…ÃÉÚUá t+ßäõøÅ¾Ä½t'gíáõ÷T{¸…AÞôƒ&à›¿Á#vrUéÆÇþ-|4+Nn…që`äé»rp&¾ƒµÀ䃷iÌ`ž°u𥠆 ò-%ì½DF /Ó`’¸Á˜Ã0ž3'ܰ~ñ×àOqõu±ÆÀ, ø/Ç›%Gô‡oêû<" ½žüZù°Ûn{Ó(æpß_õ^¾T} i^Yt6í܈»w[¶Ù iü³ ÑoÏ÷à›Ýûx?àrýÉÐ/¿iM›O|€£÷Ãüó^¤-\Ìáï}pÑ7eÕ7 vÓ/:/¾OI½ÊÃ+à3òÎÇNx¸< Ì%ÆúЋÀ´w£^ŃT'ç‚×õÊÏYf¨…ìü·ýà ™ôÉ“í¾2«5xJÁíé¿ã_"¼ ˆzQÖ~:šôµ"TB(÷ç.ûÊÕ ét2A0#ŸOqš2½÷ë>¹/óî8 ²;ýB:A${4t:d6×G .¿éÆß:|F£p™u‚K/|Ìt¿¬§à+Ý3¦­ûñ“Ä5Èâo;ñ“óèôŒ;,,^ÕsE]PÞ¡ýJ¨¸S¶Àoú{@úÁÜa6Y? ¸$9ÓGϳóz‰™ÎVTXäÁ¯û fÉ;”xÄÅ• äŠò¬sªŸf¬SÎW+Ûà&„s²òiû$/ãƒu³?|‘å³ÓYîÃÖàêÉÓe·ýbG²Å·õO}–o2½Y3×u)“KÌü†q¥²ÀÛQtM”ˆ'÷ÞâѨmîÀótŠ_¥Jí±Pºõ£Ž»«ëˆgyocôªŒ®üñØÇ$4õØUÎáu¥Ûö»Á*ÂïÊ*`Ü/¨°NìØâkªpÚûUÂ^mø™ƒ‘+6Y¸©X8W 3a9»N„•tÅ]4<éËv eÉ UG!Vf1P5 V§grÂ1ûè=ð5’RèîâáDQ§üþ/ «3 ¿6VËäCð,uMKÝ xÇ]Z9Ì#-Ù»¼|lÓÐ!ï™¶(“'ÊÂ×ß•wyyYúdM8^«Jê|Yµ8Ÿä\Mª…,÷¿«KBΔZ~…·/02¾ÅWäùéè,ÈT½R1Ñ5kÅB_t¾ê²)+Ñ$¿8«Š{¦¾.Û²ä,f#–ÁMÝ.þ:%£t*¤+«  Þ?H4'1±Òà1v6èw£®´!‘6Uía:"EÄÝZègO€”€‰Ë$’Ht#/Šâ,ó°µP†áy‰6†ˆÌ²‚ÏàJ1Î{+`¿z.]À__pÿDžþ!±…Žþä›Þæ«7À[q!19Ñâ$ÄÓɰ6b±¹¶K’P€Ô丂Œ±"æP{—ùÓ5)h‘p&Q+·‰×£Š“9Qöj6'P©˜däÛÎ6\YóDâ|OÔ›b<.§=£¸ê£ïŽ`Õ<=ë":×`“ ûY-žN€X¹¤]ºw1 ³$Sï•M›…I‰`=Æ™V9Ô¸®eÚ TÛ%s5£ØßÒ½L/@ö"†lŒ_ëD¶°RgvŒ% ]Xµ&Æü9ë0ÅÛtKž‹[ü  Q¯%vW q!؇ýjr P!ö> Ó|(ëïú 6àT×!õÆå¸=Ñ>eQÇUÄ´ùu°1ö«iŸ!ë-ÉÌãÖ3àîÏà û>cè~ßk]†#"SJo$!"«ŠŸ]$Bí‰^›$xT³DQ’zFð³HèGƒn¢»E ÁE‚3>1JñÜá,²³ÐY_öv4fª;,,ÀÕF]5uBÙ%Û žøs D¿‚¨Ñ²ý¥‰€"±âj²Ö+û Œè‹Ù膯™e¨4'ÐUÌŽbœ1™i­›&‚` cB!o¹*½ŒEÊ7ÈÑe8ÓæÅÃ9ÐcIõÈ:,LR}•ïIœÑƺëï$‡>ø`“ ÄÞ}Õ!„s ¶mõ*—èlÓBUYênAíªr›t6•ë©k•°Þm„‹v²³NªŒô>ŽŠ'@'C"8ÁÙNØXo¸áŠÊîÎæw…L¼ª¶˜ÑèwO5ò~ÚkM‡:VÝ•®°ñö‡<[ô)½¡WGORÞ7d Á¢&ˆûè¶ìÚ¼’ÉŽ66$RïLô}Û¨*#Wçýӌ䴦Æõ`n%"™âDjö7ôÊËóÊJŠå—ÓIl äÒg`÷¶±>i“¯uØž#4ÊÅÍã˽¢HªÅ&7{™É ¹+–6CC“}ƒä|âc©#-&?ø_ð LÄ®Ü I.%Y{1AŒáŽ,EaO$HA&88Òàmÿ(rç¥2_⨟S´EÔè¤(A´5*¢"Í¡A_þÚ Hõi¼Câd„+#A§aòÉ»r$žQl²ŽG|‹¥šöcÔ'ÝÖ@‘“¾Ü¥ð|Ûj3Õfí+B^ˆ~€ÕK‘Õ6È™¨ ✮&JRUŒŽº˜6Ó¹4惵P|äbhYG›,Ûkš:fßê`&Ôo€bÏì^ÇÝ‚ž‹_ —Ukµ{d˜Ï·ãQ[ê¥Nþ‚ºt:`¥•`cVÇRõœðÆ)™gË·3˜¼€­})!Y¨`,h0•ESÏ¥+Ø¿uÔd>ÍV|;ƒ¦@ƒ,. ΊÞÎü®È±K¿óE\t@–g½gÓÛ‰áaË™…{¸™a3䥥‡í ƒ1"ÙPG»ˆ yññÙɼnþžñÃÜ™iùÎr­Ôsi¯)Ç`ø"ßýGkH¾ß­ÖxHÚ;ólM§a¡#’!§ºY¥’%õÎè }ºjŠ_Ýsçv´ÌëÐTÒ"¿&«”´#f!*îT†nBD427_›°_¼DÉ\ÐfÏVÒ-¾$<t˜ì‰izÛö즇®§•¤lË!ùs“Z“ƒF] Ù0•Þ°³ˆK!Æí"¶ ª¢HvÜDÒ…d Iî<2zwФ%RTàl+w^ ºÄ9‚CÖ3JŽ’NgJ¨ìW"Å’Ç¢ü1{1·*uK°Ãñ@~ËxcÞ·¤˜!/à“·ü\·óF+ã‚ ?‘0-ûPÉ!æo癵 0È™Ý> ‰!ÕÐõ%Q€5‹š*Å#úA]ŠÄeÛGwEòMš‹ˆnv“oîÜÚ¥÷DžG0Ð(raS8 yï¹${´¨'D$ÚnN½^¶"åÙfN‘rQÜSŒfMr½_Û'^œJþ0m¶?æDºd©: :’v’«IÊw‡¸Åk4¯•»Ên¸T3Ü$I¹Ê[Idk§\©œçÔT3 ²Öˆ“u8ævîe™Aü²¬'.'‚MôÍnQ7%d/¤ãћɠœ kþZÙ3Î6$§B’²&ÄrÁÙ®Ü6û€«7jœÅ~a¨2fÁÃÎ&«2àÑ«T.Å95Á°,]¤Þ¢¦ëûµr«Ó+}›AIµÞp|¾ÛÈ0-9Ö*š’s——ÍÙqÊçç<8$7cÂò"Ò¢:+©jé9·Eùºž°ò‹Yžú¬†¤¥oç’Ò>¨îóRI¼ ¼šœ¶Lßiº´*! Ô¬Ý[Å?X]hSºSEˆÝ †?g ¢æ¦<»šSmVòÐ # ã¿‘D|U(-ªŸ@˜TŒI ÷sÀNÊý¥Ñns©ª°mŢЮ‹]sgÈ«“!+^«Cœ¦•[—˜¢—“rÝLoã .=ßÜîÔ{Ç ãýd³ä¨g¦Ê´ –r¶Ëƒ¨Æ/Ï%iÖà®Â¨k5PN¦á‹=-WR`™ªî€ØRDÆìÝš]ƒòbÁ&†NB ¶Ì.nWÔÛær¥ž¸¤×2_ d5™•+¢) ›™ËÚD‚§‡¼UÁ0†¿ ˆK;u>Q›áìÔA þ-¹f†$Ä׉Z?”šÉ®°j¡`ƒã¸eDCÿ‹x¢[úÕ\¤ÄŠ®žªdÑ[Lô‚bƒ”Ç%ÕÑ\%ï„ÉO^Š”\©Ú°zókiç²nÄñJ.Õ¤2r!z´µrk{Œæ“Ò^ªðvøÕ¯‡ªR¥Hà‹,ûÆx­!CH „3^·V繬B™'ñÉÞ&§ß ŠÇ“'ŸH¦8©\&)Ù;å¥Ä¡¿6qWq[ŽŽ˜dp÷ˆ}¯“!±²uÌ6›C™Ä:Ä8F’ãGc6lîг>ÇÄ*ë56èÐ)§-›xî\‚]ðô˜!LUíÚSU°+.%]¤’n› wýøÈ>Âë’Bi€ìtZÐX·&79ñ0ÐåWÇî4(#Ù½hæÅ€™SË)8­V {ˆ/P¾|2XÌùÑ1ê,¡ÎJeÅ“ÞïX`)> Ì9 &¥Uáò­vRa*ÇÆ¼É^ƒï ûº>ò¶¿¦ý#ÌÕœuR$£á½1ÔmÞ Jê5»kï¦öI’Òo,g‰8øzë$r±w@ ð ƒÿlÉØ»™VÄ!yq!&ÚT©¸„¼—àˆ™ëñ¯•ˆEHëeV\ÿ: ²;ÜÞìŸ5Ä\$;¹›õHj@|d…€[ a>Of).zäÿ©GÔ¢º­ËƒŠ5½l‘}‘C$Ö¥5³ ŽþvLvž×°ƒ$‘ë|޼×áÕ|Ú¼[E‰>âÇ Cðï§ò™^2éWBz« f‘©x£Ÿ‚û¿/¦?ÚIÉu¼xvéÿ; '¡k(&ò¦ú ÍÂk Ò$ÜA’0J´Ð ­¥.µ$I¨®Í›!z)”Ê$†¨<0úðÌ?ãpËÀœËRÏj³¡Â¥Œ°’¹áé~“ÚÓ1‚‰[³Õr $í/À+sj8r¹¡¥†ÿ#sˆ>Ñq§€£–E'õw&/¸ ‘m(¸ebÜK½®CƒL¹ÐñL‹>egœä/â§äCcÁöcClëºÛ­;‡‡ÜÌAw•e)È_G÷ÅWEªCf<_>¢`GHÅ;¦%Èhü%1©Q½¾#“5ð¶J.‡töDSzh¶¬2”@b$¿[Î$ß/—ùsæ˜SÔEW |ŠÌP™…çJ=®èzÉ9Š¢ ­‚ª]‰Ûd…ÂÏŠ r1Ì…mh”¦t>*C“™{4éñºéU7):Ôßð=ñ~KÊ*Ï·ˆ“åèÔZ)hf`42iÖ€¶BÛ %UÜAe,³²¿r¶Y.Ñ­ìÙ¤öBj§rIC'Ær÷?ŠnKq»o#C“ 'Aú0¶f=‡ãÓëÌÕ¹]µ>ñÒÜ.é탞åùÞåˆF½*÷¯É™w,µhˆ@’¾SÜ] /þýÜ“€,i6kë ï9þò^$G/O•Ì]…¶­HÃ+ÞË–±Uîy tâdj!é ±™M^?×,-ŒwÈBg9;eRÔ¶ˆÛKÆ}Xùˆ…ž×ßàUx¿‚ɰã0¬€ÉK›Û  [MZ{±`V‹ŸKñF¢8émçâ[ôÖ šØ¦ãOhi_"3¶Akjm©÷»vp¢YƬ'Vß¶¶(K3‘k?LnJÌÖ[ýÖ–0¤R›´²—y®ûØv=,l.è|è¼,–SýN1ßÛo€º•U%µ­šàÅPJ+?ìý ¶KË0g]ne•ÏNϸWÁ1G>bÜ«£R˜â’åãÉÏs®D;)q´ÃÃJš@”`v-RÞ©ÊØiyŸ*ª{êj»’ÁЂ‡½:Kgd²$(È?fcOvˆì &îÞ¦°JDÜñu-¾`IÅÝ¥´ê4ñ*¥è•míĉƒpÚм­¤[“ n£C÷yìT¼Ê]«Õ]»¬³w (;+sþsyk¸6èš–¯:Í9µ£ä«¯Fð EˆrýTº·*/Ä™¶•æí§ï8T›gÏé{.@9ðõ_ ÌIaÞÑÙ˜«>†´pB|LeJ&“‹@zWÁ¦³tK€¥‚smáXm1ÕëZ8¦©²Ý‘[ÿ Rƒ¹¯Žõ×xòïÖ¨$ÚòDâhwå˜H9c‰Á¢¬“¶®äqšÍQ²=½oø¾Ïbe ¸á;gñ‰ÖlŽ ä¢W–ÏzéC”‰Ð}Q~Ÿƒmê÷Ê] D„·4æºÉ^j’äÌ Ö…ãÎæåØUu~›@aþA±¼wÈ&cî²R±kC‹æòÌY=çSõè$5B²›î^~¨m¦îû›p‰“›¬1Oðbi´ÌùÄ @øº5!ÖkAUÙ(®.˜¨^]Ë » ¬)UnÉ?m#ˆèuI*KŽJÌ‘<д£—|«èÙñ¡ü4ÎÙ4]ÖäœBº9Øø]âW§¬Ø8pÎ …y“}ØZ·ì¯Ò÷{cùÞ@§œÌpgutP± ÓɹRÒ ­XMÛì ÷aÊù¸R–-PS«ý»Lf¤æ^¾;ÞiÎDCŠÒ0¿Â à"¡ßT­j±óšðCmmľVÃou‰±„iy—ð* ==«¹ A .ìÖ(Tı¨íŸªqÁÒ–›éËÒE|§®ŒùÊI@bû®/·è†u%ÕÈnˆKí©¦í,%K®ù$=ü…¿â–Ê+7²žˆš!ÖE'kR}!¤áÖ W§be0ø`ê>H¦ÐF“ϲ—\}\Дm/¥j ]ÎF¥½ÁyÙX3Ÿ\n%8¤ù’œ‘öØl ¤É_QÎø®¿#hGaéo R9Ó¹óPgý®1È‚È[1>esw¹½–BµìVÛÝö^: ŠýÒ>ºÕìÕeÇ;®‹y•ú²Jþ:ö„µ‚¨–.C*㉶–ˆ•ô’“BƒzµSÿÅ'b¥íº¬}ÃHëÍaÊ{†_M´Q€DS±Ç…²B¶ú®?ðR³é.—%Im«h*ùG/Ÿý'üûÿfxsÃendstream endobj 146 0 obj 6799 endobj 150 0 obj <> stream xœ½]K“·‘Þó„ÿanîvpŠ…7p؃%k×´µ¦µ¢×޵÷0âP3²I)‘’¥_¿™H PÕÕCÚáÙÓU…ùøòì·—ó$.gü_þ÷ù«‹Çÿí.o¿»˜/ÿþ»½x{!â —ùŸç¯.?y7)ßLaâòÙ×éiqéä¥õzòòÙ«‹¿ôѦ£œœsê ࿸òó;^‰Ikãäá÷Ç+¥ü¼=<ƒ“óbVt“Rp›ò‡ÿ8Âg9<Á'½ÁÀ“òð+øïs¼O¾<^Sº)ˆÙþ÷x¥ãý*Ž'gϞ⛤”ÖÂÐ𴛤0ùý.ïS^‡: —gᬣYx¯hÒRhœ’zÒ&°ç}Ä÷;Ì+ šOR0q#áz—ö»:Çß— O2LÎJ› j<ÞûÏ~ û[Áö ˆ;ͶêÙ lL;’nô—BOJ[‰÷]å¯Ô<9Bº_ÃVÎNÃvM°èYàyúNÀôLÚ˜ÆÕe3‡×° 7OʇÃ;ÀÀeÓÞ ×Õ¤LÜ‰É +Õá›øR¤éët§°úp _ T;¼„;½˜úËz½>ôS$¯SÖÔáÅá>Í_ÛÃ×ø¥™,Üšæ¤E™ŽÄÊ“2À„OŽ@!#…×iÓ½µZÅýÃõ7]ÿ Øt$¦ÕÚÅ]DZ€ê¿KÎÃuøRIcùRÿŽTJ:x-ûúþˆD×J~€W e]`—G\ `ÿ?¿xöË¿ËÍ0»wðHZ $tYœÑ&cãyб÷uNÒz|P3~ðîNÄ FÓ>:áé£tb|ýÆù†Î³7sàìñC%*›Mª>T–&Ø—wõM4W¤ÛîJà³Lô»©âP÷ ÷JƒîüËû¤ÎÑÞ¬2¦² ÄflÔ˜ ,–A~6Ü5&0³Ú¡™å½®OoODž>Ç2Ix‘Vˆf:³½Ò*šªÊTã!ßÔoãÉz…,emð‘Ía£…/Šôfäk°Gò 1Ð Ti3)™6Œ¡üâýΦ%ß&¹M`,‰ .Æø(/ }þ‘ô’ªz'1YfxÆ×‰ŠVÎñå}š1ߣ伸ÂϺ«Ããýïëý/Ë+n*ŠÖHHêwI'Ò_õÓqÝ"(™%Q*ʉ >ìyáǼGvÖŒI[Ùa¬²ÊR`ôÀÁ3(Qø@ÚU€Êv7¯P0k­7ì†kä‹oE4$¢D±.q=ž[ÆEMÙÜM¯a“x‡C˜Ipã1bèú0³œyœàÙ3™ç»ÈÃ_eâEÇt´Or"½©B²2QØ!=®Ôÿ\þb’Áö×ysØg ªlýÈDïDÁRFuk¸Þ¸©ò×#.ÍNbn„±Œ÷Ž.÷6F&£»5<¿©¢ó¾ÎÈýêŒPVòF)A:µ¦äû£Ðn øÈT~ßï<ÊË#´àÀ¬mÀzŽÜ¯A!Gäj ŽÄ½–ÖD^ËN˜–ã0ÛrWÇ©¯D( *5åuF9qZŽÉÊ .åÒ ¼iWó¿—HˆUQ`­pz[0HšÀŸJ²îO¿g¼aÂ}$e‚fTVÑǦ:…ú© ­$YšÞM’Œ`á™%ðêVoB\}½Îfò~p«à\X•ufB%ÜÂá ý5°@Ä*–K: ›æß™à½æ(bqÓ 1vý±Á6ðb$¡I$lMKµwŒ1B‘€?íkÍU ê9K2(ý† ˆÆhÈ$†ß‘ÝTÈÕ0d¶ž?ô&Ý ·¤ 2Yuø# Õ¢h|ñ,ôI¸Æðe½µ;óÙ³‹/.Þ^*5Ù°ʥÓý¥±°mÒcPé“'Ÿü×å»oß¿¸xü§Kqñø7øŸüáSøçɯ/ÿíâ³'—_¬›Z÷•‚M¸ø`ñ5“°)àôPZ®¯Åx;ÙÁZ,XAÙ¬¥7w¸åiLR£L=t¬W×7bâ<§Î÷ëâƒ6pKwŸT°3 CU%,P& ?²ž¶S(S$ãš]£ëV UÇÜ´0·Ìµª¦lZÒ°µ®Õ4e˜.…p æd†Ž´HfrïôÁ БO¡` 6*Î}ÉØFÔ·ÙYœÝIà¹åR˜1G ×ýBd!ŠÇ"É& ¥Ð¡Ó¾U§Œ: *¦îàê~É8£Ûç0²Ûy2´Úãÿ&]_a €(úWÒEõi5û}˜&š ú]Ä‘#L}šNR¸8‡¡ "tžå@@[o›Á¦üf=Ò õÓ›Æ`ººS U¤hÐŒAúŒIð• 8JgÑ´“Ûtʉ!}Ò:1- a^L#¼ ~ê9bh£jd8 ãaŒ¶ÎèYq?7méýP¡¡ÎCÉCÈq͵LøDÚ´`£ ‰ÕçRŒö#9e”'ã"<çr`"ÚDþœLÚÇÝYµÁ*ÄFxÚ#Ï‘—.äƒa­O™Ørsü„xËhF„õq÷,óÍåÍì¯ù°4Ÿç ú.û³1@H"Â\啨”wðʘ¹2³Š©£ú¿ý²rd¾D7ê…ùÇñt•-•É›®ºp ³ûD|€ç\[á+¹96Ü…h¤ƒ½ø9I×vlˆ»½‰œ­qîù“ÛÞât¬ŠÊ"HPÁyíM5ªI›Ñ“Àz–1…Áßsg*m`vƒØŽ óF86½½çɵÔ9 †ÔSª†aà#Po®þ‰áÁÿq 48¡g+â•ç/8dÃGz«b³âtŒ¼’6‘ä Ò Lo*ï3¿ý>¦üMo^%œh­@Ü?{KäAj½ e.t|ÀõCå tvÌ;x³!Y©=P(”1&J~vvvH… .FVÖ=µõɾË<YÝö °HÏå 7©îbžMW©ÔC@f,¼ƒAv˜Óµn2X~ }rÐkÌógñ™*4¯hi­J'õÉ#Ù?²HwΊÛÃ}«En*cR\+;Í!œ X·~µÔ‘>¦5h¡»Äh…ãì…Û£æuÕÙÀ,•ØüŸšE‡;Ì1©îŒ­%W1ÈCÐ%NæÔW®±§LÀø›‚q4‹E ÌðS°k×À£‹ü@JlpÇ©QHC·I¤>Ó”–¯ÇBÄMq`óm«š"Û²|:ö^ÄðÞJ숣)$ÊZ”©aU#ûò0°«ÕBç#6544¶¸Ù¢KHk•Ò•á™A]K-ßôKg®qeœ®Žô¨)qÕz= Š"^gœ²ÉðÉ4½3þ™c­‰Í+Æi£7ã 5½™€Q1R´ªÒ5¯ZÛçÅFbr´bcLJ96Á+šË×–gj%ÔZª”HÓ Ì@ |'”PZbRJT¶á×Êù{ M¬×”gd×2+1ØåEî Ô”+÷ö¨çšL…½÷Ñá`É»Œg › pβ]¦ºõÊónRT¸Mfœý&ç7ì„;eI[±²KÏ{y¯Õüd-Ƕ"f±ÚˆÓŠ­ˆ)ÃX)W·(ôøcîÇs.sN­ai­XÔÜ´Ö„ˆs•BZj-pKçà Š%ÎaéâŒs”Ö‘vfmÈkSßn!hbG19™‹üf,ÄøÛðOZ[`»51Þ²y*!¦“yWÜjº_j ÌÔqçuoÙÕØtfjU˜s–ña~T –³'ÊõXæ$fqÁÉë«ZO3ªÁ:e¹'³‡ù`i‡ˆ¬KÖ5…7)ÁÌn~Ër¬p•‚ÿ6×7ÙÀ‚®\ïF“TaÂvSVØ‹Â@dÊqÞ‹ÍÁYoþDuEñõ2╹ÛÏ[œ]Œ–MXúζ‹óIšj¨üáõ¢È½5Tž£º$ª'ýZÎy¼]hw’¥é¸P-Ù_±M¼âéͼÝÕF¢ø:ݲ3ß{(Ée`ʨ²û†¨Î û‚ÈÖKbîrhQÒîÁ²6Ol™ª«½Øª®NE–naX™é²r ߯=p$mÛ¦øŠ ×põ}ÑUž÷i–ÓÉ?ù`W:ב„s£VkfK@}-T:u)ׇôüœúÈÉ{|A¦ÝA“÷‡’Åàxž(¬m òÓzÖýZÏ¿ Žš¨óT1G÷k”¢#üˆ*á1GåÚPB‰^ó3.„ 6Éà×sÛ,O¹¯P¼=ŠËF{sÞ¹ä50»rØ!œNl0êaê7ÏO·A´Øc2Ä€3(ÄZ¦jor¤åòtOY=9/öð·ŠùƾO>7<‡q±Þvõ1’U³DÙˆc‡‡ëºòc¬< +Q¥Åéà½Ùèìjõá)¤`+=ÃdÜâèµáµÅ‹“˜ì\Pt)AÁ|Œhl*jÝŽÆ’¿±,Qèª+ÎÏOÄãÃ5}Z`be±ËÇ7 CÄ­å`ä:ájðb¬¬*évæ»AYSS±:8˜GÄtûU+U YOñð?Ç&D‡Ü >r¢n[{wÝ.ª˜ žJ±;áŠcÒÕâÊAÌD_u4<–àã"§Zlo‚øüÜ wc©ûH÷Ûe€£“FŒ ß—+CøK'X;óå¬5&þ»Y6gÌ¿·ä=n8Àì3XÙ[Þ0Ìmlg”t'D È :•ϲDXžžÛB›¼Ž¦]Kîž1%pä®îÊZò×Ó¾á5ª´(Öw|6µð*º¶FÕ§]6ß¾tÃÖ<_SåǪd)»¬:“ T½Ü7˜ ³“à™,ã׸/žžþž9ëÑþܶ#%iC_öGÉà”,æLÞÔl Psç{Ó+l—œ`ùfÍ ”É5à¶B~ð°al7 Ej£Á°Ó$Ý•É1 @A²ð§QƒŒ;®Ká_5]GS]´]i;:ëõàsý©¶@?(Ȫ®®—ÖPöÉ©¼àÓ‘á&\›HØ”ëQ\GfO倹âür‡žRÖEÔMhßÙSE@ƒœb Î̵µ±cRˆB6L¹íÆ/#¡gb°eÕ”är‘óáXŒ¹6ÈöQ÷)À·2­ä³»iÖí1¦Q5T—yÊ¡°æ RGÉEs¤ÕšÃ¥á½ï¹ )kû[uoXøµ; ÍY8Û=J·dg=’¥5 Û'ÙQGß4{ºÍ!±Ñ“#¬öÈKÝiÒWƒÞc*ä–cé\âvÓ1Y›Ž}Ž+±³šSHNLÊ)„¥ëWÛ* ÛoyÅû‹-[yážá +cÌçÓØ_ Y>u Cóõúo´ñ  Úxìsf颌œ:Š¥~_s4ÒÔzŒuóŠFhéŒ&Rès£ÞÄ ±ºSé[´¦Æ*éÝ¡vV+BØû®¡ûç«…Pg¥võ5£y°žÂÇhn»ÝØGÉ I,.lªñX96CÙÙŸ°Ï?UF-§ÄدN¸Í«ÁY$ª>eÇí˜`¢¯J7Ï~WßÀ| ·/È 35:•P¯вžƒ’~ áŒ@yÓV„Ž@ò#¹sið¬u¡u ͆FŒ¡Zççþ¨MhÕ%f=y~^c7=$*I‰“bhg¼GçP‡ùWGT I2jñ¥_ÒZ_1VEì’S¹<¯´CYºa¼ñ3,/v!Æèu«„ÐËÝù×–˜¨×±Öê„J‡QUÐOƒi!™ç9F2H7x»Ö,ÕJÖ%,ÕÊ,ÇjeÑ£C[—»$Ø3È‚+tª´êÛHÍe ޳Üǘ‰YÚóŸÅ%QÞK2›Æ%éOéÔ#£@ï¿qTOØ´G¼Û3;™-`ÿCnÿ*ºz¼µlб‡ ,œùNI“[lÿì¼ î.;qè³Û8º—”óIÅ¢ñÍ<&S L2º!u€Ø²•!Õ0|Ä8l:‚#ëù|j bZiŒ{§ÄYñYzf }ÇöÈgáò+ ûr_TÌÕT»FV+Ùü\ ±mІ­ÿåùœú„ð²›O‡ÿ_b¦E)RTX³æcÍÁ,›ú4:\üÈœélŒYÑó8.,ªQ–9ëAê¢l¦„ª–¬;¬°¤ÁWJ*¨*,—¢|ìDýG¾¸×OGÚšJT‡•}ï¶Xdhj½eyR,z˪TpiÝÇv˜ UÜ8slRÉÈvå·b~®ÆP¾sóû­ù¢K=¹šÓÅåTÛz{ÜÕÅ_n¹Ë©ÝdˆÙ>|µX–æÈZ[ÁFæ¡ås=ÃÄ¡;œßý”„¼ZsÕ4"±±ô¹9¹“¿r­å"ו¢6•r‚dh–ÕJŠ0fÕ×ÙÖÑÚ_ ‰K@€Å ˆõ,÷° ¢ÒëÐÌc{8a{H¿ÛÔôñW¥~¨ÂßSž*—=rðSÕ:á±~P”×ÏO‡~X=÷u9Gݨ¦¬Jóæ8×e=ð&›",«žÂNÁÊðÈ,³ÝOäý‘ÿ”v:ꌓen<Øæ(46.ŸKËZíÓ/OT=d9‰pnèåå¼¥8›Þ09…ÙÊå¨Àˆé~šøá˜~ŽÐ¥¬A®Q5¼ ¯k\dS`ó¡Ð 'Œ¡“}Ð)½­;XEU¦èÞ©62”†ö_\ü?éJ'endstream endobj 151 0 obj 6689 endobj 155 0 obj <> stream xœÍ\Y“Çq~G0üöI˜qp›]w•"ø Ñ%›:L.­PX~°¸‚{€X ôë™ueugÏÎ.V²É 8è®3+Ï/³úÇ“yR'3þ[þÿìòÑ߆“—7擯ῗ~|¤¨ÁIù߳˓_ŸA#¥áÉ”æ¤NÎ^<ʽÕIÐ'>Ú ^ž]>úïÞ;üïÎþz5ôðvš-t:;‡†_íOÍBJj÷»½šRŠ6í~µ×»?ïOÕd­ zwÖÛü&?56î¾…§*Á°aga¶ibšôw¿ÝcóàÃî÷Ø<Â?¦ µ²»ïö§±Éñ‚ZOZñ5áÃIkíýîmyÿÕ~±åüq¯ù‹Ûzšgs|‡³Yè«h·Øûßà‘ñ“šÝîkÜr³Ú}ßzä“1 ZZV[€Túfªy#’½.›ÖAåCñ´œÊ©™aâ”òá<ÛÓ ažk ðÕ^‡ÉÙÙì~‚åÅèCؽ†å© {ù®S÷yë^¶kïh&ëÚ€°ËW½wkxƒçÉ9µû°×xÆVïžìMœfeÍîcf='Xf}ø~o¨·b‹x‹¶“Ñz;vN“ónw ´›¼ÞÒ›²™À‡Æçç}qçÂ:ó.‚1ýQ¦[kŠƒ\à˜þ>c|_ÎU³ã¹~Ï97Ãï~XlY‹˜a\’/´Ópj×{䣠U•C  PÆØ¤ùÖ*‰œnÃðeƒÉÙNÅPÇÊ—ÿþH PÉèÊAEÖ]êsÞX¥Úš¸p½ê žÃÉ% ÓÇÝ B;_fAÎgYŠ#¶X®A×…Éúrd$ Ò6ŸíG@ |k ¼7q$aMñà5, Ï[û0¯ª@4¥GUFïK~Åõ]>˜éýÞÙ Eæ×GÎãf_à_a=ylJçUÖü»þ´¨´uߢ¤E0‡³ßýGW'Ìü5OsVº¤nKU8.£L4Ye'Û{R©‰E›3QÁFe{Z þøÿ@KHû ‹ž_| 3¦0¥v[jý{ÜÙ<+…‚CûýNá› ÿ˜ñèçêACî¾€ŸzÎd¢^¯PI€êŒ¨oò©˜hzÿu?Nz ÷M{xÝ[^µ‡/¡%hÃ9{åáO½åÛöðõ¡î0ÑW‡'z?샽¯?ˤYÚÓq,¢1Pé²?}Ò~¬N»§|6í¤hŸÄ/? §W¾íÏÛÃ_´_‘NÚWöïìýf`õû WO”‡´jäM¡.ûy_fd04&¹M³ÍÍ]ˆ\Õ_Zã¬êü×ï wÀ†2J?(k:a\=&²i'´›#µù©ñ5ü©k\ðñšÑƒ\ÁàµDÊa å×yUvŽ‘”ï~ê•çL>Ùã›|²Ã¢ëž;§ÈÚóH|‹Ž7ŸIwêoýë=ÎÑ@(WÛtþ]—ìWM„éðÎê’f³ðIéT¿èì!Z…× ’DVx"p'3c…WÒ)½-<ëô0ò)2ée{x)ñÖZ&³¶–¢ÅfÓó¹–àdv´i£Ü4§$„o©z~¶Ì=ÓŠÅàyTÖ]kMgÄÏ~iŠ*³K«TÊÊm*àü㊿Á½åP«Ähì!Æ`9FOú3<)ÜCŸõ]¢4·–}Ž -,mŽÜ«eû¹FÿœçÄé~[?n½.ŠMÝâ̼"בŽ×À*MÇ7?·ÄéÎŒqzÛeõÉùÐÂ:¹q„È ½ÝgÕWíÝ»îžsg¹‡’´I3X9äɤ°hÿw„Ç Ê|B&[§¼ÙÑYé`È« V.›«‹Ä,ÐÂE!·Æsô~ÃËýíÑä2xÍý`µš´êV¨xß ®NÁ¼úš°ûndÂXdô´$[4Æ Ó] ¬#|q­C$Ö~ô½0ÕñÛ†1\enÇü¹ã~»1 ð— HŸ/µ;¼ç «¶¨‰ oÈ,(¡}dâüž‰Tgp¤ ‚ÇkÍBêL_uŵ„O Md& ?Yƒ¬UTÙ‘+¤¹.*hÇŒ#+\àðëëeÑûõÇà…õXj[dꢇ4®£h[çmk¬Gì¡ [#t—øêàY˜—;çú¸Ý4ϸ«®Ê)Ψ×EQÀ h45ð‡De>°6?¯Ø"S¥ÊZ—©¼%o (QMúY?”-=ä,á‚Ûzx`^ÏÊTºª»«†²WpÏ*+«¬>컥Ýd:†‰ß›,± CKNéÄ4‰v{ÊÍ‹ö–ÌËz¤]¢å(Ó¤-)-d’BÚ"#è@Œx¹H“b‹àšŒzípfD;OIUߘÙ/™¸/!;ÌŒ`ægDì^” ØƒÀâÍT)(Æi«Þ®¢²Räå¦ ú‡•Ñißé›q§Û;ýÐÂÌ×µ÷ `øÛ®Qâç‰!Xdÿ¶Ï1#Ýÿ¬ é7íõÑD£–Wå½á À”>Ÿ¸å„GÖÛ½ö>‰–÷­Ãg;@ùnìDŒgÙ–^l€ü‘yæ,øór”È^q–&£²áÙÑ1\q<»wGŸÝ»¦Ϋ·=™LëÆª†CfIQ”þÃù>ï'4´¬ ÿ u-eeÏØõJZä‡ÎÅ?ˆ9‹6þ¤S=OõùBºØ©ž7ût1* áTZ‹¬ /³k«» ûßbÐa„S°óVÊÎúb–W~Áâ2)‡ í"óe…|õ•肼ƒb1Æ‘@…6õGD â9.>B~Š+æ.KXˆädzÞÕ¿rn2Zñ)zsSà£BgØV@êõrô{Qüñ85œaHQãèåÝSbTóRNšah%ËLÌdœÿýÑ­Ôtít;¨nÆBàøY /¥¹ðò‰{å×¥4#ÓkÞtáHÌ—Ï0ä|² ~à<” U¢¢!Ka¬å@ŠÌ9šÄÁEtz5Xeg¶ÈÀ#d`ÒL§¼F@&¥Ã(Jé!†–XèÀ™ù:/^ ­ yiU±Ñfè/DLxµÓ÷]l ² Wè̯ òج¤HÂ9/ÅJˆN´TâZ¼p¾…žrYóX•ƒêZe‘pIn›•‘„ ¤ l>Œ>`7ª«1Æ-d…岤„ÓÖsª« ï—’$¤Â)ÁöÕTàr‹…k4‰U4¶Y‚¿ùläDæåØKòÎÇóqq»‰½?a“â+­ânÚWZè=ªDrf›­hYî˜"Q"› rzdagD™ÐpœüÞGFy°¶ît”QcûͲ¡§Ø*ù]²³ï(û"žB¥¢Çx!ÞýÀ¤PP˜îYŽÎè}¹ø7rs3<4M“â…€WbKÖŸ­®v*rBÙBŸ…DM˜aj³n³`æ\iæ@},Àý…ŽïòÃñk^ˆÓ‡|_|”Î Tú¶7µ°r²GÂxÖ„8§6Käx’¤¨“;ˆÁû¤‚˜Þz°4Pv©B¯nŹl`j};„æ>zZÖ:c¼%Sr[þ¦”-JؤÃd'Ç9™H• ^,͉ ¿’Ø,0X”ÖnvŠ+VU®bž† äK|SàÊM[@•‹££t°t`ë|?QÉê NK›âN‰K´·¯—5`­® ”»óvÛÖ”‚MQ§÷NŒY©å–ƒEU©Nß7À5£AX9ß&^Ô'lE" ‰Òó*«¯sšE\(ãO)×ß ÑÉEâ¬õ4oâ4g³p#X¬ÁN>„]-wIVøCŠa»F$g˜5{=š‚ç”É¢‰Ä*—EüÁd÷ÅC^éÊÀÚ9'3ôýoÁ`é®~x¥Ùé̬F»/‘ÇKpùëyXÇ%ãMÝϯ^Ó¹cyèû_‹3mí2fÎPw¦g%™&K » âºK`0¯ËͰ …Q.^¦ƒyA­œI@kQVõ(AK.e©TY¹”¸ŒaAõêÉ€ 0+«9ŒO¶¥•Y­‹²4ÞúFªõ'z9añÌ"@½ ,WivrUÊkÜÆ@ xoø¤X-ƒNt7unIíZ^± “u†Ì±hºXŽ*v¹ø‘n-;KüŽO·1HK—KÇXÍ‚(¦¨~žÉ ïÃX&BZŽ2$£PÒ-9T¶J—ÚûÛt¾™¥‚)Æò¹òBÁÆq×j·v\íçyUÂ>tùcÅÎ%×YŒÖX©ÿYɱ¤“àÄ ÀÞ¶…Ýœ«]xI›ÅkÈ*­Cj;y»6(’›G1w°Q؅αõVÍã èAy.èF…5ØQ¤QëÉØ^µe_Ü%‰1^,Ÿ3ºµu•!O…F£—µrâÐRT'N ×õj9i-D•«§›Êð9¿\kí}…æ‚ß¼‘šËåçU ‹ä½»c‰íò~æÕjÒÑYÁ 4‚W ƒ£Ý"‡\à¯ÂÓÀ‘¨¦îàRf[^Mìp¬Ãäo°ƒz­Y—¼·jYË lƓǗÖUð&ïsSŒùnì ·B%ž}¸MZ~\Â’ÆË”-ÉqõÀ9НÞÎvñÛ–g­kÙ¿¬G¢±dkÃQ—~ùñâú rÂÂî’‹ª³ždàŠ]Q»âcû¾±ð˜ºoàÃ<ê 1¤t/ZØË@« 3%& â¦x]ò߯¥¦Sæ«Å¹;VNø8«<ŠÝƒ K)«L{kJíT¨¥÷¨¬À D‹Ìä6¥Þ~dß fkó%GîñÙ1B[Ó®y²ó¬sñ.B²1aôBb}DŒ“‚Šý¹õ~Ž’¨Ár (z3^ÍïÐ(K˜imvEÍ@Ûlhh'eS¾ñƒÉͨðRu‘½fûj«‡¼É¸³¡u´†´©MÖÊØ ŽóoÍ8]K`ò|óˆ1âõ?¨ ¢Ø<­‹½¨Ãõ=ßì)KlÄâí'`†ÀïͱªCÀËiÌø®Á¯?ü ‘ðO5ªæ@H'x‚ÿt®?O±ºÜ«o˜´šÞzOÄq<ýº÷‹iÖá›àÓ±€§b‰óÆ7 Æ›KOú´¦I ]ùN ¨EÒ–Ì¥«õûn•èÁ•‚ù¬ê„­ø©`Oe3€¾"Œ+×ëäÉ UŠûä¶ ÆADÃÌnU-ŽwtüriRïþàzS f-vùúIû2UFÛúYÃJˆ‚Ê?†öȪ§zÄZäH޲_Nð›ŽLذ~˜AŸ sÜYjfHø™è3¯«¢ tRºŸCŽïjB{À¢oÿðHNú ®ZÊ=óéÌ,H¨ì8“Þ´Ÿ€b¡T´êPÌÆÒwÃ]• EܵB(ù¢›Tã‡KFé`I–3]@õJ–åm*jíl—Cæ’²øpÂ8Ø">SH…jÇ@k°Üiæ¤J‘ºç¼œo™z¹!úúÞú^9d×HÎ}î‚`0 ê7% ÔdˆÎ,CcFXÔH¨ÂX7‰å¡Ê 6ÈꙜDó÷xPTš«ÜœÖ Ž:SÂÁö%¾ÌÉûËèèöÎð~L oûkJ—m£îŒAû=ß|9ʸyšM3(yÊôضðô7Åβ6jOŸ¿ëlµsð·ž‘¡%R¸U†ÖSùkD}U86äyÊêGbÄ´ØÚØ¡f—n­>”íà£u²_¬µ|Ó9u…oÓTýU®s×pi¸ù+YæUÑàÕawáe¶4ù“ã1Ï ü!f­ 'oÆŒ¥ñ]†.î—¶ª*>è¦â™½«…zYJ6¸r¤S*<» 09SÃÆµ,n™Ë/{cÙü#={ÔÒ¬ÁŸP!ºz>XZFvÌSÇë’åüWøz¨÷np.t<–ðYN+Íñá“‘!i-®—Ö²v³]ÉRë»…žeã‹O(b܉¥‡©ÕÝÂÄÄðS䌥éõ'Ç ú¼Æ ¢mkú y:Ä‘õò¥¨ØæfyñP¤h¦e¥Ðצa]è,}­·“‡ù›ÑcäG»Ç´õãÎDìéà7 ê·îÆ%qŽ:¨ ƒ“kCF‹V´~tƒ%ÆìlÛËç+Î"^È'G¹xÔ  Êœ„}+ fçÊQf·°(«‰gìÆìKÂòYrÔꀵšÖndÞo×ȲãÑÑ·U*§u»Þ…u¼(ÌÉfÚüóºî†á›žZ,¡j&Åè±4¹Ú$C\=DYXÍ`mcÀyqÏÿ°û1^à@Š)5Ý€ز»TKDéåŽù’QþЛHùrþm Š_‰ XˆË}ó!˜« ðâ0Þ±Àäùm¨ìb5:ܘÐè»L°>Ôú#%£h¼+YÕ!œü•ܨɹdNªä¢•«$J ÷˜…2°™+xùqȺo|) F©ãå¨Ym_í`)\„wa bƒ@.B•ˆÍ,š”TÊ2\íœÊ¡ÆE} ŠÃ~(ÁÊ’¸1«ã9¶Æ¼*T2ô©Fü®Õ©†lªü~\”†Q ¢YäÃ/‘Gcå4Ä‹£«5^Î ‰a®2*j}BTtÓd„TËÃKþÉzDÊÓ`]ò×µ<ûÑSñ´Ú¬wUÔD;Ãs†Í˜v@4þ?¦\«kù¶–o ’r’æ`àß:Ò¯(䲜CÊpo$§xòTøÏ¾ÔësäWc¦rɦrq‡N4Çû"<]}œ&¯ße¾_x)g®I'(wLæq?~:‡¬~ò-ø_‰Nóú“Ͻªt­ukUÉ•¤Ùÿ¾ºÙÁ.d€Jp> stream xœµ<Ùr7’ûÌÐGðMÝu÷1û ÉòX³3¶¬cv7f4)“ZQ$uplÏ×O&Î ÕÝ4¹áp«ˆB‰DÞ™ÀÇC6ñC†ÿ¥O>½´‡gŸØááÿ³ƒã¸Z;«V7u¶Ÿâ£Ö|õi½AÈ S«+ŒtúÐ;g_½ËtqYß¾…+Å…À)àaÒJ‘OÎkÏã5Ž}ìT¦S^°Ç)¼ÐfR&€Ý´ž€¤V¿T!â”VJæ0“†Æ´jky?ú:-Èr·:[ë‰1îdYìíÀ“<#—6BÌq?Mõ,Ä-ûa.ò0%B*º‚Ì„BQ2<§[û/™DfN„QéqO5Gîƒ@&¦=F¯UÀ32Ài}Ag|õ ¶ Ë)vß•Ï#4ó¤ ·1¬P,4Ã^Øq°/Ðé$ÏpS_€×“1°[¸\ €NK[§ ü‘´á¶–‰\rr…$¤yRž TæiöK*ˆoHí<ìWgþ„# èÐùz+_&üÑÉ.às©æd--àÈù|‘ðÏ“²ÊT¹tÆÅ¯óX£`˜Æ;èIaܬ~Æ÷À–°ÝWkBété\N™¤Á ÈTDÌiÓÊS¸ËÂéÌðÊLÎ ƒð° [¼É»,™£j¹.=W’N…]U¤ùJµ—ØeB%êsÊå#"ô¿A°¬o”éKÐyfA“ü¿r°ï|õ~-–x%nº”_ÖÂÃ3hÌ«º™~ZYðQ&žH݈¸%[´wiH\¶Ð ’y¡3Üxo•“ ,;i$:P â:õE¤TdPýݱG}»Lè ¨´0ÅÙŸ$²ÛC··¡Ùë.·\UA °&’v y ’Îf‘¬ê=L…0’RcåÖÁzÚ3zà ,$xæÒ玎rߥ­$w&fRèͰNøœH¶7$FBå|’ŠÏVí%lÖxÕ„¼ËHÉnÈ43¤¾™0´ Ž!¡¦U—•®’ü–hzj5UÊýy“ƒ:É2ÀÐ….†¶Ïi5R+½_EÙû…Z~:«{ßÌ÷ÏÒ+K"cÆZ§að¤ÆZžYæYìÑó,RÌ’rÊNF4nÝ!‚‡íAÛ¸Ú8fîŸ^…. ›¤÷Œò Œv)çàš”F1z/¸ Ôê?‘Ï5GKþ-¾÷´üo𤥱<ŠOí8BÈ&Ř€}û„߈,E¥q“eÑgÚâ:'c5 œÏš`ØN\3MëÁfEºMýâkåÈ# ëòuOrÜÃÂgh“|dþ 3 ëmFÑ!—s¹bŠ*h••Xö ÅðÃF4¹ƒ•„ý®€J|Áž‰¢ÒЩˆ“AiH鑲Œ°•èlÁã>ÂÅhžW½Ý´°¤Š4ªת„côX—Ua¾OŽ/ÈD•™áw,ƒQÂWêMâ!´ùýYB S 6Ô%öX¡ï¢Õ!p¢ÕoÏq„ н’RØai%¯7`§µò¯+½g*-^’à|@¦v`ÝK/oO¥Î4Têl ÒE¶ò<¸™ûÒ^ŠGe'…2³ôQM!C8¶W0¦lÙMO| "8%$µQ£&ÆÀð`R.x÷ûmXAà™g¦T«2"ƒ€*2™A:å×à3[“W!¦€ñZ:ZÉð{ô¨¬Í@ÎKöÈ»;‰"ZM‘H+ÂNÒÊlNûIHÚ>¯äO\«v¥¤GW”µxP+%å߃4Ö*£;á¿+˜rZaæ:(•¡ÈŸQ4)ÇNT—ž‰RìšE4Ð]MB Ÿ)d¸R[æ[øàzÈ„xH¤'#"»!ò7ìˆL*%Î1n!¢+X„ˆÒ^N»¬Œâ¦EÙ›¹O;Ž`•´VjÇÑëÙÿÂ4¶gšeÏø÷T[â&~q#Å“R>®º4)SbÄÙ˜ªÂ †¸B³ä%¾ª ñenh‚ à§¡õ¿ÍCÈÛÛ‰ ˆ¹‹„ ’(È¢ÊÈ$c,ÑeÙÎI1ÌvÄÌ2jò%©ð®b5= )¢bæ`[«8I ¢¥íf†* Gõ’+1Ô ûýJDUeê¨6£1Ú)Oœ<¬qN]¢î”Q!ý€iÆ%ìÆˆJmÖ·1¸W”ExGýóE¢ü=þ9ØTÀëºH'±='»5)œæË.!—”<Ž„³å q&3äOnPÞw¼)KŠFz°`h íyŠŒ‚‘æøŒÎcæDªÀ¾éãEÊd ÜÁV‘ cÕmUA¤$>R "bŒ¯=µ]4ÆØ’/ƒ€Ij¹Õ¡Rü4"°u3Ë|$ÎÅMUh´xhðj‚#ýÓL'£/:oJj$ÿÆÛZ D¶R,§©É܆s7qwè ^ЀâodPªÈ4j+a“¤™£99EXæ9 Û˜haZݳÖÜÅÇž¹bþt#ƒõ¢ç:{4rŸT)MøwøØð yÉ4¸P1ËÙÃd v¡ˆï>¶jP*:ƒB1€U¶nn‘ˆ’{Mÿ9Í"fD`÷@§¸&²9€{9³Â–“Ÿ­å5/Ý@Æ!|û–iÆ6|’l!Ã]®Èé@wÕ¤+ÒüÀâB“€…øp2˜”·»r¿É}"zq‘-|ôÈ µ\PÐHûù:bàaîr]b{LvÝ1"2žYdž¢oú½KÉk–HQCˆa¹ ±ó$ÃŒ‚D¶ÓôǨ€Y{Z _ÊBçÆuA«Ü½±±HïTu|t>$÷-öÙ(‘—#ŠÂR»å|žýK‰íˆÉMT\IÝš kˆ–¶Î¢ŠóJþ¿’ïñ0ÇŒŸ^Ìm8â6ÏÍëQ4‚(Õʇ]%eÐèKÝE“É´KÚ¹6KVc ìrÛ£×¢zGbl²†è Ûä%ÿÐä%a ’uÛ¤aÏâÀϲÕãÏ üÁ4\ðÓVoðç%þ„.ÿ±Þù˜GšbŒó•CÂðvgÅJ#«mÔ‚È ÿü­´®„wà¶ W¿-ï/êûãÒx]?—Æ·µ÷¤6ê¬:Ò¯õýui¼tS?Ñá•w)m’ßÕž€ ö‹¾‹9ο""ÿ¾-xÅrSôTê#à‘í¤Ç Á·¡VÔF™P Ÿaú}kÆt]õWõýW¥ñï«Úº)­¼6þ}]Z¬:íÊÅmW¥ñ¤6ÖM»,O_F›BÂÌ·ð‡6¢#‘éñ½¨«æ³üHûRûþÖì&naØ®ÇøƒÕM«'øóuj9kpËÈîé­ÚÍ-‹»w\»Uœœ¨wˆ¨Šæ ÃÅ ÈŸoØä7¸Í ÷Ëèý?¶ÓC;g~<›í>žÏöã›ÂCo’ ¥.Ò. 6#¿¬<þTÜKü3ü„.lù)Þ 3 v´¯¦4êÚø¬4nV­ ŒžØ³mÿSýàhÄ)Uê ÙW”§£©dàŠ×–{Rã§‘>kzføy$»obxT‚*) Ê”/e: `úDsn2jëA:»XRp†/«Æ€—ö·ÊÆ@‘£Ê—˜L3$.¤ ä`›^ˆ¯°M!?^KËSk–duþ<øRîà/ü?ÈjÌÁäm)É ´”f`7þoÜ+G1ôޏ4€ñšYe.Yͧ“eÃ|÷.ghæÃ¢á<*âî*H–qfÃXp5ŒE×Öb®#-¤ ˜·%µiŒa”—8éx"˜UvR]HDSë=×òÖY¸°©ä%°YË—Ya^2¬B!^HSí7|øQÉCìÁj)å4+¾Îå5ô_ \Ú¼wN"Í,q;âm=Ú³è`ÃBBáïrÂnñëaaá`DµØcð>ÊÁyB6´;T3.¤ë‹z®çÍZä³FàÐMHxÇÚø­¡u2Xe{:–uðzŽ#GrQ†Gr/f˜µB!kbü°‰9"Èêç’„6á$  ï<“#, <¿ŒÁ}²Z¶sXIQ¤ ÄÝšKÁyQz".ц*}õ }ÑR‰¸X“(ÍÝ%€! ¥äþÉ€(õ"ZãðU¼‘èaOLH7g1˜³†íI§šƒäû`!mÙúèdYޝ¤Ôî(ÀO«éþ´Þ²ø®7VµÞÝÓÉXfÃÑD1i&ʳ•Žc\@MLJXÅãÐW ‰‡?„™˜ §!U¤eÐÇR`¯€¼§Í¤Rù2àÆ t`“ ®Zæß:£i r©;n†ÙH”K K6@V[ÍlW--€ Â<­D‚,ø5TQç²VÞ†X}=×5ŸæJèúò4Ͱ¥ m8´­Ðöy{µc£ m¬£.Úxf4àž‡š5™7@7Ø~:ŽîX] Z-Wz §SgÐÈnÏ´v¬ßc عÐGR'¦BV\ö´ÜØÎJo9d†ãçß–úÉ 9´JÏáÉÝ—H)ÅþÓ*ÕüÈmtNî6TÓ8æÞs»šÅZ¾&‘;7¯›ôm€EwU^Q—„ϺƒÀ1UM ^D½gän!Ó#>hö”z>Í)FœÐ¢µ¼`Mç2sÐXh²-”–×ê„‹¥Äl!ÌR,–hÇRê˜nÄ(¨v §$€Ö GkNwž¿Çá…,07(P ¹-J´*”$/‘c[Ú¨<-§EÏš¦ê˜mM5žÆc®ØÏv ©})é³QËν‹hzÅ,`]µÁïzvG­k^Ê„WÕÐxZyã­ )1†^•˜hUÛBUzßÙ öx4˜6h,$†ª©TX)¿ÐÕzˆ»Ž*Ú†æ÷?ªX«ÔRš2"V¥¢"éH[ñ³¼trS)m–éÀɮӇäŽbnv~HžÒËÎL'-‰\t]¶•7ãÞ–á=ÞD¨6m>põ¸Ø-VôzîòéxÆx•ñ³ð̆Z"XyU±aâCtȃöää¬9ŽñÈS­ SRz]ëjL Re8ºñ„c*-÷\‘ˆ yNññã’‰rR‘ÕrÆ6P¾×ã.v{ô.ø‚ÅÔVd%Ï£KüoËäÕhiH&…RÈ(½\çExB±‡]pCÃûÝû>6„¯¾K­9-ôÍ:'Ÿ¦Àº,¤vrŠ0GvÉG)Ü^óDK™À­YÚX£×z᛽Ƹ¹dòYn¯¦7HnïsŠY{µ+!Øf†¶%±JÊdd‘ãF¥«,¸ û¼õdʼJ•¸î@ÏÁ"ßY¢©¹ëÎ-ÞÏáu°†‚FØ£¤2€°¥ŽüÇ Cö èˆx òNURûª„¿-‘t2ïí}x¦QO²ç?ÄÉL!Öµ_ų&þÜ–Ïu~#æ¨Qì6¯µ@:îÒØ-±ìw2¦ŒÔ®#&ÚÒ•åÀuö…šªÁUéŽ®Í ‰ÛŽÊŽê5φapÍj™“Ï@9ßpïìëKŒpt + kPQ¨Vïä&¨Æy¨Xûò2ž´ªvÁH­°@ô„|“t{ÖˆýÔø}Ö _Sãw­‚`žÈe¢<ž–Æ7u”õ}«grJþáÖ"™^y¯á­€#µèl8 »ÇC? ór‰t1·hЬRl®çÌfy†[gªœ­Çw3•«ªÚ×ÙFo%ý–c~Κòä!wÈâyeÔ§sÇ4vô¢"Gœoï‘æ/›þù¶)iÅ2Ä­¼C%ãî>¦·«åŽD˜g1˜Vèâàã¨h±óÃí`Ü/ÝU5’b¦Òwíá8>Š1.tƇêdP"OŒøÓ´EÀˆ3Æ<õ–ë&kØ'÷ûÏÂ&£á³GÅcÂNä™ÝM2ª¿¿è‡iÐT(æŒêÞçpI@ç}{Þ=„±Ìr Aþ¾Õ”y’˜Î×M¸í…óY—ÜÉÐIkÜ®ÂD|Äî)ìÙ¨d¼aFÏŽ0.Ö †h¦SàB½S`l*R9ßÅðÖRR*cfÏ£0G†‡¯ 7äÑQQ¶èHFYŽz6¶Áe'ÏêZyžÅîüfï`‰çdÍîs²Ù$&ü_ÍÇß4Èixž/ŸŒ›Wì’¬Ø0ÏE‚ƒ·7ޤš“î,Œ^Â-NÞSoŽ­”Šk´D@[ üÍÊÖáÅZL’ Ô·¥ý´ÜE jâ=™Ìù:Þ'“£J†Õß²”øÞ¯‡ ³Dàû+ëšB%'5UgùiMî«#'²D4Y¯&E5¾ZEpÞû¥Ö’'rDŽ„“ø?á¨&UÏÁõ@VEª\ªÕ3u6òB¼Á?›1c:†”CU¯*EpŠÆô›ñbw(åqD9ÃcW£ÕD¥Ò¸Ï^üpðñÜfnÝ…Ü!¨npîЀÆfïñ}òüàèù_¿|ºy{pô_‡üàè[üyòâ)üóüëÃ;xöüð‡Åû};c>Ýï+¬Æè¶A_œ¥K~ïCB”Í9XDª_”º±A¢Rêî~Žx¼òÕH@Œ|ÂYW““‹Œ‘}°J5FÍò‚c]Årå†oBâøØÉX¼ûÍ\k|X8ŽUnXšJî´£×Xm3O[U(ò>AA«Íœ•ZO3×DÈYÂÁ]lëNM<Çft¬ùÆä™¡¶±3´p}zP›Û®DÍ}šÓÑ&Æ/æw2:zßåH’”‹œš¸Öã £L¬¯¸c°Va&,qŒúDüª™°ÜC,Ô¥ÐO<ýÅ'Sü›i.ˆ4»¢R²ãÕ³Le•dŒ£†nóf[MìÒ6i†aj;-]ãþÜϽ½[oðÖÙä§q¸£’Ÿnµ(@aðÒm Áމ"Z[&"~‘óRéìVü^È™·ÜpÐ0=Mè«gÎüTG–“Û¸4ÓÉà®Fwý‹Núáà_ZÎäendstream endobj 161 0 obj 5826 endobj 165 0 obj <> stream xœÕ][Çq~'ÿ†}0 sÑô}:†ØŠí$–-[^',^î’KB$W"µ‘è_Ÿªê[uOÍÙ³Ü̓-˜<šéék]¾ºµ¾;›'u6ã?ùïË7O>û*œ]¿2Ÿýþýä»'Šœå¿.ßœýò) O¦8GuvþâIúZ}æ;ÁËó7OþºÓ{·³{÷·óÿ‚/Œê¾ðvš-|t~ ?ßÌBŒj÷{5ŸظûÅ^ïþ°?¨ÉZôî¼µùUzjì²û žªÝi7ía‰“ž—ݯ÷Ø<ø°ûOl¾ÀÿLîdÑÊîþ´?8èÄFÇ| ´ž´âs‡“ÖÚûÝïëôþ»þbÓùý^ó1†Žkzšgcü G³ð­¢Õâ×ÿŒŸÔìv¿Á(7«ÝŸë©ÇhŒ‚–ú†Ù– à.}±?hÞ»d¯ó¢uPéPúc<äS9˜Ž1N^šÍîeÛ³W0%Ø^³{¿?Ø`'çôîrOkÝÀY¼Ýë09 ŸýïÞPcµ{^[´·ßÃ2—ÅÃâjŸé󃃓°~wÿöº¼zÝÚ˜eš•5»Úa2n†~áýÎ+¶…Ý›=,Ȩàw·m—{&Ø O«šçÉše÷¬½ßOÆØ˜Vƒ“¸joÓB´±Ô.„ Ï}r‘W›_ïñ“ƒ3¬ÙR‡/à_£ªÝ7Ãþ`·ö‡èÅ„èahZ‡@²Q®ÊÌ Ç~t0y¼e}¾ßã© ë¥Ý¦;Ü2{ì[Ç|.ÑY:ìÅMŽ >o¿ø±à¬ggò €Žq¾JÑ|ŸÕóÿ€}ZhódüÊ“ j©ûæÔЧ‰Ä×<ÉûWzPf<ë´àܻ˔û:×Uks±Þqxãg²Æ ÁÐÒŒ´ss?ãÞÓ$œwcGÏŸ;Û;ßò96 †uÿ#£Œá¨¿mK¨|Âÿ`¬æh€î¬‹øFÁ¯×b,‘†1Ž8äA´š;ÎÃÅÅíþµN’GváòG‚Vgç_<9ÿ—¿Â. ¼A‰fHôƒØ,¿P^c¤ž/ð÷ þñÿ¸F ™g¥v¿ÅÅ]Å9'ɑڽÃ?®KÆ%ì~Јр^)_Üiù ~~èhH$ùÝgí£ßÖ÷ÏÛGêÃÚÛúð]{HŒ½ÐL^Ö÷í=Ê9T{0Ò¿¡œœwKúë²¶~ÙZ_HC´‡—íá÷|ÚëoÞׇŸ"S£ói½å+ YãÜ4/EÖ¼i¯_µŸ?¦ŸH\Ï×;5Ÿ_¿ëÏÛ§A{¶?xþ‚¿ÏkËŸÖ5·g¿Ã?þ·°£–ˆ¯üIdçÿŸ¨ÃÆ€‹gç}ÓC~ø½tÞ¯¤–ïÓâ¿—èçy£¶OêûŸ¶÷Ÿ´÷§¿6(5SÔ…€Þ ^ÒA“œ¸ßAÓû‹ÊýÝÒíÜ«„*ô ‡ˆR¼âûòQí£œ4#‡_'¶ü§8ûÆòŒQŸIÓ½ª¯:*i g4‰ñ튋‘u/WÌ[Ïû}wÞ+¸šÚPMT>ÿ¼ÁZ˜âhvmDø @°ü¤;\ùj?_C3šÎ`eˆ`iX¦¤/Fu ס0yMÀ£Eg¨j=hoglcG\ýC³pX?u© "³ †ˆp±ƒe™ø‘_13îõ_íŒðQª¹Á†Ì®Žï·„¸½,0¿jPôö´“6,…bé 1jž³ö 5ºn˪Ci`…ˆv€Ã\šØÎÚ:Pù¶œVzŠSö XÕÍ¥µI¢0oA/ “Ùшª¢Úü0,œü¤?Ào4T9Í´>Ú/”.QX£QY.Á‚oÒk„׬«d̈‘ü€ Œ}Ë ‚úeëZ²=; «ŽŒ½¡Ø‚SrÚÓ2T‹Û¦ÝÜ fx&¤˜ûƒs`4|YÕ=åð¹vT_ŸŒÕEû-mU›y¢U¤ãätå‚јNÃùËFlßß+Á®CAîÑÌ_ªñ౟M›­¬m#f­1gÄWxÎ •ÈGt|…bB![ÞL:Tç°ÅÞ4‰†ƒ`Æ€¶!N(ÛÐÿâ‚Ç„lkDÞ*sÎ&c銷™@‘mKuÁ¿Ñ%· –â§Hz(î6¤ª—MiVôA;`‘.L§–×Çu?&Í@3a8Øjk8iA cþÄaž”2k ƒ³m¿V§“i]1Œp_&}³Ç‹¼<:æâZB†u ÿ÷ºµ&éâÍC4¦LØù£BÁ ¤¡”?ó“d^ùàмU ›²*ö‚&6÷Öoxš–à+×{ϱÓËF¦.¢³µnað=s·á‡[ßVÈ`Ów:¦ÙÔ! [?d!Îôõ®°¯×óyÙsÉ-Ÿ•#'€O¨ƒ­%Ñ…Fg‚Aqò…-.ÐyhIWWžkÅrVÖˆ ¢ Û¦n«wãîÜ3€aÒ¬ÇF­Ò'ŒwÛ' 8uŽÃ<ô×ûJö(”gòªïþZ†Œÿ²µ¬_¯°îS”½æñ]FºéCSH7Ë\œ!ðsE>œÍ°—L>ÎmÒ<ÊýhH8¬Œï:›emÔ`½Qc¼§¸ÈSQÎ3xôCö:d´ß\èß0Ö@² ޵Û´/}Ð$>mî$Ñf äœÜDiù›‡°ª‰Å{N ¤4g Á‹;Ù$ (ZÀ0r†±I%»ë6xR%æg]ð]ñ½œ™mÇ úá*ëpú¾þqZï£)ØyRYØ!âétÿÁ*Cˆà¨ÃÛΚ4ˆˆü󦔑–ܧ²2©^¬‘Ë¥€yû`Nãk€Â‚å1§!ªS—$ÙJtiöA1 r÷êhCEáâQE “éÜs yÿz­$Ì÷N¦EÓŒ'4Œ C\wÖC#æ¡ ›ÌµžŒÕ±Ë§É(„k'Ú»XQ3Ž]¤MŠD6êgT)¦£7P0ƒ:õšÕÁmîrXHŒöäU.Á¡PâdE†Žak°ý{ㄆ€%ß>d#c³o²!‹1cظµÉzLó ¡[E;¸î±Š,â·Ð!™nF=!¯·k`DÔëWiDN Ó§¦ãFBê ø…ÍÆHb@øÕé(ª:Öƒ˜<Îý^C~±ã„¼Ÿn Ý^&HD[mæeMÝ;ÅŸ¾Zk¦!†ÝO¢ÒR´·Öh[çzÓº8$DïÑ=è8h( £z"Ö˜þ¾ ¬ø´#úa )Âx Á˜Ãàq[æÂÔ äÏÿ\“<«€›£[5y²‚jÈ_ȼ¢BÏ+eÎ ä)“ÙÃg¡jÖÑ †_n¢™¦£gÅ8`$k¤ã^©Ìøšì`¶÷‹PT[ÓÜÑõv»¨i còJ5[PÑd*WTƒ‚ñòjÞÞê6B(®à§²”¢²Ž ‚o›‘|¯Ô»Ë ›ý pÃhµÍôe„åeÁ0KoˆÞŠŸJ¢°~Ó³…Õž0ÆÚÑýÎ+Ùs2e¿ÓT\hŽ…[Ê!\a½Óµ3ž•#×®.ZNp!'ÇSŸƒóvM¹ÖÖN6x{' Í–^aË5Ñ–mza¥poVh&TÜéVѲ°é´æˆI¤,‚3§·³:n6cLÕ Z µõ6vAãF ¶| ’m¦á²pÙ&GäÕå¢1ÙmÃôð y”¾c'z;J`– BŽÐðq —@”™”à‘BJ )¢“Ó¿‹•aûPN¡ŠÎž©œ%d”ï@Y©‚vHP ¢‹¹Rk¼wÛ8ï&À†dœ*9rx_³Î3„¢íêõÇŠ¢õ‘Œ$ÁUFA³Ó½âTÛÓðV@¼àPØ€G‰NÊñÖÀ gaœB„-ÂÎ}Ú{Åõ›,¤RjC/ñ{¯%r;Uƒ°Z×S¹KÁ°¾ç•зE‡qÎÇ£®ª‚ìLüøhhÒÔO m{^ã´CÛž<¤KÕ.?M–%Ú;ÏZkü*þ÷’:ñRÞÀ fB<Ù¥½PgVFãž=ÆýRþV9X,£ »üZõ7Ê@èL w†×µDŸw…×Dt˜Ë‰é1&*ð‘ßÕ Ü5Ä¢(QÉûaÄ‹48ˆq‚c*§”nÀh›^<íR´¯‰„µ‰Å ¥&ÉY¦‰r˜¾"Ïo£Éu’¯`›¯„¶¬&îÊXÔ1ɪSŠvªO¡Œ~#?·=ñTÚÛÊaö +µa:s³©rtJfDcjú±KLø¸¹Û€%—±q°ÔyÅù X²ic¯,k§N›ÏÚÀ0:Ù,qñL Þ$; Ã4¿¨…‚«Ž‰ìúŽAÜG˜¿¢Ž“õë}Zû—ëÜe)Q}ÑÃrY²!×™šÉ ŒáªØUv4ŸrW³$»¶ƒf¦*¾í%8YAQ²‚`›0N¸©òz?©týó}-ºü¤à•GwCO¼„éP6¦W0èEσêÄþ3Ø{zóvÞ‘\½Õ!âÁž@¢J¥þwŒŸ˜%S‡?bƒb¡çR°FM¢ØŠ¢‘)+%W=õ"Üb¥jÖP¼p“Ø3:kƒmX3Å]œ¨ÒD®÷Cîgzžj–3…dè5– X€°!†R¡f1³/X ±il¥#pryf`(…±;¬(ž§yQíp*Œ€£µhÔãk‹º¢|ÿšz=¥#•‡ÿ ðŒç-ß¶Ž»…Ä-ŸƒøQÅ’‡šLô©jÃX•Ù5ò.¼€‘–Ù ñ{C“ÆÌ<²½ U=MÎ`(öUa‰™µ•IY_8Má{ƒ^qM®ž2zÛ@SíRY÷L"ç~ïßeæB¶-ÌU²]³1sRÑÖ* |¬hkVÄR[´%Yb¬ƒšôPR:T\6R}ÊÁÁ,Wg\óöikz‹J”ó}ÙàZΧÜoXeÐ2ZÕ}Ÿ¼¸Q‡Ta¸%Jæñã8ÿ´ótðCÌñVR’¡ãÒŸöXéß0Ìš":'Y_=#¤A Ò ŽÀä:Ø–D¨_ë3[’Y“[ÄÈÚþ“FsBËèm°ÉÙ°h "‰Žš‰U4ZŒ÷HéÿõåÏÐØÀl °ýFm³Ígò›ÖgÏÈE¿‡ nºØ;VæXø‡ö³W4ƒqÄî´VêÝb{ÁŸ'–U㮺 U£¦bn eXÏɇºŠeõù#üþœ*¶apŒÓzŽúú÷ÙWQ§s·×AŽ‚JuYÇù¼ /'À¨ÁÐ(uÕ6q¸øä¢¹i>V1 æø @»>©¸n#MPw)“9MÐù1M¨Ù/¦G®N@ª—y©Ò„B—ƒüÙ>:*ƒÓ0l©Ý¶¼c¼æÄà]fÃHg&§%—Èuã,û¬}ÙóÛÅ¢ÝSNRºd DC錋7« 3ÛÀ{;{]^“™›oÈ™~ÎC¯ìbf2Tvj ™šÒógu¾}‰¶ 1-øe(Cœ»KÒÃgzH Ž$åqù#µØòº1ÿvµïùžî¦²šcÿ¦pR8Gådù6"ZÂ䯼–}bMàã(õøCr31-äP©åýõjû éÆŒ…ÿsíØÿ—Ä`)¨/DæˆBg³V»GeDrbµ ‹òøIN oYE¡`®z@Ç*n×f„ÏÝa–ÖAÍ ^Eí[°¾™ºã…ã8Ëð¦‡N†K®\ž¤KEnÇòã©îøu«»Fç(]w;ºo)9VúµË6’`¢žæ{A€…?ÖŠ‘L±@…Qœ¤ E Òë´LFR Ÿ}²oí´HW\~¼Ú Ô^ŽW¥ûšNP1%ð¶¸È9R€(_á“3¾+Ä`˜oi¬ÌEvÀ &á«Á×”Š,9[m׫Ӗõ<óîÖ$À¢H)¢%-Åß Ï…ìk¹ìaÒR”~U(á”8¯bÙ ¹°"a¿â\ˆ'è·RiŽp!è¿l\=2¤ÃÈÙÆ}Ê Õ¸I¹Éòþ}u™ ØO—™EøOe.äîòf³74]”ñ W+%Ú-Ž+-®¨ŽÚDŸïú¨® 3—4%ú?Q\B(.Èšê^Edêäz‰ÞºÎïcAß*3žž ôËÖÅŠsðÒÞÞ½tч„´©nèUVsNÚ/FsŽß/øÞå"”PÄñIñà`2úRhÛìËÕjC}ƒ|Á­xÙa}º©N7d#fIMJîË©K²­¤HªÚ@ç@4˜O,Tµ]­9½¿Ni°Pض<ë5¿|ÅÀ Àm Œ\Ÿ6Á 6iа„ôu½ŠÞmÅÕ©îòˆ¾>r+·€]°•»ƒÌª o~ù˜{ÉÚ ßÉ:Ü<Ð%e¤«ÖH—)èÁˆx7ÑÊØäZ#aÉQ›éF Q!296ɯ”Kä»VÚ•%€ç¼"¼Îp‘S7[ù{/Þ]ŽÜŸ7Ø¿Ý1ò[\B ÍÊ·¸0}¿5R™MË\³ž8©Žîõ>ÏêêvÞ¥ü·œn-¹ ï²eëR\óH6׃ö×,±ïó ”Û&¥Åz¢qùZ¶ Þæmº‡G$kqÌQKžpüÚ“Œs¦V‰/ KÁ¾£”’z6-ñežLŒÁ.ð‘Âl0T{hä÷˜«·»_Ò @ÊHò ]*¢Ôˤ­ÅübXœñTÛ¶Ä<ëäþ¡K ª£úôæìƒ£Ôöôƒ Û2K:^O.¦â©üúü°ÁH}¿ùÌJ‡Èf†åü“²‘¨—<ÿ:õm^oM—¨;€,x‘ÇۥȕÛBøï 04“Kwtndû—jÃKehÛUº½×¤|W&…ìÑ…’M$xÒbí.œ1Ø<9õY¬ £kˆ‚rϤÌd XÕ³á9¤7m9%óÜÒUr,uáZ ’ç&v¢¤Ÿ°¾ÝD¸ Ç$›§²#sˆj®nß(¹Ë-XrHJ¥ŽòkW».xåžjĨ$]%‹Üë’3*Ü_º2ãǸÉ&ø„;“c~î¯>·:—ö²¯ïcf6þÙ¾Ju ®×iÈa°b˜79H<ûæ pNWεéÌn`1-—ûT.ùI‹mV&Ü/“„š3¡­ÆõlU6޼—õ 'Ϊ"˜ëncÞ2|p9ê îà¯ÎŸüþù?ˆL7‚endstream endobj 166 0 obj 6271 endobj 170 0 obj <> stream xœ­]Û’Çq}‡þ† =Í8¸£®{µ~ $’a‡(ÙÔ:ì°èp—hXˆ$Ì‹^™uͬÊî™Y"-gº«««òzòdÍ_o–“ºYðåÿï_?ûõçáæÅwÏ–›Oáß‹g}¦Ò7åÿî_ßüæ.2 >9­Ëªnî¾~–ïV7AßøhOJßܽ~öçƒ=ºÃé¨O!sPð&}p—å¤M8üñxkNZkïÿv¼U'k]Ї;ü4Dµ˜Ã¿à§qUK8|v4'ï­wåø®îðßÇ[›þ4ôÓ?õáSD¹“ŽêðÛ>^y  áð»#Þüzø>4ðp·>9—:C§ö9üiqk™„ï?‚gü×QÖ5Úµ>-T¤ "Z ®"¼M;œßmuAÃÃpóK¸e®hC÷•H:SìV™“ó‹Îë2cáƒf]®Á–7WŸߣ9­Rhõ[Æ"Íiá:Uï'B÷¦«TV ,†bæ”\ô¶ïλþgÈÿà Äxí;ü¶/ãÖDæÏ¾8´k‰E#Ã~qÌ+°¬‘*2íïŽ ¼¡Ò*½"ï ëj000Õ"X”æÏQH㺘÷GÍš–jt¤ÂЇ'ùÞaò«,èÙd$ ‚}óUúÐxA1I`{àN0}ÉîÜWuÈêÈw]”ÄzgÑߺ_e™sàHw4¥Úˆ´N ¶_ö^µ‡T3ê,™3Ñû,ùéE“Ü»5æ÷-ûŽ–K,ÿo…MˆžWßð'b–%'&¥EÇäY«Âè¶Í6ô)|Vÿ‹¼åwx“ƒ%¤>*m¸øÕA›QŒ,,ÑК]ÿ—ÆŽ¨hÙG(P¡*âoòז͇».´€—¸.íׯ} ‰eó¢Ðj”±ÍH«\>x.c’ù²·2µ@Ñ÷ÈÚ„ÉLÕ¦«Ýhoð`ÇÑÔ9ˆ‹a_ˆF½ìRŒ/¦Ñnxî4Šÿ˜6B­&'˜t(m‰w=cSl‹õ^â4˜@T±hGZî^ÊÄq»éîq+iÖ¢ƒ.›($ëh%ñÆ{a0n%­Z“ »Ê}¥8åÃZƒßU²Æàz‚ŸÄõ$ǹòE·‹N¯v™ €%G°z4$UƒaL ÀîY”2MRŒéñêz%šT÷ô_è'¸^–%ßR·ô2éÛêKÈó]Ö…æ´jJæŠa€•3Fªœ$0EÑŸ”3[m× –²ÜºÅÚ/0œ5²‰§+èÚ,xâ '/òæ/9ÏJßž»ˆ×GÈÏ -6GuÈ[­ƒœLá€ËÖè4$ò­…¥"kbŠmÈÍÔD“%™Óiµ˜*g€é4L Šª¸°¤üÝEj]Ñ*NÉL0Fte}\°™nÁD\ÑXMH»½'N‡<(o…¶É›;®=·ÿÆ:¸@`Ãó#\ Ù¡>‚7‹Üõ¶{žÔ@¯ñ´ê––KzsÙà ºá\J¯ÒªÕÿiá‡D2´ð›¹’®RŒD,Ù¤LÓ*1Ä Inô†ú±«®w"ˆ« I©:üæ˜æÆ¾O2À‡ÂARæçÝÿúÅΦ¹'øbÒžÄÁø–'iÅ! íL¤ÀMˆhÏ7$Ss)Ój`,‘^ÌšðT‰ëˆ<Ôg)¦i«-͈°}cPM÷¸I^S(ˆa^&ED›ûÍßç©.ë*u6e‘ý=qÁ%ƒIüý³»øsIï‚uxŒ0©?~8¦we@HIz—¢îÑxÇ0•× ˜\€é§Û“‹â³pOú˜<8›¸Dyu&?tãD@×)n®YânbçVäÊPäA¬JŠ”°mדZ‰2Ä ¡z&πÚ)¹È÷REY@¾J“åáÔ×Å6†S4k6ᙜó©KS§ŒyèæSwÜÁûd’6¬O›äŒvà1ÌVª ë˜ÃìnÚT ‰ãç“:.Š ZÕŸð¦.-Èb8:×4 ™ µûpåcÎ hófö«aBá7Ãâr9W¯ìÚüÓs²*g˜=E•Æ"®¡ÎË1|æ‘)QCÀ%ký‰.Òôž›‘5³-a¦:9`]ŸZb>1g|K½IN9W ò×zù†›ë+£êñì‡8(¶]€ñsˆ¤ˆ‰à÷•Ú÷ûm-Z¢] !z© Cø¡« 4“öWIBWÜ—´$)„kÒ‚`}LX‚ypS6æREÛÔ—¡òA|vO×éOÝaòµ•)¦]ëeƒ­‘Âöyˆuµ­"'` WWÃê R°”d¤U<}€43¥ ë/¦™ãôWÍŒ“Gñ¤¢8#*Üš÷Ï®BMb{òîŒóC6Š!úë}l’„²§8?¢)R"ÜŸ^ªËŒ×\V-aZ3|Ó àb^‹j¤¾vAl–kqGЭÔ';ðaMÑ*Ët`ì\‘¶HHØ®¶ºÌ`^וš×§×¿HRRØÝK«u†º(P]Çò¥Ê‹‰e+•uy ’Yp±¸!ºý®Â=Щ— †ÛÅ´®±D¥‹øFR20ÿ¼4¨&𡞪f¤I[†ô3ïC´š'[¨Ï{0cñB`V¾ﬞ,Êé›–ddrÆCfà¯.WÍ™z_PVÜNÁ®??ŽV¬üÞÆ˜×Ú­´¶¥4Å~Ô £ã+~Á/ŠÔÌh˜˜âsøâ[Ѭëe‰)­Ý45yû.(+C>‰;R¦A¼H/a—l®: ¦!Õ;=HÞÓH2H=a‹ƒä2sæR–’{’õWI4HŸ$‘Ãüuae–ŽIaÉcµ¸¦EÚ&LE|f±§v ´ŠSC|,Í@³—mEEÆÃ‚oW_k…F„@È…­pe1¡ ý€Ç˜DË ñÁÄt&ۃ߸©skW„€Ìá§„åKH|_äIUFªê°\h‚à(#Ê ¡GE¢6—9Í]Õ\¦îÿ#Iƒ:Ü”7ÅÑé08Vý$¼ˆxÙ%|ˆdJe ¯Þ.ŠÞ¹/ÆÊF~¯èô¾mþß5~Àó´4ÐfÓȯѽΚ­n^tÐgFjÅ'4“×ý FÝðFZöz·6Íìf+M¯ôhDÐ\¾ÓƒÇ¿¸üˆhoý³-ÿPëÄl± ¯¶m·°vX\¶—Ý¥å‚Úf!â3ãB”ÊD=›žtœúyÌŒ^‘÷Aî³(ß´>\ ‹n 3[cH—‹RÉÙ)mÀR˜…9ë@„ª`¡iUi‡H ð¦8•Émæ-%1plŠd·ñ½”â2 е’6¼íz6LCÒµ‰1™–†ûï 7Éø}{§÷Á‹4«SºZ:6B†wæ$LcÉF|ÙþKQ)ã?K‚CÈ”,‚¹lw‰Þà4b¦ÖT)µí§•8uBðueW&xxðQ#IšŒ*ãvÅöÊæ5Ì |g¿jJŒãûnþ«9ïЮ9r$=QG×LÍÝBü‡ÅØ xc®%lAþu(¤”x E¡Ò Î äÂÆ˜ ‡£%äUäJ.é¶‚;ÐÛ0Öá~SÚAq-ÄaÜÂݨ[SÚÖksÑP—W©Íf“Ø^¸3{*S+5Wêt]-?„£)O§xã’ÀmÓÊÓ$Oþ¦±1W=“j1ŠÓ`¼xòQˆb®ä`¼“A'PÊ#C,Š’Ø qú‘-cñ­0Kª&‚~_1Î)çðÔê\~vãW®#¿ræo)ˆ÷aò0ar^‰Ì{%]¼¦ ™^—„—Ïh(b8ryßE†Ö*}·ðyœ!…´hàlYý ÞÂ)f¬Lk ŒÙZaÁ°³.Žo̺׻¤Hõ‡ÆÀÏIHB$_S²>é"üê;|ÀziÛ cà6ˆdŒüN™JæNF`æ×2úp”¾º“n°èy}w'ïD’0‘$1¹ “…ÛÈY4„0ŠÝL$Òô?/¨>3’—†‡d_ö@ì²þ*Ô¤Æz\ÿ\n˜$öxø—Y D}R/@µš0ìŒ0`ÌÆª¤)*Òü³5‹ÿfpS¼ÈÀº@DÌšt$bô÷ýòžzÃ=Û'6\|Cyí2êñ³{N.‡,Š™àf€f7—ë[†$íÌãÕ€€×k‰t—¾ZrÚæ"ØtÂõ!i·œiùŠŸqÌ8?³´xx‹QÛšˆ]있ç7äþ@Ì;X½v£¦Ë$ª0 Â'ÀÎ8¤Ì;=„èºÌ÷ø«Þ=Ñ‹jýv†‘p¨‹a¤‚Ù³W*ÂÄ{¨ð9¾ yì[!"kãq~ñyñ20ª–’/©dôýfù¥üDÆúˆ4æUUzÞ"˜›L]åYC;¢œáˆ5ÉGá씼Ûž1—ASv ZOë4FL–Ísƒ¹XQû=ìHÁ—«P×±êKÿî\õ¬Ã]]D¦¢j›¤UwS¸”HÍ) {{ÇÇák—-‰>'£TÔ[›õJQ}•¥Â•Y3CÙB¢ÃîöÚˆåh±ôVÉæ#Ó²°{KbÍÙ½…ð²™m“æå}&P¥p4Ó°Œy K4’"FEFãè´”`äÅãAÓÃèEªëH ¾²Ýd ßÛÊÁ›³dëYÅFãSÐpApä3ÛT®žH}«;¬æ7ß%Ò™HÛÛeK"øo³áÁè[*!?´$DJÝÑO®-ŸÁ‹?º ϲ(íöÙ ŠNkLIŒ‡ÃD¿&!œ[ÄѮ ¹% %å Ž§Lµ ¿×ÃA*¡Ûñ©e­ ²á:Pm ÜGñ…l‘Ï?ÅgªH!£‚_Ù•;¢=•ŸØ¼&KªïÞ²3-^Ý…¿OI%ßÊõiŒï‡õÛPÊEþC:¤c³…¬Ùñ¾Ø¤Ò¸I†­H~|jGÂç —K~ J\;3 Ù-bv×è­qƒšŽ'ä{›'(ËRœZ‚á.é#KDÉù¬)T,|’ý†kÒ´ ¾“†xàf ®ìf_gíPË¥‹u=áìY št·•‚Ô‚ˆÏøEÑêÿ?Â}~M€ö\ÎäZ pë\ú˜€ò #…Yò²°ÊŒ4¿lHõeÉt¥µ´ÁçUêžÚ‡Ìü 𠀿•@»´:Ï:@åÞ=JX3Dw9”7FU£‘šcÕ’ ·¬ƒu§š¡ éu¹¿#¾%Ú’a70Ö%‰…1óDT!u‡ÅUÐ:™E±±­» ü'@D kàñ-%Égc(X{9‘ñã9J_Ô¬TŸ}¦0Xš´­fdÚ–n¤´>×Qz8@s,ËÏ¢‰ªJØœI“y›aŒhhlZf +qd»=Tˆ”DZÖd —\¸‚’rÕQ1ÓÕúnI;. ïâs-{Ø…„ÅJé qödbgŽ6•4ó1$×&xàssÞÀuI‡°£®j¦2ŽÒ³Ðú ?C*§\œSî+¦¨ÀÓibÖÔ&‘½þ„Ù‹dä^¿Åó5&Úk¢Ð[y¿å¬•ãâ¬Dî44VÖþ^³g9`íÅH­jƒ½>à cÃ…£ÑO+îðèëûâ é&ªç‹€w»ˆ>{ªVwc$.Ÿ4w¾ÏUÄ*<ƲÀÈ-i“Ž¢{²^Í’ÚÖ™äÙ¬~WäC¸CL$6pµ‹:§2×mpF³ùÝãË„#)ÆLi³S Ãi/¨iŽ• Ûòa^´ „k¢ƒ ˆáÄÝ‹*ýŽêÇ(°ïÕ²Hb¾KÐ{jÉÈÞæmÓ:ÁS]â¶ý|V¿KÚt®C>€‰†VCGkBðÏ1+r]šÉýy¼Qê´B‧0ß–e¹€ù/*¯ŽEe]W<ÇätT œ¦êé{ W–ÁÂÃÕ)8¬b½=b²írOåI¹%­.ÞPç-Ba-y®ŸÓ+“úIÁ¸¸e âÍ0HPtf` 8<á’=Ï®>¦‚)_jØåC¦ï¿Â!Wmc¶çäoˆ'¶((ã¥ã¬5h`âU&„ØOšéúœ©\—ãW¨t”ó&Îy÷ãG³å­¤6п ÚÅ©ZnQ𴆛q¶p”)S£­€qqnïã0±ŽËoŸ¢ƒ­ËddzñWeÞViÚ8»—lÇ`öÅžŸšOh=š”s9çu ? ¾¶×÷¿¤í ·f ¹%$Ù'÷Ö*mΨ%ôÇ;UÚb<ÎÞ2,º)’Ó’™ŠŠÄÞ¤Vjg~mÍ“ q.ŽvÅé Ħ1Nˆ}ÒfÖ“±ój„Å:–”&rG…ø¸5ôüFÚÏCEû4c)wø=noîƒ oÑ*Q挫7xröZï´Š „ØBd3±ÿhø¼|†¢“é5d…+GÂõß9 ª@øÐÅÐH£ÊñÉ(t•yµRx°X‹t^5s S›6ÙwRàxR?8^+"ä×yH294ÁæÕÛ<-IP—ÝÿSš^n­È‡@@vEü ™žgJ;éH¦4‘Ÿê¨êËqˆI<ÐZíPŒ‚Ôµ ßÖão2éýIWaÚ=%˜ã8D›Hƒm‘F³èÑ­‘ó•?õÛå?IŸþö¦…Ÿ-ðÖ;†¦:ÅTŸR[î&׉ˆ1B7±œŒ­†“§EˆJú'»]lÝŒ¬†¤ ŠyŒÄ ”*qïÍ-°Y(-ušRwU3È,@Ì…©å#Ÿ_Û‹§ê¤5­wk‚ĉ/Åóñ7x˜g*àQ½KùŽ©à¬ƒnG7p{›îrjmrNýQú ²úÃi¿Ë§…¢'Ms³.Õ™‰@:1ÉL¤”‡J£Í%î½°*ÿÒ/¹à)¬2áö¥X½.m ={i:f^P+Þh}bØWໞϽó®N(ÅCÙEP´øÔ!‰®•¸Þʇ+¶î¸mTby{>Þ¿iÊÆO¾ûF~½­õÑ*¡cC¯¹ð|ÍyèpàÓ/a˜°YHPo,«ÖVo¯—ÌmV—dÒé…]³½–ª-½‹*é|RŸØ/RÊÏØŽ4f9p^HwñÖα ¼´ÅÔÕ-ä½—Åòï Dm4–$q+Aoy6T˜Õ2tR¥N^óžNG!•¸²–Ü?ý~IÿPƒ(ñÝIYàVÆž.–ÆÜ„$¥ùè3¶Æ2§W8\fÅRT®ô > stream xœÅ]Û’ÇqõóšáoØGÌ8°Ã®{·v)Q’,’õ úaÉA]€(SþygÖ5³*«g¤l2ìötW×%/'3OÕ¼¾^NêzÁÿó¿_¾¼zÿÓpýüÍÕrýkøóüêõ•Š7\ç¾|yýáS¸Ii¸rÚ–M]?ýê*=­®ƒ¾ö«=Á‡O_^ýù îàþ;áÅ“ÖÚûÃïk÷þ³þDºóû£¦ïè®mèÓ²8xÇgø6 Ϫ8Z|ú—pÉø“ZÜá×8åuøc}"µ¸£àN mCoKp–~{¼Ñô&l’|œ­ƒJ‹Â—ñ&¯ÊYàÅÛ–ç >îÜìá¯G “«ôáæúUjË9U~ĹüîxcO0‚Å /æºñå1Žúz‚¡À²¸cwÐðVÞ¼†gÜámjÍ/¾´f7Mšx–Ÿ„FÞk/~Q~Vo|‚7è°‡žÇEQ‹9|Ýšÿ¦uÆ„¬`üÔøÜ¬ù™(õÆí‡Ú6NƋᆇ£YO‹‚&±çN:ùXÒu ¦ö{^ÆãÊ,j$tþ¿ÉM|.µp‹¿~½Àq€¯_“$¥oÚÅ7õâéâ³vÑ”‹²ûC‡ªÍ¶¦¡¢ÿ~¨Æ­sov±*˜,? +Ë©‰.·g$+A$›TÞO4´ÜÀYÕ ugh]pŽ¿oNVꀽ¶Äý÷ñfÁ„Í“«Mé‰Z7Ɔ¿Ì‹ŽÚ.ãìut¢1`ƒôÜDÌp7MÖúÝ{Ërý;kŒž$ºÛ-#0xÄ6‡Å!ú•8ÄÁ€•w†Ê@á}Dé±s¢£{V´5@4˜Núq~¤cðƒu­• 5Ep'¢pÕ·Ñîù!ŠŒÚŒN潫­ªC(ÔoëOÖ™Ò´q—„Ø-œ¢„5ü&¹0"ÞMp|ÎD¿¶«=`¹”Vtâ%@ïÎ H¥®Q+îŸú3h ñãÕñG‚0z1 (ʳüÞl”7»5¢zéãAð°ã#ÂÂ[›Žµ;¿iàÚñf“[]Š:!tÚtDçÄw—ɇØê,¶·`: qm¤“}Edè‰jsˆ³/ºÖª‰E¢¼’Ý:“¨âTñƒ‡u#é0ç}‹ÚòÓЭeÛ(}Ë„ð2y\l”jQò›Žä9YaJ$ˆxi¢{ÿíÕÓù3 ¯MyhZ^ˆ #Ýlìd;†ïeŽ-2S7p‹1lÙ5'+ay¬‰äAxlš£_Xþf©.†­HÀ¶Äò{âתœ±‰+¢ý–Û‰1žD¿¹º(”Ý ð6ýrÌ‹®)÷’ ë³i`€@(Ð%Y–?5ÎçÁõ"‡’ѵîT³ZžtE»|ÙÐ^ÀZc,‰3f"8b;aÿï™àÇûAù›L{ ]ˆÿzÕî/2½h*Ó¨åM¯bºÃçǪ«OÊâD´RT§#ú*[´òû£³§à3¨!ž« Ím ö¢!ÓàѦ½Œ+*°d{Ch‡Â÷æ“Êx<±UpèòH-*´†\ö¤/?­¡x죋•Á#Ek£§!ÑC€ ¤+{H²¦u¨–5?väžË­ŒM#ð 4¼ÃYß@;䃋0ù®7¤ø®l }¶Fo…w¡”ÐU§1¾ÆŠ†»õÑÓ«O®^_sò1¡ «µ^ ‚±¯×N{ q1GüáÇWïü»ë¿|÷öÙÕûºVWïÿÿúð¿€>þåõ?\}ôñõ'ÌèÇiw 9}œ –K6V/ŽÆJû” :#k€ÃðžÜr1ŽË²–µâ.¹>›7Ä𠽩+óáXÝ"ÌÏS¡ óh@‚5”f¦ñ²HgAh¼uŠn²ñÆ[o¹Ýå¼³Ùxx\¹aÉÙ„WßËÍÙ¸øƒÿ’ÅJ²³s:¦œ©^$ÖJC씊g²Üœ²  ða+êù?³œéùN4ÄAf1ÿØ­vÅ|„þ‡zϹs©ùA{ø<,Ý×мÏ)mpr2“øO‚Bg™Y þºs"-Ë™fŽCÎlm š g­ õ“£³€ò?cðÀc h·ÞN­M™û_´‚¬Ž…T¾iV—àTJPôtŒ£rÀ‚*½É†¥K8ì–ìò1Dw©aáP–r'¢³F˜ð¸l„ñqÚ:ßu¦ˆâø¯Î¡ø8¢±LáB5Õºª¢ØR5« y¦Õ ɲÐÒÞƒú١ȉ#*:Ön›bŽÛã½ÎѼ€tsô&WWª ¸ãŠjÜ¡;gÆí¤Yb¬q×âÅæoº0Œ¤/(øÀ®©ZkI’YjkD½RšÝ»šEß`âŸ¶Ï ü$7z*Š£òQ‰V‘Nåt Nw<¤C_PeËÕ¥Gc;ê|°]¯&0õ•ð¸à;£‚B=¸H#æ2D½ü‰¸ûL;&ØõbJ.äÕ/H©oX1ò¦Ôó§ñ¾7õ¯–`×5m.%Ëk–<õ·Øhå)ôj;Î2Q½Ë²ÖvµÄäq&â³ Ô³à$ÑùKûN¬M—·4ƒßÞž­¬ÝüÙ Únj/e(Ûl6Zg½4h}, ÀÓ†5æÊ. »¬¥ ªmÉa”*ZË+ð,û*„S‡`)ï ù£™ƒÈIƒs É‚«YRÔÿ:ˆ¸Êžd%oG –§…C0bÝHžäbR ^½É$‹—ýýiÌ7 ?°^{áj dêP»»0ƒˆY³ u3)Ê}q^Í«:$ßÅ[ªôÕX‘ y9i\0×gš½€ÕË­ZÔðôÊWÌÓÍçƒÔt³ï°úX*„_ üùg¼dŸGã ˆÕ;!.ÿ°›òj²Ú¯M KÚ~ ”ÃÔ…áy@¼ØÃÂØ-ÄäeoêW]„­T†Ll‹• 5bK™6Î}ýÆ0¬Òƒ`K™6ÕTß¹JÛÿ'9w¥Ï$Msô' Åü{¶ä)Al%·ú·Ie´ÏòÁ-1'ñ2£uj_wÌs&g›–Gn]H!Ž$ØÑ>Ñ#V›beÌ,[·ÕŽåÔvΨ0×qbÖ½ýVií”i‹YÇG²¡ÖäN&äŽÔ•\³ÆÍ‹™lVð£¯FÕ€[ó'ߪӭ%Qdìyò&¤üÃù!eŸ0í§Ï9©¯¬ÀÍ ³_£dŒø^Þ;]fÔ%h1RQÃòèºh; 7`Ò:n?©È KLÀÊâû,Î뜊0 ¤óC_eoÁ"E"êÔþÑPߟ8\Æù=©E¹qbÆ”-Cr½ÑkYÓY}ëcêkÀªMKt¿þ,‚"!ô>¯VÇ s,ÚpË&PûÚÅ÷¨iNñ·N~Ã6L°;=“´wf h'¥—Ó,\ò±<û÷å ¤h~m8H~ÏϵðQP2IË89uÞu–é“‘!Críâß(º¿€Wƒù Cì°eóÚ¦^ÏÖ(±epˆ$‹Õ‰×¤ÿoGYæE_Â5½ÉüÁŠPªŽîÆm !Z*ª»ÊT–‚rœ‘“óYÙ k¸  %ªP.÷‚îFÈ4Á7=\GDýÅseF¶°5•ë3bL(Q÷6µQ’JÁ•HÀ'DhX¿ƒÎ{ïB8|p4øNP£´×e³Ñ» ûÑ·œ;•j²9Ÿ©Â“äÀÖ½¬³¦¢y± övƒØÊ¶¬¢÷Oíîjy[«¤@uqkñÌBÝÅCZsV â.K‡Þ:4•¬x%·áDÚòÝήƒàE®qÍžTIîÄ eÒm¶Üæ×ÕÀpöe‘þo ó çרS!¥!XE` £òû¤¸³%6òm¶¢q >o[£ésá+yœÐ º–„pYà9«FJ»—äqÐÃ8-–²û^‚/3-}[Ó¢nÛ±8N- è_sÎM5v˜I›Šk/ŽÈøb$‡ˆGJ·ª\ÉŽ„2,á8ßæC@JS )…4’kVg…ÇÙ(-.íñó>n¶i'ó°ÊX{ý"s^¢åð'¿ÊÅbÆâóXqëóH¦ RüÈw ݃¿ù3ÞÆèTd‘\ö‡…ÚäÇñò¾Ìq¿V®M ‹Ÿ…Ü”_(ð¹Ì.”K Ê|ëÀ4"ÐøýUЏµ§ÁuFÚ8Ã(ô˜P‰9d:‹ØAšoy]>-`¨Ñã}Txxp›`ÛV©~ìÓ~«’{‘‘Qšî6X>W_èEâæà)ÒðuYîèÝc–³æ_¬(ÈEà<.¼šI¡ã7`}fUŽ&ûFq@F1;Kú–)\—„m2KøkB")šX-9Î-*Ü”öù€BXi™‚(’ôŽÔ×P7¬då ¯¦Ïs\C°DÄN°š½n•Ðý‘™hýo³ «©€¥Dß4ñj#ª™5#ÁÿLÜ]4%Ï w+Ä/dß…œ)ëûèMªö åãîfr §7Ûg‡ºÒEX߯Ђg)¤ö“TàŠÆZÂä¤LNŠ×[Ú ²— Å|5 Z+Ÿ¥WbÎBôBÐÇz/>tÇL|ÌÎó "÷y¥¬=7Ýg¦ :y[]H¯](3$Dw á“HL¢qNbJF2Æ) z?îˆwøqqGÜÀ±uqˆ7&,vüFœ0ת}‹:Gmé«”ÞåÕ‹<¡ÜñD驵ÀJqÇx#õÄCf!k"åš|4á:û¤·ã“Ø"BSYyäýŒ”Sã›yû¯‡HõYVWÉš+ùÆ2[9 zEíƒëœÅ)ïóš ÓJí–2Ýl³HÉ-iiï39¬¡ö†,ƹ“:ÌÜÍNdúïS§¡ƒè¡óv¬Ì­î"<¬`£»»î0‘ÙÝÌEƒ–[ݾ žÉúT¢î8>¦Ó}‚¯¼×Ñ|bÀõY°±0U•—CV”Ä/ºEÕÈ‘XR‚Ìe»žºp6ͱ…Úðš Òí˜`ðÿÙvŸ8ŠpÛršý’S „x­ìœ3ékèÞ-•Pâ§bÅY>‰ó´öæƒwš…‘2ðN1$QªdÀ6²Õ­”Œê7H ZB°9†'›„ 2OsÔõô“Rð1ùGp‹9ÉGEHæM$î<Ï4$ *+"äždc'†Û²f¼눰 F›TΓp-ó÷I+!7Ã6“²Î|ÿ­kÁÏ- \9~¸Í›Š»­ Ò~à±]{I*<6·ÎŽóÈ-IoÇÔ@æêíÔg“ùÎñŒ«ß9‚Â5ôoߊÞÒw%âN8™–ª/e>' T¤:ô½>ªdqU€-`~}¥¥ÃC8÷Ž¢ÝQGEÆp|µ3T÷«i$ܲ&…Dè+[ù3:kcd4Äþ×Áû‹¼TZçБçí"D“í¯³4Ü'<ò5‡ ã"òfIu|»Z)3d'}='ä/zî+²Võ‰‘…º—¡ì”„Ué\-¢’÷ÓÓ˜ãlqóÏÏvÛYוÀžà&iMøÀÓã7Êp³UöÝ쨀°ôÛ.Ú‘8ßæsúáð¡=MÀóìNl„ÛìÑiëcÏ'+½~¬ä S4’ÕJ·ˆ{ˆ3_)•0up%qn*5Ópe'oÞÊ1ÐD°ŽYºAn†>Ê>ù‡¨ûíÜÀ>¶(©n²C˜ˆ1SÌ"’b¾®4ÑqLÔh@T5»nz§IrFqËk y´Œtع¥¯vñì·83Â$èSÌNN0JíM ;·pp‹ÉRQ*ç5pñ˜8­t¸ פĵ´ó°voÖÒèf§nH!ñt€¾¦1ö™D0)ÃîN¾žj? –é६Óe¾HJÿýc, jbö§Iï@Âl[äu›cC11öj)¥$¢º§¼$žOÏ8ªPI‡täQµîüDÁ9æ¤9Î?P¦ÄÓãçE_ûƒËrÕP”nVÐ4Ö&EÎa3L>¥,¼S\*ìÅ)—Ëtå';ÈŽßK¸œù ˆ³í+&n0Ëb SÁ‹Z*ˆyub‚Åé¶ÚkòñC=£¢ÔË÷¼Çó×Äh§mÄádŽ>cIdfb "3Ù“"V‚'„о|…r¿_¾ªîÝVvµ9}ØÛ7™g´ß/$Ò9J“Š0›8ûÏ't!â1úT9.ºW4Ø.‡~(–ˆ"®¤õê¶Iv¯äÎcOé³wâ äºÕl L+ËE ¥Øé‘½±ìºŒ}®ì‰~ŠÙ¤|Â0§(tÒXS©2eIeª41H¬'¬¥BÅŒfØ×Ü•6q[Õcê¡yiž?C^ñ`ृ—ʉcA xIé‹LòC­þu,O‹œsgÅ9!çžµôIÜYꩬڻž§Íå¢a·÷%GHd‡‡teGvSD×J‹å$ì|L›N±;{£Ë¤–i‡†COŠˆ þLNaNüî&^1Q M-¾)Ÿ’‚çÔ8]í’Î!» ô••â ]Iÿ Ê! ¢G9i¤;{.yKN¤ÚzÉ‘ד ªdQÕkݺu6(ë(ÍçnÑŠœ²Br«!d\Ì­ž­ZHµ¥D"žð¨ —™]˜ÕNë®çqinð Â.¶ãƆ%J9Hý.»m‰{ÏŽîbRœ Ó¦hàcw|Æ2¶ßDÄK³ïCÓÂ^{9ê+=W¤û|É1‰[aˆXK•cil8\pž<Þ©w˜Ù¹Ž½KHÍ ðùÍ8_èQùýù˜á鋺B*£ D‚ã:’ÆÃ{[³”Ì’*L¾?ô—ƒ…Ì«?Lj6sŽ{^’–.ƒ€v BŠ(Zêbº@KËỚә¨—žŸÜyåhiB=šùöš°‡9”©$4!9ªÁ»qRgWuç—ynã÷Ó¾÷}{ìòÕ®ûŒ m/KÇò_y†úí;©„±øwt,),xÛ´&wy¥Y+²\ Û-“ãÊ ±Ðòò£dÒeþ ?MˆEzç@uÆ<Ýš˜LCðÅ!D!kéû‡ö£™7D'¸6…( ëÃ# ‘›5Û×?Ùþ‰Ó¹,5°>yé‘+…+ŠÖß9Æêòi[J 5·ƒ¤ z;{xÅ‚çxiÝ!°4s"x?ûc€X¢ kZû_ë7¨Z€'Ômì§ÏjÄ"¨]Õ¸+dŽõ„¦b௽­ÑßäŒáæ¹MΤOJy"¯úÑ%<^*…Ž^³ðèšHn¥%ÜíB¾ëß oÝ>XŽ[nÛ:Ÿ’CˆK6äáÄÍ3ü¥¥ ¾Û"rh·ýø4kƒ65ìò± n{ç„ùîSei>Lj†lz _× +#‚!lL`±EÑòqCÌåï`Áñ:ºëTÄô¬¶“C5p¾”Žd£N.A™ºÿRB—ÛMe…Wì‚#ÃÈ™çÙ䌼Ç&è’VäsšéyÞF9¢sõlÊsÛÉ2×`M¢]•Âñ’„R2@u¥õ{dx/æQ‰I˃¹q #œ“L´¹ig©¨Ì¨y¬þ”(<³ÑEBªÊ¹Wß5UÕÕv£ö̹µ„g0gáŒË¾ŽP 2ÿQáñdŠžÎ$…ûåÌ1ëİaø*:<oü2S”LrCwFn> stream xœ½][\Çq~§ü†}ÓŒÁŸ¾žsäÁNdÆœ8ƒ±ò°"¥¥ rwu¡eæ×§ª»«»ªOõ™Ò A£Ùsé®®{}UóÝÍt27þSþûòí³_þi¾¹ÿáÙtó[ø÷þÙwÏLºà¦üçåÛ›_¿€‹œoNë´š›_?Ëw››ÙÞÄÅŸŒ½yñöÙ_þ§£=ÍóìþÇ¥/n—i:Y7þíxëNÖÚ<Þš“÷a¶‡øí¼˜É~‡ß.«™æÃŽî£¡|¹¬k8ü×ñÖ§Žû¯G{ø-<Ä„“]ÌáŸÛóÊ Ý<þåˆwÎq=| _:xyX¿9º—Ç—ö'øèqkY„ƒ¿ÿ Þñç£9­ëâWzù²8vÉÀ%ÀgÏ'gíÐùžèìÉ/(—9¯«Á1>?Þøèa[ì#£ mÖÆ“]#¿ˆ‘ôÓönö1“ÀYûß/~G §ÆŽî;M œê‹Wp’n>¼ð¶üåÖM§Ù¬k¾àáhçSð@ãwy!˜ÃÛ#\ã,èKXá$¶ñð¼Õ{cíá{ør2'ðø¯q°4gÒÿþt\–hÍáuÛ’¼×Ø“s èƒà ÆDŸã¥.=øçíQoˆ/Û3Àõ¬§–òöÙ9þö»´¬ÄWƸô¿ß#:çW Ï¿øt7®ÿ©ß±u¨”—œx˜ÕßÇžøî,„9ÚtãÛã­.›£oöohsÚ…Ëá‹C½’=¸ÞôЖð².ý«#¾3æ=qîóA]/cÐ_ÂEÈæp§"r^?›…8ÅÎæð³#0 ¨™ µ&ÃØ#¯l >‘N!&2¼©ßÿt´+<>ÑÈ>ïï·Sv‹²Œ‡8Ó‘Í&¶W1*ð×ÓuEy£c‹{U·‘d¢Ðå7ÄÉfò|ÄGÒ̉R¸ŸyÁý4–Ã]¼<‚†y xön€S,„w Í+ ØEŒ— ÿ‹c6ÐÎaAí O_ <ÈZ<1zc³wí©½˜Ð5ùë‹ß—Èiüá9´?#×,1ÉVc«¿ƒ‡Õ[\r‰ ÖfI$ê½u·HŽ/UòÃa×y_V¦•¤¥ƒÄbNäæ§Fƒ&oØ'` 0³ª ÞÞÀ„Ž]H\6P] Q§)7úK»¼-«hÇ!Ä4‹J¦W•°.g>BäæcމÙ €l­K°D?” <Ö9¤cŠè]Þð ìþÈX"«‚¨§Šdã±ñ±“<ü#üÜ ÐPLÍ6z%‚mÛtEYhœVöŽ{)˜L‹ýO} Óõº¸Ö­µç>/ï…—± 7d]Ù~j^ {ýsâÆÈ¿ý1É‹á¯Dê ¶@v[ÑNxj'8k=·0(%ótšà…èâGÚòêc)¸ øKEÕ7&Ö»Þ‘)SÉpñzÌjì]{©°-À± ,Ê4Éü³RÙlD¶I93iI–2-¥Õ)ޏ¸¯›(á›=HØ\õWaÑÊkï¤*Lû*Y«pCœ…UiŒ÷Ù?·N÷¢KlWt¥‘ ±B÷™‘Œøì§¾v¥hçÝgªN&ôw(nT"¿%/¿Ʋ ê£H®Q‹¯†‡vç=q¼_ÀËœÙú9ÛU–ûjó î¾w³* @CxN v6¾$^ÌÄï>ŸÞºÄ¤^ËÇ^£Jy¤Ãµ¤_"j¥‘Ù˜šL"ik®€×œ–Í–$oÓs~Ö ™GbM.ßC!k”K`|̪bÏHqØð®Wõgé.p˜óXX2r>€a5z„ƒYÎ dÅd_2€Ó“Àm 8þ]Z=]ùÓQÄXuQð©}]äŒ*LŠ™ï&©Ûî&Ò,šþ9Ò+Q¢fºÑÆlXÞæ¥ÅàÆ.TYPãWC"·£Añú7àoÜ#|`q–eK]!CE2u¤­èÔ{¡û|ÏNãËfFt½‰š»©ó‘s"õ„7w™=¥ŽpîæÅgÏ^üâ/<Äé¢eô§‹æ}êuºX[aße& ÌqˆÛR@ލÂÇEÌý4%"‚®é¢=O”\&?-‰»7FySu¤Û¾5M¯JéCg$×xúO–ˆvÅ Kš–=[ ±ã¬—Âb€F¨¥:+Ç¢Á¼2ëŠ]Ìy šÛ0ïØT\³©y]a,‚%亓QÌS‹Ššpü>Í1,ëú'-ÁžÜi‰{)ð,™Ƭ¤òÖ¥ÑÚ8¶aåÄ@á,DZ²Ñ\¶êz•F¢« ì}rc“!áq2æâ1° "Fzà>+R4û̵‘AÀ]ަ0§ËA‰‘a¦¬„§Œu‹uóaQN}úÏGR„A[¯ ê0BYMâæ_ÕôpV*0<™Ù§Èêñ¨Û°•™0f£Ü²& 3 ·9‹MT"â‹­×Ç,|Êšã…–é긿”‘…Æ’ËcdÅkšÒÒª [{ &b…Á7Yc |öŽùp]ð†©.» ÑÚz*h1¿Âgۤ˻÷k²¦ÈI§ÛŠ]²‹A6*Û±˜ $ã|øV¦=-˜¢PS$à-$ô'}¸i”PáVZ`jüRÀ[;OIè„~V©_D ã…Ê!EÉådY~¹¾w$övÉú|›p¶ †göº„3ée$ÜÓÞÿ‹<4Ó2[Æ’¶ †p÷yíÓdw%,†ß÷;‹'^R‰‚æŠSÆœû¦Í!r’¹¯‡ÆÇ”ÿ€Ó³Õ‘@nÞ×(AÏËmÅú=9IÕ/²F¯Û[UIEºâÒ§ãOÌ5¢—r§D|k#~‹—RŠìïº'6²v°*púÎÖw^jሒ™«_q35qX›ÃT‰|.ÆûFÑ&tÁqoUKªp]ÉÍXó—Ý^¤ùa9G+«?X -§…<ä,kšÄqmÂ; ÿï"Šœˆ²ÒÛºAÁ/õ>Ïì“H!yŒƒ±M.™ƒ#™|u–U!V ¨7gÑÉ';ã÷x£k)²}IÍ/µÐV\ÒE–íÈ}Gl½#Ó†Ú5æÃe‹”†h‹¶µËé«~eQ(6fÇ­y`¬lÄêì¿ÃÐKàø Â;0 9{…@Ü­äù4­øõPÌ[<Å…¥ì6µ×1¥¶¹˜L Uš„µOÜÎñHÞ|ýîZ>G±[õ2fÀêeÈ\‘`*”©^·+ùÝÖÏIÁ¿âŠA$Õ·Ñ—°š¡X¹DHiå˜L*‚øºD¢Á²/»3f Q¿C.µ6ñê9‘<äFPˆmÙ&)ð©_•hœDV³-‹7ÀB&HÇËÃ1 »Š—Ñw_ÖùªÈƒg“ÙZúø]99æíuÑà:ƒDó ‹^‘þóYïÂËrb®Zjbàk¤g_z“&6ÝÃNPº~ã+áZ‰.»]ÒÌAcF´.Uª‰æÈr¥ÃŸT³D„f驹wÌ iÒÔ2KÜg{‹ùæò&çrÐ}Úð`’yɃvò{“Ü+ôî78Ú”7ŠsVv.ú‘p¢Ö®šYü¶Ê;—Üõu’g§f¯”<*L)˜¢Du_““x#ÇàˆúUœMkb¯'`"÷áòÙ‡IT}jbš S©Ïå©G·1‡NUâÝÃ0'â¸æ»(%À«dUnSq±E >ÙHÏëø«eŽÕQõ[¹Âgld©jAK¤Šgd\›¿o³æmlÿÚeÓ]‚îå„zȦkžRµ #g²¨iû’ót¹#ŠWb㉗ÕÎ,é²etos,*‹`ð­® <Æ„›~¼pOÂÔ©õ.9QÞ‚GöãdR2nÖ}×aZ„9ß*õ)cËô³³`&Ü ¾¥oŠÉÏŸÔ%©Ã ZÎ6ÌÒ2MÝNËw–‰Öa{ÛjL‚jJÃiy„Ù;<ùŽ©-—2r훳y¤¨OVWTC"@Ò Ž %«‰¶ä^ûÄPH˜{3[~ÉGcA0¸±µ ¹®³¼ÃtqÁý'|9ÏËä·ìC £ép.©¯…"û>ÿ½ÛbÄûLóGøBŽ!6XL¶ŠÂ~&n^-j"ÈÞR-hÞ«ó›·P…=ˆª¤´QÌÏ;ïÎeê‡,"—B‡(ð iÝÇ0‘UAþõžëê…ä%“红ˆ—¹’Cb6,‡Lûž¥ Ë•\uw )=³îZDÀcúWÚþÊTÃP+cêÅåœ&Ë(4Ý‹Ba·‡ÏÍ\jç8æÒâöK 9ws ]:üüðq%£6°O„*jhÖ‘½r †µ[ÇRÛ‹-ÉV] â‘vÄ¨¦Üeî<'Vç±”Êõ\W­ÃŽžë %¬'UFs_šH WèIsQ˜$Ù‘ÙÂCÆ[à<~ÛJŠMõRa¯Ë´pdÓq¹´m1`‘5 îBá«8ý³ývMJÌU#õþs$1²EíLPBX&à2Ó'?isÂÊT'=чSSTW^‚Û…•èø“…#ŠŸŒfÖÎÕ´x¶+ÖP8£éæ>«”IºÈV·Ò¡•Z´ä´dü%uß©Zf¼W70²ˆ„7‹$d±b×äÊsjP¸2õ?‘v;#”©çiCga4s"°ÕvU#§#`ã±…*67#SâØt¾JxF-Iȯ¬9§²~¨Q†]³7Ãö1õj•i´pDïc­I¨:- ¹ gæû‡–ØÚ®;]´SÎhýúH±¶žÉo™þÏð}ùã§ÇÜf¬æ—"ê¼ödÖ’ÎZ­eÇ·IyVVæ×mŸgùOýªµÒÅÊ,xÜŸ¥sà+B:Ôn÷Ë’J¯;õ„§%M«u,5móB.1¯³tnUW°ìh€le ÏÞ“IƯëlE….½ÆœüŠS‚ZqäCK—Œö$€¼Cx‚–‡âCXÄP ™²’€‘èÃ-õ1Ó¹t(4¦¹u¤3œxæûÚhž}BÇÂ%=9vÞ,nv»Ú¸´ \*%l^Jìáƒ1mE^d0®0U,‘§™S"hõŸ¹ëâº3USöJ–veÜ„Àƒñ^2‚Gž:@ –•Ø%oÂÞ"QÔ± J.±ZWé~P„ûßUzç?áIŠi»Jp‰Æ`¨Šso"¨¹•‰f)H‰-m7³51y·¼Î Ø:ޏó‰C$õVŽÜ¾µÍé÷ý Ÿñ¨†±M¢Ðl¹âíúTÏ@jðüɳñ®yu˜ÔF]6 D[é“jêò¨ïfqHÄÖB–7;æ¸4f®Çö(·BN*öt/É,#¡R5Þ+Ä”ª-) t0›ÂØïžÈœXñçr‚!yVÉc€m߬z#bz8K³8 ¦@° à€A×Ï0ÑVÒÜÂÔ‹ˆ}¼»ßÃ:‡cœÞHë³;^AîÑh^õmyòmv¯ñéóUÎõ”Ð?ºï<°þÍU;ãŸl<©‘ÈoÙzïExbþçð?”Býl£púŠþƒÖz7ÌÄž‰…/À<~rLIC„æËlÓ“\»eäȨh´~Ä6e{k2ðÀk4ŸQêNpæ#j˜e–Ó©õm”1*ÍÝ7§ªÓa™Q™Ë‡çD0{ ÷vmÈ-4~A`fÒJå.µ„\â¾ÛÓhìË(£ÜÞö€Àþ ÿ“¥þŽI4›f–ÙÒˆ!ƒÖü—À®ÕXòG¼×&ïè‹ïy —À‘¶‚v‰}µ}–ž2@OÊ8:¹‰¥Ösˆm<¯AÖX°WD¥3öêÌ}îhÛî›ÝÏ©>æ‹Êµj‰Câ…eþª¬AoЬ‚ @ Õ71Ío«¥Àm»Ù®Ø²dïñZ vix¾*íL]òšØ7ÁJë&ñVQ*± ÇÒâ*æ&Q¾4ͦW)É3)Ù+w3Ùðfë(=¶œ™R·Zœëõ×’³ÛÓiy’ƒÈªpuT ¤½Óù±­x9h¬9*îߥ”) q"°÷GÅïùKØM[ ƒ°ÎÆÙ´0QÙí2ëF°!jÉ®½ž9ßc'ËazeK:ªíHL¶ÐÝÄç œåªogfIgwõ!‡l'±§I½xÞÏåZѦ@v ç´ÿa›“ÏÈ/¼ØÑ/«zœæ…=÷¯F­Ð7¿cyWp &­9òMq lWÈÆ-£~þ¤ò‘i:mÖ'øJ\Ø¢(úD0Pôòî¢5p*Hûó`J†ü¿ÞùÀ:ì÷jÜ´­s#Ó»vÉÅJW£ gv*×µCeè@$tPÔ€qÒvoÊY‚8ùËÒw©6ºôÚªÚÔuë?ëÔ–sH(–!Ùg2 #¡Œ±× +iîi2œg;´\Y‡Ø(ZJ“æž\Ž«PÀ¶D×å„K©î.¿õŸðc´ds»ŸÅv4Iš< üY?ëêœFëTô"*žoûaÎ…h}£¢Ü5jÃÊ“¸ÖAåS«£œUãyø™2º–ÊdÚ,°u[!`Eqš§FLæ•ÍL*xü‘Þë\kZRyn³Fy{~]Å´þw ÀüSEÍ ;3 —e¦BÖÑi˜l%ÒÄ”KŒ C¹ÇÍ©¿± vjX;ý¥y-,¶ïÊhEúvª]6Oêæ´su­©¨ÜºSfÇU__žÃ^¨4Ö…F/Ö¼©ÌP…±ôY^«LÌx¾dˆˆý5 éÚ*ñ„ýRÙ3ýfÇ|؉4Š6ú:˜³–FŸí·÷vº%joöŽ£Ã:Öt„üÍ“<‰WiâÎñçÊÆh±ð÷eì®·ÝŸî_v€ æÈ0¾cý6Å—†»Z‡Q‘)Ú;®h=/»˜á¸S‚+(³z†vͯ*mÜŸ¾xöïðÏÿÖn Úendstream endobj 181 0 obj 6876 endobj 185 0 obj <> stream xœ½[Ys$Å~Wþ zœqhš®»êÉa0Æ80Æ ûü ¤EÚØC ˲À¯wf™ÕU3Ò.aÄtuYy|ùeöçë"ÎWü'ÿûúÅÙ‡_¹óÛ×gëù§ðÿÛ³ÎDpžÿuýâü£K$$ü²„5ˆóËïÏÒÛâÜÉsëõ/_œ}³“{³ó{óßË¿ÃJ°7¬^V /]ÞÀÀ÷µ8‚Øým/–¼»?ïåîËýA,Z'w—mÌ'éW¥ýî+øU˜Öí4¬¶ì·E®~÷×=wÖí>Ãáþ§ò$^ ½ûz00‰†ø' r‘‚î \¤”ÖÛûOý‹l狽¤kt×9ä²®ÖøWÓ𮈧ŷÿ?)»ˆÕì>ųŠÝ¿ëiÆ ”€‘æ†Ý–  ”>ß$„S’ÇùÐÒ‰t)üùVj……CH—srý¦õ~ÑFî~Üô[\õîÉ>îvpcnš@ŸÂ~Aöj÷²ýv‹S8†ÛýóÞÂqîÚó6¼$ìØîÞ&QŠUÑeëìmž ò^£ƒË«UâJ×q„T:÷y™îM›îL·X묎ô+Š´ '„øŸiGN)~²¸£5yŽù®©+>©]Ö°Q),Õýn^·.Ƽ‡²KçA+ÕîõB­¨(Å*ÉáóNðå"tñðdP;\ où` Ì¯qU»+ɶÉ^›Úçcãóàm%}²™$ü$×mg7Yo˜<ÈÄg3+i}L…²8da„‚½®2ÉäÛ]Ò9çâµÇ“»(ˆÑÉím™HücæT´ZüKVJ´ø¸N ú¾Æ#À…;½ûv_ß»@7â¢×#"Á)n²‚•EbAë/›U%Yð\DÅšD>Â3éÅÂr§&n²Žs|Ù|âFÖ¨:efX$‹õ&‹Ô®‹”JedêWip™üW”-ÈC…G\¶aë‹ €”aüqñFñxuiOŸã@ æv¯àÏè,mÓú¼=ÖœO©¼)§,O^$7kȃ &[èûÛ&ÉœK©n¼ ¬ký¼Wð›'«ãæ`)]®>&îMõ5^n=ÓÝ“]$E»0Á'9m=µ«ï=µs\—•3à«UýrȺm4Ì÷+ŽÓ Ý!{i|ùž ‚[î›:W…kƒ†ˆÆDo:Ç)žà®Öè»Ë&Áwiˆ¬ßÑ ®èD]°Dߨ^Áèð4S^cÆU\âAššöb™ü—‹¿d‡FçáÀñÖ}Üó#/ÑÐx‚-&0 >äx"jB’–ÅÑr&P»Ò. \çÓªºÄ‹Ó8õœÏ5UT]€ Œfb±‚<@å´k­{?ÚŠé_β‹˜Œù³¢C0Å.{@a¡‘@Î!„q´õíoµ±(„WÅõ í® v!‰éN€Á‰"µŠmAö“Ô^6ÑaÈ?:S¥ÔdÜ7NÉfcdO•–Ón@ okJŠØ‹ ÁS5%ºÿ ¾\¬nØ‘€f¾ÕB,[NÇ Â#u^ ¥‘ø쫣B!›ª¿ýV—œ$H ©u=°…zj¿uÙ:å…·9HÕùúÖ&¥6¢2•6ô ã3YÖR/u›)1+I”‡¢„wÔIWÍ3†€ŸRtÑö! ÄÙ„¤ÑÃ,X³¨…Ùùœnc —‹+¸­sGóÝÜx¯.ÅEãñ.Æ]B/1ÑÄ“`ü‚§¤u6Œþ„¸ÀÔ$£•¶1¥ùM4¯qàZ‹;ÍšnZIsFS•"æÂù÷”Bl…dÙÌçÐsBW5’ÒVí9Ég¬ÖÑÔÆˆ©¬‚¶³¯£Á©¢åôyiX Õ6,÷Cþ„E³Gý$x†±Æ3þJ©š”vn^YÊô5ÞÕï1ŸšyD˜ÓŽB&V1“ǃÔmìÚH¿£dEX@šŸŸ]þñ›€g"uu$rÓÄÒjG?ld‚'`Á¸ltcøR¬)/_¦À=ÑJ5*üâzp¶Î)¥ ÑîIÆ+’ÔBÏ2ßähC,Ê,¢§œù¡Ò+Ënïyq/«`Üú„©)E&_óÀÒ cW²½ÈuM°Tâ ZpÍ÷ „#?6ÖüŠ\Ÿá„žfÊ‚$dæi@'®ˆÔaûû-Pœ'®4ÈÈ‹òn->ùžE¡Ù›2Š: çâq´4c‡]:Öž“”yå6ää(”o¬ ‹D5ºVLļK¨:2šHñ@Ät´ó‚˜~Zó ŽE#}ëÆqtˆ„3°P¨›ÁXpD.ZH¾¤èX+íHý"ÙF‚Ä”ÖJí¬8†/»Ž«§¥9cÐ.ÚˆA÷kJ0°(ûü(~Õ.mPÈò+Ľ8C™Ê¾Lˆ:!—9‚à¤ÞÅ(v‹ºÇâz(ëW-ÁèØÙ-CÁiAcB—‰Å®ÔŠT–õ¬÷©ôãÄ¢ö”ƒ$¬„²>ö;|Âô‘§™E"ãr}¬2 úþ>nQMIÜÜqºÜ›OJL±=•q0´±/å!±%òg!Pažq™uK¬Ä0SjºÁnƒox<)Ý苽pn¹H9KY¾÷ƒõFÀ|T&H°5¡„x¼!, Io°Ã!‡\¿©ƒ’Ðí˯©õJ*¹ëh°§[|’743& År' é6Þd Iμº~\ ÷8³®ÜüœcJhÍ@ä*fr’m* Aµà 'mDC{¤“¹š¬5Uù—#»ûÄó7Có H‘X@ËžSÛÌÞ¨ÃgmHÑie¶Üx ,I€<°B¥ ¥ñ1L:V³škšêLn›E ¢ ?•“Fb“¤Àöîq®Ì@”â"¯àq#-N(Ž+ ¹@{ªé–Ьøõëyþg©!’51”&G{¤kÉ'ÃÙómÝP²p!-WôV„µ$h4¾eÇ üm¦¶þ¸G+6 –%Þ'ÍA„ùfh0£&’à é–A¿õ´;uo2(,‹<Èna-­Ë€²L·(„%Ü Ñ¹R ³ƒ¨Ô) Éá'ZOcIê¿ç±d¦!y(Ó.ð¤ }:Oó“a*ÒT§v.6UÿžU*ÒÆ"mD|$S ß+ÖÛú™íƒ÷YÃunxù³†ÓYZŠM¡uQ”¯ x›Ê„ÙRž÷qñž§Æ[±ŽÅÛ½ l5sš¨©£F¡¢ŠzŠk÷Q$&!­íì#º8†t[ۋ‘ŒûDPb×È´-#fßš|N@Êd׉„Ž`øb/‹ÅW`$ù¤R‚… ”‰ 4¾ïš}0Ÿ`Ð_井Z¤aˆ7°°úŽ]×?IÉþ ­¥}ôS08jùõ³„KA¿ûN™Í·xÎú±]Vg\墨G8™¼ yÌßúÚ`6æ>v75â¬#ÜÁÛ?”7Q©9Üc_ÐmË¥çužƒÅ Èaf<4·¢w¥—× ²CîÞqóÁæÛCŽgóŠrn^GD™µºÚ\i`GjmyÖ®™*å(…µÐµz7h5Ý€>–t ìŽ$kÊŒº=F¥@Þ¸iEiÐ.)‹´#‰éñÜhXA. d Ñ•°³Ð´BÃïd«³çï¾ÂkóauàR°ôô”b¨Ø ÔT—6-=Ýcß-d.»‚ñcàÓ%Øw†‡x.„‡<Å"+÷½ë)Qãd…:¦&› QþÔ‡]쨿@ƒß[Rw·xÚ"¯ëT½­…ßX †=â‡ÕµÎÒÊ`£Ë¶t\,=i>„1HÅìq&o“Í­”³è[Ê1A«Ãf kÕ% J2áP.wuêJĈǪ9›©½¦ÐdÎD¸¤Üÿƒ%ÈmžqÅ\PG€°ôÝ5ßcbÄøÍŽâ¡ÈÞ•#}1D¼± dwãŽæJ ²¥có™æëÛ©†åãö3ïAæî$¤¯Òçíæ†d4ìÛ!ÒèYvM§ËAM:7êëx5!}òJ\;i_–}5‘/™û²y3GPÛÆó,Bú®RÞ˜Cš³EÕ7ÆGîO‹XØ~·Šm¬ä ›ÕÆß²–C¥v'’pw£¡þÝh!§(bчX~ü]ë“lÚ'—gÿ‚þw„Cendstream endobj 186 0 obj 4137 endobj 190 0 obj <> stream xœµZ[“µ~ßâGœÇ9)Πûå!T©WÌV^ Ë®½ëJìƒ1¿>Ý­[K£Y_bpÇ3©Õúú뛞Ä*ÿäÿ_?½øì¡?Üþz!ß¿·Ï/$ 8äÿ]?=|y ƒÂA‰Õ9å—/ÒÇòàÕÁz}¸|zñãòÕñ$VëŒn¹;žÔª”Ôz¹:Š5:áD\~ÉO£Z^åU4qyt„gÚZ¹¼8ž´wkX,δ÷Êýûòoim³úà%®míjt ‡Ë¿_\þåÇåKš_©èa)øN#A‚_'¹:£âòW•Aȸ\ã r5J-ß‘,Âù°<;ª¸Z4IåC”¤‚™´1Æ¡X> Æšå1<J9«c·Ú5|¨­Ö >„%Ôê`ÀCxhƒñq9£ŒÒ a—WðÓéŒÌ«糈¶ðŒ^ g‹:ZÝ6“Ô!ÎELúˆ+L­Š>.A˜V §º2&ZXA­Þ{šJŰZÓ¬Öo`-•6°ü%‘^A:%ÛÇç£ OZê5sÓæT?û$=„Ç¡Û÷U‰ÔB¯Bšåç6ô a¢ÕůÓh&¹wŠIþß›U*ó1Š ºÔ~Õ–É+zð„ͪµ‰éS6(éÀŒ«›MáÚ¸©àW°öÉ]¿§&ßuýîŠ)ÎdÒ~)<}P“Z­Ñ\žnãxlñòLð—Pt6MŒsÓò/|þ"ÛýcÄ!žBÖ®BáË{Vñ·VgežßÂÈ»¦ÈGùˆœ¥¡@ÞÒ)¼èAº¬!iû"ÿÔÒw›‚e!b4Ë4?¥´®ì öž÷S¦d4§¬¨“$…¤¯ å=|cËN0 ¯xD7¸oAcò‰•Á7.’h¯›á±‰*nš9áÑzA@F6‡‚«²CIØÙ³Åbkˆ@ O°™ò¦Hü | _Í|‡* ð.,¡?ä-€8Ÿ´ý·¬Ó¼œá â)·*8à “Ç@L^F¾FaÌ¿‹Ý|.ܳ`C’eF4Øf•°œ“=Ì’}x°¸b¨J¦Ù—(¦$ê|x>F9žX¶ä¢ÍÜw Ë{L§ì‹ø°ê„” |ø¦­–¤Šàƒžµ9øº¤;Xg¨uoMûiY+[©,‡üLÑ$,ª‡•é‘Ô†Û¯©£`?M~5ÔÞÿž \9ïÑF6Ç~>{Ò60 Fk¹ã ƒ´‘¬nà¦É$6»/Ÿÿv´‚¸¸a€Fæåcg?ŽG!å»ÕÞ`Œ×3kª³ÿs¨Kîg'!&]zýAÔ`"„-¡ŸÎ`Þf¸²Î9ÿ3B)Ÿ÷½Eó«Þ¶þô ªHS Ô™M¼¨^ºsÁ.`áPOÂÌN¬­Ý˜–Ÿ5iií× }äÐ!@Àj }+ŽŸ“jeԊ͇⳺|}‰§ Y±’ò•ÕÚ,%áØÆ¹E_ñÑÙ]“ÊúÐv×F²RXm¢ í“4†WăÕÄEs¢CG5e¾Ó¹_mE3Ô íba2H-kÙ!ÿõýHý” “D˜¦sãä»ñïþ Öèð¬µÚíÁAxmIÜdì2ΡzòÅB‡Õs‹hg ]o\íùøßd†„cþ+jØøE$eÇà¸Çaî¢MÙÇ·dY1}a¤ûœTQ‹+çä4ƒÑm²I êv³2²«R§pàr"Â{VÍü¡}•D ›€ˆTĈÛ: «,~”¬l'’­õׇT¼ŽÂ‹3û‡ BzK¦˜>2åœÛi~µ)åâ†X>ÔDßR„Ò«¶KlÇ—E0Ñw …¹'_Î'3M@ß)*˜edi‹è‹´¢ÚÓ€©êYw}TÎþœðÉÔ¾¥ò jU¼òš#ðŸS’"’·Æn§(<…UQ»·•”)÷ãÂ!“m!†hÞË)>šÙ@ŸXO9lVãZy¡Û4å¦8§¬ D!Þ-ÎÕÂÂÖ¤%`_„­ü|ƒˆÒʾ;ŠÕ[%ƒI$úP,VÂÊD>àA*Dg—¯ø^ø˜ú6°e,}ñßç$Bêì`Ã)ºXæ•ÑAŽT¢õ*±”Ÿ)C +'Á`ߌQ&©øZf5N‰Ÿ?¡]cÙõY{ý:‡ÈÃN“—Æ&…*ÓFDm[ãKõ,µ„Ì#¢º30çt´ Uz|VjÂûä  ºFrh^a;Æ6lÖFP ÐŽ¼B®Ášå·£&ó˜¬|=ë k¶ŠGI7ka%¿èý63ð”°’­M@ƒvù'•ðçÁ6”Ù“•t†®pë2ç^j ´7ÇàÁ–¤©õw½“Ý0ù~KlâêX oÒü™ËlïÕ,CÖl[Í&v*Š}ÝzaxVúÁÜÆŒ}0+~NK× ò’Ü4³ÎЃ,lÂ¥7}M x<$¬Ñ3I‚ïZ,y_¢›jlÓi)V¹07žI±pè™V'¢ÇÜû«—±/DáƒÓ&Þ¢ÆÑƒT×2!vÐgMèX(¬î.‘ê\ImÈí4ÿò/üÏ×8Ø®DŠ¢èŽ*l'+?ŸÃO%¾§T€"¶&ÎM_=Á¿¢Ma÷)*óª¦ÑÏ‹žŒ]DP:gÊ¡ª?—M­kkËnÙÔJÅ 0›–y9Ùë3VNÃÂú6ñ«‹º.hæ±Ðï¬øñ‡‚”ªÏ‚ÊW31úZ€í:Þçã¬ZÛΡ,ïìž79Û&èì°íÐ ·R¼®ÚÏwh6CH¹$up¡T¶´ŠQÖÐÜ{ë »Yq¤QQW¤àáÙ¯ø!¶]$o›Ÿ¨bn4c®®Z=vi#ßÎ/—0%›Öðï ÖÖZˆL€à6âXDìˆìžŠÆì*ɶŒ¡§Ýî$gU ·…#¾žu†tò¼ ÑCrŒ°½NM“Ù$¥¤ãE%½š{ð'ýÖp¹’óÌ.мWgocí»Ù–±c¶µÕP¨àk™÷wUö¢»ÁeêÁL*ë¹–6Kb¶SÞ éFïq L€T‰Ö+V›Óùvât§“ wèLÓ¯Wu4½ýKÊ.DSœÓ£:àEsD/ê×íaù{{øòC\–¥–îMÿ¹. Ps¯Ë‚w”ðÒ¶±©ò×úe}wøm>®Mˆj16P50t¥´*<äü•zViï©:`«dr-eðPŽ“¾It9X/sc(ÆmÍUPy6ªïíOAȽî÷Ü’'R«´±œ5c«-M½ë¤ ìÙÖ+F­åÄ+â—lzC5q‚]÷–Î hfùŒvx%´n\ËûC®åÌÃPÇœÕÔØiå#êÇi%ˆÖ&õâ|r{U ktõ XÑ­Þÿ+µs^&‚ Wµ-öáÛÄžKÚ ½¿ÿ©ü> )ÃTÏ’/-îèòMÀiظÁÄ€Ïéè—´\cˆý øé¤ ø‡(°3àQK71…¶XbtËGÅÒBvl@aóÿa¬!Ç"ð[d~-«ì¾ÏM{OÓË!Jëî%¦6¾Üê;]Fõ5~ÇXony7©òmÝ„>ÉÝô!2öï#$qwr– øj¶³fþƒÃ`™ò¦4-ìnQwsÑÚ¹‘ÙߣïPn_9!'Ýî>G(÷lï-q0h½9Ò5?D^ƒ*_n°²ÞoàøfŽt{«°Ã¬³9{r=³ U.W`ZÒ]Z£bKèãÑ‚õçì!ë M-¤¥+íuÁƒˆ“{õi¦Ôˆ0fka›ÛH­ébå»Ò¢MîqÖézˆ>)pkð1y˜Ì¯ì2Þ´Q4êÒõ|eybS`ð‡…¿•ùÐ"&xUovû©C|‰zÚM‡Íõ ¤ãyˆ33‚·$AcÝ´¯ IÅ÷5Œÿ¡>›T²Z‹þó´O.n[Z0&Cx°ˆs8Õn@ª^a«º__^üþüWsendstream endobj 191 0 obj 3469 endobj 197 0 obj <> stream xœÕ\[sÅ~Wü#ô泉ϲsŸyHª¸ÙI †Ø¢R) *²eË”-É`¿>Ý=·žÝÙsŽ$óXšë×Ý__Ö?O£8žðßôçÓ‹£¹ãó7GÓñøïüèÇ#AŽÓO/Ž?9NBB˦ ŽOžŷű“ÇÖëž\}»QƒÙLƒùþäŸð†ü )§Qkxéä :~:lÕè\bó÷AŒ!x6róõ°ÐÏ8¹9©}>­JûÍ#hU0ìÆÀ\#´KáG)7Ÿ zTJZOÃ<¶^pÂoþïzøGѬ Æ´6µ¥ÄæáPærÖå¹p0׌ðrs»àøÊ¤ x)4¾ÃŒÚxAÉQLBn¾ÂçRJ˜ê›AŽÓd¤H³ÐK³ùÙ¤iéÒ‰xŒRócܦsÜÂ8B€«RÏW-žó‰ÀØMkžæiù©¶¥¬&˜ßJCfvMø«†>[P}“åi„3è6¯E†óù`*ࡳ¶#³üµw‰€~Q DÞ²Ö×Åþ=x3È×ú¤Ž·èŸ½ŽxMä6o‚Àl‚{YÜVi¼T2ã ·×SgÔgM¤ «øÛsüMá@ëS*KšöÚú/?í Ý„»gª‹ÍÁ•²Ò’$‘Y€.Ó†ƒ_™ógZ’›fP¢áµ^Ê„Òt=x$E®ºR‡J€‡v(¼á—%¼ñêeУ¬ð] v‡+[™Øt;€1s¥®}Tê‡ëlƹàKÂLDa¶y³­Îîá6“w Ê­ÀeIØ?\VÕÖ3U˜8»‹7ø–&;¾†s©=A«õŒŽ,µúRš@ƒˆ Wru Êã@)¼*SêFö«þß}­Ð.aö¾8®Y<³bf[~Ö7³„y—`䥎X>]˜ x†Y›Ó"ÁhöS‘ Xi#Ëz_ÑùCé¸ä&lÛ·8s‘i-´OX¾X¿ž×pÀÅ¥ÂÊâ0V:¶&c^bdðÚ·tß ‡'ºŠ…¸¤Dr®@a¿€ AÎñ%«HÛ—G'æ/}ºã¥=ã¯RÏ…g„Å+X"˜µqò“ˆk5¹&ÙÉ€M‡k'=gôV ж@ZG!ô‚ nݸJØŠ1«B¾”Sœ•ënðJW* I6Þ5"»SR¿@+ŽgtkŸK¶^MEãç uŒ({|Žç+¶¥•à”­\õDTdB½1×\³x#Ò¯«£úÛ»dþÆ ª*ȶÿç45¼ï™À;ŧck<­'‚Ò{w§eXh ?€5³ëv2 Éœ¦"âW©gÖ«î’Ö¥)OÝ¢‰Ñë™…Ì67¥ÖWÆuõÞ“CBãÈ/A›"/k š=ˆ ýgt} eéÄ0˜"5‘žG“cPs›-ôÉR2™‹Á‹ñk$cÑüdÚÅçá$Πò“·r©hÕMˆö*6âu®Ù5MöÚ,‚µ‹e:j5X«:g|¹»Ãe`©•ìXê½~Ÿ’ü¾K¶å5WVÉð€›ž/¼¨–rÉO³ž6²V,Û”&7ìu•·…:o}¨d5ñê”p¾àßÂ&˜µZ÷Ú*ÑÃXª@íVUC49 õ<îÆôÒU ÂYø« L-‚u¾¯„«çÉ4’BºOkÖx9BðvÝê%—×ÅÀ½D‚Abž¬Ú&àñSû,Dë«çM4‡+)“,¼6£<´‰Æc¸L+ÀÑŒ­$lºv²5 óÐgµ¦ÑÒL£*ш÷‹pHL],½f²º\«Š³m#"möà&·Ø*¾3•'u8ȳ氇U«6 '?Ù³gÙ”Åÿ]d{ŸSÇ¡„`fô ­l£Ù ¥è€'§ABF8L”›„3@È@oâÊF/¬ÄÛÌÏ_ÑO¨V)s&F¹M£3@7õæ£8&œ0RPg)÷h@`Mq–¿C´<-J Þ‰$2—G¿¬Ÿa£µ¨&-¡MÏÂWñ9Ü"2«,Mœ"í6< Yr‡Ù…‘ÒÚç—(åÒ:×Mr®§À0A·°!s€I‹±«NWˆpgÒÔØyb݉:kuñeg>T-ÁŽRÁ0Žþ AÙ ™tu›we£"k‰°%ÕÀdzݕÉz‚ÒÜŽ/Y>ÿž¾äZ%®ÝÚY@äý 1bÐ^æ&¡é8‹­@ <ù’g` 'Ô,ÓàR½e†lÅMM¹à\~fy—ŸÆf®gŸ Êr„¥Ï‹Ö(ܰ»‘¸ËìÞ£TìsïîtWǸd‰€YVÌRÝÒoJ)G¤Ý \'r’8}‰ËÀCãW”Ï¡ fo®‘©èW9Û¢7çÈfT(…V‘4™ãlåSÆ-%ûqÅz J¤æ´º¡ÏSYÂ4 îðõÃü0—ïÇõ/«8 2̘þ ]‘9‡0¾Éxæ‚ÎfgU˜ö)7hæÝÔç]¶ñ½$†:ŽÑ žeëúa2ÔøÕ!Z“áS̉€жLàÝïë–31X£‹ ®¯Hjõ9¾ãw"T‚c¸¡—íŒ]O ÓS’4z™¦f"ε^F“—2ÏY’š}XÆdF÷ëZXö·Šîž¸M8 *\Žþè\ÙÑú óÓyÞ‰UpWhÍÓj\±ž¼dÅ(uGb™I줨°€/ƒ€SÝ]*=m­ÅvŸžôü÷†™—¬ÊyÏ™éRQÀËÙÏ,+ Öò–»Ëƒré’ŠåA=JÃüÀ¤\ë6Þ )ÆI˜¾IÍ‘· fzʬÞûý¨’¥2«v²æ²v·1 ÎBÛãÂËgƒ¼r¹ª:±ÈV®aiɘžÍþ6š: ½ÓóÕ{.O¶BªÉÆÊ€Æû1f„¡y)N×LÌ2¸YT„áY+y§©`'o±®U¦/R"xS`L™0Ü àL’¢g,ε®•i$Ŧ`,*ýrðdjõæ¿8P4»×e±hº0qð¤I†G"¸¤F©à‚Q#2'BÎr ¼F³ª¢N„a·ÆE“w‚Þ´@x†@i™œWãµëÌkб½ï~ª¨øµp½ÌÑÌKF’"Åq€awjQ™o‘±úÖ»‡¯âí¡¬/ªB±€¸ 4Ò¶”cs¬ê…VúšÈÁ6n²Uê{$àÖ3£·dÒùùÿò 2_Ã<,вÇÑÖ¡rbþëREã*9X0‘¸Rݤš¸c”ê´á œiÞM%o"Gâ ÜÖ,ÀýºÇ(Zø;G‘Þ…æ…%‚#)ÝžN+º»ulíÚ—g•d”’N0»ë±°¸­boË|©ê€Ü-«Zê ¤½.×!bˆˆ‡¸{YŸÛ¸¾œ L5¹^|Λ•ŸéÉ‘™ïÚð%›!/z—`xÙ ÿAyq €µ¢É‹½!îÿµQbÐpTÓÍ…ÿÚ«¸o6.ajÞ¿ª"þ5 I3.ƒ1L[уk "­ßŒæZ ;žÝ”eF&f*DĪ6¦Ä»QÝ6¿®'¹FµË¢nàØöb̵­DdðZU¿îÍ1”#ƒ^@¦Ìl×»th.2ᆠÓÒ^ [øÑÎR˜5€ýU›–ÅOsPŸä6fMÉôÃ=äÔì½Òûyyð*E»sbõ²ô9­Ë鿯:ÚOµñ}i¼(-1ƒØvV;>(¢2Ѫð;›”~R:¿ªëOkãËÒÈòÂ?”Æßv¯™½ó¶·åÚx@þ¹¨ÛyýágC*8Œ”;ÛsS±7.¶½©zx¹Ïe/y~Ñëy¯6ÖýûrIõНjdzrIÍ8p]¤ÁþÈW¶£¦“'Œä‡ÊmäŠÝäìQ°JqöwëÜFcÛ~¢Å¬XNŠì’ÜÈãÜ2¹!=OnÈ0Q1Ô‡NnЮnÜ P%%r(À„Åm9{ AîCQøNÛÖ}ÂÓŒ~k¹Ëĉ½’·Žã”Óô;ÆŒ¹K%½‚;œñÐr-Ï1ús{3T0¢¸S¥„52dL;5fœgèÇŒ£‹9aç¬ÖÍȉú 1c&úà‘…µøó4l-ùrѺ ÕzS Õß–ž¸¶ïËowÓW$²/`q,E7p-ÍÜŸN"ä7Q±«¹ ÑIÝQ"ÚÐ÷è ¨g1×­1O—ãfÖ`}*ŒhçþGì»VùŒ8û™Ti£­[ >2ÖcÖ D-OÊoâ°f¥è,…VÉ£YÉÉ4ðàæßr^7£—ºüi€;U¢~n<óÍò („Cgb´5f<« CºvÅÚ~¡.ø¼‰(ŠÐÚVá·9s°ò‰’ãa³YÍXZy‹ß]9ÕôH,VüTYNU´—»#£ºí©"lÁ ’BÏtˆÝz?ªÖ~ô”‹•e÷ëx¶ÝæzÙ,,¿1^‘>Ž™“óž]E›\ȉÇpûŸP=Ì~cäÆ8"—ñw.%î~ë¥>XÍSJƒåš'Pšš‹Õ­Ýü &*0Û_ò„“«5®R 4ö×<á8fLJ#Ö> stream xœí\Y·~_øGì[fm«y“ `;Ž¥X–yˆdµ« :v­Ã–üëSU¼ŠÝäÌHZ9y0I3l6b_œŸŽçIÏø'ýþüèæ=wüèÕÑ|ü5ü}tôÓ‘ Çé¿óçÇ_œB'% e sǧâÛâØÉcëõ$äñéó£mÌÖl¦­œœsj#éˉóa’³ßüu« Ý³¹½=“÷!˜Íü‚×aóÕöD)1ix‡›0ÈwðDëIJµ¹·Ur³ÔÔMÒÚÍ?·rsŠ_³âoß…'_áW­“›ï·'>ê`þ}ú7Ø,›í ºL³‡m^ÀVL,¶ÔñDË0y}|¢æÉ‰b‡3èð W&'£õ檌MO^nOô¤”õæ5nÌüæž<ÄwÔ¤„' j¥Ø<®o?ÀîÆ4›Ïjë³LÕ[ MBÊÍ‹øÔΖf|¾=‘“µÎêÔG*½¹“ý`ØçEð§/Jlî×Ö·q±s›'yÊÕŠRÝëtÈκ| Þ«|6Rh<š†êo®Œt^öpI —šátë pCelgx(FMÆ"]`åv Þ²Þt&~á¹–äË-¿š€:óEœ1Í ÎN\Z¿y‡Û˜a4þÀÁجÏÙÈ‚ÔÛHbï7´;36ÏT>Åsk¶0•ŠÌþ9üýγÙã«Bx+6*’C̶w"d³Œ»œ·Ä ™=AŒµö°¡Fxæ2 lÙ>'—ÃÁYŒñéX‘}“ühvV2¾Æ- Kô(#  Íšdè—*éOêñ±sœ £6]Â*ý4 ­ˆ“žbO'ý(Г—øDLÀc6Ÿ‘H`¦#ÕAæÝop½Òƒ¦Y™1»Í·0¬µÆ98'8Œy†Óø%FíIÊ$rsk›•â_€*°@ÉÁìöa0'[±ša_FGäq"_äoL6¿,.Âdfñ?G9gˆndššB&!'Ð{iRäÖD&'<’IЉ®ˆ8¶2Îd²^C2dÒl,dŒûõÍgŒýËtgÆ˃ÈÛq_ÄÛp.q{õðoÌÎ2þËÜj}yIƒ'.Œ{êÉ&ÑçêI E‡2TúsÔYL&ê¡2.[ª<Üù£-r“ðUÔÀzü'w¬,vZ9‡±åò»¬€pÊú£¦‹Äg–Z×X£¸7ÓÈB$™m„­Ú-¶ßŸ·FO Ñ®±&K% Æ’+˾¿#Þ–©$2s±Í|XÑì@ 0¤'A©]ždafY%-SÏ/ Fâ™–!‘*dA³x·¨lœ?ª ¡Ø ÄÍy'­ª~Šö+ ƒI™IŃªùe+˜"½™°p€Ð™x2ÑXú–Æo8ƒæ±ÁXë‘Z Ò1øÅ>2Œö÷º÷»Ð40ÑÂBG†Ÿñ›Ö:ÿ¬Ý¨+--ßÊNo#=” –‹úœÙü×HXð·> ÛÔÖÓ½ÜúhÐ(HlÅ—dé½AV®G‹ÔL•!û_âë‚ÐÊÈé9kÖ¨¶=C&C«@£Îb­•}UX(`˜ò>ϸã¬èº(¸D*!ÃÚ;¯þ09·l2)k_€HQÖI!Ù²|bŒ§Œ¿Ë1\U<|Õ!L—?B-&ˆáp’>û¹#G/Ñ>Í øÖQÍ¿ÃìÄ!Ê"]™)ì›ôÜÆ¶†zl¢tÍÚ¥ŸQ~†œBñÀêü˜ƒzé·³8zŠ/h¤)=”*zîsVŸ—FÖ³Žö²6þRŸoQŒpį±í¢v|°%fŸiUl0x ‚8MJ•ƒ|f ¼¯ìä] ª iÔ¢˜´Éa3O‰áoÒçøN ûÜsxû‹k|þÚ «‘¸§U´ÁÌ&¾n4’œŒŽ‚Í•óg¨ç2‘ÚëYÅ)ìõ$¢hãJ\ÖS¾è¼óYU/Ö#¼’²ã1#06P”bÁ®, ÿ†#Þ̵ç›îÁ—šÊY‹râ÷.gÄáÊàG? ¤Oþ% é¬Â­Ñ N3ùþó ù+éL` ð%nô:ÿ“¾èPÆ@0`B (³èÑbÿ¸˜4²®²!vÿ¦ê*&­wY°3ñ¦pã@ÖNˆâXt7ó¦2UeÄ&ØÃ;´BÙw¬“è)° W=L–ÃþÊV!a‹yÀ}䔷 ¯âN\âî[1Øåë!GWÞîùzµË$X‘<ÙuLVÜþ;;‰“‰4±é†DßõPùv/"-Ù‹aý×)¦n@òj%ßõ¼¢˜ÄÕŠ0v‘R’k·õØå$Gš¶1º^ä¬ ÓK3Û)2 Þ¯³Y&ú+ìÇÐ:üÈbH=e]˜ÄsýßñPØ8MãªlctâÙ‹PDÛˆ.ŽÁW¾ÇëE(ìÐí¹gÄb·Ëƒß‡Þ¯ÏJãeÁ¡ç¥íiíøªàÐ'åñ¯¦æF„©F§ TU%6ô©>ù“ß´„½[(>$q™8Ò¹xM™¦v&,'véx^û´·sNmÊ£h± ¶5…Ø¿­_ g™Üä|Yø3’æñ®J)VR»ÝÂÚ*5jŸýXkÞˆ¬²%ú¹^ئ$Ë9_/#6»Ú."ˆ e\™éÛŸ”MYÖ™¤2­še;mÖ›9Í¥4:ûãàsA·žîÃÜP÷áÑc>,ñzˆtr»uŸý?™9ÐëµqwÌ»¡ƒŽÁ¹÷ˆ„žÕŸT± ð1^F±»,à^ö®‡hr©¢ªQÁ¬£õM[[ZÕ¾èï5T¥‘˜øšÍÊúÈ2R—2pjÑ÷õ|:5(OTÌ@~@eÂe¼?ØUØô÷Æ ?ËÏZD$¬ßZET@Nr´RD'¶ë&E„de!éßâ?ŸÙ»U ô!(‡ ¶#ÆÎÌšjg¡WÈvîqyë¢'ôL¼+W¼²V¯{v¾6¾á¸(7~étïk:ÓùÍCuó¬…Ù´&å‚ éÙ ìß(ÝÑ:HTô$WOØ8‰—€•³=l Bšz@……Mlb‘·y—âÒöØÜUa&Å™õÕ(‡ÏëÖÅ2m65·²„N–|©XJpUD¸…0DF‚žƒË0çEò©Ji¬‘1¹« ÔA,º1`1s9¬a>Öá.X7"‘ƒ5 Ot•‹Z,³—¨Ãê;ƒ°DßHŽY,^ÙwËR¬¤up´8–Ì+àMõ󙬸³ùn†Ñ¤Ž1c&€«údiãK²Ù8² ÈRƒ#9R=šò|Ã0ž4—•s¹J{>ÖaÂ-u¬ý¼Øñµˆãdz’tÄ—L´Žg)ãmg,¦ÖèN\¥×qÚZ·p“-²°‚£‹`ž¡r92* ¶Ë ÓRv°fUÄb-,ªªe+lë‰ÿ¼’Œÿp”gLh*¢m_-ÅíQ*O›nãlUÇ¿eþ ×õ‹Šî´[[Y¬E Û4Ä?Ú å!jå0D]© q_¡S.Ñm“ô¶“\DzÁ]ߥu«Ò.šbÍœÀ`kË…•ÚnÚð^2™ ±‰År^18ç¹€4¥Ž}R`Ò­3=àˆæCƒ|QÐW )hc¸!p7×­çóT( “PMA8q‰ Ç å,rŠÏš¹ÿV)TŒúÌZ­ßJ›Eî×W6%~J»Y3ùùMÚ«1ñ±`εªp +D_EúV ÔžìJÚÜçcp¸Ü=GNU;b½i¤a'!ƒ}U+d[)ê[¬Uê&Ñi¯¼§âš~yf¾'¡]q†IDvÀ6 ÅÇa£«ÃÞì¥k³ºª&Ò9°M%Ö @‡ÓÓ힣\—À]¶:>§ôwŽ;LçgbðÝ{09fÁo–ˆgˆ‡%ÇÚû9§ÍZ1Ç `ãŠlô2ü%v?*ȆÑ0ä‹÷ ²E§6R©µûÊo±[«ÁÀ…](ôöbÑ <=sHÏÈ7tšKG—ñÒ^ð6[Œ\Yþ>Õ0uŒáÍëF#¹KÁ¬v\)æ‡6K:Çpý€)^öa±Ë‚õ«ÃËêÕ?Ž;­þÐp¹Z×õ^¹¯›XRw-V)N¹ì]2.&zíøQ`ëÝ™i[êÔY®ðq ‚R¢qT1¯ÈEáiÇÈØÊðëmtÉëNôNB EÞSïÆ™Ð:=é‚xi»èñkt×›cigÒß%(ÚW–ŸÊÞ»åTKb-´À×[JÉ^½TÌšØIÞ? p*Õqt Aa¸òôŠeÁB=¸€¡oe2ZKw؇–(CoûNAª¤]µ@h|Ï¿{ ¿…<íÍ"˜~fù½a 3‡ñ¯Dl±ˆúDÍnKXÍF碌Ÿ£þÐè{=®¶`Y6Ó ¸“ŠqóçéE½œÍ‹ eÈ¿t¦$âÙš-|Åê8î>‡,%ÃM×®›_/è×uEŒƒ :smô³;õ^lKÍ¢;œÓ8¢ùÒ‘\”æôQv¹v)ü%¹èJ—§_¯…\XtÌî…T©loK'z´J|HÇ–Ÿ+õÀ„2s1h/) NÇžº«Û%KG JTIe$ï·X±Öå¼íý¼è•'¼í½þª” ÞÎåAoËcVfTÓ¿yÝÕ°wÊ?‡Ô]e¯³¬MíLØ'½­Ý(„íuqj纫JÌg½:±Å ü.iøƒ2ÊÉRÏ5¶ˆ¾WSŠÕuJ µùu”N âF­©J3(ì¾<‹7È ˜ÂtŸ^ËÁ}zÄDZ]?47¡y/’Úýuœ=‰Ív Mµ±ÚZ®½ùË6´º h·¸ò8ùà|éšP.¸åË:d…Î)OÐôG©uæ+ݼ¾Ä†Þ>$sQ,Súi˜Æ.ƒN{Åí¡K¼Ö|¤ß½ÎXáðËŒ†S®v†Nd¬Öw¹/·å ö®ŒÝ&תuQ–+ÄÖúNÆŠ<Òæ"Çÿ…G]þÈó3O#0¤à›=W8XÊWßÝ Q±KñÍõïx^§›à{æ‰ þ:*g’çNšáS¦’ÓOf \6.U;ï~˜J “™QÕØÄ—“¾ûD–boÒKÇ4Ìžß$Y¥º\½Ÿ=ûeª}_Ã]éâøú×RIQГK®¡>È墖_/«}úÁMVq•ø¢£6õwë öÚ‘0n¯µì(ÌÁ“"ð,DǃJ–!!^¡<•¼vAÉYµ½?­@‘™u­–þæ_´[\lI)£að&]ækì~[³‹wá²õ¯“vµŽi܈ã$ÅólÍ¡é)3K!â œ¥›tM@Ù˜~’bLšÝàëÝ1Jjè§ š±Á£ò˜Zˆ‹ ”2x:¦%Ý2®ÙµJ7†q_ýþü휚dendstream endobj 203 0 obj 4720 endobj 207 0 obj <> stream xœÝ\Ys·Î3Ë?bß<“âŽp¦RqUäC–íø™J¥l?Ð$u”H.%Š:òëÓ³1ì.Ié%vi¹;Àh Ï¯{æÕŠ |Åðÿð÷äâàÁ“qõìú€­Á¿g¯¸ë° N.V pe˜ØÄWGOüÝ|5Š•±j€Æ£‹ƒß:ÙëNôú£ïàÉéB°A)¸éè:~Ù¯å0ŽÓÄ»o{>L“US÷^t?÷kýô(º£ÜçkU*Û=«†í4Ì5ÀuÁí D÷°Wƒ”ÂX7̯ýZà #·Ýc¼×ÂÒÍ*aLcÂÕIJÞýا¹F3ƹp0ƒNš[Ñ}ÓsŽ]p|©Vp…7À0ƒÒÜ ÅÀÝOØ.„€©þÕ‹1-x˜ÅÝ4›ŸL–.Fî·±Üø5Ÿ`ÜÕ¶`äÓäwóu¿FâÕ$º ìÊÁ0Ó½é%Ðn`î° Pv—¾UMº;ƒõL|аÈ3Ø>¥8lä{$W>ŽÝIºšÛ¯òýoð~ èÉ=ÏíÇ}îSï+°lК#ßеâ}À2°AÇÍä7B”—Z²>"ĪàÎãIãén!H¸Õb¦ìjOh]+§·½V`‰…c«<âMa £ÓNA™)4³0ƒŸƒŸ`W„Ô™ø¦f<XÎFêHüš‡'~ÁOH`{Þ安ÏóèfÜ”Çå†dŽÝ”‡‘u 6¦!O¼j眪ö¼OtP{yپɌv…º}"…¯æùûq"mëÿ¸ÃY‘9.zp3¤°NuãlZ˜,{È@B R‰x>¬^“âJM^x*‘K‚xp˜¬Êâví]+\àéܼFŽ>Æ>F2yã0ÀÐdp"3DÇqj2réÇF§Gì'œšvÚ›¼ÔdV$(kã!\ò^Ÿ²…»m>ŒeÜïä70‹ãlddÿ •3÷~>ÄpSÖî<Ó‡ì·væG¢® ½_ãO¤Èm²¸@ëa½)÷}.óÅÃÚÅ×éâ&_|—.^÷ý_>’»ßäŽO{Ç̯Ï7ŸåæótñÔ3*§õõÃÜñ böN*}ß”tØ4µSvqh‚0î+X_áÝëb¯ÖÕÀy†c*O¡åm,ôRy‘æBˆUnmä̪,³ÁÁñØNSó5e£eÚë¾'Ì$–É®-À»qpœð=YÏ‚1o—ðÚŸ‡CBîtÁ‹”…}ê쓱ðƒ' hÁ*(#\M‚3jµÖˆÁEÏHcZ ºÅÅNþþŽسï¡Y3ív𠨵s©\ XI=t1Ý0ÊmCËjp¤…q F-¸U݃Ô“ÑW>éÑ­à‹ÍŽJ©¸Á #/¡0ÈÀe¢­½ÌÍiq×0 ‚yJ׉ge~88úëoß+‹¯¹‰„w@|D/Rák4…WU§¦ ’f_ÔÅœ03™ÂXdçná'+b®t=`z´ÍÂÀ“@€( NœÜ×ÂØfÅÎuÛû[ÔU±8Àµ]8N;N£÷ðËLIÿŒO’øcIº›h/ï᤹jçBœŠ@×2ðÝP|#º”ÜåÅ›šºugï®V³ßJåµt’Ä=™—)G}<æÅ¹rdsŸ–k&ÌžiÌÓe ›?àí]‹°h…(ýsá‹ ›|Æs¨[ÒX—5 WIKb÷e`Â}𱼄_XV˜H¦K»„?û×v·d ¢ ˆï™ïH7y2ãÛôäE@¸%7.B'@ìsšÁ$5VÌ:´¢œ*«#IþÊ“z¶ÂöýsØX‰1ÏoÄ2KcÌâZQ{àÅò{ ˜i' pƒûyº­ÕB"ZF’§>+ÂíÌ"7UÖNKÒuQ ˆ¯0`â9QïO]zbðnÈö´ÊçFYQÕfÂ99«È Ÿ{ÏmDêIfï6p8£0åG‡„ªÒÓ%EŠ… ³eŸoõ‡o –p J­é¨eÆÑÑÖÉP3yRl1Î÷A!®áöt-T{¸­*Q°Óº@Ä<ÙÐó¬çàı‘"5u8ÕŽ¦Èxp5?™ÝØ4ø8›^pÉD+ÐTû.JS+û(©ÊpW jwª[ ZÏ’ÕÁLé$l^ȺS¨r¢mßQxl>Ô™EBÊ”™Õˆj¾Éêÿd)<‹" äÎgÑ"5Ò0ÁÍM>ã…) ,¸ WtÜaðUkè*.æ¦"S‡³ì8nG™8)a¬—ÄûhT9´óµfjŽŠ9+ŠÞ@«Géü0ºNíKÆÚ7òx›£S}*MìÕ™P©s•=Mêðên×Ö¥…%€…-ê BÚ†0âªÖ$‚ãÞj€÷¨p ìèìô.©ŽR€G„…8WùjQ@U<¢eÂPÂÌ“”äžã”u-k£¶•’g—Ž×¦/4†< ñx^ñê¸Á¦¸,mÊÎ ÂPñ³Tx¾öÖ—¹8¸ÜÈ`þä³Ü—æáËÒA,¦íxƒ„g²©ñ¸cÓÌ`oÎ\o»L—aA)vw%_´`å}Ý៕•Q­¾¨ë*‚¸µ¬Z´Ø²^q¨Ã($uÕpâŠTJÒ¨hŠ\×´–¹¼Æ¦Ø”]O³U?Ë[TΕǹ©®*©³bÈ£XlHl¯ÌØïá¼{g<fñ}B þƒ?ÃïbƒG—Å?˜Ajé Dc‰è¾¬¡üÒÍÏ„”Ï%,2!#욟2z[ÃDÎ+xqñ@“ôŸG÷8;‡»£Ìüíû>Œ_›¡‹g6U ˜”ö)«IezûU{–‰Á'rŒFæbº«Œ?mŠHrÇÐ^)9 ¿|I|¢8ó¨én³vþêŽEÝU|YMí´Èc”­‡]¨1{ÃØi«ìl³LÒNƒÔÅ;V6^¿NvK€^ø„Å;Yº ¾òú#û,"Ž0¢iƹ,w å\Ó`dž„šR“aËG0šQ4Ág<iZ ¤3 u™=áUT‘J|Á£uq³ŠnRO_®%éÎs¶ÛúQþvD{—Lµã ·€4š€4fC·‹Õ–/Y »‹å ÒÆ$åc·ÔÅä»J/ªtÙHæ‹ôœ”`¥‰)ýZÉ߬ÂùeH5« år]¡ß³n6T P=+%vš÷Þ5_MUàhï¬ñ/ÿ#óuendstream endobj 208 0 obj 4716 endobj 212 0 obj <> stream xœí\[sÅ~Wøzc7åú~I© „$ÄIQ@%¶dÉ.¤•Á–Áÿ>çôõtOÏj-/© .Ö»===ݧÏå;_ŸñÏÇlâÇ ÿ¤¿O¯Ž>zd/^±ã‡ðÿÅÑÏG‚;ÿ­ z¹z´–bâL¨ÐM˜շkcÀOë8“ôî¿Á•Ïð§RR¹ÕãõFÃWËÝ'_ÁB`®d!JÛ‰9XËÉÌ_ƒáÿØQ9Úq£8Ÿ„:ÞH6Yî}¼ás˜A˜Æê!~< 1Æ9N@®îãÇ+ü¼Á-~¼À×øq¯ôþ >÷øñïõFLÞ;gÂ-±Ïum„•ÑÐìW†ÕÁŒ¼—«ÓÒõIíúKiIºII–7@H÷v€³8жŽ{7DIŠ˜û㔯P]Œ±FÁWÜxÉìäË>×Á·kaa²Ò†}VžÂWçx·RNм`a\~ÀÈ.­Gƒ9<¯ò!â½·IpµúD؆½2´saÝÄTÐY«AyGvþ—b ßáÏïñ#Xüüø*wY}Kççþ [Ò‹‘Í5"7>+okã¯ÄM8\ ·‹¦¯´¢nã§ÒíYíö¶4¾©Õ/\Žæxº¸ª«Òx5ZÂvänwOóÆ›ÚØù§ôý”ÞËA=Å#ªn§xŽªÕ¯‹³ÀU+\H²h0Ž ðñ[Ū_a0Óü­\M6h˜Y]D‡ãaåpФ±.§µíö¾ì 2™ ÚzÛI¼š×ƒÖ¼‚Q}wÇ0úkU„ëÒç—ÚxF5N‚³Ô2^lòîÁäÂRF´ª'=ÁÝ“ULá^Î…‡x¹¿Áé*‚­=ÎCN°ÎCLZ ¥ÃܨŠÓ€‡ '¸9§M…1aG>ê2^RA×É,†•|9ØTÜ(2æ‹0tÛzù6ƒ¶Æ&%ÀôÈb@Ž<,í룓?~OáZÑ,`´äì•·A»Š5•/×k°–QÐíŒÀ¸°]𼩖í(N)› ª€–!ˆÌ̯£!ŸÅ¢“MHm&©ÓD­÷|¬Û@­<ÅïŠÔ¡$½ZÉVŠ ÍÖÚ5+•{wáœÑÄÚo†$}µ}:j€ð|²‚gCº%¤3ï s´å³ 5‚ñFZ-Ê𧀶˱=MñsĉÖ›R/œÔ€ÿ8-`Åu€(4¯³ó¤©Š ŒO ƒH Ý&SèðLÝ!¼ø¢ŒyšÆD‰l²H6ôãGLÚç þ’>‚c¦ˆ¬ñØñ¨/ F³2= Uñ:Ä”·Ëx3ðÿdãRHqVUµ¸NAI¨€âFfF,օ²«§q^Z„¸.<:Õ)/Uõ¬QDŽïŽz¢ð”ôÙC˜´hkœ’ +'šJQG#:[ÖUõæ.ÛÕ% µ?|&à0Í0„Ñh”‚µF‰+óUbÑ*ƒl­ x ¯¤©Šœµ(äÔtÒU”*ajž×‡—[•Þ3=HÚ¨È1z°P«éèõú pü1^Ö5Þ$µÕ}-³ŠV¥¼‰z‘P:‰i,ÃÔ8Y@‹åbÑ¥Ÿ’”3Š›V .Ñ¡ù`CõÀ[ˆøÀí0fŒJ×'q[ü²wƤº÷®þ“½ëCcÖq#ç~¿>AZB”˜IqXQ1- „ëôýi »q  œ-@'b•Û%ÐØâô‚#Žà{áó­}Qì¾–Ò¸ßylš9lLêiÉx2XA#n«ÅØïº2µq´ÑK|@=Í @'q_Ępc9¨*ßI„d\ï­+€îPû³² •OuqòbÝènu†¿¯2òþDGˆã#Q+âU1Ç^‰ÈF˜À[.%"ßäˆë•<ÿSüø²ÍóKîÿ¾yþň¹»%/Kž_ï>¯_®a§À[JòÄßFøeÇ*švoww¬mMNŸ¸-±æR÷Ê8oF)ý%Iéç|Õ­a2ðb¤—äd²2´‰~Å|»ÍÜvðÐyÈ çW‰#*Nìå–¡º;Ï,ËQ²¸’G !îú`Ž¡¿ÑûFÿ?ê…Úˆµ§J±ê€N¡sÔ>NÈÍ u4‚„oKÖ³­™ÅÙ—¬Fz6°- tAE„&üh+"-Â1JbüÌtªB// ,Á-g·hTXw9ÿ–’ 6•’ Âª¶©CäªÅ8Ñžá0ÌâIÏaöž-J™L}RøDz=©Ú~‡)ž}¼ŽÇUÌS‘9—‘†/p25£61²’Û·CÐEò Ä´`0zu×yDXË]«RiX”YIÑA\É®$&à ql´ Êm¤¤+øø¸ƒÏ$vº­&‘Q“SiXþóÅ«Â"Zm;ûD¥éÉõ•ëè,p‡­âåíàòY¹Œ ­»%^FYàA(ÈF+¿-I—`_(ÌÎÒBªãs[,Á<ÛΡc˜Y7pr|™‹é•#Ï"QUWi’™i 8U2šp°èüxÙå–^—*²Ä·Óqâi”°dÈëjµ‘Ìjà%¬ÌG‡Ø÷ãV8 gB‡KüûÍ LÅß"dQÆO¼ðØŠT"k=sŽ 9ëLý ·äéFYz½‡L’t\dä\~“$шC'dñÔ‹†úNÀÎÜ÷bÀ9E™†]Ìb9!á`ëR6ò°ÍFþùÿläàÙHíx3ÊF.oK[òcqä%Ù¾U!ß̲‘ôŒœ˜Ü4K$&÷j_2‘9>ÞÖ©¦3OŽºÛn;TEü E—Ƀs6ž”³QÌíÇÙøx8˜pá'Êç“ïWs¿_Cš(vDc5ñkÆÎžíé lãzp§!Ÿ²«ýº °þ÷]º†!Ä®ˆîXxÄ(©Dõ‡—É2 €ÎË@ÈÓ?ÄY‡‚/ZøBäsAüobRC030©¸Á1_ÖUS˜ó< ‡3!ÿ¹®õ/í‰RÞA S®cU€Ó…¹Ña͈‚nÛ£Ÿé¬éؘ"´j–‹vh!ƵYnŸuéÀ=u‘žƒ ò²ÅœÕD NÃykÒvÑÞÖÕ$´GH˜¬h¹¬4©~N°÷>À™ëEx`û:q” Yß û‹§«þ‘b¥ì4tô ±A<ótç¡&´*.T=™ð#¡÷KÜûºÀéS¯CS©ÉÞFT*· Æú L¨Rå)×!7e`‡¹sÆŒÁ‡›p2<œD¯LÖXïl14%@C$vÚŠBÄóH) òÌi.ÜWö„Uw"1„dä´.–óî­!L ÝXs/CÎ"èŠIe+ô\ci¼—kDÃn•ª‰Eñ\aC£ÕÌà‘JšE4Ï‹ø£‚ÙâbH•1 äíÈ$Ž’¢ó6?ǸáñEÕŸÌ¥BÊ&‚ê—Õ-&‰´‘ޏëë"íÑÈBµp"š†…!QâÛ`;kã³/q$B§zBˆ¼o-oÅFÉ ¡ØˆŽVMLzê9‚^è¶ 7WÔ #}Iøaø"JÐ"ËN@)3K’”ÓÇ·±Œì èÄ3ï=«”¿Ýùf?•΢½-ÊŽôT2˜ê =€¶KŸ©{í’'qUƒR¹¯l ÷®y]XSé“b"ÅÒ¹ù›„r¤iWqNˆ}9ˆ´¶7®ŸÚurŽÇP:3¨„uQ÷E]JÛ³xBs‡åW<Æ~8ˆAò»‡—%–v“ÜzõùkT$mT4 ªXý;„øÂÇË4y‚/V½Å!bîÞÄš'h$)(Ž…´.Ã%¢,)j˜¥YàéëMóŽÚí9 T-xWÿœO4ò1 n¨ÿa^˜¬>- K³bÌd-ä3\±|r¨'ùý*CJ§ÈŸÒì#ïâ’ä- ï ÔW±À!§ß„PA³PŒªùì%SÆ0˜Þ1µá.’€p/!+f»Ì*Zf¢®L©›*>Ÿ cØ4þQ€»¼GK ã^ÞVK@׬¶«A°?Jâ›\4º]P«f›¤DÒ¢GO~ê}ax|¸ª…>>h첦ñ<¯ñÅ©å“â”´]uIß!¨Ïÿ<ù\S|Ãzì/ &Q0ÁqN½GN‘18ì†R«ÝÞ +oC@—4pÈÖaJM‹&ªK¶p÷›°9ÁÚ§”6Ÿî((çñ…Ô=N²$|¬€Ç9KÝ&I±Ú×—Wƒã–„ÎíÐQÃiG¢í|+¹ ƒÓ`®é£×Õ Ôäu1—$Ç?ßÔÆfKê9 m¤×Ìt¯ΓÏëó > stream xœåXYoE~_ñ#öäôÝ=BBÊa;,òï©ê³ÚÛë ±2öt×}t}Óï§làS†?ñ÷b=yðÂNϯ'lz ÿÏ'ï'ÜLã¯ÅzúhD\ÀÊ0²‘Oçg“ÀͧVLSlÎדWìu§zýfþ 8$§B°A)`šŸáã~&kÇ‘wO{>Œ£Sc÷°Ý/ýŒ¶¢›šÃ°*•ë^Àª±]¬ î!ºG½¤Æy1/û™Ë]÷=ò:ø'½V 2‰«£”¼{Þg]ÖØ¤ -] ˆ4w¢;ê9G”/utÀ ®Ä JÀ ÅÀÝϸ/„U¿õb`L µx¦;ú‰Òhº°<„Q9Æ·ln:ƒX>Ž!œ Mvñ1àc Ò´Ñãagƒ|,ÑÆ8ïÎÓkwTîià “?Næß¼ò´eúE–y’e®Àt>£3ÝEÔ+0·ð~“‰–eñ¼µx•Ñ&4但<Í>üUrš7¼™yc]ôTf«Ñ@E(ÿÛjÛO‹íGɰ`û’Úž‚x†;«"~›‰NZÖ]”Šͳw޹î2/n åý'?÷úq˜]@ñÄÄMÎA.¿3›98£‹_èºfã—¸ýäÿéöñ^·kïJÕ^¥Dëe÷m°á6ï_uKºTÞû£¼ø±PUSÀaÌÎâ"°_·BrÞr¶bß]\´¾¡ÛÄ 5ZxQd[EÕ÷ñB²³_L¾)‹/‚+«Š ÿTÒ!AŠÉa!¨Ã—hOój*õ4Ÿ ØLâT åc˜TœÉî]˜G†¡Ë þâ0m!Ý8nU´SƒVÚë¶ù ¢ç©ôCíhíÀO ƒØÀ Œ2Õ¨=;Œ4 Ó“(Íì§E{Å.Ì8(Iôl☱襅q ³œè9¸@¬Æ×…wGHE[)£‹¸FˆÑg½[àñ­"Œ-—\2WiD8lZ#°GLYùíQ+0MbY9Û}B8<œ˜…™tÌûù¡× ÀŒpÞ›U’K-IlD)Ô˜Õ d‡Æ PÓE•!F@ºm I]ÃOÌ<ìû¹jŒ5*ú‰Žl2’!‹ë  0‘ìDç“Ú“€H+&ë}dÎuo¡F$W¤jdþìÜBuNS2WŠ(œ÷š¼Ïð°*!ÂHÌB(f€Š@‰¹'Ϊ”NÜÎÙ€lºDb Yˆ Å‚˜ÉMÙA #€CŽþO ëÒUº¥`÷6—”A¥vãŠû1®JîÆ5¶€äbJ¤ÀBÞ<Ðm¢ÄÕJR0×£ eqœÁÃq_iI§§}X©z²~|AÇp¦ïZù9ѧ­NYÄF€4©²bRç¥ç°Œà¬U R( EùïJ Z®@-Ò–fð¶°õ«Rª¹°‹ø”|1’ÒM‘ÕÒ;N“RÔ…z[* í¹k~ü«ùÍ!ì8HÓ±~ÀÇa&~’x»Ÿðñ¦Œ®×]&ºmÍዾ†ÊbãÛÁ¯æ–Lan{È3DʧvWNeW^ŽUœ`22k¬H„è¾¼_aqq™å¬ÈZ&\7 3×Yá @¨q1¸Tâ·,¬¨æ$æC_wIA¸2 )ºï*°1Ì@1ú“&¨ ê>´pÖª•ô .î†û¤•ÕO-wÐtÓtCË£Á󺧀ùÁ ¡ê/th[u‹îe vq8ñƒ;fàšš×Cª4$À¥ÝÀ…Ý{À+ Ç Ud[ûmc!1ÌImL„>¨a»:Ä“ÎY_“€¦p8üÛ)¢´Þ˜n^° iB˜7RÁÙ®U<]… ì(È)Ƥ9€‰@iß…~. ø™h Œ† è/VCE£Œ Nô¤Ç˜Øv8êµà)íÄ §TöÂÝ6åP°YR[M Э¬" Y*ÂX3b«áþe·‘â{ZBÅCS›J – &N\,Oà‘®Ø ~˜Ï ¬e?bÃTüSäÏÕ †ñ.¸I7ie¼£=¨B‡&Ø Lµ&ó%A }|³•jªP»„Öâ‰7œ%¬krsïý!íQ¸$kËe%³,ÔÿNîPz3áͯ„¯Q2@c÷}Oùâží±” þÝã„ÏC)²CN†w §¤ð§°Î"‰æ¶”dÁ,«h!sçÓ6H¾,È—†ÔrC"AêýÜäÓgx†˜yÚ V!´ê“"D«n’f’¶úƒ·U쥤‡¸ÛÂnÜ ÿ ¸=ÇWÿðØËO¾pÉs‘î±È]äëžëx´{­±l¡š=­n2p+€\ß^fXSXšwdË¢h„'Z°Ï©ßTxgWÿ’º´{;T@⪂oÖ A5@I`+´œdj`¹åj¬Ò¸%B°BÐØá|ò+üü š|]endstream endobj 218 0 obj 1886 endobj 222 0 obj <> stream xœí[Is\·¾3úsÓL"¾`_rHUb+¶â”œX““ìEZ”Ê\´Ëò¯Owck¼Á›¡$Vª\%«, 1@£Ñýõ ðåJLr%ðOþ÷ôòèÏ?øÕùë#±úþ??zy$iÂ*ÿsz¹úû&…•“sÊ­¶OÒb¹òje½^m/¯¿Ú‹É:ãƒ[?Û«I)©õúd#¦è„qý"Fµ~³‘STÑÄõÏÓÖÊõ«Í±ön k‡”‚ö^¹Ÿ¶ÿL{›É/qok'£cXmÿu´ýããõß`½–1Èõìd‚”@ôÝÆÉII‰Û-Œ®®h‚pÖ­OamµV°?|¯1~’F­«Â©«Tœ¬ò‘˜ö!8Ÿéh5r TU0Ö¬ŸÂ°PÊY»ùn°…šLxÔ¸y›8wF®Ÿ´QNù¥(]Œy.MhüñdcQÓø#¨˜Ôð¨$°c`L*Eš¶nÒÚ¢ÌËÂöý¶üjô}aÁÚí¢°vãôضÏ8øÞOÖX§Ã$¤Ñ€ àr*ÑzÞhå8ú¤Ñ¨ãHÌEb‚¤k-õÔ™y‘—lภ䨤ħC©;ïYiSìû‰Ú8°ÉÈŒŽ«Öÿ€ïa @åòà? ŠF4¨¦`Àœ·g`ÅÚr6ó{ ¤5Øi༳c7FQ·ÆNÚtŒ*`àŸVļBÈ"/ØÀØŠNË”:w‚Íð¡ðDѯI ¸©ó°©j‹pü :ç)T^fF0«JxÀ×US_c'N‚%÷ =çq–ç±Ô0ýŠ5ÃÑû¢tx ãYÒ“6Š'Ïûjâižmãoh* ¤c¼õ渌·lbÆ&¼ M”qxÊíº¨²R®ÀÒŒ$gH=!—³±܉^D³± Í/†'mäß¡çTJûÈ™Ð2ßìÆœ_pc½vP7/´Š4»c…,+†IÃêSàuR«a|–I~Æ2"­bÏšŸ À›É+:ƒ Æ€¬RX A!ôˆ¶r¾A7O†L؆¸ÑŸW°m®Q°1ʸ~ŸbŠ’ÙFH2d"xP@ Q’þ €{0a-À°,H²Ù®I˜ÇZ:ðI}hà’Ý\Ó…pÃ/ÆzØ|M±”0äF%"E2ë¹NƒBø]7ˆëYœÉ~„e2èSÇZY²¶EO.XGfËpÚ…†™$°ø¢Ç5ÚIï%î–ŸO¢V‚D½6fx3¿s‰lCÖÔÒ± Z@šRíd1>.RÚI–¯ñ숈ÂáÇ>Ÿ­ªŒÌ®2j,d­U= ,ðN‹A,º4òfCy\Õud=Y`Ç„ßapÞS ƒ–@ݘ")KÔÀ-¢?ùDŒ× ð㬠u¦kõ<›úÀyq~䜠M:rÎ<c×›LxK1z¼¿íåb'#ü€û[ô<Ëv…Û˜Ûȹf <'“¥“ELÍÏv¹iàœÈ´—$SuU{‡QÌqþ¥®Æº‹ÌB²É7I!h™1>k˜Ï™4¥QŽ ±Áþ”Ç:Ô°—¥Úm.KÅ*©fŒ™Å™“fPèÒ1hK©ÈOÍŠ¸ÆµHúÀ²ÅU««ú58I?¾`Á¸`ÕÔ0>µ€ò©Žœj©Þx´¤€wÎK¢wMŸ¸x \NJ`%TÐÂ.ÜÎ3#Q¾gÊ(b3ènâã¸ZŠŽÅT†èü\s…ü”ÇK<ø…%óqÙëXÇÉ¥ýLÞ€F& -$æFx { P°€„"ÜÆ(̽U2˜äƒCÄ(;³¹Ï+­ ú)‰1@=#Tfb03$ˆ€ð̆0×9Â, XÈêIúÉÆE:“zaòƯ¿ÚÈIê`ÊNÂ`ô¡3Ä 6#¼4¶mO<JoÛÇ'íã«ÔÒ*xFŒÍ}ƒÖ(cóIñ|Œ¿z¶ÿ_ÊĤex3ClÅÒÌ=jy@ÊÑ#d¨`}‹ 'ìSòmãY+æ¬Cqômʯ9gÅïù Ï_™èZÎS)ƒË¥: ¢àÁ¢ç£âtCñM;m pÑ”—’n øÜ_e;":©‡µ[xàAÏúØy5؃¡Å^¬•8¶v*³QÆá¨vìdleØYÔnŸºVI_¤ÓÇ©æšÑµoÛö3'…ZÛd[ ˜õ×°pñõ;l úU пqOˆ"P§>Ä0,Á9wË¥0*Ž¢_×{HÜ Ô8צfŸ¯¥çQ·…I–Båö8¬0‹‰×©Ø-YU|VFQ†æÜr¬ÊÍ5&öò©¶ŽAUõÍ }u9W ªÃÂÜ;x*Yº ^AyÊç9ùS\"È¥| •dR†¨Œˆršõõ‚£²aß®}B°Zršú :–†»Žž²¦ý5=ä½"ÆZd -"4J¢ùžx¡ÞtD70󤄢û¸œ‹šó=„m0FåkÅT…âÆ™OJH#‡yhi+ò›§¢´_U‡²˜6ØœwO-Á7³ÞÃwœ7(î4hs @4- ˜e6¹²³\žÓÀ™xéz£{ß½W¼ÀyŠæô”À¢¾w*2“%ð)Ÿ|êÜ£ƒ22rW»çÚ³^ð¥*$7—ËQoz«Øiqt|å„1Ñ2v/‘WtÏ@õc¹'¸þÅÈOt-§êIGÙ÷šG föh]"RNØ'"¥Ö«V%YzÉ’ÛÔ1UFóŽi ¯t¯ÖúôM±µs+É}ñÀÊtûP=°rÞ×bí¦ÛðÀ¼dB×N“[b!c„ˆJ ÂùNr•è$Ñ1J¹¾?¢§\ÿ¸Æ¿ßâ_ØQÀWšŽHÐJ³ŸÖ/°WH†‚¦Rg'Í9iƒ—uÍlÔ^µÁ÷uðrƒ×VzŠîiì¬MüyCIWÒ­¿‚°” L¥Émr£pÚ©ƒ¯Ûàó:øÛ~žÙš7£#·Á·£5?nÊ(*®^™¤îPSÒ×ø×w•@ÕÙM¥ÙÈl¯©&¼2çª ž0ÑfÞkƒ¯êàûª¤¦âë6ñ¬*©£ꢊá÷¬2ìž*¡Tö}%pmý.ìêuüf6x3¼§˜1Þö‹ð ¯—؃/;(±y3þÒ“€þ¶ê¶šòÊ¥«ìÜ£PPbàÝÑ-vå‘ä »ò˜#3 ý”’àlU:ŸÙ•W/jk%Š·Ý•O…‰ÿè¶<ÞŸa+¹Üq›É¶,¾o7‘VÝ HòvV$EÌyóUI'M—ùÁJÐ*¿Ø-8a‡À--¶tpK|ºõ MÌaÌô‰uÁüe!dëjVð†Q‚î…f¨À—s2uîßã…F•œÛÈô^ê[ö m´Ÿù{³z¨\ø[‰rŇ€ÊÌKÛÏè«D|áÑïvæKÖOejý]¨M÷öwâøÌ H•»*íú¾#2ÇTõ§MíÂ( z¥MS²Õ¥èQìÝQ7ñ“zã™IFª¿Ãb¨~\g"o?ÕŸK°_ËÐÀæX_=8ú~ÏáÎ !¿{¨qÅr+'÷ªìZ÷@Ep rF;=K#ÝüÂ'ÍÝó8Ûuƒ{ˆ°e9‚Õzê~<¬-‘ëMÿ:5‘µ móÜË2Òà¨C¯*RSÔwWbù€=³y€©3ÿ°j©jÏcvVÛ²è´S3^N®5ã»·¦é½!ķо7Fï÷=Òˆw®wø½"gWYE¢äÁxû²‹T8ï½wÊ)Iž÷hnÐé”;4ºi3{ОŸíäìFÓ!¦õ>Bspñ‹Î|-1ì#²ã¶÷׿°è¹s½‹~cyÀ8?ïá9t´ùêDðKÛOnï<üRÜV] oTü@¿…ÕR|à—¢Ýó׫œÐ}%{“TžV襮!R!ƒÙw[`À¨ðÐrÆ•¯K12Éžoé—ŠðÔßà–ù Ý¡‹âþ—2rêv°F1:un‡wQ{ý¬6ÌCÚU(C_ý0¹{ƒUK_îÜ9an•¬µ¯é±ªÝ³ùeòÓý^T4•ŒÊòQö¦µoÕƒÜÅü½éða4Ë|Æ^•‰=…á?µÉoD*ýº{—( ZÄâ%&à P$CêvJÞp€,™£·/g M³Šá¤%j÷œãŠbÏïXP.h%\÷r~šèÌB]Á¬P«%*$%*qò®ýòO)X™¼.BI!ð—6»9gã{ˆÙ#îM˜˜¦ÔàQ~]pVI²%øi6àO×Ü“c»±øýýíÑàÏÿsgº[endstream endobj 223 0 obj 3679 endobj 227 0 obj <> stream xœÍ\I—Çöy¬ÑÇn?uQ¹g^üžY$cËhad,f3ƒ`ÀÒ¯wD®UYÝ=#,Ëz†¦*×ÈX¾X²Þ®ÆA¬Fü/ÿ}öæèÞwnõâÝѸúþÿâè푈 Vù¯³7«ûÇÐHHx2„1ˆÕñó£Ô[¬œ\Y¯xyüæèŸkµ1k»1ÿ:þ ôP‚õ°a=t:>‡†6[58‚Xÿy#†¼ë?mäú›ÍV Z'×Ç­Í£ôTi¿þžŠÃ:œi=À)à t/=Ü(7xìúï!à©7äí˜æÁllœñ!<ÕnB¯ãSLƒíçkÁö°–áåú ˜ ›x˜I™<—0tP º˜°~ºÙèë„_¿‘Ã8X÷ý”„¦0ž’@Ke×_cw)¥µ¤áq3/ÆË#kÊSH'Ò)ðsÛ ýôj«ÆÁ‰Òi\!Ülõ8ÂBÄúcšGŒ*>”²£^¿„u8çÔúýF Þ[hø 1öð ÂŒA­eûùÚ4`³½Ùlå`­³º¾É3>ÂÀN”^ÿ°Á‘6~}ž6¨ƒiKúýÆRB G:å‘täáåFºÁèWœ† yýÝ öê1íYç-îÚÛÈf|JÂtmÒú#e£Îò8a#KƒÁÀñp}Ý:uô‘À—‘O%PÖÙ§Wœ¾d¹ŒFNR%¢_·cLÓŒ‚rg}†lj4E¨ðu5˜$t`ÄŒñù¸ðaáK¹¥ÙÚ‘ _db€â¹åòˆbßfªDi0Á'âà¾Ø˜øwë?Gãi‘¼TFñ n~”° ªÊgŒÌ~ÙZ’)šVmÆ¡ô ç|Ùä4^-pùèáý²@@ -ÜL§DÞ̦yt0QRs-†˜‚i1‰T’!ña/´k#è·Ñ/ððU&>yDÔvðG“Þ¡@q ‘'¼ý:±tãEáÿrPLÒNÚ´ÒžiÌûîÉECÐc.&ñtE>J=ÊÖ…n ©¥¼®¬Ifl¼6‡66["";TmµG;slQ% È„á¡Ë½•QQ\µŒÊþ—[Ž!¿M@K{w%À,X¬rU‘Ï/`úÈ¥ÆFdˆ2 "_"G¦gÑ–¢5‚?oð”9XLiйTƒNA¯ÿ«“cl•ß.çÀ¡HçþÃG°Á5Ã]™¨%X)5ÑxÉ€ÿ) ¨ž¦éqû{á¡–É0xHѨtc´y]5û†9Ðø×v$dQOª×Eªãºû¾ 6ÜÄ ÑeF­Ð„¢Ö²¾¤R-j¸¦g2Qè”ëžM'D­:‡!¢‡šÎª‘ÛƒGÞÞ^Pýítóqy…e™ £#?ÛÔfj¢û'.(â7C»³_4-8;-Ø–èµæäü~Jö@Zçf’…Ã!êQ&Š÷óÃE,Á±,™qn…Û‘%°›Wl—=-•@ín)!"ÜñÃpk0é”ÿÁ‰aPbߺî䘞gØ0Â69) ÏÉÑÿ\@¹ƒ¢Q_Þ5áêÄ"(™Ð:Š!p º‰Úò©õ¡tƒZ¶ž‹‘LFçq}ѳ™Õ\æÖÏë ‘q7Ä ž4ö¦gOÛ8§íáëúðªþ:Û8x+œ^¿êYÇ—ø(ƒ¤?6ɲ«dH>©5®ã«£ã?PÊb,éòFÙ'•ä‹4æ¸DMh<ÛÝɽ®”¥Ô®]^UÊ6’˜CÉ^˜Óðhk ŽúµpåmsîyДwVyF{‚+š™Êá9iÐaMd†Ÿ°Ûe@b,‡lç-8)ÙŽhyÜ&Fpî«Vb‡ÚÄ1Ñr2‚‹[)G©ñx%]sOãõñÒkŠÖh·Šì£ÔhÇiŸ«Ø§f!ƒ\r´¤Ð¿ SÛšC.Ò?Ø =ô9É*] U£¿nÔí‘ôçºT²õy\.ž$G'Meò¦õªH¥5¼i¦¢že"P@@êEëTU÷@Öü ¹£ÙÇf9H2F3êNëXNE]á‹Æ4ŒÀ9[ªÒÍâ%WLÒlâa¥bŒû™‚. SޤC¶v6¬¿ÇÅ9„PCä8°ªÞ t È´$ÇÓ¶T’ë@%ŽƒFu®G€ü“È–D±G¸QD–%ÞÀs\þH"s8¤¥ž„Ýž \ú÷§bDö}òÀíŸÀ¡;ðVÞ©]ŒFv±LÌzR1A‘÷CC$Mþ®‹å±½Ó…ƒ ûÁàŸ·Ùá½½Á“âíÜ%xR$=Ȩ!gñRd2m“ÍiȽD¤Ç0ÑØÇ'rrOeŒ4.¡ï¸?'ûÎî$'È=ÚÒhÈÁÃÑïp©}ÊÝ´Ø&1„´?&ÎÇÁI1‡òfKGX”‡Ó0†*J'ªúšÉž°ÍÁ¡ïèãó]ˆ0C‘^±~h0f™  ˆã˜Bò±ä6^¶Ï½\ÌÏt\I6‡Th7,=—}äߎ’+X ùÉÚEý‰¸8WC¾<›ú·Hú:Ði;æÇ•aéâôÔ&\àtµCÙ–€Ù&Ã0yÍx6޾=z»[dc=,ݯ”°Àþ~¥Q ¬Çƒûî=þÛêý7ÏŽîýc%Žîýÿ¸ÿÍøëñÃÕïŽ=^}{ËÒŒ[pžT|pMu“£¼jô¸+—×*éWY?Î@ÖÿI@nÖ,ûk†EÉXF |ž³¡³¦Cý/F¼mÚ˜ Ù™Ð"Ú"…V“â”±6¢»Î^r¡×ŽÆç»ÆÀúabXgOTgõWÇ ]q³ _i‚V&‘ŠškfcLj a¿­Å¢Ä%¼ª´À‰Îð™6`ª.¸]Î"·´¨ OšÖ™±íEŠÁQÇ‹åæLr<ùh3§»ÉÞHÜ™ƒÖI¢õ²b.“ƒ¯°db;H¸:ç4Àâ]ÉС ×sxªú-ˆr\²9)6ðÕaá)\ÌæÌãS‡‡MZ'Žæ Éê\÷âUÏiDªXêÃ6æ­b6Ú£»"þgñ«£*ö ¨JcšÊý€˜²è0Ûåpõ©ïxX˜U‘jš¤RSŸ²5e“_TäÐ*æs®š`"µ-õø®âƒIˆeŠÎ%‹ù™ëÙêKºì€8$WiºTÉTp»Â¢©ÙY&@-0*P)D±Y‹n[6bSåcÛVÏ@]´–8Ó4»¡HœÎ »ŠP/£leÝʰ?ÌÌ®#Øï­‡…à·˜0õf“‹qÔò³»gÑAd“#8—5ï˜G´»ªU4px¼F¯<·GZÀá›~†®ÉšbŸµ\pÐÓÇŠ.Št1{˸º3}Þ²±s•P„j^yµPìó"‘ VxK|* -åzÙV˜$6ª‰5Æžr]Q £“ «GIt±²³‡6Ò^E¥¸fmF.r’z³dæIMN©•iá˜ìb¦íÆ8¡êàBÂÖ§3nåÀñ-QC7S&Ká–èµ ê]2¦{‰”žU 2½×ú™Aô)]Œ=,¨s’.T¬ÅŽÔ¨41spˆþÆ|"à°%žG곩炭Êv¾Ë1 „cuÐÑÅ2Þýh27FøÝ ?=«qöPAãå¦&LÏæÀõªNÃ+Ì* ›áêpfQö`N¥±ÀSÎïÏš*D»K°4þúª‚«ïñŸO÷ÃÒ_Ê™Á£r(çn› ëQ’’½v IsHt>±ø2F‰,Þ+Ihuì(ûzEV´¢ZºM&l_ü˜ð—†TØ‘#Å6)š$‹G'*ÞgèsXæ«ÇÝÀ Þ·Xð€s÷׿yîöC£JÛ💻mÉùÎ*|³ó’2KÖÔÊWx”cåü„ÿ%OkæNšÃðö}¡Ù…çw M¦Ô~¡É o/4ØÑ¨*4ÎÇ„Þ󄿤"W3îí·@ZT5 )W^ÁnS>ŠØB_Éêx–¢†©Ò_v¢UÎÄ£ð)Õ)“Ï·;æ)¯¾gÐÔi&ºŽ—M×"wvë†ñR-ÑÅp$øFÊ哼•c“˜–Ý""u¼¶$#‚f>I\ЈyÒ€‹ÍRLŽ;tU–ÐA"Ç,»ygÙZbó<ôpÓm\"‡JF-4r–X̾Ñ#NËòå÷``Dd ÃëÜÃ5KÒ$‘ôy³QX×£Uß‹+zG™…Ûjä¶]Ôšà_¿/ßr€gô$2$Síדݷƒ­j2›ª¤úUß/Âðºír¡'×]ßý²gTèŠ&8d[nÀÆSš›E°%ñ¸ZMuÀp9€fTP1VÞH2óˆÝÌÝ&2™‚U¶Ïà“Ü2c¡n’ë¬p4éhv-³ø3j{YmFͤ‘âJšÙ²§ù²Eñ3©$xÂOø¼™v%¹nn 7'JzÁ›Këv.kØ)Ëš÷Ý«ÇD> {X&*åf~¾òLÊ…ò~Æy%E-PLûçÞÚ¬:F‘ƒ \Pë èm!âÚ¥Í{-'^Z7û#Aѧ±˜~ycz-m¼‡‘úô1ÔI[tÃYËõQ_l@Á8oT?4'7/÷•lQ5 ¼GÏ9¹”“¯P°7«ç$B×WS¥j.óÁõòÚ÷|ñ4Rxv¨Ö”7Ž_vv¸,4?m<ÇŠhKÒ~­\ ÷Ô"‘ï®<óMªD%4-1 /°Çu\1QJR‘ˆÄÍAQ6ÞEˆ}@°¹œÁÏ‘j#ÄEÀ­Va¢kö‹úÝT™(Žøi ‘•pKÝ0˜êˆMFÛ5<ÝÒÈYbdvÅ­‹¼qßF-V-á7!òM´¹BÙ£ÄK¡;¢] ¯‹R.©hTÏ ê€·,I©¯Ü±>bì©[+÷|²·ÂQñc/F€£òWa2,©÷NÃTÿoñÊøî N $Á?- rîXëoRÑÖÞò7,Ãü¥:ÝRœ «'yùI~Lâ(&WÊ^&·Cp†¥H4Ø r"À¦KÅ1w8ú¾ájµ aôý¥%âÁië»BÅ‘»‘3-ÁñwŽóóÉÁèt@v1mªâå¿ÐI àí‚4Ã\‘Òz¹^=quÚWß ˆ\1™ï}¨gÊgo‘sÛ $_3ùxQ]1ù ²\ªKGv•«$wrÔùjTZ˜„u€Žš†Öê»áä…º†:r·YV—ÇOøÄû®Càœb)€ôw %d¯È׆H&`—Œg`Ÿƒ5§Ì0¤¨Ñ4?ÝÆS…oIƒ2SS½)bè7)x}ôÌš-àÿŒìUý®P‚ÞŽ®_þ´Z‰5ûßýf¹Çendstream endobj 228 0 obj 4716 endobj 232 0 obj <> stream xœÅ\éÇÿ¾Bùö›ç!ï¸ï#‘#ùÂvDǬsȶ` kv±Çä¯OUŸU3=ï=Ù€Ø}ÌôY]ǯŽ~?ŠYž ü[~?|zòÞWþôñóqú)ü{|òÓ‰L N˯‡OO?<‡FZ“9Š(OÏäÞòÔ«SÌ,ÕéùÓ“o&·³Ó¼S³÷^O2ýç̇8+¦;; ϵÓç»39‡£Îwgð4H¡§{ðQÛÙX=nz?ÆLœ>Á¦r6:NÔRÎM_bc¬WØ ~ü¨0 i§vø_5}ŒÝÝ,…Ÿ>Jóû%ޝèp°X105ΧÌçéÓ¯wu=î̬µraúj§PC;:RoxÞ§Ë;‹¸\SY±6¡Náe˜þXhùÝù_à€Êä`w³p ç@y Äö;›š@ž)geNÏ´˜½Œ1w¸KIë™>ÅŸãÊ„2-– ?¾`%"Ì1¸éÏðQ‰é|~?^â«Ö+½x$ÄBûwkW?=oÈûû£‡/ÛÃçýá·»ú4ovÂ6gç cH»Sø!íNîô$vCºÉF³;»(ùŒŸ~Þá :a¦ïá,Q?igk#RB:%§‹Î¹©T vc§'•ïÛ ržðnzÈš¾h£õ!Ò6£J\‰m´.$q Bð¼Ár.ÉÔ˾˜«þñ‡º -0ð£„×ÊÏÖMû<ÝÑ´2zz-q2å€*ÚºYÛé¿o/ó<ÜiÒã\bøì ‹B¹‡åãnœ™­³Ó³>@!»‰ŠÌúËî NRi]ŸáÆ Ž±Ö;Õ©ý §‘Ó¡¾Šé[O|y4Òèr48s?+bY‘H'®#J(tJš²´h érYÎ̘¢Â¼óUÅaŸOñ¡´¢J?üÑ\Q(Ô˜À‡³’*é«'mš'ýų®! Q÷´ŸÁ4Z °O<yz&5¾V™…ÊÊyˆÊÁNek%Ý~¦ï”ÝÇôEçë+;á+«¨ß„•+§¡j 0 úµŒsÞáÙ Ç`Ý! æW0­^k€Ê;GhÎf^k2!Fnë@ÓêÓ¹ù~ÈT”4xF°ÖJ•W…óAE„Æù÷­Ù«óóUç®Ç8¾FEÂ-(“6>F˜×¥!y„}ËÚ@ƒ6ÚˆµºÌ‚€ìîª Œ8Y ´˜u 7\3LyÙHÒÝÒý!³# ø‚6Tµ¨©.Á©ú€þña¿–E'~uÕ†‘S%üõ`“f7cBå]‚%Ã÷ ª 6Ql<†Œ1»J¥Àg¡Bq;8-à}<-Ex )Â…˜­`o·(7ÍW' n@ª'–s²í TI·õÖ”Ý3>Û; ªCQùÿ)ž›F­ßÂÂ×èÂPÝ2‹)jpEHÎÃ]Úvˆõ¦·:c3ÉËÛ³7VÅJd ›æpe·<3ûÍ’F®“+^é:¹òá@«s ˜6QaË 0I WЋzµíc\ư\ü+ÐÙëûú1§?Æu›$7ïPµ[ Ï³‘Ä í¥LŠÿ}\±­M#Ì=<ÖÕqÔÎn)ó6 —à$öÌÊ0s»Ÿ›ÿžae”wah^ÈdXÎ)Úi\Ùx*ŒS‰Ï2©­¢x„Èvìl9 *ÐqŒÉd8ª X†ŒMV|©SÀ´°;îškø£¾:¢¸“GY; Vÿ߀¹™®ÉÊ58f›AïØLD ê ‡ æFï=èæ×X9TöOcÏ›¸•û˜?bø¡,PÃ9­dââóÈ “☵Aû[¢,!P/ÚC ŽÔ§ö7íÁGýu¡<é‘'’.N·Ûûg£1K¦?µ§H¤Æ;wOÎo“VÙ’š¯ª¼@ß'ñNìšrM1’,c?jB:ï‹»7$XãŠm.G‘, ]:½8bó« raM¯4úr‡‘ S¸5wbX¹ºånOˆß{3TÒÏ:ˆb ¯KŸmbH¢E”Q ïó¢@>7èt%¾–Ì¢³r’Smc ´a5}Ö¬ÅÇ0<´´òuŽ`Ví¦±¬/ÙËJ9#OR8 ØhÙ©ñ yÉ`þº›œ«e¡ö댈3Åàˆ%íÕõÿuž¦ëY´(MMÛmüUH¹åäÔ°XßèØ±Ïϲ…‘´¦Zؘ¡CDXŒùºGSQt -€@‘„Ú°§ÄI¼ Çãøyj>I ,çnÎÒk·ˆy@ð@¶øØ«¤²ß,19|ýxg‡ê¢&!m8ì½TºKœ*à ÿ‚VÅALÓ‡¦ó6Ñšû\$î:O³¥mjvSYúéÏB@(YQFh®z’,ôƒš*O0îºâ¥¼zî!”}šè[‰­(‚ù•¤Çá Ôª[#¸"pÈdM G¼0Ñ.­@ ûoù ÄY¦úoàkºœZ²9 óŸ:DfRé 5 •G‡ÂïßÔ†è |WÿóNæÍH?dÅ|ÉlׂP9À’#Dz–®in&‹`N%Dv*ØIw•< ëð¼u‰Ùóˆs5 7Äþ+7å¢ï cs^¤…S”ÄáY$Ë ¸z'E?¤l5oÉÃ$”%)_æëè“­¹¢M3›bÕÇ^’âÁzÛƒNqg{Ã9®¯YÊÇÄÓ˵è3d¤üZÁn~Dw+çř䯰ΔÉÇ¡ÐQœkì*¬H¡§x€xh«ÆNÿ«²<ÉK˾s-Ú¢¥,Z—Ó´ž­µœð€›XJH»®ÉÀ9„Ã‰âæ¹ñN†•E)(V4„µ™EŠò¦¹-hTG_ÝçB…°˜«è Û#B? ´ƒAÕP€¼¥’(‘b'$"ØërʸY—J‹ÆfhIÃ×`%ŸçmõWÖ ŽzW8mÀ6#î٧Ξ£àðšä¢ì•¼²ý-IÂ@‚vW!²òzµÃÄòÒ-€;ìN›1_=mM¸¨ÅO;g´ÝÞòÒª5û\5UBYLZ 6á:äc@l]1Ä6%K³Ä\³×r;ßA\Zk­YkRxúÝ¢U-ª]ëÄ̺c€_™-MOl ãT»?æ^ Œy£˜Êõë!j&šµ¥'˜KY3ÏÔÙ+¶QÄ ìØ V@£(FÜNȃ¹@Ò`iL·=Ä2æ:G›éïHsªÃmüˆ» 2®<‡ì†µí0”yI€¡%Ø#WÅ‚´ü—[GK¼Ó¨lœ6Cô%0ÖŽašÂ7v¯¢æ…€kE(Ú_TÄ`é”ɶû0†ßÉ“¨áNÒVž¡²x ÍP‹îoxš5¶®ô†ÓÍlÆÀ­Z?sv€ÄšÀ1c”ŒKÿ³†06½Ö¥pƒla6™´RcKxê{ òÎü’lÕ ¦Ì“g ð.8§—½ozµ<枱Ωۮ ©gEgðÙ8î³*8¯U²p —Kð¶¤!œlŠ©zÊׅæGõbÊ.T襦gá¸!56ª·o-ò1¹ ï0·gŸ‰‹¹ž—&úJõZ•€U-SBgNaWÄ7DŸ&xb[Ú™û[KÆ_#øA`¡” §µzŽtŒæ8:*¬¨¨°üž2ŸcQ: 7 ¢«þK±¾c>ªa!×VSµ½:ÒHtzó5ÛF²¢ƒðK’ Ÿ)ÕR¼¿iL§Í’ò/¸}qT)GAzÇFr¼$•j<£bœS G¦ôt/‡Ž@’¸kÕ"GDuQ+¹RXîüoÕi¥P–×çµN´ð3ÝHQ)”[8wéÇ#ŒÊÈ(S,]Ð{AjuVn/„Þ,›! >µb¹áŸˆ¼¨»œÎŽå–Ð0«ÕËCà`°JjY-Ä1Ì„Ã8å—±@,œ@,„·Ú=?kü‘€'áWvéµ< ¨/0“ö6a·E}4B½äç&(í0$¥ÂÈlÔ܆q#`ž,ìˆâ¬¢"a´¦WrÞI•:„jµãJë0{µ.#'`ÚÄÝr#ñ`p@ký c»9xµJ¤E™o¹òu(xODŠ{bÒBç>Yò 8… +‹,W¹È6·[|©å™Ð‘RMœz¹!öÂíZÍ™Ïêet¥†wK6u—øur¼¤,9·6½˜¶x #UoþP>©ZbéÏËÙF:‹êbÔù *QéTïâ1dU‰!e¥ùœo²žµ]ZW}ºÐoÎÀÊùàj|ä¡VÔ¬Â4βܖ£|T»$Žcþ¡7`$ ’J÷-[ –¡“˜K€ —á^Ì¢äö6C-¨|ö…Z‚Øji¶ù^öq37QF:œ-$^ÞCK]zº;§Ãe¶Éép+Rì qµÂlhNÚj¼ u kÛ1Í­â&× sðÖçgm9®U¾Ÿ^,ž<Ôül^(×ÚÃ+È<[ùotcäsž–$û,w} Øþ,ݪÇ-9PS˜ÝW[ˆ#cw[\R^/jUHtsX0 îãû¡kJ¢Nò²B ~›sˆáë2µ‘%cu‚ríÅJµºƒÅ•ÞæÝÍTœ¸Á–$6ý¯›Æ7õ+Īæa4ùõ.]Œ^UÐÔÚ ØÑvQ~Ù×Τf_!f¡‰REÀD/åÍjuÜMP©„^ÞÅ/‡ ’2>(Xn‚Žê{•$n5¡êüC>>oï„ê¬Õ{óË^ÃwѾ\ëB4oí[ÔÛ»Lš”Ä ÁE‚Ôíò@-ô-¥º‡.¨¾¶Ò¨Nû1²eñ'H×àjïâ²òÝv̉;ÿÚY”_Q&·“=¶§œ8¬Ù}Ò~ß2¯ŸÒ–åNSŠè­ÝÖoeßð¡>s@Ù K.†ƒ,j×Ý>&ÕöÆÜÛ,7 ÇQj#ôAÃí$Šºƒ»»»”£™þ^ŒHA$˜d±ËZ畽“‚ ^øéŸ0÷6°ÖŸg£‹eV-R &Õ½Á[¦ÏnR „ܲ`׆WßÇ“”Îþoèšäôã›k/ý¾‰àõÈ–|¿¶%¿ë7øpÁ4o]0·¸º˜…ˆ˜šzŃáé*¿$Çâ¹5óF=Ø^‹Sàão"³¯BßoÆê7Z%=‡ÿZ¿v·ßo\½È± tÁeóÜHDçðÀ’]Þ«¢Úâk½ÎdK?9?ù;üý?EÔBRendstream endobj 233 0 obj 4556 endobj 237 0 obj <> stream xœÕ\Yo]·~Wó#ôæ{ ë„û⢒¸©Sd«­´E“>È’m ±%EK–þúÎpòð\]9J"ˆ,s’ÃY?Îñûlæû ÿK¿Ûûð¹Ýs½Çöÿÿ¿Ùûa‡ûéãwû . eöÌóýÃ×{q6ß·bß85Cçỽo7rÒ7éþfHÞÌ0~f&žÀÀO¦9[ë=ß<›øì½S~óÑ$6_O|VJ[±9¬cþ[¥r›çÐÊ=µ«ÍÐ#„Ÿ‡é™ÐÓIÚÙYo6Ÿ8‡V§Iï—°Ì' Ú¸âShUvæ\m>ÃVç9,ƒã—{Áñ°ƒ4wbó)¬„C¬$uZÀ ¤„)Úo^LæZî6ßLbfLþ?žÔ, zR/¥Ù|…Ó…Ƈ•fÚÐ Û#{JKËã-(Go˜tÕþd³åÞÇÛøê°ü@Ã’œo>/ßmðç-þ8Çgøã<ž”³8~ó'X{GFWÓ@Î;³y[ojã/¥ñ²6¾*HÞ;øÝm®GÓFuõëÚøÝ”[#g€ ”3JÏNz¬á³qŒGÖðInô$ãŒNŠ4=Á­¬„Ýh<0\¨T^àêСUx"áŬáFo&9ÆàFOãe)¯C¿C*x+@làt¿—[ñÈ–ý ¶¾Íó_d)ú‘)átÜâ;äŠ1ÖÔ}t^ÄÍ Ï@9ÈBÖ˜$çÌÂôÏqŸp°$Ù§°°s&ÓѬ”@ ¡ê™:®öâµÀ­¢À‡M ©ÂúdgpdéPª]è9§¼ÊSÒÊ6pÂò°Â*Ø]G³>^ †'Ð/Ì,˜%ý£‹A£H¦g-òÝf—q@Ç¿¼Báf ÇmQ:d¢0]T,\T3Ÿ¯­C¤êµJgåzRš>„Sáÿ ¸°›×È6¥œÌ‡Dz—Ål™ zuÚ]Î]PÁ]¨¤d œ ø†yT…°Êýqi¥Ì¸#f!W³]zÙÞp«ea1÷Ó" À…[Ñ¢´° ¤j”E¡À!I¾*O»+ç@Ù‡ë•ÐwÒÄáÍÙòp¢ÝÙÁYràõg.ŒÛFÊ T ¨  f 9­DÈY:¯ýDbokër½Š@¿ šW©¢³Ð ‡VY¾ÀõM0J/£6jaÊ|-“`‚¶!‰äŸ-õñ¤q´ùÐAø ñìU’ai]h7ÉM$ãd±¦É +fX‰Ž‹&5m¯ž 3ôH»W”ú7QóG³!VM1.é ©Þ¾ñ"(¦`¶Ù)Ш:ð31{Un¨Ù.«%åµF´8G³,áx’!>¡R«¤P ²\{£°æÝô«åñ“?àfU×2{²?P$²}Û:;”º"2é¶…qcñ§ŸÉà¢â™ˆ8œYšJ©Èi¥óU³å‚åÖ9ÙY«šùX/Gr^UóüŽþ718HŒAP2»ƒm—‰\]Ãè2ë8¢9hqÁ÷£+;jïtT\b=è’ŽÁvèº(剩$æC`ëáTâW gGÂÈiÀ›q17÷WvÔñ{ÜŠšQPÈVªäº½Aˆ"§1$vAˤÕÁ¿þT³2çmý%r›/l¨ŽY±/z -ʪr»°ƒˆ.â<äg¾HÃi¨“ì´,¥OœÉ±Ì/•1UD˜ÒP#ÐhP¢çi\•9eÆšTÍ t¤¸(»u ]lZœXs»SuÑ+~£ª¹êð†×0§Ü6•n]AÒ®¶ÄSƒ˜LÍzD‘œõ.ÑÔœæ’Y.f6«ËØj2ûYÎhc*ˆimÌhc2ûºä±(Òacq4數¥Ôæîcz’å¾.ÃÏFYî«ÚxS©—t$Íwm€,ÎJãy³û’@I3—uî¿méum¬k¾]ÉÆ£GË ?è]¯17Ç_QêHzßì"8VVšh•I7ÍÖò¯WÍÑÓØ¨`ãMŸ—¼,× .\–K?Î7Ÿvx\Æ\Œx¿Ã±[6þ¶€†qEˆÕ£š4Ì | Ö|=Œ ýþ~©˜2HC2¾b<2Í­¹“_ƒ–ဲ1XqRÙk®º¦0_®G†awŽ’GQAñ±&[sâÈÅêqïFïhœ‹‘A(»-%^sä-i•¶´Mq¢mç­?K«Knë)Õ8ˆ-ζ&h·56<øØk¤¨‚“Y M_·B$1è”b‰A@ÆÃ3 #Œµá²‚DXÑÒ:pÛ‡ ZOªÐcÐê%\Í))ÍŽ/¤lpÏ$À‹?"Û–ß “ü'y`ÆjÅÄ ‰äÀÉyDž+Í B’»O h”€@€ÑxˆšýªþÄKàôp·5É1¨Àì(–\fÞ6Ñ;EN3¼ç;uŠñz/4º»ˆ$Ðå¯IhÞy!´Ì›\0Åe4‰ c+™YÆX‡1†(6zÄ<]‹{¤Ä1º¾È˜6ô|@qFŒWµ`zÛŠT `nD>­ºŸW¸æîp…m63æ÷ô'ÃÇÜgÑw1Ýu>:`gû6™v$ÂüØãÕLp”]ž´ [¢Pï29B¹Œ(7?f4,„>?¸má†ÊÎAV õ°º`Aál šPë?$€©ÔiZ™áiç@)Ò?šÝ¡äƒÁÕŠ]¦Êû%¸& q%Ù![éÁ-CS"ÕÛȪ ?“p¹ðu3¢`¶$¿Xøžx¶žÚÅïÉ炬aPœŠ8+²J“QjóþÜzÅ´™þã¤Õ ‹Q×ÈO¿Šï8˜¡%aV‚m r—GËx…^í:{Ƀ56>JLwyújô3z¹Jج%:±k0ø˜`Ú@U¢¹‡H‚ ‹€•òúF§V#êÌfU'vØoÞq‡«ˆ»•2[_(Ò™Ûdqè|Êñ“mþÝÎÜÿÎfW苟Àt¦€i>ÖÒœ&/­±ÂÉ»ž!…V9øgâp¯s·%Nš¸ó›-àÝÙÈïÞP_¤CÌ7‘ìQ &†8Y HO ;NvM÷²ì>É€ªë ÿjt”³Ñ–Î3BŒ‰z:tµû:œ2H!Y«å`œŒn˜¬P5Ɖv7v¶v—ï"'E&;h>³L´ÒRø’eâdÄ‚Vzêï+!x¨¢EŸïþþÛ ëNs^BÐR<é–Ž«|!f]¶ƒß[àªR:Šý'©ËŽËUËLr·„qœ&Îe‘%¬ÛA¼ÉýiÖ³®á:ÀÛ«2 Î!@ƒ{­0|ßkp“Ƥ‡õkO’{wr’OÙˆsfãªÙl¥æd$†U¾¯«ì.°!“‹­Ç£ ìv4ÿ$æ¿\Lˆ[o^WHºuÙ¼Ä作ÇÞÔ±D/ÇàÁEÕ_äÚ4ó¬÷ð¸^ëEÖû°eÝß]ïûG/¯ï®ê /µÃÝ$©º>ñœäƒQ;¯Ë_ŒïRÞ¥ÿ°ö?­¿~Vý2_tVº{$K*ORq¢,4í¦ÏhR®Xã¼ùgÙgxy}QzWQŠÂ 9D) ô{ŠR¼Oèr½¸C$6 .ðÃç÷A®ŒЄ„ßÜbD/ –t[2G l¹ðŸ'FPOj&ñ’±L4 ËÀa¤H„bo¦Å×l¸&ƒÕ†~yÄÞÍá§&ä·Ç7'¹ùjB°„§#þ¥gÇBAjz…‰6R8„ïåÌ­óÈ,V…˜f E9B™ø:-7&@H¶Ò#Ün‘‡¢ó üÂhˆ˜•ËÅÏS)[¨MP:\ŒÔA>0/1Z'øÖyÈI²ø"ÍÒr=:TüЄK*ѤĢC„Bmð¯Ã [%ÔYðáÈPõOp›aBÛ>e4IÁÚ§MyäJÅöÓéd”$I.I~ %á¡pˆeº¤š£b”xËD<ݲs’~ÿP¿r ŸBàWB„Rî£ZKHëSNóšÙëd±¼b­ä™¹¼Hr*Hfœ•Ë©ö¦­F­8uÿD“€k[ÝHÂ[Jkð×Ä]­MGIQó³I¤ç£](ˆ‘.…]÷(JZ³ý;|\Q.]-œL‰«þ¯)¹+¿T¾"ˆPbɤ²!ýiÞÜWŠ G$(T ÙRð$Ápv¼s*Ô»Ê7<‘i–\…R‘͆jêEµmé}†;’7^”ÕP%,wO”‰ÌQ‹ø]Lƒwua ˜͑æDVÒSR++ Gi…eðšìÍö/ µ »Åbð㦺T¤n<)èD5¿–êP޽.ÎX¬þn©†§T {ýŠ% áõKÉåë©IÕZv²Ú¢õu­Â>²Õ=¾ÞÕÕn¨-j]«üØfvµºH @«« Tí#æÀ!^tÞ,‹»råkÔA£‚©¹ëSRŸ?|ltXÓ1¨È…´b2(ê½ç> 72”¼¦ïMÂ]W‹x>n‘àôm¡hæEë ˆNÂ%|{œÜ0ßRלÊ6wŠh’£ãþu…ágÄç,¤R™òŒüÌQp)»ˆ\ çV륲G…s«”æ u¤×ͦ~O¡åøÝ=·‘ë”À¤8¬mwH‡c壯¼¡+ÆBí+r÷š§-B‡ ° ŽIk|¬2F…gî©/*\agú¥z›òëÖ•d.‘Ú(dåË¡Ü]”"öZ?ŠpCþ–¾)Z©¡ˆŽ¯«•N}—\=œT“'N"§D‘0|S/þˆ D‹ÅëýtWvûá#£(v‚¿òáÖÊÙBä=>Û¯3п궻èòŽÖ>p.>€Æ'åVŒPUñQIîŸá_ŸV cåh dló$ &È…3 à ˆ·Äîõô6øãhÔHvV{|]‹øŸ—EÄŽ–â§(ç¤aXE¹ûûõÚ×r+Ò0ïî²KõÊÑàOþR5rŽë¸@÷ë1Ê:Dí&¿—Yt…µºÄNw¸ödÞ|X4ˆ0ãe9Y¿ÞTíwÞù“O[Ö]8ùמMùŸ7ˆ<…C$úçý¿ÁÿqÆendstream endobj 238 0 obj 4135 endobj 242 0 obj <> stream xœÅ\Y“Çöó†~Ä<Î8´MÝǃ’,pH²„V²–±„Ù]Ä!áï̬+«»zf@,‚Ùž>ª+³òøò¨ùe#&¹ø/ÿ}|urç¡ß<}u"6_Âÿ§'¿œHºa“ÿ<¾ÚÜ;ƒ›´„3SQnÎ~>IOËWÌ$Õæìêä_[·³Ûi§&ï½Þ*úrêCœ”Ûû;µý|g¦œ ÛàÛéNOZ+­¶_íNÕö‹Ý©œŒ1nûã®~³ž®j£¦Üöop8)¥œÛ~Ûn`÷>ÜŠ)Dá…ÛÞÝE1 iôö ó>F¹}€÷†(…çƒ}³“SŒÁÄí÷»S‹³ˆößgº4F7¼cH?»r5PwùFø§FÊI™Í©“—1¦þo¤Él¿Æ‡8!¤æÀ×Ïñã§-~¾Áküx†¯ñãÓz7]¸Âüø¸‡³þ<©÷ÀÝÆ[bÚŸ$%¶—õÚE{àM=ùºüo=ùbeè|ôª]~]OžN¾i'_Õ“?íÊab!ð«c¡‚Žasªâ$ð 3]VF­N¨²4_ƒl9gœé,Ò$•ÉPÚOÖ˜FiTÙ¨ 5;yY%‚X«p}Ê Ÿ´^·A–0Hž„;½Sl,¤T)Š"нú·&¥ìÝÏŠ>=ÞÁ¼q¾LÓ5@»ñ¤DIF×zHˆäó„UÖ(À ”6ðºrTgð ¨\½(“Qìä[TCŒŽŽM¤]¿n#±yÔÝ)׸PÆEÑ„ƒ($If7ÏZ ÕÈ À”ÃŒ,ÒÀ^Ǧ›Í†6aûX“d$‚’̱´°XwáB’%©ñä.>›ÅÀŠH“}‰“µ“î–×»HvFcãXïó›-Ì#ƒÓ>UDSÆÍ©Ô“Eq¦éŸ'v0€0È-#A =·¡hjwëÑÃ]@O¥ÝöŸåÜ*O” G·Ïeåätp…LH£­r¥ÚhTaÕ¸‚_WŠÓˆE-ãZíÃôk#ÄÇ pû î=ý÷ë\¹²œÀü#¿!í,§`G&)ì æHÌD6”^þ3¨z69³Äžì&WÙc,Læ#ˆ‡±4}Î5bŒ_š{!¹‹UžÀJ‘5>ûtô—Íãí¯;Ï­­O¦É zÓ{íê$ÑIh4L«XS«„5›~Ëüs{êº÷j™. — Àƒ2Áµä­ÐÞštÞ€Ñ"\Ê$®â½çífKòö(9r«5Ò€Õ·|t†+:4šÈSŒŒ’t‚÷Ïİ•¢Ã†tÛ²&¿Ÿ™¸Š¥ÓBIœ·h D[~¦>ùMTºÇåã$ðüR·kË%A¬—{Y>8—ŸU°À„åuʯGˆÏ®I9£°ÌF}Ñ&Ñã2®‰)½×>Ft êS€ÝLA8*4TŠ,µ$6åN”Z˜‡fÑFJ!Åžè…-*ÃÜzt’”w±E1ÓÌaýXO²;âó€ic\€t|;‡¹¤åKž§8"µž{Ú[…Ù }t‡ÃY=0$ûyA*j+,:ñI“¦L€1 áå$¥]šo ¥3~kð­Ie'¿¸šÀQÊDÀñ¡®3Û£j6“ þBÚQÄŸ¦LÏi¡ EÚÔ´Äz$Ö‡˜’À82b*Cny ² .Óeª•Ñ´Õ\€(¡"0÷»‚'šÜ!S+‚øº7Õ¤Ieá½.GÈL·{!*‡h¢0ÐÀS1%g]^h<lÜ`“÷ª~˜£ª)Ïf"E’,â[ÑŽ±ÙlÑÙ¦« N/Å»@l•r(%%©E~Û>Ï‚²Þå 'Ï¢<ÑJ,¥^KˆhõÓûê'«‘M΀f [òÎó¤«|Ÿ­>Ðɪ#Õs±‘X:æÅÎ:½ìÎ@HÐS „͹P"Ì“Ù]^;áïÈòÉ5óàɽ€=FXÆ0m‹b¦ÂBªÙ`ÄÅÌ/ñã~•ñÏ‹ 9Îh0º®c\6=¹ßEyª™³G)/!gùöai‘g«w#C°yMàÁ4“Àçr–°]Ù¥.( è KÁï¡¡[*ã}uÉ轺„Y4ƒ\— êÙ«KirGé eÕŠ.• cWŒ«e$z©×…­h¬nv]ÒhQxD/þˆíT‘æk%GÓ#’‹:MN×`>Ñ*zl/àŠt×Fqè±–YÁŠ×¾2(MÎq»ÐÖº …Êg0¤Õ?X š*GŽ’G‰cQ9’Ú[Ìö±¨ºÅB‰‘A Ý|–ÈB‡y}dY%Å [z|•CÓõŠˆ‚™ªÛ'^Û‘€¾9Ö*"˜{ÁrĬ~®ˆ>”<Œ‘Ù­”)Gÿ·Í$$"²÷eÒ¬l´UŸ*T'T«d=r’gïã$?dOÁÇ Êrüàn×'X¶§È¢«7f ¸ö-õª›äÇÇÞµœ+Õ+{ÌjK­W#ŽÁ¬úH? Žj¿ŸMù!™Í%Ý0'ÎWqpG¦p’ïÕ¨µ}: ‘¹G–Ôˉ5¯ÙõéÜæŸ/x©$;ò¡–cvŨ²¦äg%ÿá”üztòj°~Ä(µZ=”jg‹9ò,Ö¦>ç>²Ö æÎñN-:Ùr–s–oÆ hVJSzp†YLû8‡ª3Wöö„Ï|L5^oHsÖ‚Ò@\ÍDÂWI°{U·‰ôСö.õèl×·í1¹{èSá(ÿ~ÐRÀ옥 §/›¶ñÔyJ²ËI/ô:ÌŒŒ÷~ÂÆ¢ÜeÙZEõfÔÖ•€8‚S¤}%çΑ²¦Ôa”™ÔŽssû2ᔼåa–54 [J ÂzÞð5ùaL£WÏ€ç°$¥BWò3úcż…„3ž¼Ø»¢£ö7ÞÂ`°|¤å»é„‘jûËÔ9Œ@òÛ϶9Ý>yν"ËSˆíú"na©V4¬èâh,Ø*UK?9Sd×S)pó˪,ÔÁšÆ_ì eer¾ n÷A}‰ò<5Ò»ˆ/r¼€_–^ø¾6•Ë©¹\IÄôu¡¡Œ¶D“ì&Y(ÒºUí²Ñ}’mÁŠáÃìz¶CÎÚY«þ"ìbM´-$ý4 ¯jmÜó¶ &-Q \î%èälÈK‹Ë¡ÑRü€\d'1óE­%‹•Z”éaAÎ9¹&èË’ÒB¢ËÉ!ÔLFmOZ¿NˆJÓãY³1l©:rRdºypÐ ÚÛwß)1€Tÿt}¸% „’d /4.sÊX•ç” ¾fúP "öd³É8NjaŽZò2 ”ë{XÞÖ^rÝ6tý?ÃÈ€Yh|ß/箇7Kq¸Ôvr–ýÐÉ5 ã¶ Ø5Æ-ɵn=-BÚiSB-XžC”£ðflår 4«kަĆe a¦_¬Xìv N>‡2 œÚ3½ûª÷¶irš2êÔÙ­­z5sQ9Ojbò¦¬ vðéZ”EÕ™/º£§ØO$Ö7õ@tk㠸ܾ¡,õk–Ö“Ã~OÙP&Rëíyz¿fxdÉPYöºa‹ë8åV&u4·V0Ò¹²º5œ²C ¼ÞôFl´KDŽd<íñÚ²Q’?t#OiÇVmÄæx³ÞëTö6ÌÔ^#å(ëÛ ŒôYžžú›Òè•¶€QÛØ¨òP3ãne žÙ÷™…-$ó æÄºœ×¸Ùg­”)4©Ë±Í:3øƒOû®î2ÚæÆúÆFðæ¢QqÁLÙbÃæ†ËVô½ÀÙeÎÔ&û ÇjLArǰð®àc .ÝùE«[q&®iLR̯ËC°”HÍmöëÔ´òŽ}Á$)WIî×MsµE©îÝ)Äö¡4wÕ%áy¨'¾ÊÙùn…S¬ë°Ál½ø¿¦aU O ,—%húæºõŒíšý/È`ÍÒ§fm1øÐû/ ŸŽmÙ u•…=N¦UQ_Œ¬sAv 6£ÞÏs}¹ûœr}Ú-ÄVBåhE§®]&Ø7 £ê€ßÿŽ,å‰ÊÞÆSr¡£”ܾ”<ºL´¹Hð›m_gˆ§lzìZ6s¾…v;‡VÌÆµôKÝ ¸ž-BêHù]-ŽÚÛÕBqˆŒ|«eoÜa¦3ñÉ{@ß®=2ÒÆeò6e ’0հϤ)çqGɈ”fˆõ5„¤­§=o³í «B½’ÿ%óßç;Ϥõf|ÍLf0ñ¨&ñJ¨Ù›ŠQ×c;ZAõhY±X;ÜmßÇË,}Š~F¤ë¯m»ãâ¾xº“fÞ¬¯çøBÙÙž¢eð2ÆBVÜS f{XÒ5×·'G¯èk{èùuàqgL+3x–ãX‹›ì²|Wž†ÑÝÏœæ@"3eC 3On²õ^Í>=M ÁÛr2Œo™ÙÁ{0À턺3H³½\A*óÍ[ù‰K½/…«ÝŽŠ ©ˆ2ÛQáÅÌ ÷Éñ_;ú™„ŒÂ ¶Ë£ÿŒ¼_&{Œ´iÁîMM8Ùwá^£¶Qëá‘rKŬn½*8V}–ò–áÃ&d©ã‰±›Šõ[À‹)„((Áüû¤Óà‚WéL?F5U>7µ'‘4ïUn«Ø?¾m»Ô* 2ž6ýíÍÈL9]תxße‚têÿ›WèÖѶ¶£ª‰3ý0Qé ê¡È;ÚÝD™}ÐcT¿-ïb$¯YÑýès?C @‘¶ûÝ q]­Ö;ö—a¨†£¢ãB˜¸C²õÌAÙa¥dι±#¨W¯²=¨ˆÄL€0޽ «8µ.ø'ÊÌ0»qP›(‰ªÞºe$åÏúÑCžÎtc{¦ŸY§Ãj3;‡A°0ÛÅÔ,{m€(‚¢“>ïžÚh0öºl¾/J¸“‰ñ wûP½Ë¿Ò“Ü‹‹uÈ#¿ò–ê³9㯎áb5÷ˆC–V&WAÑÊ3 ]Ö—ŸdŒƒºHm¿ŒM‘4ûM™…ät(.± “Vj]T ´Ûî}Î.k 6 ÷7©Ê.ìþcMσµÍ?zy_åc/Ï{3`™ÇmXt\=(©`Gû—¨Õò˜R{Ô_`]’Ïê=lÃP÷ lË âÛÑã¯v˜3´à¦Wž¦¼%pîm½ü¤]n5KúÉCÕ‚ÛªiÖµýêäìGñø«ú1âvCbyåörÿÕïf|áñ³•ŸV·ý%ìGê8ã)¿k$ãëóvãóµÅPâÃ.µLwò?‹\"Ïendstream endobj 243 0 obj 4740 endobj 247 0 obj <> stream xœ½\[o·~ò#ôxNá³YÞÉ—uÒô'M¥HÑôA–,;ˆ-)–åØùõáu¸Kî®,©bïryÎõ›!=v<âñï³7GŸgŽ_ÞÇÿ_ýzÄ|ƒãø×Ù›ã§'Јqx2¸Ñ±ã“‹£ð5;6üX[9ÀË“7GÿÙɽÚ{õß“¿Ã‚U_h7Œ>:9‡†_ìb0Æ9¶ûëž ÎYévÚóÝ·û¤T†ïNJ›?‡§BÚÝwð”9èÖì4Œ6ÀÎÝÀ|ž:úr/Ì`ӻ탧V‘·ßÀ0_ÌúÆ¿„§Ò ŒÉÝßð©u †Áöó¹`{˜Ë³|÷Œ„M,Œ$TÀrè >>Qn÷ýþ à[Ãìî‡=ÆQÁ¼Ÿîå 84…þZ ½û~Î9ך4<)}ÆéA¿~zdNqnXØ.é.â6Ä8æ\Ø ·¡ñd“ÕàôÈÓžÅ1GÅv—a?oð©RÖÈÝ Xˆ”°»·û¬IHÇwï`Ò\HÈS$¯†ÝЩéùê7|/Ü7d…ïK›/ª• 9X+ü/ «%P˜’û=AaP»{¶?xâÉ)âP\ÈÝÜ9ÎŽõn/ ?#è{2¿¸@£ùîgØ cŒØ]çA¡Ì uyü†´6ZÒŸ¥×ó²ýá§$PE5§ð:õúÒÀ °×Ø«”zt~ ¹Éë21a=#³æ©‘½ \>Ž–Œûj F5Œ2mø‹Ð¹ª’W¿°gÀ(ƒ°Õ0Aáɹçð‘æÆÏ\2x‘&Ÿ‰ãêË/2u¿Ñ…B—™¥ýÜ•TYcÐ&¿&_à­°h\ç;F³ãȬB÷ ^ØjåÉ®± ·¸<•æÊFQZ“v°i0›çÐ΂øsåf„!ëUé>w &‰ëÒ Š¨œc÷#Š`b*ÜÙ+Ô{ ì8eËÒ´l÷Uxè\Å´ÈŠ¿ 2VX?YÇ‚CäÙ Ìc´' ~m |o§Ìù?ñ«ŠÍˆÜGZع6@þÿ ß[˜Êƒ‹mj2Džâ7Ñr¨¯.ÂÚ 1á­WE†3›Eò ÆÁUYØ(OÍøÆ0ßÈ[­¬§ÚR [™ÕÞ>›Ò™<æI‚àqæ¨õªÈ@j-CX}mºþŠÖØßƒ °›×Øk6FèÍkµãi¤³¼[IQg‡¾s^óö43Yoãš~z°þJêlý C¡^r£;0z_íñ½Ñ†6%7øq t‰»¼94=Þ›{†“/Œee•Ôî¶ Y–Õr€ò„8щ¨’´„Exèí‡UʉTê88:ÁÉM Z:.0xܦ)ݦ1¥ñƒfë¨{›tèží‘Î1¯¸Û,–Ÿ–÷×tcà{î#¬¦>ÎphÓ×øÝ¶ãµQAý‡äí7¢e\ðŠhâ.ðϧøp9üy‹àa²‡0ùÝ“Ü äUŸ·m>NBEo'„6—åá“Ö÷ùáUyø[~x³ÇE1C¾~W^ì}4†ù…×/Êë×ùá¹ïÇHrÄgOJÃw¤óÔðc~vM–lÎçy~x–û¹ÊÏ^·hQ¼h‘âmð ™xðíøA¸8 aÂmîùçj­©é“Ü”ímŠƒ;E{:-?ß”ž^äž`eŒ/´Øý17 î˜&åëu“ùê4ý ‹ô¬çߢÆñœ zgíÌ¡ÛÀÍÏò-¾ÎÛv5óõœ×Xüõò^_fnî°}Úë›V?¯ $jz]T›e!5¤¢Þ,sséücîçº%g-n¦¢^åéb–¸ù‚ÊQ ¬¨’Þß–Ÿ—‰›çÂ1çæͦ—¥éinú¦â Ò«ëã ä|hq˜ÂV `Tö:ôÇöb7v a{o4".ïÿª]ü§m &7q×@s-}@RLðBÌïA®Gˆù9¸5hãæàeò‡C‡‘ öB›”sü.âYۢ‡Ê9Fì§ÿ 1Nldª8 Ûq⦻Là+ܲéA( °±ž˜µÈ]ríY´k$öaÄýÑaàèT,¡Ã~n—±©¤œ~…¥L—Ðalƒ Á": ÐA‡%çƒà»áI¡Õ\9D\Or†kxDtø`x@ðkLXrp‹sD&$‚1W S{¢E¹®Ã É‚#:Œ»ƒ~Ñ&tØ“Vúàè°_OÍàˆ ËÑnĆáoÏæ]¨À‡–}&Îyp¸ma|„eÈF/X˜?‚I‚¼ËQÞ:vº#õt.NBäë„LñÜ)Âêñ„6ÅCÞY7Ï’!‚n O(n,G·ˆ§½ZÃ㣈 ãÒkÇë¤èÑ 8pðήc£6æzlÌU6Æ\‚¹Z†ýº7ÃÆ\¯ÀƉŒk°qˆ'e 1æJ}ZL5ºDfý 6æ*ÁÆéáýÁbnæ`1 ,N›³—òˆºŠ$jz¿Näs˜¿?ZÌ•wh>-FÜk4mŸÐâX_Ò51MÔÀ‹ÁKáûR¡Eß øBÓat®ø¦®1Š“Ü/£›³‰Ë$V©aj^VñÄ«œñc,#Æ –hyx_'ãÖ~œÖ\ç^üâ ÏW¾·–Ç)‡Q$kƒØ+[Ã^cÝñh*ÓÓŠü~'V€ë´N6( ­0›ãA>4ìÉÒ$€ì*ù„@?ç ãõYy6A¥A"­ ö—‡¶­X9d báÖ<šÎÜ<ºÂ’ñ„"ÍäIrÕE£æ ýü|¯rE¤÷: tµ'X† bà$³ž5¥}$B ¿ÅÈ)•¢ïêí®+`s]ÂŽÛò–ÀU>UÅ1ˆÜ¢èq >ûäóâ’M8‹´A^RXê>«—$N=r阣fÁJ,X®íB¤5øQðý*·™è‹gaùLŸÃ’B¼e þ5÷5û}žÉÅêXà#P®¬ˆ*Ýt´b|&XMH§-a®kY€’+]à!»¶ÎVI³*`u.°Z‘£– û¼,*"P3±Ÿ°rÿ#Å8n›„*ÜËN‰n#ÓÃ׃0×–Åø@´[7IêÓªë ¥Ò„LqNz¬\ÊÇ~ý,D¢E™uÄ ï a–~ì!VêÛqUøb1í!Õ>vùeVå …Èã{lŠ’²kUì»\IŒƒïøºeoêìNSš­!ÑIŒ•’ ú?w±‚ø`Åyš`·Xáh¸~Àjí¸9·ÊeèÂÝ¿V»Ø+õõ0°Î`ƒÑðO±IØ,¸?û§¬ôFghnì½7%\|C]¥*»yÿäl•Ú|ø´W:àbÖSÉó™pAR«Ú5L™Ç´u^Rå„HÕF†<4ÌŠŸhIf³«å(p„{s†s“ w¿à ¬`"$á´ÌÎ|§õ¢sÌð²êÐßÌ#Œ"W]“R^|ÜŒ&û¹9/Œ¯Kâ/ºGžfµ°taÒ1Ó¾¼•é-ê#z`:ŸÝXP'é4>úz¼J ¿÷Z·sÍ43}ÀÓ‡ànLõ ª\%èpäìF‹õ;ö+Î)ÂINµEØ=a<³Så–QEcšU#ž9Ƨ“|Áyñ€ÐUýRªµ"çm¤kŸß¨rD(ÉÏÅã,ÛV`óÂa;8THP>=*iÔßGjíÀÉšDÅ©.úOÚõ˜-dòôà²I>›žÓô'Á$•¢H`A˜½Jâu|¨àÞíH$M•“Œ]F‡=‹Ù;¿¶õS­J¿ÐdÉ!¶Û•F7á`Ã=Rƒ Žj:gd ÝI*dîç$]ÓR½Ú4:eôoËu$¡üãžSpé›êÞ‚ó¿H—ä;~hÃ!î†ïˆî¾c©Â<•_ˆWÂð<òÑ% ½……®jã¼Òëáˆs§>¨âS?µ4E›KŽâ›ë2™ÄUi4yÓª‡¤²#¿ìZ§¿ß+ ·µ›qKƒ ¨©ôˆTØ%Jx˜¹ïI6©ÜŠ#¦U@…ú§æ°è:j–?P ˜páׯá3ð0•O€$^Â\ˆó0í½ŽÏÅ3`T#xÊ¢cšGEUùƒâ—Å*É”µº2±*"w`cÉèå±h¨YÑ 2&)‰øzïÏ¡ážOx”¨ÿV1G¥¨C±‘rm+›ŒüöºÑwÔía}œù­u>Ï}¢½j²Ó¶Su³,¢ /Mî»?%WË"HYÁÝÊrF=ù<%Z)fAQÍ^Õ·ZP·ÈÞ© ¹qœkÒÇc­ûþù…j€‘ï§Ø_ÜP´ÉVÐÞSñÛ‘WzUÃÇJ’‰Š÷‘›ë\ßuF¦L©4Ï}†à,Ç”fRt'wv"N¯o[*g+8î'5žˆ³«K6U(¥÷ÖWUƧ>°Ü2ؽZ µ ñ†4²ÆV/„­B]œQþÅšPŸ+9¯z.—âW·w©6;üJîÛÆêšü¥‘H^:I‚&¦ºý%/Êíæ˜lˆ<½ ¤ÄìûBþ¡Ü+hÈ…·WJ1ªèÖNÔy<8šD¢qNtKªŒ»ê|þÿ9ïåÚÖ;iïˆMõMñõ¦]ôëãpññ³5¨ŒM‹%f§`–Où´£{úG$¿à•r?ÍwC¶´&ò~õ˜_’QTþ†4pTÙ ã¢ç¶³äv+DЏè—שVqva4,×e쫬ˆ§°Z4ÓªåæÇEo«¼IùpÜ<öÜ=L9kÌN®Jµ$µ¹T˜SôzX¸žÝàAòFµúõ7S0õp¡ïHÅéÞ…TÁ5#¹6pRXåè¹ö-õ ki5r168ÍC¸'œÞÎ -Á1dbƒÜ…Äæ¬œ+–_<œàU°o V*Ђ _DÚ”Æ T› Xg_¯_ÌlŒLŠ|¼oÕÁN2f Qv=R An¸-³›•ëUE¬Ì€ ûïüd¼ñºtƒöá!NÅÆÜ€uþD$U£Þ4R¾J˜©s.ºá¥ä›…ò‰r_¡måäÂ) Ϻx°Û‹Rż(µ—(ï·ËH$¼6(Æ•Ë^ò¡ã2zKíp²ìÞûV¬Áébãµ?y—ˆôѼ‚ á¬Üpé:J49óç“£Âÿ¥Uù$endstream endobj 248 0 obj 5240 endobj 252 0 obj <> stream xœÅ\K“ǾoèGìM3¶Õõ®:Ø6’,Û²%£å |Öl˜AÀ‚ð¯wfÖ+«ºzfØ]Ù"´ôö«ª²¾ÌüòÑü|>Oâ|Æ?éï'/Ï>{àΟ¾9›Ïÿÿ?=ûùLÐ çé¯'/Ïÿp 7)g¦0q~ùÓY|Zœ;yn½ž„<¿|yöÃÆnÍfÚÊÉ9§6Š~¹p>Lrö›Ï·zòÞ¿ùb{!&­µÝ|¹Up¯5fó'<ç}fó·­Ä[”–“6jó NRJk7àPá$ Γ³›m~Ÿq2 âlà'ã(κ4J³ƒQÄ‚סŽ6—8–s!ˆÍWÍuïRnóÝöÂàÌa–ìÖ[%'!´Û<,ݯ—Ùõz7%g€-öKÄ?nðç5þØáçøã-þ¸·½ÐÞáý›ßLqSƒÚ<+ï¸Ú^H\‡·ôx<ù¶žüPN¾ª'ÿYNÞ+Goêå·åä£ÑÉëzòM9ùã6FÁ€Á˜É«àA2€y;Ë(±Eð«‘ÌE‘wÜ3/fµÙƒè_m¥› @W`ÛÌÒl^dez›5)Þþ'%I“Ò•I);kZ[dÊøÌOø«œK¸¢Páégõi_0 •†ÝÕËlœëzˆcxAcôjÿ©]/…FåQa¦ñ?©/(+,ÃkZù  H·táU3%åQÉ=<­á@*Ý=¨\ uEY(³IRp w€Fˆ|r$½:Pša4n½R°p™·;¾ÖÌ!¿Ö Ï_‹Ï]×+õö´\éD{=m­XZ7° ‡ÅŽ/ˆb&/lµ•1X:{ÓO¨Z{E6€wà…šŒäÓâ>ÍÂe{ÃpG`ÈÞ¡ÕCóæ\ݶt|ð ŽmŒ³Þ{¡Ñ ‹¦$C6¡C+|kƒUR¡Y1xסŸn û g§a~Û±þè é×—¸|kå;_1RÏ¥çÎu‹³³àîÞà¹æ9ppíoq•îæ¯û9J àk¹p¢MˆRÃß"X™Í ×ѶjR3k`f&)‚~D¡f~ˆž%<üÕ–»Wð)eI6Ë•ä ­¯Èz’Ê™«úÀó‚Ä]…úS\£žfaW5¯£4Ë˯‡“`ûRF µÒÕ—GpǸ‹5¯ëFî~M Ó‘$íWbÕ°jx³qúaµ³]1¬+Ö2¾SnÞWïÿ¼º‹ÎoXGki¤-†Ç$é!ö­m}^GÊw •‘”}”éÌí½Þ¾îZ’K Ï p4ß ÀTx)ŸNå_Dàf/2ò?lª8 "¼—T6åÓÛ» ;òð–û?|Yö.†Zí2ɵÚóz´ß*ŸÐAž`EÓL}kÔ‚´úÖÆ_õÍèÈÐ2Ã?’ü®…*1èÅûʆžUu ´0dyL)‰­j`c.6× g…XlW4”u¿¢±– ¦­b>‡HQ-ø€ÍäÃ϶¦°9šþÒƒ)ŸI{Ó~[@ʾ%†Å–Ýnmûi4øÁ»•éGôÛɳ_|Ÿì}Yçæðú*§ÑbIÎVˆ \GËlÆ æ*…¾1zQûÈi‘­©RuØâÈ-ÁèTcˆÛc(i™1PlíñCch+Ÿ¸XÒIÆP;„ v‘úkjTæ)¨PuæwOˆ0ž2 h½°·E rÀŠpÁs'³"Z‹èx}^Õ¥A¯2¸‡³ÝG †ZåÅ’Óh›W)>PÁ9ë_‰*>RaÜ "Ó£*cŸ(OHkì™9R :%aÖ¥í5Ö~¬e´O‰·¶i°2D®Ü,=ÃÒž£ ¬pSEOœ;íÛnŒ¸/¹¤ôc;K ¡õ‹qþèä>.:à­VîôÆ1…Œ c¦Yg}9²õŽÃqŒ'[À£¦ÂƒyÅLCFÑîHÅ»dE$0pš«š—–W±ïˆ¦ÅEôôŸÖz;Ÿ€ÆÀ.ƒ†¸ßꦚE ëNå[0±ÈnÛМÌjT=^<5J] ?Ù.;W󖘂Û|[r}táëš·|¾’¼,)FÊ` C^†§wå¦ç£D#< ˆƒcG ¬xòõ(ù®ž|^NîG©Ñ7ͼ‚ƒMÂØnÛ|}xÈÝúŒ‰E,æð¢œ|QOîËÉ÷£%T=­—i⾤„EÀó]þ6¦nD™)@Š)ɶ6•›1-“ž&s• žÐRda8ΰÂ<³]3FqCæ0ڀ׎¸²Y†3¸ålZÃàô-s‘¤²Œ6}–½TŒ±ù+섵jQPï«èJûÍ_âÚ~öû‚{4ó°!hæ"ºäÖÀ7%¼äøÅ%šÝÍ!ˆ®¹ØšHÛ ζ…Ä ŠÄHD]—¿Šó?`º—¤õÔºÜsX£lA§?å|{ Dú8¤È.çrÖ˸ƒLl^‘fþE£%ä^zÏ®Í p¶&T´ ZPfX*í¬.Æ}ÏR a‡—†ª„஘ÿ7……b ð>ù«ÂùgÌ•á¾mxm:ùrD‡,üß[$ÂF8vî'µDðçØG¦ ³œYÐrååÉ&ràùÔf‡† ›[db–|• ÏŠ’JC„wØk ™-€Õ rÌŒVüÐ ,@do=S$C,j]µ0­·ão$Qk» ¸ô×ÍsÌ{mô;-ì ¿c~­eïc­@OV‹¶Ë!sm’­hìnvóãvÜ|<åXÊGI ÝMͳã6 œÚ¢÷˜eM1 D\†0(!”'²U›CõðËAð‰Ê»TbFÎsŽeࣕ‡ˆ‘u#}l.:® $G¯Öx¡8K¢U‡–ìJºšÀ Nt7i‰ ¥ß«5ØÒ†Ô¯B«Çè{7ò ˜w²(R³L‰H#µc(”e.6®ÈÜ ­e2­ÒxZPS´ÊK;¦™7Ð';¯–x QÚAt…Æ›ä‰0ÞÒjÆ_Ài|EAvç9·áðï …Ù%×´ŸìË±Ò Ì¾t¢•(*Ø“»dÞ±ÓàW±Ì<û°nqZ©to1ûRw.uŸ7hJ[’µ(>¿¬8žj(Âβ>ÙQô{¬6‘߈m£è!U*-´UæÝ˜•`"§aL®J1"'=}ÚtÈ QìÓ¶!+%ïF´pý[’&:ÇYˆ¶‹%ÆÒë%ðKŸX” ÎgÀÎÀ\X~I¡*ëk^½­(j"®¸ÅeI¹Ó;n"îÒûþ EJªë'š"gÃPyñ•‚=¢8i"ÃõÊGãž:^ôŠ­¼CÈvm-–ž*}w™4C©Æ“úŠ´§(¿ë7ÁŒ¡ð·&RU‚3¹˜êB”#ŽÆÚô…£Å‡/ü§/ZÚ›˜;#P¹…Mc¸nO©ä™\ª}êÓ%7ø85¥·âÛ´n…n‡ÇÞíõÉÈØ<kÓ}¡"¥ìÊÁ,&t€Žò¾·í|þ¼\øuú´Å”Zøó°t¡¶²Mè´r‹ÈqzF#ƒù@!~ñ» €õùÿa ØxD\·€»Op0¥eJ×¥CıÆ*½RÇŽj`äâ[ô"³“õ=WñaAßKµïÆs;~™:ñˆnS[Ž Ö~‡6(`Å`Ñ)\É·¾FÓb¬³;ñ±'¤UNY~/»ÎcCÔåa¿æ)¨ê~x^÷!  "LSÀRU”­v0ׇ¸~ð¶v”ÁAãFš÷õÙåo~ÈÆ`6¢6¡¸·xÖRŒëKÉ6\Û6K»òð‘rø³ï-)š°¶]ê–µœP­½´öÔPH×pêC^qÐ5’,.š‰éñ‚iw¨M-¯ Ô¶HŸÎ*’øËgñÝ ™)$7ƒ=Ïì«ÓeøS%q¼¥È„˜r^6I¨nfHÌ}“ò»ªm\6¶šøxíå@aQY|¿?^„DéÚøÕក…ز#Ù¶¤®‹–=&Î-6;"t£eÀM?öýöPcR/«ì·œ§Æ­»Ö2*ÉÀjÑE<³ ìàûkå4åÉVÕùso©g´Uc?‹š]+íéw¡”Q¯ +Î?­í¦!þ¸¦ž#züGg¬¸MDOè‚M9^^¢¦ØÉzã rjÕ0þsKk_Š'ù­*Ïâ[V¼â>2ÕéâúÑ—>¼xôÅåÙßáÏÒnNendstream endobj 253 0 obj 4560 endobj 257 0 obj <> stream xœÕ\[Ç~'þûæs"v2}ï¶äHŒí(vˆ½¹Hq€…v¹xû×§ªúVÝÓsö[ÈòÙ™¾wU}_UWÏË£yG3þKÿøüƾwGg¯oÌG_Ág7^ÞTà(ýïáó£/N ðd sG'oÄÚâÈÉ#ëõ/Ožßø×FoÍFnÍ¿Oþ5”hjØ0Í*œBÁÛÛc59‚Ø|½S^‡Í­­ÜÜÛ‹Ikã俤–ù2>UÚo¾‡§"@³nc¡· ÞH&) znèÎV¹É»`7ß O½ao¿ƒnn/ÚÆïÀSí&!ôæ|ꃀn°ür,XÆ2C!#¼ÜÜ…ž°ˆ‡ž”Ix MA¥ Š ›¶Çê:á7ÛÊiž Œû‹­ž”„¢Ðž’°–Ênþ‚Õ¥”Ö²‚'µÍ4šÓÑ l”@Xý V]°×?£K©P]ÞnQ•¤Ë‹ŽR¡fÏ,¬‡¼èF¦©›9ä¡¡„ã€Ò Œÿ´¾‰ÏbóIÖ,ñuƒaÃlMã¾X9ó¢i!¥õy¥±ÖÃÜi-xY»o?6¯-­B’D¯$®Æ± °ZƒdÔZ–*×íÞâCCŒZe êþ1(üæÇM©Åä‹iËC´c`õH¢”‚Ç*.+êšÆ!êõž¥¡­ù®1¯ÿ,1ág*Ává&¶á@B6Êh~™]kmëµM‚œù¬!¹õS|» Âæ+TSJ‹dZS‹Ú‡A‹ û=X‚Ë®žÖ½fBóã[“/›Çq 8&.¤ÆÂþguH2ŽMÌ!$£Œ¦‡Ò”˜*xi5”¶°‚f«Î[È×gØÂ³òW}þKî"k‰j*Iª þ I ‚$•Ùe´< ½¬Jµ¸ÌnWヶ`•Û<¨=0©þÝvFíD{4l…Û¡ðŠñ`óšIk>´yC{ͤ¡Ì†¨‰y;rÁ‹â>/d° ý l0þËã$‚¦-º§ Xh=IêRë—G °x 5ê‰yîÐ"–3 òdbl|/ÜÈ#œ©PÙ3‘`pg‡óí¨Û+¬tÆaªûÉf£æ‡,Ç ß© £~NÛ$<ˆ¯‚>p<îjz#pU¸ªhâl ƹˆá'déAÉuSï#«õ/êÃý‘¤ž¦%høio‘³\ß *0T lˆyÞJײ—p½Šâ'‡3Ô¤„ÂÒk* ËY¢#ƯYÑÝÈ$hø;¥AºÒáF8cõâÇßvLتÒ"bÇ”êYe?l´ý°È œU†·®†¸´‘D@‰ï'cøh„\µ"3ìËç£êÏ žŽŠ›~â_?,/ 6=cÉ‘&=|\ ^ðyæ‚ÏK‡Cp~5èð-¸¶†²­å|X<µBü Ñh™öØ«ßrf¦?R’ƒ\ÇÀ” òÑ0ú½£ÜHÜØ©ÏƒEèBÌ* )ö†Ü‘ý00%q0 Œx‡n!säyúÑ¡™“Þ>rdUà‘s‚-ùˆý6Ù!dà(ö æu=„¤m1!}`nbDHSOögØmfźãøÿƒÆ÷¸»¸vHü+ÃÆ/®ƒôçãò–yh€NÇnÛ•þÖ«‚ÏGµß¨º¿ ÙS6Œ UCäá@— rœ+ß–#нÈ #´¹½ -‚#hS1ÿ[Œ3`¢›§²¶šq)Oä€<’A’ ÃÊ.±âªvoW£²„AŒí C¾)×;0·Å±Vµ3àhpè"Ôä“ݧì9ƒÎ‡”Gªµ<Z—Ù©ÆÈ¸œ%çEè±!cÙ.ƒ `ÓPvú0Q£Ý“Èp#†û²LÏý¶°Å“Y(Ùkmç5ú¶t)…í²Zб8s±7ŒÔÖ˜Ùî ¶AÒ\3b0¦æ-²å˜‚ -¬J0TÆÑYT›Bc-³[UäsÖ PãNY%”8;S¤uØÔ®¬A, ¢$TEÐ'ãj±@Hà{äÑZM–`ñÌš•hú°OV4Ó写bãcÁ6/–áó(jJ<ödQÀ<Ès^+fP»™N‘þÃ$“‰|´3 :iÖ‚Asë–ÆÖ0´.[ìYÚI9&„,‰½(l£ß+±ö6¥+Íÿ€Sƒ³ô|gÆYް[ž. 4%Ik¸L?åt…?et  ¥ˆZ9ÿïÿÒlr™Sÿ¸­­©Ý#³ M„åÇ™#T¨Ã¸Â½™R ®¤Pôj—ã¤m¶è8ÊQ@“aRÄŽ0Y]†ë<²Æ[b]— ç\™€ÅÑâWÓj*¿+“#¶¦„l«5‹©›Õï0Ÿ·=-^Ýq)i‡7œ³©¸]C€A÷¸<'‘Ð!/š«f]c&Ó©”"ž¶£Äþ¾žØ–0"·ì¤ÔsIyÄQ,ã´3””k#}¼aÒNÒ¡¶·cpI>Ó–¶–ZžsV˜Sôúüåy”"‰Í^¶Í¦$µœÓæQã ß ”Åò›ØeUÜ&7·$8D“¤[$§¿87R¯ 4ñ´=N XÏ`çå‹l"KzZbû"%ÊUúÍm1º–ÚÒÞsä—ÙÞ.õ^™­é´ªÚÙhëùV¹øÁùV1›ù=/×¥|+2Fí—4œrp DwΞ ›;“ežoU mó>Þ»ƒ…e9ã+Ééľš,ÌÖ+¸ÆÉ+Ûqž­uÞçÒÐ" ³vs}.ih¯ººz)/X:ÝûdÚœõ¹VIÞGùåC'wtám‘Y"õr$ÅdY†÷TL‰]Õï2Þqw ÂïB“š2€¢~c~`Ä®¡Ùlûƒ¬öˆd‘CÄÓž ÛÜ >äSƒÆWS—)(׌ø6~jœqë¦îHò®I~Èa £ªÎ.7 C6vÅ}w¥Ò€ÍJL÷W÷å©5î{ç:q_Jú¹¼ØãL”ŽA¢?ì5 1ýM\³°áš…Ú “ßóxèà¶6Rb†ÒÆî8Õªã\a ö+»t$†GfÇ _ºR/“‹.±ÉR— ûøÕŒÌI¡€×FÄyËͧyF«_Û`ÆêSl7Cò¶øÒ˜vAáæV\¿£{kXÂùê¤tt“‡¨™o)‰œÑ’ Qi¼Æ­ò’±ë€ ÿIÔÒ‰•:æÐìu­°ÌbG×´ù E<ã„¢¯-Œ-„cöWÆ2ï·iº] œîÈ*ñ2ùB’2T½¨И{?GÐIÏ•‡r—oó™>ÅVd!Ÿ›·¹æ8¹úm‹6¿w­Ï¥´`Y 7ÔO L›g±ÝuÇÀä0¹>|füøSV‰³ä߈U´.´p¡‹À ÎÚ,ÜgÍŒߥrثӚg÷o§ç/¯î\O¬™>Ó·\!MWJs)8×£u?ØjRς־HÐg!ÀΑ¯·W|8}=;ºäQëìÕ±à^ȵ@áòÛSöÔ¨|Ù‚7«g_ÜPVº[üà…\qw'\‰ûúWïak¡éЯSlyFœÃ{_Ñ—€VkäžÆ–:ûýDµ:´Ö®\ã¨}§¯I|KßÄb÷“.º™òŒBaɈ³l·uF‘h6«ÆRç-æ¶ä '7Ùrú¤ˆ]¹˜içü”ö;§½(Ç\ÝÆŽ5û‹ýló(ûÆ:̼Ơ¥AäÛæ ¢ÈØÓ‘*ÞåqQW b€ª]–·É+Åg¨±€7ë±ýFeñÜT¯£,éÏ\º¯v MY µ¡|ÝAuîk÷Õ'Ì@óšƒ}Û8‹Õ`æRk¼¹.\q1oé+Çy¶DåmuR™° ¾¼Ñܺ“F¯=©Ð(»_ 2²çEÛ©‘¯°Ù–{€»@i ÷cã˜'pÀcîƒuz¶ã“|™H~èô¼Üï¡è‹'·žÛô)}ÅE¸š”ãîMds'‘f⯣@‘æ»}®­f¢½¶J zm•#B^#:&(Á‰=OWñ~üŽÓU:yуOnaý—ÌkeNÀz¨3;µt3sùáÅC¿’äŽò`ZGbåt7~Ä`åƒ1XçË£×=Þ¥ƒ@£‚,ªcljÌ»~R£Ø!&ÓH ¨An²5÷aùñÁÔ“—•Ã)Ì ‘p­ú¼éDmOÏ5|ÔïUJGßžêŽ!ªJ–´!›S# Ä,¤ô°˼w†: –ßg°6À²ò­K1Öê=2|}×"^4Îy“TÞ8ÅÁªÊ€‰³ïE¡ßhuÇãsLA¹Ý™é¶ðèzîuu‘ÖÏvŸ‚ËQr®éC€,”9©‡ø WÝ:@4VcÊ÷ò¯,ýº<Û;—e††ÎoHÖ›Hvq¹?\Úm â~yrã¯ðï¿¡YKXendstream endobj 258 0 obj 5154 endobj 262 0 obj <> stream xœÕiÅñ»å7ìÇ÷"v˜¾»#%‚s‹B”DÑâcaïšØ 8¿>UÕWõLÍ{o½K¤È?ÏôQ]]÷1ßÍ“:›ñOùûÉ‹Gï~Ξ¾z4Ÿ}ÿ=}ôÝ#EÎÊ_O^œýæO¦4'uvñõ£<[}棔>»xñèï;¿w»i¯§‚ÙYúÇyˆiÒsÜývoà¹wn÷»ý¹šbLÉí.öçð4ªÙì>ƒŸÆMÖ™Ýã½Þ}ˆƒ¬uAïÞƒ~°·0Å»X_X¿ûfXX)¾ä»°íŸq-3iZÕáhxñù^M)E›v¿ÅŒÑ>ÂFôÆÓ”Ikí=˜Á )©²CRsØ}ÜÁ36Ö-‚Šÿ¼ø=` Á0'˜æȺ¸!NÌÞåñLÖkw^ž›y *¥<Þ2ç`g ˜4Ó¬”N°Æ9ü&e§_Tú»=ÌsZE›¡\9‚Í„y2püÇp*ãf8êW¸”‡ƒ^Â÷£vWûs  h8s{ûo˜<µ|ñw3D6c,x@¤ÇmpºòvwÛ~ÙÂZóä¼Ñ1ìnÚ lìkxè`·{FÕpºëþºõ ±:(Ûq—åáPgã hÿ㣋_ òðä)ÀMxx•ì-¿S„Q¸éXÜùðÁžð:iøu‰Äçf¸ú+Ó&ØKBÌñÐPÞ¾¤^k6õ P°@u_Á”4ÃmöþºN¾B¼Æ).>Ùk7ãgp´yÖp¥¯})˜*ð¿ÞŸÚ ´glàÑxX6ùGÎ@ûš¸­[K e¸ŒrìÌ †| ÚrŠu½µ7S(7%?ëÊŸ"uÄ4‡‰Ó3UÂ&€0 bº zPÿ!4Æ&½ûy7ødŸvFú±uà.øÒÏHèð_רÜžUauÏ€£­¯Ö@Ôhµû¦ :€y¿Ë¬ÇMR|ŽW ¨4}d‹û&À±#ˆF»?í‘N H8&møá™TùCacâOÿÖ6ü,ÓHÈÝ ÜнٶaA;épÄ„6–ðr%½À5f`kvßšCPìõ„Yk’ßý°× àuËÍÙÂùV¼”€FðÖƒF@á´{L©‘B8¼ÜMrt©&X ò•nûÐ/›® pGxnû›|¯fö•¯ûÈ”„” "2L)‡g¶*NZyÜÎDÐTº’ëLŒ:¦Ù³se`™ó‰:Ý!¶ŸW‚k?:m_I4x“ï˜m¼Ø:éD.!Pa%«OåÂ0Õš¢ (uPE&z`-Û¾eôÚ˜ô ^†E¢ü¦P¿‰õHòù+ƒ1‰ÃÝ\L@MŽoÌÖj÷•ú¯~àëŒW ‘4Üb£è׸¡š”BaßÀxÞHáï¤Yé©q V"á2mSÞÁ)¬C‹–[‹Fo¬_/±¿ý¦s ÃãU:{™-™ó|^"{”êtìÛ~×ÄFhzÅFå´Œ6oûÄ/—„tŠÿŽÝíR¢áPc(A”ëÂ9æÇ<_{ Õ%¶Ê û·ãàÆ!$°‚át\d‰«L™Ù¦¨.³–*¸ïšÊ€äïK­$eœ¦èÙÃQý‘ì°¶ØñÁ7£;‚Sìx´Úªb‚cþ¬p0­­ì ßÍ]t’JË_­l"ðkD²{’ t­àèÿõ°ÞÙú:WºáLR„P0*™ø^v¤7Á`²¸lÔm8`£iª;)Ÿºï;8ß#7mÙB©àhzAK#Ùè„V“,­•`ï“Û£ oDbºÿ0.iûÜdÉgTf•c`@Í:‘¿yw Å"zG?hð•TÓ ÏVW‡ú¬£ŠÒ.S"Iþ¡¿E8££e7ÅEã©—º±0gæ˜Qúãs€–5 äœEË#kâ¨úoöƒUU7ª—¬ˆÎµŸáݶͮ]BŽcï%ô‰ÁÝ7kÛÞìgý)Ï…‚AþÓZ6Mjh§ëÖ@×ëà¾ÂýZz÷ÿàò1±ZÄ?nè&ÃÐáò]2fd?q‘XhwXYƒ1»0+4ÇD7Ŧ8 BÖv… I\v4¬B­¢VLNúedòJÖlÀŸñ–pÍ£œ?ß…Úfɰ\¸Äóú)à{á:àÞ#Ïfs«àed†Á7L0Û AYÉŒA©È:¢Áb–ÒîªÐ¨?Ùõ3c.%¸õŸ ¢<ÌDj#}†ù(mÞYBƒ0®MÑföž\°kiÎ@¼ë×£ÕAÖX7ÍÌžÑì8C|/xSe;Ý ‘W€XNÜ»²%ïBòµèƒÊhcÄÏûè&ÚŸ­„r1¥Qæ´ÝݨZð²^ŠFW[¤ÓÚÈ \Š”ak–Ù #b4ª¶d3Ð"€ìdú;Æ0Ìçh'¡ZÕ–é©î´É^.§6Œ~X§·áÖnÉ:²ý“h*玞}Ëœ£ë#Ê|Ï5Êu Ã5˜lùY\rSÑñ…‹ÙÚO–©™´qˆÆÉŸ2™ûÆà6Ii Êî>@çY)Œ‡™üö;üÿ-þaˆÏ³kI6lýÿ‰æ™dD÷BOçÛ6†=|Ó¾êѳŽšg½û5œQÏ„Ý<ìuv)=¼•üǾ>•"¨ç v¢I1#DÏ&#Dß#˜ÚéëV´NªYà·­’Ê©rÿløJ/ö½wÉ‹-ñ(íŠ}^¥¬ìq"®d/øŒÞžf[C+“"jݰ[5WŽ)¢÷;? !bíñé¶.ðq{ÏbˆîÖ‰xÖÎ[MGßr¥œî µt6˜“ú´˜|j;þSOÃRqS*ŽhA©uøöQLpK›åWC~d†‰±ßó#LûDèð⛕€ú|¡‰7ò]:¯ã75¨Úp·Rø‹@ë  /]fC½,qdqr‘,ÐPxÊEÉBç+èz/™k›\ÌÖ´Êw"i¤4);#€…KG|I²Q³Ÿs»›àx°E:²'½ô‚«ßÃè™+²c]Ф¸6Ä“^I,Å•¹UŸâyµïÃTu÷%[‚FaÈ|ËÄšù2ŽÒCæKƒ@Óäei?i°‹PÃé"±¯TI£ bügU"cé]*29ô·½æ©ý÷šÍuû Ãæ_áÏl‹Ÿpµ O½Œ1PH,û²æ öÞ[ùÖò31<¦É1öµ²`Ð!¿Y“C}«œ”Šâ†zN°¡Ô¬üÑ,ëç5² U‚©ÂüêàðÆ-iƒ›…ž‰eðÄÞó"4š¡Eö µ"[¬.v‚¬´4VŒ´U׬Ãã‡(R§Z&ô˜mß *ŽÏÚ_Þ‡=ñJL<ñµ1Ñ~G'{Û#§Xé`Z¹ºôwUYك̃]X]ÜÏDe³ —uF³ë¦’Ñ<–ß§Ks²ì†õÁ¨ËÌ¥}™ùÎ?Œ>¨ èšÁ’–±ÍUäéð‡\Ò@)-qޝy̧àܹ 3 ¸z‡ÞŒ~Ñ—ý§ù?(íÊvoíï}T¾ì7aFi÷I÷÷žm8}y4új1P%FñÕN÷ó¾jìŸñ‘kÿ®{šßJ ½éûôî(^õ×Wüë9wò3Ë/2óû£~&p¡?óÓú™@&‡üÌjl¼¥Ÿiµæ~fUéäÂ6cge=ýVÃÚŒ§-‡¾¼e—øòm¬¤cÎP¦\‡ng˜*ïÝ7ÙªÀz¹æa2óá$Ë7ÀÂqDäÚ] 2?eqÂ+A‚³¢á‚ñ|ð[Yì«àˆÛÏFŠŒ å!lÜ92‡d»âìmY¡TTTVЇS¢–”»«o[/û…‰Jo;¦%ÿfVó`¥hÛQÖg™E­E"`…xgÖúÇü˜©^!K²à;Á4ëêü8VôÇÑõHÇÑOGÿm åŠ \Ól¤l‹˜ÈW°™Öååjù0£ñ10º\ì"$SË!k@\L ÁmeÉÏo··H.¢R‡ËD+û€Ís”(+T‡h+ïcXZ¦À‚´ÍˆH!œœ^÷­8NÊ×Ü7OËB:õ=ºÛ&yGðy©8KvÆè fkÛ¢ðškÑIÉÔ»vIZ‘u­ò}`,d,p!‘R;±j6ðZÈW¥f¤r‹•OIJ]i%.é“+*$7x'ÃTÌn»èRæä^ÜPåÿ¤DŠWîà6UK»oç­Äâ°§Q¸¹+GŠM14²PBíWI.ÝÝ„¹“+Ð2›®yŸýÿ»ÿj¯Û¯i!Q?×¥ôðVr–y¦¡]‚™ÿnšM僓Û&to›(}º6F(ªÂÖlX;\à]()ƒ™<ŠÉH='öd‘˜Êsg#£lÑxZHT<µQËÎØ¾F¯€9ÔquxT¦´9ô ê+ãYz æmMkÕ¤U8hwÕÚÅ»V=ÓÊ49Ã"}hÛ’/‹ˆ\Æ2ƒ+•*k=\ß-ihÔëa¦B 1mol` ¢‰c"Ø‹aAäÅ8>liÒL3ÖõJ5lJK‹G<‰ òĽ¨œÀ¥kFòØòŠFfÃ<öù‡Ê¾’ãâ†C6vº¢Íá[çN¤R¼Zó‚ßÇø¢ý‹™‚Ÿ ªGǬz˜Y·jŒÀPk7ÿ#þ\ÖàRÉ’ÜfK±Ÿ½Iý“¾+Þ¹ÁJY5IÎXWhµ'íN=Â9b>ŽWBµAßÇc¤ž*Ƽßôˆ„©>”é,¦¯‹¶Ö/Ójf–Ê„£Ðs›”Bãôó,ö}ìíðxÀ€QƒTÔ¤ƒ-JwÊŸá«Ñ},‡iuBAî®aù¢ÃƒrUh¥r‰¾`p_·rѵ¶Ž‹×‚ï­v¨ØÄ[4.†ö9|vè[!¥áLŽÃ.UNŠ$ 0»‡âp̳;Ã÷O/X 6EÊåfkÝiæ?Ršñ‚IPá?œ×]gw‡~#¡œåºB¡Ù ”²÷\Ë™’Ž`”÷píù´Ç+cÖdDÙÄÃɯÞË¡åe¿ï?m±Õ.\ÄêéR{ñR¼ÃyÐï=Ê õD€s­z~<ÑØ=œˆpX©²ð¥‰}ö;eÇ9I²]?Æ|,kýUéE?¨×^Â’Þª ®‹sC¡¡ÑsÙ›¿­ŠÅ‘Ÿßs­+¹¥cl`¡`{b B tH„4ç>°èåàtžW\Œâý¯°@qªžxèÂúÓC sõaÁ ­Ãñ(+K\õ¯Inø‚ð 1þàÎ Og ÜŒ#”ϲ¹Ð›eªžÅ?ÌÙ ëD/‘þ·0O´£îef _¶æ$$ä8t“JŸÚÛ.1Ôù#•ÄÎ Jb ­ ]>ÕÅêC=ËT‡ ôûáÅ£¿ÀŸÿ íÆendstream endobj 263 0 obj 5310 endobj 267 0 obj <> stream xœÍ\io·þ.äGè[Þ·°¶¼-PÇG$vê¨m€º@I–Õè°-ɶúë;Ãs¸Ë}IM ÃòŠKÉáÌ3gý~— |—áŸôïáùÎï_ÙÝ“«¶ûþžì¼ßá¡Ãnúçð|÷ñ>tâZÏ<ßݳGó]+vS¼Ü?ßùÇB-5þýçþ·0Bòf„ñs0hÿ:~µÜ“ƒµÞóÅ×K>xï”_üy)?,÷ø ”¶b±_û<­R¹Å+håÈÚ…Ùx#„‡á™Ð“¥´ƒ³Þ,þ¶äZ&o_À4_MhãŒO UÙsµø[ç0 öŸ®ûÃZtÒ܉Å3˜ »8˜Iê4@ H C´_ü¸ÜÓ0Ör·øëR ŒiX÷㥤€®@O à¥4‹—8\a é¸_i¦åݰ<²¦4…°<ž‚rô€Y@WíîI6Xî}ׯ:ð¢6ôzÖáWK‡Ìàvn´ÅÃfG§×ÇõõUi„ÑJ«+ÿ nx/ÉûëÞŠHã YQi|½Ì­Èz‚„þngÿwëxüjS_•ç#ŸõvÜΔdGïJãiáñgʯÜñ¢ðx£³²Š¯?éÜñ¸ÇÖGeºÆÃúú²4Þ:½ÖUœ”އ¥í’nžÒ gêÅP0,ñDIëÎ 'ÈÔǵëEézÔ,Mi “Ê*Ž ZyÌ´Z$RN%2uŽhªOÑ@J7D“d÷%–2vA¾¼a"ïþù°ˆ;/`s P×£˜Ž aHy½ø­ƒ”†)iƒðŠÁkì§tQ@í ÛÛJ£ÎÝâ à y4¬E$…³Œ$¢šbù÷°jc´µ¥á O;ñ`[žâ ,Y!($–hM®¡§sVÒ÷u‘W8ÖÖˆºQ\Ê’õˆÏ‹_áá'nÉ Ÿ–hˬï²eËQ3 ®R¹7ÈFd„§}qè9rCÆ ²ê†¡Àf7h£[[,ÐÞ€UE ]Äýï°`kµËTDÙ §¬°3-ÄrS_“CÃa‘;^î¡A<ÁâÁÒ¶œ™š0n¼­ƒÈÙ4×»g?ˆÝ=°Ã%5,;¾ó°çxøÊèrøº=| :Ü$B•N_8‘ÈG#8y?=}gÕäô¥2 TœPhOB 8N]l7¶ve–8GßácôgˆAx‚DŽ4,UzêAýT<¡¾WƒzB 0=Ñ䑪ÄÉŠ\%º§'D,І);,¬à•…'Í1Sµ@™8Ž‚ JcMÔ£Ú{È‚Öõ…$¸†Ü úÝ ç÷1ÑÁ0£u ö“Âü)íC±ß 4ú¾+rZ»ž—Æ­ìþ”ÐuÐz'-=Ôן{Ô7«º +‡§£;ú]1É3›Ø× L ÅTµ>@~<©c‹MžÒ¬.(@Ÿ±îÕ•™ZÿÄ…ÜõˆºGé}@1aB@`L{÷pUí ?e§g/JKt?»f¬…Góì¼`2’”ÙùŒ9‘“ëjz›DqFÑ6v}DsÄm©]“kÐf6ˆÇ6ÍOaôøÓ¯ANÇÌÙþ"Ýê>!>8ñó~Þô'œÜÔô373ý ,DXÛ›~˜ð!M°fu.ŒÕk{Îî÷À V笷-ÛÕƒ-kj+ô«:Mô}ZkT©€qÚ›œ¬èˆjƒ:Ôo ôÖÌd„e`ªCHö°bÃå4hi‘°ƒLozAË = ™¦Ã'!S¦4Å@2J"6ñI©ã":×YÎJ´—rÕÇYâF‰ÍiXØ@Üô¤Û<û†§h‡ ÖØgB÷ršê”èzˆMÁïÎquàÜ‹?oø­{»_ÌãÄ ˜_ó ÐMcžè¨IŸÛ;A‡ïì?$·v\´ñs î;Ž7ÁäÊhSêm´³¿QYk²öIsâ­_à4𣔬ÇUÜÔ½'åö¢,ã{²3ÌÈv“Â,‹‡u.MdÔ# í¥-‡ø^e Cñm•árZ‡x篤 oƒê©æF&íTiGäó°<:_ôÀÒÆÄô:лúO‘"ºÈf”tgW‡õ!¯ãFrד×U–#%iëÜ_,G¾jÐ]ÉÇ36W¯l¸¯zl§ö ç9h1úQ…w±·Iâù K:Ÿˆc³­Œ°À»î}Rm¬¢WÛªòâoõ)oøüGœÀÂ#_0èýØ5:h tÏ00²ÖسPk0h‡—‰³Y–±ïigg#mìhñÿ`9B·,•—Uÿ0¡z°¤/‰¶P¿¡ð”¢²ð6ÏMƒ¬Y‡ˆGÐNþ¯rÁ?˜i¡£HÿPï¤HpØ–¾€$·UBèåîåÈãÃØ&@^–Jm¬¬hEõ|cFŽmªªÑçgƒStÇ©- SW± ·­Õ2i"ßoóö_ïÜ„&:+, »¢—f It˵ ÉŠ*ªèÀCø§ •d2EO÷:`|}yÑT²Cê´fÒ; Îèȼ‡ü®Z°’ k¿kZ =N;€îƒ Bø@5‚ ûý2dU±ðà>b²Ä e‰i¾5%éˆD1ä=”¸§ù@òw0e S6’Ëâè–³ûæµ+`£à­gRÕø( ð$DâD7Ðj òEÑÆÁCšY‡ŠÉð¾kÁ°ûAìÃXÁÙzK¡j›Ì Äe…žD¢1ãðfD¶yÜ t=‹nøÒð7 }¯|b¦B ð%Šʼn¦^GmüÏ9³†4’à´6>YbvÖÜ4n;ž|QÌr¿r3à@üÂ{!1Ã;,žN³uzzÖ-±0­ñIºÝ£ÄÆ©„Ñ'†zÅm¯"„5e>…»K A›æ½¼ÐI¢y«–$vT4G+ÓHadøàš é7€º-„óX•ƒÁI!Ó¼n­Cüš$j/ö(°Ï‡HgqÌ&h&'ßhr¹µÑñ2™êT_6ój"§¹w”f“\ØÃ„.çñÎ+EÙ0T`ö\±ÜÊh9EaósÎÒÛÝrš)hž´¤ÂþžÈèM;óc°þ6O‰Þ˜(·ö"¨ÈÜ(Tµ-%K(ëÀñæány+IJÛj¤§)¾ëÈl¸Rjñ»ïhýë[9t)8-ßËW÷’±ÕZˆ¨§üذE‰Wƒ7ÅdtRGénŽø;¯$±¢U¿˜ú,±‘{ÚQ?¦þ3x{†Ï¹A…Ï4´(gë~‘Þó°ŸXÑÂþ!ïšl£!@÷‹i’Ô™ªïZX~)ÆqVÐ6¡¬HS"þ·iJ`l@0’öNA‡˜9r‰(^§yŽŠ¾Y|ëx[4‚‘³¡íß5˜ ƒZ5Íkíy×So-õ·7ÕœNŽ¡­¤\^ï¥(Ù¢I mèøWlm꦳&f8¤ØœY¬Ý¬¬g¶nk„"]¹¶Ñ¸92`K@J7»pJ÷ZÄ´É“’{ˆ‡ê¢ª“! ][ELQã|-3‰ N'ˆz–”RÈqÊqâ¸`÷¨º;³¶"äÜý<10FoL§ÍS“Hfpõ>k}S†€d)W€ ³€J%‘a'‰ Æ×ç1ЧÉÇ)úé¶‘.ÚM¹Ö^Þa+àx)w9Î<ת‘î‘„åÄÀ[7ÝÑ˦yßHgbŒ×GT"òD&ˆ œèJEòÌ8 ^÷š)Æ4¨~U8šL® FŠmŠP1$êüÎrTÁ¸¹åEÌòÎtm\õ©&æ8ß 4[ެ¥Žc¬Œ÷ô5T.¡tW¹—Ôs˜hb^8wc·Ï°&ðO1Q”½ÖŒ=Yê†Õ±#ªÜI±n`Cëó̈í¸âtÕ÷'ÉQß\B¦Ám ~ ’¥BQ=óQl‹9œ¤ù¾$¦%y$pÖ«i°.=½{ºUf°nº“]m<,B9§¬Ù楩\h8݆ßì5x?_[¶%ÞKü€NÞ ïSÀpg¼ï”çŠPí=­x•æ†b·Ë +Þ‹¦>wóš²imÜŠ’ÚÙZ®;õa·õ5­)›~IÛ”øÖ²»Ü±–â5U{Ó ›Ï\ÚO€Óg,Ӆ׺ώÝï±ÏÉfV}Iû±$õ`ŽO? iKÇÆÕ‚ÀþöÕš_£âvûò3î·(?K³l_~†÷8jŠ*w-?Cìoá¸S{+à øoT{»=HííÿeÉì«f>Øp/É.3¶ž÷Ggä©ÿUôØ?êû¤övúm©úc:4eÿ©ö¶ý$3?~¬”(bw>E8êuí~†8_›»ÍO÷wþþ Ë"Îãendstream endobj 268 0 obj 3944 endobj 272 0 obj <> stream xœÝ\YoÇ~'ò#¿h6ÐŽû> €mÉwG¢a¶(R¦K¤,Š–•_Ÿª>«gzöàR±’æèé®®®óëêýõ˜ü˜áŸôÿÙË£Ùã‹ë#vüü½8úõˆ‡Ç鿳—ÇŸ@#ÉáÉè™çÇ'?ůù±ÇÆ©‘‹ã“—G? f¥‡q%Fk­T¸Y[çGÁÜðéJÂs£õðÅjÍGç¼×ÃÉj Ogrx —RJËáó•b#¥´ÃGpû`¥à£]~¡Ìð¾PГµ´ËaØa_r¡W­áÅ·+>zï”>†Î¤ÆARõÒ„OF!„1¤a$ÏzÏÓž3;ü³’'•ËCXî~:ù8Ì œ‚ŒÌ³NÎAȽұ¡;æ0ÖÛ­Sõd£åÞÇöfÅFé½…aF JJÇ9t2yhÍ ˜ÇhýðÝʹ‘I˜ñëÕZ WÃóÐù÷fµ†SÞˆá)Lϲ‘11|…M5WÎÃShê…UÃ;¸ÒÒX>¼] ?jÇåpƒ+øzJÝ[n†sèɸÑ2 죱Z 7áBr=<ÉA¤ŸÚÐö<Ïì2\麆GÌ{É#…¢ ØÈàò룓¿þ0ð•ì- ×£7Läuù&ILå&.§ÖÉ)ùpÈ/ àÃ)¬á«*Vp)~à€B\ º¼?—†™áÇ´…‘9\c/—Iä¥Ü2ø»†a@4¥ÎVÒ‚6€¾<«áW¯‘IR*/ÂíYTHä"‰VÊD>{ cG)<ý®¾¯__µ]ãŠ*ÔñyÖhX ;jÊZ‡ºŠs€Õ  Å(cÒÀWjø¤jÓçEžeÊ&#.”rÍrzPpo'zñ)t´WNKb ºñoq \1ø÷ÿA>Ã,Ö2¬èp¿´>ÃÛSüù„sH–3ØFY­üðw˜Œ` tù«7µÙiïáMyx]†µO{B Ú?:é§ê/^Æß¡ð†N[q˜ Ï‹,x2¡ìñ?`@c”ÑäŠXt´ 'ØLÖêá´Â œæ»Õš…μ‰ÖGèw.¤@ñNBšé]R|¯Ê BºVLõâiNRËÌoìãE& ŽPhzÕi–Çv1‰Š£€É- Q0¤v£< Ba©˜±”ñíM†)6¯b˜‚æ?,²ŽûõZ¥™Ä+WCL}( —y`$l‰âÇëÀfÝ@ðÛ*<‰ÃTeÛ›"¶õªÓh¡Dýâg´6(ž|Ò³Fš U‡,îdeß$«Œ%Ž\{‰ÊmŒ5Š^V Ž‚¨¥ €1çà¯q µ¶à᪜‰žRQÅp‰fz”×h$öÄ«D]E—’ɾXé‰###u_wÄ ·"ò׃ñJ¾ÈØ=|.»{¡Mφ˜üYbˆwz£X +ÁèmvŸËjz³@G† )ãjF«ý´´¹¬ß”‡è%ŒÙà%€6ôƒ„§‡y a #¸;?º A¬ ñ<‰Ðׯ$þ'–ïÑÊA,ìAI¿_……fä$„cHüV'í6E20U·ÑI+¤;s¡~q'k²›“j¢N71qUCä©ÎÜÜñÞÎK”4´í^B8 ,|ã%ÖBCn¶…|ŸÆÂ­vy¦™'W…îj/£¿áàªÝÄÝ4nBÉà:ÝòLÏ òf7‘²ÒµØ¸Î*2æDTß¡ö‹gŽ›ïà(0ýáªuJ„øû}:ДܯQt“–=Ýwãßðy1µ_àíã]}óòâ:½Ívúª´y]¾ûúõgË"À¢Aú¾¬zž‡í “ó  Ϩ¯xˆ§‰óÿ$w`<„A‹ n xc‚[r)u:šªÌðÛJ«,‡ U-ðM5O£c›Níå‡IȤ¾Œ'KÒ2 Í2Ž[ûQ€iV×&Ï(1……¥gB+qÄËãakçÑ€1V@¬*åiרVQƨ8jœÈ¢œÍmr æ_ žë˜ÝÎÌã"¦ƒÙÜ¢‚;¹;²sÛ¤BÙæUȦ@Dïågç3V `ç>`žÂ›ÄVŽaeñ=ä‚ ®ígüÍŸŠ0é¶r'ƒ VÂ*‚Ãf/!œ”ª<ˆ‚ÍJ¸CmŠöø2þH É' ÖOlAâ%t"D»üN­Z3[UÔšøÐˆ,ã0Ï áà!'1.¨gÁF.ZÇBŒÓ<ÍBOèFÃ]_õºŸL‚KcÐdÝ¢Å^0ûM¼â"^H@¬'3À”à 5±Ø,¼¾l§n|ˆäßVs\Z¾¨ÀBÖŠÐRÚi}U‰*_ãJ[dNC>ñ•][•<- _v9é=á˜qÄK³ðï,Î()`IvòÅX7>¿6c.3¥¾öT£?Æ«ÛÓ}çÓx‹Lã‚ !`SfBkû+zC–ƒÞ>å68^Ã{ pƒÈ߬>(±ßGåÅÆ`Ua ýƒ#M} šü½;/áÕB¹]ö¬Ó[|¯AüüÌ'àë¤EÂX›µ\xfÐH› oÐÉiMÌoM6Ó9N¤3¸W]ÓWìÑ̈àœq€EC“îP[„iŒEb´d‚v´?LaÊŒþ!ìPÐéþ䛘YE‡ "l\’cÂñ¥û† N (ö°òiÓÙB>J"€o*ŒþU…J¾‡¡ã‡Ñ±o †ÓU48ц)º=I³Ç`¢[ÙGK Ò~~#2Ð|ݤø!Úë™wÛT5¾Dûù«´b˜hÚ…GwŠ .’ŠÊö>àiuˆ²›@£1Ca³ Â70GWÿ†òšn†H‚Pƒ¥UY¤s .;)D7ŸøÊ‹”) ŸÕ‚l0è*$`-€²$¨Ä»ßT/LF>£áiN#+¨£F47 ã³Ú õ½?mLZK?HßׯA8îh?ÂCó^E)Âc2·gMD‹Â"Tˆþ'X*ÎÅþÎGZd!–b¥˜“%^ä[Ü*P´ŸßûØTÎ6ØèT'Ù˜†ó^tíoTÔÈh‘y⤠|]ž¯\hк ™“¤¢ä·Žÿ"ôcoëçE*/K×åÙÓÚð² 8)oŒõDHm<©±ÃÚ=Ì›#±ñgÿ‡kwÞ#í¬4|NÖ“ô˜|ÑãúýN?W½~¨`䆗½ÅEÁЪî6ápö14ç­SÆË¸BE$_Nd$5îîŠÉlyBáž÷‚Ö?ïSø”?'û›´CªÞé¸À_e&'è–Aåz$¤U ): ’½¼kÃÎ Ë0‡bj›d,pØØn$JŒÐYGÆj?OVdÿ·b'¡bÒ´aê¶Ò¾¼¢¬tØÞ%4äø³=*fÖ v…àn:8ËÍQÖ3º¶YÞ~Kûç“-nu1#Ã_4Äs!æ&¾·¾ð胮—èÁ ËÝæ *Çâfƒ5ÅVX¥h åa8ÔPá&ª½õ´©Úƒ $ØÇÑ ¯ÏÒÞª&yÉlwžÅô¯´ä´d,ʹËͪP0¸ÓfUê/m§êy†×žC[69µ€©šœKÏ&§Ñàx.!¸°®Ë £A™$†©‚{[T°¼ñ‚\œ»`Û.-EŽjCiÎż¨Ææ²£·:qïÈVãžKߤ[ïÈЦ€ØàÆ;äâJbõÉΊñ„:V0Í $ݵÛ9,Õ~ySê*ãßK|MœË"؆Bׄö(Ç¡…oÞ!NˆúvÕȹŸîâëp8GOJ¯:…½€;0¨6ên‰ë/Ðd";!…ÎkîP×a•Äaœ¬ÙÖ&Â[cÛ­†n%€çYO¶Ÿ»¿}ÝJ¡ 7w‚Œ¤ã›ª«nÿÎó¾Tø!í ?"€ç&oòo(ÕWÛ\¸¨ÉIþÝ™=t6׊±ÉÑ®ÜU#×Ä¥“_€!G¡šˆ"}ø6y#£ÞS¥V©—ÎÌdG2/&"å×mõaââ´yY/üÕÁ|¸³âå*ˆé«ºtW«…£êkÉT(þjŠ_S=㢰˜“½¾îŽùR±SÝŠY+@ÜŠœÂâ,”Lo#€DWÉ”áÏMuM~IÜp2eÌ2LÓa3vß%ZiCŽ<–5›¼ R`nwº‹Ç˜-ûò‚tN2¦¥žáíZo:“æÙõCz…Ó{;óJGà ¶w8›%ìô¨ü>g³ÂAûYߤ4^Õ¢‡¥Ð}+ýÈQXÂËÖÌC¿W11º;ÕNjêöãþŒµ÷s¼ ÙbaxI`îæG#²ð7µ³OŽþ þ oîendstream endobj 273 0 obj 4519 endobj 277 0 obj <> stream xœí\YsE~Wð#¼0³aµ»îª6b9ͱf ˆ #Ù’Ã:lË2øßofÖ•Õ]=3²döe!FÕÕYWž_fÍËýqû#þ›þt¾wÿ{·rµ7î ÿì½ÜÔa?ýïè|ÿ“Cè$$´ a bÿðé^|[ì;¹o½àááùÞ/+½6+»6¿~ o(ѼaÃ0zxéð:~º>Pƒs!ˆÕƒµBð:¬þ±–«­Ä µqruXû|[•ö«ï¡U ëp¤ÕO¤ ƒðz&ôÙZ¹Á»`W?®…€VoØÓ‡0̧3Ú8âgÐªÝ „^}…­>ûÏç‚ýa.#t2ÂËÕ0vñ0’2i/¼ ¼bÂêÑúÀÀ»NøÕk9Œ£y²Öƒ’Ðè) {©ìê;|]Ji-ëxXi¦é]š›SB:OA{~ °Y@Wï¨qp"„x_a¢ŽÛ¯Vßà8ã(Äê[üó~üºÂÏkü¸Àgøñ?î•ÞÏñÏ'øñ?þXHÜroW—¥Ï«Úx\ïÕÆç¥ñIm|[߬=n†p«Ç¥í¬v¼·vxØ£Z•Ç—õñyi<':NÓ0©í¢v|ͧ¦FØó¿ÃÎÊquUž½®/<î5^—Æ«Úøë:·âùË;‚ô|»wø·ÙA|[Ðü´õ ´wØŸ¦ '‚ºÛéÞÿx‡³“6ƒWÁïH;˜ÂOn­bï‰Ò0CÀÅ&E]ÐÐÈ´ÆÐ„ÒãRÕ“Ö ¢þ"vÒ¾*/x8? _@àväçÇñ«Ó€à-[ÚÖ¹RøŸƒˆY|¢èœìñ[wJç +*i ð—A®V:Hâjmm‰ZÒÏÖD  Wä”Zƹhw‘^ƒ?¯ëÔæKBÕg„‹ÿ 6Î$•Î/a#Š©°0e•g óE½oJ7=*>òYžqù‚`Óå@ A$œ…wqê¥Ç5Ÿt–к®ýbL¡€!ЍÛq×Hø°ÑÀ8§|Í… S­Šn-‰¶€fú“©ÊÓ¢‰ˆ4@Äv—ŒÎk˜ y…¬j,®½Î.ºnyVÞ¿¨ïŸDCx CŒÜ?@Y7 +´r<ƒ§¸f†A&ªÈé§í&âtáù°c9ÔZÒºÊÑUªOQöq|G¢†TÀ¬~ïpFbÛÜŽš[ᄚ#OLî[ÎÏï4s‰s:*Ü‹Ä7pRŒ­‡ôZÏ ?؉:Z4o?ãŸ?ü•æm'³„æmÁ,eó†ºÞš÷b’6êx«ÑXá¦úÛéx­#cÝ™ŽQœag<ì®b;_“*©ò4`¤e0ÑiÔ(̃”s—_FITèq^÷ô0›veï'q¦Æš¬ ´Ågf&íØû-#I;Èý\Úó8WHŽ4Ǽ!âÍûÕQ6ˮӞ/x· xw\“¾ƒª½È ä@‡'h­³(é 9a™Úa9? :Íü òq‚kÛ|F2,¼¦ÍqŒ4ER “ÞVR‚µÅ}TXårݬ!}õÎ6üŠ;n´'ž¹!UÙãæ‚¬^}çMG׳3ÆíЫ°•O 3ð¾Êˆ§>QèÇqrÚ2.,Ê¿ðÛ®ö3¤Yù aÓcí2³ás'ûþL+’qr-+§Ý<å3 Þ2íÆÆqtY4K¾Ø«È¸‚d›ù–ûH0ˆPŽ"ùThÏj™ßFlKr$cÕúÆQî=8)¢ej{Ÿñ8ÿf¾S®Žxš…,­‹*g:­²fZ°ûçzÒÚæ{iš°Ë–‹Ð´ì†»™ÇÇ`ì‹k> †]4xŒÄ§sV•Hfd0:4Y¢1à«î:æ¬=³A+Óx€¸öEVû¢¹Âóœ>­ˆm;“ؤa3iH{hŒIÜ ;­‹ßý¸Ý£¸é‰u*Kn®  • Ù'SÁ‘½¨j“WǺ:sÉNGáøï ¿~ÔÁ§}ö?±OK’õ~^Ù!òz\òT}3ÞâJŠñ{ÝäÈ*­:º·ç®ÂÈ|ÝŽ7Ÿ9=Ôl]‰$7Í òr˜)f÷ŸÐhõøÍ€80h¨Y=ÊÜ"çã!³2Ybn?’ã𢻕™³kW~æ6aÂã,xVв8ô¶9xt(ÔT0ÎS¼ik¼ù$Î9÷C::ÃqÌÑ=mdízƾÁHà?±$#Õ…!¶ÙjÒ8QËÒ™ï ¯WóyžV{P`%\ô\íRä¯Õ֨󾎣ãü]{Uz\AFŽdôƒtá,E÷bÙwˆówå? Ò„1k #Ã1oéaq/§>‚ÈpNýyF(‚\ãöµ<ª­ Ç@L9VW^ ÜÐú-(SŒ}*Ç^2ìÉT7F¡Ñ•[X·áÇ‚¬°‘ÚuUÐ=gç¢O—Àë¸Ahuã üz¶À d­ç€ƒÃ)7š)Õý}ÝåJJ*øÃ"·§ÖÈŸàLL}®«‚?Îß Ç-°üVŒ~ðz¢ÃNlJ–ˆ1š¸1ìõñ(ÁÈÊ‚€HpZxš µV'îO–~¨­ÇH6æ±n“³#`›}W[}sì§Â §8€—GÑçV ÑìYÄ+8¸ðb‚ᬃ·S¬õíN§Þì$4G&´‹˜AGâÄ[¶‹°%¦ÝÆøÐ…–6Ž-¦ãûÀ‚œ¼=gà˜çÃ’Çõgbáæ 9¾“@sïç y„¤Œ¹Ää?JÜ’ÿXæ7e‘Ql÷Óѱ¬kH nêýM@È&d)($ß  n‹Þ™ÉBv:eæàUžg[úꦜIŒp¿XeçMõB[à,ö'Û”9Z4ËÌÕQkI·¶çßÒqj*g íª$zÌ™w•À§<þ„ü|ÛM¸à{os ‘íýàlÉ.0t\P™`pïc½ ü£Q)Žó\Ë X0Bè"K°W’II!"l2žnHKi¹¸·Ó/ª:nNHh º¬eÒxÖxJp ÔŽO-:ÆÀã–2⦫´‘º»‰Ó€»á©™ðøK Ã}¼&ÈÞX}OîÃÎ!­ImÖ‡8´Ìzª¼ã½`Ö’ªsmzòõ Z4AR­#x¬À¸ ¹a u¡$Ž­Æäì{qx¿4Á/Ó~ËzUªä™ú®Ý_Tåß<ï°N4–)¼Žól}ð?ªk1©oIº³ße}z?!g±úÊ>†Óq §vç(]Õ|z)ƒn:¸ê«Íó篖µì*ï L‚ü ¬Š¦Ž ZCûh[T³²œžRË쓞‰lj›.óP§ï@¥²¬YvŸŒ^5QÊ@L²“tWœx«Rû.,7…sìÃ"ø8cgV¡!ÍnÏ^ÉKßäÚ‘¶`r us}@jî%T ÍE.Æ‚aúF¸2"ã?v\l"$Õ³µê{Öó•Š6„ Ͷ•BÛd"NgÑQdY0V¡Ôõè'GÓ¤(’tël1€Àl Cû4C1*$ÐìçND4‚p‰¡(õ<©ÚÓ’Õ«€‹.»!gE ž-»”5ÏF»è½Îhžó×AðÈ@m™£Y+’X\N”šÛð¬ÌœÏá¶0òypÔ*•*³S…‹™–ÒvYk¦ß?‚aœ ³v› ²~êvË¢pIÕÙêdhhÉ~©, žO²Z8®A8»;ëVææSl)6ÉÐ

æT%¤2lÏåjµ@½`ãXeÀå/3*ˆÑö+égÂ&u,½dás{îq,ÔÁ*…Ó‚MGR¸Æ<6þúTѰm/¤)9I6?a¿7ZÊ M¢¤\Žzj4\2¥í3è`…A t¡ ˜5ƱÐ6ÏÙ-ˆâˆ©&ݯ–'.«~)c-nµI¬ë—Ø(ÌýSò¨RQÓìrÕr‰ÕMi·ª9ª]®Öˆÿý_=êFô5<Þùfm%þ{“’oè`}Nn<ê44Yú<àÍnèÞݵWVƒ²ùN”Ê"‹A¾Øäÿ´ÄB²^ójã;AȳÙÌ©5­uƒØr+Bßpc–!XŒu½¤mßXñ뎷p'"K]+êÛJ« ]ºãJeÌÓhÛR )+Í®?À +Ùú¾Bµ1`ž¿98fg»QÖ¦l.NÐsLjñô|´£†_ß„ⱄx9t' Bß scÉÕc:ak­g¹<Bˆ·G Ó÷êãç›ÓàE5,ÍŒŽ³Öò³ž•OêvÞãfÛп;êÙ¶B(yCjœ\÷ËÈ7¸‹ÁªTƒ2"ét˜•|Ô®'KNƒ n‘›Ï‰‚®ÿwVÍ©¢ˆ£ Ïv²yõfè¢Í«m;ýˆÁÓò¤Z—¶<± uÀèj52,ýž~Âá°ÜfðPæ në·õ3ÏÛJùÕÓœVä&„ILd ¯9ª®¢‘ó¦:Râ=EZ³ öòj;Þ1´—S/©q9{Ëe–³z›±Tä}×òÝå/²äRÈPS‰ÜAâ7Ä×Eä·\!)£E×Or+–’¯¨¦×):ÚöZbÅù¦·XëµGÏo"ä™Þãé5˜„¬ß  û™Jð 9Å8Š›/Á¸% „ŒÛéšùc ÞìFlÍ¥€„•Ëf½ieWL†ôÖsl­Ù‚ŽÍ2ŒKßšvÒÄÈ’&^^gr‡‘ü&yž[ï>xa˳†ÃîPÑ ÕD”ÒÎ0<àe¹uÂ…êq‹Fd<ü>hP︪n d•ŽNw  –mc9NïþöASýu±AÇÏ5&)éò;t}h+Zp;,ýªI›'y§5³+jGÔèò ~T£ÿã:_D 1ßo‚òÿ_G‰Ð€×>à prGYÝŽ¡4ªêÑܯ!ï/.˜;D÷›,vjü­—²gHÂ辰[0Ðåç”}%ÿ¢ww‚ùpK ß‚ã0ä7aÈ‚òC!ópýW#(Õd@/ËÈÊ›n xóÞ~“ëóýÿÿAß¿endstream endobj 278 0 obj 4577 endobj 282 0 obj <> stream xœÝ\éGçó‚øFâƒgP¶]÷Dç’l„P@h½ë¬#{=IìÅ„¿ž÷ê|U]=Ç !„3[]]Ç«wüÞQýýŠM|Åðé¿×'¿°««×'lõ!üÿêäû:¬Ò.®WïžA'É¡eòÌóÕÙ7'ñm¾²beœš¸X]Ÿ|½6½ž6b²Öʵ œZç'ÁÜú íFëõ“Í)Ÿœó^¯Ï6§Ðê8“ë/á§Ô“ÒrýÑF¬?ÀNJi+Ö¿‡?ßß(xÅh—(³þÞP0’µtÈÇ0íŸp,9‰0ªÆÞðà« Ÿ¼wʯ߅Á¤ÆÁRÀê¥ ¯LBcHǸ<ë=O3xÎìúuyR¹<…åîïg¥€„R°ƒ‰9 ÖÙ%ib7:vt+i-°ßiêx*Ùd¹÷±¿Ù°Izoaš V%¥ãé­¶Sû˜¬Ç•ŠI{$ä+8 cë×ð‹y/ùú¾â…Uë°£–›õبӓ6býIx+çI×á—–ÆòõÛð“v\®·° Ř€3!#]ÂHÆM–i ήÅú&ü\¯Ÿæ¦ô†áŠŽS;‚€­”‡}›÷ø*¿\×U¶)*%½–‘Þ­Î>=9ûå×k¾‘£âzò†‰|B霙æ0_8X ?_c«Ö¦|Ì£aÈGÊ \®pÀIësøááTɯ#ëÕwÞbGÇdÖ/÷@R8yüãæ”.ž”f \C&C3$…´ÖA.Â/!ÕÒ‹ ;ßf)¢ÚI+À7  ÎY‰'[6QŸÓíÀs`Í÷ª„|TÄæ+|®'R¾ g)¼„sr{‡Kt–]‡,‰äwik¸¡ºµ²ŸõdƧ—q°Ñ4Œ&PƒLPFx³A¾@ʕ٠<Ä—^U‚ÿmv ™O]¼VIå᯸ÆIÓ;ð27p޼qìo@4ËOÉm}û²¨òN$ež½ô}Y:üˆËt0“Ç]çÒù£¶+ï\ä»gL,€E¯¢Ò T©]r ÚÄ&P+.ËÞ«4 +´ÏTÃû¸žH ’þo›òf3‰´>œÇ„ÇžÊBÐ]8î£Æ¹¶5sžÐåè™·˜GØÙ©ƒÇ©•!ÖU½ÆYÌ*Ör]r~°ölæ¬ãµŸ8ÓsµÑÊÖœTyŽGH5> Ԉȳ‰¡¹©ŸÎG‚A+(°¡7õù›DÎC¢+PQp˜õy¦‰±iÛFÀû¸î‘8½(C€±y^NªIZC’ÊQy Z0šÈÌÏ«ŸÂ¤…—„$P¥•‘‹ÂŸåð*ËR- BŒˆÊ-IU}§h¥%ù‹jUU¾Á=W»Ìtl7?G5êv¸Ë¯@åÐCX…vªò8b}ܪƒ¡•ʪ{FÄiGˆ„ý¹·/PO8«SÏ“†2ì:œÆP°ÉŽ.F2Wû´ˆKµ1ss%#W>¥6 ~1®äúŸDÓÁÁËp°¤ç\¹ŸW"qýYÃPé{^»‹L6Sf 2†sÌÄö+èD#BCrÜE•㆙ ¦ 7¦[­ŽŽ…\”(xn€yôXΈVÇ)Ý ˜¤n†;ßH Ð ´u{b8…nA. Àk{ЧRè`bÈyÌÂ7x¸$OmX*ïšpî¶,îmåòB žÑÎŒ4 §¿¤Ø¨Î-[ÙÊ5 ÛMfÇ>Ù¢ÿcÁDÈ-ƒ3¶Ü›ðOB”eø÷ÿÁ5ÂÞO£‚  *ö~â:üYÿ©(4âïÔg[답ñ¼4þP/K#¼£´)4ëßm lŸ½BoJãëÚˆj%¶ŽÜ˜,ú-H/g½ôë¾€?Ýðî xžwv_€CòB(P~‹hL±^¢-èÆG.¡,äмº·'YŒÊ†õlÃø8mX"AÒ†aëlø5.Ì…ÅßË$>¸1@H.xëÇ<¤Ë¡xt9’>r2ÚîÚ§þBcFÁØ‚Ôò^-Ù¦¸Š`H$°¿S½;ò’ÂBÊäˆrXí}8ßCk’Þ èÚQ8˜mf¸ñë¯W W²IÉÇ%¦ CPxÒÖÂYïp½pºƒGsªÀª8ÛE²Ñ¦ ! ­}R£pŸbk”ä/+ m dàw.À!Íì>Ç’è÷n[ ´ßáËÍÍ´¤L€â÷"p ÷R”3ÕzJ% wâ¼÷T «,‹“‡-èr#2òÕp+‰±’0)¡ô_AQ~™˜I‹JGØó´Î2F騩.jŒÒ3÷¼“|iI㿈.½Èñ[Ð^äsai'9N”¾$š6ogɃq©±+BÂ&É5Yï5@$"Ï &"{¾NY‡ ãö$ÃU\Æ$¼çáh‹jovy3"3ÂãW-?£>Â@Ã#´E®“ JøœFÅxˆû»´SŽn!èE”J~…È$þY<•ñ òb+á¢óÈÐz”zaTqé;G›žKr1(4£ Èw#;¤C®õ©’:$LS±Ø LƒXŒÏÔ1ˆƒ¸ß= ûM9ÎE‡á|Ó Zk$RS`Òâ®6dSkô¤ wqSa?_ã?çèMăõßËncïù–ç±¢µñYiü±6¾…š(‰@Á0 @aÈÀ',†°âãŽÈõ2Œc‡±¶¥ñºt¼.mÏhd,Oø¦ ràÛCœÝΫ‡s‹ˆßÛ–âx¹ñň,”úùÀ(ñ cdú]Œþzp•m^ÕŽ-õCˆñ@ý*.A¼ÿ„ÎþŠËåhi¥ã·äèȈy—#R¿3g;‡Êbîøjt¢‘'HÐë>g[Ñ¿*¡Ž–-ðgÌpP¾È?;ÆH‡Ág!`ºX½|àØ³rXãÑËbôÙt î%ïOÌ2‰"¤Š”)Þ.¾§¸×æJ[|ƒÀÏjãÐ_"pÙh1‘´diì$M“™ 0(?pÌÍ ² L>¸A‚Rʰ//[°1Ç&æJT¢ Å‹„E*ûÓ]&£:õÕ#мi1eZ:‰¨UøG‚ ÃÌ$âb <•opuBîvì’«å&DU÷—¹”ÊL]b d0•…/ x1Äú©Ö„¾_U(‹O¼¿#1Úo³&]ÖÖñ¦)î–ììÒWÿMTp5×1^;²æÙLD,õ@ɾj4å ¥šLÉ\6ªkÙèÈ– ]®X^ÉC‰Œšœæ AmºÉj{¢8’4ÿƒÑÖ~ 3‰à#E‡bì›(ª%‹~­ºÏÀ‡Ró@>¯ãÁIO” mÈ®Fnhð†ä±gí(8{9ˆqµ›a;jžc¾M”¥‚æºBü<¥Ø ؾeþÓYKc¡Uvöµè”a§×Óî?T±±´õ—›ˆ€èïwH"ë¤pµü”ã"+R¯QãKAÇ„äIuÊñBóY Äj3Rmd%ä³T1Ü rZm–IU3ËÁöœph#$öA±1Ô6÷¢‰SƤ͞[þÎû8vì¤}"P;‹†–ŒyŽ‘8é;ôÒ‰€zt:ƒúñAÒ÷W˜ÇtH´Zi¼GpÌ@ñ»’ˆµE€夰¡•FsiBŠi¼©Ñ…;«D  ßŸoJ´1›ŒWÑäsLÕz —JКRÏDy~Ï‚Z·Vt`1ÄdB)Iƒ}^%¥ésX ûÌÔ¤ð"Az7ù1l3‹ü­xL!ßG…ÏN !c(VMžT^5©G*I5TvOʽÜ“_vÌ^(# {…ek9g¯På@0y¬¶a ‹ó3Ì.&aQãÄ=)ü5s~}÷×éG‚Á þ=+ò'v$ÕÖg»­#…çD©T™?‘¦¯‚R¦uÏîi2­¨”µèg> Ò€—Í8‚ÆÅ´má¸ÂLÄ"Oñ Šf‹Ìì›æ5L ÙÖcag“{™”/«À9ʘy´­ÊÞWUV{ïÎ÷Æœ âq¤£œÕ¨æ¼¬"å8û«:R‚õi”y]ó¬¦-"¿Ì–Jåäª)V®ŒŽÅx‚[ †M`¡òðæLU±’kžól+ÊíÑ·ÙÂñ’ÅÈc"@ «FèzÛ4g·×]‹”/ż¸ß»™w¡zÚ¾Fr÷ÜmÈ®æ°t’ZÆeñ&·ˆ"ÐÞ q &xÖ$d‰ÚzG†¤huužÙ¡P1|+ô@.--á¤H(ÀNônª‘JÂ|.@™dáÊ"ìMX† 7t¸£V51Ê€Áiæý8$0¼,”Ô&øY÷†ò½Cm»ûhÛ3Üu93S©OÝ¢«sÌ®‰Þ#’”bN€c D½¢¤Ô3Çý9šÇ˜ÝP“³ ˜«äÝ%Á’B°ât׸hí ÊD[~6¹£†3áX¡Áã3Tfº²ÔëH£‰>' -™m,"ÊiŠ|¼9È/¢ý|Góxþ¶ÀM}Ž (H9H?†dV'o K«q½‚.ÜPMx«%“ù—Nµ|4¯ÆÍák …5%–Rhw4*Âê"[)à„n}ˆEýŸnµî’€3÷³ JçK£—‘ ¡’¶(Ýž©Öø<²iœ/G0÷Ïv ö´ÃE€T¡~ý)Liíîx`¥ô„'i¸y©@Ðjåt¯ ¸±ˆ>)+!_jú,A'`àÌéŸmÐ1įE/Hahc‚3ݼèô&j€e—[‰5¦ŽFÿxb@ãËŒTYº\CÈýj3ÇBĨ”×*B:´Úþ½Êtã‰F fM¿ÀWœSKq†9Ð{¹I@>ã’#f;n×”0íO±dArÚ⪛Æ/C˜Ž|«à6Ÿ9=J&›’b«­M ëTrñ±!£¡¨Ï¾­ñÅáK5´xý™Ç¤áE€„µDÊuñXav^‚ìB³C—¨K°FË ¨”÷„¥¹6“HD€ífðy ú%‰´¿–é÷Æ>“î;$öy´zÖwäøh[Õ}® Àš>öseâ5Oîºz`LÂ!‹~E€#4Ð~]ÉÇ0<Âr6‚æG§FæùÙÜï8"ªÄX0(G&ÞÊ’»oKc´d×méŒãîöÅDT0)™g´ÐUJHuO1p½:füà«<1«Ú!¹|Öû.«y'SûÍ&tº †im—¾îäxåÁ?8;ùüäû•Œ…ÑlÛÅ9€XέÀÄá ‹ë“wŸœ<~òÙêÍ7ÏNÿeÅO„ÿ¼ûç÷à?OÞ_ýääƒ'«Ï?~Ù‰`úø%Ç’˜çŸ¿lÂ’ñƒŽ`å~kûQarØ÷¯¡“ ©kZš¢L ÂÞzË{ø-{}Ì~1…fÜ®Oxp >Τ‚ÚÍw3L,OxȯIzè¿zSzˆ@®l’€@ x‰öÜ¿ D"9ÊÅHÈ’†1­hd·ÕÝK%cÄjæ$©E~â½e?x訔4ýÎHãÁµg¾+¢Ó¹¾žzvå¥`)òKê¶F¯¢ºe\µþ®Øk÷Ä箎óácPÝÐ]JÖdg·*Õý,=ŠßGýÀ»´,®Ïbª8æ|þåÄ£>gc4Ù1]íBÈy¾Å=ŠygSarÎ0Ô:g•ñ:ï,_®—”òœí·~ÍíRÜtÏDiêÌÌK;:÷’©ûëä›67XRl`÷w00ààÌEXpLO +LŒØÕšå£ Ø^.$ôw Æ0ü°Âåä5ÿ7o8küùÉÚêRendstream endobj 283 0 obj 5107 endobj 287 0 obj <> stream xœÕ\YoeÅ~·ø–òÀ½h|è}yQ€°‹ÆŒEÆcwõŒÆ>·Owuu-_-}ÿã“RÚŠÕyóøT*·úžrÓÚ•Õ&øD? ¯ç‰>]K;9ëÍêÇ5çðÔiòé·°Ì'Ýܸâ§ðTÙ‰sµúŸ:ÏaßÓ‚ãƒ4wbõ¬„C¬$uZÀ ˜ ^^Ñ~uw}¦á]ËÝꇵ˜Ó@÷Çk5ICa>)€—Ò¬þ‰¯ !Œ!Ï뜉<˜7GhJKËã)(GO˜óªÓ3É&˽§ñLf_}Ž?Ű${•a+«ŸWøóþx‚?~ÇÏñÇ2ú!þy…?Þàÿ®Ï²Ü™ðJsS‹ÊhxìWÑ@‘÷ruY†^Ô¡OËÃûÍûéá³úð9}=ýö¼~übôÎÏëü4² øCY¦ôä¤w§g f  <kGÏCOÞ0‘åüó5œw^_ Èj ä“y¿Ê (€³}My8(ͤ•F¾å§ ì‘fcœ5d:dƒ°“`nõr­Õdpaô#km8µÁÜp¢yqý e_À'*pNêpÏP°´†9­VJ< X©`W¿ç5žTɾ^ã¡r'‘±ù¤RºIȸÙØý¸š‚O.æ„T &e·Ö(úëUód ÛÖZÚÀQ倣.¼øÎ(‚ÂU¢G Îs(&Û‘‘ -Ãþ8Yö *½ÍË«5ša-¬‹Ò Á(éóéFá.•š\â™×*¨EZ‰Ø‹/ŠÂƒê£‹Œ3Tÿ-'Ó=‹†N+¯l¹ yQ‡Ç}jPº†Ž|xÈ¡aId(MS/ÞD 6¬•ö§g°kB6}‰ÆWi­[–gq 8ɇ‘‘Âû²ô{†:´à) 3¡I^Ô$] Êxªwù¥Äà ùdN.ž6ž*ÈÒ> çgŸ$|¬ÐQ®a!Ôó¬™(‹_W?@lü=‹#­ˆ¯HIxíOH˜Äøhß`4ÃЪØHü‘®¹Z#½ùˆài|5 |qéUTÞD-$•ŸÈ3ÆÑ<$ÑŠ‚ÍepüÕoQ]øEy•áWæñ÷,bªèJîEeº0ñÏ˼fúBÑbä¦LopØ]+܉4Îdkbóf`…ÏÐä[ò^G?à#~Á#b–5GŠK|Qm°ó©ù®b£»õ­×À7ïÀ8–™é!ßTÿk‘*Ì´‚JX”­ŒæcëZd'TÔhµ ¿&…?&©y>_c{‚s$fî!¡xJëŽ`w“ÿí&¿„y¾.Ààþùí;Å<ËЫ:ôMyøª>¼)ŸÖ‡÷ËÃJ×ËúqBF@èj„¨.GÄ?.ׇWåá“ »S>#€Ì¡‡ãv ¤Y„ìL’WІ¥Ï÷iò]€4xV þ;ƒq`{¤»@bŸ SÄ>µ¾©’€ a,†cOŠ3ÜéѤÎFý¡>`ਠG %‚‹ôr*±¤ZvqÔ«¦…Žñªi‘ÆÃKÚ™<Ì”þ“"^ò„ðï¥ßK?•A»lÿB•Ÿ:F› ÀݨMÂ2ð)¾GaøþkÓ\¤Ïe‡¾!C“ì€ö²#CùÆÃËNštS}& }K!YBpÂñÈÓˆ\³ÊT×5ôlxBÎŒÕs¨„8Â9°1Ëú˜‡Â!EÛ4ã"óôêýˆKÁ#ìX-NDLš™6ni)D ö>¬âœž„Rk™3a„>›€î*8‚8ËÝãM )`*%=>2$¤92 y”Im€›lDºMŽªXž—j·Í§t,Á¡Ä{Œ˜|M¢øfÆ!!ôù~~6V­ê °¥h.kC£2D© K0§Ðtœ©Áqï+q‡~¸Ã]¤o°­HLÈ"p1LQàü†¨êk⣆  (ã'£²f Öb3Á“ù+&5òSÖ f°¡€Ö€-ç Z™MÆQõó‘e',|]ƒ€ŒŒHÖâ­Å\Qe"£Ú`‹d¨>€™Ñy‚¯–¯þ†ÌG£­¢OôËÑ©Y:¸úKåqð| ª5ëåLf:(…zÈtVå Û(rô+Nk11ƒ9Hª \™éeåX &M§¹ë…Èœü:¶ A"td+ä7¸Ž&~sf®²#Yç)/ÏÜØÃñ\k¢û0“SûÀå-Z {\6 9Z=䯮ÒŽâEðû:Cu"ÒGל°±“‚¾R–ü·1ŽP6˜-¥Ï¾ƒÌëì'ª”‘¬-1üÃÌV´ †Gc*dz¶Å ˜ýjƒ Æaf¡–=ƒðìËÙTŸ4?ð,Sf–j`€5¹Z–z†jOÐLÑëjYÄÀ'æL·M7„X›¢¦ÌY4)€i·s9.öýÍÚ…ô› ƒ¹Y°?‰p²`L °p`Yè[Ú‰)¡«Ä£Ýî¨.äO_´ZR‹RZX¸§ÖÄTé I–8A¥È‡Öð/¡#¬€Žêç8%È«ÒÑû'ˆ}[žgo˜b`™iš„”2Ño7. „zK")êò¢]K¦?%R•ö¡´²³ên±ÕŽ!¶QËXNɈåªèÍÉñ¡å¾J c0Ç&Ë}2\"Du K¯Ì ­/9Q½„(TLu ÷$·ªÃHEÒîƒFôpÌj„cùX;Ïœ­yÜX+ÈCkM0E›o‚CĨ–D¤ƒû `ÑÅB¡›RY •§õ’ëVÀh]pA-f‰Yr²áVM0€PX`u:—Ýoš@ø*-·…2\B–,TfZw½M7ÇÃ-=†7%°«¿âûy²È~ïöC—¤²ÅÉBîKBd$ÏÄ*æ3n޾ËYÎ|Axʸìò0ñÖÔY‚õY“ÖhYŠ¥nâá ËÞ$î°Å¼ìU¾h¼dojï7ÖI¨¬zʃúV(¡’ Œ£ȥͲ‘0¦W’èöæ;+—!5fÌç2Ûpºà (wP3Ì,R’Y¬Káf$!ÌÞ3ÿ´4 ”±¥"xD1†„·›Ä­¯}—2’”z'8büÉ;$ûÓ”ïºÞaA¦Õ,©9K [²¥ÿY§²ÐN)áß˧h‹h¥å÷Í9[R yBgë^–ªI]–o^—ªIÍ'/óXÅ·QqU¾&D4µ,8Èw™È&¥$’Éޒ¦U?}TA(tlp¼©û Ï2-”w²Éåpåƒ9&­KÅ»µ‚k&$•u“Va/ÚkƧ5m1  ˜Õ#è€ L!Ðz›¹è’'z-–SÄb5a­o§F¨mÍD´a¦frb¬ÍÐÁ_î[aæeöš6Š™fÙ&'>^öPÀ¦íAX9É9” =õ½Š¹¹ãÜ×÷‚Q‰ÝQÜBzßHo‰ÇámÔgCóÏΞÛÛEhšé´â@Æ×K¤ÊbzðÖt-Æ‘,Ä” Ž`wÆcÜÿ2ùw6eÙ`G2?Þ Ý&ß G»äíîí¢„çypà Ò9kf#o22)ûm1íöh,YÜm% ƒÇÍmWgjnT.Ã!l{{o”¯(gҀ歽0Êâµ&ôÿÞÛÝrYüåM<* ¸ZpLÓÂÒ÷­Ôf–«öy¾€UúßrÑÝÜF éè= \ÄÄÃØBÐ"β*å¶[šØäu \!>àΠgßóGUñ‘UnC£š¸ßšà.fÛæÇ³9.}—LÖô«#–ä6t?sÆ·T&¤ØT™(ì]jEÞSíÞ[÷þ–%4Ü|Uâ¬oðÇÝ2ø—ÞîôÁÌPOŽLÛúð1 9¦Z Sf!ΖV½mmwo§ÃnK(Õ?\ ¥è±³;¨²sërZW(;Å"é™1¹vhDm‹VÊ© FФ›„vˆRk)ÂmèQ(rhR ÜÜë£Ür¦i; EÔ\84,Â]¯Ð0:\ÃCŠêyа€‚yî3“)c6s'Òî)$ò«å"ÖmXø½^WÒZëK2Fù|¸.')T S—ìc¦¾)¿õ8N‚1)0•Zé4k ±X¸†Õ„X;Á; ¤ Ö\aÉqœ-)eCç$Ú3èDáêˆÈ-K Ú"ÃBá4öª[ˆhH©¶Á“‹ ¤k<@¬¾b&„¹M rœøw†\¿¼nh5ZF$:ÊèžÊtTôs ]‰´ó * à­´âHpݲԣöV0Ø< ?Öf=«8'VåîÅSR#„žæº°M…Âu“"HØ ÓË´œ•+‚3T/bB…&¡cL?Ñ̤bnC\ºæ³¥©æ¦GŒÐîâÄõ¹|gPºmzJ”“¨ì½RÕËÝbv!†lî&ly»6F=À»,³ûsD-sÉŠùp͈J±~[ÈêË!±8Å}éÔWµSŸ¨ Ðó–;ßÒŽÛ¤CΪÍ} 9Æzg1ÝRwê^‰\rt±2F&Û,Óב*¬S½ªò»^6™šåø²÷™)£Ö7À&ù©=c$o.Lˆ…ÛLqLL’x{%ùˆ»íN´Ëp&ß×8"¹V{CoE6´^àÐ(lo¹hLÒÌwÇäÛÀwçt_j)Iéukˆ7\XFºKkà [}HÁ¾Zn.Ê®—v$ÍÓ˜Ws±Eâ(0ü1›•,ó°T¹é³;K`X\íŠAŒ'W"Gu÷`Û’S¢'¥¡SÆ.ÁÙP‹jîªä>´€Û1 ÙŠg¨Õ»×Y•ŸÛÀׄÎäƒk±yÖ]Œí½Ú-Ú¼­¹$—m Ö÷|«FmÓvh ÷ô"6q.£úWj‚T’rvØfڡվݵªv»&·ÙzÚ;0îIÒwÔ‹ÔuÞˆ‚Ü:9)÷©*Wò“|B•HÀÍï\/§N‡¸.7…í¨ &•ždW^#=DgÁI£µ°D´ˆBï»èÚ–ú@`V{N÷Ìâ·/ð[ùä¦ ¡‘LDÂg’¿žAÄÚv|¨æxÖw5ôf>:MúCÇVÒw] Å47¦‘÷&ìJ—’¶£$’ß·À ¨_ D¾•þ‘ᓚoæI¦]ç.Ñz7¬­ Ö–í—X?o÷õàçÛy´M:¤Ó°¡oi±aŠgÖ<>ËÌ=š­K0yXzù0$$w‰Hh×¼Vév¤ íÙ—À3ØšpÍaè!õC!qÔv¹¡= ¤‰œG¡¶¨¥ÛÿnLs«QîpE!‘9G9B Ãæ›.âm*¥xöÎ̲VÇA¿åo@X‹®N†oò88Yóö 2)=Ö:‚]%"åu°ç½Ämäu°B‹ù­’ÚaLe-6óÇfÌÜ÷?öTÁî‘Ä& ¤j ŠÉhµ/. í–ã$ið;Ó\¥ëmôdg†Å³t't­"ߙƙb×´!¦®½måNn0÷·`™Ó5ÖÜ£"c–íPQNíѦ¿ pK‚»ƒ7´º+>õî!·Ñ…­¿Ö™9“™Œî=6Xäíɲ_ØÒ™"&‡};6§Ü-5ãÚSäam)µeØ8r=ª·>xëÝ$Eо99ÿ cZ-ª‡Bû=»0-?ü­<$ýÌO‡ûǸš‡K¶–]”Îæ§£ejÑübsÃòƒÁÀáŒŲÿ­Õú÷™‚!r %T2#én"ÍU„ø+F†mY”HgÛ~IÏl@9*¹¹çš5üãüä_ðïÿÜ©àIendstream endobj 288 0 obj 4528 endobj 292 0 obj <> stream xœå[YsG~Wð#ôæî ¦©ûxذñ}± b7Øá„‘ýï7³Î¬îê‘„û°A0ÌTWegeåñefñz—M|—áŸôïÓ“{íîñùÛýþï¼ÞáaÂnúçéÉî{0Ir™<ó|wïÙN\Íw­Ø5NM\ìîì<̨‡i“µV*üØXç'ÁÜðõ(aÜh=|7nøäœ÷zØ70ê8“Ã#ø*õ¤´¾ÅðNRJ[1|?¿,1ÚåÊ a…JÖR’÷ൖœD ªq6Þ/ƒo«Âã4Fø­Äï–‰'el¿Nü³¼ð÷Ëv“éœÚeôÄ@¿ÿ‡*.MÏŽ*‘¿Êà»f+ùëË`š’­/}£ÒÝ­3ÉŸ5›Í_/ê22÷°9³üõ¼~}[—í/F ]² çþ:–án”Cƒ ºšŒÊß(DyÜÊš ǃ^Åu—É9c¶ï€1–ð¦uû£&¯îùàc¤#਋ĸ…kÉìîpCÓ7ŠWùÝhŒ,žnx¬ÑƒÈøC²µ­YF¨ôD¯úûÌK*3Ç19P Fõ)z î-Šœ0zìJ%íWÊIq÷_cÏY¥—£ÇK¤©uÞfq¥ÒBíw°3Ìšƒ»ÐšÌ!ñ‰ˆ¦§•ÈÓyÉZ°š“#tb@@eú íUfû­Æ´JŒî 0Â2B‡Àºƒ…®Ì€ NÚn%<ª9/Ç-¾IÐEt!ê‘aTgp ,N€÷áVá½¶@Êt¶Š3ê9|8ÛH¡4§›ÙGà1F„@`dà¶ÁµQ@Í‹Î\3 2K 9Ä͘€u«ÚÅAãm¶ë#Ь“ÚhžL+)r¦ú›…3bür_” Z¦MDIÐc†@’dÅ™Qçã~[ VÕš\ò¯J;ò¼æåtšP¾í62äU„fò4Ê[:¼†ä& ’D¤Ò Ó÷Ãé.ñµ¨FŒ›U›-ê³¼¼N$o-Ä_QÎÓX¦Ò>îòü´|£æ”“—2ÛG˜ã$õ±ŸáfÀ“ ­0´ß+Eûûa˜õûêz2¨šG$ c6¨ƒÆ( æRA›«˜Óü³–~¨_ ãO¾çOY×{P2V¾"¤U(ÿKyÐBtÀy°®‘Ç#»@Ù,¡ñ›!RL«À‹Ø€ieÄBÿŸ6ø°‹kÓàË^¦P_t@ðõ =%)Ey\!þIÃwyo1:ja=yÜàáœ+\”ÇDg4 Èx¥f39éÝ,uã£Ø *vk€8: ˆy¶_ÄJb0Ô¾ŸGí¶ÙðB‡8¾h.NQgš`’Ò>„.âO+˜Ù2dÀ„öA<÷vOE<ÇqÜã ¬6bá(aC°¿šWÁüI\ÊÜ_µ ¬8_|FÑۀ幨 _P¢´d‹?bn¨IÙæJx$¡Ï 5ùÁÑbdñ¨´°v?Ê­þ%ΡšÁ•lK5Y-@ÊøYƒ,Þ-áÄ<7ØŠÑïRÿS3€@6ô¼*äY€]ÿ¾Ž3nÖ²‡¥WË;`gaf¡~‰+àŽ¾n~(ÈFwã€3±¢³¤(„ð±»óBtˆ–cõº³Ÿ÷Û5.VÔ¤ à¢ApÜ,UÅmc-~é@¶ /uÈRêmO^ð Š o4šgõ)Zù²Q°ž d%ÕÆy¢J¢±νÔ®f¥Ëœ[÷[¦5[ G z¨»I:)JÎXÏ ÁmoÓgÌÇô‹ëÇc•ö|ý ´BnŽ}ƒ”+Á¶MA:7Q)˜Tª"Ô³Öz¶$•ZÚD¹ U¥;½Zz±¸Ö¥Ð[ûþü®¤!Aøû¸qýƒd™'Š R§2()漺Wþ“^¼Âê{M¸ö %fûÉÅA|ÑàM%(¹|Tò¯zPþ¨“»„œFQr°p¾Öy\Èüü¿LªjqY§¥i9,W²•Š(ÿ3ÜžDé}Tl«jÎY4…+ç羉œ:¹gÐ++wQí*i+V…DŸÅ¯Ô»EwoŒ2:p–2ðgíÙ†B+è„á,èu˜y,¢¤ë…ßÖßaô“ÊDPWP—e+óyuVΓÁߨÎBŠì’]qɹ×smÔØI ß¿>4k$´ !jKÝÔÁ{¾jEçÅ‘æòKÜ}lßÂÉkOñÔüº_ëß–ûqGÑ/k¯²uJà?áÇÂY¾ÿhí÷æŲvÜ”–{NVpV¡S“.€\rm¥½Rѯ!W0{Ųø˜†2V˜ù dä[ ©|ñ-Õ” c׳<Åùzïo›å…J†ôYú†ù2 I–k/KÅ~*â >9•}VKlB@(©e™û ßX~Qm½, 6éöBDæ÷~ÕŽo:3 ' ^¢Þ¡ä´ÛFðÇzÿرpáˆY¦ÂX ¢ ¤ìÅViC8W &&Q"öíZGÔÌtKc]r?¸mâÑo‡6šÉ›ß¨ä¡MΰS ÄLS£#ÅtØ àu¶l¥Bœž¾Ku1Lå<Õÿ•«6e¤J‡Orq·ii,‹Š’ÛyS#Õ´€Á;Ë»=íý׬Ñ=_Ò0öàÅa!&»ó~ -;ã­Ï]ßȃµ/Kjõþça¹ÿ/O~ú¸™@†ü¨h³/Hê>eÐdr;š5ñúýv&ñâ!FS_ü¦w$o±Õ*»™±ž4l^Ml®ú5 ë(5zC’vr/´ohï4Ûîü¢9Î{·QŠ“¤®õ l®…ÌÌrqH]–zµÿtND¿¤}¸0pÝ»ˆØ6jÖpZ^ÎŒ™'·ï8Û»îÉs*G/É/òVœ9ïÆ`µ¿¹ ø—æƒÓü¹ø•ÏËØUœ&ºÆ´‚.½ õKóïÉ+²Ó¤Ž”’„,„V–?¹7Uÿ§µô£¦ëËûŽÙªf°-;eyë÷_2’½à÷¢\cõÞ“ÿvÔ«)ôðìZŽÐÇFÆâÿ.¼"4zp-+¿]h´re-[ùʵ|ûì#"§¯övþþ ²Ä>ƒendstream endobj 293 0 obj 3427 endobj 297 0 obj <> stream xœí\YoÇ~ü#øÍæ¤ïã%@l'Nlç²èFâšTdC)K¦å×§ªúªžéÙ]Š’$„`k5ÛÓGõWwÕþp"fy"ðOþûâùƒ_}éOž¼z N>…ÿž<øá¤'ù¯‹ç'Á ©àÉE”'gÿ|Þ–'^¸`føòìùƒ¿Ovg'±³ßœ}ohÙ½áâ,¼tv ?ÞêÙûåôûœc &N¿Ù©é/»S9c½šÎژߦ§Ú„éKx*#Lë'«ÍðRqV^/}²Ó~>ºéo;)ái°ìÛ?Á2¯æÆ?§ÆÏRšéø4D Ëàøõ^p<ìEÀ +ƒš~+á+i› ¦‚´†WlœíN-¼ëe˜¾Ú©Y ûþhgf­`(̧ÐR»éÏøºRÊ96ð¬Í™·óÒöØžòÊËt Êð[8Í×pªÅìeŒé6ìN§Á‹K¶stB•;ûãNÏÎg§ëÝ©ò@MXý2-g¢¾‡zïõôOøšžùé |tnÇM?Âë!88ÇwíÇ8“˜-Ðæ§5³w*Lçp¯ÏÊd7ÃÁ8äª}s‰ËÄÙè8]5LÀ.íô·âœw†|Lc”60ÄZía{§p³vú€/YFÖ ±¿Âeíl¥ÅðÜÞÃw®ì6eø4ÿBÈ(¥œ•`¯ðú¬…Ãg*y­Û·ìœOp“)?=E¬À÷’Mþ†Mþz‡\û¡­½ÜÈ´‰Šhsà¶øe«?î ZÀ*6–«ÝXàÿ})À™Ry«sÈ~WIsØs`dï<š&õô9± À/_àõ¥%•Ûv™rN‰X€‚óÛØ,\¹@t¸ißœÂ"Îð¼@’8;à àa‹˜§c7ÈŽ.N¡RBeb £–Ä~šnD9¸Ø«^°0Ë/h Þ ç ÅÁ»º¨1ô Îé-ÝFCÎhΰ¢4 ³Dim ©Iâ|½#1¢] Žb›a̸¦1ž—ÑíGsî‡x ‰ÐÝ`•‹ú´}ÿ‚¯T‘ ¸c[¨>Ó½@aǹ&êÀ‚<ˆ;WÏÀô¢ôN 4Ý=û*ܬ j9D./å×M\á˜ocHç~ÒÃ÷q¦8{Cm{Žƒ•‚á> B P“ÊøO= `ô TÔÆZ»|%ïÁ‰óvý Q lïpîH™#Ž–w \0ájÇLâÌY?ã1½üb/̯{Õ!°~x³ .O 2ÀâMà`#ÔŒªi°s$Ü¿B™od ˾¿ÎR\@¯ô´®(j 8‚itt³~_€µa —°IiV¿ã@«[= –uô°¶w. |$Wû8ø²³uNñ¸½_\x2°0`OÛ%»…ê¦d–†$ó!ó"Éè2&›&4‚+C{re^àHn^heHð2AÊ‘xF=`3å†ñ:¥©2BÓ…ËH fññ€Ñš$8y ~[)ÔPc%ʸ覗絘¥Î˜¯é­ôÉ‚~eFðŸüè_T{ ª|4\¦3iƒòö¼¿Õ Çøúè%^)¼gT{öÓYL‡$&€å‘ʤ¿&êl±Sš4a;Ÿ¥׋ÝfýdlXHè&ñ¢ƒ7š ân)’q µ G·fúÇTañ‹vÿØÕ§ ^Á7ÑÓY&™æKéÑ4ü\ôâ´#/î§‘¼¦Kp£:7ŠX?›øÀy@5F;7éé=øøöæQ’áàÊ.ìð„[ÒÞŽä˜ÛÐH™b<^Ž$iÃr!©“EQÍ Þ,Û[ßÌ,* Z=ÞP7G–áxÜ^ŠwŽeŒúo2"ÑÍôpà®5x6ðÖ¹™üÞ2âô†”ô‹½¼‘ç²Fj‡E-äÌ€>eHºhh*£h?ß ±“€t˜zËZ%ÃbC<3KHE9Wì¬å¸s÷Uiû)º2‚z+¤E™èm*þœ ®º0ã{uÅvCñu‰k-x¦3@Ì¡t8ÄÆF$ ;ÈôqŠÅ‘š3Dd”ås#ÞÉz3€E’ ¦¢5 +ˆm}_åˆEÖF€UÒëfî%ÍM⊠æ`dá‹Î¿I÷îp-š<ÇýÏt’‘[:ÈúÑío#µaö·SEFJOXLW™,6L½Cœ#™éð§$ˆ‹Šhxþ I–€–„zÖxÆHõ Š_cБ <ð?VÔźjS¡|Ô)|±²Ôr¯wiA›‘µ±¢pß1Öœ6޼„CÎêâ>ŸôäaQÆ2ÍÍjSÜä¶¾ J­(´¹l¡£e’ г0ës—ò9`)ðäòHÁLÞ˜ dzãw°$ )p¥OsX)§¯ñŸÇÿ}V¾À(¼¦Øðô þ|»2úÿôÚœRôÉ—LWœÆ¼ÜÌ€¦Ø˜’Bb9¶‘¾þ©}}^>£y¼‘lž‹6ðº>|^>¯Ï·WuÁë×(Ìœ%µýk¸)%H¦ï~m†=¼©_µ‡à(ç§x¥U³}ñàì—{î®Ý]ÑàvtODM7B”ÃkXÓâe{xÉO[>Qˆ_D¹;~ #…”# <\ICÐUØ_„5ïí"öR¿qÆ+( ‘ú?È9—£­]Ôß³«c3–ŸHýá`žëÑ<œ-ËÀ«Ñ&4´È‰—!oös Ò:,pQ>.€‘SÔÕÕ*uï5ånXCrÓôK‰LßãRî&½T2ÜÆ+X2ÜÆ£}¶2/îà¶‘<¹;%¸qW–kçët½L´0z#ؾrbÐaæâ0DÃ.¤N±Í¼Kö‡¶ÅªÝÂϪO'Uµ^ëµ`œðQ]ŠA˜”Æèq\‚zë$R9f{¾"ÃíV¶Üòb…<|¯¾Ù‡%ÛÃíÜA¬¥½–dÊ­ò)j2ŒI®SÀ«+¾å—ŒݫæÁñÔþÜÒwë !ØÎÌàn)‚½Âb(¯3„C£•eµ‘ˆ›Aþso:l3fXÔ¡¹uµMJ‡Qm3L‡áíeÍï¬cÌ_*Tn‰±>ÀÝçÅ@E4?›øbjŸVü‘V"" ¹™ÝYäÅüõ¢M5Š×”„' ~ÜÂŒ ÚTIûÔeÌR±ŽÆWãqñív¹£4P‰o‹üËrd-Ež@®T/º [‚ã¡|ØvþgY&ØQÆ—bÎo$ÄJ”ä`‚¶Žüú#bÛ>œ àêL‰ýfèW?§p”ñŽfè†ñ^¬ÂäE½ÃýW_=å­Ud<FIN1•[+"ÝNÌ:Fo܆cÌi–½›<@H*`š”†g–‚*è`“¥Hôñaæ`%I ´‚X‡ÂJ`ê|Ž›µÒ40IGn°©ð?iD(H#f#„²!]…Ò¨ð*\˜=Ìô¨¬xC´Äˆp~ÄÞ`ó´ik&RT3謁Üöõ KýлÀ3šù§ò(+KY$ê²g3.W€`’BÔ< „©î8×ô)­Þ]Û€DÔJŽ©½úëmТëÍܲß-9V b†åѹ²RGà—° eŒ*E¤Þ¶€Œ)+Õ'âÖ±¨n{¨Ÿ[dvl¦'õ ²JWõ¼Ï®ãõ=ÍZíÉ,ëÌ’Õ¥lIú6dí´tsAr±ž]¦‰¿r=2‘­"Êè…j^%^KiÝå(›¶}}fâº6RT¥4ÜÁœ‚¥±>oQº0¬»ìlãQ&îÄ$kÂïàJ[Þ“~6*%œnUFd䪌¨uäú}á쟤SKf(—HîEÈMóJ“ÿݱh®1-ìЉ»¤z•ÎÝDJÚ’!•êF°E®øÈtR°&±Øõ6|^ÒòôkC×GT*Á{Ÿl˜Vx‹K,ø~àNîòÛ(cû ˜E"¡‡/­{{´Ô¯nBU¦ló°Ðb±ðÐ2E¼©M_¿ä±†uÝ_UŒ³ºî/ðêÓÓG­$÷ÎåÝ›.P.`Âz-ÓkaõR ×@¬I‹žÅƤÝ ÙíwA(ëÂyåÖ…óÀ8Rí­›ÇšÏ¸…žƒ5óxâÆ<¥æ‰³ï"È‘Ê!ÞR4Ó…lUËSÀ3ÅÝjÌ­K•cé%ºéOzÀn­ÊCeÜ6J½ ˆ£\_êX²ýjÌò•E­j­¨ï l¶DÃþ£hC¶X–Á´Aùô°^žE˜»oí¿’¯úqõᾬɓŸß=?˜Fyê"P=Tô*}ô‰jê]»V05•¹n% ¬›ÕA«¤‰©1j]Ða… è‘C+nß§gB×§g¢§àÎyÚÐ]êÊ¡:ñC϶û²‰ä^_Ï 4$ÝféW¸Ù¢ L#O3a5¨Àu_ áR‹Ý]Âõ2¹LKëw—­Qˆí…ØéúX’ì»ò¥oÚ»MÌ@äù1£Dÿ¬˜¿j|ßìbN¶Â๷ÔîþÌâQ 2`X0°‹AÓì"26'¶*±tRÏ·kúã'@¡”È“Œ½ÅÃŒf#?/SUp1Þ¨„?ùD;/Eç+t`,®‚wcñ`:0¦kh\q ýΦìn®l&;C¢´•¶Z¬‹UÇß):"Œ QÖ7?¾Ô’§‚{'`ËK¨È§Ò…*%W½Q”^ CÒØ¿£^‹èy¯…¥)ùP¯EôwìµHçšuñÂ’Cë’cɃÛmmßÀDaц·¯å){·–‹´¿=„¥8Qqk°íqíHvÕ¦ñžZ.¨¸ðØ–‹ý)©Ò™„‰zõN{.\J!î¹(]K‡R[㦠"Î[7] º±q¯eˆ÷µZ¤ÊZ9Ë®àœer ±Õ‰–…®”<¦ç‚h¤6ü¨Ö=”SÔîVÕ»ÚªÞ}ÝL¯Æ+ÏÖŸrM‘§ç‹EøÉ8²Œèº È)Ã#º. @Û¢u]à+Ö]©Áôè® \6†=![“.æ.¶µq©–ç–]ðöÛu]ЙâF;Ó¾n‹”þˆ­´ìpó`uógPÓ6ÕÒ=éRéÍûê¾ þLu ù"¸šÝ7_Ü7_ü¿6_4 pß|qß|Á›/4K*t±Ïûæ‹ÿÊæ‹ÅÝÝ7_ü¬Í›œsß|qß|Á›/ªÔÕï:wRz$6.ò÷Ç5\ØÈc`Ê%Y.l wè]v\xq·n‹üÓ‹}·EnãXt[ !|g:¿ßn `ŸÚ-ìzÝn“ÑÖR>þÚÏ(ɼê1èmOısÊ+æ>”P·ÿCÝ7«s£­:òë>h_ædÆú›‡‰^ís3YÀO;;±4l—¨A8¾a&nFµ£_SÈ/ž£ÑJöÏj}BwÏ,+ÔÖe7Àº4ò™°ªA,‚CmQ¢Sz÷©Žg;ì1©ª}ûŽè×äq¢˜Éw¬†(6±Ú_”ZV{šÝ;EÐëJ‰có0©c‘‡I­:š±Â—y} @VŸÄ#š]³ZEøgzÑbA%[?I´ÞVmsÉøQ[ÈÌÀkÓ«³f[×# æ¾n¿·ù~{öà¯ðç?v.endstream endobj 298 0 obj 4590 endobj 302 0 obj <> stream xœÅ\k“Å‘ý®Õ˜ýÖ—ÝiºÞUÞ°#°‘ Ö°xˆõkcc4‚°t#Æ¿~3³^YÝU÷öÌH^ÄUwuu=òqòdVÿíb™ÅÅ‚ÿ¦ÿß¼zòþçîâÅë'ËÅGðß‹'{"¨ÁEúßÍ«‹_^A#%àÊ– .®¾zŸN^X¯g!/®^=ùódfšrvΩÉÐ_.³\üôáA¹Ù-§a™®ðœ\诗Ê,Óï—fÖZ3ý ®ÌÎK¡á¦œ>9\Êé7‡K1{àöïàÚGÐDÚYzOMðÒ‡pIÙY,núâ æ¼醆'¶Ó3ìDk¥ýôëƒÂaZ—zø¶NmŒ‹=j7 ÇgõIÖþå=¬çOppÝxÊÛÙhøõAiùùárÇ·Xvõ?a8ÖçxOWuØUÞAZ4'üÿ\ýv 6‚íLb^õM_FSa`²¬Mwx?Ä)*l]!é›ú {eÙ¯Ÿðø$ÎëRúyZ±!ÜP"À~d`]²a}³Û´ÓV Xƒ襾Q¹´©f yÀ@”52b³—‹È[IóL[ ›Ê¶$kn%èKU0´àhïŒQ¼iéø&ÿxYžÀͨϿB}´V WºmìÚ% e¶`Ÿ„‚×W«™¹C+UîËY\u0Â2oa«ǺÀ ä2rYÙ—x]“óªZÒ ô0qm¦¯ð½x5.ë¢H ÈîUvãP0›æ yÇq`·½hÍØd­®^¯q"hGÂJ%Øep…ôè±3qÍ;¬ Žó\À•pá=ÖÞâb:¥Ö‹ÀúƒÛm®’–ÇâÇØRH.ÁLøÐ^ :OÀ|è×ü!©e6vzZ$u ­Om%hÐ÷8p §y³Ø_U¸*×ÇFõhÁ¬e’]G^5£\ª–KÕÊDˆ‹B:A®&® ¸À0/€Me¯Á‚ ¥†ù+X*œ?ë½µ² ›îvnʯ"O{â‹/ð¡ÊýW—½¡tQ%§1ÅÇ:b.otͨ¡¼)ãaéÌýÐȬd˜þ2•ž‡ï€õ2°2O»n&Í¡".³ö€5åfçð­#󌢠@E¬vÒve®­†‰»v{eHêÓ=Ao¶@#Æœþr(íþ{À%“ùÛªâV˵ëFHîÓl[_0²Ï\ z2Ê좞,”Ú´ö­¨<6'þn0©):‰ëP„êµ¼Y A×Ñ÷oO*_kó{ÊwÓÈøÖU!Ž0°aÂò a[æ][ &L°…ˆ§÷Ô3‹"¨÷ßЉskУ;Pó¢³¼çÍØÓά[nÐKit] ±æhý+Xì[bÖ3Û t'%±UdÔ™®ÍgÞtú­Úõ<î°Zä4„GqAZWÐXBœ¼c5A0 ÒÎCË*«ÉƤ(M‘±'=‹Jzµ²G ˆ­B¶r;6ôyÔ¸Ú_Äsn»TBÛ?tä1? Ž‰óuÁ.YúL²> vöÜßÅæ ïu} î DŠZɇ¨tœ$3­¾0¤,Ñ'ØÙ9Vsû"îö"Ì8J ih ÓþˆÓSüÁÃW¸¦ VêDŸ<Ò ’ éœÀ] [{›¸Ï&ã%kçk5žMþo÷_sÓèП㠶‹L²ÊPþ5ÿHU"3l‘Rо¡ül‰ÇÑ~qY~ ã!L|ê8X‹Eä”qm8øó þ2 2t©ºÄÖÅ¿âÜHE¦ÿÅq‡³§Gb›»zÔÖÀå0ýæ#ÂÝx]š~_›^÷.¾)_׋°é*ν˜»H²¬æùq;Ï?>pž?Ö·ß•6ßÕ‹·å"Ͱ‰wïlÆÄÛ i›y»Ù«€Ä]˜Cы̔ӋIgR†ÉGçfÀ^åñÄq¨Y8p{i© c,ŒCÁU”d$=²†=ô’ºG<÷Myѱ>ó""?ëù3é¾°ÑRôTÞO_àój‰Â÷Ut?7ýï[èói½ÆZ–ÛÔ¥Ÿv‘±]È–ÄÑ-`Òˆ J:âÈð!ðb/ãŒÑ|†æ Ìl`#þŸ1VAˆÌ®¾‚U´nÑ!ÔŽê"Ò%—†@(¥ô^»¨–,Æ)`=& FòÞ%M ÏÍüèϻQÇ=,{±4‹vÍçÓÚåŠ+HcL&]BHÖ¹åjˆ![œå]<4?Æ4ö5 QÔƒØlaVpù¡ÀŠIdÏ qñ‰w%à(Mˆ"R0ÈÅ …´ðBK~Yd©Â&§ÿ(N€ü¾Â€”ÄPŸ>ÅtÀyÃ;ZÇê¤{à×X[öWñø± ÜqD¶£ðH#Ü@²S%.c‘Úü:f4.Óòµ8IÅë:o¿%t9‡¾Gþ¶Êq÷~7–Œ2f}t'0h!¨ØF—CåY5Ý‚د5üw†¡ª¼Á†Œñ¦(Ô¡¸ˆ 9ÎÜhþJla¹Ñy5½ÀÑí•D| kð).!μG•rb–"-©¶aTkc¨¾®ðëŒ9Ç×ܶ _›_G¢¼s&–CàÚ§_¤þ¼iµ/mC@úÃl2L߯tëM?æT.âðÛѬz• EZ«VƒªÊ¤×ãÃ…XQÓ/4 ÙÉߢ +ùÛg1ά"“³Š§cgÂØéO¸€˜íU<û9zg!l(’±6#áu—Žr-•]a¹ÂµoP‹Ù±‡/2è¡?P Z!tŒuEõhM($Ó&Wú¢Íi­ƒi,UÈ€=e,Žé%0Ðmä’`Pk3tÍlâÅ®8e fÔC"$ÕM†‘lxßGòf a„é;® "°}^$ö\s‘R÷èW”úæ*¸c‹`D*TYù54ÏÖqßhQLû$Y±r"I Æx£M.uýE³¹°è’¦ÑÕ§&™Üæfi‰Zl•ôY© ©öäù·Ãˆ\Ö°GÍnªÔp!ZCÞM³ØTj¼(Z¨=¦5é ~~ Òs–°' P~ꯈn¾ìq¯Ä,—uéâ’9!ß 6ì!¥°§´ï@1{Pê¢i±˜é½´À¢ã¦kš„ÒzJ%KžE‹ƒ“ü·ºæµ«è~:¦Æý’¹Gd}I2°<ÉœŽ\(u¢p?¡žÈ„ëé¸w2%¤YŒ{œÃ«ƒÂ“m`Þc‰f=M§µë ÛíFµƒ-zg f¬»áï±Ûô´]\”´§sž€}Ñ Ýç¤t#w«Ôæ8»G0e±‡ž…þ3±láïŠX3d™ väòg‡˜pö”²l0-ɺtYΟÅnÃ}(SŒå?¯A`Áûã¨fòETü€AÊEþë„ çýaœCÛÜ«™ïØ(wÛš…t<1gê´N'­ñkæywK}òguº¤S%{"ŽŠkÓ‹,S…ñ c¯y•šŸá(ß± Š4ñ\ñ® FÜbZm‚â„!R5áËÒæË¦R³>˜/þ£×ò»rñî@1&ˆf¬ó¤ŠG¹¼íjÇ…RËX;Z2ù-Í<Æ ZDÌð`ú,ÊɲÆÜ69¶gÍ‘Åùš2-¡†.³SS |#4tüÜÂV#fNZR°gùY°Ò²Ú-”$êÐζJD㷦ájßÈ4…møÁëE Û!èm¡•9YkwÖ *æz%ÀŒ‰ˆX,¯²”¬ö„Z'"ÂÙÐ)‘ªS&’«Ü1×ä7ÀâŸIW¬øî]AQô†šjè d“Ï»]/ub „.Ê#éŠíÑñ!]1¦¬{ÅŠêßhe.ü¬b;øIÒ") xUJþsagµâò¾îô/öl9uevç^ÖBã‡}Àª¾»ÁHtou§Æƒ8žX ÐpR‡Õp²"Ÿ!7Á’ÞÏMäšËú™ž–¤ Ívæ1$E\1¯Û´=ì:™äó%œÃKCéÿWª"ó†¤*<74{© ¿ìÿ¸;˜ ÖuÍc*ö*rùÛ'+p—8‰˜\´©qµÉuÿ`r"U{®*SÖåöíWe˜^ E˜Œ¬U6ÀhÁFç£gé‰5Vÿ§ÓvÍM\=†› F‹¸ˆx†oM¼êqŒ:xÍ{Û’ /97±}úª_]âÎmÎsÖCžÈlÀÊc üîÎsž`8*/¤üù°í±¢l¸‚8]OžîѵP»–•æÊöïˬ4ƒI¦KÑÔ¯l‚_öžÂ§ZÆæó/¬×3“§Š¨bß[®D[÷?ûuölWæ>j¹nƒàRIç@‡¦¸fu*có™®I³6åÜ×:¾k>©Á ^â´Œd–…ÊÚ†ïªÒ•cÅ Ka!Uþø7ïΆŒ•Ù€O¶Ú2à¸F:M¦Q„k <•„j}’# ñ÷k.ž*†°äA†Œ¾b (R LŸúXjît H‹X Œ_õ±é’$ Pð7y¨ë³ÙOl®«Êí8âíú{)w9‰Â>“לý¡µ-¡«kR¾ÏØýºJSOØ”Èàj*û‹£Ú” Žzß—ŠbúWß/ÛOñ…h=Îõ]‹£X"7>ËÞ—øÁÂÇKËõKM}_à&h\xtïqå÷æRÄ™¸1±¯Pšé³ü6&µCh8—Ö¬Ïf5ˆô˜$•U{ôΰ­ŽB§ ¾õáÏ”™_φ+1ˆ612*ãán£¼´Üý¶ÊmysÚm•FW®òÇÃð(ãF$dÜC§L}Њâw7胙û"·Òuc@ˆgŒQ`úþK4Bfº„‚i¤£ó[ã“&‚öbçgÚƒ4˜3vV}&­ v¶]5ßWR͉ø\²Å=?ü’œl¾v™™f·’Î3³ª_TdµÍÏ®žüüû²ëendstream endobj 303 0 obj 5214 endobj 307 0 obj <> stream xœÍ\[sÅ~wøzãœZvî3©Jª’`ÈÅ!DŠÊåA¶ÀN!#ƒ„Ÿî¹vÏÌ®ŽNR©ˆãÝ[Ow}›ùúl]ÄÙŠÿËÿ}öòÑ»»³ç¯­gÀÿŸ?úú‘ˆœåÿ<{yö› øHHx²„5ˆ³‹/¥ÖâÌÉ3ëõ//^>úûÁÍAÍ?/þ-”`-lXV.®àÃßÏÕâ\âð»£XBð:~}”‡ŽçbÑÚ8y¸hß2ÂËÃû0~âa$eò^BWÐ@)hbÂá“ã¹¶NøÃ§G¹¬«yÿæ¨%áSèOI ¥²‡?cs)¥µäËÖgžô§G攇N¤]Оî úÕgçj]œ!íÆûÐqìɯ Gg]…€±áŸOðÏ?ø÷ÿ|…þ…¾Å?ïÔ¯Ÿâ?¯ñÏeþN"ɽ=|Y¿¯µ3°#öð+˜©\¯ë»o[ƒËÙÃÛúðu{øcyŠë…-0vn|òèâç'-ìÉîëÒ:ëÇyNWK¾¼f$°fYÅ›!Á»ÃþÒ-×fñ*ø¸ç¢î¹>ªôu'ذ7HÀ,§ïozï€ã>‡_Zƒ¬ÞJ¦ƒÁE—ŸŸÃ‚XŒ60_,pì‹éû×È­Æ8+ɧßU¥ìªðÉ)ÚýóÔ|ylmnð!Ì=¤ñ cÒÆ‘ü $Wé€ š–"•>\¥´¹W§öªWY”4ª“z~dë®Ï¿À ÑÚ®áðvk©èH›«¦Ò\´ñ…¬ø‘•ÎÕ”òëÉðÿF]$¥B­×]—×ÈbÁÁZuã╼– ù¬¶½…^‘IÔ ê´°YÒK\²µÎjì ‰¦ÊÓ‚–ºLT+¢ªošŠjËߣ†€Žð§·QÕ§Ý1@[ìèi#Õu,-z V …¥óE­M0í¯•kÀežKØ4#ÏÎQ‹˜¸Þ«¶^à é‘-‡×I½#è¾!ñPm‰LSü8s¹’ôpy¤2óy!ãÒ|ƒD€€n 7m`‰\]rvDî,=x4®îDQš8ãïŽF/ÀÞ>öS¹å–¬€,:Mç ì[¡ ÝÙ7ÁÌ+øš¡¶Ê3ä Ø0d“/a ‚ðð„³¿?"ÖKç m 5É.-y3ü~±"lñÉ¿gøÏ›Š€_ÍtöËö°5$Šü«úðvðKÃvýo€C®*Ñ˼àÛÕõ&pDu.OäÖ¡³›ØCø™µ'Aª]%9D`?œ^@ëüÔø`@?؇¨Zã0|È€S´wþ'ùD‚žÑ+JC /]x “´RÖÏ(µë ­(ÆUd¬)jù¶-5CŒ®N@I1m’qSÑD Á>-pÙ”‡i*"å}€&C†[”f€Â(Ì÷}‚ ±V5iW  @ä\dÞ‹Öêý#¨_bF‚ìy¬úúŒe-˜”oEøeRÈbo—ÍŠ~†’Ö·GѾXÉ3âù°ïLˆªÏþ€³Ÿ‡¥=˜=¾jgkp†êl+¨Ï@ ±Zò0ÊQðx1aç×ø¥Œ¼‡ÏÈ{åS­'ø ‚ªÍ«g@h|ا‰ûd= nò:#ëKPx•õ3Tëjw ¨F&ÌPº„ó^Pñ’&ô)¿NX ˜±Z[\‚Ûêœ0ržÿyõ p„ ÑÍÌà]p;â8òØ'Z…¼‘½3xK ÁÛ˜ ðFÁ:²0>öf3œlT<Áy­Ñõ¸Fãj¦K³^sdÓkƒgŒ+®3Ë‚qØþÞ €n£új¡j» ÜÞ¿jì„܃»x8²*pT¨H½Éw*™qí}Óö·3½xÅ=™WóÌO„VŒI|™&‹|©UѯùÑðÿs˜¨4@„§%šFùsÄjwáÖ†SY5+ØÌ#ÍàïÁNŸu… ¿Ê†-(ôÎv¾LoÐáR)fvÂZ@¥¬ag-I7˜Û©µÛÇÿûøÛÿû˜”6‰q¿€R!˸šM!DBÚ€¨ãP7®q;Ðvx30°¶²s(Br²0ƒÖsÔÆl MA^-àòþ’|ñÂJ4MÖÅ)¼NjÔ[4XÑm#F¸Äèñ*ñ¾AÍ ®½Výbà%ô`­wÁÁ¢À|q`è°O£)ˆQŒQÀVêòàƒ;öûM3+Mk•\ŽŽÍða€9’™ÿ »5 •¯½ñüI¨|€¥?NÆ(ÀÀcèI©2 %B˜‰&PºaYÖÚÄ*J ‹t]¢•^V¦$]âï¢ÙF¦ôn|oEŠ;ÔAQ YK§·íçÓö3SB ÐMí|›f*ÙTÈTëôÓœ½×næXªµDs‰5ò¢Gí‰)ùs´E´‰“vÛì ¢c‰jD-M>jz}l`é’÷D|/ÖLCûÕ2V«@`ဃŸ JðÔ,áÆ'ÊâŠ"æOr‡‰  ¦¡âÞ*Ñ]Ø åDjMWE¨U;ÊNhœ Š¿W%½FÝÞºd&øù=+詘)d\òóíl°¥¢S-ÀV*Þ³Ú è’,Õì@U*`~ÒoZC87´«‰ž§U‹#¶­ÆÌ–,q‹6t¢cX™ù¤2¤é]#7k’$H€“'~Î ù¸cš§V×5§ò_ÔÞ°åbµ•O}ˆ±Ç.¦àlcs?1ñc¯p®"hµYp1.ÜÆù7q f¶ÓÜʪ{yÃC,à2 !îüÜk¬A!±/VhgNá6åMähê](g¢˜:‘£¡l0ÃOÉÆ³AOm¼’¿PiƒjGdR`ϹjéÏÂU]è˜F9RØM[Joê6f‹5ÑÕ,¸N²µ q‰Ì´67ÜEΖ¥(sH†Žàtg²Ía7¯dò&A¸—ûª E/“èN5ÆÓ)!}¤%™-fµëMDì :A«g÷àIÄ};±†#>#hR¾¾å\ߪ{uÜkó¶o‰{‘džu'’ ˆ£0›“A¯IY—@ÅšËfR!$$:M8#~8 Za} M‰Ä]Âä*ç¨vr%y覀I‘BV„ï3žˆ’X$øP¬xáŒoÍTN aÓìÚ5™ù® »¬Q¶´Àøö)‘ŸD¨A$J¬üæ8×™½\Õ€¾j …κ¶4öÙ7k<ŒöUG·˜)Û5De+˜óü^¶BØà”ÅÌ+ 6Q]€°Ia«°‰¤P7ÙaU1ô÷Ö Îq"Åá^yÀŒñ¤¸&±ž¼jdç&æ÷ ™íeÄÃ&{ âƒ!Y jßVACô $c密ixtxÁ'DÖ¼âbACïÙÆ5Igxôh0³'X¯uGœæÙ„™È‘ aL”§ú„q¢NÙÂüÈ|’t`IL|3hlyUæ&-ÁĶchޤç½ÛÈ7fÊñòh:OK—ˆ:ù‡ £œ©LM°?£xœÑl:ex‚L•¦6\‡\¨8ÕºÈ!™¶e••‰gïDvXÉš¹ªÐ$ÛËó÷E*,E+ò@ü¦ù„úÈ„œ ÆR÷†FØÇ>ÃltÈw 'W/DÞS}°™uö³#Úà^Ò4 %׌D¸ºÇËsÖï0h†¹]½„!ì¤(+隘R’z½iøä±¿µrÞ¢ÝKC¹GQÌ£¶…!Qñƒ'-Ú¯!—Œ¬SžÅjÕv'ïyS)ôqwö+Ê®Uxˆ›j/®—MËM›6—QíéO4ÏRjõ$%§ÀÓ+$tX¼3Z9FâGXí¨tœY\¦òT5aMÞ«±AˆA m¢)ÙÉÝU™8o5¸Ð¢oÛˆª!:ê>ßÌš_ͤØDäûd’bÎnˆW“ÄÎü¼‡å!‚IV‰Š8u¸Ô$騳r¾OO"Ûè<²7k`F"q˜¹Œ1ø.ƒõp“‘„á"½@É‘8ä´Ô²e¡?jØ_«gG#–1êÐ3“cD˜çÄHȬRü‡ Ð-8•è¶ÊÛÈèI„ËÜÀŽh–ûLçÎÙÍ~¤=¦½‰}<1™ç©ÜèwZ3ß…Ç3A8³ò“t`aDQòbê%7NtÒ°6ä]ª4•ßËÓHîc2ùÔšä&ë"%9ˆÜ~M˜rLÛF×lH e¿å²ý<í ŒN.;™\Ùáq“6¥æVš¼µqʼnæáWSb2IH4è͸˜ùÏÌßœ’®¸ôª«¥É̱éŒåîß&mî(inÖ(RÔ ×Y²oÙütYÞܪ õeºqaÂs”EgXjMvÁž7vÃ…Ö\°pÈÖÅQ“!\S¸E9KB¾ƒ;-ƒ©˜ôƒY­Hç5=Só+Q¢¢=íÅ—;qÔ|²>·x½æg] ¢œ_¯™¡KAI=aqf+Ô=ƒC{[ÿ¼åþáyM¢‘ñø§¶’êï7UFP£Ÿ–—ø xygHüŒÛ‘ûXn|Õ²Œ$‚Äú8]p…sîX§×¥r&¢o{åé‰Ü×x´±ó!¡’+eê1ëV¥ÐUÓÕ†m1µ "‹ÍöËòð´ÌpR’!3·Ÿ¦>Ò;Å¥¼›"Ô>š—%8ÚZß‘Œj=ö'i±bojÄmD-I’7£Ѱ…{^h'¸ºø²Fmy´ ™ºcÅ¿.ðt_x)v¡ÁÙºÚ=«3(Ìš3}À,U–”˜§f—gö­‘\ëf1›ù*ï†àH9Ñ`zš*Ë' ŠÛ˜¶Ã¶/gù–þ–°tÉ]LX¥ÐÅrÝN†*·3¬òN뿹Gr…z³EŠËU«'¥Gùò-¼39ÃSî)›»yù¨ÀCÝ”Y¸ªtÛ_ܲ[jMİ ÊìÊaäFIòŒU¢Wîo2Ã(‰ePB«³¹3e65Þú#=Èv$õvÃÍîÝ¢dg@9`nópÀ 0Ä’m “2¸|ˆÚ_çÃÎ¥UA gŽ`Ô˜y€,FNqÝ-Å ¢œ]¬ Y­åìHó dp;‹Œ2r51ÛˆÑ[.ÛŠ„PHæEUY­j?SÚ×ÙWµ*°Üj }'Fl>± ‹YÄZOÛÁâbúê¿#`å OˆÈI©='“/›ë®×»,¤’ár­!Mv¨T<Ç/Ìnê`7†ÝRÛÍôÑ5n:bk*§$¹shŒOnœE³´¤Ó$ándà…aºu%+$s„€ä Š HÍ2*ìg%uï[ë!öÌ]~rvç„óo‰ŠÜÂ"ñ¬v¶lG“±2»û_.Æ"°H‘¾ýSkb£2§¿À¯^ã’ŠuÄI÷¥@œïj ËL¼5b3,!ÓнóCˆ ä¸ÀjØíP$.ýán8ÕÃöþð~ 0—Çz-f)•!•xSšJ–~«Ýž—O‘*rIÚg8Y{ï øµgN¥ó¸‘ëµ7ôØ¥³ó¢„§I.´Ð* ¤kË$¹–›W"Ìà'bš_ºWp>–ZµÃïðÉ/Ú­>e™ ¸áéN›Å‹¶l½1©·×¥a—{¢jÖŠžmݤãÐk»œ“lŠ~›:Š—>þèÀÛ*{ 0Ó+WcPòu‡s¹Ìt ›™PÏëíC„³dðcR+ð ~µNf'D me˜2iw&,_çØ_5º$D;„©Ç,µ,»>ÜC™ù°°€bÉ“†'d½@”5´ëÈPì‘/Í(Ïœ_—ü ©S!Èô™:I[Û2VÃ`ðÅÈ(‰;Û2\ßQ‹ázÛ@étä¦W5ùxtGÊÉÙ«Mûj®DËH^_<ú üï?eo“4endstream endobj 308 0 obj 5668 endobj 312 0 obj <> stream xœí[[Å~_ñ#önÄ´»îU‰Éƒã8f9Œ¯­ìŽ×Ø‹íüúœS×SÝÕ3=»&XQ„÷V×õÔ¹|çÒ/Çø_ü÷ÉÅÑ­æøìÕÑxü%üvôòˆùÇñŸ'ÇŸ@'Á ep£cÇ'OÂhvlø±¶r`üøäâèûN÷ªz>cDücc¬øh»/zíZ©î«~ÃkSÝI¿VËFÑ}B R‰î>vRÞ=è7ã`ÝhFMÇ} “i-µên÷ØÉ؃ÐÝ?p7Œ£‰/Êhú|»wã02nËÛý÷Â9×¾¯xÚ´¨c0cXTœv:Žšu_⩘“¶»c$‡ýs|Äý h}Ô³Á9+]<ªqŽ¥÷x¾{°K89œ[J§èjd;÷à‘ØpÕáÐ;I‰Ýè,ó¢Ÿõr‚k G<ЈLüîjgé"8“i !˜ßÙl\‚öãÉ×Àpí„' Ë0Z`‹“S`»½ÂŽÉÝ`åñH ´r¡¹úga^ äþ¹ßpËüó VÊh­Þ38å“üôØ–§8pÄÒW¥ÃO…>¿ô$‹taÒé5\§µò<±ñ¶ŒÃÍ™¦¶åõ+\× JJºn~}¯iŒ–¥í<=<îý^80£".n„€]ùÃ8'¢Øm(®#üð9†kG/óSœ„©HD.d÷EsaœŽÅÖòþ²ù5î‡q²½gå=û8ÌeÊŸâ8륎CvÀý8ø¤ESB4œÿ¬÷¤£H|Üai„SéH̉Ä,#:Ã<«w¿öJp1ÖOxž‡]•¹ò°t£å‚Y +Ì™ïZóÑE ÂÀzê<ßi–¸øÖ‹E$Ćá¹Fèñ¦ˆE¦GáÊgHî•$áˉ(l ;=â”òn¼ßhüޝJŸó²`¼Ñ6å ÇÕtf䤜³pÑ@Ÿˆbdƒi²¹Þ¢²þ‰”G}/¨F ŠŒÉ !G¸uB‚ÊÀÁMf#úñ/E’ngUy—w óþ Wƒ3rÌwD|Þô Û8›ð¢¯ !}Ô Î*GÁ4ØC¤2`@¦¬4Ÿ5Øq›®œEÒ) é³– ò¦%Y°ÌQné²0ÇÝ&ND-Rºž“§ Yà"+‰Û.ëÅIÇmeK6‘^€RßSV‘(ž²û8qcaî—án¸†!<šE)°3 €šËÛž£6©Ô} KêÀh§SÕ—ú<ðÅYoD4XE8$åP["Üe>B¥óçJ5ŒÎU¶!êŸmKþÊÓLðc£Ú+ÊÔ`#î›Ø/ú¾bë´u­—N?1‡ÅÈ4¨¶æ-@ÅѸ$ kUOÐÙi-€œÒ ÕØNPÆæC¥AFQ;ˆKD»X‹™†JG1–k5§Ø(€¼T‡0E¬2¸¤Ã£ž»ÉP†?Á¹@Áv;{Õð'—éΕ(Jà´ÿ˜Òsíç- bdÐ{äIæü\‡3`ön¤hžá¬jéÒÓ=nËÚKì»Fk_½$×°Cf™[â*³°¾ó Ú’ŠÛyì÷°JJý^µª$ÞùýÿðKm€Ë"MåŠêï,PÇYä/¯ý%,œØ'¡Ãj=„“ÛIiæzçÈ£xç\àn¢õG‡àwÇõí×å” g a²ð¸­èò  ýVký\é…¤@‹J$¸šôœi.tZº¢ËÈŸ/¹iT­—üeIEA}™! #^¹¬x²h¬ç­'BÁæj6sV"Jè7Ìç²ÂÈR€l¯°ìÆpÅБ=HX³P`~Õtm±e€¶D·KG„‚‰M š)¬tVØ‘g¬°¯çKð”9t)¼ùSÞ•¾ÂêéPF쑉¼T Eüïüb¶ã@èŸ.¬†ê‘Buà)»E ·C3sà;< ¼†ðw¦û=’”Ö«éëB\Td2Ì f‹ƒ"dq^³ªk»²£§ÙÉBA3©ÎÄÃØ¸° g\kdô Dœ¸z"öì®a“"£'¦\¡PQSòºàØŸPy“80îªÖÀkœÀ¬ puz·i QŸz”Ä•ZÇ‚ó`‚þAÐ9’Á˃72y ï0ÌËig"s8æ²ñö-• kâËÉ$VØé ¸N²@¹ý]ÜŠp ‚ ðe—pâ$¯ •äÐDË ûs0ñÑÕ·=DQO «Ì€g"ÙÉ­A ‰0µ&ÆlP¬Ã8Dé°FfT?Ñâs´²¡jÁvð#޾,bEùc˨çÞ%=g¢sìg=ßV˜l#¸ò÷2C_ȶEWÏÝî¹cÈ¥çÁÖ–*™LOþ®ëCò £bÕäÕ›ôŠ¡ø!°,m•l°ƒž¿€¼í¾ÄŸ¯p×ãðõóü⇯ðï Ž³ñþ¦Ó`ÿîϰG­?å9ž£L™ô®|j¼,ÏsãÛÒøin|•Ÿ^—×[WtLjü¡O­H‹ÌëwN>Ùqî;ÿcç¾õ€KÊ€RV€Ù«ù€÷¢•Š`À˜Hµ¨CC¸ÜNÜ”_Y 3y–UÔ“œê]kt­&1¿*-t5QiÝ¢»ˆÐ\ôpTè,æ> -M îD¦P ih£rH|IDcB4v/DŒ”ŒUÄ¢Ö jý= Ì·±éÂû"B»­VÜdK`þÈ8søö:°Ís<.œù¶%!…Û?m5¾nMT¯Zc²±u¯X™  ¸‰H†ÉÛE €E<škqó¿ó<ØÑë)BŽöUö11ì =‹}ëí8ä™ÊhDÙ§GÜÑz9Ùè¢ÿ=عŠs3jãü I²®1#Pj}^Èñ¶ˆ/wÕƒ…à½@‚3T:(úï÷²|³˜¾çj€ºJ©äjHŒðWî‰èJ>î½·Ë‚Aɬ×MÉ€i­à1U ‡QNcQèFp‰~Oš´Àòî}G¡×/T®lM‹d8hJ îãÇ<ûÇû3M´b>…Akv£à?_ƒÄø(ö(a¬ç@†]©„/ðoD DÝž¶°ÇE…=È3ÆS×ëðŸÿ›:|'f+º›Z´*» Ó0¿ôÛqÌiÇÇkÑí¼4žSbÎáÝu‰y0$”7‚„– ¬ª™ í¼v$†I¼„䑊©ªãâ‹êÄ(’X›,žr‚qƒÍßG4r[m[ÕS %ùXv]æûjÕˆ Ag\F !I™—KZÏçÚwÀÇØ}µV˜ s!Ãn`ÖI8MT&íkÄmÓé÷™ë&¡‘}¹Åw}ñqWGm‚ÀœM& Žp¶¢-eý»ÖôÊäIeˆÎgÁ‡8ÍEÚ£ýœ>Yp1Ó‚³¯åEO#“+(õ1máÀÜå‰Û¥Y¡)qG»4k’tA˜SIn (â×È’/2f¥´3Žs:Ì¥»D5qjÁáõ¶TEêóí>A“ø¥ æ±™ðY¸yµ`*aÙ[T }A¿×Tjb¥Ë’Ô¤EÖåÎc9GrJnY’·{˜êxïöl´¾ÿ½gŒ¡Æm× 8kHÆÄ*iUʤÁgÆû¼nPü# æ:fÅ/b©Ù’bJN%sVƒF§ªš½x†0NõME®#Z!HÞ.{jHG¼¢ÓFUáG%F³m¼ÎÅ1²]ƒ8+?ˆXi®Š0DYûWÂØUÒŒðš >’òÒFÔ(Tª0ݶåËOZ!Q” Î<ß[ÃCÖ¤>†…¢íßÖf4¿µøcÙS£Ä Ź\8¾l‹ÂwsjÐÙa¸ìItm©p<€6Åé ßõ±,Á­ QùƒÉ€â&U4 Ô]÷ /ÀÀ ¾>!|¥¿•ó‡¯õ}‰ÆÄR÷äCPÂ[ú¥h•Ï,H»«ü£Qìµ]¿¨<É 3’rÚú¥QÒª œã^˜o™©ôyQ1Y!ŒEsai[5«F&‘«DZüô Ê°JÚ“Ò7*â†ájÔ¥4N¶Jã4 À“þ.ɯÃú³<7Ži„(É—-Ÿú’þ _'Yª_™8“÷þïL~pÎä|Á«¨•ù` ‹fòœ®<ñ1ãÒ?á]»¨­Pá{uMA\ôÔ55«\ÓïŠ?Z'M¹žæ$¿l½8 ;0Ÿ “þÓ†÷íëÆ/u¼½RŒê¡y-|Áh¨Ä?šAÏJhcãû &=œËõ$R_ÄØ‚¾å¤lqIä 7>%R½;";ÇZþ·-q,E¢¬¤1 Å^¹Åà÷ btù½V—Þ99úü÷:…çendstream endobj 313 0 obj 3857 endobj 317 0 obj <> stream xœí\Ys·~gò#øæ™”v2¸‡¤*>äØI9ŠÍ¤œ²ü ‘Řܥ%Q–ÿ}ºq6f0{‰N¢DV‰Zbq4}|ÝhøÇÓq`§#þ‰ÿžßœüökszùêd<ýþ^žüxÂ|‡ÓøÏùÍéÇgЉqhÜèØéÙó“0š~ª­à˳›“ï:Õ«Nöêû³/a„`Õí†Ñ ³ èøI¿ƒ1αî=œ³Òuèy÷¨_±AJexwVú|Z…´Ý×ÐÊLk: « ð çnà †§‰>í…¬qºû{Ï´ZE¾ý –ùd67®ø)´J30&»/°Õ:Ë`ÿ9-Øh¡“b–wa%ìba%¡â–ÃT0@¢\÷M¿R0Ö0Ûý­çÃ8* ûã^‚CW˜Opà¥ÐÝ_p8ç\kÒñ¬ÌɃy=y„¦¸7,œ—ôVñVb s.œ†íEè<9d58=òtfŸ÷°:³ŽwÏ€b)ïÝk É}ΑÆk Ø#HÓM¿âƒÖFKҸ40‹¬Õ°ÅW86Êî9‘R:Ó½ìWÀ"¡GÙmàÌa2a LçÈÈaßÒ)X¾¥xwQZŸÀÈÐÝ¿ÁB°U«ýq ›#Ÿ Á™»îç„=18à œ€“I"µ.Ë\P:p§\Èî×¥qÝú ã)øžÔÀÕÀ…!sL¸ŽM3®cã„ëÈ àºí€âóSô«…BŒ \2É@^äI60Ý=Å Þ\gÎëD·a:.=²¸ ]w—…”v\—Ö<&qFÉHšÿ+O†ƒÆ2ç‹ÄC׉îM¯ä`4·ž±×yÜ]ÑÄ,.¬û]V;ÜúŠƒ(:}ºÅV¨ž‘£HsàQ¾Äqá(x¹ùëùv7 =ê–ò¼BíV váõl‰ÒêX:òò¸W!üÇ?*ϯ«4nÚ¤°T&ˆ–åžç(—`›…?‚8æ<Ë.Kv€ÜÚk8Q…M¤Ô1L§´©U:M¾æFw? õ=D;|‘—HvCƒHl‚. ©P… ' $W‘Ê&…ÅÆµWîä`³Ôš â!•èn˘"Ÿo=‘Ì ^dºHa>NÞ–îkò)˜À‰¾q…úvKã:Dµ"SÀj$¦¤of6"(]RÄ!Q„´•7c@ãŠ2¨ìM)ÞWÇ€pcãÈ8cøõ;üñ1þø|‰?þ„?ÐMz:¿>îðçþX#`mAB®r§×¥ñAn¼,/sã¦4ÞåÆÛÞ¢ke†Œ~^:Þö¡Ã(ÈŠoË×Ïr㵟ÇHFæYoïXÚnhǴີÅW¹ñAž§t¼+¯ ¾ÉmOhÇ´ .Á¨ü>Ú|èŒÕÞ”þÕPÿuý®Ú*¡–œMêKf ú¹||ÞF&{Ý$çuu¾aûü¹ ŒÀÅ ›ˆ²{'`$-€9sÀH ï¢Ñ ÖöKH=H½¯Gxü²xœë²W(Vd+ª5µ¢‚$ô%м\Ž™:\IËØ¸v¥‘{T€^ÇšòìÅñ—íĽPƒ–,;Ò#=µS†;[Ó–…Gå80È}-ô|û;ƒew¡Ö(ÐXÁCÑÌ(Dv¤D±OôÆç‰¶‰ƒˆ¹¶…üÌ%Ä8Ú“ ƒf')gwˆÏÎ Oc3Þ$Šy¤¯/ƒwEX¤6IHíÆJb,åº7Ç^ƒGgkø’:â÷Àðú`ã“ÜÕ§CãœhJÂ=€¼†D ‰5C@8Gb  §!-ßÌì ƒ5ã£Øá˜~pÌ÷æ˜Wª€å“àJWJ¤ ¤é{ž»¬ÞvŸÏ³¶$&k9DÂì7M÷{]Ñ?Y‹L†ÃŽvÕ‰mKž¿wêP?­íÄO³^@ÓöÕǤÔRz¡s ŽÚ6cESùš*&ó6ÆT!Sò¿Åo¿¬½ Z»bþncì¤\ $’á¨Üj[­bQJ±áÅ€µLPm…›ò´X‹GÉdÉ|ôÞZ‹'ùë—åë›­¨ú¶Ò‡<:u¤ƒ‰¾Í¼nþ,ÏS[­²á#ùîu‹˜9ò * …É85©hé¢j)ÝP-¶Kµ¦˜øGv¬ZmÏÿ îóï­N}þA§öÒ)©„Oßß«7-‡)VpoI±œž*VöYµžxŲ0“ùlÓÔµ44Cùßô­8nÓçÜœŸf  Q.=þïdШ,K4åi!aYŠWkaõ¦šh)ÂS&iªJç|Oú 06 …ûøOÐ[‘op›˜‹4…B¢Ú)l(S§KÙ:ñÇê_Ä™•èxïãmŒIR~Qi¤N&_´ÂÅI4îh1äª6ér4©#Fo9ÐÑ$ºÛ2jú"s­à4¦Kl´VAó&Hh©È 9¼Ô–NbÅê¶"ÅD>\Ll©ÃÅŸšú0M2 ŸÚú£xQuršUŽ4É%M°ä9f÷5øýùÝzºÖöxc£b‚E+¥5(í–ˆöÄw\Ö  Ì«µÚ×?àE+¦u'Ý“®„,cäY­!·EˆÎYf©ÖÆ“åR7o:Ë “¹ít¬Ñ J>•Œ±˜¤ßqÀˆ.Ààaêü— Y|¦ÝŒ^g¿Ê©ÅM•ÅOûV¦­ äkŽEGóËz*ï*X¼¤$ûF„Œ</ßø`†äß rZÓžŠ¦uÉ­“|Ï;§æ‰ðN4ì(à3Xa€²Ãw£ÄVhbOPL¨=¡qZgóu²stÞ×.ªaMðÅlNÄð¾¯}1~wàÝz!̉fêLwdCLˆ%3U&l›t­oÛ¹C¡Yö™‚N­Ò› À¾#ÖÉMÙõ´q>—¾®-`%ØÐ˜#ˆ‡=pÆX%2²çxC=õ«D*`¯Ô†Ó[ªp2†Þ4¡cpûz¬ßc<°ŠB/–£¯-0ŠÑ k[IO ‘7j€õoX9ø-ü„à ¾)ŒeѦ‚3$E/qXíGÆñæ8 [ýßRãë9«}>•Šâ Ç“›¡'åã¡pßçÉŒ9ÐxSðSñ Þ¾í3^Ɔƒ“xÀ0;7C(ÄQ#é¹)IæBøšTĸ$n›wJ¿¬Y|`O‚÷h½Ì*î­¶Û øÆ¦XQ”1(é9±¥Û“¡4Hñfލ*äóà½ûgI8ÝU–~fÄ,-hlÌ´¢ÚW),´-(rXÄ;ª rI®aaI…B´Ä#P^ø¦ùæÝ?®Àø x )9øÁ–·àY¿o]CÀú¾°d¤iŽmi&öUÔ“;RãÞ(üLnÅP…I⤶„ÉñX&0ž”c&ò›gÞ Â4Œ« ÚÊÊ0ru Ìu8•ÿ±Ò˜¨ò™8Ýý#ïnšf²¦$vÉÌImB–lÍÿ—\“êëu-$€D\ð¦”)aŽ“2îN,¢¯Rž™öp¤…,OÝŒËI㤺êçèÝåž¶›o}˜;ÀÜ„×d w²˜Ç© ‚C)ì4ÑÌr4¤¾ S‹RÁÑšâžMk¤Id¾ZªÃމùa*ø‹©ž©GäŒ5ë,sYøì]Åäjk’ªÁz@½ÊF\U¥•ŠU£dƇã5ôâ”1I² ÑM»ÍrW÷–94tÈþåqŸ ©ëÓêjƒ|/þ瓳ßìYf°³‚³ÑŲ¤ç\ãn¤ìy¤–#²dâb±K2¶VÆÆwòõè mÂ…6ò㿾Èà‚®“Š JIk­¸Îµåöþm‹ÞW¹#Ëm¤pgݨjØ1oÍS:Þ4(#üy¶OýýÖÚ÷ ùí  YMݶŸTûž P#ù;k¤XÒÈ‚ÄÉÀ˜lÃBá—è-y’÷X+Åÿ¾V^dÙ§ú;R͙בҞ·j_"ÜlÿyRãU£îŽÓ-Ì«}ŸÄW`|Ȳÿ¶h`5ašF4ËcÏsW¢«O§&Á©`$¶úâ'|óìv<„¹c¨§oºÐˆc«1IÎdÃ9cbÙ¹ÎÙ§'ÜŽ‚@ H[±h|â¾¾Á›ÛvèÞ¢I|N©î÷1°¿QâÈ$¿™‘“·œU渼VpM ’œ¾€ÃsÒ=ž¬`rOß ‡•*– †Ó­Inj<°À"=°À%FK MŸSU‹wÜ^4ø~ùš©rj^±‘ð¾Dvóë:æÕðG$ÔûÏ>ŽÍå¡t~à©xêžÚ†§>;;ù+üùºkÿendstream endobj 318 0 obj 3895 endobj 322 0 obj <> stream xœí\YoÇ~'ü#ø¦Ý@õ}$H;–8‚ìXŒ“@öʤ(!)Y¦,ýûTõYÝÓ³‡L?$1 Ñ»³}ÖùUuõ¼9f?fø_úÿÙ«£ßÚãË·GìøKøwyô戇Çég¯Ž?;…F’ÓÉ3ÏOŸÅÞüØŠcãÔÄÅñé«£§+³Ö«i-&k­\ÙðåÄ:? æV_¬%<7Z¯þ²>á“sÞëÕéúž:Îäê |”zRZ®>] ü _”‚FŽWØU*è+Ã'Á&gMhþþ}Ž#˜‰3³úl­&)¹6t2lóéšOÞ;åWß®……K³úöóƒEž®a7‚…5ä†q,åÅêÑúD¬âĤ$Ì'íä¼äÐØ³¦ï‰Ô,Mí9³«@‹¯q9 áéæþÞÍ#Œƒ¥I—†} ‡0†4ŒD³Þs:îî!~UJ*—§–ÿpúðXDø§´˜žžÛ4¬þņÊц'ŠóI¨ãÉ&˽¾€„e¬¾Ä?Äç«§øç3üƒLZ}…þŠt¡Ilü~ý~…oñÏ5·èÌêeiôS}x¿<¼¬,oêÃÛòðõÚÁÍ-é}MÚÉ; âwU~¾ª?¿+7a«8ix¿6 ¶Nd²ÜÑdVdNHÚ=/ª&²ªÕu Øm4˜¬ò´ùýúÄFHë ™«¬ÉmÕ¤­H]¼V¸cä8:TB´è†­±Ùw€›Ì"ˆö .Ä‚{‹åšK‰®ñ¼82Ç+ä–1Ö¨´,Æ3¥; Õ>7•ØfSD~Œ¨…¯¤OJR(‘ftQ†•Ñík¥‰xÞD4â~Ù ‚2Iá¨6%2,. ¯àì&KL$ÒÉHÒFúmxÄhUÀI’*ýbÀÌ3ìN:@ž‚4ÄÙÞâ/@;¥‚‰C6 Êúú —)ð‹Î,ªªØ*ÄLÐgÊsžÖcZýÎk\’\)4p™“©6C;EÆDFK²e²Z\"®T èLÑe]¹å‘MI $¸x@› ·a‰~Q×ÊAO@ “8)òt­dÏ5Žñ*§…?UV²<Ÿ'~€­ªÍ_×ßû)¸—baßæƒR$bµ~0 ‹´'<ÕÊQÊ8A sÕúŒÐý˜wAìfB–€°QXh g4lÔM2‰äb輯6ò#­™‡‰äašÅ€Á†Ú ×Q“À>õ£ “dÃ0ë΄fQúY4¨u=d¯õ‡‘ÿ¼Œ‹D”„*ø°á®à´sdÇ}5 p> J;W'[¼ÌŒ²áZ'“è\zàÒ##PŒhɵ̋k•€¨ï¡$B%7 ³0ü)¬u/ê(yäè^"Aƒ&éì_fnb†.:…þ(3W„Îø"Å)îA•èL;"Vj®c ˆ©­j=‰È¸ñ'Ò#eÄØ’ãÈçiÍ&»@Œå¤¦JDú–mU­Ÿ†ÂæÖ@)À3@—›>.qêÍZ7CDÒè±"eÊpÌ&,éZ^Dƒ¼"ÍŒ™S38òîøNðè.ˆÕ%’DÆð¼þÐèA¶Ë0ÚÀ-fh7”ó!ºšz~$Ñ£u$·¤¨*˜²6“ Ý ÊcÁÛï“ÐÁ¡viLör âDe,ÊÌÉ'Lr,¯s`—Ó:ïyPÑØuň&¸.î×Á`^j fuN‡^ —lüÔ9ómÓHo\¯[-ê¬WQ @¯˜ÊZp1’šhK:®Z!C' ŽPkIäŸ@±Æü×åq&"X=¢cC?@„¼Š1n×tðŠÓr6Õ¤)!®¬JYr‰­ QI”ó,–1®è(þ<’èÚeÙ:Kà™*ó “J`Ú›ù„]±Fö~ }¬{Ñqt"/ËH›0aä$6½m8ªmm›ôÍL΂ÿ¢J’`àˆËi¢ ‘\-ÒÌvE‹•– FÛð\"Õ!q8tŠqÇ»µVø¥.®Í F¨ûCâ1["—|@$òÀeåÐsäŠfª8‘%‡!\mŒ% 6}O%©>0ÝiÎAGýLà('µ09O²g…‰•ކBKñ QŒ›ØÛ;3ɲàÔÀÊý"äê€_vºïéW2Y_¦äÇž¤TוIÀgD=š“ƒÁûòqöìMã‘h@t–Ÿû¹ªN•ÜY@€êDÒš8.ˉ°¬Mcm1°›Ö0¶ ,¼‚†n4uJk:¶n‡2ϳ0ß{[µçu ¯Ë~lÔ²©vÂ' eyßšiÌ£P!möñIà¸ÕÉxðºáZÃ>–Æíéܲƒì…¢+™{Š6‘œæ˜«P…1IT%ÀQæí²§”vè{ ¢¡ úcŠ—"¹ïí¡g[p¦žq3‚ÍGÃ-¨¬‡œHîPÓæææ!Ó¦Àµp¹Å_…¼ON“?¯…'¤I„I®KåÕ5VgUŸu.´7‰²­[J$>† {x¡ rÒíå<–Ó,wsŒR.°ÂacŸx‘@âK|È}=ùÅ‘¾+±øûÖY¶)£hb$!Í®kË<07»LÆÁFÛóbÃÀÏÙ¢ÑΠ&æ”ñ´°U-l P›pádÁ‘Q¬³ÔÚœ€ËÉ­{!9#2ã=ì ‹àÔet©„M Š\(ŒÊŸhR?GT®®,¥AQú”Cž¥’ ¦ÊÝ'•LØ(CD³Å ¥#™a<`‚£-ù~B5𷶆éÝ~KX¸'Hà˜„b*–¬4Ùe‚EmSl)Ïiä•Ú¢¬à F ½‡/J½O toÁvDqf2E3Ú¿Xw³”˜ïá!õ½šÀ6ÖÕ³6m0ÑXd—†M¡û¥ãýÌ CÄ»PAï¯É|¢FqX@ÊËà×?®K‰ˆ50'‰V-R#f3e•¤ ‡ C<£º’3Ć‹ºüJ!ãÀ äEuMž!¬á—¹*[xòOˆÑpu)ïV䎺Ï{XŽI¬Þ-;,òêÄ4ìul"®%¼ú¥Éä|ik5L·ÒpZ2Þµ?uÕVg Uºh’_8žªc°ÎáÀ(?жÚ¨ÕdëšS®Ñe[Oü3:¦Q<ù¤Ó¢Ù+1¦ÛꊙÅÓÑ{ €JÐ8ª=ñ»óLÂ0Ù·ó4–&zZ'ßÐz`“µëOGÎÍx¿Òß¹K æô ¨4!qbÜ«í¹STE"˜aàViA`Ñ‹¼S1Šk“Êr"p…iû…3•Ç÷Òn™¾3´–{MMqK"][Ýò4Knª™ÀTZëßÃÂLU%ç KؘAè#„àBf@}Áôˆä '52Ýžçr’OÈAÅr¤e"Tº¸/,àsÐÁÎOÕpsû ½ÜB:mvx×ú Ä—FØ>áá¼Ý01âlFÏXL¸ùaÌ;"ÎÞ6j-LLPow<ûÔ^eúêÊ;k1 ß§L,ǤÁ׸8™¥ š"-«ÛH+dí´œ×71²¡>ï)׺‚°¡ò©‚3s×€‰äÜ«ø_ü}vV˜†Øà3š”* —íG.‚jÉxá2\·²; *C—ÕÍÙ}éˆÛ›„@Αœõ>Ú·=;yº³àµ¬\"ø!}ˆµ´BÑZÚXBûèèôwOÔË•^ËQÉ-/šöM,×Ü´ËV™’GX.û{6€Ò•ù{:‚¤f~{4ŒõŠn4Ê1 wöû!†Ý"“ÊÉ]1æ–³¾²›CcJÊîö*,Õ¡ÇÄÒiãï¯"|ƒ0Lˆ%Ùøé¿é*¦ê¿/?·eóåÚ)ºŸ—§×Þ¥!í\>/¾M8§Þ}x;¢ÅUi¸0bžð‚t™]Ex;º_°iÈÜ}Œºš›~h–°&•x«@ƒ¢el ü»k ±Î•²opq!äcã‘a †Ù4EþhŸÌ.ûM¶ëpt´NÌë”ÊéîÐ:1Q¶Z§t,ô+Z§°/¿ý«ü°¢õ€#™¹iâ³êÖ=R]:æë5¬qÙeÝs“DRn'3G}9¯Ì<ÕÌì.ï űÖt!Sª _ ™RÕêžR[ÚÞ±^‘O)émúbÅ”V'y…yø”Îp\.t®R…Fñ„&€Øè¶erÎÜrzÀr£C,ŸÜ•ªIØ&~-¡¦éÑϽ¹K]1)úœsz\†A£j"Éo©͇â'” %P á‚Hb’%J.$Æ*ÍN}è…x2 ­œß ¿©,8cƒk9gc aBÔÑãÈœÈV:dãH­évN5*MúIýùzðs¾a!ÝÔrfrµáÐè"X“ÕI…f‚†hÅç°©Fc]FXç.šfüHú9b;§ÄÜqp˜Ô_v7L+¬ûî7X÷?ëÈ0„fgµé[z vÐô6ß0%·vÛ ¼s€xÕD£'\òòµSrtêb$‘ ¢#vl¨PÔ ¨•[ƒ>oG²¹¡ëÔyŸ NÓNfà”Ü@­aâSû±øÔ²‰ózdnÜ]ãS#wãÓäš~E|öµ Ÿ‚4mŧɉmŧi+cT­b…ǧ£æeK6&ö=€/>©Ÿ `ãÖЧ×Ӕݚ4j€a÷Lûï‹añ$Ù‰aÛ|=úÀÎÇîQG¢lÈ‘ìÊÖƒâq9\Ìv‡Éä2DMƒƒ£]G¾X+Û/póû[yÄtä"ìJ\˜\J®Žª. Ùs©@âýòjà+üNgyCRåƒ0 •=³Z%·H’¥ñÌz¢‹“¥úu[~êDXNDÃj½Ýd¾ø Èüße0™âöyÕÅÇ`Žçdùƒ>—åỼ¸3u×+5î Ñ{3K€ÔL£2¢Á3Š2kä—· Ü9¬ÒìØþ¡ÅWâ €­F.â*ÓbhŠ)—«Üôil8Ä×Ó0“Ê[ÞF{ðQ®CC#0@th5³a@ŘÐ.&ªE@'u¤ |s T –>œÕ¦©Iïë$6užäÅ•IŽØ6=J“®hçÚp4Ëuî|O¼Š'ÐÙJ>Š„NY¹rì6 ÀÓ¢[ˆâ‹Ò-h» ‘|¼Ã3Ì`½Zï¥Pƒóãüº¼Ã(Êɶbñ4¾Á캑œ ÚoÙdDÆp&ÞUêŒòƒè´•8aDí<®—ýå+ÉuÚy% Šíí…¦8ø^H³G]¼äÞ¿<‡¼hïðf+€Œ<š›­ñúµ!7ò2S퀩ˆéSÌy ’Ê@ nJ±ùø~æÈË+rÔlQñŠhýaPWÑ•!àÅÃú  -À˪r·pÇ—Ò‰Õ?áy›9³ëp•ñú¿ÕnHB,æ'·0Óò2%ô<Æab¬Vé•üW°íÍ-y?­ÙýXx dc—FeL ð ¹ÝruX‡_e}ÏZØ|,Œg¸é^FžW×Z!/à WUS¬O4‰¤Y ‘÷¼ÓÖÒ×]švGe=ö÷®éçÒ”[5ûÂbm‘2’+kFr¶Ñ6ÏHrEÔ.¶[m éÛ!(OšªÝ‡§GƒÿþFýoÛendstream endobj 323 0 obj 5064 endobj 327 0 obj <> stream xœí][“·q~gü#¶Ê:ÇÅ=ÜI%©X²§$ÆW¹Tœ‡%צYZîR&WóëÓÝ@ æÜ¸ôSJ¥åÙ9\Ý_ÝÀþp1íÔÅ„ÿå_¾yòëoÃÅ«wO¦‹¯àÿWO~x¢¨ÀEþç囋ß\A!¥áÉ.NQ]\ýéIz[]}ág»ƒ/¯Þ<ùïۺߺÿ¹úxèæ wÓ /]Ý@ÁÏ·—fBŒjóÏ[µ‹q¶qóO[½ùýöRí¬uAo®j™ß¦§ÆÎ›oᩊPmÀ–6;øFë¸Ó ^犾ؚ°›Cô›ß*Og'¾}Í|¾¨[üžÚ°SÊn~‡O稠,¿ì –‡¾LPÈ©Yo¾„–°È -—˜5T/¯¸¸y¾½tðnPóæ»­ÞM“ƒ~ÿfkwFCQ¨Ïh˜Kã7ÿНk­½¯j¹{P/uOô)7¡ƒJ«`g¹ 0YP¯½¸4Ó.¨Ój| S훯ðÇ3lgš”¢ÉÞüþøÃ>à;üñ¼ÇO·—vX~óÐ6Tc*”êøËöRãÌÏ~s_þT¾+¡&7”Àœ×‡ïkÉëÑÇòð]}ø‡-?ÅI€uq~ýúÉÕ¯Ží×åÇhÜ¥yðZµ4x=5ðÛúð¶›Ç‰½Ãÿ|ï [ì—£1ßþ5û×ß‚xK‰·n7›8ƒÈ«,(òzkRéN¯¹]Ä2YM}µ… §æ¨7„Mj-¨êNP $pJÌz[óÏi×Ùè ä¥vqç`»×ï¯AU½¨enaO‡ ž¡_ÖÁÔq ÷[Q⡾õÇìý<θ…jaÿßmu€ ¦®(,ÑÖ`«få£}ƒ6–DÓ…±×;Œ¡NÞÕ:n¸(Ÿb¡Ü‘à­¨—'Gð'|ÝSß—&ºy ÌÓœ‡Ž•:¶X†®q3±VcïP!ÂÌu=`¬‹a 5ï´‰¼äeù¬l‹§Qàž|‰öT¬çfQ¡§™˜’hÂq¡Ì(õ–ø5,:Ë=Á÷Þ…ÍƧ(e¬´hµ4 ú%^¾-•·å×p¬ öAYù‹KT‰0;iÈãÕE1«RvÖÂæ“ÄfHMe9ýäiÞ´§Q'öv†íè{^{2åÌQ"‰+ai¤T¤,­±´¡"\#b^E’ßüE}x7ú÷††Ç0Û/Êþû€Íi˜#³.ñ¹Q'ÄÇÿ*å÷ðÛ~—[Qú¡Ì”ú€pZGàóÓA‘¦5<(='¡×g…ž'Ê«VFi²ÂFàËp¾D=‚˜¸òvG,L­î5/ÛpGòR„¤ÿÞ%1ŸÀBÎ- E›Þ¨PúüXà¯åºšõM«é¥Š ŠÛ!í§²`‚¨ßWÛ‹oˆ¾Ö ™z=EÑv-™<ޏÕïlC Õq-·Àm^bØb#E- *ùï±G.Ù@ç\+ßE”ü”â¥Nlêë.†Œ›j¿N ÿ>qbCŸ…¦ƒÇ—_Ôi~±s–}»‚´¸\šÇØo¹7 *ú9•Ä*„Ñà‚h `raÑâÃРñ«òTÅ-‹¤ž'œ­ª•Z¤TP¾ˆ÷Ê -ˆüÞýD Ñ #",GBànRì²ã÷èòV™ä>MA«õÅžj„Ô ™ôAoH°Ô‡*ú¢¤¨“±žÓëÎ@Ô¤•ÎÅé ¨²‰c‚’«rB­é1vÅâ ìŠ/Ždü-†\ÛSñ¹™HìVðùbs }¯¡»èÌ͆&7Î4¹½lPI6"˜@Aç<Ë Þî¼å-ñ +’НӦèªNèBºe—šÍñP…[¼«O‹<¸Uó€-9ïØ\FP¼êPp6Y硵¢¾&| ‡Ïr.ù)kbÃÈnŽ‘zd]XÃ3OÎÒwÏë«CNJ>EæA;2‡Íßc…É í¸oUdÅÖ{‰vÒÎGÂcÜ^Ÿ4ÍØ2õzµ×/tê¨òãv§½ì"Ò†U9ßfN¼g1Gîh¥Zm’šÊúºxÈ$þEÐ/¡ÆLÓÜ¢´üí!x2²! æúYˆ™ñ:à29á°¬z˜ð<Ì‘¾z[K6vüÒÂèÕÉ;À:ô3œ\OîO]À*kK/}¬äkÐ` ‡X2B­ Bøë-Ø:rDƬô7ð¾÷½p¾†ÞÀ#úko"…c‰uŠßa×4‰­èš‚î—â“Üc¯Û ¼P€Â·Ìc,nE’eØ@¡Èr«3iž­cŠ2IWCogò»ö*Ø´rެuÁìþ>'MÝü8ÿ*#áªjûù0AÊö{wN¾ábGbkÞNÚÃØöÃÒ7؆&öd‹>ÍDÏ4—o¦„@Äêk^}…±Ÿ ׊Ã0âÜê8v{?à÷!;RÁVtT7ŽNîtê|ƒ*^W7&¸É“ëEý÷#\džcÈ<ù3€0& µ›*Y’«Ò~îEoÁÔ €ÛHE2Æy"±ä¯¶äe[ èUÏ›D±`ég[Bé~!~Yg«âòÚ—òÐoÓ4gÒºå_3œHƒk]F¹ ¼ ¥Õꂚ` K·› _P¦å‚Âö`v€^\âÏ„ÎT¸)[ÜxGˆeÕðScnÌ. ^0côzƒ Agzù>@ÐkQn³“ðsÀºgÀã[™Ì$è~7OEÐóš$:OkÃK>°_q…K8‚׉Œ`ÇMBÖ3náÆàĺEÈõwÈE!7‚.Ì➆Øêo±æey_Ia­š»8‡²ùði a¼ðM.¸e¡»ÅÐqÏM X§€Dâ}dªõÕ:kö½7Eò¬†›ç0e‰½Bim !×Ëžvjœr…Œ¤|_‡ÿ]¿áùÿÌnDlX{jà¿Õë:ZŒ…giï:ŽÏºc@‹Ê% Òßf?jZ¡B¸E7o>+u qø,C¶P-‡.¦ó4ƒ”X“4­î…<ÙÛ1¼`wÝûLʸHLFˆb~HºB{€¬rËpc…Eè´ãFVLy#wu¢P4Fø½¥&™ˆÚyä„Ô*G ¤fJ}E#Úüo©cØ™ûÄLê¼’à‡l~% ÇCf^•âë Ô >{|Ãôà6<R ÈŠ_r>ËØgr%Þ@¢Ññ#‚·’NÏ3uIº•­ÅBºá+Rý#e(ØóWÛ6ÊÞã£Sé`B@k´JŸÃ¬[ ¼ü»¥âꥌ/ 8Ä‚ì­ë6+CÇ!䋵>ñ½/! ]«o°L-Ý)`w¾" Ôwk—‰ Š«ný8 #Äuï…£w°Kš.€õÅ@7òX¤½Ö%ÙÄhÓr3²DÇ´$Í"p”FÞÚ‚¬îPÒ&¨'DÚèM¬ž㟘B߈Ê_À ÐœealZÂ*¯? ­ß1+‚Êéì8¾øk‹ä¡"ñƒ—ÁŒ@´i @P“c.¸ì4#1ø`DJ"¥R-Y9ª Äë‹-aXø$òËÛ< ’{kD!8ñ~Â@`3YÜ—ÚXM(ÁåM•£„cåw§Û±O´^+Tfý b`Æv\ý-/ùŠÆXÓëäàãËQ,‹ u¼0Á׬ŠáÙRÎK²<Í”w%|«\ÞÚ¡ÁuäT·¬{ á6“ÐÑ7<†°’ƒÂI‘8’N[– 8þ¦ ¤å”žÉÙ£÷åˆåµ´ÐZRQ‰~-ƒ@§¦pe(»Škš~}T~V ©sí RH §~B„H@l" JÇ€ññxÿÕEò_ó%˜’œsrò;Ù^âõ‡EgDDn‘³ECÌÙ`m¦#Q n=q+ ~[Öf<4ðÃGåÇ­³ ôÜæ_< [9ŸHŸšž)F‚'èó$P]«ü%SzM Ë}j|"ÎÁQˆ|.¤K Òujyê”A4¹Æ§ïâ¡k}‹}yÜÉ’Ú•‡Ñ"”eb†2kß²çãD”He£xÐV—y™=éeþ— ¡ /×>ÎÄø´¿›§„Þg›fø>­Å8-ñ&ï £×Å—¢*wmoŒ}¨9ÑÜ"ý!–æh4tgop.Ðc+“½ÄûÛ„ä„£Ç!×£eÉN‰†³TÇCôý¶v¥V‹<ÖŒ´½ðT{0Ó@itG“œK²LlB¡±Ð…]bªU› ÂN£mYöè ;3bØ®·†TƒmWéßÕäKjäP&ËžX/~lc½”o¤Õéj:ñ;ñH5S8êÈã}h¥3ìfS²ñûœ·‚R³T¼SŠ9æÖ¸=)¹yÚîäÓ†”WѤS Ñ€~:•)Y¡8±Ç{#®"„ÊÃne~/¿Í€ Ç™lË;óˆ>¡ÓK@qbÊWOå¢èÿ†ÄEäCaS˜$£ž“MTÍ~IÊÑÎD® wBƒ‰œ!Lúve£_jy–b½b?´•éLªÑ…×ýÔO3‹;+Þð^äRôS}œ£™ByWÙ BÅÇŠ1Dì²I•­ÚtœÊËŒƒÛ/”Ù¹Ÿe¡ûº(Ú®ÙWR“¢Ð·û’?[ û­Ý(u7»¤¡(ý‚d>™`šÄ½¸l'îâ=ÌÑöÑàù‰µF'ã.TcŒ˜.бѬDZà±´#³¬ìþCJŸ‚KZ‚YD¢4§± á ²M¢ WIMÛñ†ŸâÌÓY¹Ð*û”97l·~/<õ$ ´%±Pž†“Wœoˆ+iæ}Èà4ÑÆüÖ}¯õW/àûšêPDp‘W0p›m:#ó(òãÓq‰˜³ï¾bòäF[&Ù £?KÓf9Œ^¯™M˜ÞI—ñ@´øm6¾R’’Ý¡™tA&Ú׳~L_OFœ…³l o'§ñ 7Q¦0ä4¹5ËGz«þ†„팹`S…xe‰ È÷hOme£áw}¬¶P†Žl©#›Z’-<ˆLÌ€òÈ|ÏH˜ÅBݧ%êºZe‡ävÄMbæ³™‚o&Œ2C¦ì[Ÿ›dsfF‘°9ã…U¥Lž¿ž Hâ?ÍG¤:©‰¼ñ»ÙŠ3Lìnw¤‹`Ž…,9¿xžf!-md_Žl/™ÊÖ{Í,ez‹cyt­Æ×Y–c…›Ã0§`óvç;øªÍhËÚ#f ¯RCtͧ0§k0M¥Ò-)V›4²_ÙE,ÛÊQþêªAÁlîr&ƒ‚ÈNd=Ͼ:`›ç#üµÔ²#Í‘ÑìôÎË´ñÔû–òÏãÌòdÝ<€Í2#ɯðS<7ÚÓ¾ßw´³ˆÌ<â'j͇>Xý=Í ÓÌmúÏjÅ a¬³R]:…j޽†Ž˜õ€ç ü&<ðQìXDÄ~m`a§@2¯qL*F9+PblÃ<‰Ã9 s²¤-rIvÛùÕ‘)Í>kl2…C‚C§.Ou5ñƒ}‡Ëm°}RЈ¹ošºÖ6qŸÆ‹=¢1RÁÑÍpã6ßó`„¾mǵÂð°F3º&ÖsviÊå÷x'ðg\L^ƒ:#+@·Ü0é-„³ú}mÄx‚îŒ=±ï°è÷•·ËÙýÔñd}Š£®‰Qƒ{ øÈÖ  @ÊoœfôªUˆå¹ˆôN" ìzOiÍú›ƒÀºyºCÅcúìèÚ ŠnÓå,x²‹N¬ì¿I¦Þc[м‡¹¸-F<¼+ŸÖ‡/ËÃûú°Þ¥ó~‹ÌeÎ'={S ¾ÝRŠëdÄ+×õë÷¢t€Ma÷|éÏæïêÇQûu.þŠ÷uËõìÿ—k°\×£öÿ(‡täÅGuêÃ7ƒŠÞ5Áèåƒ(˜…9‹8®±üÝÈ“oFBZ7êt1RQvæc.F¢£v{.FJY‡±Çší ø œ‚ Ê}¼e]¥ÔIã¨"ΠÓÓ.M5Ê©ž!e.šÎèéêÊFƒ­YVW‹³z|ú€œC<ôƒmiM×.½è껡uA³€©Žä^¨¿ó`x䘪Ë5Nmù©˜ã#ɂÌQëÜȹr×ÂÒç?þ8µXØ’GHËÔ]¥to#ùröä£û^0˜Ù¬’7p\¤Ðn9û° Ò=#6ûÎçÙ“LÎV›njkÉñìÁJtnQäÁ- ˆôC{·ú:éR‘?ùøÕ©û–Ÿ2%ÓœS|¾@cæU´H[ôЮܫáÝ5 }ýT„jóMâ§Œ5#7‚“ª©¯Ñº?Ð$kÄ#½ÊdÎD—ô®¢¶?aFÀà|Ç(`•®˜RÐò»­5UVxà.ÕMÞÆ…r"íäîA¤)o¡äjëaÔ´.š •4-ö†¸j˜V>t“ÊrÄq¦£^5Ð(Žä¦£ „Aò!¨ÛÁñ ÙA™§œ¼ŠouŒ» Ø^ÿu÷WŒô__œªèœ¾thÎË]õçºÄE?v×YÉÔx™Å¶dÍë Žªæ‡\`V_ÈQµ'¬ØÐAç¹Óããz),’çErƒ8X–®9¸Í0caœ}ww“LÀãÄD ô4nÔ¶)÷Ö$['A<*=Çp¡¦?FŸwpN1Gâठ.þâ³õ½‹<”ÊBRìCÊMo¯¦³ -ð,Ì*e’gHps,‚ÆļjÃ_ ¶X½?¯¿ìì[ Ò±Ûë!RHºÃÝ 0ƒ¹IŽÀáˆåº‚G8§g| 3_Yr ­€R~×aŽðblÃÚ¼÷è"ìäc.´^E\Õ(¤y\½A¯´Óœ¢àsÛΗ<2q•b#{|E ›‡M™Õ3æ–eT•r[”‘B{ÒÑ'C—U`÷^1)ÒÆx”D2›JÎ(ÔlIT7ŠD„@Í>RiR}²¯NéPÏŠ.n³tKÛ•ôÞ.]úè,²ó/¿ËW èêÙ™ùr[Þ^ãSÛ]Z‘ükqU£ßV@WödKo"›“CéÝ‹ì-ÅÈ•\܇gbBR]”µ¨¡3ô¹¨êÃ"qvyšÝ¿j¾ðøwV»q^u—¦%ÄôCÍ ÎaÆtà¸Æ‘¥ž«‰65Dyc“ÿúM²Þ*Æ1ˆ„²;ä?s Ì[))ò†;ÇwŒ¬‡aŽÃ”•ñ5žSÔéXr£.­imëáøú}õgm”shϽËF “vûôS\uÀîµAÙ¬‚š†ñÉiLlt«M0kã =ÚcG¥8r’®ÒjDÑ,½6"Y.ÙkoÀ!}=@ÊÛnxv ±å÷ íãFWœ¢«aT> _\¾ç¢ØMUöL]O·qa–íYzž|ܵ¯Gð‘ùžÔN«–øÎ>z›U@ ³oóà8 ðØýK㎗*Ñï³ìïX»¦#Q2ñä›xÆju‚=UzÑÁÓûèžÕÁ|±§Ý¼K§íJÁ>ǽ^( KJÈ0ÇýÔsI|#ÏÁs"*%æ‹Ö9gj¯3¹ð ‘¼*DÔŠò·Ù)ä4 Q'ÅY‘JDɳ"HëiQ)/.ç))/5§z满NRÎÉÍêú²³+·âÕûE"ì*——8F+ Ô wÂlwY k×ÙOêØ?wP«–÷×'+)×á-®wÜç†HZpt·?3L_bT‡.ÍR‚Zv²:¿Ryij2”$w½ÇjçhÏøPjs ²#kqÔ5åÀïþ{¹^mWÒÿþý®ô—V¯´INi쓜ä}}ä¡_GHÜÃøo%$¯眅|Ÿ”‰%纞”…Èçt[ÜxÞïÑåŸåIÑ£tBIæQ´B-2Eëe"“4uɦ›ªùÖdqQsÍ2¯47kˆ§2-]\ÃW˜ RwäCs§]"ÄŽ¸Ž.t8t†Gïòv >ÜTeào¶ÞÜ¡KÒZ`J Rņµö°§•׊ÖÛzLóØŠ§X=TQ±Œ¯ïé·WOþ þû?BÓ¬Ãendstream endobj 328 0 obj 6248 endobj 332 0 obj <> stream xœí\YoÇ~gü#øÆ€;îûò‰¶cË 'ÎÃZ´H!I‹¢%û×§ªÏꙞ=HYp‚@´ÛÓÓ]]]]õÕÑûã1ù1Ã?éÿ'/ŽÞl/nØñ§ð÷âèÇ#:§ÿž¼8þà :I-£gžŸ==Šoóc+ŽS#Çg/Žþ¹2ƒ^ƒ­µre×µu~Ì­>$´­WÖ|tÎ{½:ÖÐê8“«oà£Ô£Òrõhø¾(>ŒWøªTð® Ÿ5¡û—ð÷#ÁŒœ™Õƒ¥äÚÐɰϣÞ;åWgpiVßâ{~d@äÙ«,Ð;Ʊ”«Ï‡µX}Œ$ˆQI˜OÚÑyÉ¡³gÍ»k©YšÚsfWï/þ‚ÓÈQO÷×É<Â8 MŠH¾ocHÇÈ4ë=§Sàê>ƯJIåòÂò}û[DöOi;2[xvÛ¦:Ø-ì¸VÂN¯%-÷>v ÛtÇ5Àä"¿5ìõ-N¬µ5Z<çB¬ž”O×0ÁU}ñùcá‹^½Ö™»Øé®vzòâœ|õ,KÔUe[å÷DLÈ$bÖXÊ"“¯#7•kx˜·Ÿë:ÓmÜd­]Zyüa4ÆUÛžç›!,Kj 3‰R!ÕêͰfH§õ&ñ[ë󛺼Wø>Ðä]⃕…õøçÀ>ʜ؆CRNÞ·LYØ2A(ÀÁš DAÌpº“„àÞ-vÍ%¬Š‰¸f"šUÚªTQ%=‰ˆÂ¼ø…Ç£¾Õî…€=FºNòþÕ‰~ŒÂ"Œµy*|©ìôOŒm=üÊøf€)QN`J+ÂY9Ÿ Sî³ daƒuÁÍêg"¶ ¢Òx1QÈ7z«ˆ‚9—ÍÑ l1z~žÛópÞ{ Âx Ai¯#-ŒY*Èô¹n·3q¾=%( ÂRÅX:::n{r&¬oh4i›Œp“óA¤¶È:™”šp «`„MÕØÇÖÙB[¯³ ̾êŒ^ŽOo>r 7•Wh‹ê‘©Ä‰Ç'1-í]äÝ’Ì«pÈ Õv—QTm8}¢ÎÙ¬c¢&%²Ì•.¹¾8ãä›8#÷$ÒL7ód‘æ²PgEVx †’ J¸,FÓÚj8¢[™j¸“ ’ÿéîIô½ëŠ[¤$ÊiRæá«Ñ{‡Ùô¾1)¡MË%.DsaF“MµÃ ŸËQÜ7HB(Kô?þ}•ÛŽ)A0Éø(¸‡<‡ÁêR„6¢ô¥¶G&¦á¦? ŒZɉŠ/)å¤HVר‰ J« œ ¾=ÁÇ pa¥-êíg¢!-Úqëƒol;¶)f5Qß}ß± Wía [ý3Ž¡5_ÓaˆXâÚ‚šœèu4©V‡'Hõ!;¢óÏ‘#¼â*Œ þGüˆÇ¸¸HTrž™ÐÀµàj»2C;<¯23¯4…Ìy.eÊ\pœ$Ì""â ‹‹¬yàSP ”i" —¥ZöÉô;VY",»'‰2Èl5mµù¿ªí ;[ÞÔ?!ß@;Њ€´o\˜bù[DEÛ—@´÷Ö˜3×’ˆžˆ–,ï_%93eÙÀ¢„1‰‚#BJ4œå&˜Fð8kHœã£:C¡øí%2X Ë’y«'$ )ùÞ'$8“\Üû„d9;M6¯ Rž/yµ\¦ǺþõŰàœgë±ÿÁ¯Ë ɃT·vy…?4 0Dƒ # ù¦§é‰òî‰ã¦¥¢jgáXT@‚ۄƪ#Òàl”y1%‰­-ézÉÃi 1 å¾ëþU5ÃÉ"«h{¥.¶_°Úm8 N`W;†aäý—i$  Qòáà:‰Hg 5 àU¥g1À"¢™ßOõâKsÕ;—úÀK½[¾U}¨c{ÄÉÍ$ïÔ¤q—˜šjL|å(¡R{hôLHEÞE_*ÌDùˆ@(-¢UäE¾ºÁ›ÆbŸ¤¸á= ynÍr#¬Ê5r‡8 ÎŽË>Ñ:œÕ§ùêoÅV®¾[á¿wøŠlÁZ ä3ö~‚_¯ñŸç©Ÿ@qwÁt¤>/j#Yƒ†Â¯þ„j èóç©ë¦v}Õk|R¯kc}ý‡òé´>~IçÆ›^ã¦4¾ê ôº4>ëMþª6^ö^¿%=Aؘ涱rÎŽ`[™$¯|7”縻EÈ>?:û=ÝLÌĸrx-´}ûÿÍüMoæû…¢Gu ªÅI°€ä¸ªAöò&àz”ƒ¤:£vžYVü'ënœëø#Ê’ær`˜ I@Í1C#éé‚çf0å³NG»]†8ï¥Y.—¶`v­CôkSë5޵CUbn¤Q•1TטñËþê„’$ZŸÚŒÞËßéÄÔÃ$X=¯É‚·º„÷ÅzâŠÍãkd¯§1Ú¹‹Èh„ó]‹™#ç)˜»Û( £b­Q|µU]pPç=Ì bÛtÙé9šNÏb‹ö™ˆf/špýT|‡¸g{Ü‚cQ"¨ÒÄ$AÛ •æ§!T"ôm6¥ç9e'FË{ŠOöüÐÀ$¸]8UÙ™5f›&ÁÙ»AÑ &¸Am†À¼4@¿®3MõIÌ\’£³¼&ù^’"5ääd7p&¡S ³³lÌ*v…6ðÚp8ÙÙÃÕèŒY„¬Aˆ4uu>0îh§QíšfOnf‚’âÆaÝ-Rýw¼ÙB+Ê)MK¼&µµžŠ9 §Ùk"`t†ëµé}Ù®›´.±á4‡‚󈼞jй·BhíÉ fd×@ÛÉæÈ­¾Xñ'¶å0Ñaò íÎcF"J’6Fi¿söMa4Š„ñ¶¹!f*ÔâÃo°îeõ· S9‹ý'¨3±ôÔ M–íCÏg=¤vsúKŸ.[¸ë] ™¢¿>àœS[ÿÅÖ}áŸÞ þ}Šy.î&0ŒnSÞÄ~Íù\vMH«OU4!¨¡LNÛd‹OÊgr Ãʬbä1‹×/Hé…z–L1WÖb©Yd&—)Õ²-›ê|sZ—óO<†¹;Á†a†ÎFžðËB.I5%CÑ\-‡õÈO2gó@ªÿy JxßÉރΠÕ0IJ¤”š–yJ ”.RÉc<ðÅgOrïhŒ¯Ù²¸í ï4ÍaŠûÁ¼†OìѬآMM«›æÖ—†¥GZ•*¨¢á4)@êf–6=(XMãŠ3 ‹¢P…¢'¼³cê¢Ü${ÑÃZËòØIì€nÉb…¦Ðsr ÊÛ9x&v[–·9*¡`Mê H¢ÏÑžX¬ÔW5Ùæ¸U% ·»bŒ–Í)žëŸ‚n">ʦd¥„u*»HÛ¤ä%1Ò´ÐÜüÚeÛÌï£bhÞa¯1ÅFæŸÕÜä EµqšHD|Šª)ɳ\—ŽÏ›©·Ù׫žIï†~jãÓÞ”/kã òzŽòÔ·‰E¯¡¬Mèh'h¦™;‡ƒ~¡Ì˜‡·®Ë8§½ ëjï:6\ËVÂÏëãÄ+TD·e ›†éH宯J×M‘b,Ej³àWJºð³-ø%­ µUÒÍÿøA+Ç…àçà œPS!‹(Ê–yày›Iùô} CÁí1ÆT‡Â ÆBUÎÛ€AΠԾ„ T͇AÁtŠ ªÀ äù~“(hˉð•”àgqüªŠ¦V4 ɤ.?±s8Ë—X]nì4uý2I3Æq(Þy2ATSX“ëö T¨»…±mhƒýi}+.CõBL)»‡†j‘;Kb(ɲµäδbKmÊ=;ËÕ–úÙX0XêÒYKéÄjMÌsì«MÚ-ÝÕ#fcv [1þÞ¬¦f¡¦DL¢P6&PѺ‰)"ÇŸ ‡,œ"¢USŽHxPv_ÀPÆhkëü,ˆ4ÑXUŠZÛ‰JÏB-Qíu‚pCÞ£~;î­9÷%‘qR“èæ y'²*Òø®’sfMÓ3ªmDχž4Ö k·cçTw¢.0i#PþZûè:“uM´‰­)XÌÍøÂ¼J[‹ÞSKŸœWò¹n7È ŠTЊ{ÝsÃP óÛ4]ãÁM\+¨á¸¥ð÷†ˆQ},"~¸†öÝ@1õœÃeˆªÌâÊe@Ú"Õ°Æf?ðo"›1Lm]|nFSàóbýbØÂr‘ŒÒ‹õÀ¥û¼r…æ,`C JQà'i¥BìJ±u,E帶V«Ÿt`)–¿„³öjNÖ¤6§‚óÅš@<üÔ’9ü†4²X5[ß´¦c1A1=H3ã&Ƨw©ëƒòW©Ö0[3»ãj]ª–¯gfž“ÉrUz¯¶ÿaÇ<{‡¼jvòɽ brãÍÜö2…t6äâ¿L‘^DÍí1m( ð)Œl ·˜ÎP^ñ¾…Õí6TóÅ ÈÄå.T‚ñTæ…xÜÜ„?T#°EdRÓañªŠ–ä3)…Œ^°eV¯XcX(ä0ìN§À_Á¤×}ƒÀïàP=X%gK]Ù\™9e o\»T°(iw ÛŸìÑBǷɸF ¸áQsƒ÷"K"–r®OÁm ­)‹‹[±¨±ßb}­zH´¶RyÓ=Ò¨õº±×öÒF«Y둎ÑW1U$’>»¼8«†ÌÑW¬²Ô½àk&9_½êH:M]mþ€ÂÉþ›ã®w“©ŸõB¬•f7ìU×uëý~ÞQ¦WG'q×ZúwSâ®?lŸç´„$´9 Z)_ˆ-çqî %\»*Þõ&|^ƒ© å$½#D;‹»6¡ÚwmÓÓ„kyÄ=~PˆÖî¢Í‘#^Nq¼ò zÁ†Ìpr³ƒO´Sòê•v­1$j>‡¯Bv= èh±1’5òEJþ£/¬L½þ6êA¾pƒÚÉÅIé VFi»×®RÔ¹¡ã}æ]¿·°µx XÁhY -qè E§ù±§AFׯBñi… ñ»^2˜sÍUð’ñ; =1»å&…n©LµöM![(„¥L†+dbÚ„ÝÁ-¼ªë·å¸§?å5€]AßKÍ€%'%D¹É˱¶A}ÞÎ&á±…Ø H}ë$Þ#6Km¹Ç᧘¡ñ1Bñ÷Á¦)>–[ ûG B\ÓLî0§X'áÍáw˜±@ŒS_/çÅ4ùõ†íÑë(sš™Åò+åú8ä«ü‰”_}ñëáy‰V5©ozXâ¶Øð…·³¥|Ó³¸µÖ 1è%Tæ¤èë×b¹_·?ÖGl)'Ni˜+r%—ˆ;žj¡ä<Í”pz¶)1× K×Üzgø—"µ¤¤bßrÅÔýP}2ù‹%}²]ù‰¶*s9˹«¦2dáüá;ÓøƒXI3wîe·Ç…þt5²› Jö^ºÙ¥Ôn²»-X¹5ÞŠu.mÊ‘›©ÿÑûÝ*ŒÅM®ù·ÕÆõÖq›ö «ï‡äRï’l?Þ‘èsÄœ Ó¤òQ˜‘yrƒ„TEwÏÉŒöXÓ¬¦»/;Ñ °Hí<Úøš£‹O.3a Âgn;T* a½Ð±+íD’I"[,”c5·Ó£ôóИKÍÍ–ŸïâÓPKüµ?±ú;ü%?“W~fÐÓ[Á¼‚‘eÍLG$¡+’Á!¨ÃŽÔ3ªÛ¸%¸Rj'?n•i»Wáà̕˿\UÄDOônó+é§™HçšÛe}öK’–H¯ÄGh`ŒÿYš³ÜyQlΫØ4%Ÿ} þõ+Yendstream endobj 333 0 obj 4638 endobj 337 0 obj <> stream xœí\YoÇ~'Œü"/Þ5ÄñôÝý¾ãÀJ‹IX~ H]ˆ$Ò’([þõ©ª¾ª{z–KÒG†©ÝÙ>«ëøêèùþpžÄáŒÿ¥OŸ|ø;|üê`>üþ|ðý ‡éŸÓç‡C#!áÉæ ÄÞâÐÉCëõ???øvc¶fã·æ»ã?C%š6L³‡NÇgÐð“푚œ Alþ´S^‡ÍG[¹ùz{$&­“›ãÚæ³øTi¿ùžŠÃº…Ù&øEÊ0IÝó@Ÿn•›¼ vó­ðÔöë_`šOc㌟ÂSí&!ôæK|ꃀi°ýr-ØÖ2C##¼Ü|3a3)“&ð†‚JA6÷¶Gú:á7ßÊiž ¬ûã­ž”„¦0ž’@Ke7ÅîRJkYÃã:fZŒKËckJSH'â)hÏOˆãêÃ#5ON„Oãs˜Fß|‘?Á”BA6wñÏý þ½Ä?/ðÏSüóÿÜ)­Oñë9þy–ÚI$¹·Ô/¶y^Þ=<)¬ÏÊç[Äû¤g0Ž6Šù°yØYq•ñ÷“:Ðl òð)?lº/Wô°<|5Ú{øz0ÐëeXŸûÛü4ž!?Cm&¯‚§CTv–ñÃVÅÖ¤š)`›$xŸ³yÂ'­AxàÜò'8<递V!Í‘t0´Yã'cq7 º[`Æ'Ãߟ³:çˆüùç‹øÑδÛüé¢=ÉZâk1«´Ï­ã#\E ëVW1"íxOõc«dP¤ê ;NWú*É(-²04b­fŒç€ 9 ˜Ž±5#®´ñëiæ±* ƒ)UÀŒ?kC6TeÚN̨ï%û-Ñ`,7­g¥eý„Fg6 f울¦¿h€ÁQ& K1"Cé(ÔF&ve‹ó!rÑeåô:Ä輤-j³ÔN(Uµ7’µl¥N "µ’™hªñ¸OªYÄõÌÀÉLá@gØÄkÇðU¯2%ðmžõøw0ŽÐ%xãïÙ—íèÏp^bæ÷¢aöجI‘ çPé_DU¬gO¢Äx7Y]H#@òT§'&Þ ²¶6-—á´Y5 y­ Ñ~¾Uvr0&ƒ¾ _ÏxànœJÁqô¦˜ûJË–í¬Ú»)¯6™ "Ak7*yRY‘³¢zTè·% 1p3¬–*§ ËN¸žf*=ÿŽÆR[`Uº?ë·¸À™øh‹]@­0?æ |(‚öüaÄ_F[º2ªùÂO¶Ã¡Õ™øô6Î}=+¿>áu†£_Ž@üiyx^>+_gbÅ?A(lfÅ|¡/qFã8M^ÅÐÏcóÛû&¸wÎ s¼ðc„HxÔh‰”Ízá²YwTR¯¡§¢ X&âígG[Ô‹c_¥€X.ù;ŒJQk"t•W:*(¨p,•¾¤–A‰€ÀÞˆ™öjµ„½¨B‘?”i`¯ò­òPÄqTX‘Hä«I[6æ@Ùhµ†êÌüœ¤•u(>úÈÙyÍ<›H/°÷8"Ф›'!9¸mèjXçF{×›y™L8h^àZ^(RJ:Þ³Ú]ÇL‘îÚºÖ!úZÛDJ>„1кX;É™ù$¿«ÓÈW'¨Úìí„Ê…ÙtEÍ 3º*&eÌÕˆ ‰Ž=d~RåM‘¢uÒ vnânÌIun!HèFS¤Ó5@{äØ^Œ…HZMl3ŒÐ&ß2ÇFkIod-f—ØF:ß-J‰ŠU-*ÝLGÏ61ŒcVÁ(ó¼7r@pÕ&zÄ7t᥉t’ éÖJæ814Zîe À »ÌX”ÍDkf)g ¬#¶q¾bQGÞM ÚwÊ?Çh“ä¯X„QkÖM †Þás9{SS™íz¦æÎ"| lÍÆ UbŒ¶2ʰ¢‚²?¦vÙ&»¯à'¢^Þ°ÑÜ2ÎÍBUЮkÕž‹­ññ¶›ôpe‡Ëõb)1d ¾ucTóóG@ß õðšÆŽ›¯â½Ê€,—×äúÀ©ÁrZ­Ü¸M?GºÄ´.ëÄRî†t©–‘M{±ÓÂDÃ’hÔŠcÙ…:'h£ GPÜ,JGÃ2æ|P1וXm/×ùR¯˜›,ž)îÉä×[X؈‰«¤s« b¨cˆB¹w]éÄ‚VTnÞvÛÞ-Tó–$S©ó}#ÛGñX¿Êœó5¹O©ap»ªté*JŠ$äãÔ¶¸™à¶›¤Ò¢WJ«!(á6#‡¤JÐiR‘µž)—¸p”E;šgÃä‚TÂÚj–›ÖMkmKªlClµŒØ¦z¸ôåNò›¤âE~µÊ6ÍbE+Ð(æ©=èEå­ ›4v€·/ff>€ÅJªÊˆbɯæ?³^ˆ•¿‚3!å(ÕÂ2èM oŽâP±/quü ׎ðÎçÊçTãŒÓÉ 5/}f V€ÅâBì)›)ÁŠ §´V%xâÿIÏÔ½ÛJÐË€ÁÊ’Âé>Ôä;@KS‘ô*n 9ãÒó,j-=óͥ˼ٗæ% ¡ª’©ù›”hG­Ö®XEyß6Í5x/ÃR)‹Ý¥:PJ>mW]xƇjJFû\H‹ö­sªþ?¡ðòÂOÍ{|3¨¥ezrGyc ëÉNA_­øc´[7cG›,dŸ²»X'oö+Pþ,æ†Û/Ó:M¡§y‰“šä`Jp»±’“à&`¼Ÿv³åÌ-y”*“G© e­?{%{_!gº½ÜÛsOéðš»<ÝÀƒM¸¢eÈ\ÔD2ZhJjgžZfX»ib¹¯pÑ]l+œ0Ü[ /épÂêòPQA#yïe¯( Jó/Ù*g&¨ªþ2òZíØ ÊZ ÈÆ³q…’SÓ•O$…å,Ј¤zµùé:Iï^Æb·«Á{œvöd[’ÒvG·"øv'†ª×ùhûúf¬·Ûêúäs“7“£ýé\PÁVŸ«­Aj‹5Pó)³iïR¤0õPí3ä?ªf¸ªÀƒõÉò°²´Aél.h"‡ÌíFNN¡cëíÒ;étç"©Ó¥ÑxLlƒîÜíõªæ¢TP³Ïý B÷`g|ñŽÑNè@9À®n‚A§*§w£ë¨dèei$-K%Ä8Ùš·¶±lü‹:ä0Ô›•..• ¶lj’Åy‰4‹ê¼=n ™œ/™€—Ý$•6AÌók„„ð’Ä:°ËÈ;n ¬´Fõ=®Åc†ÅE GQy¿¾Â…ÅX[ó!†Dwd‚³K@š/Fç:tb³W@ öNþzö‡òA÷Ê%ûåéÂÊI-Kÿ¹.UIòv»˜Sºr"²šÀY˜ˆ0 ë€/F&­‰Š¥h‘ Køº!þ^­1)ò“SÂÙ6a½õþf£(Æ>u§I×–!1l"¶B‘«+)Ù^#¬jòŠmr†óè $âìr?°wSÔIä[»•²šŠñ1øzדD… ©Àüi&2M¯ê/4IÅÂ^¯½[‹òª¼Ù„Eó¹Ô{hAVñšõ¼ê/œ •áÕ"Úª÷“–ª1ˆJt=^2k…li6~/gÝÎ9–¤aäø4A¾‘Úg’;Ìt%c)Y-¼•† 1n×ÇîBï Œ²Ý5Fƒ¸ÝQ¨wéIç»+ÖŽèf ³°,ü^¸‰—Yçr ´n E_*йIôÀÀ@:¯úHÏð.^7Lº»ò˜â°Ñ!­^–ÿ¿Rqé>÷[¥ÉàÅó¬vôêkäËK/ì"G½ôò¤Üo©÷D^òyòý–Z×zZ~ÂfÌ÷[^Ž–¶¼ßrÅ v¿¥Îüx…Ë®w¾)™Ýu‘¾ø„r/üÏm !‘CÁiS/ÉeËÞTP¿ Fƒ¦õMqVYýjõËbTÍýa¦(sé]òÓ®…‚•/ÅÙýPp<%½,X“Ë”B_±¦ɵ‡úó@` %¬ä­®É~š_ûIúwø~¸JÄ;üÿ@àŠ*þúî×›¾Møt0áãkCé_¥nÆ—›äº,ü50/¥ûB/Ì ížÄ›HŠ^¥¨WÒy®W·D]uED7¼ÂVÀ,Ç^3¢ë»$e)Nªå ^äí$w†c¦\L––2»Õ´S¾TQ#ÃùãíK™æh†~£˜p¼i6Ï>Ùøyê_òbýòe<íÈ\Ý“—äo‰ø7ºþÁJÿ÷ñ1«iJ¹Ìµš¦²«±nˆ~k¾¥ˆºÁH*Q[¿+•^Ÿèšp•EõÂn7¯ÉA¾±]ªŽì ff)õ2hñ+ÛZØ=k±þÒæ· `âþ¸Ûã®Ü¦¼4m„°ú÷ÜÀv%UÝí(gÊ5‹ø"ôF‰µ‡¹fQDF¦k˜¡l‘n=ˆÊëÊ—fƒê{¬ÞóL/³Ø—§¼¡5~›3e„ >¾|ip{¡ÉéþÖ}½?Ðü¼Úcƒ™´½ŸÉŽ 7x‘Ú>–wâxùöy«HS¥k*†{ eu¢ùÕfX©(Óð¨`Àj+ùЋÝB/y‰Úá À”ÃTAïat[Ó_)ÚÿíhMÍ^ S‰qÅGeôQp¼–QÔÔUMûBôj+?§WKíõvÛZÕ¾~·”¦b¡¬&•Ä  G…üóG[0œ³ãý¯Ò–qà›ƒ… „‡ñÙñÁßà¿ÿ&ÆÈRendstream endobj 338 0 obj 4983 endobj 342 0 obj <> stream xœí\YoÇ~Œü¾e×ðŽû>À‰$p.‹Øy )Y2Bse‘²’Ÿªê«z¦g9\ËO1 S»Ãžé¯køÃ…˜ä…Àÿò¿×ß?ùð ñâø þñä‡'’\䮿¿øÝ% Ò®LQDyqùí“t·¼ðêÂ3Iuqùý“¯vnowÓ^MÞ{½óôåàCœ”»O÷®;kwØäBŒvw¹?ÀÕ …Þ=…ÚNÆêÝG{…_á‹10è÷i’oÕîÕôI‰)xGÃÿ ÿŒOp“n÷»½™´–ÖñÉpÌG{9ÅLÜ}±®ÝîŸx_œ,òr»Q‚ÖP¦g™¨vŸïj÷ .AMFÃ|ÚO!j ƒ£èî=h+òÔQ ¿ûdñœFOJE¾¹¿ÏæQ.ÀÒ´JKÃ{à嘄æc”| ÜÝ'øÕmB™Byù¯Ë?‚þ@ELÆúIPáå3P›…ÕŽMMàFÊI™‹ƒ“—1¦>…Ð2vŸ•O >)að•~|½ÃŸoðÇ-þøÜãêèoñëküqÄoA¼¸ÅàØ˜»vñ¾^¼j_׋÷íâu½øràƒ•ïÉ×^óyüƒi‘é××í×/ÙŒøo$›ð®[¯±f÷[:*F=žîõhÿ­?hïø¶–÷´‹oF÷|½¯W“RAƒRít ¤Õè„JZ5{=²iÓ˜l,_î#9¸ÂÝÏø®8ý=x9̪äî9ú‰Ÿ¬7$ pmË5¹1R)P¹E¡?¸CÓµ6ÀðçuLý¦lSÔYD‡ñN9šÕ˜5`ùóG'p=à¸eox˜¦õ A 1Hí¾Ù+X¼Ë€1GøèòÜ^ë¼H¥ ‰‚µžý Ú8°-Gë¸ÍÁMX!®¸4 qÊi/§aãß´;« ˜,g;ÇM‚¢•ä Ä1ì17å1Ï÷hZ˜ÉÕøð-Z“1NDþX\Ó÷øh59ZWmÇ·UvYm^Š5¬"ÉNÈò4/]ÞG'BçU–TøãÞÔkà[êG³}@¬ËûÀ_ûƒ¥A,Âm[X23§àã«v×U³E\ꆃÄD@QT‹òâ 5(¼†dr»® èÌî#Æ–™ÉWA3‹Î¢Á\Ö{„ö¶š2ûͳôp£#Ü š™:þ¼›ÞQÝu¯†:?è @c¦×¯¦à¨00ëÄEGCë#Ñk¼ƒåH¾Èæ ×õSç4èî ÛòEûÄ4×uö? Á›Ž˜Oƒ/ù´í"™ºˆq÷ëA¿Æ‰!z9¾äÙ:™kýºˆÝ½¡¦U„,cd±å-YŽ¢‘aÆwìãæ øŠ•˜ª7ƒ-Nõ† à7¬ò ¸*©Y@Çh•¹ °G/v‹g¶_–hüî7øÑcÔØIäiay†ÔÓîû Þ,ðå<¡ùÖ,.¹éŽÊ•ª]¶D¬§f1IWSsŸÔ½Ùî>ÞãÞ¬A’H•(‹Åè„CI"‘d-qß´_´Òõ%¯8ëŠY%~¬Åk6¤ä0 Ä@)íS,Ù<™ÑVęѿìU0¾ø%¬×{»Z>ÀJæ9yFà}–J((× 5x¼aŒ#j"ZW¥ö—©|Ä‚h¦ÛZX*n‹/öÁ€ñ¨f*8ÍX^/ qÕmƒtóP*Ê?³üÛÈÁ¶—,Ч¹ê·j ’+[3±( ÕÖ™"I2Ï’4v&ÉHUHñ(P$ÄÉåmJ¬ ˜äpf[(Ô²©!ð*ÞôȽ™u©]Ü RâšuçÂô¶#IeJ4@ø½:YfG4[£+ À°[¢kq§¥Y–)Gj‘ Й󮨊’Tœá ’"†U@T¢O‡YËã°º-íW’ã¸É#ÿžI8èÙ®bKè-‹#7&LÈü¬1)ö£[ìeêyZ¦u3–Är{löÖÍíÀòîRBðÊØ#^ÅòÑpøßa#Œ7(¡IÕ´ŒàEJéÜCíþu‰°ªh€OÛ-*Šú8üoâX½—¬ØàÈü-:¶RÖ–(P$T˜-gÅALLygâåÉ_¿nÞ3XI#8^RÃW8©· bšX!7WSF-ƒœóDîÞ1«[Âî‚@»myb•ˆÈ›y¤Å[ŒËu[ú8îm (t£M/fN›B±dWY¯BbNÃf²B n®5’dnÐVû~¶…0v•JzqçéÉCâsgl@IžÜ'ÙÂó†z’kSP]–Ø]!ËMe³–KÅçcvFÒó`k¥F#²códuÉqYÛ Áà 7Êõ“œSµ7BH,C/Y(‘˜Òûƒ‘nŸ3[?ö$XÙ©×›<+ x¥Êfüù<èpKZ— DÀ­°à3«Gõ‹Ãžþ²Œ€vܪ „ *(yf”¯4DùžN¿j(Õ%Ú¬¦Ápà•VOŠÞªüŸu™C? ¢üLÇÆâ }²ÃÊtVø,°\:ä|ðLÆÈQÔ°}à®%ù’L·ŠWÊlʪ{vÏ«¹f|ª³½ÁD¶Ý)Ø™ÉIÈ|sïP˜.Xø²þU3Çtæéæ]ä ñÊÀâ…—†½—­Ê©Ævº¼.PÀ¬Ô(œnižk'´tÖÔ™ïU—O®J”§=õA¾á¿Ry0›D .«äDïXݳÎ[ ­×Ãa5?ýícÞ=sª3©Q$9ûÊü‚pÂf± Çvñí Si¬Ëš·G¼S±F«Ä©mÈçõÇH6­ñ‚6_eSf?Ö1LL7õâÍ#dWÈâ¡èn*wÛþ³s·›ZEÔ&Ú2ñRx„×\gP§v=#ʧ#½-8Ù%º7W;&ÖàérËÆ}k'*"W6ÑöX_nˆn‰]½x$ÿ@ŠñP¬[òxÒBŒÖÛb< N”íJiT䲊¸óí+¬c:Xåw‡=°Iˆ¡Â wÊ'eôVg‹žâÃ"%?Ö×1“å–§”É‘~ʸ˜˜¨ÆŸ¦’²O=)\‚´C£1 Štjƒz,ÐÌXCé”0 7b !Å-‚ I´$µ<ÆD\uÑyÄ 7R°T|Å.;Ôô´P8;ˆ2(Á^¦h¶kÂP¾ <~˜ÀDóÃå3÷(&%;q™ÉÆ)TÏ´y‚Öìy””¥v–yÓѳ²¹¬ •I=j¬BªE뫺ªüÛ C,.¢Ý¿(eRÞS_ôo1/­˜uqD»Ó3ó™N·7aÜâ8ûU ýþd~¾¬—yä+\¥!*¾«Úq(v·½7X,¦|•ÈÅN*ûÕ¨ªĶ1ëBõN!“ bDº~ÉœµYú§[¥/So%Áá`Àýb±ò‘“vS€5~=ŸÉT¢'jfDfÓv"“nļ÷¬¥]§K&-½ç<‰o¤F9(¡“½la¨úl:“x¤°ê9…ðY(AfتÁ Kg*M™³€,ÛV:Ó,Ã@aµVᩲgЙgâ¢ÿ_qQ†VÅð : ÕT©>0dîo$”Q‡q ŒÁÞBS+Eï7WŠ› ”sØôR¡TôøÇa›>þdìã %Àm؇0å:öÉ9ûÔf·}-+•ŒÈ'¤w~ØÉúmƒ0«)/Ïù^»Úw:–ST»àÕ³ggI~PësÃ)|¨ýƒ­jVÐâip}v}`=aÔꤢ#gÉss‹OêµÖ®ô»¦ÎHÛ%Õ%ã\2’c¾Ž=lµåHQ¤~À:<­#ÂYM}÷Í©ü[Ú ¿(K®Þ)%¨®ã™g¯4Å•Æ_j÷R}9\ôr„,Ef¨¯˜0×\f|Ö6ìSÒ ­53U0¢víLjDÖÒ5ê=e_C76î-{Nß< 5½ãeficÓ~Õw‹î˜—.3Ùúh+’k½ Â9ɪ‡cI9x%jX&–æl€’µ¥ü¡ì°jçx(Ú&Æþr<3˜w¿çûÒ˜¹W{è-W*©Wï‘íø[èó9Ù4kº×¬ 3‡Éý£×=†g’–7¢l eÒ[ð1æT´â1º¼´åS*_5áîø(ª”ôÚŸj².ÿƒ“éÔèv˜µŽU7}û`iÛí²çäta[CŠ{¨/«¼ux&ÝJ„í -¿¸j4¦Á;o7šQw€átÊ M脌7&# i1°®¿=•ÛÍ1~£! l©Ü±gmiûÉ¥ã~ÒwŸÐën'÷ìÝÄY oì#”d›ëëeË“Ï, Þv82Üzú®Zü±¨xÿPI•Ï.ÝÀäÏ4ind*9öð½Á.°“rQ.³xEÈ=rû:öEؼì*°Ôú0¦ fo>H¯qûÆ<Ý¥º3µ¦ˆŽÔÉhËR…icâEê*Å*ÿ³Š­ñSz5~ Åб ¶nÀ•!æõâóžM@$,ÔÏ‚„O2 D"<=s·Œøn´Žö{;þ–?mDD&áŽß ÖG/äþ\tËFº`Ûkög¿òa  Ä«C¬»“ þéŠùÛù^U‚ıS°o®üÀ‘4^6Þ¡ºPÈ&"³O×Ç´ã¼;R©ùß6Áí¢Õ<Šñ0¾c<Š`¾É•X£-sC³7ßÿ›•¥Ô¶â EBŸ–öó +U»,çìåÃLe¹¸|ß„£|Dšr‘Ã~ß E~MD{ôc‘)²üøÜ?ÁÜšÎÞúãLFXàŽxôª¸÷æ¡{‡-à’UËâ<‚~ÿX»…Ñ»Öç–:±ïâ(·IãY¿ó²p2ÚrE〠5\J^¦S9·Ö1m 1¸¡pКÆíá6Y:ì»õ³:‰W§:' x†š|°$nXº~`7¿JŠHl¡±ôzJg÷¤±u»OOLvœ–¾öªðé“ ´;DF¡(Ù6s¤ù{RO3BÖòØ|¡or¿y×eË«ôI­]ge=öì/ü„hN‹p~ô®U”³‚,1ïpž1RÓðö÷_Êí¨#e¨Ï³ÑÂØ+ò…Q¨ w™S ¶ÍÈ× °Çàzjèa§ªW™pObþ¬—ÜOÛ¨y¢4:¥’WM)³víÁߪ—2ã‚Ǻcð7MÊoF³#4<áÆ}*d“ãÀ´ŒJ> stream xœÅ\é“Å‘ÿ®%öo˜o¼G0í®»j»6{ØË‚`}°;ÒŒ4 fÀò_ï̬+³»úÍ{ZÀˆ§î:³òøåQýÍÙ<©³ÿ-ÿöêÑ/>g/¾{4Ÿýþ{ñè›GŠœ•ÿ={uöë'ÐHix2¥9©³'ÏåÞê,è3í/Ÿ¼zô—߻ݼwÿûäwÐÃ(ÑçiŽÐéÉ%4ühn¦RR»ßîÕ”R´i÷«½Þ}¶?W“µ.èÝ“ÞæãüÔØ¸ûžªÃšm‚7Z§I+è^z¼7aŠ!ùÝW{¥àitìí`šVcãŒá© “Rv÷Ÿø4&Ó`ûõZ°=¬e†FNE½ûfÂ&f2®L5 Œ..í¾ØŸ;èTÜ}¹×Ó<;X÷¯÷v2šÂxF-ßýv×Z{Ï>éc–åÁ¸´<¶¦2…*Ÿ‚<·se¡Ÿ=;7óTJù4îaà Ô~w4ýGs.x½{ “‡ÌîõÞL1zXE{„Mo¡§ Ð5ÿõ9ÐàH¬Ãu^‘Mnw…¤ð“³n÷ vm-œu¼©ƒ¾é_íÏõä} §)›Ú}½£ƒ1uxº_ïqæ8©Ùõâ⬟,éuë4Zeï/`5O{›¶°+Z¯6v÷oûsæIÎtˆFûÈY‹â§°™º ÷Cx¥¼£|²‡õ„¤yÏÂd:Á2ËôÞ…°Ê‚Ňb?ÿDr…ì`´@d‹2®¹íŒÙVÆù­3!²ã>ֆޅœÌü¡ ÃeŠàå™èŽDOÎâšÏË¢ÏA¼œŸu^{Vͦr¼Ÿ}•:|ú«:…¤”6¨+<ïÿg8OuW)b}Å9£²£¸í3Õ¡Äñ=&ˆÑAw¦>¾èóÖÕØ`Uòü†cm¿vÀÚòþ´÷Þ~¡ÏÝU8нkÏ?®{ãâåä}ñyeKžya;í 9Ëä‚O01°·Sã_<â?n…[=ÌÆ*‚|àOÿ$Î6ÒÌÄ„ qVLÈô}X0 1ð‘á I°FÍi‡_YÙ(¿ÔŽàÓ}ô¼Ñ@ Íic”l‘” \ ÖcU½+»È–¡Îr¹'¶fk–/™m®¿2¿À?†5uœm›aÄÉ“a³qVù€>9hN®PwžUÖÌHSƒöäœÌN¶`=ÎÑÚÁ¶ÖÏð¯wøÇMi§q•@Ö7­Í«þ°w|ݾnßö‡÷íáÕ>"ƒ{?ßD1s^F~ýmýª=„ÞÖÙiú P#%²”ë1/Fû†¾ëɺÒS¤{Óß>zòÁy¿øÉiÌZ>kïúö£ƒ4~Ýhü¶½¾ï¯¯qœ`;Ôç½!?¡Úpq@† éOu@¿ø\[ú¬›¢¥…ÂáRòY8ÜÞŒ ¢rSÂã-J6+pëÑ4àjJt•Ȇ¶ˆø, ýìÈ¢mÁ@;ëÉ»û ôW`! ìа÷F o˜µ‚eØ–i‰ÐXL ¸ ÕnŨ+(e$°nFay:Øñ¢L“[€gÈ É£Óq p¤Iœ¯˜1ä˜7x‚S°/Z6ü†VUH»mAö¬Îf™ƒ¹»–¹Í¦tFËTÁ•‚žvNeftœ|Yô¬ØšÁ&ÖE£æ/‹6*ðE~ˆFWÊ!:ÆA^åðÎpC|ûÎafH¢ÎËü÷Ö”l´Nà×z2Ò°â‚߯¤Q{Ç!ïû£Áfä2à¾[?ZÙ·¼Á«]§ ù=¿îõ‡väml3=lg©ÂôÆùiÍóØtÈóÅË1!ׇ±ÔrhžÌÀà ÂbŸv߯®ÐÅ¡ ô2Ièk¹žcqYÜ0uC†<^®Fzó£¦ÁãÖ ¤ªé©á|yþ‚îe¡š tÝyºÑBu`,ÏF+?ƒòe 3Ú$ДÎë@ˆ®æ§†HiCIjL{.¨a;%MêÜ/Îïñ¯š‘ø¸ÚäŸÍw;ùCøýètk}Ã{W#|+L¦w Óèùg4—Kú£ÌeqX`©]´‚Û5’KY²…¸9›£S£#Už‰Ü¾ô³­ ¯*][á¹l=[ÔßPÛ‚G³¦˜Hwõ2R/òFï0o‘9¿ ï#PD2dÔ1€ŠïºT»±útƒ¬ãñ™(jŽV5Bj:³5ÊÖSëA8³û]ä(ö•ËTý#á”^wó OP‘¯ê•s°.yÓ¢'þ†}²—uŽ4ÍÀàj£Ôó¥7z ß«½ζv¡ n„#¬“š<…t…7Ã}6oÿu`òÞf~Ó>ÐÄÕÎ5¤WNö²[P”zŸñI;Ìm>ÍÂUçB£P•…/zÄ~Ìa–a¦D˜±H.Äæ–´<`Y¨\^C.›1Á*'¤‘ÐN€uø¡7n»»é? ÊKË„†M¼‹M-ºt£À݆­Ñg¥'jŠ,3‹,"'9Kûv`ÝšEmOØéåŸYš 9ZZ-‰ç˜ÍFkå臖øëoRÓæGó‡Qcm¶Q1°œ{eÈ@åÿ+¶Ž²ÖÝメuÕOZ×£@Z(Ig:à­Ðz^Íi¡õ =¼À´$l\FB\[°íÈH eUfp±\*%|ý–Á¢”BØPJ8pÅ¢3âC’\@'RÎ) ™µ(ÔÑ!aKÉôȉ¢c¾­ä¿ðmWíW]ê0íÑeá?°“§ú€åisÊÜ2rúCw‘Æ:ÎS‚å‚ó/*ôsjA»>ù“a*ªÅ~t`%=0y'­«¼·!åÐK d¶³P8Øšûþô:[ó øq¤<ºjÏÄʤÂŒÿ½5f³VÓ_öC‹ì¶Ž…h¢ù¢º_v÷^‘ €-Ð `Xò‡Þûåut›g¸¾¤]°¦õÀÔ„ŒÁ(Æ¿k“T-YÚ ­Ð9Ma÷¡àõåwò) "HÛ€[¸ß/p² S5"–µ4ËlÂGÁw•£_›Ðpbó³˜ãÉס‰!e2¨D°óv çd¨úQ‘QŒÔ³pÕ_%Ë $(iÈJÁ¼Y~:eYUðÀ=;$xÅFT媈”Yî=¾ÓŒŽ`“¶‡*ZË#8}•– ~"ÂêûÎz¸cÆÛ#½ÙÎb8¯àè¼u[T &T Dó@Ô"bÔu3Cóxþsfh(¢[ý§áûþÃQQ–×Î:ƒ8>R.ɘ™Ü\¨>üQ˜„ÿ`ä ‡Ê×:•åKì·¬ø¦¦l¿ÜS„5%Ó¤)‘Þ M% ëõÒ‚ï…b‡N€Õꌅˆ°¹6E¶¬ŸqñÅ^Äá«9"Ž7É|¸:Ç”wŽ8–yÏ3!1ú¬ éXå2”9+¦û0[ ±lñA/`4\£qe%…;k H° v-ÒP›ÎO‹ff.ѤV[M†¶ Pw;]Ô°OfMpôˆ5‹Lê|©"µrdÕFŽA9í¬d®ª×6<Þ¼ …„ÏLÜvƒt®0Â-¿¶´4gV¼‡ xŠœâ@µ* Óü ¨*êh?TêJ›Ô»ÿË€ü‘ä+·nnìp¶ m”ÌvÕ§ï7ƒTë8æÈ”ײ@Áк‰ÜD>–+¸OåØx¤m] ÚGFï^É)Ä[Á ¨Ýwˆ'™ƒ€Í;‡‰t¿JiÉt˜ˆÙ ÂÄ"YL¸ü6’·f›ôf˜Vg…MÃdyH,5 Ö¸¥Û$y£Ú¶Ð $sÅ>ëô!›‘—áÔÒœ»QþŠgƒ†7|uÂ2¤}œoÛ³«±›Q^±Î¬º¨NxÃ6“uIÀÒî¢LЯÁ:ù¹"ü™± ÷lêÏ…kSÿ²=Î̼Ø|E/'óãå÷jÞ4fJÁFàJÂaÅaùäÍ‚À*„Š ë>@˜ÀÛ¤HßÁNJA76Ä)¸P¢Æ™@E–TO„×îþg?f“ƒÆzd‚8¡w´oÐÕ6µ:,âùyr&ÌÏÄdžµCeŠÝœCáT­VÚE'nÃ9AY>Æî @ñlØòØTxÔÞã uŸ†R›©Ï:½¬TÊûuVH£ª:Š)›aÉ?Mîf.×[§H¼. ñ9èÑL™¾éäéJñ¢Õg` ‚WCGÙÍh2QkHœ‚˜¬iÕ`ÚRaL®]ê!]€À3ëË¥=隺æðñ¨(CZ„ŽHp…M——€¥<ئ`ã¢øëÍl«Xå2 G»ŸS<)½žCÎØ2ÀÞ‰×/.™f·š¬ŒÄ [ CƒLõÛF\[æ°<`7,s!òPŽœ_,g®Ï•8Y5†MÏ$Na9î†T ?u£MŒ(ô‚RIÇx½\æÛ²Û@)Ó| §h¤[øQy;&¡+?Í,𠲬Î8ã¡@ó:»]߈`w‡U.ê^÷Ԁ̱ˆc µ¬‡ù££¥‹ÝÝ—E¨kñ^Çx¶J7êpúëT?0R•›.)Ö²w{ö;D¥œfÏØýµö¬Šu-²-Êi5è<ì£@ô…¶{ Åm"GLz¶Ù §´éu—øÊ*uZn°PXÆ‘Š»‡‚ÃD®3-Ãû·£÷-s™›`)N´éOP:JÜ *E©Ði³*†O*q9:›L1dOÁУ"ëAÜd^ÖzܵDÆ;.• ãŒ(¬žß®pÊÕ/.”1hsŒ|e²Ý’(áà•¼|M-ºk‚·Lq®ó$˜ °°%ÌF0£µ¨eÌ{ ¬#jJ0U ²¦ÍvuWæ/uÐ/ÑÕ¼i~ T1æ¨RÀù—ve™ß|(»n²þdO»µý¤Ø•šc)v%A±)v%ÜÂ*>V¸†¨Y®ôUðS#@¾¦Eæn}á(ßó‹˜ wxÇýêÃ<˵m&(NC–™íaQ±Gƒ~V2—Ù–l—\G%€›’¬‡¾# ¥2å ÇhŽ8ÂK<Ö’2wb©…õ‰Ò °¨Î•àÂË,âV¾‚·GQ’M$uW“Ù¬^±ì)9n0™ícË<¯Ñ;Ι£}xMæí>†lP;¸|-c\ØÔêHœEHW"‰ „±€ˆ©Ÿ‘«†ã¯uÝÂU“±û±«ÖâXù.†‚9%&­¸¹{ö«òÄbÆaSYWHÆÍ“P¨8–l ³Bz%Àpïu}+êõ m·¡TµwÌP4\#ÎÐ TSÃ2#Ï„f•WÜ.½b½úв|drÈ+.,œ?ôéë-}ëySƲ‡J%ÞŽx{ °_ìJM9²‡€e;–ZŽªf}} WCf}Ë„Gg*ØÏ¶ñË5‡Ø¥$kÄÔgb"}!Eî¦S¾”2…±„g.Ìî¼ëw ·ŽÉç¼û±F(—àš-1T:Ÿ/IW{Èwè„<èºÅ´¥àkdÂõ+\èŒuâÆèzÐrUxèV7¶Y’ØfÎÅ ªÍ?îzÅfynÊWáòº4V+S+üêÈVÑ^Í'Cl%ÒY˜¤âÏÐûMYEp¨,ãƒ}¾£2ÇuOVš ÏZwSín÷éZy[î3˜…<—k1ã\> z{Œk#«Ÿi¡´´59Çòˆ•ËP_ªegmIÇÅÁ(uêÝ‚±KjwÒb´òf}ÛBtº{šÛžG%ã0EGž+Kzáƒë.#¬¬ DkÝÌj“%ªE~½¬g˱ÚÜ.$«Ò]þi³`|í);›ñÙ®0Ð SÿÝPFe{;œ|÷¯ÝÒw™x)%¼GxaWÝ‚ùµPOwÙ7)kÝgs‹$º<'^€´®€‘׺¸ƒ“- UùÌ"üɉ[JÇ%aë‹§Áqpàe±¢û‘,ÕO}ŠH´«·þ`¬,“uÃWYUšÖhG±5½ª‰0™í³Ce e§NübÒ)v£ÖvÍi¥ôlLË"ÄäÑÚ ï‰¥¯Ùµ†µ¨ÓžW_‰:_*1\6ﳑêåf$;þr#j#«§~­^WFq]ÙþšI_Ͼ÷ÊoàÚܰHäìTCæ­€l¡S™o*ã/‹Š•Ò¦R×»ýÜ5ȃàõ*s§1Ø8º¸&¯¤#<´~ÆÝ‘>úÐ*߆Y…Ûz‹bè>£ÐÂÑ_zhþ’`9•$àœÊ øÅ H÷ÝK¾_Ôû÷²TÓ#ml–{oyà ð;sª[,ñS¼#rJ¢ãн7Íò©’a5F‹‹§™˜_$ZIÒRès f;¿×Á•ä€ñW‡”=íÆpÜ3Ô8õ'…À„¥Ü…ãZ̪Dù#ðUÍZOX—°š…#ŸkWa¨ /‘–JHTùÛFd¹ó ÏÀÈÖmr;GP­ãª¬%*ïrÐ/0dš÷϶I&eèdt]czå¨Þ„þ}#Å„Xò€ç,?!SÜe&–¢Ì®j]cŠß¾IŠªŸv#s\â߆w± 6ñ,D o:öE•amÈ1â·Ó… ØÍYáÿˆ‚öÝXáå–ü—7‹^À{˽oÙFÇbþk«dCVËÒR¾`ör'v­8€ùxúF€5Cïwrˆs×£¸»XÍË/ð¶Êß8å#(Œ}Fù ê³x­ÈøQ2£ò‘Å(Í#ãщH*~‰%#Kor £©ƒ³ùY9ŠéÚÄF ü‹Z,qAº²Õ7ÿ*Gf¾+¥F³%8Ø®ƒž{“˜˜H\ÏKù¦úÐ|Ãøˆ[DäÈa}èn¬D%¿`ÕÈ©óoi#èIùæô» K«Š%–eÖ[a¢üU´êF)„²ÔÄ‘3`Ö¼ÉeR,9C ¿«ÑŸLi7Vwej äÅ›ʽ€¼å˜-ÌÏS3XÙoæŽó­TÉŠOkµŸÎ±¹znt«m}{¦«Ý`Z°hŽcÃÓ7´.ÛE8®)]4êeøõÉfÅ@†œ¤‹Tâß$w‡—À`³2?–ÙÈdA rÝÅ8ÇëhIŸh&çH•Ÿ<úoø÷²¥b·endstream endobj 348 0 obj 5799 endobj 352 0 obj <> stream xœí\[sÇq~géGàgYÀzç¾ãTReE”,‡¡m v*‘ü$ˆ2p@‘)ç×§»çÖ3;{ΨØf©$ìε§ï_Ïþt4âhÂâÿÏoýê;wtùîÑtô ü{ùè§G‚Åÿß}y ”€'£Ÿ¼8:}õ(ôGNÙYBÞ<úac³9:çÔÆÑ'nö£œæÍ׃‚ç֘ͷÉçÙ{³9Nàé,&µù~*3j£6¿$þ h þ=4’BcW¥¡¯¢_rgg©ùsø÷+ÁŽb²›/=*%Œå“a›ß bô~Ö~óÝ0;X¸²›ÿÆ~~œ`‘§ìFN´†Ô0Œ¥½Ü<Näæ).AŽZÁ|ʳWû©ê{¢Ì§öbr›_-~Ó¨QJÏ7÷§figXš’aiØzHkYÃ@4ç½àSàîžâŸZ+=§)¤9ýœ;?mÜ8Íp„§ñØÄ`°áI|s¢¦Ñ ïCƒ»0˜1b³-K¿(O_ÂÚµRn¾è6-ï¡“6È'6oÊû«Ä4?'mØ9Öé:½~½g3 Ç,ú-üÏæ%üt~4Æc#?œ•lˆ÷ØØ˜¨<ü‰ÍvWVƒC_c{1Jå «rJmná!œôY˜kªŒa¦9vŠë¼ã[ ›ùÂ`ïjF:Íq9RéÍyþ•éñEKC|‹4tØÛn^ ÒFƒüü ³Ëüº»¶º­p|$«s£N½+”˜QÆ#»lãôÀé‹™œ˜ùLiÞhè”zWZ^ç×åW ¨ŽQŸ?ޤ~SF`\€’ƒÞ€”ŽÖ:›NzqfòåëZjžgdÒ%ÛJtNâæO„¾›d NÄøÿ¢ÃÊaNd­üèzÅÑíd+>ƒ¥½Â…ã œõ±MI ~rqývÒ™à 8Ã+2ˆXéùº'ŒñôgWÆ€Í0ž`ó½(Dgb‡ó±F…òžZ9 åØ*ZñU+ÛÀ6]”ˆRÌ&Àí:h¤VúÝ“ñ­EªÂ{<|éըߗvež¼h±äpœ&k„ü#jŒFÍWÿ+®ÓÒÏ Þà Ҁ2Œ{+)‹ŒœÄQëDk|ªÊΠ£ ¨°SÚÀû^÷ðV‚ýkІÊyKûòÈ%¶œU8í"7$B$ÆÏÿæBÙ kf.”‡C1ró±xW‹3¹ÆvŠ„ðEPÌFZdeƒX½áOÓ4L ", p[Û¥…6Š x[»X—A{—:üØ•(¾&´)`0ŠÁ ®TÜym.v$ßÏcüg€nLµ¿.LÙãÙ®ôã2 ŽVk-)¬4:éXìtÛå£àŒ5ÞS”JT>à›°×¨“X~v;…#gd”6’Ì:"è|^îAÐLzänA~¶Øâ? æÿ¢<ìúzlÝ)7€Ì ü ðÙ£Ó'?D¯¥Õ Cli©îšà½ð*J>æØìÇèM$Â]5†üÌ$Ï-³Q0ÍY¢INE’£È–5®?žÍcîÝb¯Úz'3_:°åöø!®ÃÏì€Ï¡‹F_MïâúËŽ³æoŒ%kNÜ[@úyIš©Ö 9fØi:"ÕøKZ¾"zpì8eO:ªJJØäš$ò ÞÓÀξ²°Åfª¬hœÊ y'‡ÜíRŠDQ4#;2nld¦Á˜ý­ÃÓ‹°&<äΆmíx›^¸yQ•‘µ'ðº(ºÛH괛Ěž7~Àœ½kÔÐS™¾‹ÑXƒqÅ´3û…úsMAL2 “•ŽWýÀ§k‘™AâÜ‹c'˜ »GÚqÔmÌZ‘Ór‘`D.²‰WrAH0³ÓÓŠ&šÊÆO=Á †ÕK «Ìžâ.yҜ⋿.þñ„3‰'Œ*üÕ-FG†(&=?ˆ—Ü(\º&[‘ÔZPm¥æÖ¸æiÆèYjàpµO§퇢™øÔ1z•gá ÚÅUÓ¨¤n”Xë@<ÎÔ*s{Ófwnˤ«¡ è \_ÞW㔢Ãf- ˜`m“Ð*‹½XŠö[x7)îÃèË8r*9ÓÓ3ÛHÝÒÖ¬ Ó”eŒÝ KN$6 EŸLÅÖg•Öíë߸ßF±d‡×£KâÊi*C×¾áÒà€©¹™Î²b›Á’†·µCSD$ê~9Ë‘‚˜Î<_:½Ò£*ê¤îVÉi=‹oÙqââûÌšg3õ–³£ÐòcCºy9÷ò:rÆÙ¹\÷’{])‹dõó §Tޝœ'JzTiz Q±ìäÎÝçù`0ÏW‚^˜ª`€Ï÷9Ci³cõ‡mËìíè îs"]ÅBh˜9À<Õd · ÈE §r,JL¢HAºBP$‘‰gšS™Æ«êå1™³ð´;Y"²•õÁT [K[ÉÈ0_ e} ÉlÊ®úß"ŸÒ–,4Ä„æy|%Å®<~ž÷¡qÒóY»uæIë¤]já¬9ÃV´8ÝtŒ"íÄ,µM-’Kùt-î„ †&}˜+Ä Úd…ÎÅäY* YØmܯi"ÚVÉpU»”bÆm¡g¤µeùÁî2~%6D#Ö½7ä?ˆ:XÒ¿4Å3>gÓ¦¥”i£äÍj—îÓ³œÈ«zFÍÉò™UÂ'Z·Fq  OÕ…:—b¡ù„A[ «,`x~­ÉßV}|ðót³Cu¡ÀUE)½§3!ªµ˜9QÌðÐk)a,ÁU†’`µ’Cä×Alf‚²Øàú5e úÐ"Û>ËF4ûë™eƃ¿Nt åR°rp;…Û…°&¬!@¾¢,‡õ§ÞàÙQ¼LDB·CCПP+Ù†Æúýê˜ôæ! ´ ÃeosU÷åÃó‘·üuzˆyL§¦PL°$-PÑORxÝ{_–ü¾<<ŽfÇhy]ubó'â=-OkêáO,ñ¸¨T`[×v"á%–­1M¿„‡ø/¤AH2Ä•\V7ûºBExrS×r-GÈ*ß‚%W«îð«ñ0oäMÆÚ ˆU›\n…\šn¦¾âÔD}B/€ñvÏÈà~ª³ŒA/Ê>©£ciÒ4éqò É_Fôó)á M‚ùîõáuv*B ²Ïõ.C vž » 4µv¥ê-æçy™wŒ!À„ïEu@ºŸGª±à6ŠFÅÌQ EͲhµ=ÑYä2;|ÍR•”—ªÏ2ævxI B‹1ó[ã‡Ì#?çM/Ó¾‰½oB7JvSª¡(Œ†|—µ e+@å諺ÐeÚ¿·pÝ:qª×¬X@š©¬R«Ý¥2чïf³Îc;ƒd,*š˜!Ÿ2†ZƃX‰NZ ¥7)Ö²Ó Â@µ@P† gƮдDTù™pø"gê¤puiÝTåÔ¥¢c H]›ˆ@ ´&W8‹Aõì‰À0f’MzÍ€_ÃjÜðÄ`0!9D×Á˜>dE*‰ã„± 7P‡w@¢ºô©`|Y@#-¥ ©»Kë“‚SÁ£@lÆaÄÈiý‡‚}±Â©EÚ•_ŠòÇhQ²ª¥¶þÇ!<›tæcÔfÀ¬qjäĽYÿï ÿ&®Mÿ!09æÅJÑU¿)«Ï¢{x?BjrX0Îr)¸€ž¨,rÓyƒñe“¦i¼Œd4MFw;U¸qaÔ}õÏ ænêI¤Ìªšb8;«òl K«|ù‰ráÂÛžB“P…­™T­»o¼üoVäòÛ¯„!–L3¦j–šKñõ>)ÚæÑPƒ=Õ€J7WJW•ªÙ ë jƒœÿðÊÈãڤʙ¯Q¿%®´Ró‚Æ¢¹Rÿí¬hª^Z Ç´Ý…p¿€ßצNÀ4J± ¬ç;L«;Šîi¢¯÷°§ª`iªÓÎWKXöÅOhèÀbr hÊx»ê«®XYSø×»<R*A8ÛÜÀYÂÈO†šú•¡o×êÊÞö¬è)àÅ‘õÁ»üà¸\ÿåòË1XY«ˆ"m1D}>”Üoü¦Ð³AL3Õ_ìÉ‘òñå ä:‡¨3ÙIPA@H¬ ×.ÈI)R/ÒY¼&W}ÆH²¥aá½VìÛ*?¯¸×ñ5&˜]$¯‘Í:?÷׭ǾL\}öc æA|œF]­ìÂ2ægV¿dJ±ùfO*ìܧ YÄÛ-‘þ°¨°Ëæ 1¼šÈ–ßëê¢Û´b¸0³] ÞF@Kö]ÓHçС«4XÐø˜IÌþ‹©öÎmM¬÷J‹‹"§ZÀôñc¼¯WhÊ®ª2|±þ’×IÜúC/ÌÕõÿM>8^Áñ¾ð!Xχ#eÜk‡ƒ¾1 „‡l¶ï“{%[ ¼9rຖߡ(’µüÁâžA¨àj>Æ¿¬°o#ì¤ò휽ݻJ Ò·šïC$NM¸«äü[N¹•tbEöóù€‚m€û£¤kªÓ5ý;õ¼x2ÒöªŸ²¦Çm’ Ñååôܽ°ÖË 2@ѧûGIòµÈ¢'nþPF‚WêÏuíú¢ƒ×ü«B·ƒé‡ä•L~^¨‰cZMïíþÎ:£ ùI&ÜT*H½ïWëRbŽˆçø¥5r×?qbŒžçz%É¿ð| Ÿ?gŪ0ð›‡õͰ’ÿ;«²Ø’¥no­/zÛ™R°(úªYšÉ»È´W*ð‡ö[ëôž)ôÿ1h`[9Oâ3lû¶ý Û~†m?öÿl°-è‰ù3lû¶ý Û®eχ ¶=(C„6``÷‚¿òÃü«F?([ÁeŒô©øWV—(jwÂOÅ¿ ZÍÀª%}>ä ùÅÛPvúŦNMïzïu;9i<þZÓ­Cñwx ðËòí³øŸOÄr»Ìœø–ó2#A:Õ›Þ8lßæ#z’ŸÍ5ÕtøšÉnöïTð’ŠoóÓõi|Hó¯”3ôaã.ÿ„*øswýúC±²ƒm—ëúl_6ì• ÁƒêºáÐmT„ñÂm!ˇ¡º`ì(%h^”QËÏòaQ„ô”ÛÂOOýþù?3]ù¬endstream endobj 353 0 obj 5354 endobj 357 0 obj <> stream xœí\[“µ~wùGìç¸|&£»”©ŒÁÄIˆ½(àa½¾,•]ÛøóëÓ­Ö¥5£9{I¨ÔåewF#µ¤¾|êþf~9q4âéÿ§×þpÏ=yym<úþ=¹öË5¥ÿ^}z „„+Cƒ8:~|žGNY¯¸y|q퇕]›•\›ŸŽ¿‚'”hž°a=YËÕ×ë´6N®Žk›ÏéªÒ~u®ŠÝº8Úw¤ ƒðxîèÖZ¹Á»`Wß®…€«Þ°»ƒa>›õ#Þ‚«Ú Bèռꃀa°ý\l²ŒÐÈ/W·a$lâa$eÒ^BWð€Rðˆ «ûëgð«oÖrGrºÖƒ’ÐúSÖRÙÕßñq)¥µ¬áqí3‰ýFñ˜Liéí‚Ô|6i6jœvC­5žl²‚eÞ³¼5®^Ó ÆˆÕ«õF*®ÙºªƒYý B;çT¼-PAÄêÍÚèÁYéW'°qç¹ÅëúÔ#X ­a?W/ñ±0ãkWO×Ò ƒNÕཅ>ŸA;©a}t ¨a\äi½†Ã¿€ÖƒR:ÈÕ;œ¤ ð`ân­” •ˆ†sJ€q cV?®ÊÅòq#•´¾^úq O( Ë@Vdëbu»ÿ®hpÛ½4ÓçǺ/+ýˆ õ4®´T:JÅöõ@ã ¬Èû~±ÞÈÁZg5."<4hXª$¡C’?º/ä óšáݳªóyùlc·@ÜTuœR~rÀÑì G³º 2dsÝhÁÈ<8Ëú=v š ;YÉúc]\§EœßFz4q´‰Â€†ÇyNÔ"ýjG wÀŸ„Æj¡œ‘h;ãŸÖCÔ5ÄëOÖlWO‹V“Þo”—¨Z‡„rf@‹k÷n.1þú¨´y‰Vk ºÀç84;Êø$³ˆ‡Û æ ùÅqLËÀô:“‘«Þ—=ÞGmK2ÀT™`¿0 ›M0ê”±W㣠M6 oP¸ßÒƒxY›q!-Aw.h‘Œ´e,§Wo«º¦UF3¯úVÕ½þF35«Ú‡*m©4sá8 M £íŠ®³FÑãt¬c#']õÔŠ<ÉpM¢€nÐÒT·zÖSÁ§¸¤TK-£–àrU•ï«(U£ÛY=²Š µ ¢–dIEaaÓö<+€ð¬®^Ã¥30'û Êži5t£Œoâòƒ+å]0„Ü#[ˆ·Pp²©æµ\ì2-µüàÙF  n¾8||Ü CÝy»``¾~Ô©“Þ“ákÓ'±õDÂ=¢‚-G<éÓlZØMÇÊ4të i¯$é|šfëöY|•ðí'XN«Ã=ïœ#„.®‰lu³v€d·×¸ÝÖd»÷š&@'oܯ0è‰0PC¸Q]}9¯¿$-ä͘²1Å`H&.¦µýMn"ÒyÕr_›ô5/÷•õ ÈŽÚà‚r{ÀAN1¶jô_gèßBl²‹ûlø„»&Ç͇°  %5½1M¥ ¬WXR¾¤qˆ,`óÑqÀ€®–)_U<î1d00U—•¿þ†#˜e„€MªÍlÓù´ jþÒT¬Åð!´ªB‘ ¤©µ1a槤uŽédžŽµÓ|3” upÓó+ƒüýŽàM „â3˜E:ðÞ€¥¦h(ÊØjßdlý`cn7”¹ ãFàAlG!5à™~€ÃÞDô…ư¶¡3dTAj}Š¢Mćí$B#3 ©ÍE½X|\/¾(ŸÕ‹oËÅ›k‰ná¢.еµáÏëh-#‰–)·Ÿ²g°§Eœ]{Õí¼4¬’Ô†ïÊ€ðˆHögØ9FÅõzÒ»X—æe½ˆ9[ºÚMÐÃ!Ä«€z1Œ.8ÚE½W†þ~MËW‡›äh™lIg#¨=°»ùÃçܵ§“B‹›²æYŠ>®Zò‹é¥3ArZb¤ãÀë®!=äþ ÇÑþàÅm6{¦&V˜ÜAÖöÍïÜÚÕ†çEùmñi1¢Úð¼6äOϲ‰½*¾d2¢ÝÅdÃßöü(hOÍ^¶÷ž×„/¹÷lz€Ÿ…P—gM&z¢–CÓ¹XÇd²õ*ƒ´œ Àú*Ë3±è4 DÅßÀ`})W)ë0®Ãkj1KÒ@’mN'Iö8µZÂQ?“f¾ˆàR¾†-U£ŒÆÂk>ýƒÚÐáZ ¾äކtŒYYaölžoï%(䙣 ,ÛqZáýÆlž¤¡ÒíÚ ë›5̉å–« Ú2VLN‡V°&x ,VÅÏ-_ËÃÂÖÁ¹%Gúµ´TýƒCjµ¢é"mwz¶9/Ù¨ îà ·Ø!£Ù÷w×wnf˜.2Œ‘“Équµœ:䮂"ò´†Õ'Zûï7«IÂXâ~”´Î°|û]†ŽÐÑ bžÈë¤áú.xµœþXò¸q™í6 ÿ²ƒwÒ6ŠËÞ«¨ý\®/žÐáÒÊ´˜‚iÍëªÔs¾U&×3}*…*–ÎîDÇT5³ªåœ<÷¹ÁMéo¸†ý Ä4L©&¢f.Ö²gê–zCGvþ)ø'èjð¶5¨§MÏ[©c=ëŸ0€s`KƒFL:ËÎó¨ QWx¦ÐÝ<IK5öNyÌ[¨€>«ñ¼ï_^bDö˜T ”þ™‹ŸNÄ)V- ithÛ>4[dœö6vk~¥%¾ŽÓÚÌœŸYŒ§.xëÇŸÂ\ú”^£­Å—U.Bå—|±žóK¶SK"«¤0B*µ$>‘ëÍœ[U"/êÅgåâÛ>%óKx!™îѱ²¹ÚÈ9»Ö‘·6¬3>ÈË6×›Ò˜Q¿êP¯¹ÈFÉM~±KM©òçŠašÔ{:àp–Jú=yB5ö‹šð-þùþÀ“áêSü¬ŽÕWøã/øãóÒøV~võWüñbÕ[ƒº´?ó™uv+[Ö„º¬ £i«&pÝ˼—êm¡$ý/U¯,åÈd}3•)Ã99wóf¦VmÓ¨×[ ns’£ÍoO€?*•¹KRü“Þ®¾c»Ñ7–¹ö¼/kh8ÈQn!KÆí‚7Æ¡âÑ# q·´A[™ËËVcõ´XHÕìs®‘Yv°ÿ@ެ wÊŵ¥¯-ñÃê1Û{w7€Ê@ñ¸{¸SÜ(}»Y?ÙṆ\Õ˜yÕq)Ãf²©<í>q^­¢ßÏ#¾¦¥mc©|® 9=σåà™bi5´­¨Ît-3À¨£ˆñÿc€3"%$~]¤/öCˆ”Ú_.‘RËóÔ,1¡-½ä¾‹"Ñ›^X‘á'Œ'”:ÑNsª¦gÑ l„TM™ÅО •<°aƒgE2ï#Gæð¯ X¿‚²ß—DÂØùEŸoGäIÏòã8Uç·HÄqîfçK"ލ"¬¾ñå:*‡XœÈˆè|S·M„ƒX› Ò VO™ýäœmH÷Ëɹœ%‘Tøœ}È£=“²ÎÛD&qaÎX.’.Ê ˆíw™õÏoa[®½]†K%¿¤…iä.Wfª4eÄœ‰ãYwún[þòHÎKþv_Yò£XØ‚]ÀàÞ  ¤MŒ£å£ÒÉøù'±ü“øm.Éá»;¹8Þ¤ù&¼€üê'¿Ý+Å~9–N¥0³Bef&vÑõ–ì%’ˆ6—=úíuü6:nÆúé$Ô{ú»[O„„æk:N§Y-V?;oYq˜ñ,ú·y”‘ér­Ý %•ùÙí&[q×/ÑèÅ<ª´¤(¦ s]ŸWn‡)/'7½¿Õy)3‰ÿ›¼Ù•RD.)ã)/q;óûçÖOÞ¸ÛÁÍÀ¯8°OÿÂ5£ÈˆïSKˆ1mƒ•[e?$‰OëæÔ´ü4§h¤»å½r;ý.TŸ»ÑÔì; ‡yÑ\\Å2Õ¥ZÎ[·I÷šFM)øHtÕòƒ¹‘Ó6^:lIW-cd$O±‹ÙûÜ$«[ÎÜ"~Èã~â]ÞU‡|Ú1ß8ô‹/JqU–Dä4°¥¯"à¼ccâ¯9Å*R6d¥Â;ŽŸ3cC1ún©{Ö^®Om9Q½c¡¿S¸M¼z6`íó×ÜÛ¥\Œ! ºûå§´Vmþ¬OãÛHøÚ8?—öŠE3‡ŠÔ'qLœý2‰#W“0¯?G©—?ÁŠ_ šYÙºžR8PËøkêHܸ{íøÆu㊺qEݸ¢n\Q7®¨Ãu㊺qEÝ‚nÔ‚ýÝ…Â$5.ÕÉR˜Ì%™Ÿ~wåÈÇïëlù 6ü=‹„ò\Žáš¶ÌþùñµÀÿÜŽendstream endobj 358 0 obj 5082 endobj 362 0 obj <> stream xœí][\E’~·øýæª÷!ïv$`47F ž]FÃHclÓFj»Û€ÿýFDÞ"óä9Uí6û°²MÕ©:*ü _ŒFŸ¤FJ|UxWÓ'%–à5ÿþý=öà)Üáã£Y´–ÖñÁ°ÍGG¹ÄL<|q &®Ýáø^\LòáV£Í¡4L}™¨9^ªÃ§8µ ãi¿„¨%4Ž¢{÷R[‘‡ŽRøÃ‡@‹¿á0zQ*òÅý}G¹SÓ*M ß7”s¬a"šQò!puŸâWc´ eåå¿þ ö¶ˆíŸ±~¶ðᓼmúhSCxÃK-õÕÅ¥‹—1¦~Â!åá§Üáº>|Ý>­_¶‡êÃoë§ëöó£úðª=<1äËúéÁ¬£íá>øzFlš¯øùÓ«£‡_¥7¸Èõ+_ËS$æeô 0©¾¸"Z'T¢Þ  mâá3üóIíˆ~ø'þùÿ ‹þ„þŒñˆÇSãá׿Ô?_Ú,^ÏÖý[ÃdÝÛö)>Xé±£õæ>Gb  ýgi¹Ù[³ÿ¨CO)+|3Œ ~œÍâçn¾VFÔß}¬§3>zÊWLJ-3EÐ7´Ì¢L¥ëŽõ']=mï¿èX­|ìåÄx‹üvø]}JŒ¥$P^ÆÄX6†÷by ±üð Ø/®ã¤Ñ‹t¤ãt•RÔ3Í »±MÞïÏÐªÉÆá)¨oc¤R4Ah&¥†ZØ&4løX¼Ø“o’Žv¥3[ÍWÐ!LYIÞpxi쬔9¯¶ìú£§_IŠäÆ9ï ›Ü‹ÖM~œ§ ò£t Q¥#dGbÜmÅReÉ,Ñy‰­÷n3a€«€ÊŒž©e´už`ù°^º¶1Ó×Â؆õs]ûyJ; Ë mšæ!39„Ì[%$ëé&ëëZ‹"Eéöu+“Y'=_ž.¥iÒ8>‚K"ówp:±Ÿ4†nâðAû5m¿ÃK:7ÀßOxà—㥠È{öÒuù5Lp8¥~“p#AÇ6xÆÇ†ßqŒÙeM:%ÒvE`–¨x^u°ëöf¢€Ëî£À$*iÚ h÷¦¢†Ê"ªEÄÈþÖ dq\l /ã(•wP6oÒ‚cÔìá|Á?­Y` !÷–'ÿzÚ9mxÊ(ê÷“Á~©úïÅQyh*4ç§ÆdíS׋=êØð~ý„Öm©¶¼/&E\$2K'’:Qd0–Ö›»Oê?›Û-2iƒY‹6tK²‘(Ò;y?·ÈæÙDÍ?FîG~Õ.Fy\Ù§Ó±Kf¢NÚp×m ¸¥±yö~û™ËH™ÔU@ðä¸2/ZÄ¡Ëùc-ïHÞ4®6ÿ`µyMÞ‘¹QÞƒÅË=y'Þo/uòŽÛ ÞæIit…vF ˜õ¤jÚÓ2 ÿ5%Ê/S£Ä¬×’-IËWÄ„…lÏCãt pªëˆ–‡Â@±7ê *XøbLKû'™ çìÆ@õm/È%avè†T\ð…”b[Ù3|aÒfgž»/RÔ“—Þ[ î™TC‡äª;ö4ÙSëk <®@Å0*U$ÉÛ˜§ø¾%~W ðdWöcÝ:¬ë1A0Çዱ -XG¦k}®‘µNsg< õý`hÖxÚðê& –ø=¯w PõŒEŠ”3ÖÛéhÜ€àMYŠÔ¤>v@N ?³å`GTJAé€Éôa™hYž–gp1³P9éæu‘i寷›¬ÙštX²±®àÖÅta¦ÉÎU5Æ$0¹> lª_Û§G48iJñ`¶1sF|uð/Û;ÙîÐ8Y0AƒvNÍÃ{¶æ$T¬Ç‰9 TÙÅ"dø‰–Ùs÷Žï‰SãÜó}OTáÙ÷$Û¿rþ™&Ï…Æ8(øä `¥B1µûP˜ %[Æ‚ÀOšÊþ2Yw9ˆa&Sp°wþ×ì0WŸo•HAv—qŸÝi»¶p@œ5Ã>›¾df*%±5V­f¿J%dŸäí!Á-.üèÙd ·wÿ‰ô–9 4„ÌÅ3|×’Õ'ªiÕ}fn¦À• Ba ThxXÛIAn·»ñiv†¡=ÚÃ=ãtN¬fIš‰¦ðàNYùYQ‡²ÛnG–EÚkxp•Dl)ä4ü ”aKÕ6¡ÁÛ”¾‡ÿBƒ„âýk¡x]µèú«úð§ÙmPqÒѯ‚–ºÑ;B„ñN!v(1 0ÿ*ϪÜbµ?¥ˆ#Ç&zîgPºtT.’J‰ÀbÁ ó›ýOÁ¨éù÷ËtÚ)†úˆªo1&U¾«*2'–Ìûÿwùõ«Šþ{ì_Dfdéâ7™Q”™œR£#ŸWýÖ ™ìa”mì!V ¹îXËïx¨Å»–±²„°ŠIæÃ'_à–„(¼Àc/!&ð °x¹´|`Žò´/ÙÕÒmýPƒ¶¨K ó’GoÎ*Yú«Ö¼­_€×ÜõÅ`‚»ñÂôL wö–,"!Éú›ã]ÈàÓ:¸‚wÉ6|ï"ütpyŸŒÍ¦ÐúF•ç±gvK°¤%9`sab^Q¡ßt ½{CCøALf v¬*´Œ¯4¿åÒ™mX<†S Žî &ÆèhÅÄ8ÏœpƼ ®«Ô6[Qcó›SÄ¢afuZnï1ÿzü×冒Ð.¹ nª2©¼Ï0w=ÃÉìTIGæV0"(h‡c =oŽ›¸Þ¤|ræT3๠oÎlŠNQÒ[ëÍÓn• w]¯8–ÚM-ãqŒ£ÛâS˜fï7ª!K€‘GêË(;ˆtl@ò1;$»6)ÕÙã/Íð÷¯`Æõ[ü\e㪰{6Þ1|ÌáŽY—+}ÎùÎÒ)þ†Â()¾bÓ»y“= ·@y9©!¹ÆCaLß§--»SÓSBø3\(RU¦““©H!qJ"w¢å›œ±qxš“iᄌ±Ø+N3‡>óˆúDNû„¹0#äžø†Æà§çzÀ² £8¾Ñ‹_ŸÌKê5t‡“e€àuÇÁ}³×M’vŒ\ƒ[ÁIy€^5õd¶Y{éÐRBO¾hÓòtF6§ÛÀóæ+×ÇE¡«8KQ¹mÓJ+æ¿^‰)Î$ú¡\“4¦(šÀ‘ɯ „rŽÅtš²¤T¾Í ·H[2ßÌò(íuvªC&•¿]IßÀ¿iBì”2(L½Qš6©;Ω–´’uªeE%5¦•ÝQaÈ»¸*mÛ)ÕZJ§ˆ K œ[+\Vb¯UJýì—~€†w~'-˜kÖÉM섹 hT…£jÏ S¢^`áZ‘-«jg`8ƒ®oŽvîAàše22½¡ì®ešDÉö‹c04·~Û=P–ç÷Ï‹©<¨Î-[ŒÌØ…iÖùPÇófÈs‰=ûof¡5* 3Ó`ÝÖ¬48G­3ãnêzZ†:/á>%ô¶g1ÐùnBsNÚjДß&hÖ¹yÀÁP‘QU,?—8•bá\î<*.‡YÆ|Þ ‘ÓkI¾ º Ý9Ú¤Ò­·fôâA+Iôvr¦ä8ö´N‰ HëèµsŢʼ´Þga@ÝüÄzs³‹p‘˜Y|Ñ>§9äÚÍ`UWtnU]½›ŒD»âmýdгÓT‰ë0[£^%û”ÚuWOìÑgÜ#Qo(‰oê3†®¿âW\¬ ü‚½¿âS3Ϊú; ¥ ÿqL¿™ÍðäÕõç·¹ûB–€µL=œ-âá9¤]“ÇY;(1¶”{òú—Ĩ½½Ž.±¤uÚZ3U29Õš”Ëþ‹Ižè&€E M3>­¾ñì×'Ô·&‘­ØkV‘Õç¾y:CÒà¤R®9ÕScio^ãÜ´0Œ&‡dLèGI^ðKú,8«aš˜HŠHÉ-Ç¡U÷áF8ª³–z ”œŸg†¡éþ«¶â$5;^5£T+PžWk' ®GðöNá´¦gŒè>JòÈ|š^f…Ê5rƒžQv¥wCˆ;–ŠU;Ÿ…rí¬H_gµ~›éôä¶’cèìàÝ.5È0¤KO%uêd ú]-`eWT†*'â£\…±”¯Ia¬b§ïuc¨÷ƒ¼&mfafcÏ»ÒÀnÍ£Ž¯k‰êÈÂeG¬[4ç¸X5ÝdCHÍ g±Q«#­¡j_ç—ôþ6ÝíW¹ õÆÌÑï|ÑÁmP…¢`±â*~›Wµ}®m‚d— >7Va2ÜÇëXÖËaº¸S&Ô¼hKÑ:u7ÂjÅ]–Nn~Íuk2…^USgq¡ži´-C Á!Ü Ôà3à™ÐÛ‰FËq>ð»4ᆰšá×£°‚›ËísÑ ÁŒsТ½Ä:e-wÏôSXXã„ãÐÏ4'˜·¦ Á¤>nãg>¹_’XZw£Kvg‹Gt~A‡Qµ³’<Ä•¾žžçwô¼#Dò6 C¤GŠt'Ч¶½Ôæ*O^Nj;©r:KÊ̶êЭ2•ÏvI'©¡¿3œïÏ‹ëÕñ€ §8S¹ùñü3uÊ–W!)Lß<;`„"o×—hYbv«ÏßâI tNPo:BëBÒüòZPš¹U‡Zò>ºãWW=“ ó;lfrvÅå¬wQË€B’zb…‰ÃâBÃølï?›äë¿å•G:G˜jW“³bhÚ[‰¨µAO$9ûW%-ÆìÜwD+êá‹–ÿcì4ZfšGs”ˆû0@5X˜*Ûù%)ÑUÉ^Ò*;ÐãÂ5¹»y$G¼tµ?ÈŸ¶YnxžóÛœò|z´¿Ì‰$r«<•ý¾ºÂi8M0ª‰ì»Ñ,} çµÄHnUÄ&“]fˆ5‚‘[ááV‘ôÉðpvU QßTÒ}áØ³ô5: jPÒ‰…ó2zÕÜ[éÕ0Ö"©é}f¯A;Oê“֕騗ϩoN®s9RY†óWÇída: £ÎÕÇMG Úy0<ÖQ„ÀÒùÅÒæ}ÎnZn׃Ý$xæŽX3oéžb:îbz×§z¹mË©ã3ØØZÔ¯êmuí¦ãuð”HCA£7Ë2XéPn¿y2E[v ŒÔ4;ž øóá!·yB1»“Ò»¼œUÿ‰<`Ž"O潜å &˜^p¸/GÿûÕ¦Î..è9 wF5Üšgë*:A÷xÜÆùű`uÇÙvMÒ­ªL§J|ð™&+âß –tqK)ÂcJx¢ÑË­‚¦»¿¤¿ðÍ{àf7INEòe9³Yå´RÕæîQç•Ý­Õóê^Çr"ú¥ÌÀµXmãîC,¼GÏgD¤ËXcÒ«i娛^ÅӀʔë3Ê"m?‹ ëÇZXÎoj”X´Í»"ùäm¿G±^¨%0Fx‡ÇÄð )ráCú½(lA· ´{ãð>A éå±Þ²0%øê'Yé¼úsòæt#žd.÷ÛBO)׿‡I¼óì Î/Ëï9ƃ_9DÇ¡¾³ÙL”¼ âdXi"6îÏíp°œ éžåòŠS0Ö_áw°‰9ŒkÌÈîÿ±åêÌŽöÞwv¢DMû ÕØ¿äò¸í6—¢VVä6žUº&ѳ<÷¹%ñBöupŸ>¼÷_ðÏÿ‰–endstream endobj 363 0 obj 5486 endobj 367 0 obj <> stream xœÕ\ë]µÿžòGì7î­²‡ã·ÝJU 4„(…¥TD7YؤÚGÈ&„ð×wÆÏŸû( ¢ l6¾~ŒíyýfÆ÷‡“y'3þŸÿ~t}ïÏÜÉåݽùäøsyï‡{"v8É=º>y÷ : -S˜ƒ89ûþ^-Nœ<±^OðáÙõ½¯6vk6zk¾9ûF(ÁFØ0Í]@Ç÷¶§jr.±ùÛVL!x6ÙÊͧÛS1imœÜœµ>M­JûÍgÐ*Lëâj|"e˜¤€áe¢÷·ÊMÞ»ùçVhõ†|ú ,óÞbn\ñ}hÕnBo>ÄV,ƒý—´` e†NFx¹y+a+)“ð¦‚JÁ6ŸoO ŒuÂo¾ØÊiž ÐýîVOJBW˜OI8Ke7ÇáRJkIdz6g&æäšòÒ‰t ÚÓ[€Ã‚yõÉ©š''BH·ñ&޳o>À‘öybó/üçWøãCüñþÀCÚ|ƒ?¾Þàϵ÷ þó þxŽ?îoO%¹·›GµÏmk¼¢Kc›íº5Þ¯ßo=†p›g£)_n^ö¬È29ƒó8-`Hi»[_;>¬mOZÇ绤cÊ<Ïk ÑÖL3ÜçŸàÖä¼9¯Ÿ=Q}Þ_Qbñ¦Õ ¼!‹|å½håq½ÒóœN¼üJ†}½­Í‰‘€k(#)&cON%€eZVlþI:Qeÿƒ-P*|›ï€óU•Fr4l@È¿ª ~œXY=O•Ÿ'cäæ‚¶âx$\À§ÞiàµÒ’„J8~ ²éÔæiݺE‚ç1ÀÃα+Ÿ(&¥U¼Ÿ{ jóãÖèÉYé¡Ñ —Âö‡m¹«Òþ®$áð,m+'qÓF\n ‘N)< =ƒ”Û¼CìŒäÕ9^´‘Qv¬u6·$k+e¥Myº#B+íYÚºm¾ÂS1 w¡ñ<³"¨ÚÊŠã#(;ým¥ž¤rT½=®J¬Þ<ìû¢iÏ4Á,ÊÅÃEäc™E¡Ò ›7Œ.S&zÍØÅ«66ß´ÅÈm¾ÔhåÈ|wxšú¦©3#y%ñXNe€Kñ'§`' ‡OÇ#ÑæXP"–ž:H• <ÚxÙâ;ÊäÊØ LÎÓá]ÙYÇ–hƒGÓ“;&Rõh5`fgÏY’ ¨²@´&Ô3ŽT(\:²™ò` ¥%l€»PÑ –ƒqÃN¤Ï€{›J×§|‰÷b5\gm¥Ì”Täîu¬O~=GO¼‚åÁH°ÙIð‰à\Týl‹L,L<]2¡BZO>hLI˜ö2ú2ñ4·Eö(ª„•«¡AÒ~0‘œúñUý¼ê#¾êè¶8o㌟ŒÓ\Æ"÷§ˆÌ_íŪ®ŸUÔ„ÜÖµcn´dM‡¨2:C{g<²$8{–$;[ÔOZZPs†ú€|>”kœï­Öº"ôA‘Tž´Rý¢7KÈ#-\–3l jHËè jðZÉThì=*«èuÐB×ñå/·ÜÅ£ZFiYèæ$éÈ Ò[øw‡uëŒ)6¬Š’Ùa˜‰¥ò¯mx§¸Ûà£Ñx“K_ÓØÏ¤‹„9w¹¶ÚELúæ\ÛqƒÈ¡6èöFÖøëýE‘ø—ã#‡Ê8ð‰Õñ¡C§-w5 %è–Ž F`še@d·3 9°†b5bÈbƒÇ¥“3¶ˆö°Á1c!8?Ùãú…#ÂÑ¡áÆ ]”õñ"Q° ÿÀ°¢Ã/”+üÚ˜ø¢ÜTßÊ‹5ƾåê?_ †$ Ðf]á–lIÛÌŬz9-L˜;>À€sÖÑJÊ íÁDiŒî™±ßÎMè­'p·'tIµ,5)>k.Û0ÆœÍS)m4‚ãÜzŽÛ}³2¯”":!̪ ת”e^Ïf³f%j‘t…O0O“cyÐÏ9N8½ö•Ì›2§nPÌÒy§RXpÒüÒóÀ5Fø§qq‡èÎqìÖ×ìô$+§±Ô ÷Ínxv·å^&oj‰7ZÆ8§ë%¸wʈ¥CXç­†‰i®z7FÒ«åå ß'[¤ûçqn £S*¡½Úï'â2‘ZQº¸¼ÃÒ®°€ÝžÇ÷®ˆÊÍD€Ö ©HM)Ä9@"»ÀaYxVyÆ™Æ3µDŽ‹ÃÀªN,^¿¬Æyùô#¿ ÕÃâµ ÎÛ›çÕÜ¥òÂÃ:/Bóvñgœ%½Z{çF#¶®ºÒ@§3s R¼aÓñQ`Æy‹ÓA;ÆñÓ’ó‘Žêò0©êÄ?2g‚ß'˜¢qaòšDãJ*›DÜûVé\SuõãEÁAž¶“‹üL£‹¿=lR0 Å‘ž·ÞMzP(Ž/ÄXõ<ááÔÌe­Åc<­©¨‚Idà¢øªëFcŸƒ•ðO ‚æ‘©O'"øOO›„³6_u–ãÈóvƒÑ]POr pO§X/xƒ²“¾[(É‹¼‘£“›8ŠM/i1n¼øyŽ×dŸC?»ÜvÅ+r0ÓTžšñSªrõr[_5©¬›í€›ÿœ•Ößo¬Š”`]ᜂ"Y•bÏ·+«¿SáŸÖ‚1&-t,ê /]Fò…ɾ€ Y¯ºnù¨¸zBõ7a­®‚Wᣈ\ïÒ¹Oñ¹ÄÈ.›ôHTGÓÔ©ŸïÕ5啇UHÎ''F6C—,!Äìá#OCL¼T'¯½ï}È>)£õ¼h²K¦$ÝÚƒj“ze9(xR”ÐQaôÝi®\BqaÌ¢EQùíz¾1R«ÃÊ9.pÄì½4ÄsxP¥ žuíLá£^׆iËãŒá©•B˜f½hÔ)¼_^Ú±‡A_ô%À*ðfö2¬{Ú·’å+:‘ßVç0MG Ž´ð‘HÇÝæëg\Q^&ÝÕžµÃèK9^îf0ÇeïãVS=‚`û3‚M7SK.u<Aoëk¯'"iŽÆÝÇ䓹ǚ ËhíX·g5}'ÈìÂæ‹³!u‘h=ÊWЯ@!¦›rÚÀQÝftñ×J·âoøý+©Ä¿£dóåöÀÒ-ÔŒ1´±ê¢^‡~ãFm|2ê9¬gz‹j€Æå]¹fï{€Á"0Ø0&à‡/O¾mƒ.kãíhú‹Öø-%d×[þE{‡ÍõdT©Ûù–í¤{†£…‹)öA *]ùk<°¿Ï„¿X{5ÀMaË%¯èö’ÕÝ÷vù {•ϨU¢ý?)%VÔ:LÅ‘o­ž‹ï«;=ª¤%2Ñá.B±šäy후Û`æZtªmgø…HÒDqˆpÕŠÎ{Påñ³Ãt^Ô¢ô Ó¯©>ÖDj˜=Šá€¢È8©wÇ€.õNÌzÇÖ¡œ1õߤ~‡µ|På8&n¶(s#\…0d-wË—ì Ø”OßrH]ŒO¢Wð»kkü|T¡ ºÐ/”Š~sY™SëuéÏa£ã¤ßÍ“XbÁöž¾\XÔ WG?ì}Mžz˜&d%'®$Ì;0QƒÄ[,Õ"^€#e ]3Å®g™‚û¼ä+¸©ÙüÉÍÓZ¬‡ˆ8XDÄûòå¤f,û€À4_¤/{SñK"vÂŒêµfã~fû"E«µ 묇¼3!ƒìúG„1;À^H°J‚7AÕ!"•/@3#O±qU —dJªö’­òÈ8Ì ØÉƒNzµ…ÝFÔz?gK×Y3ÏXt{ïC:²/§*÷þz¾•$mqfuÉæ¬Sþ§KöæL•®nËl¬­Ù‘Ë_ß3¬iD¢f0ÿžåMw~‰Ô£ÔÔô…"±*W#“/7YÉp+î½Y±«4òwk!>:B™#âS‹O0Ó’J¸<}¨v`ºs‡ZŸ“ ^ªõRíµª¼ó)ï”Vµ–†IÙ€2^«ÅêÒVd5—dùÁ ¸‚Öã×L—@ßz˜jÏ ’¥;ÂÓ–9¦Xš ªE2÷=ÚþhEÜS_f¸›íX¯ÅJÿzvïðÿÖÆ\/endstream endobj 368 0 obj 4890 endobj 372 0 obj <> stream xœí\Y·ÎóÂ?b€./ÜÇÖ:xúÅÆ¿$8ã8õïø‘saLúȵ^ÿ°ÙΓu³™õú¯ ³(©Ó„ÖŠõ·3Yé`j >긴qŽ!mBuÊQÚþ‘_ZœÞ i×ßÀS¦&! ûSžà%×HX)4¥¿ $Óò› Ïéjq Ã쿎ÿÇ'CŽ X<ÍNîø4ž–Ú¨0PZ:p+g˜Æ®¶bž s.¼ð%PàÉÀe²VLó̘§wý3þñëÿ|Š<Ã?®ò§§yôküç­ÍV½¾ÌOa$Çû_÷>ËŸöFÂ|jvë³üà]õ-ó×\H²kœõ,??EM“.íH‚¹Ü39«øúmQ0ÛàÙs *t™ôjq†iÊ…g#áA”ÃL¨O²QðŒu|BSK& tÎŒêUy)ìÇ)Iæ$#oáœrâLÅC€‰#aˆæ0õtF?‘¾àÎù$q•rl8ü—ž¬ázý>¦0.h³…Sœy¦¹¸åÚMН¶ ETdzìQâO~,ºò5ØÏÊ]À±3PB:O‚Nžo¢•­Í5žQï†Ö'Ò¸ID£œxa°#é!¾c,^·K.ƒ"y"O¼X;æ€w°%x¡7V\ù}òw‡jóry9W²—…ùÍFÉÉh§ˆ ‚Ç.›'‹Wýi½ü\2<#|(þ =YñÐ$&ørƒj &Ó[g-ÑÔ€²â¡ „Y²¤1¾*c:ôˆÖFSÕ‰ëS'‘³¥®p¤Ö¶½öµöÚz" 'Ùs¼G–iÔÑFÄÐ$é®C¨Ý§°Ú;»×Á!€qÔ6K5á}rÜnž$w‰Ø`Ø£tÉÏ"Í‚™ò,°N SÛtOˆD“Òiþ)–sAËrÅi£YQ[urH—ÞOÐ³Ä ß K4¡§T8PjÈ¢Ð2£÷èI¶ÁÏ;áž8ØW<È$Ú°(JÍ(ÈñÃë‹ê.gì‰ »QëÅC…Éãì ¿‹ - +&AÄÑÜ-±QeýѺÂÉrМ`¦6©,1jæ/`ê¿+ÀªpçÒ³þòÆâáÿÖ3³HJtœÊcŸÄov”÷ûr›’ã(ïŽÅ1ˆL•®@óA$| »­=ÁÙôÊ{XèY—ðY´Xïîn¬W#¼ îâh´œ?¨vÒÃoï{pí¬‚kˇï6h€¹q#ˆçíóìáÇ<¾$}¼‘ŒDæ) õmXèyVžåÏ{ä^‡ižk ¶,(ôVg ÅçyÁ7=öžGw ¾@Ü qÜÌ<샩5s#~þÜ^æ?Nèa…CCüé¿§˜¿@ðùrw{dâª÷BlBöcГc«ƒ0v²O`ÊB¨›tV­«Ú×ÈZAС ´öá‚XJlíƒP™—$àØ¯ßDKLÉÓÚTÂa­Ç®Êo°g誔MƒªOzÁW …nW³wùž6”è .çv5Ž>K˜yËI^io%Zë¨â 0ml£†_>Íú¡†ßf-çùHÉ}l¿ }dIˆz(¡™YòjÑ/,|„1IÛ0M£ø>mKF³Ò¶ÝF1C…FÛpÇÊÕÚ&¨-Ëá5µ- FÌ¡\›£Jë*>^W½Ì4'iï"¢—jÌ )Â%¯sÉÄBg™Í)Áqž5ô¼V€H|0ã…*Â2Çï-ÞYXô6•o÷YÇyTÈA$Éñ-©*¦~ªXˆlÄ¥Ÿ$Ê-°’˜®ñœû…(©RD,&‰xȤH6^óÂ>ÃKò(¥ ôr˜ÄHà¤Ú;|i¤@ó ë`²k†qóiÖ*_LÍ:=¹¥!D'41@´Á” p?Z–À'¥ï*» Çùh9DOJQ…ÈHNù¸k"½e*¯A¤©EÊaµ¡¾Éô§dÀ³#¡5ÌêÃúçµô“ ž”ªÉ«Ä\†ôé<ÛFÞÛÓH¦³WæAEeÎ'Â#‘ž²v Ľ^†MŽ'ÈäVΘ­®ò5_bõÅ8Þ©¦ƒ«”XØb'`ùG…=‰¥mü̲š˜Î‰Ð«Ê¾JþªIU:Ä]>nqñeº^Ö%Ó9بC‹nØBòB‰Ñ‹@<æ1ï™Õ ª4çãPwߦÖù!š—bÝ‚Ïôü´ÙRDþþEnc¤Â¤ÇO¤¤DÐAñMˆu@»ñ^m¬ÏÂ(¤U… 2xÖ £@頻Y,öaN¯ˆVqÏyÞÏFi{¦£f’õ¥a©SÄyÚFb‹“RúilJØ?,9‰r<Õ¥§àÔ‚Žj[>ûÊÚÂÖùM%Å„©´’•¾Nê¹ªÉæ‘éìn(=w,;÷àeÜzmÌ÷Õ>eV…hrÌûF…ŒÞ 7+"o ˆ5ÀÀ8‚¾ð½ýê8j‹H3ÝæWìì•þª!IJˆPÂŽä´ÚzO¬d{73ÛT粘«[V¹j½ÄZ—`K Na¶g÷®ÜÊ®vàä<±CôÌòžžùŸ¹F¤Ó‰ÑÓ&5«B(•Ó/!Ö±ûÔc(ºuÇ(üDw¬T/ ÍàÎøÞ·ÀBixÒVب]UXMá fŠAà°f4lþ‰=*ý8 I- 5‡È`üvAÕåá K'ÉJVR˜Npè{v$P÷Ru?–½ÐØ0’L‚=а*ô%0ðßüÆp¢€ÀFð¼1ŠY­þ ¤>ÜÑÄZWØbõÐΆœGYª0gÂCò1[=$Âc$·)wãã^ꥉØo“)„W;úRJŸï´Âa¦FîHmÄŒÀDŽٴ¦«Â^š ŽÕ9&"¦3>‚ˆê€åj 5z6)á«Uƒ*éFQ5ZÚž ¨#” žÖy— º4#4¨mhç{ªº‰ä”_Œ;?0Òá¤YBtÓ,u†x<çG¹‡˜¤îöKTì 1ìÜ Osm»qPQ´*ž¯™Œ° ùšÑäO¿¸”Ð@Œñ?OƒþX”÷óMnÔ 9tïOv:’‡‡x|+Û÷’ƒ)¹Ü‘ƒÞ S*{Y»Ñœ‘}h¸ä;N”ì&U¿ËYœìÞ,JBø§Ë„MþæþÞw%$;Ý TH>»$,êG׊žDÃëJ}Ý®=ÈG7n|±I…óùÙu›ô¯×TŽb†íì—Îú„YY“ô ”6Žo{-û´=£¹-°g¾û=õúBõe²B~ Sz€ô:û‡^$Ð59dO/?žóŠ´H[ÊÅ…ƒ*ðª3SÉ}h€ø²Êx“ÆY ç:aXÕ‡’ÃFÔ„ŠGêÁd¢KùYE$Ò"šªPÓÖ£(”)Ø^×õ¦— ';N \Q׆-ƒìm·=õVDÓŠ”iûÙ‡žW­ÂáX/„6'u=cäc£>a;D*ýTn0Ô®D“f"n)D9Ì ;žä¤mã‚hËèá)•E"VjãaïåFøÆŒ%>Né]¥|™v_qì“¢¡`ÓH¹sjJT ÚEàßÍYá…?Ø9U~÷y­0òƶ›Ä¢A6©ÍZÊ¢0Ynmí¡ àÛÚ­í&ùI}=uuÍæ2ãé·¡ ÏhM¿'¼Aõ(¼©õÂ{e”㊛ݎ¿Áq|¶8 ±H±–to:õʇì5žÅð§²µ»æÆµ[œ¼D¶˜qj)ÞÛ¶e :ÌM’mí¶°ÃdèÕÇ[í6W÷²›‰!NŸ™ê`àñàNÎW,xƺ©/N’ "G¼#}É75Æ(žS²±Ýܸۤ&Z9 Jý÷&öc\'Ö_Õ‘kî½%áëž RK•ý?šF³dã¤Å–ADàqF{ƒô“)Q¸=q>}C7ü(ÃÚzÝaÒ ÷ºÞ¯ow<ïí¹{‰·,I6ú¶w.¿Ûu`mÁÔ%—UÃüÝÊ]âþÖÎÄÜXg/†ð:E¹kÔ»b}¤c†cyèC/{ùJ û¾B¦]„;„`¹Õ¡ ^n ¦›OL¹ú†cíMú…fÜ_•˧y¦*ž•±ÇÎÓ&+®ïj{v!°ú¸›Ä¹Ðšò¡é:ªoùM¶Ù»]E¶ Ò$#P*EîØà!ø.‰ùW¢ 訮œ»EÚvõþ=Þ…¦ ´)¹\˜×Ǧ–‹ y±W>µÅôHmsz±-µô 1˜*ÓÔn—ýLämìmcÖ××SÄ<‡+öCü~^fŘåî¾È¯îZÆÑ2XîGú¤à•ô\øûuBvùDÇI­Òu5ð vÌE0_;|Õ‘æà8\¼6ÙôåÉ.G¸å–û&ç*·ÊÍt¡Ááû?îe|ô þó»‚æˆ¥58> Ékü˜S¹dKá»üð´<,i„‹(Aø;íÍôט)ÊôAÌä†ðžk÷ Ïvo“ä^5lÂ÷½µ\OjSgƒÂÏ®˜r£øFª\ip0/ìˆÑÜË—°[àð"D*uAØc䌂 ûeŒ»µuf`é:ÜoÃD0‚ðµÖÈ×4.?zµÁßÐ0Î!Ù¨/\¢b§q'ð‰°þL0‘ê™Ó í@2|ôÔH.ðî?SV9’ù N:‡›céa™?¬.YÞl2ðñÇ2ÒÃC&¸6Í|”\^‹[BA0ÇHNß¿*+#­‚ûäVÚÛ2A¡¿å#ÔËZ€*1oÿiT~LPÒò#Ä>׿ÜäñÔM ¿jÅJÙQYF+÷øûRÎ7Œö]Mø‘àZÌ®'0¼jQ×Zâu>ò¢© ›D¸…C7q¹¢ kRXßïÙ\â¶Qw¹‡ò:^0¦ÄÑO×MöB§ÏŠÿ©c/zGÁqí¢åûqÚš`4rWš°#·Ã'ýiã¥À‡îïÖ”Ú(JïâþÆ"#‘ºOꮩ½4.ʹò®Å‚©[ÔböÓS³Šò5KÞ¥95݈ª.žå¥·œor Ýy‘,ßÿ‡•ÒÑOùíÂt¸wS5µ€F2{‡„zF(/™nænWoÉÖåBË çw¼hBdr±ibè¦CÊÌ©ûÕÿX›¦w¥òa5)Ç}Žï€·þû£ÿgó\æendstream endobj 373 0 obj 5026 endobj 377 0 obj <> stream xœÅ]YsÇ‘Þg„¿ošÙà4»înGìFH¢,sW¶% ¶Â±Ú¤A.A$Šü÷›Ygf3ܵC$ØGuy|ùeVáõé<‰Óÿÿ>yrÿ¯îôâíÉ|úüwqòúDøNã_ç/O¿>ƒ‡„„+Ó:¯âôìŸ'ámqêä©]ô7Ï^žüׯn þ÷ßgÿo(ÁÞ°ë4/ðÒÙxð›íNMέ«Øüq+¦u]ôºùj+7?lwbÒÚ8¹9+Ï|®*½lþ WÅ Í:ÿµ îH¹NRÀë©¡[å¦Å­vó÷­pu1äîŸá3ß4mãÀUí&!ôæ!^]VŸÁçÛ¾àóЗ2b‘›?À—𑾤LüÀ"¡)xA)xŬ›Ÿ¶;ï:±lþ¶•Ó<è÷×[=) B{JÂ\*»ù ¾.¥´–j³BS6iÍMi°§tOÊ2þVzž[dVÇ?¨PU@梸&7EP¯³/R‰Š¦À|Œç?± :"©ÒµÒŒJÔ% ÓA¤<- ¸Gâf¸Fk/„}Œï¯K[:æ¥8 …Û~bíñåÇeoJ\ÁìïšÆ)-âûž˜êž}&ÖçUq ÒÀŒH|Ò§¥Ò'ˆH< ˾ˆ €Ü×*Ô  ÐÆ*‡ÐFküúÚ/jé›`ÚÝyå0<=NƒGÅ×%5®ÍBÝu7 y’¿5øÔIòÏüôÓg€.dÀ„`L·ÛÄ© ¿ „0U/,L•n–PWˆYÜìè×ìüñÿø:,g7;1kå¾(eý‡?@ž¢Ç}Þx)ïÇp2ôŠÔù°á4‡ØìFzñN3˜(ÐÀ7ùâ‹øä@ýäeïâã|ñM¹ø4_ü•þ”n?Jq¶²’}rö¯Í´ © Ãô`p:ÐíÂ<ÝvràU˜ C:Nfè};u÷&_¼(3TæòyyòËxLjûŠŽÉ é³Æñ<Ç?§ÞæŽÇÞÍ ¬§õ#V!b}’‡ô.ý^¼ÌsuÍod¹ ½¬Ô3¶©«Ë÷§rÿ?éÅ45?í]s*'—'Q¯ˆ›²¬äõ«|ñz²w^.æÁõi$p•^;¥JÖ>¸XmM‡ÙQCƒ>`þfº~‘9Žêkü¢À[il !&¸ @×xL^šb@îkï"Gø>}èER TXp÷Ò¹Nð’œ7èc‡OÔ ŽAéÄyÛë#’ïäHËvŒ>yîE€'€}¤]ÎÖ1>V¶fààš›dCJ"ë¡Fšä[øuÐÍ:d¯ƒ%¨DªKë®<â ÿ9 ªK¦…(¸ÄÆd¡½u´pÀÎÙ0/íàú*É& §Z6Yš£c )€JäubMfFÖ ´3ÀÁ–-Å$7$]—«): ™•FQ`ý»¢™EŒÓȵËÈÈbwXlG;WE  k`ÜÀ<´jP~"ãIØbsÀÿ¾ f ½@º1¥.2…éãmBœG­€PY'­˜iù‘ORÖ!XGm´÷CNO$hE¡}Uâ×^€Â@XœaTä¯e)²öh;!HìiŽ/ E:1f4ÎÁÜ\”"u•¬š¥V"dÖJH{T˜¨>AלEž}T5•ð!7× bül"ñ ·‰Ê.þÚí¨‘eöjPî¿'ΡG!¶aLÍ̪±Sò”âz@žŒF-֛¡Il}àz$Éìu‰–+Þú¼ßôH“Ô#M¹ÿ+?Óc5°k×™3[Ù¾ðůø¢.*Á¯—và Ðp À®rqª¸ó±9%‘P¨Øs¥×g8ÄJÙ„¡'YÅÑž'ËR;zYä&7ÔÕ ì}7%BHL.Àb˜P–•zžvK v; Õf„å<¯3ò]FÚ¨˜ëù€ƒ­’‰Wa¦ò_ýÀÛà>ØXÝò¢Ï:#2ÿ™E4ˆŽ¬T+i¨^¸Fumm£@ #ƒ`”kð.aŠ8•4´mØƒØ²Ñ æ¡#ø€LÖê¹mFPjá»^ô™MÆæh7õ4pbøÖÚÂSV>§õ¤÷äTàôYe*1¾¦9LmÄ0sMÃÛ+2+R~R$C¦ÉÏ('Z¨F&¹òèd$—QOÀífŸR=}OkßÎ9Úv*òŒËTý3¢¦µ(1]šž6ÕÕCu‰.—UÈà ³ ÁÊþ¨À¾¨~¸§¸.2O¬Ëˆ\žõª7£¢š2Ž"‘Dyzç" Kdƒ˜§0„/CQ¸„9çØ =Æ}B6-Àâ*äå±V«_ Jß’ó‘±:Õ<ª„ë2¡Ú0ÏÐsç®ßó7!›>ÛC .tKØC¦|¬SR,ð¥Ã!I/œÛé‘D#+µÎs0x,9¦“{•ZP°‡wAGa|ei¾¸ˆ; ó?0«WŸãd‘Dz‹DýC,çgXÖ°£ˆG©´èÄÜä \T•†¦]YŠ´Öðû¤²¯«µä»ö¹o¾œj-AHC˜H:'ÞçV–AhFJúxíÕÃvdãK ‹äzT¡¼D<ÕE½ù/ÛÜEÒã¼ùx0áÞ—¼Y+ÊecXèHå[ØL½ È\„:rà «¤±Þzõ]~¥£ª„eáõã^^~ Ýâ­vIR“À‹,˜ŸÅQ±'~°!Òl €Cy Å‘Ë #›JöâC2ˆÝ°'À.9©ìtF„¯cd%D½à˃šX„ªCª±ÈTl²;¾ÆÖ‡PÈhªšÅÚçÔ4o˜ î/m Å`CòiéVb ¾¦1ÚÈT'Q¤­Œ )›®çPh6r!‡o÷jSt>êëá@¾ÖÀwºˆæ…ÜÁÈ݆,8˜~ Fú%]ý𨍛ž‘dÅ;ÙДC„ár\ê›ç‡UiëÈ]EÈÝž!㪊I«($6H²ÂºýEuI.tpU½‹žQ€u¬„‚Ð ìŽÄ 0Ž `0\ή±žÅ̬¦>×ÿE"W"—½ h˜TN|µ]gj™Y=~ÞÂ’NÛPV&˜"Tĺ¸ÙñD»ÕT yYCvåCrT+„)šÿËZ!d,Õ ¥$ÊÇ Q Ÿ€t7®ï•™\RpÊŠ„¼Äkº+ƒ× …Ea˜ýŠfXIäk­…{s~w¢B©Ý{œZ £m:ÁÿÊöƒ墑rñ-˜uÌ%¥D…ÕŠ6t—uOmÆàuOŒA¬{¾J0}+ú4ŸzÖº/Ÿda éag ÄS1SÚ$ú=Û#~'/é!Y*fFØ6M._+XïR?_6íJ%½¥ël·!Àë5QRyÉÈçGù,)Ï]UkïÄ—B…g*‰U$ 7Ji*%@3ÛT˜Ã6œ“ÊGÈÚ¶ëÚ~6¡é¡4q‚8:™4ëZ\$?B²®«õý **„”o.XëÛ¨‹0v,M"ÌñÈæGO0›¾'p”©™"â+õ˜Ïêèfte?©ZšU/‡¹æb´},¹®» ±HÇ.I¬z¥"­4z«ÒêÉõ6×û´H?X8XKª©‚®ô®£ªvÒ ~_ŠIËÞŸ~ô‹¨ä^äï|}_zül»è 8|ßc2ØìáòHÙ€H{'$|a\.ï)+a1y釭O]°¥þ(/Ÿ¤ÈmÇ(üøJ6«H&Tgó¥Gw©‹Êvø÷T,TšC`MvP&–Åæ=fLeö° ©„NsÃU¢ ë2ÚYÇÊ+ÑH–5Yvd+>ùÝÖh迤ù4§ÚP*:¡„ìZ®Ó‡½R ÃËÔí[na Í­Š±Q×ÔËÌëÚ† iö»qõjxx´Y‘õÂû©P[²-½ûJ:B w»ŒHGG*ånÃ;â:¸¦®œ,åi;R—«úÔšùgü§QÔÌg'P ê¡øþ•Tb$3É·(I=ѯNbm±£æP“ÑsŽ‘ˆt¹¼.Ct{fÙn`Í>ÇóÈÒ‚}.ïÃPÃ:E…Rþq– ñÆå`E^Eš\p”H»Ž•µK(WV°ì ‹ ¤ljµk×t.q3*—ÒU2ì Š •)@é1䤷½ –dHäýUVœL·`©(|ænðpQ e3;}¡zYj¾»À—o.[Õ«tÆmGøLìdð[ËJ“3ÈE‚|é†Ëêý–vÚ + &êýPé”*¤Ž}ý“‰>ÛaÅØ"bÙ%/»‚Úví9Õu§ ;”?Ãþù88ô}¤â9u‰:­nOË@м‚\á~Ѻ´"`ðý•„QEC‹2 •B,1Éõ¤¸ ?9¬0ˆ »@†‰°p!…{º?ÎSmí4ëzÓ×iœ”?èmbÇî„óâæJ¶ï6¿1µ°ˆ%Sý¾Í=úOšèãúº_¸µŠÙl’Zü²”yl…OGT§bD”ku>À`^â¹ Ç×$ôãŒQ(RÁ%jÎ"ôWd›×¸ÉwD³gùÐýßtD2¥áx¶«$wÊ<,©ñSp=®S˜`½HÄÛTëµê›íî~*º±o,튛(‡¹šYÖv™À…>÷ñ̦JN­ê ßÑÚì%­ [Zf(Ýy‰uƒa»ü¡ Ìg°â¡mÓ9â!…ýDT¿’2އ×|%˜Áð5 S‹v ÙYxw’“°3eó¬ (/•ý‰Àª¦îHË´¬tçrë·Ec³);(Ѳý@šú£ f w!´ˆÆ½vi(Zô0…èÓL3äІ„I»$hBÒdRÎ÷€ R® sˤŸ%Í’‚›•ý¥ž§‹J«š5‚ä. ÎXŽÅ »Ç}\ë·p(Êu·! Šʨoš)E×ö*ŸTÒCŒŠ'ASb«1…`^+ÏKÂbøñE·ˆ…Ub†ù“‚VôLF…žº l}@CñFËîâÛYb%¿;˜O j*û±(]â¾Ãõ÷Ð/NŒ>U·¶± Ì6 î¸Êõa3ŸM•˜½qQÕ¹¸Qñp‰|d>¥0—cpxS³xL 12¿5ñH˜Öj^æÀXÑcJì&Ïø÷×uéëO•Uêc;”L‰ýù±Z„ì!›Ð…ÂûÜ'’µW°En)q‰$ª@â’xôY@IיŌec&ùf4ºú%¾|+YL)TYÑCeÆ_4¶¸Ú“ÈÙ+×ÝÖ˜vÔ“,uÄö Ñ¦¿D“Ü”pÆd€“ã/ŦºÓ@… Þ 'gž=SýeêI>”B’—Á)øöìäǓק,ûó+a†—S©­žìr*Üâ«Î_ž|ýðäþÃ?þúææéÉýŸOÅÉý?â_ÿð üõðÁ鿜|ûðôÇ[•‰õ}Nâg Cá¸Ì¼d_âd+ïD‡9{¿—K|Fh;ò%¡NÌ_è…Îï·aŸ”pwăIÖ2lƒG¤8ü8L¦3ÒÙiWÌ~¥çT}fæ/$¯¦¥'³k&Ìœ¶nÀµ*1õTH)–"i­ï1q†ö“p&Ä¡‰ýÓû¶Ä]ÜØûTHìͼä)$ MJhôËVsW»ƒÈée>Y=¶-0àk%Gþ“ðÕõ ÂG>7ý‚ŠÂÔ;»2Ÿ¶ˆ»i•ÕÙ(¥ãSÂòî§Îî¡90½ä×_3Ÿ‹<‡!áN0»%?µ-Vúñrï”Ìšý.ÆR¢Xû×$œ¼é,xè(ÿ˦¾4@kAÉ…?ðƒá,ø˜›N¶’¹>ÜZ¬ïl÷ÙújTÐ’T¿ªIŽôñ½å†n&À°8ü¼×;÷o eˆ¤ÚlÑlñ{«SÔ²Ö VÒš=è5nàîÕøEME?Y gc±—±ÁŽÓØÚ¸sO<4ûhA¤Öe@Ääh™Åˆ\f½1™ÅlÜmk"уÌU1ëÜüøÌZJw˜•Æ(umšÒ!TÕM’Â|²å¢¡N=¿¸>l>¥¦ïµ9L6!>À:äÜ@bEÌaV„Œ¨:–ÕÇ‚iís$Í¿g ¸ŸCãüù<œïPaËDS>]Îèf[»s¿®*²ÎÄÓ§JUÃqäÒ¦¶vá‰YÞå^Fç|Þ+¡á®eíRmÄÀ³3[¹vûI 5¹uY77Æù±{…;SÝÉÌ+ÚE=ÀL'wÓB¶SD¶ºÖ{Å(éi?ü‰ŒøgS·ª8ÌOH}BrÿpÊ´VŸÂ¹§6nióé!°2ìáhïÔq;ÇŠƒýý1=èÌ:Àí%.ºñ$¬CˆìA>PÖ›¦eXÑýXÊ¡‡ú·(þ°ÀŸ·þ×^øùR®:Jù*h JqÁ°°7ɬ²³SÊ.;ê3ª@ó̾g¼S¤ð$<ŸO€ã9ÒÊçÍènà«+^ª?¼éè]Ø4ß·±N¥#³ÙVÁ”3i¶ ÖÛ&3½[õ§›$JitXJbd#;¯ý½PÇsä|³iËœ_"x‡Ý™(¶$y »íøtŠÂÜÞV¶”˜! 6ôºwZçwI°2–¸Å†ý‰^Yüþ‚Ùøsû=„ñ>zYÿ_ä=þ"„N~5†Tý­Ê¿+õ.E†‡%ñŒ*CéñT;~ŠGù©µà‰ÄäîŠÛre±Tk,Íq”ãR⺧ÝK'—ª^Vwš{ ÷‡žf&ûˆŠÙ{‘–¥@Û-¾dèS¥:Îà‘ç{ǹèžF3ÌÅ—N/5A²1‡Žç.2ß§¼£Ô§–û'xÜŠò&¼rJáU5Oàül'Ýðƒwp¸!½Ÿ…ÿ¤šš6\Îûz› Yu÷ýáôÝopjH†} Ö a. Rd~q÷᡼£ì€¯+¶ýdeGª{uëEaËïŽb§dtN)w˜9â…ÄئC¸¿ÛÆÊÃáÊåˆî_6Ût7ºñ?ÎÚ¹rÁmMbóïÛ|tõûÜÆ›r@ó»|±{àø½rñ}=þô®wÎôe¹x/_|_.–×ËáÒäê÷?ž.^GD&ÝÚÿøó|ñÕÖÿfíÏ«Þ÷ÅçùÁWùÚ9£‡€3=EœbâFúú^$öÁ­%¹'í\5?â;oòÇŸ4m†nâ×" 'q“H-½Í-ñÓÁ;½É¾-÷ñ·Ñ£Õ}ôÇ“ÿHëÀ0endstream endobj 378 0 obj 6408 endobj 382 0 obj <> stream xœí\YoÇ~'ü#ø–Ý@;éûx ßqDZ˜Ã°ó@‘²$X"i2•_Ÿª>«gºw—Ø@`H^ÍôY]U_]=?²‰2ü/ýÿäÍÁ¾µ‡/®ØáðçÅÁÏ<48Lÿ;ysøñ4’žLžy~xôãAìÍ­84NM\½9ø~eÖz5­Åd­•+ÿ`áÁÆ16 iWŸ¯%¼3Z¯þ´ÞðÉ9ïõê þôÞ)¿úl½‘’OJúÕ'ðs²Ž3¹úr-ð «Jo¦9oê›ÊT Ã.´"Q ˜Öö•mdÐÀŒ\X¤D¥ÏB±f¥.3@¥®äd€ÿJ²~Üo«›)çïШB·kdçÂv†<$ƒ‡’SIÛTÞÎ@„ºƒnåNö €ó:6àh¹)×Xnn2‡¬Iò9ì qéNɃ „š}ä'W°‘á@WJë[üç þ…LІ‰@8µ¶yWž”‡çõáëòú(€o‡þÇü7£X¨ŒÏôY˜ûÿz‹—a^ç59.Mò|MÃåroëÃËòð¢üzU_ßÒ…ç‡ïÊÃËúpgwàI¦¹%ÏHóòð$4´Š÷Éûjô“M—Î/Ë8çåÙu¯áI§á9%Pžð´7NZZée çÍ<ùçUmz]š'[TL®nér&•Ÿý°.¿»ÎŽ´`Kˆ 9*Œ)÷rvˆoXÆ)A´ËMù×Ô^oú[ÚØ!x†÷žuØ ’Ü\á8âÜ[P]áá,ÄåjßŒÝ Ø˜¡O¸ ™ ªmæ~õ–ò–Q[4X©ôv¬„ 3°xTªðÁmbA\ã”àÌ¡ æv2jäÓ¸®êw¹‘Ébƒ «·Á â^ŠŠ‰x\™¢76$çuB½•V'**ë:V'.Lî¤Ý莊5Fž„n,¹ûÀÐ?ñ¯'E‹|Šÿü¦ÂPPö†n[z·x»§^ßÞ=è5agK]_Uï^ € ’'|ÕÛ"Ýw§6<ëAroÂ…ò„´ËBA_VE~^¼îéüÀfÜù gžJkÎ{TÁζ[ÔQWÆÑÊЂ¢_ôæ»êóCÝwô!¯ËÃãÞÛ^·j-°£×'¨t©_%°Íi{±¥s„!7ºèÀÀ-‰Ñ`LâA¡ÿo¡9±a‹bsÓZ‹ÝoÑÊë‹ä¹ò÷­à A¢ŒÔçË!ŠôdsÃqDµ:dßܘEøÞfu"k”£Ø÷…5…ä†kO ñ²(Îß”gs\ ÔÕ×òÛÿãÚo×”üUáÚ²vqmGŸÆ5,PʈÖ¤Ÿd‘X²'ÀH%tå\ø/Ïh)ŠTó ˆ“ãF ?å–¯Ã/LÎ` ÇJ˜ PO\¢ä¿Ä•I%êhhBìY‚Þ³~õ—R;[`h.ïÑ }dJ{X=ÙEÁ‡Ƽ©?ŸÕŸ—8˜6R8Œ…Õ+CÛ^ÃC +Ñiñ¸ä³úº,/­„+ÝÃ{ ,üäàè÷ßÓ¬C'+Zuž"yµ‘ $ó0‡4Æ0ã…!m•$ʈ:Îê]Ò<ñ§yXº l ʨÒÀ ’bîŸE?òôˆ©#2v…!¥EœËâN·¸ÍÒøÌtÓûŒI+4«ºŒ¯…5À˜Ñ‰5(,˼Ý2Ê{'YÕtò¦¦2$˜AR,W˜ii…$5þ%ò0Ó‚§\Ž„£ÂÄø´ŽYYîibô%)ǶqÐvä<€ùãµgÐÞ©I0ðcÃ@Ok—˜p—°.#²Ç­·Èž–0OÊ< ˜—2¦ I[E¢Á9i`j&;Kù3‡ñ5 ÊœGF+¨´!K0LUš˜¡Es™gkÙÖKæX£ZÈ–WÙWc§¸3‚½BÊì—W)+é&ˆÆé ÍüÙ@;)pÛ³Ž…\Gy”IÄBߘ²¦< «ÙGæ; øåO$6Â0'ƒ„S©n6™Êf7iNr.$WN²ÛYÁº•be!Ô<™ÍDZôc“)ÕzÛi˜ß;ëRƒ¡1>g€™kÓdòì“g$áÛ²v[Úp–·N2 ¯lÄxÜ0™ *ËÆ*­Ø=ã–ß±ßݹ?áØVF«W{ .·ÕlÕÙ”}.lS–ʼoýE¬Þ@ñ?‚“˄谰Zº@m”~-G±ŸºiÓ{Õ]kâ—è’8,€²]aû›†×[áûB$Ó÷N·$æ‘N"M™ÙêÊWqUgìMê1»Vßó”ÄhpE˜ré%Ø›„óúÈP‘:•Œ%\ÓÔàv« Ϧ½³Ne³DÂjƒT÷iÓâN´$˜r«…õ“Ük%)ßÉÅÁKE‰,»¶FñJå–­Úä(MšaÞ8-q @:8n—Hé62'±‡Nh $á Îp"zÛDa%™Û«Õº%¶6Œ?Å\’·!˜Ÿ:ܦÙWȃ/<y´´ØdTõaÆân­¾^Fh—à|6J?,‹ƒDO˜Õxÿ[#É" $ØV _­œ·€ñVh»ŠÙ„œã¥åœáÙBûõCÈ:ÆËÒáŸ1Ÿ›ªÁgÅå©î ÏÚˆÒáBƳ²Ì$êè«Ò[ç±J?ÎÛ\o«ã¯õ ÚŸ.h] ÓÒZ™&yÜÑû&C¾HÕ(ߎS(T:¶Ïý é‡*ófÈK ®&áÁBÃRi^Í¥ÖÀ%wJ‡×31 bS“/½(¤ŽÌ{/æÌ‘ÇýÒP–…³iÒPFo-WÈ}öMè–¼ÕÃZí˜apY3e¦æ¼†a܈ٖJ yÆ¥vm+k‡G)Ã%IèV¯î¥æv/`yƒ¢,J˜Þâ½4Qr¾q×­ñ{ÚcÔ*=°Î, ÷»g\¼Gþ©ZÇÔ&Ô²‹‚=4mˆ³¨š6ðóþi«œGàzœ>•àÈé‘~(FÄéã@æx_X~›¿'öăd *Âïˆ X!§%5•ÐÄ0M~¨ë'G ƒæè6~Úd«Ôï™k ekn²#3¸ ؾLð®Û…ˆ“»CƒÄàÉúÝšÉá·ªUÙ‘*@ùzWJK.d=‹zZîYÞ“àºS$†µpÊïŒ~¨@|°»ÐÞMvÞª/Þ:bvke8YßC–ò8€¡ZMIKyö3‹~éÆ`ΑlÍš¸ïVÍœKä"£])ÄsÑïoKsÂÇTôÎh]£‹KÑè\Ñ";Œ­'Å£uÇÇM”nù°ëA› ûb4ê>«mnwxYm'eÈÅyLšø ')÷ÿˆMþì@² wÅs™Ûì«ÚÍë/JžIŸ«[ÕèТøü>ye°üP@nóçDÚk%Ó‚éÉ#<>y]Ù.“&eyºIÙ¥rNŽQ a\wS2fsчö/±S:y kºå=Ôx¨»,úé¡bî uv‚÷Q*¶)5šÝ FÖ•ÊvïçŸÆojÜU¸Âç(dN{èú5#?1E¼SsJ›%¥=|BýÛýFÆ€`ír¶s¥ÐÝjþ“ã³´;îRË+ÈU]ßKflH¤ZKémùŒTÿÓYÛ­›NÄÁÑ›àZv ÇEíµë«^w»ËZ[£Nñ±ú.ºìL÷}Ì©q–\„£þ]¡¶:¨Wc©ôƒšˆ¯«¿–§ÂN8 ^¸sg@?Æéu'':÷Œ"4õÂ'ÌÔ{Þ…"u¼ çñÛ^×a%:"îß+"ªTp'—5ú^eîQú¸I;n’9â\(@Â&{…«TvâlV™‹Ð2‡w­e4à·Ý4c8ÓÙÅ< Š„úaÐZ…®b ÊÍÀA±>£#®Y·…éSyг”…L¡ýbIíÝõ-ñý|0IµÆ¸9D˜Ï!MÓ§É[Ž›{ˆ˜Q(v‰&ï–üáÒTÄ×…;=•®[»¥ˆIÿ"z2-Ÿ×ØÝ.çàÁ¢˜é‹¹ïcoååÑúŸü þû/2 µµendstream endobj 383 0 obj 4967 endobj 387 0 obj <> stream xœÅ\io·þ.ôGè›÷-¬ ï#@ 4qâ4GÓÆŠ")PYr¤À:ìȪáþúÎðr¹z_hcX^q¹<†sÂ:œžs°f9ÃÚà Î"•×0ÐÎÖp¸éÈ9“ÀÓÈL º[ãQdyµvÖ ºä¥ŽËb®€£/prc¬QÓÛ:ÏM}Œë°RÖ_V¾: bÀ$µc·`Ç`Áæ1QÚØö=.FH•^ k¦7Èç– u¬¦µ5‚®‰,OÞؤ‚óÖyiØéÞX?+éÓ–q–õ-ã×£Óé6 ›a ¥+›E†B€€åó¿ÀU˜Ùh;}¨G÷:SMÃÙŸåõš¶1ÏNHù%VÇý@>¢}Ø ŠÖ†í¦MYn$IZa€9@©iXpAeþ¬öÍ“àî@ò™HƒúÑÈça—'-+ïþ g—èi˜©4FÉÖ>hÂÒ†kÌ¡§wÛ]¤?Ô¡kGd〬®ã|2y¤ ™ŸêaŸç©Pž¬yâK£ÃL«²„×íÄC¬Ë+û,Y¸céïÈg7ô¤‘!„µ’¹ýœžžÕáôV™Y»tºZͰ Xç¼HÆMÛ;Qé• ­¶ŽM³—h®An=¦e0þÕv¡Õ›¾‡±ŒáA©Ä]µLÞK2R;a¬Íb§uÏ^'•/AÖ,ã k:Ë*ð3ʸŠ ˜Õäc…ñÇŠS§c¦yC‘ŽÕYÕ«P`Œ£Ö&/3(¬UžU”.‹Y‡F–ÊÇ_´D Ô©G{?œ<ψœq2zQ–ï©è6$$¸Fº`:‡Ú ç>ÂÑλL*vQ˜|¤¼AAN‘÷8' G”Ì㬨;•œ…qU——¾ïq=zæ0AôWldÈýt!±£u”Ô"«·BVÍ@Tîq£ïu:ÿ),7T¿Wƒ˜[›u¶Ž °Ðmh+ÞÖîÍ{Ð$à@dYVb)Ë€€ „ý©Î‚n^‡c†ÌmíhÒ¹ å:Z8jµøëéhy6~F/ Ø(à‹Tz,’…LÐg¬Ì_U>&lFèoÞG— ô¥_²ø%…Q¯Zº{ÜA&ôÃVI ”Þ<ÝèúKGŸÁî> ¡H?ª?Ð[UóGN;iu÷‡Ê•…~çõô½ àøŒ1L¾œhðô m½‘k•Oþ´ògøüÄë3ì¦ôºBŽ#‰[ÕX<›¤m„g #ùšÆÝ{gÖΆ}öà‹pð|µêŽsÓAž‚/X›õL£7(¹“k#p4ÌkMfèÛ E¦'žŒu¨2'†­’<¨¢s¯6Q‡ÃŒœKªC‡Ÿ4ÆPzÀaõ»ðè¡O+­ Hÿnâ(Á\âJ?ÃG†9Øà÷T ï[d/€Ä’¯#û4Þ½}£Oä03/ì›  R-¿¼°ÀÇàÙí[œ"RhC½Ý|p¸fî `òöæ<Ù0N$žo°ðAœèåcʼnNÊG5úó~ÔxUßÔÆ§¥ñ¬<ŒbKWµñMi|Z›xÕm+º}ƒ`3µnW©lÕNñ*¢ZîÀÀßPýYöv¡6Uf)ò¨pê7’ž—QµW@´ ŠeãúÈ1&ïgãÄN …è¯`9Û¸5Ãr=T–-Ñ0^-¶V&Xl'ƒu"Ž® g÷®Gâ~E¥ kÀ¸0Ç3 d;–ãíA.åü·CA¯"?( «¥'Ñ%õ |ñªÚÉjºËÜd¢ ^†øÑö [sƒSŸdvùìïìîñÈÿ©ŒÜ†¾ú"rõ)<ÂÈŒWƒ ˆ4T£Œ†b.VÞ6A¿~:ü¦S€hИ®z÷>÷!Ë‘Dy¿D)ÀÈB—'õÈóR.z^·`£<ï°hü° È=,ôéù ô¤˜Ô›¥G„N½c¯,ŸpÎQ9náJ%¨¨ÀÇÓJw{t%åK¢Dh]ž¸ÒÖã!üÐ:bQW™ði£çš §!;ÑfB^Ä‚ÁF1º‰m½$ù)ü=q„#"ǜќ4T=ua@"Ì{**ÕGÃe(ŽžÀ+ôFÑŠŽ)1ä6ÔR™ˆ(ëªã²x+_ècb˜÷j³*XÄU’`e3- |相ê0ërÕJÂ%’¹ÍE‹4…E¬pPU¨õévˆ, ß&Á*F{þ¿Çh˜tAñVEkùõÉ蛺޲¢Gn\0i¬wn9)Ë ˆ¯îHLy,!q¶ BÐhz®ó°·–O#—íû@uK1f"îÇeeq›£)Õ‘ª¯F‹ÍÈ_ô%lˆÈn³÷5nœN´ÍÉ!SfYV:¡££eèô ª´©z7Ì@r~!keŸëjÏÒØ«ž È]çÖ2ðri¬’¡|hÇà´6!ó¯<˳”ÔsA¼„Ôý”z‚!¤˜JyÜòôĸGÛVrïV2$Ê6F’¶-$Oµl«5ÄMÉ;£åöÎ0G ͼw!âù$õ€ÆéߊlkD©>Õ·µJ+>­dÄ ‰ÛP²V‹ÁHn§çi^§N)deU:8ÇüÙLŽŒÅíÐßúaUSõOúé Ñù‰páVòøi§?QÅ\^†hmz}B…2‰dev„ÓŸàŒ‰«tÈC'”ïÚúžrD3`?Ì2ôåÆÚ}á0NÊíJ¡ä¨º²eê°é6>šµ-a4 Ä:Tǽq´P&…’ËhYŠJd$Ð)¨EAwOém/ˆAÒ‡1`.çÈ©jã$C%=JåmCäá*„"[+x­¯{Øâ‡ŽÊêp²çíIÂ8OD>|¶ÅáCС}(‘KÝJAÞ¤ÝΨ„ꃢáDÛ©¤ù©ÞƒD¬G¢#srÂׯ+Å‘•!˜Ý·~l/­² djuý“NsàšÉ R=}'(ðÅTÏ>É›cÕ*ª2D›Ä,td Èì¶<ù F:aªè~ô“tv†*ŸjôaÕL uÇÈæ×áA'¯þÍ7ÈXrÕ-j. :㦔ßë&ˆrYxΔA•^¸9ùŽQ榖Ω².haÐ̪òب> ý»AÇØIà©tøB—ÛFÈÑ‹R>ÔÜŒ,DÜ’Ü¥¨¢d›*bÔ@jÜA:Žwæ×ŠpŸ·Aºgåé4s¡1%vÔ!“d W ­3º 5FbrèZ-±ÅÏYÌNêêEïß› \X”W÷½žç¼ËípU½á‡H=^xâ·8Îéø#H=Î$ø¤>ݽÍÿÈ—ƒ1Þ`Uf„dºˆK* ¹g çAC$ïÿæÎ,ïˆ:‚PéQrKÞ·˜<>Hø.·ºSéϸZ±£:Âay--&‹1îG©óÅýñâxÐc ¥â’¦#µˆ«¢äxåˆß|¯VYÛU˦ûT‚aûàÎ2ÍCªW6ùâ‘XÔ]¢·#3qÜž• O …îþG¡¶¥¹ñô¨6²­µ_—ÉÁe°¶œÉ.}ºŽ%°²U,¯cYÙfKÇ·±BÕOˆzˆ¾èÇÅ;ðÛnd Ü`ò ©Ü]R¨q§‘@ ‹0ßs‡ìoò-L¹\[|‹Î'dD'e»¨äkcGÆ|¯Rù–a†+LÑ6.éÀ—~»çA 5g½Y)%J‹<0Ó¤Ð5C6/k®û:o«šºjó£zݵÂÀàwå 5Ï’kõxáÿ«â’ L÷W,Û¨MþŸc¬óxö£+ ¦ä-꺂sì$ I³‹ÎW6Hb[&˜vµîž?¥.ÒAÚwËô 0à»A¬‰ ðmÉÐu´ÈW5r ‰“oƒŒO¨Xá°GUÁ¹1‡,‘’_îýþüIÞÝbendstream endobj 388 0 obj 4544 endobj 392 0 obj <> stream xœÝ[YoÇ~'ò#öM»‰v<}w ˆ[vlv›zâ¡HŠ@‘²(Y–}ªª¯ê™žÝ%cII jöôôQ]ÇWÇü´±ñ_úÿôÅÑ'ß»ÕÅÍѸú ~.Ž~:4`•þ;}±úü)=CƒX?=Šo‹•“+ëõ äêøÅÑ?ÖvcÖÃFÎ9µð‡¤Ž­ÇA*·þj£'‚öë/7[1hmœ\ÿe#ùŸßo¶ãàÃèF»þ }»Ù*%× y ÍÁy)ôú|Áû C^‡ÔÄèòX1ªõchJCÔú‡ÍÖÀ:^{´Éo}¾Ñ,a=¬­$FÙõ_ñu)¥µl`œÓ… øJlÿ N––pÂÿóøÏ@8  #q=Ðîø,Ñ+lL¨=¸ÕB R¯¶jD’…øÂŸ`´ å–Ž£†q"ö}‡¿~\ãïO7[<<óë3üû½Æ_çå›Ò÷j³•xFo×÷aûc î8êy}ö¢tž×ÎW½Î§¥ó~ÝÈMé|]Gžô:ßð=æÎ7¹7Ò ˆÓÐË ^ƒë*SÕ»a†`G™ïáae–k¸’«Ê%7x±Æ8+a 8ÎJGFŽÑAâNq¨f=6ÒZHI'ñÀHÀx¼v ,{Vg=EêtçqŒ^Ûµœ5\F.¶Å X vò)…; |xœ8 Ö¨4©Sjý¬NpN (|½ù_Öæ›ÚÌg„ýu†k”ƒ™õÏ£8–§!—y™7|H>©4'è­Ü ÇF¶ŸÆiöèJ4,%Øü'd P¾Dfdc!¥aÇ@ûM+JË&‚Å-l)èõÛ °K£ÒÓQÔÆÎWcI#‚¸¯Gúõ4°³#Š\­AòŠã(/à‡ŸûQ“ɼÇ`4ó4/yYž&K ÀH¥"ž~+]«­À Q *0Ò*üL$ôʧ#!‡£Tƒ ¡N¯|úlz™8OKi–Fn܄ц³í9“¥ü56òª·(’ÐzbÌI ë¹Ôás¶ÆT*ÖÈ# öÛjÊÈËÚ€qrÂòSŸl€«ƒ72Q72èVý½,¦¸¢¾¸æ2„‡ #P؃yÀ8ë²}ô^q«ùCº   S8Û«$~(JÕÆ`­³:Q–A¥æÑÄàþÐNÜ+œvÖppfºO’þI¥¦Žž¼C[/‹‚mÚuVPúy)ä¹Qƒ”YÚñëòàY]¹]º=4êoëù«Ô°+ÏïD± P0&DˆE¾ÕtÌÅžÆÜQ±ÃCRo«ê³('YI±ƒÅ”ñ¤Y VD™˜É*<܆=‡°š¶8ÜՊ`uX 6-F“Y ÷w/ŸóqbrµEå&(~-à0£RË8Çž~g®e\[ ·!(j=‹Á€|¯ˆºˆAƉ×k85 X³nq¡M_Ïx™¼p6ê,MP,º‰´%Ž»oõzct“±K<âQ…©,}ÒÂÑìEŠæ®*YIÑ2„¼w ñ\l¨‡“00ѳc“—€> w—w ˆí9r¸ä=egªç!?Ø Ú­îÁ¹a´ÌÞ¹fôpvR¹ÑF÷ "ùûi Üb~ØnAáW=¼þ¬}3Ðuœ•Γ:ò]3RŽ4òSjö_¨Žs/ºžÄdûá£øú#ùÊ„ÅO"À›ë"#f «RLŒ©ƒ;@A{1ìü Uý{B>õy‘F6óo‡Ä>¤Õ`Á¦9XóA´%ÀãÞw0ƒB&°ÄÊȽ¹9LA"«>ÞªC{­.®gA]#–O>–R‚ÑeØÎV&S]&Ø^õËŽ`â:I»w$°‹2ZÔ»äpïvp’G2³×GÁD¦zLG ¦Mf—˜1oÑÂe:öê„‘q¿®u'Q@ÄâLgÜH0×:Y:“âç€2|Ñá^òr¦)zíKàIJ>¬ÿÅB*·³Ê3UÌòï¡ÒwKêVñj¹ì^à^[XµŒÃá÷Ó£?ÄâD=½Ëà(2­û£0y£J0“ ™çû k‚•kâ¬Ð‹jÀs(q>Æ{l`öBAôºñªˆé,›ªˆ³ UõYDÎÖZÀVLéÏR<ÒÚAa–œ¸’Ôù_pâêë×=ÇjšbÂi–QzÞÛÝ›=~`žÉ;æì±ç§½=ÕéϺ3-Ì”›mBŒù•¹y›¨ÉnšRy½GÔ- fŽðÎŒÝGryï[?Š ¿šƒ\^žÖM:ÕqMÏwJÒ>°@×Ü(hAí 0™1fðÁ &$írt+Å×hYv§ÕÀcF”µ¨+uˆñú[¥Õ´ ”:¼›/lðú¼"†- çg¼kåÉ©—ãÃùH·Ø] ©ºA˜b.âD£˜ØP‚xްá·Ö"Ðö¬´¸dŒébêÓýY@’J„E'7Ÿ·¦\ÚdG‚6üV˜“ÕA¼×gà÷“$ØdI Íòv™”¤–âæ>{P ô  šåÄw?l˜ý€€I «@%qZ<è « ÐBo\” 0"ÁßídK†Ÿ˜&66óòˆ!91OÊQxeg„øWø0„¡H / ²X‚4NE$;ÔZ˜7(3ç,H³! ¦¢ëPQÂyÏíï®|Œà°}¿–’¸HÛ½îÓ!ùÊÅÀZ½'Ì”lmvtf¶6Vbð©wšZ¥Q÷FÁneiA²!; ·ÛZZJ¿ªÛšZº‹6*Fü`jd <æåWÀÔD×]/)2»hlsX´ã~ÙvRº+%îdk•±ƒÒb÷À”†wTœÓ†ÇfeèßiSô}ªßY4zB ÊM ÙÃÃ,ô†Zc1 ¾;3’#lªGPËP½À9ÛÒ§’TÊjÍy ¸'Q"FDtI"¦ˆö=„²¶¸\(ªÅŒ;3¬Æ™ K¯ô¤h’¬Þm¼¡…OÓ„tÒ–ù?l ¡‹¡‡i‚3‡ ع8 N±;•9aAö^GU¦ÂÉC²í·,°ÍIŠCk'Šê}_‡§BÁ1ðê\–Røµ“6ið^I‘¶l$Kæ„ÊbZ:I2ѺLŒjMA %BLƒò²6Jçùm²!•µú3Õp!bö·ÓòhþÓºÄ^ŒcîÜãâSçÞd*qs?ìVµŒÈÓ$¬«ETMÄäVV~ã<ýúâÿÙqþøqþÜ;Ï#jŸ›½P?ÞI ç`)¦ äYÛx«Cã48²p‘¶2b<– ®@Ù7ñP+ô?p!~#"dX‹Òì<0û€kãƒDå#­q&žÜ)Â'¹óB €¢ZáöÁp;)rnâÇ)ž¹$½«#ü½¤ÖHš1÷^ÀNPVȘwô•S^üMm>©Í´%=:“¶|loùّ蓘q@MªM/v‚¹JÊ%{tüû^EV‘èÊj3uè.g6ïz£|·Üúªê²‹èOjN;‘‘2+¯…±ƒ‡Ó1µÀL+Ós Ÿ<éúm®[»î!*MÞ<*£âf&†^D€Þ/­­ó³Ð ÊòºóÚWŠÎjÙ­¢`®'D#>É*àHªVሗ3Ó×ä·Ë§MªCÇåÂÌR<Ô ýå=µ¡?ñžC”é^N’í¬œ˜”ÿtø¸oüŸDd;¶ÕãóÊîT7×7ÝÝ‹Nd7ÝšRP£Ë]:k‡Vhûuq“j:âQ Ûß RP%ŠX^cWuø/ÌËQFf›@O«~[:lzD¬œp‹|ú ôëb2?ÛäÒïˆCžã/´ÍÄ#ñÏj`}–ÎèCŽ,_ÎŒ\M2Ÿ4ötžDŸ¥£«…g¶ú—(9éÍW©3g;›òèFÞåÝʲ‰¿½h¾ É`££bþïpŠºUã·!Í79³B»ÓŽ—Ú,BASu×¢'’†Qð¨âuÝä›®²LÅ{à#õUr«:'Ä Ááca’ëM™²ý|’M9uk¹ÝJ¥·½B±ÛTæ¥o{@=×/{–¡ÿVü¸5²‘ÕTðP{¬ÿV¸òa–Ã$xͧÕIðª0\Ð@Ì áÒ_ýþýÌÝ`rendstream endobj 393 0 obj 3658 endobj 397 0 obj <> stream xœÝ\éo·ÿnôÙWøm–7Y -r'm“¦‰ôHQ8²#ÖaÇ–süõ^Ã]î;d¥ ÃÒ—Ëc8ço†ïùÉ4Š“ ÿ¥ßg—÷Þúœ¿¸7|ÿÏï=¿'¨ÃIúuvyòî)tZÆ0qrúݽø¶8qòÄz=ÂÃÓË{ÿÜÆ ÓÆüëôð†Í6Œ“‡—NBÇ÷6[5:‚>Þˆ1¯ÃðÎFŸo¶bÔÚ89œÖ>ÄV¥ýð´ŠÃºÁÂl#<‘2ŒRÀëy ÷7ÊÞ;|½Z½aO?ƒiÞ[Œ3¾­ÚBèálõAÀ4عìk™ “^ÂLØÅÃLʤ ¼„¡à¥à†/7[ï:ᇯ6rœ&ë~w£G%¡+Œ§$ÐRÙá/øº”ÒZÖñ´Ž™–ãÒòØšÒÒ‰x RóSئcتit"„xj£bçÙ!›1ØI¶gæÅ¤†k üåf+GkÕó8§fxO¾ßlaGJ9<‚ÖF›áåFÞ[ØÇãÚŸ‡i4FO`ŸÎ95\ÕÇi`;Ùᦶ¾ÄAÈgS}TÔxaeayx\a|Í)U õð‰hŒ³’=g{™/Oñ;O †ãžoâïÞ^šáaR1N!°™zT--q‡Réá;Ü!’%°ÆnO6ÿYiÄá]€áýÚž‘d›OÏîãÛVtM‹O#[YÖ8 ¾¯8\0´íí¨aâ:Èã:Iyû'ì¨G©ޫljï¡äó[>蛑0¡ÇEPʸí­ô¤;N¶ ÎÙŸ¶£!£v-¾¶Upæ,ˆŽÏÓñÙIw¹H­ü4N°ðfó°] ¿Dâ(o`Ž4ŠéÕF:`ïI±ž³¨‚CÑÊ?T-W—í<ì±ÒLÜ¡ÎÒV¤“0ÖqÆžuÇ?ëX\(;L¨†Ìö;ÑxÔÛyy¿…±ÞD"HhW»·r‘ú Ä$^÷~TVd^oUDÃS™TÒ2ê÷øþ9Ú )‚’Y5ŒÍ$ꌉ ž7Š žâwHØ($‰°Zsg„•Ö3ÂÂPU:ÊŒ©«TfLÜ)AÜÄŽùf(|Úcγ"…Ä7U ã¬p6, l³~.ãT!c€š–5M>Á˜îB1º-w}³Áy4¨ç|Ìe†‡q­Ú"«ý!Vûž.ÚÅØl 4ƒ ßÇZ ÃôUÙ‚í€8ë‚ëtZS)}3ø(’6ÛiÔùr ’‹AWZ×™JJpeÓîWeí+ʶ Gt\O–!“¡Ùêòî> ÊC3™¬«`âÒ,·7ô.Óƒ(‘:­a8­^ÑãÊó(¾Ê’¶/êzÒ¨¨(°b±åd”ˆž)‚ÎÊ:t#ßÑ‚úšORT‡1žnî1žÒ¹wnkzÞN•·Ú»ñæòÄe¹¯ÐvV«¢ÀÕ3ÖÜÖ=Ãc˜ÀSÌZT+ ¶äJ©·¾2Ø%“‹Æ>JŠ<NX9鼨Xü«²Ý ¤)2ÍZ['Í‚)·Ã?úÑ;„ i£ÜiDwk"ˆùÿySJò ã5°˜c&`ëgðœ,*ª·KØÁ~n ÆL›…ó‚ÇpÃ… ³'®Æ’ ¹W€Üó*¢è‹e¼@r¥W|@ìžø×’T}hs€?¤â[´»È!U†çþNÃÚ0V3cø¥@ yÒ°²>r çý< ÏLp0Âð@´C§úa@ˆ S¤W=i@gNa³>…÷­¾¾Ê±èØ,lQŒ?ŽTEž~¶ÓSa'ùh·}QÆ‚ŽsYÇá,•rìS:OÕ=OUõúÒ 9n–¡ÁÂD´¶ lq×Ä:ûöʨáPEÝ.. ÖRÎÐé&ùåûh"5ñýÒÑ!É9dØËßTS0:väçà}°ç=;ðçQŒÆ¥l,•K˧(@L)õŽXFØdW >Ð&¿¿²Û ’Ä¢´Î‚P¸åGòø°ÁÎý&صj¦þ먕3—œWÎ tk?çЀY¾ëx€pZû„åaeö²J&¤(µ 1ÚskîÌa9Jˆ€~Ø Â7镸€…›…ÂõN³·²N3¡ €±Mùu^‘†r¯ä“éÆçhM´0÷‘î»n†xœ,ŸZEeö¸:”ˆð Þˆ^ýåFM£Îv“€(8aâÆ™8BüƒNB¬¾ú&óxAMØ­/ ׄ*-)$¹Žƒ(m@Ó Æ§å=æÍç­jÝúðù<;oÏ<üET‚rÐèú·¾Ð¾P¥G\ô˜b´:«þaRÒ‚¤Á`n1Pm…Þ–By߯Ó!ºÓ.‡ç?co$=r™B“IêR¢ {¤fîó²6>*¨¬†C"3²ìù}i|R¯Jãym¼Î†§‘ÎÊóõù ¾ØWÍê‚§Èý÷0<0%†û—½á+-Îjãc>™Ëºù{d:kÆÌ1¸OŸ»ø8°WÁÓ麢ÜôAùéáÉI{¦p:ÂÖw ¢>ÙÕ£è!9<%'Ñ9®:Š&GZç’” Œ¯—]t¯¯Ú©,Σõ"¼Û%2%“ÜYdX|Œ"†3šÈóe$;%\óEI? S<\ÃÒU[t6„XÿÀ×½Gö½ŸW=Á¤µG E¬Aï'7T Md±sñ žU•Ó¼™ªÂ¡„E ‘{jø$[48¶xUG~Ø™9àL›e}Ý*ò¾¼Ô‹ÖŒ2 Ž]ªEúñ§"˜þ^ÕâSüAÚÙ‚|òaboR•¸SÒ$àíL@S¦Iº*¯«1oJã‹V)ÄÖý:¡lÍüÿé„nìØê€Ù{ÈyVüJôÊX–ôëûL¸:£Ülußv¦.ž¥ÎjÁæð|Y_a±Ð'¸XÑ'9ÞÙ¥òºKÔ~)Š Ëì܈Ídñ‹Vß«²ˆfŸ¤g&wÞaÿÿÜUOËÞ‘Ün¤L?ÃKw¦t+ œÝ¨ÖÜÒM lÏï,AŒŽÒñ0äV+HH°„B.ב‘©.¨‰ t6¯'¦ÜP¼¼€‚¥3|VЯ6rø3< ðF¡)ÚÅIj)Æ$Mü8E,¼o9Š ÷´„߇øGˆEm ,aOâ¸Íú‘øa4z÷©: ^4*û} ]P[³Háõ°˜F›"·1m߆ɘÛÝQÊ‘1­® 0mŒÓýE 6Ñ–~('1Ùa%VÏŽVÃ!¶µ'­Í)Üý5í‚OÙ¢b­+¥ï:™»]Ї N‚°ôÛ&§‚ë…³g¾øõf¯ûX8’óÞšñ2‰ƒeGÜÅÚ7H6‰¥–‹­,GÀ:`i’µBÍ]ŽX¤QÜÛäq87w(3d¿ÐƒqJ#du„CÑf[¶ÉžŒ¨<ÛÓo]#‘n5CGr׳†·× §-ê(cÂºÔ ÖÏ«R½é¸"ȧeŒËúÑúN196ónZ¥Þ ~–^RU$»W`ª)çAл1fn†[· ÍœÈÄëàà˜ ÁÊ{®ŸKavn›Ü2`ºšH²‘k¤jlvÛ"lº-rê©ç´«î&”ÛJ¥ëÖ  ©Ñ±¤¥oj8ðÍ€mfgìŽÝëDݵÌ*ž"õVE©ç 1Ñb=gž=rg“(ì±ÅÁYºf o–*kÄ7Å JÂâTUˆRì†ýIÚüð›n”À Ôµ`Ñ×8T2ï ¡€®àQ¶ªŠö©Í^Y;Ö;ŒòÚ½ l(`¬Tä?þÌJ—ü%øYv‚Nd_u“…rJzéç”ó›å:&Œ#:'…Ïyb ÑÜË›XÄ @ôÔÌ`%)!µ^U•ŒY¨=ÔzŹ:EkŠ—BŒ§^WæÚDšXˆê_mÀ…†úäÚµZ¹Þ4•Êd) $ƒ€?uÇ"-Ÿ­údW9@Ô*©ž©í•ƒµ ö¶:fWܽÀyC\äÖE#ÄÁA2OÙ9 ÑLLïM˜†È’ÁY£˜±ÑhËíC¬ÛTmz­cK–Z©¶~jâmY@•w§bñ}·_ÊÛÅÍ´zþî „¤¤l}Ãî`Â×Hbϵb¨P*&”‹éÅÂûL^ÿn÷3WÀUX”ÆÝa9â‚o~ƒ *­x¼ikµÚ—]2 C”¾¤¨Ú±d"3pc¡È—3øi·ž·ÓCˆ{2ªôLò†·Ñ‘ñQ^|Ô1x,Ïø‹Õ¸IZM~1s+xEJä"ƒ±°ð†ixñ¢¦py·]©^Êx.0Ò žÛøöÞ²Ì&kK5ÁW­Ž›U —¸pE%¦îÝ«0{†Ð-bDX óP‚Ã:`ŒèÜØV†ÍÌE§î¯[†”wm]‹`Á}ŽgEó¸8Ws¬ªTßܾhX¼¾ÃÜíe-U#5¹.žê»–Ö…ᦫÓ[ãâcõRãú0}_”ü<*îzUÅ.‚_ߪå™»ÄP»0’j!ëXÏ™CtÓÊj4éªF³äj–*ƒÝ™ÑâZÇ¡ Æ©¶Àæ e¶kŠ7bÇÔ.ühWqöÏ2°‘o,ˆ£XÂÙ'VÆœ|* øõàìî œýó Õ_¤ë.K¯*a “¤5c´‰{:$D¼£×Jt%»t¦+:ªS'GOVrgÔ]"9v…uÙëØ™¯ÇØÄ$Ûµp½:cú¨]Žñ "¼è0­4-FÙez:’n]ÙæY¬“‡möìöÎ2dh³Zêik©gòõ²ÂY—ÞéQ\JæI¬œ9¦ÙDGck=íí#Ú¶VV«öŸulmk³±"u\‘LìA1™ „ÃøÎÿ… ÙÅXÕBL3`=›ê¬éçl XtÏW²û,é«)ñª>®ø#ÞÙÈ$Œ=î¼õ'>Ï7y{H¿¼=9¼Î]o4³ÛÃhUXÄx¹yÕ‘œ9¬ÝãU•¾C¸8÷ '¡OávÀ…)ýd¹TÒ‚± SÌ‹+Éñ3qÊ8f] ºDʱŒëËŸ·•€õ‰ØhlÛû¾ÿzJ5…Õª¡6MÕ9TŸnnQ©ð´ŒÁ *W=·êr­Ð2•2îó¢÷:›èœûoéÓã¦3N$ö¹§½BI˜2J¾Y¿ù¦v}£´Âs#'êzÖ[Iéû¦1\VZ"¯0š §º¨ ÒIœ†Z±ZéyQß¿¨«ºìNËæjKE©|•$€—¢²2ø>ð×®}S!6;ÂÎ~oj_v4lC¯šè@…äã¶5ºy°'Ý¥×*ݨœ Õ(¶Ž * ´`D;orÿEay¹;ÉÎE"™™Ùœ·½)8yQy*Êß”çÑxm-ËZ¨üV«méšÒ=ðzç›^ ñ¾] ñ»+Z¥áï2^ÉÎÕƒèq«8Oåëwá«ä¥"Åm Úœþµ±Y²šj7XpÍìÓ·UËßщ—|¬Ùñ}!Ìï[z“»ÌtrÂØÄùžš, ›¶SRrl)B<âþ½å]0(â@ï•JNn‰5Ñ5­=ɵ|³¦*J e˜ž}@JþSÚE5Ûâ¶wKH±þëÝ„!E‚¸¸Ðë{+I̱[\KŒUµz”ÆÆo xíû:™ç1)-Õ?±/ ÂèÖ³S>6 Ïi€Z¸zHjd†¼g°Þͯ™žã6sÎ.¿5ÂÒ}élî¼"Óð¢t¬ò@¿,&,MÁúaß«xè5ϞƄ»áKé}ïBƒ_f)(7þ߯ޒ¥å0ô›â·†ì¿¸u!Ó·.‡Á¹Ðàæ#&rV¾…è¶×36Ö+ÍžÉóÓ 5‚ I–@¥NtŽ\j„,jŒÈpÛ/œH”]É‘õ¾Yæe,ˆÅ‚ÀÒöœ¡Ìl4R™-¤É–*º²MhùnòH½ÇT šÊa¯‘äJCßhvÁ–4_wö ûpÿßÖ±é Gñ^ãëéæÃ ÿNàZ®ýE—öëœ 8:p}UÆ`áÌEÏnbT«¤Æz›†…Sõ ^÷Þ NîóÄÂÝ%#>8½÷Wø÷6þ ñendstream endobj 398 0 obj 4594 endobj 402 0 obj <> stream xœÝ[ëo7ÿô0ú¥³×ìtôIó¡$¶ó¸¸IÎ^çÒ´‡ÂµÓ4hlçÙ"ÿý‘zR3œÝµÃ‡ é¬E‘ü‘”òn§kÅN‡âÿOÏo}whw^}¸Õí܇ÿ^ÝzwKø;ñ§ç;wW0H hi‡n;«ßn…ÙbÇÊãt+äÎêüÖOYôM»­µV5~Hß°t]×Je›û ÕZ1h×ì/–¢Õº·²y¼ôçábÙµnèlgš;Ðu°X*%›cø\Ágkºyˆœ†ˆvœbë :›ÆŠN5?§´0D5G‹eëh˜v¼H³î.t Kk+ ›Q¦y‚Ó¥”ƦAW"ü+ØY\ ÷ïÕ?@p "8ØbÛ9Ýê äeA< ¦0Pj:pG.U‡"„a¡8ª¢oÓÉDv·ìýV¸(›þ€|ö½5²ùgᜑ¢y¿X¢ô ›Oa¨ÙŸ‚T´G.a?-îõ>{ÓÎ4o ÕHÀtÚ¯=ʵZ¹æe¦AÖx“ä3 eÕü¶XJOÌz q´¦9Çc¬Ñ°x¹¶JEÚRéæ FÛjÓ8ÑÁK' jsºPÐÓÛü^ø=)K Cøó4SãVÀÁε 6BÈ”~¤pÆuàDcP6ͨ[°oAº?£®Ãþí`š¿r€o[IÙ;[à‘+0!‘O˜tje#ž…SÓ}´SùHPïqü9²ª[ƒ‚únH»e†u¼J¢‰¾ö'8ô:©öG}°ÁO¥uGàÜMЉÍûÜGÂ(‡¥„ƒpzg)TÛ£Î{y\Ô‡•ÆYCTð64ZéÕmÌ vG^¤"/}?=‹¥4èöÐü¹èu †äüŠY©?Õ`´ôImH°whr7QÌT­ÄvÈg¡~±·Ø÷à˜?" T°©‡@K ‹½N%GÿjÑ·]'œJ³çݾ¿$;×<È4Ï®M„"ùIm^°;$È´N+;|[qà»A{o qA †î’(–¶ü€G¨a׺ù¹É–“»Ûl,¯2:â¯Û‘O¡š¯¡ƒ `ACÂ0Y& xå)A¨#T=.IÓ{_L@aõàÔmz¿úÏ äFz;ÂKÔÝ—£ºA€‚AòüëèŒßNQY: 1‚  [ùÚÈ…ÛÊðòà멳?~ÐØ}@A±½§Î³#s æ¤;E–Bér€ó]F7 ]‡ÇE‡Þí IÜ~V*T¥üƒh.*Õ€rTÍÏïËŽ»‚ž¨žŽ~7îDÛ‰|’½4~2^o‰U~“â´WÕÔÓÄp9·`ñË«xÜpíÞ£2)Ý‹æqÕäØ/ó1ª)Þ÷ #H¯­É¥€cçà aJ8‚Ÿ)Ad¥GTgªíôKIð˜";ŒÚ.r]ü!{>Œþ:„>ºÆoìÒƒwµ©«§S-GHKK½pæè8GòÆÞo±ÇÙ™ß^Ù¡5ÒÐSCCŒÿUdGe xâÑã$õi©|w¨]CÞ q0(¦ëDXæ,ãù?= ÿå~í‘~‰¢]úhÓŸÚd}ž{aóÚ¯úæî´~Ø+D»orã§Òø27Âô^v 6©á²Œ:§ËM§^”Æ”ž|»æï@rÌ^N9ÎÞçÆ³Òˆüt~hÔÐØÿ±ôŸpŸrã‡ÒˆÈZg²”Ö©Áùã,Å„ã q8Ÿª¸õY "Êu³ÎKíwç:J¦Ø.ã;N@‚³Bü¥§ÄäÂ45tÞûóájÎÂBºò !/í <#y)ùDK€°—ÿ>­õ¡&Yeú‰Ž(ÚàÐ[à IÎáoöc¨N¶{&À‘¿údó(‹Oi"¸”€öÔÝ“P  ÷ÖKêm•o Ba–‘ì­d že´¹ÌFÁÞQæaKFÒ.hŒ”¤‰ ·f¸Ô͵f’¯$%’;_€+©Ê0¡o:RyÔ)Vq° ½Ci¬ã&@5\Õi`ƒQ[A…“émÀ³‚„±S.Ö¯“g€„4󤸑Ñiƒµõ6'û±ÍmƒÇtlÄûyLÜmk²Ó‹u+ç ó¿‰Ð+­·_…±”xÏûÿ¾´ÅÂSXGÂYö2W¥¸B]Và[€—‡[7„²·_÷3Px¤}< ·¨²^2(*¯l^xe ¾+¿pY¨!FT;ã1à÷Ü÷²Løœÿ⨼/g”ô :Ÿp$.({ô”:Åÿ:¥ÉÐ)û/ h]7…ÎëY1|Rû+[–Ù Oc¡9š ÒjCËÃ[€¤ìn’8¨8EâuCRh1$ÎI!¨öÙn ¢0ÕIàÃ,gFàŽzD01¡gþK Nt£ºÇ5AT‚>(éj•Ú›‚(¨…?NR¨U½7Æy'aån‰NÑAˉrÔõzˆ4¯_Òðe>ϠǾUxFQõ¦÷^0’¸QéR[_™^gÙ¡úgI%d[ N•6_}ÇšYþ?5À·%ظ[ì>Z¸5@N6OKaí9,eM,SúpC_$ïݪtöt]?—n"0¡Õ!Þ¬}z(¯Ö!º&I67“Õ’Œ–Ô!ñRŽÃÑÄ«îça8Šï—0À_~pÇ…îŠð|=¹C•ꮋHÑÆâAὠѪ]tô8‰H7uVÓÖJ©è5³RûJTz9£äæŠ]áaXïÝEuŬü¥³?OŒ ’ô5Xæä§héÊ÷É }­êÖìp4ÂDÍû?îdë|]hdWæ¯ÅC¸Ç ÙhQ€àsùkâ¦gŸ7Te”´– ™ÌF²Œ2†ø4i*¥&÷OÓû·™ê2ø= ­{鋤»O ´b©ØûH_öÔº(¬õ5å†Í>r`øv¦´<Űëâ^l½ ð©MÀGìpÐG¬‹(äE|´¡ä,¸iÀ­Xm¶XTâX> ¤1ÇÉü´ ·žœw!–•à 8Ÿ_ý‡µ€ÃõmßH3_~Eiç¥qå5´uþmÇq| 󔢯œ·­µ±½w¼Š'ycl()†LÉiM—»¤D ï-ËQN± CàT4ìzÁæ#uu¤ŽP=w†£çL0i7¬ qV7®ìæðã$eû9MÂø£y6SrNnÐí) Ü0QÏD]j ò:}²D¢)_“8ÊQ×!þuŒíæÞéŃ€hÇ¢Þ6Ão|‡‹ø6 Z= …’ñ}¹³ÍÝÜÿ°ô¯8Jsãs–Òãܧô?çÈÑhlß#âu¦_°ŒìsŒ®89”5÷æ„Säè£ žeÈÑÀ“Ðß›¥¡Ê'Yk¯Œ½]E¦¾¦6ôÃÈÝϪñ$sy\È=ÍG,륟pÆR*BX±”î1Jå`Wr)ö“­æàÖêo?ùã6ÂN=â´ã 9R³TŸô÷8ÕÞç,goFuÓ›•·ï9Úß º…Q½ÝÜø„ãn¥{•lÒçaùü¡|r´ÝÕƒ‰n£Bß©ô’P jŽçé}²”„h'†x‘Ÿ8ý½JSÿo¹ÿ5÷ ¨.¦g@º<#bÅW|åÜé%[™~±â;¯é9BÒ¯eÖˆÄ 4s&ô_—!O¯NرŸËéòÞb'Õ´Ñ‘úûíßàætÝï$D5S‘±'zAG&Pؤ÷Ö£×Qa¤¬yÉiQ-°iÕ¢­P^tåQþZßM¸Ú3ðoy9ùU–2Ùü—TGŒÀÙq¥2sVœh­´Ÿufþ¬ºaÓKÁ·Ü‘MUQÞ´û,™“ œMMuùUňץʶoaÈ?8 ¶8~F˜>-$ßT$+`ï™Ç½¨ˆáj{í#~½}ê/â%Ì|¢'G|D™¿^¡øücïægOÅW?_¢>®,”v9JO9sý‘ oŠ}Üæø$žúN9“Ú©¯G·¥õKì`ŽÂȾÈÑJ‰'*FÖ"vÙÁþBiÅ ‡œÒs*'´¹9Mcã²ÈQµÕi¤ó‚¹ËéǦ¼£PzÁ‰ˆ„'OFóz:«ŠÒ¹˜„ìÿQuj•#Ï:›­yoŽô»ùpï¾{Ô5rßw+W–ÕÝ«ÈjšY­®qh›‚Êí¹˜Ø '_©œE»A¾š“ïA:‰Ò?Z/2ò˜3\N*1YѪ$+ܶö’7AÀtG²³¥6=øyö$RÍÆ™’&¯¼ó|fÍõ‚¾¿^¼†cæ íbây3òᵆ••ç[SÚã(]‹'–ÒxÚã&­¸Æ9F“Ç"~v/Vü?sLAIMŸñsDAê ıámY$º9x=Îúò0#Û¼ÒXÎ&3‰5A:k“lU¾)†xTw°{q[X#ñ¥O¯È̃Lî8³µ7åh’ #¶<Û¹F²ëÙ7† ªeϸ©‡¬%l Ä†B,ùÊc ùp{|½}'3›£™lëY0C|‰˜¯IDsbP´DÂS­ÁÄžûÜØ`¼•ÍñÊnÖ¤£¬g eKIÕå¨g¡ž¾›•¶Ì©ëS›8¦‡0²tÈ ·÷š¥âF|B¦¹ÎÌþ•Á¤ÜÁÜ{ûó›ܦ3ÙIÖ²)šßåØÞÚ•ñ”+m¹zøÆRÚL\R‰ùVœ1Ö”¼YTæmd5„|íp÷W·þ þ7/‡`endstream endobj 403 0 obj 3963 endobj 407 0 obj <> stream xœÕ[msÅþžòGäg-κó¾k· LÔp¢WKoY!Á ù÷·»ç­gw6çäüpË2ÆÙ™žž~ïg&ív­ØíðŸðßã×;_=q»§—;ÝîwðïéÎ_;‚&ì†ÿ¿Þ½w“„„‘vè±{øçŽ_-vܵ½náãáëß®1 Ù˜ÿÞ‡J+ìÐv=,:<‰ß4KÕ:7 bñ}#Úaèõ°¸ÛÈÅãf)Z­“‹Ã¥xÚ$¼üœ!àÅ?^\ÖTÉ\Ü«Q‚å¢S6ˆçÆËW1²­ßW)mâ÷uÝoè÷+ i]¿ÿ}Ê&µßNü¿,ö¬Š' ÒtÃâ( ¼Ë³žÃ7,{Ū1vœ÷iðy<­ ¾»¾F‚A#»²ä3P¾veœ±?eÎÎkûeÎÞÇ™žñ÷¦p!°d,Vw—X`™¡÷¥*åÕ_ñ†Q²8r/ªÎ  ‡OÓ”§iʿӆûá«îÑMôBàÿKüÑå“ФñGŽqµŠ”™Æ/uÁ‚JÛ.´×Ô™Ìò¾Ÿ,‡.ä‡4x¿V,k4ïåÁ§×k=¨»5êûµò4þÊkÔQŸJÚÖÈØÞ­ºí~Á1#?Ź—…ÿ-ùe*Ç笅"2 ‰dê$Iæ!ŒFêÞ<Ôȩɜ$ÝÃï½@~ôYžšýò¨v_e+Ë%àóÂÃÃàÇ…Üñ)äÛ¤ÇïÊLzzŽíqíÈGÕ#Y[TÍ¥U²˜ñÕ© tĈÖ‡VûÓŠ­Lù¹#,aYHF;‰Á}u«”$Š>˜ÞiÔŠ:˜¥A«ª…ý¥À"T£“¾¹¸ÕÈÖ9§"Üõˆj:[s`( OƒÌüµV[ËA®0æ>Ëô_D¢oò؈ÛO˜5ÐŽ,:åOÄÈœG2XŽt‚ÎsÜhÄ›”Ób3®ò**v¬uVãöºñ*¹øGµ¶ÀèEÉ ›û¿GÙ°A%ê¬d<²•ãc"ÐvÚT>Ôym³¤h’FpÞYEH—È¥Ó¾ãUÈbÝ!*ÿYÞ(ð!mOºÊ_<¯óýƒÑ‘CéÈeµ à¨ÅÛ¼ˆ©IzF,êõ9I¼‰O§Ùg™D²*1Ý¿¿Í<Ô¸õiUh„R+yu}ÛR­2`*ʵÚÃ¥ÎÎi;¯qoRBJæ,ÏÓ°`{J™©=àLF¬zj¨Še/(òàfÌ#NSÑjËmêy²ïlr̸ÃL',§„µ‰³èülUéïÈú³Yˆ´FƒHó’¼9˜1û¿(â™K²tÝ÷¨›ÞIÊÌ¥BPÔ®zðÁNƒ„]UáÇÀÖ¬ ¨£ÈŒÌF“Ï\`ëÒ™VªYó‹‡dRJÖØÐŠ—½l¡ú<ÁøÈ¡‚¨I“Á¸D˜ƒA¥ïÑÆV²ô Ûœ'{9É®q;’?Y”MÉÔŽ …6 8‰’/‚“4ȤšMÒ HžynÁÌ͉ç¶t*V:J-;Yi×…IˆIU'[+è.¥ÆN]F9ûƒEò)Mœ>#H¦&KmÞ{tj(2R¤ÍqZxÄ “ÏDf³»ˆûúe1-zÁ›JÞ@cÔÝ­'´Id¢ --À§D¼t¢ûž³"[øÃ‹˜B{Ȧ9÷"ÍüÛEÒÇL¨š€P[®‹ºˆÉ';К¡Ä;‘÷U™3²-fdø£§Ñ$ù‘á2³Ÿ„è2_\ed3ßÔ¶;ñÆŠE ”¢‘À¬kË›ŠQº ÃÉ8>àåžë•B®£ã­k‡aÏ ˆlÊË¥Vk±É¼œ!qZ³u^Ë‹’ÐDÞOb`ªÂ¬Gã\›:þú‘nZ>RäTC™Æ©3mÕËPÖPUTÊ“9/d0ºJö¬”4–°¥RØ}W>޼{’”Â=íÒKªt˜‘íE’Âà ²Î(­s¼ß€F'êôë ÒÚu°%.%oyöRo÷>þ–ºQE-%9=ª°W°S‰ªwªl0#G 4+0&”ˇZÛ—Œ« †á×gMD_‰×„½„æ`MG]øtɧ´$Ã’†vöœt€ª´™Öão#ð—šbì® veêq’èy`+¢5Ð;eºˆøézBùnB¨sÎ8ÆAf’69[Ñ5•–¹@ާk»¤Kè†RvÂîe`%H#ãÍï3»¤¥-áë£`ÂH=òõÄ'š>ÿK¤¹zîgõèk(¿K’’'6´Ÿm(“’R'IjWøãYšzöˆÉÛšªò™˜z«o7ò`†ƒÆwl^çˆÍBÓ‰2è¯aü81þ:Fˆ’qµøEuB&£ 2#ŒpmQó³L¯ÞÖ¢³§¿¬‚P³hÂ}S¼XjÞÎ "&;åf†¹î5ôH]ö÷Bdw~ÁøD™÷Ž¢Õ¿<~–a«£š£°ÁªNš©_ß®ùÆÛÚ`™&„>¦ÁµÍ« &[~Y¡^œ EÑ÷dC.aæ ž‡C›Âüf†‰¨žù\¨žïçQ½N>³=ªG]Z¼¢2Ò9ŽˆðŠücƒ¯á œ£j (³°$^¯ŒôœÏt`—øöoZÄc9Çú¾j‰ŠÞ´ì,Üb„,® 1zXO€s‹¨ýt¶d%•¼¡á§,=\ÌïîøÛ?ÌÕ+>Ÿ¶ñ>lT¢2±R>B7h¡ —JÍtƒ™» ÜØ *)}\Ås10H›¤lÀ5¬C«±6‚†讀'X/§´dHØÔGˆ²®ƒÔo3‡WùÔ*áÊ þ$+î$­)Ã*%#Fbݶ‰²HoØ#Á“×qH¥ Úö@$YwGÈJ¶î‘¿h ¿¢¿m xBÚò&mÜñ¸‰°\vó@vä­ŠeœpÓ˜®÷dPöX¡‡µô@w6Œko¢ø6õ®Pfw3 8ÕµÖ^× |à-uäÃLt€"Å•…‘lág³øý]Þäb–(Ð2:'– AFZZ[Ũ7 Ïq“7Ñó(9œ„:õ¼qAVuà~Ú—‡ßdTïB`‡ú v®o+«Æ˜Œ6ÛWà_ 2&sU–_Øœ˜A¢RÜÖ ŠG).¼ú±G˜±|†ªÅ³”às-Ì ÖpæEæ(ZvšÄޝ äñ(Í Æ5øª¥ŠÎeHÛ1£ò¡{˜²Ž!EÍ#ô q¤~A9³Û_Д@^ú€8¶¾KQš,óPg¨‚äÐÓ‘¦P'‘³&‚iÀ¥Ì–<Ê¡a*KDHn^ïT‡—Žn #Ç»%éæïP_˜±â¥ ,PµO¸Ò‘ßܤ_Àx1”q+\É„{úÒØBº€û}¦+uÖÞj1ÐQkή61êô](9Æ¡+ö½µ†XÿB×£-¿¹ðÝ×]¡Ï„é¹Ã3Y\”šÄ\ÁKˆaS£,$ÕùÐ*7\¸:ôþúþ:ÐS ›ˆÆpܾõå ¶qÑøÿ´3}½òe…0…‘*‚òô†$-ÈG «…ðÏ5ØKŽË장—Ò×bg?ñ#^ÍÐÑÊZ¦Zp|‘mnîþNC—­yËêªÒZ´Ôõ)–=q /ñ–èÏc9Vm`91eÜA^ Å‘êšå,ƒ¸ uüÓJðgòÅ$׌<9jz‡‘ˆ}hõrØpãWˆ©‰Ðß¾6è…CS6‡> ©m‡Õ7®½§µåØØC—²•5ÇÌ”…¾SmCgo÷âq·zD…œkÀ°¡¼òªè5a! ° ÝVY¤„œJÌv®VyJoh‡o©§áˆŽC7mS„îzqS>=¤e@Uí²G«B¬Oxé^¾ À‹Ñu‚\ŠaNùH~#/öö?àMóGJ|î"È¥wgqu<Úcë¦|çúѯqüsäÈÔâµË>ù;µN™ŽSÆr« à©R”3ÔK¯¬RXéQWZ3²¼w­ª¬Y¨ï0&f Øk„Ùöãlíf:@l· z¶»3Ö[éôîæ0 ÊÊ(z[\k"X¿á·R›6×¾\‡&DGÃ>Ê&pR–d Ìiþ<â5ƒXØ{ØëR{+›Cƒ£ >Zq×aœžçά†/i&¶Ý,3ÜIv“z˜\@¬„!#†¾6ªY±,ç߯´¬^RÆ*ü_ÑŸÉ¢ÑNåüµ`Ì$ÊvÎŽ«ì¾‹µ’rUŠÁK˜Î;iy·ø(•åÖ½†np´å‡dZˆezŽç·ây'Oô˜O_¹{uÈ­êîB£ò„¿L =0)Ä™ òÁ*v1~¥TÕZtÐçõDÀ¾æeMt(äÚÓ%Ñ—ª‘¯áÓs™ÿ‡kø oÏÃo'k?þ`pšïóÏk×ð™ú%?o¼†?ªñÆïæIÉzü`û‡;?Â?ÿ%‹¿Tendstream endobj 408 0 obj 4056 endobj 412 0 obj <> stream xœ½\YÇ‘~'ô#æÍÝ v¹ò®4à|H¾ä]­4^@¶÷aÈá±8CiHËú÷ŽÈÈ#"+«»ç!Hê©#Ï8¾ø"²¾»˜'u1ã?ùÿ/ß=ûù—áâÍݳùâwðï›gß=Sé‹ü¿—ï.~} W¦8Guqùú½­.‚¾ð‹”¾¸|÷ìo;¿w»i¯§‚Ù)øC§ ‡ež'mÂîw{3í²ûtP“µ.èÝí5ÿóËýaž–8‡Ùï~·>ߌѻ¿ÀÏKø9…E+»û¾°,1:|@M1.6æ«QÍ¡<«f³û~ê˜ÝWûƒƒ~,¼ö—}yë×{;A~¾†É¿ûo|]kí={Ú 1*Þ¿™å.‚Zþïò°p°6lá`ŠÓ¼ÀÚ]^ÃzX³wô ¶üÁC~ò`f\²H/¨½E6£–Umõ7mêWÐÁ·eC^Â<­UZï>Ò=,q½‹~€ýY¯Õî´aÃä|`ß¶ÕÃûÆOκÝÎݹà5{[û~À…õ³e7þ¿ôwÓ{CͰ˜mŒ·|èÛÃïö=y¼Å&Œõ“uf÷~.ðKûô"SíÆŒi—ðQ6Ž;¼—WƒÝ¹Æ;ð‡Q¬™Ûºbø-5 (Nz^@t‹Ô0™û cáU“~iùà»Ö^ìqŸõ™ÄÔ)óCkµÎìºuJº9âþ ë êô¢Jiꊭ׫´³JsΫ›×‰–`‘-–fªDØ<ŠèlYB¼ÿž~ê ÊnâÕð–r“˜ |ù‰Jyµ7¨¼*î~DÓ ÁD+sÐ!N‹½8(‚:kZ!ëk‘Ñ $²ÚbBÚèàA;~ÑÞã뮣†u·ÜÄ|¶‡©PEn8¸%û3¾f&ãÔî{g'XéEjçG®\¸ÚX¾/`F-,„ž…’*©’^6á/ö lŠsV ü‡´¤E)åûöó#&X*5)eølólÔéO¦¦m:M¾Û5xÏÌ Þä2ÛnÒÄæ†  €Ñþ.ªq‡ópB,o“ô,Á%5?¤ !E÷àpä?b|Wo«83«€úW¶„6ÊãO&èøüË¢OU±Ú³IŠó,’»¸Ðdš Þâ¾ ,c™fe ˆ”Iw“ÝFÇZø¢™ÄöÎÔ8ϸ-•Õìnû³ÁHÚÎ;ÄéÀzZ(\äòÈ˺]çYíôžW»¿ïÖ6ùÎ×' «×îðÚ Ë³p1kB"ûg}åŸq)ӰГ£¡È]co6)7öiÞr¡O’š%—ߢ¾õ®o€éÅQ!1Vˆ ²w2ƒ½ÂvúõvΊv@-»éL»YÜô5+¶O(×Ì ç3*ðu*Vm+\] ¹èf¨³0§¹H“¼%‰YÂ9ê(wÑ*À˜MBI;ç‘<¡ÓÌJIžM­¤Hîu=q¯rÖV„££ãÎg÷÷}•‹w ’ÙEB²É€Sà¿gEKñ 4ÙoÀÂðŸ_¡9žg¥„ŸhQ)I ®5jÁÜ}‚ô4úæWvÏóÃÑ óu}æ¶]ü¾^|×.>¯ïÚÅ÷õâÕŒËìb²rí•xÛÂ:ý'¬"bëïG=ÿP/~Û.¾ªoFÃùP½h·_ŽZo ò¼]¼4tÕn·‹GïÀÖ–«°|ZL\Ò¶,÷ —‡S¸ü‹=‚K›Ñ%“Óìå—`ÓÒÄAAkæ¡v0 ÷þ,(Ÿ›BuÓ·Àù2£Ÿâ8•Nz{¦¸ ã¡Ò‚³à°ó\³mñ`oåu»5=‚hÀRàÀxx†ðX)0ZÙA`óö(€yyµ$lýä9‘«‹¯°VûÕEÃZW×p¿ð±Aˆ†¥êfæK⓲ÕÞÌ´@ÂXšÜ{ËÑ8ƒÏ£ór(ÝâsÍxK1mÂc=>Ï>Ÿ  ­º…ÒgŒ¢>À=ÛÁ$jÁrÁ³re l \ÈD@÷ o5„ ô''ÿÒ!€ˆdšƒF>|•BCš@0o#o”ÉBðÉ0¶(Ø`i´ÙÀú+d$ãp¦oLN˜(âT¿‚avI[Øõk±;ÅÛY…‘8—×rfx¨hÊG.¼°ú€¸!¼ Zk#×+9¸Ò¬Äeö á®Yù•sï™Ãó45+°ë3 ˜—ÉÇ­b&}4Y)÷g¢&8F<ÎìÛY'[0–52ÖÌ:šeÇfýQFzÃÃàHçyaëÚª0y'\U‡¬ƒˆ‹)×›½+lmbkÎÐøâª64žd<°x”YÎ*[¸Xƒk¸#¬·Ô·¼Ûä\0zØDíãMC#Þ~qJHŠyXG®Å™Ã)Ö¨! ÍáÉÂÖÂÓ‰ ¢—˜Ž´`ƒÍ?¡?‰$R{NKéBb,.~K^swŠÉ³ã_4²8SD:‚±a2ciÃ<´YÆý.B¸æ ‰3O¿Ý£mA(M)_!!Ï;l¹½ø§Æi1¢þkj¡ÿºiÜ<_”¢3£‚ ,â64äÜ<#]꜀£nÉCá I4 vÍ(²x”I(†"%½¾8g†?P‚ULkE2…ëFëîãù F+~UÄo`»°v4ÒÞº h. ökíq‘íe¨~þ¶‹lS<‹æ" :èHžñq”v z‹äÞ[»7êÁGö­äàJˆÖ‚‚góët}ñšÆaS ÉulS®rýÇ'§Áy# ip4³ð@n÷ #»Év8áˆßq2•pE“‰éÙDv$:¿K±¤Žv1Ñ–[N %p‘)‚æã’ )!WÈÎD*|šÿ¤x‘–bH…‡°£c-Éð›ÿ»WJ¥ÏébJwÝ/&ßëÒ"{—š²45Æ-БGàx•¥šg¦_fÐ¥½/±ˆÀíBïÐ,&%‡Ru$7ˆ@g¬4‡ÈÐIÖ|aDÏ*ßL±½{èÀÓÚÞ›®quJplšqqÈ©TYe~›{;€ ^ÓNù1àΣ7Ù”üeJÚ¼ýºÝ>û¡ðX”X‘2E‰2X`>s!+táýB8hÉSV×üù³ËÿøÛî€Ë˜e±CŠZ, ¾íl’PÇí³èEPL<ÏÖ§7^»ƒ—…"ø rEÁF…A–«DxÂzJ‹kh¦¹wîŠ ç†)%Æ…¬õÀÒ`}&‡ÖÕ»„dàç*r»²ÌC-‘ÈÞÔ{4¿9 N…ȲìïҺɎÛZ.÷¿"²Qƒˆ©ÙeÑÑÆpÅpÅj¶ªÖë×^ÓÐá±-}¤s–iYžŒå`Ê#¥U¥fAÖ2%OOÂl¤­‚äE¾Š±ùHâ¸\_‚ dz‰ƒJ ŠÀ­97$Ï‚myRÓúÄ£WŠG: ÆF3ª~è„ú|Z§ø ææ†hbT¸Í˜9÷; X„Jj!¶#ÔÄ4näŒóÆu{³)tuT'ÙÃúd»’à@Dƒ“ÌΦµ÷®×bÏur‹ŽÉK"ÝŠ,$p#K ”2Ì”„Á<ñ™iJ);ÓUl­sïHfr#0{Ã×_ëM²2‰ä #²mxÏ–úÜEZÜûL)S!KÉ µ‰IR…_ÐÛ’¹Yk›<®æ%ˆì-&ó©þVÌ›ÞwŠsÚ—Dý{†Ædþ%B(2‰Õð­éÞ¬½~Œn)M¦ŸSî¯Ðû>¤òˆÚÍï÷òXAÊ ² .£Cò0ìw_î—Æ†þu};òp­ÏÉž¢ÄM˜œûi˜<®ë]ÙÞ’/H¸XU\Œq»½,.øCWX~@†FMþ©rŠ: 'yJqJª4Îã¬á=S6X‰èÏÓ,x|µ&ØKêé<‘L.êЛH¦ÐkcœB–’Ã6؆åÜ›‰jØÇ *`äq˜Ç‚y¤›25ÕUè¥Áå JKO=–«ë· çĉš¸;‹ì2s‚¬Ç¸.¬¬´§í‰#ÎFÍ͸6?žÑíF圎*Ị̆+B#¢M#EG$ôQ«_D¹Ù~äÊ+³…+ÞÌwäU|ÁÑG.á¿­ð)°Ùªæ¥+·›å<¥žúÜ®“6%ï¿ãÎóœZÿt(!Si㺟ï]‡o3Ë‹ ò+i)w†‹~Wwõ˶ÔèoæH=1¹…ä]ZaWÌ5–½÷"#.Yªü—Ÿ– e]u13QÊ&Q<’š“WÔ4acÝ©M—„SÁ¢ã]4ª „v`oÅA5N=`•´îñr-ñ0Õu@`Œ°æ‰È^ˆ7AQôÃdŠarxrRq$†f/]óO%öAÛq!êÅ`Iš.Ú@¼r¬Î,£ ÿGjWÈ_ÖonžÚÑKÈŸU 5õõB©õÐļ,ÊD‰ÕGËIâ CŽç”¢¥ÅòRj·ø‚ÓeÌ\ix:^PX#èÔØá±G𠣃}Ýé™Å oóµÛÐ!P>k³XÎS¶»C³6ð|f—il‘ª< V1t_ç)‹4êì§yŒ7XßLrW<ÏV_ÇJhMáDʦ•ÏCå8Wµ3kÏë³;†2¢)Få¥_&g>ùÉ6ã/ R’-E·û½Íl|—äX¹«îÄ×(­Ç}…pNó¬Ý—ª—m@²þ¸ªƒlò\/-‡4ÿBФ4eL“€Ï[妎> 6€ Òšü2ÕjÈŒŠC]iu:;ïwß1pÃì±<9¾yÜ7‰Æ¾5€{iøöçœ2®ŸÈÜŽlûÕ¾–_>„›#Í0À#™ dftcR£çú¾¢ÏÝéÖmçqêyœ'÷3g}_«À ƒŠ2adsá¢ÆÚíQh¹R[AØ”¥swFН¨«zhŸ†~1%ÕÌÉʳQm¿ÐêöøÙ ‡‡Ø\ÍQ x Ò¯ ÙÇÐÂÔGáß:ó×ÊFNè*n.*šANæJŸßOX·©Ä°$*Qà€dœJ;Z\J"=#¿ÝÃ_Ë•’Ž±Û ÷à{Ž^Eúþ’*Ÿ8¸OUN C„GªrÊ÷Øá…a}ƒ¶¢ÊJrhMˆæšöuµû¼‚0ÀT¼ÊLï †ÒIUnØNœrÉÉÈt„×T*+}å ݧD©oŠ¥o ª,ÊùçVßì9½´Í&Z×Þ È’“£u1YìñayVß…¯¦æ´,%+Œ}‚l2†]o÷578ZjÉáæŽ¥Hƒ”óíÃOnÛùr€ZǧgÄf´:8;ÀÏ mš¸ü¯Aº‡§ÍpªP&+BÛ׿U±¿.¥¿q÷Ĉ‹ÊÏ$´)û8m4üék¼¦»\þ`î¢Ý‡}H<Æè+Gçþ8”Í|AoÚ²6¡«]/´¾ª^C–±§²)^ǾB9ʧ c_?‡§ŽšôÔ‡Ž=¦« çöë›Gº¯ÜKGn ëÁq¿–Uzé%yË ÛQ¯$*ëACÂÙ=\—FuY[¿0vh,pø÷eÍÒˆû¤Ù©“9Ã|6J½ƒ}^n’x=Ïko(P\FŸ¨JLÿIô? Î=á@2 @ÿè 5tiòÉÀŸÈ¯G|zùìàŸF_U¾endstream endobj 413 0 obj 5242 endobj 417 0 obj <> stream xœå\[s\5~wíp±9gaGw‰- N¸ l⥖‚}pb'q1ö;Y“¿Ýº¶æèÌŒ»–b‹ÂÌh¤V«ûë‹.ÍoûãÀöGü'þ÷åÙÞ§ÏÌþ뫽qÿ+ø÷õÞo{ÌwØÿyy¶ÿå!tbZ7:¶øj/Œfû†ïk+øñðlïçÎôª“½ú÷á·0B°j„vÃhaÐá1t|Ø/Ä`Œs¬ûºgƒsVºî‹žw?ô 6H© ïKŸG¡UHÛ=ƒV怬é4Ì6À/œ»3žô Ö8ÝýØ3­V‘_ŸÂ4'´qÆh•f`Lvß`«u ¦ÁþS^°?ð2B'Å,ïÃLØÅÂLBÅ ,R0@¢\÷¼_(k˜íþÙóaðýe/Á¡+Ðd)t÷=çœkM:š‘= ëÙ#<Å)¸aA µÞLÂ8¹¿ã`˜sA/zn%Gѽ‡)Œøèº¿BÒ©î²_‹B²»Â™”2šwoQZÖKëm/k5ð¸üŠË0ưî–&%(¨;/Ô@e ÀÀ…‰Ë°Z¡ƒÐv°¢BíMuÚ{š9Z¶{éÉs!»#˜–°v}ì_1#%†¿+;(­<ÃËDû—ïP’“Eà,ïQßd]÷ˆ:nŒ§%$Ï4„£‹FÏú´6Zz@Èà/]æp*r$×… F‘+7°Q‘uµDŽÜ’ÙéQ j$CŒ`!É“HµIó¦#¥1‰P&ÞepÑŽç¥59ŽêÔ,jÎ)™u¬¨LT*)“ZÐ&ŽŠ$¹__N™ÈspVû0µ€ÎBŒ£ílðF‹°Þ˜¨Ò#ËFÁ½B–`~aÛ°ËHÑT%×eP”«žç”T„‘ÚC$ú ¶‡î/xp)ÖxoS3îj«Kz'³dã8/Â|Ý+ðÌŠî\#—/RÂ2¢ŒWÈ6;™,!v¿+àß~˜½ (¤Þb/ÈøPb/ÛxbÓœ‚æe€?‡¨þWE*â$ਠ®ee@ŽÜ™ºLÌß“m!|dmZ‘÷°>wða™Ñ攢â"6‡þ½Ø\îÞÚ3qg½ƒ¨O, î[,p:Ša„[´>kl܌޵OŒ ñTôýnâ)‰°jŒ㤣÷é$ê—t ñÑ€áShrã$›ƒ[!©Ã›Ľ“õ¯‡%î˜SN‹;÷ÀæÎ Z&`W–ÊÅì2L¬L€wÈCÅt§œáâÇY£Ð°9¸[.~‰§ÖØc€‡FÕë¼LÝ]Ô¬™·L÷¸Jmq©µO§™¤] ”,æ=»€5‚è÷¨! †qXÜñhÔZ‚Á óa¡唸ýMT¢* ^ šÖ!”¸âÊ›Ôu8yP°f!½óÕb #crÇeù´”ÀStà”Ö\aÐìÙŒÃ߬³ì~P@w¶ÙÿG }Ð=Úø5Ø ÚŽ,(Ÿh¯Á#(úë“|‰`P–vÿ©Þz¤”]Îh¡tQô^ý“iÚ6u˜q²qqJ²¦ƒ+m—(…Xjæ¸ š·ˆbT’Üë•Hj Ü3âHÊÁì ÷;õÔÇ»yêÆm•ÅÎzlœ³,ä~!#Ôå¼)Q—èû/3‘Ä-H«öm^0õti{µ9‰½hfT¡á»ÏÒtaÛ'mµíƒíåàt0ãLú ¿ Z¿÷Ãðå¡`Y8)FXGjFoŽª°Ú'¥ñ’˜6žäOoËÏG­Æ2åª4ž§F\`öùßíþígÈ:€áúOŸ¾*£0Ô¿$Ê·lüãÚLLÛ1#·±ðÁÈYÖ¼‹Å,üˆ±¨"´öû»â¤NÕmÞ€^³ØbH’ÁhS‘“dÞ/4wè|П`ñ87ž–ÆW¹, Ìç'†ò¦ôKPx†åDA5ZBúýŒÚŒ‚T)­rã«Øè^6“ÿµe§ÅЯKc!Y­Ss>ï('KþO5)±T?ÊgÉU«çš¡wO­_”ÏŠöJ+l÷ògV>~V:[Ò¹¯4lq^b=E$ÝUç-A^ßFs‚œ’Ïr”µNŸs݆y¿ŸìòÅfµ’ø÷®•Hµng™8Äb¡ÄA™¦Á‘ªõ¬Zi£ïiµ–Fßåä#+¶Bñ-ÃÍ:&Q¤­ñ{²¿$ÞëÍžú¼ß¾ ÷M°mT~v&#{ÙTÌj[Ef*+l¼òþú¿:îOĘîþ•o4Ó'¹üúh§ÎR§exÏ…§2þæÍ4®Ú°C¾j“þ®ßßð˜ú.;Xõù¾Ò“Y¿ÜBzxV&!µu×¾5¥[°j•GÔ ñ¹”ÚvÏ¿~ƒîC•ƒ=‡Â 2®®§ìåG>¬É2¹\»>dj`]ëҎ܇’ÑËxï?ùڿͳÖø¨ŒÞrÛ¤4¾õ¬/gÑ ¢­ îGzâ!tÉtMI|OM…A´$¶þÎèù ÙCì~uõºÕx¹=5Ú=».» ô³Ï’ÊêÖлø]⟼Eé4^i°Š»V-ðFt—Œ)îÃëF3¦rh·l-â¨%¸ ‡L$X¬Z\ÕŠHÇÛwr0º¶«|4qdáó>Ýâ8& AÖAê ÿ”àäûøÃ@˜>ÉßÝáÃÔ QrFuÑÌrΛ Ïš4Ç“«¯ŠÛéŽt8àó‰râ }u:†} ±p¸ªw“x ़O¯Ég=z¿‘SKžðEK¹«‚NZ:¿W¦-DÀÉ=ÀæÎmÝš¹]9h9k­°é;Ya¢tÝ2¼*aLYd\Ä‹–FŽZüþºÝoâüÒùÜyÓÎ ±úpuQi0ïážÏùN–6˜Ý(®øvÀ#¯ræí`Ugä^à$a_6p…1Úa¨c£D+¾Á1Ø&„}àÕÉ]ç³Bæ¸p'ÊAº%L‰ÜgȱêAèÞðÜV,7ëž\´·t¿l56w?78¶9È¿“‹ê’?ºË ’Ðçè”ßû%ådêÓŽœ¹'/û§Òóån9›ÑN+=V[”­Ú~ÚÒö“JÛ‘³i{s Ó~ØB.7¾Œ[,ÔK&ÿmqJχFëÔÝ®}ÕÓ «'Va¥Ê_Ò ðçÛ pþ"ƃ0œ‰pY‰9¼\¬ÏäX/:Û‹Ö!ËÏèý‰–ô9© ´&\WaÅ£¤Å˜k¶}Eäô‡œF5³c9ÌôÜ©“í-’¯ÃŒŽò=TZÕÏ¡ñ Ö"2Gر|êcÇÆáÛZ™ªãÃè\.ø³ÆWãIÖ/ßãËs È&>n«ÈD”+z,¦vÆ A»À+ Êt9¢¦²âÒW¼ÃQ"%ÁnÃöûé*_/MxQxÑ6`[ 7€$!CÁÓbGN-11L&\­;Š„·Dû #fÊ)Öu;Á©K>ª½k¸À‘c]ß™JP >:Üûüó_çA>endstream endobj 418 0 obj 3693 endobj 422 0 obj <> stream xœ­Wkk$Eý>ø#†|±œ¶ÞÁ…5(¢¸Î"âú!›ÇÈ$Ù†›1rÀž“÷D1ÎJ¸Ëùˆ–,aaÔHÊlÿ݇˜²Åü A\¶@‰;mÝ”ÐHV"yƒ‚b$E&UR…{ïw¹ç"R¯4ÍO©w=¾@Åà]%—ꩤiK¬Áhb¡Žx¤Ü %w ¦Ë½ÍSê›ÍUõV£ü¦ EÝ—\W‚¶ç2¥œôYÄÿ/å•(ŸÒI‰Ù«”‘„&õ"RaÁëÔOt§ô“a²¾- mVÔÅ~‰äÝP±€2ì·™è-Ç߉tí Kúš×žÐ±rë’MK–vº™¦r°Ä€­T¾ïy3ÕÓ>F¼DH©¯’Ð6‰›ëQΤM>»B| ÷fÓ,9N¥¨³­•0¸MZuupZš–¿èe›gÏ )sÑCŠÚ¨é`Y}Ú[97ªG¢º‹mÇt‚øHÂ8DÙ›à3rΚF'ý½Ì…X-êU}2e™RÃQCY$½Y¹C`,]ýªº°:I]H _æO{œ¤b®¼:ãºnü»Ðª˜U‰jR…·•iP…ñ]®%;‰›…¹Ts%òyÕ(KÚ²ÓÞ^TNmɪÿL¦ÊÂßpÎSH1J][|ëŸ7Ä\æ¨ü‚ÂÔÚ«œ‘#]f·Ö‡¯²h”9ÜÕõWœ}Yß9Ãic?¨Æ¸åDP·M‰9}åg÷œî°£Wëp¶v‚é|\¯$×ræÀùx6tô‘¯.ˆiM•G*<, ›BÇl¡Ž{v”nvŒãw5Ð$ÁÉÅ`àzA5ÑÏŠ¸ÀkBGaîýàªÃW’)/6çL`–Žƒ“Uíz‚^’RªíI/¢æ|¨÷_ª’»öZW»½Zšû¬7¢Ï£6„è!ÏÛç>]5ÌËå¤vé£RqK Þî’J2›5U‚\‰ò©$)a×µý"«õD[èI ʉ%tP4Ñ}Aï$›kSl)Àþ²€ãñQàF½¢G‡ÑÏt{/žé³Kûþ³‹œà£ Ç-pÉè{x‰×úäTìwr ®Ez=¦?ý¥>k;n‰®ÅšÀŽÇa¡½‹åO#üyÎ$}Czý¤…Omð¾’à«4xÒ,Ÿë`çó¤^·ÁM<ïc-Óu#Á¾-ó„œæø>Ý¹Ž“z¨+ª”Ù]ZÒVÜ/n•éüße0ÊÖ×uõ¦ ¶ ·mð²O¬G(j~Æë½7Øž{ïh!åô̓ûÖtƒûþ0ô°¾]/~ÅÏ”µ¯ªendstream endobj 423 0 obj 1371 endobj 427 0 obj <> stream xœeQ¹NC1ìý.×Eïú.ÉÁUpCƒ¨‚H•"âÿ%ÆÉC Š,k¥Ù¹dï­g±~œinvæj]ìöÇx{‹»5{#‚Æfgç$Q Ü|Û¿ÍQ-¶¨Í52–}g>¨¸DÙ¥ÏþEŠÜØWˆúˆ 7 \JkBwN¸µ];¥g7Ž1¥~⬎hˆ•Ö@¥Á¶Œ$blT«@þg´t¡p--Ó»ZÓÙö1‹  ‹Dºhm‚˜Á¿ì2øèâAJR•n4(I!MUaA¤F¯n– -RéÍ){ŸÐ{î"~Añ–!ÓÓ«jÎgÄ~òœêÁ÷Pï¬Ó¡EÆ/¬ºyÁùêïe*endstream endobj 428 0 obj 275 endobj 432 0 obj <> stream xœµ\Y“Åöóš°ÿ¼©ÇÁ¶ê>ü( ¶&lÐ:ü@8‚½XÉ:Vèß;³Î¬®êžYí ´š©®#ëËÌ/Þw;6óÃÓŸ—¯Okw7?°Ý_á¿›“w'< Ø¥?._ïžœÁ ·l6F˜ÝÙ'ña¾³b§­Ü½>ùnúbÊfm”ufz¾?³\Êé|Ïfo˜a~z›>õbúyÏg/¼òÓõ>“ZóéÇý©´fv“Å™œ´V˜ÿžý=®­fë,ǵµž•ônwö“³?}7íOùì¬eVe³rœ‡Ya.1¥â¾œ0ÎØé+!µàbzöÂŒue)¦gq£x üôOœŒÍB9ú)Á:œõž‚£z-ñ 0ƒpJ+89üÌâ :øåÁ÷ñ¼nfJþ¼˜¥|zvÀŒ6Ó›º™Kx\j)™èn…ÃP—çdL§‡„É¢ã.röÌGÙù† "; ³q&ñÆ@®Jy²SÊÌp±ÓgñS¼Ÿ÷rvÎÂþ„òÒÚY…K|yvòÍÉ»”³  8U³ÛqÎ<ŒÞ)íÜlÂìÉÓ“ÇO¿Þýüãûë“ÇÿÙñ“ÇÃÿ=ù×ðÇÓ¿ì~wòåÓÝ7«ðkÏ‘ñw=KƒËÌ*¢ðÀÉÂ]¦ýéõ^Á¸(q/ð|¯GCÖO¤´Á“|ò)¼"z¢«z3í¦_Ê~˜›~@,à ÃAã åÉË"ƒú|ÕíqsŠ'T’|ŽŸ;+ƒ:@±Þs€*þd€OƒÞxšwV¿Và‰*¤”Ehòr·{igxÞO¿ Ú!­7u+Wžx!Q9k%ƒ,`ûTí}JPfzG¦ß‚^ê‘þ…iŒ5ЬUáO4åF:Ü[ òü>eÓÓŒO¿‘5ˇ—ù‡´ a³’i°•/öE ø5b»³+@B:ŽånºIwÏU¹=ük’«åfº¨“Gx­È2d$yŒåô¡îwr*ÁB1µ;å pæwô¾Ú‡l`s¦¦SXfTûA/àíðÇWùÚÊýÕÉAîÒƒµ3|ú>ûë^x°ÏJ„» øz#ŒµÓ#ø˜©YÀ¡Fq¢b$ê,Œ‘36<ç“ ÞZ°¡m¹Z¼3>Ö”•¹@Üuzä´Qü %eƒEÏû ÷66.6¸m¼uá%\:Ïl,C:ôÒuOŽE<Ÿ¥¡ŠÂ׺¨h~UY´cqV®昨ÚMܦ÷ŦåoàAn‡ š¬³ØøÀ C]½ÆïtúXýp½õR=ˆio=i±0ÑÓ$d m‘üU€ŸW¼¾¯OKn©3Àµ?¨³z $É* ÇT$eýûo ùxÖ¨<¥D€ÙêYak 3=# ƒ£ŠD)¡†DæŽÂª°:ߨ•²–»@mïJzýE¥±ñÚŒ.äÃÃPBsŸU#O Á7 }Áï~ Ì&ŠMW²µÇšz¹m|V|ž\”PT9qQ"ýô#XûñEÝ Ÿa@-Y÷6zMï%=kpïœéU½À‰²oÚÝ4\)‚ ‹( †…f 94;‘9gç$‘®à*¡@‹ñÃ]ç§“2D µÊÙ½£êÁÅK4—6Чaôy,Ð2ànÁ1ô¹œÃFØ*ÒÔ»{¡>F–Î…yÀgŽˆ²P$DZÂgI`æmWèÜRK³WT.?Ÿê&Rá1º3blçøa °ÐA•DÓØc‘ B¡[±ið#"T yCNTE‹üŠö°Y®du-iZó±p,@µëóŒS¶Øà‡´Ai¨G"ƒ€Õ'UÐ5À(‘wljPŸQ_™ h 9æü¨«¸ì{ ×9׋.‘7|Ç\¢:ãÉãK†tÓ/ÞmЦF©»drÆx/3ï5UÁ5'†Ñ’°«ûÚ´ñ)§m¼Yõu1‰ BQYiŽrz)·5LàŽÒ¨D‘‘2¨h=Ÿìs2µOúžWŒÔ˜:±(LÔ@ºTÌ 2Þ†ѕָ?éâ ._hFJ«5YE$ÊAhNõ¨þn#ªã’ŽØp “t:‡ã¢Aê+è¯b’½®ÐåÏ’ù\¤F;|~¨h9¯k’9p.–7³ˆCËuÉç„ê!0·l­T^¥$ \|¾Á(¡B’æˆìo–ÍyR,ÔòêF@ªd§ßlì»5ß#ƒ‰ ‰R^µÔCtwp]&šp9|)žùAPRŒ(œ–nµÙª79j.;²¯Ö² sGˆh"·q(E]vZ%OÒ”tßÛ‘§!1¨Ä´¹ZF´c­–Iœ…늪«'ñ$A|ŽÒ7¹XJ´ü#E›d(ÄÖ¶M“ÅÌ‚›Ú¬rt€(-L>èPˆ;>~Š‘†ô÷¬jé¹ nLø6ÊN°KÅ%Ég-¢iØÜWD>àºÛ&ZçAc˜”Y ¬^Ô&¥K“s‰´Þ¡¬IBì"kÊ¡² Óv Svß.ë3Ѕ̽Ãar4cÒ¤,ÕØ­”Q’b“!ɨj‚aP¸à ÖjÝÕ£µöAëwBæ´1¼/—š{:¾Ú{ìQ5àD𥅍"s„—>ç|?*Â"Wݪ µ4u”GÁ² Ò||4/2¤ª‘Å8Ä\xÃ& s¿Vi10ïŠwLõNMMÃä:“Q¤ çŸ/SØQWüâ÷Øó$tYòá¦Wüe¦ÝI:{¤‚Y5wÙ ×g¢™N#Ê]¹ÞŽ…š3ëv,·‚‹$J`ëÔ»Œ Ó|;c—ëFÞ‡˜o\ò1ÌŒ´£+ù$6«@‘ñxÄÒR%î ’?HÌÐaé³µ ÷-¨æY·h@ ÛÌ5S¬TÛGA'I–£Ë«J²T^lWÂWYwêÁ‡{½Äwt ÷öï½è­Ô ?ØÄߟЇ¤¯Y–êö¹ ²hý:IýULEà­55IÄ®VBst5™øh·ŒÛ[gKÃC8ÁÌy×-ðË^+0H¥¡wïCH-CìQQÊìÆSYË[;.µi1bÛÔBÛ£C·Û·%Äöƒ”ö¹â"²á´‹A¥&H`EèR|±2´ýõ-a¹Ñà{j_Á›@Åô¿ ¾%ñM9¼Ñà~éŸ9ÌÓ51j{Ýä ²O´«±_tT MòÎÊÝÄèeß6b™ÙYašFA-І½±Ëì„.¬·oí°-’óq—CQk¶;?£ºLì’ùªÕ½Ý^„ þ£#ZÀ'w[.\ÆV¶»ß1–A´l$\ˆ¿ëõ»;€‰Ö*od7:}ÌôûÑ®Ãà¤Ý±娤P¿}ä»_i¿UܽsQ]øµ¢ºð,¤Œ×lpÀ– NÁ$ÏýŒÔ&Žšx6 îšÐÍ5èv5>àëºç Ç`Ât­Ãmû)ê1KÛÝöd 0£œ•w„µ8ñ:zRÇh›¶u†å:ˆ°l}nËÂÜ‘ÚJϘ ¹#©ˆnŸÍõeŒV¢x“án,ðÏ`uE1­)³&Õ›5ñê&5mÉ85“¼~ÄÖˆÓçoŽçôMÏV’O«‡*o}g¥îÁË• žŠæËžÆïª ³0¹h¡ýøÐ™nârbe ÉHo’nƒ­ ›Cº?Aâ9T?´Ìi…\×1]=?<ŽK5qŽ‘©H«K§£R”š/ŒÕˆb\$峬…Î!:U³9G1jÓ–ý‡Š¨)åj?]^s”Dâ+™~áÛ¸! Ü“*nRØ(ž¶1Ÿ´Ç4ŽD;”óy߯`Ÿk-±hI› J3D!—Aƒž%õvŸ˜f,Ì Î@µæe ×µ¨òû˜y¼Wá@s|IùÚ7]lK YÞ%†Õ¢Ó ÌÁ BÈ­T—¯-¶ –ŽÇi¾ìX$?“Ä6¹ˆ rFúq:SÓèéyY~8|ë©jZ±©”çòyWôËQòZZî2•›MAµr¶_³âkÎ!§Šëé“^›¶Ë;dÔ‘ý‰WÈÉùüšcèï9ØGÒ@µ}‡$wµ w½ªwé¨[ï´IôG±6‹A¬—Õ ¼è·‹ù6?¦ÏC.SÞÓKÊ—:”"ºÓùiûmYëã^aZoÿ$ìkXØe"Ð^ÆŠc£[¥Óôf†¾+|«á h\ËšŠ *µß(¸už% ¯-6rï*óRÝ9œ–Ê/Eó±. _‰Oe›¦I¦y©çmÅé‚ë£Ë‹á1BÈÍÙúåW†k©ú˜þüí!&¯:]N¶S¡ámP€¯ èö‰`¾­nªGÑN[“ñÜ­OéwÓ1?€]’,¦Ç á‹^‹>¢^K÷¤aX.xG$÷: ”KaëÙØALBž½Î5:ÀÜI奧ùŒCµ-l¼¸'R [-@¤×¤†óRscnvª{¸yŸUËÒ¡šèÌ:5Êr;¦0†ýF`ÇVŠ^eªÕ7M–5õº§™–Ç‹!ÌúE9lí÷È ÇY¬½E%I‹! i ú¦V8m“¡OEÄàuAöGÞ‘¤ˆKbä¾Ï1ÓXB¹)q®Ó—|=Ò»$Äý{—BA\ÉͶzá5xÈ»´ÕWJq ` Er"ug/"ˆ&h%1vî‹O»Š·9…±ÀÓÒW)o]QìkÇu¢›}m]¯ó5Ù² ¾ã_p ©=À胼à( qá€+Æ+ê²ýU ËDÑPd­ˆ¢çu½OqkV¨¼ãåÚÔYŽ Œyx߆é-ÅîÅ\Ž”ÒŸÀ.ý¢ÎR¤jåíô´yò&s•'È^ß'¢‰))ã.*—×úF†/ÏMÉ¿y$ŽÖ#°‚§¤Œ!oÚCjÀk$¯Ê–Cg&FTzx”†ó zûÈA‚Ri`”ŠiGì,K@dajiZøÝ^ßœüW^ÏÊendstream endobj 433 0 obj 4564 endobj 437 0 obj <> stream xœ½XÙrÕFͳÊ¡7¤T®<ûRyŠNeÁø¦ò@åÁØÆ¦â!_ŸîY4=ºv ,fzzºOŸ>£Û– ¼eø7ý<¾l¶ŸÛöìMÃÚ'ðיּmx˜Ð¦Ç—íÎ&q#ƒgž·ëWM\Í[+ZãÔ/×—Í‹Îöºs½þ}ý¬¼Záô `Íúæíö+9Xë=ïžö|ðÞ)ß}׋îY¿âƒRÚŠn]æìÅQ©\÷F%X [ 0.„§³‹Å=œ +¥¥;>îñÉÛí£]ç9³týa¿W•ò:M€?²û&pŽ[¥U`9¯B[ÑGͺÈà=³ÌÀ™œ¼³:Mu‚«` 9NŽSœúÂð3üÛ- È6dóhFcpþÀ˜ a Hmj𢦃â=L™ƒÆ¶UˆòbdZÚÝ¡pFõEø$'ßÌ3t,Ü[ÆJìð·2þwÞxF_$Ù#\ˆ%úìúœ‚_ß”à×\þ—UH¤³)´N*e® kñ È E_UŸÒ”€6y.lÞÙf¨pVd×Ô›;ô[©þ“ ­UÎ…+¢cAÝ’ÞÄyÌ•ŸH*hiU2`´j®4të¬0)I ³ M¾ÖËzå “*G[ªΩâó@´0zX ÔwKÐàPªv¶NæäH­b®«ÒÂ"¤Ö)ÙÊÛœl„>©‚륵ÉÎW‹÷ Ò8;öY„ØyYsØ­W-¿¼O*‹Šz¼ÑY±¬a’bzˆ™QæÉ™IíÏóo-ÔÓM“Ô(Œ“0=Q¸¹—Ëj#à]ÕtòöõŽØxTÚ{èB>ÜYt5E9tßÝUöX>sl~]·†!¿ˆŒ¼YEQ„=î= © ”É1­ÜSFEZf^¯,|å¸ "HÙøI!y® ×Ì„¼Ò<*g‘×ðõeIÛÚpÎÏBÚé”eêQ5þ’JŸHÛšn<‘^uá@ŽB½¿Nä rÒŒ·½²Çès°ŠoõÕ‰^ø&Bd†a«ñ›äçaiüj¸Q…5A?¢¹@0Ÿˆ9£–,OÐ%î ñ$¦cÆNæpÿ ’ƒÃf;C\fI_õNL£§]’/x˜½usÐܶzjøD ï\Ë-\‚¡õhR~_6;ûÍöþOíÛ»w§Íöo-o¶Ÿâ;ÏváÇþ÷íWÍÞ~{ð/¿†s¸¤…Û éƒøQøJ¼'½®DêÕ·x6ÁA›‰/6Áñ» =¹ÅÒ#BÃߎO=²…-þ#ƒy[¹Tÿæ‰=9Ä_ä#ïÑ,OLîèêºV‘Õr^<¢Uï-}zÍá;hþ1‹~fendstream endobj 438 0 obj 1816 endobj 442 0 obj <> stream xœµ[Y“Ç~ß Âaßèqh[u~³ò¡°%Y¬ž„–Â,»’IþõÎ̺²º«{" =Õude~ùå1?ž‹Yž ü“ÿ¾¾=ûü;~óó™8ÿüsö㙤çù¯ëÛó¿\ p®Äìœrç—ÏÏÒËòÜ«sëõùåíÙÓ‡ 1[g|pÓ‹Ã…š•’ZOW1G'œˆÓ}~Õôæ 稢‰Ó³<ÓÖÊé§Ã…önSÀ™‚ö^¹ÿ\~•Ö6³^âÚÖÎFÇp~ùϳË?þ0}I“gÝôëáBÎ^É4½Q:˜Žª1nz M8ò)}”’Ö¯žâp²0ýžj«œÔÓK\@úè§WõÓ³4Ò3}‹oŒ‡£Â¾e0$p‹]„åê`í¦Gm ¿¥Í /ac*ÎVù˜÷\K+!ë¹\,âfÖÆ)‡Ó8£,â Ná0Ó|гRÅIÂûRùYšéØ€Ò«¦w­g-µ„ÂPç^Þ¡2°×w´” ˆ§Rð~i½~­JLÞ“T 0s‘îH‹²Ð G’BƒLá“÷p¸àBpé—íûG‡ ¸Zc¢ÍB„ßÀاÒÓÏøÐZïÔô6 µB¥*oÁG@9àÒîbÒ†ÔMÃtNIœd:£¾]Á˜×ðOëgƒ·d`©Š[€š*ç={±}ÿº­ø´}Lß+mHŒÃ}ð-ÿ–fÕ>¢&ÂmXMžß“X\”GxQ.>F‰Æ´^äu^ÄvrÉ06°¡×õÓKP¸==GMFùŲ/iáú=;â ÊßÁõ[¶ÙnK°8¹= jhAw-.ŸH¼Ì¶ì«ò-3¥•6ã@4 úåìxÍ*^[´Ê@¢êõÃÝA®Ù[ú†×)×Ò¦ÍM4¨+oÛ‹ÌÜÛhfÊ‹e¼’‚–t€„1ž_¨øˆpŠ·ô‡ƒ¡~ÄÁY§Wçl‡`kˆCa÷g AÜu§ ãœVg+CàÊŒ%…`ó}Gþ3 Ëüm˜†½ÁÐ¦Þ v”·øsÞAÓ;"2lX ¹9Ø^ÞÆ¡¢» «Ó\@K6dït½Ðeø>f?Eï Ãìà`ŠY"ë/ð„Àpµíûª—8¯í0¬ÀLÆ0€«d±løxZÀk냖K "‚ÿ‚H¹@[ # ›}YÑ«›·Œ.VfO “wL¨c‘-áÆ–ÏåÃèV_4%}kJ‹ÎðÃüc6¿à™ï¹Kš]†|KÀM»!q¡He$¸ùi‘V³‹d˜’v¦ýòµ!,4cxŒò$*3`^F¾–)5[§N×€éÈ K.ÿé¨ò’p¼±Â%©Iò’ÔVÅ8 S´vd„(6šâdÁ`œMO{G›±VyÉ\Ù*™çZ[æõ–=d*vߦâŽ:/Ë2“!ʤ<ÛwÀ º ¶\32²ˆ,ŒÞ ÿЭ0xîÐÀÐßÐ…IÄó+÷„~žÝzkPcÉ?ÙG™‹ƒG³ŽØî(œ®p1àmÊÎt\ ¿í:S@˜vÄ T¶ÆvSNÒväK[˜[yËÛ÷í¤½Êj»ðYWý?QúÊtVF8nÞ…Šã½½á>͹!°…`üÚ9Ó¦²I<³„;­¤…tªy~¦¥_PI8Vð³wŸ•ÉÒç3õH¿AÕDë(Èå‰îÆ—º…F€º¾¸ÝÜ€ ´Ô)¦a¬€Ý ßFIñQSΆ xó!ù„\€ÌpÚM )|»rY,ÊÌžq;ãû”ÍàA¾`Ú¢-]¶ïס-â=‚‡G³Š\qël?ûÞ9í-áð›¤ìæ®Ð¿‹[Š¨Ø«6/€n&ÏEäÐÕz. &¶..Â{ÕjyÁ¢¨7a.çiõIÃÓAzä>‹é@ÁÍÈïyÃé ŒŠíðe£7ùÃÜêó ]Ÿˆí¡Ûï@±Ðç_R_z²Ï€6€°hçx ¿ƒ[¾½Ú „L]¤–˜¡Ht¥jkIÍä4ÊBûTÝžö‚V÷.Ϫ|]ï;Zѱœ¦¿+‚$†­»Üœá{&%K½¾ëO¾©æäXÔôø§ö¸žqÛûâDÌû¾cL¾¾3L›±,Á…öUçN`²Å³žB$)aÊ0d¿(aø…Âlôﳟà’ÿ;.)§Gƒvåêè½ͳ H³u³“vN-ØÞø1À”f–’gú®º½ôöC;0z7P*ñÎã©C²qPÄnìŽbæ¯I»\¹±á¸È{z¬5bŽl§™üÏ®‰È±ëE9lÛ2ì|¡ŠÓþoMŽÎ(`µÓߪƒÝá€ÏpÜb:Kß!‚I¡  ²kW>Ï uÐÄ.iÎâ’»ƒíqB…E\òŠŽ`¤ï™X;…7´leu–9LcÖ¶c#TU¼a’½ŽJ™ìn&¦ÿÎ)Ý0­±ÎëWì/¦Ç$þßÍaÑðõqÔ×E¡eèFŽ„ÄìF‰‘ÌŸmÅjat8ôo&C…ÓØòò IswWøbH'Ûõe[I²RcÀnÁsËÿ±8k#Ç¥à›À™,gð]®ZÌ«.ERóQYõÔðªb%þ«}ЦL*ðá”GXb.¥ÍRKÜ4$m0øÃí¸ž–1pW–&T>UàGÚ”gl›¤ÓV,’Eïl†º+t‚"f)Ÿ(WL“reÄSËq}Ô‚:k[(%‰·_0“ûͰ§×S8 –ö»ä/î¨#™fåÅÈVFËñ£³ÌÊŒà7]¬NƒÙ-/ØÊYV°U!YÏ*ÉŽgÁôé-³Ì‡µ²‰rÉ eŸUÄ< X”5ÐÞf,×e£–—Š»”ôÈóÅ]|xM)^ð#êÕ:+™¬r*ø=ó¹§ð#ä$îzd’KZ9}èþ·î!¸oT£$C07ý{–›[¯9L…X™eÐeý Bdð5ßRoÑ&”Ä4Ì[~Êc–O)§Õ[ð1®o ‘ß°›|èT,•ñªâ‚¶`Ö¸jíõZ};Ï@5éOH‹ÕZ¸M 8¤¹ì"XÐßðéï‚ÏA¸òûêdîÓYSöÑS5¹løqD§(Ñćˆß4§ÍÈòtµÑÙ–LåªSüÓ^cC v ‹xdÇ~³…?Ïù7àøNQaL?R}€\ÈQfc+Ló;NQ÷NÉ6¿c¨¼™dS˜†§ #«b¦„ê",ÙCGó©ñFx74»œ½Œ'Ç@“fµUQ,óòƒ&‚Qzª7!‘2\µqbѼp¯Êëºâ%ªQŽÍÚ^)¹[Ôâ”—?̇i *¦RúV*i7@¦:«šdÝiƒqïÛöFJkµïbÅ9ÃMùe÷ì¤ftœ1w=Ô×X µ3 —²TR±8CH­„XøÀÎ(à½kàeÑÝj%‹î©Oà”$ºÃÖÖ­ö%Ü :¿ÞŸŒŠï¸ð(lØêðq7” R  §s .43v˜kÎtFüžY^ñ&x™fÃ, »ƒHGJÝ+;ÕIÝ–9±â(ŠÜ˜÷5Š®v™ÎÛ«ÿ¨SäX¡ç*í¡|sßô»ªk­+ò²‹:ŸÍN68—¼oÖýùºcŸ°Hsy˜7jÏí³‹ :¯}fD(8êÜ ØmSµ)ƒˆKׇxi6¢±+ÑÁMWˆÌ©E)mÎÀ݇F>šl+kAìRÇíV‚â…›*d>ºiæB¾,êH•ÜêõìiµPŒßl¯sÀ·ðž7K׿ Ä3ï&nòö²·O:"ꋆÆ;‰zú¨MÏ$Ÿ%<]tðÐY—Ñy –è2Éÿªz‹‰º•ä&~©å2¿õdàFìöU‘,ôV»ÌJ/1‚mtgý3Çvs”÷¥tø+óÁ'†N¸‘UéoMñæÒUÉIÇë¢|‚ãü‹ÈFåÐ+€”Ô"ô" ûÝk¤N™/ꤦÜ{¹ócT±ªý@p«Ï–¶+‘Ô°dzÇÔβTù»ƒ53 ‹´øÛ¥·^%¢Û2‰K&)m5±Æ†Ê×%ÌåQâ÷UrH(‹‡­™a• ®BCžØÇj£.¹>oG?‘Ã$Û±j]Oìî;‘2TzÞ´Úïyë~ S(á–w] ÿÜDÄØmJ‡mt.êó½ëʹÍ'Ù ‘Ô•°.ž-/f| ¿6s:}–Ÿ\±™Y¦ï.§¬™ñ0®„=G³ÍaŽöÃÈ6ð(þ‚W.ºí!ÇËÛÊ«óÇšæxjN¬XǤŠÓü“%¿ëÜf™#ƒÝ’´ JÓæ¸›Ç‡G;ävâ¥Ü)gÜÞOH=#@ì³6Ï* bíÊÌktù±5æï¦Ì³º6¸!(3½í/öƒÊTÈA·Co>k[êhO­ô¨68WØçâ‡Å2Ñ©­¥ÓÙ–únÂô5XT£/£¼K®íýüe^”<@ÔĬNù]žÖ˜Œ5·L;“ô}\'/]Ð=f²³s ‹sm¯ËsRØ0Æ,½Î7Y×ì¸Eù„E›4âÍãA;‰§uìÕHD‰tŒ¦NÁÕWGOU±Ó[¿6+£}R€Îº¡Ð{?¬0¥!¯ çW4b»-zêo­½h–qD’Ž6ú>>àöÃ,¥‚ê°uhUP/-H…åM‘Ï1Þ´(cÔõo6Ò`ÅM<Õ©ÌÒñ­¿¹¥™¥»†¿hhÉ“ pW!,8ûYןrx˜-&,üòòìßðçÿ>è½endstream endobj 443 0 obj 3934 endobj 447 0 obj <> stream xœí\[Çq~'ˆø/ì›Î:‡Ó÷y°c;qàØ‰Ì$ $YrÉ¥,r—âM¢}ªúZÕS3sv%> ¯gzúR]—¯.Ý?\Œ'u1âÿòŸ¾zðèËpqýöÁxñOðÿë?þøÂ(ú…íiöðÑã+høÃÑœB˜guøçAæy²óá׃>üÛpT'k]ЇǭÍïÒSc§Ã—ðÔ@·q¬<×z>iÖä«Úã² ìøO0Îo{š&g=}ñ[h®ÝIÓá÷~|8üßO³1êðÇᨱ½±ú#ÅŽpÒÿ ½w!Ä—»S‡¿ G?‚šÿ=èÓ8:˜%~ñxŠi5…øíWƒNäâ>fza­AÍs"[ZϤFsx‘º·³;<ŽÖO'çæÃK ¦m—@w0­iò0lûõ Ö ³Óúð¾šç“ÑÓÁÀÏ0ÃÃá9,1vHSÞÙû62öq2Æ–´~ 'әߕéÜàÓÉ:sxÝ>Ç~svÖyˆ`LûîiìU­É¨l‘øý4ŒSñŸW­ÙUöøÃ`â'eýØ!ø#ö{b&œÁyj¸àר¬9ü8 0yñóL3?Î|–0ü:©FJ\çe$<%É›¹ÁŒZ¨"-·0ÀDhÑfñ™Ó¹à5ýIÉ^xð™$€\èÜјöº5Á>IÿÔ@ªÔËìl&8þjÏÒ"¬¹={V:†¹¸1œœŸÊÚ±ÿÖ0OÃûúMUë¹[wˆNëfÐ0†ahŸÜ&ís,<*Ó5U;Q~>ùúKÛ“Ô`šá矱ÖÚûÃçðSùÈ4H¸ÆxFÃbÌÌ¥´HnêGŸŸ%Ý㬥ÛLjÒw‹ÆÁ>Òã>£ÎÔ†±ž£,ó=j5K£m^ô| Sô =åsÒ ãKÔƒATý‚æ 4ÑÑKšO“‰4WêTÕÎŒP¬³ŸU¶±‰¥J9b‚Þàkõßm ¤7‰×ë.yÙBdÒÊâb"€V~Ødà¥(,…€`Ϭ  jt?+è —•œ±æªÚg? Ç÷+Ì>.÷j!ï T¦…ñ>/’ $¢D9qó”h“Ù Zfç×ð8ãIM‘ cüô2zK4ùˆl 4”B92ø-·*H0> ™âdA§Ÿ!1z†P^Ô«™ÖÁÛ%­ &|­ñ#®Úk÷8Åk>Ͳ…`’½×ÛB8"â:üU4;dºï°;XîLmÇmÔù¸õz 0D‡ïÚä©s4ä™ðf„ý¾à¸d¡ïIp “†Ù ¿”=#t²kò’ˆZy#©ûº£ds‰Ù«\ÿ#Îd>…9I›céíu3~Òû(/™jÜ®ÃqmÔýKvE]gWÒêý¼Í®°kã<·#_Í!®“ #úºqpé6á¾' –kdÀo'£)˜G0L×׎ØìSCµf·¢ä@§æ":gY0 ¯æÃ7LuRj^·ó™³mOó”ÔŒˆÆîÕvÜ(è÷’ŒH Lfj‚À2äõÊÅNä÷:[» –êÎ’ÞH8§·­]’¡L?nt^7!ʳCF¥Ø7á¤Þ KJº °¯vS¤%R:ã{\vÌbƒA~3à,”óÑМõRϺi‰ð2,檟nIZ nŽQ[©«“Äùxô"Ý}íS£bÿ ˆ÷\t—ªê!ÕE‚ÕDó|ì÷6 ÎÖ ¸E èù•™ã ŸYi„"¡gôøš$¼ Æ 5÷̉¨¯×Ô?z0ºV{Ö%B퀱gO0‘‰½Žá©«Å×w$³NãdÂ/ /¦(¦_@Ыx‡›7S›ÔàEöð=¸] ÁRD\ëºÙ_Rg¨¦1¶ÝäEkˆ*ÝÔ‡ Þ·^ÉŽ6ÙiýoèV Ìc̉9!Q58$ƒiÏqžHj½ýBŸ×úèPº"Ç+I™¢·»‚ÁnÙ1_ã£ø¬jhç@ô'Yxz}_¾;Â3ÀùFèj0ø*ÄÌ·–k"Sˆ¶ˆÛÃÔf Ip BY&Ø¡ùn\ë¿h°‹È7î& \ "H*Îe˜ C¡VdPÝ lÜO}‚EPÞ¸¿’i†dM±Y1e8;c VÅ$Y_STÕƒ'–Þ¤·ÀuÜ_‘t<©0?ª.È»’J¡Å 'þ¦ERåxVc·ÄŸ`‚Ê%!‡­½qQ¦¨çcÙÚî¡KØËÄ#Kéì9~ü*{ú`tªÐ~úŠà—¸¡¥šö¦Ø<ÔQaNn4iÄäjEƒêLÔ$¢Ö-‰Ø)a”H‘•^W¡‚¾NCm«*œhøóÁ~s‘À ºÆ „eÙ®„ÏòfÌýf€Ç`8Éã,x3ƇӞª«>=ΈÆÛ%E»ôù—VÁ§hïIÆ ó$ïº5ÊôPd×dJ½Ût’z‰*•åñnÚ´ÖœÑB )¬š¨¢f“̸­Ê(CZÏïµY!A;€ÊrÒ1òBTHfJãÿr)$`h‘Ÿ.›“¨ nÊLþD|ÞËžfBQÑÖ–`,!† Î@úQ‘9³Ê˜”rj— JXçáýºÆ'©¾k‹âÊ¢a(WÂI$Ÿo0>3Ï5áhHž}')#ÚŠ úŸšÔJ[c“‹Ïôãæ%áϵZ€QU¼ÇðÄÇ&Y?Õ9T£|AmÁ£/•y5ÈóÅz2Ãÿª”ÚØ‰çÀO,É$ø ¦ƒ6ÑvFjÌTháŸ/ñR‰ô6½@ˆ¼’c/R¡JÀ:š±âÉ/r.aœÖMC”¾{.…‡«j&½C>…[ƒîe0ï¾ZÎb¨÷Ä0«³â:ìd9PÔLŠ’µ-_¯š¨<Ø¢F¦‹ïK¸8³¤zîg•jÜV“åm—Â?B›ÀAÏ’ÑÍ„S>GÕP4ø'àóïjcLùÄocc‰ÅÁü)2aq10Ø%„,*–XG‹ ¾DU0Íc…ûëZ¾öû!¦ç‘÷äplÉo“Ï»ô’…ª…ª\ceeéœ ´1èYßå”[°G‹7v&~‰9dv¬À¹Pkä‰~ó¦=F§ˆöÊ…PŒ`‘ÑtÓM–ÇXX’k§˜ö1¾wq Ü@¡!@5Ec0“×éï¶ Ð ¾2[5†ó8CýäïM2‚ »ÅÌV}d‰V)˜Øå(€y4®¿É4Vt Ód•t²ŽœÖCä¤Hh?3œ^2v/KN K¹4ñ”§p„BØèvÛ©¥¡”o¤˜âSRSJ`zYZnr–bâÕéÖAFÝ ßÓϰk@¢{)h\s´·‘Ô; úª6Ž@äkÞØá…4þùœ=Kí42)èÑɾÝÒîJ¤*ì‹ìyè¬O§Ü³ »Lª„¯Kè×k1Êì÷‚ì]híc†Ún‘F3ùþëÅ\`7¿’ AAúÀ@”nБ6©”•¾Í!*zI(¯S E¯ëiG#WFl¹ ".Zõ¡>¢jé“+0ž|WàÄÙ>jdi-\#‹à•U°ødvÄ(`‹C•ÔP¬ùƒdNs¨˜GJÖÍi³aU?fòKs#¤¡šSæì ¨2ÇŠ9ÅÇÈ2ÞÄ@ÊjÍJ©Êô©ŽürèBD¾H1Œ{øÛ ûõÀØyˆ8=ù4C]4öî)>;C].žùÕý=+´YS‰Å­>óSÕ?«é4ï‘5×wwYÒšÞ'íì$»Ne%a£¤ž¬ð³V|Fê?þV´Æg”P[K°Ýß5Š ©vÈÀžªé(²JN±!ï«í¬›ßRb8˜ŸI‘_Ý—æfc°H²æx­‰õ¾«új=c ªžåYžŒ«ji=Fql\[¼n Sv½Py >xt½ÜŠÄ=—xVDs£?gâ’ƒÇ[§˜Ë²’¥(91ñ4Å~¨ª†,?zûe"–ñmÕqуHŸ}(¿R»›æ(¼«ß¶‡XÍšj†%ëúþÛö~3v¤œ=Q%ê­?ï[/fߢGà9ÇFD1-Ê&JhFªŠ.±|žŒ—™‘då…º›0(Ó`‹rä\oYb(4–—fWŠÅÈ­š&6µ(”^Vï–öÞtV!ùz2¬ÆOY‰MÚe®ÇXDªA¡y¡Âü˜×^Š5´©†£©))׿LC³ŠéÎC¸S'AÞ.‹DŠö,à÷BÐnkJ»è°ˆz]±5—Î"íþ;tœÎï·ñü®K©¢bÁ "žjžÉYáÿ4?S­¦Aƒ§øÁ€â‘¶D}• šW‘½ª7ÈŽ+5hÚ œ§6nÔñP´Eâ´Ó ÅdbóŒ¸w«Iué¾ú¾W ËZV“F*œt—4Ê%÷$qµ`¦Â±ÅohU´Èçrq`t)ÂJù‰”‚ºæº6:ïhõtNóíZù2´²@ð€'fV…Ætnþæ9¬Zsøe'u%!)Ü3Ъ±#q>îsEÆÉ& tXµ÷ÏD ¸5½’üf‚}ÖlK¡‚Ø©” ë’þl%Öòt²×çµ;‘ëú?ÎuÅ;Åæ0ßú|@a[·eVø¤8uO4ÄI¢QD«DÙ:~¶dkRœ¼9ÿÙõyŸ¯+ ÅpõáQýÓ qĽ1|þ´6þX1óu¡U¿•ø£ÚðC}ö¬5|9DH5>òšú ¥Ýo¢w k¤ð=zÌ&œ€Œhp'F@’ÃÌ'Åo¢b˜ÕT¾¸¢“¡÷ë:h#OPMOUhÓ‹ ”NMxYLí|N»Иg¼ ›S‘V¢)WŠ$í™K”!,DRØÞ­©'î”Þ"‹rPSòÅ£ê}e:j V¤Š£ä0ïž§Ç‹óÕg§#·LnV3¼²œrü´9çß:ò‰勪þš#aÏЩqÔr›:p¡EnêÃËöð-}X¿)êïº>»mŸ4 Ö´Ú[©aS[MOþ(MâMUÏHß‚}& ø®5lüymøÔðmp[c‚'Û*€HÔx©ÊriîÚù›¦wÈéíÿ4«•ùã}çy¦Ú -Ð4ÆÝÉÈsN/‡Í£›µö–¹lùÜ¥;3HÀÕ szlURŽ5ÞKySŽôÿºæ ]+nËŸ* ÿgu UBßM×4œFÀÛ³*ú/¥9ÞA…bÒüPÔ!N“CHr —Œ²ÿ-yýýa౯ŵc7ž- ËÏPªæGêîòž”Èéwñ’žåÇäÀ9’)¨X†¹uÜ)žDW†²ô–· îw:‰ä8f}•èËõÕ;\?ŠSâ•Ñœiz—€$ùøwT|¡^eÐâösÜʶh©<ÚÐHÁ/“ +M>±¾ªâÓ„°½µ\ ¨–‘çRœOpéŽOûs¼ñ8T½ ƒð´h½xM*K–„î= mætwÜŠ(–›Ø-0ßþ¸~wV¹»a=M¾˜Ð2N]®¹Ð÷Ýv$æèn™_1µå¶Šþ0O*Ôñ¤È•ìÒÙ„ñÛ¨â~Ï¥$©Ë” u¼<eWŸQpÄr#þÕ_DzQ}‚Â)_½e”é¸!?tE¨/¤xáM¾´i½ÐCºsoõn<×ɬ]]ÂÉÂ?I§Ù¡r ï.ùŠxf$—tÆŽ®ø#ìÙrù«Y’r‰ìº±xýÙþ¡ûÕËuHä¦)0ËNO ”Í“NLϤɻvwH¹Z ¯'ŠIÙ‘¥ÂJ#…áܘ"éœ%™­¥”¶âÜ!¯‹ÚÍ^䬷‚[™/ H$â.Ù©[,‰KŃny’4ûÞE`ݱ¢…¯‘¤¨Åìëù­þÎQ¹¸—ÅÜssîa?6w¯Óý¤GW ÙbåšÁ?Ûâ‹,ý‡Úu‹ ]Ó˜ëúæPŸ¶s2#y?Ô§g×·ù‘Õ·9s—ú¶r^àŒ ®)÷T¶™'ùLwa›¹;[(—ðË`@:šÒÔäÚá©«|T" €’5§·ÜEU.€aíÊÇk÷YØŽu@ f%Twç¼Àt1sµØ‰ää:ÐŽæt·Š «Œ©fŠ—ñV©#òI:­“Û¡xðÆ è4e{÷3UøŽÝ'¾q`ä>3ýé…|ò½n‘¢ŸÙ¾”ù”ø´kJybÚ•r±ò9W\Æ}2;¨ð”oTó:¤D Ž¢ºîN)ÄjÕw®© šL.måÜäò1éb»„:‹«hyðpë$ÄFí»cG;ÐËXW$å[º(ëži•¯uêÇÂ*—ËŠw»8ST a[9‚ˆ®Æ¨éýÝãÿÿû_V¯­„endstream endobj 448 0 obj 5727 endobj 452 0 obj <> stream xœí\YsÇ‘~ç:ÂO挗Óê:ºÅj#lS²ìÚaY I @A ƒ’’¨_ï̺2«;{f [öÚ±dp8¨®®#+/Â7'ã NFü[þ?õà½OüÉåëãÉoáßåƒo¨Ôá¤üwþêä×§ÐÉ(hâÕÉéWòÛêÄëì ôÉ髟oÂvÚ [=xïÍF¥v>ÄAaó‡­ŽƒwÚm>Ýê͇Û¬¼Þ|²Uc„!lzð;|BŒïó—­…AÃh¿<ý=,æc‹Ã`=§e 0ué¨FÞsgík8ÙøOÅ˜ßøyímC·GøŠ}ʸ·;³y…ïðã+øÆQ©ÍKüñ ?^àÇPŸæoðãuëü9þ¨ðã}ü˜Úº¶å~ð£b ÁmmwÖMЬSÏüü}z>µFEZêI_¶oÛc‰´Êû!ØJj2nÐfsD¾…1Â`'8Ñp<Öjc7×оZ8>ÜtpÃdíæ ¾F5&R¨aš€Ø[çíÛ›­Ó÷©Wøç‚a­Ò0YþÉ<üÙ _ÓÔxQ¥©Û0le·ù«öjó6õ*¤“ 1”—âdñÀõàœw¸‰is¹MƒÛQÈ–wðu0Æ+—ž^ӸؑF¹¦Y.óÒÆÑá.`K6˜6v!íïUÞŸs¡ìocÝ’)7*<²]9£2ÃäF …‘ö¦ƒTÎió@S>jìi¨ýïGà°$RÀ?SßWÃN¬Q• øZ£÷÷ÛÝ8h­÷e½Jk” ´›îd´‹(é›Ïð±êNP÷¢t2qól«cmDÑÈ£Å=ÝEŽ»ª“ïgÂ׸Çtå<þíÖ¤—k+h£Fõ ý‹²‡˜ýf¹f$(0ù‚q1xô:réDÒz½$-2pÍæ9‰ëM;ÇÂW•üÄb 0Ê7¾ã ÍöHï°ÍúÔ#ƒ‰™ô´YO&šWm`ZöBºŠØ%™(”I21Å Ä©b ¼bBÒLð¥¹9ÝA“uC…ù=>¢/=½×í~2²b1Ö'Å"-UÔt­#j[“U1ØY¯ˆ«‘–­dµ|;mÿEòCüø´}{‚§øñ”›°j×>oçÔxÓaf;R>û¤5žQOäz|€®ªÒõêz×ßPã›Öúµþ²5Ò70À83†ióß4Ó3Þsù:ƒ_l¥í?¬’×`‚]`ܪ)1ô¹¤»^t¬CÂÆå³²ÙY/ãÈãÐË8,´†Ô7MYê|/MÈä¤ Yg˜_fBß‘¦ÌÚ Ó ·?#!bÆVe’º/Ì€¥·nÝBFvóÅ5£þ‡CÖ*qF}¯“è<(Û©ŠÒ|Zk0|«ut"‚Õ`¦¶`Ø$Z YGTUðWfL«tŠ+J&óBꣴïu¢cs\pú*í7Y/Á»^[¡–P bR×›|*£B[2–Èñ3^9JÒuÈfŸG«*ìbºjíýDüÇ­îymlO’D56‚+4j³"¦>ÜT¶¶¸ùÙ­,{~žAOl%ùÔuGÃ&>[ÁŸI*-zór i¤ëù!"g~‡Ïa} `ç­ñfËhþ–^cl|ÇE°Î…ÀN.aÇ5Ѳ`ö¦©yŠÆ0ø±Æ'­ñ4‘ÏǨÐL¤9 Çhü(‰»Ö|—Ô0?¤¬{η¥—À€èÀy”ø‡õá'¸”G?fåŤæ!.=€¨ÂiCŒ67dÔÑTR ~»3klIxü IeàjrP®ÊñÉkœ6=‡õJXôŠû¢Êvó‹h±wp7£2Gx>e½^—¾B^Ôžéäa2uȅݹ!ÔCmJRÀ€EC»‘ër¶Ùò5x»`¨„ïÜÚi³õà!c“f®˜°SÅV7g»@Úâa: !“MF˜cï:Wu¼Þïx›ìóKÌØë¢4C´\E,¦J.Pˆ,öóŽçîã <«fjT”æüÈþÌPß’¡4¨ÚCýGjü¸5þŠ`ôÿx¤‘ö"RåAa;ŽHÁüa„ðhDÚ«mæ£ A€äýNǬ´w“öÁ‘~J”NƒR\ù”Ö°ÀG[tï|‰vF`þb½’ñZ×m*Né`ŽÆëŠ÷a ýŒ1öŠ^ Ž5^,ÕlÅQ‹ž÷ÚÀAC D¥ƒíQE¯f«#¬yÐ ñžÈ8.@^R¶ë oQ矑ª§˜¼>,S¯)uZðåe°kuƒR+ °¢TšG m ´ö`¡ñB¥LqÀE’¡çõè§ÓcÜV͇ëuÚrs¥³M~ /-§¸ˆiÇ='´ „Ϫ¹©#žf8xfŒ³­ÐFÓá¶ãùkC— sS‡ž¹³ŸYÀEËfÅ©¸¯\36ŸZrØ´GÕåèºØlR“nÚÆìµ™+‰ó®½Xªêõ' ãóƒj${SUýp#¸¿ÅLî¨×qÍŒÏy4¥;º×…Á Á›Ð ”ð§Äs>uVa~Íßãžaå`RÜ7dRÐÞä­w¦ä°\_—m÷ˆ¥8M6zÎÍ5-g‘;Y=Ê6xSþÓâîÏ©ñek¼&‡A‘?jÏÄ÷ÔJ™oz‰ÆÇÖh©1ðwj£å9*®áœæ9p`s­¦¿Ã_±cõW@|Æc]ŒcâÞ&íb€6MŽü-I+k5>›ÏƒïÎñÌ–²NYo¿.Ãò™°+ᛕ™ÎQÁ¥ZŸw¸ZGÇßÎre 9Î#™Ë8Žú–ÃÿåIUmt³ÏeÂCè–5Hx&)Uä°-×ëkÕ¨\Œ–œDézM…»B13yê¹¹›Ó'it`%oŠé™?5e&û˜}mÎæO–¦îH!3ù4È3êÔsÌo¹hV2äàÄKÀfA A”1¦ïH#,Nÿ˜,Aå°¹“MìÄôðu Â#oÇÞažù°ã%Ò4U<Ž,¡5Ywˆ¹ÚNü@k 4ÑÄ”TÚ+j®9w: O±—RÜÑO ¼snõ w횬!±¨:€ÚÜ4¸ëç\d©æš^,¨fFøgá_ȶYà÷Â2«,ér^û%+Ý—úPÍR:4LÞKœ÷Cë(-¢i€ Д $2q" 0¶Ü(«§áiJ–%Íœh{W³*“}…FµÏ?§Ð(QK.#7¥@¨n¹çéU=˜rB$…ey9>ø§1%¸Ì­ÚQ¥A¶?QLšóSžTº$<½ÓÍ2Lr0ïCþ½…G³BïŠ`°ž…Pr%ñzU`ŽáåZ<”À ù v!VÔ«]Rñž‘ž ›(˜³A«¡@PhU­ÂE9í…›lhrÅ3;9ÇS„k® ãêNò¶Ãy}%BU¯…ëfeVï¶bf¥yñ† @vŸôÐÅ ~‚À[I Ý'CПžb*äèÍvÊË6˜ùY8rÅq’ô^QWZ¨ØX¥{ͪº/‚0È 9ôL`m‹(lØæ2f'ÖˆÔízà r-T. IuÂåq[7¯ûzŸ‚¦‘»ÞïôÉ,L›Ö£9 ;hTö-ùª@n[ ä¿×>(n‚::¹êX^X:¿k•ËFaV†8ðpHm¯Çšè‹‡,“Ì1n?A–ùѧŽwåc÷Eìƒô"£Ù×ÝÔúÒ_Râ\I¤TÔu—G¥nfË‚XKòÝRã×­ñLâNbª»®È5U©F‹‰~ŠÅ%Êhœ¤%´ò_´ç¿ —Ö(ƒ_mÊ(òE±¥°¯™Øfó?ÔÚ–ÕÝ~±œç’qnð-†7®òHé׫ÙÄ#ˆjsÜôšx$…5“3•à&«äMQL\I‡•¯÷`Ä1é Óì²'ðe¯®Ø}¨z f-‰È‘¡UqßkÁñÁ£RpZþ7¤rÑÜc+`@ë)!Ö“1"vâq&ŸH HWͽEû`©É>íÒ«W‚Õ6Éa+fˆûÀí²l«/ž¯Ü=EP6)™i†…?f†ÍGêûJ z0¼Sy– º÷Þãà¦Õê9iêzKËaˆHrq$õ.RKÚ[¶—7Ö+b!Y‚Ž:ñð;\_JÎÐqøjøIú{¾×.EòY¶®¼ŠiÒØ¡ð›– ”nU®ðº¿°ëd!VY¥Ü%kå/?6”Å HM4©L㧈ja—Gõ—rÓQŽ×ˆd,™ƒ½ØVyšzˆw}Ö¯ Jh÷ ¯—Ì–’ |4÷®ôÃS³¼ ¶¯< i”oÚioIÚ3¥Ç<ÖžÙY, CYLUµaÐèä{EŒƒm9‡TƒÔ?½X"oj¢™»Â©Z˜¹éËulJJWAa%G¬\§ (®6Ös%÷ªt:¦4«{" v-‡U‡ëMÌ]©H6ªŽ0ªÑú¸M¯—@ ÷K[Ç ÉwhJ]*ÍÊ,]$µ†|S‘åFˆM¶ÆûË{6¸õ^¯3Æœ*câ-[0~{‚"( -²§fª¤Bĸ+ˆš— í‹Å k2å;Zǰ´ëŒ`Ê©îËü±ø»ËŠk=ÀüŒ:Ý7¡’†0}¥Ê ý=ö¤±)ÔšñŠgxå~µIÆú¤ÌKž!4z#›0 +%¹Ê$Âêa°ü@7vZHA¹ÃJÇL–ÞÎrS&ö ª%­"ßͳ-z|–åÆã¬]”>õ¥º‘b SþjË´w»Xº‚/–)o%ÜZÈ üÁøå^Ëí¥Pt¤(õ1ydáúŒÄ|]M*CÏèÈI#†mp…·œÅ³âvCÔLs/=g+öu¦o»š õÚÖ3r|ð ‹N’v%.î@ˆT‡= Oʇ³Ôø]†]¡G¯ÎïUw±'7À”³túx¬˜½P+ÁK1âx({³ÌTýVňJ•Xªø8¿­”= ¨÷¿¹ÍàŠ,‘ó cH|#^ MÄ*·^Ø °2œYþ@¸Ñ“Á: ËÐzµçˆû½]±’AÇwº‹4éR,Ä™ªx—yžz Å,æüvž¨ 6ÿö‰h[ÉÙ)-ß#£çµœÑýCÂ'Ú‡”³<"r~Y¶9Îw“õœ×»[ǹ“s3gî(Ï ý—ùEyÁ¶bèdžtK¿ó-WLW.„óí/+ÂTÿµá-¥[¶xµ¯×Úå®ížû¼ØNbiéN »:,]£a£JÒr!eÜgÕÛ~œ-¨¸™™:bºÈ j&À½“)e‰G$Ú¬f_gùñšwÔ“˜)]»P%fI…ûäÝÈE¢²ì[¼œÎÖ·¨èDõÚ8®6€d̪ÿæõ…÷Pý,ýÚ!ûö ÞÜ)—nœÓÑI§Ðôþ=KBh_’mWV°Kü•ÿÒ’'/º¹Ï¹–»ö„'«X€=eˆl å*gKš\·¿£|•4ל]î·ß§…+oñõT¬Éª½éåúÞ‹~U)ÙwÛ¦ž% ½å)–œ Lý>Z¬‹2†ÿ’WÒ̬dúÍ6™noÙã‰ºŽ®4xÍ¿=ákfË(/Ú8T]®ø‚ü©ö ÔÖOû¦§Üu›avо¸Âåm£ÒÁ§w¾oT|½=Ì+D –:z)QíLêù®&™¼üüN¢[})Ú>Ÿ–·qpúËîôëHtïö1=ÿsk¤ßê6gm²ÿ¬}ÓXû­Ä±œO+Kr6å·*oSôczþ¸5þ¹ tÅVÑ:ž 3R2û%ÏRÖ ‰«Ålìï„•3 ]²í,2ÜO¥½ž·™WÖ’ª×mêyžsŒéªîÿU1~#Qê9ÓsÈ ‰ý‘ùO™ó6N÷[¼jÇØà ‘¹’ˆB–ïneæ*2w|êúü»nîÚõ%'K}¾˜4;õËz>éó6£«zJ]oy-;ÙÐ)óáéƒ?Áß¿{Øendstream endobj 453 0 obj 4907 endobj 457 0 obj <> stream xœí\YsÜÆÎ3Ë?bß¼HiAÌ`.ø)–,YJÙŽ,3§â”‹â©ˆäÊÜ¥hÿûtÏÙ4v)K®ÊCÊeÌÑÓýõ5˜æ/‹®‹ÿ‹?O®_ÙÅÅæ [| ÿ_ür |‡Eüqr½x|„„–vè±8:?£ÅÂÊ…qª…—G×ÿZºF/e£ÿ}ôWÑ :Bvª ::…ŽOšUßZ; bù¼í085,¿läòe³­RÚÊåQéó4´öÊ-_AkÓúµZh—rheÕåÇ<ãt œø;Xç«FµÎie苯 »Ô­èÜòYƒ­±ËøÞ }/–ß4+‰ý{%[XÉO„D ÑÖú—=N'–?4+ V¸å?Ùv*qÄQ“ÂY?öÇFvÕ ^E~­`¯V C`[Ø]¿¼ Ó«A/Ïš•R¦Õ¶_~ZµË+XÔZ§$¼WH‘”ËmÓ›ÖY¡–¿5«®•R úÌê`C¢']Á¤ƒ„.ýò14®´YÏ7È­U¤wa׿,r•J¯›@éÂL×ÀNà›5ª^W àOo—kèsW¶ ăÈlß“€Ùi$ˆ†_„nͰü{nËd®a×vBõË“< Î_Ö}Súê´¤ŒÐ|\¿92´ifF¢³”`ì~Ñ z~çDR²“¨ Sc¡pLÝ U"OYªNÛé„o'‹G¹«ÞÐ !`ÏÒˆ›FÚV'ã:º"Œ„ÇÄe!ÈêçÐhp¼GVšòZEÒÙÉL£´dÅGindÔ*qj%zèØÉÀ°ë4¥Ö$È $¬Âú[ÔmÓvð|ö­¥AÕA×z1è"à÷MïŸDÞ^[”eî†M=,Ö»H­'šà}l¸¹€ =-ÊPÖ ïá8ö§+}È;* ¨ÍBØ› pA"2äwim™² nDé<äIëºNËå}±¼Ÿb•¨W(é4q$§¸IÙW\¢JmD’Á“ªR©È.GqIt$C4ëSÁügŒîÄopîi¤üž[V£5îu°Vçø^)×K"+\⊨7à ¬Tk!d Á€) óÚ Þ"šûÞÆëPd¢W!=¸ÀKPÓ©Ðbx@ñ=8_øC.½ÂéÝÐ٠̨QÇ,èqNÆ?×’8Ò@²ÎñWá7Æ*b½Cs`fÔ¬6Ÿñ½ÆC¬Ó`Â4ã‹NS„Ž­ƒZ`¼„ÙgÜîíÓ)&, Ëg÷lÌØÕ®‚¹W" H—I‰ò"Ÿí`VÚ2 'AÑ€EFø® 'ƒÊL‘6à+iä >Ì Ð’.'…"8§ZzбY—à—0¼ã]wöE‘9D™_£µ•Akó;/¿EúVá¯çõ0È¡veOJ”7 C;°æ$ $F-tp<þ ;`pg2'A:Ѳ¨ÁÖ`#·+ïUØxš=_µŒÃÑÌj$›Zé?ÂAôT=ìééƒ ŽÊÛ L,—\ ™ä¦ööS®"£”„Ú9îy…€“Ã?Þ„‡ón+˜àó'wp-Ð_¹,žH†T&îm¥ú¶³ƒ [t˜Yå ´ Žºðtæâà #1°Mï¯üÚ‚3|‚”ˇçàˆ ZL  ›Ò­ƒA±£1\’0‹£oŽþ¼+µê¤÷+>wpÊÙÜ)ôU*¹,Õ ˆH âõBo;ãh‹R±Î—„*Ÿª:穚sFÉ'R§ æH cúÁÁ¨!gB¢¥ ú}ÉLq‚†rhOK²¾l”enܲ@húAÙ]Ⱦ†Œiö… œì}õÓ2û§¬÷>Ø)¿ab”9þ@Å)ÚDìÖ[Ü@°7)rm—ŽÅü]–xã™·œb€øñ§'S­è$µe8c¤JB3N®#jtYRªI6â8ÉõB‡IqráDµ0éá¡Ð!”  N6s‡F á.``î-,«_ï‰RÊ>`¸Vèp²Ü(UÇ<òPé*TöÎx;NôgeDÐA„€æ{ä2 jÇ =á|'9` Ç^ÓÁ¹Þ@×ÓÔq¸? =½M0[*š~y‰ Æ[¦ÇÃF'”z®HTG¼HQ-Q5ÔùP®4^RÝïaRâ£J€HTueÔÚ¤ W¿+Š@”ˆ;¬ˆqª„޲Ì8°‹lªÕˆä7w•¯NÊE¼É(áÀO’èœ:½ÿ`oŽ(q¹Qr–û_©õ• ü)Xú &’üƒØV½×7/Œ¶CùþzÿdÀö.W°Ó> l:ø }´‡a˜Ñ”v ÑW¹ 9Ý9ãšÐx\¯p&¿x9}A§O…îmi|“O >/òcºSvû¿åÆëª'>¢÷º«6æ<Ò¦Ö£òø2ÂÖÔzË΃ӑ°Z!˜AW¥µ­ ¹Í§@ÙH½ˆHò\Ús…ÎQ¤².¬Ýp(~—ßqü¼åĵñÖÂôç £”eÎ/Jã!E{j¼£sNÁuËÉõ˜“kmÔ&:æPZ–¼ß³u¢ii2SUø\W“ ¤®5õéñºAÈ…ð™pi„œ©Í3ÕàÈF©F‚§Zò»ô÷ å{|º(:Rä{¼g¢{ŠÃ©T‹±^qè¹åIJå„~²û5&ð s€Mœ+Û¨-™t$jFgM?:µ½Ì–?›ÿ‡¹àÿ›ÿÚü?Ïï‰u>Ê/Ë`§9ý}ˆyF9¡ .;A©G¡CZ"IŸ†Gw_„¾fI«ì«Pã]m §ü%˦V&†Èlj“§"³RYÀ.Èú?œ—)sn‹¬¯8T¼­ðø@TœW\kµ¨®ªß¿g5ü¶{ì› ïËhs£õýµV7ŒnåCà:qάÿ{¿Gú›¸¦³DyoYf}²0 ¶¯Ñ7°€­ü òS@„ÆØ ´u;yŒ_5RëÏÕ®F¢Ä¾Dý~­ÂÅ‘gõöÕ ¹ß“MLíI­€×œ,o¨ xõÊO÷|¢o#?z]ÙtVçCòdÚœ;m*úG!y8†¤JFÁƒß;7ŠÅva‡øÍôøˆ³¬7!Ó¼fÍÉþ~7t¶#–9±_ÏwjÂïèô‰—=ë¢Éæ¡b¿aß+Üuµ—i_/çA´¿Yí0S­,¦Â‡t}8’ ¡º?ôÚ”ó®Ó —7ÉHe\Ĺ)cçœà‹`/84Ô æMê „[É·_Îté=r]s¬ÎX¯’Ï»è'§‰Â6sl}i:ªˆ/Ê:à€•³žÝÞ…ùÅαù(ðÆ›ÅÖÚ™ Û 4C5L/ò^=CÎkîå“ÂY_vœêHݯÒã˜rPu‚™¬Ðq¡á„cNÁÕœAšê–£ŽMo©`pÊÁ1kb‰'‹S§ž¤ªr¿=#º|\™Ö-¹Ã“íÉHf³’p¬¤ëZ3veï²YZ׺4›Ð–Åp±‚}²X³ $x_ï֨ל¬7áƒ%pÍÍ÷–ÃÁ¶Â?*ÈM÷P ÐjPËÀÌ@’“‡EºéÐ(†"Ø‘t÷ÝÕÖ“ø±}‰ô“üþiyÿ*7~W¸z»[”$Íøy^iÜZV¦äüóá¡ÖÎÔ4Ä|ÔƸæ¾âÞ((ŽF$f'3‰óϧ|ü§,žÊ4ê³YËÏ_n¸•Ê }ÇëEÙ[`$P}º_渭Ð:ÍøRˆZ¬³?Í™}±NÑÀ¯'ÛŠx·¹@rg|ŸÕ:ö<‰=œÙpÙT®‚ÀðÁ1þôH•¤X£Ã›»©Óœ¾ã"‰ÏçÌçã‹›CÇÉ{rqn —سœÒÈ~Ö(GI< ‹Ï0.ιäÜá‡À˜àŒ…$š±ºY&’H=ú¾‡'ˆuœ1Ñ,–‘D >^)ÅÛ ÖóJ1Ë~VAlbÃ}¦˜ÒGú¹†0ú]µ2IG'ÜÏÊ'x+pV15²jŸµÞã/8VÖg#Éœ•å­Ø6u³›b™¦ß¦çh®op¤íZ}Īè‰Íñd†QìFB¾é©ï(x*¯¯~LÓ)>™ó$N*¬¦+Ýrø)²bcßÍø£Û,`J„‚Ñù—Qsx4qÛb*vžäLÜíx­?T7Qšù '^”¸‰á4=Jêt·¤Þp<áÎFj›?© ;N®h‘”³´\ÍÚúng¸ô¨ÔÌ]Û¨#×'ëk¹é$¹'¸Ž%ràNs½{Ÿ×-÷3wßç'—ó5Ôtoor¿¸¢ä»Œé®·¡÷úòþ:r=t£pÎ/RÞ< w•+SHq-2€<ÆË‚x±qßítËÖ8Š÷5ýæLa¿YYM0*º}ݰw*ÃÈ@ª$(ïG;©nk–B›”ï×~žÇ&iŒº¼ÌâU^r1“  %Å=åRæ¤6]ð,õù¶sdNígÉMV” jŸ/ò‰ûN¦Ú=ÀwªïèÇu¥¾ÖÂŒ‹n³äËι»Xr£IÕ1©6%®ëšìTn*Ýè¢;{Ó˜4¶q™\Á!Úô××IÀV½= w ]Óµý0X…·‡HÆe’ãFk–—s€10½ïÕE‚AɺNjâªZ¡;f4ÈXúg†V:t«dÚYôc±LEÒñw@³±Z ¢[¼üý¼¬t„Ê«¥´ÎTÏøyÝèÖvèâ >^‘=– ¯±”L·…иӧ*;€˜€<‰5·½ $ÇÁÆv…¨Á_°Ä¼Î£9.Á¨ºN$>‰èèýਠZ¹XI5HñQ6Á©ÂÑçMú þ¢3©oÁí+_q1ÁĨÊ$Þm£åX}5-eê`z_ü8Ò¬ÓºûŽ%¬ºÝ}õ±l='_5.ŒA3qá ™¯ËTÖ×’ Â•ø¶°q˜«uªÁEÊŸ •²ßà¨ÐìÏõõà«K©3j».U)™5.¹"dí¨þ#ê?V…—Ò‰Ê`<*W%žRÒÕ+ ¹ìV‡RþÙË÷‘csu–¥bH(õŽtrY>îsò1uú‡&ˆÌÓÓ/iÕ cs/‹QŸ-_ôUw辦(å©Ô¼âVž|ðË0ãÿB  –Ô8ßŠÓøãäúàñ‹ƒÃß.¶·wg‡ÿXˆƒÃçøÏã—OàÇ‹¯:xúbñýþ-aE«p•¶ó÷Ä®Ã)þ¸¨ÖQ*½˜Ø¬IÌ -Õ¹¸ù÷D€™¡Uig¥|l g³ÙKAäý¾ÑXÆ.ݸ!/‚í¯w†YXŠÚƒAÞ³âëJaTÂséM¡8ú"ïv-ÕE¬¬ õA·ìzr䓼mS&¦;?)Ç›½½ùs>Š©ï…’·§ÁÓ“5’ïT?©±Ü˜.ŸuÙ "®‘äöå”%§&4Ë/9ÎùÌrê7=ØFܲ–_‡ž7§ûÌeã}é(r£ÌMª¼ð_)„h endstream endobj 458 0 obj 4412 endobj 462 0 obj <> stream xœµ\[“·q~§]ñ_ØÊKÎIéŒw N|KqÄõC*ÊÃj×¢\"¹¤%Êá¿O7®Ý`Î,—‘J¥³sÁ`}ùúëÆ¼¿Yq³â¿ùÿ÷o^üò+wóê‡ëÍoá¿W/Þ¿ñ‚›ü¿û77¿º…‹”€#KXƒ¸¹ýöEº[Ü8yc½^„¼¹}óâ¿OþlNËY.Î9u’ñ‹óa‘«?ýæ¬à¸5æôûóE,Þ‡`NÄŸ!xN¿ÆŸZ'O·ç \ë¥Ð§ÿ:ËÓŸÒmÉ5ÿsû˜<—L Ž/«‡yÝ>乨³Á /ùÌE­‹!¤ þžž"Vuúk™óëö㢅Y¤:ÝŸ5Òº”ý®Ôë**½³Z|]¸)H8¢,xïAœzñUû›óE:‡’ôþ0gëL´ Ì‚ÆHÆü.ž¶Uí¢Ü F"ax¹¬!€TÒ•:ظôÜ…t"íéoðvx¼P°Vù‘¯ã[cÉ?ž¥Yê×G8f.È»‚-ùECÀ0ðFîUóñ5/ =úö¶Íá¶_Í3“(P~Vœ„ç2v0À†çß'p'g|hjÞ.ÈþtUÄê âü^o@ûdzwI¿À§ûDwáLè¨J”¾u± ‚ššZÞóì徑 ¾J¾z2%6ø” Þ54‚+Ãâ$Þ uþuTt šìlÑô:·ÉÁÓr¶×ÙŠ¢‹?Æö‹k¼$,Y?tÉÄÀc*ÈEÈ+Àt\­FYÎ<% dU ¿£Ð?Ÿ÷Pv–$Ù,Mëõ_ˆªÿƈϩÿÆW.¯,’‹>ç5G.OuË„ï%ÍšÐh©ú£Ÿ!}1ØSÔeúYuÁƒ,3ŽÒô’y|eRþûp%"Ü÷@ «¯½¤Z;´ˆZ K4Ž^ÙŒ¬+6„as8Em˜æG¼ø" Œ¦6´Á.Ò(ïÇi£5sÿijrßQ¨-CP–7æPIí%B4H‚º²ŸaÞ¦$,lÜY>@ rTi˜W h\kWµ|ƒdYÎÑ'u"ð¶8Q¢m¡ŒãŒ¡nŸŸŠxOt™+Àh ã¸Ñž±Æšî˜ŠšcŽ91$ëè1žÅqÑU'NVÙ«ÃmÐNZH韃fŠÌ—2×L@&–ÌsSô*n£Îu _·±"ùÑä+¥Þê"ªòÐåmt=®Ñãþ}3Kæ$ï‘àÒJdzJÛ¸ÊõlqdŽi`±›†²ñM¿`n\Jëc¾õM½í#*#ú&ÒÎn@ñúxb[SÔèf –bs'|9Ìb‰˜ºXS$`ŠXŒEÚ)zÓ‰“w!á~à.fÉ8y@ƒ§„Û.p±Rëêã_åœôenà4@jvŽ´‹ËCì‡h4àŸz(=.Ó·(}œ–»:æ„‘Å2åñ6 Q0äR"I(bvÍ ¦¢þ¾J³,,1zXÈwÑÃÞ÷^¿Aà/¦t6=·e…É;;;ÿž0ÅÅ€toVÅ|`˜ÏüF§ÚÆÅI¢j›߉>r¯ön×éS…\%zr>Ö;2ù!K$P¯¬!”à HsÂisT‰ªØ"ƒÜõæ^ÀEÆu¨ë;é(®¾ÈR“ J#vÝèæ·íü”"ª 4P<¬¶© "?:7˜–‹‚¾†ˆJÙyãb/½Þ³<–-Ç>ǹƒgTð‹ušéøÖØÇüTŇ4àÂ9ܘõÁ+Io¤óÌe («š<6 3|ÛN°ÈnÈ«l±-è!þOPi‡C"ÀÛ;½‹+rð©ÕlÑË3Íð½ =&âä_Ì‚¬ÐVi;DÒeáX*˜põƒR#ÏOß6 ôlÖ' ʳèV¡XÊ6$äFÆnÉ~â6|3 ÇøR—÷üC‹ñèËæ`Èè$V¥aÓ è5ù•áu¡¥Ö9AĹy­lå1ej †E½÷„nø00£áM„Pjÿ]ÍòIFš©ØÉy²ÁŒ«¿´G-²5’9ø»ØjçaÕû”G1&øC3†M;ÌJ)æŽg°1hfqKâI~:|‡&êløðø7WÙ°$.n1ÄÈ-°ÁY?rcAåS©ÝòëiÜH —‚Ë`’?‘bõh•›]‘‚Ká–eÊZ.:$eZ¿>Ÿc•^¬¶CõÆá´pa¥éjo2áy#>1~åÂÞ~ÂõEˆ°“”hB“çêbV^#+?†˜£åû,“ù± °ëÃÒ®5}ÓìÐI=hfN÷<—¢$Ýde±³0Ff@„[ü¹ÂÖ7¹iºáIQR!”$ ¬Ãd£lÍ &‡²è®„Ö8SuóZWa¬­KJ54mI DÔ^­ Ó¹aãä¸gj¯冎aÿu`,»x't1Âh÷¤hZ×,\íaþ‰„ŠªÚ³ µ’kÍU¥™8­bnQnb\>ßÙt"¹•T‘ŠF©§u;åZo™•r“uÒÞüQQ·˜8Uq> MM›¬5²m«1Ú¬çg‚êšeâ캭³Ð•ö$ÌZE·0!lcÿ«n#÷ B#!¨RË2Ÿ`Nà îÅ­"æéBo< UÛNؼ!+ƒ!k5á³ÕnR½¦ýõ{TsîÖížm?ĵÀ™,¤B7#æYê£)à•Æÿ:#Þˆ›¥ú©, (D3¥]EîïR¸Âüg÷Âgc@¡p[xlY¡ ¼­D°´sjØeUÛ‚<%‡ôAe€DO1êðÍ>†üÁ¬Ã@NÒ”ÄGÀ£Ý‰å9J›Øûþ$¨”ªjÃâÿ0ðª®ë½}MS& Ð=ø®)°UñŽBP“x5œY·Ïò)+=`1š€‹¤@ì'€+»êp™fIWß´sîAaÇËÁÐkqÕšÿûw¼ßÆF&ûúèmãù–(ÙŒV Ë[Æ9Ä#| ½‚°2âà@·T׬M7c²/ªã>½§4Ò s|e"BíBái…íë‡zQµH?}D«Zíµ‹Ån·“ gòw¢ÙÉà]×J#¿Ì(ÂÌpjG(ç!«Ôû ú©Î¬ÿó¶Ü-»—Ô ýH¥?¬O¶¬–¢mÛL6Ž$¥Y†¹6=-h$]¯&¡µ.÷¬׎NcdjVŽÞOS*'OE3Ñ2Áãªÿ•JíòØçÌîjag\eÁP¡šö‰ÝÅþ³Ar³)F^m¾FöºdõªòaW’Ÿ¹’BÿVe>´Å"q ‚W‰g£QÞôàª<Çô¬tVåëyD Oëóup¼½š1õ[å÷šaÒò5ìXÙf+r\³¾'(kSý$²ê65ÿ !~ù•+Û‚nqQ Lò(p ñÅ‘¼E¿½âÅ무„´¼ÇqÖÉ0 ;ØpãÌnØIb‚GÈvÆÕOê=H9³´?gIlªX§l«|v·nG;Fž7÷M·ŠO9~œ @ÚQ“+…U‰#’Îõhó!·A6Új´è”CjÍ|jMæÅ5ß§îòN‹`Ç‹pd·Ê~ˆÌïºÝËÅ‹-:vSv]¹Í2ï2±ìQmowÜàVñ¹À51þ|–ÝÆðÎŽ/Å6/+ý™†,Mê©ì's‘®ÿ¤¼š´!¢ëv①ʆ˜ ©K?ﲑ6–:þ ÐXÒ™g™—‰ƒ‰„tEpÿútk}M“ϱ¦Q§Å’Ûy3à Ik29ž S.Áb˜ñü¼ï:-©ç5“¿o3Žä‡µu4fã¡Y3éÃ.k×Çp:ž( ¡\ê0ÙüÒñŽiKbfBéC_½ U¢‘΃t)É×MMdƒÒ`¢E¡(Á)™v–4ç#›Øþõéðó\ÅZI‹p¦”ú¨Uµg¨qåßõ´@_~*bºÚ Õ‘öªì¶þÏ=v¶ë×1+ù½U·?7©‚uc‡ß·Àmz€F™áC1#(¤ÕôË,¬1@K(B"åQñv3iŒ‰%JeÁð<îs|6'µÈéÊGMJ  ó®ÎTë)¹Y»Á”ÇË«£ªÔ÷ZÖME)À©Y*ªÙ.Ö} ƒPZœ7T©ÅïZ÷eý>@×ü‹g67a¡–þ¹^ù›ôLü¢Ï»¼Ý~%»ï8üê*UA¤ZY$Õéa‘ÊÈ‹G¨ôé+Vå‰lûÁÕ ¼­O ¦Æ‚çf'qSÑ(“½’ rÛß ]²“LŠííPˆ uÛ„£ŒmßÝ8Høi6„¨xù]ÎLE×å–¸è=ª§ç`ÛCaôÓž¤°L ìä£(óÆÂ®‡¬ßo`4M×§áŠÕç‰X¹ãìÉKÅ›m3õι–†¹Xî]ZÄx#zLžó¤.„P`˜ãdŽdØmG`ã8WiV5lÿérδ&ßYJnÍÙ€œ~ʆmŽÝ°1shv¤¢Š7í;“^—å|€¾y"Òù ÅãÃêØFÉc|&d£q Oah©<ªâè#sóÈeXëÚ:§çÄPÄVG‡4¬öõ:üü(â¶ABÊnøjâjÛ?Ki3Ö›òZÞÕRIŽXçÝAü$çÌ]F&µŽ³¿ i’¥Ñ_UÓÈÏPÎåjooœŒUd[HþL,EÜ›O J6­Sþ2îZ&ùjéã[Åëİ@­HJÇcð’NmØW“¯ý<«‹ ó>ÀO˜Ìn`ÿ ×î7iÚ9R§ÌÑûóv»¯¾Ž:äë¥ÃUâµûnZ„º…#Êô!(»³Ù>,«ùv3[l «°Ã/ßý%Ó=Žd¯oϵŸqê ógÈ×%T&ÕÀrº}¸b`1¼È]¯Í™$âûVç¡l·Îäïj•vpäúHÅÂAÒŽ/)-S¼¾tès~âmKb ™÷™V0bS¯|Rõ”ïhï48Oýœ­G¹¨éäjª{mq÷ù|·ó¡Üv~0¾°l ˆ5n;éT¥÷­Áqô–³ï5Ä6¿É—A'ÛÜ©Å\ãhÀC9™oý,øÿ?rAf>O¾¤\ÏE-Èâ#ÝQhüÔ°6E 0Hë?ò5“™»/%¡!ãòÐò®õy—6 ºC¹ÒÊÉ{úö´jöÂ`u5þ§€ùJ:Õù+`­DW(Pª9ŸáÃWX—ðªtˆnxVŠšmõB½Ú­Ÿ¥Ó´H6Y€mgbÊvkâhÐg阵&aN&&Û>ºm]l[pÚå<û(ô¨²ô*¹GLž…üK‹ä‘œðaä?jn¥¹þ¯o_ü'üû œÀcendstream endobj 463 0 obj 5463 endobj 467 0 obj <> stream xœÍ\YsÇ‘Þg¬~ÄYØS|…σ; ãrÞÞ9²‡†§p—b’Ê Ÿ#Û gùö»à>^Ÿ?‘Ê·¥ž—³“± pÕ ›ï¥›f¡CÏ<Ì߯ý.‰‘'oýbÄsWÂL*+ Ç8ؤ´Ä¢ÀöHƼôExÙ\Êfö i|o4ûö8 ˜3JÊ8 ½H*¸"®[.¢tŠtYDY”64Wó†3Fàz,¨&¯‡_FÔ‚³¡óOGÄÖpWøøÅÙ™aÛ]:;$Ï>Òg/Œí] Sl­ýW ê6-ÆÎš=|1‚´ëH·ÀJA‹Ú´,ÁóQE®|QZP—7A—ÒHH[ :w  í =ÈõxŽÄ>õ9ç¬þp OËŠ“ˆôbCܶ€õ%Ñ0r™ àiä_ä©8 ¬–¦?ͤ¥ÒÜ‹Cgd°Ô¹'ÃØì¶ˆó öPk ’a"—aíP€ I{ŒÃƒ´¨ÓôH,\ÞeØ ÎýK‘³ÕO¢ÙÄ„ö/œêîyívuV(;oÍÀü4 éh]ì /âÚaC‘ -HÞËú¤ó $â³Åµ%ÿ÷ga Ó½Ó2\T^ŽÀ¼Þ-†oÿE‘Ö"ì¸\3.¬”VžoÇÂ7ÆÂÜð$ 9öú ÷cÁBêt.8òuG¡œgþCµs]Í]& wOlgˆÐŠê$BÂ1ÞfR}[š>ɬTØóš勊—Óiÿ1-™D 9Uö% à ý]’õ?`^óتË3ù Šaœ†Æ™ëBØ ? ÉL\àYT¥÷2¥Ú ØœÝD䣶$ÑþŒô¨žÛOùÅú&-6œÂøÿ[¶¬‹Ò®tÎ"Xµ' LäÝÝDùÂÓËòU†É}ˆ/Vêâ”6Ú$ŽÎæÉÜìÛXPRXÚ2\geH¦ÛŠÐÜeÕ™•½-b™%÷n9dÃF‘ «jD:ÈößI‹jÖ ø8 A™Ußñ!jü€*‹9ûrtd"8`í‚Mb˜ò/¹µS–õë#Pf Œ-.Hnâ¡V°Ù™ê~’aœƒÔ72&MXèñÆQ==„#æ~×5Ó„g/-Ÿkä»<¨«A`Yq Z™=D !}λæ© ðÝ)>¦Ôd¤ßáÁÃ3ÑbÙרÍÒ®°ï;&ñÝÕ”yÑâƒTW¾+ûH›Ö–L“Œò/AG9—åÿç@>´ne¢¢òàqÆì&÷‡×ü\Èæ‚w÷¶G”¬LˤOY#Xã"™|÷ŸË¿Ó‰Y9WT,=ˆá>r0×/ /¿§aO ŸôD"lmº™–D¸¸X+qШ…‹·l,XRò9¢û*@’B$ÄÃÙ³òþ»"¯¬ê>-Ðj-°+ÆNHù9øÏëµðÄ-£ SV5×cïÇ‘ó©±ÓêØ†5¿ZÉe²P µIi€`·j®'¡E.u’©«À¦D2ÅVÍ“Kë÷Q¾–t­G+4IÙm×äõÜÔ‰5G†U탄+KÞ‘”Á·ûç˜2²A_•$ή¦T2m0±jîÆ<Íœ î|Ÿæ¿¦Gýz¤8ˆ³ÃÃàãÎ/ÀþH=œÆ_{©0\XÅq^Ô‚q'Sà°o‹Ô»#DÃ,X<*)é¢÷Ç•Dqá9éŠÞZ*ï¨BŠRžû¹+nÁe’ ü[&îkÂHD<Ç¥8¢[Æm%~‰›¢$ªY¶l¨‡^@85meujB¾ÈÓß|oæ‡ ÈC óɈ›€ž{¾ËŠ7øÙÙÉ7'¯vJM–bÖ°·ƒÅÂ>ðo M†Á?ytrúè«Ý›×·—'§ÿ»'§_àŸ|ýøëѧ»ÿ8ùìÑî›{†ÇµGñY¦Ù…9[:m*Â1Ðüpt ðœQ¥:×bA’RØ$Œ¿áð5  jMƒ¾ wüžrY”!cîÌ­„ÕÞÓJÙB3ø¯§¨úª¥ƒàXNP Sä5äò«‘Ùa­lEÉ›Ma®³*,#$k<]õ.|b‚~ò¦&EÎêjÒ&Oó#Æ&g⢠Ž’®`æòEï}:=»—I\ÈNò×Ùö{jí`˜íä³j¼\mxº¬öïLÁgôzF‘ù‡‚§2äÒöq)hUΑÖSV®C)Ï Ú¸ æÕ›2÷Ag}-EäôAT÷ÝŠ>JÖô‚JjŠ©UÙ ’8Ã!‚¬5ÇÞëÁø.¹•« Ü»[,ê1ZÂŽ^!¨£U5DxYÍó,Aww'ÇG£÷aˆ¹€qVÙ‰§ÐtÒ[Á‘À:s>>Ï‘ÏC^1uѼ$¼˜–É#³Å¸±‡#ȃ÷Òô£’s’€’–œôç#*<éxëìp)Œ¢`!ÓÏ×öñz2]ñ˜ÎËÔW~ ãª-–Fë23ÐÛÏM’,hw´tµmQ‘+G*Ò*ùTç9´ŒL€ŠñήÕ&Ƽ¼É ›X[k¢©4ÇÃXo‚ÊLspɸ0{2•×\ÍÖ^MZãÒ ±›b!v‹úÄIn{;Lô jrqçÖºm÷*–Ëx£LÄÓøÙÂ@“MÀ+¼Ttõ †Û~8À+<æáa³à}OÖ¯77$¥6ª?ô†$z e7ŒG_vH|ÖE<§£Yç`K΢n-¦]ó„ß±qlÆòHcãÕ2æÉmH&„±\˜ïܤ_”!Ìp‡:DvÞbwÐô¤/*œ”pi)²„àQYl§ƒ6¼ T`JU£s )­£Ì_ •RDÑ1êCÂÿÄ*%¤X>UˆÅM2”íS"M¼‰-!Âi›£>_<(98{½aÐàu°ç›‰NàEÕ=”EX 5W×i(naˆ ¦N~6¤œE“¬äA¦˜„®R1‰6ó7qɧը5ùRvµ[êÐ3y­mñC BíJóôdŪïF·€€/0ÞQÁ˜*‹~>ÅÝIÚÝÊëM,R¥%ÖþÄeÈ‹ãAr‚j4tÍÝZÆÓ,ÞUÂŒ¨üÔ0è™´&DŠ<¢fʪ4¢pZ!áÎñÙL]cÈaÚ$ÓX‰Ax²rüƒY„önrÙ"q€Õ¸"ÎõDlE’«ðû0ŒÇ“÷L…Elc¢\€¸óAÓ¾fžOÈ¢©ä:V;¯S’½0ÄFTÏ’u]£ažˆiþF£U)AlžJ›VÇ׸¬hPj; %Ù_¡Ò‡Ì¦G·N¼÷ÂLWa¬¿ÚT»H¬…'nY¶"V–Šyaå¦ÌÁû:—´n %g¸N¿|È@&2ÆY0jJHˆ­3”¿‚ÇÅV¼* ¥f* Õ3qj…VRæöm/ ^Å­3Ï`nm…k@>â`!ج…¦áÛÑ€‹j¥k êŠ4±è]é“XÖæ2ÅÊÀ5q»`Šaã}?0ŽëÈŠ!„| P²±G1¡ïå‘\D(®TTo{Baì<-<©ç€•u8™ÉÙˆØH[ËÀ»ÙÇÄF±P%‚Peóa£ìÇ@O{UluÆã¨È0›Ð)·1a`ľLÆc;Nka)ªâÿX¡A%_¿‰³í*\HÆ´P¶fµ¬b¬$ƒ¹Â‰“ÅÊQ)z—JÊC±E7˜˜÷ÊUu¨†–¨ÍÖÿÓÖp°èÆ<0Óí$UTÂ7ðz/@¨ÃÊc»H ‹y±Fã¯ÖQŒó¥[qæ5žýå7± š|åæ.æªlOðÒÃyòh kˆg—ûo…všA•&ÏÍô/ѳáŒk„R×\ÐϪ€ $QƒözyS7ÒXVA\kò­ªÉbޏË:zhXC"ÌÇR³PÄÌ!7ÇéMY4rÉÇ…‡×±»¥ŽÝa r‘}øÆ#tÇ`3Š´UÒÄ"uUøˆÓ¼T•‚½H\7ü×+ög1×UYòÒïØút³¬„ªc•ïÑ”ÕÅ›÷ ÿ<&}ü”݂߫yí1d S£µý`XÍSn[ ‰¡8²²ýR¿o‘úÎÏËœÊ!ÌLšbî=dA%>ɶb…±º€­ñšÉ;[w bk]‚1ë*ªÇ% ÅÅÙ*V*2×ñ`|š²ujãý![HËBÆY9MÍÔ ¾á!ß¼"Æ-æ>lpwAòeÙç+’…ÈWÒkͯå=Ì är_Ž QœvájßäiïÉ Ðxxä(R÷¼$§ÿ?^’Ã2G`3+‚’öÀ0J4‹"ƒH¡ÀÏ•¸Í°!$ܰ|u¬Õʬ(_šÒ¬œ»l˜ê`ÖÍÊdZs'i#|,Uˆ.Õ!‚R{[g°ik1˜ÅŒm]NÒ³8u©/V`Õ÷WO–)Ûƒ3ÏOD×äËkXTƒî‹ ê0*ËððAyxšž–‡¯ó×üWzý&?œÊÃ'ùáeo ‡û<ë­èuyg×äB±…L˜U³øn/â]Qä¢üœJÓ7¹éywÔ‰f Ø!=ûGþÙ—™Ôn¹Y˜,»DP ôDZQúö²C1™Á¹6v-*­à¤ ÷ÔªH*'TIåê]#Ã6Š*s‹(4mº7üJë"–|"N\4ÈíB¨Ô£ê0ŠU1»mæ’Y”ËqÔ¿XZ¯ª eæëêÿSëtv$[¿Ìö2ÀHìu^Ú¨?ÚДÚ6jåN4NgL¬ XA¹}³*º[µvkÝ1-)ø…J棰Ü1c,{g5g´Êu”} òc@x«:žùŠë╸‚˜™ »ÞÎÌäx}—kKË~`&ƒ•V¡çÄÕ%vrÿG^ò["•ARBÈøíY(Ý%ïˆ"1¡\&ed´ù 5Èßͨ›‰¢0QõúbVñ°kOåš¡²ÄLnɩʵڔÌYêÈIJ72æMÄ0¼ yù"d— Ë†lD° ¼øm3@@hO—î“)eI‰j£qHÓÎåê»ÍÁ4mºÍ!C܈ŸEuwŠÝCz) åY;ýSe_®+ !€×sƒÇg|Ê:¿Ô¿LÜTÅÂÔ¾ ^)8ñnï»& 3·šU­ªv« ZŠx/ïQO'ì~¦çÀéÐϳun^ÅhÐ|¡pvÀcnë°„K•áK\îH“hóžV.^äéŒø˜t3;}ˆ¯ØC†:Q&½ˆ)/Íuó÷Íhîw°¬&ø-è¶ÙiÔ¶¢Û…%¼YnºÎš"› 3!WüVÒUù,Xë´ ÃUì“5ìë4¥D¿â-<±J“S­³2¡.HÐÎÂ]+p¾4™Ofo˜Ø±z´|^1˜¢ém**Û%KvÛ“ÝNi/Æ«ðÓªàVÚW⦊¦EöÌyK¯u!sr’•L‡Ekµæ¨µ‚Ý ’tjaxC„OõT÷¥ÓØÈÌGT$(À~´wÉÔÏ]žÇÂ>gj?|%<ë1uÖ,ž•Þã¿rl~…mëóWÊ­¯x㪜 _îÂ&9/ÚÕöXò´Š¯U‰•ÓVyw½œÎ·ÌZ;ÔàìCAår•‡j—þ È}E °©˜ÿ _4DÑWÌÏ}“C¨@ºcž­D'¶¿ÖQÇçïEÅmìX÷bfuZ³ùNc',TÁ«¼Šs-²yùÛ7ø8›êCÁ~¡Æ‘À™3¥Å¿9ù´òP©endstream endobj 468 0 obj 5392 endobj 472 0 obj <> stream xœÝZmo#Ç þnäG)PìÑzçmg÷ÐH‹¤/8íAE4ý`K²ìžd9²}>ÿûóFŽv$Ù×& ŠÃÉ«yåɇ³úaÒ6bÒâ¿ðw¾9;g'«û³vòGø¿:ûáL¸“ðg¾™ü~ƒ”€–fh1™]ùÙbbå¤ëu#äd¶9ûgÕצjjÙXkU%Ý—©í‡F¶}õM­ ½3¦ús=M߃©Þâã0ôz¨¾ÆG­•Õ¬žÂØ^ ]}WË꯾GwlÌ¿f¡`_&´7mrÍAS?P÷|à–hº~2UmcÅ0ø ;صڦüXÔS#†fè»ê>5ºK”±m…¨.ðë¶4X?fŽwaö ªÛ´î~\¤Ù7õT¢`‡Zc—ú·Ô¿M8R¶näyj|¤‘÷©qI´æy©q‘ž6ÔM«ïJrl3áiõðtIÝ7©ñöÓV·`iSwæ‚ÐÚJvM§# ¨ÙöðEVÓL²ðXÂÔT©¾i5@Ed[áý¦T[ØÒÉ¢¥ºVƒÙ5àSHéðÑ 1ì<ŽnÈüeø~›Ko€°6Š5ný:¸$›Î6§Æ *®¦ @Ë"B:ÝP%ÉŒ‡a2^á Чúê3j]ÇÅð„¦wK<9‡µÃ ö÷²JU×t®Ïa‡÷õ´m¤Tvèhôš@0茤àdRÉêOuŒ÷ñeG¹~§Ý‘€iM¦ÏÃ&J3QÔý;&9ÀÁº¦Ï}H3B»ö]=´Ni(Qïvš§U/¼6c~õ§ŒFý PlgaÐcÛÞêe‚xà&+Ë®wŽf†Fˆ.¶Zá¼Fº5´ˆf/H‚ËZÚÆèVUϸ†D# qðÄVôQ`ü*­ˆº€TÄ4hb*‚ºO13¢ï‘T1FðÇ’ V Hßrµ§QE`Ï n“ §Ò­u– Óµß&s eûF˜¯ÜJ"Ú4FQ„h”ÎpÆÜ1 ý¡‡,ç]pµDÑ$(ßã€@BO{{Þzc¹t&kÚ¡¯¾¯Ò‚L‡[¿v+2‘" l‘Vñ 3(ä3sEÖÌåŽâm‚; ÃGw8©ŒcŽNK¯êhÖ& AÚØd9„fêN ê~Nø¾NÛé`abÜV)l£UÙæ™Äh'— »N ÏŠk“'³vÌã¶žtLƒ®Ða`qéU´ÜÛu:k¹‡í=¼`«á¨AyÚž”›Ô=²*Î ð3ç8ìž-s¨Æ¥”;ì=eÇS Êã“DöU ÏÂàïT ­£BÿF¥âžÇ{&hXÁ¯:ÈÅà8TÃæª• Eo‚ü%Â'E߈ÛÓäjÄ42†ÐÈ(ŤFA“J%jAG#£R}›rÜ6 É.*ø¡§#²$âsë‹U¿ÆGÀ¾ìÃ:!÷(k›ÿ‘‡a„´%ÁJïÐ6ýÐÚ6$¢BãcÂ~"jO­ÇOÁƒ“ËSF <¡2M ¶1»‘cá8p}¤ï—50ÙéHG$Ž_Õ{14…dôæ /€Vb/«BE=À¸"ÀÉÿ’Ã^‘S4G€ ñjŸ‹¾;^¶\¤ŠÙ1•Äò=‡óµ‰›çjÀ”Ûö2X9õw1€¡ gîÇÇkWÎDô?§ î©HyâõHtž¬q\,C5$4+g˜oR µ+U!˱÷QúŸIbm²,í™j$§ŸˆÊ·g³/‚bRlðÒ›dõë×ûŽQèŸ^yw¥Mç¥ÒéªÔ¸ä ×ÖIñ©Q>ÜR]ÇJͫҚ˒F—\9¤‘¸Ñ])–îøÈˆ>2ª~]®hîLŽX&³=o³X› ² ƒ¬à?äüš ÇÄU?”𴦬°åz4 ’vËPÂ'òX¾¢•Š ¼é,s¦] '¼á6oÐ{& Ò“öŸK&Y—Ræ*S¾@¢Ùï…íÖ ú-ó¶ˆOÒðbv‹1FÌU)j£l¿×€£Ë—E”cà <b%d£$¯ª}µÆj;NjC­a»Q)ˆÎ/ZÊ„·ðEž¹Áb›•Šã¢à}*tq†4X¼BNwÉÖv/rX`¦¢´wÄ,ó:M+ä²C5«{¼a1*˜ÑÅ=v9’ø(qÌGZó.XE /¾! `âE\Ú— öVÐC†iºc¯AE9}bZF3•´,”›e4t!>+ጜ,» (Õp8^Kû7¯gÐ}Ç(ê5¿ ÀÑ„4Ü>ëQ%¿­±Ï¯÷*I(TÚ6»Å`“ØÞ¥»¶sgÈ:–A‡v„àam¤'ºqÀÙñž0¯=¿÷~Át¾ ÷ 0¹'øJs<_@7>+O§ÒZ.:Ú”1§—¿ T†˜ýûu ,ˆÙ«Ä8×ñ#å×ðÞá&ñýU¤×¦LÂ(u1"^$ çu!ÑHÆdiä])#ßó§ØMl‡¥ö7Y¶Œu ¸‘8ö6‡Þs¸ª/Ò“Å‘}õƒejû*in›ž¨ÖÙ”XQþBF 'êu·¡ñMI‡ÄMY².¾ä¹/é={Ï2&wŸòæ§d¡ìuÒNaÝótèÓÛ›«Òƒ”èœ÷µó;ͱ—.ß`‡ Ù*¿Ú÷µ_köΫž“‰ÉÕ\­|Lž5n“gË´çüµ ï¿Î8j\Ž˜ÚM _’®ŒŒ+1:li€È– µD†ô8©o\ë¢d©½ tìT×%Älò¡áX =7 £±Yx™gðÛ{ÿ×AÐä—}Ì"a\^¦<£Æ¢ñ> !„·“q°òêíýl×}?š]PFÃÃڔŵÿÿ„°Ê,> L,”ÒÛ̞ÿ­4@!?$¿^sy<íäë´—„—ÜFÁp«d‰Å^xy䨉æ)ViEý^Ç{ÀÓáçTPÉBv¬Öÿ©ÿ °8ÏåÑÞ&´ãùI Ï#äÀ¾ÿ›yÂBºá)oY:Ó ˜‹3üûB^ÙŒPþë"ßÿ<†î)œ`]$ #­.%~R2=dñu„¼x2OFOÉ<-aSd°Œ×žl|ÓTü ÎOtTL ÞjÿxAˆú¹¬¦­Ù»t*þ‚‰]!¿.ð…ËÁSïuoC4=DkƲx+—éý§Iü'£2Žé( Ô22‹L{Óñãò›2¤ƒÂœË©> stream xœ½\Y“·‘ÞçYþˆ>XÝêbáè—Õµ67äCÒlØÛ±q(ŽÌ™!Erdéß;3q%P¨îJ”›U(•ç—™øn3Ob3ã¿éϧ7g¾t›çoÎæÍoà¿çgß °I<½Ù||ƒ„„+S˜ƒØœsŸ'7Öë nžßœýuëwfkwæïçÿ O(ÁŸ³ž‚…‡Î/aà'»½šœ Al»S^‡íG;¹ýãn/&­“Ûó:æ³xUi¿ý®*˜–Þ5Áu)Ã$›!.3.§À‰ïùt§'ï¶üƧ0\šIÌ~û?;|ÐY·}‚÷}PJl?ßí%ŽWZNð&šý;l­qŽn*œNl¿Úí üpÂoÿ²“Ó<X%>q¾ŠIá=ûçŒäj ¼OôÚÃ^!’-îÇ‹Ym¯âô:˜íPâ-,Á{ Kø^+WÛ7»½¶j2&Јë|½üêy¥`)&/g{”õK¹ý~§`¤Wž]{ “NJé Ó¤{íæI*úÛe%ý´³Ý~›ß—Öd(—^ÂS·íNò”Âñ—ÅH ú | ¶³š†§1NØí‹Ýžƒí›°ugåöñnïfÚí´#ç½ø ä&à§eö‹¸ týš¯ó9üWŽcœŸ´ÉÛr GÁƒ~šE?ÏÅ¿±šý$}¶íHé&£¬‘v¡\°y¯ h‘œY ?®‘2pܪ•sHTšE¦Š´>}Å0›ö®s°q½wŒNû10ÝU}_ó¬µð¬Øþ+r£„í®¼uÒd8¼>ˆßT(ÒUË•T“2L7wì8+’­înÄ‘ §Žh¸&¯€«Í<ùó$Ò"Ûd3+f‡ƒh½êiæz²“æÄa‘’¾Täõr°].Á#r˜Fçâw‰{­ò! Ÿ'š;y%'š÷` ‹Ã÷1é(:¹Ÿ«qÜùài7´oñÝàëÅ8÷%M´ÎÊi5l ™’F3͇O^Všt¢ËŒZgˆ6­ ¸¬L_˜(½Þhî˜TƯ®P§Üy7®1Ûß©5¾ïÜ”¬zq,}ÑKÙ댑ӽgS>*jŒY~üͳD F…o!SxŸù&Š|E9Ø¢]e฼…)èd9²AL6zâ·>YõŸZÁhˆïv@ò°ð¶ðëKxe°"KFg{p=Ñ>¼³¡Yg%«iž¿¬Œšö B/ü¶µQÉXøÛÉÞ˜ ޼±–©ö(ËîG7<‚w³‚pPì3qZkÿ¬}o’,… ÑÇ€-É¿Áº;}‰¦?¬[ƒ¤äÄíd%ùœÂ¶·³÷ÔØ9Z]ã¦Ô·_´Çå@8¿”†ц¼"Ð0 Q< "/(éÁ™½… ÓÈWc·1JTÑW;?,Ö½ä$B¶!ÅÂdeE‰EØ1˜!ûˆ!Ò‚´(W›P¹¼µD¤GÅöoÛr¿§‰ Ã×°p㢅ªÊêkÿ¶K‹–I.!¦je¢ºWa5Zˆ„i4vzà‡+cÜñ‚ '?Ý)t-4-‚4§æþþ0ðh5B«Íß&‘ÂP*‹Ô(ú΂¾Ã)ÇÖg !÷×Urw–ÊK`UŽÍ¯‚¯,Ú@vGÅ{•6h€«…»”ãµ×Ë_Itˆ`mÈ1ŠÆ³-Jû~U‡dÕ#¸„$éSÆ"ìTfA5b 9«–"I驊½•›øpYÛðyÓš1w¥(TŸc9Œ²_®ó\ öFÅ ÿ£â1!y@LÆÜ½–4Á]¸hDyŒ{‰É øhÚs€ªñ}zyèûd4(ÎîþβŠ$ãÁ(4æÒ”K#„¤ÓÀ ù¤rû0™—x¼ÊRulb¿Σi-L¤Wkaž6ܾL¼­Á¡›h¦åW7 |æäÊ›Pl`º=š (0š·ÛÿÇͳ@~Øb±DŠ…ÉªÅ¿â8š!¦i®Ë]°Uðÿ_å1t;¤ÞÔ÷}SÖA×å׳ƒ»ÂE_¤L‘y]."*g4¥Ï–‹ì=WåâM½øltñq¹øˆÿZN$ëŇÍ:|Lûüj´Ž·åâÅèâ]½ø¦\$»þz7Lø6˜<£Œï @ vL¬©Ð|ÿPê þ ñÜ쪛z8 þ§•¤ëºL.‹±›¨YzG:wxÄõqŸâgŒš%(ILÔ 5à0,`¯hç€`,¸M KТ!¨×ÌÛ-){öµæ¤Žç©hã2ìC|‹¦°jô¨ºž:V‹*•9ª Æ8Ú+D yV!û"ÅáŸøj6äŠ0ìôU¤ŽÖ]"ˆCò•(×Å¢?„”iÿ››…:>55Ia#EûÕ©Ä´¼2FæÇî¿E Ìì[ t×s)Œ“*ætY-H[›ó%ÒÜ`ÍËmJ) Ò÷³ó³/ξÛÀT–J„@€üFza¦Ùo´šbÕÑÇOÎ=ùÝæíë»ggþ´g~‹ÿûøŸÀO>ÝüÇÙgO6_ܳIz\‰À÷Äz¤X˜£ŒJ¥6y7l‹l#¿AúAœéCÔZáþŽy›w­ª»Fò*¥iåqPà^A…Q0ÆNÁ?y“"H²“B?å ýZ‡¨ ؘš ßkEm27yB)1ßc»‹*–—\Ô]¬ø¦‘\«¼sëE,í'…¤ÖŠdŸeörè4/ÝòeV-5¨DŠçq1 ¥oÃÀ;Î(ÙÂÚ$d0&¸«î*œÎ1Ê€sÌ|ÈÌKG¢V†¦¶™´ŒÂµ0_­p¡‘ p³˜v¯/c‡DѺ8>b»åµkZБšáEÁßsH N`–¨Ú …”+q•„GÐÍõGCèX×!šXü' Þ™”‹b¢y^²WŒAj]ϱN˜0Q² χ‰Ÿ×Ì8Ùy6-Šu(æDøØÈ^pV%%aÊ [‹÷³­U«¶–ÊTÔ¢þèh Ò‹zÈØ ®…å)y¸›Ò™c··•éûAT¢ujˆILL@i2 ]œrt7r1ᬗq_´Ù• @ö¤ÒþÛXº!Êzmãa†Sէɔ±”ÎX"w÷'ë×¥ L“¸–ÆO)mµØ«jðF–Îxg@—…&4ªuŸº<‡ø¬Ú ºEš ùa”˜F+9 ô…{þQܸ•½¯ÁÝÀÐ’øŽ¼Íû£;é]÷7`D™õF*Šb€S^f‹e-AtQl”ˆ5öÌSµ•]Ê4¶èÂY»Ùü,БÔ:jj¥ÌX<† r‘ŽÇ\:zXâOUSÇa¡ Fðƒµ^$,î¹m¡ÈYG„îñ&Ý`XPþÉÁ üëU…ê¯ë# úÅ€ wº)_Ö‘—|[láTØû{¡G)õÍÀ×GÊ?HJ¿‡0¸ä“ÕŠ4îÀEûXéõ êÕ(`^G@&Äj¶Sj'óØýD¾šeŒsìßlJP9»¹iÅøˆz4À$zÎn4Æ7£Çjð³¥."fS à*çpðE¹„Õûþ¾D‹Ÿï<Å?zû—ˆ` øgõ¦ÇÍI+Ü”RqMb®ëHnAHvX~Ç^ðbGùMÌ® åÄS”0.…uìù\| D‹q²hŠö0´Ë5ŸÚul6–¸ÞDðÛV‡Xnø3¤†£ovsogu+«þÀ°¨ &ŒJéNv S å(ÿ82ÿ(p±±Õ§å¯²*9^‡œ¯Çý[V„š¤ª–ô®'t,\ÖH€Á×|çe`¶ 8`Ö×µ°œˆ)³¶†Á0IFZdJÎw‰“YÁÑ"'4¸•g‘R&V²¯ƒ£R Ô6¶Ê¬YÉÕ‹,YƒH¤æ‹…ص¨.„ùû²ÒVÀÑa €´#X3HèÈåðl‡ §èÝ@ÄK‡0Uî¾1ò»&ÖÊ+±!r¦à[…N@%bSÁV×u.%£U¨N?Ñß>¡ˆa”ÂŽô¹Ô,ER Êp£íX½*švÃ"ý¬Þ–÷2 Ë'ÑüëÊm?* Ð.Øn¾ª±"X\d®£ºU0nЋ›p5"˪cÑ)—\¾¬üRÇtYk_6Ýf5 ß.ì*B.:CxÔ†ÍÄ%T½ØZÙ[¿‡|¿êàü™J¡¥PǺHÈðîNÂl [„Áç÷è$€»åõ3’ðÙÚª0kp±¾|¬‰Ö¿Àò±æ®]þaK‘Ë0EéQàf`žaèZfà\R"Æ)"[)¾l‚êØ{¡¹wÓ0ǘ¼”€Ô}ßT†HŸVFåQîzP²·¬‰]ߌÿe8^‡9ÒlÁ2+e‡ì"Àbg•\¿¢Mö;Ì_A AªX o]Iy÷僱©E^~»Ê”‡ów°ƒ©÷8A¨Õº9®–Ó¦1Ö³(lÉ]Dw܉ImÛPípUm71vêêÚPÐfûSkÕžrJ8HŸzûŸØä§X2T–TÇå,;ý†½òÌ'PØBqXíTê`ûªP”C|W›¢g ²¾ð¤œß_'°^ƒZã}© ì©¶¿Àf´Â(”oæ,Tw±('\Ô3#G¹¾!ßÏ©‚b`gX€ŠW¢Ó¾•è;`F@ ,Š5ð’*yÐs¤&Ó ˆÔ8 R8ã÷A4ð÷‹]éuÉAå§è êLì?ècö˜ \Lý±<®Q^½<'˜öAöæ¶}fPݰ¨TOžAlÓYÖì'Št«71yðõ€ K¤†xlÔ¾–J ¨©i¦õŒA¾?Q;ñ£%”]æ\HSÂò´JqÜiîW7EyÇÞ ÇS]ÛÕZ½Â(MZ;Ù€2—Âüå+,Æ<. %uº0ÐaòTØÍfZÈŒX|„tšyŒ]Ÿ§v@×÷ïžÚ=‹ªÛƒ Ãè:UàÍšqüÝÈb-#CJa9¡´¼UnÍÌÇUuùÜücÌQÃÞb()šü3ûÙr‚÷MU5~Ato¾Mø„a瀱&¤ä2p)ýF–”µÞœt¬J<©ßŸ§$Bi¬üàkn NÇ®r"VkÀ²1Éê¹ë3kEm9!ª<—lÌã‚w*Ä}3ÛËe4óêâ ú¦PJîÊÄþ£3¶Ö*šrÑžâmeÞN˜_°J±;ùN þë]üJëþ;Ë+ädÑ '‡%d^qñ‹½œä„%ùY]¦÷xÎEb'©ÜðƒÚéÐ:[)›S5[²`æ*ÙHd­Î^ÏÅéT²ôU]©¯¨Lܰ6¿æ²pÖË]ÓV=Ê0&Æ,bÓ7Í3 ‰j­Adïv:^5Ãó+ñeËzxÊ&Õ–ÜÔ6¡^žš2G áÂ'Dêø*Pˆ$”L‚èÀ!©8WŒÎ²¼•Î^2ýaEÇήËN¼m޽„É4·GEΜ‘¸Ák[=G6êì\×tÀ±£žÞP¼žt÷ëªÄÀY*ƒ·Cw!rWY‡” ¥ÏŸh•cñ§{ÅÜMœÖ–õ†ÑÓÁ,hJ¯jº6†ÞËo‡ÔÈð&"eïáŽâTvñÀ§R?-&%>ÛÓ=Ï´l`èÎÈ«KÙXÿöЧÒK¦äZ6jÙÛÕ×vjããÆA.ý_]WQe씣&ßT#6§`—. ¯ºö@|ôø$HåFžÙPç?å¤ov6×áœscÖ»cMc¸ëCNVú CaéìðÐ¥túª£d+;õ%é“Þ½íÃùõ¤ÞƒÑ­;¥µ'°…ÕŠòN©N˽ªœ=> &{:M¿ e‹¾8û7\xÜZendstream endobj 478 0 obj 5927 endobj 482 0 obj <> stream xœÕ][Çq~'ÿ†Õ“Î1t§¯3í·X±ƒò%æ±#È’+-’»+R”DýúTUߪzºçRk  ÕîLO_ªëúUu뻋é¨.&ü'ý÷ÙëGÿ2_ܼ}4]ü ü{óè»GŠ\¤ÿ<{}ñÛKhd<9†)¨‹ËoůÕŬ/übJ_\¾~ôÕnÙ»Ýq¯ó<›¡?óŽzZv¿ÝÛ£1ÊùÝ?íõîÉþàŽÖÚàv¿Ûà9üáw¿ßøÖ;·û×ýA—%Àû/ñ×°)6t³Þý:ÁŽþŸxo½Ë/­ÿûå¿Á„aNlÂðÍqZ`Η×ižóÞņvá ÖÀzüÅÁLÇY…?x sܽÇßâðã8MJí^áŸßà£x»û¼…8ˆ2Gç' Ò—.ýÕîS|w?®rÓØÛÕ©ŽðëÇ›_ÓÛÎtëLcãS£t^±oò³ØîY™÷mžWlü¶L³~v‡?~Èsí {¼x¶žûúð1ëq_œšÙ(¯kÃ{¶3Øp¶Š-úº6¼ÚÏǰ¸©!àzÀ×¥Ÿ÷½é¾ØðX~[¬Ÿ|__sç~nʳŸKÃs4¼D^=èù¨ Óþ'HH¢]vÏ£´9‡s³ð›Òš¶JÃ÷/?|³? ˜Ú YË+—ïAÎ`x­`úIÀoc¯~ò4Sè+,q[”Åä(äµ³ñ½:΋Np»wµMâ¾ö,Þ×î¨vŸÔg¯òd¾‰Ã:·P·yqÖEîð~ö–rßʉicÓð³1u…È×ÚµÈ:ù“òú-jçf¯w/¡å´µYv_ïJG8£ÌGð°iÊ#+MG­Í"Ë.Gk&]Ú¬¿Æ<×ßäG÷Èf²G_´Ûcõë=NÝÕäë|q*t¤Ql±‰7fµp>­O‘hl¥¥‘ÍsÄFqŽÆIN*YÏŠº`Û»€Íyï´¯â½(ýÝÖAPF¦@óC.BR–5‹rSÈ‹‚±‘<‡DŸêa–H¦«Ä&s 6©úSÜ­@ÉTÉ(»Ð,f ‰ áS ·Î›Œë¼Û;.C ²Î&54ƒ]†NaŸæ†¸¡.Ä÷u¸ç=F΋2!­1 l¶`kýcÅgwÄ‚‰ >Ì*3”JÏwlIpažóŠ5±ÇHe ¡"–fó[ñV4> ÄSÙ`fF4Þ&õh€p ËBú\÷Šý-õGòõÁ¸åèæ¢D¢¬%nïHNåãòè:ÒÙê•#v’´µö ›ò×$çr4Z³Îî¢ÇsHÄ9¯i´2~²}0ÏyÁl56¶mÀ€A/„±a˜gè×õýÀËH|Œü»ZH‘õ$ö öx8þOø9Hµ÷}«¬0ƒžî1m£ qIÞI%;û¾’dXNIÌ÷ÌŽÐC´© c¥ÑŸµ“¯ÖÝÃÞêóÌUUt”pÖMÈ‚Sf5앙Ŭ]Œªl»V.È¡+í‚ÜzܪÏqZ°YʬUºÛÄ`Ÿ¿¨¢¹gösâžáEâzú¤öÄ x¬âO‹yú-IS$™§®Ub^ ky[ÙzhœØN°/³Ìûd~É_ç!®3™ÊÒÔÄÔù«úKÒ_ž}—T/'…¼ü7)‹>¼¡ÕZvpzLv˜DutV°ói‰yH³µL'œ,T7w†h3‡ w(!è0g‰9Çx·ÈFzž­íEc§ª£¸H{€žÈ„Ñq߉~VõDr'Ÿ'†Ð»Ï€²ÓŒ¿}Z¾ø¬üÆVH¹™ÁyÆX+¤“ôÁÒ†-s™†#•Û«U*»ˆËDFíÌì#À Å_ñ-RḬ̀P0"ÍV0¹Á?Ÿµò©U_Þp•}|Îg¨š'ŒÒatˆ‚ËØ=/Zp+¹³^DA]ï%xÒ$Á9ºÁ?7xi2a¸“~RãÁ6Ú6 ½Ö"=b£0"]%‰XŽË¦L•aÀK6zÃõË vŠ+ÿ5Ö—Lã fm‘HÚM1+n¢â1DuÉ(a„§P¸Öø¾†?\ ¸éˆT’†C0ŒMôj¦#ˆx‰†1Ï¢£j ¼®ôÒºo:§ó\sÓ³úìºç£! ­'>|* ‡Z"B=ð>,¾uº£4jXÃK¦Õ³‹øŠ=ÇÈÀÍ’×ïê0Å ²ÌœXY)aa²n,.øzÖ M²ž¯:%€â#â&s9·5? sj"&Ðú=§y_À :K …ÕÀ$^²‡ °çóÊKö*Ãðž…@¸ÐYä[-”‰œ°B5ì—Éãüj¬êhÅ’0X©»ède¤í¸¯²–ël”›µ’g‚™jfA 3*›v{rßóžxõÙˆvÐ`Ìúp K{p¤¶ð$´† $Œ'ÊÔ JÐà5±[è2{Þ¨ç^ ££½#Dædœ®ýFœ^ÆrÂð«8¿°,èÞho1&K®Äljö÷ðç2ëòþójùO˜•[Ü£‰öð‹º¤Ul€Â}™b0B¡Ä>,C‘|‹e1%hQ‚êÒ)îƒ-…t Ï©°ûØ>ôŒ•Лh††’H4÷#@.¿~' ´Ü}j»¡¶Ã¯þDªI+VwOøn÷uOªÉéÓå¦ FKÂdyiq7bRë’·Èxª1 ‹7Nkž‘]×@%òØØø ÑA=£v\ÇA7íU¸ê®¡`LØܰÓ0u±½GD'£(]Ö)>ïw %OâYtï ,Õ6KJrÐòÎv±6/Æ…ÂD½¬^ËuæqãF3Œ²½BGú!‘Éežtº1†ë‚/“b2Š;€L`kØ0©“òÅýOnÓ¥à<]ƒµËÐQÔìÎÁÀ !XôijüãÜy]‘ë×ñÌâÉ*2Á¡Pk$ÉM\ÕÒç£ï¿ëÌ¡ûQŽDÝ`øÀøœË$ui­£…8»'ªïòõ£@Éõ)è°‡ÎÒÝv™µ*|f”˜x•.60j;K›’A,Ò§o~Á4è,Sd)X"RIp¥•‘áóÙ úŒOÌ絎4OÓ,9Ù(b˜¶S2”2ЃéÂuôFo;zèîm Ö\c'°sLØ|€­@·KÏäŽ6Øf}ƒé“KDámÄÅ™v¸âɰ0é °”š>%‘Yf&2[~Ö's ƒínÏä®ýV”‘_UF-2ð‚ùX”ðô'BàþVÈì(ô¼°…KpŸ³ä«pã(ä?\€b³‹x”èC$ä!Æ@HL¬§ABL1MK$ØýÊŽ§¨Æ‚AâŒÔ]†óæ&Eqˆ¨ ÕNhT à]£-“Άh3N)ᕵa&B‘^pDsF"Ó)µÍŹª&Âá>2u`TÞH§¦£›[Á‰ÛŽäþ„=;òNQ!Æó@ï‹#7>Ü„÷¥‘gºbû£L<ŸT‹³„,Ë@DP›r1¬+Ž& ®d4sc\W6Jr2)ªeð… †/*¯žÁËÙ°˜H[…ºòT¶%ú߇ÂOþã,ã包™Ôß•Ù(8)¯y=Ão§Ö_¿‘yÁà‰ݲf™¬Ž…CW±§ŠÇJÃ&i³KE¤Ÿ˜\ƒÜx•¹ü=æBfÊ âe A-†n©CÂSHmHC~°GC_Þ€ ›JÛÔëáI1Ì_ïË ¥vÏ‹–À˜»ÏT Mëº3(,+™Ý„iݰbeg|¤âs‘Êô‹JgØÄjÒ«³ˆs¿ïìÝÂ/6õÓE*)zNBü‚ïbôæBp­Úö§ËFa´jµÆh1($ÂZ&s>›…† i¬tËÚ•B¡Ê)i߆Â$u†V¯(ùy‹Ñ¢àm8¡F¿¡ÝCÍ)°aQK§L‡ü#UÊîæî_•ºÓ„]»œÎ—œãÛ‡h¿Î)e ӆܼM%½ŽXPÑ[Áã9u­1Ôå~ŽÁô-Hæ1 #V£.¦Qj¤Ý {·/Ua,7€ã2}=¤7ëÀ =ì6¹lÇ_ÁÏ1ç²`ÉlV¼É €XÔ,z.V£a[vÿ]…ƒôsŠÏP÷[ª.ɺŠ^]ïÓÿBú.A[×$»Põ1ßLÉ*Xå—™h÷ Õ0G­–’‰T:Pþ´ïN±(aÍ‚”ô˜„ÓÏ\¬Ëå[V¥cÚ.2n¿L5HµœöU"¢8J¡¤JUØ…3Ü~¶âf60ø¬“1±1®;'c‚ZT¡&ü‰ªÈ­:#â¢Ù2n‰ÞÈcD5rEËŠEÕ4%úA]lSRÍ­e§¨ 5Š^0Å2s“Sì «àÀ¬;÷ÿ3èÏìN6í°0Š ü-…â“–YM®x#¥¤Íù¤ŠIOmõB餂½ae2ýÙ”¤F.Å<ðÜl(YÆ¿V+åu„ÌYbí6·ªßhsɲÆ2»ãÙ®r”ÎòÁ†5ËŠrù ‰ª¼¯³î s‰üÏ; ï"àZqI9]ýÔ¨®À ²^FÏdWÀ=ˆÎ_~›Évµ…ü¢ò’Ià† 7QC$¯ª³Jì‡ nóKVƒÿ¥Àó ÚÕšÌ( ÿ‘mŽÑÚš‹¦T¬ïŽ×(Ï„ÌÌVG?ñ†çìõzè¼Õþ³ÛÒŸ•Ô$Qä½±×k¿•»\6ujÃXø¿¾ b'dz0ä–¿H铦äõ¨¸ò¤ÜâiH´*¤Ó(>ë<ÑGkž÷ëä9®ªÏÁ ˳zYSLËÃ@\ UBJY»ï(^ù'0ŠpY«X"¦¨4Û8¦&×Dò!›PìTÜ9:°…WK]EÆ”¶ÍSæ« 5Z›åÊw.õDyÓ©’©öƒìË“:ÄB˹éíã»8&™ýÒì Yý¼ò¹zLë4z¢fÏÉçU•¡ÆÓMåÞv3ã,ÔaÎ×$/s*‹Üƒp¾5ò|ÒŽs‰>œ9· „2ýs1!u[9?lÒæü’Ør_%ñxf{ÊÛÞl_6Nlø¾ÌœtqªlAs3œ6;Ï—FDr†{P $ÆKèì„sG³¾ëŽ5µ/èµ5iDiM*ÐUù®©¨a°W­yýÇ]u·šÐ·lþu2ÖnP\U{ô<¯¢"z˶¸¿ÕNT˜'µS<ì0 ü3O Išãy™ÕÆyMJÊÐVæƒ †"P±Ððñm<6tÿXè³*3MÚ~LÂ>r(ögu°k¥:úÇu£Û>föA˜ù°ŠgXzñ4óèNy|½(%â%*VØRb$‡´]§u}æX2â°£xHwŽåê‡&eAç½}çH¿\Ä)…¹˜ƒÙwÝ0çÄ¡a<…‘ žÂ.V/U'`ƒxÇÆƒRB䔊·A™5g”â–÷Ã\!Ÿ6á¬ø?×zÌfä,Õóóª)häQªÇGýɃÊ%=gðMÖ.M„eȲt¬Ó/Z¨ãʸ@I‰cÇ(éªO¤©·dÖÆèy"üE¦=Oñ—ßï鼂Èwnf8ãtl*‚aHý¯÷ìÚ™^ï,q·mH€ÓAÇÓ¨jÎ>SÛ˜ü±¨kSSÖ}ÏjæÀla7qÞûœóâ<ÆÈ1‹£Ù5„Y¶O °ÒJ^!’ίˆ4oNÓú¥~žÅ:F•oêcD‘ÚöÁe \…¦£_ìØ ~ʾ«L™²M.¦ÑÅ<#´Ö!Þ{tJ"ê¥Zƒ®°?xÛSX„8#æðqyó):x¢l™è>NK¤ídž˜~Š’™d8½éYur ü£;È@>®Ç !£6åcÊŒƒ;Š IªùÑ×î6²°@O¬¶tHMÄÅKωŠÄyPFÍ´.Œ£r×QĘn’;+jSÕF>"¹¹!§ »§ IôÏÐ1l‘—0Ô#Õ_îòaìîoØ] d~¤ýu,©øçã0ÕÜÎåš«'•˜=!\+Þæ1+å *Kí¨VÖÆ;ÏDDk ‹h;y,Sµý¸}lºñŠ=¦Г#t’ÐFm—|GQ5Å6‹Åªâ(govWRídV º–ª¨^ŹaŒÕ|½šKP!í ×Ogžÿʬ)ìsÄ °<+–µÔ¥½“8羪ýŒÅÌÓ/°šd £™jг޳üª‘ñÍlñqÞ -!Ž:—Ïí¹¤1f —X²¦µ–($Ý{/2 “Ž S7L™“¾ 2k‰Y„š°ßÐ\§^Æ×1“”†UýHãq…÷$¶iŸ‡;äÂà–®<4‘,2ÓñüýËÎïóÅ0Y\~Ükôãç@)Ã.JÙéÝðµNÐg«œÉ.Îêq·5áù¢Aâ²II§Åª…€ sN<†ÎMb¬~ò¾£ŒçeãV½,Ø[X?(Ekœ—\ïú:šïža9mÂQ‰øÓaÈó-øÇšèTç”i»(Ú—¦ª€ <¼²v+Ÿ±¹Â)éÈ6í‚U жÛv j̼y˜p°[é~ñaéÿ•[ÜÒ¯Uk^ïží]ùŠg`ê%…äŸ q6!‘.ƒ‹+*ºÌC˜)Vׯ®²h¯  €&Y:oj 7Æ|Òj½äâRô%±’t« d ‹¯…E5OW›¥3•*YÓÕ³•‰Ø½0Mp÷jåŽâmLÝL“õ™N‡cÛÈÈm:|µp\¢S-"P|Ne¿U‚å$;øñI…¦»Yõüˆ ‹;¾*Mª@°{14Vð¯Þ»zC‹xú÷A&i§’/kO©©É¤“RêÁØ%R ²“ÿ`çq n#º'c²~܈LºXuÿ0]c{*5WxâÖ!ƒéVt—u-©|ŸuœW^æprC¡»¤Ég½Y¸Eš\êÒµE¡Ë–ŽA9/ªƒçû_»7XkÛÞ ¼ng<v º;àÔ¯;q±›ŠßíóMÎoËëûrUq½–ø¶>—,»t2#>x_[Õ»–¿)óÙäNÅ«X^og!¸ „ix1é2!'/F|›—sÞü蛽–½9²>ÙÃ7ùaFÞ}½ÿ© 185ýÿd0ÊÕºéwÂ@$•›ÑE=9t±9]š~WÚ\õ&É6ë¶<¼‰ûR¯#¿«­¶—r]·€ØÈþŸóúRòtæX…*JgŒÁäQ¨ÚTã¡6°ñb­îY4Y”&ÏÄÃGSéÑ`cÆÔo:¦2;¦ÉjÁxd†À„VC°Å6ðy,D#x±æ8T—‹±Ð•TðœeœÇ¹*ñR©R;ÚA Ž€µ<_<–Óê%N³?x7ç2VÚVSâ:4þO'hŽxO÷š£ëꬼ ŒOŒ;•±“úõû›rÞ é!ý½•“Ôx…7RH˜Ùµ)˜ÌS°Vxe™ ç€iÆŽ᳊Mf!j.Ó´nó–cb=yh¯‰Þßb"üã§ÍF^kuȆòénÚȶ.º_ ÂåûQÑÖÀmÝö_‘éˆh×”T›…¼Æøfáeas¾GòÄ5wÈ…Ös Zëþo'Ê$Õ‰ìñç ×°cT‰TÒ¶Ó}š.âw—þþù_rˆhendstream endobj 483 0 obj 5846 endobj 487 0 obj <> stream xœÍ][“\·q~gô#˜'Τ¸'wÀU~ˆd+vʉ‹©8e¹*K-E²DrW¢h“©üøt7nÛÌ,©¤b•Åá9ÐøúÞ€~x¸oâáŽÿ¤?¿}ýàïÿà>û`øðÿç~x ¨ÁÃôÇ·¯~þ O¶°ñðÉwboñÐɇÖë ^>yýàO4øÿ??ù'è¡ï!w½ žÜ@Ã/ŽWjs.qøÍQl!xÿp”‡ß¯Ä¦µqòð¤¶ùu|ª´?üž*–¾µÁs)Ã&›&,#ŽCàÀÿßùÕQoÞmù‹_Asi6±û×Gìè¬;üßû ”8üîx%±½Òrƒ/Ñ@8醯Öçè¥ÂáÄáëã•NøÃå¶ïf‰=žbRxG}ÿx”‘\-¯½®`­N„Éöêx¥µ‡Îæp Ëÿþj̦¤Ä©i£¶Þ¼„¯ÁÔÕáMœæpÚÝÖ×ß `¢ÐùÆú Öཅ9>£çÖ÷•›±¾œz•îµCýUZ=ƒžÖo†~æÏœ™Ì¨$ÆtNØ,|¤Ë[¹ ‚‡‚ ßáBùÍÁl»^0$È¡³lÝãf¾ÂÁÿm/r"´¥³sîx3™è–ßÃd‚ǘà#Ý¢ÚóbWs0&@x§i!B‹Lnå+Â4ýÍnÞ HÔ–ÔÝôöjU)F†ÍC¦=°»¾Œa3î3´ï™#OÞ,—‘ý&!dR§ŠÒzU…ªâ2»em‰‹ø)M̉À®öe³~YÕ$SµJî´RЇ¢„ܱo*î`LWR‘€c(»]ÐK40ËK©X/x{~4-—h48°¤Ñ ü¤Oσ½ãL’ºåÅ‘Hc%ÿÄ]…ùuË©‡Íœn’0Ù3•‰5"µze’ñÅ$¾lŒ8k=3uV‚„¾ÍนqÝgµ÷›V$&\*™ ¬Êçÿ« (Ë^' ‚@hjʪÌ1`Ù¾HÚËòù–‘§úM<Í4À`Ðæ0$kÕi”¹J4*$¿B[\]¨ɈÚ=|)3 )Ú6ZÜÙ5X”$ø‡Æ2‹vÐì¯Õ"ª Ô¨ÂÈ#ÆwYöXÖô66 ÞLU°73=¶B Wy€Ùv.¢22ó6ÑЊjÕF'¢™|©\ó®š`¬i#aªÉƒ¬i…™9¢‡{2š'È"w"LËtâla“å1pãÁ¢e•ü9kæîÑõT |8zíšÇYƒû,â/±>x. ç¿9‚0RB 7W?as» æv×’u’òK$2ÒÒçf’‚;¤M\ØŠŸÁW‰^€,¿žàñY}Újí,êqyàÏŠÝå}mþžh(‚’àh5Á½o-¢8G¿¶ËI'µjä:‘Õë›iXš wC\jDö¹«lÑÉÑÖØ›±ÇsÜ>I¢ŠÁ ¾§À[I&R”e‚¶±3®ô:ÎÇy”þ"ÿx3ÇΦ™õ5X¼Ö¬9BI:°pqç ¥y é~F­Güäý&uf¨7iÕjn)A¯w3+%àL‚í“üiä$ˆG 8wS[4·—²…’L•;ýi²‹Ö5—C8†‘¸ù¤?Ù(© T=çÖ†/#/E"¶z)Ó9@.õ{±~£€• ŽæðG Ȱî_bOO4Þc Ñr¥G·©±ôÐ ð–ÀuתŽÎ¯™bˆ«æ(6¥õDÒ€¼@%ˆ%Zy¢l ÓôÝ€ËV«  ÂI«Þ›Óµ ëÄQeÅw©¿‘äEÈ{ûÜ·Ùwò b܉ûFqS§ 7¶2oàw‰¢™FÎSŒspŒCIX(oz7ïe6FÒ¶ïX CŽ;ŠÔî3´~}" 0¸Ô$éý…øOko•ÉÝ`saÈk¦6+hðû£{Þ×x:‘o–*$[sžŽ"l)~ døòLç¼iá`Ú1ù^=ÊÌ:¯Ñïïˆ;FdË‚ÔÌûÎŒõQ Êkßd= ‘÷*Ë&œY¤qdçg(uÂ!þkÏÿÂ`·¨=ü¦ëΤ†ñõ.<O”M_Ö‡¯ËÃgõá›òðí¬Ïmyø¦>¼.1É‚cWðiæ–û⡟"„hÚ ß|?›ç«Úéiyÿ¡¾ÿ‰w2r‡ßŽŒˆôþÇá'†¬A ·˜ ´0Õï<ù»Ë·îDzz²u›ìY¥L»+ñpwÕÿ“ÝýŽ?»_Ï6âålÏë˜uóokË—³)ý4Û|6üóº£WQ/ Ò,úÅ&¨˜;½lVÏÚꀱ‚ð @ºJSiÍ\%íÙËOHâø‚ðô¶€êe•)‹'ñ €Lôì-ž|ú×È•€´à1Ìc‚~*nêC˜™¶Ù/êûgé}è&œßËúþ=ñêÙfogŸ©èûqŠ”’ÆU>oæ^w—¤Õf] ¤Þq.²cÀà7}èF1*^_–ÿ¶ò¤<Ä$âÐÜb<Ê>÷j¶àÇu+i¿Ÿ1á]}8•ÕSÆ®;󗆲u»²€>‡YŸúá'’{¯c=± ù+©í³JªÓ¿®moà{7äá…E»¶Óú,áÛ†r¥Û)2ñôµ›šl<ýMrØIrâÛì|cÞÇxB¯JçÈF¹îÌígvÖÕDnxî>.Ã7¾t–ž1ojÓ3 œ´t×ÓûùD&øà`•!~‰?=ï?óWGEn¡Äð‚ôŠLTVSpMÝ{£•QûEŠ'š`¢\ƒ.ÛÂv€< ×¹hÒš> R½çm*ÿ›#~B€ËjÚ/º<©ùócËs÷§.Ó£Œ²;2ß¿¶©CPª!ö‹6:pc°.æ~< rÍu4f[Ÿ@sµ¦õߥ Y:ò(£Š™÷!Ï𑉾¨¹^þ5­‡L啸”U;²h'YK•/,@ưÝ刌Jõ ’qš0jJ ¼eâ|àÐØ0)!UÊËŠÛ6WBMaHÞX=‘yÈMÒ”›m¸`?[gÓ`ç%c,&{Mßšf6ÛpVLù>%:‰ÌyLŽ[ÿ+1oÜâ¯)Ú–|QšPA¸´³§ñïyM Z‰yŠÕΡ ¸ô%+™ÆwÂN%Š8ÃÇ)¨ £:|†sÙMú„ ïªì~:͵ þÀ><+I‰p]#°VYyS4“™€?g¼‘ Š þT¡Ç?¡ÕcïFðL¢‹DÔÊF‡×ÑÊßZGg ó"¿ ÿZ^” ëR¦ÖW£E¬f29—õܱüCNá£ÔW”‰øwh jίëÄP˜&¯9+ÞšTãv¢Û8 Z´¹C4:+š§J8â9ÊgÁ‹è‡]D1ʪßYY2cþ¯Jű²Å;•̧¼'‚Œ!d+¨ç)ƒIƒˆg¼U†¨ ó¾:»´º"æ 7ù^´¶V›…¡æ'²4†[Þ-Ç•Âd¤QË;µ|l*¤™œC¨£œsšüÓ$@Ø3‡†93<·å¯S½¸gÍ;eSÀô—}ʨK‚àGßšÙlSsf"nvbómD6||uuQU'e8Ãá›kƒ11ŠÀŽPÀÖp6ÈXô¼ÕȆÑÞ[£÷rËu÷Ú€¼¿«@³‘‹ž'\ÒÏz±`îûDÛwQ¯>ÏÙYDœ>6>–ÜW ²ÂÛ²a±8¹ÃI.ê2h¾gI†î\Ýk{«zvÐdRìrÛ²ì+^^?”C­ øåZtßMšk¿ä'EÁbµ™¢êã\¥Æ¦FÁ63©µ£Ž¥¾-›`˜\•¾Ž±ÐWÑ›×,a¿\ý‰o­Å%ÌŽÅ_MERO9:³5­Í|Å~Å‚2!úr $eÓjê`ä¬QwcryjfÖ G1Úòç›VÕ$jž¨'Ël“\B\¯jÊ¢ìýük`!ôA˜KĽðLLÞ¥†QX)ãÔƒblz[ŽD%t²9›;?ó0°ñά¼azÄ­zÀ’YäªfQÒG¯mZ›cn±Tot:°3Æ›."w**¥ÐX4öšsR¦à¼µÙ„êpL£–>øDô”ùœöœFú¯pÓ¼#_§–ÕuÏnD„Ùî¨rö¨y/pãÕiEWfæø™ †‡Yý§š‡2²+¯l#¤…GÿFS耮EHeoµz#W"íV¥u×­êMÎ4KWê&ÁhöwŸ™ÁÞÙ>@ñ{ ªZ¡²ò»ö@žvÕr®^µ!îÅQµI™[+qY!tsôÐÛûFã!X;I~d8‡ˆ»² (õ5†ãˆÕÑ¿œýœ¸ #OÅ3'ÑyS#ÏsËÚ,Ó2®¦ZÄ{À(ô;'0¹°¬9+êx8öPtkEØ{z&м\”Q@±q’r¥®áíÂÄß³tXÞ‘*«¿m€>U&3uËÎV% ºcûVhÒ—HIªêÕg V4£wƒfô$â–jÂÛ΋í•ñ‹!Lˆ3 ¥çÒeRöQo¸Íɾ6ûdöîròL ß‘gýL¹ŽsäjöOÿfê²3 ‘`È(ºT=L¬f 0«Nm ‡‡Ó ùlñL©¥C  d÷Ýd­¦9þ[3³;ç‰Écw‚fÍŽå 4íŽwŽ'•˜Ä®0¬Ú¡[LÛ$‹¦°¢Ñ=fZt Î Ê*ª@ÑYhQ9*¾­¥,ßYÉU,²XcˆåXÿÿhú)ÖC6=Ô¼†OEN  y¹_â–çåKr_fÞ Æ‰ßVÌ ·g÷T;ÏM„|†u~Àéiéÿ•„lçÊ@XåJÇò#œ-Îeû€:˜ícHãçË^òþ&õߤªrtÜaþ]EÏUt&î_@>¬oŠP-4\ÄìR]EŽ¥Ûä8S¢óÀ¹ñäV“gÿ¾ž+ŒkN%VòÑÌe«½› —è7'[b#W‹¯ ¡W²œÆ7}‚eyz%}ì’L m­ò/‰câ1:B€&Ëôðíšß¦£q³»c'O_O|ç7½(ˆÇ›xq=ˆ9¬à·…‹Þ·Ý—Ýy-w§wìƒ×Ú°Êþ¤_¡¹múw8AØ}¼CjkãÃæý•r@›J0aŠñå/¼¢_¨PŸÅ–tÉ€?ÙWjÎtyöͺ]‡c£`pbUlB¡hx¿(ˆU`Dëñ‹É'zÄl`»Ê¦iîþ²Lˆ=| Šl¦<¥<¾ÆKˆ ¥B÷ Z¡¤£zè<ÔÛ#&; c-™`Ë/Õc½Ïô2ÍHœ^qò3½¡ö¼«xáQ>i“LTf>Lj·-â’`‡zõǪy¢‹Y¹;㣉oA“ݳ:±¥EŒuÖ¦nÌÇXC[rÖâq¥Ö#ßc4h~<­5™£×hÔD ’ñdzm»o‹z^§l¢øY<Ír 87Ȥ•‰Ý.ÕÇïbQ‹€0+±Do_¨¥: v’§ÿÇŠjdý%‰‘H™V;°Z¬IL§XMG¡9ÿeO4±Ôh]òxrVß sÉ9HЧ‰ñ™5½¾˜)„æ «*ö,#3¤ßñ‘²‡ÙT Û²:#|;la&ó‰Â.ž-T1¤zÏ:hô¾Œ;|‘Â1®V£|lîžjj1TÒ+ÓgÂWl!ב»Ð³†“(•²]l…KLC²míJ¹V—µD‚´¬1½„`bGÑYýpÊ—ŸèÐ ‚] ÁR‰éEð²d7;š÷ÈÏðkx\æOW@t9w«Û§ŒÝeÛ“¿é¶£‰ÑFál¯&F“æã˜¦¿£Bš•iî4»ö%R32„a¾DçÒ‘ÕáÂo dvGlô|,3ëó±{xP…¥Ê›d”~šk ¶>lžo, Óp<ÏH¬ï/J$iC07úœ]W‹¨ÞMæÒ)B—^\h4Mà]¢MfU+9—èM¾/eª~j~íÔ‰äQKÅä$Ž¿Ž_ž,Ë\ÿfv hÛ3_åXóãiF¡½Ö%oç.+¦Ï%ës ÁÎjŠr5Ù2º «PuÆuÃIPå¶“ þ÷Ò×9?~A”2ßÛµ¬Äb7š 5XaиºT8Ë’€“:Äì9ìšb#'JIyö µÍãÚëÎÁBRN&„‹ªÛ9pötëǶ:£AeÅv-wÃýó¾4u»ÈÑ^x0ƒ<³±÷H_¿ŽnL›l‹V~v/j­ Sê Ïl´)Ì&VÓy²á†Û*ǵ„@÷¾~äèˆ&Y3}éâ æeL•7gÞ§ðñU¢P›çýø›‡ÚS"ù’A¦FÊ Ñ“2/vÍ×ôžŠliØl—äèìúÞ•lÓÅ~â9Óä^9 h7®ŒÁtkÔ§9ù—Ú<¹}¾Säïç¥ËÉé‹VèMý*f<4Kc–é4lÛG²¿ðä“] 뜻¬«†Š%ãÕRÌRåú‚¬Fp&õwy9pLåciº•uEã‡d¯/†<‘`᥌lnµòpwsÓ®‹¯¡ ý"-×Nê>Îó ;bºÃŒ­uryiEŽŸ/ù;½?鹉NÉp5ú%ˆ½rS@6êÄRóöµŠJü<§¨„ ST——84¿J^xÙ¤—\i™ª.¯'FY"P«n¦ØdwuåŠÈARÚ¬«éM'OÎ0@S2oAµ¶3þ¦·‚±$TeçZÚqêá”õÅòSy ñtßçÔgý×)—>~›UŸŽ÷Ö¯°žî…Déâˆñr틘12ˆdöX,À’r]ÊzÚ«f/ªê)×nÚÑäY3’~©²=›_;¾?Ÿªêx9ò2«ªù%5'È!Áî]^—ÕÊãÔPm”AïÃ5‘Ë{WgÛNšx-§Ìú·¸Ø!±Óƾu(3Šüߤ7D ÈÞìfÈûf5ªã"FNá¤Õ‘º-Ÿ”àŠBûØ$íØÚëvtš8OœÕÞ_Ÿ©Ò2ÉêþúdÛ|Ô õ³',Ö‰¿î„ŨR5ÒÚûiö™Mìf\;ÿŸNx{“xøoó ª 9ùäm[òþtæ•°Ð?Ju‚§> stream xœí]YÇu~§ ä/Ìï x/»öj~° ÙNÄN4AX4ÒP#ËP åH¿>çÔzNuUwßáˆO†@ð²—ªêSgùÎVúöj:‹« ÿKùæÉ‹ÿrWwß?™®þîž|ûD„®Ò__¾¹úÝ5<¤\9ÏÓ,®®¿zßWN^Y¯ÏB^]¿yò׃?šÃù(ÏÎ9uÐá'ç糜üáÏÇ“:K)­=ü÷Q®ñŸÎ‹Iþr<‰³ÖÆÉrGÁ=§8âß֘ÿà3Þϳ9üþœg¯çÃ'ø(¼«æÃÀ›¿…?ÿ¯X«­ 7µ„›òð?G ãø<ñIœNi/Áûþ<{¶<²ölž5­Å{E.þÞ—ö,=¬"_+Ã[:Ðÿ6Íbr‡O'÷5|_¤Œ›g1žI˜³,ôqÖÑ'>eáð »þWØ>Ø!²}pý<¹¶ðú6mÛ|4øä)ß:©éìÄ<Ç'Èn}}”îl´³‡÷qÍÆˆÃ÷81^øÃs¸*ayR¾É¬ðÕñ¤gwÖf>üKöÞJ•O~‰÷'@ÖwÞÖÛïâO;•9ñêð’F><­×^ç·_ÂŽk-¤ÌãàË7ðo€:À Îê2+<Wå”:܇‹‡ß×Mh‰ö‹lÙ:² ÆÕ¹³Ö,Ÿ”¨ä¬<ü:]‹»£=݉äÓys¾Â™¦I–<ìôº\|Y/Šrñ\/²×Ó¯êíï{ïÜ•‹?׋ŸÊÕýK’ƒ%áO­<}ÿ‡£I1S S™ôX~÷øXh66S*n¢™æÌZØ12Â$4¨"­lÚ\/ÅR‚fÐ'ysñê§u$ò@Ù\}ø{+îóltbCö+—r°Â«“P°êIÆU)",ÿeáß{δïê3ßÁ*ÎJÙIv'<?µB©‡Ï3 ®ËŠ úûiœ*YÐAù”ïà­ŸËÏ`V3sùuÆÔ š6°·ôb£” «/+…w¤?OB«D Ü”ê×8˜?Ka·uˆžà½‚'%,OôF™uÍpzÙ¡YTO•f¸ùö~.¼ú,-–ñpÝ(-5È ¶Zϲ¬xï¼ë½ý¶rmeÊtQ:Ï¡ ’ûU|Ðj[`où8’"›7Hû8]å¹Uã.)º|üIJ° C‰ŽAˆÌì#9‘ˆ %#ã•/ÃcÕö¨Ây)].?~‚¯´€@aÝRÍou$©Îòap¿ÓCÛ§¤ ¶ï¾~ç "ôÜ"ä€9ÖYôyÄ!¶–HÂ=^5JàÊÅd’b î›EPÙƒHKaéˆuÁý74Ê# û¿ãiBMáfÛÖ¼;…H Ä4f!©S×Ñ¿Ã) ŠÍPÃDÊ‹°ï‘³á–InB¡©‚„Û,¬IÁâò`ÈÍIŒ¥Œ}W%Û‰OàþÙ:Y%cI%.®„`gfnµNè)–$sŠÆFúц)õû%Dš$(Û ™sa{p`9 •[¤úèGøJç•'׈’Ë:}Òcz:ýWÇ I öo9R“jÃj}`H$³ï2 7³¨Vµñ­þ½áÿDÝàñChüºjÐOqvDåzC^”Í.ÓM)œUkfDà'š}{†| `R%³Ð0SBmh"·¸20 3$á;TÆýWPØõÛÀ®b¿ë}‡åkE’ÊÍÂ66 ·W²ìÀ4a^˜4k¡†P2n¢$nÏ'$µÎA[$Gm÷udÔYNFéeâˆàž£­›|«›HLÔ‹Á·²ñëžY/œ2ÚÀ! +ÒÔd í9Zwá%ÂÈÄÍùËÑ["oÑP0'?Ò«‡döé­q ´32•à ÉÕû£ Ž‚¤²AJ¿+Li ¤܈r²Ð$„ážÁ©GD$  Œ“"‹>ýÅ€ö[L_‰Wm¥Á‘©…MÉœŒ[ ÐþŠ^ʪ!Ü¿P’ [† uP!\„¢@$*pVÈÉáÚ¸B äʺø'\™ ~Âʦ ÷ñv}ÏÐ[¤w|CËKøá„YG)ŨÄ4£oâž"@"9Ä6¼]Ȱ#‚fkð{X\'Ó_0E=™ƒ¹k³0Ÿ ÑÅý·cç)H¿ìë{ò5÷êïk•Àýp£Ú2Å–‘Êf¼1RsDû…/ï+ãžKáÒbŽ(ÛßWé&<Б±ŽyW–š÷ ÂLû©ŠmäýHn Æþiõ)â~É-üyò §a¤Œ˜ôátÒo ®ð[lñ`‘¬Û4†ò̰4¶çR<´å_'Õ¸É5NÚpMxÛI"$ð »p™ï…(¢ò~ÇìÏÅíØÖGZi`B7–ÍD‚§•Û_w€ýËFc#C2Y€i0¼MØ7YGgh` u ø&mê½5W#ãQ´?‡R_ô–K°ó=Å–^:M·É©¬ÒÁÆÞ¸æ›8B!5ÒÂ4 •á¬n³>"Ïg`ÀóA× ØËsK®[>Ð7fìউ7pÏÛVÃ$Y ”²baÜ‘<ÕºG'ÞKtë¼{N©ÂáÚaà^)Yêmú°kÌï90Äýªl^­Ñ«àº:WQ¿¶}AªïTµœ\ $7"§)–޾gÑ^A…Ñ›£§H8–i6‹u‘\ cP¡C dÝ:!e¦¹àB•ŒCÌÄÚtšÍœg~ž¢K,®Óðõ5è0d6ÄôÄN1¯«©‚Z(÷´'#cD‚QˆM¦Ÿ@E4æ,Ø/I`x5fÞu“–þ[Ô„ÜÒd ¯ƒäÏ€åêC"›ô ÖÌJ“Ø=âø$ è$Eß8–-ôøF£IÉë–ºém¨ªD+Û¶ py;“O›eôž„Á'؈(øÞ±]&: q> ç}À³|ï2°G3°Ñ˜HnŽƒ³®®ãaJŠ2‘´Î¢À{¹] Æîa¥màÄ­]Ux㱬l©€r‡±å(÷6MÞd€‰ä¨ïD‹ím¤WT1n¢¶áðv2‹Y2ùàXÌyM ²~9I™“!—i"«ƒéj”ã[×D&†3³&2Qª‡cšé.Áé°>䆇à+Mü€˜.‡ )C¶=ì¼Ô’‰€7‘Vº{²ë¢}‰ê^à”+ÖM‹6Ï@¼‘GSt>¬,]ìÐq7æ Ó^´ëBr¤Q©ù‘âvà‡r|´…yôh …“NÉFr¿(N~‘Ƥþ¶2êëÒˆzÕ•X0æ]×*Ô²ÞUrÝ“oØñS¶Z ?н#saö,­…sóW’:©€²0)&ÌáÓÿTÊ ÉÓÍ‹!ŠÛÈeþÂZy‹Òž]ÄZ!Øä­÷ ƒˆ¬Ï7|Y¸EÊøò­eÈÿ6yàmýH"ý¼ÙµÝÄaŸ:.Ø‘Ùk3}›Ð­Daz<­ã&Žƒñ³ÐSöziè4~*GŒ+Umè¾JØM²ÌB¢J péª22ÓbOû#+~žüÞŠo»WWÄò-!å ‚LtH7Ô„Ë“÷UgõuSª¾ èTû—kwG¦áƒݨ“ uÊ>Ô|‹~Í÷ÒA”«­dÒgÌŠ®:Âó£!’ì I^ƒƒ ˺®qIy ®æHñ²GÕÙ§æ¨vDk`Ì% íw2ÃGºÃ€ç†„ÓQ…J*™Â;nF|’•n M¦½PS ÷‚C´Ç6*ŒÔ&‰ºË‰g› ($î~â^ÇO®dI¥É;„/q´ZiÁ5ÇPª "m8–¦…§ÁcA'¸`ûè)g½š4Ä® ³ò2(²¶"T³º&1ÌÑ)&´[¡…v–Í:H!yg#Éžì M 3 PmùCNÜ,w ‡Õ7,EK48˜²ÈË<†—̸=äW©b:£›X?ÏB‹Ýužá¾Æà”¡¨émjPg¯‰¤ÛšÏ%|['¸ˆÝj’ž™%„Iµõ“ëÃo޹g*ÕFD‚päRÊèÿÆyvŒ¹¿’±DQùº ÐgåÒ´3Íò4È}ì4êa†rrz ¤·¬|z(6¬´3+–’ºÝ¬mÒáRXˆ1™E8ÿUïuõãÈý8Ò šM‰Û£'úšúšÜYʶÅÑØKöçS&zŽÑ1‹8O†ßELË=EÀQ&ƒX掛ÓJRš4cT/ÊÚjçÝæ¹€Ã®Y–ð¯M³\†GÈÈü4špl-+'(Ç©õàfÛ¸QF%JçŽÃîn‡'«ë+MðSHrí*;nQ‡>}Ç $äb®¡TMsF©hÏMįë·o$V?/,—|ÝÙ÷Ð rgÇ¡+ø“F7ÚSÔ‚àÔ'ï6Ó@Ÿó0ˆLlù”‘û´uw.ß4¦…üÛÙ’LBî^ "Î=ûòpɳúœ¿—šC´“YÄ~¶º'd’ÖÁÏP+ŽSï`‘ô"ÚŽ™õY‡c4oXX:ÁŸESHã´î5$çàbê«o¢Æ$è=4Ô&”—¥M,ÍÔr޳SÝÒèåI½irRÞFÊߊà4M"Ýð4÷žÓ¯rŸuA£ã5Ú¸ñÿ¡ ûm6Y.€Øf³yðD®©v³8úYü*÷´£¦77Jšw¸Þ'Õ:3 ˆÎ.ƒlñ”PìÞ.ÁéWä¨ãtè!UÑïÊ<Oë-„VÎóDÍM¢XñiŒÆ2Iz•(¬~:w¦ÿØõsx‰K:!4R`‡³Ÿ«³aŽiž—Ïp?"%ËQ¬,o$;®‡ϲèÐpÝ'×OþþûÜÂÏendstream endobj 493 0 obj 5343 endobj 497 0 obj <> stream xœÍ\YsÇ‘Þgb_<³&šuvøauXâ†,Q´Ö®¤ˆ/€a R¤üë™ueuWÏ$V¶&‡Ýude}yVV¿:“<ø_þûñ˃{ýáéÕ8üþzðê@RƒÃü×ã—‡ŸC#©àÉE”‡ÇÏRoyèÕ¡ f‚—Ç/~Üĭ݈­ýùø¿ ‡–¼‡fŠ:?†Ÿnôä}ŒróåVN17ÿ¹U›Û#9c½Ú·6Ÿ§§Ú„ÍCxªaØM€¹&x®TœT×ä‡:ârøk˜ç³­™B°ÆñŸAse')ÂæÏ[ìèßÜÇ÷!j-7_m¶×FM0 „Dÿ;g½§—‡“›ï¶G~x6ÿ³U“¨ÄÇ[à˜’ÁSß¶*±+J3iãrë(³ë–êeŒ‰kÇñFX¸ž„”*n,'•Ÿ¤ÁÃ$µV›§øÚ9·y¹@YðÑo.x_[^ÔÞ'ðKúüyc[£5ô=ÒA¬Àà^NéÍóÚ#õU0]nèb€eI:Zɤ©½01RK¯' ïßAK©qoÎ=Ò™Fî96 “·R¾Þ‰É:­€cµåœpel&I;ocŸ"• ¨ôЇ¶Á2‚ëˆïpn;)Ë­lL¾ðÔ%í[/°_Ú ØÃ¯ŽÿãÇÍ_f#åY‚ƒ¥) "D)¤Ó(=\ü2€±%PÇZ¾Ã÷°+Aeh:k34C„– éA À£A°wÚP/€M@ í/ÎdÇÏ˳+x”[6ë”Àw$pIe:@þ¤î ‚'¬”çOpø‡ŽÄÈ,tu‚Öå¬5Ä5KdªÉ³– *­/°±Ÿ”â#\àCË×ÖÞ]!G¬õŽ„êóãƒo^jNÒW°žp¨•‘“‡k‹ƒ üäþÁ½û9|óúíÓƒ{=”÷¾Ä?>yð)üuÿ³Ã;øüþá·7T„R;œf&©Ç¶Ê›ðv}%Ö°ƒ•Ø4u+«,änÞ6éúo°Î ì¸ü—(¸Îié[#;n7ÏpLЬ0“•4¼1Ï.dƒì_¦Áè²De´œË©‚iBCp§)ìÖúi¨u– ÚÇO1x»ù•àÓGRG ¤WGØÇÆôö#T<“±ÊÕUÂÉX ÞlÞ6.\V&?ï¹rZDϲ·¨X t vÙs8#Ï Óé!+p:dÎ80Ug#5Ähî -h%€1‹ýìôEaöóÁÖôÊ¥®¸m¬Dsÿ 5ÆÁ^ô#ÿ¸ØÂÚGªˆ!î w €ì:Ná½5f§iMAˆSÄ€¢¸9Zô@×®N€}Á(,´¾¤ô5’-×Á™»7D_¤­Qq糂á3¼tmʹtäÇOš$ÏåÁF+íŠÑA›xÖ´ýLhqJD’ d HäOF›÷ M™µ`èFøoô!FaU**’&nË”w¤\˜X «RA Ufc^¤‡È¿'#È;á„ë÷ fdUWDF•„’f£(˜AxÛ¶ºŒÖ’-ª³"yþP´¥ ´õôÏ¡©ákä ø,ªSœÛÅàHÎO›ŠÿNédn91C{ÆÌT·/?mI`Tñ®)×…3‹#°\X?\x%,o*,±A³hM×9™Ùn”U©3}FêYŒõ ÖÛqHS- ë¦\à!èTÄ)Åð‰o½y9^82ÅãPüÙ‘šèçîs)ï²´…“¾¸ê@‹—vÂušâšB£• ÍØ,­„W>§‚qj¿fl2e¦‹¾0ŽÚå–W\-eÈ&wZf‘(À苚Kù”ßòíFNN£†LiÛQ¢ÝµDûý­˜¼U2ž`O)éøµ®&3ònE¢ Mr>>*1Ëðphdþ®hºó¦6ßU’€IYdäCÔÛU‚Šâƒ YÐB>PHƒp¥õ*¹áÖ´b'UÓ °õ¬j–}8o&ç4©ÍØ¢°í’^añ‰É â'·#þŽmçß'›‰£½­dÈöµS-kåx·ݘ 1BrLÐuéêvT™B {V£.±ð¶r Ó†ŸgJ÷„Fü±(ø ¸Äå0‰QÈ#Ûtüê"G>Rô'’¨Õ—† VÕ<;ýÜÞ¼Ìý\,S!ç™Ï¦MJæ­Ù›™0in¸×Õ ‚{·³•±ä3OÜåó¦¤ÍM:ØÝ{€§enìvmþÀ÷šÀC°2‘o ¶mÁÈÉPP`Js1%ü (ì-¸ùÿx\££†Â]&¤¾WåÔîgX‡mQ¤Õéóm}‰ <© $@"½Xß?oïÛÌØ´­ <1£½´<å4–‡¯Gc¾©Ïꯗ£ÑÏ[Ÿ'Î'œ¤òþY}xÒ¾Ñ ³Cdÿ %˜2êrStEž&Ô[ªªÕ±tú;ïTž&ç<õ>ÂŒÁoã`nÀÿµËÿ6’ïׇÚß3›ƒ'ä(±5ÝfÞ7H^vïóÃÇ;óÃg£‡­Ï“¼ƒÁöÌ(}^ަ|=BÍ_ܨlÌóè–I=Y€&ËAB/ؼimÏ:úËÏ?ÎÀ”æïMïo ¦ýj‚I< :XÊô‹úð×&ýûðôl4ýëí¤o–_ŒÈk3½!óu¦‰Ò³ ™ …ÐÒi@iˆ×aÊ Výa8IàHõ§<¿18Ô._4Í7Cpœt÷K¾eÏù>[ ½ÅŠd¿ªߎ”ÉëÑŽ7Ã2uœEÕ Æ´¤ÿåä 0•õ¡h-E}x·=ÜÓöFâ1äuœ pm´"²ïÛ0ûš^Žû¾›‘É”!¸×3ä ­àèÆ†<õþ§Š×? ¬¿T'¼&b8)9FN8FŠšlu†5?üe$ˆw›êÝç îsOλIÛ†'k°y‰†²G ”¤ÜÃS'O¿ß¦;Ê£¾…Ñ„Îæ {-?ð†î^õ¯~´zKź9ÅBøAÖnV™NÏ „‡`[.ë„ n$P³D¥U0ÚÒt}MÏ|.ãSEÜìw¶³cIˆC•›Ã“VÖiX<€¶ŠŽ©Æ•uú®FÏXGå ãBPb!z^,+ÞZöç>Cª_' %⪄¶TB»µ€ø›î Þ ðè0 €(ž;•óà%…ˆõC‘OôUËTKm=¢•§ÃøÈé Ók,wžÙ”³U¤Èñ8ÌòšÍZÌ–ÖÚûöÿ·< Éé*%eYs_7ÍRm£ñ ñ¿cµ"Gø ùYÏà€gQ½Éê<õê½À· ²®ëÔ›ºemƒÂÏ }˜¶”˜ÕG³b7V%ã³öXV° À¸1T]—$AT(˜¿èÁª£Ò’Þ­Fæ¦R£„åÚÑÖê¶ÿ‡ûæ*ËáFyi ­qswÎ{ó¨?ßœUî"v\³)ƒœ÷ƒt…¦¬¸­ð«÷˲Úq­HmšÖމLW8P§]=éaÕ›³cuÜ¿ÝpÝW€e³üº‹>éלÁp„R"YyðòQ táî3Ôâ¤àgbù“›´©·óK[ùPËÛ3n¬¦z%§Þ–\2Ôv}@Þë;CÞ2ŽâŠÀ!wš/-œºÀ %aŸL\¶§ì4u5ñÌÚ”ÊtÕSaŠœ5JEšQÆî@!ï¹­oˆ;½‰é6Ö¥+iCÕ7;–ì®ÏÉ@d Mg8Kï,]BH÷`’…w¥ÝÇ{W„–þ èc½+ &ž%£VDrå±öv*ÇüöJ¤Menûî9ô‡+•ƒ­Ô'[—h§¨d«^ØÇaU)–„TcÍž^ÔÂ`æ8ò—–dpŠÏð\¦‘µF“®©Å-ÊðP”]²ÏÛÝU¨bˆLdžš{uzT$Ú¦¹Ãå¹'%ov¹­p¸·G‹—õdô²Y¡Ü¯_.JZ­H»§é$—„Vú±(‰ìëÜNz ×݈ËÅJfÝËmK³ÔõÚ ô ùN—‚‘LUwÊÎt~ìÕJ'…J¬Ù!<Øt¾Ô¥ý²Q6†Þó«ã¡Bˆ‹NìJL£UJy a•ÆÏÔ‹mÐ] /¶ Ê_g€ µÛ‹H_]6¬uÉ·g Ê˱ºÚqï `Fصv_­ìÈnõÚ±êÒL±6 mU/ë!Lçz¹xòb-Ã1¾®ô«›ÏËpJ 2ùÑPB:å:t‹ yÍ·rvdW\R Ö7ë˜E dÓ¥¨B™¬4·°¨†×MgÂ7 gVR¤,ÅÕû¾í" mµ5‚z„‡j0÷sŽáë:P¤l®ë@Ÿêyy!¡;A×v ›QñB^®v(ΣZ¶j‚fqNâfoWÞ°0§jºÕ'ëî¥ã%ýü‹#‹ …ßóD3#»$va"ù‰·e0Ž;…m;±~­àä—Y9ÖL vª‘È©¹\ò¸Î•}”s³“jÝTëê6Q¨á¦(’­žfç÷¤1]»Y‚Eå; Æ2O®Î°´rá²Rv©îzœ3ƒµVÀ9»“¸sÝË99æø¨Ð"_e.,Ížy©O5Hkµµ©¨¦Ösl3xt96㈀“äöc¨4Bs§±gو̆- îÌàÑ•§j³ÅJ‰„˜ŽEF®ÔS¢Ž´à×wQüÌÈ22‹Åê6—>ˆmÃŽ¯#–Ä-±J̯#¦Ëóî–Âv#5•Áûi5÷¥mÊùî®Ñç8Ú¬£{wmÀêo- 3‡ÁÀêý(B$¿%a){Ï[Êåô›¨æÖÆëûM#)¥{ nþñ‹Õ›ÛTæËÅ`©²ú¨ø|±¾5ÏÝÇHò1n15Vî³?]vÙ“-+æŠÌYse’Û’&ªä Wþx©5f;Õ{êtûcÇ=ò\l½0¼(+Ùð†0 4¨ÃG—>1PnÏ2ùNiu÷i•™GØ>ÓÁR›xƒÊï./Ùºš§æ…Ð™§§tÍ#ÿ£Å÷õPèÇòCBßË?~WþiKÕÚJìøM€e*ãùþ — »›=ïÙõ¸•›?e°",·õ)§¾:~m»ŠfÀc«) …ß Ü“ÂHD²9r³ül¾•gggúë!¶sßQÀܪ÷ÅýŸ†×~Õ¼Üÿ…r]û$ ,z,OÞÒ†oGŽb¾Ð#^àj§ùð]*²Lîª4ýÉE0;’'~2Z=m\¤o³¤w C¥åë…}×ÔO)•5i5"IëÚ¡»twà12ÅM»¾\Vps·|0ÉÃ*•Ý·fÒ÷Ãv|*Mð¬O˜>¦gcý¤Ÿà_XŒ™¿½×Õ ¤Á­ÕM‚‚œì$6šëœî”µŽ’‹ ¸¥u^EY´Ú”ñLZ^do;ÊE9XÖ[޳þ{´fÄûu±^’@†ˆô±¯y.@;°óÜà!fö~š•Û7ÔyM²$ËX–<­%Fi²} „$RbÇ•œ˜¾OqÛ ¡Ëu’SjÎ<¯öe—ÙVo0S¬þ@u¬ÁÀ<.ƒó5ášÁ]ÂÀˆƒ¯~!ªÃ+-²×Êëpýï­â·>né>$‹Íñ†ª“_ÉÏx³voxâX/] 7ÊÍÚqƒ?_¥»õAÕs½½¹œt [óZª•ÃŒ·=íìK×ù°@^ê®ÏfãMâ¯ë{ö ö%oré–deí_oé`LˆpßûCû”Ò .|GZtRÁqR±éóC»ÅA¹hKÖš{–…J¾A ñ?ÙRì Uýl8bÒigL_æ*¾_–ÔÔEZÇ‹¤Ú'ÃÑëh#c3*þL{ÂÊ6×0H_ÎÍNÙ÷]ûæ8D†2<%Ž_“Ó~³zço–»Jöɺ¡Œæ ùçÉhEråëH7 Q‹Še1EBqìK„Kçë“©îMÞb4IN¨Ä½4ý¥dȬ{õ…–kiÿ¦Îé›Óßü©ÚLsendstream endobj 498 0 obj 5690 endobj 502 0 obj <> stream xœÍ\ë“5’ÿîã˜oîæÜ…Þªâb7°ìÂköÌ,Á±c=æÎžf<Æþï7SÏ”*«ƒУR•¤Ì_>•Ò/'b'ÿIÿúêÞ'ýÉÅÍ=qò7ø÷âÞ/÷dèp’þ÷ôÕÉg§ÐIKh&1É“Óç÷âÛòÄ«7šAª“ÓW÷~Xk»ÖjðÞëôÇÆÓ Ä¸új½‘Ã8 +W_ëÁ9ãìêáZÛAøõ7hór2ãê‹õF5«Wß®7v0ÆL[%ü´^­>‡ƒ¥Ð«ÓøSI“¾?NÐ÷lUJ9·z´V?þ7̦HæßÄK8=‡iO0S¹¶Øq“žl´ÀéL±Ã:<‡z7-Ë\¤[}¿Vy8ŸïàO2ÓÇðÄi˜•YÁ'.ërÎá Œ„‹$ŸÀu¤×M˜{¦€nq0„ Ÿ¿^oÌ µ™Ôê¶Nƒµ#—ñž€c«üžµÞ©Õ4Ž8çÞ4ðCi³zZ~ýœYúQýVíw^ ä €0¯×¸n¯õê÷Ò%N‡\ìY@%+L³ŸÆ¸$3R*2ÀÛõF‰´ŸèÍòWoÖÈy M†DYò6òMOX?®~­ŒŠ]&kÒ÷­˜pqY]#åå–eÇÁà#y… #¤…y \ú©\æt)}q©£$ü|³¶fæ÷/ËdnÛÑ‚A¬Ì¨ƒHlÒ‚7RÃ|„Šë^†6¢ñ!ü[…úÉRÈuÛò XV¹´©%}m<¯@G¥¡Í 4þE}Ë28i;Ý•ßø=›aåa=¤7R÷RÎ9ïL\x]2" #eH;Ð5@ÄwdZ‰Zù4 ùLsÉßç$×Àg%P Š&¾MÖS¾+ÛÖpPª úáéëÊç®NV9P×¶7k ?öš òÆÃµ¥ô@ôz,ËB^iùÚœ‹øRy¼oÎÛfåiÕ›ˆ˜1.>3Hf))}aÔAt$L4,aþÙZûTŽÂ×´DÃ6­žPŒƒÝ€qPHŒ'•O*|fgø¿IÓpÞWPž®#œ’­¬h œÑy¼3ÂÃ{å'‡u‚«‹¢:|]3€‡´e¤U¡âÄ K4¨£WÌóâ\PíÐíÅWHº ÞÓ«?á<$Êò$,$ª äÉ>ƒì| Šk‡J" ì ŠÙ?V9š›¶–€,Œg†4ÑÝ” ~,íƒ °|eé“ÎDÌMr‚î£Ç ¡ÓÊË@ ˜‡CLöÓ:Tô£îB‰H…Vñ?¬Î€øXȃŒ LRàwÐ)šÔ¤@ Aî[sÙsFŒÞÌAÝ \‹fT±šnõYœˆ1AEbsON(:ü_tRü½‹V0ræ`rÜÚÖx9š Ø~³àÿ=,mñókø‚ZM¨YÆ÷`ç"üÁKr2ã¿£æëò¹-áhEDý‡õ£ZTè œ ÿK@Ó_Öˆï¦Õ?q!@ꈟ²ÅÞƒFW÷¦*<Ëéõ,€D÷gÏU»ÕÜ[ªøˆÎ2=­2–¤"§5Ô±A ƒ²Qáú 1·Ux¢CU›ÒŽå5Mzõ¯üáò4qƒ@WÐ?×1nÂN ¤‚•ÿ/üõSþÌ}×) œ585F_¼gú~§œÁ:À™×6„F‹Î<Ø[ÆëÌ*']9Á/-/Ahˆ^ÌfWΤ”ü¤, 1J SD ¸ _\¤ƒ".˜þ/‹SÜ+”*X<0J,/ɯHpazŸBKçx‡ºzE ¸Ï«§4äÌó7HƸ̿¢õÞy£×û[Œê&Ô¦=Ÿ²MC£^¥EeòÅ êÂÒ£E¿°]7Ú‰ :T‚+ñ´|sÛzáÝÛ—Œ*FÞ`dãUæoû©‘x6D{N6Ö!G€‹ “ïáÞ…p\%¸äYÚÁÈ镯$qøóvóºE-þaÜò2Œït¶¡Øz[?‚€˜B6Y„œ ±NTåJvÞMRò´‰©œ;GŸq‚šÚx0O–“Ep3g˜Šú½pÌ Óyì8¢U9bÓV7ᬚ„]¡W_¬Ÿ¢­ƒÈ¦ÅhYUùè±,ƒžaVÁ(ý^&#J^A怖þh' ó(­‡xYÑ›0gž(ø2ÜP_¨qH W=iÄqž¢HDý‹”šsT,·1òó6(qƒ™×.Þ.:E¦^ÍøÛ&vò»-w›,›äIr¡r}è Ô:4­J½\Ca(NŠ÷Ç´J¤ÌG 0Ï6ÿÇZ c¥5Íú°rALJùš õ³2É]E@¦Ú)0•dŒoëÏÈ\àS`®PÈܬ¤YØ}*QŬJ›y!ïsYÅ›ìÎMo-ˆ™ïè*xÐñufå ãÂ2>² ŠƢêg½ÇÓúIB¥Ô|[Ì*‡IÁb2[rˆ "p¼×]ŽM¬v †ã"mY† Îf¸5¾ÎLÅᧉì2NQ”D´%S±¥º‘ )!d ájPÆöª-÷ñŽjUf5¶#ʽs*‚ê0TSnK 1bí€$­rÔÌ4*ÄL8iÊ&Eg5;ìÄ´˜àA•¤ü²”ôÜñš}ôÃëœ>çýmÜ Dë®ÍèÁ«FÎ’þ³}Ž.r™±5áM8ú¢z[|4âögÀXÙJA6ÜûL‘¨Ö иzi›¢‘6›<¥H€Væù p)¬us»da 2ù1›ïc.a99kcŽ=ïJºœ±Ýéz -Æ"Í…‘ó$yÆÆ‹UÔ$ÕcçDÞ "À4*L膹Ao\¢… ‡$ qÌÌL“yoûw×eûË«, øÛz ^½Êù" Ä©˜[ð_òv ’Ë6黼s€œUÓ¢@d-ºhýe£ –ÖúA3‰pÈsškÌä€WÃÙ=y¡KêzäÆç.Þe£„Æ«Oi/—œC…Êžœ ‹|’ÚÈ)@Õ¤s¦Ç*þû3²³s³*§…>¯¾ÉѾKH¬~“ö ¨‡–œ¯:·˜âA“7ßÀ Å¢}K>à>Wq®«I:?é°ºƒó;b†D˜úœØDìSe‰ô.ÒV„rž]’º1 ­ÿŸ”) ”ÚG3›àÕˆ¡Â¯±A%ßgZ:ìæÈOi&u‚–ÈÍøz¶J¾“’&Z’´ ëå=KER[O½òP} ¦v<€É˜ã#€Ü˜#Ue(úDšHB<Î6—¹µâøšDÍQ<4Ù!Ëyw,iÐÓBjk› ß±øU Œ[yÍE­7®þ¯Š Icóº&S9DC‚Vš—]ªƒ2LI tÙ7›o\¦,©±D2^TÛ²3ExΘ8 çdÃ0¤Üj°.²$áúeÈW&)—Œ5 Sò}c0]@(ì¸O(BÉ‹\0—H¬×óTQ•Š[FxÎ’lH’pBgüZmårt6ŽC¸oúd†4~AU,ç÷Ú4WŸv…°¥ ©ãü¢yn­‹¨…–¢‰o½€P? w±µkQ5ù`'.h†Š­œh2œ!©‚+§ljèÉ ecb|Ð똑h=µÖ–¶¯Ú$GÓÉ“\OÚ¼¿ch¯&B{’e·Aö‹CKˆ>šUŽÑÑT›¬JY-É&$gdµ;Ó ycàøU­‘@U-åÞð 'Ñ:àv§ÄmþvB–‡à‡N†%,Ñ´59gQe  ÷É~zƒß*Vþ1¹Íe𦉠ìwhĤØBZëŒV¡R±ç*[l=–Öy÷Ñ9oum"±1 !†Ò9¼Æê!g‚ÂÀòÀ¬×9me¢¬B£Yf2§~‘h ¯¯ËµT5¤µ 5”&(ùekRãAR\+%—¥Æ¹ ’X—ªa+ýðRQ¡ gZn"S¬Ùã?–­íËc]U“³ â£wBÃ"=±îT³Q ”ø"Á[ÖüÌŠbs8 Üî4Z4IÓ^“ÂÆþLÉ_uгé ?xçXùØUx—hÝ)DˆˆåÍT8£1²5Ä/›dˆyš0t¢z:ša7õ!ùÛu)¥sr~ßVE1DÚªp$¼ÄZaâóEץͧ¨}['±¨h^d±n“ÓÉâØNˆj>fŽo.PT¦¢©šY†²ÝÜ^ÎPÒ¼›šæÐ]Ú$ç‚ 4ó¸wÍxN]’N'kÚ(ÜøIëg¾¾wúqS5Oi²«:‹8Ìh£w@|JÆùä1xÔôè èhd¸"ƒÐÙ'Àh;8ýÑ‚]&0sUΨˆP„>:< ;€võCé¬ñÏŸ•à} «·yƒ»‰y_´©—ñcHW@;šØ×åõuÏÐ@MáM]ž_×ççõù—åù_êóÖçÏËóm}þ’.07nKã¯).Ë/ðfÍ´ãÞÙ_q³¯ß|UϸžïN#ÚQ|ž[¯g?.u;07•J´w¥k*jO[IýíøOŠ l…Pö‡N¸Â8Ö³Êþºlèc•èŸpìyÓ:5>Hß1p·µçëÊ”[:&ËèÜx‘^ ¾ËnNÿµ!tî{ÙÃ'|³*Þ§A‡zõþ'üÂ3jÁk ¥„AµxlÀ¶mX&®8L\&H‰ýì«/½mè“ŸÕÆËÝèÙÒÑwª‰3Êè<Ï¥‘ðé¦Îó‹òüûúü´4>ªKãßkãiNÓêOE]¸’šºßtÌ?¿«x ­šáóÏokßû=vÂHï[óŠ;ª¼ò*+ã³²@ÝpäEaõ{(®3JŽ ½<»k¹¿pŸ¯Ô¾nf—Ùˆ›ÞXú+îÏè˜ÓúÒw,ç•ZÍGõ¢})¡ºq¤²b¬%^ø¯u¤fÁù%Òõynm¼¢fÖrÖ’ãù÷^©d\¡v-„V æL޽ý”[b 4n› %Ýß’MK<©¸Ì Ñ}чñh²ß~oâ¦N¼:—ÉL¦5tw.\°ð‡\–èW2n8d4zÜŒ>¨Ë?G ¯""ê ¢4¢v ö)‹xR¿‡·²m(À¸—©€ Yq"Šv2;À4 'ÔI?åX¡Žé*ãíº•Ÿ“?é½öÍX³ ?sÜ»i ’4ã>%øþ¢„úÑÁ÷9ÙËÙ-·5³ÞÆýlßq«%;!¿eW”¡¥Ð;Û÷…–³E;Ä m˜oÚ†˜Œ¾¿®ù–=Ì ªp`¶jì“Çã‰4ƒ6NaRâ1\¦¡'rm̸VƒðFొUMжÿû!ÜX#o•±ôD„ªÖ =HøáaÑáuåv”ƒƒ'DfÚ`â3ü¨ ‡u°ÎëPjƒeGÊàyr¾¶(ºÚHg¸Kq´Èä~ˆÅQ;¼!;'ýî›Ôp·O÷2‚’¤.-åŽ7U¨}GRR}:·Ý·aj³z6j\R°Êî>pû]‰þÅÚ.T„Ä çú´4éMÊõØ-—CöWB!lºtà9.M—Sd¹€Vï*IŒ…+Qͤzvvš%¯Ý® Œ"»ÛüqÀæÎËm¢;Æánç®Òß#ËaòkÍv}žfªN dhÝ=’u/{tӜ٣H{Ä„õÝŽâ“ÆpŒPŒ+v/¼hh®9k·,r])v´S9uæl8ËyňÝ„`ö6òÖªWw/ùt¾]ØžlÉ< áŽBd³¯¿í% k“ÈçÈ©<Me*¯KÛn] Y—Ñé¾ohW÷йº‰¼GnèRø¶ŽEœøÆOà6W®ÐjK?˜J`k·kû.x鮉ª[€µª«"É×8\ -EÙu”¶;- ØŠ ¹}ì²…r(G¥5ïÇŸ¶Ýuªá yŒÇH]?tW ¾{£Ø°¸Y(w‰Y@ ÝHO7?ð'n+jX›D·W,¥Ígaj¬ýp¢7ÐaYp>eXÆ•á©ÇKÙ”çjjð Us¶xé./ë©|$”ø¸ïnª’Ÿ >¿ªrC×"¹¥î(<†m ‹Ù|]R‡2SÜèm5ˆÂûST{®»?E& ÅKD<¸CÊîîT®*ïÌìü1óZ±ª‚”7…ÚPz÷rLv÷”SÀ¾ÑêxiZ+Ó|—aèý!î2Ì7ÒõwàLS8t¶X6¯6¡B™²±ÖJ6R—$Í‘ù&ÆV>"Ù蹫î<[ÞReá–$ˆ쇂Îç 8§-cÁ¡ÃÖ:ñ¸F9iRúRWð ±DÈÖ@í)/.‡0Õ¼gwîvßQŸä»í•*3q¥Øá( ø`× §I±H¾–nl+¯šûÖ–h€*¢Ð¾å¬ÑR½¯v9–Ê-úˆEˆÕƒM åþƒý8‘ì0JÅù‹±6R‘‰‹äÖ‰…•¹01Y£ssäì"Yö„yw« ê Г*Þ’™1¦=Ñš©Îr±×Æ‘WþŸHýƒìйtSöý†¸¿ "‰X³|k:§•¯4 ·ÑAü´Hþ‰¨þ¨V >jìl×á–Çî.»¹vFâuT‹‘T¸Ôµg¬æ%ùdŸ­ËU”|–S¥£,¹Š&,ÐÚìQ2ä#–³¡’2–Ì—ë¸6k.ÕP‰Û0T,E箊x™n…ä0&dd°îK ‡\_ʺ•3­>?>¸pC!ðNŽ—*œ>%W#“Óõe6ò8w.Í2Ýÿ ç÷ ö:jTÂ.$á$eÜiøt…(wšw1 bVì7;êŽ4z«dº“›p^iúsŸiLÎö‡:–'K‚Štÿ(=­…nï½ë„¥üâÜÞª©Å[æûY`Ü‘Wü¤Û7<µ›£%À*ø„3g] ½^¬É‰eâ,9Pä¹v¤%³CRE²¹¢SÍ£O`X.‹ì’ª\TSÏâ¨øU ŸZd낳 ìöÍáýÃ4j8"ŒíËMt!×¢iü¸_éõØSzÇØë‹„À/ZzR¼)[¯‰Ã‰ùxƒ÷Ý£ª>9¡ÀLwwšg(ÓÈí¿ptO|^q§† e½¼roP"XëRÝ!‘üQ¬æQn#ÅZsÃVq¥ø£vè1ƒÂ,þ'ü©J[­ëËÅ~Ò’ÆOëæœ¥_ÌlϦV0×/mBÙ &„(@=[—jèúQ[_r¥ñ-7|Û3ÖpRY@¶¡ë–.ÙÙ|YK–ªzØRdí§÷þþù7ð€!endstream endobj 503 0 obj 5729 endobj 507 0 obj <> stream xœ½\Y“G~WøGlš1ž¦îÃ<6€±—ÀØÖÃÒJὤ]]üz2ëʬîê½¼`‡Ç3ÕudåùeVõ¾Þ“ÜøoùÿÑÙ“ß|ë÷N®žˆ½?Á'O^?‘©Ã^ùßÑÙÞï÷¡“TÐ2EåÞþ‹'y´ÜójÏ3ÁÃý³'?nâÖnÔÖ>Ûÿ ŒÐ’PÂLÑÁ ýcèø‡íNOÞÇ(7_måc0qó»­Ú|³ÝÉÉëÕfŸú|™[µ ›o¡Uô›kMЮTœT×åû6ãr œøo°Î[3…`ã¾€îÊNR„Í·8Ð;¿ù3>Qk¹ùz»SØ_5ÁJi"$ú¯ÐÙ9ë}z¨q:¹ùn»³ðÅ˰ù÷VMBX GìocJŸÆ~¿U™]&pvÁ¾€À½lÕË3׎`öÍ~œãÇîN)7¯êÏÍ5~¼j]N¶;vJãrï@™“&uÏ/aoȵà6ÏṌðC³AÇôü˜žŸ·çoéùYk<ì&-oF8§ˆi‡¹á‚zÞ¼È95^á,aŠÀÛŸ6­ƒì:”Æë´`bÂ=ÿ@__å¯FU[ږ͇nÜyÇ2å*õdóøúÉþ§?fñ¼ÄÆdäÂæ]iLVÍs­±Î÷†w¯׸Hsë\#yÁí~i$Ï©qª¸“ “G]Ü)?ÉæTÎ ù:Í›wxÚ”qê\7Góc[ïSüù(Xpi?KüPøñ9W"Ÿ:"ñYÞÓ.)ãÅåHÏGwNºs?ÝHfìÇ>‡´üê…¾æÒXº¤Û<0QwÚ ³ª{§£(Fm4†GÛ6’ë¬{ßY½XïBžëªS|Ð; ³·k. ¬¡%“oÇâÏåÈ]ïï%°ÒøYñÜ ‡7Mß…¯ó‘¥|¤pw¯¨Z£¥ž®ØÒr‡Ó¿íó%…06? aŠ$:µÖê©öWÅ‘Ìü `òÙ i¶Õ¡O9¥ývË¿i1 —ó%ÎEÙôІrŒ|J¼Zn äG:1„u-§CòŠbé¬ÅJÏ, m¹å9clsë¹S%Õ³‡…L&433\~ÞÂc œÙÞWg%¯÷9åù°ç3 <%¸^äy¶›s\¯F‘êpd™ïÀËÜê¡©IþrdŽÜ»X˜c–lŠ™:`(+Aóc/bå ³87Ãäd”kðÊ{ïMznq=°,]ÏØ5=0#ª²ãÚý!6£i5”/üÊBùíÖö˜u‡? ¦ú”¥ßÏÉ ‘`aaç— Øð Ö!Æ%Bx>’ÞƒàÑC¢òMñ††^wnaàF/ÈÏžl²ÚàÉÌÖ´1ä>ÃhI’~S%M$0s÷lô†I ýHê§‹¦å¶ìá)ØÖÏ ÕîõéÓx‚g“2„äï½{"ÅPEãó8Á,ýpÄ>šðhE½‡™Õ/*I½â/;w…þ»(Ö)Þ(Ý[KúÙ°ë™j:ÐI5SÍZp«Î£¥E)}3ÕÓÑmW `Ň'Ÿ¬r˜™vP¹º©1úQÊ gEþ–Ê 7e5e0°XµÄHXŒ*­Ï¨•ÖÚ!Í$èñg·Ž©‚/  ²p<øÜ¡BuËelÌH².å&× Ó8ýé«!ÕŽ–ùQAlܺ´Ð“ÏÖetµ®‹¢ «Ötc(è,¹YA&z¹í³©µ<‰ß›0ÔáˆeIU0=LYÎF«ßÇ´ïKãT+·‹iÓLoF ŒÏ;uªB>íĉ9îÕ†"›7Íð¯ª$sŸcþ TG5§›v74õ^4·T}–|º‡ß|z³¼:[X* ôiVöw£^d±,žÄZÅBgGÉëRíé¬r—iûz(cE®,ßÃ2å ÷{PîaF{ù¿”&zP5û”L,óCÕ6“Ƭg§õ¤LMEÿµ5xiBbUZœÔà)£RÉ.m˜Œ+‡ªA ]Ž/µåø2ÄhËihz^'p¼Ãßa*c'%Q•²Ç„‰­rýr8Ò@wd«5€Š¨‚m„X4h…$냜óΤ.'ð²ÃÆ4ê —¶Ö;UPÚ€¢Öo×°‰¼fó]”u‚@>P;êŠ76Ÿ}`ÀPm¢ª+¡ˆ±«‰“–-ź%H1Ñ@í¸oˆÛ(†ƒ¼™\ÎZödÛ/Ì4°mÜ[ð ÇYa¨¬Ïžb±Â‚:€¯e[;­gÜÌ»I°™èË¡ ]èHp?™cÑš*H<Ÿ^4*Ÿƒ€løK€«š0YÇ'\‘µЯÀ)˜çy¥³LkÐlEÒ…š‚Ò‘x.É$OÞv*ªmîÉ[¹,ª£¦ÍYÍ+«žz3!‘øíÚ;XLý^é—ÉwJVáÊd1dœqºÍWíæwqóÏvOÉô6I±©4º/—͉T«[ íÇŒ£*!8kü¤”æ÷!ØLmIÆ­_ Ív¦¾Úݨ¾uÎ$åº.T²«# #i•YÆŒ=—\ß[Û1 ;줋$K·ªü•惼V}rIÖsÚ™Tºé;9–U‡é²Îç½÷Ù'SúÂjk² NˆûNd;dRÃ$Eؤ·ÌõbÌ:ÅzîOÑÚ¤êå¢_âE²”Þ’sŸ°eÊ×à My¸âÑ¢š)a¥¢ñ{Òa¦gŒrRÜ4fu¢¢¸ZªIÅù„`+>§ès3y=1xÆä:¨uM{ñª³ëúø’¾2Ÿ…*êI‰Ÿ$ýWS°V:[p f?4ìÞ>D"š{âjÅÚ œ2©eÙoÐÉœzÝzÔˆ*)SÁýuÃëBKÃ@Áƒ#¸»ò Wo ïúê>^ÃbžÛ{$À( À¬¸ól²;#³š?ÔÒ1&§ŒSwâ¯Ë_õB¼À~(ƒ££µ4i_@pÀ@XÏðµ˜?žïuˆ{ŒÀ¨ïVµ@kÑG¼•'¬ž‡‡FÞHR:i$Ñ^ OšÅ¸‘žs’+†2­VÑy“¨â‰ë2kžï\¤É@.à<žWé´º¤§|ž¼oå=§ßËæGPAeoBůŜ´ˆ‰/q %ÆVhíD@Pf~££"@´¹úYM¢Ë6JÈ‹·AûÚmí î"%ŸCûj+«‚ 㑹†¹*BÓéóÊQm)ùº¸ZJJR<Ðÿâ#4 ^)o@m6#çGQ{; xÈ~“\åàÂäXùŽmFFC›~Íú+E‘˜Ÿ£MP’£›No+ªê4ôh«=„hÆ>¦ŽÁ'š+KJF­hL¨!Å#…(fÓƒäu¬vKüɫ䘑XÖC.†^nÐgïú¬­Oä½§ˆðjáqo?rrèš®#£9õKīŠc‹òÓ6ÑÒÏÆÔm˜rW‚Ÿ|¶Ä]¯se#ìA¤ÔÆ),l@XìlÀëÐÞLMŠI0³ü•x`` JŠÉ[%JJ¤àñl |ñ ¯4Üd9¹ˆ7½AhRë´Ì8¢š<(ÄR½˜—’-ÐbXÉCS\p¢ÎZ&Ð*øTƒÄÌq¤M•m$Õÿ4}y‘˜ŠºmÎõ•E¥±£Ê†‡x8Z´@ìºw¼D(ôºp.}’uÅcÅðXî°(* Ù‹¦ä9ˆYf½4¦?; \kô•ÌéÔì ê¡~5Ãød„a[²ææ¼âiykß{=§ÃœUr¨ÏöÎ<ð]ªU•ã< ÉpXä–pe.‚H¥¦w[k&`bèÞÛ¡³«AŒÓ8æDß-á )(ïù¡ ÷sË^NhB½[nj–4gø>Å>Å‘ïæ¥žÄšù¡k=‚šùoTA ÝÒ%`Í1BMî{ Nù¬sÌH°Zα0´r’ÒÊ´Ù’]ž`É{ ºqBònFØê¤oûxµöhz`tsFÅ VQ¦‚£€²ÈI—€sg!\>|hu3,Ü’fW <˜5¨A§"ªT\V"VÓáâºáb÷) a¶lká¯u9¦ Ù†æ8¼îjJiËj§0üQØÑÃtæ®Ñ015W0sg7h.Ç&ÆñÉXñhVOªÅ=&Wc¬­ùUô!"cÄQFÚ•U’GÕq³Rk)ø"ŽÎœH_W;˜­>íiæz•·€E)<{«÷ixÝ¡ëEŠ5C—<,ñŒ˜sB•X¾ý/çíÄ´dGÞ±S*–8°Ý¬¥!õCôJ%èÕÜA–ξz "¨†‹»ÌÐù{­Ò±kÍ¢¾A6¹DáiwÍ"ÈÀ¦>'h3Ï.0:UªŒc îT¬Ü víð«B ¥ M€ÈÐõt­}¦Ý“>î4þ§õï|rªPƒôÁ::„84Q~ѮIJ×LèÚ$»þ9|e©{»þq‹á+«tW–ÝÊ~л³‡|Íz=”ÞË¡ëtËðG@Ö9™nC¿ÞÖ{ítñ4ý)d´Îï,d–Z?•·; K¯GÛï^±¼ë‹kt ù5=;š~øâÚðbõ—m•ÃðÆí½Ä8x!á¶·|ë¥è;éô¯³Nÿ {ü€_âÇ·Äq˜³¤„Ù© gzN/_Ìþ†Žˆ·Šá݈÷?ÙÛºÄüC{þ%=ï6Y¿iû$ðŸ»Ië×$‡÷0åa)}Q:_î?ùüû_ƒÄendstream endobj 508 0 obj 4394 endobj 512 0 obj <> stream xœíkÇñû…q’?°³Ëôsz,9‰-?âÈ&‰¹HH˜‹Ï8Ç6œYþ頻®î®žéÙÝ;ã(Qb™íéGuu½«z8î7ê¸Ç¿üÿ“çGw¿ŽÏ^õǟÿ³£Žu8æÿžÆaùÕ üx†o`­~ÜôÊ­à÷?àGjÜŒ£Yýa<>žã«Kü8Ã…ûè{¥°»Y}³ÂOšã›®[Û1À˰ú Œ_çc·ÖЂÇGnÜ”ÆGT€/¥ñÏr×o¡Q÷´]½Êß•ñO ü/òûgåý›Üø´4ž—EÊïO«÷ÜxU¯Äƒ x/f…tG˜Š?VƒæÓ¿jÁ㬠xÀjj²Çke6Î÷:žg§¹ñ"¯¥cŠw þžäÆË2üyn|Q¯rã«ùþð÷$·výRîš`ꇚ² çe€ô,#7Å­„+À‘ÃñÉ—G'¿(P~¾´8céeë^•mü&÷á ¸¤%Öj6þx­ ”D!ÿQö%sa°7nÀ½O~p/,rò{7„,kŸvÞ*­Ó­ÄSy‹ô:ŒcÜêvû–¿ í^œ+Ü~ë’Ãeª6e7(&QúÌ/J_XתƒòÜW›ö7D:£„ †áGÜ®¹ë,mÇ0‹©à¼ÌÈ„C_B&¶·˜k‹û‡/¦f¢4l[¬•2¥œ ¢mߘHAL¥E†ó-шQÔš„D©BƒcT„{yÒÁ©YçIÊЬ»!ZåÈÆ“Û†w‚¶æLdIKŠÙ›¤ÓX"ÁÓr¸ŒÀ-PÃS7=@“ 0Dˆ @•ž4¼ö°ìNã#êÆXqsUh±Ðs|¯ÇÌèàòôí[„¿‡ 2]4»´Û1=縄•t`ÌeDKùvQ ,Ô /ˆøµ9Âçꜚ+0î È í);â0iØrIó¦ 0}?Ž‹jÄ€íî€æ’cÆñ6á×X$3M_H-*àÓ8¿×¢î",Ð-q®¢rc=p¯Z¤ò¸5»Ê tìQ´0™‰à ¡ÙQÎ&ù©3ô„Ò‡tÈhÑðdŠG°|ìMý˜·tZál2{ ™!ctÿ®ëa2¥Lf:”x‚W@Ô‚‘íÍñ<™÷‹,Pö¢p+Ò¿Ðÿ64…šJtÂàD­ÑUk…™­…,‚à(K6ÎÆQ( jÆAÖë(>2M¥l¥Ž H œ¬’TiÞ–RAÿ¥7äÉÍTØ>ªO¾Æ¶tA>=ƒ»˜Ë^¨Í‚žmäpÜ˲ÁqdpîœÌgÔÔ|¶'5gÔHÐ5y{o™7à(kÔµÑãꟂ›Òë·B¼î4¬¤2&Ry[¤¯ N4ƒ€ `ÀêÏ`’0†¸!]i€ä§ÀÛC1-¶¨F®¸’Ô$­v½K|%pÏšØf-Wè3–³~ÓgDøH‹$‹Úä7«Ü æ5|6Ýö ,í~ŒÚ±¨†Cmî½Û&üÆnÙ(a³ 䩘­å¶J‡Ÿ'gqK«­ë™ç&£WÑËÊÂNóØÊlé0’(Õlô,."ZÎSÑWǜĠtÑø¬çU‡Æ:мRzJâb©TðÊ$Þ[quÌÝ«i”mWW=¨pKbdC€«Ÿñ£Dø0йú…cý°z¿„ßPäsÒ¼Ïá÷ü%OˆÔ›&»g0ùå£Ý¡Ãj[&Ìë.§H2œ—è¬él÷©ëÊ)²fè'A>4wìp¾èík¬¨7AvXôŠx]’3y…JªÄpá¸(jâDA*]±’põ/{© oŒeaÔ@Ðjm€b„-ô$ž“âw»‹ º)NHÀ‚ RnLvæ|shS^šÏ`„¥Þ\‘=0GABf¯w_Ü©x~j4BªæÓ“®Û¦ðM'ívnK€‚ Ð´m9K^§{|Í81á-JDhä,æßÖ ƒkò^n)º8EëSÐS’% ­Øhg--ÉÔ¬‚¡–ãÊ,‡Þ+—±1ZA›u,dÁËOn2é‹ öÆö0Øœl9³eꦥ»ÃNM´­Ä„§¬˜ŠB3!Úð2;zŸDÀ..ŒÊãã)Ê0%h£iVKn/œçë… vñÛŠ®'/íÅÊÝc!ii‚¤™Å¸K €ÝkiŒºdƒS£H]Í×ç²'4Ïö!¨¶7ØâòÅU‰ù!/£ •Áÿ]+$ã| ¾miåt5ÂÜ;Ò?i­(9åѶnOÍT|7É7IœÚ»Wj«iêÎòµÔÝr&ÅŒêIÞå´Ä¡|?6)^dç&!—â›i0äú‹˜ fVEM­sÞÀ}ÒuC/ ‰W˜½’‘ +ûÚÖ*ïZÊE( T)©u.$1FÝ%câépýŽb3ô¸@X`¨YˆP:Íï"·¶iiñÉÛq¨¹Æ À5VšÐ<ËuL)!rGé¬e±áû˜Ä‚‘åˆ3ao¥é]”m•6d Õiö™B6úP§nÄ6+7·Ì…Kƒñ2„eÝäßQ¢„ïuÜò˜i%y¬¿ –¢“W»¥œ°zÎbÌz—³CiÃù²Ïš4ÊàwkîŽf VX=€iûÞ½Ž»_†(¶ª 5WT1té7ÌhbGÔ­áë·‚î9´æ\#´–tEŠÀ6]OÌɵ%S½SÏ3»hË]Ëžç{øõ~|Ô¥²­/ðã>û–ä—‚8¡ò”÷£+ù¦8£¥…'ü¹¸£ïåÆ{¥ñ£Üø 4~‘ïKŸ¸í×REØJÿ¿¸™Œ´b \6éAð`m›cnkWÀ%ãÌÁSÅó¡L[I÷ï&ÙüY†ÝŒ1¡±Ï¢f^¿V"ž°b†VƆÒa;âÁ7XNèo)—ÞÚSÓ=ÞrˆÙnT1M¼äTA+Ž)¨‹p{~hø«ñí\-U¦H­–<Öš•‹Ë*D×hÊÃ.È\aZ0*æÙ—m‘¤ß#b¥™äR¸Œi4”wߡىÁÐb 1¶žŒ¶D"¤QøÅá˜ýQe*Écؾ(®mG>&E+ç3ÞÇ“h†&ë¨)+*›( \4(Úu1 ÚB¤­/ôS¤F2£ÑÂ/½˜6‚#³ûË1™§Ç@ÖßiŒ;¡6/b(p„S±@˜äØ`hL޲­BâÂ(3 +$ym`7ëì€â¬2’jv$;sØŒ‰J޼ìˆ[¦êkÅ-gQ÷Tb-E&´#ÝÇuoºœ©­M%)çIuÜ)dN_[ò­A0ê’¤£Œ¦\ÖÁ5+‚³¦*­+öê4ªÝY²³SÒÑγõÓÈÚЈt㬴èg¿Æå̹2>–2;ÔPÙf¢ò™²!ÛZ³î‹9rÍ¡ þëXÌò²•ŶÏ$DòðÉL%0* 35Þ˕ƹ±²Ók•®(ºKÕ¸áúzÆÌý-`8¬à(–›7Qmî¼þn,órËæ×Û֩̽‰T.µŸ@ÿî |ò+‚KÛka2¦²¸¦þnhé¾È.]?b‡ŠaÅ…¡Tš‘ãÔ2- ˜ë‰r®o,‰d¡Ïf• Ê87n¤_*çm•®´ yQ]¸XzÚ …¼ÍrýrnÅÇâ‘EÉÍòõV3 ÂÛƒÅÍ€TjœøÅUPà!íþz1FðµJ&c,èÏ«Ú18 v!9…³©SˆƒñóNê|É£ò2KPºœ‹'.‡¦Úá›ÓÊ6:¼4^¦¬#«Îj]a–¹ÕìZU`¥FÄ1–6ši&ƒFxåKÀlüÕ@ &ˆÁù²O Ê”ò(c(çpˆ3߸óòƒÃ£€*Îç–ç ‰ “U…ôj2 1¼*þOEßÖï3€¬‰Ô[2‰{ü,³ÇÛ]—“ñîE“p9ØØâH›É¢§l­õ¥¶²6Y/ÊUÁ!Â_hå‡s½¿]ŒR¦ùßðI¼ÄQ{ò)²+Ù`E²*°;ßÏj)çŠÓËE¡5™‹ÂœìLщ¨ö”Z#­Áq£ã¹!.m,‘lÜ­°2+<óÿ…‚K=[„/’ißa3˜ôƒm Ÿ±É¢˜­Œò"’³ÿ.cß›ßeÄâY±EµD½xz!¥ö·5ÅNÌBNBzOp€ Í 1˜ëpÀUl¼Á"yí@EÙ0â”ÛZZª.OâÕ¤ºŸïBbÔªQ¬_c¶k§b"— -VV!¤µiv½—dž¯0b ¬äßr¨OÁ@³b£iu}ÚlŽg½xç’m*8©*ë2T©>®oƒ1n—’×Kʉ‘í¥•'Æ[HAË¥ôr*pÂ9àMóZKu³Iœd+T-B=ÕÁÓ*ÇmÉ‘I㜩³2â‰ÉT ›=&ZªÆ²NV2ç û»0þË âæL+ ]•qޱ*»¾ÂÈãIA~â¤ò#³È·¬±b™47¿•,MõJ‚Z éË´ê²·å*“*¤È|¤ºBDg׬mÒWZ‹oÊQz-ŒÀÌ}Xº!<µ?R™‡q—îç§»'m»«¤E*I'÷èãŽZéŒeÓvÜDQ âëªá$†¹ÃDÔ‡%«.³òvÊÀ©;ó ž•­Òòé³"µ@ÅpKÙ¤†l¦uÒ‚zM-ꪉ4>c’Û¹Iáš%¹{CN¦µŽmõ#vsš«z}ŽxW¹ÒœžbFÚdØÆ›ÞŽ®½–e·»®û§X€ö²rJÄS0ôFUfÒr ë’pI/×íúéïªâF«¬ª^'V¤‹;™k[Š"ú·Oª3¬Q$Ä x€¿žcLݾâöŽjc5­NI*™ôG»qÛcv*¼jU¸ 9 XùmµÜ<àRZlL·Œ2·HËèvlj9ýNîs~ m§YvI{MJ£ŠWW¹%R‹ª·XŸƒ±|xD ¯BÎé> stream xœ½\Ys$7r~Ÿ˜ÿúiªb©p£6bì½ìõ®lKܰ’(ŽÅaHÃ¦Ž‘Æûë‰3t5ÉÙ …¤f G"/àû‹e þ“þóöÅÇŸº‹Û_,€o_|ÿB„é7o/þå  OæuYÅÅÕ7/â×âÂÉ ëõ /¯Þ¾øbZfÒóÕÕá %èrÑójᣫ×Ðð7‡K5;·®bú׃˜×Õëuú烜þóp)f­“ÓUmó»øTi?} Ot;yk†çR®³dM>/=n»ÀŽ?q~{г÷F[úâ·Ð\šY,~úý?tÖMÿ†ïýª”˜þt¸”Ø^i9ÃH¡#œôŸ¡±µÆ¹ðRawbúìpià‡~úŸƒœ—ÅÀ,ñ‹«PL ï·Ÿd$'ðe¢×%¬Õ‰udþƒÎ`fjú'fŒwz:ÂÄ´›Wo§¯ÒÍF/jú?|(g)Õô:ÎE¯fú_X8LOÊéxºéhù.¶±‹­Cü óÞÂÄ?‚Æ.v†ï{£áEýâMoÌ µq³Rö=ëô—²g?b=k¦»<û¸>حؿSŠ÷)̶~’_?ÔŸïêÏŸð#? ¡§—õiY:éó—ÊE¥ûïê˜î2Ãò¿†f~ÖFÚð±´°9ÓMXºT:P‡Ìä®”[¼> 'ÈÕÎzYRzƒw‰pb3À7µùC‡½/ðóárAr«M«\FfÑÀ*ÒÒ¾Þñ%|—[#é.3í.…‚-2’p#Ë‹I5x, ’*WZ;à„̽(+È®r¸Ù O¡àà’¼uè1î9‹zWm¦·(wÖ:«a ¥ÖÈ F«k…õ®#ë7e:°~P+«L)½Jü:.Æee•¯«¼nÚd–Dy]—Y¢¦GB»úÐ+W@ÞÎIeeõVHhuiµ,~w UÖ{¥©¤F‘D¶PRÌÈ I¢øêÜ „3Ó«<qÀ?â>/¶ ,êØ¡ ¤Y½*,üPßW¾~¸]¬J†‘¼‚m—Ó·¦ Ò,bñË휃ۖ6Ü ‹ÄT (ràé/§21"Þ8øë"AN2E‚œ˜ÕGƒp<ªâÒãAù¤‚àÄ%y-óP(·hìžÛZ ¥Åœ ÅUUÙfÜÕ‘˜ôDIÓêásOùçšÙœô—½-LÉ÷•3P 7 ìO«œaPÉ5¶2¶ÍùÝV]WÞ¬¿oe‘üòPÞ`Ñf ä÷à&çʪŒEA«]¼'óÇ•Åñ0ÔSøá¯RhϘŸ­Gå¥*Gè4n n?n)ì.(è(€“&oQÉ…¤¦/Jc…~•ŸjÇÆïñ??”vâp¹®áwè!>ü×z$«¶ü©>¶ÎO?'OåéWùWIÑufß°qߨßPè‚jM(ÍÙU€[pxQÌf2nÒ‚ì–¡{Ôï‰%Igá’ ³À³Ñ„ùv¾1a@8F`&iHªtVÆ¡{jy¤ª‡Ñ­È–±Ñ Pq # a`BŠ2DbuØè­•C¥—Qgœ-éü¼Žp ,‰°Ná‡V‡Ù´ƒEƒl 9‹»Àá Ê€™$ü{ /ÁEëõuOû#c[ð¿„š¾ü¡6@òUn2e~ø Ãi…àoË–ÅæuS#”ë®%*F§ ª:,Ð*‚«DI®÷o'[hLÖà p&¬“½Éˆçgbï‚Û•ÄF ŒÇÏðœ•ç9fçËw’`´ï‰´½ÛZaƒ©2w¬#|—ð9!0˜S%¨æfÂä[ò4ÙšÅÙ„À""C5 ÆY+1Ä>¹Ëž3AMFÕRÔeT˺q”+áöìŽx—èªHT_zâÆ ѰÇå8%AZÎü 8N5Ä]y~j‹ŒðK­+wSÕîÊk"i•ûÉd’’ÄtmÚ1DM^Éä‚DêphÕ•/^U]„ØU¸‚^#ŸvKæüè%õD2/®}• ,é¼£=$ÕV¢9Õ R ~þéÅÕ?}1y m8 Fq†ÁƒªåÙc  ,ö7à+…\r ¯BU“?y‡DT”P`vòP(RÚùÙÅ fáü¶(7Å {«ü:ý;tj´ tjm" PÒЪ€Eâ†Éé€5Õ”ô.ôä¡S úÞ £ßq~Rè4ÓE£ú–¸cÂÔhGw¥aœ§BMÜBXT0Ô0{1Æ/FÕ®n‚uw*?òà/ë7ä}¥Hœ’Ôô›¸L Rp_¾î¡#…–ÃKq; ¤è8\Ö>º£â–à©ã@«'}&íæch=$+-áT*%ÉE2†ºHÉ'*Nõù~¾p:]¸¹D¾’EÖÆ“ž*àºkätãj«EÀN)æö}mYh‡ŒHƒGÑ d12b܈š>&5Ž­³ï¹äI³YP9<1ˆ=¡&[T_V0Aâ6i* åŠrW+Õ·U1“éà&«ëMX7±™qµ;ĵ² &@Tä:24qÔ¤æõ8bºDiúñWœ§Œãµ¾ÿc8;k| ¸·°VÅ8¶‚ØÎ-¸½WŽ…èį'-¸ó%–œ@M†/òL8dêÀ‘žô„V T  h‡õžÇõúRÇ܆$“n{cJ Ï¬ÏÒƒ+Ñ]èÇÉ5r(ülÐsñ™ì/ç6DjržÏj"0Dec²oíT„µ#Ï8/s\ Ä,l °%Éhãá̳VèZj _úÒŠ6YsA ÁÒ–GjýJ>ÏêÆº´q;/)¸­|Ùƒ´m¼6·¥ÑJ,/@WåÜtHà4-ùÈ9BÀ˜R->ôœ(”Õ;N({à 1fZÊ o¹ÆžÓ-¬¢ÝÍÚbKÖeÏ>7®Ý 𜃻vÀ–÷)DëçR’Cb V•äÔµu­è1˜`¸>‰¾žìÓ¾+)Û”3UÔÖ‰!FÑW”Ù{æjaa.ËÌ6í#ž÷äÖ…P WC0to/úÙÊGrb‚õ4rìL yç)níì $ Y±Äö ²2¶427˜HÇðZ£ä)>*]AvÂ`ב`ëª6EÔΘ’ÑüÿR„>«“æó¨*•h†xIRLk»ÙBpûgi«a"]Îkæcâ_½2*· ¿2–†ÿ³·²QÎÀð$Ф³iÒ6%NqvœßÓÒ9ӌޛ§%ô«‚*QÖÕÛjÖ¼l œ€ãÆ£Um²,gœò¤\¤1æ4LÌzñþ#)³R9 `#ñ®¹åfâdÆFàp^i‡²¹k§¶#.…{iÊœ,ÈÂ%£Úšq`žŒ²¡ì¥ožî’·­æÅ ân+«ƒ'Ö ð#Ê5744¾‘™¼"n,p ’\N+èE‘À4¥YŽ$¢N…Ÿ2A82º®ÁYd¼^‘‡}m¶ÙF7u/‰~K´¿§‰E|(+:¤ÒÁƒÜKÀCg!õ½±—Mx¶‚Ò3D®ˆ%@ð…XOe¨ÃÞ º’´Ó2ª»vz'*”°Ýñ*ÒM½"òX|F )ê[Ÿ *„ÝÒ…ÙSIÉxUc”eKœò¼ ¿7þóíVÎt(‘í'âî:ðЬð£¬ö5G Q1MÝ©«=%¬¤:¾ø^‚ŽÔ6ò´&0leÐvÇÌ"õÇ7l€Mˬ#R&nhu¡î€BA –g¬ž³¥¯“¶àFI¶À Ü´“*‰qru`j*¼b¹›© kg îïœiB»hÔ‰LÓ&x£tKÒ˜ZÔ½:BQCKÅkç$„Ð µ”[±SÜ«=½J"#Í"Qœ• Ú}Oû5œ,)äaŽûVÞ+•›¥´Ð÷=©fgºRDU ·ìÊšTÓ/]<ª¸¼8cú:’naeÀYƒ²ã –J¢D ´ØzyUwmŒwb QÉqªÇlø+Õâ|(ÕU¢!¢ñÈU¬mër/Q׃’¼ÀŽanÜn5ħ+^¶Ø ¶%à½ABÚÆËDÕ‰%‡®Vx¢œ÷ÔvƒZËð— ýbáU‚^‚u›v'CÌÔuúøS!^¹êàK±êÈȇxšc?ð«Ø)ž ƒ‰?ãÂæ®6ûÅ#ȵÚtœ~.ÁÏþ€§1ân;F†e`d ö®z]kƒ·¶w«ñúV¤ç9]x| ¦¶qAµö¼£qWÔÊ x0 gÔVÛÙE<<С°FPú‘•T¨Y+ñ…¤óz8tÓ<£=4m z·!=Mª6¬ö2–&øMˆžTc#zÈ‘Î^o*2lÎæ”y"ø›4†í­í㻇Ú晴o.ƶ´kR%:êáGèµq³Õ§ÖˆLÙþ¾^CÃ&ÕPÒúÚ ý9LU{<ñg¦ÿ†o£a FذVÝ *V£hOÌ;;Üâb•r/Ü[GoGF5ÝM›çD•Y{1²T®øV¥ço»ª%6sTj ,Kþc5é”Öò¾¯«Ü¹e< 9è!â —‹S økO ÅKÎYI|'–êÛ›¨ríã¶'4ˆmrÖ×Èb½)X3ÆM šÄ…óÈoe«÷$LQ¹rƒRn ±“zhb>aôf€¹ñ¦p”#ÀOõ=…щ@ó9"ƒi×÷zYòø„Ýòß„BªE7Ç.ÀJœB[מŸí¤2Ú¸ ¨-· aOš2‘æ^WÏ#+©Ïå3¯‘VݨoÒø*f{ÿ¦¼Žy%:]4~)¦,ÆR™Â»gÛ¼«‡C ™)ЋõK4;5ï˜!ÛJt¶n–×71A€®÷ö̰ê¹'[¬Î±ðj!1Åæ¸VRë›Ú-VMÛD™`5¨*^w˜±ãüvRŒNRÞ;q›XSxq)eŒÉ<"n³¼–ÅV†Š6lAOIOè=rEs_l&øáèý‰â÷ñÉ÷lïE¬ýÛ²Qð0ŸïÀmõã[ò¡³¾Ï«R#± Þ+soPUå'4,Dzºk&ÛÃïì(Y+Ãç«l¼Ì\þÔ=ÿ–ªËâNÚv'¯É[=ÈõÝlEƒ ÑÙaûâñÆq¥Þ8$[ý-žÏ6Z’$Ú?æýO²—¯»Á{õ\Ë9;¤Bùïb‚Š*§øj|ƒ¤©ÈÉí˜\P࿦ۇÀ꽪7ìì^8ã×úœ˜Ò5$zÈ×ùÜ3©Ç n,»ê|qôp­š¥8„4²–§å»T–‘CL¤:b!¬œÈ`Õì$‘œwµ[ 3Â&¿Ô e믦€L<÷âføšD;7x¯jª IŠu?öY·dSÂìÇe"wð>©û E>Ûõ¹ÚÅÝ…#®‹ßiiü)vOa¯=Ì·ÇmNí5*%Õ*Üìè9,ä°Q7Žv~ɲ»³O ]"CoS.õR¾F¾NÙçt˜[™>ÿäC×î1uVúP73•Â<‡ ø¡Þ\¡Æ‰¢|Ê—+/‚ú'oœÆ°Uºz1e˜›pç-QʇɮÛÏÏËÅö«–K‰#æ´Gò4iTvg\¼K`|+X¦J/IT6\œt‚SëæðYœ+ÇØO¼© îa=Ðë>ëøq*¹àÓÇ(å^º±{»jfªŸÎ¹]]z~,.)ü ¬—óW4Æf<ÓNÅËæ!âä4¤<¿=º˜ë6¥ºCÓMk7g78–*•Ž…Ý:§ÀkáM†:Qy:R„—½û€ûo’y^¥&Œ•zñSpá|ñ&Ž‚±¢A;†>‡]ÛÒqHÛ³ÝP_ÿ^Ýw­4'mÄdc,btÞý•<ÇÎÃ&Ã|ƒM¾¡ ªA k,ɘxéõ;·‚…ë5\y„©>ž¡_áŽìP!ûÑqê¸ÙñþWrw»¢+=ãÁRÑ|È4Rã8'ܹ³o_å÷Ktnñ:À«> stream xœ½\Yo%Å~Ÿ å/Xâ!}·éÚ«"E YIBHŽ"< ö03ÊŒ=À°ýûœSë©íöµ=$(`·«««Nå;[}}±­ìbÃâ¯^>zïcsñôÛGÛÅŸáÿO}ýˆùñ?W//~w ƒƒ'«Û»¸üêQx›]~¡­\¿¸|ùè³ÅÔ²øjŒ ƒ_6ÿàh·måÂ,¿?Åj,ÛÄòü‘ÃC³|x8²Õ9+Ýòï_þ~«ÖR«å#Ãíº1µ¼øþÿx$ôÊ6½ü-ÌÀµ^þˆ3H© _>…Aÿ9Ÿ2}Ç||8n«uÜI™gávù| –«ÍòœÄÂÿ¬ÈêuÛŒ^.ýŠsŒ~$εXFxÍ±Íøþ׬W~r8*xA:µü³¼§ÒFrøÉÉ,aEÍC2ôýƒÛ€&°öËáûdÏ"a¿¸ü+œ!9CXͺY8ÆËk8:'¥ %w«•G±­†9|‹_PÊh¾ü„Ûdzsz¹9p³*íäòÖm­æly sý«ØìÊ™&xV(‚c^æVÆäòcè 3 „é&¾¯Äò߃ð+g‘>‚] ‡—}ðìã«Ð‰)šLà&–Ï¿1Ô ³m,ŠºSryš{eÀÀÔ˯ò³È B0ò2–M‘‡Å-2†ÒWÜLI_'¹3ò°d8íJç½Î›¼ê6éE#ÒçÈð47È9MºDÉ£dÈivù²ð@æð›ðLƒîxG¯BHçåJ8$‡k„‰L“¹±ð|”Lküž€s`†Àº7å=8JØÍ*Qa¢3Pqççi¡ ·¢6çT½‹öi‘1Ë3¢èx6Ä6ðÑ A…Y‹,]åg`M´q~‡½€²P‘É \i[‹ê?¢Ÿ¹76 e$¬‘+üŽN¬ì_”Át¼*¯¼*òDd öœr}U6Kþž—YÈ‹”ãfCiJGPŒeŠsŽ MôCa¼ç9{ûb82¾­¸öo+ç Æ‚©@ ™ðÔÈ‘‘Idœ®¿ü½;¼øRQA2à“I0ZŅÞÂg¤“~)äpfŒí·£²ÐZÁ³Ð‰pm——8‰^µÉ6•@ð½9³0þXŸå`þâG ëäV£®%„,Òr{ b©R«þh‘‹qý`„–À!pfÎ*¯Ò¹5Ç ÀÄ †AÑÂ`NZ©'ÅõëMú_‹¬*ró ~ÑxëC6VFŽd€èƒ§YnÞœÉ(öRÞÔç‹^®¾jxbêÎQz·põ‘†Õ€.èõ"è”›¨$7-WX~#û%ËŠ¼Ç+ Øá5-/ŒQ’üÆ–ø€ ˜BzÜN#áBõÚtHà θwzn #zß3ømÔü¥ðvmQÒò1~ß F“«¹…yƒhxrÕ&£°)¾@HOÏxüG‹„ÈåJ!Q°™­˜‰RDÍÏãV3ÂÆ[ÂÔ¢cw š5r— ¸Cœ™=t`(+Öè ì–ï[Š‚GcŸŸ“¹nƒ—ƒJ£Ö*3\S­>0ÉUÒd„>7µµ‰gµ9d/!N÷q y+’æË UÖz‘Ÿ!ÁȪàTU'ó%ô€CË„oQ3ÿz]„¢†ôq#GfV-“^ÿ¼fŒ;'ŽysE5ob—'?¾òv-¨à¥k½1°à¡»ŠËd? ³è)ÞÙ¹ËK#¼]%9u[¹ÒƒîyÈç<¥t+\D¦ï]^@Êß(ŒÊŽÁPî…¨±§læëÎ]4t% …]‚,WʼnŒ§\ßL† »Eï‘Ú«²$¢ópÞ›Â}Wœ]˜÷iTñ“Åa}»Plàîjêñá' ÃGÏÕï©ÖÑS½Šƒ•#¬œk8âžÆM:‡Ï‹ø¦Ïï# @§ŽßCͳI%*ŸØÑt¸>èFFÞ†n`—Éê'ð&ÚÁ€—lΘ÷¸ö¶`%è(„GZütCmd§}1Rê¢Â† fRÃMŒ@Àòà¨$V¾+>IgDØŠÈ.Z mQý›ÞTsì8ìÿÝkpUi~OšÐ_–õ³¢£ŒÈ/ÁB®ø£5º2¨0”´þAG1ÎNâr”¤‰Ç%”ñZ¦7 ¥O6Á‘F_ò!ZDq»9BÜO5)NÆjµ<$ТŒç¬ 'â³ y4ø:»þDDM­ õŪ³¨Œ"<ô™ÐÈÀ4ÀÒóB€ GΡx[ã #}d­q˘„óEB—>š\‰d©§1Ì÷{7‹Ð²2ùOÄ6DRjÄB>–ÒÊ5+O8Ïó†ˆÁ½¡†!N†<ÌÎP>Z3=WDÚÎQûqßµÞÙçJäIª©4´ù0ioGBˆ‹UeäÖaÚLƒÙ‡5œËŠ5Rö±ßÇ´6 ä:üp½É…ùf3ç°~YcpÈ ’åè8¶ f:»Ä,”×Gkº ^ŽÆþv8Hç’h,ßþ²ðW§j¶/ϧÖQd"=EH)ºY‚]Ë#hæ¶qƒŠxú Ìšl:šŽÙÇÂ{Q:Ejñ ¶Äž›”•z±ò© AFDîøª”E$#ðAæX?) &å9UýÅx8èÎO¹NíM„eQ+‹8Û’…Ðãï_å¿!àEík5òM|ø²<|’Þ”‡¯q1¾b€wÓߟ”¿ÿ”þPÞæ‡ß”‡×ùá¯ÒO^†St!Ȱ'Òø/,¸ñåná¥ËL¸ñ_Ÿ¾Q"=Ë{^üm~øzgk?ýÜDjk31űjC]vÛXþ£ÔÖç@O•YJe¡Okn/j‹Fþš¨ò&ªþçs>ØwÂD»J=з –‰fè!2Ö¥¢âþšH#YÁm£›ÂÚ•ys8: Æ‚)#§>5MØzzÓh[)‚¶êØÊ£ áG•Þ ] ˜ è_EÂoå6ÆÇ:7q‚ IÜiZ¤þ<îNÃf‡Ÿžë¸£jÄ0ÇJrØz£1õìf= 㦉Q HîclUP-–Ÿ(Skü¡dÕºº˜a¥Vú¬g—™#Eи¯ÿf@°ØS4~(zÏ@â׌µF°RQ9~\Û?bûg}õB­Ò³âÞlý;óÉ·z¨Å“.Ô®½)eŽäAãVÛµ€ýK]{ÀænÉ~ŽÍŸi¿fɵbÐ2FÉݶ)Rñë±ì}ÊR£ ¥ßV ^ï²N9^Aõ¸…/¤nê%¤uUôs;õ›“¤Ùæí&ùÍÕÌ,cá·Opœ×½ŠTÀêi;º×ŠÑœ« “Ë• ¦ °¦!¬©F&5’ « uiiÊQºŒ$/ÖÉÁ*w™61Ï‹ »åÃâ¢J¢|(S£ØYhᜦœwjš˜¿ÝR§‘p[[AHÐE—/Ÿ(¬(¨~-‚eÀùO6ñ¹¡\!qÁú 5þsӼп'ïÞÛL_$âQŠp&ºx!X»µ9CÑX·eÊœ,¸(;²÷.sJK+H° À¥“šæb\(ò'ÑÄ“0 î½v{ˆÊ¿<™S5hIb9 ìŽux#ļÚÖ÷Áj=áÔ@+¹½‚ÖĢϼ @zL2Ê ‚$úÇPSnéÃtó^ f4Û=.²:GêˆÎõݼ…Fƒ>è)Pgá2‚ûâ`,ü½}õ`§'X=ô±‘´ŒëdtUøÛ¤™-*»P-Y‚åþ«zXU§Ó]À àÕYÓˆ#¥•wP5àyæ7Š8YÑFx‚Õ6"V³!{¼¨Ñ$ Jó.Õãˆj ‘tèéVìºSnHݱʺ‹]ן˜OdµÊ烼¥D`,Ù¢`8WèŒ[V“[ ôÏ &5Éè"¡GEø®3ˆ±\— ÷aûºå)…§š2æût›&¼æhÒ0Åãrü€´7}·p­±F_¿Î (޳¾”,UÛH3òÀb|ñôOšÅz¡su²G,ÜÆÊœ‘&*ê"?TìÄšú{¶iy©Kówµ°Y‘\nSA õ{QÑ΃ûV !å¡N•3´¿Ð?ÛÀ­Êåž]‚¡YË›Šà5 Z61_£?¢!Pœ,ºÓò㸻o{¹ô±”¯T![®ž]²Ù AœÄ’f…9t>@)ø–©Î‰¤Ûî[Ò»ŠÐÔ,§ƒƒ[7‰™Ó—F¤ƒ ý¼£ló“  ×6HœGaâ} «Èá:b“-µ´7s$ÑwíŰÞXÇW´…þ†mߟO€#éQºu?ë=[Ú¥±A'‰Ëo¹ZgD€a¦´» (²]¹M¶ðä˜Ã¿È#‹eGld|·>­&ªzc­®‹sm¾ƒ4ûJbÛ¥*+4R­6ã}h“åËÆêXp#>è÷ûÌë^í&šü=…ƒûvx7³ÞØN…¬‘Õï®BâØÀ• bà}ŠêD&†yNóšÚÉ ^nà5^¼²é³¶^Y¯1È[] ‘5H!&R™³îÃJ›;Qü¤òÑ¥ø§XéÅp‹®°k–âˆ6 wr…IJ´JÙ”÷˜PÍTå;ÇW§”Úy\K ß´½ô œIÉ™=Ó¿4ÚNt|“ƨßQ±s 74ze 8t4ßA(´ì/ôeQSÁˆžÌÐîtµ4ºwèÐÍ&†…9à55ɼ°á“Ÿ‚Sð>1—nî$tH^#Ó9{°ßwóVüào=ÂPÿ¨h¶iËxVLwl#’² âUPä8@¤#‡Ó«+Ô‹¥z¦zï@ï?÷Eú›¢ø9‘X<<>Ltf—éW M[ Wâ•“ZÂiêTíN·ê¨ÕS¯•¾\C8‡ë«.“';-›Væî…ÂÃS]ö«¿{–,g‘6f­S™jª‘îÒ[m«:KBVÚÏóÇËGÿ‚þ?®7†endstream endobj 523 0 obj 5626 endobj 527 0 obj <> stream xœ½\[sW~wåG¸*Ua†Í4}îÝEåÝÂV’eÁ©Íð`lc\±±ãá߯t.-nõxlœ …™9÷#}’>©Ûùc»mÔv‹ò¿{'[^†íË­vûü=ÜúcKÅÛùŸ½“í¿ïÀ ¥¡¥éÛ^mï¼ßJ³ÕvÐÛ¾³ tîœl½^ôK·ðK÷vçŸ0Ã(>C·¶é=LÚÙ‡ÿX®LBß«ÅKÕô}gûÅ“¥^¼X®Tc­ z±Ccž¦Vc»ÅKh5°ì¢ƒ½h׺ot5ä·aÅé¸ð/°Ï÷KÛt³žw|õkTÛ-~XâÄàÃâ9öw½1jñÓr¥q¼±ºâBxèŸa°÷.„Øip9µxµ\9øT·øïR7mëà”8cg Óª qîoKÄe;.®ô7Ýö ®Tß'©½†Õ{øãN‚wìüâöÑ-¬ßÅë.ŽðÇ þ8ÀÛ·­R‹oaLÛÁ³8Çž]üqYy»\cú¦ï«¸$n’û>VÛåÆÏeã—Jh$,íT7Ýú¨ÿdh< •v¥=÷i¥ó¡—ú/«•Ú¾i•E9•þZZøÑšnqU¥|dÛ^d©ufñ‰ZÄÅŽ‡VÔ¦êL£íöJ™ÆùV'íÑÕÎh‰3~ôÒH#Ï“&ޏT¢¨à‚7 ý½$tRße5‰ö›6‚ømßE„‰‚:…z™ÒY<Êzñ±Ë7•$WE”:4ê^ á!ö5|ZcG(÷†FÒ=^Ÿ„ÆuqtŸ†BÛŸJÚ½’¦ÌÖ‘ìLPd1´®Ÿð™œVš.?ˆ:=Ÿµ×wI¥w¼ÏÄVÓ$“1ù²‹©àaÒGɯԂÏ~å@Ú~Ÿ/_T$;K’Ðû@V9 Že‹±±÷a,+ìŠóü<\ƒÙâ1aæY^#ÿا%¾Ãïß×ä0öå5vhË'Rã¯Cã+j TÎøV,p)¸Éc©ñRj¼¸‹>§þJ&µfÏÆ‘sé†7ã÷²¸‚Å®ÔxUá?ßðVbIó_pÀ«ÚÖrô?›„x´”Ó‰4k£YÊfFòb°ˆõÃ-~įOèÒ`67øC‘<ÿ†·hãÇvX€Lx¡‡ÆÇäo¾^o6¿Pãsi$M³>ÖÜh]«5c;_ëgÐ=’€Az³$!}G‚x°þPWÄëõ·ø˜>>än%ÚT:?¶©ìf±"š£œ‚i}”ú?@ωÑ}¡Gy/žÆ ù®4àÇÊC—è~= Bóìù@RG5dB£0¿ß•àxÁå¢ëô¶"IÌ9m~¥þ_¤à°SA´8¯ßEù|:Óöy% \ÚÚyøšéºž\ŽÓõnÂçÒ1LÌ[˜gs"}$)ÕàKÜ]sSgöý J‰4ÿ' ;[oäîŽ$q|,y‘’#­ˆõ ✛DLЮ«þ’¡M­µÈ.[ö”¬3Œ2ÙÝ!¿Sö*æ\gÒö—$QZ”‰á(‘BS¼t@µ±œ®¥”í\òCWÒéŽINbÔ£+I+]J­¾üÔŸœG;Å ¾Q¶"8¬‘"r½dVx…›ZðM0ùʬ ì“dWÒ¤ý2;òB@eå4¹tżbMÇ×zÐMy!Á˜¢Ä¡äHDãµ Búà‹Ó&YRãhü´ú™h¶ã”t¶Dú¨|Åpb¢7âû\H—³µo‰Jߊg䯝©‘‘úo*ªmû`u÷Kµ™&1ŠV¯Ùwn|[3Ã5$\”˜ˆÈœ‹½í›LbƒZó]0-E¢>SbÙ+³Ékr¬UË\Æa-ÿ)3¯¨sJ¶¹+ü¼yè~:ôÿFý”ðü‹_Ià94>%Zó»¤ËÏCã&dºÄ¦;¦6 ©‹1þ¹ã u„îwó¼æDÂÕ¿˜vÅÿ8Ù¹Q[×ÊEìˆÑìý”©Dýº‚Á¼]ÜlZ5ç­à0¥ÎûDºî”HUB¾·ÀVÎ$ã‹ÉñªÂÐD?~¬Ÿ\:Û”Ò’+ÿ¦òïÓä-³+ šYÈ©\(Í)¯;§¶ö9\|ÝÆOÈ,ì„;™ÈpÄî.'’+ªç’WÔ ÃâíRÌl§_žbҞůu(Nv<–u‹Þ‘Ka“°5›—’pN¤+Õ:)fvWeLÊm·ÀiU=/žã>kEèGЦfýÈ•b Ÿ( uÎøë®\ÿ>¡Gs ­ãéq%üõ.ô^^ɱ.td u¿…Žl×·Ë[ó¤Û×aêBðÑz£\”UdVENwMÚÁ Þ¥ÈQ?$}ô²ÛV¶1Öëø¢n[侃Ÿ‘wø¶N°/›¥A^£û…ÚÔr¥”qS@Tuã}4\[´Ž¥àíÂâÜ¿S^£ŠË:Çñ“Žr׳Ú:8(´y…ÚB:¤­ñlJD…±Ê[t>¦ƒ=Áú^Q+bÅ5]ë -µ_Z Æ»¼nùÍaý»Ð¯B×+v$šsš.n=;G’býBœ ÄT"•§ÿ³´øú”Mϸñõ*‡†lñÍ(ú _â‘©QØ¿EãÉu^ó) Pš±±^§qñXÄÆµ=XÙaZ]ÍÎ{ÛÞE4€Ö!Ý)³°uwé’q{©§AèÒ]t‹%Á†=è¬Ço†ÁùiAèPb˜Ó@beË5‚1qŸw´íq¹n¨]ܨχˆ×¾Q­§‹cä‚(ä¼cóNãbÑËN§û´ãE„º”¡åªåÒ Æý¬ÓÃrE+H¯Á“h•¢˜Æ ß6ÐåÍ>¦'Üóþæ¦'7*`Ä(ßhbO 0Ÿ·¼A—n‰ /É w6ɧ×AÅmÃi4¨‰m Ö‰A#¸hžæwh eíãaEÚ%‰¢Ueí£óZå»Öu‹‚ ¶ÃS¬æ­4Z÷c…úÖ¨B‚×E/Öu ï{çAë_U…½¨*0>)ÿ45æº^Ù‡&1N÷CÀÙ®A߃z¶näù:WtŽw$ÆÉF¤^Õe ÊBÆ{‘µ5Ž’T“{Íïs¢ @„Å¡ÜàqIóËob›åȨB (¯°˜>³à²ÀA²°Gm‹dH„ìž³vOÉð^»ôð!c`=%Šu@"ÞÝÀíaIñåÔ‘ BL€ÄDœ399¡@-Ÿ±@èG#Α|ÒÄPöKL†’ÄQJ¶XÝµÑÆ3^C¨ƒô'½¾9'µ ötÐetªtë¹oÜC´X€Y$4y+Bw:Ã4ÒàµÆ7F–×Áè`¸Ã©‚gëÀ‹i#ÃçUÖ‘nÌ& ×ýE—ž”âUû#z˜ëøx¶ézyÌ™‡œãnsÓ¡cÞ³’ÂØ tß7–EÝ·áAæO¤; ´ÐûâêqA¶5eâc'± ]/*¯—ˆˆ×]eü™Å ž™Þ©÷4m‘ŒÒÈŒäŠÂѰzph—oÃ$f­¦“¢ %®"—(EÚ32”¼­³éšG¢J’¢¦÷ä¨mŠ^½‰Å^ ‰"z·=&š=p"Ÿ;9HDUÌP0ÆåL«Ĥ Ž%¨L 05NTdÁÎûʪãÙׄÝëH—$OÀ0Ê" ¦?ÀÉ,‹VÁÜÙHðl·„Íd4HïU1vÑÓÄå0ôì 2a,©²ùšÉµ:2íÆ ˆ¾ó¬ñ9áËb›ñ<¶¢WǶ(Xg&"åÅß,‡ ÃÙÐZ’䦇!|СàíѨ*Ùç@ë+\xb—âÏ«LXýœîKÎQ1w|ìÞ”ŽM"…Àò¦Ó ëç9ON1DªÑC)¼¦úƒfˆ¥õþ¹Ä´Y/‡N”ÃíS“|ßwÙd<ÅäPªº»I»µíœ®–`ödú3‰@QK^ñÜ…™Á͂ބ˜7Ì> ÓΧ8iV6 ?yÒ÷á}½‘‹Õ)·ân³›Ö8tµÑÈhì4jwÁN\6 ê䨰*e·UÉ ìµÞpp‹Êp6MzZJö÷¬’š?øGð®¶m“Ó~7¹|áôĸ~_š¸§Zð”¨àïiZ‰Ý ÷b˜odzR€:LwMõÁhÀ‡_¹«­ ÜbÆ^mô¢n¦V‚®¿¬á;î‘ïûY¼Ž‘ ip¯B Kã“J¼–Œ+jÒ¾ÙÈ|Ø©Ùb\¬¬x{°|û¶|J6ÅV’£$¼2‚[Z2tž#Ûb}=|Ñâ8Wc¨}[V–{†!Ku&>Go1d¹ü›†éWƒïù¯<âÛìÑœ}ùhàœ¤ÓÂßaù¥P#§ùBÒ¼'~“\ ¨Úþ…¹”œ1å´2oÕ¨œ•2à•v=VHoLŸ’úô몠„^÷À¥&J@a`°‚ Ùþ(IagiÎÙM9KàOGõ3V ˆÒ0TÔ¬¶—$²:ÊlPÆš»/•ƒ:EØå^p®àëÓs V8ų”Ä‚T²ýù¢OŽ]ÆÛµp)¯1b¤¼›B‚ó±Ô’Iø,b½‡ë„q!˜¨Kñ^Δ^!CŽ +³ÅA>Dcê, é$êéÁNéfùe.uóÀûúžŸ‰ñÒòñÑÒ"n|h p _¿O²ª\þYG‰h IÖys$ß0 T±T“žÌˆ)Ë5P“ßÉ*ôçt¨£*k`»5”‹Ä_2c‘á1àþ)W¬’:Ø”€¨á £,Ô¥‡Ë£²¶Å0Ueb¤Ø§Íë'¸ª²w / ¹¶Qj£`œ‰EwÛ’ÏêBôEnøÕgv…%Œ^+™_Ey-#QTm*¶M¥ Y>…צ·PΖʚáОç´fÍ•â)}ÇËȉpxÖ< AO—bOPa8²fSIBªÍ%s3tæ+}ùÿ=t­ÊÚ ìße…ãó/Ù$¤§…Ób‘de?`YSm@~ª«ìÅTÌëŒBy*<ÄÔSáÒàOEOU±´ðø!à“§ê2Ƶl„ª‡$±”ЕÇx¯HOðAvÛúø–f!†+8䯦ò.pTßt¡GÊF•«b Uî sA.ìV7¨ïº¾PTQ§;[ÿ†?ÿ]·ˆendstream endobj 528 0 obj 3869 endobj 532 0 obj <> stream xœ½\{oÇ‘ÿ_ɇ`œ ÞõyÇÓcœ’8Îå|vb38v HŠB“’%ÚÒ!¸Ïžª~Vw×ì.%ÝÁ°½œééé®wýªzžŸÌ“8™ñŸôÿóï|ô•;¹zñ`>ù þ½zðüNÒÿο?ùí) R®L˼ˆ“ÓÇâÓâÄÉëõ$äÉé÷¾Ýø­ÙL[99çÔFÀ"\Øùyž¤r›¯¶JNb–zóåV.“³Ònþk»SÊNR.›?lßz;ͳߜÂÀÉy1«Í§x[kã$L¹›'¿Ìn¶ô©/¶ró< afë6_owÐpçÏõÙ4Ò~ó»0¹[‘fYÄìÒ‚º‹dèÃí2O³yqýÐ/ñª”ÒZX˜–Åëåo§rÅ9a5Ó좧@ňæ¶&ô'4Fâ¸]¸SóäIJÄñ~;OjYlc‚·(å…Ê—‹‚¿¿B©Ék ¬Ä(ëÜæï/ÒéÍ °Ñ:#Ó%áÄæ‡íN­Ð›³­ž¼󲹆-z ‚—@äôÈkxÄ(”d¸óÎl^nw 'f¶ôáWy GdŸáççN?ø–²ÿIåæ%\Õn2@áð J³ÞÜn•›Kù î[ Ï-›Ÿ×§®³Œ¾{o¥€‰4ÜRÒyžæq7õÙ+˜¸°,Š<ó ¥ 4|VÇ’©êØ(Æ€ðçŸÞ‘WÝ÷opÕ~ÒjÙœ‡ç¤B²ÕFm!áá¨P&‚Vý ü3-B/ŸÉK{Ú’À)E’眰up!Ük|Gm²B\ú÷($Ö:àó3†à—eð«4ƒò”"—[¹¨ $>éY×Óqž8†Çexÿcü^ ÓâŸÏ(•ð‘YÐá># ˆcœ}1:3—/AòË;ô¡ ãöÁ¤xæ waʃQ–´…íø§M4]ˆ~³ƒµ*Ö©´KdÚ øŸY|¤‘©$Ý “Q,$ʈ³ä:ü!,U8ú÷ µÎQ­xM$ü'4ÞRšfÈØ ’÷ãÖh4ð>¼»ðÿŽªn§y„UœÕ­ãpœ{•8Yษ ­oÒc°¤‹: òÿ _ª‚“¡Í@|çMÚcáµÉ!4HJ + óµFKÏrBDD?I–6ž¼­îõiÐ ÏÁ~²jü¼''ŽD©¿¤•HÌL¾Ñ{•-©;þu¢ŽÖp¹œNÁwþv‹û‘ÖƒÿÝO©gXœUUx“ÍSn±D‡ÊíV}`“V®©J6D Vƒø‰…®ïI$O$?“!ˆ¾e¤Æh…(öر×{á÷ÙãÀsj ¾W Ð""oÎÁPðt‚¾â°2TŒÎtíÍB.ÞÆ‹óìŠÀÂKˆ€ÒãEÕ*ÆeïBà÷Ñ:^d¬¡Òžµ"%]7ÿ9ú^m@ä€y[!é[ý ¾YKáA¶ÜZÎÁrS­‰Rï'a‹ÔýiõõѪÇDÓ¢=ˆ¸QÁº„Q«_œ Dç‡2}W幰ЗÍÍ Þ„À ž^‚¢õúº>WCÛ$èqç­ 'ûæ%‘±Î\¢ËR ”Mó¤8ã&Á¸Œ¹ÙÃ>¥Ð¼zbl6† !*¤ûÒÇ,ÒÂ61A1)Õòq‚y±bøòÅœ… Å2A¬ls ù‡í‚B§]–cå<…ôF¤%ÈXH1:±J¶F90ªÏ¬Ï—Ùç,µ‚ÔæøJ1f&ÆIÔÚ§Xq=ÂE©v¦)¡¨ òÀ'ׯ ye— Ëc8ê– á\°ÍA~€Ì²æó}^"ÆÀw@#Áh+ìÌž›hI¶a“ ?H³"îì6.*Ýü“qw­7²@Š‚z]ÙçYë3+µ&~²•Ã!(Û—øF°m¬q}²¬2Y’@—Ö¬îüÛjðêÅŽa Jû „†|)rŸÜ ½Šæä¾qË]F먌 n½& ‹»·‹îüÉ+|Òá¨ÍûùÅßæÿV“{n{MÄH­nbè⩜O£¾&‰­Âü-, ÂÈ ¤)‚B0|êÒ¯˜h—űÖ°>uå+‡J%‰ÉaFš”v^—Ö¦ª(Ѫ_f$ºÏáÒŸ¯ÖÑUå^'>*ÙfV£Ç÷QUµ;e^‘n­6uÆhÕãT#7cdŠºÄi@›ñ(!0R¥J‘ÝLn†>GªàsØð”Q¹Â3Þ·í”ÀØEÔkœâµIø¼ÐhG‰1”k$RÄàh¿êLBã€Í3€–µlzIðöýJ*#âÕÕÎ1æÓˤK’€x¬·í,FF¢“ç¼tïQ -ÞãQÒ«†<©#s¬‡3ˆ9J~µ5DsEH¨Ìéá“4\–Œ«@wA¾ºJ\±u}I£õZ,#åÆäÑ(’Dßö$È@UØè¥pG$û»MZLéG0þ[.|·Žu^–· rË#WmlÕ!(m\§`” î€)%ì¬ø]Ô -P¬¸¥ø£"J´;ЦW·ñ¥{âr.Øå¬B ø£47Y·dm‰*m”#oD^ipÛZÑ4Ä6ÞòÒ_v¾ª=I¦|)ÅKq…;H’}ÿêñG` ¡†Œ)¥öc`­œ.ìµ0o(°–äa-kkõRV""VöH®ÏÚ16¶¡‘>¥¼ïG…u¯kTŇF#M>ÀTkÅäÙˆ4³¨vïPHð=WN[LyƒhÐå’¨£Z¡Ypé‰W^ O›øš®ã6Úh Oˆâ‰½«‘ ™…¼%ÈC›P àÆEÊÙ”lYÒÄ7‰mxóœHú]µÇ·Uèœ#Šû42óÄÖv>D`Æ{…«£‘iµáf0Yß–ÙB¢} £‰F{ }°Âc@„æ( E£5<*}‡]C¶dTmu”¿U “Hce½§†‘aè4æ+•½žŽöIA”ÃÖ5dž‚L<ʼn:ž&¬ Y²ÂÓD3¢G„šÈ+£A`œw}ÓÆ7Ét@è[WQØ·Æ\“_d¢£9;Û(½ø >t•5TŠtÉÛh¥h1zXÏÈ×bÁ¬_ ‰²×Ñ6‡eï£?8‹wЛíº:Ë>£^2ÑU7È&ÉòÚ£§Q@swq*pè+€ö<#õJ<(mÉy@¡®‡…°¡’Û…¡ó¨|Á–OG&Å™ ¶ 6JØ6:Ï’?(iëjGT8¯›Ù°ªE˜°* ?|šÌ”*Ý€c¥4ßlapOi&KNÁŠ’Nœ‹¶‚y2PJ¿»:QtøB=I¡°îÑÜÃáY ¡iåR§ìYÈEDeeÜÔYdÙ¢$³RuÖ9&‹ZJ’®06[6lÚÛeûµ:Á?UŠäHQ›ÜäuV¦ë´«ôÐóبkËKDº›d+•$ÌÁ¬D.Ôíd„ѽpøkJf¹\7—TV*gc(cwûö¢Þþ°IAÍPg€i½Ëy‹Ì˜¤êÅÑ`ÒšØZÙò§²¯–A%–™:ê<‘¡ªº£5JæEõ„8„&ÕÌ.¨?÷ÈÍ>û?úHbœ[‹Ì=N,eò‘jqÁÞUJ½2&‡ÇR-=Qš°0{VŸJ!¦xÅT·®“†ByŠû”=Ú¶®ÜáJ±»ÀS:4°*«$@#±Â¨),Œ1WÜuë42Éi®1&áÒr7)Î!9 ‡²µZlpA° FÁÖ`~%Ç丩fÀÐÙáfôA8~%ã¦%h\ƒ¼/Ño'Æ:‚?{D&ç šÅåÙHÚêzØ:j bÔGÞ˜I\5²WÞjiÅ'ËøôEjŒP ;«rà‡>eüÇü²nº^,#k°­£ábº(øi³­äXò—¥þ}®ØFð üK‚Òï*)ž™C$µù=6azÛÂ@2Äa«!I}'r_õAúhè‘Dl)ƒ5ÊM.ÄHÃJ³ŸœÃ»R#}tGt:á.К߷,<Ç"wᎽ·öÄ´蟅¹TŠ#bsÓNõ!®ü·$¢Tˆ²R ÈLvòÞV;S" Æ_0ôû‡ ô¿½µ$il’W3Q§ñ!þè±¢1q>ÛêAyr>‹óÍmV@’ë¶ÐPªøRÖAP)éD‡Ã¬ç{‘ÜR"%5ŸdƲ³6qI=À„fMâIê-í q-Äé°‰iù \©2%2ÂîXkÆö㻨ZdæYÖ?q²ÏCç‰Úp oÛ‚‹½ÁÖŠ“òhnËÁTUenLj,HÇ7•(G Åäý’ ÝÊt,Âøjì,ÿ( ¾‹i0"ú¦Å´,!=ì²p5ÿ ‚1I=¦ßĵ-‹Î‡2ð$Æ Æ_Ñþ_mC+ZéQüT„a‰Ãå^'ˆ`ÖÿWÞ$ÃãSòÔ`íÊyõ -¨2ƒ¬kEëZ¤öÔtCž›÷<âáos9k½¬'Fº+x¥¥“‚WN=-²µ2B-bÛ¤6‘ #Ö»ØÔé²aæ»6UtPŒ–È#Ö=MÌj„—¦ˆ2¿µŸQ뀵Ռg™©QF¨WŒW¶„:d«}*ÆßïFÄFÎÙŒ­{yô‡É(7Ö.rÀû дeŒtŠÆ¹“ãCŠ|µ†ËŬHzÀøãFz C™`<##Úg*ˆ¿ï‹`¸­Ÿá*°&ÊRX’"7‘jæè¢‘X̯›¸f” ´ÖM·¨7$|ÄŽìcFS’:Ì‘:dk €q¹†evrÿ±Ÿ|Àİ8ªýÖ? ss8 ¬ª*U«Çù´\{‚ –‘GT ÊØvÆb³¯Nö~Ýx’¦EM²)£ßç,@ŒK ~Û‘—A!;pþH¨2ÎÀðˆûjs\+è!Ë?¦ ?‡T%q`'!¿}E9Åç©‘®ä;jfÏõÈ•œUrVôøàè¤ÄWTF¶ö–L´ m֦èOüð½®sìéàÑ¡p„E†øæM9*0¥GXoFºæ€bÓ59åRÂl»üª¦¹N`kçÅ@ â»2ýdòsÓ‰*ºiUŽiæ{mÖ½„ˆÇVj@Òh¶`B Î6Ú‘)Ñ#Ϧ@•ÄÙ5« 㱘j•ª@ßÇÍljúðX%ª‰W¾D[ÉŒþ­JJ›  ˜%ˆ0=ˆ‰µ(Ñk.†ËGH!ˆ®dûìäB‘<|œ­ž•½^ŒÁÊžÓy9f?ætQ‰|º‚=ý´O–…zc&-=Øür.v¥h‘BΜ’¥º;V1´çе%·ëÍèËU  \¾€IÇ@aÉ¿æÓMá?$ãiÓŽ´'’u¤³‡"³ä˜mäÔS:6ËvËtYkÛ#G)TžL0KÃ%Êíëɽܣ©’KNI⛞ˆ9¦_?†ÇŠÍÚotDb„R°šAåÞ a,¿>;† is«ÇÕÉF:Œàw5±KÁ¹FØFTSÿ¹X=•š°˜anÚ\TQ"åù|¥­b”–‰!<:ú¸'ÜÄËw©cCi>+xFÂ0yŽ6qÿ‰M”¥M—b<®}›L ~¿…!Ê·0Þƒ…„Õ`·bpË,‰˜ý+ŒCÀ ‰) Íhø€€ÜNåÁO‘­ˆ@Òø—rGÊ9R¿)á—˜5:¾°Œxñ¦>~[.¾¬/º,Ÿ×‘ͲóÅërñ=|»Zò†]Òu‚뵸¤©Þÿ¢þL»Cñ˜êòQü¦ü G)sÐR¾Wˆˆø¢¼÷nЧüdáèÈ‚º BVøæy¹Ê‡ÏëšN9>| Ë7δԿæˆò¢^,ë ·Óý'õþGÞÊÅËzñy¹x˜y‚¤Ä’}ëä™÷ù!æ}Ü0/' g¾úqÏÒØ\BXŠYF° d5g…=—鮆$1~3aÃb_És®³÷³ìý„cïU}èŽ)•}/9w{øâ~xe³÷«ã¹ÿÙ!îB¹p=W@="Ÿ42€õ¥.£rp[äà=D‡S”µÞa¹ùe}ÓW7ÿQ.þƒ3š„tUš.êE i‹nuèÐCSÖuI úp0‹HÐß·Alºx½ùu½úë^‡³xSTåŠÑ¡§…ˆ7‰¼||ÞP¼x›GWòÕõ§‹Ä”Y.ž2«whÔQ‘…,¥Ÿ•‹Ï8µº­_Ñ5e zGöݦ^T¯Ò¯]½íêCÛFÄ,@,åæó¼ÛñѦ)ýñ…˜ ¯F9I ‡­÷€J)âÏ}žó)zs˜‹†aìÉõ¡«eoWfj*bMï#ÍbGé/ò#ŠÅq6~¬¶¨æ,òl[NÝçË5d“×u!-Xï¥{%|6 ƒfRu\=¿TrDŽtæ ×ÂDqŸÞ6È–ȰلÖRå…<.³G´~æC~·m–¹ÚsÍÕYÆ“vˆÇîï­KôjÓ‹ÕS´1í·ÖZQ%ö|2ÖÊ3’ÖÊBÉ>xôˆædCž'ëªY&¢ä¾Œ×!Œùû6~vȾ¯6øÉ V×P¤fO“æ´·÷ B± <™—jHßx{ë¶À ô\”f”T¼9’ª©©ñ²ðz‘ÿqħ{ÀXãt@—ÿ!k3À”*¸ù¨^¬xí\!á¼ü"‰§ÈÚ”QŒÛ ˆfØÙt¥<ãVF`ÖºÉgùFüó¼ÐæeK–™v¡ ñÁ@Œ n?r_¬ìv¬¯`¥ÁÏ¡,øQ³Û7FÖ33wÃúI§bÚýfxI/îcæ'OWf¯¼VVágÜy䡸e7ÿÍ$l5©ÀÞNßÒ «\B2I‘šø%Idº3‘["áõ¾¯ô ø<>]é|Îmš –Î0‘ó&(@;YR®ÜtkÊ?IÑI÷é郿À?ÿEX_endstream endobj 533 0 obj 6013 endobj 537 0 obj <> stream xœÍ]éoGrÿ®ä`yo#ÎNß= '»ëM°Y86‘8ØÍ‰´("¼Dж”¿>U}VÍÔ¼ƒ"‚À°ü4¯§:uôó‡“qP'#þSþ{~óê—ß…“ËÇWãÉ7ðï嫯TpRþs~sòg0Hix2Lã¤NÎÞ½Êo«“ O|´|yvóêO›ië6qëþëì_à £èz´Ãäᥳ øOÛS3„0Mjóû­¦)ÚióõVo¾ÝžªÁZôæ¬ùm~jlÜ|O L‹ëlx®õ4h6ä‡6ãr œø°Îo¶vˆÑYO¿ø ×nPcÜün‹/6ÿŒßÇɵùÃöTãxcõ+¥‰pÓÿ ƒ½w!¤/ N§6ßoO|*nþs«‡qt°K|ãl Ó*†ôî[Ée#%שŠðŽ=9…³5M™l_Áô›Güã ÿ¸Åã£R›ñ¯ðmˆÎÃÙÓ˜ü ÔHèÉð?oúÓOýéžz5¦eò£}Ü›öð¶?¼¤;X®ó±}½àÔ8Ÿ“¼„­‰óÝÕi{ù3RL™Áùï¯Î~QHƒ{Ü<àç@}=ÂÚ?šÍ£\;‡i”³aqwý˜}éóöð¼?¼kÉ&7í)'¬µ'„%' “çM‡} $Ô†9}TºìLJ6_)K6zµ }Ý~¼NúÝôþؾIf"Rž}¬DWA@ô}RøRDÿ(ìD¿ì”¶Á¤Ýi÷3d§.àG-«ÅçþñõNeÇÞãŸñ{ΗÄÅ·MU®›‘ÝÚ)—ü\“¾ÊæØyu×÷Ðeøý¯ØvǨ ³Þ³Ó–‡÷ ißÒ}”O×Lè;×ó©ì>UÃyïwëògvÈÿ+¦ÌÔ0e8?‡)„ÔÀOÒì ã4S«»¢k@uÑ–‰v 3š°à#N‡ ¼(3è+º˜õ›ï¾~|ê,$\ìäfÒÇ£øÐøõÄ] !ÉEós᳞N®;úf4Õh’'IøÝVPÄnìÖ¿rÎ~)£ûyï;£9÷£?€gF™€§Çx“4²G„¿–ÿ+A÷–)ŽY"c&ºÀ<¶mÝׯ·‚Þ±æW]úö¤ÙD‘$Q1±ð¢×P’Õ¹Ø rÜõH|Gœ]<{‰²aMªNvOfí˜ëºÇr,‚¨±Æ¥NTí§« ðõ Š?ùø¸jÕNˤ‚ôvSõ–r¬0ýù“qR® p2paÈû/Dv?J´¿—ÞrÚÇMÑìuö í„‹hÅÃ÷¤øH2"%c•BÏw"&;ÌqüZÌ=/zœjøsñ§à;]KÊç"C„°O9;¹dcüh +Z'•5w!'ÊЫ­ÆZƒÙüÅv„W4¼EÞ'ºÝê08;fHYåôŽ´“j»¤0Üž.vß 7ëèƒ#=õ17[ Œ¶YŒã`®;ÒÆ&ñÔVrÙôã}ÿ¶èꬪǺ<‘Ð[hÄÄŠR'(T=W©¯ƒª ¾ ̨ ›¥–eܘìÂgð·|Öc£/®X–Ð>-®c¥~GÖ;¯‹´Õ*#ª}ªžZq›Y&qNQ:7Š႘.IJÙŽ³± °³Ç ½Vƒ‚8 JÁÑ>„¾œ2SÌëŒ-\1tKÅÀ)`$„þèÈ~ÞbUrt†È[ÿt[lr(k\ŠÀ—â†ßà ßüý6¡&=ÆCEÔQ‘$ƒöHgÞÈu¥@–`¥Nh³³Ø'ÀÉ÷‚;PnªúqK÷–ÜS¹ÿߢÜXÅÔÒÑÙÉŽ;'g3p(áZPør÷ VU,Œ}b¦¹ƒ¥ abJ$ý˜‰jPêHýð.éÔ—èÇ„›;ÄÂ… SX›ÿôƒö4‰¾ZÎTgt¨|#»'²7Pí)QŒ¸ïx]ÑfƸ.é4|Lj Ð—V-è;U§çÜQL²àã‰äE°£I÷t}²Q”è .©…†FªEQ“>‘]%1 ã ^L“¼0¥QB!MR‡ÙL¤Ð·Û„ <¸šÙ!¢±œ Ù?&Gq”°ëñK„]Oö¡‹°SˆKf¦©Øö>E—ÞŠh«¨S¢ßgÇ'"$Å€L"€.šÓ °ˆæ2ï2eP~ûªwÜ•eÙ bkˆ±‹†²¬>ë-9Cñ à€ªZñŽtÜx" ‹° L/MÙ1±ýîG cat=7}ßGãþ‰¸ªV™¸þì§-@‹P¢Aä°e Ö:Ûw:hÌ’ö¨…öà€´™µ¸‡LÔø¾¸‡ÂcMbJ—Ñ"5ZeeNR£ pNI“Úú¬á‹Hîf4N@¬csµSçùú㬠L<‰ )½|™#%ŒôIŒ1Óïc‚‹Â­Š¡~Ú:;À!"G;Osc€“ G6‰¡u(y ýˆöÃñ3¨Q9»Ë{Ë}k²‡É¢£rfÊΣø¸h4•ILßÂf)0!þÆ–Ú¶RTó$¡ÔÅr¨t¼L÷&Ê_*žUXvq›??,@-úŠO%¨•ü»T¯¼é<*Û„ë¿èÂf…Suó 5Ânðã,EQ%ì«n7 B³PLgÖ·Z2ô­nó¥ÿ¶¬b‡Ôã”D{Õód0 M˜¬›ªš7C¯bR;y%íOEü…ÄÒ.8h,ü.fwk†&"ž…Ü(–èÁ‹ã2gä¼ïRÝå¶¹µÁ=pnê[\ ½i@ÒbªžYš×g«©»L5|[)~™9J CHù¥cs2¤æ‡ë ñ|>œ eRÀu :¥¼ëuÿãL‚-B*ÅŃÂùTn¯Sèb”ü΢3bx-V kž Ö}J|Û7E³«9î€Ó60µɲG²X`‡“Ádmü¬µ]¬Û£u„¬F6NÙ#1¹sëÑNNÍaȨ$GB0lÏ8%úp÷±šaªHI¬H“(„¤j¥XÕ¥:ŽÔO9 ­™oÄÕê˜õœcR‹( ™3´Ví~úL¤²`‚É’%p ìr:åIÆ ë«ù‰œna†EöxB/øòŬބ[±ŠnååJî6Cá™M!ßÌÞi ùÜ7õ&o|Šžcº¬„ œQ(Îá…ãÈš L“ý¼Ç-eå5ºÕÛ›KiòAبx]±k\Ã,LGî;ÓýQ¦Á—¹$”¸ƒBóæ5…S ëL;Ræ'X¤nï¶&5šO(xg'!±ÜC`;dÓ‚Ö¡Å¿#hà>—êØÊ‹™“õ˜¤Bˆ…]„óÙ…µqürë–Jœü‰–Ågó!$দO³üÈ!~%§G~Rr÷M«¹åôï2ì®6 à‚ˆæ¾ŠkÝmÉø½;¼/1ý$ÌԛꫲωV×þÎu9c²Ý½ÆÀ—Xr3DÕ>‘òaê±Ãìm¾²õå‰gL> ­Zú¤ªTDÐŒGO࣠øSÆYÝoˆ@UJ1¬ §RA3±ÅúA¯dPÀcH]95Ø™2Ö¦±ÖëRêÖz] I–˜i-l¢™jXÚcdû%šFÂ#o0:t›ßNãAÀLç\ýsƒ3d5DéØ}±ÈÒ*çç˜@¶e*…‡g¶R[L9+gÄQ)Åô߯"çNz¦<­ëŠ@$y÷™öËœÜ[æQH\éœì\æÚo53ýëHÌBHŽâ¾Ö×xÚÂuÞ#Ãk3@4îKÜ7›‘L :*CŒõ¾&9®¸.¾6«aH¥ÊAµ‘ejt%ÀÂz é÷1Öc™«}ʶ¹Š5c«q®êD&w3Ý‘ˆ©tO"íÛ«8Zçè:gÌZ§éÒýäºLƒI"`û@\ËEMê!Þáàµõç©zäÌŠâ ©Ðc_qæ¹éŽjØŽk@Éy²2MgÑ­Ø_±Ù—èG©¾Í Qœæ¾-å¼FRLNê wÇ™GÃàšÖìŸ13Íø%Ñ5+?Ý2%¹›ùËE»y‰óÁsLz’W57fW˜“ ‹Í35Þ÷)gGº¼–± ôs=ÀÖ³Í .iýªu`W ³³QÙA”ácj)ÿG_QÉì‘“”Ì üZ1¾ó׿_¬ÂÍ£‚_?áÇìXºÎÒP‚ (6=¹;KKq¤lÅcd†R€¬§d‹¢Bq¾I÷£Äèh=dtïì˧­¢_»)Râ™]±:ލ“ã ò\eHj%x(z¡FôjÄL`¬£\Bm•¡«l}ƒ–ðÒxhöªiKfµšŒ¦uÉ.ÆÄÇ‘6àÎ[²ÈY¸õîáú¸†ÀØ]ý(°(z>}Œ1y>ÌoÆ|ˆ7¬W³¤¹ö\¯pêrË.Ô<¦eNº]¦ú6禯¦“m,Ùðš=]»Êäm¿ÊmÃÞôë(´4›Ž‰Ò“2æ{5ÉÞ63µÞ 1¿wƒ‰…Ó­IhrÕý‘&¢jEú;B‘I &2Õ%}Ä’iO›—JA˜7©eí ©ÎKš8+£%µ¾îB!tû K›p㻯{`ô¶{5 :ZÜÅÞ^¼e¯E·Tô‚ÅZðĺwÊÅ4°ýS38wÜçSOÛ7u4"©n• Vá8:È\b©Ä!ÞêÐqNØ=ç}tÌk7®°ùïê-µL8Z߬¹iÒ¹Y¤M®esB„ö¾OÍn®,o–aó\«kɺtÚ°ˆg*3/ :)J1"Ph–´}Ó ÝzĦ]\6(’ˆ.·µ›sV½÷Z²ò• R¹¼’‡ÞOû„¯uÞÞ”~£ˆÿ®t(Ú]žë­´€+ϾGÜ`ñhä~µvQê• ŠÍ2ƒqÞt´œÔ`þ Ì!^yh sŽƒ;Y”ÐJ/š.—е†°r•-»…YÍ3³ÒamW•¦žê;4˜¨PůÛÉ@-#ÿfË”Òêzަÿ̹ÔzÀBÉ·…èPæR ö\ì{ÓR"V¸êÆ4-õÞÃ2oΫ—tñ iRiR4­Éœ  “ñâ—ýPè/~\h&Q šÞ`Eìõƽ™XÏ.VK*Þ!‹:•¨ã<èÚUE?ïÈk7w”}Ínf! ´&ÿ¸…ÝΜKE:²îÖÞ[„I‚Äï±$`îv¨nÀ̺ê–6¡Qîu³bèoIöd¡q&iÁ t¯î¯\ó”2ç³î ¬ѽz)‡1»Zuzª ¹#äk¡ Š%1ð»*üê… V*ÞÛý{‘ˆp÷=MU•‘ßnS®;’GlÎ"ãäÌR—”®Oׂ¹Ï÷œt¾m ·;¼ÝWΖ“™‘1W 7xv&'¬SI‚Ѩ$¿×µƒØUIpþ‡% þê@íªGÂöLãÑáD›î µ §óVAH ¦_™†Ü-6MÁ¼/ ¡|Ÿ 3T2ŸQ)¾\éRæcŒóÈ›$ŽkÌÀ> stream xœµ\YGÞç?¢5~p÷Š.*Êë•elð²ÂØÆcy%{µ‚.ylþýFä‘•Õ=¬½B0EVV‘q|qä¼YƒXø'ý<9_Ýyl×/Þ®Æõ×ð÷ÅêÍJ„ëôãä|}÷:)-ƒ½X?_ůÅÚʵqzr}|¾úyã¶ÓfØÊÁZ«6þ#BÃÎã •Ý<Þ*9ˆQêÍ·[ék¤Ùü´Ý)e)ýæþVÁ§fš6¶;18çý´y¸ufG·9†ŽƒubT›{øZëÉJr7Îv4ô«G[¹ù>0²±›¶» >Ððæ»úmFi·ù2 n½i/F›Ô4’®_lý8ŒBæÅµ]¿ÅV)¥1° 1xï´ÿ÷ñ?œ@1BNXÍ0: èñ)PÑÑà/vÜ¥7;5Vx; m¤Ø¼¬ïŸ…•Á*$­ùÞÀt:.ù9v·0»§'t[å …!ëg“àÈRé°¶œYÏ´A>ú9F;z:þÕv§¥´—@ÞisRº×.u؆u”ËTVÞ\׉ŸÆG+X‡îlå`™^Àº'¸þ·-ò'ø23Hùä¬>’±jûa2Q~„¿·»ôÏ>‘™ô¸X$½0Ž9¹›4,=ð±P4µ{aäïð¥wÓæ†Œ±FCe¡ÍNÀR0£šsÜ(«§=î„‚2nõ9Ž…D±™¼x˜õñ¤°YbHkg¼žÉúU †Ö…û€Ï‘ûð¿ ‡‡#SzÔD¦ÄÏÊãOpÖ4ÓgNÈJ7.ü›}¸:þëÏTÇq6ÖR©"B>ã&3ê%nÒj=¥éêÎðPÉ'xf Ãôd‚š˜ŸƒÙæfçtlÏÅS;(é=òR÷ý/›ÒÊÔFšš„_¶8-ïç›GQ&›Ç¡Ùæç ç-RDÌ’(bÆÈ=8††Q´\TExȲ·j+Û42ƒt : ú; ¹¼MÂ’X]&n ÒÈLÜDø:’D‚âGå)P„²ºÂ׿Eî“ Š_VaÉfËk$sÒ­y¯ˆ {yä³(¡Íư5M £r[HbˆÈíp:j€æ/«í%G=†®GÍÍ·¡`P ûͺgH`€ Iù„µ 'LŒèýü13ÄFÄAÈÆ aþË8¶w¦ÄÈ=숕6\¦3ƘDk!ˆâè‹ëíºÐàÞD‚?Ñ–Í¢iP¶>Kéû¬#ÇsÃÜÛ€.9ú$Q¹Å£p›÷ÛI£O9鬰ú5åê$)­¦KÞE,µWÏ£r›À!#ˆ†Á¸³ÊkÊeÅaZe‰¨˜©À­º1@Ý1x}`±›+¡ÂÜ(SEgì5;BÆòÍl" ®I‰Ú­‡t¹mušJ!žl´u^c8,•ð?—¹ó­O;V±. -ÖäCà·ê(wY›«ÀpX“…­DÎé(^Ps¬iÙ{p6žQMÒS:  î.¯k+¡ªÑ‘јOÊ.éãÔo†Bc[<†G3 ÒÎf`>|XMx%©”T+Ñûæ´ž$;¨%?5ÙiÕ7ÕËÂ>¿–@s÷³V$2F`’þ<ª_cö” € ã- yFs–c˜…©W|ÑS„;gäjÇÌCæT M–|Š›@… B"åp6¡—1ÇB|1Ù唂Ér /š¨®jŽº3 àH}QävíêjÝ›QÆÄ¯®¼OÖyZ¿!†°qêH6ðzpDîz2w’.ʰ¦6’8Îú5wkGcq; `Ô 0&*üL1·#XT8°¼`Ê# ½L£K&`Îg’cð¶_•N(ÀL΄N±ñYm|Ñk¼*0¹–ÁNÁ^çÖWµëEi|WÑ÷K A/ipCžŽð v~TGˆBÌ"cöÄÁ݆…ð-ª°¹ø„gèc\«ö!»ê‘‘:7ŠÉÉfž×·gtðù8=9ô.wb²SC£ûµóÃÒømmüb‰p õá^Qµ‘ß`tãFÑp[Š!1ÖtïµÞ)ÓÊ3Oo3g‘Q&ªn4è}PéN¹M×ùŒÚD;šs ›»j  ×Õv°“Ú5zgBhÔ$Y…ˆqÝÙ9sÆeŒøP« ˜ëÄm`¦·éÛˆ¬¸/ÃU}>ÿ¡ïÐE6¯Š·*uW=#¿¸ÖE£–âׯ»>ë,nûèrfM¤æ€Š„#Ñ Ë~‚þ:)8Tr¤Šp U8DiԽƩ6ôsò$à|aôO¨º0NâgÙ›Ò–FQ]}”lN|ijf­ðˆAö{ZTÛ \|Y¯ëÕÜémš¬eDÈç$骾¿,€¥á°)NJãuπϟ1«A¬RTƒª™*?â\Q½óô32Ùy¥ÛÓîlW}‹qÿT­ OÀíÝuê“G9홈çûmâ³òtšÔ2xÃïK㓞á¸f{“Ñü@Þö&ºî7ƒñ›°™ XÚáœæÀtPÎt€¼©·ìDÊãgóÁü G3³Q€Aò®ø/0ëhZ({[?jú¥8#ºÎ0ý3";P^f[Ï·j”°¦£Éã!š.Æ6I’+foŒ|ŸïÈó‚@,m¸ÿÚ€øoˆæ&K¬É'î  W¨Ãâ3b×j ÿí þin#ùéÆn Zz¨¬5¬JÓ6sb‚/­ºÞGåÃI4†Àù£¸Fð¤*^_6<Õ çÌœêBÕs–SVâº;xqpÜoFIÅ‚ái<ç#¦*#5Úi‡‹à´…d%â´êvQpó—葉úè­ŠÉáPR \ÉêrRþÑwÝBî^sþ Q ÇÝW h ÖxRKu æ¶’ð°å0ÀÖ7mS­>*f¸Hü¢·ZˆÕ£ó½HÍûA‘Ùyë‰NކU¹w_—aíBZý¨DΓlTéÁ š¿oKI|v±ƒ”B_*Œ„„ú1Ÿ0„i´Wˆ>ÚbRg‚c¦$ÖÁój\â]Þ/2¸V9(´÷ÆâRȷܤ·U°û3Ü«Óo°ØŽ†×%xÙSèGfÀNî’^ûò§$¯Õ’9MØø* Ñ&DÓÅß³nŠÆ˜q8Ìo¦À²@ †¢?N*íÎÓ~¬DªÑ‹ÒøYcŒ3ÞÄà•ÎT°Kò Ø •béB…¬5©Æøí §Ô§&¤Hjt§ŠÔ<=P¾4,Z¨{(X‹U+‹åh;¶&Óàˆ³òq)>ŠGÌ^'’hMf¯ÖÂ*ki".‰ Q2˜ ø‘ÆUÆÛ±›Ë˜_Q2(ƒÊÉxâ4ùÀq}tÅD8®»SÆ"ä®UðÊœ·”sXˆ6žÕè$ÐÓ…r<à g€ñÂ%ü6Þä;qô&êÜuú#€AmÆ¢™(·ñdd0çTŽs%HÍeï•kì~ïxõýêÍZ©Á„ÚLX¥[+ v€ 0 Gv:9_Ý}°ºóà›õ»«ëg«;?­ÅêÎ?ðŸ»ß} ?|µþËêÞƒõ÷‹e Ü3Èe Ê†µbDJ¥ ¢òKs ä,?"ȼ¸G€Cz0ÿÿ=jØœÓl2ÊÕ •h7w2¤F³¥‰jS¨„Šv¨™€X ­GÍ“N0ÕO 1ZF¼jÆ\ SÍy'Ç3ÙGï–À¼®úajBîÂÑÄþ.F倰Vv1á\nXͤ&ƒ§£Q7þ2x&"²~âÉù)! €£X» åŒà³ \Q]DPkçÅ¢-±z¨™‰4#®ÏLó²H\ÿTw‹^ãrPM-Öz‰ZgF³K‰ÎM!©F^U”Œ!6“,¬V+pÖ¾R•pôÙž„ìM¶Špv'ßs«cx + 2!‡Õ½’"¸2Yé{»É‘†ÜF÷P)šGRY’晕Ž|d9XN fšþÛN¶ªÏ:oC»P¥i=,ëEãƒ$Mò~!aÓ §¥Æÿô"¡è¹ÈÞ¢›)Ù˜½¼Ó|ÌnúÌ^c}'½o0ï³'ÙÓ£îOpHpÚu]̦{¢ ÇnùLDF`Q`¶Á`ôÊŽP…Ÿ¶ÚçºÕíZßs9L'û™â™_ v’G®Ð‘³&´»Íj§xHh^L8Ë‚œF¡MfÐ6µ-åî#ìs鈿%Õ9°gÉÅJ¾òÑ[1–Bg‚¦yúÕ1ˆa$ÛÒË9ùˆ"ìä€PeõÐQ©³ÉGbXZ¡Xûœ‘§Xë7q¼F÷ãæåñÂK¢Wª³j1-ƒôy»!qNr±‚Y¬ø/•'®è(ë•o$/³º‘\š¡™”DzÛï\*¶mjcºaE5Åû#] Zˆ\—Õ-‰]®ê$]Ñ\O,Ød­9´WìTÿ,÷¬ XŽÕ?qË*‚¶}‹UV’ŒFàéUʽ{uƒ\s[!õUyy¯¾¼_ÕÆ{ªTã¤Êïo—Æ7†Á“˜¡àåk9x‰¡^·"q÷lpÈe;žFÀK%ºæ' Ò³Qá «1¦ˆsLnfu"’Ùûº(×AndÿC᳕å2ÖCJ$D™t¸E=“5Î=ì邨ÓLBþzñbZšìÆ7a8tPj¿ã£ ÎÁ/1ŒÁôwè§ý‚ ¸ÑP‹ÌnÌ$Æ €³E™ÄÃOé£m'98–y8r/OôþQbh‡S28î‰CÖÃvœÜ•æöÚmì£#<ÉEØö)ãÕ=7 ºLßCùZ¯žzé.ëP¬úG§,ÞÕ¿wVˉW¶j …$¶€2?ò* FÛìžzm}¾›l Zw|Z´WÎl íüÞ ù5¯]Ìkó‹]#K”3Îx‰„èºÿé6÷%“‚^R‹ä¤ºÞ^“éCŠXšoã×Å28 …ù íùQaO.·†ÌA/í#ü©©½÷ýaël¼¿@SÖw öž0Ðÿ|àÉûï¶ã ¼ÇˆÍ°Å{‹.”–FÑ{/¦BÁFôæ.Ò87äð½Eá–ëõæØ®˜@Ãvôd±PUýÜþ+|1)cEmë™X‰õ™i½w·á´…ä2…÷UE‰Y;v –¿’[Lä.ëÉ̪¥[­Ê šAõn®°üÑ(Átá±[fÕ‰¡Pðì¶eMÂM}Œé;ÐÂÄUÉ·+ù=oöU¼Ã’l,«ši‰<†êLÌÚóиv°‡±´ „€€ûè3YXùM#“¥EHj yʘ N2ÿæ@XJâÐ×Ó´Lä_¥L$€¸À%ÍÅëø«Cæq1NM g l@¢ô<ûÅ;µp?Þ:½ÀliCÙ1³³]E3ÏÞð÷3V$PÆ• r!ôAåÓÜ]Ÿ|QH˜.§4U_„Í¢~2²^ Þίà‘ÇÂbø–êÌãKiØéV] qRéý¦½çwdÉ-Øå‚þÞw¾ô7*?/)!®3Íh„$ñ÷«ÿïûaªendstream endobj 543 0 obj 4762 endobj 547 0 obj <> stream xœµ\[sÅ~WøâÎ&Öfî*¤ äR„$ ¢Há<È’-;±%ÛBÆÎ¯O÷\{fgÏ §(ÛÒî\zzúúu/¯ŽÙÌþ—þ=qôÛoíñåÍ;þ#ü¹|جngï„õí>é5ò–ËYbúõÑé¯Ü]#›Îñ¯ŸZ&>OüÌKäßuycëvbDCÃ*Í<ülw'åáïá¡`°¤Ú=Ü•§6.e›ëò›—ûöy85ÌD>EF=Æ¿Þ&–I®<²ìéh­¯Fûƒ®q&-Nº£?tÃÒ}Ì=\è6T‡¹©DŠ…#sA‰_VšF¯¢Åx–,˜Q÷Žã ˜`dÜIæÜ Úpí]d ˜láÁǃ¦%VhMxù«‰ÁöBJCÄ8e˜ZȶbÑ0 fyx[åàź*zU÷#ºÕ…Ç<\ÁüÕA‹—íÀÖ­\6„ï¼,µ¼kÉD‡G•œ²TZ”:•Ÿ w˜lˆàúç“Dƒè 6ð—_˜ý²î¹¸V|¿¸W|˜.Ö+B^5øÛšÉ@qyƒë‡à(ªÄ?%ll !ˆ†¨ûÞÈÆUÏ…Šd{­(ݨ'7ÈhÆŽÞ_ÜÞÈ AçYð«ù@A§Cêíâݽ®ÓG4¿™$üh¯ËÌùeÒ¶Àì–32<ƪ ‚êëH$ºæ*«ë¿zr?DŸêYóV]Z䡊w†<Úùkê7ZÔK?>+ÆPl ëK!i…ˆ0vÁã*ºA}¤§‡&v‰Â+VýM–…ýþb‘ä3 ŸÑ›k®ñ0ªüêøB×ZÓ12)¯"S¥õ†²†C ¤ ÆÈš—b.píeoBYã4ZKaä/(ü蜖Îå|°^Õ€t|8@|Q„û6 ʱDTk«â$u‰ ;) ò-‹…öÓ ÇVl7¼ânÚ.´"ƒÉ-œHpZéNÿʈÆ[ÑqÖtÆUCøƒü« Ö²NñÂ^çÁ{9r©oÉ¥"QD_éË!ÖSL…Ë.G}‚ 1ÀyYjf&n}‹Çb!Ò}ÚHN¸ä¡ô™‡öV5mpO’/J ʨx\¼c„„ôY'šP2O|øº ©.“J:·¥Z“ÞIÅeˆ …`i¿K3´ï\Ò£ºåó²~‘¢©yL ƒàæSµQUŠ˜•K³khd f5£x|ï³OP$h Ѥ^c¸á4º‰8ж²½ù<ô ±Ô½Å‘—¸•Y÷BÃÙĪ´`êé=å6B©?ÕK'G»”0Óð zQ,üŒà’„m`™ƒ7hWïa4 ¹Ós ™Pã0ë[Ñí÷ä3jÚ•´{)¦i´ðËXìñ'4$YÂbÀ.6·IŸP ''áع¬áÂïìîÓòþÓ ; 1³aŽ(ê4Žc¼Ýé[À¡ÐôFŒ*P¿ìTsyÿ¸¾UÎ ŸjŽz§S,hlpƒ9P¼™ÏIpl¦…krú`*ugJˆ°]G'ù ®Û ˆŸeí5Gj|p¤Õvä¥eÞÀV´ÜÉ“‡–¨£í–ˆÆÖº%KÓÅMîÛ!z{~·è1›ŽZðÈÉÐÐMxÉ@8Á»­b!%0ÿè“u}Œ0®fXÚw!cõ°O+œqF «¤ÂøŠ8Æ–_Åý6áu\eû¬þØ9> €½qÞ4*Í—Jã ‡çi4¥§tàôµ‚Tt¸ç-u™yê'éíÈO ѽìéïö{‰-ôxÃuŒæd”ýšòþ§ýæë •žÿãȤÇ»° íáð {=\qÔ-òÚ¬UsðÊ¢ÿ_Y¥ ~i % WËÁ"ñ ‘;±ãéBÈo÷…Ãü íKDR7B L™S'ÉÖ(þÞ ‹·])’“âPÂ’mW*c¦´AÑ´|#º7µØäÝ0ñ*·Í5Çò¬¸Cñ[.ìFP¸.‚Rnæ¼­ŠH£FvUýGÈ8üÖUoBQ&©tv±Jñó*¥fñP£ÑÁÜÓ™)bSÚ 7¦a”Ú°º ¯ëEÜ­—r1¸þ.wzîÊêäy¨=p\ óŸËV*Ëóz¬³z»Ž3ªA§’¸9U¸ÿ–yÃ4³›5Áì3”‘f±¦ð¤Ü"µ$EƒŒShR[Ö„2÷÷B”%¨Ã`Ò ùÑ® âj)þ´ªC„ <÷.@(ä*!Úµ”&ª¢æ$þµyÖ0º"†¬1±­€f;ª…Óœ½jOFïG•ÛšÓFÊÒåÓc’HêL"¢h=bÇÃçSˆA¹hL°‚$3±E…Ê)Ñùe\p\ذR»g ÜFä.Ãe{t”`±xo´/ðM¬nâ:dÎ)¼±f¶^!âNø+'Ýà¢*øÀ΀åCõ•ä6ëTÖogœ9XÉ8•Žž?ѧ¬ <€ˆ-À-PÜ· $› 8$ˆ>Áæ;kU“Œz.N1BZ‚÷¡ÞûÁHo@š¬ŽÈD#Ã’ÏVÚ"Þ´÷«•e‚¤çãµiÑÇ™U1)Ï’ÉCk¥Ò0;%4>NDòã&aàœÑÈ.(ôY%ÿ»Û2ZûµjÀÐm[fFÕ^¢«[ éºAúx b˜é}˜©èÉAÍø¦ôµº–‚«°hî¡v×­N‘À|„€Äõ³BAƒ#*šDÃ6ó¿w?,Û&^ð÷B¸´YÛ6R˽pýéÆ Cl3 Ì®ãþ&*÷šzFǽ­žQRõ‘ćÖ%c­_ ¢|Qç Öw=&Ù¶!dŸ+ùš­¥óT456†…èb-¥¡…äVG:ä¶Ò¨C ¦ ™¼ÈÝ Òå›.c:"(Ïî]`Û |Àþ¾ÏOI/݇5û½SnNš•Ag‹ŸC:ŘgäŒkðsÅÏ‹ŒÆx†œçIû¼<<«/ËÛڙùQ@rî€ÜÖŠüÉàÄF}aÝcÏ1LQÅÀ &£ŒÃÀÈg{SÕµòy‰/j\¬¥˜‹dç:#€éB ‰h3ÃÖæ=[C–¯öÚb´vü5.®wkÔÀ½¼ÛÓXab×Oñ½¿¡±JtsB¾Ój÷BåÆr$ 'CŸÅˆ‘ɦXÏ„°:w6PË µÔäG÷¨j“E×Õ48 Àð«êŸVF`~ÀxŽ—QcukåâiÍñ¬¤Gï&gczô W"[ÖįžC v"È%B ¨fÚò£ErØrè½U&q¸T´<ä£÷¤KØ[í¾Ÿœ™çXc‡×^.#êc!œQûÌ5 ñ>Ü cdîua ~MÁf aœãá=ì„Ñåó°“E—ŽÅBôøÌ8öÊ_åG7øm‚÷rhG„™9éœÿ~òlâPF±VÉûwªäj•ÑKä£ï; ;éÅ¢›^kÔ¶v4”U%òt²Ò°·s ‚ʶb¥ùg`[Ák!Ãû©Û“Þ ÃeØ¿IöÂÃl?O£ƒß‡ìµý UWsœ…E.)êó.ˆ{YúÌ›n`œˆàµÓ!]jµßcʸùU]övd[NCÔDm~©ÓÀ†2íÖÓØÎ#ˆ9&†à×ДâI,Q(N¬R°î­Ž¯6jbÔ´·¾(Bñ£FùÌYñ¢6‡u]½>‚ º}B¼¯s’2«iÆöÉîZ Ø”W¨±,„PfP£°]{|¾Ó7„s / mø¸mµ­êCcâÅ®H5ºÀ¸Öâ/뜗z)f뮲eT ÉÁØ”´HéiELžÒœ)¢/muXèuu`jÈõÌ÷Á‚n› è#àG€Op‚Ù b@i#&BÊߣÐjÅ_õs¹a¿®½ô(Ëz›Ô7E…´Y6æÉ‚‘i'ˆlŠ|üäöÂqÙ^ukÑ*ŸCÒaÛ*ŽP ŒÔôײò ÊÜÿYWð4Â@§÷J¤×“14’^Ò\ú'w‚€:~]ÀwP½Ò÷VmÕ:}ز҇\Y¿£èñH"‹!ïã0(ëïö¡Yò"+šíí¾C4—?%YÖ&ëàRÒýÕ/*—ró „\¡J–?î[ãùô£JX1µ8Ãj™jÝ¡JŠhÎH>ÁÕ‘ǃ3êVi\Hø<‡¯„ ñ ¼Dëà#–Ž%®´.&5˜fnÓ–ü}Ù8cÄYÅ|ˆ/é<œ8¦ÜnÌÁ¾žÎ J6¬,SïîyZÃ"áýZE5gÿA°¥¤ø×&a‹WXÛÀGõ}(‘aË/÷ƒ*rNÒ·’x’«|6IÄàL,ÚXÅkV†lšŽ~+µ¤’|à¶Jê—;ðKÆ„« š`SÍiµ/$«±äÿ«ZR M醌]NT¼ïõ‰_j%ýC·U,‰„Œ2u8¤"_žýþûFÛ˜Åendstream endobj 548 0 obj 4205 endobj 552 0 obj <> stream xœµ]iÇ‘ýNøG ´ ¸ÛД*謁-Ѳ$e“cz²>P^9C‰‡%ìŸwDä‘™Õ3=¤ ê®®ÊÊ#Ž/"“?Ì“:™ñ¿ôÿ'¯o}ñ œ<{k>ùþ<¿õÓ-E7œ¤ÿ=y}ò§3¸É(¸2­óªNΞ݊O«“ Oüb'¥OÎ^ßún·ìÝnÚë)„`v ¾(ºpºÌó¤MØ=Ø=©YÛÝ·{½NÁk¿ûÇþÔ?i½îþ¼7ð¨wn÷ÍþTM˲®nww¿øiž—ÝÜ8…EÍfw¶Ö MžÎÓ²Îaöü©û{½ûÐ⻇ûSXøå¯õÙÔŒ±ËîKj<¬«J­¬j©CÍEvëíý:O³Ò¹sí­ßâU­µ÷Ð!5­ëb×ïÏþ¦fŒM§ujò ÌèÙ9Ì"NÚ'o>M¿žšy j]ãM·a€?ïOí“7ÛÝË<ëï ËËâCؽˆcvNí^ïOõä}ðv÷toá¢Ò:ß©U}ø ÜçÖɹu÷:pQgí~±a²Îì^å»/á–çð‡=žÛƧ_Á# _yºó ÌÅ À’×>¤Ø5>»Œ©m^Ê~¼ÅZèa|€=ÿ4÷}IoO `7¼ñë{ å-<ÃY²ÖÏ+½•ýÒÍ>‰S‚k}î£v MÐcùµ>ñjë©Ã:Ù²Øõ×áK.ö:LΘ¨­Þý/üŠ/‰3Ì_’/̓Շk©ÝUSÃAMJ9h™æ9¨8…oQ-M˱:›.z “Šm•ƒ×뤋V–&#½Ñ¨€“ÎÛL“ªýÂÚ¼¨÷Bg`aTYO?ãª_uVœ'å‘Ú¢\Yüö ›­ö¨7Eý/Ñ4¡¶è(‰E?RÇ7Ø0:0ܶàýlrÊ£ln‡"~?‚ұߟðÇ9Xô ‰J惔À­Kœ–UAcóËL´+n ¹‡¼JUjã—†¾ƒ™¥ìDpØ`ŒÐ¯ò‰w+»G¬8¹}g]Tôuž]Vt‹MÐܯ‹b—üÀâgaÆþX ý1O_Í íOˆ#P+WÏE¸’ mpötôäìî­³?|WàØá2Ñè£ê9‹ ¯ }|ö2v ù=~†¥3YÜC÷î0ËÚÖ q & »ã—ÕE¦xõ‡Ú:“XÛ´|C}£ÐÒçu»ûÆÙJwÏ–$°ZbG„dz c4~/GÕF¤uM6vRůôÃûò oV€¤aiïá÷oð¯ûø×?wåÁG(×àË@cÿ¹‡k²Ïʯ¯ë¯ËÅ_êÅ—£;ßó‹é4—û’ï¼]?þoüˆ²ƒ½Ë—›î¥Ï¤ÉCDe¦™Á>‚¼FÉŒoþ¹üð<ÿÀgæ6~„ÝÁ¿”çXß¾®ï”ß·çÐ(¡OcíØùh׋|òñšœ¼;õãWuò¾Îî}ÖÃ]½y{vË”¾2U—5Né»"Š—Yñ1 qöö!~ÿ;þuï(±{[}wxjÎGú3ÿTpéy¹ø´>ó+PßлÑ]–Oõç8h…Ëþ°^=.ÑWÃ5|tã%úœ? h]\…gõû‡²R¯ò:–9Hk MêÑ0ÜÍŸâ­÷úŽ¥þfMØcD4¼‘­!ö |Ü<{6c¥k–­áåhaOGß׋¯ÊEød×… ø‡‘°¼=þt$kl*«r».ÊÝzõ›n‰¯¿‚-ŸpªáG´õÒè±a#ŸÃ²àÛ=Áká>cèc|êME1Ãß™#k¤_ŒDàK lAFx Aš ‰=F7%¬rb=¾o„_n„$¬g‘"ÞqE¤ˆý¸ÀÁx"r+ÎMF“Dá/mÙý¦$T½@ˇ_÷Ä ^½¢(ÉŽµÃŒÖŠòx_ã’Ô .9O³Ý,ÎÃóèC¨#°Ì_\Êà¬Lm—=Ψ„ŠŠ~­0>ÆHq60F‚çQðCeÆR#ÎFH\ãd‚U ¦ƒÄ”è%äž+t –¡{¦,‰§Õ(¡kò+É0‹aAÛeúLÓ‘¥AD…‘”R­4xY$Î~×áÜI)Š0]%‹ÌÎã˜gR§¤hz¡®]á {)RVF¾1éïÂ"©Ÿ‡XÂàiH, ‹ßNóH;.»ð)÷ŒifâÜ\ÏEK¬H|޼#¸2XŸ#É’¤`¤NàTÛo£^½àOÇΫ“fVh×’° y÷¢ÚFæEê-Πd$‰– ³âp‚ÙªâZ¶ÄœùmÖ@;¢ùT4ö¾†·Â6Q+ì2¥àN=Y~L)Ë0ú Þ “i=ûÄò 2Ý<‹+az¢ܧ‘÷LOIÏļʡùq7ÓÊHä…-ý-:SàÇÑåÌ SªþõR1rKÞs2¹ ' ØQÏ7 äÊ;Ëo*rû\Z w/[ô3 Ø2©©(Ïî™zšÅȵ÷²gòæÑ/Å)“ö›¡_blŠY|k¨sD>q ]‘ž9wY©L9}˜¬ÿm_hê{0I‹®\Y’\cC˜l;…o°,0ÙØI:èJúHÇ;,"…»|žÄÛÿb¬!ÿ²ÝYdÄSgÁV2meJx¿jæ¾\Äõ† †’5ìdÃaE®&‰ (è1+Å/“Nxòv9ÅÞ6BiÂÕ·Ë5âóSžHÆ%øbGPlÁ|§Î;ÊÃ0þç4½ø4”øòÞÂe…¶Ôða•»¿CÓbƒP£þ$d¥q³dÅ ·¹J­v] ’)Â!ô5‹CËÝ3d ƒChT(`º” ¬6±iêÛ¹™V»NÂŽçH‚“h§ÅÇüà/ŒyF9ôhµ\ïߤ+Ø¢$ 䬠êVeáÛr²‰_‡‹¡ôɬwf.ÃÁŒ? ÛL³ÃÊiÏ%Ú°žø@ãc>SN:&ÖÓ›$sŠIS$aÌ‘Ä,ŽJ Uc6)«Òª)›5Ä+U˜z±;ªñ”›ß„F«JÑñ å÷z¡øKÓ9ï¶€Òë¥ÄÍsŒ9˜Mõa…Áe‹…üΊAÓ$ô‘Ú’eÆ»@ò°ºÐ˜7ë …±ü*+É‹W #³mçi^šø¥x€¢;ô?Ñùõ1gËdB¾šWZêîÇ•¶ã$­4Àn¥gþÎè.â€%É çOš´fî¬ ˆYÁ6pª–¨zá†C“aÕB"Ò³[ÈwŸœÁþ(ÃÐâJ?²RŸ¯p(–2|7´ÜQ|¬ÝtJ–ÖèÆêm•bYñ¼¶"& €Q¬~!W„;àLØŒ|ílÁ½²”U¾ª,%K>.ŒE“Ð„Ä +¶T$ÏÖq,UZRÅ)‘:’ño„™}! —¾CÑÜÌä*$ a†‘x*¹~™”ÄMh4æXþ”a—ŠšÅº y4“Òa”5=8é#ÖJrvøøºê£éÒ&6@º áÐ ˆa^n¬TÝÐ%Ò`H×Å ‹ ñM_¤UšA ˆ«zì@i~­ç¼KlV2”láóC”8˜ZiK…™žLUrLŠpÔÉ(ô¦dk ¶Ÿ ÕHó$aJ…뮇tÍ;¼s!‰¿-ã,èsMt5jÑb!奼¥et›TÐÐñSÙ–«ö¤AŒ£nʹˆêÎdîÜY±aihƒ®Œ§RˆO„¬3µ2z]²lq¤iëË™A„K-r&‹Õm¡äÙ~±Xß¹ðúNfåÒÌT "£@.Þ™–D:¢M‰ƒ‘Õ?Ô°çû¦¸1¡… ˆ4U•?© ø±¥¬Ÿ'¾R›m_)˰™}-Šu4ZM$üÁ’‹<Ï’’‘áÍJv¹ñ¸˜¬føHì«ÈÔ¨Øê`\A.y>…²10‹}‘+º:¦…E3¶‡Lñ ˆÜÁª|Ãåá¤JqZ$XÎÒ¢KåÅLªà5™<œWI…5‡BDpŽNHõË[|˜~Šš„XûºJN;…LÿV7–_EpËâÕ&îMî&äÇ"mQˆ”çqwÄza©9´Ï@/¬‰ ¨É¤üeÙya¸‘Š ¸…P|‡‰øäØjf«‡«o¤ÿŠðç1+÷"M¸'äšJ£5ß$÷€S>ÌmcÈ!H—®eÏ÷4¤Êš*éi†ûÙ°àaµýõ÷Åëñf[juJéN‰ÿ›öÌù²ACM¹Ÿæ –ež`úOü>Ú e†LÑ].}ÿ (ŸyeûxFá"£†r]Ï7åKü:ÈM±à”ݚǹ,0ÒŒ,ß;CfA(Ÿ‰üµ(6õ¾\¯þFVõlXù¹a/«ÀŒ<ÉŠ1ªÔÇQåÔÕá$ÏNò&Obªm< à\GF:ƒ»ïÖ•C,nŒ0âÂ5Ī.U¬Bå*T2¶Áo†®`XJv •ËIþíî0Â#‡­Ù¤¿”@M°|ßwùµy¾OÁŸrr£,MŠ€IMÅGäÂÏMÏeœ* ʯ*Ïw¶Ú¢ÁtýÈfý$<<üz{ÜÇÔW…å0<+¾©Ï óAÃÚÏ&å„ pž¤ƒ`@‰QÐ #…(ÓåªPâ_r•±[[Úî| BåÊá¶b›_œ–´šãRË´¯ª[îqªÙ0xMÚõ”Ù¹›ÒèyÛ= ùOûŽŠ"0x[è*t¨¶×¨ ÈÙ—ÂØ¸W“ã•ÒuÖ®4´]äž_Ó+|L×ÅÄ”c›äs÷ÕzØžrAÌ$¡²[Ϫð¬róµ‡U-܃ç½WuÑôÚRx9+GN6@Ëò^úS¶‰Æ)¥<ºYŠùEĨB´Üa¦ôã"HUF € ÑÛoøx@À{O…[=gÏÖË@üJÚRíèØ’…|«žb²uÙ(_Ì;aùãÑ8ˆ'¬¥avïRz#\õ%nU±%ƒÆÆ'‚²@Š˜w,Å! tEÛï&W2Mod—¹±îÃôkLãrP݃ôË, bbÓè0^ +.£y ±>8І«´1‡fE>,’!‰¤—hô2$¾¨"ÞQ ,E(†õ€ðc@øçtBÀÓÿƒ»på¢:{·Ô½R*A+vT\4ÿbFBB ¯e]>†ÿ(ú¶´Ò |ɲ& ñkÒ³ÿCW•G™^ÙN}¶;"6Û‡»-¤#\ÝmJ¨Œ9ÝÞÁÞªòš{©As9á¥8AštÌPÞÆÃRŠ^` IŠyý‹Õh˜U¬šÀ6ß*ą̀ìU‚ò–„Û)Åî¨ËX2†Z›Ò&F"×Î8ºëåÝ{ß|+£WšÊìCue{fÝ Fsã¢NWD¾ýxËB_¶XVÊÃ4£•0€îé•7,ø: &Ö¬=?q­GÓdßþ0(HÈ·%Gå£Åf LµãÙòG‰))ÛÓ[]66)³ xÞK.Œ¢nÄa¡B•AAË“dšÜMŽ C]_jbCi/¬³ˆ&2ô‘)8²×H%ÇÄÀ2yîpöïlf‰ö5xéG‹d=éí=Kätx WßzBaÂc¥þsïh;~Iº±Às5,í]…f¼‰˜i^A9Ž:VöIÅYÚTŠñ±wñìE¿>"¬õ­2LÀV ·wúÿ>áÇaü6rm‘Ú¯;%›-hÏÂJ†X®½v±§ðc€¸P¹6àEΆ-9§"æZmc~Á' H÷ô¯…•0®1’YH¨ÍÖ§4ì„j«ÀYoá¡oGæÇœ¦êæ+PÕ .ô—}½n6®ëëª!bfeŽûêˆÑ!¦¤×Ê Æù’ÎpXCE g¤“M¼‘ñÆ90I¯‹Ld#¸ó&mÄATnuWÒ^Q§²%ik»Šˆ{?š4IŠ“X‘¡ÜÌ·ãùÒFÚx4*7õáX*¢\ûØfC!âN\ïrYþfM¢+÷Ì÷<-Œš6åhºëxÜ­ÙîŒÀ´9MÃøÕºËÍ=TPÓÅïMÜOš\+¯¶Ï–~ÖY¾ÙYˆA³H2Éq†¤SIE?¶Û³YcsL/Àÿ/t‘ŽuÜYŒ|ÁymGuµÅŠx±ÂKfÖk:бHe´¡ç¹ô Ü&ûi k<2ÈÆÒßÁAǨÔt ­+;ÙtJ_§B^\¦–%ÄV»@!p (D?J$â°¦¦ÉD#EU‡}J¼ôîÊ"{3î¼(Ùl‹m°º³Û"#éHœÎMܧ=›Do—ÙNýå*{,ððJf»ó‘U#ÆoçEâ3þúòú˜Þdù›Ð ¥ú÷Ì|ñ@©YüÛ00ýÕa=Û»|`}»>4—[l£6uµûVk:NòÓÔîç¸ïถ%ÖâÖ/âÿŽË˜öü‹* É÷Á´{¶µöŠ—ý~_v7÷È8ªÈ9Û=?Ëá¸:’–1¤ÈU{ÈÂ(q6*[ª„i³®»ˆvåy j Ø.åÎÙ­¿Áÿ÷ä:endstream endobj 553 0 obj 6239 endobj 557 0 obj <> stream xœµ\Y“·‘~§ù#&øân.§T¸GY–´Þ-™œ°-óäHC…ÈÒ×bìŸw&Î*Ñ=M C!©§ …#‘Ç—ðöl]ÄÙŠÿäÿ¿x}ï³Çîìêݽõìkø÷êÞÛ{"68Ëÿ{ñúìÐHHx²„5ˆ³‹說ř“gÖë^^¼¾÷ýNìÍn…åÞ<½øøJ ú•\õ,|xq ¿ØŸ«Å¹Äî¿÷b Áë°û|/wßíÏÅ¢µqrwÑÚ|™ž*íwá©‚nwÆZ๔a‘]“¿Õ·]`Çqþ¸×‹÷F[úâÐ\šE¬~÷Õ?tÖíþ„ï}PJì¾ÙŸKl¯´\`¤ØNúÏÐØZã\|©°;±{²?7ðà ¿ûû^.ëj`–øÅŨ&…wñÛ¿íe"WOäóL¯sX«!$²ýßÞèÅY¥vÏ`õ¯ [˜£Ú½OCé`v?Àº`t)wï`²Þ-ÞãÖ<‚?Œ kSýŸ¶ÿ{¾n^b7+üac7@q­Ü"¥ÊÄõbU»—©½]-Là\ºu1&ÀlUœ  ³zI Þ/@4ï¬åúýt¶ŠEÒ"ÏD (P¿½¸‰/$,NÃà­#üà§B”kìöÉææuE•lpi6®å94ö‹6[ÃÓe:M¬¶þaœWéiçÐ.ÐÁÛìp{ã|áþÖÕÕÞ¿€zQJ‰*‘æ6ÛSÚ;as'«ÈŒ‘g¤ ÇHO8&]X¹³~J8査HTkÊ»#ú()Zë_÷ç+ÎÏ»{“z“°Õܜޡ‹J? Ì( 'C6'DÚüs_ç±”æHÏóLÐs¡ ãU&ºn92‰Ä¹4:”„‡mÅG¯¡ˆ±³š<Ìé2—Y™Èä,ôçwÿnÖ­Õ~@;9²W™­TÃ9fªÙ5ƒLÿlÞxÙÀ`oÑI y0! ¦§Oë´‘_Žz"»ñ Ž æ/ ŸuóËÙÅ;X뇞E ’t&[ óožÎè:‹ÔºX]DªM5”ÉQ ^‹H»h¥‹2ouÖÖáÀ À±^€g™‚̃™ÄÎQd@Ëd^B:¢84&±½©•Ä·qçt"^'0‰0–Œð’Ô<;%­úºIyÒÀV9N³E*F923“·Û(nü•%ÞÞì;ÎÍ›åFõÍÄz\F4:`‘AFTƒÄf}#qà7=ÿ]7ósÉ™ÂKES@¬å/øB„qyš*Ôivr=ÁìF;vÕN(MÒ ?bÏi“™îÞá[¿ æ˜r!>Ú°abÿN%•þT’¨ŽŒå“Þt¾Žò£`á^‹"@Ônò\¥}XE%s^!Ãj·èAc ¢Ñ:žð=PKFj½(=ÎMFë‚HÖû&‘µ‹Ö°Îó²ö…£¨·2)É~yáž? €ÅížTQú¾¹wñð{€¶`kCp€eÐaJy!}Õ‡‚{¯Bá„w_Ãû`TšˆøbA æŸ&£@(çgÐdßHé¼… Á¾,0ÑkXÎ R¢(ÚXþ„kÊÀu$Aˆ :Xädø(FhœA8`"bT0ÀM´. ÆŽ5j5ç£Nbpgߊ1y6²fÅÏ:cP1q0~²<³& Bìû *M°é’j]ÔaÞÀà‚>å J¶¤:©åL‚—Ô$”îéj£ÎðaÑxÏðã° G2‹èv#îÎìVp:vKàá­ Aä+Mûüi«[ :´ÑÚm´g?Üõ Ý"1zËÿoA'T—M%±ÄŒ5 êA±Ï”󉽴CòД³D!Œ\·³Xc£eÙÊ êü‰öË’Ô°‘?p6cl„LÀbtú%®Í€Ë¤ÀÈš‹½iÜOÊŸšÙižàÌ *3èâA\"Ùõê¿“0/*+pB×2pM€PS@^¦Å"ÁÙqÝoZ›ÆtŸ)UÉxô1ÂjFs`&{ :ÚmÊÒ©‹9u:/ï;!ê÷¶Ã¯DR’è;áKÕ‡Q2Mz#0 £(›Â(÷GÉTû‘à'‚K¡ ¹{×…t»Ú„ßR+TÄ'yx‰Ì[\Þô#q;J…û:.T}UÏó(~×á§äÄ—·€>ÊuÜ£<òI˜ ’ ›sT%ëë]]Ý¢$Ýb×Nù?gÖ\{”`ä<ª%âÄeP.eÙϯAN8 ùýY¥å5LØ·:qmüÑ4 –è62œ>Éq‘D” ­‹àáѨšU ”¥üˆ#`C7FEÁÆJX ‹rã@&Œ|[·ÎT¦ Qº¶=vÍYHß«ºÒðI’›ö@œ­kîýe¡‚ÞRf&®d4—Œ†'QÆ6"~skÞšüƒ!oÀ‹V¢nÁ¨%Ì ÜoØe">í˨L >}¼§ÉxÔ~ô ©$*BæÂH¦ó~4X¿ &^5­ ð¨nÏÿ¹‹¬’“Í<*Ÿ=orñ¨‰bé >"œ•Ó ØÓ£ÕÈfvDcp •­qïúmC™T¨6.òöI~mFv¥8ß³Çd},¾sð Æ;½Ìøsf­4rúgÑ~€%´5¡Uð΋ºñ§Y,ÙØæ=oÜGy¿â¯g=‡wSY65ÕxœixÝž" g©cñ…MˆUîþw“ÃÈ9:G[Gɨ$¢õNÇW{!+b68f˜Ÿ4”|ò$°êÖÛ¸ä-Å_06ºa¼Óq ÕOÓ·@eäÝ©²•i¦`H#wÛN qí3˜³Q«½ˆ—]Ë/ã¥ßæ<Ö#8½Ëþrû^냘>¹Þ˜ÀÝæ®fö6w{—^ˆ{ˆö€ð2‰òéÎCO =TIŒZGEÇøwõ)™mŸsúì±ö}©ƒ³XE¨‘ˆòf­Ðüá ØD!ÒŸ¯ê[œhÜ]4ç:`èH쾇•`•¸²ð]ß[ê(Â|Œ|ן¯êûê¯ØqäTì8?Ãadr^ZË_[GoêÃå–àܲŸ?¨Ÿ´Ï/êÃÏÛÃÇõáE{øE}ømýõM{ý€és|ÈoÛÃïêÃ/ÚCò¾©éi¡¿ˆ?Ambâib~Ž~5`ŠKlŒÂ¸hâ#QJ3`JUbúJˆ2›>Á”TÉô=Øãg|Z~³P‹0ÃÇM¥ñ%¯LëhýÙF 5“¸'Vª>éë7?^¶J]å± ÐßÓ²OF¨¸è\›Õï“À€µ"ÐÂP¦Œ4ΑɄ•.DÓ{$‚LÔáüZ…¤ù_Ä N,B˜ÞºHk(z—˜ô–·—ò´ï ý*E¦-B“ Ëg96¹‰j 2—©>Ë\ß´šŠË–¦»IÁptafŸJì4oºRHÙ+ÏÛ8"óí=©ÝòFÎÖ±Q«fÊpºNJgõ|Ìu¨ì¯µ§™ÓÄ=Ö>è^ •ÔÔi¨5™«°ˆê.;c¾E+.\š3 G-EªˆSK‘óŸe ñKØ5…Ùcr0>cÒŽžO«¯¯öI“ Ž%Áþ¯)¡³x,5>*-VM¢½8"6xZÿzPÌ4¹½±&]j)ôñc’Æ#Á»tðÔٙϫ®¤51ŸÁÐøsVOÚǃ§–ñS8 6…‰2EWÜ÷Q&¦Bü²¸ƒ3£´%Ež§••ç庪óJð¨Nv­“‹..“<É…\VR Rà w éÒFGe^Î<þ¨ì”³šÏÒ¬1ãÅÅ®zÜÕºÎq^¥MÌÞždÃÙLCöQ2™zËqxÑØX™‘<¡&j{¶+ÒTV÷£ìô]î–~ï Õ]=í$DaÚcŒÌ%¬; ÑO|qeìö¤ö»Š³LŒˆpì8 Ħ¯¨è‚XDÉÌñQNdOñQžá-ðѹX‘†¥‡¤¯)Ý Ež(<É«¿îœÞ–¨§nb¬â˜Ÿ†±âÍÖ…. w9pñt™¹. ϱ7dÑ¿¯Þn‰&À®²'úš?:$ÌfV"žõ|ÂaIE,É¡Ãéççµ`wø§Á­Íù%dTâ¬o¾Æ÷WùìF0¿l±ý ö"ÐÒå‡íý“úF^>抜Ö_ºèlo7P«»þ®=ìºG›C¸ñ [èÜüÈ•fޱöÖÞl–Šh¢ˆû¸’q Å0ØO»X7ÐÌð6Š}²u9* åM>ÛQÃ4D3ÒP¡JÞDÍ¢H-ïgõaE¦©Lbõô\MðµáìÌ6kIhÀ‡Rú{(ñ@V½`ƒ+D´5ñØK4Ó¨Þù/!ÎiM»þ~&Ò=‰¥qÚº‚G µŽ|Õ˜8MÓ°YË÷Û\¤ØEKUß1)¼eÜ5ð¾Êñ4ìjçÎêNœx¯Ÿ±r0½?÷3ã/“3¯DJ†Êø×ûx¼ÀÚoòw°ØxÞ6ŸZŸ §·ÈÉw œ)Ä{VCl4Ρü-îω-e ŽÁ§(,›zhíÆ Ê¶§´Z vˆÊ̓mxyì‘rœ,‹ ž–c6(“9Â虤-6ªfËO†lâ´™šcÔ%vÛëp¾ÜÑî:à#6+¦w;Wž±GÕN"Yr÷d"+°3khåH­¡Ävý#Zù”µçûßÔÅ8CçðL-áÝm%v:ð]ÒäÔ Ð8Ä iø¹0v9 …s´ UÞ×öd0–£¯âfÌD‚9¥ÎÉË4jÑhVsŽcÊ‘ð~ˆ$·4ÀÆGk—:ľ6%$?wŠÞÞ<ã~-k‚VK ¶]N¤èhë–~'$©;pñáºM´.Ÿ×·pNÍ̧·å©îhÜ‚|¦‹xÞor© Òá8r¿Ý.ŠËȺ+jO+M)דA“DýLRæ»sØL¥@Y渘ØÖ™¹€„cg#É…!‡ï1ÀnoyÍ‘¡X2—U_o¹Ì51XÓýÑ¿àíÀa]±ä on_M À”ëÀ>ÉÑÆH›M‡$³ò j1)[ˆ97Uù~ "NݱŔü@á©õ¼xqÀ8D4‘iÒ¼SÞ3ãЛԹkÜCÕ‰Q—d!ìO/ÚP©H¶–àÔCNŠ$zLoþ&¡Ò¤%µ5TKþûC-ZŸj[nq€M'h!=©ÇÂ?¿ÚÇ[±RuÄß9Z\c5‰½¥1c¨”Ä¡ oö—û ÍkÛï ê(À²Wà´\ ?…ê0íOéG“&%-u¶ ܯÄp±ì›¨ìžDl-MCr.j_-ʼnJ>a«å´ŽmÇ'vqí¿Ã;}•õNï>zÚ:CrÄûÍ)êj2“=µÚ*#àsÉ“Mìß7…jОöñ°qP]ÎâË‹{…þÀû8îendstream endobj 558 0 obj 5793 endobj 562 0 obj <> stream xœµ]Y]Çq~'„ü†_to¢9:½wû͉Û9Ö² ëaÈ¡†‚IÎH2))¿>U½VõrïŒHA tyÎé­º–¯–n~w±oâbÇÿòÿŸ¿~òé_ÝÅíOö‹?ÀŸÛ'ß=ñƒ‹ü¿ç¯/þý >Ržlaââê›'©µ¸pòÂz½ yqõúÉW4‡í(7çœ:ø‹ˆ.ý¾oR¹Ã_Jnb—úðÙQ†ÍYi_/•²›”áðŸGM­1‡?/Åæ}æð磷۾ûÃ|¸9/vuø=¾ÖÚ8 ]^î›»Û-mõßGyø4гu‡Ï—hxó—Ö6w£´?üGìÜ… r/Aì.O¨{H>ýí1ìÛ.d™\ÿégøTJi-LHl!x¾¾ú/ 'PŒS±Y½º*"Ñvø£Ž&}ì/46Fâ·—ùãKµoN„Úøã¾©,eƒ‘”òB@Gõ¡˜½70S¡Ôæ5HnÖy¸?¬”‡ë£Þ¼Ùaÿ<^›Ýê÷±±³ù­ØÃá,Ò|Ü ½í ¿Àï‚pâp #ë}—Æ·Æwi6Èo µóÀ ¨­7£WíÃWåGš‚¶t->|¼”ÀWV”yc¡Ã¼’6ðŒäÀúâêÏO®þõ+ØF‰ó@1FÀì ŒdñÖ¹ÃËÆ:/`‚Z XŒ¬¥Ü”–‡çõ!¶{S²@@]~ú¸^ƒh©6­üá£Öå«"-y@)ºQ`UvÇõåïÞ´¶·ðZHà*E‡MÍ¥Ò¹K§]Ã|é7©©¶‡[q‘°¥eU{ô|Ò-´ÕÀ…H³õ‡gm2×@—én ±B¥]š.érؘåš_‘ô`‹Œ• */šÀˆj3¶LÐJ`õûô¶¾®LbàEÚž`t|þ ;Å|y±i#¾Z“Y7tÕFBŶ„fi?Óî좛HëùEùà&-Á‰(—‰(—"ÒÚ'ÚüØí·{&yPÆá’§â`ÏqßA€LüÄ”¦5_³¹`Û°$eu$x徸6ЯZ)këâÂrÓ]/ Ûe*UqQüŒ£‚€‘OÞ¡í‚_‚p6³¸½ê áÛKC)©d¡2c*£Dœó¦…Z›ÌT^PÝÚdN q[lÒ©=î´ Ì´(üFÙH¶ISÓÅ@iûÁTÄÏhm%Œ¢¢…÷NXÂf8ÁŸp‚`öàÅ7¸d­½JÊñ{$­¡s¤ÉËÊ„y 7€º˜¾ÇE¾l˜ áUý¤r|Ú¸°›öiè,¤êbìþÕD"k“Lki“Ür^F%±ËDUÊÍH2ït²=Ú3sÖr‡ÆJ±CêD²£bWH;¸G LÃ_qÊhó'ñã¿`RÁãW‡§õií"µÆ~° 4 3±£ôæEýõ¦½¾®_·‡íKF{Òa_å@û£ùù¹i?üv]ÚþTÞ·‡ßׇØtÂŒ/ÓÜ€5 ÞÅYÀП´É<­-~l-ž×‡?äÚ´úþŽ¢¡þ¡=}Z†Ô‡¯óÏàéÏ¿ëÇ3¼qÉ6]Ž!ªj 42@¢€ qJñJ›tàÓ#îPfǯËX…4‰Ú7³áf¹>2íý$ùM’E«¨P¬ï[OM1ŸQaÒŠ¨!îù2à5GS3ßžåv¨Œˆ¶ÚЀš¨*—J.’ÔÚëR ŸvbâÐÞoRMÛ­-©ŽN‡4É Ngô]Ü@£¾)FBjò¥vG¼iíÈ›×G%€‘I¿„–ÿÄÉzÐy \Á4e š GúÞ.6äqI¦aT¯¦hHf®³­ÿ.ó¥®Ì¼Ãð %4ÅM ì¥Uv5H¡Ý“ÖƒPà†½˜Ë ¢/`»²!ªÐ_…ûøËh8»_¤añÍTh±ËÓB›ß!Ý #©ÄRª&«ÄçÁùú ˆŒÌÚe•·m„ûÆb`«½BŒ2âü&ì*&Ð$›wJvŽ¡‘¶Î€lÎpu€kæ°†P~&žMÉàŸ‘MÂè‘6i|ÔX½sÖ3s¼´.DŇ¾-‰~¤à…G×äOˆð`¶ ¡‡Œ<×jðÖm©½+«iÀ† sŒøøÙi¡è˜âglˆŠÎîÄožMçWø­†šÖú>®Dë‡ë{ ˆu©îa–6v×ÜãÔ ¡±ÞU7ûÙÊÑ3¶É˜^'Q0±ê¨ÖÁzl™•2°Ø¶‡ä&ƒ³U(e,3í¶p{'¥3‘.•_ïfª ž7Þ'4Æ.¶ ±tZ#WïD7¿äœQ„Ü[®Ê•1ú@¸¨úæ(V‚‘­no'RóIñ¬È³úÙ¸÷lËÌÇîà'±˜àg—ö'‚¨ð[x.ÕTÓ?' žG´©ýöx©ÓLèPéhÚl¨VbØ9añ7³÷…àÖE/º þÀ)i^æ“z±¹Êé«8 F‡¹ˆ T1ñ [ñ £÷§±¦»ÿ/ÎI¢Uûë$L^*_sƒTûºN¾õ.TÁÿRh"*ƒÁIµ×e—“áR¤dŒãTßâ¾Ù2£=‰æ6)|ûv¢éJ{P®°1Øñ;˜:ÁBMCØ¢© 씳±oh|†·€¥§Á6®µsìΦ;<Šê x‡}¡Aû©•0T ±> z[qÜ0Qy3½O0¦Ü0-Ò 8È”A új¸þôRBùäp‘ˆèÜåшTd¤«¼Û¬“T"ß6æÏJLÑÌa=º 9XšÂ‰¬éàïˆÊýôÈrA)!åa_$¤Š~±+³ˆQûÍ× û[?$¨åmãw꟤`pþ³ ~nq´¥jÄF0ù?–äMiý¶>$øá`Ê ÍRY`PÊÍRp«YT“°CÈÚl÷…^ØÉ zqÕLX¡qÛ³Æ=D-d% mR”qh¤¡‘QÕ/iˆ^ ¸ÛŸ·!³x(áN)åÎAîÄ¿©³Ä è@@ÒøgØÕËć_-@AÑTð8Gú#a¸A”φÍåp†D¢ÞÞ\¡ ÆIf¥-³~vÀ¦– jÿ{”'Ã^j’‰Q›˜ uf³P‹‚ƒ£gî;rNÖ ¶:ˆE;+¹½1Ì]tÖ‰¢è1‘3»³ÄzI.r¸ÏFõ>ÏÚ?¾‰Ôj ܦwÙŠ¸ÍU'û[B§ÑJUâ1|9ϦÄ•]9¿™#YÐ'»aöÑf¢Èeá À`O^븃§|âŒdºpɸiੱeÃMÌ›{Eá…L£€^Dd†¦w;í³«ó9¨)9~³’K¹E¹#ºt›ØD- M#€÷{® Øct×°NAíѰç@ƒÏ#0lqÕ°óçy‘NŠ…ÍT‰XÈ=剾èÝ1b˜­ù %£µ‡è<ÝL¤ã£†uÞL^ß´õq? ïâuš&b>Ò{ÑBÔ0¼š9¼å:¤9ËH¤T´Š/›,‚íÃ̘‡n²ýe0˜šl©…™†µÉŸz@@ < H2Š&#štYÄýÆ Þ±ê‰ÚÏiL@=Õä¾:U9X^ì¦u"j¿È4~Sh…€ÿ6e¥M®rƒÛ#K*g@ŸX,®d1ìÄ带5^8DŠh “½#šëÓâ…¨sÙySDôs×3ì!fâNÍÇ/GF§ṟS¢Å%jÜD\ãµ›”;…-FÕ7©–(©2Ž~{G #¯÷K½Iò4³;*3s•„’³mŠº3Ô-'{Yÿ‚\ÎÓÜÇ-gÄW#0˜z¼ÄAx: ެŒK§ÎoÉSØmLÅzã¢ñ72hðK[SX£ƒ‘ñMuHJGß™{Ó…³g¤(ì`¸ë“pk7¯Ìof8ˆT_7 Ü—3dއëÿöþ³f—³Ì r5 €ÖäËÜDÈfR±00¤ëÆÊI¶Lï”ÌÊwHÔåR»èœò4¤¶>JÙà¶.Â!ê¸@§'ÒâgŠóˆÞ˜1C™E`ªw&Fewd¾…VÚŸ®¢ÒΡó°µKéãE®aPA7ãDI¢Ç%Ï¿ó±¦vçLKïÉ&ÿ;'?„Ý‚¤Uzƒ”_ÇÍêB·È èƒT¹˜TÄ}4V‘L`ÕÎx<&ôʬlâV*;¯7ªM7fv21¸t`¡¯unΘSÔœ¦Š|C×UL)ÑÁÖé/¤Òpý©âˆ‰ËPÓ$5Ö̱)I…è§y4wÊJ¤ëÙº;ãC°T™ˆìÀ‘MŒ;i1j©èUY#n8°Ôééj€¦F”¿tLORÅ¢´ŠŽû4üÜ\ÈZÐÈŠ0â afE-¡û¢etÙ™œ`l_åVÍlV˜27Õ ÜZñZê!¶#õ[oê7Û¬àŒÔ–µ"¹§íá'VÑðX‘z¶¿´÷ŸÕ‡Ÿ³F¥ íË7Bh’žÎ ÆÌæ‘jœ|ô¼C–yçç©‘¼þWmŽù´‘¼·da@(;fÙ—P2¸]ñz[MÖ9scâÂIj†UÁ ÊfP+XÛ”æ7 ¶[nÚ:KGdžæ{b–c÷\ìB\ú:¢Ô›*ÜTÿ"IØzg;¡”TèŠÈHÊgY’'ópûR‹zYÒáˆ#ãTdèìk易1Ã\ý"Kܺ¥6y îÙP “kVãœ: ‡ÓÁ2ÑŽW±@ÇΣWg„…‡Úp±™ç»â«<™g|ûYD£µ- ÏSŽN«{½ô½ˆ•4hf§oRú­Ì{Ì”üÆÌ°ÓQÓ"­}Ï\}²ƒ’‰*§*b5'+¶ù²X:¢Îœ¸/$n0KŠ%qÐ^î%îPÛ”­1‹º0ô´ÊaŽ|;/3™x¢s'69®Ru0°,½ÓþĶ¢Ñj8S ^”’òqBI¯]%£úhé Õ‰,ý£Q“Àb-¤±ºs¹JÜŒ¹Y˸Ð>bƒ÷r¬ B*5WNž>„3jIffT 3PàX§‹Îä–‘¾œÉtqð~wÄRÑVçÍ™S9@f,™Xw±V ÜNWéé::&>3&³9Ò²3Ûj‰ËS ý¬®k:æùIòPBË„¯'ÕÈdÂ9=n’-Ñ}\KKZïÓâ„A² ¨k/~>‚âvVµbC¡Ú\HèIëzÆÏÒ®räÉR´–eÆn}j¨À k4!ÇiS^5×E‡÷‡]ÖÓqò–­2NyÐsqÆ\Ã,Bqð(KŽŽ§G?h±bP1Kúž°g—N´ÐÃIÜÅÓd ¢ 9Cü•…lüLæ‰*‚¸…cß"¼ÒIC‘œï´6eØ îþgfˆ×ÑÑsŠÖ-ŽÍ§¬$‡ fg‚i' KMžI €(YˆXN –'hc)‡žyÀE_Bße ÊJÝÙ txo°ê¬VªËDÌÎÅhghÏ•]òbŒÌÇåíÇ€¿ìêƒT up¤rç=E é¢EÍ‹ú­ùÃ+ †ÀÙÈ«Dòhe–Xµ¤ ¬TT\79êñy•X8.4섪*¢×«*Ò)|@Ln€ÔеüˆÅ“Ð{‡ë †É^öb (Ë ׳yA?5ýÒŸÀ÷N³ðõÍŠ ìôö—øú®HÞ£« ½P^á…³)]~.iŠE!jˆ*e©~!Ÿúsv"ñ%× ÖGÈ>¶=§ê"u¡=¦’‘½X’DSžw5ü¬8{& ×ääº鹎xK?¦^[ð$RVjhvÙ’¯“HYjÈœªÝ¬2§AÌ3§¥É‡JfbqèÕ°Ö]®”½£_ u¾êŸót®Õ9W†ó+ÈSïv!R=F»Ãå½Ób'Ý+ÿE$/K’D’©r)•À‰áî©@M _çõf¨U_§H  €IYþh‹<¹§‹~AýÆ 6Àúï¹YRHÜ"nO``›xÖi8·JåEA7²ÁÙ¹š)œ t¬tÀãœEÞ©›eÈV÷±”º@m&…¬2`ÞbñË,&Å'Æ8éÂÙ‘ðüQ£‘îܳú¼äùð-–#|¸È©5xE¬Ÿ”õ•ËWj¡ÓGìÐO¾L„Ë"/I.nṃs&gâ’N‡‡˜WeBDÅ]:"&çû£GçÊØ™¯·Ä°:ör®zzHiî·LÎjïä€êI”‹;‘˧¢ßó’$ÂÔiŸugàíéZ޲±²¹ï§«4ÊAp³<â—3WûÉC®ÓBÐ_ï•H÷™rž!¢ÀÍg_ß›dÄì†ãÉH<Ö™Çí†ãXkÐ"Å+¤ZžJ8wŠûuŠa/“a—Bî'lŠØO˜² Á'—_,kÃs ›—c«c"çâ:9GÖs¿üÜ`»A;68 FLíÒmŠõ…Ø/†²èá«¡Å©uŒ²õåqСSþª†‡J'’ÖeùFÐŽ>º$CT‘ijË‘E,³q§î!@«3¾u*ñý•m‰{[]£q]ö8ë¨]I–Cn,znNV˜–î[?ó¾[­R5Ñßppö~†xëXw?C1*R‹ÿ¨×åKCyµ=;Ò/áÔ©S›*"+Ÿõë¨gZé=¿Ûã¬ê§ÅhxŒ\è÷œÕ†lvg™¦çi‚RÈÄ%…Õ¯+ ++w‡r 1–4E¶fjd ‡a “H§ûOàfÉý«WÙRHF°0ÊÏrÁIc ÒÕó¸Kr]šÛª”ê š$)ð^уˆßƒyŽ—Ë¢†÷µšc¼¯õ`éîÖ’ÛýÙKrH‰Q¹¨ÒÀGDý‰ïQ/tèpLöåó9yÜzvNž8?}ÊCÝ©,2üR#C}“L'ޝ&ç§M4lø„•r^-BÝcÅki•é3Y¸Éä~"^Z”ŽÀ'¹JùæÕòŽ;jÓ ŠÌZè>³V?¸£=ÏÅyþQžnòös7Põ'ã«ò!et¬ƒ  - µZ9ÿó6Ë€Ÿœ=¥‘4ëö`?8šÈu563·ÄnŒ,IΔ®QYMR3ÑvmdÏœÝç¦ T†ŽU*:sÇCº1@Ó£@ &ä›KÎõ¯d1´±`Z÷tg P1ÆRY<9'BçÏæøæ#bY©d\¬±P¾oæ¸#_þ­PÇÓ‘Î(²Ê˜±t’/¢€"?É • þ¾ŒVPÁÊõK÷7¯¡BucgEœØ‰LÐ !õè v¹³f³ïNàVE?^w×AâfÇÊ‹h© tÎW´pað¯ËÍ‚Àìè4…Z®9â–aÃw|ZØ0Vm•è·JKÞ¦|V¦?Î2äã ‘ÖT©¤ê|;×lZåTëôz\Zø®IÐñCœÀ͈“‹v#&¸r9þV¿ù¾=l7ßÞ¶‡í†Y<,Àoj‡>m_ªúPÎú·ÙCÃzÍ“S¬÷³ÖNÏà?¬À/È™]¬óBk¼,Š!¦E¬Vû<ꬋ>ÌC廋²œ:$R˜eœ¶§s¸£+ŸÄxÚ©cIÁSŸˆŒ†þ†³Ú[¢ó'‡îÂpm?ƒ• ­´t À~2.†§)[yl®”Ñ}ÐþÒµ÷9¹‡‡ô´~d´ […z~'¥¿o›¥ÝöÏt9žóˆQí?¸¼$çb㺜bNukSx´;=ГùeVÍáø7壨E<~¸€æ¼in‹ÿÜËcLKš¹á|”!rzÈÏd¦´Úg¨€A Ev÷ÈÅ#Ÿ%­/Ewò6”›å’üèVeºÂf‰ƒ- ¾H‘ÕÆwñáüž¶É%7Ó[Ì'DjŽèòïþÙ '(|xöTÂﯞüü÷ÿòz"endstream endobj 563 0 obj 6131 endobj 567 0 obj <> stream xœÕllç’«äâ[ow+I¥dI–ëå}zS÷㯻ñj€Í™‘½NêÊe{D Ðï'¾?zu4à?ñÿ§7>}:]¼z4ýü{ñèûGŠÅÿÞýæ Ržô~ðêèÙ·Âlu4ë£É=¼|vóèÏÕÙÍÿŽýë³ÿ„YFñYz{?ÁÄgg0ø³nkúyö^m~שÞ{7úÍ“No¾ì¶ªG;ëͳ2æ‹ðÔŒnóžXvãà[=<×Ú÷ºò<¯¸\þ/øÎçÝØ;glj¿ø†kÛ«Ám~ÛáÄyš7¿Ç÷Σ6è¶Ç›Q÷ð%Z7ýG×j4ðÓn^vÛ±7fôzs3 SZÇlnóÑ[Z1~ yk«±·£¥e¾…U½G³-âŒÓÎÌýh­Ý\ânFÂ>z‡ï½³zóWTýìæêóf`”AH¬~U{Ý#1°j “óü«Á>Џš' +"%èyî]⓼…„3ãz=x¶ø^œá¶vãÌ‚aCƒÂý˜ÁòÂ,oǬqÆe¡o¾øýè*/yÑñµp—· Œãæe™ëŠÈy~_3udÁi˜a¨(â· ¹á%®3ÇJ(USQUÞÕYäf£¹ø9©¥‘ ‘² Y+<XN–ãOÂþ™ôš=ë`âÒ@Q‰#ô¿ED(’=ì˜ì\÷A {ü;‘ʽpì«¥0g?Ffáã³ÌSa¶–LhÏšP¨'WKäD±üÀC‘l…l’.e­“ÎÊ‹¼ Vͺˆ' w|£/ò’+‘xŽ |,IúZïH£i0Á4(† Ëçø>ìJÃO˜Šn9 ãžÜù…2í6Ín‘¸F.f+ƒù’ë'òEmú.Ô@9ÞU¤Ü©ŸrT&šF?˜`iÊcæB~úttu\°‰a=ëu@ë}  8|m"[h÷!Ýna‹ ¬^„èÖbà¼ýçy€Bhz ÙÛMâûü½ÕYÍh#ÎnÂXÑæWyÀWUØü)?¼-«ž—Uïóû«òþ‡üð¼<µ`h{O˜MO¿/?ß„ŸH²'åéËú³`d ƒmž¦Ÿe¶›»ò³œÑm°?’ÄüÏzÔ⻼{øæ§ A‡CN÷:3\ë‚æ0åµC!iÿ™¸n¡¸hϤ÷{&­ÑÊÒ†<.rððéï¥éOV¶œ„äq!Õ'¢¼d^DMÖ‰_¿Z³Fî¢Dù9¤G9ÖÍŠ‘…àrÒ Ç¹Ìµ‹²‘F¡_Y;˜,Š+F(ªZH½[Í“$Ï;×=Nnò‹ê1mÍÌ}&¢j‚iGlšÒJ~óËP0vsR…µX¬%暌ú@-+‘è˜á’ÓŸ<Ôâsý?N+U´ ¹Eú5óß»ãb”RÖôËCa¨YKÕÏ:Å)Ø8²½ŠÇÞ–]”Ô$RÄ4㎢ o;U˜¢5û“‘,4~YÂUðyx»ÎPÜÖ‚Óg%) èÅìxh‘†iC‚qèæaª¢ÖÍo3áp !“'–Xeë`ï?"$˜FŒßðão;‹…ÚµÛ¨¢u”Ù€1Ù$~LœÍ"¦ùWñS*'ÝÌìà+q9Ì;ØŒÑ&—•€tDáh1°Gü{·m33ñŸÖG&3RŠßë’–,»Ó!SÎóJb)á¼äºx:dr3ªòã+…ßʉ@/R¿™ Ü: ØöË9*©‹¹HMEy!§“3ô^7¹J¦JÂi÷¤úk¯¦sO\}$ØŽ`«vT*±¤Ìžòµ‹ Ý…la@[i¬!¾Y¦òhgfLE›u*¤Èò"!B#ñ:º^iUí–b÷FÉ¥*k2"­a5‹SXêúÛ¥•³yÆN˜«m2*±œÐý”“.­†ä¡ûˆ¶*?&€“Ú ôÍÆX>£ô*sÞ(ˆeÕ`ä©=4ŸóYe¥ÌTH*.ÊÊS;¬š ZŠ4z âUÀÆ¿uÉ*²Š$ùäšYÉ–©SçEü‡nÔmùߨæš°-¤¥¤…—yoŒi†J§X©¶\ã‚Òø.Wª$¢çX³ºÈ¨ˆ&X˜š¬8t Í$a“ÄåAæSÅzd‡U‹§&Óš;¥« BF­‘ÞIEªŒ{îÂA1å!$6'^ںМuºò1fªXå³ø‰‘’Á&sLKE­@Àª­¢_wT Ãj9Þ,B´¨ÕD†ì*AŠùûÂ5宋ù€3@;ÛŸ˜b}øÒ ñÉ,¦`f¹x0|Á2‚lLSVpÓ FYkcn¡e æLQùì¿.i҆È)ÎÚ”IÓBmZ[¢ ãï…Ï1‹=CWÆ{¦ãÌ6…V™®Å"HT„ÖÓ_Ãày¶ŽÛþy¥Td>…샶ÌYpm%9«_H¦èN{Ñ)ÞWÇ"5|,l‰ø*ô©šU•›!¡‹öBÙ ¦9sKzƒoâ<å¢&€T滋?\ ÷ü(¡h³.|cå¿h3± 6±:£Õ^‘ú9Xx§¢ ArAAÐ$†V’z‹>Q¨ö{Ï»ð²þõ½Þm>éª*ìªÍa‰$$]¦ò‚Ÿt¹`Xj©È§ŸW u\Œé<ö‰“šSß/ô‰ÉæUÖ'ÉMàžD¡ëeqã¢B8ùI‡ÔÄZ ßs¨j9b0U!l0+•0uý$³í¢Æ÷hT9Òà¦XNUØ4ƒ\V ÆÙIn¢›i<¬»Ir¹¨®Ïh"Ä)Än%°K7»!ÚS© l—]"®èÛ^¬\M ×5N÷L%s™ªxÅÇœCÈ«0Æ)žJ] •jAGW­‘¡uÊ.Ù[ ‰åJ³¡uGVÙ ÆQE=²f³¦êG2kæJ}5KÉÖµÓ€2 @ÅzhߦdòsFuYX`Ûià¾: £#ÂB¥§bvlËöÃR97¬(16öX4±ÒR¥ñ©Šn² ïd±óˆÔw,p´3 ’¢2¡ËH Æïj'Vkj¿Ö‰×„h-즇+}|GÙÍÅy‡xcÃÛÓ,R£Ld™ÂZÇÌ¢)éó„ ©zYyX·lR1°ÈgeÍÃUXÜçž"ÞÛÂÀÑfFÕ²H=ùàP¹¸öÁP“è®pÝŽs.L3¡Mlø§JbÕòÍëXZ¯úaÎì"'-äv˜R­F4\¶—„„ź—BEÌÊ‹L²Öyµp晞b ›ÝHD;uU¬Ã€Ûæ¤?µšÈoªÎ1哚ë€>–õÏ5cÊôô¾pz|çôwlÕÍŸÑò¼‡Ði´ª>xÝoóµÌGäiïê‚cÌvƒ¡ŠX\x¤qr[JÛ µ¯MeéçPx·Ê Må^¨»Ï]P}ÜíÞ2ŽÊ$Ä­5‘™[ZˆGÐ(à1ïe—/@ª(T]>0ïTQˆ:¥gÑ@•fÜnì-oõ K f’4 ’Ä_-IcŽa96OÕN=öñ˜½Áƒ·L/íJça›ÏC„ÂzlK'LNÏæ¶·ô›„žÊ j͉}£;¼—ôìK C/ÈØÕM”a™öÝ»`@æÏ¨57UÊ„ '¬m';³¡³TñðÆLÊ4üvqøDËuX9m3Oä‰ËÌÆEs²vIs–gQe—²ŒõÁTPÛåY€‹uô iÉu¿Î©d4«É¨ßÑVRõ•UvOŽH'ãÅ ¾òd‰ÅkäôovÈ*ßœ(4oÞH¼Ä Põ!»é?ÒˆC›Ìž ž ú}‡¦]äÎÎî6J±íð{Iʬkì7¢3no1Ç4µÿJ|·£‰ŒrÈÍãìÉž¯%ÒzÛÒZb/‡\—äÞÏp÷Ë·Ûa&|í6˜Na‡:ß5úàoU¤$™6¸ ‚òpwX«Ö7`˜&ao‡P"&%1ärl‚ö˜oòB!C5?)ÍâÆ¬’ê-…)DÖìØæ–ŒØI”Æ+DÊ}|BÙTš@ä¸bb™“Ç™–Ya¼â1ç¡ä¯WÍÌõ{"æãŠO"´j•Áʱ¤7PqÕ54™ÚHr»2`˜Í>O}#[o(DßTi(K)—5·(اõm.;Ê·`;ëñ±È®Ùí yÖÛëümÚ–=ˆíâePœq’‡÷Æ©1ŸoMY)™ ©€ˆš=%4Ç¥´1GÕT»ÞZdÇ‚ÿ ÕšYμ4úÕIJõîÚèE¬úT˜¼ôœš–ýÕ +‚Onª ÞeEŒ‰`í´¤hVðRã=fôOb_¥bŒRs–l ‡6?¯…ÿÉ`ҨŻ–#^’ÏÍruµ»e¢HVPò–™`Xdøe¹}ðOè¾Ìlö¯Ãu©ÓŠõolK é>„p¼›¥5º™Ió7oÄC¯¨½ yÀØàý÷!ïeV«nÍ‹Å=åÒ¢ª„%Ý”<rOö…vl“­Þl.ª`º®Q”eg}£mBèí¯+çé ë…’ÞpÁƸó(¢ ”&•J&ŒÌ±>ý…!_»4;¼vr<§•¤Nãx G‰wýÈL×Ú&¡V7Cùòj‡ää›w­¬Ýw‘aµ7Ãî 2¼ÔóIgpƒ“æMŒ2:µSÁHÂ*]C´7“’°,NK¬ñNº¨¥ÜOúUyçà Ï߇/9×^ÆtÆw¥¹µ¼jÓë›bz5 ‚õ0ø\³^Ò“5¿ä[hÚbǾ©­~£ ¯îÓàYÌëÛJœe Te†¨ÑÍý웃[f5}˜ˆ"N­TŸ”Ï,…w¼‡$"$Û}èHªBQ•—&©ñ;—Œb_dª‚áþ¥ÙTœ¦çÁ“x÷á%ë--fëmP9j˜¼—mšÕ{î•üg~‹‡dw„J…`{“÷ÆyR®,žs¦Þ…ëR8ò.Ül¼€¨­'æ“HîY• I÷\@ÅüõTu×Ä„j•œfn"‹”Uu16²šÛÖÕáÙº`¬q“E;®{ê8ð®{R´î=^{\÷±á¥—¡G3ß–’»êL¾=a˜7énpù EJSßišÙ¶—Ï“øvôŽ Jã~Ýνl_¼ë„>¿:Ö±Òƒ¾««›J}ÎTô:óãÒ‘ Û:¼×óTÚNiƒd}êÇÒÃҀȚÀ¯*€¥NX¼¶@Í#[ç¹´»!:á`y™4ð†í7 ,+¾à+’3;ñk© õ&¯Sša±Yƒ5Úo3J€‡T¾kû§ÐZõ÷y¦«Õfã+ VìæˆëD‹êƒÒ"¨â­šwï7·~¯d¦#“ rÙ1[ÐÁú„+J^ö_rˆ è™î勯ÿV^¿Ëôq&}ç’}'ÑÇ{ù3éá·yàßò3vAÊYþàÚ% ,i;ig'ìaX0P]‘>¸Âr!P¢Ë]âï5=Ô‘ùR;uÅ}éý‚ýBÇ •И]ñ_zß0àÏý7üó['lµendstream endobj 568 0 obj 5564 endobj 572 0 obj <> stream xœÝZmoÜ6þî_±è…xU‘Ô uH‚KÒ$È5Ms‰¯×¢ k¯í]tíM½~ Šþ÷ãP"gFy´É]AdyDRäÌ33ÏŒüë$ÏÔ$‡Ýσ“¯^Õ“ãÍN>yêþïüº£ü€I÷ãàdòpÏ 2ÊI²&oÔdïh§­&µžT¶È”žììü”Ø´L²Tgu]›D¹_”LmžgÚÔÉ«ÔèLåºH¾Ku“Õ•®’¥ScªLë&y’7µ*ËäY:U™µMS&ÏS[eyn“=70«­ÊMòEYk·ä4Ïl“×yEg½HuòÔMÐnåªN^§ÓÒM(Ü“—8·[Æ6y䯛Fu«4*¯» õ„d胴ɳ\é°¹þÐï@ªµ®*·!•5-š7{wêt#ê,J•UÖitoî´JËÝÿ2-ÛÁ…¥ƒ§…¶Nu“iQdÚæªô…{Uò.k¸,áÍy®Tr ¿ž»óçÔþ K [/“™»5nõÆ$gðè.ݤnY7Ç$Çp¹ˆVéTñlåÇ´B·LálÖ8áYâÈã(\¢pM7„_!èÁ騀ãN•Éʲ±í¹÷㑯áòs×¹Ž *èN¸ —wø–éÕçô8ÝÝ.>¾ŽÂ#®$½ü; ¯P8B|Ïï¦ÖÙFY Û¼ù=ŒZ¨±×ÔÎ enÆ^ƒg ë¬éΆ¶=akx_ˆkÿÀ4 ·…±nRXˆèêoOR°¹nÜï:8ÆiœC,ñ#]Þî||ÍtÕ[Þ~W"&ÿ9÷ðî©qVL¦ºÎ”jšv W€Eô†o³”]åºE)Üøi–=D¢ý9,Eжƒa‡…­ƒß¢Ç–ªñ,š™<çî1ÄÁ;®2· 0W¶ÞHn|. ™o»8DG![÷~@u€àzH}7Ä=²óøR6Kx«m`"Ŷ6EãÒG@'?0Ù Ç”ŸÂcA‡‡ÖŠªÇx×n7˜X0ÄDµµs{ÓÚ§sÉH nï¢*\óX.˜â#ÁlAÎ0س9c^I0›KXÀ57 "þ> 1ª,[T["*n€B;n4Pq(¬Þ qnoÚg…£8àB‚Âêÿ …áQÁGøY°xYåî+ž"VpwéoSنўÕbRYNZ¡7s*Æ:]ø&©hÜÓujò¬Ôî}À›k·{gÈ'n™²¨-à&×U·JíuSdªh*íÖs²F×]ÊÖ¦rZÞ¸çÎU”ÔªÔN[Þõu•UE0öO­9÷#ߊ†%ÉäzÑ—ðû—Álk}ƒcôÔ»ðû=L¾¥`´$Â7îXÊ:¹M¦ØÅ(t-¡ƒx!îö€;ç5y΃tØ.F†±Ì3ÌèD%b™ ¼´ m<ÕðRaÀ=š0Í;V/ÀØ3æ Ê6=—ÞB:ÝYUn€Ÿ’ZèâH:á"D§Úƒ` «cº<9ßp%Œ0Œq‡¼@)9YjÇçJ – Ç™4 ´UÉ6´¼õ™–’JVˆIÍÛ-@>D>"RöÓ":f+¤†x;“€8hèlKb¼”„œm0E†ãIËcŽ9Áz‰%ø¡x TÊéºàZ·(xº:6Hõ.¨lKÀ±%l F‡Œp¥#I(’¯í dJù)«ð!šõ:71јä/‘%â*WÈ1ï÷ò†‚ß5\JôÁ~âk¶ËµLän|Ç=Ä“ŠÂ· Êå"UB»M}œ\„„¡+<¢€Wp_²2O0ÞizPÍ(¥ ¥$¼`࣠C¾j‰fK~®ÜnÉ–pºAü;އÆ3¸| —qãOC5Ò)ÒPû‚½ô˜£ˆôÏݾ‹.‹.Mê ËÃñÿÇý\üØv9 ”ïåÑØöÁý“´²‘6 •‹p¶yK6-~6¼`» õÃy1!°Cýô"Þ{~oêŠ!‰“>tím°¦º…—vûœµŽñ!ß^ù ÄørsaD¾¨ÍÆð³¨‹—AG·o:“WîKhYI#¥†âË–å@ÅVsÉlcyüÍŒÍ×pùg 44ÓõÏ_Fzó»©÷[ßËCΉà/Þ’oàB²Ô«øø ¿ÆÏe$”ÞÇ÷¢P¡ðÇmý£-=E¹#‡ŠÑÛ’ið9„Þ¾þ•Å{«íÝ.x!a=aŽq@„ú¥4ý@RQàf•?ð¼Žï|ɘBšÐÉ@Å¿%`¡”DÍaß@ Ï3Š£>8›b”‚†Àx)bJÖHœV€3÷4"VÖ'Ò–7¸»OÊoùz_Ôé>ý2H ¤Ì$Ðêièδk’çãYXþ ùýŠü•î/ÒJø…øŠsh¼9ž}9ÔÃAQ·pì7(åI ܾÀ±_3íå«ï»,Ô~l÷ù_Ç!ÎÁj«‹OÞ¢:Ð…ä+£-ë®ØÛ†bþù=Ø_¦èÃO=b7ú÷vþáþýYÓpendstream endobj 573 0 obj 2706 endobj 577 0 obj <> stream xœÅ\Ys·~WùG°œí¦¸ãÁ 8•‡øŒS¾b±*rl?¬HI”C‘²(ÚRRùïéÆÙ=ƒ.e»b•É%ƒ£ñu÷× `:q4â¿üûôù½÷¾qGO¯ïGŸÂÿOïýtOÄ Gù×éó£N ’P2„1ˆ£“'÷ÒÛâÈÉ#ëõOžßûn#¶f3Âÿvk~8ù¼¥}KŽz^<9ƒÊnwjp.±ùëV !x6ÙÊÍ×Û´6NnNZS©Ò~ó ”*hv㡯Ê¥ ƒdUÖçM`Ã_B?mõà½Ñ–>øªK3ˆÑo>Ùâ‹ÎºÍgøÜ¥ÄæóíNb}¥å=ņpÐ_@eksñ¡ÂæÄæÁvgàƒ~óíVãh`”øÆÉ¤&…wñ݇[™Ä¥=—‚ Îí`®N„ÄvŠóG!6W0œ¤·›ËZøªîká³^ÍÇõÓÙv§ƒ‚7›_zJ…ç­ðY-„&Íà³ë×„ŽŒð‡¢£{Ü>¾NµòXÁÈ1¶õ„õU>^´º­”žPƒ±#ñó{'ünó²'¦6»Oz¹èM¹‰ée{<ôäýºSˆ#Û ŽvÒ ¢.âwPuó`GdOÊŸ8˜üGç³ù~nkõ¶» G?Œb³É¡R€”ÐÁÏÑ@æqJ×ëÐEl/Ý´ç/{Í?¦!¢50äàãÏÑvÁ;ÅA MÑpÅz£òç—æ/6Ÿ¶ 'íãg9¸(fpvöh‡¸1Á§u‰¢~Í$_ǯ6×uq®ðG,;Óテ{k× „C£²Xñ6ŸÔ矵ç_Ôºì§uL±ç›ZõygYÚgåoÔ1aÒ,ÏóTéúÆ6è^n;hê¯g›Ø¾=ÔÓ¯&Ùã6º6îë;S Ÿ–Â"„|”TøñM})–½‡?Z•¯ðÇ×hôgƒ%“-u+ð;ó¯kªLsd¿ê5¿góœÃ¬ÉÓ.„®&‹†C5Ô¦¼˜¥sÚmlÎ 9$0.2}+x¼XWç¡Ç|¸$n“Ô|¯zKzLFµÆ;ÿ/–ø8š_(Æp§ãWŽ™ºÍŸsK^L]—ôÀ>§²/Åž¶_ðÐ õ„[Ú9uézÕÓÞÊ7`½bzKl>QÌE3¬!ÈôÅ ÷_j”0`4¾ÂÍðÃu ,ZÁùKÝhô¢Þô–‚â&]Ë×Zºhë÷ˆ+l ëêº'8• ›Wl‰'æâ¬·j]‚Ô4û9SR3ÔwJ€}xpuÕÃ!÷×káý¢“N2ÐöŸ41>žÁ/#¹ˆñ|&°%æS¦ôVö÷mB nþÞûÆA`¦´•˜MÙI!† vzT5ˆÓ2N^V(6¢–I ÍfDÍÙ|€½H%,Q¥fD²ÒR³ÝçhŒF‚bó:áÇa–ÇÅ ˜ÒÁˆü¶]oÇAK'4¢FFkˆØÒÛÒ¡ !íŒ0F%=75çbr¬5,5ù˜šµ.ƒVÇÁ$`žZ)Z*3øÑ ]‡·¬@ƒwÊ2ÐwÚ;äyI½Ôô&…6Ž´j<ÓÖ=¹¯”ÖIÙ<ÁL$ÇƒÖ ´ZˆnŒEU18ðòätx(W‰Ù<k\¶{øÑdÅ E„XyRßȵíhé‹ÓÇX†(Æø‘j‰Áge¤Çü":k™A)ARåSmè:#|*•ޝ-HµŠhàÀ®K+’aœÖ :k2¤öò%­$›‘40bæñÂL‚ ƒEkKƒl€e] '©,I¬º…*çô¯­Š 2¤ä줺Pcœ2èŠîùâ´‹ƒmóÎuÊ,¥0ÒÖñAßg-=›¦Œ¦Nà§A_¶wžBY ¥³&¬„ÏÛó4¿Q´›Dî´ö ü,!i}\+ô(Æ€ë–Ñj­&vYÛ!C©e¤•ì<¦È²D9ÈoØuRE'å£3†ÞáÍJcDSŒSŠà™uØÒ¯„~{Š3XV`e±aÔX‰Ë á ŽZ"DÉkÜL(ªM¼CÆcÃÔ ƒ ™å9G{©CÆ_‹ÇZi®g00 3*Z®H€ÒFų¹ 1þ7 åÝqáÜtR»žJ½I*^úe‹û&Ò¹(R¢¢gMº÷ËPV #¢û>ö­yŠË«Ž´PC"_²ÖÙúQ Ç4d®˜ ¨‘µn…x\~ NZªWWT È'»ÏHnÖwÒ™,2®4 sÚˆØi¶9ö!ÅeÇÙpJëÜÔp^“®aðàä©úTI?m6Ý0‡ùµùôâœí=ŸzìÇc,Œ'¬- –­x¶dìvàÁ£¢n`>óLåMÁÖ½ÝY+ĈѡÜbh‚RM¼›|‰ ‰t>ÁôÄM•uØ}Y÷ wÐ8O%é8ž¥ÐKxÜæÌšCzœ9`”Öl â ­“‰ u°¿Û˜é¦YF~ƒ{ßÕ.2k¬ƒ³þ+}à„å~½@k‡u!Ë€o™048MÙ)õ Å»<^°ë­÷!}È`¥ æTäf­Ùâ!ÛªÍ úÕqœªiò.HßYh›œÅyG5f4!‰Ãz:‡Ýsœ—_ž0ð{N6bÉ”—žÞ̓><77=ÕAù{3Ãç«Á)k»ÜÈIÕ’'ìÕmÜA—cçFäWF1±Æ7 ÈÄ p=Š˜Ò†I.Y—r'‡(C9â>PœZ?mHÅdÀ§‰sãßû:v!JÛhâ™õ-Ü)Ë×;½‰ ÙŒéDöa®w•ù–€R,“AQ×ð‹ãi¯÷ñ‹ÁµO{c@,p†´<ë`êãº÷•{Ÿ)'·ãH;ÀÇh+–9Žœ#¼<^êh§F „nŽøOMû‘@_dêdA‹ ‘ðy_V»Õf°ïp?NmÂP\Yb–L‹"ÓÏËêCsl =4 O”Ä„ÁR-¾ˆâP¶éïóf$Йò'˜KæOQnÜgEˆëî1ˆˆ±Éº{°‘]M¸«ûGgô&¥c€@%PXÆ2(ôHÒ òà,Åi¸®lFðž( q±¥K1 ™Ù0‰óU`ÎÁûruó6Â.ç9æ‘Æå‚)Nè¹ó¢iBƒZƒnÅ!f ªÄP©Ï”&fgßlº 0Å&ˆ(|bΓrÃ2Ý0UÄtÌ¢í<{î;føFŒð?1بȽਔɰMNiZ8תت¶S'_C^‹Á§ò]3Z? ¨´ˆ&|É!Q-F)mTÏOgÍ*,7ÞË6å”H7Ûú(në{¼(Ï®©0ؘÛ=÷ÍmiRjÇâfeÑ„_fÙbÔ$¢@% yžf–ë! ²ŠW©;ê]šÕe~—ós¿[Hžn)€^v 7Q )*nùPR]iûæ±ð¡(®C"ЬJÐ4k3ú·†·`‡‡à-ã÷©0¨>È1 ÖA2¶oÕaI‘ºÏøÐÄ•$e‡†Ä^W³ÄߥþnçãY§ò*eK²ëœ%'Q1t±: ´žl?0˜è€ÙUr ™,¤g; ‹[]1òÐÕÔÕ–yÏÖÆó6oH’!+G2¡DØxÈ@3ªÝ ÁäAˆK°(·»$Pf¡ç:¼ØÓ´«s~JGóÃ÷ƒÒŒ–s o‘ÄLÓ$…—R&ã!ÎWTÑí”øÝZ-mHŽT'q!æèa8`\Š“D+9É•c^#?^¯H)Qtt¤¡Ö;j'ž+ “©NœËØg׃eèTÊÞïØõZ–t$ kv¢°ð ’0a±ñ^Š­“Áün/žçÂì)æyÜÙ6ãH¦!Kr+y®øâqÞ!QmOåÇ6âûYŠò—å)øS:£1„å9q>ÑæT}žá Ç™¨‰Šd•‰á;d¿m²4“È$b®³(ÃÁ3ûþ%wÍ2Æ5ñ`'ÔÄ^ñ€‚K ÁJhúÂY©è̤ ˆ>{{DØê;é!éìŠïPßžðÌK€*ÖËW³TüL^g£oÙÎ]ÉvªØ¶XY¶5Jƒæ-胗 ›Š'…Ë”"U>Š´ÀEsží-P,ƒ¥•sJba ¶YÅÕ×ì:ˆö´F iˆŠZÆÂ´1~wà`bBNÃæa>ná‰+ú¡¼‚xMìã´g3ÎÓ3)„ í›ÐgMdöŽQÀ`¤)vAò¹ŸdO× ’ª7Œ¤Ô°¤­uyÅÜsÕd½¦ÛMó ?÷XK) 铺´®Ð×Èç¼z…ÏÉ 9—ų3ÞŲ9¹–^¢ävgd¹“~šº¨^4Í¡Fôðò·¤WÒøö’êî$ƒÀ¨dŸÞÁÐá`×)ƒŠ:îä:“*類Ò-Цç©â wëܵwä¢}€‰¨˜Úšjr1¥_CaÅ2ë24:£ŒuŒÄIoÑˇR_É@W>©åMϳ¼b>ˆb5‰ÞÎÝõ¶ 8Y«P¼KY&®Te ,ô`~‹¥Ï;žcÉ IMCè•íæâò²Eg1#îÀ˜É¾.Ñ«ÖÏo–ˆ””da®H @»^¼Æ“e8#mÖ"ÞÉ6Õ²{]׊”bR„Þ¦Ñ}ÈI"¯„€?Ç\ã¾} n&sã°J·rRâ-½®­wwôRDy7ûtá~—%5s8˜Æùf)»”òFöãÕ³)šP{HlB,Û©hAs)ÃqÛq^âxˆ6'ÙxÍâ«Ûö®#¨¬û·™ßèÍbêOO†«hŠW$è!£º"£rbÓ8Ùt „l£A#@üã¯^NyíIõb.`%\N®‰¡YgFä:ÙããÌz…á8‰é 4úí¼áZ~c)wÎÓxn6d^æƒËzy§<¡Èeb'N0™+½ïåjã±kã¢ÛÎy1\0­Ô¯9ËB½X‘Í~¬œ9ÍÞüÀuÊ^šUOqè™ó|«(óP¶Ò|GY±BMHêIB¤»m8Ñ΋’õð A©X²9Eÿ$ýÉ÷'®%gsõ‘Çèį=ÞȽ䫺mRwMf„A[–J'Ý¿O,éô CÀ„鸹€áV5ÿñÎB|S.«ÍxÙÛr9Âæ¿ñ; L¼&6¹—ž.Úüy[îÊ·&ß/e³[;í{1Þï]åé^ð¿¦Ká¿k!¹¥D.¶jüšîüÎL \¬n_åAît¶ÂrÇ@ðÏ»4¿Ö&k½\ ;É aÛ`1¿lŒÛ¼ŸùÕÏòë’Ò?méôù¥í ¹NKîñ’ÛYäÙµnïÎNÔOŒ{ñkpÔì (n:«Äç´Ëœ³¼CÎv½hÛì,³£&Íâ/~f´w‚²lF;ÛñŸéXG>¤K£½v‹ÅØh¬Ë±o~¬ÊgæS…rê¨Wüb9É*ârpÓŸœIŸ:wvxd8QZêuÛ$Ü òk9”z¬ÛNÏ “ ½M^öcØB¯ñp<`¯"°Ã;µB½~[gž÷#Äü.¹ÛžÑ4‘!ñ¨„éúòQMÎP/…V¡‹BŽ»¾¸wL º&BkÝ{>ÎÁ•êíÞÆÂÊÆ~œ–™¨ÇŠ>¢È.s»ñ–à„Â¥ª‘Âi5§påê\c.~q?sSÓíúœA›œ1¢?‘[4r‚œþ)‘ôʲðíNnNJ|®ÚV¬À4×òAÐ,ÓÉ¥‚Þš’‘báðC­Y5¢wg–2R®¿ï—)n’×}â7!ß…'ÑïMÓÎѺØÍ7cÊå(²{Ö€;Éšç?Úi”Û’æ™ý¡·d¢—O‡epƒ±0³ÙšX€y„šGŸœ·iŸ §ŽEúž‡¸ó~ûý®;«ŠF3ï63M©qË=~Ç]7iœàkØàÿ[$©¸/û¥Ò/)9§Œ ý}Øìýʵ€XJ¾›TÀP}G¡&RPD/’åÝÜ:‰BõÜÊíã“{‡ÿ×(=Óendstream endobj 578 0 obj 4964 endobj 582 0 obj <> stream xœåÉ’Åõ®à#æF·ƒ.*÷L"8°Û± s#£1R ÍHâëý^®/³2«ºÅ€­p@OåþòíK>?›'v6ã?ñÿ—Oï½û…9»~qo>ûþ½¾÷üóÎâÿ.Ÿž}xƒ/“›;;ÿî^ÍÎ ?ÓVNŒŸ?½÷ÍÎîÕnÚóÉ#v þàþÃq9O\î>ÜËI¦ôî¯ðq²Ö9µû|Ïý¿Í§O÷!ÌÄÜý~Nœs­w_àW܇Úý¥óåþ &)õ¬wçØßXΪ¡Ÿîá#sÒâ$ódÝl ï{69g¥ÛýÚµVÆÄ_B‰8¿c³©öd]ZNÂÊÿÄNR*ÃwŸ„ŸùÈoÂ8Çè,Þw>’®ìÝ<ÍŒÛxˆ¶+9Ïçiçßžÿ .î€\TlÒîèü î¯b†Í^açCl=$".tú¶f­†óÿ°?à=éYî^ÁÏNÌi¿…LÀ6åîeà ܥR.ì!Žâ“‚]ÆQœí•®©º¾ÐåYi&ë?Œ‘’q¾ûnà¾Ý±§t¼?è ‚Q|w™?Þ$ž¤eÉžâ Z-w7åëÛxX0»‹½?¥œí„—l4ÇÍ ‹8`ãâ\ȸ"þzœV{‹Â µâ&œ ðíÁž›IÉYdÀsAh„è‚Sô!¨H‘œ åŸq 0»ï÷Âo‹‘½¼Ú#‚f&€[BŸŸ÷ÜÁNüÍ+ sÜ9¸£xD§$^”œ|4äãaY6§ÅàÇ/¸C8 qšô$P W³óPgN«w÷wùkžiÊ£¯3¿ÞaÒÂ݉ˆgøñ£ÂÖÁ…Ÿ½ æ‰ìàrìWzæ<ïÃ*FH 2 ;ƒ+ƒ%â\²âJ_/y§é«]7vf€ _Cç<ñý}¦'<œe¸,ÞÊ€ÎBAêø¹L½€º³³ š >Žf¤"Ž’Ò éT0 ¯ÔHX“œî«ÌŒó§tJà}ùÛ×Çuû7ž…ƒ¨û™†#ûDTÖÆaî|ˆóÉñD oÇ…`†ŸË…@>!¿ÂR\Y{ö à'BW!ëÄNîšOˆl˜M°Ì+è~!­YâŠVðL›ÆLðW\î Èôn‰SùþexÀïpTÞ€ ­\ˆ˜¥+ìGìd‘¸V¤jŽ þ‘Ãá ”“,z¢‰\UXÒ\ØxÁøÌ^j8vËXûjoMhD†óÙRâ&²aX®à}¹#¿÷}‘#Çÿ¹ðßía×xLÃüí ‡.Ç\Ýóu:íáÞ«Öh/Kåzr2ç“€ò³š´L(_É'ŠÈþ(íNo îFìVQŒ&(_a´_‚õ©ªH‚G¥g¤`ÿg &éÁXÜX°$ØDéX_ÆÆ@,5÷/˜–0Ÿ­>+¤ÒUL–gxx„ψL‰ -ŒàÆ í2¹èË%¶ßî[LH³ª‘Á-©“%!”gE«ˆ'¸š”$'LÚžÕ\1ëÆ+F 0 B—]b’ê£8ü6ìÅCDT Wßh8·zÊÕÊjõˆ„ýaÕDÜF¬#jè ç£(}“ÕÄ—Ê!‚gá+&´@xJˆþZ'’¬GK½å.2¾Ô’0p^«‹fæÉ)Àò\4’RÒâTAjÁÔ^¡­ç@Gc'hTÉ@Ø¢´ëßv"¤Anèuˆ£&.4h̬•ã~””-öä=Z6*Ñ3¡ÒüÓ¹*Í?­9œ?ƒ&ãžÍùe}°¼(â¼F%¥‰L×qj\^êŽ6$¤ÆE7È-íN Í” BŤ³=Q±€N@,Z #ÝJ«´(£r… {R«§€©`Z7({S"T2>ؤ" íKA‚«>¬DÖ8#Ÿ=Ã_ãŒLxÎHPñeÑÈ~„³œ«|EÁ‡¡ Z5 òì].YiE¸.ØÐCåŸÙ+•°‡­¼×éGì4/CrŸãé®áµçëmÜ&zDЪ j›f¹Ô›h×C<ºÎ$:%£±rŒö Ö *SfòÈ2@“E½êH_ä°àézP¾v§'öMiÿµtØ'ðáŸöÀíõlC·/—Ò… jT<_è*FJ™J#eF– ¤ÉÊv÷¨‰á¢òLõPê:ˆ›y¶IjãqlwgÞÿÎfE>VªŸ˜a²ÃɈ!ŽØVû#¼)Ê:͆cÅ1H‹ôÈ4Õ˜À#3_h¬Á3ë¨&Õ5q*±­n^À¦W„ö»Î]”+WJ'áS¡¼—‚4£V3¨0ÏD–¨ô4„¿]U<-LF.ª´~iÇU “Ë2¡àö}ÆpâBxŠàÚR¯òœ5ò÷¨Š dÒì²…;tåfËyˆ Ùíq˜ÚX"@êj{ÍÜQÀŠÏÎ "¸é TUôH&eÇŠ‹?ˆ:’”KÐU0;Ò–Ì3R÷¢;bÈ} é»qŽ ‹¼ï~L¹J*5öt„ ±¨K¢H»(Î?D—'l!ZãŽA!âÔÎx¯Y$]ý<£M3&t&Jµ¦ÎDW˜Å«å¹Av;í¹qǵA@}²zS$wðEç­^3ÀÖh'×ññqÍy’K9†{š#ñ+À>„çP‰$L if¯ .C³µe”c£d3Hÿ œ¢YTk=Jp³‰Ø=ÇQ6hz¾$ê) QO4ŽÒ¹õìÏŒ¸~+™äÏ4–IÄZG°ÕräAÇR'øq³Þ|T»™Qš á­7¹¦§pò·ÆÐD‡g>*ärëµ' ûÝt¸/ñÇžâaÍnÌÒN±¢q_<JÞfâd„Ôiijƨ0i³¤;ôW÷ lÅëYp¤C¸°ñP­üÅÿÄ(-þï=lUø†ÿá01XhÀ?wßÂ>fÇ0âeîòOâp/<¹6‹rà*·?,íßååc™éIù„¥€ê5ÞÚ—ö›ÞÇÒóeõ1ÍôSoù'½AÓGu&†Ïîÿéx˜zH¾—ÿS` .%þ›$ƒ~ù!ùzàËx&ÏØˆñÀ?†ؘVzÑkÿµ³üëÃã[ÏQÝÿ þøAõ™Ô~SÚ¯ÊA¸šôµ¾üâé¯{9Cþù?@ë(×|î*ñÊÇ|/[ þý©•œ™À,ý|qÚ ù;5缓øñœÓÝ!ä‡wì­œ²înIHv.èî. ðËCiÿ¸\õãÜþ´´Ø\wÔxðû.dvƒI, ¡0ߺÚZ‚óÎð4ÍmuàúGeÊE:¾ÇÐQ‘6Ú‚õ7³7âŽz)ڇʱ3 †LLOE;-$Ÿ"Æ ð,O’Jâ‡ÄU‰)âRÒ Å’êÙº´O…&qo¦ )ëÛó3ÆÎ4¨>¶6cwEÃ=ŸdIš~“œO,ñäLårexÉüÿj93¾› {Ìv ó'ft†úŒÆû°V”<ýœoÿÞ|tt·Þü×óÏ'·!nÞ`",õž ¸•ôÁìU·HÎ=™^ž4í´8ÏðqpãǃçÆO™¦WôkòôÝ™èû îLáø„ˆr„w“ý9„K½'õ‚ÿn®Æô+­ÅL?1nY„P²^ê"„Žï±õªa·A¾¬¶¾„Ð"•ÃõŽˆ“…’Œ³!<Ãz¼˜zbÊÑtŠ…Ó±õ/õóLb©Ú@öä,T–Ö,˜®‰éú¯_–™HdºÖ"“îØ™?–¤ØìTC7³ÙØôa Õ‘à’BB¥{IlEþ¬­î0h¤mÏóžøå 95³KmÚÙ1+È'fh<Óß´®NSé†BÇg>ñ““¯} TõI}œœÓVóŠ'$O…8°þ“%Ç › D¬V ß*»’^׉±`6Á .´¼à£«ÀŠQÀz’˜]çÓÅSÖbb!ŽŠjO˜Ø [cψðÛ)r¨(¾­a™ Ðdàèú‚r »d’è]È-íì ùPÈZîgM8¦ O¥Qˆ%‹3Ò§ÏÂôÚ¬†Ú0÷÷¸Sçwò.®lŒTL˜ =qCñÐ/…ȓnj^9AYo°…2ø³¨G$!´ åã]˜Íé{)q½üåÙ,V5!_¸¯y$ORLÜ29zij³>K¾nhSMšdJW-A±(!©–›x)¬¯!ŠVI\¡jAÌVá4ôÒ¿“9ÑÔÊ`giÚ\DšÝ¾A| R=W¬ø|“Sy'´4ŇT;é7~›ñÖã± ¡}$ćÐCäÌ ¸OÌ£GT•©z…j‹ ®Ò`:ÓOLyS©PXK“Úf ÷@S$ØØE$þö™ Í”ð=ÔN +˜dH€8UˆvtãwcY¼:¦ª4C<¶öX_ç¨tñ8TÝ¡²šXK©pêF§’ ;µ™ x³Ñ~‰˜åè(ÏIõÄ‚ä†tBèo•ÉskAº’‰P:½eÌ‹r¢Æ–™·, žºVZÅuÈP½qâ hq+˜›‡»­Y¦†4räÈzBuëŠÜ² Dê×Lö§Ów]HèdîæÒô{ên_¯ && ƒ%ˆÎ :Õ^qRÿ>–¨¤"¼›{ÛÔwtt¯é ÎœÍ¿‘ U¤¹!œee«TT~¤nß @ «kRÇÂz±PÈ ÛfЬe‰ßEÂÜÇk¹A5Ü}]£ÎèZ½ wˆW½—{çðÕI© 뫇¨HîmE—8ÒAK°Ðx„·¯ŠÚâ\&‘Ô(¨ªuRµG IÚµ¦Q¯‚ú6'Ú'“µæ^Þ”6ƒ¤PbÅV¹¯=]ÐôØZá,Éh5 ƒ«òŒÇËo8ÝnÆÍ¡Ú ¸¡ÄÄŠÑqW|¤´æ^eAbÙmMY Éä~VFUe8ËäQâãòÙˆœ:~“[Pßcæº;Iï[–Q I©&‘ Z[)3‰þ|$³‚Æb†á 2,¸w6Ä-Ì£¼²ã8m©ñ?^… Ú©/ü÷• ôµfc],!©µP§]öŒî.S O ÃåÍ0îy{‰bàÆ€Qá»[o ÜA¥#ÜŽ¬mŸœ\Tž§$BºìL·tƒxЍÞÄ2ï(Wxº C…êå醅6Rúµ¬ά“Tgªâ²\8sëBsôlàŒTëèïiÙTQšG]ФXè´¡fÀ³F¥QõJÅ^A*ÞÚy;ë¸HŸÏ@æ9Òg6¸·—qQËÍe¶,¢®„VdWúj¶z <„«¿Å![»?ÑËÖô¯ûoñÅ4ÿƒÒ®AÈŽ+“óÞNBó¥éXÉȵ‘4ÂW•¬Ö,”{Öy÷d-lŒÓ`‘eÇF¡áat—Zt… $êÇ5£œ­ÔÞp,µ¥pLÔ«Þøã‚•”|®U+-cÁ€ úªÓ÷q僰 ·®îúå„£˜_.£¬ÞàÄkÅUˆ™¯ñ.eVòÈxÕâdË8.÷ß"ú1d“ ¿pœV .‘vFLiÓó4sprwv¯ÕˆÕ/pÍ=9¸_$X¼R ÄI?ô&KÝ8²·p,\*[s0`ŽQCƒ "'-³Ôè`µÎ5>äP±ø.Þ“gúæ%Æx.ÞŠ«†CléÛ,€®ŒMƶÏÌÁÊ õhc„Ã×€Ô¸ø[fj+ªXäå±ãBŠ-¤wF9†Ä)E?G’ o¢ËXU›½]²{ŸH#ÖBMñ] €YóžÅ\’FD]~‘rÅœˆÏyt©í8ž[¾rW¶'XC4I`²’ï‹(·¹¡“õØz›ö&h÷ráz^æcÔ^,rFÂûV³;¹;nEìûª\x_ÊLÖT¹Ã[.µ¢c|r~ï_ðÏM‘¯endstream endobj 583 0 obj 5202 endobj 587 0 obj <> stream xœ½ZYoÇ~'ü#øæÙ@;š>¦¬D’À‰y Hõ@ñ²$e^õëSÕWUÏôr))1’Ã>ªëøê«êYþ¾;ôbwÀ¯ôûàlçñ »{rµ3ìþß';¿ïˆ°`7ý:8ÛýË  #½¼Ø]ïÄÝb×Ê]ãt“«³×XŒÝßn1¾Yýv)ÁwÉA÷ÞÀÆÕ!,þëb©zk½Ý Ñ{ï´ïž,d÷¯ÅRôZVv+Zó,Ž*íº0ª@,žÓõ0.¥ïeµäe‘8‚ÿ ç<]èÞ¹Q>ñ–˱ƒëž/p£5¶ûÎ;¯”è~Z,%®WZöpR„Jÿ3Z&ŠÝ/‹åV¸îÕBöÃ0‚–¸cµ¯IálØûr!£»j'/“¿–`«ÞG·=_xÑ[§mwÖ_ÂaÎ÷JúîÌC¥ g '(dîÞG-Ì`º5h&©î¨,þ,(£Š<ëz¥ÆÍòÒ£³&ÌœGñÚ$þ. ©74}…nGkd:_‚a©qàKßÒÒwYÛs .vΪ¨éIÔVƒ®ÚËnŸtôÎñmà¯ÀÛãTÝ#<ÚÃ2—ŒE}öãe=""ü¹n(s—x¯²+à6’‰¹v 0 C­°8'Ùu…BÇ Ð!W3ËaçGáƒÈ>°Â$§ù±„\Z‘¤ƒgÓÌFø“&ÎÒö£Ûv”‹‚³†Á²¹£¬ hÀp[o`6 ×}C °.‡0·ïS@pÍaQ´Œ^Z ÕfÑY…UƒU Œ1ƒFM4ø]Eûò˜465ÛÀ$˜=C0 žVàÑ­ðÝÛnÏ)éÎ7OãØ 2¶÷Îðø£‹?!ªú†Õ&T•µþ`–*kgæTEŒ ª¬à;ñ…øf’î&¢‡×Ljù£DXú6ü:?¼ ¹"½ë¾s¶pý4PÇ÷ÈñRJc¸?&d‡Ža61ÂPÂ’û‚S‚yî<ú¦¬ü¶žR:ØèMÉ‘ô ™Whè¼[²þ¢Nœ%(%qp!o²ÇBæŒÞqš1Ö2òŸfñ8H¼G% ³¢G踺| ÁõÖ²<á'”x¢`v±pB«îv¡B”øÌ`!z…‚Úá1¬kJå|^E‹‹‘o f¢Ae¬•ˆMž}„ºŒ`¡®KA30*7<³Gœ F5)/¡ÇØ``Uó—Þ·+a‘¹¦‡4ÎöF‹œ4D “xŒ€4å9wbA=C%]oF]Þ"ẼSÂavµ®R %„NHާcAwI,ˆÞ’euî†Ò©®*Xc¡KF9%‹Q@y`Ö&¥ãi1w’ãêªCŦœ½yMJÜVRc8íÞZÑ"âO%1< óò¡<‹É‘yV8à%Ãk.ÏJÃðƒ¡,Àº_„°TÂ̬poÓ´ZÓê*bA#Pú ôÊý†Šéº—› Ë%ØŒ½±Å¸¡)£4% ZMòjÞ#ãã~ýFòæ‰ukû”„6ŪÑmQŸ„Ç@=Añ*‘â/-¢B6´à”$¼Ó›á¿0¿1Í…)?‚§6•–”VX«0!µ ´;/B´Ë# –‘y¡k‚¡­uZªÑ¿Ú í@RL·;»èô(fªÈçp#µóüUÚ„žêÝ6ß5K…mÈ$÷Lº¾êþÀÆóF|•—\åÉeˆ Iç“þl1r¬Ñç±û­+KK7öd=NIbz—s¤Ìÿ¶À‹6ÔMãy.Áq\ ±Ð,ÃOêÞ†Õ%i\•Ù'ókDˆÐN•‡ »l;†Û©Q 'ª(/wV”5»³¦“ƒüúš4¦A/Õåõ;¤ÌÀýj xyÈ%{Ú®Ú1à^ÅwXr·ÝgðÐûî3Á|€Áæ•èÓZ ”&þ´³úÓëò¼Ê“qqÿ˧%žÜí 7÷Ø9_hW½I’½Ç7"K%úäã× '¸as.«¡7 GÇCC~‡Wq ty#Ø‚Ù8YsWÖ¼Y,‚» ´bKX.‡Ãqn‰zN /H¨ÂY”AC+—eð- ¾+ƒ×¨w¼pÓà9­¼.ƒG4xÒ¼Lp3ØIùñ*>bgM£•X&,¯Ý§Ñ³ò˜o˜“qQ4ƒöl„¸ wÖ3’µ*ƒ/“ „¯f.8LaƒÐn‘ôŠbqP™kz¼iYÅOeÞÂÛ4ÉXØof ˜“qíyË!‰2UÄ<:l…ð¸ îWš¦Áu‹ìÛÖ¦ud•Á+BÝqËQ—är•ÓJTL%ÿ ÜWJ—ÝwÙ2šØà¤¡©ÝŠ®·œMæB뀧ÁO ÷Æ ³(ZÈAmb¯W‡5y9e®xÒW ™¯ÌJt÷þ@"BJ3FüÚðbçq vÄï«PÍí&,^¶½É‰">Ÿ¥ÑšÅr¼¬k{;mÆÿÿL9ç³Ö™WÄDZž­ùƒýˆîøidYÚe‚™->~"‘ÜïH® µ¦r脉«²›KÖÛ–S()O[%ëã¦Íƒ=1ÑŠKâLßYlÄç×ÑiVù¶ÊIqÄmu͘çz]·Ïé`J¸©›™rÛl–ÃC‚Åã.'’®ãÑ8ž!ŸR ?xÌvþL£¿Ðã¯ôø‚Ö>‹ÑùOÓ5w´îC3<—•Uimvã—Tð¾æVmÊgˆ›«Íu<ËÕ$J ÕÁ‰þHOOðÇ‹òç^Y\¯‹c?W~Nƒ{484 `}358Ï„æê’c¼n¡é¤ BËÁýí¶åïÜ ý™½G¸”Èõ n®+›˜q„[ÏÀ^MÞ×lÖi ÷œ[ï&EeÔ³ ì¶|¢0³l¡Á'UÞHr‰ÞV²¶ˆ¯¡™TÿOó‘“õ£Ùmªn¬$¤Šº äÙЛ–#ê®&Iºjù‰seæôU´aÛ&îØFø¢7”§ÊÒ”Šq ¡8ü1Ô?ú;¸2ÈŠ7y³é×=>Í,œ rv[wšE1aùG0nß2(ºÍ C}AŒô ?ï:8©ØŽßóç©J«Þ8ú8µ‰óû0ÚŠTª–dJ÷ÿF& JuáGš{BNÿÂ~ôA÷Yè&·Þg_R ÉÜþqæ«­„±ïD ¹Ú3 l¿˜æ•u3ûÀ>é²w(5Ð'fº­f4àk¥¬çöôç’Ræ|õû‹W_ï¯jÀ¾ŸÍ$ž—1D|äÕpٿ̤9}5–¼Áχð7Jßôk‹…Ž*·Ü‹‰f’ž×Õ¦9̯+p¦ÿ/"š `Þ›ëðrlÒe(WÀã&›±[M ]öö²4@[òìy‹Ï×-£É'—bæÞûÈó[Ƙüýs~{#ð™¬)NmÈûVÜZ~9n ªö[ncú\´PEz_¢ŠÏV;ÿ†¯ÿ[…zendstream endobj 588 0 obj 2663 endobj 592 0 obj <> stream xœµ\Ý“·Ïó•ÿˆ­ÊƒwvÐ÷‡Sy0˜Ä$¶‰í³)ÇÎp(˜³ãüõénI£ÖŒt»ç¢8–Ù©»Õ¿þž{½“Üü“ÿ}ôâäæ×~óäç±ùü}ròúDÒ ›üÏ£›[§pSØ(19§Üæô?'éa¹ñjc½Þœ¾8ùa{{·“uÆ·}ºÛ«I)©õöÁNLÑ 'âöU¾ÕöíNNQE·wpM[+·ov{íݶW Ú{åþ}ú÷´·™|ð÷¶v2:†Íéç'§ý°=ÝE1‰q%àJëhõöÅn/'£0°©˜L¶zŽûË dª` Œb‘¢t°Â^;?¡·…Ç´UNêí3zÌGŸÀOl¯Ÿi/£CHÄJ¢›¢ˆ‰Ú8I'T¡öþñÞ0bñÇpÑ©Ôöåno”žŒC 0-„Ç‹x§‰–Ýù+~t+ UÚÎÚí]$%„wž+ð­V¾É‹j¹ý .õä”hdw²6§ùðd4œ¦ ÛGó–p>fÒÚÀñ%:”6@§jØÕkÍ®Ÿá O IEc”uƒúÈÓz#ò,õ$¤É»– fZŸãÍtˆ¯pŽ-ç­~G‡c­w çÎéÉW'¯7ZOŽø ­ŒœDØÂäBâÖÝ“›w¿Ø¼}sñøäæý<¹ùþ¸õÏÛðÏÝO78¹swóÕ*­¬hå'íp›É$ÄT&¯"Ú1#Ö)dàwgt:ÎH_­ 7ò¡I×{U꬀«:rÿñ朖¾Þdà¼íö?¸¦­Ñ)iy+bÞ]Ȳ„wh hqåe¦2Z.äôªÒd€™'/»ûqÒPë,_øÁØ‹ÁÛíohV@;}$˵WÁ£¨öøŒE›uÒzxÑq™¹r®hjðf{Q¥ðªûqò³VÚˆÒ<˾E³bÐl¾ ²žÏ ÓX!PUtÈ’qJ¶çUnd47áÃd½ª0a±µ(Â~Ö9šÖ´Ì܃´• X¨ ¾E'sÞÚ‹üá|¼÷ Ó¸'H¸ócÇz ß[czšxÊ„zŠ: ¢†•Ö`i‡à³àV6TM¾F²åX9óãU£ÏÓÑǨ»zç³²¨‚'?˜¯-Ñ‘/ŸU$M»½÷<¸+.Gù~Zo¨ç™´Å) (¹G”OÖ6ï™6eÑ‚›ëé¥u¸RQš¸'ST qa°ê*.p¥‚@ŸÌÖS Ò—Ñ (ƒ_‘ô@ÐY['Tvf"T´Á]‹I*†Í[å?²p&)æ]ûm’„ÔƒE pÞ ãiÕÒÇ<žÃhW«pL©­'2öõ¸æ Œá%hüȵ ä‘~­K2’ª‰x„’÷E_ÓŽn 2¸P´IwGæTCŒ‚Îz¤@Åp—¢sÞ1:C+ÇGñì Ú.DõÜtÁ+!ÀQ‚ žTIÖÀó/;r I‹IŽóøßªPDñlí«ÊVåD惠p~ZÕ˜Ñ^my'PK7ÉíOŒ¶¼-Spà_Eø æžt?̽üŒL¥°¯jÉË™¤ MëKªJ&¶Q¯,è÷Ój>Û©l¶¨Ð·ˆL]t¬øŒÆnt[ç°°V6.,þÊ1+‚ЉË6ÓƒŸÎÀ As+ö n ØÒ‡cp@¯á¼Ö™óx 7ÈUå:ã¢/ ÞßûÇÈèñÝ;)!Êßâ¡«F ¸™XtzE†§µD³]ù,•":f튭B)WÕkpA’Óû¿òôãN,uÞ­)'C­Œ Ô\‡7Je˜$µ8ù º n£Šç­áW59¿¡KIx£*ŒËóä1”^œFŽŠ²·RQR]â€â7õ€nWÉÜE7¡ÖßÅ£±Ä+„--*sÔ ÌêXDVÖsM[å:Ì ¤ð8ɧIa˜™´¢ûy×ÉÕ^vcœ·³þ7F'KèÉŽÓõgÌM5çò㎣"–¢ ^VÁ,®ÀNpåýñ™°|¨ÀbUÍb5]df¿Q¸\Ú³¨·…=#ó¬ßÇ{èm?¥™= {L¹ÀSЩÀ)åðInmº dJÄ¡0ù³%#5Ñ/Ãç)ï2Z÷@á$…/¡:ÐÃrĵŸt¶84Z‰.húni^¥'míGÎ&Sfšì ˜RÒkV¸j)C>¹ 6!IGÈ ƒB•’ä#Š 7nrzv4‡‹‘ ÚPµÐ¼ÌáÐLW÷€“£Ÿe5:‰q 22Naan_HÜë8y%t¢4Â#Âaàa¬ªJ·V” ÔÍ@è#&/A¥ð½s¨#»eЃƒýĪ8PW~NŸPÁÒ2<ƒô†˜€S‚öÖõ^ì©: €ŠÿÚHgò:‚’–²KÚÙÈtB`-€ýÏ©². ¾ËDˆ” Â::FJ¦´×°¨»‚{‡ˆ"$®Áò¾I Èo<'¤³g¯p¯Eí0üþX¿$\Íiбh‘>öR“+£SKwØ…ØWÝf²}4—U`^¹Š‡æÅ(²HC°gÚšµ¬5s‡ë3K‰9;3»<³ø1•ÖŽpkx+`ÞÇ­á€Ãwtk·&Ä®îä¡=¸9Ü>™ÄòØt{|?îã{øãküñ)¬-…nûø¨S™lñÌw(4þû9þø6ßbb Ky³>}{¾ýžCŒà²¶_Ì¿¨ïÌ¿¬OËŤÁôMfÁa^ •”ž5½ê÷¯j¤Œñ%¸#)\ßIg½¡{༘}èÖÛ1>Òžû¤£L‰RÉ”¬+I9H7Ý|HafÛ)†¶øÄDÌ›4žE¦õû©`Óù?7j6Ì‘SÏ·zÍÔÿ¢"Ï-àÆ6Ô>ã4 _0žªL$Ô‹IYë(Ë JÊØ°ì±. àú(;[CNd°_b„æRU¥^ ¹ò^6¹ Ø-cC[õ ‹ZnGÕ™"ÛšöŠ&Õh@f•Ôóú!ÞSk09Nrk“Gðø< È;ÝJ(çdëÀý¦ZŽB ô¢S¦ýhé½%Kÿ`·¬F§*`\.˜ÓÀž²Î¶UŽjŠ_U6™ܳ\¶4®·e®ƒuKöW*W.m2}_·šˆŒÌyQûÌ¢ßW]4{úQ.¨€pz…ø÷í2sOmáHC;.|”Â!º¼Ó‘•—ˆHÐêïAǾÛI‰í…3QàLùg¦|Tc5Î<¶¹ÜíßÝË££Ñ f|åOpØŒ–/w‰ O6•ÞªZ³žÕŠ_Iˆ¼ê)UNìÎ[«T¡ñŒ‡U/¦+L ªÉ‚^×4räj®n„)ܺÔS¢e[ ¹‚*µ@™{±›T.ÈKjŒ5¢9];Ïù˜ˆµ©·,Ò¯º:PlmŒÍB)¡¢‚]ÔÛ1Rç*…lL|CÛ Mèñ+­¯ZçBrrÏ:~¥ÿI8ÔP2ë¾+JÊ~§<Ð=°2íö ÀcÑPÆÞ¸UÝ$áÑÝÆêYžYu‚"kÑ‹ôÖ]¨//;àhým|ŠÀ*A%wýÉܵLÞÜÏe¾àz²)ã’µ=”M•ƒ®cXœJs…0"[;B²îNhØ”6žÍ2öÒ¬!Y³E¸ÃºÖ­†¦Y/µýpë?Äýºèb>Œáû±³ÅÜfÐÐj‘çÆ£;… çæÑì–6­HŸ…äm_’3‹í jÃÔ§SÉ£JT?ø¹jǨ$ëýŸCIbrQ4†o'°ë½ø'ÛòQ†‘Ù[4¤¥¡Ðh”aÌΧ™à+™tÝ…ÎbcedÞ„ÙÎáØQ‡T“vsNÐô¡Èßµó åx››Bþ°oª9¨ßoÀ ôxÀ Ô7{yKCfêÃÙÐê`5ð"¢½Œ“–1(‚—îå8Ž»jä;÷ê=_ÓÜoýÓ´ŠT£¡@L„ÙV#0j¤,ƒòpÊÚ"³3é˜Å6ާ^Ãb7òH¨ÓC×18«V.·4Œ:Ý®¦L½r+l¬Œ!D;®†TÍ-¼’§‚Ãïq‚šÛ@)úÈÁ”£xLs0ØÃÍZcé_xOA*Ýîd™ËþÕC®ÐA"]pK];Âÿn´ˆH"i©Å j}o×!VñBÓvO¹× 2ÞËlyw‚çåÜeìØnÚÙuºîÃkí+p@®5©‹ŒE¤aØßC¹±oe½;Ë<÷>H‘WÇÔ·Š^``/ÒØËÁpˆG9´¢‚cõ@˜äº0¤E *7 µ@sÖqœhÂy6ÿÖi,ŒuæAšèˆwikK)"%”HŸ“t£Œ¥Pbuó¢«y¬fÚ ‰¥ ¬:c½ñOm!8n§;W5±ÎTÕÄ̵ÄX´쿬áãZ·¹ˆoí2gµHyé1iáy3š£B¹ÄÛ·êâ/ êÐø¹4ìâ~„~n4±N%Wœ< Ý-/ñ«õ潎i0Ú‚)Wk+m][ÏÒ'™àh¯ ª=»w¬Æ^ïOg[ˆæ”éõ¢Ùï²F7éõ=˜«4¼aõ1üòÀÏ{A&…n—#&ÇëªZáý=&hšGŸD<&GlkÁLŽeìHñd„0ñ2mÂbCÒMkßá¤ÓL›ö6a²LXÔ¼rþ\ßC¾q˾wr^CºÉ6Óê–&óž×"U«¯€"6¼ÖÀg–çht’Í\6Þ…Ed?10ÜØ-†.‡oàÌãôÃ;gª—ï÷Ô¶©öÁsì[kwï‘dà/fr™R3‹ãœ¶­ $HéÉÕ:ñáR½¥ý 9aWF o<¶™O¼7¹»ŠzÄÄižc"`µèVó™ãû Å€cŽ×1“ñ“¤×†w .+ ]”{ŽT­QÝŽ[®8õŠýÕ9-*ùý·àh Ì­¢E¢ó°"° ÷x-@äö’*Тˆuhåµ¥Á6ר_;CVzòx\˜)œf‚,–‚ÛÃÍ7µj¾–ï÷«0pá²=|Ÿ’¤&ì¾ë@ïazµÎ³ÊGvƒmï­eš(;xFÄ X„Ëßé…fRû! é¸åªy;Öø1,©°z|ZM™¨Áñ–¦Š¹ò¸ZOZ-<|¹‘9ïîØÀ*‚Ì9cµ6Ƕ¤Ò¤ˆM êûR7;¬+ª3Í5hkC†E1†8oy7¾mt¢äýzaYd…ÍÄ%õÚ-C›pVvfi‘Ž:Q‹÷ðÑ6˜lŸi c¯Û´ŒóÚy~MÒï(°ž{nÃil#`Ø J­™ y í={Å n¹âÝ tó6{m1¹0W[y/!W(â¬Ê¦¶scIæð­>¯ Í10²+¹V“•™/œtèüú`‰„#¾täÉãç¢rmu‡Šž´ËvêIÙƒ'I 4‹"/.ú጗öˆ{ÝV¼þðRðü9k¼lN™éx.ðSAám<ß8yç‚ĺ\2¬3b59O]ŒÊÚ1ƒº®x ¢¬gÉlÔË”pΩôÖÌUf¥UÛ:d/³ð‘\’Æ%Ç” ohÂ^lÁJ/f¹ÎK Ùþûó&‚äÊzPßS yž| ZqGT£…cy×%üEúüo€¿þºúÿ¬évø¢9 ÚþTãžcV÷Éêf—ûo¶vm}ëŽJ€ë,{gw:r;kì¤Ó8Ny=nz¾hÄ'¥ì%xYk8ÁAÃÕ5»›¶ñ¨ipÓ‚ŒÖ=Ú#5Ø Æ¬pm†Uf¬Ùp÷a¦·bê|8d X¼`¢ª~‚Í •‡™“-:ÚöÝûUœÔþJ€ö÷Ûì³”ZmGmþ(ÿuY‹yv€s¾X ÁßO3;TìÅ"ú…3_ücó³òendstream endobj 593 0 obj 4590 endobj 597 0 obj <> stream xœ½\Ys·~gô#XvU¼“ÒŽ÷À)?øøRdºb•Š”H•-QÖeëß§»q50˜]R¤W¨Ýœ>¾>0¿N£8œð¿øïÉÓƒ;÷ÝáÙ˃éð øÿÙÁï‚ÆNž~r„„_F?yqxôø ô‡NÚYððèéÁÏ1úÿ4˜ÿý z)Á{I/F ýŽN¡í§ÃVÎy/6_bô~Ö~óñ 7÷†­µ6NnŽJ›»å×ûð«‚Q7¦‡­só(…Š­g)4oýí Fká1÷›a+a.?5}”‚Æo>pZgÝæ+ì4{x:…Í$7? [ÃI'ÂVkmÃ^·°N'¼[Ž“‰ImÎCoíÍæŒ«çÑÀ¼'ƒr0º1üù1ìòŰգRvÒôõdÐðPH¹y+g+ “~ƒÆÒΣ‚_ârq–·dƒ=$nTmž•ùÎp=DmÞ FÐy¦YK_óŧY_â¬&|°ð\*Í>BK3ÃË[^À ¯pjì´y¤‚&FÚL8·2ëx’Ì Ä±ØÖ—S+_m~3Š÷éS†—e<í÷÷a;R*ç-ÐÙAβpzØRߩҶجÜÚKvܸ~> þ6åÓtÂæ#p:‘sÚ0j\¼7ºt[¶ròÔÎÛè´\?ž—rŸ·ØPrr|µ¸‚L”U2À5óÎ`h0XV³cZö±5F9R–€ilùV+ÜBcË[hªa<6sþ­'aL ’ÅÀó½gúÍÁÑ?~NÐ÷^`Cìgô¼°ÅØQñlqRœ¢£8q¤¨8éˆ%Ø@RˆWEÖ$λB¸ V©ÆFiÕ?ûÈ*袀·ðmßÂÑ_”6§€VpòĽLa¯1¥ô’°1;nœíO¦)K€®–u u£]HJ˜çÑΊcöŽÿpVéÜórF]qݯÀMq}Ä´Dt¡’<8Âa'ïk½Eq\Nƒ…g*Tè(¢ëÂ2¬P»¯Û@º›Æ"k-¬QœWÖÑ,Sd§Á °ÚòE”áóžÒeM#ÍÎöTFmqéaÅnaÀf`fÌ8 ½ hÅš=$@µ°€Çe€Ðþ§6ßã\Êïд‡Â=ÌéÀ•1õwC€A@G™di ¼i4á$ºpá 3Û†Ï0v†‰¤ð{`,Áœ§‹™0¦ ¦3·-Óívc‘Æ€é˜ï jPÀÀȨ-z žé{«’ŠÙ”@:¢gŒ?at\„&c³ƒ÷·! ²éZïb¹c^Ÿu¡Lk5ëš;õ¹Ø›ºÝF’(¬—ðÀZ0Òp`‰ÍÞ¢ÂÆ ½šÈâvül¢ÎÖžC°'Úœx„˜Gìí¥w}*§]âÁËšÿØ-u¤EM¨­å—çɳç¹eiÜ(j [+°u±?]Ÿ ë‰&‡¨[ÛœÚ8´‹EtU|È–Æ¡©YÎDwèòi Â~€´‚Q¿$ÏFëa |òã"¿(¬਎\¥ âqòÈG4‘•jmdZ$cò¤´$þ©¶IhyÅ鬂¨C4‡ç;×p¾ÏÀ©ã‡ ?ß¹¯ç* /À\vžD8»o`r¢)Ð þ|¾Æ?Yß<€©@NÑ,cTˆË -‰ð¼`#pÓ$ˆY¨¹?Òw’I ÍÝËí/pSÞ µÂg8ˆ'Ëü2ÿøª´|‘|²«;¨á7ùÇãÒ²Ìþºü”cã¡Å¤LKÞv E ¼±ðÉ€:b5 Í¢ŒÍò¡ØÀ]W¨‘ôH…:?„eæÝ“°¨Ø³ö´¡\#ázÝ8zZ †,kb ÐÇFŠÄ·#í”[ñ¦Š“B ¬Î‡€¯³wFQB¢¯ø²²L¬b†Cަ3Å›û4˜yvEö u€aU‡tâë#ê(Å"Àܪ¾ö»V¨;)K¤ÙÒ| NÅ 9§¦§c±n‘ï1ŒÃ=¯-±Òn f¨:!È…r^(þu-øu‘c&³@fÿƒ éf¥¹¬ßÇMÍÜe½ù,Œ‚Ö¦RA@8ªðwNÔäˆÄ­VØ&^’Ì¢ôûc»R€ä¿W»±í¹ +èh®h&n§"£Ók ð%ô`¸Ž…M™æ¯È9ƒ+ãA5#ÅQ[ /Úâú4I•|6¹ÕU¦Qÿ`ä*!wÐÁs@xIîÆ„(S²{£€r}õ×[G¤‹±*ç¿zA=F»eYRzòi餻ǚà lÈI…¥–Ö¶Ò‡¨wSfÆÈ>b¨Sr&Êi1MÜ^4#öêQ°™Œ–`å>B;ë7-E›Á‹/›ž¹_!ï5U™¼R½Y&(ã`&;aQ•ÓN&&s‚õ)@î¶èoFF劉—E"õs Ìžs]çlû’{™7è[;Ṳ́8™o ÓZÁuo§  ¸+(â*G®VȬŠ(ç(U’\é=„³šÄQüàdTµ´¹ZÕ²rº]õ:Uâ`ð’©1ªëßt™š¥=.†:ÎÀ‹ƒ‰ÉþPiwÃâÇÅYäÜȤˆ]—óà•e­¯ UßþÔ‹A0¸Rb«É>4Czö€&}_e_µ¬h¯> ”Oº¸°ù‡µ»å“pK„Jµ­rò²Z æ¢ÿå^¶ž©¾ZYM•KÝ’š³&úÏÁšÕ±ô >†¨-;¯^ؤ©1`} §É’÷Õ<–0…¿ŠzꄱzØ3&FJñÝy’踮uÓcÃ+¨IÌK0¾Šúœ1n¤YVeÀºp`Ni8€–©«&UeCÙ Ó‘L—Uú‰E§ 'd‰wÇéðlQG8P…Êvlàì°·µãs®ƒ09ž£ºF¼Ô†’ò[)£¢±S…9OHSTbG2ŒVª»ªóÊ*dçJãTr)Å(»¤8úûÿrÃJV…t[]P‚à‚M9ÆÐ­«¨ëŠsÃÖ£ì¡ ³e¬]S%¾=w‘ÐËÐÈÚ{ÊRUaT‰f¦4Ä"Ü-c¨@͇²hG*MÈ!Ò£Æ fšeãrÛqv^•`÷;ªhĵ,ï_ Œ…Í¢ræ.×"lÚT Õpz¥*h%YÛÄ”c5Çÿ¡B"G/«mRêdµ0™Õ¾Q”Uù¤ë+ô‘1AJHÒàs,6m¼ri/‚CÚã¶[Ó6ΛØyù$“ïŠ?Mœˆ¥Ý%Át¯T‚U“˜,¾­ÚCƒ%i2ËX\Œ$/ã(D ãè?Y¬®§ôkÝ›Âà ¤c£MNqY^Ϫ²kÍÝT mÀÌð¾Ƚ¢ÅÙ1îÑ U2ÍíñN› á€bCb\& N^ø©•¨Æ~(¶ä* SìPg¿²“J`ÖîH/Ì®d^{X´9ãÈÇH&ËÙì"ÍSßÕÆã¶©²RrÒÓvK¾«*µßÅ{ 'EF õöĨ+‹֑¬{æh]ÑÇÞůYM½YT1§¢È:Ã@hÙ,}s8µ¿ä¸ŠRÑk3ÝËÝxfw_£änv©  ¢×g×^u+ݽ¨¹•Ýpî|Ý5lUJ«Îd¥ËÁ1éúuÉðåÞXd¢£ê›‡.Îú3î¸p5ÓÞˆ`˜ Ô%þ(g² ùôÐCd5tƒ ol(˜ˆŒ Ý’fõ[X粆ÞxÁÒà|›IŽœ$¨CqíU÷1ðuÉ$Mš3%iF*Ÿ‹¯90Yb²;YG+*ùIp¹[Y‰Äu(i:áÒuªŒøxW}…ÿüjø/>ŽyB §‡¹àSTsÆC]“%fÇ—/àÌŒ§Š=á‹â?A,-Ž[Œ]+ÑóbZá ,ctÓ}´«Q=÷õŠ{yGÃîîjNJðM<o{.S¡†¯_tÂåìwYºcÍÉä@ë±xåQòõÜÒÈàóS>Ced°íX™è¥Ð^oìúarz×—v lkú®¼bÅÍšïŠÕ7ž>¢=*Yü{kÍJI_]&Š_Ùm´ÝáĘØ6åjMÏhœôÀ{”¤XéÒ´MºÂKÕiçÉÿ#³¼ÈްÖü„™rf¯ú`µ!= Q¿æ§pç†xÂÛM>ø¢h?T©©ÊØ(Ì*ô,“óE±v„W*×Féd,úµªuke]•sÄ7r•líÝл —b/ZÃ<(ÏZ]¯qrövV6šæ+,9î’eŒq‚K£ûwÒD~æ³%M:}yc±›ËH¨^ª+Q×Âêp±¼sU¶¾O)f€ëÁ®T"¡–—y£Ñ÷„V‹dwߕ̱y$MmcXЛäÃ"Ed:iXÄ®“¡TR™QÙö¸yÉ1‹ÊsöN¨ä°®U¹HJôVµ÷ŽÜ/ik›@¦˜ó݃øxÖßÈ=Ãáʆ®ätî(“÷ nÖ‚WFãÅ’ÆìãáRâ.ªr×U~—º$”ŠHEëFºhÿ«ï©ÉËí®“†ç«˜óâ-¥â1LAq³õÒˆDÊÚ-aËj³x‚kfót§L".uù”Ý à„ÝáÒéû]ü(üS.7~›Z¬]‹¤¦ŸénäýÜ©ÝC*ÊÆ!r¿ý+¡ñ>ÎmÛ• ~õ•Ü+Ù{}pŸá•3¾Þo^&ÌC-+·Æ5êJ†%ʘiyP¿Ý³¤Ð°fìvœµX#ìý9Ö 8ØÇZE|)„ŠƒFVW”ë´$‚ïl¹*—a„PUZ©¸D¹…2T˜b¼ò&.޳Rp4å ËØíæ“!©€×¹LKÎЫgD&|^•oUÿP驿oÔè)v©¥.®® bÓ+jø¥À ’q»Mý5*]Œ%ôÞ3Щ¨î Ü=:ø7ü÷?KKU›endstream endobj 598 0 obj 5236 endobj 602 0 obj <> stream xœµ[YoÇ~'ô#äA3wÒ÷a ¶eËìX‘éF”Š”H"¼ÄC¶òëSÕgõLÏrIØD-gú¬þê««÷Ã>›ø>ÿéÿ£‹½¿¾¶û'·{lÿ%ü;Ùû°ÇCƒýôßÑÅþ—ÐHrx2yæùþÁû½Ø›ï[±oœš¸Ø?¸Øû÷àG=L£˜¬µrá—u~Ì ãFNÖq&‡¯Ç Ÿ”ÒV ?Œr2F=¼ª¿7bøbôlÖIJha ¥3“V0Å£^69Ï,3ÃOãFÃÊk:Çkì‰møðbT“sùß;ø#óÂ+•»I冯ÂÜÖC·ƒú1öóœÙá_#Ÿ¼wÊÓ^u ÿ9ø;È DCä¦4ŸŒÑƒ¸8H(ý‹•£7J±I¸ý ,Þrïc'\Küñ þx…?P6ßafÁ†¿ÅÿB‹ïðǹÅÄç8—“6 Îìû½ƒ¿ì<"Š$žÛ6#–a¾Á?â×eîvŽ^À§ôû:õ›ËuÃAþ (3yí]Ô@Ë9cípÏDk>œetÞÂHJL>ÞŒ5Ii˜Þ>”Rá{>ií¬î+ªÎs÷4¸àa À¥—Á/qp3)ɇC|­'¸G‘Ñ:ƒÏÈá?ŦJËáYgʸ6.]û¯™gíÚ¬”¸ñ0¢l L>þR üªB˜¨¢ó3ÄM&~Ú buˆ™¬áäñ¥16FvÐp„y d"-HU£³ŒŽé>8SY϶Lh#NÃe;K®\e ›å쵎FiaRäœÎ»¾Í§ds{[î2Ø„qÃÌö¶¾9¬¿â4çe O¸TÛö÷¶I›Û5Æ=^VŒã¸w(;1ïó.a§Ud‡©‘0©‘@šV"¼(KWÓÂÂF±_!Ù~4 Øúþ¸¾ÿS1ê10ÈCèô7]$&-™U —L T#„OÜ¢%¸qÕj#‚ôJ1òsÒìe¯PÒ€T¼vNÙ4! }ƒ½5(rÒ´² ‰'DܤþR8[WyÔßJ£Ó2Ï}ˆüã(%ò¯=âÔ0zת Y”H{QlÉD1€‘Ph4ñX+FÈyœ-9­<ºŠzÀ­i‹+X“ZïÂ; OÑ…ÊŒ1Ö¨¬•Bs˜µL¸3¤¥Ù:'!îÀÇ HBާý&õU„'L“Ðñe»O¯Vº»¤žˆ?VU®IÃûVAÏQ’ôÒÿEpBsN–õ)p r?,q]Td”‰g—ØFùF“mó.²ÎðnÌÆâ,yz¯a-qŒw޲e®z–±[:KG ñ°.I1®Í: *™•ˆú†--7õõQþ€;>©–¡%ëÿåV¥_*Ðj’cK«2âœxרñ¨EÔ"•OgÇçÉêÁj{hX8íP}üPà¹éxð”êQµ¶þ°… 9ð 4l;kc©µ»®»jÆÈʧú츞}|¨´+êm14ŸPÁ|€ÿCà|Û*N\¬°ô¦j\:EkDK7·IÔdµÏŠDvÙlNCögÍ{¬Ë­û&Ðý<£²çöÙ<­ãÍT2ð¯ždùx?â Õ§çõã}ýx\Û¾«OAõ•·²ã¤~¼©ý®º_—=³äÁ å] Ïpá¨ï†8.ÊÚP¤Ÿ©%.8šî`ž|zKÖ`D–q=@ßayÄW ¬–~Ì¡˜èù6TÕ¶@뾪àª`Ãç04×;€àP3lÙÞyu ÉÔ²Õt`äÊV©œx'a\m xp ËVíˆÙ©m¦qc<¨:·4FÇÝæLÏ÷q†Q ÏéñÕ-áƒ(ÖX(ˆ ¼¹G›5q+Ø_b$AÑÀg…ÀÚ>lpƒËM,½åf>u5MHA6+£«ÐĢǨ#I*(b ²» %¾fƒh£œàêY8úUÞ£Y!¿°68ïÂðÄxñfx rÀ¿çÍLOðFmŠ€Õ0ðî6-š÷Të‘×[%ËC¯¥É’‘v»Fõñâ³"Þ-n]Zé:™á\„Ì‚ôŠøšÇí€Æ_x»*£šŸ¢ú“hœxlÅ›ËkT†ó”:ew'­[u'[ÿ¡™°:Ž,§.1Óbe±a43Qd¨6ð,ÙšEàœb²xîÑ“}¿¤¬«‚q%üx„AŠrÜêù4¨S^LH°uš+¶I„]'ƒp?7‡9pKR½nùžh ]*¯oâ$¬öAÐW€/9§Yà"Z¡À)®Óþu×Ó[rJ”hÖ i²-è%û+à Ql„¼]%ª”¿p¹fJô¬>­½z˜?¢šr‰kæ´­û†5ôlfWðÃ;6ެî3ê'o’èZDˆ6ëPÊ~;Š”ï7`üC1ÌÃv±gU7ˆí!.UÈ;€ËuÔXÂËk‘c0‘îdijxßm›¥Ÿíº^Ñ]iQí†ÓUÛ—21ÛÁI6Iýmp¡¤`’ºÞv^pã¢æE6@Óz¨\ð]3cêèoÆèÍCòÓîÜ+7¼Fÿ˜Ch@MÏÏ,y¨vGpÔÜBÿ4hâLÙ¶ì £_ÝÍ4@]}vAˆk‹ËÙ!ûóoñð@­¨‘ÍI˶¸?’ç)K.ÔJìœkˆÄŒ+Îu/-Ð]Šb˜®”€Ñ£ß^êNô„Ñä§fNJ*ëwÏR`§uvÁAÒÐ3ˆ31¨¯<•?4ÑaN»–_f¾"9ؾH~±ñÌÖÉzb¡ø ÁŠÑ}$_V$W|µñq´ˆä“:‹9M µ\XŒž/i¢Ÿ)Ř˜© “ð[bâµ$Óh¢¡¢´´r[ý¾”!˱ë‚@¬oÏŸ”¿C èÈš®Š*°’‡è¹I‡cßÕÑB³/çãÇ& ¾jýßr|5³le„s˰„¨M™ªú˜rý\ C-ëçÛŠB07Ïä ¥L[ ¶…"/ãÞ¦1\Ù—µXÔÙ‘Ôñh•¡¦äÍXà (pÆ@$¢É-¢hT?^Õ@ß*™ÆfÁXCR‡3Á„}ÙB;ÊFáK•ã6Rõ˱¾d!?«Œ ¬ý(\ZX®â2;oÖ ¦€íûñs€*çƒz¬ðn@½Æß3ê«Ãž2Ì&Ë6ÕÖ¼.¥žˆÚælžŒÚä¿dÿ3í¦õ?×ý˜ä,íè~h4;þwöMƒm£æ¡¹¶wY'*FCht Eƒ¼ð„Ž:”Ûwκn!úX˜Ñ™yÎĉW$¬±ô~ÎAÆOyOv5VM#}[П(Åø²"3w±uÌc}ÇuMÌY¢s‹7sHwž]»“‡e5%úCíyŒ›½UC)3ìOd‚ÃÑk²<äÜIä*Nθ$ ™Ï;ÐB"ë°Ã–¬ë•šE͉bˆY5w›ÄW*jÏzºAʽ|,WmÖýXT¢ëTtï|† ÞM?'N-Y3°$­Ud†èTuÊܽÒïçÍ%жf‚÷>¬·9ÒŠµLŒ„U 4BÈ(Ó}°˜šŠjÓë\[‰¥”5V›Â[DXºšõ¼mv1¦›aqªçu–H›q–ßðÝ][Æ œ•E^ÆYÞ–§—¹O}ôøö<“/•¥»caüÓÒÿ6< ÉõG šL›Œ¯p ð°,Nr”LŠpi¬Û¦Ú¦Y£óí]ØbY ,cQFñá‹Fš™0êœ÷½3]HM?B0¿Ç3œQƒœŸmCq¹ãCDOµ=µ²ºôì&q™3‘§ßç9uÀSlþºÎùcyøs}øªb+Ë´ú?T–6hB|8å‚I[==‹’­¯â`#®=O½M /+éxáE‹p]þ!ÿHQ‹@¶îWɯõ"ÞaÓþQá$œZ#B˜udvÙ:äÆ#ꄾs†‚ø?ÊpIÊ/œçg± Zðý€ü}p¸wæp'ocÝY‰S ?éRâ$¾I6!â–2òáÛä)JÖè“^&U”CŸ‘@µ¹ÉV.}ÛEfvw±©µ<«#tJ1ÑÕ;^ÖUv»/JÁGÖœ*áJ’f¡àÛÖ çeI;ÖÌR`àX/ªÕB–+öBÑTí–`›`X„Lïª?.tŒ—·fðØçê–jþ=é~{ÞŽéÜʆÍÓnßA¹lÚùÕö{¥'ÓfêS.¥ÔA7°þàˆ]¦5‚Ö|FV6ÒŽ01ötéW ÄFR*|BVVà£!ZæãMdݽòjë­ª¤=ô®gÜmܦÎ1Ló¹ÌqçNE†Kµ z[Z›/u ¹ÄÎê¥ùßä÷à–£Ý­>N÷­ý8j…—Ä|kƒæeî6÷·^Ó+†ñ›Ñs@”*§ <Ä"¨§e+9êxqÌ*§Wí=¯ÞÝœ³ºRÓžOí¥]*ÞÃîtó !.Óåì@×v袻û{”Y…ÛzÅ(/âqĤ]¸é¹V¨Éƒ.'ñÎt.&±Íø ãÃW`ž\­i^§øGrWèÌ0 gf– ]LP^E§HX*“é;. ÿ竉ê¸wCç!hÜö-yY_å¬:Aï6|ºÃDÙ2ϳJ0½µËDùû;à{t¾ÕÖ~qç)w‚ˆæ¤oô¾ÝöÐ÷?¾jla“Ú ×3‰#ßÝ$.!N!ðpa‹›$ˆlbJCR¦Y0t¯pŸ[P¶ûú`ïŸð÷ÿÅ+yJendstream endobj 603 0 obj 3894 endobj 607 0 obj <> stream xœÅÙr9rŸ;øˆ~¬Ú ‹Ò-mÄ<€1Œg¸iv˜ÀæÚÛØæŠaþ}3u¦ªÔ! 6n·UR*ï³Þ-Ç-Gü‰÷ß..Ý3Ë—§‹qy~_.Þ-˜ß°Œöß.¯¬aã°2¸Ñ±åúÅ"œfK×ÚÊ®ß.u¬Wþ—÷êÉú78%=Å4œ[ÀÞ~%cœcݯ=œ³Òu—{ÞÝéWlRޭ˞ݲzV@í\5ô+cìÀ™ˆ»-g’î¾Ù‹AkxLàÞèWîrã䌰C¹îZ×mº=•1µæÿÅúŸëÙ(ºW—҅빨  ‹ÁZm ,JxÌ8Š%­  téQEå%|Œ3KàŸîNQnJÍ)œ ã4Âñ¹“äÂø„'ÙÀE·Ÿ¯ÆõCÔ¸¸ð1Aœ ÈK¡¤@üÂ0MqÄ3¹üås†þ ÅúÄu&\Ù¯çBvÊâaëùž‡t àïðÒI˜êÑyLçøõ@ÏÇbk„YÿŠ{‚(¥­Ì™•µÜé‘-G±z[Ë[y«meGû`t+‘·Hgá‘í~z†Ý|äwÞÆ|úwØ3Z¿çQ½=CçèD¬ö'ÃâNYÌçÑúÒó¡<‡¯Š9ôIzŽD3°M¤m…FšMù ÆÅ£rö$/>OJ€Q<-¾.;ßÒiñ´rò’ `Ám[L<‰fôgYù;¬Ìù†xä=‹”×=¼?š~²M¯ÔiåA#ËÛtµXü4/¾¡OÓ²U;˜_î…ò—Èé8ÉÈbƦTȲ”ÒÔ 㒦ĔÈíŸ+70p9)éÞ‡^ø5FÖò¶‹˜w#jK¯ÃXámÔD¸fOÛhQÿ‘(Íh}¬À,Ôæô47QfjdQfläµÌ80Qq»Øx v‡ZÁTÞÀÑfÏ‚´7ê~Å*PïÕx˜p¡h2ñű,eÄ`P™Qg+@ Ū"\Œ(!º¶Ú ª´Av{ì9 îÒæýÞnœöãÔ9§··"wFÂ$¸Bô²WĪ7X4JV©ªŸ¶=øpå¼Ë&±¡l¬³F"º»ëÅÝÅ»¥^#Ç%\,T <¤]‚™ŠYlÖ]Ù[\Ú»¹<;yÿ|qé%[\ú?®ÜÙ?{W—ÿXìî-ï~cAh‘KÔHÚx…Ÿ‚“æu¦ôDÞ·HË7S椧è§SÞÆhJÚHÒ1â¼B*¸¥Ý–÷ͤ 8¨õuñ›*«¥¤÷göºÎ“¢ÓâF{§uF,Ž“Èé•R«Ô#â:´œj" •|á~tiRæóñÖãrIIð ±uÔG” ý¬„æ’&ä }1Ù…ƒÔ(ëKÉfÔí®&ùô ñ|0R”µi’¶¥n^h2'x;µ(8–Å—¡¾Î †OÜlfgæ¿£IDT™#)¡R"!ªMGUfñªtFó]dóKùsTªî#AyƒäðAQü©u.„9¥0½KÙ[Òã™E=&_e R3îRöÀ¤ ÖR¾»ªO‚T”„ù^ê6¶Xu¾ìcƒà3£ ’Ö Z¸¤“È"­)ØæH¹‰!ŸÏU9%‰£–Vå$”MÁq-‹ntÙ v/9 4Œ?ÏeCŠi•Ã{.i<Y G¾fÈ‹¹bxŸ3œ6&ƒQö§f½+ t5$50’óUÇX„k‹âWï ËÏ(×3¡×ïG/ÙÈX`%À—óÑÒº§”þÄÒ £J‚Ж}¹"Á„›×ËU_–æs#7öBÓQé8@Òé­ëͪ¦¶øØlôÚiÊg¬°} QÕ°Ý7˜}Dw2@Þ–áe“©ò@5pþºAÀc%G(ÙüÂnUÚqf/”ud’¿íí•_38oéÍÂûÊùÙw{þO3Rß”¢k”–ßþ"€ÃVŒØ¨lØÜ¯÷U3Ć3Ó¤ÞÒe¢ºîRÙ„Wá 2ÝèáIèùã+FzÝó§Ç ͳ¡Ñ|Wœ8çÉ ¥Û 9” {€ç`P:Io­ø]yÒýlW nýY3jÌÙ‘+ËC§Cô¦ #ÀšŸÇ­2ìS)Øò”½[ÑÜ’8ŒÇÞÓ¸g‹Ã!_è:ñGm `%ù\EvÕAã¸„Š¨HJÚ™à,ŸÖ!˜y1çUqÞ–ÛöÒ !'Cž2ðÎol„9k˜b§qè:²Ð›ŒúJ>½Î§ý¿«Ó—xAçm~”{9ž‰§ï§É©N8–N³49Eö£Ü<ŸÂˆ Ïù nLs–ôäE™]œ{VxØ7š¯{2”œÏݪùâ"Eš|F*q:ä ?؈94Kô¢Ú<å/ó½ÿ¼Þm£÷E‹Þ“igej]ƇŸZ¤—C_%“WdòŸFff<•à>Ö\¬æ7ì_&ðFð[ŸÞ7؉æ@ö|¹¦qºç‚ÂQ©r?MÊ]&ÝñÍŠ&íeñYC)CŠÜ?´fô!mxÿÙÎೊC³9sÃÿl~ÐO\Õ†·èð­µãì9–p’¦»ÕüxªåðM•á•SÈ+g|¢€éšŒ5>ß Õ!Sš6¼æäíÒ8aÀ¬þaˆ;(Ö‰'9…'„GéëPÌ’t\ba6'Â;µt©„ÛÆÃTA™"€î²áÊzo3!鯬0 ýæ0AÓƒál>C›¾VYµ¸«‚£P^P©j0‚cØÖhþ”ø[Âs£±[âýç$ë^ŒÍLàŠ"p ß÷"]jÚiÁqßÙøÞì%ÒX×”‰™u~”fW­9±ï¶àø°¹F©NŸëÑÌs°!B´îëwcíõÿ¹ÙSmºÇ'uӺο·ÕºLMgé@PûÜ®¡=`|0­0…Àä6›Å¦¡ýxÔ§ 5«Sß’.§§dS ¾•zwñ?ˆ~Ùendstream endobj 608 0 obj 3370 endobj 612 0 obj <> stream xœ­ZYoÇ~'ü#ȃgí¸ï#@bÇ1l(J"oVhÒ:ñ(FÖ¿OUõU=Ó+’J`^MwW×ñÕÙz»‹Ü ü/ÿÿìâä«§~÷òæD쾃?/OÞžHÚ°Ëÿ;»Ø}}€MZ—%Š(w‡'é´ÜyµsÁ,Rí'?Mq¶Ó2«Å{¯'GÙû%Âôí¼—‹1Ö«éÙ¬¦?ÀŸ?ÏzqÎ8;ýµ->ž÷ªl6núqÞ[øå„ûçáà®b|+€•Ã9\/áFü£g‹›÷yu¯ÅâeŒi“Jl奧à ì+aÂt÷š°i¦³ÙÀ•R©él\´6QM¿Ô§@á=°‚S¾ï•‹µ*‰?Áº÷ÎÚé{%„-\¶‡¯A b)íP0F ÿœä5°ýMÑd»ú ŽìØ«v™Ñ~A=¦u¯Ëq¥ÍtË qïÌt=¸§ –ŽeÁäôEÛÌ4rƒ’ÜOÁ½a‘RM—œ›rqûuÞ–oP]š4×n½J· á§×…/Fò¬ª\ß¶Õó­&€ø³Ñ ¢Y¼’+É>FYÀ¦Of¹ÄL,¸CRÙ‚!èé/xJ‘#lî0¦ßãO p²OVÀ¿žQWÊ…Šjeë@LR¥2nSm_º+j-áu'9àÛ E`/òí%¨Ô •ÄÌ(ñ«µétQZ¶A‹Ù¸3á^K³Xc§ ½¯ªS2GÉ\I+ÒV»¾ÇOPcÚ·dSꎗ¸IXÒ³Ê7Í€ 4m´þRb ¾j˜îÔ_pu:wÐþˆbG´4ƒæ§Ý1ù™äž™y†LÔ¾!»Œ¡DÏêß̘˜ E°S\ï$ðˆ¢åµ K´±»qs§EA Üf‹yh.D\Î <Ȉêc¸~1C8Õ*Ôk¬*(’k ðÅV‹q5”z‰¦ÏŒÁWL)@ÀM2Þ› ­!ó“ÚÂ1fÓ½äEä–ÖÀ쇷dûŽaH Öx°»æÁúì ®FÅ»x(Ç·ñ]d_sâ@ZŒ=„f#*ò¶úF—œ2­ÀP²qCjÔJ<÷ÔÝGm=Ë[ŽY+ÃCÇhð¬ŽñœÖ];*S3Sâó©R9dÇ€˜lÿÕçXÝÁê“˰ç3ÆÈlBr—Æ¥ó¢É’í½ó<~¶Ì[kèÅó –âm¶ÐiÀeLЪ±ö™àÝé ·ÿY)hà×-p“ó™rnz:ï!pFá±­0»l0&U€ãJ:ß¶Çk ×` ieî,nfì\axG•†h¤’¡'´Mç2}¬Xái“b Gû¯(>ø½n±Q©Ôþ.Jå© ]™ ˆ‚òS.ÙpIÊz¤☸ÞöÉHz€”V ±iñ²7“’à’VßrÈ@|O¿ý)¢­¿VBtŸJäó-?‰LϽ¯|b"DdŽÓ{RÉ_”Ä]æÄèÆ {Q¥|Wõeá„ȉÍÌÙu½îuÕ[U#é¡“÷nîþõp=­*ªf¯*ªdn«_×=™³Ê[ݛ䩢L_}¦P:ëÖj¿/‹«Ž#€3ùZ•š²<õBzúϬÉGd->OºÙõTÉÑwdQ¼1&ßßdVÈâ™cYTO¹ #45l›Z§s÷73Õ×x4` ¸—Ì| àÑHAóÚç#ÞîˆÒ*‡³Ÿ§T Ei{LIN ŽÊŽ·üžkìú¤‹èŸ«˜Œ2ö­R"”B(‹”=¤“Pû¥ýŒUÒŸ¹ƒ Ž…Æ¿­´m³„ò]éÂ"B— k©†©òM-Iâ ÖœóÞ?ç©UÊÓ"º…Ó¡½¤™¿,«Ø>nŠ¥r îjiµ;xÜtBܳ[àÓR,KÒYé2¸6j Ⱥ›—ëDÁð†c°Å‡VÒ±ž’¥þr‹=ýSŠGk×z—ÖD-‡¥WŸ æZÇQ«Ê²$§Jì—Eá¦Ôfˆ*ÖÛ"N¿i,½­¥æVÅŠR p<ƒ aÍÐi_,â_ÏŠ ü¢´jJq¿h©®!+×½úP–íÊž4HÊë[±N!? ŒRjÒˆ#æÕêQÈõ2ÑÍJh¢j˜Â ˆ=ŒÕ=G¬@ži+OpíówÚº¨w{‰W…âN)+ÞáNY¥øóQæBoçˆæxÅ_£dëmV6`’çäÍHíã ’YCÜæW$7ùˆçó×ÒŒ™#]Òh$BqgÓwÕiwÐô‚G½ð„R—ßR^r›_4,ÎTlÈ{5u¸2ù¿WÊBYRJ9YÑ®Ë}ç£Ô”ü')vOlÐÌåQ ¨13'¬äklÙï*#R)ó$Ïáñs&ƒî¦Oe³Ò÷ØŒ>„°•u¦cUÏXÇùw Ô@ÅúsÄ}LSîïÐ2V´Î¦°Ÿ¢AœCYÁ¾nlŠ"°ùïcü™hýq¦°Ûž ²>ˆ3A̾Àönœ¬2ï"…$ðõIyt誸Ï.+¨F» DrƒtPy¾R±ÆÑKLX^K]¥XÝu;ÇR©Þ"¤'1ÚW8×›Y‹/­xy]çlmÇ"ÍÞ sèðyÅ|‘ôÎã/„3ŠïǨgëÍ0¥<ô‘Ä@å…:ØŒCûŒçn»:¯o¤!×ï Ãá]cˆR` ܚȄ¾J¼¿Á›Ò˜°gŒ©¬Ç)Ê ]ÓŠƒ«jOÀ,Â*¨vݸ¹éú’ì3läÅÊŽ«T¾%¬’«“1KG¦ÄMmæÿ²“6Ͱ@ʯ2IcÇfÒ¯øS (> ÀÛúgÏ–ÙD–ÅÁõN7Ãé²áÅÃ{óUz02°ã," ŠFõæmk3v”æ]¯u>ÚÒóã‘TF?µœPübS;x+"Sš1žK0Â×pÀÀçöãùˆ4ÒgœÿÅ’qï Áâø<ë}ƒ>¬áòuN˜Ñ +˜ôo$…-V%^%Ãà¿h¸ä_“*µ§¸~÷#gy—ïÑ›ÿ©Äªb¦‡ñ°ÃGþiÊÕ±kŸ±zø~õ–U"·kÑFù£g¶6åŸaáÊ·‡“¿Áÿk™Úendstream endobj 613 0 obj 2666 endobj 617 0 obj <> stream xœ]=k1 †wÿ Ö`Õ’?dmI¿h¡M¼•N)ÍtCèÿ‡êr9Šéy^á³OH>͵¾ÇÉÝìÅŸ~]òÖ'wvtüú'7 "¶ jRòãÇ-6yaßzA[ŽÉ}‚zéõk¼˜•ik±6óÆ·±÷3ЍRxBÕ^4܇wˆ„¥Tá0®Ìî:ÝÛ4[jP;…E:2å•îLeK¿AÆÖl½É}…ÈvKÓ?'g#ª†˜ÏJ“ð> stream xœíYMS7½ï¯˜£ÆÅ*úþÈ!‡`C‘8àÀ’‹,,¡¼ Ø8ɯO·4#i@,à*IQ.@ÓÓ’^¿î~šjå ÃÝßébôÍ®mN®F¬Ù„Ÿ“ѧM÷gºh¾Ÿ€“k£ÆÓLf£8™7V4ÚÊf²½'ëí˜Qm”u†üÖŽ‚KIZF½a†yrÑY½ ×-§^xåÉq 6©5'—íXZCḒ“Ö CX7æÒü:ù!âPÔ:ˇÖTIïšÉÛÑäÕ{²{)Ç9,»ÌÃE;æÔx§u9<À…¹SÆ:ܼ…SZ‘?…ñ)9GèÜxOfÍRíUšÇ!Ì9Ä ¥UÔÃÊ0Mja¸$[!bf„'ÜÚY';”ÌhSÞßÁ¡„05Æ)YÓ>ÎóÞ)K®z%%² ¤RÊ$ðÆc$SèrݳVxª…Rsë  »fÏÀÌ„06(ÜÂD©¥0¢Ô€CEǵQœfkIjfr™"g,9oV?¤k¯"g5f2 ˱§5U^ OúO^0ÛiÖVºñüs˜ódĸóoÄøº?{¾¨†Ÿãf¯cû=Æ_Áúo…ôtàÉÅZ?Õ>%ôUÐe íýÇýW…›?$¥V;ŠÿR€±„Ò)‚UšÝâ»û\xûìVÖ€§ ¯ðú"y_‘r­%\ÆåãÊëXtÆå{òy-êëšàÕoHÊͯmBIª K¥î¿µñV‡Ÿî“ЛÉègø÷7½œ©endstream endobj 623 0 obj 1379 endobj 627 0 obj <> stream xœÕ[[S·~çWìã쩳“]F3yH•mìàSÆq`]É)çÔ)ØL™ÂÅÿ>ÝÒHjÍô^XXbìbÑjZRwëSßFü9(òrPàÿö÷d¶õÞœ\oƒŸáçdëÏ­Ò Ú_“ÙàåˆJ=yS4å`|¼åF—#U­rx8žm}ÊÊ¡¶?ÕPÿoü%K:J5yS6 ŒOúÕp$sS—…Ìv†"{?†£2WJUÙØ=¥Ê^»NmD¶½²ÈëÆØu øÉá©M.Êl8Ò8ºÑÙÇa™7M­šlw(óªÒÆ´-©¥]joX`æÿ/Lª‹ì\QQUÙhŠ ¿©Ÿè²šR—Z)°iLe²·ø¼†’2Ox"¸–Èsd”P¶KU£Ä(oaŠ*ÁZR )Ú©š²0Ùû0[Õ4MÙQY˜àͰ,¤©¤öúoUŒ)Ø0e ¼‰¼(4pùr¨r)€¦“Ô&+ª¯HH$oy„yG„ƒ* Âï>a±]R˜Ò¡FÕ5#UèÁvÝ vr`Qø8ÇS\´(Ê2»Á¯?p ‘·¸„ÌþÈRj;†¨ºªì–>¨ÕºJ'÷ aTY·SºÇÀ”E^€èW¡ó"޹å&:å–< ¸Žk¢f`ïtUÀY{·5þ×''¢•·/û=Œ²}ï£ÄÇ^ìì ?޼âõ~…ÿÉŒNdöHzÇf$ÿùœ†ÎÛØ ãuQ[}^spQ7ש’£ð©Ä¶õ.Œ²ÂîF‰ol8X `päž væ8+Ÿ…ΣؙhÌwÎ(eÛÂ…c­ÃÓiÀ ¿½Ž"/8¹.¸ý>êïwm6)­=ì{aÔ»ðà¾ÒÆ•¯¸ý&<Þ…ÎKîhÚ]®¡]oRî·^x7jÏoúãìÕÀM輋—‹kßV_’€ë‚36‘¥cΦž-Ù¸Øù7çu"&™É7'®©dí8mR6p;1ŽÐÁéÅ7ìŒW‰ì--Î3औŒÐ è¦vó†ý·à@¼ »>ñ[ßÊ<áNöÙ™û;2¡zD‰üàëó¢.J'¦õu(f<{¾ÅÛýG8¬ï¾àäùÇèHI„Â’xÀ‘ýŽÉdTE¢¢DU‘ÊT@ÕX…‰‚?@§ç7Ã7Ð~d‡ÑÍQFJç5ªŽœ%L5¶!œ­k‘D®$¬Ë*@&äSd_1Ö5MY‘>TVUäBãQÁEtMHI5KÕIƒ4­Z=9ƒXiT7¿„ç×km*‘ýc¥±Ë\Ƽ§9T»»¢T&ákíÓ­4pNä—ÞdD”Øsó"(vg¸RAQò?¦-ñ|”|£¦KÂáå>w²¸NÂY„ÛŠqõ®79kkÈ!´¦9¾Mt>]¥ ú?v©ÕÍû¥ b²Õó‹Eììúõïµ_žÍëèÝá’✳s³‡…),²Ò@ÂQDã Z9T¬¬?æax‚`}ÌÈýqrŸs3vÃ7(í«µŒ##í¦Ó§·aÔn@ç*ü0}@€#œ¿­/:äs$¥.ͼÑ6j,$ŽîÇâQq¨X­líé ãpŒ"²—«*Clç¿ ]üÙ?±çKˆéß*–È{{Ê)6¦CS;Qeªì¾¾ „sL‘_åç0tNÂ<1ç8ãt<æTqœÆq#E#òÚ'¤71!½ ¦ÕO"kLv=)QZâ›pñFwNÉ‘üLGa&„p¥!Ü’ºÌWC¸,:)áuÀÕo…PÁ!ßá·—Ur‘ð[_’/-chœ—@š=Ÿ+–, ÑËÞÛeÙØä ¢³ï,E³aÚ‡@^·aœì‘CgÖ> stream xœí[ÛrÛ6}×WèQìX(//}èLã¦n.M[W™4“d2ª,»ë’X’íü}’À.ˆ%E%2ë¦i@`÷ìÁÁ’þØ÷YÐ÷ÕOùw²è}{šô/Ö=¿"/z{A^¡_þ™,úF²RÊ–ùYÐ÷ŠÖA_„‹Ó~œr&+Œ½7ƒÀùoâ‰w£§²%OqË!÷Kyù, ²¬?:“~ò†Ñ`¤¿©ÃÏòÀ|?ŠË?Ôáí@·ê°T‡™:lÔáÈÔþ˾ñÁ†,ËÒ4Î ‹:·P —P8¦jBóµ—Ê$u­–¥ÂTëòön¯M¡lÍg~Àß{C!­‘eº¿¡F„ ·hD¦ð­§K•郈‰Ø—nyÞ}³ËƧmm¼67Ï©[Îq͉fôÁÎŒo±½tÅ¥±q+_%<Øíi]qJ™õÈ<Æ8Û+S¸5ý,©Â(.Lʼn)[açêâ~”OÃ,d© ½'1®j(³Ð,B–Ü)š+d½šBÖ;à¼Wˆ@”¹ËúÍŽ;ªfÔÃшÎh¡AÀzÿdâtˆµøhôB$º& •KÖv¸ð=§Èú 㳄¯ÛÜY*tOn  çÉ@ñòÔ@g£qfV¹R™N5â*2Æ]­8p=m«j+.x´“åóxÑ6.òÕ·GžA ì\»äo}¢Tú”P×ÖjÁ©+BÀ.šak‰{[P.òîÀ!Ìn‰Šäm&Ó¤®¯M‡cû3J^ØëZ]›H©%ìý€y¾—<ëB·FŒ´¿š¥µÝZqKát†‘à¶+„‘ž(ÚÒÄ%aÛû}z =q"猪JjöÃíj6j˜ –©\’J*eFª¼òd8$IªasE±Ïå°ó2õ„ˆÉ%IîYž0! Ÿ©Ç†a+£rÆy† ~^(ëÞxaÆÂH–®<¡ûåY˜ã,rATºJžp.M»-Nc?W«º5S½ Jå Âƹ„v0$i@в$ßÉΘ…AÎͺêXö{á徕óf‚ó——‚NÊqÁRµ’)û¥Üe³/\òX]·eމqêU…9I$±!‰Ð?lþ‹Hz›V¿ªË_öšÃÊH‹E KŠ´@O“;Kó5æöž¨ËÖùÓ¿Í Ž§<ùïLóGÓês£qšõ’GÜÙÃI|ãÄmfXý‰Ê§™ŸÎ èœqšp”HF™qeÅ0fõiðšoS­48ñf7O¦~n¼‚Ê÷´Ä"‰‹ÀM~ jŠ;Ñ'ÄóݼÇÙÍŠÃRV¦¬jÃå!·ü¿Î-[1 *™Ã}”IØŸ*Í"•Pâ%“¤¹*Pç1“ŠíAíÐ/ýs&êNíŸ Ç4etP÷­ß(ü„ˆËÖßOÄ ;Vн‚½™Ä +‘ÿæ°“*æ¯[Œq:Û¬j¦±?ÖDI4ƒð È©YzïšY‰#î#¸_˜Vj¬·2 äóe|fÍc'Í3ªpBèë»7WÖ £ñ#Ò%êýG•«û«r¡‡ÒÂB¹òñ¨÷»üù’1Òendstream endobj 633 0 obj 1998 endobj 637 0 obj <> stream xœíkSÔHðû–?b?&Wn̼3÷Á*õ|{°|°Ô²x‰» <ï×_÷$3Ó “]@X<)BÒÓÓ3ýîNÆoò`Ú¿ÓÁ½e3Ü>”çð»=ø6`aØüÙ˜Ž‰q€¶´l8þ<¨g³¡áC]ÉÇÓÁûŒåÊýV¹ú8~³£³¤-,³fŽ7ûQ>…©X)²¿rž=€ß·ùˆRJëAÎdö¸*óe€Š²¨¬që”ð[À(ç¶à,[ÉG g[•­æ¬°¶’6{•‹BkeLs'”pK-ç•ýw@T•Ù\‘s®uön¹Æ@õ„^â6­ðP)@…m£Mö Ç+ø'èæÉž®Å9î9n”`6 Y!ÇÈoiJ`-!¸à )ËJ“½êUµ¬#²@àIΠhàJ(/ÿFÄÈTa†U°7^”¥‚]>Ìe!8 9ÁAlBSyEDÂy³G  {Ds%˜÷Ú'[l–ä†ÕV#+j5#Yªá´nÐvÜ\Ô[*{Š—¸hY2Ç·púÌ>dx=ÆË^vðr„—»{·ðò/'ùˆ£(+íœƒÜ @ !µý›ì>ìöf­È¾‡ñµ8i€Ç¸E)yàFÆÕ§qx€[¸€Gô¹m±Ö•z1’¨¸I±rKGž?gHó.EÒKlnGæKád Ü﨨]{·Z'¿`«xé”Ô‹SXT΢L|n»àÖS;zùËUPóKÇ:?]ô¡/˜¾Ï¼RìõœØµ:ä§¿¡çl¦¶¶wˆ E¿à$%õ» :s_2{ľw̭̃Ëù¦Uûžµm!¾IœÙE&ÚŒQM³¯‰L™ÊêmZjùÙÌÄÝ8¡®æKqQa7 h÷UyS⛚® ø-ûi ü,¥ê/ŒsûŽÐÃE£tø/µÃÉnt_í‹î·uѯYuv[ÝT]Ôë9·uÑm]”HA·uÑUÔEKPFT•g5ÎÄ—Ô.TU(©þné2/fU}Üë2/f]¨ZÜ‹Y—*K{moÊzÏÆ,µ½ðFÏ'-Îu¢ÆS®s'ö-SlìJ5“´ªhßÁë3R;^ˆGlˆü²kîè Ûõ%SÙÛ\€½K#Ü,â?øè"¿Ö•Ѥ…¨÷a„ 02¥+9V¼ŽáŒ8r<í×?۰܉ÀdCƒD9<ˆphO ¦Oë#Œ¥,`„î=;ž[ óÞ ʺ/LgBAÖ@*œè<_lqÍðÈh_lx›è)Î} iQ.ÿ¤Oâm¥*òµöŸfêÈÂÂÞ$F$NñcÅ^jÓ”H’ßI“·&‰ºïˆ Ô'ó˜ëRѬSW_ÿG gkñÐêÅmmÒ˜YK°»-ŽŒîñ…oåg¸¹´™ÍÅü{œr¼É"?wŽoDG¿Š0Ι »ç×-x±?Å'óWšä¥„Ï3øjŒä½rš¤i´¤)U—ÒU/ ³ˆu'ïÉH+ïBfǯ‹É &ö1 àés€ÞB ŠÇ%ð(;0­4½ƒ4ˆe–¸Wz”žæÄT2'y–¤ÀÀß~Õ4`5rÿŒàçP)Ý8[­ãíz> stream xœí[YsÛ6~ׯУرXxô¡3qœx𦩫í´IŠf$E‘ØýõÅ‚° –¤dˇM&´»Àî·à×nÆÝþ-þO:?¾ËºÃóNÔÝ—ÿ‡¯Xuè.þOº»Ù)f²%,¢"îÎ:åè¸+X¦y7Íy(; &÷½8ꈃWr$ÏñÈ>D˜ón?‰Â,.ŠîàDzô“ÞûðøE>Â(ŠãÞ|ý zð¼„Ç#x\Àc'èó<ƒþ½Ÿƒ¾„‹¢ìTÒ8 úL6åyÚ»6#Ûxnw¨Æ Šm¼¤Æ|L+!NB‘FR@¯;ƒV{_ÿYzµø~»®;‘iœØF9\DyXäÙ Â:}Ha5Jè¾¾{ }¢c6£ˆ^;DwÄ¥3ÜçsjÏ)æçÔÜMerá,+”`½1 ©²ÕWÔ~”£”ŽÞÃcWk°÷ ¿Âã<öLç¾B}i^P ÚÆ¹iüb/‘†rùAÄ}f;ÎÔÊE”Ðú³r+:]6u´mÜQ3œRKÄÊ×t®(•‘qù ]pÁ-¦áGPcI.½¹rÄh <Éq«kÁ‹Î@²_ÒìƒßE^õñ¨¼ÙBåÉAÅgx©À æ,c‹1æ\AЂ5‰ü’ºÄîhÀ+ç×7·xÊGýÑL,~…M‚ç3£õÙÒ±¡ŠxS V“(4OP£ÖF+`À'„Q\ú¹¡iÄo\9Bì»Òÿskök7{l®„ÙÛüƒf¸H…Ä„Ü}­}k›½t–JØìŽí‹( Ý8VD kô•ÖKrX%çì/ÖXç8*Ð}¹…îÚ ë8 E²Ý½Zó]­ò3ƒ`¹çtÃV2HØW$@ÇÎü+¼*qëÖ`Öb«Ã2ü^ˆ6$ÃþZ"™'5¹×¾‘ÚÁÆ"ÙÆ¤9)Ÿ8steFëŽx0‚ÏpLMÜÆ\Ý©¸uxµpÓ Î˜1•qË_ØVí­jWIj.ÖëŒlãjº/½ƒÖ}‘VuM¾H›³^føìm‚î"Ö½ÕTLqœ•’¥‘R„îS&?%ÀÖB‡QtpuÉŸÙãf‰¼ký{%œóÔíÒ“ÿ?lNŒrÈr V­ï[œžŸd!éÇËÓÑ#"¤0¼?É:òwé×"AM&!³’cÓéS³2QåЪœf\¨½³ßß@7Åý=Ê2pÒj„Ë9!°S ;KbðvÞW3ÄXöÀºCÖ‰PQ|B¢Éq¦kÊÍ+€mÜhV†Uc5‚1ás÷7Ðç> ã!D^Èš7¶²~4p¼8 Õ†Žc7‡ áç˜íêl×ÚçÒ”L o«üÅyÈ+nôØ`ÆžrR@qË5‹ÆóéŒÓ~ä„2iŒ[PìgÜ›}%c94T7ÌzŽ ¶Z—L jö¤Öçi†3Š!EgLéȮƖ…j(j†¸’äYÏ9eGŽ˜+ËRîzãL­ÜÒ%vîPçÖ-07¢ò½æ’ÀDdÌŽm×s{ˆ®¦ª‡B¥5}ˆ]ˆ«"S¼Œ¯W—!æúá©è†RÇ…õú(uòÇ´;üúIí•f·_±®(Îo­ë^¬ íDiC°%ñÛš>1fh¯(Ìi¥¶%Wë2³ B_Æë­¬zɯ³(dpUO*)âRnƒ ç!‹8x# £9–ÇÂ,ËÊ-X’¤¡à¢÷˜eyÁ©¹Ð}”±Á¸4ZìèÒ4K¹Z7“¦ž‚ÕÆ’i!½âÔvU &ç¼È5©8& /&Óº9:e€ŸGôy !)¡çËÉ⇡¨SIÔŸ›QênÔï­K´‹Y\w„Ò×6O)7³ã¸V?˜ÑÚt0#~gD€Üìºn[è²öSJ´îåM+ï‡ÔÑ›­ŽÈܦQG÷®l»Ÿ+Tx™tcÙC5¦1÷¬ê‘0Ôe²qàæžuËU‰~T`WvҬãÔœ mH›&gT#•t BßLãˆbŽÔö™Ž¬Á]cÌ~¹ñ‚¹Ú¼5}UÛß[ n+îXÍÛŸûÑ ¹q›­"ÄŧÏ5n®+ÕR !>{ GfgÄ#éjå>Ãu¶†!ìÉ\è–“(…Úuk:gçL&6Ú’oyìPgˆË)|;úœ²î–ã{Mì_ÊŽq9Â?õ@ ñmQŸ¡#5ÍÐNÜ}ÆßÏ¡W"m“mi׫¬zéMmQ›£ôî·Ù¾- î‹SH9”W']*5áÁRGà¶!gF$$[Û©±‚Æ wØ€5[XÁ¶Íð’b8¶ˆufŽœw‹P‡ÜÖàn<^.¯Uw7ì€óš2›­.ùrå­í i?Ðp¡j¥JiÝ«‰Ä­âûÞ>¸`'-‚­£ƒ`Ûn;>É×× ¡½»hH}=1¿N(! ÉÍ)É´îuµ†j”îßf#Ôr›m§òàc)\×ä–8‰-wîE˜¤«îÜÕ˜Æ3Ùwfz+¾z}÷r)‰ –”ÞÓVÂÇEc[×¹Tµ8`¢Ü””Eú~„2ˆ$¬ìS³cÆzW”S–¢6@//BåæT€áS^ Š?:x0išŠýd)£Ò9¬Uº)(Žû5{8@̯fŸ/Q³o/©ËÃe½¡¿­âQ}WuA¹ªÏÄV}Ny%² þqÔ^iNMÍ÷J-~uD9 aîôk [íUçë§öˆáˆ`8\kRez»ß¥ò*B'Ù-F¾ÖxÖnoß§Ê:α¥h†Ž¦îòJZ[ÒýbÐy+ÿý|Š–endstream endobj 643 0 obj 2269 endobj 647 0 obj <> stream xœí\ëoÛFÿî¿B©Ââ‘ûà’wÀMš¸7—KÜ^m8¶de×’ø¿ï ÉÝ%‡+‘š¢‰a™Zîcvæ7O.óû$‰ÓI‚?õß³«ƒ¼2“‹õA29‚ß‹ƒßҲäþsv5yrR-q‘éädqPN'FL²\Åpóäêà×(êHÀo2ÕoN¾‡Q2¥£TiQÀÈ“sèýt:“±ÉÓDFßNEô5ü¾œÎÒX)•E'ÕM‘ªèYÕ¨ˆ^A«Lâ¼0åZ°NÃ]!ŠX¤ÑëéLãèBG?MÓ¸(rUD?NeœeÚ˜úJjY.õjš æÿ?Lª“è?¸¢"Ë¢çp)2ü]íDÇH†»”¾äº™Æd&úïçðORâ M¤®%Òì %=ëK•ãŽq¿‰I²hkI)¤¨§*ÒÄD/ÜÕª¦(ÒËÜϧi ]2ؕԖÿ5‹qCJ;2Lšm"N T>™ªX è ÓIl“å—ïHv^Óó•„•>!±^R˜´BMˆµ™Ò°5™à Â'žfÑy5\ë4ºB@2ÚTLEÈÁë©4À- é½ß.•ˆ5 »@Ý"/ÊíR„â¥ý®Z1ƒ¯¦3¨2™ŠV^€ëŠŸøyã[OaŽ øãÝ,ÖJE¾V[Th‹ŽsYä律,Õ¾š%—‘¿²T`}š–âˆþ‡¿Eøy‡+ü¸ÄdHtèz/ð+î6ïq€¢<#}V¾ñÖ5^ûÆ÷®q WZA³Œþ ;GÚ‹ŠÅU×ïzÊ5Þq“þ6µ­È(€006Ÿœœ|E9òÍß•#½lÀ«èh,” iGØpáçáŽ3 ܱ͢Hö¸ÛRÞ¯·ÜíÒ/yÉѱq‡¾qEg³×®ñý4GÛ˜„²ô;T¥Ðh4•¤4OC%9˯3ǯeݯMÒ§9މ¾ñ†àÈò‹½˜ä[" ‹ ߯BƒÚ'Ú»!jðøøQ˜ÜšÇ¤çg–dG½<Þ8?¸Û7þöœðç1*%B]pJpë:6´[%¥ò#~üìF=³BÚ›T<ãˆw¹gïÅ·¤£­TVÑÒÖ ßƒ¥ÝŸå¨\H±'p”@xéF=mlîÒm.ܦ[¸ÚkµÃ;ÎØ‘F/¿Ëßâ—X1àt» Ž;Þ,ZM¼æ:nˆÀÚ—tvÁüûy|È4ç¥g;ÎÉ`bLì‚K²¤( æu^pI ÔðÜdE¼T2oÆ^6c;ÿË5³YŠT]6£uš{Ì!‡R*5y™@Ò"U—,¿’Üïè* fŠ2ãÈ‘w’HUšãHH'3Q1LÈ`ÔãS)uIÅ7@̦+òª¹”¥€€Ð¢LJÛ91Uôý+ò íò!¼]í]Hå3£| 3Êh¡;3*/™ÑKÆýþê|pùõ‰sÓßãÇ¡Wp–}†ÅÂ×MBÛЬ8µÝt«êòǩւQ-6ñJ¿àtÐyÿ‚+FEåG·;®¨6ÚiL\鲈s«Ê÷^ùNÝ„KVgç¾ëÚu-ˆ*MÁ®¬Ò<«ˆža8Èäé 4¾phd0èáWu~Óv¯£1Æ„aȼõ·h b³vÀý± ãœV0؆ÿÇ‚, wkDÔm÷TômÏr×FcÄG°Á®K¸­Å ´Ô{«g:Ù]Œ×ÎF ÁêAöŽ*…å@ªþΉe@–Œ=õÜ‚Uĺ‡0œÑOŸ¹ˆ>?g³Ç¼éˆX¿¬ÂßËJvÅôÄZû”›-Fu†(°F[þu˜ë¶]§¶ž¡×w\q ^wè”Ï”O)œ˜,fΉè6²²öˆA!ÊD’´‚˜tƸÖIÁ¬Óe]HøÙ…¯ûâªs“JŒ ǃñI&›E‚gk`"z‘@±×Î{ ×£ã&ôZ¡À£ü;Ó5 L)€D’AÕˆ%?ðÙþ‘¯,môlkg¹Ž ‘ȱò<Ô/©ÛgêMÙ2Lˆë$ÖbW¸^p[ò½4³oÉ BhOô µC§FR`¬´J£˜zÇ‘U¦[ùkd˜^i<ƒ>pdpyÜŠ“ÓÃpì‚87Ü‚Ü>N¿åL[Ói¢ÎÑZ–³¡ƒ‡fù¨Á_뀟á- _sÓžûÆ·”.8àí±Ê 6w²ñ-«wõƒ…Tã3‰K ïËë-P_S±ƒÃ5Y]Nû¹ý¨¶ýjà,¿Bĵ$X?ñÎï€TF¸ äå„;|²÷º_ ÇT9ž®RCçñõh§DI’WBòü‘Ø’o:)Ðg ¶ÜÖx¡+¨éM}ÕfAÇÉrÆÌ‘F_2¸a2‡ S´þ{Ð2>ºÊßQöVùi4ÒÎØ€Òwô `µ+EËv¥§ ˜©XôW?Â̵ÎÞOè¨ò´Cë®rÄø¶nlæ."¯(ØýÚ ?vmÛèüãô Ú'6 ­d=Â5Øœö³è#†g`Îï8Ù7j½Múx¯×ûzL§xßZ›Uà; Eî¼RCî¼u6´+û"ý1Ò'º)÷ðx2#ƒUà±¶jWÓ·pšê‰b3ã®à4`aY”ak³ƒ12ë ™»zóa0’‰õÊô¤¬ì½ôÏ[ÇzçýfûQžrÑ4Rñ5šCǬ8:|¨pÉIû°™¢°Cç]CË•õöÆ®L2¤ˆÝÃøF¨ß~wÁ䥷Þ] yvoV_'¾¹K–3c|Z_¥è3©ŠXÈðítµÀáÌfãö‡sŸ¾»iVa¾ú€Ùt–Ñ2Ä&ôønº1Ž>£‚a–|ºÄ÷!‚ÿ?àÎ_¾óÙ>!’” °S³L’ÜY%Àÿd ÍFT tU%xvrð_øù¼.¶_endstream endobj 648 0 obj 2646 endobj 652 0 obj <> stream xœíZmoÛ6þî_áÖkIIÔ€hÓ.ÝÒYçn Ö¡ðœ41RÛ‰_Úøß¤ÄãQ:YŽó²t(Š*Ò‰<ïž{áÉWÝ(Œ»‘þWþM:߿ͺg‹NÔ=PÿÏ:WØ è–F“î³3E ó(»ƒbvÜMSÙM¥Õ€Á¤óW/’SÿÕß¿¿¨™Bâ™}%¡Ý>Â,ÎóîàDMú)èóÞ@_ôågu £(Ž{ûúñ7}yßÓו¾Lõe¬/K}Ù úBfz|ïIÐOã<ç½kà1úL‘¤L{Ÿ8tÄO@ÜsÄ5ž^Þ}v¯‡@üäˆ{@¼vD7ýîÆîõuëâ–Ø0= sɲœ^| Äi ÕM&âÞhóŠc8ÚïQ/˜Dmlæ^/‹[Á¥©íÏ#2…cfÄgV»Õsæ°øIg!¦^=O´2,íÔ3€å´NKÏj„ +ºpïßp¯·Ñ/öÑy˜¤#Q;¸)j½¸±ŠÖ§µvÄ¥wÃ"MÂ(Nµ7D½…‘Œâb I.‹-˜µµ%kø°.d4Ѐ!ÿnº¶bgˆ†b0[s“êÀðïD³|f@[RGÄÀV]ð„â³v@½FuÌëÛ…º„¡Cã†,g¡´nˆ¸¯¬Cm‚>Wse#öÿЗW úsýxä°ov Ø¿ö±¿®½ÝLÛcq Àh˜mÕOækÂÞ[!QlÀ±]pLmïÛòÁaœˆÔ‚ôí‚xJ s‡ž<÷|TÄ23V 'dlšQZhÂz-VøP¹„DÏ"¤ôKj½"¤´ÌAÄ%UB8⊚£=ÊEâ~©‡f‡úS_ŽÏЪeÒŢɡìÛoõÍ¡nçP-j%ªeÎ:TõtÒ… sfÎR8ãa–ei¦dcúN´¼Q:á"Szg¦v 3©|´w®t !Tz< „º‹SáY(¸à½‹ …Œ±4Ë´l±š.3¡¶³&Š‹Ã4•º´Ôr@¥½U™R„œ‹œ)ûzƒ–Jpµi;Á§”d¥ YÊz?(fJLåÚ$vèPñ= ³[ž†‰½T=fôIM¨sW8ÔZÌ.L™¸´Ö9 v=©-(ä)âX€˜úª3ø‹ûîQŠëËøû]Éè‚éSC*–\P~zw'Ô¾PPº ‚½§«/¯Ï©¢¾®^W JÜ Þ·ÓZ=,“[lat£0Ùª@åBP¾ñÂ*¯˜f\åµÓå:±Å†Ÿ˜Ê¦ì@%Ã)Œ™PÄ)µÿøªSÒˆR«ã2¢ ¸ À:Ù —"ãVõò|³^Ì™]{ˆ§xôd¨hmã ÞI‡2¯« N©‘§P‰¹³ª_`ˆDб‹^E/µ¼ )AˆP™†)aà2&$(cð4ÍRatÕmŠ„R—ö ®¸>5 ãiƸŒ‡ó»€Q©r8PÔ 4´ÕOÊC¦°´múÍâ§_ý¦X3ã|Cúe\TÓ/KÍÂíéW¶§_sCµœ6ŸÃ Í$RÒŠ6)ª8쪚'‘íI0¹L §G¹®gQ}‰ðéráÜâ*»&P»æ¦ZQÊ â°Ol½+‘J–Ö‘ÛZUú…©1íŽÄ¹ ?zQ®äË ÀD1‹y)ÒBd ñkXn›Yš°aØN!“ëÚi˜a¨nHsH›¤â*âç÷©^@×× ^7}Fm™öTm²“ºj±å$3dôžÌƒŽý Éé¤:¬"ÏDG9ÕËýîÊ|:øêJÉ?Œ×¢iCèx0ö=!‰>’Á"kÈœÚF¥^/ºþ:Ve©ªÈ\Iìùo™m¶Gû=z}E«ÕóÖêCPù_qý¢Ë†@'°3móu’gºQTÿ.2t\}° ìƒÑR&«f.Uyœ}pÓÝŠeÎP‡ìê”…i S@ê—!ãSß];jëz8¿E=ü ô  ›öF6甓8Ï9¡FºcüÔCnI¼¦ßĽîb›b”9¨Á¬}«|žw¡hlUSŒ>35÷:ã}¿ä9òJžãö¼º¡Q@Ff§©¦†R]åcâ@|†ý¿Þ¸'û;§ø'õ 4Å¢©#¶ ãÂVгSªTΩ zø¨3Qûo-Ra–éô;‹]@’2…ê— ¨DÜÊŒF§«û.®ßúrï;¹Gf}´]ûÆ UÌziUý˜ZʾýßX¾±Œ®±…Á• _±åó:û¶ð$[‰(–ža •wçØÛáëÖ=*øµ¯àÃÛ;XËÔV-!ÒïÌwè$D¶+Û‡2U ‘t.ÕÖî-ZÿºÍ©v-¤£‚|M¹qÌxD@GË»T ýÌ€÷08† Gbyîcy†¯Tëå˜+Gü@yô «³òà.P]C»~^Ù˜šóîTyØJiê«r«¼¾ß9µß%û×®ÊJó\½P%üp±øÍâÊjÖm^;xY¸xƦJl_î´OÔgÒèC‹ P©íþèbScj7‘î•î¶ Ô›”ÿԩ檌¿´  Þ‡ÌFå·}l%›ƒ^ó¯n›/@Ssš:!uŸÝOZüÆb½ZYÜ=QUIKÙÁí1d“‰žÙxó5˜ˆü0Bþ8ÉÓÍÙzk7¶&Ú"Ÿ¾t~Uÿþ×Jéendstream endobj 653 0 obj 2055 endobj 657 0 obj <> stream xœµUYoÔ0~ϯȣƒcï¤z€8— „(ew[*ué±­Zþ=3Nb{»‘PØ(ŽýyÎoÆÞëZpY z†ï|U=Ÿ¹úl]‰ú߳꺒Q >óU½×¡DxAÖÝiÕkËÚAm½æ¸Ù­ªïL6†AÿþèÞ –’¥–<ÈP³[ ô˦UÜy);j€íâû±i%×Z[Öõ› 5ÛïAã€ÍU‚ûà¢//Ç]€ÀA²ÏMkH;ö¥‘<¯{×(n­qn˜)£¢«YãŽö¿¡Q#ØòÖ²œ‚¥ŠŽ†ÞRiª.¼AQ Ó9ëØkÚ÷øSeðEL…ù ˜s …ä±Òž2¦|…–µèK)P0˜ R8ö>轺ä#Ê’ƒFJ±˜•2#ÿÅ”6) '=Æ\ƒQî5š+@Q4§iS¶ä+ ™1¢]Œ‘ÚA l«_„8¸'û®Ñ¾ìšV S·XuG½u©>Ñ;¤a—œ !)N\R^ì˜ÑxKÃ) ç4,i¸HÒ Z®iØ„¨ô6ªô2—¼Ià*ƒ; \gð*''f¤có„-7´µÑì€ †  '…çû^dp™ÀßSáܦÙϼ=Ÿ²ž ÙÉàzÂÐIÞÎàÝ”Îq“P*)6±/‰·U÷l«|]R;¢å«Gå‹E[ÑpµY¾“MâÒ™HbÁç|*úLòbŠº_\LÐðgªÐË´Ä‹Ùä¸}7¥C,ö(‘¸ÉÝ„ìkÒš%6{æ(Cª±Š½I‹G ù˜‹¤Y.¤‰o1õÀ› ^&ð~ªøhÓˆð{™‘¢“ÏJj·¹¡À-« ‚t·[rõüÝL%6XÒÊ“¥âŒ‘ŒÓóx*À{Ù×áæ.ÎN åê6!’ŽåýOY?н?,q÷a¬qpñßjãToÓñ´†ÜïªOøüör·ðendstream endobj 658 0 obj 720 endobj 662 0 obj <> stream xœÝ[YÛF~ò#ô¶d0bؼļ¶7qÝÍN”'':F3Z벤±3þõÛwU³‹¢†’`a˜¦›}×WU_U·> ㈠cñGÿ;[¾¹-‡÷‡A<üÿ½|0Ya¨ÿ™­‡óJÕ0‰£¢HŠáx1PÙ°L†y™ÇëÁ»àU8Š£¼ÈʪÂQ% KÓ`ÆQ]ÄE\;]Z'Á1dQÔYÜ…¼,ÍsìÃQZQ0ÑS•–eRØw–ŒRóÈ¢²*™˜GžGYZWÃñσñ×ï‚_¤Œª8.ù¨¼«2Æ'³ïYRÕYᔯÃ‹ŠºÊs> ^šf¯!fVV5+taZ穚Z%¼ç×¼4O 5uQ!©‹*øŠ¿f+2läk\äE° fe]ê^«¢De[±3¬¨kÜä '•%µZmVq9Du\«åÖ+âÄ,—/&åmùãI<á(ç2ËÉ×à÷@”¯Äc+÷üÁ¿3&f‘3ñ˜Ø*¿‡á(«Ë¨®J1”¯?޼+VGu-_eGr–cÛÝ­XT]ó¿ÙÂ70Ÿ¥-4“d™Yn ù ·¥má4ºƒF{ûý¾C£G(ÜSÃßÙÂ9ï“cvn &TYKÎì#Us¥^³´ÂC£©B!è´(¢‚kÔx>x‡›ïÝ5ÆÿO{BSŸÃP¨ÿ¼.½fºsû*æ4R“±4Ês¡cznjÕc¢Á§f–JÜ¥±|UØs ªv*—{ª¾͛ڸ£ÅòNãOˆ@ÂðO˜æŒñw"â°›Q`áöTáŒóÕFéK%ÊéN÷"ìne €§Œ¿ÁÔ>µÌ c{‚ï[P•© Y*æ'Ç-g\ÄÝ9a1ýÝ:‹2]}"º„ŽÎ ô#F ð© JôI“'æ)öF™®£ÉR£ÃÈ܃àÒBЕ§´†êmß4€Ý%‰=ØøŽÔíOªÑÊ~ ³¯lá @‚ÙšßÀ˜©ýž¸ß¹òŒì·¾%Î( c€°ÁЈ:3…BR\@ØO­;ÕÂ@ô‘ÎG×o=â†f (<´Yw½îÖB¢Ð“kl}‰.(Ùo#27kÉ{áåxYâɼ,©“&äž*Ô"«£41b×¥êkÏ„4ê»W¥-öЙk.³ fE˜…/€¹¯Å£ôqSÏi¡>ÏEg×€WÞ/=CX® =m/ž=…²4¢ÜÐÐòמ˜jò$¿ži䥊?Kœ}Ö˜2Æë*0ÑÈ4S·C!Øî©³(D¶ìhƤ·XTP€[¹tWítIñÕ=Ôœº€­ &¸(ÄÒÞŸ†þ½R¥š®^ÊÃβ6ÐsYÏG‹CRrz’5È1’çüG ÿN…ejÔÔ tÈõ—Ï”°¾ƒž"0— úÁòî]ÁT+~tÄÕK†Ær(q:ËGA%·!¥SJPÏÁªÕlÅdhiŠ–"Õ10’Á)±ú#>C¸@׺T>¶…Bö¦”Sk'ŸoðÒ±äd ý1$ôw›û ٺіè)p|Qˆ ‰Ü˜‘ã? ô-¼ŽAŽ¿’þí0`]WH×%§-Š×°Ù²Ì„x÷Öƒ7%s”+i]sR ×Ýâ6œŒ:‘þn°dŒ`IïØKŸ¯(›t©>Ðä©·ÔÌh%œ;@ÅF6/£D„®•ZY5òWw'‚À¹:pª)n)ÕNÇo e‘%†ˆ¿LDwp^vlFI}EiêêðƒáO-{ov¤+Êér;J 0ç5µ:Š‚•Æÿr6UXæ×‡‹${2DÊJ6U¶èŠÙ§gœUEBx€1{å1ÏÈ;jsA KjN7àeIòþ¬Ôd¬eýìnÙöDÖ© -Å™ú˜vkâgjà϶T\´íPO“¯ºõërýQªÅè·¦õôÚìw£”emI±Ÿ0Ö6 ¹Õ‘iãê"˜æ½7y4!«=˜ºvUºéÌê2“[g¨u³*äî<èêþnÎ=ó-ä…K[ ñVž!šx}:Ä ‘öO§‘tìP]ëéꂨàÐÞ6 Š½•Lîô“ÕÖ•~˜…¨éïqÇmÜûõic‰ ÿpNŸ ±é}'ÞƒW3.ÝB’:©B’ƒš´kÁ (’5“ˆÔ +6I'„/Ö?2! Z˜#Ûtè™Íš[ p {2€6¼ËÚ¸‚ª/Ú¡bIï™U†UhXÁDï¹ãÍ.Ü|œ†‘Ž^Ù>P4ô<>,ÁwðíÅWHáB¨ñH¹qö´m#x¯G᜞SWáàí ×sK̘rqvPß8ì)+D~öþ•\BY…‘båÆîì‡ þj@|™>ÀœTíñ`y;j#Úbø ­…Xל@öñ`´Á$Çœ¡˜‹zçÂÂ]..œtŽFŽ-úÄ«{2Á62pz@ÐÛLÐé/`=º5¡¶ï© †´9:ô&“¤ïÚRh\;ÃÓÑ…ü/©F+gx‚ÞÚ]s¼}Ùöâ‹ç&HyÅù?Ùøè À½…ù•ÝšuŠ ÍQXïÜcðã t!¥c3‘M²u¤6k6µ#z2Ò+/ë¸ï@ââê% Z|†;}´gì©8º¾âæ^è°YÔH»:öQvNDÒ ì@ÊWg£ˆGkjçag‘Ÿ_JÆÃ]ìèzľ#nëÂï 7')2i+(wlŽs‹•ï¢VÛd½µê=·¦Ö¹×zœÜÓ/ŠÀÍa­¶âT”@îu›µ>E [€ÐaÐÝ¡öÿí€ÔîÏx!>‚ ¿Ú·pšl³Ùÿ‚Š7À›Pó1¼¾Òh&3wnö^o¡Ù+§ÆyH-nˆ¡R1¿Ø•Ø1ÕÍàñø9TQ&ª)Ý4ø'ŒýÆVºm,¿yÙq¾®( µ½µ…hŸHظGC®þȨnj| ›uG‘Ák8½õo¢ªUkW•RÍôqþ!úŽR)¿îª­!‹ÔââŒÃ¿°MßaÓ7ý`‡À¼ÌíÞ|6hûsX öDpU¸q¢Ø†×@æç”À` wcîÚVN\Þ¸ ÞãÅáÁ½’ þù¾¿¶…¿yé«¢‘<IÂiËɬ$ím ­;Î5¦ßzU ‹”ë'nµ]††›7îj‡Åw. …žÈ_ð¢#Ží÷×ðÝŸq‡ч¹±YͰ®OP!ÕO’àBSÊj‘§Ù35‹îäïÉ ¤kÿAçÚè„/”§ «¨&y} Ýñ|N‚Í»ëˆ*È ¹–Ùxx¿TGƲ~ò¥õÒ"‰š÷WŽF?Ùîç_48ÿ7ÝßF{;î2!Èñ¾sòãÓÒV Y•’B’·f Ïe\×ú`;R¬³Š˜ýÙÐʘµ™iþ^ÀDeòÇä|"/ðÙX¼¨d³È £¬•¢†Ì !U÷ÏRq2$Yâ9¶Eâ‘gœßŸú±YìÀU"&:¦ ƒUDØðËÓX'3§}ÓgVuË}é;ýÁ+m¤*é‰BE·™÷K0ÊŠ4 Òp½{¤öùö_!'CÞ’v­ˆF ƒüÍ%†§Î{®™h0ë¸8ubBÖÌØ}6¼ ±µl¹œ<ŸXœåËÐÅ%|äÏÇlÊ$;×ѿ"¼âáÁ5Ã+ŸÐ§}¤…è8+Ò|»_ñ¥y”q[q†~ô¡À“`à>ól Áä›[–àßLK¢$fÃ7 *~ò0çV ç6!­ÞŒÿáþ%uJœendstream endobj 663 0 obj 2896 endobj 667 0 obj <> stream xœí\ësÛ¸ÿî¿Âß"ÝX _¢Èd<4O_“\›83ÍôúÁ‘lÙIv$Ëvî¯/û–¢^i:mïætò’Ýß>±Ô·Ã8Jcý¯ýÿpzðøÃàp¼8ˆ_«ÿÆßsáýßpzøçSuS’*JTÅUrxzqPNéaQ摺x:=øG'éö;©ú/ïöÿyú«•%tTšVQQª§#uóón/‹ƒªJ:oºITUe^užuÓÎ_»½$Êóþ íœâ=/kj–—Šš©iÍóô‘º¦'O5¸,¢~^öÕTnRu•U<ˆ ó€wÝ,*Š$ss’' Š¥öãçÝ<*ËAQ‘˯ºnȉ¦•U–%÷êõŸêŸÌÎ[¦INoúMSÓ¤LJsÿÇn¯¯Ö1HÊšmyIÙÖ³|ë©¥ ’ªªÙ7RStÎôÇ­þ8× øs®žgƒNOÍœÆß;Áå,Šã$é\é?gúc¬?~ïªq¥¶¦þ8ÑzfqÅj#ªžj—…™´&ž#ñ1o‘xÄ)“Wƒ¨RB[HcØjqÄ1Ÿèu–j¦Aç\ÿŒ×?¯&öøˆï¤Ë/€ø‰§@¼Dâ%Ÿtµt³,ŠÜ)Áo´_ó¬ÔÛpÔ…ø5Â{GH•¿>ê*ÖVYUvŽ€¨ÒK‹J¯¤—dQ¿ˆÓzAšm†#ø Ë42ÃúÃü9‚d¹zR^^úk Î  ˆðN¾fK|̸‚x ‘õ~Ã[¢Ùf‘Õ[ìW¥¯9jL?©4w¸¢ R0`[9wä´Åìs¨ K¸4çÝdçU&kYríB³D}§ZFðu^+,òéZÒ‘[š; û·§¿XÖ|ÑýqœšØÆµIÑFQ­²æ–tí¶_?ç8ÇMßw O†Ü-,çÝ:‘3$jŽçU©éš3ˆ,wÇ’yjš?Æt#]ŸSÞ\+Þp±Y°7ŠÍÊú«d<Ø÷Ò’çLmœÍ»«-Lž7Ë·ä¬Æ’­„Z;ZPZ-¯)‡ŸÆáÖzT{€A}ûÒ=ÐDVK̉…¤¨-#‰­C ÓFùkÜæDþ“ áê¸:Üû5®î ]CÊHZºÄ¶:Ñ~àBªÔ!a Z]äæÄÅ› ´wìÀç–Û ßÀ,$.üðk[u»¦ŸSÁ³a©Å‹’aLhsÉLWhu\Ô³Õ>øB–Fðý~róáÚVT)uà˜–‰‰ø‚†ƒpŸC﫾W„f=³>ÁÆ ôÒÿBè-$À )6Bpu?„.°ßjG /ò<ÜØí7‚É2„ 2î6©_"‚fPYT¶qhw›î¼û½4NÏCÑ—Ë® Ìsé ÚÁ˜°›3 ì„bŽI0¶€€;χÜ+¶r¤zÔˆœõL‚³{ìPcä¼ \æêÎ5úåerʽU~²@+±‘œ‘Bƒñ°v,H|3áG58ÄÓ”{IäìÂaUL!y,€¡ ÃI¿jÉÄæŒ»\ðºdT<Þ°?…ê‹îñ aЀYÿ­=ïÜÎ)ºB¿ Ú3¸;˜$ÅΉÄN:­*®´Û C›Ðój²I¬&‹ØCCBÄŽ±+AÉç-×låh„0û#sÎ4ÀÁ`ÎÖFTˆ!ÂÎÔ ó-é}çs0—8³¦Ö‡’ä-PEŤ¹¸IŽ8¨W—¥Ó7OW]‘e«êõ$?«PÎ[¼"B©%¼ /Øáœ벌=¡(â¨Ì„<ãkç%ù)8ké{— ›äÀkóúñy½*^ b±8Æ7­Ðîů5:}/Ði9£×0x–ÏŸ×7(b>µIý™ùÿdWŒÝˆå™î¥1m…B#Ô§¹^úÚVVž>€d'/Ò½P¿Í( Ïóº7Ö$ýj·‡ÂÀh XÙK–H “® `eMÀµqóÂK¸öw¼†Ý4ï‘ø ˆïøƒ´RÊ$6ãUd&ô–©2 cn/–Òr'(ECT ípg×ö\ iEØùÐìÎwŰÆè=žyÀ4q§Z´=“P\Ìo¶…E¢cCµµxÐ{ 7W”9‚‡S1Wü¼LàÛtE®´waÚÝH|¸5Ápt«Q˜HœJD¡Zk:^„å %ipaZ-+ùXz¨h/Xìú—Ös¬gHýˆ_Ÿ£i Ç'XÏ ëeÉNé'â‰/vÆÅÂùn\®80%‡SíÓÙ¬Qxsª5ÜÌ+¸FØŠnæ#j~{”M,3è0K1¼î9¹Aj½ðPÛ45Åm¸.%6®_=k-‰‘UBC]ÏÄÅ#œ–nã3ÜÆ&6ÅÕõc¬€Iæ%ó²—N,٢ɦ0·¡ƒzÌÄ{ý-»B^d&AØóàÚ¹÷Úî`ƈŠ9üAÖ“ÈÃIÙ‹[•ŽxÔP„ÝwÆ™ŒIW7vO6ÀîéoðÎaƒÌ'–Ú’ØÖd%Ä—å‰{Ä2”r&kdê–Bï–å Ø,wÀ¹×O¾u{·eÝñ°Ë­Ü¶Gºrwéé2´ðÓLJ¨[2©º¬¥;¹­´x+tŠ ¥©²éHJކHvÃjÙîUH²Å@º¹‡Áh`ö¸YÕľ "Ň­¿Yè "|;×ígÑL3<)¶I2å`Í6PÃê=*›X%Ú¡<¾• ŧ>“Vv‰ Å ›aœð†¨—}O¯ƒ×·9CöVƒø—\§lý±â(ÕK÷ɶî¥2ÎVÎdÜ‘††<<RãÛ–×â|xú'ÀjÐ\•è¶~¢fö= ºÒý )†›;›PèP¶“@Ô+²ƒ™ÄæÍD¿CLààüŸ"r´)Ηċ»fÿFÙÞ´ô”ÛÈnHXRïÕ™zÙ²—ªÂ; ›Gb¯áús¼þ?!ñ=Oqs?¤¢¼” BˆM9 ËnŒT›% 1z­Õc®ÕKëåÿ‡£ôõË […æDâÇxCÜ’{λÔ9᳂ì‘TÈ«Éc6YªÞ0®ÌÖV9ßäÌ*4'ÂË&Znl«ß£9¹„Kgî‘Ï%›,Ö‘Å"9÷moÐwD÷†ºrÈ=¸N4ø˜N^¬m‰G°OuGLZDqJ (ÇLœ–xÓ²dú.Rø~©œÓÉY!©ELD` ƒaúÞ§Wi–»ÓyV¢¥| ò¾‘v×°'÷í)¦º©Ä1јðn= ±…¯Íá!(9ï|×wwD˜ä)h”ÀC¨â r.ÁI|ݳ¸-pk.‘¸òf&?´ð ¯‹@bŸ˜$²¾JT§Pº<'2]ºq";oœ³éÍàÐ÷_H‘WÐeO’ÑdËPe µÔkåM«T¿ÃUhB¯c;+åcW‰-ëß{HœH3ó»+ö}›—Öå‡9³Ø8@”åռƉ'mj…/‘R,ê‰ ÿÄ j–øO%öÊ üØ‘Ö.Vö¥“¶\z™ÿ-´_UÐÞqäI m˜M6bߦ+øÏú…|Ë!í oÞ{= qEê ¾îÚ±}N:,äØpé·¸rVí mµ$4,ÈæZ,JaZ=·…Vë1Cž{WMàtMzDçØñÌð‰‘þ$…I.›ÂÉ­k”‹a¤ÚÔÕÛä±,ñ Ú³¸ë¿õ†a‹Ø\»ÍÂ;ÉËÂâuñTÀ b[¤áå„Z@7û°^3«ê¾¡´¬=×(¤Q 5Êo DðHá[i Ñbˆ} Èàï]!9X£Zg‰GÌšbšà„BV‡’žyB­Z£§ö¼ee/”|þ… ;²{6Ìµß²Õ )ƒwöÓÂzÝà× Õ߬Ân+kE¯' æXfrD,H}@âgÔçý…->læ+׫¾Ÿ÷“/YpðÚÇñAÓÔ%¸C¦MûLÂÌ 3¶¯|~e"Ú eÌÌŸÐ$yö&a$ª¢n6-O¥w i×V¤öâ¶ÅÎô•pe)ˆ¿C‚ÆÿåéÁßÔ¿ÿÏè³´endstream endobj 668 0 obj 3755 endobj 672 0 obj <> stream xœí\ëÛÆÿ~…>J©¥"©#?EÛ8M‚4NchÚÅYÒÖËÔ=û×—KÃÇQT!#aYrÉÝ™ßîÍÇÖ|ä´»Ñ8ò’‰ç]ÇÙ×lP’Ã_‡xÃÖÞd÷øþpeþ{c>òo©ùøu4‡Éå$‰/‡†pe>Öð6yqöôi>‚x§ÞÄóÃ|LAÜšyøÙ÷ž§Ùà8æÄWH\ÒŠ¾Câ—tç›ìºŸäËT‹DàM6»-ïéÎ ßkI‘hää“hæe2üábþ…ˆ&‹8ŸY/²X£ÐoàÅÀ…Ìym_œiÁ#°Œ¹Y²¹Ò¤x@⎈ $ÞñŠO‰ø——† ±!µá4è YÙä.lüvdd„¹vz…Ží‹ËasŽÜÙñq8ü†¨ßÑ×9 {Ks¹Üg‚‚{Ùb_Ñ+|¢Žék@Ã<¢zŸc»˜±j”ÄÅš>"ºžÍÇ…»žíÆ/}rì1]ÁÄ $‹È|ò$i LaRŽ>WKh"7$Ñö8ô‘h8¶PµšMýhqšLÂpÊ8úLÀx$êN,T¨T&¬„WB$ð¬ÊH¼å“£aTð¶Æÿn?fÉfµ€œþL¥„I°ZXj:ŠE÷3¥,wR¸¸Â^ÓD¯4̯Ïã)q8E±ã.¨°Ùr,O–é3¼)ºúÊ¥ÌÝL1ý¾Ä]ó'‡‘¢S¤h·Â9\k®#%–Ÿ^$…v„G‹ä€|]Ú&ääk@^xÂ-XÖ|6ƺ+N½Õ=žÙ©ö¤E…”)öc¡<‰,/½ˆ†€ø"°½éJ z­DÒ°>9)!·`¤¹ÈlØ_ˆú-}}‡V¶µÓ&×ú„È9XíÕˆ¾^îzU¨ÑOšØT]c%Î š`+xÌà⩌T9Z‘¶)]sZgÊ/BG”ÍìÑü‘V[ŸKŽkO×÷Ú›vÚ¹–AhIá÷ÂÜ~×Ü©ŸµÉ¡*ØL2 Œ®ÿ y’¤ý 58åó±ÉãN;¬­èImÀzzK–R€Ï”ɺ!úÅÒòI¥ÀÝNÔÍ [GØÆ7š›ºÁÆ1ñßæ#Æ›s?_憡9@‚˜°ªRf©/)š5®Ô&%#k,¬±€E-iã#Ó¸ri$ÕPv%– ñŠÊªµæ“ÄD]ï¥×…*®» 7¹í-©Á9¦Ã]e¤en5Sà–h‚x2E‡zC ¼Ø(lVXãqs6Ïx$£G{²JPúZRèç’¾s•Á\0³þVO¨eµæ½]øÖK˜'g“1]k@¹”9n5QPÖD$Ÿ³Ô€RT|H˜dž4 ±&µ‘Ãz®•¶†_8¬a©ÂaS_u٠ƔƗê'ÛD4“¾ASsÇmue-¹Í’±ýÒŽ© î¦ô¦ŽÙ¼"o4a eöf‰trlâÑÓ2ë|Í›ž ™âɃR¥Ôë,›9ÿþÓ³SqêG¼þ'ºþ$¾&â[$¾".Α8§;AâOD|]?œ•Ëß(ÉÑÏtùoT/l²Ífò޾þH'ëñ°QÕÍ–3ñVç_%<æ…u7o7f­ƒ]—ˆ”¯r€Cú%Sw·ÂØ_jßgèoxDÌØÑKÚKÔØÊ5íEA‘&áÂPÐ dÙ=šèUÏFGy‘c|W 2‘°–ø3ÖuÇ br÷Ä£ñlu^OddA!8êàA­3ë®J£”ÃVë¬l4Nl5F³"b'ûûŠe®aWÆRïb-%/×vÃî-{ÄbÚÒXn¥G\!êŽR|( µÏ¾[DWuÕ‰¹ƒ®f­Ú>33Í‘c¡hQ7|ƒ×e@d‰oiòU¡ rª€²œîæ·±œY›`=¢S¶K5)Ø«(‚ºÉïø@|UÄMw[@¥MEDKwKý¬^#„º­Ò 1¼=äDn\X­^T 1óß/Rp7P®W'*”‡#½†½J{ˆѪA‰/ë!¼Öœj²d$q´j?SOÛ[n§´­}| …tÌx¥ínÔË¢,ô¹‰ýMìjF©–¶I¯—Tfí"üóvÜT¦®~ð ÿŸšð«‚sµ<ñ›Òù÷(KÖÎut¦ØÑ[ÎÑíj·%c|§@HuÚ­%lÊ©V©Ô^‘RºádJÃG å’Ý4N8j¹µ[ÈáгÒöÑy¶ÐD¢F)jê/'ëŒaAÕ‘bu´2 ’@½ó^pÄy’+º¼n#6Ï#Vý¢ºc¼Ñ8†¾V¬˜v>W8¯•XniW[sOI5'DÜhÄm…±ƒ2ˆÄ¶µ•-°í8©–&Èx–»ÚÝP'Ï“!E;S}ZŽª°¬öÜN± ò¹C¡HøQØ1ži ORB\VOÖöùÑ,ÊæÒA·}o:;Ò¼µîòÎÍò1Eg)‹!ú$Ú×È"ß*Æ—Gtl·a#ÀÁÒ@ÇW`y}~â(c½ÒÀ˜Ë!@–V"½ÅW ØÂHì8Óh?®T#9…ª7Éø[¼þ5]G×åNO­˜šõUÁTyȈ©_©n+yÿÛQ».íI}ªðÑF݃åî|UÀc)—…¨a«¬| Š!úWc“±†r<0Y«=lê!9¿¢®áÚL’{ÈÙl2óÐCÊHÜ¢l…dõ$§¢ðíÎ@›Œ±ï.uûV=0  $ä`UëF¬éMÝ].·Nv\ôÂú3€çÜŠÕ0£ Ðx¯b’± ” »aŠ7)ØÉaSÙítÄÞnÑÙs ž—{ìSœNPCîªôÉñ¼å¡“GSËן´hGXî#„;ê«„îÑLKäòfª0mÎÊuÝh2ØiœÙSTAýÆêÉð¦øäÿV:¾n(bÕø‘ëíy2嬂ÐZY ÒIƒÔ³[4E-9oà]Ï òÜuÏ¥«3gî=ç¦s¤Q0·öL[®Þ…~òŽwjÛÛ5g­bÈ–Cü_6¸ÏT·¶üNRyxú‹ŽB¸¹Ë+ÚÀê”;è@]‡&ÛË$q»lK?þ¢Ú) ü©<^W¾÷èSuÅ k«Sw°%~Ø7G5âKÕ<Å9 ­6-.µç­4„°Óõ,À•/4 ?k³Tc]Þpu’‚ʵR”–û þµŠVÿ±š&ÓåÒÆêCeµÇ¸¿¦ç¾+CP)—ÃñkûA§þïFý¦fy=íA¸¢¸[Hʵ_ªu,*W'iÇÝS=R ¡:mòVvùب°ªT_J«ô(;Š&Á”†D'ØÙú'$Žé¼+¦"\Äx ÓÑÈéAL³ùP[(^?«/k¦;[†Ò½;]+ùCm „ÀÆã²ý °ÜL{ݹG%„J×ñ·‹â@øJKsº¶¸¿_"QAõÞ™HUyUmTmèm‡æMð]ªb#Ðï?eèðûl~ÊP0+xÆ(èžß)¬M¾ú¨Ý¯ZF·ùUC¸·ïŸ2Ü£¶—Ûw|Ôù'P›„ö^gã$Ê“­–8§ÅõguXȯ!þ^÷Zœ\º 잤Ü*æ"5vÓî‚ï(’g_§Ôò1ì§ŒÈ@ì¤8[ôŸ„º¸Nb=ªoôøŠˆj+Õ^0Ñi>[»ïL= §Ù?ýtß)v:¡ªí¦,6×E=ØÝ/o‡ÊO¥aÀß"¢•Ôd½l£ u{Á¯©š©¾ž_ü=ûó?!Eþrendstream endobj 673 0 obj 3073 endobj 677 0 obj <> stream xœå\ÛrÛÈ}×W(O"·L, à-?øšµc¯[©JU6µE‰Ųx1IIæ~}Ìt7æ )Xr%»e æÒ}ú:=úzÜ÷üã~öñ÷ùìèçOÃãÉú¨üWõgrôõÈÏ;ÏŽ_œªN~ Z¼´Ÿúǧ—GúkÿxÇÉÀS/OgGÿîøÝ¨¨?q7úÏé;õUèó¯‚ õâD}x:V_v{¡7¦©ßùµë{iš ÒÎónÐù{·ç{ƒA4 :§Ôçµn Iç“j Õ°ù|ÙO½Ë|õq{Ñ ‰ÔPfPÕ¿ï%iØó >tC/ŽýÐŒÉfÆÃ¢5êv¢þ óª;ð’d§ìõ›®ùämÖ–¤aèw~SèªÿÂbÜ$ð¼ÓǬ5ð?Éûîö"µŽ¡Ÿh² N¶^A·žZÊÐOSM¾•¢s‘ýXÚ§Qöc£ë§^¿?ìôÔc¶þ4ìüÞÉÞM³ó¢W¨úø¾þrbÇÈÇý½Ûí Ò¡—&Ãε}57=õ‡jˆ £pw®hÎ…}©ƒ¾×W[¿°×ô5ÎPãœó-%ùjnùºÍûs´&ZÈŠV—“ÁùÞ³јOšÆÌû€Þ¿³µLë/ê+?Í—:E£Îù3n‡ƒÐ³2±„0c³ý0£)ÛŸy\™¥fø¶­Ÿéñ¥~„I†BÓúÖ¬uÀé6¢Ç3úì­,[Oo ç‡^÷Î…Ac6‡‚`/ÇCıíqcÉt–ýÓÀMï8Öè&°«s,¯-ª¡¼IÖ‹ugô¼Fk„!báˆ#X‹FÄF_TàŽ±–Í°àŒ¾t6ÛX¡‰6üs·qŠ–4ÏEÍÇð8Ñx /°€”l× r²•€‘Áe"À 0Íú®©•I’Æ–^L®(MÊàºã€ ‹ÍýXšoD ü:«ÐŒFõ@ÎßÙÆ'ÅL}®næ4=!ôJH¸‹Pj¼b4q0tX â)DÎ_ ž’S××ß>£]­Ð´,æd _Þ¥ÿ–{&Nñi¢BvŸïªÅ©õáBëÄÉÐ¥ìÄ…Ú‹„ÆR¯-§Î-ßçóý(Žv 5“…,ƒ¡’ ]$…S„Þ+¤ÐX¬1CŸCÃ,° R}3†ø˜¿wS)5¦‡|ÃÝšA)tÝ:7G™M¦–B®X¸m_Z‚hó/Ô× ™ghí1âköã‹·EËz&7WFÅúyÝ÷fÀ„2Ò1Wr¨óW«óI,ßêbŸqÕ˜;:_ÐðÌŸf*ˆ¢‰(I3–)[ñÊh6dq¡G‚’®ëgñ¥æøšZ;¶t Â×µÕn”]˜ZÅ5²]8¾H#^Þ‡±cM„~cß³,à©müLÁÈ%ÒiÂÊ›ž0FØ Kל5D "ïÆb¶T¹eå¡Um×p•íw Â7'š}„•ƒÍŠú²娕E ‘°ˆäÍS"#ñLþT€çÜ*¸¸97ZËQS:¡q+vS"ŸöTÈæJ…Í$¿  ”|èf,.ê'"@mÈ­¹á¯k}/ç9ïI2£ÓIÉ€ —Nœ*ºZðXß:*M©=Ø;Q_ØÍû$êõÖZJÐ\Ô`®í5l Ma" &°¿PvŒÌí}t^¼Z3ƒó ŒÆiø;´idM²¤ 0®ÖÊ#ÕBÈùLúÀg£$LuÚŽânJ°m\—½0¨j5&dÊÛUCbç÷I›âLmK©ˆeÚïšÐ½’käWœl )êG»«ƒ2[Ð44Á Êcu¥ºê4ÐHu›qAæóTÅ$ïΡ3JFâŒï 3o9š¡¤$¶µø2¢”~µ{”\ÂØÆÚ¦®[QtÆlçp7GìÓÞ`’ è Ùª »àƒk« >.á"…R¦¡ð°‹ŒÐGûîo’AºÕùœ^Ø^XûN‘ψ¿$Ãl¤|×äªù.]/®œ‡Á,`×iœ4¸ PÅÎê—ÃLÅÚ"Sþ¶öD¢È÷% i+ŽQæÔWºKÆA–ª„?•G.Ò+Õ‹­’zËQ°J©?SYJ+RŽ‘‘v‰d[4àšQ¶ƒËnf¨ nÓëZ[èSB)®¦(L%pßÔ*õc1÷+êù‘ÿ ãó-œ%ÚÇbJô5›é5=~r‹™Êv(®6D+ib&ß ’_ßÇŸ@|"’éQZÎŒœŠ}ÌZ[ðj>å0;³¨[ ¸g oÖXWŠ‚è®ÀÝÌ8Å38Ý3ßýpáA›Q"Íi}:qÙ%YæÄIq鄾dúK™–Âä ÐáKqØGñýÆ*’åe úî—Ú|cnBR—sò˜ÜÍA³óqüaò°¢¦  º%Û[å&€AA[NDUõ-EŒ­¥‡*¿Ý¢Š;jì~ÂzÔè~9tâÞÙY'œhâhQ6¸ûiŒ%ài?TœÐÍ<Õµ%TI]MoNv*и°ÌꢵL’›ŒÞßh@£@ŸKõéFì,—âã~/44ÊdD‡¥÷*Beü´¾Å¥Tº³µ»qñö-¾¼§f=Èa8пáF2×tøE’ÃáÎ5šŸ*\p2ámnN¯¤ÎeY”ɺ'¡%çâ©TAxý²î<ӨϳçÏÙìÚX¦ðHõéË‘ F¼nm$XEøjŸá±þÎäÝaÏ™ÔÆ%©Þvm™»ä«:%ŒWF"ûÒŸÞÿ«áý‹†÷oÞ¿kxÿ|÷÷°VŸz¾vGJR.R¯š:¼lêðÁaìUÌ%‰ ŸdoòŽùÓ3©c«Á¯È*µ~5XÚ'¤ÁOPã3dS™Úô8±ÕÃZƒs´d˜÷% µFX`®•X½Ñ¤Ï`™ 4}©FÁ†7UiZáÑßÐPòb¦tíòá¥k÷›UƦór%v¶kïB$¸„ŽøÆv Uó …âÍ.€{jM†° Æ ýà)Î!¦ÆtTB@ÿVm@—Ð4Nùâ™GXàk#mòª•Ùƒ‚ýFUd†6ÙÉQ~UZÏðTÅ«I¶FiÐz´m°N§àm ’õ:„IVî'9]ƒAN³L! íaf†‡W!H?@UÀTÚ–°WUЬ0²”4j`;Èø¾h4öGNk2q~{HÍ<§˜"&ÎÉc£÷ÄèœC)£)ÉgÊU`ä{åÂP¡Ì ‚Ôå¾9¼þS¾Z*Á k,ÙF$P0¸E´gÍÂXºü„~MqWƒ~]UÀÁeN´àôÇwá&ÀØÖ$Y ±ÙF…j<2WÍ[3w)!–ELåü*šØU#ê¶èbRöa™Í…åk“z3œ ðý±KX(â&—鈫ô®™ß"3±Ç-ì1úT«ö(í=D¸5R®óþCÖóµñãÔórÿ ÀͤH˜ý< /ãÒ5F& Ìè^•½è¼ºr%ð%¦Tñ%yÁ&òþ——°WÀÑ­$o̸a‡îqÉJÍeŽ?ÿ±-\ úRó‡ÊÃ3hø®»qåAétS øsÇUUkKOc=*yò]j9ܰ²ÚɹÀ£KHèéN(‹x‰X²Ã¯ŽRº±’ÛÊ‘|N‹s—«±§…H<ºD‘ ¾š¥.EQÅ]ã®Bm<åÜs﮵!šNIG«¢)8 ‚¸ÿE9ü©VQ$m8 Káð›GÒÌæñÆz‡Ã45–»¾Þ!ë(=6W’ý~˜Ý·nñ×YÙ»¦¥ŒTÉk31ÿîRwÏâ,B’Œ­]ªÃüº xt ÇÍ—ýY~´6}C­¢Ã½%/Ö·Œ°²4 /¸b·&zÔ9¤Ö>|4Ö¿öò•‹;*¹h¿8Kæ”mï2M3Z¹û\wýb÷bý~£dѨ¾ ¹ùIÉ`°±! þoÕ¿~06î©ß“Ò5æiî rV]<ªó‘ råkSƒ‘¶âTÎ6¢¬í=“µÒ’á¯~X!.+hí.^èesgç¼Ú…™ú Ä8ÄH*Ü”o­¶ŒÜ)ãÊÕÞìlN¨uukIɰ[Ê0yy'¼#ÎE(¹ç¯FÄ¿Faìèˆìhc™ëPºÝ$±k©zÍæÈ¬ç²Òsã£ö—½> stream xœíWKoÛ0 ¾ûWøh°çgl÷( »lðaC»Cê$^€¼j7]ü劉%J5Ó.sW8@DQ(R”Èyg~hìÓý–këí·Ì®+°?ÑoeÝY!g°»Ÿrm¿/(SQŠOÚÅÂÒ¡F±?ÉíIžø”¡X[×Nè¦ND¿™›þ,>SÉ$×%½$ ™ˆ~b3*ôÛõbgɆîÙðËõÒ ÷ ‰N)?›Þ8Šu#Yý CgÎþVl೚ 7®ë%$óIža:„ ¦h«ˆ ¦2¤ó‰ÉQ¾<Ÿ0iH¸P‰­O±Æˆ%Í(qìÔiñdjE\q£ˆ»¡óŒÝ£Ï ŠV@œI"s[ûé$ .ýbo®³»'·“J£€ïïñé·pö=Öl¸5k¸É@ßla}¥ˆ{ ®q:Qñ æ‘éÓYê»ËåŠY!gägïñ]˜=¦6¼)§K—y4Nu)ZpÝ)’8g'× ¨éæ"Äy0n©Qî°7Ää´QS¦Þëô{ Y)ÉÅ1&jÊ#¸š)äíÕ]o; r\ñø¥:w bs‰X°?%1Ûv*åY …+:SƒCº)%±£žä”§@2Å€5‡“¡ *1EàkŒh X&C;¿[˜h‰Fóì¢Ïý ´å…ƒ†¸Ò„8‹5ªjg˜YN 67À'RvÄ‚€~r•ég”üžJw ”;…•ÃY‚r‡Aí€ySÙ2Ñ㘙)úÛoûcVVÈNݲ9K›–GÌ×'¢öÒíú âïÕÒ7uïýk0âTDzLé+ãî2ÈZÈÎ7X|gZ¿d9¯â$H¼Öý =V<þõòò ¤I»å,•Hû§Ü€´µ:Il¥³³£ å¾hÎh+ÐÌ -$@6@щ#¥wÞ¦ƒÏ¯–!0·¢UóˆV?> stream xœMP¹N1 íó)“bLì\v¹ÀrI\K:Dµ+¶šbÅÿK8sÀIJ¬<¿#ÊÅ@z-ó8š«Cµçì½öÙ\ N»Œãh¯›’ ‚¶}›Y¶’-œ@—m4Ÿ}v¤Í>µ'UEܪˆ «°”|ã‡µŠ {ð"œÄí<¹7? ¤”+¹öÏÙÏhLìŠFµòzƒîº9¡Š¹@NœÕj5U~–PC™ž}„R0®ž›¤Zê‚æ@A!¹[Ÿ€¹Ù¬ïü*yìKŒè^4`¾ê‰‹/¦-éµ£„Œ<ñ?üõ¹Û¾™w­_@•Vendstream endobj 688 0 obj 242 endobj 692 0 obj <> stream xœµZYoÜ6~ß_±R‘UDR‰<hnƒ¦µ7OIì½ltgµvìüúòÐp†÷ÊôD‡œë›!åÏÃvu©4™ï}ÀDz|ˆ.›2«ŒÌ2#&²²4ÁeV{kìyaš±i®üë{t#p+çAIŠ0,ËŠáˆ×Ž[nÌ¥U† ¾äOÓ¼@®[‡t6)¿­o6ÔÂîØñ7[¶¾oa†47 3ËÒ,wçó"ÁqÚ¡«£·ÙøÀÙÁl7ú@ só~‡ª]îñ‡cþ„Nzoüø5ޝ"‹Z3€‚8 ŠªhçÑ`ƒ«¬ÂÈ~nåÕ¶é{†µšuÙQ‹Ë=°Â‰)ïé0„·šèi‡ÁºI#Á>‰iüULãËÀL ë]Œé.Æt£ Øk-%7ÔW€jî;ç1Á·}_‘õžè^:h¨L¢tXvÚ †1Ö/Ðú‡B dããgáh0º°i'Tòä}¡¡vH¼ ·E?²Ä¡È2Ò†ž]ž'ÛÄÏÀåýnEW@åž-å×ñÖO¸ÀŽ}ç:ôÉ2Qßý”x‚)lb³È 6vôª'¬{û£ (£ð„U†ŽÕ0DRAjšÑ`w.]e†àhçD˜Õ<ƒ# JûÔs=ì d…Ç_ññSê‰Û°2Ü—vªó<ƒ4s ªÐE'=Ž´êi³R´Ôù ¾Ú¿º£H¬‚ÔtPæÐI…¬¬##‡ŽÔ~€X. §Ø Õ•Öú{Ô‹—ÁtˆÅh¥wFâ3šQˆëQNªž~Æ!ÆÇäDݬЎG-nîYåëÌy/TZÛ÷CÐÅ„›½/(äyA"±õ›§ëíÛü¤>;ÿ,a˜d˨À‘â«-˾cÇÑryªÅÂÛ \·†T} ‰ñð ù¨ráoy¯Z¶ýìßÄÂ'Zï5°8#|ŠÒl D;ñ𪇣z^{¬¡!€F+oP/º/þ°š&§„>0èé)ùt\ŠªsX,§'êÉ¥6ëµÇŽ¢è;l#:ºÄSÖ’î‚cíiváÜiˇß-½õ˜¡ÆŽG¤3Š·Ï½ƒT‰7O(QÑ ž%µ%¶4nj+Æü"t‘ ¥†ÀÇ|‡„;tôć˜€7Grä+LM«§ †‡úî†*Õ]Uagßk¿Ä6ÂÓOAïmF®œ~FŽ3rßùÕ/ˆ C‹¡By#åbÿÎ&vÜ s mÈ‘ä/óþÁ4ïÚâýàME‹£÷Þg<59¬@º kÀÖ@Û4âõÁb‹oµ>NžYþâÅ‘mþ£p×O|(yÓ ‚H¹ @ è㬼ÉëŒ1¥àé¾úæÃ¥·Ûmd]á\¡E¸{¯9«šy¨š'Ì›o“ˆœÐÚί’ºÈÓ0?îüÆïB$˜×Mpׇrvp°¡H.œë¨Ð©‰¹éÅUO&ô¥¿ðïñˆ„ç6 G€Ôe¼“ú¦¡š©ÆAPÀ1‚úÝ#"&BûúÕ÷íBEnB|5G+E Æë˜¤Ë˜¤ÓÀ#BùH"\…;ÁÒá6€.zásžJtŸuLLR-D‹£E,D¢UaÜc/yôç^¾D ÂuNí46îýÄ-@ âðCM玺« yÊ¡Bãƒï¼DÊwûe%ÐÊ–OIÝïO'}jZÆ$ŒÙÕy€eeÇoü‚ä« fÁ ó&œkðôD³Ž¿×Ö6µ°v Ì{ÒÁLâúÆm,  ÀÓ=Hq8á•„p–0®Óë Ñ·ëÒûò‘—fž«KÑx_åÙWbFíÓ×3²jÙÉ"öÚçoÓ¼Æ=žw§æÿ€(¿h¯ÏxŒ{¢ÈÃ:vbò\¡)&‡uµ< ŒêHˆâ8‡áøçÅÙ÷cðËKÆé?~p^f²Ž´uÜ?ŸCg©1¹LTZš9oƃôÏÿ,ä•Ãendstream endobj 693 0 obj 1995 endobj 697 0 obj <> stream xœå[WsÛÖ~ׯÐ[€;C•’‡Œ\ãD¶sMzÆ™ä>ÐT³X$eÅùõ÷´-X‘DYbbabqêî·í”‹ý8Jöcý×ý?žî}ÿ®Ü?]îÅû/Õ¿Ó½‹½ÄØwÿ§ûO†ªP’*JTÇu²?<Ù³µ“ý2ÝïWy¤>§{IX™ú‡Åÿ†¿¨ZYÂk¥q•}Uqx¤ ? {YT–u?‡IT×U^aüö’(Ï‹2 †Tæ¹¥fy¼SÔL5kúKÕ¿H}KÓ:J“àE¨+”ý2x¥+TêOæš©Ò$a¯PÍäuÁ ¼Õ-fQšUÐî]õGU—q_ýÎÒ(®S[6JÓ´ßÇÄØn™Tª7ÅÕW¦fSǼó÷¡j#.Ô0º¦©àø`¾Û¦“J5ò,ÌÕØ²4år¤ebÙ›Wœ½=ÇßžR™Ôµes¢Ú ý(UCq^Eq,ôû±~,õc®ûã$ .õ«ù:vEòZÕˆ«à«Œôã«L [å“c\Wø]}Jµt«¾i+ñHW¨ÔKÎÆ1¦ïc>8 .€¨‘dQÑ÷†ÿá3®hÆfÐ+|c£SýúÙ}ÈëRuàʨÑYb&?ÇB†3¬ý=Î{á7;¢±®¨ÙYõ£Z'hªš‹i¬~—Á ϩ䄷Ù.Éz?—xNã]ó$ì3ÝERdM%¹O¥žf¼y&£<ŽúUœÚSͽX?×ÙuÊzì¤,š¡V4Fè…«ýU¿þHµ7Èç;O@ÉÉ2,$”®|¶¹J¢Ô.$Ëp.5ïá]›§OR{_‘x%!ká¡À9`ˆŠºj‹&mh™b¡¸Qaû ˘$…¶OH4Rð쫳>ˆM.„Ñ5032L¸8Fž>f¡X–é;ú™¯:º’šÌ9ÿ~SÕ9“d6â’m‹{Ñ2o$”ìîB¹±žwh[zƵEè£5´r’äÇkf Õ‰ÓKâô\j“É”¾ŸP¥·4õÉØ¯Ô#Ï$õÈI7ƒ9øé/ÈzãI.9ÿ-ÖúMéM|&[G#r‰&<‘ðÆ&ŒÖDˆFh–Å}Îr –ÚÖ>—†yº„ªsÏ´„¹¦yë7©òXbí¼KO¢ð¢Á›Œ¥á‘d‘TVK7Ëk%^Èa\ó¹ÊŽ==f¨ï¹*=†®I°è,ÎQƈÑ)GÀ”žÝa¥ÿ⦠<‚¹»9àó Š‹Bÿ $;ñ¹0"ˆä;ü>¤ï/ø–ˆïøšˆ cþ >‘Å$†\m}]-» ÅäR <ÇB Úé¤=âÝ£”[ˆÏÅ^K6ÿéwu½Üûµªov×z%5Š2Ç*`ûT†' GÝ ïžÞAÉÏëg¼’vDÉöfqqrAÕ¯wF‹eSÇø`)uAò’ÏÙ˜Ò¢ˆR°¤3M‚Qý©aTMåFܾM­ÿéÝâJjóT".È2|‘ 6‘€ñ2qL~‘O—`3áV&ó’â4ðiÀúÚTk§¶ž >GÂ*õìΙ˜¿m%›m¾']ÝÔýþJ?ôò¤^ru¥ íƒá½ :75 [UÚuroôû›ˆ¦-= xyYhÇqÜ•nenÙ}Ì-s±Ã·\ðƒ¿ú×*IŽaEFQ\›‹uÄ7\Ì‚¾–¤$®Ý­$¢g7YRÁ¶ÝV;êWušÊúüó®òךj¶ ÌfAðž[.£Ì¢¸RfëÈÝæùò±Î³•Û›yvNâŒù}Ö˜<Ñ¡~}¦ƒ­%q[1],5šáppn¨èΗqE@ÝÜŒœpÉ~½"Û ‘™Uû‚Ù ¦ÌbˆLÛiXI%ÅŶDp%õyÄ'Ä3ŠÀoÅ_è‰åË,ú8@â"zÖ¾ú^“ЩUw’š©bâ9³-àooÓˆî„DGa›x»$‡ &ÀÒ„ŸrÌ0Ö€D×ñºdá'›iJnHɶ-ÔZ »k„F`³ÆŽÏE‰™a‡k ’yüŽmüæLÓ¶ZƒX€ou“APÈ »Ùèšçס,_4X<ìr6tú5 ‘Èù4xì²XžHbJb!×ôaÄ’í¶XÞ á€J}d5 oôh…‘ß«0hßlb™·ioêA…ÅB mûÚ¥N×­wF%ð˜|¸¯2vÜ;K6wÄl!96b·µ“d˶²Ä%FÑë½å%u{Hq¥<ß‘üû[I‚ÿÚ˜9 ï}¡á‚©4YÚwҢѿþ˜,ô—8¾EDNæ•Ê£0ý¥— ADþí‚@ÒΛ®f9Ü™ÀI[ú0|˜üF§ÃZ ©ÏçB«Ï6? bˆ‡¦ÆÕ©ÆHÚrš x½Jò 5vò¿‰_âFÓ±Èyq[aA¬»]šÙºÄƶŸÄ…TqeˆŽ·þn7º¦W@õTkݶ‹â+™þ©÷ æRÙõ§ñ Nú¶©šFh…ç$Ÿ+Dœ€ô¬¸dá«x“nå7'}o[ußþ·ò`ÙþÓA•Ï’J¥æO$¢çíU”â–Ö„U ¢qh–¥‘ð”i”怆[_C2ÒJLÎ;ð1 Õ|P{H³ý_mZ4ézÑgn™N´/íl:-/z»©„”‰Ô¦·ÔíÖO×—{â]k ÅÛŠ‹õó¯TÌÈ|‹V$ #Áqèb{|˜ø7¢Zr(x£VYÿtÚ1Õ×9]yèg]*¸¡ŽF?k®ŽY_‡7^‰y._ º®ÚÆí¦ºì_éq&ïÚuÄ’¹ o—v&Ò"êüæ‘/Y>_bkC”Mú¦±a.F„]õºrf Qæ³*Ë6pÙ€KYI–¨h`åa²Û‚šèä~ŠE ¦þö@ƒŽÞžÉÑ7ÈkËk‚=k_á`줻4âVî€TùÛEå†Qé}3ŠN×™8~@ŒÚâ½”"ôs.½ßcÏ*²sä·»‹@“6óõâ@²= š×ž¤!boCéYl÷ë·º8×v7ˆÚu–àÂ9Á%#&JÓ°<Ë!ë×j¢öܵ¾,ê£I¨ÈÄž¸Ÿ÷þ«þþ‡G‰¦endstream endobj 698 0 obj 2542 endobj 702 0 obj <> stream xœíZYoÉ~ׯà#¹'3œƒ3‚…ìhm%¾V¦‚ì ÒDH‰KRöÊ¿>}UWÕt g(Ê»0¦¤fõUõÕWÕÕý[/Ž’^¬ÿ¹ŸW«“¿^Œ{óíIÜ{¡þÏO~;IŒ@Ïý¸ZõžM”P2R-QWIo2;±½“^>J£¢ìe)Éêä?ýd÷Sõ_ýüuòOÕ3+iÏa–'ºË0£qRU½Éµê4 Ó~®?²Á0‰³2Š“þKý÷þ˜êkõÅq’ضÍ`˜Ç•j÷gúï…þXºóM’ÛŽ:N>ŠUŸ²¥ÿ¾ GQU•eÑ¿õ£ï°qê’äÖLDÄñ†Øxé—Ò$Øç¿ƒaV£ªÌÍBmã'©ÏFj¼ÂÆÓZÐg ÚVIåE¬ìøêdò5JŽFù‡·Ç4êt-XÁéºÝ ©ÙûaªÏªÒŒñmÕG¿ÎÓDý^0åWª~hÜÐî°Ï¾qŠ’Kßx7T ®Q›Ï۬РÚìÞ+ØX‚©ÁØiçÌaÌ£Lºö}Œõ¶t3y\ª© >Á@Ie'^ò'\÷[ßx¯]§r¬µêêÁ7~ÁF4 òµ3Z•¦K˜w·“L%Âp¾Ç#ÉÞ ¼£:üϽˆq¡¯{¬••…Ù¥V²Öoj4[Wª1OFXs*‘‚Øø€kj€*RÒS`½P))*…QUÊÜï} &µˆ²äs®?^3·4, €,ÅhÔhÀ„Ëä€1ZR¶„ó齯Qbb˜%ÌTÏלï°m¾ôÛü€Þd`a0´âˆ€@˜öÿ{Éɲož7A˰ï˜X\ -·Àí™ÞO®¶^ ó=K™ÙKà7’RwÒê6h‰kr«_ÐÆ¶áCI·¦,-­þ-´/Ú®iGe¦2“œëϰӌm”íD“iNÈ™rÇWûÉÐM:ôQXÏ"t‚¬±dØí­‰Ÿ·ï¼àa‡–ž¡¥7’Q%BÄ‘õé{‡"¨*ÿ}…`ã/¦*¥¡,­ÊÐíHòˆ)ÊŽ»ÑÄÚ}nçŸ ð¥2JùLC¤ ‰õy;7—”„Ð$pøL»ëdr&I1—üo¤™EjFÉkŽ€ÝV¾ñRòãMÝ 4]D3‡šÁ±6Dð2ÌDXöh$!…ùè‹°dB;¥SÄãSZ5ÌSR8uQôF—ˆ¢G?´pà÷É3«2¦“OŽ‹¨ôyRE3ºsüu‚¼ö1:9p¹‡õœM8~lTÝzœùdÖÁ%\†*çÖ7~6üÂCñFDïæî ˉ™xl!¸‰Cæ5šãé|GZqPÛ•K šò<šv,t~–b°0 ,rÍûå‹×=´ðJjäY ä7ÿžs¤FTÄ%À¢”¨J†š©‰Zªï3d}›âdý<VY‚Ûì^:iÚ›p’s“UQQ&€¦+,XY9†¬N˜á’“)ÈnHxã>ÞM·nßÐï›KÉÒs =hi~ú~Ôéœd9}îÚWº_)Ó”™ÒNÈt@fò­ì©@ÖÈÉà˜‚Å©þû½þx>pÅ+}Žu ±—0,9óXWzTŰ)†ayJÁ Õ^Ç&l »lø½y8†úuƒ$FݰÝ!þ²L@ØÁ¡ÒÔ•Ñc¡rɳ*¦LÉNÑ€Á·‹ëôíÁ‚‡ž?, ÉÐBä‰+‚!x‘’Ìg Z¶"· ³^ˆÂ°|~Ía†WN·aÔËIñš›ß%E#%mÑ⟤°³•΂wL}ðý¥4;b¤Ú¹\  ¾;ÔÛQýãï3w‚éè•äÀ |r’“|Ñe9G Am Cû’÷©a8 õ:ðÚ’8­½ÿIŠ+$.,ÙêêN+&榆$œ‡Ugˆ¼5Üp²@g¿öî»’”Çn{C•±›Y¢p0-~/ºçñåmt:©"=ð¼ ɪv™ºC¬½ÌïÜG—(ÓÙ$ ª?È€¿©KÖî75¢$¹-^JÓsý¸‘bt “ƒJ.á鲩Ô=ðd踇­gUÑg–\Ÿâò^ùÑϤ1á_Ì•Þc÷ç¾Q“\!‰¤‹V^JžIüqާ¸µdeÑßD6h¨U@¬ÿ»Mc1S=úêyêýqážïíë„$ìh°ƒ¿Ñ,nUº‰Î—šÞè¿ÍSs™þÑúBÿyá¿ý ?Þˆ>õ“*y¦~¢ÁæKò"SšaªYYtkƺp‰2“º£¤XÛZH³ßbM7X#{Ÿ46ñAæøÔÍ®ò©ºO½/œÝ1Úÿ› ¿ö"æ·gþOÝ—ùóÉEÕ𔙌Jê¢<ëbðƒÇ}ü;(Œ|a« Oþ¨ž&€JÌ–w(RÔs·7}ïíêÂj¨bTŒ4îÄûˆ;EÄÜÌu!:8Bš˜àžÂ–^]ÈíþÜX¼y_5¥¶žÆ`'£I¾Ø¸ Zmrd€[åQFÞªR£ëHR¿Í_wˆ×ì‘BÀÓd Ç[Ã>ÔÇÄ‹59Šñg€ý²ÿ#¶Ö¼çlrò³ú÷?eŸ-Êendstream endobj 703 0 obj 2536 endobj 707 0 obj <> stream xœíZYoÛF~÷¯Ð#UT,ÉåÙ·¤IÓ#hÒD 4EàH²­F¶lIv“ß½gfw(ɶÜ…c„¦—{Ì~óͱÇÕ KóA¦~ìïÉùÑ7ošÁéú(¼ÿO®Žr]a`MÎODzR^È’´Ëº|0>92­óAS ê¶LåÇñùÑïI>¬!ÿÃêñO²•Èq«"ëÒ¦– ÇSYù»áH¤MÓuyòÃ0O»®-»äɰH^GyZ–US$c¨óܔвMÞÈR!»Õãɱ’T~+Š.-òäû¡jÐÔMò£jÐÊÂvÓy™¼Ž*ÙMÙU¸Â+Õ£H ѺqÔèrœ,m»¬Éjù.Š4ë S7-Š¢®½ ™ï·É[9š„DŽ%älº þn(ûÈ*)æ[ÕR7°8èï¦ë¼•<–R6QX ;HÑäÞ²ÅðŽ,¾#)R“wYÈ>“Ú>ª¼“@‹äõ÷ õx­Ô¸Y–k”…ž–y¨Ò‘™µ©üÜW–½4"oÓ,ON|ár8*”2Û:¹ô…3(¼ð…ï(}?ŽÊ®‘•¨¯c¨0÷… (œùÂ)~-§™µi×6É„ë ¸€Â¥/ܨæ|oPá%7¦l^™®¹!ßÝë¹y-%«PH~$ÕêÎÕ¬UP  ¥þ2«ÓºuÖêo#ûq”‹´ª³"¤B³/^YäYÎÝI3Õ€!°¤Ð•Èå{TIÄG´ÐXKê³]O8V]s57¸Oû¶ê!ŠWyÜ7‹ ¥IWh;¬êÏ„õH“h*ªYTÝ)Q Ò[ÕµƒñË£ñWXsíš{ªþ|¢ϼ?ñ6-[´¢)•Õ~äìÃêó˜ÃñÔ^šo3sPÍÔ}ɼÆ5·Úx 6þŽktÍu¼C&øÅùg­ ƒ†.ˆ¤XYmXÚ|'G]ካyŒ%UÊ`áZm‡kŽŒµ h¾ä ShþÖž±&qM0¦(î¼é†ãËÂÎÙv¦ÒXS4i®³ ãªJ5ýL=r6ÔÌÕ(ºó€X±ršô"óÁ”Ñ32”miT”72hU·: KÿÂF€ò¦Ç`0¾Ö¿(áºßß¾O{ tÝN¸îUÍ4*lbµÂØÄNcÓ#V´tym…£1A¥WQUiáÒ‹k qP ¢Þ †ZGum×lÎٵ›¸Š:[`\ñaœì”µ· 2Øìóf{´»&C;¿B‰gó5;ô!I‡ÂË:MµZ®³JÇ5rïN;—hˆvF@Å»R¸à¼À;EC¬ ÷ðH ¼¸˜8ZšŠ73KZÏ ¯˜+UŒô¹äà'–î†[s5A¥s޳§ÐœR_|á_œH+¢ü]ï!œ¬)tù´va*Auûº­ Oç&ð•ÑÝÌó`ê µuZdC:Ž8#^r³„&œI.`­s8ýÝÉÙ€Lk6ÊõÍ“Yü’™º8%| Z8Iv¹TTgúTÖ0̈þ8S=Úû½íÝ©~0g]ù­˜‡´I ¾~ÔÝÁt7åÌÖÞ95Í@ÐKnx~ÏÍyÍXýŒšºT—r<œ/hþÅœs‡íøÈƒwBϸš+®¦YÑ2‚æö÷!l_t@)ÍOïŸX}Ç~¡}ÔãCéñp®žµÖX—Ý£.Z—÷wýQ‚.ÉÆC_ KÌõ³ž?·Ts,ûè3 t~ðÉ‘I_wqz±¢U„1‘,¬mtTí ³›S†ÄFrûpÒk^/üc†ù`eZ€ Ú”¦y|Ä£éi©äGOñÖDœLHz¤Z8M Úr9 $ ‹óXñ@ g„CqŸhùr°ý6~!gr ²äÙS)EÚIÚÉPì>õ'¨?Æxh@53/îeãA[u¡ˆ7³Nw±5dz:R€“7íN<•—ÖðÜÆ6ÐðšSd¯S”ŒžsêfÉÈ®Ê瘱8Ç[ØÂ/ÜèÛÜÁþ{ëaÌÓ¥á™(ÒÊûäàØÅ~ìÓ´¸]0†µ–¾ˆ º‡µÄ9¯yMc}F(Ø-"³·÷2ð”åí&píešÐ:MlŠ—²lí;ï>ŸhË«âÖ>óq‚aWŽÕ ¶·\\s5]Ò»ö—³qG}'U"ˆ…km/ܽ1 uĆÏTo Ý¥‡î.g·ìù{Éa}7|‚K€Ox®ò™0Eÿ€ÎnËÄ…·©ÿB¯Y¼ã‚æqÃñyZö˜ŸäŪ?vƒMHXqx §ñ&IŸkær0¸FˆcÊ;oT–ï¸Æ¸M«Çu `/8Ä`†Ô—ðGEÛÖ9P“¯ É„ÐñSLë'²ßΊAEî:ΩÍ3´D¤øY÷‰¯è³dTmÚí:§_sx‘[2Î#²‡!KYÔ=ëFÙÍÑsÜ}/5«‹›~hgÞyñ#£¬ »]f®/Ž4·¸Ó—zÇw ÚgÞF6*¶…‘| <[:«7(^Rx7”¹‘3£‹qK¸]Ô¥Wû,!Ù´ãÆäŠz§½½f¸«á(¾b2ñœ ±kÕÜë­"`ÿÿ42p§œ¸RË×¾•$½äÅ"ú'‡(»´W¤Ç¹.Zì0û»¢<Áâ´aJ,4ö‹ì‚z)Í»"n¢>?sxQîVÇK½i6@yËuO˜+ÞéHù}=ÛÖ½»g/W^ˆ™$GawJb9@âØÉÆ(ÖCt ò¢Kç&Ѿ=Çok8Çÿâk‡ äû`ê³×g”BôãlXþƒ~€¢‰b>d™W͹Ç®A˜ÍŒÿ> /Contents 5 0 R >> endobj 16 0 obj <> /Contents 17 0 R >> endobj 21 0 obj <> /Contents 22 0 R >> endobj 28 0 obj <> /Contents 29 0 R >> endobj 35 0 obj <> /Contents 36 0 R >> endobj 40 0 obj <> /Contents 41 0 R >> endobj 45 0 obj <> /Contents 46 0 R >> endobj 52 0 obj <> /Contents 53 0 R >> endobj 57 0 obj <> /Contents 58 0 R >> endobj 62 0 obj <> /Contents 63 0 R >> endobj 67 0 obj <> /Contents 68 0 R >> endobj 72 0 obj <> /Contents 73 0 R >> endobj 77 0 obj <> /Contents 78 0 R >> endobj 82 0 obj <> /Contents 83 0 R >> endobj 87 0 obj <> /Contents 88 0 R >> endobj 92 0 obj <> /Contents 93 0 R >> endobj 97 0 obj <> /Contents 98 0 R >> endobj 102 0 obj <> /Contents 103 0 R >> endobj 107 0 obj <> /Contents 108 0 R >> endobj 114 0 obj <> /Contents 115 0 R >> endobj 119 0 obj <> /Contents 120 0 R >> endobj 124 0 obj <> /Contents 125 0 R >> endobj 129 0 obj <> /Contents 130 0 R >> endobj 134 0 obj <> /Contents 135 0 R >> endobj 139 0 obj <> /Contents 140 0 R >> endobj 144 0 obj <> /Contents 145 0 R >> endobj 149 0 obj <> /Contents 150 0 R >> endobj 154 0 obj <> /Contents 155 0 R >> endobj 159 0 obj <> /Contents 160 0 R >> endobj 164 0 obj <> /Contents 165 0 R >> endobj 169 0 obj <> /Contents 170 0 R >> endobj 174 0 obj <> /Contents 175 0 R >> endobj 179 0 obj <> /Contents 180 0 R >> endobj 184 0 obj <> /Contents 185 0 R >> endobj 189 0 obj <> /Contents 190 0 R >> endobj 196 0 obj <> /Contents 197 0 R >> endobj 201 0 obj <> /Contents 202 0 R >> endobj 206 0 obj <> /Contents 207 0 R >> endobj 211 0 obj <> /Contents 212 0 R >> endobj 216 0 obj <> /Contents 217 0 R >> endobj 221 0 obj <> /Contents 222 0 R >> endobj 226 0 obj <> /Contents 227 0 R >> endobj 231 0 obj <> /Contents 232 0 R >> endobj 236 0 obj <> /Contents 237 0 R >> endobj 241 0 obj <> /Contents 242 0 R >> endobj 246 0 obj <> /Contents 247 0 R >> endobj 251 0 obj <> /Contents 252 0 R >> endobj 256 0 obj <> /Contents 257 0 R >> endobj 261 0 obj <> /Contents 262 0 R >> endobj 266 0 obj <> /Contents 267 0 R >> endobj 271 0 obj <> /Contents 272 0 R >> endobj 276 0 obj <> /Contents 277 0 R >> endobj 281 0 obj <> /Contents 282 0 R >> endobj 286 0 obj <> /Contents 287 0 R >> endobj 291 0 obj <> /Contents 292 0 R >> endobj 296 0 obj <> /Contents 297 0 R >> endobj 301 0 obj <> /Contents 302 0 R >> endobj 306 0 obj <> /Contents 307 0 R >> endobj 311 0 obj <> /Contents 312 0 R >> endobj 316 0 obj <> /Contents 317 0 R >> endobj 321 0 obj <> /Contents 322 0 R >> endobj 326 0 obj <> /Contents 327 0 R >> endobj 331 0 obj <> /Contents 332 0 R >> endobj 336 0 obj <> /Contents 337 0 R >> endobj 341 0 obj <> /Contents 342 0 R >> endobj 346 0 obj <> /Contents 347 0 R >> endobj 351 0 obj <> /Contents 352 0 R >> endobj 356 0 obj <> /Contents 357 0 R >> endobj 361 0 obj <> /Contents 362 0 R >> endobj 366 0 obj <> /Contents 367 0 R >> endobj 371 0 obj <> /Contents 372 0 R >> endobj 376 0 obj <> /Contents 377 0 R >> endobj 381 0 obj <> /Contents 382 0 R >> endobj 386 0 obj <> /Contents 387 0 R >> endobj 391 0 obj <> /Contents 392 0 R >> endobj 396 0 obj <> /Contents 397 0 R >> endobj 401 0 obj <> /Contents 402 0 R >> endobj 406 0 obj <> /Contents 407 0 R >> endobj 411 0 obj <> /Contents 412 0 R >> endobj 416 0 obj <> /Contents 417 0 R >> endobj 421 0 obj <> /Contents 422 0 R >> endobj 426 0 obj <> /Contents 427 0 R >> endobj 431 0 obj <> /Contents 432 0 R >> endobj 436 0 obj <> /Contents 437 0 R >> endobj 441 0 obj <> /Contents 442 0 R >> endobj 446 0 obj <> /Contents 447 0 R >> endobj 451 0 obj <> /Contents 452 0 R >> endobj 456 0 obj <> /Contents 457 0 R >> endobj 461 0 obj <> /Contents 462 0 R >> endobj 466 0 obj <> /Contents 467 0 R >> endobj 471 0 obj <> /Contents 472 0 R >> endobj 476 0 obj <> /Contents 477 0 R >> endobj 481 0 obj <> /Contents 482 0 R >> endobj 486 0 obj <> /Contents 487 0 R >> endobj 491 0 obj <> /Contents 492 0 R >> endobj 496 0 obj <> /Contents 497 0 R >> endobj 501 0 obj <> /Contents 502 0 R >> endobj 506 0 obj <> /Contents 507 0 R >> endobj 511 0 obj <> /Contents 512 0 R >> endobj 516 0 obj <> /Contents 517 0 R >> endobj 521 0 obj <> /Contents 522 0 R >> endobj 526 0 obj <> /Contents 527 0 R >> endobj 531 0 obj <> /Contents 532 0 R >> endobj 536 0 obj <> /Contents 537 0 R >> endobj 541 0 obj <> /Contents 542 0 R >> endobj 546 0 obj <> /Contents 547 0 R >> endobj 551 0 obj <> /Contents 552 0 R >> endobj 556 0 obj <> /Contents 557 0 R >> endobj 561 0 obj <> /Contents 562 0 R >> endobj 566 0 obj <> /Contents 567 0 R >> endobj 571 0 obj <> /Contents 572 0 R >> endobj 576 0 obj <> /Contents 577 0 R >> endobj 581 0 obj <> /Contents 582 0 R >> endobj 586 0 obj <> /Contents 587 0 R >> endobj 591 0 obj <> /Contents 592 0 R >> endobj 596 0 obj <> /Contents 597 0 R >> endobj 601 0 obj <> /Contents 602 0 R >> endobj 606 0 obj <> /Contents 607 0 R >> endobj 611 0 obj <> /Contents 612 0 R >> endobj 616 0 obj <> /Contents 617 0 R >> endobj 621 0 obj <> /Contents 622 0 R >> endobj 626 0 obj <> /Contents 627 0 R >> endobj 631 0 obj <> /Contents 632 0 R >> endobj 636 0 obj <> /Contents 637 0 R >> endobj 641 0 obj <> /Contents 642 0 R >> endobj 646 0 obj <> /Contents 647 0 R >> endobj 651 0 obj <> /Contents 652 0 R >> endobj 656 0 obj <> /Contents 657 0 R >> endobj 661 0 obj <> /Contents 662 0 R >> endobj 666 0 obj <> /Contents 667 0 R >> endobj 671 0 obj <> /Contents 672 0 R >> endobj 676 0 obj <> /Contents 677 0 R >> endobj 681 0 obj <> /Contents 682 0 R >> endobj 686 0 obj <> /Contents 687 0 R >> endobj 691 0 obj <> /Contents 692 0 R >> endobj 696 0 obj <> /Contents 697 0 R >> endobj 701 0 obj <> /Contents 702 0 R >> endobj 706 0 obj <> /Contents 707 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R 16 0 R 21 0 R 28 0 R 35 0 R 40 0 R 45 0 R 52 0 R 57 0 R 62 0 R 67 0 R 72 0 R 77 0 R 82 0 R 87 0 R 92 0 R 97 0 R 102 0 R 107 0 R 114 0 R 119 0 R 124 0 R 129 0 R 134 0 R 139 0 R 144 0 R 149 0 R 154 0 R 159 0 R 164 0 R 169 0 R 174 0 R 179 0 R 184 0 R 189 0 R 196 0 R 201 0 R 206 0 R 211 0 R 216 0 R 221 0 R 226 0 R 231 0 R 236 0 R 241 0 R 246 0 R 251 0 R 256 0 R 261 0 R 266 0 R 271 0 R 276 0 R 281 0 R 286 0 R 291 0 R 296 0 R 301 0 R 306 0 R 311 0 R 316 0 R 321 0 R 326 0 R 331 0 R 336 0 R 341 0 R 346 0 R 351 0 R 356 0 R 361 0 R 366 0 R 371 0 R 376 0 R 381 0 R 386 0 R 391 0 R 396 0 R 401 0 R 406 0 R 411 0 R 416 0 R 421 0 R 426 0 R 431 0 R 436 0 R 441 0 R 446 0 R 451 0 R 456 0 R 461 0 R 466 0 R 471 0 R 476 0 R 481 0 R 486 0 R 491 0 R 496 0 R 501 0 R 506 0 R 511 0 R 516 0 R 521 0 R 526 0 R 531 0 R 536 0 R 541 0 R 546 0 R 551 0 R 556 0 R 561 0 R 566 0 R 571 0 R 576 0 R 581 0 R 586 0 R 591 0 R 596 0 R 601 0 R 606 0 R 611 0 R 616 0 R 621 0 R 626 0 R 631 0 R 636 0 R 641 0 R 646 0 R 651 0 R 656 0 R 661 0 R 666 0 R 671 0 R 676 0 R 681 0 R 686 0 R 691 0 R 696 0 R 701 0 R 706 0 R ] /Count 138 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 14 0 obj <> endobj 15 0 obj <> endobj 19 0 obj <> endobj 20 0 obj <> endobj 26 0 obj <> endobj 27 0 obj <> endobj 33 0 obj <> endobj 34 0 obj <> endobj 38 0 obj <> endobj 39 0 obj <> endobj 43 0 obj <> endobj 44 0 obj <> endobj 50 0 obj <> endobj 51 0 obj <> endobj 55 0 obj <> endobj 56 0 obj <> endobj 60 0 obj <> endobj 61 0 obj <> endobj 65 0 obj <> endobj 66 0 obj <> endobj 70 0 obj <> endobj 71 0 obj <> endobj 75 0 obj <> endobj 76 0 obj <> endobj 80 0 obj <> endobj 81 0 obj <> endobj 85 0 obj <> endobj 86 0 obj <> endobj 90 0 obj <> endobj 91 0 obj <> endobj 95 0 obj <> endobj 96 0 obj <> endobj 100 0 obj <> endobj 101 0 obj <> endobj 105 0 obj <> endobj 106 0 obj <> endobj 112 0 obj <> endobj 113 0 obj <> endobj 117 0 obj <> endobj 118 0 obj <> endobj 122 0 obj <> endobj 123 0 obj <> endobj 127 0 obj <> endobj 128 0 obj <> endobj 132 0 obj <> endobj 133 0 obj <> endobj 137 0 obj <> endobj 138 0 obj <> endobj 142 0 obj <> endobj 143 0 obj <> endobj 147 0 obj <> endobj 148 0 obj <> endobj 152 0 obj <> endobj 153 0 obj <> endobj 157 0 obj <> endobj 158 0 obj <> endobj 162 0 obj <> endobj 163 0 obj <> endobj 167 0 obj <> endobj 168 0 obj <> endobj 172 0 obj <> endobj 173 0 obj <> endobj 177 0 obj <> endobj 178 0 obj <> endobj 182 0 obj <> endobj 183 0 obj <> endobj 187 0 obj <> endobj 188 0 obj <> endobj 194 0 obj <> endobj 195 0 obj <> endobj 199 0 obj <> endobj 200 0 obj <> endobj 204 0 obj <> endobj 205 0 obj <> endobj 209 0 obj <> endobj 210 0 obj <> endobj 214 0 obj <> endobj 215 0 obj <> endobj 219 0 obj <> endobj 220 0 obj <> endobj 224 0 obj <> endobj 225 0 obj <> endobj 229 0 obj <> endobj 230 0 obj <> endobj 234 0 obj <> endobj 235 0 obj <> endobj 239 0 obj <> endobj 240 0 obj <> endobj 244 0 obj <> endobj 245 0 obj <> endobj 249 0 obj <> endobj 250 0 obj <> endobj 254 0 obj <> endobj 255 0 obj <> endobj 259 0 obj <> endobj 260 0 obj <> endobj 264 0 obj <> endobj 265 0 obj <> endobj 269 0 obj <> endobj 270 0 obj <> endobj 274 0 obj <> endobj 275 0 obj <> endobj 279 0 obj <> endobj 280 0 obj <> endobj 284 0 obj <> endobj 285 0 obj <> endobj 289 0 obj <> endobj 290 0 obj <> endobj 294 0 obj <> endobj 295 0 obj <> endobj 299 0 obj <> endobj 300 0 obj <> endobj 304 0 obj <> endobj 305 0 obj <> endobj 309 0 obj <> endobj 310 0 obj <> endobj 314 0 obj <> endobj 315 0 obj <> endobj 319 0 obj <> endobj 320 0 obj <> endobj 324 0 obj <> endobj 325 0 obj <> endobj 329 0 obj <> endobj 330 0 obj <> endobj 334 0 obj <> endobj 335 0 obj <> endobj 339 0 obj <> endobj 340 0 obj <> endobj 344 0 obj <> endobj 345 0 obj <> endobj 349 0 obj <> endobj 350 0 obj <> endobj 354 0 obj <> endobj 355 0 obj <> endobj 359 0 obj <> endobj 360 0 obj <> endobj 364 0 obj <> endobj 365 0 obj <> endobj 369 0 obj <> endobj 370 0 obj <> endobj 374 0 obj <> endobj 375 0 obj <> endobj 379 0 obj <> endobj 380 0 obj <> endobj 384 0 obj <> endobj 385 0 obj <> endobj 389 0 obj <> endobj 390 0 obj <> endobj 394 0 obj <> endobj 395 0 obj <> endobj 399 0 obj <> endobj 400 0 obj <> endobj 404 0 obj <> endobj 405 0 obj <> endobj 409 0 obj <> endobj 410 0 obj <> endobj 414 0 obj <> endobj 415 0 obj <> endobj 419 0 obj <> endobj 420 0 obj <> endobj 424 0 obj <> endobj 425 0 obj <> endobj 429 0 obj <> endobj 430 0 obj <> endobj 434 0 obj <> endobj 435 0 obj <> endobj 439 0 obj <> endobj 440 0 obj <> endobj 444 0 obj <> endobj 445 0 obj <> endobj 449 0 obj <> endobj 450 0 obj <> endobj 454 0 obj <> endobj 455 0 obj <> endobj 459 0 obj <> endobj 460 0 obj <> endobj 464 0 obj <> endobj 465 0 obj <> endobj 469 0 obj <> endobj 470 0 obj <> endobj 474 0 obj <> endobj 475 0 obj <> endobj 479 0 obj <> endobj 480 0 obj <> endobj 484 0 obj <> endobj 485 0 obj <> endobj 489 0 obj <> endobj 490 0 obj <> endobj 494 0 obj <> endobj 495 0 obj <> endobj 499 0 obj <> endobj 500 0 obj <> endobj 504 0 obj <> endobj 505 0 obj <> endobj 509 0 obj <> endobj 510 0 obj <> endobj 514 0 obj <> endobj 515 0 obj <> endobj 519 0 obj <> endobj 520 0 obj <> endobj 524 0 obj <> endobj 525 0 obj <> endobj 529 0 obj <> endobj 530 0 obj <> endobj 534 0 obj <> endobj 535 0 obj <> endobj 539 0 obj <> endobj 540 0 obj <> endobj 544 0 obj <> endobj 545 0 obj <> endobj 549 0 obj <> endobj 550 0 obj <> endobj 554 0 obj <> endobj 555 0 obj <> endobj 559 0 obj <> endobj 560 0 obj <> endobj 564 0 obj <> endobj 565 0 obj <> endobj 569 0 obj <> endobj 570 0 obj <> endobj 574 0 obj <> endobj 575 0 obj <> endobj 579 0 obj <> endobj 580 0 obj <> endobj 584 0 obj <> endobj 585 0 obj <> endobj 589 0 obj <> endobj 590 0 obj <> endobj 594 0 obj <> endobj 595 0 obj <> endobj 599 0 obj <> endobj 600 0 obj <> endobj 604 0 obj <> endobj 605 0 obj <> endobj 609 0 obj <> endobj 610 0 obj <> endobj 614 0 obj <> endobj 615 0 obj <> endobj 619 0 obj <> endobj 620 0 obj <> endobj 624 0 obj <> endobj 625 0 obj <> endobj 629 0 obj <> endobj 630 0 obj <> endobj 634 0 obj <> endobj 635 0 obj <> endobj 639 0 obj <> endobj 640 0 obj <> endobj 644 0 obj <> endobj 645 0 obj <> endobj 649 0 obj <> endobj 650 0 obj <> endobj 654 0 obj <> endobj 655 0 obj <> endobj 659 0 obj <> endobj 660 0 obj <> endobj 664 0 obj <> endobj 665 0 obj <> endobj 669 0 obj <> endobj 670 0 obj <> endobj 674 0 obj <> endobj 675 0 obj <> endobj 679 0 obj <> endobj 680 0 obj <> endobj 684 0 obj <> endobj 685 0 obj <> endobj 689 0 obj <> endobj 690 0 obj <> endobj 694 0 obj <> endobj 695 0 obj <> endobj 699 0 obj <> endobj 700 0 obj <> endobj 704 0 obj <> endobj 705 0 obj <> endobj 709 0 obj <> endobj 710 0 obj <> endobj 31 0 obj <> endobj 24 0 obj <> endobj 719 0 obj <> endobj 12 0 obj <> endobj 720 0 obj <> endobj 10 0 obj <> endobj 8 0 obj <> endobj 721 0 obj <> endobj 192 0 obj <> endobj 110 0 obj <> endobj 722 0 obj <> endobj 48 0 obj <> endobj 723 0 obj <> endobj 32 0 obj <> endobj 711 0 obj <>stream xœµXyXTeÛ?ãqŽGÃÝ©™²¬Ì´ LË=EÌ ÷… BA¶af?gî3ðƒ¬Ã"2 .„†¦f¦æÒ‚¶¸•fY½•••=gzæ«÷F­÷ºúÞ¾þø®¹¸.ÎóÜ¿û~~÷ýû=GBõíCI$’~‹WOð÷üú¸øDÙG|˜lû¹tRð¡Á§¯s¤ìâ0Ô<­Œü‡P´D2/øÅÀĤ¬”ØM1jß'ÇúN˜:u²o@BTJldÄßÅ꘨„5ùï»"126Jõ´o@|¼ïrÏŠTßåQ©Q)éQ½±’ÒÔQ)¾‹7F¥l¡(êñ€µsÖ†Î}aÞü ƒ‚/ Yº|ÅÊU«×<7yÊÔiãŸöóŸðÌÄIÏRÔ#ÔTêQjõ5M=N¡ž ÆR㨧¨ñÔÓ”åOM &R“¨g©ç¨ÉÔêJN)¨©‡¨AÔ`j5”F §FP2ê~j ©Õª”¤÷Ô§^D7÷Õ·[º@úóa¿¹ì06¿ÿÜþðÎ}>ë}>¨øÅ îÁó·™8äÍ!¿ }pèô¡ê¡×† ;4|Ýð÷F¤ÿ.Y¼ŠäÒ­sŠ ë$m®y´XæZ(ãj-[!ÌfýV|Âý/yZDLòൖ|^[/¼bí„:x›o±¶ÊuË ºŠÁZѬªÛÛøZU ‹€ÙŽÇ œ N)J‹žËµè:lç`ìƒnK/”Ø*…bv+|©q'‹ƒÄBÙq|QŠÓ˜^D.‰SÒ誤Åhñ~š‰^¬®ë<ð=(ìÎM–>‘°"mæd9p‚¥˜ï2ØR@“Q§Åà™ò§ÐrC9XÁª€Ê–ê}‚Ý)ßÄÂFH‚`a£Õ¢#ôlsÊ Õ±è!Ü$ÇQÂ×éÂAáÍt—Ðem‡N8É4Mˆ-‡`J+ªÐ<-Gýp^¡x°( ?%3ÌâݵÃöIt;œ¶ìå­¥B™µ”ÍfB §(§•ô{Ÿ7WQ¤âo;Ð^§D¼òƹfÉLñ•dë*‹ÂÁUñ^gÑOt;äæTN“`Êäb!Lñrñ!A’Ûß}>ãè¤Õµ_½Ÿ³ÏzRâlÜ#ëBVû¡ø(ómÕó›¦ÎõÇýUø ü™,1êm`µmSu£&)ZÌܪ~&ÒoŽWtäãJ¤]kÄOdÝ'ŽîõÔ-ž´$A,³& BGUNf®.ß SáhìÀ÷£}Æ °ƒ h9ÍJ»3† €(PÄÃb!ÚJž¿eæm±è)ü•<×ÏÉöã5\Z¦)Íqž”v^ì%Ÿs°‹#Ñ ï2¬iVMÔCU+šnï­Ú¹)TšÓ5ž¤¾£]×"Y±Ñf4s<Ç+y gâùU‹åz=X,@>‚¡(ìØòº`ñ×à,„Ø=ûQóµ7T7®”[jLœt¼Ò°5`nHÈÚåÙk€€}Ž¡…•€¦†¨žýìø×À"Ÿã˜Â´ÞBžW Úb($ì*†›]äH vŠ¿9%ÇÅŸi×£®‡dež²eFÈPº—3¡8MÚÄ8Ñãç¢Éf~Œ[ãþU¯5›@£È·C½R gÞBuÒ&?=蓲5þŒòžŒëÙ¯i4öŸp…bÐ BÔ ´Mƒc^<_æ¥û-óí7+±_¶/˜9JµaeàêÇÇüÁ{‡ÍCÕ“NÔ¾SÒîšB»‚P™,…YBWá áýzþUT+½Î¼ÓªYÁåpÙª&f?ª!ùä>™˜> ؉L'2ÙÛì…5‡2H¹#Kò Ë¢!O– 4©û$cŠ—:˜3å†tx^§zƽô™×LEãíHVüÀSá¤×'êöàG£6tQv•9ÛªY“ÅesY÷bçøg$û;™éBÅwc³ z¸)|Tdþºû¿…6ÅwØ.‚*öÁg°ÇÃÑÍÌ M±ÃNÒ®"e¢‡¼J¸‰râè;ô\ŠÂd…vûYðº—ø –MIB"¤Ã&H÷ô…“9_mHã¹,^«2'éÃ9­zÙì˜@`Çã'ÐüB@³?E÷©N]ûòÕOcØ·#}¬î'äAÑêu£FyoX,š|eðœøÎÐnPàøe¼gàùH†‡ éW/ï<¼KU–ÖYF–ÍVÅzÇþ)'Úé$ÜC»ÂÅÛ2{[AÙ%`Œ§‰g{šx#Â&›w~³õÌÛ¥†ô^¶©¢p–!Gª³;­åW@ñYD8úEýŒIÅ^8OÿŽ ¤3Áy…›P(«ö£j):̄㚰hÐï’Ø‘w¦EœL£ËâÏ$/kùU` ÄMÜL¢âLˆ¹ ±y·ìˆ ¦8£v:(RI´]Þsß ¡ƒŠI´V͊달%½Ñèþ'ïDkwí£Å8qŠ E¡YçO¢VI\ã>!¿§šžB7]~2ý6‹ & L»›Àv¦ªÍeœ¿»KnNч†¿]¬´ìZ›IŽº¯å |)(ÊA°Ûj¾Ê š‹»2ƒb,¡Ä¥Âk¼`Œ—7ôÀjðÜVÕ\÷óR/1Óš]Sš$¿ü &ߤ]âXš¢ØGâ•äGg£d@LBah- EYJ·Ò=Z6fÚçÈog߃(Õ»·>í8ì'?„à9ÓRñKýTAã¦o˜ì=}ØÓŒN+sû{µ£÷dh:ƒD#¾F}>¸ŒRáŸþê0ÿ™¯‹»îêÖ§Ìå“I3s¹XíFUú”1þ¤Ú#=¢pm$•æ p^w #Îa¢éøáájQƒ¾’ÝtÜ~¾foŒíÁ#•ø¬gØÿïX¼~DqÏü‘éðWQ?IÁOoS~°ÊÅëa+ûì…Í=×›nUØÍEz­Å á”ykbcc ç^ù¨Qh€F±’)™M1u©Åì2,!2µ­ ^(­+P”XÛˆ©f?ø0åÓVà~Òæ±=þ-¤êAE=´xíŽó1Zø|2lyzÛK{p<Ð÷|_š5bW¸ÊÝl¼’~9]~&¹`!d³3ø?õø¤Cˆ©(¨reñåùS6§ŒÅa¼ŽØWNa´™Š‹¡´XÙ}¡޿þ¢“ÜBCЀ:þpT·*aÏæâmQ¥ò {\‰ÁW¿³z.\Gôk³Fe[Êa«R úr›]°Ú”^¿Nï– ÚåO‹D^¼‰–X[ †èYÿ]Ùc’øT.™hp­Gƒ³¼×$íC~¥{Ñ$Ø Ph©çíq„z¯Ç©—›6sy£€"ÕdÝM øFè†[ð G¦­4Šynk±C€k™ÇÒ’Ò=@$yÖ§´+T¼ »×;QüzK,¨!Ț🽳 ßL%×zú“ä†áW‹äåPi«Q½#ŽýÓø»9½Ø-å² òxÄwS‹îG €dõJ¤z×(i„ëeÚI\¶£sgó¸ç²ã`¹5Õã²T&gky^Ÿ£ÂÛÜé¾"¹'YlP h;M½&{®Ã:XmU{—”«d’¹‘dظmPÖ‚¢ó¿÷¥É ðþk&ý«^¼"+o¬ßwQðÞM¢¸ÕÄ1GC°5Kð\§Ì©z¥å˜è¤Ž3˜t8Ó)^ÌæËÀF\þÎÓ°]éÕÂî"^Â=†æ”qÅ[ ôå @G¶4óq„{"YšIF˜ìÿeéY¨€¢°oÜ?Ê­9V}ùf/µ—"›h—_vƒ-S W …÷ì ‘Kkq\ýro“äêEdû„FKÑ5YÙÛÛn¼y®¥ãзÉ\Ýg®ÚÄ <Ý’ªNH­ÍqØÂÙwW4¬À£ñb< ~² @Š“‡ê_Cuætõ‡p‚}ÿÅŸ°Ï¼õ«7¨•§ñ%Ydhó—6ø±­GUÕÑùÞ¤;+mPçáÁÉ!*c~ôìЋ¦^<{¡¼N‚Ãhñ#Âô¢âÂ"¨c±ÁÄŠZU 3o Ôný¢D(·6Øö@+é€pæåuÓ¢×/ ؼ$-<ì©Ü‰ e³*Ò[^-ìt(«oî@W¾òæëÜ$9{¨ã0jÞO#3ú\G-<œõ¿¶ì[Ò¨ìwhÀ•u»“k•ÚBuµ®hO-¢Â-öÊ샓1=ÖLTUØ+ Jä»M–X¿±%³2¦)¥:ÙSç]í9¶láÊ¥›”S—˲OD4f·¤·©!”1qáÓ3VyïÃS?ëTö"ÙõåÕñ±&Ò×WQÁZœŒÞ•iCrŸyiA\hhx0ÄCDa¦Óf!îئíuí;Ô¥ÙyŒËæôd½võØo©>Aƒ Ñ88È¢QK.ÁCðpÜû/éÂ,~öà¡ÍJüp€,$iÿéö*4¬é5UyCç©÷}£õÅE[ÍÒ–ªÔKÃçz$H"#þë6J¼-ù×/4*e2ÇÖÆø¸Ä„„´ªTg{Kk«r%¾(kK©LMJHPW«[w8›w’ åyùBŽKºP z/Ã5Œv™yœ‰w×Þ-_:ù‹EÛê]Ò$©÷ÓâQ×zYqIׯ–iK´Fƒ%K«t›cÈ#ÃլДèËÊí¥%öÞ:\r‡äÒèó´Ø(®•]OBñ/‚Ff(#žSã©°ˆ ®ÄcÑøË×^Eý(¢ûJÑthfq«{­,.¨õ=׉jÚ>Rí½q¦b°ÛÏi°tÎÌ%?¯ŠÄÒ4‰½Ä$x·säkô1-Žv —YKzQVè@£œ4œ•׌4Ã!8Þ<É]+7ÅóyãïÕäëD°pýó›ÀÌÌ¿wñ!. ŸþL–ûo£—oÐb šC<#oÈÊÍ6›Í“…ƒ—¹H¢Ðsϼu¾k÷Ñ'ÏÂ,¢Ÿ92œ†‡-Œì0•µ¶6îÞžUh$—w³²ýì[»OûaûŠùsâ¦áØG…ãðz­Ö”¹ ±ÓËÄk@~8EØèÿA È~tCV-и¥&­(6³O„âccf–ŸIRî7´wÀ.¶!§1&k½vÁs¯þ)…¤?Ÿ_svR­ ÚýÚ-8Êž^t| ðìÒÌòÔöÎÚö¦}‘§¼…ÒÉhÌOÉvk¶óužWŸÝ¨,1> endobj 712 0 obj <>stream xœ•X TWÖ®¶¥ª4ŠJ["hªp7â1&qCDqCqmвƒ,‚‚tßnA6A„ÙK܈kLœ¸ŒÑ“L2F’˜Dã$¹E3™×³LæÿÿóŸ:Øp|ÕïÝ{¿ï»ß}*¦oF¥Rq –¸¬6Õü«½2B¥Œì£¼¨’ñÓk]É0@ ú6Œng…—‡à–A8u0£V©Ü<6, ßi7~Á»i³fÍ´›¿Ã?|ëŸ`»%>‘þ;|"éÛíV†lÙêû’ÝüíÛí<ÍoDØyúGø‡Gûûõî½ dGhT¤¸Ý’?ÿð`†a¦Ív YºÐ5Ü-Â=2êÍhŸߨ-~Ký—½µ< ÐsëÊU^Ûw¼<ó•Y§L6}†“3ÃŒf–1c˜åÌXf3ޱgV2Ì*f<ãŬf&2kf³€YÏ,d\™)Œ3•qg¦1o0o23˜EŒã̼Ì,a–2ÖÌpƆ±ev0–Ì`fcÅh˜¡ŒÀ c¦Ó„1“È¿ßð~ñýºûèÿó !/Ü0wà°zË—-aÐëƒ2[^8¸sHäO­Þ²úF“ ÉÕÜ:chüÐo„ á‹ai?«v{1–?«ýCÑ^V•¨»Žª•à.'!©r7ÄAìKÙK Ýß OÝ•ž2øh-[o8m¬†Sð6œLçeNçù†Œ\ƒA:ƒ-°”½Bì-&Óe_A34ÀC¨£Ë&räK%H@–T[Öòç>‰ÍÛ>í0Y!Kod­5­­² åŽ®ëé—uÇô¼ì†þª´¿S[=W$ån^Ç}ïuÊaÒjϵa¢æ2™—b¡å®eƒŸD®q4ÈéÌ»µš°H¶B´Æ 8špè`­Q°ZyAÀ"\Ä==üúÆ9–L”)~÷ Üã¿pú8‹ÝnZdº;YÍ÷„Ñ*~,¾úÉÃ'_;ß /äHÎäº@<°W³% C­÷ X Iün CÉXÑR¹Ú hLªŠÙ8T­œÂ`m§<%3É+SÇ2ø¡¾†¯ú‰äñˆù´ÎÕJÅ'›JÛ¡ šâËK·Â*ØÀ;aˆF¤qÍ10I²ò“¬ºŽŽJz»º+»kšP 9±É:ÝÞñÍåKμqØlˆ‘8’ ćø ýD#.C „\É^C\b2Ä饽Ė \j³aæ‘5Wµwß…Ïàí dÞyïÝ÷>=x޾š[F41]9ð•c¥Ô[G²ZÆQ&EÕ±¥ÁêdCË™‰C­5w1ÿ&@±ÁPPÐÐx.« øo/%Vd”ëšE Z¸°IJÊóïÓÒB.åš[ö4¿û %´™ú%;oõöØHIóU;G\)«¿ÔmøOÐl„=¥UV:e-ñHÅÔèÐ¥º;ÍE[Àá:œHƒÞ†¡d" d½Ôí¢e1½»SP:Ñž{>Žiw­[{À^¢Ú½:hÓ÷ñK~uŸd˜T'cîyó·FgYÝ€G-EÄéd ðd2Öu°_çzÏ—d¬Õ²ó“½'Š«0'³è •.…d /³Û1ÕâŸ*3œ>¦Çê²¢dPÝ/4{>ŽYÕaÎàhiMq|a˜ì„ ¸›hù­¨×ÇÆC0ï[³³ªª¦´á¼WÕ×-ë<"EM+ZpäÕßžf¦ÎÐjlƒz¸¦tóño2oP.cÙ/ÇŸ"ã‹4‚á]¯ Ýß=? %íShv@´PÖ’X~†û:ç×€Rh@ë° íÌ•Ï9DúÑ€èù/2©&eDU}“Ï-ÜMÿ1Ÿ?eá­ìEAæ¯=‚â»õÁ«2EÃ.CZ)ðG ³\ú3CuŸbüİüÀ¬-Àï 4÷Ö[JBK⤆ÀúÔ{ ¼¦Ó”z7q¹í¼)5*ìNón1­ €€ÔH‰¨¸H>œm„C¥¢ÊeÛ‚ÎA ðÕø }óκÀc’_UPÖì|3FÒÇSÆ”¢Ÿ¬ô—­Ì´™ˆ£×·[kvu:/T‡^ ˾òI¸ñC™ Lw?XAá•Ákq¬=§‘!‚ý"Ãv¥38W­¿æÝ‘x >ì[réd{Ù{'¿†ÿÌ â~OM—K r×PjêÉâ@¶ 8ŽLÁƒ'ž¯¡ÌR›É¤6àÏ2Î-Q=£”ê/«q‡2J ZMìq¥–Õ;¬?>ø9ÊÙ}uëƒÖ‹wÄóÚµœ{PDÈ ¸^.öò3Õpž*í¯:K ÊXk"•E·…ÙºfYÈÜ’½pJÒ´*T:ÿ†¤•ܬµ«]æ¤W\ñË?üOg÷QÔ7•·á~ÝDÕ8â7âVc%²2ë›>6Ògøš“ÇR"²Z®1ã ´Ñç 4š1ÆR}î³é)³¯T,«*•³j%C dìϾ´Á„ë‚õᛌÑ^ËW¥§èAŸ¶G"<É ¬´¸ ³ÛtÓôzÚ¯6}é¢ë.èžù`S¹¹¥fL± ©Ø!ã²ãèh²ªÁ~sp:™ûN´Òÿž°6þC<Í–äÁ‘òDH”–èëå<­ZçÂwÉOb¹oÆæº˜£Õ5¥MÇcŠÒⱬCðwë|æJ[)0¦“ìd2ÎvŽ}ÿC¹±©LŒÃiÂdnÒ”Äðµ[êZÁég2ÄÞˆ)#ŸÉª2势A½€ýpX~AVöÇ`Cq§[£O£Q¯3†˜£.€<]ÞÞ}© Û·o¦ãð ÈY4Èl˜ÞCA4êmtÑ-§bMâb`ØP0ž3dB\Ò•ÐFÉÅÆdfÀ}@zŒ*ìC†YøiÙJÃUã ¨VÝ ºf!÷3;J•M¸¢ã’‡Û”q¶ý¦Å~R÷c™+,.:\XÌkšS´{uŽÀ ÏzôÛñK2Îe]ðÎ)‹t¸Ÿ;Zwºªƒê»%®ZXæ'ûnL Wð»°çß›¢5)—hjëCvAF/"t;~c+ìÖïÛ£×K„£<Ò`ùòîQ‘¢6¹/›ÐR2rö—@"âÈÖ࿵²ï•{—®]Ý—'6_NÆ—ðåãÈg$ÀžX½.1M 󨳖6 СímÀa(Ô¥§çK¿&XVÔ= 6ï“ùœ–qÊYè¡£òýï“LÖpšöSëÖdmAìGÏ £Èð/&ãø«§TTKë9\œeAãÉàc}WQ¯F,Þ< *OIUMrn5\„† ²`Þò§áÏÙz^Ùw^ºœ…¤<½!š¾knWXˆÒëCÒ#Òu4|¸¹3\¤¶ Îõ6œ‹…8C¬18CO%—WJ8%­ûãÜÝ}!Ø…œrI¹ËA™Áp,ãH†Ž_!³þéžTJ}`MTp‡¡HXW•nÐCß=Á ¼ACÍ’çq_íµK)_©_ê–Êráhuêug¤·L«»Ñc:9%Cˆí·Ñ§7ÿPt8Òâtiñ©RôÏ EtÅ(=Úœ•Nô5ž24•ž¨lhÈ«ìFbm47‚͘¤¦.¶¡Ç:ÍGGuW~!àv2ŽZÃpK$2ž¼E¶ ƒ;1E‡>bw_rUX.Ç|?Øv-å<€ëoùKãÕ—i»}?¤áÍúÅûç€;¸î›îã¶ÉÅ5ÊËì T›}{ ¡Ôñöûn28ÈZóûÉ‚›–ýCǦ}ÿr2GíæÀ§,öù §"3tÙ⮤”ˆá½ëb*×”66´Îž@b!ÚÏÓÞ5;]+[ó6±½ÇéŽ$#i·¯AGóNMH9èÊRbò·©ÚôÿwòªÔíÜcm{ÛÿêÙ›©2×›•™¡ûÓ"´ ÄÛq‹aî‚…0‡L’¨©%M8ùë[&Œl´ªùÒÕ¸ÕðÐõµæÇ$<€žÂ ¸ÑÚ 7>„76m‚7fHÄrÐqVWA`lÇý›rø‰]…ÒñÂRãAƒ.M— ©|xQleeQñ‘ò¸º»´é›ÅØ<ŸÒù´žcWÍvõ-ñ­‰”BS·A4ìÚ¿¾!ˆ×t1‰é.Ѷk;æ¡]ï_¾y<å7jŕǖÁ$£í'Ͱ9;©CîþCYøkÄ‹j-[°$ÀÏ‹ #Ö·µ]y ¤çsÉ/Ĥ¢×+}=ÃÉ÷ öÛ°±v…”¨ÇGìï8ªyÜ}濌'ÿûüBk¶)‰I2…ËXmÂêÞªa2N´CÇÏÏXkâÑ„ÿ°ûsèlœ½t%¼BfI8)Z@þøÙwá=þ)éó Y.vþµ&ZH:1ÐBšz ‰Õœæ ¹€º»ê­5ÔÁ¸À›°þæÖ–¨kû¨ßþ1ÿ³Â2*]Ñú=‰z)Mµ–Aò­´&ÝÁ”÷õ™ 7WU{ša<7¬wnëÄ©V÷iÃéo­G©¬ˆ‹9—5¡Õ†vc‡³:ÍÃNó4W¹!´Ôúxz{×67™j[~1)tŒùW³Õõ¶ñýÇsZ­5w{eº@ÆUoÉYY Wmš]ûöç[ÉÈrqèž{H\ÜcªRôú=Iâ¦Í+ÚåÐÖG&/˜4zщ¥QRûúÚ½¨Šà5Ò¦]}hW¿!ÌmÌ\2¹'¤ˆúÃõÜO.êñ“9Fcö±­í½õRÁg]C‹§¨~õ£©Å’eW#…ÈýKª&÷Rv¥P#Ù5Sø§3MR-d6-r?±Àßë¾Oµì… ÊŒËô¡ÌqTîÀáÈ}-—°=ZÙlNÁ·½J‘Ϋ»¢”…ÿŸ†ä¨d©ÖY Cë·EÅ ™ó§.Ì›>Àßì˜îɱ¡ÀVáôü;ÕAâóº**ä‘Qcd×"á÷-ÞŒë:ù›å¡MWkƵYmÎzýqŠ÷éý±Ö´ÿ“ü§í×jËvÎùï“üÿ¹ {¶¶qìÔ5ë6†‰;MÉð'ðÜäÁk>úóܯÜNjÆg¦Ó8¸ò”Õi*àKqˆŽ´Öt£~%s€lisö¡#òÓUªµéå‘i±¡°ƒßZrêÔ‘Êúk>ïŒ"#É,g’)j~‚×s^kt“ç~q“J˜ôõßÐíìïQ+a®ô=yGX¡§R ãkàæqȹã+˜ç`óíÍ7I¥JÉ+Q¡5J«òHÈ=FjEˆ7 Ä!3aô~}Ž.—ײ$›‚)÷ƒüüýƃYAÝs65‰ô]@FÏ»¾ Y…ræ{b§3NgË97J/×5ò=Ñ+ÑÀxÝÅ¢»^Ì3Ù%BˆÏ )‚ZþægÙ Ÿœñu_¶us°Ø.Ü4U·À%þ»©­„%’ëë“6ö¸¿YÔtÎ|k³ç|[2™µ( ÓG±23åõÇD2×]¨‹•C;¶·„ŸŒ† üLÇxÏ žgïß?ß\WÒqs)i7áæ Œ´£Ž{¾H[„b‹…(\’—ïÚçç½É b!À¸£$/ãd´òµ‘Çüü"ÂüÝÏzÒÖ2 §}‚9´7óÈ2zü«Ä–ˆßÌÃAuröÍz‘¨}…Ép÷Û'ðá—ËWïÙ/åm£cÛVÞ#lÜLñ×û¦gò_QSl2{Z\ŒÖcÌâõÓÉaÿlÚ|ßàŽdA DþògÜ+“8²0•:L=èlˆ«é~Â}ò—ú/ªJÓËŸÔÐ8ØÂûU…™NVU4žÛ|ô!ƒÉX?ÒOt =š<3Ç|÷†.UùxI·ÐExL.M4–d”þ´²Du]ñT+Æ®åBfd/‰?˜–*vú×Ki»!ô6; “ J3óeõäÙ¤|nRµÒ~c¾cªÄÛÂc=¦T’ª'ÉÆH<¦â^#Æ}+’4" °²,ñNò9øtÀmx÷À¹¼Î›¹Gà$4Æo.z FÁ,X S÷®IxÉ#a˜E"Un¡èÝ/¨ñÇ.µP¹aI:Ø›,ÎñK›2¿S[ÂB‡ár1ß]@$-×’ñ´Óç‡Þ+;s”@apGÕ˪‹8ÝPT+.hÙôÉ‹ö&¥ÎƒxÚòXùÔ¹æÖÈ~r]†¯xäÆü•ߎK¦-?½ëHMCÙ™s>…»ö‹UGêš€Ðæ>ÏÍßÝu¡D6ŸÄÝ ƒ6±Êü^% &-NÝÆëÍPt¤p–¨$¼H?©9¢=ò{ü^x¿ôÎExÀß›{îóÂìůyW‡Ö·VÔœ¼äupŸA¬;Ör ø3oKÔë1©’¯N§OÓïÑëöPó¢éNŠÍ…Ãb ‹*˜°V ãÆ„­Ù|ƒt"§¢ùÖ êÍ>¡k§=^Fyä~çÛÏ;‚Ð'ö¤U²âZb…wpaÍúTYS…ÇòDe{T—­×ïÚ-’ïºß´Ðb#Uù¾Z®>ãóžkÖO¹fÕ<¢ïN°øŽEOàW©Ÿkú []DÛWÎã6m&`n{ý¼:=H+âpîXÚA]-Uû/Т"[wpwºö%IžQ«S½a.¬.ËI¦–?øHŠ—H+Ëòûd‹§Ú.äR'Ñ 3^“4?¹€á‘yÑG4«ŽÐàÏ{ŠØµ&yéË÷_ÆÁèôä3´-“v¹$Y9¸©”%³9¹?²/ˆýûÎ,Я!{Àd h`É0ÿ¶¦úÌ endstream endobj 13 0 obj <> endobj 713 0 obj <>stream xœ­ZXT×¶>ãÈœcW&'‚š3¶Ø–XbCXˆ UéÒa(Ô53ô^f†â€€"vQc‹¯Æco±ÝÄÄhbö!››ûö4¹ïææÞï¾÷ñ}(3çÌÙk­ýÿ¿öÕ¹%‰$óVÛMþ7Œï/âtâß{`ý/Š–$+è.†îëL ¬ùÅ}®×›‹D —mœ²ÕÇ7làˆù#ÚMŸ>u }€WÈV÷íÜÃ|½ÜÃÈþ=¶z…Ehïï?pµpGèÀÕ^¡^!;¼<Û=?0 (<Ì+d C §WÈvŠ¢6Ùo_?/pÃü  ‚? Yº(lqø’K#Ü—EnYåáíù±× ï•>«|WouܶÆÏÉmÀºÁL4múÙ3†~øþ°YÃ]FÌ9w”óèîczl3n¼Û»‰“&Ϝҭ'E ¦VPÓ©!ÔJj5”ZE}H½O­¦†QŽÔpj 5‚r¢FRk©QÔ:j4µžšG¡6Pó©±ÔFj5Žr¦>¢ÆS © Ô"ÊŽZLM¤–P“¨¥Ôdj5…ZN}@9PS©©iTÕ—²¡:Q¶T?ª3Cõ§¬¨”„¢)Žb¨­Tj Õ•Du£fRÝ©ªµšMõ¤©^ToÊžêCYSRêХ܍wE]EÝ(WR2r;ˆlDw;¹w:-vŸè¼¤³Ùª—Uš¤“$HòÎdì˜è.}»Dt9×uNWc· Ý^v/ëáÙ㻞 zÞì5£×ÕÞãzêcßÇÜçkOë+Òïø¿ó#ÛønÏwÏôÓ×dcosȆ·õï7±ßwý·÷ÿe€Û€Š÷Æ¿wœË”±²ö¸uЇƒ{vl2pHü_‡:¿o÷þ©÷›4ìÎpnøáá·‡ÿ4¢ËˆQ#-3 FÞ6h"NÖ)õJPÙBBx´›P:ýU’ߦŽüF’Pw¤ï°0$¥§œHJÑEÚc±F²»èôóy/úJyÂwb‘†®ÕeâPoÉóºÖ.Û8‹eO’Øç¥—/À—ÌÃñwð»\k'ÿrÉuÜGÖZNKòQËgs¡þü ²}ü诧_Ãâ<™¾Éâ>uf­ U •ô÷Mã/X7}¨¬'¯’›ù &QÕ]´ó®˜÷CÛXôÎð׸î3 ‹pÌþ8uA=~øI9Œ]X7Øl :²>…zØ'Ê÷Wh§¸elË,¶2åJ%$$sì½ë× ¶xž‚'a7ì>Àvèc4õ;$CLdÆËA‘¨‘%ã!§c0ãõ»P3:†Öíú‰MÀà 2]¨ €)½QÖÞ5x­1ñ¶M!fë×—QÑݾÒÛh>zÌV7©næê§“°îñÑT{/ÃÞ Yœ´``ÖtNirú ÔíÇ£¾Çg¹oIŸ_¤ñP¡®d*6ËZ}ß4Õ.í1]TB³ºî·ö›)Äî1€‚]ü¯$v^+æ÷· `3sÉc2™"Dp­k$rne–d"«·Ñ4òP;I«m+N‘ƒ’m£ÓÁÈñî’bd° ‘$cYäXì ž&þšê¨0÷€—¾×µÌaýËé7°|ÊN4qhZ‰VãþÈÏ‘áwþ6mÃ%¿»í/$çàrxó‚}+³§À,ÀâÈ>#‚V¯BÃô:û&›£Ìë]wQ!¡Û|ïOY¼èÏ’ÀŸ §½&XIŸWÅo9ÿaÌ …ßÅ}žCÌç{÷U›dzäÏâA4øE†‡ÆÇù¹3ïãGˆFÝ>¿ûå­¦Ék…jV ˆÎZPí.ðm4‹[¢\6D‚Ç…ÍÃsINl;:Íð˜~žë÷ÌŒJB$Säþ£8;”"iïiV‚ÆBåš",cÌ’@nÕzöm#ßfìK’]‘Òò–v__|ý ¯ôš{ƒEãH?ú*S§ÒD$@0hŒ5•˜ójjü«Ýæù,v‹ã¤×Q'ËÞço<½G{HWpI—ì íÕ¹õB€Ú³B€‡,è`{€kÌhˆYÌßl™É¶üç%Jêô7H¯í…'mݶùu2¤y@›ó&ô©‰ÛFsSPFGèÝ%h˜‹0GB'ñi‚)¹‰ÿ Ôº¶,ì0Š!¿úJ!O´–5)ïÄÀ|f½¯Ç¬©>§îGrª|MZ"0ñ%Ã6t4¤ä¦kµ¥¥œNº’Òýî4F‚\úà_¾8°3!O¶­Æ3Ë=‹‘^wÌ]œº_]ÅÞ¨Sº¿ŽÓ&ejaò!½Tö-@ªâ9•21I©òªÚ±¤”=½;úV†Ëj‚«_ÄŠ{ $’d@!þ}‹5a’ùÕô•Æòϳùá¹ÀdCV¡ Í£÷¤¥FxË[³F@ôèð!zTC?Ö˽eËhé!ÜK“—âum$²¡öìÏOìðp÷{A‰ôï9ʯÆéÄÂQãðDìŽÝÑd< ­¾z«âÌ.R@QÊה܌†P M3ˆ~¼Œú™ÅȞʢ!<-‘h¦ ©dÂïãj÷z–P¥êÊîTÈš8RïÅð¤˜k·ç,h—¥ ljùþ%[¯Ë½Î•[$¾*{Bó^0|IH½Žãñ1Oÿé5¿ñΗDwÃ5¨#Ð ¥g D…è.üókÚYUn o"mA¼H»‰äûßdíh44×ÊB”œyDF:Ñxøoè_HOv^4oªòÐ1Ýïxç¨&Êð(zL@cNî¯:WÍ‘,nð†Ò<£p!r}îM®Bˆj&‰Éf¶EUAßÔwD¥’Ïä‚…ß$ëÝ7ÛVLÏTµ¯˜0—ÜÈ÷³ˆJù81?=`³ËŠ÷]¼G˜z»& Ba“.ZÁMnDB’Z©”¿³lpgT£È'hÕÙV쨣: ‚ÀC@„>iŠ|4#›Œ8]j>äCZvZŽÀ—¢¯©pÓiÔ™ßaíEÑÈbô ÁŽßà¸V±NûpÇòvVÔ÷Æm¶¿²âÑË«Ÿ_Ë•i³Èóv1üJzoœ'ܬöÒ¸í^$ìzú;ˆ÷•µKj{X%‚1ý;zÄ–µä× a…“°Âa;¸ê"…°ê5¦(ò—Ô©ñp¶ÍT£ÌÓò^¹ äÛ5ëÕ¡ÛÛ£j€"uN|º"7 3r Nµƒ ©ydUio®oÏ‚Öj}„ëBž*ÏYãŸmÒãôÉBté? z›—¸!M.¼d›ú¶Ìßcж ?cåãÃ&ë¦ëÎOÑÔËWÍ}¥1rôà+6Í£Òý0ÆO nËN†8Ò«BòmÊér¡‰‘ÛãÓà¹gC‘30Óº, 0DWT•*òRk7ie•uGr‰¹9rÊs¢Ì›–•¯W}¤Z0wkÈ:ØÌÌxrþâÁÆC¥\ šÆ§ÇÌßêºqKÝÑOšî¢éyâ.g‡<~(?•E‹‘}VÖñæÛ‚· Vù‘ÂûÀjØÚîm3 b“SðE|Ì]ù?öß|1ÄÓ/ÁÆŒ¤ìxH° ð$þ@0±ÂP»ÛL,í;ÒöwH² OQ1¨%°;wï>R^a©ß[xHÀA°:@LêºV/àÀ¨ÎŠ'sKLb|ªÂa–ͬ’“—a ……Ù†¶ë5KÔ1°\´AB]?­æÐŠï1kã²Ô.«W­TïòF…΢­€jhR— 2®OɇB0U×~úEµg–|φ,y~ Á[RRl`ÃwjOêLÄìÑìl JVͼ!¹jBÞMDdQ)qhGÐ\¾‹>ïðYmÒúÌLkµY•‡ilXaÓ†/û¿ñf#¿Ç’Yn.Q12=.bÑJA›[´çä'YåpêƒË½*¶èWÃðV¯ØîºÃßk›¸‚Oyh±{z(!>ÙŠP®‡çÚ)÷¾ »mÖBþ~qâ ÚÚ¿“Þßpµ‰jùHOâ”þ°Æ|‰¤Ã4¹›Jîñá„}î‰ùI¤K+Î7k‹à-ùD‹.\¨ŽESM&±D:5aÖØ`12)sÔi¤í* ”k/Oôoäs˜Zà‹FµŠlRãã¶)âÃ×.\©dâŠ,±¤e™ ˆ©ˆ, ‹pmò9z~ï©SåÅ „ªöiƒYDlܺ§b„É ·E¥€x&¸$¢ªÂP¼óÒœ=³qŸñ˜Â½ñ;ß ÐìWƒºçä$‚Šð£BÍm·4Á˜µ“ö¡)hê¦ãÙç5>u„™ÄÙ–74°Š/¿-FŠ–‘l’IEÆàYo­ŒŠ—¡móè2ÙÕ‘v×8UÊøz-딟NPj› ú¬´\¤iéa£m½"yÓH úKmÇ_ á·FâËß4"ž% ФDáÀÖ³6푃™‡L]|1ߟÍΈÉO†(_%V| ±â/KP'âg$\ÓÚ#IjHµË$U@w‰_Aœxîºc3fHD]%¿“EÛ6$“´–^œIïOØ%4þVùjìOKÔow«p껉Y,ýn’\8°«Æ,CÆÎØ&øPË£œ]ÃÝÐV„îÞ«:El_ƒîlõ£ewí B M±×Üh²Ê¨ß }ªøéUbÛ2‘MÊÓh#ÉRgûWK Á )Ô”©´ˆdZKÿ´ÅtzªV“¦àÇ´>·ÉNÐj2)€ÌR„®„C¯(}5ÕÛ`lÔù (~.A²Ö9ô[˜Ѽ¶)7é"É8ŠaMz0~ïôœô3~(ùÝï§QÄê÷<€Ä¥9ɺÔ$µ"Y-ój‰°Ôì®@çÛF8tô•E Ë,š%AÝuûÅw#¾ÆïÉðëßí5ü©ˆ¨P1‹ÊÚºG4 mtÒÓ„ ¼¥ ­>}¯ A™uÕ±ˆkhÞµºc}¥?£4— /Ê*µ5…fYV^YU#0axXÆ/6D–œè̈,vOà^U)0Ï._¾ÞÓR&«ßUŸ^"ì€^#W¦Ê!‰ÎO(Ê)Í,+N¨ñŒØ¬Øâι׺ë÷páìÍ&/óY|lÔ6ðe¤-àŸïe‰XíçÌüï× ž¨ëÍ7êâš×Wqk«VÁÇ„Ý Eë—¶Ã5eÅIñßÙa ›Üݰ_/;#y€:çFv`¯}uÙŒz™øj‚ŒdfEû_ˆùÂLu=~½h4óO(qE£‰›_j©ËÈ®æ ÇŒÌËRdÛœ¹ò$Mr¢F¦prpÙzÁë³Y'î|P4ƒòÑÀÛOŸ£SpÖ¬«LÙ™Råm Î!ŒÊ,Ø0êö9éGÖr«N¨.hê59É z3ƒ»´Íà™Z]n&Z½¾ö¸eëŸGD³ºÜúuz±äÎTC—Rô5Ú–§Ç~ZJòò òò2FÈËõlGiפ)ËRà ?˜+L3@%Se ŒŠ^w2ðÔµsžpÒÖ–q«CË·o ݾ½<´ºº¼\Ú„Y„$~ºÙ7ˆêÍ(ëÊ2‹[ƵLg[‘$²m{«M)¬E£¡„/GmT‚ÂŒ­7˜óð—ìÕ¿„ƒäçì%Àð CÁ.AÊ Ì JÒr `KIßBá¶<¥mû¢ÃþÒÕ(¸Iôú¢`€‹X.5ƒxº´+gs²Î77錂­Ý®Š‡@âÜtq‚D•jräq ĹÂ=mø0ú;ª–°v5ì„FM£úMG½¢/|r}P“#DÙFF+#ÉUUÚ3:#1ÃÕšjá*o¯ã‚ ¼ôm7”-ÁPưxð¨Ǹà®f´šãûü›q¡!“@ôãgHRÌé ºJ×ÂA{}4Îê­à Î:Ÿ·Úû¦ ZD„JÄ$-µ,eÿExÇuf0ÅoxK²-ƒˆ[mq·ˆø;lACeõ%mÇ–±0LtlÓƒ‰¡KV)Ô ¼¬u‡ väuŠ‚¶a¹ú˜Ûv’¨œÁ­}yŸ ~Õ Å¶þb“™®Ê‡bÐ¥§;;öNÿtÀѶ³P÷ÿuÆñ= È7Ú+î¡}®ëÛ“‘kÿx2ò÷ÎbâFÚ’WòK¨ø—A$y%§öåì¼~€Ú_CækXÖž¼¿h Û ªd’¼Q­[lðd>^“¦Î 3ùÎÓPÑ–¼Em pÓmî8FÈó1}dƒe­öx /×è‰Óÿ‹«¯AZjž7rim±Ñ'éóÔ%3-MçÓmЌ֌ömÛ_fr^fDs_‹P_šk£±üölè7ߨ ààâ zCANá4V«FqJ¿”ùËd Ärª˜”tezîݯPW­}÷¿¹, ¼Š\v÷I£Ùºé1ò|ºôq_i+²A·Ùre ÞõÍåMŠ­&.Ö\ýËcME;³÷œÝ|x~÷'¶9X&ý³àóWrŸtâ·X¼È{½s‡ºákìr8«(Œ:·È¼w£æÅ㢃à`áJ¼a=gØí°ba?!áFþ³ëyZðTÌñ¯Ùla÷ÃÈ`¥÷u¾²” ‘lÃ[«é‹²ÏççefÜ€|B½yÌL, ßf‡ûoÃ2xŸI׃á@×LÃ'úO²N¤•<ØîX½¾mäc ¢¯ÅhMËX¶6¨$88(j·§ÕY«MÎÛЧk‹™=xûÏÄ+¤­¥IÙѰý¨bØÑ¾Òëh*¿‰Ý´S¹ Š™O?kºrõºù«=Wør¦Xö‹†#Çà"ótâ© Ãg؋ҹ6¹p¹ !f¢>VmŸâ8¢ß —‹BVßÜý¹^~À«‰‹4Æä,kd†»³UчûWE €û¹ë¦O™îîéš ÷µ¯¤þé½2~¨PÀ¥O‘')àϼ]aýh?dÓªh'Ý® nVu±%´0<& Ésñ‰-÷Éß“œ©2aúÒÄ5£\ݸ-®aî0—Á}¾‰:º·ét‡{Ïfc`øŸj€£pNÀ!cCåÑÝùuD5j·»æù¥-‡MÌ´­£&q휂×Ñ™F4®5ˆN¶xŠù"dË¢0IA) ‘+Ã>ò¾š#)l)N†'Kn &­NŸG&ïܤlyŒ*^®âfà“Vxå¿~+L ¥P(C><ΠϑĶ¿T C“%³p“F­J¥­<;)·HŸŸ«çn£“Vhå¾… oÙ¶µ­lû4‚˜ëÓ-¿ô}n¸ýÚúäݯ—š¿~ÚWŠQ:Ájò’{Š(Y [ˆí:)*f[ 80«kf¡~¯¿µ+¬ LôÐÒú4.`½}ôF`¦À©#Ÿæeçe>…¯éßÑì?À[hQàëvÈò=ÿù"|ã¯r4š-ˆyŠôO_î¬4XŸl^ÿôåÁÓõÍ}¥3¢tEÝC2GA(,v^<3‘ñGÍ,n¦'¥»4ÇŸKÓdiÒ€©,-­¬ÚQ¢ðPoœx|<ê“,sµ¤ʾúŒØ†»®ÍIÙû}²óé¯ÇÉt_yxs¡£R«Ö&èoŽ5ê÷i<_rwÎðßDcqâb;˜ œK¢w{îJnŽgžvƽ*”ˆó8{èÜ­¬ŽfÅNEþiì‘­b–8YËìS’£¸/n!¦Zý¥ÓVL×VËejsuY™âçhBØ&¤7=4YŸ<‡V›Ñ áw_é1y‹}‹ ›‘­ÓC#`.15%EÁmX´8h|æ5Ç"‹wú3gÁTÜ÷øbƵ«§¡ÎphÇ1ÙgÞGSëá+h¶d¤i56­N³KЇTPÛÊs’rrti¹Yœ™ÇF,ÉG3ЇŸå7ÛÆÔºùëdÒ{r~Eëð?|4î"Ñ+.ø_íØI ·ðý-¨È$jº»û<êoFg«Ä-ËQV5sÙ6Wp‚uÍ~»o¼tðæž‹ÆºG‚ÃðV;iÄNmß~qöÒW„ÅÆÜ]à`¿f{Æüº‰\Dø·?×MÁAàÄL¾³üûûgöÕ6p—Wœ‰9Lâ?J÷€iõB{Ù [ªÓ`aî5ÖÔ…!ê%3&‡sn²&—€}¥õë¼—­vH fZØó·wÕŸ8Ö1W"[L“Œ·ÌG·Ø·œÑúíoÝσײo ¦õ¯¿‘@;ŽÞHír¢³[þK›{ì‰FiWl3ïÈVDWúDÄ%*œF­Ñh€QCAZMæçÏÉòÓ3™©i©òisp×å®ûêJ*+Åþonk?îÂzã/ŽÑ÷§ÅèNa‰ñÖEã>ÈÚ­4мÝhê…úäw|ŽR¯H´[„¥+¹õ¸S_5+÷ø[Ž,Í&#MŸ)kç:AÑå'—HG<5ª{~·êt, ëçWê** ÆzhbN{\Ç#1å°héÖ²¸2á<à€;Äq–ã§ ›ˆ(‹`‘çʘ¨¨(Ù’ùáã‰t¹ÒQ ÈˇìŽžò‡D÷[t(†„ׄô,Ü£kÕ ÔkÊg„QJ¥BêÒ(Ùw#NáI€½ÏñÆ polß^1Eš2#çñ%$=Ã5£NyH ÷˜v(ÉM¨‹ ]0œþ4#ê2*¸Œ(³˜¿O¼L£ ã¢%1 Ñ*27_Wà ÌÐ1ã°5¶þfÜ«‡«›vÊrÖ‹Ü Ìׯ~Fñx²ÅSð2< OÂÎx%âðlärìBfáYEê^ELN ÄpIäCÕªúÀc\èX`ðRü.²C‹#‚ÞGÓÐ{hî„ãSì–øBs¡láA¢@·cóòõŠ`æ¯x€ÄH|æÁÕšÃ1Žõ²üH¢:Q‚mB_ù~Ñg¼•G ‹dK³Ó2!Ï6_^“¢†È`.4ÊaSHT!šmSŸ#OˆOÌÇœ.œÈûã¸\5(À6F/OK.N–¡AK°lId’2lÕ\Ë¡?ÄâÙV±ù‰ùE¹yù9ñˆS›¸£>×ÓUé*½* ˜¢ÜÂü\eVtVG»a}ã/cE¨k£ea=Û8ê—1Ïñ{¿ÆÒ하fDÑAƒˆ·jócQ4‹jÞâjP­¤J#" 2ŽÃµ¸–Ž{+êä/ID PZÀýö=-K²Ñê…o  åO…qû(ºËefÆo‘á²?›¿x1­“b4BÚª5jˆFzwEV’ï4žÛYŸfඨÃl«ˆ/-++ÚyfM“ý8Üm=qXòÛŽôtþ½ž‰Ð‹ŠX­V·,ðãÍ.2…‚<\ÙÆ6y7o"úBè^7U”—‘•óûP‘Ò o Ô‡„ùœ—’0ÿüùü¯´ÂJz[I ­Ôùl!„Ï Æ"Ç!²ÿlõÈÇÂâm$!Ͼ:øev%$UqIʘD†¨¬ØbóeïFÊ>©%‰Åïy<ÿuÌ(ôžðÍ' ­8-ÊE%bTV°§qÉ*Z€p–I¼RÌ+QkjU†Óo³ çIÒ3b’TÂ×VðÙÖ­VÈü.VIŠïbÕÑþÂÜyû•uügX{b;VS¨ÉJ€DP¥j¢=[]l¶UFUTT–Ôrš\«¶¢N߃úÞµ>ú½³E>f>'´‰Eݦ¿À”³[Œ¯‡ÖÑEmJ ‘â^Ÿ?ÉÏP¥§^S¥Ê"’6F,Ø”ébLÖ«Iiȸœ#ÃGˆ@'dêôi\nQÉÛp Ì›²¢Š¼už°‘þ¾°"Ô=ÔÓ;x̃ÕÇ£Ïè5zM.0µÅæòòhó¶8ß”MS.Bóò[$¶Ø9uVºIDèÊûⳇb~p¨C[¿2’G‡øÃCzß]Ž+7{)S¹í ŽéAÀŒÁÌ:Lýgt…¼ÿÍ)˜×,²¢ŸßiúìHU$p1ªa»R¡ ©LRÅC$0˜¦Û$kS—§µ¤Û!0ÍrþÇÿXa> endobj 714 0 obj <>stream xœuTkPSg>‡@ÎYñÒ³b—=¡·­ZQ U™vJ«®è:Š „[É… (,÷äM4E äB¸$€-ƒÐ S”†ª•í–QÇUk¥Å–m;ýû±ãž€nÿtÿ}ßÌ{yÞçyŸ—$<=’$…‘1qAÁî× ÜŸHÎ߃û³ðþ¹ÃsI^à-oÏ÷ý©{+QÊ ô¦/ \NHrÇî„H™¼H‘•‘© x)r]@PhèÖ€p‰X‘•š" ˆIQfŠ%)Jþ“°W–š%V„çäĹ3òâÄybE8m¡u¤L"ÏWŠ1²4±BJÄòp©L®Ègåì߸9(8„ ž'Þ!þJì!öûˆDCl%V¾Ä b%±Šx†XÁÏBPËH%9ï‘*ðH£ž¤§Êó?^¬—Íë{á!áìcrÇbÙcÛž¸P²‹Ûn#¹ÕsÑLÍ­©J@«QÃâùïüJŽÈrwëh)uÙ`€³à„ MK»¨½ÂÎÿL`0Ö 5~È(ÁAÆRЂf$¬”r¦ø'|wJAI­\3ƒhüO/\,ä1ˆæx œ¿DÄ8Jp{P Á©ì’ž;hÊ‚õ ÞVYHë~bÿ2/)5Q[• Â-TRDñ]Ú Ã| /Û] ý"Kýr}ôÊ•†øX—þŸÈ ]½ì19]K”7sÁ6²cuL ¸Ã(›A̺Ÿ0½_~¯ÄÏü¸ Ñ’™Gh%‹³q“Ifé ¼_÷1|=p¹³ßùáyóûp>(jOë<Ñ™“{P–xH%zqP¼ß…6Ù¸ÍäÏãÈ<)@ZÊ,"Ž ,о´«@#jv1hÕÆG˜ 9]£]£°È=ø SÕaÑ|öïŽÆfÀ ú:sGÿ µè//mÆžxéÎWÞÈ‘Ö[ EJG± œîi‹/=!üçO~ ×P 3Óûà«ZèN°•5ǪANKef›­¾½CîLÞ"ݤªfuH ÄÏþÿNÃt@;|º r!¡­ëñm*¶å6n‹…<ÛŠúè&÷ccy¥*¿¢ŠÍiÍ1½ 4öÉØµ¯ 2{2E]²÷ª*FÊê5­…–âú|ÑÉŠÄ]‰=?æ³5ÐëôÚ5 º ÔE"ìOú´Q¯·7±Æ“`h4÷†& ›Îîª8%Êè”›v‘˜"àÝiø‘¦À«¯< Ç®£Å´w#/?’[QäÂT^p«P1Ólëìߦ±†¬Å˱߿Ö#ZÚ»I}¢ºR«VkE¹[ßV¦ò‚…‹¬”ÞÊÔ¢ {'ü &üœ>ËM¸ï¼›pº­š!ù‰EpóL[C–›_ —´¨Z:-mÍ,fq,#¥®žªæÙmýÝx‰ë` Þ[ðPñœˆó¤žVóê],ùæ\³¸% òÌÛ+0ÈËÓÀù?{,:¿À>÷¼‹´ÌÅ8ÄÝdNµ6ÿZχÄkµràýaàQ×(ƒB¨mu ~g¾ÜàšÔu`Ã×he]Tž6 ¤ ƒçθfhLEŸŸ÷3–Ô Ðúã'›ž8­ [kûöV_ Ùw ÕÜ _4Ë òíîî.“XÙR1ÉoTµµ65º†Ä_áýç‡,ÇNäs‘¿CDkᅵý†¬\„|ñ ’Ñ {E[ù Ü §ºøfÄ•žÕÈšÓù)’!’TbEbÆÑTxªÇ ywF€¢™v¥]!-T*$­*G{³ÝÉ>Ai›{ÖFöM¢ZþìCŸ3p[}3còÈíÈæØÛ¥éÛdÑå1€ X2¢{û¹°ëyCp. ¹Æº¿4<‚1'ã/˜w!Ê¢BdÙ%˜„p ¾0Ütíbç‡üÑSZ_­ƒ×yÚÞ†°²XöˆVešøéu篢ìºõÍ1Œô…lžü@úZà9vð‚Ž´Ñó*CSÂæH…í†þ@Ÿ…ï¡:‡ ÑœYð¡»Ö§èßÓÈËEN£ìÛ.½Îä 5G+÷•«ªˆ oÄa»ãòÕ¶ô2 ‚ø;´ù+þÒ;_z5þ<··5v9UVY…tÖ:1<0ô¡í›¶$„Çíá$\à•Ç‘ÔS‘ï?BiA>®µPüCžl„™£ºTÐåF°°Â;=omÀ«wf&$†:þ!u©]è¦]6Y^n‰8ø~„Ûo÷Ì~þÙ†&önëèçð5=:¶þÅð؈ÔÎÊF{KcGW^C~õ¨ž‰i0}v¼xJ³Wš,’ÎÒÈuô2~ÓÃ츭ÉN qJåZ2¾”]â¹ÕæýÛ)oïq³·Aü}vË’ endstream endobj 9 0 obj <> endobj 715 0 obj <>stream xœYXçÖžuagDì³`Å^cIâµ Ø@QìXiÒE¤,}÷ì‚Kï,E\ETK¢¨‰FMŒÆò'Q£¿Ñ˜D£‰Æœ!Iþo@cn’{ÿûÜgÖç‘Ùof¾sÎ{Þó¾³2Æ¢#“ÉXG—Ù«ÇOþ;Lì/_ï$É|Ý"¬5Ѭå`mqðõ{{á=1¬;ŽïÁÈe2'gwÇà­Ñ¡~>¾ávŽÃíÆO›6ÅnV w¨ß& ;p_ï@púG€[ð&?ïðè1v³ì–IW„Ù-óóôöêx¸cpàÖˆpïP;—`/ïÐ †afÎ šì¸uÎÜP§°yáó#DFy,Úæé½Ée»×bï%›]}|—ù¹-÷_°2pÕä)S§½9Ìa¸õè1cÇŸ0qÒ]f ³„ĸ2ƒ™¥Ìf(ãÆ c–3Ì f8³’Á¬bV3³™QÌÆ‘ͬeæ0cwf.3–qbÆ1ó˜ñÌ|f3‘YÈLbÞ`œ™ÉŒ 3…YÌLeú26Œ-ÓéÏpLgÆŠ dº1Ý™LO¦Ó›yá™>2+fM/cÁÄ3_É–ÈLÆv2våËå -öZ.´Ü©°P¬U+ÚØ2îuî@çy÷w~bfõi—À.'­'X_è:¹kM7Ën»ïžÝcbøžCz†õêÖKÛëDo»ÞV쵫¼¶Ïì>q}Þí+ôïû‹M/›7lBlnØ´-è7¾_b¡ÿY±K·ßäK5 ˜qœY\X.7´Nã“K5;à 4©ÉÑD×ö“Mr h‚ÓCÓÓ ¸h•b—þ,ÔB \…J gf#À‚ó2r@¯ÏlÁ>6hTœ'ã,G«{ô öÀPMŽbÉ]1†G޲$±Šn­–`­L2”£ 7 L.îÆ3ü·žïNŽ.¾3ý-vRéI–*ö\x)Ée'[©¿»éÑñl'ôc‘¹Ñra¿1l†@jþº€¥*ß“"|ׄ•fÁîø¿øºü@ël^õ¼í‘½J\Íâ´›÷~;õ隣ÄÁ5»oÁQîÁ”d’@Vx¬ÄìSãô5s½Ig%N¾àñ]tg±s a68û½IXe·ß:MH`RÄ~&Y=Zc>ZËÅ æ±ÿØÇd<™2iéCú>ãqÊÝÇØK z²”'};ß: ï–5(+.5Ã{аµ$¸ÜV;7GxF1*‰7ãªr\hDO³ìÚ‹º&y«ºu_ ÂLG·có«f-I"cȲ™xâp25è„,vC«’ݵ´ÊD2Šð«ÆÃB˜XêvÞ·Ñÿ ß]=zúÂõ'¹Çà:`W:2GŸ˜ùÀU‚¾JIëEVšqˆIìÛ {FKf â>2’wÂåŠêˆæÐ³Àဟ¾À¡(Œ¹Gú»®Žòߤ<Á’Y¿—°-ûÏrñûµîÃ3®Ä† q\½H¥ª8@*ß0‡VN|DË6{‹¯Ó²5¾*Û4—£-çŒ$£°;qU×_úòâ#ÁÞ…Ë~ûWÕz–­Âé¼c•ï:ßõ󷌎ên€„ˆ&3“nmƒÓh&Wb%$Ã7O'³#ã°éŒâa®ç eÖy(fª=F ®XŒã8L ‹Ï5)‚PmÙö#ÝÑ{U«¥¢Ûo² ±L®Ÿ={Šœ½0‚7eáDì,Ä&$o‡hÎÓ´½ºÚTrèøªÝîoû9yÄR¤Ëdꟑ~&©nBò$ äN§GIÛ®¥ŸÛžH·mÕ:o»×±E­°Zà¼C¯"¶X{Š}˜½qvG ³“6Ž–c-RàD¨ž]HºÒ覵0)&Ñ®NÖø1Æ|,»Š3ø2ÈÚ‘¢ÄBZzBrjzpñfƒpd>±GD}ª²&Õ”’ †‚÷q¹Ú¹øQ°R®Õm.ÒÕ„e·ArQ–ŠË…]e‡}OB)؞žùh{,ÄUªôÜëgX‘»(oIã>¼F”æ†ê]\¶„>#dTJ`Ÿ%5€»YìÕþ hCáÛùÏÌŠ0øÃbX‹õœ 퇰 Á›B£âÔ°  ]®zûО–\>Üò¯qŽAì¿ï§‹ŸµRîõ/,¸|È-¦›“5µ·>kÆå²hstm’£8„ÇÁf2Ý<Zw‡tnËMRÏÚß ¿r­ùô5¡Åc» 0(` \¬”z<¸B*ða3–š; |CŠ1¬µ/ÿܬ¢1úÐÂhŒÏI)¹¥ÏÍìŸÎK½ÁÖê‚züµöxoÃ=ÏÒ¦¦u玿"a|..æ_âp5;cÃâé3ÓªO ø%N¯ªf‡] ú©êÜ4 º78Ë`if]’á€R´ P•U’—;ˆ†€»ihaVøh†=†T'‹¶GÄBÅ6èŸ@=ž@ƒZé–¶0©F‘7ËÄ$±ŸU”™}è°ñÑhÀ¶‚–Ѱ5©ÉZЦª•¤3É%<$#ë}éAš8šKOˆkß!›óÄѤ©•Ia±Ñò= m®ôþ«é&ÖÐ5gØŒ¤q™‰)¹a šôdmú ²Ô†0X&­×Ì£«ýÁÛWãè¶žYÑ™É`›GQ—]þKmž“âœéOÛ È0d•J,5ðmJô¬ÁI&Ù^Z OiFªðÿ`ö9bïF¬R§x쉮©«56–%—nÏL9UPÜLJ¼§)7±d™¸‘ÈÇ!uéÓwššË•›Aõ½p\ă c"Ä*uP •‘æGO‰ö_ëi:ò2õßí”°¸õÜ+‹~â›<&ↂ¼œì{`kf—ÐJl€@˜¡R¢* J»KÍiÙ6+rÅoÿ‡ÀÜÂ>ý½É}zf*¤Ù&¬…AÅîÑM…C|Ó>Ä·²+ m§ºë€íŸé®î#P-¶y9Ù_Hr£ò£UWA°´¡2cj2•0rÒpìjÙô²°¢}Å',Ž#ËèL›œ<lUìY½ê)ç6ÁnIÙl‹Ü™¥]V¶ò Z¢œô·ôP)ªô)/×QŽ•ÖÌ}ÑBýL¸â8¥|Ì“¦¢WëBþcïû&¶¤¬¤¬¸üøÊS 阞ߦJdÀèûd€ëºmþžÊîü¾c'J›èw=€ô^°–…mV¸¯SûÃ<Ø|,¶Bоê»?Ö¤•kŸXÉN1´Ô󳣓ÏÖ¬X«™+a3Å«¼‹ï¿è)²Î$~h–UHPJ»ó†ÂÌì îý4il,ÝQˆKOOѦKµ“¼†uRc…ÑÓ»¶7Ö]Ú†¤ÆÇ¥ÆÛFnðwš i ½®.9S˜10 ,Òo]³ÇÙ['¯5— ÝÄtÊ’T?4R4­ä¢/væó@£ÕƧ ÉÛ¶ÎKG¯=à¨ÃgtØûfѤjµZV™ž·B9½Û«GoÖ°‚8Í¥úˆ%¯;‡áøzä²(v-FÚ¿ÌÓ°£â3é9uØ›'Éâ¾D üHÊé~4/¡Õ†¤Ek¢´ÑÀ…«•úÏÚ¥Éçí¸ g¥t„eejuPÁ‰§t,V·ý´3Á .Û0äîÌúÖN6:)ÅŠý3ØKgP#A[|ôÜLüØHH„ÄHŽF b* ÅirÑYÁçä \™¶ äWE™iÙ¤0|[ÑŒràî+H}›˜@ŸŸl•储EQ‚k-=Iön¤pãDž”PƒDßO$ô‚¤7°ekhBHìÈ Ç“ÑöÔÑ2Óå*^Q¶ÈYÛ}Þcñê8:áIÀÞQIZѨ¬?}ÆP ‡ 9Ú´‘{9¡:xTL9*Gsëd^§ÕEÑëBþ‹¤šX1©íë¼x¶l«ÀP©o²P¡ÓíÊ,Õ—ëJéT–w:Å]0¼ áw•l M]UzmšN \Ûd Û²Åt£[-þ£C~'>‹«1„¯4@u]òõõG•MnK%]7yéE잎Ñ8òðó’¢£MKQ†,\éNW ÑbÿÓÊZ ý!ÝcCÙž}fJX9ÄZ·FÊó&¾±µGC» YˆöòÖJüšG_"àPJÂÈ2Œø´#ö¸•vh>i#ù…à\ïýžûÕÔo¨þý ãö¡›/_©>CUÞYUí†ýKó]èltH˜ºÆ)Ôo¹jº¤Ve«^p†Q³dù잤*%m¡0“.OÏ>*6å鵃°C¸"¹M{¢wU45òiš3ŽÈ½ ' ™¥ºF~þ[U)g’¥Û5bK‡ÎÆ£4$ªßçñ |ëë;O‘u‡LS¶ê ÅŸUöñ8¦Í[SÈX%Qb‹¢Ã‘õ{pƒë{0n¯¬þ†=7Ü’c\È 9 Ežúôòñ †ø\emqUf‰>=•úÌ8.²pÛ®]…eƪè=*ÏÈèHÁ³Ê+g5-ްüsr=›ü”Û·EûÒñ¢ªÜlŒ Kq ‡eœë‡óÑß¼}òú—KkCó÷ªE0‘zÙªSeÅ7Òñ˜­+Ê+à°‹Ÿ—ŽKwï‚Óúõà4Iyš¸óW/Ç­òõ]JˆÏéÆ ç¡HùÒ©J}ö7fuèÚ9’„ÿNñGÊÿ¿4«ó&ÞiÆý&l0÷j¯G#Ú÷í½CÜ%¬ƒé œäž ¼M\„6Ëß ò¬½ ?¾˜ªûÙÞ‡±‹â 쉯©ó£¾}>=<ûð½¥­î‡üû…%IqÛ´ÉqZeꚀÈ`XÉ“¤´$_#Œ‰Rp9O:c½ Nɘæº\;‰¼% Ý© ZÄãßã` Œr k•ó‡¶Ô{yøy{×û:`ª?$9d¥¡3p3— †Fz¡w.âHinÆ›[Ùƒ²s÷ñê}9f‰Î¼CEú(䎛ÎHz’éÓIá| E¨F›ï>£ÃÓnÄ5Ò%jLÞ$ ŒœåAèÉ´ìXÜ€»·œ8óÞæo ^ìÀ(¢U~¹ Ý$ígò9¹¦”Ö|É@†ïŒ×‡fjò4¹œ‡b ÚȺÜìË%y9†/¨#âp‚ªJû¸˜WWÂ%އµÜüã]]X•%S—Ö 8º-Î_ÿ=fñ ÷ž½!½<±àßÝuz?|Æ=ÛLdÄvÎŒ+j–\óˆåšmN°ŠJÖ'nÔÞ;ܽA-Œì£«w dþS>*/¸’îòÆOúÊ;Ç6,ðŒV-Û"ÎoðõÑŸªê¢MÛÌa”ÒÞz+ÔÑÁ­å󫇫yòÁ*´:eÂ_¥¤÷F_|M.öÅ}ü\ Îd\€Ovq¤Pk0a×°µÒ?dËösO­~J—Žùó." ‹jåÙhÝônÑ'{¢XÉ;ÀÍïÂ]”]¨\–©Ì Ô»ÀnnÔ—}Kéb·q°·‰\û4ðÚàéi 8Ð1 Z,þr®ãZ8«ýÚIÒû’˼fú· ‰IZ-¤q‰ùjCá·Ñö£-§Ü6nÝâåSís´¶´(;[èxåB2?/§ef¨Ø³"IkÖ’ÉÄ‚XÆÇ·ÇŸ;sô`Ü%ÐT±£3à|®]UàÏ'®¢µQzYˆ^”øžˆËù42ø Ký¦UîÁ¼ˆªÔqaÂm® ÛkÚ]ÙxjÃûC‰‚Œò#]…¡¯tÝ?±#þŒsÙjƒÖWI®ÿõ[q ÛMì‚sÈò±EŽâþiËþ^ϵ¼ò×R¾PuÆŸÝÊeçÄr1±u9O3F3Ï•ÆæÆmK‹MÚ¬DSC3c]¨.(ËÌ+2¼DªI|l’5S‰+½!/Ä+üCÀ’@Ô@’GŒ ˜ Ãzò8ïaQÆÐê˜bÀx¸ ²O>¾’U{àÜŽÂ)T¾ ‹$ìˆ ŒŠÚªƒMI©;ÃÜL«‹–r|ÜÊòµðf-"ré—Œmª2Å>h1,àÚ*ˆRÅ6é„£ôxÞ>ÉöÅmÐ / íq³ì4Ú¢«ÔYzô§Æ;=2Ùu‡:)y:ì ºt¬¢qÏWÿS”‡ò/>>9´²û„ªHË‹F­4館o0i 0d ´d{Ð<ÓqúJGO•’’(u"ÔѶÛÅ©ìˆ>€öÚw_kj}†ÐE’å…x›G ä¾ì ¹ c¯»ÒœSTuÜ¡ ZO  ±OV`wœöùWOÞ ý–Œ­¾¬ùà|Î]w> endobj 716 0 obj <>stream xœcd`ab`dddwöõõ441U~H3þaú!ËÜüÓëÇÖnæn–•ß'}7ünÈÿ]O€™‘ÑÍ'Ú9¿ ²(3=£DAÃYSÁÐÒÒ\Á17µ(391OÁ7±$#57±ÈÉQÎOÎL-©ÔSpÌÉQé(VJ-N-*KMØìœŸ[PZ’Z¤à›Ÿ’Z”ÇÀÀÀhÇÀ ÏÀt[øFßP¾ÿÌœÇRüX;ŸñÞïÌ?Í¿WˆN›0yB÷ôîéÍ&üÙ÷}¦DݤÎîŽnކ¦¦†¦ ­3[ä,üÝóˆk[ÚZ»›$¦4Mëëíž4CޝtáOû…¿—M›6ƒíwâ4öU\—¹å¸XÌçóp.™ÈÃÃÀƒ jS endstream endobj 111 0 obj <> endobj 717 0 obj <>stream xœcd`ab`dddwö Ž441UH3þaú!ËÜý»ï‡ÿÏ&Önæn–%? }·ünÊÿ]_€™‘ÑÍ'Ú9¿ ²(3=£DAÃYSÁÐÒÒ\Á17µ(391OÁ7±$#57±ÈÉQÎOÎL-©ÔSpÌÉQé(VJ-N-*KMX휟[PZ’Z¤à›Ÿ’Z”ÇÀÀÀ’–ÅŸÎÀÃËPÂÇÀ t(Æý OËø~tüî[ð#mñÌùŒßsÎ1_ÿã¸h÷åî…‹—Ì»hñÅþ =ýýÝ9¦5w׫E8wÊýöfïÖí®.̯­-(ðiçhiéjlœØ=µK~[ǃ²nuŽßQìÝÝ™ûÓ¶åži^ÕÍ1}r÷´©­Ý=ò6Òv4­ï˜ÖÝÛ½Žã»{÷Êî}SëÎz/M™ökm÷¥îå|ÿE3õ+è"îÍÌß&ŠÎìžW^Þ]Q+÷ÏŠ½¶»bþüîy3倎?¼àûûùŒ‡ˆ3ÿðÿÞ'úÍø‘ÒoF3#%…Ç&_¾3>xòEêÃŒ?2À|x[´ûh÷Úð +¼§dws46v7@|p«mCÜ”ô¾†îÎî Žß@ævGô6Îð<]¸©á7Wf·Kw>ÇoönçîÒâ¢ÊÊ’b×ö¶®ööîVކ©ÝSß?Ùw¹Wî;0|^vÏ^º|æÌeËNõsLšÔ3âý„>³Ýï9øJþ´_Èö[`ûf®Ür\,æóy87Ïâáa`•BþÇ endstream endobj 49 0 obj <> endobj 718 0 obj <>stream xœz \×Þö„ÀdÜ: êq·UÛº×]qkA±.(Š Š"û’krÂö%°†E뮸âÔ¶qm½ÕÛV±ÚUmí=cý~ßI„¾õ¾÷U‚ÎÌÉ9ç¿>ÏsaoGðx<Á OÏÓÍÿÄâq£í¸ð3P”àóx«×n_/ y{Å;cfÌŸÿÁ×0aОÝác1žXO, &ˆ…ÄDb#1‰ØDL&<‰·‰ÍÄ;Äb áEL%¶ˉiÄ6bñ.áM¬$Þ#¶«ˆ÷‰ÕÄtâCbñ1“p#fîÄlb 1‡XKÌ%<ˆˆuÄlû°.G¡“‹Sì[ì[yoýB‹è;Ç`G´;¯q®r†.¡.çGºü£æúuôŠÑ÷ÿñö?~cf3"æ;˜Í`ïŽñóý؉c#Ç6Œ}<Ž·b\Ƹ†q×ÇóǯÂ;ÖO8=qÉÄÏ&͘T:™æªsUÀø›šðê¹`>4qhÅ!™:„ Pø£A]zg4eRZZ2H¤ÂꀖyIVԀƦ8ÀVÿæç’Õãâ@hX ¨`_’Ú:ÐX’^(ÏeÓ²c€PhMŠ>s@ΤeIØaô4:þd‚ž¦N_ÂÜ[t3(ÛÃ,'%BAb1cY—“y‡8><ÿIC(r¨"ËÌ㣀”OJ… ,´T³+Ѥ%p’ƒ®45 ­¢ð£:PÆV“p ŠA.HëCJ¢ñºµøîoÖi¢ˆ} ·ü‚¶8ˆbþúȼ‚¨ÛúX#ô1:~g‚RÓvìÎæNÑpùM•G°_ˆÛv 7GÐ×«ŽŸÔuŸA±¤Ì¼‡ZPÎÖwÉH§W‘}Ü£"¡ÃÕÎû¦í7T²n¨˜FN02ä7Ë}¼÷®ŸÍâ…ÓŒðK#ï’ Öšø\ Å+¾÷ ²Göf!§¦A;h÷ÃБA»ÑÚÕãÞ³ïnܸuûºûô÷<–¹²½„b<Áz¼e=YVk±ZÒã¼*PÃŽCI²³ à¼d½KM•ÍæÇ5xóz¾®8 5BAï=8À6“®1»)ÉÈåy‡Mðó«|NÌݧËAmX|zrj:£ÌÊDa°a§n+Î-›0¹£5ÿ ‡CêÛÎ'û£A’B•lê; ¢ý5}Îïp |çÑïW/î\PÊf'dIÕô:³]Hh„ïáçÝY©ÁAy@-}åòùkw//Ÿ=u•ûªÅO3h’ý‘ÝÇÍ€‚¼Ÿ~€NpÈÌŸÇn÷‰ b~jP–úÿ%‡» ÿ)‡É^o^5ÁƒØŸû¸ctaЀBê@ 3蜒Ì.ˆAÌóF™ó°H€vÅ'KAHv ª• |EîÏ+hfŸ *AUP ˆcV ƒ wö‡&Xaâ_å ݽ2¶ªKCö^A?Žx ÇÀ9pö8¹°HÐuŠæd?  C;Îs õÛ€† ~?ݵ¦ïÚ“C[Nðg"üê6âˆØOœ†œÐÐï§@»ÏO¶VëYâÝ'Ö m±ö&WCHoôž?ßÕýæ“§7M_Ý;±ÄÍZ«0Æ}-áa:aÚCòÇOF:̶s޵šÞi3}5Ò œº` !ð’– ª’yÖýXâÇ Ð*·½½#hJ+ bºúÙê»±o‡‚ïšàêG#œN@!\GåG8ˆQGkãjU¥+¯×ÉÎÛº&~­'ëd:` ÙÙ2ýêX`»‚¥¶F€øÝ«›x/Mp4¶‘—B G“oÜûh ³ß°÷a6ìï’÷‰ì{6G{‘= Àñ¶Ê¡ÆN/àY˜O‹râ²…¹á9ƒO¨ºæ¦þU•ͨ²šº Ä$0×^t†,UÉøê}Çx¡h~Àû¯žÊX§gm)_%n¹o_ðô›Šî ™ôŠŒ¢(@™#ÂNH€°± \ÝZÌ´œWpáÌlþ×éß­Ée-…gáqܘM°§ÔfèOט¯ÅQl0X›À¨<6&‹µœ«eût|Þ# ĺáÖYÛgî>6Ö"}þú´ej»dBÛÕ_›f, D±BòÍ-Õ}OsV÷ ®þÑL«Cô PwÈòZ‹Ãe¬|HZòê/P„wÆyÈ"°¿™Õ‚¿( §š¢ï9RhheþðŒÛˆ>¹ÈVlè’!¢Ïõ¡>ãó®3ÎÁ{F^ Éç–ã˜4öqL?›±ñÐ=ă÷ Ñë¬F гâ ЗJP ŠöSV”É4ònuÂÕ8.SñN{\7àfÛØÃ®÷ȹóÓÅ)ÛA]8““›“ Ê©±N(Š‘†¬ýtÇóξ3ž¡‡®&È7òʹ$>·Ó¼e=ž/Äã¾JÆG[F%ÛFnCgTdF]âIù‘øk™E VRLfêÄdÄQ*Ò žuh³2-÷¾]Ù«¨3G”-= \ƒì‚ cícuiv¥&s½ZQ¿œ”â„ P ZAvyNÕûÆçFÇ‹¦]ÐÇ?–³k¦«BO«ÊÐ Ó»“s³SX*¸µùk4a×D°ó–¬üøVç7oܼ޶ÉÓ–£ÏÚa,ö÷Fî6-ß/ÍŽÔ‡}Ò ½W¿÷Á8.BMµ]™%åª:àÒXœ}ˆå4µ‚Þcûi„ª›¾ ß2ò.Þ†•·øÜ"¸‰ÖW‚VH®ù G¦NÆÌwð‹I†Î§žÔšÓ*>%SœÊÆlݬˆËÀ²3’o)õUºôΕ‹7Vk‚ T¯zi7Ázš@x™†Gc ÈyÄF¢cè¨>zÀµUõð(ƒüP>= õò3ò³à¸:ÀçE'K®4?÷@‹¢Ì³x^ið+“6'mŠŠ z£‡áš^kúéjÌ”epŸ²|мÿhd2 ö¶èªË WÉÂ%;g3[&ÛøË Ô1©þÖØðwR7E]k„"qwRâ¾±*ÍBRwž<{æú X$êûd}ø9¤m“…‘œÌþwòÇc«·lÙµz*Ž…¹ƒÄ_…®—.^…;¯:6\›yÉ'—7Üáôï$(ƒ+éÍ»O¿tüø¹ GwlÙèëëÅΤ³•‡Dm€zzçvg£¢!ÁÀê‹krJÔšÈêÔB@i«‹ªÅM›“¼UA;YIQ`åN@½»rÙÜ]Úà21너$‰"&l$,È]}À‡ ‰šój| ¾õªã›Öø3[ë™Ä¼ÝU3µŠL‰ %Ë,¶ä¥I¥*È9Y¥9…€®Ñ“—;^QÐܬckË À@uB0ÇwٮɥÄêÿÝ7"–.Ó‚JMÜÁ¤*6¥$þ@jÉñŠŠ–‚š à3p’ú{‚”4u£I·ž¤m§%pÝðGö¿ÈüŽc¬ª~[·èqÄdØÍ´Û¤ÃmE§c<ºM>=¾~»·Ï†éì z†ÐŸ¶VÁêÛ¥Q­ú¿ñà`ÒéÌ}ÌÕAsDU,ˆ»;« ц$u­æÓCÍÑ óó0›¢Ü—Nž¿òÕŒ¼A¤—õÖÖƒçŽÐÿùj¼¿g°ƒI[õݸ>Õâ€:Р> Ú–ðãH§œÒÞSQc0TU˜žÞàxî,¿áÃŒÓ+” í—ÿy? BrV'²óòJðóa°Œ:B»ƒ½mqF¥F¥Á¯gu*O©y.WÏ|ñàüG®sÜ6®°45=×jä7]ÂY={ ¹¢µA( ;J‚[´Ú¢&¶Âwárã]EV(¥Ìæ3è_dZy¼Y(1»»» +­íàù×zn¬ŽŸóá ®ƒ>ï—£Pøel ÊEïgù0j?°7ËOU‡™ôAŸu8ë‚ú†ú‚ú\ÎEpžê*þ fáN£ãq“§ùÓ|ò,ƒ]ôríçÚOÿóþ¥í^=|—³ÿ ¥¿ª?Ñ.QçÞGÐÀ-ØxrÛ?£§_—Å®Y¿lä”g³à0èøôñO÷ܯ¸ê™E¨™žçÖn2^¾öÝÓKk×­vÛ4ÏŒ·ðj°%Ž?<üùëtö© üD¬ùÓ²}K¯³Zškµ ·B­¥àF¸ëa5d~lÅÁ7yuÂÄûØ n¬£“ÑÐÅoOÅ  Ž-ÏÉÍÕ`QP¯‹Æ%„…T¬ÄlÇ·¾aÐG¦!¾iâOš‡Ó|<Ú;§=r‚Arè[>»ûèVûícQ\9[\¼s!¥J ÒAzŽ((ÏÍçY⤇ãnÂI7á8¯…óæsvðú ²¸´´9ëFVÀI§m7üÉR(Èm.”—P®’KÑ ç o¼»„”‚ÀÀPÌ~FÆ£IÞ¶Ÿ4d_š oÊn(ÎbÊá`‡_ßp Çuñ«e† <ÀpƒÃxpƇ÷9{º5¬.Ä_º¯1ªùPmSƒ®Øÿí~ç<ý#—ŠóØñòõ5ß¿î\sÝÂZOÂúÓÄc>`+Øê³cMµJh$øhüª¤g59…ù š2Dkã;ç]^©$fŸÕ›Am9sHWžýÜm¿ ‰õ&¬p¯`ÆYùÖä”t9H¤0˜ÖëkŠ[¿ô¼ú2­,B ã/@v‰k–W­Áï[JÝ´ßX¸å 8 NŸ>ÜQHYi)ìÿßí^ßeO'nöKSÒ2e©@BIË´U?^€öŸ†5ûDEEhÛ,®è€ã:`fßÁkiïhÿ¿øÜŠ×ÃèœÂ¬\ŒþRm\tªXžÎ º?We$+ÓAª‹¸\RY“WÕ;üæ7úî¾+Û¶í[ïêÚºþÌ™Ö+w™Ù+i¹¸þøñÊúââÊH__q¤œE›¹ûôý½íÛ½ý7,[üɦÓm‡.ß³Ž4?RÑXRRæç+Ž›‹­]ÏùêxíÜtóçTº(¯$TRÕâb‰"S¥1è!Ú£HKLb˜ŸT˜ ¿EþÎ¥ŠlU Ê+‹«+ñÝ<†nÖ:»c„Ã<ƒIÓþu;tÆ&~€åV“­‹¿ßôläÊà9‘[õ~×â.¼x®àc¿X¹m³Ïä]y›ôk™”” k”*q´$줖žZñŹ#͇š˜rñ±­—õiÃç§÷Ge”2*Íð'JÀ>àRQ¬oÑ,¬¥ÐZ8…–žSùÔ庺ªY)Âã¶mbâ='© .UíÍUh£÷m H—Ê'ùZýé¢âSç,mÈëæÃ›¼Cœ'Ÿó€Ïéâý¸ ÷ay„l.ªý¸¨à+4.mÅO‚q©¢?Hy0~ÒŠ¡Ó<ÁE=\ÿœ÷ùð{.þr_«_p|Tt¤NÔ˜—«YLP¤‰3W,Úɦ¤'§ãä‰×ÊJk~7AG毡و[UÆP’R”œ‡¾…þβ‚LµP±\$ÆwSYx¹!üJJµÄKT)//ÈV”š'›¯{ª«ùP}3 ÊRsâ‹ÑЯwBíÁóC…#¿+/ÊËeT~º.*íBΨ 89£es~ù½M5€ªËÕå³Ý`3:vtž|>ã«ß1(ü³Ä4œ*¿ôìlCyk8Gµ a•6ÖÛmSHT¯¯ÖŠÓ Ó5L­áTÞ'€zùIHhTŒ\œÌ¢‰ ÁL°‡Ú 7j0N¢åô›ð¨ÛŠƒ˜²½‚Whì|xfËeíÑ€¦Å¥H‹Rs3Y8ñÊÐ,g&ïC,5]Š[R)š¸Ú¸ ÷ôëaØY#lÄ¿xÇÛ¿k‡«p®NàâéÌ,3¹¡ºÏAhÀÍwÛ~< ]o(A+Ñh4@¡á`äÇ<ùúRƒ!$'d‚äd60Ä?)Kb $à8øÎ‹—¿N$¯«f× [ôŽÝWï}òâÑÇ7,Xà³q—Ù‘OôÜHlô*nAç•äáêË {4tEVúSЀùÍþà`¬W»eE1ˆ¸&+P‚Tà—/¥•àÀóÖ#b½<51 Ĺd€ðà z[¥rá. ¼?Ø_РúTYǃöénî®—d|@éJ*Ê´ò¥šj?ÜUjn{óŒ¯ÇcR,ÄyòñëA´ðº‘Á©ŠöÏ5‚PMòºõ!ÃÓ^7ÃÆíÅ7álPÜMÌ©a ÇÙ€ ƒãÉbЈIΠñhœ œà84ž”ƒÀ<¸ØŠ¯E:Þen¾õú}:½0E¨8iB|JNrv ¿þóÃÜäü„*à¢+ÓVägfjX[׿Á–ë|Ø’MK=vHäÉ™ñé ÎÒš›_^€vƽŸøî……ø7÷kòÔYyŒÍrέ‹¯ÇvË·>òeÚŸãÑ´>×nÖó^s¥×Ü´Öé|l³Íà[6ôѸ}ÛMœ»Ü Zž—2-A‘Ž»9KSR2@•ZR“£Qç3¿wü¾®T‘4À¥¦°9O«È‘ç±V ¿c0­g#Óþã>l®å|^¡óÊÕ÷G3øÄ¤JÓ0ÍüsuªD@ŠK|Y‚®*¯¬DÓ+ÆygLðœá惺uád‡ì'[¾U°î%í ýs8bˆòéÅî8oÃI¦_îÞ¹ùšŒÞvGý[6a„gÌ?=òKKc²v8;¿âÐã¬@itšœZñ«/qV«JÛ@5C€4@ ݦ*-.-:¬FUÈÖ© /3k3…@ð9~Tt1õ4 *j@SƒP­`ÑèlLz›(8Gj3x6­-Û¯®µ ,n°ñ%NÙt¼ëÝ_ž§É1 ûÏõJ+%ªX%^[X‘^VyDsè8Óµ`ºÀv¢’c+ƒéd¯w­ðzÝ›ï.ôÍo`Ѷç:a™‰ÿÙeZ‘’–d”ùS>µæU]÷)³8‚A òÊÙï;|­ýäuðNº‡£þ‹æÏÝgHÒZ{k‰");yªé" ~¹sÖ*ï nžor5n›p«a{ÝÚœ@@%`±U™å-£Äî ¦vÒž²c¢M!Ê ƒB«  ‰J‹Çñµ~Ð=(cÕp¨'ìÛ²ƒåËN«k¬¡kŒV'³Ñjd—¥lïfßYWÍ_ä9Þùq'Œ4í1ËŽÑí —ÀêîòÏ \µ}up­Lg¶§4­03›ijºeþíó3>aÒÀÈ6$J¨ PnÌN9ýj.Dæ$ùËÙ6¬Û´vúž%E§¢ØÜÜ< Ðõ~æ8ó§ ˜Âøæé³[;®¸5š½ÏÉá@Þ#ø«ùæ/èri¹$)-=-• ‹ˆ’ȰM)H,N,‰ÓH!%ÄIÃc°*””IÊ‹4¹š<¦ÑPW^ A¾¢D^’¨‹=꡼Z«+k¨ÝÂ0rýp*Ümç‚™´"(q .Hmb`."<úË}dK"HÜ·]-6i%5?ˆ‰ £Aº*1ŽB »( áKôR`um“Î1:žëÜb‚*‹>kä\è@à›êcG©¶s}Temâ¨RDÍ9¹…ùL}ó‘ L¦œ^=<±Ü}áÊ?ˆX“1{1?{±AT+ Sì÷õ*h‡ýòò_,ùõg'q°m* Q|žÀØß4€éo1°Ÿqà@ÓÀAñÿ µ¾² endstream endobj 724 0 obj <>stream 2016-06-13T15:51:40-04:00 2016-06-13T15:51:40-04:00 dvips()5.96.1 Copyright 2007 Radical Eye Software fitsio.dvi endstream endobj 2 0 obj <>endobj xref 0 725 0000000000 65535 f 0000619128 00000 n 0000676445 00000 n 0000617987 00000 n 0000594947 00000 n 0000000015 00000 n 0000000924 00000 n 0000619194 00000 n 0000633891 00000 n 0000658436 00000 n 0000633568 00000 n 0000656260 00000 n 0000632816 00000 n 0000646206 00000 n 0000619235 00000 n 0000619265 00000 n 0000595107 00000 n 0000000943 00000 n 0000001114 00000 n 0000619317 00000 n 0000619347 00000 n 0000595269 00000 n 0000001133 00000 n 0000003475 00000 n 0000632269 00000 n 0000640599 00000 n 0000619379 00000 n 0000619409 00000 n 0000595431 00000 n 0000003496 00000 n 0000006344 00000 n 0000631949 00000 n 0000635717 00000 n 0000619461 00000 n 0000619491 00000 n 0000595593 00000 n 0000006365 00000 n 0000009018 00000 n 0000619545 00000 n 0000619575 00000 n 0000595755 00000 n 0000009039 00000 n 0000010221 00000 n 0000619629 00000 n 0000619659 00000 n 0000595917 00000 n 0000010242 00000 n 0000014903 00000 n 0000635106 00000 n 0000666396 00000 n 0000619713 00000 n 0000619743 00000 n 0000596079 00000 n 0000014924 00000 n 0000017693 00000 n 0000619795 00000 n 0000619825 00000 n 0000596241 00000 n 0000017714 00000 n 0000021021 00000 n 0000619879 00000 n 0000619909 00000 n 0000596411 00000 n 0000021042 00000 n 0000025600 00000 n 0000619961 00000 n 0000619991 00000 n 0000596581 00000 n 0000025621 00000 n 0000031464 00000 n 0000620045 00000 n 0000620075 00000 n 0000596751 00000 n 0000031485 00000 n 0000035736 00000 n 0000620129 00000 n 0000620159 00000 n 0000596913 00000 n 0000035757 00000 n 0000039900 00000 n 0000620222 00000 n 0000620252 00000 n 0000597075 00000 n 0000039921 00000 n 0000043306 00000 n 0000620315 00000 n 0000620345 00000 n 0000597237 00000 n 0000043327 00000 n 0000047247 00000 n 0000620408 00000 n 0000620438 00000 n 0000597399 00000 n 0000047268 00000 n 0000053580 00000 n 0000620501 00000 n 0000620531 00000 n 0000597561 00000 n 0000053601 00000 n 0000057035 00000 n 0000620583 00000 n 0000620614 00000 n 0000597733 00000 n 0000057056 00000 n 0000057371 00000 n 0000620658 00000 n 0000620689 00000 n 0000597899 00000 n 0000057392 00000 n 0000061570 00000 n 0000634646 00000 n 0000665502 00000 n 0000620733 00000 n 0000620764 00000 n 0000598065 00000 n 0000061592 00000 n 0000066832 00000 n 0000620830 00000 n 0000620861 00000 n 0000598231 00000 n 0000066854 00000 n 0000072321 00000 n 0000620929 00000 n 0000620960 00000 n 0000598405 00000 n 0000072343 00000 n 0000077961 00000 n 0000621002 00000 n 0000621033 00000 n 0000598579 00000 n 0000077983 00000 n 0000083414 00000 n 0000621086 00000 n 0000621117 00000 n 0000598745 00000 n 0000083436 00000 n 0000088893 00000 n 0000621181 00000 n 0000621212 00000 n 0000598919 00000 n 0000088915 00000 n 0000095646 00000 n 0000621276 00000 n 0000621307 00000 n 0000599085 00000 n 0000095668 00000 n 0000102541 00000 n 0000621360 00000 n 0000621391 00000 n 0000599251 00000 n 0000102563 00000 n 0000109326 00000 n 0000621444 00000 n 0000621475 00000 n 0000599425 00000 n 0000109348 00000 n 0000115083 00000 n 0000621528 00000 n 0000621559 00000 n 0000599591 00000 n 0000115105 00000 n 0000121005 00000 n 0000621623 00000 n 0000621654 00000 n 0000599765 00000 n 0000121027 00000 n 0000127372 00000 n 0000621718 00000 n 0000621749 00000 n 0000599931 00000 n 0000127394 00000 n 0000134276 00000 n 0000621813 00000 n 0000621844 00000 n 0000600097 00000 n 0000134298 00000 n 0000141095 00000 n 0000621897 00000 n 0000621928 00000 n 0000600271 00000 n 0000141117 00000 n 0000148067 00000 n 0000621983 00000 n 0000622014 00000 n 0000600437 00000 n 0000148089 00000 n 0000152300 00000 n 0000622058 00000 n 0000622089 00000 n 0000600603 00000 n 0000152322 00000 n 0000155865 00000 n 0000634489 00000 n 0000664907 00000 n 0000622133 00000 n 0000622164 00000 n 0000600769 00000 n 0000155887 00000 n 0000160420 00000 n 0000622241 00000 n 0000622272 00000 n 0000600935 00000 n 0000160442 00000 n 0000165236 00000 n 0000622347 00000 n 0000622378 00000 n 0000601101 00000 n 0000165258 00000 n 0000170048 00000 n 0000622444 00000 n 0000622475 00000 n 0000601275 00000 n 0000170070 00000 n 0000174376 00000 n 0000622550 00000 n 0000622581 00000 n 0000601441 00000 n 0000174398 00000 n 0000176358 00000 n 0000622656 00000 n 0000622687 00000 n 0000601607 00000 n 0000176380 00000 n 0000180133 00000 n 0000622753 00000 n 0000622784 00000 n 0000601773 00000 n 0000180155 00000 n 0000184945 00000 n 0000622848 00000 n 0000622879 00000 n 0000601947 00000 n 0000184967 00000 n 0000189597 00000 n 0000622945 00000 n 0000622976 00000 n 0000602113 00000 n 0000189619 00000 n 0000193828 00000 n 0000623042 00000 n 0000623073 00000 n 0000602279 00000 n 0000193850 00000 n 0000198664 00000 n 0000623148 00000 n 0000623179 00000 n 0000602453 00000 n 0000198686 00000 n 0000204000 00000 n 0000623245 00000 n 0000623276 00000 n 0000602619 00000 n 0000204022 00000 n 0000208656 00000 n 0000623342 00000 n 0000623373 00000 n 0000602785 00000 n 0000208678 00000 n 0000213906 00000 n 0000623448 00000 n 0000623479 00000 n 0000602951 00000 n 0000213928 00000 n 0000219312 00000 n 0000623545 00000 n 0000623576 00000 n 0000603117 00000 n 0000219334 00000 n 0000223352 00000 n 0000623651 00000 n 0000623682 00000 n 0000603283 00000 n 0000223374 00000 n 0000227967 00000 n 0000623748 00000 n 0000623779 00000 n 0000603449 00000 n 0000227989 00000 n 0000232640 00000 n 0000623854 00000 n 0000623885 00000 n 0000603615 00000 n 0000232662 00000 n 0000237843 00000 n 0000623951 00000 n 0000623982 00000 n 0000603789 00000 n 0000237865 00000 n 0000242467 00000 n 0000624057 00000 n 0000624088 00000 n 0000603955 00000 n 0000242489 00000 n 0000245990 00000 n 0000624154 00000 n 0000624185 00000 n 0000604121 00000 n 0000246012 00000 n 0000250676 00000 n 0000624260 00000 n 0000624291 00000 n 0000604287 00000 n 0000250698 00000 n 0000255986 00000 n 0000624366 00000 n 0000624397 00000 n 0000604453 00000 n 0000256008 00000 n 0000261750 00000 n 0000624472 00000 n 0000624503 00000 n 0000604619 00000 n 0000261772 00000 n 0000265703 00000 n 0000624578 00000 n 0000624609 00000 n 0000604785 00000 n 0000265725 00000 n 0000269694 00000 n 0000624675 00000 n 0000624706 00000 n 0000604951 00000 n 0000269716 00000 n 0000274854 00000 n 0000624772 00000 n 0000624803 00000 n 0000605117 00000 n 0000274876 00000 n 0000281198 00000 n 0000624878 00000 n 0000624909 00000 n 0000605283 00000 n 0000281220 00000 n 0000285932 00000 n 0000624975 00000 n 0000625006 00000 n 0000605449 00000 n 0000285954 00000 n 0000291011 00000 n 0000625072 00000 n 0000625103 00000 n 0000605615 00000 n 0000291033 00000 n 0000295913 00000 n 0000625178 00000 n 0000625209 00000 n 0000605781 00000 n 0000295935 00000 n 0000301808 00000 n 0000625284 00000 n 0000625315 00000 n 0000605947 00000 n 0000301830 00000 n 0000307258 00000 n 0000625390 00000 n 0000625421 00000 n 0000606113 00000 n 0000307280 00000 n 0000312436 00000 n 0000625487 00000 n 0000625518 00000 n 0000606279 00000 n 0000312458 00000 n 0000318018 00000 n 0000625584 00000 n 0000625615 00000 n 0000606445 00000 n 0000318040 00000 n 0000323004 00000 n 0000625681 00000 n 0000625712 00000 n 0000606611 00000 n 0000323026 00000 n 0000328126 00000 n 0000625787 00000 n 0000625818 00000 n 0000606785 00000 n 0000328148 00000 n 0000334630 00000 n 0000625893 00000 n 0000625924 00000 n 0000606959 00000 n 0000334652 00000 n 0000339693 00000 n 0000625990 00000 n 0000626021 00000 n 0000607125 00000 n 0000339715 00000 n 0000344333 00000 n 0000626096 00000 n 0000626127 00000 n 0000607291 00000 n 0000344355 00000 n 0000348087 00000 n 0000626202 00000 n 0000626233 00000 n 0000607457 00000 n 0000348109 00000 n 0000352777 00000 n 0000626308 00000 n 0000626339 00000 n 0000607623 00000 n 0000352799 00000 n 0000356836 00000 n 0000626405 00000 n 0000626436 00000 n 0000607789 00000 n 0000356858 00000 n 0000360988 00000 n 0000626502 00000 n 0000626533 00000 n 0000607955 00000 n 0000361010 00000 n 0000366326 00000 n 0000626599 00000 n 0000626630 00000 n 0000608121 00000 n 0000366348 00000 n 0000370115 00000 n 0000626696 00000 n 0000626727 00000 n 0000608287 00000 n 0000370137 00000 n 0000371582 00000 n 0000626793 00000 n 0000626824 00000 n 0000608453 00000 n 0000371604 00000 n 0000371953 00000 n 0000626879 00000 n 0000626910 00000 n 0000608619 00000 n 0000371974 00000 n 0000376612 00000 n 0000626954 00000 n 0000626985 00000 n 0000608793 00000 n 0000376634 00000 n 0000378524 00000 n 0000627040 00000 n 0000627071 00000 n 0000608967 00000 n 0000378546 00000 n 0000382554 00000 n 0000627115 00000 n 0000627146 00000 n 0000609133 00000 n 0000382576 00000 n 0000388377 00000 n 0000627201 00000 n 0000627232 00000 n 0000609299 00000 n 0000388399 00000 n 0000393380 00000 n 0000627300 00000 n 0000627331 00000 n 0000609465 00000 n 0000393402 00000 n 0000397888 00000 n 0000627399 00000 n 0000627430 00000 n 0000609639 00000 n 0000397910 00000 n 0000403447 00000 n 0000627494 00000 n 0000627525 00000 n 0000609805 00000 n 0000403469 00000 n 0000408935 00000 n 0000627591 00000 n 0000627622 00000 n 0000609979 00000 n 0000408957 00000 n 0000411744 00000 n 0000627686 00000 n 0000627717 00000 n 0000610145 00000 n 0000411766 00000 n 0000417767 00000 n 0000627772 00000 n 0000627803 00000 n 0000610319 00000 n 0000417789 00000 n 0000423709 00000 n 0000627867 00000 n 0000627898 00000 n 0000610485 00000 n 0000423731 00000 n 0000429882 00000 n 0000627953 00000 n 0000627984 00000 n 0000610651 00000 n 0000429904 00000 n 0000435321 00000 n 0000628048 00000 n 0000628079 00000 n 0000610817 00000 n 0000435343 00000 n 0000441107 00000 n 0000628147 00000 n 0000628178 00000 n 0000610991 00000 n 0000441129 00000 n 0000446932 00000 n 0000628242 00000 n 0000628273 00000 n 0000611157 00000 n 0000446954 00000 n 0000451422 00000 n 0000628337 00000 n 0000628368 00000 n 0000611323 00000 n 0000451444 00000 n 0000456274 00000 n 0000628432 00000 n 0000628463 00000 n 0000611489 00000 n 0000456296 00000 n 0000462302 00000 n 0000628518 00000 n 0000628549 00000 n 0000611655 00000 n 0000462324 00000 n 0000468024 00000 n 0000628626 00000 n 0000628657 00000 n 0000611821 00000 n 0000468046 00000 n 0000471989 00000 n 0000628725 00000 n 0000628756 00000 n 0000611987 00000 n 0000472011 00000 n 0000478098 00000 n 0000628820 00000 n 0000628851 00000 n 0000612153 00000 n 0000478120 00000 n 0000484031 00000 n 0000628928 00000 n 0000628959 00000 n 0000612319 00000 n 0000484053 00000 n 0000488889 00000 n 0000629014 00000 n 0000629045 00000 n 0000612493 00000 n 0000488911 00000 n 0000493190 00000 n 0000629109 00000 n 0000629140 00000 n 0000612659 00000 n 0000493212 00000 n 0000499525 00000 n 0000629217 00000 n 0000629248 00000 n 0000612825 00000 n 0000499547 00000 n 0000505414 00000 n 0000629316 00000 n 0000629347 00000 n 0000612991 00000 n 0000505436 00000 n 0000511641 00000 n 0000629411 00000 n 0000629442 00000 n 0000613157 00000 n 0000511663 00000 n 0000517301 00000 n 0000629506 00000 n 0000629537 00000 n 0000613323 00000 n 0000517323 00000 n 0000520103 00000 n 0000629592 00000 n 0000629623 00000 n 0000613489 00000 n 0000520125 00000 n 0000525163 00000 n 0000629687 00000 n 0000629718 00000 n 0000613655 00000 n 0000525185 00000 n 0000530461 00000 n 0000629782 00000 n 0000629813 00000 n 0000613821 00000 n 0000530483 00000 n 0000533220 00000 n 0000629868 00000 n 0000629899 00000 n 0000613987 00000 n 0000533242 00000 n 0000537906 00000 n 0000629954 00000 n 0000629985 00000 n 0000614161 00000 n 0000537928 00000 n 0000543238 00000 n 0000630038 00000 n 0000630069 00000 n 0000614327 00000 n 0000543260 00000 n 0000547228 00000 n 0000630133 00000 n 0000630164 00000 n 0000614493 00000 n 0000547250 00000 n 0000550694 00000 n 0000630228 00000 n 0000630259 00000 n 0000614667 00000 n 0000550716 00000 n 0000553456 00000 n 0000630323 00000 n 0000630354 00000 n 0000614833 00000 n 0000553478 00000 n 0000553764 00000 n 0000630409 00000 n 0000630440 00000 n 0000614999 00000 n 0000553785 00000 n 0000555238 00000 n 0000630484 00000 n 0000630515 00000 n 0000615165 00000 n 0000555260 00000 n 0000557778 00000 n 0000630568 00000 n 0000630599 00000 n 0000615331 00000 n 0000557800 00000 n 0000559872 00000 n 0000630654 00000 n 0000630685 00000 n 0000615497 00000 n 0000559894 00000 n 0000561958 00000 n 0000630729 00000 n 0000630760 00000 n 0000615663 00000 n 0000561980 00000 n 0000564323 00000 n 0000630815 00000 n 0000630846 00000 n 0000615829 00000 n 0000564345 00000 n 0000567065 00000 n 0000630890 00000 n 0000630921 00000 n 0000615995 00000 n 0000567087 00000 n 0000569216 00000 n 0000630976 00000 n 0000631007 00000 n 0000616161 00000 n 0000569238 00000 n 0000570032 00000 n 0000631051 00000 n 0000631082 00000 n 0000616327 00000 n 0000570053 00000 n 0000573023 00000 n 0000631137 00000 n 0000631168 00000 n 0000616493 00000 n 0000573045 00000 n 0000576874 00000 n 0000631221 00000 n 0000631252 00000 n 0000616659 00000 n 0000576896 00000 n 0000580043 00000 n 0000631307 00000 n 0000631338 00000 n 0000616825 00000 n 0000580065 00000 n 0000583834 00000 n 0000631382 00000 n 0000631413 00000 n 0000616991 00000 n 0000583856 00000 n 0000584868 00000 n 0000631468 00000 n 0000631499 00000 n 0000617157 00000 n 0000584889 00000 n 0000585205 00000 n 0000631543 00000 n 0000631574 00000 n 0000617323 00000 n 0000585226 00000 n 0000587295 00000 n 0000631618 00000 n 0000631649 00000 n 0000617489 00000 n 0000587317 00000 n 0000589933 00000 n 0000631702 00000 n 0000631733 00000 n 0000617655 00000 n 0000589955 00000 n 0000592565 00000 n 0000631788 00000 n 0000631819 00000 n 0000617821 00000 n 0000592587 00000 n 0000594925 00000 n 0000631863 00000 n 0000631894 00000 n 0000636059 00000 n 0000640961 00000 n 0000646828 00000 n 0000656534 00000 n 0000658851 00000 n 0000665129 00000 n 0000665731 00000 n 0000667068 00000 n 0000632731 00000 n 0000633372 00000 n 0000634387 00000 n 0000634984 00000 n 0000635624 00000 n 0000675015 00000 n trailer << /Size 725 /Root 1 0 R /Info 2 0 R /ID [<6FF04A5E8744D689DA2CD93044B1C795><6FF04A5E8744D689DA2CD93044B1C795>] >> startxref 676651 %%EOF cfitsio/docs/fitsio.ps0000644000225700000360000253415113246025103014604 0ustar cagordonlhea%!PS-Adobe-2.0 %%Creator: dvips(k) 5.96.1 Copyright 2007 Radical Eye Software %%Title: fitsio.dvi %%CreationDate: Mon Jun 13 15:51:07 2016 %%Pages: 138 %%PageOrder: Ascend %%BoundingBox: 0 0 612 792 %%DocumentFonts: CMBX12 CMR12 CMR10 CMBX10 CMSL10 CMTT10 CMSY10 CMMI10 %%DocumentPaperSizes: Letter %%EndComments %DVIPSWebPage: (www.radicaleye.com) %DVIPSCommandLine: dvips -o fitsio.ps fitsio.dvi %DVIPSParameters: dpi=600 %DVIPSSource: TeX output 2016.06.13:1550 %%BeginProcSet: tex.pro 0 0 %! /TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin /FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array /BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get }B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr 1 add N}if}B/CharBuilder{save 3 1 roll S A/base get 2 index get S /BitMaps get S get/Cd X pop/ctr 0 N Cdx 0 Cx Cy Ch sub Cx Cw add Cy setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx sub Cy .1 sub]{Ci}imagemask restore}B/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put }if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X 1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N /p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{ /Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT) (LaserWriter 16/600)]{A length product length le{A length product exch 0 exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot} imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M} B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{ p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end %%EndProcSet %%BeginProcSet: texps.pro 0 0 %! TeXDict begin/rf{findfont dup length 1 add dict begin{1 index/FID ne 2 index/UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]FontType 0 ne{/Metrics exch def dict begin Encoding{exch dup type/integertype ne{ pop pop 1 sub dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def}ifelse}forall Metrics/Metrics currentdict end def}{{1 index type /nametype eq{exit}if exch pop}loop}ifelse[2 index currentdict end definefont 3 -1 roll makefont/setfont cvx]cvx def}def/ObliqueSlant{dup sin S cos div neg}B/SlantFont{4 index mul add}def/ExtendFont{3 -1 roll mul exch}def/ReEncodeFont{CharStrings rcheck{/Encoding false def dup[ exch{dup CharStrings exch known not{pop/.notdef/Encoding true def}if} forall Encoding{]exch pop}{cleartomark}ifelse}if/Encoding exch def}def end %%EndProcSet %%BeginFont: CMMI10 %!PS-AdobeFont-1.1: CMMI10 1.100 %%CreationDate: 1996 Jul 23 07:53:57 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.100) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMMI10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle -14.04 def /isFixedPitch false def end readonly def /FontName /CMMI10 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 62 /greater put readonly def /FontBBox{-32 -250 1048 750}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA0529731C99A784CCBE85B4993B2EEBDE 3B12D472B7CF54651EF21185116A69AB1096ED4BAD2F646635E019B6417CC77B 532F85D811C70D1429A19A5307EF63EB5C5E02C89FC6C20F6D9D89E7D91FE470 B72BEFDA23F5DF76BE05AF4CE93137A219ED8A04A9D7D6FDF37E6B7FCDE0D90B 986423E5960A5D9FBB4C956556E8DF90CBFAEC476FA36FD9A5C8175C9AF513FE D919C2DDD26BDC0D99398B9F4D03D5993DFC0930297866E1CD0A319B6B1FD958 9E394A533A081C36D456A09920001A3D2199583EB9B84B4DEE08E3D12939E321 990CD249827D9648574955F61BAAA11263A91B6C3D47A5190165B0C25ABF6D3E 6EC187E4B05182126BB0D0323D943170B795255260F9FD25F2248D04F45DFBFB DEF7FF8B19BFEF637B210018AE02572B389B3F76282BEB29CC301905D388C721 59616893E774413F48DE0B408BC66DCE3FE17CB9F84D205839D58014D6A88823 D9320AE93AF96D97A02C4D5A2BB2B8C7925C4578003959C46E3CE1A2F0EAC4BF 8B9B325E46435BDE60BC54D72BC8ACB5C0A34413AC87045DC7B84646A324B808 6FD8E34217213E131C3B1510415CE45420688ED9C1D27890EC68BD7C1235FAF9 1DAB3A369DD2FC3BE5CF9655C7B7EDA7361D7E05E5831B6B8E2EEC542A7B38EE 03BE4BAC6079D038ACB3C7C916279764547C2D51976BABA94BA9866D79F13909 95AA39B0F03103A07CBDF441B8C5669F729020AF284B7FF52A29C6255FCAACF1 74109050FBA2602E72593FBCBFC26E726EE4AEF97B7632BC4F5F353B5C67FED2 3EA752A4A57B8F7FEFF1D7341D895F0A3A0BE1D8E3391970457A967EFF84F6D8 47750B1145B8CC5BD96EE7AA99DDC9E06939E383BDA41175233D58AD263EBF19 AFC0E2F840512D321166547B306C592B8A01E1FA2564B9A26DAC14256414E4C8 42616728D918C74D13C349F4186EC7B9708B86467425A6FDB3A396562F7EE4D8 40B43621744CF8A23A6E532649B66C2A0002DD04F8F39618E4F572819DD34837 B5A08E643FDCA1505AF6A1FA3DDFD1FA758013CAED8ACDDBBB334D664DFF5B53 9560176676ABB71BBD0EE56B4CC492C0652750227CEC7B86E4740EB7B8775564 332769DD30794E501BBB0E4E5CB665F3628E10B1137CC8BC5C0A64A310B5E27E 5FD6E3B04DA3914C15987E638A72790AF4073CE9CDBF6E3C749CB4DFF9C54951 A58C386C54BC4E98B102B5E91E8567D2EEEF048F2CBD5D243701D20909290B4B A3083F632D8552D42DEE0C69A4B14D8B15AA082DECC12B2ECAE6F663E6D09F81 EE2979EF41FBF12C9D8BF23B77E0A20088EBD107C5BF9DD6F03FFC3AB65B69A7 54953327E1D4AEF5A146273392BBDB321D4CC9A8FFFCFE5C515B466E21546CC7 C6209E5A76F916B03DB98BC6CED334F33E7B373D42761696F5A876CA6F93F16E 15A07E2E102148CA4F62A99C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMBX12 %!PS-AdobeFont-1.1: CMBX12 1.0 %%CreationDate: 1991 Aug 20 16:34:54 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.0) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMBX12) readonly def /FamilyName (Computer Modern) readonly def /Weight (Bold) readonly def /ItalicAngle 0 def /isFixedPitch false def end readonly def /FontName /CMBX12 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 11 /ff put dup 12 /fi put dup 39 /quoteright put dup 40 /parenleft put dup 41 /parenright put dup 45 /hyphen put dup 46 /period put dup 47 /slash put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 55 /seven put dup 56 /eight put dup 57 /nine put dup 58 /colon put dup 65 /A put dup 66 /B put dup 67 /C put dup 68 /D put dup 69 /E put dup 70 /F put dup 71 /G put dup 72 /H put dup 73 /I put dup 75 /K put dup 76 /L put dup 77 /M put dup 78 /N put dup 79 /O put dup 80 /P put dup 82 /R put dup 83 /S put dup 84 /T put dup 85 /U put dup 86 /V put dup 87 /W put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 102 /f put dup 103 /g put dup 104 /h put dup 105 /i put dup 107 /k put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 118 /v put dup 119 /w put dup 120 /x put dup 121 /y put dup 122 /z put readonly def /FontBBox{-53 -251 1139 750}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 2BDBF16FBC7512FAA308A093FE5F0364CD5660F74BEE96790DE35AFA90CCF712 B1805DA88AE375A04D99598EADFC625BDC1F9C315B6CF28C9BD427F32C745C99 AEBE70DAAED49EA45AF94F081934AA47894A370D698ABABDA4215500B190AF26 7FCFB7DDA2BC68605A4EF61ECCA3D61C684B47FFB5887A3BEDE0B4D30E8EBABF 20980C23312618EB0EAF289B2924FF4A334B85D98FD68545FDADB47F991E7390 B10EE86A46A5AF8866C010225024D5E5862D49DEB5D8ECCB95D94283C50A363D 68A49071445610F03CE3600945118A6BC0B3AA4593104E727261C68C4A47F809 D77E4CF27B3681F6B6F3AC498E45361BF9E01FAF5527F5E3CC790D3084674B3E 26296F3E03321B5C555D2458578A89E72D3166A3C5D740B3ABB127CF420C316D F957873DA04CF0DB25A73574A4DE2E4F2D5D4E8E0B430654CF7F341A1BDB3E26 77C194764EAD58C585F49EF10843FE020F9FDFD9008D660DE50B9BD7A2A87299 BC319E66D781101BB956E30643A19B93C8967E1AE4719F300BFE5866F0D6DA5E C55E171A24D3B707EFA325D47F473764E99BC8B1108D815CF2ACADFA6C4663E8 30855D673CE98AB78F5F829F7FA226AB57F07B3E7D4E7CE30ED3B7EB0D3035C5 148DA8D9FA34483414FDA8E3DC9E6C479E3EEE9A11A0547FC9085FA4631AD19C E936E0598E3197207FA7BB6E55CFD5EF72AEC12D9A9675241C7A71316B2E148D E2A1732B3627109EA446CB320EBBE2E78281CDF0890E2E72B6711335857F1E23 337C75E729701E93D5BEC0630CDC7F4E957233EC09F917E5CA703C7E93841598 0E73843FC6619DE017C8473A6D1B2BE5142DEBA285B98FA1CC5E64D2ADB981E6 472971848451A245DDF6AA3B8225E9AC8E4630B0FF32D679EC27ACAD85C6394E A6F71023B660EE883D8B676837E9EBA4E42BA8F365433A900F1DC3A9F0E88A26 30F40A9C74C8E7773BE601C0E245E7FC10C02939848C3D28D823057B3EA23EC9 E2BFF7851FB65FB12A4318A21D2C88EF9245D4C7BF21C81C4FC4CE0149E96278 48F7BF97A5C3691E6CE038033AF54DE91D320EABF2B2E98617FD4145BFE5EBBF 1A5634DA07B00257A51966FFC009CA416D37AD30F4BEE6D72AB64CB2D62466F0 42D66D6D33EF9107272835EA9C1C8FA04562864BE684FD5F8E6DF19916FF8346 F39F3E1FA2975B5CED24EB160FEF6149954F76C359E9D15A209EDD7445BB6303 6AFF9E1373CDD50B93DB137F3896D282F5C04AF0AC84AA02D5421A73E3AFB735 80EBE676C2870822BA89F4BA85034D6431BC4A44CC264DDD10EA146913E9063B 038BD787A659C6A88C42FD5FBC51234664A8A1621A38C73ACB7199592AA5EA84 B78BB5DBA7CA43E30CA8D3957CFF478712556EEAB1990C97B9BAB47ADB75E327 B361D3039A3629B09EB84CF814773858F1D354AD8D526E85EAFD50944CBCE042 367D1153D7B4EC4DD597DB0F57379DD63304869DEA4FA008D411E30ECFD62E41 29F51841A9E07E066F06BB4829F87B7722562686FB801D6690F73233053B2EEC 473B9899F284296BB634358A22DBF361C2A57C59438C429EFB04B80BE083E238 A6749D6AAD1F17F318B880D26D230B86F80A99C27B87F7605DE40A0848543DE2 4AF7D5BF61CA6B00FA156DBB9ABE7BB0EC79CE8FD5A2FC5BE17050F2A74E8905 75A9982E12698B289E2213DAFAAE40DD22B424562D7417E8B82A5E3DDA814669 D4CC949397B0DD2B0787016CB8FDFD09318719D7C47DB72E094C12C6DF3EDE88 663D6357CE7BFE51FD4A93887F022E3A22DCBE39CA86E104CE54C05AA0B5E469 0AB9DA29D19ED5E783225ECD1122BFFF5E4E63488FF215A9F555C190ECDAF130 B34E6BFC66AB1F7D000CC09CA9872299E23EC9B0A8ED04135C982978B9D7C4E5 F9C7968B540837CC667196C7B40F579E8258C8C7AC569AB787BB112C046D0068 86AEC034183A3DE02FB82C2CD3E252746C012F2385493F59DDEFD5AA95A26C61 BA64D85CE90339A0C19F538C6E0516513B9E7661505AB81F45AEA04618CEB379 12F6BB94E2812F2B3C69BAFC9135B439D74C6A94C0317E1B2A2EA514536AA990 7B94105AF7DA13148A807CB2F679DBDEE10B09BDCC8BDC7365166C910AA450C7 4FD88CA8BB639F1BA53A4B108D2E1633C5DB38E64DF4881E0FC1118559A078E8 52A0E2A87F98461EE7B0B56DFB6C3F340430E3D5C41C12141E4332951B4DF03A 6824E8CEEA4AE8AC9F51981184287EC2710E4A51DB5E09DCFF4DFCE6B82A0B5C D2E658D38FA7B2854778650A78AF230E97A4C195865C404EC18A5FA99EA30FE8 755EE5B11397D3CCAECD81EE3F3D1EE1A1B1FD6B669270912948134ECBA3D5B3 011CD3286DD6729DBCFC9A8FC93356BC70A876AB636E5C8EFA89881D3A6E0592 D4CDDBBD21A67033AB3354BA1333206874D2F7D0E571AAD845A96057F005F730 C98EBDFB006EF8874CC386A0B611389F9CF5204C65AD951306B0E090BB287EF9 CB7DB38F2A58E2ED6813F2138922E28FA44792E5C57A70C6152B4A6E73462F8C 869886D1E5718C85F1CD5E7EC4BD73C6A4E3218A7118D42CFE42BB83A6B72729 0E096EA902F81330771203309DEA91A560B56DE63911EBB6147600BB9B6A5166 A818B7B8CE58279E22D776B2CF423897110CFF24807319C84A2063CA464C7616 8260B36124AFE08188795E334864712574CC3DE12C3F0962D51734A44289BFE2 2525F5D641EF82F25C1EAEA56C621525EC86FB6D09D99941D18094B7D77719E0 3957294DBF2D221A49807B44323098D816A21C8F1BB888BC1075E2D6FD770014 829050B6F8E297853701C467BFE76C1E52E8AFD5AF67B3FAD5A608C23E925F0A 87E7F56B0D05F4D4276CE619190A983BB19417E280B53060AF777BCEA0D1F4D1 B803687D9C2050D0B2EBF3EFCB9FE42E02AFFA5233A49D27550BF8B32B1A3A3D A8F58FC0FEC58439D12CC87CEEBED10BB6D9BE84DDDA7FE7A7283D2639212CEE 2DA539DE06298BF452F896FE103A4BF864E5399C3F220FFFD82AF1975FCFA69B 8C9782842F016682EFAE7269A34FDC5ED188E3E6E24FAA0345D9558B19521D16 9FB47306CD1D15F36C9386347FCC9906A5420F4F6E030B007DF4D311B8E102DA A653AB0BA300D9467B092165B016C6F28E8D417E1B93A6A176329A67C5E0FF79 167F9CD8E2EDD33D5B11348EC7BF4C88C3226377DBA6C4723CBE67A7118F3CBA 34EF78E08A4211C39205325D138840E3F3FAA9CCEE74569B8F59CCE7E7D35D3A 0999DB04EC83483BA245883D764A3CF556949BE4B121C6483ED26D192405EBFF 089A97C4BA9649916F1A922F48CD04B7338EABDAEADAC52F42CF48272EAB9192 C17906F59CD98D5A54443BD474385AF6B51B9C14EA8AEA27AE3473DC12DE901B 42DC378872B001B2C929C54117E6EDAC6202BF1028AD2793FEA3620935539071 9BA89FBFB98229EF30B0382D9D603BB451634BFD08901432F16B31C9245D3645 28456E44DC8B6C9C052B9446107116AFCC2EC0F39F0CC7B5E146FD9E995594A2 DDDE2BD3DDAE13B9659969623BDE57219731BD3893B63B77D5218B94FF535FAF 2595C30EB0A003B144461C8115C5EC93595B4FAC2BC0D084E326E1F2CD14AC0D D9B4C1467961E2FFC04BD2DCDC1A16E9582653B1CECD98AEB6ABF1E88086FD2F 347774D628A4E70B6803EA481996C07D6D84661D003CF3C92D32791A06405C2D BDDED14EA55744AA956D04CADD4B2F5A0FBA5D29CFC84CC54CBCA53B19FBB69B 6199174100938FC1E16E7EC73BF85B058E235E282B17116250CC9965706D80F4 EAE76E2F7E96E901CE29AFBDE9CF9E19CC2432DE75B4E67DBB7BF62C6A3A0C4A 1800F457B745F18AAAACAB8DEA973869EFED9464631EA2CBE95F78133B4DA06D 394AB1CB50B6EED8E868AEA0EABDB783EFB7F0431A450D9C48492A04BFE3A0A7 9BFDE3B9DB2235EE46EF0D3E754F95819B6FD407E974856C83228A3C2A076966 02E3F0F2F27CAE5C820FCF3AC5FF38C715B3DC3CE9AC77FB13382D2B606F469F 768D1B82CE3D66F1AB552902B3BFC8E1B3A5A45D3C3D914D304070AAB6C49393 028CD984C44C2D8DEDEB61AB45A4B2237A236C0D3088AAC5A7F89EDFF9A09639 8B1887E2CB29D9E9B5630A45879069E58DA52E5603D026339E637D7B83E6550E CBD4349FB018A01749E171C987C30F8C36651501653A4421869F04A9B8BF792F 41B8D1E9F9101B658EF726DE26BA616A20A667FE7B571F68FF3BC77B127EF315 64D1D39C07799B45A40CA2D4FD81633368EC9654282A91B8F38066B3D781E8EF 3DCF9CB050096E84E8DE000568251ADFB56AB4AECF2D29BB47110D277E5A1634 D2813F9239951645D505C53CA91481C2B0F9DB72CC4C3EBB12D2BEB7B4201C23 BE8EFE99CCC6A0D520F6282F0876E6A69CF5ED38AAA9066196A9456C5DEC58F3 341797EFFF3040BB65E2479165581DD67AD36EDF24DA29DE341106F258C5FEA2 D538201FBB6C0C3A132487E01488FAF2EE5A61E7079547278DFA812C5D822454 F5B0E67620BEBAED135E63C8A55B29F685CA3CCCCBA06E2AEEECBD92E29B985A 23B93078BF8A6F41125529C1C171D7A8C1AFD9017CC089570E45E873E74D7FEA 7193C263492D4A6E73C65531C324FEA1CF9C4EBB6E501562EAA0EC4DA6C5FF7C 49DAFA4DA93D9F35F06616002A66468D7ABF3B3CAFE293A7CE0D1034B971B063 EF162C62E480D259E5AD6383DDCCB0F2CE0059E7E04681106CA6378D59F3EEE7 0AF84F11FCB538E4155CEB05D48678FBADF22F99B9D6589629FAAA181F78BD79 9D97F53E9FC10919970EF6CECCC6464540FB4A8EAD144B5662A4B0BAD31DEFA4 9C1F280C18BBB0FB005896075E3F4C52C9F11A2C0DD60CFE581C771A72273053 796AB48AD2500600E3355CE0C91E26DBF8C135C6B12FB3B2E89B9011CCAA3D2C AF8E2F38BE8D2BD82966B0037DA0B64A955AFC5181D3F2DA0F4FAE47875B5D3B ABCF48A2C3D1ADF69F5A3BB51D456B19085363318C3D371221A7319EDA644EA0 C30EB56AF819CAE5DEA47A7495B463E388562FB76C94621CA7F0DF9FA6C080EC 9F8AFC21AAAEAE2359869EFEFC8BCC433B683EE1DBE927463CEB19CCBE08ACA5 B925E88AB69BF8EB7A0781F57FADC2111659F9A480B8B4158806CDBFD950C4A7 0D792235486658CF8A96B0FDA2EE36468788225B794AE541683D2F5568B1239B 2956E585AE96E5C0FEF1D632895B3A0E0FCC57EEDBAF40F395547F77D7F4F6D5 23066F8B08FD44B1F26E89083C70FF24CE2AA2168AA8B09BDFD763286A243BC3 0431A22C8CC88A524E2C3DB01F1B65A1540A8C2EF5CEA9303DFC3F3CDB20EA23 600F870EC83EF9992A976ABA1D086EE4018DD3F7004301A7A431694DAAB46B29 538000BA28F999C70C3F72C1DB5CD7B1A4FDE6A0A87BA98332EDD260D30CE677 7176F2FE3D12C3434985AB6CC12AB6BD4872F5376AE6E6CA9C4871007D6DEF15 6D15C96C0433ACFD3AD8DB22100ED3D696FFA7DEDDA0449A14F435E9868DC2CB 8C1306330A68C38FCC010442A51DDC47BBFC474BCBA5A404A5705A0812B1DDB6 CDE7EFD4D833C7DB0D4C91561C7369AEF96E849D23FBC55429427FDAF7E2DEFD 18E2BA193293C0BF21F7241626E30573F2BB36C0BDF9A1065B2AE02DCE822156 0AD58921ED46E65C40FE54C0F9C58AD8531536208F5A6F538836B74090AD8191 486F29CED44DF9C4A547FDE7C40F833887845BDDCC68D84F2F445CD4D871FE87 52681595A6D0DC3FE1E2B00C53AD686E866FEFC39F6C7FFCAFF8191C13F7598D 3EBDCD33CA548FE31C67AA26568BE071A4D5750F9246695A4184042DB2FB0680 C0E1FF57CF2E9E360828CCE1C7F22D5CC921A995DBAE0D2469D4C5147D607923 455D9390580E120416B814A310E5588A0D54160728CCE53712D266C090F7175D 96725CE1CF85B0E3772347D9DB0CB282F04A2CE1A1358675ADAB4F5504554189 B141B5FA5BE5D2DD4FD88C91AE99E6504365853F95620C378657DBC98D06A4F0 38DAC9CB25A11D8A9D224C9CAD1369245B4A8E19AA55523BA8402CF056FA7818 DA762A53F9A2F02F17E23C97A38C14ECC34B985B1EABF9900698E122F11EB4AA E5524C3DA713271DAB8969B693A7CBD313F28120C7A68F4B3037AC043C992D7E F5829F11930CA70B580A161635228ECF20C5BA4D3B1587FD7A1D52C2530FAF7D C2C9431C7B4521296D391A3436642230E0E5D74E6D5E94277373513DC443B09C 0BC80C1EA1F22A7F2F4CE3627E852B5A636DEC22ECE7FE76F53FFC41AAF1B490 15E8060C6448F07997AE8D012B640630D72B11D77FBFF41F65B6EE2D70345A6D E6137355349A55DEA19D1DF5551B54F1E2F57E85568954AF23B2CA6D60859F11 2BCF6FB935BC106B9BBCD8E8DD551D82C7D348E03B71BD4E052686F1A0D59091 EE647EC64FBF77F558358129B938993D0F75673B45F41D2EDE54FACD6DDEF68A A8D55C257CEFC0E0D382C60A73C49DEC67AC68E5066749A1C00AE616A2C71A4E 14A95123F58FB1D940E2A0E51EFA67C2F2BDEFF85376D211DD8F15D43F2CCE7B 47B0CE25CEF1D450EFE17476BC3CFF661C1EFFC82E80E0A69FCCB25F39E51454 E53912FF49EBFB3CD9593F6FAE81F1F0A9E167282286F8407F9F0023538D75E5 76171E5A7005F053ECA82809C7073A1A480198BAE0085BA9BD1EF107D4324B24 F96E24BB4FDD80B195546854618282F770631B5F3FEFDC035E6954AE76304038 9ED525495644EA353E32F65140DEDEF41CD343B5333954D3A4C413BC3365B0B7 3ED0DB1A27C60237A0E82407753C1F9817C4A0D7F07D328FE2216B34CB8A233D FC5A420704C8F1D42B57E69424267E5BFA8C2AE65BA324262DDA2812D893050F 7D50D4487A5BBE53D7CF041DA6EF76A659DE8EE07DE413E940AC2160C994648A 6D0D0A59860B4080977C18CF6540B5F5B3B4DB52EE9CDE105D965E9FE5999208 02CFC8639767B033A3EBC2C42066F6E7CE3B8D6E2F25030D14957F7FA8E59A7A 5685A8A8479545C373DE7778A5A65D7ED6139A2C8FADBE8AACD08D56C42D11E2 CF01E2D78D4301556A8D7AFFF7642B10A36E93546EC8B2059870C472F5CD463C DE1DBB211CFF689095891B9980D9C9438FF7EC687DA72C548502B5EA0FFDFEE8 D982B934E7A9F4D62428FC6719894C0ED4B0040BBA5D0FCBD0E3D80F2E245513 4C78489DB71F2EDF17CEF7784370D080B75122290F59D4B4CAA0484A809CAD27 94FE9EDD79994079695C3DC4440C6B2FE4AB0129F2514EFFD8615425F7E74567 D93EADD0FB68FD8C6B9E3C1275F4FD32B8CFF3D8D04B185E2D702E46289456E7 F6A2A0D83DCF29862BD08AD7AF05E3380AEE207F44E5B8C11A89E954AE0BAB81 C5A8D1449693A0E5AE02D0AC8D1BF1CD96DBA29A747CF41292027ED8C05DD325 8B92300CFA2FD33F14CEE073F8CA93E33BB952B2E58E666B1E12CB5634136777 6D155B1855064842120EF87ED8B1CB6C95D74EF97C0B85DE90E266DD14793F70 27038C774A64E5757DE6FFFDE5CCB2BFA4B771BD7D02FCF0530E0768DB74FA39 2BE1C80A37A77AAC1B4972AA0335A6E51787781D482D01CCE8CD8FC732BFB1CD 69E5BF80E44F7F484277E5D8B9611B8614ABB9C8865F26DA08108D355EA7B451 2364F41F4EA9BA074CFD14377B092F4274F18F42B30C83ACFAF87513E8CC9716 7ADFE45917E3B9D034F4ECE1455318BA74C68CD534B7DA3E3C1C94A10E7F5738 46EF5ABAA7F58C0CB25A1F78F8FCF83DC2FA4F74B7F01E3141E1886C457FD285 A44A1A57E968358BC29CAC2BC79CD14FEF92F522C9873ECFE82A01BC4191BAA4 5D5212A7AFACEF600F738F4E6C691BD5D8D6F494187F43D42B1E876E6B12A02E 8357B376CA901EF9945D7703E28549C291731B78BC185AB2D3EA810CAB3A500E 2D2DF7934A616B3B0705F0928D97A742DB11392C51901CAB772C44113F1A5873 54C74B49EA48DE55089AFFB75B288185955DFEF25610BEFF0789A40381A1ADFB 95628B44B810062EF1AE97D6101B13B020276040FD886422F69A92254B222986 500384843D82F4A706D5160CE4E35556253C2B73B539D101F166873974CB1819 26D751F2E4DDA3D93FC7128C2515A75C676ACCAF8C07E2863951ACED319EB268 87C5802B7C54317A414BF9DA26EA1B53C5A8A9536F54FBA1699E1FEC82403359 66741ED2B98756BD5DE594C8CB2E0C24BB372EB2EE6F7910940CE6EE8D2770DE 6343C52B4065B6AC1B3DE9C4575B8061DE6F05961E68FE6527BA66EC51AF4948 8CEEC967F6E376BAA1DCCC8D50DC72C76DEE3644F890D4DFAD6E4B9115F43F9F 25CB66AE9E46331F5233609A390523BFD6D642F6BEA65B7500C3F7C28D03C2D8 A3B5C7ACCEB8147C62865F8DD2F844F294E8AA932F5D9482FE0A1461EF74BA57 BF1848B7CE0CD572A583A6837F9D27B6844E62DB08DF1AC678861485877454E2 FADCD5C87B57340824621B978982092C1334625551D36494A1E0246336B4104C B823C8ECEB49EAC4F8360867BA86FA2929918ABFEBC195C559BAF28B2396DE2C 5A550C3A17CDB40C4E2A4683590B0BBE2031F525216083CA6D9DE3247D0B77A7 7348225427CBD78F4C8DD795D010D66B5D16F513066C021F54DB36BC6902190E 53470B96270C8DCE6AA8F836F926EC56E5A4C69BA37EEAAF22AB1D09860279BF 97935068A4D11319146344CA8CA2B87E81D08345C699A81F0F4BAF56E39969AF A8094449E595CFFAF5CEC0540940DBBF79273B13D1A884BB2C354509CA95E582 34284D9EE6992D5F3D2FCC09F99D1B8B31B59E651C17A174D98E2AE214332D44 9F3769402AE4D2E6707450545C6A5322637648488BDE496DFA32BEBA617BDE88 D07982B6948B94C91247FAAE6AC69A8727FD4AF3154C5F6B435379119898DC8C 3110AC36907AA6653E28D292D7AFE2C3E54B6D29800BC7176B4F0D00E09904D2 F5DF5805E4C8E4348F017ACB5C62DD8EE155F56AB87315F95BF1A7AF147B71B6 AE4952942EE6676E491E9CA622504DCE2ADC678AABB16886ED89B6309EEEEE6E 08D8133000ECFE0BE713E5D144DF17E98DDFC61C688E9A89302773835DDF9254 A4985D6567AF8DFEB4335E1CD6B9D7DE23B009A7BEEED3BE0D7F77BEFB5BF2A1 07A44B1F9CEF1EEB6D3F49804D6BC47AE26DF2F878E8ED4861FA691AF085A254 688418486DAF652BE04054A8A8CE7EB42C5B30146C3ACC47502AD1BFB1A92DEE B3D317D4D2FB276BF7C4F11678AC10CBB01C3DA178A5C101BA5B995D18136261 EE1EDCBF883B6BA4335CC33BCBB116EE70B1372E01E64DCFD534672D9C84FBDD 79C8D2BDDE8D5C55F852E41FB5C1076D91B0D5C0E13F70B66904E08243EB3287 C6257181962EF755E7A603AA23D63BCABF36F18684582182CC20CEA4F1DA0665 1A8F1A4AF7C09F0351460919B10537E19A0ECA06DD9C00368137115979D3058F 635AEB09C1C561D020B5E19358F216B8D17582A518FDEB4AD7735FFA2C746D5F 163CA092531649865A1DA92CC8FDA32490826FAF4A9BA50653C2C3667F61D880 D6523745251E5BADE8DB233EF3A62E7C92F21AA31618EB0A08D47F406FC07C54 FC04404F5BF9DF6D2D53334DC93138323AE39E95F9CB2260995970E173C997B3 414701687EFD2B2088E50ECBDF14FBCC612AEF323683D2800DC9B9EB054B8CF9 3295728A29DFA6E22A98540806D6C89C34B188C29723DF52C50BBD4EF02C887B 335A72FCC0F7C358AE98D26FF44F1632CAA1774AE6F8852EE8BC262FF77A2E24 8B8833B7C9F9C65F94C889A06095776BC75361EA184FB5C5C8BA401A8D2D9771 D0D71BEADEDFD70EF617B92FE12FEAEAFA5F6013A28DA3C666BEE78D103C8947 3901E3B368BEE322935020EEE395B9701F65615D510809D8AF431537805E0B5A 908D1B2C659582D0E54294B5BAFDF5FF482712179CE8F6820C3E72A73EE0A4C2 43F792139AE3F8AB7A8D22A6D4C222B2B63CE37F0431157AD317A63E05067704 85F00AD9B822B1506DA0551ED23099D53CF6E5127B5AB291B33EFBD26C21E9AA 4096BA233B76B87EEFBBF8721EA8C37B933C5D901C4E451C1B05A5920CDAC618 F9431CEED497EA77D36CDF497354E158B9016CC888DDE52EF00302C140B29C1E 392F5974EF8EB272C054F3906F5D0B493C2478AEB0A83E469850BF76AE766B4C 884B10B49EDB704B33AA96020522C5218D7258210572E8B274FBB05B51380F5F DD14C84263128C4D037314263E8B1ED48C816F06B39E32D5A894E114F9B1A2EA F255A824E41E768E70ABBB14964CA00C9C3EC281D14BCFB681BDC943BCF320C3 0DB0B18DB7FDE42A3A2DEBF1746BE74E18BC0A8081DFAFDBCD64050ABBBF3A66 72D0D7CA15E88ADD7F0A1E1F70D397D838AFECE3352FAF0B149D5DA940B518FA 9594FF7171A2A6B77CD9CF96143DF0B708EF569CC135A2240343B3B50633437B BFCB0416AE4AADA1A480CFC134C1DBB9472279C4966B99B473272AF27150B683 09C57E73A83E7339B022F0388640EF9561C518AF312EBF0EF120CDFFF9F193AC FD6FCCCC337922405224C8015431BA7610EDE19CE9176A6C1F552AC7413ABFCF EAE1FC65D1F56917B125E498E37D2E7AD170F0DB13DFD8D430523B774DF5B2B9 971F0F78F0931E81A848B1E2D901BA1A011957B56831AA755DE617F8A40B843B 470D96140340CA72B45C2BF0C0CB635A6D7B25A084AAD2830288ACFA119C3AF9 5ACBEE18F38B244B7FD29210A7BF1D3A5EBD17E2B268C36CF439120B1947EBC2 CF769AD003B5C178F5FBC3AB5D901682CAF6AEC1D66B3F3DF730C27F09430EF3 81F32BE8B781338BCA00F8BB26B89804E750BEB587E558F48AE34A0516B1B4F8 342A97EEE51D352EB39C2819A200790E5BEBBC50EF4FC2DB326FB61F969EC2C0 98CD4F78F741C11D2744F26B443302392316A5C80A9ED122C7D27C1C89D098E3 ED365F63F5F2DB3889A4EF86587722E0059123D95D3C471751D8D8E84941BB5A D14766DF319F648FB6FC6B39E94450BBAD6F83E43B92B72B5D4F6804031782D9 9E40AAF10A291F048E4A0B6E726B1E81942615DD0A862087048BD3B261E8F8A4 25D82D60D90E58A9F3C03CCF9593F0A8738F397E058AC523438F58B2AD206B85 98B61EB8536BDEE0219867CD40F10F622EABC2D52297B257EA0DD929B0BB7938 158C6A6BA70514C27CAD1F310C493FEFC4EBCA10CE4F77686C374E1125F69855 9869DB3887046E82DA5EDDBDECABBEF1E050B26A91A6CF23D3F06B4206D5573F EDC6CB4DA302A355CD3CF80B54B270FA1844FB5DA988D08A754D30CC5F8DB71A 5AFF8F08A67CF1DF916E3370D961EBC802E2AE36B25F0B2BD2F01DDC9D52E45E 18D579D5C4A750F27262D2364A1CB2BB36B116626A9C1B6E35E22E81FF695E1F 713B9461726F5427EBABD116AF543A84981796A6FB49F72BB7AEAB3ED5E771EC D1823DCED5EE170126069B5369BFBE2C1225EF0E5757B2ECC2360F8EB34EE3F2 5F39660B7F714A82EFF3A61B7C9D26A32FD4C6EEEFABDB9914BF7DD6FB240198 81F121394D0C2386738E343645A9CE8585145ED6957EB06466D5037B1FB3210D CF0E79E0920167C5DBD605FDF8A66F96CE741DA7DD85D629280681BFFCEF027D C9390E2EE59F24B714AE30A802F112BCA54AB3FCF419F65B4B27CB7A543B55ED 350D9BE596B15AD6F79730DC86D82DD075390869201CD6FA2D22F77FEF7619AE 6FB42C939079757BDD06BE3B8A7CE60AEA6D1B753658F858AA2584D4A4CBAF7F 0D701BBC0379973E5753B848BCB7CF56FF30E5AC9D2E83F33B4D87DA222F1306 1877A2D810123D951F5CE12B17862EFDD5A86DA3A3987D973F70541D70B0CB3D 0F214AD4B1FFFA21A29E5C7856CE49FA93528E6D53570E3D8D6B17FA27B28AB3 FD2BBCC63139FD7F86DE6A84A2204CB30FD14080D45EA14EA784A5471ADE8A70 2864A204F10AA5B2A2C870521B97AD75CE3F6C078F1BACC99BBFC0E2F2387022 6F72BF44DDB62051E1B81A1419CF2F033B77FE46C2208E7DA22F83392EC97328 9A5E3DEF8BD6323E16D1D14FCFC890BEFAAC9F879198703CC9FD0FEEAA639EC1 B787D77B325A213B71ED56F1ED09DAB41AD4F8E314FA8154BAACF480F110B939 86477401D4ADE8FB386CE8959027A8B91C56C53028C7AD7EEB61DD986D303572 86324689E1AFF282E10F789421EC2BBFC5637C18936B1F2B4D02C8C8D5039503 D425992185042BA95E50C1ADD6563F3C661AAAF32E29F9A4BD3ADBA7A55962F9 ADD1CA560CDF1D0BEF0C57E4EA11587CD17CAB65D9DD830CB738549C6F614612 FACA8E3031BBF29682324D9E12BD792F9F3A24D7250D2AB55FC984C6CDBE070F 5F6282F51C4DEAD075EFA1820E044174FDBFE9AABB68E6254F4B59E8F442DBCF D2AE8ED7ACAFDD486DD36530A71F9A0D9FF91B19FAF723B4909C9F99D5CB29F6 2CB6384D6A3544359AE23E09770F82FF7C9327BD392BD0F6B607897B6D826C50 B84B2E0722B0E27ADD479E5607B4500B8ED238B99C40B2BB47F02352BDACAD22 262DBFBD38A9D4D1BAB79053F4F172397F8F7C00CBD37164A0C89B7E31EDB3C2 25D32798F7F83582CCA56EC0F419316EDB2F3299E40BFFFE63C5C2A0ACDE3C9A 414C2BF9F341F40FD4C8A5B1950EA05A26DD6CE187E181E6AA167F26AF6A4E5D 6E4AE9430E0069749299D2B9D8ED6A3E647BF2707948B8F6D16D4DFBBC71BF61 5EBDC349EAA9EC847880990795B75B118423D9153B05D5D6BF0D20E909F8B22D 0DC9A8CD8CA5B43D92F4CB54344B375926EEFA5BF058B7BAB54B5C97BD5653FC F05BB1A5991B068C26B0420DECA3F1943D093997A3A8BB061BB25CFFC0CA1DCD D85CB203491D176C4C183BB124F22D57678841F08419028F250C30D1237A0213 E5A392E60B27D2BE5240346B99EAFF9B57F108DA66B6AB826546C6411864F7CD FE404BEE7D58F28580C448AAB599D12B00A3FDB2BB93737971A5E13FD7CFA970 656D45145A54DB1BDD0701097445ACF73861FEEB01835F35790E98EF162D5F37 E1A5617CB2BC22074305FBDC8024E741C7BB0FA0E17F123AF953742E01AF56A0 AFF35515ED55F9621AAA309D36964B0187F56FE1F02662B7DFD745F2F3BCCC43 23C8FFD86F382E99DFF681A7D22CD133153C40C3FCBDF86DBED11FD36F9B6B3F C5FDBEFB72496F3C209BD61EB9558CB2BB1672CAD20F8086DF3492147770C0F5 95444F8731D0A1F6036C3099DAC1993B2C838794554E8A3B96614090077BAB84 A5954FF123B90550E1D1A4AB2CA6E8214C473B3CF56746959C062AB6C28EC09B F22096BF7FB6321338085C726C42745088742C6C55D4EA9854CAA71E7BAFEC70 A29302F3C909A6E193ACDC6496F7929713DDD1F4B813D73E794377CC0B956B9C 2D07F5AF8C01D7D9F932F114547E4EBB953ADCED8B20E83FF41B1F4FA5A02915 0C63DC0619BD7E3B5E6FA60157A21794D7299C5774C0FF7D929FE9BC1EABB7F3 193E83584567271D2123E6B069DC23889B93CBF2ECE77CD8CCD649AE853784CE A79337DC93FB835373CAB6E183F5CFEDCE41C418E8C0C48D02BDDDC0CD3D3B4B 285195948E36529F28A6F925FDF16248F9331CBF5A08DC0ECDE2C36FB0A0AB89 2DC0EA84D93C834DDC1BF962D89153901ED7784D9E68BD06357F279CCB7C602B CCF4F389CD7CB4197D2A9271D65097AC31DC2FFEF76884D0910639237DD0C020 F0DDBBAD4C2883ED7313DFA0539D989C1FABB6A5ED54FC791B196AFE787363DE 6688123AAD777F27E4DD19C32B7FAFB9E8E0552DE8DA00570B1AC3E8CA4C7866 6CDE42B4CB89FA30F0AC964EC7F2F77D3F1980313330F26E545BC7A8F5072AA3 2FB0329361BC8BE2C2B48FD060C89CAED6DD9BF6462BEE5FBA59C569D8EEEEFD 8C1BBEA3B73A537D1256C7D6CC73A9CFA3DDB34252A3A4509536D62802A615DA 4AC07C441743B45A15D85181482717316C5B12F6E52BF9A1C287801F3677CFEA 6B60F505F9234792D6E82DCE04C72C308C0D17B80B14B291AA4B437DB7CE5E35 436CC41F868ED6162F25BE5C9FE406FE656FAAA39A72CD5DE07569F21C55198E 54678E869AB6959798013ED6CB2D9CAF568F43D2624ED5F602B7F16F9D27C12D 48EE40743E1DA97E6702FC3634CEE0AF9E6FB3C4587346219C4CDC0B6CCF7F99 E40B48B6C7F5BB21DA0656B683E71A4CC310B001A180D9E00BE05215B170D2B5 C93C2636B61BA3A840076A5F41B8DB3E0B2A38C3848DB0CCD419E5E14DCD1397 AD9811172CE82D7CC7D825B6722205E0072FC807FB647E0442333D42CF799579 C7B7406D147A69C59E03536C8D2EF372AD9C374B977CE1A0784C83073742008E 480EC148196F146C5278FF1EC8252E708B9042389C11547351F093CA8488DC3E 1D5126DF92EB568240BBBDD84B2129B6E8FD6999651566BFB632984240E14F4A E8F5BC9C04ACFB19B327E5246E5BA5B73A0A308D930A588E57174574ED2FE506 9512E3CD02D75AFDC1A36BFB585493E4164F3894679FA602BEDD8CE9E821D187 47CD38794364E336B65126F61CD3CA861F9919F24CDD410E5F03AAFC4E45E30A 486F6CB28CE7A6A2125C55CCCC11BA659E72234CE9D5F6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMSY10 %!PS-AdobeFont-1.1: CMSY10 1.0 %%CreationDate: 1991 Aug 15 07:20:57 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.0) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMSY10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle -14.035 def /isFixedPitch false def end readonly def /FontName /CMSY10 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 15 /bullet put dup 102 /braceleft put dup 103 /braceright put dup 106 /bar put readonly def /FontBBox{-29 -960 1116 775}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052F09F9C8ADE9D907C058B87E9B6964 7D53359E51216774A4EAA1E2B58EC3176BD1184A633B951372B4198D4E8C5EF4 A213ACB58AA0A658908035BF2ED8531779838A960DFE2B27EA49C37156989C85 E21B3ABF72E39A89232CD9F4237FC80C9E64E8425AA3BEF7DED60B122A52922A 221A37D9A807DD01161779DDE7D31FF2B87F97C73D63EECDDA4C49501773468A 27D1663E0B62F461F6E40A5D6676D1D12B51E641C1D4E8E2771864FC104F8CBF 5B78EC1D88228725F1C453A678F58A7E1B7BD7CA700717D288EB8DA1F57C4F09 0ABF1D42C5DDD0C384C7E22F8F8047BE1D4C1CC8E33368FB1AC82B4E96146730 DE3302B2E6B819CB6AE455B1AF3187FFE8071AA57EF8A6616B9CB7941D44EC7A 71A7BB3DF755178D7D2E4BB69859EFA4BBC30BD6BB1531133FD4D9438FF99F09 4ECC068A324D75B5F696B8688EEB2F17E5ED34CCD6D047A4E3806D000C199D7C 515DB70A8D4F6146FE068DC1E5DE8BC57030ACE57A0A31C99BEDB251A0ECAD78 253AB321023D15FF7F55A3CE81514C1E7E76240C1FB36CD4874DDB761CC325F5 D588700B294849D690F93526EF438A42B9B5B0508584EA3766D35F5B8D51C458 ECB9FBD23A49576EAB06BACB7EA6D300985500835F4FE597D4A1110C8EABE6FC CE3E1F95CFD3A42446F25355381D476B2FFB6EF247BF58A6FFC5EC0E4CC207BE 46485F8E07350B37DCA8C1864E62614332A1D3C9DEDDD6492181949A2C3498C9 EC2A81C1F4FF989A4654E375F509D24D969B97D2A9940FAF43BBB286E08559C0 F8D9674B0A294B36D3A050F7DED8C80E1D230812F6B8387B17948FD29FF050E2 AAC5EBE5D96AFD0879534E2F4BB81613A1571750F9CF4215199F93813D815B5D 1C79E11A0FCBB627CDE569F88C741CD502627777BB058ECAC09B6ACCFACA69B9 8F8168B0B5A1A6EB13E884B348FBB2ACF9EB180F6E27D57F8503710CE037A34A F8B157201657C825E2A4B4A7696B58B7A988C05E43E66F0FF277A7694C555C54 AFB1D32F6DE102136FC810E1F3B5CEA42476EAC7AAFB390E3252B2169DCDEE6E 328507BD0E24734A85AAA263E0D2F64BE1607455BC855785BC27F8B30FE917B4 23AB3C812975355942E955501AF85A3C0CE836911AF679EA44AD6A7D042A6549 0C471FE294E8490024D93ADCADED460FAB7FBCDC29EFEBD2A9A127E11869E659 961B29206CE63944B6FA4B9315BCC528EB1E0223CE94C795A5D5231A7FC8545D 6B287B965F8EEDDB67A6774129DD01D5A21694ABE320BB2553043D4C42ACFF91 1009372CB03381035BEEEEFD05631E026A0980A72A67B3703323A4E7C94FFCEE 8D0B7407F9CCC043D3D184BEA4728385D6AB2FB0641DD8F5BA7E04035D30D628 7E97D31C1486DFD5B1D076B84B4ABA4829ED4310321F1F24B847C44E00185A69 37711A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMTT10 %!PS-AdobeFont-1.1: CMTT10 1.00B %%CreationDate: 1992 Apr 26 10:42:42 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.00B) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMTT10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle 0 def /isFixedPitch true def end readonly def /FontName /CMTT10 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 33 /exclam put dup 34 /quotedbl put dup 35 /numbersign put dup 36 /dollar put dup 37 /percent put dup 38 /ampersand put dup 39 /quoteright put dup 40 /parenleft put dup 41 /parenright put dup 42 /asterisk put dup 43 /plus put dup 44 /comma put dup 45 /hyphen put dup 46 /period put dup 47 /slash put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 55 /seven put dup 56 /eight put dup 57 /nine put dup 58 /colon put dup 59 /semicolon put dup 60 /less put dup 61 /equal put dup 62 /greater put dup 63 /question put dup 64 /at put dup 65 /A put dup 66 /B put dup 67 /C put dup 68 /D put dup 69 /E put dup 70 /F put dup 71 /G put dup 72 /H put dup 73 /I put dup 74 /J put dup 75 /K put dup 76 /L put dup 77 /M put dup 78 /N put dup 79 /O put dup 80 /P put dup 81 /Q put dup 82 /R put dup 83 /S put dup 84 /T put dup 85 /U put dup 86 /V put dup 87 /W put dup 88 /X put dup 89 /Y put dup 90 /Z put dup 91 /bracketleft put dup 92 /backslash put dup 93 /bracketright put dup 94 /asciicircum put dup 95 /underscore put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 102 /f put dup 103 /g put dup 104 /h put dup 105 /i put dup 106 /j put dup 107 /k put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 113 /q put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 118 /v put dup 119 /w put dup 120 /x put dup 121 /y put dup 122 /z put dup 123 /braceleft put dup 124 /bar put dup 125 /braceright put dup 126 /asciitilde put readonly def /FontBBox{-4 -235 731 800}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 2BDBF16FBC7512FAA308A093FE5F00F963068B8232429ED8B7CF6A3D879A2D19 38DD5C4467F9DD8C5D1A2000B3A6BF2F25629BAEC199AE8BD4BA6ED9BBF7DABF D0E153BAB1C17900D4FCE209622ACD19E7C74C2807D0397357ED07AB460D5204 EB3A45B7AC4D106B7303AD8348853032A745F417943F9B4FED652B835AA49727 A8B4117AFF1D4BCE831EB510B6851796D0BE6982B76620CB3CE0C22CACDD4593 F244C14EEC0E5A7C4AC42392F81C01BC4257FE12AF33F4BFEA9108FF11CF9714 4DD6EC70A2C4C1E4F328A1EB25E43525FB1E16C07E28CC359DF61F426B7D41EA 6A0C84DD63275395A503AAE908E1C82D389FD12A21E86999799E7F24A994472E A10EAE77096709BE0D11AAD24A30D96E15A51D720AFB3B10D2E0AC8DC1A1204B E8725E00D7E3A96F9978BC19377034D93D080C4391E579C34FF9FC2379CB119F 1E5BBEA91AE20F343C6420BE1E2BD0636B04FCCC0BEE0DC2D56D66F06DB22438 452822CBEAF03EE9EAA8398F276EC0D92A7FB978C17805DB2F4A7DFBA56FD6AF 8670EB364F01DE8FCAFBAF657D68C3A03112915736CEABAA8BA5C0AC25288369 5D49BD891FABEFE8699A0AE3ED85B48ACB22229E15623399C93DE7D935734ADA DA7A1462C111D44AD53EA35B57E5D0B5FC0B481820E43222DB8EFCD5D30E15F9 BA304FA879392EE0BCC0E1A61E74B3A1FC3A3D170218D7244580C7AA0DC65D19 741FA5FE6F8CBF60250ACC27454BBF0897CA4B909C83A56672958752ED4B5E79 E18660764F155E86F09EFA9F7685F2F5027EC85A775287B30E2069DE4E4D5712 E7D033481A53A2702BA7542C71062173039030CF28D8B9C63B5596A9B42B33E7 D922944A38713383D3648A4AF160A3B0C8F3379BA4372BE2E7EA49AABA75AEEE C5DDE1D8BF68483C3D21271280ABB91D54CC819680322EAB72E1250A760BC8DA 726405EFE420635B5B7F0B48752C06083E92BDE06401C42A2C528C8A60381227 CEBEF0C9440DC034DAD9C19FB27DB399BDAEE22053591D6538587C768C1B7B0B 7D1E222D2D8AF3A6473CC4C0D6C3E0DB49068CEB8C9BD1C5CD486A50DAA10BC7 7D6286142355E3F21DD254E27C00C442728A0BAEC9D3F17AE9CE320D365152E9 EB0D5E3874F2BCEDA98521D23FCFC30B4B69DAD2ADBE80E5964ED0ABEF6C73B6 DAD30E2C5061E3747FE536E1A5D190D028F2130AF608F5DDF9DDDF1E77DC8437 ECB3EC93B33505DF47884DDBD1DC6BBE4098DF04A29AF6FA3AE344600D0AAB53 B3820DD7ECB600A3B8001C51AF2CA7A39AE1485A087FD1752DF68F55B52B4DA7 48030F2AA7E570B3D56C4EAD367B9B73FBC0A7356253233006178B9A6BC19081 B815B5988AE76FE6FAFD7AC239072B1106A3F509381AAEE79B2F2154CAC4727B D199CDC8B4D05DF4BA006982512ABD7539E28D937B0F87FF79A3F84C29ECF943 A8DCB8BDF8EA9E7A0E7CD60BC2308C96B3E889C797D0FF28FF4847016B3DA141 E76FC6BE78A6EE9CE07E651FF86E720A1A1F075972D36E5C55162E3FE26BCE3A 814BFEB12D4C5FD24340CFFED499C7CA183E57EC4F12CFFBE3291D43F7270575 C6C3306F832EF182ADD0AA14C4D8669A17C09F632406AFA195F90C4DDC39779E EC0A77E590211592D6EE19563963225C06C2F13265EBB5A6CFB7C17D9E77650D 11958305727AF662AE73AD0E3ED5F7E7086C5A0C3548A8129575980B06C715AF DD55C8DF869BED0A7883491030B1A7E82C5EB04E5A7D952E716DD8F2EF6275EE 087614CFAB55FCE2BBECD7E8D9C90FD8359E929D5E0A416A23BD58158318B4FF 87B095EB63F7F052B3A77F136FD66EB2C52BD46CD7DB3091A4B78A607112B12C 4D171B2A00B78B0E1C44B0D90C20D9244281F5123DC1F6063F91E9E3E48DE78B C862D848BAD073A4FCB5EEC9FF54B5AB8E234CCC3C7439C62ABC4A13EF1B8897 ABBF21F900C564C9A305FC36FC7224932F766E6E72C2EBB55953DFE2AFC2E3FD 33A0C6F0FDFF086E9FD796E7242596AE85B877223532667625E371D2156E4C04 0D7FFCD3337B93DF066CB6FE1E13960719EB7CB409EE805C08ACD2C06303ED9C E34C898787A43C1B428B896551C6FEB50A831C6F8CE2073EFC662EC286CB7555 A3B42E58772E82FEE206948B8C439FEC5E4ECB9E11DC3A4CBC7611E30890E408 637A01A2118441B4F9467A98BB2A1B03BB2F5D8E3DB7D1D15C188D9E856088EC B762F07B1C06024F7EF53A2FBD60C0A1F4C0275D07164545250ECEEF8CB15B04 A2D8AC44DDE818C4E3CBD2A5FA0FE49750886CD7CFAAF8B780255F89DF7F4F5C BB594FE7C1597DA71813C2952AD3E811524459EB71D29696B450C924B6A5C843 8F36A0F1D7DFE796FB9564333666D74AE614D0D698FAFF20F83C86524C894BB0 272221C060544F3B653CB0E4E4F82B20D7530B3806E6A5830852C58070177815 E287C847F19F64E854F1463C23DDD80093D6FEB8BAA22C5F05C21F99FBA7193A EB7CD49CFDF4308C6C68CC955A45FCFB54FCADA9A3BFBDE086B057DE88BE335D 280F5338D7E66AD39FD08F9B55884F1F377FB6869FBABE3EAA4B7ACCD85BE672 724B4B8F236B0889B6E7049CBA558A89F17863E82DF145DB8C7ED1F36332DE23 3C0053B74E850FA14F9EC9EFC23AF18E153CC96FB0FFD910347370E57F0D81E9 4A83E2D189EE5635E85A2BEAB5B1CB974546BFB2FC2ABA1E15DC0EC1BB3AF1DB B2F93538B92F504CBD7AAFE36F5F3AD45EB16378F169B17869FE81464CB826CB 400D2F5441A496B6C60A4F15FD20ECCAC1F8F91015E7E1C1A10B7992A1554E52 9FBEE905A3005336E49CB04BA7223F1674C0BBDFA06ACA34F7BFDA56906E04A7 4DD79EC7E79B021A5008F3B1E04712D689366F520B0FA66A558F957011992728 561BF4B75C2BE07C4024C172085E51CCC5CFA439F570297154CDDBB3AA25CD6A 3004B936488851BA1E814260C06CD5479DCAB1A6AE21A5F4563024F973D738B4 0DDB6C6DD2E3AC21B4F6D95CF9AACA782919F5D3E613D61F3224A982AF485C8D EA0037410EB70AB7D3EC174C6D5DE5C9C5A1220EF7C2B74499ADCEEFF077D1D3 50C1124535F88C3C3F66477E42F1932665AD323E06B398D2805B9CEA632F5B1E 50FA587B102A35E2F15EC22DD66E4DF06A3F4BB717A3ED7FBBE2458EB4D896DD AF00D1BC71FE1CCA27890ECBF9F0AF01D3E65CAA29427FAF06B3BE1E640522E0 73B213D04491B93DB29113EF72211E31F4C5A7FD58451946CFC15FD805112FE2 547D1131A46710DFB75659A33695FFAF3CDD40AE5260AD6766DA81DAB0A6E96B E89D57AAEF32B5EDBBE9F7CC033BB2595CA3FEDA2ABAC8E5395EBC35BC112FE9 67EAF1F123228538091483050847F8FB5194203609502D3A09CDE811EADC18B9 F039593782C27EFA7697182D6367E88E326AD5622C5A457FE2644FEADA88615D 9DE3E483BFD9329667953CDB86F9D2F0D4F02DAB8A98FDEB1D17CAAED9B6E2E6 0C55C1FEE25AB98FF59FC235876029CE03E4A713B75B3163BE3B2DC0D4472DBC 473E10400C0F57E627AE97FD0C1CB0F78FD8E2FA831A3D2B1C2BB3F2D4E812A4 194C8732B0C525361DC8480CB27C30CD4DCFF01318D2EB4F5234B4A42EA8C23E 7B3EECA41B8E4F54D5458B37EF0FB2F49EB19F4EA8AD2B53820FA36E93DD309E 48847F5C01B1118ECE7D0186E6B8953344EB775D655AAAD7BCDA642EA2E39A15 855C027CBC0E3FA752900EEB464E2D39404D1B85072B40834748C6F9C74C5B6C 3CEDE988343FD984CFE4B856A481E60E2E65D3BB41BAF2FA80AC0BFE381071C4 573C6ED65C524FF777F34D82E9661E4A75E3878CC77BC59218244612219C5A92 E95B90EC2C38614665550026F1730D11162F19D841681C04C401E102C047541B 97B9264D86F47E25A347696AE5EF0FF3ECD9BA32C92901DEDD816F7D73ED1216 0A98771892472CD625A8F7F19DEFCF5CA2AE57F8AD3898F2C1005B187DEC6F2A A31C32720EBC934178E0E9979013B3C9AEDA4051DF63D8C903A399DC88F83DCB A73F1B2083819D1BBEA5235F8FE1D098F32A2BA6274424A99A4975FE4BFD59AD 79B40A8003CC0AA728EA79D6BDCBBD73DF45B7918BC099C5BE4A068BF64A30B1 C39442CED98AAE1BD495F6CA32D564A72E3BF753B49E4178927E4BBC0F06048F 96DE7C30AF580B0BFFDB330B3B87D7F6532A24F403680BD9F15E758CDF04EB94 E83C7E644FDE5BEE7CE73EFAC75669E41BDFB20A5B8ADE1137378DD8102A0DBE 19499A623770417CBF5211395A6BA9F4490F4707A46F1F9B3FBE642DEA0CA053 9ABC307B1E71DC2B069DDDBB4EAE378BCC75AD61DA900AF8BA6DF0E27A8D2258 DC80205305AB6ABFE3726703E60869BFAFF1874F3C0E05FAD9C05D7D89ECECA9 DD2AF5F777D7514208697E712B52448B364D3ECEFD8127043DDC9D0757B7CC37 5CDE8001D007A6E961EA24D7FFC92410F3B13A32946F12A50DFFA256249BC8D7 C1842FB84AD51B41008EC4604F6B70990510EE13E6DA34F864A572D99A13FFC7 3609EF2BB1FCDEDF37A6018248C545E086EAD1BA1143E74AC60B684E755E59E7 36557B915F92EF78FC177621D49F777A2AF39F3C2AA6EC74750AAAE08BCC21CA A71CCDC91DD45E6050D83ABA49ECE425B55EEE137C55619037F1C30530BD0A6E CD2004B6A040405064D7E87C55536680364E09248BFAA3FDF95CDA0708E55F4C F7D0A92A93DEE0C7B69638F171B28B7F854CCC6EBC6AEE14864BF5144EA36D46 A9C297225AB0325E28EF6BD06D7E40E3A724EA1E50C4C6163B195CFFD5DD291D D7BBE9AF4324A69394117EFD62F08D6BA6A8F0AC3E2353492999AF28FBA758C3 A50B6840CC72054355E6CBDBD86F683537A4115049BC1616BA35C2B0B6F5CC32 3F6831DE4E6029310738DE23D36D2C6E82F04EB675FB89789F74AFE3B8854250 51812FBEFBCF162947554324FADAB765C74B6DA89F60A734076D44BBE45263B1 3FEFEEA90EC7948F23F34D4049087AF6563692417DDBCDD5A9552A373C2528F8 0318D3C0669279F292127CBA40B0ABE08A1476BC9EBFA8BD5D622BC5CE7DBA20 C689BDAF50D5B1EAA89E296787CC53845DB2BA54FDE363DCC98A7BA256663869 E9E02E09077884DF1A2A41AA698B7EDE8DAFA621B552DDA91AD1E671D636FB36 91C62B4D2D4112F2C169E0023EB7521F570CECC54ECA5EBA462049AABBE2ADEF E3234BFD71B26DFDD9D34DFA69E5E80FD90406E6505A6798F030A4B5172A7BC2 C9B765A86ED55C0590E0432719BCD7BDE7CCC7F6B33BD467063D886276C8879D E04897A4623111C14A1EDBBF69E2FEDDFEAEB2A785C6D2F0711DF4B93AAA291E 7F4E0CF9CC3FF0D31953C594DAD014097DA02CBD5AE8828C7E7B5BDA09188B05 0D7263F164E1E78CC430ACAD1E8FA71001E9BCEFAE47C79846916A5F819CA366 5734089BCDD458CA1A9E8E17BFF357A91F9A7A8A6E1DEFB121353AA80F1906A5 AF7CD2E59EE6776FC0DA6574DA0DE522918CAC4E566F13FB9B64EFE79F3A3BC0 689E3B0676741C90FF3BF85C7A0FA9716F4ED0E329512B66BFB8AEB56C3DD6B2 24F8D6E23751A8485F7EB46719E9D22618FEE86D5E01ECCF4C6E74368A8E9B49 245D80E7484DFBC916FB2447852B36EF3F99A82B6C106F786707D7689DCD7AEC A0C51AC1A3F67034C16B74994403FAE7743BF02149BEBEF554814BEF31B79184 3FAB4D2C887E1BEE81B465D12DCDDAD03DE5ABE9E763C440B2CFD42FD16D96EB C21FE788C8C2688F79F148AA7090BE64B0EA710D376222FD1590301BA9A2E715 D33B8C1D95F2589AB0EE476F7046537E27DBBCDADEA1E7357C9D7FA92C2F93A6 7BDDF58A44966590821023380C97CDE37EF6D449E35EF32BCA6E69DC8458511E 8DC8AB63171A6018AC9A334829E5978484C4C6E917A5F1C254E6669F4037C691 36980250A80673E0F18C9E0FBA1E5CCA3BE30B8E7B7188062B25F8E1E16528A2 F217C18D6A1955482E5463FBF097ABAF7314E449C6FEE56E2695407A8AA9648C 61AC2BF3B2D9CB6317A9B16CE931D318C8BC9676CD908505568C197D90C2BB46 06431C999EB68C8216409E4CABACB2BB34A05B697B9DD1E91471A404B4969519 E25209EF4EDD420944BED17B18DB3566FCB8059699FE416789191EC2B35086AA 2E10C139E3C9FA0A535DEE9255A867A26656213E85851DE5F51F9780D3A6E572 F1F5CE64DA176CA810799DC1C60A8FD2A5ED42E613021A19928EC4572059B2C1 EE441E79CDF7DD4AF7B6E3D3230419ACAED329388044B107DCB4DE91B71EB838 904B1F969738BBDA064FFE75C6623639BE9924602DDF0C166B433B9D54ACDA5E 018680477FB8F10621FF32319E58DB672D744959A33E7314A1B3CDE0C038F7D6 0C8A195AF191E36B0325334A711CD8E25D9C1D257E46A734779E486567481108 E0281DE96907D460546578DE83A0A01A9ABF64402B48DEF739F4308E14145753 719CEF720FE5CF8DAD7845E74D502B69DC18D172C3A27411259B8042F3FF82C3 B157BE242C351830255CF0EDA96577375A70657BD9A2E9FFC54AF0AE563D73F2 E510279FEF48D79F5F7745DBB492F1D74DA738E6A4FE4364799B5BEC93B4CAF6 B06B9B8C8D164F8FA1FBBA693204064F2C1806C39910910E02ECA8D092558CB8 33338B359D56483B7B99A1D8137204EC1AE70ED3D75881FC3B00BB9349AD934C 81A9F285312FDDC77FA923B18B1873D288C2AAF2E6D0AF90BF25A982B843789D 5662D6A2DD58E065026885601ABED4B09CAAA3116DEE6B430B15BE0A121FC1BB FDEA5A501F0798CFFFFEAB5101E707F1A00C8E014A3561FD39972EA9AB108EBB 960AEA7FF60C301AD6CBFCAA7D35CBF6F8462A4D76C4FBA6F3DF6BB762DF7900 9F69529AB4EAF96C2866444B257160E8822533A7A1240C83EC18C364F577407B 4CB314678D2511735308A1660AD94B8B818CEA4A3DC00C5A1C978F8BB4E0491C 49328F6CDF95BF620AE53056364423841D84418B23C2A447B0CCF8D8633FE2E8 4A4AC1C6C74627EECDC994059F1BAE9E6B10FA80D767B3FE97BFFAD413DCB0A8 495039744B48266278194D60422D6E7C74D0DB45ACF217797D0C0678EEB60759 6231438CFEFB346553A7A447B50807EBB6E885B5A49CA9A350EC4A8C76EDFBB3 A4DA1C9E3EFA193CDF08553302998F20055C84420A4C5252F764CC4B7A4BEF6A A09170EC417B296DD9E2301CD8EABE4A087E648E0525A9FFAF26374C47FDC123 82F18C9884843864F418ACB08041E7896FDD395225532460A8194A8DB4DBD824 1C68C6665F85059E365EC0972EC6465E2D8867449907DA6692A021F026F437BD D02654BC11381BB6557663E0B0B8C4F2FF69E4776F4EABA69311BC1AF8155F7D 6D3A418BDC912CC7CF1A4BBC8A1376D8B4DEEB6585416959BCA4AA08D4520C33 EB054DE53140992D0707210593BE62B3659E3E493C4562C2E99CECA143791DAC 679896BCDA0699E405957E17DDBD243E65CDD7C9C8629F29A2078658746A7779 0F75BE24E2DDBB672B95F26366BAF036B3C23BE4132D7362E76D4183A469E0F7 29174711ECAF4FD9A923E72FE58DF2854C5537E3626317D471D1E8A922C9BBA4 CE9163A4086AC4A231C2BF35FBC39A5BBCFE41843CAC7D81A054509D31572BE1 596E0B0B563DF2BF0E57DB4943DAEE35CA26C8433FEE4FC61145C77F65DADE75 62DA18DFABC7F4194906F53884E62E77D8AB3E099776AB93B2B4D0C98FA44C71 597202A2643942795EE8CE098FE26F1AF8134F1E75FAE18D563B1FF43A511C9E EAFB9EFCF61490A1A4FD2CF354927B72C5EDD5D62B2F3F5006D6130562A13BCB 1B988A994A8D68B051A5A821CCD5D0F8D9D49FE7CD04EECCFD7A554CCDFFD77E 27AC4AB5BF9FE40F90EBD066C483796CE1A364E95C5E0CF2154834760522F128 B2DBD1F4F73347D42635B2875A23597C35A0823CC6F71E49598125411BC9B2C2 72470D36DD967C947AFB031BFCF770FE50551A134DF8C5D1AB1F09819569A57E E23D4E87C0B52CD02B0A2E3FAA7D27A94359E82AF047756BB769BC5950A75207 78ABD49D174F2F69810AFFA9336A52D6B93B004DCA5CDE58475C0210E0BA1D20 FD4FFD6838EC56A0922472D4C4EE0CC481574BC30618179E733EA40A48847E14 A75BE7717CC5DDCB5B0718074EAB6FF07CFFE794D335B3A13EB968EA8FC5B08A 13B38AD1C2C964E4B07E90B9732C458216B028E07DD593A5B767A2B415EFE7DA 951FC07800F11C7E2EF9BDD152BC6815B7F32117F49FE08BD79BEB949003512A 327F3F8FAE1767E7842348BA4373649F1A21DB2C56C081BCF9FA4EA86C8DFF00 FF45C4F1386CF8C2C4120F3F6019CEBB639F2D272D08C1763A470D4BF6330DC8 43C069A6333113C3A0C93471486EFE9BFC02B760C7CBB2E9156087D09EE8A178 5EF50B34994094C3F0015EA2ADB6C920F4302FDEF128711994875551C4E883E2 DDEFFAAE11F2234AFDD96400BB69C1B4E6EFD75734C586A10A54A98E7D790F28 DEF7C7DF61FB23BF91AA700AE585EBDE74E215DA49F4ED466F46129022722086 8884D8E026F35C4BEE7E866DF8E0846D5EC3534069B713FAB02D4B4EE3B44E1B 656F30D629D40AA1337786C1FDA08EA1217AFA4A6E2498B334DAB5461A70DFBB 5AA5686C89FFA4EE82D81CE2B28334DC5C032487CCE998616F48150BA1281911 076E626E5BFCC56A0A4CDC559F878F14C2BD7A5148C1D8CC303FF9EC473354D2 D4FB0F0F2AD0CF182A28074ED6552E179222570DE0E0D44E8FF4DB36C3AD6487 C4BA53C8548714A69FCF8E3E5202F09469D7447C6519AE902C1D611A720BAFB5 59E27A6DBA73624F44B4ABE0988BA3450F82E03521CCE8EDE8BE7EE1223B575A DF9A52650E85545525E6F121FF2D1531F156EA9D5594239AEA2CD09EE28ACB15 A445E11FD1C031188DB61881F474D49425C084489A88A47D681EA68E7FC4B1F9 DBB552063A02A0EB51125E9B2CC646B940D46FF457415F9565892DEAC030F08B E4C10DC38D825C7597394C844CB863CE6C843F67F2E1C42C4EF86AC7FB727BF0 224B5E91BAD99CC6638AB2C64469A81D8B1789981872ED037B3A34BDF3130137 80FE80FDA65EFBC11A08B98A1AE595F980B577E22D3CB7FED1D4016F5290ADF5 47D7D9BAFE39F294582F2C084003E9C83FDB9EBC87C8B477CB8BB359EDD9BBC9 9368D6605E1468A20909831BF602EFCEC0D5EBA99A2223E5A269275C8B221B3A F9226654185929F794E1979ED18B4CD36152F973433AC67BE24B9D953254FBBD B644CDF3BF0E29A2C72113DC486E46DED2CE8F8DFA8B0F8478D1F18C9AA8E054 A31C3DBE84ECEDD85DF6AF9467AC2990ECAA3384FBCA1BBE598AA0D6813C859E 1520B88BF30ADA910A6AC3068A5B8CFD76B7F0F6F4AF4C32450D628B5320C384 F23A2B5E8756895584155226A30F8B0437E028978491DCD00E79C0ED58DF261E 79B9DA17E57AEE03EE92102EAB2D63E69A88EE0B1E2087ED0C0CF6475EBDC3BE 0324D1FC8F7B90D8D807533E5436F2C2583B9629EC390403437FDAC908557894 03054A6DD6A3586043A9C8BFD0C7EDE1229DBB9F69F7A5D20F55664D061F6517 0051C6B3CD7338241FB403F2AF77DAB1A8EBE1650156D40863EC1957372BFDEA BA8D0BB1193CC5BEB5A68C8274802E14FFA3ADCEBE19070325B1BDB960CF2988 C0F5A9BFD843C515ADEC8B8AB02B2891EDD7502D9F28F4E58D8F67D1ACAFD0C3 3531E0C7D1554344CCF90AC8696E83A3F968252981CAC09653956F4343B99D3D 4F17CB8BBE4506B354439B70F2024871D16668F9DECD8EDB872BE5E6ACC406F1 1DF4E3ADF60EFED57D1C426292970199BB663405236C6A907B6891C6190E87F2 78D9142220FF295C7BF44AF61470798FB8CFBEE6973C69DA1CC24ECB058AA753 DDBFD92FBB15560EA19D5D92F0005B74F06F0EA5901D231996E0866389DCA433 E62BE48479687084C1D67BC592E592939F806FA8BF5F0D3F644B1FA6F056DE0D 51D3F212C6818CB6166317058C2A0C07AE2E324CD90D4EC83CF4819B10CC348C 6DBABA024A5FCDAE6E288F82DA060BCD16437F07DCA43BF1E5A1B402F16C78FC 075BEE900B4021A1019C4A5ADC33230047FF11FDE8FB775DDA267040A22B4E5D 6012F7E72B8BC8DD3A81369A08FB81C6C4873C2147D03D4181D6D8032DD2B610 9C44CAB50C5BD8F489EBF01C72D4198B66EEA4E976462F8874143640B82AE57C A51EDEDE75A9A55D31587C14F8DEFFE69F75EA7B95BF725CE9991FB2F07AF568 5AFEB39447B728B99BE0502BF28DE1D92B15926BE4E3DA2E7BB44A24836A97C6 EE3A2080E01DC6514180DAF9C055F4C94929D34F193920020505E62804461630 9F42C652F9D5681C91BE23DCB0C634247E739135F925EF3D5424767D5F5C5879 C46F2E32C7B3BE9E90FD6ABE693A6016AB77670129B58B8FE719FA97FE320842 6488CB85B6BCC0012975D22E75A2E086131DE676AB825A386C086FBE1B65DDDD A19F06AA4C1D3EC84751C649F4A62CFDC48A7CF88CFEC68B959C211B60DCB045 6BFF922FD7349B98E1769394E6CEA4F764AC4B6536AAE4E6BE69099A39A6A33C 97671C3AB4E7A94DCB829FBA97DFE5F71B1728FC81F826699DFDB0ACE9BC60E0 6EC15D35EC479F3F53EE4D0398BAC138FED504A84A13B78568E3F9C86BAE8B88 61830A80F8B994D0D66A8FA3FCD6C5099C29FC285ABF096EF9A3BFDBB522157C DCE9F0D6AAFB1F8D7B0A3C573D0C170357175DD56EAF37BAAEF4C92FBE17E26C 7D2BDAACB9B8F33D09651FBE0D49A8BE66B78D075485BCD38DED5056FCE48A12 D28E9670EC7CF4E9A277D6ABC2F7AB30BFF290B5452582F372FC9DE6CEA9EC0B 84328269F14FE7F47620B1042B283C54161AFCF84B46E6B1410587295E4F8958 C1800F120B59639C85D46D46A4C64309931A8C91F138EB52F779189EF75B9157 D624045F4B8846856ADF0AD735FC6FA41F7B6C002E9D1EBD92468E86C843AFB7 4D78E3D54D866029DE5DF865EE3F7313AC358EDA70A792E22F2F806EF86A6B57 64AAD565C57E64B1A6635B7394B4B5729189319FCAC8529ADE30633B9BDEE0D2 AF1F8944EFDC7C408FD8FC270822CC01E7BA355C856219B3AC5D05CA37EB0EF1 6766D62383AEDDA1F7CDAD1DF0172E766BB46C5FCCDDD61BB019D283EDEF312A B2DBA38C9BB0928FB93F50E8516AB353BE04403D132805B5AAAA17163AB9C847 F1B54946B0775FD21325C82E4EC7F2186C54B4396BC4B0B913A59E4444D11B39 8AB56F2FD5788A9BA45DA5499A50BA74D28707F62086907BF8342E0C753A31A8 DE293B592F51D74DECA52858CCF76C69BAF2224F640069BEF2604983FB478173 792D68030D7A6E3FE083AFFE9488D872897ABFC88CA8BFE484A75201D73058D4 72A8A26A50BA1F2B50CBF98D46DFED0BA057619BF370E435A0400147928D7C06 28DF2A03527E3BE925D6A664E4640E63BD22D54A038D934B3DB5B500E075B8AB 06DB5279274E65FF870F1E5106E190AB0FD8849EEE2D605FD4F0DED2C3F86831 4EECBFAAD8B2A895F08DBA692A8176F9080045519CC6C46B52F0F31DF112AD79 8E46B9899C5527A011AB63FA443ACE90F09434C295A5D9E6753AF2645407488E D29E7711546F87265C130B76B4632242E43962A5C886D4DB6316A2F3420FCAEA 3055AB5A9E1325EA870CE87F34BB2B3110E4919E1AFEE67606B00B03DD6824F0 20BA42968B81DAE198C88057438E36056D46C550E3E5E03A99BD4B07E66A2179 BBC5B3FB06D5D72022C53A3F3A1B759472D5A50D7F7A1F4E31D3F7A30EDC1D45 4B00AEB5DF680145A123CCA3BBD801CA64B2CBEEA99842720F8DCE432909AE78 5AD3F29AC69D302C62256CC4D47AC92EE11D2A3E1C666CEA24876491BB167548 9E3A990252DF8254CB5E7141F57B78FD1FEB38BE135815C6FC86EF81B5994711 E43083C3234C55DAD97CCCE4FF3F55C5A6C22ADD2C549513A465CFA3D8A9AEB6 331374DC05A4F496BE33F9263172FB6FE1CCD19EE9515C5155ABECA9492DC743 BE4142D63FB5E17D55C9FE642F07995502AECD9D555603D15B5BE420A65A6E98 4F341BA13E44DBBC1DC8CF0D561198A2B40FAF35F7ED5FEB4429BF71F5C88637 CB114F1377FD3227EDF592733EC68F4EFEAB14FE7C26DA7031075E04289FA6DC 8A79F81E4E18CAE8380CC585E7DA3DCDA3FCB53929AA8D772D53FC6D821EBB14 EB472017FB56CE9410FEEFF14EA69C188993922DAFEC805F4C8028537A9D6365 AE1A6BEF37CE8E02B995C41382984802AD3D12AA9FAA36837F9F9F8F60D16B81 474238F136F442CA9B14620F83E4046E41EB0FD02BD04DA7863DF26624B5489A B8BA35B0B3A8D128FA10E01DC9B622C26CC57CA79CCDEEB7E174698EFDCC0CBE 879AE1434B3EC5AF48E6C2EC5652DEFE0ECD7415FA46BC0C80FCC57CC808B3DE CBE4CC7B62AD3B092487F7A23C38A2D9102DEBB1CF4C1EE7FEDE1E8BBCDF7F73 54CAB1E591F9B3B3159D879A9492394B32F2CC43EE7EBA6E293AF12D7FC4ADF4 DAF8F2F48A777E927A915DE1FD9125B52D406BACB0BEA149F6F6D79D92D06413 5D68461A772D531F2E76D1947D2ED5BFFCD758E062B5435BFD180F7E3734D5DD ABD86A1C2BA643955A36C482BEBAC608F588C43E6EA7EA2AE01D0346D28F50CD BA8F9FD23674AB19A2B879E0DD19029EAC5D74D16B186CF4BE3382E74E361427 536A00347E536701808C1D31A617D1F9269110B76A0D59C7B84D98C8FE308733 C9497B807A77D244FEE03ED7FB5EB4D6ABB74A7129F23AF628BC01BEC6C43ED2 D62F4E2133006FDB94D33CD31F9FFE57C8C9E31DC6D7A81A2C6ABF1D971EE222 96A4D79F7232190EB796A43ECEB88F1C64A88A10C3AE8E98711EFDF984BF270B 55C5B9082D54DA7D32B168CE573597DC5A453D76953DBDDDBC1798F8A645AEB3 78B6B5BAF60C9AFA9D5F818740EDAA977EBEA0F68E531550E607E6FCB04F3E22 BC9D6440E1E153C8D780213DAB08CF8CFEB03018942AF980642745D711C7DB1D BEFD825627798897ED8185D80234B6C087FBB602ADB1263C2A2A0F59AFCA7B09 EA4ED3BCF936C2DAEA9C8DDAA90130C24AD1A1BA47711CC760FF72EB3F27C165 CA1FDCF1250C6CA4A788AAEEE08902AB4EB03C6EDF281CA2F5B074C859DE3963 27F7CFC53CC91C80F779ABB25F7A6601453DF5606B72EC562F615A92C1DCED58 3911BE7784B6E8B17F8993E4D5693A327F9C289701F39ADCF583BB4EFDE1F835 1A59BBC2E6B73CF422D877B0B423E4E8FD116F5C66A4BEB706A3D42E7EFBB5E5 E73CD03D7A91719337CC8E13F9D8DA255185FBE3F4FB6DBE8EA90AF036A09BE3 5047B59BC18C1C3658ACE003B6535E42043E4D7E6D79E0B48B3D0DCA36C046D1 D5ACE0B6F91CB78BCBD144F3FAA3D9D711C9D11EC30B6CCDBF43CD490E9AC229 9ED2CFAC4F53927040CC8FD26004450889A1167FA34247B7C283A46E4C0A8C20 AB43314A34EF0BC02C5558746D35F2315624FB9D4A8ED13E3D1A8B80B872798E CCB9775F985E31E8228B03949B4E35DCF7A41C834E53CE3C163EEECE81A8278C FEA3A9E3264627D33738170C12F4EB23EF8F00811723FA4FE56A0EFE8ED5EBE4 90455B690EAE1E8F1092C1AAC07FC418A6790C2DDA6DF739B9B586B68263EB63 718EAD2B11037C5D26FF31FB2E56AB82773921B00EF07DECAEE2A8FD71AB232C 86865012F1FCC80CBDC4B0E881819601CE2FC5AC36875F2FB5C088436BB11159 813020F0433EDF6D96FD162F5E3241F88BA7025F2B010208DD1DF737FFF1185B 812864C3049CE325E06610404C8DE9322187DAA7FD90FFDF2DF3C86D94E8E792 377C1C1F10FDC78E1FDEAF718A2857C4922FA300C8D3FAC136BA2957C675FBDD 21E3A9E29C797142BA6D30FABB0D5E97AABB49D113A55C4838B253AB8D7443E7 15596B3BDF01C88C17135A74AF78551CEB6B0041BD17ECAF89321E6948E1C531 B227A1F071FC3558501BFFC842A4F8B80C14D9213E0633485A66F899BCB473D7 3C72329610575B6279C781714761468C785E426DC9393564979B1D6A6D55AE9B 4954010208883EC964F35E8363129682AAFA2D40E1ED08A4A1DF27F3DB5474E2 92B917B45D9473AC94EE40662DF06AC9D004541B6F88DF5AA4A36756620CBE83 1254ED1C3C9CA39B09E0D4148DA552B00FC60FF68E7159F556998EB8A66C8EC3 3B7842ACEE888BCBD1FA183BAB95B06B245ACEA49F8CC51A2EB01053E99E9A87 A5198C2FC26E270961FFF61A093A084594E6C0298CF96B251C5F8395ACDA26FC 461E6DB774F6220F8FA04C68519E19CF69EFA73E9A1BDFFE833B228DC19571BA 34B7AC21EB2BF8B1876BD11E128F002AC9AD6A9785CBBFE2D5FBAC307BE7CE5B DDA7C12820028FBDBEF1343638CE166E43B95E6518A83828AA3C3628779FB2E4 CE32DED584715FD18C95D38FA85772DC8650EFC42F980A1ADC012ACD93B7E1E5 FA6453179ADC6F17C94FEA1F4CC2EF6A2A975C687ED81DEB7111F0897742B373 30720766409C534C5E0A42D7221337FF3C4C59BBD239518F3976DC55FDBB8C1C 8DB9CB4B05B1D9AFBAF0FA1D82B1564AD7FC92B6CB3582F7DA309403EB78916B BFDC6F918E26A39755E5AD6394D985C92F7927FB1287FAFF2F60248236F918DC 2E8557C6805B01090A037E8D5C529E2D70976A9CBF3785F4BAFAF9923DB40756 7B6CE8EE83559893E3930790E5917EC3421FEB042C0CBF6CE74F16C44FA08025 82EDA0833C0486CDA66ACB450094BB65F54C83829B47DAAAC9E4CF115FC275C8 6BE583008180F2E2C9B003712ECE32333199BBF9772A471EADE59355FF264DD7 ADFD42FECCD00892FB545DFE555AAA4B273B82BD2740CB8C9ACD144DEEA94188 D1AFEDFA1FC63557F9E527C00AE7D14762FEC2814487CB60E406F8D4A47365B1 F7B0E0A56CEF011CC11345674611EBFB5A7C587C34F786498FEE4F0F999AF42F D955CF2ECC5B64BB1C100310DE5B6C7D106A80FA4ACE0184A6E18FAC544EEDCF 307334E1C2A0CB6E488B21DA3BDDC5B593D5ABD6006D1E2BB56336EA88D56DAA 62DAFDDC379B06EF80E9F3661C6B7AA6787ADD06155F3DBCABAB6BA3A46C9047 5D295774447BC007D5423B9840E2ABACB5B811B30ABFF547A8A6E2C18A92DEF5 D30890D49388E80E6EC7626FE3236AABBF64B21E5525FFB7C802511129EBFAD3 D1E19814500A465DA92054F93FF77864698288510AB599237D0DBE1EECF81C46 F706515DF10A1D0FB06939473BC72429A42CE6E15BA2C97720756D80DDDC171E 7E8202D385C2E5B4A5A011933CE920E98A09527DDBF49FB4DAF2E736B1E42F57 354C91CAACB68BEE8FDD10F4DECF25ABA4EFFC4588DFDB9E98640737C015EA04 A33D5AAAF9AC4A7D288BC9D4A8AAB9B852516E215DF7614B10BEF003EE1D0572 E4654DBA4D71959D403B936339D41C381FC1A206BFA6505DF3082D9FF767EF67 437E8C2A14A8B6F0FB98C80DCC42A30C57C8AC3FE83570A1B4AB404374B85F45 A1056E389A7148CAF714CF6DC26A04E3DE8E2E7FD26F6CDE3E836AE65E593A9D 3FA7A24A32E3E99A152009C8713FF8960FC93A2E49B8F442B81A90F98B99E140 5F0E0253DE8ACE69F1248040510DEAEE069307FBD02B821D1DAEADE6C41111E8 37A80AB702B8D79977DD73429695C13DF81ED3B562FF4C168AE03ECD24909A41 22C579987CBB22700D1D34BB16E5D0B4BEDB4660D34EF5CF0A4FE507198EE14D 9FAF7C97CF769EA9159E1D8210B063141913DD402BAFD515CD746A7CBC061A74 CD6D6DF78AA722FF543C5379A1AF5102B75C06F73E075BD8531353892E1733D5 8143315C0C780BBB21D6954119C0AB1D4C89EA67C0AFDD4607AF07D509F481A9 9045776F08003CB429316307E66E1F9490E8547FE0336BDD8B070290558E0DCE DB08FCF371A8A9FE905E9C3BA4CBD4F12BB2F512838D395BBCAB1488C58122C0 CD6D3634C0F6E193E2F2E8C632BB9185B20D94503E02244938D4400F0DD8FB81 3AB0CBCF32E462A223F9680A14AC8876917ADEDCC9B181D584AA307CFF3B66B6 F59FC840A9E8D1BE101AA1DE41934C22A1017A8AF69D257433C2D2C5A0474F9D 362A669B4044B3990BF83E8906C5B7E2B45D688CF12CC1FF38F2EA47743676CB 55FCD3C6261C6F5AF002869128882E39E089A6FA108195A8B86CB07913FFFA6F 6D8F8D5C9E897D63C174825286953B9DCB09B8475D0675E09C1D26286107E89C C75F92D14002B1289A5E11F059F28FA27DF23FF395EEDFD5F22374FF67F0B60E 81D249898A228A6A89141B23918E977BA79C5F5E6CE84FD35F51B136D81428E4 E4D205612F6DEEC1CE6AE571B30A33DE004A8F096656A3BFAF8BAE8A2C73AA53 D7984D6777540082F3674304D2C3F17775BDF86A27563CC2BF95F190DB3E28E9 FBD0716C0F1B0D56A96E2E870882F03A3E160621FB469355859954858C9CC2AB 06EA8F87EA163B9ABC176D704D3C17A37508864381659070B071B80C79D6D60C 7858A32F5DE87B1F818E78048CE81E229FD7BD91286ECD773147F94E7A184450 D1060F0FBC5A8DB06BB4009B3F5F50EFEECEF8FE970E3FBFEB5ADEDE9EAC6A49 AECCEB5378A9CE274BC7F25D03CF477C2054D313FD988A4D913D20ED3981CE47 8674501E487FEFE5DD91CB0E5ED24BE1D2D45C88DBE1378B11F6B7076FE56BF4 8E8925E65FBF23330B9C4A943CD96EEC06A6073AED304CDF520CD2AC1CFFAC7A 6B8D8FFB7327834C9DADF578F250A51BE64D27A2B65A16DD0204635560B47075 3A054F7159EE483CA06345D3D55EFACD47AD32A9D7D7404ED0CB742A3AB8C47C 2C5CC71EA3E1405D6E114DD53D85C2350D46A8E4BDFD1667C65A8152D9F3331D 6235F40AE36EDB507325E21496725F3351C239207C0C4BBAEE2DC7D2797B8818 BEBAFCA4FEDBBBBBF3FDB633A0C21A8BBA856D4A3119394FB00AD092E314558B 99CD5B138D4A42BB7B621DFCC2A2E2AD262479E878D8F26195A643BA0D13F9C9 FCF3B6BE5774DE6F4564FB82BA3B2B9BA29A5F406F1A135D46DB10C80CA11E1C 39C9A74A18D8EEE86C85556F8B9203E00DE0B1A164134E48FCE7F37AAB98A79B EAD809EA81192ADD3D3C6B35E521AC99E190262E5454C7170B081CB8AE338D09 D489BB694D228CE9C05DA95297BF106A3B71A99A5F199F122971F5C4B0B9C53A 4344FD111B92AF456697E0B85142B71FA56802C392C886A408558A297EC3C717 FB803CA1002361034D40420699FFE3C149800137EBA3AD99AAAD74B471038675 8B073F692D278E0A088D3F51360C2C79A83FCDABE9963A4D636631310E7C6D35 EF02828CD45CEBF9892C2761D934E07AF32BE74852C13FE63BD3DFF3619CEFA1 25F5FAC01306FD99A573F0F5F29116967FFA22C9236EE8EB052488C4CC204855 EEDB80B30838AEF66DD960389684231FAAB83750575E4C9BAE860D9B0F838927 791AE22921BAF254FE561771B7A9164362D6BD462A82763F6D19737ADA1C2B92 BD72443D7521795F9D3702F83B04BCF992667CA255A3AA539CB71F25F2D0ED57 9E0B180D1C199211FBC17EE282E7CA9E078593E6340BA651AB949482A0760790 E4C3F1446653CFF964B9A3142FF4FBE8C75CFBAEFFEEE1810D38033CBDA2FE9F B42BBD97740EF0C118C7954FBE81FDDDC74608D036A3BBB75EEED4E1A4A56381 0F57C993C4651E4753A27684D170EBC495D09202AC0CDC5F10267EF26EF4E7D0 908F4524C91AD27F43737253BF0617559F2EB99EB26643D8C28B61F8968CEE7A A79A818887ED9BC3AECE4A35AB15752A368D09594F93B7A741282DB5C6E42144 EAD79AADE23733A43500563C3AD34E0421D1E3B4642EC1D70F0054E3DB6CC218 FF930B11B1CCC3E4C90BC523D4635161C89CD9FF8F2C4F6E4127ABF479914610 4D95589775902AE3993E1CE3D4868A1055BFF961CCB244AE25C76C4CE556B8AF 98129765EA10B35FFF3D24DE1CA68BA55E133084CD2562832630E302C3823EB2 5D7293D0C760EC1788BA6BC9ADB7AF6DA83C951E0A23AD98EFAD64AD387F7764 21320EAA8DD04EFC4C2BC011185DAC3DC1FEF1461F3F9ED515E2240433D855E2 0229E1D5269092D0FF790539D2946A608E82E1FCA5E3A1254B27AA134C300FFE C7C724824AE8B8436577129608078274BB69FB6A026D0CA48B97314F596EB375 390574158057D3E1C3EA4AC61BEC73F81C706A6C7A9B42EEACD6A4B5C4E69FD2 C68AB11CF02CE3D9B7148BAEC69F92FD7DAF6C9D772BE60AD4579BCE18396E4B 60EED65E6E2E62B283F135675C188F58C831B3A7ADCACACD39871EF8905B3264 567AEEE25FB31D64C6596D60597315F1AD8F74E5577E6C966F8F65B001850D1F 39F0234F0478F6DB136F17F20262CC072B25202BCC8A67EECB03A2834136EE5E 8FDF55397F3572922DF82D25376DA73083419420003E99A020198ED0ECA44A72 DCFF31392F59E14720BA027A5A5E81B3C32BE7DBEE039CEA50AFD5CF9CB9080B 3952949A3165C5AE1EF9D8C76E0C901DF5013469D55C8AFE1554A74D6C565533 FD00D77FAA0311910C9C191ECBE1A0FE30A4FCDC3909D4F6322DE2DE90865099 ABAA1A087DE9B4642DB649ECA28D40631EBA0B3902EA6D70F9260EA9DACBCE35 8EFFA26B2E8BF4567406788443950D8A71339F595C83E28111FC90181AF60EC8 9A7EDDE1989A2678B8C570F5D0BC178C4018626B9AC851604F03C98469EFDFCB BC34589B59973E918756A2C1BB7D1811BEAA17D193DEA92EB273D50AE5C0FC30 661B330B083311E5D971D70DE46E2239532FAC9A6D8FD913E6DD03F42ED6148C 4F04E6D136D41C24BD9B973109A9B63233E51176EE64D247DE1C5CBB43F568BC DBD5A6AEDFB68E5A0C8DC465E9949A96665AB78F41132F96F3680B5A9A79DC44 828FBDA04368F277C40F629961EAA9F3B253276EE252478A9F409C2FB6447C65 37AB9FC9A216970D7BF6912FAFC92BA0C000A58950291FB3E47F0DFD493EC7CC A99555CACEB7EC87F4250AB92E7136500138087A19053E9152B6F007B8D3DE8C 96224FF8D464BD3289C08AD1E05B9D063375F38FD42CE97ADAC4E5B83B8A88D2 B2634B95A0DC0AE6A407E62D153BFC434B42680FD0F62F5FCF0818182F182D1D 6B9EBD47149F8506CF38BA61D8AE460A8B660F40DEFBC9243154E5683EA8D574 8D48276FE5128F972D96E42D89E374F7D8C72E70F84F028263507BC96F6B2B92 EF4B992CA46361BA3EDB888A6E5C57688198EF10A616F7DCCA55B4E1645FFBEA C2201D5503101C400B147CA23A805AA95FF059120C677C32ADC486DCA6E775EC 23BB704624D3755E09505C395CC3AB83D68F10E2D6E1497BC179F3CA82A3DFC2 38275D10D3253264BA9C32DA47C0088660037C7A789C1DAF75D0476BA9ED5B62 CD30BA0E268DF3537F8298BDDCA16B1C970C2863B21CD839FF6B713438447A4C C58C1F0ECE39E126AAC2353E31B6FB808253501CF26AA3AC48433D4CE5A946BF 10347C814A195929213655345791FAEB7986B1DD4F2B0C9E7116B11A4F1157CB 933B48B488B7DFE700423AD4FAA7E26F003B87B6255BB607A3A639830D68D663 A3350CDD992B528E3D2176DAF79AC03F6455B1BD626ED15299042B46F03BB46B 992109329C6F67F1CD92A620FB4D806558D6CFDD75DE4F7D6C558CD5325302BF ABBF40001F90CC940511F63F32F112EB958944E37A603642C0CDFC7941D9EC65 F1F5B2805EC17A6662FABEAC3F1A7CE8A4958D64FCD57759F5CA294236B5834B 0071972DBCFAE0D89A1BA76FA1EEF2C8ACB12E45C8D8939B3EF1DA3970ECD2A3 30AE415757A89E44CED997FFF9F6378FDB532ADAFB25872A690137609D91405F 4FDA7B432D432325F1467A7C85363A9E2825F86D5B9F9523E53FC5B58D82CB28 90D43D172B2CBABDA71E5B83928A6271468C197108584BE45647AF5C9BD930E4 18E321AE20B3D28980B1CA53F8B2696043BCC4C925F218B0AFF8E8C2BC1B85A9 134BD28FC51E5F4E803761720601C5D9D87921116C342D832BB14EFA08032E5D 7C0C4F14F118883DBB1CA0313B6658E3BB5A7ABBA4970CAB64E66515031BEEA7 F0311CD7DF8CCADCB38103DBB1D60CE59FEF567B2755D0A65100C8F8EA622025 4AFEC5D179796C4F87808A76B3F420A228544CC12427AE7A5E2FB6CD76D4668D BD5A22FF8161EF3FB20EE9FE64EFC4D1E466DEF81D20A395B020BDB7358E80D0 6CCBBB8725B9AB973B060770E4CB902F429D75295D1E5ADA0BDC01D0DA7A4ED2 A21346CC735F3E6662B87BCDED41C39EB2174C5ABD9C89A4A6554B3523E08BAD F208FFE1095E6641C548DC0B7116851695AE8813E691347526DA61EC59DB43E1 03BD503968825F7EA207E22EA04656780C15E1E9D0A00CF8CEEC4D3FD48A4E93 7E82A2D0F952F5ED616618739ADDA48480DA4665526260E4269F135C89C2F28C 28B435A1A40C924B79934D6CC536A58D2F102CB46E4C3F6F5390008A7C7B5E28 4044E385A5D6FBE641B6FB074C4E15DB9D25152E503EB7DB52F45913FBD962C4 550310BC3592CF1C56A7E19A73261219812CA9A818856901E9F0FC46FA53FD67 20A7AF35375DC845C8A9BC82F46C061F46233CE3F963C6AC49CCE0936A1813CC F7904CBE756A07106AC3D9B58C28EB405FE50A12710C7FA7B4F6900E163125DC 43672E2C565C6959C412F7CC333F49E0FF5B1AE666E0770255C43E1779A67D7A BD794057140D8D1478B7B3C43C84C2C2E56DCA12A1A536F80B16BF9C5244FFB6 906F2729E0D6C3A6AE9A837CF39F81668CE7B299F4EC9825892A961935E4C81D 7A9FE5D9431283C53770E41DB77A70500A9B21D63B2F073D75D8E11579FF7C63 3D1BD1D11EA3C49A594D1D83A733ADB8D887AABCB81C32E3913FC4B2DD1DFF11 10C193CD5D5D5FDC8080F9B99C9B29A86ACFD94EAC9E052790D6A46E5A5E946F 6AB9541056CC23323C09CBA556F1B0F28BA2C30E039B3552DDBAC17B9311BF1F 648D3527E8650B3FC89CF81256E9A4A9054D9F1A9839BF7E0B875D25EAC8AFA8 2B5663DAD7CC7DED3206BF5957291DF837535DB23BA63F9F7ACA7141E1490A68 327E35FB7888C160C2D47BC4A7CD84194FF52646DF43AC83A51489481CBA4D20 1E5094E7AC3EE66A5828BF1D87A530D7786577F164AC3D5C0D624FC6CF1DDFFF C2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMSL10 %!PS-AdobeFont-1.1: CMSL10 1.0 %%CreationDate: 1991 Aug 20 16:40:20 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.0) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMSL10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle -9.46 def /isFixedPitch false def end readonly def /FontName /CMSL10 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 45 /hyphen put dup 46 /period put dup 47 /slash put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 55 /seven put dup 56 /eight put dup 57 /nine put dup 58 /colon put dup 65 /A put dup 66 /B put dup 67 /C put dup 68 /D put dup 69 /E put dup 70 /F put dup 71 /G put dup 72 /H put dup 73 /I put dup 75 /K put dup 76 /L put dup 77 /M put dup 78 /N put dup 79 /O put dup 80 /P put dup 82 /R put dup 83 /S put dup 84 /T put dup 85 /U put dup 86 /V put dup 87 /W put dup 88 /X put dup 89 /Y put dup 90 /Z put readonly def /FontBBox{-62 -250 1123 750}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA0529731C99A784CCBE85B4993B2EEBDE 3B12D472B7CF54651EF21185116A69AB1096ED4BAD2F646635E019B6417CC77B 532F85D811C70D1429A19A5307EF63EB5C5E02C89FC6C20F6D9D89E7D91FE470 B72BEFDA23F5DF76BE05AF4CE93137A219ED8A04A9D7D6FDF37E6B7FCDE0D90B 986423E5960A5D9FBB4C956556E8DF90CBFAEC476FA36FD9A5C8175C9AF513FE D919C2DDD26BDC0D99398B9F4D03D5993DFC0930297866E1CD0A319B6B1FD958 9429B9D40924DC059325D9D4CC0344F3F997A99E6CC0676735EBCD685AAC9142 08DAFEC78BB41AFC2F1C219910BDF41D6279284EF600B69776CA15BC8A34347C 30783C52AFA60FBE3E353E2AE354CF87B558776A22C776C7A0B5AB5CE1F941EF C2D9CAC37294BF407A671F10E4743BF842143F4F7DFEE643BA3BBD8BB9E3F24A BCCF7F0ADF8BA500620C81033EAE8C4EF2C1DEF13AC575F1B3BBB66F093D3B78 5412B82B67FFA087AF57182B2230F9F2137180CA58A7D9B2C822FF04BE6CD01D 43B2CA7058C7B953F6D9B5D6E91ECBAA5CDE1159B0E59C83DBAD96D6C8C8BAB1 374EF652D10C0F3EE7104472C98DD3572AAF2D45A70BF7061447E21EE3C3BF23 DF39C2D1B35B42CD5297BEBE6BC94F7C9DC6E61EC67E4F677256FED9064BD3E4 B51A71B1D27CA4E5AA9E1D8080E6DAB5310711EEF87C40859FA935B19524AE83 63B163FA8397BDFF443227FEDF7DB27DC35D89FB1C5E435DA0619A5C88AFC73B 89A2DF5E767C5B536BC7167A840A0C32BD57A14DE69A7D0D819AC36FF32F908A 5070F32983BB007437E3500799DF5E0AD3710A4C0000F0098D5BE99F2EB9C1C2 C444FD9552D0DCA098A94B3BF176F511CEE13DB7EFFAED7C47B5ADCF8D4700F5 7A5FD1B49560969BF5C44F3749370663A04776F749DDD7B50674D93254426C4B EFE264BEE7810EC93784B7C01A7F29EFD92547E13A2C7851A2E709FBD5B87850 4A44F08F56A542DBE072D2FBC58D9E6468E1AB858DC35240E30D31C7AC13D6C5 7D2BB634BEE96FA0E10F842B11A789F72A333DD6DDCB1BC23227EBC406E50B40 30AF0C48E6359AB0C46898CDAF1118E46BFF8B00F54EACBC2AC262AB898C42B9 2E080C10DE923C1F7BD11CA700DA95F7E94C4C77EB24EFB7D5DD39CF43896343 AD32237117AD4B4C24EF2B9AAB4228720C9F9EDA61ECC327D71641E9657DB045 3E35C6ED9AFD4B88FBBC287F2B08E20CD064866D01062364E81E3594D85A3216 396597A1DFC0BE35873C5BF3B12F115AE64354DE66EACD29A904A98FB23A530A 64D6DBD4198DF302D6EC7460A65E40609374E2031E0A3E8A3CB33C9823F1CEDA 6857069DCB4384BD963FE143AB8C46C2A6953B5EE8CA955E084517BDEB8A6EAE 7004A47347A65802F42FB1C3E2BCDFEED75859F600C521207B1F12360D8B5B5E BCDDD9A8B43BE2886777EAB5A7006AB74FE08677A20579E5E0B6B949759F8346 347F3AF2C105AF9A10341270B338AB4FDC2288B79D98A54F8457205DF24ED632 B28F3773A7D9B85113CB50A9C472C537EC2F2AEC0243B6211664D78DE60EB3C9 717285D76DD931E6BFC44864BFC7F99BFDB8A2954BF0C5712F21B490CD7E416F 12EBFE13341161A9053FF78435759B60B0F54888463C4B456CBAC7490988317F 17CCF703B1298BFF7B8F1002A86171BD2B7E9D8C4E20D426C132E7A9A1020653 B82A9B932ADB1C912AB90997600AF5D56DBCE887D79EB994466A78D9040C2034 1E537DA15822B32E17DA808628519B5D964B961125D6CE8158FD72D84EC1021C 68FB5F28CCC9FC14CA321D290B9A2F8A9196B06F787DC618E6C1957AE2DD8C3F C2D2BE2A46B8A2CB9BA13255AA74ECFAAB942328B176D6E13C3810CF28B976BA 58E89F16B00B2BE618A07955CC9C46A95F5A07FB240D95452CE799C8709D45A1 85994D7BAB6792B58694594B881C240F3C36129EFBFA4AC5B5074E390AB2E39F CE9E366EA4E95A5DFF8CA2E144E2F0050F512414FBDA7A7EA24D2804D22FAA04 C2261EE07DD605953453B94243250098753EC7FAF186A2BB5FD481DE92D3A6B1 E03DCF5C2E2EB80A30D0569ED52550B5ACB2BBF67A86D4F4E65D868B2178AC94 14C344582F4ADB60E79ED161C0B7DB7CC6FF8C391FC1B2A290B33DEAB127C200 C309335A5601E10DA4BE03730AF8297EF872B08C54110804CE0FAD959F416B9D 5E13E390C820F540C109F6D0F71AF41B0587CA7450810019F8CAEC40CFC3C617 5D0163AAAF368C1DDC966CAE0BC65A31083D01CA513CAA2A5D3FDD301A557CAD 148344C2463CD950F033DF4686BC452D6206760EDB2EB00026F5318440AC8795 D1F9C0595F392BC030B70806C8FEE3DE6C140547CA3CAE9B4B3F1663CFDB5519 6F2790055E57B004E48FDCEC080F8C8417FCB849E34D5C85CDE82D435089956A C0F3E924EB2C4328CBFDA7D115BDBC58716D98B4F49A6F2E841AD8B31F2148D1 34A68D8E23ED7AF5D891A520ADE49714ACD727EE708BCB6668939DCE322AF08E 53F071980E0077FC9BA5A10B3BF911664F61327233022B59E72F38B2A64E90AA C858FEFC4476C42C6398128D10F889CB7E0B96E4D13EFE60CD99998388CCB554 C7561FCCE0BC98152D9E4FB1D7AB69A5BBB87CE684CB2795F90A682210E75F9A 539CADFF715672E0122236E42A8F54DD833D4F99E672B390CB63849D911943E4 CB0C6C9693751380E7ED446DADB9C7CD98E042FEA6E76E473AB981D8A5CED403 9A06577BF4960204938151DACE2CB21BA653A580DC8E57500B172839CBDE3751 8A48345DD78508B4D5B35083973E026272994D3D58C6BC0F505BFCF708388ECA 514F0DB510FF93CF4673EF0A19A89B0E08F3235BABE22638A843CD1B92DC72F6 7EF613DCA9053AE8177BF3650C44CCCE8F1B7CCE6EE269F54F8857B5576BA1D7 8403538A00B1675276C38CD38CBC7B73906FAA9A34DE35A9F03CE84A0E60B499 CFBA23F6C2EB6580B07EF12D68446359FF50E039E0AC2186499E9B589B6DD483 0D432890F26241863A182314369ABE41338B2883A7CCA07439FE96465A5DE153 490D3DDFEC94DFE203CA50520AB3553F6FF5630404C2A2BCA0E65935210CFDDD 433842A96E7646942824D43D0F9F5DDA9195850737EDE2D65B769292D5427023 AEB225160606F8D821F08AB9B33E8C30D492E1C57A3259B1CFC1C56C5747EFE4 792D365BD95A08758383C496F6D2729EDD5297E8C1571C2711F65FD6D6BA0126 BCC6FCADF50C3075B9339D9194E79A4377D728EFD1E597635425407FD3BF22E1 062866AC4580ED0DCE3329BD884F5E022385FB0D020CAD3ACBB9B0F696C4C911 8C26C714194A606A95441101F427247208E296212B4FDF1E68CD054122C64CD6 C0CD1EE077F2630FC30DA75EA8C3DEB388418C004557EBE97A136308B2E8F079 2A225D5684449EC17A1A288265CDC0A0FAE05DF0F03AC4C61B13C2AF9C5AEB97 4E63BB904FC564A28601A9F79E43155F3560A67B2B49EBDB1399962A2C0F55ED 73FC547D024FE86F65FE2AB8EE5B65377F9458077B0C6D31BE033B258B87E1DE 2C9646601F49B17A69341E8064F6DF881046488C2FA69AA0F9BD635057256127 C4DC77D9D71C895D3040F9E6EF7653BE1F904978749D5F98F531C5564FE02F4D 000DB6DF12C17EB6B9C13726B0DD1D8A23F5CA8B984A350DE453F808963140E4 3248089231E94E9B298DC62B46610176ECF3B8A1C77064CA3E90480C27FB8B01 5E06A2CC70485242DE5CAD12DBE8037433E39E978DCA6D59923C557FDEBCBAFA 48B435C528845F0B7BEED2323CB3622C19816F2AAD6BC7027E36BE571A1C8FF9 F2090A806CCA9B4A869E5E15EB363C608EDFD82C88A11E6644978790A0AD0647 A786BDC3B6F0531B1D5F01AD551C3C759EFAF72E146CC7BB125ACD1DD6197DC5 2B3AAA053519F55E433569CEECBA8009C20B4AAFDE97B8EA362C8639ADB0F771 0D7AFD709E4E16C1CCAC746A2307505A462F77B1B977F4EF3BC32CD87968D463 C7B02975D3269F1E3AB3CB1565CBE061F928AB2943B43408891B9D3C6FF864B8 FD69D33E79951101FACE7C635F8B2BD3F45C27F4E2F119C969F552EC2C5D047D EC3D0C212AA56F51240DB8861DF7398C3897B8DD8F1B2400FB49197AED7803AA FC07426EF806A7CB2DD05B8978996754E72BD2A3078E578191221EC40C71F050 79257CA1E7B0EAACB2C0DEEF23C4B2BCA93AF1BB58D94BCA90BC12A50FF9FC32 253C51DC821ED1FA42318788342A8C1812EB45E1A1AA66D9CCFE0D7A107638CD EFB007C6A6BE3D58B81AA688D787F7D0553677EFE62A3E59C2874A88D5719E8F 9F1E12B507D39FF42589C1475DC5F0974B423DB8DBCBA2C04075518EF5CD747D C582F0DEFE4F674617DE189EF2030FB38194C08D3FF6D0CC1969494D86A74342 337F5A3EAB685175FCF927B27E00F69A3F0B5B65E6FCB9C310ABBD731CA8D647 F87D8B2BAC0D46E4CB24290D064B536CC0FEE46BE2E0982DC832F17A8668A78D 313F9943C5CE466123BC3B80122B69278A3B61FD4C5ACEFFA8B62EB6A1DA2AEC 7A7FB0D4B1A5D3B59235430FA156F45CA682AD86F3FF33D94C0867AD1E1D7AD8 7439A4E3ABE919C6E3DE041175E0E3A1F2A878CF7144ADD7091DC52E5BE98830 0AB8869740D57C6013C92CF23FE175EBD5C26330CA8B83F1B3EA50228085651E 64F36D1E8B1FEC84FE96CD2BC8AF45198C9CD8388301B1BAE9926BD8A014CEAC 3F8D5AA5C6DD2232A3F2FEB58E86F2835FB055ABA8567A3E53D0D7DD404E0D99 7F2D19678CF28BBC35AFDD80DA0F1F47060CBCEA4EC5358FA8B000C570169AA7 6718FF6DD3EA7622AB8725FD764C2EC14E2DCDA0548EB94981931C0A2FBFE083 37D342A73ADF7BD3282E25390EA45D5AE7052C058AD6780ED90AA5007669AD9D 839B78DBC708D312C5E109E7756AE6D7D6BB2191FE1B6EC56B0721E6A53C8CB1 6519FB1F37A8F38EC33E4A5766672E4785475A0F8431CEE6D66FDFA4680BCB28 4EFAAC29A37BC21D9B884F508738D5F0225ABCDF34CEBD4D173321E328F877E8 590DA7057B8EC485BC92A14DFAA31A63A6244D1AF09F29F0E36C6F9CFF260EED 10CC0D2730237B4C7D32BFDD509B6E3502A463284271A3991982887CF56DD662 0654E725CE1642E0816092D6EA59CB60244DE99E733C2C8E990EF76B70B20B00 734092F47103AE3ADD001D19F588546D8F9E8405290CA23BB3D3FA81F034EE89 EEC731F922E6F28BBF12798A0A4D6856DC7D1987829310C32CB81B5F85B92FA4 3DBA34BD1950E4E4ADD08B54F12F923A36195790A7D91447E91C75DB1D17F351 D2FE11A9158534ADF9D06E2CA4BC2F11E9914AE70550D52C5667DE9DCDDEEF24 E57C9F372DE435F3FFBB3BD498BD0B56B1B53534CE9F74BDF113E06268AA1050 CC6D925F17CE2F7AF499C5DA843EFE205E640079F47F5B5BA0F8FA27FB30DBBC 3D3F95DE3D72DA6E726F7D599AB903EA90506732D051B5541C5952D522F354EB F8B4E8C34660F9A53F9299DABF9C0CB5EE6F0685E522042814F58A0C5B54E0CE 58BB142FF89520E7DCD0321598AEEBB393008EFC4774E2B3BAA16C714BA68DE0 C8814BDE1B37E87B1F7D4E8177A23C793F8D3F6CBC6833848CCC0885D01F20C2 479E8F80CD07715EDB2BA7139837DB3E090F2FF71A66016E6805C6CACB18BA97 035C6F33D8CB3CEB57D55B07AB10FBD469B14933299737F2535C97643662868E 41B46920C640A039A4DCE141371BCA56E66A2A6C0FF74A4CF52A851291B7B674 8B7B676307320B1DE482A28741FE51E8FCCCB79DF636DDD2CCD73F2B46C29C2B 6B32C6C58AD847A41486323E5B75AB58BCF81FAB2E7D794191D6C66F1DD1F742 6B0D0356D9460AE3287B98D3613E576238C10B6D18D4FC4FF25ED3A7A85EEDD7 5FACEAB91FB2F0E6ABB6499AE02C3B1E6D2032BDF5E1ACC575620FD8199058DD 499B758C1B5C0B69F930F3A4C73E2E363168FD7E03352DBAA3FAEB32B29C34EB 7DB8B049FE0C20AE7B36DA2F783F8AF72CFBDFC698CEC9362FB188DE13CF08B4 830993A117A1F06996B000787DDFBEDA484266BF6956FB0B27CF5613CF11DF1C 2BB3677E8CD75742BE2DF91F646817E1EC1F60EE24AC8B116CA297F57CF6317D 0F098301800B7664C0C19D12BC6C85688F105D3C91F18C6166EB9E586980FD40 1928B4190E3DFCFB858DCFB0B8A536D14B9AF13BA62BD71969E9141ADEEDAB35 1DA0931BF97D7749C4F93577D4DFFE52B373D4E88D85BE4F9E87B858AB32C26F D4417FCA56EA2EBD9C96D3596D09781E09AFFFB1B4441293EA965FE8F78487A0 5B327A789E1104D30C62248A62660C3F5710E0DE61F6F5DF848507F1CB7DCCDA 5F4D645939ABBAE1472F2704FEBF7AE27D7075946A02E322D43DB7A48F75A467 5E081127E8CC6C1F4E674A6A8883E67BF4CD67DC016F0734DB7D2D1CA01FCEE6 DD0B05A18A0FE8D678524A936B4AC20E512606DC99F412B589DE60841A0B67D0 82F5F8202C1C561A60CD6779FB9DB36D5C210973BC6460EF7A01271CDB1F1D63 FADD31E847C3B1EB0B9D4803A59CF6101D2178B0C68660E5078DCE5079FCCEEE 1DBE1E9FB0ACC7C973CD013E06A8D0D99B73E863987676E852F08756EE0DC548 D2ACE7C12532CF8A53253722C0AC57FAA8E9B95916E30B46A8481C6607CC8979 012E32098D7BF25586677CF9349456D708D37D676AB9E72877A4AA616389EACC D4568F515BFDA5F56938455FD44F42AED19E9933930F0BE06B999D82C9A1A37E BBB23B6F155C8DF5CD9374D76DE34F099B42DD6DE794BF68684DB697EA5ACDED 49880D90DBEC3E5E2F5EC08F1EA04B29174D918F6DA252FDF531D7873BF74871 224BCB8A5AD6D87583AEEB673FB02EADFE76CFB7D08ADD021FC30DDE27E77D7F 50F3B5D09196AB64CE919D4E991D84D1D583763D5ED14EF6B106399908DBAED0 D3900D1E15205C0F4B5AFF9104926FEAF219FEB0690552827DC496C10556441F 60FB15A6D64B52B2F84C6E49DFDF59816D67553AD81ED5573B000FDD6519864D C384B3D60EEF2B1BB5C1141764AD6807DBF37BE031D670AF8632BE22A7076AA9 99555DE31320B458C792EBD69279F58EC7317B1A52D0E51E950D76FB2C254C11 CF91B8EB98EA650ACCE188585E642D17A211DA2574E509EB4E87EBFE313CBFDE 51F501C45B182D75EBFEA3EC9B95691E097E46D792BC095C6B0BD266B097BAB7 9B8ED5797C17FDDB538AA00DB25482823B875CCD6E5EE55A76FCECAFFE8631B5 3E4C3E9EC1E5408A2A2010FF96502D1CB940350524C797A89A5FF8E6AB47E4D2 80BBE24B89EC689BFB00B9C5B469620DBB2F0281B757FF3AD2E84EFD0CA3D456 A481978D788B40C8EF363A41B2C85E0AE198216E29A17D67D0FB19919879EA31 57B62FA6123AC99A36840C6432895DC4528BE0D2FB5FE4F24F5DE3DFC5CE5E57 CA4BE5EC998712BE30C680B8DD1F730CED756221598A0A8E5C448800491D8907 A80C58E0D78D4A53C7B651177453802785A39C887AD73E87908D1E6AF244C67A 9A5029E17CA9F1BAFCC5802E842C33B39275F046C809F2AC427279361B3FCA39 154E1175EFDB43DCD748DC7ABC240C8AED3F4FD78FF4C7AA684AADCEDC564AED B35CF787921E74B51F4BAF2A8EC4BB2C3A78D2CD697BBAF16A14236BF7607F81 6093A211924ECEBC1AA68511F7D9963DEC9689E801CA25DB41B89782A6471A62 92965E950E21D5E41CE5496D95553FE6B9BDD94424914A3DA9F878A28BCF77B3 BDA77E647D03250DFF74A2D17CD59BCC2763171F0EFA759C453A435F0AFC814E D64E3EDD354A334150402AC48A6F84693B2C10E91C67537B45A5308502E96460 871481EB917739EB412DC4262012D9ADED07CA03BABCACDD04A6C3A87F4938CD 6EE57009BB556DBCAA1E208D1B2C03F01E47EC0826C99C8A8DFB89212193E8A0 2B2865539F8B7888664DE8CD3E5A193E6320EE7E111EF5A3EB73DF7ED921E4E7 A26B1B1D18D92D78858086F7133DF3ECC8A80E499C576DAFFA25DA530769829D FC01632F7E18C5F481DB0006621F7DD4320ACEF939AEF57A41A11E6BF8A183DC 6B2380A390E5F3568AAA53ED30292C6B28EC7EC45C17F471229E37FB8C1E5582 B480FA1B647B69280035A0823C512F4AA0286201B2C9B7CA85D5FA65648F1479 C86882D06BAFC16E0BE7EF0F4E16FBC4ADED7F49A2DCC9E151E26F1502748B2C 0BC4FECC8B11398034491060133041AF08BF8EF5B1103852F3834F6DD659494D 4AFD896D3E85560664B0F1F031ADACC315BC6140CF38668BBDEC82C202890144 64BB345B4866F14CABC63D744F3E158AEEB004AC1A550502C2AD5F9595170EC0 BE4A0A8D1232E0DEDA7F829B0D1A599BAD2007F9111EC24F1E08022168C2C34A B1DBC6A844531D7A8D21731C042A7B380A1FB1D6B82E6EA341B123F8CC078324 95A5049CC0C46392EB9116A03FE0F1B6168D272D96D8281A1527CA80A16A7449 F31C1948E9D6A0E6550B686D985786CB6AC7B58DB428755875CFAE0572D2FD6F 7AA794CEC2AF0B7099AFC1DA5B3ABB479A7530B8EB9BCE9688BCE0276BA736BA E88737ACD9E781828D687114ED67DCAFD4E7404C7C0E924A9141CC27692BEBE9 5E8660B935A6F18F321E0AFA5B606F67A4D8CDDE5B424E504D52B2CB8E831A5D F77DCCA96FC7D75E24F2D44D897FBBC3E35C98EFC52875E149E2C583AF6C10CA BEDDD89A099F97D70AD5CA26C0CCF9E65352819C2FA1174C157E69D48AB817FC 007ED04651DDEB2FF2D8D7D405B401DAEBCE6151353441860A41731CE520F75F 6FA578EAFE5631925738B325F8AF2B0E15A5B84E9E1E203119ADF574989F3B33 84404AF0FF3EF287A226E8C9877DAAFB358E5F1A5F5420767C0B6836FFE901F7 CD1DF68CA5778B4649759E1F3F9FB5C5748E295ACD163EBF1EFB64785625ECB7 A5060407B009B0CBEF3FF5935CB10233BD332B73F9C69AF4ADF799CFA08EF25C A6CCCA840FAEBBC99C8639A75667BF652CF3FC25542FA6D873AEDC7AE369BB1E C15BEB51ACB928C61F97E45559FDC572003885B999B4B91F66459BA96082C763 A9F7A5C7C7F27B9CFAE1E80ADA4570300158A71016DA3600579434AF7F35AE65 8B267F947E13216E437A98485CCBC940389CFDB05BA3E663DACF32F21978FDB5 18528E1CB7AE189E007FA0778D62B9D05592E25559747E578C17156BB507D6DF 4B4198BED9F33ABD6E93F7D084DB0824F0C351F8D820BD9530CBC821CBDB276A 8C58D133DB076D9BB5689DCA2257FBC741C5F59AECB0BAFF81E0B899291B6F72 5CAF3CE6A729BABE19AD5E6C31A790ACE92E952E82638B6AE9C0F61FF3A30003 22F75DD843E2317CBA51FEC548525A4C8EDE18D2FEA0F6D8FC00B33E44938D2E 88663593AC4D1652680D51F1DACC46413C43902F77790B1C2E266293EBFB9C78 833A274EDBF9BC80D19212D2635532B935766D0006697A7EC775AA3657152D72 53540266F89330E3E19671E73E4BBB5F9A716EB13CD23FEC5B5358C7E004F101 6100FEBFBE124B765BE98D24BF2E89AAD4A27C75A3549CD3907BD582E577B1C9 1543C1AA7625E5AC9AFFCA8BEB637E5EA8C2BEAA30C8A7741D954422171D5086 07E87A41204D0CCBD3A22E2D5184764921F19ED5981C52B539B06EDFF7A3EC02 DF85F0132F038BE6CA49DB6A4F5A17CD5FA0AEC05478BE9605A3F7BA1159A76F 03A38668E6F2C72AA7E4DDE730641216CF7B9A61BFEA6EF937A54F2A2962A320 9498FD339342ECD80A0FB71DE820AE65B80A5B7A8E9196D2530B8DEB0A1FB8C7 15EAAD601F6836A6C8C0605BBB6A336A523A6CAF13B064D04F48F002B579266A A46A47426ADB627668386804EB7AA726E1D65249F6440447BEC02306368C6B9B 0C736C4E5BD2362B7C9F0F7540B5DEBF391141BAE24EE7995303C1967B3DA371 E0E052DB1D5259725163265BDFEAD1798D71912B4C7AE63BA1CEF08FB8A15E3A 25D67D9E3A70A040AFC254086D02FCDA5BCC1EF37450BA967EA9AA5C952AB4F2 64F3D7487617B261CB8DDA5AD34429E3474A5C12D7DABD9F7053B22935909AE7 D1D554D0C24436476ED68B1D209DD7AA80A6A547E045178D1763D596A5CA7AC6 4E38DFD247A13D54EE7F2FF5A3442EDDF7F4894CA301A05ADD6E9C5020076497 F2BF7F15BC210DFCE1A8DB7DB5ECA33EC5A7D635C089620177BD3E1F981D9CBA B1299C0CFB41F53253A367F7B05C110C3702C570EE29503EFCAB28EAE54FC81C 922A0A80EC12E1A5D7C191603CCEB1FC7F41B06F2D91DADB13716D2D1F6BBB2F 927AB0F59DEA31F198D5422989AF7AE03D5F4AEF146323F8977F79540DC4200A 89615E702B72127B7FAFEA8152B53EA8ED9BE3BE7EE935B61ABD0B9C3DFE96E5 B1A47626E4B62D96A9AEA785524FE73F68FA218DD58918D55E8338000DF0F5AC 6ECC8E6ED15AF45B45E74AED4F06C132E8076E21C79F6D313494BA23EAC84742 2F778B9948CAD5BA1D589A3EA21516EC56A5E40D4CC0A5919180C2736D6570CC FC03087BB9333C11310C8E5D814CB9AE8EC2D2973437F8B80C8CF48930E228B1 4B35BFF4A7423DFD51D881829038D15AA5E3AC6AB976D3549CCBBD59034F1E7B A539B629EB8C2FD450677510A7056C1D6184C20AE04B8BE7525526C9B19BC64B 1B3F6BFFB675B7D218D58C8D87F4EB1A28082A923D404CC58859AE55F0F8F433 3063E52630170B2CB806BC95469581FB149AC66F00C26466ED3E1BA6459309DF AE6050F36FEF2453D0CDB3DDAED0FD1E5C7B21A9469E62E9CC09 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMBX10 %!PS-AdobeFont-1.1: CMBX10 1.00B %%CreationDate: 1992 Feb 19 19:54:06 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.00B) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMBX10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Bold) readonly def /ItalicAngle 0 def /isFixedPitch false def end readonly def /FontName /CMBX10 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 12 /fi put dup 45 /hyphen put dup 47 /slash put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 55 /seven put dup 56 /eight put dup 57 /nine put dup 65 /A put dup 66 /B put dup 67 /C put dup 68 /D put dup 69 /E put dup 70 /F put dup 71 /G put dup 73 /I put dup 78 /N put dup 79 /O put dup 80 /P put dup 82 /R put dup 83 /S put dup 84 /T put dup 85 /U put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 102 /f put dup 103 /g put dup 104 /h put dup 105 /i put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 118 /v put dup 120 /x put dup 121 /y put readonly def /FontBBox{-301 -250 1164 946}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 2BDBF16FBC7512FAA308A093FE5F00F963068B8B731A88D7740B0DDAED1B3F82 7DB9DFB4372D3935C286E39EE7AC9FB6A9B5CE4D2FAE1BC0E55AE02BFC464378 77B9F65C23E3BAB41EFAE344DDC9AB1B3CCBC0618290D83DC756F9D5BEFECB18 2DB0E39997F264D408BD076F65A50E7E94C9C88D849AB2E92005CFA316ACCD91 FF524AAD7262B10351C50EBAD08FB4CD55D2E369F6E836C82C591606E1E5C73F DE3FA3CAD272C67C6CBF43B66FE4B8677DAFEEA19288428D07FEB1F4001BAA68 7AAD6DDBE432714E799CFA49D8A1A128F32E8B280524BC8041F1E64ECE4053C4 9F0AEC699A75B827002E9F95826DB3F643338F858011008E338A899020962176 CF66A62E3AEF046D91C88C87DEB03CE6CCDF4FB651990F0E86D17409F121773D 6877DF0085DFB269A3C07AA6660419BD0F0EF3C53DA2318BA1860AB34E28BAC6 E82DDB1C43E5203AC9DF9277098F2E42C0F7BD03C6D90B629DE97730245B8E8E 8903B9225098079C55A37E4E59AE2A9E36B6349FA2C09BB1F5F4433E4EEFC75E 3F9830EB085E7E6FBE2666AC5A398C2DF228062ACF9FCA5656390A15837C4A99 EC3740D873CFEF2E248B44CA134693A782594DD0692B4DBF1F16C4CDECA692C4 0E44FDBEF704101118BC53575BF22731E7F7717934AD715AC33B5D3679B784C9 4046E6CD3C0AD80ED1F65626B14E33CFDA6EB2825DC444FA6209615BC08173FF 1805BDFCCA4B11F50D6BD483FD8639F9E8D0245B463D65A0F12C26C8A8EE2910 757696C3F13144D8EA5649816AAD61A949C3A723ABB585990593F20A35CD6B7E 0FA0AD8551CEE41F61924DC36A464A10A1B14C33FAFB04862E30C66C1BC55665 6D07D93B8C0D596E109EE2B1AAB479F7FAA35279ADB468A624BE26D527BFF5ED E067598E1B8B78188FA4BCFB0B51692D07B0BEBB930C6F0997B437E2C51B876B 61A563A2673932C2045833FAA35DB22ADE12102335D5DC734AE3AC5EEE6658D7 92EB62131E1DFBA441F53EFF9021D9D4C491F26BE8F54C61165CAD778CE8695C EEAF70E3B20C64D4C2B34A084B5770BAB2A974E898F62BFE90F132A37E2DCA4F 43E13DB13C94DFA8ECE2B7374827AE168634FA007F8981ADA046CED3448BF453 FCD9A4F194FA648F9FC0971734BB69CB73439CB0DD021D44A7C11BF295E81733 4DFBA460FF3D654F9FB337E99E6D66FBA87A817EB9CA1536C84833870E3626DA 55D48DE850D3E6F6B29DA0E7C9D681283586F208DB8D58042E3A7CE55BE84822 C98237911453E479EAB65AFEBA3F61A763B40E74535BE56C9D8D06DDF9441741 5C9D9D917439368736619717FAB4F06E2C329AE0BA411F3FD522D9C33AD8369B D7DCC9DF993778482F35F965973DE876FA19E109AA198A00658AB3F0D8E3DDD1 08A573F2D525202AFC57E05D141E6C0BB811E1FE280EEA002B7A45BB363AD06C 318D320D2C81AA5DCC842CEF66E7DF7670588CB39C9F42EE7763A3A17372432A 173BDEF7ECCEA297CCDD76A835C36DCE9DB8F8CB66CC71B4920CF5BF055A5260 5B41A5373BA6E4F63C85671D979EA5EC30D22163E6D206168A3827F465279870 CA80E6632872F721BBCC622EE4214BF723551C846765495FA9921E11FE1A950A 53150C3F5D8595958A47E0B16064CC3AFD65DA294FFD111153F4F233BC5468AE 69585C16CFBFCA32C4B96C161F47B56661DF84FCD8ADD3EC086CFB6BB5179BC3 A5469A1CFBC8620BC711F42D0D3139BCE4E38698D9C574450DB43B5A19FA6D54 0368BA9F7A8DBF96DCD0B8968CD194264E6DD10A958846C278B8C2BAFE7AAF8B 44C84C955F1A89A13E62A054BC76CABBBF6296DE00A79CD7C8C61C70F127618E 9975B59A880685E126F57AD80F8F4D376E1B476BDFDAC868FB6AFAD9D694B561 001623C4D9F55366D053B52F2B09EC08B81901AE0986C5350312E626006038AD AC15FE313FCEE1A2E61F8992AC00CA7BB7F997707EA377D37EA6FF35BFBC2866 A572B31491F9B80445685DBA5E62F166E80589F768FC95BBC79158C23B2F1BD1 25816F1486A64F76D99A638AC0DC101FDF390811B3C118C2D972B2E7587F6F24 7F1DB2DD922D237A7D18FF08FD665355CFBBEE799D3BFF11CD94CFFDBA3E725E DCF4CDE4307E3B199D91893A365D04F43A5305BDD2538E28A0788E061F3A621A B4A04E5063B47F0109C1693A284FA43E8F1EA9B68145FF51C005D3FA40713BA8 1879BFC3CAA881B9D885A0C1AA8BB9A8C848963020A5B15F862E7DCC78F25D7C 56437215999EB78142C128C6CB1E6E75EBCBB1E4614E8516FEB1E68400C61326 D9F9E8A41216901F77D9466455E2A0B45FF50B27B55A1E1DD4F243C92BA6B175 8F7695CFA1E91CDD8651AEBA3D258FFABA6280BF2420A98FA7CECD552D152CFD A8CCC94C032087A28D68332769DD2CB4ECECB15717C245BA305CB616CC72644D C78326E77FA602364A7B1630CA0BD0282FA781E14282982C1AD13479B6178D28 1CAA541FD3F4316F4FF81C53496DCDF5F86E0D7C870FFCD85B36C936B1E08D78 CEF3823546BE4329B97EFA4E2880AF3361C0DD67F77C8BA6F1CE3822B7FBE567 064ED0477949BDA06483F8DD04F891473C8FBF73A61F7C06B20FB8B5F0BF4B77 1429190979A4BDB29D77E94D5FB486A93B8B61DBC84AE06B4E06CBDA3A942043 9F9926F541DDE4E9B734A985F9054493508C5F7EF9ADE372C520840F15F705D2 51826A537FD158C4105443E38116307A1D4608E9C6FEC3353F57E65E150EAC0D B923BA82331D83E41C97ECAD6F8F32242DFB52EAFE2209B9F41DE483C8549B97 407186E3A04011C8301B6C9A6D36D8170F40523FEBA5E498B8E5B7BB28581B5A 08892C2894316068537336338E46F5113462AEA9DA7102ADD13EFD2EBFBC27EF 00B38C25E4E23843C50C888B22BE1C76AC3F85CE148B7EA0F47D72E56726D13C ADE5A5D539A8379887352298B7ED202D909C8BBFAA0BBE7CD378B80488333B88 E38B1C3C8DD17F32583A642A1D0A4408B0C244185C1376364E723D83803813BF 106524811B9116A47F0A3205513EB80A4F798B330C9C4560F98FC3A2FA181680 C83D6BA02AEB9E57310A60C39D31D5BC8AE28BB3171F90B69C11688521BA0845 3F7D6E4CDB496E3F8B46D080156669BE81DE017A70B3B7D5EFD202F26514335E E06DF49F24576733B1BC191480D8C4E613537A80FBB7C408E7562D31833E3405 2C16297EFEA28E55E929640DDC8D9C12D15A89A03C8637336BDD0D712AD5A2EE 34012D38FD1AC70D13C3833B0A055B545F9EE98A463A2B3B424CC138AF6CA929 A7BD80C3A804D5F80153DCA086B862A7D621B47F109EB93D67A73934B066B546 BF15F27517D10CB8C83F7B319F423C16B42AA435231B9C4A05053D7109715804 660B7052FAC3EF49E66AA763DCF07FD1AEFB5ADBC9913D3329AF36A7C5359038 963383D68357C48B254DC2508706B1D5B71B66E2589214A336ACB11EA0E4070E 3F993DACD86186718E488D4734F024DB314643A9488841654924DF275A1A2221 2FCDFDB677FC3FB49409A644CEB01B260A4210613C0AB3FA3BBA7CFD4CF2867B B261875B9C592124D8A5609FCE7B376A39F6AC86E94F40587F69BE0E8B4C2E64 DDBFADD699BCAA66A856556CDE4620A3C104EE29F9523D0ECBE6552A1B8211CF 66D12AFAA3E9611858D51B46039B5EF0F3E9A020A6370B34E80F83195A643F15 86934B5BA8B60ECCD0D3C9496F8D32E70ABE513FCBB85A77D992E73AF8B955DD 5AE1FDC1CD972E81DF6816DBBDB583FC1410D2486F7479F1A466182482EFFE44 DAC31E1F059370329DE19FE4629F33433576C1E3E6B49F122F2F7333C36AC744 BA663E209AB384C9AC13B5AF8E9D0D7182D5F4D1EA874AE24DBA41DDB6586535 8CA487EE4084602F3F2A7A46A1DEF17DE9B98728FB8113FD1BC2A62D3EAF7F83 EEB13A260689B6BC369064D027601C48AF68CF0B507BD5AA8426833B11D5F086 E0759BF00A3044F0719679D27D8D8AFA8FC303917255FBE6C1317702DAAB2C88 4669AE63FDC111F7FDF28CDBADD14E9D82CB39340F567FFDFA4716CB99CED1C5 871E005ED9EF2A8C3BD948CAD403F180EC8649FA7C4258DB0E1CA5F1ACA24DBD B59A2D1D7D920103457822D0F03F7D4CA5FA2D944B13FAFE51C031FC9416E5E3 4987815ABCD52F279B7E1A86F659576B57860004E6E22A6FF097760138E683C0 638CA1E808E4B88CE859772171D8F864F99FA82FBB5909E75603C5010D49C62F 256EF48E28DB392A15716DCDEE0993D3C8B9D7A8DEE99AF3401FA9A39521767B F04344EBC10A08F880FE13DB7E11AFE3372B8691EA9807B11BAE3C4B7536B7CC B58A3DED042A85AE55ADA24E74A0A50BC5747F9C8E816A132CBB3987FAEBF451 22FE85DD817E8E6B9DA980F189103C5E972614AE92FD7506CC61589B2284BC84 A4486A73B619585F82FDE4410A3841729C2A26E7E6FD5052FEEAEFF792EC1B58 0131564B3C5FF80F3FDB1132BC1D83FD8D0B4961AA68000BFB9A0989036BB0E2 CDDB585566EADC55623BDEA1F218DFD343324776DD201CDC9AEE023DF5B98195 AD23DE4BB8EC522DDC094D15A76FD38B85964AAAD1E2DF9513B87281F7106032 D833B6E2019EA1E9D05C7AB6CB34DA376FD9BA187E8BDA5DF7EE06134DA2F577 115F6E891601CAE2BFDB23FEB902E2B1A43F7A834632B6A7784EF9E9A659DE56 5E7E66BD19DC11ED276BC0E117C8968E955629700B639BAE108F342BF38220BC A4C110641D1F70F6843206711275F5C33A6100CD20825B2ECE39EBA78631E349 FAAB77A671146B5A712B40F644B86BB1BF3EE8F75E49ABBC757485C1A53BD9B9 34BCFF603FFF6AE40A641E9626B0F9259F79B06BA573D6A42DCFA21A7D69BF63 E1BCCFE3816EB1247C9F6DFC07A59656D89D69DB5DAB731BC84B77EFE8860EE2 AD317C5F30763FF2C1B9C00C0FD480282FC591C84D7E5AB2A795B1D2B3E50E5D 6061F96ADC97AA2DA0B04E96F8E3961CCE37109474963F05E9C15FDF55214DD5 210DD9C43391D12018AE5480429C9D0738CCB2B0178A8824968536C99CB0BE77 B649AB272EDCF07F46DE28AC2DB08DEABD47C1EADB1B2193EB614BC26FF58583 B4543394A1C8DCB80606EE803B273D8E313179922EA334B26E58EDA4C2BDFF7D 3A7D83E0EE66A4FC9C6BC9863F8F9752D66CD473F28194B9F26D624F30FF8DBC 77A700D39436E16839628F46B0F3637AA4E8BF1B6F5B95CFECD5626B13634939 C46CE51287BCD099E31DADA771D251961E311640C0623956B2AADBD1F18A5F74 8DAFFBD0C0AD49F4EF2880A60AE0DF30AD1425B79DB0CDCF9472D2EA009E9829 56EA40DF5941215E176B1AF92C6374AF78D9E6622CB915537EB9F5DD807EFE7C 9749B43CD46272AE2101C1172A5210A4F71421E75C874046540050485E27FC7E C4A5DF6E3679343F161F3BDEDE5BF274D8B052224E987F4A135D2D8FE7F84EE1 E0BF07ACF7C40DC3A9C50CEDFB0EB5EDE8FE341E696ADC8710EFA61526629305 AC390632DE1B80CBE8B55B2A9600D8B94CBB43F4E0728C08B250A8F4FE484720 E6A260E226D420DE06A87617A3264792743639A0FE4A2ED4D9627E78B0222991 A583A5A87AEA5D695EBEF083D770C5771D7304E17ED5FDA30485E82FC8C41B86 4D68C82CC51D87AF64B277E0DF3E97BD5887C7E1D913185D2FA7F29FF0BEC2BE 14A3E6D029DEA2D9DB4A08B5B3ED8157FEDA81F552EF0918ADCDE7580C48FD58 B0FC972EE053225A5B2264685C7A14AFF0706B13EA016721DAE4F8525B8C1E80 A3213A33114A3007B7EA5CD2B1AF43487F191D22A5C106D3BA83A22673131EE2 5B370CC9430E2FCA3B5E3D181FF1FE29DF3A9E6823F243708D19260EC2BF31CB BCBF8684B4E663F3B93AE10A636CC9E2F075C29F2AC4951E85DEE75B87FE2438 C389B91443C821D4183C0C35E916FF970B51856FB04B61FF8A265206898EA5AB CF60214736A9A0A9C320F462E7B6F7CB43C084589B88DF4217C69434107D8DFB A9F3D9C248D26EC0F1225F842581F27265516AFCD19B9FDB23A18ACBEDA6AE5B 0C8445E30DA6F2611E3173B7E7A6C2BE8BCEE2FC8D688AE82CA35AA85B47C48D A64FDC522636F50ABFC0B2EA41EA35D67B308CBF6C2A86B0CCB58A025DEF703B FD186ED17A94B64DE3F9830621D11F0D94F518030A232D7C5927625B2B61F414 ECEC88EC56CE35BD4AC7F7D4257BA661D2856B8043F236CE60FBAC9186E0B245 9CA6DAA942CB5E4D5A4A59A48AEDE5EB78FE118F766FA9A16ECBB6CDEB641421 7267F61338AEC49F83A9DEA6DD1F7FBC53ECF8DF0C6C2EB871518A94CD832E53 1DA38A4390638D9115136C9D7E3FF7494DD7C2033D39D21FAC65512164664997 785058E339CBD84ADC911F1FF4633667B7C172748F83235C241EF9083A29B907 AC96C96B45CB517099E62B7E1DFC89390DBF51D02F1BF2A1AFD3AE38E3026990 5E9F5A6FA9746C9E61DB1A6EB4F484C4EFCEC8F915F46E196ADBA0D2FDB82E3B 1A97DA40A76874B349BA4D480C360FEC74B1CC187C76128624D1C063D077BB8D F3E50D3CB072C7ACA0F3346BFB1D112EBED706BC035F8C8A6A23474BC914E551 1CA4FA8B354772352F7A0EEBDBCE9CBD523CC03E2C5C03084FD372DC9F7113A8 8ACEBCDA2378AD0570714AD3879C7A05F120D18DC6C0AC7C5950117B9C8D24A1 D59CBFEAAC8E439E52FE8438B59A7164CAF45C78E8396FE323FF38EA05B2107C F20D2000F220EDF53987710F0C0E2DF4230391E545C2D21CC810A8E902323A2B BA82A938A9221298D214BA068ACA55C690B7B7A508BD6595860E880F7AA9F030 27E4243410CAFFD55BA49F5CA06A8FF416F194D3E3AB7192ACF871C7478DF987 16540ABBB52520CBAEEB922BF441D940E813995D4ED3D8DD707A631707D5F553 D73223CDE27A4699C2B377C319C1A0896AA544018FE978F5E65B24B278A108B9 8F3D7FAEFB97C51F9AC0CC60BD9CC620B315C91027B83F0153BA8F7CF627934D 6D44536CE65F562ABF7A46DD66401FA9158F3B603ED6EE02C14B1919613FEC58 8243E4215173307F4EAE1FDAB515F26419DE06FF2DF62D0E0E60563BCA2A7634 4B58344AFFA0F104229A6BBAAB5CC149573A19C5903CBC58009807EB095ED97F BFC664A073337252DFCF946620B1679778D6EEA5C1015B0F73E4DBC798F90AE1 5CC47F90690314CDAAF1FA54C47C9DA655DAD56FE577468C6199C346CE0D5C14 F3190325FEE8CD9F9545625F5F00EBA1B449F55FDD4E53FAE7C5286468677ED6 2F324DB5A9C804C8A2BEA08625C37E2341E5C5A49C06C15F23BBBD08D56FA07D 2E6FDF1CCB9143BDD8EF3C48079B16324FA502C29DB5120878BDAD0A783CFF92 19AF72D3844B77A18BF1D2BCE1C41134761176794957AF3B8634D9C5A269671F 5676B9D71F99E56EF7F84374F15099EB73515268827EAE0B114A10FDA6171656 249A963A32C88761299004EC6848BD76B6D8D68379EB302D2528ABBEB85CA4DB DCB6B0C376D86530F4FE8E17B93952C50D2136CDFB1E217748CEBF8AA6B46BAB 73034165C62F02628CA60EACBEE01864323CD45EAC63832BDACEE0C39BF6952C A07095AD3D82C80E2875ED7B998F8D9F5D26D7416AA70E53760C04D2F07CF734 E9AC0CBE98C1642B93075D96E35AF27717A52EEB4898F148BCD6F792194681E5 F0A396D7E2FC5676FA380A34EFC2085A7D0A5DDBA1476D0823BB77CEF027B833 A144BC9D0DDD83A6986D4153664226DEEA70796247B400AB0C53148D61BC69C6 BA4C4A288ABD172909EDEDB5CE6494B4F86A42572D0BCBCF857A64A13503EC6E 4B495640064B9C4299C0B6AE174DEEB07DB173AB3CD0A00F03E9545386A3AE24 717387668FD6EDFB94402E3512A7A6F14ED8F079ABD4E161D42B40BE5027E3E4 22D8EFD20D83D85AEDA43557FC14973ABDA50ED56948FAC97B44BF6EBBB6DAB2 E05C768D80E843837DAAFE5F4781812CE3364155672C77AB66301A94E2A9E6DB 85EF7C07FA61CB474C2CFC6A2F7D90962B4C0D9B95F391420EA0938BFA21461F B979C547DD7144D2C73A0DB184D4E1152F82A559F09EBF4620BC1B9313E03FEC 0CA4C8D1EBDE10514F3ED772C73E76E67E3B20805A93BBC4E9646827276C758F B57CEE6AF20227134072637C357683DE58A7830FA2227FA344860C2E4B332268 22E6346071A229CA44AF26E180BA8AF72645D356C8AC2DD443F8C9E4775316D4 F832981E22EBCC3D707DF08F12114D104341F83E27734D81A56005E5C0AA55F9 DBF4FB0D4B17BDBBDDB80B3EAA35925C70B846BC4C49D0ACFDDAAB55280E838E A962BB1FB63870089E1670EA0F1E6F810830E100D00759E16688AF88C5E832A7 01EBEAB36927754AD34FBCF10F6B787B6CB1F90EE1C119A62E88B81BA82E71B2 97ED389F742FEF4B76CE6A17D0516BCFBEFE6F7185A54397B3538E190CC19E2E 4CCB233AD9126D64977FF2E89C12CBA5EB2ABF6E91289728CEB3CF67950765BD B6CB85DDBC55A6F452561F0AF5350DFEFAC063CE5F25C6F00C7D2CEF0B880324 A82CBFF49C6796AA0C943440218E59C2A98E43C2D2764CAD05C0C5C4EA10F598 F97288CCEE303179D86191444516A79AE6C4FD1E9E60615E3B547CAB7D471F32 0CD1AF2B3F69C8C047FE1A01845D1F1A6EFED268601F87F8A92211BAB650913A 0A2D98053C511FA63A8B3813E2E2B3FEDC870C5E6206101C4DD70AD1CA223A32 FB276691EDF2421D12A4B330C4BC655A1218AAF015A384B8057A71B8696FBC73 CFA6A9CCEC4AD7B0789E290F483E96E741325E6062C5F0B37C50F75A81D00344 966F1FFDB35329F1653AC58EEE4C4B9E97F89EE4A3DAC15D67B6FA4C814A0995 7460E20953FBD68438F0FCC139724701242D7C45AD30C72141A695453D003D72 AFC26291C1F4BF991BEA7404DD85C825B840301B9215060870B1E5177D0AF621 83FE4365ADF6FF293B7F9627ABA242F0A3E4A608570E46682A0CCF1284961F63 B3E68FAD31F3452B5ACE03F95505B3BC194C783DE0F8BF66CAB795BAC0544191 4D98F68ED7E13FA2A535722B667F6DA5E91E74A01D815F8F3CCFB5B4820E0797 3553604F9341EC1B735D9F96457879D61A216A449D7B8A94C928154358253459 AF775289AD8E86DA52D05A2C58387ADC92B18E1F0D1C04CFBEE4877F49953FF2 42A7654DC8812CB057B305A68B6C22C8BAAE86855EC1ADFF0B3E00D60C853807 20B98B49E7B0A9E1583E685716F6C2CC58162127FC8558AB128B53554A679763 512DC6999BE36C0110423659F580491D0071B4AC2374D5D305AB506B24E63E44 BBD84371A903BF4CC762A0E0D3142BAF794A332B629C0C8F87366F0130FB6E7B 84BF4D812759F2AC831D1E3703177215908039D66CF07D17258BA2B34EBC5D68 E86A5F0252A7FD1EDACB59639A56C710049D5612818EBEE157A773D8AF209CD4 4A6816A6BA050D5C23B85C53E6C50CD2ACE0B218C8F87A54671E271EA0A8477F 4A1DD5D223C0C644580373A57CD67EF1CCF7FADAFCD53843526AA357F666B835 4BB78097E85D4D9211DD8F506380056F03D9C9DD9EF63EE9AE3A5FF0F74C654A EDB34C3E9894E6248A583032501A0C4B3816262300859EDDEFC8B4B095130B91 A0E583759F16CB9E5B38C42CE172DE2DE760A9E994233F006CD772964A621DDD 686F4DE3DAA62A937ADCE746FADF3BEF3FC2F90C3661FCCCFAD07CD4C22A2F8C 4DF29BEC9C4ED7FB3006301DE829E18EC81C8B7F27EE3AEBE4292548C844523D A6F07705F4F16891D5C310B62BC698014846F9887925163C732666B6595A19CF 4344B5391DC011EDA337BB0D00891E6CAA8A6DC61C87C467181950BDCF13A7E7 BECB71FBD2BFCD3D93135D5A508D172C3F63394A741E1F6764735A61B90353F7 B67797C681A1AB28131E8E29CD12906A9EE1E2844451FE9DD9B0228AB93C7310 F2FC310DDABB8418B1C29DB475E42233826FD9D0800196D6A825F380165E27EB EE33F99FCEC55AB289E5D5BC4B02DE34008BA722EF503608673CAEEFC884E36B 2D2BF1B6410DE582CE243523ACDBBBDF75A886CA62C634F99A8216AAC0B762BC 4312371C42DF685CD54923B02A5C7610CFBC2F1AA39F0FB7EEE423B787308DE5 634071E08F7659C70A6EBB94826EFF8C817AD6A01B13E91F0F15F43100B0DB6D 052DB9CED475535E482A58E3528B50D66BF785454A17DA4E4280AAF58F6441FF 0D18F744E745FCD33024713DA26FD532E640E9BAB1195BCA469E9FF2476E9008 AEF4A4A68B5114A7C2A29448DB7A9E93AD6B06429D760AAD16B48FD9D5395480 36315FE778F795CD7B4F4F5081F8636FE81681E643BBE83740B8393E22293B6D 008C845E6B3B5F518B34337644792AC0169B793093D308641F4A4DD3DE51AABE 95E16160C170D0DCA01374D0EF9C0C1138AB40F2DF6E4E7E5C45C8707182F8DD DD59586336662C831FD0228595D89E5818A85E6D2C461A252BC1A2DC5895D28F C2CF0BCE8DE71A094B7BFB56A0640AF9274CDF166B0AA5F9E32C5F595ED7CECE 10F6DE434D4CE74211A93C88625E508546DD3715A18800E4829D27A0F1067F0A 31BF17B596F13E728FBCC9FC0EA5D01AA51B5CD8B76258FC9A283D7E7B8CF14C 80D2EAE16E5F6BFE3F773B6609BA7473B9431C7DF9560AD9FC6E4D64DCE17C7E 9AA26089E18C5AD0FCB8F1838E58124B0028B2C2E4D5CDE965D02195C16E968C 51714CCF9206576B6D07128DE08529C4D94A1E2986E9060CCBF3AD61C605035B F78A0F954F3E1E5227526C47631375202CE7B71F014053C68652EC5DD89001E2 780310E4BDBE74B38CDABB12B604CA278AF003A951F7361A607A3AF0E1CD8C8D 065668CB80022EB608FFD13A49FFF3DDE556B4F8BB7D8B379120AAB86D71AD8E 64CFFB848D698536EF379DF427309125FDCAF1F521A767B8722DDC88A64F50AF EA8043686A2BF63A8B447B6B588ED2985C773661881ABC98E09DE56F7F1FA305 78055AB3C1C99FB40A4FAA548BD9CA0B95C29D74E6A32F3058EBD42AC47B427B 98D24AEEBDC0F957EB5887100659B402AB542EB5EC0A4CD278ACAC36BD87798C C41B89E8888E23552B06434635D39D6E4011F9E155D648029FBB2D9F8837774D BB8A7D722A8EBAF520E0CCB55EF124E5E189BD7332E0EA5A90B10AB63FE405A1 6A40F4B356482ABADD9EFE8E7D2876F5BEE9405EAA684BEFCD179271C29AF089 097C485E4D7911EDA8997D29A67B9C225D592EE5B3B79C3F8931FD7B1A6E3960 328E1E2718E7F999714A6439F2DD59B5FA553106F3CA3F82D7247F61020C7440 F88FE379239A75D25FE3B3F20EAADEE28864FE249EE86664C792D92FB6E0EB6A 9D3F154EE8B06501A347761BEAE8929E122790A718E2389AF824728904A8D449 8DC150E294B5C9F4607019120F7255944A9A8D269ADB25FA6CF19FC52B50FE7C B86962C94561EC3386D0D54E476AE255B82A242DF5676D26242C59391D0796E8 63039DC728F0787DAD489F3DD3F7DE89561892A5E8A38A3B28B7E942CD331E9C DA010D80EE13169C73F055F2941462B954C1602E2BA63DAD5578DA5ED29F68C5 50A869EBA6FCE2683FBF6A22EC68D25B306A27B79AAF8E889E82E2986A8088DA 7934ACB4168DF49CB75BDA561940C8DD8A7800E4D0A7C1DA6A23C48AA319FFC9 3AD59846534F647DA0263EAB436564B6A501473795D2E5B5BD1E071292F958F0 909A4247E8714F06A959A5FD8407A4B5D701CAAA3D7AA7931E091EADA1821DB9 A795A21744000A01933981BC2C3382CC6C2878BE0F3C91DAD353C9182ECD3DE0 C8A7B8921F87CEF6A6124BEA3D7F77A4AE68731C0AA996A9BFD86D7E78BC99F7 E6B1BA1CB38EB0F4F36CE7537C3476E85123D3DCFE3B925BD5564705E204B101 FD0DBF5377E44978B52DBA6BCA2780DC42620ADB6EFCB026C148EFDE93DAE351 9388DCF162AD385FD4F9F3A671FB07570878A52DE86C00255E93B45D928449A0 36A0E59C8881CC43A72ABF81819AE18FBBACECB668E0F062591EE485CEEEE60D F4F218CB633F7A0260B4884CF2EECF06E5705A197D2990DA5D9A7456129FB40F C0C6B3B6B2FC22D4264BB48337A98C375DFCBF80080DF4AA0753293E91C96FA5 12A0B8136C7C4C80FB032C68EA75660EBD1FFB27491B7A6D984054D35FECA9D1 5FCCE108B2F3C4C23202CBF5B85BEE7F0F420FCD74CC5D558A016874EEE3B5D7 8E046B303D46468BEAB588ED948712DE467C5ED1F42DF22C9B402C596D24B72D 2F609E7CACDD293B5BF0C9553D22C47EA88339AFD06EB3AE466EC2333C1C85A1 00CA808A4264FFC89A485AAD982CE70C5EB9070BE28B380BC239FEE14C455994 726DD99D74920AFA174CE979BF410E72A22D151FD7BAC732B7BDD1A4142BDB99 70B521BAFCA51DED5829A9A36F7FAE6E41BFA981FF2F209C9F3DDD617890BA28 E2CDAB7E51D49C22F338ECAE92B418855FC59577F8F199F5E372AF73701CD030 273B84196E718BA54284A26D724ABF7E698A94A47CE3917467540AEC57B31E4D 3B8691B200EAEE8444AD5BA8C24A602B7EFAFDE2EF05BE950222229FE68CF9D2 7B5F40456B0C5A884385AE655B9AA57095B4A0B0199E7C787CCE1E0C1CAB4E18 506587C792DC259D0EA306972DB6170F008FC9582D4930BEC21D5DEED3670071 85EB62A3BA27A30C9245F0380F3FD20A085DD77661C3408378172F830AE09837 8380D1C07DA549314DFA349E9566259888581E212CCABA00BBAFF7FEABD4F848 6672980B30A1968293CC7E8A6D7DE4A5CFC7BA3708A76122A3D2552F69B6E79C 0D6C120A098404EC2B2B67E80DE56BE7BAC2A05FA3EE6B68596E98E3A997303A D0A072D846360D0321F3F856A8C7007F489B82BE253435DE87C8163ECD0489E7 585ECEC657A0E040A9C1FF28C94BE2B2471AE2C5966778FAA120DB1DE340E3BB 9164EB236F63D8663566C306F263A79D03FA3C26F0A3A6DA8D0AA119EF05A515 CECB66F7D06EE72C00E2AE1363D5DA802AE6FDD5DC07F994B332332FC17A7AB7 258A0328BEC8F828CD3833F6066DADB4B62C42FE93F07E35D1C8483D12D52954 42795EB0130CF2A6A2600FEDED32D288DFFEB25FBA5EB70E4B78601A0A653162 5F6A3D4DB999E0AE48E8CAB9E332048EDE4ED293CC62B7867F3159C28D6D73B1 3A951C22096D1A77A68E37C2F6CDF58FBA5CE7D6B4E5E3FA78AC2B0845F7CE15 A27B284DEEAB751B1088C9E190F4B90D3D9E068AFE56EB07ED0C8E332A49E8B4 65570124F18665724A3E52A204BDB06D68B452A4D63F4B0CA4DFA3CED2FEEA1A D86ABA5D4B3EC7943FA2DDB74F93D3D4A1CF559D2EB3CBA0B986E939137EE099 42CB3160219BB791799DDB079A10836EC5AC37E12137FC33266A7A6273987E57 C97EC1F6207AE4517CA2D4E08CA90A5DD27015C65D22DADC6D06DEBC6BA5989E F64BB70FC214E1536882F72ECCF238CB5BE51A261CE55661ABA44D00DBDAE487 ABFE21C5178A131B5CB3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMR10 %!PS-AdobeFont-1.1: CMR10 1.00B %%CreationDate: 1992 Feb 19 19:54:52 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.00B) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMR10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle 0 def /isFixedPitch false def end readonly def /FontName /CMR10 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 11 /ff put dup 12 /fi put dup 13 /fl put dup 14 /ffi put dup 33 /exclam put dup 34 /quotedblright put dup 35 /numbersign put dup 36 /dollar put dup 37 /percent put dup 38 /ampersand put dup 39 /quoteright put dup 40 /parenleft put dup 41 /parenright put dup 42 /asterisk put dup 43 /plus put dup 44 /comma put dup 45 /hyphen put dup 46 /period put dup 47 /slash put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 55 /seven put dup 56 /eight put dup 57 /nine put dup 58 /colon put dup 59 /semicolon put dup 60 /exclamdown put dup 61 /equal put dup 62 /questiondown put dup 63 /question put dup 64 /at put dup 65 /A put dup 66 /B put dup 67 /C put dup 68 /D put dup 69 /E put dup 70 /F put dup 71 /G put dup 72 /H put dup 73 /I put dup 74 /J put dup 75 /K put dup 76 /L put dup 77 /M put dup 78 /N put dup 79 /O put dup 80 /P put dup 81 /Q put dup 82 /R put dup 83 /S put dup 84 /T put dup 85 /U put dup 86 /V put dup 87 /W put dup 88 /X put dup 89 /Y put dup 90 /Z put dup 91 /bracketleft put dup 92 /quotedblleft put dup 93 /bracketright put dup 96 /quoteleft put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 102 /f put dup 103 /g put dup 104 /h put dup 105 /i put dup 106 /j put dup 107 /k put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 113 /q put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 118 /v put dup 119 /w put dup 120 /x put dup 121 /y put dup 122 /z put dup 123 /endash put readonly def /FontBBox{-251 -250 1009 969}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 2BDBF16FBC7512FAA308A093FE5CF7158F1163BC1F3352E22A1452E73FECA8A4 87100FB1FFC4C8AF409B2067537220E605DA0852CA49839E1386AF9D7A1A455F D1F017CE45884D76EF2CB9BC5821FD25365DDEA6E45F332B5F68A44AD8A530F0 92A36FAC8D27F9087AFEEA2096F839A2BC4B937F24E080EF7C0F9374A18D565C 295A05210DB96A23175AC59A9BD0147A310EF49C551A417E0A22703F94FF7B75 409A5D417DA6730A69E310FA6A4229FC7E4F620B0FC4C63C50E99E179EB51E4C 4BC45217722F1E8E40F1E1428E792EAFE05C5A50D38C52114DFCD24D54027CBF 2512DD116F0463DE4052A7AD53B641A27E81E481947884CE35661B49153FA19E 0A2A860C7B61558671303DE6AE06A80E4E450E17067676E6BBB42A9A24ACBC3E B0CA7B7A3BFEA84FED39CCFB6D545BB2BCC49E5E16976407AB9D94556CD4F008 24EF579B6800B6DC3AAF840B3FC6822872368E3B4274DD06CA36AF8F6346C11B 43C772CC242F3B212C4BD7018D71A1A74C9A94ED0093A5FB6557F4E0751047AF D72098ECA301B8AE68110F983796E581F106144951DF5B750432A230FDA3B575 5A38B5E7972AABC12306A01A99FCF8189D71B8DBF49550BAEA9CF1B97CBFC7CC 96498ECC938B1A1710B670657DE923A659DB8757147B140A48067328E7E3F9C3 7D1888B284904301450CE0BC15EEEA00E48CCD6388F3FC3BEFD8D9C400015B65 0F2F536D035626B1FF0A69D732C7A1836D635C30C06BED4327737029E5BA5830 B9E88A4024C3326AD2F34F47B54739B48825AD6699F7D117EA4C4AEC4440BF6D AA0099DEFD326235965C63647921828BF269ECC87A2B1C8CAD6C78B6E561B007 97BE2BC7CA32B4534075F6491BE959D1F635463E71679E527F4F456F774B2AF8 FEF3D8C63B2F8B99FE0F73BA44B3CF15A613471EA3C7A1CD783D3EB41F4ACEE5 20759B6A4C4466E2D80EF7C7866BAD06E5DF0434D2C607FC82C9EBD4D8902EE4 0A7617C3AEACCB7CCE00319D0677AA6DB7E0250B51908F966977BD8C8D07FDBD F4D058444E7D7D91788DEA997CBE0545902E67194B7BA3CD0BF454FCA60B9A20 3E6BB526D2D5B5321EE18DD2A0B15E53BCB8E3E01067B30ED2DD2CB9B06D3122 A737435305D42DE9C6B614926BFD44DF10D14402EBEDFF0B144B1C9BD22D7379 5262FEEAFE31C8A721C2D46AA00C10681BA9970D09F1EA4FA77428025D4059BA 2988AC2E3D7246BAAAFB89745F0E38580546045527C8779A254DB08DCC6FB9B9 0E172209FBE3857AF495A7F2B34BC895A39A30F903DC6E3202D29AC110D868F4 7184CB78407B8B9D42F6375F67FD4B828592E4A977B9E71854D143CD1A9EDCD1 767CC2929E071FBA4C3D17500E28A23F697B5D5CC68D5F56EAD14BD504E07182 3FDC12F5404E74EC1C02AF00C1A6A17F958770ED4A024F5B3644DEFB61F2578E 56013D0B4E7CA3AD255E23DD63369A921D427EEE0E098E8148B16E8A5613A8F8 A5F1099E15AD16EC554B644DF306F0CF3571055A81F1B464529DB49E919F88E7 581066BEC4765E31BBE28C245BBF0B74610DBA30C63A71A4F3B60593A6B41C6C 636C980828CFE9A3362FBC02F1967F0F770A4790F90DEF9D56E0A76B0703FC58 2841E6E8D984FB476D4FEB960FFB6B386EC6CBB9EB83704B0AF63F38C77090A8 DAA165E6C6BC86601B14F8E9F504A9D578AF05128D8C1BCEA9D21057958D5DCF 653026524A2D101334AA3DF02A3CFA410836E6001561C00FB34AB04FF97302F0 7CCD024F8C61577E82FF229A45F7FE22ACEDD95AE8052044A41EDF46B8F84346 7275F5423171DF88188EE93BCFE0A84AE5C999E9C774A32B7A2826CEA8A8560B 2F61A42F967BCBE2081DCA5547D9EC53467ACF8A6AADFC54CEDB7305DD661ECC 3FE33D8C93D2425ED57BA83F360A384F6B94023EF8938DC136ED1F66CDB618EA F40377CDEE0F17653E011F5CDE11C81A3FA5F7168681C02167B275AC0F73EF89 521A152823FCFC811C71E5D05D99094EB69E5724B34217D101BAA302B5BFDDF1 4DE66F7887BFD458C2A97A835C72E7A6EC2500577B0B057BA1B4773094EA1954 589FE5B1D1B4520FFBEFB6ECD015B606A244E605E78D39EDC316D97D99862CCE 898341583D28F141A02877B76050B07694737E9F107F153E5A5C7393CD479A09 114F07D12DE0185B971BD526301914EBAE20A38DC804C2319EFF3C8C4186630D C91141528F408EEB02C718A0A3E0D39D1C9853F71113AC07DD209828B4873031 3E7A4E45D95025D9C558CC0C313BA3333EFCEB2D95B7BDA88C062E5243DFBD99 744C678DF4AE3478C68B4F7BF5C52DFD8A81DA0BD2C95229BA43D15986717CB8 A925638049C2A15A6913B9819B3642F68A07C4FDB2552C97D29211FAE2F16E40 076342D4C5A72E0D5185CE8EFB7A8D87D7F345E776512E8B41609794052B9A08 87EE0DECF203189379B9DEFB8DEC9585DEF2B44C7F64B4DEE827C74B975BD1F0 82D7E511A5A0FEBD52702F7E68157B509F303378B191BAFFB4229495AE65C558 D72D9AC8286E61633B29CF90917E4A01030D6B82CBF263751BCA8AB219284B04 80A8F4B34D0592EEAB82D64F9A5EB6A08A6CC5A7F3D3EE2B61710DB386AEA658 7A059E9633123EFEC39FADEA37C4205112063F7BD3D2F8319A30DA796E55BA23 00DE2B3C15511F87044ABDD9DDA9247B5E785A01A05B39F1A395E36AEA4D3D4E ACACCB99E99DDB1AD1329069714FF050311B274E495FFE43D33DB3BE958098AC 61150EBC4F9DB7BFC8F6C81047DF0BABBBE67970D14524C82334B693724A0818 0007E4E848CE4AC8F07E72F02D74CC5C06DE0A67A63156F9567DEB913E874E56 B993FF1EF6774A9C582D8DABECD1EE1D1731457305A989E9BCCE8CCA4872B3C7 7635D840A0FC8FD9A40CB7B2FAAAFAE3274A2BD0CF7F681E877830103D2DD3DB 761F3D925AED45E0427BCCF205201BF0DFC16C0109A4389F37F25AC6E4E70C85 1BF6A47B91F62079EAD1D983BDD249D0EF82B21F89FE58CCF2612BA50EA48901 6757149BA3C3FE22E61F80F62CCB355082A71F1C85E8819E71E8997CAD75ABB6 070F0CEE40E3A9CDBCDE24D59F2DDEA887568EBE585EA8D40BB4D0677097E73C 1C76DE3BD95B2BD843B1522540C5CDBBE4E1E6FA4A77F93E724F4942757B50C4 40E316CA4DAD1D9D36823BDAA73E3BEC72B03F6DB2E99C89D2C3F840C15CBBAA 0EC7330D23A3EC2780813F0C1F56C891FC040B958C7861DCA654743DB8FFCE0C EF4EDF238CD820A3EC97CA497B2C2504E43B9F29707D7F92114E8053CE90C494 4C3E681028257FAE5E2C60C3E1A33E40A7C5920A8E6FBCD4686135296590D866 1359BCA5B650EF33AB7582BC61158A573F93C4ACD4BE3D0E36EF1A7683B85438 1FFA47955F8C1EBB80BEBC9427F239EFB50BA42D8C72AC0F77A511AF3832F819 FC3576C4A28B6154B8B14B9B88A84B2E9DD9AECEC59A9CD717151FAA26CACA64 FF6B2A5F561F77E9DBD2285695F0B1DD8D1D174EC5ED48DA7324EE88698105B1 E28FB0EDB30067AAAB1AE5EF6527DD1A83DA04B50E5E2B7F2A63F0E8F924B2B3 734ED216DFF4E41E2C074741FEBDBB01A103B5A68961A12C571A0A35CEDB11E7 DB6C9046AA97B45F756EF5B32CD3E1446C9616BB8A7F57308679AD7E5368648C 37F5CB0CB4C95D49C8DF2D30A8C17D8870BE3C4D9A077BAC5EDF794050C793D8 D26A5DBAB2025FBE4841308D5FFCD592C37514D1EA9F7286EE8789D41BD9E38A 905038AD5FA8405AA7568F9B34F43DD17FD575EAB5067147CAD8E9C0A454B292 74635B10585CE8D8F891A07360DEED0DAFE9836B006C3ED2B6E10674CC17CD8C 9A862C5C51EFEFB1AA02F313DB95969B90714C62F32BBE3062E2D805989EDA55 0684402A5FFD3B330B194B1EE4490D05044859619A7A6A7AFEB4909B63CBE907 34CA9F2B19D27DC59F737344E1298EF87FD4210D08FF55E143319DDDF5E94582 1FD4C58EFB00CB9C840ACF598F300B9F6BBC4C83A89E7CBDE9F37C0EBC924777 9337FD42AE2B208FC6CA3E0D9FF9AA07BF7BB68ED07EE307267BE7547020AF1B B3D65F802A95A69A2CC366B51AD5771EC679B23253F21CDF12E8584ABEA58D92 38F3B4710D434F5F967A9868BCAB5C4B57F5E1650356F9509050F03FAD247F06 607D717C4C183CE793BA995DCC37C836BC994465C1785517466DED4A2CCA2AB3 32F2D92C7DA918D720341298C650B4ECC780A457CF6CFB2120313BEE25A34AD9 3B2C2B587AA791104E38D27C117C3B4255791862E6750FEC3C32A5B965D72FB6 E333DBAA452661F88B7CFBF442A9CF467D01B1AEFE817317BE81CE3479E17E71 6C24D0A6C08978B3DB9EA09567FFD14118259E858E88648222DFEB2A655E0A0A 98F08F3D13539005E85DDFD0B1CA60E48C0DC80FE0AF9550344B07548E9B3039 E9ACAE903B7A3AB6FE24324319DD792FC5140A2A368D233140DA5690D5A8DE57 A42AB04F6E9D167CC3D0348FA7CB3EB537AEF89B99C7C93F398C9360A0B1E2CB CC7E403B1E439CE040F958BAA50E36980FB3EA7F789FDA23F4292E566BCBB731 38BCA4A234E2A205D815FE2A450DB6586D56E8C1AC62A50DCA49CB76E122D050 E1A3413CE5BA8BF96F34990DCA2668FCA06BA66D9031AD98650EFF39D881929A 28D99CFCA94FDB163F970F29F3A2617F83F4894EB997EA7AFB67A6293A08E00F 37D5A50FC0C360BC4B7F9C876A6351F9D4B3279C1083D6DC79F5A63EA48CD5F7 02FB3C581F446AA9F19603AC165BAEE2EAA7B2574268947479540B5801FFB122 AEA27CE208AE86BFE14B8D139C16ADFD5D7ECED40EB0E258B38E509A8A1E07F6 EFEED540300ED1EF27AEA5A9B1B0FCF027F626B7258F4485B8A17399188CEDB4 8CCD037D55F8EE4BA5D2E876DF7083409DCD95F644F43778567B61F3A41894B5 485A87B1381E9E98C713E2BDE4594977B85C7A4F58D542C634F9F76B9403E23A 87D1091723B30E53CBB97A1406EBB78A7E06DA949505FA40F0D5CD0675EC4B6B 207B7210210E7145ED707377A9A1534FF7ABD8395083EC23928A03E3016F636D 1697B161377879568A752DDBE939BECABDE106790248103F1C6D75D474584F85 33DD684D3E4927EAE6DA1C2020EB78B226A43708351B8844E4A491E82D018AA5 AB46821A444373FF2CF81F996193D0C6AC98E2302BD0D7909BE77D97F1A6CC58 959CDBFE69014EA8F95224F2D2EC70DFCF8A38EDFA77581CABF0921B863A6544 24740A40AC91E315E97FAAB8D490AD44AE6805A9C7471AE945A40886A2DA1F03 7B94629ACBFD5C307ECACB6DE6FDD477F439CDBAC935A94679F037F1FD6DEDA4 F4EABA6C9837CD7679DCF343E823FE70D065D0379ED0EA0C51DF0700B7F97775 4EEDBD920782FF119223FAA23689358F35C8A68566DA0D9097C6D0FBF163EE2F 656EEE4291F0DF40C5F4910DBBF3A9A33A0B349A2FF1D01811857F9335FF04B6 EDDCEDA0172528348FED69047FFA80E2EEDB6A612082134CED2E167A061EB226 CAB50190F731B40DAB9650D4BC581BFEE93A2CEB9E9BBF5860760405127A1E3E 7FBEC40343D0D2E8EB80083B354C095C483A8405B7BC144FCC23E8F25E745A4E 8C527635AC995A1065A7FCFD805C6CA7CF611C06845EEE14D07B81E3B404E727 20CCC5BD3657D1575949FF993A71F5F8C5236135963F13D8C09B1F3B08CAB6B3 58460385AE220AE727B0CB9C05020EB678240921E0735D7A28E6C17CE22AE05E 6C9DE888DC5D3E24C60BB94289910B3723F60A74A8B48ADD5E03B6886044DE90 69236204BB7411A3D9119333D328F3A7BC446AE7C2C4C529D5E3D501EB99C900 D040D670DA581CF03FE6243093192F5E91A13B79BEF60D605A2EF3BB93B569A6 9C533A1AAE2CC70151A0BB5992A5B8269472E626D299F66D3DC25952AD9CC205 25572F56F774E156EB78B0406C4DE584660E1AC7E629DADC0BC41E725BACEE76 FE217A7B0190A4CB69E9F32F4F7A184BF53EED2B1659DAC33A2EE695A88D9F07 D076E3ABCEA448A576DB7B0C5549A5A2D63710141F4E539DECF167EFAD871552 7BC24AE52DF04152173D6E4CA827DEEDEFB7E9C3E72B5934C5DF97BC1EB23749 F776539AD43E9200A04341EC0594EAB62A0C7050DCA43945E58C4890350F3ECE 5BA67C3D716D5360A5C1FCB6EAE1EC00D59B46402B16B14B821EEAB4758701D4 4CECA59735D67B099AD9CC4BFF50B846CFE14E35E4D3D1F5A3ED2641ED940775 0067986ABE6AA117DA321122636AF7FA88AF53A473BDC12A4844F46F43D94ED9 CBB72CF2CCB37469C2E63661BCA5A298D5E9C6BD3D41853FB4867DF938DF0391 2F7ADC04FD1B0D6B0D5478581D4A2E51BDA015A4FAA53378696FB50A3297DD3D 20C365B963BBEAC22789E0073AA921F0640F63DE0833764999F02B66E800991A 438223368F1AD8FADC75E2C5130F76148FBB0ABCE3B1270C6F1CAB55259B5290 A10A1CD5419F9254ACE5834A4B8A71B8068EC21E6C4AFE9E790C74EDF7411289 3AEF976BB7A42A7CC1AABE4634CC1700272E6B272BC6CA5F1549F3172537FED6 C4047BBA4FE5776BEB53E8AA82BB17AB4796C1F91264A7B7E95EC14C0F74710F 9E9CFD51DB71C3CFA152D6BAD9E60B38D688C7CC5B587F37BC2301C2938DE2E7 88E1607E5B0CE6AFD63989315A9AE3BACA1E0C0E0F6CBAFF02685282033A7532 3E5B0AFB7AF6F4E3FB5801D175D02551F9746503A2E50AE9AA8AB56DE79BDE79 74B4550F3890818AE801957A3B6A822614EB8D12FCA584EA8C41B814D30856A5 97C3ABB9F665D1B72B8D19C4D2BEA46AE1332F8BD2A6FD2C2A1183E48F62C4DF 4175B4CD65A9B145D400D1CAD7E00D0D154182126764BFD3A267F85BC623A575 92FFC5A063A9205A02C89CA4B40C4D489F17D383FAF081A3C0B2C94E21BAED8B 1D06A4495F917C37F8B04070E9A90F60AFE3A8F0073086F00C5A707A96D4E1D2 BE5A637EC1C614997446262573426452FA5872FF661B519E24A34E3C58D4A07E BBB6C294D4DED3EE01A853EF8E153D905B0598241F97301CA600C09B7D116901 77EA1F6C40CBF7CAD5991EAF92890305BC710270FBD575B626A59EBEBE2A9A21 D02700440C57557225CEAD5FC1EBA1763746A061A7F4DFF5558F6CF9160F7CD8 7C84BE7407ED508BEB2338DE3C5207A7804FF21C4E0FEED254C0DE812FC8DFF3 4B5B890B24BE5AC7C00DC1C193C88A6B33A442E184B4F5EFF79F4CACB8A56DC4 05098C620D63A0135F8FE2959A396398A421FC16F8AFF99F702C1B10F92ECFC2 2D86DB2489887879926E2AD34DB4F7A9CC460E12812C24FAB08ED0F2C3DF3FCF AB41034C07225F20ADA5B5AD6AF5349319D3F937DD64B2E0A0887B880BE636CD F814C498584F19BBB3FC146035E4EB4A3B7EB436E7713D968B24840EE00C019E D08263764CF0839260BE71F875E5408AF4A8AB1603F7F694C2DB705F6E13E1C9 4CCB224D0E2B610FDC729EE8E33366D0AFB0A014C3AAC6B915C2268C27A65624 261E38226363108AB1C12BA960649782D0A02F87404350EB7F58C6C54463C1B1 334F936DDA18C96B577D4409F18E63A79F708A816096A6FA1071B1FBBA3DD470 C00F032534140440012988D81DBFFEDD0F6B02827CF76A92F638A685BB1686E5 D0624C445A765E6527B4D2FA2B8BBF035D9B0BEAA0CA35D937FA9B4A79224387 CD974CC0A052A5C78C4CA12379413303DBFD11DC6B78507875E6643D36679EC8 3CBB213B5116E5A262300890D85018D550C69365D717BD3AD5579C906F8BA35F 1C07EE6B17F394FDEEDFF5340A86E28FDA9ABD8803D832117A74BA868326A1D3 4004DE8942437EC0123075F2C6B97B306AA3C806FBCE7CAFC83C2CBC77E25C3A 082DFAD7D69D36ACE654CD17916062449BDA3C3AF3806416B16C718128326DDB 062CC9FFDE6FEC2D0451C4994F5C681A18D7E5310917B2994756AC8FD055F7D6 92FBD23FF685754DC09F36AD98201040626C381FBC63217DDDF511ADE6D13101 0043EFEBFB8C49652EF4FED438B5322D83C6B998BB46BD5B5F31BA2DADD76B78 ECB3D44A2AD40518C22914CF53AC408E8015F2E828F6F4908FE0C85DFE30B8AF 7A1E91B6AC7E25BE17F971DEE8271DF880E440EC95E45A6C909AB0DD6259AFAE 35B3AF9B04936FCE351DA6D244D34EF22D0B8156A583845423E93A3E5C827287 EEB8E89E19E4FA0D6406506B73285484A75082DF8E0219FB5543B57AAF63C47A 0C5616682F22DEE96A8CBC70BEB556DF3E719CE0E70FEAB87448B0FBF45EA6E0 2006416E39CAAC51A4568736D8F0270144CEAA8CFF832AD16907E09E49444BC2 80306B769125A50595838E76514A7FB0F1392AFE209D8817FDBCA2DBC8CBF8C8 5948F7E471B6B94D7FAFC382B02824888D3C5860D1AF18F729678899932A1AB6 A6A7A3FAC08BFFEC6FFA3CD9543D36AECD2AED91B0D8674EBD6A9728FE8BAB6B 4D3E8E175D0941775B3F96144DEA873B48F3F6B7B6A30D2FAB960AB555AA441E 69DA76ACF6894AEFF47BE6BCC094E42D735EC1B9D65474C31F0468FDD3CEAAF4 333F60053CFEEAABF43569FD1C216FFD77EDD13C344A0024CBDBFAB9CEDEC95C 115192A65A818C166A5C4441FBC0A1379D0F3FE58922EE49BB91857A03BCA8F4 0067F324EFA67755AC0943EA80D0EED33A817BCE9D5676F9963844F6A2DDA48E C9B3D9B1E9F8CA3FF805CEE70807B028510D0AC5B13259280021D06260FAB24A 0143CFCEE0C3FDDD6D817C717DF925DF5022C37A19FF63F77D464F699F585E93 CF29D5AC1F2CD04E992E5E714C1EEA2FD56400E45A42813E4BBF87BF0849834C F54A730E4B399FF3BB4E14D9CBAAACD79CF06AF35C128CEFCA1C43C8A5ADC1BC 3AB187E52F70A2562F7A705C58396C3B9198C78AFB0BCAD890956F7D463C70FC 0DD0AD6AF96D778AEE93A3A79A514A16C0324421D5DD3F7BD1002252E0F24DDA 3EDB1856E47B979C235BCFE8D6B2FF68864FBAF0CCBC3BCA811760643E0B2E73 551BA0BCDC4037F497911B8A5CCEA5AC79B2C8229F317B690108ED2C52E7429C 01DFA8C97FD5FF794EA69BCE240C02A9640CB5194CA6AE598C605AA92086AC82 C983661FE88DB62A3B732F78F43B93E9C22A09B29FCD79E41053D4E27CE6F3EA FF365338B03B87AA0D48063D02B8E4C88075FB2354A05EC177E3FC76FE4E4DB7 7337F0AA30608A6775C928A39A515C20A285D0C4541A2A6F06E6844A6CA428B1 68D522A3EA084A2EFD17E3FE423F2F55C9F19E842D2E30CB79026C2D2DA9CAEB 8C4DE6394771D9C2D071F1B17047FC66A2ADA0FDEFECD6FAD63EA5F2196CCBEA A4DB2C62A0948DD2A8A0D30E7F6808FCB912704E647E1FCB8E54D27039F67009 4E995339D198156D3F6522EC70AEB3F22ABD6699C36386B98E0992A57FD9BED5 D9EBCD492CE373E46A35A906C17AD2C4C490A9F74039075C8AFD8EB52C9631F4 0CAFAAF50E8C6B4C565D859F6DEB844846D560318367C21967D6100DBE5D3A1B DD12DF6B8A3633BBD59EE865445D2F1E8814D8D64C3BC913183B59DF20361B66 6F3DC614B9AC2C2CA4C30E1A01C1C2A2054FB4BE7D58C6BFFEFAA4E13087C434 ADC6D8F1185F68B2003E7EA12A991128037E54D2A88EEA2E794D89BF531E107C 54278EE82F49454FC13638CD0B83C142BA3E0F5462CF92FDF0FA223EBF69D12F 3D99BA804FC467F40945B1B0AC23DF88BE1BDE21E296A82870F6322630C06823 27629EA02637E6E3E10F16747B3EB3E479AB8A347FD46D581608D453684278A4 AA58BC490F673269CBE7356CA4F9E523CDC3F5D98EA1B95CB686BCD17366B609 72BB6B2167EAA0D66E36EF6A1170EA56A8485A659E55C8D50108F6455F1C4227 6CB5DED36763E54089C6C04BE71D5B762254EA4374C136F98900F25B239652FA 71A14A43F046EC8171C490A5755F90DE4ED09F8AE5EA1A6A98EC026B612BCC35 6879F1942C6B45DF7A50F4E49B8C8013164CA04DAC46F1D799071BA6402EDCD8 F55BC6B064A2264A37D4BFE59754703B2C13BC4C2586A61EE4A9F9915F00FC13 05072451125EB001CE97BE3933239DF6501A664B45FFB5E63467CDA463A5AA14 504AFA4C8D4A976B459D8B41046615E06DD43760FFB72488397A34C4648C8B4F C56454126529C50AB1D3B328136D31F79EFA1EA011C8C6FD6AC27FF2D4218B34 3F99304558FE4B1C81BBF4807AA89ACF653EB74E9A2C85D8DEAE86F1A7B3B5F4 077D09031A32E48C069539410F68EEE2A7ACE7B200CA099BE59009268219DB52 27A2D68DE15C91ADBB30775AD1701708749754BC4F0BADF52540EFEBCEEA9FC0 E00ED70078142201E897E93EEB6B8C033B2B21617162BB54060D3A14BA41D481 9B2BCBFA81A176BF324C8425310DE6C313113A9DA8A950C6439996C957ECD22A BEC6631437954D043A5F0F83508A7EB24EBE9058841DC13E42E5A817928965A1 0566C3B7A4593733E519AB17F3995C6702E3378822FA575A537E720BF26BD14E D08755D999FA4AF6D0BBC2A54CBC279C8E75514733DF7F2C19B84F043A4C9A03 979FEF3A622C92ADC58FE94C3C6C6ED45472D1E48290173613F991036368E036 1F8A871A66BE125074CAC7887A69AD92D96F157BE10A6604CE0647E5D2F6E4B0 8E3CB6AD0E830C18B4C239094238357D1D371F643F50E81CAF234EC88E0CD6C7 BF0B0626895B812E489153B01F94C0D86769A239879CEDBCF2402894B6E79566 1AA9B48033407926F18C7399C641C3B0C898AC99AE6595E865726374CCE03954 92D48AD6A336888DC372676F0E1BB9821F638924976163976175D2A687324741 912DF146F8C7F6EA428814DF6F235728386BD3558CD588BB1699B43C1DD6B4E5 CC4E75E69FE0158E8666CD4E86BE2E79148680287615041E559DF70923831A27 63D40F0F873B3DCFCE27E0BA3F396EF61417E77DE37C0D11902FD961CF5174EE 8EB1DBC17A1B0FED2BB385C9475096D7EF37BE12B0D75F6C1883229F3A62A679 828645A2E71DC2818B037613531463FFB0F84EBC614F6A9C3BDD29807805E580 0200984E41C66B9C99A62EED7E91DF58C72EEA135B03B08292FF4532728086CB 5ADD2170758529CCFD0E652138B55D545DBFB5C1DD4FFEFFA87DB31F24DCECDC 203A0B9D242B8F0ABFA7484545FA7BC22CC5F30C28629086ABD681555FD8C060 00F4B5444B0C79EA2F1EBA2CBF0C45689B6D4B09A1292DE9F6E92A9C52A4F601 924EBAEDC0F478330826DC36A3E3AC35DE0B82145E378108A75D4DB79B78A713 4A54643465AB3D1127B69467DF7AAB30EA92ECF0B5C475FD5922EE8310F8913B 7B1AD24A93EE946C8E6DAF09C3697934E94DD0074D8DB4582D26F9807786CD8C D8CF959020822AA23D57077A73126BC5716FCFBFC6271C9F1BBEE9730198EDDC 41BF84898B24CD5A42D6D060C281B1810B323C5AC6032870041F007EFF54BD07 63F24FED3250E1F67F98E4B73678A5BEFAB99103F09E59E5E80D4BC9A2977FE4 3AE53E66D4185F52A001E6CFE374CB6A934187664F782F63E3C3359C66017383 99693E9A5AF425BE05A681BF7073A3108C77C2A31A9ABFCB24384010E36CDAB1 86219786B68AB2A6A7065167EF57C5EB79D790824A459A137E7CAE466F1EFF55 8BA7CF2E9382C1BDBBEDB381E7BFF677DF252886AF2BF19B2E2D8C44E0C35957 A0491E4723DA85E67BC6182EA0803EDF4BAFE302BFD52D84BB888A70232F7D64 3CA598EF660B77E88A6A8A4A4D63AAEBB88E400D20581F2DB42ED3B2B184DF15 6DC8E586726B5074EE71F347494C84B2365830A932A4F05F3EF70FAD933EE655 12834498F3A58AC270D74CBAEF756CB8A499D3EA9B99C37DBD8D84970B188530 82AFCAE63D692E6A72777CB1BB9523C75F9EBD4DC7F6E5D6F39862BB1D7AE93E 5BBD3E135E919421C3DE94A2EF81914B6EC5224906F83EF47292301C59C3836C 3F359945C40C61D9FC0AEA5A88A9A93DE5CB8DD195725FE145E79B7DF33B1FAA F14A457C39D12AA5881FE5607251BADC4CA3A1FD901BEB971C765D568803D1D9 832D5444A1D8332E125B7D865D5B28CD78C7043D8A86AB4DCFA769A183FB4B05 749DFD67A669B7DBF6A6283CA516B94704D74F64C3FBEEAC15CD1A2D939CCF23 3A7837791AA06E6167291EC2DB0C34846D7D158EF594C6499288ECB69EDFD50B 4AA7F1E37993781A3933174BDB9F8EA0D41BDF7896BECC4BD9E6FE17738AE1F5 FC0B9D80D6247E861AA03A36B3BC648FC8610203AB27DB18B48BD494A5798406 BD74B5D1631C2844DE39ABECFC6518C45A89E117D7C498348FAB6C512DE91210 1C07826D1D6131AFC8B138B595641D80C8753C45ABA3EA94D2B175F382508B1D B85D1133FAB93F41187C9399ECA60142A1356B1E5CFD821108C347CEA7ADBF08 0B124290E9D736E2043039D49D7D297ECF51BB2D2A9BF589761AB8C1E7249722 BB558C01661AFF993684BEEBD24DA09D0184440581B53FF4BF3C0129422E8F94 F214FD0FE66F14DE284435437600C6B9CBB80CF7CBD3CECB34757BAC210DA30A 2DE252E3DE81792D101F032EFD210853B4D37CCAF643D71C4733C81202D5212E 4E75DE6E19A3F1905A22B668DEED9A8BCABC2365A1B2C6DA539FFC709B85038F 99A65DE1C6782F0C757D402F59F11968695061FD1EB1293BD54FC33E1C2CA4BB AEA897043AA9FE619649D835D131E18DF17A9D1ED6163BBA1A9DD12B9BB42A74 F67DEBE8DAED8AEA55A7F022159138F97FF379566A42354358FD09DC88FA9EAA 5CF2ED8B4D13C1339C07D398E96D0287FFCECA5C5C32218BB43BFE08196D3D1E 23973D34833CD9BACE28436A5FFD4816542473B7CEAAE489D7FC0F5012BCE6F8 4D28102E67187E50603942FE7514770BB9157E67F1459F77B2D8FBAAE9A4C987 295D1DACC6AD96A0818C9E875FEB5354BC2A1D28E2A1F45C8628D8D5B0C58651 5083D10F070C42724CB17BD93D598ACE9762EB5060E2687FF9EFB1F58A95A5CA 1AF7B72010131F0618EF48E9BFD21C17B297812190CC427B569313B025C39843 57E25E37934EA128680771B49E7A3F1978B3A6238EA54D83CFB84EC2A296791E 3990AC7AA99A9A5EC4A560E59F27DE1680C81E5930C136A83E8E7B4ACE6AAAB5 57DFB10D605F501081A8808BBE3F6E297A90F5E09A3CDF26FC387399EF4D5C70 E7A3E9AD46B0305E86DA98263A7F44357D4E950A63D7BEEB9D2E3DF3D066A6B7 9E940CC10E8007B2CEA1C11521D2095EED15F3152F92B10E0B4E9AB74138F241 4303245DED32F590E1FA35275F2A0A26FC74F9A04F1CE9280B9A5F136644B77E 9F4A7CD818309F8FF436B07EECB4E6D4168501F32B348446AB6D693C81FBA667 80FCA9390E36759B14F7A406E66F7BFE7E91BCD495A53097E55EEAD39F8A89DC FB4CFB345F075FA37C763528DCC7D80FAD8F674B107E60FA76597DE95BAEB3C9 A3BA95633F1A44F20A2679BAC5D867A8ADE1270B3A87CF973424372BAF552056 C9C37ED61E8A791D32997F15AA52A1F259FD02267DD7F43A218224DA371093A2 2945C99A06AE36A43107BEA63FE56A9A2FC0EFDB46DF08C2752AF493035A5595 EA90BD9847126368DF8E22FE380E50A893FB21914E78BAED3AE5F9F03F7027DC D10B91264F4459B8D0136A8C4139C416C64E304128104B6EBB0F3978C69FBF5B E090B5C295B98578A79FAD2AF4233821A08C375DF4C4429C93623C43907B99D4 527E67CE7A73786E4D2F817A612AAC7B4D9E3F4A79BF382F15008DE76A9A8DF3 47C60F100B09D971EC4690B1A04173A1CB66A2269BE80708FC29D82C552151CC 385F1F179889059D5D70D252C99D0F84D12FDC13FFDFADC11A731262BC8E2AAC FD8FA176352F9D114322CAAC7278113C9B48C869D5EACE4215CD50A125EFAC99 88312CF4E12FC1DA63029140E8EB1BFE1D79A7A338BA2188B599A1C224A0FBA1 3CF40EFC11D7D3333FF371DED67318D2F6DC8B5F34A5728233AC9BB2EF214D67 B3F2D0FDAA10F2C932F7AAC4EF557E31909175A3F61B0804CA0C762C53F20A83 53A8A6FFC37E002EFC441614A8E540921635FE855CBF1338431AC8F66FB1E17E 6770C99ACCE479A366F00211F8915AEF2940F44E43FBDAB05FE2D64565BD2584 59F65129BD9695C4787C6CEF7FBA70E2E0FE4FB7051F65AA824782F9887E5F96 DF2527C15E39CD1D5BDDD48765BC0C528037F69F8C5F168810DFC2D974AA0E62 20104E3F291DB79BFE816FAAC5765BA298797EA491EF82AF07769675D60F4E4D F088426BF9CF41B0DF5D840BEA5ACFB5382015DD26ABB0851AC610B12553BBD1 788032FDFAF98C64AF5E2FD0B08FDB9582CDBCCFDA38F256930349697AF7566D F980076F5E072279EF92BE37DB65AC1D702B0E85C856482A8BA9B44CC43BF3EB BB7504F1F2696B597A0FB8085E3F6E3BF178837363F750679CF2CCF7B01027F8 747E1DA4597C8F93CE8F07D304FA72C64972CF08CD8B8F3331285EB0ECEDF8B0 64B53AD633C6D90340797802DFB81D424DB73D68BADB7811765D83C2C57E3BAB F543E327CB8B0356D4A84CA1BF0AAAD57FB9EA0E5C70090A04745C916A3EA2E9 2AEFBFC64AECCA2DDA387A3A8AE1D27C6B031A28E8FB3F871576BBBBF7217CB5 4ECD354B391D4661B278B1DAD9B3AA0F39883F31537E158075D73A5C4D37FAD0 4181846C724986DA122D84914611B7C50DC964E21B40ECBCDE2FBCCA5A30E11C 5AF792173E502843DB785CD34583FF25251C712087589EA26D73257EB7B9D484 72FCB8988317B1F886C5EB9791F4688F087DC8D2D0B82B5EC38CC026C45C406F F0BDC2C47011AAAFC765C2E520BF3C90C85E0D4AD3D59E75585FA2AD70B3C527 2383D7582779217F435224718C04EC8467BA8C9319F99F3F033B148B24CA80C8 C2A35C0B3BB874DE6AA03D3DBED072A45DBC5C8A746F83ABB578F872D535EC21 D16BE93537193CD36DFCAA9BC9FA95033EECDB3853532452385A71D1E92D12A3 9AE044E7142F0911125B2C2C881678886AA4E924B5718172A3161C790E2E6F04 9A28709CB38269D8D460A8415E68F64D6BD3C9ED9D9744DB7AE04B9F19B8DB63 EF85CEF8DA88F8442E2AC150FDD3A15BCF9740CAE7FFA1DE92E2571CF2C0E0F6 90F13F5ECB3CB88FE13D4B8963B51ABFB9040A25ACC10B08166441D7275106C7 D5F58C5A80F4F5472181D985237B431B8DED88BFBE1215B6DB506B7838A26C4E C129AADF9C36C4177C76930CF6008104E0B5E3A387A13CBBBB8109AEA38FC35B E7DF40B4734AAF9A7CB819D94DFE944E994DD21EE7E9BC4014BA7F0A1FD7C098 6F7A699E77867DA25507D723B6CF9174782B58AB59D89BAE119F145D61F83687 2C2A1653B501E71415A0978D2FF39468686E2481CE4F06B981FC398F93555A87 E93A098C9FF28BDCBAF0637CD63BEE7FA448538FACC04B11C068A16E687BAF4B 5D722363F7E1EF39B8DDCE5C947DC2A69DF4A4FCF40C397FB446A37E74502E49 571846E8951AED1102A7B67B7038EA1C7ED210A077D83222E988C0E5D2B88BF2 C71DF6C9F4400104F2E8DEA364D3A45CA1C1E6651C3972E89E5CF31881322FFE AED481E2602E19D31A735C14F3C7A8D585C46ABF0C5C64BDD64EDD35D0ACF67A 5C91C26E2D53C47EEE126FCCAC1F7E9A67A0A02DBAC2C3EDFC15F55DD73EE385 A7A32431AE18BD4F2C612FD5F5AF4380A259C0C38D22FEEE403A7B9CCC4EF62A 6CCFE803F270AA5FB5C4DF8419CCBF6AC611A721688ED51B82C1E5647F2B988E 2B84B5343C26D8495A23908A6EAB2D2376DB03F96D493A892B6548E0369988CA A2ABCECD47663BFE45F4F3F910952056A5314843DBF4A8862ECF20B9C6427E86 E90CF8132B2A03E1A0109C2C1973B5830B9AADC952F41D92EC44FA3E79C77155 AD89D10EA1E3B30126889BA190C86ADD788045D0F933226A4AC2FF91A9406F6F 976F337400FF3921D372AD11C929109E7F2D7C2A494888CD85BD790C8119681D 83B11275991898106C693C0EDF1C19B8731A84A94470D2BF52F0123E5BB89E56 39D5CCA023BF0625DA16DE7DB7611108CEA00E3CD4B8C03F31787EE00A94B542 A88B4369139836FAFCFDA51CDD5ACCD351C567663F1140357C1414E3301174F9 0FAAF917EC9C19DDA2F41C671B3175F49DA30593FA6C93A067560053822D9A9D 0A440C3DE6C4422E0EB2F7E86082F7734BA83D02C30EDA9A22354D1DCBC8D186 6A43BF3DDC5209DD661A87CEDF97BA43262C6D418DAFFD943846120FC5E1A06A 5C7D847154E41CDBE66B0538189C130DC4094D7F1709F15460AA982DC438F380 766D6937A65D1E01B70FC903E2D906FC31448FEBDB937051BD538019D849F81D 9C28FD74ADCA7996C9F319EA011A00AD195FFB5149F1B0B550ACB239D6D161A9 E45FC9F9018F471885D62869831C55EBC118920B864BE49244DAE14794EACD02 A096A5D16B4800B0A1AF3EAD075EA2476743425FE2214BDE468A20749C6FA35C 9CAC2363798D17891339B28F8BB6D0BE628DB425FAE39D65D3C034D041BBF7CF 4EF74A6AB6F656144930C034E57F02C528E054F65828BDE71083109F43FAF0FF E520EB4BF5D92932BDE44D54797E58DFAFCBF5C819474A7B9282D087F819AFA7 F13B47F2CDD0BDDA2D8ABE8D6A0886407EB8550B96844FEE859BB61C799975C7 056361974EBA586DB2D3DDC859CFA0FF493C5C8DA81B2673AE6C94CAEECE4B0B 498E9F060E9948D0CB5C47040265075BBF6B40382EC26C5822DF3632F1F24973 DE14BBECF72DD8535F05BF15276DBCD457432FDA386EA8131FE695CF61F11B37 1C917751B54637348823C481D4C2B0DD4C98671BF1EB42919C6E11554D86490B 8E2823073B9F1DB5B04EE262840352032E1B9E4B688FCFB1144E43BFE455AE25 F914AD37E6A694900C5CEA010A04631BA180B9D126989E46566101B868EF178B 6BDE396797925C90780A1840369DD3F7AFA7C6A2D46FFC8024B12C356D5FEEA7 9270B37CD936AF7AA2F041836B00D3DA2F190F4E8C97FB7E9903446F8847BE6D 32A1772991AB24ADD997BB3B97452F21A25591459AA9F15A0B5395DE1D23B038 07D3B35338E4BA1214570B83D730F9FE2F0C0695A331B8E391D1FD879FA2174D 3F83FCAE5E1441C51B7CC7AE625CE6F6EE29604FAFF1DD5C1FFA48599AA073E4 E54E56028BD64FDACB47C715566D193332542E7A45F27F87F9BD0E7CFEC8EDD0 C604549AA0831EE8CA7C68A8A4A6549B1E7C0BF2B6EEA70AFE13024C41557568 D11E69C2F8D7962F5FFB6367016D93125A92DA39E25F30D5E4B85F66D34B0528 DCD0D71BB767B7EC0A58272DBB90D0D0D0F661B783F724929CAAD9843E044752 C5D1F2F6DBA6CBC67410623EC23D7C7EF15B18484315CEA679FC1526B576F54E D1DFDD0E8ED5F2B1449A05501D0110DB989F62F815A30E84BCB0042A0FA14855 77D07A326FA8F2B85E67E20935F9DF0068B107572BA80DCFFD90F922B79A85C9 821363FF5AD881CF7C0212B2E6238B49813FEDCE319FC0FE40A42797235DFCA2 0F1B939645B97D26A23CC5D1ED56CA253AA1E5C8E88E93C74F410835E3D5C2C9 731649584619ECCBF3A50F95DD7EF36A8C1B5F63222863F0D8223CB787B88027 54835558B8E4CD6FA1BD7E4024B6C7267C1266AE9E7D7CACD4448342BEDE1EA2 717FD60DE846878BA67710AF4508F33E2D8D1827B7AD0A8C94531079BF2550BB 87B73A3848857F32B5D7AF2CC07DF0590D6090B7D820D701E669ACA06BA8F194 02672D01ECD7E2BD4E29FE18176D8317BF9523D2900B7CCACE98E9B46DEDE394 0CB3B65538418147C93E77FADEB94B66FD048E47A0F1C3BC92A51633F83E68EE D239C0F2F5EB9EC68A048EB809B5B9F2DFE41F815CD33623CC2F6AA0C06C9F53 ADF903E40B50945A7A288A016839EBA12CA78156F617ECF3BFC8AC106A0B1CD9 9E2474C0DE1B88B5B18117CC68187DF5EF78C5B1AAE36D39946EEE1D931E704A 9D0A315054F5362FDE90A0C04F159F93715B4082554A6FBBC03AC4C2BB6E3A33 8563FB20B664A350BE0CED555FF8DCF2AEF4FADEE74A09522BC31CF7E4FFA014 DCA45475437866FAD01AAC47DA6951197066B69E6E850D4076C0F8B3F04355B0 E26711458BA45DA22AB577B6D71C8697816ACCDCA0C59E1BD92FA8C730D09863 ACFA216600EEE43FC54E9BBBCB873C64D0C9FE41DDCC573AEDA8A699F780950E A63B8EA80A78E89724BC77DE5F7ED67FA860EE16D7E847FCFC198CFACF6FD4F5 7A25146DD526769E6A4080E908C16F7CEB0EBEC4778A6A888414FD67BC2593FA 6D0111E37BE74CA96748A43A7345622CEDA9D1DD5482E8119DBA73E73A35FA0D ADA16A14CDDB54D76DE1D407BB39C00AB23EA1CECAC9C4DBD64DB5AEC80AC9D7 FAB6A1A3C4CA84F630A8D3A143A3490818A7BF0C8F16F6220BBEC2B8CCD528A3 4A5F899039BB3E21B9554E3BD873E2C1DAE37F0700B43CD1939CE5D16773520E 7A915895E74BB21222996FB5623FC6F077F44AAB49FD6E8B6AE3C8A9A93DA0C3 445FCFA9EC73F98378C5B4EF3E67978B7FED5FED1EDA85BBD4D0108D3E059E63 28E11EC677315B68DD63C517853C1A65967BF1B859A9203DBC2F03C4AF6A20AA E17C7103917CDB42303D88E4A1997B34201FCC208C941249624D039D069C2977 B28AB8D215B245CC115024E3FD2ACB74184C8548DCE81F4D65D4CE268E360C03 FB719F335050EFE6B13EAB0B9580437C6067F0251660588FB519409390F94326 97C1C7A485E28C199DFB746BFD1CECE61C6F66D20946A54D9F05CC7F14BC7BE5 9F0C229CD87F1A35D1AB547EBE307B0A5CB61F8E7661DFE503FF2EB3344EF7B1 FED24165DAC30B5B6F39D1D1FA414A19E7FFEFCDF93808EDD4493AFDCA0BE31D 03EC07BBF75FFF1654E5D3AA64DAA505454A499E398C2F53DCB93BF548451764 3E4D7004D97DEA315CB51588F654CDF6FEABADA788D6DCABAC86E3DC9BB7E42B FBC1381C47277801E353B58400F9B9AA4DE2E1BF4E6433688C8569182F0F4568 6D5E7931C695A5CC181A815B3D3252AFE7F25EAFCD8B07FB7B127731A25D951F 51506723A896F8DA4027296D11DD4123FE93BCC81914409D2E6381F1F2840852 4214BDD7C2671B85AB24BF24F895E67A91DF23E21C5663797F049467329F3DB0 A74763B8C6458A5C9FF1157F9DD08C37351A6F074E1E5A05F9827AC15FFF4A68 93E1D010E02D82B63C1661BBF9113D415052C4C5070E6542E5E07223745355F7 3DD76EDECF1C5328A29473B07BDEB0D4223C5D3DAA6BF3E639C2FF860AADA0EF 05A9BBEAABD8389112937B0F282A0D6C50A7CFFB0D214523EB8618583DF0EFBB D98086ABDF5EC23F57F1101E86AFFD2CE314B4240380C6FFBE4530E6576180C2 3A3695E4D70DAC730C2057578AA0CF3E8E464500C0F2C7ADFADCB41E1DB62D83 86DAD27D800C797B01D3A701C62A3A1D0E1C18D76CEE1AC9F581CC1C697A6E50 62053E7EB21754BA9D9763654CD7FC08B53A12408A4CD4B99F4061C41FD06922 ADCD8518DFA056B825A24965B576EF1DE31E3A4E2E54AEFBAFC8BDF5E833AE8C 929405416A91A45AF0977E396ACE32C969C87FC93DEA7888A35B7C9E8ECCC350 C9388F9953925A208E63514E9BCBDB99BD47D146DE4EEF08810C81DD6DC06EBB DC1F0035A6DA0D99F32696E8B4A226435376E26C0ADC8846D28C8B875BD03663 73592B3FB5D5A0C927140F27B6CFC0FE2A8DBDC77CBEE70C0E2005EBBAFB8BD0 5B24447CEC27AD4225DB0DC1CBBBE69AE423F9622A4A8BBD9466962FB54B64AE 726060F18B3EC8D945009E8FB6C2ECA462758A78BE369F00AA4FB8534468F700 A9376FB42130ED96EF9DA17B7B9589474D1427D0D8FF5152F6306527B12D4329 3CF929105E04AF564DE552C4F06B466F16A8724945CDA9E098AB31A032CB2D05 BBC3CD225A51D818A9695D6E32DA429E702632B32FECC25722652F67165695E6 D9819D5B200EB3626FAE8FF7376DED2B1720CABD8AE2BC1A0A39B7BA427BCEFA 936F934DC88685CAAC7DE19929C9F99984CA938BE0044FB341AED41B19F97F41 2C31E2C4DB232FF90BC0D15F1991DB60E7E944D90F7FF591136E1F260D3764C8 8BA791589D455192A19ECEB8A9E80FB5506A479EE444322C4E8E8FF0DD9BCB8F 749C69C488E816625DF57EF673DB1A85BFB19D960461EA8E6718A1325D878D37 FC7BC693F15D8A85AAF4C42216490BEA3D1638BE006CA2EC9D4DDEBE3C641754 A78F6EB4B71D7517351A91A711CEE1FFC4FD57B0EF71E2959EAF82AB5494234D FAAB49B1EC4DA7A2F3657458CC1CF6229901C2AF5339E2E36F92197762A8E446 5F8F9D24A57B80850DE4264FA9F23C947C35801C2B557CFF02B15637D5B9B059 9994ACD938E826E4DAAF9581A63EE82995E793ADE573CB2B9628BD7B899A1C1F D437749137278A36B921206B70495E0DF379B7B7315FC02058EAC7F9128A3B4A 30E20BCFEEE17A99CFC9795F193E4356AEF6DB94A7CAC8880FAC9227A0BF78D8 B7BC18F6DAC8E5CBA63996CFD5E4F78461AFECE7EF62C585B5E5DD40789AEAD2 597E24874B3BA77799D67DF746E70FC9DA4CCD9BF40F9897092352B3A12682E9 4A5A92795C8B52E212FBE7323349E867ED8FE78B8B42325C6AD4BEC036BC891F 0AFDCBDA2A75DB64EDD020A39A4AF0387B68D64BFED1C5FC11C58919C6FA0C96 F617CA7860D5C10188376F31F1E323A95AB36138D4C8AEABFFF46CB6A3618ED2 88C3BEC6184BDC2522388424FCAC44EC1DCF68E6B0A19B01A223BD7193EED9C3 F5B838BE944E6C4CFEE7742EEFCCCF9F60EF632849E3306B990B2CA74B8F6AF3 465A0BF22E1E59798302338B06682323B19C4E44FEFE84C0A210031F132E015E E74264B3B0DA6E09E116572E707C45FE7010C8D291BE49657248E416B4F244F6 E557295AC3633C4B84B5638EDA1B2767D0FD770654C2667EBE9494B1DC28825E C12B1244900CF0F45EDD038BD90A98497250F897F1221A1733DBD4540D1B374F 827C8C10FA84F5A1F6A4C921426BCD3EAFB1B8C654131F15B4BA3E8D489F00EA 9BCECF58E9D15BFC1B16E4A08F0D5459D26559144278DD721DAC117E4C0F6EE3 19930DF91DEDD9664287F11ADAD823DBAB597729C554DA905BC72A6686481108 7FA7B78D41FFEDE9830955C6309749DE1ABD705BD346019D4ABC4C340C9A2A9D CA7D20D6CEB59E8B7836043C49D33C86469D27CA62851DBB00E6B8F4E28714C4 B5F277CC2CFF502F0E47352F296EE242318D73197E754E4620A9B7DBD075C93E 5225C68C47BAC50FCB58A6D33E1B55A39D131DBDD4E014C126DD320293BA9748 4712E66FBBA2BA24BC8F4B1A285AA123F7B8146F4684CD922EBD333A7B493CE4 F9C7BDE8FEC45429EC26DF8569130F0898C3D43F7CA90C210B103117911B27C1 A14E0068595867748609ED646B5E08485E7467C36A528C738C1B7CFA362CA720 C088CB808926A1D895DDFA944468AB702AA7F91D8A4BFA372E6D7640A8E24273 75C1C8466DA13AC7BC57CC6ADAEC27CDCCB29BFA5473CED983B9E2EC94132E18 6D77798D59EDAA1BA98A0618A1066374D655D55066BCF81FAB2E4511E1928ED7 C77FB148D57D8EA24EE0720AB527AA3A76285B696FD2FF3546901E849A5B3802 F21F7205C80F9A4A102DFE192C5C5A5403C6A8AE106C10746A550F7CDFC992DB E3A64BE4A2726AF22D403EAD6AC921F48D6535E9E850BEC1E5B0AC79AF04502A 1FBD5043391104C6DD0B09CAA3654A7A21A52D6164FA2E7A4FDBE9CB328C3A53 05406F4A2F45A1FD4B2CF998E94B7DAF2E3CB584A8AD83CB32844979EA560E0F 6EB5215F705141320F1BAF1504E210D3690FBC58830BACA500624F7A7ED3EEA2 789738814E197DAAF6DA815029368B28818561F044171ADDCB73B6DE459C3E9B 64196B66F8A12A1BE100124EF86CAB8B7A10822DF4951766AF568D826E0B91E5 E640EB8D3D8B188912C510D456231E46972B177019A807DA6AE89E76400E82B4 EF3EC27BCD8F879A5A7A04BB4D5E290514EF7ED3A976A5B2D5B4F9359B283DE1 1D7BFB356B3F3F02BB45FA93F0B442330A9AA29F8680260D1071BC27829EA312 0ED69BFF2730E0F550F35CF2CF16AEC7D8CFDECE336F95789FA1C76B4C6BECB4 D6400166ECB6FA2A44C587F15DD55F55A1F7FFD8F07CA99EDD2052218828B191 D52CFD56538ECE62E946AF57C39CDAED30DE6FE58491181ED84E700092A061BC 821B6A5C32A0F436DA74826E0790EBC7D55F14223DDA0234680D41A5BAC55EBD 8D657911A3C10F9537AC9D3388EBBD5856F043A544AF4E60CA7243DA6D38BB28 4646E77BF92BFA763150C7E4543E844B01097CEA61AF0CA802CD8055BEDD63C0 6D91EE700452A400496DCAB0632DBC58C5285E8722F9BEB4860842B48B1D9FAE B266B6381548CA943B5EEF047A6805D99AF761A42AA6850CC458E1C147E3ACC4 E41653EE36F6BF8C938DF808E8DF9220690A1E36BF5C7924DE8944C261955F25 A7976C3FF10C79A10D8EACBEE51C00E961588131E35B08BD2B07962EF33769D8 8A7FA9BA8EA90C38B846963030FB463511992396C25B4F83D6E6842BB7408064 B979DF1E0A1C20719C8F9430C1F46B36DAD548471A37B4328DDA480F3274900C E33879F1C6AE71A76437DA0F6712297CE10B14552768C06315EB48500514BC14 AD86EF94E5AE2390B6D9ABC097BF1A9CB666988EC3797A3464930867433F7F95 D26D8DED9791F0C49EE8AEB9017CCBA02B4B68D639B58C864EAD6067B3D1FD22 E989551D11DB9BF2A8D833391D25109F007D9E3F7ECDE5F21C64AAE0B0D4C4CC C511D9E7251286551308E976F1C69422457B9F6544A768188EC36C7964D158C5 09ED5CF20C62955EEBFB0C4A851943CB1BEDEFC216A5F11051C9074C8971A13C 59EF979D9C6C90E545E7569F16A202E0488548C6AAD14AA2D3F5C15E5807F39A 00752DDE0B2537CEF6F67A921342CD30B85CD65841BA2B92156F2ABA110F9193 1D8F5C3E7BC15D1F2A1B45FC37DA6EB07B9D77EC0C8F507F49599A3CFFA76C0F 4EE4037576BE710FD8D22424899D80D389FF23B8760FFDCB88B5BBB17345D278 42286B59AFC25036261678551AF7CB98432D66CB6C49E3ABE73B47B0568839B0 9820B34D98B0B2312CE07F438A94F7DC4C5D50066AF6FC3399BB9D58AF4E4F7B 8271B178FB44B6C9A286FF4925C920DBC35D5AF5E24B60C5637C4D1343312EE2 FA5625B6AD5ED764EA7D670761365EFDB46FB8153E23072885C3225ED394EFAE 6B319D543ABA7005821D8B857D06235F83FED9697FDB48074BE3E797D96811F0 10BC6392B1B9D4A896B3993C0A77E94B57CBBE264C12463687BCEAE30C575B1E 16DE09B2D92E58155BC5AF9339C62F48DC0C66831B7F519B236A7F1AD6E2EF6C 7216A0304F415B8C95E46AC28A0C2EED00A5E22B193338BA67F78735D8C26F7A 994D25DD5FBD72BD3B1DCA1E2B0F7151439313824FA3811C01FEDE345439CC7D 604ED31A684426939CB3F2B9DB05D509A7B0EAAB0583662991FC3ADB4C50A515 3B881A40DB960A9D6226C4B8BE7DE1CE38363BBF3537A68E269787913EF43FE0 AEFBCFA0C199AD0337F48564CCA04DBB0442A4C8BC13B0072BE782817F59C8D7 4A052705029F8986F888C498825819171C12E4CD2A33BEF7FAFC3447FB5CE42B B3BC34F3F2B61E0E43048E32522CE84FBFD8B7E36F9C83320D5C8692AED52588 A2359603E13A2F2E43B310D433B83713F94D77557C9C8EFBA9B5E5419B75BE5C 25E87490EFF8A2C54734079826AC3CC2B77B982F3D11141FEA98B417603EFE94 240F453DD6E62737EFCD0A104ED9009B009C4A62A2188A7FAAA0778F36E3CC25 D3E6D192B338E69B6C6A63ECB42EB981B08D2B65646EBF09DBCE03940135D76A E22D04BA3C8293534A9BEC2969B54A12B346AD976FACA36C07376C9A8F2A198E BF0BE85F63EE43845F761274E0D9CB7531C451516EF085BDF6A02833E38B8B87 D141D8C9F39F6F032880A6E39022707C2D318613A800E1F5A312B300115EF120 744D58CFF4C7BD46757945D541C1349225F2C0BB4ED39A2457B7D8E3DBE1C5D1 D150794D5EB2081B8F4C13F73ED220A7FCF5E2DAB5CD77926FB66CE3063A21DB 1B76BDC2C8B2AA374B9F362404AA707E3E4751848540E83B712DEA3423FE49B6 0AE4D96AAFCB9D6198918EF460E585BBC2A37B3318643CECF4D3F865E14692D9 74267716BA6CC117B13CF185717F6FA0C8602041CE79E696CCA1FECA4AA4CD31 A06916B369B7FAEA1F66AE081DF3D44236F012C557C8076772576CB116783153 C2DEAB8CD542F0B08C75E00AC57C816B372E20C2660374BF09AC498FB3AC9A3E 1BE52953FA41686599DC7213845478725D54DA531A0375CEC8BA1827C27DBAFD 6555A364CD1AEDA1A5DB57 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMR12 %!PS-AdobeFont-1.1: CMR12 1.0 %%CreationDate: 1991 Aug 20 16:38:05 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.0) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMR12) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle 0 def /isFixedPitch false def end readonly def /FontName /CMR12 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 46 /period put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 54 /six put dup 65 /A put dup 86 /V put dup 101 /e put dup 105 /i put dup 108 /l put dup 110 /n put dup 111 /o put dup 112 /p put dup 114 /r put dup 115 /s put readonly def /FontBBox{-34 -251 988 750}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 2BDBF16FBC7512FAA308A093FE5CF4E9D2405B169CD5365D6ECED5D768D66D6C 68618B8C482B341F8CA38E9BB9BAFCFAAD9C2F3FD033B62690986ED43D9C9361 3645B82392D5CAE11A7CB49D7E2E82DCD485CBA04C77322EB2E6A79D73DC194E 59C120A2DABB9BF72E2CF256DD6EB54EECBA588101ABD933B57CE8A3A0D16B28 51D7494F73096DF53BDC66BBF896B587DF9643317D5F610CD9088F9849126F23 DDE030F7B277DD99055C8B119CAE9C99158AC4E150CDFC2C66ED92EBB4CC092A AA078CE16247A1335AD332DAA950D20395A7384C33FF72EAA31A5B89766E635F 45C4C068AD7EE867398F0381B07CB94D29FF097D59FF9961D195A948E3D87C31 821E9295A56D21875B41988F7A16A1587050C3C71B4E4355BB37F255D6B237CE 96F25467F70FA19E0F85785FF49068949CCC79F2F8AE57D5F79BB9C5CF5EED5D 9857B9967D9B96CDCF73D5D65FF75AFABB66734018BAE264597220C89FD17379 26764A9302D078B4EB0E29178C878FD61007EEA2DDB119AE88C57ECFEF4B71E4 140A34951DDC3568A84CC92371A789021A103A1A347050FDA6ECF7903F67D213 1D0C7C474A9053866E9C88E65E6932BA87A73686EAB0019389F84D159809C498 1E7A30ED942EB211B00DBFF5BCC720F4E276C3339B31B6EABBB078430E6A09BB 377D3061A20B1EB98796B8607EECBC699445EAA866C38E02DF59F5EDD378303A 0733B90E7835C0AAF32BA04F1566D8161EA89CD4D14DDB953F8B910BFC8A7F03 5020F55EF8FC2640ADADA156F6CF8F2EB6610F7EE8874A26CBE7CD154469B9F4 ED76886B3FB679FFDEB59BB6C55AF7087BA48B75EE2FB374B19BCC421A963E15 FE05ECAAF9EECDF4B2715010A320102E6F8CCAA342FA11532671CEBE01C1B982 4B1CF704E817814FF9C921A7DF86627623F382208EB0CCEC832D35D9B936CFA7 3946FA2494DBC51325D4330866D33DD3E546B774EB8ACC089E62AFEE8955A55F F2B6F74FD94C06C5C71F87938D5295A2ACF34830CD5242B56841A2B4137544A1 32D98E64AD37F790574845703C739F5BDFB05BFA53B0F4389B0FCCFF03D25AE7 09DDC79EAB0178EF14D67282335F3AB8B2AFACE2E06433376B2007DEE8B60624 AE40AA85E30531E640E128CD5F89EBA045D173D10E50C8C0522099DA01F1B00C 542D6FBFA1D372D43C55305F01D70BEC886B96806AC7BA30B76FA28E75717FC8 AB91CB77949111B50B8566C1C0242A6F73E444877F0A39CC1EA349594E7540FF AD34A14D43FC327A1517B6B034B322B09347BA663558256046DC0D66DE0099EA 1B33A960B7A3C37FEE174795CA3C975F9D16DD114308ADD38F203B7DE2E8A220 885A7E036E768FBB3B599E5A76C8E7CE0B75820B269EEE63EEC8156098D183A8 A6D20104A15BE6558EFD1C9C4F5D230827E102D33E5D96C9522AD0D46B430943 3B64D20F701A7B064FEA4EA6E28DE141C2BEF2FC6C9F3237694002B9B18789C6 D157AD81136E8E951CBD0366A5206F05F4A68C7C1017E49F254ED437707E87B6 6AAD86C83DBC17FBC5FCF9E51DE92CEAE5C6818967AC83A26B3AE2E54AE34218 0D5C577A0F56115705ADADCE83D89735A71D69E8CAF93A20A22616047C498A1A 0092BC92641DF088AC0C591572F8D719394C19585CD1F03DF4D35F627AFBC502 A2C36CB17EB20E23835F6E0CB42B1C18532DFFBF0840666FED39C99BDE7DC317 974DC1D34097CC7B71ACDBCDED56E7EB088B4E7D2AAF4F761745DEE6D371852D 4F51756C97363F7D9AE57D19341CF566C531110F8F04197B207A4BCADA5199D4 CB86798A5059690E4F1C18A9ADBF9BD3E54AC6BC7B0908DBE211F4E7964CD594 1C3AD1AA5536E4BF9A0586DDC944D99238E2A3ED0F178F49B1A45BCEB385BC68 98AEE8041EDF3243ECE88920C04B609A7373E661B0E5ACDB0FD366CC417615B8 6C35D5FEED5EB88FE43D4688A7ECAB9D1FF5A44DFB75FE133A5C243E2B9F7F77 B33F05A19C616A5ED4634EEAC2B9E6F9A344ADF85759070E7083FA255EC10296 E3DEBEC97364554F8CDF3BE4E5E2EEE9E4E45FB96E677F01FA938D0CDA3F5471 AE69BCF62A767784279F56790C0789646DF52978F125488EDCD6B73EDBB489AF F811E568EDD1F7CD8B5BF7EBC228245BF2C62A06EB195D8741C76F5DCFE74F80 FED9A7B976104C0CA2536A4412B89AF59686278B858584AAF32B674E90412EE2 1C8D0463194B58C61671161578E69FC7CC0FCC62B280055D4FC3043304E9E2CD 5F3318799C0EA5F28EED6D3504E96DFAFAFC4F543F230712C706DE7C45CC9787 A069D4DF2A2C2FBD6EAA437DF7516A3E4FD3DA89419CC9BCCD2A73AD0FA50294 CDE5E44A9165E301B5F704365678E92FBDC4510A5DB07FD9AE33D4C84C9FE155 E37BD11BE772DC9251386845B7BEC43C24C189FFF8BDB7273F62220AE14B1A60 0AFE4E34818E562F410E77821E76B484F1115BD553DCB16AA903852003EF08F2 E0F957413F700296B101646D527B5B310F1B91D0BD9E89E6A775A580201E80B8 7CF3C74957B2A3D1570A2A4916B8A0975F0A81716DBC3951ED697869EBC156E3 F0A23EEBD4FC396012828EFF16B54612A009DD4995F130D37BE4807F8B245CE2 BB5A38299450E19188E0C466A7797AB2C212116ACFAEAB012AB7107AA6A2FA37 728C28CC379BFF030365AC36905415B2DBD212248390F79B7191F2F1DA344F0E 9619C0FA65A2F476272B03C5B796D926B1790F641EB6ADD5D4442C7CA34FD39F 0F07EF7837C5C9E4DBF477CED9AADBFDED496AFF3F1C45F23D7158A56CAF97EF 92C1C497C5A01F715F7E78E0254121B30DC4524D6D5F973A4B57FBF5DB7AEBE6 9E8434BBFF5AF266ACD0AF8BBD187FCA81C2281F0C91A034F65F1D817C719C5B 0AE0A10EDB2710CC595B4573B65B1B8E98D763439902375896EE49506856F5E2 51038BBE4FA692FE726887E9A5E065BCB4DA264DF7CD16D67B7ED0996CC4396C B24053DCAD500585E333CA028CAE126BFB0377D0E8366EA01F735371E3EF5190 50F0C3BDB1D32BE74968588ECE292B2F5012586265E55AAEBECD3951AE2C9C5F 3D64EAD776C7A4DEF14290037DF2ADE3A2810143A58AB50F5AB48232FF2B1A98 982CFCFE7A9A52A774E0D9A624BAEEFEE43CF556BAB6ADFBCA7BCDD3F05778BD F0FBD6EDB44CE80341CFE098F908A099EE3010C7BAF55C5582B053EB0CF5C34E 991FA08EBA1FC5D3B893F8545CC37AABC686FECA16646D81EA85D25F2AA8EA77 5E8B2FBFF81D86B7C64925E42F9FF75655AA2DC7B5BEECF8BEC424A4C236A415 6127438B84B02A8BF4D492512634F3AD4992201D7D6C6AE703A7809A77E7767A 3511588FB5B93013A1FCD2B0380C2321B19EE90EDA17B12A0D790E5DAE925B3A 4E026D2B52866C779C83EF5F31F4F54D7A289480C2FAE03138709E503ED81204 D6287D1711497562A0E28416E75D65D3425560F1CB61104F2A733F15AA0BEF31 D7308DD1846D6B9B5921D36F994344441189785075F9FF2EE79207AA0E82B5AD 609C387B86EB0ABACD9CEA427B981C30006ECE05BAADF7592F74DED5907FE422 7D316876A7DEEA4B4053702EFDA2F861490C7034E7A929F0492535503C0837EE BC80417EAC6704D64B693819FCC0BBBEC2B9BCBD2F5FD6B5FEC468E13BF720CE EB0BA928A7A92CD4705CA1BF67B3B395148E434029714A75CAF4AED10E45D5DC 163EBCB40CF5C9066CC946B6310B505F8FE89D7F610C9EA4E542BDCC188353CE 90D7BB66398EB5B153AA09A62ECBAD0C8B40BCC4E30280E57B47418FA66A2347 0CAACE2201AB788595D5B74EFE9BADF5679C6A97E7E714DA8D1E7C50271E072C AE75962CA72981F6ED551C2C9D322C007234D5DBB570E3C1EBE06DDA2E011B20 55DD67C1D3E9B3E7AC47C1D15DFE921E8F1FBB6843BBF37D669E637D201B84F0 9D49E981C6F1A803C1B40FE4DB82C3A53D138795B3816D4B07DE20621D5A644A 57E86C30E7A8096880A02E4723AA31EDB8DB7E95E373F96CE6E41EEC9EF06020 E11CB902AD80E02892F6733FC715C0957238158AAB70D6FAEF073D0259DC24FD 4B3DC7F0DE52D04B1F479806E7714B73EB1D225E1A83B9BC4177EB0C672BFBFA CF4CD8EE1C5D8639434D7951537923AB79CB195181019DB1935B705EF6DD9A3D 3F15F7E634554208F4E8E7D775BB4A6E1E0EC05DF40B444B3B8D00A528E80B09 ED50BCB1407B90D5CB7C3FE49C4420B51FA0DF45436FF5071FDE0E17F14C650A 0785E6CBFF8E6C6A79BB002AED449A16BE91458BF2DFAE96D887DBE264B45C86 89DD114648E6626197C1D181F63141634346FBC14CF4BB310FBCED5657CDBD54 D86C098E7A52D9D8A829BF4C700992862434F2FAEFBD7104CE221E8D985A2AA0 B659BE12D8CFD0BFC998A2CF7409A90690A65D20E3C909B2073D336CAEAD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont TeXDict begin 40258431 52099146 1000 600 600 (fitsio.dvi) @start /Fa 193[71 62[{}1 90.9091 /CMMI10 rf /Fb 133[50 59 59 81 59 62 44 44 46 1[62 56 62 93 31 59 1[31 62 56 34 51 62 50 62 54 9[116 85 86 78 62 84 1[77 84 88 106 67 88 1[42 88 88 70 74 86 81 80 85 6[31 1[56 56 56 56 56 56 56 56 1[56 31 37 32[62 12[{}58 99.6264 /CMBX12 rf /Fc 149[25 2[45 45 86[45 15[{}4 90.9091 /CMSY10 rf /Fd 133[60 71 71 97 71 75 52 53 55 1[75 67 75 112 37 71 1[37 75 67 41 61 75 60 75 65 9[139 102 103 94 75 100 1[92 101 105 128 81 105 1[50 105 106 85 88 103 97 96 102 6[37 67 67 67 67 67 67 67 67 67 67 67 37 45 3[52 52 27[75 78 11[{}63 119.552 /CMBX12 rf /Fe 129[48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 1[48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 33[{}93 90.9091 /CMTT10 rf /Ff 139[75 1[79 1[108 7[108 2[88 3[94 29[140 9[97 97 97 97 97 97 97 97 97 97 48[{}17 172.188 /CMBX12 rf /Fg 165[56 68 68 93 68 68 66 51 67 1[62 71 68 83 57 71 1[33 68 71 59 62 69 66 64 68 6[25 45 45 45 45 45 45 45 45 45 45 45 25 30 45[{}38 90.9091 /CMSL10 rf /Fh 134[55 55 1[55 58 41 41 43 1[58 52 58 87 29 2[29 58 52 32 48 58 46 58 51 11[80 73 58 78 1[71 79 82 4[40 1[82 66 69 80 76 74 79 7[52 52 52 52 52 52 52 52 52 52 52 1[35 32[58 12[{}49 90.9091 /CMBX10 rf /Fi 132[45 40 48 48 66 48 51 35 36 36 48 51 45 51 76 25 48 28 25 51 45 28 40 51 40 51 45 25 2[25 45 25 56 68 68 93 68 68 66 51 67 71 62 71 68 83 57 71 47 33 68 71 59 62 69 66 64 68 71 43 43 71 25 25 25 45 45 45 45 45 45 45 45 45 45 45 25 30 25 71 45 35 35 25 71 76 45 76 45 25 18[76 51 51 53 11[{}93 90.9091 /CMR10 rf /Fj 140[46 46 1[65 59 65 1[33 2[33 3[52 14[88 20[88 10[59 2[59 59 59 59 1[33 46[{}16 119.552 /CMR12 rf /Fk 138[90 63 64 66 2[81 90 134 45 2[45 1[81 49 74 1[72 90 78 12[112 90 2[110 6[60 2[101 4[122 65[{}21 143.462 /CMBX12 rf /Fl 134[123 123 1[123 129 90 92 95 1[129 116 129 194 65 2[65 129 116 71 106 129 103 129 113 11[179 162 129 173 1[159 175 182 4[87 1[183 146 153 178 168 165 175 17[116 1[77 5[65 26[129 12[{}40 206.559 /CMBX12 rf end %%EndProlog %%BeginSetup %%Feature: *Resolution 600dpi TeXDict begin %%BeginPaperSize: Letter letter %%EndPaperSize end %%EndSetup %%Page: 1 1 TeXDict begin 1 0 bop 861 1940 a Fl(FITSIO)76 b(User's)g(Guide)356 2399 y Fk(A)54 b(Subroutine)d(In)l(terface)i(to)g(FITS)h(F)-13 b(ormat)54 b(Files)1055 2659 y(for)g(F)-13 b(ortran)53 b(Programmers)1667 3155 y Fj(V)-10 b(ersion)38 b(3.0)1727 4058 y Fi(HEASAR)m(C)1764 4170 y(Co)s(de)30 b(662)1363 4283 y(Go)s(ddard)f(Space)i(Fligh)m(t)h(Cen)m(ter)1522 4396 y(Green)m(b)s(elt,)f(MD)h(20771)1857 4509 y(USA)1682 5298 y Fj(April)37 b(2016)p eop end %%Page: 2 2 TeXDict begin 2 1 bop 0 299 a Fi(ii)p eop end %%Page: 3 3 TeXDict begin 3 2 bop 0 1267 a Fl(Con)-6 b(ten)g(ts)0 1858 y Fh(1)84 b(In)m(tro)s(duction)3136 b(1)0 2118 y(2)119 b(Creating)34 b(FITSIO/CFITSIO)2405 b(3)136 2280 y Fi(2.1)94 b(Building)31 b(the)f(Library)58 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(3)136 2442 y(2.2)94 b(T)-8 b(esting)32 b(the)e(Library)j(.)46 b(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(6)136 2604 y(2.3)94 b(Linking)31 b(Programs)f(with)g(FITSIO)40 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(7)136 2766 y(2.4)94 b(Getting)32 b(Started)f(with)f(FITSIO)55 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(7)136 2928 y(2.5)94 b(Example)31 b(Program)86 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) f(.)131 b(8)136 3090 y(2.6)94 b(Legal)32 b(Stu\013)92 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)f(.)131 b(9)136 3252 y(2.7)94 b(Ac)m(kno)m(wledgmen)m(ts)30 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(10)0 3511 y Fh(3)119 b(A)35 b(FITS)f(Primer)2918 b(13)0 3771 y(4)84 b(FITSIO)34 b(Con)m(v)m(en)m(tions)h(and)g(Guidelines)1993 b(15)136 3933 y Fi(4.1)94 b(CFITSIO)29 b(Size)i(Limitations)42 b(.)k(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(15)136 4095 y(4.2)94 b(Multiple)32 b(Access)f(to)g(the)g(Same)f(FITS) g(File)h(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(16)136 4257 y(4.3)94 b(Curren)m(t)30 b(Header)h(Data)h(Unit)e(\(CHDU\))87 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(16)136 4419 y(4.4)94 b(Subroutine)29 b(Names)79 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(16)136 4581 y(4.5)94 b(Subroutine)29 b(F)-8 b(amilies)33 b(and)c(Datat)m(yp)s (es)44 b(.)i(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(17)136 4742 y(4.6)94 b(Implicit)31 b(Data)h(T)m(yp)s(e)e(Con)m(v)m(ersion)65 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(17)136 4904 y(4.7)94 b(Data)32 b(Scaling)89 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)f(.)85 b(18)136 5066 y(4.8)94 b(Error)30 b(Status)g(V)-8 b(alues)32 b(and)d(the)i(Error)e(Message)j(Stac)m(k)44 b(.)i(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)f(.)85 b(18)136 5228 y(4.9)94 b(V)-8 b(ariable-Length)33 b(Arra)m(y)d(F)-8 b(acilit)m(y)34 b(in)c(Binary)g(T)-8 b(ables)26 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(19)136 5390 y(4.10)49 b(Supp)s(ort)29 b(for)h(IEEE)g(Sp)s(ecial)g(V)-8 b(alues)68 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(20)136 5552 y(4.11)49 b(When)31 b(the)f(Final)h(Size)g(of)g(the)f(FITS)g(HDU)h (is)f(Unkno)m(wn)k(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(21)136 5714 y(4.12)49 b(Lo)s(cal)32 b(FITS)d(Con)m(v)m(en)m(tions)j(supp)s(orted)c(b)m(y)j (FITSIO)72 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(21)1912 5942 y(iii)p eop end %%Page: 4 4 TeXDict begin 4 3 bop 0 299 a Fi(iv)3311 b Fg(CONTENTS)345 555 y Fi(4.12.1)61 b(Supp)s(ort)29 b(for)h(Long)g(String)g(Keyw)m(ord)g (V)-8 b(alues.)62 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(21)345 716 y(4.12.2)61 b(Arra)m(ys)31 b(of)f(Fixed-Length)h(Strings)f(in)g(Binary)h(T)-8 b(ables)70 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)f(.)85 b(22)345 876 y(4.12.3)61 b(Keyw)m(ord)30 b(Units)h(Strings)i (.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(23)345 1037 y(4.12.4)61 b(HIERAR)m(CH)31 b(Con)m(v)m(en)m(tion)h(for) e(Extended)g(Keyw)m(ord)g(Names)83 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)f(.)85 b(23)136 1197 y(4.13)49 b(Optimizing)31 b(Co)s(de)f(for)g(Maxim)m(um)h(Pro)s(cessing)g(Sp)s(eed)44 b(.)i(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)f(.)85 b(24)345 1358 y(4.13.1)61 b(Bac)m(kground)31 b(Information:)41 b(Ho)m(w)31 b(CFITSIO)e(Manages)j(Data)g(I/O)91 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(24)345 1518 y(4.13.2)61 b(Optimization)32 b(Strategies)69 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(25)0 1771 y Fh(5)119 b(Basic)36 b(In)m(terface)e(Routines)2504 b(29)136 1931 y Fi(5.1)94 b(FITSIO)30 b(Error)f(Status)h(Routines)84 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(29)136 2092 y(5.2)94 b(File)32 b(I/O)e(Routines)e(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)f(.)85 b(30)136 2252 y(5.3)94 b(Keyw)m(ord)31 b(I/O)f(Routines)36 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f (.)85 b(32)136 2412 y(5.4)94 b(Data)32 b(I/O)f(Routines)53 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)f(.)85 b(33)0 2665 y Fh(6)119 b(Adv)-6 b(anced)36 b(In)m(terface)e(Subroutines)2159 b(35)136 2826 y Fi(6.1)94 b(FITS)30 b(File)i(Op)s(en)d(and)g(Close)i(Subroutines:)76 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(35)136 2986 y(6.2)94 b(HDU-Lev)m(el)33 b(Op)s(erations)108 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(38)136 3146 y(6.3)94 b(De\014ne)31 b(or)f(Rede\014ne)g(the)h(structure)f(of)g(the)h (CHDU)99 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(41)136 3307 y(6.4)94 b(FITS)30 b(Header)h(I/O)f(Subroutines)i(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)f(.)85 b(43)345 3467 y(6.4.1)106 b(Header)31 b(Space)g(and)f(P)m(osition)h(Routines)60 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)f(.)85 b(43)345 3628 y(6.4.2)106 b(Read)31 b(or)f(W)-8 b(rite)32 b(Standard)d(Header)i(Routines)67 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)f(.)85 b(43)345 3788 y(6.4.3)106 b(W)-8 b(rite)32 b(Keyw)m(ord)e(Subroutines)116 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.) 85 b(45)345 3949 y(6.4.4)106 b(Insert)30 b(Keyw)m(ord)g(Subroutines)108 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(47)345 4109 y(6.4.5)106 b(Read)31 b(Keyw)m(ord)f(Subroutines)64 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(47)345 4270 y(6.4.6)106 b(Mo)s(dify)30 b(Keyw)m(ord)h(Subroutines)55 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(49)345 4430 y(6.4.7)106 b(Up)s(date)31 b(Keyw)m(ord)f(Subroutines)116 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(50)345 4591 y(6.4.8)106 b(Delete)33 b(Keyw)m(ord)d(Subroutines)87 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(51)136 4751 y(6.5)94 b(Data)32 b(Scaling)g(and)d(Unde\014ned)g(Pixel)i(P)m (arameters)113 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(51)136 4912 y(6.6)94 b(FITS)30 b(Primary)g(Arra)m(y)h(or)f(IMA)m(GE)h(Extension)g(I/O)f (Subroutines)117 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f (.)85 b(52)136 5072 y(6.7)94 b(FITS)30 b(ASCI)s(I)f(and)h(Binary)g(T)-8 b(able)31 b(Data)h(I/O)e(Subroutines)d(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(55)345 5232 y(6.7.1)106 b(Column)30 b(Information)g(Subroutines)121 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(55)345 5393 y(6.7.2)106 b(Lo)m(w-Lev)m(el)33 b(T)-8 b(able)31 b(Access)g(Subroutines)60 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)f(.)85 b(58)345 5553 y(6.7.3)106 b(Edit)31 b(Ro)m(ws)f(or)h(Columns)106 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)f(.)85 b(59)345 5714 y(6.7.4)106 b(Read)31 b(and)f(W)-8 b(rite)31 b(Column)f(Data)i(Routines)66 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)f(.)85 b(60)p eop end %%Page: 5 5 TeXDict begin 5 4 bop 0 299 a Fg(CONTENTS)3334 b Fi(v)136 555 y(6.8)94 b(Ro)m(w)31 b(Selection)h(and)e(Calculator)i(Routines)95 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(64)136 717 y(6.9)94 b(Celestial)33 b(Co)s(ordinate)d(System)g(Subroutines)98 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(65)136 879 y(6.10)49 b(File)32 b(Chec)m(ksum)e(Subroutines)75 b(.)45 b(.)h(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(67)136 1041 y(6.11)80 b(Date)32 b(and)d(Time)i(Utilit)m(y)h(Routines)69 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(68)136 1204 y(6.12)49 b(General)32 b(Utilit)m(y)g(Subroutines)61 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(69)0 1464 y Fh(7)119 b(The)35 b(CFITSIO)e(Iterator)g(F)-9 b(unction)2154 b(77)0 1725 y(8)119 b(Extended)35 b(File)f(Name)h(Syn)m (tax)2330 b(79)136 1887 y Fi(8.1)94 b(Ov)m(erview)84 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(79)136 2049 y(8.2)94 b(Filet)m(yp)s(e)62 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(82)345 2211 y(8.2.1)106 b(Notes)32 b(ab)s(out)e(HTTP)g(pro)m(xy)g (serv)m(ers)k(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(82)345 2373 y(8.2.2)106 b(Notes)32 b(ab)s(out)e(the)h(stream)f(\014let)m(yp)s (e)h(driv)m(er)54 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(83)345 2536 y(8.2.3)106 b(Notes)32 b(ab)s(out)e(the)h(gsiftp)f(\014let)m(yp)s(e)83 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(84)345 2698 y(8.2.4)106 b(Notes)32 b(ab)s(out)e(the)h(ro)s(ot)f(\014let)m(yp)s(e)68 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(84)345 2860 y(8.2.5)106 b(Notes)32 b(ab)s(out)e(the)h(shmem)e(\014let)m(yp)s(e:)70 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(86)136 3022 y(8.3)94 b(Base)32 b(Filename)90 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(86)136 3184 y(8.4)94 b(Output)30 b(File)h(Name)g(when)f(Op)s(ening)f(an)h (Existing)h(File)81 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(88)136 3346 y(8.5)94 b(T)-8 b(emplate)32 b(File)g(Name)f(when)e(Creating)i(a)g(New)f(File)57 b(.)46 b(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)f(.)85 b(90)136 3508 y(8.6)94 b(Image)32 b(Tile-Compression)e(Sp)s(eci\014cation)91 b(.)45 b(.)h(.)g(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)f(.)85 b(90)136 3670 y(8.7)94 b(HDU)32 b(Lo)s(cation)f(Sp)s (eci\014cation)47 b(.)e(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) f(.)85 b(90)136 3832 y(8.8)94 b(Image)32 b(Section)39 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)f(.)85 b(91)136 3994 y(8.9)94 b(Image)32 b(T)-8 b(ransform)29 b(Filters)54 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(92)136 4156 y(8.10)49 b(Column)30 b(and)g(Keyw)m(ord)g(Filtering)h(Sp)s(eci\014cation)91 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)f(.)85 b(94)136 4318 y(8.11)49 b(Ro)m(w)31 b(Filtering)h(Sp)s(eci\014cation)82 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(96)345 4481 y(8.11.1)61 b(General)32 b(Syn)m(tax)44 b(.)i(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(97)345 4643 y(8.11.2)61 b(Bit)32 b(Masks)43 b(.)j(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)85 b(99)345 4805 y(8.11.3)61 b(V)-8 b(ector)32 b(Columns)92 b(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(100)345 4967 y(8.11.4)61 b(Go)s(o)s(d)30 b(Time)h(In)m(terv)-5 b(al)31 b(Filtering)62 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(102)345 5129 y(8.11.5)61 b(Spatial)31 b(Region)h(Filtering)59 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(103)345 5291 y(8.11.6)61 b(Example)31 b(Ro)m(w)g(Filters)h(.)45 b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(105)136 5453 y(8.12)80 b(Binning)30 b(or)g(Histogramming)i(Sp)s (eci\014cation)f(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(106)0 5714 y Fh(9)84 b(T)-9 b(emplate)35 b(Files)2933 b(109)p eop end %%Page: 6 6 TeXDict begin 6 5 bop 0 299 a Fi(vi)3311 b Fg(CONTENTS)136 555 y Fi(9.1)94 b(Detailed)33 b(T)-8 b(emplate)31 b(Line)g(F)-8 b(ormat)48 b(.)e(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(109)136 715 y(9.2)94 b(Auto-indexing)31 b(of)g(Keyw)m(ords)73 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(110)136 876 y(9.3)94 b(T)-8 b(emplate)32 b(P)m(arser)f(Directiv)m(es) 87 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(111)136 1036 y(9.4)94 b(F)-8 b(ormal)32 b(T)-8 b(emplate)32 b(Syn)m(tax)i(.)46 b(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h (.)g(.)f(.)40 b(112)136 1196 y(9.5)94 b(Errors)63 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(112)136 1356 y(9.6)94 b(Examples)72 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)40 b(112)0 1607 y Fh(10)67 b(Summary)36 b(of)f(all)f(FITSIO)g(User-In)m(terface)h (Subroutines)1215 b(115)0 1858 y(11)67 b(P)m(arameter)35 b(De\014nitions)2563 b(123)0 2109 y(12)67 b(FITSIO)33 b(Error)i(Status)g(Co)s(des)2295 b(129)p eop end %%Page: 1 7 TeXDict begin 1 6 bop 0 1225 a Ff(Chapter)65 b(1)0 1687 y Fl(In)-6 b(tro)6 b(duction)0 2180 y Fi(This)33 b(do)s(cumen)m(t)i (describ)s(es)e(the)h(F)-8 b(ortran-callable)38 b(subroutine)33 b(in)m(terface)j(that)f(is)f(pro)m(vided)g(as)g(part)g(of)h(the)0 2293 y(CFITSIO)f(library)h(\(whic)m(h)h(is)g(written)g(in)f(ANSI)g (C\).)h(This)f(is)h(a)g(companion)g(do)s(cumen)m(t)f(to)i(the)e (CFITSIO)0 2406 y(User's)k(Guide)f(whic)m(h)h(should)e(b)s(e)h (consulted)h(for)f(further)g(information)h(ab)s(out)f(the)h(underlying) e(CFITSIO)0 2518 y(library)-8 b(.)50 b(In)32 b(the)i(remainder)f(of)g (this)h(do)s(cumen)m(t,)g(the)g(terms)f(FITSIO)f(and)h(CFITSIO)f(are)i (in)m(terc)m(hangeable)0 2631 y(and)c(refer)g(to)h(the)g(same)f (library)-8 b(.)0 2791 y(FITSIO/CFITSIO)31 b(is)j(a)f(mac)m(hine-indep) s(enden)m(t)g(library)g(of)h(routines)f(for)g(reading)h(and)f(writing)g (data)h(\014les)0 2904 y(in)c(the)g(FITS)g(\(Flexible)i(Image)f(T)-8 b(ransp)s(ort)29 b(System\))h(data)h(format.)41 b(It)31 b(can)f(also)h(read)g(IRAF)f(format)h(image)0 3017 y(\014les)40 b(and)e(ra)m(w)i(binary)f(data)h(arra)m(ys)g(b)m(y)g(con)m(v)m(erting)h (them)e(on)h(the)g(\015y)f(in)m(to)h(a)g(virtual)g(FITS)f(format)h (\014le.)0 3130 y(This)32 b(library)h(w)m(as)g(written)g(to)h(pro)m (vide)f(a)h(p)s(o)m(w)m(erful)f(y)m(et)h(simple)f(in)m(terface)h(for)f (accessing)i(FITS)d(\014les)h(whic)m(h)0 3243 y(will)j(run)e(on)h(most) h(commonly)g(used)e(computers)h(and)g(w)m(orkstations.)57 b(FITSIO)34 b(supp)s(orts)g(all)i(the)g(features)0 3356 y(describ)s(ed)j(in)g(the)h(o\016cial)i(de\014nition)d(of)h(the)g(FITS) f(format)i(and)e(can)h(read)g(and)f(write)h(all)h(the)f(curren)m(tly)0 3469 y(de\014ned)g(t)m(yp)s(es)h(of)g(extensions,)j(including)d(ASCI)s (I)e(tables)j(\(T)-8 b(ABLE\),)42 b(Binary)f(tables)h(\(BINT)-8 b(ABLE\))43 b(and)0 3582 y(IMA)m(GE)36 b(extensions.)56 b(The)34 b(FITSIO)g(subroutines)g(insulate)i(the)f(programmer)g(from)g (ha)m(ving)h(to)g(deal)f(with)0 3695 y(the)25 b(complicated)h (formatting)g(details)f(in)f(the)h(FITS)f(\014le,)i(ho)m(w)m(ev)m(er,)i (it)d(is)f(assumed)g(that)h(users)f(ha)m(v)m(e)i(a)f(general)0 3808 y(kno)m(wledge)31 b(ab)s(out)f(the)h(structure)f(and)g(usage)h(of) f(FITS)g(\014les.)0 3968 y(The)20 b(CFITSIO)f(pac)m(k)-5 b(age)23 b(w)m(as)e(initially)i(dev)m(elop)s(ed)e(b)m(y)f(the)h(HEASAR) m(C)g(\(High)h(Energy)e(Astroph)m(ysics)h(Science)0 4081 y(Arc)m(hiv)m(e)35 b(Researc)m(h)g(Cen)m(ter\))f(at)h(the)f(NASA)g(Go)s (ddard)e(Space)j(Fligh)m(t)g(Cen)m(ter)f(to)h(con)m(v)m(ert)g(v)-5 b(arious)34 b(existing)0 4194 y(and)25 b(newly)h(acquired)g (astronomical)i(data)e(sets)h(in)m(to)g(FITS)e(format)h(and)f(to)i (further)e(analyze)i(data)g(already)f(in)0 4307 y(FITS)h(format.)41 b(New)28 b(features)g(con)m(tin)m(ue)h(to)g(b)s(e)e(added)h(to)g (CFITSIO)f(in)g(large)i(part)f(due)g(to)g(con)m(tributions)h(of)0 4419 y(ideas)k(or)g(actual)h(co)s(de)f(from)f(users)g(of)h(the)g(pac)m (k)-5 b(age.)49 b(The)33 b(In)m(tegral)h(Science)f(Data)h(Cen)m(ter)f (in)g(Switzerland,)0 4532 y(and)g(the)g(XMM/ESTEC)h(pro)5 b(ject)34 b(in)f(The)g(Netherlands)g(made)g(esp)s(ecially)i (signi\014can)m(t)f(con)m(tributions)g(that)0 4645 y(resulted)c(in)g (man)m(y)h(of)f(the)h(new)f(features)g(that)h(app)s(eared)f(in)g(v2.0)i (of)e(CFITSIO.)0 4805 y(The)22 b(latest)i(v)m(ersion)f(of)g(the)f (CFITSIO)f(source)i(co)s(de,)h(do)s(cumen)m(tation,)i(and)21 b(example)j(programs)e(are)h(a)m(v)-5 b(ailable)0 4918 y(on)30 b(the)h(W)-8 b(orld-Wide)32 b(W)-8 b(eb)31 b(or)f(via)h(anon)m (ymous)f(ftp)g(from:)382 5178 y Fe(http://heasarc.gsfc.nasa)o(.go)o (v/fi)o(tsio)382 5291 y(ftp://legacy.gsfc.nasa.g)o(ov/)o(soft)o(ware)o (/fi)o(tsio)o(/c)1927 5942 y Fi(1)p eop end %%Page: 2 8 TeXDict begin 2 7 bop 0 299 a Fi(2)2452 b Fg(CHAPTER)30 b(1.)71 b(INTR)m(ODUCTION)0 555 y Fi(An)m(y)28 b(questions,)g(bug)f (rep)s(orts,)h(or)f(suggested)i(enhancemen)m(ts)f(related)g(to)h(the)e (CFITSIO)f(pac)m(k)-5 b(age)30 b(should)d(b)s(e)0 668 y(sen)m(t)k(to)g(the)g(FTOOLS)e(Help)h(Desk)h(at)g(the)g(HEASAR)m(C:) 382 928 y Fe(http://heasarc.gsfc.nasa)o(.go)o(v/cg)o(i-bi)o(n/f)o(tool) o(shel)o(p)0 1188 y Fi(This)40 b(User's)i(Guide)f(assumes)g(that)h (readers)f(already)g(ha)m(v)m(e)i(a)f(general)g(understanding)d(of)j (the)f(de\014nition)0 1301 y(and)31 b(structure)g(of)h(FITS)e(format)i (\014les.)44 b(F)-8 b(urther)32 b(information)f(ab)s(out)h(FITS)f (formats)g(is)h(a)m(v)-5 b(ailable)34 b(from)d(the)0 1413 y(FITS)37 b(Supp)s(ort)f(O\016ce)i(at)h Fe (http://fits.gsfc.nasa.g)o(ov)p Fi(.)57 b(In)37 b(particular,)j(the)e ('FITS)g(Standard')f(giv)m(es)0 1526 y(the)31 b(authoritativ)m(e)j (de\014nition)d(of)g(the)h(FITS)e(data)i(format.)43 b(Other)31 b(do)s(cumen)m(ts)g(a)m(v)-5 b(ailable)34 b(at)d(that)h(W)-8 b(eb)32 b(site)0 1639 y(pro)m(vide)e(additional)i(historical)f(bac)m (kground)g(and)e(practical)j(advice)g(on)e(using)g(FITS)f(\014les.)0 1799 y(The)d(HEASAR)m(C)f(also)i(pro)m(vides)f(a)h(v)m(ery)f (sophisticated)h(FITS)e(\014le)i(analysis)f(program)g(called)h(`Fv')g (whic)m(h)f(can)0 1912 y(b)s(e)31 b(used)f(to)i(displa)m(y)f(and)g (edit)g(the)h(con)m(ten)m(ts)g(of)g(an)m(y)f(FITS)g(\014le)g(as)g(w)m (ell)h(as)g(construct)f(new)g(FITS)f(\014les)h(from)0 2025 y(scratc)m(h.)56 b(Fv)36 b(is)f(freely)h(a)m(v)-5 b(ailable)37 b(for)e(most)h(Unix)f(platforms,)i(Mac)f(PCs,)g(and)f (Windo)m(ws)g(PCs.)54 b(CFITSIO)0 2138 y(users)29 b(ma)m(y)h(also)h(b)s (e)f(in)m(terested)g(in)g(the)g(FTOOLS)f(pac)m(k)-5 b(age)31 b(of)g(programs)e(that)h(can)h(b)s(e)e(used)g(to)i(manipulate)0 2251 y(and)f(analyze)i(FITS)d(format)i(\014les.)41 b(Fv)30 b(and)g(FTOOLS)f(are)i(a)m(v)-5 b(ailable)32 b(from)e(their)h(resp)s (ectiv)m(e)g(W)-8 b(eb)31 b(sites)g(at:)382 2511 y Fe (http://fv.gsfc.nasa.gov)382 2624 y(http://heasarc.gsfc.nasa)o(.go)o (v/ft)o(ools)p eop end %%Page: 3 9 TeXDict begin 3 8 bop 0 1225 a Ff(Chapter)65 b(2)0 1687 y Fl(Creating)77 b(FITSIO/CFITSIO)0 2216 y Fd(2.1)135 b(Building)45 b(the)h(Library)0 2467 y Fi(T)-8 b(o)43 b(use)g(the)g(FITSIO)f(subroutines)f(one)j(m)m(ust)e(\014rst)g(build)g (the)h(CFITSIO)f(library)-8 b(,)46 b(whic)m(h)d(requires)f(a)h(C)0 2580 y(compiler.)73 b(gcc)43 b(is)e(ideal,)j(or)d(most)h(other)f (ANSI-C)g(compilers)g(will)h(also)g(w)m(ork.)73 b(The)40 b(CFITSIO)g(co)s(de)h(is)0 2692 y(con)m(tained)25 b(in)f(ab)s(out)f(40) i(C)f(source)g(\014les)f(\(*.c\))j(and)d(header)h(\014les)g(\(*.h\).)39 b(On)23 b(V)-10 b(AX/VMS)25 b(systems)f(2)g(assem)m(bly-)0 2805 y(co)s(de)31 b(\014les)f(\(vmsieeed.mar)h(and)f(vmsieeer.mar\))h (are)g(also)g(needed.)0 2965 y(The)45 b(F)-8 b(ortran)46 b(in)m(terface)g(subroutines)e(to)i(the)f(C)g(CFITSIO)f(routines)h(are) g(lo)s(cated)i(in)e(the)g(f77)p 3538 2965 28 4 v 33 w(wrap1.c,)0 3078 y(through)22 b(f77)p 459 3078 V 33 w(wrap4.c)h(\014les.)38 b(These)22 b(are)h(relativ)m(ely)i(simple)d('wrapp)s(ers')f(that)i (translate)h(the)f(argumen)m(ts)g(in)f(the)0 3191 y(F)-8 b(ortran)26 b(subroutine)e(in)m(to)j(the)e(appropriate)h(format)g(for)f (the)g(corresp)s(onding)g(C)g(routine.)39 b(This)24 b(translation)j(is) 0 3304 y(p)s(erformed)19 b(transparen)m(tly)i(to)g(the)g(user)f(b)m(y)g (a)h(set)h(of)e(C)h(macros)g(lo)s(cated)h(in)e(the)h(cfortran.h)f (\014le.)38 b(Unfortunately)0 3417 y(cfortran.h)28 b(do)s(es)g(not)g (supp)s(ort)f(ev)m(ery)h(com)m(bination)i(of)e(C)g(and)f(F)-8 b(ortran)29 b(compilers)g(so)f(the)h(F)-8 b(ortran)28 b(in)m(terface)0 3530 y(is)i(not)h(supp)s(orted)e(on)h(all)h (platforms.)41 b(\(see)31 b(further)e(notes)i(b)s(elo)m(w\).)0 3690 y(A)f(standard)f(com)m(bination)j(of)e(C)f(and)h(F)-8 b(ortran)30 b(compilers)h(will)f(b)s(e)f(assumed)h(b)m(y)f(default,)i (but)e(one)h(ma)m(y)h(also)0 3803 y(sp)s(ecify)f(a)h(particular)f(F)-8 b(ortran)32 b(compiler)e(b)m(y)h(doing:)48 4064 y Fe(>)95 b(setenv)46 b(CFLAGS)g(-DcompilerName=1)0 4324 y Fi(\(where)33 b('compilerName')h(is)f(the)g(name)f(of)h(the)g(compiler\))h(b)s(efore) e(running)f(the)i(con\014gure)f(command.)47 b(The)0 4437 y(curren)m(tly)30 b(recognized)i(compiler)f(names)f(are:)48 4698 y Fe(g77Fortran)48 4811 y(IBMR2Fortran)48 4924 y(CLIPPERFortran)48 5036 y(pgiFortran)48 5149 y(NAGf90Fortran)48 5262 y(f2cFortran)48 5375 y(hpuxFortran)48 5488 y(apolloFortran)48 5601 y(sunFortran)48 5714 y(CRAYFortran)1927 5942 y Fi(3)p eop end %%Page: 4 10 TeXDict begin 4 9 bop 0 299 a Fi(4)1896 b Fg(CHAPTER)30 b(2.)111 b(CREA)-8 b(TING)31 b(FITSIO/CFITSIO)48 555 y Fe(mipsFortran)48 668 y(DECFortran)48 781 y(vmsFortran)48 894 y(CONVEXFortran)48 1007 y(PowerStationFortran)48 1120 y(AbsoftUNIXFortran)48 1233 y(AbsoftProFortran)48 1346 y(SXFortran)0 1609 y Fi(Alternativ)m(ely)-8 b(,)42 b(one)c(ma)m(y)g(edit)g(the)f(CFLA)m(GS)h(line)f(in)h(the)f(Mak)m (e\014le)i(to)f(add)f(the)h('-DcompilerName')i(\015ag)0 1722 y(after)31 b(running)e(the)h('./con\014gure')h(command.)0 1882 y(The)f(CFITSIO)f(library)h(is)g(built)g(on)h(Unix)f(systems)g(b)m (y)g(t)m(yping:)48 2146 y Fe(>)95 b(./configure)45 b ([--prefix=/target/insta)o(llat)o(ion)o(/pat)o(h])764 2259 y([--enable-sse2])e([--enable-ssse3])48 2372 y(>)95 b(make)476 b(\(or)95 b('make)46 b(shared'\))48 2485 y(>)95 b(make)47 b(install)93 b(\(this)46 b(step)h(is)g(optional\))0 2749 y Fi(at)24 b(the)g(op)s(erating)g(system)g(prompt.)38 b(The)23 b(con\014gure)g(command)g(customizes)i(the)f(Mak)m(e\014le)h (for)f(the)g(particular)0 2861 y(system,)g(then)d(the)g(`mak)m(e')i (command)e(compiles)h(the)f(source)h(\014les)f(and)g(builds)f(the)h (library)-8 b(.)38 b(T)m(yp)s(e)21 b(`./con\014gure')0 2974 y(and)34 b(not)h(simply)f(`con\014gure')h(to)h(ensure)e(that)h (the)g(con\014gure)g(script)f(in)h(the)g(curren)m(t)f(directory)h(is)g (run)f(and)0 3087 y(not)29 b(some)g(other)g(system-wide)g(con\014gure)f (script.)40 b(The)29 b(optional)h('pre\014x')e(argumen)m(t)h(to)g (con\014gure)g(giv)m(es)h(the)0 3200 y(path)e(to)i(the)f(directory)g (where)f(the)h(CFITSIO)f(library)g(and)g(include)h(\014les)f(should)g (b)s(e)g(installed)i(via)f(the)g(later)0 3313 y('mak)m(e)j(install')f (command.)41 b(F)-8 b(or)31 b(example,)143 3577 y Fe(>)48 b(./configure)c(--prefix=/usr1/local)0 3841 y Fi(will)25 b(cause)h(the)f('mak)m(e)h(install')g(command)f(to)h(cop)m(y)g(the)f (CFITSIO)e(lib)s(c\014tsio)i(\014le)h(to)f(/usr1/lo)s(cal/lib)i(and)e (the)0 3953 y(necessary)33 b(include)e(\014les)i(to)f(/usr1/lo)s (cal/include)j(\(assuming)d(of)g(course)g(that)h(the)f(pro)s(cess)g (has)g(p)s(ermission)0 4066 y(to)f(write)g(to)g(these)g(directories\).) 0 4227 y(The)24 b(optional)i({enable-sse2)g(and)e({enable-ssse3)i (\015ags)e(will)h(cause)g(con\014gure)f(to)h(attempt)h(to)f(build)e (CFITSIO)0 4339 y(using)31 b(faster)h(b)m(yte-sw)m(apping)g (algorithms.)46 b(See)32 b(the)g("Optimizing)g(Programs")g(section)h (of)f(this)f(man)m(ual)h(for)0 4452 y(more)f(information)f(ab)s(out)g (these)h(options.)0 4613 y(By)37 b(default,)i(the)f(Mak)m(e\014le)g (will)g(b)s(e)e(con\014gured)g(to)i(build)e(the)h(set)h(of)f(F)-8 b(ortran-callable)40 b(wrapp)s(er)35 b(routines)0 4725 y(whose)30 b(calling)i(sequences)f(are)f(describ)s(ed)g(later)h(in)f (this)g(do)s(cumen)m(t.)0 4886 y(The)e('mak)m(e)h(shared')f(option)h (builds)e(a)i(shared)e(or)i(dynamic)f(v)m(ersion)h(of)f(the)h(CFITSIO)d (library)-8 b(.)40 b(When)28 b(using)0 4999 y(the)f(shared)f(library)h (the)g(executable)h(co)s(de)f(is)g(not)g(copied)g(in)m(to)h(y)m(our)f (program)g(at)g(link)g(time)g(and)g(instead)g(the)0 5111 y(program)g(lo)s(cates)i(the)f(necessary)g(library)f(co)s(de)h(at)g (run)e(time,)j(normally)f(through)e(LD)p 3065 5111 28 4 v 33 w(LIBRAR)-8 b(Y)p 3514 5111 V 34 w(P)g(A)g(TH)28 b(or)0 5224 y(some)j(other)f(metho)s(d.)41 b(The)29 b(adv)-5 b(an)m(tages)33 b(of)d(using)g(a)h(shared)e(library)h(are:)143 5488 y Fe(1.)95 b(Less)47 b(disk)f(space)h(if)g(you)g(build)f(more)h (than)f(1)i(program)143 5601 y(2.)95 b(Less)47 b(memory)f(if)h(more)g (than)f(one)h(copy)g(of)g(a)g(program)f(using)h(the)g(shared)334 5714 y(library)f(is)h(running)f(at)h(the)g(same)g(time)f(since)h(the)g (system)f(is)h(smart)p eop end %%Page: 5 11 TeXDict begin 5 10 bop 0 299 a Fg(2.1.)72 b(BUILDING)31 b(THE)f(LIBRAR)-8 b(Y)2507 b Fi(5)334 555 y Fe(enough)46 b(to)h(share)g(copies)f(of)h(the)g(shared)f(library)g(at)h(run)g(time.) 143 668 y(3.)95 b(Possibly)46 b(easier)g(maintenance)e(since)j(a)g(new) g(version)f(of)h(the)g(shared)334 781 y(library)f(can)h(be)g(installed) e(without)h(relinking)f(all)i(the)g(software)334 894 y(that)g(uses)f(it)i(\(as)e(long)h(as)g(the)g(subroutine)e(names)i(and) f(calling)334 1007 y(sequences)f(remain)h(unchanged\).)143 1120 y(4.)95 b(No)47 b(run-time)f(penalty.)0 1534 y Fi(The)30 b(disadv)-5 b(an)m(tages)32 b(are:)143 1949 y Fe(1.)47 b(More)g(hassle)f(at)h(runtime.)94 b(You)46 b(have)h(to)g(either)f (build)h(the)g(programs)286 2062 y(specially)f(or)h(have)f (LD_LIBRARY_PATH)e(set)j(right.)143 2175 y(2.)g(There)g(may)g(be)g(a)g (slight)f(start)h(up)g(penalty,)e(depending)h(on)h(where)f(you)h(are) 286 2288 y(reading)f(the)h(shared)f(library)g(and)h(the)g(program)f (from)g(and)h(if)g(your)g(CPU)g(is)286 2401 y(either)f(really)h(slow)f (or)h(really)f(heavily)g(loaded.)0 2815 y Fi(On)30 b(HP/UX)i(systems,)g (the)f(en)m(vironmen)m(t)h(v)-5 b(ariable)32 b(CFLA)m(GS)f(should)f(b)s (e)h(set)g(to)h(-Ae)g(b)s(efore)f(running)e(con-)0 2928 y(\014gure)h(to)h(enable)g("extended)g(ANSI")f(features.)0 3088 y(It)j(ma)m(y)g(not)g(b)s(e)f(p)s(ossible)g(to)h(statically)i (link)e(programs)f(that)h(use)g(CFITSIO)e(on)h(some)h(platforms)g (\(namely)-8 b(,)0 3201 y(on)28 b(Solaris)h(2.6\))h(due)e(to)h(the)g (net)m(w)m(ork)g(driv)m(ers)f(\(whic)m(h)h(pro)m(vide)g(FTP)f(and)g (HTTP)g(access)h(to)h(FITS)d(\014les\).)41 b(It)0 3314 y(is)33 b(p)s(ossible)f(to)i(mak)m(e)f(b)s(oth)g(a)g(dynamic)f(and)g(a) i(static)g(v)m(ersion)f(of)g(the)g(CFITSIO)e(library)-8 b(,)34 b(but)e(net)m(w)m(ork)i(\014le)0 3427 y(access)e(will)e(not)h(b) s(e)f(p)s(ossible)g(using)g(the)g(static)i(v)m(ersion.)0 3587 y(On)c(V)-10 b(AX/VMS)31 b(and)d(ALPHA/VMS)i(systems)f(the)h(mak)m (e)p 2100 3587 28 4 v 34 w(g\015oat.com)h(command)e(\014le)g(ma)m(y)h (b)s(e)f(executed)h(to)0 3700 y(build)35 b(the)i(c\014tsio.olb)g(ob)5 b(ject)37 b(library)f(using)g(the)g(default)h(G-\015oating)g(p)s(oin)m (t)g(option)f(for)g(double)g(v)-5 b(ariables.)0 3813 y(The)37 b(mak)m(e)p 405 3813 V 33 w(d\015oat.com)i(and)d(mak)m(e)p 1279 3813 V 34 w(ieee.com)j(\014les)f(ma)m(y)f(b)s(e)g(used)f(instead)i (to)g(build)e(the)h(library)g(with)g(the)0 3926 y(other)26 b(\015oating)i(p)s(oin)m(t)e(options.)39 b(Note)28 b(that)f(the)f (getcwd)h(function)f(that)h(is)f(used)f(in)h(the)h(group.c)f(mo)s(dule) f(ma)m(y)0 4039 y(require)44 b(that)i(programs)e(using)g(CFITSIO)f(b)s (e)h(link)m(ed)i(with)e(the)h(ALPHA$LIBRAR)-8 b(Y:V)e(AX)m(CR)i(TL.OLB) 0 4152 y(library)g(.)41 b(See)30 b(the)h(example)g(link)f(line)h(in)f (the)h(next)f(section)i(of)e(this)h(do)s(cumen)m(t.)0 4312 y(On)25 b(Windo)m(ws)h(IBM-PC)g(t)m(yp)s(e)g(platforms)f(the)h (situation)h(is)e(more)h(complicated)i(b)s(ecause)d(of)h(the)g(wide)g (v)-5 b(ariet)m(y)0 4425 y(of)43 b(F)-8 b(ortran)43 b(compilers)h(that) f(are)g(a)m(v)-5 b(ailable)45 b(and)d(b)s(ecause)h(of)g(the)g(inheren)m (t)g(complexities)i(of)d(calling)j(the)0 4538 y(CFITSIO)25 b(C)g(routines)h(from)g(F)-8 b(ortran.)40 b(Tw)m(o)26 b(di\013eren)m(t)h(v)m(ersions)f(of)g(the)h(CFITSIO)d(dll)i(library)g (are)g(a)m(v)-5 b(ailable,)0 4650 y(compiled)28 b(with)e(the)i(Borland) f(C++)f(compiler)i(and)e(the)i(Microsoft)g(Visual)g(C++)e(compiler,)i (resp)s(ectiv)m(ely)-8 b(,)30 b(in)0 4763 y(the)g(\014les)g(c\014tsio)s (dll)p 679 4763 V 33 w(2xxx)p 901 4763 V 34 w(b)s(orland.zip)f(and)g (c\014tsio)s(dll)p 1924 4763 V 33 w(3xxx)p 2146 4763 V 33 w(v)m(cc.zip,)j(where)e('3xxx')h(represen)m(ts)f(the)g(curren)m(t) 0 4876 y(release)44 b(n)m(um)m(b)s(er.)76 b(Both)43 b(these)g(dll)g (libraries)g(con)m(tain)h(a)f(set)g(of)f(F)-8 b(ortran)44 b(wrapp)s(er)d(routines)h(whic)m(h)g(ma)m(y)0 4989 y(b)s(e)37 b(compatible)i(with)e(some,)j(but)d(probably)g(not)g(all,)k(a)m(v)-5 b(ailable)40 b(F)-8 b(ortran)38 b(compilers.)63 b(T)-8 b(o)38 b(test)g(if)g(they)g(are)0 5102 y(compatible,)29 b(compile)f(the)f(program)g(testf77.f)h(and)f(try)f(linking)i(to)f (these)h(dll)e(libraries.)40 b(If)27 b(these)g(libraries)g(do)0 5215 y(not)22 b(w)m(ork)g(with)g(a)g(particular)g(F)-8 b(ortran)22 b(compiler,)j(then)c(it)i(ma)m(y)f(b)s(e)f(necessary)i(to)f (mo)s(dify)f(the)h(\014le)g("cfortran.h")0 5328 y(to)28 b(supp)s(ort)d(that)j(particular)f(com)m(bination)i(of)e(C)g(and)f(F)-8 b(ortran)28 b(compilers,)h(and)d(then)h(rebuild)f(the)h(CFITSIO)0 5441 y(dll)j(library)-8 b(.)41 b(This)30 b(will)g(require,)h(ho)m(w)m (ev)m(er,)h(some)e(exp)s(ertise)h(in)f(mixed)g(language)i(programming.) 0 5601 y(CFITSIO)f(should)g(b)s(e)g(compatible)j(with)d(most)i(curren)m (t)f(ANCI)g(C)f(and)h(C++)f(compilers:)44 b(Cra)m(y)33 b(sup)s(ercom-)0 5714 y(puters)d(are)g(curren)m(tly)h(not)f(supp)s (orted.)p eop end %%Page: 6 12 TeXDict begin 6 11 bop 0 299 a Fi(6)1896 b Fg(CHAPTER)30 b(2.)111 b(CREA)-8 b(TING)31 b(FITSIO/CFITSIO)0 555 y Fd(2.2)135 b(T)-11 b(esting)46 b(the)f(Library)0 805 y Fi(The)40 b(CFITSIO)e(library)i(should)f(b)s(e)g(tested)i(b)m(y)f (building)f(and)g(running)g(the)h(testprog.c)h(program)f(that)h(is)0 918 y(included)30 b(with)g(the)g(release.)42 b(On)30 b(Unix)g(systems)g(t)m(yp)s(e:)191 1156 y Fe(\045)47 b(make)g(testprog)191 1269 y(\045)g(testprog)f(>)h(testprog.lis)191 1382 y(\045)g(diff)g(testprog.lis)d(testprog.out)191 1495 y(\045)j(cmp)g(testprog.fit)e(testprog.std)0 1733 y Fi(On)30 b(VMS)g(systems,)g(\(assuming)h(cc)g(is)f(the)h(name)f(of)h (the)f(C)g(compiler)h(command\),)g(t)m(yp)s(e:)191 1970 y Fe($)47 b(cc)h(testprog.c)191 2083 y($)f(link)g(testprog,)e (cfitsio/lib,)g(alpha$library:vaxcrtl/l)o(ib)191 2196 y($)i(run)g(testprog)0 2434 y Fi(The)30 b(testprog)h(program)g(should)e (pro)s(duce)g(a)i(FITS)f(\014le)g(called)i(`testprog.\014t')g(that)f (is)f(iden)m(tical)j(to)e(the)f(`test-)0 2547 y(prog.std')25 b(FITS)f(\014le)g(included)g(with)g(this)h(release.)40 b(The)24 b(diagnostic)i(messages)g(\(whic)m(h)e(w)m(ere)h(pip)s(ed)f (to)h(the)g(\014le)0 2660 y(testprog.lis)h(in)e(the)h(Unix)f(example\)) i(should)d(b)s(e)h(iden)m(tical)j(to)e(the)g(listing)g(con)m(tained)h (in)e(the)h(\014le)f(testprog.out.)0 2773 y(The)30 b('di\013)7 b(')31 b(and)e('cmp')i(commands)f(sho)m(wn)g(ab)s(o)m(v)m(e)h(should)f (not)g(rep)s(ort)g(an)m(y)h(di\013erences)g(in)f(the)g(\014les.)41 b(\(There)0 2886 y(ma)m(y)35 b(b)s(e)e(some)h(minor)g(formatting)g (di\013erences,)i(suc)m(h)d(as)i(the)f(presence)g(or)g(absence)g(of)g (leading)h(zeros,)h(or)e(3)0 2999 y(digit)d(exp)s(onen)m(ts)f(in)g(n)m (um)m(b)s(ers,)g(whic)m(h)g(can)g(b)s(e)g(ignored\).)0 3159 y(The)f(F)-8 b(ortran)31 b(wrapp)s(ers)d(in)h(CFITSIO)f(ma)m(y)j (b)s(e)e(tested)h(with)g(the)g(testf77)h(program.)40 b(On)29 b(Unix)h(systems)g(the)0 3272 y(fortran)g(compilation)i(and)e (link)g(command)g(ma)m(y)h(b)s(e)f(called)h('f77')h(or)e('g77',)j(dep)s (ending)c(on)h(the)g(system.)143 3509 y Fe(\045)48 b(f77)f(-o)g (testf77)f(testf77.f)f(-L.)i(-lcfitsio)e(-lnsl)h(-lsocket)48 3622 y(or)143 3735 y(\045)i(f77)f(-f)g(-o)g(testf77)f(testf77.f)f(-L.)i (-lcfitsio)188 b(\(under)46 b(SUN)h(O/S\))48 3848 y(or)143 3961 y(\045)h(f77)f(-o)g(testf77)f(testf77.f)f(-Wl,-L.)h(-lcfitsio)f (-lm)i(-lnsl)f(-lsocket)g(\(HP/UX\))48 4074 y(or)143 4187 y(\045)i(g77)f(-o)g(testf77)f(-s)h(testf77.f)e(-lcfitsio)g (-lcc_dynamic)g(-lncurses)g(\(Mac)i(OS-X\))143 4413 y(\045)h(testf77)d (>)j(testf77.lis)143 4526 y(\045)g(diff)e(testf77.lis)f(testf77.out)143 4638 y(\045)j(cmp)f(testf77.fit)d(testf77.std)0 4876 y Fi(On)31 b(mac)m(hines)h(running)f(SUN)g(O/S,)h(F)-8 b(ortran)33 b(programs)e(m)m(ust)h(b)s(e)f(compiled)h(with)g(the)g('-f) 7 b(')32 b(option)h(to)f(force)0 4989 y(double)24 b(precision)g(v)-5 b(ariables)25 b(to)g(b)s(e)e(aligned)i(on)f(8-b)m(yte)i(b)s(oundaries)c (to)j(mak)m(e)g(the)g(fortran-declared)f(v)-5 b(ariables)0 5102 y(compatible)34 b(with)e(C.)g(A)h(similar)g(compiler)g(option)g (ma)m(y)g(b)s(e)f(required)g(on)g(other)h(platforms.)48 b(F)-8 b(ailing)34 b(to)f(use)0 5215 y(this)26 b(option)g(ma)m(y)g (cause)h(the)f(program)f(to)i(crash)e(on)h(FITSIO)f(routines)g(that)i (read)f(or)f(write)h(double)g(precision)0 5328 y(v)-5 b(ariables.)0 5488 y(On)27 b(Windo)m(ws)h(platforms,)g(linking)g(F)-8 b(ortran)28 b(programs)f(with)h(a)g(C)f(library)g(often)h(dep)s(ends)e (on)i(the)g(particular)0 5601 y(compilers)40 b(in)m(v)m(olv)m(ed.)71 b(Some)40 b(users)f(ha)m(v)m(e)i(found)d(the)i(follo)m(wing)i(commands) d(w)m(ork)h(when)f(using)g(the)h(In)m(tel)0 5714 y(F)-8 b(ortran)31 b(compiler:)p eop end %%Page: 7 13 TeXDict begin 7 12 bop 0 299 a Fg(2.3.)72 b(LINKING)30 b(PR)m(OGRAMS)h(WITH)f(FITSIO)2041 b Fi(7)0 555 y Fe(ifort)46 b(/libs.dll)g(cfitsio.lib)e(/MD)j(testf77.f)f(/Gm)0 781 y(or)h(possibly,)0 1007 y(ifort)f(/libs:dll)g(cfitsio.lib)e(/MD)j(/fpp) g(/extfpp:cfortran.h,fitsi)o(o.h)191 1120 y(/iface:cvf)e(testf77.f)0 1335 y Fi(Also)32 b(note)h(that)f(on)g(some)g(systems)f(the)h(output)g (listing)g(of)g(the)g(testf77)h(program)f(ma)m(y)g(di\013er)f(sligh)m (tly)i(from)0 1448 y(the)f(testf77.std)i(template)g(if)e(leading)h (zeros)g(are)g(not)g(prin)m(ted)e(b)m(y)i(default)f(b)s(efore)g(the)g (decimal)i(p)s(oin)m(t)e(when)0 1561 y(using)e(F)h(format.)0 1721 y(A)f(few)h(other)f(utilit)m(y)i(programs)e(are)h(included)e(with) h(CFITSIO:)191 1937 y Fe(speed)46 b(-)i(measures)d(the)i(maximum)f (throughput)f(\(in)i(MB)g(per)g(second\))668 2050 y(for)g(writing)f (and)h(reading)f(FITS)g(files)h(with)f(CFITSIO)191 2275 y(listhead)f(-)j(lists)e(all)h(the)g(header)f(keywords)g(in)h(any)g (FITS)f(file)191 2501 y(fitscopy)f(-)j(copies)e(any)h(FITS)g(file)f (\(especially)f(useful)h(in)h(conjunction)811 2614 y(with)g(the)g (CFITSIO's)e(extended)h(input)g(filename)g(syntax\))191 2840 y(cookbook)f(-)j(a)f(sample)f(program)g(that)h(performs)e(common)i (read)f(and)811 2953 y(write)h(operations)e(on)i(a)g(FITS)g(file.)191 3179 y(iter_a,)f(iter_b,)g(iter_c)g(-)h(examples)f(of)h(the)g(CFITSIO)f (iterator)f(routine)0 3394 y Fi(The)30 b(\014rst)f(4)i(of)g(these)g (utilit)m(y)g(programs)f(can)h(b)s(e)f(compiled)h(and)e(link)m(ed)i(b)m (y)f(t)m(yping)143 3610 y Fe(\045)95 b(make)47 b(program_name)0 3936 y Fd(2.3)135 b(Linking)45 b(Programs)h(with)f(FITSIO)0 4186 y Fi(When)31 b(linking)g(applications)i(soft)m(w)m(are)f(with)f (the)g(FITSIO)f(library)-8 b(,)32 b(sev)m(eral)h(system)e(libraries)g (usually)g(need)0 4299 y(to)26 b(b)s(e)f(sp)s(eci\014ed)g(on)g(the)h (link)g(comman)f(Unix)h(systems,)h(the)e(most)h(reliable)h(w)m(a)m(y)f (to)h(determine)e(what)h(libraries)0 4412 y(are)32 b(required)f(is)g (to)i(t)m(yp)s(e)e('mak)m(e)i(testprog')g(and)e(see)h(what)f(libraries) h(the)g(con\014gure)f(script)h(has)f(added.)43 b(The)0 4525 y(t)m(ypical)25 b(libraries)f(that)g(ma)m(y)g(need)f(to)h(b)s(e)f (added)g(are)g(-lm)h(\(the)g(math)f(library\))h(and)f(-lnsl)g(and)g (-lso)s(c)m(k)m(et)j(\(needed)0 4638 y(only)h(for)f(FTP)g(and)g(HTTP)g (\014le)h(access\).)41 b(These)26 b(latter)i(2)f(libraries)g(are)g(not) g(needed)f(on)g(VMS)h(and)f(Windo)m(ws)0 4751 y(platforms,)31 b(b)s(ecause)f(FTP)g(\014le)h(access)g(is)g(not)f(curren)m(tly)h(supp)s (orted)d(on)i(those)h(platforms.)0 4911 y(Note)i(that)g(when)e (upgrading)g(to)i(a)f(new)m(er)g(v)m(ersion)g(of)g(CFITSIO)f(it)h(is)g (usually)g(necessary)g(to)h(recompile,)h(as)0 5024 y(w)m(ell)d(as)g (relink,)g(the)f(programs)g(that)h(use)f(CFITSIO,)f(b)s(ecause)i(the)f (de\014nitions)g(in)g(\014tsio.h)h(often)f(c)m(hange.)0 5351 y Fd(2.4)135 b(Getting)46 b(Started)g(with)f(FITSIO)0 5601 y Fi(In)32 b(order)h(to)h(e\013ectiv)m(ely)i(use)d(the)g(FITSIO)f (library)h(as)h(quic)m(kly)g(as)f(p)s(ossible,)h(it)g(is)f(recommended) g(that)g(new)0 5714 y(users)d(follo)m(w)h(these)g(steps:)p eop end %%Page: 8 14 TeXDict begin 8 13 bop 0 299 a Fi(8)1896 b Fg(CHAPTER)30 b(2.)111 b(CREA)-8 b(TING)31 b(FITSIO/CFITSIO)0 555 y Fi(1.)62 b(Read)38 b(the)f(follo)m(wing)i(`FITS)e(Primer')g(c)m(hapter) h(for)g(a)f(brief)g(o)m(v)m(erview)i(of)f(the)g(structure)e(of)i(FITS)f (\014les.)0 668 y(This)25 b(is)h(esp)s(ecially)h(imp)s(ortan)m(t)g(for) e(users)h(who)f(ha)m(v)m(e)i(not)g(previously)e(dealt)i(with)f(the)g (FITS)f(table)i(and)f(image)0 781 y(extensions.)0 941 y(2.)41 b(W)-8 b(rite)32 b(a)f(simple)f(program)g(to)h(read)g(or)f (write)g(a)h(FITS)f(\014le)g(using)g(the)h(Basic)g(In)m(terface)h (routines.)0 1101 y(3.)41 b(Refer)28 b(to)i(the)f(co)s(okb)s(o)s(ok.f)g (program)f(that)i(is)f(included)f(with)g(this)h(release)h(for)e (examples)i(of)f(routines)f(that)0 1214 y(p)s(erform)h(v)-5 b(arious)30 b(common)h(FITS)f(\014le)g(op)s(erations.)0 1374 y(4.)52 b(Read)34 b(Chapters)g(4)g(and)f(5)i(to)g(b)s(ecome)f (familiar)h(with)e(the)i(con)m(v)m(en)m(tions)h(and)d(adv)-5 b(anced)34 b(features)h(of)f(the)0 1487 y(FITSIO)29 b(in)m(terface.)0 1647 y(5.)47 b(Scan)32 b(through)f(the)h(more)h(extensiv)m(e)g(set)g (of)g(routines)f(that)g(are)h(pro)m(vided)f(in)g(the)g(`Adv)-5 b(anced)32 b(In)m(terface'.)0 1760 y(These)22 b(routines)f(p)s(erform)g (more)h(sp)s(ecialized)h(functions)e(than)g(are)i(pro)m(vided)e(b)m(y)h (the)g(Basic)h(In)m(terface)g(routines.)0 2124 y Fd(2.5)135 b(Example)46 b(Program)0 2380 y Fi(The)32 b(follo)m(wing)i(listing)f (sho)m(ws)f(an)g(example)i(of)e(ho)m(w)h(to)g(use)f(the)g(FITSIO)g (routines)g(in)g(a)h(F)-8 b(ortran)33 b(program.)0 2493 y(Refer)38 b(to)h(the)g(co)s(okb)s(o)s(ok.f)f(program)g(that)h(is)f (included)f(with)h(the)h(FITSIO)e(distribution)g(for)h(examples)h(of)0 2606 y(other)31 b(FITS)e(programs.)286 2891 y Fe(program)46 b(writeimage)0 3117 y(C)238 b(Create)46 b(a)i(FITS)f(primary)e(array)i (containing)e(a)i(2-D)g(image)286 3343 y(integer)f (status,unit,blocksize,bit)o(pix,)o(nax)o(is,n)o(axes)o(\(2\))286 3456 y(integer)g(i,j,group,fpixel,nelement)o(s,ar)o(ray)o(\(300)o(,200) o(\))286 3569 y(character)g(filename*80)286 3681 y(logical)g (simple,extend)286 3907 y(status=0)0 4020 y(C)238 b(Name)47 b(of)g(the)g(FITS)g(file)f(to)i(be)f(created:)286 4133 y(filename='ATESTFILE.FITS')0 4359 y(C)238 b(Get)47 b(an)g(unused)g (Logical)e(Unit)i(Number)f(to)h(use)g(to)g(create)f(the)h(FITS)g(file) 286 4472 y(call)g(ftgiou\(unit,status\))0 4698 y(C)238 b(create)46 b(the)h(new)g(empty)g(FITS)f(file)286 4811 y(blocksize=1)286 4924 y(call)h(ftinit\(unit,filename,blo)o(cksi)o (ze,s)o(tat)o(us\))0 5149 y(C)238 b(initialize)45 b(parameters)g(about) i(the)g(FITS)f(image)h(\(300)f(x)i(200)f(16-bit)f(integers\))286 5262 y(simple=.true.)286 5375 y(bitpix=16)286 5488 y(naxis=2)286 5601 y(naxes\(1\)=300)286 5714 y(naxes\(2\)=200)p eop end %%Page: 9 15 TeXDict begin 9 14 bop 0 299 a Fg(2.6.)72 b(LEGAL)30 b(STUFF)2995 b Fi(9)286 555 y Fe(extend=.true.)0 781 y(C)238 b(write)47 b(the)g(required)e(header)h(keywords)286 894 y(call)h(ftphpr\(unit,simple,bitpi)o(x,na)o(xis,)o(nax)o(es,0)o (,1,e)o(xte)o(nd,s)o(tatu)o(s\))0 1120 y(C)238 b(initialize)45 b(the)i(values)f(in)i(the)e(image)h(with)f(a)i(linear)e(ramp)h (function)286 1233 y(do)h(j=1,naxes\(2\))477 1346 y(do)f (i=1,naxes\(1\))668 1458 y(array\(i,j\)=i+j)477 1571 y(end)g(do)286 1684 y(end)g(do)0 1910 y(C)238 b(write)47 b(the)g(array)f(to)h(the)g(FITS)g(file)286 2023 y(group=1)286 2136 y(fpixel=1)286 2249 y(nelements=naxes\(1\)*naxes\(2)o(\))286 2362 y(call)g(ftpprj\(unit,group,fpixel)o(,nel)o(emen)o(ts,)o(arra)o (y,st)o(atu)o(s\))0 2588 y(C)238 b(write)47 b(another)f(optional)f (keyword)h(to)h(the)g(header)286 2700 y(call)g (ftpkyj\(unit,'EXPOSURE',1)o(500,)o('Tot)o(al)41 b(Exposure)46 b(Time',status\))0 2926 y(C)238 b(close)47 b(the)g(file)f(and)h(free)g (the)g(unit)f(number)286 3039 y(call)h(ftclos\(unit,)d(status\))286 3152 y(call)j(ftfiou\(unit,)d(status\))286 3265 y(end)0 3623 y Fd(2.6)135 b(Legal)46 b(Stu\013)0 3878 y Fi(Cop)m(yrigh)m(t)37 b(\(Unpublished{all)g(righ)m(ts)g(reserv)m(ed)g(under)e(the)i(cop)m (yrigh)m(t)h(la)m(ws)f(of)g(the)g(United)g(States\),)j(U.S.)0 3991 y(Go)m(v)m(ernmen)m(t)30 b(as)g(represen)m(ted)e(b)m(y)h(the)g (Administrator)g(of)g(the)g(National)h(Aeronautics)g(and)e(Space)h (Adminis-)0 4104 y(tration.)42 b(No)31 b(cop)m(yrigh)m(t)g(is)g (claimed)g(in)f(the)h(United)f(States)h(under)e(Title)j(17,)f(U.S.)f (Co)s(de.)0 4264 y(P)m(ermission)g(to)g(freely)f(use,)h(cop)m(y)-8 b(,)31 b(mo)s(dify)-8 b(,)29 b(and)g(distribute)g(this)g(soft)m(w)m (are)i(and)e(its)h(do)s(cumen)m(tation)g(without)0 4377 y(fee)f(is)f(hereb)m(y)g(gran)m(ted,)i(pro)m(vided)e(that)h(this)f(cop) m(yrigh)m(t)i(notice)f(and)f(disclaimer)h(of)f(w)m(arran)m(t)m(y)i(app) s(ears)d(in)h(all)0 4490 y(copies.)0 4650 y(DISCLAIMER:)0 4811 y(THE)33 b(SOFTW)-10 b(ARE)32 b(IS)g(PR)m(O)m(VIDED)i('AS)f(IS')g (WITHOUT)f(ANY)i(W)-10 b(ARRANTY)33 b(OF)g(ANY)h(KIND,)f(EI-)0 4924 y(THER)42 b(EXPRESSED,)f(IMPLIED,)i(OR)e(ST)-8 b(A)g(TUTOR)g(Y,)43 b(INCLUDING,)f(BUT)h(NOT)e(LIMITED)h(TO,)0 5036 y(ANY)33 b(W)-10 b(ARRANTY)33 b(THA)-8 b(T)32 b(THE)g(SOFTW)-10 b(ARE)32 b(WILL)g(CONF)m(ORM)g(TO)g(SPECIFICA)-8 b(TIONS,)30 b(ANY)0 5149 y(IMPLIED)38 b(W)-10 b(ARRANTIES)37 b(OF)h(MER)m(CHANT)-8 b(ABILITY,)38 b(FITNESS)f(F)m(OR)h(A)g(P)-8 b(AR)g(TICULAR)38 b(PUR-)0 5262 y(POSE,)24 b(AND)i(FREEDOM)f(FR)m(OM)h(INFRINGEMENT,)g (AND)f(ANY)h(W)-10 b(ARRANTY)25 b(THA)-8 b(T)25 b(THE)g(DOC-)0 5375 y(UMENT)-8 b(A)g(TION)31 b(WILL)f(CONF)m(ORM)h(TO)e(THE)h(SOFTW) -10 b(ARE,)30 b(OR)g(ANY)h(W)-10 b(ARRANTY)31 b(THA)-8 b(T)30 b(THE)0 5488 y(SOFTW)-10 b(ARE)31 b(WILL)h(BE)g(ERR)m(OR)g (FREE.)g(IN)g(NO)g(EVENT)f(SHALL)g(NASA)h(BE)g(LIABLE)g(F)m(OR)g(ANY)0 5601 y(D)m(AMA)m(GES,)26 b(INCLUDING,)e(BUT)f(NOT)g(LIMITED)h(TO,)f (DIRECT,)g(INDIRECT,)g(SPECIAL)f(OR)h(CON-)0 5714 y(SEQUENTIAL)28 b(D)m(AMA)m(GES,)k(ARISING)d(OUT)g(OF,)h(RESUL)-8 b(TING)29 b(FR)m(OM,)h(OR)f(IN)h(ANY)g(W)-10 b(A)i(Y)30 b(CON-)p eop end %%Page: 10 16 TeXDict begin 10 15 bop 0 299 a Fi(10)1851 b Fg(CHAPTER)30 b(2.)111 b(CREA)-8 b(TING)31 b(FITSIO/CFITSIO)0 555 y Fi(NECTED)25 b(WITH)g(THIS)f(SOFTW)-10 b(ARE,)25 b(WHETHER)g(OR)g(NOT)g (BASED)g(UPON)g(W)-10 b(ARRANTY,)26 b(CON-)0 668 y(TRA)m(CT,)d(TOR)-8 b(T)23 b(,)g(OR)g(OTHER)-10 b(WISE,)22 b(WHETHER)i(OR)f(NOT)f(INJUR)-8 b(Y)24 b(W)-10 b(AS)23 b(SUST)-8 b(AINED)23 b(BY)h(PER-)0 781 y(SONS)h(OR)i(PR)m(OPER)-8 b(TY)26 b(OR)g(OTHER)-10 b(WISE,)26 b(AND)h(WHETHER)g(OR)f(NOT)g(LOSS)f(W)-10 b(AS)26 b(SUST)-8 b(AINED)0 894 y(FR)m(OM,)37 b(OR)e(AR)m(OSE)h(OUT)f (OF)h(THE)g(RESUL)-8 b(TS)35 b(OF,)h(OR)f(USE)h(OF,)g(THE)g(SOFTW)-10 b(ARE)35 b(OR)g(SER-)0 1007 y(VICES)29 b(PR)m(O)m(VIDED)j(HEREUNDER.")0 1451 y Fd(2.7)135 b(Ac)l(kno)l(wledgmen)l(ts)0 1723 y Fi(The)29 b(dev)m(elopmen)m(t)h(of)g(man)m(y)f(of)h(the)f(p)s(o)m(w)m (erful)g(features)g(in)g(CFITSIO)f(w)m(as)i(made)f(p)s(ossible)g (through)f(collab-)0 1836 y(orations)35 b(with)f(man)m(y)h(p)s(eople)f (or)h(organizations)h(from)e(around)f(the)i(w)m(orld.)52 b(The)34 b(follo)m(wing,)j(in)d(particular,)0 1949 y(ha)m(v)m(e)e(made) e(esp)s(ecially)i(signi\014can)m(t)f(con)m(tributions:)0 2109 y(Programmers)25 b(from)h(the)f(In)m(tegral)i(Science)g(Data)g (Cen)m(ter,)g(Switzerland)f(\(namely)-8 b(,)28 b(Jurek)c(Bork)m(o)m (wski,)29 b(Bruce)0 2222 y(O'Neel,)34 b(and)e(Don)h(Jennings\),)f (designed)g(the)h(concept)g(for)f(the)h(plug-in)f(I/O)g(driv)m(ers)g (that)h(w)m(as)g(in)m(tro)s(duced)0 2335 y(with)i(CFITSIO)e(2.0.)56 b(The)34 b(use)h(of)g(`driv)m(ers')g(greatly)h(simpli\014ed)f(the)g(lo) m(w-lev)m(el)j(I/O,)d(whic)m(h)f(in)h(turn)f(made)0 2448 y(other)40 b(new)f(features)i(in)e(CFITSIO)f(\(e.g.,)45 b(supp)s(ort)38 b(for)h(compressed)h(FITS)f(\014les)h(and)f(supp)s(ort) f(for)i(IRAF)0 2560 y(format)32 b(image)g(\014les\))g(m)m(uc)m(h)f (easier)i(to)f(implemen)m(t.)44 b(Jurek)31 b(Bork)m(o)m(wski)h(wrote)g (the)g(Shared)e(Memory)i(driv)m(er,)0 2673 y(and)23 b(Bruce)i(O'Neel)g (wrote)f(the)g(driv)m(ers)g(for)f(accessing)j(FITS)d(\014les)h(o)m(v)m (er)h(the)f(net)m(w)m(ork)h(using)e(the)i(FTP)-8 b(,)24 b(HTTP)-8 b(,)0 2786 y(and)30 b(R)m(OOT)g(proto)s(cols.)0 2946 y(The)45 b(ISDC)g(also)h(pro)m(vided)f(the)h(template)h(parsing)e (routines)g(\(written)h(b)m(y)f(Jurek)g(Bork)m(o)m(wski\))i(and)e(the)0 3059 y(hierarc)m(hical)39 b(grouping)d(routines)h(\(written)h(b)m(y)f (Don)h(Jennings\).)60 b(The)37 b(ISDC)f(D)m(AL)i(\(Data)h(Access)f(La)m (y)m(er\))0 3172 y(routines)30 b(are)h(la)m(y)m(ered)h(on)e(top)h(of)f (CFITSIO)f(and)h(mak)m(e)h(extensiv)m(e)h(use)e(of)h(these)g(features.) 0 3332 y(Uw)m(e)25 b(Lammers)e(\(XMM/ESA/ESTEC,)h(The)g(Netherlands\))g (designed)g(the)g(high-p)s(erformance)f(lexical)j(pars-)0 3445 y(ing)42 b(algorithm)h(that)f(is)g(used)f(to)i(do)e(on-the-\015y)h (\014ltering)g(of)g(FITS)f(tables.)76 b(This)41 b(algorithm)i(essen)m (tially)0 3558 y(pre-compiles)36 b(the)g(user-supplied)e(selection)k (expression)d(in)m(to)i(a)f(form)g(that)g(can)g(b)s(e)f(rapidly)g(ev)-5 b(aluated)37 b(for)0 3671 y(eac)m(h)31 b(ro)m(w.)40 b(P)m(eter)31 b(Wilson)f(\(RSTX,)f(NASA/GSF)m(C\))i(then)e(wrote)h(the)g(parsing)f (routines)g(used)g(b)m(y)g(CFITSIO)0 3784 y(based)i(on)f(Lammers')h (design,)g(com)m(bined)g(with)g(other)g(tec)m(hniques)g(suc)m(h)g(as)g (the)g(CFITSIO)f(iterator)i(routine)0 3897 y(to)g(further)e(enhance)h (the)h(data)g(pro)s(cessing)f(throughput.)42 b(This)31 b(e\013ort)h(also)g(b)s(ene\014ted)e(from)h(a)h(m)m(uc)m(h)f(earlier)0 4010 y(lexical)25 b(parsing)f(routine)f(that)h(w)m(as)g(dev)m(elop)s (ed)g(b)m(y)g(Ken)m(t)g(Blac)m(kburn)f(\(NASA/GSF)m(C\).)i(More)g (recen)m(tly)-8 b(,)27 b(Craig)0 4123 y(Markw)m(ardt)i(\(NASA/GSF)m (C\))g(implemen)m(ted)g(additional)g(functions)f(\(median,)h(a)m(v)m (erage,)j(stddev\))c(and)g(other)0 4236 y(enhancemen)m(ts)j(to)g(the)g (lexical)h(parser.)0 4396 y(The)40 b(CFITSIO)g(iterator)i(function)e (is)h(lo)s(osely)h(based)f(on)f(similar)i(ideas)f(dev)m(elop)s(ed)g (for)g(the)g(XMM)g(Data)0 4509 y(Access)31 b(La)m(y)m(er.)0 4669 y(P)m(eter)25 b(Wilson)g(\(RSTX,)f(NASA/GSF)m(C\))h(wrote)g(the)f (complete)i(set)e(of)h(F)-8 b(ortran-callable)27 b(wrapp)s(ers)22 b(for)i(all)h(the)0 4782 y(CFITSIO)k(routines,)h(whic)m(h)g(in)g(turn)g (rely)g(on)h(the)f(CF)m(OR)-8 b(TRAN)31 b(macro)g(dev)m(elop)s(ed)g(b)m (y)f(Burkhard)f(Buro)m(w.)0 4942 y(The)h(syn)m(tax)i(used)e(b)m(y)h (CFITSIO)f(for)g(\014ltering)i(or)f(binning)e(input)h(FITS)h(\014les)g (is)g(based)f(on)h(ideas)h(dev)m(elop)s(ed)0 5055 y(for)41 b(the)g(AXAF)h(Science)g(Cen)m(ter)g(Data)h(Mo)s(del)e(b)m(y)g (Jonathan)g(McDo)m(w)m(ell,)47 b(An)m(tonella)c(F)-8 b(ruscione,)45 b(Aneta)0 5168 y(Siemigino)m(wsk)-5 b(a)27 b(and)e(Bill)i(Jo)m(y)m(e.)41 b(See)26 b(h)m (ttp://heasarc.gsfc.nasa.go)m(v/do)s(cs/journal/axa)q(f7.h)m(t)q(ml)32 b(for)25 b(further)0 5281 y(description)30 b(of)h(the)g(AXAF)g(Data)h (Mo)s(del.)0 5441 y(The)j(\014le)g(decompression)g(co)s(de)g(w)m(ere)h (tak)m(en)g(directly)g(from)e(the)i(gzip)f(\(GNU)h(zip\))g(program)f (dev)m(elop)s(ed)g(b)m(y)0 5554 y(Jean-loup)30 b(Gailly)i(and)e (others.)0 5714 y(Doug)h(Mink,)g(SA)m(O,)f(pro)m(vided)g(the)h (routines)f(for)g(con)m(v)m(erting)i(IRAF)f(format)g(images)g(in)m(to)g (FITS)f(format.)p eop end %%Page: 11 17 TeXDict begin 11 16 bop 0 299 a Fg(2.7.)72 b(A)m(CKNO)m(WLEDGMENTS)2577 b Fi(11)0 555 y(Martin)33 b(Reinec)m(k)m(e)i(\(Max)f(Planc)m(k)f (Institute,)h(Garc)m(hing\)\))g(pro)m(vided)f(the)g(mo)s(di\014cations) f(to)i(cfortran.h)e(that)0 668 y(are)d(necessary)h(to)f(supp)s(ort)e (64-bit)k(in)m(teger)f(v)-5 b(alues)29 b(when)f(calling)i(C)f(routines) g(from)f(fortran)h(programs.)39 b(The)0 781 y(cfortran.h)30 b(macros)h(w)m(ere)g(originally)h(dev)m(elop)s(ed)e(b)m(y)h(Burkhard)e (Buro)m(w)h(\(CERN\).)0 941 y(Julian)f(T)-8 b(a)m(ylor)31 b(\(ESO,)e(Garc)m(hing\))i(pro)m(vided)e(the)g(fast)h(b)m(yte-sw)m (apping)g(algorithms)h(that)f(use)f(the)h(SSE2)f(and)0 1054 y(SSSE3)g(mac)m(hine)i(instructions)f(a)m(v)-5 b(ailable)33 b(on)d(x86)p 1784 1054 28 4 v 34 w(64)h(CPUs.)0 1214 y(In)c(addition,)i(man)m(y)f(other)g(p)s(eople)g(ha)m(v)m(e)h(made)f(v) -5 b(aluable)29 b(con)m(tributions)f(to)h(the)f(dev)m(elopmen)m(t)h(of) f(CFITSIO.)0 1327 y(These)i(include)g(\(with)h(ap)s(ologies)h(to)f (others)f(that)h(ma)m(y)g(ha)m(v)m(e)h(inadv)m(erten)m(tly)g(b)s(een)d (omitted\):)0 1487 y(Stev)m(e)g(Allen,)g(Carl)f(Ak)m(erlof,)h(Keith)f (Arnaud,)g(Morten)g(Krabb)s(e)e(Barfo)s(ed,)j(Ken)m(t)f(Blac)m(kburn,)h (G)f(Bo)s(dammer,)0 1600 y(Romk)m(e)h(Bon)m(tek)m(o)s(e,)i(Lucio)d (Chiapp)s(etti,)g(Keith)g(Costorf,)g(Robin)g(Corb)s(et,)g(John)e(Da)m (vis,)k(Ric)m(hard)e(Fink,)h(Ning)0 1713 y(Gan,)g(Emily)e(Greene,)i(Jo) s(e)f(Harrington,)h(Cheng)e(Ho,)i(Phil)e(Ho)s(dge,)i(Jim)f(Ingham,)g(Y) -8 b(oshitak)j(a)29 b(Ishisaki,)f(Diab)0 1826 y(Jerius,)j(Mark)h (Levine,)g(T)-8 b(o)s(dd)30 b(Karak)-5 b(askian,)32 b(Edw)m(ard)f (King,)g(Scott)i(Ko)s(c)m(h,)e(Claire)h(Larkin,)f(Rob)h(Managan,)0 1939 y(Eric)38 b(Mandel,)i(John)d(Matto)m(x,)43 b(Carsten)37 b(Mey)m(er,)42 b(Emi)37 b(Miy)m(ata,)43 b(Stefan)38 b(Mo)s(c)m(hnac)m (ki,)j(Mik)m(e)f(Noble,)g(Oliv)m(er)0 2052 y(Ob)s(erdorf,)c(Cliv)m(e)i (P)m(age,)i(Arvind)35 b(P)m(armar,)j(Je\013)f(P)m(edelt)m(y)-8 b(,)40 b(Tim)c(P)m(earson,)j(Maren)e(Purv)m(es,)h(Scott)f(Randall,)0 2165 y(Chris)d(Rogers,)j(Arnold)e(Rots,)i(Barry)f(Sc)m(hlesinger,)h (Robin)e(Stebbins,)g(Andrew)f(Szymk)m(o)m(wiak,)k(Allyn)e(T)-8 b(en-)0 2278 y(nan)m(t,)31 b(P)m(eter)g(T)-8 b(eub)s(en,)30 b(James)g(Theiler,)h(Doug)g(T)-8 b(o)s(dy)g(,)31 b(Shiro)e(Ueno,)j (Stev)m(e)f(W)-8 b(alton,)33 b(Arc)m(hie)e(W)-8 b(arno)s(c)m(k,)32 b(Alan)0 2391 y(W)-8 b(atson,)32 b(Dan)f(Whipple,)f(Wim)h(Wimmers,)g(P) m(eter)g(Y)-8 b(oung,)31 b(Jianjun)e(Xu,)h(and)g(Nelson)h(Zarate.)p eop end %%Page: 12 18 TeXDict begin 12 17 bop 0 299 a Fi(12)1851 b Fg(CHAPTER)30 b(2.)111 b(CREA)-8 b(TING)31 b(FITSIO/CFITSIO)p eop end %%Page: 13 19 TeXDict begin 13 18 bop 0 1225 a Ff(Chapter)65 b(3)0 1687 y Fl(A)78 b(FITS)f(Primer)0 2180 y Fi(This)23 b(section)j(giv)m (es)f(a)g(brief)e(o)m(v)m(erview)j(of)e(the)h(structure)e(of)i(FITS)e (\014les.)38 b(Users)24 b(should)g(refer)f(to)i(the)g(do)s(cumen-)0 2293 y(tation)33 b(a)m(v)-5 b(ailable)33 b(from)e(the)g(FITS)g(Supp)s (ort)e(O\016ce,)j(as)f(describ)s(ed)f(in)h(the)h(in)m(tro)s(duction,)f (for)g(more)h(detailed)0 2406 y(information)f(on)f(FITS)g(formats.)0 2566 y(FITS)37 b(w)m(as)g(\014rst)g(dev)m(elop)s(ed)h(in)f(the)g(late)i (1970's)g(as)f(a)f(standard)g(data)h(in)m(terc)m(hange)h(format)f(b)s (et)m(w)m(een)g(v)-5 b(ar-)0 2679 y(ious)38 b(astronomical)h(observ)-5 b(atories.)64 b(Since)37 b(then)g(FITS)g(has)h(b)s(ecome)g(the)g (defacto)g(standard)f(data)i(format)0 2791 y(supp)s(orted)29 b(b)m(y)h(most)h(astronomical)h(data)f(analysis)g(soft)m(w)m(are)g(pac) m(k)-5 b(ages.)0 2952 y(A)34 b(FITS)f(\014le)g(consists)h(of)g(one)g (or)g(more)g(Header)g(+)f(Data)i(Units)f(\(HDUs\),)i(where)d(the)h (\014rst)f(HDU)h(is)g(called)0 3065 y(the)j(`Primary)f(HDU',)i(or)f (`Primary)f(Arra)m(y'.)60 b(The)36 b(primary)g(arra)m(y)h(con)m(tains)h (an)e(N-dimensional)i(arra)m(y)f(of)0 3177 y(pixels,)32 b(suc)m(h)g(as)f(a)h(1-D)h(sp)s(ectrum,)e(a)h(2-D)h(image,)g(or)f(a)g (3-D)g(data)h(cub)s(e.)43 b(Six)31 b(di\013eren)m(t)h(primary)f(datat)m (yp)s(es)0 3290 y(are)g(supp)s(orted:)39 b(Unsigned)30 b(8-bit)h(b)m(ytes,)g(16,)g(32,)h(and)e(64-bit)h(signed)g(in)m(tegers,) h(and)d(32)j(and)d(64-bit)j(\015oating)0 3403 y(p)s(oin)m(t)d(reals.)41 b(FITS)29 b(also)i(has)e(a)h(con)m(v)m(en)m(tion)h(for)e(storing)h (unsigned)f(in)m(tegers)h(\(see)h(the)e(later)i(section)f(en)m(titled)0 3516 y(`Unsigned)h(In)m(tegers')h(for)f(more)g(details\).)43 b(The)31 b(primary)f(HDU)i(ma)m(y)f(also)h(consist)g(of)f(only)g(a)g (header)g(with)g(a)0 3629 y(n)m(ull)f(arra)m(y)h(con)m(taining)h(no)e (data)h(pixels.)0 3789 y(An)m(y)i(n)m(um)m(b)s(er)e(of)h(additional)i (HDUs)f(ma)m(y)g(follo)m(w)h(the)e(primary)g(arra)m(y;)i(these)f (additional)h(HDUs)f(are)g(called)0 3902 y(FITS)d(`extensions'.)41 b(There)30 b(are)h(curren)m(tly)f(3)h(t)m(yp)s(es)g(of)f(extensions)h (de\014ned)e(b)m(y)h(the)h(FITS)f(standard:)136 4171 y Fc(\017)46 b Fi(Image)31 b(Extension)g(-)g(a)f(N-dimensional)h(arra)m (y)g(of)g(pixels,)g(lik)m(e)g(in)f(a)h(primary)e(arra)m(y)136 4368 y Fc(\017)46 b Fi(ASCI)s(I)29 b(T)-8 b(able)31 b(Extension)g(-)f (ro)m(ws)h(and)e(columns)h(of)h(data)g(in)f(ASCI)s(I)f(c)m(haracter)j (format)136 4564 y Fc(\017)46 b Fi(Binary)31 b(T)-8 b(able)31 b(Extension)f(-)h(ro)m(ws)f(and)g(columns)g(of)h(data)g(in)f(binary)f (represen)m(tation)0 4833 y(In)k(eac)m(h)i(case)g(the)f(HDU)h(consists) g(of)f(an)g(ASCI)s(I)e(Header)i(Unit)h(follo)m(w)m(ed)g(b)m(y)f(an)g (optional)h(Data)g(Unit.)52 b(F)-8 b(or)0 4946 y(historical)37 b(reasons,)g(eac)m(h)f(Header)g(or)g(Data)h(unit)e(m)m(ust)g(b)s(e)g (an)g(exact)i(m)m(ultiple)f(of)g(2880)h(8-bit)f(b)m(ytes)g(long.)0 5059 y(An)m(y)30 b(un)m(used)g(space)g(is)h(padded)e(with)h(\014ll)g(c) m(haracters)i(\(ASCI)s(I)d(blanks)h(or)h(zeros\).)0 5219 y(Eac)m(h)i(Header)f(Unit)h(consists)g(of)f(an)m(y)g(n)m(um)m(b)s(er)f (of)i(80-c)m(haracter)i(k)m(eyw)m(ord)d(records)g(or)g(`card)h(images') g(whic)m(h)0 5332 y(ha)m(v)m(e)f(the)e(general)i(form:)95 5601 y Fe(KEYNAME)46 b(=)i(value)e(/)i(comment)d(string)95 5714 y(NULLKEY)h(=)334 b(/)48 b(comment:)d(This)i(keyword)f(has)g(no)i (value)1905 5942 y Fi(13)p eop end %%Page: 14 20 TeXDict begin 14 19 bop 0 299 a Fi(14)2398 b Fg(CHAPTER)30 b(3.)112 b(A)30 b(FITS)g(PRIMER)0 555 y Fi(The)35 b(k)m(eyw)m(ord)i (names)f(ma)m(y)g(b)s(e)g(up)f(to)h(8)h(c)m(haracters)g(long)g(and)e (can)h(only)h(con)m(tain)g(upp)s(ercase)e(letters,)k(the)0 668 y(digits)25 b(0-9,)i(the)e(h)m(yphen,)g(and)f(the)h(underscore)e(c) m(haracter.)41 b(The)24 b(k)m(eyw)m(ord)h(name)g(is)f(\(usually\))h (follo)m(w)m(ed)i(b)m(y)d(an)0 781 y(equals)29 b(sign)g(and)f(a)g (space)i(c)m(haracter)g(\(=)e(\))h(in)f(columns)h(9)g(-)f(10)i(of)f (the)f(record,)h(follo)m(w)m(ed)i(b)m(y)d(the)h(v)-5 b(alue)29 b(of)g(the)0 894 y(k)m(eyw)m(ord)34 b(whic)m(h)g(ma)m(y)g(b)s (e)f(either)h(an)g(in)m(teger,)i(a)e(\015oating)g(p)s(oin)m(t)g(n)m(um) m(b)s(er,)g(a)g(c)m(haracter)h(string)e(\(enclosed)i(in)0 1007 y(single)28 b(quotes\),)i(or)e(a)g(b)s(o)s(olean)g(v)-5 b(alue)28 b(\(the)g(letter)h(T)f(or)f(F\).)i(A)f(k)m(eyw)m(ord)g(ma)m (y)h(also)f(ha)m(v)m(e)h(a)g(n)m(ull)e(or)h(unde\014ned)0 1120 y(v)-5 b(alue)31 b(if)f(there)h(is)f(no)g(sp)s(eci\014ed)g(v)-5 b(alue)31 b(string,)g(as)f(in)g(the)h(second)f(example.)0 1280 y(The)c(last)h(k)m(eyw)m(ord)g(in)g(the)f(header)h(is)f(alw)m(a)m (ys)i(the)f(`END')g(k)m(eyw)m(ord)g(whic)m(h)g(has)f(no)g(v)-5 b(alue)27 b(or)g(commen)m(t)g(\014elds.)0 1393 y(There)k(are)g(man)m(y) g(rules)g(go)m(v)m(erning)h(the)g(exact)g(format)g(of)f(a)g(k)m(eyw)m (ord)h(record)f(\(see)h(the)f(FITS)f(Standard\))h(so)0 1506 y(it)c(is)g(b)s(etter)g(to)h(rely)f(on)g(standard)f(in)m(terface)j (soft)m(w)m(are)f(lik)m(e)g(FITSIO)e(to)i(correctly)g(construct)f(or)g (to)h(parse)f(the)0 1619 y(k)m(eyw)m(ord)k(records)f(rather)g(than)g (try)h(to)g(deal)g(directly)g(with)f(the)g(ra)m(w)h(FITS)e(formats.)0 1779 y(Eac)m(h)37 b(Header)g(Unit)f(b)s(egins)g(with)g(a)g(series)h(of) f(required)g(k)m(eyw)m(ords)g(whic)m(h)g(dep)s(end)f(on)h(the)g(t)m(yp) s(e)h(of)f(HDU.)0 1892 y(These)31 b(required)g(k)m(eyw)m(ords)h(sp)s (ecify)g(the)f(size)i(and)e(format)h(of)g(the)g(follo)m(wing)h(Data)g (Unit.)45 b(The)31 b(header)g(ma)m(y)0 2005 y(con)m(tain)h(other)f (optional)g(k)m(eyw)m(ords)g(to)h(describ)s(e)e(other)g(asp)s(ects)h (of)g(the)g(data,)g(suc)m(h)g(as)g(the)f(units)g(or)h(scaling)0 2118 y(v)-5 b(alues.)44 b(Other)31 b(COMMENT)g(or)g(HISTOR)-8 b(Y)30 b(k)m(eyw)m(ords)i(are)g(also)g(frequen)m(tly)g(added)e(to)i (further)e(do)s(cumen)m(t)0 2230 y(the)h(data)g(\014le.)0 2391 y(The)36 b(optional)h(Data)h(Unit)f(immediately)g(follo)m(ws)h (the)e(last)h(2880-b)m(yte)i(blo)s(c)m(k)e(in)f(the)g(Header)h(Unit.)59 b(Some)0 2503 y(HDUs)31 b(do)f(not)h(ha)m(v)m(e)g(a)g(Data)h(Unit)f (and)f(only)g(consist)h(of)g(the)f(Header)h(Unit.)0 2664 y(If)24 b(there)i(is)f(more)g(than)f(one)h(HDU)h(in)f(the)g(FITS)f (\014le,)i(then)f(the)g(Header)h(Unit)f(of)g(the)g(next)g(HDU)h (immediately)0 2777 y(follo)m(ws)g(the)e(last)i(2880-b)m(yte)h(blo)s(c) m(k)e(of)g(the)f(previous)g(Data)j(Unit)d(\(or)h(Header)g(Unit)g(if)f (there)h(is)g(no)f(Data)i(Unit\).)0 2937 y(The)k(main)g(required)g(k)m (eyw)m(ords)g(in)g(FITS)g(primary)g(arra)m(ys)g(or)h(image)g (extensions)g(are:)136 3172 y Fc(\017)46 b Fi(BITPIX)33 b({)h(de\014nes)e(the)i(datat)m(yp)s(e)g(of)f(the)g(arra)m(y:)47 b(8,)35 b(16,)g(32,)g(64,)g(-32,)g(-64)g(for)e(unsigned)f(8{bit)i(b)m (yte,)227 3284 y(16{bit)27 b(signed)e(in)m(teger,)i(32{bit)g(signed)e (in)m(teger,)j(64{bit)e(signed)f(in)m(teger,)j(32{bit)e(IEEE)f (\015oating)h(p)s(oin)m(t,)227 3397 y(and)k(64{bit)i(IEEE)e(double)f (precision)i(\015oating)g(p)s(oin)m(t,)g(resp)s(ectiv)m(ely)-8 b(.)136 3585 y Fc(\017)46 b Fi(NAXIS)30 b({)h(the)g(n)m(um)m(b)s(er)e (of)h(dimensions)g(in)g(the)h(arra)m(y)-8 b(,)31 b(usually)f(0,)h(1,)g (2,)g(3,)g(or)g(4.)136 3773 y Fc(\017)46 b Fi(NAXISn)30 b({)h(\(n)f(ranges)g(from)g(1)h(to)g(NAXIS\))g(de\014nes)e(the)i(size)g (of)g(eac)m(h)g(dimension.)0 4008 y(FITS)e(tables)i(start)g(with)f(the) g(k)m(eyw)m(ord)g(XTENSION)g(=)f(`T)-8 b(ABLE')31 b(\(for)f(ASCI)s(I)f (tables\))i(or)f(XTENSION)f(=)0 4120 y(`BINT)-8 b(ABLE')32 b(\(for)e(binary)g(tables\))h(and)f(ha)m(v)m(e)i(the)e(follo)m(wing)i (main)e(k)m(eyw)m(ords:)136 4355 y Fc(\017)46 b Fi(TFIELDS)30 b({)h(n)m(um)m(b)s(er)e(of)h(\014elds)g(or)h(columns)f(in)g(the)g (table)136 4543 y Fc(\017)46 b Fi(NAXIS2)31 b({)g(n)m(um)m(b)s(er)e(of) h(ro)m(ws)h(in)f(the)g(table)136 4731 y Fc(\017)46 b Fi(TTYPEn)29 b({)i(for)f(eac)m(h)i(column)e(\(n)g(ranges)h(from)f(1)g (to)h(TFIELDS\))g(giv)m(es)g(the)g(name)f(of)h(the)f(column)136 4918 y Fc(\017)46 b Fi(TF)m(ORMn)31 b({)f(the)h(datat)m(yp)s(e)g(of)g (the)f(column)136 5106 y Fc(\017)46 b Fi(TUNITn)30 b({)g(the)h(ph)m (ysical)g(units)f(of)g(the)h(column)f(\(optional\))0 5341 y(Users)k(should)f(refer)h(to)h(the)f(FITS)g(Supp)s(ort)e(O\016ce) i(at)h Fe(http://fits.gsfc.nasa.gov)27 b Fi(for)34 b(further)f(infor-)0 5454 y(mation)e(ab)s(out)f(the)h(FITS)e(format)i(and)f(related)h(soft)m (w)m(are)h(pac)m(k)-5 b(ages.)p eop end %%Page: 15 21 TeXDict begin 15 20 bop 0 1225 a Ff(Chapter)65 b(4)0 1687 y Fl(FITSIO)76 b(Con)-6 b(v)g(en)g(tions)76 b(and)h(Guidelines)0 2216 y Fd(4.1)135 b(CFITSIO)44 b(Size)h(Limitations)0 2524 y Fi(CFITSIO)31 b(places)i(few)g(restrictions)g(on)g(the)f(size)i (of)e(FITS)g(\014les)h(that)g(it)g(reads)f(or)h(writes.)47 b(There)32 b(are)h(a)g(few)0 2636 y(limits,)e(ho)m(w)m(ev)m(er,)h(whic) m(h)e(ma)m(y)h(a\013ect)h(some)f(extreme)g(cases:)0 2797 y(1.)43 b(The)31 b(maxim)m(um)g(n)m(um)m(b)s(er)f(of)h(FITS)f(\014les)h (that)h(ma)m(y)g(b)s(e)e(sim)m(ultaneously)i(op)s(ened)f(b)m(y)g (CFITSIO)e(is)i(set)h(b)m(y)0 2910 y(NMAXFILES,)e(as)f(de\014ned)f(in)h (\014tsio2.h.)41 b(The)29 b(curren)m(t)g(default)g(v)-5 b(alue)30 b(is)f(1000,)j(but)c(this)h(ma)m(y)h(b)s(e)f(increased)0 3022 y(if)40 b(necessary)-8 b(.)72 b(Note)42 b(that)f(CFITSIO)e(allo)s (cates)j(NIOBUF)f(*)g(2880)h(b)m(ytes)f(of)g(I/O)f(bu\013er)g(space)h (for)f(eac)m(h)0 3135 y(\014le)d(that)h(is)f(op)s(ened.)61 b(The)37 b(default)g(v)-5 b(alue)38 b(of)f(NIOBUF)h(is)f(40)h (\(de\014ned)f(in)f(\014tsio.h\),)k(so)e(this)f(amoun)m(ts)g(to)0 3248 y(more)31 b(than)g(115K)i(of)e(memory)g(for)g(eac)m(h)i(op)s(ened) d(\014le)i(\(or)f(115)i(MB)f(for)f(1000)i(op)s(ened)d(\014les\).)44 b(Note)33 b(that)f(the)0 3361 y(underlying)k(op)s(erating)i(system,)h (ma)m(y)e(ha)m(v)m(e)i(a)e(lo)m(w)m(er)i(limit)f(on)f(the)g(n)m(um)m(b) s(er)f(of)h(\014les)g(that)h(can)f(b)s(e)g(op)s(ened)0 3474 y(sim)m(ultaneously)-8 b(.)0 3634 y(2.)54 b(By)35 b(default,)h(CFITSIO)d(can)i(handle)g(FITS)f(\014les)g(up)g(to)h(2.1)h (GB)g(in)e(size)i(\(2**31)h(b)m(ytes\).)54 b(This)34 b(\014le)h(size)0 3747 y(limit)41 b(is)g(often)f(imp)s(osed)g(b)m(y)g (32-bit)i(op)s(erating)e(systems.)71 b(More)41 b(recen)m(tly)-8 b(,)45 b(as)c(64-bit)g(op)s(erating)g(systems)0 3860 y(b)s(ecome)33 b(more)g(common,)g(an)g(industry-wide)e(standard)h(\(at) i(least)f(on)g(Unix)f(systems\))h(has)g(b)s(een)f(dev)m(elop)s(ed)0 3973 y(to)39 b(supp)s(ort)d(larger)i(sized)h(\014les)f(\(see)g(h)m (ttp://ftp.sas.com/standards/large.\014le/\).)69 b(Starting)38 b(with)f(v)m(ersion)0 4086 y(2.1)45 b(of)e(CFITSIO,)f(larger)i(FITS)f (\014les)g(up)g(to)h(6)g(terab)m(ytes)h(in)e(size)h(ma)m(y)g(b)s(e)f (read)g(and)g(written)h(on)f(sup-)0 4199 y(p)s(orted)f(platforms.)76 b(In)42 b(order)g(to)h(supp)s(ort)e(these)h(larger)h(\014les,)j (CFITSIO)41 b(m)m(ust)h(b)s(e)g(compiled)h(with)f(the)0 4312 y('-D)p 129 4312 28 4 v 34 w(LAR)m(GEFILE)p 696 4312 V 33 w(SOUR)m(CE')g(and)g(`-D)p 1491 4312 V 34 w(FILE)p 1736 4312 V 33 w(OFFSET)p 2137 4312 V 32 w(BITS=64')h(compiler)g (\015ags.)78 b(Some)43 b(platforms)0 4425 y(ma)m(y)c(also)g(require)f (the)g(`-D)p 1002 4425 V 34 w(LAR)m(GE)p 1358 4425 V 33 w(FILES')g(compiler)h(\015ag.)64 b(This)38 b(causes)g(the)h (compiler)g(to)g(allo)s(cate)h(8-)0 4538 y(b)m(ytes)k(instead)g(of)g (4-b)m(ytes)h(for)f(the)g(`o\013)p 1473 4538 V 33 w(t')g(datat)m(yp)s (e)h(whic)m(h)f(is)f(used)g(to)i(store)f(\014le)g(o\013set)h(p)s (ositions.)81 b(It)0 4650 y(app)s(ears)31 b(that)i(in)e(most)i(cases)g (it)f(is)g(not)g(necessary)h(to)f(also)h(include)f(these)g(compiler)h (\015ags)f(when)f(compiling)0 4763 y(programs)f(that)h(link)f(to)h(the) g(CFITSIO)e(library)-8 b(.)0 4924 y(If)21 b(CFITSIO)e(is)i(compiled)h (with)f(the)g(-D)p 1386 4924 V 33 w(LAR)m(GEFILE)p 1952 4924 V 34 w(SOUR)m(CE)f(and)g(-D)p 2654 4924 V 34 w(FILE)p 2899 4924 V 33 w(OFFSET)p 3300 4924 V 32 w(BITS=64)h(\015ags)0 5036 y(on)36 b(a)g(platform)g(that)g(supp)s(orts)e(large)j(\014les,)h (then)d(it)i(can)f(read)g(and)f(write)h(FITS)f(\014les)h(that)g(con)m (tain)h(up)e(to)0 5149 y(2**31)k(2880-b)m(yte)g(FITS)d(records,)j(or)d (appro)m(ximately)i(6)f(terab)m(ytes)h(in)f(size.)60 b(It)37 b(is)g(still)h(required)d(that)j(the)0 5262 y(v)-5 b(alue)30 b(of)f(the)g(NAXISn)f(and)h(PCOUNT)f(k)m(eyw)m(ords)h(in)g (eac)m(h)h(extension)g(b)s(e)e(within)h(the)g(range)h(of)f(a)g(signed)g (4-)0 5375 y(b)m(yte)c(in)m(teger)h(\(max)f(v)-5 b(alue)26 b(=)e(2,147,483,648\).)44 b(Th)m(us,)25 b(eac)m(h)h(dimension)e(of)h (an)f(image)i(\(giv)m(en)g(b)m(y)f(the)g(NAXISn)0 5488 y(k)m(eyw)m(ords\),)32 b(the)f(total)i(width)d(of)h(a)g(table)h (\(NAXIS1)g(k)m(eyw)m(ord\),)g(the)f(n)m(um)m(b)s(er)f(of)h(ro)m(ws)g (in)f(a)h(table)h(\(NAXIS2)0 5601 y(k)m(eyw)m(ord\),)c(and)d(the)h (total)i(size)f(of)f(the)g(v)-5 b(ariable-length)28 b(arra)m(y)e(heap)g (in)g(binary)f(tables)i(\(PCOUNT)e(k)m(eyw)m(ord\))0 5714 y(m)m(ust)30 b(b)s(e)g(less)h(than)f(this)g(limit.)1905 5942 y(15)p eop end %%Page: 16 22 TeXDict begin 16 21 bop 0 299 a Fi(16)1277 b Fg(CHAPTER)29 b(4.)72 b(FITSIO)29 b(CONVENTIONS)g(AND)i(GUIDELINES)0 555 y Fi(Curren)m(tly)-8 b(,)31 b(supp)s(ort)e(for)i(large)h(\014les)f (within)f(CFITSIO)f(has)i(b)s(een)f(tested)i(on)f(the)g(Lin)m(ux,)g (Solaris,)g(and)f(IBM)0 668 y(AIX)g(op)s(erating)h(systems.)0 1133 y Fd(4.2)135 b(Multiple)46 b(Access)e(to)i(the)f(Same)g(FITS)f (File)0 1409 y Fi(CFITSIO)35 b(supp)s(orts)g(sim)m(ultaneous)i(read)f (and)g(write)h(access)g(to)h(m)m(ultiple)f(HDUs)g(in)f(the)h(same)g (FITS)f(\014le.)0 1522 y(Th)m(us,)43 b(one)e(can)h(op)s(en)e(the)h (same)h(FITS)e(\014le)h(t)m(wice)i(within)d(a)i(single)f(program)g(and) g(mo)m(v)m(e)h(to)g(2)f(di\013eren)m(t)0 1635 y(HDUs)30 b(in)f(the)h(\014le,)g(and)f(then)g(read)h(and)e(write)i(data)g(or)g(k) m(eyw)m(ords)g(to)g(the)g(2)f(extensions)i(just)d(as)i(if)g(one)f(w)m (ere)0 1748 y(accessing)f(2)f(completely)h(separate)f(FITS)f(\014les.) 39 b(Since)27 b(in)f(general)h(it)g(is)g(not)g(p)s(ossible)f(to)h(ph)m (ysically)g(op)s(en)f(the)0 1861 y(same)36 b(\014le)g(t)m(wice)h(and)e (then)g(exp)s(ect)h(to)g(b)s(e)f(able)h(to)h(sim)m(ultaneously)f(\(or)g (in)f(alternating)i(succession\))g(write)0 1974 y(to)e(2)f(di\013eren)m (t)h(lo)s(cations)h(in)d(the)i(\014le,)g(CFITSIO)e(recognizes)j(when)d (the)h(\014le)g(to)h(b)s(e)f(op)s(ened)f(\(in)h(the)h(call)g(to)0 2087 y(\014ts)p 127 2087 28 4 v 32 w(op)s(en)p 349 2087 V 33 w(\014le\))29 b(has)f(already)h(b)s(een)f(op)s(ened)g(and)g (instead)h(of)g(actually)h(op)s(ening)e(the)h(\014le)g(again,)h(just)e (logically)0 2199 y(links)i(the)h(new)f(\014le)h(to)g(the)g(old)f (\014le.)42 b(\(This)30 b(only)h(applies)f(if)h(the)g(\014le)f(is)h(op) s(ened)f(more)g(than)g(once)i(within)e(the)0 2312 y(same)e(program,)g (and)f(do)s(es)h(not)f(prev)m(en)m(t)i(the)f(same)g(\014le)f(from)g(b)s (eing)h(sim)m(ultaneously)g(op)s(ened)f(b)m(y)g(more)h(than)0 2425 y(one)h(program\).)40 b(Then)28 b(b)s(efore)g(CFITSIO)f(reads)h (or)h(writes)g(to)g(either)g(\(logical\))j(\014le,)d(it)g(mak)m(es)h (sure)d(that)j(an)m(y)0 2538 y(mo)s(di\014cations)i(made)f(to)h(the)g (other)g(\014le)f(ha)m(v)m(e)i(b)s(een)e(completely)i(\015ushed)c(from) i(the)h(in)m(ternal)g(bu\013ers)f(to)h(the)0 2651 y(\014le.)44 b(Th)m(us,)30 b(in)h(principle,)h(one)f(could)g(op)s(en)g(a)h(\014le)f (t)m(wice,)i(in)e(one)h(case)g(p)s(oin)m(ting)g(to)g(the)f(\014rst)g (extension)h(and)0 2764 y(in)i(the)h(other)g(p)s(oin)m(ting)f(to)i(the) e(2nd)g(extension)i(and)d(then)i(write)f(data)i(to)f(b)s(oth)f (extensions,)i(in)e(an)m(y)h(order,)0 2877 y(without)25 b(danger)h(of)f(corrupting)h(the)f(\014le,)i(There)e(ma)m(y)h(b)s(e)f (some)h(e\016ciency)g(p)s(enalties)g(in)f(doing)h(this)f(ho)m(w)m(ev)m (er,)0 2990 y(since)j(CFITSIO)f(has)h(to)h(\015ush)d(all)j(the)f(in)m (ternal)h(bu\013ers)e(related)i(to)g(one)f(\014le)g(b)s(efore)g(switc)m (hing)g(to)h(the)f(other,)0 3103 y(so)i(it)h(w)m(ould)f(still)h(b)s(e)f (pruden)m(t)f(to)i(minimize)g(the)f(n)m(um)m(b)s(er)f(of)i(times)f(one) h(switc)m(hes)g(bac)m(k)g(and)e(forth)h(b)s(et)m(w)m(een)0 3216 y(doing)g(I/O)h(to)g(di\013eren)m(t)g(HDUs)g(in)f(the)g(same)h (\014le.)0 3680 y Fd(4.3)135 b(Curren)l(t)46 b(Header)f(Data)h(Unit)g (\(CHDU\))0 3957 y Fi(In)32 b(general,)j(a)f(FITS)e(\014le)i(can)f(con) m(tain)h(m)m(ultiple)g(Header)g(Data)h(Units,)f(also)g(called)g (extensions.)49 b(CFITSIO)0 4070 y(only)38 b(op)s(erates)h(within)f (one)g(HDU)h(at)g(an)m(y)g(giv)m(en)g(time,)i(and)d(the)g(curren)m(tly) g(selected)i(HDU)f(is)f(called)i(the)0 4183 y(Curren)m(t)f(Header)h (Data)h(Unit)f(\(CHDU\).)h(When)f(a)g(FITS)f(\014le)h(is)f(\014rst)g (created)i(or)f(op)s(ened)f(the)h(CHDU)g(is)0 4295 y(automatically)28 b(de\014ned)23 b(to)j(b)s(e)e(the)h(\014rst)f(HDU)i(\(i.e.,)h(the)e (primary)f(arra)m(y\).)40 b(CFITSIO)23 b(routines)i(are)g(pro)m(vided)0 4408 y(to)36 b(mo)m(v)m(e)h(to)g(and)e(op)s(en)g(an)m(y)h(other)g (existing)g(HDU)h(within)e(the)h(FITS)f(\014le)g(or)h(to)g(app)s(end)e (or)i(insert)f(a)h(new)0 4521 y(HDU)31 b(in)f(the)h(FITS)e(\014le)i (whic)m(h)f(then)g(b)s(ecomes)h(the)f(CHDU.)0 4986 y Fd(4.4)135 b(Subroutine)45 b(Names)0 5262 y Fi(All)26 b(FITSIO)f(subroutine)g(names)h(b)s(egin)f(with)h(the)g(letters)h('ft') f(to)h(distinguish)e(them)h(from)f(other)h(subroutines)0 5375 y(and)34 b(are)h(5)g(or)f(6)h(c)m(haracters)h(long.)54 b(Users)34 b(should)g(not)g(name)h(their)g(o)m(wn)f(subroutines)f(b)s (eginning)h(with)g('ft')0 5488 y(to)e(a)m(v)m(oid)i(con\015icts.)45 b(\(The)32 b(SPP)f(in)m(terface)i(routines)e(all)i(b)s(egin)e(with)h ('fs'\).)45 b(Subroutines)30 b(whic)m(h)h(read)h(or)g(get)0 5601 y(information)e(from)g(the)h(FITS)e(\014le)h(ha)m(v)m(e)i(names)e (b)s(eginning)f(with)h('ftg...'.)43 b(Subroutines)28 b(whic)m(h)i(write)g(or)h(put)0 5714 y(information)g(in)m(to)g(the)g (FITS)e(\014le)i(ha)m(v)m(e)g(names)g(b)s(eginning)e(with)h('ftp...'.)p eop end %%Page: 17 23 TeXDict begin 17 22 bop 0 299 a Fg(4.5.)72 b(SUBR)m(OUTINE)30 b(F)-10 b(AMILIES)30 b(AND)h(D)m(A)-8 b(T)g(A)g(TYPES)1697 b Fi(17)0 555 y Fd(4.5)135 b(Subroutine)45 b(F)-11 b(amilies)46 b(and)f(Datat)l(yp)t(es)0 805 y Fi(Man)m(y)h(of)g(the)g(subroutines)e (come)j(in)e(families)h(whic)m(h)g(di\013er)f(only)h(in)f(the)h(datat)m (yp)s(e)g(of)g(the)f(asso)s(ciated)0 918 y(parameter\(s\))34 b(.)47 b(The)32 b(datat)m(yp)s(e)i(of)f(these)g(subroutines)e(is)i (indicated)g(b)m(y)g(the)g(last)g(letter)h(of)f(the)g(subroutine)0 1031 y(name)d(\(e.g.,)j('j')d(in)g('ftpkyj'\))h(as)f(follo)m(ws:)382 1284 y Fe(x)47 b(-)h(bit)382 1397 y(b)f(-)h(character*1)c(\(unsigned)i (byte\))382 1510 y(i)h(-)h(short)e(integer)g(\(I*2\))382 1623 y(j)h(-)h(integer)e(\(I*4,)g(32-bit)g(integer\))382 1735 y(k)h(-)h(long)e(long)h(integer)f(\(I*8,)g(64-bit)g(integer\))382 1848 y(e)h(-)h(real)e(exponential)f(floating)h(point)g(\(R*4\))382 1961 y(f)h(-)h(real)e(fixed-format)f(floating)g(point)i(\(R*4\))382 2074 y(d)g(-)h(double)e(precision)f(real)i(floating-point)d(\(R*8\))382 2187 y(g)j(-)h(double)e(precision)f(fixed-format)g(floating)g(point)h (\(R*8\))382 2300 y(c)h(-)h(complex)e(reals)g(\(pairs)g(of)h(R*4)g (values\))382 2413 y(m)g(-)h(double)e(precision)f(complex)h(\(pairs)g (of)h(R*8)g(values\))382 2526 y(l)g(-)h(logical)e(\(L*4\))382 2639 y(s)h(-)h(character)d(string)0 2891 y Fi(When)23 b(dealing)h(with)f(the)g(FITS)g(b)m(yte)g(datat)m(yp)s(e,)j(it)e(is)f (imp)s(ortan)m(t)h(to)f(remem)m(b)s(er)g(that)h(the)f(ra)m(w)g(v)-5 b(alues)24 b(\(b)s(efore)0 3004 y(an)m(y)h(scaling)g(b)m(y)f(the)h (BSCALE)e(and)h(BZER)m(O,)g(or)h(TSCALn)d(and)i(TZER)m(On)f(k)m(eyw)m (ord)i(v)-5 b(alues\))25 b(in)f(b)m(yte)h(arra)m(ys)0 3117 y(\(BITPIX)37 b(=)f(8\))h(or)f(b)m(yte)i(columns)e(\(TF)m(ORMn)h (=)f('B'\))h(are)g(in)m(terpreted)g(as)g(unsigned)e(b)m(ytes)i(with)g (v)-5 b(alues)0 3230 y(ranging)40 b(from)f(0)i(to)f(255.)71 b(Some)40 b(F)-8 b(ortran)40 b(compilers)h(supp)s(ort)d(a)i (non-standard)f(b)m(yte)h(datat)m(yp)s(e)h(suc)m(h)f(as)0 3343 y(INTEGER*1,)34 b(LOGICAL*1,)g(or)f(BYTE,)g(whic)m(h)f(can)h (sometimes)h(b)s(e)e(used)g(instead)h(of)g(CHARA)m(CTER*1)0 3456 y(v)-5 b(ariables.)39 b(Man)m(y)23 b(mac)m(hines)g(p)s(ermit)g (passing)f(a)h(n)m(umeric)g(datat)m(yp)s(e)g(\(suc)m(h)g(as)g (INTEGER*1\))h(to)f(the)g(FITSIO)0 3569 y(subroutines)41 b(whic)m(h)i(are)g(exp)s(ecting)g(a)g(CHARA)m(CTER*1)h(datat)m(yp)s(e,) j(but)42 b(this)g(tec)m(hnically)j(violates)g(the)0 3682 y(F)-8 b(ortran-77)29 b(standard)d(and)g(is)h(not)g(supp)s(orted)e(on)i (all)h(mac)m(hines)f(\(e.g.,)j(on)c(a)i(V)-10 b(AX/VMS)27 b(mac)m(hine)h(one)f(m)m(ust)0 3795 y(use)j(the)h(V)-10 b(AX-sp)s(eci\014c)31 b(\045DESCR)e(function\).)0 3955 y(One)22 b(feature)h(of)g(the)g(CFITSIO)e(routines)i(is)f(that)i(they)f (can)g(op)s(erate)g(on)f(a)h(`X')h(\(bit\))f(column)g(in)f(a)h(binary)f (table)0 4068 y(as)35 b(though)e(it)i(w)m(ere)g(a)g(`B')g(\(b)m(yte\))g (column.)53 b(F)-8 b(or)35 b(example)g(a)f(`11X')i(datat)m(yp)s(e)f (column)f(can)h(b)s(e)f(in)m(terpreted)0 4181 y(the)28 b(same)h(as)f(a)g(`2B')i(column)e(\(i.e.,)i(2)e(unsigned)f(8-bit)i(b)m (ytes\).)41 b(In)27 b(some)i(instances,)g(it)f(can)h(b)s(e)e(more)h (e\016cien)m(t)0 4294 y(to)j(read)f(and)g(write)h(whole)f(b)m(ytes)h (at)g(a)g(time,)g(rather)g(than)f(reading)g(or)h(writing)f(eac)m(h)i (individual)d(bit.)0 4454 y(The)41 b(double)h(precision)g(complex)g (datat)m(yp)s(e)h(is)f(not)g(a)g(standard)f(F)-8 b(ortran-77)43 b(datat)m(yp)s(e.)76 b(If)41 b(a)i(particular)0 4567 y(F)-8 b(ortran)35 b(compiler)g(do)s(es)f(not)h(directly)g(supp)s(ort)e (this)i(datat)m(yp)s(e,)h(then)f(one)f(ma)m(y)h(instead)g(pass)f(an)h (arra)m(y)g(of)0 4680 y(pairs)d(of)h(double)f(precision)h(v)-5 b(alues)32 b(to)i(these)f(subroutines.)45 b(The)33 b(\014rst)e(v)-5 b(alue)33 b(in)f(eac)m(h)i(pair)e(is)h(the)g(real)g(part,)0 4792 y(and)d(the)g(second)h(is)f(the)h(imaginary)g(part.)0 5125 y Fd(4.6)135 b(Implicit)46 b(Data)g(T)l(yp)t(e)f(Con)l(v)l(ersion) 0 5375 y Fi(The)22 b(FITSIO)g(routines)h(that)h(read)e(and)h(write)g(n) m(umerical)g(data)h(can)f(p)s(erform)f(implicit)i(data)f(t)m(yp)s(e)g (con)m(v)m(ersion.)0 5488 y(This)i(means)g(that)h(the)g(data)g(t)m(yp)s (e)g(of)g(the)g(v)-5 b(ariable)26 b(or)g(arra)m(y)g(in)f(the)h(program) f(do)s(es)g(not)h(need)g(to)g(b)s(e)f(the)h(same)0 5601 y(as)i(the)f(data)h(t)m(yp)s(e)g(of)f(the)h(v)-5 b(alue)28 b(in)f(the)g(FITS)g(\014le.)40 b(Data)28 b(t)m(yp)s(e)g(con)m(v)m (ersion)h(is)e(supp)s(orted)f(for)h(n)m(umerical)h(and)0 5714 y(string)33 b(data)h(t)m(yp)s(es)f(\(if)h(the)g(string)f(con)m (tains)h(a)g(v)-5 b(alid)33 b(n)m(um)m(b)s(er)f(enclosed)i(in)f (quotes\))h(when)f(reading)g(a)h(FITS)p eop end %%Page: 18 24 TeXDict begin 18 23 bop 0 299 a Fi(18)1277 b Fg(CHAPTER)29 b(4.)72 b(FITSIO)29 b(CONVENTIONS)g(AND)i(GUIDELINES)0 555 y Fi(header)g(k)m(eyw)m(ord)g(v)-5 b(alue)31 b(and)g(for)f(n)m (umeric)h(v)-5 b(alues)31 b(when)f(reading)h(or)g(writing)g(v)-5 b(alues)31 b(in)f(the)h(primary)f(arra)m(y)0 668 y(or)40 b(a)h(table)h(column.)70 b(CFITSIO)39 b(returns)h(status)g(=)h(NUM)p 2185 668 28 4 v 33 w(O)m(VERFLO)m(W)g(if)g(the)f(con)m(v)m(erted)i (data)f(v)-5 b(alue)0 781 y(exceeds)33 b(the)g(range)g(of)g(the)f (output)g(data)i(t)m(yp)s(e.)47 b(Implicit)33 b(data)g(t)m(yp)s(e)g (con)m(v)m(ersion)h(is)e(not)h(supp)s(orted)d(within)0 894 y(binary)g(tables)h(for)f(string,)g(logical,)k(complex,)d(or)f (double)g(complex)h(data)g(t)m(yp)s(es.)0 1054 y(In)g(addition,)h(an)m (y)f(table)h(column)f(ma)m(y)h(b)s(e)f(read)g(as)h(if)f(it)h(con)m (tained)g(string)f(v)-5 b(alues.)44 b(In)31 b(the)g(case)i(of)e(n)m (umeric)0 1167 y(columns)f(the)h(returned)e(string)h(will)h(b)s(e)f (formatted)h(using)e(the)i(TDISPn)e(displa)m(y)i(format)f(if)h(it)g (exists.)0 1496 y Fd(4.7)135 b(Data)46 b(Scaling)0 1746 y Fi(When)38 b(reading)f(n)m(umerical)i(data)f(v)-5 b(alues)38 b(in)f(the)h(primary)f(arra)m(y)h(or)g(a)g(table)h(column,)h(the)d(v)-5 b(alues)38 b(will)h(b)s(e)0 1859 y(scaled)f(automatically)j(b)m(y)c (the)h(BSCALE)f(and)g(BZER)m(O)h(\(or)g(TSCALn)d(and)i(TZER)m(On\))g (header)g(k)m(eyw)m(ord)0 1972 y(v)-5 b(alues)33 b(if)f(they)g(are)h (presen)m(t)g(in)f(the)g(header.)47 b(The)31 b(scaled)j(data)f(that)g (is)f(returned)f(to)i(the)g(reading)f(program)0 2085 y(will)f(ha)m(v)m(e)382 2316 y Fe(output)46 b(value)g(=)i(\(FITS)e (value\))g(*)i(BSCALE)e(+)h(BZERO)0 2546 y Fi(\(a)30 b(corresp)s(onding)e(form)m(ula)h(using)g(TSCALn)e(and)i(TZER)m(On)e (is)i(used)g(when)f(reading)h(from)g(table)h(columns\).)0 2659 y(In)h(the)i(case)g(of)f(in)m(teger)h(output)f(v)-5 b(alues)32 b(the)h(\015oating)g(p)s(oin)m(t)f(scaled)g(v)-5 b(alue)33 b(is)f(truncated)g(to)h(an)f(in)m(teger)h(\(not)0 2772 y(rounded)38 b(to)i(the)g(nearest)g(in)m(teger\).)70 b(The)39 b(ftpscl)g(and)g(fttscl)i(subroutines)d(ma)m(y)i(b)s(e)f(used) g(to)h(o)m(v)m(erride)h(the)0 2885 y(scaling)30 b(parameters)f (de\014ned)e(in)h(the)h(header)f(\(e.g.,)j(to)e(turn)f(o\013)h(the)f (scaling)i(so)f(that)g(the)g(program)f(can)h(read)0 2998 y(the)i(ra)m(w)f(unscaled)g(v)-5 b(alues)31 b(from)f(the)g(FITS)g (\014le\).)0 3158 y(When)44 b(writing)h(n)m(umerical)g(data)g(to)g(the) g(primary)f(arra)m(y)h(or)f(to)h(a)g(table)h(column)e(the)h(data)g(v)-5 b(alues)45 b(will)0 3271 y(generally)29 b(b)s(e)f(automatically)j(in)m (v)m(ersely)f(scaled)f(b)m(y)f(the)g(v)-5 b(alue)29 b(of)f(the)h (BSCALE)e(and)h(BZER)m(O)g(\(or)h(TSCALn)0 3384 y(and)h(TZER)m(On\))g (header)g(k)m(eyw)m(ord)h(v)-5 b(alues)31 b(if)g(they)g(they)g(exist)g (in)f(the)h(header.)42 b(These)30 b(k)m(eyw)m(ords)h(m)m(ust)g(ha)m(v)m (e)0 3497 y(b)s(een)f(written)h(to)h(the)g(header)e(b)s(efore)h(an)m(y) h(data)f(is)g(written)h(for)e(them)i(to)f(ha)m(v)m(e)i(an)m(y)e (e\013ect.)44 b(Otherwise,)32 b(one)0 3610 y(ma)m(y)i(use)f(the)g (ftpscl)g(and)g(fttscl)h(subroutines)d(to)j(de\014ne)f(or)g(o)m(v)m (erride)h(the)f(scaling)i(k)m(eyw)m(ords)e(in)g(the)g(header)0 3723 y(\(e.g.,)h(to)f(turn)d(o\013)j(the)f(scaling)h(so)f(that)g(the)g (program)g(can)g(write)g(the)g(ra)m(w)g(unscaled)g(v)-5 b(alues)32 b(in)m(to)h(the)f(FITS)0 3836 y(\014le\).)43 b(If)30 b(scaling)i(is)f(p)s(erformed,)e(the)i(in)m(v)m(erse)h(scaled)g (output)e(v)-5 b(alue)32 b(that)f(is)g(written)g(in)m(to)h(the)f(FITS)f (\014le)h(will)0 3949 y(ha)m(v)m(e)430 4179 y Fe(FITS)46 b(value)h(=)g(\(\(input)f(value\))g(-)h(BZERO\))f(/)i(BSCALE)0 4410 y Fi(\(a)39 b(corresp)s(onding)d(form)m(ula)i(using)g(TSCALn)e (and)h(TZER)m(On)g(is)h(used)f(when)f(writing)i(to)h(table)g (columns\).)0 4523 y(Rounding)19 b(to)i(the)g(nearest)g(in)m(teger,)i (rather)e(than)f(truncation,)j(is)d(p)s(erformed)f(when)g(writing)h(in) m(teger)i(datat)m(yp)s(es)0 4636 y(to)31 b(the)g(FITS)e(\014le.)0 4965 y Fd(4.8)135 b(Error)46 b(Status)f(V)-11 b(alues)45 b(and)g(the)g(Error)g(Message)h(Stac)l(k)0 5215 y Fi(The)33 b(last)i(parameter)f(in)g(nearly)g(ev)m(ery)g(FITSIO)f(subroutine)g(is) h(the)g(error)f(status)h(v)-5 b(alue)35 b(whic)m(h)e(is)h(b)s(oth)f(an) 0 5328 y(input)j(and)f(an)i(output)f(parameter.)60 b(A)36 b(returned)f(p)s(ositiv)m(e)j(v)-5 b(alue)37 b(for)f(this)h(parameter)g (indicates)g(an)f(error)0 5441 y(w)m(as)31 b(detected.)42 b(A)30 b(listing)h(of)g(all)g(the)g(FITSIO)e(status)i(co)s(de)f(v)-5 b(alues)31 b(is)f(giv)m(en)i(at)f(the)f(end)g(of)h(this)f(do)s(cumen)m (t.)0 5601 y(The)22 b(FITSIO)g(library)g(uses)h(an)f(`inherited)h (status')g(con)m(v)m(en)m(tion)i(for)e(the)g(status)g(parameter)g(whic) m(h)g(means)f(that)0 5714 y(if)i(a)h(subroutine)f(is)g(called)i(with)e (a)h(p)s(ositiv)m(e)g(input)f(v)-5 b(alue)25 b(of)g(the)f(status)h (parameter,)h(then)f(the)f(subroutine)g(will)p eop end %%Page: 19 25 TeXDict begin 19 24 bop 0 299 a Fg(4.9.)72 b(V)-10 b(ARIABLE-LENGTH)31 b(ARRA)-8 b(Y)31 b(F)-10 b(A)m(CILITY)30 b(IN)h(BINAR)-8 b(Y)31 b(T)-8 b(ABLES)956 b Fi(19)0 555 y(exit)26 b(immediately)f (without)g(c)m(hanging)h(the)e(v)-5 b(alue)25 b(of)g(the)g(status)g (parameter.)39 b(Th)m(us,)25 b(if)g(one)f(passes)h(the)g(status)0 668 y(v)-5 b(alue)31 b(returned)e(from)h(eac)m(h)i(FITSIO)d(routine)h (as)h(input)f(to)h(the)f(next)h(FITSIO)e(subroutine,)h(then)g(whenev)m (er)0 781 y(an)39 b(error)g(is)h(detected)g(all)h(further)d(FITSIO)g (pro)s(cessing)h(will)h(cease.)69 b(This)39 b(con)m(v)m(en)m(tion)i (can)f(simplify)f(the)0 894 y(error)30 b(c)m(hec)m(king)j(in)d (application)i(programs)f(b)s(ecause)g(it)g(is)g(not)g(necessary)g(to)g (c)m(hec)m(k)i(the)e(v)-5 b(alue)31 b(of)g(the)g(status)0 1007 y(parameter)j(after)g(ev)m(ery)g(single)h(FITSIO)d(subroutine)g (call.)52 b(If)33 b(a)h(program)f(con)m(tains)i(a)f(sequence)g(of)g (sev)m(eral)0 1120 y(FITSIO)23 b(calls,)j(one)e(can)g(just)g(c)m(hec)m (k)h(the)f(status)g(v)-5 b(alue)24 b(after)h(the)f(last)g(call.)40 b(Since)24 b(the)g(returned)e(status)j(v)-5 b(alues)0 1233 y(are)36 b(generally)h(distinctiv)m(e,)i(it)d(should)f(b)s(e)g(p)s (ossible)g(to)h(determine)g(whic)m(h)f(subroutine)g(originally)i (returned)0 1346 y(the)31 b(error)f(status.)0 1506 y(FITSIO)i(also)i (main)m(tains)f(an)g(in)m(ternal)h(stac)m(k)g(of)f(error)g(messages)h (\(80-c)m(haracter)i(maxim)m(um)d(length\))g(whic)m(h)0 1619 y(in)j(man)m(y)g(cases)h(pro)m(vide)f(a)g(more)g(detailed)i (explanation)f(of)f(the)g(cause)h(of)f(the)g(error)g(than)f(is)h(pro)m (vided)g(b)m(y)0 1732 y(the)k(error)e(status)i(n)m(um)m(b)s(er)e (alone.)69 b(It)39 b(is)h(recommended)f(that)g(the)h(error)f(message)h (stac)m(k)h(b)s(e)e(prin)m(ted)g(out)0 1844 y(whenev)m(er)31 b(a)h(program)g(detects)g(a)g(FITSIO)e(error.)44 b(T)-8 b(o)32 b(do)f(this,)h(call)h(the)f(FTGMSG)g(routine)f(rep)s(eatedly)h (to)0 1957 y(get)h(the)g(successiv)m(e)g(messages)h(on)e(the)g(stac)m (k.)48 b(When)32 b(the)h(stac)m(k)g(is)g(empt)m(y)f(FTGMSG)h(will)g (return)e(a)h(blank)0 2070 y(string.)41 b(Note)31 b(that)g(this)f(is)g (a)g(`First)h(In)e({)i(First)f(Out')g(stac)m(k,)i(so)e(the)h(oldest)g (error)e(message)j(is)e(returned)f(\014rst)0 2183 y(b)m(y)h(ftgmsg.)0 2557 y Fd(4.9)135 b(V)-11 b(ariable-Length)46 b(Arra)l(y)f(F)-11 b(acilit)l(y)46 b(in)f(Binary)g(T)-11 b(ables)0 2815 y Fi(FITSIO)38 b(pro)m(vides)i(easy-to-use)h(supp)s(ort)d(for)h (reading)g(and)g(writing)h(data)g(in)f(v)-5 b(ariable)40 b(length)g(\014elds)f(of)h(a)0 2928 y(binary)35 b(table.)56 b(The)35 b(v)-5 b(ariable)36 b(length)f(columns)g(ha)m(v)m(e)i(TF)m (ORMn)e(k)m(eyw)m(ord)h(v)-5 b(alues)35 b(of)h(the)f(form)g (`1Pt\(len\)')0 3041 y(or)30 b(`1Qt\(len\)')h(where)f(`t')g(is)g(the)g (datat)m(yp)s(e)h(co)s(de)f(\(e.g.,)i(I,)e(J,)f(E,)h(D,)h(etc.\))42 b(and)29 b(`len')h(is)g(an)g(in)m(teger)h(sp)s(ecifying)0 3154 y(the)f(maxim)m(um)g(length)g(of)g(the)g(v)m(ector)h(in)f(the)g (table.)41 b(If)30 b(the)g(v)-5 b(alue)30 b(of)g(`len')g(is)g(not)g(sp) s(eci\014ed)f(when)g(the)h(table)0 3267 y(is)j(created)g(\(e.g.,)i(if)e (the)f(TF)m(ORM)h(k)m(eyw)m(ord)g(v)-5 b(alue)33 b(is)g(simply)f(sp)s (eci\014ed)g(as)h('1PE')g(instead)g(of)f('1PE\(400\))j(\),)0 3380 y(then)28 b(FITSIO)f(will)h(automatically)k(scan)c(the)g(table)h (when)f(it)g(is)h(closed)g(to)g(determine)f(the)g(maxim)m(um)h(length)0 3493 y(of)i(the)f(v)m(ector)i(and)e(will)h(app)s(end)d(this)j(v)-5 b(alue)30 b(to)i(the)e(TF)m(ORMn)g(v)-5 b(alue.)0 3653 y(The)25 b(same)h(routines)g(whic)m(h)f(read)h(and)f(write)h(data)g(in) f(an)h(ordinary)f(\014xed)g(length)h(binary)f(table)h(extension)h(are)0 3766 y(also)k(used)e(for)h(v)-5 b(ariable)31 b(length)g(\014elds,)e(ho) m(w)m(ev)m(er,)j(the)e(subroutine)f(parameters)i(tak)m(e)h(on)e(a)g (sligh)m(tly)h(di\013eren)m(t)0 3878 y(in)m(terpretation)h(as)e (describ)s(ed)g(b)s(elo)m(w.)0 4039 y(All)37 b(the)f(data)h(in)f(a)h(v) -5 b(ariable)37 b(length)f(\014eld)g(is)g(written)h(in)m(to)g(an)f (area)h(called)h(the)e(`heap')g(whic)m(h)g(follo)m(ws)i(the)0 4152 y(main)26 b(\014xed-length)g(FITS)f(binary)h(table.)40 b(The)25 b(size)i(of)g(the)f(heap,)h(in)f(b)m(ytes,)h(is)f(sp)s (eci\014ed)g(with)f(the)i(PCOUNT)0 4264 y(k)m(eyw)m(ord)21 b(in)f(the)h(FITS)f(header.)37 b(When)20 b(creating)i(a)f(new)f(binary) g(table,)j(the)e(initial)h(v)-5 b(alue)21 b(of)f(PCOUNT)g(should)0 4377 y(usually)31 b(b)s(e)f(set)i(to)g(zero.)44 b(FITSIO)30 b(will)h(recompute)h(the)f(size)h(of)g(the)f(heap)g(as)g(the)h(data)g (is)f(written)g(and)g(will)0 4490 y(automatically)d(up)s(date)c(the)i (PCOUNT)e(k)m(eyw)m(ord)h(v)-5 b(alue)26 b(when)e(the)h(table)h(is)f (closed.)40 b(When)25 b(writing)g(v)-5 b(ariable)0 4603 y(length)34 b(data)g(to)g(a)g(table,)i(CFITSIO)c(will)h(automatically)k (extend)c(the)h(size)g(of)g(the)g(heap)f(area)h(if)g(necessary)-8 b(,)0 4716 y(so)31 b(that)g(an)m(y)f(follo)m(wing)i(HDUs)f(do)f(not)h (get)h(o)m(v)m(erwritten.)0 4876 y(By)e(default)f(the)h(heap)f(data)i (area)f(starts)g(immediately)h(after)f(the)f(last)i(ro)m(w)e(of)h(the)g (\014xed-length)f(table.)42 b(This)0 4989 y(default)27 b(starting)g(lo)s(cation)i(ma)m(y)e(b)s(e)f(o)m(v)m(erridden)h(b)m(y)g (the)g(THEAP)f(k)m(eyw)m(ord,)i(but)f(this)f(is)h(not)g(recommended.)0 5102 y(If)34 b(additional)h(ro)m(ws)f(of)g(data)h(are)g(added)e(to)i (the)f(table,)j(CFITSIO)32 b(will)j(automatically)i(shift)c(the)i(the)f (heap)0 5215 y(do)m(wn)g(to)i(mak)m(e)f(ro)s(om)g(for)f(the)h(new)f(ro) m(ws,)i(but)e(it)i(is)e(ob)m(viously)i(b)s(e)e(more)h(e\016cien)m(t)h (to)f(initially)h(create)h(the)0 5328 y(table)31 b(with)e(the)h (necessary)g(n)m(um)m(b)s(er)f(of)h(blank)f(ro)m(ws,)h(so)g(that)g(the) g(heap)g(do)s(es)f(not)h(needed)g(to)g(b)s(e)f(constan)m(tly)0 5441 y(mo)m(v)m(ed.)0 5601 y(When)40 b(writing)h(to)g(a)g(v)-5 b(ariable)41 b(length)g(\014eld,)i(the)e(en)m(tire)h(arra)m(y)f(of)f(v) -5 b(alues)41 b(for)f(a)h(giv)m(en)h(ro)m(w)f(of)f(the)h(table)0 5714 y(m)m(ust)36 b(b)s(e)g(written)g(with)g(a)g(single)h(call)h(to)f (FTPCLx.)57 b(The)36 b(total)i(length)f(of)f(the)g(arra)m(y)h(is)f (calculated)i(from)p eop end %%Page: 20 26 TeXDict begin 20 25 bop 0 299 a Fi(20)1277 b Fg(CHAPTER)29 b(4.)72 b(FITSIO)29 b(CONVENTIONS)g(AND)i(GUIDELINES)0 555 y Fi(\(NELEM+FELEM-1\).)44 b(One)30 b(cannot)i(app)s(end)d(more)i (elemen)m(ts)h(to)g(an)e(existing)i(\014eld)f(at)g(a)h(later)g(time;)g (an)m(y)0 668 y(attempt)j(to)f(do)g(so)g(will)g(simply)f(o)m(v)m (erwrite)j(all)e(the)g(data)h(whic)m(h)e(w)m(as)h(previously)g (written.)51 b(Note)35 b(also)f(that)0 781 y(the)g(new)g(data)g(will)h (b)s(e)e(written)h(to)h(a)f(new)g(area)g(of)g(the)h(heap)e(and)h(the)g (heap)g(space)g(used)f(b)m(y)h(the)g(previous)0 894 y(write)j(cannot)h (b)s(e)e(reclaimed.)62 b(F)-8 b(or)38 b(this)f(reason)g(it)h(is)f (advised)g(that)h(eac)m(h)g(ro)m(w)f(of)h(a)f(v)-5 b(ariable)38 b(length)f(\014eld)0 1007 y(only)c(b)s(e)g(written)g(once.)50 b(An)33 b(exception)h(to)g(this)f(general)h(rule)f(o)s(ccurs)g(when)f (setting)i(elemen)m(ts)h(of)e(an)g(arra)m(y)0 1120 y(as)38 b(unde\014ned.)63 b(One)37 b(m)m(ust)i(\014rst)e(write)h(a)h(dumm)m(y)e (v)-5 b(alue)39 b(in)m(to)g(the)g(arra)m(y)f(with)g(FTPCLx,)i(and)e (then)g(call)0 1233 y(FTPCLU)33 b(to)i(\015ag)f(the)f(desired)h(elemen) m(ts)h(as)e(unde\014ned.)49 b(\(Do)35 b(not)f(use)f(the)h(FTPCNx)f (family)h(of)g(routines)0 1346 y(with)28 b(v)-5 b(ariable)30 b(length)f(\014elds\).)40 b(Note)30 b(that)f(the)g(ro)m(ws)g(of)g(a)g (table,)h(whether)e(\014xed)g(or)h(v)-5 b(ariable)29 b(length,)h(do)f(not)0 1458 y(ha)m(v)m(e)j(to)f(b)s(e)e(written)i (consecutiv)m(ely)h(and)e(ma)m(y)h(b)s(e)f(written)g(in)g(an)m(y)h (order.)0 1619 y(When)40 b(writing)h(to)g(a)g(v)-5 b(ariable)41 b(length)g(ASCI)s(I)e(c)m(haracter)j(\014eld)e(\(e.g.,)45 b(TF)m(ORM)c(=)f('1P)-8 b(A'\))43 b(only)d(a)h(single)0 1732 y(c)m(haracter)33 b(string)f(written.)44 b(FTPCLS)30 b(writes)i(the)g(whole)f(length)h(of)g(the)g(input)e(string)i(\(min)m (us)f(an)m(y)h(trailing)0 1844 y(blank)37 b(c)m(haracters\),)42 b(th)m(us)37 b(the)h(NELEM)f(and)g(FELEM)h(parameters)g(are)g(ignored.) 62 b(If)37 b(the)h(input)e(string)i(is)0 1957 y(completely)28 b(blank)f(then)f(FITSIO)g(will)h(write)g(one)g(blank)f(c)m(haracter)j (to)e(the)g(FITS)f(\014le.)40 b(Similarly)-8 b(,)28 b(FTGCVS)0 2070 y(and)35 b(FTGCFS)g(read)g(the)h(en)m(tire)g(string)g(\(truncated) f(to)i(the)e(width)g(of)g(the)h(c)m(haracter)h(string)e(argumen)m(t)h (in)0 2183 y(the)31 b(subroutine)e(call\))j(and)e(also)h(ignore)g(the)f (NELEM)h(and)f(FELEM)g(parameters.)0 2343 y(The)35 b(FTPDES)h (subroutine)e(is)i(useful)f(in)g(situations)i(where)e(m)m(ultiple)i(ro) m(ws)e(of)h(a)g(v)-5 b(ariable)37 b(length)f(column)0 2456 y(ha)m(v)m(e)c(the)e(iden)m(tical)i(arra)m(y)f(of)g(v)-5 b(alues.)41 b(One)30 b(can)g(simply)g(write)h(the)f(arra)m(y)h(once)g (for)g(the)f(\014rst)g(ro)m(w,)g(and)g(then)0 2569 y(use)36 b(FTPDES)g(to)h(write)g(the)f(same)h(descriptor)g(v)-5 b(alues)36 b(in)m(to)i(the)e(other)h(ro)m(ws)f(\(use)h(the)f(FTGDES)h (routine)0 2682 y(to)f(read)f(the)h(\014rst)f(descriptor)g(v)-5 b(alue\);)39 b(all)d(the)g(ro)m(ws)f(will)h(then)f(p)s(oin)m(t)g(to)h (the)g(same)f(storage)i(lo)s(cation)g(th)m(us)0 2795 y(sa)m(ving)31 b(disk)f(space.)0 2955 y(When)35 b(reading)g(from)f(a)i (v)-5 b(ariable)35 b(length)h(arra)m(y)f(\014eld)g(one)g(can)g(only)h (read)e(as)i(man)m(y)f(elemen)m(ts)h(as)f(actually)0 3068 y(exist)i(in)e(that)i(ro)m(w)e(of)h(the)g(table;)k(reading)c(do)s (es)g(not)g(automatically)i(con)m(tin)m(ue)f(with)f(the)g(next)g(ro)m (w)g(of)g(the)0 3181 y(table)29 b(as)f(o)s(ccurs)g(when)f(reading)h(an) g(ordinary)g(\014xed)f(length)h(table)h(\014eld.)40 b(A)m(ttempts)29 b(to)g(read)f(more)g(than)g(this)0 3294 y(will)k(cause)h(an)e(error)h (status)g(to)g(b)s(e)f(returned.)44 b(One)32 b(can)g(determine)g(the)g (n)m(um)m(b)s(er)e(of)i(elemen)m(ts)h(in)f(eac)m(h)h(ro)m(w)0 3407 y(of)e(a)f(v)-5 b(ariable)31 b(column)g(with)f(the)g(FTGDES)h (subroutine.)0 3859 y Fd(4.10)136 b(Supp)t(ort)44 b(for)h(IEEE)g(Sp)t (ecial)h(V)-11 b(alues)0 4133 y Fi(The)26 b(ANSI/IEEE-754)h (\015oating-p)s(oin)m(t)h(n)m(um)m(b)s(er)d(standard)g(de\014nes)h (certain)h(sp)s(ecial)g(v)-5 b(alues)26 b(that)h(are)g(used)e(to)0 4246 y(represen)m(t)j(suc)m(h)g(quan)m(tities)h(as)f(Not-a-Num)m(b)s (er)h(\(NaN\),)h(denormalized,)f(under\015o)m(w,)e(o)m(v)m(er\015o)m (w,)j(and)d(in\014nit)m(y)-8 b(.)0 4359 y(\(See)31 b(the)g(App)s(endix) d(in)j(the)f(FITS)g(standard)f(or)i(the)g(FITS)e(User's)i(Guide)f(for)g (a)h(list)g(of)g(these)g(v)-5 b(alues\).)41 b(The)0 4472 y(FITSIO)26 b(subroutines)h(that)h(read)f(\015oating)i(p)s(oin)m(t)e (data)i(in)e(FITS)g(\014les)g(recognize)j(these)e(IEEE)e(sp)s(ecial)j (v)-5 b(alues)0 4585 y(and)27 b(b)m(y)h(default)h(in)m(terpret)f(the)h (o)m(v)m(er\015o)m(w)g(and)f(in\014nit)m(y)f(v)-5 b(alues)29 b(as)f(b)s(eing)g(equiv)-5 b(alen)m(t)29 b(to)g(a)g(NaN,)g(and)e(con)m (v)m(ert)0 4698 y(the)37 b(under\015o)m(w)e(and)i(denormalized)g(v)-5 b(alues)37 b(in)m(to)h(zeros.)60 b(In)36 b(some)i(cases)f(programmers)g (ma)m(y)g(w)m(an)m(t)h(access)0 4811 y(to)h(the)g(ra)m(w)f(IEEE)g(v)-5 b(alues,)41 b(without)e(an)m(y)f(mo)s(di\014cation)h(b)m(y)g(FITSIO.)e (This)h(can)g(b)s(e)g(done)g(b)m(y)h(calling)h(the)0 4924 y(FTGPVx)27 b(or)g(FTGCVx)h(routines)f(while)g(sp)s(ecifying)g (0.0)h(as)f(the)g(v)-5 b(alue)28 b(of)f(the)h(NULL)-10 b(V)g(AL)27 b(parameter.)40 b(This)0 5036 y(will)27 b(force)g(FITSIO)e (to)i(simply)f(pass)f(the)i(IEEE)f(v)-5 b(alues)26 b(through)g(to)h (the)f(application)i(program,)f(without)g(an)m(y)0 5149 y(mo)s(di\014cation.)63 b(This)37 b(do)s(es)g(not)h(w)m(ork)g(for)f (double)g(precision)h(v)-5 b(alues)38 b(on)g(V)-10 b(AX/VMS)38 b(mac)m(hines,)i(ho)m(w)m(ev)m(er,)0 5262 y(where)34 b(there)g(is)g(no)g(easy)h(w)m(a)m(y)g(to)g(b)m(ypass)f(the)g(default)h (in)m(terpretation)g(of)g(the)f(IEEE)f(sp)s(ecial)i(v)-5 b(alues.)53 b(This)0 5375 y(is)44 b(also)h(not)f(supp)s(orted)e(when)h (reading)h(\015oating-p)s(oin)m(t)h(images)h(that)e(ha)m(v)m(e)h(b)s (een)e(compressed)h(with)g(the)0 5488 y(FITS)33 b(tiled)h(image)g (compression)f(con)m(v)m(en)m(tion)j(that)e(is)f(discussed)g(in)g (section)h(5.6;)i(the)e(pixels)f(v)-5 b(alues)34 b(in)f(tile)0 5601 y(compressed)d(images)i(are)f(represen)m(ted)g(b)m(y)g(scaled)g (in)m(tegers,)h(and)e(a)i(reserv)m(ed)e(in)m(teger)j(v)-5 b(alue)31 b(\(not)g(a)g(NaN\))h(is)0 5714 y(used)e(to)h(represen)m(t)f (unde\014ned)e(pixels.)p eop end %%Page: 21 27 TeXDict begin 21 26 bop 0 299 a Fg(4.11.)73 b(WHEN)31 b(THE)f(FINAL)g(SIZE)f(OF)i(THE)f(FITS)f(HDU)i(IS)f(UNKNO)m(WN)978 b Fi(21)0 555 y Fd(4.11)136 b(When)44 b(the)h(Final)h(Size)f(of)g(the)g (FITS)f(HDU)h(is)g(Unkno)l(wn)0 805 y Fi(It)27 b(is)h(not)f(required)f (to)i(kno)m(w)f(the)h(total)h(size)f(of)f(a)h(FITS)e(data)i(arra)m(y)g (or)f(table)h(b)s(efore)f(b)s(eginning)f(to)i(write)g(the)0 918 y(data)k(to)f(the)g(FITS)f(\014le.)43 b(In)30 b(the)h(case)h(of)f (the)g(primary)f(arra)m(y)h(or)g(an)f(image)j(extension,)e(one)h (should)d(initially)0 1031 y(create)i(the)e(arra)m(y)h(with)e(the)i (size)g(of)f(the)g(highest)g(dimension)g(\(largest)i(NAXISn)d(k)m(eyw)m (ord\))i(set)g(to)g(a)f(dumm)m(y)0 1144 y(v)-5 b(alue,)26 b(suc)m(h)e(as)g(1.)39 b(Then)23 b(after)i(all)g(the)g(data)f(ha)m(v)m (e)i(b)s(een)d(written)h(and)g(the)g(true)g(dimensions)g(are)g(kno)m (wn,)h(then)0 1257 y(the)31 b(NAXISn)e(v)-5 b(alue)31 b(should)f(b)s(e)g(up)s(dated)f(using)h(the)h(\014ts)p 2051 1257 28 4 v 62 w(up)s(date)p 2389 1257 V 32 w(k)m(ey)h(routine)e (b)s(efore)g(mo)m(ving)i(to)f(another)0 1370 y(extension)g(or)f (closing)i(the)e(FITS)g(\014le.)0 1530 y(When)f(writing)g(to)g(FITS)g (tables,)h(CFITSIO)d(automatically)32 b(k)m(eeps)e(trac)m(k)g(of)f(the) g(highest)h(ro)m(w)f(n)m(um)m(b)s(er)e(that)0 1643 y(is)32 b(written)g(to,)h(and)e(will)h(increase)h(the)f(size)h(of)f(the)g (table)g(if)g(necessary)-8 b(.)46 b(CFITSIO)30 b(will)i(also)h (automatically)0 1756 y(insert)j(space)h(in)f(the)g(FITS)f(\014le)i(if) f(necessary)-8 b(,)39 b(to)e(ensure)e(that)i(the)f(data)h('heap',)h(if) e(it)h(exists,)h(and/or)f(an)m(y)0 1869 y(additional)29 b(HDUs)g(that)g(follo)m(w)g(the)g(table)g(do)f(not)h(get)g(o)m(v)m (erwritten)h(as)e(new)g(ro)m(ws)g(are)h(written)f(to)h(the)g(table.)0 2029 y(As)37 b(a)h(general)g(rule)f(it)h(is)f(b)s(est)g(to)h(sp)s (ecify)f(the)h(initial)g(n)m(um)m(b)s(er)e(of)i(ro)m(ws)f(=)g(0)g(when) g(the)g(table)h(is)g(created,)0 2142 y(then)g(let)h(CFITSIO)e(k)m(eep)i (trac)m(k)g(of)g(the)f(n)m(um)m(b)s(er)f(of)i(ro)m(ws)f(that)h(are)f (actually)i(written.)65 b(The)38 b(application)0 2255 y(program)e(should)f(not)i(man)m(ually)g(up)s(date)e(the)i(n)m(um)m(b)s (er)e(of)h(ro)m(ws)g(in)g(the)h(table)g(\(as)g(giv)m(en)g(b)m(y)f(the)h (NAXIS2)0 2368 y(k)m(eyw)m(ord\))j(since)f(CFITSIO)e(do)s(es)i(this)g (automatically)-8 b(.)69 b(If)38 b(a)i(table)f(is)g(initially)i (created)f(with)e(more)h(than)0 2481 y(zero)i(ro)m(ws,)j(then)c(this)h (will)f(usually)h(b)s(e)f(considered)g(as)h(the)g(minim)m(um)f(size)h (of)g(the)g(table,)j(ev)m(en)d(if)g(few)m(er)0 2594 y(ro)m(ws)30 b(are)g(actually)h(written)f(to)h(the)f(table.)41 b(Th)m(us,)30 b(if)f(a)i(table)f(is)g(initially)h(created)g(with)f(NAXIS2)g(=)g(20,)h (and)0 2706 y(CFITSIO)g(only)i(writes)f(10)i(ro)m(ws)e(of)h(data)g(b)s (efore)f(closing)i(the)f(table,)h(then)e(NAXIS2)h(will)g(remain)f (equal)h(to)0 2819 y(20.)50 b(If)33 b(ho)m(w)m(ev)m(er,)i(30)g(ro)m(ws) e(of)g(data)h(are)g(written)f(to)h(this)f(table,)i(then)e(NAXIS2)h (will)f(b)s(e)g(increased)g(from)g(20)0 2932 y(to)f(30.)44 b(The)31 b(one)g(exception)i(to)f(this)f(automatic)i(up)s(dating)d(of)h (the)h(NAXIS2)f(k)m(eyw)m(ord)h(is)f(if)g(the)h(application)0 3045 y(program)c(directly)g(mo)s(di\014es)f(the)i(v)-5 b(alue)28 b(of)g(NAXIS2)g(\(up)f(or)h(do)m(wn\))g(itself)h(just)e(b)s (efore)h(closing)h(the)f(table.)41 b(In)0 3158 y(this)28 b(case,)i(CFITSIO)d(do)s(es)h(not)h(up)s(date)e(NAXIS2)i(again,)h (since)f(it)g(assumes)f(that)h(the)f(application)i(program)0 3271 y(m)m(ust)i(ha)m(v)m(e)h(had)f(a)g(go)s(o)s(d)g(reason)h(for)f(c)m (hanging)h(the)f(v)-5 b(alue)33 b(directly)-8 b(.)47 b(This)31 b(is)h(not)h(recommended,)f(ho)m(w)m(ev)m(er,)0 3384 y(and)j(is)h(only)g(pro)m(vided)g(for)f(bac)m(kw)m(ard)h (compatibilit)m(y)i(with)e(soft)m(w)m(are)h(that)g(initially)g(creates) g(a)f(table)h(with)0 3497 y(a)d(large)h(n)m(um)m(b)s(er)e(of)h(ro)m (ws,)h(than)f(decreases)g(the)h(NAXIS2)f(v)-5 b(alue)34 b(to)h(the)f(actual)h(smaller)g(v)-5 b(alue)34 b(just)f(b)s(efore)0 3610 y(closing)e(the)g(table.)0 3941 y Fd(4.12)136 b(Lo)t(cal)45 b(FITS)e(Con)l(v)l(en)l(tions)k(supp)t(orted)d(b)l(y)h(FITSIO)0 4191 y Fi(CFITSIO)29 b(supp)s(orts)g(sev)m(eral)j(lo)s(cal)g(FITS)e (con)m(v)m(en)m(tions)i(whic)m(h)f(are)g(not)g(de\014ned)e(in)i(the)f (o\016cial)j(FITS)d(stan-)0 4304 y(dard)43 b(and)g(whic)m(h)g(are)h (not)g(necessarily)g(recognized)h(or)f(supp)s(orted)e(b)m(y)h(other)h (FITS)f(soft)m(w)m(are)i(pac)m(k)-5 b(ages.)0 4417 y(Programmers)36 b(should)f(b)s(e)g(cautious)i(ab)s(out)e(using)h(these)g(features,)i (esp)s(ecially)f(if)f(the)g(FITS)f(\014les)h(that)h(are)0 4530 y(pro)s(duced)31 b(are)i(exp)s(ected)g(to)g(b)s(e)f(pro)s(cessed)g (b)m(y)h(other)f(soft)m(w)m(are)i(systems)f(whic)m(h)f(do)h(not)f(use)h (the)f(CFITSIO)0 4642 y(in)m(terface.)0 4930 y Fb(4.12.1)113 b(Supp)s(ort)37 b(for)h(Long)g(String)f(Keyw)m(ord)h(V)-9 b(alues.)0 5149 y Fi(The)23 b(length)i(of)f(a)g(standard)f(FITS)g (string)h(k)m(eyw)m(ord)g(is)g(limited)h(to)f(68)h(c)m(haracters)g(b)s (ecause)f(it)g(m)m(ust)g(\014t)g(en)m(tirely)0 5262 y(within)35 b(a)h(single)h(FITS)e(header)h(k)m(eyw)m(ord)g(record.)57 b(In)35 b(some)h(instances)g(it)h(is)e(necessary)i(to)f(enco)s(de)g (strings)0 5375 y(longer)27 b(than)f(this)g(limit,)i(so)e(FITSIO)f (supp)s(orts)f(a)j(lo)s(cal)g(con)m(v)m(en)m(tion)h(in)e(whic)m(h)g (the)g(string)g(v)-5 b(alue)27 b(is)f(con)m(tin)m(ued)0 5488 y(o)m(v)m(er)34 b(m)m(ultiple)g(k)m(eyw)m(ords.)49 b(This)32 b(con)m(tin)m(uation)j(con)m(v)m(en)m(tion)h(uses)c(an)h(amp) s(ersand)f(c)m(haracter)i(at)g(the)f(end)g(of)0 5601 y(eac)m(h)c(substring)d(to)i(indicate)h(that)f(it)g(is)g(con)m(tin)m (ued)g(on)f(the)h(next)g(k)m(eyw)m(ord,)h(and)d(the)i(con)m(tin)m (uation)i(k)m(eyw)m(ords)0 5714 y(all)44 b(ha)m(v)m(e)h(the)f(name)f (CONTINUE)g(without)g(an)h(equal)g(sign)f(in)g(column)h(9.)80 b(The)43 b(string)h(v)-5 b(alue)43 b(ma)m(y)i(b)s(e)p eop end %%Page: 22 28 TeXDict begin 22 27 bop 0 299 a Fi(22)1277 b Fg(CHAPTER)29 b(4.)72 b(FITSIO)29 b(CONVENTIONS)g(AND)i(GUIDELINES)0 555 y Fi(con)m(tin)m(ued)e(in)f(this)h(w)m(a)m(y)g(o)m(v)m(er)h(as)e (man)m(y)h(additional)g(CONTINUE)f(k)m(eyw)m(ords)g(as)h(is)f (required.)40 b(The)27 b(follo)m(wing)0 668 y(lines)k(illustrate)g (this)f(con)m(tin)m(uation)j(con)m(v)m(en)m(tion)f(whic)m(h)e(is)h (used)e(in)h(the)h(v)-5 b(alue)31 b(of)f(the)h(STRKEY)e(k)m(eyw)m(ord:) 0 920 y Fe(LONGSTRN=)45 b('OGIP)i(1.0')524 b(/)47 b(The)g(OGIP)g(Long)f (String)g(Convention)f(may)i(be)g(used.)0 1033 y(STRKEY)94 b(=)47 b('This)g(is)g(a)g(very)g(long)g(string)f(keyword&')93 b(/)47 b(Optional)f(Comment)0 1146 y(CONTINUE)93 b(')48 b(value)e(that)h(is)g(continued)e(over)i(3)g(keywords)f(in)h(the)g(&)95 b(')0 1259 y(CONTINUE)e('FITS)47 b(header.')e(/)j(This)e(is)h(another)f (optional)g(comment.)0 1511 y Fi(It)29 b(is)g(recommended)f(that)h(the) g(LONGSTRN)f(k)m(eyw)m(ord,)i(as)f(sho)m(wn)f(here,)h(alw)m(a)m(ys)i(b) s(e)d(included)g(in)g(an)m(y)h(HDU)0 1624 y(that)f(uses)e(this)h (longstring)h(con)m(v)m(en)m(tion.)42 b(A)27 b(subroutine)f(called)i (FTPLSW)f(has)g(b)s(een)f(pro)m(vided)h(in)f(CFITSIO)0 1737 y(to)31 b(write)g(this)f(k)m(eyw)m(ord)h(if)f(it)h(do)s(es)f(not)h (already)g(exist.)0 1897 y(This)23 b(long)i(string)g(con)m(v)m(en)m (tion)h(is)e(supp)s(orted)f(b)m(y)h(the)g(follo)m(wing)i(FITSIO)d (subroutines)g(that)i(deal)g(with)f(string-)0 2010 y(v)-5 b(alued)30 b(k)m(eyw)m(ords:)286 2262 y Fe(ftgkys)46 b(-)i(read)f(a)g(string)f(keyword)286 2375 y(ftpkls)g(-)i(write)e (\(append\))g(a)h(string)f(keyword)286 2488 y(ftikls)g(-)i(insert)e(a)h (string)g(keyword)286 2601 y(ftmkls)f(-)i(modify)e(the)h(value)f(of)h (an)h(existing)d(string)h(keyword)286 2714 y(ftukls)g(-)i(update)e(an)h (existing)f(keyword,)f(or)i(write)g(a)g(new)g(keyword)286 2827 y(ftdkey)f(-)i(delete)e(a)h(keyword)0 3079 y Fi(These)41 b(routines)f(will)h(transparen)m(tly)g(read,)j(write,)g(or)d(delete)h (a)f(long)g(string)g(v)-5 b(alue)41 b(in)g(the)g(FITS)f(\014le,)k(so)0 3192 y(programmers)36 b(in)g(general)h(do)f(not)h(ha)m(v)m(e)g(to)g(b)s (e)f(concerned)g(ab)s(out)g(the)g(details)i(of)e(the)h(con)m(v)m(en)m (tion)h(that)f(is)0 3304 y(used)32 b(to)i(enco)s(de)f(the)g(long)g (string)g(in)g(the)g(FITS)f(header.)48 b(When)33 b(reading)g(a)g(long)h (string,)g(one)f(m)m(ust)g(ensure)0 3417 y(that)h(the)f(c)m(haracter)i (string)f(parameter)g(used)e(in)h(these)h(subroutine)e(calls)j(has)e(b) s(een)f(declared)i(long)g(enough)0 3530 y(to)d(hold)f(the)h(en)m(tire)g (string,)g(otherwise)f(the)h(returned)e(string)h(v)-5 b(alue)31 b(will)g(b)s(e)f(truncated.)0 3690 y(Note)d(that)e(the)h (more)f(commonly)h(used)e(FITSIO)g(subroutine)h(to)h(write)f(string)g (v)-5 b(alued)25 b(k)m(eyw)m(ords)h(\(FTPKYS\))0 3803 y(do)s(es)38 b(NOT)g(supp)s(ort)f(this)h(long)h(string)g(con)m(v)m(en)m (tion)h(and)e(only)h(supp)s(orts)d(strings)i(up)g(to)h(68)g(c)m (haracters)h(in)0 3916 y(length.)i(This)30 b(has)g(b)s(een)g(done)h (delib)s(erately)g(to)h(prev)m(en)m(t)f(programs)g(from)f(inadv)m (erten)m(tly)i(writing)f(k)m(eyw)m(ords)0 4029 y(using)38 b(this)h(non-standard)e(con)m(v)m(en)m(tion)k(without)e(the)f(explicit) i(in)m(ten)m(t)g(of)f(the)g(programmer)f(or)h(user.)64 b(The)0 4142 y(FTPKLS)28 b(subroutine)g(m)m(ust)h(b)s(e)g(called)h (instead)g(to)g(write)f(long)h(strings.)40 b(This)28 b(routine)i(can)f(also)h(b)s(e)f(used)f(to)0 4255 y(write)j(ordinary)e (string)i(v)-5 b(alues)30 b(less)h(than)f(68)h(c)m(haracters)h(in)e (length.)0 4544 y Fb(4.12.2)113 b(Arra)m(ys)37 b(of)g(Fixed-Length)j (Strings)e(in)f(Binary)h(T)-9 b(ables)0 4763 y Fi(CFITSIO)25 b(supp)s(orts)g(2)i(w)m(a)m(ys)g(to)g(sp)s(ecify)f(that)i(a)f(c)m (haracter)h(column)e(in)g(a)h(binary)f(table)i(con)m(tains)f(an)g(arra) m(y)g(of)0 4876 y(\014xed-length)32 b(strings.)46 b(The)32 b(\014rst)f(w)m(a)m(y)-8 b(,)34 b(whic)m(h)e(is)g(o\016cially)i(supp)s (orted)c(b)m(y)i(the)h(FITS)e(Standard)g(do)s(cumen)m(t,)0 4989 y(uses)38 b(the)g(TDIMn)g(k)m(eyw)m(ord.)65 b(F)-8 b(or)39 b(example,)i(if)d(TF)m(ORMn)g(=)g('60A')h(and)f(TDIMn)g(=)g ('\(12,5\)')i(then)e(that)0 5102 y(column)30 b(will)h(b)s(e)f(in)m (terpreted)g(as)h(con)m(taining)h(an)e(arra)m(y)h(of)g(5)f(strings,)h (eac)m(h)g(12)g(c)m(haracters)h(long.)0 5262 y(FITSIO)40 b(also)i(supp)s(orts)d(a)i(lo)s(cal)h(con)m(v)m(en)m(tion)h(for)e(the)g (format)h(of)f(the)g(TF)m(ORMn)g(k)m(eyw)m(ord)g(v)-5 b(alue)42 b(of)f(the)0 5375 y(form)h('rAw')g(where)g('r')g(is)h(an)f (in)m(teger)i(sp)s(ecifying)e(the)g(total)j(width)c(in)h(c)m(haracters) i(of)f(the)f(column,)k(and)0 5488 y('w')36 b(is)g(an)g(in)m(teger)h(sp) s(ecifying)f(the)g(\(\014xed\))g(length)h(of)f(an)g(individual)f(unit)h (string)f(within)h(the)g(v)m(ector.)59 b(F)-8 b(or)0 5601 y(example,)47 b(TF)m(ORM1)d(=)f('120A10')j(w)m(ould)d(indicate)h (that)f(the)h(binary)e(table)i(column)f(is)g(120)h(c)m(haracters)0 5714 y(wide)32 b(and)g(consists)h(of)g(12)g(10-c)m(haracter)i(length)e (strings.)47 b(This)31 b(con)m(v)m(en)m(tion)k(is)d(recognized)i(b)m(y) e(the)h(FITSIO)p eop end %%Page: 23 29 TeXDict begin 23 28 bop 0 299 a Fg(4.12.)73 b(LOCAL)29 b(FITS)h(CONVENTIONS)f(SUPPOR)-8 b(TED)29 b(BY)i(FITSIO)1168 b Fi(23)0 555 y(subroutines)40 b(that)h(read)g(or)g(write)g(strings)f (in)h(binary)f(tables.)73 b(The)40 b(Binary)h(T)-8 b(able)42 b(de\014nition)e(do)s(cumen)m(t)0 668 y(sp)s(eci\014es)31 b(that)i(other)e(optional)i(c)m(haracters)g(ma)m(y)g(follo)m(w)g(the)e (datat)m(yp)s(e)i(co)s(de)f(in)f(the)h(TF)m(ORM)g(k)m(eyw)m(ord,)h(so)0 781 y(this)j(lo)s(cal)i(con)m(v)m(en)m(tion)h(is)e(in)f(compliance)i (with)e(the)h(FITS)f(standard,)h(although)g(other)g(FITS)f(readers)h (are)0 894 y(not)31 b(required)e(to)i(recognize)h(this)f(con)m(v)m(en)m (tion.)0 1183 y Fb(4.12.3)113 b(Keyw)m(ord)37 b(Units)h(Strings)0 1402 y Fi(One)f(de\014ciency)h(of)g(the)g(curren)m(t)g(FITS)f(Standard) f(is)i(that)h(it)f(do)s(es)f(not)h(de\014ne)f(a)i(sp)s(eci\014c)e(con)m (v)m(en)m(tion)j(for)0 1515 y(recording)30 b(the)g(ph)m(ysical)h(units) f(of)g(a)g(k)m(eyw)m(ord)h(v)-5 b(alue.)41 b(The)30 b(TUNITn)f(k)m(eyw) m(ord)h(can)g(b)s(e)g(used)f(to)i(sp)s(ecify)f(the)0 1628 y(ph)m(ysical)36 b(units)f(of)g(the)h(v)-5 b(alues)36 b(in)f(a)g(table)i(column,)f(but)f(there)g(is)h(no)f(analogous)i(con)m (v)m(en)m(tion)g(for)e(k)m(eyw)m(ord)0 1741 y(v)-5 b(alues.)42 b(The)30 b(commen)m(t)h(\014eld)g(of)f(the)h(k)m(eyw)m(ord)g(is)g (often)g(used)f(for)g(this)g(purp)s(ose,)g(but)f(the)i(units)f(are)h (usually)0 1854 y(not)g(sp)s(eci\014ed)e(in)h(a)h(w)m(ell)g(de\014ned)f (format)g(that)h(FITS)f(readers)g(can)h(easily)g(recognize)h(and)e (extract.)0 2014 y(T)-8 b(o)28 b(solv)m(e)h(this)e(de\014ciency)-8 b(,)30 b(FITSIO)c(uses)h(a)h(lo)s(cal)h(con)m(v)m(en)m(tion)h(in)d (whic)m(h)g(the)h(k)m(eyw)m(ord)g(units)f(are)h(enclosed)g(in)0 2127 y(square)20 b(brac)m(k)m(ets)j(as)e(the)f(\014rst)g(tok)m(en)i(in) f(the)f(k)m(eyw)m(ord)i(commen)m(t)f(\014eld;)j(more)d(sp)s (eci\014cally)-8 b(,)24 b(the)d(op)s(ening)f(square)0 2240 y(brac)m(k)m(et)28 b(immediately)g(follo)m(ws)f(the)g(slash)f('/') h(commen)m(t)h(\014eld)e(delimiter)h(and)f(a)g(single)h(space)g(c)m (haracter.)41 b(The)0 2352 y(follo)m(wing)32 b(examples)f(illustrate)g (k)m(eyw)m(ords)g(that)g(use)f(this)g(con)m(v)m(en)m(tion:)0 2602 y Fe(EXPOSURE=)713 b(1800.0)47 b(/)g([s])g(elapsed)f(exposure)f (time)0 2715 y(V_HELIO)h(=)763 b(16.23)47 b(/)g([km)g(s**\(-1\)])e (heliocentric)g(velocity)0 2828 y(LAMBDA)94 b(=)763 b(5400.)47 b(/)g([angstrom])e(central)h(wavelength)0 2941 y(FLUX)190 b(=)47 b(4.9033487787637465E-30)42 b(/)47 b([J/cm**2/s])e(average)h (flux)0 3191 y Fi(In)28 b(general,)h(the)g(units)e(named)h(in)g(the)h (IA)m(U\(1988\))i(St)m(yle)e(Guide)f(are)h(recommended,)f(with)g(the)h (main)f(excep-)0 3304 y(tion)j(that)g(the)f(preferred)g(unit)f(for)i (angle)g(is)f('deg')i(for)e(degrees.)0 3464 y(The)24 b(FTPUNT)g(and)g(FTGUNT)h(subroutines)f(in)g(FITSIO)f(write)i(and)f (read,)i(resp)s(ectiv)m(ely)-8 b(,)28 b(the)c(k)m(eyw)m(ord)h(unit)0 3577 y(strings)30 b(in)g(an)h(existing)g(k)m(eyw)m(ord.)0 3866 y Fb(4.12.4)113 b(HIERAR)m(CH)34 b(Con)m(v)m(en)m(tion)k(for)f (Extended)h(Keyw)m(ord)f(Names)0 4085 y Fi(CFITSIO)k(supp)s(orts)g(the) i(HIERAR)m(CH)g(k)m(eyw)m(ord)g(con)m(v)m(en)m(tion)i(whic)m(h)e(allo)m (ws)h(k)m(eyw)m(ord)f(names)g(that)h(are)0 4198 y(longer)34 b(then)e(8)i(c)m(haracters)g(and)f(ma)m(y)h(con)m(tain)g(the)f(full)g (range)g(of)h(prin)m(table)f(ASCI)s(I)e(text)j(c)m(haracters.)51 b(This)0 4311 y(con)m(v)m(en)m(tion)39 b(w)m(as)f(dev)m(elop)s(ed)f(at) h(the)f(Europ)s(ean)f(Southern)g(Observ)-5 b(atory)37 b(\(ESO\))f(to)i(supp)s(ort)d(hierarc)m(hical)0 4424 y(FITS)30 b(k)m(eyw)m(ord)g(suc)m(h)h(as:)0 4674 y Fe(HIERARCH)46 b(ESO)g(INS)h(FOCU)g(POS)g(=)g(-0.00002500)e(/)j(Focus)e(position)0 4924 y Fi(Basically)-8 b(,)55 b(this)47 b(con)m(v)m(en)m(tion)j(uses)d (the)h(FITS)f(k)m(eyw)m(ord)h('HIERAR)m(CH')h(to)f(indicate)h(that)f (this)f(con)m(v)m(en-)0 5036 y(tion)e(is)f(b)s(eing)g(used,)j(then)d (the)g(actual)i(k)m(eyw)m(ord)e(name)h(\()p Fe('ESO)i(INS)f(FOCU)h (POS')c Fi(in)h(this)g(example\))h(b)s(e-)0 5149 y(gins)40 b(in)f(column)g(10)i(and)e(can)h(con)m(tain)g(an)m(y)g(prin)m(table)g (ASCI)s(I)e(text)j(c)m(haracters,)i(including)d(spaces.)68 b(The)0 5262 y(equals)44 b(sign)h(marks)e(the)h(end)g(of)g(the)g(k)m (eyw)m(ord)h(name)f(and)f(is)i(follo)m(w)m(ed)g(b)m(y)f(the)g(usual)g (v)-5 b(alue)45 b(and)e(com-)0 5375 y(men)m(t)31 b(\014elds)f(just)g (as)h(in)f(standard)g(FITS)g(k)m(eyw)m(ords.)41 b(F)-8 b(urther)30 b(details)i(of)f(this)f(con)m(v)m(en)m(tion)j(are)e (describ)s(ed)e(at)0 5488 y(h)m(ttp://\014ts.gsfc.nasa.go)m (v/registry/hierarc)m(h)p 1659 5488 28 4 v 38 w(k)m(eyw)m(ord.h)m(tml)f (and)f(in)g(Section)g(4.4)h(of)g(the)f(ESO)f(Data)j(In)m(ter-)0 5601 y(face)c(Con)m(trol)f(Do)s(cumen)m(t)h(that)g(is)f(link)m(ed)g(to) g(from)g(h)m(ttp://arc)m(hiv)m(e.eso.org/cms/to)s(ols-)q(do)s(cumen)m (tati)q(on/eso)q(-)0 5714 y(data-in)m(terface-con)m(trol.h)m(tml.)p eop end %%Page: 24 30 TeXDict begin 24 29 bop 0 299 a Fi(24)1277 b Fg(CHAPTER)29 b(4.)72 b(FITSIO)29 b(CONVENTIONS)g(AND)i(GUIDELINES)0 555 y Fi(This)43 b(con)m(v)m(en)m(tion)k(allo)m(ws)f(a)e(m)m(uc)m(h)h (broader)e(range)i(of)f(k)m(eyw)m(ord)h(names)f(than)h(is)f(allo)m(w)m (ed)i(b)m(y)e(the)h(FITS)0 668 y(Standard.)40 b(Here)30 b(are)h(more)g(examples)g(of)f(suc)m(h)g(k)m(eyw)m(ords:)0 941 y Fe(HIERARCH)46 b(LongKeyword)e(=)k(47.5)e(/)i(Keyword)e(has)h(>)g (8)g(characters,)e(and)i(mixed)f(case)0 1054 y(HIERARCH)g(XTE$TEMP)f(=) j(98.6)e(/)i(Keyword)d(contains)h(the)h('$')g(character)0 1167 y(HIERARCH)f(Earth)g(is)h(a)h(star)e(=)i(F)f(/)h(Keyword)d (contains)h(embedded)f(spaces)0 1440 y Fi(CFITSIO)40 b(will)i(transparen)m(tly)g(read)g(and)f(write)g(these)i(k)m(eyw)m (ords,)i(so)d(application)h(programs)e(do)g(not)h(in)0 1553 y(general)33 b(need)f(to)h(kno)m(w)f(an)m(ything)h(ab)s(out)f(the) g(sp)s(eci\014c)g(implemen)m(tation)i(details)f(of)g(the)f(HIERAR)m(CH) g(con-)0 1666 y(v)m(en)m(tion.)50 b(In)32 b(particular,)j(application)f (programs)e(do)h(not)h(need)e(to)i(sp)s(ecify)f(the)g(`HIERAR)m(CH')h (part)f(of)g(the)0 1779 y(k)m(eyw)m(ord)g(name)f(when)g(reading)g(or)g (writing)h(k)m(eyw)m(ords)f(\(although)h(it)g(ma)m(y)g(b)s(e)f (included)f(if)i(desired\).)46 b(When)0 1892 y(writing)35 b(a)g(k)m(eyw)m(ord,)h(CFITSIO)d(\014rst)h(c)m(hec)m(ks)i(to)f(see)g (if)g(the)g(k)m(eyw)m(ord)g(name)f(is)h(legal)h(as)f(a)g(standard)f (FITS)0 2005 y(k)m(eyw)m(ord)k(\(no)g(more)f(than)h(8)g(c)m(haracters)h (long)f(and)f(con)m(taining)i(only)e(letters,)k(digits,)f(or)e(a)g(min) m(us)e(sign)i(or)0 2117 y(underscore\).)68 b(If)39 b(so)h(it)g(writes)g (it)g(as)f(a)h(standard)f(FITS)g(k)m(eyw)m(ord,)k(otherwise)d(it)g (uses)f(the)h(hierarc)m(h)f(con-)0 2230 y(v)m(en)m(tion)34 b(to)f(write)g(the)f(k)m(eyw)m(ord.)48 b(The)32 b(maxim)m(um)g(k)m(eyw) m(ord)h(name)f(length)h(is)g(67)g(c)m(haracters,)i(whic)m(h)d(lea)m(v)m (es)0 2343 y(only)c(1)h(space)g(for)f(the)h(v)-5 b(alue)29 b(\014eld.)39 b(A)29 b(more)f(practical)i(limit)f(is)g(ab)s(out)f(40)h (c)m(haracters,)i(whic)m(h)d(lea)m(v)m(es)i(enough)0 2456 y(ro)s(om)e(for)h(most)f(k)m(eyw)m(ord)h(v)-5 b(alues.)41 b(CFITSIO)27 b(returns)g(an)h(error)h(if)f(there)h(is)f(not)h(enough)f (ro)s(om)h(for)f(b)s(oth)g(the)0 2569 y(k)m(eyw)m(ord)k(name)f(and)f (the)i(k)m(eyw)m(ord)f(v)-5 b(alue)32 b(on)f(the)h(80-c)m(haracter)h (card,)f(except)g(for)f(string-v)-5 b(alued)32 b(k)m(eyw)m(ords)0 2682 y(whic)m(h)h(are)g(simply)f(truncated)h(so)g(that)h(the)f(closing) h(quote)g(c)m(haracter)g(falls)f(in)g(column)g(80.)49 b(In)32 b(the)h(curren)m(t)0 2795 y(implemen)m(tation,)e(CFITSIO)c (preserv)m(es)i(the)g(case)h(of)f(the)g(letters)h(when)e(writing)h(the) g(k)m(eyw)m(ord)g(name,)g(but)f(it)0 2908 y(is)d(case-insensitiv)m(e)i (when)d(reading)h(or)g(searc)m(hing)h(for)f(a)g(k)m(eyw)m(ord.)40 b(The)24 b(curren)m(t)h(implemen)m(tation)h(allo)m(ws)h(an)m(y)0 3021 y(ASCI)s(I)i(text)j(c)m(haracter)h(\(ASCI)s(I)c(32)j(to)f(ASCI)s (I)f(126\))i(in)f(the)g(k)m(eyw)m(ord)g(name)g(except)h(for)e(the)h ('=')g(c)m(haracter.)0 3134 y(A)f(space)h(is)g(also)g(required)f(on)g (either)h(side)f(of)h(the)f(equal)h(sign.)0 3483 y Fd(4.13)136 b(Optimizing)45 b(Co)t(de)g(for)h(Maxim)l(um)f(Pro)t(cessing)g(Sp)t (eed)0 3736 y Fi(CFITSIO)22 b(has)h(b)s(een)f(carefully)i(designed)f (to)h(obtain)g(the)f(highest)h(p)s(ossible)e(sp)s(eed)h(when)f(reading) h(and)g(writing)0 3849 y(FITS)33 b(\014les.)51 b(In)33 b(order)h(to)g(ac)m(hiev)m(e)i(the)e(b)s(est)g(p)s(erformance,)g(ho)m (w)m(ev)m(er,)i(application)g(programmers)d(m)m(ust)h(b)s(e)0 3962 y(careful)24 b(to)h(call)g(the)f(CFITSIO)f(routines)g (appropriately)i(and)e(in)h(an)f(e\016cien)m(t)j(sequence;)h (inappropriate)c(usage)0 4075 y(of)31 b(CFITSIO)d(routines)j(can)f (greatly)i(slo)m(w)f(do)m(wn)f(the)h(execution)g(sp)s(eed)f(of)g(a)h (program.)0 4235 y(The)f(maxim)m(um)h(p)s(ossible)f(I/O)h(sp)s(eed)f (of)h(CFITSIO)e(dep)s(ends)g(of)i(course)g(on)f(the)h(t)m(yp)s(e)g(of)g (computer)g(system)0 4348 y(that)j(it)g(is)g(running)d(on.)50 b(T)-8 b(o)34 b(get)h(a)f(general)g(idea)g(of)g(what)f(data)i(I/O)e(sp) s(eeds)f(are)i(p)s(ossible)f(on)h(a)g(particular)0 4461 y(mac)m(hine,)j(build)e(the)g(sp)s(eed.c)g(program)g(that)h(is)g (distributed)e(with)h(CFITSIO)f(\(t)m(yp)s(e)i('mak)m(e)g(sp)s(eed')f (in)g(the)0 4574 y(CFITSIO)e(directory\).)54 b(This)33 b(diagnostic)j(program)e(measures)h(the)f(sp)s(eed)g(of)g(writing)h (and)f(reading)g(bac)m(k)i(a)0 4687 y(test)31 b(FITS)f(image,)i(a)f (binary)e(table,)j(and)d(an)i(ASCI)s(I)e(table.)0 4847 y(The)k(follo)m(wing)h(2)g(sections)g(pro)m(vide)g(some)f(bac)m (kground)g(on)h(ho)m(w)f(CFITSIO)f(in)m(ternally)i(manages)g(the)f (data)0 4960 y(I/O)g(and)g(describ)s(es)f(some)i(strategies)h(that)f (ma)m(y)g(b)s(e)e(used)h(to)h(optimize)g(the)g(pro)s(cessing)f(sp)s (eed)f(of)h(soft)m(w)m(are)0 5073 y(that)e(uses)f(CFITSIO.)0 5379 y Fb(4.13.1)113 b(Bac)m(kground)38 b(Information:)50 b(Ho)m(w)37 b(CFITSIO)h(Manages)h(Data)f(I/O)0 5601 y Fi(Man)m(y)22 b(CFITSIO)e(op)s(erations)i(in)m(v)m(olv)m(e)i (transferring)d(only)h(a)g(small)g(n)m(um)m(b)s(er)f(of)h(b)m(ytes)g (to)g(or)g(from)f(the)h(FITS)f(\014le)0 5714 y(\(e.g,)31 b(reading)e(a)g(k)m(eyw)m(ord,)h(or)f(writing)g(a)g(ro)m(w)g(in)f(a)h (table\);)i(it)f(w)m(ould)e(b)s(e)g(v)m(ery)i(ine\016cien)m(t)g(to)f (ph)m(ysically)h(read)p eop end %%Page: 25 31 TeXDict begin 25 30 bop 0 299 a Fg(4.13.)73 b(OPTIMIZING)29 b(CODE)h(F)m(OR)h(MAXIMUM)g(PR)m(OCESSING)f(SPEED)971 b Fi(25)0 555 y(or)32 b(write)h(suc)m(h)f(small)g(blo)s(c)m(ks)h(of)f (data)h(directly)g(in)f(the)g(FITS)g(\014le)g(on)g(disk,)h(therefore)f (CFITSIO)f(main)m(tains)0 668 y(a)38 b(set)g(of)g(in)m(ternal)h (Input{Output)c(\(IO\))j(bu\013ers)f(in)g(RAM)h(memory)g(that)g(eac)m (h)h(con)m(tain)g(one)f(FITS)f(blo)s(c)m(k)0 781 y(\(2880)27 b(b)m(ytes\))f(of)f(data.)40 b(Whenev)m(er)25 b(CFITSIO)f(needs)g(to)i (access)g(data)g(in)f(the)g(FITS)f(\014le,)j(it)e(\014rst)f(transfers)h (the)0 894 y(FITS)30 b(blo)s(c)m(k)h(con)m(taining)h(those)f(b)m(ytes)g (in)m(to)g(one)g(of)f(the)h(IO)f(bu\013ers)f(in)h(memory)-8 b(.)42 b(The)30 b(next)g(time)h(CFITSIO)0 1007 y(needs)36 b(to)g(access)i(b)m(ytes)e(in)g(the)g(same)h(blo)s(c)m(k)f(it)h(can)f (then)g(go)h(to)f(the)h(fast)f(IO)f(bu\013er)g(rather)h(than)g(using)g (a)0 1120 y(m)m(uc)m(h)c(slo)m(w)m(er)i(system)e(disk)g(access)h (routine.)46 b(The)32 b(n)m(um)m(b)s(er)f(of)h(a)m(v)-5 b(ailable)35 b(IO)d(bu\013ers)f(is)h(determined)g(b)m(y)g(the)0 1233 y(NIOBUF)f(parameter)g(\(in)f(\014tsio2.h\))h(and)f(is)h(curren)m (tly)f(set)h(to)g(40.)0 1393 y(Whenev)m(er)24 b(CFITSIO)f(reads)g(or)h (writes)g(data)g(it)h(\014rst)e(c)m(hec)m(ks)i(to)g(see)f(if)g(that)g (blo)s(c)m(k)h(of)f(the)g(FITS)f(\014le)g(is)h(already)0 1506 y(loaded)33 b(in)m(to)g(one)f(of)g(the)g(IO)g(bu\013ers.)44 b(If)32 b(not,)h(and)e(if)h(there)g(is)g(an)g(empt)m(y)h(IO)e(bu\013er) g(a)m(v)-5 b(ailable,)35 b(then)d(it)h(will)0 1619 y(load)g(that)h(blo) s(c)m(k)f(in)m(to)g(the)g(IO)g(bu\013er)e(\(when)h(reading)h(a)g(FITS)f (\014le\))h(or)g(will)g(initialize)i(a)e(new)f(blo)s(c)m(k)i(\(when)0 1732 y(writing)j(to)h(a)g(FITS)f(\014le\).)62 b(If)37 b(all)h(the)g(IO)e(bu\013ers)h(are)g(already)h(full,)h(it)f(m)m(ust)g (decide)f(whic)m(h)g(one)h(to)g(reuse)0 1844 y(\(generally)c(the)f(one) g(that)g(has)f(b)s(een)g(accessed)i(least)f(recen)m(tly\),)i(and)d (\015ush)f(the)i(con)m(ten)m(ts)h(bac)m(k)g(to)f(disk)f(if)g(it)0 1957 y(has)e(b)s(een)g(mo)s(di\014ed)f(b)s(efore)h(loading)h(the)g(new) f(blo)s(c)m(k.)0 2118 y(The)g(one)g(ma)5 b(jor)30 b(exception)i(to)f (the)f(ab)s(o)m(v)m(e)h(pro)s(cess)f(o)s(ccurs)g(whenev)m(er)g(a)g (large)i(con)m(tiguous)f(set)g(of)f(b)m(ytes)h(are)0 2230 y(accessed,)37 b(as)d(migh)m(t)i(o)s(ccur)e(when)f(reading)i(or)f (writing)g(a)h(FITS)f(image.)54 b(In)34 b(this)g(case)h(CFITSIO)e(b)m (ypasses)0 2343 y(the)i(in)m(ternal)h(IO)f(bu\013ers)f(and)g(simply)h (reads)g(or)g(writes)h(the)f(desired)g(b)m(ytes)g(directly)h(in)f(the)g (disk)g(\014le)g(with)0 2456 y(a)i(single)g(call)g(to)g(a)g(lo)m(w-lev) m(el)i(\014le)d(read)g(or)h(write)f(routine.)58 b(The)36 b(minim)m(um)g(threshold)f(for)h(the)h(n)m(um)m(b)s(er)e(of)0 2569 y(b)m(ytes)27 b(to)g(read)f(or)g(write)g(this)g(w)m(a)m(y)i(is)e (set)g(b)m(y)h(the)f(MINDIRECT)g(parameter)g(and)g(is)g(curren)m(tly)g (set)h(to)g(3)g(FITS)0 2682 y(blo)s(c)m(ks)36 b(=)g(8640)i(b)m(ytes.)58 b(This)35 b(is)h(the)g(most)g(e\016cien)m(t)i(w)m(a)m(y)f(to)g(read)e (or)h(write)h(large)g(c)m(h)m(unks)e(of)h(data.)59 b(Note)0 2795 y(that)34 b(this)f(fast)h(direct)g(IO)f(pro)s(cess)f(is)i(not)f (applicable)i(when)d(accessing)j(columns)e(of)h(data)g(in)f(a)g(FITS)g (table)0 2908 y(b)s(ecause)f(the)h(b)m(ytes)g(are)g(generally)g(not)g (con)m(tiguous)g(since)g(they)g(are)f(in)m(terlea)m(v)m(ed)j(b)m(y)e (the)f(other)h(columns)f(of)0 3021 y(data)i(in)e(the)h(table.)49 b(This)33 b(explains)g(wh)m(y)f(the)h(sp)s(eed)f(for)h(accessing)h (FITS)e(tables)i(is)f(generally)h(slo)m(w)m(er)g(than)0 3134 y(accessing)e(FITS)e(images.)0 3294 y(Giv)m(en)i(this)g(bac)m (kground)f(information,)h(the)g(general)g(strategy)h(for)e(e\016cien)m (tly)i(accessing)g(FITS)e(\014les)g(should)0 3407 y(no)m(w)36 b(b)s(e)g(apparen)m(t:)52 b(when)35 b(dealing)i(with)f(FITS)g(images,)j (read)d(or)g(write)g(large)i(c)m(h)m(unks)e(of)g(data)h(at)g(a)f(time)0 3520 y(so)30 b(that)h(the)f(direct)h(IO)e(mec)m(hanism)h(will)h(b)s(e)e (in)m(v)m(ok)m(ed;)j(when)d(accessing)j(FITS)d(headers)h(or)g(FITS)f (tables,)i(on)0 3633 y(the)k(other)g(hand,)g(once)g(a)g(particular)h (FITS)e(blo)s(c)m(k)h(has)f(b)s(een)g(loading)i(in)m(to)g(one)f(of)g (the)f(IO)h(bu\013ers,)g(try)f(to)0 3745 y(access)39 b(all)f(the)f(needed)g(information)h(in)f(that)h(blo)s(c)m(k)g(b)s (efore)f(it)h(gets)g(\015ushed)d(out)j(of)g(the)f(IO)g(bu\013er.)60 b(It)38 b(is)0 3858 y(imp)s(ortan)m(t)31 b(to)h(a)m(v)m(oid)g(the)f (situation)h(where)f(the)g(same)g(FITS)f(blo)s(c)m(k)i(is)f(b)s(eing)f (read)h(then)g(\015ushed)e(from)h(a)h(IO)0 3971 y(bu\013er)e(m)m (ultiple)i(times.)0 4131 y(The)f(follo)m(wing)i(section)f(giv)m(es)h (more)e(sp)s(eci\014c)h(suggestions)g(for)f(optimizing)i(the)e(use)g (of)h(CFITSIO.)0 4430 y Fb(4.13.2)113 b(Optimization)38 b(Strategies)0 4650 y Fi(1.)43 b(Because)32 b(the)f(data)g(in)g(FITS)f (\014les)h(is)g(alw)m(a)m(ys)h(stored)f(in)g("big-endian")h(b)m(yte)f (order,)g(where)f(the)h(\014rst)f(b)m(yte)0 4763 y(of)g(n)m(umeric)h(v) -5 b(alues)30 b(con)m(tains)i(the)e(most)h(signi\014can)m(t)g(bits)f (and)g(the)g(last)i(b)m(yte)e(con)m(tains)i(the)e(least)i(signi\014can) m(t)0 4876 y(bits,)e(CFITSIO)f(m)m(ust)h(sw)m(ap)g(the)g(order)f(of)h (the)h(b)m(ytes)f(when)f(reading)h(or)g(writing)g(FITS)g(\014les)g (when)f(running)0 4989 y(on)k(little-endian)i(mac)m(hines)f(\(e.g.,)i (Lin)m(ux)d(and)g(Microsoft)i(Windo)m(ws)e(op)s(erating)h(systems)g (running)d(on)j(PCs)0 5102 y(with)c(x86)h(CPUs\).)0 5262 y(On)i(fairly)h(new)f(CPUs)g(that)i(supp)s(ort)d("SSSE3")h(mac)m(hine)h (instructions)g(\(e.g.,)i(starting)f(with)e(In)m(tel)i(Core)f(2)0 5375 y(CPUs)21 b(in)h(2007,)j(and)d(in)f(AMD)i(CPUs)e(b)s(eginning)g (in)h(2011\))i(signi\014can)m(tly)f(faster)f(4-b)m(yte)h(and)e(8-b)m (yte)i(sw)m(apping)0 5488 y(algorithms)k(are)g(a)m(v)-5 b(ailable.)42 b(These)26 b(faster)h(b)m(yte)g(sw)m(apping)f(functions)g (are)h(not)g(used)e(b)m(y)i(default)f(in)g(CFITSIO)0 5601 y(\(b)s(ecause)c(of)f(the)h(p)s(oten)m(tial)g(co)s(de)g(p)s (ortablilit)m(y)g(issues\),)i(but)c(users)h(can)g(enable)h(them)f(on)h (supp)s(orted)d(platforms)0 5714 y(b)m(y)38 b(adding)f(the)h (appropriate)f(compiler)i(\015ags)e(\(-mssse3)i(with)e(gcc)i(or)f(icc)g (on)g(lin)m(ux\))g(when)e(compiling)j(the)p eop end %%Page: 26 32 TeXDict begin 26 31 bop 0 299 a Fi(26)1277 b Fg(CHAPTER)29 b(4.)72 b(FITSIO)29 b(CONVENTIONS)g(AND)i(GUIDELINES)0 555 y Fi(sw)m(appro)s(c.c)f(source)g(\014le,)g(whic)m(h)g(will)g(allo)m (w)i(the)e(compiler)g(to)h(generate)h(co)s(de)e(using)f(the)h(SSSE3)f (instruction)0 668 y(set.)41 b(A)28 b(con)m(v)m(enien)m(t)i(w)m(a)m(y)f (to)g(do)g(this)f(is)g(to)h(con\014gure)f(the)g(CFITSIO)f(library)h (with)g(the)g(follo)m(wing)i(command:)95 894 y Fe(>)96 b(./configure)44 b(--enable-ssse3)0 1121 y Fi(Note,)37 b(ho)m(w)m(ev)m(er,)h(that)d(a)g(binary)f(executable)j(\014le)e(that)g (is)g(created)h(using)e(these)h(faster)g(functions)g(will)g(only)0 1233 y(run)c(on)h(mac)m(hines)g(that)h(supp)s(ort)d(the)i(SSSE3)f(mac)m (hine)i(instructions.)45 b(It)33 b(will)f(crash)g(on)g(mac)m(hines)g (that)h(do)0 1346 y(not)e(supp)s(ort)d(them.)0 1507 y(F)-8 b(or)36 b(faster)f(2-b)m(yte)i(sw)m(aps)e(on)g(virtually)g(all)h (x86-64)h(CPUs)e(\(ev)m(en)h(those)g(that)f(do)g(not)h(supp)s(ort)d (SSSE3\),)j(a)0 1619 y(v)-5 b(arian)m(t)26 b(using)e(only)g(SSE2)g (instructions)h(exists.)39 b(SSE2)24 b(is)h(enabled)f(b)m(y)h(default)g (on)f(x86)p 3066 1619 28 4 v 34 w(64)h(CPUs)f(with)h(64-bit)0 1732 y(op)s(erating)30 b(systems)f(\(and)g(is)g(also)i(automatically)h (enabled)d(b)m(y)g(the)g({enable-ssse3)i(\015ag\).)41 b(When)30 b(running)d(on)0 1845 y(x86)p 143 1845 V 34 w(64)k(CPUs)g(with)f(32-bit)i(op)s(erating)g(systems,)f(these)g(faster) h(2-b)m(yte)g(sw)m(apping)f(algorithms)g(are)h(not)f(used)0 1958 y(b)m(y)f(default)h(in)f(CFITSIO,)f(but)h(can)g(b)s(e)g(enabled)g (explicitly)i(with:)0 2184 y Fe(./configure)45 b(--enable-sse2)0 2411 y Fi(Preliminary)f(testing)h(indicates)g(that)g(these)f(SSSE3)f (and)g(SSE2)g(based)h(b)m(yte-sw)m(apping)h(algorithms)g(can)0 2524 y(b)s(o)s(ost)31 b(the)h(CFITSIO)e(p)s(erformance)h(when)f (reading)i(or)f(writing)h(FITS)f(images)h(b)m(y)g(20\045)g(-)g(30\045)g (or)f(more.)45 b(It)0 2636 y(is)36 b(imp)s(ortan)m(t)g(to)g(note,)i(ho) m(w)m(ev)m(er,)h(that)d(compiler)g(optimization)i(m)m(ust)e(b)s(e)f (turned)f(on)i(\(e.g.,)j(b)m(y)d(using)f(the)0 2749 y(-O1)f(or)g(-O2)g (\015ags)g(in)g(gcc\))h(when)e(building)g(programs)h(that)g(use)g (these)g(fast)g(b)m(yte-sw)m(apping)h(algorithms)f(in)0 2862 y(order)d(to)h(reap)f(the)h(full)f(b)s(ene\014t)g(of)g(the)h (SSSE3)e(and)h(SSE2)g(instructions;)h(without)f(optimization,)j(the)e (co)s(de)0 2975 y(ma)m(y)f(actually)h(run)d(slo)m(w)m(er)i(than)f(when) g(using)g(more)g(traditional)i(b)m(yte-sw)m(apping)f(tec)m(hniques.)0 3135 y(2.)54 b(When)34 b(dealing)h(with)g(a)g(FITS)e(primary)h(arra)m (y)h(or)g(IMA)m(GE)g(extension,)i(it)e(is)f(more)h(e\016cien)m(t)h(to)f (read)g(or)0 3248 y(write)c(large)g(c)m(h)m(unks)f(of)g(the)h(image)g (at)h(a)e(time)h(\(at)h(least)f(3)g(FITS)f(blo)s(c)m(ks)g(=)g(8640)i(b) m(ytes\))f(so)g(that)g(the)f(direct)0 3361 y(IO)j(mec)m(hanism)h(will)f (b)s(e)g(used)g(as)g(describ)s(ed)g(in)g(the)g(previous)g(section.)51 b(Smaller)34 b(c)m(h)m(unks)f(of)g(data)h(are)g(read)0 3474 y(or)d(written)g(via)h(the)f(IO)f(bu\013ers,)g(whic)m(h)h(is)g (somewhat)g(less)g(e\016cien)m(t)i(b)s(ecause)e(of)g(the)g(extra)h(cop) m(y)f(op)s(eration)0 3587 y(and)26 b(additional)h(b)s(o)s(okk)m(eeping) g(steps)g(that)g(are)g(required.)39 b(In)26 b(principle)g(it)h(is)g (more)f(e\016cien)m(t)i(to)g(read)e(or)h(write)0 3700 y(as)i(big)g(an)g(arra)m(y)h(of)f(image)h(pixels)f(at)h(one)f(time)g (as)h(p)s(ossible,)f(ho)m(w)m(ev)m(er,)h(if)f(the)h(arra)m(y)f(b)s (ecomes)g(so)g(large)h(that)0 3813 y(the)i(op)s(erating)g(system)f (cannot)h(store)g(it)g(all)h(in)e(RAM,)h(then)f(the)h(p)s(erformance)f (ma)m(y)h(b)s(e)f(degraded)g(b)s(ecause)0 3926 y(of)g(the)f(increased)h (sw)m(apping)f(of)g(virtual)h(memory)f(to)h(disk.)0 4086 y(3.)51 b(When)33 b(dealing)i(with)e(FITS)g(tables,)j(the)e(most)g(imp) s(ortan)m(t)g(e\016ciency)g(factor)h(in)e(the)h(soft)m(w)m(are)h (design)f(is)0 4199 y(to)j(read)f(or)g(write)g(the)g(data)h(in)f(the)g (FITS)g(\014le)g(in)g(a)g(single)h(pass)f(through)f(the)h(\014le.)58 b(An)36 b(example)h(of)f(p)s(o)s(or)0 4312 y(program)g(design)h(w)m (ould)f(b)s(e)g(to)h(read)g(a)f(large,)k(3-column)d(table)g(b)m(y)g (sequen)m(tially)h(reading)f(the)f(en)m(tire)i(\014rst)0 4425 y(column,)25 b(then)f(going)h(bac)m(k)f(to)h(read)e(the)h(2nd)g (column,)h(and)e(\014nally)h(the)g(3rd)f(column;)j(this)e(ob)m(viously) g(requires)0 4538 y(3)h(passes)f(through)f(the)i(\014le)f(whic)m(h)g (could)h(triple)f(the)h(execution)g(time)g(of)g(an)f(I/O)g(limited)h (program.)38 b(F)-8 b(or)25 b(small)0 4650 y(tables)31 b(this)f(is)h(not)f(imp)s(ortan)m(t,)h(but)f(when)f(reading)h(m)m (ulti-megab)m(yte)j(sized)e(tables)g(these)g(ine\016ciencies)h(can)0 4763 y(b)s(ecome)d(signi\014can)m(t.)41 b(The)28 b(more)h(e\016cien)m (t)h(pro)s(cedure)d(in)i(this)f(case)i(is)e(to)i(read)e(or)h(write)g (only)f(as)h(man)m(y)g(ro)m(ws)0 4876 y(of)g(the)g(table)h(as)f(will)h (\014t)e(in)m(to)i(the)g(a)m(v)-5 b(ailable)31 b(in)m(ternal)f(I/O)f (bu\013ers,)f(then)h(access)h(all)g(the)f(necessary)g(columns)0 4989 y(of)i(data)h(within)e(that)i(range)f(of)g(ro)m(ws.)43 b(Then)29 b(after)j(the)f(program)g(is)g(completely)h(\014nished)e (with)g(the)i(data)f(in)0 5102 y(those)i(ro)m(ws)e(it)i(can)f(mo)m(v)m (e)i(on)e(to)g(the)h(next)f(range)g(of)g(ro)m(ws)g(that)h(will)f(\014t) g(in)g(the)g(bu\013ers,)f(con)m(tin)m(uing)i(in)f(this)0 5215 y(w)m(a)m(y)c(un)m(til)f(the)f(en)m(tire)i(\014le)f(has)f(b)s(een) g(pro)s(cessed.)39 b(By)27 b(using)f(this)h(pro)s(cedure)e(of)i (accessing)h(all)g(the)e(columns)h(of)0 5328 y(a)j(table)g(in)f (parallel)h(rather)f(than)g(sequen)m(tially)-8 b(,)32 b(eac)m(h)e(blo)s(c)m(k)g(of)g(the)f(FITS)g(\014le)g(will)g(only)h(b)s (e)e(read)i(or)f(written)0 5441 y(once.)0 5601 y(The)g(optimal)h(n)m (um)m(b)s(er)e(of)i(ro)m(ws)f(to)i(read)e(or)g(write)h(at)g(one)g(time) g(in)f(a)h(giv)m(en)g(table)h(dep)s(ends)c(on)j(the)f(width)g(of)0 5714 y(the)j(table)h(ro)m(w,)g(on)f(the)g(n)m(um)m(b)s(er)f(of)h(I/O)g (bu\013ers)f(that)i(ha)m(v)m(e)g(b)s(een)e(allo)s(cated)j(in)e(FITSIO,) f(and)h(also)h(on)f(the)p eop end %%Page: 27 33 TeXDict begin 27 32 bop 0 299 a Fg(4.13.)73 b(OPTIMIZING)29 b(CODE)h(F)m(OR)h(MAXIMUM)g(PR)m(OCESSING)f(SPEED)971 b Fi(27)0 555 y(n)m(um)m(b)s(er)27 b(of)i(other)f(FITS)g(\014les)g (that)h(are)g(op)s(en)f(at)h(the)g(same)g(time)g(\(since)g(one)g(I/O)f (bu\013er)f(is)i(alw)m(a)m(ys)h(reserv)m(ed)0 668 y(for)k(eac)m(h)h(op) s(en)f(FITS)f(\014le\).)53 b(F)-8 b(ortunately)g(,)37 b(a)e(FITSIO)e(routine)h(is)h(a)m(v)-5 b(ailable)36 b(that)f(will)f (return)g(the)g(optimal)0 781 y(n)m(um)m(b)s(er)e(of)i(ro)m(ws)g(for)g (a)g(giv)m(en)g(table:)49 b(call)35 b(ftgrsz\(unit,)g(nro)m(ws,)f (status\).)52 b(It)34 b(is)g(not)g(critical)h(to)g(use)e(exactly)0 894 y(the)f(v)-5 b(alue)32 b(of)f(nro)m(ws)g(returned)g(b)m(y)g(this)g (routine,)h(as)g(long)g(as)g(one)g(do)s(es)f(not)h(exceed)g(it.)45 b(Using)32 b(a)g(v)m(ery)f(small)0 1007 y(v)-5 b(alue)32 b(ho)m(w)m(ev)m(er)i(can)e(also)h(lead)f(to)h(p)s(o)s(or)e(p)s (erformance)g(b)s(ecause)h(of)g(the)g(o)m(v)m(erhead)h(from)f(the)g (larger)g(n)m(um)m(b)s(er)0 1120 y(of)f(subroutine)e(calls.)0 1280 y(The)36 b(optimal)h(n)m(um)m(b)s(er)f(of)g(ro)m(ws)h(returned)e (b)m(y)h(ftgrsz)h(is)g(v)-5 b(alid)37 b(only)f(as)h(long)g(as)g(the)f (application)i(program)0 1393 y(is)c(only)h(reading)g(or)f(writing)g (data)h(in)g(the)f(sp)s(eci\014ed)g(table.)54 b(An)m(y)34 b(other)h(calls)g(to)g(access)h(data)f(in)f(the)h(table)0 1506 y(header)26 b(w)m(ould)f(cause)i(additional)f(blo)s(c)m(ks)h(of)f (data)g(to)h(b)s(e)e(loaded)h(in)m(to)h(the)f(I/O)g(bu\013ers)f (displacing)h(data)g(from)0 1619 y(the)j(original)h(table,)g(and)e (should)f(b)s(e)h(a)m(v)m(oided)i(during)e(the)h(critical)h(p)s(erio)s (d)e(while)g(the)h(table)h(is)e(b)s(eing)g(read)h(or)0 1732 y(written.)0 1892 y(4.)39 b(Use)24 b(binary)f(table)h(extensions)g (rather)f(than)h(ASCI)s(I)e(table)i(extensions)g(for)f(b)s(etter)h (e\016ciency)h(when)d(dealing)0 2005 y(with)37 b(tabular)h(data.)62 b(The)37 b(I/O)g(to)h(ASCI)s(I)e(tables)i(is)g(slo)m(w)m(er)g(b)s (ecause)g(of)f(the)h(o)m(v)m(erhead)h(in)e(formatting)h(or)0 2118 y(parsing)30 b(the)h(ASCI)s(I)f(data)h(\014elds,)g(and)f(b)s (ecause)h(ASCI)s(I)e(tables)i(are)g(ab)s(out)g(t)m(wice)h(as)f(large)h (as)f(binary)f(tables)0 2230 y(with)g(the)h(same)f(information)h(con)m (ten)m(t.)0 2391 y(5.)64 b(Design)39 b(soft)m(w)m(are)g(so)g(that)f(it) h(reads)f(the)g(FITS)f(header)h(k)m(eyw)m(ords)g(in)g(the)g(same)h (order)e(in)h(whic)m(h)g(they)0 2503 y(o)s(ccur)33 b(in)g(the)g (\014le.)49 b(When)32 b(reading)i(k)m(eyw)m(ords,)g(FITSIO)e(searc)m (hes)i(forw)m(ard)e(starting)i(from)e(the)i(p)s(osition)f(of)0 2616 y(the)c(last)i(k)m(eyw)m(ord)e(that)h(w)m(as)g(read.)40 b(If)29 b(it)g(reac)m(hes)i(the)e(end)g(of)g(the)h(header)f(without)g (\014nding)f(the)h(k)m(eyw)m(ord,)h(it)0 2729 y(then)j(go)s(es)h(bac)m (k)g(to)h(the)e(start)h(of)g(the)g(header)f(and)g(con)m(tin)m(ues)h (the)g(searc)m(h)g(do)m(wn)f(to)h(the)g(p)s(osition)f(where)g(it)0 2842 y(started.)41 b(In)30 b(practice,)i(as)e(long)h(as)g(the)f(en)m (tire)i(FITS)d(header)h(can)h(\014t)f(at)h(one)g(time)g(in)f(the)g(a)m (v)-5 b(ailable)33 b(in)m(ternal)0 2955 y(I/O)g(bu\013ers,)h(then)f (the)h(header)f(k)m(eyw)m(ord)h(access)h(will)e(b)s(e)g(v)m(ery)h(fast) g(and)f(it)h(mak)m(es)g(little)h(di\013erence)f(whic)m(h)0 3068 y(order)c(they)g(are)h(accessed.)0 3228 y(6.)40 b(Av)m(oid)29 b(the)e(use)h(of)f(scaling)i(\(b)m(y)f(using)f(the)h (BSCALE)e(and)h(BZER)m(O)h(or)f(TSCAL)g(and)g(TZER)m(O)f(k)m(eyw)m (ords\))0 3341 y(in)35 b(FITS)f(\014les)g(since)i(the)f(scaling)h(op)s (erations)f(add)f(to)i(the)f(pro)s(cessing)f(time)i(needed)e(to)i(read) f(or)g(write)g(the)0 3454 y(data.)60 b(In)36 b(some)i(cases)f(it)g(ma)m (y)h(b)s(e)e(more)h(e\016cien)m(t)h(to)f(temp)s(orarily)g(turn)f(o\013) h(the)g(scaling)h(\(using)e(ftpscl)h(or)0 3567 y(fttscl\))32 b(and)d(then)h(read)h(or)f(write)h(the)f(ra)m(w)h(unscaled)f(v)-5 b(alues)31 b(in)f(the)g(FITS)g(\014le.)0 3727 y(7.)40 b(Av)m(oid)27 b(using)g(the)g('implicit)h(datat)m(yp)s(e)f(con)m(v)m (ersion')h(capabilit)m(y)h(in)d(FITSIO.)g(F)-8 b(or)28 b(instance,)g(when)e(reading)0 3840 y(a)f(FITS)e(image)j(with)e(BITPIX) g(=)g(-32)i(\(32-bit)g(\015oating)f(p)s(oin)m(t)f(pixels\),)j(read)d (the)h(data)g(in)m(to)g(a)g(single)g(precision)0 3953 y(\015oating)e(p)s(oin)m(t)e(data)i(arra)m(y)f(in)g(the)g(program.)37 b(F)-8 b(orcing)23 b(FITSIO)e(to)h(con)m(v)m(ert)i(the)e(data)g(to)h(a) f(di\013eren)m(t)g(datat)m(yp)s(e)0 4066 y(can)31 b(signi\014can)m(tly) g(slo)m(w)g(the)g(program.)0 4226 y(8.)57 b(Where)36 b(feasible,)i(design)e(FITS)f(binary)g(tables)h(using)f(v)m(ector)j (column)d(elemen)m(ts)i(so)f(that)g(the)g(data)h(are)0 4339 y(written)30 b(as)g(a)g(con)m(tiguous)h(set)f(of)g(b)m(ytes,)g (rather)g(than)f(as)h(single)g(elemen)m(ts)h(in)f(m)m(ultiple)g(ro)m (ws.)41 b(F)-8 b(or)30 b(example,)0 4452 y(it)36 b(is)g(faster)g(to)g (access)h(the)f(data)h(in)e(a)h(table)h(that)f(con)m(tains)h(a)f (single)g(ro)m(w)g(and)f(2)h(columns)f(with)h(TF)m(ORM)0 4565 y(k)m(eyw)m(ords)d(equal)h(to)g('10000E')h(and)e('10000J',)j(than) d(it)g(is)g(to)h(access)g(the)g(same)f(amoun)m(t)h(of)f(data)h(in)f(a)g (table)0 4678 y(with)40 b(10000)j(ro)m(ws)d(whic)m(h)h(has)f(columns)g (with)g(the)h(TF)m(ORM)g(k)m(eyw)m(ords)g(equal)g(to)g('1E')h(and)e ('1J'.)h(In)f(the)0 4791 y(former)27 b(case)i(the)f(10000)i(\015oating) f(p)s(oin)m(t)f(v)-5 b(alues)28 b(in)g(the)g(\014rst)f(column)h(are)g (all)h(written)f(in)f(a)h(con)m(tiguous)h(blo)s(c)m(k)0 4903 y(of)d(the)f(\014le)h(whic)m(h)f(can)h(b)s(e)f(read)g(or)g (written)h(quic)m(kly)-8 b(,)28 b(whereas)d(in)g(the)h(second)f(case)i (eac)m(h)g(\015oating)f(p)s(oin)m(t)f(v)-5 b(alue)0 5016 y(in)34 b(the)g(\014rst)f(column)g(is)h(in)m(terlea)m(v)m(ed)j(with)c (the)h(in)m(teger)i(v)-5 b(alue)34 b(in)g(the)g(second)g(column)f(of)h (the)g(same)h(ro)m(w)f(so)0 5129 y(CFITSIO)29 b(has)h(to)h(explicitly)h (mo)m(v)m(e)g(to)f(the)g(p)s(osition)f(of)h(eac)m(h)g(elemen)m(t)h(to)f (b)s(e)f(read)g(or)g(written.)0 5289 y(9.)52 b(Av)m(oid)35 b(the)g(use)e(of)i(v)-5 b(ariable)34 b(length)h(v)m(ector)h(columns)d (in)h(binary)g(tables,)i(since)e(an)m(y)h(reading)f(or)g(writing)0 5402 y(of)f(these)g(data)g(requires)f(that)h(CFITSIO)f(\014rst)f(lo)s (ok)j(up)d(or)i(compute)g(the)f(starting)i(address)e(of)g(eac)m(h)i(ro) m(w)f(of)0 5515 y(data)e(in)f(the)h(heap.)40 b(In)30 b(practice,)i(this)e(is)g(probably)g(not)h(a)f(signi\014can)m(t)i (e\016ciency)f(issue.)0 5675 y(10.)39 b(When)24 b(cop)m(ying)h(data)f (from)f(one)i(FITS)e(table)h(to)h(another,)g(it)g(is)f(faster)g(to)g (transfer)f(the)h(ra)m(w)g(b)m(ytes)h(instead)p eop end %%Page: 28 34 TeXDict begin 28 33 bop 0 299 a Fi(28)1277 b Fg(CHAPTER)29 b(4.)72 b(FITSIO)29 b(CONVENTIONS)g(AND)i(GUIDELINES)0 555 y Fi(of)26 b(reading)g(then)g(writing)g(eac)m(h)h(column)e(of)i (the)f(table.)40 b(The)25 b(FITSIO)g(subroutines)g(FTGTBS)g(and)h (FTPTBS)0 668 y(\(for)i(ASCI)s(I)f(tables\),)j(and)d(FTGTBB)i(and)e (FTPTBB)i(\(for)f(binary)f(tables\))i(will)g(p)s(erform)d(lo)m(w-lev)m (el)31 b(reads)d(or)0 781 y(writes)34 b(of)h(an)m(y)f(con)m(tiguous)i (range)f(of)f(b)m(ytes)h(in)f(a)h(table)g(extension.)53 b(These)34 b(routines)g(can)h(b)s(e)e(used)h(to)h(read)0 894 y(or)29 b(write)g(a)g(whole)g(ro)m(w)f(\(or)i(m)m(ultiple)f(ro)m (ws\))g(of)g(a)g(table)h(with)e(a)h(single)g(subroutine)f(call.)41 b(These)29 b(routines)g(are)0 1007 y(fast)38 b(b)s(ecause)f(they)h(b)m (ypass)f(all)h(the)g(usual)f(data)h(scaling,)j(error)c(c)m(hec)m(king)i (and)e(mac)m(hine)h(dep)s(enden)m(t)e(data)0 1120 y(con)m(v)m(ersion)41 b(that)g(is)e(normally)i(done)e(b)m(y)h(FITSIO,)f(and)g(they)h(allo)m (w)h(the)f(program)g(to)h(write)f(the)g(data)g(to)0 1233 y(the)34 b(output)g(\014le)g(in)g(exactly)i(the)e(same)h(b)m(yte)g (order.)51 b(F)-8 b(or)35 b(these)g(same)f(reasons,)i(use)e(of)g(these) h(routines)f(can)0 1346 y(b)s(e)f(somewhat)h(risky)f(b)s(ecause)g(no)g (v)-5 b(alidation)35 b(or)f(mac)m(hine)g(dep)s(enden)m(t)e(con)m(v)m (ersion)j(is)e(p)s(erformed)f(b)m(y)h(these)0 1458 y(routines.)40 b(In)27 b(general)h(these)h(routines)e(are)h(only)g(recommended)f(for)h (optimizing)h(critical)g(pieces)g(of)f(co)s(de)g(and)0 1571 y(should)e(only)i(b)s(e)f(used)f(b)m(y)i(programmers)e(who)h (thoroughly)h(understand)d(the)j(in)m(ternal)g(b)m(yte)g(structure)f (of)h(the)0 1684 y(FITS)i(tables)h(they)f(are)h(reading)g(or)f (writing.)0 1844 y(11.)41 b(Another)30 b(strategy)g(for)g(impro)m(ving) f(the)h(sp)s(eed)e(of)i(writing)g(a)f(FITS)g(table,)i(similar)f(to)g (the)f(previous)g(one,)0 1957 y(is)j(to)g(directly)h(construct)f(the)f (en)m(tire)i(b)m(yte)f(stream)g(for)g(a)g(whole)g(table)g(ro)m(w)g (\(or)g(m)m(ultiple)h(ro)m(ws\))f(within)f(the)0 2070 y(application)k(program)f(and)g(then)f(write)i(it)f(to)h(the)f(FITS)f (\014le)i(with)e(ftptbb.)51 b(This)33 b(a)m(v)m(oids)j(all)f(the)f(o)m (v)m(erhead)0 2183 y(normally)g(presen)m(t)g(in)f(the)h(column-orien)m (ted)h(CFITSIO)d(write)i(routines.)51 b(This)33 b(tec)m(hnique)h (should)f(only)h(b)s(e)0 2296 y(used)26 b(for)h(critical)i (applications,)g(b)s(ecause)d(it)i(mak)m(es)g(the)f(co)s(de)g(more)g (di\016cult)g(to)g(understand)e(and)i(main)m(tain,)0 2409 y(and)d(it)h(mak)m(es)h(the)f(co)s(de)g(more)f(system)h(dep)s (enden)m(t)f(\(e.g.,)k(do)c(the)h(b)m(ytes)g(need)g(to)g(b)s(e)f(sw)m (app)s(ed)g(b)s(efore)g(writing)0 2522 y(to)31 b(the)g(FITS)e (\014le?\).)0 2682 y(12.)53 b(Finally)-8 b(,)37 b(external)e(factors)h (suc)m(h)e(as)g(the)h(t)m(yp)s(e)f(of)h(magnetic)g(disk)f(con)m (troller)i(\(SCSI)d(or)i(IDE\),)g(the)f(size)0 2795 y(of)h(the)g(disk)g (cac)m(he,)j(the)d(a)m(v)m(erage)i(seek)f(sp)s(eed)e(of)h(the)g(disk,)h (the)f(amoun)m(t)h(of)f(disk)f(fragmen)m(tation,)k(and)d(the)0 2908 y(amoun)m(t)29 b(of)g(RAM)f(a)m(v)-5 b(ailable)31 b(on)e(the)f(system)h(can)g(all)g(ha)m(v)m(e)h(a)f(signi\014can)m(t)g (impact)h(on)e(o)m(v)m(erall)j(I/O)d(e\016ciency)-8 b(.)0 3021 y(F)g(or)36 b(critical)h(applications,)g(a)f(system)f (administrator)g(should)f(review)h(the)h(prop)s(osed)d(system)j(hardw)m (are)e(to)0 3134 y(iden)m(tify)d(an)m(y)g(p)s(oten)m(tial)g(I/O)g(b)s (ottlenec)m(ks.)p eop end %%Page: 29 35 TeXDict begin 29 34 bop 0 1225 a Ff(Chapter)65 b(5)0 1687 y Fl(Basic)77 b(In)-6 b(terface)77 b(Routines)0 2180 y Fi(This)27 b(section)h(de\014nes)f(a)h(basic)g(set)g(of)g (subroutines)e(that)i(can)g(b)s(e)f(used)g(to)h(p)s(erform)e(the)i (most)g(common)g(t)m(yp)s(es)0 2293 y(of)d(read)g(and)f(write)h(op)s (erations)g(on)g(FITS)f(\014les.)39 b(New)25 b(users)f(should)g(start)h (with)g(these)g(subroutines)f(and)g(then,)0 2406 y(as)33 b(needed,)h(explore)f(the)h(more)f(adv)-5 b(ance)33 b(routines)g (describ)s(ed)f(in)h(the)g(follo)m(wing)i(c)m(hapter)e(to)h(p)s(erform) e(more)0 2518 y(complex)f(or)f(sp)s(ecialized)i(op)s(erations.)0 2679 y(A)e(righ)m(t)g(arro)m(w)g(sym)m(b)s(ol)f(\()p Fa(>)p Fi(\))h(is)g(used)f(to)h(separate)h(the)e(input)g(parameters)h (from)f(the)h(output)f(parameters)h(in)0 2791 y(the)i(de\014nition)f (of)g(eac)m(h)i(routine.)44 b(This)30 b(sym)m(b)s(ol)i(is)f(not)h (actually)h(part)e(of)h(the)f(calling)i(sequence.)45 b(Note)32 b(that)0 2904 y(the)f(status)h(parameter)g(is)f(b)s(oth)g(an) g(input)f(and)h(an)g(output)g(parameter)h(and)e(m)m(ust)h(b)s(e)g (initialized)i(=)e(0)h(prior)0 3017 y(to)f(calling)h(the)f(FITSIO)e (subroutines.)0 3177 y(Refer)h(to)i(Chapter)d(9)i(for)f(the)h (de\014nition)f(of)g(all)i(the)e(parameters)h(used)e(b)m(y)i(these)g (in)m(terface)g(routines.)0 3525 y Fd(5.1)135 b(FITSIO)44 b(Error)h(Status)h(Routines)0 3773 y Fh(1)81 b Fi(Return)24 b(the)i(curren)m(t)f(v)m(ersion)h(n)m(um)m(b)s(er)e(of)i(the)f (\014tsio)h(library)-8 b(.)39 b(The)25 b(v)m(ersion)h(n)m(um)m(b)s(er)e (will)i(b)s(e)e(incremen)m(ted)227 3886 y(with)30 b(eac)m(h)i(new)e (release)h(of)g(CFITSIO.)382 4157 y Fe(FTVERS\()46 b(>)h(version\))0 4429 y Fh(2)81 b Fi(Return)45 b(the)i(descriptiv)m(e)g(text)g(string)g (corresp)s(onding)e(to)i(a)g(FITSIO)e(error)h(status)h(co)s(de.)89 b(The)46 b(30-)227 4541 y(c)m(haracter)32 b(length)f(string)f(con)m (tains)i(a)f(brief)f(description)g(of)g(the)h(cause)g(of)f(the)h (error.)382 4813 y Fe(FTGERR\(status,)44 b(>)j(errtext\))0 5084 y Fh(3)81 b Fi(Return)40 b(the)h(top)g(\(oldest\))h(80-c)m (haracter)i(error)c(message)i(from)f(the)g(in)m(ternal)g(FITSIO)f(stac) m(k)i(of)f(error)227 5197 y(messages)29 b(and)f(shift)g(an)m(y)g (remaining)g(messages)h(on)f(the)g(stac)m(k)i(up)d(one)h(lev)m(el.)42 b(An)m(y)28 b(FITSIO)f(error)h(will)227 5310 y(generate)h(one)e(or)g (more)h(messages)g(on)f(the)g(stac)m(k.)41 b(Call)28 b(this)f(routine)g(rep)s(eatedly)g(to)h(get)h(eac)m(h)f(message)227 5422 y(in)i(sequence.)41 b(The)30 b(error)g(stac)m(k)i(is)f(empt)m(y)f (when)g(a)g(blank)g(string)h(is)f(returned.)382 5694 y Fe(FTGMSG\()46 b(>)h(errmsg\))1905 5942 y Fi(29)p eop end %%Page: 30 36 TeXDict begin 30 35 bop 0 299 a Fi(30)1747 b Fg(CHAPTER)30 b(5.)111 b(BASIC)30 b(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)0 555 y Fh(4)81 b Fi(The)33 b(FTPMRK)h(routine)g(puts)g(an)g(in)m (visible)h(mark)m(er)f(on)g(the)h(CFITSIO)d(error)i(stac)m(k.)54 b(The)33 b(FTCMRK)227 668 y(routine)41 b(can)g(then)g(b)s(e)f(used)g (to)h(delete)h(an)m(y)f(more)g(recen)m(t)h(error)e(messages)i(on)f(the) g(stac)m(k,)k(bac)m(k)c(to)227 781 y(the)32 b(p)s(osition)f(of)g(the)g (mark)m(er.)43 b(This)31 b(preserv)m(es)g(an)m(y)g(older)h(error)e (messages)i(on)f(the)h(stac)m(k.)44 b(FTCMSG)227 894 y(simply)23 b(clears)g(the)g(en)m(tire)h(error)e(message)i(stac)m(k.)40 b(These)23 b(routines)f(are)h(called)h(without)f(an)m(y)g(argumen)m (ts.)382 1152 y Fe(FTPMRK)382 1265 y(FTCMRK)382 1378 y(FTCMSG)0 1637 y Fh(5)81 b Fi(Prin)m(t)30 b(out)h(the)g(error)f (message)i(corresp)s(onding)e(to)h(the)g(input)f(status)h(v)-5 b(alue)31 b(and)f(all)i(the)f(error)f(messages)227 1750 y(on)g(the)h(FITSIO)e(stac)m(k)i(to)g(the)g(sp)s(eci\014ed)e(\014le)i (stream)f(\(stream)h(can)g(b)s(e)e(either)i(the)f(string)g('STDOUT')227 1863 y(or)h('STDERR'\).)f(If)g(the)h(input)e(status)i(v)-5 b(alue)31 b(=)f(0)h(then)f(this)g(routine)g(do)s(es)g(nothing.)334 2121 y Fe(FTRPRT)46 b(\(stream,)g(>)h(status\))0 2380 y Fh(6)81 b Fi(W)-8 b(rite)39 b(an)f(80-c)m(haracter)j(message)e(to)g (the)f(FITSIO)f(error)h(stac)m(k.)65 b(Application)39 b(programs)f(should)f(not)227 2493 y(normally)31 b(write)f(to)i(the)e (stac)m(k,)i(but)e(there)g(ma)m(y)h(b)s(e)f(some)h(situations)g(where)f (this)g(is)h(desirable.)382 2751 y Fe(FTPMSG\(errmsg\))0 3085 y Fd(5.2)135 b(File)46 b(I/O)f(Routines)0 3325 y Fh(1)81 b Fi(Op)s(en)34 b(an)h(existing)i(FITS)d(\014le)i(with)f (readonly)h(or)f(readwrite)h(access.)58 b(This)34 b(routine)i(alw)m(a)m (ys)h(op)s(ens)e(the)227 3438 y(primary)30 b(arra)m(y)i(\(the)f (\014rst)f(HDU\))i(of)f(the)h(\014le,)f(and)f(do)s(es)h(not)g(mo)m(v)m (e)h(to)g(a)f(follo)m(wing)i(extension,)f(if)f(one)227 3551 y(w)m(as)c(sp)s(eci\014ed)f(as)g(part)h(of)f(the)h(\014lename.)39 b(Use)27 b(the)g(FTNOPN)f(routine)g(to)h(automatically)j(mo)m(v)m(e)e (to)f(the)227 3664 y(extension.)44 b(This)31 b(routine)g(will)h(also)g (op)s(en)f(IRAF)g(images)i(\(.imh)e(format)h(\014les\))g(and)e(ra)m(w)i (binary)e(data)227 3776 y(arra)m(ys)e(with)f(READONL)-8 b(Y)28 b(access)h(b)m(y)e(\014rst)g(con)m(v)m(erting)i(them)e(on)g(the) h(\015y)f(in)m(to)h(virtual)g(FITS)f(images.)227 3889 y(See)43 b(the)g(`Extended)f(File)i(Name)f(Syn)m(tax')g(c)m(hapter)g (for)f(more)h(details.)78 b(The)42 b(FTDK)m(OPN)h(routine)227 4002 y(simply)37 b(op)s(ens)g(the)h(sp)s(eci\014ed)f(\014le)h(without)f (trying)h(to)g(in)m(terpret)g(the)g(\014lename)g(using)f(the)h (extended)227 4115 y(\014lename)31 b(syn)m(tax.)382 4374 y Fe(FTOPEN\(unit,filename,rwm)o(ode)o(,)42 b(>)47 b (blocksize,status\))382 4487 y(FTDKOPN\(unit,filename,rw)o(mod)o(e,)42 b(>)47 b(blocksize,status\))0 4745 y Fh(2)81 b Fi(Op)s(en)24 b(an)i(existing)h(FITS)e(\014le)h(with)f(readonly)h(or)g(readwrite)g (access)h(and)f(mo)m(v)m(e)h(to)f(a)h(follo)m(wing)g(extension,)227 4858 y(if)38 b(one)g(w)m(as)g(sp)s(eci\014ed)g(as)g(part)f(of)h(the)h (\014lename.)63 b(\(e.g.,)42 b('\014lename.\014ts+2')c(or)g ('\014lename.\014ts[2]')i(will)227 4971 y(mo)m(v)m(e)e(to)g(the)e(3rd)g (HDU)i(in)e(the)h(\014le\).)60 b(Note)37 b(that)h(this)e(routine)h (di\013ers)f(from)g(FTOPEN)g(in)g(that)h(it)227 5084 y(do)s(es)30 b(not)h(ha)m(v)m(e)h(the)e(redundan)m(t)f(blo)s(c)m(ksize) j(argumen)m(t.)382 5342 y Fe(FTNOPN\(unit,filename,rwm)o(ode)o(,)42 b(>)47 b(status\))0 5601 y Fh(3)81 b Fi(Op)s(en)31 b(an)h(existing)h (FITS)f(\014le)g(with)g(readonly)h(or)f(readwrite)h(access)g(and)f (then)g(mo)m(v)m(e)i(to)f(the)g(\014rst)e(HDU)227 5714 y(con)m(taining)c(signi\014can)m(t)g(data,)g(if)e(a\))i(an)e(HDU)h (name)g(or)f(n)m(um)m(b)s(er)f(to)i(op)s(en)f(w)m(as)h(not)g (explicitly)h(sp)s(eci\014ed)p eop end %%Page: 31 37 TeXDict begin 31 36 bop 0 299 a Fg(5.2.)72 b(FILE)30 b(I/O)h(R)m(OUTINES)2693 b Fi(31)227 555 y(as)31 b(part)g(of)g(the)g (\014lename,)h(and)e(b\))h(if)g(the)g(FITS)f(\014le)h(con)m(tains)h(a)g (n)m(ull)e(primary)g(arra)m(y)i(\(i.e.,)h(NAXIS)d(=)227 668 y(0\).)41 b(In)26 b(this)i(case,)h(it)f(will)g(lo)s(ok)g(for)f(the) h(\014rst)e(IMA)m(GE)j(HDU)f(with)f(NAXIS)g(>)h(0,)g(or)g(the)f (\014rst)g(table)h(that)227 781 y(do)s(es)g(not)g(con)m(tain)g(the)g (strings)g(`GTI')g(\(Go)s(o)s(d)f(Time)h(In)m(terv)-5 b(al\))29 b(or)f(`OBST)-8 b(ABLE')28 b(in)f(the)h(EXTNAME)227 894 y(k)m(eyw)m(ord)37 b(v)-5 b(alue.)61 b(FTTOPN)36 b(is)g(similar,)j(except)f(it)f(will)g(mo)m(v)m(e)i(to)e(the)g(\014rst) f(signi\014can)m(t)i(table)f(HDU)227 1007 y(\(skipping)26 b(o)m(v)m(er)g(an)m(y)g(image)h(HDUs\))g(in)e(the)h(\014le)g(if)f(a)h (sp)s(eci\014c)g(HDU)g(name)g(or)g(n)m(um)m(b)s(er)e(is)i(not)f(sp)s (eci\014ed.)227 1120 y(FTIOPN)30 b(will)h(mo)m(v)m(e)h(to)f(the)f (\014rst)g(non-n)m(ull)g(image)i(HDU,)f(skipping)f(o)m(v)m(er)h(an)m(y) g(tables.)382 1376 y Fe(FTDOPN\(unit,filename,rwm)o(ode)o(,)42 b(>)47 b(status\))382 1489 y(FTTOPN\(unit,filename,rwm)o(ode)o(,)42 b(>)47 b(status\))382 1602 y(FTIOPN\(unit,filename,rwm)o(ode)o(,)42 b(>)47 b(status\))0 1858 y Fh(4)81 b Fi(Op)s(en)38 b(and)i(initialize)j (a)e(new)e(empt)m(y)i(FITS)f(\014le.)70 b(A)41 b(template)h(\014le)e (ma)m(y)h(also)g(b)s(e)f(sp)s(eci\014ed)g(to)h(de\014ne)227 1971 y(the)34 b(structure)e(of)h(the)h(new)e(\014le)h(\(see)h(section)g (4.2.4\).)51 b(The)33 b(FTDKINIT)g(routine)g(simply)f(creates)j(the)227 2084 y(sp)s(eci\014ed)30 b(\014le)g(without)h(trying)f(to)h(in)m (terpret)g(the)g(\014lename)f(using)g(the)h(extended)f(\014lename)h (syn)m(tax.)382 2340 y Fe(FTINIT\(unit,filename,blo)o(cks)o(ize,)41 b(>)48 b(status\))382 2453 y(FTDKINIT\(unit,filename,b)o(loc)o(ksiz)o (e,)42 b(>)47 b(status\))0 2709 y Fh(5)81 b Fi(Close)31 b(a)f(FITS)g(\014le)g(previously)g(op)s(ened)g(with)g(ftop)s(en)g(or)g (ftinit)382 2965 y Fe(FTCLOS\(unit,)44 b(>)k(status\))0 3221 y Fh(6)81 b Fi(Mo)m(v)m(e)32 b(to)f(a)g(sp)s(eci\014ed)f (\(absolute\))h(HDU)g(in)g(the)f(FITS)g(\014le)g(\(nhdu)f(=)h(1)h(for)f (the)g(FITS)g(primary)f(arra)m(y\))382 3478 y Fe(FTMAHD\(unit,nhdu,)43 b(>)k(hdutype,status\))0 3734 y Fh(7)81 b Fi(Create)30 b(a)f(primary)f(arra)m(y)i(\(if)g(none)f(already)g(exists\),)i(or)e (insert)g(a)h(new)f(IMA)m(GE)h(extension)g(immediately)227 3847 y(follo)m(wing)25 b(the)e(CHDU,)g(or)g(insert)g(a)g(new)g(Primary) f(Arra)m(y)h(at)h(the)f(b)s(eginning)f(of)h(the)g(\014le.)38 b(An)m(y)23 b(follo)m(wing)227 3960 y(extensions)29 b(in)g(the)g (\014le)f(will)h(b)s(e)f(shifted)h(do)m(wn)f(to)h(mak)m(e)h(ro)s(om)e (for)h(the)g(new)f(extension.)40 b(If)29 b(the)g(CHDU)227 4072 y(is)h(the)g(last)g(HDU)g(in)g(the)f(\014le)h(then)f(the)h(new)f (image)i(extension)f(will)g(simply)f(b)s(e)g(app)s(ended)f(to)i(the)g (end)227 4185 y(of)k(the)h(\014le.)52 b(One)33 b(can)h(force)h(a)g(new) e(primary)g(arra)m(y)i(to)g(b)s(e)e(inserted)h(at)h(the)f(b)s(eginning) f(of)h(the)h(FITS)227 4298 y(\014le)29 b(b)m(y)f(setting)i(status)e(=)h (-9)g(prior)e(to)j(calling)g(the)e(routine.)40 b(In)28 b(this)g(case)i(the)e(existing)i(primary)d(arra)m(y)227 4411 y(will)f(b)s(e)f(con)m(v)m(erted)i(to)g(an)e(IMA)m(GE)h (extension.)40 b(The)25 b(new)g(extension)i(\(or)f(primary)e(arra)m (y\))j(will)f(b)s(ecome)227 4524 y(the)32 b(CHDU.)f(The)g(FTI)s(IMGLL)f (routine)i(is)f(iden)m(tical)i(to)e(the)h(FTI)s(IMG)f(routine)g(except) h(that)f(the)h(4th)227 4637 y(parameter)25 b(\(the)g(length)g(of)f(eac) m(h)h(axis\))g(is)g(an)f(arra)m(y)h(of)f(64-bit)i(in)m(tegers)f(rather) f(than)g(an)g(arra)m(y)h(of)g(32-bit)227 4750 y(in)m(tegers.)382 5006 y Fe(FTIIMG\(unit,bitpix,naxis)o(,na)o(xes,)41 b(>)48 b(status\))382 5119 y(FTIIMGLL\(unit,bitpix,nax)o(is,)o(naxe)o(sll,)41 b(>)47 b(status\))0 5375 y Fh(8)81 b Fi(Insert)30 b(a)i(new)f(ASCI)s(I) f(T)-8 b(ABLE)31 b(extension)h(immediately)h(follo)m(wing)f(the)g (CHDU.)g(An)m(y)f(follo)m(wing)i(exten-)227 5488 y(sions)26 b(will)g(b)s(e)f(shifted)g(do)m(wn)g(to)h(mak)m(e)h(ro)s(om)e(for)h (the)f(new)g(extension.)40 b(If)25 b(there)h(are)g(no)g(other)f(follo)m (wing)227 5601 y(extensions)32 b(then)f(the)h(new)f(table)h(extension)g (will)g(simply)f(b)s(e)g(app)s(ended)f(to)i(the)f(end)g(of)h(the)f (\014le.)44 b(The)227 5714 y(new)33 b(extension)h(will)f(b)s(ecome)h (the)f(CHDU.)h(The)f(FTIT)-8 b(ABLL)33 b(routine)g(is)g(iden)m(tical)i (to)f(the)g(FTIT)-8 b(AB)p eop end %%Page: 32 38 TeXDict begin 32 37 bop 0 299 a Fi(32)1747 b Fg(CHAPTER)30 b(5.)111 b(BASIC)30 b(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)227 555 y Fi(routine)36 b(except)g(that)g(the)f(2nd)g(and)g(3rd)g (parameters)g(\(that)i(giv)m(e)g(the)e(size)h(of)g(the)f(table\))i(are) f(64-bit)227 668 y(in)m(tegers)43 b(rather)f(than)f(32-bit)i(in)m (tegers.)76 b(Under)41 b(normal)g(circumstances,)46 b(the)c(nro)m(ws)f (and)g(nro)m(wsll)227 781 y(paramen)m(ters)f(should)e(ha)m(v)m(e)j(a)f (v)-5 b(alue)40 b(of)f(0;)45 b(CFITSIO)38 b(will)h(automatically)k(up)s (date)38 b(the)i(n)m(um)m(b)s(er)e(of)227 894 y(ro)m(ws)31 b(as)f(data)h(is)g(written)f(to)h(the)g(table.)382 1158 y Fe(FTITAB\(unit,rowlen,nrows)o(,tf)o(ield)o(s,tt)o(ype)o(,tbc)o(ol,t) o(for)o(m,tu)o(nit,)o(ext)o(name)o(,)42 b(>)716 1271 y(status\))382 1384 y(FTITABLL\(unit,rowlenll,n)o(row)o(sll,)o(tfie)o (lds)o(,tty)o(pe,t)o(bco)o(l,tf)o(orm,)o(tun)o(it,e)o(xtna)o(me,)f(>) 716 1497 y(status\))0 1761 y Fh(9)81 b Fi(Insert)26 b(a)h(new)g(binary) f(table)h(extension)h(immediately)g(follo)m(wing)h(the)e(CHDU.)g(An)m (y)g(follo)m(wing)h(extensions)227 1874 y(will)39 b(b)s(e)f(shifted)g (do)m(wn)g(to)h(mak)m(e)g(ro)s(om)g(for)f(the)g(new)g(extension.)66 b(If)38 b(there)h(are)f(no)h(other)f(follo)m(wing)227 1987 y(extensions)f(then)g(the)f(new)g(bin)m(table)h(extension)h(will)f (simply)f(b)s(e)g(app)s(ended)e(to)k(the)e(end)g(of)h(the)g(\014le.)227 2100 y(The)23 b(new)g(extension)h(will)f(b)s(ecome)h(the)f(CHDU.)h(The) f(FTIBINLL)g(routine)g(is)g(iden)m(tical)i(to)f(the)g(FTIBIN)227 2213 y(routine)30 b(except)i(that)e(the)h(2nd)e(parameter)i(\(that)g (giv)m(es)g(the)g(length)f(of)h(the)f(table\))h(is)g(a)f(64-bit)i(in)m (teger)227 2325 y(rather)24 b(than)g(a)g(32-bit)h(in)m(teger.)40 b(Under)23 b(normal)h(circumstances,)i(the)e(nro)m(ws)f(and)h(nro)m (wsll)g(paramen)m(ters)227 2438 y(should)31 b(ha)m(v)m(e)i(a)f(v)-5 b(alue)32 b(of)f(0;)i(CFITSIO)d(will)i(automatically)j(up)s(date)30 b(the)i(n)m(um)m(b)s(er)e(of)i(ro)m(ws)g(as)g(data)g(is)227 2551 y(written)f(to)g(the)f(table.)382 2815 y Fe (FTIBIN\(unit,nrows,tfield)o(s,t)o(type)o(,tfo)o(rm,)o(tuni)o(t,ex)o (tna)o(me,v)o(arid)o(at)41 b(>)48 b(status\))382 2928 y(FTIBINLL\(unit,nrowsll,tf)o(iel)o(ds,t)o(type)o(,tf)o(orm,)o(tuni)o (t,e)o(xtna)o(me,v)o(ari)o(dat)41 b(>)48 b(status\))0 3380 y Fd(5.3)135 b(Keyw)l(ord)46 b(I/O)f(Routines)0 3624 y Fh(1)81 b Fi(Put)30 b(\(app)s(end\))f(an)h(80-c)m(haracter)j (record)e(in)m(to)g(the)g(CHU.)382 3888 y Fe(FTPREC\(unit,card,)43 b(>)k(status\))0 4152 y Fh(2)81 b Fi(Put)28 b(\(app)s(end\))g(a)h(new)g (k)m(eyw)m(ord)g(of)g(the)g(appropriate)g(datat)m(yp)s(e)h(in)m(to)g (the)f(CHU.)g(The)f(E)h(and)f(D)i(v)m(ersions)227 4265 y(of)24 b(this)f(routine)g(ha)m(v)m(e)h(the)g(added)e(feature)i(that)g (if)f(the)g('decimals')i(parameter)f(is)f(negativ)m(e,)k(then)c(the)g ('G')227 4378 y(displa)m(y)30 b(format)g(rather)f(then)g(the)h('E')f (format)h(will)g(b)s(e)f(used)f(when)h(constructing)h(the)f(k)m(eyw)m (ord)h(v)-5 b(alue,)227 4490 y(taking)27 b(the)g(absolute)g(v)-5 b(alue)26 b(of)h('decimals')g(for)f(the)h(precision.)39 b(This)26 b(will)g(suppress)e(trailing)k(zeros,)g(and)227 4603 y(will)37 b(use)g(a)g(\014xed)f(format)h(rather)g(than)f(an)h(exp) s(onen)m(tial)g(format,)i(dep)s(ending)c(on)i(the)g(magnitude)g(of)227 4716 y(the)31 b(v)-5 b(alue.)382 4980 y Fe(FTPKY[JKLS]\(unit,keyword)o (,ke)o(yval)o(,com)o(men)o(t,)42 b(>)47 b(status\))382 5093 y(FTPKY[EDFG]\(unit,keyword)o(,ke)o(yval)o(,dec)o(ima)o(ls,c)o (omme)o(nt,)41 b(>)48 b(status\))0 5357 y Fh(3)81 b Fi(Get)37 b(the)f(n)m(th)f(80-c)m(haracter)k(header)d(record)g(from)f(the)h(CHU.) h(The)e(\014rst)g(k)m(eyw)m(ord)i(in)e(the)h(header)g(is)g(at)227 5470 y(k)m(ey)p 365 5470 28 4 v 34 w(no)42 b(=)f(1;)49 b(if)42 b(k)m(ey)p 996 5470 V 34 w(no)g(=)f(0)i(then)e(this)h (subroutine)f(simple)h(mo)m(v)m(es)i(the)e(in)m(ternal)h(p)s(oin)m(ter) f(to)h(the)227 5583 y(b)s(eginning)35 b(of)h(the)g(header)f(so)h(that)g (subsequen)m(t)f(k)m(eyw)m(ord)h(op)s(erations)g(will)g(start)g(at)g (the)g(top)g(of)g(the)227 5696 y(header;)31 b(it)g(also)g(returns)e(a)i (blank)f(card)g(v)-5 b(alue)31 b(in)f(this)g(case.)p eop end %%Page: 33 39 TeXDict begin 33 38 bop 0 299 a Fg(5.4.)72 b(D)m(A)-8 b(T)g(A)32 b(I/O)f(R)m(OUTINES)2650 b Fi(33)382 555 y Fe(FTGREC\(unit,key_no,)42 b(>)48 b(card,status\))0 804 y Fh(4)81 b Fi(Get)31 b(a)g(k)m(eyw)m(ord)g(v)-5 b(alue)30 b(\(with)h(the)f(appropriate)h(datat)m(yp)s(e\))g(and)f(commen)m(t)i (from)e(the)g(CHU)382 1052 y Fe(FTGKY[EDJKLS]\(unit,keywo)o(rd,)41 b(>)48 b(keyval,comment,status\))0 1301 y Fh(5)81 b Fi(Delete)32 b(an)e(existing)i(k)m(eyw)m(ord)f(record.)382 1550 y Fe(FTDKEY\(unit,keyword,)42 b(>)48 b(status\))0 1881 y Fd(5.4)135 b(Data)46 b(I/O)g(Routines)0 2132 y Fi(The)32 b(follo)m(wing)i(routines)e(read)h(or)f(write)h(data)g(v)-5 b(alues)33 b(in)f(the)h(curren)m(t)f(HDU)i(of)e(the)h(FITS)f(\014le.)47 b(Automatic)0 2245 y(datat)m(yp)s(e)28 b(con)m(v)m(ersion)h(will)e(b)s (e)g(attempted)h(for)g(n)m(umerical)f(datat)m(yp)s(es)i(if)e(the)g(sp)s (eci\014ed)g(datat)m(yp)s(e)h(is)f(di\013eren)m(t)0 2357 y(from)j(the)g(actual)i(datat)m(yp)s(e)g(of)e(the)h(FITS)e(arra)m(y)i (or)f(table)i(column.)0 2606 y Fh(1)81 b Fi(W)-8 b(rite)31 b(elemen)m(ts)h(in)m(to)f(the)g(primary)e(data)j(arra)m(y)e(or)h(image) g(extension.)382 2855 y Fe(FTPPR[BIJKED]\(unit,group)o(,fp)o(ixel)o (,nel)o(eme)o(nts,)o(valu)o(es,)41 b(>)48 b(status\))0 3103 y Fh(2)81 b Fi(Read)30 b(elemen)m(ts)j(from)d(the)h(primary)e (data)j(arra)m(y)f(or)g(image)h(extension.)42 b(Unde\014ned)29 b(arra)m(y)j(elemen)m(ts)g(will)227 3216 y(b)s(e)f(returned)f(with)h(a) h(v)-5 b(alue)31 b(=)g(n)m(ullv)-5 b(al,)33 b(unless)d(n)m(ullv)-5 b(al)32 b(=)f(0)h(in)f(whic)m(h)g(case)h(no)f(c)m(hec)m(ks)i(for)e (unde\014ned)227 3329 y(pixels)h(will)f(b)s(e)f(p)s(erformed.)42 b(The)30 b(an)m(yf)i(parameter)f(is)g(set)h(to)g(true)f(\(=)g(.true.\)) 43 b(if)31 b(an)m(y)h(of)f(the)g(returned)227 3442 y(elemen)m(ts)h(w)m (ere)f(unde\014ned.)382 3691 y Fe(FTGPV[BIJKED]\(unit,group)o(,fp)o (ixel)o(,nel)o(eme)o(nts,)o(null)o(val)o(,)42 b(>)47 b(values,anyf,status\))0 3939 y Fh(3)81 b Fi(W)-8 b(rite)36 b(elemen)m(ts)h(in)m(to)f(an)f(ASCI)s(I)e(or)i(binary)g(table)h (column.)54 b(The)35 b(`felem')h(parameter)g(applies)f(only)g(to)227 4052 y(v)m(ector)d(columns)e(in)g(binary)g(tables)h(and)f(is)g(ignored) h(when)e(writing)i(to)g(ASCI)s(I)d(tables.)382 4301 y Fe(FTPCL[SLBIJKEDCM]\(unit,c)o(oln)o(um,f)o(row,)o(fel)o(em,n)o(elem)o (ent)o(s,va)o(lues)o(,)42 b(>)47 b(status\))0 4549 y Fh(4)81 b Fi(Read)22 b(elemen)m(ts)h(from)e(an)g(ASCI)s(I)g(or)g (binary)g(table)i(column.)38 b(Unde\014ned)20 b(arra)m(y)i(elemen)m(ts) h(will)f(b)s(e)f(returned)227 4662 y(with)32 b(a)h(v)-5 b(alue)33 b(=)f(n)m(ullv)-5 b(al,)34 b(unless)e(n)m(ullv)-5 b(al)32 b(=)h(0)f(\(or)h(=)f(')h(')f(for)g(ftgcvs\))i(in)e(whic)m(h)g (case)i(no)e(c)m(hec)m(king)i(for)227 4775 y(unde\014ned)23 b(v)-5 b(alues)25 b(will)g(b)s(e)g(p)s(erformed.)37 b(The)24 b(ANYF)i(parameter)f(is)g(set)h(to)f(true)g(if)g(an)m(y)g(of)g(the)g (returned)227 4888 y(elemen)m(ts)32 b(are)f(unde\014ned.)227 5036 y(An)m(y)d(column,)h(regardless)f(of)g(it's)h(in)m(trinsic)f (datat)m(yp)s(e,)i(ma)m(y)e(b)s(e)f(read)h(as)g(a)h(string.)40 b(It)28 b(should)e(b)s(e)i(noted)227 5149 y(ho)m(w)m(ev)m(er)k(that)f (reading)f(a)h(n)m(umeric)f(column)g(as)h(a)g(string)f(is)g(10)i(-)e (100)i(times)f(slo)m(w)m(er)g(than)f(reading)h(the)227 5262 y(same)36 b(column)f(as)h(a)g(n)m(um)m(b)s(er)e(due)g(to)j(the)e (large)i(o)m(v)m(erhead)f(in)f(constructing)h(the)g(formatted)g (strings.)227 5375 y(The)i(displa)m(y)g(format)g(of)g(the)g(returned)f (strings)g(will)h(b)s(e)g(determined)f(b)m(y)h(the)g(TDISPn)f(k)m(eyw)m (ord,)j(if)227 5488 y(it)d(exists,)h(otherwise)f(b)m(y)f(the)g(datat)m (yp)s(e)h(of)f(the)h(column.)57 b(The)36 b(length)g(of)h(the)f (returned)f(strings)h(can)227 5601 y(b)s(e)29 b(determined)f(with)h (the)g(ftgcdw)g(routine.)40 b(The)28 b(follo)m(wing)j(TDISPn)c(displa)m (y)j(formats)f(are)g(curren)m(tly)227 5714 y(supp)s(orted:)p eop end %%Page: 34 40 TeXDict begin 34 39 bop 0 299 a Fi(34)1747 b Fg(CHAPTER)30 b(5.)111 b(BASIC)30 b(INTERF)-10 b(A)m(CE)30 b(R)m(OUTINES)418 555 y Fe(Iw.m)142 b(Integer)418 668 y(Ow.m)g(Octal)47 b(integer)418 781 y(Zw.m)142 b(Hexadecimal)45 b(integer)418 894 y(Fw.d)142 b(Fixed)47 b(floating)e(point)418 1007 y(Ew.d)142 b(Exponential)45 b(floating)h(point)418 1120 y(Dw.d)142 b(Exponential)45 b(floating)h(point)418 1233 y(Gw.d)142 b(General;)46 b(uses)g(Fw.d)h(if)g(significance)e(not)i (lost,)f(else)h(Ew.d)227 1483 y Fi(where)24 b(w)h(is)f(the)h(width)f (in)g(c)m(haracters)i(of)f(the)g(displa)m(y)m(ed)g(v)-5 b(alues,)27 b(m)d(is)h(the)f(minim)m(um)g(n)m(um)m(b)s(er)g(of)g (digits)227 1595 y(displa)m(y)m(ed,)31 b(and)e(d)h(is)f(the)i(n)m(um)m (b)s(er)d(of)i(digits)g(to)h(the)f(righ)m(t)h(of)f(the)g(decimal.)41 b(The)29 b(.m)h(\014eld)g(is)g(optional.)382 1855 y Fe (FTGCV[SBIJKEDCM]\(unit,co)o(lnu)o(m,fr)o(ow,f)o(ele)o(m,ne)o(leme)o (nts)o(,nul)o(lval)o(,)42 b(>)1098 1968 y(values,anyf,status\))0 2228 y Fh(5)81 b Fi(Get)42 b(the)g(table)h(column)e(n)m(um)m(b)s(er)g (and)g(full)g(name)h(of)g(the)f(column)h(whose)f(name)h(matc)m(hes)h (the)f(input)227 2341 y(template)35 b(string.)48 b(See)33 b(the)h(`Adv)-5 b(anced)33 b(In)m(terface)h(Routines')f(c)m(hapter)h (for)f(a)g(full)g(description)g(of)g(this)227 2454 y(routine.)382 2714 y Fe(FTGCNN\(unit,casesen,colt)o(emp)o(late)o(,)42 b(>)47 b(colname,colnum,status\))p eop end %%Page: 35 41 TeXDict begin 35 40 bop 0 1225 a Ff(Chapter)65 b(6)0 1687 y Fl(Adv)-13 b(anced)78 b(In)-6 b(terface)77 b(Subroutines)0 2180 y Fi(This)31 b(c)m(hapter)h(de\014nes)f(all)h(the)g(a)m(v)-5 b(ailable)34 b(subroutines)d(in)g(the)h(FITSIO)e(user)h(in)m(terface.) 46 b(F)-8 b(or)33 b(completeness,)0 2293 y(the)43 b(basic)g (subroutines)e(describ)s(ed)g(in)i(the)f(previous)h(c)m(hapter)g(are)g (also)g(rep)s(eated)g(here.)77 b(A)43 b(righ)m(t)g(arro)m(w)0 2406 y(sym)m(b)s(ol)29 b(is)f(used)g(here)h(to)g(separate)h(the)f (input)f(parameters)h(from)f(the)h(output)g(parameters)g(in)f(the)h (de\014nition)0 2518 y(of)k(eac)m(h)h(subroutine.)47 b(This)32 b(sym)m(b)s(ol)h(is)g(not)g(actually)i(part)d(of)h(the)h (calling)g(sequence.)49 b(An)32 b(alphab)s(etical)i(list)0 2631 y(and)c(de\014nition)g(of)g(all)i(the)e(parameters)h(is)f(giv)m (en)i(at)f(the)f(end)g(of)h(this)f(section.)0 2961 y Fd(6.1)135 b(FITS)44 b(File)i(Op)t(en)e(and)h(Close)h(Subroutines:)0 3197 y Fh(1)81 b Fi(Op)s(en)30 b(an)i(existing)g(FITS)g(\014le)f(with)h (readonly)g(or)g(readwrite)g(access.)46 b(The)31 b(FTDK)m(OPN)i (routine)e(simply)227 3310 y(op)s(ens)h(the)g(sp)s(eci\014ed)g(\014le)h (without)f(trying)h(to)g(in)m(terpret)g(the)f(\014lename)h(using)f(the) g(extended)h(\014lename)227 3423 y(syn)m(tax.)41 b(FTDOPN)28 b(op)s(ens)e(the)i(\014le)g(and)f(also)i(mo)m(v)m(es)g(to)g(the)f (\014rst)f(HDU)h(con)m(taining)h(signi\014can)m(t)g(data,)227 3536 y(if)35 b(no)h(sp)s(eci\014c)f(HDU)h(is)f(sp)s(eci\014ed)f(as)i (part)f(of)g(the)h(\014lename.)55 b(FTTOPN)35 b(and)f(FTIOPN)h(are)h (similar)227 3649 y(except)26 b(that)f(they)g(will)g(mo)m(v)m(e)h(to)g (the)f(\014rst)f(table)h(HDU)h(or)e(image)i(HDU,)g(resp)s(ectiv)m(ely) -8 b(,)28 b(if)c(a)h(HDU)h(name)227 3762 y(or)31 b(n)m(um)m(b)s(er)e (is)h(not)h(sp)s(eci\014ed)e(as)i(part)f(of)h(the)f(\014lename.)382 3996 y Fe(FTOPEN\(unit,filename,rwm)o(ode)o(,)42 b(>)47 b(blocksize,status\))382 4108 y(FTDKOPN\(unit,filename,rw)o(mod)o(e,)42 b(>)47 b(blocksize,status\))382 4334 y(FTDOPN\(unit,filename,rwm)o(ode) o(,)42 b(>)47 b(status\))382 4447 y(FTTOPN\(unit,filename,rwm)o(ode)o (,)42 b(>)47 b(status\))382 4560 y(FTIOPN\(unit,filename,rwm)o(ode)o(,) 42 b(>)47 b(status\))0 4794 y Fh(2)81 b Fi(Op)s(en)24 b(an)i(existing)h(FITS)e(\014le)h(with)f(readonly)h(or)g(readwrite)g (access)h(and)f(mo)m(v)m(e)h(to)f(a)h(follo)m(wing)g(extension,)227 4907 y(if)38 b(one)g(w)m(as)g(sp)s(eci\014ed)g(as)g(part)f(of)h(the)h (\014lename.)63 b(\(e.g.,)42 b('\014lename.\014ts+2')c(or)g ('\014lename.\014ts[2]')i(will)227 5020 y(mo)m(v)m(e)e(to)g(the)e(3rd)g (HDU)i(in)e(the)h(\014le\).)60 b(Note)37 b(that)h(this)e(routine)h (di\013ers)f(from)g(FTOPEN)g(in)g(that)h(it)227 5133 y(do)s(es)30 b(not)h(ha)m(v)m(e)h(the)e(redundan)m(t)f(blo)s(c)m(ksize) j(argumen)m(t.)382 5367 y Fe(FTNOPN\(unit,filename,rwm)o(ode)o(,)42 b(>)47 b(status\))0 5601 y Fh(3)81 b Fi(Reop)s(en)38 b(a)i(FITS)e(\014le)i(that)f(w)m(as)h(previously)f(op)s(ened)f(with)h (FTOPEN,)g(FTNOPN,)g(or)h(FTINIT.)e(The)227 5714 y(newunit)f(n)m(um)m (b)s(er)f(ma)m(y)j(then)e(b)s(e)g(treated)i(as)f(a)g(separate)g (\014le,)i(and)d(one)h(ma)m(y)h(sim)m(ultaneously)f(read)1905 5942 y(35)p eop end %%Page: 36 42 TeXDict begin 36 41 bop 0 299 a Fi(36)1319 b Fg(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)227 555 y Fi(or)36 b(write)g(to)g(2)g(\(or)g(more\))g (di\013eren)m(t)g(extensions)g(in)f(the)h(same)g(\014le.)56 b(The)35 b(FTOPEN)g(and)g(FTNOPN)227 668 y(routines)f(\(ab)s(o)m(v)m (e\))h(automatically)h(detects)f(cases)g(where)e(a)g(previously)h(op)s (ened)e(\014le)i(is)g(b)s(eing)f(op)s(ened)227 781 y(again,)c(and)e (then)g(in)m(ternally)h(call)g(FTREOPEN,)f(so)h(programs)e(should)h (rarely)g(need)g(to)h(explicitly)h(call)227 894 y(this)i(routine.)334 1136 y Fe(FTREOPEN\(unit,)44 b(>)j(newunit,)f(status\))0 1377 y Fh(4)81 b Fi(Op)s(en)24 b(and)g(initialize)k(a)e(new)f(empt)m(y) g(FITS)g(\014le.)39 b(The)25 b(FTDKINIT)g(routine)g(simply)g(creates)i (the)f(sp)s(eci\014ed)227 1490 y(\014le)31 b(without)f(trying)h(to)g (in)m(terpret)f(the)h(\014lename)g(using)e(the)i(extended)f(\014lename) h(syn)m(tax.)334 1732 y Fe(FTINIT\(unit,filename,bloc)o(ksi)o(ze,)41 b(>)48 b(status\))334 1845 y(FTDKINIT\(unit,filename,bl)o(ock)o(size)o (,)42 b(>)47 b(status\))0 2087 y Fh(5)81 b Fi(Create)24 b(a)g(new)f(FITS)g(\014le,)i(using)e(a)h(template)h(\014le)e(to)i (de\014ne)d(its)i(initial)h(size)g(and)e(structure.)37 b(The)24 b(template)227 2199 y(ma)m(y)39 b(b)s(e)f(another)h(FITS)e (HDU)i(or)g(an)f(ASCI)s(I)f(template)j(\014le.)64 b(If)38 b(the)h(input)e(template)j(\014le)e(name)h(is)227 2312 y(blank,)28 b(then)f(this)g(routine)g(b)s(eha)m(v)m(es)h(the)f(same)h (as)f(FTINIT.)g(The)f(curren)m(tly)i(supp)s(orted)d(format)i(of)h(the) 227 2425 y(ASCI)s(I)c(template)j(\014le)f(is)f(describ)s(ed)g(under)f (the)i(\014ts)p 2037 2425 28 4 v 32 w(parse)p 2277 2425 V 33 w(template)g(routine)g(\(in)g(the)f(general)i(Utilities)227 2538 y(section\),)32 b(but)e(this)g(ma)m(y)h(c)m(hange)h(sligh)m(tly)g (later)f(releases)g(of)g(CFITSIO.)334 2780 y Fe(FTTPLT\(unit,)45 b(filename,)g(tplfilename,)f(>)k(status\))0 3022 y Fh(6)81 b Fi(Flush)33 b(in)m(ternal)h(bu\013ers)f(of)h(data)g(to)g(the)g (output)g(FITS)f(\014le)h(previously)f(op)s(ened)g(with)g(ftop)s(en)h (or)f(ftinit.)227 3135 y(The)j(routine)h(usually)f(nev)m(er)h(needs)f (to)i(b)s(e)e(called,)j(but)d(doing)h(so)g(will)g(ensure)f(that)h(if)f (the)h(program)227 3247 y(subsequen)m(tly)30 b(ab)s(orts,)g(then)h(the) f(FITS)g(\014le)g(will)h(ha)m(v)m(e)h(at)f(least)g(b)s(een)f(closed)h (prop)s(erly)-8 b(.)382 3489 y Fe(FTFLUS\(unit,)44 b(>)k(status\))0 3731 y Fh(7)81 b Fi(Close)31 b(a)f(FITS)g(\014le)g(previously)g(op)s (ened)g(with)g(ftop)s(en)g(or)g(ftinit)382 3973 y Fe(FTCLOS\(unit,)44 b(>)k(status\))0 4214 y Fh(8)81 b Fi(Close)34 b(and)f(DELETE)g(a)h (FITS)f(\014le)h(previously)f(op)s(ened)g(with)g(ftop)s(en)g(or)h (ftinit.)51 b(This)33 b(routine)g(ma)m(y)i(b)s(e)227 4327 y(useful)29 b(in)h(cases)g(where)g(a)g(FITS)f(\014le)g(is)h (created,)h(but)e(an)h(error)f(o)s(ccurs)h(whic)m(h)f(prev)m(en)m(ts)i (the)e(complete)227 4440 y(\014le)i(from)f(b)s(eing)g(written.)382 4682 y Fe(FTDELT\(unit,)44 b(>)k(status\))0 4924 y Fh(9)81 b Fi(Get)31 b(the)g(v)-5 b(alue)31 b(of)f(an)g(un)m(used)g(I/O)g(unit)g (n)m(um)m(b)s(er)f(whic)m(h)h(ma)m(y)h(then)f(b)s(e)g(used)g(as)g (input)g(to)h(FTOPEN)f(or)227 5036 y(FTINIT.)36 b(This)f(routine)h (searc)m(hes)h(for)f(the)g(\014rst)f(un)m(used)g(unit)g(n)m(um)m(b)s (er)g(in)g(the)i(range)f(from)f(with)h(99)227 5149 y(do)m(wn)d(to)h (50.)50 b(This)32 b(routine)h(just)g(k)m(eeps)h(an)f(in)m(ternal)h (list)f(of)h(the)f(allo)s(cated)i(unit)e(n)m(um)m(b)s(ers)f(and)g(do)s (es)227 5262 y(not)26 b(ph)m(ysically)g(c)m(hec)m(k)g(that)g(the)g(F)-8 b(ortran)25 b(unit)g(is)g(a)m(v)-5 b(ailable)28 b(\(to)e(b)s(e)f (compatible)h(with)f(the)g(SPP)f(v)m(ersion)227 5375 y(of)35 b(FITSIO\).)g(Th)m(us)f(users)g(m)m(ust)h(not)g(indep)s(enden)m (tly)f(allo)s(cate)j(an)m(y)f(unit)e(n)m(um)m(b)s(ers)g(in)h(the)g (range)g(50)227 5488 y(-)42 b(99)g(if)f(this)g(routine)g(is)g(also)h (to)g(b)s(e)f(used)f(in)h(the)g(same)h(program.)73 b(This)40 b(routine)h(is)g(pro)m(vided)g(for)227 5601 y(con)m(v)m(enience)34 b(only)-8 b(,)32 b(and)e(it)i(is)f(not)h(required)e(that)i(the)f(unit)g (n)m(um)m(b)s(ers)f(used)g(b)m(y)h(FITSIO)f(b)s(e)h(allo)s(cated)227 5714 y(b)m(y)g(this)f(routine.)p eop end %%Page: 37 43 TeXDict begin 37 42 bop 0 299 a Fg(6.1.)72 b(FITS)30 b(FILE)g(OPEN)g(AND)h(CLOSE)e(SUBR)m(OUTINES:)1561 b Fi(37)382 555 y Fe(FTGIOU\()46 b(>)h(iounit,)f(status\))0 807 y Fh(10)g Fi(F)-8 b(ree)34 b(\(deallo)s(cate\))i(an)d(I/O)g(unit)f (n)m(um)m(b)s(er)g(whic)m(h)g(w)m(as)h(previously)g(allo)s(cated)i (with)e(FTGIOU.)g(All)g(pre-)227 919 y(viously)28 b(allo)s(cated)i (unit)d(n)m(um)m(b)s(ers)f(ma)m(y)i(b)s(e)f(deallo)s(cated)j(at)e(once) h(b)m(y)e(calling)i(FTFIOU)f(with)f(iounit)h(=)227 1032 y(-1.)382 1284 y Fe(FTFIOU\(iounit,)44 b(>)j(status\))0 1535 y Fh(11)f Fi(Return)30 b(the)h(F)-8 b(ortran)31 b(unit)g(n)m(um)m(b)s(er)e(that)i(corresp)s(onds)f(to)h(the)g(C)g (\014ts\014le)f(p)s(oin)m(ter)h(v)-5 b(alue,)32 b(or)e(vice)i(v)m (ersa.)227 1648 y(These)37 b(2)h(C)f(routines)g(ma)m(y)g(b)s(e)g (useful)f(in)h(mixed)g(language)i(programs)e(where)f(b)s(oth)h(C)g(and) f(F)-8 b(ortran)227 1761 y(subroutines)25 b(need)g(to)i(access)g(the)f (same)g(\014le.)40 b(F)-8 b(or)26 b(example,)i(if)e(a)g(FITS)f(\014le)h (is)g(op)s(ened)f(with)g(unit)g(12)i(b)m(y)227 1874 y(a)k(F)-8 b(ortran)31 b(subroutine,)f(then)g(a)h(C)f(routine)h(within)f(the)g (same)h(program)g(could)f(get)i(the)e(\014t\014le)h(p)s(oin)m(ter)227 1987 y(v)-5 b(alue)39 b(to)f(access)h(the)f(same)h(\014le)f(b)m(y)f (calling)j('fptr)d(=)h(CUnit2FITS\(12\)'.)64 b(These)38 b(routines)g(return)f(a)227 2100 y(v)-5 b(alue)31 b(of)g(zero)g(if)f (an)g(error)g(o)s(ccurs.)286 2351 y Fe(int)334 b(CFITS2Unit\(fitsfile) 42 b(*ptr\);)286 2464 y(fitsfile*)k(CUnit2FITS\(int)e(unit\);)0 2715 y Fh(11)i Fi(P)m(arse)32 b(the)g(input)e(\014lename)i(and)f (return)f(the)i(HDU)g(n)m(um)m(b)s(er)e(that)i(w)m(ould)f(b)s(e)g(mo)m (v)m(ed)i(to)f(if)f(the)h(\014le)f(w)m(ere)227 2828 y(op)s(ened)i(with) g(FTNOPN.)g(The)f(returned)g(HDU)i(n)m(um)m(b)s(er)e(b)s(egins)h(with)g (1)g(for)g(the)g(primary)g(arra)m(y)-8 b(,)35 b(so)227 2941 y(for)d(example,)g(if)g(the)g(input)f(\014lename)g(=)h(`m)m (y\014le.\014ts[2]')h(then)e(hdun)m(um)e(=)j(3)g(will)g(b)s(e)f (returned.)43 b(FIT-)227 3054 y(SIO)35 b(do)s(es)h(not)g(op)s(en)g(the) g(\014le)g(to)h(c)m(hec)m(k)h(if)e(the)g(extension)h(actually)h(exists) e(if)h(an)e(extension)i(n)m(um)m(b)s(er)227 3167 y(is)43 b(sp)s(eci\014ed.)75 b(If)42 b(an)g(extension)h(*name*)g(is)f(included) g(in)g(the)g(\014le)g(name)h(sp)s(eci\014cation)g(\(e.g.)77 b(`m)m(y-)227 3280 y(\014le.\014ts[EVENTS]')30 b(then)f(this)h(routine) g(will)g(ha)m(v)m(e)h(to)f(op)s(en)f(the)h(FITS)f(\014le)h(and)f(lo)s (ok)h(for)g(the)g(p)s(osition)227 3393 y(of)38 b(the)h(named)e (extension,)k(then)d(close)h(\014le)f(again.)64 b(This)38 b(is)g(not)g(p)s(ossible)f(if)h(the)g(\014le)g(is)g(b)s(eing)g(read)227 3506 y(from)e(the)g(stdin)f(stream,)j(and)d(an)h(error)f(will)h(b)s(e)g (returned)e(in)i(this)g(case.)58 b(If)35 b(the)h(\014lename)g(do)s(es)g (not)227 3619 y(sp)s(ecify)29 b(an)g(explicit)h(extension)g(\(e.g.)42 b('m)m(y\014le.\014ts'\))30 b(then)f(hdun)m(um)e(=)h(-99)j(will)e(b)s (e)g(returned,)f(whic)m(h)h(is)227 3731 y(functionally)34 b(equiv)-5 b(alen)m(t)35 b(to)g(hdun)m(um)c(=)i(1.)50 b(This)33 b(routine)g(is)h(mainly)g(used)e(for)i(bac)m(kw)m(ard)g (compati-)227 3844 y(bilit)m(y)g(in)e(the)g(fto)s(ols)h(soft)m(w)m(are) h(pac)m(k)-5 b(age)34 b(and)e(is)g(not)g(recommended)g(for)g(general)i (use.)46 b(It)32 b(is)h(generally)227 3957 y(b)s(etter)i(and)g(more)g (e\016cien)m(t)h(to)g(\014rst)e(op)s(en)g(the)h(FITS)f(\014le)h(with)g (FTNOPN,)g(then)g(use)f(FTGHDN)i(to)227 4070 y(determine)30 b(whic)m(h)g(HDU)g(in)f(the)h(\014le)g(has)g(b)s(een)f(op)s(ened,)g (rather)g(than)h(calling)h(FTEXTN)f(follo)m(w)m(ed)h(b)m(y)227 4183 y(a)g(call)h(to)f(FTNOPN.)382 4434 y Fe(FTEXTN\(filename,)43 b(>)48 b(nhdu,)e(status\))0 4686 y Fh(12)g Fi(Return)30 b(the)g(name)h(of)f(the)h(op)s(ened)e(FITS)h(\014le.)382 4937 y Fe(FTFLNM\(unit,)44 b(>)k(filename,)d(status\))0 5188 y Fh(13)h Fi(Return)30 b(the)g(I/O)g(mo)s(de)g(of)h(the)g(op)s(en) e(FITS)h(\014le)g(\(READONL)-8 b(Y)32 b(=)e(0,)h(READ)m(WRITE)g(=)f (1\).)382 5440 y Fe(FTFLMD\(unit,)44 b(>)k(iomode,)e(status\))0 5691 y Fh(14)g Fi(Return)30 b(the)g(\014le)h(t)m(yp)s(e)f(of)h(the)f (op)s(ened)g(FITS)g(\014le)g(\(e.g.)42 b('\014le://',)32 b('ftp://',)g(etc.\).)p eop end %%Page: 38 44 TeXDict begin 38 43 bop 0 299 a Fi(38)1319 b Fg(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)382 555 y Fe(FTURLT\(unit,)44 b(>)k(urltype,)d (status\))0 819 y Fh(15)h Fi(P)m(arse)27 b(the)f(input)f(\014lename)i (or)f(URL)g(in)m(to)h(its)g(comp)s(onen)m(t)f(parts:)39 b(the)26 b(\014le)g(t)m(yp)s(e)h(\(\014le://,)h(ftp://,)g(h)m(ttp://,) 227 932 y(etc\),)34 b(the)e(base)g(input)e(\014le)i(name,)g(the)g(name) g(of)g(the)g(output)f(\014le)h(that)g(the)g(input)f(\014le)g(is)h(to)g (b)s(e)f(copied)227 1045 y(to)38 b(prior)e(to)h(op)s(ening,)h(the)f (HDU)g(or)f(extension)i(sp)s(eci\014cation,)h(the)e(\014ltering)f(sp)s (eci\014er,)i(the)f(binning)227 1157 y(sp)s(eci\014er,)e(and)e(the)i (column)f(sp)s(eci\014er.)51 b(Blank)34 b(strings)g(will)h(b)s(e)e (returned)g(for)h(an)m(y)g(comp)s(onen)m(ts)g(that)227 1270 y(are)d(not)g(presen)m(t)f(in)g(the)h(input)e(\014le)i(name.)334 1534 y Fe(FTIURL\(filename,)43 b(>)48 b(filetype,)d(infile,)h(outfile,) g(extspec,)f(filter,)716 1647 y(binspec,)g(colspec,)h(status\))0 1910 y Fh(16)g Fi(P)m(arse)e(the)g(input)f(\014le)h(name)f(and)g (return)g(the)h(ro)s(ot)g(\014le)f(name.)81 b(The)43 b(ro)s(ot)h(name)g(includes)f(the)h(\014le)227 2023 y(t)m(yp)s(e)35 b(if)g(sp)s(eci\014ed,)h(\(e.g.)56 b('ftp://')37 b(or)e('h)m(ttp://'\)) i(and)d(the)h(full)g(path)g(name,)h(to)g(the)f(exten)m(t)i(that)e(it)h (is)227 2136 y(sp)s(eci\014ed)26 b(in)f(the)i(input)e(\014lename.)39 b(It)26 b(do)s(es)g(not)g(include)g(the)g(HDU)h(name)f(or)g(n)m(um)m(b) s(er,)g(or)g(an)m(y)h(\014ltering)227 2249 y(sp)s(eci\014cations.)334 2513 y Fe(FTRTNM\(filename,)43 b(>)48 b(rootname,)d(status\))0 2776 y Fh(16)h Fi(T)-8 b(est)36 b(if)g(the)g(input)f(\014le)h(or)f(a)i (compressed)e(v)m(ersion)h(of)g(the)g(\014le)g(\(with)g(a)g(.gz,)i(.Z,) e(.z,)i(or)e(.zip)g(extension\))227 2889 y(exists)j(on)f(disk.)63 b(The)37 b(returned)g(v)-5 b(alue)38 b(of)g(the)h('exists')g(parameter) f(will)g(ha)m(v)m(e)i(1)e(of)g(the)g(4)g(follo)m(wing)227 3002 y(v)-5 b(alues:)370 3257 y Fe(2:)95 b(the)47 b(file)g(does)g(not)f (exist,)h(but)f(a)i(compressed)d(version)h(does)g(exist)370 3370 y(1:)95 b(the)47 b(disk)g(file)g(does)f(exist)370 3483 y(0:)95 b(neither)46 b(the)h(file)g(nor)g(a)g(compressed)e (version)h(of)h(the)g(file)g(exist)323 3596 y(-1:)94 b(the)47 b(input)g(file)f(name)h(is)g(not)g(a)g(disk)g(file)g(\(could)f (be)h(a)g(ftp,)g(http,)561 3709 y(smem,)g(or)g(mem)g(file,)f(or)h(a)h (file)e(piped)h(in)g(on)g(the)g(STDIN)f(stream\))286 3973 y(FTEXIST\(filename,)d(>)48 b(exists,)e(status\);)0 4311 y Fd(6.2)135 b(HDU-Lev)l(el)47 b(Op)t(erations)0 4562 y Fi(When)30 b(a)h(FITS)f(\014le)g(is)h(\014rst)e(op)s(ened)h(or)g (created,)i(the)f(in)m(ternal)g(bu\013ers)e(in)h(FITSIO)f (automatically)34 b(p)s(oin)m(t)c(to)0 4675 y(the)g(\014rst)g(HDU)h(in) f(the)g(\014le.)41 b(The)29 b(follo)m(wing)j(routines)e(ma)m(y)h(b)s(e) e(used)h(to)h(mo)m(v)m(e)g(to)g(another)f(HDU)h(in)f(the)h(\014le.)0 4788 y(Note)j(that)f(the)g(HDU)g(n)m(um)m(b)s(ering)f(con)m(v)m(en)m (tion)i(used)e(in)g(FITSIO)g(denotes)h(the)f(primary)g(arra)m(y)h(as)g (the)g(\014rst)0 4901 y(HDU,)e(the)g(\014rst)f(extension)h(in)f(a)g (FITS)g(\014le)g(is)h(the)f(second)h(HDU,)g(and)f(so)h(on.)0 5164 y Fh(1)81 b Fi(Mo)m(v)m(e)32 b(to)f(a)g(sp)s(eci\014ed)f (\(absolute\))h(HDU)g(in)g(the)f(FITS)g(\014le)g(\(nhdu)f(=)h(1)h(for)f (the)g(FITS)g(primary)f(arra)m(y\))382 5428 y Fe(FTMAHD\(unit,nhdu,)43 b(>)k(hdutype,status\))0 5691 y Fh(2)81 b Fi(Mo)m(v)m(e)32 b(to)f(a)g(new)f(\(existing\))i(HDU)f(forw)m(ard)f(or)g(bac)m(kw)m (ards)h(relativ)m(e)h(to)f(the)g(CHDU)p eop end %%Page: 39 45 TeXDict begin 39 44 bop 0 299 a Fg(6.2.)72 b(HDU-LEVEL)31 b(OPERA)-8 b(TIONS)2414 b Fi(39)382 555 y Fe(FTMRHD\(unit,nmove,)43 b(>)k(hdutype,status\))0 797 y Fh(3)81 b Fi(Mo)m(v)m(e)22 b(to)f(the)f(\(\014rst\))h(HDU)g(whic)m(h)f(has)g(the)g(sp)s(eci\014ed) g(extension)h(t)m(yp)s(e)f(and)g(EXTNAME)g(\(or)h(HDUNAME\))227 910 y(and)34 b(EXTVER)g(k)m(eyw)m(ord)h(v)-5 b(alues.)53 b(The)34 b(hdut)m(yp)s(e)f(parameter)i(ma)m(y)g(ha)m(v)m(e)g(a)g(v)-5 b(alue)35 b(of)f(IMA)m(GE)p 3665 910 28 4 v 34 w(HDU)227 1023 y(\(0\),)43 b(ASCI)s(I)p 669 1023 V 31 w(TBL)c(\(1\),)j(BINAR)-8 b(Y)p 1468 1023 V 34 w(TBL)39 b(\(2\),)j(or)d(ANY)p 2234 1023 V 34 w(HDU)g(\(-1\))i(where)d(ANY)p 3173 1023 V 34 w(HDU)h(means)g(that)227 1136 y(only)30 b(the)g(extname)h(and)e (extv)m(er)i(v)-5 b(alues)30 b(will)g(b)s(e)f(used)g(to)i(lo)s(cate)g (the)f(correct)h(extension.)42 b(If)29 b(the)h(input)227 1249 y(v)-5 b(alue)27 b(of)f(extv)m(er)h(is)f(0)g(then)g(the)g(EXTVER)g (k)m(eyw)m(ord)g(is)g(ignored)g(and)g(the)g(\014rst)f(HDU)i(with)e(a)i (matc)m(hing)227 1361 y(EXTNAME)g(\(or)g(HDUNAME\))h(k)m(eyw)m(ord)f (will)g(b)s(e)f(found.)38 b(If)26 b(no)h(matc)m(hing)h(HDU)f(is)g (found)e(in)h(the)h(\014le)227 1474 y(then)i(the)g(curren)m(t)g(HDU)h (will)f(remain)g(unc)m(hanged)g(and)g(a)g(status)g(=)g(BAD)p 2884 1474 V 34 w(HDU)p 3123 1474 V 33 w(NUM)h(\(301\))h(will)f(b)s(e) 227 1587 y(returned.)382 1829 y Fe(FTMNHD\(unit,)44 b(hdutype,)i (extname,)f(extver,)h(>)i(status\))0 2071 y Fh(4)81 b Fi(Get)31 b(the)g(n)m(um)m(b)s(er)e(of)h(the)h(curren)m(t)f(HDU)h(in)f (the)h(FITS)e(\014le)i(\(primary)f(arra)m(y)g(=)g(1\))382 2312 y Fe(FTGHDN\(unit,)44 b(>)k(nhdu\))0 2554 y Fh(5)81 b Fi(Return)39 b(the)i(t)m(yp)s(e)g(of)g(the)g(curren)m(t)f(HDU)i(in)e (the)h(FITS)f(\014le.)71 b(The)41 b(p)s(ossible)f(v)-5 b(alues)41 b(for)f(hdut)m(yp)s(e)g(are)227 2667 y(IMA)m(GE)p 546 2667 V 34 w(HDU)31 b(\(0\),)h(ASCI)s(I)p 1242 2667 V 31 w(TBL)e(\(1\),)i(or)e(BINAR)-8 b(Y)p 2133 2667 V 34 w(TBL)30 b(\(2\).)382 2909 y Fe(FTGHDT\(unit,)44 b(>)k(hdutype,)d (status\))0 3150 y Fh(6)81 b Fi(Return)29 b(the)i(total)h(n)m(um)m(b)s (er)d(of)i(HDUs)f(in)h(the)f(FITS)g(\014le.)41 b(The)29 b(CHDU)i(remains)f(unc)m(hanged.)382 3392 y Fe(FTTHDU\(unit,)44 b(>)k(hdunum,)e(status\))0 3634 y Fh(7)81 b Fi(Create)34 b(\(app)s(end\))f(a)i(new)e(empt)m(y)h(HDU)h(at)g(the)f(end)f(of)h(the) h(FITS)e(\014le.)51 b(This)33 b(new)h(HDU)h(b)s(ecomes)f(the)227 3747 y(Curren)m(t)j(HDU,)i(but)e(it)h(is)g(completely)h(empt)m(y)f(and) g(con)m(tains)h(no)e(header)h(k)m(eyw)m(ords)g(or)g(data.)63 b(It)38 b(is)227 3860 y(recommended)30 b(that)h(FTI)s(IMG,)g(FTIT)-8 b(AB)30 b(or)h(FTIBIN)f(b)s(e)g(used)g(instead)g(of)h(this)f(routine.) 382 4101 y Fe(FTCRHD\(unit,)44 b(>)k(status\))0 4343 y Fh(8)81 b Fi(Create)30 b(a)f(primary)f(arra)m(y)i(\(if)g(none)f (already)g(exists\),)i(or)e(insert)g(a)h(new)f(IMA)m(GE)h(extension)g (immediately)227 4456 y(follo)m(wing)25 b(the)e(CHDU,)g(or)g(insert)g (a)g(new)g(Primary)f(Arra)m(y)h(at)h(the)f(b)s(eginning)f(of)h(the)g (\014le.)38 b(An)m(y)23 b(follo)m(wing)227 4569 y(extensions)29 b(in)g(the)g(\014le)f(will)h(b)s(e)f(shifted)h(do)m(wn)f(to)h(mak)m(e)h (ro)s(om)e(for)h(the)g(new)f(extension.)40 b(If)29 b(the)g(CHDU)227 4682 y(is)h(the)g(last)g(HDU)g(in)g(the)f(\014le)h(then)f(the)h(new)f (image)i(extension)f(will)g(simply)f(b)s(e)g(app)s(ended)f(to)i(the)g (end)227 4795 y(of)k(the)h(\014le.)52 b(One)33 b(can)h(force)h(a)g(new) e(primary)g(arra)m(y)i(to)g(b)s(e)e(inserted)h(at)h(the)f(b)s(eginning) f(of)h(the)h(FITS)227 4908 y(\014le)29 b(b)m(y)f(setting)i(status)e(=)h (-9)g(prior)e(to)j(calling)g(the)e(routine.)40 b(In)28 b(this)g(case)i(the)e(existing)i(primary)d(arra)m(y)227 5021 y(will)f(b)s(e)f(con)m(v)m(erted)i(to)g(an)e(IMA)m(GE)h (extension.)40 b(The)25 b(new)g(extension)i(\(or)f(primary)e(arra)m (y\))j(will)f(b)s(ecome)227 5133 y(the)32 b(CHDU.)f(The)g(FTI)s(IMGLL)f (routine)i(is)f(iden)m(tical)i(to)e(the)h(FTI)s(IMG)f(routine)g(except) h(that)f(the)h(4th)227 5246 y(parameter)25 b(\(the)g(length)g(of)f(eac) m(h)h(axis\))g(is)g(an)f(arra)m(y)h(of)f(64-bit)i(in)m(tegers)f(rather) f(than)g(an)g(arra)m(y)h(of)g(32-bit)227 5359 y(in)m(tegers.)382 5601 y Fe(FTIIMG\(unit,bitpix,naxis)o(,na)o(xes,)41 b(>)48 b(status\))382 5714 y(FTIIMGLL\(unit,bitpix,nax)o(is,)o(naxe)o(sll,)41 b(>)47 b(status\))p eop end %%Page: 40 46 TeXDict begin 40 45 bop 0 299 a Fi(40)1319 b Fg(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)0 555 y Fh(9)81 b Fi(Insert)30 b(a)i(new)f(ASCI)s(I)f (T)-8 b(ABLE)31 b(extension)h(immediately)h(follo)m(wing)f(the)g(CHDU.) g(An)m(y)f(follo)m(wing)i(exten-)227 668 y(sions)26 b(will)g(b)s(e)f (shifted)g(do)m(wn)g(to)h(mak)m(e)h(ro)s(om)e(for)h(the)f(new)g (extension.)40 b(If)25 b(there)h(are)g(no)g(other)f(follo)m(wing)227 781 y(extensions)32 b(then)f(the)h(new)f(table)h(extension)g(will)g (simply)f(b)s(e)g(app)s(ended)f(to)i(the)f(end)g(of)h(the)f(\014le.)44 b(The)227 894 y(new)33 b(extension)h(will)f(b)s(ecome)h(the)f(CHDU.)h (The)f(FTIT)-8 b(ABLL)33 b(routine)g(is)g(iden)m(tical)i(to)f(the)g (FTIT)-8 b(AB)227 1007 y(routine)36 b(except)g(that)g(the)f(2nd)g(and)g (3rd)g(parameters)g(\(that)i(giv)m(e)g(the)e(size)h(of)g(the)f(table\)) i(are)f(64-bit)227 1120 y(in)m(tegers)c(rather)e(than)g(32-bit)i(in)m (tegers.)382 1374 y Fe(FTITAB\(unit,rowlen,nrows)o(,tf)o(ield)o(s,tt)o (ype)o(,tbc)o(ol,t)o(for)o(m,tu)o(nit,)o(ext)o(name)o(,)42 b(>)716 1487 y(status\))382 1600 y(FTITABLL\(unit,rowlenll,n)o(row)o (sll,)o(tfie)o(lds)o(,tty)o(pe,t)o(bco)o(l,tf)o(orm,)o(tun)o(it,e)o (xtna)o(me,)f(>)716 1713 y(status\))0 1968 y Fh(10)46 b Fi(Insert)25 b(a)h(new)f(binary)f(table)j(extension)f(immediately)g (follo)m(wing)h(the)f(CHDU.)g(An)m(y)g(follo)m(wing)g(extensions)227 2081 y(will)39 b(b)s(e)f(shifted)g(do)m(wn)g(to)h(mak)m(e)g(ro)s(om)g (for)f(the)g(new)g(extension.)66 b(If)38 b(there)h(are)f(no)h(other)f (follo)m(wing)227 2194 y(extensions)f(then)g(the)f(new)g(bin)m(table)h (extension)h(will)f(simply)f(b)s(e)g(app)s(ended)e(to)k(the)e(end)g(of) h(the)g(\014le.)227 2307 y(The)23 b(new)g(extension)h(will)f(b)s(ecome) h(the)f(CHDU.)h(The)f(FTIBINLL)g(routine)g(is)g(iden)m(tical)i(to)f (the)g(FTIBIN)227 2419 y(routine)30 b(except)i(that)e(the)h(2nd)e (parameter)i(\(that)g(giv)m(es)g(the)g(length)f(of)h(the)f(table\))h (is)g(a)f(64-bit)i(in)m(teger)227 2532 y(rather)f(than)f(a)g(32-bit)i (in)m(teger.)382 2787 y Fe(FTIBIN\(unit,nrows,tfield)o(s,t)o(type)o (,tfo)o(rm,)o(tuni)o(t,ex)o(tna)o(me,v)o(arid)o(at)41 b(>)48 b(status\))382 2900 y(FTIBINLL\(unit,nrowsll,tf)o(iel)o(ds,t)o (type)o(,tf)o(orm,)o(tuni)o(t,e)o(xtna)o(me,v)o(ari)o(dat)41 b(>)48 b(status\))0 3267 y Fh(11)e Fi(Resize)26 b(an)e(image)i(b)m(y)e (mo)s(di\014ng)f(the)i(size,)i(dimensions,)e(and/or)f(datat)m(yp)s(e)h (of)g(the)g(curren)m(t)f(primary)f(arra)m(y)227 3380 y(or)29 b(image)i(extension.)40 b(If)29 b(the)g(new)g(image,)i(as)e(sp) s(eci\014ed)f(b)m(y)h(the)g(input)f(argumen)m(ts,)i(is)f(larger)h(than) f(the)227 3493 y(curren)m(t)34 b(existing)h(image)g(in)f(the)g(FITS)f (\014le)h(then)f(zero)i(\014ll)f(data)h(will)f(b)s(e)f(inserted)h(at)g (the)g(end)g(of)g(the)227 3606 y(curren)m(t)25 b(image)h(and)e(an)m(y)i (follo)m(wing)g(extensions)g(will)f(b)s(e)f(mo)m(v)m(ed)i(further)e (bac)m(k)h(in)g(the)g(\014le.)39 b(Similarly)-8 b(,)27 b(if)227 3719 y(the)h(new)e(image)j(is)e(smaller)h(than)f(the)g(curren) m(t)g(image)h(then)f(an)m(y)h(follo)m(wing)h(extensions)e(will)h(b)s(e) e(shifted)227 3832 y(up)32 b(to)m(w)m(ards)i(the)g(b)s(eginning)e(of)h (the)h(FITS)e(\014le)h(and)g(the)g(image)h(data)g(will)g(b)s(e)e (truncated)h(to)h(the)f(new)227 3945 y(size.)41 b(This)25 b(routine)h(rewrites)h(the)f(BITPIX,)h(NAXIS,)f(and)g(NAXISn)g(k)m(eyw) m(ords)g(with)g(the)h(appropriate)227 4058 y(v)-5 b(alues)37 b(for)f(new)h(image.)60 b(The)36 b(FTRSIMLL)g(routine)g(is)h(iden)m (tical)h(to)g(the)e(FTRSIM)g(routine)h(except)227 4171 y(that)30 b(the)g(4th)g(parameter)g(\(the)g(length)g(of)f(eac)m(h)i (axis\))f(is)g(an)f(arra)m(y)h(of)g(64-bit)h(in)m(tegers)f(rather)g (than)f(an)227 4284 y(arra)m(y)i(of)g(32-bit)g(in)m(tegers.)382 4538 y Fe(FTRSIM\(unit,bitpix,naxis)o(,na)o(xes,)o(stat)o(us\))382 4651 y(FTRSIMLL\(unit,bitpix,nax)o(is,)o(naxe)o(sll,)o(sta)o(tus\))0 4906 y Fh(12)46 b Fi(Delete)34 b(the)f(CHDU)g(in)f(the)g(FITS)f (\014le.)47 b(An)m(y)32 b(follo)m(wing)i(HDUs)f(will)g(b)s(e)e(shifted) h(forw)m(ard)g(in)g(the)g(\014le,)h(to)227 5019 y(\014ll)38 b(in)f(the)g(gap)h(created)g(b)m(y)g(the)f(deleted)h(HDU.)h(In)d(the)i (case)g(of)g(deleting)g(the)g(primary)e(arra)m(y)i(\(the)227 5132 y(\014rst)30 b(HDU)h(in)f(the)h(\014le\))g(then)f(the)h(curren)m (t)f(primary)f(arra)m(y)i(will)g(b)s(e)f(replace)h(b)m(y)g(a)g(n)m(ull) f(primary)f(arra)m(y)227 5245 y(con)m(taining)k(the)f(minim)m(um)e(set) i(of)g(required)e(k)m(eyw)m(ords)i(and)e(no)i(data.)44 b(If)31 b(there)g(are)h(more)f(extensions)227 5357 y(in)f(the)g(\014le) g(follo)m(wing)i(the)e(one)g(that)h(is)f(deleted,)h(then)f(the)g(the)g (CHDU)h(will)f(b)s(e)g(rede\014ned)e(to)j(p)s(oin)m(t)f(to)227 5470 y(the)d(follo)m(wing)h(extension.)41 b(If)26 b(there)h(are)g(no)g (follo)m(wing)h(extensions)f(then)g(the)g(CHDU)g(will)g(b)s(e)f (rede\014ned)227 5583 y(to)35 b(p)s(oin)m(t)f(to)h(the)f(previous)f (HDU.)i(The)e(output)h(HDUTYPE)g(parameter)h(indicates)f(the)h(t)m(yp)s (e)f(of)g(the)227 5696 y(new)c(CHDU)h(after)g(the)f(previous)g(CHDU)h (has)f(b)s(een)g(deleted.)p eop end %%Page: 41 47 TeXDict begin 41 46 bop 0 299 a Fg(6.3.)72 b(DEFINE)31 b(OR)f(REDEFINE)h(THE)f(STR)m(UCTURE)f(OF)h(THE)g(CHDU)1042 b Fi(41)382 555 y Fe(FTDHDU\(unit,)44 b(>)k(hdutype,status\))0 828 y Fh(13)e Fi(Cop)m(y)36 b(all)h(or)f(part)g(of)g(the)g(input)f (FITS)g(\014le)h(and)g(app)s(end)e(it)i(to)h(the)f(end)g(of)g(the)g (output)g(FITS)f(\014le.)57 b(If)227 941 y('previous')39 b(\(an)g(in)m(teger)h(parameter\))g(is)f(not)g(equal)g(to)h(0,)h(then)e (an)m(y)g(HDUs)g(preceding)g(the)g(curren)m(t)227 1054 y(HDU)f(in)e(the)h(input)e(\014le)i(will)g(b)s(e)f(copied)h(to)g(the)g (output)f(\014le.)60 b(Similarly)-8 b(,)39 b('curren)m(t')e(and)f ('follo)m(wing')227 1167 y(determine)j(whether)f(the)h(curren)m(t)g (HDU,)h(and/or)e(an)m(y)i(follo)m(wing)g(HDUs)f(in)g(the)g(input)f (\014le)g(will)i(b)s(e)227 1280 y(copied)32 b(to)g(the)g(output)f (\014le.)43 b(If)31 b(all)h(3)g(parameters)g(are)g(not)f(equal)h(to)g (zero,)h(then)e(the)g(en)m(tire)h(input)f(\014le)227 1393 y(will)g(b)s(e)e(copied.)41 b(On)30 b(return,)f(the)h(curren)m(t)g (HDU)h(in)f(the)g(input)f(\014le)h(will)h(b)s(e)e(unc)m(hanged,)h(and)g (the)g(last)227 1506 y(copied)h(HDU)g(will)g(b)s(e)f(the)g(curren)m(t)g (HDU)i(in)e(the)g(output)g(\014le.)382 1779 y Fe(FTCPFL\(iunit,)44 b(ounit,)i(previous,)f(current,)h(following,)f(>)i(status\))0 2052 y Fh(14)f Fi(Cop)m(y)35 b(the)f(en)m(tire)i(CHDU)f(from)f(the)g (FITS)g(\014le)h(asso)s(ciated)h(with)e(IUNIT)g(to)i(the)e(CHDU)h(of)g (the)g(FITS)227 2165 y(\014le)g(asso)s(ciated)h(with)e(OUNIT.)g(The)g (output)g(HDU)h(m)m(ust)f(b)s(e)g(empt)m(y)h(and)e(not)i(already)g(con) m(tain)h(an)m(y)227 2278 y(k)m(eyw)m(ords.)41 b(Space)29 b(will)g(b)s(e)g(reserv)m(ed)g(for)g(MOREKEYS)f(additional)h(k)m(eyw)m (ords)h(in)e(the)i(output)e(header)227 2391 y(if)j(there)f(is)h(not)f (already)h(enough)f(space.)382 2664 y Fe(FTCOPY\(iunit,ounit,morek)o (eys)o(,)42 b(>)47 b(status\))0 2937 y Fh(15)f Fi(Cop)m(y)27 b(the)h(header)f(\(and)g(not)g(the)g(data\))i(from)d(the)i(CHDU)g(asso) s(ciated)g(with)f(in)m(unit)g(to)h(the)f(CHDU)h(asso-)227 3050 y(ciated)f(with)e(outunit.)39 b(If)25 b(the)g(curren)m(t)h(output) f(HDU)h(is)f(not)h(completely)h(empt)m(y)-8 b(,)27 b(then)e(the)h(CHDU) g(will)227 3163 y(b)s(e)e(closed)i(and)e(a)i(new)e(HDU)h(will)h(b)s(e)e (app)s(ended)f(to)j(the)f(output)f(\014le.)39 b(This)24 b(routine)h(will)g(automatically)227 3276 y(transform)31 b(the)g(necessary)h(k)m(eyw)m(ords)f(when)g(cop)m(ying)h(a)f(primary)g (arra)m(y)h(to)f(and)g(image)i(extension,)f(or)227 3389 y(an)27 b(image)h(extension)f(to)g(a)h(primary)d(arra)m(y)-8 b(.)41 b(An)26 b(empt)m(y)h(output)f(data)i(unit)e(will)h(b)s(e)f (created)i(\(all)g(v)-5 b(alues)227 3501 y(=)30 b(0\).)382 3775 y Fe(FTCPHD\(inunit,)44 b(outunit,)h(>)j(status\))0 4048 y Fh(16)e Fi(Cop)m(y)d(just)g(the)g(data)h(from)f(the)g(CHDU)h (asso)s(ciated)g(with)f(IUNIT)g(to)h(the)f(CHDU)h(asso)s(ciated)g(with) 227 4161 y(OUNIT.)26 b(This)f(will)h(o)m(v)m(erwrite)h(an)m(y)f(data)g (previously)g(in)f(the)h(OUNIT)f(CHDU.)h(This)f(lo)m(w)i(lev)m(el)g (routine)227 4274 y(is)g(used)e(b)m(y)i(FTCOPY,)f(but)g(it)g(ma)m(y)i (also)f(b)s(e)f(useful)f(in)i(certain)g(application)h(programs)e(whic)m (h)g(w)m(an)m(t)h(to)227 4386 y(cop)m(y)j(the)f(data)h(from)f(one)g (FITS)f(\014le)h(to)h(another)f(but)g(also)h(w)m(an)m(t)g(to)g(mo)s (dify)e(the)h(header)g(k)m(eyw)m(ords)g(in)227 4499 y(the)j(pro)s (cess.)44 b(all)33 b(the)f(required)f(header)g(k)m(eyw)m(ords)h(m)m (ust)g(b)s(e)f(written)h(to)g(the)g(OUNIT)f(CHDU)h(b)s(efore)227 4612 y(calling)g(this)e(routine)382 4885 y Fe(FTCPDT\(iunit,ounit,)42 b(>)48 b(status\))0 5235 y Fd(6.3)135 b(De\014ne)45 b(or)g(Rede\014ne)h (the)f(structure)g(of)g(the)g(CHDU)0 5488 y Fi(It)32 b(should)f(rarely)h(b)s(e)g(necessary)g(to)h(call)g(the)f(subroutines)f (in)g(this)h(section.)47 b(FITSIO)30 b(in)m(ternally)j(calls)g(these)0 5601 y(routines)h(whenev)m(er)g(necessary)-8 b(,)36 b(so)e(an)m(y)g (calls)h(to)g(these)f(routines)g(b)m(y)g(application)h(programs)f(will) g(lik)m(ely)i(b)s(e)0 5714 y(redundan)m(t.)p eop end %%Page: 42 48 TeXDict begin 42 47 bop 0 299 a Fi(42)1319 b Fg(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)0 555 y Fh(1)81 b Fi(This)36 b(routine)h(forces)h (FITSIO)e(to)i(scan)f(the)g(curren)m(t)g(header)g(k)m(eyw)m(ords)h (that)f(de\014ne)g(the)g(structure)g(of)227 668 y(the)31 b(HDU)f(\(suc)m(h)g(as)h(the)f(NAXISn,)g(PCOUNT)f(and)g(GCOUNT)h(k)m (eyw)m(ords\))h(so)f(that)h(it)f(can)h(initialize)227 781 y(the)36 b(in)m(ternal)g(bu\013ers)e(that)i(describ)s(e)f(the)h (HDU)g(structure.)55 b(This)35 b(routine)h(ma)m(y)g(b)s(e)e(used)h (instead)h(of)227 894 y(the)j(more)g(complicated)i(calls)f(to)f(ftp)s (def,)h(ftadef)f(or)g(ftb)s(def.)65 b(This)38 b(routine)h(is)g(also)h (v)m(ery)f(useful)f(for)227 1007 y(reinitializing)e(the)e(structure)g (of)g(an)f(HDU,)i(if)f(the)g(n)m(um)m(b)s(er)e(of)i(ro)m(ws)g(in)g(a)g (table,)i(as)e(sp)s(eci\014ed)f(b)m(y)h(the)227 1120 y(NAXIS2)d(k)m(eyw)m(ord,)g(has)f(b)s(een)g(mo)s(di\014ed)f(from)h(its) h(initial)g(v)-5 b(alue.)382 1361 y Fe(FTRDEF\(unit,)44 b(>)k(status\))141 b(\(DEPRECATED\))0 1602 y Fh(2)81 b Fi(De\014ne)27 b(the)g(structure)g(of)g(the)g(primary)f(arra)m(y)i (or)f(IMA)m(GE)h(extension.)40 b(When)27 b(writing)g(GR)m(OUP)m(ed)h (FITS)227 1715 y(\014les)43 b(that)h(b)m(y)e(con)m(v)m(en)m(tion)k(set) d(the)g(NAXIS1)g(k)m(eyw)m(ord)h(equal)f(to)h(0,)i(ftp)s(def)c(m)m(ust) h(b)s(e)f(called)i(with)227 1828 y(naxes\(1\))27 b(=)e(1,)i(NOT)e(0,)i (otherwise)f(FITSIO)e(will)i(rep)s(ort)f(an)g(error)g(status=308)i (when)d(trying)i(to)g(write)227 1941 y(data)31 b(to)g(a)g(group.)40 b(Note:)i(it)31 b(is)g(usually)f(simpler)g(to)h(call)h(FTRDEF)e(rather) h(than)f(this)g(routine.)382 2182 y Fe(FTPDEF\(unit,bitpix,naxis)o(,na) o(xes,)o(pcou)o(nt,)o(gcou)o(nt,)41 b(>)48 b(status\))93 b(\(DEPRECATED\))0 2424 y Fh(3)81 b Fi(De\014ne)32 b(the)h(structure)f (of)g(an)h(ASCI)s(I)e(table)i(\(T)-8 b(ABLE\))33 b(extension.)48 b(Note:)e(it)33 b(is)f(usually)g(simpler)g(to)i(call)227 2537 y(FTRDEF)d(rather)f(than)h(this)f(routine.)382 2778 y Fe(FTADEF\(unit,rowlen,tfiel)o(ds,)o(tbco)o(l,tf)o(orm)o(,nro)o(ws)42 b(>)47 b(status\))f(\(DEPRECATED\))0 3019 y Fh(4)81 b Fi(De\014ne)35 b(the)h(structure)f(of)g(a)h(binary)f(table)h(\(BINT)-8 b(ABLE\))37 b(extension.)56 b(Note:)d(it)36 b(is)f(usually)g(simpler)g (to)227 3132 y(call)d(FTRDEF)f(rather)f(than)g(this)g(routine.)382 3373 y Fe(FTBDEF\(unit,tfields,tfor)o(m,v)o(arid)o(at,n)o(row)o(s)42 b(>)47 b(status\))f(\(DEPRECATED\))0 3615 y Fh(5)81 b Fi(De\014ne)34 b(the)g(size)h(of)f(the)g(Curren)m(t)f(Data)i(Unit,)h(o) m(v)m(erriding)e(the)g(length)h(of)f(the)g(data)h(unit)e(as)h (previously)227 3728 y(de\014ned)e(b)m(y)h(ftp)s(def,)g(ftadef,)i(or)e (ftb)s(def.)48 b(This)33 b(is)g(useful)f(if)i(one)f(do)s(es)g(not)h (kno)m(w)f(the)g(total)i(size)f(of)g(the)227 3841 y(data)f(unit)f(un)m (til)h(after)f(the)h(data)g(ha)m(v)m(e)g(b)s(een)f(written.)46 b(The)32 b(size)h(\(in)f(b)m(ytes\))h(of)g(an)f(ASCI)s(I)f(or)h(Binary) 227 3954 y(table)27 b(is)f(giv)m(en)g(b)m(y)g(NAXIS1)g(*)g(NAXIS2.)40 b(\(Note)27 b(that)f(to)h(determine)f(the)f(v)-5 b(alue)27 b(of)f(NAXIS1)f(it)i(is)f(often)227 4066 y(more)32 b(con)m(v)m(enien)m (t)h(to)f(read)f(the)g(v)-5 b(alue)32 b(of)f(the)h(NAXIS1)f(k)m(eyw)m (ord)h(from)e(the)i(output)e(\014le,)i(rather)f(than)227 4179 y(computing)f(the)g(ro)m(w)g(length)h(directly)f(from)f(all)i(the) f(TF)m(ORM)h(k)m(eyw)m(ord)f(v)-5 b(alues\).)41 b(Note:)h(it)30 b(is)g(usually)227 4292 y(simpler)g(to)h(call)h(FTRDEF)f(rather)f(than) g(this)g(routine.)382 4534 y Fe(FTDDEF\(unit,bytlen,)42 b(>)48 b(status\))e(\(DEPRECATED\))0 4775 y Fh(6)81 b Fi(De\014ne)22 b(the)g(zero)i(indexed)d(b)m(yte)i(o\013set)g(of)g(the)f ('heap')h(measured)e(from)h(the)h(start)g(of)f(the)g(binary)g(table)h (data.)227 4888 y(By)30 b(default)g(the)f(heap)h(is)f(assumed)g(to)h (start)g(immediately)h(follo)m(wing)g(the)f(regular)f(table)i(data,)f (i.e.,)h(at)227 5001 y(lo)s(cation)38 b(NAXIS1)f(x)g(NAXIS2.)59 b(This)36 b(routine)g(is)h(only)f(relev)-5 b(an)m(t)38 b(for)e(binary)g(tables)h(whic)m(h)g(con)m(tain)227 5114 y(v)-5 b(ariable)36 b(length)g(arra)m(y)f(columns)g(\(with)h(TF)m(ORMn) f(=)f('Pt'\).)57 b(This)34 b(subroutine)g(also)i(automatically)227 5227 y(writes)23 b(the)g(v)-5 b(alue)23 b(of)g(theap)g(to)h(a)f(k)m (eyw)m(ord)g(in)g(the)g(extension)g(header.)38 b(This)22 b(subroutine)g(m)m(ust)h(b)s(e)f(called)227 5339 y(after)27 b(the)f(required)f(k)m(eyw)m(ords)i(ha)m(v)m(e)g(b)s(een)e(written)h (\(with)g(ftph)m(bn\))f(and)h(after)g(the)h(table)g(structure)e(has)227 5452 y(b)s(een)30 b(de\014ned)f(\(with)h(ftb)s(def)7 b(\))30 b(but)g(b)s(efore)g(an)m(y)g(data)h(is)g(written)f(to)h(the)g (table.)382 5694 y Fe(FTPTHP\(unit,theap,)43 b(>)k(status\))p eop end %%Page: 43 49 TeXDict begin 43 48 bop 0 299 a Fg(6.4.)72 b(FITS)30 b(HEADER)h(I/O)f(SUBR)m(OUTINES)2086 b Fi(43)0 555 y Fd(6.4)135 b(FITS)44 b(Header)i(I/O)f(Subroutines)0 809 y Fb(6.4.1)112 b(Header)38 b(Space)h(and)f(P)m(osition)f(Routines)0 1019 y Fh(1)81 b Fi(Reserv)m(e)37 b(space)g(in)f(the)h(CHU)f(for)h (MOREKEYS)e(more)i(header)f(k)m(eyw)m(ords.)59 b(This)36 b(subroutine)f(ma)m(y)j(b)s(e)227 1132 y(called)e(to)g(reserv)m(e)g (space)f(for)g(k)m(eyw)m(ords)g(whic)m(h)g(are)g(to)h(b)s(e)e(written)h (at)g(a)h(later)g(time,)h(after)e(the)g(data)227 1245 y(unit)h(or)g(subsequen)m(t)f(extensions)h(ha)m(v)m(e)h(b)s(een)e (written)h(to)h(the)f(FITS)f(\014le.)58 b(If)35 b(this)h(subroutine)f (is)h(not)227 1358 y(explicitly)29 b(called,)g(then)e(the)g(initial)i (size)e(of)h(the)f(FITS)f(header)h(will)h(b)s(e)e(limited)i(to)g(the)f (space)h(a)m(v)-5 b(ailable)227 1471 y(at)24 b(the)g(time)g(that)g(the) g(\014rst)f(data)h(is)g(written)f(to)h(the)g(asso)s(ciated)h(data)f (unit.)38 b(FITSIO)22 b(has)i(the)f(abilit)m(y)i(to)227 1584 y(dynamically)g(add)e(more)h(space)h(to)g(the)f(header)g(if)g (needed,)h(ho)m(w)m(ev)m(er)g(it)g(is)f(more)g(e\016cien)m(t)h(to)g (preallo)s(cate)227 1697 y(the)31 b(required)e(space)i(if)g(the)f(size) h(is)g(kno)m(wn)f(in)g(adv)-5 b(ance.)382 1958 y Fe (FTHDEF\(unit,morekeys,)42 b(>)47 b(status\))0 2219 y Fh(2)81 b Fi(Return)23 b(the)i(n)m(um)m(b)s(er)e(of)h(existing)i(k)m (eyw)m(ords)e(in)h(the)f(CHU)g(\(NOT)h(including)f(the)g(END)h(k)m(eyw) m(ord)g(whic)m(h)f(is)227 2332 y(not)g(considered)f(a)g(real)h(k)m(eyw) m(ord\))g(and)f(the)g(remaining)h(space)f(a)m(v)-5 b(ailable)26 b(to)e(write)f(additional)i(k)m(eyw)m(ords)227 2445 y(in)39 b(the)h(CHU.)f(\(returns)f(KEYSADD)i(=)f(-1)h(if)f(the)g(header)g(has)g (not)h(y)m(et)g(b)s(een)e(closed\).)69 b(Note)40 b(that)227 2558 y(FITSIO)23 b(will)i(attempt)g(to)g(dynamically)g(add)e(space)i (for)f(more)g(k)m(eyw)m(ords)h(if)f(required)f(when)g(app)s(ending)227 2671 y(new)30 b(k)m(eyw)m(ords)h(to)g(a)g(header.)382 2932 y Fe(FTGHSP\(iunit,)44 b(>)j(keysexist,keysadd,status\))0 3194 y Fh(3)81 b Fi(Return)38 b(the)i(n)m(um)m(b)s(er)e(of)h(k)m(eyw)m (ords)h(in)f(the)g(header)g(and)g(the)g(curren)m(t)h(p)s(osition)f(in)g (the)g(header.)68 b(This)227 3307 y(returns)37 b(the)g(n)m(um)m(b)s(er) f(of)i(the)g(k)m(eyw)m(ord)g(record)f(that)h(will)g(b)s(e)f(read)g (next)h(\(or)g(one)g(greater)g(than)g(the)227 3420 y(p)s(osition)29 b(of)f(the)h(last)g(k)m(eyw)m(ord)g(that)g(w)m(as)f(read)g(or)h (written\).)40 b(A)29 b(v)-5 b(alue)28 b(of)h(1)g(is)f(returned)f(if)h (the)h(p)s(oin)m(ter)227 3533 y(is)i(p)s(ositioned)f(at)h(the)g(b)s (eginning)e(of)i(the)g(header.)382 3794 y Fe(FTGHPS\(iunit,)44 b(>)j(keysexist,key_no,status\))0 4086 y Fb(6.4.2)112 b(Read)38 b(or)f(W)-9 b(rite)37 b(Standard)i(Header)e(Routines)0 4306 y Fi(These)31 b(subroutines)e(pro)m(vide)i(a)g(simple)g(metho)s(d) f(of)h(reading)g(or)g(writing)g(most)g(of)g(the)g(k)m(eyw)m(ord)g(v)-5 b(alues)31 b(that)0 4419 y(are)d(normally)g(required)f(in)h(a)g(FITS)f (\014les.)40 b(These)27 b(subroutines)g(are)h(pro)m(vided)f(for)h(con)m (v)m(enience)h(only)f(and)g(are)0 4532 y(not)36 b(required)e(to)i(b)s (e)f(used.)55 b(If)35 b(preferred,)h(users)e(ma)m(y)i(call)h(the)f(lo)m (w)m(er-lev)m(el)i(subroutines)c(describ)s(ed)h(in)g(the)0 4644 y(previous)30 b(section)i(to)g(individually)f(read)f(or)h(write)g (the)g(required)f(k)m(eyw)m(ords.)43 b(Note)32 b(that)g(in)e(most)i (cases,)g(the)0 4757 y(required)26 b(k)m(eyw)m(ords)h(suc)m(h)g(as)g (NAXIS,)f(TFIELD,)h(TTYPEn,)g(etc,)i(whic)m(h)d(de\014ne)g(the)h (structure)f(of)h(the)g(HDU)0 4870 y(m)m(ust)j(b)s(e)g(written)g(to)i (the)e(header)g(b)s(efore)g(an)m(y)h(data)g(can)g(b)s(e)e(written)i(to) g(the)g(image)g(or)g(table.)0 5132 y Fh(1)81 b Fi(Put)37 b(the)i(primary)e(header)h(or)g(IMA)m(GE)h(extension)f(k)m(eyw)m(ords)h (in)m(to)g(the)f(CHU.)g(There)g(are)g(2)h(a)m(v)-5 b(ailable)227 5245 y(routines:)39 b(The)27 b(simpler)f(FTPHPS)h(routine)g(is)g(equiv) -5 b(alen)m(t)29 b(to)e(calling)i(ftphpr)c(with)i(the)g(default)h(v)-5 b(alues)227 5357 y(of)35 b(SIMPLE)f(=)g(true,)i(p)s(coun)m(t)e(=)g(0,)i (gcoun)m(t)g(=)e(1,)i(and)e(EXTEND)h(=)f(true.)53 b(PCOUNT,)34 b(GCOUNT)227 5470 y(and)23 b(EXTEND)h(k)m(eyw)m(ords)g(are)h(not)f (required)f(in)g(the)h(primary)f(header)g(and)h(are)g(only)g(written)g (if)f(p)s(coun)m(t)227 5583 y(is)31 b(not)g(equal)h(to)g(zero,)g(gcoun) m(t)g(is)f(not)g(equal)g(to)h(zero)g(or)f(one,)g(and)g(if)g(extend)g (is)g(TR)m(UE,)g(resp)s(ectiv)m(ely)-8 b(.)227 5696 y(When)30 b(writing)h(to)g(an)f(IMA)m(GE)i(extension,)f(the)f(SIMPLE)g(and)g (EXTEND)g(parameters)h(are)g(ignored.)p eop end %%Page: 44 50 TeXDict begin 44 49 bop 0 299 a Fi(44)1319 b Fg(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)382 555 y Fe(FTPHPS\(unit,bitpix,naxis)o(,na)o(xes,)41 b(>)48 b(status\))382 781 y(FTPHPR\(unit,simple,bitpi)o(x,n)o(axis)o (,nax)o(es,)o(pcou)o(nt,g)o(cou)o(nt,e)o(xten)o(d,)41 b(>)48 b(status\))0 1082 y Fh(2)81 b Fi(Get)44 b(primary)e(header)h(or) h(IMA)m(GE)g(extension)g(k)m(eyw)m(ords)g(from)f(the)g(CHU.)h(When)f (reading)g(from)g(an)227 1195 y(IMA)m(GE)32 b(extension)f(the)f(SIMPLE) g(and)f(EXTEND)i(parameters)g(are)f(ignored.)382 1495 y Fe(FTGHPR\(unit,maxdim,)42 b(>)48 b(simple,bitpix,naxis,naxe)o(s,p)o (coun)o(t,gc)o(oun)o(t,ex)o(tend)o(,)716 1608 y(status\))0 1909 y Fh(3)81 b Fi(Put)34 b(the)h(ASCI)s(I)f(table)i(header)f(k)m(eyw) m(ords)g(in)m(to)h(the)f(CHU.)h(The)e(optional)i(TUNITn)e(and)h (EXTNAME)227 2021 y(k)m(eyw)m(ords)c(are)g(written)f(only)h(if)f(the)h (input)e(string)h(v)-5 b(alues)31 b(are)g(not)f(blank.)382 2322 y Fe(FTPHTB\(unit,rowlen,nrows)o(,tf)o(ield)o(s,tt)o(ype)o(,tbc)o (ol,t)o(for)o(m,tu)o(nit,)o(ext)o(name)o(,)42 b(>)716 2435 y(status\))0 2736 y Fh(4)81 b Fi(Get)31 b(the)g(ASCI)s(I)d(table)k (header)e(k)m(eyw)m(ords)h(from)e(the)i(CHU)382 3036 y Fe(FTGHTB\(unit,maxdim,)42 b(>)48 b(rowlen,nrows,tfields,tty)o(pe,)o (tbco)o(l,tf)o(orm)o(,tun)o(it,)716 3149 y(extname,status\))0 3450 y Fh(5)81 b Fi(Put)34 b(the)h(binary)f(table)i(header)e(k)m(eyw)m (ords)i(in)m(to)f(the)g(CHU.)g(The)g(optional)h(TUNITn)e(and)g(EXTNAME) 227 3563 y(k)m(eyw)m(ords)i(are)g(written)f(only)g(if)h(the)f(input)f (string)i(v)-5 b(alues)35 b(are)h(not)f(blank.)55 b(The)35 b(p)s(coun)m(t)g(parameter,)227 3675 y(whic)m(h)f(sp)s(eci\014es)g(the) h(size)g(of)g(the)f(v)-5 b(ariable)35 b(length)g(arra)m(y)g(heap,)g (should)f(initially)h(=)f(0;)j(FITSIO)d(will)227 3788 y(automatically)27 b(up)s(date)c(the)h(PCOUNT)f(k)m(eyw)m(ord)h(v)-5 b(alue)24 b(if)g(an)m(y)g(v)-5 b(ariable)25 b(length)f(arra)m(y)h(data) f(is)g(written)227 3901 y(to)31 b(the)e(heap.)41 b(The)29 b(TF)m(ORM)g(k)m(eyw)m(ord)h(v)-5 b(alue)30 b(for)g(v)-5 b(ariable)30 b(length)g(v)m(ector)h(columns)e(should)g(ha)m(v)m(e)i (the)227 4014 y(form)c('Pt\(len\)')j(or)d('1Pt\(len\)')j(where)d(`t')h (is)g(the)g(data)g(t)m(yp)s(e)g(co)s(de)f(letter)i(\(A,I,J,E,D,)g (etc.\))42 b(and)27 b(`len')h(is)227 4127 y(an)g(in)m(teger)i(sp)s (ecifying)e(the)g(maxim)m(um)g(length)g(of)h(the)f(v)m(ectors)h(in)f (that)h(column)f(\(len)g(m)m(ust)g(b)s(e)g(greater)227 4240 y(than)j(or)h(equal)f(to)i(the)e(longest)i(v)m(ector)f(in)f(the)h (column\).)44 b(If)30 b(`len')i(is)g(not)f(sp)s(eci\014ed)g(when)f(the) i(table)g(is)227 4353 y(created)27 b(\(e.g.,)i(the)d(input)f(TF)m(ORMn) h(v)-5 b(alue)26 b(is)g(just)f('1Pt'\))j(then)d(FITSIO)g(will)h(scan)g (the)g(column)g(when)227 4466 y(the)k(table)g(is)f(\014rst)g(closed)h (and)f(will)g(app)s(end)f(the)h(maxim)m(um)h(length)f(to)h(the)g(TF)m (ORM)f(k)m(eyw)m(ord)h(v)-5 b(alue.)227 4579 y(Note)28 b(that)e(if)g(the)g(table)h(is)f(subsequen)m(tly)g(mo)s(di\014ed)f(to)i (increase)f(the)h(maxim)m(um)f(length)g(of)g(the)g(v)m(ectors)227 4692 y(then)k(the)h(mo)s(difying)f(program)g(is)g(resp)s(onsible)g(for) g(also)h(up)s(dating)e(the)i(TF)m(ORM)g(k)m(eyw)m(ord)g(v)-5 b(alue.)382 4992 y Fe(FTPHBN\(unit,nrows,tfield)o(s,t)o(type)o(,tfo)o (rm,)o(tuni)o(t,ex)o(tna)o(me,v)o(arid)o(at,)41 b(>)48 b(status\))0 5293 y Fh(6)81 b Fi(Get)31 b(the)g(binary)e(table)i (header)g(k)m(eyw)m(ords)f(from)g(the)h(CHU)382 5593 y Fe(FTGHBN\(unit,maxdim,)42 b(>)48 b(nrows,tfields,ttype,tfor)o(m,t)o (unit)o(,ext)o(nam)o(e,va)o(rida)o(t,)716 5706 y(status\))p eop end %%Page: 45 51 TeXDict begin 45 50 bop 0 299 a Fg(6.4.)72 b(FITS)30 b(HEADER)h(I/O)f(SUBR)m(OUTINES)2086 b Fi(45)0 555 y Fb(6.4.3)112 b(W)-9 b(rite)37 b(Keyw)m(ord)g(Subroutines)0 764 y Fh(1)81 b Fi(Put)30 b(\(app)s(end\))f(an)h(80-c)m(haracter)j (record)e(in)m(to)g(the)g(CHU.)382 1020 y Fe(FTPREC\(unit,card,)43 b(>)k(status\))0 1276 y Fh(2)81 b Fi(Put)36 b(\(app)s(end\))g(a)i (COMMENT)f(k)m(eyw)m(ord)g(in)m(to)h(the)g(CHU.)f(Multiple)h(COMMENT)f (k)m(eyw)m(ords)g(will)h(b)s(e)227 1389 y(written)31 b(if)f(the)h(input)e(commen)m(t)i(string)g(is)f(longer)h(than)f(72)i(c) m(haracters.)382 1645 y Fe(FTPCOM\(unit,comment,)42 b(>)48 b(status\))0 1901 y Fh(3)81 b Fi(Put)24 b(\(app)s(end\))g(a)h(HISTOR)-8 b(Y)25 b(k)m(eyw)m(ord)g(in)m(to)h(the)f(CHU.)g(Multiple)h(HISTOR)-8 b(Y)24 b(k)m(eyw)m(ords)h(will)h(b)s(e)e(written)227 2014 y(if)31 b(the)f(input)g(history)g(string)g(is)h(longer)g(than)f (72)h(c)m(haracters.)382 2270 y Fe(FTPHIS\(unit,history,)42 b(>)48 b(status\))0 2526 y Fh(4)81 b Fi(Put)36 b(\(app)s(end\))f(the)h (D)m(A)-8 b(TE)38 b(k)m(eyw)m(ord)f(in)m(to)g(the)f(CHU.)h(The)f(k)m (eyw)m(ord)g(v)-5 b(alue)37 b(will)g(con)m(tain)h(the)e(curren)m(t)227 2639 y(system)c(date)g(as)g(a)f(c)m(haracter)i(string)f(in)f ('dd/mm/yy')g(format.)44 b(If)31 b(a)h(D)m(A)-8 b(TE)32 b(k)m(eyw)m(ord)g(already)g(exists)227 2752 y(in)j(the)g(header,)i (then)d(this)h(subroutine)f(will)i(simply)e(up)s(date)h(the)g(k)m(eyw)m (ord)g(v)-5 b(alue)36 b(in-place)g(with)f(the)227 2865 y(curren)m(t)30 b(date.)382 3121 y Fe(FTPDAT\(unit,)44 b(>)k(status\))0 3377 y Fh(5)81 b Fi(Put)22 b(\(app)s(end\))f(a)i(new)f (k)m(eyw)m(ord)h(of)g(the)f(appropriate)h(datat)m(yp)s(e)g(in)m(to)h (the)e(CHU.)h(Note)h(that)f(FTPKYS)f(will)227 3490 y(only)33 b(write)g(string)f(v)-5 b(alues)33 b(up)e(to)j(68)f(c)m(haracters)h(in) e(length;)i(longer)f(strings)g(will)f(b)s(e)g(truncated.)47 b(The)227 3603 y(FTPKLS)27 b(routine)h(can)h(b)s(e)f(used)f(to)i(write) f(longer)h(strings,)g(using)e(a)i(non-standard)e(FITS)h(con)m(v)m(en)m (tion.)227 3716 y(The)23 b(E)h(and)f(D)h(v)m(ersions)g(of)g(this)f (routine)h(ha)m(v)m(e)h(the)f(added)f(feature)h(that)g(if)g(the)g ('decimals')h(parameter)f(is)227 3829 y(negativ)m(e,)i(then)20 b(the)i('G')g(displa)m(y)f(format)g(rather)g(then)g(the)g('E')h(format) f(will)h(b)s(e)e(used)g(when)g(constructing)227 3942 y(the)25 b(k)m(eyw)m(ord)f(v)-5 b(alue,)26 b(taking)f(the)g(absolute)g (v)-5 b(alue)24 b(of)h('decimals')g(for)f(the)g(precision.)39 b(This)23 b(will)i(suppress)227 4055 y(trailing)35 b(zeros,)h(and)d (will)i(use)e(a)i(\014xed)e(format)h(rather)g(than)f(an)h(exp)s(onen)m (tial)h(format,)h(dep)s(ending)c(on)227 4168 y(the)f(magnitude)f(of)h (the)f(v)-5 b(alue.)382 4424 y Fe(FTPKY[JKLS]\(unit,keyword)o(,ke)o (yval)o(,com)o(men)o(t,)42 b(>)47 b(status\))382 4537 y(FTPKY[EDFG]\(unit,keyword)o(,ke)o(yval)o(,dec)o(ima)o(ls,c)o(omme)o (nt,)41 b(>)48 b(status\))0 4793 y Fh(6)81 b Fi(Put)33 b(\(app)s(end\))h(a)g(string)g(v)-5 b(alued)34 b(k)m(eyw)m(ord)h(in)m (to)g(the)g(CHU)f(whic)m(h)g(ma)m(y)g(b)s(e)g(longer)h(than)e(68)i(c)m (haracters)227 4906 y(in)j(length.)64 b(This)37 b(uses)h(the)g(Long)g (String)g(Keyw)m(ord)g(con)m(v)m(en)m(tion)i(that)e(is)g(describ)s(ed)f (in)h(the)g("Usage)227 5019 y(Guidelines)33 b(and)e(Suggestions")j (section)f(of)g(this)f(do)s(cumen)m(t.)46 b(Since)33 b(this)f(uses)g(a)g(non-standard)g(FITS)227 5132 y(con)m(v)m(en)m(tion) 38 b(to)d(enco)s(de)h(the)f(long)h(k)m(eyw)m(ord)f(string,)i(programs)d (whic)m(h)h(use)g(this)g(routine)g(should)f(also)227 5245 y(call)e(the)e(FTPLSW)g(routine)h(to)g(add)e(some)i(COMMENT)f(k)m (eyw)m(ords)h(to)g(w)m(arn)f(users)f(of)i(the)f(FITS)g(\014le)227 5357 y(that)36 b(this)f(con)m(v)m(en)m(tion)j(is)d(b)s(eing)g(used.)55 b(FTPLSW)35 b(also)h(writes)g(a)f(k)m(eyw)m(ord)h(called)h(LONGSTRN)d (to)227 5470 y(record)c(the)h(v)m(ersion)f(of)h(the)f(longstring)h(con) m(v)m(en)m(tion)h(that)f(has)f(b)s(een)g(used,)f(in)h(case)h(a)g(new)f (con)m(v)m(en)m(tion)227 5583 y(is)f(adopted)g(at)g(some)g(p)s(oin)m(t) f(in)h(the)f(future.)40 b(If)28 b(the)g(LONGSTRN)g(k)m(eyw)m(ord)h(is)g (already)g(presen)m(t)f(in)h(the)227 5696 y(header,)i(then)f(FTPLSW)g (will)g(simply)g(return)g(and)f(will)i(not)g(write)f(duplicate)h(k)m (eyw)m(ords.)p eop end %%Page: 46 52 TeXDict begin 46 51 bop 0 299 a Fi(46)1319 b Fg(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)382 555 y Fe(FTPKLS\(unit,keyword,keyv)o(al,)o(comm)o (ent,)41 b(>)47 b(status\))382 668 y(FTPLSW\(unit,)d(>)k(status\))0 889 y Fh(7)81 b Fi(Put)30 b(\(app)s(end\))g(a)h(new)f(k)m(eyw)m(ord)h (with)f(an)h(unde\014ned,)e(or)h(n)m(ull,)h(v)-5 b(alue)31 b(in)m(to)h(the)f(CHU.)g(The)f(v)-5 b(alue)31 b(string)227 1002 y(of)g(the)f(k)m(eyw)m(ord)h(is)g(left)g(blank)f(in)g(this)g (case.)382 1223 y Fe(FTPKYU\(unit,keyword,comm)o(ent)o(,)42 b(>)47 b(status\))0 1445 y Fh(8)81 b Fi(Put)41 b(\(app)s(end\))g(a)i(n) m(um)m(b)s(ered)d(sequence)j(of)f(k)m(eyw)m(ords)g(in)m(to)h(the)g (CHU.)f(One)f(ma)m(y)i(app)s(end)d(the)j(same)227 1558 y(commen)m(t)37 b(to)g(ev)m(ery)g(k)m(eyw)m(ord)g(\(and)f(eliminate)h (the)g(need)f(to)h(ha)m(v)m(e)g(an)f(arra)m(y)h(of)f(iden)m(tical)i (commen)m(t)227 1670 y(strings,)g(one)e(for)g(eac)m(h)h(k)m(eyw)m (ord\))g(b)m(y)f(including)g(the)g(amp)s(ersand)e(c)m(haracter)k(as)e (the)h(last)g(non-blank)227 1783 y(c)m(haracter)g(in)e(the)h (\(\014rst\))f(COMMENTS)f(string)h(parameter.)56 b(This)35 b(same)g(string)h(will)f(then)g(b)s(e)g(used)227 1896 y(for)30 b(the)g(commen)m(t)h(\014eld)f(in)f(all)i(the)f(k)m(eyw)m (ords.)41 b(\(Note)32 b(that)e(the)g(SPP)f(v)m(ersion)i(of)f(these)g (routines)g(only)227 2009 y(supp)s(orts)f(a)i(single)g(commen)m(t)g (string\).)382 2230 y Fe(FTPKN[JKLS]\(unit,keyroot)o(,st)o(artn)o(o,no) o(_ke)o(ys,k)o(eyva)o(ls,)o(comm)o(ents)o(,)42 b(>)47 b(status\))382 2343 y(FTPKN[EDFG]\(unit,keyroot)o(,st)o(artn)o(o,no)o (_ke)o(ys,k)o(eyva)o(ls,)o(deci)o(mals)o(,co)o(mmen)o(ts,)41 b(>)907 2456 y(status\))0 2677 y Fh(9)81 b Fi(Cop)m(y)21 b(an)h(indexed)f(k)m(eyw)m(ord)i(from)e(one)h(HDU)h(to)f(another,)i(mo) s(difying)e(the)g(index)f(n)m(um)m(b)s(er)f(of)i(the)g(k)m(eyw)m(ord) 227 2790 y(name)37 b(in)f(the)g(pro)s(cess.)58 b(F)-8 b(or)37 b(example,)i(this)d(routine)h(could)f(read)g(the)h(TLMIN3)f(k)m (eyw)m(ord)h(from)f(the)227 2903 y(input)28 b(HDU)h(\(b)m(y)f(giving)h (k)m(eyro)s(ot)h(=)d("TLMIN")i(and)f(inn)m(um)f(=)h(3\))h(and)f(write)g (it)h(to)g(the)f(output)g(HDU)227 3016 y(with)36 b(the)g(k)m(eyw)m(ord) h(name)f(TLMIN4)g(\(b)m(y)g(setting)i(outn)m(um)d(=)h(4\).)58 b(If)36 b(the)g(input)f(k)m(eyw)m(ord)i(do)s(es)f(not)227 3129 y(exist,)c(then)e(this)g(routine)g(simply)g(returns)f(without)i (indicating)g(an)f(error.)382 3350 y Fe(FTCPKY\(inunit,)44 b(outunit,)h(innum,)h(outnum,)g(keyroot,)g(>)h(status\))0 3571 y Fh(10)f Fi(Put)33 b(\(app)s(end\))f(a)h('triple)h(precision')g (k)m(eyw)m(ord)f(in)m(to)h(the)g(CHU)f(in)g(F28.16)i(format.)49 b(The)33 b(\015oating)h(p)s(oin)m(t)227 3684 y(k)m(eyw)m(ord)c(v)-5 b(alue)30 b(is)f(constructed)h(b)m(y)f(concatenating)j(the)d(input)g (in)m(teger)i(v)-5 b(alue)29 b(with)g(the)h(input)e(double)227 3797 y(precision)22 b(fraction)h(v)-5 b(alue)23 b(\(whic)m(h)f(m)m(ust) g(ha)m(v)m(e)h(a)f(v)-5 b(alue)23 b(b)s(et)m(w)m(een)g(0.0)g(and)e (1.0\).)40 b(The)21 b(FTGKYT)h(routine)227 3910 y(should)35 b(b)s(e)h(used)f(to)i(read)f(this)f(k)m(eyw)m(ord)i(v)-5 b(alue,)38 b(b)s(ecause)e(the)g(other)h(k)m(eyw)m(ord)f(reading)g (subroutines)227 4023 y(will)31 b(not)g(preserv)m(e)f(the)h(full)f (precision)g(of)h(the)f(v)-5 b(alue.)382 4244 y Fe (FTPKYT\(unit,keyword,intv)o(al,)o(dblv)o(al,c)o(omm)o(ent,)41 b(>)48 b(status\))0 4466 y Fh(11)e Fi(W)-8 b(rite)36 b(k)m(eyw)m(ords)g(to)f(the)h(CHDU)f(that)h(are)f(de\014ned)f(in)g(an)h (ASCI)s(I)f(template)i(\014le.)55 b(The)34 b(format)i(of)f(the)227 4578 y(template)d(\014le)f(is)f(describ)s(ed)f(under)g(the)i(ftgthd)f (routine)g(b)s(elo)m(w.)382 4800 y Fe(FTPKTP\(unit,)44 b(filename,)i(>)h(status\))0 5021 y Fh(12)f Fi(App)s(end)28 b(the)i(ph)m(ysical)g(units)g(string)g(to)g(an)g(existing)h(k)m(eyw)m (ord.)41 b(This)29 b(routine)h(uses)f(a)h(lo)s(cal)i(con)m(v)m(en)m (tion,)227 5134 y(sho)m(wn)g(in)g(the)h(follo)m(wing)h(example,)g(in)e (whic)m(h)g(the)h(k)m(eyw)m(ord)g(units)f(are)h(enclosed)g(in)f(square) g(brac)m(k)m(ets)227 5247 y(in)e(the)h(b)s(eginning)f(of)g(the)h(k)m (eyw)m(ord)g(commen)m(t)g(\014eld.)239 5468 y Fe(VELOCITY=)809 b(12.3)46 b(/)i([km/s])e(orbital)g(speed)382 5694 y (FTPUNT\(unit,keyword,unit)o(s,)41 b(>)48 b(status\))p eop end %%Page: 47 53 TeXDict begin 47 52 bop 0 299 a Fg(6.4.)72 b(FITS)30 b(HEADER)h(I/O)f(SUBR)m(OUTINES)2086 b Fi(47)0 555 y Fb(6.4.4)112 b(Insert)38 b(Keyw)m(ord)f(Subroutines)0 762 y Fh(1)81 b Fi(Insert)26 b(a)h(new)f(k)m(eyw)m(ord)h(record)g(in)m (to)g(the)g(CHU)g(at)g(the)g(sp)s(eci\014ed)f(p)s(osition)h(\(i.e.,)i (immediately)f(preceding)227 875 y(the)34 b(\(k)m(eyno\)th)g(k)m(eyw)m (ord)g(in)f(the)h(header.\))49 b(This)33 b('insert)g(record')h (subroutine)e(is)h(somewhat)h(less)g(e\016-)227 988 y(cien)m(t)28 b(then)f(the)g('app)s(end)e(record')i(subroutine)f(\(FTPREC\))g (describ)s(ed)g(ab)s(o)m(v)m(e)i(b)s(ecause)f(the)g(remaining)227 1101 y(k)m(eyw)m(ords)k(in)f(the)h(header)f(ha)m(v)m(e)h(to)g(b)s(e)f (shifted)g(do)m(wn)g(one)h(slot.)382 1349 y Fe (FTIREC\(unit,key_no,card,)41 b(>)47 b(status\))0 1598 y Fh(2)81 b Fi(Insert)36 b(a)h(new)f(k)m(eyw)m(ord)i(in)m(to)g(the)f (CHU.)g(The)f(new)g(k)m(eyw)m(ord)i(is)f(inserted)f(immediately)i (follo)m(wing)h(the)227 1711 y(last)27 b(k)m(eyw)m(ord)g(that)f(has)g (b)s(een)g(read)g(from)f(the)h(header.)40 b(The)25 b(FTIKLS)g (subroutine)g(w)m(orks)h(the)g(same)h(as)227 1824 y(the)h(FTIKYS)e (subroutine,)h(except)i(it)f(also)g(supp)s(orts)e(long)i(string)f(v)-5 b(alues)28 b(greater)g(than)f(68)h(c)m(haracters)227 1937 y(in)36 b(length.)59 b(These)36 b('insert)g(k)m(eyw)m(ord')h (subroutines)e(are)i(somewhat)g(less)f(e\016cien)m(t)i(then)e(the)g ('app)s(end)227 2049 y(k)m(eyw)m(ord')30 b(subroutines)e(describ)s(ed)g (ab)s(o)m(v)m(e)i(b)s(ecause)f(the)g(remaining)h(k)m(eyw)m(ords)f(in)g (the)g(header)g(ha)m(v)m(e)h(to)227 2162 y(b)s(e)g(shifted)g(do)m(wn)g (one)h(slot.)382 2411 y Fe(FTIKEY\(unit,)44 b(card,)j(>)g(status\))382 2524 y(FTIKY[JKLS]\(unit,keyword)o(,ke)o(yval)o(,com)o(men)o(t,)42 b(>)47 b(status\))382 2637 y(FTIKLS\(unit,keyword,keyv)o(al,)o(comm)o (ent,)41 b(>)47 b(status\))382 2750 y(FTIKY[EDFG]\(unit,keyword)o(,ke)o (yval)o(,dec)o(ima)o(ls,c)o(omme)o(nt,)41 b(>)48 b(status\))0 2998 y Fh(3)81 b Fi(Insert)32 b(a)i(new)f(k)m(eyw)m(ord)h(with)f(an)h (unde\014ned,)e(or)h(n)m(ull,)h(v)-5 b(alue)34 b(in)m(to)h(the)e(CHU.)h (The)f(v)-5 b(alue)34 b(string)f(of)h(the)227 3111 y(k)m(eyw)m(ord)d (is)g(left)g(blank)f(in)g(this)g(case.)382 3359 y Fe (FTIKYU\(unit,keyword,comm)o(ent)o(,)42 b(>)47 b(status\))0 3648 y Fb(6.4.5)112 b(Read)38 b(Keyw)m(ord)g(Subroutines)0 3867 y Fi(These)29 b(routines)f(return)g(the)h(v)-5 b(alue)29 b(of)g(the)g(sp)s(eci\014ed)f(k)m(eyw)m(ord\(s\).)41 b(Wild)30 b(card)e(c)m(haracters)i(\(*,)h(?,)e(or)g(#\))f(ma)m(y)0 3980 y(b)s(e)f(used)h(when)f(sp)s(ecifying)h(the)g(name)g(of)g(the)g(k) m(eyw)m(ord)h(to)g(b)s(e)e(read:)39 b(a)29 b(')10 b(?')40 b(will)28 b(matc)m(h)h(an)m(y)g(single)f(c)m(haracter)0 4093 y(at)38 b(that)g(p)s(osition)f(in)g(the)h(k)m(eyw)m(ord)g(name)f (and)g(a)g('*')i(will)e(matc)m(h)h(an)m(y)g(length)g(\(including)f (zero\))h(string)g(of)0 4206 y(c)m(haracters.)65 b(The)37 b('#')h(c)m(haracter)h(will)f(matc)m(h)h(an)m(y)f(consecutiv)m(e)i (string)e(of)g(decimal)h(digits)f(\(0)h(-)f(9\).)64 b(Note)0 4319 y(that)30 b(when)f(a)g(wild)g(card)h(is)f(used)g(in)g(the)h(input) e(k)m(eyw)m(ord)i(name,)g(the)g(routine)f(will)h(only)g(searc)m(h)g (for)f(a)h(matc)m(h)0 4432 y(from)h(the)h(curren)m(t)g(header)g(p)s (osition)g(to)g(the)h(end)e(of)h(the)g(header.)45 b(It)32 b(will)g(not)g(resume)g(the)g(searc)m(h)g(from)g(the)0 4545 y(top)i(of)h(the)f(header)g(bac)m(k)h(to)g(the)f(original)h (header)f(p)s(osition)g(as)h(is)f(done)g(when)f(no)h(wildcards)f(are)i (included)0 4657 y(in)f(the)g(k)m(eyw)m(ord)h(name.)52 b(If)33 b(the)h(desired)g(k)m(eyw)m(ord)h(string)f(is)g(8-c)m (haracters)i(long)f(\(the)f(maxim)m(um)g(length)h(of)0 4770 y(a)h(k)m(eyw)m(ord)g(name\))g(then)g(a)g('*')g(ma)m(y)h(b)s(e)e (app)s(ended)f(as)h(the)h(nin)m(th)g(c)m(haracter)h(of)f(the)f(input)g (name)h(to)g(force)0 4883 y(the)31 b(k)m(eyw)m(ord)g(searc)m(h)h(to)f (stop)g(at)g(the)g(end)f(of)h(the)g(header)g(\(e.g.,)i('COMMENT)d(*')i (will)f(searc)m(h)g(for)g(the)g(next)0 4996 y(COMMENT)37 b(k)m(eyw)m(ord\).)64 b(The)37 b(\013grec)i(routine)f(ma)m(y)g(b)s(e)f (used)g(to)i(set)f(the)g(starting)g(p)s(osition)g(when)f(doing)0 5109 y(wild)30 b(card)g(searc)m(hes.)0 5357 y Fh(1)81 b Fi(Get)37 b(the)f(n)m(th)f(80-c)m(haracter)k(header)d(record)g(from)f (the)h(CHU.)h(The)e(\014rst)g(k)m(eyw)m(ord)i(in)e(the)h(header)g(is)g (at)227 5470 y(k)m(ey)p 365 5470 28 4 v 34 w(no)42 b(=)f(1;)49 b(if)42 b(k)m(ey)p 996 5470 V 34 w(no)g(=)f(0)i(then)e(this)h (subroutine)f(simple)h(mo)m(v)m(es)i(the)e(in)m(ternal)h(p)s(oin)m(ter) f(to)h(the)227 5583 y(b)s(eginning)35 b(of)h(the)g(header)f(so)h(that)g (subsequen)m(t)f(k)m(eyw)m(ord)h(op)s(erations)g(will)g(start)g(at)g (the)g(top)g(of)g(the)227 5696 y(header;)31 b(it)g(also)g(returns)e(a)i (blank)f(card)g(v)-5 b(alue)31 b(in)f(this)g(case.)p eop end %%Page: 48 54 TeXDict begin 48 53 bop 0 299 a Fi(48)1319 b Fg(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)382 555 y Fe(FTGREC\(unit,key_no,)42 b(>)48 b(card,status\))0 797 y Fh(2)81 b Fi(Get)31 b(the)g(name,)f(v)-5 b(alue)31 b(\(as)g(a)g(string\),)g(and)f(commen)m(t)i(of)e(the)h(n)m (th)f(k)m(eyw)m(ord)h(in)f(CHU.)h(This)f(routine)g(also)227 910 y(c)m(hec)m(ks)h(that)f(the)g(returned)e(k)m(eyw)m(ord)i(name)f (\(KEYW)m(ORD\))i(con)m(tains)g(only)e(legal)i(ASCI)s(I)d(c)m (haracters.)227 1023 y(Call)j(FTGREC)f(and)g(FTPSV)m(C)g(to)h(b)m (ypass)f(this)g(error)g(c)m(hec)m(k.)382 1264 y Fe (FTGKYN\(unit,key_no,)42 b(>)48 b(keyword,value,comment,st)o(atu)o(s\)) 0 1506 y Fh(3)81 b Fi(Get)31 b(the)g(80-c)m(haracter)i(header)d(record) g(for)g(the)h(named)f(k)m(eyw)m(ord)382 1748 y Fe (FTGCRD\(unit,keyword,)42 b(>)48 b(card,status\))0 1990 y Fh(4)81 b Fi(Get)26 b(the)f(next)h(k)m(eyw)m(ord)f(whose)g(name)h (matc)m(hes)g(one)f(of)h(the)f(strings)g(in)g('inclist')i(but)d(do)s (es)h(not)g(matc)m(h)i(an)m(y)227 2102 y(of)32 b(the)f(strings)g(in)g ('exclist'.)45 b(The)30 b(strings)h(in)g(inclist)h(and)f(exclist)h(ma)m (y)g(con)m(tain)h(wild)d(card)h(c)m(haracters)227 2215 y(\(*,)38 b(?,)e(and)e(#\))i(as)f(describ)s(ed)f(at)i(the)f(b)s (eginning)f(of)i(this)f(section.)56 b(This)34 b(routine)h(searc)m(hes)h (from)f(the)227 2328 y(curren)m(t)28 b(header)f(p)s(osition)h(to)g(the) g(end)f(of)h(the)g(header,)g(only)-8 b(,)29 b(and)e(do)s(es)g(not)h (con)m(tin)m(ue)h(the)f(searc)m(h)g(from)227 2441 y(the)41 b(top)g(of)g(the)g(header)g(bac)m(k)h(to)f(the)g(original)h(p)s (osition.)73 b(The)40 b(curren)m(t)h(header)f(p)s(osition)h(ma)m(y)h(b) s(e)227 2554 y(reset)33 b(with)e(the)h(ftgrec)h(routine.)44 b(Note)33 b(that)g(nexc)f(ma)m(y)g(b)s(e)f(set)h(=)g(0)g(if)f(there)h (are)g(no)g(k)m(eyw)m(ords)g(to)h(b)s(e)227 2667 y(excluded.)41 b(This)29 b(routine)i(returns)e(status)i(=)f(202)h(if)g(a)f(matc)m (hing)i(k)m(eyw)m(ord)f(is)f(not)h(found.)382 2909 y Fe(FTGNXK\(unit,inclist,ninc)o(,ex)o(clis)o(t,ne)o(xc,)41 b(>)48 b(card,status\))0 3150 y Fh(5)81 b Fi(Get)30 b(the)g(literal)i (k)m(eyw)m(ord)e(v)-5 b(alue)30 b(as)g(a)g(c)m(haracter)i(string.)40 b(Regardless)31 b(of)f(the)g(datat)m(yp)s(e)g(of)g(the)g(k)m(eyw)m (ord,)227 3263 y(this)37 b(routine)g(simply)g(returns)f(the)h(string)g (of)g(c)m(haracters)i(in)d(the)i(v)-5 b(alue)37 b(\014eld)g(of)g(the)g (k)m(eyw)m(ord)h(along)227 3376 y(with)30 b(the)h(commen)m(t)g (\014eld.)382 3618 y Fe(FTGKEY\(unit,keyword,)42 b(>)48 b(value,comment,status\))0 3860 y Fh(6)81 b Fi(Get)31 b(a)g(k)m(eyw)m(ord)g(v)-5 b(alue)30 b(\(with)h(the)f(appropriate)h (datat)m(yp)s(e\))g(and)f(commen)m(t)i(from)e(the)g(CHU)382 4101 y Fe(FTGKY[EDJKLS]\(unit,keywo)o(rd,)41 b(>)48 b (keyval,comment,status\))0 4343 y Fh(7)81 b Fi(Read)22 b(a)g(string-v)-5 b(alued)23 b(k)m(eyw)m(ord)f(and)g(return)e(the)j (string)f(length,)i(the)e(v)-5 b(alue)23 b(string,)h(and/or)e(the)g (commen)m(t)227 4456 y(\014eld.)47 b(The)32 b(\014rst)g(routine,)h (FTGKSL,)f(simply)g(returns)f(the)i(length)g(of)g(the)f(c)m(haracter)i (string)f(v)-5 b(alue)33 b(of)227 4569 y(the)c(sp)s(eci\014ed)g(k)m (eyw)m(ord.)40 b(The)29 b(second)g(routine,)h(FTGSKY,)f(also)g(returns) f(up)g(to)i(maxc)m(har)f(c)m(haracters)227 4682 y(of)i(the)f(k)m(eyw)m (ord)h(v)-5 b(alue)31 b(string,)g(starting)g(with)f(the)g(\014rstc)m (har)g(c)m(haracter,)j(and)c(the)i(k)m(eyw)m(ord)g(commen)m(t)227 4795 y(string.)49 b(The)32 b(length)i(argumen)m(t)f(returns)f(the)h (total)i(length)e(of)h(the)f(k)m(eyw)m(ord)g(v)-5 b(alue)34 b(string)f(regardless)227 4908 y(of)i(ho)m(w)f(m)m(uc)m(h)g(of)g(the)h (string)f(is)g(actually)i(returned)d(\(whic)m(h)h(dep)s(ends)e(on)j (the)f(v)-5 b(alue)35 b(of)f(the)g(\014rstc)m(har)227 5021 y(and)c(maxc)m(har)h(argumen)m(ts\).)41 b(These)30 b(routines)h(supp)s(ort)d(string)j(k)m(eyw)m(ords)f(that)h(use)f(the)h (CONTINUE)227 5133 y(con)m(v)m(en)m(tion)25 b(to)e(con)m(tin)m(ue)g (long)g(string)f(v)-5 b(alues)23 b(o)m(v)m(er)h(m)m(ultiple)f(FITS)e (header)h(records.)38 b(Normally)-8 b(,)26 b(string-)227 5246 y(v)-5 b(alued)40 b(k)m(eyw)m(ords)h(ha)m(v)m(e)g(a)g(maxim)m(um)f (length)h(of)f(68)h(c)m(haracters,)k(ho)m(w)m(ev)m(er,)f(CONTINUE'd)39 b(string)227 5359 y(k)m(eyw)m(ords)31 b(ma)m(y)g(b)s(e)f(arbitrarily)g (long.)334 5601 y Fe(FTGKSL\(unit,keyword,)42 b(>)48 b(length,status\))334 5714 y(FTGSKY\(unit,keyword,first)o(cha)o(r,ma)o (xcha)o(r,>)41 b(keyval,length,comment,sta)o(tus\))p eop end %%Page: 49 55 TeXDict begin 49 54 bop 0 299 a Fg(6.4.)72 b(FITS)30 b(HEADER)h(I/O)f(SUBR)m(OUTINES)2086 b Fi(49)0 555 y Fh(8)81 b Fi(Get)24 b(a)g(sequence)g(of)g(n)m(um)m(b)s(ered)e(k)m(eyw)m (ord)i(v)-5 b(alues.)38 b(These)24 b(routines)f(do)g(not)h(supp)s(ort)e (wild)h(card)g(c)m(haracters)227 668 y(in)30 b(the)h(ro)s(ot)g(name.) 382 929 y Fe(FTGKN[EDJKLS]\(unit,keyro)o(ot,)o(star)o(tno,)o(max)o (_key)o(s,)42 b(>)47 b(keyvals,nfound,status\))0 1189 y Fh(9)81 b Fi(Get)27 b(the)f(v)-5 b(alue)26 b(of)h(a)f(\015oating)h(p) s(oin)m(t)f(k)m(eyw)m(ord,)i(returning)d(the)h(in)m(teger)h(and)f (fractional)h(parts)f(of)g(the)g(v)-5 b(alue)227 1302 y(in)32 b(separate)g(subroutine)f(argumen)m(ts.)45 b(This)31 b(subroutine)f(ma)m(y)j(b)s(e)e(used)g(to)h(read)g(an)m(y)g(k)m(eyw)m (ord)g(but)f(is)227 1415 y(esp)s(ecially)h(useful)d(for)i(reading)f (the)h('triple)g(precision')f(k)m(eyw)m(ords)h(written)g(b)m(y)f (FTPKYT.)382 1675 y Fe(FTGKYT\(unit,keyword,)42 b(>)48 b(intval,dblval,comment,s)o(tat)o(us\))0 1936 y Fh(10)e Fi(Get)c(the)e(ph)m(ysical)i(units)e(string)g(in)h(an)f(existing)i(k)m (eyw)m(ord.)72 b(This)40 b(routine)g(uses)h(a)g(lo)s(cal)h(con)m(v)m (en)m(tion,)227 2049 y(sho)m(wn)32 b(in)g(the)h(follo)m(wing)h (example,)g(in)e(whic)m(h)g(the)h(k)m(eyw)m(ord)g(units)f(are)h (enclosed)g(in)f(square)g(brac)m(k)m(ets)227 2162 y(in)37 b(the)h(b)s(eginning)e(of)i(the)f(k)m(eyw)m(ord)h(commen)m(t)g (\014eld.)61 b(A)38 b(blank)f(string)g(is)g(returned)f(if)i(no)f(units) g(are)227 2274 y(de\014ned)29 b(for)i(the)f(k)m(eyw)m(ord.)191 2535 y Fe(VELOCITY=)809 b(12.3)46 b(/)i([km/s])e(orbital)g(speed)382 2761 y(FTGUNT\(unit,keyword,)c(>)48 b(units,status\))0 3052 y Fb(6.4.6)112 b(Mo)s(dify)39 b(Keyw)m(ord)e(Subroutines)0 3271 y Fi(Wild)32 b(card)f(c)m(haracters,)j(as)e(describ)s(ed)e(in)h (the)h(Read)g(Keyw)m(ord)f(section,)i(ab)s(o)m(v)m(e,)g(ma)m(y)g(b)s(e) d(used)h(when)g(sp)s(eci-)0 3384 y(fying)f(the)h(name)f(of)h(the)f(k)m (eyw)m(ord)h(to)g(b)s(e)f(mo)s(di\014ed.)0 3645 y Fh(1)81 b Fi(Mo)s(dify)30 b(\(o)m(v)m(erwrite\))i(the)f(n)m(th)f(80-c)m (haracter)j(header)d(record)h(in)f(the)g(CHU)382 3905 y Fe(FTMREC\(unit,key_no,card,)41 b(>)47 b(status\))0 4166 y Fh(2)81 b Fi(Mo)s(dify)37 b(\(o)m(v)m(erwrite\))j(the)e(80-c)m (haracter)j(header)c(record)h(for)f(the)h(named)f(k)m(eyw)m(ord)h(in)g (the)g(CHU.)g(This)227 4278 y(can)31 b(b)s(e)f(used)f(to)i(o)m(v)m (erwrite)h(the)f(name)f(of)h(the)f(k)m(eyw)m(ord)h(as)g(w)m(ell)g(as)g (its)g(v)-5 b(alue)30 b(and)g(commen)m(t)i(\014elds.)382 4539 y Fe(FTMCRD\(unit,keyword,card)o(,)42 b(>)47 b(status\))0 4799 y Fh(3)81 b Fi(Mo)s(dify)33 b(\(o)m(v)m(erwrite\))k(the)d(name)g (of)h(an)f(existing)h(k)m(eyw)m(ord)f(in)g(the)h(CHU)f(preserving)f (the)i(curren)m(t)e(v)-5 b(alue)227 4912 y(and)30 b(commen)m(t)h (\014elds.)382 5173 y Fe(FTMNAM\(unit,oldkey,keywo)o(rd,)41 b(>)48 b(status\))0 5433 y Fh(4)81 b Fi(Mo)s(dify)30 b(\(o)m(v)m(erwrite\))i(the)f(commen)m(t)g(\014eld)f(of)h(an)f (existing)h(k)m(eyw)m(ord)g(in)f(the)h(CHU)382 5694 y Fe(FTMCOM\(unit,keyword,comm)o(ent)o(,)42 b(>)47 b(status\))p eop end %%Page: 50 56 TeXDict begin 50 55 bop 0 299 a Fi(50)1319 b Fg(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)0 555 y Fh(5)81 b Fi(Mo)s(dify)24 b(the)h(v)-5 b(alue)25 b(and)f(commen)m(t)i(\014elds)e(of)h(an)f(existing)i(k)m(eyw) m(ord)f(in)f(the)h(CHU.)g(The)f(FTMKLS)g(subrou-)227 668 y(tine)35 b(w)m(orks)e(the)h(same)h(as)f(the)g(FTMKYS)f (subroutine,)h(except)h(it)g(also)f(supp)s(orts)e(long)j(string)f(v)-5 b(alues)227 781 y(greater)38 b(than)f(68)h(c)m(haracters)g(in)f (length.)60 b(Optionally)-8 b(,)40 b(one)d(ma)m(y)h(mo)s(dify)e(only)h (the)g(v)-5 b(alue)37 b(\014eld)g(and)227 894 y(lea)m(v)m(e)32 b(the)d(commen)m(t)i(\014eld)e(unc)m(hanged)g(b)m(y)g(setting)h(the)g (input)e(COMMENT)h(parameter)h(equal)g(to)g(the)227 1007 y(amp)s(ersand)f(c)m(haracter)k(\(&\).)42 b(The)30 b(E)g(and)g(D)h(v)m (ersions)g(of)g(this)g(routine)f(ha)m(v)m(e)i(the)f(added)f(feature)h (that)227 1120 y(if)26 b(the)h('decimals')g(parameter)g(is)f(negativ)m (e,)k(then)c(the)g('G')h(displa)m(y)f(format)h(rather)f(then)g(the)g ('E')h(format)227 1233 y(will)i(b)s(e)f(used)f(when)h(constructing)h (the)f(k)m(eyw)m(ord)h(v)-5 b(alue,)30 b(taking)f(the)g(absolute)g(v)-5 b(alue)29 b(of)f('decimals')i(for)227 1346 y(the)37 b(precision.)60 b(This)35 b(will)i(suppress)e(trailing)i(zeros,)i(and)d(will)h(use)g(a) g(\014xed)e(format)i(rather)g(than)f(an)227 1458 y(exp)s(onen)m(tial)c (format,)f(dep)s(ending)d(on)j(the)f(magnitude)h(of)f(the)h(v)-5 b(alue.)382 1687 y Fe(FTMKY[JKLS]\(unit,keyword)o(,ke)o(yval)o(,com)o (men)o(t,)42 b(>)47 b(status\))382 1800 y(FTMKLS\(unit,keyword,keyv)o (al,)o(comm)o(ent,)41 b(>)47 b(status\))382 1913 y (FTMKY[EDFG]\(unit,keyword)o(,ke)o(yval)o(,dec)o(ima)o(ls,c)o(omme)o (nt,)41 b(>)48 b(status\))0 2141 y Fh(6)81 b Fi(Mo)s(dify)22 b(the)g(v)-5 b(alue)23 b(of)f(an)g(existing)i(k)m(eyw)m(ord)e(to)h(b)s (e)f(unde\014ned,)g(or)g(n)m(ull.)38 b(The)22 b(v)-5 b(alue)22 b(string)h(of)f(the)g(k)m(eyw)m(ord)227 2254 y(is)30 b(set)h(to)g(blank.)40 b(Optionally)-8 b(,)31 b(one)f(ma)m(y)h(lea)m(v)m(e)h(the)f(commen)m(t)g(\014eld)e(unc)m (hanged)h(b)m(y)g(setting)h(the)f(input)227 2367 y(COMMENT)g(parameter) h(equal)g(to)g(the)g(amp)s(ersand)e(c)m(haracter)j(\(&\).)382 2595 y Fe(FTMKYU\(unit,keyword,comm)o(ent)o(,)42 b(>)47 b(status\))0 2881 y Fb(6.4.7)112 b(Up)s(date)39 b(Keyw)m(ord)e (Subroutines)0 3084 y Fh(1)81 b Fi(Up)s(date)36 b(an)g(80-c)m(haracter) j(record)d(in)g(the)h(CHU.)f(If)g(the)g(sp)s(eci\014ed)g(k)m(eyw)m(ord) h(already)f(exists)h(then)f(that)227 3197 y(header)j(record)f(will)h(b) s(e)f(replaced)i(with)e(the)h(input)f(CARD)g(string.)66 b(If)38 b(it)i(do)s(es)e(not)h(exist)g(then)g(the)227 3310 y(new)f(record)g(will)g(b)s(e)f(added)h(to)g(the)g(header.)64 b(The)37 b(FTUKLS)g(subroutine)g(w)m(orks)h(the)g(same)h(as)f(the)227 3423 y(FTUKYS)28 b(subroutine,)g(except)i(it)f(also)h(supp)s(orts)c (long)j(string)g(v)-5 b(alues)29 b(greater)h(than)e(68)h(c)m(haracters) h(in)227 3536 y(length.)382 3764 y Fe(FTUCRD\(unit,keyword,card)o(,)42 b(>)47 b(status\))0 3993 y Fh(2)81 b Fi(Up)s(date)44 b(the)i(v)-5 b(alue)45 b(and)g(commen)m(t)h(\014elds)e(of)h(a)h(k)m (eyw)m(ord)f(in)g(the)g(CHU.)h(The)e(sp)s(eci\014ed)g(k)m(eyw)m(ord)i (is)227 4106 y(mo)s(di\014ed)38 b(if)g(it)h(already)g(exists)g(\(b)m(y) g(calling)h(FTMKYx\))f(otherwise)f(a)h(new)f(k)m(eyw)m(ord)h(is)g (created)g(b)m(y)227 4218 y(calling)f(FTPKYx.)58 b(The)36 b(E)g(and)f(D)i(v)m(ersions)f(of)h(this)f(routine)g(ha)m(v)m(e)h(the)g (added)e(feature)i(that)g(if)f(the)227 4331 y('decimals')c(parameter)g (is)f(negativ)m(e,)i(then)d(the)h('G')h(displa)m(y)f(format)g(rather)g (then)f(the)h('E')g(format)h(will)227 4444 y(b)s(e)41 b(used)f(when)h(constructing)h(the)f(k)m(eyw)m(ord)h(v)-5 b(alue,)45 b(taking)d(the)f(absolute)h(v)-5 b(alue)42 b(of)g('decimals')g(for)227 4557 y(the)37 b(precision.)60 b(This)35 b(will)i(suppress)e(trailing)i(zeros,)i(and)d(will)h(use)g(a) g(\014xed)e(format)i(rather)g(than)f(an)227 4670 y(exp)s(onen)m(tial)c (format,)f(dep)s(ending)d(on)j(the)f(magnitude)h(of)f(the)h(v)-5 b(alue.)382 4898 y Fe(FTUKY[JKLS]\(unit,keyword)o(,ke)o(yval)o(,com)o (men)o(t,)42 b(>)47 b(status\))382 5011 y(FTUKLS\(unit,keyword,keyv)o (al,)o(comm)o(ent,)41 b(>)47 b(status\))382 5124 y (FTUKY[EDFG]\(unit,keyword)o(,ke)o(yval)o(,dec)o(ima)o(ls,c)o(omme)o (nt,)41 b(>)48 b(status\))0 5352 y Fh(3)81 b Fi(Up)s(date)23 b(the)g(v)-5 b(alue)24 b(of)g(an)f(existing)i(k)m(eyw)m(ord)f(to)g(b)s (e)f(unde\014ned,)f(or)i(n)m(ull,)h(or)e(insert)h(a)f(new)g (unde\014ned-v)-5 b(alue)227 5465 y(k)m(eyw)m(ord)30 b(if)f(it)h(do)s(esn't)f(already)h(exist.)41 b(The)29 b(v)-5 b(alue)30 b(string)f(of)g(the)h(k)m(eyw)m(ord)f(is)h(left)g (blank)f(in)f(this)i(case.)382 5694 y Fe(FTUKYU\(unit,keyword,comm)o (ent)o(,)42 b(>)47 b(status\))p eop end %%Page: 51 57 TeXDict begin 51 56 bop 0 299 a Fg(6.5.)72 b(D)m(A)-8 b(T)g(A)32 b(SCALING)e(AND)h(UNDEFINED)h(PIXEL)e(P)-8 b(ARAMETERS)1083 b Fi(51)0 555 y Fb(6.4.8)112 b(Delete)38 b(Keyw)m(ord)f(Subroutines)0 763 y Fh(1)81 b Fi(Delete)32 b(an)e(existing)h(k)m(eyw)m(ord)g(record.)40 b(The)30 b(space)h(previously)f(o)s(ccupied)g(b)m(y)g(the)g(k)m(eyw)m(ord)h(is)f (reclaimed)227 876 y(b)m(y)c(mo)m(ving)h(all)g(the)f(follo)m(wing)i (header)e(records)g(up)f(one)h(ro)m(w)h(in)e(the)i(header.)39 b(The)25 b(\014rst)h(routine)g(deletes)227 989 y(a)34 b(k)m(eyw)m(ord)f(at)h(a)g(sp)s(eci\014ed)e(p)s(osition)h(in)g(the)g (header)g(\(the)h(\014rst)e(k)m(eyw)m(ord)i(is)f(at)h(p)s(osition)f (1\),)i(whereas)227 1102 y(the)d(second)g(routine)g(deletes)h(a)f(sp)s (eci\014cally)g(named)f(k)m(eyw)m(ord.)46 b(Wild)32 b(card)f(c)m (haracters,)j(as)e(describ)s(ed)227 1215 y(in)f(the)g(Read)g(Keyw)m (ord)f(section,)i(ab)s(o)m(v)m(e,)g(ma)m(y)g(b)s(e)e(used)g(when)f(sp)s (ecifying)i(the)g(name)g(of)g(the)f(k)m(eyw)m(ord)227 1328 y(to)h(b)s(e)f(deleted)h(\(b)s(e)f(careful!\).)382 1582 y Fe(FTDREC\(unit,key_no,)42 b(>)48 b(status\))382 1695 y(FTDKEY\(unit,keyword,)42 b(>)48 b(status\))0 2028 y Fd(6.5)135 b(Data)46 b(Scaling)g(and)e(Unde\014ned)h(Pixel)h(P)l (arameters)0 2278 y Fi(These)24 b(subroutines)f(de\014ne)h(or)h(mo)s (dify)e(the)i(in)m(ternal)g(parameters)g(used)f(b)m(y)g(FITSIO)g(to)h (either)g(scale)h(the)e(data)0 2391 y(or)33 b(to)i(represen)m(t)e (unde\014ned)e(pixels.)50 b(Generally)35 b(FITSIO)d(will)i(scale)g(the) g(data)g(according)g(to)g(the)g(v)-5 b(alues)34 b(of)0 2504 y(the)e(BSCALE)g(and)f(BZER)m(O)h(\(or)h(TSCALn)d(and)i(TZER)m (On\))f(k)m(eyw)m(ords,)i(ho)m(w)m(ev)m(er)h(these)e(subroutines)f(ma)m (y)0 2617 y(b)s(e)h(used)h(to)h(o)m(v)m(erride)g(the)f(k)m(eyw)m(ord)h (v)-5 b(alues.)49 b(This)32 b(ma)m(y)i(b)s(e)f(useful)f(when)g(one)i(w) m(an)m(ts)f(to)h(read)f(or)g(write)h(the)0 2730 y(ra)m(w)c(unscaled)f (v)-5 b(alues)29 b(in)h(the)f(FITS)g(\014le.)40 b(Similarly)-8 b(,)31 b(FITSIO)d(generally)j(uses)e(the)g(v)-5 b(alue)30 b(of)g(the)f(BLANK)h(or)0 2843 y(TNULLn)35 b(k)m(eyw)m(ord)h(to)g (signify)f(an)h(unde\014ned)d(pixel,)k(but)e(these)h(routines)g(ma)m(y) g(b)s(e)e(used)h(to)h(o)m(v)m(erride)h(this)0 2956 y(v)-5 b(alue.)41 b(These)30 b(subroutines)f(do)i(not)f(create)i(or)f(mo)s (dify)e(the)i(corresp)s(onding)e(header)h(k)m(eyw)m(ord)h(v)-5 b(alues.)0 3210 y Fh(1)81 b Fi(Reset)26 b(the)g(scaling)g(factors)g(in) f(the)h(primary)f(arra)m(y)h(or)f(image)i(extension;)h(do)s(es)d(not)g (c)m(hange)i(the)f(BSCALE)227 3323 y(and)i(BZER)m(O)g(k)m(eyw)m(ord)h (v)-5 b(alues)28 b(and)g(only)g(a\013ects)i(the)e(automatic)j(scaling)e (p)s(erformed)e(when)g(the)h(data)227 3436 y(elemen)m(ts)f(are)f (written/read)g(to/from)g(the)g(FITS)f(\014le.)39 b(When)25 b(reading)h(from)f(a)h(FITS)f(\014le)g(the)h(returned)227 3549 y(data)i(v)-5 b(alue)28 b(=)f(\(the)h(v)-5 b(alue)28 b(giv)m(en)h(in)e(the)g(FITS)g(arra)m(y\))h(*)g(BSCALE)f(+)g(BZER)m(O.) g(The)g(in)m(v)m(erse)i(form)m(ula)227 3662 y(is)34 b(used)f(when)g (writing)h(data)h(v)-5 b(alues)34 b(to)g(the)g(FITS)g(\014le.)51 b(\(NOTE:)34 b(BSCALE)f(and)g(BZER)m(O)h(m)m(ust)g(b)s(e)227 3775 y(declared)d(as)g(Double)g(Precision)g(v)-5 b(ariables\).)382 4029 y Fe(FTPSCL\(unit,bscale,bzero)o(,)42 b(>)47 b(status\))0 4284 y Fh(2)81 b Fi(Reset)39 b(the)f(scaling)i(parameters)e(for)h(a)f (table)h(column;)k(do)s(es)38 b(not)g(c)m(hange)i(the)e(TSCALn)f(or)h (TZER)m(On)227 4397 y(k)m(eyw)m(ord)29 b(v)-5 b(alues)29 b(and)e(only)i(a\013ects)g(the)g(automatic)h(scaling)f(p)s(erformed)e (when)g(the)i(data)g(elemen)m(ts)h(are)227 4510 y(written/read)i (to/from)g(the)g(FITS)f(\014le.)44 b(When)31 b(reading)g(from)g(a)h (FITS)f(\014le)g(the)h(returned)e(data)i(v)-5 b(alue)227 4623 y(=)40 b(\(the)h(v)-5 b(alue)40 b(giv)m(en)h(in)f(the)g(FITS)g (arra)m(y\))g(*)h(TSCAL)e(+)g(TZER)m(O.)h(The)f(in)m(v)m(erse)i(form)m (ula)g(is)f(used)227 4736 y(when)33 b(writing)h(data)h(v)-5 b(alues)35 b(to)f(the)h(FITS)e(\014le.)52 b(\(NOTE:)34 b(TSCAL)f(and)g(TZER)m(O)g(m)m(ust)h(b)s(e)f(declared)227 4848 y(as)e(Double)g(Precision)g(v)-5 b(ariables\).)382 5103 y Fe(FTTSCL\(unit,colnum,tscal)o(,tz)o(ero,)41 b(>)48 b(status\))0 5357 y Fh(3)81 b Fi(De\014ne)36 b(the)g(in)m(teger)i(v)-5 b(alue)36 b(to)h(b)s(e)e(used)h(to)h(signify)f(unde\014ned)e(pixels)i (in)g(the)g(primary)f(arra)m(y)i(or)f(image)227 5470 y(extension.)59 b(This)35 b(is)h(only)g(used)g(if)g(BITPIX)g(=)f(8,)j (16,)h(32.)59 b(or)36 b(64)h(This)e(do)s(es)h(not)g(create)i(or)e(c)m (hange)227 5583 y(the)27 b(v)-5 b(alue)28 b(of)f(the)g(BLANK)g(k)m(eyw) m(ord)h(in)e(the)i(header.)39 b(FTPNULLL)27 b(is)g(iden)m(tical)h(to)g (FTPNUL)f(except)227 5696 y(that)k(the)g(blank)f(v)-5 b(alue)31 b(is)f(a)h(64-bit)g(in)m(teger)h(instead)f(of)f(a)h(32-bit)h (in)m(teger.)p eop end %%Page: 52 58 TeXDict begin 52 57 bop 0 299 a Fi(52)1319 b Fg(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)382 555 y Fe(FTPNUL\(unit,blank,)43 b(>)k(status\))382 668 y(FTPNULLL\(unit,blankll,)42 b(>)47 b(status\))0 919 y Fh(4)81 b Fi(De\014ne)36 b(the)g(string)g(to)g(b)s (e)f(used)g(to)i(signify)f(unde\014ned)e(pixels)i(in)f(a)h(column)g(in) g(an)f(ASCI)s(I)g(table.)58 b(This)227 1032 y(do)s(es)30 b(not)h(create)h(or)e(c)m(hange)i(the)e(v)-5 b(alue)31 b(of)g(the)f(TNULLn)g(k)m(eyw)m(ord.)382 1283 y Fe (FTSNUL\(unit,colnum,snull)41 b(>)47 b(status\))0 1534 y Fh(5)81 b Fi(De\014ne)34 b(the)h(v)-5 b(alue)34 b(to)h(b)s(e)f(used)g (to)h(signify)f(unde\014ned)e(pixels)j(in)f(an)g(in)m(teger)i(column)e (in)g(a)g(binary)g(table)227 1647 y(\(where)42 b(TF)m(ORMn)f(=)g('B',)i ('I',)f('J',)f(or)h('K'\).)g(This)f(do)s(es)g(not)h(create)h(or)e(c)m (hange)i(the)e(v)-5 b(alue)42 b(of)g(the)227 1760 y(TNULLn)d(k)m(eyw)m (ord.)71 b(FTTNULLL)39 b(is)i(iden)m(tical)h(to)e(FTTNUL)g(except)h (that)g(the)f(tn)m(ull)h(v)-5 b(alue)40 b(is)h(a)227 1872 y(64-bit)32 b(in)m(teger)g(instead)e(of)h(a)g(32-bit)g(in)m (teger.)382 2123 y Fe(FTTNUL\(unit,colnum,tnull)41 b(>)47 b(status\))382 2236 y(FTTNULLL\(unit,colnum,tnu)o(lll)o(l)42 b(>)47 b(status\))0 2569 y Fd(6.6)135 b(FITS)44 b(Primary)h(Arra)l(y)g (or)g(IMA)l(GE)g(Extension)h(I/O)f(Subroutines)0 2819 y Fi(These)26 b(subroutines)f(put)h(or)h(get)g(data)h(v)-5 b(alues)26 b(in)h(the)f(primary)g(data)h(arra)m(y)g(\(i.e.,)i(the)e (\014rst)f(HDU)h(in)f(the)h(FITS)0 2932 y(\014le\))35 b(or)g(an)f(IMA)m(GE)i(extension.)54 b(The)34 b(data)i(arra)m(y)f(is)f (represen)m(ted)h(as)g(a)g(single)g(one-dimensional)h(arra)m(y)f(of)0 3045 y(pixels)h(regardless)h(of)f(the)g(actual)h(dimensionalit)m(y)g (of)g(the)f(arra)m(y)-8 b(,)38 b(and)e(the)g(FPIXEL)g(parameter)g(giv)m (es)i(the)0 3158 y(p)s(osition)28 b(within)e(this)i(1-D)g(arra)m(y)g (of)g(the)g(\014rst)e(pixel)i(to)g(read)g(or)f(write.)40 b(Automatic)29 b(data)f(t)m(yp)s(e)g(con)m(v)m(ersion)h(is)0 3270 y(p)s(erformed)g(for)i(n)m(umeric)g(data)g(\(except)i(for)d (complex)i(data)f(t)m(yp)s(es\))h(if)f(the)g(data)g(t)m(yp)s(e)g(of)g (the)g(primary)f(arra)m(y)0 3383 y(\(de\014ned)e(b)m(y)g(the)h(BITPIX)f (k)m(eyw)m(ord\))h(di\013ers)g(from)f(the)g(data)i(t)m(yp)s(e)e(of)h (the)g(arra)m(y)g(in)f(the)h(calling)h(subroutine.)0 3496 y(The)41 b(data)i(v)-5 b(alues)42 b(are)g(also)h(scaled)f(b)m(y)g (the)g(BSCALE)f(and)g(BZER)m(O)h(header)f(v)-5 b(alues)42 b(as)g(they)g(are)g(b)s(eing)0 3609 y(written)32 b(or)g(read)g(from)g (the)g(FITS)g(arra)m(y)-8 b(.)47 b(The)31 b(ftpscl)i(subroutine)e(MUST) g(b)s(e)h(called)h(to)g(de\014ne)e(the)i(scaling)0 3722 y(parameters)h(when)e(writing)i(data)g(to)g(the)g(FITS)f(arra)m(y)h(or) f(to)h(o)m(v)m(erride)h(the)f(default)f(scaling)i(v)-5 b(alue)34 b(giv)m(en)g(in)0 3835 y(the)d(header)f(when)f(reading)i(the) f(FITS)g(arra)m(y)-8 b(.)0 3995 y(Tw)m(o)41 b(sets)f(of)h(subroutines)e (are)i(pro)m(vided)f(to)h(read)g(the)f(data)i(arra)m(y)f(whic)m(h)f (di\013er)g(in)g(the)h(w)m(a)m(y)g(unde\014ned)0 4108 y(pixels)35 b(are)h(handled.)55 b(The)35 b(\014rst)f(set)i(of)g (routines)f(\(FTGPVx\))h(simply)f(return)f(an)h(arra)m(y)h(of)g(data)g (elemen)m(ts)0 4221 y(in)c(whic)m(h)g(unde\014ned)e(pixels)i(are)h(set) f(equal)h(to)g(a)g(v)-5 b(alue)32 b(sp)s(eci\014ed)g(b)m(y)g(the)g (user)g(in)g(the)g('n)m(ullv)-5 b(al')33 b(parameter.)0 4334 y(An)h(additional)i(feature)f(of)f(these)h(subroutines)f(is)g (that)i(if)e(the)h(user)f(sets)h(n)m(ullv)-5 b(al)35 b(=)f(0,)i(then)f(no)f(c)m(hec)m(ks)i(for)0 4447 y(unde\014ned)d (pixels)j(will)g(b)s(e)e(p)s(erformed,)i(th)m(us)f(increasing)h(the)g (sp)s(eed)e(of)i(the)g(program.)55 b(The)35 b(second)h(set)g(of)0 4560 y(routines)31 b(\(FTGPFx\))i(returns)d(the)i(data)g(elemen)m(t)h (arra)m(y)f(and,)f(in)h(addition,)g(a)g(logical)i(arra)m(y)e(whic)m(h)f (de\014nes)0 4673 y(whether)40 b(the)g(corresp)s(onding)f(data)i(pixel) g(is)f(unde\014ned.)69 b(The)39 b(latter)j(set)f(of)f(subroutines)f(ma) m(y)i(b)s(e)f(more)0 4785 y(con)m(v)m(enien)m(t)33 b(to)g(use)e(in)g (some)g(circumstances,)i(ho)m(w)m(ev)m(er,)g(it)f(requires)f(an)g (additional)h(arra)m(y)g(of)g(logical)i(v)-5 b(alues)0 4898 y(whic)m(h)36 b(can)g(b)s(e)g(un)m(wieldy)f(when)h(w)m(orking)g (with)g(large)h(data)g(arra)m(ys.)58 b(Also)37 b(for)f(programmer)g (con)m(v)m(enience,)0 5011 y(sets)j(of)g(subroutines)f(to)h(directly)h (read)e(or)h(write)g(2)g(and)g(3)g(dimensional)g(arra)m(ys)g(ha)m(v)m (e)h(b)s(een)e(pro)m(vided,)j(as)0 5124 y(w)m(ell)31 b(as)f(a)g(set)g(of)g(subroutines)e(to)i(read)g(or)g(write)f(an)m(y)h (con)m(tiguous)h(rectangular)g(subset)e(of)h(pixels)g(within)f(the)0 5237 y(n-dimensional)h(arra)m(y)-8 b(.)0 5488 y Fh(1)81 b Fi(Get)39 b(the)g(data)h(t)m(yp)s(e)e(of)h(the)g(image)h(\(=)f (BITPIX)f(v)-5 b(alue\).)67 b(P)m(ossible)39 b(returned)f(v)-5 b(alues)39 b(are:)58 b(8,)41 b(16,)h(32,)227 5601 y(64,)36 b(-32,)h(or)d(-64)h(corresp)s(onding)e(to)h(unsigned)f(b)m(yte,)j (signed)e(2-b)m(yte)h(in)m(teger,)i(signed)d(4-b)m(yte)h(in)m(teger,) 227 5714 y(signed)c(8-b)m(yte)g(in)m(teger,)h(real,)g(and)d(double.)p eop end %%Page: 53 59 TeXDict begin 53 58 bop 0 299 a Fg(6.6.)72 b(FITS)30 b(PRIMAR)-8 b(Y)31 b(ARRA)-8 b(Y)31 b(OR)f(IMA)m(GE)h(EXTENSION)e(I/O)i (SUBR)m(OUTINES)589 b Fi(53)227 555 y(The)26 b(second)f(subroutine)g (is)h(similar)g(to)g(FTGIDT,)h(except)f(that)h(if)f(the)f(image)j (pixel)e(v)-5 b(alues)26 b(are)g(scaled,)227 668 y(with)h(non-default)g (v)-5 b(alues)27 b(for)g(the)h(BZER)m(O)f(and)f(BSCALE)g(k)m(eyw)m (ords,)j(then)e(this)g(routine)g(will)g(return)227 781 y(the)32 b('equiv)-5 b(alen)m(t')33 b(data)e(t)m(yp)s(e)h(that)f(is)g (needed)g(to)h(store)g(the)f(scaled)h(v)-5 b(alues.)43 b(F)-8 b(or)32 b(example,)g(if)f(BITPIX)227 894 y(=)39 b(16)g(and)g(BSCALE)f(=)g(0.1)i(then)f(the)g(equiv)-5 b(alen)m(t)40 b(data)f(t)m(yp)s(e)g(is)g(\015oating)h(p)s(oin)m(t,)h (and)d(-32)i(will)g(b)s(e)227 1007 y(returned.)65 b(There)39 b(are)g(2)g(sp)s(ecial)h(cases:)58 b(if)39 b(the)g(image)h(con)m(tains) g(unsigned)e(2-b)m(yte)i(in)m(teger)g(v)-5 b(alues,)227 1120 y(with)40 b(BITPIX)g(=)f(16,)44 b(BSCALE)39 b(=)h(1,)j(and)c(BZER) m(O)h(=)g(32768,)45 b(then)39 b(this)h(routine)g(will)h(return)e(a)227 1233 y(non-standard)26 b(v)-5 b(alue)27 b(of)g(20)h(for)f(the)g(bitpix) g(v)-5 b(alue.)40 b(Similarly)27 b(if)f(the)i(image)g(con)m(tains)g (unsigned)e(4-b)m(yte)227 1346 y(in)m(tegers,)32 b(then)e(bitpix)g (will)h(b)s(e)f(returned)f(with)h(a)h(v)-5 b(alue)31 b(of)f(40.)382 1602 y Fe(FTGIDT\(unit,)44 b(>)k(bitpix,status\))382 1715 y(FTGIET\(unit,)c(>)k(bitpix,status\))0 1971 y Fh(2)81 b Fi(Get)31 b(the)g(dimension)e(\(n)m(um)m(b)s(er)h(of)g(axes)h(=)f (NAXIS\))h(of)f(the)h(image)382 2227 y Fe(FTGIDM\(unit,)44 b(>)k(naxis,status\))0 2484 y Fh(3)81 b Fi(Get)38 b(the)f(size)h(of)f (all)h(the)f(dimensions)g(of)g(the)g(image.)62 b(The)37 b(FTGISZLL)e(routine)i(returns)f(an)h(arra)m(y)h(of)227 2597 y(64-bit)32 b(in)m(tegers)g(instead)e(of)h(32-bit)g(in)m(tegers.) 382 2853 y Fe(FTGISZ\(unit,)44 b(maxdim,)i(>)i(naxes,status\))382 2966 y(FTGISZLL\(unit,)c(maxdim,)i(>)h(naxesll,status\))0 3222 y Fh(4)81 b Fi(Get)35 b(the)f(parameters)g(that)h(de\014ne)e(the)h (t)m(yp)s(e)g(and)g(size)g(of)h(the)f(image.)53 b(This)33 b(routine)h(simply)f(com)m(bines)227 3335 y(calls)40 b(to)f(the)g(ab)s(o)m(v)m(e)h(3)f(routines.)65 b(The)38 b(FTGIPRLL)g(routine)h(returns)e(an)i(arra)m(y)g(of)g(64-bit)h(in)m (tegers)227 3448 y(instead)31 b(of)f(32-bit)i(in)m(tegers.)382 3704 y Fe(FTGIPR\(unit,)44 b(maxdim,)i(>)i(bitpix,)d(naxis,)h(naxes,)h (int)f(*status\))382 3817 y(FTGIPRLL\(unit,)e(maxdim,)i(>)h(bitpix,)f (naxis,)g(naxesll,)f(int)i(*status\))0 4073 y Fh(5)81 b Fi(Put)30 b(elemen)m(ts)h(in)m(to)h(the)e(data)h(arra)m(y)382 4330 y Fe(FTPPR[BIJKED]\(unit,group)o(,fp)o(ixel)o(,nel)o(eme)o(nts,)o (valu)o(es,)41 b(>)48 b(status\))0 4586 y Fh(6)81 b Fi(Put)30 b(elemen)m(ts)i(in)m(to)f(the)g(data)g(arra)m(y)-8 b(,)32 b(substituting)e(the)g(appropriate)h(FITS)f(n)m(ull)g(v)-5 b(alue)31 b(for)f(all)i(elemen)m(ts)227 4699 y(whic)m(h)c(are)f(equal)i (to)f(the)f(v)-5 b(alue)28 b(of)g(NULL)-10 b(V)g(AL.)28 b(F)-8 b(or)28 b(in)m(teger)h(FITS)e(arra)m(ys,)i(the)e(n)m(ull)h(v)-5 b(alue)28 b(de\014ned)e(b)m(y)227 4812 y(the)k(previous)f(call)i(to)g (FTPNUL)e(will)h(b)s(e)f(substituted;)h(for)f(\015oating)i(p)s(oin)m(t) f(FITS)f(arra)m(ys)h(\(BITPIX)f(=)227 4925 y(-32)j(or)e(-64\))i(then)e (the)h(sp)s(ecial)g(IEEE)e(NaN)i(\(Not-a-Num)m(b)s(er\))h(v)-5 b(alue)31 b(will)g(b)s(e)f(substituted.)382 5181 y Fe (FTPPN[BIJKED]\(unit,group)o(,fp)o(ixel)o(,nel)o(eme)o(nts,)o(valu)o (es,)o(null)o(val)41 b(>)48 b(status\))0 5437 y Fh(7)81 b Fi(Set)30 b(data)h(arra)m(y)g(elemen)m(ts)h(as)e(unde\014ned)382 5694 y Fe(FTPPRU\(unit,group,fpixel)o(,ne)o(leme)o(nts,)41 b(>)47 b(status\))p eop end %%Page: 54 60 TeXDict begin 54 59 bop 0 299 a Fi(54)1319 b Fg(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)0 555 y Fh(8)81 b Fi(Get)36 b(elemen)m(ts)g(from)f (the)g(data)h(arra)m(y)-8 b(.)55 b(Unde\014ned)34 b(arra)m(y)h(elemen)m (ts)i(will)e(b)s(e)g(returned)f(with)g(a)i(v)-5 b(alue)35 b(=)227 668 y(n)m(ullv)-5 b(al,)31 b(unless)f(n)m(ullv)-5 b(al)31 b(=)f(0)h(in)f(whic)m(h)g(case)h(no)g(c)m(hec)m(ks)g(for)g (unde\014ned)d(pixels)i(will)h(b)s(e)f(p)s(erformed.)382 914 y Fe(FTGPV[BIJKED]\(unit,group)o(,fp)o(ixel)o(,nel)o(eme)o(nts,)o (null)o(val)o(,)42 b(>)47 b(values,anyf,status\))0 1160 y Fh(9)81 b Fi(Get)32 b(elemen)m(ts)g(and)f(n)m(ull\015ags)g(from)g (data)h(arra)m(y)-8 b(.)44 b(An)m(y)32 b(unde\014ned)d(arra)m(y)i (elemen)m(ts)i(will)e(ha)m(v)m(e)i(the)e(corre-)227 1273 y(sp)s(onding)e(\015agv)-5 b(als)31 b(elemen)m(t)h(set)f(equal)g(to)g (.TR)m(UE.)382 1519 y Fe(FTGPF[BIJKED]\(unit,group)o(,fp)o(ixel)o(,nel) o(eme)o(nts,)41 b(>)48 b(values,flagvals,anyf,st)o(atu)o(s\))0 1765 y Fh(10)e Fi(Put)30 b(v)-5 b(alues)31 b(in)m(to)g(group)f (parameters)382 2011 y Fe(FTPGP[BIJKED]\(unit,group)o(,fp)o(arm,)o (npar)o(m,v)o(alue)o(s,)42 b(>)47 b(status\))0 2257 y Fh(11)f Fi(Get)31 b(v)-5 b(alues)31 b(from)f(group)g(parameters)382 2503 y Fe(FTGGP[BIJKED]\(unit,group)o(,fp)o(arm,)o(npar)o(m,)41 b(>)48 b(values,status\))0 2749 y Fi(The)32 b(follo)m(wing)h(4)g (subroutines)e(transfer)g(FITS)h(images)h(with)f(2)g(or)g(3)h (dimensions)e(to)i(or)f(from)g(a)h(data)f(arra)m(y)0 2862 y(whic)m(h)h(has)g(b)s(een)g(declared)g(in)g(the)h(calling)h (program.)49 b(The)33 b(dimensionalit)m(y)h(of)g(the)f(FITS)g(image)h (is)f(passed)0 2975 y(b)m(y)26 b(the)g(naxis1,)h(naxis2,)h(and)d (naxis3)i(parameters)f(and)f(the)h(declared)h(dimensions)e(of)h(the)g (program)g(arra)m(y)h(are)0 3088 y(passed)k(in)f(the)i(dim1)e(and)h (dim2)g(parameters.)43 b(Note)32 b(that)g(the)f(program)g(arra)m(y)g (do)s(es)g(not)g(ha)m(v)m(e)i(to)e(ha)m(v)m(e)i(the)0 3201 y(same)28 b(dimensions)f(as)h(the)g(FITS)e(arra)m(y)-8 b(,)30 b(but)d(m)m(ust)g(b)s(e)g(at)i(least)f(as)g(big.)40 b(F)-8 b(or)29 b(example)f(if)f(a)h(FITS)f(image)i(with)0 3314 y(NAXIS1)i(=)f(NAXIS2)h(=)f(400)i(is)e(read)h(in)m(to)g(a)g (program)f(arra)m(y)h(whic)m(h)f(is)h(dimensioned)f(as)g(512)i(x)f(512) g(pixels,)0 3427 y(then)d(the)g(image)i(will)e(just)g(\014ll)g(the)h (lo)m(w)m(er)g(left)g(corner)f(of)h(the)f(arra)m(y)h(with)f(pixels)g (in)g(the)h(range)f(1)h(-)f(400)i(in)e(the)0 3540 y(X)k(an)g(Y)h (directions.)47 b(This)31 b(has)h(the)h(e\013ect)g(of)g(taking)g(a)g (con)m(tiguous)g(set)g(of)f(pixel)h(v)-5 b(alue)33 b(in)e(the)i(FITS)e (arra)m(y)0 3653 y(and)k(writing)g(them)g(to)h(a)g(non-con)m(tiguous)g (arra)m(y)f(in)g(program)g(memory)g(\(i.e.,)j(there)e(are)f(no)m(w)h (some)f(blank)0 3766 y(pixels)c(around)e(the)h(edge)i(of)e(the)h(image) g(in)f(the)h(program)f(arra)m(y\).)0 4012 y Fh(11)46 b Fi(Put)30 b(2-D)i(image)f(in)m(to)h(the)e(data)h(arra)m(y)382 4258 y Fe(FTP2D[BIJKED]\(unit,group)o(,di)o(m1,n)o(axis)o(1,n)o(axis)o (2,im)o(age)o(,)42 b(>)47 b(status\))0 4504 y Fh(12)f Fi(Put)30 b(3-D)i(cub)s(e)d(in)m(to)j(the)e(data)h(arra)m(y)382 4750 y Fe(FTP3D[BIJKED]\(unit,group)o(,di)o(m1,d)o(im2,)o(nax)o(is1,)o (naxi)o(s2,)o(naxi)o(s3,c)o(ube)o(,)42 b(>)47 b(status\))0 4996 y Fh(13)f Fi(Get)29 b(2-D)f(image)h(from)f(the)f(data)i(arra)m(y) -8 b(.)41 b(Unde\014ned)26 b(pixels)h(in)h(the)g(arra)m(y)g(will)g(b)s (e)f(set)h(equal)g(to)h(the)e(v)-5 b(alue)227 5109 y(of)31 b('n)m(ullv)-5 b(al',)31 b(unless)f(n)m(ullv)-5 b(al=0)31 b(in)f(whic)m(h)g(case)i(no)e(testing)i(for)e(unde\014ned)e(pixels)i (will)h(b)s(e)f(p)s(erformed.)382 5355 y Fe(FTG2D[BIJKED]\(unit,group)o (,nu)o(llva)o(l,di)o(m1,)o(naxi)o(s1,n)o(axi)o(s2,)41 b(>)48 b(image,anyf,status\))0 5601 y Fh(14)e Fi(Get)31 b(3-D)h(cub)s(e)e(from)g(the)g(data)h(arra)m(y)-8 b(.)42 b(Unde\014ned)29 b(pixels)i(in)f(the)g(arra)m(y)h(will)g(b)s(e)f(set)h (equal)g(to)g(the)f(v)-5 b(alue)227 5714 y(of)31 b('n)m(ullv)-5 b(al',)31 b(unless)f(n)m(ullv)-5 b(al=0)31 b(in)f(whic)m(h)g(case)i(no) e(testing)i(for)e(unde\014ned)e(pixels)i(will)h(b)s(e)f(p)s(erformed.)p eop end %%Page: 55 61 TeXDict begin 55 60 bop 0 299 a Fg(6.7.)72 b(FITS)30 b(ASCI)s(I)f(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(D)m(A)-8 b(T)g(A)32 b(I/O)e(SUBR)m(OUTINES)979 b Fi(55)382 555 y Fe(FTG3D[BIJKED]\(unit,group)o(,nu)o(llva)o(l,di)o(m1,)o(dim2)o(,nax) o(is1)o(,nax)o(is2,)o(nax)o(is3,)41 b(>)1002 668 y(cube,anyf,status\))0 933 y Fi(The)i(follo)m(wing)h(subroutines)e(transfer)h(a)h(rectangular) g(subset)e(of)i(the)f(pixels)g(in)g(a)h(FITS)e(N-dimensional)0 1045 y(image)31 b(to)g(or)f(from)f(an)h(arra)m(y)g(whic)m(h)g(has)g(b)s (een)f(declared)h(in)g(the)g(calling)i(program.)40 b(The)29 b(fpixels)h(and)f(lpixels)0 1158 y(parameters)e(are)h(in)m(teger)g (arra)m(ys)g(whic)m(h)f(sp)s(ecify)f(the)i(starting)g(and)e(ending)h (pixels)g(in)g(eac)m(h)h(dimension)e(of)i(the)0 1271 y(FITS)36 b(image)i(that)f(are)g(to)h(b)s(e)e(read)g(or)h(written.)60 b(\(Note)38 b(that)g(these)f(are)g(the)g(starting)g(and)f(ending)h (pixels)0 1384 y(in)d(the)h(FITS)f(image,)k(not)d(in)f(the)h(declared)g (arra)m(y\).)55 b(The)34 b(arra)m(y)i(parameter)f(is)g(treated)g (simply)g(as)g(a)g(large)0 1497 y(one-dimensional)c(arra)m(y)f(of)h (the)f(appropriate)g(datat)m(yp)s(e)h(con)m(taining)h(the)e(pixel)g(v) -5 b(alues;)31 b(The)e(pixel)i(v)-5 b(alues)30 b(in)0 1610 y(the)c(FITS)f(arra)m(y)i(are)f(read/written)g(from/to)h(this)f (program)f(arra)m(y)i(in)e(strict)i(sequence)f(without)g(an)m(y)h (gaps;)g(it)0 1723 y(is)i(up)e(to)j(the)f(calling)h(routine)f(to)g (correctly)h(in)m(terpret)f(the)g(dimensionalit)m(y)h(of)f(this)g(arra) m(y)-8 b(.)41 b(The)28 b(t)m(w)m(o)i(families)0 1836 y(of)d(FITS)g(reading)g(routines)g(\(FTGSVx)g(and)g(FTGSFx)g (subroutines\))f(also)j(ha)m(v)m(e)f(an)f('incs')h(parameter)f(whic)m (h)0 1949 y(de\014nes)j(the)h(data)h(sampling)e(in)m(terv)-5 b(al)32 b(in)f(eac)m(h)h(dimension)e(of)h(the)g(FITS)f(arra)m(y)-8 b(.)43 b(F)-8 b(or)32 b(example,)g(if)f(incs\(1\)=2)0 2062 y(and)i(incs\(2\)=3)h(when)f(reading)g(a)h(2-dimensional)g(FITS)f (image,)i(then)e(only)h(ev)m(ery)g(other)f(pixel)h(in)f(the)h(\014rst)0 2175 y(dimension)e(and)h(ev)m(ery)h(3rd)e(pixel)i(in)f(the)g(second)g (dimension)f(will)i(b)s(e)e(returned)g(in)h(the)g('arra)m(y')h (parameter.)0 2287 y([Note:)39 b(the)25 b(FTGSSx)f(family)i(of)e (routines)h(whic)m(h)g(w)m(ere)g(presen)m(t)g(in)f(previous)g(v)m (ersions)h(of)g(FITSIO)f(ha)m(v)m(e)i(b)s(een)0 2400 y(sup)s(erseded)i(b)m(y)j(the)f(more)h(general)g(FTGSVx)f(family)h(of)g (routines.])0 2665 y Fh(15)46 b Fi(Put)30 b(an)g(arbitrary)g(data)h (subsection)g(in)m(to)g(the)g(data)g(arra)m(y)-8 b(.)382 2929 y Fe(FTPSS[BIJKED]\(unit,group)o(,na)o(xis,)o(naxe)o(s,f)o(pixe)o (ls,l)o(pix)o(els,)o(arra)o(y,)41 b(>)48 b(status\))0 3194 y Fh(16)e Fi(Get)30 b(an)e(arbitrary)g(data)i(subsection)e(from)g (the)h(data)g(arra)m(y)-8 b(.)42 b(Unde\014ned)27 b(pixels)h(in)h(the)f (arra)m(y)i(will)e(b)s(e)g(set)227 3306 y(equal)k(to)h(the)e(v)-5 b(alue)33 b(of)e('n)m(ullv)-5 b(al',)33 b(unless)e(n)m(ullv)-5 b(al=0)33 b(in)e(whic)m(h)g(case)i(no)e(testing)i(for)e(unde\014ned)f (pixels)227 3419 y(will)h(b)s(e)f(p)s(erformed.)382 3684 y Fe(FTGSV[BIJKED]\(unit,group)o(,na)o(xis,)o(naxe)o(s,f)o(pixe)o(ls,l) o(pix)o(els,)o(incs)o(,nu)o(llva)o(l,)42 b(>)1002 3797 y(array,anyf,status\))0 4061 y Fh(17)k Fi(Get)34 b(an)f(arbitrary)g (data)g(subsection)g(from)g(the)g(data)g(arra)m(y)-8 b(.)50 b(An)m(y)33 b(Unde\014ned)e(pixels)i(in)g(the)g(arra)m(y)h(will) 227 4174 y(ha)m(v)m(e)e(the)e(corresp)s(onding)g('\015agv)-5 b(als')31 b(elemen)m(t)h(set)f(equal)g(to)g(.TR)m(UE.)382 4438 y Fe(FTGSF[BIJKED]\(unit,group)o(,na)o(xis,)o(naxe)o(s,f)o(pixe)o (ls,l)o(pix)o(els,)o(incs)o(,)42 b(>)1002 4551 y (array,flagvals,anyf,statu)o(s\))0 4890 y Fd(6.7)135 b(FITS)44 b(ASCI)t(I)g(and)h(Binary)g(T)-11 b(able)45 b(Data)h(I/O)f(Subroutines)0 5145 y Fb(6.7.1)112 b(Column)39 b(Information)f(Subroutines)0 5357 y Fh(1)81 b Fi(Get)37 b(the)f(n)m(um)m(b)s(er)f(of)i(ro)m(ws)f(or)g(columns)g(in)g(the)h (curren)m(t)f(FITS)g(table.)59 b(The)36 b(n)m(um)m(b)s(er)f(of)h(ro)m (ws)h(is)f(giv)m(en)227 5470 y(b)m(y)f(the)h(NAXIS2)f(k)m(eyw)m(ord)h (and)f(the)g(n)m(um)m(b)s(er)f(of)h(columns)g(is)g(giv)m(en)h(b)m(y)g (the)f(TFIELDS)g(k)m(eyw)m(ord)g(in)227 5583 y(the)d(header)f(of)h(the) g(table.)45 b(The)31 b(FTGNR)-10 b(WLL)32 b(routine)g(is)f(iden)m (tical)i(to)g(FTGNR)-10 b(W)32 b(except)h(that)f(the)227 5696 y(n)m(um)m(b)s(er)d(of)i(ro)m(ws)f(is)h(returned)e(as)h(a)h (64-bit)h(in)m(teger)g(rather)e(than)g(a)h(32-bit)g(in)m(teger.)p eop end %%Page: 56 62 TeXDict begin 56 61 bop 0 299 a Fi(56)1319 b Fg(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)382 555 y Fe(FTGNRW\(unit,)44 b(>)k(nrows,)e(status\)) 382 668 y(FTGNRWLL\(unit,)e(>)j(nrowsll,)f(status\))382 781 y(FTGNCL\(unit,)e(>)k(ncols,)e(status\))0 1044 y Fh(2)81 b Fi(Get)25 b(the)f(table)i(column)e(n)m(um)m(b)s(er)f(\(and)h (name\))h(of)f(the)h(column)f(whose)g(name)g(matc)m(hes)i(an)e(input)g (template)227 1157 y(name.)38 b(The)21 b(table)i(column)e(names)h(are)g (de\014ned)e(b)m(y)i(the)g(TTYPEn)e(k)m(eyw)m(ords)i(in)f(the)h(FITS)f (header.)37 b(If)22 b(a)227 1270 y(column)i(do)s(es)g(not)g(ha)m(v)m(e) h(a)f(TTYPEn)f(k)m(eyw)m(ord,)j(then)d(these)h(routines)g(assume)g (that)g(the)h(name)e(consists)227 1383 y(of)i(all)h(blank)f(c)m (haracters.)40 b(These)25 b(2)g(subroutines)e(p)s(erform)h(the)h(same)g (function)g(except)h(that)f(FTGCNO)227 1496 y(only)j(returns)e(the)h(n) m(um)m(b)s(er)f(of)h(the)g(matc)m(hing)i(column)e(whereas)g(FTGCNN)g (also)h(returns)e(the)i(name)f(of)227 1609 y(the)k(column.)40 b(If)30 b(CASESEN)f(=)h(.true.)41 b(then)30 b(the)h(column)f(name)g (matc)m(h)i(will)e(b)s(e)g(case-sensitiv)m(e.)227 1761 y(The)41 b(input)e(column)i(name)g(template)h(\(COL)-8 b(TEMPLA)g(TE\))41 b(is)g(\(1\))g(either)h(the)f(exact)h(name)f(of)g (the)227 1874 y(column)36 b(to)i(b)s(e)d(searc)m(hed)i(for,)h(or)e (\(2\))i(it)f(ma)m(y)g(con)m(tain)g(wild)f(cards)g(c)m(haracters)i (\(*,)h(?,)f(or)e(#\),)i(or)f(\(3\))227 1987 y(it)d(ma)m(y)g(con)m (tain)g(the)f(n)m(um)m(b)s(er)f(of)h(the)g(desired)g(column)g(\(where)g (the)g(n)m(um)m(b)s(er)f(is)h(expressed)f(as)h(ASCI)s(I)227 2100 y(digits\).)41 b(The)28 b(\014rst)g(2)h(wild)f(cards)g(b)s(eha)m (v)m(e)h(similarly)g(to)g(UNIX)g(\014lename)g(matc)m(hing:)40 b(the)29 b('*')g(c)m(haracter)227 2213 y(matc)m(hes)e(an)m(y)g (sequence)f(of)h(c)m(haracters)g(\(including)f(zero)h(c)m(haracters\))h (and)d(the)i(')10 b(?')39 b(c)m(haracter)28 b(matc)m(hes)227 2325 y(an)m(y)40 b(single)h(c)m(haracter.)71 b(The)39 b(#)h(wildcard)f(will)h(matc)m(h)h(an)m(y)f(consecutiv)m(e)i(string)e (of)g(decimal)g(digits)227 2438 y(\(0-9\).)45 b(As)31 b(an)g(example,)h(the)f(template)h(strings)f('AB?DE',)h('AB*E',)h(and)d ('AB*CDE')j(will)e(all)h(matc)m(h)227 2551 y(the)26 b(string)g ('ABCDE'.)i(If)d(more)h(than)g(one)g(column)g(name)g(in)g(the)g(table)h (matc)m(hes)g(the)f(template)i(string,)227 2664 y(then)33 b(the)h(\014rst)f(matc)m(h)h(is)f(returned)g(and)f(the)i(status)g(v)-5 b(alue)34 b(will)f(b)s(e)g(set)h(to)g(237)h(as)f(a)f(w)m(arning)h(that) g(a)227 2777 y(unique)g(matc)m(h)i(w)m(as)f(not)g(found.)53 b(T)-8 b(o)35 b(\014nd)f(the)h(other)g(cases)g(that)h(matc)m(h)g(the)f (template,)i(simply)e(call)227 2890 y(the)27 b(subroutine)f(again)i (lea)m(ving)h(the)e(input)f(status)h(v)-5 b(alue)28 b(equal)f(to)h(237) g(and)f(the)g(next)g(matc)m(hing)h(name)227 3003 y(will)k(then)g(b)s(e) f(returned.)43 b(Rep)s(eat)32 b(this)g(pro)s(cess)f(un)m(til)h(a)g (status)g(=)g(219)h(\(column)e(name)h(not)g(found\))f(is)227 3116 y(returned.)40 b(If)30 b(these)h(subroutines)e(fail)i(to)g(matc)m (h)g(the)g(template)h(to)f(an)m(y)g(of)f(the)h(columns)f(in)g(the)h (table,)227 3229 y(they)i(lastly)g(c)m(hec)m(k)h(if)f(the)f(template)i (can)f(b)s(e)e(in)m(terpreted)i(as)g(a)g(simple)f(p)s(ositiv)m(e)h(in)m (teger)h(\(e.g.,)h('7',)f(or)227 3342 y('512'\))i(and)d(if)g(so,)i (they)f(return)e(that)j(column)e(n)m(um)m(b)s(er.)49 b(If)33 b(no)g(matc)m(hes)i(are)f(found)e(then)h(a)h(status)g(=)227 3455 y(219)e(error)e(is)g(returned.)227 3607 y(Note)h(that)e(the)h (FITS)e(Standard)g(recommends)g(that)i(only)f(letters,)i(digits,)f(and) f(the)g(underscore)f(c)m(har-)227 3719 y(acter)44 b(b)s(e)e(used)g(in)h (column)f(names)h(\(with)g(no)f(em)m(b)s(edded)g(spaces)h(in)g(the)g (name\).)78 b(T)-8 b(railing)43 b(blank)227 3832 y(c)m(haracters)32 b(are)f(not)f(signi\014can)m(t.)382 4096 y Fe (FTGCNO\(unit,casesen,colt)o(emp)o(late)o(,)42 b(>)47 b(colnum,status\))382 4209 y(FTGCNN\(unit,casesen,colt)o(emp)o(late)o (,)42 b(>)47 b(colname,colnum,status\))0 4472 y Fh(3)81 b Fi(Get)39 b(the)g(datat)m(yp)s(e)h(of)e(a)h(column)g(in)f(an)g(ASCI)s (I)g(or)g(binary)g(table.)66 b(This)38 b(routine)h(returns)e(an)i(in)m (teger)227 4585 y(co)s(de)34 b(v)-5 b(alue)33 b(corresp)s(onding)f(to)i (the)g(datat)m(yp)s(e)g(of)f(the)g(column.)49 b(\(See)34 b(the)f(FTBNFM)i(and)d(FT)-8 b(ASFM)227 4698 y(subroutines)27 b(in)h(the)g(Utilities)j(section)e(of)f(this)g(do)s(cumen)m(t)g(for)g (a)h(list)g(of)f(the)h(co)s(de)f(v)-5 b(alues\).)41 b(The)27 b(v)m(ector)227 4811 y(rep)s(eat)38 b(coun)m(t)g(\(whic)m(h)g(is)g(alw) m(a)m(y)h(1)f(for)g(ASCI)s(I)e(table)i(columns\))g(is)g(also)g (returned.)62 b(If)37 b(the)h(sp)s(eci\014ed)227 4924 y(column)32 b(has)f(an)g(ASCI)s(I)f(c)m(haracter)j(datat)m(yp)s(e)g (\(co)s(de)f(=)f(16\))i(then)e(the)h(width)e(of)i(a)g(unit)f(string)h (in)f(the)227 5036 y(column)i(is)g(also)h(returned.)48 b(Note)34 b(that)g(this)e(routine)h(supp)s(orts)f(the)h(lo)s(cal)h(con) m(v)m(en)m(tion)h(for)e(sp)s(ecifying)227 5149 y(arra)m(ys)f(of)f (strings)g(within)f(a)i(binary)e(table)i(c)m(haracter)g(column,)g (using)e(the)h(syn)m(tax)h(TF)m(ORM)f(=)g('rAw')227 5262 y(where)f('r')g(is)h(the)f(total)i(n)m(um)m(b)s(er)d(of)i(c)m (haracters)g(\(=)g(the)f(width)g(of)g(the)g(column\))h(and)f('w')g(is)g (the)h(width)227 5375 y(of)39 b(a)f(unit)g(string)g(within)g(the)g (column.)64 b(Th)m(us)37 b(if)h(the)g(column)g(has)g(TF)m(ORM)h(=)f ('60A12')i(then)e(this)227 5488 y(routine)29 b(will)g(return)f(dataco)s (de)i(=)e(16,)i(rep)s(eat)f(=)f(60,)j(and)d(width)g(=)g(12.)41 b(\(The)29 b(TDIMn)f(k)m(eyw)m(ord)h(ma)m(y)227 5601 y(also)35 b(b)s(e)e(used)g(to)h(sp)s(ecify)f(the)h(unit)f(string)h (length;)i(The)d(pair)g(of)h(k)m(eyw)m(ords)g(TF)m(ORMn)f(=)g('60A')j (and)227 5714 y(TDIMn)30 b(=)g('\(12,5\)')j(w)m(ould)e(ha)m(v)m(e)g (the)g(same)g(e\013ect)g(as)g(TF)m(ORMn)f(=)g('60A12'\).)p eop end %%Page: 57 63 TeXDict begin 57 62 bop 0 299 a Fg(6.7.)72 b(FITS)30 b(ASCI)s(I)f(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(D)m(A)-8 b(T)g(A)32 b(I/O)e(SUBR)m(OUTINES)979 b Fi(57)227 555 y(The)31 b(second)h(routine,)g(FTEQTY)f(is)g(similar)h(except)h(that)f (in)f(the)h(case)g(of)g(scaled)g(in)m(teger)h(columns)e(it)227 668 y(returns)23 b(the)h('equiv)-5 b(alen)m(t')25 b(data)f(t)m(yp)s(e)g (that)h(is)e(needed)h(to)g(store)g(the)g(scaled)g(v)-5 b(alues,)26 b(and)d(not)h(necessarily)227 781 y(the)38 b(ph)m(ysical)h(data)f(t)m(yp)s(e)g(of)g(the)g(unscaled)g(v)-5 b(alues)38 b(as)g(stored)g(in)g(the)g(FITS)f(table.)64 b(F)-8 b(or)38 b(example)h(if)227 894 y(a)c('1I')g(column)f(in)g(a)g (binary)g(table)h(has)f(TSCALn)f(=)g(1)i(and)f(TZER)m(On)f(=)g(32768,) 38 b(then)c(this)g(column)227 1007 y(e\013ectiv)m(ely)27 b(con)m(tains)e(unsigned)e(short)g(in)m(teger)j(v)-5 b(alues,)25 b(and)f(th)m(us)f(the)h(returned)f(v)-5 b(alue)24 b(of)g(t)m(yp)s(eco)s(de)h(will)227 1120 y(b)s(e)32 b(the)h(co)s(de)g (for)g(an)f(unsigned)g(short)g(in)m(teger,)j(not)e(a)g(signed)g(short)f (in)m(teger.)49 b(Similarly)-8 b(,)34 b(if)f(a)g(column)227 1233 y(has)d(TTYPEn)g(=)g('1I')h(and)f(TSCALn)e(=)i(0.12,)j(then)d(the) g(returned)g(t)m(yp)s(eco)s(de)g(will)h(b)s(e)f(the)h(co)s(de)f(for)h (a)227 1346 y('real')h(column.)382 1611 y Fe(FTGTCL\(unit,colnum,)42 b(>)48 b(datacode,repeat,width,st)o(atu)o(s\))382 1724 y(FTEQTY\(unit,colnum,)42 b(>)48 b(datacode,repeat,width,st)o(atu)o (s\))0 1989 y Fh(4)81 b Fi(Return)22 b(the)i(displa)m(y)g(width)f(of)g (a)h(column.)39 b(This)22 b(is)i(the)g(length)g(of)f(the)h(string)g (that)g(will)g(b)s(e)f(returned)f(when)227 2102 y(reading)33 b(the)g(column)g(as)g(a)g(formatted)g(string.)48 b(The)32 b(displa)m(y)h(width)f(is)h(determined)g(b)m(y)f(the)h(TDISPn)227 2215 y(k)m(eyw)m(ord,)e(if)g(presen)m(t,)f(otherwise)h(b)m(y)f(the)h (data)g(t)m(yp)s(e)g(of)f(the)h(column.)382 2480 y Fe(FTGCDW\(unit,)44 b(colnum,)i(>)i(dispwidth,)d(status\))0 2745 y Fh(5)81 b Fi(Get)29 b(information)f(ab)s(out)g(an)g(existing)h(ASCI)s(I)e (table)i(column.)40 b(\(NOTE:)28 b(TSCAL)f(and)g(TZER)m(O)h(m)m(ust)g (b)s(e)227 2858 y(declared)j(as)g(Double)g(Precision)g(v)-5 b(ariables\).)41 b(All)31 b(the)g(returned)e(parameters)i(are)f(scalar) i(quan)m(tities.)382 3123 y Fe(FTGACL\(unit,colnum,)42 b(>)716 3236 y(ttype,tbcol,tunit,tform,)o(tsca)o(l,t)o(zero)o(,snu)o (ll,)o(tdis)o(p,st)o(atu)o(s\))0 3501 y Fh(6)81 b Fi(Get)29 b(information)f(ab)s(out)f(an)h(existing)h(binary)e(table)i(column.)40 b(\(NOTE:)28 b(TSCAL)e(and)i(TZER)m(O)f(m)m(ust)h(b)s(e)227 3614 y(declared)j(as)f(Double)g(Precision)h(v)-5 b(ariables\).)41 b(D)m(A)-8 b(T)g(A)g(TYPE)32 b(is)e(a)g(c)m(haracter)i(string)d(whic)m (h)h(returns)f(the)227 3727 y(datat)m(yp)s(e)35 b(of)g(the)f(column)g (as)g(de\014ned)f(b)m(y)h(the)g(TF)m(ORMn)g(k)m(eyw)m(ord)h(\(e.g.,)i ('I',)e('J','E',)g('D',)g(etc.\).)54 b(In)227 3840 y(the)27 b(case)g(of)g(an)f(ASCI)s(I)f(c)m(haracter)j(column,)f(D)m(A)-8 b(T)g(A)g(TYPE)29 b(will)d(ha)m(v)m(e)i(a)f(v)-5 b(alue)27 b(of)f(the)h(form)f('An')g(where)227 3953 y('n')34 b(is)g(an)g(in)m (teger)i(expressing)e(the)g(width)f(of)h(the)h(\014eld)e(in)h(c)m (haracters.)53 b(F)-8 b(or)35 b(example,)h(if)e(TF)m(ORM)g(=)227 4066 y('160A8')39 b(then)e(FTGBCL)f(will)h(return)f(D)m(A)-8 b(T)g(A)g(TYPE='A8')39 b(and)d(REPEA)-8 b(T=20.)60 b(All)37 b(the)g(returned)227 4179 y(parameters)31 b(are)g(scalar)g(quan)m (tities.)382 4444 y Fe(FTGBCL\(unit,colnum,)42 b(>)716 4557 y(ttype,tunit,datatype,rep)o(eat,)o(tsc)o(al,t)o(zero)o(,tn)o (ull,)o(tdis)o(p,s)o(tatu)o(s\))0 4822 y Fh(7)81 b Fi(Put)31 b(\(app)s(end\))g(a)i(TDIMn)f(k)m(eyw)m(ord)g(whose)g(v)-5 b(alue)33 b(has)f(the)g(form)g('\(l,m,n...\)')47 b(where)32 b(l,)h(m,)f(n...)46 b(are)33 b(the)227 4935 y(dimensions)d(of)g(a)h(m)m (ultidimensional)g(arra)m(y)g(column)f(in)g(a)h(binary)f(table.)382 5200 y Fe(FTPTDM\(unit,colnum,naxis)o(,na)o(xes,)41 b(>)48 b(status\))0 5465 y Fh(8)81 b Fi(Return)29 b(the)h(n)m(um)m(b)s(er)e (of)i(and)g(size)g(of)g(the)g(dimensions)g(of)g(a)g(table)h(column.)40 b(Normally)31 b(this)f(information)227 5578 y(is)h(giv)m(en)h(b)m(y)f (the)g(TDIMn)f(k)m(eyw)m(ord,)i(but)e(if)h(this)g(k)m(eyw)m(ord)g(is)g (not)g(presen)m(t)g(then)g(this)f(routine)h(returns)227 5691 y(NAXIS)f(=)g(1)h(and)f(NAXES\(1\))h(equal)g(to)g(the)g(rep)s(eat) g(coun)m(t)g(in)f(the)g(TF)m(ORM)h(k)m(eyw)m(ord.)p eop end %%Page: 58 64 TeXDict begin 58 63 bop 0 299 a Fi(58)1319 b Fg(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)382 555 y Fe(FTGTDM\(unit,colnum,maxdi)o(m,)41 b(>)48 b(naxis,naxes,status\))0 808 y Fh(9)81 b Fi(Deco)s(de)33 b(the)g(input)f(TDIMn)h(k)m(eyw)m(ord)g(string)f(\(e.g.)50 b('\(100,200\)'\))37 b(and)32 b(return)g(the)h(n)m(um)m(b)s(er)e(of)i (and)f(size)227 921 y(of)c(the)g(dimensions)f(of)h(a)g(binary)f(table)h (column.)40 b(If)27 b(the)h(input)f(tdimstr)g(c)m(haracter)i(string)f (is)g(n)m(ull,)g(then)227 1034 y(this)d(routine)f(returns)f(naxis)h(=)h (1)f(and)g(naxes[0])i(equal)e(to)i(the)e(rep)s(eat)h(coun)m(t)g(in)f (the)g(TF)m(ORM)h(k)m(eyw)m(ord.)227 1147 y(This)30 b(routine)g(is)h (called)g(b)m(y)f(FTGTDM.)382 1400 y Fe(FTDTDM\(unit,tdimstr,coln)o (um,)o(maxd)o(im,)41 b(>)48 b(naxis,naxes,)c(status\))0 1654 y Fh(10)i Fi(Return)32 b(the)h(optimal)h(n)m(um)m(b)s(er)e(of)h (ro)m(ws)g(to)h(read)f(or)g(write)g(at)h(one)f(time)h(for)e(maxim)m(um) h(I/O)g(e\016ciency)-8 b(.)227 1767 y(Refer)31 b(to)g(the)g (\\Optimizing)g(Co)s(de")f(section)i(in)e(Chapter)g(5)g(for)h(more)f (discussion)g(on)g(ho)m(w)h(to)g(use)f(this)227 1879 y(routine.)382 2133 y Fe(FTGRSZ\(unit,)44 b(>)k(nrows,status\))0 2422 y Fb(6.7.2)112 b(Lo)m(w-Lev)m(el)39 b(T)-9 b(able)38 b(Access)f(Subroutines)0 2641 y Fi(The)d(follo)m(wing)h(subroutines)e (pro)m(vide)i(lo)m(w-lev)m(el)i(access)e(to)g(the)g(data)g(in)f(ASCI)s (I)e(or)i(binary)g(tables)h(and)f(are)0 2754 y(mainly)29 b(useful)f(as)i(an)f(e\016cien)m(t)h(w)m(a)m(y)g(to)g(cop)m(y)g(all)g (or)f(part)g(of)g(a)g(table)h(from)f(one)g(lo)s(cation)i(to)f(another.) 40 b(These)0 2867 y(routines)24 b(simply)g(read)g(or)h(write)f(the)h (sp)s(eci\014ed)e(n)m(um)m(b)s(er)g(of)i(consecutiv)m(e)h(b)m(ytes)f (in)f(an)g(ASCI)s(I)f(or)h(binary)g(table,)0 2980 y(without)37 b(regard)g(for)f(column)h(b)s(oundaries)e(or)i(the)g(ro)m(w)g(length)h (in)e(the)h(table.)61 b(The)37 b(\014rst)f(t)m(w)m(o)i(subroutines)0 3093 y(read)29 b(or)h(write)g(consecutiv)m(e)h(b)m(ytes)f(in)f(a)h (table)g(to)h(or)e(from)g(a)h(c)m(haracter)h(string)e(v)-5 b(ariable,)31 b(while)f(the)f(last)i(t)m(w)m(o)0 3206 y(subroutines)f(read)i(or)g(write)g(consecutiv)m(e)h(b)m(ytes)g(to)f (or)g(from)f(a)h(v)-5 b(ariable)33 b(declared)f(as)g(a)g(n)m(umeric)f (data)i(t)m(yp)s(e)0 3319 y(\(e.g.,)40 b(INTEGER,)d(INTEGER*2,)i(REAL,) d(DOUBLE)h(PRECISION\).)f(These)g(routines)h(do)f(not)h(p)s(erform)0 3432 y(an)m(y)c(mac)m(hine)g(dep)s(enden)m(t)f(data)i(con)m(v)m(ersion) g(or)e(b)m(yte)i(sw)m(apping,)f(except)h(that)f(con)m(v)m(ersion)h (to/from)f(ASCI)s(I)0 3544 y(format)d(is)g(p)s(erformed)e(b)m(y)h(the)h (FTGTBS)f(and)g(FTPTBS)g(routines)h(on)f(mac)m(hines)h(whic)m(h)g(do)f (not)h(use)f(ASCI)s(I)0 3657 y(c)m(haracter)j(co)s(des)e(in)g(the)h(in) m(ternal)g(data)g(represen)m(tations)h(\(e.g.,)g(on)e(IBM)h(mainframe)f (computers\).)0 3911 y Fh(1)81 b Fi(Read)26 b(a)h(consecutiv)m(e)h (string)f(of)f(c)m(haracters)i(from)e(an)g(ASCI)s(I)f(table)i(in)m(to)h (a)e(c)m(haracter)i(v)-5 b(ariable)28 b(\(spanning)227 4024 y(columns)k(and)g(m)m(ultiple)h(ro)m(ws)f(if)g(necessary\))h(This) f(routine)g(should)f(not)i(b)s(e)e(used)h(with)g(binary)f(tables)227 4136 y(b)s(ecause)g(of)f(complications)i(related)g(to)f(passing)f (string)g(v)-5 b(ariables)31 b(b)s(et)m(w)m(een)g(C)f(and)g(F)-8 b(ortran.)382 4390 y Fe(FTGTBS\(unit,frow,startch)o(ar,)o(ncha)o(rs,)41 b(>)48 b(string,status\))0 4643 y Fh(2)81 b Fi(W)-8 b(rite)31 b(a)g(consecutiv)m(e)h(string)e(of)h(c)m(haracters)g(to)g(an)f(ASCI)s (I)f(table)i(from)f(a)h(c)m(haracter)h(v)-5 b(ariable)31 b(\(spanning)227 4756 y(columns)h(and)g(m)m(ultiple)h(ro)m(ws)f(if)g (necessary\))h(This)f(routine)g(should)f(not)i(b)s(e)e(used)h(with)g (binary)f(tables)227 4869 y(b)s(ecause)g(of)f(complications)i(related)g (to)f(passing)f(string)g(v)-5 b(ariables)31 b(b)s(et)m(w)m(een)g(C)f (and)g(F)-8 b(ortran.)382 5122 y Fe(FTPTBS\(unit,frow,startch)o(ar,)o (ncha)o(rs,s)o(tri)o(ng,)41 b(>)48 b(status\))0 5375 y Fh(3)81 b Fi(Read)27 b(a)h(consecutiv)m(e)i(arra)m(y)e(of)g(b)m(ytes) g(from)f(an)g(ASCI)s(I)f(or)i(binary)e(table)j(in)m(to)f(a)g(n)m (umeric)g(v)-5 b(ariable)28 b(\(span-)227 5488 y(ning)k(columns)f(and)h (m)m(ultiple)g(ro)m(ws)g(if)g(necessary\).)46 b(The)32 b(arra)m(y)g(parameter)g(ma)m(y)h(b)s(e)e(declared)h(as)h(an)m(y)227 5601 y(n)m(umerical)i(datat)m(yp)s(e)g(as)g(long)g(as)g(the)f(arra)m(y) h(is)f(at)h(least)h('nc)m(hars')f(b)m(ytes)f(long,)j(e.g.,)f(if)f(nc)m (hars)f(=)g(17,)227 5714 y(then)c(declare)i(the)e(arra)m(y)h(as)g (INTEGER*4)g(ARRA)-8 b(Y\(5\).)p eop end %%Page: 59 65 TeXDict begin 59 64 bop 0 299 a Fg(6.7.)72 b(FITS)30 b(ASCI)s(I)f(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(D)m(A)-8 b(T)g(A)32 b(I/O)e(SUBR)m(OUTINES)979 b Fi(59)382 555 y Fe(FTGTBB\(unit,frow,startch)o(ar,)o(ncha)o(rs,)41 b(>)48 b(array,status\))0 813 y Fh(4)81 b Fi(W)-8 b(rite)32 b(a)f(consecutiv)m(e)i(arra)m(y)f(of)f(b)m(ytes)g(to)h(an)e(ASCI)s(I)g (or)h(binary)f(table)i(from)e(a)i(n)m(umeric)e(v)-5 b(ariable)32 b(\(span-)227 926 y(ning)j(columns)f(and)g(m)m(ultiple)h(ro)m(ws)g(if)f (necessary\))i(The)e(arra)m(y)h(parameter)g(ma)m(y)h(b)s(e)e(declared)h (as)g(an)m(y)227 1039 y(n)m(umerical)g(datat)m(yp)s(e)g(as)g(long)g(as) g(the)f(arra)m(y)h(is)f(at)h(least)h('nc)m(hars')f(b)m(ytes)f(long,)j (e.g.,)f(if)f(nc)m(hars)f(=)g(17,)227 1152 y(then)c(declare)i(the)e (arra)m(y)h(as)g(INTEGER*4)g(ARRA)-8 b(Y\(5\).)382 1410 y Fe(FTPTBB\(unit,frow,startch)o(ar,)o(ncha)o(rs,a)o(rra)o(y,)42 b(>)47 b(status\))0 1700 y Fb(6.7.3)112 b(Edit)37 b(Ro)m(ws)g(or)h (Columns)0 1909 y Fh(1)81 b Fi(Insert)26 b(blank)h(ro)m(ws)h(in)m(to)g (an)f(existing)h(ASCI)s(I)e(or)h(binary)g(table)h(\(in)g(the)f(CDU\).)h (All)g(the)g(ro)m(ws)f(F)m(OLLO)m(W-)227 2022 y(ING)35 b(ro)m(w)g(FR)m(O)m(W)g(are)g(shifted)f(do)m(wn)g(b)m(y)h(NR)m(O)m(WS)g (ro)m(ws.)53 b(If)34 b(FR)m(O)m(W)i(or)e(FR)m(O)m(WLL)i(equals)e(0)h (then)227 2134 y(the)27 b(blank)f(ro)m(ws)h(are)g(inserted)f(at)h(the)g (b)s(eginning)f(of)g(the)h(table.)41 b(These)26 b(routines)g(mo)s(dify) g(the)h(NAXIS2)227 2247 y(k)m(eyw)m(ord)35 b(to)h(re\015ect)f(the)g (new)f(n)m(um)m(b)s(er)f(of)i(ro)m(ws)g(in)f(the)h(table.)54 b(Note)36 b(that)f(it)h(is)e(*not*)i(necessary)f(to)227 2360 y(insert)c(ro)m(ws)f(in)g(a)h(table)g(b)s(efore)f(writing)g(data)i (to)f(those)g(ro)m(ws)f(\(indeed,)g(it)h(w)m(ould)g(b)s(e)e (ine\016cien)m(t)j(to)f(do)227 2473 y(so\).)54 b(Instead,)35 b(one)g(ma)m(y)g(simply)f(write)h(data)g(to)g(an)m(y)g(ro)m(w)f(of)h (the)g(table,)h(whether)e(that)h(ro)m(w)g(of)f(data)227 2586 y(already)d(exists)g(or)g(not.)382 2844 y Fe (FTIROW\(unit,frow,nrows,)41 b(>)48 b(status\))382 2957 y(FTIROWLL\(unit,frowll,nro)o(wsl)o(l,)42 b(>)47 b(status\))0 3215 y Fh(2)81 b Fi(Delete)25 b(ro)m(ws)f(from)f(an)g(existing)i(ASCI)s (I)c(or)j(binary)f(table)h(\(in)f(the)h(CDU\).)g(The)f(NR)m(O)m(WS)h (\(or)g(NR)m(O)m(WSLL\))227 3328 y(is)e(the)g(n)m(um)m(b)s(er)f(of)h (ro)m(ws)g(are)g(deleted,)i(starting)f(with)f(ro)m(w)g(FR)m(O)m(W)h (\(or)f(FR)m(O)m(WLL\),)h(and)f(an)m(y)g(remaining)227 3441 y(ro)m(ws)f(in)g(the)f(table)i(are)f(shifted)g(up)e(to)j(\014ll)f (in)f(the)h(space.)38 b(These)21 b(routines)f(mo)s(dify)g(the)h(NAXIS2) g(k)m(eyw)m(ord)227 3553 y(to)31 b(re\015ect)g(the)g(new)f(n)m(um)m(b)s (er)f(of)h(ro)m(ws)h(in)f(the)g(table.)382 3811 y Fe (FTDROW\(unit,frow,nrows,)41 b(>)48 b(status\))382 3924 y(FTDROWLL\(unit,frowll,nro)o(wsl)o(l,)42 b(>)47 b(status\))0 4182 y Fh(3)81 b Fi(Delete)26 b(a)f(list)g(of)g(ro)m(ws)f(from)g(an)h (ASCI)s(I)e(or)h(binary)g(table)h(\(in)g(the)f(CDU\).)i(In)e(the)g (\014rst)g(routine,)i('ro)m(wrange')227 4295 y(is)i(a)g(c)m(haracter)h (string)f(listing)h(the)f(ro)m(ws)f(or)h(ro)m(w)g(ranges)g(to)g(delete) h(\(e.g.,)i('2-4,)e(5,)g(8-9'\).)42 b(In)27 b(the)h(second)227 4408 y(routine,)37 b('ro)m(wlist')f(is)f(an)f(in)m(teger)j(arra)m(y)e (of)g(ro)m(w)g(n)m(um)m(b)s(ers)e(to)j(b)s(e)e(deleted)i(from)e(the)h (table.)56 b(nro)m(ws)34 b(is)227 4521 y(the)e(n)m(um)m(b)s(er)e(of)h (ro)m(w)h(n)m(um)m(b)s(ers)e(in)h(the)g(list.)45 b(The)31 b(\014rst)f(ro)m(w)i(in)f(the)g(table)i(is)e(1)h(not)f(0.)44 b(The)31 b(list)h(of)g(ro)m(w)227 4634 y(n)m(um)m(b)s(ers)d(m)m(ust)h (b)s(e)g(sorted)h(in)f(ascending)g(order.)382 4891 y Fe(FTDRRG\(unit,rowrange,)42 b(>)47 b(status\))382 5004 y(FTDRWS\(unit,rowlist,nrow)o(s,)41 b(>)48 b(status\))0 5262 y Fh(4)81 b Fi(Insert)43 b(a)i(blank)f(column)h(\(or)f(columns\))h (in)m(to)g(an)f(existing)i(ASCI)s(I)d(or)h(binary)g(table)h(\(in)g(the) f(CDU\).)227 5375 y(COLNUM)c(sp)s(eci\014es)g(the)h(column)f(n)m(um)m (b)s(er)f(that)i(the)f(\(\014rst\))g(new)g(column)g(should)f(o)s(ccup)m (y)i(in)f(the)227 5488 y(table.)58 b(NCOLS)34 b(sp)s(eci\014es)h(ho)m (w)h(man)m(y)g(columns)f(are)h(to)g(b)s(e)f(inserted.)57 b(An)m(y)35 b(existing)i(columns)e(from)227 5601 y(this)k(p)s(osition)f (and)g(higher)g(are)h(mo)m(v)m(ed)g(o)m(v)m(er)h(to)f(allo)m(w)h(ro)s (om)e(for)h(the)f(new)g(column\(s\).)65 b(The)38 b(index)227 5714 y(n)m(um)m(b)s(er)j(on)h(all)h(the)f(follo)m(wing)h(k)m(eyw)m (ords)g(will)f(b)s(e)f(incremen)m(ted)i(if)f(necessary)g(to)h (re\015ect)f(the)g(new)p eop end %%Page: 60 66 TeXDict begin 60 65 bop 0 299 a Fi(60)1319 b Fg(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)227 555 y Fi(p)s(osition)i(of)f(the)g(column\(s\))h (in)f(the)g(table:)43 b(TBCOLn,)30 b(TF)m(ORMn,)i(TTYPEn,)e(TUNITn,)h (TNULLn,)227 668 y(TSCALn,)22 b(TZER)m(On,)g(TDISPn,)g(TDIMn,)h (TLMINn,)g(TLMAXn,)f(TDMINn,)i(TDMAXn,)f(TCTYPn,)227 781 y(TCRPXn,)30 b(TCR)-10 b(VLn,)29 b(TCDL)-8 b(Tn,)30 b(TCR)m(OTn,)f(and)g(TCUNIn.)382 1035 y Fe(FTICOL\(unit,colnum,ttype)o (,tf)o(orm,)41 b(>)48 b(status\))382 1148 y(FTICLS\(unit,colnum,ncols)o (,tt)o(ype,)o(tfor)o(m,)41 b(>)48 b(status\))0 1403 y Fh(5)81 b Fi(Mo)s(dify)37 b(the)g(v)m(ector)i(length)f(of)f(a)h(binary) e(table)i(column)f(\(e.g.,)k(c)m(hange)e(a)e(column)g(from)g(TF)m(ORMn) g(=)227 1515 y('1E')31 b(to)h('20E'\).)g(The)e(v)m(ector)i(length)e(ma) m(y)h(b)s(e)f(increased)h(or)f(decreased)h(from)f(the)g(curren)m(t)h(v) -5 b(alue.)382 1770 y Fe(FTMVEC\(unit,colnum,newve)o(cle)o(n,)42 b(>)47 b(status\))0 2024 y Fh(6)81 b Fi(Delete)29 b(a)f(column)g(from)f (an)g(existing)i(ASCI)s(I)d(or)i(binary)e(table)j(\(in)f(the)f(CDU\).)i (The)e(index)g(n)m(um)m(b)s(er)f(of)i(all)227 2137 y(the)k(k)m(eyw)m (ords)h(listed)f(ab)s(o)m(v)m(e)i(\(for)e(FTICOL\))f(will)h(b)s(e)g (decremen)m(ted)g(if)g(necessary)h(to)g(re\015ect)f(the)g(new)227 2250 y(p)s(osition)26 b(of)g(the)g(column\(s\))g(in)f(the)h(table.)40 b(Those)26 b(index)f(k)m(eyw)m(ords)h(that)g(refer)f(to)i(the)f (deleted)g(column)227 2363 y(will)33 b(also)g(b)s(e)f(deleted.)47 b(Note)33 b(that)g(the)g(ph)m(ysical)g(size)g(of)f(the)h(FITS)e(\014le) i(will)f(not)h(b)s(e)e(reduced)h(b)m(y)g(this)227 2476 y(op)s(eration,)e(and)e(the)h(empt)m(y)g(FITS)f(blo)s(c)m(ks)h(if)g(an) m(y)g(at)g(the)g(end)f(of)h(the)g(\014le)g(will)g(b)s(e)f(padded)g (with)g(zeros.)382 2730 y Fe(FTDCOL\(unit,colnum,)42 b(>)48 b(status\))0 2984 y Fh(7)81 b Fi(Cop)m(y)30 b(a)g(column)g(from) g(one)g(HDU)h(to)g(another)f(\(or)h(to)g(the)f(same)h(HDU\).)g(If)f (createcol)j(=)c(TR)m(UE,)i(then)f(a)227 3097 y(new)20 b(column)g(will)h(b)s(e)f(inserted)g(in)g(the)h(output)f(table,)k(at)d (p)s(osition)f(`outcolumn',)j(otherwise)e(the)g(existing)227 3210 y(output)29 b(column)f(will)h(b)s(e)f(o)m(v)m(erwritten)i(\(in)f (whic)m(h)f(case)i(it)f(m)m(ust)f(ha)m(v)m(e)i(a)f(compatible)h(datat)m (yp)s(e\).)42 b(Note)227 3323 y(that)31 b(the)g(\014rst)e(column)i(in)f (a)g(table)i(is)e(at)h(coln)m(um)g(=)f(1.)382 3577 y Fe(FTCPCL\(inunit,outunit,in)o(col)o(num,)o(outc)o(oln)o(um,c)o(reat)o (eco)o(l,)42 b(>)47 b(status\);)0 3867 y Fb(6.7.4)112 b(Read)38 b(and)h(W)-9 b(rite)36 b(Column)j(Data)e(Routines)0 4086 y Fi(These)22 b(subroutines)f(put)h(or)g(get)i(data)f(v)-5 b(alues)22 b(in)g(the)h(curren)m(t)f(ASCI)s(I)f(or)h(Binary)g(table)i (extension.)38 b(Automatic)0 4199 y(data)21 b(t)m(yp)s(e)g(con)m(v)m (ersion)g(is)f(p)s(erformed)f(for)h(n)m(umerical)h(data)g(t)m(yp)s(es)g (\(B,I,J,E,D\))h(if)e(the)h(data)g(t)m(yp)s(e)f(of)h(the)f(column)0 4312 y(\(de\014ned)32 b(b)m(y)i(the)f(TF)m(ORM)h(k)m(eyw)m(ord\))g (di\013ers)f(from)f(the)i(data)g(t)m(yp)s(e)f(of)h(the)f(calling)i (subroutine.)48 b(The)33 b(data)0 4425 y(v)-5 b(alues)30 b(are)h(also)g(scaled)f(b)m(y)g(the)g(TSCALn)f(and)g(TZER)m(On)g (header)h(v)-5 b(alues)30 b(as)g(they)g(are)h(b)s(eing)e(written)h(to)h (or)0 4538 y(read)j(from)f(the)h(FITS)f(arra)m(y)-8 b(.)51 b(The)33 b(fttscl)i(subroutine)d(MUST)i(b)s(e)f(used)g(to)h(de\014ne)f (the)h(scaling)h(parameters)0 4650 y(when)d(writing)h(data)h(to)g(the)f (table)h(or)f(to)h(o)m(v)m(erride)g(the)g(default)f(scaling)h(v)-5 b(alues)34 b(giv)m(en)g(in)f(the)g(header)g(when)0 4763 y(reading)27 b(from)g(the)g(table.)40 b(Note)29 b(that)e(it)h(is)f (*not*)h(necessary)f(to)h(insert)f(ro)m(ws)g(in)f(a)i(table)g(b)s (efore)e(writing)h(data)0 4876 y(to)j(those)h(ro)m(ws)e(\(indeed,)h(it) g(w)m(ould)g(b)s(e)f(ine\016cien)m(t)i(to)f(do)g(so\).)41 b(Instead,)30 b(one)g(ma)m(y)g(simply)f(write)h(data)g(to)h(an)m(y)0 4989 y(ro)m(w)f(of)h(the)g(table,)g(whether)f(that)h(ro)m(w)f(of)h (data)g(already)g(exists)g(or)f(not.)0 5149 y(In)i(the)i(case)g(of)f (binary)g(tables)h(with)f(v)m(ector)h(elemen)m(ts,)i(the)d('felem')h (parameter)g(de\014nes)e(the)i(starting)g(pixel)0 5262 y(within)k(the)g(elemen)m(t)i(v)m(ector.)65 b(This)38 b(parameter)g(is)g(ignored)h(with)e(ASCI)s(I)g(tables.)65 b(Similarly)-8 b(,)41 b(in)d(the)g(case)0 5375 y(of)45 b(binary)e(tables)i(the)g('nelemen)m(ts')h(parameter)f(sp)s(eci\014es)f (the)g(total)i(n)m(um)m(b)s(er)d(of)i(v)m(ector)h(v)-5 b(alues)45 b(read)f(or)0 5488 y(written)36 b(\(con)m(tin)m(uing)h(on)f (subsequen)m(t)f(ro)m(ws)g(if)h(required\))f(and)h(not)g(the)g(n)m(um)m (b)s(er)e(of)i(table)h(elemen)m(ts.)58 b(Tw)m(o)0 5601 y(sets)36 b(of)f(subroutines)g(are)g(pro)m(vided)g(to)i(get)f(the)g (column)f(data)h(whic)m(h)f(di\013er)g(in)h(the)f(w)m(a)m(y)i (unde\014ned)c(pixels)0 5714 y(are)f(handled.)42 b(The)31 b(\014rst)g(set)h(of)f(routines)h(\(FTGCV\))g(simply)f(return)f(an)h (arra)m(y)h(of)f(data)h(elemen)m(ts)h(in)e(whic)m(h)p eop end %%Page: 61 67 TeXDict begin 61 66 bop 0 299 a Fg(6.7.)72 b(FITS)30 b(ASCI)s(I)f(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(D)m(A)-8 b(T)g(A)32 b(I/O)e(SUBR)m(OUTINES)979 b Fi(61)0 555 y(unde\014ned)41 b(pixels)j(are)g(set)g(equal)g(to)h(a)f(v)-5 b(alue)44 b(sp)s(eci\014ed)f(b)m(y)g(the)h(user)f(in)g(the)h('n)m(ullv)-5 b(al')44 b(parameter.)81 b(An)0 668 y(additional)44 b(feature)g(of)g (these)g(subroutines)e(is)i(that)g(if)f(the)h(user)e(sets)i(n)m(ullv)-5 b(al)44 b(=)f(0,)48 b(then)43 b(no)g(c)m(hec)m(ks)i(for)0 781 y(unde\014ned)33 b(pixels)j(will)g(b)s(e)e(p)s(erformed,)i(th)m(us) f(increasing)h(the)g(sp)s(eed)e(of)i(the)g(program.)55 b(The)35 b(second)h(set)g(of)0 894 y(routines)h(\(FTGCF\))h(returns)d (the)i(data)h(elemen)m(t)g(arra)m(y)g(and)e(in)h(addition)g(a)g (logical)j(arra)m(y)d(of)g(\015ags)g(whic)m(h)0 1007 y(de\014nes)29 b(whether)h(the)h(corresp)s(onding)e(data)i(pixel)g(is)f (unde\014ned.)0 1167 y(An)m(y)41 b(column,)i(regardless)e(of)g(it's)g (in)m(trinsic)g(datat)m(yp)s(e,)k(ma)m(y)c(b)s(e)f(read)h(as)g(a)g (string.)71 b(It)41 b(should)f(b)s(e)g(noted)0 1280 y(ho)m(w)m(ev)m(er) 32 b(that)f(reading)f(a)h(n)m(umeric)f(column)g(as)h(a)f(string)h(is)f (10)h(-)g(100)g(times)g(slo)m(w)m(er)h(than)e(reading)g(the)h(same)0 1393 y(column)g(as)h(a)g(n)m(um)m(b)s(er)e(due)h(to)h(the)g(large)h(o)m (v)m(erhead)f(in)g(constructing)g(the)g(formatted)g(strings.)44 b(The)31 b(displa)m(y)0 1506 y(format)26 b(of)g(the)h(returned)d (strings)i(will)g(b)s(e)g(determined)f(b)m(y)h(the)g(TDISPn)f(k)m(eyw)m (ord,)j(if)d(it)i(exists,)h(otherwise)e(b)m(y)0 1619 y(the)i(datat)m(yp)s(e)h(of)g(the)f(column.)40 b(The)28 b(length)g(of)h(the)f(returned)f(strings)h(can)g(b)s(e)g(determined)g (with)f(the)i(ftgcdw)0 1732 y(routine.)41 b(The)30 b(follo)m(wing)h (TDISPn)f(displa)m(y)g(formats)h(are)f(curren)m(tly)h(supp)s(orted:)191 1952 y Fe(Iw.m)142 b(Integer)191 2065 y(Ow.m)g(Octal)46 b(integer)191 2178 y(Zw.m)142 b(Hexadecimal)45 b(integer)191 2291 y(Fw.d)142 b(Fixed)46 b(floating)g(point)191 2404 y(Ew.d)142 b(Exponential)45 b(floating)g(point)191 2517 y(Dw.d)142 b(Exponential)45 b(floating)g(point)191 2630 y(Gw.d)142 b(General;)46 b(uses)g(Fw.d)h(if)g(significance)d(not)j (lost,)g(else)f(Ew.d)0 2850 y Fi(where)37 b(w)h(is)g(the)g(width)f(in)h (c)m(haracters)h(of)f(the)h(displa)m(y)m(ed)f(v)-5 b(alues,)41 b(m)c(is)h(the)g(minim)m(um)g(n)m(um)m(b)s(er)e(of)i(digits)0 2963 y(displa)m(y)m(ed,)31 b(and)f(d)g(is)g(the)h(n)m(um)m(b)s(er)e(of) h(digits)h(to)g(the)g(righ)m(t)g(of)g(the)f(decimal.)42 b(The)30 b(.m)g(\014eld)g(is)g(optional.)0 3184 y Fh(1)81 b Fi(Put)30 b(elemen)m(ts)i(in)m(to)g(an)e(ASCI)s(I)f(or)i(binary)f (table)i(column)e(\(in)h(the)g(CDU\).)g(\(The)g(SPP)f(FSPCLS)f(routine) 227 3297 y(has)38 b(an)f(additional)i(in)m(teger)g(argumen)m(t)f(after) h(the)f(V)-10 b(ALUES)37 b(c)m(haracter)i(string)f(whic)m(h)f(sp)s (eci\014es)h(the)227 3410 y(size)31 b(of)g(the)g(1st)g(dimension)e(of)i (this)f(2-D)i(CHAR)e(arra)m(y\).)227 3553 y(The)24 b(alternate)i(v)m (ersion)f(of)g(these)g(routines,)h(whose)e(names)g(end)g(in)g('LL')h (after)g(the)g(datat)m(yp)s(e)g(c)m(haracter,)227 3666 y(supp)s(ort)34 b(large)j(tables)f(with)g(more)f(then)h(2*31)h(ro)m (ws.)57 b(When)35 b(calling)i(these)f(routines,)h(the)f(fro)m(w)g(and) 227 3779 y(felem)31 b(parameters)g(*m)m(ust*)g(b)s(e)f(64-bit)h(in)m (teger*8)i(v)-5 b(ariables,)31 b(instead)g(of)g(normal)f(4-b)m(yte)i (in)m(tegers.)382 4000 y Fe(FTPCL[SLBIJKEDCM]\(unit,c)o(oln)o(um,f)o (row,)o(fel)o(em,n)o(elem)o(ent)o(s,va)o(lues)o(,)42 b(>)47 b(status\))382 4113 y(FTPCL[LBIJKEDCM]LL\(unit,)o(col)o(num,)o (frow)o(,fe)o(lem,)o(nele)o(men)o(ts,v)o(alue)o(s,)41 b(>)48 b(status\))0 4333 y Fh(2)81 b Fi(Put)29 b(elemen)m(ts)i(in)m(to) g(an)f(ASCI)s(I)e(or)i(binary)f(table)i(column)e(\(in)h(the)g(CDU\))g (substituting)g(the)g(appropriate)227 4446 y(FITS)c(n)m(ull)g(v)-5 b(alue)26 b(for)g(an)m(y)h(elemen)m(ts)g(that)g(are)f(equal)h(to)g (NULL)-10 b(V)g(AL.)26 b(F)-8 b(or)27 b(ASCI)s(I)e(T)-8 b(ABLE)26 b(extensions,)227 4559 y(the)31 b(n)m(ull)f(v)-5 b(alue)31 b(de\014ned)e(b)m(y)h(the)g(previous)g(call)i(to)f(FTSNUL)f (will)g(b)s(e)g(substituted;)g(F)-8 b(or)31 b(in)m(teger)h(FITS)227 4672 y(columns,)39 b(in)e(a)h(binary)f(table)h(the)f(n)m(ull)h(v)-5 b(alue)37 b(de\014ned)g(b)m(y)g(the)g(previous)g(call)i(to)f(FTTNUL)f (will)h(b)s(e)227 4785 y(substituted;)28 b(F)-8 b(or)28 b(\015oating)h(p)s(oin)m(t)e(FITS)f(columns)h(a)h(sp)s(ecial)g(IEEE)f (NaN)h(\(Not-a-Num)m(b)s(er\))h(v)-5 b(alue)28 b(will)227 4898 y(b)s(e)i(substituted.)227 5042 y(The)24 b(alternate)i(v)m(ersion) f(of)g(these)g(routines,)h(whose)e(names)g(end)g(in)g('LL')h(after)g (the)g(datat)m(yp)s(e)g(c)m(haracter,)227 5155 y(supp)s(ort)34 b(large)j(tables)f(with)g(more)f(then)h(2*31)h(ro)m(ws.)57 b(When)35 b(calling)i(these)f(routines,)h(the)f(fro)m(w)g(and)227 5267 y(felem)31 b(parameters)g(*m)m(ust*)g(b)s(e)f(64-bit)h(in)m (teger*8)i(v)-5 b(ariables,)31 b(instead)g(of)g(normal)f(4-b)m(yte)i (in)m(tegers.)382 5488 y Fe(FTPCN[SBIJKED]\(unit,coln)o(um,)o(frow)o (,fel)o(em,)o(nele)o(ment)o(s,v)o(alue)o(s,nu)o(llv)o(al)42 b(>)47 b(status\))382 5601 y(FTPCN[SBIJKED]LL\(unit,co)o(lnu)o(m,\(I)o (*8\))41 b(frow,\(I*8\))k(felem,nelements,values,)764 5714 y(nullval)g(>)j(status\))p eop end %%Page: 62 68 TeXDict begin 62 67 bop 0 299 a Fi(62)1319 b Fg(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)0 555 y Fh(3)81 b Fi(Put)37 b(bit)h(v)-5 b(alues)38 b(in)m(to)h(a)f(binary)f(b)m(yte)h(\('B'\))i(or)d(bit)h (\('X'\))h(table)g(column)f(\(in)f(the)h(CDU\).)h(LRA)-8 b(Y)38 b(is)g(an)227 668 y(arra)m(y)c(of)g(logical)h(v)-5 b(alues)34 b(corresp)s(onding)e(to)i(the)g(sequence)f(of)h(bits)f(to)h (b)s(e)f(written.)49 b(If)33 b(LRA)-8 b(Y)34 b(is)f(true)227 781 y(then)f(the)g(corresp)s(onding)f(bit)h(is)g(set)g(to)h(1,)g (otherwise)f(the)g(bit)g(is)g(set)h(to)g(0.)45 b(Note)34 b(that)e(in)g(the)g(case)h(of)227 894 y('X')g(columns,)g(FITSIO)e(will) i(write)f(to)h(all)g(8)g(bits)f(of)g(eac)m(h)i(b)m(yte)f(whether)e (they)i(are)g(formally)f(v)-5 b(alid)33 b(or)227 1007 y(not.)46 b(Th)m(us)31 b(if)h(the)g(column)g(is)f(de\014ned)g(as)h ('4X',)i(and)d(one)h(calls)h(FTPCLX)f(with)f(fbit=1)h(and)f(n)m(bit=8,) 227 1120 y(then)j(all)h(8)f(bits)g(will)g(b)s(e)f(written)h(in)m(to)h (the)f(\014rst)g(b)m(yte)g(\(as)h(opp)s(osed)e(to)i(writing)e(the)i (\014rst)e(4)h(bits)g(in)m(to)227 1233 y(the)d(\014rst)f(ro)m(w)g(and)g (then)g(the)h(next)f(4)h(bits)f(in)m(to)i(the)e(next)h(ro)m(w\),)g(ev)m (en)g(though)f(the)h(last)g(4)g(bits)f(of)h(eac)m(h)227 1346 y(b)m(yte)g(are)g(formally)g(not)g(de\014ned.)382 1604 y Fe(FTPCLX\(unit,colnum,frow,)o(fbi)o(t,nb)o(it,l)o(ray)o(,)42 b(>)47 b(status\))0 1863 y Fh(4)81 b Fi(Set)30 b(table)h(elemen)m(ts)h (in)e(a)h(column)f(as)h(unde\014ned)382 2121 y Fe (FTPCLU\(unit,colnum,frow,)o(fel)o(em,n)o(elem)o(ent)o(s,)42 b(>)47 b(status\))0 2380 y Fh(5)81 b Fi(Get)34 b(elemen)m(ts)g(from)f (an)g(ASCI)s(I)f(or)h(binary)g(table)h(column)f(\(in)g(the)g(CDU\).)i (These)e(routines)g(return)f(the)227 2493 y(v)-5 b(alues)30 b(of)g(the)g(table)h(column)f(arra)m(y)g(elemen)m(ts.)42 b(Unde\014ned)28 b(arra)m(y)j(elemen)m(ts)g(will)f(b)s(e)f(returned)g (with)h(a)227 2606 y(v)-5 b(alue)26 b(=)g(n)m(ullv)-5 b(al,)27 b(unless)e(n)m(ullv)-5 b(al)26 b(=)f(0)h(\(or)g(=)f(')h(')g (for)f(ftgcvs\))i(in)e(whic)m(h)g(case)i(no)e(c)m(hec)m(king)j(for)d (unde\014ned)227 2719 y(v)-5 b(alues)28 b(will)g(b)s(e)f(p)s(erformed.) 39 b(The)27 b(ANYF)h(parameter)g(is)g(set)g(to)g(true)g(if)g(an)m(y)f (of)h(the)g(returned)f(elemen)m(ts)227 2831 y(are)f(unde\014ned.)37 b(\(Note:)i(the)26 b(ftgcl)g(routine)f(simple)g(gets)h(an)g(arra)m(y)f (of)g(logical)j(data)e(v)-5 b(alues)25 b(without)h(an)m(y)227 2944 y(c)m(hec)m(ks)39 b(for)e(unde\014ned)e(v)-5 b(alues;)41 b(use)c(the)g(ftgc\015)h(routine)f(to)h(c)m(hec)m(k)g(for)f (unde\014ned)e(logical)40 b(elemen)m(ts\).)227 3057 y(\(The)29 b(SPP)f(FSGCVS)g(routine)g(has)h(an)f(additional)i(in)m(teger)g (argumen)m(t)f(after)g(the)g(V)-10 b(ALUES)28 b(c)m(haracter)227 3170 y(string)j(whic)m(h)f(sp)s(eci\014es)g(the)g(size)i(of)e(the)h (1st)g(dimension)e(of)i(this)f(2-D)i(CHAR)e(arra)m(y\).)227 3320 y(The)24 b(alternate)i(v)m(ersion)f(of)g(these)g(routines,)h (whose)e(names)g(end)g(in)g('LL')h(after)g(the)g(datat)m(yp)s(e)g(c)m (haracter,)227 3433 y(supp)s(ort)34 b(large)j(tables)f(with)g(more)f (then)h(2*31)h(ro)m(ws.)57 b(When)35 b(calling)i(these)f(routines,)h (the)f(fro)m(w)g(and)227 3546 y(felem)31 b(parameters)g(*m)m(ust*)g(b)s (e)f(64-bit)h(in)m(teger*8)i(v)-5 b(ariables,)31 b(instead)g(of)g (normal)f(4-b)m(yte)i(in)m(tegers.)382 3805 y Fe (FTGCL\(unit,colnum,frow,f)o(ele)o(m,ne)o(leme)o(nts)o(,)42 b(>)47 b(values,status\))382 3918 y(FTGCV[SBIJKEDCM]\(unit,co)o(lnu)o (m,fr)o(ow,f)o(ele)o(m,ne)o(leme)o(nts)o(,nul)o(lval)o(,)42 b(>)1098 4030 y(values,anyf,status\))382 4143 y (FTGCV[BIJKEDCM]LL\(unit,c)o(oln)o(um,\()o(I*8\))f(frow,)46 b(\(I*8\))h(felem,)f(nelements,)716 4256 y(nullval,)f(>)j (values,anyf,status\))0 4515 y Fh(6)81 b Fi(Get)44 b(elemen)m(ts)h(and) d(n)m(ull)i(\015ags)f(from)g(an)h(ASCI)s(I)d(or)j(binary)e(table)j (column)e(\(in)g(the)h(CHDU\).)g(These)227 4628 y(routines)29 b(return)e(the)i(v)-5 b(alues)29 b(of)g(the)g(table)h(column)e(arra)m (y)i(elemen)m(ts.)41 b(An)m(y)29 b(unde\014ned)d(arra)m(y)k(elemen)m (ts)227 4741 y(will)37 b(ha)m(v)m(e)h(the)f(corresp)s(onding)f(\015agv) -5 b(als)37 b(elemen)m(t)i(set)e(equal)g(to)h(.TR)m(UE.)f(The)f(ANYF)i (parameter)f(is)227 4854 y(set)30 b(to)g(true)g(if)f(an)m(y)h(of)f(the) h(returned)e(elemen)m(ts)j(are)f(unde\014ned.)38 b(\(The)29 b(SPP)f(FSGCFS)h(routine)h(has)f(an)227 4967 y(additional)e(in)m(teger) h(argumen)m(t)e(after)h(the)f(V)-10 b(ALUES)26 b(c)m(haracter)i(string) e(whic)m(h)f(sp)s(eci\014es)h(the)h(size)f(of)h(the)227 5079 y(1st)k(dimension)f(of)h(this)f(2-D)h(CHAR)g(arra)m(y\).)227 5229 y(The)24 b(alternate)i(v)m(ersion)f(of)g(these)g(routines,)h (whose)e(names)g(end)g(in)g('LL')h(after)g(the)g(datat)m(yp)s(e)g(c)m (haracter,)227 5342 y(supp)s(ort)34 b(large)j(tables)f(with)g(more)f (then)h(2*31)h(ro)m(ws.)57 b(When)35 b(calling)i(these)f(routines,)h (the)f(fro)m(w)g(and)227 5455 y(felem)31 b(parameters)g(*m)m(ust*)g(b)s (e)f(64-bit)h(in)m(teger*8)i(v)-5 b(ariables,)31 b(instead)g(of)g (normal)f(4-b)m(yte)i(in)m(tegers.)382 5714 y Fe (FTGCF[SLBIJKEDCM]\(unit,c)o(oln)o(um,f)o(row,)o(fel)o(em,n)o(elem)o (ent)o(s,)42 b(>)p eop end %%Page: 63 69 TeXDict begin 63 68 bop 0 299 a Fg(6.7.)72 b(FITS)30 b(ASCI)s(I)f(AND)i(BINAR)-8 b(Y)31 b(T)-8 b(ABLE)31 b(D)m(A)-8 b(T)g(A)32 b(I/O)e(SUBR)m(OUTINES)979 b Fi(63)1193 555 y Fe(values,flagvals,anyf,stat)o(us\))382 668 y (FTGCF[BIJKED]LL\(unit,col)o(num)o(,)42 b(\(I*8\))k(frow,)h(\(I*8\))f (felem,nelements,)d(>)1193 781 y(values,flagvals,anyf,stat)o(us\))0 1034 y Fh(7)81 b Fi(Get)29 b(an)f(arbitrary)g(data)h(subsection)f(from) g(an)g(N-dimensional)h(arra)m(y)g(in)f(a)g(binary)g(table)h(v)m(ector)h (column.)227 1147 y(Unde\014ned)k(pixels)h(in)g(the)h(arra)m(y)g(will)f (b)s(e)g(set)h(equal)f(to)h(the)g(v)-5 b(alue)36 b(of)f('n)m(ullv)-5 b(al',)38 b(unless)c(n)m(ullv)-5 b(al=0)36 b(in)227 1260 y(whic)m(h)d(case)i(no)e(testing)i(for)e(unde\014ned)e(pixels)j(will)f (b)s(e)g(p)s(erformed.)49 b(The)32 b(\014rst)h(and)g(last)h(ro)m(ws)g (in)f(the)227 1373 y(table)28 b(to)f(b)s(e)f(read)g(are)h(sp)s (eci\014ed)e(b)m(y)i(fpixels\(naxis+1\))g(and)f(lpixels\(naxis+1\),)j (and)d(hence)g(are)h(treated)227 1486 y(as)f(the)f(next)h(higher)f (dimension)g(of)g(the)h(FITS)e(N-dimensional)i(arra)m(y)-8 b(.)40 b(The)25 b(INCS)f(parameter)i(sp)s(eci\014es)227 1599 y(the)31 b(sampling)f(in)m(terv)-5 b(al)32 b(in)e(eac)m(h)h (dimension)f(b)s(et)m(w)m(een)h(the)g(data)g(elemen)m(ts)g(that)g(will) g(b)s(e)f(returned.)382 1852 y Fe(FTGSV[BIJKED]\(unit,colnu)o(m,n)o (axis)o(,nax)o(es,)o(fpix)o(els,)o(lpi)o(xels)o(,inc)o(s,n)o(ullv)o (al,)41 b(>)1002 1965 y(array,anyf,status\))0 2218 y Fh(8)81 b Fi(Get)29 b(an)f(arbitrary)g(data)h(subsection)f(from)g(an)g (N-dimensional)h(arra)m(y)g(in)f(a)g(binary)g(table)h(v)m(ector)h (column.)227 2331 y(An)m(y)39 b(Unde\014ned)e(pixels)i(in)g(the)g(arra) m(y)g(will)g(ha)m(v)m(e)h(the)f(corresp)s(onding)f('\015agv)-5 b(als')40 b(elemen)m(t)g(set)f(equal)227 2443 y(to)d(.TR)m(UE.)f(The)f (\014rst)g(and)g(last)i(ro)m(ws)f(in)f(the)h(table)h(to)f(b)s(e)g(read) f(are)h(sp)s(eci\014ed)f(b)m(y)h(fpixels\(naxis+1\))227 2556 y(and)k(lpixels\(naxis+1\),)k(and)38 b(hence)i(are)f(treated)i(as) e(the)g(next)h(higher)f(dimension)f(of)i(the)f(FITS)g(N-)227 2669 y(dimensional)g(arra)m(y)-8 b(.)66 b(The)38 b(INCS)g(parameter)h (sp)s(eci\014es)f(the)g(sampling)h(in)m(terv)-5 b(al)40 b(in)e(eac)m(h)i(dimension)227 2782 y(b)s(et)m(w)m(een)31 b(the)g(data)g(elemen)m(ts)h(that)f(will)f(b)s(e)g(returned.)382 3035 y Fe(FTGSF[BIJKED]\(unit,colnu)o(m,n)o(axis)o(,nax)o(es,)o(fpix)o (els,)o(lpi)o(xels)o(,inc)o(s,)41 b(>)1002 3148 y (array,flagvals,anyf,statu)o(s\))0 3401 y Fh(9)81 b Fi(Get)33 b(bit)g(v)-5 b(alues)34 b(from)e(a)h(b)m(yte)h(\('B'\))g(or)f(bit)g (\(`X`\))h(table)g(column)f(\(in)g(the)g(CDU\).)g(LRA)-8 b(Y)34 b(is)f(an)f(arra)m(y)i(of)227 3514 y(logical)41 b(v)-5 b(alues)39 b(corresp)s(onding)f(to)h(the)g(sequence)f(of)h(bits) g(to)g(b)s(e)f(read.)65 b(If)38 b(LRA)-8 b(Y)39 b(is)f(true)h(then)f (the)227 3627 y(corresp)s(onding)c(bit)g(w)m(as)g(set)h(to)g(1,)h (otherwise)f(the)f(bit)h(w)m(as)f(set)h(to)g(0.)53 b(Note)35 b(that)g(in)f(the)h(case)g(of)f('X')227 3740 y(columns,)41 b(FITSIO)d(will)h(read)f(all)i(8)f(bits)g(of)g(eac)m(h)h(b)m(yte)f (whether)f(they)h(are)g(formally)h(v)-5 b(alid)39 b(or)f(not.)227 3853 y(Th)m(us)c(if)g(the)h(column)f(is)g(de\014ned)f(as)i('4X',)h(and) d(one)i(calls)h(FTGCX)e(with)g(fbit=1)h(and)e(n)m(bit=8,)j(then)227 3966 y(all)30 b(8)g(bits)f(will)g(b)s(e)g(read)g(from)g(the)g(\014rst)f (b)m(yte)i(\(as)g(opp)s(osed)e(to)i(reading)f(the)h(\014rst)e(4)i(bits) f(from)f(the)i(\014rst)227 4079 y(ro)m(w)g(and)e(then)h(the)h(\014rst)e (4)i(bits)f(from)g(the)g(next)g(ro)m(w\),)i(ev)m(en)f(though)f(the)g (last)h(4)g(bits)f(of)g(eac)m(h)i(b)m(yte)f(are)227 4192 y(formally)h(not)g(de\014ned.)382 4445 y Fe(FTGCX\(unit,colnum,frow,f)o (bit)o(,nbi)o(t,)42 b(>)47 b(lray,status\))0 4698 y Fh(10)f Fi(Read)31 b(an)m(y)g(consecutiv)m(e)h(set)f(of)g(bits)g(from)f(an)g ('X')i(or)e('B')i(column)e(and)g(in)m(terpret)h(them)g(as)g(an)f (unsigned)227 4811 y(n-bit)k(in)m(teger.)54 b(NBIT)35 b(m)m(ust)f(b)s(e)f(less)i(than)f(or)g(equal)h(to)g(16)g(when)f (calling)h(FTGCXI,)g(and)f(less)g(than)227 4924 y(or)e(equal)g(to)g(32) g(when)e(calling)j(FTGCXJ;)f(there)f(is)h(no)f(limit)h(on)g(the)f(v)-5 b(alue)32 b(of)g(NBIT)f(for)g(FTGCXD,)227 5036 y(but)38 b(the)h(returned)e(double)i(precision)f(v)-5 b(alue)39 b(only)g(has)f(48)i(bits)e(of)h(precision)g(on)f(most)h(32-bit)h(w)m (ord)227 5149 y(mac)m(hines.)64 b(The)37 b(NBITS)g(bits)h(are)g(in)m (terpreted)g(as)g(an)g(unsigned)e(in)m(teger)k(unless)d(NBITS)g(=)g(16) i(\(in)227 5262 y(FTGCXI\))e(or)g(32)g(\(in)g(FTGCXJ\))f(in)g(whic)m(h) h(case)g(the)g(string)g(of)f(bits)h(are)g(in)m(terpreted)f(as)h(16-bit) h(or)227 5375 y(32-bit)j(2's)f(complemen)m(t)h(signed)e(in)m(tegers.)69 b(If)39 b(NR)m(O)m(WS)i(is)e(greater)i(than)e(1)h(then)f(the)h(same)g (set)g(of)227 5488 y(bits)34 b(will)g(b)s(e)f(read)h(from)f(sequen)m (tial)i(ro)m(ws)f(in)f(the)h(table)g(starting)h(with)e(ro)m(w)h(FR)m(O) m(W.)h(Note)g(that)g(the)227 5601 y(n)m(um)m(b)s(ering)27 b(con)m(v)m(en)m(tion)j(used)d(here)g(for)h(the)g(FBIT)f(parameter)i (adopts)e(1)h(for)g(the)g(\014rst)f(elemen)m(t)i(of)f(the)227 5714 y(v)m(ector)k(of)f(bits;)f(this)h(is)f(the)h(Most)g(Signi\014can)m (t)g(Bit)g(of)g(the)f(in)m(teger)i(v)-5 b(alue.)p eop end %%Page: 64 70 TeXDict begin 64 69 bop 0 299 a Fi(64)1319 b Fg(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)382 555 y Fe(FTGCX[IJD]\(unit,colnum,f)o(row)o(,nro)o (ws,f)o(bit)o(,nbi)o(t,)42 b(>)47 b(array,status\))0 788 y Fh(11)f Fi(Get)37 b(the)e(descriptor)h(for)f(a)h(v)-5 b(ariable)37 b(length)f(column)f(in)g(a)h(binary)f(table.)57 b(The)35 b(descriptor)h(consists)g(of)227 901 y(2)c(in)m(teger)g (parameters:)42 b(the)31 b(n)m(um)m(b)s(er)f(of)h(elemen)m(ts)i(in)d (the)h(arra)m(y)h(and)e(the)h(starting)h(o\013set)g(relativ)m(e)h(to) 227 1014 y(the)28 b(start)f(of)g(the)h(heap.)39 b(The)27 b(\014rst)f(routine)h(returns)f(a)h(single)h(descriptor)f(whereas)g (the)g(second)g(routine)227 1127 y(returns)i(the)i(descriptors)f(for)g (a)h(range)g(of)f(ro)m(ws)h(in)f(the)g(table.)382 1359 y Fe(FTGDES\(unit,colnum,rownu)o(m,)41 b(>)48 b (nelements,offset,status\))382 1472 y(FTGDESLL\(unit,colnum,row)o(num)o (,)42 b(>)47 b(nelementsll,offsetll,statu)o(s\))382 1698 y(FTGDESS\(unit,colnum,firs)o(tro)o(w,nr)o(ows)41 b(>)48 b(nelements,offset,)43 b(status\))382 1811 y(FTGDESSLL\(unit,colnum,fi) o(rst)o(row,)o(nrow)o(s)f(>)47 b(nelementsll,offsetll,)42 b(status\))0 2044 y Fh(12)k Fi(W)-8 b(rite)33 b(the)f(descriptor)g(for) f(a)i(v)-5 b(ariable)32 b(length)g(column)g(in)f(a)i(binary)e(table.)45 b(These)32 b(subroutines)e(can)j(b)s(e)227 2157 y(used)f(in)h (conjunction)g(with)g(FTGDES)g(to)g(enable)h(2)f(or)g(more)g(arra)m(ys) h(to)f(p)s(oin)m(t)g(to)h(the)f(same)g(storage)227 2270 y(lo)s(cation)f(to)f(sa)m(v)m(e)h(storage)g(space)f(if)f(the)h(arra)m (ys)g(are)g(iden)m(tical.)382 2503 y Fe(FTPDES\(unit,colnum,rownu)o (m,n)o(elem)o(ents)o(,of)o(fset)o(,)42 b(>)47 b(status\))382 2615 y(FTPDESLL\(unit,colnum,row)o(num)o(,nel)o(emen)o(tsl)o(l,of)o (fset)o(ll,)41 b(>)48 b(status\))0 2945 y Fd(6.8)135 b(Ro)l(w)46 b(Selection)g(and)f(Calculator)h(Routines)0 3195 y Fi(These)21 b(routines)f(all)i(parse)f(and)f(ev)-5 b(aluate)23 b(an)d(input)g(string)h(con)m(taining)i(a)e(user)f (de\014ned)g(arithmetic)i(expression.)0 3308 y(The)29 b(\014rst)f(3)i(routines)f(select)i(ro)m(ws)e(in)g(a)h(FITS)e(table,)j (based)e(on)g(whether)g(the)g(expression)g(ev)-5 b(aluates)31 b(to)f(true)0 3421 y(\(not)e(equal)f(to)h(zero\))g(or)f(false)h (\(zero\).)41 b(The)27 b(other)g(routines)g(ev)-5 b(aluate)29 b(the)e(expression)g(and)f(calculate)k(a)d(v)-5 b(alue)0 3534 y(for)35 b(eac)m(h)h(ro)m(w)g(of)f(the)h(table.)56 b(The)35 b(allo)m(w)m(ed)i(expression)e(syn)m(tax)g(is)h(describ)s(ed)e (in)h(the)g(ro)m(w)h(\014lter)f(section)h(in)0 3647 y(the)h(earlier)h (`Extended)e(File)i(Name)f(Syn)m(tax')g(c)m(hapter)h(of)f(this)f(do)s (cumen)m(t.)60 b(The)36 b(expression)h(ma)m(y)g(also)h(b)s(e)0 3760 y(written)28 b(to)i(a)e(text)i(\014le,)f(and)f(the)h(name)f(of)h (the)f(\014le,)h(prep)s(ended)e(with)h(a)h('@')f(c)m(haracter)i(ma)m(y) f(b)s(e)f(supplied)f(for)0 3873 y(the)34 b('expr')g(parameter)g(\(e.g.) 53 b('@\014lename.txt'\).)f(The)34 b(expression)f(in)h(the)g(\014le)g (can)g(b)s(e)f(arbitrarily)h(complex)0 3985 y(and)h(extend)h(o)m(v)m (er)h(m)m(ultiple)f(lines)g(of)g(the)f(\014le.)57 b(Lines)36 b(that)g(b)s(egin)f(with)g(2)h(slash)g(c)m(haracters)h(\('//'\))h(will) e(b)s(e)0 4098 y(ignored)30 b(and)g(ma)m(y)h(b)s(e)f(used)g(to)h(add)e (commen)m(ts)j(to)f(the)f(\014le.)0 4331 y Fh(1)81 b Fi(Ev)-5 b(aluate)38 b(a)f(b)s(o)s(olean)g(expression)g(o)m(v)m(er)h (the)g(indicated)f(ro)m(ws,)i(returning)d(an)h(arra)m(y)h(of)f(\015ags) g(indicating)227 4444 y(whic)m(h)30 b(ro)m(ws)h(ev)-5 b(aluated)31 b(to)g(TR)m(UE/F)-10 b(ALSE)430 4677 y Fe (FTFROW\(unit,expr,firstr)o(ow,)41 b(nrows,)46 b(>)i(n_good_rows,)c (row_status,)h(status\))0 4910 y Fh(2)81 b Fi(Find)29 b(the)i(\014rst)f(ro)m(w)g(whic)m(h)g(satis\014es)h(the)g(input)e(b)s (o)s(olean)h(expression)430 5142 y Fe(FTFFRW\(unit,)44 b(expr,)i(>)i(rownum,)e(status\))0 5375 y Fh(3)81 b Fi(Ev)-5 b(aluate)35 b(an)f(expression)h(on)f(all)h(ro)m(ws)g(of)f(a)h(table.)54 b(If)34 b(the)g(input)g(and)g(output)g(\014les)g(are)h(not)g(the)f (same,)227 5488 y(cop)m(y)i(the)g(TR)m(UE)f(ro)m(ws)g(to)h(the)f (output)g(\014le;)j(if)d(the)g(output)g(table)h(is)f(not)h(empt)m(y)-8 b(,)37 b(then)e(this)g(routine)227 5601 y(will)28 b(app)s(end)e(the)i (new)f(selected)i(ro)m(ws)e(after)h(the)g(existing)h(ro)m(ws.)39 b(If)27 b(the)h(\014les)g(are)f(the)h(same,)h(delete)g(the)227 5714 y(F)-10 b(ALSE)30 b(ro)m(ws)h(\(preserv)m(e)f(the)h(TR)m(UE)f(ro)m (ws\).)p eop end %%Page: 65 71 TeXDict begin 65 70 bop 0 299 a Fg(6.9.)72 b(CELESTIAL)29 b(COORDINA)-8 b(TE)30 b(SYSTEM)f(SUBR)m(OUTINES)1307 b Fi(65)430 555 y Fe(FTSROW\(inunit,)43 b(outunit,)j(expr,)g(>)i (status\))0 816 y Fh(4)81 b Fi(Calculate)28 b(an)f(expression)f(for)h (the)f(indicated)i(ro)m(ws)e(of)h(a)g(table,)i(returning)d(the)h (results,)g(cast)h(as)f(datat)m(yp)s(e)227 929 y(\(TSHOR)-8 b(T,)32 b(TDOUBLE,)h(etc\),)h(in)e(arra)m(y)-8 b(.)48 b(If)31 b(n)m(ulv)-5 b(al==NULL,)33 b(UNDEFs)g(will)f(b)s(e)g(zero)s (ed)g(out.)47 b(F)-8 b(or)227 1042 y(v)m(ector)37 b(results,)f(the)f(n) m(um)m(b)s(er)e(of)i(elemen)m(ts)i(returned)c(ma)m(y)j(b)s(e)e(less)h (than)g(nelemen)m(ts)g(if)g(nelemen)m(ts)h(is)227 1155 y(not)30 b(an)g(ev)m(en)h(m)m(ultiple)f(of)g(the)g(result)g(dimension.) 40 b(Call)30 b(FTTEXP)g(to)g(obtain)h(the)f(dimensions)f(of)h(the)227 1268 y(results.)430 1529 y Fe(FTCROW\(unit,datatype,ex)o(pr,)o(firs)o (trow)o(,ne)o(leme)o(nts,)o(nul)o(val,)41 b(>)620 1642 y(array,anynul,status\))0 1903 y Fh(5)81 b Fi(Ev)-5 b(aluate)33 b(an)g(expression)f(and)h(write)f(the)h(result)g(either)g(to)h(a)f (column)f(\(if)h(the)g(expression)f(is)h(a)g(function)227 2016 y(of)d(other)g(columns)g(in)f(the)h(table\))h(or)f(to)g(a)h(k)m (eyw)m(ord)f(\(if)g(the)g(expression)f(ev)-5 b(aluates)32 b(to)e(a)g(constan)m(t)i(and)227 2129 y(is)f(not)f(a)h(function)f(of)h (other)f(columns)h(in)f(the)g(table\).)42 b(In)30 b(the)h(former)e (case,)j(the)f(parName)f(parameter)227 2242 y(is)40 b(the)g(name)f(of)h (the)g(column)f(\(whic)m(h)h(ma)m(y)g(or)f(ma)m(y)h(not)g(already)g (exist\))h(in)m(to)f(whic)m(h)g(to)g(write)g(the)227 2355 y(results,)e(and)f(parInfo)e(con)m(tains)j(an)f(optional)g(TF)m (ORM)g(k)m(eyw)m(ord)g(v)-5 b(alue)38 b(if)e(a)h(new)f(column)h(is)f(b) s(eing)227 2468 y(created.)42 b(If)28 b(a)h(TF)m(ORM)h(v)-5 b(alue)29 b(is)g(not)g(sp)s(eci\014ed)g(then)f(a)i(default)f(format)g (will)h(b)s(e)e(used,)h(dep)s(ending)e(on)227 2581 y(the)35 b(expression.)54 b(If)34 b(the)h(expression)f(ev)-5 b(aluates)37 b(to)e(a)g(constan)m(t,)i(then)e(the)g(result)f(will)h(b)s(e)f(written) h(to)227 2693 y(the)28 b(k)m(eyw)m(ord)g(name)f(giv)m(en)h(b)m(y)g(the) f(parName)h(parameter,)h(and)d(the)i(parInfo)e(parameter)i(ma)m(y)g(b)s (e)f(used)227 2806 y(to)k(supply)e(an)h(optional)i(commen)m(t)f(for)f (the)g(k)m(eyw)m(ord.)42 b(If)29 b(the)i(k)m(eyw)m(ord)g(do)s(es)f(not) g(already)h(exist,)g(then)227 2919 y(the)f(name)f(of)h(the)g(k)m(eyw)m (ord)g(m)m(ust)f(b)s(e)g(preceded)g(with)g(a)h('#')f(c)m(haracter,)j (otherwise)e(the)f(result)h(will)g(b)s(e)227 3032 y(written)h(to)g(a)g (column)f(with)g(that)h(name.)430 3293 y Fe(FTCALC\(inunit,)43 b(expr,)k(outunit,)e(parName,)h(parInfo,)f(>)j(status\))0 3554 y Fh(6)81 b Fi(This)38 b(calculator)k(routine)e(is)f(similar)h(to) g(the)g(previous)f(routine,)j(except)f(that)f(the)g(expression)f(is)h (only)227 3667 y(ev)-5 b(aluated)42 b(o)m(v)m(er)f(the)f(sp)s (eci\014ed)g(ro)m(w)g(ranges.)70 b(nranges)39 b(sp)s(eci\014es)h(the)g (n)m(um)m(b)s(er)f(of)h(ro)m(w)h(ranges,)i(and)227 3780 y(\014rstro)m(w)30 b(and)g(lastro)m(w)h(giv)m(e)h(the)f(starting)g(and) f(ending)g(ro)m(w)g(n)m(um)m(b)s(er)f(of)i(eac)m(h)g(range.)430 4041 y Fe(FTCALC_RNG\(inunit,)42 b(expr,)47 b(outunit,)e(parName,)h (parInfo,)573 4154 y(nranges,)f(firstrow,)h(lastrow,)f(>)j(status\))0 4415 y Fh(7)81 b Fi(Ev)-5 b(aluate)36 b(the)f(giv)m(en)h(expression)f (and)g(return)f(dimension)g(and)h(t)m(yp)s(e)g(information)g(on)g(the)h (result.)54 b(The)227 4528 y(returned)37 b(dimensions)f(corresp)s(ond)g (to)j(a)e(single)i(ro)m(w)e(en)m(try)h(of)f(the)h(requested)f (expression,)j(and)d(are)227 4641 y(equiv)-5 b(alen)m(t)26 b(to)f(the)g(result)f(of)g(\014ts)p 1380 4641 28 4 v 33 w(read)p 1585 4641 V 32 w(tdim\(\).)40 b(Note)25 b(that)g(strings)f (are)h(considered)f(to)h(b)s(e)f(one)g(elemen)m(t)227 4754 y(regardless)31 b(of)g(string)f(length.)41 b(If)30 b(maxdim)g(==)g(0,)h(then)f(naxes)g(is)h(optional.)430 5015 y Fe(FTTEXP\(unit,)44 b(expr,)i(maxdim)g(>)i(datatype,)d(nelem,)h (naxis,)g(naxes,)g(status\))0 5350 y Fd(6.9)135 b(Celestial)48 b(Co)t(ordinate)e(System)f(Subroutines)0 5601 y Fi(The)36 b(FITS)g(comm)m(unit)m(y)h(has)f(adopted)h(a)g(set)g(of)g(k)m(eyw)m (ord)g(con)m(v)m(en)m(tions)h(that)f(de\014ne)f(the)h(transformations)0 5714 y(needed)30 b(to)i(con)m(v)m(ert)g(b)s(et)m(w)m(een)f(pixel)g(lo)s (cations)h(in)e(an)h(image)h(and)e(the)g(corresp)s(onding)g(celestial)j (co)s(ordinates)p eop end %%Page: 66 72 TeXDict begin 66 71 bop 0 299 a Fi(66)1319 b Fg(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)0 555 y Fi(on)25 b(the)h(sky)-8 b(,)27 b(or)e(more)g(generally)-8 b(,)29 b(that)d(de\014ne)e(w)m(orld)h(co)s (ordinates)i(that)e(are)h(to)g(b)s(e)f(asso)s(ciated)i(with)e(an)m(y)h (pixel)0 668 y(lo)s(cation)36 b(in)e(an)h(n-dimensional)f(FITS)g(arra)m (y)-8 b(.)54 b(CFITSIO)33 b(is)h(distributed)g(with)g(a)h(couple)f(of)h (self-con)m(tained)0 781 y(W)-8 b(orld)28 b(Co)s(ordinate)f(System)f (\(W)m(CS\))i(routines,)g(ho)m(w)m(ev)m(er,)h(these)f(routines)f(DO)g (NOT)f(supp)s(ort)f(all)j(the)f(latest)0 894 y(W)m(CS)38 b(con)m(v)m(en)m(tions,)k(so)d(it)g(is)f(STR)m(ONGL)-8 b(Y)38 b(RECOMMENDED)h(that)f(soft)m(w)m(are)i(dev)m(elop)s(ers)e(use)g (a)h(more)0 1007 y(robust)30 b(external)h(W)m(CS)f(library)-8 b(.)41 b(Sev)m(eral)31 b(recommended)f(libraries)h(are:)95 1285 y Fe(WCSLIB)47 b(-)95 b(supported)45 b(by)i(Mark)g(Calabretta)95 1398 y(WCSTools)f(-)h(supported)f(by)h(Doug)g(Mink)95 1511 y(AST)g(library)f(-)i(developed)d(by)i(the)g(U.K.)g(Starlink)e (project)0 1788 y Fi(More)30 b(information)f(ab)s(out)g(the)g(W)m(CS)g (k)m(eyw)m(ord)h(con)m(v)m(en)m(tions)h(and)d(links)h(to)h(all)g(of)f (these)g(W)m(CS)g(libraries)h(can)0 1901 y(b)s(e)g(found)f(on)h(the)h (FITS)e(Supp)s(ort)g(O\016ce)h(w)m(eb)g(site)i(at)f(h)m (ttp://\014ts.gsfc.nasa.go)m(v)j(under)29 b(the)h(W)m(CS)h(link.)0 2061 y(The)i(functions)h(pro)m(vided)g(in)f(these)i(external)f(W)m(CS)g (libraries)h(will)f(need)g(access)h(to)g(the)f(W)m(CS)g(information)0 2174 y(con)m(tained)i(in)f(the)h(FITS)e(\014le)i(headers.)55 b(One)35 b(con)m(v)m(enien)m(t)i(w)m(a)m(y)f(to)g(pass)f(this)g (information)h(to)g(the)f(external)0 2287 y(library)k(is)h(to)h(use)e (FITSIO)g(to)h(cop)m(y)h(the)f(header)f(k)m(eyw)m(ords)h(in)m(to)h(one) f(long)g(c)m(haracter)i(string,)g(and)d(then)0 2400 y(pass)29 b(this)h(string)g(to)g(an)g(in)m(terface)h(routine)f(in)g(the)g (external)g(library)g(that)g(will)g(extract)i(the)e(necessary)g(W)m(CS) 0 2513 y(information)h(\(e.g.,)h(see)f(the)f(astFitsChan)h(and)f (astPutCards)g(routines)g(in)g(the)h(Starlink)f(AST)g(library\).)0 2673 y(The)24 b(follo)m(wing)j(FITSIO)c(routines)i(DO)g(NOT)f(supp)s (ort)f(the)i(more)g(recen)m(t)h(W)m(CS)f(con)m(v)m(en)m(tions)i(that)f (ha)m(v)m(e)g(b)s(een)0 2786 y(appro)m(v)m(ed)37 b(as)h(part)f(of)g (the)h(FITS)e(standard.)61 b(Consequen)m(tly)-8 b(,)39 b(the)f(follo)m(wing)g(routines)g(ARE)f(NO)m(W)h(DEP-)0 2899 y(RECA)-8 b(TED.)29 b(It)f(is)h(STR)m(ONGL)-8 b(Y)28 b(RECOMMENDED)h(that)g(soft)m(w)m(are)h(dev)m(elop)s(ers)f(not)g(use)f (these)h(routines,)0 3012 y(and)h(instead)g(use)g(an)h(external)g(W)m (CS)f(library)-8 b(,)31 b(as)g(describ)s(ed)e(ab)s(o)m(v)m(e.)0 3172 y(These)21 b(routines)g(are)g(included)f(mainly)h(for)g(bac)m(kw)m (ard)g(compatibilit)m(y)j(with)c(existing)i(soft)m(w)m(are.)39 b(They)21 b(supp)s(ort)0 3285 y(the)30 b(follo)m(wing)i(standard)d(map) g(pro)5 b(jections:)41 b(-SIN,)30 b(-T)-8 b(AN,)31 b(-AR)m(C,)g(-NCP)-8 b(,)30 b(-GLS,)g(-MER,)h(and)e(-AIT)h(\(these)0 3398 y(are)f(the)g(legal)h(v)-5 b(alues)29 b(for)f(the)h(co)s(ordt)m(yp)s(e) f(parameter\).)41 b(These)28 b(routines)h(are)g(based)f(on)g(similar)h (functions)f(in)0 3511 y(Classic)j(AIPS.)f(All)h(the)g(angular)f(quan)m (tities)i(are)f(giv)m(en)g(in)f(units)g(of)g(degrees.)0 3789 y Fh(1)81 b Fi(Get)22 b(the)g(v)-5 b(alues)21 b(of)h(all)g(the)g (standard)f(FITS)f(celestial)k(co)s(ordinate)f(system)e(k)m(eyw)m(ords) h(from)f(the)h(header)f(of)h(a)227 3902 y(FITS)j(image)i(\(i.e.,)h(the) d(primary)g(arra)m(y)h(or)f(an)h(image)g(extension\).)40 b(These)26 b(v)-5 b(alues)25 b(ma)m(y)h(then)g(b)s(e)e(passed)227 4015 y(to)39 b(the)e(subroutines)g(that)h(p)s(erform)e(the)i(co)s (ordinate)g(transformations.)63 b(If)37 b(an)m(y)h(or)g(all)g(of)g(the) g(W)m(CS)227 4127 y(k)m(eyw)m(ords)32 b(are)f(not)g(presen)m(t,)h(then) f(default)g(v)-5 b(alues)31 b(will)h(b)s(e)e(returned.)41 b(If)31 b(the)g(\014rst)g(co)s(ordinate)g(axis)h(is)227 4240 y(the)d(declination-lik)m(e)j(co)s(ordinate,)e(then)e(this)g (routine)h(will)g(sw)m(ap)f(them)h(so)g(that)g(the)g(longitudinal-lik)m (e)227 4353 y(co)s(ordinate)i(is)g(returned)e(as)i(the)f(\014rst)g (axis.)227 4513 y(If)35 b(the)h(\014le)f(uses)g(the)g(new)m(er)h('CDj)p 1454 4513 28 4 v 32 w(i')g(W)m(CS)f(transformation)h(matrix)g(k)m(eyw)m (ords)f(instead)h(of)f(old)h(st)m(yle)227 4625 y('CDEL)-8 b(Tn')37 b(and)f('CR)m(OT)-8 b(A2')38 b(k)m(eyw)m(ords,)h(then)e(this)f (routine)h(will)g(calculate)j(and)c(return)g(the)h(v)-5 b(alues)227 4738 y(of)33 b(the)g(equiv)-5 b(alen)m(t)35 b(old-st)m(yle)f(k)m(eyw)m(ords.)49 b(Note)34 b(that)g(the)f(con)m(v)m (ersion)h(from)e(the)i(new-st)m(yle)g(k)m(eyw)m(ords)227 4851 y(to)e(the)f(old-st)m(yle)h(v)-5 b(alues)31 b(is)g(sometimes)g (only)g(an)g(appro)m(ximation,)h(so)e(if)h(the)g(appro)m(ximation)h(is) e(larger)227 4964 y(than)37 b(an)h(in)m(ternally)g(de\014ned)e (threshold)h(lev)m(el,)k(then)c(CFITSIO)f(will)i(still)g(return)e(the)i (appro)m(ximate)227 5077 y(W)m(CS)f(k)m(eyw)m(ord)g(v)-5 b(alues,)39 b(but)d(will)h(also)h(return)d(with)i(status)g(=)f(506,)k (to)e(w)m(arn)e(the)h(calling)h(program)227 5190 y(that)30 b(appro)m(ximations)f(ha)m(v)m(e)h(b)s(een)e(made.)40 b(It)29 b(is)g(then)f(up)g(to)h(the)g(calling)i(program)d(to)h(decide)h (whether)227 5303 y(the)k(appro)m(ximations)g(are)g(su\016cien)m(tly)g (accurate)i(for)d(the)h(particular)f(application,)j(or)e(whether)f (more)227 5416 y(precise)e(W)m(CS)f(transformations)h(m)m(ust)f(b)s(e)g (p)s(erformed)f(using)h(new-st)m(yle)h(W)m(CS)g(k)m(eyw)m(ords)f (directly)-8 b(.)382 5694 y Fe(FTGICS\(unit,)44 b(>)k (xrval,yrval,xrpix,yrpix)o(,xin)o(c,yi)o(nc,)o(rot,)o(coor)o(dty)o (pe,s)o(tatu)o(s\))p eop end %%Page: 67 73 TeXDict begin 67 72 bop 0 299 a Fg(6.10.)73 b(FILE)30 b(CHECKSUM)f(SUBR)m(OUTINES)2080 b Fi(67)0 555 y Fh(2)81 b Fi(Get)34 b(the)f(v)-5 b(alues)33 b(of)g(all)h(the)f(standard)f(FITS) h(celestial)i(co)s(ordinate)f(system)f(k)m(eyw)m(ords)g(from)g(the)g (header)227 668 y(of)j(a)h(FITS)e(table)h(where)g(the)g(X)g(and)f(Y)h (\(or)g(RA)g(and)g(DEC)f(co)s(ordinates)i(are)f(stored)g(in)g(2)g (separate)227 781 y(columns)c(of)g(the)g(table.)46 b(These)31 b(v)-5 b(alues)32 b(ma)m(y)h(then)e(b)s(e)h(passed)f(to)h(the)g (subroutines)f(that)h(p)s(erform)f(the)227 894 y(co)s(ordinate)g (transformations.)382 1114 y Fe(FTGTCS\(unit,xcol,ycol,)42 b(>)716 1227 y(xrval,yrval,xrpix,yrpix,)o(xinc)o(,yi)o(nc,r)o(ot,c)o (oor)o(dtyp)o(e,st)o(atu)o(s\))0 1446 y Fh(3)81 b Fi(Calculate)42 b(the)g(celestial)h(co)s(ordinate)f(corresp)s(onding)e(to)i(the)f (input)f(X)h(and)g(Y)g(pixel)g(lo)s(cation)i(in)e(the)227 1559 y(image.)382 1779 y Fe(FTWLDP\(xpix,ypix,xrval,y)o(rva)o(l,xr)o (pix,)o(yrp)o(ix,x)o(inc,)o(yin)o(c,ro)o(t,)1241 1892 y(coordtype,)k(>)i(xpos,ypos,status\))0 2112 y Fh(4)81 b Fi(Calculate)42 b(the)g(X)f(and)f(Y)h(pixel)h(lo)s(cation)g(corresp)s (onding)e(to)i(the)f(input)f(celestial)k(co)s(ordinate)e(in)f(the)227 2225 y(image.)382 2445 y Fe(FTXYPX\(xpos,ypos,xrval,y)o(rva)o(l,xr)o (pix,)o(yrp)o(ix,x)o(inc,)o(yin)o(c,ro)o(t,)1241 2557 y(coordtype,)k(>)i(xpix,ypix,status\))0 2885 y Fd(6.10)136 b(File)45 b(Chec)l(ksum)g(Subroutines)0 3135 y Fi(The)33 b(follo)m(wing)h(routines)f(either)h(compute)f(or)h(v)-5 b(alidate)34 b(the)g(c)m(hec)m(ksums)f(for)g(the)h(CHDU.)g(The)e(D)m(A) -8 b(T)g(ASUM)0 3248 y(k)m(eyw)m(ord)33 b(is)f(used)f(to)i(store)f(the) h(n)m(umerical)f(v)-5 b(alue)33 b(of)f(the)g(32-bit,)i(1's)f(complemen) m(t)g(c)m(hec)m(ksum)g(for)f(the)g(data)0 3361 y(unit)26 b(alone.)40 b(If)25 b(there)h(is)h(no)e(data)i(unit)f(then)f(the)h(v)-5 b(alue)27 b(is)f(set)g(to)h(zero.)40 b(The)26 b(n)m(umerical)g(v)-5 b(alue)27 b(is)f(stored)g(as)g(an)0 3474 y(ASCI)s(I)20 b(string)i(of)h(digits,)h(enclosed)f(in)e(quotes,)k(b)s(ecause)d(the)g (v)-5 b(alue)23 b(ma)m(y)f(b)s(e)f(to)s(o)i(large)g(to)g(represen)m(t)f (as)g(a)h(32-bit)0 3587 y(signed)28 b(in)m(teger.)41 b(The)27 b(CHECKSUM)g(k)m(eyw)m(ord)i(is)f(used)f(to)h(store)h(the)f (ASCI)s(I)e(enco)s(ded)i(COMPLEMENT)f(of)0 3700 y(the)f(c)m(hec)m(ksum) h(for)f(the)h(en)m(tire)g(HDU.)g(Storing)f(the)h(complemen)m(t,)h (rather)e(than)g(the)h(actual)g(c)m(hec)m(ksum,)h(forces)0 3812 y(the)k(c)m(hec)m(ksum)h(for)f(the)h(whole)f(HDU)h(to)g(equal)g (zero.)47 b(If)31 b(the)i(\014le)f(has)g(b)s(een)f(mo)s(di\014ed)g (since)i(the)f(c)m(hec)m(ksums)0 3925 y(w)m(ere)39 b(computed,)i(then)e (the)g(HDU)g(c)m(hec)m(ksum)h(will)f(usually)f(not)h(equal)h(zero.)66 b(These)39 b(c)m(hec)m(ksum)g(k)m(eyw)m(ord)0 4038 y(con)m(v)m(en)m (tions)34 b(are)f(based)f(on)g(a)g(pap)s(er)f(b)m(y)h(Rob)g(Seaman)g (published)f(in)h(the)g(pro)s(ceedings)g(of)g(the)h(AD)m(ASS)f(IV)0 4151 y(conference)f(in)f(Baltimore)i(in)f(No)m(v)m(em)m(b)s(er)g(1994)h (and)e(a)h(later)g(revision)g(in)f(June)f(1995.)0 4371 y Fh(1)81 b Fi(Compute)33 b(and)g(write)h(the)g(D)m(A)-8 b(T)g(ASUM)35 b(and)e(CHECKSUM)g(k)m(eyw)m(ord)h(v)-5 b(alues)34 b(for)f(the)h(CHDU)g(in)m(to)h(the)227 4484 y(curren)m(t)25 b(header.)38 b(The)24 b(D)m(A)-8 b(T)g(ASUM)27 b(v)-5 b(alue)25 b(is)f(the)h(32-bit)h(c)m(hec)m(ksum)f(for)f(the)h (data)g(unit,)h(expressed)e(as)h(a)227 4597 y(decimal)32 b(in)m(teger)f(enclosed)g(in)f(single)h(quotes.)41 b(The)30 b(CHECKSUM)g(k)m(eyw)m(ord)g(v)-5 b(alue)31 b(is)f(a)h(16-c)m(haracter) 227 4710 y(string)j(whic)m(h)f(is)h(the)f(ASCI)s(I-enco)s(ded)f(v)-5 b(alue)34 b(for)g(the)f(complemen)m(t)i(of)f(the)f(c)m(hec)m(ksum)i (for)e(the)h(whole)227 4823 y(HDU.)h(If)e(these)g(k)m(eyw)m(ords)h (already)g(exist,)h(their)e(v)-5 b(alues)34 b(will)g(b)s(e)f(up)s (dated)f(only)h(if)g(necessary)h(\(i.e.,)i(if)227 4936 y(the)31 b(\014le)f(has)g(b)s(een)g(mo)s(di\014ed)f(since)i(the)g (original)g(k)m(eyw)m(ord)g(v)-5 b(alues)31 b(w)m(ere)g(computed\).)382 5155 y Fe(FTPCKS\(unit,)44 b(>)k(status\))0 5375 y Fh(2)81 b Fi(Up)s(date)28 b(the)h(CHECKSUM)e(k)m(eyw)m(ord)i(v)-5 b(alue)29 b(in)f(the)h(CHDU,)g(assuming)f(that)h(the)f(D)m(A)-8 b(T)g(ASUM)30 b(k)m(eyw)m(ord)227 5488 y(exists)36 b(and)f(already)h (has)f(the)h(correct)g(v)-5 b(alue.)56 b(This)35 b(routine)g (calculates)j(the)e(new)f(c)m(hec)m(ksum)h(for)f(the)227 5601 y(curren)m(t)40 b(header)g(unit,)j(adds)c(it)i(to)g(the)f(data)h (unit)f(c)m(hec)m(ksum,)k(enco)s(des)c(the)g(v)-5 b(alue)41 b(in)m(to)g(an)f(ASCI)s(I)227 5714 y(string,)31 b(and)f(writes)g(the)h (string)f(to)h(the)g(CHECKSUM)e(k)m(eyw)m(ord.)p eop end %%Page: 68 74 TeXDict begin 68 73 bop 0 299 a Fi(68)1319 b Fg(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)382 555 y Fe(FTUCKS\(unit,)44 b(>)k(status\))0 807 y Fh(3)81 b Fi(V)-8 b(erify)35 b(the)f(CHDU)h(b)m(y)g(computing)f (the)h(c)m(hec)m(ksums)g(and)f(comparing)h(them)f(with)g(the)h(k)m(eyw) m(ords.)53 b(The)227 920 y(data)34 b(unit)f(is)g(v)m(eri\014ed)g (correctly)h(if)f(the)h(computed)f(c)m(hec)m(ksum)g(equals)h(the)f(v)-5 b(alue)34 b(of)f(the)g(D)m(A)-8 b(T)g(ASUM)227 1033 y(k)m(eyw)m(ord.)64 b(The)37 b(c)m(hec)m(ksum)i(for)f(the)g(en)m(tire)g(HDU)h(\(header)f (plus)f(data)i(unit\))e(is)h(correct)h(if)f(it)h(equals)227 1146 y(zero.)55 b(The)34 b(output)g(D)m(A)-8 b(T)g(A)m(OK)37 b(and)d(HDUOK)h(parameters)g(in)f(this)h(subroutine)e(are)i(in)m (tegers)h(whic)m(h)227 1259 y(will)27 b(ha)m(v)m(e)g(a)f(v)-5 b(alue)27 b(=)f(1)g(if)g(the)h(data)f(or)g(HDU)h(is)f(v)m(eri\014ed)h (correctly)-8 b(,)29 b(a)d(v)-5 b(alue)27 b(=)e(0)i(if)f(the)g(D)m(A)-8 b(T)g(ASUM)28 b(or)227 1372 y(CHECKSUM)h(k)m(eyw)m(ord)g(is)h(not)f (presen)m(t,)h(or)f(v)-5 b(alue)30 b(=)f(-1)h(if)f(the)h(computed)f(c)m (hec)m(ksum)h(is)f(not)h(correct.)382 1623 y Fe(FTVCKS\(unit,)44 b(>)k(dataok,hduok,status\))0 1875 y Fh(4)81 b Fi(Compute)25 b(and)h(return)f(the)i(c)m(hec)m(ksum)g(v)-5 b(alues)26 b(for)g(the)h(CHDU)f(\(as)h(double)f(precision)h(v)-5 b(ariables\))27 b(without)227 1988 y(creating)46 b(or)e(mo)s(difying)g (the)h(CHECKSUM)e(and)h(D)m(A)-8 b(T)g(ASUM)46 b(k)m(eyw)m(ords.)83 b(This)44 b(routine)g(is)h(used)227 2101 y(in)m(ternally)32 b(b)m(y)e(FTV)m(CKS,)g(but)g(ma)m(y)h(b)s(e)e(useful)h(in)g(other)h (situations)g(as)f(w)m(ell.)382 2353 y Fe(FTGCKS\(unit,)44 b(>)k(datasum,hdusum,status\))0 2604 y Fh(5)81 b Fi(Enco)s(de)33 b(a)h(c)m(hec)m(ksum)h(v)-5 b(alue)34 b(\(stored)g(in)g(a)g(double)g (precision)g(v)-5 b(ariable\))35 b(in)m(to)f(a)h(16-c)m(haracter)h (string.)51 b(If)227 2717 y(COMPLEMENT)30 b(=)g(.true.)41 b(then)30 b(the)g(32-bit)i(sum)d(v)-5 b(alue)31 b(will)g(b)s(e)f (complemen)m(ted)h(b)s(efore)f(enco)s(ding.)382 2969 y Fe(FTESUM\(sum,complement,)42 b(>)47 b(checksum\))0 3221 y Fh(6)81 b Fi(Deco)s(de)39 b(a)f(16)h(c)m(haracter)h(c)m(hec)m (ksum)e(string)g(in)m(to)h(a)g(double)e(precision)h(v)-5 b(alue.)65 b(If)37 b(COMPLEMENT)g(=)227 3334 y(.true.)k(then)30 b(the)h(32-bit)g(sum)f(v)-5 b(alue)31 b(will)f(b)s(e)g(complemen)m(ted) i(after)e(deco)s(ding.)382 3586 y Fe(FTDSUM\(checksum,compleme)o(nt,)41 b(>)48 b(sum\))0 3918 y Fd(6.11)180 b(Date)46 b(and)f(Time)g(Utilit)l (y)i(Routines)0 4168 y Fi(The)29 b(follo)m(wing)i(routines)f(help)f(to) i(construct)f(or)f(parse)h(the)g(FITS)f(date/time)i(strings.)41 b(Starting)30 b(in)f(the)h(y)m(ear)0 4281 y(2000,)k(the)d(FITS)g(D)m(A) -8 b(TE)32 b(k)m(eyw)m(ord)g(v)-5 b(alues)31 b(\(and)h(the)f(v)-5 b(alues)32 b(of)f(other)h(`D)m(A)-8 b(TE-')33 b(k)m(eyw)m(ords\))f(m)m (ust)f(ha)m(v)m(e)i(the)0 4394 y(form)j('YYYY-MM-DD')k(\(date)e(only\)) f(or)g('YYYY-MM-DDThh:mm:ss.ddd...')61 b(\(date)38 b(and)e(time\))h (where)0 4507 y(the)30 b(n)m(um)m(b)s(er)f(of)i(decimal)g(places)g(in)f (the)g(seconds)g(v)-5 b(alue)31 b(is)f(optional.)42 b(These)30 b(times)h(are)f(in)g(UTC.)g(The)g(older)0 4620 y('dd/mm/yy')g(date)h (format)g(ma)m(y)g(not)g(b)s(e)e(used)h(for)g(dates)h(after)g(01)g(Jan) m(uary)f(2000.)0 4872 y Fh(1)81 b Fi(Get)31 b(the)g(curren)m(t)f (system)g(date.)42 b(The)29 b(returned)h(y)m(ear)h(has)f(4)h(digits)g (\(1999,)h(2000,)h(etc.\))382 5123 y Fe(FTGSDT\()46 b(>)h(day,)g (month,)f(year,)g(status)g(\))0 5375 y Fh(2)81 b Fi(Get)34 b(the)g(curren)m(t)g(system)f(date)i(and)e(time)h(string)g (\('YYYY-MM-DDThh:mm:ss'\).)53 b(The)33 b(time)i(will)f(b)s(e)227 5488 y(in)26 b(UTC/GMT)g(if)g(a)m(v)-5 b(ailable,)29 b(as)e(indicated)f(b)m(y)g(a)g(returned)f(timeref)h(v)-5 b(alue)27 b(=)e(0.)40 b(If)26 b(the)g(returned)e(v)-5 b(alue)227 5601 y(of)31 b(timeref)g(=)g(1)g(then)f(this)h(indicates)g (that)h(it)f(w)m(as)g(not)g(p)s(ossible)f(to)h(con)m(v)m(ert)i(the)d (lo)s(cal)i(time)g(to)f(UTC,)227 5714 y(and)f(th)m(us)g(the)h(lo)s(cal) g(time)g(w)m(as)g(returned.)p eop end %%Page: 69 75 TeXDict begin 69 74 bop 0 299 a Fg(6.12.)73 b(GENERAL)30 b(UTILITY)g(SUBR)m(OUTINES)1979 b Fi(69)382 555 y Fe(FTGSTM\(>)45 b(datestr,)h(timeref,)f(status\))0 821 y Fh(3)81 b Fi(Construct)26 b(a)i(date)g(string)f(from)g(the)g(input)f(date)i(v)-5 b(alues.)40 b(If)27 b(the)g(y)m(ear)h(is)g(b)s(et)m(w)m(een)f(1900)i (and)e(1998,)j(inclu-)227 934 y(siv)m(e,)38 b(then)c(the)i(returned)d (date)j(string)f(will)g(ha)m(v)m(e)i(the)e(old)g(FITS)f(format)i (\('dd/mm/yy'\),)h(otherwise)227 1047 y(the)32 b(date)g(string)f(will)g (ha)m(v)m(e)i(the)e(new)g(FITS)g(format)g(\('YYYY-MM-DD'\).)36 b(Use)c(FTTM2S)f(instead)g(to)227 1160 y(alw)m(a)m(ys)h(return)d(a)i (date)g(string)g(using)e(the)i(new)f(FITS)g(format.)382 1426 y Fe(FTDT2S\()46 b(year,)g(month,)g(day,)h(>)g(datestr,)f (status\))0 1692 y Fh(4)81 b Fi(Construct)34 b(a)i(new-format)f(date)h (+)f(time)h(string)f(\('YYYY-MM-DDThh:mm:ss.ddd...'\).)57 b(If)34 b(the)i(y)m(ear,)227 1805 y(mon)m(th,)d(and)e(da)m(y)h(v)-5 b(alues)32 b(all)h(=)e(0)h(then)g(only)g(the)g(time)g(is)g(enco)s(ded)f (with)h(format)g('hh:mm:ss.ddd...'.)227 1918 y(The)j(decimals)h (parameter)g(sp)s(eci\014es)e(ho)m(w)i(man)m(y)f(decimal)h(places)g(of) f(fractional)i(seconds)e(to)h(include)227 2030 y(in)30 b(the)h(string.)41 b(If)29 b(`decimals')j(is)f(negativ)m(e,)h(then)f (only)f(the)h(date)g(will)f(b)s(e)g(return)f(\('YYYY-MM-DD'\).)382 2296 y Fe(FTTM2S\()46 b(year,)g(month,)g(day,)h(hour,)f(minute,)g (second,)g(decimals,)764 2409 y(>)h(datestr,)f(status\))0 2675 y Fh(5)81 b Fi(Return)44 b(the)g(date)i(as)f(read)f(from)h(the)g (input)e(string,)49 b(where)44 b(the)h(string)g(ma)m(y)g(b)s(e)f(in)h (either)g(the)g(old)227 2788 y(\('dd/mm/yy'\))31 b(or)g(new)e (\('YYYY-MM-DDThh:mm:ss')k(or)d('YYYY-MM-DD'\))k(FITS)c(format.)382 3054 y Fe(FTS2DT\(datestr,)43 b(>)48 b(year,)e(month,)g(day,)h (status\))0 3320 y Fh(6)81 b Fi(Return)30 b(the)h(date)h(and)f(time)h (as)f(read)g(from)g(the)h(input)e(string,)h(where)g(the)h(string)f(ma)m (y)h(b)s(e)e(in)h(either)h(the)227 3433 y(old)d(or)f(new)g(FITS)g (format.)40 b(The)28 b(returned)f(hours,)h(min)m(utes,)h(and)f(seconds) g(v)-5 b(alues)29 b(will)f(b)s(e)g(set)h(to)g(zero)227 3546 y(if)k(the)h(input)e(string)h(do)s(es)g(not)h(include)f(the)g (time)h(\('dd/mm/yy')f(or)h('YYYY-MM-DD'\))j(.)c(Similarly)-8 b(,)227 3659 y(the)36 b(returned)e(y)m(ear,)j(mon)m(th,)g(and)d(date)i (v)-5 b(alues)36 b(will)f(b)s(e)g(set)h(to)g(zero)g(if)f(the)g(date)h (is)f(not)h(included)e(in)227 3772 y(the)d(input)e(string)i (\('hh:mm:ss.ddd...'\).)382 4037 y Fe(FTS2TM\(datestr,)43 b(>)48 b(year,)e(month,)g(day,)h(hour,)f(minute,)g(second,)g(status\))0 4378 y Fd(6.12)136 b(General)45 b(Utilit)l(y)i(Subroutines)0 4630 y Fi(The)30 b(follo)m(wing)i(utilit)m(y)f(subroutines)f(ma)m(y)h (b)s(e)e(useful)h(for)g(certain)h(applications:)0 4896 y Fh(1)81 b Fi(Return)29 b(the)i(starting)g(b)m(yte)g(address)e(of)i (the)f(CHDU)h(and)f(the)h(next)f(HDU.)382 5162 y Fe(FTGHAD\(iunit,)44 b(>)j(curaddr,)f(nextaddr\))0 5428 y Fh(2)81 b Fi(Con)m(v)m(ert)31 b(a)g(c)m(haracter)h(string)e(to)h(upp)s(ercase)e(\(op)s(erates)j(in)e (place\).)382 5694 y Fe(FTUPCH\(string\))p eop end %%Page: 70 76 TeXDict begin 70 75 bop 0 299 a Fi(70)1319 b Fg(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)0 555 y Fh(3)81 b Fi(Compare)43 b(the)i(input)e (template)i(string)f(against)h(the)g(reference)f(string)g(to)h(see)g (if)f(they)g(matc)m(h.)82 b(The)227 668 y(template)36 b(string)f(ma)m(y)g(con)m(tain)g(wildcard)f(c)m(haracters:)51 b('*')35 b(will)g(matc)m(h)g(an)m(y)g(sequence)g(of)f(c)m(haracters)227 781 y(\(including)j(zero)h(c)m(haracters\))g(and)e(')10 b(?')60 b(will)38 b(matc)m(h)f(an)m(y)g(single)h(c)m(haracter)g(in)f (the)g(reference)g(string.)227 894 y(The)31 b('#')g(c)m(haracter)i (will)f(matc)m(h)g(an)m(y)f(consecutiv)m(e)j(string)d(of)g(decimal)h (digits)g(\(0)g(-)g(9\).)43 b(If)31 b(CASESN)f(=)227 1007 y(.true.)45 b(then)31 b(the)g(matc)m(h)i(will)f(b)s(e)f(case)h (sensitiv)m(e.)46 b(The)31 b(returned)f(MA)-8 b(TCH)32 b(parameter)g(will)g(b)s(e)f(.true.)227 1120 y(if)j(the)h(2)f(strings)g (matc)m(h,)j(and)c(EXA)m(CT)h(will)h(b)s(e)e(.true.)53 b(if)34 b(the)g(matc)m(h)h(is)g(exact)g(\(i.e.,)i(if)d(no)g(wildcard) 227 1233 y(c)m(haracters)e(w)m(ere)f(used)f(in)g(the)g(matc)m(h\).)42 b(Both)31 b(strings)f(m)m(ust)h(b)s(e)e(68)j(c)m(haracters)f(or)g(less) f(in)g(length.)382 1505 y Fe(FTCMPS\(str_template,)42 b(string,)k(casesen,)f(>)j(match,)e(exact\))0 1778 y Fh(4)81 b Fi(T)-8 b(est)31 b(that)g(the)f(k)m(eyw)m(ord)h(name)f(con)m (tains)i(only)e(legal)j(c)m(haracters:)42 b(A-Z,0-9,)32 b(h)m(yphen,)d(and)h(underscore.)382 2051 y Fe(FTTKEY\(keyword,)43 b(>)48 b(status\))0 2324 y Fh(5)81 b Fi(T)-8 b(est)31 b(that)g(the)f(k)m(eyw)m(ord)h(record)f(con)m(tains)i(only)e(legal)i (prin)m(table)f(ASCI)s(I)e(c)m(haracters)382 2597 y Fe(FTTREC\(card,)44 b(>)k(status\))0 2869 y Fh(6)81 b Fi(T)-8 b(est)25 b(whether)f(the)h (curren)m(t)f(header)h(con)m(tains)g(an)m(y)g(NULL)g(\(ASCI)s(I)e(0\))j (c)m(haracters.)40 b(These)24 b(c)m(haracters)j(are)227 2982 y(illegal)37 b(in)d(the)h(header,)g(but)f(they)g(will)h(go)g (undetected)g(b)m(y)f(most)h(of)g(the)f(CFITSIO)f(k)m(eyw)m(ord)i (header)227 3095 y(routines,)29 b(b)s(ecause)f(the)h(n)m(ull)f(is)g(in) m(terpreted)g(as)h(the)f(normal)g(end-of-string)h(terminator.)41 b(This)27 b(routine)227 3208 y(returns)h(the)g(p)s(osition)h(of)g(the)g (\014rst)f(n)m(ull)g(c)m(haracter)i(in)f(the)f(header,)h(or)g(zero)g (if)g(there)g(are)g(no)f(n)m(ulls.)40 b(F)-8 b(or)227 3321 y(example)37 b(a)f(returned)f(v)-5 b(alue)37 b(of)f(110)h(w)m (ould)f(indicate)h(that)g(the)f(\014rst)f(NULL)h(is)g(lo)s(cated)h(in)f (the)g(30th)227 3434 y(c)m(haracter)28 b(of)f(the)g(second)f(k)m(eyw)m (ord)h(in)f(the)h(header)f(\(recall)i(that)f(eac)m(h)h(header)e(record) h(is)f(80)h(c)m(haracters)227 3547 y(long\).)56 b(Note)36 b(that)g(this)f(is)g(one)g(of)g(the)g(few)g(FITSIO)f(routines)h(in)f (whic)m(h)h(the)g(returned)f(v)-5 b(alue)36 b(is)f(not)227 3660 y(necessarily)d(equal)e(to)i(the)e(status)h(v)-5 b(alue\).)382 3933 y Fe(FTNCHK\(unit,)44 b(>)k(status\))0 4205 y Fh(7)81 b Fi(P)m(arse)27 b(a)f(header)h(k)m(eyw)m(ord)g(record)f (and)g(return)f(the)i(name)f(of)h(the)f(k)m(eyw)m(ord)h(and)f(the)h (length)f(of)h(the)g(name.)227 4318 y(The)34 b(k)m(eyw)m(ord)h(name)f (normally)h(o)s(ccupies)f(the)h(\014rst)e(8)i(c)m(haracters)g(of)g(the) f(record,)i(except)f(under)e(the)227 4431 y(HIERAR)m(CH)e(con)m(v)m(en) m(tion)h(where)e(the)h(name)f(can)h(b)s(e)f(up)f(to)i(70)g(c)m (haracters)h(in)e(length.)382 4704 y Fe(FTGKNM\(card,)44 b(>)k(keyname,)d(keylength,)g(staThe)h('\\#')h(character)e(will)i (match)f(any)h(consecutive)e(string)191 4817 y(of)i(decimal)f(digits)g (\(0)h(-)h(9\).)f(tus\))0 5090 y Fh(8)81 b Fi(P)m(arse)34 b(a)h(header)f(k)m(eyw)m(ord)h(record.)52 b(This)33 b(subroutine)g (parses)h(the)g(input)g(header)g(record)g(to)h(return)e(the)227 5203 y(v)-5 b(alue)27 b(\(as)g(a)g(c)m(haracter)g(string\))g(and)f (commen)m(t)h(strings.)39 b(If)26 b(the)g(k)m(eyw)m(ord)h(has)f(no)g(v) -5 b(alue)27 b(\(columns)f(9-10)227 5316 y(not)h(equal)f(to)h('=)f ('\),)i(then)e(the)g(v)-5 b(alue)27 b(string)f(is)g(returned)f(blank)h (and)f(the)h(commen)m(t)i(string)e(is)g(set)g(equal)227 5428 y(to)31 b(column)g(9)f(-)h(80)g(of)g(the)f(input)g(string.)382 5701 y Fe(FTPSVC\(card,)44 b(>)k(value,comment,status\))p eop end %%Page: 71 77 TeXDict begin 71 76 bop 0 299 a Fg(6.12.)73 b(GENERAL)30 b(UTILITY)g(SUBR)m(OUTINES)1979 b Fi(71)0 555 y Fh(9)81 b Fi(Construct)41 b(a)h(prop)s(erly)f(formated)h(80-c)m(haracter)i (header)e(k)m(eyw)m(ord)g(record)f(from)h(the)g(input)e(k)m(eyw)m(ord) 227 668 y(name,)25 b(k)m(eyw)m(ord)f(v)-5 b(alue,)25 b(and)e(k)m(eyw)m(ord)h(commen)m(t)g(strings.)38 b(Hierarc)m(hical)26 b(k)m(eyw)m(ord)e(names)f(\(e.g.,)j("ESO)227 781 y(TELE)e(CAM"\))i(are) f(supp)s(orted.)37 b(The)25 b(v)-5 b(alue)25 b(string)g(ma)m(y)h(con)m (tain)g(an)f(in)m(teger,)i(\015oating)f(p)s(oin)m(t,)g(logical,)227 894 y(or)31 b(quoted)f(c)m(haracter)i(string)e(\(e.g.,)j("12",)f ("15.7",)h("T",)e(or)g("'NGC)g(1313'"\).)382 1153 y Fe (FTMKKY\(keyname,)43 b(value,)k(comment,)e(>)j(card,)e(status\))0 1413 y Fh(10)g Fi(Construct)35 b(a)g(sequence)g(k)m(eyw)m(ord)g(name)g (\(R)m(OOT)g(+)f(nnn\).)54 b(This)34 b(subroutine)f(app)s(ends)g(the)j (sequence)227 1526 y(n)m(um)m(b)s(er)29 b(to)i(the)g(ro)s(ot)g(string)f (to)h(create)h(a)f(k)m(eyw)m(ord)g(name)f(\(e.g.,)i('NAXIS')f(+)f(2)h (=)f('NAXIS2'\))382 1785 y Fe(FTKEYN\(keyroot,seq_no,)42 b(>)47 b(keyword,status\))0 2045 y Fh(11)f Fi(Construct)30 b(a)g(sequence)g(k)m(eyw)m(ord)h(name)f(\(n)f(+)h(R)m(OOT\).)g(This)f (subroutine)g(concatenates)j(the)f(sequence)227 2158 y(n)m(um)m(b)s(er)20 b(to)j(the)e(fron)m(t)h(of)g(the)f(ro)s(ot)h (string)g(to)g(create)h(a)f(k)m(eyw)m(ord)g(name)g(\(e.g.,)j(1)d(+)f ('CTYP')g(=)g('1CTYP'\))382 2417 y Fe(FTNKEY\(seq_no,keyroot,)42 b(>)47 b(keyword,status\))0 2677 y Fh(12)f Fi(Determine)35 b(the)f(datat)m(yp)s(e)g(of)g(a)g(k)m(eyw)m(ord)h(v)-5 b(alue)34 b(string.)50 b(This)33 b(subroutine)g(parses)g(the)h(k)m(eyw) m(ord)g(v)-5 b(alue)227 2790 y(string)31 b(\(usually)f(columns)g(11-30) j(of)d(the)h(header)f(record\))g(to)i(determine)e(its)h(datat)m(yp)s (e.)382 3049 y Fe(FTDTYP\(value,)44 b(>)j(dtype,status\))0 3309 y Fh(13)f Fi(Return)c(the)i(class)g(of)f(input)f(header)h(record.) 79 b(The)43 b(record)g(is)g(classi\014ed)g(in)m(to)h(one)g(of)f(the)g (follo)m(wing)227 3422 y(categories)36 b(\(the)e(class)f(v)-5 b(alues)34 b(are)f(de\014ned)f(in)h(\014tsio.h\).)49 b(Note)35 b(that)e(this)g(is)g(one)h(of)f(the)g(few)g(FITSIO)227 3535 y(routines)e(that)f(do)s(es)h(not)f(return)f(a)i(status)g(v)-5 b(alue.)334 3794 y Fe(Class)94 b(Value)619 b(Keywords)95 3907 y(TYP_STRUC_KEY)92 b(10)j(SIMPLE,)46 b(BITPIX,)g(NAXIS,)g(NAXISn,) g(EXTEND,)g(BLOCKED,)1002 4020 y(GROUPS,)g(PCOUNT,)g(GCOUNT,)g(END)1002 4133 y(XTENSION,)g(TFIELDS,)f(TTYPEn,)h(TBCOLn,)g(TFORMn,)g(THEAP,)1002 4246 y(and)h(the)g(first)f(4)i(COMMENT)e(keywords)f(in)i(the)g(primary) f(array)1002 4359 y(that)h(define)f(the)h(FITS)g(format.)95 4472 y(TYP_CMPRS_KEY)92 b(20)j(The)47 b(keywords)f(used)g(in)i(the)e (compressed)f(image)95 b(or)47 b(table)1002 4585 y(format,)f(including) f(ZIMAGE,)h(ZCMPTYPE,)f(ZNAMEn,)h(ZVALn,)1002 4698 y(ZTILEn,)g (ZBITPIX,)g(ZNAXISn,)f(ZSCALE,)h(ZZERO,)g(ZBLANK)95 4811 y(TYP_SCAL_KEY)140 b(30)95 b(BSCALE,)46 b(BZERO,)g(TSCALn,)g(TZEROn)95 4924 y(TYP_NULL_KEY)140 b(40)95 b(BLANK,)46 b(TNULLn)95 5036 y(TYP_DIM_KEY)188 b(50)95 b(TDIMn)95 5149 y(TYP_RANG_KEY)140 b(60)95 b(TLMINn,)46 b(TLMAXn,)g(TDMINn,)g(TDMAXn,)g(DATAMIN,)f (DATAMAX)95 5262 y(TYP_UNIT_KEY)140 b(70)95 b(BUNIT,)46 b(TUNITn)95 5375 y(TYP_DISP_KEY)140 b(80)95 b(TDISPn)95 5488 y(TYP_HDUID_KEY)d(90)j(EXTNAME,)46 b(EXTVER,)g(EXTLEVEL,)f (HDUNAME,)g(HDUVER,)h(HDULEVEL)95 5601 y(TYP_CKSUM_KEY)f(100)94 b(CHECKSUM,)46 b(DATASUM)95 5714 y(TYP_WCS_KEY)141 b(110)94 b(CTYPEn,)46 b(CUNITn,)g(CRVALn,)g(CRPIXn,)g(CROTAn,)f(CDELTn)p eop end %%Page: 72 78 TeXDict begin 72 77 bop 0 299 a Fi(72)1319 b Fg(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)1002 555 y Fe(CDj_is,)46 b(PVj_ms,)g(LONPOLEs,)f (LATPOLEs)1002 668 y(TCTYPn,)h(TCTYns,)g(TCUNIn,)g(TCUNns,)g(TCRVLn,)f (TCRVns,)h(TCRPXn,)1002 781 y(TCRPks,)g(TCDn_k,)g(TCn_ks,)g(TPVn_m,)g (TPn_ms,)f(TCDLTn,)h(TCROTn)1002 894 y(jCTYPn,)g(jCTYns,)g(jCUNIn,)g (jCUNns,)g(jCRVLn,)f(jCRVns,)h(iCRPXn,)1002 1007 y(iCRPns,)g(jiCDn,)94 b(jiCDns,)46 b(jPVn_m,)g(jPn_ms,)f(jCDLTn,)h(jCROTn)1002 1120 y(\(i,j,m,n)g(are)h(integers,)e(s)i(is)h(any)f(letter\))95 1233 y(TYP_REFSYS_KEY)d(120)j(EQUINOXs,)f(EPOCH,)g(MJD-OBSs,)f (RADECSYS,)g(RADESYSs)95 1346 y(TYP_COMM_KEY)140 b(130)47 b(COMMENT,)f(HISTORY,)f(\(blank)h(keyword\))95 1458 y(TYP_CONT_KEY)140 b(140)47 b(CONTINUE)95 1571 y(TYP_USER_KEY)140 b(150)47 b(all)g(other)g(keywords)430 1797 y(class)f(=)h(FTGKCL)f(\(char)h (*card\))0 2042 y Fh(14)f Fi(P)m(arse)f(the)g('TF)m(ORM')h(binary)e (table)i(column)e(format)h(string.)84 b(This)44 b(subroutine)g(parses)g (the)h(input)227 2155 y(TF)m(ORM)27 b(c)m(haracter)g(string)f(and)g (returns)f(the)h(in)m(teger)h(datat)m(yp)s(e)g(co)s(de,)h(the)e(rep)s (eat)g(coun)m(t)h(of)f(the)g(\014eld,)227 2268 y(and,)f(in)e(the)h (case)g(of)g(c)m(haracter)h(string)e(\014elds,)i(the)e(length)h(of)g (the)g(unit)f(string.)38 b(The)23 b(follo)m(wing)i(datat)m(yp)s(e)227 2381 y(co)s(des)e(are)h(returned)e(\(the)h(negativ)m(e)i(of)f(the)f(v) -5 b(alue)23 b(is)g(returned)f(if)h(the)g(column)g(con)m(tains)h(v)-5 b(ariable-length)227 2494 y(arra)m(ys\):)764 2739 y Fe(Datatype)761 b(DATACODE)46 b(value)764 2852 y(bit,)g(X)907 b(1)764 2965 y(byte,)46 b(B)811 b(11)764 3078 y(logical,)45 b(L)668 b(14)764 3191 y(ASCII)46 b(character,)f(A)286 b(16)764 3304 y(short)46 b(integer,)g(I)381 b(21)764 3417 y(integer,)45 b(J)668 b(41)764 3530 y(real,)46 b(E)811 b(42)764 3643 y(double)46 b(precision,)f(D)238 b(82)764 3756 y(complex)809 b(83)764 3868 y(double)46 b(complex)475 b(163)382 4094 y(FTBNFM\(tform,)44 b(>)j(datacode,repeat,width,stat)o(us\))0 4340 y Fh(15)f Fi(P)m(arse)38 b(the)f('TF)m(ORM')h(k)m(eyw)m(ord)g(v)-5 b(alue)37 b(that)h(de\014nes)e(the)h(column)g(format)h(in)e(an)h(ASCI)s (I)f(table.)62 b(This)227 4452 y(routine)31 b(parses)g(the)g(input)g (TF)m(ORM)g(c)m(haracter)i(string)e(and)f(returns)g(the)i(datat)m(yp)s (e)g(co)s(de,)f(the)h(width)227 4565 y(of)40 b(the)h(column,)h(and)e (\(if)g(it)g(is)h(a)f(\015oating)h(p)s(oin)m(t)f(column\))g(the)g(n)m (um)m(b)s(er)f(of)h(decimal)h(places)g(to)g(the)227 4678 y(righ)m(t)28 b(of)g(the)f(decimal)h(p)s(oin)m(t.)40 b(The)27 b(returned)f(datat)m(yp)s(e)i(co)s(des)f(are)h(the)g(same)f (as)h(for)f(the)g(binary)g(table,)227 4791 y(listed)41 b(ab)s(o)m(v)m(e,)j(with)c(the)g(follo)m(wing)i(additional)f(rules:)60 b(in)m(teger)42 b(columns)e(that)g(are)h(b)s(et)m(w)m(een)g(1)g(and)227 4904 y(4)36 b(c)m(haracters)i(wide)d(are)i(de\014ned)d(to)j(b)s(e)e (short)h(in)m(tegers)h(\(co)s(de)f(=)g(21\).)58 b(Wider)36 b(in)m(teger)h(columns)f(are)227 5017 y(de\014ned)j(to)i(b)s(e)e (regular)h(in)m(tegers)i(\(co)s(de)e(=)g(41\).)71 b(Similarly)-8 b(,)43 b(Fixed)d(decimal)h(p)s(oin)m(t)f(columns)g(\(with)227 5130 y(TF)m(ORM)30 b(=)g('Fw.d'\))g(are)g(de\014ned)f(to)h(b)s(e)g (single)g(precision)g(reals)g(\(co)s(de)h(=)e(42\))i(if)f(w)f(is)h(b)s (et)m(w)m(een)g(1)h(and)227 5243 y(7)i(c)m(haracters)h(wide,)f (inclusiv)m(e.)47 b(Wider)32 b('F')h(columns)f(will)h(return)e(a)i (double)f(precision)g(data)h(co)s(de)g(\(=)227 5356 y(82\).)54 b('Ew.d')34 b(format)g(columns)g(will)h(ha)m(v)m(e)g(dataco)s(de)g(=)f (42,)j(and)c('Dw.d')i(format)f(columns)g(will)h(ha)m(v)m(e)227 5469 y(dataco)s(de)d(=)e(82.)382 5714 y Fe(FTASFM\(tform,)44 b(>)j(datacode,width,decimals,st)o(atus)o(\))p eop end %%Page: 73 79 TeXDict begin 73 78 bop 0 299 a Fg(6.12.)73 b(GENERAL)30 b(UTILITY)g(SUBR)m(OUTINES)1979 b Fi(73)0 555 y Fh(16)46 b Fi(Calculate)32 b(the)f(starting)g(column)g(p)s(ositions)f(and)g (total)i(ASCI)s(I)d(table)j(width)d(based)i(on)f(the)h(input)e(arra)m (y)227 668 y(of)e(ASCI)s(I)e(table)i(TF)m(ORM)g(v)-5 b(alues.)40 b(The)26 b(SP)-8 b(A)m(CE)27 b(input)e(parameter)i (de\014nes)f(ho)m(w)h(man)m(y)f(blank)h(spaces)227 781 y(to)40 b(lea)m(v)m(e)i(b)s(et)m(w)m(een)e(eac)m(h)g(column)g(\(it)g (is)f(recommended)g(to)h(ha)m(v)m(e)h(one)e(space)h(b)s(et)m(w)m(een)g (columns)f(for)227 894 y(b)s(etter)31 b(h)m(uman)e(readabilit)m(y\).) 382 1153 y Fe(FTGABC\(tfields,tform,spa)o(ce,)41 b(>)48 b(rowlen,tbcol,status\))0 1413 y Fh(17)e Fi(P)m(arse)36 b(a)f(template)h(string)f(and)g(return)f(a)h(formatted)h(80-c)m (haracter)h(string)e(suitable)h(for)f(app)s(ending)e(to)227 1526 y(\(or)40 b(deleting)h(from\))e(a)h(FITS)f(header)h(\014le.)68 b(This)39 b(subroutine)f(is)i(useful)f(for)g(parsing)g(lines)h(from)f (an)227 1639 y(ASCI)s(I)34 b(template)j(\014le)f(and)e(reformatting)j (them)e(in)m(to)i(legal)g(FITS)d(header)i(records.)55 b(The)35 b(formatted)227 1752 y(string)c(ma)m(y)g(then)f(b)s(e)g (passed)g(to)i(the)e(FTPREC,)h(FTMCRD,)g(or)f(FTDKEY)h(subroutines)e (to)j(app)s(end)227 1865 y(or)f(mo)s(dify)e(a)i(FITS)f(header)g (record.)382 2124 y Fe(FTGTHD\(template,)43 b(>)48 b (card,hdtype,status\))0 2384 y Fi(The)23 b(input)h(TEMPLA)-8 b(TE)23 b(c)m(haracter)j(string)e(generally)h(should)e(con)m(tain)i(3)g (tok)m(ens:)38 b(\(1\))25 b(the)f(KEYNAME,)h(\(2\))0 2497 y(the)h(V)-10 b(ALUE,)26 b(and)f(\(3\))i(the)f(COMMENT)g(string.) 39 b(The)25 b(TEMPLA)-8 b(TE)26 b(string)g(m)m(ust)f(adhere)h(to)g(the) g(follo)m(wing)0 2610 y(format:)0 2869 y Fh(-)80 b Fi(The)24 b(KEYNAME)g(tok)m(en)h(m)m(ust)e(b)s(egin)h(in)f(columns)h(1-8)h(and)e (b)s(e)h(a)g(maxim)m(um)g(of)g(8)g(c)m(haracters)h(long.)39 b(If)24 b(the)227 2982 y(\014rst)32 b(8)h(c)m(haracters)h(of)e(the)h (template)h(line)e(are)h(blank)f(then)g(the)h(remainder)f(of)g(the)h (line)g(is)f(considered)227 3095 y(to)42 b(b)s(e)e(a)h(FITS)f(commen)m (t)h(\(with)g(a)g(blank)f(k)m(eyw)m(ord)h(name\).)72 b(A)41 b(legal)i(FITS)d(k)m(eyw)m(ord)h(name)f(ma)m(y)227 3208 y(only)35 b(con)m(tain)i(the)e(c)m(haracters)h(A-Z,)f(0-9,)j(and)c ('-')i(\(min)m(us)f(sign\))g(and)f(underscore.)54 b(This)34 b(subroutine)227 3321 y(will)42 b(automatically)i(con)m(v)m(ert)f(an)m (y)f(lo)m(w)m(ercase)i(c)m(haracters)e(to)h(upp)s(ercase)d(in)h(the)h (output)f(string.)73 b(If)227 3434 y(KEYNAME)33 b(=)f('COMMENT')h(or)g ('HISTOR)-8 b(Y')32 b(then)h(the)f(remainder)g(of)h(the)g(line)g(is)g (considered)f(to)227 3547 y(b)s(e)e(a)h(FITS)e(COMMENT)h(or)h(HISTOR)-8 b(Y)30 b(record,)g(resp)s(ectiv)m(ely)-8 b(.)0 3806 y Fh(-)80 b Fi(The)26 b(V)-10 b(ALUE)26 b(tok)m(en)h(m)m(ust)e(b)s(e)h (separated)g(from)f(the)i(KEYNAME)f(tok)m(en)h(b)m(y)f(one)g(or)g(more) g(spaces)g(and/or)227 3919 y(an)i('=')g(c)m(haracter.)41 b(The)27 b(datat)m(yp)s(e)i(of)f(the)g(V)-10 b(ALUE)27 b(tok)m(en)i(\(n)m(umeric,)g(logical,)i(or)d(c)m(haracter)h(string\))f (is)227 4032 y(automatically)35 b(determined)c(and)h(the)g(output)f (CARD)h(string)g(is)g(formatted)g(accordingly)-8 b(.)47 b(The)31 b(v)-5 b(alue)227 4145 y(tok)m(en)34 b(ma)m(y)f(b)s(e)f (forced)g(to)i(b)s(e)e(in)m(terpreted)g(as)h(a)g(string)g(\(e.g.)48 b(if)33 b(it)g(is)f(a)h(string)g(of)f(n)m(umeric)h(digits\))g(b)m(y)227 4258 y(enclosing)g(it)f(in)f(single)h(quotes.)45 b(If)31 b(the)h(v)-5 b(alue)32 b(tok)m(en)g(is)g(a)g(c)m(haracter)h(string)e (that)i(con)m(tains)f(1)g(or)g(more)227 4371 y(em)m(b)s(edded)39 b(blank)g(space)h(c)m(haracters)h(or)e(slash)h(\('/'\))h(c)m(haracters) g(then)e(the)g(en)m(tire)i(c)m(haracter)g(string)227 4484 y(m)m(ust)31 b(b)s(e)e(enclosed)i(in)f(single)h(quotes.)0 4743 y Fh(-)80 b Fi(The)28 b(COMMENT)g(tok)m(en)h(is)f(optional,)i(but) e(if)g(presen)m(t)g(m)m(ust)g(b)s(e)g(separated)g(from)g(the)h(V)-10 b(ALUE)28 b(tok)m(en)h(b)m(y)227 4856 y(a)i(blank)f(space)h(or)f(a)h ('/')g(c)m(haracter.)0 5116 y Fh(-)80 b Fi(One)32 b(exception)i(to)f (the)g(ab)s(o)m(v)m(e)h(rules)e(is)g(that)h(if)g(the)f(\014rst)g (non-blank)g(c)m(haracter)i(in)e(the)h(template)h(string)227 5229 y(is)h(a)g(min)m(us)f(sign)h(\('-'\))h(follo)m(w)m(ed)g(b)m(y)f(a) g(single)g(tok)m(en,)i(or)e(a)g(single)g(tok)m(en)h(follo)m(w)m(ed)g(b) m(y)f(an)f(equal)i(sign,)227 5341 y(then)29 b(it)g(is)g(in)m(terpreted) f(as)h(the)g(name)g(of)g(a)g(k)m(eyw)m(ord)g(whic)m(h)f(is)h(to)g(b)s (e)f(deleted)i(from)e(the)h(FITS)f(header.)0 5601 y Fh(-)80 b Fi(The)40 b(second)g(exception)h(is)f(that)h(if)f(the)g(template)h (string)f(starts)g(with)g(a)h(min)m(us)e(sign)h(and)f(is)h(follo)m(w)m (ed)227 5714 y(b)m(y)33 b(2)g(tok)m(ens)g(then)g(the)f(second)h(tok)m (en)h(is)e(in)m(terpreted)h(as)g(the)g(new)f(name)g(for)h(the)g(k)m (eyw)m(ord)g(sp)s(eci\014ed)p eop end %%Page: 74 80 TeXDict begin 74 79 bop 0 299 a Fi(74)1319 b Fg(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)227 555 y Fi(b)m(y)k(\014rst)e(tok)m(en.)52 b(In)33 b(this)g(case)i(the)e(old)h(k)m(eyw)m(ord)g(name)g(\(\014rst)f (tok)m(en\))i(is)e(returned)g(in)g(c)m(haracters)i(1-8)227 668 y(of)e(the)g(returned)e(CARD)i(string,)g(and)f(the)h(new)f(k)m(eyw) m(ord)h(name)g(\(the)g(second)f(tok)m(en\))i(is)f(returned)e(in)227 781 y(c)m(haracters)c(41-48)h(of)e(the)f(returned)g(CARD)g(string.)40 b(These)25 b(old)h(and)f(new)g(names)g(ma)m(y)h(then)f(b)s(e)g(passed) 227 894 y(to)31 b(the)g(FTMNAM)g(subroutine)f(whic)m(h)g(will)g(c)m (hange)i(the)e(k)m(eyw)m(ord)h(name.)0 1158 y(The)f(HDTYPE)g(output)g (parameter)h(indicates)g(ho)m(w)g(the)f(returned)g(CARD)g(string)g (should)g(b)s(e)g(in)m(terpreted:)382 1422 y Fe(hdtype)857 b(interpretation)382 1535 y(------)523 b(-------------------------)o (----)o(---)o(----)o(----)o(---)o(----)o(--)525 1648 y(-2)572 b(Modify)46 b(the)h(name)g(of)g(the)g(keyword)f(given)g(in)h (CARD\(1:8\))1193 1761 y(to)g(the)g(new)g(name)g(given)f(in)h (CARD\(41:48\))525 1986 y(-1)572 b(CARD\(1:8\))45 b(contains)h(the)h (name)g(of)g(a)g(keyword)f(to)h(be)g(deleted)1193 2099 y(from)g(the)g(FITS)f(header.)573 2325 y(0)572 b(append)46 b(the)h(CARD)g(string)f(to)h(the)g(FITS)g(header)f(if)h(the)1193 2438 y(keyword)f(does)h(not)g(already)e(exist,)h(otherwise)g(update) 1193 2551 y(the)h(value/comment)d(if)j(the)g(keyword)f(is)h(already)f (present)1193 2664 y(in)h(the)g(header.)573 2890 y(1)572 b(simply)46 b(append)g(this)h(keyword)f(to)h(the)g(FITS)g(header)f (\(CARD)1193 3003 y(is)h(either)f(a)i(HISTORY)e(or)h(COMMENT)f (keyword\).)573 3228 y(2)572 b(This)47 b(is)g(a)g(FITS)g(END)g(record;) f(it)h(should)f(not)h(be)g(written)1193 3341 y(to)g(the)g(FITS)g (header)f(because)g(FITSIO)g(automatically)1193 3454 y(appends)g(the)h(END)g(record)f(when)h(the)f(header)h(is)g(closed.)0 3718 y Fi(EXAMPLES:)30 b(The)g(follo)m(wing)i(lines)e(illustrate)i(v)-5 b(alid)31 b(input)e(template)j(strings:)286 3982 y Fe(INTVAL)46 b(7)i(This)f(is)g(an)g(integer)f(keyword)286 4095 y(RVAL)524 b(34.6)142 b(/)239 b(This)46 b(is)i(a)f(floating)f(point)g(keyword)286 4208 y(EVAL=-12.45E-03)92 b(This)46 b(is)i(a)f(floating)f(point)g (keyword)g(in)h(exponential)e(notation)286 4321 y(lval)i(F)g(This)g(is) g(a)h(boolean)e(keyword)859 4434 y(This)h(is)g(a)g(comment)f(keyword)g (with)h(a)g(blank)f(keyword)g(name)286 4547 y(SVAL1)h(=)g('Hello)f (world')142 b(/)95 b(this)47 b(is)g(a)g(string)f(keyword)286 4660 y(SVAL2)94 b('123.5')g(this)47 b(is)g(also)f(a)i(string)e(keyword) 286 4772 y(sval3)94 b(123+)h(/)g(this)47 b(is)g(also)f(a)i(string)e (keyword)g(with)g(the)h(value)g('123+)189 b(')286 4885 y(#)48 b(the)f(following)e(template)h(line)g(deletes)g(the)h(DATE)g (keyword)286 4998 y(-)h(DATE)286 5111 y(#)g(the)f(following)e(template) h(line)g(modifies)g(the)h(NAME)f(keyword)g(to)h(OBJECT)286 5224 y(-)h(NAME)e(OBJECT)0 5488 y Fh(18)g Fi(P)m(arse)35 b(the)g(input)f(string)h(con)m(taining)h(a)f(list)h(of)f(ro)m(ws)f(or)h (ro)m(w)g(ranges,)h(and)e(return)g(in)m(teger)i(arra)m(ys)f(con-)227 5601 y(taining)27 b(the)f(\014rst)f(and)g(last)i(ro)m(w)f(in)f(eac)m(h) i(range.)40 b(F)-8 b(or)26 b(example,)i(if)d(ro)m(wlist)i(=)e("3-5,)k (6,)e(8-9")h(then)d(it)i(will)227 5714 y(return)34 b(n)m(umranges)h(=)g (3,)h(rangemin)f(=)g(3,)i(6,)g(8)e(and)g(rangemax)g(=)g(5,)i(6,)g(9.)55 b(A)m(t)36 b(most,)h('maxranges')p eop end %%Page: 75 81 TeXDict begin 75 80 bop 0 299 a Fg(6.12.)73 b(GENERAL)30 b(UTILITY)g(SUBR)m(OUTINES)1979 b Fi(75)227 555 y(n)m(um)m(b)s(er)31 b(of)h(ranges)f(will)h(b)s(e)g(returned.)43 b('maxro)m(ws')32 b(is)g(the)g(maxim)m(um)g(n)m(um)m(b)s(er)e(of)i(ro)m(ws)g(in)f(the)h (table;)227 668 y(an)m(y)e(ro)m(ws)f(or)g(ranges)g(larger)h(than)f (this)g(will)g(b)s(e)g(ignored.)40 b(The)29 b(ro)m(ws)g(m)m(ust)g(b)s (e)f(sp)s(eci\014ed)h(in)f(increasing)227 781 y(order,)33 b(and)f(the)g(ranges)h(m)m(ust)f(not)g(o)m(v)m(erlap.)48 b(A)33 b(min)m(us)e(sign)i(ma)m(y)g(b)s(e)e(use)h(to)h(sp)s(ecify)f (all)h(the)g(ro)m(ws)f(to)227 894 y(the)h(upp)s(er)d(or)j(lo)m(w)m(er)h (b)s(ound,)d(so)i("50-")h(means)e(all)i(the)f(ro)m(ws)f(from)g(50)h(to) h(the)e(end)g(of)h(the)f(table,)j(and)227 1007 y("-")d(means)e(all)h (the)g(ro)m(ws)f(in)g(the)h(table,)g(from)f(1)h(-)g(maxro)m(ws.)191 1267 y Fe(FTRWRG\(rowlist,)44 b(maxrows,)h(maxranges,)g(>)525 1380 y(numranges,)g(rangemin,)g(rangemax,)h(status\))p eop end %%Page: 76 82 TeXDict begin 76 81 bop 0 299 a Fi(76)1319 b Fg(CHAPTER)29 b(6.)112 b(AD)m(V)-10 b(ANCED)32 b(INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)p eop end %%Page: 77 83 TeXDict begin 77 82 bop 0 1225 a Ff(Chapter)65 b(7)0 1687 y Fl(The)77 b(CFITSIO)f(Iterator)i(F)-19 b(unction)0 2180 y Fi(The)41 b(\014ts)p 325 2180 28 4 v 33 w(iterate)p 614 2180 V 34 w(data)i(function)e(in)h(CFITSIO)e(pro)m(vides)i(a)g (unique)e(metho)s(d)i(of)g(executing)h(an)e(arbitrary)0 2293 y(user-supplied)35 b(`w)m(ork')i(function)f(that)h(op)s(erates)g (on)g(ro)m(ws)f(of)h(data)g(in)f(FITS)g(tables)h(or)f(on)h(pixels)f(in) h(FITS)0 2406 y(images.)i(Rather)24 b(than)e(explicitly)j(reading)e (and)g(writing)g(the)g(FITS)g(images)h(or)f(columns)g(of)g(data,)i(one) f(instead)0 2518 y(calls)36 b(the)g(CFITSIO)d(iterator)k(routine,)g (passing)e(to)h(it)g(the)f(name)g(of)h(the)f(user's)g(w)m(ork)g (function)g(that)h(is)f(to)0 2631 y(b)s(e)30 b(executed)h(along)g(with) f(a)h(list)g(of)f(all)h(the)f(table)i(columns)e(or)g(image)h(arra)m(ys) g(that)g(are)f(to)h(b)s(e)f(passed)g(to)h(the)0 2744 y(w)m(ork)37 b(function.)61 b(The)37 b(CFITSIO)e(iterator)k(function)e (then)g(do)s(es)g(all)h(the)f(w)m(ork)g(of)h(allo)s(cating)h(memory)e (for)0 2857 y(the)28 b(arra)m(ys,)h(reading)f(the)g(input)e(data)j (from)e(the)h(FITS)f(\014le,)h(passing)g(them)g(to)g(the)g(w)m(ork)g (function,)g(and)f(then)0 2970 y(writing)36 b(an)m(y)h(output)f(data)h (bac)m(k)h(to)f(the)f(FITS)g(\014le)g(after)h(the)g(w)m(ork)g(function) f(exits.)59 b(Because)38 b(it)f(is)g(often)0 3083 y(more)g(e\016cien)m (t)i(to)f(pro)s(cess)f(only)g(a)h(subset)f(of)g(the)g(total)i(table)g (ro)m(ws)e(at)h(one)f(time,)j(the)e(iterator)g(function)0 3196 y(can)31 b(determine)f(the)h(optim)m(um)f(amoun)m(t)h(of)f(data)h (to)g(pass)f(in)g(eac)m(h)i(iteration)f(and)f(rep)s(eatedly)h(call)g (the)g(w)m(ork)0 3309 y(function)f(un)m(til)h(the)f(en)m(tire)i(table)f (b)s(een)e(pro)s(cessed.)0 3469 y(F)-8 b(or)37 b(man)m(y)f (applications)h(this)e(single)i(CFITSIO)d(iterator)k(function)d(can)h (e\013ectiv)m(ely)j(replace)e(all)g(the)f(other)0 3582 y(CFITSIO)g(routines)i(for)f(reading)h(or)f(writing)h(data)g(in)f(FITS) g(images)i(or)e(tables.)64 b(Using)37 b(the)h(iterator)h(has)0 3695 y(sev)m(eral)32 b(imp)s(ortan)m(t)e(adv)-5 b(an)m(tages)32 b(o)m(v)m(er)g(the)f(traditional)g(metho)s(d)f(of)h(reading)f(and)g (writing)g(FITS)g(data)h(\014les:)136 3961 y Fc(\017)46 b Fi(It)33 b(cleanly)h(separates)g(the)f(data)h(I/O)f(from)f(the)h (routine)g(that)h(op)s(erates)f(on)g(the)g(data.)49 b(This)32 b(leads)h(to)227 4074 y(a)e(more)g(mo)s(dular)e(and)h(`ob)5 b(ject)31 b(orien)m(ted')h(programming)e(st)m(yle.)136 4268 y Fc(\017)46 b Fi(It)27 b(simpli\014es)f(the)h(application)h (program)f(b)m(y)f(eliminating)i(the)f(need)g(to)g(allo)s(cate)i (memory)e(for)f(the)h(data)227 4381 y(arra)m(ys)e(and)f(eliminates)i (most)e(of)h(the)f(calls)i(to)f(the)g(CFITSIO)d(routines)j(that)g (explicitly)h(read)e(and)g(write)227 4494 y(the)31 b(data.)136 4689 y Fc(\017)46 b Fi(It)32 b(ensures)e(that)i(the)g(data)g(are)g(pro) s(cessed)f(as)h(e\016cien)m(tly)h(as)e(p)s(ossible.)44 b(This)31 b(is)g(esp)s(ecially)i(imp)s(ortan)m(t)227 4801 y(when)44 b(pro)s(cessing)g(tabular)h(data)h(since)f(the)g (iterator)h(function)e(will)h(calculate)i(the)e(most)g(e\016cien)m(t) 227 4914 y(n)m(um)m(b)s(er)36 b(of)i(ro)m(ws)g(in)f(the)h(table)g(to)g (b)s(e)f(passed)g(at)i(one)e(time)i(to)f(the)g(user's)e(w)m(ork)i (function)f(on)h(eac)m(h)227 5027 y(iteration.)136 5222 y Fc(\017)46 b Fi(Mak)m(es)39 b(it)e(p)s(ossible)g(for)g(larger)h(pro)5 b(jects)37 b(to)h(dev)m(elop)g(a)g(library)e(of)i(w)m(ork)f(functions)f (that)i(all)g(ha)m(v)m(e)h(a)227 5335 y(uniform)29 b(calling)j (sequence)f(and)f(are)h(all)g(indep)s(enden)m(t)e(of)i(the)f(details)i (of)e(the)h(FITS)e(\014le)i(format.)0 5601 y(There)f(are)h(basically)h (2)g(steps)e(in)h(using)f(the)h(CFITSIO)e(iterator)j(function.)42 b(The)30 b(\014rst)g(step)h(is)g(to)g(design)g(the)0 5714 y(w)m(ork)26 b(function)f(itself)h(whic)m(h)f(m)m(ust)h(ha)m(v)m (e)g(a)g(prescrib)s(ed)e(set)i(of)g(input)f(parameters.)39 b(One)25 b(of)h(these)g(parameters)1905 5942 y(77)p eop end %%Page: 78 84 TeXDict begin 78 83 bop 0 299 a Fi(78)1455 b Fg(CHAPTER)30 b(7.)112 b(THE)30 b(CFITSIO)e(ITERA)-8 b(TOR)30 b(FUNCTION)0 555 y Fi(is)f(a)g(structure)g(con)m(taining)i(p)s(oin)m(ters)d(to)i (the)f(arra)m(ys)h(of)f(data;)h(the)f(w)m(ork)h(function)e(can)i(p)s (erform)d(an)m(y)i(desired)0 668 y(op)s(erations)k(on)h(these)f(arra)m (ys)h(and)e(do)s(es)h(not)g(need)g(to)h(w)m(orry)f(ab)s(out)g(ho)m(w)g (the)h(input)e(data)i(w)m(ere)f(read)g(from)0 781 y(the)e(\014le)f(or)g (ho)m(w)h(the)f(output)g(data)h(get)h(written)e(bac)m(k)h(to)h(the)e (\014le.)0 941 y(The)24 b(second)h(step)g(is)f(to)i(design)e(the)h (driv)m(er)g(routine)f(that)i(op)s(ens)e(all)h(the)g(necessary)g(FITS)f (\014les)h(and)f(initializes)0 1054 y(the)41 b(input)g(parameters)g(to) h(the)g(iterator)g(function.)73 b(The)41 b(driv)m(er)g(program)g(calls) h(the)g(CFITSIO)e(iterator)0 1167 y(function)30 b(whic)m(h)g(then)g (reads)g(the)h(data)g(and)f(passes)g(it)h(to)g(the)g(user's)e(w)m(ork)i (function.)0 1327 y(F)-8 b(urther)41 b(details)i(on)f(using)f(the)h (iterator)h(function)f(can)g(b)s(e)f(found)f(in)i(the)g(companion)g (CFITSIO)e(User's)0 1440 y(Guide,)31 b(and)e(in)h(the)h(iter)p 874 1440 28 4 v 33 w(a.f,)g(iter)p 1197 1440 V 34 w(b.f)f(and)f(iter)p 1677 1440 V 34 w(c.f)h(example)h(programs.)p eop end %%Page: 79 85 TeXDict begin 79 84 bop 0 1225 a Ff(Chapter)65 b(8)0 1687 y Fl(Extended)77 b(File)g(Name)g(Syn)-6 b(tax)0 2216 y Fd(8.1)135 b(Ov)l(erview)0 2466 y Fi(CFITSIO)30 b(supp)s(orts)f(an)j(extended)f(syn)m(tax)h(when)f(sp)s(ecifying)g(the) h(name)f(of)h(the)g(data)g(\014le)f(to)h(b)s(e)f(op)s(ened)g(or)0 2579 y(created)g(that)g(includes)f(the)h(follo)m(wing)h(features:)136 2813 y Fc(\017)46 b Fi(CFITSIO)40 b(can)i(read)f(IRAF)h(format)g (images)g(whic)m(h)f(ha)m(v)m(e)i(header)e(\014le)h(names)f(that)h(end) f(with)g(the)227 2926 y('.imh')d(extension,)i(as)e(w)m(ell)g(as)g (reading)f(and)g(writing)g(FITS)g(\014les,)i(This)e(feature)h(is)f (implemen)m(ted)h(in)227 3039 y(CFITSIO)29 b(b)m(y)i(\014rst)e(con)m(v) m(erting)k(the)d(IRAF)h(image)h(in)m(to)f(a)g(temp)s(orary)f(FITS)g (format)h(\014le)f(in)g(memory)-8 b(,)227 3152 y(then)35 b(op)s(ening)f(the)h(FITS)f(\014le.)54 b(An)m(y)35 b(of)g(the)g(usual)f (CFITSIO)g(routines)g(then)h(ma)m(y)g(b)s(e)f(used)g(to)i(read)227 3265 y(the)31 b(image)g(header)f(or)h(data.)41 b(Similarly)-8 b(,)31 b(ra)m(w)f(binary)g(data)h(arra)m(ys)f(can)h(b)s(e)f(read)g(b)m (y)g(con)m(v)m(erting)i(them)227 3378 y(on)f(the)f(\015y)g(in)m(to)h (virtual)g(FITS)f(images.)136 3557 y Fc(\017)46 b Fi(FITS)37 b(\014les)g(on)g(the)g(In)m(ternet)h(can)f(b)s(e)g(read)g(\(and)g (sometimes)h(written\))f(using)g(the)g(FTP)-8 b(,)38 b(HTTP)-8 b(,)37 b(or)227 3670 y(R)m(OOT)30 b(proto)s(cols.)136 3849 y Fc(\017)46 b Fi(FITS)30 b(\014les)g(can)h(b)s(e)f(pip)s(ed)f(b)s (et)m(w)m(een)i(tasks)f(on)h(the)f(stdin)g(and)g(stdout)g(streams.)136 4028 y Fc(\017)46 b Fi(FITS)20 b(\014les)h(can)g(b)s(e)f(read)g(and)g (written)h(in)f(shared)g(memory)-8 b(.)38 b(This)20 b(can)h(p)s(oten)m (tially)h(ac)m(hiev)m(e)h(m)m(uc)m(h)e(b)s(etter)227 4141 y(data)26 b(I/O)e(p)s(erformance)g(compared)h(to)h(reading)f(and)f (writing)g(the)h(same)h(FITS)e(\014les)g(on)h(magnetic)h(disk.)136 4320 y Fc(\017)46 b Fi(Compressed)30 b(FITS)f(\014les)i(in)f(gzip)h(or) f(Unix)g(COMPRESS)f(format)h(can)h(b)s(e)f(directly)h(read.)136 4499 y Fc(\017)46 b Fi(Output)28 b(FITS)h(\014les)g(can)g(b)s(e)g (written)g(directly)h(in)e(compressed)h(gzip)h(format,)g(th)m(us)e(sa)m (ving)i(disk)f(space.)136 4678 y Fc(\017)46 b Fi(FITS)26 b(table)h(columns)f(can)h(b)s(e)f(created,)i(mo)s(di\014ed,)f(or)f (deleted)h('on-the-\015y')g(as)g(the)g(table)g(is)f(op)s(ened)g(b)m(y) 227 4791 y(CFITSIO.)32 b(This)h(creates)i(a)e(virtual)h(FITS)f(\014le)g (con)m(taining)i(the)f(mo)s(di\014cations)f(that)h(is)g(then)f(op)s (ened)227 4904 y(b)m(y)e(the)f(application)i(program.)136 5083 y Fc(\017)46 b Fi(T)-8 b(able)29 b(ro)m(ws)e(ma)m(y)i(b)s(e)e (selected,)j(or)e(\014ltered)g(out,)g(on)g(the)g(\015y)f(when)g(the)h (table)h(is)f(op)s(ened)f(b)m(y)g(CFITSIO,)227 5196 y(based)f(on)h(an)f (arbitrary)h(user-sp)s(eci\014ed)e(expression.)39 b(Only)26 b(ro)m(ws)h(for)f(whic)m(h)g(the)h(expression)f(ev)-5 b(aluates)227 5309 y(to)31 b('TR)m(UE')g(are)g(retained)g(in)f(the)g (cop)m(y)i(of)e(the)h(table)g(that)g(is)f(op)s(ened)g(b)m(y)g(the)h (application)g(program.)136 5488 y Fc(\017)46 b Fi(Histogram)28 b(images)g(ma)m(y)f(b)s(e)f(created)h(on)f(the)h(\015y)f(b)m(y)g (binning)g(the)g(v)-5 b(alues)27 b(in)f(table)i(columns,)f(resulting) 227 5601 y(in)36 b(a)g(virtual)h(N-dimensional)f(FITS)g(image.)59 b(The)35 b(application)i(program)f(then)g(only)g(sees)g(the)h(FITS)227 5714 y(image)32 b(\(in)e(the)h(primary)e(arra)m(y\))j(instead)e(of)h (the)f(original)i(FITS)d(table.)1905 5942 y(79)p eop end %%Page: 80 86 TeXDict begin 80 85 bop 0 299 a Fi(80)1618 b Fg(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fi(The)43 b(latter)i(3)f(features)g(in)f(particular)h(add)f(v)m (ery)h(p)s(o)m(w)m(erful)f(data)h(pro)s(cessing)f(capabilities)j (directly)e(in)m(to)0 668 y(CFITSIO,)29 b(and)g(hence)h(in)m(to)h(ev)m (ery)f(task)h(that)f(uses)g(CFITSIO)e(to)j(read)f(or)g(write)g(FITS)f (\014les.)40 b(F)-8 b(or)31 b(example,)0 781 y(these)d(features)f (transform)f(a)i(v)m(ery)f(simple)g(program)g(that)h(just)f(copies)h (an)f(input)f(FITS)g(\014le)h(to)h(a)g(new)e(output)0 894 y(\014le)36 b(\(lik)m(e)h(the)f(`\014tscop)m(y')h(program)f(that)g (is)g(distributed)f(with)g(CFITSIO\))g(in)m(to)i(a)f(m)m(ultipurp)s (ose)f(FITS)g(\014le)0 1007 y(pro)s(cessing)24 b(to)s(ol.)40 b(By)25 b(app)s(ending)f(fairly)g(simple)h(quali\014ers)g(on)m(to)g (the)g(name)g(of)g(the)g(input)f(FITS)g(\014le,)i(the)f(user)0 1120 y(can)37 b(p)s(erform)f(quite)i(complex)g(table)g(editing)g(op)s (erations)f(\(e.g.,)k(create)e(new)d(columns,)j(or)e(\014lter)h(out)f (ro)m(ws)0 1233 y(in)g(a)g(table\))h(or)f(create)h(FITS)f(images)h(b)m (y)f(binning)e(or)i(histogramming)h(the)f(v)-5 b(alues)37 b(in)g(table)h(columns.)60 b(In)0 1346 y(addition,)33 b(these)g(functions)e(ha)m(v)m(e)j(b)s(een)d(co)s(ded)h(using)f(new)h (state-of-the)i(art)f(algorithms)g(that)g(are,)g(in)f(some)0 1458 y(cases,)g(10)f(-)f(100)i(times)f(faster)g(than)f(previous)g (widely)g(used)g(implemen)m(tations.)0 1619 y(Before)k(describing)f (the)h(complete)h(syn)m(tax)f(for)f(the)h(extended)f(FITS)g(\014le)g (names)g(in)g(the)h(next)g(section,)h(here)0 1732 y(are)c(a)g(few)f (examples)h(of)f(FITS)g(\014le)g(names)h(that)f(giv)m(e)i(a)f(quic)m(k) g(o)m(v)m(erview)h(of)f(the)f(allo)m(w)m(ed)i(syn)m(tax:)136 1960 y Fc(\017)46 b Fe('myfile.fits')p Fi(:)37 b(the)31 b(simplest)f(case)i(of)e(a)h(FITS)f(\014le)g(on)h(disk)e(in)i(the)f (curren)m(t)g(directory)-8 b(.)136 2137 y Fc(\017)46 b Fe('myfile.imh')p Fi(:)37 b(op)s(ens)28 b(an)h(IRAF)g(format)g(image) i(\014le)e(and)f(con)m(v)m(erts)i(it)g(on)f(the)g(\015y)f(in)m(to)i(a)f (temp)s(orary)227 2250 y(FITS)h(format)h(image)g(in)f(memory)h(whic)m (h)f(can)g(then)g(b)s(e)g(read)g(with)g(an)m(y)h(other)g(CFITSIO)e (routine.)136 2427 y Fc(\017)46 b Fe(rawfile.dat[i512,512])p Fi(:)35 b(op)s(ens)30 b(a)g(ra)m(w)h(binary)e(data)i(arra)m(y)g(\(a)g (512)g(x)f(512)i(short)e(in)m(teger)h(arra)m(y)g(in)227 2540 y(this)i(case\))i(and)d(con)m(v)m(erts)j(it)e(on)g(the)g(\015y)g (in)m(to)h(a)f(temp)s(orary)g(FITS)f(format)h(image)i(in)d(memory)h (whic)m(h)227 2652 y(can)e(then)f(b)s(e)g(read)g(with)g(an)m(y)h(other) f(CFITSIO)f(routine.)136 2830 y Fc(\017)46 b Fe(myfile.fits.gz)p Fi(:)d(if)33 b(this)g(is)g(the)g(name)g(of)h(a)f(new)g(output)g (\014le,)h(the)f('.gz')i(su\016x)d(will)h(cause)h(it)g(to)g(b)s(e)227 2942 y(compressed)c(in)g(gzip)h(format)g(when)e(it)i(is)g(written)f(to) h(disk.)136 3120 y Fc(\017)46 b Fe('myfile.fits.gz[events,)c(2]')p Fi(:)59 b(op)s(ens)40 b(and)f(uncompresses)g(the)i(gzipp)s(ed)e(\014le) i(m)m(y\014le.\014ts)f(then)227 3232 y(mo)m(v)m(es)34 b(to)f(the)f(extension)h(whic)m(h)f(has)f(the)i(k)m(eyw)m(ords)f (EXTNAME)g(=)g('EVENTS')g(and)g(EXTVER)f(=)227 3345 y(2.)136 3522 y Fc(\017)46 b Fe('-')p Fi(:)40 b(a)31 b(dash)f(\(min)m(us)g (sign\))h(signi\014es)f(that)h(the)g(input)f(\014le)g(is)h(to)g(b)s(e)f (read)g(from)g(the)h(stdin)f(\014le)g(stream,)227 3635 y(or)h(that)g(the)f(output)g(\014le)h(is)f(to)h(b)s(e)f(written)g(to)h (the)g(stdout)f(stream.)136 3812 y Fc(\017)46 b Fe ('ftp://legacy.gsfc.nasa.g)o(ov/t)o(est/)o(vel)o(a.fi)o(ts')p Fi(:)33 b(FITS)28 b(\014les)g(in)g(an)m(y)g(ftp)g(arc)m(hiv)m(e)i(site) f(on)f(the)227 3925 y(In)m(ternet)j(ma)m(y)g(b)s(e)f(directly)h(op)s (ened)e(with)h(read-only)h(access.)136 4102 y Fc(\017)46 b Fe('http://legacy.gsfc.nasa.)o(gov/)o(soft)o(war)o(e/te)o(st.f)o(its) o(')p Fi(:)d(an)m(y)34 b(v)-5 b(alid)35 b(URL)f(to)h(a)f(FITS)g(\014le) g(on)227 4215 y(the)d(W)-8 b(eb)31 b(ma)m(y)g(b)s(e)f(op)s(ened)f(with) h(read-only)h(access.)136 4392 y Fc(\017)46 b Fe ('root://legacy.gsfc.nasa.)o(gov/)o(test)o(/ve)o(la.f)o(its')o Fi(:)32 b(similar)24 b(to)g(ftp)f(access)i(except)g(that)f(it)g(pro-) 227 4505 y(vides)30 b(write)h(as)f(w)m(ell)h(as)g(read)f(access)h(to)g (the)f(\014les)h(across)f(the)h(net)m(w)m(ork.)41 b(This)29 b(uses)h(the)h(ro)s(ot)f(proto)s(col)227 4618 y(dev)m(elop)s(ed)h(at)g (CERN.)136 4795 y Fc(\017)46 b Fe('shmem://h2[events]')p Fi(:)35 b(op)s(ens)30 b(the)g(FITS)f(\014le)i(in)f(a)g(shared)f(memory) i(segmen)m(t)g(and)e(mo)m(v)m(es)j(to)f(the)227 4908 y(EVENTS)f(extension.)136 5085 y Fc(\017)46 b Fe('mem://')p Fi(:)52 b(creates)39 b(a)e(scratc)m(h)i(output)d(\014le)i(in)e(core)i (computer)f(memory)-8 b(.)62 b(The)37 b(resulting)g('\014le')h(will)227 5198 y(disapp)s(ear)25 b(when)f(the)i(program)f(exits,)i(so)f(this)f (is)h(mainly)f(useful)g(for)g(testing)i(purp)s(oses)c(when)i(one)g(do)s (es)227 5311 y(not)31 b(w)m(an)m(t)g(a)g(p)s(ermanen)m(t)f(cop)m(y)h (of)f(the)h(output)f(\014le.)136 5488 y Fc(\017)46 b Fe('myfile.fits[3;)e(Images\(10\)]')p Fi(:)49 b(op)s(ens)35 b(a)i(cop)m(y)g(of)f(the)g(image)i(con)m(tained)f(in)f(the)h(10th)f(ro) m(w)h(of)227 5601 y(the)26 b('Images')i(column)d(in)h(the)g(binary)g (table)g(in)g(the)g(3th)h(extension)f(of)g(the)h(FITS)e(\014le.)39 b(The)26 b(application)227 5714 y(just)k(sees)h(this)f(single)h(image)h (as)e(the)h(primary)e(arra)m(y)-8 b(.)p eop end %%Page: 81 87 TeXDict begin 81 86 bop 0 299 a Fg(8.1.)72 b(O)m(VER)-10 b(VIEW)3086 b Fi(81)136 555 y Fc(\017)46 b Fe('myfile.fits[1:512:2,)c (1:512:2]')p Fi(:)49 b(op)s(ens)35 b(a)h(section)h(of)e(the)h(input)f (image)i(ranging)f(from)f(the)227 668 y(1st)26 b(to)g(the)f(512th)h (pixel)g(in)e(X)i(and)e(Y,)i(and)e(selects)j(ev)m(ery)e(second)h(pixel) f(in)g(b)s(oth)f(dimensions,)i(resulting)227 781 y(in)k(a)h(256)h(x)e (256)i(pixel)e(image)i(in)e(this)g(case.)136 981 y Fc(\017)46 b Fe('myfile.fits[EVENTS][col)41 b(Rad)47 b(=)h(sqrt\(X**2)d(+)j (Y**2\)]')p Fi(:)38 b(creates)30 b(and)f(op)s(ens)f(a)h(temp)s(orary) 227 1094 y(\014le)f(on)f(the)g(\015y)g(\(in)g(memory)g(or)g(on)h (disk\))f(that)g(is)h(iden)m(tical)h(to)f(m)m(y\014le.\014ts)f(except)h (that)g(it)g(will)g(con)m(tain)227 1207 y(a)41 b(new)f(column)g(in)h (the)f(EVENTS)g(extension)h(called)h('Rad')f(whose)f(v)-5 b(alue)41 b(is)f(computed)h(using)f(the)227 1320 y(indicated)31 b(expression)f(whic)m(h)g(is)h(a)g(function)f(of)g(the)h(v)-5 b(alues)30 b(in)h(the)f(X)h(and)e(Y)i(columns.)136 1520 y Fc(\017)46 b Fe('myfile.fits[EVENTS][PHA)41 b(>)48 b(5]')p Fi(:)37 b(creates)27 b(and)e(op)s(ens)g(a)h(temp)s(orary)f (FITS)g(\014les)g(that)h(is)g(iden)m(ti-)227 1633 y(cal)k(to)g('m)m (y\014le.\014ts')f(except)h(that)f(the)g(EVENTS)f(table)i(will)f(only)g (con)m(tain)h(the)f(ro)m(ws)g(that)h(ha)m(v)m(e)g(v)-5 b(alues)227 1746 y(of)28 b(the)g(PHA)f(column)g(greater)i(than)e(5.)40 b(In)27 b(general,)i(an)m(y)f(arbitrary)f(b)s(o)s(olean)h(expression)f (using)g(a)h(C)f(or)227 1859 y(F)-8 b(ortran-lik)m(e)31 b(syn)m(tax,)e(whic)m(h)f(ma)m(y)h(com)m(bine)g(AND)g(and)f(OR)f(op)s (erators,)i(ma)m(y)g(b)s(e)f(used)f(to)i(select)h(ro)m(ws)227 1972 y(from)g(a)h(table.)136 2172 y Fc(\017)46 b Fe ('myfile.fits[EVENTS][bin)41 b(\(X,Y\)=1,2048,4]')p Fi(:)46 b(creates)37 b(a)e(temp)s(orary)g(FITS)f(primary)g(arra)m(y)227 2285 y(image)c(whic)m(h)f(is)g(computed)f(on)h(the)g(\015y)f(b)m(y)g (binning)g(\(i.e,)j(computing)d(the)h(2-dimensional)h(histogram\))227 2398 y(of)k(the)f(v)-5 b(alues)34 b(in)f(the)h(X)g(and)e(Y)i(columns)f (of)h(the)f(EVENTS)g(extension.)50 b(In)33 b(this)g(case)i(the)e(X)h (and)f(Y)227 2511 y(co)s(ordinates)h(range)g(from)f(1)h(to)g(2048)h (and)e(the)h(image)g(pixel)g(size)g(is)g(4)f(units)g(in)g(b)s(oth)g (dimensions,)h(so)227 2624 y(the)d(resulting)f(image)i(is)e(512)i(x)e (512)i(pixels)f(in)f(size.)136 2824 y Fc(\017)46 b Fi(The)31 b(\014nal)g(example)i(com)m(bines)f(man)m(y)f(of)h(these)g(feature)g (in)m(to)g(one)g(complex)g(expression)f(\(it)i(is)e(brok)m(en)227 2937 y(in)m(to)h(sev)m(eral)f(lines)g(for)f(clarit)m(y\):)323 3206 y Fe('ftp://legacy.gsfc.nasa)o(.gov)o(/dat)o(a/s)o(ampl)o(e.fi)o (ts.)o(gz[E)o(VENT)o(S])370 3319 y([col)47 b(phacorr)f(=)h(pha)g(*)h (1.1)f(-)g(0.3][phacorr)e(>=)i(5.0)g(&&)g(phacorr)f(<=)h(14.0])370 3432 y([bin)g(\(X,Y\)=32]')227 3701 y Fi(In)37 b(this)h(case,)j (CFITSIO)36 b(\(1\))j(copies)g(and)e(uncompresses)g(the)h(FITS)f (\014le)h(from)f(the)h(ftp)f(site)i(on)f(the)227 3814 y(legacy)g(mac)m(hine,)h(\(2\))e(mo)m(v)m(es)g(to)g(the)g('EVENTS')f (extension,)i(\(3\))f(calculates)i(a)d(new)g(column)g(called)227 3927 y('phacorr',)30 b(\(4\))f(selects)h(the)f(ro)m(ws)g(in)f(the)h (table)h(that)f(ha)m(v)m(e)h(phacorr)e(in)g(the)h(range)g(5)g(to)h(14,) g(and)e(\014nally)227 4040 y(\(5\))35 b(bins)d(the)h(remaining)g(ro)m (ws)g(on)h(the)f(X)g(and)g(Y)g(column)g(co)s(ordinates,)i(using)d(a)i (pixel)f(size)h(=)f(32)h(to)227 4153 y(create)d(a)f(2D)g(image.)42 b(All)30 b(this)f(pro)s(cessing)g(is)h(completely)h(transparen)m(t)e (to)i(the)e(application)i(program,)227 4266 y(whic)m(h)f(simply)g(sees) h(the)g(\014nal)f(2-D)h(image)h(in)e(the)g(primary)g(arra)m(y)h(of)f (the)h(op)s(ened)f(\014le.)0 4538 y(The)c(full)h(extended)g(CFITSIO)e (FITS)h(\014le)h(name)g(can)g(con)m(tain)h(sev)m(eral)g(di\013eren)m(t) g(comp)s(onen)m(ts)f(dep)s(ending)e(on)0 4651 y(the)31 b(con)m(text.)42 b(These)30 b(comp)s(onen)m(ts)h(are)g(describ)s(ed)e (in)h(the)g(follo)m(wing)i(sections:)0 4924 y Fe(When)47 b(creating)e(a)j(new)f(file:)143 5036 y(filetype://BaseFilename\(t)o (empl)o(ate)o(Name)o(\))0 5262 y(When)g(opening)e(an)j(existing)d (primary)h(array)g(or)i(image)e(HDU:)143 5375 y (filetype://BaseFilename\(o)o(utNa)o(me\))o([HDU)o(loca)o(tio)o(n][I)o (mage)o(Sec)o(tion)o(])0 5601 y(When)h(opening)e(an)j(existing)d(table) i(HDU:)143 5714 y(filetype://BaseFilename\(o)o(utNa)o(me\))o([HDU)o (loca)o(tio)o(n][c)o(olFi)o(lte)o(r][r)o(owFi)o(lte)o(r][b)o(inSp)o (ec])p eop end %%Page: 82 88 TeXDict begin 82 87 bop 0 299 a Fi(82)1618 b Fg(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fi(The)41 b(\014let)m(yp)s(e,)k(BaseFilename,)i(outName,)e(HDUlo) s(cation,)i(and)41 b(ImageSection)i(comp)s(onen)m(ts,)i(if)d(presen)m (t,)0 668 y(m)m(ust)30 b(b)s(e)g(giv)m(en)i(in)e(that)h(order,)g(but)f (the)g(colFilter,)j(ro)m(wFilter,)g(and)c(binSp)s(ec)h(sp)s(eci\014ers) f(ma)m(y)j(follo)m(w)f(in)g(an)m(y)0 781 y(order.)39 b(Regardless)29 b(of)g(the)f(order,)g(ho)m(w)m(ev)m(er,)i(the)f (colFilter)h(sp)s(eci\014er,)e(if)g(presen)m(t,)h(will)g(b)s(e)e(pro)s (cessed)h(\014rst)f(b)m(y)0 894 y(CFITSIO,)i(follo)m(w)m(ed)j(b)m(y)e (the)h(ro)m(wFilter)h(sp)s(eci\014er,)e(and)f(\014nally)i(b)m(y)f(the)g (binSp)s(ec)f(sp)s(eci\014er.)0 1253 y Fd(8.2)135 b(Filet)l(yp)t(e)0 1508 y Fi(The)37 b(t)m(yp)s(e)g(of)g(\014le)g(determines)g(the)g (medium)f(on)h(whic)m(h)g(the)g(\014le)g(is)h(lo)s(cated)g(\(e.g.,)i (disk)d(or)g(net)m(w)m(ork\))h(and,)0 1621 y(hence,)f(whic)m(h)e(in)m (ternal)h(device)g(driv)m(er)f(is)g(used)f(b)m(y)h(CFITSIO)f(to)i(read) f(and/or)g(write)g(the)g(\014le.)56 b(Curren)m(tly)0 1734 y(supp)s(orted)29 b(t)m(yp)s(es)h(are)382 2015 y Fe(file://)93 b(-)48 b(file)e(on)i(local)e(magnetic)g(disk)g (\(default\))382 2128 y(ftp://)141 b(-)48 b(a)f(readonly)f(file)g (accessed)g(with)h(the)g(anonymous)e(FTP)i(protocol.)907 2241 y(It)g(also)g(supports)93 b(ftp://username:password@)o(host)o(nam) o(e/..)o(.)907 2354 y(for)47 b(accessing)e(password-protected)e(ftp)k (sites.)382 2467 y(http://)93 b(-)48 b(a)f(readonly)f(file)g(accessed)g (with)h(the)g(HTTP)f(protocol.)93 b(It)907 2579 y(supports)45 b(username:password)e(just)k(like)g(the)g(ftp)g(driver.)907 2692 y(Proxy)f(HTTP)h(servers)f(are)h(supported)e(using)h(the)h (http_proxy)907 2805 y(environment)e(variable)g(\(see)i(following)e (note\).)286 2918 y(stream://)93 b(-)48 b(special)e(driver)g(to)h(read) g(an)g(input)f(FITS)h(file)f(from)h(the)g(stdin)907 3031 y(stream,)f(and/or)g(write)g(an)h(output)f(FITS)h(file)g(to)g(the)g (stdout)143 3144 y(stream.)94 b(This)46 b(driver)g(is)i(fragile)d(and)i (has)g(limited)143 3257 y(functionality)d(\(see)j(the)g(following)e (note\).)286 3370 y(gsiftp://)93 b(-)48 b(access)e(files)g(on)h(a)h (computational)c(grid)j(using)f(the)h(gridftp)907 3483 y(protocol)e(in)j(the)e(Globus)h(toolkit)e(\(see)i(following)e(note\).) 382 3596 y(root://)93 b(-)48 b(uses)e(the)h(CERN)g(root)g(protocol)e (for)i(writing)f(as)h(well)g(as)907 3709 y(reading)f(files)g(over)h (the)g(network.)382 3821 y(shmem://)e(-)j(opens)e(or)h(creates)f(a)i (file)e(which)h(persists)e(in)i(the)g(computer's)907 3934 y(shared)f(memory.)382 4047 y(mem://)141 b(-)48 b(opens)e(a)i(temporary)d(file)i(in)g(core)f(memory.)94 b(The)47 b(file)907 4160 y(disappears)e(when)h(the)h(program)f(exits)h (so)g(this)f(is)i(mainly)907 4273 y(useful)e(for)h(test)f(purposes)g (when)h(a)g(permanent)e(output)h(file)907 4386 y(is)h(not)g(desired.)0 4667 y Fi(If)35 b(the)h(\014let)m(yp)s(e)g(is)f(not)h(sp)s(eci\014ed,)h (then)e(t)m(yp)s(e)h(\014le://)h(is)e(assumed.)56 b(The)35 b(double)g(slashes)h('//')h(are)f(optional)0 4780 y(and)30 b(ma)m(y)h(b)s(e)e(omitted)j(in)e(most)h(cases.)0 5096 y Fb(8.2.1)112 b(Notes)37 b(ab)s(out)i(HTTP)d(pro)m(xy)i(serv)m(ers)0 5320 y Fi(A)32 b(pro)m(xy)g(HTTP)f(serv)m(er)h(ma)m(y)h(b)s(e)e(used)g (b)m(y)h(de\014ning)f(the)h(address)f(\(URL\))i(and)e(p)s(ort)g(n)m(um) m(b)s(er)g(of)h(the)g(pro)m(xy)0 5433 y(serv)m(er)f(with)f(the)g(h)m (ttp)p 801 5433 28 4 v 33 w(pro)m(xy)g(en)m(vironmen)m(t)h(v)-5 b(ariable.)42 b(F)-8 b(or)31 b(example)191 5714 y Fe(setenv)46 b(http_proxy)f(http://heasarc.gsfc.nasa)o(.gov)o(:312)o(8)p eop end %%Page: 83 89 TeXDict begin 83 88 bop 0 299 a Fg(8.2.)72 b(FILETYPE)3128 b Fi(83)0 555 y(will)38 b(cause)g(CFITSIO)f(to)h(use)g(p)s(ort)f(3128)i (on)f(the)g(heasarc)g(pro)m(xy)g(serv)m(er)g(whenev)m(er)g(reading)g(a) g(FITS)f(\014le)0 668 y(with)30 b(HTTP)-8 b(.)0 987 y Fb(8.2.2)112 b(Notes)37 b(ab)s(out)i(the)e(stream)h(\014let)m(yp)s(e)g (driv)m(er)0 1212 y Fi(The)e(stream)h(driv)m(er)f(can)h(b)s(e)f(used)g (to)h(e\016cien)m(tly)i(read)d(a)h(FITS)f(\014le)h(from)f(the)h(stdin)f (\014le)g(stream)h(or)g(write)0 1324 y(a)44 b(FITS)e(to)i(the)g(stdout) f(\014le)g(stream.)80 b(Ho)m(w)m(ev)m(er,)49 b(b)s(ecause)43 b(these)h(input)e(and)h(output)g(streams)g(m)m(ust)h(b)s(e)0 1437 y(accessed)30 b(sequen)m(tially)-8 b(,)31 b(the)e(FITS)f(\014le)g (reading)h(or)f(writing)h(application)h(m)m(ust)e(also)i(read)e(and)g (write)h(the)g(\014le)0 1550 y(sequen)m(tially)-8 b(,)33 b(at)e(least)g(within)f(the)h(tolerances)h(describ)s(ed)d(b)s(elo)m(w.) 0 1710 y(CFITSIO)34 b(supp)s(orts)f(2)j(di\013eren)m(t)f(metho)s(ds)g (for)g(accessing)i(FITS)d(\014les)h(on)h(the)f(stdin)g(and)f(stdout)h (streams.)0 1823 y(The)c(original)i(metho)s(d,)f(whic)m(h)f(is)h(in)m (v)m(ok)m(ed)h(b)m(y)f(sp)s(ecifying)f(a)h(dash)f(c)m(haracter,)j("-",) g(as)d(the)h(name)g(of)g(the)g(\014le)0 1936 y(when)g(op)s(ening)g(or)h (creating)h(it,)g(w)m(orks)e(b)m(y)h(storing)g(a)g(complete)h(cop)m(y)g (of)f(the)g(en)m(tire)g(FITS)f(\014le)h(in)f(memory)-8 b(.)0 2049 y(In)35 b(this)g(case,)k(when)34 b(reading)i(from)f(stdin,)i (CFITSIO)d(will)i(cop)m(y)h(the)e(en)m(tire)i(stream)f(in)m(to)h (memory)e(b)s(efore)0 2162 y(doing)c(an)m(y)h(pro)s(cessing)f(of)h(the) f(\014le.)44 b(Similarly)-8 b(,)32 b(when)f(writing)g(to)h(stdout,)g (CFITSIO)d(will)j(create)h(a)f(cop)m(y)g(of)0 2275 y(the)h(en)m(tire)g (FITS)f(\014le)g(in)h(memory)-8 b(,)33 b(b)s(efore)f(\014nally)h (\015ushing)e(it)i(out)f(to)i(the)e(stdout)h(stream)g(when)e(the)i (FITS)0 2388 y(\014le)g(is)g(closed.)49 b(Bu\013ering)33 b(the)g(en)m(tire)h(FITS)e(\014le)h(in)g(this)f(w)m(a)m(y)i(allo)m(ws)g (the)f(application)i(to)e(randomly)g(access)0 2501 y(an)m(y)h(part)f (of)h(the)f(FITS)g(\014le,)i(in)e(an)m(y)h(order,)f(but)g(it)h(also)h (requires)e(that)h(the)f(user)g(ha)m(v)m(e)i(su\016cien)m(t)f(a)m(v)-5 b(ailable)0 2614 y(memory)30 b(\(or)g(virtual)g(memory\))g(to)h(store)f (the)g(en)m(tire)h(\014le,)f(whic)m(h)f(ma)m(y)i(not)f(b)s(e)f(p)s (ossible)g(in)h(the)g(case)h(of)f(v)m(ery)0 2727 y(large)h(\014les.)0 2887 y(The)e(new)m(er)g(stream)h(\014let)m(yp)s(e)g(pro)m(vides)f(a)h (more)f(memory-e\016cien)m(t)i(metho)s(d)e(of)h(accessing)h(FITS)d (\014les)h(on)h(the)0 3000 y(stdin)37 b(or)h(stdout)g(streams.)64 b(Instead)38 b(of)g(storing)g(a)g(cop)m(y)h(of)f(the)g(en)m(tire)h (FITS)e(\014le)h(in)g(memory)-8 b(,)40 b(CFITSIO)0 3113 y(only)32 b(uses)g(a)g(set)h(of)f(in)m(ternal)h(bu\013er)e(whic)m(h)h (b)m(y)g(default)g(can)g(store)h(40)g(FITS)e(blo)s(c)m(ks,)i(or)g(ab)s (out)e(100K)i(b)m(ytes)0 3225 y(of)f(the)f(FITS)g(\014le.)43 b(The)31 b(application)i(program)e(m)m(ust)g(pro)s(cess)g(the)h(FITS)e (\014le)i(sequen)m(tially)h(from)e(b)s(eginning)0 3338 y(to)h(end,)e(within)g(this)h(100K)h(bu\013er.)41 b(Generally)32 b(sp)s(eaking)f(the)g(application)h(program)f(m)m(ust)f(conform)h(to)h (the)0 3451 y(follo)m(wing)g(restrictions:)136 3735 y Fc(\017)46 b Fi(The)36 b(program)f(m)m(ust)h(\014nish)e(reading)i(or)g (writing)f(the)h(header)g(k)m(eyw)m(ords)g(b)s(efore)f(reading)h(or)g (writing)227 3848 y(an)m(y)31 b(data)g(in)f(the)h(HDU.)136 4060 y Fc(\017)46 b Fi(The)24 b(HDU)h(can)f(con)m(tain)i(at)e(most)h (ab)s(out)f(1400)h(header)f(k)m(eyw)m(ords.)39 b(This)24 b(is)g(the)g(maxim)m(um)g(that)h(can)f(\014t)227 4172 y(in)g(the)g(nominal)h(40)g(FITS)e(blo)s(c)m(k)i(bu\013er.)37 b(In)24 b(principle,)h(this)f(limit)h(could)f(b)s(e)g(increased)g(b)m (y)g(recompiling)227 4285 y(CFITSIO)29 b(with)h(a)h(larger)g(bu\013er)e (limit,)j(whic)m(h)e(is)g(set)h(b)m(y)f(the)h(NIOBUF)g(parameter)g(in)f (\014tsio2.h.)136 4497 y Fc(\017)46 b Fi(The)32 b(program)g(m)m(ust)f (read)h(or)g(write)h(the)f(data)g(in)g(a)g(sequen)m(tial)i(manner)d (from)h(the)g(b)s(eginning)f(to)i(the)227 4610 y(end)26 b(of)g(the)h(HDU.)g(Note)h(that)f(CFITSIO's)e(in)m(ternal)i(100K)g (bu\013er)e(allo)m(ws)j(a)e(little)j(latitude)e(in)f(meeting)227 4723 y(this)31 b(requiremen)m(t.)136 4934 y Fc(\017)46 b Fi(The)30 b(program)g(cannot)h(mo)m(v)m(e)h(bac)m(k)f(to)g(a)g (previous)f(HDU)h(in)f(the)h(FITS)e(\014le.)136 5146 y Fc(\017)46 b Fi(Reading)c(or)f(writing)f(of)h(v)-5 b(ariable)42 b(length)f(arra)m(y)h(columns)e(in)h(binary)f(tables)i(is) f(not)g(supp)s(orted)e(on)227 5259 y(streams,)29 b(b)s(ecause)f(this)g (requires)g(mo)m(ving)g(bac)m(k)h(and)f(forth)f(b)s(et)m(w)m(een)i(the) f(\014xed-length)g(p)s(ortion)g(of)g(the)227 5372 y(binary)i(table)h (and)f(the)g(follo)m(wing)i(heap)e(area)i(where)e(the)g(arra)m(ys)h (are)g(actually)h(stored.)136 5583 y Fc(\017)46 b Fi(Reading)25 b(or)g(writing)f(of)h(tile-compressed)h(images)g(is)e(not)h(supp)s (orted)e(on)h(streams,)i(b)s(ecause)f(the)g(images)227 5696 y(are)31 b(in)m(ternally)g(stored)g(using)f(v)-5 b(ariable)31 b(length)g(arra)m(ys.)p eop end %%Page: 84 90 TeXDict begin 84 89 bop 0 299 a Fi(84)1618 b Fg(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fb(8.2.3)112 b(Notes)37 b(ab)s(out)i(the)e(gsiftp)h(\014let)m(yp) s(e)0 774 y Fi(DEPENDENCIES:)c(Globus)h(to)s(olkit)h(\(2.4.3)g(or)f (higher\))f(\(GT\))h(should)f(b)s(e)g(installed.)53 b(There)34 b(are)h(t)m(w)m(o)h(dif-)0 887 y(feren)m(t)31 b(w)m(a)m(ys)g(to)g (install)g(GT:)0 1047 y(1\))43 b(goto)h(the)f(globus)f(to)s(olkit)i(w)m (eb)e(page)i(www.globus.org)e(and)g(follo)m(w)h(the)g(do)m(wnload)g (and)e(compilation)0 1160 y(instructions;)0 1320 y(2\))j(goto)i(the)d (Virtual)i(Data)g(T)-8 b(o)s(olkit)45 b(w)m(eb)e(page)i(h)m (ttp://vdt.cs.wisc.edu/)g(and)e(follo)m(w)i(the)f(instructions)0 1433 y(\(STR)m(ONGL)-8 b(Y)31 b(SUGGESTED\);)0 1593 y(Once)23 b(a)h(globus)f(clien)m(t)h(has)f(b)s(een)g(installed)h(in)e(y)m(our)i (system)f(with)g(a)g(sp)s(eci\014c)g(\015a)m(v)m(our)h(it)f(is)g(p)s (ossible)g(to)h(compile)0 1706 y(and)30 b(install)h(the)g(CFITSIO)d (libraries.)41 b(Sp)s(eci\014c)30 b(con\014guration)h(\015ags)f(m)m (ust)h(b)s(e)e(used:)0 1866 y(1\))21 b({with-gsiftp[[=P)-8 b(A)g(TH]])22 b(Enable)f(Globus)f(T)-8 b(o)s(olkit)21 b(gsiftp)g(proto)s(col)g(supp)s(ort)d(P)-8 b(A)g(TH=GLOBUS)p 3532 1866 28 4 v 33 w(LOCA)g(TION)0 1979 y(i.e.)42 b(the)30 b(lo)s(cation)i(of)f(y)m(our)f(globus)g(installation)0 2139 y(2\))h({with-gsiftp-\015a)m(v)m(our[[=P)-8 b(A)g(TH])33 b(de\014nes)d(the)g(sp)s(eci\014c)g(Globus)h(\015a)m(v)m(our)f(ex.)41 b(gcc32)0 2300 y(Both)31 b(the)g(\015ags)f(m)m(ust)g(b)s(e)g(used)g (and)f(it)i(is)g(mandatory)f(to)h(set)g(b)s(oth)f(the)g(P)-8 b(A)g(TH)31 b(and)f(the)h(\015a)m(v)m(our.)0 2460 y(USA)m(GE:)g(T)-8 b(o)31 b(access)h(\014les)e(on)g(a)h(gridftp)f(serv)m(er)g(it)h(is)g (necessary)f(to)i(use)e(a)g(gsiftp)h(pre\014x:)0 2620 y(example:)41 b(gsiftp://remote)p 1003 2620 V 35 w(serv)m(er)p 1271 2620 V 34 w(fqhn/directory/\014lename)0 2780 y(The)f(gridftp)g (driv)m(er)g(uses)g(a)g(lo)s(cal)i(bu\013er)d(on)i(a)f(temp)s(orary)g (\014le)h(the)f(\014le)h(is)f(lo)s(cated)i(in)e(the)g(/tmp)h(direc-)0 2893 y(tory)-8 b(.)73 b(If)40 b(y)m(ou)h(ha)m(v)m(e)h(sp)s(ecial)g(p)s (ermissions)d(on)i(/tmp)g(or)g(y)m(ou)g(do)f(not)i(ha)m(v)m(e)g(a)f (/tmp)g(directory)-8 b(,)44 b(it)e(is)e(p)s(os-)0 3006 y(sible)d(to)h(force)g(another)g(lo)s(cation)g(setting)h(the)e(GSIFTP)p 2068 3006 V 32 w(TMPFILE)g(en)m(vironmen)m(t)h(v)-5 b(ariable)38 b(\(ex.)62 b(exp)s(ort)0 3119 y(GSIFTP)p 347 3119 V 32 w(TMPFILE=/y)m(our/lo)s(cation/y)m(ourtmp\014le\).)0 3279 y(Grid)34 b(FTP)g(supp)s(orts)f(m)m(ulti)h(c)m(hannel)h(transfer.) 52 b(By)35 b(default)f(a)h(single)g(c)m(hannel)g(transmission)f(is)g(a) m(v)-5 b(ailable.)0 3392 y(Ho)m(w)m(ev)m(er,)34 b(it)d(is)h(p)s (ossible)e(to)i(mo)s(dify)e(this)i(b)s(eha)m(vior)f(setting)h(the)f (GSIFTP)p 2691 3392 V 33 w(STREAMS)f(en)m(vironmen)m(t)h(v)-5 b(ari-)0 3505 y(able)31 b(\(ex.)41 b(exp)s(ort)30 b(GSIFTP)p 1016 3505 V 33 w(STREAMS=8\).)0 3790 y Fb(8.2.4)112 b(Notes)37 b(ab)s(out)i(the)e(ro)s(ot)g(\014let)m(yp)s(e)0 4009 y Fi(The)20 b(original)j(ro)s(otd)d(serv)m(er)h(can)h(b)s(e)e(obtained) h(from:)36 b Fe(ftp://root.cern.ch/root)o(/roo)o(td.t)o(ar.)o(gz)15 b Fi(but,)22 b(for)0 4122 y(it)33 b(to)h(w)m(ork)f(correctly)h(with)e (CFITSIO)g(one)h(has)f(to)i(use)e(a)i(mo)s(di\014ed)d(v)m(ersion)j (whic)m(h)e(supp)s(orts)f(a)i(command)0 4235 y(to)41 b(return)d(the)j(length)f(of)g(the)g(\014le.)70 b(This)39 b(mo)s(di\014ed)f(v)m(ersion)j(is)f(a)m(v)-5 b(ailable)42 b(in)e(ro)s(otd)f(sub)s(directory)g(in)h(the)0 4348 y(CFITSIO)29 b(ftp)h(area)h(at)286 4577 y Fe(ftp://legacy.gsfc.nasa.gov)o(/so)o (ftwa)o(re/f)o(its)o(io/c)o(/roo)o(t/r)o(ootd)o(.tar)o(.gz)o(.)0 4805 y Fi(This)j(small)g(serv)m(er)h(is)g(started)f(either)h(b)m(y)g (inetd)f(when)f(a)i(clien)m(t)h(requests)e(a)h(connection)h(to)f(a)f (ro)s(otd)h(serv)m(er)0 4918 y(or)30 b(b)m(y)g(hand)f(\(i.e.)42 b(from)30 b(the)g(command)g(line\).)42 b(The)29 b(ro)s(otd)h(serv)m(er) h(w)m(orks)f(with)g(the)g(R)m(OOT)g(TNetFile)i(class.)0 5031 y(It)e(allo)m(ws)g(remote)h(access)f(to)h(R)m(OOT)e(database)h (\014les)f(in)g(either)h(read)g(or)f(write)h(mo)s(de.)40 b(By)30 b(default)f(TNetFile)0 5144 y(assumes)38 b(p)s(ort)g(432)h (\(whic)m(h)f(requires)g(ro)s(otd)g(to)h(b)s(e)f(started)h(as)f(ro)s (ot\).)65 b(T)-8 b(o)39 b(run)e(ro)s(otd)h(via)h(inetd)f(add)g(the)0 5257 y(follo)m(wing)32 b(line)f(to)g(/etc/services:)95 5485 y Fe(rootd)238 b(432/tcp)0 5714 y Fi(and)30 b(to)h (/etc/inetd.conf,)i(add)d(the)g(follo)m(wing)i(line:)p eop end %%Page: 85 91 TeXDict begin 85 90 bop 0 299 a Fg(8.2.)72 b(FILETYPE)3128 b Fi(85)95 555 y Fe(rootd)47 b(stream)f(tcp)h(nowait)f(root)h (/user/rdm/root/bin/root)o(d)42 b(rootd)k(-i)0 829 y Fi(F)-8 b(orce)34 b(inetd)e(to)i(reread)e(its)h(conf)f(\014le)h(with)f ("kill)h(-HUP)g(".)47 b(Y)-8 b(ou)33 b(can)g(also)g(start) g(ro)s(otd)g(b)m(y)f(hand)0 942 y(running)j(directly)i(under)d(y)m(our) j(priv)-5 b(ate)37 b(accoun)m(t)g(\(no)g(ro)s(ot)g(system)f(privileges) h(needed\).)59 b(F)-8 b(or)37 b(example)g(to)0 1054 y(start)e(ro)s(otd) e(listening)i(on)f(p)s(ort)f(5151)j(just)d(t)m(yp)s(e:)49 b Fe(rootd)d(-p)h(5151)33 b Fi(Notice:)50 b(no)34 b(&)f(is)h(needed.)51 b(Ro)s(otd)35 b(will)0 1167 y(go)c(in)m(to)h(bac)m(kground)e(b)m(y)g (itself.)95 1441 y Fe(Rootd)47 b(arguments:)191 1554 y(-i)763 b(says)47 b(we)g(were)f(started)g(by)h(inetd)191 1667 y(-p)g(port#)476 b(specifies)45 b(a)j(different)d(port)i(to)g (listen)f(on)191 1780 y(-d)h(level)476 b(level)46 b(of)i(debug)e(info)h (written)e(to)j(syslog)1050 1893 y(0)f(=)h(no)f(debug)f(\(default\)) 1050 2005 y(1)h(=)h(minimum)1050 2118 y(2)f(=)h(medium)1050 2231 y(3)f(=)h(maximum)0 2505 y Fi(Ro)s(otd)29 b(can)f(also)h(b)s(e)f (con\014gured)g(for)g(anon)m(ymous)g(usage)h(\(lik)m(e)h(anon)m(ymous)e (ftp\).)40 b(T)-8 b(o)29 b(setup)f(ro)s(otd)g(to)h(accept)0 2618 y(anon)m(ymous)h(logins)h(do)g(the)f(follo)m(wing)i(\(while)f(b)s (eing)f(logged)i(in)e(as)g(ro)s(ot\):)143 2891 y Fe(-)48 b(Add)f(the)f(following)g(line)g(to)i(/etc/passwd:)239 3117 y(rootd:*:71:72:Anonymous)41 b(rootd:/var/spool/rootd:/b)o(in/)o (fals)o(e)239 3343 y(where)46 b(you)h(may)g(modify)f(the)h(uid,)f(gid)h (\(71,)g(72\))g(and)g(the)g(home)f(directory)239 3456 y(to)h(suite)f(your)h(system.)143 3681 y(-)h(Add)f(the)f(following)g (line)g(to)i(/etc/group:)239 3907 y(rootd:*:72:rootd)239 4133 y(where)e(the)h(gid)g(must)f(match)h(the)g(gid)g(in)g (/etc/passwd.)143 4359 y(-)h(Create)e(the)h(directories:)239 4585 y(mkdir)f(/var/spool/rootd)239 4698 y(mkdir)g (/var/spool/rootd/tmp)239 4811 y(chmod)g(777)h(/var/spool/rootd/tmp)239 5036 y(Where)f(/var/spool/rootd)d(must)k(match)f(the)h(rootd)g(home)f (directory)g(as)239 5149 y(specified)f(in)i(the)g(rootd)f(/etc/passwd)f (entry.)143 5375 y(-)j(To)f(make)f(writeable)g(directories)e(for)j (anonymous)f(do,)h(for)f(example:)239 5601 y(mkdir)g (/var/spool/rootd/pub)239 5714 y(chown)g(rootd:rootd)f (/var/spool/rootd/pub)p eop end %%Page: 86 92 TeXDict begin 86 91 bop 0 299 a Fi(86)1618 b Fg(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fi(That's)42 b(all.)76 b(Sev)m(eral)43 b(additional)g(remarks:)64 b(y)m(ou)42 b(can)g(login)h(to)g(an)f(anon)m(ymous)f(serv)m(er)i (either)f(with)g(the)0 668 y(names)31 b("anon)m(ymous")h(or)f("ro)s (otd".)43 b(The)31 b(passw)m(ord)f(should)g(b)s(e)h(of)g(t)m(yp)s(e)g (user@host.do.main.)43 b(Only)30 b(the)h(@)0 781 y(is)e(enforced)f(for) h(the)f(time)i(b)s(eing.)39 b(In)28 b(anon)m(ymous)h(mo)s(de)f(the)g (top)h(of)g(the)g(\014le)f(tree)i(is)e(set)h(to)h(the)e(ro)s(otd)h (home)0 894 y(directory)-8 b(,)39 b(therefore)e(only)f(\014les)h(b)s (elo)m(w)f(the)h(home)f(directory)h(can)f(b)s(e)g(accessed.)60 b(Anon)m(ymous)36 b(mo)s(de)g(only)0 1007 y(w)m(orks)30 b(when)g(the)g(serv)m(er)h(is)f(started)h(via)g(inetd.)0 1296 y Fb(8.2.5)112 b(Notes)37 b(ab)s(out)i(the)e(shmem)i(\014let)m(yp) s(e:)0 1515 y Fi(Shared)34 b(memory)h(\014les)g(are)g(curren)m(tly)g (supp)s(orted)e(on)i(most)h(Unix)f(platforms,)h(where)f(the)g(shared)f (memory)0 1627 y(segmen)m(ts)d(are)g(managed)g(b)m(y)f(the)g(op)s (erating)h(system)g(k)m(ernel)f(and)g(`liv)m(e')i(indep)s(enden)m(tly)d (of)i(pro)s(cesses.)40 b(They)0 1740 y(are)34 b(not)g(deleted)h(\(b)m (y)f(default\))g(when)f(the)h(pro)s(cess)f(whic)m(h)h(created)h(them)f (terminates,)h(although)g(they)f(will)0 1853 y(disapp)s(ear)e(if)h(the) h(system)f(is)g(reb)s(o)s(oted.)49 b(Applications)34 b(can)g(create)h(shared)d(memory)h(\014les)g(in)g(CFITSIO)f(b)m(y)0 1966 y(calling:)143 2214 y Fe(fit_create_file\(&fitsfile)o(ptr,)41 b("shmem://h2",)j(&status\);)0 2462 y Fi(where)25 b(the)g(ro)s(ot)h (`\014le')f(names)h(are)f(curren)m(tly)g(restricted)h(to)g(b)s(e)f ('h0',)i('h1',)g('h2',)g('h3',)f(etc.,)i(up)d(to)g(a)h(maxim)m(um)0 2575 y(n)m(um)m(b)s(er)20 b(de\014ned)f(b)m(y)i(the)g(the)g(v)-5 b(alue)22 b(of)f(SHARED)p 1746 2575 28 4 v 33 w(MAXSEG)g(\(equal)h(to)f (16)h(b)m(y)f(default\).)38 b(This)20 b(is)h(a)g(protot)m(yp)s(e)0 2688 y(implemen)m(tation)30 b(of)f(the)g(shared)f(memory)g(in)m (terface)i(and)e(a)h(more)g(robust)f(in)m(terface,)j(whic)m(h)d(will)h (ha)m(v)m(e)h(few)m(er)0 2801 y(restrictions)h(on)f(the)h(n)m(um)m(b)s (er)e(of)i(\014les)f(and)g(on)g(their)g(names,)h(ma)m(y)g(b)s(e)f(dev)m (elop)s(ed)g(in)g(the)h(future.)0 2961 y(When)23 b(op)s(ening)h(an)f (already)h(existing)h(FITS)e(\014le)h(in)f(shared)g(memory)h(one)g (calls)g(the)g(usual)g(CFITSIO)e(routine:)143 3209 y Fe(fits_open_file\(&fitsfilep)o(tr,)41 b("shmem://h7",)j(mode,)j (&status\))0 3457 y Fi(The)26 b(\014le)h(mo)s(de)g(can)g(b)s(e)f(READ)m (WRITE)h(or)g(READONL)-8 b(Y)28 b(just)e(as)h(with)f(disk)h(\014les.)39 b(More)28 b(than)e(one)h(pro)s(cess)0 3570 y(can)35 b(op)s(erate)g(on)f (READONL)-8 b(Y)35 b(mo)s(de)f(\014les)h(at)g(the)f(same)h(time.)54 b(CFITSIO)33 b(supp)s(orts)f(prop)s(er)h(\014le)i(lo)s(c)m(king)0 3682 y(\(b)s(oth)27 b(in)h(READONL)-8 b(Y)29 b(and)e(READ)m(WRITE)h(mo) s(des\),)h(so)f(calls)h(to)f(\014ts)p 2572 3682 V 33 w(op)s(en)p 2795 3682 V 32 w(\014le)g(ma)m(y)g(b)s(e)f(lo)s(c)m(k)m(ed) j(out)e(un)m(til)0 3795 y(another)j(other)f(pro)s(cess)g(closes)i(the)e (\014le.)0 3956 y(When)g(an)g(application)i(is)e(\014nished)f (accessing)j(a)e(FITS)g(\014le)g(in)g(a)h(shared)e(memory)h(segmen)m (t,)i(it)f(ma)m(y)g(close)g(it)0 4068 y(\(and)j(the)g(\014le)g(will)g (remain)f(in)h(the)g(system\))g(with)g(\014ts)p 1955 4068 V 32 w(close)p 2173 4068 V 34 w(\014le,)h(or)f(delete)h(it)g(with) e(\014ts)p 3191 4068 V 33 w(delete)p 3455 4068 V 34 w(\014le.)51 b(Ph)m(ys-)0 4181 y(ical)36 b(deletion)g(is)f(p)s(ostp)s(oned)e(un)m (til)j(the)f(last)g(pro)s(cess)g(calls)h(\013clos/\013delt.)56 b(\014ts)p 2801 4181 V 32 w(delete)p 3064 4181 V 34 w(\014le)35 b(tries)h(to)f(obtain)h(a)0 4294 y(READ)m(WRITE)e(lo)s(c)m(k)g(on)f (the)g(\014le)h(to)g(b)s(e)e(deleted,)j(th)m(us)e(it)h(can)f(b)s(e)g (blo)s(c)m(k)m(ed)h(if)f(the)h(ob)5 b(ject)34 b(w)m(as)f(not)h(op)s (ened)0 4407 y(in)c(READ)m(WRITE)h(mo)s(de.)0 4567 y(A)i(shared)f (memory)h(managemen)m(t)h(utilit)m(y)g(program)f(called)h(`smem',)f(is) g(included)f(with)h(the)g(CFITSIO)e(dis-)0 4680 y(tribution.)39 b(It)27 b(can)g(b)s(e)f(built)h(b)m(y)g(t)m(yping)g(`mak)m(e)h(smem';)g (then)f(t)m(yp)s(e)g(`smem)f(-h')h(to)h(get)g(a)f(list)g(of)g(v)-5 b(alid)27 b(options.)0 4793 y(Executing)37 b(smem)f(without)g(an)m(y)h (options)g(causes)f(it)h(to)g(list)g(all)g(the)g(shared)e(memory)i (segmen)m(ts)g(curren)m(tly)0 4906 y(residing)c(in)g(the)g(system)h (and)e(managed)i(b)m(y)f(the)h(shared)e(memory)h(driv)m(er.)49 b(T)-8 b(o)34 b(get)g(a)g(list)g(of)f(all)h(the)g(shared)0 5019 y(memory)c(ob)5 b(jects,)32 b(run)d(the)h(system)h(utilit)m(y)g (program)f(`ip)s(cs)h([-a]'.)0 5351 y Fd(8.3)135 b(Base)46 b(Filename)0 5601 y Fi(The)31 b(base)g(\014lename)h(is)f(the)h(name)f (of)h(the)f(\014le)h(optionally)g(including)f(the)h(director/sub)s (directory)f(path,)h(and)0 5714 y(in)e(the)h(case)g(of)g(`ftp',)f(`h)m (ttp',)i(and)d(`ro)s(ot')j(\014let)m(yp)s(es,)e(the)h(mac)m(hine)g (iden)m(ti\014er.)41 b(Examples:)p eop end %%Page: 87 93 TeXDict begin 87 92 bop 0 299 a Fg(8.3.)72 b(BASE)30 b(FILENAME)2830 b Fi(87)191 555 y Fe(myfile.fits)191 668 y(!data.fits)191 781 y(/data/myfile.fits)191 894 y(fits.gsfc.nasa.gov/ftp/s)o(ampl)o(eda)o(ta/m)o(yfil)o(e.f)o(its.)o (gz)0 1120 y Fi(When)29 b(creating)h(a)f(new)f(output)h(\014le)g(on)g (magnetic)h(disk)e(\(of)i(t)m(yp)s(e)f(\014le://\))h(if)f(the)g(base)g (\014lename)g(b)s(egins)f(with)0 1233 y(an)34 b(exclamation)j(p)s(oin)m (t)d(\(!\))54 b(then)34 b(an)m(y)g(existing)i(\014le)e(with)g(that)h (same)g(basename)g(will)g(b)s(e)e(deleted)i(prior)f(to)0 1346 y(creating)h(the)f(new)g(FITS)f(\014le.)51 b(Otherwise)34 b(if)g(the)g(\014le)g(to)g(b)s(e)g(created)h(already)f(exists,)i(then)d (CFITSIO)g(will)0 1459 y(return)g(an)h(error)f(and)g(will)i(not)f(o)m (v)m(erwrite)h(the)f(existing)h(\014le.)52 b(Note)35 b(that)g(the)f(exclamation)i(p)s(oin)m(t,)f(')10 b(!',)36 b(is)e(a)0 1572 y(sp)s(ecial)28 b(UNIX)g(c)m(haracter,)j(so)d(if)f(it)i (is)f(used)f(on)g(the)h(command)g(line)g(rather)g(than)f(en)m(tered)h (at)h(a)f(task)h(prompt,)0 1685 y(it)j(m)m(ust)f(b)s(e)g(preceded)g(b)m (y)h(a)g(bac)m(kslash)g(to)g(force)g(the)g(UNIX)g(shell)f(to)h(pass)f (it)i(v)m(erbatim)f(to)g(the)g(application)0 1798 y(program.)0 1958 y(If)24 b(the)i(output)e(disk)h(\014le)g(name)g(ends)f(with)g(the) h(su\016x)f('.gz',)k(then)d(CFITSIO)e(will)i(compress)g(the)g(\014le)g (using)g(the)0 2071 y(gzip)g(compression)f(algorithm)h(b)s(efore)f (writing)g(it)h(to)g(disk.)38 b(This)23 b(can)i(reduce)f(the)g(amoun)m (t)h(of)f(disk)g(space)h(used)0 2184 y(b)m(y)34 b(the)h(\014le.)53 b(Note)36 b(that)f(this)g(feature)g(requires)f(that)h(the)f (uncompressed)g(\014le)g(b)s(e)g(constructed)h(in)f(memory)0 2297 y(b)s(efore)c(it)h(is)f(compressed)g(and)g(written)h(to)g(disk,)f (so)g(it)h(can)g(fail)g(if)f(there)h(is)f(insu\016cien)m(t)h(a)m(v)-5 b(ailable)33 b(memory)-8 b(.)0 2457 y(An)45 b(input)g(FITS)f(\014le)i (ma)m(y)g(b)s(e)f(compressed)g(with)h(the)f(gzip)h(or)g(Unix)f (compress)h(algorithms,)k(in)45 b(whic)m(h)0 2570 y(case)38 b(CFITSIO)e(will)i(uncompress)e(the)i(\014le)g(on)f(the)h(\015y)e(in)m (to)j(a)f(temp)s(orary)f(\014le)g(\(in)h(memory)f(or)g(on)h(disk\).)0 2683 y(Compressed)32 b(\014les)i(ma)m(y)g(only)f(b)s(e)g(op)s(ened)f (with)h(read-only)h(p)s(ermission.)49 b(When)33 b(sp)s(ecifying)g(the)h (name)f(of)h(a)0 2796 y(compressed)h(FITS)g(\014le)h(it)g(is)g(not)g (necessary)g(to)g(app)s(end)e(the)i(\014le)g(su\016x)e(\(e.g.,)39 b(`.gz')e(or)f(`.Z'\).)g(If)f(CFITSIO)0 2908 y(cannot)24 b(\014nd)e(the)h(input)f(\014le)i(name)f(without)g(the)g(su\016x,)h (then)f(it)h(will)g(automatically)i(searc)m(h)e(for)f(a)g(compressed)0 3021 y(\014le)36 b(with)f(the)h(same)g(ro)s(ot)g(name.)57 b(In)35 b(the)h(case)h(of)f(reading)g(ftp)f(and)g(h)m(ttp)h(t)m(yp)s(e) g(\014les,)h(CFITSIO)e(generally)0 3134 y(lo)s(oks)j(for)g(a)g (compressed)g(v)m(ersion)g(of)g(the)g(\014le)g(\014rst,)h(b)s(efore)e (trying)h(to)h(op)s(en)e(the)h(uncompressed)e(\014le.)64 b(By)0 3247 y(default,)37 b(CFITSIO)e(copies)h(\(and)g(uncompressed)e (if)i(necessary\))g(the)g(ftp)f(or)h(h)m(ttp)g(FITS)f(\014le)g(in)m(to) i(memory)0 3360 y(on)f(the)g(lo)s(cal)h(mac)m(hine)f(b)s(efore)g(op)s (ening)f(it.)58 b(This)35 b(will)h(fail)g(if)g(the)g(lo)s(cal)h(mac)m (hine)g(do)s(es)e(not)h(ha)m(v)m(e)h(enough)0 3473 y(memory)g(to)h (hold)f(the)g(whole)h(FITS)e(\014le,)k(so)d(in)g(this)g(case,)k(the)c (output)g(\014lename)g(sp)s(eci\014er)g(\(see)h(the)g(next)0 3586 y(section\))32 b(can)f(b)s(e)e(used)h(to)h(further)e(con)m(trol)j (ho)m(w)e(CFITSIO)f(reads)h(ftp)g(and)g(h)m(ttp)g(\014les.)0 3746 y(If)i(the)h(input)f(\014le)h(is)g(an)g(IRAF)g(image)h(\014le)f (\(*.imh)g(\014le\))h(then)e(CFITSIO)f(will)j(automatically)h(con)m(v)m (ert)g(it)e(on)0 3859 y(the)27 b(\015y)g(in)m(to)h(a)g(virtual)f(FITS)f (image)j(b)s(efore)e(it)g(is)g(op)s(ened)g(b)m(y)g(the)g(application)i (program.)39 b(IRAF)27 b(images)i(can)0 3972 y(only)h(b)s(e)g(op)s (ened)g(with)g(READONL)-8 b(Y)31 b(\014le)f(access.)0 4132 y(Similarly)-8 b(,)32 b(if)f(the)g(input)f(\014le)i(is)f(a)g(ra)m (w)g(binary)f(data)i(arra)m(y)-8 b(,)33 b(then)d(CFITSIO)g(will)h(con)m (v)m(ert)i(it)e(on)g(the)h(\015y)e(in)m(to)0 4245 y(a)38 b(virtual)g(FITS)g(image)h(with)e(the)h(basic)h(set)f(of)g(required)f (header)h(k)m(eyw)m(ords)g(b)s(efore)g(it)g(is)g(op)s(ened)f(b)m(y)h (the)0 4358 y(application)32 b(program)f(\(with)g(READONL)-8 b(Y)31 b(access\).)44 b(In)30 b(this)h(case)h(the)f(data)g(t)m(yp)s(e)g (and)g(dimensions)f(of)h(the)0 4471 y(image)d(m)m(ust)f(b)s(e)f(sp)s (eci\014ed)g(in)h(square)g(brac)m(k)m(ets)h(follo)m(wing)g(the)f (\014lename)g(\(e.g.)41 b(ra)m(w\014le.dat[ib512,512]\).)j(The)0 4584 y(\014rst)30 b(c)m(haracter)i(\(case)f(insensitiv)m(e\))h (de\014nes)e(the)g(datat)m(yp)s(e)h(of)g(the)g(arra)m(y:)239 4810 y Fe(b)429 b(8-bit)46 b(unsigned)g(byte)239 4923 y(i)381 b(16-bit)46 b(signed)g(integer)239 5036 y(u)381 b(16-bit)46 b(unsigned)g(integer)239 5149 y(j)381 b(32-bit)46 b(signed)g(integer)239 5262 y(r)h(or)g(f)143 b(32-bit)46 b(floating)g(point)239 5375 y(d)381 b(64-bit)46 b(floating)g(point)0 5601 y Fi(An)40 b(optional)h(second)f(c)m(haracter)i(sp)s(eci\014es)e (the)h(b)m(yte)f(order)g(of)g(the)h(arra)m(y)g(v)-5 b(alues:)60 b(b)40 b(or)g(B)h(indicates)g(big)0 5714 y(endian)f(\(as)h(in)f(FITS)f (\014les)i(and)f(the)g(nativ)m(e)i(format)e(of)h(SUN)f(UNIX)h(w)m (orkstations)g(and)f(Mac)i(PCs\))e(and)p eop end %%Page: 88 94 TeXDict begin 88 93 bop 0 299 a Fi(88)1618 b Fg(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fi(l)41 b(or)g(L)g(indicates)g(little)i(endian)e(\(nativ)m(e)h (format)g(of)f(DEC)f(OSF)h(w)m(orkstations)h(and)e(IBM)i(PCs\).)72 b(If)40 b(this)0 668 y(c)m(haracter)32 b(is)e(omitted)i(then)e(the)g (arra)m(y)h(is)g(assumed)e(to)i(ha)m(v)m(e)h(the)f(nativ)m(e)g(b)m(yte) g(order)f(of)h(the)f(lo)s(cal)i(mac)m(hine.)0 781 y(These)d(datat)m(yp) s(e)h(c)m(haracters)h(are)e(then)g(follo)m(w)m(ed)i(b)m(y)e(a)h(series) f(of)g(one)h(or)f(more)g(in)m(teger)i(v)-5 b(alues)29 b(separated)h(b)m(y)0 894 y(commas)h(whic)m(h)g(de\014ne)e(the)i(size)h (of)e(eac)m(h)i(dimension)e(of)h(the)g(ra)m(w)f(arra)m(y)-8 b(.)43 b(Arra)m(ys)30 b(with)h(up)e(to)j(5)f(dimensions)0 1007 y(are)f(curren)m(tly)g(supp)s(orted.)38 b(Finally)-8 b(,)32 b(a)e(b)m(yte)g(o\013set)g(to)h(the)e(p)s(osition)h(of)g(the)g (\014rst)e(pixel)i(in)g(the)f(data)i(\014le)e(ma)m(y)0 1120 y(b)s(e)d(sp)s(eci\014ed)g(b)m(y)h(separating)h(it)f(with)g(a)g (':')39 b(from)27 b(the)g(last)g(dimension)g(v)-5 b(alue.)40 b(If)26 b(omitted,)j(it)e(is)g(assumed)f(that)0 1233 y(the)35 b(o\013set)h(=)f(0.)54 b(This)35 b(parameter)g(ma)m(y)h(b)s(e) e(used)g(to)i(skip)e(o)m(v)m(er)i(an)m(y)g(header)e(information)i(in)e (the)h(\014le)g(that)0 1346 y(precedes)30 b(the)h(binary)f(data.)41 b(F)-8 b(urther)30 b(examples:)95 1603 y Fe(raw.dat[b10000])521 b(1-dimensional)45 b(10000)h(pixel)g(byte)h(array)95 1715 y(raw.dat[rb400,400,12])233 b(3-dimensional)45 b(floating)g(point) h(big-endian)f(array)95 1828 y(img.fits[ib512,512:2880])89 b(reads)47 b(the)g(512)g(x)g(512)g(short)f(integer)g(array)g(in)1336 1941 y(a)i(FITS)e(file,)h(skipping)e(over)i(the)g(2880)g(byte)f(header) 0 2198 y Fi(One)25 b(sp)s(ecial)g(case)h(of)f(input)f(\014le)h(is)g (where)g(the)g(\014lename)g(=)g(`-')h(\(a)f(dash)g(or)g(min)m(us)f (sign\))h(or)g('stdin')g(or)g('stdout',)0 2311 y(whic)m(h)d (signi\014es)h(that)h(the)f(input)e(\014le)i(is)g(to)h(b)s(e)e(read)g (from)h(the)g(stdin)f(stream,)j(or)e(written)f(to)i(the)f(stdout)g (stream)0 2424 y(if)34 b(a)g(new)g(output)f(\014le)h(is)g(b)s(eing)g (created.)52 b(In)33 b(the)h(case)h(of)f(reading)h(from)e(stdin,)h (CFITSIO)f(\014rst)g(copies)i(the)0 2537 y(whole)g(stream)h(in)m(to)g (a)f(temp)s(orary)g(FITS)f(\014le)i(\(in)f(memory)g(or)g(on)g(disk\),)h (and)f(subsequen)m(t)f(reading)h(of)h(the)0 2650 y(FITS)c(\014le)h(o)s (ccurs)g(in)f(this)h(cop)m(y)-8 b(.)49 b(When)33 b(writing)g(to)g (stdout,)h(CFITSIO)d(\014rst)h(constructs)h(the)g(whole)g(\014le)g(in)0 2763 y(memory)h(\(since)i(random)d(access)j(is)e(required\),)i(then)e (\015ushes)f(it)i(out)g(to)g(the)f(stdout)h(stream)g(when)e(the)i (\014le)0 2876 y(is)30 b(closed.)42 b(In)29 b(addition,)i(if)f(the)g (output)g(\014lename)g(=)g('-.gz')i(or)e('stdout.gz')h(then)f(it)h (will)f(b)s(e)g(gzip)g(compressed)0 2989 y(b)s(efore)g(b)s(eing)g (written)g(to)h(stdout.)0 3149 y(This)25 b(abilit)m(y)j(to)e(read)g (and)f(write)h(on)g(the)g(stdin)g(and)f(stdout)h(steams)g(allo)m(ws)i (FITS)d(\014les)h(to)g(b)s(e)g(pip)s(ed)e(b)s(et)m(w)m(een)0 3262 y(tasks)42 b(in)f(memory)g(rather)g(than)h(ha)m(ving)g(to)g (create)h(temp)s(orary)e(in)m(termediate)i(FITS)d(\014les)i(on)f(disk.) 73 b(F)-8 b(or)0 3375 y(example)28 b(if)e(task1)i(creates)h(an)e (output)f(FITS)g(\014le,)i(and)f(task2)g(reads)g(an)g(input)f(FITS)g (\014le,)i(the)f(FITS)f(\014le)h(ma)m(y)0 3487 y(b)s(e)j(pip)s(ed)f(b)s (et)m(w)m(een)i(the)f(2)h(tasks)g(b)m(y)f(sp)s(ecifying)143 3744 y Fe(task1)47 b(-)g(|)g(task2)g(-)0 4001 y Fi(where)30 b(the)h(v)m(ertical)i(bar)e(is)f(the)h(Unix)g(piping)f(sym)m(b)s(ol.)42 b(This)30 b(assumes)g(that)i(the)f(2)g(tasks)g(read)g(the)g(name)g(of)0 4114 y(the)g(FITS)e(\014le)i(o\013)f(of)h(the)g(command)f(line.)0 4448 y Fd(8.4)135 b(Output)45 b(File)g(Name)h(when)f(Op)t(ening)g(an)g (Existing)h(File)0 4698 y Fi(An)36 b(optional)i(output)e(\014lename)h (ma)m(y)h(b)s(e)e(sp)s(eci\014ed)g(in)g(paren)m(theses)h(immediately)h (follo)m(wing)g(the)f(base)g(\014le)0 4811 y(name)28 b(to)h(b)s(e)f(op)s(ened.)39 b(This)28 b(is)g(mainly)g(useful)g(in)g (those)g(cases)i(where)d(CFITSIO)g(creates)j(a)e(temp)s(orary)g(cop)m (y)0 4924 y(of)i(the)f(input)g(FITS)f(\014le)i(b)s(efore)f(it)h(is)f (op)s(ened)g(and)f(passed)h(to)h(the)g(application)h(program.)40 b(This)28 b(happ)s(ens)g(b)m(y)0 5036 y(default)i(when)g(op)s(ening)g (a)g(net)m(w)m(ork)h(FTP)g(or)f(HTTP-t)m(yp)s(e)g(\014le,)h(when)e (reading)h(a)h(compressed)f(FITS)g(\014le)g(on)0 5149 y(a)36 b(lo)s(cal)h(disk,)g(when)e(reading)h(from)g(the)g(stdin)f (stream,)j(or)d(when)g(a)i(column)e(\014lter,)j(ro)m(w)e(\014lter,)h (or)f(binning)0 5262 y(sp)s(eci\014er)29 b(is)g(included)g(as)h(part)f (of)g(the)h(input)f(\014le)g(sp)s(eci\014cation.)41 b(By)30 b(default)g(this)f(temp)s(orary)g(\014le)g(is)h(created)0 5375 y(in)g(memory)-8 b(.)41 b(If)29 b(there)h(is)g(not)g(enough)g (memory)g(to)h(create)g(the)g(\014le)f(cop)m(y)-8 b(,)31 b(then)f(CFITSIO)e(will)i(exit)h(with)f(an)0 5488 y(error.)45 b(In)32 b(these)g(cases)h(one)g(can)f(force)h(a)f(p)s(ermanen)m(t)g (\014le)g(to)h(b)s(e)e(created)i(on)f(disk,)g(instead)h(of)f(a)g(temp)s (orary)0 5601 y(\014le)38 b(in)f(memory)-8 b(,)40 b(b)m(y)d(supplying)f (the)i(name)g(in)f(paren)m(theses)h(immediately)h(follo)m(wing)g(the)e (base)h(\014le)g(name.)0 5714 y(The)30 b(output)g(\014lename)g(can)h (include)f(the)h(')10 b(!')41 b(clobb)s(er)30 b(\015ag.)p eop end %%Page: 89 95 TeXDict begin 89 94 bop 0 299 a Fg(8.4.)72 b(OUTPUT)30 b(FILE)g(NAME)h(WHEN)g(OPENING)f(AN)h(EXISTING)e(FILE)967 b Fi(89)0 555 y(Th)m(us,)48 b(if)d(the)g(input)f(\014lename)h(to)g (CFITSIO)f(is:)70 b Fe(file1.fits.gz\(file2.fit)o(s\))39 b Fi(then)44 b(CFITSIO)g(will)0 668 y(uncompress)39 b (`\014le1.\014ts.gz')j(in)m(to)f(the)f(lo)s(cal)h(disk)e(\014le)h (`\014le2.\014ts')h(b)s(efore)f(op)s(ening)f(it.)70 b(CFITSIO)38 b(do)s(es)i(not)0 781 y(automatically)33 b(delete)f(the)e(output)g (\014le,)h(so)g(it)g(will)f(still)i(exist)f(after)g(the)f(application)i (program)e(exits.)0 941 y(In)35 b(some)i(cases,)h(sev)m(eral)f (di\013eren)m(t)g(temp)s(orary)e(FITS)h(\014les)g(will)g(b)s(e)f (created)i(in)f(sequence,)i(for)e(instance,)i(if)0 1054 y(one)f(op)s(ens)g(a)g(remote)h(\014le)f(using)g(FTP)-8 b(,)37 b(then)g(\014lters)g(ro)m(ws)g(in)g(a)h(binary)e(table)i (extension,)i(then)c(create)j(an)0 1167 y(image)f(b)m(y)f(binning)f(a)h (pair)g(of)g(columns.)60 b(In)36 b(this)h(case,)j(the)d(remote)h (\014le)f(will)g(b)s(e)f(copied)h(to)h(a)f(temp)s(orary)0 1280 y(lo)s(cal)j(\014le,)h(then)d(a)h(second)f(temp)s(orary)h(\014le)f (will)h(b)s(e)f(created)i(con)m(taining)g(the)e(\014ltered)h(ro)m(ws)f (of)h(the)g(table,)0 1393 y(and)c(\014nally)g(a)h(third)e(temp)s(orary) h(\014le)h(con)m(taining)g(the)g(binned)e(image)i(will)g(b)s(e)f (created.)57 b(In)34 b(cases)i(lik)m(e)h(this)0 1506 y(where)28 b(m)m(ultiple)h(\014les)f(are)h(created,)h(the)e(out\014le)h (sp)s(eci\014er)f(will)g(b)s(e)g(in)m(terpreted)h(the)f(name)g(of)h (the)f(\014nal)g(\014le)h(as)0 1619 y(describ)s(ed)g(b)s(elo)m(w,)i(in) f(descending)g(priorit)m(y:)136 1869 y Fc(\017)46 b Fi(as)29 b(the)g(name)g(of)g(the)g(\014nal)f(image)i(\014le)f(if)f(an)h(image)h (within)e(a)h(single)g(binary)f(table)i(cell)g(is)e(op)s(ened)g(or)h (if)227 1982 y(an)i(image)g(is)g(created)g(b)m(y)f(binning)g(a)g(table) i(column.)136 2167 y Fc(\017)46 b Fi(as)33 b(the)f(name)h(of)f(the)h (\014le)f(con)m(taining)i(the)e(\014ltered)g(table)i(if)e(a)h(column)f (\014lter)g(and/or)g(a)h(ro)m(w)f(\014lter)h(are)227 2280 y(sp)s(eci\014ed.)136 2464 y Fc(\017)46 b Fi(as)31 b(the)f(name)h(of)f(the)h(lo)s(cal)h(cop)m(y)f(of)f(the)h(remote)g(FTP) f(or)h(HTTP)e(\014le.)136 2649 y Fc(\017)46 b Fi(as)31 b(the)g(name)g(of)g(the)f(uncompressed)g(v)m(ersion)h(of)g(the)f(FITS)g (\014le,)h(if)g(a)g(compressed)f(FITS)g(\014le)h(on)g(lo)s(cal)227 2762 y(disk)f(has)g(b)s(een)g(op)s(ened.)136 2946 y Fc(\017)46 b Fi(otherwise,)31 b(the)g(output)f(\014lename)g(is)h(ignored.)0 3197 y(The)e(output)f(\014le)h(sp)s(eci\014er)g(is)g(useful)f(when)g (reading)h(FTP)g(or)g(HTTP-t)m(yp)s(e)g(FITS)f(\014les)h(since)g(it)h (can)f(b)s(e)g(used)0 3310 y(to)34 b(create)i(a)e(lo)s(cal)h(disk)e (cop)m(y)i(of)f(the)g(\014le)f(that)i(can)f(b)s(e)f(reused)g(in)g(the)h (future.)50 b(If)33 b(the)h(output)g(\014le)f(name)h(=)0 3423 y(`*')i(then)e(a)i(lo)s(cal)g(\014le)f(with)g(the)g(same)g(name)g (as)g(the)h(net)m(w)m(ork)f(\014le)g(will)h(b)s(e)e(created.)56 b(Note)36 b(that)f(CFITSIO)0 3535 y(will)30 b(b)s(eha)m(v)m(e)g (di\013eren)m(tly)h(dep)s(ending)d(on)i(whether)f(the)h(remote)g (\014le)g(is)g(compressed)f(or)h(not)g(as)g(sho)m(wn)f(b)m(y)h(the)0 3648 y(follo)m(wing)i(examples:)136 3876 y Fc(\017)46 b Fi(`ftp://remote.mac)m(hine/tmp/m)m(y\014le.\014ts.gz\(*\)')k(-)43 b(the)g(remote)h(compressed)f(\014le)g(is)g(copied)h(to)g(the)227 3988 y(lo)s(cal)26 b(compressed)e(\014le)g(`m)m(y\014le.\014ts.gz',)k (whic)m(h)c(is)g(then)h(uncompressed)e(in)h(lo)s(cal)h(memory)f(b)s (efore)g(b)s(eing)227 4101 y(op)s(ened)30 b(and)g(passed)g(to)h(the)f (application)i(program.)136 4286 y Fc(\017)46 b Fi(`ftp://remote.mac)m (hine/tmp/m)m(y\014le.\014ts.gz\(m)m(y\014le.\014ts\)')d(-)37 b(the)g(remote)g(compressed)f(\014le)h(is)f(copied)227 4399 y(and)h(uncompressed)g(in)m(to)h(the)g(lo)s(cal)h(\014le)f(`m)m (y\014le.\014ts'.)64 b(This)36 b(example)j(requires)e(less)h(lo)s(cal)h (memory)227 4512 y(than)30 b(the)h(previous)f(example)h(since)g(the)f (\014le)h(is)f(uncompressed)f(on)h(disk)g(instead)h(of)f(in)h(memory)-8 b(.)136 4696 y Fc(\017)46 b Fi(`ftp://remote.mac)m(hine/tmp/m)m (y\014le.\014ts\(m)m(y\014le.\014ts.gz\)')28 b(-)21 b(this)g(will)h (usually)f(pro)s(duce)f(an)h(error)g(since)227 4809 y(CFITSIO)29 b(itself)i(cannot)g(compress)f(\014les.)0 5036 y(The)36 b(exact)i(b)s(eha)m(vior)e(of)h(CFITSIO)e(in)h(the)h(latter)g(case)h (dep)s(ends)c(on)j(the)f(t)m(yp)s(e)h(of)g(ftp)f(serv)m(er)g(running)f (on)0 5149 y(the)c(remote)g(mac)m(hine)g(and)f(ho)m(w)g(it)h(is)f (con\014gured.)40 b(In)30 b(some)h(cases,)g(if)f(the)h(\014le)f(`m)m (y\014le.\014ts.gz')j(exists)e(on)f(the)0 5262 y(remote)38 b(mac)m(hine,)h(then)e(the)g(serv)m(er)g(will)h(cop)m(y)f(it)h(to)f (the)h(lo)s(cal)g(mac)m(hine.)61 b(In)36 b(other)h(cases)h(the)f(ftp)g (serv)m(er)0 5375 y(will)f(automatically)j(create)e(and)f(transmit)g(a) g(compressed)g(v)m(ersion)g(of)g(the)g(\014le)g(if)g(only)g(the)g (uncompressed)0 5488 y(v)m(ersion)27 b(exists.)41 b(This)26 b(can)h(get)h(rather)f(confusing,)h(so)f(users)f(should)g(use)h(a)g (certain)h(amoun)m(t)g(of)f(caution)h(when)0 5601 y(using)34 b(the)h(output)f(\014le)h(sp)s(eci\014er)f(with)h(FTP)f(or)h(HTTP)f (\014le)h(t)m(yp)s(es,)h(to)f(mak)m(e)h(sure)e(they)h(get)h(the)f(b)s (eha)m(vior)0 5714 y(that)c(they)g(exp)s(ect.)p eop end %%Page: 90 96 TeXDict begin 90 95 bop 0 299 a Fi(90)1618 b Fg(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fd(8.5)135 b(T)-11 b(emplate)46 b(File)g(Name)f(when)g(Creating)h (a)g(New)f(File)0 808 y Fi(When)38 b(a)h(new)f(FITS)g(\014le)h(is)g (created)g(with)g(a)f(call)i(to)g(\014ts)p 2101 808 28 4 v 32 w(create)p 2369 808 V 35 w(\014le,)g(the)f(name)g(of)g(a)g (template)h(\014le)e(ma)m(y)0 921 y(b)s(e)h(supplied)g(in)h(paren)m (theses)g(immediately)h(follo)m(wing)g(the)g(name)f(of)g(the)g(new)f (\014le)h(to)h(b)s(e)e(created.)71 b(This)0 1034 y(template)27 b(is)e(used)g(to)h(de\014ne)f(the)h(structure)f(of)h(one)f(or)h(more)g (HDUs)g(in)f(the)h(new)f(\014le.)39 b(The)25 b(template)i(\014le)e(ma)m (y)0 1147 y(b)s(e)32 b(another)h(FITS)f(\014le,)i(in)f(whic)m(h)f(case) i(the)f(newly)g(created)h(\014le)f(will)g(ha)m(v)m(e)h(exactly)h(the)e (same)g(k)m(eyw)m(ords)g(in)0 1260 y(eac)m(h)25 b(HDU)g(as)g(in)f(the)g (template)i(FITS)d(\014le,)j(but)d(all)j(the)e(data)h(units)e(will)i(b) s(e)f(\014lled)g(with)f(zeros.)40 b(The)24 b(template)0 1373 y(\014le)i(ma)m(y)h(also)g(b)s(e)e(an)h(ASCI)s(I)e(text)j(\014le,) g(where)f(eac)m(h)h(line)f(\(in)g(general\))i(describ)s(es)d(one)h (FITS)f(k)m(eyw)m(ord)i(record.)0 1486 y(The)j(format)h(of)f(the)h (ASCI)s(I)e(template)i(\014le)g(is)f(describ)s(ed)f(b)s(elo)m(w.)0 1833 y Fd(8.6)135 b(Image)46 b(Tile-Compression)h(Sp)t(eci\014cation)0 2086 y Fi(When)28 b(sp)s(ecifying)g(the)h(name)g(of)f(the)h(output)f (FITS)g(\014le)g(to)h(b)s(e)f(created,)i(the)f(user)f(can)g(indicate)i (that)f(images)0 2198 y(should)d(b)s(e)h(written)g(in)g (tile-compressed)h(format)g(\(see)g(section)g(5.5,)h(\\Primary)e(Arra)m (y)h(or)f(IMA)m(GE)h(Extension)0 2311 y(I/O)f(Routines"\))i(b)m(y)e (enclosing)h(the)g(compression)f(parameters)h(in)f(square)g(brac)m(k)m (ets)i(follo)m(wing)g(the)f(ro)s(ot)f(disk)0 2424 y(\014le)j(name.)41 b(Here)31 b(are)g(some)g(examples)g(of)f(the)h(syn)m(tax)g(for)f(sp)s (ecifying)g(tile-compressed)i(output)e(images:)191 2695 y Fe(myfile.fit[compress])185 b(-)48 b(use)f(Rice)f(algorithm)g(and)h (default)e(tile)i(size)191 2921 y(myfile.fit[compress)42 b(GZIP])47 b(-)g(use)g(the)g(specified)e(compression)g(algorithm;)191 3034 y(myfile.fit[compress)d(Rice])238 b(only)46 b(the)h(first)g (letter)f(of)h(the)g(algorithm)191 3147 y(myfile.fit[compress)42 b(PLIO])238 b(name)46 b(is)i(required.)191 3373 y(myfile.fit[compress) 42 b(Rice)47 b(100,100])141 b(-)48 b(use)e(100)h(x)h(100)f(pixel)f (tile)h(size)191 3486 y(myfile.fit[compress)42 b(Rice)47 b(100,100;2])e(-)j(as)f(above,)f(and)h(use)g(noisebits)e(=)i(2)0 3833 y Fd(8.7)135 b(HDU)46 b(Lo)t(cation)f(Sp)t(eci\014cation)0 4086 y Fi(The)c(optional)h(HDU)h(lo)s(cation)g(sp)s(eci\014er)d (de\014nes)h(whic)m(h)g(HDU)h(\(Header-Data)i(Unit,)h(also)d(kno)m(wn)f (as)h(an)0 4199 y(`extension'\))36 b(within)d(the)i(FITS)e(\014le)h(to) h(initially)h(op)s(en.)51 b(It)34 b(m)m(ust)g(immediately)i(follo)m(w)f (the)f(base)h(\014le)f(name)0 4312 y(\(or)g(the)g(output)g(\014le)g (name)f(if)h(presen)m(t\).)52 b(If)33 b(it)h(is)g(not)g(sp)s(eci\014ed) g(then)f(the)h(\014rst)f(HDU)i(\(the)f(primary)f(arra)m(y\))0 4425 y(is)g(op)s(ened.)46 b(The)32 b(HDU)h(lo)s(cation)h(sp)s (eci\014er)e(is)h(required)f(if)g(the)h(colFilter,)i(ro)m(wFilter,)g (or)e(binSp)s(ec)e(sp)s(eci\014ers)0 4538 y(are)f(presen)m(t,)f(b)s (ecause)h(the)f(primary)f(arra)m(y)i(is)f(not)h(a)f(v)-5 b(alid)30 b(HDU)g(for)f(these)g(op)s(erations.)41 b(The)29 b(HDU)h(ma)m(y)g(b)s(e)0 4650 y(sp)s(eci\014ed)e(either)i(b)m(y)e (absolute)i(p)s(osition)f(n)m(um)m(b)s(er,)f(starting)i(with)e(0)i(for) e(the)h(primary)f(arra)m(y)-8 b(,)31 b(or)e(b)m(y)f(reference)0 4763 y(to)h(the)g(HDU)g(name,)g(and)f(optionally)-8 b(,)31 b(the)e(v)m(ersion)g(n)m(um)m(b)s(er)e(and)h(the)h(HDU)g(t)m(yp)s(e)g (of)f(the)h(desired)f(extension.)0 4876 y(The)k(lo)s(cation)h(of)f(an)g (image)i(within)d(a)i(single)f(cell)i(of)e(a)g(binary)g(table)h(ma)m(y) f(also)h(b)s(e)f(sp)s(eci\014ed,)g(as)g(describ)s(ed)0 4989 y(b)s(elo)m(w.)0 5149 y(The)26 b(absolute)h(p)s(osition)f(of)g (the)h(extension)g(is)f(sp)s(eci\014ed)f(either)i(b)m(y)f(enclosed)h (the)g(n)m(um)m(b)s(er)e(in)h(square)f(brac)m(k)m(ets)0 5262 y(\(e.g.,)k(`[1]')g(=)d(the)h(\014rst)f(extension)h(follo)m(wing)i (the)e(primary)e(arra)m(y\))j(or)f(b)m(y)f(preceded)h(the)g(n)m(um)m(b) s(er)e(with)i(a)g(plus)0 5375 y(sign)37 b(\(`+1'\).)63 b(T)-8 b(o)38 b(sp)s(ecify)f(the)g(HDU)h(b)m(y)g(name,)h(giv)m(e)g(the) e(name)h(of)f(the)h(desired)f(HDU)h(\(the)f(v)-5 b(alue)38 b(of)g(the)0 5488 y(EXTNAME)e(or)g(HDUNAME)h(k)m(eyw)m(ord\))g(and)f (optionally)h(the)f(extension)h(v)m(ersion)f(n)m(um)m(b)s(er)f(\(v)-5 b(alue)37 b(of)f(the)0 5601 y(EXTVER)27 b(k)m(eyw)m(ord\))i(and)e(the)h (extension)h(t)m(yp)s(e)e(\(v)-5 b(alue)29 b(of)f(the)g(XTENSION)f(k)m (eyw)m(ord:)40 b(IMA)m(GE,)29 b(ASCI)s(I)d(or)0 5714 y(T)-8 b(ABLE,)36 b(or)f(BINT)-8 b(ABLE\),)36 b(separated)f(b)m(y)g (commas)h(and)e(all)i(enclosed)g(in)f(square)g(brac)m(k)m(ets.)56 b(If)34 b(the)h(v)-5 b(alue)p eop end %%Page: 91 97 TeXDict begin 91 96 bop 0 299 a Fg(8.8.)72 b(IMA)m(GE)31 b(SECTION)2835 b Fi(91)0 555 y(of)34 b(EXTVER)f(and)f(XTENSION)h(are)h (not)f(sp)s(eci\014ed,)h(then)f(the)h(\014rst)e(extension)j(with)e(the) g(correct)i(v)-5 b(alue)34 b(of)0 668 y(EXTNAME)39 b(is)g(op)s(ened.)67 b(The)38 b(extension)i(name)f(and)f(t)m(yp)s(e)i(are)f(not)h(case)g (sensitiv)m(e,)j(and)38 b(the)h(extension)0 781 y(t)m(yp)s(e)29 b(ma)m(y)g(b)s(e)f(abbreviated)h(to)g(a)g(single)g(letter)h(\(e.g.,)h (I)d(=)g(IMA)m(GE)i(extension)f(or)f(primary)g(arra)m(y)-8 b(,)30 b(A)f(or)f(T)g(=)0 894 y(ASCI)s(I)d(table)i(extension,)h(and)e (B)h(=)f(binary)g(table)h(BINT)-8 b(ABLE)27 b(extension\).)41 b(If)26 b(the)g(HDU)h(lo)s(cation)i(sp)s(eci\014er)0 1007 y(is)h(equal)h(to)g(`[PRIMAR)-8 b(Y]')32 b(or)f(`[P]',)g(then)f (the)h(primary)e(arra)m(y)i(\(the)g(\014rst)f(HDU\))h(will)g(b)s(e)f (op)s(ened.)0 1167 y(FITS)k(images)i(are)f(most)h(commonly)f(stored)g (in)g(the)g(primary)f(arra)m(y)h(or)g(an)g(image)h(extension,)h(but)d (images)0 1280 y(can)d(also)h(b)s(e)e(stored)h(as)h(a)f(v)m(ector)h(in) f(a)g(single)h(cell)g(of)f(a)h(binary)e(table)i(\(i.e.)43 b(eac)m(h)32 b(ro)m(w)f(of)g(the)h(v)m(ector)g(column)0 1393 y(con)m(tains)d(a)g(di\013eren)m(t)f(image\).)42 b(Suc)m(h)27 b(an)h(image)i(can)e(b)s(e)g(op)s(ened)f(with)h(CFITSIO)e (b)m(y)i(sp)s(ecifying)g(the)g(desired)0 1506 y(column)k(name)g(and)f (the)h(ro)m(w)g(n)m(um)m(b)s(er)f(after)h(the)g(binary)f(table)i(HDU)g (sp)s(eci\014er)e(as)h(sho)m(wn)g(in)f(the)h(follo)m(wing)0 1619 y(examples.)71 b(The)40 b(column)g(name)h(is)f(separated)h(from)f (the)h(HDU)g(sp)s(eci\014er)f(b)m(y)g(a)h(semicolon)g(and)f(the)h(ro)m (w)0 1732 y(n)m(um)m(b)s(er)29 b(is)h(enclosed)h(in)e(paren)m(theses.) 41 b(In)30 b(this)g(case)h(CFITSIO)d(copies)j(the)f(image)i(from)d(the) i(table)g(cell)g(in)m(to)0 1844 y(a)h(temp)s(orary)e(primary)h(arra)m (y)g(b)s(efore)g(it)h(is)f(op)s(ened.)43 b(The)30 b(application)j (program)e(then)g(just)g(sees)g(the)h(image)0 1957 y(in)i(the)h (primary)e(arra)m(y)-8 b(,)37 b(without)d(an)m(y)h(extensions.)53 b(The)34 b(particular)g(ro)m(w)h(to)g(b)s(e)e(op)s(ened)h(ma)m(y)h(b)s (e)f(sp)s(eci\014ed)0 2070 y(either)28 b(b)m(y)f(giving)h(an)f (absolute)h(in)m(teger)h(ro)m(w)f(n)m(um)m(b)s(er)e(\(starting)i(with)f (1)h(for)f(the)g(\014rst)g(ro)m(w\),)i(or)e(b)m(y)g(sp)s(ecifying)0 2183 y(a)33 b(b)s(o)s(olean)f(expression)g(that)h(ev)-5 b(aluates)34 b(to)f(TR)m(UE)g(for)f(the)g(desired)g(ro)m(w.)47 b(The)32 b(\014rst)f(ro)m(w)i(that)g(satis\014es)g(the)0 2296 y(expression)28 b(will)g(b)s(e)g(used.)39 b(The)28 b(ro)m(w)g(selection)i(expression)e(has)g(the)g(same)g(syn)m(tax)h(as)f (describ)s(ed)f(in)h(the)g(Ro)m(w)0 2409 y(Filter)k(Sp)s(eci\014er)d (section,)j(b)s(elo)m(w.)0 2569 y(Examples:)143 2811 y Fe(myfile.fits[3])44 b(-)k(open)e(the)h(3rd)g(HDU)g(following)e(the)i (primary)f(array)143 2924 y(myfile.fits+3)92 b(-)48 b(same)e(as)h (above,)f(but)h(using)g(the)g(FTOOLS-style)d(notation)143 3037 y(myfile.fits[EVENTS])f(-)k(open)g(the)g(extension)e(that)i(has)g (EXTNAME)e(=)j('EVENTS')143 3150 y(myfile.fits[EVENTS,)43 b(2])95 b(-)47 b(same)g(as)g(above,)f(but)h(also)g(requires)e(EXTVER)h (=)i(2)143 3263 y(myfile.fits[events,2,b])42 b(-)47 b(same,)f(but)h (also)g(requires)f(XTENSION)f(=)j('BINTABLE')143 3376 y(myfile.fits[3;)c(images\(17\)])h(-)i(opens)g(the)g(image)f(in)h(row)g (17)g(of)g(the)g('images')1527 3489 y(column)f(in)i(the)e(3rd)h (extension)f(of)h(the)g(file.)143 3602 y(myfile.fits[3;)d (images\(exposure)g(>)j(100\)])g(-)g(as)g(above,)f(but)h(opens)g(the)f (image)907 3714 y(in)h(the)g(first)f(row)h(that)g(has)g(an)g ('exposure')e(column)h(value)907 3827 y(greater)g(than)g(100.)0 4158 y Fd(8.8)135 b(Image)46 b(Section)0 4408 y Fi(A)41 b(virtual)g(\014le)f(con)m(taining)i(a)f(rectangular)h(subsection)e(of) h(an)g(image)g(can)g(b)s(e)f(extracted)i(and)e(op)s(ened)g(b)m(y)0 4521 y(sp)s(ecifying)32 b(the)h(range)g(of)g(pixels)g(\(start:end\))g (along)h(eac)m(h)g(axis)f(to)g(b)s(e)f(extracted)i(from)e(the)h (original)g(image.)0 4634 y(One)d(can)h(also)h(sp)s(ecify)e(an)h (optional)h(pixel)f(incremen)m(t)g(\(start:end:step\))h(for)f(eac)m(h)h (axis)f(of)g(the)g(input)e(image.)0 4747 y(A)f(pixel)f(step)h(=)f(1)h (will)g(b)s(e)f(assumed)f(if)i(it)g(is)f(not)h(sp)s(eci\014ed.)39 b(If)27 b(the)h(start)g(pixel)g(is)f(larger)i(then)e(the)h(end)e (pixel,)0 4860 y(then)32 b(the)g(image)h(will)f(b)s(e)f(\015ipp)s(ed)f (\(pro)s(ducing)h(a)h(mirror)g(image\))h(along)g(that)f(dimension.)45 b(An)32 b(asterisk,)h('*',)0 4973 y(ma)m(y)39 b(b)s(e)e(used)h(to)h(sp) s(ecify)f(the)g(en)m(tire)h(range)g(of)f(an)h(axis,)i(and)c('-*')j (will)e(\015ip)g(the)g(en)m(tire)h(axis.)65 b(The)38 b(input)0 5086 y(image)31 b(can)f(b)s(e)f(in)g(the)h(primary)f(arra)m (y)-8 b(,)31 b(in)e(an)g(image)i(extension,)g(or)f(con)m(tained)g(in)g (a)g(v)m(ector)h(cell)g(of)f(a)g(binary)0 5199 y(table.)40 b(In)25 b(the)h(later)h(2)f(cases)h(the)f(extension)h(name)f(or)f(n)m (um)m(b)s(er)g(m)m(ust)h(b)s(e)f(sp)s(eci\014ed)g(b)s(efore)h(the)g (image)h(section)0 5312 y(sp)s(eci\014er.)0 5472 y(Examples:)95 5714 y Fe(myfile.fits[1:512:2,)43 b(2:512:2])i(-)95 b(open)47 b(a)h(256x256)d(pixel)i(image)p eop end %%Page: 92 98 TeXDict begin 92 97 bop 0 299 a Fi(92)1618 b Fg(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)668 555 y Fe(consisting)45 b(of)i(the)g(odd)g(numbered)f(columns)g(\(1st)g (axis\))h(and)668 668 y(the)g(even)g(numbered)e(rows)i(\(2nd)g(axis\))f (of)h(the)g(image)f(in)i(the)668 781 y(primary)e(array)g(of)i(the)e (file.)95 1007 y(myfile.fits[*,)e(512:256])i(-)h(open)g(an)g(image)g (consisting)e(of)i(all)g(the)g(columns)668 1120 y(in)g(the)g(input)g (image,)f(but)h(only)f(rows)h(256)g(through)f(512.)668 1233 y(The)h(image)f(will)h(be)g(flipped)f(along)g(the)h(2nd)g(axis)g (since)668 1346 y(the)g(starting)f(pixel)g(is)h(greater)f(than)h(the)g (ending)f(pixel.)95 1571 y(myfile.fits[*:2,)e(512:256:2])h(-)i(same)g (as)g(above)f(but)h(keeping)f(only)668 1684 y(every)h(other)f(row)h (and)g(column)f(in)h(the)g(input)f(image.)95 1910 y(myfile.fits[-*,)e (*])j(-)h(copy)e(the)h(entire)f(image,)g(flipping)g(it)h(along)668 2023 y(the)g(first)f(axis.)95 2249 y(myfile.fits[3][1:256,1:256)o(])c (-)47 b(opens)g(a)g(subsection)e(of)i(the)g(image)g(that)668 2362 y(is)g(in)h(the)e(3rd)h(extension)f(of)h(the)g(file.)95 2588 y(myfile.fits[4;)d(images\(12\)][1:10,1:10])e(-)48 b(open)e(an)h(image)g(consisting)286 2700 y(of)h(the)e(first)h(10)g (pixels)f(in)h(both)g(dimensions.)e(The)i(original)286 2813 y(image)g(resides)f(in)h(the)g(12th)f(row)h(of)g(the)g('images')f (vector)286 2926 y(column)g(in)i(the)f(table)f(in)h(the)g(4th)g (extension)e(of)i(the)g(file.)0 3203 y Fi(When)23 b(CFITSIO)f(op)s(ens) h(an)g(image)h(section)h(it)f(\014rst)f(creates)h(a)g(temp)s(orary)f (\014le)h(con)m(taining)h(the)e(image)i(section)0 3315 y(plus)32 b(a)i(cop)m(y)g(of)g(an)m(y)g(other)f(HDUs)h(in)f(the)h (\014le.)50 b(This)32 b(temp)s(orary)h(\014le)h(is)f(then)g(op)s(ened)g (b)m(y)g(the)h(application)0 3428 y(program,)28 b(so)g(it)g(is)f(not)h (p)s(ossible)f(to)h(write)g(to)g(or)g(mo)s(dify)f(the)g(input)g(\014le) g(when)g(sp)s(ecifying)g(an)h(image)h(section.)0 3541 y(Note)39 b(that)f(CFITSIO)e(automatically)k(up)s(dates)d(the)g(w)m (orld)h(co)s(ordinate)g(system)g(k)m(eyw)m(ords)f(in)g(the)h(header)0 3654 y(of)33 b(the)h(image)g(section,)h(if)e(they)h(exist,)h(so)e(that) h(the)f(co)s(ordinate)h(asso)s(ciated)h(with)e(eac)m(h)h(pixel)f(in)g (the)h(image)0 3767 y(section)e(will)e(b)s(e)g(computed)g(correctly)-8 b(.)0 4120 y Fd(8.9)135 b(Image)46 b(T)-11 b(ransform)45 b(Filters)0 4374 y Fi(CFITSIO)33 b(can)h(apply)g(a)h(user-sp)s (eci\014ed)e(mathematical)j(function)e(to)h(the)g(v)-5 b(alue)34 b(of)h(ev)m(ery)g(pixel)f(in)g(a)h(FITS)0 4487 y(image,)29 b(th)m(us)e(creating)h(a)g(new)e(virtual)h(image)i(in)d (computer)h(memory)g(that)h(is)f(then)f(op)s(ened)h(and)f(read)h(b)m(y) g(the)0 4600 y(application)32 b(program.)40 b(The)30 b(original)i(FITS)d(image)j(is)e(not)h(mo)s(di\014ed)e(b)m(y)h(this)h (pro)s(cess.)0 4760 y(The)20 b(image)j(transformation)e(sp)s(eci\014er) f(is)h(app)s(ended)e(to)j(the)f(input)f(FITS)h(\014le)g(name)g(and)f (is)h(enclosed)h(in)e(square)0 4873 y(brac)m(k)m(ets.)42 b(It)29 b(b)s(egins)f(with)h(the)g(letters)i('PIX')e(to)h(distinguish)e (it)i(from)e(other)i(t)m(yp)s(es)f(of)g(FITS)f(\014le)h(\014lters)g (that)0 4986 y(are)36 b(recognized)i(b)m(y)e(CFITSIO.)e(The)i(image)h (transforming)f(function)f(ma)m(y)i(use)f(an)m(y)g(of)g(the)h (mathematical)0 5099 y(op)s(erators)44 b(listed)h(in)f(the)h(follo)m (wing)h('Ro)m(w)f(Filtering)g(Sp)s(eci\014cation')g(section)h(of)e (this)h(do)s(cumen)m(t.)82 b(Some)0 5212 y(examples)31 b(of)f(image)i(transform)e(\014lters)g(are:)48 5488 y Fe([pix)46 b(X)i(*)f(2.0])715 b(-)48 b(multiply)d(each)i(pixel)f(by)h (2.0)48 5601 y([pix)f(sqrt\(X\)])714 b(-)48 b(take)e(the)h(square)f (root)h(of)g(each)g(pixel)48 5714 y([pix)f(X)i(+)f(#ZEROPT)571 b(-)48 b(add)e(the)h(value)g(of)g(the)g(ZEROPT)f(keyword)p eop end %%Page: 93 99 TeXDict begin 93 98 bop 0 299 a Fg(8.9.)72 b(IMA)m(GE)31 b(TRANSF)m(ORM)g(FIL)-8 b(TERS)2237 b Fi(93)48 555 y Fe([pix)46 b(X>0)h(?)h(log10\(X\))d(:)j(-99.])e(-)i(if)f(the)g(pixel)f (value)g(is)i(greater)1480 668 y(than)e(0,)h(compute)f(the)h(base)g(10) g(log,)1480 781 y(else)f(set)h(the)g(pixel)f(=)i(-99.)0 1013 y Fi(Use)24 b(the)g(letter)h('X')f(in)f(the)h(expression)g(to)g (represen)m(t)g(the)g(curren)m(t)f(pixel)h(v)-5 b(alue)24 b(in)f(the)h(image.)40 b(The)23 b(expression)0 1126 y(is)38 b(ev)-5 b(aluated)39 b(indep)s(enden)m(tly)e(for)g(eac)m(h)i(pixel)f (in)g(the)g(image)h(and)e(ma)m(y)h(b)s(e)g(a)g(function)f(of)h(1\))h (the)f(original)0 1239 y(pixel)32 b(v)-5 b(alue,)32 b(2\))g(the)f(v)-5 b(alue)32 b(of)f(other)h(pixels)f(in)g(the)g(image)i(at)f(a)f(giv)m(en) i(relativ)m(e)g(o\013set)f(from)f(the)g(p)s(osition)h(of)0 1352 y(the)d(pixel)f(that)h(is)g(b)s(eing)f(ev)-5 b(aluated,)30 b(and)e(3\))h(the)g(v)-5 b(alue)29 b(of)f(an)m(y)h(header)f(k)m(eyw)m (ords.)41 b(Header)29 b(k)m(eyw)m(ord)g(v)-5 b(alues)0 1465 y(are)31 b(represen)m(ted)f(b)m(y)g(the)h(name)f(of)h(the)f(k)m (eyw)m(ord)h(preceded)f(b)m(y)h(the)f('#')h(sign.)0 1625 y(T)-8 b(o)35 b(access)h(the)f(the)g(v)-5 b(alue)35 b(of)g(adjacen)m(t) h(pixels)f(in)f(the)h(image,)i(sp)s(ecify)e(the)g(\(1-D\))h(o\013set)g (from)e(the)h(curren)m(t)0 1738 y(pixel)c(in)f(curly)g(brac)m(k)m(ets.) 42 b(F)-8 b(or)31 b(example)48 1970 y Fe([pix)94 b(\(x{-1})46 b(+)i(x)f(+)h(x{+1}\))e(/)h(3])0 2202 y Fi(will)25 b(replace)g(eac)m(h) h(pixel)f(v)-5 b(alue)25 b(with)f(the)h(running)e(mean)i(of)f(the)h(v) -5 b(alues)25 b(of)g(that)g(pixel)g(and)f(it's)h(2)g(neigh)m(b)s(oring) 0 2314 y(pixels.)40 b(Note)30 b(that)g(in)e(this)g(notation)i(the)f (image)h(is)f(treated)g(as)g(a)g(1-D)h(arra)m(y)-8 b(,)30 b(where)e(eac)m(h)i(ro)m(w)f(of)g(the)g(image)0 2427 y(\(or)c(higher)f(dimensional)g(cub)s(e\))h(is)f(app)s(ended)f(one)h (after)h(another)g(in)f(one)h(long)g(arra)m(y)g(of)f(pixels.)39 b(It)25 b(is)f(p)s(ossible)0 2540 y(to)35 b(refer)f(to)h(pixels)f(in)g (the)g(ro)m(ws)g(ab)s(o)m(v)m(e)h(or)g(b)s(elo)m(w)f(the)g(curren)m(t)g (pixel)h(b)m(y)f(using)f(the)h(v)-5 b(alue)35 b(of)f(the)h(NAXIS1)0 2653 y(header)30 b(k)m(eyw)m(ord.)41 b(F)-8 b(or)32 b(example)48 2885 y Fe([pix)46 b(\(x{-#NAXIS1})f(+)i(x)h(+)f(x{#NAXIS1}\))e(/)i(3])0 3117 y Fi(will)34 b(compute)f(the)h(mean)f(of)g(eac)m(h)i(image)f (pixel)g(and)e(the)i(pixels)f(immediately)i(ab)s(o)m(v)m(e)f(and)f(b)s (elo)m(w)g(it)h(in)f(the)0 3230 y(adjacen)m(t)27 b(ro)m(ws)f(of)g(the)f (image.)41 b(The)25 b(follo)m(wing)i(more)f(complex)h(example)f (creates)h(a)f(smo)s(othed)g(virtual)g(image)0 3343 y(where)k(eac)m(h)h (pixel)g(is)g(a)f(3)h(x)f(3)h(b)s(o)m(xcar)g(a)m(v)m(erage)i(of)d(the)h (input)e(image)j(pixels:)95 3575 y Fe([pix)47 b(\(X)g(+)h(X{-1})e(+)i (X{+1})286 3688 y(+)g(X{-#NAXIS1})d(+)i(X{-#NAXIS1)e(-)i(1})h(+)f (X{-#NAXIS1)e(+)j(1})286 3801 y(+)g(X{#NAXIS1})d(+)i(X{#NAXIS1)f(-)h (1})g(+)h(X{#NAXIS1)d(+)i(1}\))g(/)h(9.])0 4033 y Fi(If)31 b(the)h(pixel)g(o\013set)h(extends)f(b)s(ey)m(ond)f(the)h(\014rst)f(or) h(last)h(pixel)f(in)f(the)h(image,)i(the)e(function)g(will)g(ev)-5 b(aluate)33 b(to)0 4145 y(unde\014ned,)28 b(or)j(NULL.)0 4306 y(F)-8 b(or)39 b(complex)g(or)g(commonly)g(used)e(image)j (\014ltering)f(op)s(erations,)i(one)d(can)h(write)g(the)f(expression)h (in)m(to)g(an)0 4419 y(external)i(text)h(\014le)f(and)f(then)g(imp)s (ort)g(it)h(in)m(to)h(the)e(\014lter)h(using)f(the)h(syn)m(tax)g('[pix) g(@\014lename.txt]'.)72 b(The)0 4531 y(mathematical)29 b(expression)e(can)g(extend)g(o)m(v)m(er)i(m)m(ultiple)e(lines)g(of)h (text)g(in)e(the)h(\014le.)40 b(An)m(y)27 b(lines)g(in)g(the)g (external)0 4644 y(text)h(\014le)e(that)i(b)s(egin)e(with)g(2)h(slash)f (c)m(haracters)i(\('//'\))h(will)e(b)s(e)f(ignored)h(and)f(ma)m(y)h(b)s (e)f(used)g(to)h(add)f(commen)m(ts)0 4757 y(in)m(to)31 b(the)g(\014le.)0 4917 y(By)c(default,)g(the)f(datat)m(yp)s(e)i(of)e (the)g(resulting)h(image)g(will)g(b)s(e)e(the)i(same)f(as)h(the)f (original)i(image,)g(but)e(one)g(ma)m(y)0 5030 y(force)31 b(a)g(di\013eren)m(t)g(datat)m(yp)s(e)g(b)m(y)f(app)s(ended)f(a)h(co)s (de)h(letter)h(to)f(the)f('pix')h(k)m(eyw)m(ord:)286 5262 y Fe(pixb)95 b(-)g(8-bit)46 b(byte)190 b(image)46 b(with)h(BITPIX)f(=)143 b(8)286 5375 y(pixi)95 b(-)47 b(16-bit)f(integer)g(image)g(with)h(BITPIX)f(=)95 b(16)286 5488 y(pixj)g(-)47 b(32-bit)f(integer)g(image)g(with)h(BITPIX)f(=)95 b(32)286 5601 y(pixr)g(-)47 b(32-bit)f(float)142 b(image)46 b(with)h(BITPIX)f(=)i(-32)286 5714 y(pixd)95 b(-)47 b(64-bit)f(float) 142 b(image)46 b(with)h(BITPIX)f(=)i(-64)p eop end %%Page: 94 100 TeXDict begin 94 99 bop 0 299 a Fi(94)1618 b Fg(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fi(Also)23 b(b)m(y)f(default,)j(an)m(y)d(other)h(HDUs)g(in)f(the) g(input)g(\014le)g(will)h(b)s(e)e(copied)i(without)g(c)m(hange)g(to)g (the)g(output)f(virtual)0 668 y(FITS)k(\014le,)h(but)f(one)g(ma)m(y)h (discard)f(the)h(other)f(HDUs)h(b)m(y)f(adding)g(the)h(n)m(um)m(b)s(er) e('1')i(to)g(the)g('pix')f(k)m(eyw)m(ord)h(\(and)0 781 y(follo)m(wing)32 b(an)m(y)f(optional)g(datat)m(yp)s(e)g(co)s(de)g (letter\).)42 b(F)-8 b(or)32 b(example:)239 1044 y Fe (myfile.fits[3][pixr1)90 b(sqrt\(X\)])0 1307 y Fi(will)23 b(create)i(a)e(virtual)g(FITS)f(\014le)h(con)m(taining)h(only)f(a)g (primary)f(arra)m(y)i(image)g(with)e(32-bit)i(\015oating)g(p)s(oin)m(t) f(pixels)0 1420 y(that)29 b(ha)m(v)m(e)h(a)f(v)-5 b(alue)30 b(equal)f(to)g(the)g(square)g(ro)s(ot)g(of)g(the)g(pixels)f(in)h(the)g (image)h(that)f(is)g(in)f(the)h(3rd)f(extension)i(of)0 1533 y(the)h('m)m(y\014le.\014ts')g(\014le.)0 1870 y Fd(8.10)136 b(Column)45 b(and)f(Keyw)l(ord)i(Filtering)g(Sp)t (eci\014cation)0 2121 y Fi(The)27 b(optional)i(column/k)m(eyw)m(ord)g (\014ltering)f(sp)s(eci\014er)f(is)h(used)f(to)i(mo)s(dify)e(the)h (column)g(structure)f(and/or)h(the)0 2234 y(header)38 b(k)m(eyw)m(ords)h(in)f(the)h(HDU)g(that)h(w)m(as)f(selected)h(with)e (the)h(previous)f(HDU)h(lo)s(cation)h(sp)s(eci\014er.)65 b(This)0 2347 y(\014ltering)42 b(sp)s(eci\014er)f(m)m(ust)h(b)s(e)f (enclosed)i(in)e(square)h(brac)m(k)m(ets)h(and)e(can)h(b)s(e)f (distinguished)g(from)h(a)g(general)0 2460 y(ro)m(w)d(\014lter)g(sp)s (eci\014er)f(\(describ)s(ed)g(b)s(elo)m(w\))h(b)m(y)g(the)g(fact)h (that)f(it)g(b)s(egins)f(with)h(the)g(string)g('col)h(')f(and)f(is)h (not)0 2573 y(immediately)30 b(follo)m(w)m(ed)g(b)m(y)e(an)g(equals)h (sign.)40 b(The)28 b(original)h(\014le)f(is)h(not)f(c)m(hanged)h(b)m(y) f(this)h(\014ltering)f(op)s(eration,)0 2686 y(and)40 b(instead)h(the)g(mo)s(di\014cations)g(are)g(made)f(on)h(a)g(cop)m(y)g (of)g(the)g(input)f(FITS)g(\014le)g(\(usually)h(in)f(memory\),)0 2799 y(whic)m(h)33 b(also)h(con)m(tains)g(a)f(cop)m(y)h(of)f(all)h(the) g(other)f(HDUs)h(in)e(the)h(\014le.)49 b(This)33 b(temp)s(orary)f (\014le)h(is)g(passed)g(to)h(the)0 2912 y(application)f(program)f(and)f (will)h(p)s(ersist)f(only)h(un)m(til)g(the)g(\014le)g(is)g(closed)h(or) f(un)m(til)g(the)g(program)f(exits,)j(unless)0 3025 y(the)d(out\014le)f (sp)s(eci\014er)g(\(see)h(ab)s(o)m(v)m(e\))h(is)f(also)g(supplied.)0 3185 y(The)g(column/k)m(eyw)m(ord)h(\014lter)f(can)g(b)s(e)g(used)f(to) i(p)s(erform)e(the)i(follo)m(wing)g(op)s(erations.)44 b(More)32 b(than)f(one)g(op)s(er-)0 3298 y(ation)g(ma)m(y)g(b)s(e)f(sp) s(eci\014ed)g(b)m(y)g(separating)h(them)f(with)h(commas)f(or)h (semi-colons.)136 3561 y Fc(\017)46 b Fi(Cop)m(y)36 b(only)g(a)g(sp)s (eci\014ed)g(list)g(of)g(columns)g(columns)f(to)i(the)f(\014ltered)g (input)f(\014le.)57 b(The)36 b(list)g(of)g(column)227 3673 y(name)41 b(should)e(b)s(e)g(separated)i(b)m(y)f(commas)h(or)f (semi-colons.)72 b(Wild)41 b(card)f(c)m(haracters)h(ma)m(y)g(b)s(e)f (used)227 3786 y(in)e(the)f(column)h(names)g(to)g(matc)m(h)g(m)m (ultiple)h(columns.)62 b(If)37 b(the)h(expression)g(con)m(tains)g(b)s (oth)f(a)h(list)h(of)227 3899 y(columns)29 b(to)h(b)s(e)f(included)g (and)g(columns)g(to)h(b)s(e)e(deleted,)j(then)e(all)h(the)g(columns)f (in)g(the)h(original)g(table)227 4012 y(except)36 b(the)e(explicitly)i (deleted)f(columns)f(will)h(app)s(ear)e(in)h(the)h(\014ltered)f(table)h (\(i.e.,)i(there)e(is)f(no)g(need)227 4125 y(to)d(explicitly)h(list)f (the)g(columns)f(to)h(b)s(e)f(included)f(if)i(an)m(y)f(columns)h(are)f (b)s(eing)g(deleted\).)136 4316 y Fc(\017)46 b Fi(Delete)32 b(a)d(column)g(or)g(k)m(eyw)m(ord)h(b)m(y)f(listing)h(the)f(name)g (preceded)g(b)m(y)g(a)g(min)m(us)g(sign)g(or)g(an)g(exclamation)227 4429 y(mark)c(\(!\),)h(e.g.,)i('-TIME')d(will)g(delete)h(the)e(TIME)h (column)f(if)g(it)i(exists,)g(otherwise)f(the)g(TIME)f(k)m(eyw)m(ord.) 227 4542 y(An)35 b(error)f(is)h(returned)e(if)i(neither)f(a)i(column)e (nor)g(k)m(eyw)m(ord)h(with)g(this)f(name)h(exists.)54 b(Note)36 b(that)g(the)227 4655 y(exclamation)27 b(p)s(oin)m(t,)g(')10 b(!',)27 b(is)e(a)g(sp)s(ecial)h(UNIX)f(c)m(haracter,)j(so)d(if)g(it)h (is)f(used)f(on)h(the)g(command)g(line)g(rather)227 4768 y(than)33 b(en)m(tered)h(at)g(a)g(task)g(prompt,)f(it)h(m)m(ust)f(b)s (e)g(preceded)g(b)m(y)g(a)h(bac)m(kslash)g(to)g(force)g(the)f(UNIX)h (shell)227 4881 y(to)d(ignore)g(it.)136 5071 y Fc(\017)46 b Fi(Rename)29 b(an)g(existing)g(column)f(or)h(k)m(eyw)m(ord)g(with)f (the)h(syn)m(tax)g('NewName)h(==)e(OldName'.)40 b(An)28 b(error)227 5184 y(is)j(returned)e(if)h(neither)h(a)f(column)g(nor)g(k) m(eyw)m(ord)h(with)f(this)h(name)f(exists.)136 5375 y Fc(\017)46 b Fi(App)s(end)37 b(a)j(new)f(column)f(or)i(k)m(eyw)m(ord)f (to)h(the)f(table.)68 b(T)-8 b(o)40 b(create)g(a)g(column,)h(giv)m(e)g (the)e(new)g(name,)227 5488 y(optionally)e(follo)m(w)m(ed)g(b)m(y)e (the)g(datat)m(yp)s(e)h(in)f(paren)m(theses,)i(follo)m(w)m(ed)g(b)m(y)e (a)h(single)g(equals)f(sign)g(and)g(an)227 5601 y(expression)g(to)h(b)s (e)e(used)g(to)i(compute)f(the)g(v)-5 b(alue)35 b(\(e.g.,)j('new)m (col\(1J\))f(=)e(0')g(will)h(create)g(a)f(new)g(32-bit)227 5714 y(in)m(teger)k(column)e(called)i('new)m(col')f(\014lled)g(with)f (zeros\).)62 b(The)37 b(datat)m(yp)s(e)h(is)g(sp)s(eci\014ed)e(using)h (the)h(same)p eop end %%Page: 95 101 TeXDict begin 95 100 bop 0 299 a Fg(8.10.)73 b(COLUMN)30 b(AND)h(KEYW)m(ORD)g(FIL)-8 b(TERING)30 b(SPECIFICA)-8 b(TION)1075 b Fi(95)227 555 y(syn)m(tax)28 b(that)h(is)e(allo)m(w)m(ed) j(for)d(the)h(v)-5 b(alue)28 b(of)g(the)g(FITS)f(TF)m(ORMn)g(k)m(eyw)m (ord)h(\(e.g.,)i('I',)f('J',)f('E',)g('D',)h(etc.)227 668 y(for)37 b(binary)f(tables,)k(and)c('I8',)k(F12.3',)h('E20.12',)g (etc.)62 b(for)37 b(ASCI)s(I)e(tables\).)62 b(If)37 b(the)g(datat)m(yp) s(e)h(is)f(not)227 781 y(sp)s(eci\014ed)24 b(then)f(an)h(appropriate)h (datat)m(yp)s(e)g(will)f(b)s(e)g(c)m(hosen)g(dep)s(ending)f(on)h(the)g (form)g(of)g(the)g(expression)227 894 y(\(ma)m(y)f(b)s(e)d(a)i(c)m (haracter)h(string,)h(logical,)h(bit,)f(long)e(in)m(teger,)j(or)c (double)g(column\).)38 b(An)21 b(appropriate)g(v)m(ector)227 1007 y(coun)m(t)31 b(\(in)g(the)f(case)i(of)e(binary)g(tables\))h(will) g(also)g(b)s(e)f(added)g(if)g(not)h(explicitly)h(sp)s(eci\014ed.)227 1154 y(When)26 b(creating)h(a)f(new)f(k)m(eyw)m(ord,)j(the)e(k)m(eyw)m (ord)g(name)g(m)m(ust)g(b)s(e)f(preceded)g(b)m(y)h(a)g(p)s(ound)e(sign) h('#',)j(and)227 1267 y(the)h(expression)f(m)m(ust)g(ev)-5 b(aluate)30 b(to)f(a)g(scalar)g(\(i.e.,)h(cannot)f(ha)m(v)m(e)h(a)f (column)f(name)g(in)g(the)h(expression\).)227 1380 y(The)j(commen)m(t)i (string)f(for)f(the)h(k)m(eyw)m(ord)h(ma)m(y)f(b)s(e)f(sp)s(eci\014ed)g (in)g(paren)m(theses)h(immediately)h(follo)m(wing)227 1493 y(the)29 b(k)m(eyw)m(ord)f(name)g(\(instead)h(of)f(supplying)f(a)h (datat)m(yp)s(e)h(as)g(in)e(the)i(case)g(of)f(creating)h(a)g(new)f (column\).)227 1606 y(If)c(the)h(k)m(eyw)m(ord)g(name)f(ends)g(with)g (a)h(p)s(ound)d(sign)i('#',)i(then)e(c\014tsio)i(will)e(substitute)h (the)f(n)m(um)m(b)s(er)f(of)i(the)227 1719 y(most)31 b(recen)m(tly)h(referenced)e(column)h(for)f(the)h(#)f(c)m(haracter)i(.) 41 b(This)29 b(is)i(esp)s(ecially)h(useful)d(when)h(writing)227 1831 y(a)c(column-related)g(k)m(eyw)m(ord)g(lik)m(e)g(TUNITn)e(for)h(a) h(newly)f(created)h(column,)g(as)g(sho)m(wn)e(in)h(the)g(follo)m(wing) 227 1944 y(examples.)227 2092 y(COMMENT)30 b(and)g(HISTOR)-8 b(Y)30 b(k)m(eyw)m(ords)g(ma)m(y)h(also)h(b)s(e)e(created)h(with)f(the) h(follo)m(wing)g(syn)m(tax:)370 2320 y Fe(#COMMENT)46 b(=)h('This)g(is)g(a)g(comment)f(keyword')370 2433 y(#HISTORY)g(=)h ('This)g(is)g(a)g(history)f(keyword')227 2661 y Fi(Note)d(that)f(the)f (equal)h(sign)f(and)f(the)i(quote)f(c)m(haracters)i(will)f(b)s(e)e (remo)m(v)m(ed,)45 b(so)d(that)f(the)h(resulting)227 2774 y(header)30 b(k)m(eyw)m(ords)h(in)f(these)h(cases)g(will)g(lo)s (ok)g(lik)m(e)h(this:)370 3002 y Fe(COMMENT)46 b(This)h(is)g(a)h (comment)d(keyword)370 3115 y(HISTORY)h(This)h(is)g(a)h(history)d (keyword)227 3343 y Fi(These)29 b(t)m(w)m(o)h(sp)s(ecial)f(k)m(eyw)m (ords)h(are)f(alw)m(a)m(ys)h(app)s(ended)d(to)j(the)f(end)f(of)h(the)g (header)g(and)f(will)h(not)g(a\013ect)227 3456 y(an)m(y)i(previously)f (existing)h(COMMENT)f(or)h(HISTOR)-8 b(Y)30 b(k)m(eyw)m(ords.)136 3637 y Fc(\017)46 b Fi(Recompute)f(\(o)m(v)m(erwrite\))i(the)d(v)-5 b(alues)44 b(in)g(an)g(existing)i(column)e(or)g(k)m(eyw)m(ord)g(b)m(y)g (giving)i(the)e(name)227 3750 y(follo)m(w)m(ed)32 b(b)m(y)f(an)f (equals)h(sign)f(and)g(an)g(arithmetic)i(expression.)0 3991 y(The)23 b(expression)g(that)i(is)e(used)g(when)g(app)s(ending)f (or)h(recomputing)h(columns)f(or)h(k)m(eyw)m(ords)g(can)g(b)s(e)f (arbitrarily)0 4104 y(complex)36 b(and)g(ma)m(y)g(b)s(e)f(a)h(function) g(of)g(other)g(header)g(k)m(eyw)m(ord)g(v)-5 b(alues)36 b(and)f(other)h(columns)g(\(in)g(the)g(same)0 4217 y(ro)m(w\).)63 b(The)37 b(full)g(syn)m(tax)i(and)e(a)m(v)-5 b(ailable)40 b(functions)d(for)g(the)h(expression)f(are)h(describ)s(ed)f(b)s(elo)m (w)h(in)f(the)h(ro)m(w)0 4330 y(\014lter)30 b(sp)s(eci\014cation)i (section.)0 4490 y(If)27 b(the)h(expression)g(con)m(tains)g(b)s(oth)f (a)h(list)h(of)f(columns)f(to)h(b)s(e)g(included)e(and)i(columns)f(to)h (b)s(e)f(deleted,)j(then)d(all)0 4603 y(the)34 b(columns)g(in)g(the)g (original)h(table)g(except)g(the)f(explicitly)i(deleted)f(columns)e (will)i(app)s(ear)e(in)h(the)g(\014ltered)0 4716 y(table.)40 b(If)26 b(no)g(columns)f(to)i(b)s(e)f(deleted)g(are)h(sp)s(eci\014ed,)f (then)g(only)g(the)h(columns)e(that)i(are)f(explicitly)i(listed)f(will) 0 4829 y(b)s(e)k(included)g(in)g(the)h(\014ltered)f(output)h(table.)45 b(T)-8 b(o)32 b(include)f(all)i(the)e(columns,)h(add)f(the)h('*')g (wildcard)g(sp)s(eci\014er)0 4942 y(at)f(the)g(end)e(of)i(the)f(list,)i (as)e(sho)m(wn)g(in)g(the)h(examples.)0 5102 y(F)-8 b(or)30 b(complex)h(or)e(commonly)h(used)f(op)s(erations,)i(one)e(can)h(also)h (place)g(the)e(op)s(erations)h(in)m(to)h(an)e(external)i(text)0 5215 y(\014le)g(and)f(imp)s(ort)g(it)h(in)m(to)h(the)f(column)g (\014lter)f(using)h(the)g(syn)m(tax)g('[col)h(@\014lename.txt]'.)43 b(The)31 b(op)s(erations)g(can)0 5328 y(extend)k(o)m(v)m(er)h(m)m (ultiple)g(lines)f(of)g(the)g(\014le,)h(but)e(m)m(ultiple)i(op)s (erations)f(m)m(ust)f(still)i(b)s(e)e(separated)i(b)m(y)e(commas)0 5441 y(or)e(semi-colons.)47 b(An)m(y)32 b(lines)h(in)f(the)g(external)h (text)g(\014le)f(that)h(b)s(egin)e(with)h(2)h(slash)e(c)m(haracters)j (\('//'\))g(will)f(b)s(e)0 5554 y(ignored)d(and)g(ma)m(y)h(b)s(e)f (used)g(to)h(add)e(commen)m(ts)j(in)m(to)f(the)g(\014le.)0 5714 y(Examples:)p eop end %%Page: 96 102 TeXDict begin 96 101 bop 0 299 a Fi(96)1618 b Fg(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)143 555 y Fe([col)47 b(Time,)f(rate])667 b(-)47 b(only)g(the)g(Time)g(and)g (rate)f(columns)g(will)1670 668 y(appear)h(in)g(the)g(filtered)e(input) i(file.)143 894 y([col)g(Time,)f(*raw])667 b(-)47 b(include)f(the)h (Time)g(column)f(and)h(any)g(other)1670 1007 y(columns)f(whose)h(name)f (ends)h(with)g('raw'.)143 1233 y([col)g(-TIME;)f(Good)h(==)g(STATUS]) 141 b(-)47 b(deletes)f(the)h(TIME)g(column)f(and)1670 1346 y(renames)g(the)h(status)f(column)g(to)i('Good')143 1571 y([col)f(PI=PHA)f(*)h(1.1)g(+)h(0.2;)e(#TUNIT#\(column)e(units\))i (=)i('counts';*])1575 1684 y(-)f(creates)f(new)h(PI)g(column)f(from)h (PHA)g(values)1670 1797 y(and)g(also)g(writes)f(the)h(TUNITn)f(keyword) 1670 1910 y(for)h(the)g(new)g(column.)94 b(The)47 b(final)f('*')1670 2023 y(expression)f(means)i(preserve)e(all)i(the)1670 2136 y(columns)f(in)h(the)g(input)g(table)f(in)h(the)1670 2249 y(virtual)f(output)g(table;)94 b(without)46 b(the)h('*')1670 2362 y(the)g(output)f(table)h(would)f(only)h(contain)1670 2475 y(the)g(single)f('PI')h(column.)143 2700 y([col)g(rate)f(=)i (rate/exposure,)c(TUNIT#\(&\))h(=)j('counts/s';*])1575 2813 y(-)f(recomputes)e(the)i(rate)g(column)f(by)h(dividing)1670 2926 y(it)h(by)f(the)g(EXPOSURE)e(keyword)h(value.)g(This)1670 3039 y(also)h(modifies)f(the)h(value)f(of)h(the)g(TUNITn)1670 3152 y(keyword)f(for)h(this)g(column.)f(The)h(use)f(of)i(the)1670 3265 y('&')f(character)f(for)h(the)f(keyword)g(comment)1670 3378 y(string)h(means)f(preserve)f(the)i(existing)1670 3491 y(comment)f(string)g(for)h(that)g(keyword.)e(The)1670 3604 y(final)i('*')g(preserves)e(all)i(the)g(columns)1670 3717 y(in)h(the)f(input)f(table)g(in)h(the)g(virtual)1670 3830 y(output)g(table.)0 4400 y Fd(8.11)136 b(Ro)l(w)45 b(Filtering)h(Sp)t(eci\014cation)0 4698 y Fi(When)29 b(en)m(tering)h(the)f(name)g(of)g(a)g(FITS)f(table)i(that)g(is)e(to)i (b)s(e)e(op)s(ened)h(b)m(y)f(a)i(program,)f(an)g(optional)h(ro)m(w)f (\014lter)0 4811 y(ma)m(y)i(b)s(e)g(sp)s(eci\014ed)f(to)h(select)h(a)g (subset)e(of)h(the)g(ro)m(ws)f(in)h(the)g(table.)43 b(A)31 b(temp)s(orary)f(new)g(FITS)g(\014le)h(is)g(created)0 4924 y(on)25 b(the)h(\015y)e(whic)m(h)h(con)m(tains)h(only)g(those)g (ro)m(ws)f(for)g(whic)m(h)g(the)g(ro)m(w)g(\014lter)h(expression)f(ev) -5 b(aluates)26 b(to)g(true.)39 b(\(The)0 5036 y(primary)26 b(arra)m(y)h(and)f(an)m(y)g(other)h(extensions)g(in)f(the)h(input)f (\014le)g(are)h(also)h(copied)f(to)g(the)f(temp)s(orary)h(\014le\).)39 b(The)0 5149 y(original)30 b(FITS)f(\014le)g(is)g(closed)h(and)e(the)i (new)e(virtual)i(\014le)f(is)g(op)s(ened)f(b)m(y)h(the)h(application)g (program.)40 b(The)29 b(ro)m(w)0 5262 y(\014lter)37 b(expression)g(is)h (enclosed)g(in)f(square)g(brac)m(k)m(ets)i(follo)m(wing)g(the)e(\014le) h(name)f(and)g(extension)h(name)f(\(e.g.,)0 5375 y('\014le.\014ts[ev)m (en)m(ts][GRADE==50]')29 b(selects)d(only)f(those)h(ro)m(ws)f(where)f (the)h(GRADE)h(column)f(v)-5 b(alue)25 b(equals)g(50\).)0 5488 y(When)33 b(dealing)h(with)f(tables)g(where)g(eac)m(h)h(ro)m(w)f (has)g(an)g(asso)s(ciated)i(time)f(and/or)f(2D)g(spatial)i(p)s (osition,)f(the)0 5601 y(ro)m(w)e(\014lter)h(expression)e(can)i(also)g (b)s(e)f(used)f(to)i(select)h(ro)m(ws)e(based)g(on)g(the)g(times)h(in)f (a)g(Go)s(o)s(d)g(Time)g(In)m(terv)-5 b(als)0 5714 y(\(GTI\))31 b(extension,)g(or)f(on)h(spatial)g(p)s(osition)g(as)f(giv)m(en)i(in)e (a)g(SA)m(O-st)m(yle)i(region)f(\014le.)p eop end %%Page: 97 103 TeXDict begin 97 102 bop 0 299 a Fg(8.11.)73 b(R)m(O)m(W)31 b(FIL)-8 b(TERING)30 b(SPECIFICA)-8 b(TION)2027 b Fi(97)0 555 y Fb(8.11.1)113 b(General)38 b(Syn)m(tax)0 774 y Fi(The)32 b(ro)m(w)h(\014ltering)g(expression)g(can)g(b)s(e)f(an)h (arbitrarily)g(complex)g(series)g(of)g(op)s(erations)g(p)s(erformed)f (on)g(con-)0 887 y(stan)m(ts,)39 b(k)m(eyw)m(ord)e(v)-5 b(alues,)38 b(and)e(column)g(data)i(tak)m(en)f(from)f(the)h(sp)s (eci\014ed)e(FITS)h(T)-8 b(ABLE)37 b(extension.)59 b(The)0 1000 y(expression)37 b(m)m(ust)h(ev)-5 b(aluate)39 b(to)g(a)f(b)s(o)s (olean)g(v)-5 b(alue)38 b(for)f(eac)m(h)i(ro)m(w)f(of)g(the)f(table,)k (where)c(a)h(v)-5 b(alue)39 b(of)e(F)-10 b(ALSE)0 1113 y(means)30 b(that)h(the)g(ro)m(w)f(will)h(b)s(e)f(excluded.)0 1273 y(F)-8 b(or)34 b(complex)g(or)g(commonly)f(used)g(\014lters,)h (one)g(can)g(place)g(the)g(expression)f(in)m(to)h(a)g(text)g(\014le)g (and)f(imp)s(ort)f(it)0 1386 y(in)m(to)38 b(the)e(ro)m(w)h(\014lter)g (using)f(the)h(syn)m(tax)g('[@\014lename.txt]'.)61 b(The)36 b(expression)h(can)f(b)s(e)g(arbitrarily)h(complex)0 1499 y(and)27 b(extend)i(o)m(v)m(er)g(m)m(ultiple)g(lines)f(of)g(the)h (\014le.)40 b(An)m(y)28 b(lines)g(in)g(the)g(external)h(text)g(\014le)f (that)h(b)s(egin)f(with)g(2)g(slash)0 1612 y(c)m(haracters)k(\('//'\))g (will)f(b)s(e)f(ignored)g(and)g(ma)m(y)h(b)s(e)f(used)f(to)i(add)f (commen)m(ts)h(in)m(to)h(the)e(\014le.)0 1772 y(Keyw)m(ord)37 b(and)f(column)g(data)i(are)f(referenced)g(b)m(y)g(name.)60 b(An)m(y)37 b(string)f(of)h(c)m(haracters)i(not)e(surrounded)d(b)m(y)0 1885 y(quotes)41 b(\(ie,)j(a)d(constan)m(t)h(string\))f(or)f(follo)m(w) m(ed)i(b)m(y)f(an)f(op)s(en)g(paren)m(theses)h(\(ie,)j(a)d(function)f (name\))h(will)g(b)s(e)0 1998 y(initially)d(in)m(terpreted)e(as)h(a)g (column)f(name)g(and)g(its)h(con)m(ten)m(ts)h(for)e(the)h(curren)m(t)f (ro)m(w)g(inserted)g(in)m(to)i(the)e(ex-)0 2111 y(pression.)k(If)28 b(no)h(suc)m(h)g(column)g(exists,)h(a)g(k)m(eyw)m(ord)f(of)h(that)f (name)g(will)h(b)s(e)e(searc)m(hed)i(for)f(and)f(its)i(v)-5 b(alue)29 b(used,)0 2223 y(if)36 b(found.)55 b(T)-8 b(o)36 b(force)g(the)g(name)g(to)h(b)s(e)e(in)m(terpreted)h(as)g(a)g(k)m(eyw)m (ord)g(\(in)g(case)g(there)g(is)g(b)s(oth)f(a)h(column)g(and)0 2336 y(k)m(eyw)m(ord)41 b(with)e(the)i(same)f(name\),)j(precede)d(the)h (k)m(eyw)m(ord)f(name)g(with)g(a)h(single)f(p)s(ound)e(sign,)43 b('#',)g(as)d(in)0 2449 y('#NAXIS2'.)g(Due)27 b(to)g(the)f (generalities)j(of)d(FITS)g(column)g(and)g(k)m(eyw)m(ord)h(names,)g(if) f(the)h(column)f(or)g(k)m(eyw)m(ord)0 2562 y(name)33 b(con)m(tains)h(a)f(space)h(or)f(a)g(c)m(haracter)h(whic)m(h)f(migh)m (t)h(app)s(ear)e(as)h(an)g(arithmetic)h(term)f(then)g(enclose)h(the)0 2675 y(name)c(in)g('$')i(c)m(haracters)g(as)e(in)g($MAX)i(PHA$)f(or)f (#$MAX-PHA$.)43 b(Names)31 b(are)f(case)i(insensitiv)m(e.)0 2835 y(T)-8 b(o)32 b(access)g(a)g(table)g(en)m(try)g(in)f(a)h(ro)m(w)f (other)h(than)f(the)g(curren)m(t)g(one,)h(follo)m(w)h(the)e(column's)h (name)f(with)g(a)h(ro)m(w)0 2948 y(o\013set)37 b(within)e(curly)g (braces.)57 b(F)-8 b(or)36 b(example,)i('PHA)p Fc(f)p Fi(-3)p Fc(g)p Fi(')g(will)e(ev)-5 b(aluate)38 b(to)e(the)g(v)-5 b(alue)36 b(of)g(column)f(PHA,)i(3)0 3061 y(ro)m(ws)28 b(ab)s(o)m(v)m(e)i(the)e(ro)m(w)h(curren)m(tly)f(b)s(eing)g(pro)s (cessed.)40 b(One)28 b(cannot)h(sp)s(ecify)f(an)g(absolute)h(ro)m(w)f (n)m(um)m(b)s(er,)g(only)h(a)0 3174 y(relativ)m(e)j(o\013set.)42 b(Ro)m(ws)31 b(that)g(fall)g(outside)g(the)f(table)h(will)g(b)s(e)f (treated)h(as)g(unde\014ned,)d(or)j(NULLs.)0 3334 y(Bo)s(olean)h(op)s (erators)f(can)g(b)s(e)f(used)f(in)i(the)f(expression)h(in)f(either)h (their)g(F)-8 b(ortran)31 b(or)f(C)h(forms.)40 b(The)30 b(follo)m(wing)0 3447 y(b)s(o)s(olean)g(op)s(erators)h(are)g(a)m(v)-5 b(ailable:)191 3698 y Fe("equal")428 b(.eq.)46 b(.EQ.)h(==)95 b("not)46 b(equal")476 b(.ne.)94 b(.NE.)h(!=)191 3811 y("less)46 b(than")238 b(.lt.)46 b(.LT.)h(<)143 b("less)46 b(than/equal")188 b(.le.)94 b(.LE.)h(<=)47 b(=<)191 3923 y("greater)e(than")95 b(.gt.)46 b(.GT.)h(>)143 b("greater)45 b(than/equal")g(.ge.)94 b(.GE.)h(>=)47 b(=>)191 4036 y("or")572 b(.or.)46 b(.OR.)h(||)95 b("and")762 b(.and.)46 b(.AND.)h(&&)191 4149 y("negation")236 b(.not.)46 b(.NOT.)h(!)95 b("approx.)45 b(equal\(1e-7\)")92 b(~)0 4400 y Fi(Note)32 b(that)g(the)f(exclamation)i(p)s(oin)m(t,)e(')10 b(!',)33 b(is)e(a)g(sp)s(ecial)g(UNIX)h(c)m(haracter,)h(so)e(if)g(it)g(is)g (used)f(on)h(the)g(command)0 4513 y(line)i(rather)f(than)h(en)m(tered)g (at)g(a)g(task)g(prompt,)g(it)g(m)m(ust)f(b)s(e)g(preceded)h(b)m(y)f(a) h(bac)m(kslash)g(to)h(force)f(the)g(UNIX)0 4626 y(shell)e(to)g(ignore)g (it.)0 4786 y(The)h(expression)g(ma)m(y)i(also)f(include)f(arithmetic)i (op)s(erators)f(and)f(functions.)47 b(T)-8 b(rigonometric)34 b(functions)e(use)0 4899 y(radians,)23 b(not)g(degrees.)38 b(The)22 b(follo)m(wing)h(arithmetic)g(op)s(erators)g(and)e(functions)g (can)i(b)s(e)e(used)g(in)h(the)g(expression)0 5012 y(\(function)38 b(names)f(are)h(case)g(insensitiv)m(e\).)64 b(A)37 b(n)m(ull)h(v)-5 b(alue)38 b(will)f(b)s(e)g(returned)g(in)g(case)h(of)g(illegal)i(op)s (erations)0 5125 y(suc)m(h)30 b(as)h(divide)f(b)m(y)g(zero,)i (sqrt\(negativ)m(e\))h(log\(negativ)m(e\),)h(log10\(negativ)m(e\),)i (arccos\(.gt.)43 b(1\),)32 b(arcsin\(.gt.)42 b(1\).)191 5375 y Fe("addition")522 b(+)477 b("subtraction")d(-)191 5488 y("multiplication")234 b(*)477 b("division")618 b(/)191 5601 y("negation")522 b(-)477 b("exponentiation")330 b(**)143 b(^)191 5714 y("absolute)45 b(value")237 b(abs\(x\))g ("cosine")714 b(cos\(x\))p eop end %%Page: 98 104 TeXDict begin 98 103 bop 0 299 a Fi(98)1618 b Fg(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)191 555 y Fe("sine")714 b(sin\(x\))237 b("tangent")666 b(tan\(x\))191 668 y("arc)47 b(cosine")427 b(arccos\(x\))93 b("arc)47 b(sine")619 b(arcsin\(x\))191 781 y("arc)47 b(tangent")379 b(arctan\(x\))93 b("arc)47 b(tangent")475 b(arctan2\(y,x\))191 894 y("hyperbolic)45 b(cos")237 b(cosh\(x\))189 b("hyperbolic)45 b(sin")333 b(sinh\(x\))191 1007 y("hyperbolic)45 b(tan")237 b(tanh\(x\))189 b("round)46 b(to)h(nearest)f(int")h(round\(x\))191 1120 y("round)f(down)h(to)g(int")94 b(floor\(x\))141 b("round)46 b(up)h(to)h(int")285 b(ceil\(x\))191 1233 y("exponential")378 b(exp\(x\))237 b("square)46 b(root")476 b(sqrt\(x\))191 1346 y("natural)45 b(log")381 b(log\(x\))237 b("common)46 b(log")524 b(log10\(x\))191 1458 y("modulus")570 b(x)48 b(\045)f(y)286 b("random)46 b(#)h([0.0,1.0\)")141 b(random\(\))191 1571 y("random)46 b(Gaussian")188 b(randomn\(\))93 b("random)46 b(Poisson")332 b(randomp\(x\))191 1684 y("minimum")570 b(min\(x,y\))141 b("maximum")666 b(max\(x,y\))191 1797 y("cumulative)45 b(sum")237 b(accum\(x\))93 b("sequential)45 b(difference")g(seqdiff\(x\))191 1910 y("if-then-else")330 b(b?x:y)191 2023 y("angular)45 b(separation")93 b (angsep\(ra1,dec1,ra2,de2\))41 b(\(all)47 b(in)g(degrees\))191 2136 y("substring")283 b(strmid\(s,p,n\))44 b("string)i(search")428 b(strstr\(s,r\))0 2382 y Fi(Three)30 b(di\013eren)m(t)h(random)f(n)m (um)m(b)s(er)f(functions)h(are)h(pro)m(vided:)41 b(random\(\),)30 b(with)h(no)f(argumen)m(ts,)h(pro)s(duces)f(a)0 2495 y(uniform)g(random)f(deviate)k(b)s(et)m(w)m(een)e(0)g(and)f(1;)i (randomn\(\),)e(also)i(with)e(no)h(argumen)m(ts,)g(pro)s(duces)f(a)h (normal)0 2608 y(\(Gaussian\))k(random)e(deviate)j(with)e(zero)h(mean)f (and)g(unit)f(standard)h(deviation;)j(randomp\(x\))d(pro)s(duces)f(a)0 2721 y(P)m(oisson)27 b(random)f(deviate)h(whose)f(exp)s(ected)h(n)m(um) m(b)s(er)e(of)h(coun)m(ts)h(is)g(X.)f(X)h(ma)m(y)g(b)s(e)e(an)m(y)i(p)s (ositiv)m(e)g(real)g(n)m(um)m(b)s(er)0 2833 y(of)k(exp)s(ected)f(coun)m (ts,)h(including)f(fractional)i(v)-5 b(alues,)31 b(but)f(the)g(return)g (v)-5 b(alue)31 b(is)f(an)g(in)m(teger.)0 2994 y(When)d(the)g(random)g (functions)f(are)i(used)e(in)h(a)h(v)m(ector)g(expression,)g(b)m(y)f (default)h(the)f(same)h(random)e(v)-5 b(alue)28 b(will)0 3107 y(b)s(e)g(used)f(when)h(ev)-5 b(aluating)30 b(eac)m(h)f(elemen)m (t)h(of)f(the)g(v)m(ector.)41 b(If)28 b(di\013eren)m(t)h(random)f(n)m (um)m(b)s(ers)f(are)i(desired,)f(then)0 3219 y(the)37 b(name)g(of)g(a)g(v)m(ector)i(column)e(should)e(b)s(e)i(supplied)e(as)i (the)h(single)f(argumen)m(t)g(to)h(the)f(random)f(function)0 3332 y(\(e.g.,)31 b("\015ux)c(+)h(0.1)h(*)g(random\(\015ux\)",)f(where) g("\015ux')g(is)g(the)g(name)h(of)f(a)h(v)m(ector)h(column\).)40 b(This)27 b(will)i(create)h(a)0 3445 y(v)m(ector)d(of)f(random)f(n)m (um)m(b)s(ers)f(that)i(will)g(b)s(e)f(used)f(in)i(sequence)g(when)e(ev) -5 b(aluating)27 b(eac)m(h)g(elemen)m(t)g(of)f(the)f(v)m(ector)0 3558 y(expression.)0 3718 y(An)31 b(alternate)i(syn)m(tax)f(for)f(the)g (min)g(and)g(max)g(functions)g(has)g(only)g(a)h(single)g(argumen)m(t)g (whic)m(h)f(should)f(b)s(e)h(a)0 3831 y(v)m(ector)g(v)-5 b(alue)30 b(\(see)g(b)s(elo)m(w\).)41 b(The)29 b(result)g(will)h(b)s(e) e(the)i(minim)m(um/maxim)m(um)f(elemen)m(t)h(con)m(tained)h(within)e (the)0 3944 y(v)m(ector.)0 4104 y(The)35 b(accum\(x\))i(function)f (forms)f(the)h(cum)m(ulativ)m(e)i(sum)d(of)h(x,)h(elemen)m(t)h(b)m(y)e (elemen)m(t.)58 b(V)-8 b(ector)38 b(columns)e(are)0 4217 y(supp)s(orted)h(simply)h(b)m(y)g(p)s(erforming)f(the)i(summation)g (pro)s(cess)f(through)f(all)j(the)f(v)-5 b(alues.)65 b(Null)39 b(v)-5 b(alues)39 b(are)0 4330 y(treated)30 b(as)f(0.)41 b(The)29 b(seqdi\013\(x\))h(function)e(forms)h(the)g (sequen)m(tial)i(di\013erence)e(of)h(x,)f(elemen)m(t)i(b)m(y)e(elemen)m (t.)41 b(The)0 4443 y(\014rst)36 b(v)-5 b(alue)38 b(of)f(seqdi\013)g (is)g(the)g(\014rst)g(v)-5 b(alue)37 b(of)g(x.)61 b(A)37 b(single)h(n)m(ull)f(v)-5 b(alue)38 b(in)e(x)h(causes)h(a)f(pair)g(of)g (n)m(ulls)g(in)g(the)0 4556 y(output.)55 b(The)35 b(seqdi\013)g(and)g (accum)g(functions)g(are)h(functional)f(in)m(v)m(erses,)j(i.e.,)g (seqdi\013\(accum\(x\)\))f(==)e(x)g(as)0 4669 y(long)c(as)g(no)f(n)m (ull)g(v)-5 b(alues)31 b(are)g(presen)m(t.)0 4829 y(In)36 b(the)h(if-then-else)i(expression,)f("b?x:y",)i(b)c(is)h(an)g(explicit) h(b)s(o)s(olean)f(v)-5 b(alue)37 b(or)g(expression.)61 b(There)36 b(is)h(no)0 4942 y(automatic)d(t)m(yp)s(e)e(con)m(v)m (ersion)h(from)e(n)m(umeric)h(to)g(b)s(o)s(olean)g(v)-5 b(alues,)33 b(so)f(one)g(needs)f(to)i(use)e("iV)-8 b(al!=0")35 b(instead)0 5055 y(of)30 b(merely)g("iV)-8 b(al")32 b(as)e(the)g(b)s(o) s(olean)g(argumen)m(t.)41 b(x)30 b(and)f(y)h(can)g(b)s(e)f(an)m(y)h (scalar)h(data)g(t)m(yp)s(e)f(\(including)f(string\).)0 5215 y(The)22 b(angsep)g(function)f(computes)i(the)f(angular)g (separation)h(in)e(degrees)i(b)s(et)m(w)m(een)g(2)f(celestial)j(p)s (ositions,)e(where)0 5328 y(the)36 b(\014rst)f(2)h(parameters)g(giv)m (e)h(the)f(RA-lik)m(e)i(and)d(Dec-lik)m(e)j(co)s(ordinates)f(\(in)f (decimal)g(degrees\))h(of)f(the)g(\014rst)0 5441 y(p)s(osition,)31 b(and)e(the)i(3rd)f(and)g(4th)g(parameters)h(giv)m(e)h(the)e(co)s (ordinates)i(of)e(the)h(second)f(p)s(osition.)0 5601 y(The)38 b(substring)f(function)i(strmid\(S,P)-8 b(,N\))39 b(extracts)g(a)g(substring)f(from)g(S,)g(starting)h(at)g(string)g(p)s (osition)f(P)-8 b(,)0 5714 y(with)33 b(a)h(substring)f(length)h(N.)g (The)f(\014rst)g(c)m(haracter)j(p)s(osition)d(in)h(S)f(is)h(lab)s(eled) g(as)g(1.)51 b(If)33 b(P)g(is)h(0,)h(or)f(refers)f(to)p eop end %%Page: 99 105 TeXDict begin 99 104 bop 0 299 a Fg(8.11.)73 b(R)m(O)m(W)31 b(FIL)-8 b(TERING)30 b(SPECIFICA)-8 b(TION)2027 b Fi(99)0 555 y(a)35 b(p)s(osition)g(b)s(ey)m(ond)f(the)h(end)e(of)i(S,)g(then)f (the)h(extracted)h(substring)d(will)i(b)s(e)f(NULL.)h(S,)f(P)-8 b(,)36 b(and)e(N)g(ma)m(y)i(b)s(e)0 668 y(functions)30 b(of)g(other)h(columns.)0 828 y(The)39 b(string)h(searc)m(h)h(function) e(strstr\(S,R\))h(searc)m(hes)h(for)f(the)g(\014rst)f(o)s(ccurrence)h (of)g(the)g(substring)f(R)h(in)f(S.)0 941 y(The)c(result)h(is)f(an)h (in)m(teger,)i(indicating)f(the)e(c)m(haracter)i(p)s(osition)f(of)g (the)g(\014rst)e(matc)m(h)j(\(where)e(1)h(is)g(the)g(\014rst)0 1054 y(c)m(haracter)c(p)s(osition)e(of)h(S\).)f(If)g(no)h(matc)m(h)g (is)f(found,)g(then)g(strstr\(\))g(returns)f(a)i(NULL)f(v)-5 b(alue.)0 1214 y(The)37 b(follo)m(wing)i(t)m(yp)s(e)f(casting)g(op)s (erators)g(are)g(a)m(v)-5 b(ailable,)42 b(where)37 b(the)h(enclosing)g (paren)m(theses)g(are)g(required)0 1327 y(and)30 b(tak)m(en)h(from)f (the)h(C)f(language)h(usage.)42 b(Also,)31 b(the)g(in)m(teger)g(to)h (real)f(casts)g(v)-5 b(alues)30 b(to)i(double)e(precision:)764 1593 y Fe("real)46 b(to)h(integer")189 b(\(int\))46 b(x)239 b(\(INT\))46 b(x)764 1706 y("integer)f(to)i(real")190 b(\(float\))46 b(i)143 b(\(FLOAT\))45 b(i)0 1972 y Fi(In)30 b(addition,)g(sev)m(eral)i(constan)m(ts)g(are)f(built)f(in)g(for)g(use) g(in)g(n)m(umerical)h(expressions:)382 2238 y Fe(#pi)667 b(3.1415...)284 b(#e)620 b(2.7182...)382 2351 y(#deg)f(#pi/180)380 b(#row)524 b(current)46 b(row)h(number)382 2464 y(#null)428 b(undefined)45 b(value)142 b(#snull)428 b(undefined)45 b(string)0 2730 y Fi(A)40 b(string)f(constan)m(t)i(m)m(ust)e(b)s(e)g (enclosed)h(in)g(quotes)g(as)f(in)h('Crab'.)67 b(The)39 b("n)m(ull")i(constan)m(ts)f(are)g(useful)f(for)0 2843 y(conditionally)g(setting)g(table)g(v)-5 b(alues)38 b(to)g(a)g(NULL,)g (or)g(unde\014ned,)f(v)-5 b(alue)39 b(\(eg.,)i("col1==-99)f(?)62 b(#NULL)38 b(:)0 2955 y(col1"\).)0 3116 y(There)27 b(is)g(also)i(a)e (function)g(for)h(testing)g(if)f(t)m(w)m(o)i(v)-5 b(alues)28 b(are)g(close)g(to)h(eac)m(h)f(other,)h(i.e.,)g(if)e(they)h(are)g ("near")g(eac)m(h)0 3229 y(other)c(to)h(within)e(a)h(user)g(sp)s (eci\014ed)f(tolerance.)40 b(The)24 b(argumen)m(ts,)h(v)-5 b(alue)p 2502 3229 28 4 v 34 w(1)24 b(and)f(v)-5 b(alue)p 2979 3229 V 33 w(2)25 b(can)f(b)s(e)f(in)m(teger)i(or)f(real)0 3341 y(and)32 b(represen)m(t)h(the)g(t)m(w)m(o)h(v)-5 b(alues)33 b(who's)f(pro)m(ximit)m(y)i(is)f(b)s(eing)f(tested)h(to)h(b) s(e)e(within)g(the)h(sp)s(eci\014ed)f(tolerance,)0 3454 y(also)f(an)g(in)m(teger)g(or)g(real:)955 3720 y Fe(near\(value_1,)44 b(value_2,)h(tolerance\))0 3986 y Fi(When)24 b(a)i(NULL,)e(or)h (unde\014ned,)f(v)-5 b(alue)25 b(is)g(encoun)m(tered)g(in)g(the)f(FITS) g(table,)j(the)e(expression)g(will)g(ev)-5 b(aluate)26 b(to)0 4099 y(NULL)31 b(unless)f(the)h(unde\014ned)e(v)-5 b(alue)31 b(is)g(not)g(actually)h(required)e(for)h(ev)-5 b(aluation,)33 b(e.g.)43 b("TR)m(UE)31 b(.or.)43 b(NULL")0 4212 y(ev)-5 b(aluates)32 b(to)f(TR)m(UE.)g(The)f(follo)m(wing)h(t)m(w) m(o)h(functions)e(allo)m(w)i(some)f(NULL)f(detection)i(and)e(handling:) 430 4478 y Fe("a)47 b(null)f(value?")667 b(ISNULL\(x\))430 4591 y("define)45 b(a)j(value)e(for)h(null")190 b(DEFNULL\(x,y\))0 4857 y Fi(The)36 b(former)h(returns)e(a)i(b)s(o)s(olean)g(v)-5 b(alue)37 b(of)g(TR)m(UE)g(if)g(the)g(argumen)m(t)g(x)g(is)g(NULL.)g (The)f(later)i("de\014nes")f(a)0 4970 y(v)-5 b(alue)35 b(to)g(b)s(e)e(substituted)h(for)g(NULL)g(v)-5 b(alues;)37 b(it)e(returns)e(the)h(v)-5 b(alue)35 b(of)f(x)g(if)g(x)h(is)f(not)g (NULL,)h(otherwise)f(it)0 5083 y(returns)29 b(the)i(v)-5 b(alue)31 b(of)f(y)-8 b(.)0 5381 y Fb(8.11.2)113 b(Bit)36 b(Masks)0 5601 y Fi(Bit)g(masks)f(can)h(b)s(e)f(used)f(to)i(select)h (out)e(ro)m(ws)h(from)e(bit)i(columns)f(\(TF)m(ORMn)g(=)g(#X\))h(in)f (FITS)f(\014les.)55 b(T)-8 b(o)0 5714 y(represen)m(t)30 b(the)h(mask,)g(binary)-8 b(,)30 b(o)s(ctal,)i(and)e(hex)g(formats)g (are)h(allo)m(w)m(ed:)p eop end %%Page: 100 106 TeXDict begin 100 105 bop 0 299 a Fi(100)1573 b Fg(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)811 555 y Fe(binary:)142 b(b0110xx1010000101xxxx00)o(01)811 668 y(octal:)190 b(o720x1)46 b(->)h(\(b111010000xxx001\))811 781 y(hex:)286 b(h0FxD)94 b(->)47 b(\(b00001111xxxx1101\))0 1038 y Fi(In)22 b(all)i(the)f(represen)m(tations,)j(an)c(x)h(or)g(X)g (is)g(allo)m(w)m(ed)i(in)d(the)h(mask)g(as)g(a)h(wild)e(card.)38 b(Note)25 b(that)e(the)g(x)g(represen)m(ts)0 1151 y(a)k(di\013eren)m(t) h(n)m(um)m(b)s(er)e(of)h(wild)f(card)h(bits)g(in)g(eac)m(h)h(represen)m (tation.)41 b(All)27 b(represen)m(tations)h(are)g(case)g(insensitiv)m (e.)0 1311 y(T)-8 b(o)28 b(construct)g(the)g(b)s(o)s(olean)f (expression)h(using)f(the)h(mask)f(as)h(the)g(b)s(o)s(olean)f(equal)h (op)s(erator)g(describ)s(ed)f(ab)s(o)m(v)m(e)0 1424 y(on)34 b(a)h(bit)g(table)h(column.)53 b(F)-8 b(or)35 b(example,)i(if)d(y)m(ou) h(had)f(a)h(7)g(bit)g(column)f(named)g(\015ags)h(in)f(a)h(FITS)f(table) i(and)0 1537 y(w)m(an)m(ted)31 b(all)g(ro)m(ws)g(ha)m(ving)g(the)f(bit) h(pattern)f(0010011,)k(the)c(selection)j(expression)d(w)m(ould)g(b)s (e:)1336 1794 y Fe(flags)47 b(==)g(b0010011)191 1907 y(or)1336 2019 y(flags)g(.eq.)f(b10011)0 2276 y Fi(It)35 b(is)g(also)h(p)s(ossible)e(to)i(test)g(if)f(a)g(range)g(of)g(bits)g (is)g(less)g(than,)h(less)f(than)g(equal,)i(greater)f(than)e(and)h (greater)0 2389 y(than)30 b(equal)h(to)g(a)g(particular)g(b)s(o)s (olean)f(v)-5 b(alue:)1336 2646 y Fe(flags)47 b(<=)g(bxxx010xx)1336 2759 y(flags)g(.gt.)f(bxxx100xx)1336 2872 y(flags)h(.le.)f(b1xxxxxxx)0 3129 y Fi(Notice)32 b(the)f(use)f(of)h(the)f(x)g(bit)h(v)-5 b(alue)31 b(to)g(limit)g(the)f(range)h(of)g(bits)f(b)s(eing)g (compared.)0 3289 y(It)i(is)h(not)f(necessary)h(to)g(sp)s(ecify)f(the)h (leading)g(\(most)g(signi\014can)m(t\))h(zero)f(\(0\))g(bits)f(in)g (the)h(mask,)g(as)g(sho)m(wn)e(in)0 3402 y(the)g(second)f(expression)g (ab)s(o)m(v)m(e.)0 3562 y(Bit)44 b(wise)f(AND,)h(OR)e(and)g(NOT)h(op)s (erations)g(are)g(also)h(p)s(ossible)e(on)h(t)m(w)m(o)h(or)f(more)g (bit)g(\014elds)f(using)h(the)0 3675 y('&'\(AND\),)35 b(')p Fc(j)p Fi('\(OR\),)g(and)e(the)h(')10 b(!'\(NOT\))34 b(op)s(erators.)51 b(All)34 b(of)f(these)h(op)s(erators)g(result)f(in)h (a)g(bit)f(\014eld)g(whic)m(h)0 3788 y(can)e(then)f(b)s(e)f(used)h (with)g(the)h(equal)g(op)s(erator.)41 b(F)-8 b(or)31 b(example:)1241 4045 y Fe(\(!flags\))45 b(==)j(b1101100)1241 4158 y(\(flags)e(&)h(b1000001\))f(==)h(bx000001)0 4414 y Fi(Bit)35 b(\014elds)f(can)g(b)s(e)f(app)s(ended)g(as)h(w)m(ell)h (using)f(the)g('+')g(op)s(erator.)53 b(Strings)33 b(can)i(b)s(e)e (concatenated)j(this)e(w)m(a)m(y)-8 b(,)0 4527 y(to)s(o.)0 4818 y Fb(8.11.3)113 b(V)-9 b(ector)36 b(Columns)0 5036 y Fi(V)-8 b(ector)37 b(columns)e(can)h(also)g(b)s(e)f(used)f(in)h (building)g(the)g(expression.)56 b(No)36 b(sp)s(ecial)g(syn)m(tax)f(is) h(required)e(if)i(one)0 5149 y(w)m(an)m(ts)46 b(to)f(op)s(erate)h(on)f (all)h(elemen)m(ts)g(of)f(the)h(v)m(ector.)86 b(Simply)44 b(use)h(the)g(column)g(name)g(as)g(for)g(a)g(scalar)0 5262 y(column.)d(V)-8 b(ector)32 b(columns)f(can)g(b)s(e)f(freely)h(in) m(termixed)h(with)e(scalar)i(columns)e(or)h(constan)m(ts)h(in)f (virtually)g(all)0 5375 y(expressions.)40 b(The)29 b(result)g(will)g(b) s(e)g(of)g(the)g(same)h(dimension)e(as)i(the)f(v)m(ector.)42 b(Tw)m(o)29 b(v)m(ectors)i(in)e(an)g(expression,)0 5488 y(though,)f(need)e(to)i(ha)m(v)m(e)g(the)f(same)g(n)m(um)m(b)s(er)f(of) h(elemen)m(ts)h(and)e(ha)m(v)m(e)j(the)e(same)g(dimensions.)39 b(The)26 b(only)h(places)0 5601 y(a)35 b(v)m(ector)h(column)e(cannot)h (b)s(e)f(used)f(\(for)i(no)m(w,)g(an)m(yw)m(a)m(y\))h(are)f(the)g(SA)m (O)f(region)h(functions)f(and)f(the)i(NEAR)0 5714 y(b)s(o)s(olean)30 b(function.)p eop end %%Page: 101 107 TeXDict begin 101 106 bop 0 299 a Fg(8.11.)73 b(R)m(O)m(W)31 b(FIL)-8 b(TERING)30 b(SPECIFICA)-8 b(TION)1982 b Fi(101)0 555 y(Arithmetic)24 b(and)e(logical)k(op)s(erations)d(are)h(all)g(p)s (erformed)d(on)i(an)g(elemen)m(t)h(b)m(y)f(elemen)m(t)i(basis.)38 b(Comparing)23 b(t)m(w)m(o)0 668 y(v)m(ector)32 b(columns,)e(eg)h ("COL1)f(==)g(COL2",)g(th)m(us)g(results)g(in)g(another)g(v)m(ector)i (of)e(b)s(o)s(olean)h(v)-5 b(alues)30 b(indicating)0 781 y(whic)m(h)g(elemen)m(ts)i(of)e(the)h(t)m(w)m(o)h(v)m(ectors)f(are) g(equal.)0 941 y(Eigh)m(t)g(functions)f(are)h(a)m(v)-5 b(ailable)33 b(that)e(op)s(erate)g(on)f(a)h(v)m(ector)h(and)d(return)h (a)g(scalar)i(result:)191 1172 y Fe("minimum")284 b(MIN\(V\))475 b("maximum")714 b(MAX\(V\))191 1285 y("average")284 b(AVERAGE\(V\))f ("median")762 b(MEDIAN\(V\))191 1398 y("summation")188 b(SUM\(V\))475 b("standard)46 b(deviation")188 b(STDDEV\(V\))191 1511 y("#)47 b(of)g(values")94 b(NELEM\(V\))379 b("#)48 b(of)f(non-null)e(values")94 b(NVALID\(V\))0 1742 y Fi(where)40 b(V)h(represen)m(ts)g(the)g(name)g(of)h(a)f(v)m(ector)h(column)f(or)g (a)h(man)m(ually)f(constructed)g(v)m(ector)i(using)d(curly)0 1854 y(brac)m(k)m(ets)27 b(as)f(describ)s(ed)e(b)s(elo)m(w.)39 b(The)25 b(\014rst)g(6)h(of)g(these)g(functions)f(ignore)h(an)m(y)g(n)m (ull)f(v)-5 b(alues)26 b(in)f(the)h(v)m(ector)h(when)0 1967 y(computing)k(the)f(result.)41 b(The)30 b(STDDEV\(\))h(function)g (computes)f(the)h(sample)g(standard)e(deviation,)j(i.e.)42 b(it)31 b(is)0 2080 y(prop)s(ortional)f(to)h(1/SQR)-8 b(T\(N-1\))32 b(instead)f(of)g(1/SQR)-8 b(T\(N\),)31 b(where)f(N)h(is)f(NV)-10 b(ALID\(V\).)0 2240 y(The)32 b(SUM)h(function)f(literally)j(sums)c(all)j(the)f(elemen)m(ts)h(in)f (x,)g(returning)f(a)h(scalar)h(v)-5 b(alue.)48 b(If)32 b(x)h(is)g(a)g(b)s(o)s(olean)0 2353 y(v)m(ector,)40 b(SUM)c(returns)f (the)h(n)m(um)m(b)s(er)f(of)i(TR)m(UE)f(elemen)m(ts.)60 b(The)36 b(NELEM)g(function)g(returns)f(the)h(n)m(um)m(b)s(er)0 2466 y(of)i(elemen)m(ts)h(in)f(v)m(ector)h(x)f(whereas)f(NV)-10 b(ALID)39 b(return)d(the)i(n)m(um)m(b)s(er)f(of)h(non-n)m(ull)f(elemen) m(ts)j(in)d(the)h(v)m(ector.)0 2579 y(\(NELEM)28 b(also)h(op)s(erates)f (on)g(bit)f(and)g(string)h(columns,)g(returning)f(their)h(column)f (widths.\))40 b(As)27 b(an)h(example,)0 2692 y(to)42 b(test)g(whether)f(all)h(elemen)m(ts)h(of)f(t)m(w)m(o)g(v)m(ectors)h (satisfy)f(a)g(giv)m(en)g(logical)i(comparison,)g(one)e(can)g(use)f (the)0 2805 y(expression)668 3036 y Fe(SUM\()47 b(COL1)f(>)i(COL2)f(\)) g(==)g(NELEM\()f(COL1)h(\))0 3267 y Fi(whic)m(h)32 b(will)g(return)f (TR)m(UE)h(if)g(all)h(elemen)m(ts)g(of)f(COL1)g(are)g(greater)h(than)f (their)g(corresp)s(onding)f(elemen)m(ts)i(in)0 3380 y(COL2.)0 3540 y(T)-8 b(o)32 b(sp)s(ecify)f(a)i(single)f(elemen)m(t)h(of)f(a)g(v) m(ector,)i(giv)m(e)f(the)f(column)f(name)h(follo)m(w)m(ed)h(b)m(y)f(a)g (comma-separated)h(list)0 3653 y(of)c(co)s(ordinates)g(enclosed)h(in)e (square)h(brac)m(k)m(ets.)41 b(F)-8 b(or)30 b(example,)g(if)e(a)h(v)m (ector)i(column)d(named)h(PHAS)f(exists)h(in)0 3766 y(the)e(table)g(as) g(a)g(one)g(dimensional,)h(256)g(comp)s(onen)m(t)f(list)g(of)g(n)m(um)m (b)s(ers)e(from)h(whic)m(h)h(y)m(ou)g(w)m(an)m(ted)g(to)g(select)i(the) 0 3878 y(57th)j(comp)s(onen)m(t)g(for)f(use)g(in)g(the)h(expression,)f (then)h(PHAS[57])g(w)m(ould)f(do)h(the)f(tric)m(k.)45 b(Higher)32 b(dimensional)0 3991 y(arra)m(ys)41 b(of)h(data)f(ma)m(y)h (app)s(ear)f(in)f(a)i(column.)73 b(But)41 b(in)g(order)f(to)i(in)m (terpret)f(them,)j(the)e(TDIMn)e(k)m(eyw)m(ord)0 4104 y(m)m(ust)34 b(app)s(ear)g(in)g(the)g(header.)52 b(Assuming)34 b(that)h(a)f(\(4,4,4,4\))k(arra)m(y)c(is)h(pac)m(k)m(ed)g(in)m(to)g (eac)m(h)h(ro)m(w)e(of)g(a)h(column)0 4217 y(named)26 b(ARRA)-8 b(Y4D,)28 b(the)f(\(1,2,3,4\))i(comp)s(onen)m(t)e(elemen)m(t) g(of)g(eac)m(h)g(ro)m(w)g(is)f(accessed)i(b)m(y)e(ARRA)-8 b(Y4D[1,2,3,4].)0 4330 y(Arra)m(ys)33 b(up)e(to)j(dimension)e(5)h(are)f (curren)m(tly)h(supp)s(orted.)46 b(Eac)m(h)33 b(v)m(ector)h(index)e (can)h(itself)g(b)s(e)f(an)h(expression,)0 4443 y(although)39 b(it)g(m)m(ust)g(ev)-5 b(aluate)40 b(to)f(an)g(in)m(teger)h(v)-5 b(alue)39 b(within)f(the)h(b)s(ounds)d(of)j(the)g(v)m(ector.)67 b(V)-8 b(ector)40 b(columns)0 4556 y(whic)m(h)31 b(con)m(tain)h(spaces) g(or)f(arithmetic)h(op)s(erators)g(m)m(ust)f(ha)m(v)m(e)h(their)f (names)g(enclosed)h(in)f("$")h(c)m(haracters)h(as)0 4669 y(with)d($ARRA)-8 b(Y-4D$[1,2,3,4].)0 4829 y(A)45 b(more)f(C-lik)m(e)i (syn)m(tax)g(for)e(sp)s(ecifying)g(v)m(ector)j(indices)d(is)h(also)h(a) m(v)-5 b(ailable.)85 b(The)45 b(elemen)m(t)h(used)d(in)i(the)0 4942 y(preceding)28 b(example)h(alternativ)m(ely)i(could)d(b)s(e)g(sp)s (eci\014ed)g(with)f(the)i(syn)m(tax)g(ARRA)-8 b(Y4D[4][3][2][1].)45 b(Note)30 b(the)0 5055 y(rev)m(erse)40 b(order)f(of)h(indices)f(\(as)h (in)f(C\),)h(as)f(w)m(ell)i(as)e(the)h(fact)g(that)g(the)g(v)-5 b(alues)40 b(are)f(still)i(ones-based)e(\(as)h(in)0 5168 y(F)-8 b(ortran)39 b({)g(adopted)g(to)g(a)m(v)m(oid)h(am)m(biguit)m(y)g (for)f(1D)g(v)m(ectors\).)67 b(With)39 b(this)g(syn)m(tax,)i(one)e(do)s (es)f(not)h(need)f(to)0 5281 y(sp)s(ecify)30 b(all)h(of)g(the)f (indices.)41 b(T)-8 b(o)31 b(extract)h(a)f(3D)g(slice)g(of)g(this)f(4D) h(arra)m(y)-8 b(,)32 b(use)e(ARRA)-8 b(Y4D[4].)0 5441 y(V)g(ariable-length)33 b(v)m(ector)f(columns)e(are)g(not)h(supp)s (orted.)0 5601 y(V)-8 b(ectors)24 b(can)e(b)s(e)f(man)m(ually)h (constructed)h(within)e(the)h(expression)g(using)f(a)h(comma-separated) i(list)f(of)f(elemen)m(ts)0 5714 y(surrounded)35 b(b)m(y)j(curly)g (braces)h(\(')p Fc(fg)p Fi('\).)66 b(F)-8 b(or)38 b(example,)j(')p Fc(f)p Fi(1,3,6,1)p Fc(g)p Fi(')h(is)d(a)f(4-elemen)m(t)i(v)m(ector)g (con)m(taining)g(the)p eop end %%Page: 102 108 TeXDict begin 102 107 bop 0 299 a Fi(102)1573 b Fg(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fi(v)j(alues)26 b(1,)h(3,)g(6,)g(and)e(1.)40 b(The)25 b(v)m(ector)i(can)f(con)m(tain)h(only)f(b)s(o)s(olean,)g(in)m(teger,)j (and)c(real)h(v)-5 b(alues)26 b(\(or)g(expressions\).)0 668 y(The)e(elemen)m(ts)h(will)g(b)s(e)f(promoted)g(to)h(the)g(highest) f(datat)m(yp)s(e)h(presen)m(t.)39 b(An)m(y)24 b(elemen)m(ts)i(whic)m(h) e(are)h(themselv)m(es)0 781 y(v)m(ectors,)40 b(will)d(b)s(e)f(expanded) g(out)h(with)g(eac)m(h)g(of)g(its)g(elemen)m(ts)i(b)s(ecoming)d(an)h (elemen)m(t)h(in)f(the)g(constructed)0 894 y(v)m(ector.)0 1247 y Fb(8.11.4)113 b(Go)s(o)s(d)38 b(Time)g(In)m(terv)-6 b(al)37 b(Filtering)0 1479 y Fi(A)44 b(common)g(\014ltering)h(metho)s (d)e(in)m(v)m(olv)m(es)j(selecting)g(ro)m(ws)e(whic)m(h)f(ha)m(v)m(e)j (a)e(time)h(v)-5 b(alue)44 b(whic)m(h)g(lies)g(within)0 1592 y(what)37 b(is)g(called)i(a)f(Go)s(o)s(d)f(Time)g(In)m(terv)-5 b(al)38 b(or)f(GTI.)g(The)g(time)h(in)m(terv)-5 b(als)38 b(are)g(de\014ned)e(in)h(a)g(separate)i(FITS)0 1705 y(table)i (extension)g(whic)m(h)e(con)m(tains)i(2)g(columns)f(giving)g(the)h (start)f(and)g(stop)g(time)g(of)g(eac)m(h)i(go)s(o)s(d)e(in)m(terv)-5 b(al.)0 1818 y(The)34 b(\014ltering)h(op)s(eration)h(accepts)g(only)e (those)i(ro)m(ws)e(of)h(the)g(input)f(table)i(whic)m(h)e(ha)m(v)m(e)i (an)f(asso)s(ciated)h(time)0 1930 y(whic)m(h)f(falls)i(within)e(one)h (of)g(the)g(time)g(in)m(terv)-5 b(als)37 b(de\014ned)e(in)g(the)h(GTI)g (extension.)57 b(A)36 b(high)g(lev)m(el)h(function,)0 2043 y(gti\014lter\(a,b,c,d\),)44 b(is)c(a)m(v)-5 b(ailable)42 b(whic)m(h)d(ev)-5 b(aluates)41 b(eac)m(h)g(ro)m(w)e(of)h(the)f(input)g (table)h(and)f(returns)f(TR)m(UE)i(or)0 2156 y(F)-10 b(ALSE)30 b(dep)s(ending)f(whether)h(the)g(ro)m(w)h(is)f(inside)g(or)g (outside)h(the)g(go)s(o)s(d)f(time)h(in)m(terv)-5 b(al.)42 b(The)30 b(syn)m(tax)h(is)286 2469 y Fe(gtifilter\()45 b([)j("gtifile")d([,)i(expr)g([,)g("STARTCOL",)e("STOPCOL")g(])j(])f(]) g(\))0 2782 y Fi(where)20 b(eac)m(h)h("[]")h(demarks)e(optional)h (parameters.)38 b(Note)21 b(that)g(the)g(quotes)f(around)g(the)g (gti\014le)i(and)d(ST)-8 b(AR)g(T/STOP)0 2895 y(column)33 b(are)h(required.)50 b(Either)34 b(single)g(or)g(double)f(quotes)h(ma)m (y)g(b)s(e)f(used.)50 b(In)33 b(cases)h(where)g(this)f(expression)0 3008 y(is)d(en)m(tered)g(on)g(the)g(Unix)g(command)g(line,)g(enclose)h (the)f(en)m(tire)h(expression)f(in)f(double)h(quotes,)g(and)g(then)f (use)0 3121 y(single)c(quotes)g(within)e(the)i(expression)f(to)h (enclose)g(the)g('gti\014le')h(and)d(other)i(terms.)38 b(It)25 b(is)f(also)h(usually)f(p)s(ossible)0 3234 y(to)38 b(do)e(the)h(rev)m(erse,)j(and)c(enclose)i(the)f(whole)g(expression)g (in)f(single)i(quotes)f(and)f(then)h(use)f(double)g(quotes)0 3347 y(within)d(the)g(expression.)50 b(The)33 b(gti\014le,)i(if)f(sp)s (eci\014ed,)f(can)h(b)s(e)f(blank)g(\(""\))i(whic)m(h)e(will)g(mean)h (to)g(use)f(the)h(\014rst)0 3460 y(extension)g(with)g(the)f(name)h ("*GTI*")h(in)f(the)f(curren)m(t)h(\014le,)h(a)f(plain)f(extension)h (sp)s(eci\014er)f(\(eg,)j("+2",)g("[2]",)0 3573 y(or)30 b("[STDGTI]"\))i(whic)m(h)e(will)h(b)s(e)f(used)f(to)j(select)g(an)e (extension)h(in)f(the)h(curren)m(t)f(\014le,)h(or)f(a)h(regular)g (\014lename)0 3686 y(with)f(or)h(without)f(an)h(extension)g(sp)s (eci\014er)f(whic)m(h)g(in)g(the)h(latter)h(case)f(will)g(mean)f(to)i (use)e(the)h(\014rst)e(extension)0 3799 y(with)37 b(an)g(extension)g (name)h("*GTI*".)62 b(Expr)36 b(can)h(b)s(e)g(an)m(y)g(arithmetic)i (expression,)f(including)f(simply)g(the)0 3911 y(time)f(column)g(name.) 57 b(A)36 b(v)m(ector)h(time)g(expression)e(will)h(pro)s(duce)f(a)h(v)m (ector)h(b)s(o)s(olean)f(result.)57 b(ST)-8 b(AR)g(TCOL)0 4024 y(and)27 b(STOPCOL)f(are)i(the)g(names)g(of)g(the)g(ST)-8 b(AR)g(T/STOP)26 b(columns)i(in)f(the)h(GTI)g(extension.)41 b(If)27 b(one)h(of)g(them)0 4137 y(is)i(sp)s(eci\014ed,)g(they)h(b)s (oth)f(m)m(ust)g(b)s(e.)0 4297 y(In)21 b(its)h(simplest)g(form,)i(no)d (parameters)h(need)g(to)h(b)s(e)e(pro)m(vided)g({)h(default)g(v)-5 b(alues)22 b(will)h(b)s(e)e(used.)37 b(The)21 b(expression)0 4410 y("gti\014lter\(\)")33 b(is)e(equiv)-5 b(alen)m(t)31 b(to)334 4723 y Fe(gtifilter\()45 b("",)i(TIME,)f("*START*",)f ("*STOP*")h(\))0 5036 y Fi(This)31 b(will)g(searc)m(h)h(the)g(curren)m (t)f(\014le)g(for)g(a)h(GTI)f(extension,)h(\014lter)g(the)f(TIME)g (column)g(in)g(the)h(curren)m(t)f(table,)0 5149 y(using)j(ST)-8 b(AR)g(T/STOP)34 b(times)i(tak)m(en)f(from)g(columns)f(in)h(the)g(GTI)g (extension)g(with)g(names)f(con)m(taining)j(the)0 5262 y(strings)32 b("ST)-8 b(AR)g(T")33 b(and)e("STOP".)46 b(The)32 b(wildcards)f(\('*'\))j(allo)m(w)g(sligh)m(t)f(v)-5 b(ariations)33 b(in)f(naming)g(con)m(v)m(en)m(tions)0 5375 y(suc)m(h)38 b(as)g("TST)-8 b(AR)g(T")39 b(or)f("ST)-8 b(AR)g(TTIME".)65 b(The)37 b(same)i(default)g(v)-5 b(alues)38 b(apply)g(for)g(unsp)s(eci\014ed)f(parame-)0 5488 y(ters)f(when)f(the)h (\014rst)f(one)i(or)f(t)m(w)m(o)h(parameters)f(are)h(sp)s(eci\014ed.)56 b(The)36 b(function)f(automatically)k(searc)m(hes)e(for)0 5601 y(TIMEZER)m(O/I/F)g(k)m(eyw)m(ords)f(in)g(the)h(curren)m(t)f(and)g (GTI)g(extensions,)i(applying)f(a)f(relativ)m(e)j(time)e(o\013set,)i (if)0 5714 y(necessary)-8 b(.)p eop end %%Page: 103 109 TeXDict begin 103 108 bop 0 299 a Fg(8.11.)73 b(R)m(O)m(W)31 b(FIL)-8 b(TERING)30 b(SPECIFICA)-8 b(TION)1982 b Fi(103)0 555 y Fb(8.11.5)113 b(Spatial)38 b(Region)g(Filtering)0 775 y Fi(Another)g(common)g(\014ltering)g(metho)s(d)f(selects)i(ro)m (ws)f(based)g(on)f(whether)h(the)g(spatial)h(p)s(osition)e(asso)s (ciated)0 887 y(with)32 b(eac)m(h)i(ro)m(w)e(is)h(lo)s(cated)h(within)e (a)h(giv)m(en)g(2-dimensional)g(region.)48 b(The)32 b(syn)m(tax)h(for)f (this)h(high-lev)m(el)h(\014lter)0 1000 y(is)334 1262 y Fe(regfilter\()45 b("regfilename")f([)k(,)f(Xexpr,)f(Yexpr)h([)g(,)h ("wcs)e(cols")h(])g(])g(\))0 1524 y Fi(where)22 b(eac)m(h)i("[]")g (demarks)e(optional)i(parameters.)38 b(The)22 b(region)h(\014le)g(name) f(is)h(required)f(and)g(m)m(ust)g(b)s(e)g(enclosed)0 1637 y(in)34 b(quotes.)51 b(The)33 b(remaining)h(parameters)h(are)f (optional.)52 b(There)33 b(are)i(2)f(supp)s(orted)e(formats)i(for)f (the)h(region)0 1750 y(\014le:)62 b(ASCI)s(I)39 b(\014le)h(or)h(FITS)f (binary)g(table.)73 b(The)40 b(region)h(\014le)g(con)m(tains)h(a)f (list)g(of)g(one)g(or)g(more)g(geometric)0 1863 y(shap)s(es)30 b(\(circle,)j(ellipse,)g(b)s(o)m(x,)e(etc.\))44 b(whic)m(h)31 b(de\014nes)f(a)i(region)g(on)f(the)g(celestial)j(sphere)c(or)h(an)g (area)h(within)f(a)0 1975 y(particular)36 b(2D)g(image.)57 b(The)35 b(region)h(\014le)f(is)g(t)m(ypically)j(generated)e(using)f (an)g(image)i(displa)m(y)e(program)g(suc)m(h)0 2088 y(as)e(fv/PO)m(W)g (\(distribute)f(b)m(y)h(the)f(HEASAR)m(C\),)h(or)g(ds9)f(\(distributed) g(b)m(y)g(the)h(Smithsonian)f(Astroph)m(ysical)0 2201 y(Observ)-5 b(atory\).)69 b(Users)39 b(should)g(refer)g(to)h(the)g(do)s (cumen)m(tation)h(pro)m(vided)e(with)g(these)h(programs)f(for)h(more)0 2314 y(details)29 b(on)f(the)g(syn)m(tax)h(used)e(in)h(the)h(region)f (\014les.)40 b(The)28 b(FITS)f(region)i(\014le)f(format)h(is)f (de\014ned)f(in)h(a)g(do)s(cumen)m(t)0 2427 y(a)m(v)-5 b(ailable)33 b(from)d(the)g(FITS)g(Supp)s(ort)e(O\016ce)j(at)g(h)m (ttp://\014ts.gsfc.nasa.go)m(v/)k(registry/)c(region.h)m(tml)0 2587 y(In)21 b(its)h(simplest)g(form,)i(\(e.g.,)h (reg\014lter\("region.reg"\))h(\))c(the)g(co)s(ordinates)g(in)g(the)g (default)g('X')h(and)e('Y')h(columns)0 2700 y(will)43 b(b)s(e)g(used)f(to)i(determine)f(if)g(eac)m(h)h(ro)m(w)f(is)g(inside)g (or)g(outside)g(the)g(area)h(sp)s(eci\014ed)e(in)h(the)g(region)h (\014le.)0 2813 y(Alternate)32 b(p)s(osition)e(column)g(names,)h(or)f (expressions,)h(ma)m(y)g(b)s(e)e(en)m(tered)i(if)g(needed,)f(as)h(in) 382 3075 y Fe(regfilter\("region.reg",)41 b(XPOS,)47 b(YPOS\))0 3337 y Fi(Region)37 b(\014ltering)f(can)g(b)s(e)f(applied)g (most)h(unam)m(biguously)f(if)h(the)g(p)s(ositions)g(in)f(the)h(region) g(\014le)g(and)f(in)h(the)0 3449 y(table)g(to)g(b)s(e)e(\014ltered)h (are)h(b)s(oth)e(giv)m(e)j(in)e(terms)g(of)g(absolute)h(celestial)i(co) s(ordinate)e(units.)54 b(In)35 b(this)g(case)h(the)0 3562 y(lo)s(cations)26 b(and)d(sizes)i(of)g(the)f(geometric)i(shap)s (es)e(in)g(the)g(region)h(\014le)f(are)h(sp)s(eci\014ed)f(in)g(angular) g(units)g(on)g(the)g(sky)0 3675 y(\(e.g.,)32 b(p)s(ositions)e(giv)m(en) i(in)e(R.A.)g(and)g(Dec.)42 b(and)30 b(sizes)h(in)f(arcseconds)g(or)h (arcmin)m(utes\).)41 b(Similarly)-8 b(,)31 b(eac)m(h)h(ro)m(w)0 3788 y(of)h(the)h(\014ltered)f(table)h(will)f(ha)m(v)m(e)i(a)e (celestial)j(co)s(ordinate)e(asso)s(ciated)g(with)f(it.)50 b(This)32 b(asso)s(ciation)j(is)e(usually)0 3901 y(implemen)m(ted)39 b(using)e(a)i(set)g(of)f(so-called)i('W)-8 b(orld)39 b(Co)s(ordinate)g(System')f(\(or)h(W)m(CS\))f(FITS)g(k)m(eyw)m(ords)g (that)0 4014 y(de\014ne)27 b(the)g(co)s(ordinate)h(transformation)g (that)g(m)m(ust)f(b)s(e)f(applied)h(to)h(the)g(v)-5 b(alues)27 b(in)g(the)h('X')g(and)e('Y')i(columns)0 4127 y(to)j(calculate)i(the)d (co)s(ordinate.)0 4287 y(Alternativ)m(ely)-8 b(,)30 b(one)d(can)g(p)s (erform)e(spatial)j(\014ltering)e(using)g(unitless)h('pixel')g(co)s (ordinates)h(for)e(the)h(regions)g(and)0 4400 y(ro)m(w)33 b(p)s(ositions.)49 b(In)33 b(this)g(case)h(the)f(user)g(m)m(ust)g(b)s (e)f(careful)h(to)h(ensure)f(that)g(the)h(p)s(ositions)f(in)g(the)g(2)g (\014les)h(are)0 4513 y(self-consisten)m(t.)54 b(A)34 b(t)m(ypical)i(problem)d(is)h(that)h(the)f(region)h(\014le)f(ma)m(y)h (b)s(e)e(generated)j(using)d(a)i(binned)d(image,)0 4626 y(but)g(the)h(un)m(binned)e(co)s(ordinates)i(are)g(giv)m(en)h(in)e(the) h(ev)m(en)m(t)i(table.)48 b(The)32 b(R)m(OSA)-8 b(T)33 b(ev)m(en)m(ts)h(\014les,)g(for)e(example,)0 4739 y(ha)m(v)m(e)f(X)f (and)f(Y)g(pixel)h(co)s(ordinates)g(that)h(range)f(from)f(1)h(-)g (15360.)42 b(These)30 b(co)s(ordinates)g(are)g(t)m(ypically)h(binned)0 4852 y(b)m(y)i(a)h(factor)g(of)f(32)h(to)g(pro)s(duce)e(a)i(480x480)i (pixel)d(image.)51 b(If)32 b(one)i(then)f(uses)g(a)g(region)h(\014le)f (generated)h(from)0 4965 y(this)c(image)i(\(in)f(image)g(pixel)g (units\))g(to)g(\014lter)f(the)h(R)m(OSA)-8 b(T)30 b(ev)m(en)m(ts)i (\014le,)f(then)f(the)h(X)g(and)f(Y)g(column)h(v)-5 b(alues)0 5077 y(m)m(ust)30 b(b)s(e)g(con)m(v)m(erted)i(to)f(corresp)s(onding)e (pixel)i(units)f(as)g(in:)382 5339 y Fe(regfilter\("rosat.reg",)42 b(X/32.+.5,)j(Y/32.+.5\))0 5601 y Fi(Note)h(that)f(this)f(binning)f (con)m(v)m(ersion)j(is)e(not)h(necessary)g(if)f(the)h(region)g(\014le)f (is)h(sp)s(eci\014ed)e(using)h(celestial)0 5714 y(co)s(ordinate)h (units)f(instead)g(of)g(pixel)h(units)f(b)s(ecause)g(CFITSIO)e(is)j (then)e(able)i(to)g(directly)g(compare)g(the)p eop end %%Page: 104 110 TeXDict begin 104 109 bop 0 299 a Fi(104)1573 b Fg(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fi(celestial)30 b(co)s(ordinate)f(of)e(eac)m(h)i(ro)m(w)f(in)f (the)h(table)g(with)g(the)f(celestial)k(co)s(ordinates)d(in)f(the)h (region)g(\014le)g(without)0 668 y(ha)m(ving)j(to)g(kno)m(w)f(an)m (ything)h(ab)s(out)f(ho)m(w)h(the)f(image)i(ma)m(y)f(ha)m(v)m(e)g(b)s (een)f(binned.)0 828 y(The)f(last)h("w)m(cs)g(cols")h(parameter)f (should)e(rarely)h(b)s(e)g(needed.)40 b(If)29 b(supplied,)f(this)i (string)f(con)m(tains)i(the)e(names)0 941 y(of)37 b(the)g(2)h(columns)f (\(space)h(or)f(comma)g(separated\))h(whic)m(h)f(ha)m(v)m(e)h(the)g (asso)s(ciated)g(W)m(CS)f(k)m(eyw)m(ords.)61 b(If)37 b(not)0 1054 y(supplied,)f(the)g(\014lter)g(will)h(scan)f(the)g(X)g (and)f(Y)h(expressions)g(for)g(column)f(names.)58 b(If)35 b(only)h(one)h(is)f(found)e(in)0 1167 y(eac)m(h)e(expression,)e(those)h (columns)f(will)h(b)s(e)e(used,)h(otherwise)h(an)f(error)g(will)h(b)s (e)f(returned.)0 1327 y(These)g(region)h(shap)s(es)f(are)g(supp)s (orted)f(\(names)h(are)h(case)h(insensitiv)m(e\):)334 1591 y Fe(Point)428 b(\()48 b(X1,)f(Y1)g(\))715 b(<-)48 b(One)f(pixel)f(square)g(region)334 1704 y(Line)476 b(\()48 b(X1,)f(Y1,)g(X2,)f(Y2)i(\))333 b(<-)48 b(One)f(pixel)f(wide)h(region) 334 1817 y(Polygon)332 b(\()48 b(X1,)f(Y1,)g(X2,)f(Y2,)h(...)g(\))95 b(<-)48 b(Rest)e(are)h(interiors)e(with)334 1930 y(Rectangle)236 b(\()48 b(X1,)f(Y1,)g(X2,)f(Y2,)h(A)h(\))334 b(|)47 b(boundaries)e (considered)334 2043 y(Box)524 b(\()48 b(Xc,)f(Yc,)g(Wdth,)f(Hght,)g(A) i(\))143 b(V)47 b(within)f(the)h(region)334 2156 y(Diamond)332 b(\()48 b(Xc,)f(Yc,)g(Wdth,)f(Hght,)g(A)i(\))334 2269 y(Circle)380 b(\()48 b(Xc,)f(Yc,)g(R)g(\))334 2382 y(Annulus)332 b(\()48 b(Xc,)f(Yc,)g(Rin,)f(Rout)h(\))334 2494 y(Ellipse)332 b(\()48 b(Xc,)f(Yc,)g(Rx,)f(Ry,)h(A)h(\))334 2607 y(Elliptannulus)c(\() k(Xc,)f(Yc,)g(Rinx,)f(Riny,)g(Routx,)g(Routy,)g(Ain,)h(Aout)g(\))334 2720 y(Sector)380 b(\()48 b(Xc,)f(Yc,)g(Amin,)f(Amax)h(\))0 2984 y Fi(where)28 b(\(Xc,Yc\))j(is)d(the)h(co)s(ordinate)h(of)e(the)h (shap)s(e's)f(cen)m(ter;)j(\(X#,Y#\))e(are)g(the)g(co)s(ordinates)g(of) g(the)g(shap)s(e's)0 3097 y(edges;)36 b(Rxxx)d(are)h(the)f(shap)s(es')g (v)-5 b(arious)34 b(Radii)f(or)h(semi-ma)5 b(jor/minor)34 b(axes;)i(and)d(Axxx)g(are)h(the)f(angles)i(of)0 3210 y(rotation)e(\(or)e(b)s(ounding)f(angles)i(for)f(Sector\))h(in)f (degrees.)44 b(F)-8 b(or)32 b(rotated)h(shap)s(es,)e(the)g(rotation)i (angle)f(can)g(b)s(e)0 3323 y(left)g(o\013,)h(indicating)f(no)f (rotation.)46 b(Common)31 b(alternate)i(names)e(for)h(the)f(regions)h (can)g(also)h(b)s(e)d(used:)43 b(rotb)s(o)m(x)0 3436 y(=)29 b(b)s(o)m(x;)g(rotrectangle)i(=)e(rectangle;)i(\(rot\)rhom)m (bus)e(=)f(\(rot\)diamond;)j(and)d(pie)h(=)f(sector.)42 b(When)28 b(a)i(shap)s(e's)0 3549 y(name)e(is)g(preceded)f(b)m(y)h(a)g (min)m(us)g(sign,)g('-',)i(the)e(de\014ned)e(region)j(is)f(instead)g (the)g(area)h(*outside*)g(its)f(b)s(oundary)0 3662 y(\(ie,)36 b(the)e(region)h(is)f(in)m(v)m(erted\).)53 b(All)34 b(the)g(shap)s(es)f (within)h(a)g(single)h(region)f(\014le)h(are)f(OR'd)f(together)j(to)e (create)0 3775 y(the)29 b(region,)i(and)d(the)i(order)f(is)g (signi\014can)m(t.)41 b(The)29 b(o)m(v)m(erall)i(w)m(a)m(y)g(of)e(lo)s (oking)h(at)g(region)g(\014les)f(is)g(that)h(if)f(the)h(\014rst)0 3888 y(region)f(is)g(an)g(excluded)g(region)g(then)f(a)i(dumm)m(y)d (included)h(region)i(of)f(the)g(whole)g(detector)h(is)f(inserted)f(in)h (the)0 4000 y(fron)m(t.)40 b(Then)25 b(eac)m(h)j(region)f(sp)s (eci\014cation)h(as)f(it)g(is)g(pro)s(cessed)f(o)m(v)m(errides)h(an)m (y)g(selections)i(inside)d(of)h(that)g(region)0 4113 y(sp)s(eci\014ed)36 b(b)m(y)g(previous)g(regions.)59 b(Another)37 b(w)m(a)m(y)g(of)g(thinking)f(ab)s(out)g(this)g(is)h(that) g(if)f(a)h(previous)f(excluded)0 4226 y(region)31 b(is)f(completely)i (inside)f(of)f(a)h(subsequen)m(t)e(included)h(region)h(the)g(excluded)f (region)h(is)f(ignored.)0 4386 y(The)44 b(p)s(ositional)i(co)s (ordinates)g(ma)m(y)f(b)s(e)g(giv)m(en)h(either)f(in)g(pixel)g(units,)j (decimal)e(degrees)g(or)f(hh:mm:ss.s,)0 4499 y(dd:mm:ss.s)25 b(units.)38 b(The)26 b(shap)s(e)f(sizes)i(ma)m(y)f(b)s(e)g(giv)m(en)h (in)e(pixels,)j(degrees,)f(arcmin)m(utes,)h(or)e(arcseconds.)40 b(Lo)s(ok)0 4612 y(at)31 b(examples)g(of)f(region)h(\014le)g(pro)s (duced)d(b)m(y)i(fv/PO)m(W)h(or)g(ds9)f(for)g(further)f(details)i(of)g (the)f(region)h(\014le)f(format.)0 4772 y(There)37 b(are)g(three)g (functions)g(that)g(are)h(primarily)f(for)f(use)h(with)g(SA)m(O)g (region)g(\014les)g(and)g(the)g(FSA)m(OI)g(task,)0 4885 y(but)e(they)h(can)h(b)s(e)e(used)g(directly)-8 b(.)59 b(They)36 b(return)f(a)h(b)s(o)s(olean)g(true)g(or)g(false)g(dep)s (ending)f(on)h(whether)f(a)i(t)m(w)m(o)0 4998 y(dimensional)31 b(p)s(oin)m(t)f(is)g(in)g(the)h(region)g(or)f(not:)191 5262 y Fe("point)46 b(in)h(a)h(circular)d(region")477 5375 y(circle\(xcntr,ycntr,radius)o(,Xco)o(lumn)o(,Yc)o(olum)o(n\))191 5601 y("point)h(in)h(an)g(elliptical)e(region")430 5714 y(ellipse\(xcntr,ycntr,xhl)o(f_w)o(dth,)o(yhlf)o(_wd)o(th,r)o(otat)o (ion)o(,Xco)o(lumn)o(,Yc)o(olum)o(n\))p eop end %%Page: 105 111 TeXDict begin 105 110 bop 0 299 a Fg(8.11.)73 b(R)m(O)m(W)31 b(FIL)-8 b(TERING)30 b(SPECIFICA)-8 b(TION)1982 b Fi(105)191 668 y Fe("point)46 b(in)h(a)h(rectangular)c(region")620 781 y(box\(xcntr,ycntr,xfll_wdth,)o(yfll)o(_wd)o(th,r)o(otat)o(ion)o (,Xco)o(lumn)o(,Yc)o(olum)o(n\))191 1007 y(where)334 1120 y(\(xcntr,ycntr\))g(are)j(the)g(\(x,y\))f(position)g(of)h(the)g (center)f(of)h(the)g(region)334 1233 y(\(xhlf_wdth,yhlf_wdth\))42 b(are)47 b(the)g(\(x,y\))f(half)h(widths)f(of)h(the)g(region)334 1346 y(\(xfll_wdth,yfll_wdth\))42 b(are)47 b(the)g(\(x,y\))f(full)h (widths)f(of)h(the)g(region)334 1458 y(\(radius\))f(is)h(half)f(the)h (diameter)f(of)h(the)g(circle)334 1571 y(\(rotation\))e(is)i(the)g (angle\(degrees\))d(that)j(the)g(region)f(is)h(rotated)f(with)620 1684 y(respect)g(to)h(\(xcntr,ycntr\))334 1797 y(\(Xcoord,Ycoord\))d (are)j(the)g(\(x,y\))f(coordinates)f(to)i(test,)f(usually)g(column)620 1910 y(names)334 2023 y(NOTE:)g(each)h(parameter)e(can)i(itself)f(be)i (an)f(expression,)d(not)j(merely)f(a)620 2136 y(column)h(name)f(or)h (constant.)0 2443 y Fb(8.11.6)113 b(Example)38 b(Ro)m(w)f(Filters)191 2665 y Fe([)47 b(binary)f(&&)i(mag)f(<=)g(5.0])380 b(-)48 b(Extract)e(all)h(binary)f(stars)g(brighter)1766 2778 y(than)94 b(fifth)47 b(magnitude)e(\(note)h(that)1766 2891 y(the)h(initial)f(space)g(is)h(necessary)e(to)1766 3004 y(prevent)h(it)h(from)g(being)f(treated)g(as)h(a)1766 3117 y(binning)f(specification\))191 3343 y([#row)g(>=)h(125)g(&&)h (#row)e(<=)h(175])142 b(-)48 b(Extract)e(row)h(numbers)e(125)i(through) f(175)191 3569 y([IMAGE[4,5])f(.gt.)h(100])476 b(-)48 b(Extract)e(all)h(rows)f(that)h(have)g(the)1766 3681 y(\(4,5\))f(component)g(of)h(the)g(IMAGE)f(column)1766 3794 y(greater)g(than)g(100)191 4020 y([abs\(sin\(theta)e(*)j(#deg\)\)) f(<)i(0.5])e(-)i(Extract)e(all)h(rows)f(having)g(the)1766 4133 y(absolute)f(value)i(of)g(the)g(sine)g(of)g(theta)1766 4246 y(less)94 b(than)47 b(a)g(half)g(where)f(the)h(angles)1766 4359 y(are)g(tabulated)e(in)i(degrees)191 4585 y([SUM\()f(SPEC)h(>)g (3*BACKGRND)e(\)>=1])94 b(-)48 b(Extract)e(all)h(rows)f(containing)f(a) 1766 4698 y(spectrum,)g(held)i(in)g(vector)f(column)1766 4811 y(SPEC,)g(with)h(at)g(least)f(one)h(value)g(3)1766 4924 y(times)f(greater)g(than)h(the)g(background)1766 5036 y(level)f(held)h(in)g(a)h(keyword,)d(BACKGRND)191 5262 y([VCOL=={1,4,2}])759 b(-)48 b(Extract)e(all)h(rows)f(whose)h (vector)f(column)1766 5375 y(VCOL)h(contains)e(the)i(3-elements)e(1,)i (4,)g(and)1766 5488 y(2.)191 5714 y([@rowFilter.txt])711 b(-)48 b(Extract)e(rows)g(using)h(the)g(expression)p eop end %%Page: 106 112 TeXDict begin 106 111 bop 0 299 a Fi(106)1573 b Fg(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)1766 555 y Fe(contained)45 b(within)h(the)h(text)g(file)1766 668 y(rowFilter.txt)191 894 y([gtifilter\(\)])855 b(-)48 b(Search)e(the)h(current)f(file)g(for)h(a)h(GTI)239 1007 y(extension,)92 b(filter)i(the)47 b(TIME)239 1120 y(column)f(in)h(the)g (current)f(table,)g(using)239 1233 y(START/STOP)f(times)h(taken)g(from) 239 1346 y(columns)f(in)j(the)f(GTI)94 b(extension)191 1571 y([regfilter\("pow.reg"\)])423 b(-)48 b(Extract)e(rows)g(which)h (have)f(a)i(coordinate)1766 1684 y(\(as)f(given)f(in)h(the)g(X)h(and)f (Y)g(columns\))1766 1797 y(within)f(the)h(spatial)f(region)g(specified) 1766 1910 y(in)h(the)g(pow.reg)f(region)g(file.)191 2136 y([regfilter\("pow.reg",)c(Xs,)47 b(Ys\)])f(-)i(Same)f(as)g(above,)f (except)g(that)h(the)1766 2249 y(Xs)g(and)g(Ys)g(columns)f(will)h(be)g (used)f(to)1766 2362 y(determine)f(the)i(coordinate)e(of)i(each)1766 2475 y(row)g(in)g(the)g(table.)0 2811 y Fd(8.12)180 b(Binning)45 b(or)g(Histogramming)i(Sp)t(eci\014cation)0 3062 y Fi(The)22 b(optional)i(binning)e(sp)s(eci\014er)g(is)h(enclosed)h(in)f(square)f (brac)m(k)m(ets)j(and)d(can)h(b)s(e)f(distinguished)g(from)h(a)g (general)0 3175 y(ro)m(w)32 b(\014lter)h(sp)s(eci\014cation)g(b)m(y)f (the)h(fact)g(that)g(it)g(b)s(egins)f(with)g(the)g(k)m(eyw)m(ord)h ('bin')f(not)h(immediately)g(follo)m(w)m(ed)0 3288 y(b)m(y)41 b(an)f(equals)i(sign.)72 b(When)41 b(binning)e(is)i(sp)s(eci\014ed,)i (a)e(temp)s(orary)g(N-dimensional)g(FITS)f(primary)g(arra)m(y)0 3401 y(is)j(created)h(b)m(y)f(computing)h(the)f(histogram)h(of)f(the)g (v)-5 b(alues)44 b(in)e(the)i(sp)s(eci\014ed)e(columns)h(of)g(a)h(FITS) e(table)0 3514 y(extension.)f(After)30 b(the)f(histogram)h(is)g (computed)f(the)h(input)e(FITS)h(\014le)h(con)m(taining)h(the)e(table)i (is)e(then)g(closed)0 3627 y(and)34 b(the)h(temp)s(orary)f(FITS)g (primary)g(arra)m(y)h(is)g(op)s(ened)f(and)g(passed)g(to)h(the)g (application)h(program.)54 b(Th)m(us,)0 3740 y(the)39 b(application)h(program)f(nev)m(er)g(sees)g(the)g(original)h(FITS)e (table)i(and)e(only)h(sees)h(the)f(image)h(in)e(the)h(new)0 3853 y(temp)s(orary)32 b(\014le)h(\(whic)m(h)g(has)f(no)h(additional)g (extensions\).)49 b(Ob)m(viously)-8 b(,)34 b(the)f(application)h (program)e(m)m(ust)h(b)s(e)0 3966 y(exp)s(ecting)e(to)g(op)s(en)f(a)h (FITS)e(image)j(and)e(not)g(a)h(FITS)f(table)h(in)f(this)g(case.)0 4126 y(The)g(data)h(t)m(yp)s(e)f(of)h(the)f(FITS)g(histogram)g(image)i (ma)m(y)f(b)s(e)f(sp)s(eci\014ed)f(b)m(y)h(app)s(ending)f('b')h(\(for)h (8-bit)g(b)m(yte\),)g('i')0 4239 y(\(for)g(16-bit)g(in)m(tegers\),)h ('j')f(\(for)g(32-bit)g(in)m(teger\),)i('r')d(\(for)h(32-bit)g (\015oating)h(p)s(oin)m(ts\),)e(or)h('d')f(\(for)h(64-bit)g(double)0 4351 y(precision)d(\015oating)h(p)s(oin)m(t\))g(to)f(the)h('bin')e(k)m (eyw)m(ord)i(\(e.g.)41 b('[binr)28 b(X]')g(creates)i(a)e(real)h (\015oating)g(p)s(oin)m(t)f(image\).)41 b(If)0 4464 y(the)26 b(datat)m(yp)s(e)h(is)f(not)g(explicitly)i(sp)s(eci\014ed)d(then)h(a)g (32-bit)h(in)m(teger)h(image)f(will)f(b)s(e)f(created)i(b)m(y)f (default,)i(unless)0 4577 y(the)h(w)m(eigh)m(ting)h(option)f(is)g(also) h(sp)s(eci\014ed)e(in)g(whic)m(h)h(case)g(the)g(image)h(will)f(ha)m(v)m (e)h(a)f(32-bit)h(\015oating)g(p)s(oin)m(t)e(data)0 4690 y(t)m(yp)s(e)j(b)m(y)f(default.)0 4850 y(The)24 b(histogram)g(image)i (ma)m(y)f(ha)m(v)m(e)g(from)f(1)g(to)h(4)g(dimensions)e(\(axes\),)k (dep)s(ending)c(on)h(the)g(n)m(um)m(b)s(er)f(of)h(columns)0 4963 y(that)31 b(are)g(sp)s(eci\014ed.)40 b(The)30 b(general)h(form)f (of)g(the)h(binning)e(sp)s(eci\014cation)i(is:)48 5226 y Fe([bin{bijrd})92 b(Xcol=min:max:binsize,)42 b(Ycol=)47 b(...,)f(Zcol=...,)f(Tcol=...;)h(weight])0 5488 y Fi(in)39 b(whic)m(h)g(up)f(to)i(4)g(columns,)h(eac)m(h)f(corresp)s(onding)e(to)i (an)g(axis)f(of)h(the)f(image,)k(are)d(listed.)67 b(The)39 b(column)0 5601 y(names)27 b(are)h(case)h(insensitiv)m(e,)g(and)e(the)h (column)f(n)m(um)m(b)s(er)f(ma)m(y)i(b)s(e)f(giv)m(en)h(instead)g(of)g (the)g(name,)g(preceded)f(b)m(y)0 5714 y(a)32 b(p)s(ound)e(sign)i (\(e.g.,)i([bin)d(#4=1:512]\).)47 b(If)31 b(the)h(column)g(name)g(is)f (not)h(sp)s(eci\014ed,)g(then)f(CFITSIO)g(will)h(\014rst)p eop end %%Page: 107 113 TeXDict begin 107 112 bop 0 299 a Fg(8.12.)113 b(BINNING)31 b(OR)f(HISTOGRAMMING)h(SPECIFICA)-8 b(TION)1268 b Fi(107)0 555 y(try)37 b(to)h(use)f(the)g('preferred)f(column')i(as)f(sp)s (eci\014ed)g(b)m(y)g(the)g(CPREF)g(k)m(eyw)m(ord)h(if)f(it)g(exists)h (\(e.g.,)j('CPREF)0 668 y(=)i('DETX,DETY'\),)h(otherwise)g(column)f (names)g('X',)h('Y',)g('Z',)f(and)f('T')i(will)f(b)s(e)f(assumed)h(for) g(eac)m(h)h(of)0 781 y(the)37 b(4)h(axes,)i(resp)s(ectiv)m(ely)-8 b(.)62 b(In)37 b(cases)h(where)e(the)i(column)f(name)g(could)g(b)s(e)f (confused)h(with)g(an)g(arithmetic)0 894 y(expression,)30 b(enclose)i(the)f(column)f(name)g(in)g(paren)m(theses)h(to)g(force)g (the)f(name)h(to)g(b)s(e)f(in)m(terpreted)g(literally)-8 b(.)0 1054 y(Eac)m(h)33 b(column)f(name)g(ma)m(y)h(b)s(e)f(follo)m(w)m (ed)h(b)m(y)g(an)f(equals)g(sign)h(and)e(then)h(the)g(lo)m(w)m(er)i (and)e(upp)s(er)e(range)i(of)h(the)0 1167 y(histogram,)f(and)e(the)h (size)h(of)f(the)g(histogram)h(bins,)e(separated)h(b)m(y)g(colons.)43 b(Spaces)31 b(are)g(allo)m(w)m(ed)i(b)s(efore)e(and)0 1280 y(after)e(the)g(equals)g(sign)f(but)g(not)h(within)f(the)h ('min:max:binsize')g(string.)40 b(The)29 b(min,)f(max)h(and)f(binsize)h (v)-5 b(alues)0 1393 y(ma)m(y)32 b(b)s(e)e(in)m(teger)i(or)f (\015oating)h(p)s(oin)m(t)f(n)m(um)m(b)s(ers,)f(or)h(they)g(ma)m(y)g(b) s(e)g(the)g(names)g(of)g(k)m(eyw)m(ords)g(in)g(the)g(header)g(of)0 1506 y(the)g(table.)41 b(If)30 b(the)h(latter,)h(then)e(the)g(v)-5 b(alue)31 b(of)g(that)g(k)m(eyw)m(ord)f(is)h(substituted)f(in)m(to)h (the)g(expression.)0 1666 y(Default)37 b(v)-5 b(alues)36 b(for)g(the)g(min,)h(max)f(and)g(binsize)g(quan)m(tities)h(will)f(b)s (e)f(used)h(if)f(not)i(explicitly)g(giv)m(en)g(in)f(the)0 1779 y(binning)29 b(expression)h(as)h(sho)m(wn)f(in)g(these)h (examples:)191 2033 y Fe([bin)47 b(x)g(=)g(:512:2])94 b(-)47 b(use)g(default)f(minimum)g(value)191 2146 y([bin)h(x)g(=)g (1::2])190 b(-)47 b(use)g(default)f(maximum)g(value)191 2259 y([bin)h(x)g(=)g(1:512])142 b(-)47 b(use)g(default)f(bin)h(size) 191 2372 y([bin)g(x)g(=)g(1:])286 b(-)47 b(use)g(default)f(maximum)g (value)g(and)h(bin)g(size)191 2485 y([bin)g(x)g(=)g(:512])190 b(-)47 b(use)g(default)f(minimum)g(value)g(and)h(bin)g(size)191 2598 y([bin)g(x)g(=)g(2])334 b(-)47 b(use)g(default)f(minimum)g(and)h (maximum)f(values)191 2711 y([bin)h(x])524 b(-)47 b(use)g(default)f (minimum,)g(maximum)g(and)g(bin)h(size)191 2824 y([bin)g(4])524 b(-)47 b(default)f(2-D)h(image,)f(bin)h(size)g(=)g(4)h(in)f(both)g (axes)191 2937 y([bin])619 b(-)47 b(default)f(2-D)h(image)0 3191 y Fi(CFITSIO)31 b(will)i(use)f(the)h(v)-5 b(alue)33 b(of)g(the)g(TLMINn,)f(TLMAXn,)h(and)f(TDBINn)h(k)m(eyw)m(ords,)h(if)e (they)h(exist,)h(for)0 3304 y(the)j(default)f(min,)i(max,)g(and)e (binsize,)i(resp)s(ectiv)m(ely)-8 b(.)61 b(If)36 b(they)h(do)f(not)h (exist)g(then)f(CFITSIO)f(will)i(use)f(the)0 3417 y(actual)d(minim)m (um)e(and)h(maxim)m(um)g(v)-5 b(alues)32 b(in)g(the)g(column)f(for)h (the)g(histogram)h(min)e(and)h(max)g(v)-5 b(alues.)45 b(The)0 3530 y(default)34 b(binsize)f(will)h(b)s(e)f(set)h(to)h(1,)g (or)e(\(max)h(-)g(min\))f(/)h(10.,)i(whic)m(hev)m(er)e(is)g(smaller,)h (so)e(that)i(the)e(histogram)0 3643 y(will)e(ha)m(v)m(e)g(at)g(least)h (10)f(bins)f(along)h(eac)m(h)h(axis.)0 3803 y(A)41 b(shortcut)g (notation)h(is)f(allo)m(w)m(ed)i(if)e(all)h(the)f(columns/axes)h(ha)m (v)m(e)g(the)f(same)g(binning)f(sp)s(eci\014cation.)74 b(In)0 3916 y(this)33 b(case)g(all)h(the)f(column)f(names)h(ma)m(y)g(b) s(e)f(listed)h(within)f(paren)m(theses,)i(follo)m(w)m(ed)h(b)m(y)d(the) h(\(single\))h(binning)0 4029 y(sp)s(eci\014cation,)d(as)g(in:)191 4283 y Fe([bin)47 b(\(X,Y\)=1:512:2])191 4396 y([bin)g(\(X,Y\))f(=)h (5])0 4650 y Fi(The)31 b(optional)i(w)m(eigh)m(ting)h(factor)e(is)g (the)g(last)g(item)h(in)e(the)h(binning)f(sp)s(eci\014er)g(and,)h(if)f (presen)m(t,)i(is)e(separated)0 4763 y(from)38 b(the)g(list)h(of)f (columns)g(b)m(y)g(a)h(semi-colon.)65 b(As)39 b(the)f(histogram)h(is)f (accum)m(ulated,)k(this)c(w)m(eigh)m(t)i(is)e(used)0 4876 y(to)d(incremen)m(ted)f(the)g(v)-5 b(alue)35 b(of)f(the)g (appropriated)f(bin)h(in)f(the)h(histogram.)52 b(If)34 b(the)g(w)m(eigh)m(ting)i(factor)f(is)f(not)0 4989 y(sp)s(eci\014ed,)24 b(then)f(the)g(default)g(w)m(eigh)m(t)i(=)d(1)i(is)f(assumed.)37 b(The)23 b(w)m(eigh)m(ting)i(factor)f(ma)m(y)f(b)s(e)g(a)g(constan)m(t) i(in)m(teger)f(or)0 5102 y(\015oating)30 b(p)s(oin)m(t)f(n)m(um)m(b)s (er,)f(or)h(the)g(name)g(of)g(a)g(k)m(eyw)m(ord)h(con)m(taining)g(the)g (w)m(eigh)m(ting)g(v)-5 b(alue.)41 b(Or)28 b(the)h(w)m(eigh)m(ting)0 5215 y(factor)g(ma)m(y)g(b)s(e)e(the)h(name)g(of)h(a)f(table)h(column)f (in)g(whic)m(h)f(case)j(the)e(v)-5 b(alue)28 b(in)g(that)h(column,)f (on)g(a)h(ro)m(w)f(b)m(y)g(ro)m(w)0 5328 y(basis,)i(will)h(b)s(e)f (used.)0 5488 y(In)35 b(some)h(cases,)i(the)d(column)h(or)f(k)m(eyw)m (ord)h(ma)m(y)g(giv)m(e)h(the)f(recipro)s(cal)g(of)g(the)g(actual)h(w)m (eigh)m(t)g(v)-5 b(alue)36 b(that)g(is)0 5601 y(needed.)49 b(In)32 b(this)h(case,)i(precede)e(the)h(w)m(eigh)m(t)g(k)m(eyw)m(ord)g (or)f(column)g(name)g(b)m(y)g(a)g(slash)g('/')h(to)g(tell)g(CFITSIO)0 5714 y(to)d(use)f(the)h(recipro)s(cal)g(of)f(the)h(v)-5 b(alue)31 b(when)e(constructing)i(the)g(histogram.)p eop end %%Page: 108 114 TeXDict begin 108 113 bop 0 299 a Fi(108)1573 b Fg(CHAPTER)30 b(8.)112 b(EXTENDED)30 b(FILE)h(NAME)f(SYNT)-8 b(AX)0 555 y Fi(F)g(or)35 b(complex)f(or)g(commonly)g(used)f(histograms,)j (one)e(can)g(also)h(place)g(its)f(description)g(in)m(to)h(a)f(text)h (\014le)f(and)0 668 y(imp)s(ort)44 b(it)g(in)m(to)i(the)e(binning)f(sp) s(eci\014cation)i(using)f(the)h(syn)m(tax)f('[bin)g(@\014lename.txt]'.) 84 b(The)44 b(\014le's)g(con-)0 781 y(ten)m(ts)37 b(can)e(extend)h(o)m (v)m(er)h(m)m(ultiple)f(lines,)i(although)e(it)g(m)m(ust)f(still)i (conform)f(to)g(the)g(no-spaces)g(rule)f(for)h(the)0 894 y(min:max:binsize)h(syn)m(tax)h(and)e(eac)m(h)i(axis)g(sp)s (eci\014cation)g(m)m(ust)f(still)g(b)s(e)g(comma-separated.)62 b(An)m(y)37 b(lines)g(in)0 1007 y(the)32 b(external)h(text)g(\014le)f (that)h(b)s(egin)e(with)h(2)g(slash)g(c)m(haracters)h(\('//'\))h(will)e (b)s(e)g(ignored)g(and)f(ma)m(y)i(b)s(e)e(used)g(to)0 1120 y(add)f(commen)m(ts)h(in)m(to)g(the)g(\014le.)0 1280 y(Examples:)191 1540 y Fe([bini)46 b(detx,)h(dety])762 b(-)47 b(2-D,)g(16-bit)f(integer)g(histogram)1861 1653 y(of)i(DETX)e(and)h(DETY)g(columns,)e(using)1861 1766 y(default)h(values)g(for)h(the)g(histogram)1861 1878 y(range)g(and)g(binsize)191 2104 y([bin)g(\(detx,)f(dety\)=16;)f (/exposure])g(-)i(2-D,)g(32-bit)f(real)h(histogram)e(of)i(DETX)1861 2217 y(and)g(DETY)g(columns)f(with)g(a)i(bin)f(size)f(=)i(16)1861 2330 y(in)g(both)e(axes.)h(The)f(histogram)g(values)1861 2443 y(are)h(divided)f(by)h(the)g(EXPOSURE)f(keyword)1861 2556 y(value.)191 2782 y([bin)h(time=TSTART:TSTOP:0.1])280 b(-)47 b(1-D)g(lightcurve,)e(range)h(determined)f(by)1861 2895 y(the)i(TSTART)f(and)h(TSTOP)g(keywords,)1861 3008 y(with)g(0.1)g(unit)g(size)f(bins.)191 3233 y([bin)h(pha,)f (time=8000.:8100.:0.1])90 b(-)47 b(2-D)g(image)g(using)f(default)g (binning)1861 3346 y(of)i(the)e(PHA)h(column)f(for)h(the)g(X)h(axis,) 1861 3459 y(and)f(1000)g(bins)g(in)g(the)g(range)1861 3572 y(8000.)g(to)g(8100.)f(for)h(the)g(Y)h(axis.)191 3798 y([bin)f(@binFilter.txt])616 b(-)47 b(Use)g(the)g(contents)f(of)h (the)g(text)f(file)1861 3911 y(binFilter.txt)f(for)h(the)h(binning)1861 4024 y(specifications.)p eop end %%Page: 109 115 TeXDict begin 109 114 bop 0 1225 a Ff(Chapter)65 b(9)0 1687 y Fl(T)-19 b(emplate)76 b(Files)0 2180 y Fi(When)38 b(a)h(new)f(FITS)g(\014le)h(is)g(created)g(with)g(a)f(call)i(to)g (\014ts)p 2101 2180 28 4 v 32 w(create)p 2369 2180 V 35 w(\014le,)g(the)f(name)g(of)g(a)g(template)h(\014le)e(ma)m(y)0 2293 y(b)s(e)h(supplied)g(in)h(paren)m(theses)g(immediately)h(follo)m (wing)g(the)g(name)f(of)g(the)g(new)f(\014le)h(to)h(b)s(e)e(created.)71 b(This)0 2406 y(template)27 b(is)e(used)g(to)h(de\014ne)f(the)h (structure)f(of)h(one)f(or)h(more)g(HDUs)g(in)f(the)h(new)f(\014le.)39 b(The)25 b(template)i(\014le)e(ma)m(y)0 2518 y(b)s(e)32 b(another)h(FITS)f(\014le,)i(in)f(whic)m(h)f(case)i(the)f(newly)g (created)h(\014le)f(will)g(ha)m(v)m(e)h(exactly)h(the)e(same)g(k)m(eyw) m(ords)g(in)0 2631 y(eac)m(h)25 b(HDU)g(as)g(in)f(the)g(template)i (FITS)d(\014le,)j(but)d(all)j(the)e(data)h(units)e(will)i(b)s(e)f (\014lled)g(with)f(zeros.)40 b(The)24 b(template)0 2744 y(\014le)i(ma)m(y)h(also)g(b)s(e)e(an)h(ASCI)s(I)e(text)j(\014le,)g (where)f(eac)m(h)h(line)f(\(in)g(general\))i(describ)s(es)d(one)h(FITS) f(k)m(eyw)m(ord)i(record.)0 2857 y(The)j(format)h(of)f(the)h(ASCI)s(I)e (template)i(\014le)g(is)f(describ)s(ed)f(in)i(the)f(follo)m(wing)i (sections.)0 3188 y Fd(9.1)135 b(Detailed)47 b(T)-11 b(emplate)46 b(Line)f(F)-11 b(ormat)0 3438 y Fi(The)30 b(format)h(of)f(eac)m(h)i(ASCI)s(I)c(template)k(line)f(closely)h(follo) m(ws)f(the)g(format)g(of)f(a)h(FITS)f(k)m(eyw)m(ord)g(record:)95 3682 y Fe(KEYWORD)46 b(=)i(KEYVALUE)d(/)j(COMMENT)0 3926 y Fi(except)22 b(that)g(free)g(format)f(ma)m(y)h(b)s(e)f(used)f (\(e.g.,)25 b(the)d(equals)f(sign)h(ma)m(y)f(app)s(ear)g(at)h(an)m(y)g (p)s(osition)f(in)g(the)h(line\))g(and)0 4039 y(T)-8 b(AB)34 b(c)m(haracters)g(are)g(allo)m(w)m(ed)h(and)e(are)g(treated)h (the)g(same)f(as)h(space)f(c)m(haracters.)51 b(The)33 b(KEYV)-10 b(ALUE)33 b(and)0 4152 y(COMMENT)d(\014elds)g(are)h (optional.)43 b(The)30 b(equals)h(sign)f(c)m(haracter)j(is)d(also)i (optional,)g(but)e(it)h(is)f(recommended)0 4264 y(that)42 b(it)f(b)s(e)g(included)f(for)h(clarit)m(y)-8 b(.)75 b(An)m(y)41 b(template)i(line)e(that)h(b)s(egins)f(with)f(the)i(p)s (ound)d('#')i(c)m(haracter)i(is)0 4377 y(ignored)30 b(b)m(y)h(the)f (template)i(parser)e(and)g(ma)m(y)h(b)s(e)e(use)h(to)h(insert)g(commen) m(ts)g(in)m(to)g(the)g(template)h(\014le)e(itself.)0 4538 y(The)c(KEYW)m(ORD)g(name)g(\014eld)g(is)g(limited)h(to)g(8)f(c)m (haracters)h(in)f(length)h(and)e(only)h(the)g(letters)i(A-Z,)e(digits)h (0-9,)0 4650 y(and)h(the)g(h)m(yphen)f(and)h(underscore)g(c)m (haracters)h(ma)m(y)g(b)s(e)f(used,)g(without)h(an)m(y)f(em)m(b)s (edded)g(spaces.)40 b(Lo)m(w)m(ercase)0 4763 y(letters)22 b(in)f(the)h(template)g(k)m(eyw)m(ord)g(name)f(will)g(b)s(e)g(con)m(v)m (erted)i(to)f(upp)s(ercase.)36 b(Leading)22 b(spaces)f(in)g(the)h (template)0 4876 y(line)k(preceding)g(the)f(k)m(eyw)m(ord)h(name)g(are) g(generally)h(ignored,)g(except)f(if)g(the)g(\014rst)f(8)h(c)m (haracters)h(of)f(a)g(template)0 4989 y(line)f(are)h(all)g(blank,)g (then)f(the)g(en)m(tire)h(line)g(is)f(treated)h(as)f(a)h(FITS)e(commen) m(t)i(k)m(eyw)m(ord)g(\(with)f(a)h(blank)e(k)m(eyw)m(ord)0 5102 y(name\))31 b(and)f(is)g(copied)h(v)m(erbatim)g(in)m(to)g(the)g (FITS)e(header.)0 5262 y(The)37 b(KEYV)-10 b(ALUE)37 b(\014eld)g(ma)m(y)h(ha)m(v)m(e)g(an)m(y)g(allo)m(w)m(ed)h(FITS)e(data) h(t)m(yp)s(e:)54 b(c)m(haracter)39 b(string,)h(logical,)h(in)m(teger,)0 5375 y(real,)28 b(complex)g(in)m(teger,)h(or)d(complex)i(real.)40 b(In)m(teger)28 b(v)-5 b(alues)27 b(m)m(ust)f(b)s(e)g(within)g(the)h (allo)m(w)m(ed)i(range)e(of)g(a)g('signed)0 5488 y(long')h(v)-5 b(ariable;)29 b(some)f(C)e(compilers)i(only)f(suppp)s(ort)e(4-b)m(yte)j (long)g(in)m(tegers)g(with)f(a)g(range)h(from)e(-2147483648)0 5601 y(to)31 b(+2147483647,)k(whereas)30 b(other)h(C)f(compilers)h (supp)s(ort)e(8-b)m(yte)j(in)m(tegers)f(with)f(a)h(range)g(of)g(plus)e (or)i(min)m(us)0 5714 y(2**63.)1882 5942 y(109)p eop end %%Page: 110 116 TeXDict begin 110 115 bop 0 299 a Fi(110)2295 b Fg(CHAPTER)30 b(9.)71 b(TEMPLA)-8 b(TE)30 b(FILES)0 555 y Fi(The)23 b(c)m(haracter)h(string)f(v)-5 b(alues)24 b(need)f(not)g(b)s(e)g (enclosed)g(in)g(single)h(quote)g(c)m(haracters)g(unless)f(they)g(are)h (necessary)0 668 y(to)37 b(distinguish)e(the)i(string)f(from)f(a)i (di\013eren)m(t)g(data)f(t)m(yp)s(e)h(\(e.g.)59 b(2.0)38 b(is)e(a)g(real)h(but)f('2.0')h(is)f(a)h(string\).)58 b(The)0 781 y(k)m(eyw)m(ord)38 b(has)g(an)g(unde\014ned)d(\(n)m(ull\))k (v)-5 b(alue)38 b(if)g(the)g(template)h(record)f(only)g(con)m(tains)h (blanks)e(follo)m(wing)j(the)0 894 y("=")31 b(or)f(b)s(et)m(w)m(een)h (the)g("=")g(and)f(the)g("/")i(commen)m(t)f(\014eld)f(delimiter.)0 1054 y(String)c(k)m(eyw)m(ord)h(v)-5 b(alues)27 b(longer)g(than)f(68)h (c)m(haracters)h(\(the)f(maxim)m(um)f(length)h(that)g(will)g(\014t)f (in)g(a)h(single)g(FITS)0 1167 y(k)m(eyw)m(ord)41 b(record\))g(are)g(p) s(ermitted)f(using)g(the)h(CFITSIO)e(long)i(string)g(con)m(v)m(en)m (tion.)74 b(They)40 b(can)h(either)g(b)s(e)0 1280 y(sp)s(eci\014ed)28 b(as)i(a)f(single)h(long)f(line)h(in)e(the)i(template,)h(or)e(b)m(y)f (using)h(m)m(ultiple)h(lines)f(where)f(the)i(con)m(tin)m(uing)g(lines)0 1393 y(con)m(tain)i(the)e('CONTINUE')g(k)m(eyw)m(ord,)h(as)g(in)f(this) g(example:)95 1657 y Fe(LONGKEY)46 b(=)i('This)e(is)h(a)h(long)e (string)g(value)h(that)f(is)i(contin&')95 1770 y(CONTINUE)94 b('ued)46 b(over)h(2)g(records')f(/)h(comment)f(field)h(goes)f(here)0 2035 y Fi(The)29 b(format)h(of)g(template)h(lines)e(with)h(CONTINUE)e (k)m(eyw)m(ord)i(is)g(v)m(ery)g(strict:)41 b(3)30 b(spaces)g(m)m(ust)f (follo)m(w)i(CON-)0 2147 y(TINUE)f(and)g(the)g(rest)h(of)f(the)h(line)g (is)f(copied)h(v)m(erbatim)g(to)g(the)g(FITS)e(\014le.)0 2308 y(The)i(start)h(of)g(the)f(optional)i(COMMENT)e(\014eld)g(m)m(ust) h(b)s(e)e(preceded)i(b)m(y)f("/",)i(whic)m(h)e(is)h(used)f(to)h (separate)g(it)0 2421 y(from)e(the)g(k)m(eyw)m(ord)h(v)-5 b(alue)30 b(\014eld.)41 b(Exceptions)30 b(are)h(if)f(the)h(KEYW)m(ORD)g (name)f(\014eld)g(con)m(tains)h(COMMENT,)0 2533 y(HISTOR)-8 b(Y,)30 b(CONTINUE,)g(or)g(if)g(the)h(\014rst)f(8)g(c)m(haracters)i(of) f(the)f(template)i(line)f(are)g(blanks.)0 2694 y(More)c(than)f(one)h (Header-Data)i(Unit)e(\(HDU\))g(ma)m(y)g(b)s(e)f(de\014ned)f(in)h(the)h (template)h(\014le.)39 b(The)26 b(start)h(of)g(an)f(HDU)0 2806 y(de\014nition)k(is)g(denoted)h(with)f(a)h(SIMPLE)e(or)i(XTENSION) e(template)j(line:)0 2967 y(1\))i(SIMPLE)f(b)s(egins)g(a)h(Primary)g (HDU)g(de\014nition.)50 b(SIMPLE)33 b(ma)m(y)h(only)g(app)s(ear)f(as)h (the)g(\014rst)f(k)m(eyw)m(ord)h(in)0 3080 y(the)e(template)i(\014le.) 45 b(If)32 b(the)g(template)i(\014le)e(b)s(egins)f(with)h(XTENSION)f (instead)h(of)g(SIMPLE,)g(then)f(a)i(default)0 3192 y(empt)m(y)d (Primary)e(HDU)i(is)g(created,)h(and)d(the)i(template)h(is)e(then)g (assumed)f(to)i(de\014ne)f(the)h(k)m(eyw)m(ords)f(starting)0 3305 y(with)h(the)h(\014rst)e(extension)i(follo)m(wing)h(the)f(Primary) f(HDU.)0 3466 y(2\))35 b(XTENSION)e(marks)g(the)i(b)s(eginning)e(of)h (a)h(new)e(extension)i(HDU)f(de\014nition.)52 b(The)33 b(previous)h(HDU)h(will)0 3578 y(b)s(e)30 b(closed)h(at)g(this)f(p)s (oin)m(t)h(and)e(pro)s(cessing)i(of)f(the)h(next)f(extension)h(b)s (egins.)0 3918 y Fd(9.2)135 b(Auto-indexing)45 b(of)h(Keyw)l(ords)0 4169 y Fi(If)31 b(a)h(template)g(k)m(eyw)m(ord)g(name)f(ends)g(with)g (a)g("#")h(c)m(haracter,)i(it)e(is)f(said)g(to)h(b)s(e)f ('auto-indexed'.)44 b(Eac)m(h)32 b("#")0 4282 y(c)m(haracter)i(will)f (b)s(e)f(replaced)i(b)m(y)e(the)h(curren)m(t)g(in)m(teger)h(index)e(v) -5 b(alue,)34 b(whic)m(h)f(gets)g(reset)h(=)e(1)h(at)h(the)e(start)i (of)0 4395 y(eac)m(h)h(new)f(HDU)g(in)g(the)g(\014le)g(\(or)g(7)h(in)e (the)h(sp)s(ecial)h(case)g(of)f(a)g(GR)m(OUP)h(de\014nition\).)51 b(The)33 b(FIRST)g(indexed)0 4508 y(k)m(eyw)m(ord)c(in)f(eac)m(h)h (template)h(HDU)f(de\014nition)f(is)g(used)f(as)i(the)f('incremen)m (tor';)j(eac)m(h)e(subsequen)m(t)f(o)s(ccurrence)0 4620 y(of)k(this)f(SAME)g(k)m(eyw)m(ord)h(will)g(cause)g(the)g(index)f(v)-5 b(alue)32 b(to)g(b)s(e)f(incremen)m(ted.)44 b(This)31 b(b)s(eha)m(vior)g(can)h(b)s(e)f(rather)0 4733 y(subtle,)d(as)g (illustrated)h(in)e(the)h(follo)m(wing)h(examples)f(in)f(whic)m(h)h (the)g(TTYPE)e(k)m(eyw)m(ord)i(is)g(the)g(incremen)m(tor)g(in)0 4846 y(b)s(oth)i(cases:)95 5111 y Fe(TTYPE#)47 b(=)g(TIME)95 5224 y(TFORM#)g(=)g(1D)95 5337 y(TTYPE#)g(=)g(RATE)95 5449 y(TFORM#)g(=)g(1E)0 5714 y Fi(will)26 b(create)i(TTYPE1,)e(TF)m (ORM1,)i(TTYPE2,)f(and)e(TF)m(ORM2)i(k)m(eyw)m(ords.)40 b(But)26 b(if)g(the)g(template)h(lo)s(oks)f(lik)m(e,)p eop end %%Page: 111 117 TeXDict begin 111 116 bop 0 299 a Fg(9.3.)72 b(TEMPLA)-8 b(TE)30 b(P)-8 b(ARSER)30 b(DIRECTIVES)2028 b Fi(111)95 555 y Fe(TTYPE#)47 b(=)g(TIME)95 668 y(TTYPE#)g(=)g(RATE)95 781 y(TFORM#)g(=)g(1D)95 894 y(TFORM#)g(=)g(1E)0 1202 y Fi(this)31 b(results)f(in)h(a)g(FITS)f(\014les)h(with)f(TTYPE1,)h (TTYPE2,)g(TF)m(ORM2,)h(and)e(TF)m(ORM2,)i(whic)m(h)f(is)g(probably)0 1315 y(not)g(what)f(w)m(as)h(in)m(tended!)0 1706 y Fd(9.3)135 b(T)-11 b(emplate)46 b(P)l(arser)g(Directiv)l(es)0 1968 y Fi(In)29 b(addition)i(to)f(the)g(template)i(lines)e(whic)m(h)g (de\014ne)f(individual)h(k)m(eyw)m(ords,)g(the)g(template)i(parser)d (recognizes)0 2081 y(3)h(sp)s(ecial)h(directiv)m(es)g(whic)m(h)f(are)g (eac)m(h)h(preceded)f(b)m(y)f(the)h(bac)m(kslash)h(c)m(haracter:)90 b Fe(\\include,)45 b(\\group)p Fi(,)29 b(and)48 2194 y Fe(\\end)p Fi(.)0 2354 y(The)37 b('include')h(directiv)m(e)i(m)m(ust) d(b)s(e)h(follo)m(w)m(ed)h(b)m(y)f(a)g(\014lename.)63 b(It)38 b(forces)g(the)g(parser)f(to)i(temp)s(orarily)f(stop)0 2467 y(reading)d(the)g(curren)m(t)g(template)h(\014le)f(and)f(b)s(egin) h(reading)g(the)g(include)f(\014le.)55 b(Once)35 b(the)g(parser)f(reac) m(hes)i(the)0 2579 y(end)f(of)h(the)g(include)f(\014le)h(it)g(con)m (tin)m(ues)g(parsing)g(the)f(curren)m(t)h(template)h(\014le.)56 b(Include)35 b(\014les)h(can)g(b)s(e)f(nested,)0 2692 y(and)30 b(HDU)h(de\014nitions)f(can)g(span)g(m)m(ultiple)h(template)h (\014les.)0 2853 y(The)f(start)h(of)g(a)g(GR)m(OUP)h(de\014nition)e(is) h(denoted)g(with)f(the)h('group')g(directiv)m(e,)h(and)f(the)f(end)h (of)f(a)i(GR)m(OUP)0 2965 y(de\014nition)k(is)h(denoted)f(with)g(the)h ('end')f(directiv)m(e.)63 b(Eac)m(h)39 b(GR)m(OUP)e(con)m(tains)i(0)f (or)f(more)h(mem)m(b)s(er)f(blo)s(c)m(ks)0 3078 y(\(HDUs)44 b(or)f(GR)m(OUPs\).)79 b(Mem)m(b)s(er)42 b(blo)s(c)m(ks)i(of)f(t)m(yp)s (e)g(GR)m(OUP)g(can)g(con)m(tain)h(their)f(o)m(wn)g(mem)m(b)s(er)f(blo) s(c)m(ks.)0 3191 y(The)32 b(GR)m(OUP)g(de\014nition)g(itself)h(o)s (ccupies)g(one)f(FITS)g(\014le)g(HDU)h(of)f(sp)s(ecial)h(t)m(yp)s(e)f (\(GR)m(OUP)h(HDU\),)h(so)e(if)h(a)0 3304 y(template)f(sp)s(eci\014es)e (1)h(group)e(with)h(1)h(mem)m(b)s(er)f(HDU)h(lik)m(e:)0 3613 y Fe(\\group)0 3725 y(grpdescr)46 b(=)h('demo')0 3838 y(xtension)f(bintable)0 3951 y(#)h(this)g(bintable)f(has)h(0)g (cols,)f(0)i(rows)0 4064 y(\\end)0 4373 y Fi(then)30 b(the)h(parser)e(creates)j(a)f(FITS)f(\014le)g(with)g(3)h(HDUs)g(:)0 4681 y Fe(1\))47 b(dummy)g(PHDU)0 4794 y(2\))g(GROUP)g(HDU)f(\(has)h(1) h(member,)d(which)i(is)g(bintable)e(in)j(HDU)f(number)f(3\))0 4907 y(3\))h(bintable)f(\(member)g(of)h(GROUP)f(in)h(HDU)g(number)f (2\))0 5215 y Fi(T)-8 b(ec)m(hnically)32 b(sp)s(eaking,)e(the)f(GR)m (OUP)i(HDU)f(is)g(a)g(BINT)-8 b(ABLE)30 b(with)g(6)g(columns.)40 b(Applications)31 b(can)f(de\014ne)0 5328 y(additional)23 b(columns)f(in)f(a)i(GR)m(OUP)f(HDU)h(using)f(TF)m(ORMn)f(and)h(TTYPEn) f(\(where)g(n)h(is)g(7,)i(8,)h(....\))39 b(k)m(eyw)m(ords)0 5441 y(or)30 b(their)h(auto-indexing)g(equiv)-5 b(alen)m(ts.)0 5601 y(F)d(or)26 b(a)f(more)g(complicated)h(example)f(of)g(a)h (template)g(\014le)f(using)f(the)h(group)f(directiv)m(es,)k(lo)s(ok)d (at)g(the)g(sample.tpl)0 5714 y(\014le)30 b(that)h(is)g(included)e(in)i (the)f(CFITSIO)f(distribution.)p eop end %%Page: 112 118 TeXDict begin 112 117 bop 0 299 a Fi(112)2295 b Fg(CHAPTER)30 b(9.)71 b(TEMPLA)-8 b(TE)30 b(FILES)0 555 y Fd(9.4)135 b(F)-11 b(ormal)46 b(T)-11 b(emplate)45 b(Syn)l(tax)0 805 y Fi(The)30 b(template)i(syn)m(tax)f(can)f(formally)h(b)s(e)f (de\014ned)f(as)i(follo)m(ws:)191 1063 y Fe(TEMPLATE)45 b(=)j(BLOCK)e([)i(BLOCK)e(...)h(])334 1289 y(BLOCK)f(=)i({)f(HDU)g(|)h (GROUP)e(})334 1515 y(GROUP)g(=)i(\\GROUP)e([)h(BLOCK)g(...)g(])g (\\END)430 1741 y(HDU)f(=)i(XTENSION)d([)j(LINE)f(...)f(])i({)f (XTENSION)f(|)h(\\GROUP)f(|)i(\\END)f(|)g(EOF)g(})382 1967 y(LINE)f(=)i([)f(KEYWORD)f([)i(=)f(])h(])f([)g(VALUE)g(])g([)h(/)f (COMMENT)f(])191 2192 y(X)h(...)238 b(-)48 b(X)f(can)g(be)g(present)f (1)h(or)h(more)e(times)191 2305 y({)h(X)h(|)f(Y)h(})f(-)h(X)f(or)g(Y) 191 2418 y([)g(X)h(])238 b(-)48 b(X)f(is)g(optional)0 2676 y Fi(A)m(t)34 b(the)f(topmost)g(lev)m(el,)i(the)e(template)i (de\014nes)c(1)j(or)e(more)h(template)h(blo)s(c)m(ks.)49 b(Blo)s(c)m(ks)34 b(can)f(b)s(e)f(either)h(HDU)0 2789 y(\(Header)27 b(Data)h(Unit\))g(or)e(a)h(GR)m(OUP)-8 b(.)28 b(F)-8 b(or)27 b(eac)m(h)g(blo)s(c)m(k)g(the)g(parser)f(creates) i(1)f(\(or)g(more)f(for)h(GR)m(OUPs\))g(FITS)0 2902 y(\014le)j(HDUs.)0 3235 y Fd(9.5)135 b(Errors)0 3485 y Fi(In)24 b(general)h(the)f(\014ts)p 692 3485 28 4 v 33 w(execute)p 1019 3485 V 34 w(template\(\))i (function)e(tries)h(to)g(b)s(e)f(as)g(atomic)i(as)f(p)s(ossible,)g(so)f (either)h(ev)m(erything)0 3598 y(is)f(done)g(or)g(nothing)f(is)h(done.) 39 b(If)23 b(an)h(error)f(o)s(ccurs)h(during)f(parsing)g(of)h(the)g (template,)j(\014ts)p 3125 3598 V 33 w(execute)p 3452 3598 V 34 w(template\(\))0 3711 y(will)k(\(try)g(to\))h(delete)g(the)f (top)g(lev)m(el)h(BLOCK)e(\(with)h(all)g(its)h(c)m(hildren)e(if)h(an)m (y\))g(in)g(whic)m(h)f(the)h(error)f(o)s(ccurred,)0 3824 y(then)g(it)h(will)g(stop)f(reading)h(the)f(template)i(\014le)e(and)g (it)h(will)g(return)e(with)h(an)g(error.)0 4158 y Fd(9.6)135 b(Examples)0 4408 y Fi(1.)54 b(This)34 b(template)i(\014le)f(will)g (create)h(a)f(200)h(x)e(300)i(pixel)f(image,)j(with)c(4-b)m(yte)i(in)m (teger)g(pixel)f(v)-5 b(alues,)36 b(in)f(the)0 4521 y(primary)29 b(HDU:)95 4779 y Fe(SIMPLE)47 b(=)g(T)95 4891 y(BITPIX)g(=)g(32)95 5004 y(NAXIS)g(=)g(2)239 b(/)47 b(number)f(of)h(dimensions)95 5117 y(NAXIS1)g(=)g(100)95 b(/)47 b(length)f(of)h(first)g(axis)95 5230 y(NAXIS2)g(=)g(200)95 b(/)47 b(length)f(of)h(second)f(axis)95 5343 y(OBJECT)h(=)g(NGC)g(253)g(/)g(name)g(of)g(observed)f(object)0 5601 y Fi(The)35 b(allo)m(w)m(ed)i(v)-5 b(alues)36 b(of)f(BITPIX)g(are) h(8,)h(16,)h(32,)g(-32,)g(or)d(-64,)j(represen)m(ting,)f(resp)s(ectiv)m (ely)-8 b(,)39 b(8-bit)d(in)m(teger,)0 5714 y(16-bit)c(in)m(teger,)g (32-bit)f(in)m(teger,)h(32-bit)g(\015oating)f(p)s(oin)m(t,)g(or)f(64)h (bit)g(\015oating)g(p)s(oin)m(t)f(pixels.)p eop end %%Page: 113 119 TeXDict begin 113 118 bop 0 299 a Fg(9.6.)72 b(EXAMPLES)3039 b Fi(113)0 555 y(2.)39 b(T)-8 b(o)23 b(create)h(a)f(FITS)e(table,)26 b(the)c(template)i(\014rst)e(needs)g(to)i(include)e(XTENSION)g(=)g(T)-8 b(ABLE)23 b(or)f(BINT)-8 b(ABLE)0 668 y(to)31 b(de\014ne)e(whether)g (it)h(is)g(an)f(ASCI)s(I)g(or)g(binary)g(table,)i(and)f(NAXIS2)g(to)g (de\014ne)f(the)h(n)m(um)m(b)s(er)f(of)h(ro)m(ws)f(in)h(the)0 781 y(table.)50 b(Tw)m(o)34 b(template)g(lines)g(are)g(then)f(needed)f (to)i(de\014ne)f(the)g(name)h(\(TTYPEn\))e(and)h(FITS)g(data)h(format)0 894 y(\(TF)m(ORMn\))d(of)f(the)h(columns,)f(as)h(in)f(this)g(example:) 95 1154 y Fe(xtension)46 b(=)h(bintable)95 1267 y(naxis2)g(=)g(40)95 1380 y(ttype#)g(=)g(Name)95 1492 y(tform#)g(=)g(10a)95 1605 y(ttype#)g(=)g(Npoints)95 1718 y(tform#)g(=)g(j)95 1831 y(ttype#)g(=)g(Rate)95 1944 y(tunit#)g(=)g(counts/s)95 2057 y(tform#)g(=)g(e)0 2317 y Fi(The)26 b(ab)s(o)m(v)m(e)j(example)e (de\014nes)f(a)i(n)m(ull)f(primary)f(arra)m(y)h(follo)m(w)m(ed)i(b)m(y) e(a)g(40-ro)m(w)h(binary)e(table)i(extension)g(with)f(3)0 2430 y(columns)h(called)h('Name',)h('Np)s(oin)m(ts',)f(and)f('Rate',)i (with)e(data)h(formats)f(of)g('10A')i(\(ASCI)s(I)d(c)m(haracter)i (string\),)0 2543 y('1J')k(\(in)m(teger\))i(and)d('1E')i(\(\015oating)f (p)s(oin)m(t\),)h(resp)s(ectiv)m(ely)-8 b(.)50 b(Note)34 b(that)f(the)g(other)g(required)f(FITS)g(k)m(eyw)m(ords)0 2655 y(\(BITPIX,)37 b(NAXIS,)g(NAXIS1,)h(PCOUNT,)e(GCOUNT,)h(TFIELDS,)f (and)g(END\))h(do)g(not)g(need)f(to)h(b)s(e)f(ex-)0 2768 y(plicitly)j(de\014ned)d(in)i(the)f(template)i(b)s(ecause)f(their)g(v) -5 b(alues)38 b(can)g(b)s(e)f(inferred)f(from)i(the)f(other)h(k)m(eyw)m (ords)g(in)0 2881 y(the)d(template.)55 b(This)34 b(example)i(also)g (illustrates)f(that)h(the)f(templates)h(are)f(generally)h (case-insensitiv)m(e)h(\(the)0 2994 y(k)m(eyw)m(ord)29 b(names)g(and)g(TF)m(ORMn)f(v)-5 b(alues)30 b(are)f(con)m(v)m(erted)i (to)e(upp)s(er-case)g(in)f(the)h(FITS)g(\014le\))g(and)f(that)i(string) 0 3107 y(k)m(eyw)m(ord)h(v)-5 b(alues)31 b(generally)g(do)f(not)h(need) f(to)h(b)s(e)f(enclosed)h(in)f(quotes.)p eop end %%Page: 114 120 TeXDict begin 114 119 bop 0 299 a Fi(114)2295 b Fg(CHAPTER)30 b(9.)71 b(TEMPLA)-8 b(TE)30 b(FILES)p eop end %%Page: 115 121 TeXDict begin 115 120 bop 0 1225 a Ff(Chapter)65 b(10)0 1687 y Fl(Summary)76 b(of)i(all)f(FITSIO)0 1937 y(User-In)-6 b(terface)77 b(Subroutines)0 2429 y Fi(Error)29 b(Status)i(Routines)f (page)h(29)382 2696 y Fe(FTVERS\()46 b(>)h(version\))382 2809 y(FTGERR\(status,)d(>)j(errtext\))382 2922 y(FTGMSG\()f(>)h (errmsg\))382 3035 y(FTRPRT)f(\(stream,)f(>)j(status\))382 3147 y(FTPMSG\(errmsg\))382 3260 y(FTPMRK)382 3373 y(FTCMSG)382 3486 y(FTCMRK)0 3753 y Fi(FITS)30 b(File)h(Op)s(en)e(and)h(Close)h (Subroutines:)39 b(page)31 b(35)382 4020 y Fe (FTOPEN\(unit,filename,rwm)o(ode)o(,)42 b(>)47 b(blocksize,status\))382 4133 y(FTDKOPN\(unit,filename,rw)o(mod)o(e,)42 b(>)47 b(blocksize,status\))382 4246 y(FTNOPN\(unit,filename,rwm)o(ode)o(,)42 b(>)47 b(status\))382 4359 y(FTDOPN\(unit,filename,rwm)o(ode)o(,)42 b(>)47 b(status\))382 4472 y(FTTOPN\(unit,filename,rwm)o(ode)o(,)42 b(>)47 b(status\))382 4585 y(FTIOPN\(unit,filename,rwm)o(ode)o(,)42 b(>)47 b(status\))382 4698 y(FTREOPEN\(unit,)d(>)j(newunit,)f(status\)) 382 4811 y(FTINIT\(unit,filename,blo)o(cks)o(ize,)41 b(>)48 b(status\))382 4924 y(FTDKINIT\(unit,filename,b)o(loc)o(ksiz)o (e,)42 b(>)47 b(status\))382 5036 y(FTTPLT\(unit,)d(filename,)i (tplfilename,)e(>)j(status\))382 5149 y(FTFLUS\(unit,)d(>)k(status\)) 382 5262 y(FTCLOS\(unit,)c(>)k(status\))382 5375 y(FTDELT\(unit,)c(>)k (status\))382 5488 y(FTGIOU\()e(>)h(iounit,)f(status\))382 5601 y(FTFIOU\(iounit,)e(>)j(status\))0 5714 y(CFITS2Unit\(fitsfile)c (*ptr\))141 b(\(C)48 b(routine\))1882 5942 y Fi(115)p eop end %%Page: 116 122 TeXDict begin 116 121 bop 0 299 a Fi(116)281 b Fg(CHAPTER)30 b(10.)112 b(SUMMAR)-8 b(Y)32 b(OF)e(ALL)g(FITSIO)f(USER-INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)382 555 y Fe(CUnit2FITS\(int)44 b(unit\))380 b(\(C)47 b(routine\))382 668 y(FTEXTN\(filename,)c(>)48 b(nhdu,)e(status\))382 781 y(FTFLNM\(unit,)e(>)k(filename,)d(status\)) 382 894 y(FTFLMD\(unit,)f(>)k(iomode,)e(status\))382 1007 y(FTURLT\(unit,)e(>)k(urltype,)d(status\))382 1120 y(FTIURL\(filename,)e(>)48 b(filetype,)d(infile,)h(outfile,)f(extspec,) h(filter,)716 1233 y(binspec,)f(colspec,)h(status\))382 1346 y(FTRTNM\(filename,)d(>)48 b(rootname,)d(status\))382 1458 y(FTEXIST\(filename,)e(>)k(exist,)f(status\))0 1695 y Fi(HDU-Lev)m(el)33 b(Op)s(erations:)40 b(page)31 b(38)382 1932 y Fe(FTMAHD\(unit,nhdu,)43 b(>)k(hdutype,status\))382 2045 y(FTMRHD\(unit,nmove,)c(>)k(hdutype,status\))382 2158 y(FTGHDN\(unit,)d(>)k(nhdu\))382 2271 y(FTMNHD\(unit,)c(hdutype,)i (extname,)f(extver,)h(>)i(status\))382 2384 y(FTGHDT\(unit,)c(>)k (hdutype,)d(status\))382 2497 y(FTTHDU\(unit,)f(>)k(hdunum,)e(status\)) 382 2610 y(FTCRHD\(unit,)e(>)k(status\))382 2723 y (FTIIMG\(unit,bitpix,naxis)o(,na)o(xes,)41 b(>)48 b(status\))382 2836 y(FTITAB\(unit,rowlen,nrows)o(,tf)o(ield)o(s,tt)o(ype)o(,tbc)o (ol,t)o(for)o(m,tu)o(nit,)o(ext)o(name)o(,)42 b(>)716 2949 y(status\))382 3061 y(FTIBIN\(unit,nrows,tfield)o(s,t)o(type)o (,tfo)o(rm,)o(tuni)o(t,ex)o(tna)o(me,v)o(arid)o(at)f(>)48 b(status\))382 3174 y(FTRSIM\(unit,bitpix,naxis)o(,na)o(xes,)o(stat)o (us\))382 3287 y(FTDHDU\(unit,)c(>)k(hdutype,status\))382 3400 y(FTCPFL\(iunit,ounit,previ)o(ous)o(,)42 b(current,)j(following,)g (>)j(status\))382 3513 y(FTCOPY\(iunit,ounit,morek)o(eys)o(,)42 b(>)47 b(status\))382 3626 y(FTCPHD\(inunit,)d(outunit,)h(>)j(status\)) 382 3739 y(FTCPDT\(iunit,ounit,)42 b(>)48 b(status\))0 3976 y Fi(Subroutines)29 b(to)i(sp)s(ecify)f(or)g(mo)s(dify)g(the)g (structure)g(of)h(the)f(CHDU:)h(page)h(41)382 4213 y Fe(FTRDEF\(unit,)44 b(>)k(status\))93 b(\(DEPRECATED\))382 4326 y(FTPDEF\(unit,bitpix,naxis)o(,na)o(xes,)o(pcou)o(nt,)o(gcou)o (nt,)41 b(>)48 b(status\))93 b(\(DEPRECATED\))382 4439 y(FTADEF\(unit,rowlen,tfiel)o(ds,)o(tbco)o(l,tf)o(orm)o(,nro)o(ws)42 b(>)47 b(status\))94 b(\(DEPRECATED\))382 4551 y (FTBDEF\(unit,tfields,tfor)o(m,v)o(arid)o(at,n)o(row)o(s)42 b(>)47 b(status\))94 b(\(DEPRECATED\))382 4664 y(FTDDEF\(unit,bytlen,) 42 b(>)48 b(status\))93 b(\(DEPRECATED\))382 4777 y (FTPTHP\(unit,theap,)43 b(>)k(status\))0 5014 y Fi(Header)31 b(Space)f(and)g(P)m(osition)i(Subroutines:)39 b(page)31 b(43)382 5251 y Fe(FTHDEF\(unit,morekeys,)42 b(>)47 b(status\))382 5364 y(FTGHSP\(iunit,)d(>)j(keysexist,keysadd,status\))382 5477 y(FTGHPS\(iunit,)d(>)j(keysexist,key_no,status\))0 5714 y Fi(Read)31 b(or)f(W)-8 b(rite)32 b(Standard)d(Header)i (Subroutines:)39 b(page)31 b(43)p eop end %%Page: 117 123 TeXDict begin 117 122 bop 3764 299 a Fi(117)382 555 y Fe(FTPHPS\(unit,bitpix,naxis)o(,na)o(xes,)41 b(>)48 b(status\))382 668 y(FTPHPR\(unit,simple,bitpi)o(x,n)o(axis)o(,nax)o(es,)o(pcou)o (nt,g)o(cou)o(nt,e)o(xten)o(d,)41 b(>)48 b(status\))382 781 y(FTGHPR\(unit,maxdim,)42 b(>)48 b(simple,bitpix,naxis,naxe)o(s,p)o (coun)o(t,gc)o(oun)o(t,ex)o(tend)o(,)716 894 y(status\))382 1007 y(FTPHTB\(unit,rowlen,nrows)o(,tf)o(ield)o(s,tt)o(ype)o(,tbc)o (ol,t)o(for)o(m,tu)o(nit,)o(ext)o(name)o(,)42 b(>)716 1120 y(status\))382 1233 y(FTGHTB\(unit,maxdim,)g(>)48 b(rowlen,nrows,tfields,tty)o(pe,)o(tbco)o(l,tf)o(orm)o(,tun)o(it,)716 1346 y(extname,status\))382 1458 y(FTPHBN\(unit,nrows,tfield)o(s,t)o (type)o(,tfo)o(rm,)o(tuni)o(t,ex)o(tna)o(me,v)o(arid)o(at)41 b(>)48 b(status\))382 1571 y(FTGHBN\(unit,maxdim,)42 b(>)48 b(nrows,tfields,ttype,tfor)o(m,t)o(unit)o(,ext)o(nam)o(e,va)o (rida)o(t,)716 1684 y(status\))0 1942 y Fi(W)-8 b(rite)32 b(Keyw)m(ord)e(Subroutines:)39 b(page)31 b(45)382 2199 y Fe(FTPREC\(unit,card,)43 b(>)k(status\))382 2312 y (FTPCOM\(unit,comment,)42 b(>)48 b(status\))382 2425 y(FTPHIS\(unit,history,)42 b(>)48 b(status\))382 2538 y(FTPDAT\(unit,)c(>)k(status\))382 2651 y(FTPKY[JKLS]\(unit,keyword)o (,ke)o(yval)o(,com)o(men)o(t,)42 b(>)47 b(status\))382 2764 y(FTPKY[EDFG]\(unit,keyword)o(,ke)o(yval)o(,dec)o(ima)o(ls,c)o (omme)o(nt,)41 b(>)48 b(status\))382 2877 y(FTPKLS\(unit,keyword,keyv)o (al,)o(comm)o(ent,)41 b(>)47 b(status\))382 2990 y(FTPLSW\(unit,)d(>)k (status\))382 3103 y(FTPKYU\(unit,keyword,comm)o(ent)o(,)42 b(>)47 b(status\))382 3216 y(FTPKN[JKLS]\(unit,keyroot)o(,st)o(artn)o (o,no)o(_ke)o(ys,k)o(eyva)o(ls,)o(comm)o(ents)o(,)42 b(>)47 b(status\))382 3329 y(FTPKN[EDFG]\(unit,keyroot)o(,st)o(artn)o (o,no)o(_ke)o(ys,k)o(eyva)o(ls,)o(deci)o(mals)o(,co)o(mmen)o(ts,)41 b(>)907 3441 y(status\))382 3554 y(FTCPKYinunit,)j(outunit,)i(innum,)g (outnum,)f(keyroot,)h(>)h(status\))382 3667 y (FTPKYT\(unit,keyword,intv)o(al,)o(dblv)o(al,c)o(omm)o(ent,)41 b(>)48 b(status\))382 3780 y(FTPKTP\(unit,)c(filename,)i(>)h(status\)) 382 3893 y(FTPUNT\(unit,keyword,unit)o(s,)41 b(>)48 b(status\))0 4151 y Fi(Insert)30 b(Keyw)m(ord)g(Subroutines:)39 b(page)31 b(47)382 4408 y Fe(FTIREC\(unit,key_no,card,)41 b(>)47 b(status\))382 4521 y(FTIKY[JKLS]\(unit,keyword)o(,ke)o(yval)o(,com)o (men)o(t,)42 b(>)47 b(status\))382 4634 y(FTIKLS\(unit,keyword,keyv)o (al,)o(comm)o(ent,)41 b(>)47 b(status\))382 4747 y (FTIKY[EDFG]\(unit,keyword)o(,ke)o(yval)o(,dec)o(ima)o(ls,c)o(omme)o (nt,)41 b(>)48 b(status\))382 4860 y(FTIKYU\(unit,keyword,comm)o(ent)o (,)42 b(>)47 b(status\))0 5118 y Fi(Read)31 b(Keyw)m(ord)f (Subroutines:)39 b(page)31 b(47)382 5375 y Fe(FTGREC\(unit,key_no,)42 b(>)48 b(card,status\))382 5488 y(FTGKYN\(unit,key_no,)42 b(>)48 b(keyword,value,comment,st)o(atu)o(s\))382 5601 y(FTGCRD\(unit,keyword,)42 b(>)48 b(card,status\))382 5714 y(FTGNXK\(unit,inclist,ninc)o(,ex)o(clis)o(t,ne)o(xc,)41 b(>)48 b(card,status\))p eop end %%Page: 118 124 TeXDict begin 118 123 bop 0 299 a Fi(118)281 b Fg(CHAPTER)30 b(10.)112 b(SUMMAR)-8 b(Y)32 b(OF)e(ALL)g(FITSIO)f(USER-INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)382 555 y Fe(FTGKEY\(unit,keyword,)42 b(>)48 b(value,comment,status\))382 668 y(FTGKY[EDJKLS]\(unit,keywo)o (rd,)41 b(>)48 b(keyval,comment,status\))382 781 y (FTGKSL\(unit,keyword,)42 b(>)48 b(length,status\))382 894 y(FTGSKY\(unit,keyword,firs)o(tch)o(ar,m)o(axch)o(ar,)o(>)42 b(keyval,length,comment,st)o(atus)o(\))382 1007 y (FTGKN[EDJKLS]\(unit,keyro)o(ot,)o(star)o(tno,)o(max)o(_key)o(s,)g(>)47 b(keyvals,nfound,status\))382 1120 y(FTGKYT\(unit,keyword,)42 b(>)48 b(intval,dblval,comment,s)o(tat)o(us\))382 1233 y(FTGUNT\(unit,keyword,)42 b(>)48 b(units,status\))0 1489 y Fi(Mo)s(dify)30 b(Keyw)m(ord)g(Subroutines:)39 b(page)31 b(49)382 1745 y Fe(FTMREC\(unit,key_no,card,)41 b(>)47 b(status\))382 1858 y(FTMCRD\(unit,keyword,card)o(,)42 b(>)47 b(status\))382 1971 y(FTMNAM\(unit,oldkey,keywo)o(rd,)41 b(>)48 b(status\))382 2084 y(FTMCOM\(unit,keyword,comm)o(ent)o(,)42 b(>)47 b(status\))382 2197 y(FTMKY[JKLS]\(unit,keyword)o(,ke)o(yval)o (,com)o(men)o(t,)42 b(>)47 b(status\))382 2310 y (FTMKLS\(unit,keyword,keyv)o(al,)o(comm)o(ent,)41 b(>)47 b(status\))382 2422 y(FTMKY[EDFG]\(unit,keyword)o(,ke)o(yval)o(,dec)o (ima)o(ls,c)o(omme)o(nt,)41 b(>)48 b(status\))382 2535 y(FTMKYU\(unit,keyword,comm)o(ent)o(,)42 b(>)47 b(status\))0 2792 y Fi(Up)s(date)30 b(Keyw)m(ord)g(Subroutines:)39 b(page)32 b(50)382 3048 y Fe(FTUCRD\(unit,keyword,card)o(,)42 b(>)47 b(status\))382 3161 y(FTUKY[JKLS]\(unit,keyword)o(,ke)o(yval)o (,com)o(men)o(t,)42 b(>)47 b(status\))382 3274 y (FTUKLS\(unit,keyword,keyv)o(al,)o(comm)o(ent,)41 b(>)47 b(status\))382 3386 y(FTUKY[EDFG]\(unit,keyword)o(,ke)o(yval)o(,dec)o (ima)o(ls,c)o(omme)o(nt,)41 b(>)48 b(status\))382 3499 y(FTUKYU\(unit,keyword,comm)o(ent)o(,)42 b(>)47 b(status\))0 3756 y Fi(Delete)33 b(Keyw)m(ord)d(Subroutines:)39 b(page)31 b(51)382 4012 y Fe(FTDREC\(unit,key_no,)42 b(>)48 b(status\))382 4125 y(FTDKEY\(unit,keyword,)42 b(>)48 b(status\))0 4381 y Fi(De\014ne)31 b(Data)h(Scaling)f(P)m(arameters)g(and)f(Unde\014ned)f (Pixel)i(Flags:)42 b(page)31 b(51)382 4637 y Fe (FTPSCL\(unit,bscale,bzero)o(,)42 b(>)47 b(status\))382 4750 y(FTTSCL\(unit,colnum,tscal)o(,tz)o(ero,)41 b(>)48 b(status\))382 4863 y(FTPNUL\(unit,blank,)43 b(>)k(status\))382 4976 y(FTSNUL\(unit,colnum,snull)41 b(>)47 b(status\))382 5089 y(FTTNUL\(unit,colnum,tnull)41 b(>)47 b(status\))0 5345 y Fi(FITS)30 b(Primary)f(Arra)m(y)i(or)f(IMA)m(GE)i(Extension)e (I/O)h(Subroutines:)39 b(page)31 b(52)382 5601 y Fe(FTGIDT\(unit,)44 b(>)k(bitpix,status\))382 5714 y(FTGIET\(unit,)c(>)k(bitpix,status\))p eop end %%Page: 119 125 TeXDict begin 119 124 bop 3764 299 a Fi(119)382 555 y Fe(FTGIDM\(unit,)44 b(>)k(naxis,status\))382 668 y(FTGISZ\(unit,)c (maxdim,)i(>)i(naxes,status\))382 781 y(FTGIPR\(unit,)c(maxdim,)i(>)i (bitpix,naxis,naxes,stat)o(us\))382 894 y(FTPPR[BIJKED]\(unit,group)o (,fp)o(ixel)o(,nel)o(eme)o(nts,)o(valu)o(es,)41 b(>)48 b(status\))382 1007 y(FTPPN[BIJKED]\(unit,group)o(,fp)o(ixel)o(,nel)o (eme)o(nts,)o(valu)o(es,)o(null)o(val)41 b(>)48 b(status\))382 1120 y(FTPPRU\(unit,group,fpixel)o(,ne)o(leme)o(nts,)41 b(>)47 b(status\))382 1233 y(FTGPV[BIJKED]\(unit,group)o(,fp)o(ixel)o (,nel)o(eme)o(nts,)o(null)o(val)o(,)42 b(>)47 b(values,anyf,status\)) 382 1346 y(FTGPF[BIJKED]\(unit,group)o(,fp)o(ixel)o(,nel)o(eme)o(nts,) 41 b(>)48 b(values,flagvals,anyf,st)o(atu)o(s\))382 1458 y(FTPGP[BIJKED]\(unit,group)o(,fp)o(arm,)o(npar)o(m,v)o(alue)o(s,)42 b(>)47 b(status\))382 1571 y(FTGGP[BIJKED]\(unit,group)o(,fp)o(arm,)o (npar)o(m,)41 b(>)48 b(values,status\))382 1684 y (FTP2D[BIJKED]\(unit,group)o(,di)o(m1,n)o(axis)o(1,n)o(axis)o(2,im)o (age)o(,)42 b(>)47 b(status\))382 1797 y(FTP3D[BIJKED]\(unit,group)o (,di)o(m1,d)o(im2,)o(nax)o(is1,)o(naxi)o(s2,)o(naxi)o(s3,c)o(ube)o(,)42 b(>)47 b(status\))382 1910 y(FTG2D[BIJKED]\(unit,group)o(,nu)o(llva)o (l,di)o(m1,)o(naxi)o(s1,n)o(axi)o(s2,)41 b(>)48 b(image,anyf,status\)) 382 2023 y(FTG3D[BIJKED]\(unit,group)o(,nu)o(llva)o(l,di)o(m1,)o(dim2)o (,nax)o(is1)o(,nax)o(is2,)o(nax)o(is3,)41 b(>)1002 2136 y(cube,anyf,status\))382 2249 y(FTPSS[BIJKED]\(unit,group)o(,na)o(xis,) o(naxe)o(s,f)o(pixe)o(ls,l)o(pix)o(els,)o(arra)o(y,)g(>)48 b(status\))382 2362 y(FTGSV[BIJKED]\(unit,group)o(,na)o(xis,)o(naxe)o (s,f)o(pixe)o(ls,l)o(pix)o(els,)o(incs)o(,nu)o(llva)o(l,)42 b(>)1002 2475 y(array,anyf,status\))382 2588 y (FTGSF[BIJKED]\(unit,group)o(,na)o(xis,)o(naxe)o(s,f)o(pixe)o(ls,l)o (pix)o(els,)o(incs)o(,)g(>)1002 2700 y(array,flagvals,anyf,statu)o(s\)) 0 2974 y Fi(T)-8 b(able)31 b(Column)e(Information)i(Subroutines:)39 b(page)31 b(55)382 3247 y Fe(FTGNRW\(unit,)44 b(>)k(nrows,)e(status\)) 382 3360 y(FTGNCL\(unit,)e(>)k(ncols,)e(status\))382 3473 y(FTGCNO\(unit,casesen,colt)o(emp)o(late)o(,)c(>)47 b(colnum,status\))382 3586 y(FTGCNN\(unit,casesen,colt)o(emp)o(late)o (,)42 b(>)47 b(colnam,colnum,status\))382 3699 y(FTGTCL\(unit,colnum,) 42 b(>)48 b(datacode,repeat,width,st)o(atu)o(s\))382 3812 y(FTEQTY\(unit,colnum,)42 b(>)48 b(datacode,repeat,width,st)o(atu) o(s\))382 3925 y(FTGCDW\(unit,colnum,)42 b(>)48 b(dispwidth,status\)) 382 4038 y(FTGACL\(unit,colnum,)42 b(>)716 4151 y (ttype,tbcol,tunit,tform,)o(tsca)o(l,t)o(zero)o(,snu)o(ll,)o(tdis)o (p,st)o(atu)o(s\))382 4264 y(FTGBCL\(unit,colnum,)g(>)716 4377 y(ttype,tunit,datatype,rep)o(eat,)o(tsc)o(al,t)o(zero)o(,tn)o (ull,)o(tdis)o(p,s)o(tatu)o(s\))382 4489 y(FTPTDM\(unit,colnum,naxis)o (,na)o(xes,)f(>)48 b(status\))382 4602 y(FTGTDM\(unit,colnum,maxdi)o (m,)41 b(>)48 b(naxis,naxes,status\))382 4715 y (FTDTDM\(unit,tdimstr,coln)o(um,)o(maxd)o(im,)41 b(>)48 b(naxis,naxes,)c(status\))382 4828 y(FTGRSZ\(unit,)g(>)k (nrows,status\))0 5102 y Fi(Lo)m(w-Lev)m(el)32 b(T)-8 b(able)31 b(Access)h(Subroutines:)39 b(page)31 b(58)382 5375 y Fe(FTGTBS\(unit,frow,startch)o(ar,)o(ncha)o(rs,)41 b(>)48 b(string,status\))382 5488 y(FTPTBS\(unit,frow,startch)o(ar,)o (ncha)o(rs,s)o(tri)o(ng,)41 b(>)48 b(status\))382 5601 y(FTGTBB\(unit,frow,startch)o(ar,)o(ncha)o(rs,)41 b(>)48 b(array,status\))382 5714 y(FTPTBB\(unit,frow,startch)o(ar,)o(ncha)o (rs,a)o(rra)o(y,)42 b(>)47 b(status\))p eop end %%Page: 120 126 TeXDict begin 120 125 bop 0 299 a Fi(120)281 b Fg(CHAPTER)30 b(10.)112 b(SUMMAR)-8 b(Y)32 b(OF)e(ALL)g(FITSIO)f(USER-INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)0 555 y Fi(Edit)g(Ro)m(ws)h(or)f(Columns)g (page)h(59)382 813 y Fe(FTIROW\(unit,frow,nrows,)41 b(>)48 b(status\))382 926 y(FTDROW\(unit,frow,nrows,)41 b(>)48 b(status\))382 1039 y(FTDRRG\(unit,rowrange,)42 b(>)47 b(status\))382 1152 y(FTDRWS\(unit,rowlist,nrow)o(s,)41 b(>)48 b(status\))382 1264 y(FTICOL\(unit,colnum,ttype)o(,tf)o(orm,)41 b(>)48 b(status\))382 1377 y(FTICLS\(unit,colnum,ncols)o(,tt)o(ype,)o (tfor)o(m,)41 b(>)48 b(status\))382 1490 y(FTMVEC\(unit,colnum,newve)o (cle)o(n,)42 b(>)47 b(status\))382 1603 y(FTDCOL\(unit,colnum,)42 b(>)48 b(status\))382 1716 y(FTCPCL\(inunit,outunit,in)o(col)o(num,)o (outc)o(oln)o(um,c)o(reat)o(eco)o(l,)42 b(>)47 b(status\);)0 1974 y Fi(Read)31 b(and)e(W)-8 b(rite)32 b(Column)e(Data)i(Routines)e (page)h(60)382 2231 y Fe(FTPCL[SLBIJKEDCM]\(unit,c)o(oln)o(um,f)o(row,) o(fel)o(em,n)o(elem)o(ent)o(s,va)o(lues)o(,)42 b(>)47 b(status\))382 2344 y(FTPCN[BIJKED]\(unit,colnu)o(m,f)o(row,)o(fele)o (m,n)o(elem)o(ents)o(,va)o(lues)o(,nul)o(lva)o(l)42 b(>)47 b(status\))382 2457 y(FTPCLX\(unit,colnum,frow,)o(fbi)o(t,nb)o(it,l)o (ray)o(,)42 b(>)47 b(status\))382 2570 y(FTPCLU\(unit,colnum,frow,)o (fel)o(em,n)o(elem)o(ent)o(s,)42 b(>)47 b(status\))382 2683 y(FTGCL\(unit,colnum,frow,f)o(ele)o(m,ne)o(leme)o(nts)o(,)42 b(>)47 b(values,status\))382 2796 y(FTGCV[SBIJKEDCM]\(unit,co)o(lnu)o (m,fr)o(ow,f)o(ele)o(m,ne)o(leme)o(nts)o(,nul)o(lval)o(,)42 b(>)1098 2909 y(values,anyf,status\))382 3022 y (FTGCF[SLBIJKEDCM]\(unit,c)o(oln)o(um,f)o(row,)o(fel)o(em,n)o(elem)o (ent)o(s,)g(>)1193 3135 y(values,flagvals,anyf,stat)o(us\))382 3247 y(FTGSV[BIJKED]\(unit,colnu)o(m,n)o(axis)o(,nax)o(es,)o(fpix)o (els,)o(lpi)o(xels)o(,inc)o(s,n)o(ullv)o(al,)f(>)1002 3360 y(array,anyf,status\))382 3473 y(FTGSF[BIJKED]\(unit,colnu)o(m,n)o (axis)o(,nax)o(es,)o(fpix)o(els,)o(lpi)o(xels)o(,inc)o(s,)g(>)1002 3586 y(array,flagvals,anyf,statu)o(s\))382 3699 y (FTGCX\(unit,colnum,frow,f)o(bit)o(,nbi)o(t,)h(>)47 b(lray,status\))382 3812 y(FTGCX[IJD]\(unit,colnum,f)o(row)o(,nro)o(ws,f)o(bit)o(,nbi)o(t,) 42 b(>)47 b(array,status\))382 3925 y(FTGDES\(unit,colnum,rownu)o(m,)41 b(>)48 b(nelements,offset,status\))382 4038 y (FTPDES\(unit,colnum,rownu)o(m,n)o(elem)o(ents)o(,of)o(fset)o(,)42 b(>)47 b(status\))0 4295 y Fi(Ro)m(w)31 b(Selection)h(and)d(Calculator) j(Routines:)41 b(page)31 b(64)382 4553 y Fe(FTFROW\(unit,expr,firstro)o (w,)41 b(nrows,)47 b(>)g(n_good_rows,)d(row_status,)h(status\))382 4666 y(FTFFRW\(unit,)f(expr,)j(>)g(rownum,)f(status\))382 4779 y(FTSROW\(inunit,)e(outunit,)h(expr,)i(>)g(status)f(\))382 4892 y(FTCROW\(unit,datatype,exp)o(r,f)o(irst)o(row,)o(nel)o(emen)o (ts,n)o(ulv)o(al,)41 b(>)620 5005 y(array,anynul,status\))382 5118 y(FTCALC\(inunit,)j(expr,)i(outunit,)g(parName,)f(parInfo,)h(>)h (status\))382 5230 y(FTCALC_RNG\(inunit,)c(expr,)j(outunit,)g(parName,) f(parInfo,)573 5343 y(nranges,)g(firstrow,)h(lastrow,)f(>)j(status\)) 382 5456 y(FTTEXP\(unit,)c(expr,)j(>)g(datatype,)e(nelem,)h(naxis,)h (naxes,)f(status\))0 5714 y Fi(Celestial)32 b(Co)s(ordinate)f(System)f (Subroutines:)39 b(page)31 b(65)p eop end %%Page: 121 127 TeXDict begin 121 126 bop 3764 299 a Fi(121)382 555 y Fe(FTGICS\(unit,)44 b(>)k(xrval,yrval,xrpix,yrpix)o(,xin)o(c,yi)o(nc,)o (rot,)o(coor)o(dty)o(pe,s)o(tatu)o(s\))382 668 y (FTGTCS\(unit,xcol,ycol,)42 b(>)716 781 y(xrval,yrval,xrpix,yrpix,)o (xinc)o(,yi)o(nc,r)o(ot,c)o(oor)o(dtyp)o(e,st)o(atu)o(s\))382 894 y(FTWLDP\(xpix,ypix,xrval,y)o(rva)o(l,xr)o(pix,)o(yrp)o(ix,x)o (inc,)o(yin)o(c,ro)o(t,)1241 1007 y(coordtype,)j(>)i (xpos,ypos,status\))382 1120 y(FTXYPX\(xpos,ypos,xrval,y)o(rva)o(l,xr)o (pix,)o(yrp)o(ix,x)o(inc,)o(yin)o(c,ro)o(t,)1241 1233 y(coordtype,)e(>)i(xpix,ypix,status\))0 1490 y Fi(File)32 b(Chec)m(ksum)d(Subroutines:)40 b(page)31 b(67)382 1748 y Fe(FTPCKS\(unit,)44 b(>)k(status\))382 1861 y(FTUCKS\(unit,)c(>)k (status\))382 1974 y(FTVCKS\(unit,)c(>)k(dataok,hduok,status\))382 2087 y(FTGCKS\(unit,)c(>)k(datasum,hdusum,status\))382 2199 y(FTESUM\(sum,complement,)42 b(>)47 b(checksum\))382 2312 y(FTDSUM\(checksum,compleme)o(nt,)41 b(>)48 b(sum\))0 2683 y Fi(Time)30 b(and)g(Date)i(Utilit)m(y)h(Subroutines:)39 b(page)31 b(68)382 2940 y Fe(FTGSDT\()46 b(>)h(day,)g(month,)f(year,)g (status)g(\))382 3053 y(FTGSTM\(>)f(datestr,)h(timeref,)f(status\))382 3166 y(FTDT2S\()h(year,)g(month,)g(day,)h(>)g(datestr,)f(status\))382 3279 y(FTTM2S\()g(year,)g(month,)g(day,)h(hour,)f(minute,)g(second,)g (decimals,)764 3392 y(>)h(datestr,)f(status\))382 3505 y(FTS2DT\(datestr,)d(>)48 b(year,)e(month,)g(day,)h(status\))382 3618 y(FTS2TM\(datestr,)c(>)48 b(year,)e(month,)g(day,)h(hour,)f (minute,)g(second,)g(status\))0 3876 y Fi(General)31 b(Utilit)m(y)i(Subroutines:)39 b(page)31 b(69)382 4133 y Fe(FTGHAD\(unit,)44 b(>)k(curaddr,nextaddr\))382 4246 y(FTUPCH\(string\))382 4359 y(FTCMPS\(str_template,stri)o(ng,)o(case)o (sen,)41 b(>)47 b(match,exact\))382 4472 y(FTTKEY\(keyword,)c(>)48 b(status\))382 4585 y(FTTREC\(card,)c(>)k(status\))382 4698 y(FTNCHK\(unit,)c(>)k(status\))382 4811 y(FTGKNM\(unit,)c(>)k (keyword,)d(keylength,)g(status\))382 4924 y(FTMKKY\(keyword,)e (value,comment,)h(>)k(card,)e(status\))382 5036 y(FTPSVC\(card,)e(>)k (value,comment,status\))382 5149 y(FTKEYN\(keyroot,seq_no,)42 b(>)47 b(keyword,status\))382 5262 y(FTNKEY\(seq_no,keyroot,)42 b(>)47 b(keyword,status\))382 5375 y(FTDTYP\(value,)d(>)j (dtype,status\))382 5488 y(class)f(=)i(FTGKCL\(card\))382 5601 y(FTASFM\(tform,)c(>)j(datacode,width,decimals,st)o(atus)o(\))382 5714 y(FTBNFM\(tform,)d(>)j(datacode,repeat,width,stat)o(us\))p eop end %%Page: 122 128 TeXDict begin 122 127 bop 0 299 a Fi(122)281 b Fg(CHAPTER)30 b(10.)112 b(SUMMAR)-8 b(Y)32 b(OF)e(ALL)g(FITSIO)f(USER-INTERF)-10 b(A)m(CE)30 b(SUBR)m(OUTINES)382 555 y Fe(FTGABC\(tfields,tform,spa)o (ce,)41 b(>)48 b(rowlen,tbcol,status\))382 668 y(FTGTHD\(template,)43 b(>)48 b(card,hdtype,status\))382 781 y(FTRWRG\(rowlist,)43 b(maxrows,)j(maxranges,)f(>)i(numranges,)e(rangemin,)716 894 y(rangemax,)g(status\))p eop end %%Page: 123 129 TeXDict begin 123 128 bop 0 1225 a Ff(Chapter)65 b(11)0 1687 y Fl(P)-6 b(arameter)77 b(De\014nitions)0 2180 y Fe(anyf)47 b(-)g(\(logical\))e(set)i(to)g(TRUE)g(if)g(any)g(of)g(the)g (returned)f(data)g(values)h(are)f(undefined)0 2293 y(array)g(-)i(\(any) e(datatype)g(except)g(character\))f(array)h(of)i(bytes)e(to)h(be)g (read)g(or)g(written.)0 2406 y(bitpix)f(-)i(\(integer\))d(bits)h(per)h (pixel:)f(8,)i(16,)f(32,)f(-32,)h(or)g(-64)0 2518 y(blank)f(-)i (\(integer\))d(value)h(used)h(for)g(undefined)e(pixels)h(in)i(integer)d (primary)h(array)0 2631 y(blank)g(-)i(\(integer*8\))d(value)h(used)h (for)f(undefined)g(pixels)g(in)h(integer)f(primary)g(array)0 2744 y(blocksize)f(-)j(\(integer\))d(2880-byte)g(logical)h(record)g (blocking)g(factor)477 2857 y(\(if)h(0)h(<)f(blocksize)e(<)j(11\))f(or) g(the)g(actual)f(block)g(size)h(in)g(bytes)477 2970 y(\(if)g(10)g(<)h (blocksize)d(<)j(28800\).)93 b(As)47 b(of)g(version)f(3.3)h(of)g (FITSIO,)477 3083 y(blocksizes)e(greater)h(than)h(2880)f(are)h(no)g (longer)g(supported.)0 3196 y(bscale)f(-)i(\(double)d(precision\))g (scaling)h(factor)g(for)h(the)g(primary)f(array)0 3309 y(bytlen)g(-)i(\(integer\))d(length)h(of)h(the)g(data)g(unit,)f(in)h (bytes)0 3422 y(bzero)f(-)i(\(double)e(precision\))f(zero)h(point)h (for)g(primary)e(array)i(scaling)0 3535 y(card)g(-)g(\(character*80\))d (header)i(record)g(to)h(be)h(read)e(or)h(written)0 3648 y(casesen)f(-)h(\(logical\))f(will)g(string)g(matching)g(be)h(case)g (sensitive?)0 3760 y(checksum)f(-)h(\(character*16\))d(encoded)i (checksum)f(string)0 3873 y(colname)h(-)h(\(character\))e(ASCII)h(name) h(of)g(the)g(column)0 3986 y(colnum)f(-)i(\(integer\))d(number)h(of)h (the)g(column)f(\(first)g(column)g(=)i(1\))0 4099 y(coltemplate)d(-)i (\(character\))e(template)g(string)i(to)g(be)g(matched)f(to)h(column)f (names)0 4212 y(comment)g(-)h(\(character\))e(the)i(keyword)f(comment)g (field)0 4325 y(comments)g(-)h(\(character)e(array\))h(keyword)g (comment)g(fields)0 4438 y(compid)g(-)i(\(integer\))d(the)i(type)f(of)i (computer)d(that)i(the)g(program)e(is)j(running)d(on)0 4551 y(complement)g(-)i(\(logical\))f(should)g(the)h(checksum)e(be)i (complemented?)0 4664 y(coordtype)e(-)j(\(character\))c(type)j(of)g (coordinate)e(projection)g(\(-SIN,)h(-TAN,)h(-ARC,)477 4777 y(-NCP,)g(-GLS,)f(-MER,)g(or)i(-AIT\))0 4890 y(cube)f(-)g(3D)g (data)g(cube)g(of)g(the)g(appropriate)d(datatype)0 5002 y(curaddr)i(-)h(\(integer\))f(starting)f(address)h(\(in)h(bytes\))f(of) h(the)g(CHDU)0 5115 y(current)f(-)h(\(integer\))f(if)h(not)g(equal)f (to)h(0,)g(copy)g(the)g(current)f(HDU)0 5228 y(datacode)g(-)h (\(integer\))e(symbolic)h(code)g(of)i(the)f(binary)f(table)g(column)g (datatype)0 5341 y(dataok)g(-)i(\(integer\))d(was)i(the)g(data)f(unit)h (verification)d(successful)h(\(=1\))i(or)430 5454 y(not)f(\(=)i(-1\).) 94 b(Equals)46 b(zero)h(if)g(the)g(DATASUM)f(keyword)f(is)j(not)f (present.)0 5567 y(datasum)f(-)h(\(double)f(precision\))f(32-bit)h(1's) h(complement)e(checksum)h(for)h(the)f(data)h(unit)0 5680 y(datatype)f(-)h(\(character\))e(datatype)g(\(format\))h(of)h(the)g (binary)f(table)g(column)1882 5942 y Fi(123)p eop end %%Page: 124 130 TeXDict begin 124 129 bop 0 299 a Fi(124)1779 b Fg(CHAPTER)30 b(11.)112 b(P)-8 b(ARAMETER)30 b(DEFINITIONS)0 555 y Fe(datestr)94 b(-)47 b(\(string\))f(FITS)g(date/time)f(string:)h ('YYYY-MM-DDThh:mm:ss.ddd')o(,)525 668 y('YYYY-MM-dd',)e(or)j ('dd/mm/yy')0 781 y(day)g(-)g(\(integer\))f(current)f(day)i(of)h(the)e (month)0 894 y(dblval)g(-)i(\(double)d(precision\))g(fractional)g(part) i(of)g(the)g(keyword)f(value)0 1007 y(decimals)g(-)h(\(integer\))e (number)h(of)i(decimal)d(places)h(to)i(be)f(displayed)0 1120 y(dim1)g(-)g(\(integer\))e(actual)h(size)h(of)g(the)g(first)g (dimension)e(of)i(the)g(image)f(or)h(cube)g(array)0 1233 y(dim2)g(-)g(\(integer\))e(actual)h(size)h(of)g(the)g(second)f (dimension)g(of)h(the)g(cube)f(array)0 1346 y(dispwidth)f(-)j (\(integer\))d(-)i(the)g(display)f(width)h(\(length)e(of)j(string\))d (for)i(a)h(column)0 1458 y(dtype)e(-)i(\(character\))d(datatype)g(of)i (the)g(keyword)f(\('C',)g('L',)h('I',)94 b(or)48 b('F'\))764 1571 y(C)f(=)h(character)d(string)764 1684 y(L)i(=)h(logical)764 1797 y(I)f(=)h(integer)764 1910 y(F)f(=)h(floating)d(point)h(number)0 2023 y(errmsg)g(-)i(\(character*80\))43 b(oldest)k(error)f(message)g (on)h(the)g(internal)e(stack)0 2136 y(errtext)h(-)h(\(character*30\))d (descriptive)h(error)h(message)g(corresponding)e(to)j(error)g(number)0 2249 y(casesen)f(-)h(\(logical\))f(true)g(if)h(column)f(name)h (matching)f(is)h(case)f(sensitive)0 2362 y(exact)g(-)i(\(logical\))d (do)i(the)g(strings)f(match)g(exactly,)g(or)h(were)g(wildcards)e(used?) 0 2475 y(exclist)94 b(\(character)45 b(array\))h(list)g(of)h(names)g (to)g(be)g(excluded)f(from)g(search)0 2588 y(exists)142 b(-)47 b(flag)g(indicating)e(whether)g(the)i(file)g(or)g(compressed)e (file)i(exists)f(on)h(disk)0 2700 y(extend)f(-)i(\(logical\))d(true)h (if)i(there)e(may)h(be)g(extensions)e(following)g(the)i(primary)f(data) 0 2813 y(extname)g(-)h(\(character\))e(value)h(of)i(the)e(EXTNAME)g (keyword)g(\(if)h(not)g(blank\))0 2926 y(fbit)g(-)g(\(integer\))e (first)i(bit)g(in)g(the)g(field)f(to)h(be)g(read)g(or)g(written)0 3039 y(felem)f(-)i(\(integer\))d(first)h(pixel)h(of)g(the)g(element)f (vector)g(\(ignored)f(for)i(ASCII)g(tables\))0 3152 y(filename)f(-)h (\(character\))e(name)h(of)i(the)e(FITS)h(file)0 3265 y(flagvals)f(-)h(\(logical)f(array\))g(True)g(if)h(corresponding)e (data)h(element)g(is)h(undefined)0 3378 y(following)e(-)j(\(integer\))d (if)i(not)g(equal)f(to)i(0,)f(copy)f(all)h(following)f(HDUs)g(in)h(the) g(input)g(file)0 3491 y(fparm)f(-)i(\(integer\))d(sequence)h(number)g (of)h(the)g(first)f(group)h(parameter)e(to)i(read)g(or)g(write)0 3604 y(fpixel)f(-)i(\(integer\))d(the)i(first)f(pixel)g(position)0 3717 y(fpixels)g(-)h(\(integer)f(array\))g(the)h(first)f(included)g (pixel)g(in)h(each)g(dimension)0 3830 y(frow)g(-)g(\(integer\))e (beginning)h(row)h(number)f(\(first)g(row)h(of)g(table)f(=)i(1\))0 3942 y(frowll)e(-)i(\(integer*8\))c(beginning)i(row)g(number)h(\(first) f(row)h(of)g(table)f(=)i(1\))0 4055 y(gcount)e(-)i(\(integer\))d(value) h(of)h(the)g(GCOUNT)f(keyword)g(\(usually)g(=)h(1\))0 4168 y(group)f(-)i(\(integer\))d(sequence)h(number)g(of)h(the)g(data)f (group)h(\(=0)g(for)g(non-grouped)d(data\))0 4281 y(hdtype)i(-)i (\(integer\))d(header)h(record)g(type:)g(-1=delete;)93 b(0=append)46 b(or)h(replace;)907 4394 y(1=append;)e(2=this)h(is)h(the) g(END)g(keyword)0 4507 y(hduok)f(-)i(\(integer\))d(was)i(the)g(HDU)g (verification)d(successful)h(\(=1\))i(or)430 4620 y(not)f(\(=)i(-1\).) 94 b(Equals)46 b(zero)h(if)g(the)g(CHECKSUM)e(keyword)h(is)h(not)g (present.)0 4733 y(hdusum)f(-)i(\(double)d(precision\))g(32)j(bit)e (1's)h(complement)e(checksum)h(for)h(the)g(entire)f(CHDU)0 4846 y(hdutype)g(-)h(\(integer\))f(type)g(of)h(HDU:)g(0)g(=)h(primary)e (array)g(or)h(IMAGE,)f(1)i(=)f(ASCII)g(table,)907 4959 y(2)g(=)h(binary)e(table,)g(-1)h(=)h(any)e(HDU)h(type)g(or)g(unknown)f (type)0 5072 y(history)g(-)h(\(character\))e(the)i(HISTORY)f(keyword)g (comment)f(string)0 5185 y(hour)i(-)g(\(integer\))e(hour)i(from)g(0)g (-)h(23)0 5297 y(image)e(-)i(2D)f(image)f(of)i(the)e(appropriate)f (datatype)0 5410 y(inclist)94 b(\(character)45 b(array\))h(list)g(of)h (names)g(to)g(be)g(included)f(in)h(search)0 5523 y(incs)g(-)g (\(integer)f(array\))g(sampling)f(interval)h(for)h(pixels)f(in)h(each)g (FITS)f(dimension)0 5636 y(intval)g(-)i(\(integer\))d(integer)h(part)g (of)h(the)g(keyword)f(value)p eop end %%Page: 125 131 TeXDict begin 125 130 bop 3764 299 a Fi(125)0 555 y Fe(iounit)46 b(-)i(\(integer\))d(value)h(of)h(an)h(unused)e(I/O)h(unit)f(number)0 668 y(iunit)g(-)i(\(integer\))d(logical)h(unit)h(number)f(associated)f (with)h(the)h(input)g(FITS)f(file,)h(1-300)0 781 y(key_no)f(-)i (\(integer\))d(sequence)g(number)h(\(starting)g(with)g(1\))i(of)f(the)g (keyword)e(record)0 894 y(keylength)g(-)j(\(integer\))d(length)h(of)h (the)g(keyword)f(name)0 1007 y(keyroot)g(-)h(\(character\))e(root)i (string)f(for)h(the)g(keyword)e(name)0 1120 y(keysadd)h(-\(integer\))f (number)h(of)h(new)g(keyword)f(records)g(which)g(can)h(fit)g(in)g(the)g (CHU)0 1233 y(keysexist)e(-)j(\(integer\))d(number)h(of)h(existing)f (keyword)g(records)f(in)j(the)f(CHU)0 1346 y(keyval)f(-)i(value)e(of)h (the)g(keyword)f(in)h(the)g(appropriate)e(datatype)0 1458 y(keyvals)h(-)h(\(array\))f(value)g(of)i(the)f(keywords)e(in)i (the)g(appropriate)e(datatype)0 1571 y(keyword)h(-)h(\(character*8\))d (name)j(of)g(a)h(keyword)0 1684 y(lray)f(-)g(\(logical)f(array\))g (array)g(of)h(logical)f(values)g(corresponding)e(to)k(the)e(bit)h (array)0 1797 y(lpixels)f(-)h(\(integer)f(array\))g(the)h(last)f (included)g(pixel)g(in)i(each)e(dimension)0 1910 y(match)g(-)i (\(logical\))d(do)i(the)g(2)h(strings)d(match?)0 2023 y(maxdim)h(-)i(\(integer\))d(dimensioned)g(size)h(of)h(the)g(NAXES,)f (TTYPE,)g(TFORM)h(or)g(TUNIT)f(arrays)0 2136 y(max_keys)g(-)h (\(integer\))e(maximum)h(number)g(of)h(keywords)f(to)h(search)f(for)0 2249 y(minute)g(-)i(\(integer\))d(minute)h(of)h(an)g(hour)g(\(0)g(-)h (59\))0 2362 y(month)e(-)i(\(integer\))d(current)h(month)g(of)h(the)g (year)g(\(1)g(-)h(12\))0 2475 y(morekeys)e(-)h(\(integer\))e(will)i (leave)f(space)h(in)g(the)g(header)f(for)h(this)f(many)h(more)g (keywords)0 2588 y(naxes)f(-)i(\(integer)d(array\))h(size)h(of)g(each)g (dimension)e(in)i(the)g(FITS)g(array)0 2700 y(naxesll)f(-)h (\(integer*8)e(array\))h(size)h(of)g(each)g(dimension)e(in)i(the)g (FITS)g(array)0 2813 y(naxis)f(-)i(\(integer\))d(number)h(of)h (dimensions)e(in)j(the)e(FITS)h(array)0 2926 y(naxis1)f(-)i (\(integer\))d(length)h(of)h(the)g(X/first)f(axis)g(of)i(the)f(FITS)f (array)0 3039 y(naxis2)g(-)i(\(integer\))d(length)h(of)h(the)g (Y/second)f(axis)g(of)h(the)g(FITS)g(array)0 3152 y(naxis3)f(-)i (\(integer\))d(length)h(of)h(the)g(Z/third)f(axis)g(of)i(the)f(FITS)f (array)0 3265 y(nbit)h(-)g(\(integer\))e(number)h(of)i(bits)e(in)h(the) g(field)g(to)g(read)g(or)g(write)0 3378 y(nchars)f(-)i(\(integer\))d (number)h(of)h(characters)e(to)i(read)g(and)g(return)0 3491 y(ncols)f(-)i(\(integer\))d(number)h(of)h(columns)0 3604 y(nelements)e(-)j(\(integer\))d(number)h(of)h(data)g(elements)e (to)j(read)e(or)h(write)0 3717 y(nelementsll)e(-)i(\(integer*8\))e (number)h(of)h(data)g(elements)e(to)j(read)e(or)h(write)0 3830 y(nexc)142 b(\(integer\))93 b(number)46 b(of)h(names)g(in)g(the)g (exclusion)e(list)i(\(may)f(=)i(0\))0 3942 y(nhdu)f(-)g(\(integer\))e (absolute)h(number)g(of)h(the)g(HDU)g(\(1st)g(HDU)g(=)g(1\))0 4055 y(ninc)142 b(\(integer\))93 b(number)46 b(of)h(names)g(in)g(the)g (inclusion)e(list)0 4168 y(nmove)h(-)i(\(integer\))d(number)h(of)h (HDUs)g(to)g(move)g(\(+)g(or)g(-\),)g(relative)f(to)h(current)f (position)0 4281 y(nfound)g(-)i(\(integer\))d(number)h(of)h(keywords)f (found)g(\(highest)g(keyword)f(number\))0 4394 y(no_keys)h(-)h (\(integer\))f(number)g(of)h(keywords)e(to)j(write)e(in)h(the)g (sequence)0 4507 y(nparm)f(-)i(\(integer\))d(number)h(of)h(group)g (parameters)e(to)i(read)g(or)g(write)0 4620 y(nrows)f(-)i(\(integer\))d (number)h(of)h(rows)g(in)g(the)g(table)0 4733 y(nrowsll)f(-)h (\(integer*8\))e(number)h(of)h(rows)g(in)g(the)g(table)0 4846 y(nullval)f(-)h(value)g(to)g(represent)e(undefined)g(pixels,)h(of) h(the)g(appropriate)e(datatype)0 4959 y(nextaddr)h(-)h(\(integer\))e (starting)h(address)g(\(in)h(bytes\))f(of)h(the)g(HDU)g(following)e (the)i(CHDU)0 5072 y(offset)f(-)i(\(integer\))d(byte)h(offset)h(in)g (the)g(heap)f(to)h(the)g(first)g(element)f(of)h(the)g(array)0 5185 y(offsetll)f(-)h(\(integer*8\))e(byte)h(offset)g(in)i(the)f(heap)f (to)h(the)g(first)g(element)e(of)j(the)f(array)0 5297 y(oldkey)f(-)i(\(character\))c(old)j(name)g(of)g(keyword)f(to)h(be)g (modified)0 5410 y(ounit)f(-)i(\(integer\))d(logical)h(unit)h(number)f (associated)f(with)h(the)h(output)f(FITS)h(file)g(1-300)0 5523 y(pcount)f(-)i(\(integer\))d(value)h(of)h(the)g(PCOUNT)f(keyword)g (\(usually)g(=)h(0\))0 5636 y(previous)f(-)h(\(integer\))e(if)i(not)g (equal)g(to)g(0,)g(copy)g(all)g(previous)e(HDUs)i(in)g(the)g(input)f (file)p eop end %%Page: 126 132 TeXDict begin 126 131 bop 0 299 a Fi(126)1779 b Fg(CHAPTER)30 b(11.)112 b(P)-8 b(ARAMETER)30 b(DEFINITIONS)0 555 y Fe(repeat)46 b(-)i(\(integer\))d(length)h(of)h(element)f(vector)g (\(e.g.)g(12J\);)h(ignored)f(for)g(ASCII)h(table)0 668 y(rot)g(-)g(\(double)f(precision\))f(celestial)g(coordinate)g(rotation) h(angle)g(\(degrees\))0 781 y(rowlen)g(-)i(\(integer\))d(length)h(of)h (a)h(table)e(row,)h(in)g(characters)e(or)i(bytes)0 894 y(rowlenll)f(-)h(\(integer*8\))e(length)h(of)h(a)g(table)g(row,)f(in)i (characters)d(or)i(bytes)0 1007 y(rowlist)f(-)h(\(integer)f(array\))g (list)h(of)g(row)g(numbers)e(to)j(be)f(deleted)f(in)h(increasing)e (order)0 1120 y(rownum)h(-)i(\(integer\))d(number)h(of)h(the)g(row)g (\(first)f(row)h(=)g(1\))0 1233 y(rowrange-)e(\(string\))h(list)g(of)i (rows)e(or)h(row)g(ranges)f(to)i(be)f(deleted)0 1346 y(rwmode)f(-)i(\(integer\))d(file)h(access)h(mode:)f(0)h(=)h(readonly,) d(1)j(=)f(readwrite)0 1458 y(second)142 b(\(double\)-)45 b(second)h(within)g(minute)g(\(0)h(-)h(60.9999999999\))c(\(leap)i (second!\))0 1571 y(seq_no)g(-)i(\(integer\))d(the)i(sequence)e(number) h(to)i(append)e(to)h(the)g(keyword)f(root)g(name)0 1684 y(simple)g(-)i(\(logical\))d(does)h(the)h(FITS)g(file)g(conform)e(to)j (all)f(the)f(FITS)h(standards)0 1797 y(snull)f(-)i(\(character\))d (value)h(used)h(to)g(represent)e(undefined)g(values)h(in)i(ASCII)e (table)0 1910 y(space)g(-)i(\(integer\))d(number)h(of)h(blank)g(spaces) f(to)h(leave)f(between)g(ASCII)h(table)f(columns)0 2023 y(startchar)f(-)j(\(integer\))d(first)h(character)g(in)h(the)g(row)g (to)g(be)g(read)0 2136 y(startno)f(-)h(\(integer\))f(value)g(of)h(the)g (first)f(keyword)g(sequence)g(number)g(\(usually)f(1\))0 2249 y(status)h(-)i(\(integer\))d(returned)g(error)i(status)f(code)g (\(0)i(=)f(OK\))0 2362 y(str_template)d(\(character\))h(template)h (string)g(to)h(be)g(matched)f(to)h(reference)e(string)0 2475 y(stream)h(-)i(\(character\))c(output)i(stream)g(for)h(the)g (report:)f(either)g('STDOUT')g(or)h('STDERR')0 2588 y(string)f(-)i (\(character\))c(character)i(string)0 2700 y(sum)h(-)g(\(double)f (precision\))f(32)i(bit)g(unsigned)f(checksum)f(value)0 2813 y(tbcol)h(-)i(\(integer)d(array\))h(column)h(number)f(of)h(the)g (first)f(character)f(in)j(the)e(field\(s\))0 2926 y(tdisp)g(-)i (\(character\))d(Fortran)g(type)i(display)f(format)g(for)h(the)g(table) f(column)0 3039 y(template-\(character\))c(template)k(string)g(for)h(a) g(FITS)g(header)f(record)0 3152 y(tfields)g(-)h(\(integer\))f(number)g (of)h(fields)f(\(columns\))f(in)i(the)g(table)0 3265 y(tform)f(-)i(\(character)d(array\))h(format)g(of)h(the)g(column\(s\);) e(allowed)h(values)g(are:)430 3378 y(For)g(ASCII)h(tables:)93 b(Iw,)47 b(Aw,)g(Fww.dd,)f(Eww.dd,)g(or)h(Dww.dd)430 3491 y(For)f(binary)h(tables:)e(rL,)i(rX,)g(rB,)g(rI,)g(rJ,)g(rA,)g (rAw,)f(rE,)h(rD,)g(rC,)g(rM)430 3604 y(where)f('w'=width)f(of)i(the)g (field,)f('d'=no.)g(of)h(decimals,)f('r'=repeat)f(count)430 3717 y(Note)h(that)h(the)g('rAw')f(form)h(is)g(non-standard)d (extension)i(to)h(the)430 3830 y(TFORM)f(keyword)g(syntax)g(that)g(is)i (not)f(specifically)d(defined)i(in)h(the)430 3942 y(Binary)f(Tables)g (definition)f(document.)0 4055 y(theap)h(-)i(\(integer\))d(zero)i (indexed)f(byte)g(offset)g(of)h(starting)f(address)g(of)h(the)g(heap) 430 4168 y(relative)e(to)i(the)g(beginning)e(of)j(the)f(binary)f(table) g(data)0 4281 y(tnull)g(-)i(\(integer\))d(value)h(used)h(to)g (represent)f(undefined)f(values)h(in)h(binary)f(table)0 4394 y(tnullll)g(-)h(\(integer*8\))e(value)h(used)h(to)g(represent)e (undefined)h(values)g(in)h(binary)f(table)0 4507 y(ttype)g(-)i (\(character)d(array\))h(label)g(for)h(table)g(column\(s\))0 4620 y(tscal)f(-)i(\(double)e(precision\))f(scaling)g(factor)i(for)f (table)h(column)0 4733 y(tunit)f(-)i(\(character)d(array\))h(physical)f (unit)i(for)g(table)f(column\(s\))0 4846 y(tzero)g(-)i(\(double)e (precision\))f(scaling)g(zero)i(point)f(for)h(table)g(column)0 4959 y(unit)94 b(-)48 b(\(integer\))d(logical)h(unit)h(number)f (associated)f(with)h(the)h(FITS)g(file)f(\(1-300\))0 5072 y(units)g(-)i(\(character\))d(the)h(keyword)g(units)h(string)f (\(e.g.,)g('km/s'\))0 5185 y(value)g(-)i(\(character\))d(the)h(keyword) g(value)h(string)0 5297 y(values)f(-)i(array)e(of)h(data)g(values)f(of) h(the)g(appropriate)e(datatype)0 5410 y(varidat)h(-)h(\(integer\))f (size)g(in)h(bytes)g(of)g(the)g('variable)e(length)h(data)h(area')525 5523 y(following)e(the)i(binary)f(table)h(data)f(\(usually)g(=)h(0\))0 5636 y(version)f(-)h(\(real\))f(current)g(revision)g(number)g(of)h(the) g(library)p eop end %%Page: 127 133 TeXDict begin 127 132 bop 3764 299 a Fi(127)0 555 y Fe(width)46 b(-)i(\(integer\))d(width)h(of)i(the)f(character)e(string)h(field)0 668 y(xcol)h(-)g(\(integer\))e(number)h(of)i(the)f(column)f(containing) f(the)i(X)g(coordinate)e(values)0 781 y(xinc)i(-)g(\(double)f (precision\))f(X)i(axis)g(coordinate)e(increment)g(at)i(reference)f (pixel)g(\(deg\))0 894 y(xpix)h(-)g(\(double)f(precision\))f(X)i(axis)g (pixel)f(location)0 1007 y(xpos)h(-)g(\(double)f(precision\))f(X)i (axis)g(celestial)e(coordinate)g(\(usually)h(RA\))h(\(deg\))0 1120 y(xrpix)f(-)i(\(double)e(precision\))f(X)i(axis)g(reference)e (pixel)h(array)h(location)0 1233 y(xrval)f(-)i(\(double)e(precision\))f (X)i(axis)g(coordinate)e(value)h(at)h(the)g(reference)e(pixel)i (\(deg\))0 1346 y(ycol)g(-)g(\(integer\))e(number)h(of)i(the)f(column)f (containing)f(the)i(X)g(coordinate)e(values)0 1458 y(year)i(-)g (\(integer\))e(last)i(2)g(digits)g(of)g(the)g(year)f(\(00)h(-)h(99\))0 1571 y(yinc)f(-)g(\(double)f(precision\))f(Y)i(axis)g(coordinate)e (increment)g(at)i(reference)f(pixel)g(\(deg\))0 1684 y(ypix)h(-)g(\(double)f(precision\))f(y)i(axis)g(pixel)f(location)0 1797 y(ypos)h(-)g(\(double)f(precision\))f(y)i(axis)g(celestial)e (coordinate)g(\(usually)h(DEC\))g(\(deg\))0 1910 y(yrpix)g(-)i (\(double)e(precision\))f(Y)i(axis)g(reference)e(pixel)h(array)h (location)0 2023 y(yrval)f(-)i(\(double)e(precision\))f(Y)i(axis)g (coordinate)e(value)h(at)h(the)g(reference)e(pixel)i(\(deg\))p eop end %%Page: 128 134 TeXDict begin 128 133 bop 0 299 a Fi(128)1779 b Fg(CHAPTER)30 b(11.)112 b(P)-8 b(ARAMETER)30 b(DEFINITIONS)p eop end %%Page: 129 135 TeXDict begin 129 134 bop 0 1225 a Ff(Chapter)65 b(12)0 1687 y Fl(FITSIO)76 b(Error)h(Status)h(Co)6 b(des)0 2180 y Fe(Status)46 b(codes)g(in)i(the)f(range)f(-99)h(to)g(-999)94 b(and)47 b(1)h(to)f(999)g(are)g(reserved)e(for)i(future)0 2293 y(FITSIO)f(use.)95 2518 y(0)96 b(OK,)47 b(no)g(error)0 2631 y(101)95 b(input)46 b(and)h(output)f(files)g(are)h(the)g(same)0 2744 y(103)95 b(too)47 b(many)f(FITS)h(files)f(open)h(at)g(once;)f(all) h(internal)f(buffers)g(full)0 2857 y(104)95 b(error)46 b(opening)g(existing)f(file)0 2970 y(105)95 b(error)46 b(creating)g(new)g(FITS)h(file;)f(\(does)h(a)g(file)g(with)g(this)f (name)h(already)f(exist?\))0 3083 y(106)95 b(error)46 b(writing)g(record)g(to)h(FITS)g(file)0 3196 y(107)95 b(end-of-file)44 b(encountered)h(while)h(reading)g(record)g(from)h (FITS)g(file)0 3309 y(108)95 b(error)46 b(reading)g(record)g(from)h (file)0 3422 y(110)95 b(error)46 b(closing)g(FITS)g(file)0 3535 y(111)95 b(internal)45 b(array)i(dimensions)e(exceeded)0 3648 y(112)95 b(Cannot)46 b(modify)g(file)g(with)h(readonly)f(access)0 3760 y(113)95 b(Could)46 b(not)h(allocate)e(memory)0 3873 y(114)95 b(illegal)45 b(logical)h(unit)h(number;)f(must)g(be)i (between)d(1)j(-)f(300,)g(inclusive)0 3986 y(115)95 b(NULL)46 b(input)h(pointer)e(to)j(routine)0 4099 y(116)95 b(error)46 b(seeking)g(position)f(in)j(file)0 4325 y(121)95 b(invalid)45 b(URL)i(prefix)f(on)i(file)e(name)0 4438 y(122)95 b(tried)46 b(to)h(register)f(too)h(many)f(IO)h(drivers)0 4551 y(123)95 b(driver)46 b(initialization)e(failed)0 4664 y(124)95 b(matching)45 b(driver)h(is)h(not)g(registered)0 4777 y(125)95 b(failed)46 b(to)h(parse)f(input)h(file)f(URL)0 4890 y(126)95 b(parse)46 b(error)g(in)i(range)e(list)0 5115 y(151)95 b(bad)47 b(argument)e(in)i(shared)f(memory)g(driver)0 5228 y(152)95 b(null)46 b(pointer)g(passed)g(as)h(an)h(argument)0 5341 y(153)95 b(no)47 b(more)f(free)h(shared)f(memory)g(handles)0 5454 y(154)95 b(shared)46 b(memory)g(driver)g(is)h(not)g(initialized)0 5567 y(155)95 b(IPC)47 b(error)f(returned)f(by)j(a)f(system)f(call)0 5680 y(156)95 b(no)47 b(memory)f(in)h(shared)f(memory)g(driver)1882 5942 y Fi(129)p eop end %%Page: 130 136 TeXDict begin 130 135 bop 0 299 a Fi(130)1613 b Fg(CHAPTER)30 b(12.)112 b(FITSIO)30 b(ERR)m(OR)g(ST)-8 b(A)g(TUS)30 b(CODES)0 555 y Fe(157)95 b(resource)45 b(deadlock)h(would)g(occur)0 668 y(158)95 b(attempt)45 b(to)j(open/create)c(lock)j(file)g(failed)0 781 y(159)95 b(shared)46 b(memory)g(block)g(cannot)g(be)h(resized)f(at) h(the)g(moment)0 1120 y(201)95 b(header)46 b(not)h(empty;)f(can't)g (write)g(required)g(keywords)0 1233 y(202)95 b(specified)45 b(keyword)h(name)g(was)h(not)g(found)g(in)g(the)g(header)0 1346 y(203)95 b(specified)45 b(header)h(record)g(number)g(is)h(out)g (of)g(bounds)0 1458 y(204)95 b(keyword)45 b(value)i(field)f(is)h(blank) 0 1571 y(205)95 b(keyword)45 b(value)i(string)f(is)h(missing)f(the)h (closing)f(quote)g(character)0 1684 y(206)95 b(illegal)45 b(indexed)h(keyword)g(name)h(\(e.g.)f('TFORM1000'\))0 1797 y(207)95 b(illegal)45 b(character)h(in)h(keyword)f(name)g(or)i (header)e(record)0 1910 y(208)95 b(keyword)45 b(does)i(not)g(have)g (expected)e(name.)i(Keyword)e(out)i(of)g(sequence?)0 2023 y(209)95 b(keyword)45 b(does)i(not)g(have)g(expected)e(integer)h (value)0 2136 y(210)95 b(could)46 b(not)h(find)g(the)f(required)g(END)h (header)f(keyword)0 2249 y(211)95 b(illegal)45 b(BITPIX)i(keyword)e (value)0 2362 y(212)95 b(illegal)45 b(NAXIS)i(keyword)f(value)0 2475 y(213)95 b(illegal)45 b(NAXISn)i(keyword)e(value:)h(must)h(be)g(0) h(or)f(positive)e(integer)0 2588 y(214)95 b(illegal)45 b(PCOUNT)i(keyword)e(value)0 2700 y(215)95 b(illegal)45 b(GCOUNT)i(keyword)e(value)0 2813 y(216)95 b(illegal)45 b(TFIELDS)h(keyword)g(value)0 2926 y(217)95 b(negative)45 b(ASCII)i(or)g(binary)f(table)g(width)h(value)f(\(NAXIS1\))0 3039 y(218)95 b(negative)45 b(number)h(of)h(rows)g(in)g(ASCII)g(or)g (binary)f(table)g(\(NAXIS2\))0 3152 y(219)95 b(column)46 b(name)g(\(TTYPE)g(keyword\))g(not)h(found)0 3265 y(220)95 b(illegal)45 b(SIMPLE)i(keyword)e(value)0 3378 y(221)95 b(could)46 b(not)h(find)g(the)f(required)g(SIMPLE)g(header)g(keyword)0 3491 y(222)95 b(could)46 b(not)h(find)g(the)f(required)g(BITPIX)g (header)g(keyword)0 3604 y(223)95 b(could)46 b(not)h(find)g(the)f (required)g(NAXIS)g(header)g(keyword)0 3717 y(224)95 b(could)46 b(not)h(find)g(all)f(the)h(required)f(NAXISn)g(keywords)g (in)h(the)g(header)0 3830 y(225)95 b(could)46 b(not)h(find)g(the)f (required)g(XTENSION)g(header)g(keyword)0 3942 y(226)95 b(the)47 b(CHDU)f(is)h(not)g(an)g(ASCII)g(table)f(extension)0 4055 y(227)95 b(the)47 b(CHDU)f(is)h(not)g(a)h(binary)e(table)g (extension)0 4168 y(228)95 b(could)46 b(not)h(find)g(the)f(required)g (PCOUNT)g(header)g(keyword)0 4281 y(229)95 b(could)46 b(not)h(find)g(the)f(required)g(GCOUNT)g(header)g(keyword)0 4394 y(230)95 b(could)46 b(not)h(find)g(the)f(required)g(TFIELDS)g (header)g(keyword)0 4507 y(231)95 b(could)46 b(not)h(find)g(all)f(the)h (required)f(TBCOLn)g(keywords)g(in)h(the)g(header)0 4620 y(232)95 b(could)46 b(not)h(find)g(all)f(the)h(required)f(TFORMn)g (keywords)g(in)h(the)g(header)0 4733 y(233)95 b(the)47 b(CHDU)f(is)h(not)g(an)g(IMAGE)g(extension)0 4846 y(234)95 b(illegal)45 b(TBCOL)i(keyword)f(value;)g(out)h(of)g(range)0 4959 y(235)95 b(this)46 b(operation)g(only)g(allowed)g(for)h(ASCII)f (or)h(BINARY)g(table)f(extension)0 5072 y(236)95 b(column)46 b(is)h(too)g(wide)f(to)i(fit)f(within)f(the)h(specified)e(width)h(of)h (the)g(ASCII)g(table)0 5185 y(237)95 b(the)47 b(specified)e(column)h (name)h(template)e(matched)h(more)h(than)f(one)h(column)f(name)0 5297 y(241)95 b(binary)46 b(table)g(row)h(width)f(is)i(not)e(equal)h (to)g(the)g(sum)g(of)g(the)g(field)f(widths)0 5410 y(251)95 b(unrecognizable)44 b(type)i(of)h(FITS)g(extension)0 5523 y(252)95 b(unrecognizable)44 b(FITS)i(record)0 5636 y(253)95 b(END)47 b(keyword)e(contains)h(non-blank)f(characters)g(in)i (columns)f(9-80)p eop end %%Page: 131 137 TeXDict begin 131 136 bop 3764 299 a Fi(131)0 555 y Fe(254)95 b(Header)46 b(fill)g(area)h(contains)f(non-blank)f(characters)0 668 y(255)95 b(Data)46 b(fill)h(area)g(contains)e(non-blank)g(on)j (non-zero)d(values)0 781 y(261)95 b(unable)46 b(to)h(parse)f(the)h (TFORM)g(keyword)e(value)i(string)0 894 y(262)95 b(unrecognizable)44 b(TFORM)i(datatype)f(code)0 1007 y(263)95 b(illegal)45 b(TDIMn)i(keyword)f(value)0 1233 y(301)95 b(illegal)45 b(HDU)i(number;)f(less)h(than)f(1)i(or)f(greater)f(than)h(internal)e (buffer)h(size)0 1346 y(302)95 b(column)46 b(number)g(out)h(of)g(range) f(\(1)h(-)h(999\))0 1458 y(304)95 b(attempt)45 b(to)j(move)e(to)h (negative)f(file)h(record)f(number)0 1571 y(306)95 b(attempted)45 b(to)i(read)g(or)g(write)f(a)i(negative)d(number)h(of)i(bytes)e(in)h (the)g(FITS)g(file)0 1684 y(307)95 b(illegal)45 b(starting)h(row)h (number)f(for)h(table)f(read)h(or)g(write)f(operation)0 1797 y(308)95 b(illegal)45 b(starting)h(element)g(number)g(for)h(table) f(read)h(or)g(write)f(operation)0 1910 y(309)95 b(attempted)45 b(to)i(read)g(or)g(write)f(character)g(string)g(in)h(non-character)d (table)i(column)0 2023 y(310)95 b(attempted)45 b(to)i(read)g(or)g (write)f(logical)g(value)g(in)i(non-logical)c(table)j(column)0 2136 y(311)95 b(illegal)45 b(ASCII)i(table)f(TFORM)h(format)f(code)g (for)h(attempted)e(operation)0 2249 y(312)95 b(illegal)45 b(binary)i(table)f(TFORM)g(format)g(code)h(for)g(attempted)e(operation) 0 2362 y(314)95 b(value)46 b(for)h(undefined)e(pixels)h(has)h(not)g (been)g(defined)0 2475 y(317)95 b(attempted)45 b(to)i(read)g(or)g (write)f(descriptor)f(in)i(a)h(non-descriptor)c(field)0 2588 y(320)95 b(number)46 b(of)h(array)f(dimensions)f(out)i(of)g(range) 0 2700 y(321)95 b(first)46 b(pixel)g(number)g(is)i(greater)d(than)i (the)g(last)g(pixel)f(number)0 2813 y(322)95 b(attempt)45 b(to)j(set)f(BSCALE)f(or)h(TSCALn)f(scaling)g(parameter)f(=)i(0)0 2926 y(323)95 b(illegal)45 b(axis)i(length)f(less)h(than)f(1)0 3152 y(340)h(NOT_GROUP_TABLE)d(340)142 b(Grouping)45 b(function)h(error)0 3265 y(341)h(HDU_ALREADY_MEMBER)0 3378 y(342)g(MEMBER_NOT_FOUND)0 3491 y(343)g(GROUP_NOT_FOUND)0 3604 y(344)g(BAD_GROUP_ID)0 3717 y(345)g(TOO_MANY_HDUS_TRACKED)0 3830 y(346)g(HDU_ALREADY_TRACKED)0 3942 y(347)g(BAD_OPTION)0 4055 y(348)g(IDENTICAL_POINTERS)0 4168 y(349)g(BAD_GROUP_ATTACH)0 4281 y(350)g(BAD_GROUP_DETACH)0 4507 y(360)g(NGP_NO_MEMORY)665 b(malloc)46 b(failed)0 4620 y(361)h(NGP_READ_ERR)713 b(read)46 b(error)h(from)f(file)0 4733 y(362)h(NGP_NUL_PTR)761 b(null)46 b(pointer)g(passed)g(as)h(an)g(argument.)1575 4846 y(Passing)f(null)g(pointer)g(as)h(a)h(name)f(of)1575 4959 y(template)f(file)g(raises)g(this)h(error)0 5072 y(363)g(NGP_EMPTY_CURLINE)473 b(line)46 b(read)h(seems)f(to)h(be)h (empty)e(\(used)1575 5185 y(internally\))0 5297 y(364)h (NGP_UNREAD_QUEUE_FULL)281 b(cannot)46 b(unread)g(more)g(then)h(1)g (line)g(\(or)g(single)1575 5410 y(line)g(twice\))0 5523 y(365)g(NGP_INC_NESTING)569 b(too)46 b(deep)h(include)f(file)h(nesting) e(\(infinite)1575 5636 y(loop,)h(template)g(includes)f(itself)i(?\))p eop end %%Page: 132 138 TeXDict begin 132 137 bop 0 299 a Fi(132)1613 b Fg(CHAPTER)30 b(12.)112 b(FITSIO)30 b(ERR)m(OR)g(ST)-8 b(A)g(TUS)30 b(CODES)0 555 y Fe(366)47 b(NGP_ERR_FOPEN)665 b(fopen\(\))45 b(failed,)h(cannot)g(open)h(template)e(file)0 668 y(367)i(NGP_EOF)953 b(end)46 b(of)i(file)e(encountered)f(and)i(not)g(expected)0 781 y(368)g(NGP_BAD_ARG)761 b(bad)46 b(arguments)g(passed.)g(Usually)f (means)1575 894 y(internal)h(parser)g(error.)g(Should)g(not)h(happen)0 1007 y(369)g(NGP_TOKEN_NOT_EXPECT)329 b(token)46 b(not)h(expected)e (here)0 1233 y(401)95 b(error)46 b(attempting)f(to)i(convert)f(an)h (integer)f(to)h(a)h(formatted)d(character)g(string)0 1346 y(402)95 b(error)46 b(attempting)f(to)i(convert)f(a)h(real)g (value)f(to)i(a)f(formatted)e(character)h(string)0 1458 y(403)95 b(cannot)46 b(convert)g(a)h(quoted)f(string)g(keyword)g(to)h (an)g(integer)0 1571 y(404)95 b(attempted)45 b(to)i(read)g(a)g (non-logical)e(keyword)h(value)g(as)h(a)h(logical)e(value)0 1684 y(405)95 b(cannot)46 b(convert)g(a)h(quoted)f(string)g(keyword)g (to)h(a)h(real)e(value)0 1797 y(406)95 b(cannot)46 b(convert)g(a)h (quoted)f(string)g(keyword)g(to)h(a)h(double)e(precision)f(value)0 1910 y(407)95 b(error)46 b(attempting)f(to)i(read)g(character)e(string) h(as)h(an)h(integer)0 2023 y(408)95 b(error)46 b(attempting)f(to)i (read)g(character)e(string)h(as)h(a)h(real)e(value)0 2136 y(409)95 b(error)46 b(attempting)f(to)i(read)g(character)e(string) h(as)h(a)h(double)e(precision)f(value)0 2249 y(410)95 b(bad)47 b(keyword)e(datatype)h(code)0 2362 y(411)95 b(illegal)45 b(number)i(of)g(decimal)f(places)g(while)g(formatting)f (floating)h(point)g(value)0 2475 y(412)95 b(numerical)45 b(overflow)g(during)i(implicit)e(datatype)h(conversion)0 2588 y(413)95 b(error)46 b(compressing)f(image)0 2700 y(414)95 b(error)46 b(uncompressing)e(image)0 2813 y(420)95 b(error)46 b(in)h(date)g(or)g(time)g(conversion)0 3039 y(431)95 b(syntax)46 b(error)g(in)h(parser)f(expression)0 3152 y(432)95 b(expression)45 b(did)i(not)f(evaluate)g(to)h(desired)f (type)0 3265 y(433)95 b(vector)46 b(result)g(too)h(large)f(to)h(return) f(in)i(array)0 3378 y(434)95 b(data)46 b(parser)g(failed)g(not)h(sent)g (an)g(out)g(column)0 3491 y(435)95 b(bad)47 b(data)f(encounter)f(while) i(parsing)f(column)0 3604 y(436)95 b(parse)46 b(error:)g(output)g(file) h(not)g(of)g(proper)f(type)0 3830 y(501)95 b(celestial)45 b(angle)h(too)h(large)g(for)f(projection)0 3942 y(502)95 b(bad)47 b(celestial)e(coordinate)g(or)i(pixel)f(value)0 4055 y(503)95 b(error)46 b(in)h(celestial)e(coordinate)g(calculation)0 4168 y(504)95 b(unsupported)44 b(type)j(of)g(celestial)e(projection)0 4281 y(505)95 b(required)45 b(celestial)g(coordinate)g(keywords)h(not)h (found)0 4394 y(506)95 b(approximate)44 b(wcs)j(keyword)f(values)g (were)h(returned)p eop end %%Trailer userdict /end-hook known{end-hook}if %%EOF cfitsio/docs/fitsio.tex0000644000225700000360000123734013246025103014761 0ustar cagordonlhea\documentclass[11pt]{book} \input{html.sty} \htmladdtonavigation {\begin{rawhtml} FITSIO Home \end{rawhtml}} %\oddsidemargin=0.25in \oddsidemargin=0.00in \evensidemargin=0.00in \textwidth=6.5in %\topmargin=0.0in \textheight=8.75in \parindent=0cm \parskip=0.2cm \begin{document} \pagenumbering{roman} \begin{titlepage} \normalsize \vspace*{4.6cm} \begin{center} {\Huge \bf FITSIO User's Guide}\\ \end{center} \medskip \medskip \begin{center} {\LARGE \bf A Subroutine Interface to FITS Format Files}\\ \end{center} \begin{center} {\LARGE \bf for Fortran Programmers}\\ \end{center} \medskip \medskip \begin{center} {\Large Version 3.0\\} \end{center} \bigskip \vskip 2.5cm \begin{center} {HEASARC\\ Code 662\\ Goddard Space Flight Center\\ Greenbelt, MD 20771\\ USA} \end{center} \vfill \bigskip \begin{center} {\Large April 2016\\} \end{center} \vfill \end{titlepage} \clearpage \tableofcontents \chapter{Introduction } \pagenumbering{arabic} This document describes the Fortran-callable subroutine interface that is provided as part of the CFITSIO library (which is written in ANSI C). This is a companion document to the CFITSIO User's Guide which should be consulted for further information about the underlying CFITSIO library. In the remainder of this document, the terms FITSIO and CFITSIO are interchangeable and refer to the same library. FITSIO/CFITSIO is a machine-independent library of routines for reading and writing data files in the FITS (Flexible Image Transport System) data format. It can also read IRAF format image files and raw binary data arrays by converting them on the fly into a virtual FITS format file. This library was written to provide a powerful yet simple interface for accessing FITS files which will run on most commonly used computers and workstations. FITSIO supports all the features described in the official definition of the FITS format and can read and write all the currently defined types of extensions, including ASCII tables (TABLE), Binary tables (BINTABLE) and IMAGE extensions. The FITSIO subroutines insulate the programmer from having to deal with the complicated formatting details in the FITS file, however, it is assumed that users have a general knowledge about the structure and usage of FITS files. The CFITSIO package was initially developed by the HEASARC (High Energy Astrophysics Science Archive Research Center) at the NASA Goddard Space Flight Center to convert various existing and newly acquired astronomical data sets into FITS format and to further analyze data already in FITS format. New features continue to be added to CFITSIO in large part due to contributions of ideas or actual code from users of the package. The Integral Science Data Center in Switzerland, and the XMM/ESTEC project in The Netherlands made especially significant contributions that resulted in many of the new features that appeared in v2.0 of CFITSIO. The latest version of the CFITSIO source code, documentation, and example programs are available on the World-Wide Web or via anonymous ftp from: \begin{verbatim} http://heasarc.gsfc.nasa.gov/fitsio ftp://legacy.gsfc.nasa.gov/software/fitsio/c \end{verbatim} \newpage Any questions, bug reports, or suggested enhancements related to the CFITSIO package should be sent to the FTOOLS Help Desk at the HEASARC: \begin{verbatim} http://heasarc.gsfc.nasa.gov/cgi-bin/ftoolshelp \end{verbatim} This User's Guide assumes that readers already have a general understanding of the definition and structure of FITS format files. Further information about FITS formats is available from the FITS Support Office at {\tt http://fits.gsfc.nasa.gov}. In particular, the 'FITS Standard' gives the authoritative definition of the FITS data format. Other documents available at that Web site provide additional historical background and practical advice on using FITS files. The HEASARC also provides a very sophisticated FITS file analysis program called `Fv' which can be used to display and edit the contents of any FITS file as well as construct new FITS files from scratch. Fv is freely available for most Unix platforms, Mac PCs, and Windows PCs. CFITSIO users may also be interested in the FTOOLS package of programs that can be used to manipulate and analyze FITS format files. Fv and FTOOLS are available from their respective Web sites at: \begin{verbatim} http://fv.gsfc.nasa.gov http://heasarc.gsfc.nasa.gov/ftools \end{verbatim} \chapter{ Creating FITSIO/CFITSIO } \section{Building the Library} To use the FITSIO subroutines one must first build the CFITSIO library, which requires a C compiler. gcc is ideal, or most other ANSI-C compilers will also work. The CFITSIO code is contained in about 40 C source files (*.c) and header files (*.h). On VAX/VMS systems 2 assembly-code files (vmsieeed.mar and vmsieeer.mar) are also needed. The Fortran interface subroutines to the C CFITSIO routines are located in the f77\_wrap1.c, through f77\_wrap4.c files. These are relatively simple 'wrappers' that translate the arguments in the Fortran subroutine into the appropriate format for the corresponding C routine. This translation is performed transparently to the user by a set of C macros located in the cfortran.h file. Unfortunately cfortran.h does not support every combination of C and Fortran compilers so the Fortran interface is not supported on all platforms. (see further notes below). A standard combination of C and Fortran compilers will be assumed by default, but one may also specify a particular Fortran compiler by doing: \begin{verbatim} > setenv CFLAGS -DcompilerName=1 \end{verbatim} (where 'compilerName' is the name of the compiler) before running the configure command. The currently recognized compiler names are: \begin{verbatim} g77Fortran IBMR2Fortran CLIPPERFortran pgiFortran NAGf90Fortran f2cFortran hpuxFortran apolloFortran sunFortran CRAYFortran mipsFortran DECFortran vmsFortran CONVEXFortran PowerStationFortran AbsoftUNIXFortran AbsoftProFortran SXFortran \end{verbatim} Alternatively, one may edit the CFLAGS line in the Makefile to add the '-DcompilerName' flag after running the './configure' command. The CFITSIO library is built on Unix systems by typing: \begin{verbatim} > ./configure [--prefix=/target/installation/path] [--enable-sse2] [--enable-ssse3] > make (or 'make shared') > make install (this step is optional) \end{verbatim} at the operating system prompt. The configure command customizes the Makefile for the particular system, then the `make' command compiles the source files and builds the library. Type `./configure' and not simply `configure' to ensure that the configure script in the current directory is run and not some other system-wide configure script. The optional 'prefix' argument to configure gives the path to the directory where the CFITSIO library and include files should be installed via the later 'make install' command. For example, \begin{verbatim} > ./configure --prefix=/usr1/local \end{verbatim} will cause the 'make install' command to copy the CFITSIO libcfitsio file to /usr1/local/lib and the necessary include files to /usr1/local/include (assuming of course that the process has permission to write to these directories). The optional --enable-sse2 and --enable-ssse3 flags will cause configure to attempt to build CFITSIO using faster byte-swapping algorithms. See the "Optimizing Programs" section of this manual for more information about these options. By default, the Makefile will be configured to build the set of Fortran-callable wrapper routines whose calling sequences are described later in this document. The 'make shared' option builds a shared or dynamic version of the CFITSIO library. When using the shared library the executable code is not copied into your program at link time and instead the program locates the necessary library code at run time, normally through LD\_LIBRARY\_PATH or some other method. The advantages of using a shared library are: \begin{verbatim} 1. Less disk space if you build more than 1 program 2. Less memory if more than one copy of a program using the shared library is running at the same time since the system is smart enough to share copies of the shared library at run time. 3. Possibly easier maintenance since a new version of the shared library can be installed without relinking all the software that uses it (as long as the subroutine names and calling sequences remain unchanged). 4. No run-time penalty. \end{verbatim} The disadvantages are: \begin{verbatim} 1. More hassle at runtime. You have to either build the programs specially or have LD_LIBRARY_PATH set right. 2. There may be a slight start up penalty, depending on where you are reading the shared library and the program from and if your CPU is either really slow or really heavily loaded. \end{verbatim} On HP/UX systems, the environment variable CFLAGS should be set to -Ae before running configure to enable "extended ANSI" features. It may not be possible to statically link programs that use CFITSIO on some platforms (namely, on Solaris 2.6) due to the network drivers (which provide FTP and HTTP access to FITS files). It is possible to make both a dynamic and a static version of the CFITSIO library, but network file access will not be possible using the static version. On VAX/VMS and ALPHA/VMS systems the make\_gfloat.com command file may be executed to build the cfitsio.olb object library using the default G-floating point option for double variables. The make\_dfloat.com and make\_ieee.com files may be used instead to build the library with the other floating point options. Note that the getcwd function that is used in the group.c module may require that programs using CFITSIO be linked with the ALPHA\$LIBRARY:VAXCRTL.OLB library. See the example link line in the next section of this document. On Windows IBM-PC type platforms the situation is more complicated because of the wide variety of Fortran compilers that are available and because of the inherent complexities of calling the CFITSIO C routines from Fortran. Two different versions of the CFITSIO dll library are available, compiled with the Borland C++ compiler and the Microsoft Visual C++ compiler, respectively, in the files cfitsiodll\_2xxx\_borland.zip and cfitsiodll\_3xxx\_vcc.zip, where '3xxx' represents the current release number. Both these dll libraries contain a set of Fortran wrapper routines which may be compatible with some, but probably not all, available Fortran compilers. To test if they are compatible, compile the program testf77.f and try linking to these dll libraries. If these libraries do not work with a particular Fortran compiler, then it may be necessary to modify the file "cfortran.h" to support that particular combination of C and Fortran compilers, and then rebuild the CFITSIO dll library. This will require, however, some expertise in mixed language programming. CFITSIO should be compatible with most current ANCI C and C++ compilers: Cray supercomputers are currently not supported. \section{Testing the Library} The CFITSIO library should be tested by building and running the testprog.c program that is included with the release. On Unix systems type: \begin{verbatim} % make testprog % testprog > testprog.lis % diff testprog.lis testprog.out % cmp testprog.fit testprog.std \end{verbatim} On VMS systems, (assuming cc is the name of the C compiler command), type: \begin{verbatim} $ cc testprog.c $ link testprog, cfitsio/lib, alpha$library:vaxcrtl/lib $ run testprog \end{verbatim} The testprog program should produce a FITS file called `testprog.fit' that is identical to the `testprog.std' FITS file included with this release. The diagnostic messages (which were piped to the file testprog.lis in the Unix example) should be identical to the listing contained in the file testprog.out. The 'diff' and 'cmp' commands shown above should not report any differences in the files. (There may be some minor formatting differences, such as the presence or absence of leading zeros, or 3 digit exponents in numbers, which can be ignored). The Fortran wrappers in CFITSIO may be tested with the testf77 program. On Unix systems the fortran compilation and link command may be called 'f77' or 'g77', depending on the system. \begin{verbatim} % f77 -o testf77 testf77.f -L. -lcfitsio -lnsl -lsocket or % f77 -f -o testf77 testf77.f -L. -lcfitsio (under SUN O/S) or % f77 -o testf77 testf77.f -Wl,-L. -lcfitsio -lm -lnsl -lsocket (HP/UX) or % g77 -o testf77 -s testf77.f -lcfitsio -lcc_dynamic -lncurses (Mac OS-X) % testf77 > testf77.lis % diff testf77.lis testf77.out % cmp testf77.fit testf77.std \end{verbatim} On machines running SUN O/S, Fortran programs must be compiled with the '-f' option to force double precision variables to be aligned on 8-byte boundaries to make the fortran-declared variables compatible with C. A similar compiler option may be required on other platforms. Failing to use this option may cause the program to crash on FITSIO routines that read or write double precision variables. On Windows platforms, linking Fortran programs with a C library often depends on the particular compilers involved. Some users have found the following commands work when using the Intel Fortran compiler: \begin{verbatim} ifort /libs.dll cfitsio.lib /MD testf77.f /Gm or possibly, ifort /libs:dll cfitsio.lib /MD /fpp /extfpp:cfortran.h,fitsio.h /iface:cvf testf77.f \end{verbatim} Also note that on some systems the output listing of the testf77 program may differ slightly from the testf77.std template if leading zeros are not printed by default before the decimal point when using F format. A few other utility programs are included with CFITSIO: \begin{verbatim} speed - measures the maximum throughput (in MB per second) for writing and reading FITS files with CFITSIO listhead - lists all the header keywords in any FITS file fitscopy - copies any FITS file (especially useful in conjunction with the CFITSIO's extended input filename syntax) cookbook - a sample program that performs common read and write operations on a FITS file. iter_a, iter_b, iter_c - examples of the CFITSIO iterator routine \end{verbatim} The first 4 of these utility programs can be compiled and linked by typing \begin{verbatim} % make program_name \end{verbatim} \section{Linking Programs with FITSIO} When linking applications software with the FITSIO library, several system libraries usually need to be specified on the link comman Unix systems, the most reliable way to determine what libraries are required is to type 'make testprog' and see what libraries the configure script has added. The typical libraries that may need to be added are -lm (the math library) and -lnsl and -lsocket (needed only for FTP and HTTP file access). These latter 2 libraries are not needed on VMS and Windows platforms, because FTP file access is not currently supported on those platforms. Note that when upgrading to a newer version of CFITSIO it is usually necessary to recompile, as well as relink, the programs that use CFITSIO, because the definitions in fitsio.h often change. \section{Getting Started with FITSIO} In order to effectively use the FITSIO library as quickly as possible, it is recommended that new users follow these steps: 1. Read the following `FITS Primer' chapter for a brief overview of the structure of FITS files. This is especially important for users who have not previously dealt with the FITS table and image extensions. 2. Write a simple program to read or write a FITS file using the Basic Interface routines. 3. Refer to the cookbook.f program that is included with this release for examples of routines that perform various common FITS file operations. 4. Read Chapters 4 and 5 to become familiar with the conventions and advanced features of the FITSIO interface. 5. Scan through the more extensive set of routines that are provided in the `Advanced Interface'. These routines perform more specialized functions than are provided by the Basic Interface routines. \section{Example Program} The following listing shows an example of how to use the FITSIO routines in a Fortran program. Refer to the cookbook.f program that is included with the FITSIO distribution for examples of other FITS programs. \begin{verbatim} program writeimage C Create a FITS primary array containing a 2-D image integer status,unit,blocksize,bitpix,naxis,naxes(2) integer i,j,group,fpixel,nelements,array(300,200) character filename*80 logical simple,extend status=0 C Name of the FITS file to be created: filename='ATESTFILE.FITS' C Get an unused Logical Unit Number to use to create the FITS file call ftgiou(unit,status) C create the new empty FITS file blocksize=1 call ftinit(unit,filename,blocksize,status) C initialize parameters about the FITS image (300 x 200 16-bit integers) simple=.true. bitpix=16 naxis=2 naxes(1)=300 naxes(2)=200 extend=.true. C write the required header keywords call ftphpr(unit,simple,bitpix,naxis,naxes,0,1,extend,status) C initialize the values in the image with a linear ramp function do j=1,naxes(2) do i=1,naxes(1) array(i,j)=i+j end do end do C write the array to the FITS file group=1 fpixel=1 nelements=naxes(1)*naxes(2) call ftpprj(unit,group,fpixel,nelements,array,status) C write another optional keyword to the header call ftpkyj(unit,'EXPOSURE',1500,'Total Exposure Time',status) C close the file and free the unit number call ftclos(unit, status) call ftfiou(unit, status) end \end{verbatim} \section{Legal Stuff} Copyright (Unpublished--all rights reserved under the copyright laws of the United States), U.S. Government as represented by the Administrator of the National Aeronautics and Space Administration. No copyright is claimed in the United States under Title 17, U.S. Code. Permission to freely use, copy, modify, and distribute this software and its documentation without fee is hereby granted, provided that this copyright notice and disclaimer of warranty appears in all copies. DISCLAIMER: THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT SHALL NASA BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT , OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER." \section{Acknowledgments} The development of many of the powerful features in CFITSIO was made possible through collaborations with many people or organizations from around the world. The following, in particular, have made especially significant contributions: Programmers from the Integral Science Data Center, Switzerland (namely, Jurek Borkowski, Bruce O'Neel, and Don Jennings), designed the concept for the plug-in I/O drivers that was introduced with CFITSIO 2.0. The use of `drivers' greatly simplified the low-level I/O, which in turn made other new features in CFITSIO (e.g., support for compressed FITS files and support for IRAF format image files) much easier to implement. Jurek Borkowski wrote the Shared Memory driver, and Bruce O'Neel wrote the drivers for accessing FITS files over the network using the FTP, HTTP, and ROOT protocols. The ISDC also provided the template parsing routines (written by Jurek Borkowski) and the hierarchical grouping routines (written by Don Jennings). The ISDC DAL (Data Access Layer) routines are layered on top of CFITSIO and make extensive use of these features. Uwe Lammers (XMM/ESA/ESTEC, The Netherlands) designed the high-performance lexical parsing algorithm that is used to do on-the-fly filtering of FITS tables. This algorithm essentially pre-compiles the user-supplied selection expression into a form that can be rapidly evaluated for each row. Peter Wilson (RSTX, NASA/GSFC) then wrote the parsing routines used by CFITSIO based on Lammers' design, combined with other techniques such as the CFITSIO iterator routine to further enhance the data processing throughput. This effort also benefited from a much earlier lexical parsing routine that was developed by Kent Blackburn (NASA/GSFC). More recently, Craig Markwardt (NASA/GSFC) implemented additional functions (median, average, stddev) and other enhancements to the lexical parser. The CFITSIO iterator function is loosely based on similar ideas developed for the XMM Data Access Layer. Peter Wilson (RSTX, NASA/GSFC) wrote the complete set of Fortran-callable wrappers for all the CFITSIO routines, which in turn rely on the CFORTRAN macro developed by Burkhard Burow. The syntax used by CFITSIO for filtering or binning input FITS files is based on ideas developed for the AXAF Science Center Data Model by Jonathan McDowell, Antonella Fruscione, Aneta Siemiginowska and Bill Joye. See http://heasarc.gsfc.nasa.gov/docs/journal/axaf7.html for further description of the AXAF Data Model. The file decompression code were taken directly from the gzip (GNU zip) program developed by Jean-loup Gailly and others. Doug Mink, SAO, provided the routines for converting IRAF format images into FITS format. Martin Reinecke (Max Planck Institute, Garching)) provided the modifications to cfortran.h that are necessary to support 64-bit integer values when calling C routines from fortran programs. The cfortran.h macros were originally developed by Burkhard Burow (CERN). Julian Taylor (ESO, Garching) provided the fast byte-swapping algorithms that use the SSE2 and SSSE3 machine instructions available on x86\_64 CPUs. In addition, many other people have made valuable contributions to the development of CFITSIO. These include (with apologies to others that may have inadvertently been omitted): Steve Allen, Carl Akerlof, Keith Arnaud, Morten Krabbe Barfoed, Kent Blackburn, G Bodammer, Romke Bontekoe, Lucio Chiappetti, Keith Costorf, Robin Corbet, John Davis, Richard Fink, Ning Gan, Emily Greene, Joe Harrington, Cheng Ho, Phil Hodge, Jim Ingham, Yoshitaka Ishisaki, Diab Jerius, Mark Levine, Todd Karakaskian, Edward King, Scott Koch, Claire Larkin, Rob Managan, Eric Mandel, John Mattox, Carsten Meyer, Emi Miyata, Stefan Mochnacki, Mike Noble, Oliver Oberdorf, Clive Page, Arvind Parmar, Jeff Pedelty, Tim Pearson, Maren Purves, Scott Randall, Chris Rogers, Arnold Rots, Barry Schlesinger, Robin Stebbins, Andrew Szymkowiak, Allyn Tennant, Peter Teuben, James Theiler, Doug Tody, Shiro Ueno, Steve Walton, Archie Warnock, Alan Watson, Dan Whipple, Wim Wimmers, Peter Young, Jianjun Xu, and Nelson Zarate. \chapter{ A FITS Primer } This section gives a brief overview of the structure of FITS files. Users should refer to the documentation available from the FITS Support Office, as described in the introduction, for more detailed information on FITS formats. FITS was first developed in the late 1970's as a standard data interchange format between various astronomical observatories. Since then FITS has become the defacto standard data format supported by most astronomical data analysis software packages. A FITS file consists of one or more Header + Data Units (HDUs), where the first HDU is called the `Primary HDU', or `Primary Array'. The primary array contains an N-dimensional array of pixels, such as a 1-D spectrum, a 2-D image, or a 3-D data cube. Six different primary datatypes are supported: Unsigned 8-bit bytes, 16, 32, and 64-bit signed integers, and 32 and 64-bit floating point reals. FITS also has a convention for storing unsigned integers (see the later section entitled `Unsigned Integers' for more details). The primary HDU may also consist of only a header with a null array containing no data pixels. Any number of additional HDUs may follow the primary array; these additional HDUs are called FITS `extensions'. There are currently 3 types of extensions defined by the FITS standard: \begin{itemize} \item Image Extension - a N-dimensional array of pixels, like in a primary array \item ASCII Table Extension - rows and columns of data in ASCII character format \item Binary Table Extension - rows and columns of data in binary representation \end{itemize} In each case the HDU consists of an ASCII Header Unit followed by an optional Data Unit. For historical reasons, each Header or Data unit must be an exact multiple of 2880 8-bit bytes long. Any unused space is padded with fill characters (ASCII blanks or zeros). Each Header Unit consists of any number of 80-character keyword records or `card images' which have the general form: \begin{verbatim} KEYNAME = value / comment string NULLKEY = / comment: This keyword has no value \end{verbatim} The keyword names may be up to 8 characters long and can only contain uppercase letters, the digits 0-9, the hyphen, and the underscore character. The keyword name is (usually) followed by an equals sign and a space character (= ) in columns 9 - 10 of the record, followed by the value of the keyword which may be either an integer, a floating point number, a character string (enclosed in single quotes), or a boolean value (the letter T or F). A keyword may also have a null or undefined value if there is no specified value string, as in the second example. The last keyword in the header is always the `END' keyword which has no value or comment fields. There are many rules governing the exact format of a keyword record (see the FITS Standard) so it is better to rely on standard interface software like FITSIO to correctly construct or to parse the keyword records rather than try to deal directly with the raw FITS formats. Each Header Unit begins with a series of required keywords which depend on the type of HDU. These required keywords specify the size and format of the following Data Unit. The header may contain other optional keywords to describe other aspects of the data, such as the units or scaling values. Other COMMENT or HISTORY keywords are also frequently added to further document the data file. The optional Data Unit immediately follows the last 2880-byte block in the Header Unit. Some HDUs do not have a Data Unit and only consist of the Header Unit. If there is more than one HDU in the FITS file, then the Header Unit of the next HDU immediately follows the last 2880-byte block of the previous Data Unit (or Header Unit if there is no Data Unit). The main required keywords in FITS primary arrays or image extensions are: \begin{itemize} \item BITPIX -- defines the datatype of the array: 8, 16, 32, 64, -32, -64 for unsigned 8--bit byte, 16--bit signed integer, 32--bit signed integer, 64--bit signed integer, 32--bit IEEE floating point, and 64--bit IEEE double precision floating point, respectively. \item NAXIS -- the number of dimensions in the array, usually 0, 1, 2, 3, or 4. \item NAXISn -- (n ranges from 1 to NAXIS) defines the size of each dimension. \end{itemize} FITS tables start with the keyword XTENSION = `TABLE' (for ASCII tables) or XTENSION = `BINTABLE' (for binary tables) and have the following main keywords: \begin{itemize} \item TFIELDS -- number of fields or columns in the table \item NAXIS2 -- number of rows in the table \item TTYPEn -- for each column (n ranges from 1 to TFIELDS) gives the name of the column \item TFORMn -- the datatype of the column \item TUNITn -- the physical units of the column (optional) \end{itemize} Users should refer to the FITS Support Office at {\tt http://fits.gsfc.nasa.gov} for further information about the FITS format and related software packages. \chapter{FITSIO Conventions and Guidelines } \section{CFITSIO Size Limitations} CFITSIO places few restrictions on the size of FITS files that it reads or writes. There are a few limits, however, which may affect some extreme cases: 1. The maximum number of FITS files that may be simultaneously opened by CFITSIO is set by NMAXFILES, as defined in fitsio2.h. The current default value is 1000, but this may be increased if necessary. Note that CFITSIO allocates NIOBUF * 2880 bytes of I/O buffer space for each file that is opened. The default value of NIOBUF is 40 (defined in fitsio.h), so this amounts to more than 115K of memory for each opened file (or 115 MB for 1000 opened files). Note that the underlying operating system, may have a lower limit on the number of files that can be opened simultaneously. 2. By default, CFITSIO can handle FITS files up to 2.1 GB in size (2**31 bytes). This file size limit is often imposed by 32-bit operating systems. More recently, as 64-bit operating systems become more common, an industry-wide standard (at least on Unix systems) has been developed to support larger sized files (see http://ftp.sas.com/standards/large.file/). Starting with version 2.1 of CFITSIO, larger FITS files up to 6 terabytes in size may be read and written on supported platforms. In order to support these larger files, CFITSIO must be compiled with the '-D\_LARGEFILE\_SOURCE' and `-D\_FILE\_OFFSET\_BITS=64' compiler flags. Some platforms may also require the `-D\_LARGE\_FILES' compiler flag. This causes the compiler to allocate 8-bytes instead of 4-bytes for the `off\_t' datatype which is used to store file offset positions. It appears that in most cases it is not necessary to also include these compiler flags when compiling programs that link to the CFITSIO library. If CFITSIO is compiled with the -D\_LARGEFILE\_SOURCE and -D\_FILE\_OFFSET\_BITS=64 flags on a platform that supports large files, then it can read and write FITS files that contain up to 2**31 2880-byte FITS records, or approximately 6 terabytes in size. It is still required that the value of the NAXISn and PCOUNT keywords in each extension be within the range of a signed 4-byte integer (max value = 2,147,483,648). Thus, each dimension of an image (given by the NAXISn keywords), the total width of a table (NAXIS1 keyword), the number of rows in a table (NAXIS2 keyword), and the total size of the variable-length array heap in binary tables (PCOUNT keyword) must be less than this limit. Currently, support for large files within CFITSIO has been tested on the Linux, Solaris, and IBM AIX operating systems. \section{Multiple Access to the Same FITS File} CFITSIO supports simultaneous read and write access to multiple HDUs in the same FITS file. Thus, one can open the same FITS file twice within a single program and move to 2 different HDUs in the file, and then read and write data or keywords to the 2 extensions just as if one were accessing 2 completely separate FITS files. Since in general it is not possible to physically open the same file twice and then expect to be able to simultaneously (or in alternating succession) write to 2 different locations in the file, CFITSIO recognizes when the file to be opened (in the call to fits\_open\_file) has already been opened and instead of actually opening the file again, just logically links the new file to the old file. (This only applies if the file is opened more than once within the same program, and does not prevent the same file from being simultaneously opened by more than one program). Then before CFITSIO reads or writes to either (logical) file, it makes sure that any modifications made to the other file have been completely flushed from the internal buffers to the file. Thus, in principle, one could open a file twice, in one case pointing to the first extension and in the other pointing to the 2nd extension and then write data to both extensions, in any order, without danger of corrupting the file, There may be some efficiency penalties in doing this however, since CFITSIO has to flush all the internal buffers related to one file before switching to the other, so it would still be prudent to minimize the number of times one switches back and forth between doing I/O to different HDUs in the same file. \section{Current Header Data Unit (CHDU)} In general, a FITS file can contain multiple Header Data Units, also called extensions. CFITSIO only operates within one HDU at any given time, and the currently selected HDU is called the Current Header Data Unit (CHDU). When a FITS file is first created or opened the CHDU is automatically defined to be the first HDU (i.e., the primary array). CFITSIO routines are provided to move to and open any other existing HDU within the FITS file or to append or insert a new HDU in the FITS file which then becomes the CHDU. \section{Subroutine Names} All FITSIO subroutine names begin with the letters 'ft' to distinguish them from other subroutines and are 5 or 6 characters long. Users should not name their own subroutines beginning with 'ft' to avoid conflicts. (The SPP interface routines all begin with 'fs'). Subroutines which read or get information from the FITS file have names beginning with 'ftg...'. Subroutines which write or put information into the FITS file have names beginning with 'ftp...'. \section{Subroutine Families and Datatypes} Many of the subroutines come in families which differ only in the datatype of the associated parameter(s) . The datatype of these subroutines is indicated by the last letter of the subroutine name (e.g., 'j' in 'ftpkyj') as follows: \begin{verbatim} x - bit b - character*1 (unsigned byte) i - short integer (I*2) j - integer (I*4, 32-bit integer) k - long long integer (I*8, 64-bit integer) e - real exponential floating point (R*4) f - real fixed-format floating point (R*4) d - double precision real floating-point (R*8) g - double precision fixed-format floating point (R*8) c - complex reals (pairs of R*4 values) m - double precision complex (pairs of R*8 values) l - logical (L*4) s - character string \end{verbatim} When dealing with the FITS byte datatype, it is important to remember that the raw values (before any scaling by the BSCALE and BZERO, or TSCALn and TZEROn keyword values) in byte arrays (BITPIX = 8) or byte columns (TFORMn = 'B') are interpreted as unsigned bytes with values ranging from 0 to 255. Some Fortran compilers support a non-standard byte datatype such as INTEGER*1, LOGICAL*1, or BYTE, which can sometimes be used instead of CHARACTER*1 variables. Many machines permit passing a numeric datatype (such as INTEGER*1) to the FITSIO subroutines which are expecting a CHARACTER*1 datatype, but this technically violates the Fortran-77 standard and is not supported on all machines (e.g., on a VAX/VMS machine one must use the VAX-specific \%DESCR function). One feature of the CFITSIO routines is that they can operate on a `X' (bit) column in a binary table as though it were a `B' (byte) column. For example a `11X' datatype column can be interpreted the same as a `2B' column (i.e., 2 unsigned 8-bit bytes). In some instances, it can be more efficient to read and write whole bytes at a time, rather than reading or writing each individual bit. The double precision complex datatype is not a standard Fortran-77 datatype. If a particular Fortran compiler does not directly support this datatype, then one may instead pass an array of pairs of double precision values to these subroutines. The first value in each pair is the real part, and the second is the imaginary part. \section{Implicit Data Type Conversion} The FITSIO routines that read and write numerical data can perform implicit data type conversion. This means that the data type of the variable or array in the program does not need to be the same as the data type of the value in the FITS file. Data type conversion is supported for numerical and string data types (if the string contains a valid number enclosed in quotes) when reading a FITS header keyword value and for numeric values when reading or writing values in the primary array or a table column. CFITSIO returns status = NUM\_OVERFLOW if the converted data value exceeds the range of the output data type. Implicit data type conversion is not supported within binary tables for string, logical, complex, or double complex data types. In addition, any table column may be read as if it contained string values. In the case of numeric columns the returned string will be formatted using the TDISPn display format if it exists. \section{Data Scaling} When reading numerical data values in the primary array or a table column, the values will be scaled automatically by the BSCALE and BZERO (or TSCALn and TZEROn) header keyword values if they are present in the header. The scaled data that is returned to the reading program will have \begin{verbatim} output value = (FITS value) * BSCALE + BZERO \end{verbatim} (a corresponding formula using TSCALn and TZEROn is used when reading from table columns). In the case of integer output values the floating point scaled value is truncated to an integer (not rounded to the nearest integer). The ftpscl and fttscl subroutines may be used to override the scaling parameters defined in the header (e.g., to turn off the scaling so that the program can read the raw unscaled values from the FITS file). When writing numerical data to the primary array or to a table column the data values will generally be automatically inversely scaled by the value of the BSCALE and BZERO (or TSCALn and TZEROn) header keyword values if they they exist in the header. These keywords must have been written to the header before any data is written for them to have any effect. Otherwise, one may use the ftpscl and fttscl subroutines to define or override the scaling keywords in the header (e.g., to turn off the scaling so that the program can write the raw unscaled values into the FITS file). If scaling is performed, the inverse scaled output value that is written into the FITS file will have \begin{verbatim} FITS value = ((input value) - BZERO) / BSCALE \end{verbatim} (a corresponding formula using TSCALn and TZEROn is used when writing to table columns). Rounding to the nearest integer, rather than truncation, is performed when writing integer datatypes to the FITS file. \section{Error Status Values and the Error Message Stack} The last parameter in nearly every FITSIO subroutine is the error status value which is both an input and an output parameter. A returned positive value for this parameter indicates an error was detected. A listing of all the FITSIO status code values is given at the end of this document. The FITSIO library uses an `inherited status' convention for the status parameter which means that if a subroutine is called with a positive input value of the status parameter, then the subroutine will exit immediately without changing the value of the status parameter. Thus, if one passes the status value returned from each FITSIO routine as input to the next FITSIO subroutine, then whenever an error is detected all further FITSIO processing will cease. This convention can simplify the error checking in application programs because it is not necessary to check the value of the status parameter after every single FITSIO subroutine call. If a program contains a sequence of several FITSIO calls, one can just check the status value after the last call. Since the returned status values are generally distinctive, it should be possible to determine which subroutine originally returned the error status. FITSIO also maintains an internal stack of error messages (80-character maximum length) which in many cases provide a more detailed explanation of the cause of the error than is provided by the error status number alone. It is recommended that the error message stack be printed out whenever a program detects a FITSIO error. To do this, call the FTGMSG routine repeatedly to get the successive messages on the stack. When the stack is empty FTGMSG will return a blank string. Note that this is a `First In -- First Out' stack, so the oldest error message is returned first by ftgmsg. \section{Variable-Length Array Facility in Binary Tables} FITSIO provides easy-to-use support for reading and writing data in variable length fields of a binary table. The variable length columns have TFORMn keyword values of the form `1Pt(len)' or `1Qt(len)' where `t' is the datatype code (e.g., I, J, E, D, etc.) and `len' is an integer specifying the maximum length of the vector in the table. If the value of `len' is not specified when the table is created (e.g., if the TFORM keyword value is simply specified as '1PE' instead of '1PE(400) ), then FITSIO will automatically scan the table when it is closed to determine the maximum length of the vector and will append this value to the TFORMn value. The same routines which read and write data in an ordinary fixed length binary table extension are also used for variable length fields, however, the subroutine parameters take on a slightly different interpretation as described below. All the data in a variable length field is written into an area called the `heap' which follows the main fixed-length FITS binary table. The size of the heap, in bytes, is specified with the PCOUNT keyword in the FITS header. When creating a new binary table, the initial value of PCOUNT should usually be set to zero. FITSIO will recompute the size of the heap as the data is written and will automatically update the PCOUNT keyword value when the table is closed. When writing variable length data to a table, CFITSIO will automatically extend the size of the heap area if necessary, so that any following HDUs do not get overwritten. By default the heap data area starts immediately after the last row of the fixed-length table. This default starting location may be overridden by the THEAP keyword, but this is not recommended. If additional rows of data are added to the table, CFITSIO will automatically shift the the heap down to make room for the new rows, but it is obviously be more efficient to initially create the table with the necessary number of blank rows, so that the heap does not needed to be constantly moved. When writing to a variable length field, the entire array of values for a given row of the table must be written with a single call to FTPCLx. The total length of the array is calculated from (NELEM+FELEM-1). One cannot append more elements to an existing field at a later time; any attempt to do so will simply overwrite all the data which was previously written. Note also that the new data will be written to a new area of the heap and the heap space used by the previous write cannot be reclaimed. For this reason it is advised that each row of a variable length field only be written once. An exception to this general rule occurs when setting elements of an array as undefined. One must first write a dummy value into the array with FTPCLx, and then call FTPCLU to flag the desired elements as undefined. (Do not use the FTPCNx family of routines with variable length fields). Note that the rows of a table, whether fixed or variable length, do not have to be written consecutively and may be written in any order. When writing to a variable length ASCII character field (e.g., TFORM = '1PA') only a single character string written. FTPCLS writes the whole length of the input string (minus any trailing blank characters), thus the NELEM and FELEM parameters are ignored. If the input string is completely blank then FITSIO will write one blank character to the FITS file. Similarly, FTGCVS and FTGCFS read the entire string (truncated to the width of the character string argument in the subroutine call) and also ignore the NELEM and FELEM parameters. The FTPDES subroutine is useful in situations where multiple rows of a variable length column have the identical array of values. One can simply write the array once for the first row, and then use FTPDES to write the same descriptor values into the other rows (use the FTGDES routine to read the first descriptor value); all the rows will then point to the same storage location thus saving disk space. When reading from a variable length array field one can only read as many elements as actually exist in that row of the table; reading does not automatically continue with the next row of the table as occurs when reading an ordinary fixed length table field. Attempts to read more than this will cause an error status to be returned. One can determine the number of elements in each row of a variable column with the FTGDES subroutine. \section{Support for IEEE Special Values} The ANSI/IEEE-754 floating-point number standard defines certain special values that are used to represent such quantities as Not-a-Number (NaN), denormalized, underflow, overflow, and infinity. (See the Appendix in the FITS standard or the FITS User's Guide for a list of these values). The FITSIO subroutines that read floating point data in FITS files recognize these IEEE special values and by default interpret the overflow and infinity values as being equivalent to a NaN, and convert the underflow and denormalized values into zeros. In some cases programmers may want access to the raw IEEE values, without any modification by FITSIO. This can be done by calling the FTGPVx or FTGCVx routines while specifying 0.0 as the value of the NULLVAL parameter. This will force FITSIO to simply pass the IEEE values through to the application program, without any modification. This does not work for double precision values on VAX/VMS machines, however, where there is no easy way to bypass the default interpretation of the IEEE special values. This is also not supported when reading floating-point images that have been compressed with the FITS tiled image compression convention that is discussed in section 5.6; the pixels values in tile compressed images are represented by scaled integers, and a reserved integer value (not a NaN) is used to represent undefined pixels. \section{When the Final Size of the FITS HDU is Unknown} It is not required to know the total size of a FITS data array or table before beginning to write the data to the FITS file. In the case of the primary array or an image extension, one should initially create the array with the size of the highest dimension (largest NAXISn keyword) set to a dummy value, such as 1. Then after all the data have been written and the true dimensions are known, then the NAXISn value should be updated using the fits\_ update\_key routine before moving to another extension or closing the FITS file. When writing to FITS tables, CFITSIO automatically keeps track of the highest row number that is written to, and will increase the size of the table if necessary. CFITSIO will also automatically insert space in the FITS file if necessary, to ensure that the data 'heap', if it exists, and/or any additional HDUs that follow the table do not get overwritten as new rows are written to the table. As a general rule it is best to specify the initial number of rows = 0 when the table is created, then let CFITSIO keep track of the number of rows that are actually written. The application program should not manually update the number of rows in the table (as given by the NAXIS2 keyword) since CFITSIO does this automatically. If a table is initially created with more than zero rows, then this will usually be considered as the minimum size of the table, even if fewer rows are actually written to the table. Thus, if a table is initially created with NAXIS2 = 20, and CFITSIO only writes 10 rows of data before closing the table, then NAXIS2 will remain equal to 20. If however, 30 rows of data are written to this table, then NAXIS2 will be increased from 20 to 30. The one exception to this automatic updating of the NAXIS2 keyword is if the application program directly modifies the value of NAXIS2 (up or down) itself just before closing the table. In this case, CFITSIO does not update NAXIS2 again, since it assumes that the application program must have had a good reason for changing the value directly. This is not recommended, however, and is only provided for backward compatibility with software that initially creates a table with a large number of rows, than decreases the NAXIS2 value to the actual smaller value just before closing the table. \section{Local FITS Conventions supported by FITSIO} CFITSIO supports several local FITS conventions which are not defined in the official FITS standard and which are not necessarily recognized or supported by other FITS software packages. Programmers should be cautious about using these features, especially if the FITS files that are produced are expected to be processed by other software systems which do not use the CFITSIO interface. \subsection{Support for Long String Keyword Values.} The length of a standard FITS string keyword is limited to 68 characters because it must fit entirely within a single FITS header keyword record. In some instances it is necessary to encode strings longer than this limit, so FITSIO supports a local convention in which the string value is continued over multiple keywords. This continuation convention uses an ampersand character at the end of each substring to indicate that it is continued on the next keyword, and the continuation keywords all have the name CONTINUE without an equal sign in column 9. The string value may be continued in this way over as many additional CONTINUE keywords as is required. The following lines illustrate this continuation convention which is used in the value of the STRKEY keyword: \begin{verbatim} LONGSTRN= 'OGIP 1.0' / The OGIP Long String Convention may be used. STRKEY = 'This is a very long string keyword&' / Optional Comment CONTINUE ' value that is continued over 3 keywords in the & ' CONTINUE 'FITS header.' / This is another optional comment. \end{verbatim} It is recommended that the LONGSTRN keyword, as shown here, always be included in any HDU that uses this longstring convention. A subroutine called FTPLSW has been provided in CFITSIO to write this keyword if it does not already exist. This long string convention is supported by the following FITSIO subroutines that deal with string-valued keywords: \begin{verbatim} ftgkys - read a string keyword ftpkls - write (append) a string keyword ftikls - insert a string keyword ftmkls - modify the value of an existing string keyword ftukls - update an existing keyword, or write a new keyword ftdkey - delete a keyword \end{verbatim} These routines will transparently read, write, or delete a long string value in the FITS file, so programmers in general do not have to be concerned about the details of the convention that is used to encode the long string in the FITS header. When reading a long string, one must ensure that the character string parameter used in these subroutine calls has been declared long enough to hold the entire string, otherwise the returned string value will be truncated. Note that the more commonly used FITSIO subroutine to write string valued keywords (FTPKYS) does NOT support this long string convention and only supports strings up to 68 characters in length. This has been done deliberately to prevent programs from inadvertently writing keywords using this non-standard convention without the explicit intent of the programmer or user. The FTPKLS subroutine must be called instead to write long strings. This routine can also be used to write ordinary string values less than 68 characters in length. \subsection{Arrays of Fixed-Length Strings in Binary Tables} CFITSIO supports 2 ways to specify that a character column in a binary table contains an array of fixed-length strings. The first way, which is officially supported by the FITS Standard document, uses the TDIMn keyword. For example, if TFORMn = '60A' and TDIMn = '(12,5)' then that column will be interpreted as containing an array of 5 strings, each 12 characters long. FITSIO also supports a local convention for the format of the TFORMn keyword value of the form 'rAw' where 'r' is an integer specifying the total width in characters of the column, and 'w' is an integer specifying the (fixed) length of an individual unit string within the vector. For example, TFORM1 = '120A10' would indicate that the binary table column is 120 characters wide and consists of 12 10-character length strings. This convention is recognized by the FITSIO subroutines that read or write strings in binary tables. The Binary Table definition document specifies that other optional characters may follow the datatype code in the TFORM keyword, so this local convention is in compliance with the FITS standard, although other FITS readers are not required to recognize this convention. \subsection{Keyword Units Strings} One deficiency of the current FITS Standard is that it does not define a specific convention for recording the physical units of a keyword value. The TUNITn keyword can be used to specify the physical units of the values in a table column, but there is no analogous convention for keyword values. The comment field of the keyword is often used for this purpose, but the units are usually not specified in a well defined format that FITS readers can easily recognize and extract. To solve this deficiency, FITSIO uses a local convention in which the keyword units are enclosed in square brackets as the first token in the keyword comment field; more specifically, the opening square bracket immediately follows the slash '/' comment field delimiter and a single space character. The following examples illustrate keywords that use this convention: \begin{verbatim} EXPOSURE= 1800.0 / [s] elapsed exposure time V_HELIO = 16.23 / [km s**(-1)] heliocentric velocity LAMBDA = 5400. / [angstrom] central wavelength FLUX = 4.9033487787637465E-30 / [J/cm**2/s] average flux \end{verbatim} In general, the units named in the IAU(1988) Style Guide are recommended, with the main exception that the preferred unit for angle is 'deg' for degrees. The FTPUNT and FTGUNT subroutines in FITSIO write and read, respectively, the keyword unit strings in an existing keyword. \subsection{HIERARCH Convention for Extended Keyword Names} CFITSIO supports the HIERARCH keyword convention which allows keyword names that are longer then 8 characters and may contain the full range of printable ASCII text characters. This convention was developed at the European Southern Observatory (ESO) to support hierarchical FITS keyword such as: \begin{verbatim} HIERARCH ESO INS FOCU POS = -0.00002500 / Focus position \end{verbatim} Basically, this convention uses the FITS keyword 'HIERARCH' to indicate that this convention is being used, then the actual keyword name ({\tt'ESO INS FOCU POS'} in this example) begins in column 10 and can contain any printable ASCII text characters, including spaces. The equals sign marks the end of the keyword name and is followed by the usual value and comment fields just as in standard FITS keywords. Further details of this convention are described at http://fits.gsfc.nasa.gov/registry/hierarch\_keyword.html and in Section 4.4 of the ESO Data Interface Control Document that is linked to from http://archive.eso.org/cms/tools-documentation/eso-data-interface-control.html. This convention allows a much broader range of keyword names than is allowed by the FITS Standard. Here are more examples of such keywords: \begin{verbatim} HIERARCH LongKeyword = 47.5 / Keyword has > 8 characters, and mixed case HIERARCH XTE$TEMP = 98.6 / Keyword contains the '$' character HIERARCH Earth is a star = F / Keyword contains embedded spaces \end{verbatim} CFITSIO will transparently read and write these keywords, so application programs do not in general need to know anything about the specific implementation details of the HIERARCH convention. In particular, application programs do not need to specify the `HIERARCH' part of the keyword name when reading or writing keywords (although it may be included if desired). When writing a keyword, CFITSIO first checks to see if the keyword name is legal as a standard FITS keyword (no more than 8 characters long and containing only letters, digits, or a minus sign or underscore). If so it writes it as a standard FITS keyword, otherwise it uses the hierarch convention to write the keyword. The maximum keyword name length is 67 characters, which leaves only 1 space for the value field. A more practical limit is about 40 characters, which leaves enough room for most keyword values. CFITSIO returns an error if there is not enough room for both the keyword name and the keyword value on the 80-character card, except for string-valued keywords which are simply truncated so that the closing quote character falls in column 80. In the current implementation, CFITSIO preserves the case of the letters when writing the keyword name, but it is case-insensitive when reading or searching for a keyword. The current implementation allows any ASCII text character (ASCII 32 to ASCII 126) in the keyword name except for the '=' character. A space is also required on either side of the equal sign. \section{Optimizing Code for Maximum Processing Speed} CFITSIO has been carefully designed to obtain the highest possible speed when reading and writing FITS files. In order to achieve the best performance, however, application programmers must be careful to call the CFITSIO routines appropriately and in an efficient sequence; inappropriate usage of CFITSIO routines can greatly slow down the execution speed of a program. The maximum possible I/O speed of CFITSIO depends of course on the type of computer system that it is running on. To get a general idea of what data I/O speeds are possible on a particular machine, build the speed.c program that is distributed with CFITSIO (type 'make speed' in the CFITSIO directory). This diagnostic program measures the speed of writing and reading back a test FITS image, a binary table, and an ASCII table. The following 2 sections provide some background on how CFITSIO internally manages the data I/O and describes some strategies that may be used to optimize the processing speed of software that uses CFITSIO. \subsection{Background Information: How CFITSIO Manages Data I/O} Many CFITSIO operations involve transferring only a small number of bytes to or from the FITS file (e.g, reading a keyword, or writing a row in a table); it would be very inefficient to physically read or write such small blocks of data directly in the FITS file on disk, therefore CFITSIO maintains a set of internal Input--Output (IO) buffers in RAM memory that each contain one FITS block (2880 bytes) of data. Whenever CFITSIO needs to access data in the FITS file, it first transfers the FITS block containing those bytes into one of the IO buffers in memory. The next time CFITSIO needs to access bytes in the same block it can then go to the fast IO buffer rather than using a much slower system disk access routine. The number of available IO buffers is determined by the NIOBUF parameter (in fitsio2.h) and is currently set to 40. Whenever CFITSIO reads or writes data it first checks to see if that block of the FITS file is already loaded into one of the IO buffers. If not, and if there is an empty IO buffer available, then it will load that block into the IO buffer (when reading a FITS file) or will initialize a new block (when writing to a FITS file). If all the IO buffers are already full, it must decide which one to reuse (generally the one that has been accessed least recently), and flush the contents back to disk if it has been modified before loading the new block. The one major exception to the above process occurs whenever a large contiguous set of bytes are accessed, as might occur when reading or writing a FITS image. In this case CFITSIO bypasses the internal IO buffers and simply reads or writes the desired bytes directly in the disk file with a single call to a low-level file read or write routine. The minimum threshold for the number of bytes to read or write this way is set by the MINDIRECT parameter and is currently set to 3 FITS blocks = 8640 bytes. This is the most efficient way to read or write large chunks of data. Note that this fast direct IO process is not applicable when accessing columns of data in a FITS table because the bytes are generally not contiguous since they are interleaved by the other columns of data in the table. This explains why the speed for accessing FITS tables is generally slower than accessing FITS images. Given this background information, the general strategy for efficiently accessing FITS files should now be apparent: when dealing with FITS images, read or write large chunks of data at a time so that the direct IO mechanism will be invoked; when accessing FITS headers or FITS tables, on the other hand, once a particular FITS block has been loading into one of the IO buffers, try to access all the needed information in that block before it gets flushed out of the IO buffer. It is important to avoid the situation where the same FITS block is being read then flushed from a IO buffer multiple times. The following section gives more specific suggestions for optimizing the use of CFITSIO. \subsection{Optimization Strategies} 1. Because the data in FITS files is always stored in "big-endian" byte order, where the first byte of numeric values contains the most significant bits and the last byte contains the least significant bits, CFITSIO must swap the order of the bytes when reading or writing FITS files when running on little-endian machines (e.g., Linux and Microsoft Windows operating systems running on PCs with x86 CPUs). On fairly new CPUs that support "SSSE3" machine instructions (e.g., starting with Intel Core 2 CPUs in 2007, and in AMD CPUs beginning in 2011) significantly faster 4-byte and 8-byte swapping algorithms are available. These faster byte swapping functions are not used by default in CFITSIO (because of the potential code portablility issues), but users can enable them on supported platforms by adding the appropriate compiler flags (-mssse3 with gcc or icc on linux) when compiling the swapproc.c source file, which will allow the compiler to generate code using the SSSE3 instruction set. A convenient way to do this is to configure the CFITSIO library with the following command: \begin{verbatim} > ./configure --enable-ssse3 \end{verbatim} Note, however, that a binary executable file that is created using these faster functions will only run on machines that support the SSSE3 machine instructions. It will crash on machines that do not support them. For faster 2-byte swaps on virtually all x86-64 CPUs (even those that do not support SSSE3), a variant using only SSE2 instructions exists. SSE2 is enabled by default on x86\_64 CPUs with 64-bit operating systems (and is also automatically enabled by the --enable-ssse3 flag). When running on x86\_64 CPUs with 32-bit operating systems, these faster 2-byte swapping algorithms are not used by default in CFITSIO, but can be enabled explicitly with: \begin{verbatim} ./configure --enable-sse2 \end{verbatim} Preliminary testing indicates that these SSSE3 and SSE2 based byte-swapping algorithms can boost the CFITSIO performance when reading or writing FITS images by 20\% - 30\% or more. It is important to note, however, that compiler optimization must be turned on (e.g., by using the -O1 or -O2 flags in gcc) when building programs that use these fast byte-swapping algorithms in order to reap the full benefit of the SSSE3 and SSE2 instructions; without optimization, the code may actually run slower than when using more traditional byte-swapping techniques. 2. When dealing with a FITS primary array or IMAGE extension, it is more efficient to read or write large chunks of the image at a time (at least 3 FITS blocks = 8640 bytes) so that the direct IO mechanism will be used as described in the previous section. Smaller chunks of data are read or written via the IO buffers, which is somewhat less efficient because of the extra copy operation and additional bookkeeping steps that are required. In principle it is more efficient to read or write as big an array of image pixels at one time as possible, however, if the array becomes so large that the operating system cannot store it all in RAM, then the performance may be degraded because of the increased swapping of virtual memory to disk. 3. When dealing with FITS tables, the most important efficiency factor in the software design is to read or write the data in the FITS file in a single pass through the file. An example of poor program design would be to read a large, 3-column table by sequentially reading the entire first column, then going back to read the 2nd column, and finally the 3rd column; this obviously requires 3 passes through the file which could triple the execution time of an I/O limited program. For small tables this is not important, but when reading multi-megabyte sized tables these inefficiencies can become significant. The more efficient procedure in this case is to read or write only as many rows of the table as will fit into the available internal I/O buffers, then access all the necessary columns of data within that range of rows. Then after the program is completely finished with the data in those rows it can move on to the next range of rows that will fit in the buffers, continuing in this way until the entire file has been processed. By using this procedure of accessing all the columns of a table in parallel rather than sequentially, each block of the FITS file will only be read or written once. The optimal number of rows to read or write at one time in a given table depends on the width of the table row, on the number of I/O buffers that have been allocated in FITSIO, and also on the number of other FITS files that are open at the same time (since one I/O buffer is always reserved for each open FITS file). Fortunately, a FITSIO routine is available that will return the optimal number of rows for a given table: call ftgrsz(unit, nrows, status). It is not critical to use exactly the value of nrows returned by this routine, as long as one does not exceed it. Using a very small value however can also lead to poor performance because of the overhead from the larger number of subroutine calls. The optimal number of rows returned by ftgrsz is valid only as long as the application program is only reading or writing data in the specified table. Any other calls to access data in the table header would cause additional blocks of data to be loaded into the I/O buffers displacing data from the original table, and should be avoided during the critical period while the table is being read or written. 4. Use binary table extensions rather than ASCII table extensions for better efficiency when dealing with tabular data. The I/O to ASCII tables is slower because of the overhead in formatting or parsing the ASCII data fields, and because ASCII tables are about twice as large as binary tables with the same information content. 5. Design software so that it reads the FITS header keywords in the same order in which they occur in the file. When reading keywords, FITSIO searches forward starting from the position of the last keyword that was read. If it reaches the end of the header without finding the keyword, it then goes back to the start of the header and continues the search down to the position where it started. In practice, as long as the entire FITS header can fit at one time in the available internal I/O buffers, then the header keyword access will be very fast and it makes little difference which order they are accessed. 6. Avoid the use of scaling (by using the BSCALE and BZERO or TSCAL and TZERO keywords) in FITS files since the scaling operations add to the processing time needed to read or write the data. In some cases it may be more efficient to temporarily turn off the scaling (using ftpscl or fttscl) and then read or write the raw unscaled values in the FITS file. 7. Avoid using the 'implicit datatype conversion' capability in FITSIO. For instance, when reading a FITS image with BITPIX = -32 (32-bit floating point pixels), read the data into a single precision floating point data array in the program. Forcing FITSIO to convert the data to a different datatype can significantly slow the program. 8. Where feasible, design FITS binary tables using vector column elements so that the data are written as a contiguous set of bytes, rather than as single elements in multiple rows. For example, it is faster to access the data in a table that contains a single row and 2 columns with TFORM keywords equal to '10000E' and '10000J', than it is to access the same amount of data in a table with 10000 rows which has columns with the TFORM keywords equal to '1E' and '1J'. In the former case the 10000 floating point values in the first column are all written in a contiguous block of the file which can be read or written quickly, whereas in the second case each floating point value in the first column is interleaved with the integer value in the second column of the same row so CFITSIO has to explicitly move to the position of each element to be read or written. 9. Avoid the use of variable length vector columns in binary tables, since any reading or writing of these data requires that CFITSIO first look up or compute the starting address of each row of data in the heap. In practice, this is probably not a significant efficiency issue. 10. When copying data from one FITS table to another, it is faster to transfer the raw bytes instead of reading then writing each column of the table. The FITSIO subroutines FTGTBS and FTPTBS (for ASCII tables), and FTGTBB and FTPTBB (for binary tables) will perform low-level reads or writes of any contiguous range of bytes in a table extension. These routines can be used to read or write a whole row (or multiple rows) of a table with a single subroutine call. These routines are fast because they bypass all the usual data scaling, error checking and machine dependent data conversion that is normally done by FITSIO, and they allow the program to write the data to the output file in exactly the same byte order. For these same reasons, use of these routines can be somewhat risky because no validation or machine dependent conversion is performed by these routines. In general these routines are only recommended for optimizing critical pieces of code and should only be used by programmers who thoroughly understand the internal byte structure of the FITS tables they are reading or writing. 11. Another strategy for improving the speed of writing a FITS table, similar to the previous one, is to directly construct the entire byte stream for a whole table row (or multiple rows) within the application program and then write it to the FITS file with ftptbb. This avoids all the overhead normally present in the column-oriented CFITSIO write routines. This technique should only be used for critical applications, because it makes the code more difficult to understand and maintain, and it makes the code more system dependent (e.g., do the bytes need to be swapped before writing to the FITS file?). 12. Finally, external factors such as the type of magnetic disk controller (SCSI or IDE), the size of the disk cache, the average seek speed of the disk, the amount of disk fragmentation, and the amount of RAM available on the system can all have a significant impact on overall I/O efficiency. For critical applications, a system administrator should review the proposed system hardware to identify any potential I/O bottlenecks. \chapter{ Basic Interface Routines } This section defines a basic set of subroutines that can be used to perform the most common types of read and write operations on FITS files. New users should start with these subroutines and then, as needed, explore the more advance routines described in the following chapter to perform more complex or specialized operations. A right arrow symbol ($>$) is used to separate the input parameters from the output parameters in the definition of each routine. This symbol is not actually part of the calling sequence. Note that the status parameter is both an input and an output parameter and must be initialized = 0 prior to calling the FITSIO subroutines. Refer to Chapter 9 for the definition of all the parameters used by these interface routines. \section{FITSIO Error Status Routines \label{FTVERS}} \begin{description} \item[1 ] Return the current version number of the fitsio library. The version number will be incremented with each new release of CFITSIO. \end{description} \begin{verbatim} FTVERS( > version) \end{verbatim} \begin{description} \item[2 ] Return the descriptive text string corresponding to a FITSIO error status code. The 30-character length string contains a brief description of the cause of the error. \end{description} \begin{verbatim} FTGERR(status, > errtext) \end{verbatim} \begin{description} \item[3 ] Return the top (oldest) 80-character error message from the internal FITSIO stack of error messages and shift any remaining messages on the stack up one level. Any FITSIO error will generate one or more messages on the stack. Call this routine repeatedly to get each message in sequence. The error stack is empty when a blank string is returned. \end{description} \begin{verbatim} FTGMSG( > errmsg) \end{verbatim} \begin{description} \item[4 ]The FTPMRK routine puts an invisible marker on the CFITSIO error stack. The FTCMRK routine can then be used to delete any more recent error messages on the stack, back to the position of the marker. This preserves any older error messages on the stack. FTCMSG simply clears the entire error message stack. These routines are called without any arguments. \end{description} \begin{verbatim} FTPMRK FTCMRK FTCMSG \end{verbatim} \begin{description} \item[5 ] Print out the error message corresponding to the input status value and all the error messages on the FITSIO stack to the specified file stream (stream can be either the string 'STDOUT' or 'STDERR'). If the input status value = 0 then this routine does nothing. \end{description} \begin{verbatim} FTRPRT (stream, > status) \end{verbatim} \begin{description} \item[6 ] Write an 80-character message to the FITSIO error stack. Application programs should not normally write to the stack, but there may be some situations where this is desirable. \end{description} \begin{verbatim} FTPMSG(errmsg) \end{verbatim} \section{File I/O Routines} \begin{description} \item[1 ]Open an existing FITS file with readonly or readwrite access. This routine always opens the primary array (the first HDU) of the file, and does not move to a following extension, if one was specified as part of the filename. Use the FTNOPN routine to automatically move to the extension. This routine will also open IRAF images (.imh format files) and raw binary data arrays with READONLY access by first converting them on the fly into virtual FITS images. See the `Extended File Name Syntax' chapter for more details. The FTDKOPN routine simply opens the specified file without trying to interpret the filename using the extended filename syntax. \end{description} \begin{verbatim} FTOPEN(unit,filename,rwmode, > blocksize,status) FTDKOPN(unit,filename,rwmode, > blocksize,status) \end{verbatim} \begin{description} \item[2 ]Open an existing FITS file with readonly or readwrite access and move to a following extension, if one was specified as part of the filename. (e.g., 'filename.fits+2' or 'filename.fits[2]' will move to the 3rd HDU in the file). Note that this routine differs from FTOPEN in that it does not have the redundant blocksize argument. \end{description} \begin{verbatim} FTNOPN(unit,filename,rwmode, > status) \end{verbatim} \begin{description} \item[3 ]Open an existing FITS file with readonly or readwrite access and then move to the first HDU containing significant data, if a) an HDU name or number to open was not explicitly specified as part of the filename, and b) if the FITS file contains a null primary array (i.e., NAXIS = 0). In this case, it will look for the first IMAGE HDU with NAXIS > 0, or the first table that does not contain the strings `GTI' (Good Time Interval) or `OBSTABLE' in the EXTNAME keyword value. FTTOPN is similar, except it will move to the first significant table HDU (skipping over any image HDUs) in the file if a specific HDU name or number is not specified. FTIOPN will move to the first non-null image HDU, skipping over any tables. \end{description} \begin{verbatim} FTDOPN(unit,filename,rwmode, > status) FTTOPN(unit,filename,rwmode, > status) FTIOPN(unit,filename,rwmode, > status) \end{verbatim} \begin{description} \item[4 ]Open and initialize a new empty FITS file. A template file may also be specified to define the structure of the new file (see section 4.2.4). The FTDKINIT routine simply creates the specified file without trying to interpret the filename using the extended filename syntax. \end{description} \begin{verbatim} FTINIT(unit,filename,blocksize, > status) FTDKINIT(unit,filename,blocksize, > status) \end{verbatim} \begin{description} \item[5 ]Close a FITS file previously opened with ftopen or ftinit \end{description} \begin{verbatim} FTCLOS(unit, > status) \end{verbatim} \begin{description} \item[6 ] Move to a specified (absolute) HDU in the FITS file (nhdu = 1 for the FITS primary array) \end{description} \begin{verbatim} FTMAHD(unit,nhdu, > hdutype,status) \end{verbatim} \begin{description} \item[7 ] Create a primary array (if none already exists), or insert a new IMAGE extension immediately following the CHDU, or insert a new Primary Array at the beginning of the file. Any following extensions in the file will be shifted down to make room for the new extension. If the CHDU is the last HDU in the file then the new image extension will simply be appended to the end of the file. One can force a new primary array to be inserted at the beginning of the FITS file by setting status = -9 prior to calling the routine. In this case the existing primary array will be converted to an IMAGE extension. The new extension (or primary array) will become the CHDU. The FTIIMGLL routine is identical to the FTIIMG routine except that the 4th parameter (the length of each axis) is an array of 64-bit integers rather than an array of 32-bit integers. \end{description} \begin{verbatim} FTIIMG(unit,bitpix,naxis,naxes, > status) FTIIMGLL(unit,bitpix,naxis,naxesll, > status) \end{verbatim} \begin{description} \item[8 ] Insert a new ASCII TABLE extension immediately following the CHDU. Any following extensions will be shifted down to make room for the new extension. If there are no other following extensions then the new table extension will simply be appended to the end of the file. The new extension will become the CHDU. The FTITABLL routine is identical to the FTITAB routine except that the 2nd and 3rd parameters (that give the size of the table) are 64-bit integers rather than 32-bit integers. Under normal circumstances, the nrows and nrowsll paramenters should have a value of 0; CFITSIO will automatically update the number of rows as data is written to the table. \end{description} \begin{verbatim} FTITAB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > status) FTITABLL(unit,rowlenll,nrowsll,tfields,ttype,tbcol,tform,tunit,extname, > status) \end{verbatim} \begin{description} \item[9 ] Insert a new binary table extension immediately following the CHDU. Any following extensions will be shifted down to make room for the new extension. If there are no other following extensions then the new bintable extension will simply be appended to the end of the file. The new extension will become the CHDU. The FTIBINLL routine is identical to the FTIBIN routine except that the 2nd parameter (that gives the length of the table) is a 64-bit integer rather than a 32-bit integer. Under normal circumstances, the nrows and nrowsll paramenters should have a value of 0; CFITSIO will automatically update the number of rows as data is written to the table. \end{description} \begin{verbatim} FTIBIN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat > status) FTIBINLL(unit,nrowsll,tfields,ttype,tform,tunit,extname,varidat > status) \end{verbatim} \section{Keyword I/O Routines} \begin{description} \item[1 ]Put (append) an 80-character record into the CHU. \end{description} \begin{verbatim} FTPREC(unit,card, > status) \end{verbatim} \begin{description} \item[2 ] Put (append) a new keyword of the appropriate datatype into the CHU. The E and D versions of this routine have the added feature that if the 'decimals' parameter is negative, then the 'G' display format rather then the 'E' format will be used when constructing the keyword value, taking the absolute value of 'decimals' for the precision. This will suppress trailing zeros, and will use a fixed format rather than an exponential format, depending on the magnitude of the value. \end{description} \begin{verbatim} FTPKY[JKLS](unit,keyword,keyval,comment, > status) FTPKY[EDFG](unit,keyword,keyval,decimals,comment, > status) \end{verbatim} \begin{description} \item[3 ]Get the nth 80-character header record from the CHU. The first keyword in the header is at key\_no = 1; if key\_no = 0 then this subroutine simple moves the internal pointer to the beginning of the header so that subsequent keyword operations will start at the top of the header; it also returns a blank card value in this case. \end{description} \begin{verbatim} FTGREC(unit,key_no, > card,status) \end{verbatim} \begin{description} \item[4 ] Get a keyword value (with the appropriate datatype) and comment from the CHU \end{description} \begin{verbatim} FTGKY[EDJKLS](unit,keyword, > keyval,comment,status) \end{verbatim} \begin{description} \item[5 ] Delete an existing keyword record. \end{description} \begin{verbatim} FTDKEY(unit,keyword, > status) \end{verbatim} \section{Data I/O Routines} The following routines read or write data values in the current HDU of the FITS file. Automatic datatype conversion will be attempted for numerical datatypes if the specified datatype is different from the actual datatype of the FITS array or table column. \begin{description} \item[1 ]Write elements into the primary data array or image extension. \end{description} \begin{verbatim} FTPPR[BIJKED](unit,group,fpixel,nelements,values, > status) \end{verbatim} \begin{description} \item[2 ] Read elements from the primary data array or image extension. Undefined array elements will be returned with a value = nullval, unless nullval = 0 in which case no checks for undefined pixels will be performed. The anyf parameter is set to true (= .true.) if any of the returned elements were undefined. \end{description} \begin{verbatim} FTGPV[BIJKED](unit,group,fpixel,nelements,nullval, > values,anyf,status) \end{verbatim} \begin{description} \item[3 ] Write elements into an ASCII or binary table column. The `felem' parameter applies only to vector columns in binary tables and is ignored when writing to ASCII tables. \end{description} \begin{verbatim} FTPCL[SLBIJKEDCM](unit,colnum,frow,felem,nelements,values, > status) \end{verbatim} \begin{description} \item[4 ] Read elements from an ASCII or binary table column. Undefined array elements will be returned with a value = nullval, unless nullval = 0 (or = ' ' for ftgcvs) in which case no checking for undefined values will be performed. The ANYF parameter is set to true if any of the returned elements are undefined. Any column, regardless of it's intrinsic datatype, may be read as a string. It should be noted however that reading a numeric column as a string is 10 - 100 times slower than reading the same column as a number due to the large overhead in constructing the formatted strings. The display format of the returned strings will be determined by the TDISPn keyword, if it exists, otherwise by the datatype of the column. The length of the returned strings can be determined with the ftgcdw routine. The following TDISPn display formats are currently supported: \begin{verbatim} Iw.m Integer Ow.m Octal integer Zw.m Hexadecimal integer Fw.d Fixed floating point Ew.d Exponential floating point Dw.d Exponential floating point Gw.d General; uses Fw.d if significance not lost, else Ew.d \end{verbatim} where w is the width in characters of the displayed values, m is the minimum number of digits displayed, and d is the number of digits to the right of the decimal. The .m field is optional. \end{description} \begin{verbatim} FTGCV[SBIJKEDCM](unit,colnum,frow,felem,nelements,nullval, > values,anyf,status) \end{verbatim} \begin{description} \item[5 ] Get the table column number and full name of the column whose name matches the input template string. See the `Advanced Interface Routines' chapter for a full description of this routine. \end{description} \begin{verbatim} FTGCNN(unit,casesen,coltemplate, > colname,colnum,status) \end{verbatim} \chapter{ Advanced Interface Subroutines } This chapter defines all the available subroutines in the FITSIO user interface. For completeness, the basic subroutines described in the previous chapter are also repeated here. A right arrow symbol is used here to separate the input parameters from the output parameters in the definition of each subroutine. This symbol is not actually part of the calling sequence. An alphabetical list and definition of all the parameters is given at the end of this section. \section{FITS File Open and Close Subroutines: \label{FTOPEN}} \begin{description} \item[1 ]Open an existing FITS file with readonly or readwrite access. The FTDKOPN routine simply opens the specified file without trying to interpret the filename using the extended filename syntax. FTDOPN opens the file and also moves to the first HDU containing significant data, if no specific HDU is specified as part of the filename. FTTOPN and FTIOPN are similar except that they will move to the first table HDU or image HDU, respectively, if a HDU name or number is not specified as part of the filename. \end{description} \begin{verbatim} FTOPEN(unit,filename,rwmode, > blocksize,status) FTDKOPN(unit,filename,rwmode, > blocksize,status) FTDOPN(unit,filename,rwmode, > status) FTTOPN(unit,filename,rwmode, > status) FTIOPN(unit,filename,rwmode, > status) \end{verbatim} \begin{description} \item[2 ]Open an existing FITS file with readonly or readwrite access and move to a following extension, if one was specified as part of the filename. (e.g., 'filename.fits+2' or 'filename.fits[2]' will move to the 3rd HDU in the file). Note that this routine differs from FTOPEN in that it does not have the redundant blocksize argument. \end{description} \begin{verbatim} FTNOPN(unit,filename,rwmode, > status) \end{verbatim} \begin{description} \item[3 ] Reopen a FITS file that was previously opened with FTOPEN, FTNOPN, or FTINIT. The newunit number may then be treated as a separate file, and one may simultaneously read or write to 2 (or more) different extensions in the same file. The FTOPEN and FTNOPN routines (above) automatically detects cases where a previously opened file is being opened again, and then internally call FTREOPEN, so programs should rarely need to explicitly call this routine. \end{description} \begin{verbatim} FTREOPEN(unit, > newunit, status) \end{verbatim} \begin{description} \item[4 ]Open and initialize a new empty FITS file. The FTDKINIT routine simply creates the specified file without trying to interpret the filename using the extended filename syntax. \end{description} \begin{verbatim} FTINIT(unit,filename,blocksize, > status) FTDKINIT(unit,filename,blocksize, > status) \end{verbatim} \begin{description} \item[5 ] Create a new FITS file, using a template file to define its initial size and structure. The template may be another FITS HDU or an ASCII template file. If the input template file name is blank, then this routine behaves the same as FTINIT. The currently supported format of the ASCII template file is described under the fits\_parse\_template routine (in the general Utilities section), but this may change slightly later releases of CFITSIO. \end{description} \begin{verbatim} FTTPLT(unit, filename, tplfilename, > status) \end{verbatim} \begin{description} \item[6 ]Flush internal buffers of data to the output FITS file previously opened with ftopen or ftinit. The routine usually never needs to be called, but doing so will ensure that if the program subsequently aborts, then the FITS file will have at least been closed properly. \end{description} \begin{verbatim} FTFLUS(unit, > status) \end{verbatim} \begin{description} \item[7 ]Close a FITS file previously opened with ftopen or ftinit \end{description} \begin{verbatim} FTCLOS(unit, > status) \end{verbatim} \begin{description} \item[8 ] Close and DELETE a FITS file previously opened with ftopen or ftinit. This routine may be useful in cases where a FITS file is created, but an error occurs which prevents the complete file from being written. \end{description} \begin{verbatim} FTDELT(unit, > status) \end{verbatim} \begin{description} \item[9 ] Get the value of an unused I/O unit number which may then be used as input to FTOPEN or FTINIT. This routine searches for the first unused unit number in the range from with 99 down to 50. This routine just keeps an internal list of the allocated unit numbers and does not physically check that the Fortran unit is available (to be compatible with the SPP version of FITSIO). Thus users must not independently allocate any unit numbers in the range 50 - 99 if this routine is also to be used in the same program. This routine is provided for convenience only, and it is not required that the unit numbers used by FITSIO be allocated by this routine. \end{description} \begin{verbatim} FTGIOU( > iounit, status) \end{verbatim} \begin{description} \item[10] Free (deallocate) an I/O unit number which was previously allocated with FTGIOU. All previously allocated unit numbers may be deallocated at once by calling FTFIOU with iounit = -1. \end{description} \begin{verbatim} FTFIOU(iounit, > status) \end{verbatim} \begin{description} \item[11] Return the Fortran unit number that corresponds to the C fitsfile pointer value, or vice versa. These 2 C routines may be useful in mixed language programs where both C and Fortran subroutines need to access the same file. For example, if a FITS file is opened with unit 12 by a Fortran subroutine, then a C routine within the same program could get the fitfile pointer value to access the same file by calling 'fptr = CUnit2FITS(12)'. These routines return a value of zero if an error occurs. \end{description} \begin{verbatim} int CFITS2Unit(fitsfile *ptr); fitsfile* CUnit2FITS(int unit); \end{verbatim} \begin{description} \item[11] Parse the input filename and return the HDU number that would be moved to if the file were opened with FTNOPN. The returned HDU number begins with 1 for the primary array, so for example, if the input filename = `myfile.fits[2]' then hdunum = 3 will be returned. FITSIO does not open the file to check if the extension actually exists if an extension number is specified. If an extension *name* is included in the file name specification (e.g. `myfile.fits[EVENTS]' then this routine will have to open the FITS file and look for the position of the named extension, then close file again. This is not possible if the file is being read from the stdin stream, and an error will be returned in this case. If the filename does not specify an explicit extension (e.g. 'myfile.fits') then hdunum = -99 will be returned, which is functionally equivalent to hdunum = 1. This routine is mainly used for backward compatibility in the ftools software package and is not recommended for general use. It is generally better and more efficient to first open the FITS file with FTNOPN, then use FTGHDN to determine which HDU in the file has been opened, rather than calling FTEXTN followed by a call to FTNOPN. \end{description} \begin{verbatim} FTEXTN(filename, > nhdu, status) \end{verbatim} \begin{description} \item[12] Return the name of the opened FITS file. \end{description} \begin{verbatim} FTFLNM(unit, > filename, status) \end{verbatim} \begin{description} \item[13] Return the I/O mode of the open FITS file (READONLY = 0, READWRITE = 1). \end{description} \begin{verbatim} FTFLMD(unit, > iomode, status) \end{verbatim} \begin{description} \item[14] Return the file type of the opened FITS file (e.g. 'file://', 'ftp://', etc.). \end{description} \begin{verbatim} FTURLT(unit, > urltype, status) \end{verbatim} \begin{description} \item[15] Parse the input filename or URL into its component parts: the file type (file://, ftp://, http://, etc), the base input file name, the name of the output file that the input file is to be copied to prior to opening, the HDU or extension specification, the filtering specifier, the binning specifier, and the column specifier. Blank strings will be returned for any components that are not present in the input file name. \end{description} \begin{verbatim} FTIURL(filename, > filetype, infile, outfile, extspec, filter, binspec, colspec, status) \end{verbatim} \begin{description} \item[16] Parse the input file name and return the root file name. The root name includes the file type if specified, (e.g. 'ftp://' or 'http://') and the full path name, to the extent that it is specified in the input filename. It does not include the HDU name or number, or any filtering specifications. \end{description} \begin{verbatim} FTRTNM(filename, > rootname, status) \end{verbatim} \begin{description} \item[16] Test if the input file or a compressed version of the file (with a .gz, .Z, .z, or .zip extension) exists on disk. The returned value of the 'exists' parameter will have 1 of the 4 following values: \begin{verbatim} 2: the file does not exist, but a compressed version does exist 1: the disk file does exist 0: neither the file nor a compressed version of the file exist -1: the input file name is not a disk file (could be a ftp, http, smem, or mem file, or a file piped in on the STDIN stream) \end{verbatim} \end{description} \begin{verbatim} FTEXIST(filename, > exists, status); \end{verbatim} \section{HDU-Level Operations \label{FTMAHD}} When a FITS file is first opened or created, the internal buffers in FITSIO automatically point to the first HDU in the file. The following routines may be used to move to another HDU in the file. Note that the HDU numbering convention used in FITSIO denotes the primary array as the first HDU, the first extension in a FITS file is the second HDU, and so on. \begin{description} \item[1 ] Move to a specified (absolute) HDU in the FITS file (nhdu = 1 for the FITS primary array) \end{description} \begin{verbatim} FTMAHD(unit,nhdu, > hdutype,status) \end{verbatim} \begin{description} \item[2 ]Move to a new (existing) HDU forward or backwards relative to the CHDU \end{description} \begin{verbatim} FTMRHD(unit,nmove, > hdutype,status) \end{verbatim} \begin{description} \item[3 ] Move to the (first) HDU which has the specified extension type and EXTNAME (or HDUNAME) and EXTVER keyword values. The hdutype parameter may have a value of IMAGE\_HDU (0), ASCII\_TBL (1), BINARY\_TBL (2), or ANY\_HDU (-1) where ANY\_HDU means that only the extname and extver values will be used to locate the correct extension. If the input value of extver is 0 then the EXTVER keyword is ignored and the first HDU with a matching EXTNAME (or HDUNAME) keyword will be found. If no matching HDU is found in the file then the current HDU will remain unchanged and a status = BAD\_HDU\_NUM (301) will be returned. \end{description} \begin{verbatim} FTMNHD(unit, hdutype, extname, extver, > status) \end{verbatim} \begin{description} \item[4 ]Get the number of the current HDU in the FITS file (primary array = 1) \end{description} \begin{verbatim} FTGHDN(unit, > nhdu) \end{verbatim} \begin{description} \item[5 ] Return the type of the current HDU in the FITS file. The possible values for hdutype are IMAGE\_HDU (0), ASCII\_TBL (1), or BINARY\_TBL (2). \end{description} \begin{verbatim} FTGHDT(unit, > hdutype, status) \end{verbatim} \begin{description} \item[6 ] Return the total number of HDUs in the FITS file. The CHDU remains unchanged. \end{description} \begin{verbatim} FTTHDU(unit, > hdunum, status) \end{verbatim} \begin{description} \item[7 ]Create (append) a new empty HDU at the end of the FITS file. This new HDU becomes the Current HDU, but it is completely empty and contains no header keywords or data. It is recommended that FTIIMG, FTITAB or FTIBIN be used instead of this routine. \end{description} \begin{verbatim} FTCRHD(unit, > status) \end{verbatim} \begin{description} \item[8 ] Create a primary array (if none already exists), or insert a new IMAGE extension immediately following the CHDU, or insert a new Primary Array at the beginning of the file. Any following extensions in the file will be shifted down to make room for the new extension. If the CHDU is the last HDU in the file then the new image extension will simply be appended to the end of the file. One can force a new primary array to be inserted at the beginning of the FITS file by setting status = -9 prior to calling the routine. In this case the existing primary array will be converted to an IMAGE extension. The new extension (or primary array) will become the CHDU. The FTIIMGLL routine is identical to the FTIIMG routine except that the 4th parameter (the length of each axis) is an array of 64-bit integers rather than an array of 32-bit integers. \end{description} \begin{verbatim} FTIIMG(unit,bitpix,naxis,naxes, > status) FTIIMGLL(unit,bitpix,naxis,naxesll, > status) \end{verbatim} \begin{description} \item[9 ] Insert a new ASCII TABLE extension immediately following the CHDU. Any following extensions will be shifted down to make room for the new extension. If there are no other following extensions then the new table extension will simply be appended to the end of the file. The new extension will become the CHDU. The FTITABLL routine is identical to the FTITAB routine except that the 2nd and 3rd parameters (that give the size of the table) are 64-bit integers rather than 32-bit integers. \end{description} \begin{verbatim} FTITAB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > status) FTITABLL(unit,rowlenll,nrowsll,tfields,ttype,tbcol,tform,tunit,extname, > status) \end{verbatim} \begin{description} \item[10] Insert a new binary table extension immediately following the CHDU. Any following extensions will be shifted down to make room for the new extension. If there are no other following extensions then the new bintable extension will simply be appended to the end of the file. The new extension will become the CHDU. The FTIBINLL routine is identical to the FTIBIN routine except that the 2nd parameter (that gives the length of the table) is a 64-bit integer rather than a 32-bit integer. \end{description} \begin{verbatim} FTIBIN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat > status) FTIBINLL(unit,nrowsll,tfields,ttype,tform,tunit,extname,varidat > status) \end{verbatim} \begin{description} \item[11] Resize an image by modifing the size, dimensions, and/or datatype of the current primary array or image extension. If the new image, as specified by the input arguments, is larger than the current existing image in the FITS file then zero fill data will be inserted at the end of the current image and any following extensions will be moved further back in the file. Similarly, if the new image is smaller than the current image then any following extensions will be shifted up towards the beginning of the FITS file and the image data will be truncated to the new size. This routine rewrites the BITPIX, NAXIS, and NAXISn keywords with the appropriate values for new image. The FTRSIMLL routine is identical to the FTRSIM routine except that the 4th parameter (the length of each axis) is an array of 64-bit integers rather than an array of 32-bit integers. \end{description} \begin{verbatim} FTRSIM(unit,bitpix,naxis,naxes,status) FTRSIMLL(unit,bitpix,naxis,naxesll,status) \end{verbatim} \begin{description} \item[12] Delete the CHDU in the FITS file. Any following HDUs will be shifted forward in the file, to fill in the gap created by the deleted HDU. In the case of deleting the primary array (the first HDU in the file) then the current primary array will be replace by a null primary array containing the minimum set of required keywords and no data. If there are more extensions in the file following the one that is deleted, then the the CHDU will be redefined to point to the following extension. If there are no following extensions then the CHDU will be redefined to point to the previous HDU. The output HDUTYPE parameter indicates the type of the new CHDU after the previous CHDU has been deleted. \end{description} \begin{verbatim} FTDHDU(unit, > hdutype,status) \end{verbatim} \begin{description} \item[13] Copy all or part of the input FITS file and append it to the end of the output FITS file. If 'previous' (an integer parameter) is not equal to 0, then any HDUs preceding the current HDU in the input file will be copied to the output file. Similarly, 'current' and 'following' determine whether the current HDU, and/or any following HDUs in the input file will be copied to the output file. If all 3 parameters are not equal to zero, then the entire input file will be copied. On return, the current HDU in the input file will be unchanged, and the last copied HDU will be the current HDU in the output file. \end{description} \begin{verbatim} FTCPFL(iunit, ounit, previous, current, following, > status) \end{verbatim} \begin{description} \item[14] Copy the entire CHDU from the FITS file associated with IUNIT to the CHDU of the FITS file associated with OUNIT. The output HDU must be empty and not already contain any keywords. Space will be reserved for MOREKEYS additional keywords in the output header if there is not already enough space. \end{description} \begin{verbatim} FTCOPY(iunit,ounit,morekeys, > status) \end{verbatim} \begin{description} \item[15] Copy the header (and not the data) from the CHDU associated with inunit to the CHDU associated with outunit. If the current output HDU is not completely empty, then the CHDU will be closed and a new HDU will be appended to the output file. This routine will automatically transform the necessary keywords when copying a primary array to and image extension, or an image extension to a primary array. An empty output data unit will be created (all values = 0). \end{description} \begin{verbatim} FTCPHD(inunit, outunit, > status) \end{verbatim} \begin{description} \item[16] Copy just the data from the CHDU associated with IUNIT to the CHDU associated with OUNIT. This will overwrite any data previously in the OUNIT CHDU. This low level routine is used by FTCOPY, but it may also be useful in certain application programs which want to copy the data from one FITS file to another but also want to modify the header keywords in the process. all the required header keywords must be written to the OUNIT CHDU before calling this routine \end{description} \begin{verbatim} FTCPDT(iunit,ounit, > status) \end{verbatim} \section{Define or Redefine the structure of the CHDU \label{FTRDEF}} It should rarely be necessary to call the subroutines in this section. FITSIO internally calls these routines whenever necessary, so any calls to these routines by application programs will likely be redundant. \begin{description} \item[1 ] This routine forces FITSIO to scan the current header keywords that define the structure of the HDU (such as the NAXISn, PCOUNT and GCOUNT keywords) so that it can initialize the internal buffers that describe the HDU structure. This routine may be used instead of the more complicated calls to ftpdef, ftadef or ftbdef. This routine is also very useful for reinitializing the structure of an HDU, if the number of rows in a table, as specified by the NAXIS2 keyword, has been modified from its initial value. \end{description} \begin{verbatim} FTRDEF(unit, > status) (DEPRECATED) \end{verbatim} \begin{description} \item[2 ]Define the structure of the primary array or IMAGE extension. When writing GROUPed FITS files that by convention set the NAXIS1 keyword equal to 0, ftpdef must be called with naxes(1) = 1, NOT 0, otherwise FITSIO will report an error status=308 when trying to write data to a group. Note: it is usually simpler to call FTRDEF rather than this routine. \end{description} \begin{verbatim} FTPDEF(unit,bitpix,naxis,naxes,pcount,gcount, > status) (DEPRECATED) \end{verbatim} \begin{description} \item[3 ] Define the structure of an ASCII table (TABLE) extension. Note: it is usually simpler to call FTRDEF rather than this routine. \end{description} \begin{verbatim} FTADEF(unit,rowlen,tfields,tbcol,tform,nrows > status) (DEPRECATED) \end{verbatim} \begin{description} \item[4 ] Define the structure of a binary table (BINTABLE) extension. Note: it is usually simpler to call FTRDEF rather than this routine. \end{description} \begin{verbatim} FTBDEF(unit,tfields,tform,varidat,nrows > status) (DEPRECATED) \end{verbatim} \begin{description} \item[5 ] Define the size of the Current Data Unit, overriding the length of the data unit as previously defined by ftpdef, ftadef, or ftbdef. This is useful if one does not know the total size of the data unit until after the data have been written. The size (in bytes) of an ASCII or Binary table is given by NAXIS1 * NAXIS2. (Note that to determine the value of NAXIS1 it is often more convenient to read the value of the NAXIS1 keyword from the output file, rather than computing the row length directly from all the TFORM keyword values). Note: it is usually simpler to call FTRDEF rather than this routine. \end{description} \begin{verbatim} FTDDEF(unit,bytlen, > status) (DEPRECATED) \end{verbatim} \begin{description} \item[6 ] Define the zero indexed byte offset of the 'heap' measured from the start of the binary table data. By default the heap is assumed to start immediately following the regular table data, i.e., at location NAXIS1 x NAXIS2. This routine is only relevant for binary tables which contain variable length array columns (with TFORMn = 'Pt'). This subroutine also automatically writes the value of theap to a keyword in the extension header. This subroutine must be called after the required keywords have been written (with ftphbn) and after the table structure has been defined (with ftbdef) but before any data is written to the table. \end{description} \begin{verbatim} FTPTHP(unit,theap, > status) \end{verbatim} \section{FITS Header I/O Subroutines} \subsection{Header Space and Position Routines \label{FTHDEF}} \begin{description} \item[1 ] Reserve space in the CHU for MOREKEYS more header keywords. This subroutine may be called to reserve space for keywords which are to be written at a later time, after the data unit or subsequent extensions have been written to the FITS file. If this subroutine is not explicitly called, then the initial size of the FITS header will be limited to the space available at the time that the first data is written to the associated data unit. FITSIO has the ability to dynamically add more space to the header if needed, however it is more efficient to preallocate the required space if the size is known in advance. \end{description} \begin{verbatim} FTHDEF(unit,morekeys, > status) \end{verbatim} \begin{description} \item[2 ] Return the number of existing keywords in the CHU (NOT including the END keyword which is not considered a real keyword) and the remaining space available to write additional keywords in the CHU. (returns KEYSADD = -1 if the header has not yet been closed). Note that FITSIO will attempt to dynamically add space for more keywords if required when appending new keywords to a header. \end{description} \begin{verbatim} FTGHSP(iunit, > keysexist,keysadd,status) \end{verbatim} \begin{description} \item[3 ] Return the number of keywords in the header and the current position in the header. This returns the number of the keyword record that will be read next (or one greater than the position of the last keyword that was read or written). A value of 1 is returned if the pointer is positioned at the beginning of the header. \end{description} \begin{verbatim} FTGHPS(iunit, > keysexist,key_no,status) \end{verbatim} \subsection{Read or Write Standard Header Routines \label{FTPHPR}} These subroutines provide a simple method of reading or writing most of the keyword values that are normally required in a FITS files. These subroutines are provided for convenience only and are not required to be used. If preferred, users may call the lower-level subroutines described in the previous section to individually read or write the required keywords. Note that in most cases, the required keywords such as NAXIS, TFIELD, TTYPEn, etc, which define the structure of the HDU must be written to the header before any data can be written to the image or table. \begin{description} \item[1 ] Put the primary header or IMAGE extension keywords into the CHU. There are 2 available routines: The simpler FTPHPS routine is equivalent to calling ftphpr with the default values of SIMPLE = true, pcount = 0, gcount = 1, and EXTEND = true. PCOUNT, GCOUNT and EXTEND keywords are not required in the primary header and are only written if pcount is not equal to zero, gcount is not equal to zero or one, and if extend is TRUE, respectively. When writing to an IMAGE extension, the SIMPLE and EXTEND parameters are ignored. \end{description} \begin{verbatim} FTPHPS(unit,bitpix,naxis,naxes, > status) FTPHPR(unit,simple,bitpix,naxis,naxes,pcount,gcount,extend, > status) \end{verbatim} \begin{description} \item[2 ] Get primary header or IMAGE extension keywords from the CHU. When reading from an IMAGE extension the SIMPLE and EXTEND parameters are ignored. \end{description} \begin{verbatim} FTGHPR(unit,maxdim, > simple,bitpix,naxis,naxes,pcount,gcount,extend, status) \end{verbatim} \begin{description} \item[3 ] Put the ASCII table header keywords into the CHU. The optional TUNITn and EXTNAME keywords are written only if the input string values are not blank. \end{description} \begin{verbatim} FTPHTB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > status) \end{verbatim} \begin{description} \item[4 ] Get the ASCII table header keywords from the CHU \end{description} \begin{verbatim} FTGHTB(unit,maxdim, > rowlen,nrows,tfields,ttype,tbcol,tform,tunit, extname,status) \end{verbatim} \begin{description} \item[5 ]Put the binary table header keywords into the CHU. The optional TUNITn and EXTNAME keywords are written only if the input string values are not blank. The pcount parameter, which specifies the size of the variable length array heap, should initially = 0; FITSIO will automatically update the PCOUNT keyword value if any variable length array data is written to the heap. The TFORM keyword value for variable length vector columns should have the form 'Pt(len)' or '1Pt(len)' where `t' is the data type code letter (A,I,J,E,D, etc.) and `len' is an integer specifying the maximum length of the vectors in that column (len must be greater than or equal to the longest vector in the column). If `len' is not specified when the table is created (e.g., the input TFORMn value is just '1Pt') then FITSIO will scan the column when the table is first closed and will append the maximum length to the TFORM keyword value. Note that if the table is subsequently modified to increase the maximum length of the vectors then the modifying program is responsible for also updating the TFORM keyword value. \end{description} \begin{verbatim} FTPHBN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat, > status) \end{verbatim} \begin{description} \item[6 ]Get the binary table header keywords from the CHU \end{description} \begin{verbatim} FTGHBN(unit,maxdim, > nrows,tfields,ttype,tform,tunit,extname,varidat, status) \end{verbatim} \subsection{Write Keyword Subroutines \label{FTPREC}} \begin{description} \item[1 ]Put (append) an 80-character record into the CHU. \end{description} \begin{verbatim} FTPREC(unit,card, > status) \end{verbatim} \begin{description} \item[2 ] Put (append) a COMMENT keyword into the CHU. Multiple COMMENT keywords will be written if the input comment string is longer than 72 characters. \end{description} \begin{verbatim} FTPCOM(unit,comment, > status) \end{verbatim} \begin{description} \item[3 ]Put (append) a HISTORY keyword into the CHU. Multiple HISTORY keywords will be written if the input history string is longer than 72 characters. \end{description} \begin{verbatim} FTPHIS(unit,history, > status) \end{verbatim} \begin{description} \item[4 ] Put (append) the DATE keyword into the CHU. The keyword value will contain the current system date as a character string in 'dd/mm/yy' format. If a DATE keyword already exists in the header, then this subroutine will simply update the keyword value in-place with the current date. \end{description} \begin{verbatim} FTPDAT(unit, > status) \end{verbatim} \begin{description} \item[5 ] Put (append) a new keyword of the appropriate datatype into the CHU. Note that FTPKYS will only write string values up to 68 characters in length; longer strings will be truncated. The FTPKLS routine can be used to write longer strings, using a non-standard FITS convention. The E and D versions of this routine have the added feature that if the 'decimals' parameter is negative, then the 'G' display format rather then the 'E' format will be used when constructing the keyword value, taking the absolute value of 'decimals' for the precision. This will suppress trailing zeros, and will use a fixed format rather than an exponential format, depending on the magnitude of the value. \end{description} \begin{verbatim} FTPKY[JKLS](unit,keyword,keyval,comment, > status) FTPKY[EDFG](unit,keyword,keyval,decimals,comment, > status) \end{verbatim} \begin{description} \item[6 ] Put (append) a string valued keyword into the CHU which may be longer than 68 characters in length. This uses the Long String Keyword convention that is described in the "Usage Guidelines and Suggestions" section of this document. Since this uses a non-standard FITS convention to encode the long keyword string, programs which use this routine should also call the FTPLSW routine to add some COMMENT keywords to warn users of the FITS file that this convention is being used. FTPLSW also writes a keyword called LONGSTRN to record the version of the longstring convention that has been used, in case a new convention is adopted at some point in the future. If the LONGSTRN keyword is already present in the header, then FTPLSW will simply return and will not write duplicate keywords. \end{description} \begin{verbatim} FTPKLS(unit,keyword,keyval,comment, > status) FTPLSW(unit, > status) \end{verbatim} \begin{description} \item[7 ] Put (append) a new keyword with an undefined, or null, value into the CHU. The value string of the keyword is left blank in this case. \end{description} \begin{verbatim} FTPKYU(unit,keyword,comment, > status) \end{verbatim} \begin{description} \item[8 ] Put (append) a numbered sequence of keywords into the CHU. One may append the same comment to every keyword (and eliminate the need to have an array of identical comment strings, one for each keyword) by including the ampersand character as the last non-blank character in the (first) COMMENTS string parameter. This same string will then be used for the comment field in all the keywords. (Note that the SPP version of these routines only supports a single comment string). \end{description} \begin{verbatim} FTPKN[JKLS](unit,keyroot,startno,no_keys,keyvals,comments, > status) FTPKN[EDFG](unit,keyroot,startno,no_keys,keyvals,decimals,comments, > status) \end{verbatim} \begin{description} \item[9 ]Copy an indexed keyword from one HDU to another, modifying the index number of the keyword name in the process. For example, this routine could read the TLMIN3 keyword from the input HDU (by giving keyroot = "TLMIN" and innum = 3) and write it to the output HDU with the keyword name TLMIN4 (by setting outnum = 4). If the input keyword does not exist, then this routine simply returns without indicating an error. \end{description} \begin{verbatim} FTCPKY(inunit, outunit, innum, outnum, keyroot, > status) \end{verbatim} \begin{description} \item[10] Put (append) a 'triple precision' keyword into the CHU in F28.16 format. The floating point keyword value is constructed by concatenating the input integer value with the input double precision fraction value (which must have a value between 0.0 and 1.0). The FTGKYT routine should be used to read this keyword value, because the other keyword reading subroutines will not preserve the full precision of the value. \end{description} \begin{verbatim} FTPKYT(unit,keyword,intval,dblval,comment, > status) \end{verbatim} \begin{description} \item[11] Write keywords to the CHDU that are defined in an ASCII template file. The format of the template file is described under the ftgthd routine below. \end{description} \begin{verbatim} FTPKTP(unit, filename, > status) \end{verbatim} \begin{description} \item[12] Append the physical units string to an existing keyword. This routine uses a local convention, shown in the following example, in which the keyword units are enclosed in square brackets in the beginning of the keyword comment field. \end{description} \begin{verbatim} VELOCITY= 12.3 / [km/s] orbital speed FTPUNT(unit,keyword,units, > status) \end{verbatim} \subsection{Insert Keyword Subroutines \label{FTIREC}} \begin{description} \item[1 ] Insert a new keyword record into the CHU at the specified position (i.e., immediately preceding the (keyno)th keyword in the header.) This 'insert record' subroutine is somewhat less efficient then the 'append record' subroutine (FTPREC) described above because the remaining keywords in the header have to be shifted down one slot. \end{description} \begin{verbatim} FTIREC(unit,key_no,card, > status) \end{verbatim} \begin{description} \item[2 ] Insert a new keyword into the CHU. The new keyword is inserted immediately following the last keyword that has been read from the header. The FTIKLS subroutine works the same as the FTIKYS subroutine, except it also supports long string values greater than 68 characters in length. These 'insert keyword' subroutines are somewhat less efficient then the 'append keyword' subroutines described above because the remaining keywords in the header have to be shifted down one slot. \end{description} \begin{verbatim} FTIKEY(unit, card, > status) FTIKY[JKLS](unit,keyword,keyval,comment, > status) FTIKLS(unit,keyword,keyval,comment, > status) FTIKY[EDFG](unit,keyword,keyval,decimals,comment, > status) \end{verbatim} \begin{description} \item[3 ] Insert a new keyword with an undefined, or null, value into the CHU. The value string of the keyword is left blank in this case. \end{description} \begin{verbatim} FTIKYU(unit,keyword,comment, > status) \end{verbatim} \subsection{Read Keyword Subroutines \label{FTGREC}} These routines return the value of the specified keyword(s). Wild card characters (*, ?, or \#) may be used when specifying the name of the keyword to be read: a '?' will match any single character at that position in the keyword name and a '*' will match any length (including zero) string of characters. The '\#' character will match any consecutive string of decimal digits (0 - 9). Note that when a wild card is used in the input keyword name, the routine will only search for a match from the current header position to the end of the header. It will not resume the search from the top of the header back to the original header position as is done when no wildcards are included in the keyword name. If the desired keyword string is 8-characters long (the maximum length of a keyword name) then a '*' may be appended as the ninth character of the input name to force the keyword search to stop at the end of the header (e.g., 'COMMENT *' will search for the next COMMENT keyword). The ffgrec routine may be used to set the starting position when doing wild card searches. \begin{description} \item[1 ]Get the nth 80-character header record from the CHU. The first keyword in the header is at key\_no = 1; if key\_no = 0 then this subroutine simple moves the internal pointer to the beginning of the header so that subsequent keyword operations will start at the top of the header; it also returns a blank card value in this case. \end{description} \begin{verbatim} FTGREC(unit,key_no, > card,status) \end{verbatim} \begin{description} \item[2 ] Get the name, value (as a string), and comment of the nth keyword in CHU. This routine also checks that the returned keyword name (KEYWORD) contains only legal ASCII characters. Call FTGREC and FTPSVC to bypass this error check. \end{description} \begin{verbatim} FTGKYN(unit,key_no, > keyword,value,comment,status) \end{verbatim} \begin{description} \item[3 ] Get the 80-character header record for the named keyword \end{description} \begin{verbatim} FTGCRD(unit,keyword, > card,status) \end{verbatim} \begin{description} \item[4 ] Get the next keyword whose name matches one of the strings in 'inclist' but does not match any of the strings in 'exclist'. The strings in inclist and exclist may contain wild card characters (*, ?, and \#) as described at the beginning of this section. This routine searches from the current header position to the end of the header, only, and does not continue the search from the top of the header back to the original position. The current header position may be reset with the ftgrec routine. Note that nexc may be set = 0 if there are no keywords to be excluded. This routine returns status = 202 if a matching keyword is not found. \end{description} \begin{verbatim} FTGNXK(unit,inclist,ninc,exclist,nexc, > card,status) \end{verbatim} \begin{description} \item[5 ] Get the literal keyword value as a character string. Regardless of the datatype of the keyword, this routine simply returns the string of characters in the value field of the keyword along with the comment field. \end{description} \begin{verbatim} FTGKEY(unit,keyword, > value,comment,status) \end{verbatim} \begin{description} \item[6 ] Get a keyword value (with the appropriate datatype) and comment from the CHU \end{description} \begin{verbatim} FTGKY[EDJKLS](unit,keyword, > keyval,comment,status) \end{verbatim} \begin{description} \item[7 ] Read a string-valued keyword and return the string length, the value string, and/or the comment field. The first routine, FTGKSL, simply returns the length of the character string value of the specified keyword. The second routine, FTGSKY, also returns up to maxchar characters of the keyword value string, starting with the firstchar character, and the keyword comment string. The length argument returns the total length of the keyword value string regardless of how much of the string is actually returned (which depends on the value of the firstchar and maxchar arguments). These routines support string keywords that use the CONTINUE convention to continue long string values over multiple FITS header records. Normally, string-valued keywords have a maximum length of 68 characters, however, CONTINUE'd string keywords may be arbitrarily long. \end{description} \begin{verbatim} FTGKSL(unit,keyword, > length,status) FTGSKY(unit,keyword,firstchar,maxchar,> keyval,length,comment,status) \end{verbatim} \begin{description} \item[8 ] Get a sequence of numbered keyword values. These routines do not support wild card characters in the root name. \end{description} \begin{verbatim} FTGKN[EDJKLS](unit,keyroot,startno,max_keys, > keyvals,nfound,status) \end{verbatim} \begin{description} \item[9 ] Get the value of a floating point keyword, returning the integer and fractional parts of the value in separate subroutine arguments. This subroutine may be used to read any keyword but is especially useful for reading the 'triple precision' keywords written by FTPKYT. \end{description} \begin{verbatim} FTGKYT(unit,keyword, > intval,dblval,comment,status) \end{verbatim} \begin{description} \item[10] Get the physical units string in an existing keyword. This routine uses a local convention, shown in the following example, in which the keyword units are enclosed in square brackets in the beginning of the keyword comment field. A blank string is returned if no units are defined for the keyword. \end{description} \begin{verbatim} VELOCITY= 12.3 / [km/s] orbital speed FTGUNT(unit,keyword, > units,status) \end{verbatim} \subsection{Modify Keyword Subroutines \label{FTMREC}} Wild card characters, as described in the Read Keyword section, above, may be used when specifying the name of the keyword to be modified. \begin{description} \item[1 ] Modify (overwrite) the nth 80-character header record in the CHU \end{description} \begin{verbatim} FTMREC(unit,key_no,card, > status) \end{verbatim} \begin{description} \item[2 ] Modify (overwrite) the 80-character header record for the named keyword in the CHU. This can be used to overwrite the name of the keyword as well as its value and comment fields. \end{description} \begin{verbatim} FTMCRD(unit,keyword,card, > status) \end{verbatim} \begin{description} \item[3 ] Modify (overwrite) the name of an existing keyword in the CHU preserving the current value and comment fields. \end{description} \begin{verbatim} FTMNAM(unit,oldkey,keyword, > status) \end{verbatim} \begin{description} \item[4 ] Modify (overwrite) the comment field of an existing keyword in the CHU \end{description} \begin{verbatim} FTMCOM(unit,keyword,comment, > status) \end{verbatim} \begin{description} \item[5 ] Modify the value and comment fields of an existing keyword in the CHU. The FTMKLS subroutine works the same as the FTMKYS subroutine, except it also supports long string values greater than 68 characters in length. Optionally, one may modify only the value field and leave the comment field unchanged by setting the input COMMENT parameter equal to the ampersand character (\&). The E and D versions of this routine have the added feature that if the 'decimals' parameter is negative, then the 'G' display format rather then the 'E' format will be used when constructing the keyword value, taking the absolute value of 'decimals' for the precision. This will suppress trailing zeros, and will use a fixed format rather than an exponential format, depending on the magnitude of the value. \end{description} \begin{verbatim} FTMKY[JKLS](unit,keyword,keyval,comment, > status) FTMKLS(unit,keyword,keyval,comment, > status) FTMKY[EDFG](unit,keyword,keyval,decimals,comment, > status) \end{verbatim} \begin{description} \item[6 ] Modify the value of an existing keyword to be undefined, or null. The value string of the keyword is set to blank. Optionally, one may leave the comment field unchanged by setting the input COMMENT parameter equal to the ampersand character (\&). \end{description} \begin{verbatim} FTMKYU(unit,keyword,comment, > status) \end{verbatim} \subsection{Update Keyword Subroutines \label{FTUCRD}} \begin{description} \item[1 ] Update an 80-character record in the CHU. If the specified keyword already exists then that header record will be replaced with the input CARD string. If it does not exist then the new record will be added to the header. The FTUKLS subroutine works the same as the FTUKYS subroutine, except it also supports long string values greater than 68 characters in length. \end{description} \begin{verbatim} FTUCRD(unit,keyword,card, > status) \end{verbatim} \begin{description} \item[2 ] Update the value and comment fields of a keyword in the CHU. The specified keyword is modified if it already exists (by calling FTMKYx) otherwise a new keyword is created by calling FTPKYx. The E and D versions of this routine have the added feature that if the 'decimals' parameter is negative, then the 'G' display format rather then the 'E' format will be used when constructing the keyword value, taking the absolute value of 'decimals' for the precision. This will suppress trailing zeros, and will use a fixed format rather than an exponential format, depending on the magnitude of the value. \end{description} \begin{verbatim} FTUKY[JKLS](unit,keyword,keyval,comment, > status) FTUKLS(unit,keyword,keyval,comment, > status) FTUKY[EDFG](unit,keyword,keyval,decimals,comment, > status) \end{verbatim} \begin{description} \item[3 ] Update the value of an existing keyword to be undefined, or null, or insert a new undefined-value keyword if it doesn't already exist. The value string of the keyword is left blank in this case. \end{description} \begin{verbatim} FTUKYU(unit,keyword,comment, > status) \end{verbatim} \subsection{Delete Keyword Subroutines \label{FTDREC}} \begin{description} \item[1 ] Delete an existing keyword record. The space previously occupied by the keyword is reclaimed by moving all the following header records up one row in the header. The first routine deletes a keyword at a specified position in the header (the first keyword is at position 1), whereas the second routine deletes a specifically named keyword. Wild card characters, as described in the Read Keyword section, above, may be used when specifying the name of the keyword to be deleted (be careful!). \end{description} \begin{verbatim} FTDREC(unit,key_no, > status) FTDKEY(unit,keyword, > status) \end{verbatim} \section{Data Scaling and Undefined Pixel Parameters \label{FTPSCL}} These subroutines define or modify the internal parameters used by FITSIO to either scale the data or to represent undefined pixels. Generally FITSIO will scale the data according to the values of the BSCALE and BZERO (or TSCALn and TZEROn) keywords, however these subroutines may be used to override the keyword values. This may be useful when one wants to read or write the raw unscaled values in the FITS file. Similarly, FITSIO generally uses the value of the BLANK or TNULLn keyword to signify an undefined pixel, but these routines may be used to override this value. These subroutines do not create or modify the corresponding header keyword values. \begin{description} \item[1 ] Reset the scaling factors in the primary array or image extension; does not change the BSCALE and BZERO keyword values and only affects the automatic scaling performed when the data elements are written/read to/from the FITS file. When reading from a FITS file the returned data value = (the value given in the FITS array) * BSCALE + BZERO. The inverse formula is used when writing data values to the FITS file. (NOTE: BSCALE and BZERO must be declared as Double Precision variables). \end{description} \begin{verbatim} FTPSCL(unit,bscale,bzero, > status) \end{verbatim} \begin{description} \item[2 ] Reset the scaling parameters for a table column; does not change the TSCALn or TZEROn keyword values and only affects the automatic scaling performed when the data elements are written/read to/from the FITS file. When reading from a FITS file the returned data value = (the value given in the FITS array) * TSCAL + TZERO. The inverse formula is used when writing data values to the FITS file. (NOTE: TSCAL and TZERO must be declared as Double Precision variables). \end{description} \begin{verbatim} FTTSCL(unit,colnum,tscal,tzero, > status) \end{verbatim} \begin{description} \item[3 ] Define the integer value to be used to signify undefined pixels in the primary array or image extension. This is only used if BITPIX = 8, 16, 32. or 64 This does not create or change the value of the BLANK keyword in the header. FTPNULLL is identical to FTPNUL except that the blank value is a 64-bit integer instead of a 32-bit integer. \end{description} \begin{verbatim} FTPNUL(unit,blank, > status) FTPNULLL(unit,blankll, > status) \end{verbatim} \begin{description} \item[4 ] Define the string to be used to signify undefined pixels in a column in an ASCII table. This does not create or change the value of the TNULLn keyword. \end{description} \begin{verbatim} FTSNUL(unit,colnum,snull > status) \end{verbatim} \begin{description} \item[5 ] Define the value to be used to signify undefined pixels in an integer column in a binary table (where TFORMn = 'B', 'I', 'J', or 'K'). This does not create or change the value of the TNULLn keyword. FTTNULLL is identical to FTTNUL except that the tnull value is a 64-bit integer instead of a 32-bit integer. \end{description} \begin{verbatim} FTTNUL(unit,colnum,tnull > status) FTTNULLL(unit,colnum,tnullll > status) \end{verbatim} \section{FITS Primary Array or IMAGE Extension I/O Subroutines \label{FTPPR}} These subroutines put or get data values in the primary data array (i.e., the first HDU in the FITS file) or an IMAGE extension. The data array is represented as a single one-dimensional array of pixels regardless of the actual dimensionality of the array, and the FPIXEL parameter gives the position within this 1-D array of the first pixel to read or write. Automatic data type conversion is performed for numeric data (except for complex data types) if the data type of the primary array (defined by the BITPIX keyword) differs from the data type of the array in the calling subroutine. The data values are also scaled by the BSCALE and BZERO header values as they are being written or read from the FITS array. The ftpscl subroutine MUST be called to define the scaling parameters when writing data to the FITS array or to override the default scaling value given in the header when reading the FITS array. Two sets of subroutines are provided to read the data array which differ in the way undefined pixels are handled. The first set of routines (FTGPVx) simply return an array of data elements in which undefined pixels are set equal to a value specified by the user in the 'nullval' parameter. An additional feature of these subroutines is that if the user sets nullval = 0, then no checks for undefined pixels will be performed, thus increasing the speed of the program. The second set of routines (FTGPFx) returns the data element array and, in addition, a logical array which defines whether the corresponding data pixel is undefined. The latter set of subroutines may be more convenient to use in some circumstances, however, it requires an additional array of logical values which can be unwieldy when working with large data arrays. Also for programmer convenience, sets of subroutines to directly read or write 2 and 3 dimensional arrays have been provided, as well as a set of subroutines to read or write any contiguous rectangular subset of pixels within the n-dimensional array. \begin{description} \item[1 ] Get the data type of the image (= BITPIX value). Possible returned values are: 8, 16, 32, 64, -32, or -64 corresponding to unsigned byte, signed 2-byte integer, signed 4-byte integer, signed 8-byte integer, real, and double. The second subroutine is similar to FTGIDT, except that if the image pixel values are scaled, with non-default values for the BZERO and BSCALE keywords, then this routine will return the 'equivalent' data type that is needed to store the scaled values. For example, if BITPIX = 16 and BSCALE = 0.1 then the equivalent data type is floating point, and -32 will be returned. There are 2 special cases: if the image contains unsigned 2-byte integer values, with BITPIX = 16, BSCALE = 1, and BZERO = 32768, then this routine will return a non-standard value of 20 for the bitpix value. Similarly if the image contains unsigned 4-byte integers, then bitpix will be returned with a value of 40. \end{description} \begin{verbatim} FTGIDT(unit, > bitpix,status) FTGIET(unit, > bitpix,status) \end{verbatim} \begin{description} \item[2 ] Get the dimension (number of axes = NAXIS) of the image \end{description} \begin{verbatim} FTGIDM(unit, > naxis,status) \end{verbatim} \begin{description} \item[3 ] Get the size of all the dimensions of the image. The FTGISZLL routine returns an array of 64-bit integers instead of 32-bit integers. \end{description} \begin{verbatim} FTGISZ(unit, maxdim, > naxes,status) FTGISZLL(unit, maxdim, > naxesll,status) \end{verbatim} \begin{description} \item[4 ] Get the parameters that define the type and size of the image. This routine simply combines calls to the above 3 routines. The FTGIPRLL routine returns an array of 64-bit integers instead of 32-bit integers. \end{description} \begin{verbatim} FTGIPR(unit, maxdim, > bitpix, naxis, naxes, int *status) FTGIPRLL(unit, maxdim, > bitpix, naxis, naxesll, int *status) \end{verbatim} \begin{description} \item[5 ]Put elements into the data array \end{description} \begin{verbatim} FTPPR[BIJKED](unit,group,fpixel,nelements,values, > status) \end{verbatim} \begin{description} \item[6 ]Put elements into the data array, substituting the appropriate FITS null value for all elements which are equal to the value of NULLVAL. For integer FITS arrays, the null value defined by the previous call to FTPNUL will be substituted; for floating point FITS arrays (BITPIX = -32 or -64) then the special IEEE NaN (Not-a-Number) value will be substituted. \end{description} \begin{verbatim} FTPPN[BIJKED](unit,group,fpixel,nelements,values,nullval > status) \end{verbatim} \begin{description} \item[7 ]Set data array elements as undefined \end{description} \begin{verbatim} FTPPRU(unit,group,fpixel,nelements, > status) \end{verbatim} \begin{description} \item[8 ] Get elements from the data array. Undefined array elements will be returned with a value = nullval, unless nullval = 0 in which case no checks for undefined pixels will be performed. \end{description} \begin{verbatim} FTGPV[BIJKED](unit,group,fpixel,nelements,nullval, > values,anyf,status) \end{verbatim} \begin{description} \item[9 ] Get elements and nullflags from data array. Any undefined array elements will have the corresponding flagvals element set equal to .TRUE. \end{description} \begin{verbatim} FTGPF[BIJKED](unit,group,fpixel,nelements, > values,flagvals,anyf,status) \end{verbatim} \begin{description} \item[10] Put values into group parameters \end{description} \begin{verbatim} FTPGP[BIJKED](unit,group,fparm,nparm,values, > status) \end{verbatim} \begin{description} \item[11] Get values from group parameters \end{description} \begin{verbatim} FTGGP[BIJKED](unit,group,fparm,nparm, > values,status) \end{verbatim} The following 4 subroutines transfer FITS images with 2 or 3 dimensions to or from a data array which has been declared in the calling program. The dimensionality of the FITS image is passed by the naxis1, naxis2, and naxis3 parameters and the declared dimensions of the program array are passed in the dim1 and dim2 parameters. Note that the program array does not have to have the same dimensions as the FITS array, but must be at least as big. For example if a FITS image with NAXIS1 = NAXIS2 = 400 is read into a program array which is dimensioned as 512 x 512 pixels, then the image will just fill the lower left corner of the array with pixels in the range 1 - 400 in the X an Y directions. This has the effect of taking a contiguous set of pixel value in the FITS array and writing them to a non-contiguous array in program memory (i.e., there are now some blank pixels around the edge of the image in the program array). \begin{description} \item[11] Put 2-D image into the data array \end{description} \begin{verbatim} FTP2D[BIJKED](unit,group,dim1,naxis1,naxis2,image, > status) \end{verbatim} \begin{description} \item[12] Put 3-D cube into the data array \end{description} \begin{verbatim} FTP3D[BIJKED](unit,group,dim1,dim2,naxis1,naxis2,naxis3,cube, > status) \end{verbatim} \begin{description} \item[13] Get 2-D image from the data array. Undefined pixels in the array will be set equal to the value of 'nullval', unless nullval=0 in which case no testing for undefined pixels will be performed. \end{description} \begin{verbatim} FTG2D[BIJKED](unit,group,nullval,dim1,naxis1,naxis2, > image,anyf,status) \end{verbatim} \begin{description} \item[14] Get 3-D cube from the data array. Undefined pixels in the array will be set equal to the value of 'nullval', unless nullval=0 in which case no testing for undefined pixels will be performed. \end{description} \begin{verbatim} FTG3D[BIJKED](unit,group,nullval,dim1,dim2,naxis1,naxis2,naxis3, > cube,anyf,status) \end{verbatim} The following subroutines transfer a rectangular subset of the pixels in a FITS N-dimensional image to or from an array which has been declared in the calling program. The fpixels and lpixels parameters are integer arrays which specify the starting and ending pixels in each dimension of the FITS image that are to be read or written. (Note that these are the starting and ending pixels in the FITS image, not in the declared array). The array parameter is treated simply as a large one-dimensional array of the appropriate datatype containing the pixel values; The pixel values in the FITS array are read/written from/to this program array in strict sequence without any gaps; it is up to the calling routine to correctly interpret the dimensionality of this array. The two families of FITS reading routines (FTGSVx and FTGSFx subroutines) also have an 'incs' parameter which defines the data sampling interval in each dimension of the FITS array. For example, if incs(1)=2 and incs(2)=3 when reading a 2-dimensional FITS image, then only every other pixel in the first dimension and every 3rd pixel in the second dimension will be returned in the 'array' parameter. [Note: the FTGSSx family of routines which were present in previous versions of FITSIO have been superseded by the more general FTGSVx family of routines.] \begin{description} \item[15] Put an arbitrary data subsection into the data array. \end{description} \begin{verbatim} FTPSS[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,array, > status) \end{verbatim} \begin{description} \item[16] Get an arbitrary data subsection from the data array. Undefined pixels in the array will be set equal to the value of 'nullval', unless nullval=0 in which case no testing for undefined pixels will be performed. \end{description} \begin{verbatim} FTGSV[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,incs,nullval, > array,anyf,status) \end{verbatim} \begin{description} \item[17] Get an arbitrary data subsection from the data array. Any Undefined pixels in the array will have the corresponding 'flagvals' element set equal to .TRUE. \end{description} \begin{verbatim} FTGSF[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,incs, > array,flagvals,anyf,status) \end{verbatim} \section{FITS ASCII and Binary Table Data I/O Subroutines} \subsection{Column Information Subroutines \label{FTGCNO}} \begin{description} \item[1 ] Get the number of rows or columns in the current FITS table. The number of rows is given by the NAXIS2 keyword and the number of columns is given by the TFIELDS keyword in the header of the table. The FTGNRWLL routine is identical to FTGNRW except that the number of rows is returned as a 64-bit integer rather than a 32-bit integer. \end{description} \begin{verbatim} FTGNRW(unit, > nrows, status) FTGNRWLL(unit, > nrowsll, status) FTGNCL(unit, > ncols, status) \end{verbatim} \begin{description} \item[2 ] Get the table column number (and name) of the column whose name matches an input template name. The table column names are defined by the TTYPEn keywords in the FITS header. If a column does not have a TTYPEn keyword, then these routines assume that the name consists of all blank characters. These 2 subroutines perform the same function except that FTGCNO only returns the number of the matching column whereas FTGCNN also returns the name of the column. If CASESEN = .true. then the column name match will be case-sensitive. The input column name template (COLTEMPLATE) is (1) either the exact name of the column to be searched for, or (2) it may contain wild cards characters (*, ?, or \#), or (3) it may contain the number of the desired column (where the number is expressed as ASCII digits). The first 2 wild cards behave similarly to UNIX filename matching: the '*' character matches any sequence of characters (including zero characters) and the '?' character matches any single character. The \# wildcard will match any consecutive string of decimal digits (0-9). As an example, the template strings 'AB?DE', 'AB*E', and 'AB*CDE' will all match the string 'ABCDE'. If more than one column name in the table matches the template string, then the first match is returned and the status value will be set to 237 as a warning that a unique match was not found. To find the other cases that match the template, simply call the subroutine again leaving the input status value equal to 237 and the next matching name will then be returned. Repeat this process until a status = 219 (column name not found) is returned. If these subroutines fail to match the template to any of the columns in the table, they lastly check if the template can be interpreted as a simple positive integer (e.g., '7', or '512') and if so, they return that column number. If no matches are found then a status = 219 error is returned. Note that the FITS Standard recommends that only letters, digits, and the underscore character be used in column names (with no embedded spaces in the name). Trailing blank characters are not significant. \end{description} \begin{verbatim} FTGCNO(unit,casesen,coltemplate, > colnum,status) FTGCNN(unit,casesen,coltemplate, > colname,colnum,status) \end{verbatim} \begin{description} \item[3 ] Get the datatype of a column in an ASCII or binary table. This routine returns an integer code value corresponding to the datatype of the column. (See the FTBNFM and FTASFM subroutines in the Utilities section of this document for a list of the code values). The vector repeat count (which is alway 1 for ASCII table columns) is also returned. If the specified column has an ASCII character datatype (code = 16) then the width of a unit string in the column is also returned. Note that this routine supports the local convention for specifying arrays of strings within a binary table character column, using the syntax TFORM = 'rAw' where 'r' is the total number of characters (= the width of the column) and 'w' is the width of a unit string within the column. Thus if the column has TFORM = '60A12' then this routine will return datacode = 16, repeat = 60, and width = 12. (The TDIMn keyword may also be used to specify the unit string length; The pair of keywords TFORMn = '60A' and TDIMn = '(12,5)' would have the same effect as TFORMn = '60A12'). The second routine, FTEQTY is similar except that in the case of scaled integer columns it returns the 'equivalent' data type that is needed to store the scaled values, and not necessarily the physical data type of the unscaled values as stored in the FITS table. For example if a '1I' column in a binary table has TSCALn = 1 and TZEROn = 32768, then this column effectively contains unsigned short integer values, and thus the returned value of typecode will be the code for an unsigned short integer, not a signed short integer. Similarly, if a column has TTYPEn = '1I' and TSCALn = 0.12, then the returned typecode will be the code for a 'real' column. \end{description} \begin{verbatim} FTGTCL(unit,colnum, > datacode,repeat,width,status) FTEQTY(unit,colnum, > datacode,repeat,width,status) \end{verbatim} \begin{description} \item[4 ] Return the display width of a column. This is the length of the string that will be returned when reading the column as a formatted string. The display width is determined by the TDISPn keyword, if present, otherwise by the data type of the column. \end{description} \begin{verbatim} FTGCDW(unit, colnum, > dispwidth, status) \end{verbatim} \begin{description} \item[5 ] Get information about an existing ASCII table column. (NOTE: TSCAL and TZERO must be declared as Double Precision variables). All the returned parameters are scalar quantities. \end{description} \begin{verbatim} FTGACL(unit,colnum, > ttype,tbcol,tunit,tform,tscal,tzero,snull,tdisp,status) \end{verbatim} \begin{description} \item[6 ] Get information about an existing binary table column. (NOTE: TSCAL and TZERO must be declared as Double Precision variables). DATATYPE is a character string which returns the datatype of the column as defined by the TFORMn keyword (e.g., 'I', 'J','E', 'D', etc.). In the case of an ASCII character column, DATATYPE will have a value of the form 'An' where 'n' is an integer expressing the width of the field in characters. For example, if TFORM = '160A8' then FTGBCL will return DATATYPE='A8' and REPEAT=20. All the returned parameters are scalar quantities. \end{description} \begin{verbatim} FTGBCL(unit,colnum, > ttype,tunit,datatype,repeat,tscal,tzero,tnull,tdisp,status) \end{verbatim} \begin{description} \item[7 ] Put (append) a TDIMn keyword whose value has the form '(l,m,n...)' where l, m, n... are the dimensions of a multidimensional array column in a binary table. \end{description} \begin{verbatim} FTPTDM(unit,colnum,naxis,naxes, > status) \end{verbatim} \begin{description} \item[8 ] Return the number of and size of the dimensions of a table column. Normally this information is given by the TDIMn keyword, but if this keyword is not present then this routine returns NAXIS = 1 and NAXES(1) equal to the repeat count in the TFORM keyword. \end{description} \begin{verbatim} FTGTDM(unit,colnum,maxdim, > naxis,naxes,status) \end{verbatim} \begin{description} \item[9 ] Decode the input TDIMn keyword string (e.g. '(100,200)') and return the number of and size of the dimensions of a binary table column. If the input tdimstr character string is null, then this routine returns naxis = 1 and naxes[0] equal to the repeat count in the TFORM keyword. This routine is called by FTGTDM. \end{description} \begin{verbatim} FTDTDM(unit,tdimstr,colnum,maxdim, > naxis,naxes, status) \end{verbatim} \begin{description} \item[10] Return the optimal number of rows to read or write at one time for maximum I/O efficiency. Refer to the ``Optimizing Code'' section in Chapter 5 for more discussion on how to use this routine. \end{description} \begin{verbatim} FTGRSZ(unit, > nrows,status) \end{verbatim} \subsection{Low-Level Table Access Subroutines \label{FTGTBS}} The following subroutines provide low-level access to the data in ASCII or binary tables and are mainly useful as an efficient way to copy all or part of a table from one location to another. These routines simply read or write the specified number of consecutive bytes in an ASCII or binary table, without regard for column boundaries or the row length in the table. The first two subroutines read or write consecutive bytes in a table to or from a character string variable, while the last two subroutines read or write consecutive bytes to or from a variable declared as a numeric data type (e.g., INTEGER, INTEGER*2, REAL, DOUBLE PRECISION). These routines do not perform any machine dependent data conversion or byte swapping, except that conversion to/from ASCII format is performed by the FTGTBS and FTPTBS routines on machines which do not use ASCII character codes in the internal data representations (e.g., on IBM mainframe computers). \begin{description} \item[1 ] Read a consecutive string of characters from an ASCII table into a character variable (spanning columns and multiple rows if necessary) This routine should not be used with binary tables because of complications related to passing string variables between C and Fortran. \end{description} \begin{verbatim} FTGTBS(unit,frow,startchar,nchars, > string,status) \end{verbatim} \begin{description} \item[2 ] Write a consecutive string of characters to an ASCII table from a character variable (spanning columns and multiple rows if necessary) This routine should not be used with binary tables because of complications related to passing string variables between C and Fortran. \end{description} \begin{verbatim} FTPTBS(unit,frow,startchar,nchars,string, > status) \end{verbatim} \begin{description} \item[3 ] Read a consecutive array of bytes from an ASCII or binary table into a numeric variable (spanning columns and multiple rows if necessary). The array parameter may be declared as any numerical datatype as long as the array is at least 'nchars' bytes long, e.g., if nchars = 17, then declare the array as INTEGER*4 ARRAY(5). \end{description} \begin{verbatim} FTGTBB(unit,frow,startchar,nchars, > array,status) \end{verbatim} \begin{description} \item[4 ] Write a consecutive array of bytes to an ASCII or binary table from a numeric variable (spanning columns and multiple rows if necessary) The array parameter may be declared as any numerical datatype as long as the array is at least 'nchars' bytes long, e.g., if nchars = 17, then declare the array as INTEGER*4 ARRAY(5). \end{description} \begin{verbatim} FTPTBB(unit,frow,startchar,nchars,array, > status) \end{verbatim} \subsection{Edit Rows or Columns \label{FTIROW}} \begin{description} \item[1 ] Insert blank rows into an existing ASCII or binary table (in the CDU). All the rows FOLLOWING row FROW are shifted down by NROWS rows. If FROW or FROWLL equals 0 then the blank rows are inserted at the beginning of the table. These routines modify the NAXIS2 keyword to reflect the new number of rows in the table. Note that it is *not* necessary to insert rows in a table before writing data to those rows (indeed, it would be inefficient to do so). Instead, one may simply write data to any row of the table, whether that row of data already exists or not. \end{description} \begin{verbatim} FTIROW(unit,frow,nrows, > status) FTIROWLL(unit,frowll,nrowsll, > status) \end{verbatim} \begin{description} \item[2 ] Delete rows from an existing ASCII or binary table (in the CDU). The NROWS (or NROWSLL) is the number of rows are deleted, starting with row FROW (or FROWLL), and any remaining rows in the table are shifted up to fill in the space. These routines modify the NAXIS2 keyword to reflect the new number of rows in the table. \end{description} \begin{verbatim} FTDROW(unit,frow,nrows, > status) FTDROWLL(unit,frowll,nrowsll, > status) \end{verbatim} \begin{description} \item[3 ] Delete a list of rows from an ASCII or binary table (in the CDU). In the first routine, 'rowrange' is a character string listing the rows or row ranges to delete (e.g., '2-4, 5, 8-9'). In the second routine, 'rowlist' is an integer array of row numbers to be deleted from the table. nrows is the number of row numbers in the list. The first row in the table is 1 not 0. The list of row numbers must be sorted in ascending order. \end{description} \begin{verbatim} FTDRRG(unit,rowrange, > status) FTDRWS(unit,rowlist,nrows, > status) \end{verbatim} \begin{description} \item[4 ] Insert a blank column (or columns) into an existing ASCII or binary table (in the CDU). COLNUM specifies the column number that the (first) new column should occupy in the table. NCOLS specifies how many columns are to be inserted. Any existing columns from this position and higher are moved over to allow room for the new column(s). The index number on all the following keywords will be incremented if necessary to reflect the new position of the column(s) in the table: TBCOLn, TFORMn, TTYPEn, TUNITn, TNULLn, TSCALn, TZEROn, TDISPn, TDIMn, TLMINn, TLMAXn, TDMINn, TDMAXn, TCTYPn, TCRPXn, TCRVLn, TCDLTn, TCROTn, and TCUNIn. \end{description} \begin{verbatim} FTICOL(unit,colnum,ttype,tform, > status) FTICLS(unit,colnum,ncols,ttype,tform, > status) \end{verbatim} \begin{description} \item[5 ] Modify the vector length of a binary table column (e.g., change a column from TFORMn = '1E' to '20E'). The vector length may be increased or decreased from the current value. \end{description} \begin{verbatim} FTMVEC(unit,colnum,newveclen, > status) \end{verbatim} \begin{description} \item[6 ] Delete a column from an existing ASCII or binary table (in the CDU). The index number of all the keywords listed above (for FTICOL) will be decremented if necessary to reflect the new position of the column(s) in the table. Those index keywords that refer to the deleted column will also be deleted. Note that the physical size of the FITS file will not be reduced by this operation, and the empty FITS blocks if any at the end of the file will be padded with zeros. \end{description} \begin{verbatim} FTDCOL(unit,colnum, > status) \end{verbatim} \begin{description} \item[7 ] Copy a column from one HDU to another (or to the same HDU). If createcol = TRUE, then a new column will be inserted in the output table, at position `outcolumn', otherwise the existing output column will be overwritten (in which case it must have a compatible datatype). Note that the first column in a table is at colnum = 1. \end{description} \begin{verbatim} FTCPCL(inunit,outunit,incolnum,outcolnum,createcol, > status); \end{verbatim} \subsection{Read and Write Column Data Routines \label{FTPCLS}} These subroutines put or get data values in the current ASCII or Binary table extension. Automatic data type conversion is performed for numerical data types (B,I,J,E,D) if the data type of the column (defined by the TFORM keyword) differs from the data type of the calling subroutine. The data values are also scaled by the TSCALn and TZEROn header values as they are being written to or read from the FITS array. The fttscl subroutine MUST be used to define the scaling parameters when writing data to the table or to override the default scaling values given in the header when reading from the table. Note that it is *not* necessary to insert rows in a table before writing data to those rows (indeed, it would be inefficient to do so). Instead, one may simply write data to any row of the table, whether that row of data already exists or not. In the case of binary tables with vector elements, the 'felem' parameter defines the starting pixel within the element vector. This parameter is ignored with ASCII tables. Similarly, in the case of binary tables the 'nelements' parameter specifies the total number of vector values read or written (continuing on subsequent rows if required) and not the number of table elements. Two sets of subroutines are provided to get the column data which differ in the way undefined pixels are handled. The first set of routines (FTGCV) simply return an array of data elements in which undefined pixels are set equal to a value specified by the user in the 'nullval' parameter. An additional feature of these subroutines is that if the user sets nullval = 0, then no checks for undefined pixels will be performed, thus increasing the speed of the program. The second set of routines (FTGCF) returns the data element array and in addition a logical array of flags which defines whether the corresponding data pixel is undefined. Any column, regardless of it's intrinsic datatype, may be read as a string. It should be noted however that reading a numeric column as a string is 10 - 100 times slower than reading the same column as a number due to the large overhead in constructing the formatted strings. The display format of the returned strings will be determined by the TDISPn keyword, if it exists, otherwise by the datatype of the column. The length of the returned strings can be determined with the ftgcdw routine. The following TDISPn display formats are currently supported: \begin{verbatim} Iw.m Integer Ow.m Octal integer Zw.m Hexadecimal integer Fw.d Fixed floating point Ew.d Exponential floating point Dw.d Exponential floating point Gw.d General; uses Fw.d if significance not lost, else Ew.d \end{verbatim} where w is the width in characters of the displayed values, m is the minimum number of digits displayed, and d is the number of digits to the right of the decimal. The .m field is optional. \begin{description} \item[1 ] Put elements into an ASCII or binary table column (in the CDU). (The SPP FSPCLS routine has an additional integer argument after the VALUES character string which specifies the size of the 1st dimension of this 2-D CHAR array). The alternate version of these routines, whose names end in 'LL' after the datatype character, support large tables with more then 2*31 rows. When calling these routines, the frow and felem parameters *must* be 64-bit integer*8 variables, instead of normal 4-byte integers. \end{description} \begin{verbatim} FTPCL[SLBIJKEDCM](unit,colnum,frow,felem,nelements,values, > status) FTPCL[LBIJKEDCM]LL(unit,colnum,frow,felem,nelements,values, > status) \end{verbatim} \begin{description} \item[2 ] Put elements into an ASCII or binary table column (in the CDU) substituting the appropriate FITS null value for any elements that are equal to NULLVAL. For ASCII TABLE extensions, the null value defined by the previous call to FTSNUL will be substituted; For integer FITS columns, in a binary table the null value defined by the previous call to FTTNUL will be substituted; For floating point FITS columns a special IEEE NaN (Not-a-Number) value will be substituted. The alternate version of these routines, whose names end in 'LL' after the datatype character, support large tables with more then 2*31 rows. When calling these routines, the frow and felem parameters *must* be 64-bit integer*8 variables, instead of normal 4-byte integers. \end{description} \begin{verbatim} FTPCN[SBIJKED](unit,colnum,frow,felem,nelements,values,nullval > status) FTPCN[SBIJKED]LL(unit,colnum,(I*8) frow,(I*8) felem,nelements,values, nullval > status) \end{verbatim} \begin{description} \item[3 ] Put bit values into a binary byte ('B') or bit ('X') table column (in the CDU). LRAY is an array of logical values corresponding to the sequence of bits to be written. If LRAY is true then the corresponding bit is set to 1, otherwise the bit is set to 0. Note that in the case of 'X' columns, FITSIO will write to all 8 bits of each byte whether they are formally valid or not. Thus if the column is defined as '4X', and one calls FTPCLX with fbit=1 and nbit=8, then all 8 bits will be written into the first byte (as opposed to writing the first 4 bits into the first row and then the next 4 bits into the next row), even though the last 4 bits of each byte are formally not defined. \end{description} \begin{verbatim} FTPCLX(unit,colnum,frow,fbit,nbit,lray, > status) \end{verbatim} \begin{description} \item[4 ] Set table elements in a column as undefined \end{description} \begin{verbatim} FTPCLU(unit,colnum,frow,felem,nelements, > status) \end{verbatim} \begin{description} \item[5 ] Get elements from an ASCII or binary table column (in the CDU). These routines return the values of the table column array elements. Undefined array elements will be returned with a value = nullval, unless nullval = 0 (or = ' ' for ftgcvs) in which case no checking for undefined values will be performed. The ANYF parameter is set to true if any of the returned elements are undefined. (Note: the ftgcl routine simple gets an array of logical data values without any checks for undefined values; use the ftgcfl routine to check for undefined logical elements). (The SPP FSGCVS routine has an additional integer argument after the VALUES character string which specifies the size of the 1st dimension of this 2-D CHAR array). The alternate version of these routines, whose names end in 'LL' after the datatype character, support large tables with more then 2*31 rows. When calling these routines, the frow and felem parameters *must* be 64-bit integer*8 variables, instead of normal 4-byte integers. \end{description} \begin{verbatim} FTGCL(unit,colnum,frow,felem,nelements, > values,status) FTGCV[SBIJKEDCM](unit,colnum,frow,felem,nelements,nullval, > values,anyf,status) FTGCV[BIJKEDCM]LL(unit,colnum,(I*8) frow, (I*8) felem, nelements, nullval, > values,anyf,status) \end{verbatim} \begin{description} \item[6 ] Get elements and null flags from an ASCII or binary table column (in the CHDU). These routines return the values of the table column array elements. Any undefined array elements will have the corresponding flagvals element set equal to .TRUE. The ANYF parameter is set to true if any of the returned elements are undefined. (The SPP FSGCFS routine has an additional integer argument after the VALUES character string which specifies the size of the 1st dimension of this 2-D CHAR array). The alternate version of these routines, whose names end in 'LL' after the datatype character, support large tables with more then 2*31 rows. When calling these routines, the frow and felem parameters *must* be 64-bit integer*8 variables, instead of normal 4-byte integers. \end{description} \begin{verbatim} FTGCF[SLBIJKEDCM](unit,colnum,frow,felem,nelements, > values,flagvals,anyf,status) FTGCF[BIJKED]LL(unit,colnum, (I*8) frow, (I*8) felem,nelements, > values,flagvals,anyf,status) \end{verbatim} \begin{description} \item[7 ] Get an arbitrary data subsection from an N-dimensional array in a binary table vector column. Undefined pixels in the array will be set equal to the value of 'nullval', unless nullval=0 in which case no testing for undefined pixels will be performed. The first and last rows in the table to be read are specified by fpixels(naxis+1) and lpixels(naxis+1), and hence are treated as the next higher dimension of the FITS N-dimensional array. The INCS parameter specifies the sampling interval in each dimension between the data elements that will be returned. \end{description} \begin{verbatim} FTGSV[BIJKED](unit,colnum,naxis,naxes,fpixels,lpixels,incs,nullval, > array,anyf,status) \end{verbatim} \begin{description} \item[8 ] Get an arbitrary data subsection from an N-dimensional array in a binary table vector column. Any Undefined pixels in the array will have the corresponding 'flagvals' element set equal to .TRUE. The first and last rows in the table to be read are specified by fpixels(naxis+1) and lpixels(naxis+1), and hence are treated as the next higher dimension of the FITS N-dimensional array. The INCS parameter specifies the sampling interval in each dimension between the data elements that will be returned. \end{description} \begin{verbatim} FTGSF[BIJKED](unit,colnum,naxis,naxes,fpixels,lpixels,incs, > array,flagvals,anyf,status) \end{verbatim} \begin{description} \item[9 ] Get bit values from a byte ('B') or bit (`X`) table column (in the CDU). LRAY is an array of logical values corresponding to the sequence of bits to be read. If LRAY is true then the corresponding bit was set to 1, otherwise the bit was set to 0. Note that in the case of 'X' columns, FITSIO will read all 8 bits of each byte whether they are formally valid or not. Thus if the column is defined as '4X', and one calls FTGCX with fbit=1 and nbit=8, then all 8 bits will be read from the first byte (as opposed to reading the first 4 bits from the first row and then the first 4 bits from the next row), even though the last 4 bits of each byte are formally not defined. \end{description} \begin{verbatim} FTGCX(unit,colnum,frow,fbit,nbit, > lray,status) \end{verbatim} \begin{description} \item[10] Read any consecutive set of bits from an 'X' or 'B' column and interpret them as an unsigned n-bit integer. NBIT must be less than or equal to 16 when calling FTGCXI, and less than or equal to 32 when calling FTGCXJ; there is no limit on the value of NBIT for FTGCXD, but the returned double precision value only has 48 bits of precision on most 32-bit word machines. The NBITS bits are interpreted as an unsigned integer unless NBITS = 16 (in FTGCXI) or 32 (in FTGCXJ) in which case the string of bits are interpreted as 16-bit or 32-bit 2's complement signed integers. If NROWS is greater than 1 then the same set of bits will be read from sequential rows in the table starting with row FROW. Note that the numbering convention used here for the FBIT parameter adopts 1 for the first element of the vector of bits; this is the Most Significant Bit of the integer value. \end{description} \begin{verbatim} FTGCX[IJD](unit,colnum,frow,nrows,fbit,nbit, > array,status) \end{verbatim} \begin{description} \item[11] Get the descriptor for a variable length column in a binary table. The descriptor consists of 2 integer parameters: the number of elements in the array and the starting offset relative to the start of the heap. The first routine returns a single descriptor whereas the second routine returns the descriptors for a range of rows in the table. \end{description} \begin{verbatim} FTGDES(unit,colnum,rownum, > nelements,offset,status) FTGDESLL(unit,colnum,rownum, > nelementsll,offsetll,status) FTGDESS(unit,colnum,firstrow,nrows > nelements,offset, status) FTGDESSLL(unit,colnum,firstrow,nrows > nelementsll,offsetll, status) \end{verbatim} \begin{description} \item[12] Write the descriptor for a variable length column in a binary table. These subroutines can be used in conjunction with FTGDES to enable 2 or more arrays to point to the same storage location to save storage space if the arrays are identical. \end{description} \begin{verbatim} FTPDES(unit,colnum,rownum,nelements,offset, > status) FTPDESLL(unit,colnum,rownum,nelementsll,offsetll, > status) \end{verbatim} \section{Row Selection and Calculator Routines \label{FTFROW}} These routines all parse and evaluate an input string containing a user defined arithmetic expression. The first 3 routines select rows in a FITS table, based on whether the expression evaluates to true (not equal to zero) or false (zero). The other routines evaluate the expression and calculate a value for each row of the table. The allowed expression syntax is described in the row filter section in the earlier `Extended File Name Syntax' chapter of this document. The expression may also be written to a text file, and the name of the file, prepended with a '@' character may be supplied for the 'expr' parameter (e.g. '@filename.txt'). The expression in the file can be arbitrarily complex and extend over multiple lines of the file. Lines that begin with 2 slash characters ('//') will be ignored and may be used to add comments to the file. \begin{description} \item[1 ] Evaluate a boolean expression over the indicated rows, returning an array of flags indicating which rows evaluated to TRUE/FALSE \end{description} \begin{verbatim} FTFROW(unit,expr,firstrow, nrows, > n_good_rows, row_status, status) \end{verbatim} \begin{description} \item[2 ] Find the first row which satisfies the input boolean expression \end{description} \begin{verbatim} FTFFRW(unit, expr, > rownum, status) \end{verbatim} \begin{description} \item[3 ]Evaluate an expression on all rows of a table. If the input and output files are not the same, copy the TRUE rows to the output file; if the output table is not empty, then this routine will append the new selected rows after the existing rows. If the files are the same, delete the FALSE rows (preserve the TRUE rows). \end{description} \begin{verbatim} FTSROW(inunit, outunit, expr, > status) \end{verbatim} \begin{description} \item[4 ] Calculate an expression for the indicated rows of a table, returning the results, cast as datatype (TSHORT, TDOUBLE, etc), in array. If nulval==NULL, UNDEFs will be zeroed out. For vector results, the number of elements returned may be less than nelements if nelements is not an even multiple of the result dimension. Call FTTEXP to obtain the dimensions of the results. \end{description} \begin{verbatim} FTCROW(unit,datatype,expr,firstrow,nelements,nulval, > array,anynul,status) \end{verbatim} \begin{description} \item[5 ]Evaluate an expression and write the result either to a column (if the expression is a function of other columns in the table) or to a keyword (if the expression evaluates to a constant and is not a function of other columns in the table). In the former case, the parName parameter is the name of the column (which may or may not already exist) into which to write the results, and parInfo contains an optional TFORM keyword value if a new column is being created. If a TFORM value is not specified then a default format will be used, depending on the expression. If the expression evaluates to a constant, then the result will be written to the keyword name given by the parName parameter, and the parInfo parameter may be used to supply an optional comment for the keyword. If the keyword does not already exist, then the name of the keyword must be preceded with a '\#' character, otherwise the result will be written to a column with that name. \end{description} \begin{verbatim} FTCALC(inunit, expr, outunit, parName, parInfo, > status) \end{verbatim} \begin{description} \item[6 ] This calculator routine is similar to the previous routine, except that the expression is only evaluated over the specified row ranges. nranges specifies the number of row ranges, and firstrow and lastrow give the starting and ending row number of each range. \end{description} \begin{verbatim} FTCALC_RNG(inunit, expr, outunit, parName, parInfo, nranges, firstrow, lastrow, > status) \end{verbatim} \begin{description} \item[7 ]Evaluate the given expression and return dimension and type information on the result. The returned dimensions correspond to a single row entry of the requested expression, and are equivalent to the result of fits\_read\_tdim(). Note that strings are considered to be one element regardless of string length. If maxdim == 0, then naxes is optional. \end{description} \begin{verbatim} FTTEXP(unit, expr, maxdim > datatype, nelem, naxis, naxes, status) \end{verbatim} \section{Celestial Coordinate System Subroutines \label{FTGICS}} The FITS community has adopted a set of keyword conventions that define the transformations needed to convert between pixel locations in an image and the corresponding celestial coordinates on the sky, or more generally, that define world coordinates that are to be associated with any pixel location in an n-dimensional FITS array. CFITSIO is distributed with a couple of self-contained World Coordinate System (WCS) routines, however, these routines DO NOT support all the latest WCS conventions, so it is STRONGLY RECOMMENDED that software developers use a more robust external WCS library. Several recommended libraries are: \begin{verbatim} WCSLIB - supported by Mark Calabretta WCSTools - supported by Doug Mink AST library - developed by the U.K. Starlink project \end{verbatim} More information about the WCS keyword conventions and links to all of these WCS libraries can be found on the FITS Support Office web site at http://fits.gsfc.nasa.gov under the WCS link. The functions provided in these external WCS libraries will need access to the WCS information contained in the FITS file headers. One convenient way to pass this information to the external library is to use FITSIO to copy the header keywords into one long character string, and then pass this string to an interface routine in the external library that will extract the necessary WCS information (e.g., see the astFitsChan and astPutCards routines in the Starlink AST library). The following FITSIO routines DO NOT support the more recent WCS conventions that have been approved as part of the FITS standard. Consequently, the following routines ARE NOW DEPRECATED. It is STRONGLY RECOMMENDED that software developers not use these routines, and instead use an external WCS library, as described above. These routines are included mainly for backward compatibility with existing software. They support the following standard map projections: -SIN, -TAN, -ARC, -NCP, -GLS, -MER, and -AIT (these are the legal values for the coordtype parameter). These routines are based on similar functions in Classic AIPS. All the angular quantities are given in units of degrees. \begin{description} \item[1 ] Get the values of all the standard FITS celestial coordinate system keywords from the header of a FITS image (i.e., the primary array or an image extension). These values may then be passed to the subroutines that perform the coordinate transformations. If any or all of the WCS keywords are not present, then default values will be returned. If the first coordinate axis is the declination-like coordinate, then this routine will swap them so that the longitudinal-like coordinate is returned as the first axis. If the file uses the newer 'CDj\_i' WCS transformation matrix keywords instead of old style 'CDELTn' and 'CROTA2' keywords, then this routine will calculate and return the values of the equivalent old-style keywords. Note that the conversion from the new-style keywords to the old-style values is sometimes only an approximation, so if the approximation is larger than an internally defined threshold level, then CFITSIO will still return the approximate WCS keyword values, but will also return with status = 506, to warn the calling program that approximations have been made. It is then up to the calling program to decide whether the approximations are sufficiently accurate for the particular application, or whether more precise WCS transformations must be performed using new-style WCS keywords directly. \end{description} \begin{verbatim} FTGICS(unit, > xrval,yrval,xrpix,yrpix,xinc,yinc,rot,coordtype,status) \end{verbatim} \begin{description} \item[2 ] Get the values of all the standard FITS celestial coordinate system keywords from the header of a FITS table where the X and Y (or RA and DEC coordinates are stored in 2 separate columns of the table. These values may then be passed to the subroutines that perform the coordinate transformations. \end{description} \begin{verbatim} FTGTCS(unit,xcol,ycol, > xrval,yrval,xrpix,yrpix,xinc,yinc,rot,coordtype,status) \end{verbatim} \begin{description} \item[3 ] Calculate the celestial coordinate corresponding to the input X and Y pixel location in the image. \end{description} \begin{verbatim} FTWLDP(xpix,ypix,xrval,yrval,xrpix,yrpix,xinc,yinc,rot, coordtype, > xpos,ypos,status) \end{verbatim} \begin{description} \item[4 ] Calculate the X and Y pixel location corresponding to the input celestial coordinate in the image. \end{description} \begin{verbatim} FTXYPX(xpos,ypos,xrval,yrval,xrpix,yrpix,xinc,yinc,rot, coordtype, > xpix,ypix,status) \end{verbatim} \section{File Checksum Subroutines \label{FTPCKS}} The following routines either compute or validate the checksums for the CHDU. The DATASUM keyword is used to store the numerical value of the 32-bit, 1's complement checksum for the data unit alone. If there is no data unit then the value is set to zero. The numerical value is stored as an ASCII string of digits, enclosed in quotes, because the value may be too large to represent as a 32-bit signed integer. The CHECKSUM keyword is used to store the ASCII encoded COMPLEMENT of the checksum for the entire HDU. Storing the complement, rather than the actual checksum, forces the checksum for the whole HDU to equal zero. If the file has been modified since the checksums were computed, then the HDU checksum will usually not equal zero. These checksum keyword conventions are based on a paper by Rob Seaman published in the proceedings of the ADASS IV conference in Baltimore in November 1994 and a later revision in June 1995. \begin{description} \item[1 ] Compute and write the DATASUM and CHECKSUM keyword values for the CHDU into the current header. The DATASUM value is the 32-bit checksum for the data unit, expressed as a decimal integer enclosed in single quotes. The CHECKSUM keyword value is a 16-character string which is the ASCII-encoded value for the complement of the checksum for the whole HDU. If these keywords already exist, their values will be updated only if necessary (i.e., if the file has been modified since the original keyword values were computed). \end{description} \begin{verbatim} FTPCKS(unit, > status) \end{verbatim} \begin{description} \item[2 ] Update the CHECKSUM keyword value in the CHDU, assuming that the DATASUM keyword exists and already has the correct value. This routine calculates the new checksum for the current header unit, adds it to the data unit checksum, encodes the value into an ASCII string, and writes the string to the CHECKSUM keyword. \end{description} \begin{verbatim} FTUCKS(unit, > status) \end{verbatim} \begin{description} \item[3 ] Verify the CHDU by computing the checksums and comparing them with the keywords. The data unit is verified correctly if the computed checksum equals the value of the DATASUM keyword. The checksum for the entire HDU (header plus data unit) is correct if it equals zero. The output DATAOK and HDUOK parameters in this subroutine are integers which will have a value = 1 if the data or HDU is verified correctly, a value = 0 if the DATASUM or CHECKSUM keyword is not present, or value = -1 if the computed checksum is not correct. \end{description} \begin{verbatim} FTVCKS(unit, > dataok,hduok,status) \end{verbatim} \begin{description} \item[4 ] Compute and return the checksum values for the CHDU (as double precision variables) without creating or modifying the CHECKSUM and DATASUM keywords. This routine is used internally by FTVCKS, but may be useful in other situations as well. \end{description} \begin{verbatim} FTGCKS(unit, > datasum,hdusum,status) \end{verbatim} \begin{description} \item[5 ] Encode a checksum value (stored in a double precision variable) into a 16-character string. If COMPLEMENT = .true. then the 32-bit sum value will be complemented before encoding. \end{description} \begin{verbatim} FTESUM(sum,complement, > checksum) \end{verbatim} \begin{description} \item[6 ] Decode a 16 character checksum string into a double precision value. If COMPLEMENT = .true. then the 32-bit sum value will be complemented after decoding. \end{description} \begin{verbatim} FTDSUM(checksum,complement, > sum) \end{verbatim} \section{ Date and Time Utility Routines \label{FTGSDT}} The following routines help to construct or parse the FITS date/time strings. Starting in the year 2000, the FITS DATE keyword values (and the values of other `DATE-' keywords) must have the form 'YYYY-MM-DD' (date only) or 'YYYY-MM-DDThh:mm:ss.ddd...' (date and time) where the number of decimal places in the seconds value is optional. These times are in UTC. The older 'dd/mm/yy' date format may not be used for dates after 01 January 2000. \begin{description} \item[1 ] Get the current system date. The returned year has 4 digits (1999, 2000, etc.) \end{description} \begin{verbatim} FTGSDT( > day, month, year, status ) \end{verbatim} \begin{description} \item[2 ] Get the current system date and time string ('YYYY-MM-DDThh:mm:ss'). The time will be in UTC/GMT if available, as indicated by a returned timeref value = 0. If the returned value of timeref = 1 then this indicates that it was not possible to convert the local time to UTC, and thus the local time was returned. \end{description} \begin{verbatim} FTGSTM(> datestr, timeref, status) \end{verbatim} \begin{description} \item[3 ] Construct a date string from the input date values. If the year is between 1900 and 1998, inclusive, then the returned date string will have the old FITS format ('dd/mm/yy'), otherwise the date string will have the new FITS format ('YYYY-MM-DD'). Use FTTM2S instead to always return a date string using the new FITS format. \end{description} \begin{verbatim} FTDT2S( year, month, day, > datestr, status) \end{verbatim} \begin{description} \item[4 ] Construct a new-format date + time string ('YYYY-MM-DDThh:mm:ss.ddd...'). If the year, month, and day values all = 0 then only the time is encoded with format 'hh:mm:ss.ddd...'. The decimals parameter specifies how many decimal places of fractional seconds to include in the string. If `decimals' is negative, then only the date will be return ('YYYY-MM-DD'). \end{description} \begin{verbatim} FTTM2S( year, month, day, hour, minute, second, decimals, > datestr, status) \end{verbatim} \begin{description} \item[5 ] Return the date as read from the input string, where the string may be in either the old ('dd/mm/yy') or new ('YYYY-MM-DDThh:mm:ss' or 'YYYY-MM-DD') FITS format. \end{description} \begin{verbatim} FTS2DT(datestr, > year, month, day, status) \end{verbatim} \begin{description} \item[6 ] Return the date and time as read from the input string, where the string may be in either the old or new FITS format. The returned hours, minutes, and seconds values will be set to zero if the input string does not include the time ('dd/mm/yy' or 'YYYY-MM-DD') . Similarly, the returned year, month, and date values will be set to zero if the date is not included in the input string ('hh:mm:ss.ddd...'). \end{description} \begin{verbatim} FTS2TM(datestr, > year, month, day, hour, minute, second, status) \end{verbatim} \section{General Utility Subroutines \label{FTGHAD}} The following utility subroutines may be useful for certain applications: \begin{description} \item[1 ] Return the starting byte address of the CHDU and the next HDU. \end{description} \begin{verbatim} FTGHAD(iunit, > curaddr, nextaddr) \end{verbatim} \begin{description} \item[2 ] Convert a character string to uppercase (operates in place). \end{description} \begin{verbatim} FTUPCH(string) \end{verbatim} \begin{description} \item[3 ] Compare the input template string against the reference string to see if they match. The template string may contain wildcard characters: '*' will match any sequence of characters (including zero characters) and '?' will match any single character in the reference string. The '\#' character will match any consecutive string of decimal digits (0 - 9). If CASESN = .true. then the match will be case sensitive. The returned MATCH parameter will be .true. if the 2 strings match, and EXACT will be .true. if the match is exact (i.e., if no wildcard characters were used in the match). Both strings must be 68 characters or less in length. \end{description} \begin{verbatim} FTCMPS(str_template, string, casesen, > match, exact) \end{verbatim} \begin{description} \item[4 ] Test that the keyword name contains only legal characters: A-Z,0-9, hyphen, and underscore. \end{description} \begin{verbatim} FTTKEY(keyword, > status) \end{verbatim} \begin{description} \item[5 ] Test that the keyword record contains only legal printable ASCII characters \end{description} \begin{verbatim} FTTREC(card, > status) \end{verbatim} \begin{description} \item[6 ] Test whether the current header contains any NULL (ASCII 0) characters. These characters are illegal in the header, but they will go undetected by most of the CFITSIO keyword header routines, because the null is interpreted as the normal end-of-string terminator. This routine returns the position of the first null character in the header, or zero if there are no nulls. For example a returned value of 110 would indicate that the first NULL is located in the 30th character of the second keyword in the header (recall that each header record is 80 characters long). Note that this is one of the few FITSIO routines in which the returned value is not necessarily equal to the status value). \end{description} \begin{verbatim} FTNCHK(unit, > status) \end{verbatim} \begin{description} \item[7 ] Parse a header keyword record and return the name of the keyword and the length of the name. The keyword name normally occupies the first 8 characters of the record, except under the HIERARCH convention where the name can be up to 70 characters in length. \end{description} \begin{verbatim} FTGKNM(card, > keyname, keylength, staThe '\#' character will match any consecutive string of decimal digits (0 - 9). tus) \end{verbatim} \begin{description} \item[8 ] Parse a header keyword record. This subroutine parses the input header record to return the value (as a character string) and comment strings. If the keyword has no value (columns 9-10 not equal to '= '), then the value string is returned blank and the comment string is set equal to column 9 - 80 of the input string. \end{description} \begin{verbatim} FTPSVC(card, > value,comment,status) \end{verbatim} \begin{description} \item[9 ] Construct a properly formated 80-character header keyword record from the input keyword name, keyword value, and keyword comment strings. Hierarchical keyword names (e.g., "ESO TELE CAM") are supported. The value string may contain an integer, floating point, logical, or quoted character string (e.g., "12", "15.7", "T", or "'NGC 1313'"). \end{description} \begin{verbatim} FTMKKY(keyname, value, comment, > card, status) \end{verbatim} \begin{description} \item[10] Construct a sequence keyword name (ROOT + nnn). This subroutine appends the sequence number to the root string to create a keyword name (e.g., 'NAXIS' + 2 = 'NAXIS2') \end{description} \begin{verbatim} FTKEYN(keyroot,seq_no, > keyword,status) \end{verbatim} \begin{description} \item[11] Construct a sequence keyword name (n + ROOT). This subroutine concatenates the sequence number to the front of the root string to create a keyword name (e.g., 1 + 'CTYP' = '1CTYP') \end{description} \begin{verbatim} FTNKEY(seq_no,keyroot, > keyword,status) \end{verbatim} \begin{description} \item[12] Determine the datatype of a keyword value string. This subroutine parses the keyword value string (usually columns 11-30 of the header record) to determine its datatype. \end{description} \begin{verbatim} FTDTYP(value, > dtype,status) \end{verbatim} \begin{description} \item[13] Return the class of input header record. The record is classified into one of the following categories (the class values are defined in fitsio.h). Note that this is one of the few FITSIO routines that does not return a status value. \end{description} \begin{verbatim} Class Value Keywords TYP_STRUC_KEY 10 SIMPLE, BITPIX, NAXIS, NAXISn, EXTEND, BLOCKED, GROUPS, PCOUNT, GCOUNT, END XTENSION, TFIELDS, TTYPEn, TBCOLn, TFORMn, THEAP, and the first 4 COMMENT keywords in the primary array that define the FITS format. TYP_CMPRS_KEY 20 The keywords used in the compressed image or table format, including ZIMAGE, ZCMPTYPE, ZNAMEn, ZVALn, ZTILEn, ZBITPIX, ZNAXISn, ZSCALE, ZZERO, ZBLANK TYP_SCAL_KEY 30 BSCALE, BZERO, TSCALn, TZEROn TYP_NULL_KEY 40 BLANK, TNULLn TYP_DIM_KEY 50 TDIMn TYP_RANG_KEY 60 TLMINn, TLMAXn, TDMINn, TDMAXn, DATAMIN, DATAMAX TYP_UNIT_KEY 70 BUNIT, TUNITn TYP_DISP_KEY 80 TDISPn TYP_HDUID_KEY 90 EXTNAME, EXTVER, EXTLEVEL, HDUNAME, HDUVER, HDULEVEL TYP_CKSUM_KEY 100 CHECKSUM, DATASUM TYP_WCS_KEY 110 CTYPEn, CUNITn, CRVALn, CRPIXn, CROTAn, CDELTn CDj_is, PVj_ms, LONPOLEs, LATPOLEs TCTYPn, TCTYns, TCUNIn, TCUNns, TCRVLn, TCRVns, TCRPXn, TCRPks, TCDn_k, TCn_ks, TPVn_m, TPn_ms, TCDLTn, TCROTn jCTYPn, jCTYns, jCUNIn, jCUNns, jCRVLn, jCRVns, iCRPXn, iCRPns, jiCDn, jiCDns, jPVn_m, jPn_ms, jCDLTn, jCROTn (i,j,m,n are integers, s is any letter) TYP_REFSYS_KEY 120 EQUINOXs, EPOCH, MJD-OBSs, RADECSYS, RADESYSs TYP_COMM_KEY 130 COMMENT, HISTORY, (blank keyword) TYP_CONT_KEY 140 CONTINUE TYP_USER_KEY 150 all other keywords class = FTGKCL (char *card) \end{verbatim} \begin{description} \item[14] Parse the 'TFORM' binary table column format string. This subroutine parses the input TFORM character string and returns the integer datatype code, the repeat count of the field, and, in the case of character string fields, the length of the unit string. The following datatype codes are returned (the negative of the value is returned if the column contains variable-length arrays): \end{description} \begin{verbatim} Datatype DATACODE value bit, X 1 byte, B 11 logical, L 14 ASCII character, A 16 short integer, I 21 integer, J 41 real, E 42 double precision, D 82 complex 83 double complex 163 FTBNFM(tform, > datacode,repeat,width,status) \end{verbatim} \begin{description} \item[15] Parse the 'TFORM' keyword value that defines the column format in an ASCII table. This routine parses the input TFORM character string and returns the datatype code, the width of the column, and (if it is a floating point column) the number of decimal places to the right of the decimal point. The returned datatype codes are the same as for the binary table, listed above, with the following additional rules: integer columns that are between 1 and 4 characters wide are defined to be short integers (code = 21). Wider integer columns are defined to be regular integers (code = 41). Similarly, Fixed decimal point columns (with TFORM = 'Fw.d') are defined to be single precision reals (code = 42) if w is between 1 and 7 characters wide, inclusive. Wider 'F' columns will return a double precision data code (= 82). 'Ew.d' format columns will have datacode = 42, and 'Dw.d' format columns will have datacode = 82. \end{description} \begin{verbatim} FTASFM(tform, > datacode,width,decimals,status) \end{verbatim} \begin{description} \item[16] Calculate the starting column positions and total ASCII table width based on the input array of ASCII table TFORM values. The SPACE input parameter defines how many blank spaces to leave between each column (it is recommended to have one space between columns for better human readability). \end{description} \begin{verbatim} FTGABC(tfields,tform,space, > rowlen,tbcol,status) \end{verbatim} \begin{description} \item[17] Parse a template string and return a formatted 80-character string suitable for appending to (or deleting from) a FITS header file. This subroutine is useful for parsing lines from an ASCII template file and reformatting them into legal FITS header records. The formatted string may then be passed to the FTPREC, FTMCRD, or FTDKEY subroutines to append or modify a FITS header record. \end{description} \begin{verbatim} FTGTHD(template, > card,hdtype,status) \end{verbatim} The input TEMPLATE character string generally should contain 3 tokens: (1) the KEYNAME, (2) the VALUE, and (3) the COMMENT string. The TEMPLATE string must adhere to the following format: \begin{description} \item[- ] The KEYNAME token must begin in columns 1-8 and be a maximum of 8 characters long. If the first 8 characters of the template line are blank then the remainder of the line is considered to be a FITS comment (with a blank keyword name). A legal FITS keyword name may only contain the characters A-Z, 0-9, and '-' (minus sign) and underscore. This subroutine will automatically convert any lowercase characters to uppercase in the output string. If KEYNAME = 'COMMENT' or 'HISTORY' then the remainder of the line is considered to be a FITS COMMENT or HISTORY record, respectively. \end{description} \begin{description} \item[- ] The VALUE token must be separated from the KEYNAME token by one or more spaces and/or an '=' character. The datatype of the VALUE token (numeric, logical, or character string) is automatically determined and the output CARD string is formatted accordingly. The value token may be forced to be interpreted as a string (e.g. if it is a string of numeric digits) by enclosing it in single quotes. If the value token is a character string that contains 1 or more embedded blank space characters or slash ('/') characters then the entire character string must be enclosed in single quotes. \end{description} \begin{description} \item[- ] The COMMENT token is optional, but if present must be separated from the VALUE token by a blank space or a '/' character. \end{description} \begin{description} \item[- ] One exception to the above rules is that if the first non-blank character in the template string is a minus sign ('-') followed by a single token, or a single token followed by an equal sign, then it is interpreted as the name of a keyword which is to be deleted from the FITS header. \end{description} \begin{description} \item[- ] The second exception is that if the template string starts with a minus sign and is followed by 2 tokens then the second token is interpreted as the new name for the keyword specified by first token. In this case the old keyword name (first token) is returned in characters 1-8 of the returned CARD string, and the new keyword name (the second token) is returned in characters 41-48 of the returned CARD string. These old and new names may then be passed to the FTMNAM subroutine which will change the keyword name. \end{description} The HDTYPE output parameter indicates how the returned CARD string should be interpreted: \begin{verbatim} hdtype interpretation ------ ------------------------------------------------- -2 Modify the name of the keyword given in CARD(1:8) to the new name given in CARD(41:48) -1 CARD(1:8) contains the name of a keyword to be deleted from the FITS header. 0 append the CARD string to the FITS header if the keyword does not already exist, otherwise update the value/comment if the keyword is already present in the header. 1 simply append this keyword to the FITS header (CARD is either a HISTORY or COMMENT keyword). 2 This is a FITS END record; it should not be written to the FITS header because FITSIO automatically appends the END record when the header is closed. \end{verbatim} EXAMPLES: The following lines illustrate valid input template strings: \begin{verbatim} INTVAL 7 This is an integer keyword RVAL 34.6 / This is a floating point keyword EVAL=-12.45E-03 This is a floating point keyword in exponential notation lval F This is a boolean keyword This is a comment keyword with a blank keyword name SVAL1 = 'Hello world' / this is a string keyword SVAL2 '123.5' this is also a string keyword sval3 123+ / this is also a string keyword with the value '123+ ' # the following template line deletes the DATE keyword - DATE # the following template line modifies the NAME keyword to OBJECT - NAME OBJECT \end{verbatim} \begin{description} \item[18] Parse the input string containing a list of rows or row ranges, and return integer arrays containing the first and last row in each range. For example, if rowlist = "3-5, 6, 8-9" then it will return numranges = 3, rangemin = 3, 6, 8 and rangemax = 5, 6, 9. At most, 'maxranges' number of ranges will be returned. 'maxrows' is the maximum number of rows in the table; any rows or ranges larger than this will be ignored. The rows must be specified in increasing order, and the ranges must not overlap. A minus sign may be use to specify all the rows to the upper or lower bound, so "50-" means all the rows from 50 to the end of the table, and "-" means all the rows in the table, from 1 - maxrows. \end{description} \begin{verbatim} FTRWRG(rowlist, maxrows, maxranges, > numranges, rangemin, rangemax, status) \end{verbatim} \chapter{ The CFITSIO Iterator Function } The fits\_iterate\_data function in CFITSIO provides a unique method of executing an arbitrary user-supplied `work' function that operates on rows of data in FITS tables or on pixels in FITS images. Rather than explicitly reading and writing the FITS images or columns of data, one instead calls the CFITSIO iterator routine, passing to it the name of the user's work function that is to be executed along with a list of all the table columns or image arrays that are to be passed to the work function. The CFITSIO iterator function then does all the work of allocating memory for the arrays, reading the input data from the FITS file, passing them to the work function, and then writing any output data back to the FITS file after the work function exits. Because it is often more efficient to process only a subset of the total table rows at one time, the iterator function can determine the optimum amount of data to pass in each iteration and repeatedly call the work function until the entire table been processed. For many applications this single CFITSIO iterator function can effectively replace all the other CFITSIO routines for reading or writing data in FITS images or tables. Using the iterator has several important advantages over the traditional method of reading and writing FITS data files: \begin{itemize} \item It cleanly separates the data I/O from the routine that operates on the data. This leads to a more modular and `object oriented' programming style. \item It simplifies the application program by eliminating the need to allocate memory for the data arrays and eliminates most of the calls to the CFITSIO routines that explicitly read and write the data. \item It ensures that the data are processed as efficiently as possible. This is especially important when processing tabular data since the iterator function will calculate the most efficient number of rows in the table to be passed at one time to the user's work function on each iteration. \item Makes it possible for larger projects to develop a library of work functions that all have a uniform calling sequence and are all independent of the details of the FITS file format. \end{itemize} There are basically 2 steps in using the CFITSIO iterator function. The first step is to design the work function itself which must have a prescribed set of input parameters. One of these parameters is a structure containing pointers to the arrays of data; the work function can perform any desired operations on these arrays and does not need to worry about how the input data were read from the file or how the output data get written back to the file. The second step is to design the driver routine that opens all the necessary FITS files and initializes the input parameters to the iterator function. The driver program calls the CFITSIO iterator function which then reads the data and passes it to the user's work function. Further details on using the iterator function can be found in the companion CFITSIO User's Guide, and in the iter\_a.f, iter\_b.f and iter\_c.f example programs. \chapter{ Extended File Name Syntax } \section{Overview} CFITSIO supports an extended syntax when specifying the name of the data file to be opened or created that includes the following features: \begin{itemize} \item CFITSIO can read IRAF format images which have header file names that end with the '.imh' extension, as well as reading and writing FITS files, This feature is implemented in CFITSIO by first converting the IRAF image into a temporary FITS format file in memory, then opening the FITS file. Any of the usual CFITSIO routines then may be used to read the image header or data. Similarly, raw binary data arrays can be read by converting them on the fly into virtual FITS images. \item FITS files on the Internet can be read (and sometimes written) using the FTP, HTTP, or ROOT protocols. \item FITS files can be piped between tasks on the stdin and stdout streams. \item FITS files can be read and written in shared memory. This can potentially achieve much better data I/O performance compared to reading and writing the same FITS files on magnetic disk. \item Compressed FITS files in gzip or Unix COMPRESS format can be directly read. \item Output FITS files can be written directly in compressed gzip format, thus saving disk space. \item FITS table columns can be created, modified, or deleted 'on-the-fly' as the table is opened by CFITSIO. This creates a virtual FITS file containing the modifications that is then opened by the application program. \item Table rows may be selected, or filtered out, on the fly when the table is opened by CFITSIO, based on an arbitrary user-specified expression. Only rows for which the expression evaluates to 'TRUE' are retained in the copy of the table that is opened by the application program. \item Histogram images may be created on the fly by binning the values in table columns, resulting in a virtual N-dimensional FITS image. The application program then only sees the FITS image (in the primary array) instead of the original FITS table. \end{itemize} The latter 3 features in particular add very powerful data processing capabilities directly into CFITSIO, and hence into every task that uses CFITSIO to read or write FITS files. For example, these features transform a very simple program that just copies an input FITS file to a new output file (like the `fitscopy' program that is distributed with CFITSIO) into a multipurpose FITS file processing tool. By appending fairly simple qualifiers onto the name of the input FITS file, the user can perform quite complex table editing operations (e.g., create new columns, or filter out rows in a table) or create FITS images by binning or histogramming the values in table columns. In addition, these functions have been coded using new state-of-the art algorithms that are, in some cases, 10 - 100 times faster than previous widely used implementations. Before describing the complete syntax for the extended FITS file names in the next section, here are a few examples of FITS file names that give a quick overview of the allowed syntax: \begin{itemize} \item {\tt 'myfile.fits'}: the simplest case of a FITS file on disk in the current directory. \item {\tt 'myfile.imh'}: opens an IRAF format image file and converts it on the fly into a temporary FITS format image in memory which can then be read with any other CFITSIO routine. \item {\tt rawfile.dat[i512,512]}: opens a raw binary data array (a 512 x 512 short integer array in this case) and converts it on the fly into a temporary FITS format image in memory which can then be read with any other CFITSIO routine. \item {\tt myfile.fits.gz}: if this is the name of a new output file, the '.gz' suffix will cause it to be compressed in gzip format when it is written to disk. \item {\tt 'myfile.fits.gz[events, 2]'}: opens and uncompresses the gzipped file myfile.fits then moves to the extension which has the keywords EXTNAME = 'EVENTS' and EXTVER = 2. \item {\tt '-'}: a dash (minus sign) signifies that the input file is to be read from the stdin file stream, or that the output file is to be written to the stdout stream. \item {\tt 'ftp://legacy.gsfc.nasa.gov/test/vela.fits'}: FITS files in any ftp archive site on the Internet may be directly opened with read-only access. \item {\tt 'http://legacy.gsfc.nasa.gov/software/test.fits'}: any valid URL to a FITS file on the Web may be opened with read-only access. \item {\tt 'root://legacy.gsfc.nasa.gov/test/vela.fits'}: similar to ftp access except that it provides write as well as read access to the files across the network. This uses the root protocol developed at CERN. \item {\tt 'shmem://h2[events]'}: opens the FITS file in a shared memory segment and moves to the EVENTS extension. \item {\tt 'mem://'}: creates a scratch output file in core computer memory. The resulting 'file' will disappear when the program exits, so this is mainly useful for testing purposes when one does not want a permanent copy of the output file. \item {\tt 'myfile.fits[3; Images(10)]'}: opens a copy of the image contained in the 10th row of the 'Images' column in the binary table in the 3th extension of the FITS file. The application just sees this single image as the primary array. \item {\tt 'myfile.fits[1:512:2, 1:512:2]'}: opens a section of the input image ranging from the 1st to the 512th pixel in X and Y, and selects every second pixel in both dimensions, resulting in a 256 x 256 pixel image in this case. \item {\tt 'myfile.fits[EVENTS][col Rad = sqrt(X**2 + Y**2)]'}: creates and opens a temporary file on the fly (in memory or on disk) that is identical to myfile.fits except that it will contain a new column in the EVENTS extension called 'Rad' whose value is computed using the indicated expression which is a function of the values in the X and Y columns. \item {\tt 'myfile.fits[EVENTS][PHA > 5]'}: creates and opens a temporary FITS files that is identical to 'myfile.fits' except that the EVENTS table will only contain the rows that have values of the PHA column greater than 5. In general, any arbitrary boolean expression using a C or Fortran-like syntax, which may combine AND and OR operators, may be used to select rows from a table. \item {\tt 'myfile.fits[EVENTS][bin (X,Y)=1,2048,4]'}: creates a temporary FITS primary array image which is computed on the fly by binning (i.e, computing the 2-dimensional histogram) of the values in the X and Y columns of the EVENTS extension. In this case the X and Y coordinates range from 1 to 2048 and the image pixel size is 4 units in both dimensions, so the resulting image is 512 x 512 pixels in size. \item The final example combines many of these feature into one complex expression (it is broken into several lines for clarity): \begin{verbatim} 'ftp://legacy.gsfc.nasa.gov/data/sample.fits.gz[EVENTS] [col phacorr = pha * 1.1 - 0.3][phacorr >= 5.0 && phacorr <= 14.0] [bin (X,Y)=32]' \end{verbatim} In this case, CFITSIO (1) copies and uncompresses the FITS file from the ftp site on the legacy machine, (2) moves to the 'EVENTS' extension, (3) calculates a new column called 'phacorr', (4) selects the rows in the table that have phacorr in the range 5 to 14, and finally (5) bins the remaining rows on the X and Y column coordinates, using a pixel size = 32 to create a 2D image. All this processing is completely transparent to the application program, which simply sees the final 2-D image in the primary array of the opened file. \end{itemize} The full extended CFITSIO FITS file name can contain several different components depending on the context. These components are described in the following sections: \begin{verbatim} When creating a new file: filetype://BaseFilename(templateName) When opening an existing primary array or image HDU: filetype://BaseFilename(outName)[HDUlocation][ImageSection] When opening an existing table HDU: filetype://BaseFilename(outName)[HDUlocation][colFilter][rowFilter][binSpec] \end{verbatim} The filetype, BaseFilename, outName, HDUlocation, and ImageSection components, if present, must be given in that order, but the colFilter, rowFilter, and binSpec specifiers may follow in any order. Regardless of the order, however, the colFilter specifier, if present, will be processed first by CFITSIO, followed by the rowFilter specifier, and finally by the binSpec specifier. \section{Filetype} The type of file determines the medium on which the file is located (e.g., disk or network) and, hence, which internal device driver is used by CFITSIO to read and/or write the file. Currently supported types are \begin{verbatim} file:// - file on local magnetic disk (default) ftp:// - a readonly file accessed with the anonymous FTP protocol. It also supports ftp://username:password@hostname/... for accessing password-protected ftp sites. http:// - a readonly file accessed with the HTTP protocol. It supports username:password just like the ftp driver. Proxy HTTP servers are supported using the http_proxy environment variable (see following note). stream:// - special driver to read an input FITS file from the stdin stream, and/or write an output FITS file to the stdout stream. This driver is fragile and has limited functionality (see the following note). gsiftp:// - access files on a computational grid using the gridftp protocol in the Globus toolkit (see following note). root:// - uses the CERN root protocol for writing as well as reading files over the network. shmem:// - opens or creates a file which persists in the computer's shared memory. mem:// - opens a temporary file in core memory. The file disappears when the program exits so this is mainly useful for test purposes when a permanent output file is not desired. \end{verbatim} If the filetype is not specified, then type file:// is assumed. The double slashes '//' are optional and may be omitted in most cases. \subsection{Notes about HTTP proxy servers} A proxy HTTP server may be used by defining the address (URL) and port number of the proxy server with the http\_proxy environment variable. For example \begin{verbatim} setenv http_proxy http://heasarc.gsfc.nasa.gov:3128 \end{verbatim} will cause CFITSIO to use port 3128 on the heasarc proxy server whenever reading a FITS file with HTTP. \subsection{Notes about the stream filetype driver} The stream driver can be used to efficiently read a FITS file from the stdin file stream or write a FITS to the stdout file stream. However, because these input and output streams must be accessed sequentially, the FITS file reading or writing application must also read and write the file sequentially, at least within the tolerances described below. CFITSIO supports 2 different methods for accessing FITS files on the stdin and stdout streams. The original method, which is invoked by specifying a dash character, "-", as the name of the file when opening or creating it, works by storing a complete copy of the entire FITS file in memory. In this case, when reading from stdin, CFITSIO will copy the entire stream into memory before doing any processing of the file. Similarly, when writing to stdout, CFITSIO will create a copy of the entire FITS file in memory, before finally flushing it out to the stdout stream when the FITS file is closed. Buffering the entire FITS file in this way allows the application to randomly access any part of the FITS file, in any order, but it also requires that the user have sufficient available memory (or virtual memory) to store the entire file, which may not be possible in the case of very large files. The newer stream filetype provides a more memory-efficient method of accessing FITS files on the stdin or stdout streams. Instead of storing a copy of the entire FITS file in memory, CFITSIO only uses a set of internal buffer which by default can store 40 FITS blocks, or about 100K bytes of the FITS file. The application program must process the FITS file sequentially from beginning to end, within this 100K buffer. Generally speaking the application program must conform to the following restrictions: \begin{itemize} \item The program must finish reading or writing the header keywords before reading or writing any data in the HDU. \item The HDU can contain at most about 1400 header keywords. This is the maximum that can fit in the nominal 40 FITS block buffer. In principle, this limit could be increased by recompiling CFITSIO with a larger buffer limit, which is set by the NIOBUF parameter in fitsio2.h. \item The program must read or write the data in a sequential manner from the beginning to the end of the HDU. Note that CFITSIO's internal 100K buffer allows a little latitude in meeting this requirement. \item The program cannot move back to a previous HDU in the FITS file. \item Reading or writing of variable length array columns in binary tables is not supported on streams, because this requires moving back and forth between the fixed-length portion of the binary table and the following heap area where the arrays are actually stored. \item Reading or writing of tile-compressed images is not supported on streams, because the images are internally stored using variable length arrays. \end{itemize} \subsection{Notes about the gsiftp filetype} DEPENDENCIES: Globus toolkit (2.4.3 or higher) (GT) should be installed. There are two different ways to install GT: 1) goto the globus toolkit web page www.globus.org and follow the download and compilation instructions; 2) goto the Virtual Data Toolkit web page http://vdt.cs.wisc.edu/ and follow the instructions (STRONGLY SUGGESTED); Once a globus client has been installed in your system with a specific flavour it is possible to compile and install the CFITSIO libraries. Specific configuration flags must be used: 1) --with-gsiftp[[=PATH]] Enable Globus Toolkit gsiftp protocol support PATH=GLOBUS\_LOCATION i.e. the location of your globus installation 2) --with-gsiftp-flavour[[=PATH] defines the specific Globus flavour ex. gcc32 Both the flags must be used and it is mandatory to set both the PATH and the flavour. USAGE: To access files on a gridftp server it is necessary to use a gsiftp prefix: example: gsiftp://remote\_server\_fqhn/directory/filename The gridftp driver uses a local buffer on a temporary file the file is located in the /tmp directory. If you have special permissions on /tmp or you do not have a /tmp directory, it is possible to force another location setting the GSIFTP\_TMPFILE environment variable (ex. export GSIFTP\_TMPFILE=/your/location/yourtmpfile). Grid FTP supports multi channel transfer. By default a single channel transmission is available. However, it is possible to modify this behavior setting the GSIFTP\_STREAMS environment variable (ex. export GSIFTP\_STREAMS=8). \subsection{Notes about the root filetype} The original rootd server can be obtained from: \verb-ftp://root.cern.ch/root/rootd.tar.gz- but, for it to work correctly with CFITSIO one has to use a modified version which supports a command to return the length of the file. This modified version is available in rootd subdirectory in the CFITSIO ftp area at \begin{verbatim} ftp://legacy.gsfc.nasa.gov/software/fitsio/c/root/rootd.tar.gz. \end{verbatim} This small server is started either by inetd when a client requests a connection to a rootd server or by hand (i.e. from the command line). The rootd server works with the ROOT TNetFile class. It allows remote access to ROOT database files in either read or write mode. By default TNetFile assumes port 432 (which requires rootd to be started as root). To run rootd via inetd add the following line to /etc/services: \begin{verbatim} rootd 432/tcp \end{verbatim} and to /etc/inetd.conf, add the following line: \begin{verbatim} rootd stream tcp nowait root /user/rdm/root/bin/rootd rootd -i \end{verbatim} Force inetd to reread its conf file with "kill -HUP ". You can also start rootd by hand running directly under your private account (no root system privileges needed). For example to start rootd listening on port 5151 just type: \verb+rootd -p 5151+ Notice: no \& is needed. Rootd will go into background by itself. \begin{verbatim} Rootd arguments: -i says we were started by inetd -p port# specifies a different port to listen on -d level level of debug info written to syslog 0 = no debug (default) 1 = minimum 2 = medium 3 = maximum \end{verbatim} Rootd can also be configured for anonymous usage (like anonymous ftp). To setup rootd to accept anonymous logins do the following (while being logged in as root): \begin{verbatim} - Add the following line to /etc/passwd: rootd:*:71:72:Anonymous rootd:/var/spool/rootd:/bin/false where you may modify the uid, gid (71, 72) and the home directory to suite your system. - Add the following line to /etc/group: rootd:*:72:rootd where the gid must match the gid in /etc/passwd. - Create the directories: mkdir /var/spool/rootd mkdir /var/spool/rootd/tmp chmod 777 /var/spool/rootd/tmp Where /var/spool/rootd must match the rootd home directory as specified in the rootd /etc/passwd entry. - To make writeable directories for anonymous do, for example: mkdir /var/spool/rootd/pub chown rootd:rootd /var/spool/rootd/pub \end{verbatim} That's all. Several additional remarks: you can login to an anonymous server either with the names "anonymous" or "rootd". The password should be of type user@host.do.main. Only the @ is enforced for the time being. In anonymous mode the top of the file tree is set to the rootd home directory, therefore only files below the home directory can be accessed. Anonymous mode only works when the server is started via inetd. \subsection{Notes about the shmem filetype:} Shared memory files are currently supported on most Unix platforms, where the shared memory segments are managed by the operating system kernel and `live' independently of processes. They are not deleted (by default) when the process which created them terminates, although they will disappear if the system is rebooted. Applications can create shared memory files in CFITSIO by calling: \begin{verbatim} fit_create_file(&fitsfileptr, "shmem://h2", &status); \end{verbatim} where the root `file' names are currently restricted to be 'h0', 'h1', 'h2', 'h3', etc., up to a maximum number defined by the the value of SHARED\_MAXSEG (equal to 16 by default). This is a prototype implementation of the shared memory interface and a more robust interface, which will have fewer restrictions on the number of files and on their names, may be developed in the future. When opening an already existing FITS file in shared memory one calls the usual CFITSIO routine: \begin{verbatim} fits_open_file(&fitsfileptr, "shmem://h7", mode, &status) \end{verbatim} The file mode can be READWRITE or READONLY just as with disk files. More than one process can operate on READONLY mode files at the same time. CFITSIO supports proper file locking (both in READONLY and READWRITE modes), so calls to fits\_open\_file may be locked out until another other process closes the file. When an application is finished accessing a FITS file in a shared memory segment, it may close it (and the file will remain in the system) with fits\_close\_file, or delete it with fits\_delete\_file. Physical deletion is postponed until the last process calls ffclos/ffdelt. fits\_delete\_file tries to obtain a READWRITE lock on the file to be deleted, thus it can be blocked if the object was not opened in READWRITE mode. A shared memory management utility program called `smem', is included with the CFITSIO distribution. It can be built by typing `make smem'; then type `smem -h' to get a list of valid options. Executing smem without any options causes it to list all the shared memory segments currently residing in the system and managed by the shared memory driver. To get a list of all the shared memory objects, run the system utility program `ipcs [-a]'. \section{Base Filename} The base filename is the name of the file optionally including the director/subdirectory path, and in the case of `ftp', `http', and `root' filetypes, the machine identifier. Examples: \begin{verbatim} myfile.fits !data.fits /data/myfile.fits fits.gsfc.nasa.gov/ftp/sampledata/myfile.fits.gz \end{verbatim} When creating a new output file on magnetic disk (of type file://) if the base filename begins with an exclamation point (!) then any existing file with that same basename will be deleted prior to creating the new FITS file. Otherwise if the file to be created already exists, then CFITSIO will return an error and will not overwrite the existing file. Note that the exclamation point, '!', is a special UNIX character, so if it is used on the command line rather than entered at a task prompt, it must be preceded by a backslash to force the UNIX shell to pass it verbatim to the application program. If the output disk file name ends with the suffix '.gz', then CFITSIO will compress the file using the gzip compression algorithm before writing it to disk. This can reduce the amount of disk space used by the file. Note that this feature requires that the uncompressed file be constructed in memory before it is compressed and written to disk, so it can fail if there is insufficient available memory. An input FITS file may be compressed with the gzip or Unix compress algorithms, in which case CFITSIO will uncompress the file on the fly into a temporary file (in memory or on disk). Compressed files may only be opened with read-only permission. When specifying the name of a compressed FITS file it is not necessary to append the file suffix (e.g., `.gz' or `.Z'). If CFITSIO cannot find the input file name without the suffix, then it will automatically search for a compressed file with the same root name. In the case of reading ftp and http type files, CFITSIO generally looks for a compressed version of the file first, before trying to open the uncompressed file. By default, CFITSIO copies (and uncompressed if necessary) the ftp or http FITS file into memory on the local machine before opening it. This will fail if the local machine does not have enough memory to hold the whole FITS file, so in this case, the output filename specifier (see the next section) can be used to further control how CFITSIO reads ftp and http files. If the input file is an IRAF image file (*.imh file) then CFITSIO will automatically convert it on the fly into a virtual FITS image before it is opened by the application program. IRAF images can only be opened with READONLY file access. Similarly, if the input file is a raw binary data array, then CFITSIO will convert it on the fly into a virtual FITS image with the basic set of required header keywords before it is opened by the application program (with READONLY access). In this case the data type and dimensions of the image must be specified in square brackets following the filename (e.g. rawfile.dat[ib512,512]). The first character (case insensitive) defines the datatype of the array: \begin{verbatim} b 8-bit unsigned byte i 16-bit signed integer u 16-bit unsigned integer j 32-bit signed integer r or f 32-bit floating point d 64-bit floating point \end{verbatim} An optional second character specifies the byte order of the array values: b or B indicates big endian (as in FITS files and the native format of SUN UNIX workstations and Mac PCs) and l or L indicates little endian (native format of DEC OSF workstations and IBM PCs). If this character is omitted then the array is assumed to have the native byte order of the local machine. These datatype characters are then followed by a series of one or more integer values separated by commas which define the size of each dimension of the raw array. Arrays with up to 5 dimensions are currently supported. Finally, a byte offset to the position of the first pixel in the data file may be specified by separating it with a ':' from the last dimension value. If omitted, it is assumed that the offset = 0. This parameter may be used to skip over any header information in the file that precedes the binary data. Further examples: \begin{verbatim} raw.dat[b10000] 1-dimensional 10000 pixel byte array raw.dat[rb400,400,12] 3-dimensional floating point big-endian array img.fits[ib512,512:2880] reads the 512 x 512 short integer array in a FITS file, skipping over the 2880 byte header \end{verbatim} One special case of input file is where the filename = `-' (a dash or minus sign) or 'stdin' or 'stdout', which signifies that the input file is to be read from the stdin stream, or written to the stdout stream if a new output file is being created. In the case of reading from stdin, CFITSIO first copies the whole stream into a temporary FITS file (in memory or on disk), and subsequent reading of the FITS file occurs in this copy. When writing to stdout, CFITSIO first constructs the whole file in memory (since random access is required), then flushes it out to the stdout stream when the file is closed. In addition, if the output filename = '-.gz' or 'stdout.gz' then it will be gzip compressed before being written to stdout. This ability to read and write on the stdin and stdout steams allows FITS files to be piped between tasks in memory rather than having to create temporary intermediate FITS files on disk. For example if task1 creates an output FITS file, and task2 reads an input FITS file, the FITS file may be piped between the 2 tasks by specifying \begin{verbatim} task1 - | task2 - \end{verbatim} where the vertical bar is the Unix piping symbol. This assumes that the 2 tasks read the name of the FITS file off of the command line. \section{Output File Name when Opening an Existing File} An optional output filename may be specified in parentheses immediately following the base file name to be opened. This is mainly useful in those cases where CFITSIO creates a temporary copy of the input FITS file before it is opened and passed to the application program. This happens by default when opening a network FTP or HTTP-type file, when reading a compressed FITS file on a local disk, when reading from the stdin stream, or when a column filter, row filter, or binning specifier is included as part of the input file specification. By default this temporary file is created in memory. If there is not enough memory to create the file copy, then CFITSIO will exit with an error. In these cases one can force a permanent file to be created on disk, instead of a temporary file in memory, by supplying the name in parentheses immediately following the base file name. The output filename can include the '!' clobber flag. Thus, if the input filename to CFITSIO is: \verb+file1.fits.gz(file2.fits)+ then CFITSIO will uncompress `file1.fits.gz' into the local disk file `file2.fits' before opening it. CFITSIO does not automatically delete the output file, so it will still exist after the application program exits. In some cases, several different temporary FITS files will be created in sequence, for instance, if one opens a remote file using FTP, then filters rows in a binary table extension, then create an image by binning a pair of columns. In this case, the remote file will be copied to a temporary local file, then a second temporary file will be created containing the filtered rows of the table, and finally a third temporary file containing the binned image will be created. In cases like this where multiple files are created, the outfile specifier will be interpreted the name of the final file as described below, in descending priority: \begin{itemize} \item as the name of the final image file if an image within a single binary table cell is opened or if an image is created by binning a table column. \item as the name of the file containing the filtered table if a column filter and/or a row filter are specified. \item as the name of the local copy of the remote FTP or HTTP file. \item as the name of the uncompressed version of the FITS file, if a compressed FITS file on local disk has been opened. \item otherwise, the output filename is ignored. \end{itemize} The output file specifier is useful when reading FTP or HTTP-type FITS files since it can be used to create a local disk copy of the file that can be reused in the future. If the output file name = `*' then a local file with the same name as the network file will be created. Note that CFITSIO will behave differently depending on whether the remote file is compressed or not as shown by the following examples: \begin{itemize} \item `ftp://remote.machine/tmp/myfile.fits.gz(*)' - the remote compressed file is copied to the local compressed file `myfile.fits.gz', which is then uncompressed in local memory before being opened and passed to the application program. \item `ftp://remote.machine/tmp/myfile.fits.gz(myfile.fits)' - the remote compressed file is copied and uncompressed into the local file `myfile.fits'. This example requires less local memory than the previous example since the file is uncompressed on disk instead of in memory. \item `ftp://remote.machine/tmp/myfile.fits(myfile.fits.gz)' - this will usually produce an error since CFITSIO itself cannot compress files. \end{itemize} The exact behavior of CFITSIO in the latter case depends on the type of ftp server running on the remote machine and how it is configured. In some cases, if the file `myfile.fits.gz' exists on the remote machine, then the server will copy it to the local machine. In other cases the ftp server will automatically create and transmit a compressed version of the file if only the uncompressed version exists. This can get rather confusing, so users should use a certain amount of caution when using the output file specifier with FTP or HTTP file types, to make sure they get the behavior that they expect. \section{Template File Name when Creating a New File} When a new FITS file is created with a call to fits\_create\_file, the name of a template file may be supplied in parentheses immediately following the name of the new file to be created. This template is used to define the structure of one or more HDUs in the new file. The template file may be another FITS file, in which case the newly created file will have exactly the same keywords in each HDU as in the template FITS file, but all the data units will be filled with zeros. The template file may also be an ASCII text file, where each line (in general) describes one FITS keyword record. The format of the ASCII template file is described below. \section{Image Tile-Compression Specification} When specifying the name of the output FITS file to be created, the user can indicate that images should be written in tile-compressed format (see section 5.5, ``Primary Array or IMAGE Extension I/O Routines'') by enclosing the compression parameters in square brackets following the root disk file name. Here are some examples of the syntax for specifying tile-compressed output images: \begin{verbatim} myfile.fit[compress] - use Rice algorithm and default tile size myfile.fit[compress GZIP] - use the specified compression algorithm; myfile.fit[compress Rice] only the first letter of the algorithm myfile.fit[compress PLIO] name is required. myfile.fit[compress Rice 100,100] - use 100 x 100 pixel tile size myfile.fit[compress Rice 100,100;2] - as above, and use noisebits = 2 \end{verbatim} \section{HDU Location Specification} The optional HDU location specifier defines which HDU (Header-Data Unit, also known as an `extension') within the FITS file to initially open. It must immediately follow the base file name (or the output file name if present). If it is not specified then the first HDU (the primary array) is opened. The HDU location specifier is required if the colFilter, rowFilter, or binSpec specifiers are present, because the primary array is not a valid HDU for these operations. The HDU may be specified either by absolute position number, starting with 0 for the primary array, or by reference to the HDU name, and optionally, the version number and the HDU type of the desired extension. The location of an image within a single cell of a binary table may also be specified, as described below. The absolute position of the extension is specified either by enclosed the number in square brackets (e.g., `[1]' = the first extension following the primary array) or by preceded the number with a plus sign (`+1'). To specify the HDU by name, give the name of the desired HDU (the value of the EXTNAME or HDUNAME keyword) and optionally the extension version number (value of the EXTVER keyword) and the extension type (value of the XTENSION keyword: IMAGE, ASCII or TABLE, or BINTABLE), separated by commas and all enclosed in square brackets. If the value of EXTVER and XTENSION are not specified, then the first extension with the correct value of EXTNAME is opened. The extension name and type are not case sensitive, and the extension type may be abbreviated to a single letter (e.g., I = IMAGE extension or primary array, A or T = ASCII table extension, and B = binary table BINTABLE extension). If the HDU location specifier is equal to `[PRIMARY]' or `[P]', then the primary array (the first HDU) will be opened. FITS images are most commonly stored in the primary array or an image extension, but images can also be stored as a vector in a single cell of a binary table (i.e. each row of the vector column contains a different image). Such an image can be opened with CFITSIO by specifying the desired column name and the row number after the binary table HDU specifier as shown in the following examples. The column name is separated from the HDU specifier by a semicolon and the row number is enclosed in parentheses. In this case CFITSIO copies the image from the table cell into a temporary primary array before it is opened. The application program then just sees the image in the primary array, without any extensions. The particular row to be opened may be specified either by giving an absolute integer row number (starting with 1 for the first row), or by specifying a boolean expression that evaluates to TRUE for the desired row. The first row that satisfies the expression will be used. The row selection expression has the same syntax as described in the Row Filter Specifier section, below. Examples: \begin{verbatim} myfile.fits[3] - open the 3rd HDU following the primary array myfile.fits+3 - same as above, but using the FTOOLS-style notation myfile.fits[EVENTS] - open the extension that has EXTNAME = 'EVENTS' myfile.fits[EVENTS, 2] - same as above, but also requires EXTVER = 2 myfile.fits[events,2,b] - same, but also requires XTENSION = 'BINTABLE' myfile.fits[3; images(17)] - opens the image in row 17 of the 'images' column in the 3rd extension of the file. myfile.fits[3; images(exposure > 100)] - as above, but opens the image in the first row that has an 'exposure' column value greater than 100. \end{verbatim} \section{Image Section} A virtual file containing a rectangular subsection of an image can be extracted and opened by specifying the range of pixels (start:end) along each axis to be extracted from the original image. One can also specify an optional pixel increment (start:end:step) for each axis of the input image. A pixel step = 1 will be assumed if it is not specified. If the start pixel is larger then the end pixel, then the image will be flipped (producing a mirror image) along that dimension. An asterisk, '*', may be used to specify the entire range of an axis, and '-*' will flip the entire axis. The input image can be in the primary array, in an image extension, or contained in a vector cell of a binary table. In the later 2 cases the extension name or number must be specified before the image section specifier. Examples: \begin{verbatim} myfile.fits[1:512:2, 2:512:2] - open a 256x256 pixel image consisting of the odd numbered columns (1st axis) and the even numbered rows (2nd axis) of the image in the primary array of the file. myfile.fits[*, 512:256] - open an image consisting of all the columns in the input image, but only rows 256 through 512. The image will be flipped along the 2nd axis since the starting pixel is greater than the ending pixel. myfile.fits[*:2, 512:256:2] - same as above but keeping only every other row and column in the input image. myfile.fits[-*, *] - copy the entire image, flipping it along the first axis. myfile.fits[3][1:256,1:256] - opens a subsection of the image that is in the 3rd extension of the file. myfile.fits[4; images(12)][1:10,1:10] - open an image consisting of the first 10 pixels in both dimensions. The original image resides in the 12th row of the 'images' vector column in the table in the 4th extension of the file. \end{verbatim} When CFITSIO opens an image section it first creates a temporary file containing the image section plus a copy of any other HDUs in the file. This temporary file is then opened by the application program, so it is not possible to write to or modify the input file when specifying an image section. Note that CFITSIO automatically updates the world coordinate system keywords in the header of the image section, if they exist, so that the coordinate associated with each pixel in the image section will be computed correctly. \section{Image Transform Filters} CFITSIO can apply a user-specified mathematical function to the value of every pixel in a FITS image, thus creating a new virtual image in computer memory that is then opened and read by the application program. The original FITS image is not modified by this process. The image transformation specifier is appended to the input FITS file name and is enclosed in square brackets. It begins with the letters 'PIX' to distinguish it from other types of FITS file filters that are recognized by CFITSIO. The image transforming function may use any of the mathematical operators listed in the following 'Row Filtering Specification' section of this document. Some examples of image transform filters are: \begin{verbatim} [pix X * 2.0] - multiply each pixel by 2.0 [pix sqrt(X)] - take the square root of each pixel [pix X + #ZEROPT - add the value of the ZEROPT keyword [pix X>0 ? log10(X) : -99.] - if the pixel value is greater than 0, compute the base 10 log, else set the pixel = -99. \end{verbatim} Use the letter 'X' in the expression to represent the current pixel value in the image. The expression is evaluated independently for each pixel in the image and may be a function of 1) the original pixel value, 2) the value of other pixels in the image at a given relative offset from the position of the pixel that is being evaluated, and 3) the value of any header keywords. Header keyword values are represented by the name of the keyword preceded by the '\#' sign. To access the the value of adjacent pixels in the image, specify the (1-D) offset from the current pixel in curly brackets. For example \begin{verbatim} [pix (x{-1} + x + x{+1}) / 3] \end{verbatim} will replace each pixel value with the running mean of the values of that pixel and it's 2 neighboring pixels. Note that in this notation the image is treated as a 1-D array, where each row of the image (or higher dimensional cube) is appended one after another in one long array of pixels. It is possible to refer to pixels in the rows above or below the current pixel by using the value of the NAXIS1 header keyword. For example \begin{verbatim} [pix (x{-#NAXIS1} + x + x{#NAXIS1}) / 3] \end{verbatim} will compute the mean of each image pixel and the pixels immediately above and below it in the adjacent rows of the image. The following more complex example creates a smoothed virtual image where each pixel is a 3 x 3 boxcar average of the input image pixels: \begin{verbatim} [pix (X + X{-1} + X{+1} + X{-#NAXIS1} + X{-#NAXIS1 - 1} + X{-#NAXIS1 + 1} + X{#NAXIS1} + X{#NAXIS1 - 1} + X{#NAXIS1 + 1}) / 9.] \end{verbatim} If the pixel offset extends beyond the first or last pixel in the image, the function will evaluate to undefined, or NULL. For complex or commonly used image filtering operations, one can write the expression into an external text file and then import it into the filter using the syntax '[pix @filename.txt]'. The mathematical expression can extend over multiple lines of text in the file. Any lines in the external text file that begin with 2 slash characters ('//') will be ignored and may be used to add comments into the file. By default, the datatype of the resulting image will be the same as the original image, but one may force a different datatype by appended a code letter to the 'pix' keyword: \begin{verbatim} pixb - 8-bit byte image with BITPIX = 8 pixi - 16-bit integer image with BITPIX = 16 pixj - 32-bit integer image with BITPIX = 32 pixr - 32-bit float image with BITPIX = -32 pixd - 64-bit float image with BITPIX = -64 \end{verbatim} Also by default, any other HDUs in the input file will be copied without change to the output virtual FITS file, but one may discard the other HDUs by adding the number '1' to the 'pix' keyword (and following any optional datatype code letter). For example: \begin{verbatim} myfile.fits[3][pixr1 sqrt(X)] \end{verbatim} will create a virtual FITS file containing only a primary array image with 32-bit floating point pixels that have a value equal to the square root of the pixels in the image that is in the 3rd extension of the 'myfile.fits' file. \section{Column and Keyword Filtering Specification} The optional column/keyword filtering specifier is used to modify the column structure and/or the header keywords in the HDU that was selected with the previous HDU location specifier. This filtering specifier must be enclosed in square brackets and can be distinguished from a general row filter specifier (described below) by the fact that it begins with the string 'col ' and is not immediately followed by an equals sign. The original file is not changed by this filtering operation, and instead the modifications are made on a copy of the input FITS file (usually in memory), which also contains a copy of all the other HDUs in the file. This temporary file is passed to the application program and will persist only until the file is closed or until the program exits, unless the outfile specifier (see above) is also supplied. The column/keyword filter can be used to perform the following operations. More than one operation may be specified by separating them with commas or semi-colons. \begin{itemize} \item Copy only a specified list of columns columns to the filtered input file. The list of column name should be separated by commas or semi-colons. Wild card characters may be used in the column names to match multiple columns. If the expression contains both a list of columns to be included and columns to be deleted, then all the columns in the original table except the explicitly deleted columns will appear in the filtered table (i.e., there is no need to explicitly list the columns to be included if any columns are being deleted). \item Delete a column or keyword by listing the name preceded by a minus sign or an exclamation mark (!), e.g., '-TIME' will delete the TIME column if it exists, otherwise the TIME keyword. An error is returned if neither a column nor keyword with this name exists. Note that the exclamation point, '!', is a special UNIX character, so if it is used on the command line rather than entered at a task prompt, it must be preceded by a backslash to force the UNIX shell to ignore it. \item Rename an existing column or keyword with the syntax 'NewName == OldName'. An error is returned if neither a column nor keyword with this name exists. \item Append a new column or keyword to the table. To create a column, give the new name, optionally followed by the datatype in parentheses, followed by a single equals sign and an expression to be used to compute the value (e.g., 'newcol(1J) = 0' will create a new 32-bit integer column called 'newcol' filled with zeros). The datatype is specified using the same syntax that is allowed for the value of the FITS TFORMn keyword (e.g., 'I', 'J', 'E', 'D', etc. for binary tables, and 'I8', F12.3', 'E20.12', etc. for ASCII tables). If the datatype is not specified then an appropriate datatype will be chosen depending on the form of the expression (may be a character string, logical, bit, long integer, or double column). An appropriate vector count (in the case of binary tables) will also be added if not explicitly specified. When creating a new keyword, the keyword name must be preceded by a pound sign '\#', and the expression must evaluate to a scalar (i.e., cannot have a column name in the expression). The comment string for the keyword may be specified in parentheses immediately following the keyword name (instead of supplying a datatype as in the case of creating a new column). If the keyword name ends with a pound sign '\#', then cfitsio will substitute the number of the most recently referenced column for the \# character . This is especially useful when writing a column-related keyword like TUNITn for a newly created column, as shown in the following examples. COMMENT and HISTORY keywords may also be created with the following syntax: \begin{verbatim} #COMMENT = 'This is a comment keyword' #HISTORY = 'This is a history keyword' \end{verbatim} Note that the equal sign and the quote characters will be removed, so that the resulting header keywords in these cases will look like this: \begin{verbatim} COMMENT This is a comment keyword HISTORY This is a history keyword \end{verbatim} These two special keywords are always appended to the end of the header and will not affect any previously existing COMMENT or HISTORY keywords. \item Recompute (overwrite) the values in an existing column or keyword by giving the name followed by an equals sign and an arithmetic expression. \end{itemize} The expression that is used when appending or recomputing columns or keywords can be arbitrarily complex and may be a function of other header keyword values and other columns (in the same row). The full syntax and available functions for the expression are described below in the row filter specification section. If the expression contains both a list of columns to be included and columns to be deleted, then all the columns in the original table except the explicitly deleted columns will appear in the filtered table. If no columns to be deleted are specified, then only the columns that are explicitly listed will be included in the filtered output table. To include all the columns, add the '*' wildcard specifier at the end of the list, as shown in the examples. For complex or commonly used operations, one can also place the operations into an external text file and import it into the column filter using the syntax '[col @filename.txt]'. The operations can extend over multiple lines of the file, but multiple operations must still be separated by commas or semi-colons. Any lines in the external text file that begin with 2 slash characters ('//') will be ignored and may be used to add comments into the file. Examples: \begin{verbatim} [col Time, rate] - only the Time and rate columns will appear in the filtered input file. [col Time, *raw] - include the Time column and any other columns whose name ends with 'raw'. [col -TIME; Good == STATUS] - deletes the TIME column and renames the status column to 'Good' [col PI=PHA * 1.1 + 0.2; #TUNIT#(column units) = 'counts';*] - creates new PI column from PHA values and also writes the TUNITn keyword for the new column. The final '*' expression means preserve all the columns in the input table in the virtual output table; without the '*' the output table would only contain the single 'PI' column. [col rate = rate/exposure, TUNIT#(&) = 'counts/s';*] - recomputes the rate column by dividing it by the EXPOSURE keyword value. This also modifies the value of the TUNITn keyword for this column. The use of the '&' character for the keyword comment string means preserve the existing comment string for that keyword. The final '*' preserves all the columns in the input table in the virtual output table. \end{verbatim} \section{Row Filtering Specification} When entering the name of a FITS table that is to be opened by a program, an optional row filter may be specified to select a subset of the rows in the table. A temporary new FITS file is created on the fly which contains only those rows for which the row filter expression evaluates to true. (The primary array and any other extensions in the input file are also copied to the temporary file). The original FITS file is closed and the new virtual file is opened by the application program. The row filter expression is enclosed in square brackets following the file name and extension name (e.g., 'file.fits[events][GRADE==50]' selects only those rows where the GRADE column value equals 50). When dealing with tables where each row has an associated time and/or 2D spatial position, the row filter expression can also be used to select rows based on the times in a Good Time Intervals (GTI) extension, or on spatial position as given in a SAO-style region file. \subsection{General Syntax} The row filtering expression can be an arbitrarily complex series of operations performed on constants, keyword values, and column data taken from the specified FITS TABLE extension. The expression must evaluate to a boolean value for each row of the table, where a value of FALSE means that the row will be excluded. For complex or commonly used filters, one can place the expression into a text file and import it into the row filter using the syntax '[@filename.txt]'. The expression can be arbitrarily complex and extend over multiple lines of the file. Any lines in the external text file that begin with 2 slash characters ('//') will be ignored and may be used to add comments into the file. Keyword and column data are referenced by name. Any string of characters not surrounded by quotes (ie, a constant string) or followed by an open parentheses (ie, a function name) will be initially interpreted as a column name and its contents for the current row inserted into the expression. If no such column exists, a keyword of that name will be searched for and its value used, if found. To force the name to be interpreted as a keyword (in case there is both a column and keyword with the same name), precede the keyword name with a single pound sign, '\#', as in '\#NAXIS2'. Due to the generalities of FITS column and keyword names, if the column or keyword name contains a space or a character which might appear as an arithmetic term then enclose the name in '\$' characters as in \$MAX PHA\$ or \#\$MAX-PHA\$. Names are case insensitive. To access a table entry in a row other than the current one, follow the column's name with a row offset within curly braces. For example, 'PHA\{-3\}' will evaluate to the value of column PHA, 3 rows above the row currently being processed. One cannot specify an absolute row number, only a relative offset. Rows that fall outside the table will be treated as undefined, or NULLs. Boolean operators can be used in the expression in either their Fortran or C forms. The following boolean operators are available: \begin{verbatim} "equal" .eq. .EQ. == "not equal" .ne. .NE. != "less than" .lt. .LT. < "less than/equal" .le. .LE. <= =< "greater than" .gt. .GT. > "greater than/equal" .ge. .GE. >= => "or" .or. .OR. || "and" .and. .AND. && "negation" .not. .NOT. ! "approx. equal(1e-7)" ~ \end{verbatim} Note that the exclamation point, '!', is a special UNIX character, so if it is used on the command line rather than entered at a task prompt, it must be preceded by a backslash to force the UNIX shell to ignore it. The expression may also include arithmetic operators and functions. Trigonometric functions use radians, not degrees. The following arithmetic operators and functions can be used in the expression (function names are case insensitive). A null value will be returned in case of illegal operations such as divide by zero, sqrt(negative) log(negative), log10(negative), arccos(.gt. 1), arcsin(.gt. 1). \begin{verbatim} "addition" + "subtraction" - "multiplication" * "division" / "negation" - "exponentiation" ** ^ "absolute value" abs(x) "cosine" cos(x) "sine" sin(x) "tangent" tan(x) "arc cosine" arccos(x) "arc sine" arcsin(x) "arc tangent" arctan(x) "arc tangent" arctan2(y,x) "hyperbolic cos" cosh(x) "hyperbolic sin" sinh(x) "hyperbolic tan" tanh(x) "round to nearest int" round(x) "round down to int" floor(x) "round up to int" ceil(x) "exponential" exp(x) "square root" sqrt(x) "natural log" log(x) "common log" log10(x) "modulus" x % y "random # [0.0,1.0)" random() "random Gaussian" randomn() "random Poisson" randomp(x) "minimum" min(x,y) "maximum" max(x,y) "cumulative sum" accum(x) "sequential difference" seqdiff(x) "if-then-else" b?x:y "angular separation" angsep(ra1,dec1,ra2,de2) (all in degrees) "substring" strmid(s,p,n) "string search" strstr(s,r) \end{verbatim} Three different random number functions are provided: random(), with no arguments, produces a uniform random deviate between 0 and 1; randomn(), also with no arguments, produces a normal (Gaussian) random deviate with zero mean and unit standard deviation; randomp(x) produces a Poisson random deviate whose expected number of counts is X. X may be any positive real number of expected counts, including fractional values, but the return value is an integer. When the random functions are used in a vector expression, by default the same random value will be used when evaluating each element of the vector. If different random numbers are desired, then the name of a vector column should be supplied as the single argument to the random function (e.g., "flux + 0.1 * random(flux)", where "flux' is the name of a vector column). This will create a vector of random numbers that will be used in sequence when evaluating each element of the vector expression. An alternate syntax for the min and max functions has only a single argument which should be a vector value (see below). The result will be the minimum/maximum element contained within the vector. The accum(x) function forms the cumulative sum of x, element by element. Vector columns are supported simply by performing the summation process through all the values. Null values are treated as 0. The seqdiff(x) function forms the sequential difference of x, element by element. The first value of seqdiff is the first value of x. A single null value in x causes a pair of nulls in the output. The seqdiff and accum functions are functional inverses, i.e., seqdiff(accum(x)) == x as long as no null values are present. In the if-then-else expression, "b?x:y", b is an explicit boolean value or expression. There is no automatic type conversion from numeric to boolean values, so one needs to use "iVal!=0" instead of merely "iVal" as the boolean argument. x and y can be any scalar data type (including string). The angsep function computes the angular separation in degrees between 2 celestial positions, where the first 2 parameters give the RA-like and Dec-like coordinates (in decimal degrees) of the first position, and the 3rd and 4th parameters give the coordinates of the second position. The substring function strmid(S,P,N) extracts a substring from S, starting at string position P, with a substring length N. The first character position in S is labeled as 1. If P is 0, or refers to a position beyond the end of S, then the extracted substring will be NULL. S, P, and N may be functions of other columns. The string search function strstr(S,R) searches for the first occurrence of the substring R in S. The result is an integer, indicating the character position of the first match (where 1 is the first character position of S). If no match is found, then strstr() returns a NULL value. The following type casting operators are available, where the enclosing parentheses are required and taken from the C language usage. Also, the integer to real casts values to double precision: \begin{verbatim} "real to integer" (int) x (INT) x "integer to real" (float) i (FLOAT) i \end{verbatim} In addition, several constants are built in for use in numerical expressions: \begin{verbatim} #pi 3.1415... #e 2.7182... #deg #pi/180 #row current row number #null undefined value #snull undefined string \end{verbatim} A string constant must be enclosed in quotes as in 'Crab'. The "null" constants are useful for conditionally setting table values to a NULL, or undefined, value (eg., "col1==-99 ? \#NULL : col1"). There is also a function for testing if two values are close to each other, i.e., if they are "near" each other to within a user specified tolerance. The arguments, value\_1 and value\_2 can be integer or real and represent the two values who's proximity is being tested to be within the specified tolerance, also an integer or real: \begin{verbatim} near(value_1, value_2, tolerance) \end{verbatim} When a NULL, or undefined, value is encountered in the FITS table, the expression will evaluate to NULL unless the undefined value is not actually required for evaluation, e.g. "TRUE .or. NULL" evaluates to TRUE. The following two functions allow some NULL detection and handling: \begin{verbatim} "a null value?" ISNULL(x) "define a value for null" DEFNULL(x,y) \end{verbatim} The former returns a boolean value of TRUE if the argument x is NULL. The later "defines" a value to be substituted for NULL values; it returns the value of x if x is not NULL, otherwise it returns the value of y. \subsection{Bit Masks} Bit masks can be used to select out rows from bit columns (TFORMn = \#X) in FITS files. To represent the mask, binary, octal, and hex formats are allowed: \begin{verbatim} binary: b0110xx1010000101xxxx0001 octal: o720x1 -> (b111010000xxx001) hex: h0FxD -> (b00001111xxxx1101) \end{verbatim} In all the representations, an x or X is allowed in the mask as a wild card. Note that the x represents a different number of wild card bits in each representation. All representations are case insensitive. To construct the boolean expression using the mask as the boolean equal operator described above on a bit table column. For example, if you had a 7 bit column named flags in a FITS table and wanted all rows having the bit pattern 0010011, the selection expression would be: \begin{verbatim} flags == b0010011 or flags .eq. b10011 \end{verbatim} It is also possible to test if a range of bits is less than, less than equal, greater than and greater than equal to a particular boolean value: \begin{verbatim} flags <= bxxx010xx flags .gt. bxxx100xx flags .le. b1xxxxxxx \end{verbatim} Notice the use of the x bit value to limit the range of bits being compared. It is not necessary to specify the leading (most significant) zero (0) bits in the mask, as shown in the second expression above. Bit wise AND, OR and NOT operations are also possible on two or more bit fields using the '\&'(AND), '$|$'(OR), and the '!'(NOT) operators. All of these operators result in a bit field which can then be used with the equal operator. For example: \begin{verbatim} (!flags) == b1101100 (flags & b1000001) == bx000001 \end{verbatim} Bit fields can be appended as well using the '+' operator. Strings can be concatenated this way, too. \subsection{Vector Columns} Vector columns can also be used in building the expression. No special syntax is required if one wants to operate on all elements of the vector. Simply use the column name as for a scalar column. Vector columns can be freely intermixed with scalar columns or constants in virtually all expressions. The result will be of the same dimension as the vector. Two vectors in an expression, though, need to have the same number of elements and have the same dimensions. The only places a vector column cannot be used (for now, anyway) are the SAO region functions and the NEAR boolean function. Arithmetic and logical operations are all performed on an element by element basis. Comparing two vector columns, eg "COL1 == COL2", thus results in another vector of boolean values indicating which elements of the two vectors are equal. Eight functions are available that operate on a vector and return a scalar result: \begin{verbatim} "minimum" MIN(V) "maximum" MAX(V) "average" AVERAGE(V) "median" MEDIAN(V) "summation" SUM(V) "standard deviation" STDDEV(V) "# of values" NELEM(V) "# of non-null values" NVALID(V) \end{verbatim} where V represents the name of a vector column or a manually constructed vector using curly brackets as described below. The first 6 of these functions ignore any null values in the vector when computing the result. The STDDEV() function computes the sample standard deviation, i.e. it is proportional to 1/SQRT(N-1) instead of 1/SQRT(N), where N is NVALID(V). The SUM function literally sums all the elements in x, returning a scalar value. If x is a boolean vector, SUM returns the number of TRUE elements. The NELEM function returns the number of elements in vector x whereas NVALID return the number of non-null elements in the vector. (NELEM also operates on bit and string columns, returning their column widths.) As an example, to test whether all elements of two vectors satisfy a given logical comparison, one can use the expression \begin{verbatim} SUM( COL1 > COL2 ) == NELEM( COL1 ) \end{verbatim} which will return TRUE if all elements of COL1 are greater than their corresponding elements in COL2. To specify a single element of a vector, give the column name followed by a comma-separated list of coordinates enclosed in square brackets. For example, if a vector column named PHAS exists in the table as a one dimensional, 256 component list of numbers from which you wanted to select the 57th component for use in the expression, then PHAS[57] would do the trick. Higher dimensional arrays of data may appear in a column. But in order to interpret them, the TDIMn keyword must appear in the header. Assuming that a (4,4,4,4) array is packed into each row of a column named ARRAY4D, the (1,2,3,4) component element of each row is accessed by ARRAY4D[1,2,3,4]. Arrays up to dimension 5 are currently supported. Each vector index can itself be an expression, although it must evaluate to an integer value within the bounds of the vector. Vector columns which contain spaces or arithmetic operators must have their names enclosed in "\$" characters as with \$ARRAY-4D\$[1,2,3,4]. A more C-like syntax for specifying vector indices is also available. The element used in the preceding example alternatively could be specified with the syntax ARRAY4D[4][3][2][1]. Note the reverse order of indices (as in C), as well as the fact that the values are still ones-based (as in Fortran -- adopted to avoid ambiguity for 1D vectors). With this syntax, one does not need to specify all of the indices. To extract a 3D slice of this 4D array, use ARRAY4D[4]. Variable-length vector columns are not supported. Vectors can be manually constructed within the expression using a comma-separated list of elements surrounded by curly braces ('\{\}'). For example, '\{1,3,6,1\}' is a 4-element vector containing the values 1, 3, 6, and 1. The vector can contain only boolean, integer, and real values (or expressions). The elements will be promoted to the highest datatype present. Any elements which are themselves vectors, will be expanded out with each of its elements becoming an element in the constructed vector. \subsection{Good Time Interval Filtering} A common filtering method involves selecting rows which have a time value which lies within what is called a Good Time Interval or GTI. The time intervals are defined in a separate FITS table extension which contains 2 columns giving the start and stop time of each good interval. The filtering operation accepts only those rows of the input table which have an associated time which falls within one of the time intervals defined in the GTI extension. A high level function, gtifilter(a,b,c,d), is available which evaluates each row of the input table and returns TRUE or FALSE depending whether the row is inside or outside the good time interval. The syntax is \begin{verbatim} gtifilter( [ "gtifile" [, expr [, "STARTCOL", "STOPCOL" ] ] ] ) \end{verbatim} where each "[]" demarks optional parameters. Note that the quotes around the gtifile and START/STOP column are required. Either single or double quotes may be used. In cases where this expression is entered on the Unix command line, enclose the entire expression in double quotes, and then use single quotes within the expression to enclose the 'gtifile' and other terms. It is also usually possible to do the reverse, and enclose the whole expression in single quotes and then use double quotes within the expression. The gtifile, if specified, can be blank ("") which will mean to use the first extension with the name "*GTI*" in the current file, a plain extension specifier (eg, "+2", "[2]", or "[STDGTI]") which will be used to select an extension in the current file, or a regular filename with or without an extension specifier which in the latter case will mean to use the first extension with an extension name "*GTI*". Expr can be any arithmetic expression, including simply the time column name. A vector time expression will produce a vector boolean result. STARTCOL and STOPCOL are the names of the START/STOP columns in the GTI extension. If one of them is specified, they both must be. In its simplest form, no parameters need to be provided -- default values will be used. The expression "gtifilter()" is equivalent to \begin{verbatim} gtifilter( "", TIME, "*START*", "*STOP*" ) \end{verbatim} This will search the current file for a GTI extension, filter the TIME column in the current table, using START/STOP times taken from columns in the GTI extension with names containing the strings "START" and "STOP". The wildcards ('*') allow slight variations in naming conventions such as "TSTART" or "STARTTIME". The same default values apply for unspecified parameters when the first one or two parameters are specified. The function automatically searches for TIMEZERO/I/F keywords in the current and GTI extensions, applying a relative time offset, if necessary. \subsection{Spatial Region Filtering} Another common filtering method selects rows based on whether the spatial position associated with each row is located within a given 2-dimensional region. The syntax for this high-level filter is \begin{verbatim} regfilter( "regfilename" [ , Xexpr, Yexpr [ , "wcs cols" ] ] ) \end{verbatim} where each "[]" demarks optional parameters. The region file name is required and must be enclosed in quotes. The remaining parameters are optional. There are 2 supported formats for the region file: ASCII file or FITS binary table. The region file contains a list of one or more geometric shapes (circle, ellipse, box, etc.) which defines a region on the celestial sphere or an area within a particular 2D image. The region file is typically generated using an image display program such as fv/POW (distribute by the HEASARC), or ds9 (distributed by the Smithsonian Astrophysical Observatory). Users should refer to the documentation provided with these programs for more details on the syntax used in the region files. The FITS region file format is defined in a document available from the FITS Support Office at http://fits.gsfc.nasa.gov/ registry/ region.html In its simplest form, (e.g., regfilter("region.reg") ) the coordinates in the default 'X' and 'Y' columns will be used to determine if each row is inside or outside the area specified in the region file. Alternate position column names, or expressions, may be entered if needed, as in \begin{verbatim} regfilter("region.reg", XPOS, YPOS) \end{verbatim} Region filtering can be applied most unambiguously if the positions in the region file and in the table to be filtered are both give in terms of absolute celestial coordinate units. In this case the locations and sizes of the geometric shapes in the region file are specified in angular units on the sky (e.g., positions given in R.A. and Dec. and sizes in arcseconds or arcminutes). Similarly, each row of the filtered table will have a celestial coordinate associated with it. This association is usually implemented using a set of so-called 'World Coordinate System' (or WCS) FITS keywords that define the coordinate transformation that must be applied to the values in the 'X' and 'Y' columns to calculate the coordinate. Alternatively, one can perform spatial filtering using unitless 'pixel' coordinates for the regions and row positions. In this case the user must be careful to ensure that the positions in the 2 files are self-consistent. A typical problem is that the region file may be generated using a binned image, but the unbinned coordinates are given in the event table. The ROSAT events files, for example, have X and Y pixel coordinates that range from 1 - 15360. These coordinates are typically binned by a factor of 32 to produce a 480x480 pixel image. If one then uses a region file generated from this image (in image pixel units) to filter the ROSAT events file, then the X and Y column values must be converted to corresponding pixel units as in: \begin{verbatim} regfilter("rosat.reg", X/32.+.5, Y/32.+.5) \end{verbatim} Note that this binning conversion is not necessary if the region file is specified using celestial coordinate units instead of pixel units because CFITSIO is then able to directly compare the celestial coordinate of each row in the table with the celestial coordinates in the region file without having to know anything about how the image may have been binned. The last "wcs cols" parameter should rarely be needed. If supplied, this string contains the names of the 2 columns (space or comma separated) which have the associated WCS keywords. If not supplied, the filter will scan the X and Y expressions for column names. If only one is found in each expression, those columns will be used, otherwise an error will be returned. These region shapes are supported (names are case insensitive): \begin{verbatim} Point ( X1, Y1 ) <- One pixel square region Line ( X1, Y1, X2, Y2 ) <- One pixel wide region Polygon ( X1, Y1, X2, Y2, ... ) <- Rest are interiors with Rectangle ( X1, Y1, X2, Y2, A ) | boundaries considered Box ( Xc, Yc, Wdth, Hght, A ) V within the region Diamond ( Xc, Yc, Wdth, Hght, A ) Circle ( Xc, Yc, R ) Annulus ( Xc, Yc, Rin, Rout ) Ellipse ( Xc, Yc, Rx, Ry, A ) Elliptannulus ( Xc, Yc, Rinx, Riny, Routx, Routy, Ain, Aout ) Sector ( Xc, Yc, Amin, Amax ) \end{verbatim} where (Xc,Yc) is the coordinate of the shape's center; (X\#,Y\#) are the coordinates of the shape's edges; Rxxx are the shapes' various Radii or semi-major/minor axes; and Axxx are the angles of rotation (or bounding angles for Sector) in degrees. For rotated shapes, the rotation angle can be left off, indicating no rotation. Common alternate names for the regions can also be used: rotbox = box; rotrectangle = rectangle; (rot)rhombus = (rot)diamond; and pie = sector. When a shape's name is preceded by a minus sign, '-', the defined region is instead the area *outside* its boundary (ie, the region is inverted). All the shapes within a single region file are OR'd together to create the region, and the order is significant. The overall way of looking at region files is that if the first region is an excluded region then a dummy included region of the whole detector is inserted in the front. Then each region specification as it is processed overrides any selections inside of that region specified by previous regions. Another way of thinking about this is that if a previous excluded region is completely inside of a subsequent included region the excluded region is ignored. The positional coordinates may be given either in pixel units, decimal degrees or hh:mm:ss.s, dd:mm:ss.s units. The shape sizes may be given in pixels, degrees, arcminutes, or arcseconds. Look at examples of region file produced by fv/POW or ds9 for further details of the region file format. There are three functions that are primarily for use with SAO region files and the FSAOI task, but they can be used directly. They return a boolean true or false depending on whether a two dimensional point is in the region or not: \begin{verbatim} "point in a circular region" circle(xcntr,ycntr,radius,Xcolumn,Ycolumn) "point in an elliptical region" ellipse(xcntr,ycntr,xhlf_wdth,yhlf_wdth,rotation,Xcolumn,Ycolumn) "point in a rectangular region" box(xcntr,ycntr,xfll_wdth,yfll_wdth,rotation,Xcolumn,Ycolumn) where (xcntr,ycntr) are the (x,y) position of the center of the region (xhlf_wdth,yhlf_wdth) are the (x,y) half widths of the region (xfll_wdth,yfll_wdth) are the (x,y) full widths of the region (radius) is half the diameter of the circle (rotation) is the angle(degrees) that the region is rotated with respect to (xcntr,ycntr) (Xcoord,Ycoord) are the (x,y) coordinates to test, usually column names NOTE: each parameter can itself be an expression, not merely a column name or constant. \end{verbatim} \subsection{Example Row Filters} \begin{verbatim} [ binary && mag <= 5.0] - Extract all binary stars brighter than fifth magnitude (note that the initial space is necessary to prevent it from being treated as a binning specification) [#row >= 125 && #row <= 175] - Extract row numbers 125 through 175 [IMAGE[4,5] .gt. 100] - Extract all rows that have the (4,5) component of the IMAGE column greater than 100 [abs(sin(theta * #deg)) < 0.5] - Extract all rows having the absolute value of the sine of theta less than a half where the angles are tabulated in degrees [SUM( SPEC > 3*BACKGRND )>=1] - Extract all rows containing a spectrum, held in vector column SPEC, with at least one value 3 times greater than the background level held in a keyword, BACKGRND [VCOL=={1,4,2}] - Extract all rows whose vector column VCOL contains the 3-elements 1, 4, and 2. [@rowFilter.txt] - Extract rows using the expression contained within the text file rowFilter.txt [gtifilter()] - Search the current file for a GTI extension, filter the TIME column in the current table, using START/STOP times taken from columns in the GTI extension [regfilter("pow.reg")] - Extract rows which have a coordinate (as given in the X and Y columns) within the spatial region specified in the pow.reg region file. [regfilter("pow.reg", Xs, Ys)] - Same as above, except that the Xs and Ys columns will be used to determine the coordinate of each row in the table. \end{verbatim} \section{ Binning or Histogramming Specification} The optional binning specifier is enclosed in square brackets and can be distinguished from a general row filter specification by the fact that it begins with the keyword 'bin' not immediately followed by an equals sign. When binning is specified, a temporary N-dimensional FITS primary array is created by computing the histogram of the values in the specified columns of a FITS table extension. After the histogram is computed the input FITS file containing the table is then closed and the temporary FITS primary array is opened and passed to the application program. Thus, the application program never sees the original FITS table and only sees the image in the new temporary file (which has no additional extensions). Obviously, the application program must be expecting to open a FITS image and not a FITS table in this case. The data type of the FITS histogram image may be specified by appending 'b' (for 8-bit byte), 'i' (for 16-bit integers), 'j' (for 32-bit integer), 'r' (for 32-bit floating points), or 'd' (for 64-bit double precision floating point) to the 'bin' keyword (e.g. '[binr X]' creates a real floating point image). If the datatype is not explicitly specified then a 32-bit integer image will be created by default, unless the weighting option is also specified in which case the image will have a 32-bit floating point data type by default. The histogram image may have from 1 to 4 dimensions (axes), depending on the number of columns that are specified. The general form of the binning specification is: \begin{verbatim} [bin{bijrd} Xcol=min:max:binsize, Ycol= ..., Zcol=..., Tcol=...; weight] \end{verbatim} in which up to 4 columns, each corresponding to an axis of the image, are listed. The column names are case insensitive, and the column number may be given instead of the name, preceded by a pound sign (e.g., [bin \#4=1:512]). If the column name is not specified, then CFITSIO will first try to use the 'preferred column' as specified by the CPREF keyword if it exists (e.g., 'CPREF = 'DETX,DETY'), otherwise column names 'X', 'Y', 'Z', and 'T' will be assumed for each of the 4 axes, respectively. In cases where the column name could be confused with an arithmetic expression, enclose the column name in parentheses to force the name to be interpreted literally. Each column name may be followed by an equals sign and then the lower and upper range of the histogram, and the size of the histogram bins, separated by colons. Spaces are allowed before and after the equals sign but not within the 'min:max:binsize' string. The min, max and binsize values may be integer or floating point numbers, or they may be the names of keywords in the header of the table. If the latter, then the value of that keyword is substituted into the expression. Default values for the min, max and binsize quantities will be used if not explicitly given in the binning expression as shown in these examples: \begin{verbatim} [bin x = :512:2] - use default minimum value [bin x = 1::2] - use default maximum value [bin x = 1:512] - use default bin size [bin x = 1:] - use default maximum value and bin size [bin x = :512] - use default minimum value and bin size [bin x = 2] - use default minimum and maximum values [bin x] - use default minimum, maximum and bin size [bin 4] - default 2-D image, bin size = 4 in both axes [bin] - default 2-D image \end{verbatim} CFITSIO will use the value of the TLMINn, TLMAXn, and TDBINn keywords, if they exist, for the default min, max, and binsize, respectively. If they do not exist then CFITSIO will use the actual minimum and maximum values in the column for the histogram min and max values. The default binsize will be set to 1, or (max - min) / 10., whichever is smaller, so that the histogram will have at least 10 bins along each axis. A shortcut notation is allowed if all the columns/axes have the same binning specification. In this case all the column names may be listed within parentheses, followed by the (single) binning specification, as in: \begin{verbatim} [bin (X,Y)=1:512:2] [bin (X,Y) = 5] \end{verbatim} The optional weighting factor is the last item in the binning specifier and, if present, is separated from the list of columns by a semi-colon. As the histogram is accumulated, this weight is used to incremented the value of the appropriated bin in the histogram. If the weighting factor is not specified, then the default weight = 1 is assumed. The weighting factor may be a constant integer or floating point number, or the name of a keyword containing the weighting value. Or the weighting factor may be the name of a table column in which case the value in that column, on a row by row basis, will be used. In some cases, the column or keyword may give the reciprocal of the actual weight value that is needed. In this case, precede the weight keyword or column name by a slash '/' to tell CFITSIO to use the reciprocal of the value when constructing the histogram. For complex or commonly used histograms, one can also place its description into a text file and import it into the binning specification using the syntax '[bin @filename.txt]'. The file's contents can extend over multiple lines, although it must still conform to the no-spaces rule for the min:max:binsize syntax and each axis specification must still be comma-separated. Any lines in the external text file that begin with 2 slash characters ('//') will be ignored and may be used to add comments into the file. Examples: \begin{verbatim} [bini detx, dety] - 2-D, 16-bit integer histogram of DETX and DETY columns, using default values for the histogram range and binsize [bin (detx, dety)=16; /exposure] - 2-D, 32-bit real histogram of DETX and DETY columns with a bin size = 16 in both axes. The histogram values are divided by the EXPOSURE keyword value. [bin time=TSTART:TSTOP:0.1] - 1-D lightcurve, range determined by the TSTART and TSTOP keywords, with 0.1 unit size bins. [bin pha, time=8000.:8100.:0.1] - 2-D image using default binning of the PHA column for the X axis, and 1000 bins in the range 8000. to 8100. for the Y axis. [bin @binFilter.txt] - Use the contents of the text file binFilter.txt for the binning specifications. \end{verbatim} \chapter{Template Files } When a new FITS file is created with a call to fits\_create\_file, the name of a template file may be supplied in parentheses immediately following the name of the new file to be created. This template is used to define the structure of one or more HDUs in the new file. The template file may be another FITS file, in which case the newly created file will have exactly the same keywords in each HDU as in the template FITS file, but all the data units will be filled with zeros. The template file may also be an ASCII text file, where each line (in general) describes one FITS keyword record. The format of the ASCII template file is described in the following sections. \section{Detailed Template Line Format} The format of each ASCII template line closely follows the format of a FITS keyword record: \begin{verbatim} KEYWORD = KEYVALUE / COMMENT \end{verbatim} except that free format may be used (e.g., the equals sign may appear at any position in the line) and TAB characters are allowed and are treated the same as space characters. The KEYVALUE and COMMENT fields are optional. The equals sign character is also optional, but it is recommended that it be included for clarity. Any template line that begins with the pound '\#' character is ignored by the template parser and may be use to insert comments into the template file itself. The KEYWORD name field is limited to 8 characters in length and only the letters A-Z, digits 0-9, and the hyphen and underscore characters may be used, without any embedded spaces. Lowercase letters in the template keyword name will be converted to uppercase. Leading spaces in the template line preceding the keyword name are generally ignored, except if the first 8 characters of a template line are all blank, then the entire line is treated as a FITS comment keyword (with a blank keyword name) and is copied verbatim into the FITS header. The KEYVALUE field may have any allowed FITS data type: character string, logical, integer, real, complex integer, or complex real. Integer values must be within the allowed range of a 'signed long' variable; some C compilers only suppport 4-byte long integers with a range from -2147483648 to +2147483647, whereas other C compilers support 8-byte integers with a range of plus or minus 2**63. The character string values need not be enclosed in single quote characters unless they are necessary to distinguish the string from a different data type (e.g. 2.0 is a real but '2.0' is a string). The keyword has an undefined (null) value if the template record only contains blanks following the "=" or between the "=" and the "/" comment field delimiter. String keyword values longer than 68 characters (the maximum length that will fit in a single FITS keyword record) are permitted using the CFITSIO long string convention. They can either be specified as a single long line in the template, or by using multiple lines where the continuing lines contain the 'CONTINUE' keyword, as in this example: \begin{verbatim} LONGKEY = 'This is a long string value that is contin&' CONTINUE 'ued over 2 records' / comment field goes here \end{verbatim} The format of template lines with CONTINUE keyword is very strict: 3 spaces must follow CONTINUE and the rest of the line is copied verbatim to the FITS file. The start of the optional COMMENT field must be preceded by "/", which is used to separate it from the keyword value field. Exceptions are if the KEYWORD name field contains COMMENT, HISTORY, CONTINUE, or if the first 8 characters of the template line are blanks. More than one Header-Data Unit (HDU) may be defined in the template file. The start of an HDU definition is denoted with a SIMPLE or XTENSION template line: 1) SIMPLE begins a Primary HDU definition. SIMPLE may only appear as the first keyword in the template file. If the template file begins with XTENSION instead of SIMPLE, then a default empty Primary HDU is created, and the template is then assumed to define the keywords starting with the first extension following the Primary HDU. 2) XTENSION marks the beginning of a new extension HDU definition. The previous HDU will be closed at this point and processing of the next extension begins. \section{Auto-indexing of Keywords} If a template keyword name ends with a "\#" character, it is said to be 'auto-indexed'. Each "\#" character will be replaced by the current integer index value, which gets reset = 1 at the start of each new HDU in the file (or 7 in the special case of a GROUP definition). The FIRST indexed keyword in each template HDU definition is used as the 'incrementor'; each subsequent occurrence of this SAME keyword will cause the index value to be incremented. This behavior can be rather subtle, as illustrated in the following examples in which the TTYPE keyword is the incrementor in both cases: \begin{verbatim} TTYPE# = TIME TFORM# = 1D TTYPE# = RATE TFORM# = 1E \end{verbatim} will create TTYPE1, TFORM1, TTYPE2, and TFORM2 keywords. But if the template looks like, \begin{verbatim} TTYPE# = TIME TTYPE# = RATE TFORM# = 1D TFORM# = 1E \end{verbatim} this results in a FITS files with TTYPE1, TTYPE2, TFORM2, and TFORM2, which is probably not what was intended! \section{Template Parser Directives} In addition to the template lines which define individual keywords, the template parser recognizes 3 special directives which are each preceded by the backslash character: \verb+ \include, \group+, and \verb+ \end+. The 'include' directive must be followed by a filename. It forces the parser to temporarily stop reading the current template file and begin reading the include file. Once the parser reaches the end of the include file it continues parsing the current template file. Include files can be nested, and HDU definitions can span multiple template files. The start of a GROUP definition is denoted with the 'group' directive, and the end of a GROUP definition is denoted with the 'end' directive. Each GROUP contains 0 or more member blocks (HDUs or GROUPs). Member blocks of type GROUP can contain their own member blocks. The GROUP definition itself occupies one FITS file HDU of special type (GROUP HDU), so if a template specifies 1 group with 1 member HDU like: \begin{verbatim} \group grpdescr = 'demo' xtension bintable # this bintable has 0 cols, 0 rows \end \end{verbatim} then the parser creates a FITS file with 3 HDUs : \begin{verbatim} 1) dummy PHDU 2) GROUP HDU (has 1 member, which is bintable in HDU number 3) 3) bintable (member of GROUP in HDU number 2) \end{verbatim} Technically speaking, the GROUP HDU is a BINTABLE with 6 columns. Applications can define additional columns in a GROUP HDU using TFORMn and TTYPEn (where n is 7, 8, ....) keywords or their auto-indexing equivalents. For a more complicated example of a template file using the group directives, look at the sample.tpl file that is included in the CFITSIO distribution. \section{Formal Template Syntax} The template syntax can formally be defined as follows: \begin{verbatim} TEMPLATE = BLOCK [ BLOCK ... ] BLOCK = { HDU | GROUP } GROUP = \GROUP [ BLOCK ... ] \END HDU = XTENSION [ LINE ... ] { XTENSION | \GROUP | \END | EOF } LINE = [ KEYWORD [ = ] ] [ VALUE ] [ / COMMENT ] X ... - X can be present 1 or more times { X | Y } - X or Y [ X ] - X is optional \end{verbatim} At the topmost level, the template defines 1 or more template blocks. Blocks can be either HDU (Header Data Unit) or a GROUP. For each block the parser creates 1 (or more for GROUPs) FITS file HDUs. \section{Errors} In general the fits\_execute\_template() function tries to be as atomic as possible, so either everything is done or nothing is done. If an error occurs during parsing of the template, fits\_execute\_template() will (try to) delete the top level BLOCK (with all its children if any) in which the error occurred, then it will stop reading the template file and it will return with an error. \section{Examples} 1. This template file will create a 200 x 300 pixel image, with 4-byte integer pixel values, in the primary HDU: \begin{verbatim} SIMPLE = T BITPIX = 32 NAXIS = 2 / number of dimensions NAXIS1 = 100 / length of first axis NAXIS2 = 200 / length of second axis OBJECT = NGC 253 / name of observed object \end{verbatim} The allowed values of BITPIX are 8, 16, 32, -32, or -64, representing, respectively, 8-bit integer, 16-bit integer, 32-bit integer, 32-bit floating point, or 64 bit floating point pixels. 2. To create a FITS table, the template first needs to include XTENSION = TABLE or BINTABLE to define whether it is an ASCII or binary table, and NAXIS2 to define the number of rows in the table. Two template lines are then needed to define the name (TTYPEn) and FITS data format (TFORMn) of the columns, as in this example: \begin{verbatim} xtension = bintable naxis2 = 40 ttype# = Name tform# = 10a ttype# = Npoints tform# = j ttype# = Rate tunit# = counts/s tform# = e \end{verbatim} The above example defines a null primary array followed by a 40-row binary table extension with 3 columns called 'Name', 'Npoints', and 'Rate', with data formats of '10A' (ASCII character string), '1J' (integer) and '1E' (floating point), respectively. Note that the other required FITS keywords (BITPIX, NAXIS, NAXIS1, PCOUNT, GCOUNT, TFIELDS, and END) do not need to be explicitly defined in the template because their values can be inferred from the other keywords in the template. This example also illustrates that the templates are generally case-insensitive (the keyword names and TFORMn values are converted to upper-case in the FITS file) and that string keyword values generally do not need to be enclosed in quotes. \chapter{ Summary of all FITSIO User-Interface Subroutines } Error Status Routines page~\pageref{FTVERS} \begin{verbatim} FTVERS( > version) FTGERR(status, > errtext) FTGMSG( > errmsg) FTRPRT (stream, > status) FTPMSG(errmsg) FTPMRK FTCMSG FTCMRK \end{verbatim} FITS File Open and Close Subroutines: page~\pageref{FTOPEN} \begin{verbatim} FTOPEN(unit,filename,rwmode, > blocksize,status) FTDKOPN(unit,filename,rwmode, > blocksize,status) FTNOPN(unit,filename,rwmode, > status) FTDOPN(unit,filename,rwmode, > status) FTTOPN(unit,filename,rwmode, > status) FTIOPN(unit,filename,rwmode, > status) FTREOPEN(unit, > newunit, status) FTINIT(unit,filename,blocksize, > status) FTDKINIT(unit,filename,blocksize, > status) FTTPLT(unit, filename, tplfilename, > status) FTFLUS(unit, > status) FTCLOS(unit, > status) FTDELT(unit, > status) FTGIOU( > iounit, status) FTFIOU(iounit, > status) CFITS2Unit(fitsfile *ptr) (C routine) CUnit2FITS(int unit) (C routine) FTEXTN(filename, > nhdu, status) FTFLNM(unit, > filename, status) FTFLMD(unit, > iomode, status) FTURLT(unit, > urltype, status) FTIURL(filename, > filetype, infile, outfile, extspec, filter, binspec, colspec, status) FTRTNM(filename, > rootname, status) FTEXIST(filename, > exist, status) \end{verbatim} HDU-Level Operations: page~\pageref{FTMAHD} \begin{verbatim} FTMAHD(unit,nhdu, > hdutype,status) FTMRHD(unit,nmove, > hdutype,status) FTGHDN(unit, > nhdu) FTMNHD(unit, hdutype, extname, extver, > status) FTGHDT(unit, > hdutype, status) FTTHDU(unit, > hdunum, status) FTCRHD(unit, > status) FTIIMG(unit,bitpix,naxis,naxes, > status) FTITAB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > status) FTIBIN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat > status) FTRSIM(unit,bitpix,naxis,naxes,status) FTDHDU(unit, > hdutype,status) FTCPFL(iunit,ounit,previous, current, following, > status) FTCOPY(iunit,ounit,morekeys, > status) FTCPHD(inunit, outunit, > status) FTCPDT(iunit,ounit, > status) \end{verbatim} Subroutines to specify or modify the structure of the CHDU: page~\pageref{FTRDEF} \begin{verbatim} FTRDEF(unit, > status) (DEPRECATED) FTPDEF(unit,bitpix,naxis,naxes,pcount,gcount, > status) (DEPRECATED) FTADEF(unit,rowlen,tfields,tbcol,tform,nrows > status) (DEPRECATED) FTBDEF(unit,tfields,tform,varidat,nrows > status) (DEPRECATED) FTDDEF(unit,bytlen, > status) (DEPRECATED) FTPTHP(unit,theap, > status) \end{verbatim} Header Space and Position Subroutines: page~\pageref{FTHDEF} \begin{verbatim} FTHDEF(unit,morekeys, > status) FTGHSP(iunit, > keysexist,keysadd,status) FTGHPS(iunit, > keysexist,key_no,status) \end{verbatim} Read or Write Standard Header Subroutines: page~\pageref{FTPHPR} \begin{verbatim} FTPHPS(unit,bitpix,naxis,naxes, > status) FTPHPR(unit,simple,bitpix,naxis,naxes,pcount,gcount,extend, > status) FTGHPR(unit,maxdim, > simple,bitpix,naxis,naxes,pcount,gcount,extend, status) FTPHTB(unit,rowlen,nrows,tfields,ttype,tbcol,tform,tunit,extname, > status) FTGHTB(unit,maxdim, > rowlen,nrows,tfields,ttype,tbcol,tform,tunit, extname,status) FTPHBN(unit,nrows,tfields,ttype,tform,tunit,extname,varidat > status) FTGHBN(unit,maxdim, > nrows,tfields,ttype,tform,tunit,extname,varidat, status) \end{verbatim} Write Keyword Subroutines: page~\pageref{FTPREC} \begin{verbatim} FTPREC(unit,card, > status) FTPCOM(unit,comment, > status) FTPHIS(unit,history, > status) FTPDAT(unit, > status) FTPKY[JKLS](unit,keyword,keyval,comment, > status) FTPKY[EDFG](unit,keyword,keyval,decimals,comment, > status) FTPKLS(unit,keyword,keyval,comment, > status) FTPLSW(unit, > status) FTPKYU(unit,keyword,comment, > status) FTPKN[JKLS](unit,keyroot,startno,no_keys,keyvals,comments, > status) FTPKN[EDFG](unit,keyroot,startno,no_keys,keyvals,decimals,comments, > status) FTCPKYinunit, outunit, innum, outnum, keyroot, > status) FTPKYT(unit,keyword,intval,dblval,comment, > status) FTPKTP(unit, filename, > status) FTPUNT(unit,keyword,units, > status) \end{verbatim} Insert Keyword Subroutines: page~\pageref{FTIREC} \begin{verbatim} FTIREC(unit,key_no,card, > status) FTIKY[JKLS](unit,keyword,keyval,comment, > status) FTIKLS(unit,keyword,keyval,comment, > status) FTIKY[EDFG](unit,keyword,keyval,decimals,comment, > status) FTIKYU(unit,keyword,comment, > status) \end{verbatim} Read Keyword Subroutines: page~\pageref{FTGREC} \begin{verbatim} FTGREC(unit,key_no, > card,status) FTGKYN(unit,key_no, > keyword,value,comment,status) FTGCRD(unit,keyword, > card,status) FTGNXK(unit,inclist,ninc,exclist,nexc, > card,status) FTGKEY(unit,keyword, > value,comment,status) FTGKY[EDJKLS](unit,keyword, > keyval,comment,status) FTGKSL(unit,keyword, > length,status) FTGSKY(unit,keyword,firstchar,maxchar,> keyval,length,comment,status) FTGKN[EDJKLS](unit,keyroot,startno,max_keys, > keyvals,nfound,status) FTGKYT(unit,keyword, > intval,dblval,comment,status) FTGUNT(unit,keyword, > units,status) \end{verbatim} Modify Keyword Subroutines: page~\pageref{FTMREC} \begin{verbatim} FTMREC(unit,key_no,card, > status) FTMCRD(unit,keyword,card, > status) FTMNAM(unit,oldkey,keyword, > status) FTMCOM(unit,keyword,comment, > status) FTMKY[JKLS](unit,keyword,keyval,comment, > status) FTMKLS(unit,keyword,keyval,comment, > status) FTMKY[EDFG](unit,keyword,keyval,decimals,comment, > status) FTMKYU(unit,keyword,comment, > status) \end{verbatim} Update Keyword Subroutines: page~\pageref{FTUCRD} \begin{verbatim} FTUCRD(unit,keyword,card, > status) FTUKY[JKLS](unit,keyword,keyval,comment, > status) FTUKLS(unit,keyword,keyval,comment, > status) FTUKY[EDFG](unit,keyword,keyval,decimals,comment, > status) FTUKYU(unit,keyword,comment, > status) \end{verbatim} Delete Keyword Subroutines: page~\pageref{FTDREC} \begin{verbatim} FTDREC(unit,key_no, > status) FTDKEY(unit,keyword, > status) \end{verbatim} Define Data Scaling Parameters and Undefined Pixel Flags: page~\pageref{FTPSCL} \begin{verbatim} FTPSCL(unit,bscale,bzero, > status) FTTSCL(unit,colnum,tscal,tzero, > status) FTPNUL(unit,blank, > status) FTSNUL(unit,colnum,snull > status) FTTNUL(unit,colnum,tnull > status) \end{verbatim} FITS Primary Array or IMAGE Extension I/O Subroutines: page~\pageref{FTPPR} \begin{verbatim} FTGIDT(unit, > bitpix,status) FTGIET(unit, > bitpix,status) FTGIDM(unit, > naxis,status) FTGISZ(unit, maxdim, > naxes,status) FTGIPR(unit, maxdim, > bitpix,naxis,naxes,status) FTPPR[BIJKED](unit,group,fpixel,nelements,values, > status) FTPPN[BIJKED](unit,group,fpixel,nelements,values,nullval > status) FTPPRU(unit,group,fpixel,nelements, > status) FTGPV[BIJKED](unit,group,fpixel,nelements,nullval, > values,anyf,status) FTGPF[BIJKED](unit,group,fpixel,nelements, > values,flagvals,anyf,status) FTPGP[BIJKED](unit,group,fparm,nparm,values, > status) FTGGP[BIJKED](unit,group,fparm,nparm, > values,status) FTP2D[BIJKED](unit,group,dim1,naxis1,naxis2,image, > status) FTP3D[BIJKED](unit,group,dim1,dim2,naxis1,naxis2,naxis3,cube, > status) FTG2D[BIJKED](unit,group,nullval,dim1,naxis1,naxis2, > image,anyf,status) FTG3D[BIJKED](unit,group,nullval,dim1,dim2,naxis1,naxis2,naxis3, > cube,anyf,status) FTPSS[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,array, > status) FTGSV[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,incs,nullval, > array,anyf,status) FTGSF[BIJKED](unit,group,naxis,naxes,fpixels,lpixels,incs, > array,flagvals,anyf,status) \end{verbatim} Table Column Information Subroutines: page~\pageref{FTGCNO} \begin{verbatim} FTGNRW(unit, > nrows, status) FTGNCL(unit, > ncols, status) FTGCNO(unit,casesen,coltemplate, > colnum,status) FTGCNN(unit,casesen,coltemplate, > colnam,colnum,status) FTGTCL(unit,colnum, > datacode,repeat,width,status) FTEQTY(unit,colnum, > datacode,repeat,width,status) FTGCDW(unit,colnum, > dispwidth,status) FTGACL(unit,colnum, > ttype,tbcol,tunit,tform,tscal,tzero,snull,tdisp,status) FTGBCL(unit,colnum, > ttype,tunit,datatype,repeat,tscal,tzero,tnull,tdisp,status) FTPTDM(unit,colnum,naxis,naxes, > status) FTGTDM(unit,colnum,maxdim, > naxis,naxes,status) FTDTDM(unit,tdimstr,colnum,maxdim, > naxis,naxes, status) FTGRSZ(unit, > nrows,status) \end{verbatim} Low-Level Table Access Subroutines: page~\pageref{FTGTBS} \begin{verbatim} FTGTBS(unit,frow,startchar,nchars, > string,status) FTPTBS(unit,frow,startchar,nchars,string, > status) FTGTBB(unit,frow,startchar,nchars, > array,status) FTPTBB(unit,frow,startchar,nchars,array, > status) \end{verbatim} Edit Rows or Columns page~\pageref{FTIROW} \begin{verbatim} FTIROW(unit,frow,nrows, > status) FTDROW(unit,frow,nrows, > status) FTDRRG(unit,rowrange, > status) FTDRWS(unit,rowlist,nrows, > status) FTICOL(unit,colnum,ttype,tform, > status) FTICLS(unit,colnum,ncols,ttype,tform, > status) FTMVEC(unit,colnum,newveclen, > status) FTDCOL(unit,colnum, > status) FTCPCL(inunit,outunit,incolnum,outcolnum,createcol, > status); \end{verbatim} Read and Write Column Data Routines page~\pageref{FTPCLS} \begin{verbatim} FTPCL[SLBIJKEDCM](unit,colnum,frow,felem,nelements,values, > status) FTPCN[BIJKED](unit,colnum,frow,felem,nelements,values,nullval > status) FTPCLX(unit,colnum,frow,fbit,nbit,lray, > status) FTPCLU(unit,colnum,frow,felem,nelements, > status) FTGCL(unit,colnum,frow,felem,nelements, > values,status) FTGCV[SBIJKEDCM](unit,colnum,frow,felem,nelements,nullval, > values,anyf,status) FTGCF[SLBIJKEDCM](unit,colnum,frow,felem,nelements, > values,flagvals,anyf,status) FTGSV[BIJKED](unit,colnum,naxis,naxes,fpixels,lpixels,incs,nullval, > array,anyf,status) FTGSF[BIJKED](unit,colnum,naxis,naxes,fpixels,lpixels,incs, > array,flagvals,anyf,status) FTGCX(unit,colnum,frow,fbit,nbit, > lray,status) FTGCX[IJD](unit,colnum,frow,nrows,fbit,nbit, > array,status) FTGDES(unit,colnum,rownum, > nelements,offset,status) FTPDES(unit,colnum,rownum,nelements,offset, > status) \end{verbatim} Row Selection and Calculator Routines: page~\pageref{FTFROW} \begin{verbatim} FTFROW(unit,expr,firstrow, nrows, > n_good_rows, row_status, status) FTFFRW(unit, expr, > rownum, status) FTSROW(inunit, outunit, expr, > status ) FTCROW(unit,datatype,expr,firstrow,nelements,nulval, > array,anynul,status) FTCALC(inunit, expr, outunit, parName, parInfo, > status) FTCALC_RNG(inunit, expr, outunit, parName, parInfo, nranges, firstrow, lastrow, > status) FTTEXP(unit, expr, > datatype, nelem, naxis, naxes, status) \end{verbatim} Celestial Coordinate System Subroutines: page~\pageref{FTGICS} \begin{verbatim} FTGICS(unit, > xrval,yrval,xrpix,yrpix,xinc,yinc,rot,coordtype,status) FTGTCS(unit,xcol,ycol, > xrval,yrval,xrpix,yrpix,xinc,yinc,rot,coordtype,status) FTWLDP(xpix,ypix,xrval,yrval,xrpix,yrpix,xinc,yinc,rot, coordtype, > xpos,ypos,status) FTXYPX(xpos,ypos,xrval,yrval,xrpix,yrpix,xinc,yinc,rot, coordtype, > xpix,ypix,status) \end{verbatim} File Checksum Subroutines: page~\pageref{FTPCKS} \begin{verbatim} FTPCKS(unit, > status) FTUCKS(unit, > status) FTVCKS(unit, > dataok,hduok,status) FTGCKS(unit, > datasum,hdusum,status) FTESUM(sum,complement, > checksum) FTDSUM(checksum,complement, > sum) \end{verbatim} Time and Date Utility Subroutines: page~\pageref{FTGSDT} \begin{verbatim} FTGSDT( > day, month, year, status ) FTGSTM(> datestr, timeref, status) FTDT2S( year, month, day, > datestr, status) FTTM2S( year, month, day, hour, minute, second, decimals, > datestr, status) FTS2DT(datestr, > year, month, day, status) FTS2TM(datestr, > year, month, day, hour, minute, second, status) \end{verbatim} General Utility Subroutines: page~\pageref{FTGHAD} \begin{verbatim} FTGHAD(unit, > curaddr,nextaddr) FTUPCH(string) FTCMPS(str_template,string,casesen, > match,exact) FTTKEY(keyword, > status) FTTREC(card, > status) FTNCHK(unit, > status) FTGKNM(unit, > keyword, keylength, status) FTMKKY(keyword, value,comment, > card, status) FTPSVC(card, > value,comment,status) FTKEYN(keyroot,seq_no, > keyword,status) FTNKEY(seq_no,keyroot, > keyword,status) FTDTYP(value, > dtype,status) class = FTGKCL(card) FTASFM(tform, > datacode,width,decimals,status) FTBNFM(tform, > datacode,repeat,width,status) FTGABC(tfields,tform,space, > rowlen,tbcol,status) FTGTHD(template, > card,hdtype,status) FTRWRG(rowlist, maxrows, maxranges, > numranges, rangemin, rangemax, status) \end{verbatim} \chapter{ Parameter Definitions } \begin{verbatim} anyf - (logical) set to TRUE if any of the returned data values are undefined array - (any datatype except character) array of bytes to be read or written. bitpix - (integer) bits per pixel: 8, 16, 32, -32, or -64 blank - (integer) value used for undefined pixels in integer primary array blank - (integer*8) value used for undefined pixels in integer primary array blocksize - (integer) 2880-byte logical record blocking factor (if 0 < blocksize < 11) or the actual block size in bytes (if 10 < blocksize < 28800). As of version 3.3 of FITSIO, blocksizes greater than 2880 are no longer supported. bscale - (double precision) scaling factor for the primary array bytlen - (integer) length of the data unit, in bytes bzero - (double precision) zero point for primary array scaling card - (character*80) header record to be read or written casesen - (logical) will string matching be case sensitive? checksum - (character*16) encoded checksum string colname - (character) ASCII name of the column colnum - (integer) number of the column (first column = 1) coltemplate - (character) template string to be matched to column names comment - (character) the keyword comment field comments - (character array) keyword comment fields compid - (integer) the type of computer that the program is running on complement - (logical) should the checksum be complemented? coordtype - (character) type of coordinate projection (-SIN, -TAN, -ARC, -NCP, -GLS, -MER, or -AIT) cube - 3D data cube of the appropriate datatype curaddr - (integer) starting address (in bytes) of the CHDU current - (integer) if not equal to 0, copy the current HDU datacode - (integer) symbolic code of the binary table column datatype dataok - (integer) was the data unit verification successful (=1) or not (= -1). Equals zero if the DATASUM keyword is not present. datasum - (double precision) 32-bit 1's complement checksum for the data unit datatype - (character) datatype (format) of the binary table column datestr - (string) FITS date/time string: 'YYYY-MM-DDThh:mm:ss.ddd', 'YYYY-MM-dd', or 'dd/mm/yy' day - (integer) current day of the month dblval - (double precision) fractional part of the keyword value decimals - (integer) number of decimal places to be displayed dim1 - (integer) actual size of the first dimension of the image or cube array dim2 - (integer) actual size of the second dimension of the cube array dispwidth - (integer) - the display width (length of string) for a column dtype - (character) datatype of the keyword ('C', 'L', 'I', or 'F') C = character string L = logical I = integer F = floating point number errmsg - (character*80) oldest error message on the internal stack errtext - (character*30) descriptive error message corresponding to error number casesen - (logical) true if column name matching is case sensitive exact - (logical) do the strings match exactly, or were wildcards used? exclist (character array) list of names to be excluded from search exists - flag indicating whether the file or compressed file exists on disk extend - (logical) true if there may be extensions following the primary data extname - (character) value of the EXTNAME keyword (if not blank) fbit - (integer) first bit in the field to be read or written felem - (integer) first pixel of the element vector (ignored for ASCII tables) filename - (character) name of the FITS file flagvals - (logical array) True if corresponding data element is undefined following - (integer) if not equal to 0, copy all following HDUs in the input file fparm - (integer) sequence number of the first group parameter to read or write fpixel - (integer) the first pixel position fpixels - (integer array) the first included pixel in each dimension frow - (integer) beginning row number (first row of table = 1) frowll - (integer*8) beginning row number (first row of table = 1) gcount - (integer) value of the GCOUNT keyword (usually = 1) group - (integer) sequence number of the data group (=0 for non-grouped data) hdtype - (integer) header record type: -1=delete; 0=append or replace; 1=append; 2=this is the END keyword hduok - (integer) was the HDU verification successful (=1) or not (= -1). Equals zero if the CHECKSUM keyword is not present. hdusum - (double precision) 32 bit 1's complement checksum for the entire CHDU hdutype - (integer) type of HDU: 0 = primary array or IMAGE, 1 = ASCII table, 2 = binary table, -1 = any HDU type or unknown type history - (character) the HISTORY keyword comment string hour - (integer) hour from 0 - 23 image - 2D image of the appropriate datatype inclist (character array) list of names to be included in search incs - (integer array) sampling interval for pixels in each FITS dimension intval - (integer) integer part of the keyword value iounit - (integer) value of an unused I/O unit number iunit - (integer) logical unit number associated with the input FITS file, 1-300 key_no - (integer) sequence number (starting with 1) of the keyword record keylength - (integer) length of the keyword name keyroot - (character) root string for the keyword name keysadd -(integer) number of new keyword records which can fit in the CHU keysexist - (integer) number of existing keyword records in the CHU keyval - value of the keyword in the appropriate datatype keyvals - (array) value of the keywords in the appropriate datatype keyword - (character*8) name of a keyword lray - (logical array) array of logical values corresponding to the bit array lpixels - (integer array) the last included pixel in each dimension match - (logical) do the 2 strings match? maxdim - (integer) dimensioned size of the NAXES, TTYPE, TFORM or TUNIT arrays max_keys - (integer) maximum number of keywords to search for minute - (integer) minute of an hour (0 - 59) month - (integer) current month of the year (1 - 12) morekeys - (integer) will leave space in the header for this many more keywords naxes - (integer array) size of each dimension in the FITS array naxesll - (integer*8 array) size of each dimension in the FITS array naxis - (integer) number of dimensions in the FITS array naxis1 - (integer) length of the X/first axis of the FITS array naxis2 - (integer) length of the Y/second axis of the FITS array naxis3 - (integer) length of the Z/third axis of the FITS array nbit - (integer) number of bits in the field to read or write nchars - (integer) number of characters to read and return ncols - (integer) number of columns nelements - (integer) number of data elements to read or write nelementsll - (integer*8) number of data elements to read or write nexc (integer) number of names in the exclusion list (may = 0) nhdu - (integer) absolute number of the HDU (1st HDU = 1) ninc (integer) number of names in the inclusion list nmove - (integer) number of HDUs to move (+ or -), relative to current position nfound - (integer) number of keywords found (highest keyword number) no_keys - (integer) number of keywords to write in the sequence nparm - (integer) number of group parameters to read or write nrows - (integer) number of rows in the table nrowsll - (integer*8) number of rows in the table nullval - value to represent undefined pixels, of the appropriate datatype nextaddr - (integer) starting address (in bytes) of the HDU following the CHDU offset - (integer) byte offset in the heap to the first element of the array offsetll - (integer*8) byte offset in the heap to the first element of the array oldkey - (character) old name of keyword to be modified ounit - (integer) logical unit number associated with the output FITS file 1-300 pcount - (integer) value of the PCOUNT keyword (usually = 0) previous - (integer) if not equal to 0, copy all previous HDUs in the input file repeat - (integer) length of element vector (e.g. 12J); ignored for ASCII table rot - (double precision) celestial coordinate rotation angle (degrees) rowlen - (integer) length of a table row, in characters or bytes rowlenll - (integer*8) length of a table row, in characters or bytes rowlist - (integer array) list of row numbers to be deleted in increasing order rownum - (integer) number of the row (first row = 1) rowrange- (string) list of rows or row ranges to be deleted rwmode - (integer) file access mode: 0 = readonly, 1 = readwrite second (double)- second within minute (0 - 60.9999999999) (leap second!) seq_no - (integer) the sequence number to append to the keyword root name simple - (logical) does the FITS file conform to all the FITS standards snull - (character) value used to represent undefined values in ASCII table space - (integer) number of blank spaces to leave between ASCII table columns startchar - (integer) first character in the row to be read startno - (integer) value of the first keyword sequence number (usually 1) status - (integer) returned error status code (0 = OK) str_template (character) template string to be matched to reference string stream - (character) output stream for the report: either 'STDOUT' or 'STDERR' string - (character) character string sum - (double precision) 32 bit unsigned checksum value tbcol - (integer array) column number of the first character in the field(s) tdisp - (character) Fortran type display format for the table column template-(character) template string for a FITS header record tfields - (integer) number of fields (columns) in the table tform - (character array) format of the column(s); allowed values are: For ASCII tables: Iw, Aw, Fww.dd, Eww.dd, or Dww.dd For binary tables: rL, rX, rB, rI, rJ, rA, rAw, rE, rD, rC, rM where 'w'=width of the field, 'd'=no. of decimals, 'r'=repeat count Note that the 'rAw' form is non-standard extension to the TFORM keyword syntax that is not specifically defined in the Binary Tables definition document. theap - (integer) zero indexed byte offset of starting address of the heap relative to the beginning of the binary table data tnull - (integer) value used to represent undefined values in binary table tnullll - (integer*8) value used to represent undefined values in binary table ttype - (character array) label for table column(s) tscal - (double precision) scaling factor for table column tunit - (character array) physical unit for table column(s) tzero - (double precision) scaling zero point for table column unit - (integer) logical unit number associated with the FITS file (1-300) units - (character) the keyword units string (e.g., 'km/s') value - (character) the keyword value string values - array of data values of the appropriate datatype varidat - (integer) size in bytes of the 'variable length data area' following the binary table data (usually = 0) version - (real) current revision number of the library width - (integer) width of the character string field xcol - (integer) number of the column containing the X coordinate values xinc - (double precision) X axis coordinate increment at reference pixel (deg) xpix - (double precision) X axis pixel location xpos - (double precision) X axis celestial coordinate (usually RA) (deg) xrpix - (double precision) X axis reference pixel array location xrval - (double precision) X axis coordinate value at the reference pixel (deg) ycol - (integer) number of the column containing the X coordinate values year - (integer) last 2 digits of the year (00 - 99) yinc - (double precision) Y axis coordinate increment at reference pixel (deg) ypix - (double precision) y axis pixel location ypos - (double precision) y axis celestial coordinate (usually DEC) (deg) yrpix - (double precision) Y axis reference pixel array location yrval - (double precision) Y axis coordinate value at the reference pixel (deg) \end{verbatim} \chapter{ FITSIO Error Status Codes } \begin{verbatim} Status codes in the range -99 to -999 and 1 to 999 are reserved for future FITSIO use. 0 OK, no error 101 input and output files are the same 103 too many FITS files open at once; all internal buffers full 104 error opening existing file 105 error creating new FITS file; (does a file with this name already exist?) 106 error writing record to FITS file 107 end-of-file encountered while reading record from FITS file 108 error reading record from file 110 error closing FITS file 111 internal array dimensions exceeded 112 Cannot modify file with readonly access 113 Could not allocate memory 114 illegal logical unit number; must be between 1 - 300, inclusive 115 NULL input pointer to routine 116 error seeking position in file 121 invalid URL prefix on file name 122 tried to register too many IO drivers 123 driver initialization failed 124 matching driver is not registered 125 failed to parse input file URL 126 parse error in range list 151 bad argument in shared memory driver 152 null pointer passed as an argument 153 no more free shared memory handles 154 shared memory driver is not initialized 155 IPC error returned by a system call 156 no memory in shared memory driver 157 resource deadlock would occur 158 attempt to open/create lock file failed 159 shared memory block cannot be resized at the moment 201 header not empty; can't write required keywords 202 specified keyword name was not found in the header 203 specified header record number is out of bounds 204 keyword value field is blank 205 keyword value string is missing the closing quote character 206 illegal indexed keyword name (e.g. 'TFORM1000') 207 illegal character in keyword name or header record 208 keyword does not have expected name. Keyword out of sequence? 209 keyword does not have expected integer value 210 could not find the required END header keyword 211 illegal BITPIX keyword value 212 illegal NAXIS keyword value 213 illegal NAXISn keyword value: must be 0 or positive integer 214 illegal PCOUNT keyword value 215 illegal GCOUNT keyword value 216 illegal TFIELDS keyword value 217 negative ASCII or binary table width value (NAXIS1) 218 negative number of rows in ASCII or binary table (NAXIS2) 219 column name (TTYPE keyword) not found 220 illegal SIMPLE keyword value 221 could not find the required SIMPLE header keyword 222 could not find the required BITPIX header keyword 223 could not find the required NAXIS header keyword 224 could not find all the required NAXISn keywords in the header 225 could not find the required XTENSION header keyword 226 the CHDU is not an ASCII table extension 227 the CHDU is not a binary table extension 228 could not find the required PCOUNT header keyword 229 could not find the required GCOUNT header keyword 230 could not find the required TFIELDS header keyword 231 could not find all the required TBCOLn keywords in the header 232 could not find all the required TFORMn keywords in the header 233 the CHDU is not an IMAGE extension 234 illegal TBCOL keyword value; out of range 235 this operation only allowed for ASCII or BINARY table extension 236 column is too wide to fit within the specified width of the ASCII table 237 the specified column name template matched more than one column name 241 binary table row width is not equal to the sum of the field widths 251 unrecognizable type of FITS extension 252 unrecognizable FITS record 253 END keyword contains non-blank characters in columns 9-80 254 Header fill area contains non-blank characters 255 Data fill area contains non-blank on non-zero values 261 unable to parse the TFORM keyword value string 262 unrecognizable TFORM datatype code 263 illegal TDIMn keyword value 301 illegal HDU number; less than 1 or greater than internal buffer size 302 column number out of range (1 - 999) 304 attempt to move to negative file record number 306 attempted to read or write a negative number of bytes in the FITS file 307 illegal starting row number for table read or write operation 308 illegal starting element number for table read or write operation 309 attempted to read or write character string in non-character table column 310 attempted to read or write logical value in non-logical table column 311 illegal ASCII table TFORM format code for attempted operation 312 illegal binary table TFORM format code for attempted operation 314 value for undefined pixels has not been defined 317 attempted to read or write descriptor in a non-descriptor field 320 number of array dimensions out of range 321 first pixel number is greater than the last pixel number 322 attempt to set BSCALE or TSCALn scaling parameter = 0 323 illegal axis length less than 1 340 NOT_GROUP_TABLE 340 Grouping function error 341 HDU_ALREADY_MEMBER 342 MEMBER_NOT_FOUND 343 GROUP_NOT_FOUND 344 BAD_GROUP_ID 345 TOO_MANY_HDUS_TRACKED 346 HDU_ALREADY_TRACKED 347 BAD_OPTION 348 IDENTICAL_POINTERS 349 BAD_GROUP_ATTACH 350 BAD_GROUP_DETACH 360 NGP_NO_MEMORY malloc failed 361 NGP_READ_ERR read error from file 362 NGP_NUL_PTR null pointer passed as an argument. Passing null pointer as a name of template file raises this error 363 NGP_EMPTY_CURLINE line read seems to be empty (used internally) 364 NGP_UNREAD_QUEUE_FULL cannot unread more then 1 line (or single line twice) 365 NGP_INC_NESTING too deep include file nesting (infinite loop, template includes itself ?) 366 NGP_ERR_FOPEN fopen() failed, cannot open template file 367 NGP_EOF end of file encountered and not expected 368 NGP_BAD_ARG bad arguments passed. Usually means internal parser error. Should not happen 369 NGP_TOKEN_NOT_EXPECT token not expected here 401 error attempting to convert an integer to a formatted character string 402 error attempting to convert a real value to a formatted character string 403 cannot convert a quoted string keyword to an integer 404 attempted to read a non-logical keyword value as a logical value 405 cannot convert a quoted string keyword to a real value 406 cannot convert a quoted string keyword to a double precision value 407 error attempting to read character string as an integer 408 error attempting to read character string as a real value 409 error attempting to read character string as a double precision value 410 bad keyword datatype code 411 illegal number of decimal places while formatting floating point value 412 numerical overflow during implicit datatype conversion 413 error compressing image 414 error uncompressing image 420 error in date or time conversion 431 syntax error in parser expression 432 expression did not evaluate to desired type 433 vector result too large to return in array 434 data parser failed not sent an out column 435 bad data encounter while parsing column 436 parse error: output file not of proper type 501 celestial angle too large for projection 502 bad celestial coordinate or pixel value 503 error in celestial coordinate calculation 504 unsupported type of celestial projection 505 required celestial coordinate keywords not found 506 approximate wcs keyword values were returned \end{verbatim} \end{document} cfitsio/docs/fitsio.toc0000644000225700000360000001623513246025103014743 0ustar cagordonlhea\contentsline {chapter}{\numberline {1}Introduction }{1} \contentsline {chapter}{\numberline {2} Creating FITSIO/CFITSIO }{3} \contentsline {section}{\numberline {2.1}Building the Library}{3} \contentsline {section}{\numberline {2.2}Testing the Library}{6} \contentsline {section}{\numberline {2.3}Linking Programs with FITSIO}{7} \contentsline {section}{\numberline {2.4}Getting Started with FITSIO}{7} \contentsline {section}{\numberline {2.5}Example Program}{8} \contentsline {section}{\numberline {2.6}Legal Stuff}{9} \contentsline {section}{\numberline {2.7}Acknowledgments}{10} \contentsline {chapter}{\numberline {3} A FITS Primer }{13} \contentsline {chapter}{\numberline {4}FITSIO Conventions and Guidelines }{15} \contentsline {section}{\numberline {4.1}CFITSIO Size Limitations}{15} \contentsline {section}{\numberline {4.2}Multiple Access to the Same FITS File}{16} \contentsline {section}{\numberline {4.3}Current Header Data Unit (CHDU)}{16} \contentsline {section}{\numberline {4.4}Subroutine Names}{16} \contentsline {section}{\numberline {4.5}Subroutine Families and Datatypes}{17} \contentsline {section}{\numberline {4.6}Implicit Data Type Conversion}{17} \contentsline {section}{\numberline {4.7}Data Scaling}{18} \contentsline {section}{\numberline {4.8}Error Status Values and the Error Message Stack}{18} \contentsline {section}{\numberline {4.9}Variable-Length Array Facility in Binary Tables}{19} \contentsline {section}{\numberline {4.10}Support for IEEE Special Values}{20} \contentsline {section}{\numberline {4.11}When the Final Size of the FITS HDU is Unknown}{21} \contentsline {section}{\numberline {4.12}Local FITS Conventions supported by FITSIO}{21} \contentsline {subsection}{\numberline {4.12.1}Support for Long String Keyword Values.}{21} \contentsline {subsection}{\numberline {4.12.2}Arrays of Fixed-Length Strings in Binary Tables}{22} \contentsline {subsection}{\numberline {4.12.3}Keyword Units Strings}{23} \contentsline {subsection}{\numberline {4.12.4}HIERARCH Convention for Extended Keyword Names}{23} \contentsline {section}{\numberline {4.13}Optimizing Code for Maximum Processing Speed}{24} \contentsline {subsection}{\numberline {4.13.1}Background Information: How CFITSIO Manages Data I/O}{24} \contentsline {subsection}{\numberline {4.13.2}Optimization Strategies}{25} \contentsline {chapter}{\numberline {5} Basic Interface Routines }{29} \contentsline {section}{\numberline {5.1}FITSIO Error Status Routines }{29} \contentsline {section}{\numberline {5.2}File I/O Routines}{30} \contentsline {section}{\numberline {5.3}Keyword I/O Routines}{32} \contentsline {section}{\numberline {5.4}Data I/O Routines}{33} \contentsline {chapter}{\numberline {6} Advanced Interface Subroutines }{35} \contentsline {section}{\numberline {6.1}FITS File Open and Close Subroutines: }{35} \contentsline {section}{\numberline {6.2}HDU-Level Operations }{38} \contentsline {section}{\numberline {6.3}Define or Redefine the structure of the CHDU }{41} \contentsline {section}{\numberline {6.4}FITS Header I/O Subroutines}{43} \contentsline {subsection}{\numberline {6.4.1}Header Space and Position Routines }{43} \contentsline {subsection}{\numberline {6.4.2}Read or Write Standard Header Routines }{43} \contentsline {subsection}{\numberline {6.4.3}Write Keyword Subroutines }{45} \contentsline {subsection}{\numberline {6.4.4}Insert Keyword Subroutines }{47} \contentsline {subsection}{\numberline {6.4.5}Read Keyword Subroutines }{47} \contentsline {subsection}{\numberline {6.4.6}Modify Keyword Subroutines }{49} \contentsline {subsection}{\numberline {6.4.7}Update Keyword Subroutines }{50} \contentsline {subsection}{\numberline {6.4.8}Delete Keyword Subroutines }{51} \contentsline {section}{\numberline {6.5}Data Scaling and Undefined Pixel Parameters }{51} \contentsline {section}{\numberline {6.6}FITS Primary Array or IMAGE Extension I/O Subroutines }{52} \contentsline {section}{\numberline {6.7}FITS ASCII and Binary Table Data I/O Subroutines}{55} \contentsline {subsection}{\numberline {6.7.1}Column Information Subroutines }{55} \contentsline {subsection}{\numberline {6.7.2}Low-Level Table Access Subroutines }{58} \contentsline {subsection}{\numberline {6.7.3}Edit Rows or Columns }{59} \contentsline {subsection}{\numberline {6.7.4}Read and Write Column Data Routines }{60} \contentsline {section}{\numberline {6.8}Row Selection and Calculator Routines }{64} \contentsline {section}{\numberline {6.9}Celestial Coordinate System Subroutines }{65} \contentsline {section}{\numberline {6.10}File Checksum Subroutines }{67} \contentsline {section}{\numberline {6.11} Date and Time Utility Routines }{68} \contentsline {section}{\numberline {6.12}General Utility Subroutines }{69} \contentsline {chapter}{\numberline {7} The CFITSIO Iterator Function }{77} \contentsline {chapter}{\numberline {8} Extended File Name Syntax }{79} \contentsline {section}{\numberline {8.1}Overview}{79} \contentsline {section}{\numberline {8.2}Filetype}{82} \contentsline {subsection}{\numberline {8.2.1}Notes about HTTP proxy servers}{82} \contentsline {subsection}{\numberline {8.2.2}Notes about the stream filetype driver}{83} \contentsline {subsection}{\numberline {8.2.3}Notes about the gsiftp filetype}{84} \contentsline {subsection}{\numberline {8.2.4}Notes about the root filetype}{84} \contentsline {subsection}{\numberline {8.2.5}Notes about the shmem filetype:}{86} \contentsline {section}{\numberline {8.3}Base Filename}{86} \contentsline {section}{\numberline {8.4}Output File Name when Opening an Existing File}{88} \contentsline {section}{\numberline {8.5}Template File Name when Creating a New File}{90} \contentsline {section}{\numberline {8.6}Image Tile-Compression Specification}{90} \contentsline {section}{\numberline {8.7}HDU Location Specification}{90} \contentsline {section}{\numberline {8.8}Image Section}{91} \contentsline {section}{\numberline {8.9}Image Transform Filters}{92} \contentsline {section}{\numberline {8.10}Column and Keyword Filtering Specification}{94} \contentsline {section}{\numberline {8.11}Row Filtering Specification}{96} \contentsline {subsection}{\numberline {8.11.1}General Syntax}{97} \contentsline {subsection}{\numberline {8.11.2}Bit Masks}{99} \contentsline {subsection}{\numberline {8.11.3}Vector Columns}{100} \contentsline {subsection}{\numberline {8.11.4}Good Time Interval Filtering}{102} \contentsline {subsection}{\numberline {8.11.5}Spatial Region Filtering}{103} \contentsline {subsection}{\numberline {8.11.6}Example Row Filters}{105} \contentsline {section}{\numberline {8.12} Binning or Histogramming Specification}{106} \contentsline {chapter}{\numberline {9}Template Files }{109} \contentsline {section}{\numberline {9.1}Detailed Template Line Format}{109} \contentsline {section}{\numberline {9.2}Auto-indexing of Keywords}{110} \contentsline {section}{\numberline {9.3}Template Parser Directives}{111} \contentsline {section}{\numberline {9.4}Formal Template Syntax}{112} \contentsline {section}{\numberline {9.5}Errors}{112} \contentsline {section}{\numberline {9.6}Examples}{112} \contentsline {chapter}{\numberline {10} Summary of all FITSIO User-Interface Subroutines }{115} \contentsline {chapter}{\numberline {11} Parameter Definitions }{123} \contentsline {chapter}{\numberline {12} FITSIO Error Status Codes }{129} cfitsio/docs/fpackguide.pdf0000644000225700000360000164564213246025103015547 0ustar cagordonlhea%PDF-1.4 %äüöß 2 0 obj <> stream xœÍ[KäÆ ¾÷¯ÐÙÀ̪Þ0h`¦§Û@nCS;vxsðßO‘,V±’zf 0°©K%ùñMÍjúíôë4Çÿ¼ÒSXõôíï§?ý0ý+ݧo¿œ^ÞN*˜Çe ÊÇßþ6}º©IÏÓÛÏ~²þ¬žÂì•7þEÃÿ¯Þê™n;-?9wÖOÁxw¶OAŸÔÓóL\à¾ó+Üò6þþ—·?œ®o§Ï ÚºG3…Y1 J! .œ—'}=?Ø'=Ã¿ÖÆWäîÉÍ‘‰ñðö¸ö"Ö^ãZ«â?Μý©oçó ûŠiÍ&aÞ<†É/¡p‡IÓgS‘†Û!‘-¯ðàØyÐtÃ?ý¹ùf7ù`Ýî{Ý“½D' ‚_âû€Ýæ)X$¡e Rél|†è5vݦ@G¡xÛžœ62ÊX"ŽäoÁG1б#é€Mmæ¸x“ÅçÕÊ'Õ“²ø£ô5îâ6vp³qSßäm„”9ÃãQ ܹnmÔäÖõÑ6Gh  çñ $‡ÇK ˜OqåÖ[”³€’Ù]0B!+Ô$ÿׯ§9Âå·ŠKüñ4O*.ú:)ïÒÅ—é§lvã.#´E—î{ŸL‰S²62]2¨@‹ƒÀ (VÈßž±y zUÑ]J™Œ_6\„„ù-)J³-Oo¶]d–]+l ’[NÏ¥ßP;|‰†hMÌ9Dð0HI‡R½+•ê(\{£aG©­»Ó¥]’CEnéW¼ˆÆ²I¼¨§Èí’…›CiIX.ózWÚóü¨ÛXè=ŠTÚÙJ¤dx½eÁó ¹›Dö)ïqw"`OãÂr8°ÃË`bùâö%QÒÉOç‹lȧ3q"|=LNízÄxAoåô²Tf(ˆVÉ·¼éžÌíÒ¹«÷:^-6ÆAZX$ì†Þ %4Ř%‘'ðµúuï &†1Ô‚Qp9±ˆBÓÓô*̤ݥž³ŠPéOøˆ×6%h#n2 É.Wa2‚Ér“<íÂ!˜èq@ðÑ$Je¨ßaô#q‚2KŒ”)ÿGqÂvD@ÑÀ-«¿Ä¥!]¶bІw t–´;mkh\ríö†„·ÇÄ=ဖN=I$§CíBŒ66C³B¥¸ªq=,&EÖÙ®ìòÁBÝ8m®üÒý9‚p9_ͦV”¬Šýªª2Ó°K˜1m&ý¼§2e(þ)>1“J.ÞÓ‘†¶B&3AÄB¹tèèš*Òd‘Øna:Rj‡ÂNî.³ËÃZñÀûT{¡r{§¯Qo„BU]Õš Ǫ®6ìHbU[áÕ‚2 Òü\fsMHÊÐTu©“#–}„—kÜÂay¢ Ù–ÌÐǸiò°{ë½9UÛ¦£§²ñA˜·iš*9\ئí"êGI‘™g\ž;jfr¼ß)’¤É¢§ƒÝ ¶!}4P§ )•@»#ë½"FBs¼õmè5ÎÙBªWÉ€®†Ù¢e#‘k£C "ê5‹žÂW®vM=ìÜ=G–&î‚mÈ vó×¶ªk—’^âï(ÁJäAؔ˦5ÓNÃù¨ùç3(ȧæöO­=–±ðGUO´ŒBBKõ¥ð E%• TÓ‘@RÚ“Ÿå¯Èñ'Ö(q¢fV( åŒaÐ.湯ɵ¸ÝÇíLeÉpS/Ë N7°`&ˆ6ÕŒsT~ï;ÀS1EÙ3ß+_,V±C*Zs&«K_ÆJ)CS˜b0ÎCwËàfQwµfKA†S¤T}B¢æšùKh«Ôwà˜T P9i6!o):¬×FGToÔÔ…bƒ×Hg»ðÎ?å¾Qá¥>¸Ê._[aÝ¡uµÊh‰YN™ b ô]Å3~éÝ/êôÂZ±]»ÎòHô![ ³ðn»t–ß("6Á¹êçÚÞGWþÊM¸E¿Š¹îêÜ¥÷›ªÔâ»öZ±±ÂèUy÷Q7¨I dšÞ×pD•À,Ç úº%ÕKÅÒÈ —Ré×;B@-ª¤ªjH³I´Æõ~@Ö—¼G ¾ŸbnÌ;@EáÛÁ«ug#¾¼ƒçd‹ñ9nX¹&ó-– §rîëÖMW<”+ï½ä·V6ê·ô[U³ßkiß*éq°²Õd(ݲܨ@N~±} ƒ‚Cè]QÎkg;Éh”q1À³¥¨i ÿÜyžztZw#y’]B®OÀ¬×ÒAÒ8eâãê]>âGQ¨Iy á)mÆ3ûÏã¤`5ÀÑ"L(Fæ”8RsQ­ð9\'baƒ·è ßò –,òkliìÂ^`Cõz-:ÎJ8M— –²ÆÃt&D7y6#@7}¤q§yÑz™û^bWhÓ¶‚rÍ*šÛu]›I‘Ã4vŽÓ 0ߺìm†hjåÀ¯TÚ®j4½öaÆ ££R>g_ÇZ¨zÔìÖ)¡áÉËýš>T]ßúKc½PÿTß߇Û:'ãZWi›tËŠÁ ÖU‘´§Hj4o岌ScÚª¹uoÑÕö衲"¢¼Vô'«`™cªì©—I²ªÃ&+#ú*Á+›3i:ª?߮Ȝé†Ì “¿À$‘Í•"[aºKÛKÙ, ¥š Iç Àr,Ѧr±q7kV§lXèS~µ„uÛ›'ãî@ûà9òC}¼)Œ«½ÝèN×Û<8Ùs¿kÈá¼æ°ë›s49X#4ÅìZÀJ?8œêº#ÉŸ™fi<®8PïA’t¤:ôýPBÁxbWERˆÈªN[ Êõ{ñµ•Óy:ª²ÙfŠÑÍn*Æõ¢*z¥l…K¢Úpgá>Ð8Õå8þ}ëžê½Ëfy\"…g“ÍÚ¡“Æ»R¾†02r©µãœ½«ëɦ§/“ÿUþ[b‘™徑h²äg’t3ŽÂøPž:ê¸äVAçÛÓKºQ3~W´óÜ{!•ñHsOø®çµL[ܤM ëóúžà¸)•'ç Ž]&sQϳ iæ¨{Á´^ „óʉ׆pÌ?ì!ן|¤L\<¥)%`ÿë0{bTKè}]¹¹ôAϲN›]¾a(¢f›4p÷|†§èæ|ÜAçØ9¿?“‘T´õ·"ç2Ë«ú‰˜_-ÁËX´ÙÔò·ßwéCtÉM‘X s$Èh¦;ç—Æü6̉ëTŠÆE…ÛÙáQ<Ä}‘=¯¢|;Ob±WéŸä,ž‡$°ÊÁ[7f>(ßÖá$ç¹14ˆáx¬«îüàÓõKþâûZÌÀQ¸¾ íã&r7¿·ËfÛTyÊÜ~Í2è§÷#i&&ñyÖ© èrX•[YYåÀOwýñœÍìÀùcã»P7ý§¢f¹ìƒç"bB•˜±sÏ5°aù£Oðù¢Bk†ÉšQžHÉÑe¼¯LP5k ²Îÿíò8ªú6±û;Æ¥êTŒšjSá­Ù’÷5½J‚À%Êí«R¶ibm”|ÄBÿ@ÿm Ÿ·k(l«ùÜíæfÝ—&tÕ3­UG»Œžnv£,5 rt8ú4Apó璘¸ÛO¸ÅwÞ´,ÈŒM ]6i«ÓuykéNíÈbþ^CUͪÿh Þſ،ye?›]Ѩ»W¦úÔ°ºU«’+{ÏÃàç1¤Ò1ì8®@ƒ".åí6âü=%»oa«Á¦ÆÑ"ËcG3ÙËÒ5õdÕO¤–ãˆi@±¸Nm©™bv½|Éú¶åÓm·Ûêb'ÏSˆjCRå`bÀSKÆî8;3›G5ù¹i?KH‹qÆ9=åàƒ*¥á;ý¯'…£*tõeâ+Æ—)-¬.pÝé§—NŸ§_§O×rÓ/ÿ™>½}³Ó뿧ϧÿŽˆšI endstream endobj 3 0 obj 3639 endobj 4 0 obj <> /Length 8 /Filter/FlateDecode >> stream xœ endstream endobj 5 0 obj <> endobj 7 0 obj <> stream xœÅZM#¹ ½÷¯¨s€öè[U€a Ûv-ÛdÈa‘S²»@M°“ÃþýP$¥¢JRÙ=— ·­RII=>RR'=ýñòû¤à/h3ÅÅLß~~ù럦s«š¾ýúòþñ²˜ÓÓ'LH£»pÑg‡CywxÏøˆfƒA|'âàð5 $+ Š3ó›kš»(ò¤,–ObáêQ7ü6MszÓPnФjœ³w>ËÏÏVzb‹ºÅ`üYæo~¹¼|íZUëÓ²³jô0 ëe9 uâi†V¥iñ!õöÔƼ µ8ÇJj¬–‡/ñó”»lÞ‚³™û¦àñR|€¥„Ùž,-ÅLÚáR¬1iúd]·‚©ƒ‰´²\’ª“ÕùkÒ:è/œÉ¡›§'×ôáö=Œápº$è;ò9·4ÛÜeɰ•Íä+4KîEÒ·&B¥ôÑ"…†\À ƒHãw¤vurjsùøgÏö6¸úb|g.{x§¹äx ô·=oh0ojb“ž°Å œ¨Å2@Øü¹á?9°  ¼þ«M sµ +LÙÖY¹(oa ë¡s?ØlzV êž°ŒF4ù¦–"éš´ÌŸiiö {¬Û'"ŽdÕé-EŸ 0H ¹ñŽØ—_È=AG ˆyØ-¤ñô—KŸ$¿@Òñ0˜u1 †+»­m™ÑŠg!ïGU¹A@…Ïyf ðeF׆”-N°‰È‚iÃeÿȾNÛÌo<w?˜b.4,SϹ F8s㸔Œ™•˜5."v€gÞŠûHÊ),IÔÒ°ñJ2ß³rÉÓr0ßd{N'8ka–&G<2 ~;ò)¿¨6ÊâÒW–•—F+=fÒü´øÛ•dÂÍaÇ~G£’6Ò0YzNÜRñSÆè!õhÙ¯—_ G,Û“¤ÌEÐØ«Àâ.,ɺ@Yà8[°“ºà<È{µ”D!S°còKCú¹Å‹ÁÌ© K.ã|{»¡[ë²[<å¯y/aˆæLKxl/ý¢d¶J½ö*ßë¤Ý}Õ¹‹G¾@da3mC»™ÓHéõܘ÷oÊ)},û)C‰ƒ$@ã(vMš»s™kqé´Í6÷ÔP‡ÔÉwaôXÁ•J~»†˜ÔÌPÕð ®±˜!}¸00À¤Ý~-NF9Ò»yß‚‘Ýê[p–Ì;9ÍËà[àÜÉp¸/”ï‡çg ´ ÈG™¨Pœ™Ó šx@‹Oü$e‘;sïÇ ¤´F)aýjÏgL‡*ê¤Ó„9M" ]F)à0Ñ=²­@mˆOŠ7ÎÃòæSÄ‘…`+E˜j%ÖZ3L‡° óç£Pa&]ÞïnÒ *­Œ²[Èù‚ŠðV‹zƒ6H áSþ¾©»Z¡/µ[x²ª;d‹«ÖÐæà¿ÁqÒ·Ôßh¥¼ó¦½ã©«ÖÚ@Ú0JáHÈPÈê¡7˜âÿ%¨O9s-§u÷d´L Pô~hL¢+ïpQjɈÀV2Ò-Ÿ‹1pn³BØyK€mÚ¬ÒŠLg [ .A!ÎíY–HEDXBAªNSæ ¹éŠ ¶•,¡ä‰}T-øbKmÊeì›3ï×…ô³,.S³"”â’8/™âÑ2@2ÄЃí>a›r<ëðÖVzÅ×#•y©ç.#­–Y¡ï`8)QΖ>6»„ìý¾Tvm©ìÂÀúu ýX Ÿ7lMÒ¨hÃBOî˜náwêƒlZ<ó N@Ç@¬.q-½jU»~ƨóŒ%ûý‘vû«çdôÉÁ:6qY¹l;+ÈÔ%™óÖ¶7uf‘™L. uOa8ï딜÷ñÃQN½93~…& Þã+3mªÔôðºóF[ŒïŸŒPÖNK”'áîQFIN[Jœ³ˆâ5´©²×º_Î_ÊlO&ba‡ÍÑÁÓ°"Åt8+&nœb…$½Oè Á`ñ¶C!ZÍ•“qˆ5ö7Gú Lô x[âÕ“+-.¾?øÔ6†àihê 9=láHÜ…#ìh/h!¬rt´âwyàÚN~e¦J‹8Ë»ew–œŸgtóiròs©w×B–ºÛò!˜SÉXb7O†sB´™VMØij·=d~ú|\Fä¦Ð”»=gÇ£ý¼&§ r&ÅÜ x%ªl$ñˆL¶ ™›S3’Ð×qíû7;ÞÍ›ð²!ôþ>“g·p¡àuíû·g¥¬;Û‰!FæQ¸fÈ5‡§Ž·?Q€ÈE'Sl莆´ÛxŸSx#i7¼ 4 h·¼à€»Š~¬|KÆäOq1"û¯%f¡"Öéwºšç#Z ØÙ ø)¾³æ¾~ô.u³&i²NÜ^@` ãFÇ\›ùD:×&¨2A5ˆwøå*Dúƒ'Z©÷TUØZDtª’ög+TÁÔ6¯±Ê>G‚Ç8ýi"\§O-,K0Ê’7'!kÐ6/hë2îó³‡ñ÷Ù U»¼wp:wþTŽ´Éõìzgêâ@Áï’Æ:r<›úÉØ³·²ÍžÏ76 l¬”Ý0ú† ´UI}d9§4Î¥YËÛŠ^œ¦VTsÇà|U9í¥-&âD¾ÖÉG:Ì£t§à6gÖ$(¬Û>¨ŽfuSýgÇã×bôÁÙ£tÇï.K4þUª@F÷ :P•83A|ÈöåÔª_£Ú¨Öú‰*;?PŸPbd`Ž^SF— ¾~s;UÚ•Ä!‘[éêEñ!KW=rV?ª.âõ! nÀÝ•(QÒ\ÈÓ"_Kà”mÙPo …‡.æç¦RÝ›ó×åËC:§íÜÞ½Ò‰"îÝöûZ.^¤ =2ž8’׌Ķq¤'•éeGMÓ¸Ãc +_˜‹ÝøÔ(ýPª;ÕOÍÅ‚_Gãã5ÖÞø^\‰Ë7-KÞ ‘ zJ9¦”‘H¡þîRÝza“êT¹Æ?òÌG¬K¼·Sm2S`e'=šñI­>­àÎ,˜%Éø;ðñ¢CŽ%Gú[TôŸQßöÚ^{q¬½Šó ‹ ì¹\Jx­¾i-¤åã]H¶èÈìRöo鸕"Ÿ*7óa¹²Àk¹mg[ÍÕBÞçLf•=¥‹oECÀ"þ×é÷éËý‡µš~ýïôåãÛ2Ýþ3}}ùPÖÍ^ endstream endobj 8 0 obj 2914 endobj 9 0 obj <> /Length 8 /Filter/FlateDecode >> stream xœ endstream endobj 10 0 obj <> endobj 12 0 obj <> stream xœÝ\K‹$¹¾÷¯¨³¡{R©”T EAOw¥Á·Á >,{³½àƒÍŽþû–EèUճ؇e é®ÊLI_D|ñÈY^Ìé?O¿ž–øÏ›õöõôýoOùÃéŸøérúþËÓ×§}}±§°n/áôñ×Ó—ã|2æôñ÷Ÿ.ëûõy½ø`×ëÏzº}<}«n5Þ¾¬ò^C÷náº]Üëu½l{zŠ[®Ïá².WwYÏ郰xw=_šþ€•Âv}¶¿Çkü[þ5]±æûãÏÛÅ›ø÷âbñ ¸Â_}zDü>öðb¸"àÏÁÁsà†7\9ý¼ù÷‰+œ½Ëú5ì´h|ƳÓÐM½[âa'çëï‚Up>}dࣸ—Þ#ãøÀ·åóz G‹OLò€;ÕæÓµGº®‹·…¡9Ÿ‚YâO­BPV~ØïèW€ÞAARt!Kÿld(Ú¨¦[üézïÃ,Á¥(Ð ¥ðúé¼Àp4R@ÇÂ; ç œ¸ðžQ~ láç’ÉÅ‹7†+\<6ßmq/[Ô½#ÍûøgR}”„‰ læsø·"~?LB]où32îÁBÙ7ù=DgÖóMax£YÖx¸³Úá'q3õ½UÐë­W{ÙLÔËæÙÿ¯Ö,¼BV4~ÛÊzÞó· ¹¸Nâø@gDÞ%[øx8ú)~j£œÙmÑuGG¶³•Ð.Ò–M^":šø°aGîÒÄ=.â@ˆÌ„îŒòiÙÆò&âcƒXD–¡}އƒº»*9§ŸZ%¹G#4üQí ¢¯&:í, €à“ ø‘]:’Û©]}þ16årCM3†‡@6KýÔ# JqQò¾øÞ[„Ù“{ÄœÜxOkÜMOB°)îFOè¢ÚCÅ-ðFô(ò©˜{ñƒè<¸/DlIâ•[J‰UKæÎ*îÉ¡ JtîcK¢“aÂEåÇn!_ÃúA·”…k_QS—¿ÚÆ¥ÆP™b!Ú˜ëОÆô²ÿÅK,HZDÑG5«f–¾ÜÞøâí(×E( y†!PM镙ògf·,6ÿÎ@n$Ít4 XŠ .)ä­xvr\Vª°ì vêÊ å?4Á”QÈÿ·þŒ—ç'òÑaXS/{ÃjÊ ¯q)X¯ø ‡Ùâ '#„dÊÝ€ï3þo“:éZL³M’,‰êÆ§Ú û|Ç€y› èFá4ÃO$ F£-{æ @ÝF4[3b› ? 7"†€ÛßÒÃ¥%ÊQ¬D1C…Û}ãê>Ed:/á9m-4Êv+(AöbWF­.ÒÒÏ¶Ì Ñã÷è'ÉEÖ^H¯AËÇu-àrD&I"£^iIŠþdÕyýL¼¤ UöôµêDÿŽö#S©CÖ * ³!a›y©‹¸>{gÃîÒ fŽyÄ?¥Q6Ḭ£&ƒ1^Vïìû‡E¨3»Àí]àÍ*²]äÚ% ½‰Ýâñáûµ-­ÔÉk ®àä7)Ü3‡âóai¢V„«²›¹óg³¿¾²Þja¢5½¢©–ä‹j|ˆ þ‘t|^whýÖqt¢Ð¹¬ÎzG@VYó^'#ÊÖ\ˆè&ÿÚÉdz‚kÙ‚8ÇQ0x&w62€Œ £RæèÈœ¸BÇ]G82GéÒÃkv"lR†ì‡“Ú#•k°V³2;ˆ«o…™f¨«è¤ —E5ðLô} ½:O•O@à™t¢ï¨pùKE A‘œOEoe’u%&Œ+1öe—wþ¶JÌ#%¾‡XH›§S‘A»ë‡9h§¤¢=|üapSaè½’qÎu±®dµ.6Æ•}C›8‹Âн ue]t¼âÉéJ¥Ò@)èÏ¥2˜32U½:VÒ†ÔMV‘¹€›©Û*²s'xm4£šÚÃEc¢]ì×Eº´äJŽ2ú¦Z$Aþèoí4_˜UÜrŽÆô;¨Óc$åÂX‘s¯†'MZèa£ûEׯÐ=#õ ¦2³Q**ïæÁ§ +MÄbR×ÙÎk©R]Çvë:þj8lIWÁƒjéñšºó$©œ¨Ñ²›ýDAz\bë¼}6ß…8"Ÿ®ø&³Œ³Ïñâû¼""ñ“ ‹\±Ë‰xtÈu8ùÐ¥,’ˆøyú±6f§UY*)ú=•p½Ý$ª2P–\ÃúKþ¾V±°ZÁ[7Áü¥J´gOÜ#—Ž:Uù¶7þ÷cåaæ[_V˜$ñûV0m(\ùn}« Ÿ˜4ɲéôº £B›™+{ÑBns-ƒå yöÊ×IjÙ_¶Ê÷æM]ǺϸfÕtPµm+??TåÅ ökFu•µ†4vØ9•ÈFŒzdÌ1ó0 Ì›L¿ ›­j´L•n7UZæ@°à|¨OÏ^‡@ás¡!Ü)¼ =ó=Ÿ¼ìƒ¹‘`®ª‡‡TiŽÇ®ö„‹næÅÉçw¹è™†Z“ž4zɬÄ–¿–̰Æ9‰¤*wØ$!º¯y"kˆr¥Zî9Mö¦Iñ! ªÅ%>;qª7V©dÚÀ!¯Ûö¨2ld%u/,ßÇM[±ÛS|¢:ôÄáøòÓ5¢´GµŒ³îBH˸IçI3ª’Jª¦Ê~šµAÃöÖ²VàAKî•p ©¨„A± ¨ÄB˜£ ..m×a›/ªò=o2£–˜ËT~o*° Å"=«£È(ÊŒjWŸ-€Î’…f<Ê–Í0TŸªV–‘CÔÞÒèR–z6 ›¸CNceçèjÈ«=ñH«¨à±—ÐM:–°ä§uƒ ÅHCIgªv×4]Ö<ª“6ŽsED(J´ëú²\BëØM“« H­TÇ7Š£Þ7°É't;WQ0øùÒë‰WpêØŽQu±‘;Â¥œ£Kž# Ö¦p XxÔJ…}ªÚ­­æô Å^¤ÉÊ[JTåùÑ‚]§Ì"b*/¸ ×îUƇf¼´{0[ü-O•'Pô§ƒ‹Ú>k¢'SžNÒjú€bªôÐÒ(%*síLÁx‰­R–T ×k>4 óq0¶%vHŒºêú#eƒºñTED†‹$9¢iØ2†í¢#èðú&úA9ûsð= ¢9¡D“J©´°“½Iì=Ü.µÆ·íR e¶®…ð\ öõ5׿¹[; GVBºÛ-wRµ þú*iY“옉ù»Í’³NËa))‚îGJž1‘«™¹S5bcÛ?ÕßÒP­AøáÔr˜Nå×à÷Ã_ªáw!‹5Èü×*„^*ÏèIPVNIåÅHäª{qÊLî2þÚ7§1#pÏ<œÓf“ÓfYJÓœšWMY¦$Ò% €Qð%bîLfSuúθÄÿ)ÅH›¬mÎolÕeA ´T# à±z„¡VÛ|D´7%±S–ü‹¾›DžîáÝýêòܰ¬Ì íniF¨¤)R a«©ŠëÑÙ ™¥‚–}õ¹xÆaÒM92¡AWkh’GÈÛi»sª woT›ø›»[kŠÛó7‚§1}«l&QæÐ—±nKDf”ùNµiûó"6+ãœTú“|:жâdSõ֛45a÷ÑÙstÁ é÷cÜÉv„gdŠç‚2~íM¡™‹!©Ç =àz²gA³­[gAýÓ8ºRO«,œÝ骊yéG0g{¬)²®¶M4‘æ!¯ý ÊcJ},H|Ëi }ƒ bŽ"¿ÊÃÅ -M U_‘22ÂÒ[NYD]Ûºl×íeJˆß+ ªòx“Èœ@÷r§.~öìïÆu³´E¸vd‡M€'V“_‘¥®"h¯B(Kõ~åÀe–9QÝe:(¤‹y9É`µuWTëŠQ¨¨R¸Õ5ÚòbTÁƈ$ :‹“-á6‡ÇgΔiöº¯Fñô¤H'à颋ÍgÉš«ý'ÎÑPîûÐ;)AÜK[·O“LwE¼‡ÐM*›bø×2è¥qê)Dtɯ{érÒâ¿úñúÀ±êÚtŠoz$ú7ûÍλfS¿9{e©NpŒÆ…6MÇ‹A¼¼}ÃÆ/ø±¡7óš}Fž™Éä¹ð©ƒå‹{OkÉ„á¦Ò?.´©WsÙµÙQy“XÏ©ŒM½Ö«­ŸÃD; ÒéÝ6äHuë„ÊdGï¤B¥E‡jTvªÉ­ü¹×yïToFLE¥ìXç¥-º10àÅãú|¦ZÕ‡T:$h·Ž4YÊ¡y‹¬(eØ1êçå}µõAUœ,ƒÂ±c‘ƒËÆ÷gÛW¥pL•§YÜçKË÷ÜgqÔ¼Ôsa¯«'”h´±g”öØ…^]0×í"Pò.ȇ6«Òlà"F3!8%I±·~«ûŽ2MhBæçí°}‡©:*£^«(¿ôÓ´RwúÔ`ˆÖ¨ˆ§¿[I³£±É*ï0}þ¢çÿf–«—׌盦:‚¡Ü65]AïÕü±/@M©„sê þÎpŸ»ôßÄ/•€R?ÑˉNY!­_:ÆÖ3åôŸ0”bÔšÞ·–ßÿvúõôåöÇ?wúåß§/ßÍvzÿ×éÛÓH®D  endstream endobj 13 0 obj 3581 endobj 14 0 obj <> /Length 8 /Filter/FlateDecode >> stream xœ endstream endobj 15 0 obj <> endobj 17 0 obj <> stream xœÅ[I‹$»¾÷¯¨³¡kRkfBSÐ]]iðmð€ûÙ~àƒÍü÷-)…ÖªîyÆ ôÔ’’B±|_DHµœÕé?O¿–ðÏ+}Zw}úñ·§¿üáôOüt9ýøõéíÛÓ®Ïæ´j|ûëéË¡N*¼úû÷—U_žõ‹Wþæ­?.û‹¿<›¿Ç¿ë«wz¹¸—Õ¦7z«V‡„Çñ~Ü[x‡ï¯éC'u«¹<«—ðݳÅÕÒsqÊËö‚.ò©0søþÀ!ïñMZ%ŒÝã›BÎ8‡Ë³E$)Òtëþ_IR‡U"…÷Ò0»‚±Bð¼~O%8«ƒya]‡Êe¥,þÀi÷<Lz¡i¥_¾ýééöíék׆J÷ʆaÖ´P!$¨ÏÑ´íŠÅÎïó GPÂ+<õj`ØƒŠ ß€õk¿À‘ɚʯaÌ-Ú,}æK/­¾„aáÙ ´añÑ.%ί¯8$Ù þvÍÔ¬†A o,<6Z­Ií(FšœœíÞ²éà –…2?>rmiøÌô~ßξ6½•†ÝXŠ”-B+Û£p6v]…AŒ‘a³„ý /æ†Mš×¹È«:¯…È/úýòíÝ.8¶°1D©K¦Wá#æ]áŠnì…ÑÌm$²¾+Ð÷Æù‚„ d¦ Ið‰=¿Õz×ánq4L‰0…&Bd[—è:ì~aÂ-ó6òâPb–;p»® ñßDG¶u’|X¥p§GÓ~“a9ÏóÒê«O‹O˜:[ÏöCN”N`–Ÿv‚µ#Î÷©õÉâÄDÁ "”g®ÀLD¡Î Ëô¶q¬5nÀ¶Úvªt³œuµK»'—HßÞ—àñŒ®Ó03³Û-ƒ;²ˆX|O ¥ÐòªÌ’‘òÊÚÎ8%»&Ž‹Æ— Ý‚’ÂÀE,!qÉ7o´gÚ§-i6`¢'•æ'I€œˆ+Øu¶vA°Æ Ŧ2€¶‡(Ç=‹+ßd)nÓΖç¸äu°ù´SÌgfŠ.6…c£6™!dP‡AÚ%éRšn’ežêhªŠ™ fJ'K /$wŠc>éø‹¤yØ0¥€‰ý‡”Œåö¥!ë/*ËPg3ÁÛIâ|hKGÚCz\‰Ä‡˜…üGA0²ÙÚŒ} ª—RÙ°MDóNq ±”*P*A/ÈzÖePÜÊ $çrŽÕ¤s‡)%©(Ž* nhjÜum°—VÉÊwÑWåÎS<æâleå cFñ)`E|Q ʬ…à°ÏÁ6‚’ÂzûøtzÞÚG¼€ í?è–+ óƒÂ¶ÈãLb råD ÷mîM‹¾U*hVJf››”I­J²^1\“( ð/F$Û–<ÙÙ‹ŽRÔcXÒƒyrP˜t$ Ì\í6•ñ òƒÌ8P‘}ÊBa’kxRXær‰:E)wU— ö°Ç5¼ÃÆæY­sKSIª!µs•\ŽG©‰‡»Là^#ÒFšðˆÓûƒ\¶JSs¢oE Ú¡HÑ”MHSÃØ i4k™0uÏ… T.ˆÕ*y)br ­‡Rcg:À(Ú)ç% Âf5¬i¨ˆn¹´ ”£Î­„RMBÈÈNfbC˜@¢÷ Jƒ öŽce¦×ãðÆV'³´‘8öc@“ÔTt° ±YðWg+Íjîž¹µmX¬›-EV·iÄ˹Ÿ+¢{Üî¶›äÖd±dýn!Ï€zÍ‹¯~ÃtZ²`“èYrS,Œpº¬ÓUSgë Oí¦–¶Óù˜îe†3ÍsÒBv³ g–¤Æ0¥ª.!7š†^Y«Äïýw¿ÛƘnRìRN •˜µÉšŠsè‹€\clÙåru'Ú …ª€jºè©¯¹;ƒ¿Ò¼>Cø!Šë·W½g#à‚è:Ž´J‰|*Îë>­Rb²¨ØS ^=%PºáI²¨ÈL;.ÑÉ—ÖL}Åêö„õ~ãîsé|;qß 2†# ,¾›Üí%´çÜÍQÌGÊŸqXƒýøFIsOƒÁcXUNM¬÷&Ùçáy­^±"šG²ßßiÔ—Õ‚EàP^A—+¾ŠŠo£1k3& ì +88P€C¿„MÎ\”Ü™<4É­üšJ†°ö{“Á´Kž&Ÿš7 s}Å jWìêa˶È!°b–_ä†ýnT·•‡¹NÑñæs÷¼Ÿâ𰿦ñÕY¥gñŠöNA3}2­Ù¦iÅ}±ÉT‘f6ébtŸ„àÉCdenݹ:Mã©]Ý6fØ? éØÚâãÏQúÃÝÙ²grå€Ç‘|Ú8ªÂ £d¯ Og¨“b/2 ÔT—¤ßÞ?Ó!±m(ö&fŽe¦Ý«a£ÓŒ˜qP£Yœ_c:[ä<݇I߯©^Þâ㥆DÝ~T§Å¶sAE¡[Ño?ÝŸÊÔâš¡TتWÎÓᢛ7wEËN1hã…àU/iŸ¹†¾<¯Øe¸ò#3p[gZ-­KXY¬/O\<§ —u$G¶§âæ,a|îšìÈ~*ÊŠdB,tO£ÈG Áâ+J~£kuUù׿‡ÄzUö𮺛:Šq¡úi@nN®B‹ „P‹]y©£ÎŸÑ¥eÓZäÆùÀÒwuñ~‚}r‡œ—Ü9ìÇš4%ÎÔüM¶! ;‰4µiç—dßXÂ8“ˆmÝ«:ÿªÖp“fÅÔ’:þ­oƒ=L‘ÅÁ„ºy#Í;>5ò©ow=šãÅú¶ác\¶‰›[œCº6ÛmlõÀõAaÖªëFÔg±a’6dÞè+‚oìËîÂÔÄËÝŒ¸'eQB@n°æÆ½8i¯Ú0w˹‡.¾©M͈hÕ‰E½$Q:\h¾›œ)ù-”¼V}Ï÷ç©G3õ„ʤ&ŸQÅL7Vè:ı[Öj Â$Ê‘|3ê›ÜkÁ×°S÷—”Ø…ȃ¼œµýeÒÿw8©s•;Þ»Ì]òcƒÆ ö‘‚þù=ëºPâñ{‹×ôI޾þÒ­ê©•œ9oŸç”šÆ{wÕे[ýNXw+.þŽ ¡žº£@½‹=îŸñòO‡zn Évc6 ¨¼úíÔæÜ³Ï\í­éR’©3Ø¥-äÛÞÔœXn'?@,Ê4¿Ô"x šÆö³+ ê¬å ÝŽÔ/‡4€¸R×À\ŒÖ@ÿp–‡Iÿ³l'ÃÝ‚û¬2R”kôÜýŽÉ;×ÿ Ž¡¶pÍ€äÌ·uŸzʾ7fŒ]Vá ¸¡Ì륌ÀGJ¸vÝv”'ÜÃîÿ°§¹K_n /ä ‘>ÓÛÁþR? ¤’æ¦W'¾.Ø…—>F¿ù¸U'üªg~³˜,ø…m¨ã cùË×Óo§/·?þY/§_ÿ}úòí‡ÚOïÿ:}}ú/q6Å endstream endobj 18 0 obj 3083 endobj 19 0 obj <> /Length 8 /Filter/FlateDecode >> stream xœ endstream endobj 20 0 obj <> endobj 22 0 obj <> stream xœÝ[I‹#ɾׯÐÙPÕkf‚Ô" øÖ¸ÀãÛ,àƒÍ´þûŽåEÄ÷bK©§}1=*IË[¾÷½EË‹8ýçé÷Óâþ³BžÖ]ž¾ýòô×?þIï.§o¿=½}>íòEViÜŸ?Ÿ¾ÜÄI¸W¿þí¼Ê˳<[cõj¬ºlg»_žÕÙ^í*—˳>¯úbÎv³&þiäEȳ¼ú×úãò,èµQ‘^Çoº%n—Ö[•ÿjZĽçÖ¼v7ˆŸ}„C»úL^ÖÐÚá¥Ñé„ Âûö¶.nQ¿@¼Ë-leÊQÖsÞ+ÜÕmBwjí¥°A8·(¤ðÖjà*îÏõ’–¡¶ð¾¶qÖ»,Ó‰çy=Ã)Ü M¸ 5pô´†Nñ’ñg,;ÿýóÏO×ϧ¯]5 ñ²×jŽª°°}§»j¦Ž,‚(ôxéöp·øÙµ¼Ø³ÍbIë ßƒV¬ˆª® l;§ÃGÅ€œÄsÇí-ÜÄYnâ{¶'ÛkR#- #«qÙºVŒÄ‹+ž½>rXC Í¹…œdĭ⟷ÕÒÑÒ窵ûöbû쯻’U:YÛb±icƒ‡zÜè´Ö¿%Á“nN1Æ_OÇÍý·òN;X}Ç‹ÿÞ¢Ô“oö®Mîê] hœÅâL¸,ÜÔ½¡Ó—²9®»³×¸ÜâÝA#@9ó¸ú÷ß ÊçJ)©VeÕv¤ÞͼèZ½èuò-¯E¦8¸³Ê+Êmï?•ˆPìîˆ|ñþ–i ¼(®åvJ»hµ¹³XÿÿÜ9ÛïœØ]ìžxw/1AÀ0«7=úì”^ìpª«U¶ÁôßâÞÐÄ®ø®á¦Ù" ®ÕpáWþˆL€´‚ä´³‹Ùª„ì"ö"«×!G±ºÙ¼† ðÿnDŸ£í–@8ÁÑH×`àˆN°~wÔß g!@ưàTÝfk‚jˆW/7´S™ÐÈ¥Û¨ ÑÏ£$»IÆ8/zºÙOóVzÄ¡m”j“9 GH‘H{ŸøDäOGÜJZ÷„ª¸r*/[þƒpô†ÙPZRXjÊ‘ý ÂÜQ+ÊÌßÌëT÷Ú4Qwà-À£9ÂŬD·1«p—+†G¿9‰>Nó{ w;ÀL$FEt945Ê×ââùU o‘ã‚Å%‹Xó fÁ9G6‡aÞ‹·z+æÝˆë…¢2ãŒM"G +IÂØü#…áO-@É&03Z|5gT €­öš¨økBèš§t÷!†êýÝ¿M.þ¾¶›ì5ý‹.ãiAÿö¶˜‰òJ‰MÙØ_@¡ 4W,œ38dY ¶òKuâ»1ᮢS•Š}¿=“'cädÓDtÓc3ŒXÀ°$’Q¸5ÃO¼qÎ6b!>˜DõÉÎÊ8ê€Ù5$ô¼î W¾ÍFê¤Gq¬¹H4úô‡GŸ¢ó[¶¬.úLU¹˜6áe88KR²6Š&îê·–³TAŸ´Ã“ôlÉ…®-n ‘ƒ+;ðN›ùSß°~H=å@ÊŽ#EoIÆ‘«ƒ¨wz#çÎA}ê:ZX¨Í9a^9k¯s´ÄX+v."ýH€Çt>Gœ•é«»Â\I0r‘ÀÑí¢|¿…7*r÷•%g¦†.œ` 9m]lµdf¨~ GaM Ö8@JÞ Ì<ý†ˆÇøbUQ¸;<ô‹„‹·™[Ö‡a4Öóp$–=Ûš’A*ìæBØÉ©ÖrB¬!ayo¼½µôÊÛM•é}Gq¶.–!˜Ú‚/ÛØbäék(”J9I *fNùÏ«ÓO ´¼ªB]ÖY¿;Õ¦Í kÊ×O|òLI(°UI¥ŽÑ7ŒUkþrí§NÿdÈSîä9¬³S¶%hâûMIkxó$ïÒéæÜIµ’m¹¯ùˆ`Øm·ß3CQ‚l,ÜWjØ 4¢|Iª[o ¡1•›)u¤IWzã:ltVWö¶§XÅE“FRˆqeëœ*Iìm8H’¨ ßÉD¼àPG›f‚yK…Ýgج ç‘ß ÆÆ:0ÑKÝ™{^6[ÅI9áÖè¥ÍEvÜ:@qJã©æ×¸z§ûö¸uûêÙpÒP2¤ìhÉ1•/<'D< Y"AË÷‹ïú¸eÁ< ˆ¼O Y­*õåêFƒNÕåœZ r}Yqµ¬¿Âõ{c'éxS¨ôW-ù¾©ZCuΤͲ# -øõ„P¨‹:þÔ¥êK”¸W4÷‘ìJ4ÙmîR¢—Ä¥šoû¥ÐÚ­{ü_«K¥Ó{¤i£ &¤~ l<Ä`‹ª‹öÒ©qX åçRÌàM’;f #†À-)ÙžŒþ¤rí Ó(Qϳrª¿g‹Sá0–z-„e—N5£C¹¥7u:ξï´)ߊ2Jd˜#¨-O> …âµðÈ ,‹Mfq­Â¨L¾;»ó.Gt¯ñÊ{Û+äxfY™"銄(KòŽ^K¾±"N“ò8öÌv†3Îý—¶;3'ÿëä§BïKW#é«ÅçcvɲwÞÿëY™Ëç?â׿ž~?}¹þôiN¿ýûôåó›Ô§¾>ý*¼± endstream endobj 23 0 obj 3390 endobj 24 0 obj <> /Length 8 /Filter/FlateDecode >> stream xœ endstream endobj 25 0 obj <> endobj 27 0 obj <> stream xœÍYMÜ6 ½Ï¯ð¹ÀL¬oÈzí½] ‡¢·6zhÑôп_J¤$J–<;96»²õE>>>ÒãM ÿ]þFøg…Ü,‡¯\~ùaø‹FÇáë—ËËÛEHwsƒ“f¼ý>|ØÅ à·Ï¿Þ±›Uv_æ»}]®êîF'—«¼[³Lw§–« Ÿvöín79.æîtøs†_q¢5ø^xjmXÃ/‹ËÁèUÃ;VÀ²°áD;¾É—œ¬Á5pÙ0÷Þh’òC;;¯M»7Ïj…]ýÎît¹™o‡ë¨ÅÝåæ×Ç]ÂLüÕèE²sÑa`gãï–¡“Y|¾¢Q–ßÞ~ºlo—Om—q›k—à}×O†­¼ã¼ÓÀ”p½ îf¬¦S„9[ú3\–M…G{}ð÷AÀo±ÕÆq~70NtZ%OÀA·èÒìdåW¿“–‹ºkV¦Ö^¦÷„•Ñ”hýާ³¼×t¤ ¡žÝ½Mƒ§›­Ìήô=üQ=FÌ&wEgÂ-÷`Vwu©&)Y¨¸2RÒ¶"Ewxø\H”‚Ó\„q D~Ö CÞ]Ó튗â®iËÃ3NÒ®áI „ù~€L˜uªÃÿA“¹éïA}ÖbP"ûçaÆ Q\!Ew&¢ÌBÞŒˆˆ…Làœ§©†R£Ùwžʱ÷Ù­†+¿<,š~êj'ió{ðoßÕ9flò·Z3éÖY⌀’}]|¹d¤”©ƒg"µÖžÊàa} MKN蕎?fySƒ5ÓÍ ?¦äFŒ\bøªÕŸþ€¯ð¸|EÔ©îVÂ̰ Û«ë{º»p¶d¤ ËLƒàܽ´Q$hÆø‘¹GFÀ친Â@…r¼9Ž$èÃÆñÈtA)àÆp,?Ì5föæm7̤ ãî!¥Æ×Êçú°˜žY)¤“7B–ÂÀÏà9àâÏw¥–·?[¬ºI>Áàðå¦<Ì%˜_ŽpéÕ‹ð$wõ¤XQöÎè¹`äþ ’öïÁæ«q ì@3aeïœõÄ|(‰æ:·sb0³ —°ÓÖôd ˆgÂÈsÞúâ@¤d×WÀ[ð~OrÚ.B™;‘(4íÁŸÑ a[Deo‹ïev"Û³ÛDY®1ŽLJŸ©gösö@ÙïË𓸴Ö0è×gÍ™¯ aˆGŠÂ`劼ábÓ"6ä~7_6£ Ï ÖLTÒ5K`_Á§›ì =­uØÌdPXú«#ÇX£¿û¸@Q“Œß¼j÷=Hl&/Pà°çÊwÎ+EmÍPÚHiW—ʺ)0ðK"‚øÕˆìþØÏÍH’±Y û4¼¯:A®§÷Í3Ù}ý!Øg¸'ñµUCEkø ò'lâ&zqŠ­¬@Ô'ÝyQõ†ˆK"·¢Z¢±ݧ¢ïnÃ÷“ɸúÊj©>,ŒDô’Š’úì#OÕQÆæݲ™Ox¢ÕÔÌq— ê ÙV@É9T†w;GW£º‰ÁŽéÜ2ô¦mêMþ>l?þ¬Æá˿Ç·¯r^ÿ>]þ!ÄN endstream endobj 28 0 obj 1864 endobj 29 0 obj <> /Length 8 /Filter/FlateDecode >> stream xœ endstream endobj 30 0 obj <> endobj 32 0 obj <> stream xœí\Y‹$¹~ï_QφîÑ™Ð$ôQµ°à‡õ6øÁøÍÞ…ÅkãñÃþ}Ç%)”™¥Ôì1ÃÔVf)¤P_Ò¬y²—Ÿþy1ð'Yw™wùüׇ?þîòwyk.Ÿ¿xýxˆéi¾LfyJ—¿\>ÝâņËÇwzöÞ]× ÿcœ iµÏ“d“O¯ÎÀç ßéíäÖGxˆ“_ÓóäÓÂ?^×Çø c>,0[—üV璉" x2 ^¦ ßÞêŒH “þùãë‡ëÇÃ7Ģyyr̼½XKÌ;³âÂëcÐ_Ãm À®ˆÉ¯3îçʰ 0h9à5>§´>ºgžÓ ¸ 2UŠLëÓ,sÏð[ø5Æ:Œ&’’ò .QÑóŒJ( øÉ?§7¤Žj*àñ1 ¯7ùÕÑ8xzIïH ŠYHŒŽóh+9ŒsegÈV ð‡½¦IÉìå…4½<çIóŒ@¤'âm6>çÙ`tÊúŽ2uþú"‹¿âÔ¬yxºÉìáLçS|Z6:oäÁsÞœ`1ZƒÙ¼±–[" _€O±ÓëucT¤?Y)âÞ,¨ w³Fêñ™gÆádn…¿×cdmñ/Ê(Þ„ÁµÅ)xlQh.‚¡€A«¾,v›KÝ©½Ó 3ƒ0QQZX'¦5µFÐÕ_rOÓV†çi-¯Äv–ùq„.Ê„é˜ya0CäɨtfJ¹%KB̵ªEï4ŠÑ#FI|ö’↕âí¸ î‰ñ²Ž±Ú ã4“wDhÈÜÁC±³lm`ƒD̃¬Ì¨Z¾K^kqm¯µÁâ2âÐñL‡ay Ú1²ØâI•ôµl>o¥Ø÷N5Y†¼4Àf°šQƧcÑ»E†#¸,a¡r®XßBÍ(~âês(°ƒŒSbáá¤o²>IZ£GF÷lGÉÕá™Ó· Õƒ|eÖ»6áÓ.oåSEÜòÅÅZ-â(ÒÍ{Ôèµ›´ãÕ£ø…Ó*+)˜Z©D3žþóôÃ;C÷”…“ÍM¬©ýK•ù7”ºwó“§ÄÎ-ö)–ÔŽõñ‡¯H5?Á߯áï{ù=ªgŠ>|°6?ýíò­è²%Ðc~|pvÅö)ô˜bpeÅ{Ì”1Ë Sôt”PÈ‚] =¦0Õ¥ ¦¢õ`Ι)~ê3•)xÁ>…“™êSS`M öÌ?õ™Ê¼`ŸBÉLõ)˜©€ ¦èé„)¡»zLaªKÁL™PY‚ï' ÑhYª3ºŽ(¬tF#>y%~ê3“)x±>…“YêS0S!*㧦„BìRè1…©.3E˜V˜¢§¦„BìRè1…©.EƒM =‡`Cy´"r6E<àŠtÈX é)Ò!+â1˜V-j„’RGp~ƒw# ¬Áh[Ì8‡¯;`Lëkî¼ ¹y@G‚t¬F"è&’Œ„7 õ‘§Eãóà°ÊônQ¬”*}̰Tn1˜þ¨À?˜›¨¨<˜8”à9ÓUd ½*è ÆEŽ‚çÝûfj“q«bû©É¤]“*¼R©³¯‘ïTU¬ÂÏx&®}íœ,µÂQeJ¿)ãœy²ÇËØ5tÊ5¬‹ÓÚ`XµuÚw(™8Ïy¡åb -d,ro°Åc<Îk‚‰ô*ÁÔfêK(Εqž/PAGŸ•ò;‘TUa‡šÄFB-:â^L¤š%Z, ßû‚;ÜÏLÌOPá™…öó‚“™Wú|3ï°¨Œ¹âlz[ì¥[ ë[‡¢´Ø¶ÁF›`´½+ábBIrA†¦d^쌫&úÓ¦˜§µ‹Þnwh_ð4€¿¾â¾ÞpOPÏO²eÒðÆ¯«[ð7Pœ¼~S°7‹‡?#“£ìŒ´Iœ¥uœƒ9ì‚¿=βÊUƸÕ™A&/Âw9ÕË3?ï\Ë;ëBY«¼ÄWð‹á)á…_eð–'Ĺ‹@ú2a#qY5 àÿqÙŠ(ªaÂ'ì›Eì8ç"'’G&β—OÞñ V D››Ð…ÙØ g&5‘mL´{ò·¬ò±õ†þÂÞäÖñfa^!ˆ·¥ÖÏúsÚcïu/«Ë› ¯ì¼ÕkÝ«XùçM)¤€‚Fwٰɦ¬ˆœ5Áªj¬?É4ú²šv£.ßÑã­±¿ïà-ÎX‘[€Mö¡&Û‚m”>DË7é¹[i6R_?– ¢FôÚ3u±® ••sÓhCJÉþ뜧(Åè“Ç:|6c”.Á£Ö&)€@ mP‹´Bxƒ3ür‹É-Ô­5ÞØµØ²ÃÆ`–ÙTnîÉï‘ Ù+Y¢Í[®V€TYiÈÛÒ­lÛ°Ù e#J-Þ¾ ¦¶CÍßU½EÍ0ƒÓÚŠ"ÛÀ.I=eg"€Ì°Ëßaòj˜”`,)BsþÙ;T& Fù(Ç"M,Ÿ3†J² ŽÞ£f<öðe,Â?6ÛA-rêìkå#m#­)–„j&£Ñ‰“ãäaëä˜'Ñ ž¢‹'sžôÂ)`öòš]a¢ëtذÒT…©VßînÑFÐGñG–±Ÿ²F@ Ai\Ô†LnCýÞCA/DäçBïIe/Õ‚ª¥ß]ØS¹)U,³ÚdÚ‡È6Œ´0‰ÚÞ+3)DlÙž’¨ls6iŒ¤D}‡eOk@bÈRØQ³,RDq›"%y²£ˆv€X…*¤f?l5_³R/M kPVå!Œã¸áÖMçP¬¢¬¸òaÖ{ÖÙY½ÛƒÙÖY9Q’ìèZ2ˆ¾£Ö‰ G}ç )×=·û•©XÏѾ8ZQzÇXúN/®±‘˜ Îø OE¤JVhÞ(gbÉ’Rþ…sÇ»•SÉðNÐ…Ïã,ã7ÛF[$ÕT2{4æà’Ù‚öí0ÎËÖkš‚Uù‚á)”yâYm3Ød—‘ )NH¥FÍvNRN©Yîå15«Þˆ º§êœám£zI·Cν€fØ-àÛÙʦ’;À'A4•í! õüÜ/»=ë<›ÊµM²6±?/×ß kúä¼µÁ xôr“&ÈG`g(‘”û;–Û»:=Øk‡«½°“Koüõ¨VReËÖ~Mc¨WDzfjL‘¢ÖÞ$åÂWrqÎõk’º[Ì•‘%Ԕܖ)È7q¹P&ƒ‰¾x2.w–Xß—êlîõm]´GˆX*AÐHÇN²—smh—áæc ïa³– [Á‰‡ 8íå!1[d"l„2n›HŸòm(GŠì ,>ÍwºÛð¡qA¶ÌR’Põ©Hk’9‰¿kæŒ#ÒT"ÁK{¨f=¢)So¹st;õ–6`ÓU¬ËY 5»òT]‹¶—¨HÆC±ëîD‚Xu¦]SöŠ·fJ€áË™ ZÒ*ðÎÀ·™®Š¥´úÜ£%µèž‚Ïë[ÃÁ¦ÜµTi1ïP—Ž9XЦSñƒk›XZ… aße<. 5Ê•9вöYn“·¹ýƘ]6£z6Sj†Ðoyï{mzIP©ƒÇ ÷íOŠK5oµ L¢©8lzö¾¶ìå¢ÛäyT[lIÙFvE&nù¬Ð¼¿Ó/+4»íòP5˼ªòÐ:oÂþDȯþù?{“ΪKÐê< ÝoÕ®w×Þ雼VnÌ.í½j'×8ï]Ƴž¯'¸‹aø*ž›guÈÏOýCûLÁÅ} =&gö)˜©¤ïòÓ SIßìSè1…©.3eôõ~:aÊèCø>…S˜êRSà™)~ê3•)xÁ>…“™êS0S^_M᧦¼¾@ѧÐc S]ŠÆ¦”Õ©[iB I™øxjk±nÔšÓˆot=`NWÁÖœ»5òÏÛX`ßÈd ¢šòçAÈQÎ6ˆÊŽœõç\qS9sÿ…WGgúõ¯Ž.ó[\qqÚv¿èꈚqÓ[¡fI¢{#TmDé“H¹2~Ãä„÷ ŒÜI!.j‰äJ"LÜâÁë›jòJë§Ï äÁiÃJΣa^Ú[ª]¦iáNRÎÛséë8÷VjºD7Nwv¿¸Ícò¿äm¸’ô÷ òÈNÆ®äôç _vflRí…ÿ_±ùm¯Ø@õ³3ÿ¶K6PŸÁçÿòÍ»t[ -œ»“Ž“šìg\Ô…>äžp1ïïÇpk‚ç¼ —‚¥ÈÊM³iìŸ. ‰Í| Þ´µŠœt$e ­¡k;³ìÒãÂÞANú(!ˆÐN¹à½ÃEÞ_ˆ/X—cœ oø ›*ᆺüÃ>ü‡€_p8qhJ|؆§sýë—Í º«·=ÏÏݳêÖË!_ÛýíLfír) Â{ÞÍ[;‡ùªBL~ŸÚ3pÕ?<ä¢x“î‰ÊOÿ$ è4ó¶¾?~¨ÝÏOׯ¾õñòý¿.Ÿ>>ûpyÿÇ囇!]æS endstream endobj 33 0 obj 3612 endobj 34 0 obj <> /Length 8 /Filter/FlateDecode >> stream xœ endstream endobj 35 0 obj <> endobj 37 0 obj <> stream xœµ[Ko$¹ ¾ûWô9€½¥wÐhÀ®r›¬9å±@M°“ÃþýH$%‘zT·Ç ÆvWWI|ó#©ZžÔé÷‡ßNKüç•>…MŸ¾þýáÏ8ý›®.§¯¿<¼¼?8ÿ´žÂ²ÅŸï;ý°ë“²§÷ü|6V_õr g½8{Qg¿zç÷ /ú¶Ë£‰×½ºø³¿zoY.ñ‹ô­WÞ\Ì9X¿Å_ð·w—Ç´ßÓ^/vóoéxoH—\¼dü/ÚsXpLÚ&À°Ô¿¼ÿñáúþðeĆ_×̆:E®‘v“hO ¤u$G¢t"/’mÅ@j¢"²ëñ²…›óó^GÎéYÿâÜé’ ˆMxæê}’Wä)~P¸Í£­û$q¤Ÿ(Œ2rgþ1.Ÿª[p»²>ЦZêÓÚ@Qz÷@Jº^hð!ïƒ÷îð,X9$ùB#‘Q?¨°ý²æ»€h"‡* öÉ4*AÊÂ@1™ÎH ~ 4i¤.û׋Ä'î„n|Ò,”d\Ðz1: •°Ð¢åTlË9é˜.ëy.*ó û‹Ä™§­I0:‘:K2“¯ÐªóuUô_×,¬Ðü—äºÉ6M\p=ëWRZüé ~§âõÄz’q”E¾ÃÁÇäÜpsHw%u%Ÿ´é[Çn5Ú,ñ߯.ÁÖV•à3.fT¼_]6"ÇØxÁšŒ*ñQ4Ä€ô—?ã¶þ Gq<¥üäµy’‰ *ZÞH&~;'ë5ùç—Œ>±Ãº;J"Ù92Ó>|Ù‰¾ï99)z8 "þ7åþÄmdp‰<3šP­NœÒ¿þú°Dù]0ô§–Ó£zÒ§_OÊlñføð¯ÓO 3öÉ6Lƒ\Qús;ò.æÑÓhF*Y%rËÙ-ý‰?Ñ ž‹  /€ Š-=‚§Ë{´/ôÞ´ÓliÕÐ L&‚’¡in§ ”ãi“5‘¶¯'u/ßÝýD¬ÿKTà–¡Z¢Šÿ‚ÙÆvXé¼ÃMü~n‡jpœäûþÏidtÛ†Dbä »0BŒõ’GÃ/Ý ˆ&åN’$t2ñ‡ N.lO¡õ†`èŠAò´´£ØãÏ/9ø€×ñRÊå”§WJ_”U<ñ¢òýdfQ¯`†h[XŠßD¿‡x%¶ sáŽx3ÚÅž˜M¡ãLÝ+Ù¹¸#RurÕ5Á54¶7â= £X2-›z À3£ƒ¹“·“`Ënà|iþ$èJ‹ì”òRDmòÖQvÞÇœÙø£M~ž¨4G Ù‰e®Ǩ2AœPm|(ªA®±„Ì-(ÊáE4¢­î…4‘Uу>ÙŒ‚íhu ,Ja˜ä×¼!®À='b0Ž¢D4Sù0–UÝT”T^,é_ˆgnvŽ¢o¶ð¸ä¦·º­x(1¥ Ÿ‡°n "7гÝGLr­,Á¯C92)мVmù¨ dßq¼¦±®ÑlÕìåBœÊébqíÛp…0ó±ãŽÈV¯KûN¹ÿ™ãpæ`[žàÑ€ö"£¢­ÌчãÞQ£Eþ~0ˆš„]FÁã$n.6o÷ZrmSD”‘ƒGåê\?´–OfRÍ›9V£Ÿl0Üä÷‘ÓäŠ'#QŽ˜ÒŒ¸¢|Ax\µ1b²ÁsÅg*ßC_ÎAÎeq¶Æ°®[_°œ:»ë‰H;uÖ²=4 í;<íµ vkM€‡¥AG íyº»CÂʹGîÂÆ‡a¡ˆÊÔ5ö-ý±Ïº®$@'÷B—KHHYÙª‹kϹ|Ã`¯hGq%/ǰªñN\ÜfÃp€”‰0ÕÆ¶ŠV¦Ã1Ïy|B…Vªä V <¤ X£u{5²‡Öèj î¼;¦î“֤͒bUÍ"Ó$ßÉ}â(ÅC™†•Gˆ¿éQÞ°)YÌ686¦!VDEÍ,—c)^ô0W—¶Í‚Ù*êÒxŸöÏq™ĤC“X–1Bh€3#˜Ö¼×#<Ï’‡,D1‚‘1žph²‡UÆð§µ@Uh+lG8Ctp­‹uÑ<…8­ ÛA3#$ÖÈ ×xƒâvÓ‚\‘`‹ C4 ®ú«¾3âÛµ‹÷”øxVlZ)5( :k³{’®†º¶§b¶ [ü"Ö‡,ùÐ%±`ÞüÓ^/€nÆü™7^6ýF¢gL“º_Ö³˜»¥†Ñ“†2ë“3roÖ/šº‘µ=Ì–šÅÇÒ³–¨%=*†¦M±dÀ2²FMKI–0ßs¬\¼¡¾¬â^—º\=0Á°Ä Sy¸ãtu'awù¦‚q™ÈÒ%ªwÞ5U_²H­—š?4 £ž|cmåGø¥"¤’Û,9³„š«„o¶’2–õÁsavgé7~–µc ¹y‚¨}ŽœŽ¾f}J›†µÉqáfõÅP“Š^ìöâçõRúÅ{M2%0u2Ì8f¬ïãæâ(ì[ˆZÙ(Œ2É4#uhGä×F†åöÂn¥Tk8”J àõ&ñÄç7Á.#Ö¬²Éî¹ýì<˜ctÁ¬¯¢Ñ›‹„à að§8ÞŒôëžv3ƒµeº°°³†›lóð¦ÜíêÁ.i”Ò(›µÅ‹PEúÆiQµ:“½MjçæÈú^@³Aÿwâ]rYiBÑFÀf‹O2ß½Mï{:nPR2Õ]-DEYt¤F³º.Õ(9w†Š>Ó0lQd›£Ê iìKZd»Ýïû¼5ŽŽ/a21ÕèÃ:ÖH$«øŒô··Z£ñ*Ÿe`Þ{êûÀÐçÌÚRÆÑcm³7·‘\Õ÷ØL  ÉRï' Mf?ùµRU1t…SŠ]ƒ½áÂé‹’¸UÐgú”tO”’Q[5Ü[Ð’s[rΤ5 Gjš¶:êzrNmbg©É&‡júÓm+™›5ƒµ]¯‘èb÷˜…Ú mÜõ›.ý‹îý¸²NP 2wÏ—þ³k@ºet6Ÿì›%t™¯õ×»íØÕo+{Ê;°±~×½½ù¾ß‚a8­Í«ÝT¥ºdÒOj`ey–¿waÖqW¶û‘Ý*¸AÝŠQi— i×ü°y'<²p½Ù>݉Ùãóô:iXR#²Ÿ½Än4»HG­ gr;vkqë´—M(? ÓÄ0uέJu*t\ùÆO72×î?pÌ|‚ß:åGP­Kƾ”¹Ã?ÊŒIŠ…[ͪúLX»áD†¯ð¯¤š®I Î×5á;BSN¹®œá\)ÿR"Ùl%¼ŸôXúüÓóAM(iոá²P¬NE× jÛ{>œ¿g|”}"ëZUçj³V ý ¥:6Ð|Ò€x%U‚̘?6Ô>ôÉ’ôVÏ95E!M]É¢4x¼äÐphÍZ C¡¾¢²YdÍE’«No;'m³'›g6P@úiÒÂÛ­|Ï¥yÍqBެðöûÜgrré›#!«V…Ô·8Tº³“Z¹Nü'í¤A·#CBq.ç0¤4]âC™ÜW@&3c '÷q»Ó¸m.Ö ÏÜòÓÎ^«Èz(Éc²X^h†!Ž«4VP4QáÛAÁªLÜÕ`åZ$Êdöiþòq`Ǥ0¨I‰•]¿4+xðó5+Ôéñ$ 2ÇZy–Wìð®tuÛU{ (aqšÊÁתÀ!†¡ß¨(Ê}q~„SŽSFA“Ö¡1,~zrYÓû3¯ "\Õà‹, ¡|Þ51çûN8—·{ œE1,€µ$S/ÞÚr…îóû-€˜ü™úèæ¸DRkØ $Ø£÷xZF´9Œ9%ª•£ZŠÛ«j!C`dV9èÒp5vû4ó5¸É& á[nì]„væn`Õ¦>ôoíK«ògçäÌL4@YjUÜ%y ”»÷§O¼ÄàÞ¿´p³2ÝçÙà¼ÊCm=îÑU·&”U )Gergh6)(]éNe20÷cñ2d¨G¹Eìg'øÖ‰½¶§.aËPý©ÛO¬”ïÏ6Q"ȸ3s9Ý“9ɘoÁzÚŠ.Ã>³\Xz© ý6i”þÎÍ^7çyt©¸#:((öZü[lqiø S¯øbÊ‚'ÿxSñʃ©Ë›4g%nißúþÕÁ~šPwµ€ÇšÎ´š•%Ó|‹ŒºqnÈc ©­%Ž´ôo²QÊ3GÇ¥Ùn+… 94Ô³ÿ– ÖJŠ5hÁWßü.Œ|ÿ§¢LØØ˜®Ÿ¤jÞ˜þ<3C‹øþŠÄÉÌ?¦Ñ|çÌÍ”Z~Æ‹×3ŽüúÞ=q¯²½—×£ôäK÷ ÆX×{|$A!5x+²éçË%¼Läø}OEÉùÔµ3zþ´­qJ烖É&šuK|ÝóÆ¢…®EøU†`3»Èr4w¹›nÐ05ºÀ¢úÔ7 &;ôGÛ3|plÆ‘Eh]ÎüÆGgÅ\-§Õ.Ù|•iþDCÙ$“wŽØXGÖ„±œ³Êéñ´›†¡2”ñt˜h7ž¢Ì`¢7Q¿YLzãµ¾ä£áÌéZΜ~9ývúáúãOv9ýòßÓï_ÍvzûÏéËÃÿ퇪 endstream endobj 38 0 obj 3642 endobj 39 0 obj <> /Length 8 /Filter/FlateDecode >> stream xœ endstream endobj 40 0 obj <> endobj 42 0 obj <> stream xœµ\K‹$Ǿϯè³aF•ï*hf»»d-è`|³-^¯úûÎŒÈGD¾ªfm!´lWgfe¼#¾ˆÞåM\~{ù÷eñÿY!/n“—¯{ùù—ƧËåë//Ÿ>¿û¶^œ4~Ãç¿^¾ÛÅEø¿ýýÏW»ÝÌÕ>¾½ª«5ÖYs[¯NÞ^åU.·WW<à{‘¾W·WÁ¾â‡xÎzÛüañ‘º¹°Np‹½‡åñ;«­Çá.A7ÿÐ\Õ§ð >÷šü8Á\µº©«ñ_»«17}Í·0á^aå^7¼0ão§ì(x€â[üG`Hü˜>„…w¼9y£³™rx¸Ó«ÝÙÉÎùKjìóöºFãm#Oë儵Fzêã2ÿòù‡—çç—»ââm«Å/ ÎßMÞl"#1:0P>G'{¸ø ¾é|°„ƒW7Ï'éϺu{õ-JHÏz¹hewvP 'ý—”*ýéïà·ìAJ˜áòyábĹ˜‘‹µžðBeåÃßb‹bú¤7Ðy¸–¼‚VKëŠ_>òí]º[fÀ—ÀãÖ7 V·‰ltÈ™?}LúÍÿÿƒÿÿ׋¸üñÅ/kÕåË‹4.lõÿÇå§ÈQ¾¸¬øò¢–eº6}ïWÚõàܲâË‹ö*0[›¾÷+Wýf¦k‘8-üŸ™<øt@`Ü$L×—™Ìùz²&’:]_Vdr§ë‘`¹¼ÙB0|: 8îr¦ëËŠLð|=Y ž®/+2ÁÓõ@°Ù6oè‰`ü4'8íäÌ×—‰àƒõd <__V$‚çë‘`0òL0|: 8îr¦ëËŠLð|=Y ž®/+2ÁÓõ̆³·:edë)ý!›O±Ÿl>çPN{XnÁ'\736_éС0§xä÷©?9t Ô½Óä¦X¹çã(Ä½Û wÎÝÃXÙסƒ`ã(6R_{\¨£:öÌÌÊç·&ÁêL¤¦¾þ\¨£Îò\¬ Þ¦çl1jK–=•SZç·Z½¾9L2לdÊ’+†Ôϧjƒ4U-Æ_¸w†^ónŸº’MrÕ”øY–ýUç:Ó?Õ…ºä]oá‚f˜—k±ù­ãkí)ÃõIé¹=Ó=Òy–W*(F‰ò:N»±ZŠüõÕMübôV-reUÀUIùôé·¸}þµË<©õƒ]ëh—Ûºïòu…2J vi½%ê=ÈËž©¾ÞAéµMâP¨ý°Ìi5Jr…ª¸½„ºCEÙ ªY¨bëcÝ–N†,¡Æk‰[†Ì·ù]ýCæ¯rð.3addþà]Sö›5ca¿3¡5žIb¤øYêã‚7¶Do— v0Äè]ÛT½]Ëd—óAH;²±-nš!A¶ÀÏ>@d|¾³pÑ0DÄ(Ö‚'Êûj‘€ÚØ§ÕøïN´ÀP·-Ã8ñ‰ v™‚Ly’¬¦+0B |¹Ú"šòÄïmÔ/¼š¿Sx5 ¸‹€pdD’2ú‡ŒÃ™ÃËçï™ï;¾»E5…‹ŒÒÕ!p•Q'vG#ç"±ˆ¬Ý ‚WA‰ä.\9D"A©›wo¬9î‰F%- À ÑÁ®³bõw„/3“ yT¬Ý!Ì22L4H¸¬²I†&å‘^¡ Ñò`´a“ÒTX[¥‹üÓw· -·Ø³™À’}¢E÷¬Š³³îº"äZ¾è+ˆ´ß±•Yh|ͽÁήȀbuh$ÏžCÀ:ÈÓ™„ާ §¶œTŸ\,ÜîùÕPïÅçñ¥IŠ;ІNâ¾i¨^Šò¼–] 0O•aq-–|Ð(À °‡=ƒÄû:¤6Š%;Ò‰dð}E*É2KhHüªNó‘w‹Z¨J°ð…4lp@ Áñ ¶š’Õpìko—M,ûÛâÃð•”çKöÐH ѱŠÙ.YÜÍ„G§™&èM7™•$x¦ÖRÝVêSP{aÓˆeˆø ÷ånW¬JšñÑïÔáM7Ÿ’ä¤#\Z6b³ÓHT´‘¿ðt˜ùs‚ƲQ·ydÌ6R|¦"åñø{1çÉ£Î(ŸáˆjÒ¬ L5E¬µuc(>Ò¡¹š¬¢Í&‰ÐCë)JjñaMÄÓ¿I„ÄV–qÂ_.å—ø"c÷SÉñ­Ï´?Dœ“ÛŽ|?]$éÀa£³¬ƒwê|¯­lBx•7Åæ+¼‰ºÈ'gQD¼‡n³u–¯Ô¾¹×(Ö)zE#¤ÚŠŠ*Q¤:{¢"øxÝôGS¶Bú£ÙÌšPì /)ͼLöýŠ|¼‚'d CŽ]±^Û  îIäHj®¤ªè¦Ü /ÌïÍ“õ*ˆ=ÑÁh2 pB¨1 ÈW“S×»SK úR¢ +ŠKfž~ ™’ôZÄdy[Þêøm#£’¯yƛ‹`é&,Š/2Tñü*½˜J_™6¯< =àZ÷\¶’ёޫ‹B(IñØ‚hþЙ&/Üs¤Ý̧®ÝÇ!’› !º«C÷ åwñ¸Í»i\6)¤ÐZŽxÐû„_£0inÅAÖÖ§S KÙ¯È8xXgßsH=öU@8>É=|X[Áx×2ŒÊŸõž3I·ãŸvrí3ÃĨžý3 ÿweO˜¸xEÊiÔmÿ@sMµN+ 3¡½ 0LÕaÙÚ‚<N “0ñ kód v•'¿%Úì’Z áÊÑ‹f°O/õÝ™æ0¢’òq?HÐ$ø^Œ"ùa›PQéhƨ»­‰§Òì´y÷’H{€V“°•˜²´åCRš™¤ÕfÚÀNk›p0-“畤²CŽmÉeÖ–Ú©—ÁA$©³ÊÓ$;ÁË’F\â!y8ÏUp)¼êk¹£aõM© r5†µÌ–«z’#4H6Œ""§ Ë_ ¶™0·OÑ[Ä€Ò%`Ð+lòƒˆ¼Í÷ü™êÂ*[$þ~“ÄòÜJ™€>5!g!i SÉ‚$=lüнÇ'qú§u¼JÖõ\±+%•QKÌŸœ!(1¦|ܲxdÕ,ýS8]ÑÑýuM7Î^"‰ˆÈ ³…sñÙ­‰áaB±¤*’ edYus “ߘ*°+Aý¹A­ EÕÙ³sµ$ÚáëR¶ß«Bû૯‹•YÚº8ä7mÚ_wicˆQó^QT£ìë2ÿKêÏx¾GÁù«”¯Y¢•ú¼Õ£XuéP“³ž€Z»ˆ*é°´VÇßdló^j¡µ£*,2ÍtÈ‹Ð脵ßä éžÆÓÃ5˜UÆ©p:0CÑ õà9aÞüŽò¼L0ÌG˜4À,mÏŸ¥”/£D`N«ãpAiŽgŽ€¹ŠDBêáËфٚ ¨þµ´ˆ(ëÀZ¤1ÕØ€©!eËò7ÒuL©'ÍŸ"„ÿäÑý ¸dãMí¶ÚJI,^pÏ0mšê!â,´Åwðb•ീ”Ûý&‚-yfaG§öNåê KF.¦Ø’¼Ðzà'øÝÚâHÂY’CªCo´”®9_P¼Ñ©8:jÞ~½*ëMÅ7mð7 kó@‚ž¬ÚÖ_Vâã«Å©b§hTÅ«ÞlE:ƒzéªD1ÃA˜(Á'QšõˆN’vÔVH ¶RgW°ÄvLs vF§áÂj.¤xgÍrÒÊb=©NcYN±“Ne’²ó¹=F.HR4ài öQÆ [£Ã¥›ä¸SšI×­Ž0™[r·›QA@Éï†×a;u*dÝF‹ˆ†1 dÔ£Îð~¹:IáH6Êà ÖLoæf›Ši ð”w5®×ab¥|Z>Å<-ö!1¡¡­nÌÆ·ÀYt4ˆ[:½ €w¯ª)‡æ*}Æ$YY3UÙDƒ­ 6‰Sy©ũɿ^K¸Ø¯žø¶~S7;‡¶’´étÎ ¥òªûp86ÁŠ~7TÁÙ’ AïŠÒA7fâÃ*±®Wž‚Cf¸¼”™­¥1“×újþúþœžWÅãÓÙ$=D1`Ú]–0omàWšÆð÷ØC[€/Q B¹g Á®ô£XÌ=Ÿ¾c–Œ¾ ‡ùW¼Â¨ãL½…z—t³jh'™ÒÄT+°æ3ª‘JV–³;ùÁ}“,vÝèy„³øÅVïž%–Éc„FzBeÒõ51ñß ¼cÎd-¯_ Bêá™ÿTözí§³g›ª$Gå¸fHnê²Æ§•-=Nã{úܸ̩jpÈf4_~r^)µÍI¡¹ìˆ8Štµéðü³ÌIÇù£lCKí„ú©x•i]¦*âÍÿCq’[V4%mË1ö(f?ÊÅTQ¥•;–Øþé ¥LŽLwÄW“õ‡.<—£Ü8dðãß½Hø…œ£[fªˆ‹Œ|¼gpi?¼÷7±BÊ%lUS™¤ó¥úÚ™nþIZ¦°ªtø j| z8Ÿ3[Î̬GÙÉ4?ÉÄÿH†±=²@îûk¸¿xþG¸ìàw$µ,§š°¬-Ü¥kà[9V°ÔÑ<~p%# =kú«"AêøÞq˜sfÌœ‰.fM$ÍZ[ëÖD·zâsP×Ý–zAæõjÏ¥^ìða}ú:ôáÌ¶å­ ÖeùPFÍÍ8ªPr,%M 厙’„¦D ×@@ƒ!Ûdt=Çǯú0µ¨7q±Kõ#¾ò¾ðëïžßÿ¤Íå—ÿ\¾ûüUëËã_—_þ Oóܸ endstream endobj 43 0 obj 3857 endobj 44 0 obj <> /Length 8 /Filter/FlateDecode >> stream xœ endstream endobj 45 0 obj <> endobj 47 0 obj <> stream xœÍ\K‹$Ǿϯè³af+ßUÐ4ôLw >ÈZÐañÍ–@X6^ô÷™‘ù¬šYÛ±šžê¬ÊÈx|ñ¬Y^Äé÷§žÿŸòä6yúú×§Ÿþpú;^]N_yzýüdìËzrÒø>ÿåôé!NÂúùËÙ ·¸å²¼<˳}¸Õns¶·Ë³ ßêøÓÈÅ_Ä_VüÕ/–{öëÃU‡?ïV\Ö³} ¿øeÏúlmX/ØG|¤9§ÅÖ¸Å><tv‚M­p³3ÖøG;uyguM+pmUá{8‰ñ;©‹kv2ê"ÎZ]ÔY‹‹>kÿh{Öæ"Ïæ¡møN„eq…Ñþ²~ÄÛä…Χ6V{‚# ¾íq ¾÷g‘š$+á)ñ&çýŒMÚm+þIA·› TG‹[ '9Þ á&T¡pÖi"tuì&G€hH`+Dº€j!HeèŒ"™){(·~ØôAví‚yëA—´0`TÒSä6ÕƒÕ¼èÚÒ£¬Äq»ƒ5ò©´ÎÂ"üª(\‹À©â)Úce^FÕ ó3^{[²ÈSM'ÎÖ†êÃáùQKMðGv´V1}FèÒ¥%ÑÇâ :Þ:(ÍÜFO°aGò2Y)ÉϨJ)€{¨AÁ-%($ÞpyìïÿTþN6޼t⣠W“!“É‚¡V>;~! „ÁÒd‚,² ˜OþÍñ‡§˜¢6¿¾$œ¬Éñk“ÀØŒáÞQzž…;>ÿÚ½akn&תåCƒˆTÆS¶œ ïø²&f˜l3¥Å ?ÝÈ8 šÜ•ÁP%ĶGpfÁ©5’F…$¯Ìšd!ð¿=бÁºë•›FkX¯×.’ó–^°­­ÌÐ¥[-,êâÎ <ÇÛ\QÔÚ€ëa¼KVïÝ!¬ò鰰Ù2l®EN‡ ‘óNØÌ…(¹j>˜j˜n V1–I·UÝpì¯eñ¡z­÷â#)ŒíİC”ü·ÐÙ©Ø}r$kL%$çµñÚ§™ L‡Õ@úcïåyeÞð^úãžH½‚ƒ{ÝEã¨á8³¢k)  à;°ªŒI+HMî³ñÁ×+Â2°ƒé¾â`eS\XBÓˆLq‰tJC¾#Ј…ø´„à¸I¸—µQIÊc ì{¡[b„KûscAÕ0‡†)NJî‘ç%˜Ö¡kf^erIãðñ7 ÎU9{ B䛂Côé&…%–â¿\¯º@›™&‹ž&è\D±‰t¹ÈLÍðGdÈn3^fa\¥‡3Ÿ.¹Ék'ÆŒƒ9$„Ä"å$&”<¦„xnQº…aKçÌüo¡lµå¶ZÒ5i®}RåW2¸XÇTâN¨T½¦ãæÊ@æf|«H#XÈ–U9¬†Å¸µ>ÀTÂD”XŒ UŽ“W¦ý ÌÄHU§TZÛ¸–Z»á£Þ’: Ò`‹LÉ2»‹DõQB. IÉMé_áñ•Cdå!GN×)<¬Ë†K’µ©Ë†Tq{6©ä&YÅíÙáe¬¸…r\ˆ« w̼{=Z‘ÿ-\ ©€Çû@¸;™"™8s!s=0²q@Q[¡0ý}•ŠñL®.4r çøÐAqp?‡à¸œÓï…UA¨ŠcèÉ ÌJ¥áU=/3é„”<Š-`° ¶‘—n«#¡µtºŠq·°÷¯NîÔŒ¦ÂV[ã|Þ_ÌÈJêÍ­?a.ÜgrëÙo'ÃxÔí¸Œ@ŽÒàáCºÙH ½ïNõ˜ý1CpjƒÌ½|jì ²ÀÇUÇì¦b—¶õH’Ê$=§[3}ïwF½è>Rì4òb,\³@`K‘W¹½}ˆ¢=¬¹Vb-1eÔ`µú¶‹ªñãk󯪘ð•ŠÏ #EÕŔ޵W×nt_0ÈV&©Y²xËYU²ÂXÉ/zH„‘:"kž ½±¨zúæøÝ>WÈCÆÕ’=W‰|\!ÅfL†Â3Qëmk]5ï‹æY,‚× P¨På=bÖTVI×Ço\ŸÊ:kß“o*~CnÖo9VÎe¯P‡¼—+:J2•äjÛ$°õ{Ìg1ƒ*¾@>GÀ×t~V\t¬¨)¬ÖMÑ~F»Õ©†‡œc¤¸-”ÈËF OïþÑp0Y†vEçNj†<:Á¦[Æý\ìœQZÜÄb2gíÐzŸóÚÓ§Z÷Ý” 2ؤô¡¨ISÍÖö2”¢4oãİáç³’ƒž„ˆÃ=úäR!· sJ‡ 1G9µ)ÙöKRÚ Š”$AP?àyŽåC—`WßµMÃ#>/Ôw€/\i£Ý®v×›¾1…SrÞ6È‚gª©óâ(¢khб`÷–¶»uN–z2·…LïtñžeW=äÒÆ#ôÉ«C [+‰JòvýªðºõÓô*mì/äuhhEADè)‡«°ñ­ ØPµëæø *ôªEO=‚váwJ:1”^œ–*#½{‘ÓÏHÝ•7v¡5ðŽy½¸&Ž(Nd«zîÈB…—s|8жuÓ4K"oB„î”I¡!^B* 40<m½åx%$Ø7–ì;Ú=7äû…ÏbÆ ÓdÍ* Œm#³õ3ƒ ê1p_»Õ˜™t}<߆ÉPî@GjD§j—èï;U”žßØm³1FF³êt.†bø4¤ªÜØNHÐ^0ÿfT£hš5™c¢ ¿:"ï;bj¦ì‰v]:ÞxR8?VVJH¸lJ) ¥)=\ËŽ™»w&ò| ñSÑ£dŠ_Òì`1û³…ëoÛ^ÀpÚ†Ït hõäajFÑÁâü®In˜ËGPèY×Y •ºÚ“‘îä-ŽŒ½Lål]ëÚ§#tMU»™Qí²±[™@»‘I]¨Sx¡, ªÑ&Í0ÕÅîPüœJÂe›ˆ9OQØsIù}Î]%ýÿ«qO9ø”‹÷ˆíEu]æ4ØŒ}ë<æ¼;·*›Ô_æ) xÇn–B²M‡~8…Ëey±ñM!!Ì‹Iï +þô]äÊïþß÷þ߯'qúã“Ú;%–qúíIj‰Ÿÿvú¹X­O+~{ ü´;ëùÇæüÏ"E>õòŠàóŒ"Z »Í×ó5DÑÎ@‘qDÿ4¥&®Ä}&kóŠDÇìÉ@…Z}؇tÄÏSJp5î4]Ï×$zæ;Eþ>MÅÏSŠp5î6]Ï×$Šæ;EÑ ¢øyJ®ÆÝ¦ëùšDÑ|‡R›™µÒ6v÷A½Hw”»û WÙýGlò¦0ëÚ·vn{¶Èµsß^¸æÑÍwŽ a Gpª´à}4)íëˆÅ—ú??5CËchžqíÖrÜ9‚ŠŽ¡·Úª€+m_¸-œ( -dð´r³ެZøèjŒ˜À°öŽ/!ÒÐiÈPyö±…¼L5 ޤ]ÃÃWé‰*näEc7…šÑc”ìÉSx ; CJÔxR5ÜŨ©giFœ“Au¤-ƒ8¸ŽÖ;ݬþrV[î¤LHÁÚ›ñ%45¬ !‘ZWå™qaHº ¯½;ÖÁÊŸCö’õ#´/ž¾Î5ïA‹NaKçy³¼Ë§šƒ)Ñî¬wJßà=¬Z¿ª@£ø7|™iOç#+DcñÚšê¾(9-;UëK-/j4óz^ª¤ð‹Eáµ·{ÓÃhç.f¼j§€ýÁ 9 ‹YUÆX¿2yenáKî©SÄ^å¥aªruúZÅ+ï|>î§±ÆúRÚöPË‘W?úN$üy(ÊX× Å>,ð?Ï0µíßõû,Mµ«©LèÌ•H:œ´jí ÎÆè½M¤Äškx˜²\©{­ *hÑè™k¦ëøÎÜ­äRr~A#èê-ÈØ1ÅÅ—ç\›ù;i…dŽút¨Õ÷õ+"Í@A[sÝCv!ŸÎ‡ý\1¥ž›(ƃÊòùíœéŸP¨g%rÁ<¾¯À›/¬ƒ&øôyUߌQ °yM¦ZÌùº> /Length 8 /Filter/FlateDecode >> stream xœ endstream endobj 50 0 obj <> endobj 52 0 obj <> stream xœ­[Kä¸ ¾÷¯ð9@×Xoh0ÝU^ ·É6Ã"§dw “`'‡ýû‘DR"%Ù®Î,¨érËÅ7?²ç‹š~úmšã?¯ôV=}ûù鯚þOçéÛ¯O¯ïOÎ_–)h_xÿÇôiS“Š?ýòÓKPÁyåï×õ%Øë³yñkú Ÿ¯Ë‹Wü‘ßü]ÏWGë\ZaüâïøJÚ)=Ô÷ë³}‰KáÓán¾ª— ¯>¾êßp_÷âo숻Wqƒ¸èY¿ÄËä÷âqq• æú¬à ü¿…=îÞâv@ù ]‡_b‰÷¦eú–ŽõÁhXáã ™\Ø92‰½¯—Lc¸Ú´³’óNé(y.>Õa%ºÊ \¹¹  _ 3²vn¿áñioŸ(Wð(1žo‰t§Mþöþç§ûûÓ—¡>(uY[}ÈÛø%¸´¿Ï·òi3˜óχu[ÇÌÊä$UÈ.ÄyZ°%5$A§åY$ñI >…¬ªøÈCÁg…2ÚãøµÄä ‚Ø_d ˜ŽÅíÞŠ2㡉R~1¿.¥ÃG2ºê©ܹ:±ù¸z¨7(R¹E‰V~¤6~].¾Q¯AC‘9ÂZ¸L©¼Ø¼Ë¬õ7¦dkë ˆ'¯ 3½˜ülQ94b IÙ¯ Ù‹}¾ê»¦³CCƒC%ùê¾Ù­Ð¢WT·ÌçÌ+º-9¢vó6Zu–¬wÓÙjà5r\‹ó+ÛÙÝ¥G'bο¸‹mÏœÃÆ}/9ô€6<ƒLð1WUxt>aªEuÔ®ƒ„£³NTO ÞÜ'g®ul|È“[‰råÐ(”ÜYäæø™Y¤'e3‹Lz)äÿô¬gû•Ä\M>6~®×ÄŸž€Ü4ЇäÑ:¿^‰ºx“x5¯gx™õ'd=H2´>ê¥]ÿ9r…•àˆÉ;÷jòf¾„FÐq'U‹ÌµJ3Ûu`º èȦb#e‰–p.ó$)ÚRI™ÂÃ-»*.Å>CÕ­*Y9×ôqº„·¼a1Pâ\÷ˆÒ‘:O<Ápâj$žûBO©QÔŠµO¤€™ÄHwòKŠ!x‚ô#F­ÂÅ5²ŽçøQÌcÂMA,йPƒaNßZº“&P 2Y2†GºãhæâLÞ•ôB ™2¯¿$pa†Íl²ø°õ)îÎEÚ•wÒå`JGéäRÅγd%ò6`Õ+jè%]µÑVP·hm¨‰k#Çü¨n¹¶4¾²¸¬3ÑÏö¢[NÉéX$­ê±WÓæA«íÈGô®És3ã6ƒ©S±O±jHGy:t͘éšV³Ü®ì"_i9ÒÅž“Sô»Ý.ºã’fJSl®Ó2¿SðλðT~+-ó\±@Át‹){ô÷Ùµ ¡ ßM!ô‹"B¢Âns~·QÞŽôB²N3¸ÊIx¡=˜Rè\”!CâëŽbP"½BzËHêÒÝD/&HÎ-}ÐLA.ÚkºÈ+î‹1'£x¬-:A.ö¢’K¼ÞmöXÈ¢ÏñBüÐŽô¾Ñ<ú€Ú2”Ú0 »$ÝŠ”¡”b¹$aÅH­tdêÕ[.nuï°5î˜Gù ¼sЄËAªNÍǺ>,î;Û%”ŸžÖFC?Ï£MM·RîôÈ“[QðÈcRÈò4 ®5v«D’¿‹ö7Úú*Ö$M¹–<˜crE‹)‡>X°:suãRÕ1hôŽiÒ™¨M'èï®g?Xö„>ɯ1ïôXÅш ¨Q›¸tè\òöÙñÜ©„¡#¹ pdTXë¶ãc!)Ì­¥ZÂjýèô¡Õ҇Ù!ÍUátœ/Ø¡f\eʼn}^.Sżù•ÑÜpS-e×wj©6¨òAN}”nk„X3V>M¬ ¾¬2ÇÕdg'²ûëSd÷ ü~™çëû?ë:¥bôäëH,}eÔ‚‡ª¤§®Ëˆ ».i¥ÑpïPif×ExÂ$ôN­ËY~OÞ€#„ÑðÆgºQÆ—ðdþÁxØ=hÛä’¹ãaQ2È9ê°ˆUBŠ-RGNÊ¥Èñ`Ñ` ”h»< J*+È¢kf:tÔèÃÛZºàÈ÷bœ˜GܯpØô°à.ÉÀH‡kIq¤{vÕƒºü°ÓNJ+óÐêþÔîbõ{AGo¯*HxVð II†ÜNJQ·žG£”"øbý&V{AÚI—EéÃ)%sÙ¶xQÅdœJþóêÁÓn –”\5Þk ±v E͆`Ué1qAT<µ&ûÐqaB¯Ý«¨ª<©j.hgù\äÚ&Kñ;Ù”ž¹¾¾²ªŠ,¨@¥År³6Ád€ƒæ¸Um·ÁçÇàݶ2ªåMÜ­]NB=´„sJ¼£ !Yw‘k½¹;÷?ˉX]QÃ?ïÞ¾ñpÒD!žÇ”jDxȽd‘”7u÷™»¥é!v/Z ÂedŸÊ6QÑ—"%7‡Î7k}—Y@’HÊ,hô~è0žVc»XÑ^Uâkt 0Ì‚ó/Ý(¥ú÷»Y3tÎ{¤¶ ’ãz`§.q0˜Žü(è­xÆ)å,CÐaµ´ÌŽœrroµ‹àÊC0¦÷M.Þ:2#¥¨á¾1òx¨mìôØ$òP+¾ƒWŠï­"¢¨x¸ˆw¦avb~¹k¨pÔ픵ÐfÎw’˜Ú¼'§ÕBÏC*ä¨I0µ-ùB‡ýìd4 rødˆ}Ìé>Ø0åM"î:KÆ{†­y¢—¨xRu[ ò‡×f†â+xцå0DÐ8ðÚ¢k¦Æ£µOLœU9‡ 0û.I}»êSŒZÍ|–OñÚµáÅ÷;y±]˳ãy©¾¿Ú®xæä±Ü ZÇ.\š·Hqq¶fw²ÂÔÁ €éÊpÅpŒBãÈEfO WàE"µ2†ô\/iZÈå“—tàŒS|¢J(SDñ˜ô¨ ¸Þéõ ¢ˆwí&;­jP)h;?ô-Ù©4y–@±>¶¬X5(œí ÜÄ 7ü<\jûÃú ]ÕLM‘Jì¦ðeL#–ìÞ-Œw`G£èFÀn[“Ôt_Ä­÷`ÌB³F ׬1œÐŠ­­M;#¥|„ë—”§)y¢f·´]ܬVªE_ìDHÎ,Ó Ù|N;nYï6^´”J”¡2>€BÁƒï¬Ó–ÅO‹S#¶æ.…)©½Æax1ŠÑÆ#Ø õâ7ûû×§4ïõ»`À_~xš§gÒ×I¹å²Â—M?vr4V]ÌKz-)ÐN¦ú¡JlFµ`ê‡Ä54D­š í•ÌE•W»nˆ”W}%Ýk3Óy®ªÄ±F0:æÉÒ}o€LpX-XŒ¡%R7žŽF·oüè£Hzž©;™6PõIušâHÌ8Zlj×iÙC¾DÙ¸ÜqϘÕú¸æu49¤¢ý>0©ó©£«´f‡È"ão–½œ“Ê/M2©æÛkÆ? Òljz5}r‡’siß!(Y7šg׈¦iëÛøÂÅ])Ë ¿F±]ƒiçɉT ´°mpµu4ÙP:H‘ ʈ$§ºÌÎ èÀü})ÎR£çƧƒéÂ@ßw`J#þžEŒ-rw c£hßíVQmSa[®ÂÇTåðþN­ì…)ÎÚ7–7ØK>pÇù ìÿñÈXÃB™( q„j=xÀÿ¦¤¨À°{rh®~îÿ¼¢-p’µ™^/IÌQæpÀ}–B‹©eòɺµÈå{gËu‡€îFƒ”˜æõ$_aŠ‚ûnN8–0†ÓÄWó€1æ@#ÆûnWäPò6tÑ÷1]æÉ|‚ç€çuй* ñI`cê¼£†£âϺXwFP÷ñ€ 5`¯û±Ifã]ÀK(¥DˆÈAý_N³ÎŽJHôêÑÆv1ºíâÑßM ‘f%Ž2tHvH1ó©ðvÔ©éo”Q©íŸ_ø2ý6}ºÿð£sÓ¯ÿ>½svºýgúòô?VE£Ü endstream endobj 53 0 obj 3177 endobj 54 0 obj <> /Length 8 /Filter/FlateDecode >> stream xœ endstream endobj 55 0 obj <> endobj 57 0 obj <> stream xœÝZK‹#ɾ÷¯ÐÙКÊwˆ‚îQiaoƒ|0¾í|ð²³ÿ}Ç#ß/I»}2©232㋈/"²z9‹Ó_~?-ðÏ yr›<}ÿùå;ýÇ?]Nß}yÿx1ö¼žÜ²ÁçÇO§/7yúôñË?/Zìúâ·Xc«í¶«‹[áC.zSorÿÍþ*ù¡»½Ø+ý^ìW|ƒ&ÛŽX¹8mWkàÝNVí¯0ïdÊë./FïâB3S¸Ÿ†à7¢¯NïÿúøñåøxùÖSÅ:¯ˆ'±&reéC[¸áÇWçToaNE›È‹Â‰Š‡ ~ÅaGÌ ¿ Æ5òÀÕQ8‰-¦‡µö¬ï·ŒI"!Š ½1dð±ÄŸkš££žWÖ>vñ¸<¿9ÀÀ0ÁÂsü)‚Hž~rÎp6GðÉÛáz¢áÙ¸÷QχFÅ]TG”{“öÑWA.ئœ#k u´s#ç4ú|Ïß2ETùP‰àK9ˆkIxfù•Ý/ÈQ[\½u0ÎöºFeiÉ™U¹7íÃÃQ¸rIø5αٰŸ- QyIô|ð>Ú;;¹‰ŠÑêžѶn@Š6G㫃ÄÈèA)oÓ(ÈWG_woÙ8¼÷¤è—[guú J°ïåj£‚X.ˆ@Å<;T súñé1 3aXEa$[Uœå fÃåjžZQ.ÛY ´³ÉC0ÒÿÃ0óþqX§ S‹2ÔºÃj>|'—õn.Ì#1f@rÝ‹ÄD²HŠCÖ€lq¢¨<’x¯—ì¨à5Û> ªògןsDš3Ûîƒ×®2^=¬Ë½»Ãf><·¢Ùì3 Q¯Ñ€˜º‰ÝÌ#V†êgXQ…‹r¢[1ÍLÙì+Š=äÔ®RþÞæ«ÇÖUœZq5gù„qGƒéŠkÐ!ñd¨¨Ï·bª\µðXþ²[ObQ”3cÊ}ÈŠb1ªˆ»Œš†×ùð<+BõLmCy‘þ5e+]í3¬X­y„Qg¾T2j¬gT¹ŒÐÃaQm6§VÔîì¼O`GoDCÊéü+§ÜcÃ3èD_©º1è›_YGAM¤âUØí)ž¾a!P©n~-?€&HÅŸÛùÐŽÛ$×:¿ šÚ.ÔÂ¿Š¾¨4a†À ¼)àãÜâ¶Æ‹Ê@Ï.\^CÃìUèé2ûzQïéXÕÞc¼•^ÏÛÉŸpêÏqÐd ¯ôrlª>Ò1ð€eh5Ê{ o %Šº9·k¿D:¯éuíêíMð´‹3l/ÚF½4ÙäYŒÒgS)âÜÞï‚Ïgè1~±Ë÷»ÙƒgÎx[K2ŸÐÚk’éíÕš€‘›ÛŠڽ‘šO—VÀ‘žMC¿3ÕZŠ˜õ¢ÖrW…ã-É×üè¸iðôx¯ Y‰¾º oØ‹=ÖšqlŒ(þJD¹á Ý\([?R@Wå# bKÏà ¢e Ý`ŠRxô{Ø-kœNêÜ¢>g…à@a–IzEÈ* lÌè^ã 6:–Þt‘ÝY㽇>³Ø ¦D—Åí£×fÀ”LÅ×£Ùèmɦ¹»S,¤H›¸ÌMã9Pž:¢WPDÉCb`ùQúój|ô¯u­ ^çCtfDbÎûHôOÞeI‚Ϫej;%ylœG§´jV& †¸˜Uušß*>+˜¿Çiìr•ñÊø<´èól·%&°±°¸È]œ¶¨oî1¤TØÅå±Û:qÛ_•ØwªBrcÖ)J²P}yZŒ12;Ñs1"×–6<éÕÒ•L ˆÈ!‹§ú /”–BT×#|ê»æ…Ø °h*W M“–&ù‰Ã_°Ôÿøw âÒC‡S³WÊäε¥,ûò5†ÿA_ÚÆ:ÛB¨x[Vñ©‘{U£%Ãg ‰JÃè*XîêØkž„3KÆ¢óózQþɶÁ—óKZÂ1p“vy¨C9Ûp ’e1GM+µXïÜb»T»®¹÷¶N/ËY˜£¤¾OеÚÔI<Ôº%/Éòzñ€ªŒ[N†¡à’ƒÅmkE.¯ìa.Y¤MOÏ4 Á¾!²qÑv§çPÙmELVüº%UÈ¡`˜ªÌÔ¦æZ%Áˆè¯S ­kÒC4;X?•º{|û„^AŒ ±"Ä\nß…7•vG~BU^´L!6ºŸA‚/«òŠÈ_PzÎk»>Àu1R{S1Lkìr†wœk™-n#·¾yÚ(J‰<êæPiÑ0xíZÏUx :Y*Cª.ç@¨+BcS¼ÕÃÏ‚ÅéNè&tïd³â@÷nzÝ7µ 4»MßÄi­,ÛÎø³ïà<·…Àx¤õ•‹hãn'ŠÖͧ޶ n. ÞâEMûÒ×%aó¢µu>Í©ÞpÜ}kµl`«nEÝ+2cÇøÔ5¥X×¶…¥ž;ÜsU(ú 2©’ˆÀUåSå=©Ï5è9G»ðò­|z+ët[†àuW~Ž‚Ž:êVy§kÅ(´ÓEÒúÂÿ²ZV´IþÊèUzJý$SZçÞ|`,2¾³ñçO·R!r$_ôÂöBU >½Â<ú¸Ž_çlËü~¿Ž¾o¡ºuóÄÆ¾êEÒÎwÞø ½H‹Ò lµŒ›öñ;ߦ5Í|35ßU7J$v÷½tÍ*YwZhôÇ'y½ãÓ͈³b·fã[öüŽ™157Zë½xØØÇ¥f¶gÊT¯l)$þÍŠP¦áLÄŽþS7ª·þ[Ù`©µ;†^C7ïv‰'”ôBFd¯d¾~?}9~ø;LúõÓ—ïf;];}{ùÐu” endstream endobj 58 0 obj 2737 endobj 59 0 obj <> /Length 8 /Filter/FlateDecode >> stream xœ endstream endobj 60 0 obj <> endobj 69 0 obj <> stream xœåykX[×µàÞûIètéÀH€ÌÓ€ ÉÂØA¼°@âáÂHرó0uâØÆÏ&¹ÎËMrÓ4mœ¤vÒàÄqÜ&w&½I“ÜÛd¾ù¦ÉØms3&Ä™¶éÌdb1k ¿®›oæ~óoŽ8笵öÚk¯½ÖÚk¯Í‰NN… M# C[==í>„лá´¡íQþµA]À—"õÃ#[‹¿ù!6!™ddËÎáíï½þBJàIût4¾²M°#dLU£@8qå¤pð‚Ñ­Ñ;þ>e ð mß œ¬zªð€/Û¸câ(ó3ðçÇ[CÏí™ü+ïŸ&‘h7²Æ²¾EÛ'&C—ÿøØý€ :m†½TJ)NV"•¥ÈJUªZÃiÓÒ3t™YzôÿË%yWò.º[âA:4 >o¸Ø:”v ´ðÅ®=ã·ÿ¿Õ"%ñz ½ŽN¢§ÐÛíM6íG÷ ¡ 7°¿~‰žG‡Ð9ô8:übÏ‚œ»Dè!´ño³áŸ 0º=ãÞ ò^Cð fЊ¢ï¡9ÛÏβoÆW¡Ïñiô&–£;±Žÿ  Ÿ Íð|žSùz€4¢qò#ƃÀ È* ¿ c߆žÁëÐXac hôYVf%Ú‡îhêúÉâDÊ…¿€ÆÐQÐd mCëPg²ù4U‚3&˜ÍOÑË"íàb_ésÌ9GR®<о¿Õð ¢ þzý$>?ÇìAÇâEYh—ÄCV#Õ—’GÈA4ŽV¡AäE@n‰VðôõötwuvøÛo[½ªme«o…×ãnin\ õËëjkª«*ËËöÒ’â"ka%ßlÒgh9:U©§È¤–!•x,Þ>fˆ±V‹ÏWJqKë1HÞybü€ÈÆßÈ)çðMœB‚S¸Ê‰9¾Õ—–ð û•ÛÂÏáµ½v[úøØ¼¯aÖ*"©€˜ÍЃ÷èGÝ| ðž˜wûèŒgÀ òf•ŠKKHQZ‚fJ•ÅŠ-³¸¸‹)öÔÍ”’J‡1…ž@0æïèõ¸ fs_iIkLmq‹M¨E“¶Äd¢H~ŒªŽò³%fÍqhpÀ¦ Z‚õ½1&}gÏÌ̾˜Ö[bqÇ–ìúT3ÅJ,nOÌF¥¶u^§íÚ8&)ä,üÌצc™ÿâFJ I‘r_# zÁ¼33^ ï˜ Ì-LZxÎ23«RÍLxÀÂÈß ½æ^=hˆyõŸQ\—œ¬·³-–Þ±®7F ½üh(ð粘k fmß"ÿo5#0˜lj6Ó‰œÐ ±éŽÞΣAÃi$8l}12@[.,¶èzhËôbËÕîðf[WïLŒ-l Z<`ãƒØô ÄÓ&ê SÿÕ`¶Ì¤iùZGŸÈ˃V­Á1>&±‚Y ×õ Rh—NDÔM¼æ 0€U›Æ×Z@ •ã±x’ÛGõ €/-‰ùl ×w÷Æ7B é#Ïl™zÀEcnÑ}1‡e"–ai¾êOª–g¬«Wì’ìËh‰¡¡d¯˜Ãã¦#óž™wB*ËÒÑ{9.Í.ã gœhêsSæÌˆ+«g¦783 ‚°Ò†ù^ƒ9&ôƒû,½¡>h`¡%—`8³8bŒ´t÷¶uYÚ:ÖöÖ$I4Pql¡ç&1–^CB „\,¥0…ï%¦9 ð^,ÍõðŒÉ SàæÀà"•†js=ß‹ h‘Ôˆ-á=!w’â7•Ðpjñ-J“Rä´ø æ>sâ*-!ÐÌ'†)Ô¨¾Å&¦2ЈIÔ–zó|¯%d鳌ò1ÁßKçFÍ#Z9i ÑæI_u߀]g,02Có"BóÚ ×7¶Bᢾ›š[›ù™K[× nI D yk Ñj´qõÓõlñ`Ê×ó̬ е^€‰Jz¾yÞÍþŠ&P<ÆÞΞDR´ãe)îÄÏáTCÒ $ÅHÂâN†HC‰Å¬$ƒ•0,‘¦°q ”TB£a1‹]PZì¦%|šªw‡­¿ÂÑï¬mp8Xïè‹{¯‚ûù>ÖÆañù–øÖÛöÙÞ*/«®”ãJ¬‹2k¿}–ùýcâ0,¾áWbá„ö,|ÁÖ°·¡Bô¡3˜‰ƒÞi<`$ÁìÖuëH›v–L¥ìM!Ê Eî —¡ÝpÔð¤á”Aò¾á¢aÁÀ °ÁP”¾‚J›0`dà † ôá‚Aj˜[¸ äŒ>ƒAï7gªý“r·ò¨’Q @T*%r9a6ܼkž¾·aGÿ|Z­£¿Û|…c¾¼ õÓ ÷÷§/k$Î #É’Ù±%_MtFÀ«ª³ÔŒ%ßNö¬9üÒÆÁÇÂÞÔ Üôö5S+L¦S=[ŽhÏËÝ“O¼±£Šø§++nßîV¯«{<|r¼nÓVUË]j×<ü+ÐÎìz¨¦åÈ)䤤HXV‚1ò>%Á‰B)óC‘ËúrÍW¸æµi¸ÖAµÔ: qyY¡Yg®„0¨4“Kø®o—âgãñGGŽacG¶ž[÷|5¹3×â1¼3–‘ìep3ÌlgÍ-|õ íÀdÃaÇå£ÔTô÷Ã(5Îþþò²,ìÄ“LåéoßÏ\ú†etkƒú¿=zþ ¤§j}Vc•‘,Õ´diíR¢¹B¶RëKåèCUP[²~)²s!¦ìFÚšªÐ¢UFÃz”Ëå’\ðÞ™âR} r½Ñ—+Õéò (¦Rk}©©Kó˜\”†\.g­ÃiÓ:µNì°Ùúç+l ­Í9¯­Õ:6[yY¿­ßfÖ.«ª®ª–ÊÔXÆX;Sd-ÊÌ2bÖ¢u¦qVfVUu#®Nwj™ç0!X«U›ÕÏxV »”´t ×SógåYô¨§RêågË›JœåÕ•¥Ak|%þ™f‰£\_]_¶¬tÌùí ‰'ž•µÚZRî°Þ–ÿøÍkâZl[© :ž)²—]Ü G&²¦³HFVAV0‹Ù­9ª!M³YÃ,Sâe ¼œÁh-J}*•¤¦fg¬ERNJ¤éeLÆF)ØBx1z¯®¼D-½²evbÃZgEò?òÉ¡ø\ýÄŸŸí¹P3ùÂÔΧ?|Ä~_øiŸÄ³úéo^Øwagíÿú3VPÿΈþ}™Ð†³Hžª’«|yØK\4:¥ÄhÔ:ˆ‹„ÉnrŠQèCõDË›³ü*¹y †àu9Ãjp Ä/øÈk°Ôí,4†+×›ÎÎÐõ–‡Í:â~)þ ––ŸœÌóûWèÒ|í¾ôæAÁ„?g^ø¶›yáHvè躥 ä¯ï3R “Qµ¡Mq$‘_ÏÄog›Y?*Fõ($¸ƒË±wùšåd³ ·ÚúlDjÍ´n·Þoe—™ñò¼“9À´b` ^²¤ÑiÔzQÚtI³ûœ^£5Ôø’LHó.:jöŠŠ› 3Ô„¦†"‹‘¡¦/rèldœIW\K$„m.^|¼:¸¦%KBíe€§0,G6Ûå6Ž__üª~y uùèêÒBß&wëàòl’çÇ{2J¼Äd¯Ë‹÷I˜â•Ë—Ê™Âeõ9ËV•gù|ïîà‰Í5…öE~XZ;þtÂÓ öCÞ­@MèG‚k¦ï2ÎÉXÃΆ LaUeIçÁÅRX$O^*o3’R])A èTæ5¨Úk6Öš]‹uEÑÜÂÿJ/á¢"× ¤ÃºÚƒÁY¢±š¬Äa=j]°2V«Ù_Â9ýi¨C&S¥Qã9ó‰¼Û¿M ÆÍHÍ<Åú&Žþ„=mÔž…muÉ¢IiÖµÒqáʤ!eEÔ°™:mFf!سËÔŒ.#“]­1ªó[¬ÎV»ž‘æº{'W>ñTûô»¿0Tw×TtÔJÏ)ªƒo~û—K¯ü§®]Åç«Ã}5}a–™HI1TwT-ë^οp|óÛL˜]Þ²¡Î )jqj…Í·Ù^›ÛýR×@´²Åš²u«:ƒ°V¾×÷»H‰N %òí²ûeLP•ß'gîÄ1iÅ}y™Ö”¾²NæÓŠúQÌAÞ,†Ôˆ)rÎ-ï–¹=©<¥|CÉ %§$p+SeŒÁžL“£©Ð'¾3 â[ÐBªe‰Le8E#A,ÒÑÜ読]ÌŒ45‚«éï§K®ÆY[[^F­‹è&‡úÍXFs¡;å˜y þÀ}/½„óëx+~ÿy0–¼ûm€¤ÆW¦9ôlƒý$GP1Çiš@°e=Bb{¢ëÁLÅ}õ9¶Å?¢ g!îLlì÷¡dwþÑ|r§ù ™(Ì9æ¥f¦6g«½Jeö¢‚éR-õ›23t*¤'2ïL¦¸ygr¥amrýTÂ8fYìL¥%±)Wjñ֬ʗ0ÒZ$.§“˜0„ÉiìÜä]»§»ˆ­»ÒÙ¾©ÉPÚsw‰|ûb~[K™LRR»<ñª2¯dý÷ƒäŸ¨Îç¾bþ§¤P¯PµI¿K?£gôÅrµO*MK˓Ƚ9ÇèŠ%9BZ¡/GPª}(ç¨üY™)È«E‚5b¸s4ñÁl¶d¾ƒ‰84éõ§W:a×¢—Î"]Œpíù“uwàXÜß(îi÷è3½·W=ý4¤:œÿìÈ•hû*™B%9 åÔŠ‘'ŵ}4r”Š!_&£•„r¥JuµšPk]J…溊⺚jŸ]VU:uä¿&K‹Ÿã?¿ý6ŒñÈ?_¸¨/~ ¾-`ÛP Ú+ônÑãY²È–,¼© GÊï-'+Êo/'ÕxiV09Pwò:ž·!ŸNgªS¶*2 ˜&LÓ&ÖäÐIJýù|ñ±bR\œÏq~ l4q€!]¢ÓjkICL×Wl7fàj##†MÁ˪’•˜˜¦ß,#Ã,Ÿøá؆‡'W§=©ªl¬­ò-qöî\!Ü3Ôðá/Ûg¶´ªŸ–Ù[ºí_ÛnÛÒÔt`[+®\µ«ÇnhYeªnÊWj—4•U4,5¦k‹›‚«|6Ï5äÉ(­1«¶×Z Zn©w+õ ­w[!ïjõ Á|ìÍ_“O‚¹Ø›»&—lÖãV}ŸžlNíi}i°â0â8n€c8®0gR`…ΟʙüÔ×íùÛnµ÷Tri°×37o5­-÷¼<¹uön÷•?üåË×m«7 Mãí¥Žö±Ú¦°¿”üúÇ}è×GqÎŽÿ1þÙ=Ï -zæÎ{~4X\4ø¬¸ŸÂ<š!Æx8ñ„æ]d†·³Ût2m–u–ͦN‚+s±Ä¤3M™öšXØMÍØl®²I3¼(}:¤[ý9F.¥êÊüRæ»wSÌÁ¬E˜–ÌÒȈk]*“ÊœøVók~çõèÉ28»0ø§tÝ¿D—'[öÜÔ›o½jtmlnÞÔZ\Ü:ÖäÌ$?þiü³5ƒ9Õv3+·ÕûŠØùx_^mfNÖØÆøçñßNüýHyéÈswíxbc‘}ø‡çg`}e‹g–Á:‘?OXs†9j¾ÏÌz*ÊVyQê4”i4{qéšÔdNd/:µÄÌÌÚEÅÿuy Ó2AórÙò‘Õ%/]Ë]ú¦žMÍ]Ó·—’Wü# zš¹®fºnÎ\ÇBW‰}~/øÉ ºòÈ†Ž ¡`2¸uIß’±%LkA_™ÊÛ›GväîË%w¨÷«É®Ô™Tâ&Ý$H˜"8Å([ßW\T,(¤à F¡(µ"Øã/éˆù­V‰ÙŸÃIüÜEÅe™†àTpâíÏT‹ÛºèÎþ(¦ašpØâ)j±èËØnèf;ƒ›­«¶­¬î_Y¡z‚6=2ùÙ=-í÷Ÿ¸÷åIg¼ÐZ³œ!¾”e«ñï9:R›]ÒPPZº®Õá;òÑáî©é~øÃi=þ缕»7ܳ*qVùøO61!¯`»Cº_JØœŒÂfgd“Éœ)÷*8Τ+v+Ž*XE&Ó™Ëq9­]>tÞåÐ'Òwb:8y&¼æÆ,Ñ™Y¬Î1ÒØ}ÿúò—T\šôy™F­ ’ÜÆžhgÍ–¥Ìñ¥{êDoœ%¯×DG:õúÆw^cÐkUÈÄ<ïeOË‘w•Í”‘aö¨zT!ÓV·®nsSiÆ’<]u#«ÈÊÉÚ•5“Å:¼ù~5>¦~JMÔêœR¯äÕ…¯J„bÎ'‘Ô¯ˆå`”óAÉ)ÖTûóM\“_£ÓÉýˆ—–Á±B ›«‚æXº,áÓ Gädu¶ ʳë\™H²Ø)Ö]–ë™™å„wµj1X²é7­T2²öÀPCêœvÛúÚuM’¾¼kÜ7|l½Í¶ñ‘ñm?.eèæù< ÿÍeí¡Ê–AÁhtš+‡ýåñ^ëŠÁúì¶Žü¶;Öü¢xU¥ùþÜwﻇW޲«‹XÌ­Eßþ»ßÿ óþ¶'†JJ‡~°mêĆ"ÛÀãˆ}P‡pè!¡y ‹[Õ}j8n­Ó¹2= œÄb<Š Â¹¦CeO'#gÚ«0Cäd‚›æG‹/£Bíã¸4B ¢!š9vËñRy”qˆž|œpzîwÑ:LKÿÙVË¡Ÿï“Ðÿ’ìÓs‰–à¤EÍ8cC52ÕØIÞù(ÞþX•’–¡•JÓ3t)8ã—P¼™.·K§s5»2É/ ^¦â·3nÈÉÙ(ª«â©ô½éDÜhõz….ge^òÒâ\g4)rº (˯×À¦j·º‘ˆž¥‹T»Ù’Å´2¹ƒ.ÖŒ{Åök–t®jÒgÖûÚ‹k¾%ñ1ÒööÛ¹[Þ¸T¦ÒÈIT YnÃÆæÄ~7Åã™…Ò¾šú¯‘)ñÍî½w\û*§´ý0úA,~\£ß›®cײQö=‰U2(ù‹´Wúd%²Ÿ¥(RæäùòIqôl°dB?ä€c9bJ™,¨„ik.^sUG᪾ö|! $CíIªg´ÈÏÏD– Ú„¥H §„,C»Ð£I8eàô$,Gj\”„• CåÕ/ÕvÜ‘„SÑn¼(S gí8Õ˜•6M–$aŒŒä¹$Lšüû$Ì eä£$Ì"##O¤gŠ’°å2®$,CaÖ%áT̶'a9Êew$a%ªaLÂ*´ž}' §¢¸dQ¦­‘ºÇFÆ¢c»BA>ˆøçøŠ²²j¾)2†&ù–ðäDx2 Ûù¦-[øÉ±‘Ñh„Ÿ EB“ÛCAûª±ÁP¢_w†F¦¶&¯ö/åob¸ ]šŒP¸Ü^Vq­é&Ʊ࣓`hk`r3æ;A__ Z·ŽÙA™‘±H44 ıq¾ÇÞeçýhh<Êƃ|÷ÕŽíÃÃcC!‘8šŒ€9-7MMŽE‚cCt´ˆýV“¶‡øÕh4 F£uÇŽ;ì$óðÚ‡Â[ßÕÝ9 †"c#ã0mûhtë–žHˆÎ': s¼nÆÃaP>ŽîL†èü#Sƒ›BCQ>Þ¿æ1]#“¡ÐV:Ó)Qã£cC£üÎð MDÁ"”ýoI¶—²[®v5En4†FàŽÂ½ …PJŸ è9¸+PüªjB4<ãÀ‚´Á£†÷„ø ˆ2ÂÐjy·À:•? m Á›öÝ.ŽeG« }P¤\ëÏ£Õâ;Œ:¡eRÏh¼Åø¥p·„ïn]#¶D®ÒËA£2˜ñ­z}·Ä1q~ÔfQ±…j¸UÔz3ÐÂhžIûúÄž%µBß!Ñ^“âL©”¨(;Á9&ÊîŽ.‘Ë/ö¤ˆŠ£‹\Ý·±F†þÔ^×8‡DÙÔ· Éa€G“¶Üvž5Šýç‘ÿO=ß%j·]sµHЧm£"6ê`p âÏ<7JJʵ‹ÐVàü·ö‹¢€‡Äöˆ…ãIoÛE™[!ªzÄh\ôµE·öñ°ø¦–ˆ=¢ I@ôÕ¢ÿ#`ÃA°dH´•NÊ¥<[’þOŽhoê·EŸN]gã¢>Cðäa.ah£}†D¢eƒ×Iÿ¿ÕÙþo¶ì–[Œtͦâ¨N,𷏄 œa¯à¯ýŦ?y‹MÿÍ»Ôô•·ÒtðËÇ¿|þKfó僗Ék—ñ3—±áòºË›/3ìî/ˆâsï‚é¿|j5}öiƒé_>5š~ÿ;¯Iù;,üΛiúí%¯éµKï\úÍ%F¸ä¬ò^òêMçpjÄi¨§ ª¦çbÃ'=ÿ¹áãž×šä8¶ínxá& pæU¦—ŸÃ™§¡|=DŽ6`ÝéLsX+ 1 &îþáÿ'ÓŸÄ>‘òû?žþ8ö1«ù sš6¾~{÷ÛÌÆ7Ãoî~“yãøç~«iâ<æÏ—¿pž™8?}žhΙÎÇ9×¹ð¹Sç.ž“œ}ÑjâçÊæüssÓsñÛÛ\ú/÷ æ_ñ¿2ýJìvúåØËDsÆuæòñ££í¤Ï4;#±Ø…Ø1ÆqÊuŠ<õbìEráÅ^$Ž\/'ŸÇN~p’4i°U`5D9‚'7÷ÜP8aNÐaÿ‰'˜G[Mx­¦²‡…‡ ýéñÌ\/ÕgéqµÖûw†“æ¡S½ñ#<”WîÊ4ÀC¥ñjt<èzp÷ƒ—”h^Å*Æ*'¶š¾ßµ`ºx —æcŽc$|l÷18 qGù£ •ËÕçzù#eGHûá‡Ã‡™²CXsÈtÈqˆqé^î ¬e•¨ n¤<Å{ÏR@ðsÞƒ{¬¦+ëMû÷5˜öÝWoºå‚éɽ˜»¿¯ì>¦ì^¼{öÈUÞ¸! ±5wÖ÷d;õ=2'Ó#‡@ÛF¸Ï.\²Ó&«WSz®wÃZŸi½·Ü´Þká^‘Ö#ÁL[ÁôÌá”— õ& ƒÏâl¬?]iæà•Uìà ¡vú ¦Ë D訬ñ …ÅÞ÷ýøâ*¼Ê›gjóúLþ9lÖâ•`òVPÌ÷ ¸OyñEïe/™öâÌ ]kz¸ MÁÛL—f£f·†ÕhšvMXsTsQ³ ‘¹€vYĆù©L,ÁsøØlw—ÍÖ6'[èl‹Éýëbx¬°‹>…޵1éþêY»®wã#}{FÍym±Š®ÞØ@^_[,€@i¸¼ÙLÔ܉F¢S6zá$A6[4 o[àF¶Å SÛ"Ñh$I€EmSâÓ‰ˆ±ØÁ :etˆÚ"8‚è zС'†\}€7²1"Ž,Žï qX †h$¡HD¿qBÿcDÁ endstream endobj 70 0 obj 7505 endobj 71 0 obj <> endobj 72 0 obj <> stream xœ]’Mnƒ0F÷œÂËt FBH ‹þ¨´ ö"c²àöõÌÐVêôl3zò8,ësmú9|u£j`]o´ƒi¼;â ·Þ2ºW󺢿Z„¾¶Y¦†Útcžá›?›f·ˆÍQWx§Áõæ&6eã×ÍÝÚ/ÀÌ" ŠBhè|Ÿ§Ö>·„Tµ­µ?îçeëKþï‹ÓZ²Š5L¶UàZsƒ ¢BäUU`ô¿³8á’k§>[ç£ÒG£hw)<ÇÄq„¼#NwÈ s‰¼çL…œ'gäŒ9A~ä|Š| Ψç‘÷%ò‰ù„\rOr8s~|a¦žçžeÄûè&Ù?EÉþiŒ¼úcO¹úcOÉþeØ?ÍÙ?Cg¹úéכ«ÄYÿŒH¨»s~<ô h.8‘ÞÀï›±£Å*ú¾¤£y endstream endobj 73 0 obj <> endobj 74 0 obj <> stream xœí{ xTÕµð>g3™œ¼f&^!ÉIb !ITf’LÂ@Hb2€ØâÍdd ™g&D¤4X@Ô[5>ªÈo}"—K‘j‚hk¥>.Ò—Òïö×Öªx¹þM-·—özwí}Î<"àã~ÿ?ÃÌì³÷Úë½Ö^{£á>/I'ë «»×²–•TB^'„3¹WGåÚIÝ?Ãññ£øB+zûû«<„>“§Vô¬ñýêƒ"!Âí„H‡»½.Ï€û_-„d…p}v7N|M ¤àóø|Iwoô†©YuøŒøIsOÐíÚ™;8Ã$|žÖëº!ô~¡€ÏV|–®^oßÞp>wrÅ»¡`$z-¹é!‹èz(ì ùŽ ¿ÃgäIìÆ9ßô•ŽC}æAu)úT)-=#3Ë`4‘ÿ·^Ü,2DàûE²<À=†O>œ¾g¶ñ»ÉÒ‡3/q¸ÍüLœ{Œ%o ä&r¶ „[@ªq–߉<9Æ9ÉÄQÃåp5):-¡]ŽÉ!":…W ‹KÄÇðS?çMä5R@†¸wH„ì…¡ö B&yÂvòRA{#-ä²yÉá‚d€_Ë·ãÌ+âAr?¾ƒ¸~ÛʽÜíån&‡È½ ðóÉVîÊu€üÜ N~ý²š÷!ÿ¯ ®ƒ¸ÿ~ˆxˆ“ˆÂÏÀ9äiu±ï<˜)bï£d);É#º!]NJ1R¡{Œ{‰ÑÝI¶‘7àp=¼ÅmŠ…'„ùd‹ªè$[÷ýtÎÇ­AÙé{-ÅÎ÷ Üvò¡Ð™Ò…¸N%Bš{øv”ÈGöá§_g@™ær`3rJWóÈÁ”BîG )ëPjB‚0‹¬ÄÑZ²“ì&3alALL^Ýñï¸óá]”y ÷þïä 42â>B]“B y6E' ÀsÄ"vñ%Ï.ëÕ×ȯ.+œió(Rä]¤mWÆyèÔ©¶k„\qÙ.qê.(ÑïJŠß=Óâ»3- Û®‘w´7hXí 8×q éNã¼½­Q¢»ÄüçèÜ%»»å[ ·×ÞjðÖÎDµŸ2(øÄG0¥)Ötá¢û„Ó‹¼@*ö¿9ò5bxsäÍ‘Êlc¡±¤ÐXèȉäžø@LÉüø¯a]Æÿ^ÌG]É&—Y'C*LN·)Ó8”~ÄñzÒ’‘ªOkÌ1œ©:†+®9¶ÄhšXS¹»ÓÌqË9c±ñ²K‹‹tfT¯âª«&ž¡o~óîÃÃuO÷½ø2ÿÈÉoð[ÚúÂ#'7érNnõzþB3Ïà¯âV¤{¹ur¦¨Ï‚'‰‘Û§ß$¥éSQ½Á”Ié^±ÿUÕÔ í‘cWì©2Ö íRiš 9æræâ¢Kg‹gU¹~n­²aaäùç=¼i“¸UùÙ–“Û6·ÜÿÐoøÎ-ÜU4Èy²WY"<‚¾g SÉUÖÜ)Ã$3gXÔeÞÎ=ûòŒ¦´¦‰ÈߘGåf‚>Œ’öTiMíÌ_Ÿ¿-ÿù·¼„Šm¦b£G68U9ª«fs‘ááÚ­}œ:õúÚñ—?þýï?N?OœÜ©“¶{\Ê>åc|ïsq:päÈü¨üE½$3»Nµfên#7ó"™¤G•ŒT1mŒTΩ6SòÅGßÀ—¢Å Mb„œªãw‹‡pÿLk™Âñ?Ôñ‘›žpP±Ÿ*Ô€ÐñR âŸégYWÍóúí'?Þ.ú¯^•—ëO½/  ®rH. Y/!f.u£þÑü$'§sÏM6 ¥ß>5×ÌëÍz²7eÙ§¢ÒŽì7š(‰ÃÇF>Â÷±p¢ÒZ6//”·-ïWyGóÄyd7Ÿgž—+ZR*ô©)H‚\šƒ¹©Ë¯G › óQµ³ç˜3¹b5LPÏ)åj8E8±;ýà³+_érÿj•rLy…+;ñ—2Ä?zËýÙüu×¾ðÊe—íœná.ç$.›«W~¿ÿž=;·R™Ö¢L3Q&‰”}ÖÒÉiS3É“uÙFycÁÞ©ÃÅCÆÛ'¦“‰0‰úèsì—¢X¯¿‰î`dθÿð±ÇF /£lÆc •-P™W™_YP)WVÍ+µæYó­VÙZh-jËkËo+h“Û ÛŠÚJC¥ò6åo*Ø$o*ÜPtGé¶Ò£¥ù±­±M± ùrga(?T’C…ëó׬—×NZŽú‰yÚ•ÜtTÆÁe³« g1/L™Åâ‘á7ïš·ï–N~ÂñßÓùŒÓûµÿq”¯ö­íŠünOYóÉ›¶û\/>üüOM·•—o/-=A})xê}xuUJŽX¯ÈHç3Ó: ò1BS¤Ž‚‚ü:)-¿@0“Üf!g£yó¤a£0\‚Ê›–/¥ä¦ö\}fŠ>§È>Ípb?&£Ãè55šg”¿}døÛG4›0?Ìü³qbM û^V´›”bŒ[{§JSÓ¦¦—£sXÒ,ésSçJsÓæ¦§ÉDæ.á§IÓÒ¦gWäT˜§O˜–?­ L.+¼¤t£´1mcúÆ Z¾p<¯“ti Y`€É0raª—ZZQ6¯ìÊÊÖ—ÝQ¶­ìhÙ¤åÝÎÌ [Àåsæ*µtóCTkWÎQWM€ÛZž¸vóæ®»æíô?ÿåÚ—z|/»¾}»÷)ëS÷þñ¾=¼Ӧ9VGaæôû6?ðLqñ ³f-»za[IÖ%w{ëŽ|VpÐü P¿FRiÍÑ¥¥clÊJÝ—"éôDßh¢z£ñŽúÚÿæë4ˆö´e?”Í£õU>ãhÂDXPà°<ð8f½²Ë§Â“ñÀ 'w ;}nQdô0žáÒ›LæYsÑn·™3n‘¨Ý&¢Ý¦¤˜2ÈüûÉÃU#13£fª´¦eår×çÞ‘»-W¤ÁÓS,B‹h„¢fŽ´<ØöôË/?Ýö`Ë¢G—ŸT~ËÍät‹fí˜1ãýƒߟ1cû%—pWq™œ‰«-f|½…_;‰‚9Ëø,&;n2™$`ÄÑDÇÒÜ[4ÁÑ|„¹ûZä?L# ¬Å“ÓóRM³' gÁð¥ÅC¥ûR‡³žŸ’wéd¢OoÒ™L²½Œ*ðÆ- Ú–Å•C4ÕT>Ó9}ýômÓ…IJÛ |aÜäWrT0Þh0QÏÂríÑ»ïzôÑ»î~tHQŽ»v\}õÖöï©ÙýÍ_œ8ñ‹oî®â¯|õí·_}åí·ÿ¤¼§|˜—ÿ´eúó?ùº»‹«å€¸Ú.÷v*o&¢Ù¹»Ì:U4péú'uÜ&rO¦nŸÄg§”TQŸ‘•ÖŒGàÂ]’óša”Øzù²…»2ÙøÔO/_ÆŽÆý&–ŽW1|TE…âž±šÛÌṴ̂œž‹º<Žž’Åôt¤~˼˽ˆ«P~=¼k×Îçu9÷µu»·œ¨€_oiyî©X=€úÍ&³G×ûƯÇê=æ_šù±ùS*tMZ¨çL³ëD´k¶nØD†Ó‡L·OJ5e] &³};V4Dg,ž7y-Y«HФHikÓ22² Ƶ¦m“N6&eH ÝRzFÕKùÈ];žºûÎ;î<Ê™”Žþ»òÎïyíµ#ÿöê+> ¼ªŒ(ÆC¥ÏŽîræ£W¢n„N¢#ŸXKÁ(ˆoäx‘þ¯#:ÎHˆ®ŽòQ'b) $Åð¦f>¢š/ǹp—Ùùu:Am¸"«lªj'±^û°ÙúÝùüJ,ðøüzþ{ü#¼žJ…T̺fn L.%—reP&ÈúYdW µB¥¾‘4rpâ|U¿„,á–Á2¡Mï#>Î~a…Ø­ëÔ÷‘(·Ö }⺠d·6 ›ÅºA2ÈÝÃß÷ ÷Š÷èž×íÒÿTÿŽþ”þ*LÙÕ©´P¸ò%î:”o:O8aÇ'ÛX½ð"*j ú5­]f`íò‚ð#²k½@ãµËá#˜M ©ÖÔ¶ÔÎÔP*f“ìjæ.Å/áKèüd›.çCV˾ùu}FÛÈ?d]ñ7R g÷´× ¿\¸µÑj)¢O\äðNЫä%_íÆ\õ²ñæMxË*&sIJïwGñC„r½p„¬fà}bÙ+øÈõümä-„¹žÿ5© {„f¹’¯!/â}‘ëð&2Â¥sUÜ|ÿž2>¸þ L|¸@ ‹aÆE6Þ:x¢VWråZ0óð—Þí¦`‘ãõÞ8ßÆÅ½Ú˜G¸jcÀùǵ±€ãÝÚXÄ;ýóÚX‡uÎkÚXçÌÚ8 ïP‡µq†éA.Ö È$—eoÕÆ’–ýml$Böï‘"'¤"C•ÙïjcŽL0µ1OôæRm 8_¡Ûµ±H&™¿®u$ÇÑÆzRdÞ¤ÓH­ùImœQRk~_g’î¹yÚØ@&ÌÝ D?÷õÁК°EwTžæ.“«*+«å®5r?‰†½®^‹ì¸Ëe[OÜN¡"r»7â ¯özʥӶΦ[®Õ½+ƒr«û ¼+]Kúðjæ ¬ðFdWØ+ûr¨¯«Çï–=Á^—?ƒép"uÁતǤáo8âäªòêJu: À Õ( цj+*<8¿º¯<ì »½¾`x…·<à620Ê•".¸<-âõÊ]Þž`Y¹|—ËM=kBÝÙß †£^ì {e[Ø»Zc%Fƒi¨OÕP2IJPGÉ\²ÊZ\ÍÒ̳¾¤Ó rζ”ÇPöG$— »<Þ^Wx•ôÅ"ImÞp¯?ÂÔïÈÝÞ°i­»(ºeG±pj õl‘£AÙX#‡Ð`¸!ØEùQ.ÙLKíöÆôäv{CN¢Ýˆµì DP{EL%EeˆÌ#»"‘ ÛïBz’'èîëõ¢®(åÇçïA#M£Ù¹#è‹ö£ú‹Ê'ao(ôô¹½ Ç‚ù»ú¢^ʃ4jƒÍìîéóPNúýÑî`_™éõk„(…°ªJDÛAx*ŽEîõR©%æ ‘nK ¥Y Ë/Ú¡ýȪ&þÒ”9D¢ŠŽJªê¡þnt¬Ó6P3øúÂ$èe=A9´È‘¾®•^w”ÎPù|Át6*;ðø©‘ZIr":WWpµ—I zc î`ÍQg©UB P×äH·«§GêòjZC60J\£ä Ð/Âro0ìWl9º&äõ¹P¹ÊÔèÕ^׌ÜîñûüÔÑ\=Qt= R—ÇÃ$WUGÔF¾úz\a‰òx#þÆÆ 5VqõP—‘DèŽ?‘±”(J 0…¹zÆG í‰ñ‘À†ìzÖÈþ$7—¨8a/í@3X:ˆPER»ÄÂË>ç ³MýÁ°'"Åã°ˆÒŽ-HE4l‹˜ÊÐ2ÍZ¼ty1’(Ö>´ÕÉê ?Θ÷†(FŒì …0¼\]=^º ÊŽ˜é@J¥Û•»]Äè ŒÒ õº„w{ä¾€Gc8ÁªÄ˜S%<›U#ÁÕÌlÔH.¹‡fŒ•`Èå^åZ‚a‚uÕÏæT£HaÂB½=>ÊÔ|»ÜØÚâ”;ZKmívÙÑ!·µ·.q4Øä"[>Yä¥çüÖÅN!Úm-Îerk£lkY&/t´4Xdû5míöŽ©µ]v,jkvØqÎÑRß¼¸ÁÑÒ$×á¾–V§ÜìXäp"Rg+Ûª¡rØ;(²Eööúùøh«s4;œË,R£ÃÙ‚8‘¹vÙ&·ÙÚŽúÅͶv¹mq{[k‡q4 ÚGKc;R±/²£ˆ¨¾µmY»£i¾Ó‚›œ8i‘œí¶û"[ûB‹ŒÈZQäv™”#—ˆC¶/¡›;æÛš›å:‡³ÃÙn·-¢°T;M-­‹ìRcëâ–›ÓÑÚ"×ÙQ[]³]å E©o¶9YäÛ"['F„‚©â$Ô!Ñ Mö{»­Ù"w´Ùët€zt´Ûë ušhfìÖ·¶tد^Œ#a‘–η3(€ ÿÕ3Θø-(.ÅãlmwÆYYêè°[d[»£ƒZ¤±½Ù¥ölmd°õI×¢ñKmDçN÷„¢»5ì¶fDØAÙÀ i,z—ý·7¥¾­·šYUs§…y­šÐ…›¸êⱄ‘ÅN5»%lz[ÔÔËÒz7žDjêõ¬öbŒÐT KAšLúýéxöÕ3Oޏzî¢QÄ 0Wºzp[$Îæ¨€’b‡a(ìÇ-ýa“‰ìêÃÙ°ÿFíkÇ“@NH@©$’ƒÊØ á)å_ííYSްaz–1Nü¬Õz5Ñ™úÜÑÚX©•W0äž`TŠ®\–$Vq]pét®µìÅ©ƒ$µ’ϧ’u|žutz¤%y7É㨉‚EºZIŽÕJÒW£V’T;|nµ’¤ìÕJÒE¬•¤D­$Ÿg­$ª ΣV’ÎT+Éç^+IIµRrøŽ*—ð<Ç$q±Ê%I+—ä *—¤Qì²{ãÅ.™¤@P¾à’Iº¨%“¤•Lòù—LÒØ’I>Ÿ’I·d’?KÉ$9mK-h¥lÛæŸWu$%$¿êHŠUGò…TGRru$ŸWu$[ÉRQg(ñÂG:cá#†ÂG:{á#ŸCá#±ÂgtíðéM4oeEƒTŽ?ågí\UôûWù+ü˜An(u‡*´46¦sFêI„È&~²‚t“(‘É4â&eø[E*ñ]£.„IÂDI?aâ%.ÒK,8ë „/Ç‘ôà[&íq\öäÅ_/îYß„”Îêì8U'RZ´èŸ¡šòáÂ=ŸbŽVâ¾%¤!Üëbؼl‡‹I$#–~‡¦ ñúNÆýA¤îbkcñt0,ä(ˆïUgXv ã0‚xƒŒjòY’'CÁÇv¨²F5KPÙ£Èy-©À·Gƒ_ðåÄß0Jãe{ÃLîrÄáÅ=IØbzˆÙât‹Ó5ª[/³µ$ýK­qqtL15áÊ„éf;ý¸b|G™=©ÂlõŠuõ­Œ•#áC}£|èLÒHøOvÕf.%kíto–ÈÌ xKç!?.Ç·wBf?®Hle3ÔËz™®Wá\-ði¼PÉÚ¾^†-áý~ÆS7[ójr­`TšÕ-šÝUk©ÔTSýÙÂø 2ëØþa*… bj>æ×¼ÀÅp¨š–4œQÆÅXr38ê‡*ö ­ò®ú²—Å«ê{EI^RÄ,G÷zØo„ñåÆ=.M>‰E=´—a‰²•˜~|8êÑ"iZœÇšW(ÿQô_Õû)Å„NèLˆE)¸Ùî7&A”ùZ®FÙªJC: ‹Ínä¬aQuÒÏ| ›e¨¦™^6—,QL†ð(¯T¹íc:´$Y‡Ž{™=U[KI$‚»-g׳‚e™aVãAÅí×´:Úúg—:¦9•ÛPÜ££Œ¯„×%$êgúè=' ±hð±¬Ð$ô&Qô°oJÃÂ~©&V"„›áSabö£~Ü£e¶˜…ÜŒ¶‡qì×8­eÑéÔ¸s!Æ Ë $碄NÏ„jÑ‹•„Æ’s@ò>™ÉìbœK,7ö5UêYâ:‹=ƒì”“5Û÷²ßDþ8[DÙIDON—&Qù(Mm/ÕÉílQ©SûÍ“z˜Ÿ†ã3*§T§ž$›'{]ìu±ÑÏrF{’ây§Ô^$m¬u®ª”b9ÔżGõݱú‰|ªL1.%M‚„‡¹˜ÎƒÑtÆêc<Þ,š½{Ø>ÿ²¹·N˜åYË+ ¼±™HÜ#cñ2öôðjyÎˤˆQêgRyØþ¢qÎâ¸ÜcwH¸;m‹’¼L™æ1çK‹÷`¯}ZÄüd5®úÇј—ÜÀôÐ"9„oõôr±ŒêïH¶»ÊslF7RºY†—ÙoDãÑË<éL~Ëuãån; ÌîÉúO«R’æ’mx¾±aY3vV'¢-I´rè‰×amÇhŒ!æÑ«ð{…f1õ<¤^%ųê癩Î,U—#Qí<ôÅ55ŸØVÒ‚O”N+>9ÉR¬#ÛÙšçd¬ãÚqe >5àl³‹­Ðõ"KqL1¶’Å —Š£¿)îe8CqËì™>-DøÄE÷ÚÉ5Œ†±u g­8¦¸ál3þÚ58º£gã37Z…ªôZp—“ÅÝGyQ9uâ|‚êh®ŒbŒ³EøÔŽøçk«6Äí`ø(ÿVÑq‹Æ§ª¹v†êˆb¦8ë‘£föDgãoÂu0}Ú˜Ì*·-L†F\We±3TK¨ÕãoÒ¦MÈ—“iRrjfG*OÛO©.dP*g­š•é8¥\Ó¥ÊÕÿ’8å&3¾e&¿gœÌ66ÄÃó&†ò-1m,fòÙ˜Z…:GµHõÙ÷¸ö$«Ô3}Q»QÎ%ÓHǸ’İ%[g<ï⚘|v¦©fÝz´#¼#>£ú£ƒÉZ¯éZÅ©ú½êÍIÚ­g2RË^TíšOÙ˜îFKAí´”ñŸBµ€Mû®OÒYÂú-šucü8eç8ZYÊbÑΠlÌÖñidñ»Hã|qÜÃ9`±æŸ­qÎFë7G1¸sÉ*®íÑl`þÔ¬qØ׆ !¯š»ìx®¹Ù='ÏÛ£Oîäª1Q&×–¤\›\ ¨Y¸‰ÁöŽK̪·%õÌJÜu’k·ñnر۱ZËǪÞDõ¡ænõN”\õzX}®Ö€‘xUdu`0^™ô³ÕÄ™Òz'ÁQ÷vz5óÅw™¤¯p—IÓeJÜu¿È.“ô©]&ù ë2IŸ¡Ë$n]&‰é` b]À¸UµmÃõ/®w$kó/«w$Ö;’¿´Þ‘tÆÞQ¢ôù÷ޤÏÐ;:ÞÏ·wˬg>QNïøHçÑñIîÒ\ÌŽtAŸÓïlç×ñ‘’:>gë;\ŒMô4üV’è4HŒ}*¿€¿¹ª`zY…Ÿ Æ›‡UMå¬~ áÜèjììsÆþŸeö:õ-r-ç5į·žúDã9ð_%ðqüç ü=þ¦À1þ£þš ÿ>GKà/·ÚÄ¿(ðÑ üyFŽÃŸŽÃÿUàÃZø·:8¢À¿VÁ‡;Äá0î€÷ß«ß?ïUÀ» üQwªà9ðûAx[·LðÖÁQà·þÛupèÍ&ñÐ:x³ ÞøM®ø†¿É…_+ð+~©À/88¯È_Wà@>üs¼¦ÀËŒâËSáç`¿/)ð3^Tà§ üDx^} <§À^# o,‡zö9qHgŸY.>û<»^xæÇ%â3Ë­§à«ðãØ£ÀÓƒ°[)°KR`§þ1v> endobj 77 0 obj <> stream xœ]‘Moƒ0 †ïù9v‡Š„~K©k‹ÄaÛ€Ät‘FˆBzàß/Ž»MÚô8~_DZ³S}®­ Ù«U÷ÆjÓxó xWc™Ì¹6*Ü£ôWCëX½Í<jÛEÁ²·˜›‚Ÿùâ¨ÇXöâ5xc¯|ñqjbÜÜœû‚là‚•%×ÐÇ:O­{nÈ’kYë˜6a^FËŸà}vÀóKjE&×*ð­½+„(yQU%«ÿåäž,]¯>[¥2J…ØîËÈyâÝyE,׉WGäMâ¼BÞ’wƒ¼#–È{ò®Ä9ò‘4éü‘ê\Ot¾C>o‘/ÄISã½RPMÔÈ{ÿdê?éá÷âpG?£åêæ}kZdš'NÒXøÝµºÒ÷ ÚJ•o endstream endobj 78 0 obj <> endobj 79 0 obj <> stream xœí| \TUþø9÷Ü;èE03õ ásQÓ,y ‚"è0øèÉ03À(ÌÌÎ ¹f›©™™V†ë#5WÑE3k ­\k³´R«­µ­­¶ÔÌ\[sû¥[Èÿßsîˆfjý|þ\‡9÷œïù¾¿ßó=_-¯»Ê†: {A£,•fWvBg?ûÂÑ–j¯2üšòW`ü|h©«¬²¦&ÅŠw´©¬¢¶ôÿl÷ÙB(jP¹Ílm<¡Ø°>¤&Š©# Þ¿…÷ëË+½ÓÿÖã‘ðµ«pZÌ óòïC¨‹ës+ÍÓ]¯£"¼o„wÅa®´]{æDWx¡‘6—Óã½ýîBEƒØºËms•ž?„÷ñIå0‡áa?`¨cï%]X»örx‡Ž"£¢;ÇÄÆu¹¦ëµÝ®ëÞ£§Ò+>áúÄÞ}úöë?@?0)yÐ )©ƒÓ† vãð7¼ù–Qéèü§¡h<A h%®‡·R˜þ ̬žEsPÌìÆûð|a ÌÕ£Sè=€œ‡ö‘á1(fúPз؄¶Žq ¾1L'"1_Ü&Åâ1ñ*zÄb±èÁ©d­4Qª‡Ïä5!½z¢øSäA/ã$•ì³Äô)9@ÐQ ö‹Ð:4x‰ÁN4K˜!af¯t-‡Ç ëð*üp÷ž¢ßQÈA«ðAk:ƒf“0 ü2U(þ÷®°9òˆH:ˆeD…0Ü­þ»;(äÏ)4 (›Ð:Ý]LXPa«Ç»ñWºÇÐô¹ü†|„çˆ âF1-R5@ŠÑ"À½œíÑ•âZ=3v¡F,Æ è¸XV¸_cÍm‚$*E;áS£‹™Fà9d>pÊV»£acÄdØÂf‚Ô9Iš £h z $uh`âòê†Jg`çJñȼ/Π$ õC¥âIÐ5ŠA¨¡ía:I$Fz%r«˜kÝ:jÂdåõ)½ê[½*‘aÊV4~kÇZeǹsã'‹Ý¤)[¥ë¶’Äv[ÅÄ„CZ<4P?vüde«Ï¥a5gÁ\ád²7˜†yC_cD·J‰ð'·x«b)WŒ|0aøƒ‘¶á6t­#g¤u ktŽê•Ø+ª×ídYó[Â~ß`ZñÝ7n]?æØ`MD^¢öÙ+àà“ð}Ï ±¾ÒÁšÓàÊa£V`1€¦á^åbÏæ§IéÙídBó«ÒÁåg ËÅGã#àÿ ð’a;é…SqéE„êÿâ¯é“o èÏ3|kï~YŠðu%[šàYôw~ž¾‡}ÐIe=×(<ܼS:Øt°­—;"Rð¸î%FõJë‰z¥Äu‰M ñBTdtjÊ1—þb§‹ékô lÁ#fÿÛj;2óÌwß1/=ˆ©÷Í*,ÂËp%vàe9Ù¿«˜¾EÿJߥo%2þŽ”tÂQ «!ŽŠú¨Ôøoáý=ÇïÙóå—{p7l¤[èQxžÂ…RÝ£/蜃¯…µœuô6ºŠ®¦·áu¸žõŒÈ*îY;£ë€FÜ¥sIÂpTBH£ÃQ HÚàÞ $e„cØó¯nΘY±§/?v¸Ê÷úç÷Ï{¿°3nñ=´Ϫ+ñÍ—¾ÿÁ„ßÉy³gÏáÉ =CðX Aàðâ1ˤƒ¾ƒ̪®ñ4u tð\#˜¼i€ºéyÈgUëÐØ…‹¸ýª/NŸþ¢êÛïz¿¸߉S¦¿/•¼ëNº—~@?¤{ï¼ë½œ¼—ár¼z´JWìtÃCüŽYšLðÙ„{}÷ ››W1çËnði@øÜIÚl¦›¹ àwdssݼhçóMð—€ ¼lh¯()-‘;ÍQÜîĸ_sSƒèÉÙ‘ÃÝàWÑo„›tѨ#;߄ؘè. ½…´ÁÑC…›j«ª§/~`îÜtÑ_Л£#ŽžÀ{>û¿úâ>m;w„œÐÅ Hn¯(PYZD@3q8&N³V¼Žêë¯vm?zt»k5Eu³ï_ºôþÙu¤Q¸óû¯6ZÍ8 ·ƒ'ËLc÷;¶>~±ä¿ÔKÚûÏþÆ,¡ ;øtáϯ+þÓä)/Cáð#ûþ]/,¹{Á†·îÚ;xð–þz< ˸3ΤŸ¼ºtÛ–Uª]û¡Í CgFpuÇ<êA”Ô´ÁCR…Í«n5à(úuýêÕ+t1ËÆ—[5'“¿.ÊqãÑ:Ø <Ê(‘Å….–K=ՔѰŒÀªÂÒn â„éo¬ðZ¬¯¯öÇ+þ²î‰ëònÛ4ᣄÔÒ%ž·õËóý®¡Ôü—µ~9zÖ‚¤¤†>}š¹ÎW½ã@¯3KÇA窖ÊïŸXïrÎ[Q_Óê©OmÃkð B½Ï¼zõ®uÂŒ³k6—ZN‘ ÷SÀ­ äÖ|}Ëúõº˜ï¿RurÚ ­â:áÎ7‚)§wSK6â"º)³lÓ¦—­­•VÑWùÖÌÏ_¾ú]¡x¾YÅñøÕ ª_uN‹ŽÂ†D§ –,ž7wî¼Å5ÕÕºè¯èMŸ~F‡Ÿ8Š_;v ¿âÏ]ÁÛ©Ô5JT㟥<íóY Ì¢¥xùácÇÞ(%ûÞ~tÞÜGë|ôÉa“mÄÀ'«à•‰,1AConiÀ¦p‰pwó¦2\š4ÉPW[´«ÂñRÁ_¿»ÙØå? 5ø‘á•Kskê22÷ßòå+·¯wu§'¸l·âO…QÂl®;À+>J» ³×qûlŸM½†ó˜à4U—ÀŒ0K˜ Ç>± Q©äwuu¾ƒW;w=ºÃ¹zð† B²‚Ñj¦;éwðì4[7R =„N„˜(F >€Ü˜¨oÁ8µ=N&dÏqÝoÎÊKêAËŸ†J`ÄÖò×ï^ž3×$æ7/!œw øOøOcìõ„d *aœ¥ñ e%ã$Ì" %Ž Ê^:aÆo§ÌöÌ’¾2a«ùög'UÝsÛò—ÏóùÛ׊·léÛ×d•Û+¢ÿ²ù+v¥¥M™0v|b§ë¿oÕæœîPΠ/*Y²ÔXn.™ë2ú,¬Û°aðÆš¨þ]ɶè¨}»|ÏŠÅ[J-’äßO¾ÕâvªŠe(¢8 òm½Ë9wņ #žœúÔŸ„u¾Û…U«WíZç›§‹ñ­²Y¿f¶ ú|˜êõÀóüõëÅâ³kt1Çýtx|µ¢ût€YNFË[phg¥æ Ó>š° ) ž³bùÜ9Ë—Ïùà¿ÿýàÃӧɧÇÞxãØ—¯ï=¾’¾N¿¢ÿ¦{¡.ì •á0à‹åÚûg×P»µJ‡qdvöœµÏ>»6ga¶áñÂÏé·¸Ó‰qŠi› 8ràÀ‘®¿1Gãá *¯t"9ÁyíÛÒ_»¨žªúÃH’Ø»¤¥Ããsç,Y2gîãõG¿š´"7÷á1X›ºÆõÂáÃ/¸Ö¤Ö #_ÿøã×÷~üñ z˜ïÞãOúþ~é6K Ž ñðKƒªkóÅx ¬†e¨ÆÏSý®[6W­Ú´¡tê½uõeÓf=¾aë*ËÉüßVŸ>Ì ñäJfaÕÚ/ý¤¬ä·<&!f’€?§µ`l¤ùàƒþXÄçüºÑ·E'7„D#>8¦´ó»Q;¿á¸e¹8ŠUŽÂ’ÆF_,ùV Ö¦Â^ß¼4à;°üѳã'€·=‡;áIx2îô ]ßH×o•6·#ß5 z6#5b{kÁ·ôÛÚˆ_ñBñû²E?9­®rÿ_èY_ñß=ο•­h¸{cÿsg?¾ëUiÝkC‡Ü[m±õì:àÃÆ?”üŽ!û{¿íyÍÀ—7íù¼·_Æ-Z½›ÊÏzÆðiÁ´õ´o3pz¶§x¨i€xèlO¤åÈãd”Pȑ¾k…ÚÅHËñROžã£xŽW˧Dµ†ì‡ñ´p&ÔGÿE¸ ÏÕô:ƒ.’ÏÖàk@.=îRO—Ò{é=´h­¬|Q\ÿ1±ÀX³ý‰§Ÿ^¹6Ós´4Zuê½÷N‘Í·Óéû¸?¾žó{® 䫈Zô’DMh¤ Pz5”´:p$øìÍv,é¶g…|{œ0r¶×î‡ÚöÚôiV÷ú´-žd°adÓ)¶Ⱦò7ßß ³?8!'Œ«û­Ýo¿UO¿Ûýá?v‹ÅÍud*ûœ]Cêš§ª´>ëew¡©±$¡ó»–xÇÐÍôe<Š­§ a€ü°½À˜âü‘oécxÖnúýÇnü]ö*Çáb±ïSß_ðš#Œâèoð"Žÿùdë®Õ¡,HPl jáWìÝ+¼éû¸oAßC8Œ~s¦èé;'ß‚Áw ‚d”ö蜙û|~ÑÚ ´cqñöíÏlN0!5©Ú<úÉÉE[n¯#}BÁ€„0IG)~d¹í¾‰SÒî¼aŠ#;sçÃ^Y7âÄä´®±7 Výñ5ø5r á¹$áµ]»(E¼×)äíïxÊ㺫ÓM§QÏv¼ç÷FäÛcýý?vûÔ Ô.ØD(¬’vm¶jfˆFt›x=Ú&žDFñ+!Â9 -AeR|Ú†›Ð3BO˜ CeâChYv½)äKo£Uâ£È&:MxõíÈ!.F+„žÞE7Àúcâ$À½Í–¡[vƒ˜†—‘E8 ãÅhƒeßb²‘Ó€ ð…xXi*Ú¦ûEµR £n•/´F´;֔ޠqÀËÀ7 è< ŸZÆ;—héÚ¡Ý0w«P k€›ìEâ)À¹>Ðò.ºöƒÞQÒ£,TŒ\hz¢!_wª©x:^ ÏüO!R$”  Ë…ÂBéO†‘ròy•|.êÄkÄá¢U\,¾% RŠ4F*—ÖI;¥7¥ot1º¾º]©®ZW§Û£û6,),+lrXE؃akÂÞ û²]vÃÚÛ=Ôî÷š…2P?æ<+D¢eÌ¢b,¼µC¬‡z-\æüvü}À¦ÅÂÖv‰PU«cóÏhcÆ{´±gÝGÚXuõ1mÌ"¸ICÖÆáÚ¸cô¸¯6Ž@ƒ;¿¦#Qxçïµqj#E,BÞÀƒb:jc¸ÏÇŽÔÆj[¦ Ì;µ±ãeÚXB×ÄîÖÆ:Ô;ö#mÜÅÇamކÇ%h㎉ÃãîÐÆ¨|ÄRm‰âFœÓÆQ(ú¦ØL§«Öm/+÷*}-ý””AƒR•’Z%ÃîõxÝ6s¥^ÉuX’”ôŠ ÅÈ <ŠÑæ±¹«mÖ$ù¼­CØV“¹ºrªÓQ¦d˜Ë/°1Ë6Õ<±J±”›e6bvÛ»CqU•TØ-ŠÕYi¶;ü0…f‡GÉt:¬6‡ÇfÍp:§µ¹ÐæäD›Ûcw:””¤ÔA*[o½§Ôéæ¼ k¹×ëžœl…ùêª$³Êm±•:Ýe¶$‡Í›ÍÁ«LØ€~”¾›M)±U8kú%)— X’2º¢ÖUîQì•.§Ûk³*¥ng¥’î¶Uk¬øipEV©Š %#ËAê ¢YQY XCxÑù|»]²É•V”íÙ¬xÝf«­Ò잦8K[c‘åñ6w¥ÝÃí`÷(å6· h•¹Í]²ƒX° 4zÖ+^§bvÔ*.°lp–xAcvPY±Ó2@zËm~=Y,ÎJ€3o9`-3Ë*}ã¹Jâû2«böxœ»èÉV§¥ªÒæðš½ŒŸR{©/ÃÈ7(…ÎRo ¨?¾çÄms¹Ö*‹£±ÚA0{I•ׯx[lЃ™-UVÆIÝ[î¬ò3•v£àVU h«<ÏÄÑ+•6&µÌÄS®¡¡g4“nÅc;´XÕÄoEš1h]LÑ^YU'TSŽuÞf†Ò*·ÚøF«Sñ8õЧªdªÍâe3L¾Rg8Ècgrx†Ë² ЙKœÕ6.êEœ€8œ^0ƒGeVq=@]S<åæŠ ¹Ä¦i Ø€(1·Óé¿p+•N·­M±o­ËVjBI*S-W+͵-°Ýj/µ3G3WxÁõ`HÍV+—\U P³øªª0»eFÈjóØËœ25VaóP³xØ??žÖ”Jp…™+ÚF íñóÄì9*j{ˆ›ËL·ý…0‡eS$³‹?½Þãõʤ\SNA‘Icz¾iŠR­¤çOQÆæægéÃäñFCa¡\`TrÇÏË5À\n~f^QVnþh%ö嘔¼Üq¹&@j*à[5T¹†B†lœÁ˜™¯é¹y¹¦)z9;×”89£’®ŒO7šr3‹òÒÊø"ãø‚BàÈ´ù¹ùÙF bg!QfÁø)ÆÜÑ9&=l2Á¤^6Ó³ ãÒcõ +‘ I.‡b˜È6æ¤çå)¹¦B“Ñ>ŽÁ2íŒÎ/g³ Šò³ÒM¹ùJ†DIÏÈ3¨¼(™yé¹ãôJVú¸ôÑL?¦ŠT‡Ì6Œ6äŒéyz¥p¼!3— @¹FC¦‰C‚îAyœÝÌ‚üBÄ"˜8? ½<)ÇÀI€éð'“sÆÅÏqSÑ`eRn¡A¯¤s ™E²À.³gA6÷€"Ð'3^¾Æ/³›;ß;ŠíÖÌ2¤çÂBÆLÈ-`Á» Ó-6——ù¶ÜjjäiTÍzîµjí€ÀUçøŽ%ˆ,~ê¨Ù-x`³ãX¯¦^ž>À»á$RS¯µÚÐÃR‰Ó-;Y2©±{x¤ÃXéTÏ<Åc®b°‹E‡‚\i®€mž›-Jö†.·¶Ô¸í^H&й fÝö»µcØ­S\%(£L*ÿn›Ç§”½ÚVQ›°nv–qNì¨Õ*5ѹú,ÞáþRÁ«”qäV§W†Š.I‘e^q]qét©%ïÕ©ƒdµR.§’ƒur™u|~¤%y ÇäñŸm¨Á‚E¾’ZIñ×Jò¯£V’U;üdµ’¬ìÕJòU¬•ä`­¤\f­$·¨ .£V’/T+)—^+É!µRhø¶(—à<‡$qµÊ%Y+—”+*—äìò{ãÕ.™d‡S¹â’I¾ª%“¬•LÊå—Lrë’I¹œ’In³dR~LÉ$›Ò'ŽSÀØNϹ¬êHJ~%Ց쯎”+©ŽäÐêH¹¬êHn³:R®¤:bÎÚ"P…|ÁÂGù…|ñÂG¹„ÂGæ…OËÚᇠ¯~/ä$øJºhç*¹Æ>Ížl‡ 2=ÉUîJÖÒXHË,ÐC™È‰\¨¹‘•¡räE ê‹,¨|§ Að¤Â¨ ”0^äÙU"=Ìæ"À'Á(UÀ£ c—‡¿ÙàÛ{ªá· åK :$@Õ”ªû§¡€f|˜aÏ£˜£©°o"ª Àš96ßaæ)€Å¿]Sxí§À~'P7óµÖx 9†!“sg…U§m.ðLû;.r"—Î<99Ç) c*h-ƒÿÑ)åëªæ¼š]™&½ ‡á(«_ ðIç„o7èÆÆ÷º¹“‡ öd‡`ókÕoÙóý‡­1žlÜÚ6йÕ,³íÕ±Ã4Vj¦œï´Ãš‹óíåÚ`póÌŸÖêVZi-GÐ#«Zxä…¤‘áiKvÕŠf…jíüØÑÀ+xäKŠ·«åmÛ;(³Vd>òòæe•\×Ó`Î ø!^˜dã9¾JŽ-vÎS9_³ir•q*ÍêzÍTjª©þ¬ç|9¹õ|¿K‹9•‚°z5³k^`æ8TMËN/碵?Y8óC»ƒVyW}Ù³ÌZñ!^Ï-gæq;=œ/ ì1kòÉ< ,à¡•‹—¯øõS £ -’úx R`Ù‡ñïÿU½ŸQ ê„͸xÔX‚…ïöscåx¹¯•Àª—¯ª4ä‹PÐkÑlΪ8U'5ÜÊyÖñjš©äs¡ùep·ðJ•Û*®C}ˆuظ’ÛSµµ’A<°[9ô9“yQ8f5TÜvM«-­q©ýšS¹u<ÚËù z]P¢®ÊK¢à†Ržµš„¶ŠVþ›ÑÐóo¦‰©aáøT¿ý˜Wh™Ío!‹vÂØöðÀÉÁ¢Ó¤qgŒNž‚6ÍEA œŸ ïÕ¢ÁÓÖ+A…æ€Ð} —ÙÌ9—ynnékª6Ô³Ä|{:ù)§h¶¯äßÁüq)¶ðò“ˆœfM¢¤šºØ^¦“ZílQ©3—r­š'Up?ufTN™N­!6õ:ÿ jæ'¢çŒ þ&$²rN™½!Ú(kq®ª”ü9Ô̽Gõ]?Öúñü L~.eM‚ ‡™¹.ƒ–tZë£-Þôš½+ø>û²¹°Ž›çY3Ï+A¼þOÀ#ýñÒúô°iyÎÆ¥ðSªáRYùþø6ÎÃø€Ü­wȰæ?mãC¼L™¼VçK wg¯UZøý¤Vímh̆¦s=;´HvÁ£ž^fžQm¡vWyöÏÈmFJ9Ïð ÿöh<Ú¸']ÈOü¹®­Ümå'Z ‡ê«-­Ê!š µáåÆª‡gMÿYŒ6$±Ê¡"P{¸µ-1º¸GOƒßešÅÔóy•Ȫ?e¦º°T%ZŒxµó°4 ©dàt P>¼1:ðfB“ Ž4òµ\˜S Ž3ÂÊDxË‚Ù,n—t¾ÂÖãy4N‚1ÃX€Š8.‡~3ÜS`†áVø;{ ðù€‹í5 Éœ†°g0f¸ÇÁl|48¶#fŠàG#V…ªôòa—‰ÇÛÇxQ95Á|jK®r9E?gãàÍøs´ÕtÀËñ1þõ¼>bã|OUsFŽéˆaf83£<þÆf‹à{<Àr}¦s™Unó¹ Ù°®ÊbਖP9Ê„ïñ@›AŒ¾L\ Œ’IƒÔs;2y²ø~Fu,‡R9+Ð¬ÌÆA,Iš.U>˜þ'(rùóàQ¸ü&˜1qÛ¤~?^¿ïŒæß2×F—/ë¡€SÈàpL‹LŸy3†X%“ë‹ÙqžÅ)¥s¶)‰[¨uÚò9@a4—ÏÀ5•Ç¡ A€Ï ̨þ˜ËeÍÔt­âTý^õ‰¼ífr™e'UƒæSé\w-¥`všÄùJ¡Z ]û¢³ õó5ëúù1qʦ6´2‰Ç¢C¥s[b$›Çï8󢀇s@‘æŸÎZê×G~¸KÉ*.?í–Ìâþ”§qXІ !_¯š» p®Yø=ÇÈÛ-OîЪ1X†Öú\Z ¨Yx4‡­lœUoK꙼ë„Önmݰý·cµ–÷W½ÁêCÍÝUZ/(XõZy}®Ö€ž@Uâäu 3P™ÔðÕà™îÒz'Î÷£äÓòÏòIù˜’¢É?f’_$Pò>€¿?“üÛhéàLò·Ñä½w»IïQòn7òWJÞ¡ämJÞ¢ä@Ù¿¯‡´Ÿ’}=È›)ä Jö̉’ö\G^‹#¯R²›’W(ù %/Sò%»(ù3%;)y‘’¢Èós¥ç)Ù±ýEi%Ûï¶¿H¶ß+6>—(5Þ1êi%>—H¶Qò§:ò,%ÏP²•’§)Ùb%OEÍ›¥ÍV²©!ZÚ”H¢Éé?6‘”l ¤ž’õÑd%X!ý!…¬ OZÉYSGVS²ê‰Ò*Jžè@V®è*­´’Ë#¥]ÉòH²L&¿§di]Gi)%uÉã°éñ:²ä±iI_òXy´‰<²øEéJ/ºCZü"Y|¯¸èáDiÑdÑ(ñáD²’‡$IQ² ‰<b>˜Næ?.Í!„“y01ÏJ悦æ&’9Qä~Jfß%ͦä¾(ò;Jî¥d%£ÎÝ3s¦t%3g’ßZÉ S¬4#‘ÜMI-%Ó#HMR-“*J¼MÄÓDÜMä7MÄE‰“%½È4J¦FeHS ‰’ò™¤ ^J)±Qb¥ÄBI %æá¤¸‰ÜÙÜAÉm”ÜJɔɲ4¥‰L–ɤ¸®Ò¤2‘’" \”AL±¤GJ…×c ™0¦³4’ñᤀ’üq‘R>%ã"I%cae,%cr#¥1In÷ŽRn$ÉéHFS’]G u$‹’La ”ÙD2^$écÉ(Jn¡äæ‘ÑÒÍ1däM¤‘Ñ䦥›FëDFt$Ã)¹‘’aCc¤aMdèHih ’. ‰$iádp’Ú‘¤Ü.¥PrC8”. êH’ÃIÒÀöRR$ØžèSÈ€þ‰Ò+éß/ZêŸHúE“¾}¥¾é¤O"é.õîDÃÉõ”$P߉ô9{EÅJz6‘ B+éÞ‘\¼Ž’nMäÚ Ò^ºRr•tMu¡$6Åu%±”ÄPÒ™’hˆ¦$ dÊ ‘3I'+‰ ¤c‡8©#%ºC §DŽ$í)i`í( ‹!:+aQˆ%0K(à]Hp$A”àØ:g!ð¿ðƒ~i.úÓýÿÔIîL endstream endobj 80 0 obj 9399 endobj 81 0 obj <> endobj 82 0 obj <> stream xœ]”ËnÛ0E÷ú -ÓE ‘É08~^ô:ýY¢±$ÈòÂ_Þ¹l ta㚎<.6‡íaè—âÇ<¶Ç°äç~èæpïsòS¸ôC¦tÞõí’VòÝ^›)+bîñq[Âõ0œÇÕ*+~Æg·e~äOën<…/Yñ}îÂÜ—üé׿×Çû4}†k–¼Ìê:ïÂ9ÖùÚLßšk($ëùÐÅÇýòxŽ)ÿÞSȵ¬UÚ± ·©iÃÜ —­Ê²ÎWû}…¡ûL9ÛfŽ¡*†–eåêÈZØ®Á†û \‘7`Kö`GÞƒ=s5øEXKÌ+c^Ák²¿‘-xÃ\©³6rîŽuJðžüY•®Óߡޢ¿Ã]ýê(ú{‰¡¿Ã]ý½Ô¡¿†§¢¿Å¹Šþ÷Rô×[0ýìÓßK.ý=î¨èï%†þþ:ù#^'ÿ8ù£:ù£Ž¦¿C?uò‡ƒNþðÔô¯¤>ý+‰¡¿•:©ÿrüu©dŸþú éoÑ+M+ûô·p0ô÷Âô×è§¡¿‡ƒ¡¿ACOC‹÷bèoñ¾ ý½0ý üMê? ý͘ý÷R'õ¿[Cÿ =7ô¯$>õ\Ñß ÏUòßɰ¤©ÀØ`®ÿŒcÞÞç9Ž¢ ¿Ì ¦¯Âßÿ‡iœ%Ÿß}T¢ endstream endobj 83 0 obj <> endobj 84 0 obj <> stream xœå8kx[Õ‘3÷¡·-ù?bë*ЉlÉ‘óŽÝÄ–bc‚í8²ƒ±dKŽlËXrBÔæÕ€Iš”†ð%l „¦¹KqhHÒ–å£-ö£Ï…BJëÅ$´¤íG‰¼s®d“°i·Ûoÿí½:G3sæÌÌ™™3çH±¡á0˜`x»úƒƒò¼"7¼€é][cÒxÿrÁ§¸@÷àæþÒÊ×>d­¸¹o{÷§esÀX `x®' ýôúf'@¶‰d,î!ÂCi¯!|nOì†eÚI†÷>¿/ÒÔ;aáû/íÞ0ø%~œ'ü8áÒ@°?ÜùìO¿@øë¤ïü`${ Šã…?eãƒCáÁ6»ðɦLj†ô²‡ô£†á/ˆ­No0šRRÍ–´tøÿõˆ/B!Ü,z! ®RûKa9dÂ6€©öY¿zêÏÿ—VèÔs±>‚7ƒ×Q€oÁ9ø |ëðòÅÜX‚VD8Glƒ(fÂkÄ}óáaÊþaááhÃ3ø!Ƹ€ÛÏ `*¼ÅÝr©¬ø¦>$Iâ^êßÇû™åâ-|.(Ü*ØÉ}“k“Ín7×Sð".'ý›`îK ˆÂÍŸ3¯î€¾”N±2që¦þßSð#øO¸vÁ~x„»«œú˜ôŸ% €ËÅ,4$§œ˜ž«yœäŽsº À—é]GoBø ü¥x?Yw î…W`;¦`—0Ž¥h‡7É?ýð5èƒ{à)8¿Ä ´„}XƒÞ©28ØVÈÃ;⿈·Òþzz¡FL“½­þ– Íë›®Zweýuµk}Þšê5«eϪ•U+–/[ºdñ¢.gyYiIqÑ\û›5'3ÍbNM1ô:­Fx¡Ìk÷$¥8 ÅöÚÚr†ÛƒD^D(‘|—ò(R@e“.唉³ûsœr‚SžáD‹TUåe’×.)/ÕØ¥ lkò¼»ÆÞ*)“*¼N……bI!Äf£’7§§FR0 yßÖž1o †ä Õöê°¡¼ Æ F)¥öAòò*T®Ô»|œ] S«ðEÞ`Hilò{kòm¶Öò²:%Õ^£Aµ*RÑT+ZU¤ÔËL‡»¥ñ²Sc»&,Ðp˜BöPð¿ÂiîïÛ©¤9”yöeÞŽ39´ò°Rf¯ñ*&µ~ýŒžúÏT¢"YìÒØy åØ'?¸”LR4E–óÀ@¹wlÌg—|c±àÄÔh§]²ØÇÆM¦±A/yý4kbê™»óß®VÅèÁåÉÅúÖ×+M›ü Wä“z‚D¡Çn[šoKkæiü[Ã@Ž wOm6¶ð»'dè$Dmò'p :ó‚ìr´*\€œšÉja#£Ó#3ÓvŠf}³LŠêBv/ùøî 2ÚIù´……ÂnQRÿ”o³¥§IË\­*¯DVÕ…z%E,&·Ð¬‹'P¦°)cIýSâk2Ÿ§¥KËì$†ÉñÚ½ägkO ÊË”ZG"ôüŠ\C€LÆÈ;^á¢Á…¨·F Ÿâ²*™ö53ñdfy{›ýê”ä4%³Z@Wr–âòÖ0Í’w,P“0ɲ7ùAåÔéñ…Rþ“•°Zksv5åU±wÌêV¬üí´nÉŸoSäV p«Ýne‰FšwšÔÙT W½Á_ßl¯ojó/M’`â„"ïçÄØýù 1”rŠ®H'ù¹|¾•-D|Ø×TQ¯h‹tÔ,äp•ÊRuM•ä§ú=ÍMf(ó$o¸&ÉÇðK„Š,ªk§¥iJrªkóm­¶ÄS^ÆÑ°”TL3tÌ©µÓC|U¢q$F%1_æ°œ—üö°½ÕÞ#)r£Ÿ­¹GõrҪϓ±Úp v‘³ÈM`£ái„9Sñ9ò/v®²VÅgÐÚÏ ×MKc:{}ónO ¤Sª¨N–ÂòÒ´|u÷³ýl÷iÓŽV÷óظ,³½Üö혽.4foöW©ÜTAnÎßÁt¥C=ÖoXS^FÅl͸ïl—ñÎæ6ÿ1 ]ÍîÜà?Ê!WXÓ:>—ÆüÇ$Y¥rŒÊˆ ‘Â$­'D§òç“FÕQA%¨xׂJÓMÓº&¸Í2Mãˆ&$h²JcE)§‡|LõÛ+…X|njí ´²‡lò}PAû*òŽ}Õ8r“b°‡×(FûF÷0º'A×0º–2³±¼lǘÅk?ŸSÎŽFèŽË…ĺIkÁ9Žàª:ªœ“îqøzÕQž#èrKd‘‘j5®O«Ž"£W¦ÙÒŠli¶NŠÏÅûã=bË'OÔ/±#†éžÖ)þòáŠc`˜:-—èMµyy`¶˜9³¹ }œ¨è%g4š„Æ\ÑŒYàñTNº=“èjo¯¬tY&ÝéË\í•®à@Òh[d[´pWéΞ•åDûœT®mYÜîø{S¤Ö~í7néþf•gOíò+ü.Ó§·ó7h^uSÈ“n˜Ðó\Õó—H¬}Wüj¡Oh »ÌR¨“³{r𺠥b(-k,X^¢±ùæLL’ÓÉö9Åf[~^YcV¶¸°Ñh3Òíñ Ë1éf6N’…íô`!ŸU¹Š¯trY™©œ}Ž“+±gfgfg‘õ ‹K0³¬_Å-ZX̬LJ8À ùk×·9;öTtÞ.okªÎáãïj8,(YuÅ\gý¢‚Þ€½ÞS*,×Î_¸8kq½+kÃþ—¶ßø“ý2ËëJÜ‹sã× n¸qÎ…7®ÛÝ£µf¤fO _Sã³×ΚUµÖ"Jb…È‹‹™2-µ‹ÙôzÒšf[Š<å 7sDú2: ,/9(j“•®É45f“• —`»HN`QóࢅNŽ-[[Ä\D>Q½±$+•·Ï).±§òÚT>+3[õ>}Õòàþ7³Š—̱.,Î㯙Vö-ò£_h3ì³¥ÂÜÒÒòÂ-aƒföê¦Ðù/–_µÌ¶rÅâ + 3Í;® ÜÖT„Â’ î¬TûŠòÔµÃ]ÏŸŠßP\5/Ks¿Æ zÂî†%œžC£½zÙºzg}g%ËßòW ùK‚+ä²ÞBìÍCK~¾yöì9Ù3^Éh4tXÐb1XäüÆ|.??§‘9„Ðî¡fa9LžqQ'<1í–³D–½š,K¥{ñ1•çoùÞ¨ì»ý{7ö~}k]jümSÀ}ϯûR0ϰvû·2ïy馯~ùÊ¥ÁÛ¯Lmîzf<>¥ÔßÕëaö¦ýöúÝd„;dW·~‰àz¸ÒhÈ4 ×éЀëuZ]½Þ©7¼i@ƒQ§Ó£^ÄxÒÈYp zs­Ñ˜¢å}C3(ãƒ9A¯3‹`xúæq»)á+g-Ss>­Òå }Ù^™¶¬}§c§ã9lß™cq8,ϱµÚPË6kÚôÈâon¿K¿|nEgüv|·!¾E|ñÓoã©xÛ…>²‡ãWó/“ýZX hµ{¨*pzñ£Ø©8Ñ …óây*(žÉDu˜œ. T²HWsmqãWk‡O|¢;Éò¾–âx‡ØF~™r´ %S…éo2妷5jPcîÐ Y|Æ´dUðõ´ŸÑ6 ÒÔÙvÕ¨™¹X¸#þ^üzÙšHæÄ¶cûöoܾ}÷hüÑøÃØ‰­ô¶Åÿ5þèûo½ýÎ;““‰šs'Åi+ýNJ%{–Ê©Ð&™+XEÌÍÔ¶é˜çÍúÔZ¦#3S›Ñ¡çµéT™=“ªÏ™aÌ.ª+‰bH‰$.,&˜Yµuå¾Ç¿Ç…§w>«'þ‹Ûn»ÿ‘Ûwð6}}ÇÚø\Ñ»bàážþöxG?ys%Ù±—ìЂ,Ïפ¢È¥6ˆâAñˆxVœ¢ÒŒmî,7ÅñWAÇ"ª5nÕùϵ;0DzîŒê~V•³¸O⿊oš…à_ Á3gÔs૤gé1B³¼d‚. ÔÖ ,D4‹q„t ¢(´EôgõSz^ÒWè9½ ëЦóÆ ¢ØªzÝšJÊ=êTd$OÚÓl_å÷ňK>íÃ%ñŠÞ3ŸÞvæ 3³a'ÙàSÿG¸]® ›p½ ½&t›P4e™ŠL¼q ീWV–ÝÏ0°&ë3¯I#x:ã\w032f™PÅÊD±2d ‘O1@:ÛžÊÊ™ó ,¬L Ø~ñcÃìYtF0¯aq‰Ä}ÕixQàâSØ„wé4¢‘ÿCíšÙUË*3/ ŠÞ¿þ±zͲ›ÝÜ#Ÿ|—ÖTLy½›òzŒÊÝK±{Ö•¶–ö–òÝFn­‹79aSšºæÚ´´ÎMúM#º=:N§+`ô|CjmAšSœ×9G.Æââ9‚)(Ž²Ê ÒnPkX¢§úN #p’Á´Ä4õÀS׃ê)7·¤¨çxNqú‡tÕùY…¢°»fì•]¿ÿr>̺g¤ª£f®'¸u‰ks§MIË—&B§?-Š¿•=ô4Wf¹›z/ì Ô:p§ÿ¾UÏ?[tmziuÅboy9ÅZ¶býuÞÎ=íåãÏlº&×±¤°Â3¿ 5ÅV¾rà ù(N5ů֔%r÷Ѩv¯–ÓjA/£4:@*,"àg……µ´äFËX¤¦vZœŠŠBÅåê“â_NüånªW?§Íüg\@¹9_Nã÷Ó=‘67Œ‚ç@`²Ÿ6’h<ÀòBÊê‰ZŽ6\™,x”òr=å¥ÖžÌI1Ôò¼F§3¢Ø¦aÚ¨k„Fp÷à!w󵮃¶ü”ˆ¢¨:×'•$+îLS¯UgbƒS»‹áBºð÷#Z@üø™øI¨‰…‡·4þ¶Ã\u¬‰ÿí~|ÇÜmývµð ÝF©ú°0Aržæñ \ü—Ûçþã⸀Ýg‡alvÆâ0ÔR _Ium'Ýã”’ïRùËà ð1îÂ3\ ½ƒÜ÷)_Áñ¯ ÂC !N÷†NUKx“vp`JÀ;ùY”Mlt6nœ±Ež± Á r¦r I˜+4'a2a( ‹`‚/&a i¼' ka|3 ë ­IX©X™„dÃꙥ؞„S`ïN©àà ÌbAOØ(·( #rO%atÜ«I˜‡UÜkIX€R>7 ‹Ã¯NÂ(æ[“°>æG’°J…hÖÃlá@6ÂRáé$l‚k„³I8âb}N…šºšÞͽ±Þá Æ‚Òã’»¢b‰´:Ú…‡¤êÈÐ`d(ë 8¥Õ}}ÒPïæžXT GÃC[Ã!畽áĸ´.2Yé ÍL.—>7*±áËÑ6†‡¢Œ°ÀYáþlœ —nJoT J±¡`(ܺNŠtKëÉöÚ`¬Lªèr’a›{£±ð{¤g³Sj ÆÂ1)8’6ÌLlèîîí «Ä®ðP,HÌ‘X½ex¨7êíbÚ¢ÎË9¢9Þ–Öc±p42Ћ .w¹¶mÛæ &™»ˆ×Ùéwý½±ØöÁp(íÝ<@kwöÄúûZ¢a¶žX­ñ¢wGÈøh¤;¶-8fëwn wŤX„xÃR­c€¦7…Ãýl¥ÃªÅÛzz»z¤í‘a)ØÕŒ‘Gûß’ìü{ÆöÍLR-¥ŸJ½°™ZŒÚCˆ~„ Hx Ç©¹¡‚Þ%­†(tÏq„iJP úTû *#B£N•·^‰èL~EU,LßlîVU—®¤ñN•òÙ| Ö©ßXC­øþ»ærj®43ûåÛ¨òDg8}´þËÍŸž]þ?héU×Í|SG˜ýýô=×-ÝÔ¯Oú½VYFPÍíRýÈ<¶Y•Se'8{UÙ-ÄѬr5ª3™bª¶•kÃe46ÆnšÏ¼ùg—*›Ååp•õÛÔŸ>|î° O`áQK†ïØÔ),³Lf߇høPàÐéCç »k!3K`µƒÔŽ`‰&<òP©µñ`à ÷ð«ôPãCÜè½Îà+V§â\R;©ñdžÜ>¢öGÐ. åÁÑ÷>Èï}￯Ô¸#û_Þÿæ~~ï~]bl ~„*~Rí©ß«R_Qqs’ëZälÞ|¯ç^μÍû\û<ûFöÜwvŸfÓå‚]%Ö¯ÜSbÝKßgw£y—uÇ:×®ƒ»óqL#§Çîúcæt_ÃN츕B•'gl+³n–Z‡£¹ÖµhcºõYÌÅlª»VÌÁì£eÖ‘“„î¡vOëÎ:š;›¢Ÿ)WøÊ¬ƒ>·5Bm€’4sZr+sZ´•|‹†²§³c®5H-@­£1×:ø ` Oq×úæZ&0CÎÅk|¹ÖMmnk›/ÏšáNo‘oÜ|Ëêd[¾d5óØLV­§ÖÔXh½ÊWh½Òç´ŽÔc=ÍœÀÔ'}¥V µI¾Î˜ê»Â7Ûz¶nªŽk¬Ã:ŸÑê©m¨åj}ÙÖµ¾ «Ù7â;ë›ò ³Cù-Ù44·XÜæ¡ÝÐb5{Ìæ³`6»Ì æˆyùMó”Yë!ÚY3¤;øh6Šä¼½ãšŽú íÔúzE߸IÁ;•¢fÖËMmŠæNZÚ6ùÇ¿ÔzÇîݰ¦ ^q7û•@Ak½"@fÀ(–‚ñlXÓEcÃõÁ˜ÃsD©w€#¦’¢*€§quh4JÃ$‡cÑh4FF`È0D0q2Ñ >jQ¤!‡J¦éTZ˜d`U2ÃØˆC•Äæ«º ʸ¢9ÿš aí endstream endobj 85 0 obj 5878 endobj 86 0 obj <> endobj 87 0 obj <> stream xœ]‘Moƒ0 †ïüŠ»CE ôKBH--‡}ht?€&¦C! é¿Øî6iÐcû}ÇŽËúT›ÞÇonT xÑõF;˜Æ»S ®pëM”¤B÷Ê?"ú«¡µQ¼Í[¤IJ¹ÙSâ­D^q>AΘWÈkæ#ò†8%ý–xMùqV!ï9Ošs†|d͹d>#ŸXCw™OÈß…šD²{N¸ÿ¬Dæþ³5=üñBîèg´BÝ c¥EÒ> endobj 89 0 obj <> stream xœœºc%m—Z]î²]Õ§lÛv—mÛ¶m£Ë¶mÛ¶m›·ßof¾¹sg~Ý8'óÙkïõì½režÈˆCŒ/«@Íoh£o$bcíHMOCÇ6³ÒwrPгþM-`ci(hcmø °@+š9ZýŸPÄÊFöf6Öÿ•+ho¤çø7 ¤çø·DÑÔ Àïd0è™8˜˜9èÙ tt¬ÿ•hcÏ0¶·Ñ‡"´±u³731uäüû@¦$¯BNIIõßzvvv€¾Û!!#3kÉÿ øu6²´±µ2²väþ [ZšL,ÝlMz††F†ÿp(ëYYDÌ,Ílmmœd‚äÿ“åo£ôÔ¿˜¡ˆ¢FÖFöGúWá?¢‰ØØ›ýk:VF™©££--­ñ_ÈøˆÆÁ˜ÆÚÈ‘ö/'±°õ_±¬þéÆ êŸb!3{#ƒ¿Ã»Ñþ_ª[XÛ¸X{üŸ±™µá?[ li•¬Í윌ąþ³àoê¿c&FŽf::vz&€‘ÀÈÕÀ”öŸ­ÝlþÒÿÖ³6ôò°µ±ëY:y™ý=@y8è9팼<þßÀÿ\AÑÓ Í úF&fÖPÿÍþ7ldük)=G{3W€Í_-tÿ|þ}¦õ׆6Ö–nÿ.­geø?ÿwŠ€€+Àƒšž‘@ÍHÇ `ce°³2¼þ'Û¿uø/ þ•Õ3ûÏéþ›QÜÚØ@O÷³üñ?çÐ:ÿ‡µdÿX›ð?6øÛ¥£™Ñ_×üÛ›štÌtmù÷@ÿzöàÿvîÿ?³þÃ%øÓ»ôu(âdiù/EÉþCQÀ_I¿ÿˆ øGU#k#Ãÿ]¦geféöþ¯L£ÿ¸Kÿ!üß4 ÿ/¡´âŽzÇâ·6±üƒˆ™«‘¡¬™£é8ð?¥¿½Ù[šYÉÚ8˜ýó4PÓÓÑýAES3 k#‡¿ù_˜Ñ_£üO[ØšY›ÿZ]ÏÞðß`'{û¿ªÿëÂÿ­ý¯µ±Ùߌ\  ÌVø…˜F¹‘ ?,áaÑ&„Iœ'uÍ5êzBv&8¿RàWj`ˆãØ÷ÕÞÆ ­¿ÓXz©>*nâ{|HB”ò1‘ÝïT‰}bUá¬f•všÃPh¾û¹x!cj'Ù)‹kÀ1â¾5´h{Ïz•DlŠ_â™ÿÙ=SèT^‡œmez±ƒ—å`Lo‡~k ^®žõtê1ÙJ:~\IãRÇc±`#ŒKåÏÑ9šËaçÝêÄE¹nzÛ}ËDmôàä!¶•PØ„ÂÛ«YøýÂòF23uÔ•%¤ G•D¬އ½S(÷£zl‹:ôA(À<͹9ðO ûËøØz!×±†PKð—¿GWwfhú~Ðg¿_ âg’dSÌMÏþBÃpk¨Þ2GðBeÄ1ãVô¤ b:eWâGþeéeÚÈãsfÈh°%Ç £1¿ŠÆß²F`·­®'Q|¶¾¾br²îüY’fÝúpÓ a±7Q\袖am˜äÍuu$á(óUß%õÿ„ªÉŒ®èrf¼•aéÁi5•Cê'~9‡×Æ`*•i aÙÛ|+¿*âKEGG%âtû±Ï6Ž5çð—nbq°O‘LR5jÛŠß·¼w5¸; èªè²)Ȱây_§êC†¡ ãòÁ­@&ѸT¸o‰P§I‰·^ˆFÇ <ùkXÍ,- wȵæÖˆEÈÞ>$¦ßu6›kJüÐ’ƒØ$ý 4Õ? \öø- ç‘mÉQÎ-fêLZ.?„K?Pœ¢bN÷ÜÀ{ueœó~ØmåÖ7±díIÀS­úÕÀ«†ÿ ÃÀ‚Câ•‹HÜa :Öø‰ÄL›x]ÕVWA±ë ?`Î#)öýDyÊÉNÓÖì#ú FLòjKOןòØôY –²0‹ô«¦ÁÄ.éä:Ú¾°dxϯT˜ã5MuýSžœôêwb:uºÆù3¯AQ¬óBB™)|ÃcÞŠ¿h%_"ˆèŒN Ï,Äy´ÿãèD ²h6Á©‘œ©†?àÂ[®B ÇŽƒÌOjNf‰¼Ù“Ë·Ô ?r˜ŸÕ Ü•l¸½RüS!ðLÔ3ëG/®›âH\j&6¡ù T=7Y\ìÁ­A QDMœ_¸áC9üԔͽ+á§pU~VÎqTwm-ƒ·ê‡'˜ÇÅÆQ.Çgç‹¡Èb;ÛH—=g¶=3¡YgÊޠò4æŸ8;•—#ÆÑp†‰Ý,ùèËÒµlË|æš.ûïiþl{­êæ°`¼×£Ú›þ!n3!ïè6‡ªÀܦ]|È ÎR¤UªE/X´£+R³Ô ÅwFW++„Ä£k’¹ß'ÔP€l”ä_ð¯nuQ#’^Nqf©ÊBr£^wÓí6ˆ–ɪ¥=œ3íyÏ«ã´Æ£8"‡¾ F fœÝù¢·n¹·_i´¾?ÈP ™wé%<¦+¿qåŠä¡édîôG7´*D µ™)…Þ4ÿlÛü츌ð^ºîµHöQ—-³oô¹Jèr l®H‡möúz[X·y趘@ä¿9 xySëÔÊÕãOKÐrš¶ÚvW¢…N›ì ]ØP½ßª´?bKÉδ98Š–‰²óµð[ˆòÒaÓ=¡¬šSî¡£?ÌÝç“G}*˜¿}«D"LžÚ'ðþ“ƒäÙÓ=jÓÆÂ1îVg'aî×e )·ß%†r†ícºÝ[jÎßnü ôˆJˆ‡M±ùãL9„nXßQ(èÓP]ubÓK¶Qþ ì×Iú<ïúëà ˱™•;;¶;všR*9Âì9ÞP¦¤–×~2rD2õ‰á’ƒÄ’e)þ4ÏX,”žMÀÒ“°î ÊkÇß'' ¾–#¶%{£IÙ 2›Y0C¾S¬ÙïàѺàˆlö1Y× ZÈĆcïÆÿè§2ý{ó¢è*þ@Oç-²ïOÉ8AÅÓÏÃå ,¾-ÞÍ";lÁoNÛ{“ÈøWŒº— ²ÆÅ8cµu»Ëãß?Á¹ã](Ï.i®Ô]*#ç£Bn.Eã²¼ÛDÌ)ËuÞg+£+«“¢;;6âá@êóeµ<öAsìæP­ƒÂú|Ì3ºBX”:%-0‡ÔÝߨò1lkt„‹? ‘ÐèƘĸ¾^á-dïhô²|7MLyíiY\ëÙUIãËv6òLÕü5Žcœ Y\t¡ëè™,´nB#˜‘.ßåQ£AifË—øFàEÕ'Qç‹Éu]§ idîqõ)Ä ;‹ÂÈÎì 1P„]½ ®ýaK©ž‰à.Éj“›×ÞѺu¬rxu슈Ž~4Ù¯º'b;ª‡á6N&a©Ãf³I¢ÆÜ UG8€Ô-ú…jãèõŒ`ÒÅ¡%Ñ1}"ü€8_æw¯ Ž+Ò)¼ƒh­´-Jìùë!0:êJKoo1&ƒÙÂæœÞ‰2ø!j·aùb>¦´ñXèªY×à¼po=}¨…cÆ2*ò8U±¤VVËå//tx%¶$°h¬…\Æü !‘Ål³HaeÁ» (|.L1VêxÁ0V¾ì>Œë_$ª—ƒì%¶™Hu ÷ToXÉ1X™íOŠœ ¾³OòË´VѪ¥ÎâÚðù\WG˜[ÌŒÑJÄå2dpücóÔÛSô[ó”<ê¹Õ.òâÐa}R¹a9Vœ{ª„í7ÂW³ûf3ŸK½xvá.mÁßî[ÑÇœ ö¸×,––>¸]šBðŠÚ_¼¸–é­ãÄÏ1ýï’‹0Dž™«÷E¶HR¿yçð’á™Þ¦®Æ¢w‚ëÁðÑ&z6$7ÕubeaTαþ@x& *z ¼¨ %$ëHhUÚÍ µvltW/Ç-Ÿœ²;ÿôØ:*bÖz¨ »’ú)é9R.jâU‘K}t¯ÙºëeFY¸wÆLJZU?XÃ0¡XÑu-?h¸nã…›~2ôï”q ÿ1Ë7d°ü9¶.v@PgñXê7Î訯Âþqšn¸ha6;«š±Æ^Ì*ש®c0õJ5+dg±èG85r÷Æ.f À‰Ä>Ê“âIP,­¾ Në;S6Óv‡ ª3\ H=c×Ú^=‹J®TäèO»§ª—/S¸@˜–wGnMóY¸÷Ô)»êÅWÑ £SØÙÚqR[uD KY%,ªåŠ-.b®ŒÚ¥½’ó°y;pïK)¦çf§La½ƒ _›2I¾ÈÂðÆ”ð>ÎïŽÍ¥Éó;¢ü »$«Z¯öB*åyôæå -¯éQì3“HçPO±÷ëawwüㄊÔËA2qS¹4‡ôqNÞÞÞZãÕA ÿÔn÷4cÀbLÔ™ ‹ÄóƒöÕ•Ì¿qÑ3y·. ËãéÌE ]½ká‹C— ÷Pì†"4éM®ó=1–)ÕMbÿCrå ~—NåÉ9ïüËWÃGÏ®c·Â_ù£ÿýˆßYjØóbš7zÚFŒyÎR§Ü”9gAšËºhŠârëy×=ÝÿÀËÎ ZäâßOJŽaÇ+ñ¶ 4¼’„…XªÜ.47͵ü@¾!­ê6èl}[gÇÍÝO¡#sMcœŒ˜|z‚!ˆ™Õã¶²Ò†ûb鎦JŠ8žP=äݲøüäe:%,˜ü™”H`4¡ï¶ ÿ¬þa”è!”?ªÇ·LYÄý'»œÂKû¹/R¬v®Wà˜d¯z .™E ~3¸XÍÈ›"ìƒ08 8'-ÒáKZJsúÓ8Ûy—E¬Ù(O#<‹=ÀA­Yÿ!TPéí÷bçi] ¾ÒîlÔ2%¿²ú6²÷yÁSås×ÅrDø~c.ûã B¸p8)ê'N”ÓÌOô+LFu™LvøòöýC†|Àμâ{å5A5ÑŽ JÃ/ž2 Ix²•ÓÚ7r‡×3.©ô8é¸D¬¯)Ú»ËÍq*‰ïúJwRg{˜âߣ‹xwRã§â3XoÖ­¥‡pwÙŽeªÓ»”?Jõ¦—÷@w¬Æ) HÎÚ¸—±X§gšB‡  ¯2¶Tc6‘t°—_ª6U*U­úo¾qðJ×wTÚUMãcª”˜7lX‡Ø%Ÿ‰-“>ËhlÐK‹n ^WÇÏi˜þd?IÆôÎOî›=Dö›±«D(t ÙÍ€äòŒ©»0=j¶H±ÉìÚ|® mµ›˜JJ-Yð1g”_;†Ó–Öm$îo]×;<ž’»&¸’@âÂé'çdÔ«k¡o|Šñ Ç, ý>ŠäCüùâÚ3 î¾@n䊿ætSF±Œƒ4ý£É~Y .Rã¥TÆ)¨ÀýB`Mà`–h®\´æÓ@›>Ô­OOüI†HȳÆ>”_Óavð—ocâ9©C˜]XÞÃ~¸s0ƒ“’¤ Gœêû€‚ÃíX1Úå• };Øwx@ˆi;»¸¶”“ÀÐ1Œ­À¬;?É¥Mö»"mõRö'ñ ]¤R,Õmq|’:C£’M¦VáÁebV=i~oSFñ¼ç%ÌÂÕ.2ÄÈ«+wR|ËÜÓDE€:¥0»& ˆLÈ…¾‰Ç»ñ: × TahïíäÙÓsÜï%,Å} ·£†@7òY採‹ØeX6ñ“šáúª`Ghãt0Ë%ýQ.¿åŒ¿†n Ì,·ûl±¤â Ÿfé2T›$zº}Ò0×.ž½ÉÒx¦›´j¿>‘mà‰èervME÷fšÈxmL¸ø‘.³†¹Þ€1‚e+&±÷˜7Ÿ° çx5 $žC}YÕCK­k!i `‡ûL÷œ€tûˆWH¤ueCiQ°{ñýÎ>“jqÄñ,\_¸ûH™$šR`và€W?®g`×ö<˜9¨POH¤ép4~ËñõL÷ZÉ&&¯0Źßm§­™ö ‹üÉœŒ{Ân¶ì×tœNcäø°+õ›vÅ”Gîk;Wg/ÚHËŒ6«gN/–çê:è¸äÔ¡9Ǿïoâ @8!qªù³WrizÒT.»:-tK=½§|áÐ$Tbæ.m¯ÙÜ÷is†²½ ´ "”¼Yû â2/]àŸÁ}ƪrS-ÍzãaÆYž n]° ê|üt„;ù‰‰æçƒö¥¯Fý±®»ïdD'h5úÉgàœ‹u“6p’Ói4…‡w¯#Õ“*·f)"QÙ~C#l1ôé^ÿÎä‘ñ&ÿP†oäçPÑ®üSb<ßÂqC޹ÎÐ\0žƒ¹0l­³Gú[t)ÙBÒwRåWúhr_ÌaR3ÕÑÉóÍ& $©Œ¢æb0gÊ!·³9/[JÉ( ¼—“0«Éžð„ÞgÀÞÅϫˈ²>h7â)n1JœÐòÍhÎ µ_”ìy6éá1èT@òŸºU;¯Í©á“ó†rRƒAt”º÷@Ð-–òùØ™p-‚¿*Î ¿¦n • ³n³Àå°;ƒ…Š!ÇÒèÞ¿ïjv=­ñZo ûjh£‰3n*‰rB©lUëM#V ¤«ÖR@v$†Ö7<³Ào\µˆú¬ú5 š0LÃçWØ Õ¢Ý\Áçy¾ý~*\2 ´4½ä“YðÈ8†ÙT¿FlìUÛ\,Ú³xöûу‘ôSâ4[=(é,°¸ä¦£Ïu!v9œánª®½¥PÈû÷ ¾ÂÝ‹S{飯tM5ãNÌyf=Z—!T !`Ò—¿Ïy«ÄËÚ2²BÑáÅIö¦ ®¾:u• ÿ*’Ðs0%Ïö$ÑÃà8 ÔÑPRU}ˆÕÈÀ²€[Ó½aõ€O{g=P¤†~ï¶€änœìHÎ=Žq,° tÝë£ÚS_šRϱäQ©¸Bø§xŠÛÌ:òÝ9TÎô¡×™Sõ…&!€4Ú[Þí(_G"™Š/bw‡>–6n¤_õ™.–ò–šÓTšÄó©mæIª7}—Åw‚² åFØÌƒ{C¦¥ÄÅH5çá’7OÑ@üMflFO=:µzY„+6{9ù"›P‚¬0 ©ðcî.×·Ù¸A¯HÜ}Åإͭ(nÇÀƒˆÐªz§:%FÁíhQ…=/˜x‹Š/uÑõ*GŠâ^íŸg.Þ±êÜ2G@ùag´ph6ë32,šà>ý A¡!7°„ å¨çðyŒÆ_¯¶‰@Xð!Ŭl¹!aþ3”y—N.+~æV—¿pËt¢Ê~’b#…,MÌEàå°q@;.£+u0û*aˆCh*lÓ‡·w¢Í¥:òìð.€uå}79ô$EÕ%I!wÝ/²©gÇü“™Š·®*Ò•L®ÛÝU^m9ãW×@§oÁÁ.ëùwø¢:ž’ˆ¶W=LŠ‚€”tÀ| zÐgnÚîîÏÃâØükPÌ/Kï7Ï >/8t²•‚–™a-e `£F±ÛYŸÄὄîû”ŒÜä©‚„¶ ´`›Ù,V!¡Ópé¢È€ÎÞBL$qÞ â±†…_+ßéÚÉAçnÕ°L{Í‘‰OŸàpG˜èwЖAÍKc &ï˜9s~ùönF@£‰%Rõï;žW,²p›#n‰¥œe¹…¿œ!I‹‰ô¿]%ðBMá¡ïÕ²¸æåi¾»æð"ìO·Q@ÒB”‡g¶wTWË»NG|…ßcÀú ó•¹*ù\†Ã÷œ>®HIH\À´rdX&n@5g:_ÃM>­r.Øìqä¨ ›ž[Ф¶/Ýè€\Vペ rÔs°¼‹‚÷õ¦µç¡TÞï¬ÃjàJ?fˆ‡  Ý:D“઎^ÞÈG3W$¦àã ÏÐÆ´…‚Õ÷òvŠÂÆ£új¦û_rÆÚ ’Õú/rb”uŽt<˜S 9lüv<0¬ä^Ët”½ 옘U*p¦Åäm_¥ókÒ «'¥þíϘ¤1 çFQÿ~ý¹¢‹ËAöÀn 7¯qìÌ|K¼„·S'¼óÍÇ-û86oä„LÍ™P4/Ubœ@S4B¼6 J9 OK‚nnÁÙµ[z÷Û]MTrVã÷”ˆP¨7›&+âMþ *í°ä»."ñöWLÃ+÷‡9¡_%~±ܼyf~ûFuȇ©1~„ñ“ 3äQŒÅ•p{HÇôí€ÈAOPW±ºµ¢¶‰EMŸà{0{~«“ﳌã +Ì’C}X›º˜V¿›\¢W@ŒÙÝ…¨]¿V]á½õ‘·4ÊEYÞ½öòÆ94ËÞƒ›Ìˬ®æÍgN¢m<>þ@î^éÕÍV¼-„ÃJ_k±fR t9ïn© )¦¯™s™4þ|yA´,™¯iù“¹T!xPJÌ}ÿ%cQ‰ÿ0u¡Ìæ:#|KŸ±ï¡^OSlQ1›¤ 4j}|–\äP /ûËQž¶§ïgÌ’te&††ç{@eüõRHʾ4ÊØþÍ-…>f߈@Ã~=Êô°«ÅàeÁˆr{5®½Ç™•5ãÁ–úF.ø½lìûçºmYÜÎ8eÐDWRÖsZþ<¶Š`éÂçÖÕ«~d÷µóA«ÄéÇk²15ª‡d”¶që:µe'¯“Ø2¡¦_ÈðÏ`TS=Êšßc1¥ÑÁäÄÚýxRœñ¬˜¼”9„½ôñ¡n¥w‹»¬æî–½¸=ûæèÞ[TߥÇÞÄ AŽCŸ–¥¦ßÜX¸)£Èµ+©}*pÖóï¥8ŽÅªÀ.pI­˜nÙÁ€Ž®x„fßÁÆžxÚc7õÑe¹°9Z$&Ž.þØËȆ¥¥Ì¹Œ§ÉåØi ;ÍVª‰aíáN‡q[}{+…Œö˜cÌo˜î2³ÛK¨¯v²8ÞÜ7nû¬Òßq²p qÑ"ƒå)Ó,—„ªÇ9àø*¬ÛD™7tQÓÍÄ®¦âµÕ[=üPb6 `¥ÿM¨ÉQ{^âQcìâ¿[XhHKwÂÒñ;àÆíJ÷z 7²$ºÑµTkÑLµ™áؾ/Ö×ÖŽ ¢,KÙplÞË=ˆ_ÎyC±Y|êßû9S7†@|¡Ë¨½ŒÅÔ•þ°¬¥ðå©êrÁÛp&­ ØE *’gÚ– ‚Í–=ø!§+ZYSç’A¬ÁéòŸÛqʳ´ •« 8?FI\¡¾Hu¯¨”Sy9ðš¸eõ£‡\.€ÃÝz÷‰‰½MïÒÈcêkÁm@Øß}“ûEg\°@¯¯g‡,…2b1ý’ÙO'A¢0-¬ÂøCNöbAAï—z†R~°vôhø~”„¯+ß¾ÂÔç?BœPÅt>‚*<½³Ïbe*>SX#§ŒVd€f)þaW[²À5.ˆ´•WÚ>³ò/âÃÚ€B¨…IœýζR¥ÝX¬]Ò•¦‚ÚßMPßD ¶@zÙ@•–t«5Áˆí…Z>íõÕ1gS>ÆàØùyísäßf_,¯¬½~“…OüÓÏ™-PCÕòhôÁñA€}úY.Ï–pÖb¢#’îL%¶ ªÙëWuýîqeÙ·[,¨ÇÃi'w©¥o‹¼LÙ#áøé‚öNÏoK”€Ùd› Þ¿ï¸ên]—’˜MÂÒ-_ªŽ¥ÈѬc€?GÉ¡n4ßJ4x>ÄËè~ñ¨ÏA¶à²%ÈÛ.·œÂPWE.]a3¶ßY¿š1R-CÙ—‘Ÿû0ÇIDѽd7zí2ñ?âÒ¹¶«ó·úˆ`¥s¡ƒ1¸Auôù³>U§;PaPžTóž€Îô\}ÛÀO¬˜9ÇyÂߦ<®>ÚÐS¦Eã6Op¶Àu‡'>‡ì“챋ï*jÕ*˜Š‚[¾–ß±J€qþª­{Y×ÜG\© Ë5pÿÐí-Dù@lu>ÖiÑ®ÄyÌøDÍ«[›„ïÁß§Ù›ócqN•æ8û¡„áí•Ú½gB }* ‰õhÛÉÝqŠª\ê@£è}ï4Ä<佞—Ϙª8!“ º²WS#Àê™F<Û‘˜æ¢Æ+UaUöžSWßLæ?JU7Bõ-/¼úê-ŠNÔtêA0še…µ¾p™kq¨EÍÀbx*K̽b*h”/–C]šÔ‘f61–,y†ºŠ«`ÓSÝD”l6“ÒämS„D–1Âu¾[§Q dÐI©gR šÃ®Ê&ühù±)˵¼Mòó¹h#~–ƒP3QÍœ½¼Þ¼G¨Næ>Í=ç%!jBŒÓ‹þxÏ®' äÈà÷VSðÔ`¾÷ï•‚È íYç¼›_Gó‡€@ÌcWöÄöGl·ðIH”¥]è÷^¤©ù"£µÕyç¾>×ÕÁ»ú 9øÕ´µbOPUÞ¥N‘/¹é ™*$Á„lZˆÍ ±6ƪ=zÀ½$©·î)GóÔ۸~éièÅ!{ÒÆ“édÊO§—w£é°œÕÀ $¯µƒ¢ãŠ>ÁZß²þÜíÑnʳ¸Ñ0±5;³“-•Nøçð Ê)­Ír6 Cú˦4]tš{’ÞH9¾¨”P`þÉK®JÛ¯•æ5_©wH_õ,•ÆBÚä$ý ¾´éÒ{¸ò"§3i;¥“…ºËã"sP‡rµ—%yÅØÜñŸi–¦»%±‡à—N×Âê’˜b)Ñ5œíù`Ú"î±",ny´Íþf¶ÏDë?iEÛ;þZ Î)U,ˆ’Ì\ëu@ØÙŒ;¼ê™e¯ŸyI=gÐJ'L-Ø ]_0*ãW:IËT肾³8³ZɈ×t(¿ˆp¾°@Ó@†$ı¯õ…ç%pz‡£©?ô ô?ƒšH$´l–”‰V0DÑàÔæC£œ’—0Xæ}5̇˜ú¥!;Ã\iÕþ¬ˆL½BO{®â>]ðdX×}@ •Ô ­åëgWT^Š^ÁÇ‘U}ð™ùῈÎÒƒÙáæÛD°“ú‹ÁÚky~{†‘—˜ðþÉ\ ”äítžOFQs —&÷è^úT´;È1…1R%Á£$‘9AÚ˜ûÆ^«B>B‡š_—­a0•?‰¬Nà;Å`ñò§‹¬[+åìRÇ^*‘_åYLσ֗±¡èæÖæI.~ö‡©ˆOŒ ÏvpºéB_ÄÉ[[BÞìJœo~„HÎvꉚ%ö™ÖåþX'ßÃamÏN’rŠç¸9 %ƒ&õ¨Iû†¸JËÁ~*ðÂÂ3óçzj¶û,ÞãÑ××­´»Ç”œÁ›˜·BH n•ríÞïS¡3­R­Ë¬Y øI3M‚j¶RÖÏG È,ì´”¯û6ƒìoôÇÉ.K—ÛPÞ¯9ÂVÑSÉ¥°ÕIšGR·¹k%B5{'–8sN …7¨\Ä¥¦Q(ø¯ˆ黨Íþ¯<q%p!\î »þÅ!M\@xI,ãOüéE÷…Ö€/×s©}Ÿ¥ÓËB ™­»;ýÙcIÕ†ÈMÏï¯!ÖÍ î)H[÷M¥÷®éO¦c?Tå_×þA;ñdçEeõa˜îåÖâ&Áºö~ tGä¸ÉÒ(¦ê“ÁåfHms‰Á$)6@‡õ«äßå?ÁlÏÖGæXøzfÆáz¼mTÖ@ŽÁÁ†¯&OT#~¿3ÝÙ ¨ †² [ÃXu&±zGŒßng€iİÊ÷wêÁçRyŽÂ,»•j´œF·ÌHdó Œ/í§Â†`Op°¯½¸álGñ»j-›|Ð Ïë ¿\iàø š*X:·àÀÆyg*îùô϶´R çRŸ×wû[ÈùÇyëMÖÂp§¼%(ÂÚèb?jìm•/ “™=…ãuSè£);ý™í ÛÚÿ¦•a°Š=ç —Þ†!pæàp|5Ž_«ß£dnR°ö?~³é±#2´°økó*&ûºÊÉJÏuM¸Íñ Pu\þ:\$Ë€‰`¿êõR×ÑIXwhW:u<ÉQX®d•v¾Ë÷}ð±1+]!`ËÒ–bWNL’>X7“¹¿n@æß²÷nàmv~À¬ïh6´HðÉÀœ.K¡‚#R»=iÏÛÄÐzkèC^9|)ð«›]pvmGÿ.Öž‡„˜1 ¨)7>Šqwsá›ýÓ·=¡(ÁÔìäRp7–FŠ<^V ðù0fÍUÍác ˆÒ-W¶8÷ñ\3U[¥ý•\¬K™Í’Ä“‘šÊ<*cÎŎ̶#ùÕ©áöjR|µúGl!›×„s·îW„c´¦%¶ávÂ7o|¾P¤IŠݾW^ ]󞊀w&˜(wu¨ÞD®8…è¡lÒx5[sò@rÏ›q“ûÓŒ3ªŽž1Yª#·@ÞË 3ò‚XdOÞm9âçGÄÇA œxÚFVÝr²ú6†‘+F!1™cïgvgp~0F&èbh¬ÄgÏÃDÕë[¾0ÅdõrÑlƒìdäüôi/‰D¶¨ÌY‡Ýz»w]ìgXóÎjœzÓ¡µ™sXéû\¢pb¢:G^ŸPs­w6hp¸r0å²70Þ]6%È»áž9(R…è&ÐC3WXwë¤ Ø1ÝÓ{ƒX¾©Éáç}Ç?g æù%] ç~;zLu5i¸;>,¼ZEðjI©lÝÈ7kî[¶ò玧{I7׈¿Kܰ¥ëa3š^›xùýk@_| ”â^j1[q5Û3uRë5™ò@ ‰¦ “ÒÄ5ù€ËM‚ÅöVFyµv†PZÏ÷ÂBœãí7¾-­Ñ£ƒS‰VI¡ôí³½ÒãX¬Âi!#bµ~€Ök]g)š% ׬ô8\·:¢ÐÇïglg<Ò}´ëÜBØPó=XéÝ2ý~§‹»åöòÕÛØ‘×x%¹X‚ Ú=Å`®º°NU6hµë–â,jùÜÁÛx‡_5{ÎaX HÜ1ë4Vò’ì¶!Ï=¥½EŽÚ2xš3ÒOÏg©+zBͦS.[Cüð¯ (Tü ‘2° ê°ÈÏÕ4îº~žHƒòu³&äº\[.ÝP†† «ÃRÈýâØáŠª‰³î‚iúÐÚ]u®Œ(¿AÞÒKç Ÿ@È¥†$¬Ú' "‰Ì!!–É™{É @ù.†ßfGÖBñyPó'ÙR3FzF2É?e¦b°âw ’×Cг·IÕâZ«|—FYš ä¬öëÀ)q/Ä=ëÔ²è¢ÈßÄ&}It™îxˆUá…E€0IEÊ ƒª Ÿ1*JL‚†„`ÎäÀ*qïàaÙùЄøíèæ,N’ü+@7à é’&81&•Úcó>x\÷ /g8{‚6ϯl°ê™Ô5jÞ2âñJcÎ~8AÃR”!B’Ðß´¢£*<’3Nì邜ËSuC¬Ñ€äÖ¸àôC ÌõäRC² ¯É`”iü¹—jlÞSâz˜¯û&'õݪ[dÇ-ŽvuÅ‘Šu£lAx€Å®c¬o˜S¥ <ÓÌJÿ†V)Ö~פ£Æ9\W¾8zòA;ï&HFÎ72ë­ ’®gµÃÐ2ŽŽ¸lOùt¥M¿Ú7!ëÝ:x)ªKLóÑ+‹>EaxØZ' ­Ä¦<½åœ4sSæ%¯ð½‘¯Ð?Tv”í üëÞ³&©à}Mç\©sá¾ßjЉ9¨[nÁx4)¢šäqfòÃ9Ÿöâ1ÃÎrœªÑçýÚ³dhÌe¿€]O&·v“•óøal~qB^ÖY=SR\4¼¨ž^ÒÚŸCøŠ*ýR°¦Q;­ƒß`q"Í»£iZ~EG(]yŠ/—¶[åáÙŽ!*dÁÛ¹é ×Z´ä=óôàMÿ.èýøxºñØÒ¾}"嵸ý`Ù9÷E…*rí:ÁôçÊòPÕt¯MÅNM&³Þ÷ÕOà‘K°‰"— ³ds“Ô{ðþãÇËH›z]Ž~ mÆK”§¸š$нyÌýJ·sNËgô¼ð¾v™s›¥žJ♂¤}?”B±Om=gN¼€Í$VGú ø½Àšéܳêær«bM¥É +, §J²fèU nÞJè5ÿH²¡e>Ô+Ëöå8• ¤– ¬ÚØê±*Ý!ÖaqgH*øBßmØ^Áܶ+‹ü{ãûaGr —hI‹ª`”6˜ã™6à€ÌuNf(W^›~ÄJìÛðê·à^‘‘‹¡´»ÛI@ðr‘þÀBOø}Xø`Š 4[žÍj·Œ†ÔÉU¹ãÏ+´úêv‹Þ“UûŒ×¾g"x̰ DÇúµ¨‹çzYª2Zâ0iU&ó™CäóÇ{xV’kÞöWé»Ð,c¿Ê6ÕW÷Í$:T¡Ÿjè^¿p¸L(ÛÅ2Rùùjx”¶O¢•Ù›ð¾úÊêµ°ïØ¶Ø-1¤ü¨”Aë:«ÄÃ$“¦ÕõØõL?~µ÷ŽyõFUPJû^2x(ë³> qsÌÐÑ˶I¼C·Æäî_ÞLcr[ïÛ¦ë—ÇùôsÐ8꿺-ýuÉ£<æ-ë­m§¡¬KÃö:Fy4 3¢Ý•O5‡•×ecù¤R {¯Â¯µgÊ,°ÌX=?Åö-Oà7 MIcýÖ•‚ñÛ—âÊ·aŒB3ëIÕ,­¥2 ,)¿èïY2=Òìâó¨TÕ\“Fq»`Uìз}6+m;½û6AèÞÂĹ·*Ò"T«Ý¦˜óz'п2ß!büþhÂÀM£ˆ*?`©\H¯"\ð<<œO’Œåؼ·Ïë(`óÕ©,ºK0º¾·à –Úiw`šÁº¢IÈâz/Wžû»˜_;«uzÓ=àœjâ7×ê âyì°«€ ¬÷E“G¿yùU6ª+áá^ß…:"ÑX•ÈÞ~¨"8à€úv­¾„‹dŸ·”µ8ŒUþºðÌ^%§þlÙX#°ï“`»Â²öþS ßþÊëüK¾ÂLk/ ™”“O ýŒ$ôH÷7ϪF³ g`Ùf¦ÚÑ'¹x§¸..P™½ŸTƵè¼,7¹zëh3°”層­ÏÌô'*ë%]ŸÜ^ÍdºÌB ½d›ÏGÿY¦D“~ú“ÑÝNî2 áœ6ÒÝÛᮎ{â3ëâVCQ3,üvðžrÓ¹™”™4ÔF2¢Çˆ»ÄQX ±ïÜK&5 ¹m¤U‘l!fƒ)(XkÎIü úžÎÑ3zRÌ=yÃN+!“Þ!¨0àÝ—M¦ŠÃ!òO“çŽ`1»Ñ ª„\ /Mr‹M ™lÐ%UŸ. ˆèÖ› ]á[­ KãÀ–nØ,Ô‰ø‚L~¡‹îÝõ†;'£E¼t-ÌwGjp©,¢­IÈù&™ÄÌ7Â®ÔæIšCû -‹¿ ë$‘¡ß¹%Cêc™†A š ÄÚ⟩ Êü†Oá?Z2¥äJ’v}~7âóü—ý”°Kœ(Û1K§çÎò :¯öø±Lž$îgC:$Œaã¿'÷¢>EÏ`|€³Ý´y×G0á¹R²—¨g%¹ŒWÝߊÑéO´„ÚcÖ5”K ¾ ätҎߪ¥ fb2q˜ŸÆtÔäú#¼SfW ‚$cüŽúÓò.Ì2ùúWØh¥â%û?ÿçM§*Á¤ðc>à ̕ŸbýJÿU8N–C1Û×ô'Ø»È/Z[ö+g£SáÈ>Ì“ŽoqÁE—'èÒTŠCFe¹Ò¤w³´Ô±õ‚Eå¼ð }­PuPÀw›Á ¹’çŵeiø°Ð&ᥠ¼~¬U$_Âý²¦†› Õ›^ˆe51~¸ˆwÊuD‹óóh##«X¡ðØë´aŽgj:Ã_Ôi9Î7ã.Õ¯I¿tìG]…«ÖQ1Ý¢Dá²> _zŒÅ÷Š«po+i©8¬ÌbçÓÒ–”¿ú"â ‚ÀŽ!¥ö\/È'†Lᖯƀ„j÷&<0^ìDZ*4ÞúЂ¤z “'^¤Üo©;ù¹Otò§Kí[¡CÂYT.ÿ nl^^¡ÒLx·ÄIÈs"˜ÝêÔxVª©ùñ“Wœx•Êôé-Th ‰* ª§é»²R†ä ÁÞ&¸óU¾œc¡À$«“+Y·üJ²0ôò¼*‹,¬Â4LFùN‹]qÔ9¯*,°XIÌÕT¡µfUòg„íŒx÷d ?ÈW¥}νÐ=¤E–ëc͸àסFÂ}æ(Û .„#7L(ø*¸¦ôîÑô*‹sq¯ùö…/>Ú?²óXÎQ|$ãfmïí ##íbãÉ™Áûãl5 9ìRü}…Ì2­™ÐŸ2¨¦†>2ð¶V|`1A´ÙªÈ ñºç’Í*ZÂÕQB1ŸroÞ_—ظ'äÚ|/bå2T…"œ Ñ`†.]çHÅ ®V&®áFˆ¥Ré m^\lí Ö¼Øp0ÍŒ8á`«Ëª9Ó[Šý*Âææh[ˆü–TzO·£­f@fµ¶”Ÿu«b€FDðDiBsöŠu•1?éÕky?¢D\/ÈiCpÕY I™qõ„&ðì(]^¬Iœz–já©VTž÷ƒFÁ6"ƒ ³—ÌBa éü™Sý«„‡öìì±DWSR‚Fa»µ’FÜÙ„<›ç5(.´×`‘“Öµ«â{cߊŸw Ñ伜¤•&‚ÐÓÔX&íÒ,”̘–îkÆÿ‘¼´ä!êÇ. 7_$9/ßoÖz(|è¬o[GjkyF&ϸX¥d14ümú>#<ø'ºÝrJ÷¶upÚ©­ßÌì…ñÝjÂ]›-0v”L 9 )$¤x'0VƒÇJeÍšg}%¥çÓœ¶õÒø•v~;´@ý[Ö_1âÝÖ \Ÿ¦IBv8mu#ïÝ+DéµÖª¼­?€WÒŽlÛMµxp‰Àõê©Jè™Ì*‰Ò9o:fï÷vù¹dõgÅ–l«”oÙ÷X¡JÉŽ–FSç8Ú…à,ÖQN鼩{ÚP'ÓÅ9_ÿ}Ü&´Ž­÷Xû!c Z$å×ó[ˆˆ•ÇCÝ‹nÜi€¥J‹‚Û”æ·*îk•®h ¾¡)óŸËÂ9ÖñšuKe¿_4&}y?npéeâ~ …wY|™0ƒy‰¼Vñ<âû/IÚT3Ì—S½ Ôª«_p<áé´M:d™5J>ãå?v¢Ä€oRªuò­¯MÅÉÍëÙ)&ùG _¹kðö›¸çÓ ÑùÜ®s2®G•‚> mCZ;M0K×tª9×dëñ2Ÿ–…öý a•Òð§(k0Äï:c&8¸Ñ '"‹±ì‘MÚëé6©. Ö3Í¥ŸfoÐ@bˆÌÚXŒpgµ;s¬Á{£ØËóú„~³ŒL’Œt£#_4“öSÄ5Vë €’SóÆÄ”ŸÅ±ÔÎWCÄÜZŽë_CNd,|Vu;°meõr e/ÏeëìöÁ%×ãÈz”#cÊ««€ýÏtE¬¯°B²¦˜fõPFLÓïÇ[tàÓpL˜ÊNÒ¸[¼qÍBÉYŽ”wod–h‹äcNµòþ^h,ÝUÕfÌ U·ë-ò¨ ”º¿Õ£úàW¥†ñsÔ‚— ]Ü‹ YÛ•>Ûâ›Dü“‚¶§’ÿu÷£|DË¥-û¶á]1y»±¿Šzó)áZØ…CJ $;U Ì2ÖÎÞ#°å¢dçtðË?¸QÐþ%ôó-[o°ÄšÔÑ/ůÍìj8}ÂyŽŒe-Ñ ’Ø{ú‡ÊŽC]jð È¢#w”Õ†š§À>­B±y‰wè)™«td‡áŽu£R¶©eVŽjS>]Õ¡H ü\³Kï[†¯ú‚¢–^x3¶\I¯\»¢¯ë²Ì3€A¬ÝJ{µ zûÉó=Ë匃¨:§^IUõÀtv9öpMÓePž{1g9ë"–!¹Á¯ð‘¿[Œ"[Áy ã-Ocrxd!äï[éÆNòH–§MpWþ³·ù¶#%Xȶ¿œU0îŒ ðƒ`žQ>{sVØ&AwxÊò7¬ÿÝógVÎ&¡ þŽ­Ô‡ÖœÌIóÊžÐD@Š&9»¢\µѪ¢…+RøZPiözÆ,jH«§‚ç+çð;C,=¦¥Ó´¤9J.®ˆ.ÿb$ʧuÀ ZÜÄú5XÜÎ V™&·Ú ~¯NnoÅÁÐ Œþnn:ÉÝžõ×uX¸-¼ÂáFÇ]}&ß}g#é y+ZøUãOÐÍ%³Ó§åÎâB„+«Ô> Ðî—"†çRº yä?0WËœkyj]^“1÷EèDª4;ry5=¡alÅùwÒO7øhç;ˆì©[ð­hcà F·Áñ^‘„·&GòX—¦éSq@F­Ë´¹}Ī\–M46ííMDÀBî¢s¸Ò©"¹2!ºµ°bü?kÌÓ,Ö%c”¿5þýSæÝIRo‘¾sÁÆ)oÙ]#å¤Íú‚€Iè‰xÜ?øëèD¯Òæ½ÁO“‘s-°>ä‘*ÿŒ]ýÞ,]jU%â0™Ä°á®æ’Ëùf5üènùŽAËð«á}ÿX¼³ëÍ×=ø«YÌjЉPSë®TÄzÞKiR {VPyüÖµr3Ü-Pªd¦f1³ÿ@í¿ç¾Õ‰<Ò´«ãtöÞÿ ÃlKc‹q÷1OUøH†Ó$Ј֎¬£Ò£ôµ~Ù«0iè s-=Ø·0™›Gü÷MÔ[d ©§MPàÐ)¥ï=<ŸÎ!I°V.=T•·(ÌÛ-ÛÄíÊzþÚBb4Våwج=#š–œøÑ­Ž­qS¨Žõ÷±xÈΡL~²ùk{÷ÕbìCe˜V6ƒ²ZMŸ»’¡Ï‡µÅ¶vUeyèg†p¦.î ·Ÿ$¡{*'Yëözˆ—"òû´®¬<}պ̲ ÜG Bÿ½4ÝϹª{z¬‚Ø‘þÓ1Μ°tÜmþÁew SMáë:tÇž‰>1B#Ù:i pÑ\a¯3‹ŸþÓ›ü{ò*«öW†? ‡)•[‡rù c˜:´ï3Ų•Aøâ,6í´¼X7Q?•C·›¤®ùdM6¥C}·ùX×C¤VDòyàŽ;Ü#·$:œdÇq@±¾îÑá‚1È æU±—­0œBíRΙ)ß…¥Ueõœ¥Œ6 ÞŸ×ax>8[~KÑ33Ðd°Ý¾`N·¾H„ÀÇÐßghêIcF ÙÄ Ð²Á‰é 3 |nrk ˆ½ Þ …°ú5Á\µwS“¦éèEOf–èD¡CÆ6qÊ„cQu=&sÙžºhÕ^PÑþ‡Ür„+ãÞÑYRd¸¼Ý§—Ï{" øŽ÷æÙÆEÐ ^5–A¬¯é3©šÿ¦6鬼¦±Š…‡:SoÔ“±¥ß@“Ч”@æ]4L³ú’ »½äðÀH™ædÀÅb#hP3Gª,ÛÈk\­k$K×›‚&P(Ôl åt³¬=(Mâ–ªàC\Lk¬âÌ>Sw-n³¨Yœè)ä þa†©.´9hâ ^»JÈãoè’ –Ú9O2öý-BDt‰dÊÎó†lä¸;e'ç;áÓCä¦J]¢¤/Ü®Jˆ/,¦Ñ’M ‘ÉôKH^Ö}¼„ˆ’}ûìÉ¢%xŽS{¦Œ‘áy}¸]ïKbñukXÕfH=éµí5;*GÖ…!­ÇÀiÄkF_ñÑdIðˆ½wuá<ýt‚Ø,çÎ]”'ÙQ&Yšýtä>AΚFšÔT×µºÀ«“So | Záþ˜æ æ½ùLÛæo”KOsœŒnמeG¶>H8Áß§âÖG¥÷“…0ªÊ“¹ŽÞbÌGz™mëU.]‹ Ÿÿµ×6ø]xš§Ç|”rThF+û\!²¼ÅZœ2ôÅœ\¥óšHgdM2ÐÙ4bèØöñÇó¸‚rn¾…êyu¥Œ}!:ãJNݵh½–ÿf';i"ÖméKï^„ <“þ`“S^{̸\¥+6ß‘…‡wkmN„(Ënòž/á“érü¿Ý0´Í¤³¶,'ÚÕ®ûÈæ½oI¾cj$³‹yÆÁúJÁ¨ú©Lxš‚c)`%ꊟ3ÕTç@"œÂ÷ķޱÉgoe›¸«°Í›Oº;<‚gyN$BK }è/—H?ÒDîiS†]E[*ÛZpßÛ?Ö_yŠz²µAß¼`äo=²)Ú°i÷æÇç¶L³mð¹tãŠÈKï6Y|â UÈ¡}ܹBÖŸêx²6‰&”gãíùs¤ºb RøâüPPµðÁ’4 Õ "Õ5ú@ÔjÝÛ“º57ˆAÏ_Øàì>ÄÌGUý‚èòf•ÂGºXµÅÞ†ÆÒã¨2Cö‡‰’àÿ<‚ñIh³w͈;ÝÉu¾^£ÃãÑöº‰C¶³òbmªÚ&ÉÚÕt[Uu¹‰–¦lö±@p¾ðT/ûôAB>Ê£Œ²/Ø+%·ø‹gÛ¹Vª?¹™Í*3Åñ«@Qî;›à*$¬KÁPr•9ÚQè^SU¼³y»;‰XÐ’þc¡c¤]­‘ÓžÑÔWœ÷ˆÿÐ̓ãC ¨¡“I<5-LŠrŒ•îGÑ8™cÄû§#0_¢æpïüø«;ÅŠ°yÔˆfMøÖyãr1t I#¬Ž xa÷Q2þ×y‰¡ûÉ)B0®H ›¿%ÕˆÙÁx> þq.pÓ$óZmÇæM“n\…‹°Me XÆÍз™quq<Þrúë·æ±c½õ1[hv󄇈tOý¨4Z¾*€:RÎ\+{† éL#&O†‘Å©¶Ñ´G6ü‘Yþ¹l•LÔhlò^ä¶þ3€ÍºóYØÙÕæÙ9©|šIÝ¡ä[¯ZÌ;öƒ&Zk¥Î¦Ï·"–cvp´ëªs:¤‡é»·9K–ú@\k÷lÃ~Z €±ÎÚèfœ°Ñ7Þ¨ýÇP*uî…l'Fˆdè3‘e,d#j–Ó‘§‡ /ëRÊ–¦ëDq² q27&Åióé•Ü„&{{f§ªÏT œ‘QZÈèˆo„D ¿v-v]oþ&?Ý’­Ü#nt•"ßH½ k§,Ü>TdzöO6¼íæ3¢º/Ð|œlÏ/0Z»ŸbÉÃör‚°!kýÀ”£½¤®jÄs¶ägÂ*T¢Ëdˆ‰hµ…Ú¤ûýÙA>AiBݼÿ—@ÆÎŠ]۱Я>ÿ¡îõÕe뛆^Û‹R¼b”\fÓé›Í¢X9Oqý¶¨¥¤|¥‘ÀI’ù·‰MÕ÷ú+oSêm˧ ß»c9iÒÚåaÕÜU}ƒjqáQÂà¤0qå°ý„¥)ŒˆX÷û!Ëþ×£ÆÙ@ú)!Rðã 8â°ôRâмǼ”„ÅVË%< …ÏG¸)ã½!º×*ÑÕ\ƒJ½5LÙÀð;oõª«óHŠ™ÄÄm̰iÝÍ®ÚÅÏüV¬˜Ã JCC;Ý…Ð {ù9PøœÒCÃÚr£ÞÓè:³ ùö6i°Ã!3Èúk¼ø˜CUB&¸¥(O…Îõ;m¨’%ÍîÊ’ÿŠÚè¡qkÍÀ8ù< ™ÞÜùw@Ôy§u¨UÁÞ™¥ãc“¸#ìœõB,p%ѳ)#,öϘW $íI¾ÍˆÀ€»Nhõ‰Ö°)´úz•Æ ÚÂZ6t¬tBî©\h³OÌ»qycé0Ã{­0TýÖ¯u…ѵV]èßú"Žõöq ÿ`îPX;ãJ¦{uDÈ—yûÒLjBž=®,E#$9“ôØsÜȰ )M¥­(?mQörŒÆ…æ:ŸÜ\ ›ÿšG¢ƒ@'V(—l~ky‘{€sé¼–‡mCN²î/R‚‚Mbï˦òK˜ó° éÍ" ×!àÞ ¶¸ ºÙ…§ÃW­ôk¹$}W*̤ƒé‚mˆ2bzä£êÝ•+™‚f¥ÖÆn´pä­ÌfBòR¾í›P ”'Ttš¾{î -|ÌîF¾õ,M¥öÝd'ñ60î]HÜ%ç`E·*k*cÈVé&óÀ7û6“ VØ0@Iå<¿8äX]¨¿£¯+l’ð—2 qY¶×Á1ðdÆ:ÉþÊ…öÖë€äÅ Ët¿Zë¾e^0V4e žÁ uD%Á@$Pã’:’E2C~ÊhBÃÄ×(O¿¦AÒù(Ëàå¾a›ÄU ?\™rå½?_N˽,SéØÊfê{ºsØ–ÚJ$ Ç—”mf£e0å<ÖØ‘ù ²hìX…—Š'š|7OEk £6 Ù›*/tÒù"d8n7ÇÇ q{ôa\A°''ÒŠ‚¥á‘ìoÚú5«?7Iõ«N‚Íq=oÞÓWä£R•Ò“r¯ )aGL¥Ì9®¤¢õ*E‡v©jΞ¹ÿ‚Ú7>kqBÁ=)È͘{õ¡Ôé—òXnøñ°u5]‡‡uaç‚ùÑ}îs9üÓ½Qsdª6^ÃË?§È޳/[AÃ2 nØEg‰D£:nA=TŽJ‚•Ògø”¥¥5¸ìOã!ô=²ñ§&W¨û(‰lÛЩA ,Êåì­¿¿£’uèhÇÒ†ÓÈ>ð“ÀìN´0mpFh&ÊùrÒzïI®êO–NI‡½5r#$K°ý°þý³]ôƒïƒ9iÐéÊjUsYè®ã&ãŠw΋qhJ?}gòŒ‹¶§ý{Ehaº”„v*á®ÇH®y}‘íÝFh…I‰pBÞTÔ§³mߨ~zµ +—‘c‚§Á6 E¬ï·Y ðÇÈöNÈŠåBçP,óf«EÆ/S2v¼qoc!é› Z‚b5±={?(AèµØc ¸~¨Å÷‹Œ(¯ÓsA'y>eá`÷÷ì8vÆg³³+*ŽÑ>s’Žs•O¼B~æjËìñù5²ì¤j¶ù®®&çM—¼y7¯äO<¬Yu£Øcö§’&{;fY#Q­á;Xow¬9Ì›h¹f°˜“Uu8ïŒ!XâŸïOmÇÄ“º;,›bHŒ—öãüÒe]1:s59?{¦°¿Ï„q¥èÌú×€]«ÏQ/RaAã-ça‰ζފó¼åŽÞ/-T€ Ñá=SÒ§âm©Îqè„ãL¹€šÂÎÕÒ)¡N­(¹›v3u.Kw:ˆä¡™¸òc&zU€œêò:t)æ¿ßC„m?ùôN„œ½ßsðCCMZÛFêkg,<¾ÔèûA£CÞg­ì\F–‰¼Þy¶a‰[|±Æ$Ÿxå ^Íï¶.ص‘T©}zщE¸7"Ô×T³‚È)à¬W}KSVv‘Æ€æT$rnòGk†ü₸”Pï}ç_Ÿv1e ‘ìÜIÒ T ­ZÕü^Wù¸«âK¶ÌÌ'´ß6XÁĺ@¾¢œƒy; bÖÕ Ý0ü€¼4)ùŸ‡iUÀÇ5–Œ\—Êgêù ßßææ}»èü>ûØgV2GÙåDŸ·N;ou¤›ewúNP$þÇØßÈYEn`HÊâ¥p¶zëVo‰ÉÖß¹ua =mîÝO’¨}ÕY⪃õZ‘Ìnîkçgã•`¸Ÿëù$?oYÁáCûM lÇ<§e›¹Êž^vc|eH2–±_ôÚWcÚîÒƒ?Ö{“ùBç6³oU ~Gžè&L*›ÈæZ¥Î³”ôQOšù®£‚¦Cõt‰p顆åzp!ßFö›„möQoÀt·BhÜy ;U/M+x»ƒ+Ågôa߇ßx¬1–QïܺîöæC !ýIðäaÔpM&fûÆjZ¾þ£äŸP©Z¾v¿Þñ_^Ÿ¦3¿C‡µk‹—¦¥+ø@ýhIPd£wiÈÀÙÕm°®h¹P|ü(Ž2¾p5ÁqÉÄkÀÊŸ36-˜|%Û5}”8[ µßœÛþö ·™} w>añ*7¯ó\]Å‚Ò\‚«çåWjj”ûèaŽQ?Ì"WWx ÿ3=&‚72¦5(µüˆÍÉe‰$C JÊ‹‹î²X‹6h‚èÄÕ¥ž™{ëã}–¾¿RLkPàälRþŒvÌ–8€Îú5uLþƒxÝ`CÊ=Æpí•0K‘£× š® Y¾›Mÿ)£;`‰:IÑÙ̯wåuKŠ•ÈaTf5˜O§tH>x%Nžèçc[èÚ5$mÉ~è}8Ý7Zoòj‹ýJÍjܼž"÷*˜ýËÛΤ÷ŸZJÿ£íð–mJV ¡”B„¦òñ#åKàücüyÔÀœi~ÂmØœžçò¥¯’"á䧬ß%)áð|°K@ éXüLf4ov 4jµ4–ÖŸJìÒ~”ƒD'ž(&"ú©Q¼ˆ'ýß.>­ÍÕg ÓòªXÚ0M¥SÖÀÉjv¬V{|D‘"ÈÚ‰#Œv¼KLpâ:Ùªíb-¶ ÿ eE0ÿ<¹KâϤbðê{­èLw[ó)BýbÝ ‰Mó?®j\%Ž€R  l`výK¹‚‡ü¤2¿L =ZɬKåMY~v&Ç=¾~ns•LHFP€˜¦9j/O&ŸÊ-…Ð6|ºï¶‰ÂtÓÓR*õ±¼ï·y`!Ç|˜FÌ ÷Oe)Piïðó·T¸ã3ÿ%ÅÆJJ8ŽM±¹yû,àtû-ûŽ”•9b)‰ØƒßÎ(ZÝÒ?j*5ÙcE±/F½FÒé.nÕV<ÒÓ2‚SþBr"»`l¤­«a©ëñ…À«±·åÇô¶.‡æž ›é¬Ùo˜Ò«mb ÉO’ÇÂH«’ï;Uuß®§e£j/·ymlñR˜–3~6㺷ùRçÞŠ©--Õ“{w(œÑ™ExÔ»9©9p²²(†‰3½ry~¿ bZjè„£GJò YûîhP¢‚gŽ&påÇ–žwž!JÊ+ð_qØÄ +@¯¬BWÌ*”ƒ‘pyþÉ\+š¬Ó‹Î †Ja£ÛÁB~<²¯ ˆ˜ö7fh ŒñvyÓP6å Œ^6ûx5$½N‡z9˜ÁMxeÁ“3N)¼³ŸÞ©¢oƒlqšó!EúØÈ]9Ð]ü¼²y¬Ö$Ïàòœ*ñ•ÛÉ#rùDѸ ­ùÐ8\Éï–ƒSFûÄÍ[‘²P•zþ7.¨Ýd{•1Msë9QŽé~‡¥ —XRU¬9iÌ´Ý’ëDü­‡ žLKDZ~yô·ÃÐR‡î:ЭÍÐ¥A¦Ÿñ—¢å}ê"Ìòa%·Ç¨dÚiÝœ}m˸ƒñmŒ;ç6«‚£àœI ;·T¸áÆÐeŸžgÊOw&ª j˜ MÜÎT ôôè`~3A®„,,?#rªEÎhuߢ*‚%%î»E켩åWµj`Ñžþ×Ö[Î:MbŒ¡=†°Ú/ø:<­Ea°©‹U EEÖÍ0ÞPýÀqQr8P‹¤ÅÐÿy*ÄW2f¥–¸†D‰ipó¸’(‡éxºƒ™-Ù”P ü#‘8TÇ#ø îJG›[ñºhˆÅ‹…È•v~~šA8=c{#§Š_®„Á†2g&÷*ÑÅo^òiòrN´¨åECÊ›úÄ!~‡ôœ©Û8ÝŒ™æg ï)/ t:¦¢üæ×ééºþž®s¨>ÉÁüÔ-ÎZ&˜(]A)ôaiÙ¡QÆä)¨p–¸%Z¤ľŒdz¤Õ/Ûð3Í—?\5T: Ç ÒéÄA*«2kQ7º‘Ab³{ÑÖïB5Ìò¥ËxøMì‚ä X°øÌd%Å7šMž3l1„å™­"”>E®LzŽðˆrÇ{ pÁ*{ÕÖ<÷5Þ5®¬Pi%üЈêM“®^QkðQú ±æ,íÞF‰ïê­]½ÐMØ-V<Õ^̸ò0`wƒÌV>b[*Ù<‘\ÑßW¢‰ûg5gø*¥Zù'ð–>¾%ŒèìTÿŸÓ¼4@ +ð’ÀH„ÕHìi¼ý- ‹Ú£dL'g?@à*µ!?¹<{µEü¼•|U›8 )ÈÛ"@IŠ<ÍH#X¦†Y©º‚^Óöºœ…˜å-vJúóÚýïß¾ +“WX½‚uŽeòVm´ƒ<ö·ÙôŠ—¶C4¤ÁÔ{Žé&ŠGÍåÁ¡©†jÍ|Í*±m—péÖ}IgÓ‰x¥”£íQ/kÿÄ+Ìú÷ØÊÒ‡E‚<êˆ0ÑÔ–)‰hÖòƒ®×žLJ¯|ÐsÞ”¦ÈoQø4,M¥]%“8F”ÚMзqÝù•fXWöì/¾v %Oîô»Û/|B`6UÝ*œA<”ÕàœÙ5jnv™!ð¤Õ|¥MòyYíIЩs¥z/v¸•A\x>í¶mb ÉO’ÇÂF!y>Ú 'r°y1JØç1ëíŠgX3roˆÁçÀ"4øÞ܈Åá•Êx|Óc’c%ðf¥=KöÁq›(ø«¡®"ÜÞ™ï}ñÊc¹3>oøôBÝÄLÿÙŠ:µß ë¿£gPYÏFÅü^Tóöaâ´Ås’~`O‰ ²_ë…„¢+¸ÚýÓ·ÝçJl™òF´jæYgPà ?ªN~=|$ÅRM©¯HëBÍ„ûwCµ÷>ÜÈì–zEµ,Ö«3=•¸{©Ò ˆô1pŸ7aä· ¬T¯_)Ž‹Ë™ÿÚ$Ñé“”˜u¡¨c+¸Åž Ù}¿§ˆœù8™dJ¿ihœ+cßȺ€M¥é¯4:}ò¼µÚ =@ÉÃah ?ÿK¿ëîÈ­ëù¯ ¸æ¾ñ{ôók6X@9ìž0ŸßÍ}^&!rJ¹d2¸KYoužD~ÛÀÐ'î%ZÝcñãÚ Ëˆ¼ÚC¾ÇñÏñ”à‚t÷ç6¸È5WMZßø¹Œ-l É‹¡gZ²|¾Uè ¼NØÏ¡fLúyb ² ƒ#§þŸÄK~bV5jÜ@ž[2¼˜Nå5ß%§7±æ4î〚åpÑ“Í^TŠˆ²bsbr8÷ؼÎGX8a‰q@^û†ÀdrK©ßô €ka(ã¢àP%Ü©Üh2Zj%]òÊ—Ö†.?pTQÀóä²L1h¸²Àop%4ù?±LzÍmàßà3Ž6:³åµ­™ ÚUhn·fEóþ)‹z !.Í?öÜûš`}Ë·½)ÅÚñÊ×ïR‚ó'¬ce¸U’Çv÷ÔL”²UÚÆ£øã”œh97äû‡Û&K¶Ð£1aéà bŒC€øÏ¸Çfëð¨ü%%I 4òïK|»@Ph˜m¼¡¹ú§ÕªáÌ|T×Ô”˜ô}Ä’œù~Zˆ†©Âõw¦~{™÷û5÷»¸ØÐ5dT¥Ñ:‚ý„¤ҳ\&E9¨mþið&E!I™.¯S6‡ôÕU•6÷ ¨cŸãšM þó×Úùã’[­{-r¥^<__x¥Í"qöŒnáDT0/¸<—k†”>þæ’9 މ9«møÂ ÷Ï[þ¡ý%*tI ¾æB‚j´¨„£Ä”™MãºlÐØD,Z÷¾ìrlÚtìÅ2.ÓÇE›Ø¢Ø#~õÛÞZ3ë=›O.#™ †œÙûâíôéMV:I¯ÁMsXDxt~±ÌOhK z%&wKP³òzx|ç³4UÝÄ—ÐWã~#û‰7§ªÄ`¦Ô㙞øy}_GQe/GŠÕló'¹¿»Ú³O0 ¥·êdV J˜np@æˆgF– |³O×ýÇ­â’Yªª‹”ux¥HsñϘQ³-¤ê–jrrÃËÅ„m½»¼‘ïSŠW6Sùæ½Sõܧ÷ÕCß>Ú ]‹Oð+é)˜R,‘ªGÓ 0P—üƒíÍÏ<ÚEiQè–.±]·©++Ã!Ò`!sÃI?.®æjîF,e q•b¾è_Œ=Yê{ÛË¡S1ËÉIÔà K¸IGPra‰1Ãé¬ä$+ÊuGtžŒ3ÃNV¸`=sK~-&½ëìô¿è{kRQC¼¸ôJ1o¡Ý€–K[[8,7+\û¤Ø­þunŒF›ÅN_ÐÚn^µQJ¦!·ãü9Mn=jºN²D¹¢ e¥c ,·Ífw¤¨žŽ¤”;”µ`ûñ•QBusÃnÒŒÓQN.-0جèKM›ÎÎËú²¡O‹e½h6ò£ÃÎïÛ"pÁKP\ÜÔ5MŽj©@Ñ+Ãσ¶â¨(THwk«õ¸êpPñpe¢JY=ÍêªxǪ·Å°Zʸb ëåÏV‘;œpF×›<+æÑ µ>QÒ¢õ@ñÕüÔ|°™R¿F³m\ò ß|Å€Æ/Ám€T…ФxÀèÕ³  €ïЈDÖ' Òg/ç ,O7–”íÕĪl€åæP¬NƒHG±ùÀߥDY0›z#ÝÕíQ¾L4Ž·Ó'°ï^¹»o‚ Ìå‘°¾ Žü4ʺrþý¢)o©Hp¨å`´&˜ öOn€µÑZ‡Ö¢ÿÖRÄ‚9^sFn­ MÞàÐ÷Þg¥ñ4ò±Ÿš ¼êv2–öLv›n-Ü iòæÿBÿ´bœºïO@©ŒPêf’Ù˜ôܽÚó?~í§ß¸jó.j‚¡µÎÜ?#-ƈѤo?ÀIz>#Y‹Ôq)Mëfƒð€>3á:¨__F²ºšDb)ÏFJ°·¼Î2þójù–ó-Ñþ‹$ž3'–7’¼ôvàr…X˜ˆB¬çÚ¨õo4<'Ö¥·üV5&xJkc à…~d”ƒÂ˜¶u¬âÛ‹ÂKG–=[«‡aiÚH¹½Á>¿sÆÆ²¢ú”›Í‡[•ÄG®`ñ!Ì‹bH]×›u¾‹ùk5”ωŸ“b—ˆ»MÎŒÀ×._‹2Yt"1˜ 00üåu¡BäàÑCÿdÈå#.²ói=O9´HÛþ5i\}SÛÕ—`s¥1'ây\àZÔ¤ÂuiäER2¼Ýió#•Á\ÞžÁÔãìþÉ,¯»_nöèC' ™*²,rr%9ˆëS¥Ê …"ù³qQ&ƒùeº‰˜ß¼‘âüS‡aôÃ÷K½:¡¼NZÁ†[4s¡õA"Ãik "%ŽVCŽC¾éx[Å{g}…ØŸùû2Fxÿ©X# À=1x×jK)n´í³²“Ý”Úè)ò¶¸žzoˆË©ÓÌM#­‘Š3 1ᛀb´¡!›(0£@;®(‘Î1>IVµÒ¿Ö~›ý<`+.Ë #Õd$‡YÅÁ½LchpÎyZ¨0FNpæ°*Ç:AÁ—Åñ;î?Â7-Xïôç1ªÃ3é‰C»ž>‚ ¥6i±ÌkÜØU¡(.Ph ,³0ÂOÅß8˜ ôwÓï‰ÖWîÌËSÄ684ç)—t^.w\z¹*@íå¼ Ó `«Á±›òš- È7€0Káó¥·KJHaâyPŠÙ´ë˜Á¼ikÇgÍÎ[ŒÑÔKEó^•xÕÀ\©w‚FYDZviN¢]|¤TZÇ?ª~I¢fk·+)Áî|±˜÷ƒW$- ™ÙëîËEÂô]x­„|,s¥BYµ 2`¿Uµ°ÝŠý‚š ‡Í‡g^xÞWà?õz]f^ôK´§ÝÛÐà^Xç05§pólStÔVÑ 7,GÚôó’ÇXÞ«¦:2}Húãòüíqáj‡Û°^#å`Á·cj¾4š°È³cÅÁ_tøÂšñëÁœ÷« ÄÇáD‘ï· Y¤ØIôèæŠ§K§µkÿjê·ÑÛÙ°‹Æ#˳o)R“{Ê €´Ò×ó½7Ì<óõ” 5ÁaDh¬¬ÞÔ3?jžÌ 2î•¶öœ<1©°"oùߌó®ÈLMRÏ?˜kAµsCüM.…*Æc© ƒ0\€ÑëªÎWÑb¤G>áÓ)Ò”ùB;~ó”öú=#²,­ˆC¤Œ^ËyLê~Ùñp·Õª¼¸Š ¤"Û^ƒé¶Át·Ð”"`sµ˜]É­û ž˜ÿˆÀÑ@WÓ2k#LœÃ­‘%@Ók²þJY„‹©©°~É&€}; Åõ¹ØôpËÞ ñÃKx$eŒS„ÄA=wTtº”•µ¯Äâ|ÙúØ3}jÑR‰5…kñµC<™±¹s(q›qí×XÇWƒFrÁ¼ûµ}Ç©@јë q9Ç‘ç¥ô›8‡IäštÒRÆŠ¼LAŸÐK Ió;*=G+ S–²cúû[éÊzKgé² ¶h Rx ìÖÅNÕ­çw2IpFÌém!¶kí)R¸™3ŸÜBrPµÊK³áq;Ö4q¨ÈdE ˜Z#ÜááY˜)”`Á€»›[߯¹/@œºþ£M H·upñ5™Uä§0"YX¦æ3 ‹F_Dëû(\¹Ñ@ ˜Ñ·21b®t„”ŽƒO )ù†_Ówà­p‰á®ÙR_§U‹Ø¼ýWý } Pþ†uSìE6€w^NÎ^Ͳ‘›ñÜ?ž2Oú3†¿]|ÇÄXÿ§€[¥ Aø÷š1æþ§úh›¨×:,Q·`c^–õ”èµ~Âtd£|\Üè35b bz/+«çèùņt;^kâ-[e}g60wtí™ç*.g,Q=ÜH Uö¡Vs"î»ãÎàhhªšþ”"' …#™½&£CaMLBxËÖÜ!SóòÒÇM´á"m¿4܈d›°ð‰‘Þeä“—¡“¿À~•ßTeiZ€O)—jðø'âhºu3vö4“¹÷wl¼ÊÓYoH3(…žq¢oXNQ!¦JL茅oÍ6sÆš>ZVˆ»·˜^)¼ŽO"êDl=ù^Ð…}î=ý³Ž¢=¤õèu9[ö¼qAwR˜ ÐÔ—8 J | êïEum$ñv`=BóaϨcJÍppG=%§ܰÚêºÓ‚=ÞÆ/%3¤×í¹ú÷"‡^^iÝ­ß®ÜÍ[«½p “9U¾]D9|)Ä:I?ù95^_<ÕþoÜÃpzõSõ\.l<Ó¤(ýÅ ¨Âm] /[09m\»;À&x¯Ð„°á]Y —FwôK¡f ×Ä/bÏpõ쎎k”½Æ0¼¢D3 iÒÆïì¨SÇë"ˆ‰›nÉvóœù‡!{·¤Ô?m m;‚n²Ò ‰.¢‡GõßÂ}Á;ré*Š[2ãYïüoä.üƒµ ÀÀ«³s£ ŒÉ´€ÚDÂDƒÆ,¡þ«éSê „R\·Òî…â v¼}Zcüq‚‘¿ª¨Ž>m᦭;Wá4~¹œÔ™µE¹Š§˜a[7ª`PyW÷K²ékŠ¤Âµgö6ßÔ ßYüo$qœ‰ÞÉ‹;Xzwwš;T‹B/Eïq:¸Ä•£2½ÌÙÄÁU«dxµUÄåðl#›®ÏWó™sz¤Çî8³{Z6¼î(úؘ¹ý™•ºÙÎÅ¥K«^ã¡)º¡Ï_˜«kÚÔöpzF0øáˆüi’v³˜ã½ îM&ƒ†çPÚª“éƒoýÇÒ;²yŒ‰ÛIR¡oƒs»0ÙŒ(kD;‡ W~p<Êkéý£è°hª“OYzÐõrœ¼ýEƒ‚9¢í\ñé¡ÊjÌÜ+Ö×Çt`Ÿ^t¬@4aÝÓ¹Oê ØUȪÜÃc“i3¤Æ:UEaSºYn¾;™±(>ãêüC±ó$àý¯ Ðx~rŸñ ˆàŒîkrfFU¯ÿ‡²Ê}ßÎV ¾y1ÒÉ0nžŠPBX,½+(A´=:->¥ˆ“-Ç}Á^âWûX@éžÕ*\9l#uꄱ¦— ˜Þ¹”FWÍ¥(° øˆõÁg¦fX?22¾t€îð3¨1÷ZbôK®è˜Y¹½  eÇœÊ3ô¾ÁS“Û3~*W<¾“’«ž#zÓkjë“X޼à(C-ÎÀ®½ lÞûÞýS;&Þ *™Ò¢CØoz"ëÅæëz²B}oã}h?ÒÒzÌÚ»{(WÜ<Ö*–ƒu• êÈgèÚ†À|y6; £Mù„÷ÿs6—Ãö3}‹%:Gæ¶£rsþ¬| w&XçÜÒ$v*|ðîüxGV aœóÓd3± ¿N«-ÝômÔ]Gí}A¹¿éå‰kUMJ Ô–Úgn¨ìKËidklS¾§(.²Må_xüê¥,ð:¡óšP×"±?NŠUBï±ÌEÀk™ó;'y–©åè‹:©N æÄYn ˆu xyç±ÚªUýQlü jë F‡— Í‹tv³½ù«€9ëfûg1ޮƽ,­óøpFðËr(‚ç[¨ |çì[4çÛcèBA‰([ó‹¬vÎw™ e ‚`Üàì£ÈõláãØŽ¬.óhÓá >²ò½íBã)Á]“÷0燠ԺzX‹ðcJ{ûchÌ޿ҀĤș­Ö.H ¬m$(Ϲ„Ù.¹…|Fg›¯#÷ìO’›¦˜œ Ó<·by¡Å7x ðl§Œ‰CÄí^Ðï 3äLðû+$Rk½ÚEèwo=ëuMößyB6±Ók)µS$2#©†öÖˆö ƒïáô‰} K«‘ ÿï®'ÔT]ì÷»z~ßÊ¾Ü hôv•„¨¯‡à˜§0¾'AžÝjrA&wÏöøDc'£K_³šc=<–Øv&ò/}ÖÆËÛqÈ68ÔŽíeÐQÈúPÁZ½È%oTSD¹ù<ð‚6àg ZÕ LëÇL·‹ï•7¶}“GþEhaþÝBY‡Z›±A#Þíûõl§pÉ¿:/ÑXϹrˆ¾•œ«—QdÏ^1ò[¿ß?m“h{{åË·'ïy쌹OI0å;‚e"ˆè«_&ÕUo:åW¦Öü ë%6v)@ª¥|ŽÇ˜„ÀN.¦<`ØEîy¦n˜!ߨ‘õi5¢ÿ6'Zfí…ù¦mc}7¬T°’%ÃÞe·±Ã 8§É"£,/[GÝŒg¤òå[þæV‚®@žá¿XQÛ`ë”›YëW‹^‚€˜=r\W)Ô xÇšÌIc͈ó>MC< %„ùÉ!–²òléI%‹0²¾—ÒWÉÚi¡'‰gnil§EI„aÿO7¡2ÉÛÇ»ˆüp¼Ðà ]˜]@Àbém,M©ï¸šCEû½™×·¦Ì¼Ò©r ØhAy|^ª‡Õ=™`¶x [»yu‘ï&sãý•sœy»œ2»“RöáØëà %Z9¤_Ãé„ IØ3xö›RD ŽC_$›xÉSkSRÔ~sŸÍGÞU®ž”K«y$d* ßLó¢lL}aÛÏʾeM'PÞñvð'4§lź¥~J±gV¼ŸDçÕP›LóþŸvùMð´M]:¡Ç“ßߦv•yþ–ØgR­LŒý@Ê“†ä|ÂñkfQQN’Á¦ú^N2iïÚî% Ŷ­æ~S{mß‹[]´N=—ãt¤Þ¨¹;ÁkébUãÓØ Ö졟»ÛPÝk§Îz‹ .;ïŒ1—Ç™œÐvJ’É«3Ç6é¡õìþT©“Z_çä=`§ÞYcÿ´ŠØEhÓ“ ïÓ"ê÷?ÿÐhÿOæ§j8 Yìñ°Bw™×¦Æ!«#ÙαU|$n­Ñe)ƒ? •Dº¾€ÒàsïÈ^Lx'‹Šµ¸ * uêH<áü.†½å‹Ö1çºÛuý'ûã„>BµB.UüÌZoó?Œ@ëßùNÛÅëÚSêq ½ìÈQõ|Çú¼Ô¬,/rÝ肾43])VàW •ŒQ°àhYH¡Ì›VBQÆ®ålG!ŸZþp &§·×Ú¹¹(ÓØ(–óêl<ÕmtG|£?·m³ˆË…¨CÍÀ@ ™Ã;l’¶ÐÚŸ})Ö¶˜>ÛxŠÚœY‰@1‚ÃQ†ù¸½ßžÖ¡é0…0°D@üÀê^H•ƒÚüZÑÇÊÔR|@ìãO©Ïa˜Oð-Ù‡”ÖŽiçWYÆB“ý‘ûAþœ`)%Ÿì‘+rX¼}–Ýg[ÛÞò²Sk°§P¹6\ñC*òQœ£úyÁ"± ù½I™ O$œÏGÁëÓ¼9wçg#ÕhD‰‰ÒÞ¤0ò€Ãõz6©ê&¨ñ}\ ¥Û,ÿ#ñ›ÄžÈëß9B'ÙëGj8ë ·o$FNj_‡Ä<7¿[É€Ó·ã[àçxÁäè\¬ïÒ®H9¦hfIM¯_ÉA\'€›óã¤éòmö9¬¸ÍHÏ úÖWGåÆÍµµòmC§Zpƒ/÷pÊÅ "_ÄÌà™Ÿ¬WÊC^Qœ9˜î8^ýÄ Hô†£‹"Ú0žzçÍY¶;ÎP-oº@€(€©T«4Õö3µ¡»§OƒÕ p,Dh|‰> fÚ½. ØÄÓíØMWOÃ7Ÿ¤!Þ‹é3DX.yD…OjUührË”7·“kÁsȉáÐa ×õPO æMW¥&zÖ-dæäœø(%duQç"¢0E§O‡öVu)jÊ.uŸ1sÜykÅ÷˜UiI™¢(Öÿ# èg<œ´Äµ3a[4E† ÌÉËØ )NŠË_ÿ´}V“Ù¸xVïÌ%}”"œÈ‚Ë¥lèÅ!þY\ÚZ@Úg¼þõòZ¤nŠ…_ah<§,€kÁ%¹Uä˜AMÅæäYI„)u4õ·v­EpVÛâa}çá·^nöÉ+ƼJÏY‘–5(6ÕÞ)k'«4·ÐWZËì;»’‚?þÆ4 [²¦ÛèX.÷í´è‚p_¹ñ_ãÁu´t°,t5tMvc>p[òfÏý>=&þf2²SI5Ö•Ü,–!‘¯¼ôéíÅKiJÁž {šÞgšûˆ"ßz†ŠÉ ab Pr@ªLYÑ*ôÝTy=Ii=é§±SGZTˆÈK³|¡Tj¯†*„ªÂ\Z°j¸Ïæ \êË4\jÞ ¡t¹ 5Âç"L—†]7µ®þB®Ò_­cqe!Ì0q;L$4²›B[qHŽ7Š9ÎÏgžÞhô\™qÄhø¯ ý™°Îäuf–\¬Q™–¸|¶mÈ™RFOL+’% /‹—È­~âþ>ÈßÓ?ûZÚë C±¯œ‡BÂÆnÍ•´¾„M´úieÞnHPè,†Ê¥à' g¬Á/1‘ Ü0Ö£ç©@–#½à#>‘²±¿¡}9c -¢Z“ò½}zóî âQS£'ªÛþ?>h€1àÄÆ“wŬO(®Ú.ª,<É/ãÖ/7=½[¿upï[\Y8Å[÷KI”d¬ó¥—bÃa'ò  ÙâÌ‹Äá£Lšíޱ•¬3Àù§Oô†Ï F{2ÆDÈÚŠ€q,LÖÙGûäÚ¢ŽÉwÚ±x[ÒrÑŽØÄå–È;, Æ sv9®·ýQDœƒfOÏúD¤b” N†T¦§ -gÁJ4¼)º^ÿÿ¨²ø^xy‹,šä*hoKóÒ'½ìÝ’XÒ!~ÅK }äp#øgÔ2É®<õ›#¿ÝcH÷#Q­E°ö§ÜVt,Q)¼AˆCÅ3¯¾Õ#‘ò¨XbûXª¢\’2­ÊbçB·QÀfͤ|ð9îw‰ÊÉ'»Mò·Ø‹guy%çåb)E~ý‹óJ|KN“Ý<“X¥}ëk‡çRÈ{!F%Âïj’Cã̇–ûÁ(ûÙ’6»oÖDjþ”†*>CìO#×_ì0ú£.þ@JŸñ½t./$fc,¨ÅE„ˆŒðáï/Â#`Ôã<è‹# z(ÝÎ#?褨a{°è¡Tÿ@¡¨‘Š¢E·ªÃnV¯­µh˜É™ŸÕ&4̾GÞkzøÆ"%7§eå«¢iÀ1»½\HÜ~Àu‚  khÒ<Å1*Ô¶éà8͹„Óæ7nÃÊ]´ÔĨºVvŠð mi¾L/šõåmGÄâÏ+Í‘CŸ²RÆÿƒaCc Pð¾.N&Ô3+ ZãoÝÅúiàóûˆÉ²¡Dýþ8êݶŒuÛòù`ÙˇœY*Ù›RÞüÀ+}­3À'ϲQ2L:ºMwÉ:¹t‹S•\&Žfj¸¨8)æl@è¿à쮯Çä>ñòJ I#£È¸P¢ÿ± žQV<…£Jû]à›hì, &ßÚŒDaX=a ÔÉV×;ôJ˜ =—+ÞÒ¶ X’!îâ†iЄ—œ³O(à µ˜Ž ¥ºC&Xöêõkë‰zŽÉyR­¸Êw°-! ÁÜdb£@}Áƒ?ü>† Ôy­’úØlâ q·–4ƒ`Ù…›»Ç¤`xZᘔÀl˜9¸Ø<ˆz‹Û·;îìŒ=H”²Î„Óƒmä6¾ÛºÉZh’dQûRÊ6²`òPêX— vÁ+%úâW£È‘Lù²¡a¤ÖX1œÚæÜ6ä’rÉ ’ŽÒî$ríÊýçüßUpJc¨ý)âmî}Cw€{h´_Õcõ¬–fŒÜ ›&†o:ë<Ñ1ÞÅOLøù¿n"Ýý'\†±QÔG"Pûað¤.{@ ¹Ç¿Ÿ¬ÊÚ %»ï 3ÙéU÷ HdoyòÇÑúhŒ…0Íõ—’Ö¤áJ˜j*b5fì ï(€k"E(ÌOm$ë&4”··÷Y‚üÉó´/‡<úÉÔÛ\ÑAi@ÿ¶8ã”O¼òŒÛÓ~%/6¶îñ9œ­•­ŽqQš5*¯Üþ•â~:s©,ÇÍbÈþ Ý·—ິ¼ÙÌÈ éåUgp'KÅð½&-õãLö2.‹@Xäp•ØOè×À$Z©bÅâ?%]ˆ3ñÊêˆñöú—¡•+Ku}îøêlïDXýmß÷m÷ŒÉèñ^2Rý_OÊ´jc•h.ª´œH[±¥¨=#® ÿÕ}w’¯â“sõQï¡[Qp.û_Ëöç_ýÚˆY\ô¸p»}‰¹e ¾Hï­ÕúÝ{A'£G‰½73ˆ¢ò»À„Ãü•¼Æ0Ú¦}/ywÍ„J¢/]kPÆ:/ ²Míu¤Íáµ}¸óƒ~u¼Ø:wqEeÐ}þÒ~=íƒèì]>ŒÁ‚t¯,O¦PÄwÅ8qLº<ã3”¬V–Ì£÷&ÀrÉÒÌŽ Z]xZ¶ô©H$ÿ¨ ß{™¬ ¤˜9Ú¯$Y8ÝãšÅÉd…Ññ|ØÓ¦ˆÐ®Ñ÷A”T*õ|š¡ü–Z͈b«Õ• n®‚êGF;ì#äç€G@0d»¿z<å‚Rò;[èƒ3ÙŽ„´‚oiñ£Éú£Öˆð +7v%L„HA¼ºus^µ¦ßæRÔœøödÏ ðFLUøp¬t§Fn[EJºµš0gv¨Î ^ax­&Ø×ù²Ï7ÊÁ\—5¶÷­ÃöÓ°T’fñãU‚ Ë Ú9°\ïˆg1Hák/×?]%üø>úCÏÊ[ñÑ3Ò4N–å€ùP}걤;Üýrájœz¹¼µhû“"ÞNV]rña¹r#Snw”j;·yù•÷÷½°§¡T­v–ó˜Š9ùÀ±É ËaØm!¼^ «ôô!9-Ì¿êÉ̓ߦ•µgÀŠmO³·{ût)L˜|õ5Ë^8âRa«êP‡{nÁ˜à°oyƒøƒuÔí©Í ÇëÿOÉ+ ¥úW>¯ ѳñËþ Ëýyþ¿W0÷X`nÅž¹|ù®ìbn$Nÿþ¢ fBÙ+¡ðÁxÁ¿â )²:e/*ß.tQ7_2cå3Þ§¸Çï<Î"¶èm;¨¸j" ².7m5$x™ñÂN`Ëép¢1?‹“Z›V¡#¶Œ;?î½nÇv-¯6*;F}Ðsi•üÐŽÌÉ®áøÚûÇLá{;ÀQ»}".À7ÒEò£RÍ!öÁ›ý#%þ·(·öË&¼–äm«— lWÈ*Iä™Áu ÑóãØ“5T©RlŽT/Ð 'ïÙüm­´&tTzì¹Ó m\Q=vF$ö†¸ü¥eûáÚhW´ät¤ëtˆ\Å ’ ’¾è}Z^ôVq‘Rd÷ _W6mqÕ·ÄZR¤Õ¹†u…qÆ ïÆæÿw€Ï‹ý¬…nÿ¡¼^Pß~uóÀpi`”%;Ñô,'{6Ì©Pãû`÷#v߇Å5ë[ÚóÝþO¥*›…:h\?¡ Ú±+U×.$DM—@˜cP io¦ëTj–Ò塈ªZñTŽ¥‘Ì! ênnÊè¥I¯ü’Ö˜fŸ‡ÙáðäèqD:‘¿Gy]ˆ¾¿i°dª{Ë̤`“õ ðûòsæg1¨up)Ç’ÊŒ‚*Åd'6ðY§ $V2¸s½_²¡µÎ vs£!˜¡²&¯`&›³t¾ÍI‚c)*_i`{ßfò„Éí+QÆG½âO¨¸;‡¯FÕgBÝF)TGzßçH$êXfA¾¨O/!rÔr =’ëy® ƒË öø÷‡Qn<±d˜ÈrHÝÁpôqÆ¥žöÿ¾¦„-êš#ÿZ %ÀpöXk22Â…K8†eÐ`¦Ì¡-¼¦óÃÇÃEìÁ«ö\RŸðüº90d/åØ[¼ §DáEæieb\÷yV¶§D¿Þ(nls3ÿ›D¦>àNaÉ×léL IîS:¢lîyZæ0K6y SÔgú¦æ4qÉ×-<ø÷}´¹Y××7žŽ} ‚´rÈ0Vqc¢ê÷¶Ï#BÑ:ÿEcºâ$íºs© ª·ʶ“ÐF¨\ô~x‘>1ù¢lUºûñÜ5‚5±æ¦›xŠÍ Ô¨¨”fXòÏÜH°ŸÀRB³µÜñ¥Z}’²Áà¼Nñù04réUñ̘S[“QQÔ2'?’ ©f«?ö—•Ø!qmv®þ;tó|%ŒÊl[ÉGº—ðБ@S`%[æ%9@X9ÙÝŸ@4…#Ýd¢`ÉÔ7g&Ó J˜ÊAùzH›Ýp¢¬9€˜Þ–8Á˜z3z&¥i%rÃf¨AÓäð+«»C¢- í ÷í´xsXð^#÷+Í©lü—’‡ºåE’(ø¨0ÿM‰Å*†ô„|ÓCJæZÙî—å÷Y?¦z€b‘“Ù}ûý$ÿ¯EçnŸÓ­AKÉZQèANƒ NAêî¢j1! `%î ‡SÏöB¼Õ°¡p¯0Å©:’}NÚ$×®äÙk^Ë¿·n£Ô}¦½•Ú‹%ìéÑa†ÊJ€ê5‘ÄOä¶~—P=ö©ã½L¢UÀ\cZ´)ù D”"µ¸`ËšÀ”1) FùÈãRLQüb¥^™SLËád)°2Ló¿¶®* V/­R<¨(}\ãWÍitZô­=²¤ö–?û,ÚRh=Ì,: \~Ðë‚)o…HTÝ{ õ<I/Uµn5>Mz¨¿›öÖoáF°E@·V½&MèjU†)x ²šfŸZCFÂ~ :Ô9÷ÇÎÐ~Ä0]¬òõÞ‡7)ïî¦V¸ep’0i/T tšÍšKJ­F³I Š3{˜ ;)< èùGºðíPqµ‰g0§ûûú?¾2ÁŽé‹{lΨü9A´«Yy“þ«ÏÈþŸž©Óáò‘÷cWYýÎJ{+dvkˆÀŸÔ…£ü1A—ü¢fµ¥ÉIà]ê™1P¡˜‚)X=¥¢7*íQVÉÞŸ%-U1×~… 3F‡Ôâ;uyà¶£¥4Ì š´Ç¢ï–h@ „·;„'ůT˜¥ÏÝó*Se²p"óÓao ã}«)´z 5¨q íæëyœŸÊ€ÝÌ0Žè¦K´bJR­ÔÎÔ.¸ž„m\Äö颿x„B«F´¸ "i°7l† QÅgε‰ (½·á’JõFé >S¿óœ9WqäùAÃàlû»lŽÄ5¬¾ÝMâØê/®À娌Þè-i‚;3î5Ì"/”­ ê—d•™§‘'¦×1 „?ñŽß ]e„fq¼7ß ß»7I#ÆÓ¢Óæ%D¬×V“Åe¥¦AûÜq-÷áËõ4?ËŒä¬0ŠLÁíY™ 4Ae&!Ý&6_àµ!½QÜɸ¸Ñ²439eT/WùX%«[rd¿Ñ *·Ë-ÝÚÔ}ŸÕ1íñ£,Pž³ ¼•ÑrÔ+”‘=TeSJHã°ë¬ú!sÈa¼)hµ²Þ…}°XlïOø ¢pFu±=×ûŽ›­ü-QèÊJW­ˆÓÔvÒTðu;®8‹¢µ„¡é왣GaDØ”`Y¦ÿ L\Às¢¨@»5ÄÎç>1ÿl‡ãVU&$l}á:XO߈¸l…H¼ˆ8‡¸­a}’-óB33SÌïV&vƒDLñƒEK¯iPÛ@ûrÀNh-zaA&(s×X½!4ïÿÆÊ^°ZcìzdPƒW­Dl dT³Û]á3·4z¾üÔ’Íêadâë ÁOλ^º¿§L<™ ÙGÛ.ç¼@˜tËKZÔR*Ì=‹Ÿð)¯UU_Loö uæ`|ã‰%H9žcY”zŹB9ð±£Ò/ s9A¬®x„HÿE®'ÖòŒšs˜=µ#ü«tFŸÈ(Ðk~óû„‰l¤u£”<ÐÉ# /­­á#¡(ÕÅ-’W©Rƒ ÔZ äÑøß;ø•ª½iB£ø·çZƒ•M«E²4„uêŽzð_vÓ~÷æV½‡tVû|#°±É’r¿+tW¦7o.ÜÕ?C0q‚Þ®kU_¾=2PcΔãeò4‚ŠF]‚«éqï¶õSÞcÂÁ¾—^ [1q­ï í5õ-ô8 òò)iï•–§Ó£Èí›w¡`4!0Ř‹š8qŸf<ÏÌ:WâÄ(o|‰ wÚ'i¤ êõKÔ!”3€Aïze†6Ò§ñ é24ÖÐÍà6ŸEbœž#ßoX †¼«kªÛ6lf™*uÜè‚5WæMs¬¥ÑÒ‡W"7õAá\Æ<[¦ÿž0>°Ó´Á«]îƒÈô¹#£±ÕE6Þ{M÷|ÎQ¥CôM”A¾m–×ßÕ@ˆþq[E1‡€Ïe q±Ì˜â_ZÝlºsu«M =úÅ¿B$2òæ£1¤·Îûvsõ$Ƨ~ñøÂ%ínïœ/@_j‡ÿ{`ßS0—`Œ7«Š1‹!.ýYÁï˜vGýE¨ãyv. Ðº…ÒÃFw7÷=3ÎAFשæ.í#˜©”úûqôvCmÑwÀ+w"EpŸ®ÿÚu83¾ÏÎ]P™Lõ°Éª°NÉ÷¹`4í¹x Mmp=¶ ìq Å!ï*Søä¸œk•N˜ãp­—­ÆõiO›ç ¦òBL»Wø`ÆŒOŽŸ\ɉ(‹l¸Ý‡­gKm¶²†Œ¬b”âyy½ ¹?Þ %ÃbS*:n ¸öåCÜ\Z7NC­t{ÅÚæj㷌ƋC¾GhŒPSz& ŸÅ§ UÞøY#-,—^ùŠG\ã×TUÐ2â$µ‚ç§ŽËÙ[ .BÔÐât߆ÙaÞt›½[ÐrJC-‹ÀFòßö=Ô3íV®ž91b®tªîðÁ«ý6þ+ñƒA:¨…Šä£)—•ðMUû|ðŽY9cåzÈ‹P› ’Kã&k•R”‰Y}º,> Ñè'#¾2ÌTÄö7UaÙâÍž H_Ë–a%Äõ þSúZ¶Ïúå R`"åŠ;F¿mÀ±Æ(‰)UE£Ö3P­ o4cÜœp†&öaß癩輸Ô_tmÕ«gáUq¢ç¾Íü€-Œ'Xõ %–ñzVwtkb¾ÃNáB‹ƒrÆeV´ X}ÔdŠ9¥6áË”XD多Ñò´*I‰D;Nh-E¨ÝA·³Ý7Ü1?e&ßw;ÇV× _5q>Á›òÅõ°‰š«Ê© w±´›˜yËkå±D")¯d(%÷g§}w­—kØ´P2³ ÝºaOÐm•ò¢ü)Ê­UA ‡%!ô~†bÿë *Ì`—¾´4¤¨?Þ·C<ÝGˆC®®Íh„Ò^/Ш¥£7— PëßC ›Lħž-„¦9ˆR ŠeUGH½î×;³RqôÏûy"6p葵5elÞ@rùNlÖËòÅ“§PÅRƒ~;Ý[èÆ… fãÀÑË iÜ[ÈI†Aº ØÏ0Œë$ð¸o}¹êé[Øž c“Ê*"ÂèeH}¬èãI¼Ml¯ö¯PaïR3yM3Ûö‹oí€sðõR¬nwâ'¤¿¶ùÿ :â~5+2’‚ÆŠÓ–ÉbD_ØòKÙáPôYX“ÈÝQþ"/÷D$\¿FÊZLWÌ*”ÈEv=?kÓ— c^•#v`OAˆÓEð&h xq‘ŒL™Aðb2µKÌ´¼n¢QÒò5‹ ‹s„˜P ùͨ˜¢lÆÓBïE'8Nט€ð9¡øÊªã•åapHÎ4T¶Û2/øêc¾ÙÜ й’ØJ™ ©R¥¶i¯›iŠ9úO'?öߟÂÅj !ž"Q;vÎËt‹ú3yò› õ¥2üƒ@v±"/_‡±tò~€œ3O,Èm¿ïî~ÝÇðdwA“;ÍÔ››y3ÀtcáÙ^+R塬,·àµÉ;ÐÍ$E;ðÀ¿À¡*êtø±èL„‰§|Â:éî÷åI!^F&] óœPôË–~Æ€†#i[eöÿQMï! <—Ç$Rl3NUæÕ}Åù›•@42Å$Õݦ~:èÀ‚œ¡}JÀ µz…- S@Œœ‚Àžœnü,myøòÜ9oéO†)V‰ [f+ÖK…—ñ‰vœõÂÞ0\ÖÕ×áÃXƒTv¤µ1|Iã5vóTÝ~H.ÑœñbøL”?9šdª ›™Úºi$Xkìù½WbJ¹> ¶åœiE@tãµ"<ʃ¹°éÏj‚4»-ƒƒÃ76ì}wÖ §• ½ˆØ¸ßñ‹d !Ç7 ÛL©&ßÄ%9© E„…Ëa®B¤ìá]ýýöV¼‡Žr+÷=—2ÖŽ>MÚ vïE<·DìÕ/ ‡ÜQ™{è¹ù€ÍkM³0<ã7- EÿãÃJ:Ù·Œ—†kŒ;dÈj¥Ç¦•<©:J¶ “MaÉ(òœ>E†ŽE¢¹*wD[ýb»ËÆÆºx:™šÔÍûW­oý€¶-€‡Kˆ–>i>ci +^Ž;a¸1‚ÛÍè#M)ì÷K€•Š6RG¹MsÉOûæé¼0ô>Õ\Œ:+' #S¹]ç º‚ V‹,ÇŒ5Ê ´Ÿ ÜÆ‹á&´“…äÃ䎥磺<:k²™ûÿ5„9“û˜fÕÈ® Ì Ô¦‡Š”ŠZ5Á ”›²ªCÓ ­á 5rÙJ ¹X/§Fç”ýû‚S/—¬È×Ý„æ|Bf¾½€\žÒ»ªèÏHs/Ë9.é7u¬ïáúLµ·¸S¶ð¿#ñYvÊÄ8›ùŸ»«ÑMAç‰pïŬÑÌÞ"̯+¢'ÞÚŒ‡œV.È|¶`þÝ ŸÄŒQT£¹ ä1yaδÁs¸>ˆxš#m9KvúUò¼6€Ù\pÛ]ººÙR'Ca .Z 5ë;Xd*òíæy?B´øÊ/ÙàÅ·?Ñèc»L£rä·+ÍZ:iž–€€aW—|‰^ [-²½p&OU_RÊUŒ|W_%ßk` Ì?”øÍ„g±>w«cŽsM³|_Ë…àL¸\{[]ت×@Ôþ6þAùZ.©F¦éKJÈ»ƒó;€”{ÚPÀ–½Î³Ì’ƒ’¯cÔj®l{ ¨ŠUÞ‰6²[ãá×ê¾…8}+ÏJ>• +ÛŸu ‘gS¦ÎzlXaëôQ¥ uï‡D´‡°ËWÛÌnK©IàpÚúr˜ƒõŒ[îz£¸Õ˜Nì‚*|D[’)ûà‘:GY°Î³.öqÄ•šEÅë8ãÜ]‘«þªÒª HÉÀßX‰ß[ýðùÁúwJµ·Ý%Ìéà [ªHj…7fgŒÞ­Œd)î¥z]ö–[mçD"³nÁJ%f?è¥,°¯ía±F±+–” n¾Ã̪j¹ßT%ö”—¨¥üGàö’ÆtcÚÅ‘1ŒÂxü1®WF©ôظ½!eû:‚xiõvø&L’5Rçx¤nz­ýj8êH]3Fdtú2ņkغ]q^ÕbhË 8¤Ð‰½K.°m7Ž„ö¥ÚUç¢q/xѺ=ýìú šÃÒOŠÌi¡ý%1¬ûÔi5d 9Û„Áq$Í‹‡·4Ûõ°Iõ¥¡ÚÓ¨-èÀ?°&Ü¡õp.Fx¡pôA7õd£õÃ2ÈEøž˜Þ*þ‚‡¢6‡;óå45NVœ Ío³®êÚZc£¬¦‡èŠ×­ æø@⓳"à÷õªöm€•‡Ø>OˆœÞàÒÜ ÙkQv¨†çâÄtÌñ Opspù{´…Õ| ÛÁ†ov„=‘úõ誑e{EKÜÇjø­.xÄB§ù´¤ÚcŠ2çí´Gì3B[Òƒ+û7C“Ïëü ‘ßúMZª…³_5õé½õ^_FfѶZùßå²7¾/ÔI)³ÊÚçÞÆë"ä©Ôõ‚BÉËIåo˜:Èú¿*ƒ“‘2ÿÿŽV`Â>óþ]Ëc 4 º>«ÚH/Üÿ× 31n|¦ŒDHµ¨ç~šè4úEëBøF×BšBöµ¹,‚añ™ÄªÍíð^šZUêÐUJ–Ó©d¹B±‹€% ÿÉà<äFÈ­xd©Ý¾W3Ï¢lǘ‹)4*³^mèa˜¡3b$QóÏáéüêšâ§òems‘®g‚ív¤ª,˜à¹…ÑÒÂ!6Nå÷ÛÀ¬¯vÈ‚þáµìkÖ}"”qÜ¥¸À*S¢âà2rö†cG‘OäК0ßÙÖ³(=Ì”Ô2]édž¿§>!%ÕØã ¼-2f¦-hÑFÅ ÈlKKÔÞ£$­pzv­S$Y‘P#i¼ èu[·J$òøqõ»±eß¾ñ°÷ñ}ÚÓ`Ù"36ÉÔGïc‰¥¢ÇòÙ\…«ýCSf.%"M²S”v¥ÇYá÷aa¶ß½= óÝœ5ƒF”ZÿÕ™šC™ˆ’8õq…zP[xƒIœåMTNF³a Åšƒð$µ†3"/ç<†Ñ‘ èl”•Œ¢p*“¡Ejn`Y2̬¡ÒûýXƒEâ—Híѯ®êí`Íï2èÌ-rÏÞ?_•’6]°´XHËfÕ­™¬q×­r×Hø: ÒsP¢Š¿9ý9 ¶‘ ÈÈ·²a©_ ÚÏÃ+«Œí¡PnæbÒ¿'X›R἞#é»È.ÀîX?:])+=4Ù—zLÄiqKÜõkØs×fStçÝIúJoÕ}RcÙn)÷´NUÊý”ÃNVBÛ‘iîX½Wkq–µRH»5›äký*~JßÊ&!ÄzÂÿ¾ç¿qŽŽ+úI§Égœ+¤ñÛBmN\yå“[ »±MG+`Ë0ÔlÎâ¥#åÈÈòe§ù§.@ò÷÷"WYëœè]ª3¡@ Ö½¼S¨éÛÃf¨9ãS·hÞ"’æ…<2… "~K:T=+·âðxÌxy ¶Šm@®n÷çò*Ý¢ž¡Ì 2‰ oD öÈø¨‡tª+T¤è]þ ¹{¹»>¹ÜŠ7á<H6jÁèòŸä,H?nÊØ2²¦×b›}p™Ò&ó!h.Œi¬ƒ6>a`cª¾ý»³ ÿÐj¼&œl]taÒFrr~”“£Æ1Ó>ïmP¾þ§°‘‰/¯`0°Ø]z1¼ I©›ÍáƒmŠ)#z¡>ï×JÁuU)=Ó¢’&^v ÕI¨üáSÖòFLg8™TºÒ\…ìfËz»´m'»Á©ÈâF{ä‚`v¬C¤N:&å¡þBéy ü%®tRŸJ[­âyÐìÎ! °J Oì®èWeǶ”Iý«ŒÍˆkúÁ’DwR œ Š’à?´'ap@‰žy{‹3eªï“v2  ÛËö§Q“'³ÕÿÂ(¯Uߺ£rÐÆÕJ†ÁSlKíCÕ mþ Я¯95;î74èHÏÓ«’ça¨t (jNû `e[BwÄeí×y÷]ˆÝ´>‚ÈöB£nº¹Õ/Ã$ÂÔ>ÙÂ.]–Á‰Çëå}XF}'¯è÷&¼%99qN7¢®êxö„4Åáñ k£œÔmò’‘Š¡„¸H2•Ó ,i±ÔŒN…j]£•ò£¤î‹pÇÞ$€Ztq៑î#¹/:ÂýÝ1:Y'°XËíÚÊ&Æö’g•!ëV¥•nò„“èi.·Îµºš±7°›û›¦6™i]>@`‰Ì0Xß/š”¢ú™:RYn Ý¥ˆžî[f"Ûß½$rÖ®$Á[5Ä­OI©¢æ{ëª{¥É­fÐÙ¨Bƒ0¦Ê&€ŠõÜÊUs™CÔâ= ´ÓÙb=-ài—/OÀGÙ¹¥4¢A ¼º¨£ IŽ¢9U ­ñC±%=™‡‹x ÉËT‡‹¿Û€HR#à’ô4,GùkªSj&hcmDe¥«øÞ»XlewÞe­"qAáìì ·îËYìÃ,êB¤_­îOV’“´üIì_{À›ÆÞ–‡Î¬}µ—Øó+¶šøwFýÔÆI¢ ¦`“̪ø‹Â[T ⪸÷Në¬ošZ¢RÖáÆ0èG‡h óÉÈ i§4$üÅ}sµ’»_ŒÍhëãÀùŽNWÍ#é¾ ByvLGAž §½úφ¾Ú<[™òÙƒ‰™e ¬¢’ غ–ïVĪ÷’€–„­¾¦hs¹ ÉÏ܇õèÿÈQ+¯Ú3AÿN§§]ÂÉ=Z¨,²0Ñe°ÉO7tÃ=ÔT¿“»ÄúÖ"á*ÉÕ96œ‡í~5n0­ž ›~¢/·[>ùô­Í㲩½Ÿèkp„M¹ÿDøšN·½mX~¶L Ž¥øÕjÔtmIã³L‘gÀA)öÜk ìW;']ª9ĕޠ¤d7”? ó—¾Û½ LFpá.s§ _Êý¼‡×3¯›,©1œb¿'f<¯¿¨').h#IJƒxYéò+/j½2aÿdɦúqÜlú·«ºÝÂëµPáù$0©þ-k>™=¿ºê¥2{Û踮ٞæ6ÅÀ+Hõ—iQJF-Jqø"7G—GÐ_~1¯NÓ¡w!·ßeIç×Ây…ªº¿{ëgwÝ ƒLB‘uNåE ¹”Úžµ+Éà•º=«í‘—˜½Ÿ…“=Á–Xßéñ³˜ VÚÀƒqªG€áq4Ó™YŒã±Ê•µÑëÞ<˜¶ÖÀU ¡c²ãÔ_é¡W§õ{\ î«_¬Æ#(^¨o«BéêNPî ö)…°rÁ•¸©Öâ‡Z60õ'LX/q^Ûq߯S™©‹›«RŒT6V}Ù ±K Û¯üêt¥ÍQ¼öÎ1‰T ªìN3Ü|ñ¿År&Ò¶U²ÉâU|JtJƒCÉïôi½±z‡˜ŒGŒ3*$~çD4PT¶;ÄN%“•¿“X`èäÄõÊ´4Ô²í½múXp ñÒÍ·¢Ñ…x¿ña…y;ð•·ÛJ˜É@¢â¹$; ÿ 0ü‘fÙV`S¬Å  "[ö·S‚¨ëÓ¥"½`C"~«®µ~®R}Þ(ÞñB@}]–º?*Ë_³õ$Yh%}u~êC\NRИžÙ¡D¿`ßdƒuŽÁ¢§Éybõ$ïÐNGP÷â–{çïj{ó•gA÷?:" ’‚A† Hž€pwhv/ìÜEgY¥H~çžë '¶}HAûcv›ïÌ^•&i£dåɦ_k™Õ- —ðöÊ 1ûUú–Ää¼\i#††“Ú -œ·_ﳬÖR¢å°Gæà1Ã\«.0 ­?V=’D`ÙúœÊ"“Í?1‘R¯ÐsvuÐíËÑO–…‘0÷ô`¬rÇ[7ºóåÈ-›øÍýtÌ­Ç0 èL¬Í‚CÇplÊåß<±hÉï‹ØáøÎ-ÛrÅùf¦”=xׯâbùÛMfêzæÈ±ºXøð_ÉŽ %²c7Â$/È™M4_Þ”ÕSéëk£÷i‹.’À¡ŽÒùLæZ%¼!cÀÒ5¿‚ÁyçÁÂåÞ>«¦W)‹®Ž|äs¨ bÎ3s‚úáö k$†é7GÕWÒó–üša€¥¹´ÅšÙ}í3¥Äø€H"rѾ®Øl3)§z£“¾VÏ)ð®Ð»Lª¸u¬Z²èLI™RÓ½‡È:­H¯½ÒB:óHžs›t$U/-‹̇‘Ÿûº50à㤧­Û†6’]¢üóú4ýéñ ¯[–‚ºâ¥ý}?ÄÅÒ$ñT`OC£Õ|ÏF°;©.ϧjõ°½±,ÄG^E¢žZìr¤ÕD6bä ŠÁîižC»ªº]áz,êÍ´„ê-ô\NYà®CH9ÞqBÛe†Ý–2³ëýlО9H4x°´˜+KØ”eCµ‰üþ¤{ÛÜñró˘`èÇýН‰f¼Ð²…cM‘×W®LÏIϽA»4&1´sF]riâ P5Þ„X«ŽàFÄÂJ=—ϤÆ•"vS“ñb‘‘À5ð-™£L޶œ¿"¸òïQZÄœ Ÿ1ø½ (;›Üø;XQ,‰ßèé˜n‘AÐt¸vÊpØïÓÙèö‚-ç­DF°zSÕèaKl’åöÓ곓øDÀéžêdb*¯_œŽÆ0ihܾä1Ð÷ûT¶•ù#ªªÛÉà<Å4g±=ëBH¯~ÊûË•—ÆHA››Ï#Ê©ïë2ä+dñ]ÏÇoÉ=íÃáeìXùMÜc›Æþoö'ú%ûoò¤‡ó¯’~u€Ž{²”A‹Ñ6Êl·'™dÔéÑÁ^ÔëÞ<‹¾ÖEaŠò©²Uh8ö:Òˆèg=ºVQºSªm-NŸ–ý¥$ù9²³OÿÍ:;V§9^ô©wüЇ¨63}?ØõèD2ËbZßÓÀOóÓe—àDìÜd·J=‚Ðî^çYoÈ›#U7ƒ˜`°–p4p¦àf´'i¶PÑÞÑ!Ü rÊ‹° † öTo AÚç!×.Nç\á—åÿû’»nךl"æ7ÿµd7YÁbëä;ðè@÷Êq^1®ù‚äMnAÉÀ!žKd-Ñ" QbÞÊ{бºZsí,2oÅø÷çu³Ü›Õ ]2C UXÝÓ&$Ö8ǵŠ2Wcúè8ß%jLÒäMîíˆÂag>û^ä_¤IÞy#˜¥³#q4w3Å=6½inp!4…‹+˜ Íû5Úµ°XmS©ÚK…¼bvÕÆ íÕãíÚ `|¡¥,©1ªfÝæèA°[¹ö4 [•s[ªž/ÏÜäÅmzjÙÿÒ?D®5»6"+ ÔªWŒÂDÌ},ØåÌ žuvêæIòPB ̱èúEØs}Š¡N-½ù÷ˣŽq;+tÍŒZOš#‘y×Ü 1$!ÿmÚžF @ÙÙœzîìL“}¯^‰—׳¤¹ù%S›àTæá¸&ì|ëÐûL.Û™Å,“s÷QršÛª¦Ã«Ì %óÕGÙ:ìmƒÎƒ["|ØrQw!>DæÓ4VSíÙ<ÛOÅt^þhíÊ+wë×ÁÇþ<¹kðˆ…ÑV=Feš±vÒ°"ngÔUs-§—úkœy r. ²Ö-Dl½Ã,¦ÒÝÞùÙ¶‰AŽÕ+ö·}Ú?ÀÛ=œk¨tl’Fý>ÝÔ;ðÕä£->„£ž÷—eÈs¤[NB[ ÇëhÞ…$gBJåfÿÃGHË”û6Z†Ð7J®Ï AZ+®T4§ÀS­ª<Ý1£cS¢Í4!FR¨‚0^?î²Ìéî÷n ”Ûl}.¦|ÿK¢v&~é2|°àÕë/-颋ñ¸çÛ‹¨Y[¸ãeæ üº­„@ÙƒT#ìBÉE,Á {Öÿ\=R¢òúpf_*½ÈÒ3ù¿c)"¯aØ^ì`PØl0;±˹ï€^¹ê½{&Y^sp5©ß戛:ÿÝy‘ðÒûH«Ëô;²ùë8ã*¦ó÷ä~ó ¼úáòÐÿË»cøôAN!X˜)+“žÎ‘·èé€ã8‘¢—Ö™®¡ÿÕeHÌÆ íØ"¿•õ81O2™G´HÅ.2ù­z;KXe7áRµ> 9!ÞÔz1”… ÓîË ¦íò|®p>Wˆë±gOšl™ŒK¸Kì ÍÒ‹aõ*S$n6Ê3–±é,˜jWÛ9ÿÄ/ÏÃÁ¤÷«–Õ‰ãÒö„]€X¡šgB4’–Vñ§%fßÿ£Üó ¡´7®ïF™Ë ;Hìžø³ì–·ÞŒ`-«•¸³*ë¥ÁèïÄ~òi2çS²æoûŒA6tøœ’Ö.V2`ÎÏGm/Á#/4ÐYË|Þ‘w°NÉrú[I{—å¡*ÝqéLrìp1¹¯ôS[ì6¤ÌcYE%€ñGáŽ{ÒzþXÔ }©4i}̬Yõ±HlÆ/¾) ª ›^˜Ig[JL¼ÌÈÙ±Aô¬q4é £5„†$ ºŠbßÊ-±[ƒ YqJ©á‹¬TT G.o]ÏÊ\x×äPÎ?±¹„Ñ»’Ü“c ö¾´Žññ9V§ëTcÑ×ëÇ[øNË(„¼5òM ¨€ÖWÚ ýÍMeZ5˜)rìˆó‹'}`ß…;âÒ7èëPdÝš}j{pч+ ñB/|v=®ùÁ-È Úý8X:L€ ¾CgƒeˆŽ9@þ^šÐ’/M¯ü]£x7=6pÜ!põS˱ä(M¢ˆ9L¾?P#|\¼¿ à »HC0JÿJÙé'ôN»©//èM9ÁJïŒÔ®Ä‚LÝZñ‹Þt™ßç÷kJÜvÖ!= vã²É×úø)™1*mX¶Ò¦¸Äè•·<Èß²8sá(Àpžgéþh©N¢¾: 98Œê'sÝuUßíúÞ³ÔŸL7éRÒ#Â)qz¶t9Ó«âÛûòXèU³RæË– =pêÞ] S…îÌ™©wlƒ´¢øô¹(¸~F—PàKUè”úhÇ‹Žš5ƒ¶#‘ý>±ðÙK%4´7(d£´ßG.™¦UU‚r 䕊(’´ž,1<œù—=É8ˆ ÆeÞÿn1ˉ¸aŒ‚ïÈë²b5ß9µ~ñ§|i,h}Zö­¤ñ],£]p»ØÆoG”íôáXtE®‘[æ*˜ÿV3Ñ‚¾À'`í›ýs@,Ö¯1D Äù4á–c ThêJ‡ ¶ÃHÚ£`"~ÉIõžl_X꟞ÍÕôªq R(í‘RÉo®Lb·&"(¿»êŸ7OZn¥ž £îOëöëdѦ©ÑÁ(Õnc+ÔÀj*Ûecé¬T(e‘0Tù¦y‹råäó+.JcI}Ð ¬pó”ã5ß»S9݋̉â1ð æ ?ÈÐKNoe­ªA‰jµ.‘ïd«|h¤ùëÀ0% ßÓHN/Ôx/MÂ=ý6œöCωŒ‘³¨•…P1ˆ¾ëdrrlZµ+óÁÈ"·ê;?HÀ –ñ„¯Âë]á临PÏ›@ì¤epÉÑ}æ-åŽOOYù禮QCi¦æ®¬"šÊˆðî°‰ìüiíVö´5O@d­¢ÛHSû~¶¬áüë4Raà^hêô›voVºÒû×þv„Ÿ¥e½”V(|„€¤QTN CèÑÕ¤"?ÑÃàÉIǃKú?;1µ˜Þ8 ܺ“íUo)P}_õÆ$~y¦›ÀŸ!ÜC®R†hz_rî'ø"¦ÇåÇÇæádêÔÜ=—¯\@^¨3LòI:áùaUjIR©ü~#ªÃ%Jæ›,1nÒåîmœ§¶îyIœÚðÁ,r®y¨ bø±ËÑ[a˜j5åvâÒdÚí“ÃåRæ(­edŸ&X ¦õtq!EÂÓLc˜çÛõäkgÄ~ù­~ÅðÙ2`—¯Õé¾Êö„ì’˜]ró&ŽÓps¶}û rŠêt>¹ >˜4!ü5|³+¯©³;!²&f¡Dvbðå/f¾ôÉ0°É =n ¾ŠßæÊ È‹Á™VÔˆå„ÂåÝ­’ §ÑîÍ`AýsO^weº^­c)+§ºuÛÚ·VŽš­¹¹:æ” Âc-% 0É£ŽÖïUJÞ"—MÂ!þ‘k»–h/^ S‰P:m 2—o‘³]˜/°Ícã!î=X>e2dStêÃVW@®¼±8ôÈÏ LÍ £òQ$ú´=ûùøjüC‡ £ŸÆp^žA6:Àn¢ î(Ÿ­I•õgw¦&®„|ZB#ï$gô‚ÑÉ`y2®ùÂÅ,bnÖõ|øP[ªcqþ@ð~'{øŸ‹s¬+®ÅÅe!ƒYS9Ÿ£fä:±òi¬˜ªH JäT¤Íëà‡z7¿±Áÿ·yˆÖãQx=B‰ÿ¹nš‰jû9EÉ•Ÿ\KÑ€¶ÇB]Jà=TðÖ›1¬öFDmÄâ£LAÏÆ›Çk_rd‘ð ÷À€¦ Þ½êÚ=1-…Ú;…Ryûêš['Q[ncÍÖ’UDfßµªŠë§MønˆñgÁaV:éNÍUúmÃÝATö—Zž!Íþ“‹6ßôeÚKm¨ü\ûx±ÇuKAq4À+´Ô7nû/-,èä§Ürå™'S=j  Öù{j§fÕâ(Ž{²”Ažb ¥%«Ã£AhpLÕÙÙdÕhÔ;á¡ 4@rïoÞéÚ¶ßlZŸ7â8+K ˆh#Ía$W‹5L})dåcSþ{E™‹7›ŽÀ‹üc_þêgµ¬NœÿW—†Ä¿ ×-'r8Î7Åëp:Ø&¡hïA°m#¦}ü&Uˆ¡LÀ$ÚÙTFW–=Ù¹J%{²ü@‹0T,þ·âé’ìÎC³ÏCk2߬]Ç€*ȤuíŒ3¶_Wï:‚T¶§žë¯¨º³ {r1˜Àº¯±èun²|xBcç‚Ù —ÝWœéW,„_'ÿÏ\NFõ½ z7®ähmAª[k0ªž]±ÒL“ûbeAã|öP°”ˆ•ú5êy"òºZLZ…#M¶‹œùW‚]nÒTï&‚,òÉÛö„;äh!t*»—å¶ül1_-~Ä'ƒèÁÏÝq2õ7fËÜœÍ1µ†îD€ižâ8ÛHô,ÓpiÚ¬™hiCÅm>gt~Á­Ìl'®—›t÷Jäj¿y^‰x^Ú Þùàìd!•l¬! *0³ÓðÐYgBÎ’X8Ô°8RŒ v.:›EØ5J šý/ŽVΡFJÿÃÍâSù—yÑÚaW’:ƒåj$ÑX? k§‹ù娨LLkbÞt¸]*ü‹ußòrã½g-jEAÙ³KùÎXÏcÂÎyPµ)ÏèÑÜ›Âí±DqºŠªv§jC-_¥Ã`à·º0,ë( E”~æi´ì<‰l¸ ú© Õ øC ,ìw)Ÿ€2+Ä✠…IÜ7—ŠÌ..øß³Àœ\…Awˆãvjt¥UÔ²ayÆïô…·°cIž¯µýC‚`NF—ºKã—ÁI]Ê<5,j &$jòdÌW·%S‡M؇¢÷Gt;$|êl/Kï:YÜJ£µÐ²5•91úz11›Q{v Úß‹¬ø§‡¥uŽ #i=—³«`Í 8åy¨ÚZÒ3Tù'MОâ)3JÒÒ$Ê©æ"P¦˜vÈqx‚û»:è†sHãVJ‘_j-ÖDfq4òƒhÿ©ÔyÅm­Ø×U©g­o@ñ¿þ_£S»ðIb !ÞXã³Ü¡~½q×Ùdß—iž¼Yþ¡ÑMùÖeøÓZwǹgÀè4 or¡³ð؇§Ü£^ Aû6ÛPÄT7h¨7ßs øëá(À9[<ã‡GCFqÕ¯í²Z_}(~öª¿8#Ó‰D+ªe( )ß¹èI½é¼7ºyÃ…A ËýºŠ–ÁÁ•öck4õ¾TÔ‘Æyõð î.î;´øÃ »/`É,Î(~ ËÝÁˉÈà ¶]_žE”ž- BsôéÇ¿ÕÊ,³¢2:FêûA ‰5¯lp}2ѬNˆòþh­K“™¹‰©LKÈ{–%Ó’l¦%þáI‘ëÇ¡8屎 L`ª ¡À¶ŠÇ#Å!¥äæc>=ÁhŠô¥¼ƒîê_tOsó" Û óŒUÿÐc¨pLÒéÀÍg^€ v(teÍB…¸Õuû{êièú|ßYÄqÏTe€G¤BSæÕx¼/صƪ&sÑ_:DNûj xª©ð ÷9û΢•5õ8…~Üccÿd«±±õæYÊšÒÂlMÀbHpž‡8Jš <±*å¤+ÒÝ0üw³[ãñO Éèn¼KIQšKÁj Ž>8¤S@Z)¾½É|Ú{p_n{¨b¹<=ZPê9V9(ÁèH1²†F6Pßþ°!S?jÚ˜ÈÀÜž°Ø•Hi™›À”š%x¿ii­=ßL…(­”åq*y'æ^òµbƒIÜ?¾ç^ÌÅ5Ø[q(·­Ç=›ýýqOýËé(N#IÀÊc ~ñ“íñS>g‰¡ÈXï"{»²ˆˆžƒ½±`g¿‡ë4•x¼_t˜*6ž|šÓ(œÞNÂña"lÛuÿw4#`>& ë~SñµÛÑ'Ö§úï¼1ÑqP½”Tç!Wà ›^[ÙsËÌ-8ÖŸØ¥]ÁÎ,´Æxf¨÷ÌŠÌÜ_çææŸ¸&ìç„Y¥D]“¹±í¥P¹æÅÿ©ÿ™ÏÑöÓÑÅÍH—Võ‘G+¤Mvü dJªÑÜœ4¡Ž´àŒ·yÊÅ ®"æÌ] ÐfB4!x?T½HÏÉ®Q•„&>wÄ,Ú7Ú¨Ä+CÖ 3iôÞ…²Qùj³?UÇÀ*®ç×§ø¤±ÔcR2ªg ¡„œÌ“f¾Rß¿aÑ÷µ˰£Ykå[üs¶CWé¢wgZÙme|œ¤ü€Ø”˜ Àò¿—G¶¿¹kû}nj“‡üÀ{ï5¥FGŒ&ˆu¨úiö«=hØR0ƒÞ¹3ò£y [Ô–ù^ê <ûÚ¯^þJ’Mª+výòÊüf¬›’Ï) %zUqWÀ:’cLEu×í yBA¦ÖV˜¤,wÐÚ¸œVžfVãõœÃ¡‘K"†Ajz¦XÂu&«Óíme¸ qˆsþOþÏæ}¾÷ÖØœÁˆ¡?¾ÞIÚjÈÉ=ÎÚªÓë6õ•bdîÑÁÌàPœÃ¥"žC–¥õÀÛŒ¶ù+Yk êÐ\·ï m²¾ö’€Rõï«ü`fžÓ bªJ°\@Åãhš| ´Ëƒ¬QJž*ƒ¯8´K‚ú¹°¨%ÞÎVdˆDªXKï¸c†±KJ²0³é­ú{Ô䉾£Á*CxDQâ¾äzÖ€ÑÕOÑcµ2ü­u¡V¥AsnU¡Ò•)¾2H€ Ñ™ßâÓçÜ–¢{íhÿºiôXtØ8Üæè Ù!´0 Ò_äfZ“»< «áaøô¯1ðiº”Æ û^hKrpÔþE [CÊ;‘ùš _ð)@áœÜ'CŽÏbŽH²Ö[°HŸY™v.ÓpäËÀ+0Ñ‘,º~ëbm„ +à¾»Û ê'-¸ 8º§þ‰ú©šª\àV »  dج¹¸cPúËéj`(ŒÝU®"•àßÎFšIUe`ÑU;((¦Ï =\%‰ñ;b/¡‘ææ‰–dÊñ¯Ýuƒ'îÿb<¿*ªÍ*¬’‘¡å-œ¬ôuéݲF* øƒâ•Jˆ²ž¨bŸÇç(Œ=·üþ©cÀÉýÓ³í¼W‰1qøºfþ͹%÷r¨ÆAL´¨T!ßrnä»;ëáÍ>§ðø§ò6!Bæ&}s¾×šÄ¾É0‹ÑEÿ5Ùú‡íZlKZ{¬¯M.ðc=ÓÕÕ¶Ò0Q̹ìõgmÝ'Ùhê¾"@B$žíPQú¿;]Ó1ÉËÆÐ¬¼ã‰þwç²?S[[ùÌx òZ8gªç[A$Ù´˜G,²(øî¥Æ†#p¶¯p_Ñš.1ÏÑåòüo¨m$žî½]+´¡?̧¹99­fdZEeX‚œy#0MQXúBk‚ϽēÐ\s&`èXÜAÈ%ǪL,0|‰`}“:QTò;à—S‚›!;½×¼i¡¡Â;49!rÓg3pˆÓÍJ”ƒÅ4g‡?Xð1µ¤ÌÙ[€Å§Õûûé'JÒ a&Õ'éB3.c¢|”ðàF”Søã¶d½éK¨Éw~/¿¹5¶WÉ…áXˆgÉÿßùëŸøŒòjLL6xlmÆÒûBÄ!Ô0`ç•4`Z¥N úDUcü ¾`x)™UÚÅáþkÝÑ­Vp–"–˜cHïI+÷‘;H®zEùÇ`ÇH†P|\a6nË’e‡Ðññý"cŠQçɼæìªczýÜ(.£§¦<¼úèB†ýÚËŸñ]ôXpBº=1‡ƒ{c<äÅcÄì_Qæá’’IFâ ðøw²Ë¨"‚¾dyuˆ”W›È+/ÌZR3U?VÇ`º0Vèäo(±Ï…¬Lj86Ù˯®¿L>¿Äfi0^›-<¢¸­Nö3mó[ܪ¨©œ2NmЪC ?—œö‡©%x+4ŽÎÃhêŒØò/ñå±Õ”Uš²ªÎI]ôxg/=޶J˜hödÿ¡û=ìØ7U¯Ãσ äÏJxWµž_×væª ÖÍkÙÒWPÂSà£èÕÑÑTW‡˜¬…§sM¢eñ\\hm³Äÿ1’†ú"ZQs‹#„$@k3PR¡YÄ_Íø”̶ëëªÄåxK† RöÍÁ¡—&nÎÛ‚t;3ñ>“!ŸQ›§Ø‰9B$wÖÈWë‚Íù‡…óBÜ‘&›AØG*PQ)éç‘òö÷úý]¶2?“±jùàxv ` %K&t¯pX»{ 4Ò_¸µ#ÿÛ9æ"wêu4 Šûômㆰ§¹-^á¹òÉ0m‘1ëÝkÀëXù©æpC¶Vͯ ³#ÀÃCxÄ#t»ˆGH–o;tµMÕX];Û-NŒ±ï“qõ±ï`¤†ƒÂò…û<¥òì6”캘ä§Ë~õEWU¡‹eâÍyñÁ”î †¥Úy×È€cwet|ßBU4 §`ÿ¥9¡ép·P_—(˜ðÊp¥œµâzê …g¼%xdú_ŠQ,†[ñÕ$ Ú†¾è‘›¢MþW ÔUÍWò³ÉˆÊ‡F¸5+A³é£¯têÃáM.Õv,¡T}-øAŸØ^›¨ J§à5ŸãKk… !*X‘2AÛ+!BU†õÞú6UÛ`àêG܆8ã€çĦÝ_%¶øú×Q¨'ÈÑ]‘ÇÚ’beeþÓ·¡Û„Òàé¼òŠéQg;rãðlrѬ./SR6±ýÛ¿/[Ùu[x>x°>U3(vÛÓÈÐw§ÌÆSe:*óè³Oó<?®Z˾I‡Z°ïbh*êY°¤H|ÕUTÐÍ4œç õÕ&q\¬– µVV-¢| %“ h§êÍyÑ¡ÏåyŽwÈvâaw4I·X»YTˆú²†×9Œ‰Îœ >ƒ¬Ž› KŒÇGâcS,JD¶0§¿¬;[xÜßDS7œ76\´²ƒ”äNôj’¯WM× ýpm¤÷µóí­h“[»ô‹_ƒc±ë€ûB@…ºxÀXCyþÆÕ=ö…YQè‹Â鯝f1Oß5¬î VëpK@Å1ïWËGþŒµL~ilUMmh9~#ìí,ÛåyLp…z᪈qV’à›H”Z1¹Ó©ýçãê­Áj~0)Ë5w—ʶ»™æwü÷ }…%aÓ³Hº}×?K¨<ñSÐAµò ¸ jãá·Cù)k#°¢›Šs4AñÑ\u?Ⱥî0¯ë›pО›M=- kü,(PLy +R‰ø/ øƇEiñœ¡ è•q½k†æñøký"¥còîËÿ"Â]u±Û}ÆE}uÊ~*¢d—Ô£²†WQÝñxË’A‡´ÆGƒ&Ù@¬ÝV½š¯joÕnP$Á¶BˆaÛ”Ù*ò#{SO ¸ú€ûæx|†{ðe{¶wó%t5ϰköÙ¿;¬p˦v%»Y§xûè Ó$Dz ü%‡ÎÂÿ¿ ,™ª¼šî»iÝGü.}IÓôÁ¾«ß"83ëí’þ…©D2ph~ó@)ɱF~Eñ~æ ´‡”‘ÿ¤U F’¹§ ÄPF[¨IJ±›¸vNfìWVì$â×˳ùþh/‘¦ò)é,—î9%SØ]Ää;Èœ‰ôã·ÈìMÊ'jî¼r0ˆTû`5n0Z w²„¦Ë*°„d]öZvCÏé—àðÛ1wYšÅÖÛÊQÿztË£¤osÌüÅÀ;qãjçÃ@5¤kÜg–¤6á]K-¢;Ë5ÅP|ã¤^¹ÜbëFM5h`½]ý î ü?&Ý1¶¨ÎÑ„‹ž›Äš™¯ù#ããÃ&ÞXØq?½!+²áàÕìlž²lsåóØ–ñd˜mü}ÅüÜ:¼VÌDµH†î…®XgÇ*ñbOÄû7ÂPŠ*NP×l‰ÅÈi¼éã:ØËožrFAþòÉ2¥"%ƒ@û?ØjKCö&И´q»³Í£ônœï&î:Á1‘Ê®‚RJÇÈKuÝÒœ¸Ÿ{×d¤a$Pv¸ï€Î…±Ôuë´\¸q‹Æ,ÝK2(~ªIà NL~èkj„8t\xå §Z Ÿ–¨1,â3×Ï[U·èDy³-ä}¤%x…ä5Ñ4?ä†P–]Y[áéΡŸ¥ƒ„¥yŸ‰Ý åI·ÞÖyÀrf.3ç–Ëä9ŘM?w4¢’±Upóp›97Fq?WÎdÑÙ\#Éá ë)|¶ÿH\uYuR:Òì 콫ïeýy6ôß~Y©µ]´·HOЕwh£Zp/Цu nÏ·¤Š*ç”ôü»å‹á?»Gí$.dòo[QÉH,A2£·JÛ‘#P6j ýTåÄÎk7Õ÷z;Œ\ƒ¨>Ôìºí$œíS.´¢ƒƒA®Êš&G£gEcŒrW6ôØùíuV||w“­Úo_N5æ5y…HùI`áÀ¡ÛÏ›{RÔ¦̓[>M¬è%G5m)#’Š);†’Õ¥×Nàß™\lZýwÕ¹ö•ìÁ_ •Oof¿ÔÞg¯ì_ªUˆƒãà¥=*[“ŽÜÂZCÄkL»Œˆ[ ùQµæÄÈ¡¼q->ðc` g´ö0æ=¼ýΓ=~@cgwÃñ:‡p}Ý@‹azlÍT °öTb.¾g˜›ÓÀ¯&R¯ŠêP°Ðñ`i òæÂËkH§7! éU+rÅQmË¡K'ë22mѬÓ¿²:]ý¾‹Þ<AÐmæF‡æ°´"˜0çªKˆYo©¼q¿BÕ<½V—¿ªP£ö8÷£¸"%kŽ!S§‚Ð"c‚Ø:1£Hë&„ëN¦¥&2>=|çµ¶n“ëlÖ[€{×k½qß”ã9Çx;ìu×TÓ›½:ÅøJ.-méß“Hkþσ“±GYØTv¾ŠºŸÚ‰{ð0ˆxŠƒQ†&N.*óÔ F/¤«$Vm¹û}W ]ÀsCY³Æ‚‹¨ii)>é¹bL Æ€`ãiÅÐpÔSK|ô'MšÖ¸ÿ_,E‡´¥0ó¢dÜã…?-–W ¤eÈZN$í¥˜ð7Gä)Žu)+oÅ‚ì9ñºÍX!ë"„®•þmØ”úÌkÆO¯øAvÔ߈݌¼óV$ijàç˜ |63÷ˆÁ{.}(åzˆ5Lù˜7Ç«õß—§—×äICøÂOØá–Ówñ‰®°Ó¶†X„c|*Ž€÷hE‡ñœ)ìzyO³Þ pÝŸ?µÙ­¨0ž˜!ãäˆr¯Gœ°ìÈ(ÃYL )¦×oBžQ›ß¬NÓ¢ Ei¯º²ª'‘Æê°c¥}…½C¹ Ÿ“;ü/—R3´ÑÁ’Ö²IÊ”œ0.Æ6ŒÂÏNÖ1ÆÿêG‚ÆËQÍíKë¬}Œºl¤=¨¥¡M³™a'Æ0¹¹ÐÈÑN­Ãj+?<ž ,ðíu¥˜5nF*¢ð8tèb¡7±÷¼ÁÖ=·¶Kä+<(àrÁö;yÄ:,x_çqt¶³æ+lý$G‚øþ×þìÔ1ÙãÓ¸:$«%æž~jöiÝÆl’ü¹Eo#Àƒ‚Í’ö…ØUÆa Šª<½ÉÜTBüA;QÞô=R°82ú[dH!õC{Á†) îÝ«dwD.œ[¾@?U ²—×›iœ'yàà Ö,<ÔŠCsjU Ÿî;¹“, FCOwh‡[aP&Ê–¡Ì~KÙ6Ç]Û:7÷ÜIjP¶Oú¼wßßz0øÇ=¬™—ÛÁ 2°0â—eÕ¥s¶¼e4˜òó"×ZæOø~¦›§ñ}5?ÅÏc®}­ §Xm?wÆsPMä}ÇT ¡lè­­dž÷sg!S¹p¾$`CŸŸ¤Špz§Tœ…!)3ÒA Ts .¾ÃKl¾ŒK†Â1²¤[Q@Yvö>Щ Dˆ6ŽïO§9¨Õlëw¢®ÜHç9ýÄË"ÃÝÛÝm9í°Æ ¹–wó•q3SÞ0&°O(ÐCòÔMõƒ&„ê}³šž0+Í„®¥úÙŦ؄˞Í{Šˆk׎ӧƳ3tGî%‡ð,Âk9Ëžhst|Q^S’w ˜ôÀÃólÂDóô¸e¤Gô¦ƒú¤‡{·eýͤK¡†K¸ÛÐQçÞB6ÀS‰||VÐ9K™r—ðšºäYdDE‡s)ñ=zg«bþGFe©psò…'°W³ð©¿=¿æ‹Xè$5fâ>€É'v:ááΉ+]ã@Qû!‚>^óÿý4Í4øŠÉŠ[ŠquÄ$a§q+õQ4…Ú×!œ8Á ø¬'˜:<Â<5ïÐ;8òÆiGˆ÷¦vd¹þbbÀ§Á¦þû¾-Ð÷ʯK\aÐwdø¨Ùo§µ?܃²äYéÀ–µF4®GeÞšêy>´žø‹W|‡­3Apÿ„^v_4VêKXÒ‹¡£Ìm±EÌÓQpÿ“2ýÂU§¦dxãßþ²cÀ/ˆ·÷…©þÁò<)ßóúÖY§¥•CÔ‰jn6R>ádRBĆ÷¦±Vþ Ö ˜ñ„6Ås¦¡¡kŽ¥×ÑœVªdot§&I&²÷­¨еM÷7]‘U4ÝÚqC–²û¬ÌؓIJý»u’|'µ£ økß5xùé¨cj5"×}GÔî;•3Bý%8ò[õ§ÅlT.ô¢k²¤ØÛœ/ûâôIðX„5 ÇëW-Mò©ãµðÑ·»©´å×¥oà•kÀfþ#o¥B"Žg×Ïv5:ähô¿&lmÛrØg|%YØŒ…HrTq æÚ¦Ýs>È]¸FÅò³‰¬Kt”s/Joû‡k¸‰‹z/¨"¬Î÷Ô¸ý—·sŽ«ÑwΖ¹ªøÇ»" %! j®›ÉT¸†¬98°f_am—< FLÒ—À/\ •†8:°;crÞÎÿ<ó5Reä:âkQ½@¾ã‡…®+¸†€·ÜÏ•”®úœô Ê*°ö|ç´ø¸Ø¥JÕ™,=¦0D“ŸÂÏ~\s¢£ø#{‚ÖUoªa ï­ ½Ä/«S®·{ÓS&¬;ô•é´zðÂâÈ»kLÚ•ý\ûTʦ<=‡ÛÕQ€¡œvû9FÅ ²ßÔ'鎻3!È¿•jOãùÕÿ ÿ9‰/£ø]JQÿ‘Úˆ p“A²ymý{œ³¼ÜeLU³w{Ì>³´÷¾h!“JxÄôÖÆÍ•·24ÃýØß Ûà+ް¤áÇÎeÀU\Ř>¥é˜Œ|þá]R JÀåŸ.¹ð-7Ùc“^Ú¼°hìËŸÇ@+³LdÕn 8biScÉ=…ùTï5r/2nŽ×’ÆÅژΤ|@˜ŽJ!žŸù?(½“×4å'í—kÎ:Üýž‰I‡‘DâPºˆïkóu63áçû’.×½€‚nWTSŠë rÑ Ê?wWÉ_­ûÝ"ÎÓ|0h}µG[1«ÏWœ¹<)K!רŸZÜ)ÇsU%T™Aš…1*©³^&Á> —U<_P”D¢ŒþÂi  ›âj©Ó1Nývð)'¿òL,Òߨs”ÿðÖ{“ë·3ÑÁmÍW'5(ÚgßÂ:ˆÊäR©Aé¡#cŒ£-äFödÖñÌv—>át’jãÂz]•=µ·‰X†Œš×Ääæt™ài~Û[Qø€¬{ÊcˆÈ§ó|¹¾çøá¬ÈÖöÝ@«½Œ¤‘\w'®=héul7ºI±:LcYŽûê£i>Ì–t ˜š©!É4wà `Ë–Ÿ£ä—ïàj©$þDS׉a8å,¦‚¾‘ñŽ ÔNø¾g†½ž\¡³Ò ’#õ™'ò4i!%zZsOØxê¡[|¬ãð’àøœ U”~xŸà؉g¯SXÊ7tsGzdŒßV-q1k ÍßHWw¡,¼!fÜd_ÕÿáÛÉ;šúqË~¹æÔa dAµò¥¦Ýá¬à°)/3É"®Ç-*!…ñºÈ0€]Tš`ò¹ù&ƒÌã§£õ;yu(œV#ã1®«ôK¡8ö]æºÔ0ï{/Í©R>S£ÄÅ{Éãuá´.ÜO:=b Íx·Õå>Å/ã™ñ§Ge°Fùï/8˧ŒM¦ƒŽGgƒÁÉ‹•m¾ÑiàâË….½»öôx§‰`óûJ;9ÚÛé2בÛÆÁ'Á’OüS΄J —‚y&ù›ÊèâÆš·ˆ¦:lÖøTvòÅèÏlxÙˆæRALuî Je¯¾s–Òg”òD2Ö·Ý?~ì¬éhª=gÍ©ÿä<•aÆI{bw™5–Âoß¼ñ3|Ùn?é;¹ºcÀqQã]î7^ÅdôØ"ÐÐ:çšAìð]€%Ødÿ  <ôÀûµ=Î&ï1¹ß0î ÒöÙþû"nõ¤A=ýáJÉ•œsÈÊÆ¿t£­øÕ÷ÎįÑÉ×|=0nøÿ'Z TB]]ÐûÊ$u[Y&«ÚS)qvœ›D`GÉîªêŸââx3&Bdóè–;léA­º#N¡G~®Äc1ӂ⿚•}¼èÝðð(ÿ{ÈXÙ6î£Ý–’1Ì„Àf¡föÿÈù‰eôâÜ2Ë1 yfhÌh5]׿¯Iû`ʉ0µ^[O´À+)ÜY_€êZ_Èã¼U¤ŒD´RÄ8Wª6GŠhïAJ‘¾è๠™¼JÀ`âÄm9jû‘¿®¦Aàämü¼û£é »ú|À¬÷"ÿéÊ™üÈQp´¯ÏœëF¥ÃÛã3çÎ>\¨½xw›â©ð†gù+£çZƒpæ/Ïåÿ`ë®…ŽÔŒØˆrzñ”^wÆ ×€Î’ò$ˆ2f¾ùVï¬:#ËÉOl#Oß‹PIË»?°X^˜ã±Ö8µh‘#ÛéÃ⎀›,# ŠP|ÎEI·ÿŒÐ½Ùš%•‡ÍøpæVxSåÁŸë7B£#ˆõ°á¨Š Ö‡ÐÎô©ìߦǘ¸)íiö¬”´n…¿¨DIWŽÒö¦ª P*Ãùgü"Öó¹4'OuIÑ|û’™°PWŸÅ÷Ö×*æb3a{M2ZªY_úàI8<ùÐú—¹É"I剹ªœì)¢_‘añA¡šaú£³95O¹ÔÑÆVs¼ò>rSêOg8.²Ãâ¼ï”Jú\K[…†íöí42¹“ψÅÐÁÁ†m øWýê½R[£‘èr³_­ñ™¿­1=°šÂ>ÖcØœC½”äGÖæ±ê§ ¯ìÌ´š’g 0þ–oÏ.µæù½¬íWdƒ-:çqþªu„>ìŠð*“S;ÃŒ~°w šMœâ• hý2’àäB¬c¼rÝIÏ›CÍÖ› ¤¥Áyª>1‘§<'äbé>5µ™’ÉÂú+úÁ÷áüàÌݳxu¸ŽâqnÍÒ„¯3 ãd°ªà·¤p>ù·v1YËî²òGŽ@i~¼á{‡®Õ%Y‘d+è~Â>Ôœ*j8@4‘ÏÀxr?“t™ÆD—„I‚1 Èv.K½üb†*£¨$sŽ¢ŠXÚð–$—§š#E~K‡dE–è¤_,«S;änÁé˜ÇÓÈOö÷‰ QìÛ7µîü›ÕY^›€‚’«Gåº.õkÎÎdZ£|(Ó¾áô¼ÍvZ‹ùJ³¹L‰ìÚ"Ð;]ÊXà3ùìè$Ã\¼ë2‹ÜB¡ì ?ŒÕ¬ï ^_K‡éa?¤™•6"OsÕcd•0MëÔ gµ‘cA-¸L¿S(ýF– `AÓ~c%iê]àvÛÖŽ êñ¸„FéŽ^)AqlpÁ{ú-Ó]Ðþ¯,ßã”}t@¸HŽ ¿ß®Òè•f[¨{ýáþžPQi4 {#.gþÈð¨ø=(¬ÆC`4•ìsÕ<¹êK|Þ—ÀG‹%1"Nö]ëAT•{/jg­99d_ýÒï|2µb)9^ñÐúM÷;ùû¯3ÁE­_Œ_[[̈‹KZöÇÉ£ìc¾?\‰2çAV¥ nå8?¦%퇟0e!éÔT ½ŠýÚ,ˆN ö?é8€0~„o¯UÜi¬4òäï,’ðËšõ ¡¥>’á"ÉRuãŸ>‡“¶¶aÀ’`¹å,¸Ðo%'ÞÚŠ[͹Û$iʪkÄóûâ'-‹‰]3„ý}WrFùçcZ˺óî^©„HŠÊ$ÁÍÄÆrÜ-ï×yÇÕWœñ‹ÔYŸ[ühª3Î_Öïºbà6SƒÖúÁî½QáÂ.]¥Çgׂ~4™uCž•®^q Q®úÈ` ú¬Ð¤ßÖHXo&<Ö»evÀ{=H]úÉ® DÎ\雸C¨õf®ŽGS•0˜ó׊}®<ÐÒæÐ8(ÌŒ'‰Ñ<üL XY1³†BZÖØóㆌ‚b¢1økâ‹üIIö‡Æ¦…¢Ê±=Èeï.Ü:š1±äIL~á­] ÷•h¾}*Ô^µzKÃ=ÿ‚  ŠÈüÖKëq‚2`PÕ3ÁØvZhÃî{ž°§î<Ÿ€Tv@KÜÕ®–ÆZ&kZìh½×‡Mj´Ôm8|À"0Ug z®é•Û²nIZlúºI v6ÂRR§˜õ@°æŸ1ù¡ø,]±û²x#º<(>zÞ¥€P‡âÞWª«¥xÂcüVØÌ¸¤¯?UZ$ñ¸\ÉZË \¹›Ž¡Fû µ¦{âà÷A@̱C¸#œ™‘œ~P2†Õ³Þ`Ïœ¦wWßþF£%×”“«æC0…ü <–핲küË w¶ KuÉY±v¥œÌ-¬©LÂ#Û…­Ñ2 ­†¸ܬ_òèOL&ö™ùÓt$ÆŽUËNÓŸAO#«žçúc˜‹ÒP]vYð};*•îžâ²QôFVT)¬T¾M¬+A•=°bFé!·&‡c »gÙŽ»Õ¹‡(hî 2-5Ýò$Ä¡\› ½ñ5²’¸—6eožºôŒ™íž )äiÐÝ«’O9ý+ã-oæáÖE{ rZ F±L¨ñXÁ¼J]ùT|6åÂõû¬Š6êâž6ÍOιÕU—èEÉõΚLÜÛžç˜(}¶™ã¬ Ó*UˆË%7»$8ÈÙD½2õ³Ërt·˜ÿ2³¨#*ÀA.”"×¹C†¯UïPr¨çõåIõ{ Ëûo#e'6ÝDW>::/Ÿ¡~ÏÃÐêXvèß o­z(G˜ð,bqs&޲“2Iy°É5IæiJ©ûàa)ÈöyDaŽ“–äGüyO”A´a2ðü:¸ù¡Î¸¦Yt€˜] £»ëÆì‰Œliâë_íxP´A—g©ñ( 2ä;ÅaM‹k‡*®®}–t‘=qÊÛŠ¦zŽ»"1ÅãJŽ«JêÈÕðë?Hu{€Äí½|dŒ}Írø‘¸+XXn[qà­ÈiA7H:¶š—¸æÙª›ÞÀr÷´ê®?ü|£òÜ1 gTK>M ˆe/î¤;ü¦¡üª]œö¿ä.¾½8t‡Ÿ×çab„7ùé® ã;chk AÓÉQÉ!ŒJðNšÀ•ÜF¬ ý’›Øä„ÖRŒŒ“åÛ¦a0lœ¬Ü!îWÊ!ˆÕ•ÓÚ(îwýñÊHmMñ"à°û„Âk5ýŽ—JW—Ö3"Ö"r'º¤Ç+­J* ¿ëÒW4|ÿô¢Ú›D¶•ÄëA‰¯o}‡Ã¥‘8^ÐG°°ÖRÌ™„øããª2 ÊQ6~MAƒ³iØ·)D:ç“0\H½+C´ëÄï?„Ë/|ÁÈ)\(1!v6é—:5U„ ˱׼¢ƒÇê‘?‰\±KRÝ7p›ó«‹ãSÛâ!Û/€vn;âݲþ=(½iacÉ3ÇE¯ôá÷D|¡ Iè‰mÚ5¨…̾X3-?;вy6P…f¥´‚,§*²Ñ.OZB¬`ѧØ«¸Æ=jiÅpL÷*›=,QBŒÛØvAqþ£¨žyÖa\íS’˜ävšûöÿí¡¹§¨‡Îó²ÞÝ\?, ç’tE­øe÷VŠS ”*Á‡H”Rjšìç±ft›\Áõ¹ûqilÊ|/[Ÿ@>š¶“â›øó‚³”/ÄfÄéð9ãùÈÑU³g:KÀÖ^Žühïb¼†¼ÅÒ+«D¦Èógݸ¾nOË)‰K/ ÄpöUÐ êÛÇ„ÿþy;OÄ×eé°5©;'ê¥èI©)t;½—Õ»¹)1Ó·+IwŽÃ²q›é2Fò„·Jd¾Kª4±?$j¦Ÿœ€ûÛ¸Õ¿Ù¼’•Çó”×J~¯'Ý9… ^ñ|žWN'Þ8_MìÌÇK—ºÀkQwÜÛ䉯g¸9ÕÚaŠß:Ô¦È3§‹î«Ÿ)mշ幟µ*_¨ìrþÒd. PéäŸô_-ÃÐÉܧ\ÂDñœGýºH^£?­›Ççøp××VEk½µy‡fºŒÛ€Œhr./ù³ujM…W©È¾’8ûGÞ¬ÐDÈî&–ÂÞt¼ ÏŽHMS²¥æCKï÷] c}–ò{¸—‰Kï KmbÆ»ççÎ8؃YQ `)|Y‹¡’~—B7åwü¦z=OIjÎ_R/R7³i 0Òèi8 —a²ãWª[„b^&Qq“N×Öå„§I8®„ÊŸZ É?Ý”DÕlR®ç¥Td\†ÜjÚ~ÑCC©©xì•Ï9¶CP‘× ƒŠä<ToYyøÌ”‹Zÿí­%yÈ/|ˆQˆnù™èy]Ë9þؘ‚öÒá Mn>–Mó:‹º5da\ý i´RZô÷ßȸ‰fU ÑÐ×;ÝVy^yOÏüÏõ ÈjŠk›ì-™ÀÀ/÷ìHŠúaM¹`=Tj •·ª n†ù~e¶.&#ýC®~\SÔÊh@¨ÐWîåœúk2EˆxV}SƒîÑÏz°¯ù?˜×,{Àdಘ$Ïñó àGrºîî?ÁGÕd‹ìT<Ö¶Ünƒ|ÎêœJ€þᥠEzKld±á—HÚY. §À(ìõ¦4ê®ã3ò¸°Ú£ æ[& ÀpÉÐ5”’ˆYßáìA`=ðBÕr‡™îƒ[„ Ê>IÀŸÓ†=hT½²WŠ€tx[„[@‰Å¤Š¼¶l ©úój/kÓìÞë?hCí/XÛ9Y¿ÉTnÖ³¼”=Ðb‚?Ì^8¡E¨%¥ErTa ¿&g(¼¼p¤È†×ˆ\ `Òß‚Z¼¢L˜pÿ q8ŠRQlçòá××0ÒJ\«õì“+Ñ’W_þÎÂ(˜pIæ2Ç«ëw£Iø+2šŽá²oiª„Yå!æFG-ÅëÙ﹑¡Î/î÷éÙ‡„rmaX¿4Ó~WdT¶;òPsѽçå™ÍHxË*ÌL_×§C‹ é}iE|f¼Þ7µq‹ãߺ‚²Ï¤¸V\á'*n9>© {: çÝZ ÎÇA _6LÍo0ÍàÑ´çX*Õ^€Òü ߺšC=1æ¦,FU»ÂrŸ ÎÊüyâYxº&n}Õdõã<”4PI‡$㛯ŒÌ8D˜—9hìƒC]³ÅÚÎûÇã»WÀi‰ù(¦-Oól­kV¿ Óíïö£!(£ Ùþóº±ÑbÉá8¶n .6CjcŸ¦MABõrÇÀ6³1¸©r³²ï^ÁÕH"Ï“‹ŽË¨îä9WÀÁgp tà¤x4°78-Jj5§Ûr* „Ey­î!ˆ㘠‚ÜJÛŸ5ï“dÐ'a'£Í¦ùír/îñÔ¤‡^YËmYôdp»p›^uwXß—fÐY3Ô긆EÔÚA¯ê)rürñóÊ |OýûýÓ%:õ ýŒpÄB‡hWlÍ>ñj.ØbË*#*”w7) –eMþ¹Rº')u”c|êx/²µC]ejhW:,гn­²µo’Zæþ:×P>ÎËéœøa‚M r6Ò·OÖçSR홪VüïxfWf„ü qVïìÄ£VÇï_ˆfê°þ¹¡_N ÀŠ(»DhmPWËï†ö°»nŸ<0uöM1xgR'@7}Ö ‰)#+Q´V {ú¾(‘GŽšL.ô’éüÜiÍ+ï/ê0 `®Ê%ì\¯ï£Ø—}iÜ)ŸP³=òÝá$)á¾ùX¨»½~ˆ¯9,°ÍéÙqf•š|Ìè½rv)¸~ÔŸ]'Lß/ø{}ô£.²Õé첤ô Ôܱ–HÔˆ‡ýB 2Xf?4æT‘Ëâ3ÛÏbŒß/Ó_ŠFÝ”|;ÎHMÓœ<('2â¥3·Á™š2ÔÄÑžj×aÓ©)Ç’ %O)‰£ùÈXY £‘FR@?;lnŠUøÿx¼&O ¤,h!£±88N¨²VVކ¼n> J /Oú=žŸ[pFËüeõ`ˆ,#i©ŠëŠ÷3h¶A³×ûRbà’2-hÆ_,½Á[NBU5<6m3È2t¾®5·¬q˜ðœNÕ;­9ޏhŦžFž´8VðŒ'‘ À‹þ¹µÍxö—°©¨ÈjNIhAºÀ2 žÄ>‰çêÈ­‰Vм›B!c°ñ•‘ ÜpR ³ ãÈChêá$lAiàë­À¡üófŸàaÙ¬8áQÚ¼ñv(2¯F˜º‚zv0yÊÁÚúåËlæW4¢…¸ ®OÓ†¦$žÎw/ÆçWx]×ÃÅF³­§*³´µQLÏŠµj-«Õ#+k½k8¨‡‘hJ‰ŒÎØür!(>èË*Ø´¾Ym ö±ç轌å˜^üV´Wfãü$}ŠÔñ\\‡ËázQ»˜ù3dUÿHܵÜþk%þŠMÍxãÓ=ǘê“RèíØK½æ>ªøÅb=:`'ØJÊÁr;ÈßÀdùZ†©dEÙºXÏz1³€Ó~=TúQG7hÐêžzÉsíççüÐ)„]ô¢ó0h.\æ±#ì‘ò°7K²WìvDo’Þ@’ÁCâu‚ºÀˆþO0¥ê¿%îǼÁøåœÀpJdÐc!Dƒƒ÷Åzø–Ñ0ÛDâ‹7hÿJ³.F_Ö"Ä@üÄE»Ûö «SxF7(ÔÁPŠðñ—R)Í“_fΜ<+Ù[Æi*Ïcù¥áÎŒšÏY ”;$)õ¶®ñe–Øoscn&òù*>Û@8FcÍfØ5§Æ§••IcÞ³T1:Z{ Ï›Mñ¦ZÃÒÙwRßSŠ9Î3á›pヿ »ËݛƞÍÙ0m#øzè¾iYµÖá›´ Œ ²ÿªí,C?.uwÅPs„°EÊ'€éÊeœTê§x|’òÓ¼ëìÎ&Ùs2­Ïß*`ÇR·ÿŽ@EúáoI л[Âäê@.Ígÿï‘z™Ç{DdfÏ©rž˜çc:Ú§Ž— 6çAgÅÞ §67Ÿ ?ˆûi—Z¤¡—ô/Ñ.3‚c¨áSœè¸zò‘u^.r”ÌQ¨‹¼&¥Œô?Ú,ÛÒX†tR¹ª.$–ÆévI æœ{4óÎþY@5:½{™X-Ý3X()¸n¤gåÕHŸ-¦•¸³[1Î&æ  ž&äðõ‚Då5xC­>¹áf¦ OlÜÑ—ÊÂF«èޝšWÀ“Öõ›‰l.×>…++ëkÇ÷׳œíì?’a”âÜx0ÝQÝ|ò¥¤‡¹µ‚·Ãœ¼«Õ¨Ô!;(^­Š“Q7%ñÅ:a«ỸÖ`*;½TàªÕ!“íCl’¾•d¾Ñ¡œü qˆåœßn]ãÊ5tbZ‹¢-W»íêÍî„ cÛvˆtkèæ²¿ƒåïVç:$ˆÓî°&O¯mJ KêgfÚ܆'oS­×7Ážvh„g2iËñïʲh?­åò,^®eN’°©3#Œ7R’‰°Tç \°¶Œá¾Ûh\µê, ŸÉ\å›~„@°³›Ôœá³o©2>à8£iy‚Ïš{öGSÏ¢ Äɹ‰öün‡íÕV£…)¥Á¡»f躻¥›A`ˆ!Dî”îFTRjèº;DBJ¤ÿW8wgýßåþÖ¾ÚÄ7iÛ‘ÄÀümøOLãÌêÍÀââ|òý˜Ä×Ô/ñ‘I6³Ï!ª3îŸZ{¦ßˆÂX@lJâ’íC³i¨oƒ¯KÐJÒÚr¢|”–£tCã'ß3ãkêó¯TŸ®Ë3b\!a ¢m5ü,D/ÑÎ9qˆiKùvèXÜÐK$W$©¹iXÊ¿£Æ“³ÃÚ/¨úÆÿ6õpQÚ×i¶©.ä.ÙfL~Eo@"áUÛ.ª Œ€­¼Ïi’1Cìáֻ䥜¯ß© éŒù©óÈãý§2 Ö¾¡G"VÇÙˆÅ0%yb‘ò›™9Jã5“GÔ… Žù¬oÌ>;¤@2Hp³.¬îŠI/?ˆÜðñwïÁ€k5¬ÀJ}¸åWçåÓV²,¼þ·þ=—ë#•u5–J/›x~¡ fR,ñ΋F@Eº[*#ì”ØÉ=ÿ£²UO’`öžñpmA›ŠPÎÎñ£»F²å…x9ÉsþûNn[¯Jª= ñLœ¨ ûÀÅYÔþêQÞ&*X4®I,óô0F¼åÓ<«í%‚šX«PÅ‘RÇ%®,Ì&asêœW£Tóµ‹t=F>ú™宇êüäE›ÏKÕ°¡§ûÐðzÙÀ€~6¬/O‘V—Ÿ€T¦pF Ž£›ÕpLdÒ¾‹mÃÂ¥ã¯û¹|Å3&Tœš†ª¼Ð~ûÖvå7Åv»ér—T1íf1i~NÌ3&c²TY[ â"=³Y7‚P(Ø1J›\û>‰êi1K„3"Ÿ¼ú™‹ûÙh.Íô1·€i¶ó œrË wëö¶ÏŠFéžQ“ã,³Úœ‡<Œeþ#ÕˆiÜ&ý´ :¬TCKýõVáàkµŠæq–Z#c…-Š”|UMÂMÃmházÎH14­Àß/ÐS!$¬­f~“ø@½­²¾±µq-²; Øé‡PUOIKMRŽI%2"âÝî4å–ãcd(ŒÚdN]Ççþpt/î–¹wñR­'½D9\yžÀ_~‹bÕ©_^h‹d{šC¨°xa`u«n½Ûhg¦0Œú»†åã\­´ß؃¼C*»äÕ^f×¥­o¿¯3èHÕúj!®Ô©õ¶>1Á¸®žD\œë‚›wò}ò¶{›"¤¢•Ž??ö„ ©KA¼$9§_äö0tSöKæ>@Ó¶Ýý¹E¶EÛLPpá#«3c™=ŽY·û8S‚­_˜`”P؉,9euÔ©±?å^KP_!.Í:·ÙÔ"ý½bŸc KÑë)¡ÐëÔûà Î(hwË«b!xÐåó©Þ¯rn:s+Õo‚‹ˆ:2;Q;ª{b`­ÞÞÛPUbŠÑ·ô[ Z*FUŽ%oƒðz]_H ’k¼=osnÞ·W¤Ô8—V=÷† 7Ú½?6oÚ™y C€fÚ›-êØníÂwª´SH@/¥’Lå7fÛgÚwDÄG=°pÉ2ãkŒÅ?²Þ¾Ó30ÁfO Mx#ýƒÿ&œ? YM¼‹Óu‚¢SÏÁÇ‚#VQ´ÐS3Ѹj·ñf¥ÕÄŸŒ ù¦;s'˜ñØ/™Ñ„j±ÒW1ùH¤Åÿ6QЏá(¨d+Î:€:ïF—“¬fƇÖc?#Ö‡pòJ”ËìK…0UÕKrÑ΃1]ðœ 0‚^™$VÁêÝχk£ÚÙýWl"„ñéýÝÛbÀÏ¡Y—§gŽ õ¿|FŸ|$y8c»Ýš‡¾äwÈŸ[T—„®ýY#ZTøÍú£°»ûÙä¯È âyi çàÙ¼ š,eJRëû±øùf¿cÅë,KüÛ_”>dÇÏW –êWá #}·Ë|Ýmnú»OS©A¤ÞBe< mXμ7h>ùæ&"?¼b ­u\éZšÂ­³}>Š_Çö&I­ÙÛ\.åxaÏ‚‡(ÿøA…IÎ\:ñ-Æ»Sm>Ÿ«oÏ÷8 ¤Æc)ÿþNŠ¥)m½@®‹6¯8êùO¿HQ¿Ñ2r5³ƒ°ï`Ùj~^fÃP}_B};wáSÈfq5x ªÖ27dã$Ò•§0dyi†{Èõ¼±2øÄ•0_z Bï,F}àxM“/·!µ:©—5"É+ÅÍßúqý«Ë/ÿãŒo®Éë‡OðÓ¾ˆÀxl'áýU›k§/£Àquí¸}SÃÅÐnžè³bR|ö–^û·&"é`ÔÆðÈôÛ«Õ,"<Œn)`tdÙ@³Û:;èžîg¿pþÌ¢LN´y÷#á\s»ÁíÈA凛„Ý€[5ùÐ0ÿg­4!*S46n€=ê“ß$6¥:ÝxbɃ>{ô¥ÊLC4(|y.O8®¶jGVžx8r¸q2N,€ !î,0jzúûÅç­Í ÊÕ5¢j‹-×Ùë®2.·òl ElØv^„¨: ’¼]? É€U‚Ç3Å[ÇqL;€U9z~j†_NijH{z@1sª–»¿ iå$Ó‡«¥üù­ ½ Âıýî™/ì#w?©Nbê;Œ'!íÉTq‰Ž a]'¥n¿¼œÏÿV“ mŽ•+ÕsV Vü»+'=ß:æ”ux7 7]´Æ’,ªl œq•Ü5N>í P…{\ГKÝéˆ ' sþ)Ƕ¡i#-Ӏà õ9dÐJs†}RjKðI·¿|°–û¾pÞßXcÒ²/òÒ!VKwý­z\ŸQ«Kl÷Þ2àZÃw±,g¦rÔÀœ²P‘BUÈN=ÝÛGIðØî1'Fjâèõ7¯¶7aÜuÔsà ÜC¬CŸÖ¹‹$á3üPÕÖ÷–;Ád.ÛªJJ/=Ä–åo‡Ú_®až· Ö§¿–:UwXK¸1Id4ÞzÇ t6µñ$Mõͪvµ–g…Ypñçä ±+Ü^˜dÁRBûDÊ—¥œž““®×µ±8–쯿ô÷-”ˆ)¿ÒŒC‘G…'†‰žn$q'®+„ÎLÝ¥©™ís˜zìï[I½ISí¶Á.9còš¦ßÜѶª²À柠’Óö>ëC¸Æ¯‘Ð~ÌJ_ì÷sMäý±Ä'÷­›¿d¾›XlrN¼½ó謡ÏcÓ D0·¼gbYËî£×Þ²ôK±_ì±âÆ)þ†)9ßâ¿a³NÛ \f7@ás. °¿N|Ϊ<0u¯©jâ5Kõ:ºÒ¤zc«te(%ôºÄþq r ÷Mdˆ{dq€•}ÙoÛOiüd à† € |±Ö&Fx_ÌäÏ˸Ña…ö%`V›(ĉI+óöŸ(^).´X9˜íMÀ žèPç7{­áÌ8Ëþ…A½v¿€ üGÈ› S+êé½¹MGôs`BÚÚ[F9O 'Óè<`þ=×î4La7² ÎÌ#·3»u!kü;¤»óŒŸsÉŠê°MgïÂdìõ[° _ 5ŸÑ3[]îªuÊ+hâôo¿w®j/éG>hÌrº?ñ·îUYí+õ¿#ôãT›3Ïx’&¶¸q[eÖ¦°4VrË’è¹EªXÆbÏpúËjá›ç`ÉDÿ‹×”Œ-4\¯ª"ÐVMÆÁKBþM)µøŸöÄ3èŸÞiÃgî¶Ç{¦*Ç°ßøk̃¼·ÁѤx2ÊÃ@*EV¾ßó,Æ¡^–3ð}ã‹€ŸßV].^‡GfÊP8†­Ç¢ºâ—wžaÚ2°IöÙÑ»¶\kåK{_úMÝŠÇ—6›Æo®L^Š$ç]‘ ïÑ‘p-NÞî‚ãïþ&È8ð ¥£¨dDÅ3ùp¤Ü¯ü?¾ÀÉ»šºïûM¦žGq'O7§ï¼ß}1ˆ¸cP<¢gÀ-ÞeÑyÎùÞa­irxñ©å,¯?c×<:e¾pSýSt7ÈܺA¼÷¨ÌÇé9=û‰—"øà¶ò¶Gú…/¢ í9äÛ äæéZ„Þh½J¤±¾£íÌI 5¢œÖcÀÓ|ÓQ=HÀrLò%ûÛéçœ<º’½å»–±Ó—µ†­Å ºÐÕ·9f¾â35fræ‹ضì^Ÿ†~uÀÈôzÌ|´~{õ©Û;â~ôž'8-ñŒá© f."Ãëäjˆºñï¿“4Í«¤ÒáâYF¿þ²hÏbp¾Ž¿y™ky=™´ÑA”-èG/»‰™ÎIJVh2¾\§Óu¡©ðßm–ØïÙB.0Ò6ÔJûŸÒ^;üìÆÿ/óÿ€ÿ'[+/Wg+8þ¶ž^®¶ïípþòý1 endstream endobj 90 0 obj 70700 endobj 91 0 obj <> endobj 92 0 obj <> stream xœ]ÖÍnÛ8ཟBËvQXïO HY²˜é iÀ±™Ô@#гÈÛW‡GÎt‘øˆ’®>R4éuw¿¿Ï·õ?ÓåøoÕÓy¼¿ÞòËýøtÙnWë/ó¹×Ûô^}ˆ§Ëcþ¸ZžNy:ÏÕ‡oÝÃ|üðv½þÈ/y¼Uõj·«Nùi®ó×áú÷á%¯Ë]ŸîOóéóíýÓ|Ëï ¾¾_sՖ㆔ãå”_¯‡cžãs^mëzWm‡a·ÊãésM]óžÇ§ã÷ôڶ¸¶®c½›sSòü1ç–¹EÌY˜Y™Ù˜ ÙçÜÖÍùŽíwÈæÒ™#rbNÈs‡¼§mܳ½G˜çnýþ@€?Ðàôøýþ@€?ÐàÎìÈôøýþ@€?Ðàôøýþ@€?Ðàú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_á·šsõ~ƒßè7ø~ƒßè7ø~ƒßè7ø~ƒßè·RŸ~ƒßè7ø~ƒßè7ø~ƒßè7ø~ƒß9þŽñwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßátF8#ÎHg„3ÂÙ¶ l‘Îù+Ú²rÉæÿ Y,h6¥;ÑÈDt8. Pi|ñ€Fv ¢±+íåK÷ÌèdD†TôÀŒg¥†u€NmÉ-^F ̸>-AÍÄNèÄ…²,²éŽuð¬´aÆ`¥Å‰ALt&8eÁM‹³<—“#artË„F{ÇN‡® tÛáÞ®Lˆvqè”ípvÆv¼øÎ™Kû2ž¥=²æn±•ö=Ûaîzf˜»õ1þûå‹OOgñôË$@;<«) bÏwW<}ynS—~y.®X§G¡ô¥)›Á°ÔÁõë ¨3,uðîÖÙÿdØ@±ÃÿÚ˜«ãÛ4Í›rùPvcìÃç1ÿûKáz¹â®ò÷pר endstream endobj 93 0 obj <> endobj 94 0 obj <> stream xœœºstd_·ÛéXÛ¶m۩ض­ŽmÛÛéØv:Žm¼þ]}ï{÷þõFÕ¨söš{ͽÖ<óœQ»F‘+©Ò ›9˜%ì]陘x Vv&n.ªÆörô*@ 7Q{3À_€Žœ\ÍÊÕø΀#×:»X9Øóü÷\Qg ±ë߀˜±ëß5K7€°›À`fãaûûæ°01qþ÷Dg€¹³ƒ ¹¨ƒ£—³•…¥+àNTê*šÔ´´tÿŠ0sssL¼þˆ]¬,ìÿFð7ê´up´Ú»òDÿ†mm­L¶^Ž–.c33 Ù?ƶ@€„•­•££ƒ;€J”úßYþÊLÿ÷ƒŽ ´:ÿmé?ÿMÂÁÙø½0q²°¨,]]yÍÿBæÿ@ .æ ö@WÆ¿œäâöf¢vÿTã÷O²˜•3Ðôoó^Œÿ—ê6öö>ÿ'dneoöÏ37GFu{+'7 ´Ø%ü Áý+ft°3±0q3³€N §©%ã?K«y9ÿdþ'lloæçãèà07¶uúY™ÿà|\ŒÝWg7 ŸÏÿø÷33ÀÌÊÔ`´°²‡ûûß0Ðü?ÇòÆ®ÎVž]&†¿Z˜þyýÏ™þ_˜9ØÛzýkº‚±ð6þ?SDD<>ô̬z.7+€›à÷ïlÿ£ÃkðQ%c«ÿª‘é_ŒÒöæf¦ÿì寈ÿÕ€Ñý?­  úÇÚÔ€[ào•®V¦À¿®ùoê1±3ýµåßóÿéÙÃÿǹÿÿÌú—è?LÿréÿªPÂÍÖö?¥úOE%uÈþÕÖØð°@{ ÙÿÎ4¶³²õú?rÿ×LMàÞ¨ÿÅù¿™Tÿ_r¥]ÿ6'loaû¯˜•‹„•'ÐLÉÊÕÔò?}ø_€úßòœm­ìJ.VÿçaÜ…Ø”ÝéH‘y«òbhU˜”-7«)\w÷ç˜j›úh}<9tº åðWk"4J{N /TŠú_¡$Ûzþ€…¯Ü+*žØŽ{_ø¥ÉÝbOT¬Y˜ QÐÑ︿BCIJèù°óûΦ4p«SÀðl©¸Û×­d¬Í®»¿$@09Cù€[¿üy!SÞSc&×GBÔlÅ‘DB9ƒ^%¦„e¦mm(\¢õBTWF²X²|4u+ :ˆ;¶Tg<ÛHý©"ÞÅ|ôËh¯ óû]÷)¡Œå— `.ÔqU>Q’¦Ì­rÛúó*˜ôõ–Á5$RÄ9—0ƒC=ŒLžl“ãØk*ÈK8Mk«T´Br>“„$Zq_ÛErðrÃõ£*)(Y® _FûÜÈHªõK•ÎXÂ]³Sƒv†íÛT®=«_~gÔ}wB4!H Ø‰=AŽh;è¯Ü 14rH–±^IFëo)¡q7íðÏ\q¿sáºwS»LܼÜÕb àžö–+²y+MâYËEÂŽ ·“¡<Í´¡±Ï8Ró x¿§6YŠëÔ‰œž‰ûÙöºÓÌ:ÄsÉ;°È\šA~w2˜ßTi2èýz‹ðly4Ð}Çýdº¼®tª­Î~ºÎظ„ÍØ0a_䌖(½Èž²8Ã-±æ[Z?mì†ÐZÞË7ì5NÌÅå’pÊÅ‘_÷#k×RÈkÕ:~¢rœ_™^¯åN¿Ê\elo¡å=?Dì€Á§S…Ð\M˜á U£´¾<ói/+‚cy$¢¦tv¬žÙ¤Âå#ßóƒR/嵤^ÀÎUñ€1(ÚZÅ‚ß8ÓŽžE.û.[¢»­Ã©cúVõVœð …«_†Ì~»HY³0CE ³fOÈ.Tg¸s”9P«T‹xóçE6{äó“f©aäZ⎡æý-'ùÜ)YT49»°wÜ”@ øN–Y›sÀþ²±Þo„*¢½•[a QŒ3Ó$±Áîõ»ÊNÕWžïO‘˜FüfI¬ ¯+:Ç L»óñÃJ/ÜãuJC*O†° y6¬HEo0ÙÚ2ø÷ï)JχSšÁÇ‘Ü%%ƒ†ÃƒŠl‘´uEŠ—]mí?AÎñ¼• Ú¹À«x$DÛ”S npÏ(ÜHcÔ&K±Ö@;?¦eé,‘RNû1Äs~N‹@ÑÅ’ÿ.”Ï.g¤JÑëÕ¼áÔìqÔÙ«Ò¹K¶d Sã³äÐ*\›]~QcyÊ8owl¬nLù ½waI%ÄÄø½óDQ5Ã.hx—~àô/ò—1Lz“kJ°÷ÀWÆ‹j†„ÑB#ù×ø~¬ ¿x $70†Î`wyégü¾É8»T=’0PÈù\cÂ|]<¢h·íb÷!tÏt»¾Z2¤rëRbé0q¥‚ oB]—¤le¼»ÓuhMàÉLÛ hFqêHÒ©úHd]ÂÅŠŽ5Ô ³Äýž¿mœÌV2-ƒdtï>ÛÝ;ņA™˜áå²~n„YA·&(šû¯ZïÃQut§ xžNS|ks”Ú±K°m9¿x¦}þf¯>Ò·‡;ê}°$šè©»ÁTÕ×ĠS4‘dPÕƒÁ¦SÕzq)B}Íetw`ôXI¢ ÕuÒ–Kn {ÈXÂFËäxä¡ÙP\ȃá5ÇRg1·Ëù ñ]â–h@-ʧI™}…ÀJ½a>y¼ÿ%„†Í5¡©ô¸}o„ܵÜ#Vñ¸.a‡ '¤aΈKM$+lº±âÀñ””ƒ†[ÅÛuÚp誴 Î˱™.üË!·k&Þ÷@W*nì ;•Ý›™¨Àª¾^ÇÝ”ã˜*–b%ümWw~qåÅÌf1=m„/X¦–£•-¿¶°¬}³øQžÁì‘%¹4_·"É;Ç£@d¶¸¯W<6Åy7Ƭ.ÿdzgdL{RP»ˆÍÜ|rÑ©¤àËLŸ§h2$^èÏQö¸{Ÿ1 ý=`KJ/+–‡¾ñÂ`…¸ í>¿zPKQzYf`³)ðƒq—|ÿÝ]ƒ7 Ì®[®Ñ’Þ†´æå,ì¸F<O${›FŒÈåÊ Îz7ÊkpÌ9±2Ívø©}‘µhƒç2#%烽ç…a—ê‚ȹ ûã\îæ†Ã´y·fµ&ˆ~Ræ#}õiãì–Æ6×Yê Y¸Ïýù„'êØrG44 ì‹gÍ4%ìŠùä`ÿyrËõħ„KdËI¸-˜›_î0øEæüÀ„Ñÿ0‰¿½rÉî ýümÚfbjèönä׫ÙTû£ñÑ×Ò s _vºÝB_axœ ¯£v݃ø¨F ÀºüoÙY™Ô •ûšÅމl(rNjâÓ1gë¹Õ)íDž(;(°\Û5<”!aõF6縀’UÆ+Û´NU«;á—uúÔÅq˜!ù¬€ Ù[àË6l0?:¦ÜÜ7»ä»[“£Êoä´ú6‡„-ý ºÙÞ]Ôö”„‘1šCq=óbu͉Êî‚ÔÓÉç:ÝXmü1hü‹ÐϤëÑÐûá”$·XÁ 8©‡ï»ûó©ëÁ!Õ‡ Ý4 ~“/'Ë»º_ìÏ¥SùV·ðƒtŽÓ[¢d(®Ž4×Tä8&„.óIr¥ÐèÉg‹s}'Ýó}‘íSC:õqúYjé%PŸ Z“àùOè}0„Mþ ¢}—@&'âh¶¨™¥I²ñt^c‚i¨nÒaÕã'o˜ºü”»æÖ9W¸h‚vêt®pšîn—7E‰Ù¯9V‚“—ê6·'/p—øg é}|3¦ J‚ÂuËy㢊|w­Oû§Ž©gñ¬‡šN¦‡Þ’ùÄ7¹õªü½e|r¾/u¹êÓáEg‹ÌCS‹ÀÌ:âË!n«_’g>T!šc{¤7îsÜdàÔN”}R½Ø®—„Õ;Uä½z臺je˜<:3bNúœ }Œ͵ÿ0ï%Õy»öyu™õ¤”l”j'U°ð˜!¼§&[2#WTå’ùµ<¯ÏoùÕOœ²hƒ†èÄ\f,M™Ûg7,ВШ-4Ÿ] !ü  qÈ"öšÃ2œ¸úGÖ¹àš°‰˜êžœJÖ¼j´°jéy†Ú©¶,BbJÚf¼²pÜ䯤Mk mɯwûèÞG^Ëõa^ôú<‚R ¼Ÿr–Äž <¼2ƒcA*†~u¤fÆÛÝ1ý_ßvë’vªÏ½ymoÏ|Ê'¸°äP‡aqÎMá5 ':>‚ìu|vn<ë¡ yïe«­éäµâÙƒN ˼¬QÌcS@ÏM}“ÍÊïi3Þlth~¤É^¬ˇÓ-K©Ê%gªQæGÿ|Öggÿ‰£b€ÿSMð|î!\KëƒëáðMÌ[C¾žeürúÊ2ü»òâTRÎtŸÉa–âzŸoæ…Óãvœ~úŸ«GDVŽI²+]Õa¦²¸@o Ì}ŽŸBQQgNî{3I”ˆŒBÅqBMhܧN÷âÜt±zb±%¿^#óøoî*„nM 7ŠÜ Ç`=™±àÐÚX‡¸…°8¤iGu4:kZS¼Îð08Ÿwh”R¬ÓDâß‚èu£DÓ)Íp)ÃYqc´>e'.Ê’½æÓ_iÛ‹xáACÊÞë@ŸËn+jËzÅêr6\X5„…ã|¹°ôêéàž0Áp¬k9‹K­*|ÆÅàœÍ†<ƒ>'GÍßæ<ïO¾› 7½0¹`Ô˜°0C\ 2ÒNc”°àâHw6$)Ýà³Q?é8!t Á«„O¼ÍM.2·•bÍ>Ô‡G(È9Ûµ{„€U¯Åöã”­¦q 0ޏ~ÄßÝZýÜȬ‘×)ì±Í¿ *ö¡ÆçNGBÜÿòùúd‚'°Be³ ÏY£åœœÀâ2 !Q™í`'JÝC7$H_ÅJ¿#ONÍ=b!·OÀ¶ó·šÚÂ_ë$(Û)ƒŠî´MÜW昴®²ÔÉ]èÆ u­~fÞ9(wU¨?®Ü÷S£–S®”)t4+}f9ûaŸfæmU}ÅK¿0›ÀD3¨|ÛRÔ3-å»5ïLXQÑŠ<ÅžI.±…K}ÁžÌ¥g=ÕØ`Pü¦ÐpãJ\®[u-)Ú]ºáÔVŒÍLàlðã¦Pc9†ù\÷¶Úæ‘`Ø\HÊØÂÑHxžÀ’ëø¢Â'vŽç6·Ñi¤œšhFí±†3ŸÌxc°pP÷$ ŽmÅقƶQ¨Öv †Ùž«o΢ÙÐPg4_ÀéWec³æ7î_…D¶½É”õD˜È[+ùB2`:s"œHü´ÓY‹4¯›ï[!ØÍm»­,ž¼ã&ƒ[âƒýæ:¼~_Ã65F J‘uø¢ž”CWÃê÷döëî©ñUþéQ ‚ÿØÕ(óÑP»*ûn¶ð*h—ær{pVLÈlÖ·eÇù~ö`Ҳί82/]+‘nS"ÁÂnpÔ½¸±Fדºf3úš‘DÑ{®ÍMë/¸>ß•H4ìXL׬Àò1Qm¾½={(|´!Ñ<5.††äˆ§n=3&šÁõM˜<j¡•‹¿÷+nÃ…[2qòÍPRŸË¢wÝfw_ [(‡~78D3Œr³/©ÙºtçT:RÐ2”‹Rucœ‚ÐµŠ¤wVwü´ÞÅD‰:Ð?eÊ+aÆì6uð›;× OX±pY~Êp3:ëP ³›¸ýb‚ç|ÎkÁ'ÃX7_¤0~@±BíñU2/p iäÉ·hîIâTÔÖæ?Š¢6P^ãBúõ ´ŠÖ!YÝì3u(Úí ¿Ž!.RÜL´ãŒ×Ë=A¶žø–S! (ar@¥¥»H =÷À‡ZÞIßú<׆¶Ô¼—c€ê%/Ð`úsO怇¯§H¼Ýíy†³?:Öˆ˜ÖNƒêè/èQ r¨ríóq˜Ý3È´ I.ù ¿‚rukh½«\J%IaŸ‘©¦ïÿª˜ù)ög'¥ìØqöF+(JèçtI#Çܼ f†ŸIë™Ø±„±@µ°.ø­/­cÃô…Ð67Ìᡸž;~W¾õwªÚÁ—€ˆ‘¤„«“)„?¤È´Y¾†Ñ±‚ 3­¼­óÂÞ×< ®Ò°Ïc}JÐv“ïWÉýHAN6¿^Ç‘) M¨{ WQÁcòhÀú!–Hs˜Ö8Y.GøÕ{ZUî•JìE Û‰gÓÅ´È”‹kê_ †¿ïwßгðØ[…g0dYPí­SÕ“+ûtݪŸÏÄ–ìºÂ,ûØÓr_ëÑ/c›LųPZT*öÚŒR>«gn¨q EÑ„8b¯ïÇwkÃ_°ÓŸ‹šúúrLÚeÑÁªˆÍ‰²²“fgÏÂ…Ñ€±Ã‘áÚHžeË/ˆǮږ ‘6ÉN~ZÿM€Fqa§–Röö“õ¤œý¼N¶„;í¸r”ŠgcX¼×õÏc¯•gƒÔ‡¤ ²Ü—Íb¸~ßa¶údÒæW\ž#o65Q¦ÊzÍœ‚“ðåC\~«xjÅo£öy¥( 8/ûôWw6ßo£f¿Öls‹’l~úXÇЮnf0XHp')óö+%ó·½5I± °åÁ!›nãýDUaºD¸†9K>Už»^'„ ¤»¼‹ÃQÊ9ÁÛõ7"YŸlîmî1Üá‡ë,§9 Ú°K<Æ͘ aVi¬9\€kVìÀ-@yȶqWXŠa"èyHX³hÓ¨ÃÀ›E3ŠdÎ1ä„÷-mlɳ æ0&igð]·£Jú É3Xk-b(WÔÅÙéV)³Q§Ô“ s/ÒëãöêÛäiåö§Á~`ÿià°î»›éÛekppá3ÁŽ5_§ÛwÞ¸’ã6?qÐaâ¯OæK7Šâ'ºæ†ŒGH …þŽµßŠ¨š0´á)ö(*#LêÍn{v›†åTÜ“ -;׿¬Lžö~ —P5u1n‘ ä0Ê c³@úò2ÅJFw̳oôÜáŠL`'%\Ëöû!tüô¨¨ÈÌñuäAèÍW~|3r@p"ø)â‡\ûRÖÿ©q4h)ès"K¤Žƒ'caY¼šÒ¶P.ŸeI÷®ùdÞ§¿.Ùa5ùµScrŸâþØ‹öÅk¯4S+~A‡”“i\AâŽcXò¸üäü“ç€È~:•P1P:ZãN¡æƒÆ©T'èýaQæ·d,׊öGg*ÅÜ ‰E¼ ”þ2–(5æf"pó6Å—gfù€;"†MQp‰v‡2E;×+ây‡ ëè“«vÅ¢ü®‚;æfû³!œã˜ÒZŽ>-ÉÝ…~LÈ”e!¾0i{Ÿþ»‹ Î_Ù›•¹±ÑGÃwÌ«;çÏwZ§õpb,Lž”7¯ÅÙG?&NU‚Gå?c?¯®t BÔš'–.wÿt>¼t¹…G{_§{ãæ‹LJ `½4U¡˜hûÑè•[J³ëhO¨"°3 ÚÌÙÞ2¼÷€Ô†Ü¿å»vêAŠÀÁCÊ®ü–Æd†Ë!ý9ÁªQûB&ge<-® „ô،…×¾ŽÜ„ƒÖÖ‚Êý$²ö³Ò-›Fêíâ¤~°çòãzÂM8j —ãÙb,ÑܦmTZÐ}ÑúƒÙ°à4Èr‘ =5Ô·ø{¦íyÒ§¢aгž¬~(S™Ïž—’ÈYb%ƒ-Ú¦D~_[ŸˆˆÅQyf¼Rdhq÷Il†¢>H#ÂNöóóÓ¥®§ÔÊÄbK¿¤ÐG1Äj¨ ‘b|´ ¿{,íÇ8dO¨õqÀë"óÈI›¦ ƒ¶5ñŒñ^ø‚0êDToJ™!U¤pò~Á F=´ã(ÂÜÅTÉ‘iPasÛå¸W¿–;ùÃþë#_ß`õöø‰b-¡þ[{¿‘ 95áÔx^8†CT¯áFzÿÆëéo“-£ÙÈB°…>®A¸vÖÎ,Dm¿Y‚4Üó5Ç÷¥ƒ\OÁ~Ío¹"6ئfƇ"Ýž³ÚáÎzŽœ4égÐÍÞƒf]°ÌySƒÀ”&!¨®Æ¥Û#ÂF®žùÃ0ê°[is’+¯X-[wVõ\i;·Z «ý•6ZÓGpÛb~æÊ+ƒÌÌMê.Η³nyZr½;ÑøèY]˜Ír&šm0ßÙél¬8ã™0Š{0'ûHü¬ó€9/Æ7 ðÍ5aâ\Ì¥Ž@„Ó]‡â6ƒ7xøJÂÍÔOmü\àI™{•yÍŽU#‘°üâ J¼º¼ dÛ;ƒýº™R´’ ònöm܈­.€{è‚ÿ®vœÏ «u¥ŸçQ|vèßÎS½ÄA6¦„ÖDÝBÅð¡ÇX¥èöj`8Oï„P˜F‚Ü¿ñ-ÃCÂBh^p­”êÈÔüÃnÛLë±}m:!Ê2€–e’×<Àý;Õ»}h7%v½V´6—ÀuxÜ ,s>àMßçÀL²»çíoUÑv”kU˧ÆçS{’õÀm>½‰uÉ1p÷ŒO«vuB {MÍ]´sÓxZ½xn܇ýøãÍZƒ¥;µIi{É·@iÄ~«C~K)õ¤èA¬ÊœöiâíϽ'ìñI¥¼L§DåP!hmîš-L·•Uäk€å·vÄ|¡•Fãnd†±‘’«7®Ü&<®°9Cîà ·É9ÆâGoXYßΩÉ7´QÛÛŽ“Øc •õ§ 7Ì3†ÊÔ¾Žûª ¨:±hÄ:qÛîòkPé,ØÒ¥k¶´;ïX|øÕNìw”\÷L6Éέ¼¶m™?¼ø=(¯rv:O£¨Î/.1§›© I%uDÄ…hª²ÐQŒ–J7ò°å4Œxƪ")ÖmKš(¢©„—#zµ';¯ÄbåD­‹n®ÃÖùžŠÄý ƒì"š@¢ÊªBCÞœ9ç’ÒÐùë½dðçÇV3éælá{Ö¡A¯On×ä¬_{)õ;‰|nWýPq@†bˆLh~‚mÃ]*²Òòá×2½L¯ä·-¹¢þÕ5ÙL«éwõz@V`=Ë¢U®1±?ßHV&Y 9½jašÊÅ)¥|yèÌÂÌBª §_9‰5fèéDƒ!êErLÞ«-Ñ!³m®kG—ÅÕ2G½7¶§/x¯¨#|áË‘)óújNªˆèQo–'OhEþ¸ž“­z›*9F˜P©U9Õ%äqJW‰¹Qƒ<”•D¯CU—Tö½ýÁ£˜0š×°/×Vtq›35Lnêîú·T>-4üý|ô“ ·}Íà BÅ~dÏ Z·Ú6+è½QZ£t FSo72b¸YÐÍð8>­¹dz¹™ºIÇ¥?=N[šIRƒõÓw‘Q¥ÓäYµXÜÏQÒHëßµte¿(3è\y9ÕŠ‹®5 [}h6”ÊÄê…}1íw ÙgÊã„*8¢G©òìc(›ÓØmÄ’×hé»Ñ+kÃÝʪ: ýüwºwzÖhd¯™J ¿7N]r=°)“Ð [bíaqE%Ù†çÞ¨ npßþñ…L-âϘƒz™x=zé‡+þäÚPù»/ À+'’ X¦ÕÄQ‡3,M,ˆ]ç˜Ïœ¡È¼‹hͱû"K7MEšXr'öž­ïççaÕ¬ß|ª]ø™u/(©/—f¿Ì.=›ç+pÏ „þó`MÊc’\$3…ú¢=‘Öj¹òôÔÊFTvÈ'`ç¶ ¼D^²œf5OU°Ùþ°ëêY˜r4tóª»ÏâW$Y&+ºÈ¸ÿVýÓÈXÕ7nÅøc¥@“J{¶ÊøvAsrLçvsânõz _µÿ”bóÓ Ãx§sYºJª…Ü“àÏæìqÍŒõÓTºå±®´¶†’.A%Èø\dn£Ýwbdß'7aŸ7Ãbá.­¿+TĈw0›" îºe.¯R×’éÎv6G™@š§ºî“ÐÕ|v˜JóSð—9Óäk°Y¾ŠÓoPgz‘˜^–RN(»k—N_ú8‰¬’%—¬÷÷a£ }»©£2Å„É$Ui~,CwÞé*¢¥Q}Ëîµ\ø=B­I´qb¸¼Xkë@iE°r™çyí]×ÓUYï ¸Ë”ÛŒ@©ßÂ]àyOBZ3ùú3Ë«Ä:¨ÝåšWÚ0Uò°Ëĩѧô{AÁñ»à"ˆ¿ñnsòI!X”µ`r‘lpñdfÆH5%¯óZ³q'o˜ :t[ _ ðô)äå'hoĨ÷ß¼ï“o¨+0ï1°“着TYñ ÉÙ‚Sg“²Z¥ÚÆ4ݵj••úaÍÍ«µ•†Ü.»W_åÙqÐc‹XÔöáúh* Z6>ØÔ&N ¨ÒV®8î €Ö›ñ{IƒñŒÏkå•ÃíQo„Ø\Zòo˜"!IåI`?DT¬À>f%TÀ^4›P¥ÀÐJSŽ—0¬g;_Ñe®0,­ïî§ðø0LŒ¡)½‡~>þÈÈóì9Ðl—ÄlG?ʨêM~CäÿBC„©{¬ß98êµiò¨¢q@Š*ãÿ슜%jr:7Øh)ÀÊkÉj¿%–ð΢ªÜy:èˆS˜<£¯|ÓªÎ`J-·O7Ç15ž§²Òì„ûâÖˆPÌÅà¡B yH21•Dp„JP•\vÃM¹KÕ$Hbq¹ê*;ĹâD2FbíÚóNú §,ê}x#'÷6j\ñKʆ%Oå™Ìƒh$'iQ:‡cä÷Õ‹¨_àqõ(¾]CT L_èK™£½£©î“žŒwŽëJ™‘1V³­<'×¹ ¸èTâráΈ¤¢Áá’¨! =õ1–KÉ“G¨Ô]9ó6Ú*o²~ྊ¼ð¸Hµö5Àxb'ÏK6á'¯ÜjÖ¾1»šÕì®5¥£ÑîFžÉh;X…VG›DwøE‘Öˆ ¿šRup¥}à„UÒú.Öñ¾a¯/¼ü/1üæ1“^ãÑ}ì LØ¡¯³}léõ-;”¬ÞС2× ·z¥fvŸt§MëÐ3õ˜OíÃþ'‘+4†çî+^à£$å»…„4',Z`0;däO[-¸ xà7 ÝG’ƒrLêð07ÙÑŒ²¬ »œŸ,^ûˆÑ&”ÌÊÎ_t ñl¸Ë^ ò'vÒ F®üN%Ë ÔmYíê#{#•4ÇWéiúžFª¤º²fuªå«ºá¨UÊ jIU¢ùÍýÔCŠÍ?%ò8X®PLÕ¿µo­Z3OÖLi¼Ä9îj{RÊoê•Fƒ¬ÙÔß{h&S6êø ðõðÓ&ð„¦`¸–¤Q Îÿºõùµ¯xpSaaS¹å`+q"ªE—î¸.q/³äÏ5°I)CQ~TÛ3~0饃xÚª;€i‹w2#ï\žw|g›¹é™|T°åca3–çëõ™kЙp·o),ÒP 5ãÖŽ{4h¡ÆºZ­›¡kDÿ÷×fÁá&è_«íÓu®—‚c±ù)°*¬Å¶úä9¤r¦-t¿@Æ…¢Â aÛx^YÌ~–>N±;̓âÁ~ ¹‡›ëÊdÝÌ‘©êŠºiŠnjqÉ›ý2>$‘cÜŒ¨ ÑÍ{1;qeyáÒA{* »X t¿–¸–†ø-¶g?0¿Æ¦\.\Ãòœ©CÛ¢œƒ;KJíNM“éœ)o³êwÜ *d=nYå燄œÏ9+“3.r¡– PUŸÉ•àž¥&ó¿Ö"Ñ'Æí΄káê·ß“¯"£Ü¨f»sÒo]œéÎÅâY"Cžû˜Œ‡4–ÅülüDeé™çß5® oÝŽ|‚€Öa¿y¤œm7Ž<°"8û¸òBqAÂOZ<$!aá§±×éèçÜð‹VO‘Þ ãa_Fë“»x¡üɦ_MÎ$Ié–LÖþS¦sÀ âéѹð«Q³§ÔÍí Éìyaj‰Lry!WµþÏ›9Á‡ã§Lg| ZµÈ›H»’10±µm@YÝ¿1xG\hÆÀ|?W^[ÁKüÄaµ ÕûÙu—>î$ ¤se?Ù® š{MÐ?(´k¾tÕ#|ÂÚ²þ%~åEj…ŒîúÜÄZŽj$ø“¥»ˆò¹1àÒÆÿ:Ø;ó‚$Í*]ÍP1-Eý@¬4›ò äÊÓØ#çi Öž1WyWÞ&á\L]‡×,ü–¹Ù€ò;nžÈ±Ä'âúûRAˆÐÒ¯_¾>¬’ñ3¶gy­ß$˜5ØÐ”ÈFðéšlJGŸºì³\ Þ—­ó£T°ÑÎW¢ Dè¼* ­©þ×n `ó êÞ»ìgŠö¸4E”žú‹ž!oÖSLk9®{ë=Bºë¥Ý?Äéq¼Ž²aPd š$· lèlmyy¥ìñ*¤Š°Cï!éá%Ýoð™ÂGœ/%H|Ý‚}gk2k¼ñ¹-™HHñCµæƒîLk+à¢Rˆ þ¨%#Â0¿ˆíÒÀ9p‹¨Dd]twOª êàr¾v:oßÒQ…s˜Ýôo!”4 É ßázï‡æN$¢M&’e3Ç5+É*ò ¢Bñ6¶û¤=þÔUjYÃötZ@®!÷ÁÞüÞpfuØOI+P$óˆÀ Y‹qJ)>ÆHÎ@÷ª °#Úæ$²[Kþ­Õfo.E¾’Üa[Vè±Ï80¬­£”O¯Ž”Ï?{FØózz÷=5žÔåÆÈ®<»ÛV)>ÊnAµ}ÏŽjO¤órxøcVµE‚ â½Ù*| ùjÈKYÁÃÔÀ;°Éq¾ÌÑoëÑåœêäó–f Ã2‡g<Óï&…¤€^)‘™oTycÿÝÚ)„2H7ìK½“äÛá$[c'8!ëÐûÙÝ©®ó'Q9]¡Þú,š2¶ffÆ2(þ¡¹Þ¥óì9 1«¦¤mN7xUÕ•$#3žÒoúüëËqÁ0·í³üS[Íåäœ?nKÐÉ‚r‚½/…f:ôÚ{,•P¢ŽjÃ94{æq¬ÖùÈ*Q¡hSIf^Uþù¡äùn¼Õ}ÁƒÅì=DÁýèýG¤‹Ôù¼/ºLSîÌL)W¥ïâ°´v˜§Ô±ë…ê[¢¢ðõ¢gî'˜„”áxy|`ù‡ËJšykXþOXXãZ*±š9Ü[gM6ª©@–6Ë[¿ï¹'¯Ì’áÐRF¢nÛTÈàžjòÓÈ(½y¦çž áUxYóÉ"…‹úÑp Qå”ÅħÆÂËfŠË¦Á´rfk}í5¢Ø¥©s’fÊÖ¥ c9ºu¢š÷…ëNT=aP=ñªôxjJ7JfÄ•ï`ã¥cê}Èdðïö‘hªéŸéϦYÅøˆç¥xZ×>ý“¬½ÚŸ& v©~•ð†M¼{± œeSs”¶=£Ûóù! ŽÚö‡yBpS.7=Ìf'$4ݸðr:™U£•Í"ð³ÊÀå ’–˜sG‡fct¾qŸJSÖ>OŸËèë©$Å ÿ#[±bW¦_Çn¶5ÃÄë{+¸‹¤êU9¢5ù!Š~B'd‹ÓB!mÜüOüâd¸º`{¯?®JFrÎè~c6Vꨉ7rÖ>Œ&`š¡zÅö îâ’_ÍG;b+þ¾"¤ õ`–ÖšñïUèdÏúQóÓd†zÂäƒ94YuðÞ¨,”8¯r¹Å?´§ØÍðw2GËh†é¥ x›Ö|ìÁú½ã­ã1 <¨x”Qy–lûJàŸU0•¸¾å²ë‹ì¬ê©b—)Ï)۬ʆÅ欎ŸÁÛr‚¯ãͯ[ÑTmIß²¤s»^‘hák"¸K ¬úã£Ãñð>½êŽå±rv&#ÖÃoîtÊî®Â-^<±›ƒ£€7,2Ó¬r´ø?sÙ’‡H¥¼Ê‡a ·Íb-­H²Ž‡w—[%Ë/#ô}k'*c1úZ5Ê&%z­.S_p©•åï»—«cGôœÿüùÖ":Iª¦}…(Žøe BóŽ?¥3yíÖû8ßZ¯“gX*Ñšê+¶©^1—¥yGõ¤g¤W¼ô(+O£+`×Îë™8?&ô ªÃâÎ&4<:(‚Œ¦ãMÂ.óÌÃD”Љ_pOrŒÞVìE_4zÞ‚íÌÑß%…ËÙYÞ)í¶¼n€CÍ[>?B[‘«!£°1|Gÿ@º‰9Àvú‚ a—ýŸlivˆìGÝé WUw²Â´üZ°r°»®HÚ$NÉ•h‚R{§ìÅ:¦TGˆ0j…¡ÙP⪬Rº\«ŽþEB´ÏöˆV6T»Z¹5wC(ìÇj»L¸ìn- ¹É¢Èï²]N»_Ày 0KÛ®/”ѧعX£?jd BB4ÁA×(«2ךþýw®x̹ˆ<½¥Mù6V)Ⱥv£}¡ÔZ˜Ã2Å™¤³á å%0[UÊ©½ éé$ÕÕúJÒ06Ê™ÊÝ`BI ëþ´T@%{Í1e»rÖñ(9+ÿeB¤Ö¦pÚETåP§ >´';#Tƒù;¦âoÍu?Y§‚­òÌÊ<®„/øgnN±‰ˆç éÀåÓ”¨,2Ö>QË}Wûcv¤ôóEgF:¢k¼º$Zúpïà(“ìA·ÒKJ9*GÓȽ 9Bd”É?_{µ1@°TSÍ4 T5íÂŒ&ÏMxº'©°N´8ñnß4t¤‚mîdG#÷ßË(cΠU(~Û‘¡™q^H¥9íPªœ· „Cvµö¿5×ð̤è?oéµéóÀ«yì+³÷¼Å®D½Çb.oزuÒ¬ƒS93×8SxQ ÁýãÊHV†ì)71›zVqÀöXE|Ô¯hb-!áÎóÍæï«wÕš¤3Š)ߊ÷7·,øewB’S‘nÇnO¸Nà}dËòˆínà€;wE(k:õV.ó_*¯ÇRMƒw]ul;éÂ!q¿ë¯éb@A?¨QóýËÀÔ•ˆ‘4A¬åÆŒn.¡—ì% b'sºðP°âY‘î ê‰,f„.°ÙaàK>>ÄvŠaÁú½˜ébKù DÄçÂÌ~þ졃Çãœ]6¹ð xr±0Ò½zOaM7Èi1n¤Ym­ÝÐ5}¥›©\bÒO#dÓ7Îo´‡w™Ï— 8ÒÒÙé= OÅ•YÞZë¢)õs”‘%¿:õÚì s©~°gœ8Ý×-:5™¡X¾ÇÙ­þ‘Ä%K [yÁÔ.SÀ,.kN»Ùе¥ñà!ꔟïÐzþ/…dÉáp 7põ@LŠ¥ùûÍ›ÐñrænB𑤷¡Úzù—ÔÏ@àÆx…Ñùæ°7N axhLÆœ€Ä¡æ`ÔGò;U¨SCÜõ¯™ˆð¼&Ø-9Ë``™õD:.R9™ä¢6ÇŒè'ÝŸ‚µ^dÄø›Ý{Qó«®ïb'ñpZP`ׯtBwtžßCUǽ¬Û˜ä üÅ•ˆ¿§Fh¦îå ŽÃ°»O]£´ôÅþÄZ©p>ç&Oîß ª Ï~”ñ–¤~§W!–vߟ*…u&ðCÍ„V"¥µl–{`£Å;I²ñj¼:_S.ŸI(¡D§D1ú$Ýß&¹-ôÒÂü=ãýçߎͬTˆŸF]¯k[¾bŸm_˜©–UñB´Èd†Œt »¿þG}«eñ¹Ìi>×$¼ÃRïÇÉšÙ­Ø Æ –2jJ†—Ò±Xb/tk#úa:bYZ$¯ŸÇÚ¢ƒÆÙÍFÎÔ.}Œë,6~0TwÞm%f¹1'Α6‘•-&•×vç+Äù¼ŒÈü£S~I¿²âÁî¨P˜¦r 9>½iæ°W2ÚqÏ™"ko.Cv·%,ÿ|©s!ì3Aþ0ù¤ÇZ<7XÀµº Ôùç~©â[æ8µmì¶a4%ÐD1urî®Np³ÂI|¶¶"¡²¥vsØb¤VœXóPëÑÉúBQ­º~þÊ}}ÈŸìÇÔäShwXaLXï¯nã n’"oH¯‡`ŽëB´’v®ðÉj1m™J‡kph·kx›9ô2íF.+•‹ö†[h3é¥AÍŽø= ÎŒKœ’Dæ±%΂§ÝŠØXõû“>1ruS ­ÈÃÎ,pWä›e›`¤‘Cù苇ŒSî‡^ŠŽš û?V¯Ñá‚SksšÂÇ[û=1P…¶PŸPXó—DëwAøv(œÛߪܧ@ ç¤B1§×Áe+æÛLÓÄÕMÝks¿q¬þCòØÐÊ Y>xén÷,cÆì™•;zšÝ¯ø@ÞÏ@ØïUv)®ìu/7¬"Øw R°Gêõ)uÛWô¢¾-Ôæ ¨ŽÞ²©gɬÄ׈›¨ÌxG–%QÝ<Ó*ÕjÏo¸ä=&âM‘ðA^×ó°”Ög‡.×2.Õko—@ÏeÇaõÚr(ÔÈrN-6ÝÇ \·Ù ZmD2Õ Ö:³­9th&.RT¸çÌ —o ‘Qu£½5rO-è§r{˜LóØTï6¡˜$Úô:Á² ]þõ.ùcülÐÞ®r„†“¹)ä¢Qºïu“å¯bk”Ý„°{sá&I€’… Ñ©Tšª{-øó°t—*å"Ùq:Äõá0œ1§/® Ée‡÷Ö ð Û‚jˆ0øóžüÞyˆ5˜ míˆ10­»Y@¬oy2£ˆ! ¢Ú#¿F¶º Š· ¸¹rMßÌû¬™T³Þ˜DÞ—JGž-‘Ï#šŽ^(¿Ä9âgEŸ&äФÔPÁqʃ¯' >BãæÐa)çú^x‹¿ÈsË¡Só`I+§%í+îóÑLP…ø¼ÍKÑ:Ƈuêн+ñ§°”» oˆùõaªº…0dy冗KìÒÝý2bNœÑ«]S¥.Öó3 }GšNb–-uJá–Pú{û{+ûðŸÕâ;y¶ùs–ê<‡Y¾Áfý9ËNjë{ü4‰)GãÂ{0AfÆv¨,íºÕs ß5ÕÑ9•ħð ee²´ï–8#S¬_D žŸ'‘0cƒVáߥ-Pr¦=üN\!Öô¯³XO$e–-[çÛÊRñkÅxÕiß±fašaÛÁâô<(eÿ@æ¿1Þvs¹vÖX`lÅR,×ê¥a3af½(¥†MVo\S%R¦š>pÕ·uŠwœ4ÂÅiÄO+°-êÍ^ !ÍkïG¼³Wƒ/,ÍA`rÈ ¥»D³(ÌÆ¯¸s‘kÛ‚†³¬âÕ^W˘R'öV¥65ì§ÓjoÑDsùÒj)m B,_>:ÑζYLdÿ¾ÕÉÿ·qÐ\qujé§• ‹g×ÒlGý8ÃMŠaœ…ž–ʵÑ“Æ\UUlysØoÖÝW-×"ÊÿâšlÖtÑYƺþúß²…¨Yù1øcÞÉ%”M+^,m]a{‰†K¨ukyLe WÉÁ-}Ž›¯SäªßÞm’¨ç\_†£|MZ“ý× )·ÕšúE\¼£,ÓÆ®‡&®Œû ¡r•÷¦x3´¼KÿêÈ[p”œx˜¡kÔ†O«!WB²:Î(nïï“F¿9ø²SÀ9þ{j>i½O3‹Ì k’»–Œ(mÄ¢ó¾w¾ GHºdD 8h<¦1ˆziÜáj÷yÛ[\Îdà†»ÞQhä´[øº4¥É†ÇÆÎñÏiÉ»¢!1ì qó4K=4κ 6zÚ†î/$amÜçrsg÷7d!ì\¥[ŠnÈOîÕ¶³k7(èPú“n9º+Ykc dO”Äœ¹P‚ZñéòêGö™«™þÏQÞO*Žžgú(×¹´¦#FXùl×ò"zÏé‰/VÆ!ò²äŸ]¶ãç#!>td—êØêª˜‚Ùç¿B%5°ëS³ø¥ëžbXùX™:݇å4˜PB/9ÈKñòiiÍv *ÑQ¯4ºd&‰˜Òßzí]/ÈÚa«‚”t…š4ìÞŠôýड±SÉê†ÚW™åºaK÷|¾¬ B){¸é+Ö®ðøL }^Ö¯­U‘¾³©±Õ0&ꉂóÆ¿O* Ê90Ö•Õ8¾0øSrD(½³ë= Z=+œ=©·YaXñ{ix³KŠÑ»ªJ´CT™‹ÉÕÒ0æb<þ¤‘wB›A?2{fØÄ je#ãÐ&M÷Mè+OýC¥]kAq»XkC¸S×÷|UÉ`õÑ"ä"Y#çÀ¯Úh«.ëQb 9——<žcª'ÿ,5`xæ€äåP¶í.©Ó%_'"9E uq$´!ìtãgÂ/ £ÌRDX蓃ºd,(HSºð,CAÊÛSjfY\¼å©fø³Â¢éP¬\ì“çnå&÷ã#vO/äª5<;éå9ª•eÃÓ¨7˜ˆæ„}öæ¬aHžäHOïX>¦» õÙôØSè·>È­³­a‚Ú\‹¬‹›f¡%uÍüÑåÞ©/ÙõÿoÙ‘Œm}Û'`­Ð9×rò‚‹Ê´—¹Õ•c§<‘r”ZZ±¼c®K…Ç<ÖÉZvÍ£ ¸ñÏi†<4´n‡ ]j§Â¾(€ÃåÍS‹ˆ4ïûÓ–ös¤ÌûÒöÈCÓ¯8m£”„Zô¾`àþ\Eúz&–9.|É”zt9‚’?ÝË]Þ0«Üñnž} Ô¬iEå…ŸJ}1³_^¿ܦÐÈà‡P2áYïu‘oõOl†£N÷E–Y3ÚrgnÈcš¤µé C,½Ó‰Ü›“c@/ÓÚ[¬²ÓJÂÃ45¶  ›#Vç c1w£îéE3tx7²(&ÁÓÝ•n½]g ܬžt. 0HãñÉ@ÏÓ‚åÂ1BܥΟÔ×]³ÚÁôW…áxæ©r¼­èñ¨È±` x¦bõVßGÕJ¢¼ØXºâ&”. ‚ÓÆp­Ô`3u¥+Åö<Ïßf9«—Ì·†…Rõjº þ5Ô¼Õ\ž"þà‹ÿëµKº‰#߲ݤRÜÏqM.F³Ú~¾MË^ér§å߉3JÙ=7˜ÐÄň¿|?½(WÈçA7fèRÙ¾”¤IÅëŠ9ƒ<üÍ\ˉº"g;EÑ]eM :}“tr¹ÖfV[ ǺÁHR‚®Âõ³Ž|8%×Qš®sºÐ¢¡k“óøI¯O[¤šÔœ¯'½ËÚ¼WUéPU8þwN™AâÕo¶kw´ö Ï"˜½b©ßT"¡²ÆZíȧšæJye ´ e¿‘›®€RAŸeZ›zßbRÐið,0‰çJ1'¦ 3Ó8~gò÷~èr‰öŠ@x7[M|è`)˜ ˜hõ£°E¡k8NÔêâ(¨‘2&¶Æ^tÝÓ/ô½|—¬ Íä¦/dï Jãö£+†ÛJþcZ¾!ƒ9¥„µÏ‚p÷ät«@Æ_”‘ûÿ÷¬É6%Šé4¹?÷.:`°®ü½ôNYe—Æ}#Å@u r³`B-ãšvÈF¥˜û~£h¦­lŸÇXC˜ŒÄæ_rE^ ûaNþ[ä¯ÝU÷ä@3œ 7£[ð8[9šËy›3?Ûóœš 5úóGc2ÿàGÅüäâdô;éù«Û´FpqæÞØP}ÒêHWñ6ßü3çW±‹ÐR~·}ÅÁ«“/TK²!­níö˜¸)ÏùÉs£ök‘OÀ?ªnIñ,_Š 1FV>®¨F–~‘Ä“êo&_l‡4J›UFB^õ1ÿü è“*dTƒÔÜBñMÉÕAfޤ¶òŒõ}£”•ÐüxW•½UOÐÆ‡¿ªùÚÏ Š— u|/žÙ”v£?,æeƒø.ÂÂDœRœ=^{jÓ…˜¼ç ‚vÁ ÞÉàБ™4!³=-Ó|ÞðñÃ<ÚxëÄÒÙª ‰¸ÄŒ¿N¯*$J=‰Ze0KY €{‘Þ/Ë qÛçš²¸CPXn2Ÿ±°h5©HÉ‚õIðËXÉrã£ÝëP½-Ó«ñ«IÖëË5<%ßi¡µ° åNq&Ãp<´|ëh<•TwP¾-Iޏ#µÊÇ‚ÿ¢‚ämž2Ö:Ïì¤Ôq¢Íc !E™Üx—ãýwhè}jCÕwOÌ‹š²´€fPcü*æ€2·,4ë^J`Üc¦#X»Ábf„¥ûpo¡*Nåí…¿’ž–¬HO­ñ¤ÄÙ£‹Ä /`i›²W»5Pä†[»N¼àÄâÅ_±ò $à[¹î%°›I³«W ‹·(>ºðFÛ4ß$(%·€ ¨ì»öÕÌ—Î÷w^‘…<6/–dî‰F_hèžFœÌÚØþîQ¯Ù6sÓ<‘@R艔cÃ-RÙîÇÛ–¡uQ°â’š¡á"úvxõÓDNx˜ZWlµj«ªÙ—?IØù­´­ê¬†¥Ñ(”gK¦Žu‡ÅïÀà rÇ/°Í«JMMhB̵•W¨ºj9ÜõÁ,«Qž-ÂS4%o\ÿÈãÕÐï(Oæ¨üTF»!ËrÒÇ»Jê+òjÍmþ¯ñã… 3˜O$b†¥ŒânÂoÆ÷'#àš?|OFÕu~â=èÂ=¼§w¬Kuñ²ÂÈŸd· i’¤?XUˆ û ZJ Y0_8CoòB°£¥û­«8ûIáùTY-ª•\IRÇôåÖì—F}Ä«’,ÞÑ {Ž,ßTÓ²…ÝÈRϬ]W5ÅÂYœz”eüL½án¸‰§ ®ƒ4ßjdí[Fû‘DW‹ƒ5¨3d&vR –³œ1ë×ÿζQ*ƒv(ÞÆâZˆvøø;z{ÇGŠãÅmIñ;ˆÄ²Xc'̨‰UVµ;ˇõ䦴 £Èõ)@š×ÆÂ¶“ŒÈ8 °ùŸùA–wƒ3Óuê×_¡¹z5Så¯Ïòrèó˜;~ÔÞ[mhê:_©$²ôÃÈY{×>,HÆð•yNH5«O¨Yj¾”¬´É¬Ãö™µƒ‡2Lú)žpY0ÇO ÛÇ­»h0WaAàK‚át÷üÂ=¤,¯ï¤+İuPÚ–ÿ÷^'Þ~‚ׂx¾9Š?UÍ2Ûà'W¥zk¨öðdß.¿ñUÏS|qµeëþS÷enäVn®©PæS±õNÿ~2pjôú:±Â#iÊþSV¿Ë«Íö|D¡Ï+;‰ú©*Y–øÍ)GOŽ@µÏÿ0"`môR³y ,oרä\ÕsRv«áP•i®Qø, Â0-SßÎÖÜ80p=‰-î§àâÅñ˜¨~¹'#obQùŒº9Þÿ%ë–ƒí? ½/Ì Œ9üÀ¦ù (ó­@;Ýà÷u¿ÀNê7ãîkb–ç¹ÉV){jê觪N.÷E›ñäÐÕ]5˜·¨Åêa—›S½iÛ¶î'Aò&ÀòÀQ_‹aÐ4Âd¶++ƹÖkwU­k†åyŒj€ïUt‘ i;Œ´ ­œ¬-CµŒ‘‰D ãUù‰¦×|ÇS@ˆ¥³lÎ ¸ÁX*:çŽèFñÁSòê.4e^ǹö©È;sÁ(ÒÇðû’*%¡x,ǺñL(!PFBÃA;4Ž¿uzIŽO*k?ªL²±ÀžY¥ ùø=”¾…°ßn´Eó‚zWðÈq£ÂW&a+fî,djæê/•³¸Ï÷3ãzÀ Áµ[’ÙÑÉ·÷X²¹™B憡Ž4[*4Õœ;uÌJ‚K´//yÜ÷& ³NêüeG˜’zt¤aš–—ÕÜ2¥30µÍ)wƒ„¬ï_\ݸauC¡YÈñáìì -=Ò°=¿†ªyÉ{•zï ÌŽòÝ]Ë0\p¤V^îlóqdUÛu9D^1e°¹‘PPñŽ>_0·õ'Å{K'—îÿ—úÍÅÒ¬;—gy¢“ss)úÿ.p2}99œšžš÷|ÁûÞâëò&O1UÔÝa°ðû–†8Ù’ñpÅbrP-ïžé¢$–dÍ¡Nyú†©Œʽ¸ Þü¡ZÃÌU»ùµ ½­gxt›[Ì%N`¯Õî*ùòö„bâLj7ÑÑÆ+Í4ÈÑyIࣨ^ó} ÕTím™UÃ3ðÊuÝÏåÉÏ—BRU–³†cI‹À5Cÿý)Ðê hVAcÍ´Å?ÔS¦Ü:lj­_BöÁ„æ2Ë òû\ø>å¥ ½Í\Á$7™õ®Q‹¦¶Ôƒ#↉);sƒü Œf!*oÀ Àa2+q#³F 9Àü¾es%FSÎéïw`Í‚#!¡?þ yo‰Ý`bªB¢….1ÆßØéèÝ4<Ÿàwò[wpï º4C„³ªPtͼs\,ÀV¦0&vIÌœGwÕ\8Ê[¹÷‘îGžÀÙ MÝ–?§ÂW!M½ã–«sá<Ò²–0éë„+ ³Z‰êi-v=ŸRÃÍÙPÉ|æçÊÕÇJ‘PièÎU>ù´’:ºœ]³MIjs,®ÃSO([MÊH pªØÒ ªÏìØ4Òþ.èòÙß+ú34w‹„“)pð“™{ ¶A°Ž6oÛZ¼q–1ûŸV9juÿE¯Åe9I*U£ðïg‹qÖ 0³-ìVJë‚”Âç<.£O²GlÓ¦•oÒpz;öHŒìw”è¨Â×€µ|ˆ÷DóÛ çhMõ•NXÜVlÅ1eBªœ”á^°x_Ž5}CŠÎ0§”¢i»ÅÞv:†|G:ï b˜È} |sˆ`ð,Úl}ÛfpÖ¢(@QÞŸª†Uq]Wóü&ÃFbcÝË󆺌 jež3lŒÇÐço[èÁÇÛ/ ›1tJ(Âëó½Vy¿©·hüw2–×Õ‚+ôøPÀ‚ºÓàÛ¸}âüÿ.r&Z'ëûÃÚ–PNºV˜«„ƒl®Ä`-„ÏÖÕÌÈ.cKƒö/FJïѽ I„{Ç'£ñÞç"ÉâFÎr=u¢çop¡;|lxTCÆÄDbm’N y¹¦&ƼÒ#Úü2Š–ë¡Xdç39ÉÂ+#ñ¾ô!=0µÏPîúN¤­™¦a=L¦'K Á¼È­w³Ú§f‰bR~{) Pý·7C•¢ÓkÅ>OåXŽq (]{=TÔ–úµ*L«Â+Ð┋$Ò§æ¨ÐUd9JÔ<íÎ(I·¤íAò³‚CQ? ;°“ÒB<$ ®n«ÃÅ~œ¹cýóSœŽŽÏ qªøôûQL2@—ž¬ú.7Ì´»7¬oú™‚â8¨H¸Õ·_¾÷ŸßæªI‹ÈZ‡z…[w6*8ÉéB·ÚçXá6RÑBf;zÈÉbÉ€9¼¡i¶½>Jã0^/7i\}sˆ_+áxŸè¡Ü/>U åUN™]롬‘T+²“ç¦Àž.¹ •1iì äÙƒÏ^Â@>îëL$ˆ³ÜÊþ{_þ Y—Ár“&×ǧÕ8üþ-úW4M“î„H°%Ñ&ºÛ.§á•jNÜʉÌ }+Á³ÁÃíï¤ïVÝtõo›J4¿›XÛ"·ZéÉ B²Aù!}²ëûÆgttAúg?i‚“\ı7`VÄC‰–êÿ¤ºéEž_j©Çi-óz<{úL ü‡ÓYCwÕAâwÞxïQ5UÎßT4Íin=ö“ã‘­rláó·³®aAøj‡ý†ÄH ½‚ýC„ûÈ°ÜæÐ®Jð¿ùàe‰‘•¿ 1M3¬~³D¿ŠüCN+b;Ñê.zÒS]ÖªørÌIZdƒô!HER£.pjhE+l±yGˆl”†ÆºÂ¶é=&Ãþª8ŽzØCu ¾ðñøVt³¤p;D¤248r^U‘³Þ€‡ÊœÖ8ùD7>ÕÔ@_u›¥­7$ XžíýÑ ëás@åÁ¹KznÂß8-h3÷7%C'•./çQÁå&`'ïÀÃ{þXQVÇ>ï87-ëÈ[øúÏéÐÎQ°}±­î{kÛjýà èp4ØÍx´Þ'¨+‰´!æÁLÓÐNÕ>NkÛÝ< ¯ø—4"Aéʲƒâ¾ëð%dÔ¢€©Ã{ò}ò˜ …itÂÛ+€7Z·Ê7ØÐ³WÙbw7Óü` Ñz®MG§DólÉáU`LØŠ{ê‘Åm»óß(·ŒpˆôöràÐj-ϹíD)¿q”äû°ƒÒ’íîåL·ÆôbÛ$¦{#ÅúS„eœùc0Q9R9TPuN1§@ôtõjë†ûüM‹ÒfÕ0„Í$8²…·,Å\]³¤cóòÀBïZrÞci¬¦FÌÊ aËË—X%§£ç»ö}û›Zú8½œIÀv$>‰¦DƒgOxœHÝKẠ`î—Z‰I÷¹fëx§—ÄÕÕ¹ÊZv0˜éÌÝâ±%õåÒlícz£äJ’³«ZZu+?½ “QÊþ°s"PäŸ waHbËbäÂÃ83*ñJ ÀÚX³Ÿ¬²ôþÉŸ½ôúG•öÎ¥.6+<œñ÷¨cÏlŠùb9EV5xz“m Wë}þíìËöægL›;Pü_¶ÿ57±D¦ü¹éBA£78˜¹‚*ØØúFIØn@ýµïQ) ¦´ƒvv&²QjÐîÉôR“k©%¶ˆå͇º0 ½ôæÀ«àe‹²û„°)$t×<Æmi™\`^òÕ)^çxèßÎëò@Dçü/:òœ`_Ñ@(÷ò2®ŸN8\ß“•: "mÊ_S‰ZH9-6_»f¿8Z68¤o·k°¢Þ±MPeß~ ¹'ÉïGëóƒò8ÛÏcÀXêµJÞ;{Û8{>ÖAÏáä¦ ba<ȼi¦÷bm¥ÀŠw&Þø¾þäiO¶ ñ ·ë¯%9°F£n•X9´äC·²V.`ÌZ~£©Ý–d+ØžBs5Ë ç°|öß|Œ`ñŒøò†èMÉíÿ¤î#rŽªbÓaÀ°Bƒ=‚’¦E·#±Ž3Ÿ‰ŸÛÀ…xÍ Úl]ˆùb.¹~úý#cÉóŠ0ÿ•-9ŽC§?‡½!”§Ÿ¦‰{IopìeΞ½]§ ^²x–ã‹0Jî®L–]½Þl)–Œ—0Í·¯çá@ÿÞzó0.~úTM=¨›QšXçž $C¯U×}ˆ¢Å&àœrõ!Ù„«Vušõ›i˰5Zì sRöR’”„ ›7‚üJ$Ò`$®çÞKàkK÷=µ¤NաЉ9a'S§+hñ^™á–¬î¼ôYh9ÑTcÇ}A²÷,ÙÇ«%àa †Çÿ-C/ß­(D æ,Ñà¿Àx¾2ëÉ‹42¤´NAš¥ì‡ø…Ò­nJ”3œlYކCÝŠ<‘>ÕíC¼­¿Ó,L. lI§ë5~ïk¹J{Y^ÀÙÁ¶°¿g®öÌ@ 5þA@©ó=`j³ðP`(ÀB;~q1¶ß? ,_dx•¦#ÕCÙ1GrZ8ƒ6§[0Õ#Gl6„ݾ œcî¹ÁÞó1xcMí¸>h}\³ƒ™xr̽.ù‚¥Cwýsì Ó“sÙ8»éåÍ]èše\VyÇg|\ÒÚDyÈH¸‡c”Ëý hy³>Z¢¡A\Ç"ËÚe#[²JIf8îå6Ú/^‚Vq(B-VŠVNÍ’u¾àq„.£Ya{H0u¸`U ËBZR‚g–Ee‘VÑüÊÓ‘IèhUø-yhÞª‡ùÆÊ±:ÆgŠX¹øÅu’¬QûlsC_ƒºîžInb»„‰xqO9ç{ÕâÒG.˜Ê×±ÀåGåŽ"¢b [ø€§5ÞHT¿æEåÛ}©ÿË™<¹¯ÁÐÏtLJ’™4l†N?¨iIL¨óò0ýoÿ³þ0ªoJZ8¥¿u,]õº ˆ&'ÏsZðRLû(‰«C‚»mëA{èPÏQHRÔuX>Y–kRÉ}Ô÷Œæ¢°–còö‘ÏÑ¡¥YNWθ9Í/êÃ`¡™º…y^o,*LCR_Äô|ÌVn Öc§æhRúª¼d=è¤L²[:š=ƒì í…TLȦl€Eõ¾WHi ÎÖTô'éz`(ã9G~Â-gÉ{$10 çÝ‹î| ¡1\Õ¾‹ðKªÕÏœ¹Ï?®;þ° ¿°é&7:<ùåÀµWˆü&<í뎊 1‹Œ5ä?`ƒ8çd=u§lRÌŒ}U(Kø ‰^®;”®îÕà>ÞsëáJÿ{³&råmµQ–°#–ÊàÔPà¯{ØáíPɸ;•òÂï{¾Ø>ø’þKà×Ř_fy8÷~õÂíé†N[‘$h)$ª¼ËTlÂÄ>ª$K83­æí§pûÚ*Wb=比}Ʋ_>%ÞÊKD©;ûÏ,ÚfIiÖ­ƒ¡èžîê÷ ˆkµmvÈàÍ r™ê÷-²ÈE± ›g–VB _Ð'°âØyÆ0߸5nBš>{̳ëþ/ÍûO+‘-rô'̼¯•Ƥ– q……ãÑ414«‚Úàiÿn8p|5kk°èyåj{¿K©Þœš0Èjd­OÓéMØäîœö:ó¢ƒd¡?Ôøö‰5¸‘€´°qÔ·$(:½Ç yÚÿý¬¢—5™ :»Ö:<ïŸãL¸YV¦ ƒÿÄÐçovu7· Vã.ðu¸ÁoÑ_ÓHµîÑbºf¹õÇ›B~ϽºžUFoï NîEâ·s ®ä¸¸”{ÔÆ½én:‹‚kÏÚ?eßïï{óÏ ›¯X˜ 4?òK¾,ÿy%Iʃv LoéÎ1mó!FéY^´ûª¼¶ÿ·$@<¦”ˆ¸6ÒDwY5RÕû|P¤6"3î¸oÜg6>kÉ >d0ƒHØÝH%oùLƛЂô¦$êoˆb)Ý þY>ö"Þ#âÙöa|K³¾¤R£9ûŠ)¬¤Ô’7P¦ØÅù>™ê´[+)?”R‘4ÙNe±)³…™Y.Ì‘é¼]Ï9;*ú°”Ô«?·þuºtswßÔ§Cè µ@è )7š¨íȦ+`ƒ†ýbX© ÇrŸ#èTêRÞJ[6›Û¸N•÷ÿz=ç1ÈóÑxÏ×™¨Úzg©hZ¼•5ø+“—žOÓînË®¬ù<§¾ÐHÑ^*üÔòçe…_iQ¤toF¨4¿iÎG<®‰© ¼â’ÊÌ*幜̞  ´u#pQQáXm½Ñ 9«y ´³½³K VEìTbOKà…ðËa26# 7+¢FZf~¨¡à@}!¶¦ Ÿ ÐhÚ¶ _úpŒ¦£Åq´mbÐZ–ÐîŠbcM)q3{žbzøB[ø[sB0’ñˆœ¤ªYCØ)5f<œÕgùþ½`ëÔZ€HD‹bÄâ r^!äĉ½çÿ¾«÷ˆ öØÜ ÉÇiz^f²ÚŸä<7-@1;ƒûÁÝ¢ØOÃ1ÅZb˯cŸ¨]”ÒU+妌…4O˜Jü¯ïèaÇI\£…¹ö‡žjÚ_‡÷ØÿAYЋ& áT9Å N;§P ïrRæ÷0öùíÔquYÉö¹UvÙØF UC‰6 ä‡¬¶kÓ½ÐiÂ&ˆ¤‡aºª Õ³¶…%ůχì?)U{/ìt¼Ë–™ŒøúÜ~kÞÃ+!Câ=ž"—&4N£ÌlJÞëM>ÔÊLãá¦4ßþ; qH¨bêXV™eÚÑ,½Y`Td†yT–2ï鋃4ôŒ<ìƒ £¨¸V\wÚÞ3”:…e¾¸ø ÓõµÍð¹ŽL_`¿Ä+ä*ùNß + ¡IÎøSç¹—XQû¼%ņzC±íÜYXÜìi¬ÌÒæ?2ꈾmÁÚ»Ëm¤nÓøàºþ¼>SåÓ 8X« Òý¥*§ÿã‹›ò˜Õp·ø-°?"À_ï‹®B…œ;T”ñ[wçQGÉìÊîÞYEpÙ£ep@²pl8ÿÿRÕ°÷6h‰ºvhc ^@ï­aôøûuòk2Ún¹¦¯§ÿbwiy+W¾vÁAƒ@«q”åe‰A\‹Ïõ–á­é¯}{Š!·ÿ¨JªfÍVn†-«VÚ±o%UèQȆÈ2Oî@½âºGæ=kÜþ^œfê,àÉ`Bx˜ n(`÷|ÃâÓjƽ:µrEÞÂÈ»%P ‡¸Úa5Û±ªøW°Å…^G‡vdùÄRk…sI`’¡–½h.ÙA‹"G<§I{ײp¤.W“žXÌi'UT²5sªÀÿ³ÏÅt§8 ~ʼnèS›àhËaÖ} âAD:•Ýh^´ì°ÀÔÊÒúåOt”Sfƒ¡ìÁH#¼Aµ ÐËò¼·' %²7¶9‚P¼u ©.…öoÃ6K™¤“ ¨ˆª‹òŸÝy„çÜþnžÕ&R´Aa: ;ôÜ…«erÒ©~îf²®4êÛ¶ó47‘=¯ùªFU& c©Ü|­ û©cL´ÒUÓÐ3ç‰áœ^AAn˜ßºðÛ©×ðYšåÕwú£T½ Ž F矱ÒÏŒ@þÇ:êÞP êþ3zpMúz1ËÓ¶ÛAesÉÒ¹6ÑL›‹Äž¿)µ¾”Š•—ñ¶6ßFp¸bÚ õØ›ÆÎ€Úó  ×)碿±sæ_—“TOˆØ EúøLç{ ˆ”âdÂl’dÍb'òÈ?r^–oö‰1ÿ|£éHyI¸Áf ‚ØÅ‚±C"n%Š›h XÐp4Ì” ö>zõ¤3vèþûfiu¨ÝN«Ôɾ>mÿ®›üMiŒëâï¤ßWB Äì9[æoîR*QFtmº² È‹pªž‡øn§ý%Þ|ÖU^â’1éOæiKøœEžãWT ¥ž×¿¬› G[%ç2Ç6! G óŠ÷åÇîõÆl3ÆŠ:TVÐfþ1p9#vëÇ-_žÂIÆÓZîòˆ26ô߃y8Z~ø#•Þã$ÅR¦:e&6Í·D a¿EgëDÙF":Ô×¥…¦N~‚/NZýƒk‚¹ìâf7˜p{Yø­¦†\ÁòôîÇ",†™˜Ù<¤ vª<—¡â]œÔ>î°•K ½#leFôÈ^žqÊ~ß—0ÜÍÂ@òA³µ™/çÖíÎ/ÉÚ’šÏP °6lë{'àcü¯I}TÂ;ê©Û)”µs_Ç:³ÙDm±ôÝ`–§ª½ ¤H#)töe¾íN7¡#þ+ ßÔ§2²ûŽ~NámÉ*üg/÷ήtÌÀвfœd~–¤JåàR0ci¥Ê»Ù¼Ww¥д CR&äK?X ·ÜÿÿAìþ·G‹¶/Týö‚ßkK‚þ²†ùŸXÝáñn©DÜÆh¼„+°E³t9acípƒ¢‹#ª‹“ Å‡¤a%;;BfUƒÒF^ª/ó!_ù`eOV€³ý›^l"çg½æb#Z‚º™´…£õ³œAþ"މxÚsËh’Ò°o‚ê|›lðôe(mÜÁû ‡H 'Àr ²`ÎrÐk‡0îäÿhFgT¼J 7ù\Aeo,V2™šù•å÷,Bs_V²­NŠçc<¹Jòéay“ÏZJ%{k(¦øÚœüã#$Gª·¥Ã|?Ä€@áqúC¤œÎÞ©uβ3rq-SáLÔ CE‰ËZrb1}m§$!­´X ÎÊÙgÔBf’W–æ ä?@Á]ˆYÍžê]È) rfÀ'FÆ1Õíü=qåßþ£b­3ÐfûâË3ª´"Çã7h’ô`Õ®ÚÜ}> ÓßVò›±Z¾Ë¼W3¯~mÄ¥š,—ÖÛz.UH A¾uëù¹¨¦‘Yv#UJh& êI»åùë©þ™Æ$rå(V<\:'„Fß_èoØRö«Z‚<¦JÛfÏÓWÜd÷R’ü€ø+•ìÏb˜§ý–¡Æ0¶ÎŽdj™~ØoI¿T¢¢³á÷S1ß³9c> sh›ô˜7è¨*!|H ¸ýöó’à0¥Îeef:¹$qÕU±ÞHl¨Î "D+/Eœh×v·òÜýc& ¡ì§ý|GrÛú0ehŸ€n¼«¬õ5¥¼Ú¥°…Ï<¼§àúQ<ñ @ý‰·‚!‰m{j‡ŸY·ÎÁR>Y¼K,óO€v‡v"FØønqÓzùΤöòæ„N† ‹Šû÷ôs)Xµ¨+Úžšâ/¯€ ‰üÏë¯Ê‚K\#ÇNËËñÁ…?¬¦ÞßÚH|ˆNÎåRu v('ª]ŒÃò¾ùБÇä^¨X½ôm Ë#ˆ›?4ÿríà×léE¡1ž\"DB ]Üæ’ÿ‘Õm@zMûp&<ƒ.·+Åé,>ß³kBJÝ"s¾‚ùiKèw«b„¿­C$†gãÿ³ê ê®Õ,C)6 I½Zº‡R6[¨õ:^£œ!ŒJFRêº$4Jã7¨÷-çWaõ‚Ó7õ‘e9Œ.žDÑÍN;ê(FŽ>Èi‘ìÑu±‡…¢ÀåS‹üXðÖ3±œTãR_ƒ›Ñ¨%­Õ]xº/'êžxx4%v×À@Óì#Ø¢Fä†ËgóïãåHœ¼ªf¬bÄ’NàŸ\#Í,eLç—Šº^w`Aª¦½+|”€ ÒsÁEþ]WÂý!B©“Ú%ˆz<4aÓ^ËèÖ èh¢™ Õ¼Êæþ3ô–dÉÅœNIÞÙPÚië,Ýp?µ’蔚‡NCplÞ¿™Œ'É:¿õLÚA£™”ï pâ®]?oäyÈ#dùÞQHÒþÕ³™7:¶:­–D7rùH¸E/Ü0O°6ûâNhwJaµ˜*Do¸y€þÏ¢§Ã*.¤3ŸN÷¬Ö/°*^QSµ•Ì{ÊjûÄ…kz¤M2¢ÑÍÆ'Œ¯ðIƇãôš‘‚x8ÍB†{Ó¸&<{D½"‹ Df%C>w>Ðý[ºdüj­É~{×è°%€Gµ úDˆ\\( é§|ƒ0±éÌ[®Ä· 6"¬C³ývÉü˜÷-¬—ý`M˜Uü¢1•иG`5è¶`]Bø }7Tç(¥x}vÅÝÙQfÉðj¸ZóZì’RR¡({öUgÚ¥íôò&”û%±àÖ´#¶g$ÞóêÇ5ŸåûyU:ë}UÜEÕô]Âó›þ ÷‰¢$‹õ‹>e1ïO†WÙ2jÄGzÏç³ ²Óœ ¼@§Çmªùy¾%?²\Ãñi&Ö( t{Èjz`{\êe0 ögÑíŽÝ2³d£aZG‰b{îQÓf1ç|X·nUöóFv@G£ñx£Pƒô*wšxÌ—_¢áÛ—ºfQÿä;}‰2f> WÉíõ°B1®Kœ9 ÂòȰE2^Àu·]ëhkÄWBD­· µÏm 2 ¬ÑÒrÒ›0Ï=áK;z4™z犩'ú×S7K\åžIñ]H¬ÄÞÎs½(tÐ9o äÿ3^7†Îzv+ÈŽ.yÇÓñBæ»›Ü=&ñ9Õͱ¾Œ§gL›Õ`r3¥_Ïþù. ÒëõE»¡ÀRƒÁ«W ’›˜¸jqZ½µgü³uþRå¶€môÜÇx3ûÓÅiÁü„—§•S÷¨^4rŸ6¯<}5úÓÇ$+é¾I—ꔹ fɃމ¢|‚(iµ^]þx›~êÅ»²Ȉa†+¼8\z>¢ë¤^˜]Üã,…7:¾ ïiâÛùÙÛ”N0Ô3&ý_VâÇ<.ö¶^® žSc· *òºÑl oÆ^ÖpNzN#g€¨…îˆý0,)XæN1Ðö}›çóG›j©'‘ŽT¬4CƒÈ „Øl2Åà@è¿»ç@6Îñch«xŠS}õΦ¥­yOMè©gµ¸/w–óÓj"(PD²¥wž0ƒ2ýÑànu.Óc¬ªDiª0ïP†›NœØcqÁ8§6㎊Z9b³ ;³zå"¿¦õÂø¢i¿£"¯Î|ìw§ùG…¿2X‘”é2­Ÿ–S›>áI³/“à(Mó0×t¦Ó|‚Š™ê¬Ï// Ø "œÙˆvbŒ=ŠdöòŒÁ›=jõ¸$Y`µ«Â' ÃÑF…Æ3GÇ °Úêî„Ð uýW#²l£gPgØTÅrÕ~Q Ü¿ ÛÒex5T.¹¹9i`Á:÷u^[ x»A¹(#¤ÁŽ@IEëU}FS˜ý2$“yló[KŠ𣼿µAhIÇÒR~ök';é—d=Añ<ˆD ÑñDLMЩŽr ÕÔ¤ysGŒÙÑ2¼ŽU'«Æ¼º{~ÅÓKZÙìR°}íØÃôq‡ ,AOAudÈL÷UílT‚¤kqbx‡¿åÍ•¡w[vrTÓŒíÙ#k%„$ÀØzþÁ¸õ_ô›ÓF%Õî³Dœ°œ7~ ®‘WN™2}Fã⮘­þª,1UÛœÒ\ƒÛÝô0&-eJÎXËNà>pýë‹ ?Ñ8°UܳÃÕ18•EØ´m“«Ó‹}wƲªÒ:ªÛ0Ъ…î²*Îv?xÿr¨‚™Ì2$ ࣗÜk.»î±¡îtTàáú–áÌýb|$YJìrNެ¤«ý»NƒWQ%¸1Þe—8£c:8û-˜FN¬ 8ƀ䙉5š7S4„?}¬¬ чd±mŸßRD£ºà“¿ÙóÑ*†±¿W•“Rt•$M¦Ü»#éCœ$ç“ÅÚ2Xçî1*ÌbåS¹s‰[CHÉ?XcÖdgù@yßÕgéUŠc£`ùKð\¨¾3GLq“<ø ÷é"ã™pìodo‘Û;6ÚΩ?¾ƒý¿s{wõ¨µ™Ó%ª>fw¶N»¢ Ÿ¹vi¾+.pkMg-s«RÿÈŒè…dsÀxvåû–9Cf›ù?:ÔYºUPÈÃ]—¡S•]Bðy+s¬Èšw¼:¤ç‰P ;Ø(zñÆÏ-F¢'g׫ÙϪÙK%ËТPr;¶g¶*g;#­¿¾„¬;õÂm'`C2Ï“.æÚxÓW†uoÙ<ò ÃR΄DÕALCÑ.¹»½" ‚eAk:ÊÙ40°ô™¢“hþ€õüPtjv2àµL1ÿŠÁiúAžöA|¸¢‡Sn¿Œ¬Í}¿g·Rtžué /„{Ý[°rì€Àü±œž”Ûyß?1pø3RLá*”«Ì“{r:~¹è=â Xî1]‚9ª[2’r^Plz½µá«ÄñRXaèëD‡*ÃSœ^^ƒšd[š­¡Ó§¤,|-äé¥a"Tö Û QÙ—óµâ€ TˆäÓ~í”ÆƒWÌ,d#UÐ_Sž`^ó?R$–0ßİ3¯ÿ2úù¸‰f‚C}ͱ¢–×ê‡ Úqo¡‚DpïbÎFQB_{’@r¤0VÆO³¡”e§8…Éêú]\ö~17—“∟ÞN7†)[ÕõUŸ,èAÖ–ökžccçoXïe0­XD}ŒH:«|gØBsb{$Ô¹“NÙþAGMEæ.§ì×ÒR[ˆÅ« ö%Bø’lÙ/¸x¯¸þ_ÜŽÌ“t×mب2E³%U¤&½šåÑÌ"+‰å! ‚ˬÈjû>¬zð¨ÃÓl¿T¬±oö] ÃÌêµS^’ÍÜ^·PØu‘ËZúP®¢ü»ƒW3 3¼:¾lTÛÛJj6è€ÄŒ°Ð¥Õ®%ÜÄ“¡!=OßΠ$×xÎÔï÷ˆñ#d–¨‹$R.Åœ‹¬Ë¥DÞ=` õ*ïƒæV–ëU²ÞQøon5e XÏñͪ¬´3wbü#³^1ç»›s&À^¶(ó©5cÏ<±LˆŒ³ßÉÀø8¯°°åäóãbÀMF‹ŽÀCQóJ›ZÑËej¾[ÄGIJ/=›’ïA`ä>µ—)MzÙhïP˜^3füŒï¥tÌ_µ’ÅÞÄõ“ɾ‰ßo*œedï©°,ÃT\9»° ß’i©Ö.c_Æö¸z;Nû•ìÔ?Õ¶þ\m‹kç²UÅf Ô€»IRg¨£v;±š³ãGÌ[0)å—ä<|ákÔ|ù¶âŽP<ÐÒÑN¦™"Gî6eú—Ò»ç‡rt`¶õêÊýüu ¢ªábwkÝãóÒX°à•%¡Ö$¹ƒjŸC×Kp |ãO€þSæÆueoG#Ò«c àç8ÊxÏÓÔ Tu¯Í¶gS†sáEnjȰï=¦›1E¹[( nS(¡çŒ'à 3°'*b9“¬Ê̻ƽ_‹™ÞW ˆ†ÍÉïK襢áP…<à¥tÈ;Ùæ†‚æO ‹ÕáGú`‘_+ä¿mB§BV ½¤ä¦Úº ¦8ËÇM"!>Ü(]û4Îgfiz÷:jãÍš¢Î.‘º0W¯þäàÏqô8M2sP€¬M°=ü9Z †8¥  ë9¬"Åtáíü½kd¾ËU­ÔuäÚ¹ÑÅO”Áór8¹"-(G7A,ù…M|¸ jë¯dx 2šÐš¹X‚¸Ñí]!×7vf—êw}Ofƒø”(ãïן†çº¦Ï"MŠyyZUf£ „.”¥íP‡(„öÄÙt+Þ(¼ð!“ÕáSèó…Hޝ{OEyÙ?pØ"ÏÄ! Ó==ffn%IÙËoè«”sñ…å)pŠ|ÞªuíL²ò6Ë!ͲXH²Åz¢u5u`ÁÓB'³.wÝêNûxðD­‰Dä 8wPrÏA?B-?yÅwã×T(øEÔk&½ˆø/· Â×IB5®†Ì{Ša*ù°õÿPêm9”nb§}çŠWŠgÁŽšþ]QdZKþýЉ?_•[¢ $@m\}j]|b„ÐM‚•ã-µÞ×l0–Tʼ©#¨QAÁ&OX¹iîýÐ<‰˜Ÿ=»”W²²T,vˆ®ÜLåðò=Pª¦Zx<È<õ•$‚å«å²çEg©ImSýå_ä¾Y&Ê!Ö a¢;"2``6ÅÙôT«ÜÝÓúKɆ˜#š:„«¨Ò™†Ï~hÿ{ÄA{¶§]‹³@kõ¤¬IbÙ‡5q‘ ñðv £Of´…ÝZ †ÆMÕÏ:®H”PÈG8ç^øâoHûb ˆ¯å.É)ôp< ¶0Ê«v*ʘ‘ Ë[âo9mi CüþÅð”zªÁÄ_cü^zP1ìèi‹U²^àÆ 0eI5“çÔ¢³„Í¥•?Æ¢WQ´ZDPJŒe°ùGGPÙBF×^ƒ÷Ú‡}ø©¸hâðm‡0§ÈóÀšzõ·UèUägéªy@_dw=RûÚf*&¿t?‡÷Aû›¡5Nìí€ËŸgÐ~`öÂÈ»g—/—ÓÝ,íN]<…%i{{1ŸùÎw Å6È1ÊR¬€ë™•}J¶04¸™Ý |z ÃÞa¢ÈI»ðɶÛEVkáÉ)¨Ô° r@+|Çbˆ;~ó^ RÈ>zùæ^Û)ä_çlIf|R8cm}eê‡ç Œ¸;7ÿÒ €YRÂÓíÒt´öî­`¼¯-ûñÒNM¯–-Y§±AxC;qæ5¯ÅïÓ—gM` (æ—ƒ[XYR¯‰Ú……Þ®ä!ÃlÍùMÊhÿ³NÁßž_es$ˆÆ›}Ìèm¡4 PÄ’ ·7ºÇ8Â’u€Þ©‡¹ _`°Ö©¹”¤‚îY¿í!ÂïRonä-(Ξ—M„ äE¿ígÚ#ï^ž*Cï´è ›£å,vÐÆÚ&¦/?ºVM ¬¬â‚,dãü~ò6kÎ…>Ú@ûÜîÝõÒÜK>ÁéžW®¾ZçÞþ)atùŒ'->´”;45b9©ß&S 9U*Ñ®GoÇÍNšîrô©…ò†?iŒù7ªÙη¶¯©!l*9•.ÍV8u — Ì­[r0¨p«0P93ÕÞäsûm”Ï/îúš0q¾ýg®ÚÀú¥ê)™Ò×ÅRL4BäWtM‚‹~RçSèv‡€\>… Zév"’‚§$îñø  U¶‡°kfÉ`Ãb;sª22_»çí Á‡zsÖ;o’å-ÿŠ®Ta1i\‹cIæ¡+òð¹^lŽã…P¬·mnÛûÙ¹ºdµ}ôÍ´Åd_Ë3â=}´Óý“nÞP‘v(3Gñ‰ š3ÔçyO;1Û²JÌO3‡r?‡!p5ÞŠ„"§SUVåuÄ‘çšWE2Vºµ*$øž– »‹l|@2,¶7´¥+Š2[S÷>ÊÖª%b2íTów)>Ê!Ç苽s³í Ü v™èë¥Î9)’>ìRCßà^+ýu®ßm¬7< Ò3:änšÿ,ÈÐH“-„_e‰Š¢L ÈEÚI`€‚%¸³ø"ï:Yà³ (C­ŸÀ°ƒiâb0‘qìq¹K“V¡ }²l—~u¸ ¥“.[´jÂŽ@š,û–H߸—Lciå‹ g¡Õ{T0Bbh¢|a³×Cø`fÓ^ßw¯ ^-óWpíL¸\ÐéUÇ]|$¼ÿ0–?>Fu+¥;Óœ|&åæÿÍŠ Äü|bIxV{?(¤Ì l­:^ÇÒ­O¦ž@oÍ ¨a ÿŒi<“l»ú‹É™Y§é[Âý2„eÿŸTN5E9—él'Dµ…ÇÆõš1ÚCLºÿêkZÙ·RWxše7/µnk4£ Uædæ¶ÃE"Þêc›‹7˜Ì©O#«ýjÇ܉'œÍï/Íç}ޖǼfQAšüfâ,T­m­p¦4ÁãÒKñ.÷a”§âýÞ“Èx¦¹í@8ŠäK%Æ¥KÙ Úîåt¾0ô‡À=ûØ%0LÞaá!] ÎÉÃ(?ÌNLTךâò'Ì´?F †;ÀfòŠè³°^ѽ ¦óÓ›IÏ¥ŒÁPä¤gܱ‚ï2:÷­ì¿1z·ëE‹— ѼBÏk» MÁÁúm‡{wÉy¸R3A_”[Ñæ$ž*í6†ƒ*ÏÛ vmÄW¾Jña„€¹èçóÍ'¤µ„Ë)Õ/p]„üÎ[Ád¥iWMŠ1 9x4,€ñàNôWðñ;¾h“]ƒRäáRN;ÕBnb¡AF¿Æ ò•¬íÍ!†èƒPíB’0Ò=kn©À&e©,PÆÚÜ4Ó+Ÿ6‘¯Pă4$oÄccr°)ê¨Oj÷Ì6T¼Xxï¡ :3ÏçzæŒÜ%E›ýs¯³–²ÊÞÐâ¸k7êïˆg1`Œ™¨°CJ³žDþ¼Œ+¹"„ìGèŽãÊÔÇ Ñ¸«¼ìtų0<•ÿe—xJBˆÁŠ ä#x®‘øüè  QÉ¢ªrç9ƒ# mñz*`îÊЄ¼ÔŒ˜ž#m7Ö°—еâPË’QlºK:¥&˦.yJw¶šú`·CìdÜKºUD¾REÞ3Dû´)¡Z^úAbŸf )€yÆÖp:³û]¢W^@ñŒ—¶"%H}`hÚ4Ô›éb•¦±Á)¹ÀhgVwùša×uyv¼+‘î:^×][ÛJ ·ƒ°ùurÖ¢„ÈtŒ¶À¡¢‘"Ƹ+s‹Sf‘.Gð@ÿÄkä™ )ÁAIÃÓïÅ•à«Ì²Æã½³¥1]äœ÷:^‹Aw²L 9g3D‘K®ÊÌ^jkl»@1sª‚L5Wȵ2¢ê£jÙJÒ“š`é} º« "õHJ«ðuƒ™zÁv:Ì Ý€þ\sö •K@$ýê{ýrúWæ=Vp_ìGÁ³±rs¤Œnùx•­`îÜø7¼'A:ôê{¿<¢œH0»jààÐ[GðØÂfø”¹îçã¤v…3gJ¶Ö¼ÑŸ£}U"m*¦R–NRÝa÷Üîüø[ƒÛa_IK ±Dâ”–·†£ÕÍEèôh@NÕ¯>h•¾óSðä$Â}:é@üêÌ<¶ ^….9ë]N:â;W0>ïú±‡TûaׂF:ðí"¤™KWÉÿêë®HnÅÞiQ +å™A¦ G»a¦kÝÃè¶â…98|ÖM4àèL)±¤¸ÂRXVÆ? ’À<ÏEܽ”1›©Qèùúoûý ,ø {™ì^Ü Xo¹ÆoFÁ¬âºåN×½Bh*¯­Êv£,ë ¨d~G€±g÷àŠ²©ugN±Ñpöñ›¡Ï6d£®YG7Ü)^o0Ùõ4ƾjÓËÊZg‹t.Ut‡²¶pü>ÁÍ·i·ÿçx‡qlî¾õ¼­Y!dB’mG!§F¡>9Å6‰õP@föMÂîÍúE`‹•<¹çn¼4ßn-R:¤,<0 ¼Ùð …iÄéaGj,VŸ©!~Ïœ‹.Àôe<ܨ<+ –dH\4ëÁáµÄ„†‘¬ÁšÑ©’TÚ,joQbÄp±iñ¤6‹xÅe“çhñµ6ðû´IÀï•1t˜Ý Ä›¬áù+·=‘VòÃy:\¬þõÖ^òÎä¬Å}X‰Î—½¸Ò=Þ7®MP¯ºxúš-ÛãÖò;Î\°®Ä¼tÎ0·™[㨾M]Rf€Ñc¾P#…ÉàíŒ_ôJùUfü’+ù÷k”Ó_ݪJ:Çî¯ öpѼ ˘Ãè›5[£òmj™\.r¾ÙAHÛYÓœyÔ§7öj’¼µ—ÿsb|„‹VJøPÁÇ€e‡í’dÅnˤŸ_ÜD(´;çPg™¦Æ×ζi¯Íò •C…”nÛWˆ¶ i"Úx×ç`ÜI¥íPñßëq±ÿÄ]Îj¹sÿD`ª¬¿?žIq°_+g0Šo÷HhAqq©e² 'ãÈ­¾%^ùšìn˜œ7Êãý$]ÇéØ]XôòŸ%–©(0ߪÌM2.¯­ª›4D’o¨x­ÂŸ!}’ŠÅŒ\$åýî!ç#>&4Ü,¯Uøƒ* œê½1MËXº”fØ»žô‹bÖ®bñ±p’:†›eŸ­ê 0âk‚Þõår_-¬`´-(“nîRe²Ì¹ç Û†´N¢! n¨Y¥%*®Õ[/ïò+΢¤w/æå};Òùn©Š<¿¦ Ð’g„fPtÎNdŠò~ƒ@àLÿ9ŒXkXYω˜D·~ŸJwó° Ã$Ôò8ØISzíwJþ&ƒZ‹›Hçà£IØÃH네ۤëeÊ2_˜úÆÄs"oxÏá&º=™§ˆHîR<3ÐÌÐáüáâžß§ÔîéÏ%ë¥ÏEÏ𣂜ž¯)²¬×IðƒÓà¡5œ{Âv³¿Þö2ÊzÛY#K£U0…I{{·ô/)Þ-äBÉckTçùuo/ܗΪs©iFDæ"/oƒqÚë`Ù!¢±z“Oãƒ<ƒxJÛ?8‰_´ÖcT„ïeY3t¥Ó.ÁF4ÁÆ|Ô©5\6 [i“€¡ê+FÿÈìR©O®ñœÑHë­€$ƒ°âøÆ|¾GÚt˜~fL¼²c¯£ë ¤99óC&;/ ·Ik„Ï¥†½1 "(^F™Šhݸñj.ëMU0Tãî˜ühr”Ÿ+.Šß&}·¥â[z/PËwÉA’k;hÀŸ —á¦5üù:Ôr0”xQ}~@¤crCq~l‹u7ð°'e£„÷†.ØG†§«ó ßóœ9³†^^{HQ©¥Ô«{:OŸ~`=Ä]p¤È¯C4MÇ6ìóÏR ϲøÁ)JJK_g“ï®hœÝ§ÏG~e=šb΃¡X¦]Í8v“$k„ÉîôD\^ßn1ÛCr²—Û«¸,”XíRHú'è1áìÉÈÖ]†XÚ¿òŸrÔùµ&‰8Ô?Ë)OtXY µvy7õ³kg^EZU°ÎeèørqÐ+ʾÇn§Éœ¥¨{®lÃqÍYÏé#þûûQ:‚jTžö–PÃæ–KT¡~Ñ~|þZyе|õð´ (,VÂÙˆ¥Ê½e)#÷ú^dÏðwÎU¹ÚWµUܦv x´ã-½u 4•Œ‡‰Fµ‰ÃÀÓí2-ç‘iEôïG?ë– ýEäæ:¤þF"^[B`èqT¬¨ †h‹«ÖŽš5çÌMh&çÌjï˃J”™*#Ž­‚|«£E1U*¼5<šv–Uí1€1ÊÚÏÌeÊ}ÜCAXâ‡Kl}|Ù™í<Ñ[u`í}Z ·bÚ‹zªŒÈ*¿ÌÛm% cÀªs¨‘6|„S½²21t_Åç;‰þ”MCÚ$ºÝÌèfP Üï ›;ãé|&Nà`ÉùÑ•%^m¤™î4}ï ¿Âær!ý¶$ ×àB'äξ¡ÉžD¯ÿ2Ø»T|¼{i#Öò—<œÑv_‚w&+ÞþásK¬º)·Aõ;û¬B«œí˜y÷¥dŠ×}¨Æm™¢¶²s~îO'Ua|cZAÜ NU¹–øC¡'TÇÏÂ3¹ß×€E½_,…» 辞Ÿ-4êR•†«°u«ºÁw®ÕN-!ÑIhÍ©_(CI€Š¦Yàb|1xçÕH{Á×Ô8ôzàÖ Úd˜Á¦Ž(/Ðõ{r3˜ÜB…俨AVŽ ¾izlèGaƒÒì\1ÁºÉ%ŒO>®‡ZR|!‘3¹“·>eš9¢ü·¦¼Êb(UO¡o©w|Â+§ƒ 9¤9M¤Ý÷?qi—Ÿ’»MEF8àbUV̸Þå dzù+Œ –â;T¨E¼£)fC‡8,¶ð\ Ý“ †b_sìNu)ãò”ñ•2Ý}SÞ W‘áZ‰\ˆàߖוŒŠwG<9õLWGÓ„(GNêÓ^íh¬‘~м†ââ:[“¤Òâm÷úSBíîZD̾*é‰PRà$¬¸Ú»(3¸BCÉcM,F¤ˆ›ðˆníî¤yÍ=.ÙÙ•M»žhqçüï«(:tAIÎÞ±;™:ë§Í¡ÒÒðyQC:Ùu¯á…ჴ­ákOîʦ Ö¾¼èýNê6i¸ D-Â’q”ó•W×¶Wy³gŒü;ViÔGÙ0½ ïx• †Æµ]à”⣧4_ÛJ!ÈÙU82U#.‘*Ô(T×îÔÊ)[OÈ~žÆÕ¬…CLn¢Æ„âµNo&q:[^¯¬gÓ›äè)Ã%3,aHÖŽRô´OK¢¥³gÂà3A",ܪ6÷†n×笯›Ð'pS§=|I›Ò&VvXôs‹hnë‘ΤD経 1)ÂôB\mË­]–Šâª6Æ*Tn©T$ô`ª*Å•øv{@ŽwŒ ]=Ñtp±]ü½döªãŸËv×:eSuî½ÃåœìŽÅ/¥€q®‚‹ý†…åï…˜°eàòQÓùw(›êÍm—­:µÁææÐ§ŒïÔÞrÝtÃà  Wòw‰z-øÛ·Y1!°±Ûýmj £H ›º‚Èܸ¿'Éû±ogWVf¢1—2…ò¢ƒ–…ÑFÍï~ß_©T8@aÔš°Ê$ëRKðo\J ÂÚ{À4Áwx<ìöY6’e÷ì +þ¹ñé,˼!†ø—Iûv÷h#ONŸÞrÙ†îs½`R ²ÞÙº7% F5uº|÷ßÑÈ×u.!ÝÂížÕÍ t±>égFØþX«*ÏGYn¢5µ‹ß‰¿”Ääy ”|8îeÛNc#™ítRÉêâv'Ô¥²Ã¼bØëQÚ#õBQvŠ<›7@æº"òèy{Õ~bóqÃO‚¾®Žw¤ß)>@S~¡ßD)^Ü888}tä y“ÿhK—‚F8±6 ±ySÀl˜…Ž'sŸ«Ÿ›KvàÞýàÛ«aËÏ|ÔÌô¥£Z>Þž®©µ¶¹Ðf 5a!ÂÞµ° pŒ—Ïü€ÎS_eèuùg4‹ÐMðÎS[ÀÈE'p‹ÂJ»aþ6,ÌS¥}oÖ„±3Žžš7ð`ê&ýïÊñe·»E—Ñ7û*Q`î¢O§ÇoQʺˆ±[|)ë‚>ßì†SùºBúp•P½ âQxà³l‹›ºÍ£RÓqÿÕ®¶p^ØØ9uÈq7VÌÌQL‡ÏV[Ÿ–sÑ'+§ ç“>ÿnëŽìž$çíûû²u¸¶s†9}Úg’0qc¥È9¹žÉà™ÀNê¾vHÀã!ÒÅPþ"¸ž`=RÀ%īѧåvJ‚¨ímü?„«¹Žç]†D©2ýè³rƒi1ÅAºÔ’º¡›e³Qqä]ͽVœÄuªV1<Æ0$·±*¾›PCbax‡ ¤ˆýP2¶®’ÉkG19ÒÐñ™¦ šVÂUäˆjH¢ŠcâìƒÑï"oºÌ'­’â 7cý©}îŒ _œ)Êô͘- Ä'ämëb.$C¢}ò d³jøä¸ÆŒi&rJK+×,$SÑç;iö:û©âÒ„¬h³rSoå{øž%hETÔ‚JLÓåè!Ý®­B˜㨼·â1vLm¶’žq„ËQðP7L‡ÏŠJï×jÇÓcGï¼mIIók!ŸW^Ì0ƒe¤iqWf3‡6j›„\óV¸r™Í)šO ]R„Po|"Å{3ƒË²Ûk)çLA%m4á%â´„µŒ‚ÀüB+êB0‡çv™¶ÑÍ…•Ùû5Œ²e&Ü A¹Q ž†íñ“Õï™ßm”¨°4çX¼üŠù£ÑÂó#æ$¤¥‹­vó“‚3®i§:¬UPtÑÿ ó§Ž»#âUõ4fY) k—µ}3¯ÅlL!Õ1Õ°#>fcÖÅ5Ï”5–ú]ï“l®ØËo¥Ý3¾LsGW%ÝúL­m` ‚Å‚Á¸åÑ|aobvI¬*%©,cU˜Lêg,šÐâ ‚v²?[}vÝ(qå›U”u(HÄ%º>Ƴ˜ƒ,ÞÛ<¿XÙjc«5¡DåGÎ'sÃÝ&]IÂ?’1ýêXçn‹Óá{\˹çÍ„1+—±L¦—{ªM“B ‚Í–òŠeÅ Fp¼h¶•`ÑɦòÀ;ˆ±VâäG¸˜§þÁ¿øà¡Ö=¬Éå…åGo«ÓPÞ¸?uÖü \M¥)pd°V;ùälÉbO¤¦z_«FšÂðš RçfOÅ/^‚VìÙçÂ?c(¾k1×S¹ÅROÀ¢O[KÙG~#ôÝÌËDøÃ]mýµÈCÎ{(D•ωû‘ñç°Ã“eNe}"!%ìæqÌŒÕÊDÀ@9N7;äVöÅŠhAž^áj¿Q¸ÞR„¡ò2ˆ+wÜÞÆÎ+å!¿§1vBpðÍÛD†¡ó_IãX¯‹f RÛ°n3\[.z FÃq Q•gZ¢ë ¥ògˇT·ŽæcÅu¯f³J1æaš+ÕÏrõ:U›ÂÉ;ñúŽŸý7N?øÂ÷/Š5PZ.ƒêmbÊŠ@:¸FîÎ-O}PУ9&2œ:¨¥­'N¥Ï|—ûuGœ\i6§´’Õ$æ+/¹ÊH?‰8?hKoáÒ=*½ Ƥ…(&µÂ–@§aÛR¥Ñ¿KÐ0ý­ŽöÖû=á¯Nüü²¬{iú©›`¬ô«ßkCvü¶~ä3x­º*Žâõ>'–mó€¹GØ;ÿ4ýE(Ó:°%Óÿ“”U³3db’…„ €$Õ¥LI5Ï|T·æJ‰[üÐ%:cqª-¥L½å¸|¸tfHﹿ-6N%—b|‘i}x¬¨¯Â×a„Ó›:dÑî¨XÍÆ(«=æ[¸o ô±º_e×*ø¦ž£×°Ôn ræ¼+äb7Š+³OL‡ý&1÷mÊ-Å9‚ ‚Ìd³í7sê $¤= BðÍ 9$ïCÌe±Qjpô1k÷´\´Y~éF&†xѱÞ#ï“^»VD…ò_ásû $øðk-><êÁÝqíÝö®h—»|f çšgx–M–º§u•·ÌÀ`G¡ªà“d[R|c£ùâ¦I-×~¡çþ0ÍV;¥®çYŸ…àhÿö†“V‡ÉÁIEä蕜7Ù×OÃ6¢â'!p²u¼Ê2ÞB¡«5É=ßûZ©ÛÌ“o½‹O”óŒÐY§X‰s1Ú«‹¨y¦¯ºvòz[`‚®`¡HDaëáˆô“숟FGy=A™LCÄMîÐ à;ÆYÅÚÞÄácâw p»g›/]rÏçëcg~XåSR·fŽœ ´ƒ&ŒÓPtL0ÂmŠøðœÍ5ñ³’·/&ñÒÐ[¢–[°9£M}ͲSmnk5ZpV‰ðésÈyõg×YwÐRæq}ØDƒ Yº‚8NÿËsV»(ïýüWŒïu‘k†¥‡¨ Sù Ý*ùÚìHñh²»Õ…-ógBÊSö="Ûf¢D${&Þ™XW]¤°7‘¤%b£ùkñ6˜nxßP!9õKÐÓµOØíÞG“~™ª0|Å%¯ TRȽîªÍ„ôn¦CØb±&¬Ÿké"‡› kËvv5ìR1¤›ã[Xš+TÐfɈ¢(z!¦ íîj;v;/“w6×T„(MlnÀTjÄ<É Œ‡.ùŠên/íI®î 'cÐó=ˆm¼ºK?ZÚbyåŒ\ॸš/—8ø’)È>_QÍV¤v¨.ŸóÏ©{C,VõåÇ/Òk™|þl5…Ïäì§)rSÃ)UQCŒÄEY^J÷™nGPâ¿ ~I |JV©aIÝÎK— ÎNnzõ˜µ!|(ã!¥?`ËÂ*ÑæÜ%z2í á1±H)R^w8²Ó?•~Ñ‘…sÞ:‹0WNdùÉ9ý T–£dLÕÄ“¾@ñ,—&$Ò°®û:®Âd@ßãºÓãEø5„ĉZ¨=Dæ›øè퀲-„Ï'% c'Cï™t3Ê<â7äéÇý {e,4Va1k²>Â%4ßœÔ\[_T]Ù¡ó‡‹Æx„”Á.(´ýFé‹ ¼/ >øK»,Ó´È…UrFÙŸ1»5ye· "PõO+‘¾P©IûÃÙG°ðãÜ$Ú~®–H;³‰ÞÜ%ÓL=FôÇŽæ(=ÃËÃ@©c(Ó{`Ç)êrýl'þÞ÷˜«Œ7ÃÞl#ý©èg5hÕ^ÕÆEïˉÁó•Âg«ßþiýT³q_á‹]/Õ^¶)Wý á=‡Üg¯ÿ¶ ™.kß…˜Ù€¤4ÆJÛˆsy7¥6ãMK?s;óuùQí~P4ÁÆÕ> i¯’–ƒ>ìïssS´ÈOµA70á› òØ/*Ë­&s³1(r'„íäóHU¼"’ÇÏíêÂ)ÆöI‘lŠõ,æÒg:¦„¨ÑZFfۖ𰺯°oŶÝ”Ïe–ÆÞv`‘àRè.ßõSº™€üxt^ž÷BõÁpØUAö^Àú[Í 3CoDÈHôÑÆúØÊV)5ßã% Ϊ')}&ß’° X˜.¦.޶L¨F,Ê·U£)ª/¢&«Êͬý—®ŒO)c÷ÛX™@dÄ×gÑ5Sâc£khU§?îA)mqLK‹–ìuÏÑß®o352dÀ8ÞYk]Ó†[ Æá˜ÆÔõ%=ÖÂ@‘EÌ€+ùE —'šýÝ ¾U§ˆ;êó/wÁØw¼_Ô2ÈUóð¦ú]¿\Ò@0QÇË?[¸²Jµñ†Š*d]¶«ËÃuŠO—¡Z,\<ã»#÷RmRŽëô3¹*]=f`éÃ<†p«®Æd 3WäY5þÑØŸ„$Ò‹Q}scÛ^š„ñ­úûHþ¤m¬ÿãÝ2¼žñSÄaLƒ^ù®«"0›ž‡y-œ“ñ$È!šAɨk‚e;APsò(^ÂdþÏE(CÛ”õŒ&®#êd¶£;%œtyœ‰‰Ýmó™ ´n ‰yÕŸÓÿT æpÄ£#€Å`/‰!B9RÁp\µàÏ‘W.ìÄ…KëT6I΄œ½–ɶ۬·b!t¿®ÄNC­/3 =ðøz’›ìé)ÿ“žºáþ&–QBúƒÊ™Íô$±T²ct›c"h¨H@0­<‚¢èªj`%'F­\–ÈXU,±G .ùLÙL_yÈIÐxà7×Äò¯Öe#›Wٴŵ$ØDÞÝE!¸ÿºƒµðÎ<â°\ KÝÌYªíe—Mûw¶¸T=)pUÊù²É1æÍQ•Ñ£¡XúJCæ“Äoˆ ÔôÝM2mSâ1¼î¯Š¯ –9 ^˜†~Qì(|Â6SSLb &½|l‘DøâöRåªÊ­ÿ Â  §¹óúØ›‹¶Q3䨧9X¨ËèÙÇÊAúAÒðepʈBþ’¦ù§³ÕÀ¥ö©Jâìé¬ÛŽ<¸„î”NN BÄöÞÑ8“oõßÿ©ð¾ýëÎ1eNú<㾈•Ï´R³”‡cô5Aò¬gp€ Ÿ…ËP ¦ãùô¬Fþ¢!;ª·Go¸%~Ô–ÙoÓoQ2[R~£§O³Ñ¨§S{[äßëm«Gú © Ÿ7ªH#<ÉP3ô “¯RÐýò%iæ”øè<7‹ßð–õÔ¾ÕÞ"ë5ÍOA'2?š#= ƒ“ž#I<ïÁ)Ñ«„Ë¿¿žl*ˆ½#¶a$D/\‚µŠ’÷@_ À8&ÀQX½q¶€øúbùÐì¨H!ýøµS?² ’Wó|", O^m¼6 ±sü¸sÖªLHºô¿²Vª®jûׯiãübÇ…-¿V\÷˜ ïž§IŒ—°Òc‚CÍŠ°â}ÆðFgΣ„¾Pâ~+xtˆª)½ÔB³XGc),óUgÜOÖ]DŸ/qú—rPQÙi=½(/êÛÖT½5¢è]sW3žy)eïÞEkc/óAŠ>WÀ.…ßÏ-§&ã’4Ž6JÞiœÈbc=ÃÌ ŠõD¾GØ]`‰Þeߦ÷'~eFBM0×L³:]Dõ}4¥.Dņ!)LrW_Éíiè¾™„ZB¢Ó¢Dð0v™zG~²?Wõ‡2å› ,T38-§cJôö²+›~(3øÚ^ò5¨½ŠÚœè(õ§1ÍÈ÷G§t¶sÁM;hà·¹iãf|´?}•éPa?/ò3~3·"“‚d£ÝB)ñlë2YÄ]bÁX,ÔÌÌÆ ¼BPgp貜^™ñ¬bÈ@Q»¥“wY á?`G¢µäïsu“"!t¢(/é^2›näÂõP7/oŒ®ñ4ÖP&‚a;h!µH÷ Æ¢RiùnÙü†'†Èñ »Ä{H¨U vØÇ^óÌ4˜Qäç ä ·-tý:Ú}mS„þ‚üúÔºÙb§a­ùá¤y9¥˜œ¥{9¨õûæþÿˆ6{#»ÍŽ›<€iYžW1±oì*ûûn—ê2 ™p¬oè(È$A5ŒÎŸé%‰U_¨Cåö…ë•¢ô9ÝÔ¯œ«æHØq_(Jõ±ŒêÓ–ƒP®Bü-‚óÚ—æ JOÖ%Qܯ³¨ÐF!¥Æ$¥ž' V}¼‡%Øk~qÂ1žü±2Á®×7j(‰ªgmó„òŠ&_Ãt@ì¿Ámnš¢È;wÎäsoMÊÔ-à§lÔæ¿ýŸõJD°)œGâP4Àin G× KÂo½YW!Iz³Q¡mªb­_HšÈ¨(K1Ì Oè~¤/%ÓÕi{»äÝ›Q.£—¶Gt^ˆ$@¥ µ¡-Ðù<îvB˜ é®ß÷è—8tÔUõ½ã˜Aš…@ÝÈí3»Ê¿á£$p€Áb¼ÜÃŽ|¼8^£ß'£è&A’Óë&|!¦Ñmd¢%(º2ÐRRÆ¥– p¡lÿub¾yJ&OÞAäóÔê0J×®´eè«–ñþdŠƒ­e‘c¿e@qY‚´#í±Ž…ļ8ÇéJ¾2 b Ñ />ÑÏ —D»ÝÖ_s·”žÄ¾G޲„8=ª‘žu¡œ ɪqž” 2‰ô˜wúó‡‰*I¤ŽÏ.lÏÄ1ïèOËÜ]}þùJpzd{H™‘1~qü¬ø¡­Ü«Â²8<õ&Ñ\øG=ðí"ë½,Õˆ‡éõĨÌ1ŠêçÐvþÜ.q¡6bÜ·§KNãÌú i¦„·ûŸžEÔšx¹nú„É ¦—"¨Ìag“Éä›À/ÉéO0mC2 SÓ ©¿KÆØmÖöÍ8wâUÌ# rü ~a¡˜’Ë̪ÍÎj»Iîx+¸ªÒÕ)t o¬µFž&›k~caE!A]ç½)øîðÿÙH£~×Ù§v‰lC‘¸%IÓMVZÑý‹IƒRஇŒ®½A%Cpžá‚Ñ~Ñ%kh‹âê‹!’cô TißpXAÂÃXCEŒ6´+1‚øøTJ°ìG( E¿ˆvNÙ)õk-g½Ó= ÄJ–hfÞrfVMwôݰš[^=7”-*áÖç\»TÆd§I­†žŽóÄ? ¬Nóÿã¶ÄdDJ%æ]ÇÕ–I ó¼ä~ ƒ ÎW¸cÒDƒÐ$u*üž_oxü‘(f`¹û„œ#mÙý“ uB¹e3°n=ðæ©1Žä™€‰¿N×'°Ýj¾‘ôþx‰gÉ-ÛÒ¼hý~Üzþ¤# Ð:v¥RRùá?'+ĉ]•ÁÔÀ=gNüé{OÔîCì/`/™Ío¥b¼‘ Æ™°¼·….qOM8B´L²G_A=«¬Õa‹iÖF·ë<šw4ª\\–6r¼yl\¦¬É+ld ½‘¡Ó¨Iûg°ãë×rƒqS;úœó ^S/A}R™²*ãkÆÇ¿Ía™£Ñ¯å½û0Š^*¿3÷vÃkòRÂê++½½s:s@e•÷÷8‚’±YªqŽ]gG ìq´ÍBaoí•´ ¸—K»PÞ¡Ü Á†™*Î`'U‹ˆznsÿÝÏØîÁ_Û2áA‡jÎ5d P »Cc4k]D…Îx)´öÌù8(¤Òõ£/7{÷'©_ÁÝJl\(æáD«ÿ‰ͻV A;µ‹KR‘+‚n4IÈ¢6æJÀ|/›íû<ùÉ7¦É Øçär´ÉUÚ ¾\QtFÿ¾ß»GÞþ.#M`ÅÍl–D«y„KªfÌš×ðYýYЋ‹jµùÀ[>Æ>©ãD\§¹Q"¯¨[ôx<#z».N-ß÷ÙÙ2#5Œ7Gƒvb¢¾á6ØúùÓtØÑÕŽ– aW²Î-n}ö«ŠÝÏB›G¬Þ—Ñ´v XpÓJ„žRã?¸‰¡uwÃAÀQY‰cÕ,¦v0+1¬@O½ß8\€¸77¥þ–7å9‡ÿ ™õçñcŸò£–•]ÂSQö] ql(ºK†ïñ`ޏÎb%¹‹Ó;ûÍFÃÍ(²»¾;¬^¡G ÍÃFùWŸMÏ‘Úï¤|ëÅW.•Qšµ°¹£›.tS¢¤”*æj]} Ø !Ž“ðÛ¥–‡TÐŒš†(öèZf΃á8*N¶·×]TúìïÏäBgk©Ï­ò<ÌÔ ~äèK§‹¡ºì"')•æøø\Øçý§·/M\‹nXðØ*—wôÝÀÔŽë9÷r6rÓúŸ†MR¿5§dÛž-뎎ý€,™oú4|A‚ÎÉà[kd¶¸@Ô—ÿ÷}Q5ì ,9­/ª0ÆŸ=àKƒ§ß+i†G;Éq§: ÛÞŸmæCºˆ®‹iÁ«\a ½Kõç>üYŒjä^nnÎ/ýOuR?h Q}xz¯ÜŠ1U©0PA\¨¿- 7„jƉñÓÉç@©Rem—ú1D .sÎW; ©mð.8,ja ´8ÆŠ›D ðæ3ƒ¨žÉÊ& З⽼ ¤\xË;“õ’H±W (Çf©†%…l\^Y7Ƒ⦵ò˜YøD²×°±µGB zdý®]ýž kð-FUS6,¢–õ‚Dbö„Ç^©¦íÙ‚bzÄŽSéo…*?™8 OFàÅòXÛÄê ó9÷7%ò[Á/ªÛúP$VÍÏšAy Ý·à Ί=@Y3(Äîù'oßí´åEG9nDyÑ“ø8AE ´ÿäHçBè–=á{™‹F »Áb{Ã#©µÐöµnmTÊ _vxö;bŸ;ô⃺ÎÚÐÏÊù½_Õ#@¯Ùe?à63éBŽÓM Pû‘B–…éL$JCð‡ Ìœî†Ü ZÎ"ï‡y.íöuü>¦gxN ¾»c‘ð¤V[Œg$¹‰µ˜•ìˆÏ£ŒÈµ;cÓ2vs ácé (Z\Ö ¥©ƒIéìÚ‰»Êü:¿Ã~Âà¦â€^žŠ¶es¦™@Yúª…B¬†çk#¤ÿsäœÊ)Í«=¾|¦¢‘ë]|öÔ­›Ÿ.:¯*Û=ÛQyXøÿ‹± kÝo¦Ý—ëMmÉâô‹ûTĹ‘2 Æö“ÕòÚ>œÞÿŠô|Í ‹¤Ç… ñ_í„§þth÷² 6Ìk #×·±dtÔÄ7ËÎO¹:^IiÜx©]A·Õ$S‰htmÛßæ eBuTUH4Î…€«ÉowÙr…þçz)çÿilÈW'z>™’h0-!™·«jíCe͆ès–Ú¤àØ2œ!ùM6¯»…Ð!{_’e4:_({÷ÜŽL¢;jX,¡LëÔ’7:NÇ¥ ü½)K[JϬKÝSk&åÅB®^›í⸰¿ïè#‘˾š|•íóúX, hÛÄ|¼/R¹øáþ©—c…â^,îã …vI‡]Ü”GÉÿ÷Í–Íp2¦9ªõÕ#\ìFÿŠ) Ÿ¦IwBàdÃïÈ•És›xQ›ª‚ø¨ÑØißÒ6~íYï’%Ʀ¹G÷鯫?lþ.Ó379‡ß¯ê™n#©SÈxp`”#ÍÊ~=æ) Âr[ÎjÁ ‡>ux^ƒË_!LÑ_®D„¶‰3{@ç%ÑAq92 qšÌG:uógQ¼†­Þ«ûÈ´Õ¤@Ù3A¹eqèm?»ÁW½ÇšÙïìlÈ~ }²™bVÀA´Û$LdºÕ76ëÍÐêüß§f±_!£Nº…ü×)°Ös]üþ¹8ófXåJ¾;^!q!rÞêϯG£0&Up£"3V-º¬®gûÐ@åñz`ÇõZ{Ä:†¯Ò[ a¨ö%t$'øeÌhGyÒZ×B¹!™N½)$ref6C}3bqŽ‹8vò?8~à ¿òáeéÍYnßdu%× µ¤¼Ž˜Šß°­Õ„_ÎÖò]Ä&‰Zàá8÷Ø»ð§ö)¾3Èë)ˆZûùÎD¢J¹ ¤Ñ[³ˆM¤ýËÓå¢e‚ð,÷Gß&‚")=ÙLÁ÷9¢°‚ûNâÇH mÇÑ3ߢQÙt‹(ÿŽ“8´Î— »D?­`N˜þ®A>Tµ¥ ’6!5ž°ÞöäNɉóŠrÀl˜%}ü@n°‘ósOWæ¦wšò;ËŸ¡_ëØÕeÝÙÅ龊+z$ïZ#Z¨ƒ]#à N%Ü„tq ¥Ü{qãÎÁ=4mé5~_ñ[1`ƒü­Ý°\—er2Üi $Ó[s¹ªÕjŠ>¡ËKyÔ’¡vÕëíÒOÅ&O(á,HÁ½àvéœýÚ:ª°JH­Ù]ßœšŒªIÝ÷ƒ†ÐûäëŠÝ$µð˜ÇÉAQ€íOh„³„zD¡©6 øôçvgìʉm—áiMÌP á= óÊ—R×âZØîbæð_ÙoZÓñr¥ç ¿˜' izY×ÉSºvÍÊßeb€g»·²m6%Hô!t·ÍÔFÇèY€¹ø{™•/À ,äUßÃÛGÙöcKRO1I¨dk¤åL=[PÜÏ"e§§aJûg¥§"pñ°ÓÉyj;Ñjª×?Ö©Ü…¯Å}FÖÜl=n4=ý×gòTT­‚±ËË‹”à332ÕfH4ãÝš=+•3Gk«jˆ¦‡Œ3§|[·ª>ù€¿vÂ#…jDB€ rÀûƒ#r„•\¢ÄËÇ|/ÐQBš~/‹<Íï}ówl˜þFî‰6©Ìu°e¼Üö¹¤ÚQ»zÿ»O"ò³Lé" zhT4‚ßñýx‚¦ë?þ`YW¢Y… qñ¤6N §ÁQnëÛ–ÄË`(*qÑ>`–KSS|Ó$ñáUÂçz‹ ŠÚÇU›”{ñôJeLÓ¢áïÅ‘ÀéE8“ËÜvŽ`ôY4›øøšwr‹œm!ýëè#HH˜-•AªÿúÁ]±=:ßÙ9M_wr>±;çWB"AàeªÞ²ÚŸ4„ÕI²©âH}Nü5Ÿä>b †g(õ[7`rüÜ¥únÖ¨Þ…M&DÒÌ$ :ô.ú,‘ŒÀF7V`wŒœÿ`‡Ürw¦Ûú„:öŠgts£ÐÛM(Z'¹-ÑÊ»õÆH÷Ô™™@›"(`RÆíhK{æ¢õæB•­÷»£cé¼âZRJÌJõãÏSç¤ÎÇÐ-`Ï'LW/^DœUãÕ¢p¬„ðÁJç~j—<²žâ|‡»g ï¥5SPw÷¾Qæu/±Gtƒ%nó;‘%vf2€Š.ožŽ('[o]<…›Aèo€é,^$”~*DáAÊ’¶ Qå Áœp¯õ@Q` F!=ö境,¯»š7 r!f›ð´®ýþæÉþˆs1z*ë#ÏcÁ;ú”AD:¸fëëÑÓüIU³Ø“:y0Ûþ-–áMá$ì]°²X)AùŠrFº»´m~C_·¥¿LW#{_Ú³.ñÞ÷$»ŠTX“ <”ÑÝsÎ)å­+½¬róÁ#id^Ta1­¼ögO2™Vysu‘ÿ€Ž >‹ò?Ÿ¡B‹ôáÄ«sØù§)îƒÇÂpEîUV™XRµ(i‰(5ÏÂíilÑÉFSs±y`2˜gmì'@´Ž v‰§ºL׿‚]ÖjV ‹V*ÛÑq­«Ü-Ït!ÈÃuzÜM7Wšü ž˜ªö (\ú3à@$縠?9ì¶H†S¾Ug˜aiþ ½©JE£6e}DìØ°wõó\˜\·Ï?rœÚg«°ÊìÉÝù¢ëLµ´T¯“‡™ [LÍŽÆ [¸ùB÷Ñ5PÛцa;™( Z k»ìGIÙëiu)òΊÖÜ+så; En¹‡vsă¦hØŸbYÔ¦QDèèròEºKS¼È˜_\‹<ÅéÇ®ÏÖœ´iòöx-ïébS£)§¾" ºr¶è²ƒïþ;.'Ш´:ÊQó%'•`lòv³–5ïÛÀòn©MB!ª½R ¨'Ü7Iˆ-Á%h dêj}‹=R ka3‡!¶©0^Æ-C†Iv¯ãÖvmQ½=ž³5t ">@W·(¯Ì9»ŸåØ 6«3Më‘ácƒPŠ›9KÐ×¼e4í\ûÀT·ð^ 9ºˆ)Ëïa­2˜óy©;ãÞ‘4§bÄDÙlîu³ÕKò˜›† »Âqá4_—/®%·A Þè·plYNtÖSÑA×/Ú”.Äõu.Çøâ‰ð„ ÈÂ8û,Vjyì!¬OʳÐ$rpt°i•ŸÌ–pˆk˜€­Ð'¼Ðmßv½3ï΂ ×4âEl5[Ô¿û±¬ ²HúöýÔvˆ•¹#9rrþÒ³2¤Á«_1;7®ɘN)skþL–À¸T°Þx8ÇèøÂ¾|0¦´”µç¨É›ÙœsyªÃ[Â1'+¿z¸ÝWxÀÉì}Ø¿9Ds˜eμÕ𢾠"¸ö÷]ÄиÉçOÞåÄ.mC²Dy¸>üe9ŸÔÈ­É¡àídçg€Ï¡#r=ÓZõò¿6zò=¯¾ X˜¯á?Òßw9¸ƒ_« ÖèG/¨Ç·¡3ýsàå-lVì kŸ»·Ósß“$_ú˜ò@V Ù+Ö¼Ñþ.úô{5u‰ÿÊÃ'|]§G]¹|ñÖywÇ8 ´£íCæ‚ò€¢ý;8I·ß©E‹6ìq‘©¨²å9Ú j¦?®0ï”Q«rcÞ§, f½Ëäûؾó>+pB/åøåÏv7–µ¿h(Úõºü,×^(:ð4}ãÜF¡—Q’¤SZ®*¥›”cEyæ:l0œ¢—©´ì3*À…;„W[‡h‹vvÊ6Þ'tÙ h8 +dsž¨¡aH÷cäñç™HûtKã)ð¦&w°dôQ€ûy>ôH®(ˆçÿ«c0 ­Æ?ž½Ï—Ë #ö­i£i*R–_ž“]œ¾ ñ@ý‘mK€È=É Š Ó „ µ­ï¨A°ÙÓ(g-8ŽáÊÙÓÜGšï⦀KíÏúçFÁv™’ïK}r ÊS=ʾÙS±r'úÒç¡_cÄDQ°Aˆ6‡Ô~;WnpP°¨k¾ÂÀI¶X !3¡Ë%Ë“dðÌ Jî½q¿Œ±9QâÎëâA¼>;j±KÀCû ÎuHÑ Ý%;êÅ»ø/sA˽VÁ;9tÔHN*^›â°˜$ªNÉyÂ^Rã§ã=!Ç:‘P’nÝ q$MÖ›ç*!f¼½5>5Cb‰‚®‡ž0Ï7M¿Ž3}K}ÃæèÀ’y%ôvHfS>4Óêtœ é¯b²Þ3½Ù$pËýÿEÍ ‹CeSËMö ª>”Ú’,Ì·‹ \‹lnÜ—â#Ü‹°wMü+3r”mMÉ»µsSÊÆ#Š B¸•Ùt8™'ça]¼ûÑ0sSzúèÎ'_½ 3r|¸4—$J_ÀãµìôyÔÏÈ>TG½qŠ¡ݳZ×aªÂËfþ•þeUFéÁçé¶–‚tñøqM¢pø™H ¡öÿÐÕeìéç­:1•ñõ!ómÇ6Ë’DÔsn¦œˆ8°£¦û±™<Ã%9À®¨VêC¦¼ú=4 öÜjÇŸÒ¶^tlOEJàsJ»4ïs¼.G¾mts £&ô­‚G ša‘–ǤƒÓ÷ØçŒw€ÀsuñtÞ/¨ÅT]oµg€+çÒù]ølWáp²Šn0uüÍ;~ó©Æ(¬kÿHƒI<ÄÞ¾Žk}Å"Kþ3éh ƒ\„¼]úZ 4*Ïœ‘e«ˆ3e]œå ÕŒÑdBëаH h9ë÷Ùuñ Ó·àìçü÷®’ås™ÓÅ \Åiïß}?wäùD0'HaŠŸVÜ7VÈHy<øBŽ™þ1HÉç@(1ìͲ%Ä('_M ê{’ðï"ßfö³ð_F·Û¦ý€L3bÙñ,CC¦=ÆÅ+|XÌ ßò%‰ V-ÁG„EÀ iH{¿yYõu=›™ü@ zöêÕM\fvdFaQ)zº òñÔÛ.ò÷/cÖZ«‹‡E+aw˜<…:nàëGÉ}ý¡ŠM£Ë¼BHÏ"‰Ú#I8íž . ÇÍ´Q⛪̥u…ÚøÂ%]ä2ˆ½È8õNøŠ&0 ·´k#.¡µmåþŸ¸nns”€ËÜmÃ68xO¦çãèÊÚÕ Öìp§Ì@t¦«OϲO(0w“¯Pb©Z PµWîRöjîà’ië™ÿTG® Y¶°¼ø—O pä †´ƒ«=ˆ:'§Ô$I{G¢µs¨'>{ãò:EZŠ¡du'ADˆ`Zà`¥ VÈ¥ÿ8Í–ÌÐð%Þ*ŽÐ‚À¡'(sP€¬ëþ;]ÉôE¢ìÊrNm°ž¬RV…Éç΋ñ—-0òŒý´mÓ¿ûû0A[·ŸùŒöEÃÔ#¦"ØŒç5G1⦞ðUÎHª)埅räc†Ê˜ËE°—Ó‚YÅÒnÍvîïJ.mÇø|’äJ$†óOræ²Y@èe·ï²óƒ¿œ«Ý¿ÍÔýº°«ïAó‚å¬,)v,¡1X„Q<ÅÛA'=×TÏé 4­Q¨£“;z–Ý9¢ÛZ· I=ä!Fˆs“.ÃÝR‡Ùk_uù‚ðgŸÕ€š÷+…wˆà,!H3õÓSobuÝTúä|Z/lü°4?Á+Ü*ÓC`–Ó>B–üâ–4Ô5¬Õø~[Lªî&5#¦9#ÍD˾ÿE=C …ä›Þç¿ÄC &Ûþ7&¥â ÝÔÚªä'-h AµZqNTBÑ#WcvÇGÍÊ[Lûß©>ÐwÌ7îî Å7ïºâñ‘Œ ÖX6¶…¼Šx úØÂ!˜mŒW³ì„¾˜Úð`â´Ìýž¥²!pFOäZø¥s@Üi³Xp'3·7eŽI[ñ‹úmÎ 3낤‚ÎlÿpP”­–ê¹{Q.Ç¥È}Ä­¸Äènð½}¬÷€ˆXúÏ-<^_ó«ˆÜ ¿J³n/FZºî'EØ»ã#ÆøYÌ7­ÀµyrÿÕzÚRðmÞ²¤nÞ}Ó’Û¡/’—île!c³ôýdÓò†EkEõ"Š ’EyBLpeýPŠ;A^VŸ¿™§Ýv ´èžÝõDá¹EI&„?Ä_-W):Þ#Sèúd^Ç{œjw‰¹OÙ€èr¡…–¨ TÎjЃ |¿dé0ذfF/ ÍW!O¼6óŒéµw–Ž0³]ÅvCÐÝ ¬Ð.Ëô›#Œ‹·=Á›JŽ¡*!ä㣣ÚàÅt²¾.ΘÆ>â±#S&æìZÒÙâQ˜åå Ê*™LQ,\gŒÝ3¾Sãæ`ÏØñ˜Í%vνÈ.ø·¸;p ÏLy8LZèa¹(&ëÔf’î×Y4™óNÝ{=ôGû00Ò[n¿ç"9ïæ BŽ{±ƒ¬Ùáî _5ˆXãKI·5is¶gGGá™°ùÜj—åú8[Ï€£¦Þõ'abÍéèÑ)ïÑ5TA[ˤæÏ€§;ãO ¬Uìyâ6I]É·¸çˆ=$(¡øé´Oþ¢ô )†»“~´8ÞÞ®¹Å1M?µ›t0ýv›ÏãNdî¿üv¸ùX±¸\!ÿ[üyä¯>Ó™UCùÈ&#&W·‹G¯ÁqרÁ¹¨›!¼Ð(~sqOxkZ˜{jUȆŰ@aµÚ uåV!t„ûß«}Jî(5‘jгëÒEðÈT“HñIm ÄæörŠ›ô ÖÔ j…aàœê«tu0UÕüQgùƒô'`ûç³Nð¡lØUT‚Šª¹~‹ñS{BçNÙÙE¦+Õ}û‚§[ýØŽp低è2˜ßÄkg«xò´i¥¬…Ûáá_Ebý‰ýÓÊE8%†³•¬±z/{FÂ=“0m`E»ómrÈWÔÇNÌrþ]ñ¢”J:M#I‹N§¯ÃLõåÙ—#—ŸÕ”b Æ[tסȻoº…zŠ[ÓÛûƒXÂ̤ýTBþþ.:¸úÜjßnضZð©¢ÈÝ”x®/&æ1K'XÏúÝÍ ÿÌ@-øóó‘Ï}ð¼§žO˹t}ak Ú·¡gðN‚2úJs)¡BRnu êc‰Ð€}™<êñb;Cö<\~L«ÇWSˆ“êÚâצßnñ¾€'ÌÒßL9Ïðÿ àüÂÇ:1M‚yØOý—¨‰cB#VÉJ€f‹Ûoÿƒ¥ç©Ô0¥~LÖÃñ*øªlûõ"s;Ä1É^³ \ íË5á™}ÖŒYBÝHh ^HbüÜ\Aê ‡/·@âB½Gmò}xÏ”ãËŒCãYˆêàt ¶\M{÷f0|¶ë\ü n£‘urPIY“@½áÐòÇŠAÕL~p1;ËøZ˜¤(ÜÜUÁÿHúêµ~­| ¶“°¤ÝtÇ̔Ǜ|C©Þn½@»ƒ'd_µŠÜkú¬~CIã?¼±k>‘åäRe8¿©$j[êF…¿r>¥»n‰åÏr«ëIW«?j¡Y 3cºäPù¯ÿ 9.·R¸Ndˆ˜clT1§£j$@Е1Šß_8 «Š!Ë%Eê8?5Æ^`4'S[öfg×o¬²×p%ÑÀ 3öëž_^ŠÁ ¥Ó¤Ì“j£Ó†Ú“sZ™?Ff—€Yæï^µ”P¸.>@:‚9×m`Y§Qy]õI”¡ªÈE–½Iµ7µB¦UöúŸ¨‘Ÿ.E§’téÒË#*"Þ¡o0~’Á(t¿ ¸†}JÈÄ&Ab6T Š\2å0°‘9@“,ú!;t}³ËUçž²ÛˆxšX„Î×)]n—D݇#b›¬sÉ›¬|WûÐÅ*¸ÒÚö°Æš¶YI¯“þÀ_=@%MÚÙÏã-A‚@À}½ÏZ¤+ô>\3¦Yζs'A±í?{Þ+ŠjÒžÜ[ Ô®‰é÷™>UjwNn¶›ó£a\ºp}ó48aï/Áœ`áš^Ý\jcmfLÄ"XβÃýµ0a­rôâë,Õrƒ”*^9™ÆàÑÆ{¬À¡ªFCMø™ F܇`4€3:ÞØ¬´}‘v1®âTqIçBbü5•wQœn?H†J+‚åU«LlÜEÓ˜Xï몪‡²;Sª¡ëØ×NCÀºõ-Wõ–—`]¼/$$";CVâ±5–µf>N*›1·) ˜^o<ë]N{ŸRU`Ü*üEݼü‚ƺv{mÊm=4-‹²è;#·$¼ø4bÁçÅžLAdËøÔ‡Þ Š;ò¬a<$hÝWLp{Ô[ƒ tóD1¨£¯a§q7å¹ g`cÞ>°éé2pÅ•åqáj&ïÚé&°ØH=ö=;ÍhíüRE;ünˆLšµŒYÝ6…¾ŒXÚfÒè$&YÛsOx3ò>‰Þ üÿ¤&T1ªˆ¶«N20: ÑëÀѽÊ3›upéÔG«¼öþ1^‡ÏmÊB ”Mgße$ fIO¥2K«ˆWÛT»}ÔÆ!˜½5r†åXË 9SÎ):2Æœ°N¤üçøbšÒâ¹­zäé:žÒð ÿÁ0Û ø*8ükÏ$ªÔ¿ÔîüŠ4·òpt|m5Ožšù—©Nô, þ,c†GLÙ—W¿âáîeU«Pb@…?}ú–£öD?5jûä¡‚ÅZ­œÃ›Yyd;d ï–F-ciáhõ¼@ÿ¨B¼´7Û3´죲ɉ¼ eš„¦UË’z¹ïȧ‚.ßU“öíý¹X gÊ»—Æš[èÀow%ÎøS_®VMïÎ\­“mÕÏÀ¼µrûë1¯à…ºÑY^¶› ¥Ç»˜±Òæ!(54¨Už?'ŪqøMÆ0ѳ§¸Tº=°étsÏ]YD_qšmšLÑëô°ú’Ñ*jCì´@M£ØÔÒ»ý•ùÓ6÷ÄåÉü»¥!ûjÐ\¯æ42 McêÙ™¶¶’ˆW¯þ…Ι3}\Êh&ô6ô¡6sÌÂÿãùó­N 9¤ºt¾Üú@kö]ßÐßdû{ûñ9Áƒ*qw5}èevŹkëöP¹Áö=çLEÚàcbì±³­À·ø°|çÉXŠÈ¥fM«›³…æ†D9¢\g›.F·™•‰@=¢žGœ…–gxNQ*§*´z~·¸ZÕO£tCÊ™J‡¾z¤4z3Y´åÆ’"üL¾hc‚{À Bé'8‡?94oé (L“[´ä›/»êç/å"†Ð³G’Óøó¹ì¢ô» )Üsyp"—ð¡Ò9ÚÏ…Þ²:Xk!*òJ´9yá:yÙc4·ÃŸÇ*äʹT1”NßH»h áÓéš%º>Xó0á­Ÿx"2¶–¹¹WéßZ âÅñ°‹‘ý꜄²Æôg|šö»EYÉÚºÆãþY>{’Œa“6ÿQ›ðÁÕ’^ß,§B9ËnE¼’öÊ D] X6¢zè‹›+ç4þu³Úî]»úì¼@Ë|5ºº !Þ>2†“T ꞨÃKµF:©·.–)0ÓO×á`ÃôÙ¨Á—˜!­ `+=PB0–êÏ\>g•_õY‡Û ‡qf=õµ Ø¬á$D°M{ÖêQ™ö[ÑYÀ´4‰>êö–áR%¯WÇ6/ªÃQsá ° !H&ÁiQêÜÇÉ#'¸£¸BÒþÁ²Î屚¤%]¯KχY1WéD™Y¿¯Æ¹÷ö&é88ü™3×ÔrËÎGñBC¡Ç²ÇàëAâÉÜТ’σ[DšuŒ°óY‘M4…zÿÔÇÒ jÀõ±¹3Qz‡ÐVÐx³u徯Ý̤6¡Î…^Žw‚ÓÊjŽ{$`$ëÎ/E±âÕFðæ6Lgc›àºvÝ«ò؈%´_ìyÏMs!Ú˜tfÒWå²\ß“©ZU´mºkYÆ¿ àÒú‰·×Ëè¼ð¯Y­$Õì0P÷¾J ¾DhT?2BŸ“_0Äp™Ë?s€J¸ ê/«ðB3²´ÐôõD±öküpLÿ#x(ÃÔ±ó—†Ú STÌ \‡ÀVï3}úO¬î­ŒÍå/GÒ4êH4•XÉq&î7‘ái—#¡V2ɃÏ 0®ä Ûßßñ9oŠL9M–}µQÕ4슟Åùu}Àº}í#ókW ·Œ}•M©s¡‰bo«?–8w}Iêá2} Õ`EîíÅ †PîìßÖ絪¬¾B¢BN^[N|…Ë”r€èç~E*¡)Ö M7…êdòX¬£dŒ=&5?eúW˜xR Þo†X+ªX#L픦afS‹OTúf§×ÛÍÕCë[8JnÂё˥“a‘M† NT;¯±(Éx(( UE$í¯Ô%èÜ«çò†ëˆV,:Õ®¶ù¬™æJ¤g´¨b¤…ooW^x~6±ŠüÇüÛ\ÌÀÚÞɱMU°Y“ê“Û«±±¥€—ÄÊ¢-‹™n×÷ç?œK8iߢûŸf³g5”iËÿõ2€z,†‚‡q fñnQêyÿD¡œÆ·!ÜË?»‰…”ʸäÝ";þ0š­ÊªãíñÕî³ö™Þè°Êøu Âvõ‚ÐR[K,ú†¥ŽÕIoÂ,¶ñ$ÈSÀ÷•i­{[æk46J²?›…Ìáx\åm óL!>PrWñt¼DÖ0C WYÑ’wÊ›¥*„»?ÇqתÞð:æÂm.¼×­7(‡s8b\£•aÐ×Ù"L®?è+¾ã¹jŽÚz †)ɹ·ŠÄrðõúAt׿â´(÷Ag)¢–ñ${ªâ“ŠÂ9ÿ¸Ä0‘à @®œ]ìPïþ¶`¯06Nûªª¶â¸˜Ò§ffŠ=[™ŸÉÿ’©Ž-ƒÐÌGAg•¬Ue@__=[YÙ;È[sýî\'2º‘C+Ùo!‘º@€{ºÓÝaø.>µo ¬@«¯®„Y¾ý)‡£?¹ÞӳϬƒgA32p!ÚœzØRD{¾µ¨ÙÐrc"š@¨˜mÊ·¼@2ìX€|•·òúO|5hžìyÖîÅw;FÓzZÿg>|¦n#„ºˆ7Šëĸ#ÊW™x¡)×ÊŸ û5‹©Fa‚šsø¿`è üþßO"ÿìo†¿3!Ø$îÄ„ ÚoðQ'¨—t?â¢"¤`›‚!×êIØžä)̧}5,Äúã½!33‡;‹‚.ž%5_lg¹ýÄ€PMññ•»Ë{*Y·Á”¶ïýеd!©Â#ª^‹làüL+h·§KŠ$!%šÐdWŸ‘Ž'‘ã£,E‹– ʽoÑaÑ TŽ\׺'©²Þƒæ–+i¾rÐ-X—ÃÄ‚n6J©««"ŠxtqÇߦr—næ_)æbWpHöšâm«G²Ÿð0£ÒGÓ¡îkaY5ÝXozšµUÿ:¨¹28î"Ĩ¹<õ³–o¸óÙ°0Ø —;SK éR9‘ ›GÚ÷‚”Å `%a;É.\úõqßH žb¿ƒ+¥@+ꂈå˜>#øêˆ7hå UIa>æw•G§ÀÒgÎÊbúGÓNîAð]«Ê“ž]å ƒÓLŸ>à.²lv&;ÌjŠœX_¿lظ3 e²Ç=ŠJ˜j&çaÍNL˜G®°~0énH3/ÃBaRÍ-+›ØþF>ëÚY4Ãþæ 1QÕUðQ5»C&°Š ?¸¥wÒj’÷í1„²Ãõ¡•lo,kzžÈ«<ÙT{Δ÷Ó‡ V0O/Ob—ÝéEàQz]ú|zߪñmœÿÊŒú-l)‚O}­n4Rcƒ?É#Tܱú×ð¾J|Uk&Ø)ÜY¹”â4î¸ØÇì3µJ.KO_Û˜ïàûk ‘ªˆ¶rC–1$¯äùšúþðÇ Ä?ö¿¥>÷<»~°¸È¥4 šŠÐíHÅÒŽhܸ5ø¸ yÖÖÿÇE /&6AÍÄ9jhQz5—,I|ð?ÿ­LDmM'ïÎ1”÷H€é©ó§¬ò$Ú|Í ]zI¤ZÐÙÜÉ]¸î5ì±ú¸zŸ~À' ¶Ø =‘½*¼è2×6íõ)俲(÷ª!åÖxàâö, ç¡A‚p~‚™üÁ[)Ý,7 ÊïMnOI“›~]„ÓhZ‚à·zæª_6²TpÇBí®2£)„ÙVƒ‰uøŸÈ¹xèIæ:'Uh±2¾uõ<& 1ŽØè§vç¡¥“ÕyrÇ‘ nSp¤Ë%¢iʧnÖöŽ-¬_{U¡8¸@%«‰G¨žw‚,AÅLPo&ÆóôéMlï-oæ=z)6E¤SϯpC¡s9­6ŠcÇPÔn"B\eˆ:êG>väIGL}ó«rÇwå¦söFú†ŠhU)<.’ú®|à µ T63@ÒÜoiBû,È„b!3xûC þe¢a9é‹/®$ p@õ¿@²E½CXÆ'l¥ûúÖ(~>æ?;«¬hºÏÿU.O2),žÄFÐÌ( Â`3¬ŸÙ /i—ˆxÄ9ë ª0‡®ƒ ÍÍ—™K$–Zlxt-Â÷ÔæO`sæt0ö4¬€ :Pdo)ì¸í¶˜—£‚·ÒZ3++Gµ#C¨¼ˆFu‹^wœ‹W˜ø#?ÿ š ! ÚÐË¿vƒi;f¶µ*–eìàÀϤ‚¿@ňŠ÷´³ æìFk:sÈ=9°š‚£‘.8šOW°2Î1}Áº+#]oϹ·þ #ÓÖF† íB ¶a Lð7SŽòÔð•­ùï¡$=æ€_!H‹%Ïç¨KÒà…ã¡ØÿØ÷47€§$ç®Ã°åÔ×z«zÁé'¸(ö›y‹Å±£ló¯g Ã…œ.dÂj¶L3¥¥[FR‹l¨ÔÞ\fîèrKðE¡ æ@ òKÏqÖu|b~ ‡JE ý›å&—Û«{€‘ŒM&Zë¾°!#å{wÑïZ’jç´[Ù»Í7 ¶ýr¦e³í}ij`Ý:-} Z°ÌTé“rz’Ç(9P²(jWÒl "&lE´‹€h’öyŒaF,EZ@讵v»K?z¡]âõV± ‚ó6o¾j°yŸÆ>ïßÀ1 ¬pùãðËŠ¢BÐ’l3wYîåæwÐDÁ}G—ddñ)>†cáÀ×ñ¦†"-mZôü<Ýä·ËSÎZ9på!®bq¼íùh³ÜÂÀ—"n^TÌ”ç4fÐWôëÒªóê:¯Æ?ød_ €jå.ÌûLüäûáíÇ«¯q›š‚yÒ“éÞÞTþ¯ ,*‡ÔêP<ÜIêº/‰ê]Ý4ÊÒîà¨)ƒ±P¹PÕc„¤ë%F‹ì]ê7î­“Ò³ú’ßÕ}Hf-÷!ðˆ©ñ3ÂÀp|§\'ˆ5%…þÜ6­k0‰Ö›×ŒlàÇ=ÑІ—yVì\lµ½/§à0’’¬·´„*e]T­ý¡ÖÀýÛׯ¡Vpm.`K)2—fç§2TNß=n"S6øúÿŽ¢‚© M=œ9 çÎE2¡ÌjDG÷VN ^ºê[$iªÁm¨ŒÍŠèIùQÛÖ;Yoüdº¬†ü™Vî.Ðry}•-óDqùÈÆJÊkT`Ÿ­¢\<,žq} ‰žè äœaq¸ 2™ª“nVÊäÁõ¤]×°O¶d4.x ¾8œèÛçÄ\ª¾”ú’â³ëÎyh<aí©øŠØ<ø·¾#C0h'7x7Âo±zè–nX'EÅ"≚‘öIîpNµuJ²k3ˆhŸBŒ…«Íˆieyd€?t…¶0u!t^Hã¹ü¢ST—k³eDµŒåÄ ñFóFsuüò0[„:;Xsc³Ÿßx݇ Ðþb+Žûç¶m$ZKñ38ì'й„* 2dÓä¹?`wÌúàvØ`ÿæckuu ¾îî€Å"«ÿ ­y¶fåäë÷\ü}g‹Šé:½+SNà;T²@äâE¡ Ö:]üúl´`xo¥ÌK—ÇÅÒ\ijj^To ¦©`¸^¢7)bºú.,ÝtÉFBd6·cgåF¬¶¨ìHÛ¿ºƒNl»Ïð ²BÂ’'Á5àv>p¹B#û«à3¿$¥†Ê:hë5ï99FƒsÁ©CnDep{Ëe!—Y ‚ë̱քx+§sÄN@‚h‹s«Lû"*í'™#¹–ÉÍr6¡ÿùâ1Õb¯À´>–­f=rFYY€½Ó­¸ ìèbœ¹ö¥!œÇu&÷Ìy‘ìðwW œ"?š@x/ƒÜô•I?òÔ¸Á“õaz»)(:z¥F”ÑÚïì‹30`ÉiªU7å’ï¶ãÅ:4Å=¡- Ö„”÷ì-1-c¼é4¥*Fþé„+ÇæÉåÐýIä}°½òk™ 2G:¿í£$#„•às IPÿþš¡:Zú²×’4(aÐu{¨“ 'ú`íÅäç¶–Mÿ(q†UØãH1fªíÝõZ£€qºARºdtJHŒFH7J·¤8š‘c"‚2rC Aº»a ͤÁ $Æ9Ï9·pþûžï½€ß-¼­äLo䟳å%äqënˆþ±¬· Éu’¦æ½×ÍÝDBÔŽ ã9oøz3ñxmļ…‘Sahß³5vžÇ«¤Ç…qÈé΂­Úý˜óBúgêj!¿UŒ\p¿Û•`'v컾§`ÎI¯=2EÜz| ?@½?˜œXK_m®ûTëbŽ3к‚¼‘µ9™ÉŸ³ÁÍÖz!Z2Ei䈞þq…¾ÊAÄŽ•»×(bïð|èf,ex`Ð/È8©-ÇdÛ”Ÿ{펼4.cÝ$¦îqלp£M¾ÔžícëÝG¸¥v+ýÊì½ †^ÎÂm=ܾ^`t(h%5OU(²0þ\vª\fÕ2´ÛÉ>½/­ó¤{ è„æò¼ÇRÊÈÙAÝxƒM@ÿf/vÇ..Âɸ·¼Áƒ¯*%­ç"-tCß3».\ó'‡Gxõ¾5iÏ OÕÆVʦÀM±l£T2C鯸ó<[÷~0š±sÂsý‘¾?ýº?§dœUè:?Æ—-"]_J8û”H£Œ6¢ÍÒl¨‡;@#Ô ¨ :øÓÊöä¾'6iJ´Å[öüY‘óUŸ1?ç ÞóG§·Å¿Œ ÍÎå$Xm˜“Ö¢jQ^éb~á)œ°Ö‘ÍWMæ…ÝUѬ³TÙþËMþʸ9p‹’‘þu*,Xu$ƒ ˜5+ÓìV›ç(¾ªT W°. Ô5®­_òëu eÆ\hJñ±ü)èV&óõÌŠQoà O,¡¿Q©R­X¾µ\8íX#$57Žñ¦Ð‘™gRl}(&µ7¼÷>æ¹ðÍ>kñCUN+ÃB0 œ˜¢ ´ —fxœnñn1ËÛ¢äà"äÍÑ«1½z± B«A'Nînv÷#Ç*ÙÙÆK…„nI–¢Z×Teà©zö‹Jmkc«¤bqpëù¼ãÜmê‰\Œ‡µi~þ^ì Ê™ Tä¹\Мњ,yEM`\üS¦AÍ(Y&+Lò(É8¥~’«§6}÷˜ž fªaØf¡è]8u™€i´£h€‰VÃÊ#_²6~Ø ‹o*}Ù’=B¿k«³iõlÐlwëeJ.i7ůÆÞÒýÑ¿Èð›· Q2úÜ>û¼ÅÉ‚9^Fõä¦F_7ÌÀäÉ›%ÊIдqvXê’›}̧y'.à”«|õ‹uSDuO~óW×Ån ä²¶?á"®9]Fì³ÄÎä¢ç&ÅO‰«·ËÔVORˆÇ‡Ø®‘ÂQdN¶=<õŠzïJ¿?šÚR²uîkºýN”yV¢+ø9•¾MvþpQô¨e³@Æ@˜÷!lQÍ’þ2©<Â*…(ÂZfòüŒTÊD>ƒ¾]ZÅæ·÷2[«åËØhl}½Ô²M8ù|m§ÊC‹‘•0Ü…æ>’ Xóž9Ì̈õŸà%ÔĺÕo`æÁ÷¦g BkO™[¸I¶pCÀº%™ ²ùtÙxBöÅäQÀËg7î…Ñ29\ á¦Ò¸ÇöÚ£ [ÀqXŽ„Q#tÊZb?ûŠÕ'h¢Ú5XùíÀ¯')ï¾Ñ7X…@x5r—ˆÆþ$+²T\Ï k¡)#Ž\­D {À;}$#’%ZHtÆÞ_rp‚(*)“ù¾Ñðlº7˜u5h‰®§qûu¼Ô^C:8Õô j¾'Æ#±Ì¬¥¾Ž&„Aî­EE ÿ8”¤Òú\ÄÁi¦Fua~{«Ê*GŒcÚ•ÿUäRƒo’Å-ßm'çå©@JöÊ”¥üRÙ¹šþrÆ« žÐ³QG£å·®0¶#ÊìæG¡7ÙÐ#ßÀ+'·*¡Â{JÍ j%½.ñf”xG‹WUFêó¼í÷NÆöS2H¨¥ê«¼sª™Ó—† H#Ì#°úá~zž¤D9™FIÅ!w>0C:ñD(\õw;]×µxÊ6¼&ô*]]D·2¿›«b†PPÔØJ¯ì£a aAM²A@Æðˆ×ßÃC­rös’°fMDV‡R\{q_tbÇ\þÄ%f }¥Õ¤¡6LØÉm,w;…¤ä7éùD>©ƒ$Ê«5½då[êtætp„˃¨ží¼zó=¶Ú%~ŠF[›jPÑ\ìGYRwí4N.[B°Å¸Žêƒ?(Oü°%Žj‡ ALq‘îûJ Ü®|·ß¯›•ÿ 0kMæÞN>šÒÿa(V’Z£Pwî 9³~R«'¹¾Üù±NÁ¯ümCW ƒ“‡ðû$µÓž'n‹Ïìߨ á–Óž·Ñプü ÿ«±ÿ®¢lw4°p"bï%t]uMÞ[a—iÀ?“é[ÌET_´ö”/eÉz¢»q\*³rG?jX2» ™ôm¢1%C,²|!GFèŽvû<ߪ5Sœ,Ù’Æ ŒÀ@òV¾þÅ_ÏdkêU <Õ&=`ßw5ަƒ%}… hóyGV8rQROF•ªq\¤—¼",‘W#™ñ˜Dô{ãÞ¹ª4•OBcJ,¾¨X!çÏji˜P:ç7ÀQWŽæm}=Í:‚Ü´Œ¢Œth%ÈY¿,]Ñ?Í\~é‡p65úó½-^„âRñÛAàCfµãûÔQ^l$ á`%Ó¤j&‰™Ì§orÂÙï2ü 9/Lð<„±­´®.YE´­èæö.ËÓЫþœÅ«/â£õ†+xV"9¸Â>ȇ¤E¡‘Ó%'‘’jv9Œ§³(¯~‹XmþYgñ¤â‹Ö Þ~ܲl·r5³Û‹hÊ3õ2Ĭl)Ý›üa¤’ù3cìî0×}Üð¨æy³û“?©ÎÚƒî²lh• cj>‡{4Üß2_ÏœèúdžÌRS¶Žþ/G*ªÓJ¡·iÕw÷mÌ-¥´úEâ#ë¹;‡ÆŠ1ÐY?ç47åÁr–~!†|Ý©îN.&|· ¦ìvRü5ŸúÏ<Í`gLÉV!õKLgV5I3ù#²þ±râ%!F]q65®ªv±$~™pžy³šìN!û ¡1Áù»Ãn!=P²¨ê#°RA“N\OÑÎù£È¥üº“gÕªrßñœÍbÖèÖMúcfÌদîF‹å§ÁT^¿4/ @<`s”úòÖ•y¸‘Dß"äîI}ÓZðšÿûùÁºSA«Ê£hìÙ:S„d¹Š–SþDU_ÝNrüõr®Ç}ÈŒ˜¾ŽBÜŽgÁ0õu¢UÕ7µØ÷…l1ù¾mÃ×_ÔæŸGÆŸìqüë$ñ.ŒUÞFâg;ßkÔ8Bã}Á©‡ã'–¶b$¥øÕ‹KSkê.uºµ#[ñW%Øo ŒÛ˜Ï÷›ïJórVg¿™ò¸õ:6­´—yɲA3VÌ£ i”³÷Ñvw…ƒW›Ë¤…ʆìøñãUXTº¯þz“åÓ‘v#JFu9/_a[ÁÛK‡ îÐ}l .m b%ÑPÅwNYÑfåÖLŒu©¹"¦¨$~R,BØ÷ÆfíŒáí¥Z•Þ㊈²|ÖÅÖÃÁiÓH\i3¾ìþ€ôQJrýà ç:ºDçèƒÈ‚z¹ê…±îÙ⃗#Õ”oâA"ÞHÇPm|XcâÆNú¡ aÍ#Å‘;Œ pÂ9 Š –Ë[fŸH«²#,pn<7+Æ0l‘r¬éM–=ax8g `@¹{ØHÐJ½ö…dùæ9øv{ªÕä[mnÿ“©Ó{,·Ü¯ÿ5ÈœjBŸ†ß|]Þ‰àéj¨k“Ñc4ËË/© ™Ô8OÓùókÞ®0ŸXLT´RôžŒ„Kùmëä³ìV$é(0ìA×¢¾óåðÒ¤@¦'Ÿ],]ùw(>®ÿõ>p¤7tPžºµ6 òD[À;Ù2ìò$™ TTÍk<À•*Ú¢’ˆXSy‹l««¶Kv¯%ÿþÞ\jÿ˜¡_M=<Õ·Ï]°p•¾PŒ¯[^OÙ*ìÊžá½f‹êœœªˆÄhT¬ÍÌV.1¬‚MYŸïwbORÂüÛŸ<«U³ºÓ’ðÓÔi;`ht™XzG6ö°ösèõÒ°<欥]ز °´ïÚæo_Êœ×EÿuŽôdL§K¤@5òñ{ÞÏÈ…š(CYÐGç­©ÙY˜\äS:£=¯Ê9*¦HŠ«˜áÐáƒ\HÜÎo ´LÝŒ¨Ñ æÚ\Ë1›£È;Üí1ÅRKåzµ$ Ï]š¢»}o€OË újEK^Liÿÿ›–˜>ü*¼úÍrJ- #ÉTë&Ù2>_Åö ˜«GÈIMj‚„jÖ0Vj9pØ¢!s…y™ƒlÛ f!7ÚÖ¯)üù †qy†{k(1tp„¿R÷ê}ɱ:3dæZ†V­Í¸æiϬ˜ÆÚ¯É„"ÂBêPÏ•0¸)Ú:ƒ´N9Z–ãÕe ‘ ŸRü–ÝH0É»cóʰ§u^ý Ä[\O·­r¹È¨[H>-,-–$”óšBMÌtД}]8ÁÉüå’Ô¸íìîÞ™ _C‰k'æök*„ìÕŠò/áb…ª_?¿Fg…²M-oÛë’{$%ÿ5·¯½bæ»’$kèRE9©Gmœ8P¨îkÏ[à‚€”۩YÒOgb¬¼#aɸ}WÛ¬w|1 ¹·`IUïDsHþ´üE­¡t¾¶•НÇú.Xc6Å;]fkÞ¢" MJ­üL0Á˜ïNU|Ʋ¸dñšã§õ²òE †sÊ¿0©Ôf¤ZJþ籟 ¿å@º"Õ8>‡7§È î瘫l˜.¸8AÇqå­M`ò]<¢Ÿe{©èýÕ!Ýäêòûßjó‹;!†¬eTÛ½òI›Òhœ›…þ'ÙÐ+PÑœWbùÑ-¾ˆŸèÒÝëä¤$U<•ŽS Óëè›åuNüê°FÉ«Ó |*¹nñjìí®§5kùÕäC÷©SéÌÀn—Ÿi-Ä–¦÷-ŸˆÂGÁaV§¨Üúbñ!v³œ’Ï̱G|±åÙËk?b ¦§!æú˜Le*™ÿgÿþ3_7§ ?§ ªˆ ·àÿ ·(/wªÿLW» endstream endobj 95 0 obj 70089 endobj 96 0 obj <> endobj 97 0 obj <> stream xœ]ÖÍnÛ8ཟBËvQXïO HY²˜é iÀ±™Ô@#гÈÛW‡GÎt‘øˆ’®>R4éuw¿¿Ï·õ?ÓåøoÕÓy¼¿ÞòËýøtÙnWë/ó¹×Ûô^}ˆ§Ëcþ¸ZžNy:ÏÕ‡oÝÃ|üðv½þÈ/y¼Uõj·«Nùi®ó×áú÷á%¯Ë]ŸîOóéóíýÓ|Ëï ¾¾_sՖ㆔ãå”_¯‡cžãs^mëzWm‡a·ÊãésM]óžÇ§ã÷ôڶ¸¶®c½›sSòü1ç–¹EÌY˜Y™Ù˜ ÙçÜÖÍùŽíwÈæÒ™#rbNÈs‡¼§mܳ½G˜çnýþ@€?Ðàôøýþ@€?ÐàÎìÈôøýþ@€?Ðàôøýþ@€?Ðàú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_á·šsõ~ƒßè7ø~ƒßè7ø~ƒßè7ø~ƒßè·RŸ~ƒßè7ø~ƒßè7ø~ƒßè7ø~ƒß9þŽñwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßátF8#ÎHg„3ÂÙ¶ l‘Îù+Ú²rÉæÿ Y,h6¥;ÑÈDt8. Pi|ñ€Fv ¢±+íåK÷ÌèdD†TôÀŒg¥†u€NmÉ-^F ̸>-AÍÄNèÄ…²,²éŽuð¬´aÆ`¥Å‰ALt&8eÁM‹³<—“#artË„F{ÇN‡® tÛáÞ®Lˆvqè”ípvÆv¼øÎ™Kû2ž¥=²æn±•ö=Ûaîzf˜»õ1þûå‹OOgñôË$@;<«) bÏwW<}ynS—~y.®X§G¡ô¥)›Á°ÔÁõë ¨3,uðîÖÙÿdØ@±ÃÿÚ˜«ãÛ4Í›rùPvcìÃç1ÿûKáz¹â®ò÷pר endstream endobj 98 0 obj <> endobj 99 0 obj <> stream xœœ·ct¥]°.ÛvVlÛÛ6Wl£cvرӱmwlÛN:fǺù¾½÷9÷ì}~ÜqÇkùΪùj–V.sWcg Àõ+3scSà?Ðfn¦®€/ã×Òý‹ö+~+WËÿ‰ÁPwÒ!™¹9ÚZ™þ[K€ƒ3ÀÌÊÅÔÖÁÅí õ+gWK @ÒÁèlo÷•À?°.n&ÖÀ/†¯À¿’tu¶2ýç¤ËÐWå\€®sç/>+ûÏ~!í]€c g ð_ˆ ðe”Vp°2²²r1°ð¨MiÔ¬__yc/ú/¸¹hþ ÍÃh0vü7>Û¯:Å÷êÿÞú,]þ‰à`þ¯QLQì_t·/¯9¿Xÿ“‹‹™…íŸ̬þã€Úø‹•…ãëGøKÛɹiþ!úŸ^\4_Hÿ‡#àu]M]œ™ìŒíݾTpýªó?¥úo óO, +gW€ê—èúßšÀÌÊÂÎÊø4íŽñW¥-¬\\Î_j~‘™팿Zò+ßÿÖ:,,_ò}icòånÈôO£KÛ›;xþcûKéÿ4L_šþGj¬ŒÌÿŒÍ‰±™ƒ½­À hþ‡‚ƒë—zêÿŸø¿ÎàÿÆÿÉ*áfk«`l÷/¯Û×”8X˜JV®¦–ÿ_c;+[¯ÿ¯ÞšÀ“ Vpp¶3¶ýŸviW㯮¶·øj+æÿÚ´r‘°òšý ùU{7àÔí̀ζVö@%«‡‡‡ë¿ÆÔÔÆèâàfù×üjÿÿƒø_•þMé?S`aþ—MDAÅá«¥þÃKÉØÊÞõß ŒùûÏ í=ËÍ£'@—™‘™™åËñëó_+ýÿÆ*noê`feoñÕˆ_iìlö¿6þšˆˆƒ'À‡ÀÀÊÃàädpspûþ7 u{+'7 ´€…ƒƒ™ýk˜ÿÙ6usvþ’øß¶ûJù¿žÍ­¾j zMó“q¾G ³g•Í1Ò¥ß6¸_rƒ«|«WÀDçtÉl–N´à‚…—;OM2¼v5xü¯-+h•þsþíÐ^ç1\=k(Ùºˆm:TuQ)0öþÜæo Éé£KÀXa5APCÜRç-^‡>ž¦cÒôžoœBeJâq°ó¸V£·»zìo7oâN=‚Í:~ÍßÎ~7áI¤½"¹!³Ã´}‰;©/ݼ‚Ó“AN·ÚÁ|•^hŽÎ8ç̦¿]Bw¢Q´*¡¶Aø¢AÃ-ë=A‘ÈsŠ=ýí[Éæ·DÕ YÔäåþ’ç^óåö&pÕqû§¥öÝºŽ±“Èå2rPìf/§m1‡¡}ß* iC„k·õlˆÜËí×39{;N³µ’ÿÆj¿ ñ#מäÙ%÷PٱёÒyïã ç42ðóy²$0"lÓ[èI0tUu‹^=zOÀûn›™&½{ý8Ò\BVÊ/x¥ã$m;ÝÓUçoYý~Ä\É*x‹€{qä!¿Ò…÷q(“~´¶ë:Ǫ¯!=¿±sÛ:M\€ª{m¯ ÌS:¸uê_[KÚ…P²I‡"%-äSOýíCjv©œµ£ª +;y° A¤âu9/$Ü8¸z!R|Õ·ìšïS„¡óK: ’°ãD”"ÉÓ¢E›OÒƒÓËey½‘úÚ Ä3Öª/«I›~=téðZãâ\ov^nË1Üÿx´ñ¾Ñ´gƒ<h©“ðÐüáŃÝZ 9îà AähúW{à&Š;Ç …+“|=1«9ç@*|–,äv *ç+ÛõÖ¿#J|¿)«E…Á’AœÏmŸ .½¾Kâ™;U„® ]L$M2ÁNàm|›ÃSHÙ>ޤïﶯ¨c—®å`¯Å%b±$¤BòÂ*¡tçç^*·;*ü˜ x÷#MxÕ2&bT¡j«_ÌÅ݃b£BÑ®°ò‡zqEðOKê:j‹ Nkx'YEd?ÂOÛy¾ñæÕ»Ó¡¼±ÕÇz„°­:º§ÙNú§ÍBæYÅWlLœoiú¤Ëètus[þTa-pù® è13>÷=Ápg;°‹…šgP´@¹‰Ä| k³MCµq§öúúÁ×Ï(±¥³gB YÀÎEE…>'UsŽæ$q|““Iö‰÷¶$MÅhéïo–„ï‡uÌP|[{A¨®Ñ~©ØîZPÐÞ‡"Dþ¹ñ7¹?‘ˆ³<€hˆCª®PrwÅWÄÄ(Ñ‚—-LüSDÛš9 S+ýûkƪ=z JÌ㵉PjM|ÕG¹Ëy¹ÏåB\e|Ì03^è¢Áа u9.¶Ü÷¥Y$+ÚZJ¿ü Š`¤Ð÷ócNƒ°*©pøÕŒçÒm뀇çYAáEšÔSˆ³ÇùjkðLsÁ[f¹P¶À4·W¹žd9ްf;ÃóŸ. ºgeØÄ7Û”å.¾ ˆÔö¬ð}{A?¤Ý(yyœ@ò¦y£Ã#¾ó°õ?Ï9žoÖÇPì5¶òœñTÜ– ¡=Uø„WbÏJ.ŒÄ2ŠTéŸÓ1÷_÷XM¦X' É3\Ø}–Mb*HnÝŽðÓí¤Øé7t¡áìô•GqW zø]èòb+Íø¤†QçU™3+e PØ)¸f›r6'aO•º< žiß5}L’j i#1‰š»&°-4¡'¸D¼Î³²§Áoñ矔½sT\@ýlX M÷ü$"Iï² AÊݳݼ˜îZñvÚ~®ÔK¶g9l¦`}OAö¨ÚÃëóÿÜ~~õñà.]‰V¢Ør-É|9ê[)Ö7ªÂ¬$—öNª½50?"D~A‹ÏEç“N}ôšY~oq¸¡¹—bÀÚ]ýƒºôÎ:`+6>½m1Ç{%ŒP~áñSCõá°“D¤ýµü„ÊîïÝÅƒÒ ôÏ!Ð*ª4°ˆytVâ®NFŸ¶)U\w˜Œ “ oå—œóß”X-ÇÜ?ØP…ŠžšlTƒehù¯|(öâªîÞœÐðñ¹;úZ²f(u¯X‡)¾Ã¡tˆF½²T?·:Ý.G—à#’‚FOtå·Þ¸™™1ÁÀ]¡¬Å&4 îe 1¿Š05$•ìÌC¶1!6ÓÒlxEi6/wÚ–‚ÐÒç¸ocmcn%€+!øëà!:°ÕJÅù‡XµN§onÒuS^qg”2$× Æg›ƒtH’a¡²½5—¸R¯1à 5 ¸µ˜k ÑΙ{P›d°‡ £€Ä6ÂL0ä¸$7[²šˆ•tðÊvÔ• P/'ÄLHšz`¼×¿ŸÌØoT–÷g‰eóÍŸãš›2#þæ° Dã›û™Û„tj} Ä<ñÞLáÚÊí/Pt„ÜÂ\W³êª.ˆ³]žçÝíýPDÒñ縪WÁûZ€îÐïñÄB D¸f¾o¾ Çp$6·aõcˆÕÉõiøÈÔŠö×’¢póÿiÇã¢X‘è¤àçmXgBɾï¢e<£+ï‰'­iÐK7 °q Gå zrª&Û~Ÿ Ý_ÇóVÌüõQ_‡ý:’™V~ÇÏvA´SÔ·/çÝv‚ñtá<Ùÿ¨ˆZ¨¼®:Z»Ëº‰2Ö¹¯XÐþlœ›XÝ¾®^%¤Lé¸ú¤¿%œe¸ò€*ëù.jK*þ!Ú1‚æºùQ$ܾsH†Ïr%ßGÃ:](l1P (T™îíÝNA„|ACÝÓyf´[m„7Q’Áê3ç‰ZïvçÜÕ]?ç?T/eg<œ$úSïÖµê¬UÛÎèîâiØJ1BäØsFÝZœÜ5øW†éÒ¾]·KÅû(¬Þ„×ßÑÞAh3ãôqÝäù¼9È<‰ú)Û&”GF »háxô†K•ÁìBÔdœmÊ6§<ˆrí»#Î`zê’0DL°XÍWÇ—%bþógBDo§RšXAh «ÊÅ…ÂxG†ùeÒXÚŸˆK{}–*\ù 8ŸÄ eãÚÉr`ÙìRI«2Åb•„µ5\ð·B¨yí¹\-ZìM„wuòo¨'p‡·o{Øpþ@/":Vë©€–?fÑšV‡:7¯!OQBÿMìzÃòýÅ«Âòõ¼£*b{ÏGª!즱+ñ²KÀøpY7æo(Û’C®´o ߣ‚ÖV\UIþooP4Ÿvß@üvšKe¶D-"¯…8¼1|–ÇiÃ2¹îÓZ55•× —jÒR–.,ŸÐÃfògXØÚÔ万BÕw¤ÂMž£Ð†6îÄZDd!ƒÎà=²77Öƒ›Cþ>„=êh vðⲘ£gzŠ?gß^¤!Y¨…0¼ú´÷ïa˜»„"H0¸Oz ã5ZÞtÂËþ ž¯IhÕ-Y6òÏÁ÷(Û]ñ}ã¼ »*Ö±qr@ü‰2ÀÒÔËÓÓÂßÍ }CU,êÈ+Í[xÆçm–ŒaœÏ¾!õp¥—ÎÖ¾2•ü‡ $8©WQ"?ûÞ»ªŸÉô9a•ä[#ñRÄÑûdá‹ôkÿ\haÆóÛÞ(¢rÕ™ªçòAÚL|L²¨ƒ‡UÂòDrìUWry…Û^GºvÁ'¨î>‰ÅØÊ\ÿŒ+)¿íïþÒiI=ÊI‘sm¥“±v^˜ááAëðÇi‹TÁ‹ ÃCÍÚÚQïýš‘QÀ¾G•Øc“³Œ7ŽÓy¯ØåêÉK·ÚŸž~`Ÿäg|ª¢^mAmÐíäÓQÁçÇšÄF3HßãM‰ai¤ÄD3Ð#q–þ“·LcïX¤ƒ]Ç‹Hâ\&AÆ:2—(ü?å4DW^McrâDÐæ¹~?Y,÷õš(U†'«²/ÁœW%Òóg¢À`ÿe1Xâ˜wy}çQóRåa_üA´0ý”²/VCdAt]SÕE °ÖÍÇ8‰LX3v2öîäî0ˆmàåÁœÜ~/ÜǨrZ0<„é"=u|ÍP3Cz 寧bD<·©±ÓiI‡wR&^V­|‘Ù}‚¿a~~ÉõÑ­°-Y‹rosº;“õßÔø(¿ƒŸß°åN„…Aç,òˆß‘¿Ÿ@•Wë5K! ïWFhe`i*l®ù¤ÿ´ƒÝ(ìBOô–Iæ\ÍV»5Ëðê~9–c q/è5!$ö.VGSößÈØ\»F‰)LHSQ»XýTØv&²Q¹b×>ßѳbŒ7^³jªy/òŽþ²\µŽÅ¸ L)Á"ѵÃÍpHì–·¿1[ùB‚KýY‰Öˆ´ÛSåRïËýtä9¥µPÏ“J—¶õ–6O—_Íä‰B’§Ñžrxo’¶¨õæ´=Š]oš2Ç53k\„…nÙˆ~PœÔac¸•c(ì©_"IF’°›lzEÁIEíTúVÚP³R]³C¤Ù›¸ÿhrF¥ã3BH°ê8mA43’ ªA<òn7ÙjéiŠÆ”ï’•f«u4¼åǧW™Ó© \g7þvm“p?#¿®ýÝ^p»þÛ*”ã\ò„¾%ç˜¸×»ï ²áÇ(GÎ`±ö³üˆs–ÀÒqûG#Ô õ¥‹ö­£žÎ$aÜ‘Q2¶.í­Ýà3%Þ4üLxwçäëUØÁËpž9µzÈ#ÄÔééá·@˜ÒIMSý=:L~€×6Ea¬gÐxÕ‘NÁp‰rüÊçôЉRŽ"¡‹d.ÈÓ~{¡Ë¡axϬŒp;TÌV‚ü5›yèØÂYËÃ’´ÁÖ^vËc“^ðí êE—ÿվαDAWÓê'Šô•â{g°.C]!+5}ì4c¸u8|ìâ†ØÖÙ CþQ7Yûòn|™xàÃ[)’#í|°A­Qø¶ ËÛ‘GˆÇØ–#ã‰yòM§ò‚iÿ¾¼‚?ÛJÒë4R”Ã~ÁT5íaSä´þ¡6ß°›t”§÷Œàôþ‚ïõÉ]!ëiCCU‡‰˜¼pF)œ"qjÞV H#lëéÒ‘¾Ëû7VÃUAè^· iìgÄÄè²Fø:›§nÚo‹òpËCÊP«@;j¨ð ÁŒ eTrJ¬0$ûŠ1·ÇB Ó_é! gP±=Ù‡ôêSjzMZ„ 'vÄÛNªòH¦—”cq'°X%:§,ç4©©3ËlÛ¼†Pÿ,¼³þ¹k`çÎ óxÐÊ:ÆðžåA'fK×ÿÁ¼ÛU^/Y“RÚù}!WXíRO=ñÄÉó Æ dû©žg­~+¦‚1“v>-Љø™€mStm0ú²z4Ãc¦ÑÕüðù°Êñ‡ŒD~Jc+Lp –ÚA n7Mþ²3j¡Ï,‰Íëf–u0YÅm\FºÌÿ®ß\„ÔŠ/£gï&ýºÜŒ‚û(Ñã7rJ6ÁHØÀí~âTÄ$ˊ׾£[òéï5ÍÓ«µÊ^‘ ‹˜&ô?0†£ì‘á´Fðà·¢üdlúUÇü¾´%’¸PÒ×5¹pàî®Å6¶ª){WZa¹¯oŸ 3aÁýà@ÈÅĬiËpvyàìé™[LYvtg(Á„h¿Ú«è¡¥·›"wü致ˆö Ât]D â]‘èÌäÖqï@‡wºŽ©X«¥XqtßÎôÁßd~†–0Êl\'ð\ÜV7¾°Í‘LüŽŽ7¡ê9¾#¶­«I…N‚&^fþƒU÷öŒOË”FÑN…¦ãT%úÊ®K ZÕë ’HªhÛ ¤:¾ŠîJüù »b—¸ÚŦñŽÐ,mÈw%EÊgì䬨€M…a9v,ªªïÐîëÞL Ãs%žà»q3â|ž®ÌÙ>ŒÃÈ3#­v“Ç…ŠzŒÕžù[Í‚}¶ËdLÐ¥û;· +‘°ᕃ»!4TE™FìÊ»¥û?)…Ñß–Ò34Yçö{$#ÀNÁšÆŒæù¯kk‘Í£ÔhqŠªåÛí®‚¢È]øµøƒk~îÖæ²Ôùe ‚ü$Æñ#îK™ñ©”þl"mèmGXß“ ·“¡è¤c%0Û­7î S¥\ÄÝ8†F²”Ømá£ýH=EÝÚòd®‡Þ˜ƒ˜þ0ŠÖf€tÈ Õý.‡fW­—Â\MP¦BÀ¢W­~­Ÿ¨äÄ\MîâÞRJIÕÃt"J–ÙTØÿs¾ý’¬"ú­‡ai>'ç&FõGKñr€$vÃd€ý2Sb[ôíuìu`1˜q'˜ìx‘-Re1ìÁàq>{Í&Ëáμå6jUÌÙzõ…RIM3†íÆLNq„Ü*˜†O ìåƒÂgJ•|döI°¯®*qNç[~C¦2i: èp8 ¢Cm ÌŽòqvn_^Ù5®Nö7ÊoT»ø­J±0~çzë©›ömtÃ}VJZäȵÀjªQYt%ˆ–˜¼ô¨æ³ZãtD&\VæBVEw·yÿù÷&C¿X2€E,>zg›·ˆÔGµÌh?„ÜTÌ7¾×æh/[rŸ µ$Ÿyk‡"›Í'/ô§¿ÏD1)Að›QÛ…ÕQž×K>N—²É/•NÑiàlá¹Y³øÈã:c°+ª¥=¡¾Ê †Dªöÿ/ï4ò·­ê‹ñ6«Í TõÁ°fíþ“ïÁkQ‹;kŒžÚæÈzs@ðe3½t#xlì«.ëá– ïDÙÏR¡Õ+µŽ‹˜Ê_*øãÿÁÌN¹ŸnˆV¡­lÙ#ê²µ‡‘ß3v]%Õñ&˽tÝ'†Ž ¿^†Ëg Èø£³©­G„Z¬†q(gÉ0Åoè¨0…ÿz{hÁ†9ÿxäËíëþAE)ïü9\lŽ*ÂêïùHíãé¿ÏÊG&ô 8UZlUjÆ©µ2ÑH&Îp¯ Y–ˆ¢Óˆ¿¦'hb ò“åÏÞï!ŠIO»uã–Ê{£àçPò#G3ÖïÑàz|,9Ýv´ÓÐ tDöíõ§ÊaäPcÝCé~÷ù‘ºMmí¦¤8º“AT—Y¯%¿Ó%ñÌc¹Ûô «)•fé~(ÐÛ×ü<K­ãü°ÃA#„¨S›÷1Å4AiqQS1©#!« ¦j¼ò½~H²R™Œ#ë ¶™P˜XÞf­Ö` ™l±­HÞV3à(ÈÞX޼Œjš¬tñи¸59ø1 Y-l3g†ÑsŸ1¹Õà ýІŹèê¦W¤n ›!£‰ %¿xp}­”íæO˜UüTYV<*Š›ÍET¨wGûÔe@çA\ï×ò¬xüÍîú]ú€.ÅÎ}m»:žh•¬3ŽÂ±Äßãhîz+žØïÛˆ+ØvÚL NÅ%¥‚Ê@|A>4YN†ÊÈgˆYF¢bO §„ð)©¥Œ{+P ´&ƨH°;Ûžªys¨Yº~fì»ï3ðñ‚¢sœ,Âý7ꓬÇÌfæ¨2ê<Óç3"ºzxñp)ùd[TÊœÙüÐw¬”‚–|·EÚK'G—„Ææñ'C(ÏXØ&ÀtÔ¬‚¼Ÿ¼¤s­¤bÚ‰µ¢»Å«š"Ëq`É—“¯{M-2@æÕ@øxãàŠ¶ºN·¬èµm½fll÷”hWi²¢¹FgÇ Ë±Ëï¡ñ”4¶#z礕À« vƒõ¹^Ý® Ksš;BÍn-išÆG?Þ5>Ëž­²¡AEÚbÇÊ¥\í¡ƒÒ9M4Â:eí*Û:8¼úüŽFt0œ6¢“—!²~B˜8JÏñ/£nÙŸúÃÑ k£]íó/è-42@,“½¹Í>χ_Âvö~˜).}1Ÿ÷ì®ìZüŒ"c^ü=Œ`rÄ‘4ùõ292%a³AÝ _Oĸ—E>ýáDÏù&è‚Ì9“àüo5;¬ÏcÌ6Í.•7W¯?w(çffÌ*6¸瘪>gHá¡'©¥¾üÒ¼SA4•xñÈR”>Ls˜ÊBm٠ɤ\vKn¤`Ô.Ô½rylÃ!C$E×03CÁ†Ã-Åá#œxjÜÉ¿ö=R\Jö÷hé}6¥{õ;º€aÔK@95ˆD)” “M¯/4÷®§Bìb9×ô-õw¨Þ“"l6Ž Ù@ým­f–ÝÃ;˜“™íÝà¶Ÿ‚æ@KE.깃µ½¡ Ê –$eɣ…šßÎòÜ ¿|[œn©fœ0–Æ‘F !•áLÏ8SŠº¤5 ,ÇÌBßp~5}: © â¼¥0w éžë'?twÎê´èê5hóx›‘ ¹aââÀ{öA.Åö’<à 6/rZ„uÙœºžÇËjÄžú»OICŠjÖŸÆÜà&v²_#Ýž°7ð}®¡5щz}r])ª-¹üÞûBHÏmŽ‘¢7‡<³u˜WF±Šk 2Nfl¢™ý<…ll*ÔNr›R7>Ïʼnt,DÀRîqí„â'Ùt^ÃPãD‡¢I!›Î‚’³¤6£‹°¬áGµRËG+)œ iØžü0_G;)8£¹¹ŸÛÁ‡ét4”\Nh=5¾F‡¥I6ž;zX òíÀÕê £¼™bˆ£§•ýe‡Ú4V(ôϤN¬Þ°€#DH´%.þaFú~¢õ_SáÕ³“w®WD›| Ìä¾½k¯Ç£ì!Å{Ò®ùšæœ¼naÅî~Ì7¨ (F#øDN–®"WÆ®b„ñª|F&ªQ:j²Kw÷•Š>Rè÷(Ê©OÛ7nɉÖrAOt§ã #ý!Þl¯ßá'ÄЮ_·ý…ê^d°ƒ0åïŽe²DÂÈz%59lÞ%…l§ûptsú0,zvyÌÂØL Wd°—ýW’ýàëF3Ç1ëMÜ™÷ï}h)bå?nƄ۟ƒj´ý’¸MAh_:M³vbGFÍÊgéº÷Ñ_ð¸Fà°´âïS±ÓíkUPAsÂn¾kÚ$‡¿=fëÁg†¾¿ü%”ú^µ.c_â^qÜbû¶*÷ãÕú)¶Óâw1¾¦RÕ.XCÑdæ.…fw‡§³¸_…Na®¬ bê½ãŸ²ÄžßÌ}íRq÷í"CÙŒ÷ÕÊ\¢:9³>m(uÖÓÄ$ãñfÂZ°C ÓAXâHœðÜv1‘îõ™”)%³Y~˜Y-Ÿj‘• ú“gvýds hI–BjBJ§…8kÖ— óOÅ:¾™©N@³+eå_fãe=]œj[ä¨KkcÄßHí@Q¥©ã2;ºG¯¯Œ‘÷ãúaÒ§þÖeµ=îiºžÅæ9œuÉu®ÖCxkªfÍœö±)2©Õ\åûó€íRïƒG`º¨Õ6ÈÒHëáÆA”Â-Â842¹ôç*ÝÌæö¾Í¤º+‰w™SK@:bƒ¡uⱞx®ˆç2î±{L^£Šc‹™Bhîë³î+1FaƒÔ:?jç·\L…¥ ³ÐNÑ~MŠ‘KúzLHÚÜk¤œ•®UÛˆ@¿„çÈZú6vg¿=Ûog¯EáÊX'ÇE6±Ós¤óÆÃi D™¦C#ßéšÔ¹A_RüM1ù÷¢ÅíOTŠXÞœ¬©ÆÇuǾÛšø‹Q2^Ô}§Ëµ8-¬€ž‹gry‚æõ‹’"ʉ¸òÄ (u2¬ÃEÚ6DqÇn’r÷ö|‡vÜá.- Çmh|?“PõˆrÜšîˆÛVÓàá—kSÙ‚9”wëiˆ“ÖhÃaŒ>I€Îl ”cúJÒ4[‚,À‹–ôc Hqvo.ÙòdSÚˆñÕì÷B)Pµ 0µš²¡gÆ%3$f-€Ûë/ÄRXàÔb4óo\ý@V’ºr¸|Rð-ÀBB°}IÜhb'ÏDŸŠ®‡ý6Kæí×ÙT‹% ä&ˆÛjtì&È>P ‰Ì&@ÎÕü{êåÌêYwà[ðSLø« ÕG–ëJÛg§Ç†ïgŠNû6¼hq —s¸•e°ëºm“ 3‹L¹Ì£®JZ†”rDaº÷=ÉùøÀmµÄ4s”„;ñªø¤EûQ°“(ed´©»Î=8PôϰÌê|U{[½xh¹¡GÚËá%÷xÖÜœë2å>—Ku@Ô‹âîõaˆ•~6CðÄ,F3Ðæ<È?½Ok€²¸øjì0k…ØÎÑRø´J[à`qï0&+ëÅDØùè¶Ôî›Eà ח.7¨ºÖRr¨}8˜?† ~Qn;àRÏœÖbçQã]=¸ßÍæo­ÙÚh‘%ù:±¦JÖg‹chEÊþaÊ=u®z³¨:šÂ¨j“M0Þñ PϲOÆÐ;1¢Ãв]é‚ȯãyq²ò•Û"*¶Sšü†æâ]4uv´ûëMé`tß‹q{°9ä¸*ÙïdD-·²= ‰”ÂÕêVµX+-¾òò‡ƒ$véCÙ!æ9ÆŠ7<¦oñm ÔZ»œG/·1pªÙøC {‚¨½$ûÜÔ{ÀßìH²£ D!Àá˜È§¬zxe5mÆv 0|ða¡Õ–]mLNš×ͪÁe/~Ú QW˜AÛ·Æ´ÀÒûÚ1ÿ¼cšÓX”úVÊ@. ’–Û™Ÿ0fSåÛóËï… ’Ba’ðľ­™iFnõ(PYÿ.ä Ó®ÙŸwCy¿ô©•ƒ"gkÊÅX2!2V6/ÕÍ?\¢ƒ‰tPSĈ:Ç Îhœõãûuz|Šœp –ÕâÄHè=8/-,g® “JÓ'3ï"GÆKÖLÊ“qÓ%Îp{¾ZMÜ„}]Ü4d JâOD¸¸®Ç'yÿIÒª@8íöÖmNd‹Ü{—ª/:×RyàG+rOäÊÚ&W:í¤>eä!€Ih•Ñß#òE¥ª¸F¶Cuø‹tíô†Ùª C§î C˜gÙA¡¾ºŸRŒ·êÙf̼·)´…6s‡‚ûÏ…‘ÎÌFk:IC¥¾W”¨1GÎÔÞß_}ËÆ]ÃClí¡Ü>‡Z{IŠl6G¢Ñ U³:U˜îÕ·“:•QvC0Qy˜xº$’¯Ï0ÕÐáÚ™LAU¡G´²?M\J‘yf<ÍÕ—Ž:v¼4ë…ɪÌÀ„“E.¦ê6¨È©@7b|wQáD># ^âMÐnßm£onPJI+•inGmN‰§ÊŽò€ß–‹?Ú4@UwÚ´«@†¬{ß!13–¸ñe“@s7MÛÄ “ò“lBA§ Y\ÅÀ«XÄä\ð ~$Ǭ(sV˜ÖÊ>Ö÷ÒÆðnR§Úèêôë&‹SK K}¿¨ë£ÁòUzë›O%ñr\jÃhA—¥íûJ Ó¨Å6o®qyuÖÛFÆU½'mËí/¨ ч»ˆ.I<‹B,m¾ˆ~ws”MÔêbGÆ,ÿ‡Ð©YDœ»ú°ñ'Ç{’4`BÙèC‘xlD†Q Bõﭒεd·˜j›5á!Ç)§ÕÚ?Î{{ùPABq óÜ(à™Œ ÇWÖž‡‰ËZ€ “— @ÁÙôþ!øàæË<£i9b\ ¹tÊøž;Ôï ;ÍȲٴí¾:}wƒ]Êm¸ *€Ž>f=[ÁR;fšÐrC ­1ñ¯æ ¼oÇ@±š:n¤¹gÂq¨Ï~¿€µ€Ý\ÅyJ78>ÜS“«VSœÅcó9¡)Þæå]ÆÿÔäIoÀ²ÈÍ·œÊ±í¤6}ByTäÎ{TÖ»ˆRŸ:Q ®¸Ã±R·ØÆi¢çw_¼*¬9á}ýµ{˜uaÀÐDÍÄ!Â4¥²”QŸîOæÏ]>±¡ÁZéúÉ„dÁèAMõÕ^L7NÄÓ³5Õ˜ðÿ¡®$:mIkÜv š3êûZýñ+…ü¸; «cTÁËú¾2åÕµ y jv0ôfQ`Èxpý””÷Œ «\à…ÅœûÎQ3+0é÷û7¤2Náù…ß–—È¥]"cviÿ–›,Xw*%Òêd™îúðuøqfZ#ÂûS9Û¥Ëfš}m!¼¡%]2Ãôó't¸¬–î‘ÔN9æ/Uæzþo'îƒ%F6;ÕàüCóºa¯x¢–F–¾OzgZøÉ>Pß$xk™_7(×k‹u=>GÌ ÑE—‡êßã=UêpépLnÎg›õ`~Yî¶f°e\¡;éäžXg—ð5Hg.™ Úç’”BB3søðê‰+Xîñ×UbÞœðc óDEÅ qñŒ–ešTý×!‡ø)ª² íKS••KœhõÒmuöÛUL[‹6–cφJ&gß‘-Ìŧäг-ÜTJ4ÝÂî? iâð=ÂVù<Öi£š½êɪaÖ´ÎŒ µ[ »“V@-.2¬\ùBul^\p,0›}Âëm§‡ØŸý`+e‘™›÷aËlÌüÁ9ò0rÒ;䎘Cj&Ô"óD×vxG…:Íé˜ËßZCò ëMW–¤ùÇÌv†È¸&ª÷_­?ƒÂ‹æÁ&>,f˜ÒP  ýXÇ+Ei½›’âlá0n£û Ã~˜2°‡æãi*<Òxø‡J…— Ô‡¦*%ÑìwÎhÁÄêq²Å‰èÙ%nÅïûnb›$YÖ 0ˆZZ™‰lq¹ÌkŸp¨ÄœcÖ÷£šžKÄÚŽlDQeRÐN†™’ ëv~u’mRñ%V,÷ò*T˜Åmvæ§(ÓOÅu“Ù|±‚DÀè‹ÞPÑ¡Or¹§®lú”‚£o¤©Ã<ã2·4u<·#¹¦?îAbʶ¼ºÙ ‚ãeNBª±«F‰·b),¼È®7I‹·<ÇAFÛ¼”È1õ©[ÂÖ£Úx–=åü|±¾nâžR»ñ&‘•Ú•êðÙ¦ï™ÌYÇrÖÊЈî§8Ñ}H+%m{ÐîD7÷Y1ÏNŠ8&Oë"_Y òlsŽlzíæ(fÖ%úCž‹íAä¾4\„¡±ü0ìªnÿÙ"[¾[¾B–zÆÙ¦YƦ%¨˜¤)öwï> ä{ÎÉ ÚqåeT¯ 1¡åºtlàÖâ,Y`kB¬ 20À@}çSœÇƒÌž{ÆÃÜôÇæàýá÷ª=8ÑÒä‚ÞòT¤Ñ:œÓ5M†: íüøô«µèD•IŽÄ`‡ÅXˆê"šÆd/_lÞ‹:7y\8¶ÇæÀg[¡£Y¸n5%@áxåýÜÒ ¾\¢§p}('<Ò¶˜Õf–×`ý·¬WîvFÚ±)l#‹c×>Wuºz—†HZú"·öhÂÍ1]+¤Ûk¸^@HŒ|•EO#Ãt6ëžÞ2ìœ&yiS…·LQhm›Ä#E“|û(^Èæ=ÝXºUXÃa¾¥=N9厣Âý¡Àóû£×&›æ,§móÔ ªÂÑ “*Ãv\¨Ã[¤yŽ6Miº“ó˜ÃÑŽ`” Ýi]ý¼°Ïû„¡Õï x1”K÷¿6°úÁ.Cïs¯|=ñ\v—÷j×_ÎÊÚ4Ã[wZÉGfì L»ãäØÂ ÂÑ ¸C´.ùŸ\\"¿Û…ˆ¿‰Í$G¦‚^0âáö•ÆÂK¼N›'Òü¤Ò Î݈ï¥@`t‘›Üçßá‚gÁÁú{˜Ç Ñ?Qn%.2Ñ&ÃèÍ•ðÆœÁP ßÁ»Û諜%"ªÖ8ÛŽ†ð)¹.ÏL5ÿ‰Bâ¸ÙÙ©eAlP ÿ°þúâ ÙDq¦I"Œ¾=¬#zÐlh,+×¶l_Ñú¸iú-gZË<Ñ‚.3¾÷9êéÂ6Ðä57€ÓÆÓKÈœ(Ž-íx%ä¦aÈO¢Zöiƒ3Xn×Ý èºö‰¦õc«4â÷:+)dߨ֧».ƒ”” Ÿ^D.ê÷¿]£â¼¯ùCÐRAmº?Õ‡Èr»~÷l„ELtÑ$T¤¸h×0î—ªF'‰Lá ›ášÐNš“ŸR€ß‰&ÑEï´W 0mã?•^ŸÔñ'‹®ýøÓ“X… ‹üIŸŽVÞçÉlɸåîžÓa›çcVOD†¾.÷É„Pô`f‚Ñ6}¾ÆfoÅj«‰Ýo…ßí Fy•`À%çã² æ¼mþÆMúšÔYà¹ù„q±¬Ðp ]|ºwVmWmVyŒ9ÏýÆþ‘ñ#þü —ãÂ!ýwÕ¸èŒ(»{ óJƒá¡•Xóy¶îH‘.&Úøº2·¶Â1¼Çð©ˆæJñ N‡AkÓáæá{Ã"´ ÀØ}ÙÁ^#‚äÁgLÖLðE2ÅÏ#0KU¸N®u]´ÅÍ7ö'i–L&#´¿ +ÇÕ·1—ÇÓÕIJÏ{'ˆÆ”±Fßg5c¶ˆnQß0‚øÁ€I…cb³äµŸµº'®±¿Î¶ñü ·)]E|˜†,‹Â!$ËMæ0†uå;žI¶&é"Yªß! FöùôYl³§Eô)^†Â^ÌÔ(¼²OE§ÐÒY*êÒF2§o&¢8·ãމ\EaÜ Çç.é3 aKߨæÊ.cñJ™W®ìÙöa~îr§ˆsá˜^ƒ {¬JIÜ.”âÏWævZgEÓ¿§B<‚"±~8‘TQO€·}²Àé8Ö§MάläCµØyi‹Ec…8ÖQØíCÙ‡ˆTSsßòŽ.Vµ¯EÌ…B¼þ&!;ïƒÉŸã =úá\ïW†øY¦±:è®Þ^H˾NMA—ùÐFBÉ+‡fÆ»=¢RSýYËìùe.ïÏqÓ ö¦Á7¸$Y‹w@õ#aΉîT„¬â“2­½ZžJ—§|; öA²/or÷‡ÁÕ®Ò Cňvƒ$TÙø„@+#6¼û±lyíü¯Àä⯻~Œ}.Žß¸é®xeÎ ’–h…^$õÛTQŒúò©%?&ïíÓøÑÛ'Û.Ÿn:h(BRc$ƒBQ±j”ÍŽ3-Ó‘•¨ù³NÑ[$a…aŠº1nŸiÎî|ÝïÍSP‡aÏ·”è®R$íÛ¿˜…ÈÛ´Ü»EßògDyÚ÷²$+­p.=«hÉ3r³À«[R..wÏåHÏ¡u;Âið/Þà ÷ JÕöt°¹|*éõ[ dÈeC5îžÿuƒ^ßb£¸ôÆ•ýù†C/ôòeŒ1%‚ºËƒ‡‰”ák@î³cXòÔ :ÉkƒPû±ào¶wyÕƒ+þ ²¿#eì'pkS¶«o2óèÌgà¹áA6„̎͡ñ`9U7 (ÝS}¼­ïØÜ!Ö.o¨Âd¢ AÝÍß yùú`„1¢Î2"êU õñ/â1ffUÒcp:/d—ŸºOÞÇŽ…\²Iă|*ÐL?Ò¼9ØCr”ïì½L¦$qªIÓKÖ2Qª Wζ2SZã6ýìã¥sêY¡Â#ÉC :"|’Pú³¾“r·ÏQ nÇ,X-rñ§ž©dcM÷¡ÐÔ¥O­ù,ñ¦½ÊêÚM-)q¬Yw}8eÿ@î¿î0‹z`/Lý5²UrÞFªÛ;„Z7©æµ 6•ÊÂÓ»|ƒã‰¬É¾©Üã_küŠÃNn†Y|gëz—}Y¢Q›œüƒÛ©XÃqŸ8›Ð©A™ ä-ù,kxPmƒÉ÷ìÕ“Lrµ¤¥<­Ë†sññ¶,ý€ž …µG®ˆå štwjGÄ'R)þn¸n–r3ÕoÀ⇢m¢ÝúIÌì«&In\JQ7yEiίT"ž¦ó¿Äc¯Tãþd‘íü©Ä±¡s•ÈqŽªFéÏÊ1:Ïì-œ£3][¿×Ø”dí–°|vfª |ü~U׌B*åcã^<ìs#ŽéBìòc¹MsÃòLâXTÌWš‘iˆK+M°_”.åK¯%»¾‡ˆìOMžç8)Bu¡(¿jÌü]äÌQÜüdM§…›ø¤±šÎÜo ì,¡T+[@H Hönk£ÆA~sn$ŸŠ2²úŠs”uIÕ_$%9“T¬¯¬$ìÆ—ÔUX:pýš{à o-ó5 S·(«LóÜ /¼¨?@Q€øD—ÃsQýg-õHòr6iâõ/";ÌÜ>kÜaL£MúN®t‰»fÂ?˜@ÑÁ0º nøKu±nÿbLÁ˜îšó÷„"fc™?^QÚ}ãÝüœ¦E vŒ»<–xk¿ã€Hµ&¿|Eg2[QîP}ËèRîZ“jPÉlI«êÚú¶är¬ŒŒ™Ûmá¨É®¯©L­2ÐÕººúôöó-hXøDY áŒ-¹Þùyk3òDouMOGžZ2±s¸Iÿ\É™€ eõ5[ÁpÇŸ<&ÓK¬)ÙêQ#?×àŽ‹o´°¶4üØØŠõ­²,˜x‘G›ñ)rT£ Ñç†ì›nÖtÐáS†²„çhö¦˜ž…õ“¢:@™IÂ7à†š¶3Ãc$vª—¸rŽ´ïèÅî!ë²4G»erÿµ'饞…/>A^®߃T§Üšì5xÇÜ ÿ¡Zy~<,Xj”[óìü¿'ª}4%òvÚ3%nEI~V{ø™Ý‹$ZFê4Åš^Ík„a^%,Ý÷®9Ú¸sÌEEh×¶­±«D·Ûê*ÕHðÏTþt¼TÈ«‹eùë`®±m,vÜc »7‡z3mxŒð™ ®:ÛW¶R«â;HdHÞ}éFôõÖ&VôÏC!—ÈÔË1œWa©!#Lew§VWÄärpg¬ËÚ€«wkˆ${)å¹€’$ö#6V=Vd) N ŒÕÖ¸5´}bÊ=t!ÿÁ)öo±æå„°¼ÿ„–uÔScœÐi©z¤áÙ6‰b€ó:-4…û3’þ]_äi£±1Ö1¸µÙq THЊKQ¾û]{åîø…Øûì tŒÌœ‰§îh3´‘T¸9ñgÐ;›€Ü‰lâYçÊ-ùØÝ¿§êüU“ˆ4oô®aí}8O^ޤáœVÇõ"ãÔ ðnó·˜_æ鱦æ‰üŒ3Û(ΡÕW½‚™â(±OÇxmV&X²Ïtà7âQS›üÑ6Û!• IS¥ql~±T0¬9½æ`…ÍF¦òHb&¢Sð4±hðš‘Õ¶G3Á]íS¤8ß®B%ÈÈKšQ:Z_ÍýžÂÒèßÀid€ÃÕ¶ß—Ñ™em»œ&µ‰¾"œjþw®¬|-¿H5Pö©„Ü”G?Õ¢yÈyÉ>YXím²Vd!UÖfô!ѧc_,´G“à¿ ¸Š3%÷²FÀ‡LA€ðA.ŒWéîÊj?¡Y•sˆ4ÙòÐtç4E n=üoï³ù¥GKî¦Á~:Ô>ÔµìrVfú”¹HÆýSÀø#Ó\ù¤Žß­[£¹ƒöXEº+®ðá­AÄÊ‹êm€cŠwYkåÛh|Èï£ó™Ð•v¡¬ÒˆžÙâLæu Á)t)îV°cÑ1ñ•AØ9G Ra“þm·ã&Æ0rZå¹£â‹PF}Ú,ûŠšæµ ;a5e÷÷¥+z$I-q8SÒhòIõ…Ê_¨§žW)Z˜µý GóÇZ ûrÆ–EϦpmÙrx¤¾‰RYI·^+Kâç2Áª-ý£JeˆÉ§mºæ+ðQw"KÙ‘Ø|*ÑÙÿuK­Vàeå_þ^²9‡5j÷ܵÁjŽ`–¹ªD'ÃsvTZ‰€ØÀ8cœI«;õ_gŠÓʉlNÂZ¢È )nzÚõÔláVMeµ:€t¢êz?±œ+ŠÒqú®ƒ¸0Á\à8“«®f&P_m'îJ»U5Œª3ŸpÁÝ£Þt—ƒ‡¸Ê¥â[ ðÅ$€.ÌóáȨ<ëõÇŽ=º=ìä'èùÝ+Ý%œå8rÝAÁ˜Z|RÁêSaÊîù2]¹å=þ é¬SkU2g™†¹ ''X®î2¨x=¾j‡ºu k¤gÎgÉ{·ÂËŠÍŠü€eþ_ g,W»íçPð3.}²Šl§Ö¨Â¤îYį¼qE[Ÿoa1w£_Óݤo~tJñø ð?Û{Ĥ&fD•¤Æç(¯Q»nœ¶k*3ü€X>KÁRgB’„º€ü¿²º&@ «)©ËƦFv=LG©ë´Ç¤ê¡Þ“Õu0üågIž¸DçÛ \^F†hÄÌ6Ð|Énn³ÆžxûAôœv¢=Ü ‘ŠQ…y"Èð'V±™6«xјÖ –½»wñ¹ô3ü|°s°Êz'PŽ-Yõí¯£´ä¶ …╜üÖU.,n.ã½æ‘ÏÕÉ ÷èžnI¼ƒ&z“£BgR˜>u½È 'C?9Àâ Ô5á®Ãz-´»LެAx ×øöÃ>+¹©_jó…8Á»†'Áù±Ãåï•1$i\€5[ã`ý_#~­\6?e=…0Ñéh5;âOkÞ£câ‡×ÐVUÉœÑ Ž¹"bÿ^úäO3ˆƒrÄЦ»í¤ó0ÿ]!Å‘ÜåâÐÈo‹Å˜Íz…"@è“HüƒO帶À2¤h@®æÈ(— Ç!?V¬0¥OHëþÌqbŽáD2{f|è'!3¥‰åÞ?af$µó£ K^Jš@«$¤YmûÚXõ‰ˆä*ËhƽÍó9aÌì÷?ß,ÒƒöO<Æ rè2ÇáØÝ.ôúÿp³¿]»'AoaÅGäÂ-ðüóïýƵyˆ’fŽÏx/†-ö%´YÕ#ÆE[‚²éº Û‰Ê[»ä:'€÷7x¯ ¸²Q5yÎ0 ^„UÊ(aC†q¤ú'e_'àŸ.·†›û`É¿­ͧHy«i~.w êîcú°Îû†y¾¬°c t¥4A/\È+ØhšmíÔ†w­N4xÄï ß´!î â˜=ÊGž1–—·bB·Ë«µޤlóJÁnöjgŒc\pmb³£mr‡)M‹6ZØÃD”1‘iUÖ8…Îbt¾•[­oíK¾ôÆ¿rÁêTgÓÆ0-ÈÖpY'lÂWŠ“zˆoR^õ½èju˜å³-áVW˜M‚º{s¶¹wåþ²¼ˆÚˆ½=˜g•b‘ædqdŒé ÇGS_*#©å.F,h…¾pgµùŒäD_:*›o,äù ÜC3&È VuA¯ªñïLkFÂBUÞC *„çôï;iÛݬh:«²¶}ᣂp%yŠ3t±z¿&Ó×ñwfìæ²“<ç º%?S\vVñüñªÃç‡v—ÿ„I‡òž¿8GºÆzÙªÐ' Ôš¡0±°›£‰&CÉ@v™ßqÃ)>ÎàOã‰~Iƒm3×BnrĈ°Qyäaê T“D€8¼ûöÄb»[èŠYžsyL8"cüòvnqªk«\íz;‡reèì”c!tá„âÝ9Jž1?'JÚ~,n^|i\ò„âHæß ‹Ó8³$ëlÚÂ&³*¡k708úRh@ïÞ¡#ŽÂPvⓚ@¢B…•ºO¤×}ÙRâTÞXñ´ àÙlÄð%ÝèWgEàÚ Ê]–©m:ke—2mè3¼Úö,…¿–‹G¦«¹âšü[< ¹Ÿ[€’Ñþ¨_Ö;†<œVÿÇ 1óW¢Ûtó½Ëš¬“A Yã_ÙoTr§ll[Q q[C·Ž–­¾Yˆ÷“px|G8djRCó½)¢K wJ ‹QPÉ·ˆ_d'•‚ò›oÀ|¶ Ù= (#œpÁà äzLNóó[lÌ… ±ÙFäÈøØ]LXòaʰî³Á-+p-’?rgò[§¿I~Þ,Q`¿«^¿Qù>vè2Æ@1"V¤ú7X_}Ħ•ë•ÐaÞ£jóæ &¼Ö*°Û'å)ÆcrPnì”Y±â3mÀ‚ÀzóìYª˜¡Ÿþ&ˆ%’%`Œ™dû=¶ŒfÇFïÓ² Ší§'‡óÜ8IãOòã³’¤I(‡¨m&¹ff-s7ÄãÜWÊ‹3ÇL†»úÐìÀ9ÕP{‚rsz¥ÎõZ5ì5¼Ä`Á€WAæÝ1J;ÆÎ-…)ÍÛ›6¯¤½°£öJî¼s·h/É@”Ù[ãéñhàv_|µ9¡Ïéñ<‹2Ø{Pð^K“àƒ¯À·ô„#˜\–תá¥u2‘m¸T7šTTY×»¹fq÷9ýA‡”?ŠÔ7ÁÎZ«—e>KWÓüc¹eä{œ}Bf0‡Gx­9)fBYúù”öShá¯qž Ùï7„}Á†Ívâ\ ¦| °ùÑÁ0Nv9¥¶É¤0Ëâ·=.¬¼á øB_¡ØqáñÆ~hÍ'ÒhO„F¹¹˜M‰ãKêW(:‹S ür…`ÂÐ ¯,º,œ(:- ”„+~_M–Ø x¯1 Þuä|àk°›•Eþ˜¨1bþïàÉA €â¸þX15 Õ2¨faç¤m N|Mø¿¶Ê.ûß.mÏôÌè9=Å )‹\Z·NO+£¡cÙ3²¦IFá°’Ýý\S„hrÎé膲˿uŠ BOæFT¯ÊjNn£|s#f¶™œW€Âù4¥±CÏ™Ìd’"Máªr€"º\©ˆR[²&@T¼»–8[–ÀmiøObÍVÚŸ;VëB ]w6ÒOVõœA‡˜×Ðè⟠¥F1ZYBΜڢ›n˜s‰ÃÛñ¢û/ë‘–Œ$~ín#cN÷Ø¥¿E™×9ƒsãßÃý'Z0,_Ùž'd’8(kùô’¹‡T‚º’ÔÏ•Î9:2 “Ï2rkqgn#w&¹"ƒ§\’i߯Áˆ9©n@D÷ðz¸½„½äåÔFâ<é[S&šÒ½´¤¤ø·P+ FÃþñɼ<¥j™Ó¯±­é]®‡-¾»º ö!'¯G¡09ŒùÀ߇% ûBÃÀéÞÍúˆa½𵌉ðâ)n‚Á pÒc¥µ~iGªƒ=<Å™¼.Ô–ïС4"åç¶bÔ>^‹~Ì9ßÏ>™áò zGÞ5úe|Ö…É$dЦ^™¯‚å€íb¦½&ÅéëWf9X ÉÉì;/õßÚùŽHº9q÷Ô^žÄ冠a@‹Þ~ªƒtü¡z@¡]UP;â¸_ç—r|T &oö(mÖ7®›)1J4§/®Û¶ ùày¬sR+_ÐíjÏÔ»ÑÙµ]ì €Æ0!R?‹RÇŸÆ÷J à•]kªÉÜà s´?R%ÙâM$¢cFñø* ãK“Zp=ÛþRöH`bûo³¦—¥DÖÆ|¡M¡Á¥‚Ç0ÃfƒÊnÖµ¦ñ1) Ý»M.ø­)·µWáÓ¾·ü ëkñòÀRýÌÕxÂìI~¸b ~X9itÏÞ≱›É¤¶~\†Ý=Û’N0öQ @] Sš(=—óôÝ"©öÁ©ÒC k–%¥,½™ ÿšÀáš“v/R?DCéôéLžÐ¥­—¥ÌíØR†2bü"~ÅéRoZ2¢ÛäûÍ$ .Dw$m2¡x¢Å|O&?°zîÜK‹{óTí¡ÂãÏÊ1ÇŸ;Äç¯RŒg[×9 Û5ÊFZ]+ºÔjf͸`ÆèÔQ€¨ßx#œ¦oä=G47ƒ%²lT¬$-ǼÊ73™Ne,ˆEE-ã: §Í½5Þ­èИÍ×øÐ­„‹B‹œ)yüû­á”ÅËm@¦“ÿ5\¢L[~™õɾ!¶r¥&-è¥8_åÔJûYs.žÜbV1ç©Ñ>™Õ Ï®º_C‡Ù]©®‹Yþ?—syºØE—XçDxë#ù—K[ ŸÑ0a&Sï:ºwýÄå”À°‰é§SGÉm´Íä•…ªÇ˜,:ÚAepü`׿¨T" Ç=oåRG¿ê)EåG¨g IÜÌ¥¸hôø¿³ò'Y¤jùìj˜]ÈX*tP’F¤U¬g‚Ê1´mèùXu ÿKP:2M?}+’ÈíëZ4gµD„ð·%Ý¿Ü!3#>ˆ,&730…Þo”~°vtQÅôu›ÿrá ˆ‚{‡&ò±èã¥)êO…|ESH½YŽ O¾¼¢áCR Ôúp9¡ð`DTx½í»ÔõAæšÞêqÖ\´ >«øö_¡h´äñ•°Xª%±âT/üàüö ºV%A+H³5C™uö«§ª¥1YÀòÆ rPZ•½M?w^·á;‹V²Ô2suö~wéÏ?÷1»]ô„Jwø=M -±N8žÒÆ÷lò6ã³¹»îÚ_éƒŠŽ¯9¸PY-¯D‡u«?Y>zrí‹l¶Æå±ðÂã;wUMu‘[6v×u:!Ÿ¬My⇒‡Žk7Š="ppÒÊù‘ \°§¤Tæ´1Ÿf§xW¡ÝÓhQPh<I—‹D3HÏ?@Õ:7Ìü\í­:ϳñѬ.¹’pAAŸ¹RÊLK¶®U¹`ÛK{øŠ 7ÒrÐóÜV¡²]^¦Ä5Zh.pêÑH˜QÇ—Wï ÀX F"‰»«MþúW¬$A"=ɼª|)D˜æR¤-à÷@7w 8 ÿ íR¤KMÕ±7ì­w¬§Ìît´¢;òÌ&>äl´Ý/+ ´«|3¼ºœ7ä õvñ‹”ß4ÑÓ"¤A §ëµ7zîS‰2“1ÊmÚ.£Ø½Xì§P’BXô¤{(º+Ì8¹îg”´[¹’Þ6·â%Ÿ$1L…²§Â·Z·H{hâÿôµo £¹Lù Þ)IKPÔe»þc[¦0”ñà®bþÂ^²9r÷ÏÅø½CkÖÈ×îÀ‘ÙÅ^$°xÖ?w¬MøâßE˽óéÞÿ眃YW8róŸ4!—ùG2<ÀbóZqI-œ0 fÝ5÷µøbƘÍ)óÎŽr õ˜GiãÀòƒ‹æÀ8çi» Ss&Ü|akœDó¸`n"`Ä/hI;ð4K²Ž J¦P˜élj¾›edI÷ºlGÿoΜ ùCÆ7A‚DUË}çc b”pœ/SÑÅ˃V‡Û ½ua<{üðhòÕûÔ_Q“À1m°ôeRË¿ëCsÕõ,h -ЉŸU$z° >£îðZ qLŸŸVÝ”Äòwu:E³@ÅS £ƒGãÓ~áóZòiÉD-u3T¯ù+ÌlØe#i´^LL¸H ôõˆ,t‰-È Ê2 &uºs)†xǯšfÕño"8 ¾*SÔÿv×þ‚ßÅzÅvåCye¾Š‰¥ê·(â[û©¬“¯iDLâ²\T?dY‰ì4Þ%ûíKæŒ@n¥p(Õ¹ðX¯/ÐôS±2Û¬*²‰¬o:PÀ*ÅÝÓGo°Ä!±ï³¬çÃÓ Æ·tÉf¦VŠs|í‰ÿÕºf%œ«ÿaCK@ô¹ZC,6É5KÆEVi½ìä"„ý:2dœQKlÅ#ƒÝÎåXÛƒ0‡-JE¶•ç•§ (p+kE¬öÝ!R÷‘Pçiîè,‹q¯:¶y甦æFlÓ“ò÷,ÐÔÔ­Õéå˜PSò&¯Šjà¤ÓÙ=3‡ï´Ù½ßùp AÑŒY´vøšÁ˜ØÙ¢÷¬ïN(çÙ<9D ‰@3Ž»™:‚b_ S‚MKÌPÚèNc‚È}/4—@ÂêZå ©ï¨'2e¶œÜòhýÔç'}™G7;F¤ô¨æÖB”` Jó¤}V?AߣÁd·…-wÝYÂÌŠŸ÷ûŸ´¡Ÿ×§Ç;–5i™±úa¶Yï’ŽùôA³øÕ†ðŸ®o³­jÅêg*ržôÅFóÐI‡ÐÙˆ›ú®BàX†šåÓ<™"•BŽÄd½^´Ky¹×’¢Ê£:Ðqò7Npc+*£MñÝyºzÑ€û)RkBá€Å…vñpf[¯ž³í· éÁbÏÛðiâƒYbùm›(&"ú-–Cüp,ÛÞcبóR=°+Û¡¤l(IñŸì;LÛžÏCÓxkÚÅ6ÑÝb|T§OQñn™F’F+]†Ri/³ÚU‹óFÊTrs¯w&&`¨ÛA)²ºc!kýñêYµ ›Ûc/ß(¬[‡àYóCsŲ`m–'ßWvãæ¹aÝ«èC™ÞJOGáÎÚ¬‹MVùPM*“të" iÁ÷MWÒÈÓN”èË7ãælÔa|— 'Å48­†÷Çü¨k`$(²‘Ø$#w;Ffé3ÈÆøyP<éñËá–“<Hñs±àAZ'Ä’ÀAãi]ºÜ±ð“lN§\VÜ(iu½{ Ò®â¯ÿõbg±Ö9»[·£/Õ­ƒDÿsÁ`Xí0h°Ç;¤Hõ–ßœóNÁÝ…z9Æw7 iˆ7w~&ûÐ87Ƒ¨ª½vŒw±°–k)Õ[rå›%è£ÐöTkûuüÓÉÜ[sÑþ[ËÝÜj†ëÊYû,¼ò ¿çÊ:|º*þj@®ÌnCk彸›2ÆïL;y¯5r óh+GMæ˜ëâæ-¤öi†B¦¸.én[hÀ&Eæ½&„—Ô_Î høsÌkðuhèL-œ˜Ñ’aà|Ržå8_wÉŠKÛ†>ŒÚ†\øx—üò\NáºXìXù¨¹ä¡ñ5¤!á…V6Ïz˜3­ˆ¸üeŽõÕû²f-X)¼Ñ0ú|ÿ>›£q’释çÆ1jFbª5Ù6t Sžedi½áã4ÍÞå4òcU7'§Ð¦\ˆa'©÷£¸+M`ïHpÅ"°릵ÿÉÛ%°-M}ïË+ HWIIbÞñY€hñ\ÑŸ4¡ »ügãÃuòì÷= ¿~í÷Õ®ú®i¶KÕtgDN²åNòcñ‰¢Ýáe†y8€ò„X'c˜p}ï·4H‰a2UD¢¡l܉Җ•ÐÙûÁœ` )+v¦õ£!®¾›ÅA ˆ•—•â¼^zoOɉhË>ˆ1Ž”"jÊ$E,ˆœDMÑHÕEN£óåÊЭ~2œ]™Vˆæ^ÓY©}ǦžšÎ³;O´x6ÐÊOQ)!„$"´œÏpãx¶n;ˆ*À†™T¼~è‰_SM%¿¿ìZdú› çkÿk曑2\‘ŠVáÄÛ¶ByëKiO˜+mdx3:1±ê$$’½&RB(Š˜˨¢7Ë}n/¤†•Oõ´aPû:§+¨¹f…FEe´gB&©…P¬; ·ß~æ£À\„©Úy°Ä¹Î|6L¡[õãJèž“…‡Í!ÝŠ„ôÇÅW°À~Ó>×tösòÅL¾CN—Y e´öÿ] ã2_à\mùý»Ùs#¨£X¢áX‰ŠÅø/=.Þq5Ël,sa ÷0“ŸŽ0=MæÚvæ¼/±U KNæ]CwîûFcäûÃø«QD¡™Cl\7vúHó¨ê’õÉSVµÛòýôQ`Ö¿ ˜([ʇEõBÁòÛ÷&©§®0wéÚf!™«ïêïÝ(0‡‹ WŽ$™m+ J/Çžp1”áH¨A·^Ü2ËbÆ“e‡ÕªZß^Ò p°ÿ(½ §àÇ´†Ôƪ¨1 Û×Ù+j/Rp½TÒ÷‘I1†b.[ß‚àPØ6b6FN¤`K«ËLµ×Ñ ñýgµö‚÷/ÈÌ)lßfÖYb¹§t±.w.o°ñ‡»,]G#¦víë ÔTЄ#² fµKžMîÙ³åY&·N2g¼¹àVÚÚ–"_\jáo$±«4?ĵäœ5 GE¿dŠÂOFXâd`Ÿö¼¡Ÿ@vN^“œ >੃¡»·pZCûI¼êXSÿi®¨*­_º /•ç(IøWïÊ­¸ÓœX5oDàϰU*–›À’¤‹0xXõ…”G4S_!8í€:øÚ˜™”W§è§Jƒ>—Kgü”›t¬ô‡_¥’ ØquÏ¢;1ã\šf$Xl†ÌWA0ÃDx’k6öÚõ ! 6+Þ†ñ¾™óE.åöŠúŠMÔÎDlAÅl¡&U©‚` ,غ-”Ó/.öTÙÖX»LzäË‹Ì×éR¹¢ð2´$ꚉLƒ™®¶e¢s¿äXy}'àÛˆm ?ˆÇ¬—Ù5‘MöBÝë4öó¡d`Ë.IÙáԛª”êê$§ïñó€°É(7Të’_9?ÙpäÊs;qŠ®@fåKt«}Û·¢1²~0ÖÑmLŽt5v+‡ Ñq}tsMYιRwl*+ô¸ÂpèËß×Ç~ôÛÝ;éÚ ƒ©NYì¨b;ÊÖ1ĨíÚAï¨ÕÉÈ”Yòv¹´‰ K+gØ€X…¾ù„†d<êœL½NL ožï²³ODI1~øNœaÚF¡ËÓ¾àr@à_Œ”:¢T´—½Ít®“䜨AL¸ðÐOÝÐx¥­1J•;F›ÉTîAÒ}‰™+"P×t`Ç…Œ89à'³æ8•ÊkhÜËùdGyöäìȾ视És² q$’L¼WN7µ Žž)ÀQ@FG¿RÒ›þì]°—À¼ÿƒ*Ðq‹K{%Ž º>AчÉÛU& ¼~¹`—vÝœ'ˆ%†ÕJÏ¿ÀÜïz“f&ˆôVUÁ·î É­)¯Ðô Ì«1:´¶v(µþî·ÀØê ‚loQjyŠo”/‹Õ]\S0pé8À®H²ØdæŽÓÖDyKÀ˜„î[LD>A­•ÿ<©1, .jD?:¬ï±?¬XEê©ý±ªe•ɼ¤HÎ\tˆ ῨÌsêA|“Í™Â,£s¹gűúÑš( Þ¹6%ÞûîexÒWæ©?x)LM‹?|~×~gP(BÕb¼B®Êþù%ˆv¬Ã6õi:ouÿ=?žùQ´:n¾¥xHîÊhàdO9õ’öÒÖ:ç a†E9€„ë¹@括¤ÕtÇÂ!w”ÝÿP*k]ʶTºÉ¨_dp>Yºµ¥Ä˜Y%½ ;´x]ç:>;{h—ÎG+I¹©Ý »Ó&‡0Ÿ“¶PW.ò¤j0•ÛbOW}±½×gfd‡ÄáKRþõ ?.×>çæÞú›Ö§\ »tz·@*a«À®¾éëý¸¶tg?Ê áw¿n“}7x C1"£³ÙGªß‡¤aè h;:t)ćL›p‡Â©‚õ^Ù Œ!¬d‰«A™‹4^¥ãfÃÓ.î›§¦*Y¿íÏe;/6RÞ*'˜Å1~E æ}«¤õŽq¸âÜ–¡¡—N<õá7~×å•:í㺟ê\ýMøàüoBI9q°æ²–Dz>‚k3ŽH±L9ô«cápòù½ÓÆ‘&̽ê:>.M±®SNbm’Á{Ü]ª l `9`JJG¥Àî×i$KSóëIÐÔÔÀ-BgË–6=0Sûâ›ÎX[hŸb¶jkZT Âò5l÷Á$rå(-ŸMn»J²½ÑCËòŠ:t—/[ªª>"dÒ´žÉU ‹KUQL´_¨ETR;»Pˆ‰®}áÜÿøëÚ–„¥døõ²÷tI?i£¢Óôø×0Ÿêßï¯Ô‰ÚVn8•†'ôÂáD°@½¾ò~pvXêÝI`·6nÑül©âD§¼U>‰»—-µÌúq?àã(Ãþ1m¢æÏ4cÞ£²¡${0¨Ë¢NØ·[]•õrm­!xÿïí‹B s”†Òþ©9FsƒKçO’»~ºY0ÂÒõ]Ù‘T \êz'51h¶©ùÏ in8ÿmïUJ@a°Fe)í™Ó§¼· +EÊÅY'ˆÓ.ªà4&~bOe!Hr"bt‹éõdšŸáïøZË9a¹­ëÚÊÄ?´É^¿B±ÿx?÷½[9-”ÅâZ.î)Äô½ó—U•3ŠþË´à‘fy†Fp p;;æ8´®ÏÀ}‰Po”9Ö¸µ³‰˜)9w£ô«ë’.Nê-R°^wR»¯zžQk•8¤ã?k·Æ‹šù—+/ãh! Ľä6 Y´ `Ö'˜|3‹¸&|¡E½Y‹¼Uû1h£,YÁP×O€¼ÔEåeäãB¤ÜÌóûÔ᥈pTâ mkÀõxÿ L¥,øVÞ¬WÔÈËô¯ã~‘’ÜÓ1¶(%XÏ—Ẑűk9p¤Œ‚]ùý¹?¡Û–‹XFVÞª°ÖNÞÈç†R5°T4¯ vÜÊ:U¤a*[ŒVk?ø „È É' ³Uœ%è‘ÚL Á´ÁÐ\ØŽmÒºãž§*»†1ç ãõÑ_ueߣåt8‰ø39p6é2‘Ìh½pB@6"‹Àáž\ÖÖ‡vÇf[¥.špvb¸’ñÙŸ«Hóàäa/\édd¬†•9a€rýYvÌQ½Ï$Ã3:²I_rÂÎÃù? :­ý^¡#ã@_ù¸—(–KtumZ#£À—uï–=Só{bõRë' "[ÙD‚³_a4Ù —ßðªu<6S hlÞÛŠ¥¤.Ãc=kjך¼ï;ñNv ¹}aŒ-KYÙv¥Úb÷3ƒxº@”8ÂÕuâŠU/¢Š+Œ°S÷æQÉÖA;áHˆ“Íú'#ÅÙT2QÁ²‹ë)x $ËnŒ Ô$ D`Qöœc7Ðz$ùwÄ”ø¹Ú l³À$0!I½µ&{•{$IBÍYb,&Ò+wú-³p„õýSs¸Ýe(÷;¼q€ å,="èqÏ!?H0Eíàù¶pEß á®ú?õ›‘ðv<ð~ìâˆ!}œ|$BÛÀâÍ.›ÇF“Öë¿TŽº ŒƒíÔ‘´¿0’±¦ÍtjÙÈÚxLõôÕ.;IÆà×ç¶<_½¯®ƒ²MŸ’C@±'t'ú¶Å!#9óüâ·-;¡éœ¸AÂT2Öbÿ  „eÐSm@s6¯HSÊUîXõ½ë_W[kº36âرþàJ–…ÖîTµhpŽ?Ô媒êm À€ÍcÛÏÈZðr£ÞÐÂ"§+çt0(‰Ä“5‡t«‰zóYl9¥ˆ5Éâ^ùJ@Â?”èap ¬a‘¢Ì¬ŸFyÐù<1/G; öÅÃ÷6`àk¬: ’ŸýôåF  Xi$êFJ?Íë™Äs #¢Kˆ?ÿó¹‰úÛ-¶«H¶ð’ö¨T”¬}oÔ¦c#’El¨ˆ/”b¾Dˆy}“”œX ?oÛJýbQ“Tx8W6ãŒÃTì%שt%ÝìÝpK f„¿ÛïRïJ%tÚ—ùgáÜ‘×Ü#p`A?9¹hBW¶ÍÉ~=);ùòk~©~!þ;ò%¦ñx¯€ Øã}=a}±äë€NöÈñ¾ä kk¸€ÿŸv ^¦.¢÷‰‹P)XB&"ßèWÆâÞBy”K¶;ØzÐh 7°¦è»w_j¦„ŽbŽ®'@{8PvÂKWÒÒÌ!Âvk}ngÃ1í ÙúÕî›ÆÞ.IT4®HóÛ"lùf‹¼邺l¯‘:ì+%ÝTRŸ==CÜg~~wU™ZUª¨^ˆÁl²õ¶‚ÃK_OOdrKÜÁ$,]¿Ê'\s¥‹S[‹-[î4Wh¤9ZŒn{i´ÈÞÚlæ7!)É|¡£¿H·âJ¨h$¼À¸='Ä¢«ÕT]'>Ý3UVù– )[ù!Þï}Œ¤ÿ¨tÁ¸ÔR°¶¸E ëGç.aqõ± qTM¢äÖJ|Q"aêŠ&FŒ\®Q±s£}Å\ФãòQ¶è“"wFo¾š |«k©ÿ`P›ÀXgÚÙÀ íôÃè®õ^* rL2Ò þçô7Háv)ønÞ…Ü´Ž–½åð9F± 3A B+’±1sÚ°5hVJÞ¡T€µ$À,ü™Õ¢§ÔUV˜å‹cŽã¯%›ÐW•+¡þ‘õ:Õ(…?ˆrO±Ø]t³\&‡_L4¾ˆ:uO£@&PNð­ÍÆï£µ]î C°å¼NœQÑ ƒ´Ù#-Sk¥oÚˆ‘[ÅâÃL¥ úPBB¼ÜW¦‹¨Û»Þ’8Bj¹cÉŸñŽãáTwL5QÀ¿Ñ«å)_Á¾¼;I}¿Ï\T\Æ1‡,Aš€½ËÑQÎYî‡x«µˆ\®–K5pÜ’ ÷®ZL~â2ÿt¹Ê¹òì9òDgvw’™âùʘúÉQY‚STsÔA¬k÷Ø_„sDfÏ;R„?†uŠïÍ»§!F Rsfʪìúçð(««ïyRž•=áœôK‰ŒÖÊûyñz¹¡•xMu½ätùI c+¸»wè÷SŒ°Á ö‘±¥©y›¡jŒP?è¨ð*¾Ñêø2ì·©a\‹j CÞxOo—ü¢ŽÁ+Ž#}oâ²à@ÜÖˆÅ#QPÖhi·TòÛ_ç«û §žSÉRz!ÎM'[œý‰µûTŸÉ+à(u6p¦D+C›ÈW2£\Ó1h”´J¯L-ÔŒ4Çೄ´:Êé'È×½³¥'ÿãí¼Ph7AXÿZÓÀSv²k®ãw÷ÿè²¾ + ÜŸÄf?ÙQ¬¤"í1¶÷¢Òï€E‹2à(¬æŸHdÈxûÎõÜsŽ-à(yI‘×+£­»:uåú7ǽQ¦Ñ~åU'2¤š|)AGó8Ž\ä?¬ˆee%Ìg£áo;$˜æ’y¨}+”çÛS_]Í#õ ð8Ϭ1l3¤ê¥7Ç!rÒ:á»±²žð›ôQŒ8Ùø2Ñý,üõŸ ‰¾² Û°È7Rh€2‰µqc³å£E†wziõNñqÛ¿<Ö}ãü]‘’^—eieYgMg„ Ø¡»µ¢VOY5:•k€E<«É2}ðT™ë…׆D“EíæxUÑúôÎ…²>ô3/‚?俳ˆáûš=ÌýšHžˆÐÆ!øCÈÆ9ža€Üß5©%U©5;žny˜ÝQ«ˆ©œÂWÙ|ömz¥hÛY[ £;.¨qßKƒ7ÛõúUÊÜ\OMCV VVô©F§ÞeVí×w!íŽòÆÄeKšXëà5)üˈ¨f£rwqK¸B˜ø:¼·MÐÛª7ê{ªç=aÞîÍsö±j®FIjÃÊx4®·³øóÖ¶ó “ÌÙœ*; hC¬±``ájŠ´úãZê=ƒ‘ƒ7εKpäâÅãT½ UUêÝBéõM#`|’õéU–aey›ìvoÇ鬧9Q3, "¼à“M˜¥•w½drÕkµõ:Ì'''‘¸á»ÿи{3 ´V–þúÞlA%² ΛR]f0â;8PZýî4Ï?*@=kò~é£$ ‰-³~Ñ7¸usÄÓ$B¶AXa\k³{C›B™š¹23Øìˆ}¦µ`,B_2ô†üЫծ §?þÃ5?ʦ"`âä’×>¢I¿/‰£u2UÃÒGÑ,X>2í—JçÈ+:þú·óI3õɰÃÞm Õöj©Ê“Güšqª:G´ ñP;´ÏvœvÕÊX¬3%%Ä@Û®¦?ıے”x’î=ŒâÒÔËžêâ8¤fK…¦³*‘“ (ßZŠtî+J† ÿÇiB¼x`/ÞØG¨Æ*MnŒ7¬Tv*U³@·D6óxÄÌâåvm¥Ñ3 WÓ…sääU•”g½bP7Øe¿O#Þ÷•„WDJˆé¸}×1s²ì€Bp"=f²ñ°Ç<ç¼ ÐËœ$XjŠ,Ä@nSÛÏ-§u–=}"¾£á$ÃÛ¬ÄÒ#+ç´n¾JV;n¯e¥+Æ#›gË:2?¹©W€–¡˜ÍГJÅ®Þ4PÑ`ôë‹#éâï¼TˆAù­þf´€Gï¢@ª¦u`¶ÄèË&˜ŒÕ!™Ç8¥¨cÿ·òÀz-ã$@žE:Š™k]ô‰«eܸ‚wÀ53?èPÿÞ]}BµœëÈÙóüñÖñCLŠÔ¸¨qé÷'‘;ê ÈEÍšk/Ý-`Üyºœ<Ç-{"†90èM_Ö‰7[ ŒàC¼öwúô†t ¿¿ŒóüÀwŠñNÔÆ–_HÖ §Ô1÷„Sý?^à}̱BÈÙOYùÎ6º]tlÚÅY_.q$óÑgzõ7ì<“†ã¯úñ AAùUS{E•=øÖý•±»ù_¥ÂòsôîYð¤aˆ«É©'ÝbZퟔ‘ ¸'ŽÐË )0ðíœÓz£ãll£±ÙØÚ$ÝXmÛjl[ímlcÛF›lŒsÎ3œ»ÿûçæz®F–â4‰ÓD$ÉqLLlHwBß‚ÊbÝF¶{¸-¢Ñ{„-Øæ@` ¨·ƒnŠÿæIå—§57ZFþ;oÏ"p:^L«¹d"§Û?-h: ¬¿Ç! ×5S„¨î™|Q ®*BÀéöÇËŠtFŒœœ+uásB’ˆû×-é–ðUšKò’æùïÅãAZÁܪê©ãBe-‹ÓÊ,+Œ–K‡ûˆ{`1×®ôk˜ÕA#ŠÐÚ³ƒÝŠèº¢ÃzÁâ§³6áÌCÃLi‹ê8±»'ú'Ãv¬˜¿±´Q¢@Ïú$=>~•ÔÝDQÁë^Ô0CmP»}K(½êWw.³—CÌ‹5„Øš-ĵ+¥Že<ÜÀ9*ÿ$eMí˸¤¸vBnQ;1¶ÈaNÍþY.ÅëïIÄ-…VC¯ƒ¼»äÄQ€æÖä7ÓTFï|ûNÿÍöÌΫ/Ž ÍZ¾=uûm A¦ì?Þ,ùüi: î:>JžîsÜ_{ÛËÇñ—Ã3ì÷§ôgcç?O‘ïºvð.l¡C{le`EN\ödIÞ-=ñ/•±õ€7ò›%ý"ŒÇg¢Ê<‚m(CèlÂ8Ì ûaôB?ž• ³c&ùÛò€(úw´ õ0ì§ÕÅð¸ïe)ãë܆åý'qÕ3‡d‡²ôa¥s™Å/"<û‡9üN!þtWG>1CsT¥qMŸßŽI“«áú¤b’Hj–°L©Ä òl_ù—l.ñ–"VI» 3Íå¡]aЙÈ4к’ 0«üžX6`ª·ºåÀ]dʶ€è‹"HÜ;TøE *ÔÞ¯/|¤üIYhØ»ù&KiûÙ³i’8ìzúÚ‡˜î(ïëš`&_!æŸüE;sò²dîÆ@)7jMpG›øÖ9ëíCx€°©àÃÕ Œô&®±ºúO‹a…Ý{K@=!oä%Äl3Ät‡á&4ˆ¶êâû|øµs[ŽîBœ ´C’ÓwÞš·×y™<ŸPƒJ/÷{ñv;Y ®ïs_:+hýU^aC©â%FóR+Vì™u0ÂG"xD*tz3§¬aŽXä36dɆÚê6t¯ør4%y[ßç˜kùv»º–CÁÏB.Î8 ÖpŽÛȺÿMrÛ@˜¥Y¼b­c8]Q×:¬ Ç»m¤Ù¯ É…)8ôùtáÈ `{rÅ7itÑÕXoVeúãû³ž±×L@ùQ`›8°Ð¤/ø[ß¿Ô,ô^Í?dñ=𓽍üãmu¸¸lÔî<¯‘ÇJ¨îø‘)ÕhçEäó3Žì ?zl«ôŽV Á¿Ä‚ C´žž4k”x®dxË’KTsœùÎw[?£ÔT°â÷ðE€ªMî?þX ‡+ó;¯Ws5ÔÔ€ …ÿÐÝEЭOÖ¨*ÎÃ*IQ‡ÿ9Jˆ1ÓbŒLÁËZM+ƦvÓÒÀÜ>vb”#Uyþ/¬P¤È÷Êcnxϓʘ*;‰¯àùd’ú…¬2›ƒªª©góo­&`D•éc©3Fýù"q¼c™ÝèÀq•@Ëhiµý føŽ·£Û–x—"~ýU\l\›!qa©È™ kc?}A©[œóðOχuÿ¸{Õ¶UláË—ƒÉuB± n()ÄŒu@Þ Éç}šÛSË«U|˜á’=`h›kÉëeNÈÈJÓ= 9„Ië©·ð˜æRà…ÃKOO¥†|S³ÓŸúþÛÚÄíн3«vŸÝ] IÑ4ÖqÒãL>ÿer*&__Àˆ<_I#L ¼.Ÿk=<õ zNü¨üV›ðúÐIÀYúó"lEô·ñÔ˜˜Aå»zÁò2L€ÚO&µ¦’ª_LÃÊr€A©þÉŒùÓ6E¯ ®ìèî¸1­ßÎìëQÑãeY×TË4MUA®9lº÷0Îoâ[ ª%‚tì8çƒÄ~Q—oóÞƒ2׫“V!ýd–¸“é•͘m‡ñ S¦ßšJ¡âôðÆK*ÿ=ÄdŒÙÈz”Ǹï;€KÂùḻ¾û¤¸Ša2¨Æê*xоóþá­Ç>ƒçe!2QÖM"&©¥?³·Ž’×qaù Pq>73Á4 ž½ñ\¬˜MÔÇvš½âG½Ø±åxçó³B`|«Â«ôC6ŠŠŽtÕ«ýQ·<Á XxÌFÌš4í·¼<Á£1+Ùð±ª0=-¸ã‰G DpLZáçû ;òhn[:'þ—qU'}æMQê'—W¦?%Çæüòo‹\±äó 4wAž!ë~$Xuú{ A’ùÀ2ç\=t)‡QÀü`A¦¤ÛDÓgÏÈ„‰Ž–sØâI22¼¦Ï»U‡ýÎä”oõ~ÄΕ$\L…L®ŽTê g*슬’ÉFÂ9šÏ‡c­N%㢤^®¯ú§}Eb3'`¬íé餛øÝi•+ÌÿtŽ•õ¢âʱÜÞÃRÉéG“ã“\~*]ÐüWÆt1‹•@ê0¢Ž*¶A¯A•.vwÉ iЗZxäÇÓ‹@܇ºØ\ão~&ö+,Ô‹S{GcXÙ)>‘£ª8|{׌‡€âÀ±Sã°Í‹:TkþZ D^ ÷2{"ªfG„ÊÕÉb‚D»*ž¡(G8¼wöqÈtMáÀÑŸ¨/@/¡sKQˆêÛñüì Çþß4ë_ëaå“Z†Ê?O€0o›†–l{0È=Ú×¾ ÄÌHîA®J ZX„´ˆÕìªK4ÿYošÚø{ìÌ¿î<ê´6'Œ؉ *rX›=¾Ï…ŒO†?Nÿ©t£Õç@~°8!ë«\Ø$O<²{To(ä9JÇyZÉã†ã]ßuTT•1„ln¢ëi½?„ÚgNïÊÀÊRÐyO#² "‚‰®ù*í}N‚Îü ýtOtŽ[ˆ?]“cZý•õ0 !îâÍ«²ríbrÕ°¿­ò¤saq-œ05ù1<ï–s(Ë¡æÈ&A(Ÿ™ trd3Oå2m;™ü[œéÐIøkøÄ婨¸Ÿr¡ì‡µâ]芰¥Z_t "dîö~?ZïQ—ú…²ä`I3~Ýž0aZ¨l×@D!K^VWJÆ@€tu3ä8^(¸*Â9ëóaOPªµÚHTÂÚ-3±³ðÅFÝ+Ä‹†Y3ÚF‰ýS ºÎ䨪:ù#Ó±ô¤ýì\x“Ëùx9OÏ5|iÜH•¨‚7ÅCæ"†%¦>Ï?éL gßzÞ (>wuý÷Üä„ÀU£lÌ1GŽ…Æzù±¥›Õ˜.˜…ƒõÞìðՉ׵+/C‡¼¦ÂÕ” ;”LžÉîÒx»¿Z &Ñ¿¬ytÏ2³„ÜØ¨Sõ›Í&¾Øc5™Ó½Ò”[-F–¡Gj@Kîv˜ÄðaH%Wk¨hI§ÀJO¨â³AˆdXÜœïÕÕíóãÿÃØ#+‚sçyxÈ´ªeÙÃÈœ¡ËëžÙ2ïÙ ë¥lËB Ãg÷zɰÛncvwŠ#¶ÚåJÕÕ -‚Mßy=ÄZáŒ%£ŽDm™ŒPä¼Öiíᇑ£OÎ}6Õ×”Þ»P™ºE¶RFË~ôÐý®q(Dz\Ž8?°ö²{]#iÿ ª¸o&Æ©Ûd_iú$P‡Æ±»óšAHÙ%½î\Z:×Z;£7rùÕ¢Ÿ}0]&‘æ Sªn®Ð"O1^/ýFWCeKÅX<ç£åÐ?Äc–hKUzªZ‘v“†1& /7î»:3¿º¢§îD¶Lþöœeo4k±çñïOƒ&«õ‡ñ×êÃW`‚Ò¾Œ2‹ñ#ˆ4³Ò盡Ԙêé,_‘»¬c¨7}Ôï‡b'áÚ³ód…r´ò1žóätÝ|ºü ÉîY^ÛI†I}N¹tmû\®¦`Òͺ e„]ŸJÍ ƒdð¸&S¹Øò{j9Á“{S´ø·ñˆá^»óz"‰~a‚™¡–wbþ‚ÊÙ¹gÎô¼®tŸ=lJöùi\wž–"g9âIv R¤ÏNý’•§!»>%ïq™˜L˜ç‹öA»Àêþ6wÞ; «³¬¨ýèªz‚¸Œ½×Ô"Á]ÿÁ¼ö¯$%¥Ž»œ8غG„&L©ècÏòÞ…&’r<ùé"ÓL†c¡ö´¬ö¿{+JFR<~€1ÏäáŽ-è¬8Efºm Å),‡¶ G9Ïh'1µ I7¦¦í +%:™yßÎììDÒU.d Ï—±r¬BÿÖúaúi åþôºAã _"ðßîxå÷æ¦B¿Wø k>ÊR×E`æâ]WšBÿûàH·#hÎ]@¸²}N›=–àU¨‹%ê§&7ªlc„vú'nòAžk³ßTC\tƒ0jTÑZ ÃêV†õ\YHb*ÛN7-+nhȰ8R'&dÌ_kþþᆶÑW&f)¡JT9S‚åP[Ÿïba‡ÑXÖ EÊ` &KÇÞÄ2ɇr™Ü×S78-½yÁ/Tgõô¤+Ÿs@>Û•dJJÜ|[† ”ûКèÀwæ#Ò²ßHN^ÂÉ!LJ?‘vM™îÒ`ǦۉmHHàQF±·GãÉÈ]ŒF2Ö·+|nuaïNð;åªD¬í­-І·,FJšð»¤ûìVpxÞ‹ ôÛgÕ*a×U»ÁÔ_#'BWMyV“ Óá´›øÄ–’»E›å8§d´^(è¡rz‘íADò­¶Ó˜¨ w{]»:ó½îG_B]š|ª¬¡4Nï¦;I0^“crÎù*|Vçh¥¿øY4ýt'½zR[šT½ÙS/•&ˆ÷˺Írº ±2¦)¶ +êwô$3näj(¯¹\q˜Q$ù7‡ 4 £ß-ŸIfhŠÄÖ/ëcg„•MÕNNKg÷NB¥€æP(?=cØ »HCuúaJèpY›jô¸xàöF;Žö•N£ÏÍ îÈ—;Lx¡]’¥-ÉÉU˜ÚY¦ð›¦—Ý„ š16Z‘°¤&Ñ vä"e¨Š6­Ùƒ”7r!´‹8Ш—¯”*?z±` jmHÃ~*Œ\ØÐçËà ÔhîïÀ‡SgÿÄì~Õ5hÇ´­œC`ÄÝÇçlÖXX‰³ôZÒÐÄÏÇ»;Kjeá Îý%’¨ ÅC”·æ­,Èð¿ ¦»tø GBÌê_f$ÒMwÂP¾þ¢¬í à«D½ÃÔ–/2’†EŽÝ»ÕXÌUñæÏâLù©K'=„ö²g¸êüw"³äȱ›£5/CN¤!A™A泤„Þ‡l‘ø¹6wqBe.ÒÅ‘îànb}zJz¥P¸dj¥œ‚¯hNe+!\ÙÆÁ¹ú؇¤Mì+)M)Ñ6³Lw•ÒûÅ0™¨ÝñS–PšY '>R£€TÚ8 [Ñœ{¦³‡*“ÎH;ºUØ’ ¹p¾­ä å$¤ ^øüÜUâò4|93øFÖ~XK¹«‚ÖÊÑjÏÝ7ñÑò©jë*;±Ê’²èeÅM_õuáÇ÷Á†ì-6Õ+béÁYs6¸ãŽŽ‘AJr©öy{˜ è¶áÚo—8ÕvIº®•nÄq;bÜ/7µ”8Øõkólpœ»j¤G&Ð?ÛKá×è¬ÆUá—°Â@¸&%„øz¥V˜Å@µ*Xrl´c¾nʰMœÒÀ¹N3’ÖÜõË z¨õ¨œJÍþùLäB9©ø8nkUd±¦ÈSíâa8Зå~Õˆ×sW°¬‹Wçþ)6œ$TŽjÕ:(ϘCk{’“ÃÑJÛ–ð;FJœ«ûˆÇjAú)¬1t=Z‡FKd„[õ[‚=îG~M“; ÏÁ?zoØ=B}ÛV*¼}ÛùÎqSÀ4ÜV¤>ýRyn¨2…’)ô/Ö³™§½ÄQ9Ìþ'/û°¼_õˆ¼÷3Æ›2²Ý‘ŸQ{Ë·äU'>x˜Ä\†m ~CD¯Ïê ڣÛÖÂØIL¤c"x(ÕK¥B œàç1ª°¦j eLï“í§JøÙ¢sqvúÔvïü¥²Q•ÓÈ¥Í-S¼„¥9n*êcÃ9I¤ë‡ÌßÛ¢41÷ƒGž´¯IÝy] uþö«¸Bü‰Ü¨8b›’SC3n8ð]à {÷˜UÜd =ÉR)7m­ƒÝgåÒ&ï&v™"Tt«@ïçsS½ ®hö¥$x¨¤ Žÿ'hÿüGÌì-L\ÝL\íÐþar<\ endstream endobj 100 0 obj 39812 endobj 101 0 obj <> endobj 102 0 obj <> stream xœ]ÖÍnÛ8ཟBËvQXïO HY²˜é iÀ±™Ô@#гÈÛW‡GÎt‘øˆ’®>R4éuw¿¿Ï·õ?ÓåøoÕÓy¼¿ÞòËýøtÙnWë/ó¹×Ûô^}ˆ§Ëcþ¸ZžNy:ÏÕ‡oÝÃ|üðv½þÈ/y¼Uõj·«Nùi®ó×áú÷á%¯Ë]ŸîOóéóíýÓ|Ëï ¾¾_sՖ㆔ãå”_¯‡cžãs^mëzWm‡a·ÊãésM]óžÇ§ã÷ôڶ¸¶®c½›sSòü1ç–¹EÌY˜Y™Ù˜ ÙçÜÖÍùŽíwÈæÒ™#rbNÈs‡¼§mܳ½G˜çnýþ@€?Ðàôøýþ@€?ÐàÎìÈôøýþ@€?Ðàôøýþ@€?Ðàú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_á·šsõ~ƒßè7ø~ƒßè7ø~ƒßè7ø~ƒßè·RŸ~ƒßè7ø~ƒßè7ø~ƒßè7ø~ƒß9þŽñwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßátF8#ÎHg„3ÂÙ¶ l‘Îù+Ú²rÉæÿ Y,h6¥;ÑÈDt8. Pi|ñ€Fv ¢±+íåK÷ÌèdD†TôÀŒg¥†u€NmÉ-^F ̸>-AÍÄNèÄ…²,²éŽuð¬´aÆ`¥Å‰ALt&8eÁM‹³<—“#artË„F{ÇN‡® tÛáÞ®Lˆvqè”ípvÆv¼øÎ™Kû2ž¥=²æn±•ö=Ûaîzf˜»õ1þûå‹OOgñôË$@;<«) bÏwW<}ynS—~y.®X§G¡ô¥)›Á°ÔÁõë ¨3,uðîÖÙÿdØ@±ÃÿÚ˜«ãÛ4Í›rùPvcìÃç1ÿûKáz¹â®ò÷pר endstream endobj 103 0 obj <> endobj 104 0 obj <> endobj 105 0 obj <> stream xœœ¹cte]·5ÛvvR±m;UìT´cÛ¶mÛ¶m›Ul§Â[Ï{ÎyÏ=÷;ߟÛvk{­9ú}ŽÑg_ëÏ"'ù¡L/llk”°µq¢gf`âÈ›[:;*ÙZËÛrËÒ+Mãpää*æNVÀÿ-Ž\ èàhnkÃó_©¢@§¿1§¿*fÎagS€ÀÌÊÃÌÆÃÆ `abâü¯D[€‰ƒ­!¹¨­»ƒ¹©™àß·*U%ujZZºÿŽ0sss Ýÿ ˆÍMmÿƒàoÔhekg ´qâˆþ [Y™L­ÜíÌÆÆ@ã8Ô ¬€– s+s;;[•(õÿdùÛ(3ýß?v8r€$Ðèðw¤þ#™„­ƒ)ð_³0q²°¨ÌœœìxMþB&ÿ@ Ž& 6@'Æ¿œäâ6Æ¢¶Öÿtã÷O±˜¹ÐèïðîŒÿ‹æ–6¶®6žÿbbncüÏcg;FUs{g ´Øæÿ ÁýwÌè`gbaâfeí@7#3Æ6Vq·þ üWØÀÆØÛÓÎÖ`b`åô67þ½Ày:¸NÎ@oÏÿ7ð?WpÌÌcs#'€!ÐÔÜî¿Ùÿ†&ÿ±–3pr0wh31üUÀôÏïßwºߨ֯Êý¿Óå ¬€ÿmîgˆˆØº<é™9¸ô,\Ìf¦¿óq³°¼ÿ'Û¿uø/ þýa`þŸ=2ý7¥´‰-€û?Fù«áŽ`tù_¨þñ55àðÿmÒÖÉÜø×2ÿ6¦;Ó_Oþ½0ÿ¯†ýø¿mûÿÏ©ÿp‰þÃôßý?:”p¶²ú— Tÿ!(௢6€¿¢dÿ¨jeàðX›[¹ÿßÊþtuà<¥ÿ7:i'ƒ¿ÓÛ˜Zý—äFsG s7 ñs'#³ÿðݪ6Æ@+sà[GóÞ zf&¦ÿ/¨bfndittü{´ÿ€6Æÿs[Fq#[csS€²Ó_ƒ8ÿ;ðläìàðWì÷ßÚÿZ›˜ÿítÁ9 ¡ßY•iå~¾ýhê¤d¢ÑTÝú¶{Ïí2ö^Œ{hGר‚}Wªi=,, 4Úp² AÈ/’аì¥Àú/€XMŸ„}¤ØO¯^¢+…|—1êKñn@eÌ޽ÍmÏEª·¾Ÿó“µÙÈIJ bûäJt?ð¦c¨jÑÎÁxcãEËCC¬¦Úôù‚A¾«ñûâ£Lo Æ‚Aƒa»ùèòÛ‡S¯µßz3åû´Tí½hïá‡ÉeƒàßeÍääßÔU:É-SüÈ~*íç$µbEÅÌ0X¼Ï}Y<3gW›«tÞ?/} ñ›··šÓÌœpû•^à¶ÎE ¯¸½6:°¿G¿R¾j’J>sI¬s7>˜~m0¥}¤R¤†'HwÖœ¬…Év)<ËñÁ+'Û±éý–[Àe–&‚8#sYÉÉhýbÑ7öû‡ÓAž<äë}ƒÉwhÐ$æ‚=ÈW4ø²Á³c¶ÞU\-ÿv/ˆe.eŸ ‹á{µæ®´ô?ën_ª‹Ö…އrÒÎü—×'à GmJòxüü”IÄ7‘¿Î4·ZóÒ•¥0ìrC¥Ú•}Ì¡}ŸëE‰öÈbÀnzRT¿iû¼3îü›–)‘ìMÎå:Èõ/9Ÿåª‰_TÃݲ™bºD d¼‘iº°‚#?¸A4‰tP°ï±UÂÙ¯%•˜]7_ÚÃIn’Ð-rb¼…)~¨îšÉ²E—ä”Yb`*KÆÕo¶[J¯ÌÙ0AøŠÇmoÑ"”-«LùG´*øuU>Ž-C†ú6ŒÞ£SŽKj0Ö¡üsv‚i ™‡÷—î.ÔlœIù A¶žS€ â½ l¡tÄÌÆ¼QˆÂ#'PSfQ9!•Ö!¦_ «ÚRþML#Þ­æMNzÅ"¬Ój 4)€ŒÀˆ~þïE5”¿Ö½ÉŸ>ŠŸ$Q/<¨Ò«Òº£ÃÜKÚH4ä‡, £}Kq'ïž%™FûÞ›_œÅ5Ñ·a#•öÊ8¿¿+£rK þëÙîÈ3¨ø¦[>±A á]P!ªtŽQ>¥´Q‡G¨rÇ´qXÿú1EÚy¯[A»ÎùÐT,Ýi£R%^Õ̱†óP‰erÎûÄ¿‹š]÷ÈIˆwhní®ó†¤³Øw*ê§cÈ›G'TŽÍƒºórEÓ³ 5ÈÚ-ø¹œvµ3í9SÃgêב{êâ¿ú0,€Ò4¿^CË`^/¯²h5+ÓB ^~],@8Æ=HØço¤X®_m.G×p¤’D™íͬöi~ «åÇŒe}ê!¦1v.Åþ ŽêôFkŠëd£ª— Øv¸×ÜÜ׺(ˆ² ©×W­ì˜D/\ÝöæÝ˜œŠäüõ†Î$¾ã:’ØǹÀ÷TÚa:vYš‹u‚k46 mÞéôý,oUvÑÇ0éÏOØâ+ŒêhÒÇ™<+¾ÒËÉÀ¨Kß×ýÁß%Â¥Y›Ûz½Ð´ÒÔÒë.}=û;ûq¡~ů“¼–0”ž:ÖGì3ાéSÅ\qÝOxk ¿¤;'nº°&ÈdÚW<~gƒ•Ž¡Ð]:æ…$¹Ô8Ⱥßb±_ÌÓ í¿S‚8Õê` ¶˜Ãè\¾¥öá=¥‡ON»ë‹ùÜ€íaD~,$AkäLüiÈ£^ü,nQcÛN¹Áâ]Vª;æI‹]ÕWm¥ŒÚ¼ëÏhßo‘UÔJ %šHÖ¯f”R&•h Šõ¹¤+A-CE-Ñzx§P¯ÞþÍAÕé„0EÔð[ÌDàÍñlÿŒ¤<-¿ÝÜ“ûœï‚®¹4ÑÄ9©«Èü Ñ‘ŸŽ"¢òÄfkoTo“9ä—ûã», ¿0áì×g{Üc”VLY·‚ TzÎÂiRÊŸ‹ìZ\óöç)Ïׂ¥ê=þøl /½UÌ9!¦Ê‡½Ô¶ ‹ÓôçÜs!í°ÔÉÌ;?¿Qdƃ#H}MÎtÖ×"N@t“äõ釩'‘hõA‹OPSè°y­¨´óŸAºg¢ÍÉõ*Ý[Û’3í"DHáCëmЫÆèYv$f_ÏŽ¶Õæ+(Íg†pÖÎßk´•¸Ü[»ÊÂ\­[W¹ËÐ>æñç(Ï·uª6ÑÕ8_.”‚cQ]µiaªo‚ÁíhnÞý¯–"_Aíw¦8!Ìyçžbj@&Š Må¹Lw™ðµÃF>HòÂXh×e4­6æÄòú"iXdÙµ´ ÙO¡þµ\?Ì%ì0ÈÁºMl\Û“!1žZºU‰mZW Y年!4ã±1Ъ¡/BÿXoƒÏs&‘Ú-Šlt}­ö(‡W8c“hÚÚ;à Ô~ £ õm1„0áPUyûÜ (ú×E²›+Å`îŸ;ñ5 ñ.™ë+iÃU{J„Î8½¿¦‚ bOœKÌ#²™ó…ÆA¥_lpßk&÷ˆßs!†¿ÅÞ"¸3pœ$†ðÕÀši|âH\¯B'ù¦èÇOø7•+gá/.[|G9ñÝ»ðä †€@PêG×ÓÇ?Ï5–³ %ó~âšI,¤7\)òÕÜ"ÞˆB_CVÖÕ,°´";ïRhjvž… Œg]á÷¹H} o‘MGûÂi²TšÎ8²­$~ãbP–7†<}>S§f,!Mö(Ö9ƒI§˜^«š4ÚLŠ»‘ä"­#hþØ+]辯-S^4#C¬ÎËTÕa1+I’W©ï©[haÕÕV$¨ŒQçjYsqê?âü ¬›0¿0‰¾3,Oiÿ4ETê´À&7Ì$[¾ä€F ¸Ðm»¨³w=žÐ(½ï¼êLÈœ>ùy1¿þt¨˜®£ƒm4ùã)LJœXrý»ïñ½@Ó]HKÎÛÙ^Í\Bù§­È9…Øçùh®èGµ˜€Ü£ŽjhdpjVØ›¡Ó–w ð`G>¾­ŠXEÕõu4›["‘ƒ¢°ÞÊäY#CEþñ»$šVà2Þ$!÷°?áÝ5ÝN¦•kì…°ÐT¼wP§ÿ i¡þÃö šb:]ĵچ… }*MÙ½]Žà!(¯†›7'HH«I¥\#"ˆûÌ5á©¥ØÔ’,›xöŠ¿èÜúË¥•ïºÖ•qªO,äÁ2øö·uË>øAZRïvÅFÕiÅfqõÔ%±k8Qò¶£CóÞ®ÖGÃ\ƒ¿€ÎÁ—I”2Aò÷ú¶s”D:¿îWÌùÝÄxTÇ!‘ƒÐSI-éÆXš|o=?ŠS,èëû¢Tê#ìÎÚ„ŸëÚõO ‚’È·E2ñ ØËжݴ˜·_ß9æó¢ÛÐò¶ÙY@*xnksªèõ™) jŸ±÷­t6Õö}Ÿï³´Còg•ŽDª9%ϪŸ²^J*îsr/¥a_–ÀŠº–DZ£3iÚ Ö²’ÒW™µý”¢{X“²Ý³VÑÌLžýNg”gE9ñÇ2 &JS õíónÈ› àÑ¿ˆvâÙ[0Þ©<—Ì)N«²|Â.æ lK{mšúè7F"ó ¯(‰¥_I묜YWÒ> ~ÝÎÀA®E-ɶ«çkÒ§e‡é&£zŽ>}N)„lÏ£~ŽØÑmòÚÿélÇ( ¶ó½i½i+µ°´8\ÓrÙB3õ _,¸ªÿðJ(s©®;KòÏ9<25/”ö¯qÙ 9Œ¹åg=ò³Ä/ãÞvMûŽŽó4ZçÑHf²LØŠ:ø›ŠœÌÃl ¹öìs$‰Î›Ö›©pXÆG~±w~/d¬×,S}d+uj¹ƒŽÓúœÎ £é2±\p']¦Ÿl07ÍAÙmqYÒÁ²‚‹ÑsŽÕ0ÜqDÅ~»®*ë¤Mjt·ÏKŽ'ÅÉ&àáŠSà~š#'  ‘Vc º(ú¥ ªaÉSÄ!xŸ$"} ­Î DvQ—Ž&n 1ƒ •櫹 ¿À½:!èң˂è'ûqÞµ›zã¡8ý¤ †ÄUôç*ñ6fd2~T‘§)îsŽy~)3ÙHŸÅ…Åì\Ñ_@ëÉA—)^Q Ñý¾Ö,ÞÄOgËeó R­œ™(;;AK²f£“ÜÁL®æÆà»+ÑÏ"¾G÷œ°_BøoR/½3nyX‡v8!Æ!”W:ÎË£Ï~Jæ*®â1x”Æ ‡ œv:>]Ž“¡&æÉ¬ïîãPæß´ šW[¬7ÚÎç`åï#Ùáã\”ò2«Sx ÷7k‘áe‰©6†„¿ÐáŸwúåqî³Ä/ ÁaÖ¾î#ƒÓc¨ ñpnµÈל”æðÁu[Þ£˜~\ÏŽÔKñ¯\ûÄ-E”—HÔõŸØcÆFJ®¶“ñï_Ƚn»0 ¾>9‘‚Ýf_¼ÿ„L·5Uã•;dìØH3ë¾€ï× ŽTqüͺô’«ülѸ¶Ö² †<ëâÒÛÝjçd=5RBPÅâUH¯=B€W4–aF”yæî¯¢cè`!‹¬s³´.`vÍP:Ä(J|]ü{¶W¸¼Ýi”HJç{Võ£½d ”bÆ•˜|Ðkha¼Ñz,?5«‚ÍèŒpkS6i-5ARľ&¶bì]i1ãÝý`£Yèpâå1 ðÛ×Qàv¤mY†›¦(J4é{À „ÁŸý†÷ ø`>q68òR!W^vž Ç[U^þÕÝGü{ ,8P]\âA^JbŸaš°CØîy{›Ko¿t×i4ˆýMNˆ¶T!v_{­ÀLï1 ´*âiǼŽR€-µâyŠQ,È0Ù²žêI}¾—U uð^u‡ZÕaûùõ¼b‰}MîâóF/¬W)ð„§ÈÍl˜…aûQ!&]1ñEABšÎ醯KOè3R-e°Àȳ`g"ãd+·ð‚踔žÓûQÕhd™Þ»;ü¢¢bøò=Ã!®› &èsØ­C˜#b½¾A|¢µþC{fÓ»¨õ½ÃÁ·mª˜·+8¿Ü‰ÆS â„ ã,(oÜ]ïb«„DÜÛ€´NˆêvÚÈRjâVÈáËÚo³`5reÞ¯·Ï'ù)mú¡öé Àfp„©$ß%ã ¡Ü-¹ù Œ0ê±C飹ÞX+´a’3=Å9„ýÖÞ|G]CÑO’Ìø1ó1|C•ÔEíâ#Ù­‚y t0{hRƒQE»››üÇ'6ázûœ3†Ê‰Í¡ÈátÑ-\îåò¨6Ð Xc 'Œ^ü†(Ò«¤`†ý83`ÍØÃ”ùR’äçVÞz_b:ê¤ÙqVÄI÷¹Ñågü“CëRÅRàt{̬4 -)ä -<3-–ÈÎ&]:à™>k7®E ¤Íß™zznûW"ñ¦é×^|˜ÔK"‹T*¯ÿÜk¥$%qå)Ò%R§Æ¥M‘ˆÉÀuµ ôòó0ô–eÓbȺj¡*ºV,è'ùiW7°+܂ވëÈ®Võ…-Ý— ~AÚÉq^誴Η¸Þ÷ó,0½‚᜹Ûé.AÖqÈ4Ö…‚BVÏàJY},Rqë$ÿÖ0ÐÅC‰-¦…õgÀd2&p¨‡ÄGÅvhž´ÌÎ*oe&‘Æ6žÔ(ÌåÙ† èK)©e/üV .ñv|›½ñe²X饫Â>„ñ⩳ÖÅ=Ã*ê§Ž-/ŽÜMc èV°àþàÃpV ‡+Û=ÑåÀ²áÛÛ-„Æh/çæråÇÜÃ)NôÉs„Ö~7W0ïŠÿ¹Ô'Uå&åQJ›°7陸Cåðùü¹„”£ßÑNªVk(NȬ¶ÞwTÕb¹x+¡qÈ!%`óRÐAVáWµåù~lÖ¯V–^“JXxå{§®å×è E0ú[L(ûoÚ̽"FYfsôþ\ˆï>†ÎRî9ß{¹9¬~k¶ü9mdÃ÷M‘oaí.þ®Ú)‰.Æm]Ó¨ÏЪ-VV{sÈ`[¹/M-˜=ô-5N×ÝÿBö4üVÍÊ)O mÃ=žlE]MȽt¬Øa(ÊM2ae|·$åé9¶ŠvÖôÓëB³ò#Š:wà€4Ó¤-«>V€-(ëeB&eyC­Ï¼øUåÉÄ»ª¶û£.»ÔZZ—æÞsE,Æã5”½î2 ûÂâE‹`±©ª”=ÖúÛRq£è±!ÅHqhÛڸ÷/Œ]”]yk;ÕfÌrg8%úÒoG¼‚ ŠÓµŸ¦ªd èÆo£hÅ¿²ù9Rù*ýkYutª†V‡´uŒ&qšg7õdRÁúçlëé\µ± àvñ¿;ò ÓÚÞkv|Ë 73–ŠzZ哱>= Fö}^Òúƒ’ð.…L’Dǘ_bÍ瓞/ÏÛà é|ä) 9­ûé¿Oóe׸:ôŒ!¼OÅd혅‹*:å\û†™¦ˆÎgØ.Úp7‡´y**,¿?#zK‡Úæ× â’ƒj çâYf8\^ïÿ‰â;ÕõcÑpÃt¬”H<~aç]ýCm¿Ls&Ü?æ {µ9ø.Ž"­:„ÊÈ2ae¤Ã®ß”&Žº³>§¥A¾Ö#ã?lâçµ!™=…¥Bðgճг€¥©xÖö›ÜÔ‘ ¦&›Œ”Q¼0;F™ß쀭 ž÷¬Î­nðj2¦m°‡ã¨»ÿú&_½ÞÂ@eŽ¥ú¹oK²H÷€œL–hâ»ÊAý^4Õ´3F`lvƒÝ4£tçáÂÓUÛdí\©Œ#GRˆ7xyL«×"_š~ð'ŠgÞ‡xž=·¡4\GGÄSð@‹¨Á‰`Ò¼þD²üd#­÷ÓæYz¼DJ¹£q3 ×Õå;.2»x#?É {øYÜ”áÌTÑUÈøÈÁ¥K²•Ç­¸ã†*Ò‘OÂÜ`åRÀôÞ€t]AK%4z§¥önæä“Òtï1câ@ÎÒi‹kO¤»¤Ÿ×±î"ò†¢IùWÄÌÆÇ‰õŽÅãk;àŒ•ÝQ¸a´ë#[Ç¢¶»7ËØTõw#A§´½^¶]Ý£¥¥/g—Í©®]øÈŽýjpX7¡œvœþ/¹eÑèmžô. <¡[ÎeÔ:×õD¨ òÞšˆ h0 „ˆb5oí·nÕeM²Ì¦5jÃ=ã E$]Ræûðâ!™5]}gúGhZÃÝ®ÙB©N NÝ÷úïG “phü Hjço4y¾Ï‹Ü|båÛ¼3bu;•éùâq7=™Çwh»‘5]„ë‹ð€KYmÙ>KÑŽäPóeŠkN¿Ã1©Õ.FçÇÔwâ×Û܉‰~á"ì ñ³‚ ÜaZÕov½ýÞ*u ¬ÁF³-·]UFø*ŒhÕõ ÀõæŽS‡åS˜:ô–c¦çE ­}ªî¶=nÔ±Nc®|ÕmÒ¦l!ñNÆŠÚ7ójoൠ Ž>€G*.C]5‹Q\åë^î“ÂóÁÇ S31ù¶LÛFÏ_ÐH“ Ì¢\‰ Ö˜K ,«FœÌÉç0É6"ÖWËoÜSg ÙD^§à\‡õÎn‚ÐR[ÚIt)—Žã¿Q¼°ýîzÕ«· LþÃ2Ê-2k3àÕíô*y[²J_ýÆ[L^æøÓiu-3Iòz.CK¬B|uÏÀ°qhÒáK #÷çº}€VÐ{ FLUlM%ƒU¢ƒŽøOBúW>KûŒKE£Þ%“¡w˜'àV€>½Þבæ|±ÇÝ—‡®†¸ô©õTŠ9²“/Ä«TUûy¼Xø§Mî×bBû†-Ú\qä¿BÁ¼ëävŠM’ÏsƒB çZÁN’¨áK£Õ5”çèÍ1Ì kÈá³F¨¯¹°ƒ1_o • ª½Ã*ZÄßPÐ\íÿ¼n€‘>°xéu0%Žƒ¨'ÕɰãÊ®á!Ê•t˜?ZdšQ ó‹÷‚¥v®»/ŽÏ©„ gÙ©/C¨˜zf¦{,îyšûÜS">ò­"Æ¢¨é–!ýõüä)/ošJTÁ=à^˜Užp«°ßªž4!0ßÛ¸[ѯ»BEô‡ŒË™{úȪàî¶’hªÀ‹ **£S&ŸŒGU‚ ¹‘ˆžª~S¨äCÞÓ›.¥¦AfìünÐ…×£ñ ‘}ΉÔ_É w½Íc-xèÿ±F×Û~§ù±CO;yë »ùƒ r‚'Y83É ìqàÁf¨‰œx!ìÝžkQîTÀe)ÔJ~‰Ž¾»À%©%ì Gušâ,âùô ™Óµ…Æ:æ0nÇ-HbÏgÿãÕuI[ݯ»=¢žÌ꽘;Ã䵚 ‘­¿òý$j©B(èà NyçK™ÏDzï1„y횦.GðeUŒÔþç!ÅÍ Ÿ)Ü/Ö¢²üi…µ¿?æª ßË·b+¤™·Gñ}ø¹%³Š\ ô„â¦gkÉÏ¿1fSjÕÑôëuˆòrúÊ”Ä,NÚ9¹Z ZŠ~Ü`’‡ìÄ0 ²£ì¡Z,,'Ø9ÜŒ$z_#i*¤ãxL!›Á™”ïtCm:´&áBž€È…Ñ>ú è”¶#Í6Љ´Õ5ŠºQHëruÑÔ3DPñÑð‚ô¤>°Ý#ð"…ËöÆ?#<˜‚®¹JüA(ÉÏQ³Hß s·F*«ЦecQ×k¸- Œ`ýZ©!‘ Hæ³~±ýhst¸¸•@s¶ÛAPªC%c_á볊›ì ’L¢õÔy^'E±¯Œf¥îÔJç ~¯^EhãCø&¥¸ÌêãzªÕÐÊ%>áí7œM~7ì¹ ™Åê³1³žkÞè–ÿy©Kaž3JuPu£—hv·Å}¾n*¶f[œÛ]A0•MW ­l̈²ÃþŽŸJì},AôÞwÙÐvÔÒ(ÞÆoÍÜgY$Þx’WÒ!죭ÄñÙ—Ø}uÄnèT·böxèuÇ6ÊåQØCö1'I¯hÇ:[¬™½aÖÙ“üpRÜÙN¸Eöò1)j‘b,áÿ(y¡% _†»€¬ªè( -ýìöíLÈþ@X®p# Š-Z©ïaÛ‘ÃˉA\}†å¢0#M±$¥ìEÛü(&›Ñ›ÝêCÂæ%¡³ËÙ€?B¹¥- Vï_¡‚ J‡¦pªBÅá*ô!ÎYE§œ«þcYx†:~5ñö¹êÉ¿Y}máÙ2À–pâš¿ ­q¡øÈ‰†OÊc"7×äWšc&xÜi-¢À¹×–-Å­SýÀMmè¾_²(‡%´ˆgWlÀÚy‰e‘ŠwOŠÁв¥r1?~¶0Øjf õ$Üš õá ŒX5ZýK}ì¯kˆŸŠGÖÈ.­Ëú­1·ciÄñ &‘̻ʟ„bÍÕB³{nWÍlåˆÒDBÞÔ:™Ò²â¦þ²3ñ]SÚ/¥°(|N+дJG†`~4Cå %,š0Æ~5Aó×\mt¤õé>Y3²Y»º-ò»iûàÓÚuN!TˆRaØ3ššÐ¦²@Ì‘xtÂ’zÙPÉX²o/¦ HPm+Ç" M¿1à.u¤"×w,‡ª_Ðé“C¥Á2Б¤!€îüNiômÆçÖKrfáiÛI—ZºSQú зé“[ØŠo[É2œ'Jdäv[âRtŒ¥wFòý¹g•˜;ÇÄiMðh`§ö4VüÔ‚p‰byA[¥_ØEô /% éØ_qÑ©K‚žEB>ªûñ+"àsÆÅô„$aGªÛõ-ËhÏ ÝÜìNéw‡ÌÌ}¢×¨0“OR+m6ÔW ¹Rs{¹6´Þo#òœš9#ô¿O”Œ‚¯¡á™Yº¥È‡Ê…ûÔnú¸Z\Ý4°G²È¾‚ÖÁSòx-ÇXƒvÒG­“³[§wÊsÔã,HßP¯ oé^ªˆo› ÅÛ+Iw5­ËÇ)ø8Ñ‚´Ž3â ì5 ¢Ÿµ›nƒ‡pmnSg-2žÃ›iú¦×ç¿VÒW¯Cü²lNe'·¬;ðlÀÁúSŒqМGŠo¯;ö:\C‰Ì\³*+gØ“­8.Ï9—è1ׂÙú3†ŽÏ2`ELÝ)q·+|~‚´E(Ê·Îú­2y4Çq×;Ñv0`ã¼½ÔK©l‹bm¡žÅ)0Ó QJÒ2¯~ù'Öñò7ýè|ŽrëÈxò"ӡ˹êbªCžø8å8›D ÿOk]Îë%4Ï#S¸ku‰#x‚T?AÓ% ¬’¿HýÚgÅ‹m\°`f¼ÀÎG£k=Žž$4â+µËyñPÚµÖ®èh!™†_#"¾¥õ$uªõ*½bv[ô¿[w9‚@ÔS;Õ|Ï5ç?IbYWr\Ë'kå'­[?±]Üb—çMê‰S 'å ÐeÌ€ýre´Ü“ÿ‰õn ؘǶù#Ý\cH(ÕʶX«…ó"¶J¿±}Mî^p"ê‡Ð¥¶xlesht–[´}¶¯íι7qÞ©„’µÝ"'c™„{K³´@y>d](¿||#RÑÃzæ›Æˆ ð7óG•ŒCá„¶‹Ùèþ†g{³cÖ_ƒéìóg´<Ìi@ÉãÃðö¥¼v僨N?ËÒ˜[²-h‹µÀ0†Ö-BÝ;üYÒ¸) hc™çÃfO!²6’"Uí¯ü¬¶ÀõöÐ7ô1Ò×Gé îÔuñÖlÑϺOΙ? :/-U˨î™mo“‹TÒÈ¿Ô` àCáÛ%À%C ÊQ•nï~YG(`d^0wœ½Èºêó-IEjºB¡‰aXÁA—ݤ±T)ÖÉ.OžLò‘¡7;.Y¢Ø g‘Ëu¶ŽúC½T/Zv{) îËQžIò)²Ÿ/Ôt™sŦ å«»›Óä‚T© ´Äm´¹5êx6ÿ3VÙáEPá:äÏdñ¨R¥ Â-5cUÔmÎ7eeɳ:£u—¤ y«swO”«‚ÛtìpÓ‡8§µx =1;×KVy¶Úp; Ì%E%«–'DK)à A|.C×µ~ßDãðÓTô¼¦àèa:­ˆñý´‹7Ì&  jù]†èÁ~ïÜKT¸êD ¤ <_Å,4ì÷‡ º®¯)0%È?¿o¼‰Ñ¶L éÙvhf>FOþ >jCmoð@õ×äVJ/ö®£ã¡8Xiwª" ‚!åcZË£b·úŽRŠ Ï–»]ta`fø·ØjîôgÔ¬ð:xÐçNb4T\XyV2¢„cmî°i—س1¼`¯1ã€Í Ð—:ë~ŸèÓ3+´­¢´“èF{¼Fb|£†õži8ÁB´ô[5¢‚äÍØ¤{ 1|h˜Ñ1ñC3KM§¦(0nïN2<ˆY…óq*ÆÓöÁ=dÅ%À DQ03ü<b¢ÿ‹FÆYSÙàItɣޤå05÷¡, ˆzb¶ú¾BîEA³q|é­ŽãÛ {&!Ch¶{··ó•±çeÿ m¨-мrÀ†BlÞÀd©Ó.5Bô eÏb`ŠÃ¾}«/òm¥12¸ÙrüæÎz'Y´) ©Ñ9A1_@Íeºäè½²Pí1ªzÁŠ`-W°,æÌíûºLÔ1Ì"•;[«1­˜s„š«$ÎËÏA¼ÎÙ•~öð|ÁY†yQê6«·±t"¦Ÿg¹L•ä÷TÍ–yt-R›-~‚Œî3Uð„sjç ¸Æ9&W~e<¤ùªF_ GÚÊíˆQ­v^Õl®áûÉÀa07½zæ]zF iRúv.£ß1ÔS>o“+ù ï܆Ü)wµéËLhp^ÛŠ˜éaÒ&|}í÷vúÙú±}`ü͹2@òDPÇ„­£W¯dkyÖ,›e€ž>\ëH€Í‚É@ÞNâneì/”…¼n=òú"Þ÷¦àö;%tP™Øæ€zKöÔ“ÕfJÓÒŽ˜ JÁG¤‘ªôc¥c:MÈOŸßÍDzkzoñ¡½Ù4OJ—ŽØ\¸/Ýþ Á_„”Lìì, èßܶÑÖ“¹¹ }ej Àn™FøÄyR}ã¢8`ðynLcêú%œºÝ§^ýcN~;2Õt£6 … ]}á ×Ö7h–Ög÷¥µ5ö•R‰U͉Á8h>SΧ×EÆ™šã”Eƒ–*½½ €dWE㢰QØ"qÆêÉa$©Ð^]QZlD$¡ÇûÇ™ô°v#}ă¿íd±$4…%š,_‹A¥%Z<ñ,é‡=ÆcÑ…ѵ¦“Ƭ¤Üw^Ð[Pý0Æo"ˆáTîb•uåŒH9´¿%6Äó­øÔ7u®TuTOKwï Á=j†›hº³ñÀ]VBº€^¹ABò!u°iUú.Ü’€{¢bqÏÀÑ|?ÐbÁNädØ•mŽ`㙊¡ L3}G*ØOºë\E.ÞÛ4«8]°ü’}«1÷[ýÉÕ8–üs¿ý‡¼ü“sTb!Ùr/`i”K ²\s0÷%wPD$¹Æ<$7Èšž™¡˜ˆÒUv]e“p¥6-e厃À§˜‹—¢+‹™ æRjìOÜçâd‰ñ¡²Ù–šh0‡½îÔ+ëöRŸ»P´5´õeKA–[WC9&ÒQH¯8h´ÒË-:»2UD¬I9ãsÛ­ºæL1ÞRsÎ/#VM.³¥ˆã3ü^ºX鯲ÝüÌs‡®iGÒÓ: Råq6HC©[EMÇ3ý°@Ý®ª ½õá½ÚßFäƒw¿Pªºô+뽩R¯/×o½FQnãYD´Y6ÁtFLD­Æ¹—Ae¸ÅhÖÝÍG°1ŒXӞ䟰¢L}š”.3èÖQ5 :p¦*}¤e_ðe(§F±X»8D.²<»¿F P8oŸ0×ï­‰šÏcªÎ~-¶ÓèL²Uv¸4OEDß>N0 ªW.ØìâJÚlœÙ7¶ÕRÒ›àøÊˆÓca ž,K¯ÿüÜKDæpÆþ™¯¿d­-H½¹Іöb¤3¶=©V.ÿ.åon|Ó¤&³:ôS¼ÎéSGýâê¹ÌBÑÍ»'Jæåé¹ Õ§óçÓ1¹sõÁ6iú‘çŸk«¤'ç¶ü?ózŒëkíÁiöðU Ö ^9ÎE>€Ê/²û²\ ¢}qÔïÝ¿ˆ+àìÝÆWÛÔÀÇòî}}÷LÐ\þHòõ[K¨¨ŸmÎxîNŵñÒ!£•‡ïV,”6Íô°[‹ð“sCÿ‰vf‡ ÅøI0 yÁg„°ÿ,“Ŧn¢!'ºA±¨åaNeÿ ,¤jx–ÊmLDÙRÀ./‰4‡éí‰k>Þµf,<¨×ꨑ ®¸Lÿ›ƒ`sgYotéÐ꘳ެÞe BÈû­îøÅZTÌ&€ ÿ­\ku"3JÏ­sœ¦ m÷1<‹ ÒÆ÷Eæ5iÖu"•C¡ø’­Üu¦t±^æÁUQêœÈR ¦2yª¯ÿ2þÁÚ#$S nåúM')Kyî8¼LcûæÏšB÷ö®Áª† #b|'¥´¤ð“ÄiÞ'më`•‘4p„6¨ž“z·g¾p®ú]Ëk¢¥ãWg,¬]OÝwò'X†y¨­‚͈¼ AG/Ë@5 ( °ñ5w®V½Ûr®f 8–ç§q©È„ìJõï ®$¬êÙ''0c©P&ø¬U Lþ:M<©?¿p2$ΘR'ÇfV©Ï͵ãD•r"ë“ 0*xQ$噌Am‚UÚ[úç ÑЃ¸Yä}×ñɱÓ]i–Ej£æP- ùÙžõ¸yÐöMT¤S“%%»ÒwK½råeÀŠ~|×KÙ½ƒ{øà-ï'’x¨).sê!n’íêœëgÏ\ö_·lÐÊ4±Ö×Zv{ãå’rEí¢nÏ2®'Êw#¸I·õÅcíHÙ¸OŽw³#£îc0÷Ì"ø1‚›ä7|†ó WD Sƒ¨Í¡úHùÃêyn´ZþµàòùWKÀøuã2o Ü+†û'üì°Î1&8æ·ï8i{ÔÑf>ˆ¯)×ù™í¹4ǽ)y%G½V…Ž7ËDT­†Nòª þ)úsÒƒñ!=ÑÓÅ3u‡ûÍ›…)Ä|ýÌ:–Æx¬¿;ÒÕN'éÚߌ’F å«ý»G R·<°f™7ÀþœLÌ™ÈC›žn®ïžÓö$Ö€/«„bƒÿÀ•­,¢Ai™ƒO=Z•\0õX5ŠÙ.í§‚ƒ¬?êmKUºY:„þ&„5áõ­+1a`åTéNjU˜·Múœ +£áGÍVÙS -v)•ù¡µ<‚Î[lR’¦þè-”´Ó«îYî·9¾d ÏɆÿýn>Q¿fˆÿ½ŸÝÂ[œ&sçM€í$*IôÌe˜?óTYÈ:˜MûU ñ”¥Z±Ä.êD—I‚%,o»†Ðµ'ù…Ú4L™Fªž`wÈ `ß÷&˜O@'I¢”ªo:8˜·â¤In]k'ìÑJ¬ Á§]Õµº@ŠóÔšûü{,–-8Èë´Õ“W9°!o3-¾-&Á¢ï¨¸mñû]ÞAŠ4–nÚtÉ?„Þ¾U¢…•t·¼ ³t£Û[¯±·#XŸ|ºg}áÌpå”y›˜iêwƆ&—²fªFMË:õÇ 5ƒ™|¡ÖO“Ó…ñ¦è™í.ÕPpÁÈóFâ¼)þš=Øf¥Ì,[d(߸º µð.è=v³köÞÏÑ1W;ºò=ÍN³&Ñ€±%yþ¼½{c;©–*øÝ¡ݺ®Õ“œ“m´ôœ_~zèR(KæçÈúV蔞ÌcŽ\)~¶>uFòêmµò1}£šû6(@µ“¦¼\^ÿØ“Šû½¤…ˆÊ¸?4/:ݨ³?L¢ òþ¦Q¿…^“zÚá8Œo#™´Y±„&#êžXžâ$³Àaü5[ßü[éj ßà!û¾“Ãéæ>t:8ï1§9©Þ†7ûwÓºÙ0Jî ÇËãuMjøóT†S‰O°RÂMÞW'Q=iDŽ‚«–N²„êeÏîÄÖ)ªXãpg÷»M¿ÿâ„ãôVl(ÑžS@þ”ÏüÅæ¢:=tÜ´˜ ÝL¬èÐõþ"©ž´\r¾ôÏ•B¸tI}‘Û´?dŸPW·EY$×YFâÞ©²Á2\õMˆÊïº8kú8™Ì9Í6ˆ½EzÍ~ää¨âˆÓJ)=ž¼e°<þnY³ü7–º')ì9µQ5¯È;î¶T°òøß³Ã‚§¿m ë¡ðŠ+K”T±Ç^!ŒU𠘞<ÎV;jûÀ'#öyÇÑ'¤ô‰õ°'æýêî¡Ázp=,*Déñ¶_ãÊ-ˆµÎ4cº“óâ7’!˜m$,/i÷=@««¯ŠçðáÔ {DM8üÚÌRÅEöÀé¼¼wb|ËGÿSBõ¥ðœÇù{X m°'’ÏÏ•ƒ¨Išˆ¨ƒH˜–›Ð@zázcTEéŠ9ÓBUXàhc‹]`ƒ8™<ΤÿÜQž¬Ø;s¯ý9q|ü£"6ØD×,`$rð=#ýK2›öY+°QœæÒ@`mÕÄ ÝZ’”œ ø¾\ì©a© Ÿ-m/f˜·™Nh›$ÒžæõMŒ[°êXz®ò´ ³¦‹ÛÂme·â³~óÞ›ßP½öÃÕ>ÉS.ÌãÕâ›i:‹pdÌ<› -þOh{VÚô£ÇFQ?@…h!&Ï=ªØ”)n"zb 1aí`åÓ0ã´:Éd%ȤG%cU!SŽ— {˶”Ì=1åÉäí;:,érˆ4+©¿S³Í0hú”ë!yÀO9ÑÎÓ~Zà v‚D*gSc \ÎÖú$"«»BBa%ÜFà3¤SÕ>„®zÒ¹ÚO¥vëÁðÊûh0;:xz Fà÷ÌÃiü4Ýhþ15¹f^á*–ôÅK¥Ig;£ý/M}ßhIq£¶¨yÌ æ—tBÃ;ˆû¸òã®xkŠ&àÈ›4Þ4|ÿöE½"OõœÅ³LAäÙ¯L7ø¸wª>P™£³÷Ûšö·o40 ƒŽ¡G7¢çŽGyŠÄ„ö%…B¯©á·ã µJ…_ Ÿ¼vAÖ0·Sfù­°Â0ܺži¯%M¾–¥L(@Ǽ@ewR²Ù7›©¼lõ…!  s+~›Îÿ˜ïhM¹çèú‚O××amñx N|Jº–ðøÐtŒb:IBÑŽ ´Ó$§3÷B½0`ÄCŸX› w8,ÕÐx •àpâ*Z~÷&$;gîäË9¼é°tQ0f*o÷¬ý£BCCŸa^,‚>ÛÝjœ2ò5ëÅ4H1\c¢6º·þÃñ>e«ÚЕôQP‚Qr¦o*ǰÁóRÛÅÚ ¢¦*†¶´P+’2çñòŠmóð›ÈáÐë£mg$Ê=9¸š“ù´Zö¡¯v³ö¢±X~†žºþ9°;–;éß I€ê  ð-ãZ™œ G£ÃYDÁW‚HœÈÂ^Û· ¬‘H.K(­ÑAˆÊ"ò¬¥NLæñ瞘ٶàÍ„#Ø·Àt;°nLv{š°ôˆ«ÄW‘j¥{¶=g E£ÁH!ƒY†Ü.ã?“zÅ£-ømš zm¾Ä)Ñà8ôk ¾ÊÇ’Pÿ1Å0Cù0ZEµ0uÙ{áµsì19‰<ðþ¡\,VÓÞße"ŹæÈåké‚Viq êåá ”8qi¹„Ï¢CmÞD.÷éäš×4=¶ö™íî ¹I›ía%HòC‰o'¾îãê-6eÌ¢øW[ðbê˜P4ç©þ;6VÀ‰ESQ(o‹éIZ}m0æÔYG•¹ÔÊ— ûQÀ8:ª˜Ã0ú‰ÈoÏ‘z=þ[R])WH€ªÿA²–Þâ íi#a$ý@£è/ÅÎÒñ³¢!îïh«|>̧îŸXÔœø1VríÈŒöÄtj±èió¿„s¯É g F¯(b+0Š'0ÔÒÝF¢×À‡'Xµ¢­_ŠÆ7Ko¹½‡«“ô²{t¾÷ìÕ @‰´JûBééüb½²!ÑsmûÝ/€‘Ê?/“Ÿh”Þ‰5˜õ’úÌ~3, ycõ»N5¢ù}oo2_å„›áçe¦—±Päç7`ËØÚzµZØD-bí†à8ëÈ êUB‹§©”w2j¾Uìk•FÇŽúy°R3ÐÃ\‹ìȨº¥uº±SÐ…«­ÇÝiêTÂ_“›°<¬’)ý“$B•^uÖœ>éli!«c¶™Ö.q5øA€¼–§‹÷ãúê, &÷zb8u´ šÝç°¹õ6ia‰î3l¦•°ÙN¬=çAbdr³H 2ùv-£[7»û’|ÔEu{uøì3£‘–F&ïŸ[âNØo»É0çuV£c‡Ï|šßŒèì©pCµèáÏõÍØb©ßHÈq,Ú„YÙäd“È??î¯øe¥Qöª«ˆvóˆö%0ü"öìôâ¼ “6NtÑdAÓbf0Š·!úQ½’»¬ÛBÂ;;ûgyòFð‡µ+ÏähšË·éœd/W3‰Npƒ°Á”§ÿü‘ô`†½Œ!Æ¡Íéi)­9“ÅýpЬtpí¯!´Û–©=çWÈÊà\ÔÚ;½ŽX[miåNÓ¸§]2êá® ç…ÅÈôx q™g “B{ÿ«ŠÔ3äUG(%DÛ,‚†sdúwªŽ| ç²9‡—ÐÄ/#AÕC—©‰+-â_ë Æj!€VyMpnVÈ»,м¢öÙ(„ŸÂ–„zSÆi*±ƒA×Ç@µ±á{è%Rú:fhÙt¿êÖ¯¼šÞh¿ÄðãdüŒ^‡ƒ‹hý€¢éÇe•úI`UqssÅÞšêà¬ÑÄ‹ïÌCøj-] œúrh¼.¤ÝO."¨2˜‡¾@òz¦èÅxôü†Í¼~–~¢{ÂóÚP`ëM†ºêË÷n 0Y•Ä›§œ.Δ|bÃF…¥”vì5h®LÊó³£ì~"RÒ× qk~c¼›¡¹ò¢Wa]ákä|ãr °=úœ>Æz}_íþA­CYЫÙ_ Øp ¡ Yª"nõ „d¹U ÒhZ®i"™sÏZ´2#ÃðTëKPt§ÄãIY˜0.À2ïÊ Ã5…†`vÍeDJŸ¿RgÕû `BEw€¼¨c[¿ ¤â7äŸ8³&´õ5ÕUŽÎ$ÀÏç³Ì0ƒQRû§TÏUú gÐû;_¶‰Óß]ü¼æ*Í\…_é5ª|l_õÈ£¢¨;BS~Ù~TJÉVŒTLåîI¤+pŒÎ@‰× )­9íþ¢Ž”¹UÍÆ4³{±n‚g•æ@!ŒÖ ñ9y’ ¯|KLô…?iÂõ…åj­Å'‹4äI÷b7o¦º"¡:è¨2mËcc§³R,Í“ãÈŽ'bl¦ÏL‘ÙNË×XZ7zÓoêiÿ._š&Ò§K$1Öøáöô|HÝw7Úq2JÖÏSÄ2¬EÒ®Åè Sñ‡w–óËÞÙ”ø‹ACº’®ÏìE3Ùä‰Py5ľõxÐXä›ÏþÁxÄNE UâáÄ÷‚¼c‘Bæ&_‰u׳{áχÙÔÝ=mM*;=ùs”£Ÿ¿Ó÷j™”ª¾=4‹0…¶¥L¢/1/`-ܯ!žÑ³`Á+¢à æÏ1]Cïeb^Ù¯bˆúQá^Ö=Âðàš}uwZwвFr‡œÙĈ"‡Í²qvàÈ:PåZ- =Èæ‘Õ0¢·«Á]˜…N¦_cðs˜0³’å:ÀõúðŒÅTZnûœGW…ie7³½i93F9­z؈¹l9ØåOâ}6ôÆö$2õ_¶xÇ–"3hMÀ´ÏíÖ×-uêªwë=9‡Ú$T}‘ X… «;Å&W®R.þœøÛÅ8…èÓd’PéܨÈÿΔ“&’¡ ³n“_!ímFÛ¼GšYŸy@Œ!¾-ÏÞd þô0ô‘r¿CRÌfâ÷ž^÷ØÀ‚T¹çˆ1âðÙ%ð ˜ûYÙÆl üç€À~ñZd÷£eDRÕÌûé>• 6b’ô*ÏŒíjo&g®æa$]«$éŒ}±3 2UcoŒäòcB£³ÕU7&.êñ4‰:ôà–¬H®¯<ƒÅ®ùvcK•p¨-6‡Ú¹¹Ý2lázÂS4=u&‡)rk²5ÄÐny«Ô©M˜Ž‘±œåÁ q„`l´Ç5(Mtïz[FMÿùWóná É[ý«¼ÓUý”‹·ï R 6tþ ß ])é“‚$hB/‹UâUËÔÿ&@Ù¿wqr"‡Ü¹á•/Ù·¹òç#JSy-EÃUïGÁ– ";”ó{ÞYذþ½ &ffFA+ã§Éá‘Ã[F*¶¼/Ÿµ8ÓÜ1ñù†ÀŽƒbjã.·uuLFý£Qô%HˆU…'…’ íY褛RuÊäö ¶´®ù¦ñ)AþQÚÿšèîv‰»|“\Dp'tždì) À±šP]Š5©©¤Ú_ Ú®0œW8=%ûÆD‰0OiL,kÌ–§Úª>)éšwXDÜ&š$6÷‹OLòm×¼OM½¼ãÌÕH¹ÓŒPv†+ÿ(ñKÓ Kþ=ÒüŠՕ€’ bÒ»=ÃS2ßþ„…¯6ø5õÛùÖ™ÄsbPùžq1Ú&húíÜÃðô @¯ògüên´Ì5b{ðÙÄåP`´˜£Wƒìõop)/ò”JY ÓšÂ4g=;Sù±Èþ•×OÿO=‘ÇBÌ‚Ûz A o!D9¼`<ØÙ¦½fR)ðr¤ôeÊàŽØíK?ÆïÊ6\¶/×3÷”^ ðÊ)zB¶*ß5íè=Wܻ޿že?w䯻fCAš»ör¯P*U-ðÉ¢¾=×!SA¾€@A&ùÛãpEgú`Ó÷ äYþK(5ŽzšuÙxoµ)L‚”­Z[=CxŸ0–šæ•ò<\Ž?jæ¡+õè?íC±"áÓÙhá6/»À^Y[í×´™¤’²R•géáÓz÷ìß¾¯á„ŽÞ[*hç_ˆºÅùÀ°9€¶Þ]ÂŒ?hc§@víåÅ7 ë5T¥¬L¯õÏT‰Žˆ>0³ÓœEro>¥$0êZ~Æ÷Êirî²eÛ•YàvšN­ 0Ø;_ þÉøÊvøhIû t:P) ã¼Ee:ä_oGÒŸÊBÖþÆj’´à©’âQQ´‹ ÌB˜ÖŸÚ@›£±xæöþnõóZjzcv¯Mdh4Êj|ç¯M¼éÏw ‰¾ç;ñ¯Uc2fÀ‰ÉñÌ–æ\Dw¯gX hØš÷4ÒΓž©M:É·å!syÛANó9D¤ ÎÈróÝ7îÂÍ[«¶†ÙhðݱXnržÂ N–ÝöÓ¶Q“¡m¯t¯ÓzD-ŽGsÞ\ŠÍAÖ®é{£äÅh4GvÖ–oñÕô¦9âž²ݘ֔‰Êí0ŒDAsÙl”“ aÐå_H²Åq*FWÓÐv@÷_e;Ÿ5*ð/õLeÏ®[òr>g”ãc:[.ÂC¸ÍŰE˜ˆŒ[íA‡Çù)üŒG•â#©,y²Œ†¥±ýwÌä-•Y.#%ÁR¦þ[}¤¢c;W"tÔŽµHgÖt†,fKÞÅПA­Š­ã|Ã<ÿ€1üáøðåÈ—²?ýº‘AiDûz)cX`-ÄÖÂ<{’ÚçÁ/+ζþ\¹Í®ù×P}q3M¦åDç°W¤zÈå·¹q.$ݲŸ%€fUÙ>½¯@üfm‚[4½Õ¬#øóþ³#“Ò)¶óåÓdr*¹'óÓ+yv©ÕÁª2óú ¿äâÏt½–¢ýYsÍŒõY¹†he˜sê_Ò0ø¾É¹€É€ÝμA\¯Ü¶ˆùê®2A°‘+~ŸaüQB'zNïªË–5›fc™1ÃyAÝ÷Þ r­­÷§U/Dók&ý§¿ê0»\É›ƒ>í¨¥ËÛù 7ø#P0‘¯H%]CÙu'kÖ‹SK+6ù’BRR}:¦w)Æö7Þœ ¿’(ÁÓ¯½ v[0}Ü>¤‘‡þrù’vd›Eõ£Ä  H \±`£É°9W_<1ÐKc¥o@µ¹î=lµÁC‚ùpSèKß°iSAĆv4,n¢Øüy‰îoÍþ÷%L™XMI¡ñjh$CI³Ã/9˲µ;ß{ÈY„å˜ÉÃNPÇÒS³”U/ë{= r9TKdw  ®;Ì¢-³ ßŸ­ ß£àö˜=Sœ|Û{´”¯è::Nn‘Ïî>*¢S .¼ÛÛ½ü¶åZ°•½½M'OÔ)y âAAgU /—ËŠAsñÐÚÕMÃR„6èF(šFÍ8=øôF³ÍœBkzB÷ï²b6˜aßáh>,»øÜUãæÌÀ_¬]7ÇŸÚÓ…g#gÔþõ–Kž"óPmf+zä|yÖk d:Õ{ <²«›€ß?‹DÊ|5ªÒ=Nd«ËËE,OjvÒc¹‚Úþ<¯e€Ðµ#‹ŒËR!—1²¢÷3Ñ>+¬ÙA‘–ãd:«I×àõ£ž&¦'Φ„™óë´PÄXŸ{c€YÔ ºiÌûL\ä’{½ñ.|•pVÞßóŸ8Ká AD¶9rôgU—w½&µÀæðI™èW{ÓI\%ôIÅs(‚§ƒ9½é& V°}ßiÏA.Zû¢Nï45X˜Œ¬áð Ú£°’Z¬ ÷×@W}`–ãÐA»ÔÉBà«ÝSä‰@ )9‡± >KÕäÄ›ÒùA¦ap “|SsõÂqyœ‰‰2®>¡dìÎî}¤p¥À<ÿj‹#9qÓòªXÚ7íé ø{u|QnÎ4”aº==¯g2h] {D0p=¨Zì¼}”ÀÈåT•ûŒd< 9¬V|œÔâEØ“¤åašÚõ—' ìÝ|i/t8Qšªî÷?ß;_Îbç ¾½ˆ:2GÀ‹9¥>±P~^¡ÀºâÔ³ë(RVK<¢‡Õnb·ÐH¯çTÿ‚G§w¹¶ü`ÀÊÇÆuªuEʹcU‚©*Ïû74Á[C\ŸhìÊ1"sR)¡=þh@HÉÏ‹œ¶êÀ ZWѯ”kÁÂÃ^$‡ã ~ëëö—}ú4LÎÔÖ§¡ƒ;‰D$éczã4ÕÂà U'íñ ±$6“>ôÇPCz–`Œ»ØéÞR›)Á"r¤x¿]¦K¹¼Ëm¶6j †Å¢¡M\/b}ô<Ñ;¹´Òf—ýn·Oüi?ó:B¦S‰ÛßÅp®&Ų’/¼—7IVÕº@çÈ(S9qèâ=.¿5þ®ãFF;Ü&Y–JOKøWnV¥bh4œÅ¢|3EWÊNq-˜¾Þy³\vÿÐÀ/ó¨uðŠÁ™ú|7  ¯ìñ¡þõ¡ P­¾2ä&ÕED6XÉ9º—аB¤cìN„¹Î °;¤á G¬¯»’¤9œ'1Ð p÷tĉ>¡ßòevƒ/¼¤"œ9AJ#ã/Æ&F@! NÙ¤Ò éãœs<ûG¼õYt+õ7_qçäNÄ 7!9˜Ë)ŒU"ÚÏ&ÚÅ£$Z]¢2Zöq)åéÆqròŸÃþœAµÞ¬m eEÄ7>ÖÂ/€`÷ŒE04*ŒväRö> î„IÉ5é´Ðu…²Ž³Í²ã!õ}ŒÍ¸W\eÞ˪В IÛ½ ÷þ@ ê¼ASÌ^§ÅSŸ>1J$Û¿2™É\-PŠÞ¤×/¢¯Ž‰W„•J.ÑQ5H‰À Ï\ Ð83”óÆ>\ÊQ²d¢à-ÞöÅÇz€íu :"¹mñM 0ÉÚÿ%m¾x:.úÈÄe•Cý5ÌgÔu.=»G¿ví)i­QéóÊÀ«‰;š‡£Œ´A óJ“Å$ ¶žUÅæ(üÒSê8 —ϼÕq¡h Éá3µß‰J˜;4>RS€í6ݬïBR(coÔ¥-”Úå¤ÚF [Ÿ5 ï%‹RG‚éãÀ õÛÊ~ozr¢™EŽìEòœ*ñ•ÛÉ#uñHºÚt¿­šï%{ƒ6´Âƒ… 4ÇãHL\WHªÒ”•ü³`šÍéÚ·ÀzŸSæÿŒqÚ|~:NñÐ$ m€"ä£=^`„Ôaéh_ä耫ù-}J¸…‹tˆ«QÊú²‹Dû|/¬Éž9¸€ x2°ÎÕæçÒkG Ô£¾æB‰¹+ *eøÊø¸ä™^ëà1RýeýªD–GßKmyp<¢ê›«~d4]¨´XK ù&âV@⯞#ŽËû,PNñm+þÅò(@±¿jMŠˆÃ1x øQÖ•Ä+E21ðM•» |…Ðá\€¾ØçføñÈàVÀÂÞZ%`/>à²tÏó;V¼·#,WE|kÃ˰D zâŒÆŒ|IºÈ}¸O²ÉIÿ×Sì-'p©è=û|!üéÊCª©§uÔÉÈöGr2­‹ûÚ¯/_­^òQ\ ©6,­"n‚†› kwµ™ØÆFBÓ%¨&ä¡Ót[Œ­c(ŽWgÖgÆÄd铸åo&ߦŠløÛB‰X¬ ë @±€UÑYE²àØ-4[:Ž}ŒËA*%ž—°ëþÌÁBÒ˜öî2,!*8® ~RÅ9QN›õHO©¥§¼#asPßÇ_DªÌŠïï_ô*0ŠÔíò÷€g>È­ÏbéÓÜo:¡ž„Æì‚Ñû/. #ˆ:©®‘L¢äeÒTp{û†r‰và&•9IŠkxã± ,"éAÍ€B³v+OÊYZtqX·Ê5&M‰¿][ì!_Ö˜¶($fM¡uŠ|{ÕtœÛë¨û>TÛ.µ)µqQ#ëù Ãw+EŽáK M{&>N²\™’ž0…d[€¢2}ü¢½àV”¡ÇÓË?â”L:Ðæf­€4¢ÖÇ<¸ OÈL …=jé†&¯ÛVƒ³©ŠaÈr€Xð8=XH* ÉŒ”-˜†¾«¾4T9%§–ÕŒâÌÔ(^Q2àž‚ÊÁ‰Ž—CX,—pÙFôK—ŽPË‹ðÆ)̳üaE¿µÌèíŸmÏ.¥Ãð~“‘)¦€.èì´Õ?£cœ|ÖŠËÕ¶àZÅ€S»d*îÑ©-»exó)ls?ÇHš ‡ß”C¦Ÿ‚±Á9¥hUhí…'CP–06§ úËcˆC£¢Šš¶ê¨€A>®áyypýNrήpËëĶދêßpßÐê]Ó,æ:IzÚÞKýœ,ñÖs¨×+¾iD‘·7'´ž+ âÃqWBز.r¤}1eGAða¼ˆ Eƒ'd²ø^¼ áT{”s“²—½'t2ŠÚkDR)³_@ÎE›W,—éoùË^©ÕKô–œ~¨ýÅÙae…l™¢¦€ü‰¸a ò·J´¢-^ûø%äâ³\XÅ×3϶š\Þ2?¹ ™ ([»* wVÇÖÆ@g(¡ÊÒUÓ.ÂmâPÁ8²ÉMò–Ñÿå;’e´äC’F:¸ãaJúòNü¼b¸Ýð–d²•ù`‰ÛåÚ"Ò6=êÆ'¯Ð¸ásÅÚ¶J=ºk §Û0­åõS+.úYb¯·|}m\®&bìCi}Ö­Râã)˜•[Û Óýìõýil›—2±ö®v*È~bÖ™iÓ^\°,\,ÃTïNFsy¤Ñn€|ød‹cã´ÛxL#¢™œ]Š/ñ‹‘ ˜„Ä{¯9S­ðN¤L%F6&dÑñ’÷£°Àlä6Ë>›¹ã‹Ÿ*N !Íe%ñýñDcÃ,Ç¿º§X’Æ…ØÖbtŠfr[°¤IÓ0a0÷÷K”w/õ,׫êËÁ¢•½»}Ú§£«¤hú9°“à•PÃr……îïwZn0>i_"®@lV¾=4fP8…aIÍa;¾—ô4ó : ÐäFþ+™ 8î6Æ[þ ¨6½&“e5è„Ñ´}àÁ<§cÍñr¸6FŽU4Èy BÓ«£k÷ÆMxÚ³ÔfwÞå¯ÄæNE0—‰¼ëÚ„Ô®ê% çåûN‰R¡„®É:­)*x4á}é`8)ï7anѼ_•õ.#C¸aEÃ.ý ¡ÖüæŒÛøù“)—ðù4¨"ãy%®ÆÌCòlmý!ê×{=/¡ÈÏ7I@ö ê|胆šDxþÈ›9bLþvüG(˜óD;dþY.®•zMÙqegœÑvºÆ®{8éø`f“²``Æé<®Ié±§•óŸ=„žþ*¯k§^‹òo(Îm!¨9X?ŸÍõÌ3`ÒØLåûºF7|%¦"LÛ¯ƒHyCpQ~9mÛÓ[QáÅJ7§[¹Þ¨`~Œì$Šmõ î¨¸e¤æÎŒÁ­Q¬ÝÎmÓ&Vn˜ü^‘;›£ k,òí-Ò0 «ÄýbÔ1§R}>ô­,•1Å“ƒµØòõ2~Àæ½D^ö”d¼…Óí!جnsMèɳŽõuÂkf™Œ VÛ8/³GÊgÓÕ«ËpbH‡cý°y9Äln=ûQW(/ç's&_½X5."|CÝBNV§ ä^ÝÓ¿_T-¼&LaŒˆ×R¦D? ùÿ[\>C¬aq)esðŠÝ‰~íGønU[Hªl„Þ 4º3ÿ/GÜE˜:Jm€h¦Ã^.Ò£gp}îé-øLõ–|qlMâ ÙIÄnCäù{¿.@#PØLN Ïâ;’ ¦YäGõ:¥´[U@GQ=ãFSió/sÝÜ¡Th¶½ºcœ:`@E (·ZÕ~`bqìhìßU¿(·F¨ú¬¬P´ÎŒÙÚâÖÇáòFÌßIÞBŠXø×£3…`QVXv®/Xä«áDg¯ñCU„^0,ÌeÃÞ_®3ÑÎÇ’Tòá‹Áª=‚Eêtòá'ׯûzÆó|åsm‡nƒju$ <úþÊÁeªKV_tÁp7_3hQ‡‘—Õì „À¾q€·ËðšAâ9”ëOŸæ$¿jpïÀûòŒØý:®QôØGÎTöùÜÏ^Ñþ_®"£åwVˆ,‘å3®¨;hiû>˜ |–¢¤sœN;”Cù3«sY‰ÙÀ\øì¢²†t ³¬“ ŒÉì/ÃR™ÃD×1x$’ïP¨3OæMUhG¼Œ8¾%§V9d–§Ô,ÑJ IˆÚ#ì FÄ[xã²4ºÃ7Ž4ó Fœ¦*¸0˜•ª?l›ñoíЙ šæ¤„”О(s'iVßkŒz¥Å*ãkµu$öØàÄbÓß½DåÓ6³QÂh[¬ eêÒ®«×ñýS“ãìJ+¿…Yæ 0 ¢ÞöFÞìM]>ª¨<Õ™Šœ‹= hù³”üÞF¼¿Ùê¡«Y ~FïUeQ÷>Ò‡2ËÝ›.v0 lÉpŽìïj{d‡r½ä©…`p¹Ru).$kÃØŸŒeÏ­•¢IUîÎ6o47l7œ:j›L=0Š.,Ô]ß.¶ð¬"¤B[œ|wÛ60–…kähnÇÏb&£v!T÷àyTueÆÎS_0“ûÖŽG¶ E®µIÂãACc²9`r‡%ŒÔO /õ‘šÈ6“@­A™M‡fˆZÛ`_ÿOö+Ú²=}7¤.q2®¢檑*ÃlÑ_ËÉ\waW²dI™\ 7ò _‡ûÑ'^ðQÔeÈ×G±‘úaUŽÃY€¿ÔIŠp±œ™ôÎoùÙ%gS¡1Ñ0ð?ˆÖÝ}.®ÜU—oÝ_HJB¢)íIÙå¼M¸QgN…·XPïjÞÔócµ²öœÓV¼(SG{£R«è·lüÜÐÌÙÉÖÛ’ò2nkõK…¸¯m¶v¤wÛûÞÆ¦½nFt¯FÕÒ„áÑÁ 6W $]©ÇKÀ§4$G¹Ÿˆ#Š+EѦT×wçØ±ë¯°ì›úb•pùbAï C÷FÞ›'}3$”6~q”­®øØÃÅø^ñgSsø8Ñifõ™ÌCíŒ3:Ç0› ìû4õ ]û¯ýeü{“q@•ߢG°¿X§íËZðnàÍ—¼·Ä§#È×úÒ‹ð´#D£ìŒ8¢þÛe•.ZOÈxç¤ØÒ·,LæŒ"QžÝÓ »¯õ“ÓÃRD„×e`§è3s÷Œe¥…¥ˆ’>œÈKxêËf Kí`Îz†ÏÚJ¯–0+ÎÜ÷¬MÊ=xÕªÑ_«ŸÊ^_IP¢7E ð°Á… uWíÃþè%±–r^â·Ùæ X$¡ûswá£è)„ ÅóRßû“@#ó'K¢°“l?þ¬­ºpc†¯´.¡¼ê÷o@ÓŒHð+9ôä³ÙB7$? ßš‡ˆ}\ö€.Û5ž:“7ïÏÊÁãF~âWb¤ç}ì1¦Âõ}w3*–ªQ`tê¾'¹ymXeæ†\‰G•ÉŸQÚÔ+d¡‹ø»ÂÇ^Û­Q?‰¢wbº¢wÞ¯|QËfŸ xæÈÏã²nªih–¤Ãî%¥Ó;Çô˜vïX]e™O×ò›Ó#†ühâÉ—Œ$ ?• T—9¦±rB”Ýå­‘áwšYÁ†j¢¡Ë«;¼[[ëRù–VòQ‹¨¾w{Áˆå»zž½AV‡Id·«sc±<É!Å”µ§ºcÔ #Å1èmnÂh[Ž¿¥•)6PKVùyQ ©{GÞ•cï‹ìéµFÕªÉ>°°ZŸ¤ƒ¬#Ì3Q QŽÃìÂ]û’£Ôá 3Ætüy°ãµ/|Ž’˜–PÞÒ}+uÙDÐí°9åpjò¾öÏ5|º¦¸”Ú®¤‘íªœb¢¼ EE³ÜП˜³ÞÕà¯.^@÷pÏ R6èþâ@\{µ rcú¸l˜ª±ØÜ²_ØLvÑÒe3÷’¯œß´H$x/÷“e©– ²uI…ÑIšø»YcNúÜ«¾{0ÎO˜rôûì&»ÑÉ%ñF 7G¸¼g@Ý¡û[åŸ/š@Ö{qÊ|×›bÅjUàåâ|·‚x¹©Þ®{W»¶M‚ÅsNt³½ÑõýæK“ÄžëMNÖ‘¡úJüSõWnÚëT¼ä¯õN ˆe/G%¶Œãx&8vò|ÉńάâÂvMª‹¡á‰>M ‘Ï}Á·±yÆë© ã9§˜Z9#"®`âÇ‚jÀw&F¨»v¸Ã3¶Í2'GLf=Ežpx‡A^c­=íÔ’©y›#µFÏ`Oã‹dÔDP‰®˜¤ÈJ{YrH˜âuëÙìd¡Ø>¤°¯,j¡*2F¹µên?ú|ÔJÜd·¾%½KÎõMŽœô?#üLò©YFé²µ8yÿõ±óâãÌá]×Ó°Ät_×M—÷ë¡s=-"2£d‹®± ÍPΨ€¿4Ñ $û[CÖsE0‚z‘ GõyÅZZÔ¨OMŽEùÿá zyßë§F6û N!| oÂà(ÝÙ¤øyú RˆÜNMg(MÐööQì_Ý µ¯³<ä †Þöç:½AÆ)U±ß<º¹cÔ»i¯‹N…{ªj}¤Ì+[=CBïÅtçó.֙ܵI§~dS^òP+Âú0Š€,¦ƒ±# Pˆ¶%Š'çl˜ÜìŸì´§¼ßLjټ³è†¬î±ÎòÝÀÞJ‘j¤ ÏY+¿÷LÎ^t¬2Ùbe Ðù |ã†&ð©X±K³×‚8X%Vp§”òÇD^äòÛ ˜\a¶i™ÄÓ§°¼ÒJ)p/ ¢²ñýrT.ãJ9UÄytÃó¥RjìÑ %N[{¶7cÂæÝÁ°Ôæ\·ý‘UŒç~ÑŠqŸt„2EA¥8Œlh&=3H(ŒwIÔÊ{ñÐB"dQU÷i)þ‚¥~GᲬò9q­yókx”ú©p.[äéT‰ØashFNð«lV%ÏÒxÕ3 ¦Å³.\ò²4-‹u[$A¦H£E6~ÎiîÞ% ÅŒ›1}Ž\J¡T-.ß“#zr½ÃÞ_a wFàæØí¶¾ÒLêTò¯Íi°Õp”í,CV›UµÓì´ðÒ¦_æ   –RiA%kÈŸosÖÛç8(\Ä®ÃtPÉÉò{–€þ IÂZQšó( !Ëç‡,E>¨\{éUI‡¤Ô»Ü+öÁk–^ªwLçr#eV¾î¾½Òp‹%ð?̽úNI^ }cRkŠ'.ïáê;æð¾$‚ìÙ5ÛžtÂéN‹YÔ}Tç.Eö“ŠþõÐÐ'ZÇAĽ¾Pý9 $ªÒ <½iWìeƒK§„ë²R‰Ø«&®åÞd wÍòwíÜDå›êÛÚU.üí=5æOÔÊBžFb@YùùM†ÇþÎñ¤¨9{¾¾q:ûŸø"qW}p% Þ’ýΛ¿Ç9ÀµyÁÅ—ËÃ÷ÛŽZ5[Û¥Ý`ävÄ»òkmp°I”þ2äà2GÚC‰9¯yw8ŠcãÀÆ2yÅ3Vœ*[âaD^üY¾÷NQçð¯r™ý„~£ØÜ*öö¬ê 'kÙÄø‰Ž‡ÖŒ ŒœóÕG‰Ø×¥E¤­tÅj 8qnŽ +Y5ƒè'›†­¨3+b.³[flµ7¯œÉQRÔoa”¢wßÿ•{#þ§%ÝÄS¡ÀNši 5nRÕj߸ßÌ`œ=bÞDtŽÑ¢àèä`§q¹ƒrDŸÜ c…³À*¤T“¨CcïpxãotÐ0(w&S…›gÄGAÐsQŒÛhæ3¯/'o x‹—É=µvg?)óÕ¨Cˆ u˜_O°Ïq/Ž‚Ò:¾Ú:7O:ÁZšÑŸ9Ïh§ïœ*ÌÄçÛü¬òÐÃtN“xšüO‹‰#žb÷<Œfñùˆ[Duë\0JÉÎÑÍ^8³{$ˆ9ÜúÕ9Ë¡«©=ªª’¾· 󒺦«èwÄUöfCÁ|໵D}ÀÜ`sˆ®1—˜Y¬¼%1$ó2aȺÊ×+çÇÆµº°/x˦ j^¹/X;'Wi p±%=EÁMþàУöíÌu¯iNvV’±‚ß¼:=ƒ<ú!˜PiNâÍÌl `6±Rnz™‰)aaÓàóüG¥ß°Éü8Ô6ÒZ6x£«dƒÚ¦90wˉ÷ùk“èÅ-G¾d’4ðçÍ=BQ X< £¬!|­vî.ëNÆm1JšJÿHGJzuÏ¢;JÄœvIBS U)Jáÿÿñax¯›ˆ—'r®mè½—6u(NEÅJhT$.(˜Ý(hzå<ËHC1¢Ì-Ÿ¥Q@(»UݹL,žÍ}5 Õì¹…‡‡GC$¾0ZØfC综ï0›ä·TÇì ¯ðF‡B~ ]ÖžòR oœµy/îZ‰@‹ÑáLé:mé;DžJʉã][ô¨6³ ìì ƒ¦*Q—ët+ptqH{3ó<£Ÿ uÈÑ%wYƒt•Ù†"Úu÷±ÐP“0i¼µÏ› A°‰g:\ Ò’Þœœh'VL¢„Ð>t¡<8#[#AïÙÇdɉÌ/dM3ÃOR€ÈúÍ9å £ï"šû.»À*bæ*Å£o¨Ùœª½¥lÒ¼J]Ý&,.±†¬K»]ÁEs„.m¨Pñû HÔºÙ?{~‡sÌ3Í<étAW#Z‘=¡µ#/ …¡' :Z{ÆíõŸW>~æiqÅ8ùÖ„ÙÏ‘°Ú?{( p+ôÙqã‡wV[ÕáÂáëG”¬Ø#ÊŠÈ$¬¹Û.w2²›¶ñžUý·8©H!ÂMƒ‚$ç EД_ÀäüW3ñO´œÞ|íåÅS–e¬»#%LÃ%ôIx+Û΃٫¼57ιôŠS(Ò ióUEE,¢ÄJÿ›m½y…ÖNó`Èð‘ úˆ(ï ÷K¨u»º#Ô‰ËrÇ*dÖ¶½ˆíí‹Û ø‡Ð°¬ðɦ'i½+bu =ÌÊIpOø[OèÜÜÄç%}j­;<ãà€â‚FkdŽšF‰ÁÞ….kП3è´r‹çt´¸sœò¡´ƒ¼™´Æ´9½ÒžÎuç˜kü‰ÅÕ.Há€- êß±^0N½Ä@[¨º…žƒ'¦Ž¢¯'±Â"ž­tiÇ!ÆÑ(ùÈx„áöÿ&Ù¥ÑÓÆ)NÖr°À=ø’»ZöjBKŠ9±°¡o6yïzO®–#ÙôzËÿä q¨Q³ ‚–‹gîªOˆ&dµb®Ý—ØÜÚn‹ªñšü\kгÂuø‹´QHé?0‹Ñ†Vt¸sìvØ4”k ©E\h¼ Ù¥Ü6:Å_yK•b,ù³·LèÆÝÆŠ&‹–?í˜ÑŒëêý\4ãh° £ÈgU1®ˆ„ ªtÖ5_:÷ê,Îìq›ÿv)¢/'FuÔû$âå­(®‚¬k _zt²dv>²7²s{~b²ýr"Í”lª–n¾6R ŸÎ¬C Tª±Ã&hU/1Ù±ƒåÖ«¢_¶ Ë 479Ø8§è¯‹xîê5:°‚/N·Rœ‘/Üx_Î ¥ R^ÍlºC}Òª:>kÍc½ÝrR~–ùL»UWµÇË›^z@re™† ¬·y1›lú<ïÀM$Ýb ,]œ]¡6¼ƨ©¨öá¨ö„s×›®’…†Íl‡3—b†ÔÚþ˜x¢—Ìî&ª½&ë-ÛIÛ5 ϱæ~YêWT=·|(Ö—7V4ñ­}„ÐõÓp\Sò½e%U,Jð?J¦ëµ$ñÓ]Ó³ –˜Yùñnhº~ùNþwÁÛ:kíW¾,˜kkWY#{›»:Y÷Ñ~ÀLkáVº³^¤Î¯Œúoˆý.å½uÌI¡|«pêómé<<3ìèð²5ù›oõ¸þHóàx;Þ#¦«nñiÔ$ðaAhCžü.é\=FÌÑ»È@" —¡þ…+”[Ò^¬99¢¦j1ôì?†îKÀE ªE4p†ãE¤Í£lÈ2y?,ðh ÇuË_ŠZ¥ßÑõFÓŽ‹¼sÖoU¥§ú´#Nø0¦ƒúA;Ù£€-ÖÅe»í¿‡hð]Ÿ`©#dÄ#¡dÍuo²k«{Ç÷¿{tCEm¹9ꉺ¾Õoص9+ÔdI(ñ4tàO®fŽE‰– ‚9¬–{í…S£R+–/vÕä&û"9ñä"±Á¿ÉÚSx¬v™½qTDDµTøNÀ ïHçål¡÷,ŸlÔ)L±4Ç& ¥¦¾áÿi'>–©£uÇQïˆì»á#ª z±={¤ù^TtaQr;¶ðªyµ&:&ŸZø¤YïÕèKàaÏälç1ÁC‚¨|/±ÿ‚Ç3ãO~Ã2,38R‚iutLÖ5P‡ÙSÒƒUŸâä™{Î)"uEs·Te…¦ÇP?Ù°CÙC½ 2öç¨wÔ‘Ô"T™gÉvÓÐÈK©PèºùC^»š¬ã ¶~ nYt&å|«Þ³`òó5â«W8py†FaI“„Åj¢¤£Tzbã -N€ÿ®ØB—–•ó*„,úÞÎþdi– Vim>øÓLëÕëVati¼5 ã±~×OE7ænÞ]èØ@o4× õÃ$ÞµeFW¸åYû”)Ç$}tnÙ-èlØ<‚‘þ_€q%®Íü+ aI?Rž( ±U=z×,6ß…+pW<çÔd÷Ñ ! ~AÂ]¬ú‹O J†³.ÁѪsÑw õq²üçŽIìL'9ä#)øxÎ[×þùX,ãÙ£äÕߤÖme(Òð*-<‰Þ’Ùø´ÎÀÞ힎RbËê(fY,° Ce:å5h—ÐÿÄ'×Ör\ˆ{”æ`¡«Ë¹ƒe÷Œk‘…™ã>çÿomjLályó¹î{t(®´á¬Îj÷Ì—h÷&FèôV(ow0—Ó¦]5 a'jI½ìK[™^Ž!‚Ue&ËVé´§)/Ô‘ O]Ý!WpGª‚«K~Œhæº9Òd«ëÈÔ Î%CöC¶¸3¤â|¬ÐëE‹q—Zßz‹5fš¨6„JÌðú_èxñŸÒáÆXô©YE˜Ù‚<ÿ¯“V@.3ZÓ½ × )ÒP³¤²ÔÕûúë³r7Ì|(AG¤¯‚û úþÑo£à2g—e B€æ¶JI®Ec°³óµú¤þÉ>„±½aÅ&G\2Öˆ7“l¼Dœ\<\“GáÆõ­²H„ž‘r¨ÀîåÉ}wîƒN‘d0öiwÙ±­ôÒ뜮„Ÿb9&êöŠw¸ßßB"LË«ê<Ùútà ücôL$÷dG¢3²H’cRµ@[‘½n”g[Úþ r7휴µ-åJkpÄ— ÷ ˜¶è¤Ä‚j{ Uj±sÄ-Ó†·Ldž—'B#RòµT‹žbÌTPœÿÊ«xQ¤8“¯ÝÏ-Â| YL“zÕ[íÜˆŽŽ™Â9HSÉ*”²±š.PÙ,ÿZѡҗ´gc>ˆXÃ@\’§(é}½^œ‘ʼF%™e!MŸÚ?Ä‘T¾…ÝGIöØ;‚ìc[aùÈ9ôÔõ~‹ 9#k¤&CO’ýu`&؉ta ¼Eû”ì<Óü‹|³˜Iú;À«7Íž½Sk¦@aÊ^"ûí9©¼Q¹&0 Û¿…Å-±u)rCA¬nkÿê4yçà …<¡¿d€6ÜJ¯Ð—Zgy÷¨ùÿ†?q,ãã°ë±ë,†=7^)Œ¸9ߤզꅭ…æ*Âöwì×ËÆo3gh3 ’¢}0ØàWµ£v zàKDºz"R=ØY9JwòÕ{I„MÅ&ËÒ¼ºá’ÃbmPåë‡Iü„…'¦Øåå€ÍøZ,»Ìõ özFЈu”jL V¥0ÒqôìL‡ÝyÆÏÓâ‡É”qôMãÎ«ë´Ø–Êj¹‚ñ-ïšA¯§ý"ÈùS}à0ÑÆ æ6Íb\¤L,YëÞíýu€åòZ/™ÊµkvY¨ZãÈß°üýÁ=õ§¼in~Y[¨/œ.:‰Œ%ÃMÙ1ñ±Oõw‚.úf@/ï'l£ùï“ü¶Iž¸±’±ÑmýŠmõpváê®Ñ(GpÝn¡Dî¦sóê èx²*çq€H¯LË0e4k™«†_šàõ"p.¨f‹=æL-Ú€7,8z5U}ΰðqÃ4\¡5ºü×)œ£¸³<ð«‰Ð9~5wïvßj ÆeB].iH†=Z½ª×ýW(ˆ¢Ãœ§®0É ›]/éífLù/t?e ½ªáÊSà(õÝ2ü9UU¨…`L^Ϋ[n"£SÓ²ìc6n!щ¯ÿÐï„ V7 Lnšî.þŒH†æêomï=uiJ„y[½T~'ؘ ß©=¤_ ! ”ÜçÖ5šX|îÕßU¿`KºECJ’ý®£CýÂjd©8Dé2RµNª–ñ‰fEy!O ÿ¦‘T‘ûNJúkìF‘á©JýÓaô:Ã.˜ÌÞ¿Eo¿Ãš¶ð1æ’Ü[-E1UïšèÜâÏe—Üq“V-⺺ÐK™08´2×êxÀ€^)|˜Ö:¾Ã+úÂ%ö&2ë0½ã«¬^N˜ÀZ7nU=ƒ8$eKYŠç´þëkê8¶ ]2°-¸•’£”ÿ‘Ÿ uêÝ Ëá…Ä…Ú|³EùîµämƸYd%ßO,¦„öC'vU?¡>²$«Ä|·Ÿ« ~Wº4¢jÇ:w hžR”-¾›ð+GßÙ‹b2ûG¿<8zèrÿ%1‘yyåhÛC`à sÑ ¤J|ÒÚÿâÑ•íØ —^AxѪR“P… ‹5(_=UÍs%*÷0}ŽïzM-.Mú G_¢°ìêtÒ³’Ü·G僻£œc9ƒ¼›á©œš“í.b‰$}¥]¸À÷^SDnÚ²F¯/è4Ê#€ÑxÜÑ[Ñn(”,<ŽUgòÒdâ¯|ˆ$Ó(r/Èåøó¬Gàú%ÀˆÖÂ*ÛøÆå]ì™¶ïOqûEÁÍHìÆˆÿâJ€=¿E€]‚H:DÄ¿ü‘Dý I‚¦oiÕOÄ?£k&tå¢9+1²Q¡ˆÒžu8 ³â4FÒ¤H¨²’?ÂÁFóð'Q°Út¿­1‚³Ðüì &ü:¯È²‹ÐüÓ§"ØÚ"”êÊ{¿(íØ»ù:rþ‡'~ ¬ÐLU½¨{§%=£€–ÂIùœ—á#¿…@ ¨ón(š9XµWì;ÁLîŽÞ4qmպĆ]~kRÏ@”@s‡ëNFºÆ¬ÕÍÇŽ¿4O¨·M@ˆ*<ž6C®‡ÃKð…ûõf™4!,u?9 fòfJ¬ÉT Ÿl><ÈÐZqÅUŸ¥kc¸Äà4>¦¢l« á£úL­µ úèõ÷Mã ÉŽ—3™©Åâ4±C²JF ÂÍ<\Š¡=íà8c]|1–©ÄPXã›´ó<¥ñqüßËóï+•cÚÒŽ7;ƒ‚;X Ýxª ;Æ®¼},ôù"ó°Qçô:'q„gâ݊ăY‰7'÷÷ã–"ŠË¤o0E­«Þ`üS\î<×"G›)éNÒ°ZM2q¢ëûÈ+Ü}ÿÍ »%á`æ]}Íïˆ×LÖO¬’™CðÏ:'‚;ñ‰0û•ˆ2cØd£ú©vv Þ°[1ËÉ8ç^æ’õ]Á~Ò¼Ý\jðßþĶ´‹°ï¾Lï%‚ƒ·¾0ÇîwêÉV„ŠëRü¾"”ÿ‘9yj×o!Ÿ+=¯¤»à¾ÁLR,-cU¡…ëó˜UŠ =l¬Ã‡¦â2þ})V+; HÅãžúQiïÒ2ÉUÞ)¹#ºÅç?á%6þO0Ü’w £G…ÎÔàsZƒ Cjiê|ÇÓ:I-»Ô{à«ÇUæôdâ8”b$ÚÒêtw *…ÉŒãS§ù•`=5¨|åë½ý.h´ìµ$Ò·ˆ°iŽÔ}¿¢½çœ`t·T€iŸ~æ+Ò"úƒÁSÝj\¼ýL3;€PÜuÆøÅSÌýðØ%Û_z‡íõ…=™?†–ÌÙ*kj¤»›'$ª Z(’>¥÷8ÈØý†ê‚d ±}$Iõó_(ùç@rZ:aÓ Œbðñ–âVú;Ó_C¼.¡ò€k³¨WÒ'õ$“4Û€±ÞBË=VÝÐ0¼Ç@üGµû$i¤šú TM*žlC¿ [XØš´ÃIa Ôí¿¢W?®¾¾µË¤š¶»h 7Š‚Û.)ѽ߫wU]ïà¶ReEv†‡‰8 Á'Á¢ò'“O¥/&P\¬PqŸ·‹¹ò­ÇÑ$Æçq,bäR´š®û/…êÙZÙ—´>̽î%ÐÃGà;$ }O-#gå*Ý.ãµ&C Þ>b<±”ö±™Ž^§›lmŽ ºKLËþfGõ–÷X¨;èæ³í>Ï€Ñ×´ˆ-6ÓÁþfmü¼Qù¬áÈqñ½3Mk4YiÐt/±×ÆÉÌ}†~¿ãpìVtð×BY4EÐ djÒc•ù¥ðØ]PpO.¾¬^+}ÈÉ£žvŽUvç–´Ûñ/O3Øm¶†Êýë’ |ˆø ;ªY¤hŸ´”nœ*›bè¨Ë)öÔZ¥¨spN¶¬`` g“^ƒ§ÏP?¦ -9J&µ‹åtÜž ã£ÝPû`m™q–)…N_è]©¹é]¤¶ˆ.ت¦yrôÚì{åqÀ4ñ¤Ž„W€õL%½(MHsúªlë@Ž2& YìQ'ã©;—blp±j4•òη™º’ãº\?ïš©2_ª‡Ï†øûÆò¯ÇôÿðŒç?Ý<Šó6义Ӡ,`Êéñ͘•\ÒŠÃÉÝ´–ú뀣ª(í¤îZ†¯¸\¶K3GY ?ËWÿ,S[ 9wœ-¤ÛÕA+ÐÆ¯lµõ-‹PVlú@Ûý!éGXd«n£ƒútÑ&cæÞ Ìbu]ÿcBsjs°Yi¸ íø?8îGÌѾæº_…ô€gÉ ½’Æú¬ùk ‚=è7×µ*!o´ÐDéeð&íT@çZá¸Du"…XJu?²¢Àl¥O ùÈ.ÃŒÐÏ!'-¥²¿æÛÈ$Æ(ÐÞß/ö4. 柗á[³ºp¨‡µ]Öi¶“B¯Ù¹k;ÓªV齺…„LA-ŠÍkrgûLï^óèÊmé¶Ê0¬ô' £g̵XNﴥ͸`0Ðǯª**âùù|½Ë?@ïtœ¹-\\ëðc/ÅreCz˳˜šëƒúç(ß²ò…;*,ÿX 9λo¶eæþÔc‘ÛŸ[ÕÄ®o2²Ü¾ü‚áîWQ«I]¹½ømhw9öËçã‰ï„k\kó×<~˜€¾ZðkÖˆ$gaÍ‹PÔ3½$LâØpàyæ!¿ASmsq͆–‰¤H™³2ºDÅ G~+k‡\$xðŠS{ÛbŽkz¤¬¸xR*Oæ#Ø×¹ïo¯ïvÊôÔúسTØíBÊ€å§è5·©3X”¥mÖ]Qþ§•,Ok·$PVÜ×?Ésš·ÎpÇ 2¶­AÕÿVkÌ’ÒÓQ³³ŸóÂ~H´ÍÕò‰ æeÆK<ï³­œY^”öÆn·#¤J®kÂÔN;¦H/Ž®r¶•m /T–'˜|'f8! '%]íËUÌÒ OÊò|8¦H#„A;Þ(Í3‘KiüTõ“ê#Q†&ë@B`jë[è(}W«û:LŸF#;1DìK9(×LŠ˜}§ÒÆY*§fËÚ8¾±¸š¢}ÑvÉ1EàxKƒ,Á5.` P´T€g¾±L³ª4 í²«ÏÀmšBå×®ÐTîè~ÒÌpƒzVÀO¬·ÛYí1Š|±b†}—š ¬.‰F«Ë 0s…B(Ÿ›´Ò£³×àÉ‘·‚žˆ÷7¼…sïüR‡Z2> úË¡k¤þ\}Kkœc?Râì8ƒ0I8<i8Ïé¼þ3€*MP[™ ø†©L… ÃFC7ÛÈË}E£Ý] ^~® (ÉÜÕº¨ßX{‹ x§S¡#6ÞáÞ^ˆË^¦ô÷Ê«–U¥¶gDwH7xdQKé΀&od •_œÃŒ03ÜDåú@õiš¼+DØ™UÈé8q”²ÃﯵgÚ¹S”ÚÇÜV5fºõ0»5hÓ='´–¾yt±¾zÿ³PêêŸÄˆV™ä»vg•®$ÔÆYw.¿¼€± ÖbXLñkÏÅM3Y–Gjç3Ã=Ûöe§dásà²äuõ›Ëš>tÜiXzÃÀ›cÐw“ßez`ÜO›5pü¸ã¡óÙ:¢·ã´¥áå°ƒÙ¹6MzÅ0 ÝÅ';/†(«ö4cÒ_bßÀÞ8‰?»,ßã6ëºvú7l¼W<<µ²bj=×Md$_ÐÒ–5ñ-—W@ï¿.ËD× ö^¨ŸæÓ_E>˜±ºq,—“G4°'^=fXVRn‡pùfýuîn©ÓõvZ£t êP+•oPRËÜj|$mGÓ{B‹=ñêi›À`ýþ©¿z.Ó¡ß,+z=F»#ÞÚ7U3Ì,ŸÙJëh,-Dc݇þ…“ñ}O1úf«“¤Ò Që}D@xëíDÒ°C¡.¶j˜æg˜-ÒŽmDñÌÎ…Ô‰ì$ª0!‹»ì1r¼&`y?¯R™=ü•Qca£[rzŽê£$Àmð¨]tØtíïè|Úë|…{  ½ŠÕ$\\ (ŒZw@©næ—:aç䌥ó`.X oµpQþ`úЇ¢ñ#òðÁ±uëwb¹ô^$3›ÁA&u®niç®7aOoGÇiîm ¶É°ÐbŠQúO9Ç:À¬û^éê¸:÷ §Š'.ÍìWNæsÝ¥X»éÅÃFO¼xšÖˆ5Ìëg„QH‰ Æ{ Q¤’ ¸—  U§(ŠE_ñï‘&jh«ZÇ£ùü«/ßBᄼÂN@õ~úÍ8Í(tÝòÚ‡HÙ’,¿¶Þýâ~JsëðÍ|Q†sµØ]uÇÖ²ÿOEY–@Øš„é&qΨ¢A,õ®¿“p.J.õ_zÖ¢ÿ¥þ7?Ñ÷Q¹…r5ƒÂò80ðG2–ÅÓwÊt×> aVuÊF4žÓM{ÅH¿ (0F:[ò\hñyË:mó¬:‡ Ú#‚WŒ©9‘ÒD%ô  Óš5ʳ#u´¦Uɵ¶½ç®Ó=u¿ù— ?÷âÑÄÅšXéSމCñ½LaŽ˜„¬‚jùþak´Ÿ)i€µ»‹@¯MeMkïoy%üQc7üëN!®Ê£"{Jè…:ãþïZ<šd4ޥЎ]±Å}^Զ׈Ùõ6·¨s–T„"ÎóÚíw,kÄfU0‚@`„ˆ%Ç/ïR÷‰Xy°À…·oñÎýÀÚ„èÏÝX‡kçk“æAàpáx‰2w¼¼°Œ=Be¢,×¾>œ1T0W×°æGÄ_ª¦4!ÙŽ 8œuH¬ÿcÔ5w[>*y3Íu'¶Ý ÝÊæOÆéuߘèऱ½ú·êUz•]C£ÈÇG[ò3„Öa£v°¡ÓÍ”°4GÁö‘†ÎGlÊXáÉ¢EB2å\°…=|úÁúÒa‰´ ¯«ZT]ª›Çdüj¨³]š?›’¼Ìe  –íBG3uQ’²3¸FÉm0£·$ˆn¡j6F¾8i]i¹Aú?Dv´Îßùg›.•)¯¹ûÈFd•üº{³  :å êEÙäËȬ¼•›­u ØÌ@sþÎ×ö¿£:9(–¥åŸˆâÖe™Së¢ÜuP}ƒ&«uìgǯ¦?È£†í¤ôÅšE£íwëéGÇ2Fï€2ÎB»¯Ìf¶°>g—“H½¦zÚÖhôޤbéÈ­äTŽ˜ªeF®Õ ¿--cåŸÄ%Ûç\\!ô"©ˆ§YX ›Ê bÎÓ<à®—a•ÝZ› F8XÔVPg¦BñÈ0{—Œ˜ÊKИÒ}F_}÷u›6éÞʲ—/y_â{@:“þþrõøÆ¯S'~«×M6¬³¯úI ž¡’©™¶THr3ä~ðvj1åg‘›ú°Ò`è} @ñ¤š­Áué·¨Vt±e€¿s­ '¯PבÿIµQY=›Žp »w öFK×À4I?ÜôNÚä5·|´nÏ5 #Üs‡Do­eHÐòô{y5·ËÂtá,ЂääO6ÀzÒ\»!ã£@lîzó݉nOW{:Ä3ð°Å¨¶ƒ•Hè›onXåÕ‡y±Šë³²þ¿J‹³o_u _2r÷‹‹›8¤ gÙuÄýÃ;}¡U}½d2šÞ~»Vbngw͆‡pì¨wà|3y´¢M‡yÐ]ÛÒÊxxú’IV†ãˆ<™B”óî©r„ÌUóo†Õ­œÄ„°wÔx4RÙi¾ëå a¸FÛ;¬ÓäeД¶Luý[ kM:± ÈÉáóAÃàF¥ðàžÏ¶Bõzê†á™©hÃãÅè™ÆºŠð 5Ää¦åDN^—ÿñãí%ÖÔg…á2=V=÷ÅPdžS¯_áÇ¡òÊH,PõÄ_zVt㙂nÌk›Zþg¢Üʙۡý+P²"»€³mçój¬ý¾&ˆ.Î! ÉŠ„ü:Í)V¿†$™Pÿ<,=ÙÇM)Û%ô%Ý šýŽÈœX3ÒsTaÐN ÛúïPf_Æ-~¦‹¢£ˆãÄC{6W·÷ûƒ30*½û(´@ÔÏTë„U]­ï0}-ô£±ˆ¸4ÈG/\¢ÙP¥EH ÌDKZ)d¹YyÛè.a^ñ‹öplÊä1扮YIÙÊ8üó÷\?‘Úì[?]ȶ6iŠxi÷A[m*¿–!­õj¹3Ž¥ýñ8²DdDÜÕ=·×>®7<]»ç¥»_¦ÄûC©Öx¯‰,h¶$‰pÄ·«á°x£LHÈþí¼w¡Øé6ËÈ£S.Ò‘.³ï=pžÚé5»››mŽ™¨ÞX×Í*ý¼ÛÍGŸ‰acÐëT2Iã¼¼x‹¸¯ÄæTê¯ò\0joâ–»ÑT÷u/¾ YåU– ûrWh©wÇfaÒ[ ˆ 8€€Èi0ßõ Ï­…Üüv>vÛ&@ÉKŽ”&x÷›oTˆ}”Ã3Þ;{¯HàÌ2µcœ©ù RϤ=ÔòëîVg»53e6ƒN$ÇS¹9©Óû©¬<={Å9 v>d$ûk ,³DBb¤9£ê9w¯@ê_®éÖ:‰‹²¥R7w›Yai%¬µÜsÄèŽ÷ÍDù$Û_F·Åv)½Ã5á±>AtòZÁ·C”ºõ«Žc^WT¯¦‹æÞŠiëu@ׯÈÅÿwdRKR‘D³”¤T|O'efR7C'ëjÉÿð >ç àÕ^xì÷逌Õtƒ)ìâĈˆ3PëM0Šò†Ë"$CÝ2Û Â€ÎÜs çB‚@Ý>$âÙ×nt¯4L”òJ!×5Äáøv_Ñ;•¦œR’9šÀ×¹AÁŸþ1×ÀŸ›wbè¨PBøL( ž?h®Ð»jÔN4☆FuŒnšO Bê‚<ºOr€@Ò ˜¬—Mf¹Ý'gT÷óŒß·^‰û·g²yH–Þ;qמÃMYÀúST^ŠÏ6Ä-›)xŽ8ÛSÝ|L¼½Õ™ñXà>ÔÃMš+¼’ÝæÏ2^\ È^Søì,´h|vg—Ý™»[Q¾ø„Fò1¹¥Íd• ÈõŸƒ ‡ R°À5ºÑÙ†­FœØådPMAw; (m ³®b͖θPAõÞc¸ÒDA6û¯ÙTܾ‚SIå–7øÄ*'cÐÉ’&@åúëIb¾]Ò­Ç[ÛZõè"õm´†PGSŠƒšIîEÈèÁ¿ëk\ȹCt¾'Ÿç;†‚ò™Ô€Õ õ”%——ª'¦±òRwÿ„'R5eï@šyΔœí¶[‹ÿ~I¯‚©½ÔzÏwe]Øjõ^Îqz»%]ùDCQ‹$ÿ 4ý—Z}l—Rç„ÊPýÊ!Ô±¤l×½”ÔméÐ#PÆAQ+§ÉPå“M+ÇNS¡½ý$t4+ pœå‚ä­ÈÞ]ù4ߺŽ:‘ÐsB!»èݦJO{±-nÁŠœRÆhØáú%&˜·½â®è»Ý«… 3Nì#o\ÿ,ó·"ö±sj!˜ †ÿ”Z58~2Ï${H=ÍÏß–´Šáº.K*a’•3ž,šï5¿ßäHÏr2_à8 ‚ìÿï93‘™4±ôŠ>#üKM{ÂNå˜çLÄ8\Ç9¤Þf k¿fž§pßSݱKDÛ1!_¾Á¸ß 4Ë›Æa_e•+}¤úÜ~Ø”Ñ Ê6éÇõæ«Û&ûu†üš“ wº¨:ð¶á³ )ÙC­ õ±d‡Šˆ¤Áá"†8ß*ºáän±ƒ­¥® ÷ÝDÔŽ4YÅó¤oCaNºò½×6þ’€˜¾‚žA»©&Ìr?Ê\~ÊËgŠ®¤z,P±,ÑKo¯t£(Óîñ¹¸?<ÖNqIŒ/ƒ”Æòzºó<¶ fט¬:ËBr†|l4ã¿w—¤ìôýÇîEºîr ¹U‹©þr¤éðæ=j#†nwX…%*$ú³I©…gƒJTù`#€ø9ÅŠiÉÑd`§¡ßßÀS¨5&pKŒ2ƒ´ß꣺µÉVCÂU°1¯íËzÅ¡ ‹Áù+¥SbB‡ª_b>›òÎ$N?0,n€¾ !ø’—}pdÜ-­„_EÚ>ü¸j¹ŽlîÕÍ/Ó€‘ÔþL+%*&¯0[ß–·eMc…½ZÐÛó*ù1íŽdÈ¥˜Õj›ŒèûcÀ»”ÙIÓú¾ÓãV§š8D|ÌIÖ™øbOŽ9jÏZ}àw|¤¸y=´ÜƒÚ¢yŠ3ÊŽêÑ:¯°ŽÄd¿TýU|˜Ñ1£%4Y ñ»YQÕãghx™4ÙÙB‹ÿ§)¨œÂr±œÁýƒ¦Öt·¢Ò«5À½¯# vCØIù8¯všêÖ™ÄVª¢È±Uéw–)” ÁŽÕÊ:åkOïIfN€{Ë8עРn#¥4Uõ8¬2ýZ ƒÖ%•o ÓзåèépÞ:2óRžÉü”0–n6Ÿ“çƒ| ‰žèîr²®ú‘-”“m㥣ž ÞÞìjŒÞ±µCXž@Yù‚ýK…9ìØAO°¬Š$»á¬î$@$#Öº'.iý^ì Æ ³ŠOÚŸªÁS‡vÚÄô*\“ÛãÜx¥1aË{̓´Q!¨ hÉ3y|e~Õ¦_ xÂ_º-µ¯пîèl5·-–• ûDRÔiÀ¸j6ôf>%Dó eMÅÀ|NâþeI÷ó…— (HÉ)Ø7b‡ê"mô£ßËñªÕjR¥ßkÄÏ4c |Ç[cÍN·äXAz°§Ÿˆã–“[D¡CÛΟ æóÞÆÉÞWÊ2[ЍXúhl<ÿÑ.ƒ&]è줆¤ Ìtõ¢Ej‡‰™ýÉ!7!y¦Y<­÷0ùÚo·Áª‹¸‰ ô~£ûèB5è&Ÿ·QýmïyÉ}Z}O†Í`…¦vøné^ºÛ ™›óǯô©Ž$¥7<0µæYè‰ðý€×àtÂQ"ûõÿ•GJÙÉ…ÕÝ™ŠüåX}b iFHn„‚Öj€Ñ ;µÈªó3;ë…»˜Æq?!¶‡– –O’Û7=’Ù|+æÓ:?ìÄôeõíÓ¼ÃçîRì•·é×îS⬠k¸:w!}'œ¯l·°b±Ó²…×îH*f‘WÎo¯]‚0Äå4ŠJŸ]\òg$Ä ¶tèRz2îðÊ»†)¯É‘ß:Ä;ñy`œÿ¹F­›¿™¬¸(+ØmÐÀ1 ¿·8ìÊ»9ö!¯ïQЮÖV3»ÎB-x~ýYA¥—šÖã)ªµ{5 hÌ‚ ª‚ Æ)áEnŒ[aƒŸÀy+²®{zÑÏ'?aøŸŒõáÆ(ïx,åõ\Oh0$ØÚ $‡íc0ÍÅOŸ°j]¦.ã¦? ÷¼ÁÆ¿ç=cwŸ”x zä)˜0DÒñv,ö­¼¯³ÊHN/Wɪy8Œ¿j˜ 54^¥pÁ>„¥ŽÏcÿ)ðð"‚CÐo8…Ÿ›·ñŒsfú­ò²Ÿå¶"]”¬èxãn×­œ ûÅj}ÀŽA<Ÿ—fé.“~tG2ãü*ØmD‹þk¡[Ô Oû’Š‹°µùËÖ)ªýQF%é?y’‹¢9õñ‰ÓÈž ®ç‘ÊDšmüüÏ÷ºö뎗HÑ©Bð½ïó °ñ¤ac“ E”׈«iºvƒõ7Õ¡ ª‰~’ïÏ_eY]qPó¹ç·¸ v½ñ.,Jóûøp$*T¸!·~³€§1©1̧§çãE<Ìô#â¼åÀš Ä ÚèøÞð2û× 2­ F¸Ù·å½ø²|*ªøÇ&Y[¨œTY–·2fõò‹¸2¡C–VVvj· ]ΨñèÔß<8m‰îãPd=ƒ’2ÿÞú¦›.1[GS±y5X’ñ=ú41›†7ÀÇfZÅ÷1×–C˳põ¹œ§8Úù¢èn»8‚Ésò?…J|èÖGû“eÈÈ;¹ä)mVËm¬ÓT—õ}0<–¡Óê$,,Æ¿Í6Rfq9œŠ¹ãC÷<-ñ À՜˿@S*fmP¬Ë=‹ CÁì-P1›ûfgf¶ZûO—á)—m¼ãc¨|n:)ݶb_xÆ—¥^x*ªb‹% &]ÎB¡8à ^ã°¸%M6IŸ²ÁváöÚÒG›üذc.jÊôy­cM7 Bw*ó%Óß5<Ê %û¡ ™íÞžÎU€; Ò y«n0¹[ÇÞ)ài}zŽßÕ{»{VegI±r‹øio%"0M–e tÓý+ ŒoKëÍ®\Š»zúÓh]2%#¸ûºï"Þ`ÝÓ‹\Á|*(«Àgˆ[\ìc#'¦ò´l0£®j¢3°E¡Cöä+â݇‰¶ðÛœ&”^ƒ~ip©,V ë4¨µQÃÈ&¹Œ=è&š[YÙyé[]]Ra}B”™LC«(áÎÍ\Ÿ''8üèk ~‘¶?&·¤‡¤Hg‡xš¶7=®Aä„öDï<^žZ5ÕC©v8›šŽ2QGl%ìKoçSY<Öb¼¢h‡K¯eÀÔpç´ïÁ†‚£S*t³ ýíQœ1€Ïj7ó”DÌð*? V/3Ö®Ëð2SN’C@,Ò:S'‹‚y¥&ìÓ– ÀŠ-ŠÎ7–<Û &ê=Û’vô…Çñ4 Ó‚})É/µÂn„H-"¥e‹ÛºHl‚*˜ õZû探¹±§³ˆ®Üa¾šzŠÅ¨-TùD#,ÍªÒø‰¯ut[x|®©Î©qN>ÃIqv@–ÂX‰± X4&‰V .^¯›çlâø,‘g‹iºG ¹ƒBø0Â^ѬæéêĺȊF£7êSà‡#0ïw¢i¤éEy“c\^_Åt§ªåœ„-SŠ™ï²á÷²S?'õŸï1~t+A}ç‡cÂþñîL’*Ó–K?M¦$P f®hVu(bôU)]Â=q„LêíªR£uʘ6ò­'îà žf¯5 RC=cm CXé9æp{–ÅŶ¥8“3©žÂñc1Vƒá,6εOR÷,3‰þ:ŽR„{4ãÁe "ò†©çäZb`ãKãÿpI ˆŒëòÐ÷û¬Ú|Ó r¥‚Y‰AúR õ÷ð ý°ô¢ÈŽ‘YèTmÂò¬^G:¯ÔÙð!Ó6ÞV3|<\:^) .~ÙþÛdt=~z‡ü =ÙíÂøÚs%ÿRþy‚XuwÓj îi¶ÌE*ÿ<Ȇâÿl½—ö==”g ,¬˜Ý .¦´(³j“´v§r‘Þ‘†è3¼Z ÄР¸ï_±ÜéÖç¸ÔšR8u‹ žW µ ºßqzÓÒ²aw»øtmÈðïÇW+xw~v „ çB¶}†hqÚ• ý&”RËµŽ®!¼ÁȤÎH+‡ªÙ{M@͹š­~G(Žä—^¨ˆ`|ú ˆùø×8Uãú’ ö  CØÝqá  ) x±ã•ÛW &1÷['hó êØÃV¨ÈÚÒõbÁ%­h7#"Ÿ4~‡Ľž@Zÿã:¦ä.¦£aÿ™´Ñ‡’Ëb¹®Äy’¢5†ŽÀœdòàΠÀ@¿#÷J%X÷÷?>Èv,*Éò¾]c>IæÑ pÛ¾¯<ÊkÁºîپе.·b”XR(ºYò —Î'¿ ÜUgº8oëô渘‚–î{­èq$d΋t™X;G,ï£cp¨¼ïó̵? ÂîØðÄÚKKÿ‡»·G+QÂþ¤eo€ˆÐs³Øx"›ãGg€¥¬æ´É4 1R-ÑéÙ—o¶‚tÀgTŽ·‚¶>ï^Ýß:«kl\Šˆç!@‚QÝ =¶WŒ_&`UœXÐŽm–LÌ·q˪.vxzg7ø^§ÎYÓYgl\°óiÒTïŽRÍF×§¡3ãhûö/Ô¦õHp h~L­á’ª^yªyêÂÅW(”?ïý¡ÄM"Íè |c¤T-5ÀÒOWÒÈUìP[ å°‰I†šòpû±/ÐF‹Usžñ=÷Åï²…CøY䄯âL`Ç]À(ƒ·ß¾Pì•SëÞ!à’—cöa"çÍ’«Â1<©ßƒ‹.û%¬º §d<ïx¶7áͰÐ?_Áý ‘°"müþ¼w•¤¡¼¦w8\4 Ñ]ãL™4ÜqÔ2i é»\ÂógßœSg¥C´v¾RŒ™Ûþ˜nªþ²*8«ð oAš®pÛjg‡Áj‚ÃHÅÁçŠÊ™,€ùàëä²…rŸôo1¿%djüxFì dáâŠõ( WÈ]át^=Œ±•ame¹£|õÝ´¯C±<¶s$é½ÿ$Ô@"Y7ÿPp5Öк^ƒ »CÎ Ùú«7XýÓQg·Ž?•£«KÁn=¢ÿå×ã bÓ¥åõ¡EÝ(FnüÌi©ü“ŸœAPæ$Q`ؘ0Ln®öz¾Lí¦±í¸CÒxRÊe©­ád°&ë~…Cç@ fPò3øÂrRãxõ,ƒk˜\Ç€tû*Z Œb)”Ø1ÿ²Ìà<ßló]™wÃ.‘Åï>IFH¿]98|âoôÊKâz=ÕI¸jHÚ ‡ â;º7… *ä Ò%EcÁ-Õø­>‡Õ‘—^–ûdˆÍù]ÈB¤ñ³uÞÀà 1¯iC„Ifgc™M‚ºá6½0™þšYÀ†—ÄOþæ‘òèD—ØG}®m˜NrO±ŒwH®Uºº³Eô_Î$&Üês=ä]Sªÿ?nßìf"á¼—zœQ%F\W žPÑÇ; òÇ…¨o”=”°N…øÛôƒØš#îÍ#àÊJgmýiÛYef‘ŸdQN/Ú.GªÜ³-Tµi£&Yôñ‚Cj²ÿ§Eë…o¨ÿozÓèŸ"á5]Ì«zñ„j­Ì›óæÁáÇÜŒ#—‚§>c¾šºßPóB {£‰Éô:£ n¼JPy<ÄC) Z”oò…àCì9Æ.(Š%1~´ZP¼©65O†(Ù¶ ôXÁ'ª™Åk¾¾Sì×þ÷­ð;eàž_µv·ÁÙ õíç`»ê!wÎ+ ¬¥„æÐOl:xO±Cíè]j÷«ß›Y(à õIÑëËî‰`é€U^Ð7G™ÛyÆ{.Î)3Bouî «Âá/ß2*HáÜX"ÐÂô¿Ø%ÖmQ#±R¼n§ñÀPˆÖeeò~8Þ“ö)ÜæÞT:dºƒ^بxs[p~ŽE¯²Á¶êÑï:€ ;‡&?K¼‚¡s°CñhÀ½6øI›ö-”8™ŸÅàÓüÂú…0˱]ŸXÆ>IŽfM¨VOzµ!_”‡RVéqüþí¸fº«;¹‹`Š›INº|@B€“}ÜšÙG˜ÿ|ændVp,–ØÏÉNõ ö¶1ô-ž<Ù¢j<ò*(ïÞ$ÕÞ’„ =ò„†c}£%;ç?î†ã‘è!veÔ%kû{<(O$3% ¹iâJ§?,i75³?{/~æ&üÁ›³?“&¦9é²ì€·~ýGKïR¬Ã¯øûi #û!Ä·/å›/´©Q½9®5<¿ÂªL›';И% ªÈQÀ¥Q¯<‚ì O½«Êç\S»í¿nÁÐ8g}sÛ®-¨¦Jÿ~b/‘ N ôi·cÊÀO5º±Žä>BÃ\C­ƒ†‹…•²ìšÐãæš)‚{$ô’àÔOªÜÆ8×èåäx üÆœ;ÜÈŽG¥¯ 7å ,™ö̾r„s Œ‡=ü ‚_Jƒ|.ÅÇ Ô&˜Õ ´ÆÏð¿{ LâÅmž#ù/ZiRµ€ÎT†Äí¶•« ®@$›’°ò †ïó„±cÊš¦üSNiMëhÅ >ÝÎI}[ô_0LVLeLÿ>¯N\4.µi€ÁözTÔ%l[‚²ómÕØ¼ g—ÝﯹÀ"›V+Èe6«‘T p"š9Ucl´ïÈeë,ÿÓ:öŒ›­øAÏÞº?!r˜Z+/xt²@ÇrªÇQœwÎw ø[Øï=‹ù_½¨þ…v•ÿôtу¬‹|–j–¡/.¡yÀ,¤f´óñ„.ÛFõ­álîì¯×EŠáŽÌÂÕàYél]__f¦Kóh a§¸óenÝ6€|çh‰å;Îg¤ª #sù—¬“ö¬­kœeè09v Ëm_ãúº@¤ÛÐ2`Á/ 仵UI 6ïZæ/9³\T¿–ØïZÍUÖ}é„ik _û¼‡Î¼Tx˜¿é ç,ñÐ%sßàE­¿9„–¼Â,#éò4¯<qa›J‡ØÔ+Qš¢L½;:)ÔžÊ2µ6N¬ k나ro´c4é†=/å#¥p„ƒRÍ‘j«0ØÑÉ‘$Âd*L‰gÄ| ›4-[ÈÝ>™C_õu†Õ 1Æ­š îXX”TmGQ3è†G:¤ø¬ØÍuEHûDœ°ÚeLPàìc¤=ý­¯dô#5˜oåK9ÑdD6 ïcDOÃןK:+ËhÊ ROvlœ“»ŒUÙZ¥[þ+3Ô`{Ôv¤r¿,c+Q“ߙΚ² ,»)ÀOE«®„[$30n÷¦Vw.¦À†‰‹²Z".êùz+Ä¿ÿU:SDºiœvBÉ)½ÈV(/"J§aQTSKÅׯ%"Zuw8öu—uò=ߨi([€ò—u$ اé@7¼ó- ¯{‰ÁÀa^€0òçúQ1à?OòU8qçýÞYØ(DOÖÙä'å¨BPK•]„Wc³’hìÇÄàÉä#?vnøEŒÔП¦’ú¾ä4e÷˜ï"Ý:®1îØ‡Pûº8Î5 ÑoQ§½³ƒ¢¾} ƒv»çW£‚ÎÅ÷ÑèffýŽ ÜÐæ¨Õ”`‰‹ ã ÁŠbÚ'AßVµ»VìæRIÊN¬ÙFCÐj\ËX$!¶lƒ¦©=¡67YxØ«‹T®èikzáÏÜÄ¿BBsœGIÝÈÔÀ:ÍËõ„äó4‰_àå*èâ ߸½SÁÓBÔÄ !ì$4Þñæ£gX§â2pÜ`äJ¡àr‡u¬)…«¤ïNÙZ1,½iS{ä±*ÞOêk%iIC2ÛLš×Ô@…–ÌŸ™Ùõy(“ín‹ÁV,çÒhmü"kôBÉÌ[°^™)²GýjíIóÛó}=bW± äÛ}-?üÂßÌŠ~©Gùï®c€<átI¹Ë ¸±…\¥ÑM^OLÀòTM~}㵎Í´\;Õ¬cɉ¡¯G‘³HÆÉÂsD·«ÖO 6†ØåNÅìâqþ¤9¨ Šr=ˆ$ÓõaC  ú=ÎU䙤¢XþDóÇ*²yÅuXß“!-XüTBëÑ›(Äþ¹$€ž©$ ‚šZÉnPJÇ$h%JNõˆœ„Ï*ÿ߇d ÷(kº­cn‡«K°è÷gk^žÅ©]†æk½¬h§­L¬¾Å¹ƒ¤H:F›Eàò¢Omè÷%HPÁŠi=»W2;“Ó1(†ïH BÀð(*JYå}¤&Ëp]§Ää¼÷«¸ˆâq#ÐmÌè Þl•¸_ó¤8e ©šÃ°“øðmüøôq%ÌÇÊ{õêH⇟<„_X•y|i‹ìiÌê¹8Ü»˜èeï,{ZÁ}Ó}-ëJNÉ´¦ÓÞŠñä½öé¶ðGçvC}'í™GÉv¢)K†7f¢A@¦cR?"1ud+4[0¹©ß+ˆ«}å çn¸/¿ cå~`á‹‚38{h/'ý4ݵ ŠÙÜ¢™µÉÔ×ò‰mfQ0ÝÀÖ¿†v½60Ñ¢'v_ºå…s;éÕ§ ¬ü°œ›/ǹ>ÛÜ/iº1Ïw˜üÛ éµ—Ç)ñ‡çŠ:ïV+R „†Š2V—òe‰Â³ß  Fƒw(!ƒüUEn °?2~máOß«¼}ö–ÙŠÑòÑÐjô*ÕI¨óR|?Û³yÓ­9µ¦tC¨‰F=Œ>PQ:uTU}É”ŒU9hY’ÂÖö/_Ê‚µGêÑ@q‡åy»y£"½Ë÷ˆÔÓE,T {޽øn™,™/ :‹,sŸœ¨ãä™–¦Kÿ‡‰=.³¿Î±Ee^ô[‡(·ü]À‘a@½ûD×Í£‚°B[PŠÜE?çG^Ê6À¿»³c×¥¯öümUx1@3 Œ&Â-erv嫎t?õËo΃_ô ;˜1ÙU‡2wéÝqHÒõ 8+…·ÕB÷>›Ó ®ü#{r s…#-]¾ÛúÒq ‰Î~éW0ipÃW|2˜G3WK¿F«' ͉¬˜^4ZuTlfíšËø ¹qeeú=ôÛ‚÷nX/SüÂ´ì€ ïŽíìag[]?84VѲáÙ{ã½JçÞšj  ‰Þ­+ºëy¾æUW íÕû9 ú´;x Þ¹‚z²aÛ¡­M<…X¨§áÕŸbµÓ…J >ˆ¶²ÓܸVO k·Å¹t/³ÕÿåËvŠÑúޤ-Y¯©O²ø`AÜH¬Þ)±Ú¿|œp¬5–Hè,×8*áL%$$i[òR.¾#Ï:V.ó»`Z³†Vó˜ Š÷ºÊ:/©%¶l€©k}öR{B¹§;”(O¥ŠŒn ¡÷MœYŽ|à¹DÄÍ–q¦$ÿ ­lÆÜH¿šßä$!êÉý_qŒXJ•¨Wñ ç¨Eí»¿ 6C9u’¿É ï-ó=GÁÕr_ -ì?’EÀŒ'  0.l™z=f}²[]þ˜LËEwnv‰"Úø’û2zê)WM¤P¤ÍòlνÉmh+â·KÌèÝϨ¥ÄPÒ*Óg,jïB°èóÈ_öÀ¬MÛZ·O˳Œ;PØÑe¸Ìöl‹@Iã@H@•¥«þ§È=7Öž&¼Ñ/¡ˆIæïkº÷‰ñ,_Š7IÙÚp9#†sÖÑŽöù·Ë@WýiÁaн1ÈšøÁÜ]?ŠÀs˜­ºèØü騾˜“ è·F§z1ùLÉ_¬>?C¯¸?í\sFG·ë_¡TΪî-อ!_Â8U=¾Ó)–¾å$/°ä=­©¡á‘Ìa‘@ýy|XiaB/¡Ôõ\ÂR^º)ª‡È¢„~i‚þ½'‡­GMrLšâ¶¶áS „ë?-Ò|+ÝúÅIŽï*/l[`×°wîð¶Ê²ceàW™gÄ”¥+èêÐõÈ4à¨JÓÛ¢NSÊ«Êí¹W牲•HÞ«tˆœÇÆqq«¥¯ôø…|M¥CŸ¯Ëõö.–Pž0šM?‘å¶?Ý#ÖøâzE&¹¹ßÏ2–äÊO µõtñB¿L©[¼ƒ@¼—DÅEy!v5M`ð ly¤5EÆ€”ä*[¢¶ƒQ$~°”î†.C$:àåÏy8¶ÈM5eјҒHÞw Å'|…Ó¨ìâ·‹9+­–ÙH¨¸sÆqðŠÚÍnº e&|k–½ñÓÀºëØ6·U^ܾ»ŒsSj|ãkU ®êpN îîOI8ôÇp/-­áЮ`]/ÿF„Mï–2¤SU£[£ª¨äXíÏ#µ)c}2@Ñíb•)p ú}—œÌ„œÜ›4CWÄñ*cS¡)³7ËÐêu$»¸æ‰¤Ë|õShÙNQ,ìZɰþ?þû‹ÆlkNQ©‹yŠñð7)Êçš W$ÏEÎj [º=èqOpÏsu(`³åWUŒ¸†’Š‘בã%éL6.¬n”)0c’Aå²]ÝÒ¦‹+ûg[auØ0‰—:GÁYm¿Åêü<0SÓqÚì%£÷92î}HÈbÈù“¿åA˜òG+µ7 ®š\«àm¥Ô;H7ð¡òáÍÿ¿ÿ3ÛŽk¸Ùj#FÀð†¸½ù#ôuÍIFprÐVûeZª° dú&^ ­ñ‘Ímãð¹›87 uÿ°_òH¡·,o48Ÿ"üãdWÇÑéÏóßW¦?Ñ|‡¤o/Љ[ ßÊžP“5i?^ªÚz`M 9ÕK¼ZDgðV.pÓ’BàíH:,¢ƒ¿vvX«n>/ŠqY}nqö»GëÍÅb@Ê…/:´‚+ô"Îþ³XÖ¿r¡”úÈkïR¾ ŒÛœÖWÿ¿ì–yº{mc‘¨sjûvw ö­|àþQÅRWtKyÚõ3†ßç'Æs)Ýfx¥@z,l¯B÷õUù/A›ÿƒ’[o ¤„ÞÒT %Y«cOéØcêóÑ(À¿ؘ}茉¹›FW2µ +Önd4Ù®Rƒ¶'dÔ@†[W Ñ×ÃM5˜¸ïIŠb¤vT{ O^}Q¿THõ¯ËØ×”˜â&±öü g½Yv@‰ Þ¾ÕHÊHéhL¶¥¿0`ºþ5RÕFнççp1çvÄŸÑ[^•o„ü\øæ—çè_\6bŸ¹µ}ŠD—[zƒGï»è'lýîLo5^ïðÏ2ìù½ ˜TÓ'ÇkNS™Þ"öKlhÎqûÞ˜01ªS"p¿ß…”Æò<±(Å£ïÄZ“Ë–UF½ÎC?nFç!Íùœ,‰0 ùNÁ! SJÃ:…rÍ-×ýˆË%‹Æ£Dûê§âÊ\hµ®ýB =)$:ïY\35_YŸíQùsc¾C½ï…T]íB4 bq‘4›oY³p|ì¢×3>í-lš°Þ\,±4žµhR$‚ë°ðEoþ¼¹1M|ÂÛñöæ•öã;8»pe´Òõd‹ïý–ÇåQ.:‹[ÿ0d¦$ujp9w¾‡×{¨pÞSD¸ üµ Ûw7|wx&Ü5—XadB­JRk™ ó3Tô„¶­þÁqJÌüPsðÊaO§ÅïÊå/S] \Ôæî+Q ‘v¬á[dAÆÜ®¼P]€“Û¦ÜZÇŒxZ+ŸªœðïÇüœC¶ø ™”ÅúYß2|) JˆÞ–TœÞ~\Ú:¤ïøJ‰á›Ïh\ÑÕ·š û²9‹K¾2 ?nâêOÍQ—DKÿœšÐõJÖüuX5,ý›úˆÊÇÔæ|á­9ÃWœZ Çã!pæŠð $Ô”ÒîÇëMÃHΠFæGééy˜žÚà9Ÿ¬î€tï5)+à œU‚|•¨ËÅsd}ÄóÚ<͆aAàâÀ\Tœ i] ×ë‚~…t,Ù$N†L}&ÈçGyZ1¸3W¶8¶µWúù¢@@m' èoÄCq¹Æžª¬è Íî"8Œ¯0„xŒß»íP—(›â R‘Ÿq|#Æ8Š©ü8›ø·g-g§Öo]êè÷ê8ò'©«‡¼A뷤ϣ„"¦D^ïvx:rÀŠSÔnPßÐäLHœÞ¯Vô‹¤ d›Ñ ÆÓ«&ÂÅÖÒß|Õ†ËCLMÖ•ðøå—Õã%= êêÊLûU†áe5œjèË.ußV“q®›s*r3]c~k¬êiV†¨Çh™|„'!F8;ÅSÈôLJ›X§QÄTIß œ‡D\ ôx« +·É6§^ùð­žÉòè¼âŒÓµÿÁ«~FÕ{m£jÊOöýy9”-³"f=Õ5N•̰TÎ)éðû~+Ђ¨‘¡,U J¿²Íû„ýôhé5šj<žÝǯ›é- .‘eì_¾˜\<„AŠÁà$/—¡gž¦ŒŒÄ-¸×ÓèöÀÒR,Ñ™b&ÿŒ•m? 7õh¦sŠB#²¦Ø|Z[¾uî 纵µi—üG÷žLê;G“Àp:õ>Ð*œÌÚèè`Ç¢ÛH]Oh¢‘K®||aKPÔåW¯ ’ y0•Êsšò/ýüU ‰öªŠF¬W4‘<”¼ä|Õ U¦ñfi¶À0åçRD[œÑèö>µýyÒ'ŸéFšEöW`(n–‡>"Ó‹¯Ø)——HóÉﺋ+­Ú tôÔëöÊÌ‹Ô!îš"û)bMºC%$ñTt‡ÌznUŸâ¤C”é,¿GDëŒ`ïin‘=/×Óe€°ÁÀÁ¶yU4Jd«*ܪ|‘#þ¶\+¸§JXYx"@B‘…Ë£–]é|Ì#x·Ý½7Ó–#æ uÊ(ÄÕ ¢?[Øô =À×ûÆ‘xõÍÀMGåv­~OG‘JÑ!†"CVÔ´Ie3NWAs= EÖA·(§Æ]_s?Q'ž¨ºö£ “œ$E×Ô_G3åù`  VY•Ú§ŒuW’~AB¡Ó_ì•§‡?gŠDþ“{l'¨|è—=ÜÁû¸‚H…ÕF=p¢©ÿ‰ô3l.vùÙ?å¾M·bI$Bä9bÃß*À‹ÊJ¥î:ú’˜Ô™Å½´Ï£__HhÍ·G²?Ü~–ök¯¯YmM»l`Áõìj£}÷[êiÚngX€|?ºçûÿÚ|¦ 6#?£èºN÷/ +ãîQk|ÌO SB®€m¶(´J<ˆ»GP‚WF_Ú' ›×oÖW.¨"äÞëp*¡£î q,×5y¨‘†xÈž(òºLÉUísH «¦_”ÿ’ƒù$:µ'xeg¹Ü°3s§®¹>'v„ôÊ6ð®úÝ«„biW–EófðÒ‰-ªÀ'w­(ók«ŽŒÍÃìNV`•ÇÌe#v‰f9+°cí ‰¢&‚¥Zvä'þ %1ò8z—²ö=ܽ&é¸ÒI××!3ˆSY#ÛÉhhµúh~±`$êžmÜ€±Sy€hŽTå¶[Î8>¶Q\\2gªñ¥èvâî`è—ä¿ço·¾/ožOPu5lDÙ ‚D Fý±ÿØŸŽ(iø5™Bf"É—©ƒõ5("A¦±롈hCƒWìMFZÜ"9EB~Û‹¿Ïº‘ÞW:î¤{7/Zó–ƒg¼Ï}«ËL”Õð³zYÌ”_˜€¶‘È{ª–âXÄ·ö¦¤jYM'›á_É&Cm+&}ÝpÓ™øÎnXGñpÛõ–EäÆÎÑAô*Ä90 lQYz!¥`âÙ¢ì‡æ%<‹SµÂ%D Œ”:Ù‘Ž™4ÆP·eQ·IÊ•ò ñP¢# ÅiegcBTÑÛšcúuÁ¯ÅRåqgüôNìðñ$©Ïã>2ÂkX–„$@lÐv£®Î›E˜YâP›ãØ3 t I0ïõ8\ì{­1‘™TL1û;Ý ²œS©ÐåÜÜ¿é’Õ&Ó \­?¿Höï ïcŒ_Ø9\¦53⬛T³v­úÏ}ÙÙÙs“‡†¨Õà{eð¬Dø® ÃT¦¼¤)E.Âgø¼;k]Áq„Y¢ýÅš;µ­Ød?§Ò·UýNöC»€~¾'Dÿè$Ýñ‘r &VÛ† øIë4E;'B:À Ê‹¼¾ø¾Ém‚âH|E.¬ÖTŠ9÷$=r¾%+ÅÍ¿¿;ÈaØy¶Õé©cÃÿúBÖ \öøªgQýÌßÍñŸ¡˜´e»š=šàcpZe“önGB„aºš«ÑE[V§ V Î}OåQ”±¿Q;‰„n¼yarƒX˜6r æÖ@Û1G;=Úîæ"Ú²²²hëVqÙiM…¯ P/€c¢Ú)J^½@X\6%s1¿=$^i†ýäÐîè!±-<Û_?œÖf¬cbù‚4ØìûœÊ-îÉ¿À¯¢H›áoÆzüã.ì}÷}”™H`µ—ÅÀ;èe¡–ÏÖ\K‹ã¦áê–‹ýÄÞ;“‚ú.U¸×Iƺֺ—I¼œgàš¯²žÓWüq>|ßx»­ãΪÞÚܤÏíùXY+:âÅxYôeÁé ¤Ã¥œ ~ùìõ@4з|^–%ÇnAD•¸Ùrý‚óÔ©Š½­²|ÀaÉðî˜'ç0…kkmù`8£z 0¸@Fš"»?4£Vy?`uÔ·ß ßæÑë¦5ƒ4}”Á@è7äÆðkò4X"îÜÍËü\‘®c¶¬jǦºÁÅUíÞ=§-æ­K"æÎãÔqÓ!AIåãÄìªÜU­1{idSeÐC í÷ Èj>ÚÜÕYL$%‰`L>®º ”í«Uö)š¬X-ïî@\@ÙSNÄ ×ìJôÈÌÂÒÞkøŠ|[gl »ä˜7è´Ž’lÖS¢j‘vR\âUÕË5è÷÷°ÅE \‚~Ëç¢$âë×Ëz2ÆØì3m¹{£“rf‘©Xš3ÒÀø„þmå•FîY¡?dVgñÁK…ý/~tó;6TgÕꬸʼXKÛ~¾oÉVgá# Ñ6†rºäZAnƒp½ÝJ»DÎ¬Ý üôÔüM[LÌfs9 ŒìÈ2´@ú<°)Ö‚Mó,ÏÕ¿UkÁ¤HÌ.›ûeúÕ2˜IgX Œi)û™¼a¿+`IÐS |çì[^½ù«*«×zÆu&âÿÈãFº*Èõ¿/D9Ì-\ZEßò è‘è~âtïÎ%ÐA^j ÎÁßëôTÑílÞrµµÅ6ö_)ÚÔ,U) cÀ£­¨‰TXi gû‚ ;\h»¨ˆü ø1´©û(OO¦o’%b•,jt¥£ €œk|²1á\Z¸6X<Úõ7–mœ;|t ÇH#üÛ€’íóÇJ ™N}Ô£œcTÇA—à§M¥å‡Ž‹ˆ¤‘à+êÎZ·V¬y¥pgÃã$[ÖíÝæŽLYªÇ <ñhûМ†PJäþ¡'¾ª“Çu¹ EÝ>¹ðÑQ꟟ë*µÅ:[4îRLŽŒP;æJ$Ä5àF¶eÖÆ–ž8šž¾*ý˜æ6eD°…C¿»rHMI»¤{ %óÌøK ʾÛ/KÎ_þèÖD–`le}å…ô‚5Þ_¿è*}8…GÓ¨ZsôòðƒÀpÅÑиá þ.¯‹\/,Ž¡Yÿù[»F ³ú“þ¦ÿ¾p®†YZÁyÉ\'úïU¾¿rpx.É@ÅÈ6´Ò‹%œ^.iü"$öÚûÌ'Y3škÿCÛäÈ{5;a¦E¦>åiSmKjÜÍ¿–9GáŽÀåüÒÊ\Û-á?oœ~ï­Ìöu`-¹¿éÜ+jx¼Pˆ‘Ün Û”Ò~0Ïïó`ª—$³#®ÿ ôôš˜Âèž@)8½¦dú´Û¿*‡\D¯Îð!º5JôÛƒsüe¸™÷™Á4[üœXsüšzqà T.Ÿ‰˜ZKœcÝ’AáA­g™^Aðºêõ^Ê:ŠZ~ PÃ’” °n3JrûŒ<‘ý 2·„½.ôïN+{ }¤¡]EÆÛ.R*9©®­˜bÿÉÔ/ÖÊW´ë]—Þ1lÓØ,¯¯}!Ë#ae¿Žõ¬>ak«i/S\OáähöT_±¡Žu[ðÚPi]9Eì(îÅü´,`‚Y¾S!_´4HCõ[«"C V#læê‹ç§Ðw¹¸CtÙÅË:pBd„ ìâG9á~ˆÊÒW×7à ûžKg6…(ý÷]HQð¦ Jû3ÿ‰1¨þÙ3„i èÝĪáïáqü*¶Àz' ðÀÌ6Œ‹]ÃÍ Ó`Vxºt®×Öÿ|í[ëJ £+qлvÚìò£ò™Óºt‹gZ¸ã.ÍÛ?7B. Ÿ&&Õ~ÆW䰼܉(†r¬Â­m°HÐU”n˰àÐSÍïHê ]Õ–¸šŽ¦T“‰ÕÈ ZáýšŒüâ~«N~´%õÂ)ÜÏEö„NŒÒ±w9="ëCÜäN\ÙµÃ/¸i¡'é`6mŒ£’äû#e!Ý òMûò“ZÍ ¿î“Z)¿1{&Ì}uÅ;á ¸ ¡Pj&Æ-ãT\ÕYb"Ó˜¼†¶†¹ÞR³8ÈÎÒçµ÷f-²9šãÌtzlàªæžvÊ=[)~b#U dÓûÓ¦‰4.ÀÎÇ:²D3zËØÓùTï x¸¤i}¾ª¶œæ…`àÐ;à|,6`ÊìQBäûÝ+\í¬)¹* —"¥X¤œ`G^Ô‚^ÖîãæUG¦7QèT†ôH|£4§¦Ù‚¨!ÔÜê1fÿ@©(»9oúpVMÇ‹tr=} ‘Cä)б@r‘A_ùAáXH,þáêéÚeíaÕý˜mðÓK.a¨¦|^€ŒtäѺ¦ìpKk©Ni¬+”úQOç•/š|åÆ2n^3â?Vï’²] #Kp¯\x„;+›B±Û™84›íÙˆÊ&(_Ø/XQ•§î¼²é| ÷)ÖWƒz*›G[Ù¼á +P£žB‰ohìÆa#_h¹Œù}ªn¶ª£RÔ…ô cýÐÙ… ë·Sã±Âî ôêÄþûu}`mFH³xsŽ”kÞä@||+‘(B€@˜ ѧk‚-îJK %¾j³8í·¯ÞÂ%ª^¦Mž$Ö.Iúõ”ÞÔÏò[N`‡}ýÌVœo•µ§œL$œê“ÚöÊœŽã 8Mòn)?¸í/©Ä´·Î{ÄG­]+‹öãY šÝ¶ ÏØ¦b#U¦©éoɲúuEȶ‰ÀËvlWbÉ•@E ¸†ùκ}ëB0ÜÛñ2¶zz¼ˆµ…sœFMÜF ãÀBÁ’Å®„'ì̱ªè¨qŠ¥ˆ‡¬˜Èü·¾èÊ©s8‹ßë·ü‡ýRçÍÓÕ>àŸW”"–f‰Ü—¯ <éJï„e@rC/g=£ºõ¹?–¯_@+pÅÑ0(ÔmvN’B2Û°GŸÝ.uú$ë2²‘óå´6Óù44õ›ÉØý÷æ©áà«\’ã›3ÞGóAú®ü“WÅÈÆöx’êz#&ˆ©x3D/j×+ 5°>àå¹{Ì„n=Tò0õ þ¾mëT¸©àKwuùoÈDŽGɾÏBœlœêIˆCÄÉо“ù+é7~yÆx"ª™¿ÏJù7‡$/vÑ'áöÃ’×ù3ÿdö…Zá˜Ø$ì®—Ž#dèìkÃ9‹‹âÁe® e s'±^÷a+çÛÙyåK2ĸå\7o:÷ïG&m»b…? ‚Eæ¿…Ó*Ш@›ÉrBæýe”v½|OœKfko|iÜÒ`HîOm7®IrnuþB…$²¼| ÷˜Õp·øèé3*[_jØh¯¦.’ŸR‡Ù.†Ð²%8³áÛtP{¶ÌgVKèÐøƒpÀ›Úwû%btLË ”ó¶Ž«jdó¼P ­:mgTÆ<œFÿ†Q¦IL@±ÛL^‡djw³d‹—¢°’$Ùm_umý(\Ù·½YÉÅš·c„G„;2¸µlç'£ªæ ¹ÌÐâ.ì ù€–®,DÁcÓÞe韚„0°‹}|­fTôûG¯=qø¿¼:ˆP¨‰ít5í´Ð÷ #2aóóüŸÐ°' °4 ^ÇÚw¾µ ï[‡j¢'+EŸo`¥N¦&Þ©>¼ Ó¿mØíû¨ ËxêU9ýQƒ¼TÔ(?n?δæÒÒÁÄ“®`™‚cäEô6µœ…ɉ$á\mPŸÝkª¨àºØÜßµwÀb43÷ΘéŸÞh‰¥èqÐŽT¶äŒsZ0.¥_m.Î)¬ÁD[%=wŒ1!(sÙ=Ž€gR[Éw ݗߺ8¼lž{ˆ½I4f;°Ò_)–Xæxc"O0‡˜,k=ôîäç½YŽYôåg°¿µ$ â¢T¬·œ^”Þg'<¢×¬ãw8YžÑ¶V÷Óï1ë᥈ÙuÔüiøfOÏ!ð–öR”ót]¿GåŽù™Èý`44(GrêZÁû`Z[*߯œJ³pÀ:)·M³Nã!aâbLÉc¤oˆN€Cª–›t0 \†û´„ô|E ›š#«‘˜Ð™N¥ðÕ2øk¹½¾ã€hֆȹOb² êIOb[\b0\“އrk\AuN?n$u¹z|t?Ý÷Vé¯÷~‚íåéÄé§4èT‡ÑßA1\, m¤ƒÌÓ™ÉÓl@Nž‹ëÓrÛ ¦ñ6ØÀªÒ 3»;Ï ˜¨¦f oß’ñy¹ £R2—JéÙ˺ÁñPߪ'$pn 9N@“ä¢ëóí³&þ,(<”Fèø}µ"ŒÒ›>žžRPÝÍôºÿ¢Æ¤éoßåzÍðÚ.>_ìnPĦq»7¶(|Iƒqºüü¬eÈ”ElÝ„'³¨Ùù-^â|Û]MKj6 }ØMRö?ΙâÏ€#ñDó8ÓS3²!¥CgBî $06çÉG@…6˨ÖQèMyŠ ™XŒã‘( ¬ç›>ªM=níÇb=ièäk1–sèÖë^ï×â{«ÄO=•¯Ušü+p ùÄ=ã>¿,õ¹fûÆê ‰–t\ËÀ³_D ™|çìøSçfñdÛÀîm¤›£qrG:µ›m¦~ߦC4ãéhë" ë„÷ÛåÜ\¢g~ÂŽP +"ì‰Huºp×Ãðÿâù‚ÜìuT þ„PQÏÛÆ-ý¨'›kYûxÚR¾¯×aÃK’¬AÃ:c½ñXÂùž¢þ÷ÐX«ÂØ]_1ÁzN:txT a&¶M}ÿ‡m™’&A‹(K—3«GÔ¿×ó®ê¥§ßdòÉ-×òÔ5þ¨¾°@rôª!J-eÕP¥m"õ!^´Ÿ÷é´ç|XXŠÙ¢Ó`MìšÛâúä>ÞíŸÌv]|ÒÌ I-Ãl²«—ZÍÛ^dÑ(#äÊïÿG¸Ž8õŠ u÷8œ-íò:¿ZN´f‡$̨QbL‚‚R»\’¨ÖÔÞ£¾)c_u2¬=D›¯lBW¼‰”Ê‹8HN¯Þ-¿9*¶SL¡Ç؃ZöœN«$„P‹}6î›U†^Z<°A…ÒJycØ€î12äÌú¥ƒj30“¨W ŠÔRfS\ ]鑳ïg®ŒÝj:Ð¥ÞVÍNš ºÂ1eVÑÎPZ52iœº²Qñ¢DØ(“Þ=—EÍŠö‰Áa–%2/Nÿ²r¢ jûF|¬ ^ßÍ’[˜Ì+pü×n€80³¢دñ‡Œk¾Ùú¿úýÓÿ¦t•¢…˜RnëW†;ÚEÌk&i‚ùKÕ¯ÚöuÜàNOž^‡O;ê•2êdPöͶ^.é0%<Æq’‘ý«tSy)û¬í—xîÅð5²®U'ÿÄ 7PmA[%ë%uSI$DݡȚBJ¿^èÚ·!Ö§j¸+‚êóVAàvÛköC,i]`·).±1tݪJsÆI•eã߯àÍçþç³óó8pd™‡ÁdÚ"ý½Fæ õÑ:ÞÒPü¸j<6Á&³Õ9SÕÑPˆÈ â§ÛÔ° ¬÷P²|“àðFÒŒHb¾[ÛI^w_Ôör¦²» …ÿÍD²U˜@«6.±L†æöðr¡šõêå’Ê)éeŠˆNŒôŸÍ“A?â½Ò™·AÔ/˜Ëz¢Q_*ÄÎÞœ¬Ó0å?]]3ó%CÄ䟖w¬ÙìüÙŒ õòÚ-’·:èÄ{!•vµE]Þý9 ÝøåF®ø·- 0=uZdËŠ¡E™|^°CLëø2éš<’Í@¬?|)q“§³Jø¤V_ýàΜ* ëÄ®~0Žàp1 #Àw­|"‘)û¤eZB-k[¨Dñ_†:  z–p°Hn÷Ñ~ÜaÝ4åºJ)©4Pjš[›`çO!†ô<‰è¸½˜™Øæ, ÎÎ¥LE…ôÿ—å7éÐߢl†ŽsÛ"¶xÝ·¸PÐ!Áܯ0°2 v;Ð#Þi:(OùÌpA¾à¨<•º>ª¢“ô´êqdï¬ÊТŒõßÿ©ò‡¤PØfc˜mUæ4áÛÂê² !†ŒTÎê*H´D§U2ù Rº¬™§‘Ó†î1ìü9`ùô}×ðBé} DßÉõý¤ç&R‰á3 QF6h¶¥±_=ë’øRîiDç4èó!©Iô^ïqæÛîVí»©¥‚õ{ùT¾|ˆ $)ö ÝÔ4%]B ÌÑ8:ØßpˆK:s²câeÌÒÒ*K%„D#…Á«\?{GFØ-û7É€–:¬y6EJÛ6]ÛŠUs*ྔ©˜nÌùêbé¸a:~㕇“pg~:€ÿóe.—G÷íš©f¥Ÿr¦\g”{7 4± tˆs•ËÐÃà3WSÿÒVGÂÌ«ÎDm3…²jŽkŒÖ6ef¦ÕÚ¹­á¼8–¥´Ëf®%O¥Œêl|®²˜. .y™˜¾!„ïr|òÑ@{÷¤ %º ±8Ú–øÚ••٢ǞÿÒ«x(ßo+;>h.᜸,m£dïCtN‹v­³Gœža¸e}Z2³k ѹòç3/´²ÔêÔ! ÐzLÈÿp}ÑDÆ]ûȇj­Yînˆõ—>ÁSÙÈ×ç9ê`vFn|Ó¢æøŸî¦r$½„âtÂAsùedF¾>õžSä€D«Sa·î¨1RxÓtt8ш(ö¶8Ú°éÑíê#Œn&Ì ÌªÏƒº€e¹B‰‹°éÊ^_Á“ó,>DSHq܇ ‰ ±Ø!9eµdJi'=0 o%Þ(ríìØû¦ÝÌ^¦ÿÙ½f1]')~΋ÈìåéŠ7b.72ŸkÅÝÐyn¿4ƒR˜‡`yY¸1¦¿nøI <æ]Y†5Ø©;ÝtCÐÏPú-ÚDä§°Ú˜™•ÂOÒåvmÿ¼°1¿7?[!G¸—ö›ñ,k&ퟠ6ßo›Ü^ýNxbA„ô÷6i{ƸqÖ~Ñ>ssÃ¥²÷¥T hûŸ©{ì8Æ“Îç!(D7 iV`iKL =öãJyË73²Sô}¦Nü0«Á_K“zø-‡uÇ1cϵ˅ÅkxÛ;BQFÅ:`ý¡y‚æÞÛÄ^CÕü¸‚(«˜wøŠ˜•ˆé –{´5ºíÀŠš÷ÏËê‡]¸|‰ ‹I—%K´[™~¿:uç‘£Ýd•$FÁ{A ypw·ÑH‡ê ï=F¾;=EÉ?~ ò­‰½²æM¯Âöûûé?ÅAžˆÀÅIœ‡ß£Ç¿Ú¦_#‡-B”ƒŠÄÆg'×X~9ïjhãí³|]äñ ÈJ.ºK´'Bãòj=iv×®!Ï¡¬ -Gâ€âP;Á‡úN'€C¢±>ª|ÁRt6Suò´¹€ÿí Æë,=È¥„+J¸FŒ%ÉPÞ*Ír'·ÈzÃP'ãë<ü€©~`#XH‚/G‚œpþªÞ†¢‰À%ÑC$ªkÖnª9§ýhs¦º·f,…w,ß=$ZßnF¿=Ö麙 ©@êô±ˆî”µö©mL,»sDcÀÿa“a³~$ü>ßIAˆ"›º{xŸ_´òÇ}Cƒ¥ä¶¥‡Œ,È<š*V«dL У×ÔÔ,Óµe.H½wv=®^th†p=}gZØì'$‹l:0×Þ2¤OÀ,XQQŠ O'ÎuŽþ…‘þè ­w1¥ ªHÄÒE˜u±²ŸmZ|æ—å‡D‡Jh{  Aï\$‡~ÞDЬŠ¿3Š‚²P›«I' °dîX†óÓOZiæÀd#厉ƒñ¯2˜Ý~ &Ç÷BVÆm¢ÂÆþh‡íã“‚:×sWÍš qÝ.¤k|ŽeÒƒ[Þ )ÃÚâ€V0NÁwe$ݳcm5÷T¶–]·ûݰr£:à8tDÊ õ,®&£ô'pï‡l2YÛ-g+ ]HÃ[/3…&`ÔˆîªR¶„8'¦ðçà&¢É8V=gkûc&|÷Ó2šÉJ–íì?œF,ÞÇ6­Ó¬µ¯e‹ØKâºô¶!¹ñOá Z7½ÞE•¶~ bÃ1þÈ¡èâBü_Ýa73éòVÊýk")£Uÿ³ªøaXL^“\‹ NÌ£Lûèéâ87ÚåËùD¨.7üÑ‚(ŠslÌûL\éLPµüМ˜Ö øÓ%Œì¾8ûÈ}ÍÅÉö–xBØÇüžo–4þx$zaø8Ã¥1”|OUD¦XˆÁ&›!†ÃzmO,r ÛÛê†u3Bäÿ—ãj®XY<¸”ɼ2uƒa»KízÚËTüÌ‹­ãX:ˆqúkp/õF©rã³]Ø(j Ï—ó\ChÙÇtJñßtËM¥>_9†©Úy]ì2>Æe Wg§@!•šP “Ø÷Ðц¸a0Ú`U¼a Î×$A‹yÉþ]1ë 8¥ 6µÓ0¬=¥1UÏ0º¯´I¡é±•$«¿qlYÖ«¤­K²¬Õ mÉÕdƒ@2m:jZÇZÐûÆ`KL?ýë­Îy³Vv·C¦*ée7i~Kí'>n$—|š² óS®ÄÈïñÃû‹ÎvŒŠÝšzzø¢ðæA õ7i©CÛÁq–çgaýÖULíQys˜ö¯C7­ÒzŠß¸[PÓeT3YÈ^ÁÐ1(j®ü’ÅX³ï†Ö¸Û¬³¦l\ð†Ï"“:¥t`‰Ü²ŒÚínKÑš$cuT0B?­ZÄ¿3¦¹j-e¿ºáVáýM–åÛ@e|Ü…M>o;òÁ÷œ¦8³Ë™sâ$êo*÷@Î*£•Xâ*ÂðXÜBΫ7îð®&תÿegª•›ŸPÍÎÜÑ´~æ™|–XÿÝL¿¡Êr81ĉøÐ²á»¶GÒ,ÐF8‚o1ñ3,¼3læ3â=G|æö*@éâüÝÖˆUN‡‘*R€äÔ ž!j³*2y?Í€CøH ‡xÌôsckm—ç%G¼­°¶vGš?虌åºÑ3€s *ˆ«#P3âB(å˜;ëáüv¹1m¡³"‘oŸ7"§,ÐM]ìþhÊMä# Âë ð0Pé|—CSV˜á>T6SXUXñì ¢aqkæâÐ>´ ‹¼e4õù8Ö³I}±TK2îvÓа” Ô3H¢5-îCŽWªÔz•ïéî9Æè›ÙºñJ÷Ú)öÂìO$;¨[²,…¤š¥d¿è{xU$ÁeÓJ¤P[Ýa’ U7° n¨éá=Ceb˜~‘¢~ûZŠE…[ëÖ‰1©¦ ”ÝY!.wƒ<\ÆÔh"Km¥‰Š —+c0,Z Ë>Æ©ÝæeæƯJ€ÅóHMá뵈h=Ôûå©GCžeŒ4xØì7î®áªúâñuÚYŒt㯃’éÎBËþ=;)9Pç6({pÕÏ=ñޝ[¼òäï)ÃúÑé †žŽ¨>8“!çÁ”ä‚c·˜èÿ iÆ=X¢+3q<¥ í£fº¶vä¨ü,÷{‡™+ê7úغå~?¬“Å#fOÉZÉ£O‹5ñs­¿Mägh“û3~bzŒfø®RÂ( ÔÜÐ$Æͤ  ”Ü=¼O¬ãìÝ>‘üD¨,£ü™»ÃOÒJÅÓÚÅ{žéèQÈVùËX_Ú8ñ má(î `— Ì ä!cn¥_6BÞßâÔØ¾L&4øÁç&œ%ºûÈÆ°»¡UPøiŒäõà¨ûkOË>gäR¥cÝ ÉÛª°9¤4éB‚%À„?> ý Y¨Ä;_,}¹Œgãÿë8ëåm0Žï LÊÈ·›1üHœT.ŠÚŒÂñs‹wqBSÚý ‚þ ïÌõ(—øCõ_%`Ê&Ù™£*dB™´Åèl°c9#µûV°ö‰ñ¶o1I½8ìß­Œ>`u1Ðt²$™¨yèmD‰ZÕªKÎ_¥Ø‚ Æ ÉLgãWÿo›>M7µ¾û ›öhéÁëåß~ˆF“‹E"y,ÄSçYÃŒ[µ è®óé¬kÔ©A×gµ}õ·š=e¨Î áöü¸ºÙJí•éRTÉB­®ÇLëܽ}JÖjyr~ÅÝë¶hãî 7÷êcýùþѶ÷³4é$Ú½®§ˆ¿›—TVnJNñ“ú­ ›ïÖ^?ÍNb›¯NÀ"ª>£ê7Ï;¶¸Y·ƒüÜnRû"6dØÝ»²„-Ž s¼;Òþ´áZ-·ðéͬ¸Ûûžú€:îq½Î=±†Ë_ô\µž8ù¹”­ÞZF9q_—žš&ózÁ®‘úV6cäɶóÌï±Y»SËå%×3ÑÓe"$ö[ÎêþI[qšƒ#Ÿ 4Yõ¢‰Å÷šyÚd˜f¡z„lçNB8'k³_¤s5].Ir]ïòDv@D7Ú4tÆ/Ãf{:åè ®Z¥À•<ÒÈ®&h½›œ å*Ì؈%éq­ÚѰZˆFf¡ÛŒ3^9‹×›AŽ‹fOYÛ¶ÈâaÅQo&Ì,?°r݈4ˆÓSQ7äæDiƒÁœVÖ™Ï2ÄŸÜL&ˆvaJ-ˆi·¼¬˜ 2(¦¾0Pë¡®JD焬Üi†ÊïdÂò5¹#îÞ‹°;¸Âޱ$€4~pk(íCÖ¬)ˆXð|^ó6Óªà­Ê޲P»G©fFƒ–]=hð¿ìÓ­¥\mÀY;D®ž7õ‘ÀÉ<¶x©_o°Â)­ŸGªå_¤5Q¶» ,7üfE.ßäàˆX·Šú3½jJ¢h`ãd)Û¦a/19† ô÷ºw¸®Þ>v>«Ñ¥œ½õ3°„ï•­xÙ×ÛþÒô±’ÏA†¥Ÿ=ùa⸠ ¾¥?ÿß_uŒ>»ö¼ iô£Ã(R(ƒ%7ÆŒªdA9½„¸3÷ÀmÇÏ&‚&i¹Ü•‚:Æ'»n-ïÛ ¦ É—ÒL¸àLº7º1<>UÉ â 8’Íî°îsÚQo¬Ôi}õkj×GçB¦0{ìúÍ5¢àñ‚GŸ+neÅë(ðqP&Kò¯&Âò¿ã¯–ÿZs3/ÊÀ]…ñðÓzxæ—(W¡ñìzkDðæ˜•>¸äèºøeáµø¬ I‹p°ýoñH®dEMh ð>îÑp4Yiays鑲dž˜*µ²L8}3Ó¬àŽŠ¦)@‘GLéȳAJ•„Š<´°9Vù˜BJ…íhÒàå†V³ÜæÁ·ŽñO»â¶pt ÑëÐuB(_[ý¾-Ý>¢tzIÉFÌ\ªB†ä}Œºù÷4ó&7æ¥Ýê9XAÚíÑ”ñ"AstÙçØÑüã:5(„k³¾ 3ÉJª§ýƒnér¦’ü àïÖÇÔ¨mû»²ÚÑôÃK +ò=&Ñf· pb©9A¢ ^ÑÈ¥sPvw³ÎŒàf×6Ô"]BEWHƒ@›jATMHa‘åRt]`¯bÔqï"p —õ2òAÇñ¡‚‘µ'ÕʵV WÜ€Ä@ù*tSÌÍtýÁåQr¸†zÐx¬ÍwÖŒ’&‰µ[ܻӶ[ÒÙàe-èš=wWúÕ’Û¯«yºñ oé`‰Æ Õk²Í¶\Ðu辶ì#AÛÔ½n€ôÚì×µ®–"niœ*Å n'ic/ã~ÉáÖª S±‹Ð1)Ø&HœŒÖ½a ÷WеÚ4Ñ/£Ž£è웣ÁÀOHúœw£ío‡j-®|è„þZQçõ¢|A’­6‹èh<7‘9Mí¨½’](ÀŽd¸XR ™K„Jˆ=…²8ͺy{̾À.í*A_c*ÙuôFã«j‡Tå{®GÜomãHá¯N[³øý½-n$ÅÅ\D@RhOšx›ŽúõÇGÆ c/àøô£éMaxmýÁ¢—GH’Z{‘¡%²Q‘°K¸Óz§iN "±À—åyI|^I@ÊÅÜ€I¦V`¯Tqõ·™¤: ð\êe…£tÅ60_Ÿ ;¡kgÚ‡çbÛB‡54B:­Ô⓪€(¼ïyYt¸et dwŸ®ŽØm]*VWù6‚J”´~Q.ÁI”—ËJôu3Ú•hzÊ5ÎÂjë­&ë‘+3ÓjàãaÖZ†Û0óâx»"_5b%/¬Þãƒ4ó‡´„d€IÓe­F¢‡ÀÕSðPþFU(:È.½zø8¢†…ì¤ò©tÀÑv¯ü¹µ-sòËÁ'$ ~·LÚÐåNûi7JO7ž1ñ“oÝjîq¡hÓt÷¢c~êGu¨ƒ´¦°¢;‚`†ÖOT¸¬aUÊ?I Ë+ôÀ˜cVÌ 'ê`‘5?‘Ú¬) )ÄÈl–ä¡ÑZ8 -ý™y©aqªUƒØ®[ȤsŽ"û%Gz7Yª›uE*w~¡Sˆ dà¬!xŦÂÞNx°Â4}<$•m9D} 2íQ úÒ¨oû%Öñ-Ó°K/n£.M˜ Ð…€‡G_³”ħ§œØ_I” Î»"v9v©'\Öðè+àû”©‡¢àÁMÊäÖSm*TI y©Ê²¢üAtQN îCîÖÔ›fíTÉŽÓÉ·5q«–œY%vÃì‰ fœõ„òî„!·t6Ärloé²C~`f×ùþœIjá8ó¦Õ¤v|‹„½0V«ƨùó?Hgä10Œr¿iÐè£åÅ¢%²w¾²Ðº5N„ÏO C• ŸNu¯7Ãum†}k7³ ßR›°uŸë•p6‘Xñåï»ÞK ½Ýé ¸ì‹†“GKsYh6J½ÑŠÅƒ²ò´A3ý=a5ë5X{–h†È]é— ŠsÊ *_)±v4% ¦k÷«íoYû0ͼ… +*‘ìI¡·SàÈÖ(Ø—Ü žAû…Äc‹dà?1È •†BxI» Ì·ùµö4‡zDœ·óƒGv½øé-Š÷ε|CYHgºì WÝ@œë-_÷Àõ Àï‚ô"óBzi¦Œþ>™š~avjç÷+RÑ¢YY …õÙµ4<òIvKhÁ[ù´øyh*IíI m˜JL¸V,ʃLJAUïv ‡ËÿŒß,3Fç,«Õ”³#ž 8ªzíN>ÛXŽ÷.:íÛ8Yåºÿÿ7òÿˆO2v¸#3>|€H)}ldÂxêA¢¬ÍœõG4'竆q|!> "öO2Cî`¶z¹ßÆ Bul·ëâ)”ýcÌCǸ\ 3`¸²Uè4zî¦?- tOÙ#¯ «yDGÓ¡ÎV7»²gHÂ+ý¦ÿÁ¶ÐL #‚åžÙAØÅ©ÃZLK—Wã¤g‰`1¤›”9@¥dBozX`xƒý¤•s¨œèØÈP [ËìœÄ„â8Y;ã›íC±¢LRrVè]üžGèdp¬ ¡á¼r¥þXô—NŒ–d'%ùzx…”µ#X¸¦µ`¥ð²ÕüKù¥h³™Š=»U$Ü€¥A(  "x bµ~v×ÿù#Úª¦_˜ËݲJ :äÛ;º¶G¾÷ˆqë¨~È(ýo$~qèE)Îõ¶Ó›Ü‰ÛÒ—Ô”ÓG^Fµ…»žŽô”yKñ3ÖãªXÒŽÁvóPŸê‡6•@i¾p~¬êÖÙG;Ã˲*¦ÃA°Aèqš§œ3ª~Òâº](V†güÆ)+ô9™ß;ÎKEö›ççÄ]Ý_ô¢Ypl€gããˆé¿e|ž†»½è«ºc=\& •Ðoop/æJOn‡IüQÊ-Òü–¢¬d×òú¶B‹‘É"¢œCžÁÅšòE+—˜_ßՈ뷖ªˆ¶ãÚp˜¢>äÇ=7fÄŽLØp~ó·m¼Ãƒœp¹\Ì[5ç ¶³¨ÁÇT'V úÁƒGÕ>sèeŽZá6ÈØ ¨©¹AM£`˜—0Zí"„Z!ÅIxÞý ¦>…÷^]àÉÉ«šn”QÜ[à@½(iÒ&d®ê¢ç õ6wß´ZÑöê§Pøh|^à¬L/­vB lŽ*‹©ñ¢$ÛPx ?N{ÉÃmå¿~4rEün- éqiã)qtmùJ3và¹õ¿^àG¸¾™Ù&‡¸þ#-^ÙÒñpž£&ÂvüÆLa£<’zÝyž­2%¥_ì3wÕ-!J1}–”AÍ¿ ÎgF$µ=ÑJÄ8—æOXÕºìVÂ6ZÍ{*pC1`ì7"¢­,9ïï‘pÏÿE[£kU °ÎXM ÓCtt ØŠ@E¡êiRLÆ…1Ó¤¸OŸÞk;DS{çÔi\`zò»]ãÖ¦/y: y@?Âéôq‰‹·ùNJ-õˆº‘7YÅs@ë»ÌŸσ:’)qp«ÁÓ/þL`,'øñÅÄ4Ù‹°˜ñpQÏÃó‰“ù>~ƒ(¯VÄíý‹õ.ñ‘ÇïvB ,³…œû¢lôûhaØom…#ÁÆÍTŸÌ~$…¸65“ïiaÒË/Êq „$Ùû.LJÀ);Ô,Â`úHºôjå¦ÃA‚ïJT„Däò4p'ŒÉö‚î]õ¦éÅ2QÚXAŸî.RZÅÖÐßdw’“BÄßÑ• ¾å 'A4‘ÃG‡y+•9Â’Ó.¥Œ¡( ßçÐkïfRº g"§…¡jÎ©Š )ûrÔ-®§ëø]BÕ÷_±èi†U—?`Ú÷–):ߡ鈣bçk«–ŒÛ®KÄ ú=zÒöá…–4ßO_Þ¯Vhó{ì¶ÅZÔ÷B«ã+šoÓU“6#µÂ¦úY þ¸:E6Ï{ªÃgOe¦±w€Í¸uÝ®÷º,K«8àî!Ÿ+ý+ô.ñ’·/™Óuš¼ÁÕ?ÿ]®)§×àü4”Í?Æ Î™>Þ¯@«q)Ú,‚㺂;K™ô¦,Q§&Eº¾xö„€ÐÐeúzí aããSdrÔqÄ€÷ʨ/·Å bÆÒžõ‰_µ-–Ã&ø× ­æBêv9G%ŸétmJ¬ºÊ×ù«›U¯FYD”_™Z7¿ªí׌Ù{7·ìºG^ ¤ñ‚ K0†(:ÿ}èF!R’’œé—p ï£+Ï—ÛìNi¨(wFØ׳5嵸 g\ü¾Hªÿâb ?ÃÞ»0ÖBL°3º…ƒØGLìÂþ«¿A>XiËÜÓô’Iâ9€N¸:wX©1ß×@–7y\lš…3kxxdïـ܌ 9§BGdÙdtñ|ç:Äi(¹“#‘ÄTë¹¢ªB ØJWÁö JrÌÉѺû{Œ öÇ1ð±ÕÁÒ)§u]:z¹²€5s‚c–¯×un l¯ßœéç"/ðí°ºIÉ|ÜÏè ›ç²BãeKÇ[Œ*Ú5³Ñdš’@§}Üjæ*}2ŸðwW]¥ÝÝähj7•b‰5«M€ÛÜ “J‚ÇUJÿzb{ ¼·!ÝmÚî”ÞàqÔWîÝäçe Ž¢Oü·iö!NkäöK¾"i ½rÔ²uÉ${¥c¼H3'|_AkÛ¼':@ò gòT¯œ9ÖLNhåú¦ÑÌX-<¨ÊàQâʇ²®#ÉMÓj»Ÿ-ijù44‹U$«òlÂGåzæf6› Øã•ÑôPÎùÑìü³Éëî™NL- !6t`UM˜Ê© œïKÚŸÐÌ{à_‚w¼vÞeméÃc5' ¹±åì MK{… GôÂzll —V_ 喎Ĺ ‹¥6&( tµªâY ËödQø7;+·÷+ÙÍU™ä6‹‡±ÓZ"`ž€“ô%ûäœD„*°`Ýjƒ9i3sÞÿ å6©HЇçŒð›ÓMD”Ux^Ñ £[`«0ƒ¯‘iÃäó2ü9ÏàÜ5T‚AýIÔ›Ï@’†cï½!ã¹MYœAª­ Ëö°§ºs ljȷ:¼‘úþÇ:‡"¿©qèz’!X Ìà|ÀšJx×¼-FÝë @¦¦´À>EŸEtfÁ¡Öï8ž¢²T$89ÃA©¬îA‹õü ~ù• £g¶ß¾ž}½íB•àkPïElÿIKð[ÖÊÁÅSÊ?+{ȇ­Æ»Ö ¤JÆÆôšòövÅ4v"öºRõ9&±|úN³}†¼kû'°ÿ8È) 5­±§ž4Fñ¸ŽºB—Y“æ»ðüýRI Òãç°¾·œ©íï¸ô£šÌ·O¥PM{þ|óZ߯PŽÕd +S‡ J“¦t>ý(#µ®¯‰ÒG\Ü*ß×ugÅ}ØI0x^Ô¨õ„¤ó6"2¾‰ù¶_â#K$ ±„àêÕq²‹ÁFºXý‰SpOtÄ‹…Cè¥ð¢åýŒNZKù@÷¿j@16ßÄ´^„6]>“'ñ€¯ç‡CÉ}óãp‡†•†¾|ÅÛ™£À°òQkxHàùÊ Ž¸ªõðóXùŠ dO‘ù[¦*|iÒ B9Œç¾L‚ôbØd¦ê4mRýUoD}‚6ô[šFÍõjçC8Fã\œÐ øƒÓq¯JN‰:<ÑôB—¶Ã1烙R4îGSáh¾=d~|zö®µ¿H >ÜÛzÿ†ûaøÃDr^3Ÿ Cað¡BŽY‰X/2äÉþ)ÖmÓ òÎW7ì3½èY3Ç6 5„û€™HÙK»^Ä«·“=ÃÃûÆ×±¥´dt&Þýèм4ødZrìþà™7Vtw(ñ®*ÈàØæ4ÈZk ó½xïÔtáçy¹J$ÅhÞåÒ<`)ä5ÇpÀÔ‰ý¯¹Æ5ÿEÂI~ÔžHÞà*žˆØRvËÜÞH"û=›ÊD.%àš÷€¶;û“FýÅt?¾ƒ¬ÅTì?Ó(ô0@H¦MAî³û—PÆŸ xe`u¬íä °ûìe݃ÛS ü„U%~©4ß{ku[Ùaë3úþ¦¬á4u5ð>¨ÈÈí |Cƒší÷>î ñ“8ï.Qäe¥.GÒéšFr_?ïÞv\Gt< ÏDs}1­NëEñÅ™JjÆÜø°Eä§·’`1Î$ê~Û¿w4½ÕÙ.‡½™¾ÇÍ€Œ«÷ÍÉ•Üàѱß‘ •öÒ¾æÔšúsî°Þ×®áetÕ²|tNðØ?UÒÃ*:Ê/Û8ø¾!2-G×&:›žŠp(g7‹ø9Ä3R?výäÔ¸YÑz ÑRçµlˆ©ôÎûôoLìN‘7h,Y~~ê Î.¹üMÐŒ‚U@¯#ú와s͆‹…ÆõdAØt¶BtV–WÌ;¦Æ©·Ã;=c‚zS7•(‰–¡«Ùv–TNMEÿÂK%3Æ/£eõ (‰pÒû¯ê¾™oŒšæÚV²ÀñNYÁLËÔUJG§µ¤‹ö{çÎ!Ëa+ ¤çÈ=¸B§gƒG®íÒÇwó/Øó+ ^˜zb5¹jj›âî?:ÉR«¡çKšØº×»‘Fɦ›]¶Ê!ÜÂа6õÙ±>ˆ[êѱƠkòµº/N®³À© ¡;“øõ-Á#­"JÆ ­Yk»H’&cʆ8Ty &Dh¤­â×¼!#HVðý‡ß¡‘lr赉 3ºÏ4Áɳ¨Q!Jm©ÜÛÄ3+(™¾Lõj~çéFK~3æ­,)›Ç»Ê8LœÓp¼ùá—[‡±ºšƒ0/°ðz†OÈÄRš·#?„(wraˆØxšWÒÒz2šª’÷0Sm­ª )YQà]æw‰[ÆŽ]Ü`‰²·OáS1±÷Ì3Qéq½ÍUw¸òï˜pKÿ”÷ÕIs—\ªŒ¼u;J¹äTXà™{ÑLƒ}z áó@òÆŸ±"Cïñ€ZPjo›Ç=Åø ¦9"´á¡±iLuÊð$â’—ãx$"X8cœp²Gk˜“9ªþEœi!7Ü×ûÓ€ ÝùáŠBÅ$ã{®åæËz¬õMèëé$Ãш¥ØÌè‰rd3r‡{ãû0{,›Î_•…‡:yKââ]:Rž•ýƒPø‰D3SÜá½ñ÷hº€Y@úÚêÓÊI~MHdê®xeM|q|Œç‡ó’óÛ펶â Á<°7’Èv'íqɬ÷çéR2sžNÊ\ŽpÞŸ×"ƒz4|•j‰½Ë^‚Y$Ù°ÿÑ£>%åQôWŸå¼Ù*’[¡Û›õ¬“dR}Î@@æiOŸvl°ÎÒe{4ü­­?£X ðãêZt·¯Þt+¦ƒ¹¬z†zåÙï_@G^`9‹v’ 'õsÔA6i]3®òÎÌý$A5vÜèåuø]¢J½«ðŸßaCêuž?{v´÷·–ÇÁ‰Rõm°ˆºÍrqŽ,ÿ²‹¦B6Q\ý²ÛO©SgP<ä×p]Lð(¥¬PöÌ$2I¦^7K„±…Bè¨j¥©3Ž´7#¦Ö”?UdÛZÞ'yËv€p’!HMúÐD +笘ܼB0ÙÿWK£P[Dö­t`jî•îC ·™8ûÚ?އzèÅi§2ô¢êŸ·sfJf+Þ`"=•¼”v韽°º¶ZÞ Å¨ÚÉ6(˜¡¢YÆKq£Vpãi]…¡o}gåûýŠûóñý7Rg¬"6ƒ (™5û¨Fµóú6ÞÎ~ùŒóðÝ å'¬ºÔ±6f†[C€šq¢>’l™Ü2|52Üh»ÿHÖ‡Bef¯ÿÓNí&ÍL"_fÂ=8¾ð-OJÌZÏ«$î çÚ¶Äû’Bý ;€ýÐÓÈkí‰?½Þäòxfu §?}3•+÷Ê>íWfŽiר°gYÀ4ù[BŸF&ï¢à1±÷4hÈxåLooI—ík·°’/(^|Q†$x`~^ ÁŸ x0v¡œ2ñ•W)1Nµˆ w+gKÙ£U :Ì9¤FEñmmÙ€ôƒõyrZ©,¯o·ØtþFxìa[d›#>ÈnDAi`‚%dÂðç7‘‹úíÊÔWiž‰ÚøR³÷ÎÖµŒBTd]ÜJ/¨6ƒóžý ÊØNýž³ïS‚WÉNî#î<¬˜ÑÕãtÞ+ò×¼Ó Ff¥Í™¯0J‹™ß“~jÐÕÓ,RŠbm]¼[`0Ϥ^¬Ù òšbsbê3£Pbß$xÍC è.%Л¢1qU~—¬«íNÐTÃ޵ײZ0vûÔÿ‡àF¿vk¦TªA[:]ÆO› ƒ~*t«…Á/zÑ %^;‹>ì-®<—!zùùÊò§£TÃëC"1½ÛkÙÿ|xÈôñ†zV/”E%§ðµÑ:§& ãAzÌvCp8wrÏ–yó•Ãü¾Ä™ /¾RêQ¿£ Ô#„y‚¦ÒÑ:56&pI \²Àe6?ì’¾ÉRÖÌxÐã\Yõ#ép-,ÀnÂö}é?Ô_©×j2nn³hŸyÁáM£$Œð¨ãU?v]€58º­ kB? Ìf€b®ô×Í•õ†gd†dRà°á¹œjêfùcâFÞ¨0ŽYÔDÐÉð7kVIC¼NJQpöÒ©ÑÌ-­ÆXù€74Z$¨±Õ™Ôäpÿ)ëÌ\»ãrÜõÄ›ŸŸÇkÊ™½»Üã·þ™µ'NŸ$ã€Eª¢]ì5ÄanSÑ/~EI¤[?ͪ_a¹’ïZ ƒÛb]*Ø Ëm»év)>o¸†²qwð D¨>xÃȦòŽM·–mh£áköøÅÓ¦œŸçMе脌±í±tÞ]ËÆÑ̽f÷Å4͘[ÝÌÅþh\Ú9Iëy_©^Ç {ÀÀÕÈzÁM*Öd%Ðë6à :U õ»¸„…¢ TŠôϾòoÒX‘?%ç(œdäå?Äɯâ—Íík/µÄ³^2Í Æû­IäɱùCYØ´h *•Büé4ñÛ ÓPÐoQø,æ,¯è“^§Jß$ÅèÝ»¨’ì õ)75À†éÙ„Bí.KFK‘‹µÈ~¥Êë ~(ŠÀ;™ ?Qàƒ—_¢+ˆi¹jG´yh¸®ÖÚV[›ós·p!ö²FP ÷þ”)Q× †$™>é‰Íµ’W^ŸYët‰.¹C6曹qÕVé ahÓ ¸0N£ßâ“õªs`¨ŽñôcD÷ìWd±} ("RÇØäÆvÿ@âÍàš]Kžªtä1dY]õ¯–qÏn º.Š0<Ü Á·oFbë* Á\¡Y »F£ZtZYE½AâávÁm—vΤ¥”È Ç‡õ[³ö Ô Îp`ºù(p.QîÂÍÃþ˜¨ŠÍ+->¼©Ï/ÃK”gî<°M³*o\<ÊŽ¹†ËXóVËÞu´xÄáßnÃ70T7´¶ÉÞ&ÑÈQ& ¹7Û r½ýuýmòx©^‹ýŠÃ€¤·Xtïô›0ŒË63*HPÊÝÑ¥ûymvŒ°ð{PGñ‚NƒSyÚ?ä&K»‡•Ð0´>!8xò-—¨*È2„Þ󵄼b¼b†]†;Šuè; (F»µÇ!Ü<¼(7áŒLi4ÑûH±…ʯ±!Âi Jó3ðÚ‰µëí5?œŒŽµe »A=űë:ŽûÒB2šx©õu^DtiÉYÞ‚çt2òü‡%a•F‘ùˆn>¯ÜŠÏ³¥¢’%DÎ|ÙehÜÏh)ºt©Ø)d%ÀÀÈ¿#¾Æ„¡”å˵r&ØqÙõ‚Ž$`kß.Çá#¥ûQDÈ ÜÄ;øˆA#%kmÝí~`׶б*§ªˆøaK‡¸¥5¬$ ê`ô—Lp·Ô¼_ˆNÎ^grB5rk¾%û‘öD—· †Q+¢âpâ¯ë‰&ËîÑ‚(Ðî:@(õ¦ _½>zʈ%§âèüÙ"Õí°ÈÖàÔ¨mBÿ¥7°}+ôø6ÌÀÛ«þ ÷WªË$aÐÀ  w+ gÄÝ)ºœE«±àY Päöm'Šk0w:û‹×P<ãÇ!F©z0Ý Ëû¶“FK~gh1ç¼pð×UNÌk××%ÏZcßöîúw`ÓߦÝ× "ÒÒ'õ/ä¨` & ã ;A `[ì ‡f½}ì`5ãBYÊ^ËÈ×wqhÏŸðd‘D_ì™ø«lºó`§Qgiç—œoó¯ Ü÷à¾rWUÑCÑ"‹œˆ‚ Æ@IÚTÃ|£²Ò&Ίdúõ¬ý@ÓçCe%ý»$ŠqNÅA¸ªóèÕƒPßt¯tÕèÆð—ƒyÓžnjê9K–ÙkßÏû@ö8Þ0=Ö1,Dzy™-Ê¡!q²±3Ö‰\ewuC$±ɃÍ(>°°Ò TF”"¨ÿOpÙ„¼pÂ]­§ V\?@ÌÌÔÔ\óì>Û?VH{XùO¡/ÍJü~¿uÎïyŽ sxΤv4Í¥¨½ë‚aói3ŸÜ芬…5D§Áòž7V–\ëpQ9 çÙÂ[[õ3÷ÀßÏq5Ê‚.Á<éù_¾«¼ì …rƒcÌ6Tlo5ÀXX 7Yû[àÖî_½§’Qg¸„hæÓÉi˜A(øl\ITÊHFQO\VœäùYÊ)¿.”áÈÊìÚËw;3€&¸owðØØê% þr¹{Àê‰õÂÛRµÇÕ½+€°HSÁŠ˜Nè‰×ʽå3õê» \N9ðå²&”ö—³ž¾•¹½¢µ I1ËïC5 '+½ÁŸŠà™¼Uò,п•cÇ YÿÞ :Sèyè¢@s9“‚Ê´ÜIÈ|©©µ\’I|–P«oŸã¹ÇC¡y!idãÅúO36E9À.RËjo;Ú^"/ò '7ÝÎyxmž=Äw€Ù†6- äîO ãon e™Þ ëè]¢ÄG›ßVl¤OO€ ‚g³÷ÎÁÅÚákŠŒ¡giæíÚ´úïИ7–ôyy m[,þ ̹àÐéÑý3åÙ7äV³ É‘_Ç,¹>Åð9u—NI¬4¨êÁþü“—¬‰°‘f¿«¼"!x)ªž;왘Ülü<ëi6ŸGÉC˜#6ƒFñÀê»Ó!  é©žü&Ç v¢feuuânðS }ïòÚåV8FŽ´ìëf;“U~»£™qí|Œˆ£ÖiòÈ9è?1(ìûs¤ÄÏM¼\`F-æ¾|9µ]P¨oaPùëõsËê±B =˜lî‹Ó±FGöŒäh+<¤ðé˜÷¨;_x6ƒA«>‹éÓ-§êvr#QÍ꣑]˜SF‹uîã<Ô7éËéQv›Ú®8–ŸÅ‚4 R̆„7”IÃý™%È{¦jàÆ­¸²•¶U[ý¥ÆþèǽæÀž»ôÓuY= uS™©ùž¶¥tO\kÍ­ƒ„ŸÂHÛćÀ­¸r´ú¤¯Í3hHþŸyÞ4õIÛýË$ÿi¨ËÔc7‚AÞ¦ÐË-™\)Ë*/ªœ¶þ¼‚a¢› cA <Ý=°£ÿ©©ï‰Á"±|gVB(ÆžŸÝE’Øä-Uâ ¹¤…]ÏÇ ݹqMU\¬Þæ‘Z¾o(Ý…â†Q>°ø°±¼$ªûÝD ÃG˜¼öНx×ÃQÈ6¼>y4ú‰y3Ÿ)o[z•,W¢^Â+Š÷-AñU¹~þ00Ö'ìùž¨g–2,_Âý܇–(ãy+¼[sžÅŽwͤ "‚Ùû^t{™³)s¼µÖ·NR‘Åeû5K]ú»7³—¹ TtÒPƒ›o;*^)¿ÓeÀ ¹` åàQ ™/8.>öÒ{HÂò»ÞKÆ#D\ñ‡MAø"Mu‹®U½”š‘cçFV©gOŸQTjHÎ3PàÍèó@ꎈ —Œã©Áòœmª;Üýü2Èf–ÕÕ‹LÊzOaY¿(š9wÜ„¨ÅÏàé{€Ðàç<¬íéxwZ6/‘c<¦ÇŽOZ¨ç½"]òh²cOt W5Õ™q;à‘‘þm9• TéùTaŸ RFZ²ÊPØ 87yp7„`q¨«¯’àlùøZ9+há#ºEéñ(» ‘¯¼h˜®èœu´Fâô¢Ò£Ê¢*Ì$“¹'w@(ÒÇ©ô<Á£·E^,¦„Ü‹£¿ÍÇåÂ+-Ÿ&#æHºEþÏîA]PZer%1Ìn¬%õ7冠bºp ““}µ¯ùAþ¦Çò¸5W;ƒåGAd;'.Øoö[øÞ,®Ñ°:yçÞÝV Õ\šm¿N)â'ŽYÇ}pÐ$<ØÜ…!ä?sÆ™Å_‰­¤xÍ9Jø¥]ÔÞ¼-øÐS:õÕ“w»ŠàŸ6PñŽýZRù(¹¤ÎÜÆY@ЧÀÅî Cz(øVfHïé]~¢+úñ粎3úOñfR2rv›6ºi¤[ov0\róyMpòø®6¸y¯¨…}³ÍÀÝRO•µÖõÈvL¼†&°€›ÊŸ*:’&¹Beg2fýótQærv£¿äêcY£†ð‰›bËiõxa¨—ï’¾¹•+=óÉ…‡•à3Sv —*°ˆßM%ð“¥Ô€›¸T¼ì•=¶p,-;_fåå¡cè‚låªK:7êÂ_ôÅB@”6š^Õ>—2·ær.ŸK|~pKÖîGàBòœ×KQHÞ¬líC/‚ì.wÜCSűG@RFf»}Q?Y ¦ ÀeÜešbg®®RÅ'U…w‡¾7Uœ…G4“âçq  pºá&:ô|ͬNÀ_IÈ nîF^3Ï^¾:C ô2Û&º(ù.á.!G8PiʹÒlUúßUL:Ո蓰81K7ˆ,­않?ۙʷ¦ñ‡o6í^ ¢Àºg«3ñ‘öFƒ6€¶EŸ ¤±·åô¸e¸8íÇJÖY^0‡) "HÀÞèuåëóÿ™Ì°Z¹²§¼ý£Úùýß…:Ÿá Åçfwž!JZëêoShëŸý‘mOïÄwdrnà–-züÀÛr¬Ø?ôFÉú rç‹{ñ§z7¬ ¯¤=ïgNZtÔ°_,þ"å#í5µÛÞ Ã|¥å‘ŽþŸÞ‹éütÐÎ ®¸22@˜"ðt<Ò…Ê6ü5pôEOîi± ö SŠÙ+[ô›:Õ’êvul/Ùgk½Xâ>ÞM¥šÅálçeˆ“0j”¸MÕgp“pð…Ñ¥ç]1Ìw#±ýhæ¥P¸·¸(ͯÃÏTèx«¦:¢4²gDíTñóª, åÑùtë Tÿš¶ÿL€uD„o°PÄÙå"©¨cÿ}B/›O·]‰^ÒŒ †WÖØƒD~Žßý‹Êd¤õr à'âF‘³ª÷ݹÀ :lÿÝÀî<â§nJ\±f¯òyŸü¬>kß ±½îìd'3ðTô¼wwV§!n³(ëØšgƉGæX] qf ›õ1ÿ½øt—Ýû4%'¨2Epœg¬~ߣx!1þ(oÁÅüL7Ù‚Dš74 î¨NpØ|—Ó ç5*ÃP«E„ K¨ƒÿãytÝ+JêyåNð>^½chІú÷®’=ÐÛˆÖ¼&©2þF§’SËÁ¶•Èn€TýÀñeâzsÉ BÞ9ƒò“œsctáÁæqM™ê0_›É;Šš½'ÄÌÝmßБ”õ5ë”\Rxüwm[3¬Œ?« ²QÉ ‚ç ܬ¹ú¤S-Õ_„É4È%°ù7逆 åÿÐV¥xA ü·æàÿ&o‘d^ÇÌT[O¢³‘Y+=~Ìå°†0ŒAv[¦ÚÛÂ%Þð bŽPá.õžÊ÷Bµ§YTÆJÄL2£=¿8@ík+ÎJ(ŸÒŒÀ,ˆºa µÀˆ>¥JùÉÙQ-v~E ö î-‘hºíl nÙÝËU“ˆM¶y,òÊàì ±\ð£Q6só[ˆQ‹V›a/½««„{þ<èZ„};g,4Z´Ö†÷8ŠÀçŠkÚ“ˆtBU“ã}Ûi%úØT•sår¶#é2HCÄ!{Ž|Ü´¥NxµAÐDs8j-§5Ñâ6zÚ÷ÛøEõ«[bõÏæƒ’xgÌ$mf±j=T>µ"!^Ãt˜k»déôÜ£Ëa¿ôú&f~ØÃo)*À¬þr°0‰›•Io _ç<¹ @õßagKã;TG×dGµÊ&DÈ›ÒQ€ÂŒFr;{ÂõÅš]¡xLÂÔÕ/_RQü« ØÀÑÎ]Æ›„–PÊêcª;”Ú’«ôª±ªq²Ú5?¼„– êw«,ªGŸ£¼ùŸ¦NMhŽû/VG?kœ‡Y½Ðõ,ðˆÔtRWåÓU>§°MrÓ[äàK”݉`Ž•Z°½Ü]3žÛŸ$4j Ž\Køµ‘rg!Ä®\êM¼«˜P‹âNâÔ[@àa/åêTÙ>¦{y›ñØghip³£“4+ºÊ´á†CPmR÷ ‚õ‡¶•²_3„Qgl”ûÆÎÌFAU]Ê%Á ÄÐuK"X·MtÉ¥i˲ØÜ’Sc£G„#Ï<5* á÷KÉD‡Q`&&ÌC©ÅÁG9:ß86ö“¤@.‘IØOÁæ\jë›DãwšX®Ò Ž]Þ0ê¶1Ñ÷˜‰t&ϸujþ÷˜ã@§àöÝ`È´ìiôšÃÍ .+QØ“@Ñ™#ü‘Pj'ÇãFnܽlËÏ—ýª>zdÔâ3EÔ[#Íp4@%yèΨԥ“Ì6nXÀh,Ólڈƨ`£Fã}f¢bŒ”âZÂ[ÔÙ /,„f …Gô ?$tøí¬Û ëç¦Ðfíṫ‘¯ÿ¨wÛ‡KÀ’Õs€?Z’©aÈ{4°)ßBUˆþþpÓË2déaÖ ùqò¢ »@ þåö4\;œÅ^I-{Ø b€C–¿yoUñƒÀb±¡HFbkS$#"2Ùi¡•RuJX=y _H€0ÎN4 –tE¤ƒÝ£€Ž$ãÕƒ†J¸ó¦†^9`ªÔþ­À$I ]lý/$ÜÈ¢C àð!ÕϬlIÖ`‹:Á+ Mÿº;• tþûŽ_X¬ Ý ©bË ¶ó«é7/OWÓYWw’²Ä€¡ƒ¡‡dën¶Îw}nShö~åiWGöÒ±|•ÏÉ®Kq¢ˆØ}¯»}â€j Åï™$&^AsË»6s‹¹ CCu’yÎ9Ú,²àÄ 0åTœõ5û)iƒÜízó©œØ7[X2önû³¸=Ö¢&Þï’1KÊ4®­ Áñ†³k.B_âP;¡:§¤¸.”ú_°J¿Ãç"Û4Ÿü-ƒzå|…vØG*Ô:Ì©Ïx4¦Zc§L¼žV~¿ÒnþÄAÝS{é-¥ÚÝDA´Â(®UYùVÊõ{eŸ9¡ ® Gù2ÏYÑî2[v¸Û1ˆ|æ¨X8á¥Å0Obdç4H¯žÝÊÅ>›”Sse:úQìÞ?+ŽZSDèŒÇâ. lûVYlÎ3åuÕ@ÃüäÉx¿Lqô¯Ì}ã˜$9ýK𯾎®-ÓÓ‚Dx&C§óž†É?® Ýý"Ôà€WEo {ŠÇv*Qöym£…€ÚÉNßÃÆQïù‘=Î= ÒŒòP D¥“韼.ŸËDT–XÐxÅs^¬SRëE>ÍÒ£36ø2%„EÅDòÒ:g  %h‚ÏøÙæ—é?M(À¥â]e+‰|ÙÞÿi™l©#nËL¥õl§ºå´¿òã0ÜåŸ;tÃ^¶­z—Vq@ ù‘ºÒ &®vÂÞt2ÃkŒ‰íó[<ÇåîÈ×½d<k׆¥ó–†ºZíŸ Î$âZ¬ÿžRõTЄf¯C5l+ŒÑÑ}_ýg‚H llB×ݺ/â-öÙ1ª Â¢ÉϯC:h ŠœÊØG ƒâœšŒ-öË]‰5øÞ€ëw;¾ƒ•¤‡„ޝE£ØˆN޳6ïÅS침{\p©íz:ï’×Õ’¯í¶• yîIåU&cñž2ù+¾1_Ë rÜaó¥™&S{89µ¯/:j¢g˜€$Sº\5eå\h' ÓC2±þ’ý´6–h«O¥Oo˜ ‰u Èz²i³ô•Í—alÔÀï 4ñ÷ä—/ð¹;‹I;@À±õÇ[ŒFªê DtŽq¼á fOÿkÊ ª1´?Æõß,TõÖ‹BwÞŽ÷‘Ð[gÿ¨Ý ²ãÈÀQ<8b!¹¸- hsc¼IÚ{xÎú4ž¼eÈ‹%OÊŽJDÚÞàs¼é6¯voø”?³£RÓ€Š[µ˜Â§&Ù½¼mì„4^^¶[úéä¨00‚ ¾Ñ¬»j•=šÔDrÖîŽ Ò E+vT¼ÄÖ]¨5Ýxv<ÆÀ-_1?_³Ú{}£æ]ÑÎþH^‡ÊY1¿EU×Jy ÓEÀ'#P]ÀŸ‚û$°"g”ß²9ì*¼ädÒÄUŸ¹tãÐÌ݆RÃòMû·ìúœØ± –fÌÅiJjëØŠË=§·…¨.‰ÿcä o’vómããîö|®-â43ÌŒ$£¹ä!ŒÐmÜ^R"h‹äMBþb|w–$¶byçîE EÅs89Ù¼eKñV(t}¤{··$‰ðÕÔ=ša_Î>hÍŸçw uVw—¬í½ 2Q¦<+ÓsaÑ-è`•Îvs=Rýp.¡>®ê ÙÎŽZ”¾—¸¼$Izm¿%4³÷õôP%ÚÈžÃ%3ÕÛЗFP䨖•œA¶€4%ÎìTg6š­Î‘ãõ(W{Їi$åÜ“Zªšæ¿ v¥gšSv$ g346+ÐêbAwàrÿµªRÅ?ÃXÇrÝâi V™q4ÕÔZ|í~­Æ@éE7½VCŸįÜ÷0?u ~ªhÿâFÚcíÁTo»ìøÜ\:¤&„¤H“Î÷TÌwG œ‚QþKßÐÃà£| Ù$¡Ø;{Ťޗ¹è3p¥4?¨òVà çw'å›éŠü­¨…¿ÒÏ®p "EÓ »q„—4{9æ¼-vmú[:n'˜*A=ÂŽä;Ü<Ð{#Q[¥^wI›4š¶”ñ¸õÅ!Çló¬ƒÐþUŠ>à´Vó){µ]Ü ÍŠÜ’€!h£”7)x×б«3ÂXî¼c2ñ4+·Á#Äà ;¾>Â{bšNˆ‹Põ´­hG;ÊMMÒÓ};3íº'xô W¹«Æ.Ì„Ac”´ð§ié4B†µzGÂÙ\ Ó9äÙyð˜1’'º1;Åû¡âÄÕȈقdgÈ¥àP51ØOM$¹ÌóNI,ö®5hMsÙÂ6¯ÚB‡•`‘Â{¸¾Ê¶ãWQ€ï•½ÃÿèÛêKáÐa;9úøÙ@lÚFabï BÙ=2î>þ ê–•ÀÚíÊ­ŽÚªÛv|ôÂßÌ®ñ‹Ê-bû…‹. Q#sç'¼Àc?SÍüå<³€HÙÕ•·HXŰüQ;)6¬þi޹cé’aPW•¶£@émˆèDm‡¹"ð®r äVçñŸ]v)”4{£Ø8ÞÌJ¢Ië“¢ø‡=v3orjôÖ¨ñKØ0«Œy7'ŒØÝEhŸíä5¨iU~]άdTí—@ÑŽG[¾nùj†4îW*r«Yá#:ÈÏ×~ Q¼#$öÛÊH”“ 17‘å×ÒÍ&iôž‰ìüõ:ÜgÆÛàO*(­ ¬‡üN뜅Nõ®½X¸*u=5_uOÈØ¼ì|»#H‘Œm_q»ÀõØOMåëx[sZÐÑö Ù  #ޤ?Æ3©©ïJ4hE°xßU¨Èö¶SDˆŠ?ÏõûO!›jyõ¯ ä£ëxBô«ÀU\ZÙ÷iv¾q…¦5Ã’t}‘TG8'„;ÿ¡‹™TÎ;®ÕƒRe§¦qY«k½Àަiøj‹”p”Yè¯x!&‹ÞúŽ©YÒ8•Zç˜f…`Íà ­cŒ±W—@j²žŽ4¼©¡;.Šü„ Ò:Y¡L'ÛöÖŽá\^ÈD èóc}q9âË·y®Õ»®»‚´ _1±gç%A„/mytZA®I¶BŸvVÝ3WtúD©BlHD•®ÄwjÑreNX¸Ô®mÝ_ ý£õ°â§Ñ/ŒFC¤“˜V ´Ÿ x ÕÔ¤k~j€ÞR¸It*©þêôà€…E¼±¿°ùðË´ý/£çA&©åõZmIf³Ì´áøGd”/ ë&içâ{\âO%k?Ì:È*ŽÄø½Íøºàãð<‹„¤ˆ²N–~'ÉA"߬aÕ­¦n‹T²jZ— HnçÂ…7ò‹Øg²3½Øt¶ÓŽÚ3wPÜ ”œ[¿éžPW1›®ÿHáøy »Ië%c§Qk˺–Úµw¶“ÎŹÑû6\Þs´rÊ€öpï‚Ò‡ò.ô„ª9z{¼Ë×óu~êÐÌA kD¦v©Öc”¦{iST³“ ’pß듇v¬=;2½ydFyN/Á/‹½îŠÝwF†î%Ú´E ¿]ë?ª*"õŠéEŸÜÁÙQH‘¬à*©ÅXȲaÉ‹6T®–øyœÍŽ?y€Þ‚VA‰¨kE¥8ïöü]Ù²e?‰érÛ$îl'¼“H+¶Ò¬ …À:Y\,#¢]“×÷O´ f%T"ˆ’¥:ÿ´ cܹܔ9»ÔË6ï°xˆ+én»3SÓo”håÏjÍ o˜U·Õaõ¥ß”b¦Úc•‡·²¨ Ÿ2Ckö²Z™ÔÜqõª–*Ò„” ÊZôñÑrQ)kñÝ‚WëY, è<ˇKïHÛŽÄJ•Ñ´x2gìP¼ xØ&DœÖÒÎoû7ïÓ9Îu¾˜-'åX²(Õ9 -Jð$P`%â‹!Týa¨‰ a î¸7qäöÞ6©è¶•ûƒƒ·Ðº"«Ú¤»sd™àðÁZu+úq°ÌqÛ4¢›%M…é¡ò›Q[dð€w -¢|£4pÈ$Ù;,htpXº9`µ«¤mû:“=ì³ÖK‘3BîNöp•¡õú6ÉœÃÛ2%TÃ*7Ò|œµÁþæ!¾ïÃ"L‚ÚzþÄCAÖÇ­[4„²f®1'4 dŸþ+ý"EöÝʱ•]ˆ&ûK€e`¯Z['õ%¥–»¼"` ÍO &oâäÔzóM?´‡dJ&Ñ·žó;ž?ŽÀƒí/n[TȸP,Eèõb¨õƒU”P¾Îmj±îz{ò£l5?nÄ)Õ_:.äßP`}„pÀ’æÏÀs>Ö$-ÚÁÏkµ„ÄîV˵ûý GE+=r^JÕll‘Ýx1}côŒóÂâ æ[Eÿªß€|øÛÅúWIç&—2­†¯Èïµr86¤˜™v òR`xþ²l©¼uØ”×Ø|ÎüX yF›ÖLüua²É̘Ê*OÔ@_Åc(sæ½:ÍÂñÔ¥þ¬‡ú™~T†Ñ7é×<^ UÄt4=ÀÏYIQ4D1T‚Î¥¿}PwÒWåVT•2Ж"΀œD@­ý0p¢Åå )‡ù, ØP~µ5œ%lfj®ß†›œ ´¸+/ñÌ•IÒA¡Ã¢òÿEäâ²SÕG£2bâ†vûMî†!ù=û­ÀS; 5Ö‹eaÞË—Èe-ïŸ@ê¿Ët‘øç3 ù<-Æ4ñü3š² Šù˜IJ˜ Û¡£4tþR}—´úá'†í±³y‰OMêÒÀ\¹sƒ­,ÐÊñUƒ(DÜ‹ÿ;ûèfãhLúÞ½õÝ‹¥O²ÞpîÛ»÷ÆïY±Yœ…ZaS×”s0mâúC–YM¥ëã¢7üëE7ßjŽéÌ$¹Kù!#O›Ókˆñ*<…îŒBà X ËìšËÕIr”CMú¶Ï‰,Eÿ–wY„Ï?t"AWXlÝoµ=¾¼#÷Ìi` 7ù‰ \ÄÛPϜܭ·X*ˆn*–m÷Äì™a#Ò!‘ö^e‚Åjs#í«ù'ß0‘®FÜóÖ@ eî%D#ÉMŸ Äa«êª²[Y¡àE±¼$€vQ»:Dxe« ¤¸v¶ ~׎ÐâÏSG¯ùvÎTÞõ(¢Œ %·=%ãm°ÎV$×#¼ˆ‚|÷™}V;ež«ÃÍzl2ÑæA&GšéhE=î ¼>ý­ñæ"»°iVï=Ÿ;e—Á'[„¥÷32Ë÷×›ÃÂl+‰ìæC‚kðhËà¢ÅuþEᎅeRg#ê>M`.á±zmص¤¹Jö"§Ìb}?_§¦Äü0©XžØØ{(œ´î.&Û¿;6íGZ&$>Ý·_í…Qt÷ÛÔ°wùBU¿Òõ}¿g¼ mÃvêÿä‡ì(† ɶlzå"”ü¦9&Îxhý»‡còp?ùùnp$ÄÍ7Øó*,±)]?™ß"4JÈ}»tžÝdÂߦ»Ì¼7ÅÑI† ^ÉG?;ÖÆQñÐ ~+‰Ó qºÖôEvÑb–§ë5bœ¢¸$"3uK~ï8xÿJ¾](_ÐÊ\˜(|OL4JŸ$ÌFX¡ÒÈ¢~Þãu)˜8ëkîjÞ°`#·Â ”'v—D¯ÿ2دí^)(ò°~Y81$eeà€v«ëc¹œÚ2ïÅ<‹ì¼nC‡{Õ{·¨a,F[œ)ŸÑ÷dúQöõ¨‘o÷ÝQ4¾éÊO÷{®ŠþÙ°X§<ß«l-þ!ÄYíI:Öô®íé¡Wíà; %ö„Þ¼#‡Žº ´¿€N-רL«äkí£7j‹®ÇlΪpWþ&U>éy>Ïç4%Š­J§­Ñ “öœªÄ™íi“²yNj‹Cò0ج6zXã¡»km(Šä{D5ŽO(¶QŒœ×ŽÔ(u ~BHD«V»Zš û@úµ6•,b8¤¨õš%ù&ý”RþH^KŠä?7¾ôâ“„ Œü|er{êá·¸ž7€Ú^…Em)?ÿ‚ Ésüî›°'·ÐŸ¾,‘‡a²*ò} Â@ È]§›H ß>Ò¤<9—2"mqÑilsàÅ=6u¥ŸÃ~_ž 4ñ¨Ûßyh*Yíé’€ˆ äTÊû¾¡Ô"XO&à9:ê\×áÜïÓ³3DxܼéÊ<¸SôùkKÎzéeçXc!õŽ- WÏ·ìß™iƒÇruq²VâoÈ¥ly×çÒ‘¡Äöâ­[šI¨7BˆÇ[9—Å·4˜öᙈFØ9Ná6D Bt”[›_רÞL8kQÑp´FÑ2’înò_Ê…ð¾3:iSR>Ri”&;{¥”Òÿ‚q5K{Ž&–|j2ÆhqöÑŸh‹ìwŽyªÔÞ!ƒSa5=C†G?Fë(ö­ë=ä·½¿–É’ƒpò±ÊâÍ•q³ODà˜dœ‰.Æ5˜’¾Ÿ@G(zÄ-õëC¯‹3?Œ”Igš¶{\ÜûcpsR¯«Ä–ðh‚cæ{Âh<„ÎÍ0}˜W s¤¸!}®¾M¬´Èp—\™§”Ýøßã?,ê ¨5­¨«¡’L`{Ø‹?FÞ&ƒPL $hÁ—o’·"ÜÒr”“K°l©ËËÞî°}iΊÎî+å (—ßE¡0~=ÜÏi©÷©‚Wó;7²ðþ6/*èml \#?ïq¶¡%|¢ÌbA$¦0­õ=èØãÚÛOS8Ø/á}¢Ž9N.õæÓ‘s®AR»Ñ¨º¾Çs5·%H]áV©Ko±f{n¼Þ¹^æëš”?m^§†T:üÞn­ZqèÎt*¶`…Ï žiq¢.¯Jšh7¶Ì¼vušø/r‰vH„“uùyëeìqÇ/+Soå“X\ò^w‹â“·b$¦»Z7ßÁ]}*ÒˆÍZ}µ²yóÌ/ÄÈLs””ÁÖk)Þ7a’GÅ`Š´Çbc‡hþ(Ç”T_å‘“o.í¦zdƼø¹x¯Êª‚48u_;Bõ6X]ñ±¬¯ÖD\°ËÖ/ÝÞY¬%ÑütiéÀP8t]Àެi(qÉ6;¼ÿûéù‚¨æj…‡ZŸQ:æ»jý¼ü%[4WöÉ•„X&sì4kÒ²êè‰ä åš·p¥\Ô¡¨¯;»Šqáó.zWŠ«i"†2··íì‘¢÷JÇÔ0.ö/KË(Çùô­=a:‡§l¥ŸÔ«jxÐ:2¿êÇrÖBˆ Qk#HCW=ÌÕ`òü»h¿³Aleëx{õ®¦Æèõelßfr ¼¾…±6Ö.ç1]ÁôÝíÁ%ìfü qg7xÙ°¯vTºLö&–UŸÝ‰\ŒÒk.ÀÙu\hXZã¢Ût\öPö®—Ì“}E¹YçŽK°­ãûx¬ˆã6'kH”Úûwì[§›’)?÷–ÆBZjm”èîY¶û·Èïl|¥®ê½ÿ•nùá›ÏÝC[ÓF0ORAÖJ i‹ ÅP#„ÀÆuçSlb®Ì¾‡rˆ¾Æ4…”u«C{>äþwÀ[ª]ž,fêrrå„í.‚³ûpŸx?Hê™AˆõWÍzcŸ¹·™ O+—‹–¸» ®<ûu ^ñŽbåvHA·Tý/8› ¨b3›P-Î2Ô~¥‰EH>ÅÍ1Ì,½2GBkàËME’v1¦1¹~Â5Ü„õcr–°­c¥IªY5GyÔúšéhè’×v,†2íë“×±œ¶–Aÿlõ¦=²! Uñ‚ý6Õ|¬‰‹ë”¿1U–ü"s£ (À PSsÛ£åäÏÝ{: P=`ŒéRt ¦]=À2rÙ§wâN1 ¨"íW‚OdïîËþ{´p„ƒTã¦y¥/ñ-ˇhJ¼™M “TBPÒþmtÈQ‡¾«¥é O™WE®G¡ìý¶fƒµ»GRiÜO.«`¸œä¹Ë‰ `÷ ô¦-¥³œ}=SäÕÌ„Køõ¨âJµF‰ÄA«L}wÿ¬^Õ‰ƒð-ÊÁÇŠ¡Ëñ‘£†Ð—‡‚zÓË©š5V²zéÀ²ê`…±êûî.ò ¦%eÈvÚ«£­†‰œ1°¹óå @aüzã±ÁFš¥@XGÀC‰¶2®”Åàaž“9ˆñ'EÃ=׿ôaç—M'ˆ]šD¾3üKºŽÇSGéªÌ•àà"q•RXý–ÚÀh—¿ýº å5çcpzÜspC”ÈaRÞ.4ý} CÖåŠß~î¶½m¡rU¥S¢ £LÚ;Ž½ÎƒHT¦–ò9˜Ï'Ζ“•3ü«–bUÙèú½4ˆÅs‡ˆåG?)êó?hÁÝ]~ñÕÍfy‘ÃðŠß&ÅP¿T¯Ëp¹>:iÅu¼¤ÍóxVskŽó5Á} ×J ¢u 2öd4þtÖ­ÊRÒ°Cµû3¢ê,t½’õ*Vå¢ëú`SýîçÜHï'E,âK.eTwZÖNûT ÄðζETEvóFVVD\'ak†åfÀ#ÉêL#Q7Õ‡~tk°ÖåZ[}ƒóõ°,¬¡Ä?0ì$èW´Ø->SÜéh—]rEäõcb[q¨^Œ„ÏÃùšŠþä< wcÝçyYûㆠc€,é€\ë‚ô üh­7yu¬‘]¥Õö^A^¶4éùÖ€½!¾ÕÌÑöÍ@*u? d¥íªÕ†%ÀA…+гvÅžÃÁåÆ=xôÇÕŽ§ù&Q%˜[á¯0ÚhFª3UFÓ‡+Wá”›ÕÁCKöƒÒÁÑJñr^.Mƒ£…âê^ƒd•Õ}¬Ñ‹N´—•6&Ðʇãî,Då#rM]]æV/ž,Á¬âRåÁÆ‘©{âØ?Î *GéñÛ/Rê?:û…ž'ÃþÌý"“`ÿª–QŠ“Û'”߉ ¨ªyòÏg­ö¦.ÿhs ®¡.ÍøàÞ²âècR8 ú}¬†àŠ­ûĺ}IÊqnJè!H·ÒÆÐ”ƒ€x6JE%˜ºØe8«¸„k޽¼—'4º×ZH/7hrÒïøáñµÊÛgážýFAña1ªµ¬‚Õ.ˆýå­¹#¤­2ùPüsçÁãdE ®¢¥5Ó‡`Ý=õ¥B«¡3‰!gâûšTÙ´\\iZÞSm\O\H¨uw]kû4¤ÕÀÌw ¼â¶^ ‚cB«P<¶ &L¾Ú¥ã½›)õD)ØP¥ÔQ¨ÒÍמ•-ò2J§sVmHbL@ ÂD‚$¦Q_˜CàÊŽK(# œ7,ô‹MU[ð5¦åþw¨KÁ¯‹øEÛ¹U¶$-&™xíŽ{›4kÔã¯+ ˆªÊ\œ¥eqˆ-PÜ*NÂÃ:2Æ;T‹œb½4ŒµÍDíK:žóÍf[Κzùòâ æÞžõþi®¤t‰;x¾©KnÃ%;úªñ»¸Ì ênMMƒq£Ýü©®¨¶»iÉ´L¹DG)y¤:žbôþ}-…‘#ߌ³ÙÝ‹IMøä¸¶8T (¾ßiÍéÕúd aq€1ƒJ <ª¦îI†= Íö!q·n}ÍÄó÷ €Ê|›®Vʬ{§­Rà-Ìv'QÈ6“BG#« 1rùeh[—e•àL­¿:Š‹”5YdTR- úeHû" ¼Z曦Ý1ùÓ<õºB]¸[âí¯nÙ¿7¸V÷ë‘wèN&ì'ÑŸÖ™WÆk¯ÁYáúÎþæ`ÃÑ!þº«qM夻ÆÁ[PšÊ¤ÞìYžj@‘O'q~T̨v¤¸ŠÙ¦†àºJ{/Óî?WÛÔÌÄV"ç/Þ ¹hiv&ƒàjæmœ}Õþ7Pž {g¥ƒFªëüàWZç±è¦*èð5­þºáµ¯K:´nÔð¦òä0› ÔÿlÕƒ@ˆ†öøSãØLd„@7kµÆ¾pÞZ‡”Rt(´<é³ZœJ°ÖÑp+úêr{HP0:ì)hÚ¾§÷“e,8®ìyK¡Oig™»ðFÝ®ý·,kÕ‚6gŽçÇàƒ!ü{•“NÖÂVª´ ;!âϨ²†ª.gj¢Ñ|—ð Þ!Ú~'€a ”2¹P&ÇÕª².Ú*s´tp©=L{B‚J8×»ø3ùÿ Å’AÒVgðâ7x£{i®¬Íµ‹ø¿•TãS$­ñf0 äLi’!4ç†ÄŒ¨q$µŽÍwE=©±ÑÂ[ oNtšßÛg²UGïoÍVöEË>‚áçÖa­ä¹Xïo|C—áÖ÷I'Y “>yað™®ÕžÙ‘dúªWõ¸1…°bEA+”aÔQÑ0nH¨o=‚æîzTô4(_À%°×¡Òìoueydo#Ç5U:”ô+£{±/•»ô”t« ªqG'Ö«µÀEOìeìÝΘ³àI7[À°Ô×P@P⯦õÇÀ欯<ÓæÛfÉêåæD¶ÆkâÚcq}Í„¸ê2ºswwqÝb1@/ª¹†al‚¿ä’N¬ i7ØG"6’; ÆOHâõ±O%tÅÒÃŽ˜?-ÐĖ٠ѽŠf3 ™åÒH¢B)5Ù+ÜÉܵÁ†JêcÊÆýP» ʼn=ÛÝ5y‰w’˜kÈîR«KÇõoFÉ¢§Q¡(Ÿg»ÂÌ`W¡–i'KBÛvÿ¶ø£U.6Zɹ-Kå„EØÁtKí· 2´êé@£»³=¶‘™ú¶‚ÈQ&¾Ú>§Ù¬ÝGA–O³Ì^ŠäýìNٲܢHgn­ \¯‹^*c…ãIc—äNb¡Md\±­ZŸÇ³ªÉHˆÛí4l®’”‰à=>{XtYK4Gń̵21šŽsí¿pÛ¹š(Ôs¦vå»|FÚ!D‹'\Ú¢jã'îø:NrôÚe,³æ6f÷°³·Þæ‡\úRœª†M6ë^K­íÌË0:…ä%<ƒæTðÚòãÕ Rò£@•q¸aœz^~Ep‹G|uäɈ*m“L´ïÞA išã†ÚˆŠ<£:2‡Ün‡®BÜœ˜§µÊºº»›M§ðÛØÙ‹jK Ûméò`BRJ”Úî/ImåùB<û¦B÷Ì¢T øÜ’è§–?–ùxþecŸãU4õ†ô­€>¡UòDX{^Ö 6«N¬ÍSØ3˜{¾0Xùbg²³;0I{Ÿ¤›?å‡Ç^£²À*Ò¿ê §ÿÊv+µ¼–ʨ[ßT—ó}KÞ²øwM2–Ôp¬*dœ~CŸÑ_Zìd#š¿#erûÿ8‚ V é Uì g¶”SïRõÁ! ×0| @ô“œÕlr±•'Œ%ž‡‡,ãPµ1wó/œ â?!ÚÆxxö¤kxþï2³KV¾ã0TálC½ñ¶'š]ÎñK&E\ä´Em<ßFŸÉ uÞÈ!9—Y¢ìé²ÁòÌí’oS$‹­þ¬Ïw4dX_Ïo× [L]¹&UøÊ m{"â¡»ÜÂÈQb, 21kEš|ioÿ¹¯°Fž°ä‰È㳺³“¯ͳͮåÚòwjsÁ˜þ™)þGÆÛwoì#³´b·Qh'è9Mχò¦á¨mã¥KRùpÉ5—¾Ȥ 7²ÎÃd¯‡Â6FØEq€k\F7Õd|¿™¬` {¸¹.ªïBä¦úGº"…ò=¼øº´SEVâ®âL(\¹|OÍÑÉ7/C€ëšŸuG ÒWƵê5‡ÿäÞ+ãX³ 3íÄô¤ù8ïÔ?Ìi…mÝ|Û1Õµ*p‘Üzñ½ÜÎ ¸GðXú©eµ‚Ýf¶’–,p„ OÂÀ CÝÆíÊ<Ì”?Ûœñ”þä ~^æT«€ñ¸¸Å=²ÈÙO×G¨<Nßÿ_Üf 2›Î£ÎK}_·ïFÒÙ@BòrµE÷pÙ¥¢ïÆ,€ÐÙýtŸÈý¨8ò—gîŠbÌà3ÅèËD ^_âˆSÔ%›Îš/ÏòášN9“{ÃJ6æóx À^úü &`ôƒvØ\š oç± Wxš>j½˜tD‘ù7Æ~ æ‰~eO*ÐÃyCd$À¹Ù ‚ÍIg­Fm+zµO¯cóDJÆ>a(F1#ðºˆfÍñ«mÚ’2~5%ÈøÊ­6öŽJ†?ÊP¿˜;qŽD({è°uZñÖüø“ÑÙÆ%Æ Ü¿Z9xQ¿œ²™<e邏4‰ªp4 úâ2‡ÂOøA® ²»Ó›Þé®-—ߪ͟¦H=\ŠîÕvÊÝUE$4ËE9ðúAXÇàx– ¡ ”5q±‰³£;.\Sʼn^gFýxmÕÆxI\Ɇ§3ú¬Ž~IÔgÉ_ñ ­r¸ª§>‚Ù±~|t辶Ð$Oê'ÒWlè)>e¶}Ìb+ÇöuãÈ<ï¾k7(úαäÖ}Çß—Ÿ²0TŠmÒ,æg½ âÌŒp+ó’nˆ—%O²ÌxŒDó£ì=å´cTÞIáê-‡ÂøÕfc 8µúàe€ˆÄµä£gzKš5¬"SÐ_(®VA¡%¢y~òàའ7õîk„2.è=3¸`ñÎfªg­»q²G"NÔZŒæ@Ò~qŠp”yåõ¾T†Ðñ°ssôOa4£­-1häIçŒ^YVÕX3b…«Á‰ô;äU Z}¥Jý?‚ÕÀ£UÓ¼–Þ¿@eï­Ê›`1mž¶ù…°S²Ð$!yY„®œõd@L˜Âè'"o'ò±h9YiɉðzP­]0´ªÇjóÒóœ”)œ„ØjªÆ„•mLl’ ja5’l§óV,ŸÑb;;¾ÖT±ßÐ(n'JâKƒ_òóôþ’ иQ:ûÂÐÌ4zаjæQ¨_ðoµ5Ú%êk­¹À9$½Æ˜ Â8Ú8WÕÜÁñOOȱ£ùã˜ù‚ÅD@¼A¢¿ ¿Ìóì‹2™rÍLßúÝI`¹„?ÂúxÕÀù÷‚³&»Ëé°‹Ts0}-hÕÁà4¼‡ÅÑÑØ©áïÞ,Ëýß ÙLŽ4š™4jÆÄúœIȵ¯vÍÒòŸÑâ úA"hD2rñµ˜ŸjGh%ådçM°¹¾JäñW]ÑÊ'ûO!R>¬hocFuáYªx@S-)ñÌî3„Ì&ÈÅKb†Ë‘ýûÅn °9~EîÒ ½Üÿu5 ÷“q·‰mµyq ,á¤óe‹•"OÞ,yÁjäËvx.áñ[-¾6W\w„Jê!A,Gms`XÃÉ+¾„ÿ\Y³sK UOún/DEî7‘/A¿FDíZ³ðÊo×8G¸4ëkÚWZ—å©Gâ¦ÓØ µtJLnìœ[Û_Çzî/s­dTÓ…ì†[ó`øÃÞ¯ÿÌ6”'ÚG|€oy~‰ÁÆ <VÃQ©_Â1=‹œ²ñûðUÿ³¦d²´^c«Užà7ÇV7rÄiŒÿv\8Ü0ˆx53 .¸D;úš—öñC‚ßI¼)ºxT—ÊlyêõGï(¸"Ö@—¢õJOÖ÷ú31ê° ¹Ìi©¢€_…&_üÍ#ó~"–P;b8ñ¡&ЛśˆÔÐ_Ë5lü±ØÌ9¡B”÷TâòžÍõB™ø ÌUó‡½àÇê4 Nÿ]}ðE° ùßHÞˆ×6#sgù¡îýgˆÓ.…]ï C»±|hRÔ/’ªŸ3™BÿÊg´Yáå5.“þµ[}m?GìÑ/`¡̨?ºJ€ù·1¬…/H&~§>èÁ»c8ßRœ»i£|Žâ÷L¶•âóJX”ïDzi›%O6ÎP0o¯0­#«º®!½06{4¤¯ù4מ¼…È£˜¤3Ee½yß%)Ë_¾È˜‡€.€ÌÌŠhʵ"u÷(„<¾ê{ñ!ƒ¦Õå\+ÿ0CiR–ÎØ·0¸Jst¥ŸS0âŒY­Ÿ@ˆõÉŸ>z‹­U$´¶¶~ÏuWÞ–{ö‚©@r/ÐÊ9ç ã®vS|cZAÈ%tAzPmCé=)­—7Ãgÿ¡Ž×§ïÃ8@,…;š©s±€€¦c5ByÖ)Ýr¢¦P.Ë/é©™…o¶Z[A×-Ê—:2eúUÛM]k&çñ’Ü¿‘ß¡tëûkœ8%®#£æ²(¤µZ,%ô $ z0Ðjð³ìl.-DÓ§÷!a?mï%˜(®]×|ae¶Æ0&¶Õº² £Q×Ñ/šôå+û¬áEâ¨aºY[.™\Š/?>&ç XÜ¥]m£Ë¤ãMq‡T&tr‡`Ž!“)EÈ pçѼü ·¸JIã3y‡5à'å t]È7D‡J òœ˜eƒÊh$€¿„ÁU\0O8À±(2"©{J3":òt]ÆÂµ¡Œ´ oǽs9¡.ªeŒ®çcrŸ6¯ò}YØ „Ñ@éè}ö˜ÀÜò‘‰2y+¦M‰âÅ«W…q/8§pÿîMZŽÍPkh{aÙ1y&tüžÙòÕMoó¬²<ñ/ÇÖa?ˆüʯu݇Ójû–,¨Üå@/GwŸMa-èGkD}¤ð©ƒƒŸfZbYÑ‹l‰t/ ±Øj¦èôRŸ”hCå1âÆñ±S@ÖòÁ~e} kÎ º]Ýd^T‹’´WÀç®<ƒ²±›ÐK¥ÑÀiT̘‡ˆw!u@Âp2„÷AÒf޵ò„ÜtFIZ^iÿ—à£ùÖ5ÐsDiërÿ$›Ø0b6Ëü~xŽÏ·._Ï–Òõ…Ür²`wYù;›ç¤²å»äˆ‡E3óùž²ëšvÇ»Ó'Ÿãµ~?— •Fh{‰tëß– Úö >NÀ^²‹Jà-Û[æb3ÂàÉ'é[fÚcBl¹†H(y’;=9ÿ—¥¸Iód¯ökˆ‰'R6"œdÞqît¿œý,‘Žß¢]MöV>»Ñ@Þw†M0®èçã^F`çFÕ²æL((¬±’S¢ÅïÂy§púÓ­Ë’5›íy1‘pÆ{”uxëÈOþ…Ž'¾7+Öº!íƒ c´Žè ~E€×þO¢‹aöb]Á3LQ`ÉB徿Ýh ¸xdce 7¼#ª,C!A¢¿F&Uì ÍÎ à=¡¤Òôõ"+Øèµ7¼¹zÕ½¤ ¹}D²6 ù?×bÍáCfúþVžä¬oJË™ÿ€ø›-ŸEÚÃ4Æulò¿ËûYO˜R•´²vTNè~õúÁÎóg/âïžÇ¿¢-;g”Õ,W¤MܶÞ|JÍ€çØ¼ÔKýF¾)—$N\&§^» ¥C1sà ÓTÆÄåò¿2,õºU'ë\Ï鬘ÒíÄ;?áó^²ÒÙ-|¼ˆÉ$˜L\|¡Ý¿õzŒ”%aí=xÏ9Ú®‚Z†7¼ã(Ìå±"ªÅ/t^ aå³KÁ;ï"7Åßn.E%gì¢i@ß@¹Ÿ†˜¿´:¿)[ÒÐ…¥ Ê.Ç3âu?C¸¹‚ä)tOsÒóŒÊJºþy>±Vq/Ǔۅ9‚[Š$q·QI‚f¯<£>@²2Ô>[ì ïe©,ÝŠßiÝÅh'Ü|Iª$’¡Ù+šûcIäE”tÒiÒt6›ä¸ßE3;Ý´6Õ¯qIk›®Í#®Z<ª:ÄÞé× Jâ`d¬*»ö¬(a+‘Zê mºf'hß®gú[ŠœÓÖ—kÑÅÞxñ`1ã×–7÷`´å£ò<Ë ôcƒ´$(Œ­‹c.æ”=…AfÐX£ª—.~qîôÛ³‡A8zi5ëµkµ‰RvŽÜ%Þ¯ ¼×s—4_ ˆ;<µ$â!wÉužÇÆ&ʼfDÚõŒü²”ªÚfK>¶°ÐPVoN’"Öõá‘§•6{ ,"›W&ð°Æ§´û&RTaÈc\} Åta°Àj)›HèÔyÓW,ªZ{E¯žOµpk.]3?5Ík]¬‚‡Aål³¤!Bd+Š‚y–׬NÃD4¶2мyÒå㙘ÓóXŸLI9Åã0ƈˆÂŒCè–¤;ÇÖvœù½?vîûÆ[_àçºÞ"¬<¸ù‚Ç86<ä\µfòjq;íâé ‚ÂPåC}BùâêUÀÒµN£5«Èm]¯ëô«–’´òÚPËuÁ|Ý‚Õh® ¬Pt„xq_ÈEìNºUK‹¡ïä FåTùk“.¾± ¾KiÙ T‹OÝî-ØEÄâzÂ@§$€¹c€ïÊxЫ/î§6‰Ìp@ÿÆVbc¡ô‚RMgµeaFb½Ç1­V&CÍ¡ˆ_©Š>¼/Âå†y1ó•›ßcºØ„=Kûÿªß2Å=±R"oŒ‡!3'öƒCxHœÈe ¬ñfÞ÷ÕÍÀ(î¥u<¯ZóƒZ\ë…Sb Mêi «úå•è(7g-üs%å³lßÐ1:O,'ˆ¡cT™Z®²Gö™&>ã0ãC4”ayösS°x–ÍýUâ )š š$Ö<Ò:¤¿ ·FDQ+ÓB$sh×äî úÈãó,ºG5Ô Ê¿†`Íþ}”út³ÃWc^NÜÅáá0 î*ßk)}“#­¸ämnKJ´ÝÄNEƒ¨ó vS5ú äÇ/²±^b7i’›tº(>ŸHM‡ ßìæüä‘Åû$ƒW[¦s#8#!Àç8zË2“Õ©úâLÖkÚ¸@ÒK,E Mƒò’\’ýŸn.ÀÀµµ€žÇ/’eîI­ aá³âNÃÛ|¼ç…ö]%ʧ/Y2™·÷›Œ¤(j°ß¨º>*ÊÀ=â;uÌçÒ~y»mAu¯zØÂ[£–#™ÇŸ¹úlŽ@ÛÞÃõìéxâcÝ–<¼t"©âO¶ö¦IJ&%d]*h%U†U¾â¯Üª&îB SÔgÈC\S·âFÿƒ‚T£kZ[8<,”8þÓª ƒ`ž¾¶‰¦R;Ÿö˜b½d>•Ð-l†›¯ô.âá,Ä[k¡–C žnk¾pî5RÝ=\>åÞå^ƒbHê4ýÍ秉3'®¼K2AÀä:6Q?Ý}SÏ„ú1r>kf«d'}Ä#˜]žÇÅ>âàÆŠ~·üòÏe¥nxªfZÑÂoX§OÌsmrT¾SVš=ï{A·£7*ÖsÂpqA•íiÜÒÑŒG¶4n$uÿÇRNåv šºÿ®Ä*ªh]^ü¢¦t*OT²R6¶žÓ@9L‚¿ñ’—>aÒëù6j–f£ƒ·ª;˜ƒ%ù«¡‡¸ á)‚ÇÌ McÓÝø¦nÞPþCÚÃÃWzÔïQ“i$¯Ü¼A¡ סÉÅ<5æi²$ë0>Ô; ]/G#ò+V²RPk•©IY¸Hªp³U¶qîþv»9¿ª×š¸³n¹OV«Q­ã‘%ËM¨…µsßUUKm–ŠLäÅü‘q£—Ò¬+ U_zÅ,ælöõkI’aM¢>ÃÓ9DH’+_qMˆý :åÃ+;þ £iB‰ÛƒŠ¬¯ý¯¢b_eʲä—ÔGT™uþÃ:þiNVÓp´¦[¯±MëëÏÉúÕnÃ(óBm8¼³aIê±EHÑÒ òÖ‘º^}ÈIlGÄ›rõDϼZÄtŒýR×G)•¸±‰9¦hÝýF2uËçîê½: êxÁ'2jU“ÕXíÄÑLÏ}øÏmMŒ°rþÑdÖ.‚Ù°Ï[dÜ€†q$û…­.M,þü0Ê(ÃС=ÏM¸}(C÷œÈµ¡S‚Ùþ |bD¡K¿6AåDŒ{u—&pøñXg¾ð¡Ñi}Û!q[œ…IÝFåb¦èOÊþ9͸Àpæ÷Z¶º¦Î¬„Ãþ~Þ¦?a•¢'žœ![aö¡³jÜPfqíö­±pê%Âúwôô¶œÅ rUÍÆì,5¢S{ׯÌ/Tª’Õ |BCÕÉŒÕ^(úM;ÿÀCÜÎk¿êseD  drâ^Ú(FsêVí3ŸÖ(N‚¤pôlELáªPE/*!pÅëÍ"F<¤€Éˆ“üY#ˆÙß§:w—¼ªÖn’DQ-¶¡Uvæëö w§s ®ˆc!º‰_³üð)Ï"[ìZw:ápWV_À® ;tOTqº5¾îWÐ_%ï+;n6»Y虼:D‹±'Ú FPÂÛ>ÀBù_?<®J:Õ•Id;0‚¬!–ì¤ãàÒr-cÞ{d ò<òÊ Aò{ ›0c\%§¥p9鯪ŸÅ8 û;®(`ádAN†yæ¯ð*‡0!»ƒZàâãíue¼è~xÑr„ô(؉Œ*õ¦äËy“€8MˆÑ$ætÇÓ¢ô#šÂ¬ðe »øÎâ%Õ {‚§ÝïFùXœ€ãÙ¸ð›Óò¯QF‹r‘V¾{yËó‰ZMúg &ôóî.ÕÞÎMM¨×¾ Ëz+¹=×;–L]-Ùó¤Òyìî²<gFľ7t+½iiÙ€gnÿTäWòb•ü<ÆÏ¶»F«£j SYžÅƒÀ 8±c©Hî™ 90ª×ä4°œ²R°˜é]_­‡äqEp¨œU&ÉØò<¡/=~øXâtšÙVû¦×Óó_dŠ6Ô÷nHD6t"ßkX(Ö¡ß{žÓ¸Œ2™©UªÇd_ø¡ï@u) xW0AŸR~Kô×HS5RêùãIõ&!²ã‡µò8½ì'VJÖ$Ô7Qʃ™‹3™¢•ÐòOÃj³Üô:M5¢{- æú°Q¤ äÃ{4¬ Þý0ÙxE™ZB°ŠT²±sÜÂr~¹ß, ëÃBìÒÿOdîíÕšZX(p)в(*"™ùùp­,B•²ÃÏ#+º¨°,» [Ò#¥*„»?ÇqתÞ÷Øå…7ó¶P¥w°£&„›ÂB ¨—ÙNU.$ïT¨¶«#¬0~V;Íâîc²QíGx“²' NAÜãÍÉdÄ\ v_ŒÆCÂ*ô®pþà4Î ª ß™`Çͤñ紪ݤ؜óó†ËÀu#¶N€€Ü:D¬c£ÆÊLääF3 …“|a¡H|S,³[w€Žo&ŸSL#ì%üVþw•]ú5…p*3[Ò„ùÕ˜#qŸ*ߊºîéQ7zp w-J¯§óS±–üÉ«_¢¸Äš’8+›"] e¶˜G‚噘1/Nã`#ì= ÊGö)D¥ Å h·ÒÂ,ÑÅÛÁLÎ0­ŒÕy­t†#¯ÚZ…|团ôÛ~«Æ fM²JŸKŸÁNÿ6 ì©ìÞ¾bT KÈŸ]¹ÞÜ„Y)ÚwÒ?[4ò©Ió¦>G)žJ&d}ýíÜŒÅÓò~Ø0 $´N냿´Èc®pVqí+ëCppG¾ùˆóßeõœõœ6GÌ,öfú8z”Ô7»S[¢S50c­›Ôq/”_9¹jó¿·Ü%×­tQS…“ßîLðbkÂÒxâe¤í3SðXG¸T¤J@ð«H´+†ÆW™íç´upèó`•I]± >W*ìÕ´$FZlEfg sôë¥*|zº7>ù!žI©Åÿ«; ¸ao Á¥e5MB+ Mø¡FËB6ð|fíbî š}ÍÌ­š^§A¾’•Ëâ¦}VnŽØ†ô.¹¼j*À¥-;Ù&ú)Ñó‰A¡Z7*8é±51Ÿ{‡Ïo:g7Ï.Lå7û.éñ²¯ƒE‘c‰Ð‹}tIÙØ*I ø¤¾ ñOWËíÅ'as\Ølð\ÍL¡6þÒF)pm­Ø,€•º·¢ÀPæá¸EW0d¤q]&ÿdV6ß.cùÂ~L´óðCß(¨îMëb#òEnÑ»PÅV½!Àȑѵ Ç jFÇé¨J$ǵÀcu?„4·[ö&å‡:1“&OÓö(øyD~EÜžù·ÐSF¢–ç=RËÉd£YÐûfG¸¤Í§³‹À;\ŸÝuJï,J„?‡NÞ"¥‹ñ±{ÀôÎ%µ øvN1ëÈôDü•÷Lݶ§ÖwŸ£º7ý:Íî•+†•ô$)Dx U¯"q ï×û4úS+a:ÇÞK ÿ÷QöŒ*y ç–5!ýÃ< ïþ¨è|ƒý‹6\ U+ᬮ[®eVéüvíÜ{ÈL+]¬)–ùxþecŸä溰ÿoö“?,‡Ä›X‘:¯Oò9T:1G4qÞ.ÌtÉÑ‚‚ëEæ‡áHԟ׋¬¡ª nÍPÑU7/˜ÄñcªXâ§nc]¾¨XŒPœ‹ayÚGºxª.wÈç¤}¬ÓÏÇž\r—f`¤„ñ@zJnî´a'¾¨s‡Š­NŸÔAëG½PLˆ6ºIQkí úº+äÿ¥ ÒKëÈíTžDø.yžÕ¿}‡ÀÄœiÃõ„äóä1íJ$ŽðdÍ=² óv–¡t5!(«:Ö+Ovl<¦ih^ý þj,QüYº‘îîÞâÄ?a塺Á7ÝëÜÇbÖ¼GÈ P˜MåoÑéïToãw¿dyçëÀã·œó6ês\Ô…‹R;ÕXÚ»ûÿõåöÁ¡\Ðs·~=ðÈTDŽÝCCijÚ`¹ÎŸÔ¬\·‹ðñ™_“ÿü§™¯$Âõ9j®Û¢_]L“ù’¦8áÌæh²»BJÖÛn¼ûXÏjY—”8Ò6騋í©YóZtÛt´Ìn„íUè¨PGØÊzAý+ÚT¦M1¥e¬åx£4AŠ\ˆÚ‡2;¡W³Rø}×!ÔÉ0àehyXÍbKÏÔlwæ l_%L;8ê8jßQüg-í× X¬ŒA•JòdÔ×Ã~Pl¥+4øð7ç©0òhذáÐQ@s<ëÍÚ¶}Z‹P€åñ µ˜‚Èc×?ׇÎXªN{Ò¾oçÀù;ËÙÍ@ê[våÊ)÷3šuEzØì>BÔ?t_Ñ ¼9™G´H|®Ö²ñjóèOHgäì,Û[$¤BCæ °õJ³öëOP_GçUV'žuƒÇÙ/{#KÑé¹™˜qÈ~|Hë8àäpz2Þ8«H8*M‰œû’wÇÞºå Eª”pÇ !}¡1{¹Œ_ZšlÈë¡ÁŠ;u§·+ú,fo ä-AÏ[HM¥×ÌÝåìtò*9¼Â^’щ§a–‹Û`B>/Cö0Þ÷ðišNË­þÊ âÄCHŽ´–/9fV.ŠÎÉó”6!œvóÑ@ƒ ðÉ!w±y;¯m$i¾äµH+·]YA|åÀD!j{‘øEÙ×ZQ5»¶'vgêæ¿ux”y–#Ú^Ž´¹Q« 1ªAä˜ØÿPâ'4R‰ÅU]¥‡xý'¬¡Â>¹æ’îtê€3Yêy.·¬4ÖçæÍÕO“߀®†×ñh’¶˜ap(AXž|§©Î±¿[‚ÎP§k vá}¬WŒ(átù?þB¾æ ÓÜõ'åqMä±ýE½ŽQéæ.Eö“g¤«¾V _‹ ”hÅ:DB¼ªO^ÛðÍÌkUü°õÒ| ¬u ýÅxTõtWw!BQE–NZ˜ª9Pvíîs³¹AÅ$vÉ®?·-~¡ò:ŠL34ú±ì0=§§ PøCV9´IØ{ã=Ž·ÓB´K yѲTp»~Ëp çévÛD5í¬ð2Ia‹¡EÛfåÀŽ„îŽ9’-v‹òIÇëmÄ»R vDo’ÌÎÏ÷ëí8t7}²³U@èpܸEHÕŽý[ï´’´ÈÎx·¬®#7 >æ &2Þ÷VõŸœ6ÊnæÀ­NÖÚþÿñú°‚Û…6[þŒõTo¾¤tœ®ã¥VøŽ![ ²]w¼­ ?r$T]µÖn°ïìÄ9?Æ´OõQÚOçU­§Y34WóíoxÊ2î½JÂ@Þ ·–݇_ýÚÎOeüõKŠÂåýÒÕ¶~~Y‡ö’*Ó}+«r†l¥‚z«° :¬Î­>2yá®GmÀúÀ„ ¿”À)Ûäý±,ƒ¬RŽ~––• ¿9e(Œ tÍà3ÎWZŸ«IDÊ$hDpãëYGÃÑÂÆ*ëq¾þîæÔn7T¾ÅQAT—FZ³+žÔu\7`äpß$ûòðSdSÅKôB™Ke$<Ìßšfœ¼”“p‚騸ag#au.ÁÄè6Ý ˆ?áÌcQùí!;äùãÀdõôèiÔõà !S½øIAúiù7ÞÃ]×K¸¾1|bi”e¦9»:…2)\)1§ã¨š†46?g¨Zgš›r¨'â 6'BT̰?©Õ_ÉD[2-8?± %_í/ê¾1%Þ2÷ÃÉ;ÌÆä`¢Q ÇI ý´‰#Ç€µFB P ˆÒõUwŽYdù>-µeˆ‘ÌÄ@Îå³uãšß€ý^T®®ÿÅN ôÅ&Å\lð6Ý\PPÔâfÎåzg˜Ú>B¯Áà!‹/P>8Ýí#PëV¡׫»‚K˜éù×DÜÛ›ñ#¶Š_ÊBQÂîZlJh ª„—mOþ'Ò5ↇ{°1”W(ø® —= æ¤&ïZ³NtÉÁ÷œ±á#Š»2©Da=B(œõxing‘:öÄžö5¡Ãջͯª—=¦èa:ô+j9…Q=\]<·ÂÑÞX, ÌÊU àbïIE8Ò¾ž*}»Rr–º.uR“H#ì&ƒR= —Cð¡z¡µ[“u°êßÄùŽßë"¹Ü,—YN~_U'o[g¦´ÏKÕWSÎ’5³ðL51œ¥ýÂ7Ùðy¶wúCÛúKŽ:XãC —$z…¾ýØàÒ²Rªí{Ì=.Õ줪Kš"²ñÞ^Ð <å½G í¯è”;0yøq Æ—¶ ¸Ðb9ð}ªÌc…ë rŸGµÔfôCçU棖0e²ø1MÛŸƒáï ³¿igÂêFõ/™¤‹yˆËåÝ~¶‰]\š<š^”‚ëÁ¬‚úC¯ŠI¿(T¼U<´ÆÐy¡•ãjÖ>V»HYeÛ+3¯‚áLã^Š_‹]c–vR –‰ãÒ‘ ÔòlÞÿ{!‘}²æ¯5âeœ8rÿNç&°³:|®Ûr·”½¹>U»Ýáaªp/÷SÔ$ µ´o>rP$Çî²UoicÕÃÏßëYéŒò“e»ê‡}ޱÈi1ñ24¦O­.Å>“ú¦µ9é%I9ÄùZX<‚QË  €on- šE3–?­-ƒbmïO!͘ØP;o3:]©u’¶eõ:#ß\ßh±_`ÊDLYF»"úQýHÍWÙ¯° H3'–¬í@·Ø£ƒ9©W²\hAºª{FñÁQ¹›57ò)°k½« ú^Ÿõ#°§Ç‰Õ:èM¥|åH0)ÜÍd8& 7tɘÕFÛ@ä¸QÆÜuX¦q>ÏÏ…ì«Yš}W ZÇ ™(9ö£¨ü|Z*íØÃôzK£âißh°oÛ²¾åH¨ÉH6í-/>N©Ç=û¸`0-hxõ“²–-#¹ßBWN¾ÁðÚ‘Þ±ŠŠ/úĉz¨~IÓ{‰nÅ]ê4õuµSظ~xª´£ÿÑ¡‰Ú5–:‡I âšÑRSÎ CKÐÙÖXâ ¨¤çi!c‹z2v#É+×XÌá°§×þlÿˆÁ+’b*¡ç#½@8(E$IÍÀ8 8ï=­ _|( 6,vzTïÊé›2yabÎ3Þ¯<å»XˉÅh¥â­ž¸gÔØÝœD'Cí Ž2å¿Üv3 ¿Úé÷71á¶9*Ìã<Ú£Òÿ|Ì`9¢A„;’£4ô­™irÄ|œa¹[^1–pÔ¥ž :¸[쇋q€šu ÉšâÄÆQ—4“aUžðáß¡O5WlInò]ãj|XÏ]ƒ/77Š%‘¶‘gç׊pJ¿”€î‘º§:AÜ«6!4ÿ¥ t#9ªÍÃßlç/mÛ ‚m§¥'Ìú­ÅŠU«(9Ý̯‰;­ ›AI¦€V†m¡Rµ[æÃVG Š#Ëè¾ÂŠÛWoa±ÜW)šõ¿uÎûñó`á…}íÕç_Àq4;•Àrc˜ë£b‘‰âÈ4­#S1ÃÃÐpb¹w(88Ëò²®8 6]H§]‘_êPèµ¼=Úñæa7Â$[±bøå‘Vÿ¶¼½D¾³• f©Ø&æÇœ+Ëx¾««±b ”:h„«”¡ ¦/†Xžæ…¸Êó%p W—ÔñÄi¶ ¯ç6Ð|œ¬4J•æ<Øk: a-Ä*TBÖ‘Óœ‡Èà›K½ûuÍ(¢vÓ} ‡(Åñw'Ö2¡ ßËuy“²"vý\rIi°•sà6Z>ˆÿäY©•»ÌÞÆ¶Â†ôYÃ*œ1¾@¥m¬Êüݧ(m©¼§N£#·(?Ö‚9Åö¦CmÍ‘¨ÔFÈŸBÆ~ÿ£]ÞNšmÊ_é‹Rå¸CÁO\Íúü¸?óFIMYY>Klð¾rø3NiéÙ ;¾Å™œúÕ@7™T•ÂN ‹qØL 0?ðè)L ¦1†¦µ½n0V¯Ò¬®ykKH“fö›ŽŸ‹{“UËŒÌNf`Þw –ÄÝ \>ÀvºƒF3@J«ÌíÝ}Ǩ?ŸG¬§Ïä$¬g#Àû„èþ_À}}Qm\«ÞävK©37 ‚Û Š\ñΰ™ˆ«< _GˆÓy,gËÖùá§îª/šÏtBÛu6T¶¦kq¯“;•ÇÑ5Õž?gEpÙ­Z^vf—Ü( ý'’åáÐ3×Jª½k‡É–óbïXšú›#Gºî’— 8?‹l8K?Çêë½Ç¦ó¹…=wƒ4rTÜùÌèͦBØæÖ¬’$ë†,É®÷X†±°íy|)3¿%žª¬g[׳h NÖ ûkGd«Á¯6:íO€—¦ì@Ƈ§y//–ç+*뤕×Eë)†_ö™OT?WKY/õ”@öö¸áÖ@e––wÎûså"Öm׉Ǹʲ:$·¥Vðr¥ ;{»ÿöTS($O w¾å¿“û¾ÞnwF¡‚¥Yíªƒ±›œ¹Ï[âïS‡rŒÔäKuò·½nˆð]gÂ'Lû\ûäíˆÊâNØDì65÷›SÎiž¥ÂJ¶+¼—˜[¸f4À:, 'í»ï{õ‚hóÉ|NíÕg Y„gŽVB+’°ÏÅFRTxàlòçHâ–q²¶ G»Ðé÷r)?UAÍ.FºR‹iSmÓ˜ó'‡%¦`]Ÿ4k§@DWtßõ7…ªHÉ+©åÊÖö¬F “Ÿ…÷òqüÊŠñ{~•¯,M$|F>õÇ™´©ÝÉw»Âœ ŽDÅÇZ©nÍ#¼¹0—o£0 ”³º¿ Ä3¼ß~Ð 8íÚó,¬†~IŽg×ÛˆBû²Ï:Ì“E$gåbý/r ”)Ûþ½%ý7ÑÚJ-ðê£Ìm… c/¾Fž½[CÑÒ‚ýtjµúÔdü!mqóö,”_Ñ¢c2œ¡?Œöjj¶Eû§¿€¾½­j×2¦ãHúpo9·£|}gÌÚñW1ªçà jQá>Õ}Yýƒd:ñ_öà¸@Œ‰ F)Ä ¸øbPJX0ð_ãûê endstream endobj 106 0 obj 100460 endobj 107 0 obj <> endobj 108 0 obj <> stream xœ]ÖÍnÛ8ཟBËvQXïO HY²˜é iÀ±™Ô@#гÈÛW‡GÎt‘øˆ’®>R4éuw¿¿Ï·õ?ÓåøoÕÓy¼¿ÞòËýøtÙnWë/ó¹×Ûô^}ˆ§Ëcþ¸ZžNy:ÏÕ‡oÝÃ|üðv½þÈ/y¼Uõj·«Nùi®ó×áú÷á%¯Ë]ŸîOóéóíýÓ|Ëï ¾¾_sՖ㆔ãå”_¯‡cžãs^mëzWm‡a·ÊãésM]óžÇ§ã÷ôڶ¸¶®c½›sSòü1ç–¹EÌY˜Y™Ù˜ ÙçÜÖÍùŽíwÈæÒ™#rbNÈs‡¼§mܳ½G˜çnýþ@€?Ðàôøýþ@€?ÐàÎìÈôøýþ@€?Ðàôøýþ@€?Ðàú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_á·šsõ~ƒßè7ø~ƒßè7ø~ƒßè7ø~ƒßè·RŸ~ƒßè7ø~ƒßè7ø~ƒßè7ø~ƒß9þŽñwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßátF8#ÎHg„3ÂÙ¶ l‘Îù+Ú²rÉæÿ Y,h6¥;ÑÈDt8. Pi|ñ€Fv ¢±+íåK÷ÌèdD†TôÀŒg¥†u€NmÉ-^F ̸>-AÍÄNèÄ…²,²éŽuð¬´aÆ`¥Å‰ALt&8eÁM‹³<—“#artË„F{ÇN‡® tÛáÞ®Lˆvqè”ípvÆv¼øÎ™Kû2ž¥=²æn±•ö=Ûaîzf˜»õ1þûå‹OOgñôË$@;<«) bÏwW<}ynS—~y.®X§G¡ô¥)›Á°ÔÁõë ¨3,uðîÖÙÿdØ@±ÃÿÚ˜«ãÛ4Í›rùPvcìÃç1ÿûKáz¹â®ò÷pר endstream endobj 109 0 obj <> endobj 110 0 obj <> endobj 111 0 obj <> stream xœ]Ánà Dï|ÅÓCÉÙ²Ô$²äCÒ*n?ÃÚAŠ´Æÿ}1q)†™³Èc}ªÉEùÍÞ4¡sdG?±Ah±w$v{°ÎÄUåÝ :™Øf#5u¾(„¼&oŒ<ÃæÓú?„üb‹ì¨‡Íï±Iº™B¸ã€A‰²‹]ºç¬ÃE(3µ­m²]œ· y~怰Ïz÷¨b¼Å1hƒ¬©GQ(UBQU¥@²oÞJ´¹i^“JN9»ž.Ô2Ö0sj’gÏ–Çáó{‚ •ׇ£m˜ endstream endobj 112 0 obj <> endobj 113 0 obj <> stream xœœöste_— ÇvR1nlÛ¶Y±olTl['»bÛ¶m›ã­ßÓÝOýu¿ÿ¼ãŽqÏÙs®µöZsÏsÆ!'VR¥6µ7JØÛ¹Ð330ñ,m]Uìmì¹åè妖€¿89¹š¥‹ ðÿ €#×:9[ÚÛñüW¨¨ÐÈå/ fäò7CÍ ìj°˜Yy˜ÙyØØ,LLœÿhïÄ0s²7†#µwðp²4·páüû@¥®òš––î¿fnnn€±Ç11 ³¥¹€âø‹þÚØ;Øí\x¢aK€¹‡ƒ…3ÀÈÔhúO # 5@ÂÒÆÒÁÁþ€J”úVùÛ(3ýß?v8r€$Ðèôw¤%þ#™„½“9ð_³0q²°¨,\\xÍþRfÿP Îf v@Æ¿5ÉÅíLEímÿéÆîŸd1K' Éßá=ÿÍ­íìÝì¼þ/ÆÌÒÎôŸ ¦®Œêv–Ž®@i±ÿŒÿ Áý7ft°3±0q³²€Ž »‰ã?«y8ÿE2ÿÙ™úx9Ø;ÌŒlœ>–fÀ¿8/g£@€‹“+ÐÇëÿ—øŸ+8ff€©¥‰ Àhni÷ßÕÿÂ@³ÿX˹8Yºt˜þ* `úç÷ï;½¿Çojogãñßá F¶@Àÿ5÷¿#DDìÝ^ôÌ\zV6fóßÜLŸÿYíß:ü—ÿB•Œ,ÿ³G¦ÿ.)mgfàþQþjøŸãü‡¯Tÿøšð?êÿmÒÞÅÒø×2ÿ6¦.;Ó_Oþ½0ÿŸ†ýü¿mûÿÍ©ÿÔý§Ò[ôu(ájcó/A©þCPÀ_EìEÈþQÕÕöçÙZÚxü¿eý¯ðïÀÿxHEìmLÿ)íbôwa;s›ÿ’Àhé,aé4U²t1±øÏý'¡ng t²±´*Ù;[þóöÐ331ýÿ“j–&Öv@gç¿Çú/hgú?·e·3±7µ´3¨ºü5·‘“é¿hW'§¿Bÿë¬ÿæþ×ÚÌòo@ ;ÐÎrDXŒm”ÍÅôCÕFk[¦ui¨ZаôÁÄ éÙ?Îp½_|ðD Ívò—MOÅãÅpÜ Ü§>ï|§Rµèíyôå;Š8±úê¡S6Õþ'wÍ=°qá㪺ëj«*ãO¦ƒšá;YÔ$$|¿^Nû·â}wŒe• b!±³hfžXZKVfälõ0Ìç¨è”O/L>E¨ü÷ŽE–ñ®rXŠe_ fN=ôù¡õ¤)ìÀ1lµ×6ì·5îkƒWl‹r{N:ØacÜÁ.œîq‹òÌý¡0Ý]·L5ûniè0å‘þh¨NÜ ÐÙï1kÒ™7 ýEjÕ“·`SfˆEƒ@è¢Ä»Òõ]¯ù÷&šˆþði¿Þôá®&¢B¾Ê†ŠÏéa0ù›æ†¥îµýbâ(õéH¢$=x~hDx2 EcSLˆÜË7ì‘Æe`¨(×ÍcSà‰Ðo(ºªAø¢7 l~瘥 èNM»zO4‚ò÷\ã‚1f´{¬õ_r„¾Ð-Uˆý¯Wþ;9¥ù^Ö”õc—k–ÞÃjXI½ˆYNÑt4}8SpZ£¿ûi¶Û¤ñ´@àûo­( †±ö•§G=ŽËÅ<@ÞZû=ýx"‹¥*ŠÏ¿ÕªVØå¶¡ a•$à•hÖ[_(3rµ:"Y¼|Z†`Ü×á`Í䦗Á$Ùâµ!U«½ŒL§™bò2Ý!Œ‡{}jмµYt‡ûî¶4³ ›t¥‹og›Õ|QÚ©µæ] $ãðÖNëw¸çH½~HN=¦TpŽ„­C×(tº¸˜"Zy¦²ÓÊ" !ûj*µküñè›c KÕ/T  å‘ÒSXú`ÂkœoIFßY-îâ5¢ÒÝrÓs,¶=þ‚o'{›Ïl{Ë2C߉¢ŽõHÝ` Ø•Í5q:åš9î$Ò¬þÌ-àk·¥Rä¢ItÅÿª$ âáu)Ð¥• 1ÇjpšõÁþeOìëbJŸàMƒÉNê8Ã"â$|ƒžtÊ‚B2Å»È-XhÆ€ËÔyÓs þ8wp_ö6lƒ]PnYï)‘‹Ëס¡r[—ºÝò|6í$æQ˜À ãkF¯LúŽñ k«ö Ê“ H.æIO_‰|ËMÒ/zh©ËÍ#„¤ySøâü°“k‘zu5²¦3A¢Klú ¼¡J3¯Ð+rŸ©Xê€wÖ‘g œ½pAuÚ‡ð<× KÀ¢ÿI*I”´Õ„ÇÕYŸ~zc•£,e‹)¼5-+/xE¨wfÃüÃèOØÅ“瞨Un.ŽŒgßšÎøÐ51Cä.a/V=.¹†Mcï@5¾H£™afYxˆ³³tº¤ÄeH㳋åG效هÁ¬8Ú:cÿ%}ƒñYL.bÓ‡èÛÐïÆßȦTcÔÌ=ùSDœ;“ÎBž}P‹Ú ÏÔ}YÐ$—ÄágFé1„Øôk>}‹hOayˆeоÔϹè1'ò< _…´—E®ß3RûIÀ— *ø *@?ß/¡Šì®ì&…á$"½¥3¸v,Ó ;ÈŽ¼ÏW–dÆZ(Ñ$NU‹7ÎqâƒÆrµÑù Wö°#|È8™. +÷’ö5?–6´:¼PÎÝ&æ?âüáÙÖ°¯ÖE&ï1à ˆ\⇡C\Q¬2r¤Ñp Ïì¾wªP]!û¯±Ý-¥ïfé/ ‘Œ+e ;‰|‹WÜß¡º•µP5Ôð¬â¾¦®„éw xŠQHE€ ű3&˜£\çy¸aõC­ÕøúÚE ÖÚ7Q¢wöKwYC°¤fFU?h³>ÛøsóôÁ»ÿ‚©'ÓÌÒëŒ=,4eÁQÊ\@rìÞ·2ø‚X–}w»jó&Ÿ¤(—†J¤w7¦M ¹9£Œº…EAË‹¿øó‡~c›É=4­œŠcŸÒÉ»`ý9^nmèŸP&®Ó}šì³d‹õ8Êt/ ýûÝÀË„þ ~¹À?ºyJÐUl…ZãNžê²Îê¥í\YÉcüÓ§×ÃÉ4Ëž¸’Ñ/OéìIpWG¾é­Ê¿ù%›bMŒ·8,¹niAp‚Oê3”¯ä"¨õ$§¸Á¾-PCx}¸ â*”'Íùð×€yX¤~”ÊàÙõáTÑCñ4SÍùƒKþÀ;©\d—COª·W<ÚÈö{EPîÄ|BfCfqžåª±R˜wi[¯«Á“4qØý‘Lñç©Dø%±‡é>; M¯ñ¡ í·óJíl;zTí8æP:³\w wQ«Çhép ¼@m‡ô¹×# ~ËÑhô?þȨ5:úP¿ŒûÃy³oÅñÇ^¤C}èòj¦µ&Åï ‚óÌeônU»& ‹7‘µÄyJÀ|ÞN…EL{\ʌĸ¿z\c…;Nrý“®Cg|Z¨÷TÙ¤l°ÜÙ‚~ãåÝ¿JØcŸ ¡1I´ Oˆ#Tg1\‹ú¯«?b6l(Ð~^–‡¹*ºbS³]…Á¨D§ 4Vp/{–ïÐl•.vÅ0xyÛ‚Íd…žxä1X£]—zìFx³Þƒé ¤ó"Vçg¥ë•Òé"‹_·~¬lð"YfäŠã9è(ÛÆ€VÓзS¶Œ:Hvj'R"@Ü×°ˆ¾ÿ0CH°ÕÀ6Lc†a§ÑòHmã  ÎÊVëÛÂþH*bÀËêŠã_µ.Iç‡ÞòùV%z^´ÓcxF 84bœìˆìñhãßL®m6`yG+á™ äó½ÌÖ“îm»a >dôÁ—R€ú‡Äµ9:,Öû oáï3WVSQì@°<ƒ«•mÛUx¿ ›Ý¢IJf¬±*µþØw©<šÙë³ÅŽ¹Ñ½yñóÒMÿ~'½)ÝlÖWÏ@n°Â0Q©~Ëš*£GüU¬Y§ÇÏ}ÇàÍÙÔÏWpøß”?õ g†}·¹çèåol¤A®? .ê{Ýë*y—Pðû? äò×íLœâ»^ ¿ûjïÉþºþ=ˇgÇ8-‰r¦¶ö¨Ù|Äx¡ÑO.=ðŒ-ž!зW %h!rcØ—½sÝ3É@‘{yÞƒÄnUqÃkáeãŸ0n)j (DÝBGÔ«²F’¶ÑhZj½.ÙÝZÔŸˆ¼:Ÿ9wCY('FÐËAšƒŸÜE[¸0I§–tG`Eýz²ÙÇÀ…û‚ã¥Îì,)²[ÓWˆ`ý1KA‡¼»d B¤`‹Š¾ºÞx  •Uda.M¤à7ÂÅ!#:9Ãïe±šx—·¼Ô¦Å’h*¯¢£Å£ù˜‰­ÒíâþyZr5…o›¢ÎY½w2‘“¬ëUÂÆ:©Ã®Y›ÖgæZHBÒ¨í²Úr«¦yCˆ9ïTõbÈ i6âTKºëDoîGÍ‚Æi,‡·¬ŠŠ þkë=vn%»GhüÎeoÏþ{G­ÀcA­'¹Äsƒ/Ûµfÿ1©lò0û¡ŠÙqª|1o| Ä:G®{Ï88ãûÝÏæOäZk·Ï'DÉÀ{®_οæÀPOl­Àl‹Vò"TMð/|óü.³^(ÊÉ);¿=†’«Äætº‹çfµ*4„¾Ä„UÆDp+o¹rF†xU ÀÏß„o>½Ì–Ïd- °¼´ªŠjÉ©ž£ï–d¬1  g°pì§VÈÇeL†70óŒþÐðA2"v¯U˜gêMŠó!·ò@«ík Ê•E‰æ­[à“>[3u3Æï Ü”¾>è©]S§Gªú²±ƒÖÀîï>sVúZ +÷Šxx*—(C1¥CNp¯RØœ>AU üW˜G¯cЋŠ4#P§GŽ.óZ*?St{iߣ{t\ËNfA²³™Ï– &š•¤AAÙ6‚ä‹2~âRn^É…©!ê(ÑEcv!F¢Àø³)ŽQåf>)>K´ôs‚»Ë„ð§DC¬ýô*¹ ÒÓ¼ýYþ÷õ^õð§%ƒ"žéçä v·¦îiÚVlþ¦ÆÌðt ºŒ+þ pdéç–^Œ+”1ʃvõb­ ÏcGíyòE/uîˆ6Òè« £ù7Fät£@]µ[)ò@•Àá¢C JR%$0€¿$ÒÛ ¢y$Ò1"p{[[;˜ -5ev•uQw|²·›À‘œÖ(‚D·ój.C‘ƒ±s’ÁÝžk¬ë%Ë:kÆV;‘xÝõ‘l:Å´;ÏŽíצ"|ßLnôϺÇü[²ÚãÔHL÷pa¢AíûžÊ7LE>mÿ8R¶Ò™„ôõ• êÔýñG»¢gŽ·RÜ@ªK27'<BGŠo¼ˆíØ‹“u§àfum—Se¥ãë7hR³Íß§z0ºgqSYµ*v…œR¯™v&Ñ[L¡sóR:å Ðq¢¯ 2nÎät€£¡œ2…·E.ñ¨ØD"»öÇ©YÆJqæ•s·E¿ûmxMgÐ7­”sž¸•ø~N.Õ{Cp–ÍRn²ýºˆŽcO›ç YÍ,+ÁkZ­böó[6î»t²ú=>ô(wpÐéÜß3—ÚA:}¼¤²Ú#eCŸ}âÕ@U'jw'þøø›ÓÑ÷¦Í=²ÇU¥û‡†?‰ænF@¸¥SnXò&åû¥£MËŸº» ýgY™l‹ØŒ&z,Jºƒ~Ò)lè æ1‘(úOD=²þ•ڋÖ0­ðD©\×0ᦼ„'‹m W{ÚñÉãDˆX ™0_<#F*¨Ð…Wº6eÅõx ëL& Ÿª:²…{I2ª*ä^5~ê–N[ßòBÔt²¯¾møÇø’šô¹âFš"<$FûE_“N,)F&ô¥³K,#âoiµw›‹ ú nX$a%P ‘¤dÎPÈÌùä;Õ V:{+†¢ÁìYªÏþ5EàÛºisKßg%LâÍ9hÈf׵Ǯå”4·´'v,çS%¤b¬òź>‰Xf»3‚•¾]‰9•„òv¡ô‹G"varn‹Ú“ÙN6.Md‰n5ÛN¸ë,I°¡ÜÀ8ó”§\4a oKÙ"]gÏ6„_&&}=P¬Q–8FÀè êB7w¹xewlP/ëçdÿ³îo®.ñ·Ì«’p,,a°zñµITU¢2)œ;ÇóÅ<Â\ri,?çtk܃ZL™7#Ä È¥èû2ø»%E)LÝâ<=“­µDHt‚|¯L[4h`<›Jò‘• wöÜ`7v2sPïtkë³Ï´±†ª~6C ðk‹n½ûÕi¥¥´{:Æ‚ŸÌÏl¡vŸP t°øyçØŠû~ç‡æT/óí“c]åwz¤Œ?f™cAŽñâÒû$aŽ"t¨.Ùö ZÞ‘az÷ Ù¼4èjкqä;±e¶cçÒN{wÌH×½Z’‰÷òÉRõþ _(f™.űm§€ÖñM…9c66£ÊNU.~ú0T?.$˜à©¼¾Î¿‹!#X†[¡Ús~$zHŠû€ˆ%ü**>…È#súÈš™É­gàà™JŽv­s£½:`ñT½óx•Þæ:,èRèþá6±r—J |§ÝP2=4+qC“u¸Û°?0iMÿb JavKë…–yøuj;XŸ»Šf–UwŽDk)µåÓPËÑǧO.í»±XЋ‰;±]ˆw¹¦ô“1†Áõâ‚ãͳhô¾uô]jž°kOmUõ}Ïilßÿ+/¿æŽýÝaÁ£ªžçËažlè +’kýËž¶ÔèÛ;­gÇ,‹Fü£z+Z?|eH2e6èBõÚVîéÛkOƒá¾›²ö=(ã*TöžÞÀ«ŠgSÝYV‘˜èÊ·Q}dyåàA6"@›õ­ ‚…dxhÉ4orÃ:hÒžž‡Y^މÔb‚ziÎ>j&çbµ{°€âFûúC18‘œ‘v‘6¹ß¶¿ýÌ.ðÝýVÄçò­÷ÝQ(ÂýÁNåd4å먂Jœ«Þ }©%òLò4{™?c#S$v}¼Ùà®kuu tnF=…EјYÓÊÌGùî‘Ä·p²¾"gg}Þ}”=êúhÆ${_Q¼h ýgÝŽªL"Ì[}ó:§%d³¨‡MwgŽ“ƒ«-=¾8ÇBžYîIþ‘ëûUhúÖE‡öçr/K:˜,Ï;p/ÆU«±öÊú©Õƒ¨·«å(Hg_râ.aù->+å${›ÀqQöµ&?gò0ÐRÖ¦ísZ*Ø>ìõ+3æÌòPny-ÞÁt{u@ïL£Ê\šß@v_kþÖ,^’¤ ud0*‘±±8‘Y¶+ÑqŽ=EÆ{gÍÀCÉøëF¶¼ì’“f,<ÚLhr¥?ïÅ<ËDH8:b¤ÈNIÂõïi¹(2õëjcgî-\^Ë@q~s¥Zª|éQšèo¼;’Òé¤Ü°÷üñûŽðº¢O0C§Îë «Y¥²jøáè:…J>9ÑG¢® ZÌa^0@-‰]ôí@ե»§~ lÁDRѧ6Ã<²é!NV8ä±p=°Îëø%:ŠN¨L¡—ïê°x‰-è¸ÓÙjVF¼kâLJœ+ˆígÚ[iæ–¹ÔþXÛb3:*ù$*}`¤œœ1>“¼ŠDJîëÎìÝ­¡TD…|¬;mÝX3’Øô@a×A‘ɳ°¥Þ]Ýo½î½³Ê=Û`Ü®¯˜ùŠü™âiÊ7ÏôgàF$i6æfјAEòÎþY¢‚ûö¿\/MÒ™^lH™7—u½ïý÷m¡ëÇ.fO¬vêdßÓ¥âO ´jq:¬ãÖR•úU¨ÁojMÒÝEß/õÁHóÞj-›Ç©¨ë±b$ƒÙÑP±Ðg“ :Ê᮵é§ëˆê~š¼‚H¾ÂÖ³Iù_Ùª¥H’ô\j+ |ÄÇÞ[rslÞ„Ã÷Ù¡&JÏ–|DçÊ›™ËßÅT›¡Òõ#%•µ†.' q]î–Üq®ƒ}ø0«0«V¸cOˆÍœú¬S„žÂÍ”JªÊñiÕ•´ò›š±¾È^X+7g€Õp¨Ÿ¬'÷=Ló™öÄrBŸê?9rÙo„çsæ0‘7ÆñÐê³ÖÖì} KÉ¿x/Ùb³V².Ì]‘QAüæýÞ’¡*PCWP@+ÈÅê:Ƈ¡éèÇ €!¡áp²–Ư¡™˜?À¡üQX,»·§NM—]q*BpR±î·P¦ŸöEäܘ›oi¦³Ç‰‘¥&œÃÛ·JYÄÀçCº_V ¾×­²“x²°¬bŠ·v–ÿÏÎ(D+Ô•Ò:ÛRîæ)Ã&aø.•ä‰C|'23ôÀÁM!ßK¡›S8•Õ᫜F0UÚ ¬LÓ«7éÕÜ÷ÝîT”ÊÁu4iÈÜÃ'2Áå÷ø_}Ü$Ùµh£ñ¢ ἌÖ$#©³Cð¢Å§AèšÞµX2Y‹ÖzÑP³LA°×)Ðc~74 ®¿œ*|-ÄéRÒ,ÓƒœÑ;I9õJñ,½‘Ò0@°>Ã}LÊEͰ¿štRjõÒé ¢W{ŸæÌ×ÚÚ÷–Ï­“áÒ:_A¿eV>ÍZwàÀ– ‘0FT,òV iA tùkæÐ ›ŠÞ&œé§[ N.5qªSf‹FRª55 ž—̓ŽD ¿-òVfŸ=彩þgãß77®¥ÌøÒm@ÖCGÔxÍÊÎÄj¿¯?B7Ùæ£)¯ãn‡­##ýDoµÍvEª6\Üa£c{›:¬óKc÷$ÑH½w¶ôžÇ¾Bœ‘÷U®™çjεí“fL1Í!õ!*÷gôB’ èi¶þí2åzåz‚ ¯0e¹ðÍã¾.«N\¨¯bí5¸%ø]$kfqÔˆCa×ÑEÄæ)ÎG«J·qŸEi 8r3Rê§³Ÿv6ƒã©ÞBo1ý¦ûs\B7ºƒëR“ŒäBï³9b½H{"áÝï÷¸ÓQ¸{½.Bñ^‘ ¯BOêG;³Uô2š\\“&³Æ³E㛺åT•mUÄtd¤ÞR§Ò·.jмœ–ž†‹dß"§.tè¢zHdå4„ûaMƒq/È5UUßk[ÑÙëOÓÀØöƒñþ¬%+ÓÈ®WIÿ£7ïŽñ]ŸÙœ€:4½6Âç-|#;ÎÙM ¶7ÌŠÈ=¬…6Ìb£ŽSMïÏp’†œ˜_Œ8.‰Nn¦)üÃá®ØO´ÅÿE")8,ˆ¥HÅJ6©‡ö÷%=\Ǫñpï²¼s:·mß"‰\š"õpÍj2OËàöwª!Ÿ“…°2þØ?9`«âkÄ$ ˆ9íåë§“}ãtu1ç¶¡Ø6B¡ t0áçü»sâ'€æv’¼aQIc~×_Ïwñ²ƒÊÅu{v¬ÛÒ¹ÌT´¯30˜)Yy‰{Fdøm–j•Ä ØÃ„g(‡£zPt`$zcàG2ìKÅ—Z…<“Ÿ VSu|¨ø‚ð‚˜/ë¸Öšy†íæèíAP‡¤j7SèÓÇ6Ñ|lX³JU:DöÚ T³|1n<Ño]βªÓÂpõ÷EÐIK„8RÐÙ›4Vð@’&¸[¿¶Y„âE›ò–T†•c÷_/¥†$GÈ^sßéFn­[?óÒïìövà-¾ßk¾ 0DŒîÃݼDu–¬ÜÇDƒ4ÍòK0e"Aq«J§‚ïúø­;>¸rÙÿÕ×5ºJÚ¬HNa:äžb_€í!Ÿ½"£)=Ä =ö©½ŸËv’“í^±K•Z§‘°ul\%×FÇ·d]ZWäLÃÜãÛEEr_ÀFëߥvʉ\¨ˆãRQˆ>ÇøÕvG,­þêþkO“Ú Tí×Ëô˧ûlíQPXžÑ]˜šÿ.¡6ÙonéìäòŸ~çA'£"m6XçýäÆa eCêI§~K?ÜM­4뫉2:½µv%a¯‡U%4îò2›7‰˜Q®ôê¯ðçt—äÉŒ‰$ÄX“pe†òï}åû£k»e!…Xô» =q`¥ü{Û^áïÍ÷Á¦"æX­B¨²3&ª¤'ûükqzoyÙÚDþ3!rT2X/_4/a–’Ä7#›e_”n¯1¹ðSË0Îp§ð«–žâ')xîèM£»9„‰ñ0 Q­ò~ªŒðªšsTXa¦+—ºofåäîœÁ¤6ˆ˜õïC8ë#Ô3H‘ûx÷»ûúh½lTCbîsfä+j†4k‘¦©×/ß”Kª¡€:8&Më0x[0[ mÄd]/”—ÝW‰Æ/ôk/ø"·šÆï0ðŸ3Q{H¥)”8ˆ¿gl „6cN¥vLÕ§z5ÛÇßFmW·35;¡Ž0·ßN2bûï?y èt6/6¯éß^Ý'A>S ^ÔßöQ°“mós~m“¿+Nòfh/2~Y÷j³Ô Ê”¹SÞá>·*YÖDá’€øŒ‚¬¢肤¬÷Ú +û}e#e(B¯à5&kú@‡´%¤?ÙšÍÎÔbÅDD‹Xê~ÚM·iotKÕíÂjPAºëÃ’Íï mõó\aüÔ‘döìš× ÝAg­@ªôÜBr;‡.Šw>åˆjþ²h&Á$«®»©ÿ™ÓÙÓbA Yˆ\¸£Wµñ žÊœíšªæ»7/f©–Eß—ÌŒîˆWE\«D¤5Ê‚ ïTT».T ö åÓ!ëIu5›£I×ÿµ…€ä³š9ÎÄ0HÂ{¥:ŒD(õ4F¹iq»§°@ÒŸàQ}v¨“[„šƒ©îSŸÎÝå¡ÌñB¤ÿþ™ÜS–ï1iü$Xû[yºQEÒK~»gÁéWJŸÀ¿Å C@1G%"{àÊtjC;å;*žcâ ä |ÖÇ£:j±ÀEÖºÕ"‰ èü¬p¤7µb1…{ÔÅç›ædWtºÚ#žéÜtô]Ù¸ ç!I÷+v۶Ί6~dRqÄ×-èC(âÝ“œ à‰0Ž7å®Tí^I¨‹6ƒ Îo~û£C#é©-–î‡/ÐLWÕæò¾ÁÕt mš\Â{tÀö%CœB€‡ÌÈ·ˆwò)Ù>#)QýÌiJU3$ÞýœvBYb#ýë=A6# EÌ0Y‰„´™E‘t©§®š£Wû÷ñùUèó÷º7F!Þ“‚‚#²Á5»¨ÞG½Ã~zó‚xgÒ¾‚óÑÌ$UOÕÏù0è¶ E;Á"É/3êw•ù¢¢z•;gÞƒ‚µ²!l½Œ= ÂÜ m±§WlWžÌ9LÖ}Põ_½²Qî(–k~‚뤯÷^Ѱ;ZS1FK‡ƒ©ZØråÁQð|~‚“2/Ú-Éøúƒºqê"ßlü­ŽW0é¨y?ä“iCp²aÃd+ÑMJ© •ù`Ï!Ö€°ßñ$š\ëî…ï/»|ÿälÓÈ)0V±åb+?*íGg°iðÏ«¦þÐÇ(¯Á&‹µ…Ç>»=zçé)·d/KsZËŒSΛ_.Ü<š½¾`½³\!%±¬¡L&Z,²@øƒÂú[t!{ %ØÆ»=ò†a¿ÉÇ%–¨»1’ù¹‚ôi_°™:Eí³––k¶Ÿ]íR7TGÁXðId$;ës¬ÒÆúrŠ8¾o·ŽßÞÀYC›4üÆ¿žWÇ1ÂFEÚi‚±ºJmGíDh·Ép–žJص‰=-P MS™*B†(MZ ‰MÖœ¢òÌÎÕõÓIKÝãG¾§©hðl­Økó…/žb5SŠjµ§™Ã¶øGÕeí¤gÁ íÖ@T âã[ÓewÀÿ+`û“;\Q»|êá£Äؾ– gŒrÜ)0Ê‘ÆLL­±d_½ó×uÁxÊ{ ·Öo~ d?DÉ™ÄÀB©’ª2ô7ŠLY¬|韻‡b[¨†¢˜@ÔÓõvh«Ö)‘2û…¿™!™äÔSK¨aûiõ‚.âùd‡}† ("7ÿþU/®´WŒc~ã1Pß÷~ò1»J1œ{A©ž‡ €&?©š,ز¡•G(Yù5÷µg¼2Ó=¶L{ÌùþÛ};_ÂG…F_qªà(lfgr²ßU—TUÁ;å_•”@ä5Nb]VÏ“éÀ¨³²ý܈;z?,’©*“š6ôäùŒ3ÕÀõ½?J“d§€¿;u?gáSZ{Ûö¸xŒ9‡qÆ0©ˆ‰—÷íð:xbŸl}‘½15 Z€Ì²Éx»6[EšN0ûù ž„²+:Û+Ëz+2qÀ‡,ùÔf2p¡z×qµ iG ©›Pú€\VôT\’….ß” ›ã[ž¹*­ƒ,r§æi'ǭ弊Oñ?pj:›\È1‰"qÞØBRy¯nM‘u ½x§ØGˆ~—)˜œÁ`d\#—‘;}Ô`1f¥.‰mõ›´iwÏ´Üx~@ži5'æöµÐv¨z-€àÍÍ¡2&•¶Š¾Ãëçb¥¹•AÀÀ±s‡Ìõ8NAÏ?2½?¼fYØ9 ‹X>ì)â—>¦wtDbéÛWÚ2^k¸´~èoTNy:+É#íÄÞ¦MÂù†ïÒCÜâÖŽ¸<(äݼ÷‘éC3ÞC3ÖS•;]&©éŒTÆÅ–-nÛ åúAJ…ç7no¨ÂæÐü$ÃG—ža7'{#¨UÏ”ø7 Çió%ÆZŒïÃKq ˆÇ’¨B`Qënχk¥Yôd³"rK¤H×cÓ?øFUï ˜]?vmabžGÙ\ª·o\'L·¾]ù½Ü¯BÃüŽC®¡¦yYæ^`Š1ÍfÑg½R‘jý^XÔ¢,|ï²þMXò«¼Ò·a2hêsf?œêŽ]Ð{Üo „‘ ]¤YŒðN•N ‡á Oÿ¸nf”„!쇺ÔÈCöå+ý= µ=q‹n«… ýµúô½ÜDëO 3Éäowu/š²ßœ4·i½Õ<Û²h$йzdËE¾Â†Gß-Ê{~c=}½å9Ú³IüØ”–¸-Vy[”"™¸ö«iº“ †+),óÉï1#ZúE&ièò]µÕÖÝ$p+(ÚOÙ}È`_G¯ÜSÛðæô#LàáµÛÅ£D2¨Ï@0ƒ\nà€gAìûÌ"árZyàͽÈ6™x²Á-ÂMt#'ÁÁe yqS¾Nç{„¢Þ Y—Yã8N.)”™+ÊÒ MãEvR^߬æöCÂ=Å ôI<5ƒ¹P~Þ‚{:O YéÊ:k£#úy\ùû óÈå謺ƒÚiz29Ö§À»~C ´–JÀNÍ竺èÖ÷\›Ïê•d>ò”G¦k&å€ïÄWLë/~iA&À,ÖæÉQ^ÉeÜu±NênÔ=O Ê×ñÆ\›±Ù± ¤%´-Û†H5üvŒ^¿Á¿*_öòΕÝ<áöé BI î,DqûS:Š&—ó‰9ynFECxC¤Ä¼>˜ý¥”¶t ¦ý˜ „Èo©ÈoW‡ïì ŠÞ‡ò–¹•×! ôüpõNÀn÷fQ׺P¹\F†J&{™rEöX_”¸uûBwú…åQ± á8‡A¢©‚ÕØû|Ø GZ.ä!±ç{gz¢ÖÊ>^’™ún¬îR}½r¨X¶ üA9ñ6Æ+ù¤ N>ɱHú•¹4~ù¤÷ÂPØT }x¡p÷S«Áóº³Þȴ̦¢È‘Fù[©éíxÃ\3½2Þáí›a}¶tC«O±RûËŽÊ^JÞŸÑŸ&2u™‚Œ†Òç"_Ó‡’”1?gÆä‡ËYêç§]ǃæ©]T eb.­ •€Hº hDMù›þÄ|[ðM¢$n¢"˜0ÔÄ>Ù<2IêÑ0?-4˜ 4v”™ˆ½ ÅðJÊ.yëGÀáÕ‚6Ñp_¼æ $°rHH×ä˜#Zþ¦<ûl׆_»Þæòo0E©¯©øÑògŸÑw?µ(xðÇ›q·‹½T_T·Ûvç'Í8jÓa´Y~½Séì&´ª"he“é2”PDè÷ò%9Z˜9¹-˜ƒÎ»$Éš‚qœß‰“ßc×µkPŸìêÿ¼ÐßW×Í??J¶SF(&-¶ßW- wlX±äúâî–|Õè0›Zí³¥EI&H8è“Dù|mA!GJÙÀŽ£ÈPP ]°ŒTPe}—Ü(SÍ1èÑO4>èæ^a¬)M¿¼ÿ´VŠüÞ+G2 »¥§ÅYrjiG°8úäð0¦—€f ±h2}Ã#à-cé1Í0ŠŒ¨ÓKÁ¾}r؃ÉQ af|£¤!-ý¶ „H{zgÚè|]cOöº@Ê$ÈQä(`©B™‹í®H²Èë”>¶ ´¾•»3äƒq>*ÀB*Þs¢€T—‘ ÄÍ'äW&›ŸÚ¤lž!mšÛbL‹Ó™+µàYà€Ì¹üB…[•ˆD-,Ò±uþ¤_f¬Å•eä³Âˆ¹ %Ù8Ä]ô2*ºþÍ”»dw>r¾O#"“óÔ÷ Tù.¯*ì{~à™4Ý…éŽq)ÀjîêÔô׌I?ÙKä8?«˜~èÕ<ÿkN [¿¾UU–¹ “°¬è]CókàI±³%`­3•Ñ3î(¡çrü؇f|ø8§KD+.Cç5rñ{¾¬’ÏwéHï5+¦ž´¶>¨²Å.¶/Á Ç¤v¼oŠçŽ ‹ÓÄ ±ðíÁ^Rž‡»èXŒ×R“( ñU1¼U}dm¶†ƒ† óV_q”ÅiœR¦¿?Ý–}5ãj€0ÀLÈÒ|r¾•· %Ñæ¬Ñxô;ù:Ž Ë˜9߈nÆÙ ± 5iܱO< }M­'vqqV`÷‚UëçµÄ“ͽ‡Ù^r7h»ö7’½;:•ÖÈMíqå>uø¼ùé>s’Ìú:‹o'1eïô~#ƒµtŸu4Οy‚6Ç÷åø.\:7È.é¾ÕWq$΂B¡ÑÛü_b(«MhÙ[¼–ºÂëðhP7UޤiK”0S@ÓïFÀÉn¡>mi`“BŽžŸS¼uwcßùòò ÕwŒ…joÂBš}pj^lff½ßÞp\¾s¸,cµ{ÊaѬ!2Y·žËËÃÞœ“ø}¦Ø$*Yù0@söa9ë2ccGMëþˆ†«ç!p$•Ç]fÌäI¬ìÏøû„l«q€àWÓç>wtrl•z#³±#·B¤ ²zàŠ¸81¢¾¾!¹Ñy#ØÛ-ÅãÔ·ã#»: ÀýØ©õ4j×$¶\Üø ÂZŠßɳjl&0ÙA¨ú2ì:F¿ë¼±"ø‘ÇÄçhß/U7¿ÏS÷ÝgU=B-Èí® qÊ·§LYáYŸ”qÎS[½+ëpÈ¡ošeÙJ$#lý=½CÏ4¿N?½î ²  Éò9R„}C´äÉ)¹2|~…á"å“ 4_š’q´7m ´Â²® æžÕ£áóþtuRb(”ß´eOgÞ&×1Å1:]vR i»35¼Q5ÅÈu‘µB¸‡iñ üqÌ䊇1á¹»%ÔByCIð4€$jk2Áúja\fp½ùÇW_ý°øFŽIŠG@…œsoÏåÉ'bu%â<Óä ¶GDƒÅë™'[½{š€”…²µyZHO›x €eͤIgpŒiœ„ M7´XÐó.iUJd¦ÑA‘Ü©5|uX•¸A=þ»dʵZÎFÿžLdŒûmë8ǨRJ3‹™QÂM BeE°Ú7TMºÛ–©Ž-aÎ{ð< @N“Q÷e>"(î\\yBåŠZÃ7Çx^z\Òçoà ½cÁL í•–?ú½»úÍŽ°…m]¦#þ,)Ì|FK ,]ÝK½3 ­$^ð.Ò.üðš,;æÐÛÁô!€«ŸhºhŸ1h!×™Isœ^¿ÊúmKêk²¢Sa.ëP/ !!£Š»|Ç¡Áz)ÔÅ2+³ m§câõ1š^FºSN>¿›*° ¦¨ô”Â&Å–‰_ûà˜Cß k¡ rÉ©$ƒÛµÃÔ‘¼ Dæg{ób7M*<äŽsΧ‹LÞë…+þ3ÌKFI{a¡ËVš‰žNXŠìx~.°SÑè'¬°z ¤:°ˆ.oPìc¡XÓ¨W¦]áÛÁëM$Û‚03H< ¸ÉC±+©5ò[¸JV[_lh½ôm_mǦ0`'€¡Ð©‡B!D¢ÿ@KêG*’«Ó' \ºÈµ<ã€EؼG 2¼½:èå9„:Í¥•ÄJê%¼+Åè8•³—¢bØó\–Ÿ±[¢_üºñ @$±÷¢§ \iåïµé¥ =cÞ„T,鄈D3äwÚÎÖÎ #©¶ EÏ ë⩬œØœ¤ù×ÌìøØîÅØEJâ’«½RQ¿<7çêªý›áX̳¾Ù%c(ú&vßúVÿ~ìëþîz_Ïú bäv«¬kð$¡ÍãG’PÐ¥V“„6™*ÁÙOê¿OP̺YiÌškn°ÛËbصàCC-&’+}/씆WSÈÊ(C¸²Q†îc…Œ+¡þŒmþ o±§žº™æRütŽ9¹‰aµû²îb™¢B+†Ð¬E™ÿî’õ~>¦«¨ûrz¡-¶FP°>‹h¢×2žç‚jú#H- ŒQ˜ònàôg¨­D. ‡ÛAÄÌ+%q#6PŒõ§×”Wü´—Iâm’%aO?‡1…¥j}‰–©îi–ro•YÞ*ì]$¥cñǹM¿Û}(òn*Uþåb!K$N‹))’T¢1&˜¦<ëYÔa³†ÀNÕõObtó##È;î8uWóX %æ?¹òzˆÇÇþ_J|VÇ2»àâ6 2)ê\˜[^ä]òþ¨§R 6}^êô¤—  ‘ÏÚ‰×*mÃa*BâhghÊßyqÊâZ°ÑyoÝ:<ÈI2pFÈ÷çT†äG`8¢ÏÎ66æû}¤7ÉÐäæxRõy0®­}âÅNÖMÂ*p’ž/¾Q¦ÊþÐÅ‚¯Pn 6=¦³NÜãÏÞð+mó2JÂmÐP-Bç—e0iÃÍýOÝc5@}<3 ”• ?¢gÕÄ©3âð/ë"ø¸Œ‰Wä–”õçfh´”™$ny†ˆè{Ú™Q޽¡¢%à· s¦Ð¡ Àb‰•j¼¡;Íë IäjŒË`|-h¼…†v²Š‹x’éSé×aZöæ‰w}/y•ÍÀ£iÑG #ݤpö‚¥¹é·b_ø׵ߙ›P“†s“¥_SüÂV:4µťŚŠ~l’uf­ð´ ª²Ýòf´ÁQ&ôðá»Ò«¸!ôö;³+Ÿ‡ÂéÄwZqÝAéèþ û¶«Ä©Ö³|¸ÀÃÔ¾|ÙzRk4$vÕÝ6üòZ*Âï4«)fK®.mô“‰ Ù|AÔ„‹¢ZÌËÑ‘…\Ú÷ó0¤*²›BãÑGè¾BòX¬%Mr4hqÃmh‹„Á3ˆ=•¹´šã(ï™J ú‚È?\IÔŸµbL‰ÍØåÉÛÆ ǧ´NxPeÜÏšÊûÈO3<ô€ßeþ/Њ¢ßÌ\â \”t“ˬnÂÁ+MË}o ØÞn”â@ʤœ?€@ŽÕ,ÕÞùÉÕÅâÏBoO\ëÍïÊ{èÖvI>¡æû7׋À”0ÆÐÞ‰M0UßÎDàðU©ñê6«ºrË e2Ífë&YšÐ‘C£¹=ïs]…¨¤Å ÈvÝê€Ć|£¾ù!Ç&©83'ê2ž1M—çC‚!ø¼ýÃGÿeB×3ÖÆn›È/U¾Ñ‹JˆìÚŠFÑÕzÕtƽ †!ÿLíWA<ž?ºWå5Q*u€23xéúø)ƒÞLjqwH!a¢Ê2’G3ÅÃ@=Û, Μ„€-ÍrFœXuC… ÷HãUëáLÅÄ}!|‹)ÌÍÿñ€»Bì­úŸšÙŸöt¢‰ÞQ8nà­žB •Ž"€Š„°ùù¯OJc—gªÀºJ!×V)í°*èz¯ÒC;ˆÁ—¼%?@tu#X£g'®çXàœñ㨮1ê7icë¯æ[U;*ü'[6@å¿[¤SÂdjêé¶’à;edI9߀¿CRײkõnNÑݾ¦”ò=O~'ÌsH£Ý×Et÷½‹=‘1[/ƒg˜y×¾†¿@É­”q³ÚgNÈhQÕÃÙ»Ó$ƒtkm‡ÓÒRÔ3•¡Y04îT=‚¥^ŒNo“ÌQT\„‰Zç5yÝ©d¿hÓI Ì_ƒA$H3:b"È·Ê$›>…AU÷1ºsIw§Ö‰£g¨%áLó3B´žVn.4¶½-'*Ô²ŠîÁÖøŠæ>h‡ŽÍë2ƒ"ÆmþS6xÍgË’Šiê|s»H§ÀÀ[†˜Ø?•þzdG¢‚~é:ƒb¨¸cÛg‰t»ÆGNhVZ¥x^$2óËHÔž'ÑÎÅ꨷3€-ÖO2.øpà~XA̬;Å ÛV¹:,¾Þ™.ñ›B©= düÿ@ã¿D#ø/tfÁpu¨q´“%ïè}PŒºWÁjÏhØ•Ð.¥|,1wñm²Jo¡Îy¨´i·oxã”G=‚•õaŸ’`^|Ã•£5JÙ:ñç¥.8wÛÞ~üâý¶žÔ€Úävˆõ#(«ÄyÜvG÷ÚòYŒ@ÑØ?»°Àþ&ä%^Ë[+à9³ç†b(ð T.ÄÁyÝkhÜ~çÖ½˜‡$7ÝÔß‹®°µì¦þí†\‚䘪fó Ï¢"®¹Ø¸¶àöô½ô ®«§Ò‹¡<^ÑÑL@›»ß,AOopvkU ªM×píàÖ¥ËףˌÅöl‘6/†ì›lD‰¸ š ¥ZœEdx>¿ƒ±B¨ë 8Ê\‹c?|êÅ ¢›â‰üê)@&Ó¾£‰—7~µ\²Ç_ ‹×¬)É÷Š"JFPÒípÏå^¼àÍW]“ýt/¾ôÒsCÌà×>=”…õõ‡é_Õ!}[„d˜=“ßÓÒœ#EEˆÁöp›1a ü—öòZÑÇNÁ¿À&ƨ/–K0¼šÚÔJ-»™¡v5ß–?U`ÒïÆ!6Ï×±ÐÃân–¹AvWo€yÜ(q Úÿúìž MJÓônH;êHVyå’Á« ¶Å½ù)™‘ˆìhµD6øÍèÙ—½ìØÀÿ­ÞÛ#Èó*6bR~ó:{Y¤Ðô>–"-¿ƒ(}Iô_ô¨à÷Fg)ªð, ¸FYîõˆü’Ö7‹ü üjëgfTÉs¾Z=VA±ÖxùÙXGcóá?ø’7[÷»¾-mž½U÷‰ã!de=G½OpYU)ؤwiÁ£Í¨8`žyB,¬|ÜXž#èúµ ÏJM_ðÝN±at¨J1¥¶á¯Oe‰˜•>QÅ‘PÒ)MÇ( î‚9§/èÀš¶?<EŸœñD¹-ªh_ïÆª•!y?>yAÌëÑÞeŒzV— <û ½^’Ÿ’9¸jË›¡¶Té^;^oñj¾гG±½åm[§L蛋»Ã:ðh ýW~MåÖ¶c=µÍú)V†TY‹Z)+C-_ÊçB’ÈZAnÄÒlmÓþ~5ZÖÿHÇcD¨A˜ôSˆ PèâÝŠ)—) $¡*3á?G`Ù{ù´çÍÈÇA©ß FpùÜ zó MóŒ0¾½ zIqcÖz×Â-&à ھf¨–Úb÷i`{èÀÆÔxã`ꬺé®V­3¾É*µ ÄŽäY`ÑÛ’ÜV~û”Ÿ%6?~G¤Ù xkÀÐe93ÆR×-x|m;nº1à6Î +ý}0ŠÆÐ$ÓÝÒŠ#3Áf0aÏm–ïh@1%;±d=ujD”øÁÆ:¶¨àÞ—Šm DBHn Ù ——@‚²E(†¹lºÀZ¼èö\¼OOéÛíט˫ÚBìp–µä–¸’I"] ¡Í‡8”§ØÅ6ý—r>4šMªƒ8¬-˜ÞT;jÜf‹¼È‚¯(™197è¤Â=nErg™"Ãx‰Buˆ³ÛÍ}#ü3¼×<¥¸ö<ðq Ÿarž“ÿKø 0·pP¢†Lr·Ê80‹hN0ÇÈœ€+¬QØ¡#ùZƾðõbè‰}³nž‚üÇH™Ië˜FÇ¥‘+rèÁ’þ5ߟ ÌF¥J}S¦u ¾9û™UˆláðŠá¤û7^\Ðß+Øno1ÈÌØ"-_w„Š 7 »3îÔ((ªÀb¹úÒÀƒÃ§âÂE/z.d?BؾcSIEâ†ß¦þd`õ Z"w w Ò´\yâcHˆZ{²PØÈÙ©Åð)dµ‰O m´îç_©L«¶M¶·ŠÏƒ¿»‹ŸÌë!~S".ä±ý_ŠÞÿ«Πé1sÆGéÊpó) ·Öìw)›„C#ƒ™}¦pá¥&͵åã%Õù]'ýÐah7ýǤUNÊcòÀwBнìóž™è¿,‚d»ÚÚ(a¼auº{ Ðëù!ÉŽia¥ãÚÏœÊOH½åçO–V þeDél+q“-¸6 {;mü¾ÜNÉœZö%·ŠªûR¿C&!\êa™tƒªÅ¿ Áê¬F›Z‚•[T“Dýµí,ÏšdyCæ±ñ_ó Ü‹×BüB¾‰ŒÞÁÈ€¢æví ?ð‰–¥®$âS“Õª+R,AȤΈ¦†TºsË y%?–cÔ«LîËw…ÈÝ( =ÿ:_QØþ‚‹‘Ä“¢V¿»‚«ÐÂÅéÎ<[Iv•Äíö»cÆ‘^­|Ðϧ*¿±:ç’ð""Yº´{²åã·e6tgÃ>UåÚàtÕD8Cñ¦Ö±pºrA[ôôäQÐ7$PïñhÏÚN§&¸nÒøÊ¶âD&±4Ðð4.¼]†óbû6ržÛþ¬„vÛŒl•–Ñy ª³Œ­ÏçZ¶@âµ …ô³$@rOÔBi ^#„Ïwú[ÝÇ+½|l¶îbõf4ºqIvæª&è”± ™Ÿ‰ !sò5‰‚‘ bbA)ÝÂîJÙÕl®-Tco³ÔGºrÅâ­Óù‡3—Ô0*F%>H„I2c†j„ÌëÕè±*Ñ'A±ôìu,y5)q뜥P³‘@ˆË?4–ô0o^”\"]ÐGÎêÕ0|Í@óê qªC,SD0‚k ÅCÿB¾%FÝ"V—x#XÂÔ=ôÏ­ÚCÀ¾kN¥ª¯á5›®pÛlù,>+Ôƒ&ø4L#½ŒmHä ð@¤Ä·Cƒý K»&}j5Ï2ÁOò‹³CZëäë>Hzoî2¬µ{IzC~~ژ݃'´¾ dj~\˜©Æ‘ª¡zSu¹ÇU¥ú¡b³MÍÅ+LÒƒ޵»Jüñ9ö~Ÿßo.9DnPAšƒaW~éS#6M4³ Ôiòxjж´ÕŸ)½ÓDË0Q¦1\TAüEóÉÀæ<ý~(ÐiëbGK'„H²GÿÔÙ¸+ÿÂ131Z"0´ëwì¯.2«evD»ÐÖÀ×á`mºñ¾C|Ið©RTƒ ¡Ë šnÞWàåÖb!t¹¡\´Þ^,Z8DT9»»ïýÞ3-R•šP°«l‘ÓÓÛUöM >Þ.øY3Lúôþ6Û¾¦ýØßü ªÑ®ˆãГHäïÀ¡îT/7PÑðMžƒCôØüG‚ÇvT-ž†ØÐ¬Þ¡ïK"aF¢ì\X*Õ(Ù²ô¤áô½·‹‚ât ‹¤:TO”(‹°O’ªs¯– þÒÝxm߇¯Œ/TrO úpB¸ 6¶KÆ?ØïLFŠtä½˜ÄøÉbeœÙ-uê…üˆÈ—ú»Ýñ¬$„ï¹dRºŽ00¥Üñ-ËeµðmkñÓY¼\Ö‚¼ƒêã—^˜&ƒ‡ÇȦl>Á·Ð£›<™«q5…9» ñÀÓž-Õ\¼VÂÜsš9Ö¡6Û¡ +=Òêr¾dO7(ƒÎ:qMhã§>ç£Oï¥`ÆCv¾ôʽ¾‘“Y©_ÜËј¿üÓw-Xmc9»PL—‹w ¦éL(ÖÆC+=³3§é쎫ñ«¨—Pi7%0ýM¥û ,F–ï§áˆÿu_É|à‘b ;Ve 1þ'~Ö€êö?ºz,/l(™´dŸjÙäÉx¦É@ ß=G9@ ŠÍ§qgòÔ¬%ë}j¦¥ìE÷å9ˆÐÃùº¨i¼òtÌ÷Ž8äo—Aë³ÿ²Uog|—(¿Œ…ÈhÛã°{’ßҸĀP¼Ñ¾ÕqÅ ãË11bþtQÑ”•*i{pÿ/ÕÀrew΃* z7í8Æ×œÐÏl8¸A[¯ê÷£5ÕWü¨&VŒòÂáÅ@2Õõˆ‚ât Î(·õ«ÌîÒ¢£Î,¤Í€Þj"پƠ§ u¬ÀÒö¡û¨K3‹+¼NÅw1Y“ÝÈ(£³Z‘…Æ.ÑO°5äÄ×>wAsÒ†ŒÍ×=¿–0,´«9âð¬PT¡MóJÊ;ÇKåA½^­’mÎ2A†:”K"™×_Uà@œœ–2ñ~€ÇMðÕF?“´G<ß´!ÐUNày$÷šg!•Ø9Ës›êô÷º“³¦å¿ñÍBXÏó­ŠÇA|ÆÔ=C4Oã%ƒrp>Ôê"”H(Éäò§à[cĽYN;‚Iet£h™ÌfÝž9ŸÔ&XÓRCrÍíôV¹n×ÕòQ (æSãÓjU4cQºPY)DK‡˜l0ßMs|ç ¡ô¿U`ƒÒS,»˜–ë’Ùf">ß®Ë Ô¶>ÂßâtM.êõú*ž¯RSò[v†½?íO‰Ë ’•'ågû7è÷ 0ExyUD¯-Þ©G9 Rë6rõóvéØÒ4Ù¸–Õ:-ÇõëÒ(ÒÙi[ŸPagf‚=Ž;›¾‚Œ 8´íAGé-"·QÇY ³–W­äÈä€,¶OœQ}2kÛ zº³'1ûAÞ4ŸNØË‘vÓG<Ô,0Š=b@®WxÒD¦•ƒ“¢+TgqG, §Y-ÄÏ x¢?¤ i*Êš¿þ‰ªÓÇ‘|q”­æ2ûƒKiôšÈœt×-¶Ï€Ò¹fQ ïÚr¶¨’=tе›AJyûñÇÆÝõåû·Ý†ÚO| $—Ú¤­ÑsÂ9é×LW`¯'ê>À UPŽxBý.I*ü)Z¶ )‡ùBɸCdHs÷u°“ÔAã/é„Q²]Tþq²ЈîŽï•÷¶]JÑÛcçzŶJ¥!,~œö£zO£Nˆ'2óV4’!‹Œ@o¥ÀV„v=À³YMrV!Ô1ì”6¿µð 2³å+v‡ÚWÜQˆ©ðnÄ&l{}¥ä´7òUð`Ô–]ìçæÚS<Ì-ÒAtœrÒ‚ >Ǽ'Ž×ÕLç*¢ø¥r2Åê2œ³B'‘9Ž™¤¾{%}KÕe ]w‹˜¾ààV†T eǦD°ŒPlÎΤ=WnS”q#” ûÚ@),v/ônËâSa¡p‹ø4sY|Ø×ü¦Ë·pCÅ£+Ì(ÐZ;z®L£.… ævQ;¬8ÕÂâhw‡ •Í"ŸÞît³ËJ6ÛY%Ïo‘`ÁÐì7« À áä.ÑØšEÍò©ŽÁ5ÒÿÍëà]NQÕ2ò›ÍÊ%<ºÛœ…ô‚É8J‹ÿ©xÛ·ÈY©.z˜à0M„rˆ4 ëìù‚j"ìXêdÞTÈGó)¥¥ô)ÛEÉûoý+>£ÀºdÍd#\õ6Ms´1Cª‡7»›Lê¸&Iý ^½‚|Û¹Ö:·îÄÈR©ª`Èð-ˆÅi6 Ì {K÷ÞJ^ør.y˜ÈêÚgŒãÈAý¤4·Qê\”~Â\às~,Öñ'‹|¤3‡Å °þ>‹ÿ—ñ¶N7FLÏKokUÞÈ_ÕD80ê´Ê·x¿ôº}Xýf¶G“óÅ&7VÅ Ìa¨uøþ0aø<€Òx¨}†ìà“W5ñŲv91¯Ôí$ÙžÖB3ÿ¾ûQhÇ1¯7ëW8Û~"ùSûdž¶ù5¬ªª¹ú«˜ó> Xú6U¸¨üúøHõ@ñ~”9wÖÆLDôJM‹@оüËÑøôê°Öxˆ9ùzKœ»‡§¢hûµÕWÆ&•(…ÒÐOñT¾Ð'É®p4æö¤Î‰¸‘%/CW³M3h½êŸ©!©3sT'àÖÓuÿÈÄ-ìQgøF=?{ïil.Ó©IÔ›aʲ¥âÞKð’åáéCÌváRÏÀø‹ñH(Œõi«”ü:¬" ¦H{`.pÝ+³ž~ÕYÿUíQB̽q&‚¾ör'é’šM(:Ï;Ø>ÁK&M¡G;Lsn÷e¡ú›¿ï¶ÿ¨±dî:Û÷HBÏ PÆö¸}ÈÉv·3Q½!¬PU®Ÿ&ÝÇ‚õBu¬ý¤åm»u*^îÌ®:BØÅ|Ï0[ä Ó”³â…EÍ™k¤FQ¡öQYn¸Z ©2—HëPÖ}ElÁn§?ßcìB¬ã}Ìyæ²ÆÛcÊôÃr«w»êTi j…[vEï{­h8¯EûáÖ„ŸZ4ðÈÔ¡9êÕ/Ü8ãEfòJÊ ]3Ra=`ím"j¿pÄʨ4D2öwh!\`Í¥—‘l ©w-`·ÅxzI,>ÀwrN͘?Â#¥_¿a `Ï%“ ÷ƒÉ×2Å}£²˜ÑÎ\üáüÈ1ÀDZý~¢u4À3œæn~“ò Y„’³†ˆzä«{ rqäâÒÊÕÓÉP–qîéê³ë[¡Òkˆ…RÛ‡Íê<5´ Û z5úûFtë¤DŸ‹ ÆŽ˜#«TŒ+è’š_ê 5NÝÛ,ñÎ¥+€†C» u©L ¶ö_ Þ¬`Vcˆ=%‚’ø]©Œlyj¹Á¹¬èQ¨H£øeì»BM«`(ÌC>Þ!>CÑŸd‰^ÜáZFû‘½~>Ûä#ígï!ÒGqq¸ˆ~¡ÞÛ=QØ•›ƒ%ä.bÅ¡‹Átö+´ÈbH÷·hRY°MP#k5™7!ÀWìólbgÖѽ¡ôÌ4žÙ_f±nñM7ßp•VAhÖʵ9^«þ3Ÿ>ecs™;º|qdÚ«@Cn6ïÛy1§’JñâNUҺɉߤ#+f›ý¼\«½(l2rÀ_¹né‡Èky?´÷Íå0< p’ò}‰¼êuW…‘\©Á$¼þ–V°t°q4¢pËmx©V¼éè›ÌÛÄóÀ+Ê·’—NQNhøÜf¼kÀŒ”{Ç[Ð " ¯îæš°_/5i×ã"|g–ù›14 ÆÐ/|Ê(äv­®=IÜW>vuë‰ýÈ ôÊ­/21k}TW;Õ¨Wƒv÷5Tå…«n"îããzf@<€mÉh€u‡(gÐjG‚C‡÷±yžC2*`à±…ÉœžšX7$.¤¸×ž•SGÈè»\Ï-¬4B @Ð5‘ØÓË…Š6]Ò½ÅZTÜÑOb C¥ÒÖ³]Ø®ã6 1ž´W¼wÔü„¯eŽ/s¦áN Ì´¥ºÚ£1œ/ô2{§Œ#§j¹>ð‘?¥&6ÇWK8õ?P¤²]Á³NÍNœóŽŠò”šò*Ô#¨ø V·ZBŸ]?]Oîïµ5bn^õ– Ì4ˆ‘˜w¸RVL]5Æ*¤»Ð1J–ý– 6nÎqAþE•À—Œ42‚nQ€i<}öá„X„˜ùžíš¬]çóÙóPO˜œB¬H_uäqÈ•íÄ·ž¦ùrNÌë«õááð>o_ÃÙh!lˆ˜}9 Z…šC ªzöU“–§‘ÝüéÑîç7trfæÐ3¹¥ó¸‡<þ|?òs*ï}O6t?Ú%^U9)ó¨ñÝ3õE&4QôopÞf8éÛÏP8¦+æÓ:?ìÄôf¥ÇjMÛIP'­PíAUŒêÝ[|qÞhÐùž’*“ÅÆætYÙ*͵"R–­¢æqÁtÔ1M²ð;{¾Ñ5Ú<e(TGìÿ¯»Þñ´¾â—žI­)(#˜¤ZIý'(ì„F£I ­+BqO{³„äÕ¡k¼öc¼ÁíÈŒîò®7ˆh"ùaAóý£m›í–j¾4#wwø”æÄ Í N‹àKÀM9`€ëÎ ÍàÜ»ï˳CûÅ:^ˆNµ_AÔ¬KH6é|]ö‹×ÄYããHmÅÌá(Å™ëôë* ²9n!KF>à‰V£b§Ã{ ;ÏР8¶ïÎÉ EÓÕû|Wº›!H™vž¾hKtšÿ`¯Îâu¼$±{X_ˆMCè…#º|ŠÍ.%r‰Ð~­—]LËÙÁ„ø¾´-ŒfŠèöÛŠŸÑǬZ˜Ä.fd‹ºŒ´I\x®rª‰OA:«‰.ÔsR~N&|½:$PÖ8}fû¥݆Eñû›L†ûö“ðˆ­ÚÈYê{Ï@ KŸgI;#RÉ„ˆ¡9ÞCãüÐŽNŸñQ±‘&û™Ðhœ„»CýlíSãgŠÕ º™àMCYÍ_ôá¹CÔé“¥L^ÂX[Â[æØï¬°‡è?ñ|Ǩ{ñ¸é>ûE¿§ï•¨9‘^³ûð“Ÿü^dų5•FЀFf­‡H.DäI8µ!œp™Š›°Þ°#o‡½Õêk­dsDÀ‘ï·­AMZ„èʤÞnç‹-Þ'Á_lY!ÌÏô{0…¬°0}F ¦Íhæ`_ûÔˆ‡¢2{8^¸‹ÀN²±•ØùJH&Äö Bþ‡kËSŠð.—ï³>GJÓë›>fò ó5mç`ðÐÌñ Qx€ø¥Bs!X¯@Ù CM¶a‰¾&K˜qL”Q^ðÛx‹Ï3Ï{üË\ Dà õùÖ½ç’0Žx"!XÎ^ëOQ§¬OëšOXh—TF÷e4Ch%²-Äœ6Ô§rÏî"i£ä¡(s‚[0*ˆ¨•ÓU{Òô7;Ú}#ŠøÒTôÇð‡žï§òë˜×AzTX}çW…ýÕè”%oï¸ÆÝ>“Ù;=Øz[÷êJý$ RÿÕµ¥XûÌQ–Ð d )Õ1åÍ`)íÈådam?t—)]BÄŠ·]cR¤d¿fç¼wJ:h‚Xr¿*Æîgÿ:z5uq}¯ú•ãתj5©†E9†ÎË ÷õaî˜ÁÓ®[ª»¢AÒà&J?£\ŠØ€ –‘ç·ÿõÆŽ´²®Fÿ$m‹Ð—GvE%}êÅ=Ž ãÔŸÎ^I;¤rX É¸©åaó+.qšÉ|ÍÁHVc^™SQÖ@-ó.õÏÑuÁ¢¦€ÝuäÉIÞョĮo9ÆŒAˆ º!È ©ˆL¯÷¿pìG Ñî4ƒ¾|ú¦e²–[ü£-ÉhV×˰Q `9Ù¢zRÂ@ÔWân>ÛØzÓÈKט«à­R*À÷ï} €‚hΚ ›À@Hf E‘úò‡¥`ܾ ïN·ŠÉPå„ 1Ý·èבÁ^Š'Ýó’/ke0“ˆçfj÷ |'RKW‹Ï,¦ÂãÑ׆~ßÑcŠ/¿=à@Ö8sÿ­B)wyr.Ÿ²wòè¯òM«¯q£]6»é¬@¬NYl:ÕJ@íËÄ%fê¬gKqþ¹MCáAÖù P›7ƒ¼5¹–Ô9ä?}2Ìl!>ØÀ¨jáÝLÌð‹Þô&ê[ÿ£v¯“šˆÁCêà˜ÜwÅ-ÿ¾âõšK+ÒNƒèš_‚¾È(ëšæ“c™† ç5+«`Ï›ÜøÚ—´ºû²äʤÝVÚ»B“­.è5q±©‹Lé#ãîÚÔj­yRryt>³¹yf±£éžŠüCyòÖµ‚.¦™$!ÎWöÑâ]»Ï;.Vq>Nû9]"òÇèXýM˜2ÿÚÄH5tª#xû?»6Ôšnô ÝÿÈØŸ€,,ò'*B“. ·A7xëgŒWÌŸÿ¼Á²áKFm96J„c´1ÜÆø¶^ rPÉøÙFód(N9UkÊÌ‘M‹ þ¡rÜÉ ŠU½Yº²Ã‚ Óñ~´´Ìk¾ºX¨çF– m®ÅŸï±Óã ,jvyÖ»/£u*«@ÃóÍU¢²tÒ‡e>k6õÁÖƒŸÒ„DÎ4^;LO4¬06ibˆó >¤åÞ ßkDUä[j%k1ÉwT¢‹ºñW¡£YrÊüáA§½ÀŸ¥¿ènnö’(Ùj7²…Ù¨HMó˜,l  .[Ä‹ÎL)Ê=Þ Á“**–ÿY× Ø>Õ´öE°pö¸½ìw,ßàÏÃÖ´ÏxO Ô,þµÃ3»ÍóC•P¥á_>ŒRó†ö†¸dæ–amý÷I |^­0A":¼/µ ûÓ :¼fŽ9Þl¨\·[0ˆØÌƒFë.0‡¡ŒË¤8 žaó‹»–©‡¯ ËuÜàz_Í*幜ÌmLäíõœ-”¤Î=Tp6{ø“žéŒFôG¶Eâf +¦¤ãÞ®…Ü|ˆÁ©!Ó¼ÎhHâwõ÷+,š@©Íˆ×9Êþäí<ã#í´†˜__˜—²²ðß©Ûõ¾+Ì=BZeÎf(1íœâݫćw™/ò€.:/ºCÜÝÛúî5©;^8=@²?ÍHªÅà±PÍVª?6óĨ¶}| £ÄOBå~Ô¡ûz‚¾}ÞõÏÉa˽&Ñ€û¦wþ@) 5^: !¾_ZÞ4OÙžs£á¸¸´”GG>ÖÏT PŠíðÿëGþºtrªLJ‡jêv4*X™ EŸcÐKÚì±ÂY’)" Áé»ÉHÛ ¿è©béRˆïo½Të@gÀHàalgL¥–¶aËlT÷2šÆÉ~FÍø‡RúŽÊ]žÄ\²–¾°©Û:×·Õ>î‰A] ô¹z-Jæé†€ yˆ^2ˆ§LŽìt¶Ù»}kÁUñÛ7Ã#‚S¤¸c•Ó}š‚›&Z ³àiûU+$I!Ü­^ÆCK¬ÎŽðˆŠÙ ™ÇÛ‚TLŒÚìÖsdz\òÙðô’¤ýwµâ¥LÛ±è™e §…˜Šÿ¼AkÅÂ$y(O}¥=ÅGµë¥¥éᎆIÚe`$ïWùžÏŒ7¼d†š q¹¯?% uâó Á^‚JÏ"ª\Nù™Ã\ö ¢Ä”Ú™"—mÃ^/"óWðÖÐ1ò£ÃáŸÁ ÍÓöøréíBF̵è¼~'ËrËãlÞËK=Éq¾SNo¸Në«à5ò?@•õãJˆÛgvü»¾ °–}Aÿûͺ—Ll¦wd?»±êjKBMµ“ßœfd’Ìyö _FRÞÞùíý‚#¾’Jü/LLÕH¸¿»oœÞâÌGWá$Ë”´‚õsï|Ö„ìEÜãpƒÆJ/°¢ê¡KLwÍ“ì ðG|}kUWE?¤ü·_ì4+ ¯ª^h.QƔǟ?ó¬óç Ãî?rãõñb,^ú†pœ`õP1-ðo;ÃiEª^Â^XøErP¦Ý“ÖËoìÃ躄àK«‘¶yØ´"ï÷ª†Sd¼»eÈ®¡¶Ûõ”TO­–Ö }ï–Ò}=hÒ¢ƒ$Ê0SÍê,Y…8-ÙOTÙ:€€zZáK‚-u'<Útk¥®¥ô;xˆa¥º?BíOîÀ®uª”T^*ΑþEºE.‹—•ºÇ4ÿ@“ø’Z}IdÌýå)±ÓjÝÆf^È©mze¾v$h¢gAz“çè¯G«) ‘ž»ƒØR~,z¹øG”««•IJ»mY³Å„>‡DQYà‰!C£nGaÍYnYýDëD9Ãcë"ÿ¹”û8 :íÊ0âP¡kÎ[YÇ>Â'õ‹Žl»jqkQc*QÔQ›L¡“uDÈ/àL¦"Òøî‡:nî/)(Ý÷p —Ýÿ ìwý>ŠSUÕ•]ÆÃŒƒ¢’X(Vx”¢”("÷@®ã uÓüaá[ŒE 8E¥CW>ù¢&t2=üo£6ZAT¾¦½B‰¦Ÿrû˜ŠÕ<ÜfVîüw<ˆ Ô§“ÿjhÆÐlƪu˷פR­"€*0’½»ëëcªœ]ëòšñRß‘þÑU;´«½:ÄWëÝÎÁ³ÁUΤ_$) îyr¢u…‘¹Rã‡×…Lk÷T2K@gÙ„qÊ@ÿ3“*Œ•ÙóÆ0Äï®’9¨mÞ8"4 pÞpž¹‰x÷É-èÂS$Nï+µ¿‚žÚîØÙ)šÎÀ°‘ßçõøèòÌÌ=C ƒ¶fé±¢Ðs°'„½U+•{MÞ´Áa$ÿ*×[çp3°§røLÿg¯&:CDoÙé„?è–­ãŸ)ÔûÕy‘e"é-¤ŸÜŠäó×ø>–eå!â_¢U ê£jP4ÃâJŠxñ¹ÌÚÙRrøž~.ÏŠ—Dzݑה|c1ïhŠª}_“NÅ ÀiÅ/nNŠà»4‘þ„¦1\U05´³åïw]¸NwfÓâþô±Ët˜yGÁwTxžeüÕs3=ÓÔÚ!b!øBý8~áÏ ôÞï„ÚKŒÇJar”ðתãÉʈd&Ìru·yñYoëç›Ã5“½'›ï^åNžÈ.~$¿-#g¢^Þ3ƒËu¸sPVó=P_âú2î|cõ‘À¼Ûáíì¼JÀÐ PqFO0Wû€-Ó®ìUd®:ç;ã"eH©ØD«Ë†ú^¹xªM•ø[¬Çþ‚ŠJE¢¬¦Ô£¹Êæ×ퟀ³¯¢dÎ-»yÓXBµòîË“½µ0ÈÌ\Ao1²Ðõ=#\æT8kfó¹v„³Ø{ ®«·PhK]E1BK=*þ²€Ó°~Ð{ŠY_8Ò È3x‹dœš»þ94¦Ò!“)£:T—ƹþ\b4N7øÀEŸ 8¶9uMþØbƒ_ô.p¡Èë«QVfÉOkAÙ\ÈϰsÕ†ˆô|Äyt¾§ˆ|‚“Åså,Ýèìn“Шzîì¿€^‰Í¢¾ÛB†LË'Ìí÷>öî.FHÏã&m샬À»u~3o9ÈS? õ“‚,ýðˆˆi«åÑœ)Ò„ß ïaÇèiÏ; þ½Jæ—CHÃyÉdÕÄì÷(Évd7Ã×Àž1¦"uÓ­³ú—X¤ Ûs”Ú¬L»)+x <šÃ=‡5ëæ3·%‰Ü©(ëgkœŽ5{•꿲g÷KÃÈyKß^P€­‡ žèêÀƒ±ŒFžÿR¹žlJW͇ãC¤é;€³;þIÔˆ +¥D¿ÆîÞàÚf-2l‰ö,šzãÅÄÌOlðûלtÃjÚ’.5ÍÏ|¡ÐW7¡)äÆò 4QršÂFøaòoþX1ÉOK=Ðùh8Ú^ñù¼ãd1C^zk8¼¶Òù]¯CN8wg×z4v-ø8¶ ¶–‘¸ZW˘R'öP÷¶uOç–’KN÷,âGX0\L~Üé¡hé>ó7#á }+P©•ãsêñ·¹Ó°W…¹õ@]šËìQëi‹™lü›4ViœÝªw^´OQÌ:f Aæ`¡«Ë¹ƒ`ŠäR Ð"Ÿp÷×è;GóÁ´öĘ[OM`ztÊÙzÉ\ƒïqÂÄ««î@ÃùÄ\@;í¾“îrÅŒçôQ l êÄh:n=þ6’Ý=˜yê]ùÇS·Çd†Ï}ëô¢¡Æí5Ƶ’ó«Ç²ðÆÈÕ~Òñ`€NаJð„çTRÊ\šðCóáòòEX•_jVH>ìñ¡7é´kš[)¢÷Ÿ)·Ä¥fŒ¸ñ_½^pQÝ©£hæ`næO½§¾aÕ2žG|åÓÌkõlRé[qĹö×ô}ƒ¯žö•5Y˜{ᥟä»ÝÚ­ÂDµ‰Š,Ò¤ïf{]–Õ0üÞþ¤u®Ä=\í²Qwäf‡`"óC$!±«\qD ×ÛèÑHi&õ+_TÓĶ릪çƒV©,OíÖßé,òm>%„–žñm 3KZœÑ"… Æ`±Ê¢¸¦Áà™ÚÕVRÏ‹=z©~ÜÞ:b¸üpwÒþccîc1ÖàÅkšéßÎÙP?ÀMÿ È Êiq®÷Ù—q!¢pa5‹žÎzZP¿w¿QêPZ¬áËÏ´HÊ B±9Ñ3j‡ã¿2l“éJ迟rô«-ßµ1ô*KQ0¥[PÝÏe/d[”Å“‡o®õ‘^p¼õÇßVGq¹B`],ª4aݱìæÝÆÍU{\.Ï~ÜÇ,™¼(ɬçCL‡åT‚ðju¹íçL;I£¢3&)Y•õ,a¨òN(ÚúSÍŒ,âΕêâ£fŒÙÿU34Jìt÷Dä@ ˜D ñiš^l ]çøÜÙ*b![¹ «ÖËB.½„Tå¶[Ç;1½ÊæòLÔkòx”áWPsÒØÅMŽvso¸Yê$ž™!õî ô+jéé‚›¤>y¾îÍ“9¢Dáúµ"ÊðîUˆñŸ2‚+=òîNôz8² Í«XÅÂŒ1BM´—:y®•2ÊTóiØ­„nªufïå¾ÔG²±1,†ëÛ@û\ª›’ç2–Ôóé†P>ÏL%pÒ½CvVî3uQ ÝöÏÜ¥Ü]ðruØÚ(;ŸZû°’4$[î¡_åƒu4ÞÚì!¤PÁºQæŸ_e$’¿Òü‰f\? 0*µ}Ý"™3¸¬f2Rªû_Cï©÷®hbÂ¥¦â7କ¤pÚcÏá%a°ª˜ mcǪ•ÏŽ›vœw/´ˆ ßòM/z‡ÐZ %˜œMYÀöVP 3{”äóz–OL8Áè‘ê>ŸÖH‘ì´p¨³'Á*ù ´AR)!ñ@¶÷-³äàÉ6ºm©Ùc¸WÒ˜Á8>Ý<Âb(Ñ+sóã ½ŠXöÚÙÁ ÞÈ2.G!#§%ož&Á¤ÇI´ÙhÅŸð6üËQ䨾U);ÚƈŒš?œ'Háîìßr"²þ0ÖPï®+†{œñ³¡~EÜ71‚™¬æœÛo7ñ8ÅbòžÓ…m«@ß©ãÏ —ÁÞ5Ý-ÄHçÃfE‹ÁæâËÔô´BþiºÖudCwu×®öZûÊçâ¶ú,J›‘§pt¬êT¶Ú.g¡‡á<³ß5?¸‹f_ÑB%è÷'?R¥=+"µžý ×òt´0—¹y¾/HÓQJ¼õ¸xS£Y’›[ÍÅ ƒÌÑ €4¡Þ|¥-øl-º¬Wd‡ÒFb"=Œjľfˆ0Ÿm—“øqËÔ "UpèÇ©ýœY‡kOC+dlTL·i09\6‚'ÿܵ7—nQF!Þ)CIñfx7»zÐ¥Æ4þ©/ßO6m8X´Õ¥Îô˜nl@DFâžqWB¥1\ŠSÃDýõ–Å$n‰žæk&Oõ>݇¾òÁ?DøLÀâÆnøE; _äög! SMЫ€ “ÅŒÒ_ˆè\=ià'ŒrÒÀYƒž ìYR Ã8”‰ý9(¬b}èÁ¸¥§Žç)릾%©#êjªMwqÕåhaÏ}}ùº®NÆo‘®·b§°×¥,XQœ—3#Q¬g$ÈdJ>€Ÿ6 %¦‡œÒ$¹ÙK@ÖôE+MÚZ°{ð¹¦Þ9õ#l¯-CÔÞÛ¦Û™y}ª«~_A£;×—5¢vŸà¼:²¶jÍ?ü)dºË?¾Ç›¶þµ›C_:D„ì‰ðüñ[×´uæ­}ã!}4ƒ–Ø'Ž»J¡bäù†Ë).™8ëCfAÙ˜Amê%8ÓPøD€°LíÑÅ÷¹èú¹ÈwSuOÌݵ+Ôë¶oxâǶå©#^„™Øœ»gìÝÝÀݘÿ7Æ0òVBªˆšËâ,`Òr‹³®­õ„ÃêP¸EI‹kêB‡®œÍUç8`¯Uéä"ˆ©²ŠUûIû9 ¾Lÿ mÈcË¿7ÔGAÏVœ?µÔ§ } ð-6’†ju ¯z3 G #ÕͺbSx‰Ï"[3‡ ÃLÉ7š²ÙLxL¹"´k¾úD–ýCR·w8no_Y?t‡Ë9 ág0<õŠùÞ^ÐÃêY Z\­ <·pÉ®‘Îî}EPY‰µ›aU‹Y\¸mV¼h™œÃ`À%,¢š-Â{m¿&@Ðè·ÁŽø$¸B´ÐóÝ./ÑCÏ¢Ðôÿì@ÔB+d¬Â kªÌ$„•>Iˆ°½ŸÐÕ‹E¶RñôÛ6Ô(xŒDc=Ù0 \ ÛÞepÇôvÊ7àDl)Œ8fy«M~µíÍ0V\‰ v^÷RHÜ ”ÉíZ¼¯“È"ûüœ:»O$–üJ<ÅïÛä†úÕ¢…¾ø-9w&@ÑB÷}Þ>Âéyþ~ DƒjG¼l <“›^˜Ê÷±B»Ù7û?t¿q ÿ`…ÿ¡`i\=õ—Š%3;™d½¨ÄoÑ{Èé Ì L©ÓkÜ>I#ÍP=’'"?„Êɸ½¸¶î ÁG{lU‰šq¿ûÉm#Qc¢™~ÓT×ç޳Óa^Іiñãîfù‡è8Œ¤l<öø~®é®Cg{G0þJì9R<ëûψvpþ®þ^+áb þ_háîIßeމØw™*È!ô÷¤vw„â~,Jñè¥sQa^í“\•‘¨¨`w$^šÇ}®Ð*–aÕÑp7¦ÏyÊ4¸ŸwK'èUtËNÿÅ ÍÝOöÖ©iDmfÄ é[J'U p^Ô*”0±¨Þ¾i/äsJ詬>ç/ipðWDiÚ(ÛÕÙ^k×I &ÞöR€EüÈãÕ‚£¢­é§{´O¬¾÷à P»_ûÛž x¢Ë³m “­W”3lÚÇyɰŠGì3õ~UVV$-ãSH‰Þ Äç'¯•,µÅFœ–8§<ò¶½ÎôtËiJk…Ni“öŸÆ 3r}®S'ÂHÜïõ{¾*÷™ þˇGOz†ñˆdâ$™º)FvÛrˇËÑU Kí‰o6÷|êUµ¼‡']ëƒñr„”Ô› j‹ AÛÆÔ»VHyÔZoÔ‚Ú ÈÝFw? ”Šãyº¶{)ÞS\ÅÙaä7‘õùqƙޯ˜[)_ÑœFfÙ_QÊ’¦ï•Iñ¬¬óÒ0¯Ý {$!‹+ðïšx§Nš?ÉL.VÎÈX:†œí´¨PpïôÉ0ôfÏ¡IbíXH>i#oµ¿:¼%ºå¨&º#N÷Z*1?™Ãßê>GOb‡ÊîþÕ…šÿ?…æòN¤-Ö‘od“¤/׬Ï(ºè¢ ™³ªçýîÕ:Ýi–Óõ,\w[úŸ|é¹ò:9=kLÁ5“ÝeÔ»ÕIŒJh·3@¦‘ù‘£ÌRÉZüj[üEWo€üò9dZ~µhÅ ùÁú>$çT:J‰/Jbÿ?/ çv¥ "ê\þż4Éb0ÌÉ{ºRáï!ä| ³íó½SyÓ¸æ”ܲÉÜ_– Y nêªWS/Àwixg.Àˆ¶$ÿc†OÐXáë¹ê˜¿˜²8ØEäN[e‹¡«ÚpÀïLe~q”  !ùÆGoâ…Ý8Ðtã‰ƒŠŒ²(dž@ºýìLÜÊÉàMn¾ŸÅYE›n¹õˆ˜z£û×-W{¹¼®z˜)qï2w?ÿajDþšÆw»SM®òª‹)º«jbÕé¯UNÑ’#—¯À¿#vÂa G¾“Á.Q9ØY Z×¶ÍÂDK~Ðn¿Åþ ûÎõu'¶W8©÷œý5KaY!@˜Fk[aÞ„á\yÅjÍ‘ñãÔ;Â¥iŒ¼º†ÎLu:Û§77mI„i£È—‘-K Sð`ì+Îs´r3‘ÿxê½À'Aê/Œ‘[&:úyØ7^Ó¼5¶H[ª†„à‡Û2U‹ó5òV$Dý;—ª´^4ëJ×GÙ] "Ô|ý²`5 šÒè?Iÿѱ“öφ*üŽ '1wf±\DÖ]@Ýÿ|1ïgLž6$ l8°¨¿î|díQ³iø«`±Ï—UÿÁò1Y[œ#ò;çÊxñ¡·™¾ˆÑøpç›< ˆTF¦°N™ñÜ--4m@8úÕ÷á󕉞Ȩ]¢½üfî…5áj¬"o÷}R¶Ý§Ô;‚ø@:‚åYàÀÆ8c0%U&¢ W\{88iï+I*¾á¤õ>/`RäTã'¸àÓ‹7Ûf|Ÿ‘ƒ¡cûË^Å€ðÓ›­’Ú U\ÜÞ7.N!ÖžŽ‹·rïsäO6m·á*žÍWÅâÓ™ÀpÙ”Ý{Ò‹ÚÊ;pUž;·6µâƒ3xv%³Ô…VÄ’ ·aÕ\"Ù¿h‹¹¢|Éš-’ kòöÆ´TÁKCH›ÎPÕÞCUç°`¦;`„žéì)9\ •ÕŠëö«4Rñ–ÿ# YÎ fž¼Pˆ/5¶“ Ÿ^Ä’Š1¸ßÝZ\”R¿àœ=åh\qwv"ÿâk£#‰Qò×.‚¤èføÿS ©I;:âŸàHë™WØÿV áQ(—cøx ð£´ ФjKæ ³Ä !pí,”ZÁp‚L¢”†ûÓ¢ü¨z®w” ys…^EX.n„ušé É. Èúu’ù_äs΄ìk!ô­tº ™kÃB†‡•=g Ç›]€á_2#êÅÏuQs©œ2n1% ËÒÓv“ž Ö›FYšm¯S¡%ê<Å }7ù À$YÜin~Ç<‘ЭÉ!×*HÕÐ .r*Q·à_~¾å*ØÊ8ùœK˜ÿE¢N‰»I)ùjÊ=ãûqïH߉ó7%Öƒ½îÏ«‚Ò:¾ªºÄ©„ˆ¢k¨îö´aLb^‡w…LÈ1R·]û’£Ôá 3¹Î02—Ájïà‡šÌE èB¤ Ùn0¦Q ™´.]¦#ß^¡x)ȨÝÝOÑÌ>(`Â9ý&Æm²]f¡N8•ÅaŽ·R±ø<×¼üÛ¦,­´Àîø÷ $]Нaý“7¬&¦jÈYMnMW;Ív‡™2Lcç‡ ®ÊãW .@5ælUÿ>­†ëî˜HÊïaÝl¶d0"&“"¢Ñ›×°`¶9®äìù•ƒí0oMjê#áoÕÄØýŽ1@οmCÚlG°!c&º…ŽXþ_l`žüÁI–ˆ Yu,¬½PKXàx˜ë’Ñl¥yÖ†öÚ@Å­ÔXï€A‹o“øå°—fË}žE4¬/šZê*:[ÊÓE*;+›ÊM¦‚~å“.ˆ[ÊA5 Ã&iEÙv°:G]BPÒ\j¦ÜI›àÈh>QsL9ùƒ3Ï5smt±¢MI0®fðîD 8ÜÕXÀƈÄAµgR¿¡a€é áåžµ kÿÿ‰hˆ Þw5º|fÃ/'cš2ÿ;êAg ªÝÉ{¦©¡1”¬€­~œR0üç;\YýG À0?cE?lfÉY£• {T`O÷zSq¶0zn$*ÌŒXI@½éø«.Þ"|.¿uS*BÌ1­6‡«g-Ð CC¬½n[Æa:ę́#xÇHA¸k­Ägä¿^¦ëPÇÿ²Ò: jEûp¦øÄØY±þ¤qÂKè=cÜ×'K¸Š¸.Ï<¿o{¬Õ.ÄÔ1r‘3ü½Ù5ó|ÿ±û?æ´+O¾‚*0ž#ØÓej6A†¿ˆð8±ž-å»Rp“Œ©ÐJ)±qX<º˜‘›ÜiÐ Î}Ó`-[qr>TÜ#˜¥YêÛ>‹@¡²ì‹'ûâë¹\¾šþÜ$æO¤¬Èøs„ ëž©´ãc$¢Uo¾Õ·´F‹iéþCª“FnQÒT}ÓŸàŒg”+¦H&Hª¹›ÁŒ³™Il4~:—+åk»Ÿ#ÿ@öñ^¦u?d!ƒ@ÏÓâµ#Er¨Q{¸ÖXAk5u;hÔœü i7Í =mèÉÔŽí)b’räYê·,ψu‡Â^hJËê¸~¢ßÓ°îÿÕY Rü‹#1vô§°‘@uT±—›ª:„|Þ(É8k§£xcêÈr¼khŽE„Eû¯_ £ÁI,ÃçLJêåpgXõÏ6w¶ü:!lkyßµIL5@=†& XqtDë~Kû`ñÈmÞxÁthîZ ÀåÚí½¤þ´$¹J-ïº!KeØ"s‰€7 Äþl!&# 3̦81p‘¹Ô›Àè)Æ:"ijȷ2™É\-PŠ9Ôú¦º0¼"˜žŒ‡aPueAÕ²úÖ'áÆZ,3'J¬¾Í´Gæ¡ <¦”Âi`ÊœT¢ò2Ë,2Ì;À 㓸ãR/‹ú¿ ¤ÄIô}Çíâx7ýe@[Ôò}@4bòÁ\/騾'ÆþýóŸt›ÕÈÒ’;Ê]QPr`_ò§ŸN‰œôŠø_ÄšÆj¾Â˧J‘¼^£ç—gmÞ%ÉܽVæ-·iÐd´˜ªZýë[¤ÜÛʈánf¾{n—šGT0\:„ï•…¨v™&ŽÄÃé]À¨óÀkåô‡ÂÅk›ÍÏ$d(OXY˜)‰qêz"JNMÙô¾öÚè™Åwo o:6Ø@1ý.…Ætâåò~\™<2~_ï[†?7ØÆ“7¡¿bÕ>ËD£ÿ­^8ÔâÉÚ‚¿fò7/35 0i—Ö®)ìþK²Èù0¢ÖØ¡»Û0Y_«<‚$ ©¤Ã-â&•ø\j!"åµ[,ãÙq.¨7ˆ|®Zƨ½^Áîv¦ r™ÿz¶ç)²Ð#±iMÍq’Ö…»/æS+»ÕmàiI(ËÃ2$eÀ.ñ7+‡^x&€7Í íñ,\Ÿ2F l-Ü^~ZÐQ&õa êýlÐ+Fíbeªu-ˆZ\=Ê9ä¥ÿÍÑBH£{a$™de‰ªÇ7wDã¾ü/ZzkÌœCtêk,Í+MïˆÒ›tñÚ¯œRÁ €íE‚ï ¡ûMù°u‡ƒï5êy œjÏü›ª:@]d“„]3=8mRa?ÒÂ[˜ýRTt¸¿M»Œ:tK–»“us}LíY*ðø§èy¥n±uÜõ(Ks%Ubï¨ “š§'w"y#@ïqÇË|{.I‘I"%§ò«ÿ[V¦¤'ÌcmˆGþ»ìv±W¹%9-ÓI+|‰{ÉËÉ\öö¡+¢I~'˜Õµ2ÿKä{–#å¿¿ÚA^ËñSh¬P)âÍÚ°Êb½¢œZ}†÷q"+Àþt)oΆ³†w¹¥œ­74üìì?úðA¾\Ä §õ³]nç /Räò¼bw‰ãºlG 4; Qì'Í_ïüŸ„¢$W,›Ìµ¸\pÊk“›Kèµ¶ ý<ó0¬cöMÙù8æL㟲X9l³„þ¾Å3Ñ´‡†eíÞö˜ƒKiLèoù¥(ÏHGZ6¬¸N±…ÐtN[1S Žë=t­0ödÑÖJ¼‚`÷ÿ›T1Ü¿“z:ÈÜfÎ\XÛ(Œö%±—ZNÊ£?¨{å´N– œlíhâ!,É›3{€žÎãõÛ~ÒPù=€Q‹Ï¢Ï 6á"µ½‰9…èn÷¯jžã‡X±ã;+‘,ž-ìŸE7åÀíô¦ ,Ôu70VSý§`á™Íp"GýYÔ÷JS¾#×ÓÝbgƒy˜•@ï¡„úá QOLçn|€ÊÇWÓ©vb¥:Ø^`/ DM»¶×é-ã¡»ãl‡ Cö)Lsè+PŠp‹/Þ$亂1Û±1¶PþúFê–“\a3 ö´^å*9ëEY\"ŽÙô»}”@gÖ2-}–Ïxf'£7²²7SHä³²GÄ"böWó[Âaµ´3C,ÒÓ !=ïuÐj¢þ0¢†½kNW--nM‰õV52 Õî ³¶ô¡¨+ȉRœÉm¼í©¸€À\°@Õa/Šæ’ìÞ¤DIö i„lØ?ð=ÎʆAõ 6„|Æ­HÇcD¨A˜ôWÝ^ÝÎ㈧X«ÿ¯Hv‡¤¨@ÃìHz-áNÎ<ðœ#2lpé&}"õ–ÓÃ’ˆHpAï áÑL)[!ð£3õ@&œ®òmnÁ–ÞNa`²„=þ:]ŽêÙþ JÅZ4òUH Šî*ýª ™A2ÖrÃaŽù¬“ÿŽ„îpÊ_M]ê°›i­ÒH¤Ð ¥¿Å|û €(É1$\ìºøwµH·¬§ž KjoÃãñ…Ïký\ˆ¾½©%ß -¤Ž‘1νýÁúDè²N\£­xű4Ýnº,jµâÛêûİÄ`¬ }ïò²m­^¯=0JªEòvã­ äìñý¯èŠc¸ùS~W°*\ë„Ëj˜lò«e,þºQÿÂLõTGùr ¶BÈZ¨žéæj£Ühÿå¹g5®Ó¶’XRäõQ”ÑãæeÑÌ¡t/œéä Ž\T+ÛQu¾ú&³R6ê+ï^¶myÈ,쉡- ÓYÍÍéá4,Ï °äº4á¨TئÕ¬ ¨?Î3ó&Àá~rïä“ î@†sß›ž$ õÀŠW¡»ä¸õñþéiƒ[c ”GÆ(Žáô§¨ÔDÇÒSÀbÃŽnŒ0:ÉOøàg –ÛºæÀ¨ç·Ûö!ÿX ÓMøã‹ã$ÞNS?‡N’¦ >"À}éÇåÂTmg$_#ƒHÝQdÌ3ŸpÊÿ–§En1YМLºìÉe’ìè•ÃÇ&+•cÚÒŽ7;‰¹•ç:Áò’«Vš']pSbÏSÈ,Å\Ïüm¦+ۯׂÖ”»¢sVn¹Ïn´£´ÃÈþ,…Øú6»ÚüPh\CMNñ³•‡`)òÜIº~ åBžnãŸ%×ob‚ŸÍûòŒÛ¥ÍAD«‡¾ZBó+kÅäJFucD;9Ù…‹ª—Ðóäç }‡Âôè‚ÏFLÿ¨^ïðC‰CVÞ æM#óÕÛÓQ5£Æø‚uL+äM¹*i.SŸ·¸iyÐ^€dŠuÏO€­cþ‰ˆf‚n~Ë-¸˜ÃŽøÞå%oäÏ÷ˆ†ý¬êDÈJ/ýXº0ÖÚþ\ŸÓüQuÚò C<çG/~¸¿ß [ìøhæ²”‹"æÌ”ñfNä…ðê(˜ç±8²1x•V Ä ô ã˜Dn(Öš¿üÇ`N :èîÒFQxå¤Zíáøæéq4cø¸Åûí Б£)`j²¼›F3O2Oû~Òªô€¾œsÆê›ïNMCfâÊ›%+á(ÿÇ™4æ&]ºYŽ£'4²˜ÂÏJ i95—ýõ2åѪ¤à5ÖÿSÊö3'ÄfbÎÉ¡ª]ÆK„½ÿg¡‚¬T¸·ãbSÝ7$ ¨P¶g·âVDÒïcÍhR›ÈfCmT Ðhu3n@GRd‰}DM˜N(žðköƒå$ý ]~xYÖø¢º%<ö­¢´Õ"r ³›vïy/|ËNmý™¸=íkHÖ㻂ÅKFå,ÿðÏh±zx/™G<|‰´ˆæ#£ø×ùÄè,µ—Œ:‘Æ“úæ C²¹E…w~K݃_©ªzƒãË WuÚjÙ¢+½ÈÌ}‡¶>›ð¸‹° ñ†Ö^õõG¥4dß›@m¦~~"$0Ë™épÅ-ÅQ¸ŠÃ»üò]Œ1e)# !²h¼ 1yíàJ©ÚâR!ÓŽ.kEêþ":m&¸JŸê•ÇPêÜW­Í*&p]Ì‘¹0n}›™ÖëpŒ|A·l¦œ· ,©æé“è SÉÇ;ä‰ÔÈë“7öܤ-àÆr]ðÙ` ÌšÖ‡£)t© Q%ñ[f5÷(4gè½G¡­Ý}C1‹ œñÉf0^@pŸx•: GÅ?(,Ë5»öpà#C@3#'4y…wc^%v´ â[Gp…–=ÐÍ€r}Õ0ƒ2·¢!ž½À‰(¿¿².?Çš†(Ì÷$¿P0°a8"VJäM¬.£8ø±ºˆ™9 8%Ðl`{qÐÌ––®7Ö3?ÅÆ‹W†o P±þ®kà›QUÆú8ï›G̦Ù²ºdÇàó¥a¢zDí¨‡Bo¯ê–› ×4ÊÅ!ÜBÓÑL¬?¤¦þ“tà k‡À‹_öçí«ïØ‘ Z\0ûtŽxÌoÕ5tŸàyŠ<–7¼Ö1mùy±•Jbê‚èŠ(bõÁ)µñï]–ãwòŒ}P‹Ï¼eV(@4÷8伬,š"–ügL."‹»$ñ EÈ€Ôh)¥eÔïvLiâEÇOpþ€÷»i¨•Á®ío«­÷ éU1²¸ÿãmbQˆçbIæ¶Ø ÞŸ¦Kl“‹{[—¿”PÇB€"[ú~O:U`QVšFcô®­Ò¼ùôñ9g†Ê¾&…-S”gó!*tÀÛ¿?’>‘Ò\9¡ßºb¼`ƒ'øýcïÆš×;ÖïeStKŠÏ4Ï›¥×ªíÄÊ ‹²°‚q„sôuHÄLÝk7 ÚxÕsÈrœ°mµ"W‹‘hàÔMƒ¶¿b±W†•A«°{¹'ùr ©»#ÊÊnŠº‚‚vÏ&Ý€•G8†º_`xk@A€;µ3WßbÀ‚ÂÉû ËãÅÊpà·ôc1ƒiÔ‹ÒûŒæo Œ×ÐK7ôü‘þD£ôy@J5ÉK(ç’;žBPb¢n–!žú«=|Ÿï6ùïn(„3©õbr&Ó¯ ÈiÝŃ?ðå¯Å}-—=’žˆ¯»{ªj}¤Ì+X©Œ\îÄ“EøÏ8-Š'õ«9c¿©W* 0D “)†¸Øn«åâ8™C®6à´EÊ©¡i[,4m4BÅ5?©W×¶¨š‘ç”Ij…ª¢‹ýmú}hŒTOO•i8m DÈ›‡üâßû\êFYWcËà uÈOIRùd…È•c¼ÿ®&†¹f\6ùÒê.’f΄rÀö¬-§(OŽäTrXß+ë•Öjð¬xp,$a²b¯âä‰( D×#×è÷¥hŽ90\ÒãC½z~:îùQ3a’;ÝZ}îŽXÇæO¥âžqWB¥1^^W<·«Ô5}Ý[¾ýó½M¾ó/÷kÀ”¦>ê[-Ÿž-™øÖÆ'LŠuCÞ¿,EöÉ•œ–t\’¤¢ƒ¦g»Aõ10ælþxe‚vBÅõíC¦?ÿf¡¨yr*¸§Æ#°HÐ*(NÉçë ‘«Ð0d\N‹¡¶Y®çK¶Õ!èÃdúëÔå&S Š©%F ¶a«¨~èEv¨ 2Ù1[-g)gÜÛL&?›¶ô&U/ 㬠~Ãòa|°*nzñ"kóÇ>€na"úˆ%bs1 ï¡ðÞÉ8EÿSÍp\ÔèA´µÄð wàqœWÅóaa Q¬&dÇ'h†q7¶{™»‘uˆ/Û/Áûå%õ#VùjôŒ| 䕆ú'KoeöFɬ2zI¸Dþ-V!p`” Ýòú#,¿Š¼rÜ’[,üÌÛ ¤Ã»ÍÇìUNY¥Ù«&ξ©%Ý?OÀß׫‰Ðf¬™ „û³BKççº]2ÐÜ)%—†è}[éO$ì½WX¡µ‹È';¬p ƒ1Æ ›794£ÂçB¤5£‚*…î‰`Ìæ<àì­ÙÌØ(2¤E#öIdÏo]°‚û<sL¸~*ô NÈæJ¨ä; ㋞qøF™€L…hpøAºS–6lV¾H"ÛÓ¥Ú}ßúd]#VÉ÷‡Ûn+y®9¿-*º…ŃðÒ´(1o¿võ$ëd1šÐò½nìÀ¦K éðxÑI”F¼9é9¹Þ ëè¥Ú5ˆO_ß3ô¹X2‰Ì%> Ö°o2E’Ì%ʽæ£à¯°y*¹Ã«i†£Ž¼IÉoN®·ŽåNãþÇÃ<µKò’ÖBkZ„h#L1d·+¢ÒIA%ëáïez3`ãøŸ€oÜq`”é}áÝd¡o³@¡%Œ„'Ó0ÂÞàt2d¹öc3ÝÛe,¯û}½Ð&Õ á¦%p‹'…Ø:W{w@/-jbÔ×$ÒÎ=Z´S|SV~|lºÂ®¹‹`à«#{P±õ-#xoó„mú ÝqƒñOÛ>Ä¥÷XÛ¼rjœ²vŸK&*¶%$”2Üt¹ßúcA‰ñ5 À¨ÉŒ¾œ$ŠÂ.'K•,}ye{Oï^…µ;ƒõ›êì'µ+H!Jö—€• R»Cm3‘¿¶­âE&–~BÊ¢åÃU€V[ö$Ó&1}íe8¼ýŠçk€1úôŸ2/­FhÒî£>œD.U+yBŒMÛÙÿC÷QÑîäVv‡ Ã" wÒã³hÕo~p—È• ‚©'•ó.ˆa դʟ—™×ôFdÀ n×2Vp§õÜ‹áAæÙ‚|ÿ£‰uˆ7u1¯äôÈù®ƒóø¯Ê¯ƒüúìÖŸñìt{ÊÉ~H•´õ™   ü„6Dœ£l¸Άœ·´“(Š«½ñs Áœ¼ 3·ª Fó£ÿÚÁðaî~‡"¦ 0NW˜X¥¾'±ù6xV† ¡OdêœZö%·ŠªûVûtŒ\º;sšª LÔÔÎ^zWÕSwH[,‘¹$1B÷Ü-ØS¨2x§Âsž/Ïyl,òŒŸŽ ÑH`©+ïû„áö:t>*€Ã¨^¹Êž™iÌ ¤Œ]y±˜U\>@öôfrT­¾Zð!WàxNåö(¦ƒuèã“Jr˜†Õ¥Fá¬Í‘ÝïÖ÷®8~˜uÂ$¡GþNyš~è³iYŸË—%KCw: W_Ž}ÓÉê‚l—KMÏ1 ›^¡{ÀXTA$ ãPîx#-è4ü“NÙ$žÎŸèüÅi¡ù¨7ư`‘M”Af¬åp’svÅÅýãÛ÷6FŒ}éCU›hpÙ¡ k(Åpß-ÚuÄ—ÓK”…b>œwü|ÚØ1БoÍ~+e‚ûøñ+x}çW×rÏg,fú7Í“pŸryŸ¯VPå¡9û¸ºrãGuNºÜÀÖi§"2½µš¯}†~€Ñ Bei*Ï]Ï%’ET÷9m¼7)""‚)î£øØ0 ²U~Q¬¦ˆÓì¢Öó±‚4ˆE}œ£,É.ظ—;ûÝût¡€æ'y¾BVjÿPå®ñ¹U ¦”¬¼(¢n¢<ÚË&ò2ëcûÏxr^“ìHŸC{¢¯0 2ÝÊÛ¹¤ïŠTømeƒ·MÒIKiPqˆ ÁÀÀú¦b·ç$&s7öòµ­KLÙÿJKh±1B{I{Ôtïc+¹o~Á-wk*Î3½Àâ¥ÈÈSFd;)$Õ>>±»z7°îvÿI“(@ƒhåž?Ý@8ÐÔæg¨fÚ`Ù~ú8®§õîö=ý 4ÚG+»DÁKF Ï:ž@Ε¸©¿_çÀ" „Oã'^”͵å!]'lœüo¢7ËmRZ春¸ ®±ZcÕë*\õi2활?.Øk ‡Å†}„i(ñTÁñÃ|}èü‘ Øçè/t —CíÑ=yÖU‡%¦'HË•W",¢:l|íƒf¯"¤ä¹_á@'ÄërK§-pÛ¬˜qÃÐæª^ÅT+S^&Ÿ¤lÁ1ÖÜù$ ±ìí>í8iж*Þ…óIÄfÊéŒò‡ûIÿÆ‹ † y¯Ϫ ê¹v$B\»mQ…?tŽ(`[öXµáp\¯vц\ ¾š.ÖcáÒO˜Pœ|Ì}ý:Ú}¥š¼½í÷Dr-IÒ!oYh5%óX]T»øR'ôNmÌÿ€20ÅUáillŠ Œ”GÈÀ°&©U™²h½ØRæÎ8Që²s㈤Յ{ÂRt^뎗èè3¸T˜> fÿá†pÄIÝm˜Â„r)…ÎYİaÏþ)@}¿FWi#è€Ôl 2 åoõÜò¾™‚B  îH ³í… Š ÔÌ Ð^,°¿úCl¸«žÜïaÙ¬”åÁ˜!)úþ&È`ðBb×D·“RÙæÖöe3l%#ˆod’, !$G;ÜUa•ÓØ‚Á‡«y.E¼Ï¿—4ÿç?—еAŸ.ÿ‡è+¥ jÄÀæ¨j)’ нÆ$¡Ñüô5bI~•’JŒ´$8ˉ)QA“'öÑÛ¥à˜wït&*n=(øã³«ÔÿæxÏ…E†¤ŸØæz5ý--µç¬ÑlÁ²E Îö‘–t§¨…ÛÝD’ù-ÈD†U+u8+E ˆoî ÄÖ7}ÒÉE=˺%~ìFÌM Þ±Ò¥¦@Ühqë{­.ò/Þô=\m91Z ¸Œ?ÊC± éæzÒ?)7»C2ÌÊú¨˜’6Þ˜F.Ž·6}HìJ¢Å¹@?†¤ˆ¬PëÂë̇!ÕÛÝ YT°!I6àèö.H±6×¹–Qqÿ"óïÄ~Ûær„6‚#hôÐ}qK'q^ AŠ[Ýh§óÂ{š‡g¤ÅZ ÊDòã†ÿlWuй¦Í³ Æ¥ú¸¾s!æ™k2-Në ÅsG¦]2œû dˆO(ôó7H/€‹-Ö‹c‘:†rÑxC},°øý;uWЍ¶kvß`!YîžÁl×r%ß‘à\“MÍóŒ }½9­ËÊ­Z‘-Ìð a71jÿmûrY¢oúŸ‡P #± ´ˆ" ºéqF's½TÆÙn‡šîÚåZÞë¾Ï‡Müƒ¼ ç\Ë#O%.¯_^sæËÁc=1%=­Å¸ÿ~ö R—ïâ›F‹ _œs…ÝðýN¶‘Scß{”ÝÏg(':ŵ:¥dL‹ˆ0XŠÑ=T'¡f¡+[ß °2 àȧ€=}]u5Zaƒ…ˆÅE¡w¬9;­¤mÂ/Z~÷*->®¸L£\6žvPW?½÷¤g_“êá%#j§ó¤åS©‡MùÑ•Â<·2êC³9 [Bó¶Y£jšåÂô.$¥m>¡áåiCd‡<ãYJÓ?²€ˆ¦—TKXyÛþþ­Þ-¥m íA#*YäPÐ .ãjS³þ׸!<¿ˆ@2]ó0?ü`E‡0 ’Î7Þ6HÒÖò]ãöÿYiðÓNá–P£ªŠ°ü÷cÙÁªxôÞ[‚)#+ˆQ—Åj5ÁGá`pr|ŠAêÌì¢Vöè;x1±cu¡•ó0؃¤±ôÂ:”™z3Gbyó\½'ÙZt’úGåÎ%åê¸èÕÛ$öá]£Á©¥ÓÐSÊWޝïÔ`C“‰¢×X§Œ@ðÔ¡òd,!/%çý‰.©«C=4YG~. µ;W/ÎêõgnN-LAí,‹,Õž5ï"¢üHèŸJ‚A=’Òeí°úù}?œZ1c0 °„M!·þ£ëUd½‘î%öÔЪޮtx}”3«S>àR—~«ò¥e÷ëÁ%ÝT´ýÕÓŸß&VTÇ1ª/˜™‹‹È_²—Ѝòmíƒ?Oº&±|Ehçb𠚉8޼*™5M¯7ÁŸiá–ÚŠ€UI¥@Í84^jZp Œ=Í G%¥é›ê¶»ˆ©³ÏÍ‹• ðšr2!Q/çÖ°ÿ#2Y+—ÙtÜ£ù"Ÿ ñ«FY¸“4ºþÉ~KMxD¶Î½À“d»'˜¨€5{ò«#È+GØuË@úZï7J줛úTЧ#…Uú¦ ?*àó6™ÇÏãß¿€Gº”@TA ádì×—i;ìa d'OºdlàуÖrgÍf¸uyN¢ÒˆâG¶›jÒ…±B¾Ð JƒƒŸã-° XìEÇÿ;Øs‘ÅÐ퇾!:Á½bè+—‡² FD9È`hi}*‘lÏyvaó=³t’•´Îƒ„—;'ÁèKÎW·ÁÀ T¢ 󨹅ÌÎJ–}ЩðßyÂ\(qÛ:+äÜ|ýLš½8²mGHd3KË@–Ò /¦\'o…•Vâ `¸î.«À›°–ߤ€Z¶ÓTô“RÖ~Ê«z#ËŒ(«IeÏ”'™_.r‚CEàjMŒ?+H…þ¨Ž!Øô†•zWì ·f£¿g°Ò5-‹<¼¥ãAæãv¦>GºæyD¥‹ckõ5Ót?º–)"†ß”¤/€ù?þ¼sAdš‘)Ç_Åuå' þ”êÌ´4'OuI×.ê?|¿—^æ5FsÔ‡(•m./-â'ycš08\WÿHY!'ÙIÈÄÓ:1:Ç «”ŠõÛà|¹µØÞ^ ˜‹ÌúÐdÑÒ‡Å¶Ž¸ä!¬É`fNl{i0ºz…’ÁvyâÈ$T<žÓÜÑõx%ó繓±B 1œä«+ì l#ùwæøò jµöVTJHÖØ€*ȉ½ÙÈØ~\k¡ÿ|° œ”ܶì5n°¯Ÿ¬¦^¶tl6¤9˜ÿXó.ÊðR²úµ.¢±\K@xd€Åc0Ýò]“Jag°¢Ü'ªÃߣë·w0°´xÀØS‹:?Á~c M.¦þ\I€Ùµg2tÉ$³/†xˆÆD€3ú—ío•ÄM‹fD€ö>::óù¹T98z¯ A ¶|ìÇ—v@ÆÙ %pªí=kw|nõ¿tʃ•N^êYê u?#÷Õ˜¦jÒœ:Jþޏ^_FP;@e8ùLØ»zËQg°Oþ´ÀùÇQYêIE\ßòr…jÕ¼.µÕ4¬Æ¥,•8×b(T‘N#.Å2¶Rëá½ù‘˜ãr§'+¨ „ÖMñS¾VWû‰\Œ© ~àjÞ'ß ‡…jo:3Ü¥?µ¤[ýÿ¿1¾ñ̦¤Zð «“Hð ¨P™¹ÆÄç—25"aÙ·µÞÂêw8R„¿œ2“†ä+?w=V؃ò*µÓ&¬D }î39²QÎŽ„¿À¡ÞŠ4©§yç¾GîhŸd±åØöýÍTJqÄÝãåýúÙO”4åxP\$tM)DƒÝ†@t 1©H«wwñV´€Ýÿßâ<þ˜c4o~$ô&CǤ‚T‘ôQ=˜Gã ½“dNL$>\LG;ªñõÔòNétLÌh´?ŒL?²¦ï9Þ$¤ÑªÏ¯›;FÁ ­lÃ. ÕÝV£øíÆŒWɸ@´ÒÞb”*åõI™«8ÝSê¥SÕ¥u¨;/œ=’dÏqNç®k[vï9ig§¥¥@ýub€[¿—&ä‚2ÿèâ&Ç^d)g]ºy–¸Š7§þU™­7zò8sFÆêïV±(Æà3ô, ºE€Ä`l6â‚¡áÅ‹Ïõ”^µñBå€ÐÞè»ÖJâø(lŸT_ðå{¬èÊI¡N™´‘Ë2Ùž êNÇc×4±OбóaÌdÌjPŒ'Î÷~jñmNt¡±‹åoK UáÓÇÜÿ*Î@ˆXp#ý”¿³ÛT¿jåÒ¼Âó}[§ÊjvªÕT‹û…¿hˆ¿Qì.;䔩텭O4± G +Çyå³dTQƒs$‚¡mÄ•‰¼ëÅ Ê©GÁ”OÏ;¢[à#{N«“é k=ÂØò$´&¤ÞÑÈvDwö2‹c|Œó×Á9®XÔȯÄ_Ç³ÖÆÏφp㎩mÕyÇê^ñ%jm„à XC›¨Ôážë¸íÁ^Æ$,Aš¤j¯‰jãþ­)Ø?÷·„"1÷û8ÃŒc/ÏÎrÆÙ*‹19]IÊî?áz1H–°TˆÅ"G÷žL3ô-û¹9. ú¼Ï?KaG<Ñ8°Uø”¡“.IOUCm¯óEe†®òõûN­lm‘ äø^$oZïÔÆÿ’­¬à5d°êÀëØ3õ)ü(J_¯ +8ܬµ$¾Šdãd×M5Ž‹q)(3acv\Ù®‰¦<€ÅR„c°›LÖ4ÏÕ#B0ÏaËT¸y†GWÉœÇ0":Cs—?IwGå¹Añxú•,ä?æBí¾ ÈÛ‰ Ò™¡q½Ð'IŽfOV7ýß„ªméÌyÜ¥äüâ­êÇ‘ î•mHÚ°A`T Ng>o~&p%º9î;„ƒ#;€Ùe4ôA¢Ç³†É¹ì7ªÜ tä‰=û{sÙTãÍa¹åëå#CŸÍ0¾3ÇߟñìÂâ^äC¦ÿÄÂ,®AYÌ©)ìÍ*‹«ß(ˆ¦âCkR}&o–âp ìÎLªWíg,‚þ¾Dû#*•ÇZ¬7𯟰'I†ÃšªáŠÛùmluµ8×Uª…> =ŒArfÐU¬}é \0íµ•-ûH~÷Êÿ¸rØ­»Ã^!p*k]y¬¾…ýY¢rϲ‚¾+„¬\_ð¢ÖŸ åzœþož"¬a3ÿ«{^Z0ÉVYÑUÏýæÎýD'­ :¢bž‡F7™],eHRm±Á|Ã:—‘IÞò3†ÃD]+Õ xg™h[¨£Œ¡7=c xz[LËöBhý3.&Â7#¡¸zä”R¿GŸb§Ô ‚‡µu3ûÃ2å*´·•$nGpÄ+ÖŒw¿tõD“ûœAÏ„8ñɼuÕíÊø_™&†<†Fã@C®•A™§+b°m½ÉÚþ·CîÓó0™¶;mÀs¦ó ͬTÑÁ&e¦ÜƒtH! .¯9záÿ (Q{Ù# :p†ª5GÝ#ÁŒK7IærñýV° pŒ3v¸È…×c¼]Ãw…DZÂÿÑž~ÇB]í¹æ8!ç+hS_­(ì« ‹²•éë¼-¿ÕîJøÖ—;töö™Ì(—R6ýØi³ÑÁÑ£êÇ%•PýŸèÖô¿í \7ílxü©;Pµ—‡žùòsP¨“‰àsÒlå0¬œ-LkƒêY ñ—1Gy)̱äbLrŒä u$oô°!Ëñ×+7¡l“á£)k0¼ì=ëV¥ÙZ÷å0 ¯Ò%³òœˆ‹â¢¥îŒ:¹M쉜«ÙéV¾8)‚]½{žzï oxýEƃæC.šsYøa™üüfño+“ó“yãAkþ¡ñY><˜c÷ÏÆ0ž¼@‹Bc*ka[¿™7qýAÜ=‰h±Ú¹uçïüÂa¡_io¢y³O“PÌøÖ6ƒ[Š›ã@+.µ„bí/¦³8`¼•.ëñe¨W„Ðw¹OO‚J° MýIÏz%, :ÿQÐ2¡ópiƒToÐQX[…† D'äÜ(TÓPÑY³,HÒ[ÏÝ¢‚ ²Á½T´c÷hFÜIÜ* s¿N·ÈWeæÔÚÆ` þ 9Ö]3GþÉ«G3réÌL ‡è›ª¸zÜá²Ï/aŒ;Ónö6«¨‡ó]Äq|JÓ§‹ËǤ:4!6¢†4×–Ó5>ÇŽCÚ»G VÈ,ËÓ»t{}-ÛÑè¦çdïAFÜNÜLùs°âÌ%±éœ¯A}Ëé«;x9‘HÒ[?‘³Ý‘SC™“p™zΟè ã72¦a% ªÂ4Æ–îAðj¢RÿEõÊßkæP-Q°{ÿãd9ET„ZÈ`UÓD\Ró“˜÷œ¨ (Wi"4øCZ¶ðyðö`ó³Ç‘N†®GhŠ0`+ส^`B0I-çv©ÝIê5ìɾ4Ò5b¹˜k«O;õ?ð¡:¤‹\q17íBŠà¿hÅj{0éÉ,ÜÏîFÒ*è s"ô\œ7©°ÿJ|Èîñ>Aþ`¢õF³'»híÔÍOEéi¥ Ú|@ò¦"ñ¶^WmœD¡¹øbئ: ¹†Û›r<•r£ÇG.»| {OÄÛªƅ)-β’³= èÛ0Q¶a˜b†àâÅÙéÝ‹~Ùª^«ý&ù¶Ec9uÏ @•±©å—PóuR½è³.¨Ÿ¤~_àƒB"`ðîü]úW½`›Nº¢ÚrYSºµ•ÂÂq$³ýCgÖÅM¸C.i©†¨»‚H(w¼?^ª8¼¯y’ˆ£D 🌣VOb>|pc6(¶oVgØp0[mSì…íçZò‰üAü*hãÀ©zºÞO¥›S¨¬ÆÏgܶµ°Qb/§!#!{÷ÜK.•¸ž§{JZ&pžzGò'=ùjzßRöv4³JÒófÈm-ëÊœzSÊOGô>ªEÅÒ~rhþ.º×‚þL ¡áš#ÿºiÿÄkÔ‹9Öîí„ßï?ôf¦‹ U-Ršh­]¢Œ¹‹¯Ì»êÍ™=Ë?ò]L\1Nå\—\Ä"‡ÿ½`´W}˜ V÷°ÿÈJÐOËáâ¿GS­•)fNCÉÑ0Þdž`¼3nWoÁ(+*ê5Þrvƒ²à"¶Wb_'yîe¬ëíDec„]y“ê6l&ÜÅžä¶Ä¶ }oe`²7§Fªþ¹bë±AðªÓ'«¡M;ú«(MI£ÂKDP5e¹©uoŸ3ÏׯÇJßî2š…8;9o'ªÅ6‚µlÐŒïo& `$ggqÀ,`~\Û‚¨iñ4ËÏ=3‡ˆ5ØÖ¾ ·"Ÿ2Сx ÒÛÜ@ÏÚÒ¦Påñ,`i§)§>õªÝ&±:a!^¡Æõît?¡¨ªœih½ÔYdãötßñkL•ïÚ'Š è!T‚t㪳zD'uoÏrŸz'±í23yo‚‹$-ïª:„èxšÌÖt&>œ Šö(–î§´IÀ·Ç^É S5rÞH %½Ö¦þ^ïÚZÛðÝ]³èüàÅcÈ‘=Tø’ Y WûŸªÜ1ßEZhiî(Ý|æ®ÑÚ¤©ïÑS«ü¸>«[YÙŠý¥g¶ªë<`lÒCûÙƒoP»_Þ˜6EL\Ûµ”å>K‚»Ô0òàÐå4Ȩ Œ …d”Ìa®pœ‹P?œ` _¿“õé½L*ùê+Ι%@3y7\µ,´D•–¼«QPЛƒg›Ä¡¨âñ„øßy}4Œ»¯é!¿i²S¢šï÷;cƱ;¡li\ÆâEð0ƒí3†ª„ÕYDVlrŒÝ!8_*r##…–Í>ƒöލ}ͯþü´óJl‚ÝŒ,q_³^8މ¯Êø,‡y‹cσsw_BÞǪF§=ϧÊöVƒZ…s°#FÞü/†Ô¾6Yëª[cõ4þ‚z…}¡[¥¤¦qºÊzÃÈù®–—~ΗyE½íôÅ¥^ÏÿÿØBp °¾\ìûËú{RqÚ—¼=å¹Â„bu"Îѳ3;YR…›+‚’n¿ Íøç}-2<¨™€=¼GYÜîhú¼~Ÿz‰vB“ræë…¤øÖŒ*ŠV;OÎ/׺˜‹ˆ uyÎAšlÆ—]ÉQ>iüÇç®­DYNß´ÑÙòvÚq`]s·ù’YGM’gѾӸÚlõƒò®«Ad.Öu3ÈœX¨VóaäzU¦Ž [¶_”TÇ¢·1û³drÊHN~vì¯>í%©Q` ÷]9´ÊxÛq …(0Máí¹åÀÇ›¸´.;lˆÖaL­Ã–-«¨Me‘J„QTZ.«âá†r'ayž`~Òx=~3qJÖÈ{†×†?›b+¨Ç\Õ›ö~*œ–®µno}vÞok D0àh9ñîÀ%64iô_æÛÝÌÍWPf c0ÕÐU@ÈêŸÛЗ+H„ߘб¥½æ1óå¾³Á¾ÀyUþƒãš ä§‹MØœ4›D}Ó‡õ=´Ž­f‹ë¥<+lƒ6Xÿê×XKº–"Û®Päå¯Nà1$ˆØØìˆ65½qè–õš\ƒ-llZl#ÝXyÖnÁXUèÖCgu½"Ba|j{ÊÝt—33%¾®¦öú±Y.ؘqXócŽŠüÝ ùÄíoþÏ•þ‘ׄøý Å=c×([¸.tÝñê_z‚`Q—ÂN¤bMߨ YêÎÙdíš=yÌ×™àFÃ×7O00¬&þcÌï®C\N æÌÃ\rPÁ-¯Òåçüòïÿ±ÈúÂààxQ|èA®#U4L2çò%¼ €É¼~¥íäzoþŽk`Îä§™\wx¼m@ôÛ»[$üÎÐêØ1"5G]ÛîOè­:|›ÛË»RÆŒ,«¹2‹ÀÚ«…B)•ãÊö®- Rà§Ã²3°\ôàéÔ±‰ˆ램'z¼÷º¬mÚžA7¢PÛpÃhµò~ ó Y8‚©oøÓÏ0«&¦«yð€Dç>kñ»Ýø'M+&7M3‡ZKOßâœ&å¸QiuÍ€Àu<9×OãˆÇŒ 7»§ƒY°æ)_÷M¸Èp”K| ZâubƳµå+&‚nMIG(›ñ9ÉY3$³T6l&×0ú¥$-«™ Õ[Gì­+ˆ†ÃÞ±­Fö$ÆÈaÜôz¼0TDÁ}e‚ò‚8«=Rÿ›ô3™È'éjGh£·3ý̽RŠÐ îæ(Ï®”_¼ºŒ+²úáéô<[à)ïjSl1Ø@éÔ|-) (^FH¹>å°0_}e`h LÔâUIZs,ä»5ßÇo4Ò9Ü*Kºh#Î\D¥(_‚ ¡vÊmp„ ¾v’!Ï7è˜úÃKÕv{<³óÝwݲì/ͨ§ªŸ¬ÕrƒÒœÇÃÓ§âG‘îfNÆM]ó%Õ“o±*öo¿+§ël¯ÁY±+‡‰¹ñǬZHž¦Ty å9«°Žßaú]pbÐ O´Û¸á3s„õõ9ü Ñ+TQ¤£®œoÉ›Bîæ$íDNÛ@™vvˆ"ص›Bi>Äe•k/;—Gˆu«0Ö·ìlÚ ýêÍJî××§í¾<^CEAìq,¶Ž*ʘ6*šÓÁå¸ðc$z_EÓ(:}´Qê JË[Ü’¤AO¼T´þïï­öMûÁ,ÁÅ(#3ÆñãÂ!Íó7„GKõµ×ò3¡*•c¬XREÂò‰[†*Tµ(l„pÕÈQÚŒº¨†Úiš-þ£tÁ›”lÕq­-¦)n£öfk/F²µ­,þÂÅÖ Â"ª½;1¤núb νkLjÅÍ5p*ðúײÂ*„B`Ì’ÿÜ×}¡Üž kÇ:¢©“+yö¾ãw—°rQ°ø0û3?ë£T-©•¥2•Ðæ?áæ¡ïä ÄzzÞ·h7Êäsp±%Æ{J£Òu£þX`,;iF‚£·a›ìü>‡Þ嶇û]“‰½õÃÜ@DSü•—f-öŠâ‹e0)V3Çòê&ñÇž¿;«QP&2ªi= Ÿ•܆Üêo¦%)¢-¤šãzdÉ”¿ðµ¤œ†ÍøðÙ7®}˜jD±×6üúñes8@A܈ÛeO=ÈÍwºI0;Ü]òagNi&``¤ÎWnX¦oþçªÐw#w6GRÄbÏ`Ó>Ð~³ËR§@¨ŒÆ¤p‡I/ èý‡¡ç» WqU¸^MD k×(ÆžC~cÇU)…) ¼P6œÃ•ÕFY(}s˜œt.#—% ͉Ièwì²inÏÑʴ SZŸ½èj²~:G„·y ùU85ãjÇ?HI†°' Öaqh$vŒ ²Ò@àž&TË °G],>ú·#Á7ä§(›§÷ÄøøE÷Nß'ÿÛP7ñùƒ{ @ó¿\ØÒžâÓª©åW–‘9r5ˆ£w…y¯§”i•ÿréï'K •)LûÃAþó¿ júàÒ`±$WÈ2ê–6ü¦Zߟàv¥æ'¦Æqi q ¾•#Z¢‡1 $'Å\¬çt-t¶›²¥§•Ûh”WÌâ–4•´›¢;éWn%?'ÿnCO(ØPǤ ‘ûwå:ð*XᤱÚQ)P©<(Œ®X<ò ìõ#Õ›Ssš1j¦üÎ !2Óº 埃~Ý&‰¨…8ªUK?¯Oúe®´µðá Ö¾ ìU{&ŽDÑJ°0N °„-pÝ×·fJ)ˆÎ¶B¤i„`£ ¿Í¬Ú𷲇ê$šÖa‡ºý*Ø×n˜³è“âs‡J©2qõÏ5’V›„áÿÚû@Ìf43ô‚0œÄsÍ ª¡Þe šê%’_É4œ6 ºf¿ä8¤ ›ïɽÁÙ¯tŠ[tU›á»'ùMba¾=.”QM¸k­`¶:ºÒpmhKæWuhòxÏtî&?˜Åäññì™P±EÅÆ9tôû×é¼3+!ï=µñSð‹­HµÈiÜiÔB+Áprê%ñ:£É#q¶#V"ü§J1ky×¾Js6~?FŒÿµê]—I¸{C_þ +œå Yûm‘šxÔ*Û+_(Æÿ©hx‡d»fm©îuû»Z­¢Ã=¸Òv9` º–ÕíßžO«ßu¡í„a¢¿ã»¥šó™_ATƒ-ê¶Êù 1JUŒ(8^ö\ë]f­OÛ“œK”þ]U9Îëv)ô_Ãö7º%N˜´NÐjë´ô=WºíÚŸÃÑ6ƒÆ· ŸÉX~ZÒ½Þ!áCý™žçJðê1R+½L™[fs‰7„ÈÌø.ZÓ„6 ?y™|>c¡Ãö7 F@›a;†ŸÀ²o·×÷6!SDZŠu˜L—6|@Ê_Ã,¥@ZPº7tz÷Š·Jƒ•óPB×OÐf);,]IÅ-'GU÷8%1ów×eP¹ŠñÞàÿ»‰,2eÌÿ—ð‘ ­‰FuOŸ¸ Š*K¥ŽÅò®œ·ÆÑ6P沬È[ì1É8|è jßà’ÂÍö¦ -1é“á4ëÔÜl˜ FÝ×7Vn'ý‰ª9%¡¢¸»9Øií´/qÎØe[É6É‚ï4c!LRoé&jö»5„#5,m¾Îß"¬,ªz]§~6QJ±;@࢘CÍf«Z¶+gÐEð§„nCwnœf>¶·GN>Â%ˆ »ô/ù¶‰™&€¾vÁáñ]áJ«§h ÜÔ ÍCõÆû·Œ',Ù4*Ðý%I³:ÄÒ$öØ’?|«Tˆµ&“pÖb‹¶,A˶ÁB"K>gMÿ™it„´PŒO?ÿsù¥h .Gxì[×û¤ê2{Àa…-¹u00‡÷Âè/“õ¸ªÔèÞŒ¨ôbª+d…¨o HéX3¦¹_f )n¿ç=él€%D~þò˜W”×û—ñ½0aY(ð('ÿÞ[¼6SÇbÞ X {?–LKS¶¤à ¾JêZ‡ÛËvš‰j–^mt­¯¦ü›ÞâbÀm&ù™ì~¡àùuí>‚š!†û8-zkÊZ¸Yº~ÿ­|àþÅo^2f ˆÁ™²‡žÜÿŒŒUy|áyÀª<Ø‹Ä?Ô—E½jæ2Ôár‰[YÐÓÀ*¥ýêJ=A/íT“,¦Z Zõ'|×7ÈZ­å¯è5z~§¹¹A1%®MtŽUAº½ù !É£“f%†H;=*™ Ä&RßÕ†GìîÄûÊs—  0¢t½Ro"Aã<åÕyþ%bñv+õEj³Ž²(Â(£ÝMŸí_èáÜ.•´Ž>c!P>¦@ä–£÷›Ì&ÔõÁc“³Ú–àG´HM®ÉüþàÉ›1@´eML>²íãkÙLˆÆ²”’µ¡/‹w¦fl ý¦›¤Êè!É]õL܉á"IlŽ Åkbn˜j©⛕ dŸüȵÑ[Œã÷JufÂhÀÕ¸®–šl¢µ=éÜt³©8 e:Îó* Ðá=ÃyÆäöú;xoðùn +n5DÂë–Âs™¶2"¥ê ¯–2d(…æZãï6]Héƒð ÚžÃ**÷ÄJÍܳ´Ïá$¼CÑeœU*ξBMëáMó‚k’›¦|«Ån{ÒZª½Ú´‚zu&õvT€¦ýáHÁð3ý%-™úoE#> >’¤‚XþERDó8¤DUpZ# "– †?“‹Æ~ó/þ‘‰9øyL™†IýùC¤±‰!ÏHPTZ!§â7rV*/ó©eVƒ`ô˜'¶ð› En4|©¶KÀãu|ð.¡ZÜÌ5Z®Y*Á;^5á—³¿}8u,‘êÌÓD!ÀÄúÃ( ¡°³™V©%è¨Í8E ß³zñbÕ Å gO3óZÈýóxc¬ªð‘ןuOh*?.Ø÷锯1˜F E ¦ì*-ð…°‰sq§Nï¡®'ÆpAÞ?qeS†ÎE÷¿¤öWne3wûMXyˆÛÎI3õCÜíømÃQ¶‹Õ¤‹®£Z_Ñ•R7µ¿š9ÚÜoDÎ;è‘=ÒÀpŒpìñí¶ùåÜÚ× Þ@ãxR‹GI¡ŸZ‡¿ïõ'ÜÐÎÿcî#!†˜¡ý×3„Úò‰»lÁ*©(þh‰/˜nq˜¼¯ö¶gÀõw“Bª/lcÞç¶v,¨ Ÿ,¡ÇmDTú\H<·è™y‹c|{Yï_D5%k5©‰^5ªíÄ›T­ ß(fi×øš"ÚMGÉeŒÙÿU]Ó‰‰oÖ¯µ@‹—Þ-exQNÙ]»4þAùBq·j¬ì#>p·ES¨õ}qŒ‹fv¹‰68QÄ´ÀcÔ$~c]… qPý^–ùC!©à ®+€‡CN Ítùsf<~ËeD»DU‘•œIxÂ)Ïeq@J½^×¹wZûºz¿ÏîT·£)‘hV"ôÝYØX–#§ƒ1šÎ~&fˆI…è‰SÇ­Bšž³ä}TnVt­x@Ö¦¶0iÀþ¹Ÿl&Å¢–t{OÍXÝ÷¹ç|_š[3GF"³ÝÇ7)¯YžéG*õç%áÂÚÔTþž,~@:Þ(… GŸ +ÈHTd„J*9=#ô‰’7R½Á©ã@…ÂiÈâÅÍÄ:Ÿõ7öL¤ÍS—U:/èŠ&ÅtSïÿ¹¤™#úÑ ü¼jïø'w=÷bÁÉû†eÒ{FÄœt$¶Ý0ôÄuwBÚ¾¯uÉì~ÓQˆdÛnÚ Ð(/¯‚òg²Ü¼M“ë[ÿ¼˜¼‘n¸hsLÁ⛵zÃ,¨èZä×À-Ë/=È@¹õ¹ó\CÍ´?Я.ŽÙƒú¦µd=›~‡-¾d%sæËľÙqúó9 c ¹rÂJdSœ‚'Mº¸¬”[d)Ó‰ÿe;5ó·%~üþ U¤ßÜAÈ£‹y ‹Ôvž†˜‹øxl‘œŒ1mˆ"›Ýbƒ„0Ý3À}§ë$Çðöký‹½“«þ>ÐSC]zb?0˜»:¦F¢ÆÜK¢dª&cVû¤tÄõ0iÀa)T’mÕ)Çxç&äÌ}¯üáG+ì.ï*PˈÑF£ØFîç–P`ñ§ã©M®:¬‚®+°é“Cù‹…7w3ÔÈLŸÑüµCÝðÙÅ)ïUW5¸Ã¦ª '?3¼µÉá—ÆS§­ÿ^Ëiló¿6»–ÿÞݵß× &‘y•†‹z b¥Âxki¨ªzö‡3QÒo.Á«©†Bx߸*¾/¡0g!>Ý5š¬X Jj+@mV53ëf«c÷Cæ–Q9;\1¨dù‘…ðÁ”Ôk:¢’9ùµšÈB¬«þÍgsØE¿±×–«oú¹%z—!ßF{Z­J8 Z´LáÀò¢1bFÎ]W(‡>ñÁe  {jÓº$½þOñí‰![Æmõ¤3逯9'T«!K9[ü2ç ¾CaÞ-Ô!FuPÀs)b]ë[— e'q%š±Ä3ô ô«ž|¹fbÉ›¸8óöWAy¶±ëLÐÄÓºðñ˜†sí3@Km†„+M¤0WG|óÜã³mÝš{G”s)sêÂ6Õ{KX‡ø–ëñ[â’è>ôÌ©Ÿýnž§l® $h– âv©d,ÄÀ”×$^ÇEÏ>PÛ,£’TQbnh* ýb€”ACB–ÞÞdÓ´Oø(ýUêŒ9zÍzÍÛÁ:ø£‘QI;--йÎÁ Âè»e}Ý¢¹1\¹²xWFÀf^lñ>Ÿ%Xöa…¤äŹh=ý¬PB!{þ-y‡

¨ÔËòó ò~¥Û¨u!zå‡êw¡^ï²ý6®y½Àeì1Ÿü±'•Á¨žDœ«° [óKèâ¼ù Ï·$˜›&}\Ö"äA­mŽá]~ó০JLš)áζ±AX¥ÏiR|Ø~ô㪮¸! œ2×ý2ûÑWl$`ò®µÊ{ UÈFÚ­_ÒÛ9t"—<Û3Õî‹Bè+u5nš ŽÚý繋9§ùҙϾÿŸšn‰J æEQ÷L_`þÅ Ì*‹INáQOþKGÖÕ<»a±—Ö#рͲ—FRïËøž4{H·ÑãT2MË’(SÜ•…Sb±`toÒ–gµ‡¡„ÐŒÿåxŒ—ÌB:à‹ØDZ^Î@ÇõPKXÁÇ !»§ºµ£ô{t‡q:ü8\”ç9†6µÙ¶žzµ»Ù: ûIT–fÙoUúS/†­×þnéãJ&ζBÛ×,¹ÈÖ=¢ëÇ¿IöWF¼¿Y°æ'ǃÍUl4þEt9JzxKñÌ’]ïÁ^êóGî ´$mr·wà¿¡SدnGýšÙD1 a÷¿@R%‡S×quSÓXM+E”HxÀ#û€É/ž_ Ø8D´†jVÑÒÚ-œ;ØÙÍô–èA}­Ç-…^1-rÃ¥}éÏÅ”x¬bÞ€‚© 6&²“ÍO–ïÀÍþaå_ ‘ê šh…âfÙÆ$Ôa%iƒdã9~Ÿp¨7˜­¨°“릇ƒR+´ò÷ûC+"ÿ¼&5¥ÛÙdúyoòá#\¯¢J«ä!òS@ž—Ÿ@šÿ×[Ñ…ƒÄk |F#̽½µFÄr!Â-ˆM‡MBˆï_¼î·)ov•©|²¡Çò –Šœ(âÑNgÜËŸû¢G¹ ž«KÍ^'\Wƒ*®ŽÄú’ûÊù[`àB<¬ÔZ¹ÆM®—Ìà ÚgU(aÖ1”Ä+…OV™+ÌD.íñÍzÀ•ëIuÊ,ù~ ª—:ŽVëÞ²áZé­éÜEÇ9‡;Ø_U|öµé3½¦ÓL­à%hâªpƒ ª Æo(ÈafÍû{!œÔ'ET™iÛ¶ Kó±Ý{Ѓ›¬<>^êþÒXT‚ê0ì}Ó6ˆ ;é§1œßgp@“æmfå½üZXäš'<$ƒŽ”£UÕ ì4r†æ5vJ1ÛLG‹Y† s]*ªs^‡Ò–lj¡Ú >ÙYPqë*Ÿ˜^A›\/(.¹ ´6»4}¾CZií7ä¥ÙHè†r-k†ŠrïºÏ{;-²õTÝ"u¾ ’‘‹u÷,ŒEid!íÚÍ7X™O÷’Ý¢‡4£”Šqåõã<Ž)êhùts¥ÜjR.rËÁÖ’À•IŸhþÍe7ÙEÕ*¿*ìúÌ’˜ƒMr'íFOï[$ilwÛ„ ûCuæ¤ñ,÷0ÝZÑóTßb+¤bù ÚW»ùm«¼1¤»Ã ÐB­— T£œBUÕÐì‡fùÁ+¿i:îÅdÿÊÏ0·¨Bê"fÈW+ˆSm† ÐÅ|ÇDÆ•žœ«œÿK×~üõ yz Ø;Ïoâ™Ö…¤éʘFÑÒ»f¶Q~r l%^,¹ØjZ¥ðq>qî·Th×l¿â6ŒÉ''cA»ÅC盵`)ŠÀˆʪ}ýÜC43‚r¹³<æ ½öq0¬Mª/û »Gn™'ÚI”«åŒ<öÙ»L~¶•'Í57D‚l1Õíü={£Ð-%|ôékº O-/ AŒÕèøKó6-™ªÞ, ÊÆ—XG¦Ú–u!‘j^¥ï/n_càL#áW–UÊîgdâútEïÜk`…më0äw] ÍÝJ@’»+ôóoÓ çw"€íy»÷ÔZ¿°$L‰¼]Z”0”‚ÍÚ£rVy6γ ¢ ˜¹ÚH܃²E¢¢5ú_íè€ÕñV烾Ÿ2É:±ÿŠé~º2µ¢ÍêIkt½]–âoñ¼·1C} ŽfYU§-ïm¡ïîÀÞâlŸEů† °Ã‘†:¥î]­Zd¨–‘òåýÑ/È,ª1¨µ ŽŸ·¨y µy;D컋$~¸—‡j™w‘ÑÏ¢ËÂôpž“ ÞÚZKâ,7PLjX©ï:(íð&ôia¹jäŰuaw lõžhá†t€°£^ón/–‚úLàXú¢ŒÞ,àn Ýë@¦\Þ—7]¥æ†@>Ã#d€Ù¦£‹ÜDpvvIµâ tKžÿ‚Mfo½P¸¬Íî+ çQtelP£4žü7<¢¯)›ä+õ{Í(MóQ("˜ŒdþTÃÐwtd,ÇǾ¨ ‰z;bò~`Eâ KÄ.¸:m—ÓÚo›R´Ã”uu`?€NÔÁ¸1sÎÙ&Ô$”Z%E¬ƒ#«¼×TÛK‚]ÀÓÌ'"¸ˆ¢Ã/Û^pêß’‹Wî)<ßgÊ3tšáÇèQe ð#¢{×0bÈ¥ó»A¯ÈÕI;@çbmúƒ }f„W}Ã*Ò‘`Ýz°Á_pÂÓç23×Ò4s¦OWŒ¦8}ƒŸ´n"Zàs\z.š_E+çÙ±)2ROÒ‹‰C&|Çߊ'uçVê\‰Ÿƒq (§2Íj’$v¦Xk%Žœ2Ž”fªgL‰ÑÖŠÕ¡á’£Zoû”„c²Y¦ Åc`ë6úOsB¨µâ$6*Κ%cÙötº7š´|O H*z°7‘Ëþ5†ò¡±ÿχ5…4%lœñqgTïՉ拯\ çðGëuUý«;¥ûRÞ” ¤ŸS£èR×o¯rª°˜0§82¨óÓßÐ Œqž?¿PȺÐí®é/§ïè@B§‘oµ:òÚRó“®óÖæïz])ø¡Ù± i–³Ùœ:–çXôJöâW“¦¾µ”\ZúT”Þ›ãUS.tHÅÜTXÄñ*çMÝ®£Q¯¦\󉱒œ[âK‹ªNøsí»±rs×Á4™Z覙w`¬Æ_-qà0v™ñ,­;iÅ/²¹6'íØ}]«j…™û·½a%rtÅ t2|[û¹òÒ¾/¶£¬uQÌÄ“ÀUƒ`úÙgzÃ: ÏÙñÇ}‰=õˇØƒ†K-oE^ê‹P8¤™y)‘cnÄúÀD2óT¡Ê;8™ßNÅbé*Ò·°zš¨¢¶›ˆXÈk2qYBÏkïôêw$O˜J@&££w…y› BR°;`€ðhO¶¤aF/`žJXF‘9%6–Ž/ä²¥FžMÍåãyëO÷Ã|ljEo`œ'X¹AeÇUÕ}2\^JÞñLóMëk7í~GV—øÈaŸHˆb‡ÓëþÜÞa®R1®Ï5z¿q¡ü\øyLË6–º/“³Tfòò£6¿st€ƒ!•_V;ãI¤Q¶‰ùï Ó”d(˜Jv†Æé)Ҏ輟0ú}:!Sï²÷°”¯:r2œ Ê Æ[§ð¦\î2!=ùCƒŒ/Êìýÿ÷d» ^×}§‘s÷ñº€UÇ» $õ|ºfEš(‡©›Ò~d•5RŒÇÀ+Ha½Ä«¤ÌéðèàGù;ÜqįŽCCfn=ò®(hLDl&A…ƒÕI=™½Cðññ˜A/f"\42c(zaÙ£°—î:rAVj{á:ËEà”¨Èèžò•uú²Æ*Ûð²ìÌ«1Ãv<ÙGØý4±Ö0s«È'=ánd×(úí Âh‡(5¦ßüœ&=8ª4.qÔþõná$´<ãq¹¯?¾ç^#‚—Ë7µßHʷϧI[×:Nš××ÞÛ¾½Í þqñ›]œA´ÅÞ„÷e>©DŒR.. Ês"o¤Ÿ‰… ‹Vé‘ÞuY² ‹€ú2y¦)„=Ú>Ó<ŽiG{ÜÏ—[É}ćü$i¹Ù„ÿI]ÿ.."*¶Òçab Dú„ÕhüdÀ™×Xzß«@àëa¢R—Ùò2v¹¸üŸ:ß‹–qò74=ê²¾ós=Åè!ËymŸYÿ†+t&6»'ù³k%t¾yÀê/aZß'Ål«Ó¦ ÅOu MM~-;ÉØÕ€AŠ‚úÇ9 ÇÁ„CˆÑa#·³^wN]´ÛÊ<ÑŽ“姉Ò‰ EýA¦½ü2ï~[«¯{[!Æa_9U d ìòp|¢oZ/`lΙö†|¤£´ô<²ªöËxòÑÂÞbâ£fâ~v„? b0u­:+OPÛ]¯C¥²^ ð>Qv: ÿ.'’l«ÇÈŸ\´' J¤ öÅg¾0—Ú—ÝçÕ €T—h5ö !‹Á˜W+¯Ã„Ö¨n!ÜϪqÑR#BI‡òBU1ø&áß­ ðï-nfåôÔˆ -ÓXbæp_7nš]Öå0$ 3UciŽ^´Qî#¶Ûj EÍí?ÀàÜ4ÿ„œYqº(; H\/[¹l†·wóéOà« ‡µ:Ø †ÒØ-K?ùʼng…y§2µ¨OV»/C|†ÆãɼJÏYOÖ1˰ÏâÍ’ãÒ³`æá‹0Øj9Òdä\¤µ²pSbûÞUW¤k¡Õíüôq,d¯êî/)µ/ ¶†ð`èxˆþX©ßhg ñ׿nX`Íkü>rozM94Öîõ´¬îµIs¹%«Òúì¿ÕxÄ"bp_—p*V–Þo´Fs&Ìr®Tñƒà§u¿¤F=2ü‹ÕynáGSŸE]ËrjÚ­Áê@ΗÜ`{iW‡ûˈ)B˜3‚gÊDNf/Ö—;)œüæñª_tðÒ1ÛL™vÆW#œ\‘‹Æ7µ$Žch&ªNƒ7*$©‰ãcáCî®âS¢¡Øt,á–<-éÿ=ñPVL²‰{ôã%)ûCE*ÍÄëþ)…B£QѺUC ߎ0Í‹{pÊÑ«l$£_dAÄTšnó\Eä¶G¾ú:誾Z‚ü+E-…¿Ó™­[œZõ®çÍi¿é"µc½Ä'à‡˜J\ƒù£§ÊZ[§¬®áMžÄÈsãc܈z\#ÞäØrdåøÁe@XgÙw')1iy Êš)­ÚÁ0Æ'm‘°r ×XIq—¼QÅoÿ&\ äy— ÇNÍÿß±í”0&ø³A þ6è 3_^·­zDw,O¬hHÈâ{'s¡E®_e­«Êæ¸Cõ³«ðÊùƒ'e´lªÊ÷À*i ]Íiý®iáÚ ¾R–·Å­ï[& å?TÁã6ÿˆm²_²KŒ¼•,‰ 7âè‰nÒgŸqd˜d•)çâÙPzø2oŠQG>£ß‹†fíJ‚}—w \M…+de}ñG>zË'W„š!ë3ù˜fDR‹aIάt"ãȹxß“ñÄ…­™ÓÀÅëa.‡s…ãm+^EªDXÝâ ›M>‚ÙXå­‰T%P±oÙ?pÏúûwv®;{ìÀخൺ!â¾lc^(bïþÀñÊPóy]l}ÙÝï·ó(d7™Ä>Iô£‰³òÎó2æÚù4"â8ã!ÐÍÑßÞPV;TUÇtÙ{nHmøoÄÃÀlCñFÅ„âS(ßFz¥ígêÌP‚ôïÑÒú5€-)hP7ÀRµ•¿j÷Á¨Ÿˆ±j–FC2ªß(‘Ö13µÉjA++Ú݉†d[[ Ï©«¸õv‡rvq$ÓÊx9Êw»÷çZ×+WÆÿszD•w<¸ÀðÐqjlcŠ#±Ö“Ɖæ%=ç}ØC²_H;È©¸}êhÙꥺä‡X3Ñ¡jÛû~·Š¼8îq ÄëLÉ¥ßA.åaæ ã¡Yl ‡Iä¬ÐhH]”¶VDÇ„‹¤S¡Çœ†NÀu4aíÂôÛ$÷̹B·“Ìv¯I¬çny¹v·ø«>Ë8܉q…˜rS&ÆÁ(©\9¢gM£·žZ>¯t>ê ͨùÙŽ¿ƒ”:V· þ!n€&#ûÅg^Ãô$#éâãZÞÊynhÅ8‚–óÏ(:²N1šÌÔ­>]Fëq8FœåRþ`,mõÁäÕ({/¤aB¹è+mNÃÊ.i{¹6÷ˆ¿QúOdMÇFkp)½ò3ÀÍâoÙ¯ä‹Ì`àkÐí ü~ÜŸ ¯ÑôE^ Æè÷vð=JÐ6ÁsÁP7!ü:+í>ê¹Êpý¡DÖ®Âs¹xJc¾tçµ–WK„ * ÷.æíø ûª°FT© {WÛ¸ƒÎuì­ì[þ¦jÙè›Â?³ô'ÑŠuW>xÖràHyÃm¸l¹i$ï2Xnâb8+^逭x‹PzòFWêÆòCL\K…¯GXtþÛ©þ³E_ÌŠâ6xƒænõ]A¥ý0S²Í8Ù(å˜÷GëSü¬­÷ÊëN‡΃;ðTÅŽäJCTà‡>ªQý9>F¨ÁäÙì7aϦÇ^´S†lÍËÛšÕuÃzÛ‹Ÿ]¦*þ(¹|Æ»ÈG‡ñ]àAIÒÄyj·6H+À© ’™ [:‚‡ã2¿Þ/]a¼Ú’N²·ýt®Ö སjîËU¤|;ó¸BîLK«Qß\ÛŸÎ °'NJµ­ç3Fò2ŒXÀÖ&±“¦¹=ÎôÛvw Ó9§â"¶‘)öÿ>…¬‹V7÷w72S(JÙõ“óäm[s!zx9ö÷ú›zª‡êåG=lõ/‡AHq/„…pnÎÈÏj%j‘j¹Aí‹´ì±.Õ‰ÞíCG}v .ã¹cve=s&¤Ü¨;£¨­ó]:0\,ôY¹†0k0TÒ…”Ü}ÖÑÝŸH+)Çßœ[w„Ðé%)ÀFôµÇ”­7Á4H¤àŽ}5ƒ*¹ ~Š”MSø-Pßþû“é÷e¬¾SU‚‰cB JýK~¶Õ?7vôÛĆ~îOŸ£³,ü®Ö@v8¬TpÏóH OŽ™¬ÏyÐ?í©âiZ.NÊ>ËÞíÈÒ™ª¾žÑ†‡EÛRÐÿu7ÖÌÕ gF5£ÇuÖ¡Í›£Þ–e4ráÚÂNAB׿{ìƒ×+>Ã-Œª­;éÔ-Ý#Û}ðÑ¡`¢è{F‡{_.þ[ž4’{W°Èxr–i0qÏêç+ÉGœ€(g>bñ*!ªfL{­.  Vx<ÔMaÁ,Дk„_?}ß @ôQ5Þ«%§\ížÖ¨N˜IÞ×ïëFѹø4Œýã®ÝX·ï^æ”ÜojW0Ât\¿CæWé?˜P­tRA‚©—VD`Røz‰ͨC¢]µ¨Ö)ó½±¹»/Îuƒs¤!ˆøÇ³cÄÜl ¤€ ‡—±ÁJ­¬ÎwA‹€Î^é»69åó„窤íëÎY´ìù$§_7Ô¢ö¶ä›*\°n„!™U¤Eܼ)}P'á)¦*ºÐ¥@k%º†2¹ó>úÖþ;ö6tÏÑr]Ÿ7žø™B}ÿÜD”-,Iï è”waàê#ï1’4 NŠlД˜>w¹Ö’éÜ  ¦4¼Ï‰*º å'åE¼æ›ce¥ÊÂã%DóÿÝäy=€þ®WK¯Œ1ƒR5A\7”ëj^ÛŽ¹+n.ÌÚJÕ™Ié5Sø±®q3_ùê>•™û}ŠçhaØ”…ÆÔ±ø‹B5>mcŠCû&:ewr%övØQ^“ùÇjÏv½+v•i.'TÜùV¢O±¼Úñ“ ÜŠgÐsÔ‘OT G¨ë[ Zªi“o²¡êT³sâ‘îþÃÕÖ¸¯G8'²N–Pú{N¤1ãó–¹âm¥åãÕeÑ9ÞšÛ†cã ôÄ2¥{!¯}a±YõÝZx'棔­‡Å/{ý©£Å×*ôް#Â&7¨P¸š“2Û# nSw|<ˆ=~à H®}€cñP&cš.Dpñ)· šÈTç 7?eÞvTt€€¹=Öc.äŸG¸ÄADéI˜n“¸#Ù_q[):–<7êe.ðÖÅ‹¾‚¹1a±­öa7/5ØäiïˆÈΞ'R¦UˆIOÇ¥W=}‹hjIh¿öpbM|ãÄ6z œØ x|ÂIï6£¡Â¨enÆi¢r°>ºÖµôXÉGañ3I¶m*û—Çõ9a¦ßâàZ¬%=[ïÛ#vÙäQßÿµƒ}(óOÒò3ƒhú«ßî· ˆVXÀúo>b"i ±ú²ê¯NÓj „ÆÔD]óáÆ°¿OЧž%E·[džÐQÐ p¨¢%%ﳬ“†QžUºG¼Ã+ßʶoB[ ðLÖ;Y]¯„ìc¡¶âÔø;Ö=§Ë¥,Y¬2³Uס³®ãéJú9«`÷`ù'ÈÎË ÀË7è*9ßlMµâ7p Ò›pËñÿI‘èà“›Õc6 lYS¾ÇËœv±jX3G)ÌØ†Ï«Â°‡ÜHœÑ70‹— ” ­³³šoªØ>S”-MsÉ™+ÍŒž£ãµ­Ìcý]&6Œ½ ­ø -X- ú0ÆÈö½ (5×ð©âe›ë ò8è>æQ#Eõü$tÔ$Á¬êÒ€ôÕ8ñ‚Àÿd ›‰x2!ƒÈ ç%ÇÃ]%¤Ø"C)¥ž<žÌ¾VÍ+½k¥¾•~êF WU¬&qhËš~vdGµkóÀ:ÜQÌöå±Ù¹Ä£}™…y–®VJÂÀ/§ÐuAo™Û,®1Ž÷Þlפޜ3¦d·ê]—(•)PæËÜÜs!xÝ5÷«ˆo Žƒ½H³_/á1lwí¸rÚ%5°J(–# rµ±ÌϾ ¼´ñ¶‡Vá`ç´¬ªuÈd7Ž[sHkbÜí+Ô-aÃùƒ¡Ò+Wì#þ Až¦X0‰-ž+×\¶]EH(èuqh£Øhx/ú˜¿ÃÆ¿ñæ{…ÒwÎ{tÍå´ðFpˆûNË?„^ Ç;x–8÷' ÆnäI+ë¯Ã¥¾eèÈaŒzx8p°Ä¢B§ê0™!èÀnºÁ]ÌfÏaž5‘ÝL\VB-yãc|îCd1_CRŠlˆS ’Ë߸÷4Уö¸@î(XÞËŠVÔ«ªïQ„;y›—vWI—¥Ÿ3#¥¢QåäÙw[1/üZÑe±»6³K8Í5}¡ƒ @«x|È^Ÿ‘GGp “”܃ÓÝDúCÕ¤£ŠÃÍo c%Ðs5‡g0YÁZë~eàå†w6d;hB¢âÕ…‹&R;È!«ÜkKÚ†Ÿ•Ç”Tœ•©¸–Ön˜$Áû!/žùäרРDp”b6š?FǃùÒìß«ˆ{šã‘$6À(ÌòŒt–£O‘”)ŸÇ}mKƒ… ]žì#.4OšBŽÀoâÕEsb˜Ù³³>e¥< "åù§‰âR®6K3—WD¬J&d°±‚Õ]@6Os°£ÈÇîC%  sÀÕÉøQå?8üº ([ÜÌv÷ôÒ€(¿Y!+AZà€9ñMf`;knŸ#mk.Áû½í%‘©ìâjò ¨Y÷…|5ɲpQ]yeGßÉÓ3ˆÃ“þÚxOí¢"™”-_t3ôÝv|tgOm,ÈѰÐê(È☠ñÞÆS{!¢üZjÛá9,‰ïÀúŽFY-\£9Ž-÷ü >µ—Ý-½ÀÞG¼ÝMé@]C²0œš/å‚ÍÇØÂQB™žM½×S€ ìÊ9«ïÿc1 ¸Ã ±¹‡ë†‘¨–(Yt£I Á囄ƒ˜ØÔNq߀*ÁPâƒî®6*W´"-§>øjŸH›v‚UDRwÈ6A]¾„^7mÊ…¯ÒÔZõž'­~wóÀ S,Y(¯-ÐÌÞ쀾­*†S18û˜Þî Þ}4ÕÑ3¼Žq,çíàL³Ý?Ó†‹R—Óžoeêö5g¤ùWH*È4+Jˆ’ÿ‹¼ñKÈ»ʧTˆ$ü'ùs„©DwôS)èå#= Ž*ì‡ßàKëà™ú|¶.úkÓã䜶“ž]D2Î5ç…>1¡jȦÞrt†×!$Å–¤FŒVÍâÈJæãý¥ÛR‡á`ÀÌùyÒËž›7—ãg´¯\snÈ»²ÐFJwE&ek@òÆÙœgɸ剧EP6ˆÆôšõ|{t+» ý‰£­Ç£‡Xü1]r[T;âd"l7ãç] ÈNĹÔº|0ƒÜ´Ä,© Èîƒ{¤;c»‡Ë"s|Œ³vR UÐýþ“G’r¨ :‡4›¼?† &®eÿb+þK.k¬1ƒþ¯wßÈïŒüâíbTž)P†ù7]gKDT¹Èx»¬Tã°dÒcw亜ë·$‡LYRÌúd×ò-µ·N.„t\Ø.·¦Ý¥ºÖ~Šø-á¨exQÅ(þ=QlÅK¨ç…†©¾éÁ¹¬º…8·žx´M‡x!ªµ&:V„rã—k*#–ÜÌ$¹]]Úx•¥±e5Cç>zYÓH¶¼^áw>|ç¶%‰½ícТÆhy%T)ËfœÉ…ë…±÷öìbs ­ÌîÎg<ÙÙZÙ¶Óxö’ÂÁ Ì!!ñc¸U|.Q5nך6¬æèÁJ½|Ç:¾â‹ðå÷lâd;9º…h„™3ƒÌÒ­û½f)œèÛmßù ®å5+t®ª ÐÉ® µ!þ«Öà­´ˆ´Š3ÛEº Jmo¬¿ƒCœVo°Îj 3¥d›÷QüÏÑ¢GhP´éÆ}¥Ìš7eŠÏógˆ€GX¢èÈÛõØncXe4ƒ¬Öá}yþmÜxCAr•bY\:LÍ)§¼®g?T¯%‚Ô(ÐRzý%äþWp­Ý8m­ïéKìEQ©gôÿ×1#qrWÒàYä`ª÷”µ¾>1Ú)þLýYvØ­°,ÍœêNâìSÇFhÜ3LÔ¯KËσD¶óÓpn“`%$‹úJ¹§dìf48ö$9=‡[­Pâiâ5ä(~PA¨^š ÷]¤ÿ°xr¸¨÷ÜÇ2¶’jêFw4Gš§Ähb¤20`ÙI²öÈ‚¯Ñæ!s7ÀÈò–’uöz/Í·0 FõÔÒC¬±ãü>Dn¿’HõÞ•S<zçູ±…D'~¾q¯¥º¼…8ä… „îm%^ê:Òéøõ\ ˜vzùrzæ«ÄuŠç¨.nã¬þÇ QÅB0&ŸmU\šq_‹D9ìž0ŸßÍdݲA\©X£O7º.qÄýì¡X-€¯ ^s½üÈ–Î9i_,²^Sš¥P³Ì9¥ß?û—Ì}ýbtìR²§ vÓ_ nÑ^ú$!ùI.ú†îišàºèí°"cg•›Ï𢅵Y·dïQH{qí F:öRñ~î|5vÓhV ÛÁÏUK±ÛŠ _Îq»qÐ;xN^T°Ä°WMg†Ô—özóR¸Øág€_Ö¥²ËЂãX}d”¿WÀÛó¸çœdîÈÿ¿pð ßÛDÚû¦¿¬››âŠÈV ëG‰]€7SA¸—CŒáX¬eH€à<°ÿqÝ¢”z^Žƒ¨‹tP›«óŸ³»\Uæ ÞØÙ³ÖXöÑ2JãÆe. ð¶}j ¿Ž€všâ¡ŸÂÍi!ú£ÏÒAµeGG†ïj0ÁYêñ¡œÌ‹¯æ ºnañúëö« ÖÝñÑGsÐß…&8qî¹ì÷zf{)OJ0¯Ôÿ9)Fª çxlFŒ¨ó¥ÅDië*ÑÊè0ßX¡ ‡ïo'îâX9ÇcwwnwâÕq:µÌJžã ª„¤úÇ#ú9b8 § YízRÁzhZ s o¨_Ñ-}v¹[Ù—lÀ‘UMYÁ®‘,ó‡ÀCv˾ÇX¾pNB›À­K9ʶñ½°­=¢Ã×btN,.'~'MÁë²ùpI¾¯Zj´´糤bÓÈÚkÓN”™j{ ÀFríÙAd©wë ÿômeRøjôPu‘Nå6Ëcœ(J¹ßZªI +xÈ5{öšW—6uúöÊE¿žÍØgìP{“$°äÀ0‹Ž7‘A›\þé2/ÇŸ¢v±øuþ 8½º]_?Ë-UY£(3rã9;–fèPQ~OÆÜ¸ÙúDic¶ø©B¸Pð&da  ÌÍ)Òó|ö÷g+ °û‘ôE€¥@!çn™®Né¬UDÞÞâ= ˜ö/%·‚òÁ® Ï#ÚY¯Á\tYå•á4t)”$öÅK{ð\\^!¨$=!ºg,Ãbyâ8»žÅŠë× )Ö½lŸq× uà'H r>Ç]Õ  ÆvÈëñÖØ;û®q'U€m5D°5šAdË>.a_ŠÇ I+œëÉÀ\ß×±ž;bk[U„9ÛçÆÆ< Õ&²û•P°W¼½þ­Dñ.›EÅþåj—δOB÷~‘ÎpÅó q^ËLvú‡ðä_à Wa¯lñTðiì }y¯!Ç5Œ<ß§?¢€9rXèßå‚1WÕ—7#h.p”9üž8Óºã¿/êéuº_9×–ÐH%†·ËaX›ÒrÞâ3z\õ¤Ö¬ßâõ^³B®·d¹×LOٖdžÏõEÇÑAY19=Bª“ }4æÏ—mNý^×IÁߥ׻¸Üˆ³”T§Çkh©¶Ò[­HÞ¶ÞÏ#3#ʽM à¾$]SõT¼?ÿ h?¨(ÅŒßþ잘˜ -ñò³á´­%h¨{8öoÆOZ6œ ³‡ËD%¢D¨ã?>nmX+©:‹ÎJŽ´òÇF•ÕtS q¾sÀ‰6‚f/\Á7óiÝãÃ&Û‰«M‹¥–Õ›17ÇÇÿiGý“út—,Y‡Qkd›Ô‹»ŒÆw?T¤¯/äP÷ ÆÝx*bž„Ëà æ}oÉáa2¸·±}!H¡TzwT…n’&À©”Šåç±8œÒA FÚªäUÛ]"Ö\Uõb‰¸@*@pùÎf©§âÖ)¯NÔ,NÂ¥"(4Ø«Å_Ä/6ÆnCJƒUå‹‘FžG»Ëþ*&ìNBwZüÙE§ª !šÝ´µ î™»¦ e'°(|mHàz›½šJ BTríÓ—Y§îT#Ÿ%¯ÙÈ&ú»p¯ÚBsK_Jàœ“q_ÛûU?cÿVÉÜŒ’)·¥š6]ëÖYŒ†|ŠÃù4-Mˆ1Ñ={¥ÛEA/Ϩí‚Þ«”Ññô+roÍ,künfÆ–#«=Œê£Íÿ™.z¯9q–téh£G[Š•öÔ0_i"«{ ÇúªÚ §ÑâÔ¶Öô~Á‡†*³Ï1‚Ó½gP{w'?d3ÖLïž+K¡N£ú~päøsy´¢ôŶÈ:¬,bYçÚ #ÂâÉ*@‡Xâ3úfï A%x€ë¼½z´½Zoí—¤ƒþ¡!C<œÇ©ÿ¾®Iù%ôŽË…à&¯q/o‰G0w{2™³‚ú#ÕÔ¡myÙA†BÏÅëÁR"MÌeeV­«G½:Ñä½¼À37§܈¹üj8 „@¤÷W|Š0BµÇ£Ô%†LÒ•,|x®|ÁzXѨ”%âÒ³Ò‘TÁúµ`ë„#¼í¸®\µgC®$ðùCÚæèŠÿàЙ-œEM{‘¼ÍœØ€FÙ__kÚ½°(ÅöÎxÙ¡/©suSZÓţX;2ê¤l¬Îó,‰aí]Ò¥‚µ¯5E¤Nº üÓ„†` ½è$Ò1ÙA‰Öä³å))U!ï½¢øŒ,ð¸L“Жš<¥“Ó/Oª2j”« Z[“@{þ½d&œd®#‰_3úÌœYáÝ®C¸#ã3ŽfJÝˉ¯ÂúÂT/M‹HÁ8¸Ü’¼öfþÍG­„˜6éù—tµ°„¾p3’¯|PÈ%ˆq;7Š…j£ò¢ãü:y*©Àª`kî/¬Â<_Lm~ÇŸÇT7m±±6í ¹ÉÕÛ_C)¢#Šíš=òu±q4¶ÔdÀzöÈ€-Jš “Ý1ØŸë6[‹ƒ¿¾l0v¥³îk™Øh­LCz±¹º[u´TsoÛ7¬½ÊTö¢ ²Öó‰æÌ¥}|ÁÒoï<Œ<S])l/#H[ñI¬lÆÓBB^ýžÒ|”z<°¸‘m‘¯‘Z@§‰af—?F.›û!ã–qM1›tu²X,·Ì1÷cï IÔŠ8ú‡2s|"`©<ÝBc ÜÛNNpÊË/Þ.øÈ[‚r ä„J  ì¶ßP½b¸Ýð5«,¡9ÁÌÚÝcÛÞtpF(VŸk, ÛÂe(ÊT£fšºJLì9o`Øp[ÑÇ÷+æ„–KU¯u{ dfmdÞ{C0º|t–-¸àdñ<‹»‹­Õ0ðïßBóZ’äoí•3¿åDŒ ûœS"4…dÿ¨Ý ÁêO†Ê†`ö•q»Xl]¦FuÞ$K“{Ûo­Ôõ¸Oy\!\ƒ‹&1’5ð¯×²n’-®‹>ÏòÇ_=t²Ÿ›Ò÷MœL¹>aM{ôYÝéØšìÊÛK68üÖySèðô£§ˆÕWg‡±=u•'2®– 8µÿõ"IÿÞ¢–¯9ƒ_¨‚@fòg’‹¸p/•ËT=& §om¨ý¨l –«<+E‚GêÙàù85í¹ž±9Üu)?÷¬íQ}æÆêÝ$™É£W0’/|ìÕ!ÛÝjàΑeqºA3쇡º"~ôèwQ|Àzö‚Æið_¨TnV?RÎÈsP.Ã-”á1:Œª;<¨H˜›$bE‰IŸÿS:Ñ׊ž$áÞU¦¢WÙÌô‹ šÂ›KóxwÁ·:Ö÷n“*ó NÐ!Î-Ù-„ÊÆ:–ë“ø±· áZô[ŒY‘RÁ¦ƒÁr@!M±!úJ‚`¢®Ta„´Àdë¶¾Ÿ5q²õrF›e…á·]Фë(ëø¹¥ òuôM *Š4#䮘¤¸E|é" q‘ë“ á)"¦…¤sfqzI¿î7NßRT ý.[2}ïÞŸT®/MƒágXÞ$Œ¦G@é¿+ã§z·®ç¢ã„î¨Qû@4Í”…Ææ•®<–)ñ…œ(ý¡&TA>Ê{ÛÖjxøô|Övv±'ø¶n®S®Ïšxµ Åíßã7×Â\åT€­0AÓ½ÉÜ$v?¼‘mYC|„ô½±†. &Å\²AhZPç787Qî^‹%¯ËÏ>£á>%'6Ag_ÂYƒó ¶Úk(Pžp NcOœâ¹ž.¸©Å~Ëœ ms§Aª†ï…ô¬ÂÓëI&ïëW›8^þ¨û80þà¯*÷i«ùópBúTDøƒ¢®¥‡ ²`ayw—rL?5‚~ѳåo?¯yÚ¡ 2š8»TÉM'¬n”?ÊKk‘Ý=to5ž¾Ämó¿t?oäœ¾ÎøgëÇ¿QÎèΗ]Ë­¤¦DÖÎÿ¨/pl]’RâAß-Äå/gPw¤,ž3jDÎ;•TMù ÞÝ;O ñêÜ›S›ËŠ È“vè+ÃI¯tŒÐª û™™Îˆ¾ pû¡Óq[Ùa¾H„Ûëá®ëF¦ fºäÍÜoPÆ™zK¡ÂxSwK¹¿# q9f·¬8O¢¿P×¥ÐÓ{KŽ|Æê`Ôg_èèËz K«‘©o¸œ´ÿ¾´n[#ƃÌ7óG…ÌbÍž– ¨pçQìÝd ظžõ¸Ï†0.^|²Ì—8Rwö`W7«7À.ýû†²×Úˆ}ïœnÈ‘% ¥Ê£ƒ´èC¼]EÊPÌÍŠQ×ZïÁÄF1¶ª•jq‡¾¾ÒÂöÏ;Ý©–W§6+›b65÷QÛZéT8]:‹¸þwFb“p^y™Ü©‰oådQ¶4B›”Àti:ix«©o…D©†Ž22Ÿ·ElÝà$@ak¢fØÞZd„ÐYµ0Zí"„v4A„ãçîAÈü ³ë ½ˆþIw¡¤s‰“¨Q¥´r"÷¤Yë•bE·‰¬R¸—2r“èìºëµ¸>Té§XG­M YÇ@(ˆ@},Ráöà·½ SHYBï„*W£©úYdᘀ4" ÕH¹Í{ëq>iá«9`Ì-3RØÒ i.¯¯-âëÅ1•ŸP ¶÷ÜLçöþ°ªŸy”† Q´–¥ômgO=ÈÆ¤Ý~$ŽêÔ6qÞè8,Õg3ÁÝ¢ìfòµNÛ®Ÿ±š~Ðw¦ˆàñþÜ¢ ïwùŽ>j“ÐðÖ„W€õ;N¬ö/`I È@~|·Ãöç®O¤65葬mÙù=¶£°ƒ­W=|À)à"$[06`¨üRLjVùÇ-JLÕ\ÍÛ¬NL¦¨ÇB5NæštîRæ?•~X“È#\]Gosù†›÷߸ë~9;®ã­8¿ÝÙ–Ý7.­é)ÔlÁ’žÏô×@(UkÊÙÖ¹âgÞNôúñe}RªMqšØ"¶?$Ó–ûóå‚Á<¢ ÕÓAJDõž%ŠìéCIDHmbUÄ ŸýdŽAÂ_(ºö˜,ü¥cY!ˬž#š©Q"»Ú¼ÕŒûâ6pJ–«K†ÏC,•¼ýE “|wÇ88uL'¶»X4æ5éÊÒÉ!sjÈçA æØÑ Htà7W j_Œ;M‚Pk`åÞ}ª5Ç7‚h”)„7¯ÀÌÚéQX-9ÇR°*iH0;)CE uµ ­Ö›1è¹XØ-nŽ ÅX7mä3îÚCpÆâÓÍåd;þ zN_Ëu †Øã9¿š¹ŽgÕ‘€¿NðÃÝT¢Fã®ùeâóå& „Cî17Iä½%þCØK‘ñÂñýÛ\£…Ï_ºS1˜óR²©ÄÖJÿT!44 ÊNÔÏ>Ô+ã5[›ñ‘†¥@/Èð3À,SÈ›\RØæ%‰çô‡«=¢N ڟᘪa0ý¼ëøAm¹’ƒÆR‚4@ûä_×å¿ÝâÞôÄà§—pÓŠ£&‹VŒ}uƺ ¢J·:¯fÃâr!SüÆ>¹¸­¹ØnCMÍzeC7!ê¬$=Ÿ„ä¡.x¤¾OhJï§è²dß²á݆F}-Ôº>:ý’¾¾«hO¾ù?bKc`í› #‰6×¥FæÐB\ÊŸòÏÕþÇõé$4ZÏšë§ 0PÝ£_å*‹VLÀmžÈçÞ:qôpcûJÝV/Ú@zÛ"z5‹ŠwìòŠÊ «‡ ÔÓ €:UÇ]'â–±k‚øIštEŠþŸý½Šž ’" 7dèibµX¼l¶A+Ó¶FÀ`›Ã ÑpG¼¡ƒeçò 7›€9q—@Ò¹6=ÓI™ž4’ŸPDüÇIdR_,æAŸp˜äîú¥6Þß›ZœeêÁ®T3Ì^( ¦9îh´î©ž¥[Ä€-D°vI&t‘ÉÃeÓÿc B„v«¦¿žEP &\ÒäEžKiˆ¾gñkÿ©A†KöC,悯3aÀÝôÌÝT¸I4ã¾9X€Q}à–+ xGm?±¨Ó1x­ž*ð*D› e,„&H¬ùóVzTN½¨áNIS|ÆY¬±½dæÚ§Üù^Å#àÛ„V*¨ÉV¢3À”ff+4×.ºXÔ©‰’Kª¡>Ÿ¯/ÞfòBÐÙ"6ˆZP1èYEÕÏhZ©–OxÔÍBœ>­<»7ü÷妋u8®šB*‹õލ<Ói^¦æGÚcêcPŒ&u;^gð%j²Bã—ÏBìáI#h9õsY;SŸ?è•-ÑyÊÑþ8ëKv›Ôø8”@ZnËü[•ñömæGTƒÒ“ç¾+ßFŸþžÿÆïJëÀâP©FG’â!Ë‘X?‚?8ín':ß÷˜SÇÆµÌ‘„#fA]_žÇ{±iRAn.¥Þ—ì,Z÷“ÐÖŽ– ²Ã÷©fnìºå>Ç×åØBÖpæÙï»èæ±FÎAS1É¢ª}ôuÔh2ÀâNäœÔ¤ÐPQVE®ÁÁW¥ø‹œ3Зƒ ®ëžÈÅZTmÿ8±¸¬Î‹ É/÷âvH ΃ûÂe %1Î;%ê•ÑÎc+My¤…~Òñ:ƒáÚÌx=ªød¬y¡á«U98>[t)•ÎöÊ(¼à«æ~«QƒÓ2ãúìQJÏu"s`Ú½­ÿ°ÂÏð¬N•©À9Q.ê³2o°óÚˆÍÒ‹= F|ú®RüC“™h¨¶±7 z8°}Ù½;Í™cgóh!šPÔ—6ë=%·mŸ‰ †2ròkVÿ°Ê”`»2¢ /…_‰ž XðÆÏ„䕸ìQj qèr•mr‡´JÀÅù‹ù€'‹ÞlÜ;΃]ª9á]²ƒ˜ÇTP]Ò\('Ê‚€V Zž[ew¸Š¤ì>ÚrߺõxçÇDLž,\D„ ÔT.ºwï7Ä‹ëS„láŠ?»%7X˜œ ¢&rZ‡ƒœ±náa7X‚ä No€6yx]I¨Â5Ë7»*ûÌøÊÿqoç‹{Ó„}Q½êØgÿƒ[LdN¥uíAÏS|àõ¯o–B÷2‰­ŽàutgÏá‰f+¬ÄiÐÓSˆV4ìbà”Ä¡8 DÈÌ£Øà–°[MIo%‘)š“ˆý|ÂWR¥,&±¥Ñ ôvVXеj ¿”ï_þ-mjê\à@?lõÉ,ê:¦÷/7hwÙ®£Òa<}9¢òЦ¬-åi>*~\¡9Ò%ÃÍ0žZIŠ<#î3úð×î`TzÝW%êb(ŒYðªï°Û=ëÓ‚ìqwwé³ ›Xÿ‘cazk ´â¦ðj­|•Y»ÅܹXÃ9vÀþ;À*‰7IÜ#ÉžG9úDsí¶.o¶j#xççL¦ïððÉŒXê(ŒÂø-&Pmì§mâöÞÑ& G}~ŒûiкLźr~“éîIÌ[¬«)û£ƒ`‹² €îó®p¢=ޤæ Îó¨iVAiéåún‡èMÔÐh‘;v1u*A·yÄn BQÍà/sjGñ;WJjåýR*ôG–ñíz<ྠlÏ”’š§™ñ’ÅÔ¹ôh {[U8npàG®C'ya§èDq# ü醬›‡{…} ç–;€A5†Ü÷é&µþ.Í!hvž3ÅŨÕ$¾ï¿»dÏ‚¢îWÚÿ›{Å—­1ÍðR|ßÜÝæ–T¦7£9XyþÆÏAæšÈ yjj-&|ç}´9SP+¶FµIˆ ’¡£`˜z7y¨qÃÖgv[…uGÿ–©¬®¬ÊR]ÉRFUìù£¨Y½ƒÎ VþÖ 1·)OÁzôñœû²Fj½¹r ºmaþ_ áÚa"”[ÒšJG`ƒ~èSÆ}f$cy”-Q*AÈJKÝzv9DZtÙCëX0@h!w³8‘/E ¾¡ÑPïÝâp?üƒ Ñ{+ÛÿÀ^Bø¿¤ŽÉCÚ Ç¾­zþcéþŒé<à?ÉnØ|…fØyJ,œÛøPo»}1à7ïüc̈±hÄ‹ÁÿÒ¢Ïn/ÁZ}<0ÛdDü!²ÁÆ,Š @4cJâÿÝÓ !Ž»Î0Y‰“¥Ê(Nù™µ~J£æ€H©x=EÍŽ­ª µ¼KW|ê­Èä^.µŒ˜ùCxü>§zêGÿŠ‚B+º”Ë¥_™¤@ˆaÆÉ͹VÈ4ñúBK\Ò¾úÄ4 ð@) wÇ §;Ãa°nžž;Bzÿx£ìàêNÛ–¥ˆ´½}—ctÜ´#)C±°¬hëÙòË{/ì„Àg ŸJ•/Ú4’,1ª]çÓÇÙÎYÓû‘cɘ0þ“É(?÷R.[Ô¾ ³,wƒñü@~0¨2)•.o³5Ý©¢wìzØÈíײ6Û†03ØÌ&›mþ0$»å°Ájˆ1 Pw÷›¬ûBÜ3£tfšns¼|×vˆQxã§/·Ž»æ?5EóASC8sW¡ÌÚš Ñ öoï5"r¶næŠÄäL±YÓ~ÂyúÑX¡ÏÊë7Ч›_†•l0ÿ/>è¤ Ø)aØkX‰zå‹Oy w2ÛêÌ·È7z+ew€jIúLïþf»þÙÝeƒjºÝH4§WÖ´ì/ÙqÎ ä\³× ¥uT4ã–¬ÉB72Á²>mv!W³ÀùA 2:¤;õ͆Ïü ‹±§sA7°¨bXOô ~ÝHDØŽ×wŸ’ÅL¹x!n.!k£3[nõ¿i ñß åv*ŽúôMrœnvÛ„Ñ_;ßuRÓ{…¿ž–ÇXïÐöˆÃ6ŒûZº»8RTDÃwÑq<˜7©8›-J€d¦D?Ü‹í"–¾D“ã“ò™“ad2•²Ý`šÆR¤z\àõñé¤íIájkãemÛÓímd§s€б€ÔM4¢I~"9ÏZ,å_¸-Ûxó2õV{~þ餜8£óòÎ4xïUêÓž³Ò=­AšªAe4óW à1jÞ<¿Íˆ{­[Áçægéá¶Ý?¿¯¶1©š}¿fvž <Áœ&º°aíéž´`ƒñ¥0;ÛÙ?GéJw·8'9+Qm¥ 9±ƒ÷ª¢‡~¢Nï ÒÐU«³FH”œy–ÍÞ0˜—3$Èõ°/霔)ÅC³Ç™•Ú'ƒA%…]µCy6£ {ÕÙºÿo:*°É‡jÂ)[脼L‰|Ë…~Ƶš_¬Õ¨×vßÐõ?F¶¢ü‘Š´UÂgü„N“™?ÈØ®1™=m—2Öí»Ë¡z›þ!Ö1†×8m·{n¼Â-í æG«Jò@^¢#R0ƒBC!é[­#êS½Jè~ð¡ùÕ¶Ô]Φût4N?ÔÖô»Ÿ²íË~ñ“qx*$_¥ì^¡¿!¯È* §ëuïú¹\xˆ ]sû~7aQQ‡‰§ÛÒUåoËXFÚîМ®ØÜaÂÕ1¤+çÊb—iØŒ锌 1ÇR/¾$µê|•-.†MôÒªbâõ1Bu:¡íÅd‘Æñ%Ò¶µXâ#l”Q‚šQsÄ\ ¢vžÅ^S,(ê¡Í?1Αv¦†öKÄ„¦DT»CÒº}þ‹É{áw§Ê©ÄW\ÄÆÀ4pïÛcr?Ðö–Xáå픃íj›1áL-à©ý1æTð£[@@;}žSÝV ëÍOáË*UòhÖ,m¿p š–vP¿Wûá4{¤ >Z"ÊÒ„½…µÂÇžaøîQ´tySÝËÚ!E\FÚß”Q~FÜO¨ ÝSsƒYGŒ¿¦8ÂlòŠø*°<u°JËnû‰%Cca5 Å›í !dImð>è¸3»Ÿ!bï6Æa9ü¤UxQKU¿p«’S@y;ÁªBšƒä0m‹¾)¢º£¡½Ùµ@XE8ùjKz눧sxV6Óz8ð‘¥éD<æKóìdÌó%0ËwÖ*œz+]žñ¼Ü„fÕpŠŒ#&ÿGÚNÕè†[Ì\Ìö=HÀƒë-cEŸ~ZÌk‘hxŸZ)*{#œå!Ýóïá ª”©Õ7I²©ˆKÇœ>Q,æÜ}±f4¶©… ÿÅÂýÔU´+¹÷ØG@ih­VĈ‰¸ÓoŠíˆíÙ-‘÷‹mèµyÂ|zma,±Ç¥TR úßûØ$'¿µãÞæŽÌ.“±´"€Ó«^kJÿ4"wWH2ÇR°Äh^‡!!ÔX¤åå¦Òs°£¡!íq}rŸÛ+Á½ .W‰Àœü`Eëfβ²è`ïì§xXÃ{¢Ì¯ñ­P*µ  F9z|´¢¡åÿZ¸ñGj R‹H$ö×4°‰$ü.´ý…4 t((tóT¼á2@†|3‰KÆîtɳñFÞåå‹màË`¹õ­øËçK¥©JPiMðêÀÒ^è»9'4R«3ž˃ƒj]yN%LØ&~\Jÿ\Ÿ8îP]$öܿƄ5öWàÈ: ’Ë!.…Q¬LŒT é¯îÛrŸþ´¾6¾£ À¤½ßÛÑW;+ßÍq P]ÁYôøÇÎC±<2LºØõmF“ÔÏ\HõD°›a’wæ[twçS}ŸghѺe‚v®¦VåUŸ®¡ð5òè4^Û%DÅÔC­š¢Ÿí Áz oêÜŸªÒ×îh!¤w$¡\«ž-\òõyÂ)ד¥ü~¥,&„ü»ö”pØk€$2¥9s#Q“£F9óÍùÏ\°ÏûKÃq×Z0¯ ZÔ(8RÄ/R÷fH5šC|Ñ |æÙPB±FSÙ«yþ‰ç3(zÞ¾ƒwÊÚÆÚZGä[ÜWòø†”‘Т ]…˜ïÒ£WšOô?AE_­ò¼cߟàLÆŽ‚îÆkÂÃbH1ŒóÌ‘ MÔWØÈœJÒ]¬æñNÇ0W·)£ÀTXQ µùAh)ÜY÷ÓØùÆm…Þ ~ܘ§Že?rrŽr 8LG¢cÇŒt˜EªœwCX¾ù¤Ÿ‹&8C/]À0fš{g8 §+ú6Q;-µ@<’YÁ]$ÿ—©ïqj=‰¿|Ï1Ÿ•øJftú™(›Çº…¾¤I¨7¥…Fbú¡. ²âPœI Òú\#”¼~)„ä&ðC’|è’ âš€¡,«™ m¶1ú©â& EE²|Æaåáí¨£xž¶ò I‡I€dŸl†pzS.¤]®Q:afÚuŸÿ×ügnçç/¤¨lõ^ö/h—ýÝã¾c“ß®ÈuLßT¤TzÊD ­V1ÕKQö†‡rjbÑŒ1YéT- gÂ.öÉ£>è¾þpVœ…¥ã(¼ëü¾˜÷i}7m¼R…ÓA¡Êf¶Ö–I½Šç•–EmDÎyFiÉ«a¦SW’WØ¿j«Qe÷¤´è53¢‰îÞ4»ð/ñÈÑ^ÐypÛ¾¯=ÂMsÁ`óšÉ–MÅ©Ùà˜¾å£F©Ùgf<À]¹Q\œœõ`W/Äv?uÌk‹BpDD ì‚øß\) 4OpɦD¾ŸåúQTÅÆÝ£?@üàb $^Äx%Š’Úœ1œµÌaÉ›ø=ÏWîåWùI—EwC#ž3›ýQFvÐ~*Á€— ÉHâ~Nn7?ó-&I£ K^ ']|ËxêOon‚ʵÅma^±_OE-˜Y/Ö)äÔ`HWe²“—¢³‹ ȯú{óìœO¿‘aúB=#a¢g°Ô‚5µK~U“Ž"ŠB»%ÞzH¥Ý…‘MD¾x|"MÃW˜‡Ó“MËŸóí&sù¤ûRÉT†äâ$䔄s¶!÷.¬™2¹z4¶’7(0"8ìðØ$3ÏÀùJ  n¢†rHÉù¸Ú5\,N¿Ü=RéÉÿêü’oª@îÈ2$®ó—Ú½?sÍ‘Y«¶­DYçŒþ4²@§Ô]5÷¬¬ëK{ªAït$TPµEÝbXÌ& qdºA%É;%hM²ç¹%Go3 +èÁY¤…ÔÖ)lz‰«Ð‚ä] Ùœ„Ðp«Z$§ÿÿsìjDïF»Å.–䑺9—^ò§` Súl°AL‡(÷”`Çýry—¦t«aû7ùgÉ^hè¦>¢÷˘øYI‘ã4I tmôz”o”Öµp³¬pK³NÓ‹½$SY$5ê´½˜i¨±æ³yð¢(ÇÂõê© ­¾Gù=H®"E…ƒÁZ^iÈ*VÌøéRÔ¥sÆuCçÞb…ã'¯ñ‡²#@èCW“bà:ƒ%/áÀÈ%uñÒC.—èpÆ¿ÿ¶î‘ÔMøŒD"¢ñXiÃûÓÉ×§Ÿ|o/E/"!Ïþ68y‘¨:„®F €D>}bóu ‘£aæ8"…m#ÿF®4b%j(’BYÎ/¹ˆ–÷ÉÜœyGëyGD:ÔÖ£ô“WÉò§!´NR©h7éq û*γLH1j;ˆó4ôlÔ[_ã}Åô +‚ž'= µB*T-¨ý÷ÒÚðSQ ܈Pmûa£è{.Þ9Ð¥, “«LsÈMÙµ‘`A´«+ûÏí‡A÷…žYÛYí-­ÝRUåpß8d¢ÜSîâÁk…waÓcF\öÖg(vw10@ZƒÙJéG8¨õòPèB/7vÒleˆÞ;G—@eõݦ‡°Dñrý™‚}RäkÑ/`¡ô~$Ûþ@”«Ò8J±DoL§y„q‚içô`xÅq,CeY£¯Ê%ákY—nh)>XáÛeÎI[‡ýë!Ô=£ç:•ø’²™ amˆáÄ ‚¬hìpºmšz…»°¼bÚ¯´'÷B{âKÏSÊO¦ÛMû<Wà“„ ‹2îҷɘÄw„¦÷g^Þ¦W0VuÍ>À‡…;Þ’ Ú°äãJ9¥>¤¬>WĶNyù’ðXÇ^®ÂCýßhýf;¿S,\mËÞ^„W:PñrEõKþÜ# ÔŒ™yÑ–ÒÅ:$—اOÁÊÀð‚_pãF¤bF‘õqõ ãIÅ‘î2*'ßü¡œˆuã»"…+Äù-”û bLÖGî žb¨!qÚFeá×ÛÒ£ú½ò÷/1ƒ\ôŒgñ´°%U\Ó}‹^pö€êÚLi´–Іᆀëtóå™tm—õÓ´OåíuاÃãéu|ãæÂÜãÛÈ›dk£*YGí¤GT¾T§Úa&ÿsõd²/àómá1ÔuC™aCo.pÞûM4‡¢_¶ºïŠÖ5㻜w°B/Slz“ó³qÁ(?>ôT\)M¬×0Û”;±è¨ ÝxÁáÙËØ„Q7›qFkô2ÆA^{ÆI`7kºÜ¶œ³&lŒ +::œ’r£ä;ô:ùGñÜ ÛV#]쉵[Ÿ…9ÞWàØ¶k+óaF(ñßP5°÷é4Dµ”Eš¿ß5ê.3L‰Ú¸Ð{%çR—a¿ýz€‰¸ ¹+¬ëi*Ý”÷ßXZùߨŸxÎ Ÿ˜­á¥°š •q©­ ² V*ÀåKùs»Â=Á CÃé„ãEAFÖ}è4çã0" ™ÖŠùxEg›aOü×Åþ—ñGZUxþR“°ï?}Í›ªÝž‰/’á8/ z)bîŠl’ûa´!²Ø¢egQÕ=T/g|Uë‹ ¨[¼o3¿Õ¦$¨5 cë¼›’Æÿ„wøvÖêéµFq7)Ç%$[¦XÀ–YíèxùeÒèæ;Ux\‹÷ؼQÍÌz(/'‡Æ[ÖÏÚ uÕP‘ñ¬˜`„“Un ó1mÅ´eÅhŽÛ°Â‘Œÿ"ÉKÄ×É~iè9ƒJ-²ß{>xG7§½ØÁ*Eö‘tñÝ ¶n¥ÐÄy_bß1?/íYåhZõ„ÓÏ#ÑâôD–س®õ€‰¤ß£ :$8ßæVÎk›uËû0Æh(¼oÕË•#ínåC œ…‹q{ª»oeÓx¯àg]8'.ðò39{FYPÀ&PUíÝ¥ôXÃÝÀ<î.àÇ+rñÏ›L¼‚B±;ðgd n²ÆŒ]ƒox|ò¬­7Hz©Ðg9îŽÁ@ªFÄî„æÚN„Œ† \aðô/L/¡¼ øvº/ «Ù#Å‘«4»ê:Ks6—Õ¶ÔAa5S®W<…ØøNX‚v|°Ÿw“jJTè3cïŒ ­äh$¿~‘Np®y¶¢„ øÓºK7g¶ƒoïAǧã¸+25ò媙f#æuÊ|M;<Š'VÓ46-)ã(+¹Œ–æiß­] ¢c5ŒSâê†)a»èrƒFãìÃzîATŽN2IHÀA•È”<#V†üå‚äŸÙ¡C|­æ`çz'|?5œµ¾Vžì¸ÇÓmÜÌÁñ-幜Ì8 lü”‹‚áŒìYº*îe€Œ›S§`ÅñJæMëvŒ»t„…㤞÷J›æŠ4›§h:Xʉ¿­†hGÖw©(þ­ §©ÂÝõxÙZB‡‘3ëÆkG|ÿý£ÝÍ€ji­îÝÍ¿š's8Ò~š¹'®rHŒx⇀`ül˜ÎJឥ|pæ#3d ¹Mœ,E[dYÇ¿F‰äc=/€xP!áä•Z´^qLIAÖRº|^±(‘ý…ÜÖø8á?Ïò7¡ʊγâUò¦YwÔï—ËÍø.ÉX>0ûaÛLšΗ6쪨ø„b¬W…Ÿq•É•–ˆ¼&Æ}.fjg‘þS¹~AŒl©ü‚\WãY=î[Ò‰¯&6× Kª_ä¦wÍÕ0ßW!‘Êožãb­ym^æÈdš#™¦ 7S9—–8¥fµö,NÈœÞuèKÎ…¦ïCIír ý6œÇŠb˜ÎúÚéòɵ$_‘A·àWú;­Ìä¤g†SD¥/X²¬l´C "ã~tÖ Uƒé@uòªŒÇ6 Bd¤KßFÉ&Pªö>©«V0pù“J ¾qìÖð›+§¯Â+–Ø G‰×¶Ý`Ò*ð–6§™¯d ÉQ9J³ÃOpô¦ì¿ ĔӘ+5Zœ¸ #¸0:Ú븋’„Ív²U=G×Jä_»¶½CjØ‘UÒç×¹¾ÈøJù'! xŒ6þ{·ÔÕKšyŒ“",9z[äz[Sf¹Ûª&fŠ5õyo=Lú æ2âaÞµk?s ªã„æ_ß*•àdÚo¼ÌÖ”ŒjmŸ ƒùEï¿!¼` ]“,m«a7!»çÅ’ p ›ŸÈý°üð™td˜–Jj"oÆÁîh`•J“cf¶f".i§6š ZÚ wÒöÞñ÷¦ZÝ)±ë‹züe+úAyòqž¸4Í4ÀŒSO±[ ·õˆŸÖ\]¦•)–Ld%M‰ûC¦¼ÎÞib.ãÁܪ}UHÜvÍe=¨8²ÌŽõ¬CÓüÜ©§I¦-¸§¾Õ$¤KPÎ9þŒùzô9N}¾ªábá¢[OG˜ö Ø iÑ¿KÐkÞ .ì†æò×<_®rÂ}*Ôm°’ä1&‚äŸø}=ïŒK\Ñß?CUÜð—9wlí2Çræ'§ä“h•ʹ,ô4‘\Í€íh2­sÈ\ZÿIÒ?}ô­ñUUwSäcÌðr0 ÷‘ zNbƒ¥ßÌG3g&ùmÍhA>O6ò¡b™äEšJå⎮f8Û“ëS€ûÿ-~rñßnG+1¢?²¶cFÁ4¿ˆqî£DG 4\UDv3 ¶èÙœpÀP€†(õ¾è˜ù™¡ØD–@åGÓWÛ¾ çÁ‡ZdïžÞ¢5œ³Ôy.A¢˜Y!@z C55ØŸ@ÆÃ’EFiE³ÈÆ´¡†›t :ÞçEM'ðfKýc‘f±;Øï‹ªúõ¹…e´ùQžê˜"Ê¡‘dWáº$ÚN ™ãŽäb%aÖˆÆzÒU\k[hœ8}­.a$½×.л×ú£“ŽëM\C´×Àp}Ý–]l6óC€—÷‰Y°È±Œ,Éÿøü³FóÉ3^jÿçÆ.¿£Ë²“«|«‡Ráx‘ÿš|Ù=/]sþƒt¤–»¿æYã­ù·5¥”0 H0AÙtU0²½ÈüâùaÅ¡Þäûµ ‹{ä‡Â«1 ¬‰AL5]ÌBb2j¶¶¶Yâ=‘£îYfç©ï•´Q¶¶®ÞnCmâ;ÊS•áEï’ ö8Ô3–?¬Yqç»H ­8ó/Ók(*Lì’ñuÜärâÎ…-.Aá½=Ë¢ÏTÜä¾Xmÿ<ù9n”/Ä.÷pÚ¿I×Ù”(]=I߈±Ì9iâqÄL76‡'. ¹kU2­' Çé R@=·Ü ´Þ t¨·Àíè×$ŠÌ"ו¼u6_Âw®âŽ®+òzj—™Uú”ªöùà?쯵>ôµwÀC݃siš"’6? ø;–*=™­$"ò;OLgw’"¡ôdZ•ÜÖr28ÚÙð‡4åƒõ-U°±ÆüD܇iÔVx…ÄÒÅìvÁÈ…Æy=UýòïJ¡Ïn…99òníö"ãÖô³ åÍÀîÙ*3(,Ɉ- “gv²M<š“¡tt‚.™þiŽÀZb›ž£"î³Ïæ¼xúwø`ºió¢Òu™ËÊ&ÅR}9›€(¼•ˆ{f¥À« ÞÝ}€3™ü÷ˆÄVѕϖÔQ/UJes#z¸ŒÝ”±C‹Ü³¯Ë‹Ž%6w=vNíÐÆ…ù+[ù¶F*ëýžx¤ÿÿ£4!yOÕôH€AŽ>òÏh]û^Yó¢xï%£]q½…î\Â4ÅįõpÔrׄõûZ>^Ì=FL¦~7É–9øi>‡×Rd Ð>È\ ³ýî÷+««vúG¿.†­ êõ… Úô—«9‘뿸áá‘nø考¸äò ³? Æúèã [ìs®µ ’¬528”¢^ùLhñ´¡³|LY&Ÿ°¿‡ÝÖ’ýk>îÊé.î“Ï¥jÂF0F­P«€ÂÐÙT2í· B9 œÞÛ Ä­e/ºÙ,$-ÝmíÙLIIQR¤õ™Ù MN0º¡é9nRÃ…ætTÕ>ßmÂà7$©Öœ™¼ÀÅjˆŠ¬9/“@ÞcÐïmZÏZñèê†Q×Ê8ÊV¨ŽÒÜE-[QÍ 8¤0ÉEíȇbуú‰°;ð4ÂëܵácË«ˆœ³§B¶ä§ËgÍ€›º“^ÅÉ=±æôN kº*¨ºž¥þ(õ\šl|¦Q—ÊA5õ{d¤9ØÔ]ºœŒ†Ñ7£~Œû…lÎUþQ±c†ÁR­ 31m°y»1~UÝSó¾hS~½LCsü;ÔÊ©a›wœšó—!¤mBkŠó&÷Xb·8­û»0l­ —üúAËÊtWÝ`€°ÎõVñ±R •ºNHÚù2Óûvƒý“æÏ‘´]«ÚÄt¡190mo/4éà@¬`øÕ7Ò¥Œº¹Å–Ò‚›Ÿ _#{ô\JfWªq!1MFòì+·@AéʽËaÉ’Þe£ö-¯ h;ÜÌ #/òÄQ7ñâ÷:·‹¡È(ÁR/Ù.fïß»Æ*‘öŸšÓé1ÙàBûSœ@ ùĊ矔†QB²žÇàmyZÙþw®p¦F(^E$éõY¥YÒ™Ãä{eNUD²ßVž-%}KJ\¿ïàÐóŸå•åÚïŸ>ëbBNåI£ì[a0qÛößÂŒü˜1} n ŒêŸYZÈw#ÿw^Æ@¡ˆÑÑd*‡½´ýÚ¹Jùe’P¿j|˜ äZê—ºù"ày±‘îò aË×?2Ûò ?§,Šðr!.0ísÿS L‚¢Nl’„€‡g” Qëï„ôôHû™ÐìÈÁŽ6‚È%ʹbi#ÆL¥+k.ÓjM&øVÙ¿˜zA1}`ÐúÇ -Ë|ã³ëJ5ºpé<ô'¶o˜†ƒ:çÐO¤…Wg»“§þ°`K1ùvcˆå«>½bþòm©—òv´qäI<Œv=M3&5eBfpû¤xÒ«ÚV19µU V–ÎÎf‘Þþ”%î©qgÀAOU“!BÓ÷)ÿ„¡–9ô8BÑŒ¦É*ˆü:‡7ö¨þµº+;×ìÉvösÉNÓ®ª.ñ“7PCŸé¢tÙ0i`Òv~n=R‹¦ó­ïk:Ó0r¢ºu*—“É•YDY£2=}È ôf ‚Fg¥dÔ!£/x9j bÜ5ÎIŠ%q*•¶±3‘„âü‰T†Ó5”ß«¾ Ç“iÉLÇ äGæBÿò½x èƒdï’.;9ÅG®AGÜ«¯¬àgíÍÊOô÷Ó§’øÉU$ ±h³¥TÁ|)ÓÙº,)¢›…§ÕP ;Ó¤p¼>§õ†>cn0«Ð2èVâ :ú(ÏÐ^ì¡g^3ÕlÉCµs åÎ,6b1QB8áœl ‚ƒùA D ’(”ËÚóêÛ¢V…Ø\%ÍÎÏGµÂð;œµ[ÀxŠ ˜® #>oþw{È¢®ˆqf’çùänð)e-.¢%HâƒcG°x•èø¾(r pf Ã2t&J”FçE·ííš‘nå^8 j$)… ñ·cE@EÚÒþÕ#õŽ‹Z|£èJ¶ ¯äñÿð(À¤B„—jûÕòéó{°3¹œzÂ"®À¸SÄtÈÖŒ>§ô['œ´ h<>?ñ^ËHÔ¼n•ó”u–xWjâ€""mçÜq;¹Ç9Eêx&ˆ/Îýè°|Ë\BDz•n$ IÙÌ$©j†ô0þ-\Ý÷voëñØV½~enù='²ã­Ç˜âçÀ±i-Íäs<}‘¨íð_ö¶1F½'=G/„ 19!g]‘&ZV÷hxmäéÅM¹©KDÒ¢Ž¥"ˆ‰”÷Rçq¢Jåˆ%Û.o‹^ü¿Í%*•@‹Ô¹1¬*Ðø£²°.ÏØÜŽîà€~ÊÏPÛ®ÏÅ*wõOÇ¿+ŸOÖ/‡ºmÓž&là¥YNƒOúWä+#Brùˆ‹ò»Úö‚;eXYJrif• ÿ0å6pfçêåí#Ô‰V?/xqí¶Ï÷ ¨œæÛ~÷ äØ}Îí$`¿º»Æ^f¬\FéI¤ubéƒ ö´J¥­;í@e<¿tŠæW¤Y&ñêûSc¥|ÛÍY å}P6cH>½Ðqô›™Å¶jŽ@Úúm,uz6F*°Àÿ§{PÑS'=@zÐ5Ïb"}ÒdcT‚¼.,|:ÞÒfo—ÁóD‚D¾×†t—&nrÉ™4Ãý1!tç ´f$N>0<)âJŒî{Õ°ó¿SÕõtpNªto˜øó!.¤Ç\ª9Sc¤joêãÈA×âUOîí:Ô†>‡¿ ž•çO Ù3X¿Êà4‡$;6ñ,Ī’.Q½4QyEBe·[!Dè=‘££AO(‰¹pàÄA è*ÛŠy×–,~™}fÐ>Ê[T£ÅZà¤óÉÜs%7t©´rPÿ÷h¹@ˆ>+ÓeÎiÅ%dŽhù´B¤ƒáJ]²þ?ÏôKÙ¦ÿšžN°Ç†¤/—ú@‡ ãˆ$»t’BGß^‡Â°dû9Å–GÿFûÕ=ÿ©´µ„ u˜ÄV5Ú.ÏÚŠ\ gÙ™ ÛS÷ J8ú*Gró/½KªjÄ%åfžd’mò1ç$™~n*+Pv,Cû¥Âü€©©e0XwŒïwlú¶µºÖFI®dŒ`0O{ÞPÈßþ7Žgvƒ ÆâÕ®ÿ Þ,ò£ÊJ£Á*A“Òvº–§pœà,Œ”B¨ÔIP ã·¼æ³oDSÐë&D5õL,•AÁæ=[ÔýÉyÏf§m$Fheï5݆Ä@CT;è¡hئ~6+‰‹n¶Aï„RaÛš™Âs"!½!ºÒÃTÁ.‘åXÂ0ä.`ÉŠm|%k‡›‘ M ê’CÅ“’÷Áå6OÏ4 ë¡·ýæÞ¿tò9.ü{X?'ú£-â1}š¢òšH4ÓþSžôQ‘w‡ÿ¦u|Pæ[9Þg£¥û˜“«/ã¤ÿQ!‡‘H°¬?|,[7(Ö~•Ô^žiµF<WºðÈy—0+î_·ê…ÆÈ¿ÌOfRf*Ãv\<‡•Z/ü„3¶dlHÖ•]cC¬ÇÇÔí£ñÔvEMe(^µ¿­Ò¬c¡ÀoÌÆ 3—äTÍ¢H9”zw#¯Qê wœOJÌ °Ø}ÉìË¡ëÁÙ¡ùó/91`°Ðß.˜³oT,«ýYä&ÍVe´‚ë’M¶¨‹•pZá†O†¹!0~ÍK©SJöÍv«#êÕò—;°/'w…›<¾<*)ŒJdic§a‰ÑRWÓ§¿òõІÒâ›õeš÷3Ÿ†>Ï  þÒ^(\Þ*N÷H­ØT¸ æ9ÞH£íG 6~¾,V ÞãrÚÉy)G´ŽRÍS …B öö=¤y¨ÃI;f Œ¶w"è¨îÑ–½“dôb0Ö'5âÁXË@oùˆÕŸ¦´’'B M°Ôy‹ÞÎ0l`&xÜ‘=)Oægh¯"lÁâ3h—8Ê9Æ‘5óµ-X˜Ä.eÿÆæºuÒßÖ@É7·À ü,[€L?4Gä@¥éÓ8½‹Àÿ€}Aµ¦õ›V>µ€KŽ}T IoYÍØÝ?”¥`RÞóçi'¨©ö•üíwÜ >º¥ø=î1r9X&[¦C,Åøn ~›/Ô Z--)kLëf*-“ýsDP’Ñ襤Ùïû\ÀBô•è/dŒèh4_T“H^Ûž®Þf¹ôW>AÖv®ã»¶y”ˆ(%¿Hâ8ÃÐÉuލÚç;H7c}¸ŽHBËL; ÁK†$M!EO³7õ ë–`²Ûñ|û¬Üâ2Æ[ƒÙ[ƒ¶€Óï­µ­Ñw¸f°&‘ŒÀ46 Â`ö@]?$]óðl…u5ðÆÃÑ_§=à$\å{B}z-E$7òè€Þ$jO‡XAý™•X§‰iv¶ s2°AwKSw§ÿnÕ‘÷¶kt{Ò@#κŽëT(³Æ»2iBwJÙÐS*ªaE×Ãñø[±}F/'u×ß - ®Üó&;Ì^± çó?¥|—ÿÕŽ~!Š´ˆ‚|V‡Ð!±24¡I°#Î)ü¤rý„0VVªôؾ[1î÷ÅÄ¥#™ {ª2« ÝåñI­}b˜raµ¨F¥¯CuÍ£óSöÁ̇û²ÅÈÍ Îè\€n·˜ 7i—ãö¬,sÕ¦ËY‚Û½ƒ}󚘌Ùr«ÿ ÆÌ²d})¥ùêE°9HW{gÅË“á2t2Û;«±[T7€Ä{*¦ Þ¢‹SŠÜ؉²Û yh$Ï×òŽžû ] c“øëšéW%¬’ß$ùf/Åö1èK ì"…¼“áïsŽõ•‹lï> ú?ü3°Jõx–H+éªoï<3 íÈ`5áĉKƒ½ž}\^_nrÁ`œïš€ó?I ÊÈ£GÑ7i<«gÍç>fjA×VŒé‹œøZ£ßÄŸÉ™uqò-5µIKK1x×7*W Ýos7Wãañb-h±ê3‘@ÓuxýÎ}4YOÇ´„ºZe¨ì¥Ý˜ŽZ5uL…†%ȲSÝ)âíd>»ô§ÁËÌâ @s³)*óÿùdƒ©LœvÎÿï?ì¢m`i%“ViÓ)Ö}[˜2}p •FÔXÄH)å0Çöyu‹ÚíW¾(§§(w§Ú†8·;çÓn“OyÜ«ö› .{¶Œ´yåoòبö07™›œ%ÖïR§(+²ÛÁhâödmüp(3UbjÌYUEªTÌ%aÂ^H%Zã›ÅzA lÄ/e›å‰b4úÛ~þji;»,*'5Íñþ_2$Î. 9–’9áÂH1¡ _²Rí­Ó†˜R™þ;D”$‡ñIm¯od “»¶ß >Ržº%‰–²¦L¼rjÈ{¡½MšO •A˜wÐ3€šð/F2íãóÛ >QvÎG-³‰ÌcìöÃù½ÁyŽºfv^?¾×‰¢(u“¡Zr^Ç çV˜ø`ªI÷Âqoq„¨yÎ…8U(ˆaÑ¿0Ç>ùí/Ù»’XÿLä/ç°% £ÞOuk¶Ï0x£VÎ ‘Íxr"æpa2M5œý8V=æpê@üOzZÎ\+Õo%B*ý.£dJƒ.„Âê>å§ÚЍvS<ÎtA©¼—íMÈʉþƒîÓ ßò&,,ñ’Ž(<\<óf}éÞ’Šk&µ€¶¦ ÝpÝT³8(osÅG¯›)s¼©’Àꎰ?ûìE¦I,ì~ý0[E $2ØŸ¦BÆ«;:ªÌ:@e~òWæ<=‰Ëç¦d¨å¯Ã{¤â>EfäeÙH:°'í0Rì¨þuŠËÇÒ’ëÝDE¼}®FÜz*NÐY™% +µ/t(Iø(-l†…Š%þùÜ|©Â­8+ܸœKçBòäÜÔ@/ªø•y 5—Ð!’ oî݋鮒·j(­èg=ÍÂ$Ò‡8“mtWï &˜)Þ˜Íú£Atž•håoC¶ü º¤<£Y®píÆw“‰H”‹áÙå?ß8WUþ®þ>Úýë¹´`åH 7Äjá”y_æÝáí•æØÙ† qH4LåQÃâ\^û킉Z¤ÕS¬3„ÂjŸ*d¤ž1—GxkÄÁN‚ÚÎŸÖØÐ ^È#bTÇP]ùTÔv.£•°Æ?­ÌcéèR ÷´Èè ¶œÐü€“ÁEãibnF1(ÈVímM òVê´çÞ¼$é ðŽÔï/õ®Æ¾n˚Êãàcãw4Yr«ôpTeI+ûH@ ì›Öžyÿ0“”&AÐi× ѳ÷WXE*E®+*y{`$Mzã¹ðjHsªè°s?YÑ,ú3Öh ¶˜~S«é2óèãUŽÛà Ÿ*2Rju@„$§ø‘1o´Ð×û€Y¼œþUê8¿ ¾•…«Æ©DæÇ‚XüŽ_ü>J”ÿ°¬0*¤dØg[ù3¯©Š¯FŸ¡'ìvž‰z#skø'š 7ò?›s=¤xŸÊ|®§E Ûã#„pÛd†$Ë?ln}oåØi‡Ÿ>¹Ã¾ Å…/¯Ýæço Ž`ÿÔiæ87˜Þ ?Xé“ícßµÜlk6ôç¤è(µ‰±¿º„¨7álPêPeDºœùÑI†m¹†ºø"Iñ0ómá¸yóxHr$l r†4.Óëtå"·fö–ƒÀ«8ëApªÝ0j4' ÀO²QjÈwîqë¢$²œ*ˆ·iÆP¥B—šíb‚=éÓ…€?}0Û&NOo&>ªýÕ›öh€·¸†K0õ ‘†gÕú’ÍüÐíAx,„ή„ -°åªb aCÈœ¹m/twµǾòÀ’²m]AŒf`°}—OBÓù‚ûFý£7*‡ Õ' óÊMî ýöí(@§¤>Wa¨1·ñTäeüwÃ8æ¡Ì•BA­Ÿ«"b¨5ï›ãÚ‹‡HE&O?G,…Q(¤ÿ®› Â¥³kw„ÐX6(³nfbì¬M“:v+z®çɪ+“\þùcV ¾7>=ÜÊÓv¬nÎhˆr_¸è–Ú ©ã* €Ù†äU\" \Šœ:9Ì>.FåêÐW0ÂBóÝn‡œ¯*iôYiUq‚$y'ºWÆ+:¥e™DÎÞ'QŽ»–ÚW)"§Â9à0QrïmÂl'(QL+ÎÃÁð +–,Pœ¹Â&ƆaiP.$\í§üV”løúÃ1Až3t®@ä[VÁ9É÷%A_WÌÃóÕ¹’îØX8©(ݹM£Xç)å«Û±¾¾‘.NÒ‰@þO€¹¬'üZ­””¾äûgæ××¼pdi¡ÃÎU΄ÈáÀ§‘ë5]Bm`{V˜mÎÊ;ê˹ÃÏ+¨|j?ò"X0v”¦J•–žóç0„ÉehSgëάåÜ;Hß ÏLæ¿ Ýé•ió Â追E¦}»âÆSFÇÖÍø}»(´-\•ƒšÏ§ƒdͱ¸Ñ¨Ieñ}8S<–7n~ŽÃôû)_¦ Kú›ßžéf®µ€7 ³…Öd&#G&kîž‚76ÄSÞÊ¥ k˜ö”Î& –þ.;ZD¡= U &ôrè·µñί½ö?MŸçÅÇÈýèb—xJ| ö ˆÜÇÄ›.+Uϲ"£ú[¾nó6'õD”ù¯9ᦂN‰—~LëugD–N~G2‘™B-¢ã÷½ØbAô`müƒe: fÜð#p·ÜbТjjÇ[YZ2.fëìjß´¦û|T`TÝ¿•î=ä{2æ†áì…0½!´ÚäÕ ‰ƒàÛˤümÙû\ÛBÈ{ÚÐñ ?‹€!_ÓõxÍó-\Xè8Ì^“Ìô°v¤¥ÏšÍ«Dpô»Dñj†©žGþâšøxµ-ìÙ³'×Ö1Ì\\Ø ‡ñCGìV·F ®Áø‰á“=rçƒe-–±2ÎÖPAnÄ^Ðîô9fu˦ò{Y!xÜ»s¡³î««3¯+Ô3ýö “™™ô~V.Á0Ó¢#êû6÷ç¹aÇÅøLic"¨Ì†Y8ˆO£õç$Çk=ÎCë4gƒG¨z¼gr~i¢Î ¹nhìñŒc擨)/òÉNðʨ›æ[m`À÷n¿r·=‘9 ¢ÿ«²þºË1úñe Ò†/>=%_äûÂJÚv´á‰K`—È¡}“rϾE°ŒŽ­]äùªkæúg%ºÝe‚Û™/¬}á­T¥LüùB©5¼Q @!„~ÿ4kZæúo vM‡¸Ù©a»= ¤ôó³£)g÷™I¡(ùîÞ``v$ßi¿›XÌ2^Kàì ºX¼2AÓ6£‰ïÌSÙCÏÎY²ÀùT+˜½5`)ïðlæ„í¾Û=7lþMû@µIçè(ˆ7……åÜsò–¯õîÌx§>:¥!@}6FxvkíèüÜ1>Â`Êi¸›Ïø»8È#Ý×hÀ¶Ÿ}˜í{¬ïßq;I=ƒÿÇŠŠ“i(uâ†C9Üç]©…4×Ô>ŒqQØÈÍPª>Aa§…q©®Œ²Õ1õ ¦”}ŒèÅ[ÿ@Ú«k¯‰«3"¼Q:»î†[¤8}§Ò€ˆóÂ¥P ±›a´§*ÿÏ–Çô‘~§Ü8ö¯l&ZJPX·âXè‘q˜ÿóOf7¶€#áß[0õŽf‡°¢žšLbêÛ1²£ ðÝnMO:¢(DU˜ ™ª°¢uë‰,‡·)…eŒ+‰XAŒ '>¶‹¶4S,³¥yZ-gK~÷ƒð©-qFÑ: m­+Í?´ûB/-ÓÐR‘¥µ‰-VWÏÒ§™£.EPtgòM¤‡¢M«Ë¶ùéäáEªéKž½ò(þЈBl5…IxÚèæÆÿôUá¶c*Q`çÌTí""`["-Uã vqûrg> ˜ÿ[ÆÔ’8‚ܱ¯ÖfqG¾Æ±•²º¿h'Å:ù*‡†è€_2£WJýy¦=`ÐË3×GRÄÂŽ²ò9¸6ô(—›ÿzáõ[cßÕЇ[Y¡Öiƒ6_7 ÓW’J$"¬MŠsò§ëøâe ÙÞŸêµñ8O¶»—Ú™”vbe¤öÐf­ß4xC_®4/ê{üÅ]J “ÆÌ)ðvXmGº˜3”¼]Yêµî3_ïkt—ÅÞ³ëÊŃ ôükßYþÁÚ¨-0E£cȘVv;tX¿¥„ ȤJowmüU‰××vCîsµ™¡›k÷¿F?d-Ó!ˆ©ÉµÃ5I¿bÑUXsf‰¢_בÊ+ÞÒ–b/€jåƒýT’?›!e|¢ âš¶´ÈÁ<¹ç ô‹‰9²²úêU¢|“þú#"£ìoð©à ÚªN'ÛEº~àå¶§1Ù‘ÎMŽÔ9ÔàDŸ© º<©a{ú£]† ©<=D¼Š•&Ä((¾‹ëÃØEë~)íßÖ²Àobz—£h­`ï·j°Ýšpr]/)¢c#( °ø(Ÿ6ÈŸ ½¯AàÅL=Bg†^G™ ”Zý!²Té´#¤ŒÁŠÊÌü˜¨î!è9ꊲ0@ca‰%­‘™2ûSÒ º“¼šr©,ž~­>ôjÜAԛ聆ËHEŒÁû¯Œg\õ—8¯6ˆq¹<ŽÎX·¾Ú'ÐàH43­ z5>Œœï=§³b;9„Ð Fß›¯;„ëãï¤j³Bx:â&e}`ßíZqúñŽ›5lê7=Gl-Uü¹Ÿ+óq…uà éõ®2Ñ ²>¸¯äŸaÔ·¾vG6seú “¿jؾ%WPíD°«Øk%­`ħøLùŒŠo–‹é%_òÎïAúq\ƸâS$ÉAâ'OlEãÝ|ôO©~,•¶ûTIGéÍ2©™üµˆPÑlE=ÑW|ĪˆŽÐSe€ºÀSPõ½eÁ)ÃQè`Å÷T¹ÿlþL±‡Üö 7’kµ,¬S!@Gv=zÌIÅ ñ‰ƒ%`¾8pàw%p!4®ª|çA8ëßÂîRTÑ7yHÚX?v”ÕGèB^ù•»Ó¨àhY~ceI"ˆÐƒÓž[áèôº#¯âùB(]“I£1æÿáÌŸtù³3ó<_˜}ʰ'?¿ü¨ 'sŒMì~ð\HY£óiĘz¬—2Èv­BiÃøŽ»‰k+¦]«û“Ñ´ MßÓV&LÇj’þlƒjpÊ‚¿!¸;g gý%ó….ÑŸ[rVÜSCyÿп!%p†ú\ìþ¥””}(xZŤŸ M–¼”.25xX\º% Eu4Ím™Ÿ$hLÄ€F²h2M7žNj„Oz\vž’GÔã…›Ÿ8?>ô¿8C&t PuÒÜœ`°dáä6½­ *ÔĶŵiï½ûã¨S_wZÏI„í/õºËh±F6]ë&ÏSZúÃkÝÖÂ[ 7ÛØ6±ß¯î@¹¸ÜÏp ¸¤DqÐ1‡ÿ¶—}B‹ùd@9\Á±8fª¥€ 6‡Ðð>[×Ñgè3)ÁÑy+vÁœ¿Ë®1*Ëà;OqƦ;Pá¼OvªQëF ˆ- EßûÃOÛöëãõל|gÖxzð±~èÒkb8U·¼{œ°DLLQ¤#æý¦š‘µx0q<€æ$« ÷mW›ó î»_œRºˆ¢ÌJìŸÉÝÈ ñôeõJÜ8¦ÈÒ{—ÀðŠH&ï¹s“RlUpÍû˜àÌFÏ5¼¦S`Ir€Ý<œù~mÝA”†í`9@ ýRNÀï48 òûìCH¹ïß5ÙÆb$"7LvÏ™D9_1Í_[¿„¥cC¼‡,¿Ÿâ×!­n2ðÇ =جå4ΓäÎêÀG/I–,L©¤!Q¹<&I¢´øz' ä»5Íò+)Hå5tPC…g ÝMÔ4Q·”ÊyÝS,–j Ý껭íGë£f^N¨ßÐØ>tŠ ÐTì7`ãéüé´y@²Ãß^Sß+ÁŽ ³!@£Ã;¡ìªïqö7ÿd|.¢ ”ðÓ.IEÔª»!T|‰I[”)½p½“Ù˜êÞº,³ˆ/žG‘Ÿ„Þ,jÏߎŠÝ?Aéº÷ñ³nlÒêêšY+ Yt¯ O-л٢ÿˆ0å/yYõLÏV0Y|DüSDœàéé‚ÁÓ¼D\À>©ÍB5צRÉ æ‡ŽÎÙè¼è¼´Oª#-ø²&é¼À‡âýßÛ‰NçýÇ ÒŠêIÄåL?én`R¤ÕA}¿'áGwn3'dNÖR£µ&¨¹ø•ºF »·ˆAæ¾C_3¡ ‚'É¿ÔÒ¶ŽW3lž0HÔF㣘óZã ÈØ­þ$ù¤#Oý Líé?§å9ü²ìQ÷—hG¾C=&óZÓ¯ü $Œ)&íiÃm† ³³+í‘X¦@Š=ÐU¯àÈ`ÒWþvcFÄ6©,9憉ñE­üç‹ñY_£º'$=Ú%k‚]àóf¼nLJÉ~(ΈñE!UQ˜Fµ8!ƒ*š EŠïö[궃Üé Ḱàäß«>g§4Ä¡CôÖĈ–ÄÎŽ«±g°ÆSѺq:„’*¨`ty)…ᜃ^1Èæ' Ã>~íîÿ ¡Ö4X]žü_Ää’3EëA¸7ºµ¹>y÷OœÇñÓ(Ž/‡ƒ=•R’ÑPü¡oŸÕBépatŠÅ]é='×À±¿Ö¡ еIî —äa¡ø>¤\ ùÉJQý_ †|)Òì¶&”þqúÖ#í_ˆÍÏ¢Ðú<øQȺ›³v9Z¢qþ4-×¹œ÷tzÍ›$Öý?Á eZ}¯‹ƒhÇ€ìB¡Ÿn„$̰|Oæ·Æ:g9¹Dn$Dн•ö°œú7íáúËùc^YngôÜeÚ0²h’Ñl5¢¼0î‰ðæR~µŽ[W¯\3L¾aÏ;#^Ô•P‚­ô[t©e2‘cmF1ïÂäd $À(ÓB˜§Ý ]§JƒƒûO.’7pîOÌ=¿GÐì©C”!ÿ6ç¥-6ïT”Ͱ擬ªöšçïG¤Û³W>-ºÌ¨ûŽƒ»1µ|“{Ì¢ñ"šu M[´OX°·Á)gØ®qîUªˆoò^X¿%'-J6<Ø6‰ë0ã‹SÀé„dá³V~q¸vÉvT XèVxH>ضrØ¡¸ª_ùçûÅñ•&¢Kßyöeª¡´—pê`¥h/þý†I(­Ö£é/°.û¼NôÀp‘“=tŠÑ yGGÆÍ$Äÿ¦ØŸ_EXÝÏPHEÄxÓ›Óä ô”1L ¼ÍêX·Ñ¨WŸÈ·x¤²Î áÄŽ¥Ub{៉Ÿ5£ˆçܳ@Ñx  ¬…:oïo<_-›–Ðp$*¿¾*Ö ½OŸÉù±H‹–›ˆéè7­öÄ´çå߉ыå¨q¤ÿ3ãñ‡GOvËLqvÈÿ©L™Ma2UnM+&rP½P<l…²Ž©°‘7“•ž˜._©nDÓÌá´Fx8~a{Ÿ pAeørøÃH ÌZˬ&ôÕ8³¡œ:˜¥à|–Ïý`sÄe¯QéÑ“ò€Ô»ôãrøB.H~ÍÍð5W#’âSk6ÚÕ€õ¢· ÝhvÆ« €þF^¶¾ëùÕ›z’Åç]vëWž™&ÍL´C)OI*[ ;`¸¦’-Œ% <ƳôÅ”$©ë¿¬ ¯“J‘§Y,éÖK$³SAõ£Î_,O^nk£W;6l@K™X¬žA@Ï›ãS×8M’#¹þ¥ÂàTÃlWÚÒtL#„É©ñ´ŸG\Ì»ñ1õ?½xòe\òf¥x›.eˆåïÝê$šÛé–„î\_Ï|M<écû#ßÏA~ÏHœç”¢·± _ ¾[3“‡„>/Їˆ˜‘ºšÒ©gnx×/*ó9fdYóÈ%gò( gúw}âÉŠÁÐ=û¼ßœêuýÖí|-¼×]áyš¿,6X,عrQ5ÙÓ¹f"–ŽÿÏô üÊÀ„ØÏšh[tfšÈQPÂôX­÷V—{jâºPô˜ÐÉ.­ö[¨ï½p‹Šõ›¶Þ’½u«¢¡ÝUÚøFRdzÏÔ#æé´é“äoó|ËòÀCkæ4,ü Î ¯ ˆã8Wq3÷Ìà°ù¸ÄMìØß±’gõ( Pȉֵ®=íS˜yBȹŽcRÅþdB“úðè=”>Åñ9a« 4ˤ”uí)nKÑ_TìCÉû\×zÛÓ hj±£%ºõưq­}FWƒC”¸è°bÄ\±ü NЃ—ØËFriw„M¢dYüno»¡ÒUí!ÝZ7¤Ð¶c ɺ;rFKͽԇ.žž’1Hü}àDÂéLÂ7õÓy€€ôðñž¶ÇBm‹ [,Ýûã 3S™¢ff _€£ò9ðfP2‹©Ž(=u—º©ûôøD¿àÞ(Ç hIb+ò€ýÛs×^ù BP¡[ÅÕ ù”±5§/)rDJ1¼6ÿ –KÅe÷<ÿr7µ/©uO*ǘý!tEc½ô$$ÚÜkׂ`º›ËöŒ•#^—x x¼KÇMBÅ4{”v'¬¶5Ü»óÁûÁhÌ–=†y_ ˆtçð|+Nœ|Vö¼‘óÕú¬ÕþCéyÝ„ö‚%¬Ž”Ç6Ÿ¯ BÌÜ Xþy—ú‰s@‘¶%`g0žæÕÀÚvÉ„*Bà…Ãzî¤Ø)ª1ÍwVý]€=ò¨p0y«¶q‡ óF¬¬j»˜:twZ-lÄ ëwÜ¡ †¾½Ÿ„M{ÐJõ2›áQÜ7"^rlÌú˜öQ‰—¥§š¦L%Dc5HI= xÜ3¡-#¶°m½*„#vj5)çMY{ O§ƒ.t$)­!›™wêë¥ñûEN–YPÑ/LoÍ­º«ú0.w†lRÏÔƒÅð5m‰Lå5ÿÀßNò7ò8Ûw–_ø%…‰vúàÛî¤xóSÜb>†/à 98±ô8ÊrµÛá£à.÷ñÛìaÚ’ÒêîRp½TÒóĵ5&½À$…”)Ü—ê·ú^ݾ‰à@ÓŸF¥~‡??þÑ¥þ8Av°.qFpîö­–¢~†ÐŠ‘ï[ás~úã%çÉø ‚‰?äCig³ÞØ9 uDJ)ÒÂg£þë‚õ7À–kG¦þâÀ-à•ü+©çªôå!^,C6b9¤Õ#Ç ƒë÷”ðã¦55ò•àF:Mi§0þ<óuò^ˆ])Ö}šÃþŽýTí.ôÈ­/U#‚e‘*Â5¢ W ‘3>~«b.6Yî¥ééQñµAö¼LéÛ9ö§)x^Û%ÑW†þòš5‹ §¼dµwò5ò]'²^¶(©Óì_Ìü¦þ¼¼J*\ÞÆƒcÒ;ˆwàA_}á°ñ#h' ”þM/ÜÁ±ì;÷løaËÝ ˜[ÂÆsƾK‰AÄq_~:(ä/˜zDî˜  ­7AU¥‚÷ dâ ð%Â-gŒŒxÍG‡¶—}Ž 'I²¿?Ô8ÅÅ”‚DŸ‚ˆCà¸vì‡~Ì)ÙU•ÒÈ•b ‹ ¶7f^}ÍÎrgQ+ÏØÄ®ØYeïÜûúº@ª€¬Õ„ö%º ƒ¹ÛáÉC´é¨©P(Ó¦ +ׇN[ôôý*ZLún­ÞÌ$k®|e Q`P¿taÀKÝDÇQ»-˜gäÛíþ[2^_›ºV°nl ·ùŽRõÓÁùý>Ÿ™‘ü¶ žLs¬ÓF*]“JowH}–Åžÿ1M½=õ=÷¸Å— ‚§"¿´ ùŸ¬-#òyãÕÍìcUçÓ=2•yˆ„i°Qé0E]Š’N·†jÞD/Uà‘cPéÅøÆÕ ¶šEˆ5É»0ÎЬ˖ç3 jQ{æye’Ó*å£ô[Gz–‚=«½­ú#sÛ!ýN¤× JÍM±ÃJŸá xù—¨”gwäŠT„‚#)•(æÖ-‰ƒï—°/„ÃxMúvŠk»ÄÖeWQâî5ÆÎz‡£”g¬/Ô›÷ÿÒe£“3{ˆjx¶3Rùdþ‰ßYåðÆKÜi?\VgtÓ|ª)ÙiÙšÓæíÐum2s³bav¾P²¥’„@Y ʦg–SÇ ÕT‡R}1^²o C65X™˜äñàùɵm’õýæÇñ-¿Òu8Yqÿ%ôÙôþ  ãR²cÿ´Ní^‡ûyRÛ¨¤@e°Ô§ÄEÐ@4âô˜ÿJìë'v+ÿhÇ$·áÜ‹!C±á†!óÑÒû@í’¯¶×2í„P––UtðÒò‹ZX}ÎÜnÔê›NW_v+CÚ±3ÈXÕ–»ÊŠjaLÒá¶?c@î»øÒ „jÇÒNìmm£´Ì„J¼¬;0¦°îŽô1 ³Jd§R{^².™lõ'[ƒo;Tѳz~DîT$JX\¨áZ8$³!N´ó@ЗD64ï÷V« ¥ÔÕ>ZŒkp›ºûóF×Ê£[ ñÊ–ü" dÓ^ÄQK³hà°ªvaßêÿ2Áp‘¸ŽÁxyàßð”#¤©ä¡ªÍ…fËkwYÊcKì܃§e™m¸]’ä„úœlÎmÿÞ•;c-ÕÒ“=ZEœÂ`y%¤ŠÒ™f7žgG™·ÂÈŸd·XÓd³ÏhëŠ&ÄëVUj¸úf¦Ü$éç*¹žª.={ ó8½1§y›¨–?„>©&cÀ¢®y´ Ìvmô; ×uUE }H̨¯Â…6ò]êǼ+K¬Îž‰Ër šÚ’chQIžÀB ýN6bè¯Çøù`“Ñõײ9åJ ;ñ•¦d¹b¿ò‚– ¢CÛvç¶%ð]N˜ÌŽSJç1Í õ£ý·p¿|·,…Nƒ<3—Þƒ÷+ÜYºyc·Çâǧî(øî+ âq¶:W,“Î&J¿#Á°]hho‘Æ^±X~¢¢t‘¢ÇV: - ¥<Æw»È*@œ‘…†âi6š0#ʪ¯)cèÈ”cÖzRÖ¿M¸#íBMLð… ›cêt»ç˜(¾-ºÊñSnQB/žSò½fÊÇS|u›å¤BÁ4•±2_©âÆêÅÐü%ÖN æ@)3 œÖç ŠÄOüÞH„IöÒó„=’ß…«/ù³9íßÂð­P £"ÄåˆJcJ‰\jm WïE8êSÕðGC– $R;¹_ÅGÓJ%~k/6nSñf ¾>‘$`Î¾Ž "VžZ2jFx¢–;HÉAÚ­;O#§r4… ›èÃiãü CèúXB±Ãn ΰäé§Ð=m[ýéMáZƒüÁ'0—¨¸’¯£ÎA±¯¿¥póm´,¶_ï0eÓá€_& šXò í´~ÌÝ“#µÜ›o©²ß3S 6 ô¢ÈïÆ*'*¿(ÝÛ{˜Ø6mÐYó÷¬8´1œ«-ÇÉ(¶6¢@œIçqåëøWëóy»C×K“ÑrÉ^AÒôˆi˜áQ 9Csi¯2Êá‡Kz£›’Z…¤Í¥Ïeù–d ;ÆÈÜRw&ð9ü¼põ¾ ‹û„«u‡b¡´±4’V'5arr¸!1¢Höh¹lÓ3bM|ÝÙÍ2:ì Á¼ ð›ó”É£‰lLéUнJÙ…cħÈìª߯“ú²0†´Â§*‹¹&Χ}Û7ÊMf´ÂÖ\mÃÛjÍ×» Žb…×ÏØÐÞ”eà§NäÛÖwÈ üÂ8gǛ׫ÍöE42ce—â5}PvÞè.ˆ‘½#û5*[jpM’à ȳ{¾²ãíÜŒ3U"¡Î7’Ãå(îømj”zXé8º¦Ì(UÚ¯ mç9 ~Lý*pÓù©0qóÜŽ•|ò‡<¡ÚÃ껚ü`ÌQ‰j«ÂKK©ÿØ>Sã„–wÊYC×·1Þ9þ¦.¤nË8¦Õ&«FÄø˜¯š(oÞi¨¹£n·M}P¨ÌZ˜ƒAb¹ò…O°ÕÆJÇŽ%c$íÖç?Àq©ÕŠQÄ(9#HƒhÍS5{$‚‡VUì’š!vip\UhŒÚãª5âÚ"¤VZ³Å!½•³WbçÊ=ÿÃóîù<¿?àûúç¬Ý¨a¼Û¶±n;=¶€Né`$´ßa-íñgÏ»Mzx5¹A'ʨè{å/ÍA‹éN®:)‹¥¯…!ËÊ۾ʽ pï/ºETíݹèJä&¨]m†ÝÌNS*…QäÝð—–°¾UX9­‘ 0h9uiz›Èê«äVÏÑ¿!¨ÿ±^!)¾y «*eÍg‹T¨1Ýöº)ôBóÿïºZ½ÏÚ¿è;õhZV´°*S É+IÖÄ(j}“küÛ¡ww2ÁážØVÜ¥/j~Œmª[¶Âž(…Q9º›¹ÃO ¥c^7-¼áŒÃ&áklù©Ðz¥ÛØvPßñÞ›€ ú¹M­ÿÞEi(£KN&çê¦f¤n5ª”ØâxD…¢¼Éè2w´vÔ<۟׽œÓ}*XX¡[L²0º$øîƒ`ÑÄÊ{™¹óo›c„vB´zEG è*CÕkrƒj•‡2D#Q$u ùý’¶‹Tä3²lˆ é%§kB±1ibÊ¥¿7æžtÝHÍ ö¶·HB‚iïR_ܼXß±¤R Dv[!&£à¥23ç§À"Ó¥ÁÅ ÏólA[Õ÷çÑ.”K—ÊðwB_…@Êcyx{î]† «,ÙëÂñ˜  r„à2¥âƒ6Qq#¥¤TÞÞ霋!ç„äŠTŸuÜ ¦1Î0B>œžv}ƒ\©¾ûéÒdõK—˜ñÅЬ ÉžFÉ®'zаÀÅ’|}ðm ¥ã|pâÌzdu$渱áL‰n[Ì H¤Ÿ•›¥Å¸&!]=Ư§ç5Òó‰m½ÇhùqšÀÕz½†šOìd§0£«±*AЛ³ß‹ë¯"7̇´0ƒÏ5ªòHê*áNþ•€GWTn—¬¯À^ºµúß-— ¹ Ù‚Pt‚™9Ú»yOØ |Ö‘žcsø…Xˆû2ÎA\³ÞBšNœÀ?.uàý½ËC¦ÄÑÝÖNjYRê»ì®˜’½‹@†ÙBaç(gªrâN›šnwù SºQõwî¢F‰gÎ;­ÖGsÁˆå8+µÚc{ûZ÷¿å>u¶ïÊê›0/—Gˆk÷ÙÒo$Ô¯«„ZÂ,ÄJåÖ‡?ÁmÅì5á §äë¶zv¹(8¦1þ¸¥Û“Ži¸azŒ|¤hIçŠ%CæT©ežÐ_ñ6}UÙhÂéÉ´$E±¤ë†¼½¨c–¥©olPvëÜß‘?~F·8…÷;×®FÅMÇäñä‚UîÌNú}n¬Èðn¥´À×QJø™×C˜yÖA1­e½fNžQ²à‹-á–AðKOòtž®üõKJˆ¢§U§ÐÌr÷®òë,móÌÛ'oåªlêá.Èëõí£(;ƒS)œƒÇÎü¾•’óŒsÔìÆÃ§þ_öàð ðöÀ‡á=ðþ|1xïÐ0Þû©¯ß¿_j£P endstream endobj 114 0 obj 100471 endobj 115 0 obj <> endobj 116 0 obj <> stream xœ]ÖÍnÛ8ཟBËvQXïO HY²˜é iÀ±™Ô@#гÈÛW‡GÎt‘øˆ’®>R4éuw¿¿Ï·õ?ÓåøoÕÓy¼¿ÞòËýøtÙnWë/ó¹×Ûô^}ˆ§Ëcþ¸ZžNy:ÏÕ‡oÝÃ|üðv½þÈ/y¼Uõj·«Nùi®ó×áú÷á%¯Ë]ŸîOóéóíýÓ|Ëï ¾¾_sՖ㆔ãå”_¯‡cžãs^mëzWm‡a·ÊãésM]óžÇ§ã÷ôڶ¸¶®c½›sSòü1ç–¹EÌY˜Y™Ù˜ ÙçÜÖÍùŽíwÈæÒ™#rbNÈs‡¼§mܳ½G˜çnýþ@€?Ðàôøýþ@€?ÐàÎìÈôøýþ@€?Ðàôøýþ@€?Ðàú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àú~¡_àWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_áWú~¥_á·šsõ~ƒßè7ø~ƒßè7ø~ƒßè7ø~ƒßè·RŸ~ƒßè7ø~ƒßè7ø~ƒßè7ø~ƒß9þŽñwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßáwú~§ßátF8#ÎHg„3ÂÙ¶ l‘Îù+Ú²rÉæÿ Y,h6¥;ÑÈDt8. Pi|ñ€Fv ¢±+íåK÷ÌèdD†TôÀŒg¥†u€NmÉ-^F ̸>-AÍÄNèÄ…²,²éŽuð¬´aÆ`¥Å‰ALt&8eÁM‹³<—“#artË„F{ÇN‡® tÛáÞ®Lˆvqè”ípvÆv¼øÎ™Kû2ž¥=²æn±•ö=Ûaîzf˜»õ1þûå‹OOgñôË$@;<«) bÏwW<}ynS—~y.®X§G¡ô¥)›Á°ÔÁõë ¨3,uðîÖÙÿdØ@±ÃÿÚ˜«ãÛ4Í›rùPvcìÃç1ÿûKáz¹â®ò÷pר endstream endobj 117 0 obj <> endobj 118 0 obj <> endobj 119 0 obj <> /ExtGState<> /ProcSet[/PDF/Text/ImageC/ImageI/ImageB] >> endobj 1 0 obj <>/Contents 2 0 R>> endobj 6 0 obj <>/Contents 7 0 R>> endobj 11 0 obj <>/Contents 12 0 R>> endobj 16 0 obj <>/Contents 17 0 R>> endobj 21 0 obj <>/Contents 22 0 R>> endobj 26 0 obj <>/Contents 27 0 R>> endobj 31 0 obj <>/Contents 32 0 R>> endobj 36 0 obj <>/Contents 37 0 R>> endobj 41 0 obj <>/Contents 42 0 R>> endobj 46 0 obj <>/Contents 47 0 R>> endobj 51 0 obj <>/Contents 52 0 R>> endobj 56 0 obj <>/Contents 57 0 R>> endobj 68 0 obj <> endobj 61 0 obj <> >> endobj 62 0 obj <> >> endobj 63 0 obj <> >> endobj 64 0 obj <> >> endobj 65 0 obj <> >> endobj 66 0 obj <> >> endobj 67 0 obj <> endobj 120 0 obj <> endobj 121 0 obj < /Creator /Producer /CreationDate(D:20140401143728-04'00')>> endobj xref 0 122 0000000000 65535 f 0000472031 00000 n 0000000019 00000 n 0000003729 00000 n 0000003750 00000 n 0000003927 00000 n 0000472208 00000 n 0000003967 00000 n 0000006952 00000 n 0000006973 00000 n 0000007150 00000 n 0000472371 00000 n 0000007191 00000 n 0000010845 00000 n 0000010867 00000 n 0000011045 00000 n 0000472518 00000 n 0000011086 00000 n 0000014242 00000 n 0000014264 00000 n 0000014442 00000 n 0000472665 00000 n 0000014483 00000 n 0000017946 00000 n 0000017968 00000 n 0000018146 00000 n 0000472812 00000 n 0000018187 00000 n 0000020124 00000 n 0000020146 00000 n 0000020324 00000 n 0000472959 00000 n 0000020365 00000 n 0000024050 00000 n 0000024072 00000 n 0000024250 00000 n 0000473106 00000 n 0000024291 00000 n 0000028006 00000 n 0000028028 00000 n 0000028206 00000 n 0000473278 00000 n 0000028247 00000 n 0000032177 00000 n 0000032199 00000 n 0000032377 00000 n 0000473425 00000 n 0000032418 00000 n 0000036268 00000 n 0000036290 00000 n 0000036468 00000 n 0000473572 00000 n 0000036509 00000 n 0000039759 00000 n 0000039781 00000 n 0000039959 00000 n 0000473737 00000 n 0000040000 00000 n 0000042810 00000 n 0000042832 00000 n 0000043010 00000 n 0000474062 00000 n 0000474227 00000 n 0000474383 00000 n 0000474534 00000 n 0000474684 00000 n 0000474840 00000 n 0000475005 00000 n 0000473884 00000 n 0000043051 00000 n 0000050643 00000 n 0000050665 00000 n 0000050859 00000 n 0000051262 00000 n 0000051520 00000 n 0000059774 00000 n 0000059796 00000 n 0000059991 00000 n 0000060365 00000 n 0000060595 00000 n 0000070081 00000 n 0000070103 00000 n 0000070306 00000 n 0000070884 00000 n 0000071311 00000 n 0000077275 00000 n 0000077297 00000 n 0000077496 00000 n 0000077871 00000 n 0000078110 00000 n 0000148924 00000 n 0000148947 00000 n 0000149139 00000 n 0000150084 00000 n 0000151047 00000 n 0000221250 00000 n 0000221273 00000 n 0000221465 00000 n 0000222410 00000 n 0000223373 00000 n 0000263300 00000 n 0000263324 00000 n 0000263519 00000 n 0000264465 00000 n 0000265434 00000 n 0000265525 00000 n 0000366101 00000 n 0000366126 00000 n 0000366320 00000 n 0000367266 00000 n 0000368234 00000 n 0000368297 00000 n 0000368587 00000 n 0000368763 00000 n 0000469350 00000 n 0000469375 00000 n 0000469569 00000 n 0000470515 00000 n 0000471487 00000 n 0000471629 00000 n 0000475124 00000 n 0000475223 00000 n trailer < ] /DocChecksum /BEFF8769FEC56A5E17071018699F23BD >> startxref 475465 %%EOF cfitsio/docs/quick.pdf0000644000225700000360000070665613246025103014563 0ustar cagordonlhea%PDF-1.4 %Çì¢ 5 0 obj <> stream xœí[Ér7ßú+êX51 bIlGKÖB{ƶD:|pø`“4gbDj¡dË?/Q¨ª»z!Mi"Ã!5¼|™H ^7R¨FòùïÉÅâà¹oί²y‚ç‹× •*4ùÏÉEóà•B£¼ÐÊRsüÛ¢o¬-}ã¤Ö5Ç‹ŸÚ‡ÝR ë] íãN §)Æöð¸ä!W*«û]·4’DÐí³N‰àUtí»±ø?ÜFG‡äI§£ˆ.˜ö¿ÜiisGÆûö-×4.FÓþÂI2¡}SòP¬# elûã#µ^Ç;ÕžŽ™gœ *ÐÏÇ_cêX ¥D´VóÜl z—øyŠIÿˆÚÚ‡¾¤ˆ^KëÚ))¥¢œL¹UˆŠVN»Ø^`V:#Cû}gŒ uÖ¬ª¢Ð^v<¶Ô„…òúRcuP7ž‡SŠôAhCC¨³_t$tÐÆÍMiéMªÛ,!Gè|a•¶X¬JÔËÎ`eœ²XA4§0)ŪKáÈëÛ?yRNïZ]jȵ¤tÔš17 G‚ðäzáT°r.ÅóJâ=dñÐ;µ/y³<‘c马ƦkaI“M+% ¥ª ¯°¤}ŒÃª8 ðŠi5 É.ŽÿþS«ºeÔ(¦19"Iân‘zhFøÐÃë 1D€t )¾$×4±zcò¤³BɨmÝ…HÀû%O;‹‘†6,,aX „i54¦ciË\¶'ÐW™äŠV°W ’4*úH>á8ËÔ'WKZõuŽkÕ=TN¹ zøÈôX,q­O§Mê2ò,5³Œdvõ1CÇ€l=«cN¦E;ÛçbÚ︹Ғh}!ÍÆ…ôÑUÆ…|Ä}YcÚ÷¬&‚<ú iY³™p” í«2õjñÎx,šÏ0Ж2x¬qiï1oSgUËYz·n}B´iB…¿¨L(¯¬öaXY–meeó¢¦ÉTEÌç.`aUû[j%N3¨À>ñ gL!Qki¶ÎÊÕ³‚Þ†Zo—¤œð®Y*&É2KÛ 4óÞÖe,v@yï¡×Ì_Xˆ1&1<¦`ù'ò9sƒ„!J/yÿˆ·ùŠw2™ž\}èèmgÕyð˴Ȩ3¨Áz<ȶD}¡U$­4llW’;+\§î'6ÚZÝ’iV’»ÊwTe̘ªO(WºÎ&Uj$ÙÁìLP¤ Šc›½wÖ–m~‘tRs‚“ÃÄJ4¨+C†l¨p”±AѶêa¯/:¹¹_ØUò¨àRõkH”ÔÐäZïúÎ0‹ C¢êå‹–†±¸¸@âžad«Ã=žÖ’ :Þ çcùVk€Êí¶Ð’)€zÚéö+ì ¸ù¿–ØBc´Ñ 7¿³c†|ýZ©´ãƒŽ?õX¬VÜ#”;šÜv+õ¬» šëùK/9·ºÕ!x~CRäÆz D£Âx|z2€©ñ탎GÖ.Ìp‹Á]1Ž9†dÍîå©ûU‚ÚX¥‚s5•Ë ²£^ÿ_ȸ›†mÕV’¡æ>€¹bU–Ÿ¤¹»æ*Ì™«yæY»ì^gž9õcWzª~‰j²jW©"qká<649œg<ŽÊ9œG´%œ·ÍÁ.F«ô_õ²À¬Ÿ;Z2n-•šÆ×ŒgDGrç¯G> stream xœµ]Y]Çq~'Œü†A^r¯¡9<½w ȃì8¶’ŽÍŒÀ !) ‘j¡læ×§ªz«Þî½C1DΜ­·Z¾úªºõýÕ¾‰«ÿM?ûèñŸÝÕÝö«ßÃw¾$è«ô×ó·W¿¹‡„¾zSÚÊ«›—âÛâÊÛM_Y#6©¯nÞ>úëA¯…nêðõqßœ‘Âëû£›B~:ÊÍh©Íá‡ãõ¾+µ²‡ûã5< ‚V‡Çk ÍHêÏá³›wÊšô¥¯jÛ¡±¯ËmwZ[h(¿òß7ÿ†½ö0Ž-ìA`¯% Àuón~ý×à ´º9/vuxu¼6›Ö:ø¬Üœsêð#ÜvÛÂNåÛÐUé·}w:¥á¢{šï¿ÅXëáþ·åþ»#L‰1ÚCïá£;ÎÅØñõZ|CC×~‚azoáþ½Ò^êšÝs{Ri¼¨\Ø´’éuó…“ìw>Ôú›Üîûüf8|<*º(àMƒCTa‡þð=®œ”ðœå#/}~T®…pøŽ=Yšøˆý0›G.`ÜÎò~ÞI8`­”’fÌ‹m‡ÏýÌ… ø¥Ýú 6¥{wð²õ[ðîðÛ#J‡Ú-ŠÈñÍ Ü÷õQöqú]í–ú—VY WVφÔ³‡<×ì­8×» ×Ëúį¥^:áù8Z/…Îß‘6KH0šµ–¿£ºÎú :µË8º=âÌ9ë@-Q•ÂnW€'Ð…–רïêD”5«¢ÃÕÁ‚hj¾öi!½Ó«¹× <»ÐLœA¤ûÆHX›Ò§¡Ïbw©Ï$Oêâð:ü¾åÝ&A‚K÷KŸžM¹“¸GxßYèìv¼›D¢ÊºðöíY6¨A÷Gåq€êðsÑ›ª_ìë0UFxX˶ ³ šà$eÎj’ÃF[¨ ¨elìiÔbß‹rOc#y—fS2‹{•ž(dn¢º™]nb÷y)P‡¥P*‹]}R%˜=€Káì&Á61MHÖŸ—0Iµ#U´™B½©£bGCRN6½Ê:—'Ô˜¨pyÉvÛ/6Š(|ƒ l•÷úÓ`iÓEíQ_“ì{ç¼ FòXÓ/qÁðƒ!­R¹K©­Þ¬—gdÀï4&hÚ‚—ƒÉýÈ,nj_í’IbÖ_ÍúKüˆ¥þã¯C—;ás9˜ÙûjÄ’5Ð=§ÉwhŽà×^ŽHcoªœ=ÁÕÀ>·V(Š¯Þ¼*æz"¨®>¾‡†`¹WefẂëÝt2ÃZA'­Þã”´j•¥öM‘ÕÒ‘•=Nýníqo%q=’<èàxßìÞ‚º–cˆ<ÏÖ2Êø³º”Lãp>Qp@{ÄÚ3cŸÍ:N¹qŠ»¬„@ ÿ$Bx§Ý7xÝ“ñ\:­L‘ÄÅ3\ ¨¼Fª¥5 5,+6üº6œ~HÓ0ñfð-°wNö®¾™¥Shâ[’I NKØ,’(öæ ¤›¿'ÇŒæ-N«ÖL¤ª!|VŸd¢zÛ’ø&ú}}~"¡·­)Kj¦@%‰#`µz ŸÓôdv Izš tÀ§Lò·&£{ú:58}kŠO0ÛPIV˜=ðG„Mèôýá›c'·ËûOzGù3ZNÀE®AÒÌFO b½È„£¢‚M‹Ïtp¤Öl÷“!ãÓø™_Íà]@3ŠÊq…Ð"€:ÐA\S&üo¸Ñ’ ÑõrÑ@ˆFÞzàÃPÜFÔÃfííȶ¦H I¦±6ß±98)gË2 ÎÞå+¡)¦cTHg¢˜ÇÁuÞц£òt!d+f!bñjgkЇžÂq҇ǺS&±Ž1¸ëÌ$z¡Ù7ªÅJ8¯v¹ÐM·bþø-áa¡aa(©&BúÜ U"ßÃÃýqe+Ç>2˜dxGoȨßl€dÒ°õˆÚ'°^üôºóÄÌÈT„?º^øÀïœÅˆoÃC V ƒN5€}³cºaanÁƒ†¶'}žÒŽlþší,Ó–ì8h.£%—ák °Èg'&\Mè³Ä ¹àgS«‹í³á–™~˜™QAQ~á;E~/@ØMÀ,+±Yšìý79SCRßUZöÔCf˱yÉå–-ç;³å»)‚¥Á?˜:ÇÄ¢¸;ºÿŠi)¸lº¹Êð|Ó}¥läÐDqïjˆÂm¢t,s¸†Àb(ÉÕaÖ÷itË,öŠÌJç,s/å/Õ %)¤\že#mò~ÒEî¶&I¬’’é´+Ê7D#zô©H§ì|.pæñÁ3ÜuN9Ÿ—VR›s‚É#NÑÒ\h¾ŒŒèy= x!0&2 ½5äÝl¯Ò3hk&„'÷bÊÄþ¢,;³[*|A{Ú/d²FƵ4ÆR±²A³Ñ/?oP⻤¢Fµ%Í=Ím“Ðu,§'KK*Åúì; óRáç@†Æ Õáéa ·Ñ!áŒ{‰ïÃ'Sb“Q’y€,'Tß-‚R%™éËÒ €Ò T °•u˜iŸÒ–wÙëÜÁ\Â!¥=H€‰©30°U”ŸKϲhIÏ‘t4ç=;íúÁ8Q é¾&æ§%Kž–D"¬A^WíäÒ’D[{­¥&eœ‚Šú̼PàY¿x?6‡Ñ‰>Ï£•TÛÀ–o–jdŒóŒ%¼[ES¹þŸ½‚–ö^+†ã>‰¹a–Y*r{ÓåÈÈ0›“ ¢}øêHÞF‚ §s&9“ Í]ì¨wŠh" 30ø-Æ3<û=ð…•/ ¯ß,oÄŒ&þw’šl²”qBàxbûò”~tÉ–-8{5rG¯ÝZD©É">ˆ¯ÆðèÎn·ÉŠ8 e¡a¤ÒMè&wr òé4Ÿ?})‡GšÓo4Ñ’çFochˆV¡:“€âMB#bSVpºM«D£Å•sž„$¬ïÁB!zUü˜ o²FU­È[;Q"Ñ úWµ‰w6”9s ˆÌã÷'ñ3}"a“8-8yÑgñs¤™~ÃÑC¹±Î]Ñ ÆåÈIŒD ¦­Àü/¡ ’ Ïi ’¦i¨/¸Ä®IÕanƶåÁÇLPT6GXö—FZ§$½` úŸM”±pë´–Qi‘WSßB‚ ˆÄîE°±£ÂR>é(€]´±§4‘X)4ÆzñAEC×eHûîy¼ÇÓ9yLO¨÷qÕ[·°â€qòñã¬(âþhšÇÛJ ¢ëlʈø<>üÕFZ•TÈ•¦R©®ÛšA‹Ãüë«^X(Ï 踱àö¡3ˆey¾+†„Šç´»”» XÚ€ú‰“. %x*×{Ì ›¢u¡0(“™ïÛeb6qRÔ4›†…`Ýw+Ñ'D ±oɺ g'õ¬©Ìà•Z¾âϢ߂tQÆ2m0VNƒ«Båžé„~ä<ïV²_á×y5^¤20h™1ß}Ñ3­hºÅ $“è™6w2Ä ¦ËÜó˜+›æXÃÏ}uJàüϪ”†„AÇaÔ&&\G“!ªiV×”ÛÊùmEð–{ÝØš×’{λc—GKëû ý6„™¡U¦e¤G'\s7­ûÌê8ÚN˜´¤ÕŸ@•1®1—ñÚhÅ#,sŸ2 µcÜXó·jºÀf–â‡.Ç.¸œÍÒBvTïg¹h#ˆ|G»R‹4c¦g­¯?E#!‚J¦†Ý"‰%ÇTÆå£å«XîÜ¢­¾(ðÒVQßsµ±‹ÜÔG[×qÒ§!NGØ™˜øÂWG,¼<}üÛŠY¾Æ)Þ0·õ5ÖÉ͇YDE¥É ³êÝÔ± Û ¼ÖdUkpŠ\$|—µ=ÖS2£kcJÉåÏ™9¾iJ˜I°¨XòØW$`Áº˜]3€ØâI}éåy3e✈£BqÓ ŸÆ·%Ú¼®:v¼µÊ«jÓXÌ·p©™©Šã µ@¢•ï=næhJ~ÁcèêæšC6§ä RQþ¦TÔ/HXÙ G ±*K“‘Ž›Sx‹´6ó) Ëåµ&[|bb (Ë¢Ž›NúsÕ…&ùý^!Ó>YЄehQë”K@}/®"÷dwHž-MJ¯M¹›¢w+ŸÒçÿ ´~ ë_ žþp”ñL^·ƒ—~ ú9& dS¿96iðîL|8—ÙT.¢AÌÒþ¡„rµoʵíXªsV5¢‰‹\eƤæLr%;jÚ¢Í6 Ú…˜êKj:í¸—éE¢Ž/aN]Ü Ü' °eÅ'Y6‚yƒ³"˜÷Š 3!oö–ÇùjxÀt ÚõU-GöeQ4cßÚmŸµ^#%;ÿÎØ”ÁÂg—„\tÖ€ŽòK% ³Zˆ¾ºOrŒé¶Ù†Õ®öý?«U×ÑZv x÷” ®<È’L{'E †½žb\éø×;31+ˆYÆÀ¹ÚjR—q£é\e™vÛr¹*f™IåýËòÿ4ëLèÙ>&Æ.rÆ›*l$ù†Ôü@.6¢4Ü÷“žòo1©ãí¿¡  •6àO_bÌusœBNåjr7úð?c¬Ê•èÌÑ9”¬1å+{†I Ó–…Ñ€ù9 LÕlj ®˜ÂeƒKÖâ5zÉuÁÖ s… X o g_W^oíX€œ° ¶™Ê?Å"ᤈ DQë¬Á-ßpÃòð¼6[jªò4• z>×SôÑÕP>|éOqw‘’ A¾›D<üŠ;¥ö¤¾H´žž(lU/NT¬°u¬ðžŠ½îU)žÿ»8ß}wîÄîOXG^òÞñù5ZÄJd` ¬¬Ús¢ÉõÛ?X\‡²ÁŽ*hY[0ùžC›kŒi³Å -PYÔ™•êŠV0®(àh¥îª)^ätÝaµ0K?/›mµ™ÑÛTÛ²]qÕî?…nË»_gûï#Î*§ºý;4„©ÿU7¡ÿå˜w¦ã xփ‚p³{šµ†厛TÓ|tótäY| ÏdyÁGÇGi;>:&ªŒO½­í}[.²ýø?åÛ)ÏŽøá8Ù>ÿ®\¬»ôg;éKÄÛ‘KÍÙxÄ]ä`¯%(D§½6¢ðñ¬^RGc&F!2öбM‰1t'Æ6-ÅY±qßDP¿\_z%ML¼5Å7øeŒ }ý1)Ÿu åËô×,C¼ª‹Å™á”òAóœÕë öµt1þËÉ8Mç…¨ˆÎ齨Y¶Q2"ź´—fÛŠË‘"ìbü3 É Àì˜YSµÝ™òßì”c»ðÄÄv^Þ­ Ρ"`x#WŠæÍ¥-a°2l»š‰vÝ¢ÂP ÞZjЉÄØ_]haˆ†Ñ25zwl*í¹¡m´ã’Lg)AfŽò´ï€ÔL?}•[hw²‹MÅD“Ô{Ÿ çœ.çÌÅ©²ž\K_Âè.ýÇ>µÚÀ‡9€}g@ƒÝ.Móó%:eF¢‡!]zožª‹zñkÉ™œ³øžñ­LÏô£«ÆCO¤âؼ&ùÒŽ */W‹ƒÃBnk‡KJÂÌ¥üî¸Dç92 „É©–2™¦Å™FuIÏœ±ñ®ð¹,'2EÏçE]m,Éý.…cjZ;|)Àï§‹o½¸¯º5œ6ÕÒ=ïlq[G÷Œçw²SX±éö‰lùÅi¤LRÄ):—&ŒåÊçèA˜;¯ u®½£cr–[b‰…N: ‰­¼=n78yDŒ p^]?Q‡\ù̉66–zÙ;ŠÍʾR©¥ØÒníOteTN-}?×Ñ<å SÍãÇÖÈ$á/„Qg:º2‹ØlkCm9ý&Ïý%Aiþb®uá‰ðv K)&Õ=¤™Ñãs9©0ºw×ÝÙ0-§ÖŸOÀ²Kñ6±næÁöò"²?yºÝ·Þ¥8îKçÏÃ4}r;vL« Œ½ s¾f°y]MÓ,C8!ŒïŸÊlüÞå]Þ"ßhó-CðŸFëwò¬Ï¨ 1#ÔÒDÇ…Šm†m³0(Ú6Û­šó`'a}2Ý4ÒÖtg;,g'äôÑ%»òîpaÖ"mãA¿Ÿå¸I,äìS9:@”'ŽÓž–ÛÕºŠš…dô8¿wDh¶ƒíÏ’œÁ G1a¥l%¸ÀE9‘Rò(GYÊOY’–©€ÿ3Ùr:úßMN[¢ƒ´¯ÈS¯ZsÞZûž¼®¥üm9˰ gñç d›–RŸ*.FÓ›TbÜg†„ ۴̸ۇ€)1±Ê·åé©4t.j'élO‡ËûÙ»sŸØÆ©^Mršýö­”Ѩ‡üu±ËYb爛[܈YÜ&êÿQ íª§6®(V‹Ô&Là"õÀÄ:¹«\ªOtõïný þý?5·2‰endstream endobj 28 0 obj 5961 endobj 34 0 obj <> stream xœ­[YoÇ~'ô#ø¦À;ìû0à‰ã$±hm )S„$.mŠ’üïSÕguOÏîZ¤ Ë«žž>êüê˜_NÙÌOþ›þñîäì;{zuwÂNÿÿ]ürÂÄÓô¿‹w§>‡I\r5KeÄéùÏ'ñm~ê̬Næ³P§çïN~؈i˹°3—›o'6[-¸S››i+à]¡üæF•°Þ›ÍûIÌõæÅ$gnç›·ð‹qÁUúÅ…ß\—_d«i+˜-ãämòüž[7[e7ßãû’9“6w¯ËFé%nTXÔÂ-¥Ü|=q¸„ƒ•þ ƒ³ãZ:z¥ó0jŒ’›çu2áŸð“9nœ?ÿ)耦³gž#l£½;=vrþ‡`9[k Là/¹ùuÚâQ Spî-Ÿµ¶FÑ`[gß|'0lróÛ$Ã;|³›ôæƵ•¡¯½ž¶zVÊ0“çà_•×@ç´RL¨?óãÝ$íìá›xcë8“H²¼Zy–ãN?tX ¡L:±š¾®Ë¾‚çÊÎÚ  4® Á ¾Å£K™”ŽÏŸ×âøG¥áà!èñš?#gðœOa`AàçÇIøY0š¨¬¼gÒnÖF‡'7u3¼2ó—!x5)x.¤‚—๛A/àT( Œ37¨Dç— 4?ãÆ8Y“—>M[`®4óïbŒävs·¶Ü%ò{­Êé­Z’QJžÈèP⟧ë(•—ŠWÓÌ'ÄEëòu,RÒ r„ç†)QTx°…e¥dÌáÅ·ùæ[.ÐLD\UF ¸“ë:Ät:ð%1TyKçïâ|ØÞðDE: ¬YTfbó2‘EXXt±.‰ëÀýµŠB’X˼ƒÍÀîiÅ$’úë¶å˼ê,€ÿ5ÇÌüÇÕÉQˆ¬Z ÷E™7çծЦ×@k3Á$ü¼BDœl‡ïá_+ƒ5pÁln>ñÄ;< ‚-,Àd¹®·Ñt¶Øjp+‚9ªæ¶)•Höþs4Y¦å1½jéÛ­‹"(áåü­rÔ_DŸÈ[HD *\@¥•±¶W„JD"Â¯× 4ç ãTv8¨€}8À=¥As«àûG¬å®UHT.ð]Æ¢X£’‘ Boƒ-Ýlî¦æòs ¬7¨¤ˆ6Å3lJan:°dÔ˜"+˜Ö ™x)xP\üëâŽø ¹cKÑF‰2à‚%Ïf¡gìMkp@iÅ©2)„ä`j²>_YD9o¤ùŠäTi»©Ï¦01{ŸgØzÕ£Ïëd:OàšƒQPFáA¹¦7J¢&,¯Ç&LŠV=ܲµé/ZBáeø<êV!Eã±QT)6IUDb‰h`ÌV8¸ ó¨ØS¸‰äCwK¦’³Ìþ‚¸gáêB¸ãÍ„*‚¸lèõD0;”eUÆ{Pšè¢¢}Ñø‹%é"‰¤×žÞ ÆT€$ׄfðTlPÞï&|ïˆÁ_õ^×­ä'¥”p³¤ÈƒX«:ˆk½)÷Uœ¢A¢ Ñ/²hF#=1±JÙX€SŠ*<*D‘ÎæêNŠh°ã%·A±—; *q²Ft#<Ñ' êe ˆS”‚ b-¸àkÊ hE€’ÍÍ8J‹ÌžðW¥ÐwfÈj²Æ-Õ¸tÈ¥—BªýïFÑU´òÄÆc€‚£džJiERI@E#ï §-ÝœT)ÖÄQQ¸ýÌTîû†ìRˆù "‚_«ÍÌÐŽ"ŽûjI Ò NnW”Æ £^"+} ܂٭T}Yì|bi–ñl„Uð^’úpûÖª/ ¦VnÝ`¶ó*Æõ:FOØzaDQ§>Æ@Ïš‘ݯ!6°j›Œ›FpK­(ÓPÞ´®‡ÈVgÛK|Ò¸÷‹ÃåñBQ#”ÊÐÅAq¹÷ž<ŸœŠAήZÉ—u…ûê—öç½G_³Î¨äÌ¿®ˆÑ%8÷¾ |þ¼nI&Ö!šØ¿—C_ÙÅí¿áiA'¤/h Ý»Ù|?qpΘùXŒOùµ#ŒÚãæ­}¥j |Aký¿¼"±5׺;=MXLÚ5cYÖ]²Uzö¢¤H’§³7ÅS¾Â-D0ÔÄ{#‹æìrèÉh…D‹ô”®ò[Ö™/ë‘d'ƒL}2ìâ±³S}fØ5ôÏ9Ç%×äšbÄ0‘úôx túuô¢üz÷ìý÷éRŠê²ÝQŒLrl€–>Ö@yÍÈÂ~lˆ-}4‰BBÌ«]³O$‹[Ë`ÁÕÐI7ɶ%„­Kî<:Dâí2µ³“~™vÀËhÔ¡<º =$¹ñÑÇéYxјÃz–™E*ø&4‰. ljr[%c64%»öD“]N+f]¶J{@8˜¦‘tuoOêsêÿžâQl@8t¹jÄ×Ðn´ã7s¦óƒ:Hwoï˺O¨ËÓ]t–p&X¨í»ÿ¤HbQA„Uœ5ß\Ä¿mÉÚLǃ#lÞæ}J ò™UÕ:™¼Çi‘¤uqÅ©Ð4JC…ßí<Ä$H] {Ò•¨ná)øvzí;𵈠HÞôØØ VöŽ rƼšI»žŒ„‹e”w?õ ‰–þDDh—t ™–eÙ˜Ç_/ˆbm3€©¦1<þg0´„”õ„¸‘ÁL„oŠ;×5" %]Ì:¯èGÄb-2Þ}ŽˆfÅš}²H(å<¹¿dÆS‰s˜Æ!õÚm¥]–Ïo“‡K˜Œ "=¸ÓeÕ™bµmº~‹ÿuòX–Q¶I8 Z¤¦µKÛÝŠíõÅ/H& GŠèQ*ãc<!¶àÀ·Wi…%HûT~}EqT¼a8D8…€ÕË.ýñÅŠ?>Ò “]Ë .ƒ€Ž“ð) Ü%æt†çJW×<ÖÜ(gpTÌ3Ȉ>/Z(dºÝÂàÒy7iy¡DÈù¬¹ZÁu(‹=Fwˆà"d‡FN$Ú,1“UÏL z5'ÃÚÜ.2›+‰ŠÄ\Õ8éB§³*6#™§n·Í¶h9Éà´æ®¿ÈÃÀf©+ÃÏVtVk:ñlOêóõÜmÕ‘adÜé]8U!ÝO«õž æ%Å8ñ€à€{jo‰¦&¡ÆÛwÌê”­eVj™8£z—9¦DW¹+3ÎVR¿‘¨ÀGaÕ~rÒ”3tØ¢ÖÕ7P‰Æ¯¥˜1rUÍY°¾õ¤dA‚[›GaÉjQã&C¡r5-äN­6wl…£Ù˜¦¨ÎQ }x$K‹eI‘/ÏdÙvo[éd¢¥ÖÊŠqkLîŽÐTávS)Ô]º&-4­<Ë“ì-Æu…d}Øcf÷ÅaÒ‰ás~ïpÕã_øpÉŠåi-±;«Ý‚Æ…‘ºRÉ$»E0ÙñŸX¹}ý&¡½È…‚%Q¡V³¬âñÜ#†£ 'ÃzADô ÇÂɳxÆR í!bœ‘k¼(UÔ“V3›k“·$ˆ[Î¥0ûrhÎKKf-æø-@ àrDZH ø9%9„O}2àÅMí[2›ÍáѾCƒ“çhŒWWå­ax*c0 :ã“MˆHû`EP€=y=ÐBÒ›»ð´©4¥Yˆ©‡B*]­4çâ­-Rš6 ,2.X÷ï0ºqžY8Ô7•èš‘ºHK’ó©\íA¬O+©ÑR¾€€+ë‚Å{x8o#´œ®g‡ÓÄ×ß¼ôQMf9ßTKØ &\'Ù]óÀ¨q˜-j«˜XbìqZÆñϵàu\ÏšN™¢pÁ¶—†$ŠJ›G‹i²$þgò¥î["Á#Øù™U÷Qô 2©,@yL›)’Gh¹s‡ôÐPG2ÂÁ èz÷VÎù>†±W2ÆBï& ††[³²-ž |=ó>»$$‚ñrP·Ì»Ÿ‡þ;§4êòWJ¨PR^ú¢$4æ%‰*4<˜dÕB˜²±Â7ƒAÏàöNÕ¾µHãâP¨Æãîy¢Ò¤vÝÝ‹þJÛw /Û%lø?šZv†6¿&çF;èIÐ| ,«¶žÇìæÊå9]·âÐ#‹Üð |¶e<äV[Ê䬣¯-¨!ŠÀŨñ.v÷Ô_h5Ï_-OÄH\’à’¨zäž4^.MälÛ  Y„E®QùROø0fZkˆWÌÏF»aÕ:Bˆ‹ÊØ8gšCì´UTϸéLsîͳ«Ò©õ"MœØM‘>þÿ^¿ýXûø§íΫD–G¹êË¢èEV£=Ø'¤|¨Ì,{³¢bþç ¥òg*››$8žÎw=bw“ŠIÃC] Ç%ã7Q sPKÁ&UW‘3 ò· Å)`^ËòßîGV¥{·i’L»¡H¥‡‹ðbØ-ÎzVŸÍSéÞ¨Ïß6ï¦Áa!…t6ÔJÉ5==ìN¯þîÀî7eð®¾J‹Åð¥;ºýòmJ½GmÙÛ¡²†üwò,{€€nLkIò·PˆÝ™ (€˜’]„ÛbNÇ«l7 0µ[=‡¼0æÝëÆ‚h¿éÊ20?‡Ëy ïHî #—±bX3*c_ ­4ª÷ÓÁ©‰j‘²P÷ªÕ~}ž””tëÇtæ¶Þ º.êÅž&7 ê–>V’(‰ ˜ûò™o­¦¾`Ž SÆfù(~MÌ?ùTËÇJòÄáú’/?¿^®ŸB_àL_&&ŸœÍþ‘±sãÔñ}­CŸW¶KY#£ŽÏ™r,Àž¶<§}ïCÆÏú:¨–"]Œ)Ià¶ ÷¹Çq>´¨(\‹ûrÇÍ0ý Õ÷ _º¬m@ùƒoE*-75€Ý+;ÈH„TÆAÿ>$(x…Æ/ØpH(?W}²Ü ö;L—ïç½Úÿ…&ãÖÕtÿí`FiÌÞá m$ˆ'uþ…Æ‚®[°8bâƒqÙ‘Cq~ÖèPØ¢¼™Qfjø~ÃO0í^Ù•"&MUvãg[#ÙÍ ô£¿¨z ß¢ÍB˜7¼Ä%Gö…/¦ýÀ‰¨@µÞ£ºÖm“›c ‹šd|P̰£\Äîåm£‡`Q†"Ø—Œ¹Œàþ›ó“ÿÿhø³hendstream endobj 35 0 obj 4366 endobj 39 0 obj <> stream xœí[ioÇÍç…ÄBAŒYY;š¾g,Ç€u$V ù &)’)R<¤0Fþ{ªúªê™¢äƒc„ší髪_½ªî®y·ìZ±ìð¿øïÖáâþn¹{ºè–…ÿï.Þ-„¯°Œÿl.n@%¡—B·J[¹Üx½­Å²·­^Z#Z©—‡‹—Z­…®ªy²’P¿sCóÏÕTÊôC³¹R­pý šÃU×ZÛ»Á5Ç«5Ö•zhà}] ÍÎj­zѺN7ßA¯m'µvÍ öe¬ÔÊ6G0BçŒÍ®ÒÚ¦÷Jön<ô4 Í)žóbMY²,ÊZNë]` Hµš.kAÏÛILšÜ‘üæ¶Œ‰¦@®†T¬÷]âøµžhÌ=‚q5Œ~L¶; ÈÌ׳tå#ùƒLé§™½r”4™âWË­]g þû¾+oA†÷£|É)À–{êóü0RŽÁÙé¸&g i'⯠+ï/h}wj¢ æÊÜ|X3ƒÓššix¶ÅÝá5ÙÎr†ùê;H³ Áº‘Õsm×y9••Ù׫š€'\UUýT[5ßíz÷ÈÒ 5'«ëmÖ Ïk Qb—‚ºrI]¡$yØêÔ@=®}ñgŽ*’w˜9‰úý ˜*þ~\>Þü x|ô–Îø3átåP¿Å-®K€£¾ù±’¢µ}¸ÞFf*îþð–š]á0àµñ’iîÞW íß³»¦Ø«6=»}¡ë¤,Ä'µ[$*©1j›Üûëᨠü„‡D>Àã=±ËªxA&Ò©½sޮ᫼”ÚÎ…QÚ¸y"N i‘!湸©O%³×̲÷ikG{tø-–&Ùü˜e?á®"›Ÿñ=›+*ŒvÛå˜Et$™fÜOÖ3ðn±$Ï`z´ig)±ƒ…PÈÍT`Ÿ ”}ÕB õ\Ȥ¯gÍrÿ¿V=­/ÙÚ™€š¹mH|]ûHã:Á‹Ò½^f=ç8ü¼M&Re~êÄüØlÊòY<¸ë ŠÓ&;§ÀÌk'Z H&ñ}œ€(‘¤¬öÛf ³9¢È©PûŠ~ö*'0“¥º”‡£p%Šç–Ðï¥*‰ÒF0´ð siÅ#…îר¨r ðÕJ^aâ†&z#üʃG˜£ï¿0ÂÔþë¢kîrâÁ_ýÃ-·"{ö¶#GƒÜ§EŒëß0à?j`ûÉ[ÜÔê»î²+]½ûÑø}£.D4bÃ1´äŸKÑWé“*|u–Ï ÙmxÐr&“ôFä÷;…#:ˆð‚rãRŒ77ϧJÚDxÈþ¥/8'ãÈ'Þbt|Q;kIŸäØÑÉê\zÙF×c–¹=ŒEZØ$ʬòâ››èʤ/Ê€;$S^þEû<‹õWˆ¥Ïñä9IÅÒclåÏþ‹(ƒðưœqIhgá}úÞNÍ7+É£}ô%£hŸw•ž0¬ƒìªÑT¹K(ÉxH4@Tq8~T!/½$å¿–ú~ñO1¿2endstream endobj 40 0 obj 3707 endobj 44 0 obj <> stream xœÅ\YsÇ‘Þg¬Þ4³ÁtÝUáK–-:VÞ•{7BVÄ‚* (êð¯ßÌ:³ª²g ò†Cf£§»Î<¾ü2«¿;]öâtÁÿå/ßœœ}éN¯ß,§„ÿ®O¾;ñÓüÏå›ÓÏá!ááÎ>,Aœžs’Þ§B¨½Õ§Öˆ½Ô§çoN¾Úüv»“Úì¥r›ek6ÏàO ¿ªÍüõv»3{­u0›+øAÙ½¶ðC¼ Þnî¶;å÷ÚH»¹…ÇßmwboŒ³róíVîsjóýVí½·R´[?l\yå7¯°s¿7p“¼›^q*¡ýõ¾æ¾¨àù­½‡×||ú¦tBÆ^”ƒ^Ȱú™•ËúóåVÃ-©ô0„Wõ>Ž:6F–•’Úáò´Gî·;½WJI/q¡îqDf¯´Š~ƒ/ã[Ýâ/oà—½µÎê: kLJî·_ŸÿéDzhaÁ>¿‚}mcÞCßvXêÍ9쬼zó:ÍZ:ÑZö¹e+—0pÕ–ÿzß^,»`Ű yºNؼ¤Á¤•|Ù^¾©?þßlÕ²W"øÒ~ ÎxW¦¼Q|šy'?neØËEã.¨.–üçínåÖ9l[YØF­qlE˜aDJš(^œÄî®÷z÷Q(„”Y<ðê »†AfÚfÝÂM”ëUX‘ŠO:˜‘éG^E¡ÂÆaËnÛ–à›8;P`XÑA¥Ê*·Fžá£Ìç;éõd­µÔ]opð [{¼â+-£|›ÄÞ¡äT±/¿Ã~^³Æ¡.bçzû·ÃáÃä××M ³–+Ð[-CÞEt ¡¯{“ôûmÚT­Q‡·­é»¦DìYÏóŒ²nIµð5µwEİc ¨°öäN åü“dÄ¢6€G³ÆlžãÞxàÑóöû‹Ô€],}à?±-ð°jƒµ#Û×ö”ӫκ*¹€ÌhÐ`ìØ…@”ì¦]@§”Y±Î‡˜Ï»¶°õm0jé–aYå`@²Í¸¼°Z±ƒlo“ŸÖZ0{A>­Îuê-T¶(úÁímü·[ ¢—jÞ” v–d”1VQ[ÐS€;– ¶¼§hoâ-Ö[oþ·Þdîͬ*íF'¯ê»Iâ„{k?™ñ¦âø×û&¯äéàî¢édK©ƒ#ªÃ6Aöß.š< vÒ€“E¢žL*I,8N´O;XCMeû½Ü‚;ÔÆºØ(ZŽOšˆ%uð{Ò¿ —w,þþ¢uœÔ{… ª½ƒ1þÝé°ô¦œü|lÂã^c7ïpT&j:«0¥K#ú­N à÷¾(À!”¢úSvÚ«ŠÈ$€Ž ´4J—õ¼õ'à –„4Reö¢~mÂd™{H“'‚‚ MdÓÎï 1ƒ:&#š…Rûd‘‰!Äuú;Aàåi\&“<'1a`ÜÅ‹ÈÈÛé2­¶¤'  3è"jm .zý3v· u€4!¢^-&AK?Kgaz;meô «2þ§úhô×ÐǃŽÒËÅÖPZlrÚ®~n“o÷8¯4OÂÜØ> Íx)Èhä †7²Ç õ°»‰à¤ß5ᚃÀËp1‡„«.úAŠ£-0QD$.¶-t‚çÙX®]‘x¥ðfh/‹Q£vÌDKšëhdЬYïø’£QÁOSL‡o±Aë@æþ{ -ª¨_¥Ñ l»Ývx®3¹y¡ÀfEÓºÇÆÕŒUÇ[BEmV¡u™ð£éÇütµÔb´Ô‚iÑ`f§‡¹Jw•2ɘŒ‰Œf•ÑMè#óÎ…œLÕš\$NR0ŠSÜÄŠâ€<ï³p*.R ">“’¬—N4@ŒŒEG½E7 z <¿0TsTHúøK¬D„0p¹j%2J㧬—d+VÒ’$î7Œc!?¿íMM¯[ñ!;°·8ìELlr@·èŽó½, v•WܨnqõâãØ®)O4Êbn4bK£²Ä}W2Ð4Af5c?väî¯ð@}ëfŸU>Á(+]„Q 5bÅ’äFW”>5E)0ˆTg´ ²ò¥w–IR)ˆÒqÆ3ü@î(ñß6E˜q(g_Ê@gÎ`üÚjí¢ÕU‘ŒC›¯p4ÔËnD½ùu½™ZíÓq)DË­þmKs5Æ'tK¨4 àáôÀ¯|"'Vä9Í–òõ· /£ãä–Œh5Ù &³€Ñ+dNáÐqȈøøæ³­Àµ‚8â÷0*$Þfö‰âzË9Š‘!îîYÉ’Ù9´Kãõ=Újï&s û+ýà}HøUâCcÑ&â43RÈHô»£M˰Š0KŽÓ‰¯ñG{ׯ;1žLу‹R/H΄peÃ$Àqd§{¬#+‚'ö| ¬‹¼A=æKJwÇURŽ}÷Ï邞lÇœ$(ó:JÉw>"!,ÑxùŽá;º†¦qA¥ ŠH8” •žI½%öG‚¬A€TSÈÍ­\Y2‘QŸme·o…‚™[‡å͘.Œ½èg…­€`ŸlíKÖ•7Æxí¨M^ *÷7ä7çÐôv JÀ%f†mì¹,~}›ÝEµO½–Èó6AFé%x>s/Äep-åïܾOþûd³y“^„s62eÀþ°…=tÞT“)ÃÅ‹#²°‚Yµ~V%Üœ0K|a¿g4˜½f„ c|Ó<ä·íò&]ê\’ïîÛ%yíûöì»v—xÞ¥]v½¶*&kzšß`Xz!ó2šøcA_¹ åL†+¢õ~étôÌ«€Ç!D½AöEcÑC'ýRŸÅ‰ÛM£°šlfÆ8ý^æ›ýVæ›ýNæ›ï8%ˆ ¬möh‚ úÈm\6¡ÅÍ1g?ë…‚b &–(qЉÅï@ä›ÄDÃÄ;4RZ—á©ñ[ˆf²šú"P]x‹¥c=R_·P% µèè ç5ÌP†“;†ßYó»´§qí’¤ œ‘_Q¨H}Zü+wóÏíæy½ùâb ,WâQIô2êóAÉXóÐ?Æ ±Xˆ=·“¯ô[ˆt•!pIJ¯‰.Ö„€]T £>mkþ?Ýò#O6åwíòónÿ „Áâÿßb꺂Eÿ¨{ \þµµKîþyê/_´g?:¸óHi ž€C.´Ô,•¢ÉL{~•µÒv¥×IÆÁD2HÎÉ¢’`¸ ÈJµ‡B%(€þv(wÌÉ„ñ\&ÌP.Š(u#gD8Û¼¿Ô^¹ÚºŸðÁ%º±>j™€â=ólôq& gûò<ÞdâsDE„×Êa[lä@8Kx%¸—R¡"—ÂÕé‘Ý<0a,z½‡ÜÔêœHØÀ¥xÊtár%ؘå—o,¡á#“xÌÅ^¬¶ ‘3*j\WŨ  Geý``PÖêÑìL)0v¬¬ÕϹfôhy²Ÿ¬!–½´5¬‘òXUYØD²‚dh„_ÌA $ÝÕJ3¦ªhFS—"4‡ž?_|”‘Ÿ¨Ñ6lddê³_·gkí@cÈÁàŸÿÇÉù¿}>Hv~¼TÕä@N»Ã–:y=Q‰%lú“§)±Ô.UT :vI;ùU6÷”ÝN|¦±]Ø'Ú y›©—¬kÆ”µ’nxï†l½ñ"ºÂÈìŒÁ-· úXq*IfŒÁÓXè'p øêƒ‹œƒ©3ð¥¢;}^«4§¥ö h-à$õ“ÕD+躤|_sPrë~¹¬±`¡†·„EíÆ@’_®¼Ž]'ߊ]eyË9VnÉú„ˆ[Ò¢4?\=žœ,á¡­?ºŽò’·²¸¨=©G¨ó=èõ#¤3!ŠÓùÖƒ\-¦‹a¹Ò…¬LfF–ØÊLþ¯OàŸç¿?ý—“OŸŸ~±z o¨Ë>½`uâ*éÓ¾78BÔy¬DVÑÐ'*ãeúú¨I¬_}Ô.VjÐQ¿ÆÁ¡Šqƒ/¤\ O%Á%KH£=þ ‡Ù1“$ògWJjóOY)<™ºéö7ó¶ þ‡zó¾ÝlÙÍfäÑýfäíÞO[Ÿ†yÕÆþžª# Žäϟ渑BC⎅¾ÜÑ7¦—„Ē?•«jòo þÈ)3—å-nïõP”cú¢¾J¯â6N`"Îô ð8{f‚Œ‚ˆG¼ü¯h¬ŒBÒÉ$÷…íX,Z¶*éiüë£Î¥æ~ÝQK0Ktȯ8m¼çôöþ˜G‰| 1¯9̵±˜D9»’JÔY‘ÎÆF/bû«äÅJeÒ„Æ&´KŠd€õ ¾œã¥Lä/Z“ñ¸fªìòçthÞ»1*õã ¨Ž”Jg0ë/$Žë“ëæ‰dF{lc{ë2'w­í‰ R‰,k¶XžÝ³ýË’8̨ˆgáZ JÎ÷DúÅÚ8Ò£ûÙÄHb–| ©´ˆŒ¬r|8rQ„Y‰âò¸ü[¶`¬{ñ`ö.gçQB.kýˆ8‘H~_:Ϩ§ÒÉv`ëw8—Ñíä0RCª,­Õž™:ü%E’é·<È'aìö¢ÐáòˆÝ˜ƒx<¶‹uQµ¶þC+P‹£5‘XJÇ2³Ý4¼¯Þyˆ1>†¤Ldé›´íÈßÄ2¤@¬IÄŸ¤v¤¥«™´º¼ÜÖü,›Ã¥Ñv¥:V)×S:tw½qx=ÐÉ(díŠlè¿—U<ƒ†ñ¿Õ Ssï¦â…VØVaÏuŸé ûÒts?¸/÷‹ítd¶™«€o“ÌÈþüåYO¢eÈ–ã’z²ÒöÙvúGwZ䄤óEÌ'°Ñ3ì4x+º ãîÔ+›ˆ=‹túÓXø•]­b¿/áG—™¬ÙV¬ ö ®ãk†# Ò£uÁ¥b£µO‰Ì¾È¡á¡¾˜ª]c¦mGè °©-ûp°+6AÉλWõ»NIé]^Çž•Ê‹EÆ`´?bÉpM>·**àcŠ3ñ,k+¿pÜ!ÙòŽÖl²´l¡Í­“¨ù‡@ “ÄÛôÒ"V¨¯k–÷öõt~iŒ¼=ÇïqilÏ1Õ:;Ž¿#º‰~Ô Éh—ãÙ÷ólËC#U_àÄSQõaRµúuj%ë»"tðÖ Ïõ*þ«ŸúÔmšboùgŸþrúRˆÙ aE™•¦~A–ês¤µ Fc摲]ê)JÜ›DýÈ7JˆŒ—ÏA™ð§>̈grÓsìÂ¤Ä ˜ôõwYŠÊ2rGz§ã¥(ïø -‡8é”Û¯«B u›¿{0´]¦¬>åmË.Ò¬—t–`>Ìö#þna³ÍFÀ€–´µÒbÞµn§Áˆ‚°bOµ&}Ë÷ò@ÐõdsZš$†ûœÙË£…ymÖÏìÖ¡‹mkÖ¬D/x•-i#AÄ·{u?\3´@CV3Ťj(ma&æÖ¿òTá­X«à3¯¹€âØ—¡HÇ݉Zn¹š=[õ_#{FúO…­ÂÈÄO­0õÈ)ˆ±Àúh95™ë¾8+·ùЇÅ-–úõXs)ߪ{|ÓÕXijßf¹0IþV)ÙÎÅiâ½ðˆ2~¼Ì¹Ñ¨õ\@üˆ3îÓçó cZô Dp®ûaN'ÓH–w¿6“?rr¬X3ÖÆ-œ'ªG¨ù £¡ß?I_­ˆAmœ3St'; žv•€+\æ\¦Ê²°}u§¤ì-êT a˜®µ-“–†¢— (]¬Ñ1@§É·m¢<\ÂEQéÌCŽê9”ýPÌŽ­ð H«zâ j]J5ÿé§ +§Ã½QâMW3uOÃoè  &¦ÈXaÞH)´žóš‚Û|H§¸ÄÞ8Ü%Æöª-Æ.±bÖ²ÏÚ±,\­d8hÅcõV˜TÂ5ÛöÃa\>¥¯dÄGÍtß±ÝÖYùþEfM¹ïªa¢Åƒï†øå+q,ôìì]æ!Y›ÙÈá4î.EÚdÙ]´÷„_VøÈ «•åyÝ«y^ÝaèDoò£e\:G>Öó’3‚ã„¶|xUJ¾^èfÆî£Ÿ‚A æÃbjˤ.v®Í&ß8–¬j$›¬-~ËHõæÐ¦­Ú«dš’‘ù}¬Y¾cfK0MíJP#G‡ÍNd,*Ð|Å_9 ¯BðÐ’Z'Ö`—2Ÿð'‘é‡|ÂjJQ 2&/©ž O¾ LçÐ~Õ%Ž,_JVç§m-3=°Ÿ„aHçÀ«nýîgB¸¸ÇKz×dÞWN‰ÉKœm@> stream xœí\YoÇÎ3á±ðÓ¬áMßÓ>d[_ à š”)#"%Q¢Ÿª>«{jvI“²Ä ,­æè®î®ã«k^n¦Ql&üúûôâèÁWnsþêhÚ| ÿ½<áMúëôbóþ1<$ôFèQi+7Ç?Å·Åf¶£ÞX#F©7ÇGß z»BºQ¨áƒ­€¿œÕÃGÛga¥m§Ñ5)3‡«Öj5|½ÝI[jŸbÖÃçð€u£7zøj+Gk''‡çðkrZÛá:¾$`‚×pÑÀëføi«ÆIH¡‡Ëzû ^´Ö¯`p-ÐæßÇÇEͰÌÑO^à¢$¬ÏøysüéÑñ;ßEúÜ,&5<Ýį̂µö8s ÆÚéi™‡Ó­r£6ÆÐO¶fxÿi' $Âbg+P£ášr¸‚!$)çᬾXïÃ'p¦ /Ji/+-?©ó¨ìzóv 6­Nþ”Î÷e¸{e-ž’]ƽD®NwÃy/à8ñ—³ œ½˜\Ú­pÿë:G|þ§Âiz?J©éžÃt×õùH¨Sª¡¡Ý©tÝ|I^é6ÿ5<,+dÚ<|¯çE™²oFZYBÁ FkŸ3ÂÒQ8+“À3ƒ»‰0“‡ÁEäA§_GO拉;a‡qÓµV³ »@î\àVÍ#È8­Î‰9œÌa¬¡'‡ƒ2Ë›¸®]ZØ.¼6ɸ¾ÊTø.*ýœ w`Ç@ðq%8ª™ÌðÛv7ÁiJë\^é‚ÿ”BjDäGD…AžGÑh7§ãíx‚™m 7$rȱ„9ê@¨Z2iàÁ$Ò¨€I¼6~x«Ž÷,ÏÓ°ZÞÒ1ÝMÊ4¢íd‚F”~´ª* šØÝéÞ°¦YˆAåk†…4]á^Ke…¦?ŸÇ÷¥rxU95Z‰j^›”D&„A½p7ô­Æ /éi’ ’ÒPÈM(£ÐÞ¢Â@R,Ü¿D… zv8/ïÄUIß¨Ä vnyU?)Èá(ž0¾÷p:AuÁsÓ4‡3Æ[ ' *$a‚•ÿÄ… ïªpøqœ«òð÷åá'åÆUz.OuUžy<Ô«•«êÅOËEÜk£F?»árñU}òu¹xU/>)OêÅ‹rñ]X3ÈäOåÂe3žþA7àu½Â]¼æ({¼ÍWñlPt‰yºÛYœ—³(›ßí{¡&=r’~í§x(W U—tÅù,î¸7áæ0Òi¹ÿ”é*ï =ÿ'S‘óÿž#¤2ůÜíö¸ðŒÂ<똸YcXpÊíOëçæÈÈiý”cÁ™ät~¬WŸ•‹kDjkÀ Y²}?s›B¶¯ÒOØ ¡)Ëñ¶Üç ™c#¼ßì$hè ^Ñn-‘",‡,œ,°|%ÀƒÀÙ,¸-ç…N</,]Ån°SÆ×ˆ4£'ýCeìz‘pö9.Zõ;[èæªnðñë:~#v…¡’/ gT€²!ôɱ.Éy·ñD%Ì(~‡€ªØï&~@Hš¨+!䛉¼’&X†2Aç@%¥~§ÈqØ>k—ÂÙZ12äªp*9uŽOwR¸#ˆÈ,Ež°x ‘FoQ‘•.¬ZÚ¾—B‰ÉI_7™V20ÔuÊ„Þ>þº 3.”çóY˜‰ïÜHp±…é€òf.]”ÆÚô)â€UžôÀÈ™ÙL±,™â`£í,RòÖaÂ&gqñ€BOÆÁ® ,¬.'„a/R–X:]ó½jŽø„"F!x–'9äWXjj fdÁ¢MÀ^)­‚Ù+^çáÉfgÓÜ þ„ž2öJÖÙ‘LgHh]&PS«ò@Â,äE_” ÙeÉš•×âÃÏÊ#˜Ó³+©ÓEöª"_Ø'kB 5dØ5wö÷ú‹ùè;¦;Iº¯Yüq]rc^Ð’ââÄzÌÕE,¬1­±m’hL°O«¹;ô¬»„×ÿ¾ŒÌÎ@±Ó¤¶ò 3P˜õÎVö´0Åó|·2O«Šþh+KÎñÇ•5ÞúnbƒÉ,x=P`{Â]¼æ$¡­¥¼[Y`—¤K¹ÕPAoÁ½[ÄqúF‹TèÎV¶“¦ƒíà Ó è³ èóÀZÅ(ÎIm.Ø_´>nwÖO˜i&á¦÷ÃZ¦V’N°ä¤„–øÔɲyŸìº~ôfª¶‰Ï倛ej9JN3ͧµ·>‰c)+˜ttè1| !!C¾µø£¯İ­ê{8*‹åP˜ãK30h† ÔT:ºÚ¥y3ŒÆ+»,H´ÆÜ¶ QMSHÝÞC…Å¢p#¦&r¸«ºy‚<×ð°Ùe2›«&ë"aC.áÁ‡_K Òþ~&¬N$§µI¢ë†ÁXL¤”!g?cW¥›kv"ÅJMKIÐ2°)éç-k—ú±Œ7O‚p>)¯Å ¿})mÛÜ”w¢uA’vˆz³ÐÅ·Í ¥²F®žáò‰Êb­gH‚Ê8,ecmF*¶[¦Á0^¤L¨E8h´ñØ4|»õS&1÷G‘3&|Ö­£ ›g5+T¥Z:5w2¥ h¬¦Î¨$›™ä$†¤5#Û»šùfÁ>K+µ¥T«d®5 -`„3«ê§"&jœYÖq+-и²Y¶½}}ËýEш“Æ©#&Çe÷€´jJi}È8³zêÌXtÉŒâ;¤Ì‚°Á)# K=f'*J¹¨Øï3xÉZm©}éúɘ¼ž-îî²Ù!¤]µçuär‘óSÖ¡÷Ãòsv…eÔum ™SÅúÀ˜¼&n)¹AëG;cG\‚¨F@Vš «)¹bå‚¥5LT³§&*syóìJkèJïE_æ·pØÑ÷|u«Ÿ9pVAÍ»(ù¨S™ꬕ|’ú_ùZ¿:E3Y$™”’®Öbã£Å"¯gyK‘Òøš%ù&~ a×<üjæ}O}Y㥭ԗIJÎôYv—W}4ÁÈ ÷_RÎjËB™ë¡úynqXœ ÿÖ^ŽõðøèË£—àï9|a‡?¤!%l„sáïÓ‹£÷=xôÙæõÕõ“£ßlÄуOð÷¿øþzôáæoGm¾\ýöCWÖ•¾ý ­‹$@pAðÂÇju‰Aqñ uÚgn×@;Ö×6´×ŽÎ_+íÜÅF“НVFøN+¡W›´nù5„XUl†Å§”`>u)m)j'>r,ÕªCúÉ*r ‰s’+Îb«-ÌUdô«ºùëÏ÷j¤îÃzõóúóõç§õÙo÷ÚNyµ€T-¹AUãW¨…âïáŽùÿî>Â?ŽóslPÃ45‹m·’d´.ê¡ó·%‰¥Liµ„+™†ôA@§$Ü@kÌžDÑNf\%÷|7¡ŒÜ–üÕ_k-NÁµjÚê8xUöp›`uŒ7´\Ÿ×±†ÐTh¿l%ùɨ5W<+òA ,5â§×†^Í.Mø€N±pXl¤Á‘ïÌŠ¢ªä¦ýîª \â> BšZóŽ×+i1 ŽUÆ}j¯³G°±y«y6zŠf?Äa9%Ç ø†àj¾ôÁãfbe­Žf‡>W ,¬Ü`æC¯E¹ +P•úÍE¶41L;R-z—“=@«³ ­ó„"Cie²pûáLýaIe£á½IÚÄî¹UÄn£s´¦[ÓmÆýÀ`’Q»!»ï³:΄u"t5Àº²·õ«¨'sÓƒõ'ôªÃ¨ÌÔ6Ú=Ø«y•Ê=}•ÀÖØ˜Ú:܈¬ßPZ„¢N;ßòµÑ¤I`¥ûRji¹KÚZÒvÄô_zß'ŒœwÑ¿–hÛ›@Š2-Ò¨}ßËãÎN;á§ÜÊdhЯšù²À·8ÈŠƒoSQù• .,Òr(SØkh$¬\'ûxÒ>r›©#aNƒùk4tÝv™öT÷gòû*%Ø1eº JèÜ _¢Ã¡¸4¾‰ ´”Xd܆4 mg÷á3fMÍå^K~ûð³dy ’åy'“ñõv6Eÿky¢)ämY‹!ö¬2]>¬–ã|ÿï³³°DÈ%Ž6DÍÚó1üI ÌühÜ–P’1aWÓw\?#ÐOŽ ùŒq9AàñÛÉëœÊ—ofÕ6G7´[¡Ö<[jîûng¦r6"4ÒhêA"1z\Ç“BuÀRë…§<‹'ô+ùêÞãm¹Õ~™®…LØóDúön?1&âîA]ÍoÑÍèkxÑ=?oE ­oœb)Ì‚â³B'[ër²=Fr$^¹Ðô(O ¾Ÿd»`H—ëÂ¥~èª)šŽW[wxÓÉyùM?^p)ñ={½|=ƒ#Ò~Û¯á{ëž?~ç#·ÐNºÍ0…r¦Ù¨ˆ+îà ØÑ}=Ý ¦é X%yÄ& #0 Ÿlåð!ì¬×úáŸÛà"îDRÕ„ö¥ËÏÐô_g]ä¾Â<5>XëÏ1Àù–Ç£Ä$Wzj¼ÀŠxD`>Ð"õ‡W»÷Ck’ŸmÄÔìBì(ߥýI1AtBtÎû5 ”òõãŸh›åc’w¡ðí¡´â _wçDæ>ŸÁ€c“HÁ³˜ZƨHçéómÙÄÚ>‰F”ˆ9â?{¢°mbÏÛ ±÷ö‚°ZéIgd Åe¶.Òz!–j? ¡ï×áé>ÌĦv0ЇqûÉÓZ¥L°ö/5ÌÃÆ1ÿ.ÕRÑt9µrÏ-_íõ¶tôxoP›—È5&Æ„»ˆðÞVa=ÃLjȄ×áÛ³˜mE º"zÒ¢Úà?fÓœ]¸Š"ßU÷¯e9©8úº&ÏÛòˆ¦"ŽÇˆñ«o+UyÙ¹ DéÐ¤Žžï ,)ªçk)óÚçî‹ }8@ÈÂoàâBll¡°ãË£ÿ²œ¿:endstream endobj 50 0 obj 5066 endobj 54 0 obj <> stream xœí]ûoÇ‘¾Ÿyù#ÿâÝÀ»š~L?¸,[±t°³E;,æD†4LRÔƒ:;}ªúYÕÓ3»’(Á‚ «ålO?««¾úªºýìpØŠÃÿ—þ}rypçk{xöâ`8ü þvðì@„‡éŸ'—‡w pðdë/þ~߇Îlõ¡ÅVêã˃ïWXoÆ­Öã(VÏ×½UjÔnõb½ÛqtV¯^®7JŒ[_ÔÖ9#Åêx=®Ç÷´Wk¹µÖªÕ)•#¼'IáóZßÃê”…êNêó§ëtÛa°ªÐðPH‰]PrÀN¬®hÑX…4[1ØÕ“P\*~¸ZK»õ RóV©ÐæÏ¹ƒP‘Ò0J¤ƒe"Ï€5’M3¤½duâëV¸ÕÙz„Q§Jçaþ~Ê?ƒj¬ð0»Gð+<ó^¬`3ÎãX>ÄwìVJµz´"ýÇ.‘—Éd¥¯B+œMX9«½tòrýÃÑÿ¨An¥98:•ÇÁ KzçÐH›†=>-ÊP$Ä ³zµ5Ô-l˜á lÞm¥Pµð¯ëÍ€£±ÞôêJó&mžk#áçØc?æ-sûhWÝ„Ÿžc‹ÐéÒ ã;Á¡K)YÝ]cO¥q« ´­Ô08œ‚MšƒP0rïâT<¬›àhí4ŒC®>^ËT‰Íêsì¢÷NûÕ=ü …­Ä%ÓW–ÉÈïV›þ8ÅWd RÑwÐX\7'@|¿\Çö¿€ŒQ£Â²Zx¬cõËZ…¦DšK”þßÈ\ÿÿZzønmž§,²'©gP]\=“W/õý†ö3×½]oŒõaD´Î;Eq‚ï|-=U7ÃŒPˆN¯Ks Nq¦€<=¯Ú§nn«%¸é|3ôeù“Zk¢› Uôû¾ä$îC¬S率)z8Œhʼ¯”ß‹¦-+Îü(œ}Ø×ãì—ɾ‚NØ,ü‰–CŸÅÞ§•q¥é,4÷Ø^&w g©ïn`eVcú ¹8%‹o/Àq‚¤LÆJŸD•zª`êzÑt–ù¶Ù L݉B‡ÃMf2œózè2Äí&D?~"Û?hÙl‚ên¨Æ(¡¦y€‡[`R'î»E€7þ¢FÚšr[?OæÏ+$M›…hK`¸Yi>Ñ1²å¼‰ÚEzk”wÔ©#°áuͺ,®Ð"ûÚYlð±¸BƒÂ5ÐŒÙZIÜ'ØÃçö3žÍ÷ÚÅpØ;ïµSHmÓ^×ΈmJÈê€;¨Õ¿‘ïr¯Ý°ºuï}ªkAõ´V1½À_ð\õO$û´³>§©1Ð(¢Ú%ú€E#… ÛVÈÖ™çÄŸŽ&8«7­Ð¬©Y?EËh‘æ«Ü/æøàK¨Í¹—ŠZ]! ¡Š®ÆŒE˜k$ª!¾„oQÅßÖ~È x5Ђ\]Õªòí±±d²‘¢ïS5ƒÂ£oÛÚãY sú9ÿ}^¬ðæ8†ˆ„¥Z¼ 'ÈJ§~ IšžX@ã®Ä2…l?ZÂ*ÆqGš·LÁO hŒ[§Jâùí×Â(—èì ‘ðcŽ%"3AÌ,iB´9¯#J<[çY—ß ÁåG|Iw…ãµ$¸ÅÍ`•å§|"I¬ã!A>ö ô_¯¥¤K“‡ƒ% ¤“s4˜Òå å‘ÓÿIú=¨Ä ;ó˜Ke cù…H²1Y̱OBåˆQ må™»±Ñ®Qƒ}ê fþ©¥Gª©úcyÊ£îKá÷ùëb¬¿~XÂÆ=h<Ëx´.„ƒ‹˜‘`ôÁ0K¤ ìüæH|Øld$ý¾;2·Î8"‚ÛDç˵äÖUEê'Lj£¿)¨¿ÙÑñç‹ðS{Øuvu…šrõß&ˆh`xu—×:§ôÓϽ®³s •4»](+÷vŠ[f·) ët]ÃLËŒª£(XbYx=òŒ^éÍJH؃ žPáל'*Å›œª¾Æèxõ™_Uâu…<ùÎLÈcŒLC‰ õòê:F®Gb?*%ÔK(.ª”½èîû“š.Bòanzeû™#ÃØ˜+2ÉàpvÝ5UÃaà>ÙàÇó›e¤ºgEÏ ÓD*Æ,{Û†é¢ÜÑ‚g§`ˆqly”&àAyÅKH…ÄZ9›ÆJHÑLÕìÚ Ýô,N61û½ ,ôu‹Ûβ¨[®;H¢ø?I¤1éÓ´Q4:ŸLSvöYê.áHkQâJyj,Ý7éDü•Žj–ù!4"©Àik’ÿ$ VÞsŸøõ‰ÚÅú¢[ãXVJ#¬ˆ|Ì|åÑRá/ÄcÉÑ¿|ʲl¸äwÅ9S{Êp7EúHfQ[ÖÑ3މtÀ›Ý+#¶ò öŠt2ìWÂÇ1¯< „sÛ® RëŠÈ6pû'h…f•ǺFAPI“'ôŠzã]‰‘õöe£˜Í- ”úèæ¶ñÄÆíã1 y>5ñ”m¥“ŽÊéS³¨+¤äô_'ÐFÒ,Ÿ‰2íÔ˜þg5{J ’SÇ.¹><¤Ä·®Ò"ì©e‰*¬ë’ f+j `aPa™’o…gëÊÒ••½ãhl(P`ýAiqS[ü`©EaY‹”r†¢ú\{Îo@2œœoé#à¯è58»Þ[íàm$4¯`²…„é_ÝÇÖ5|ŠÓ€p<~ wÃFŒP#ò’Gv¾yi1Ä®¢ 9¬ùÑEä çV_ãä *8þ¡¨±o` Ƈ~Ú؃U[œ~ü„‘TøbRXU‚2ñ.18ï.cÁ·è”iÝ ÓM-ô:™Áè&›±ÃPL˜1Î@ÉÓ@fÿ5ÉS´óÙ´ærXR㯟 Cöu®*uú~ ¥ó0ßÉŒ%ÍõÇó1RåŒÐQ›¦MÉcµ‚Tf×ú¡—ðW_γ5Rö«Í?•Ô&e|‹IÓ,îœGJYw%µÚ·Õ €B"<· ?¢‘?²‚ø±h öóüǾ…y9Ò\¯eäíGaù‹s­o]0,ù ~× Fq”5Mâ­[î¯B5¬¦iÑ”(.'y !Ò…2ŒJlCà'梌Q"ÿsZ~ý±Ôpƒ—¼0:œA«Å_kU°ë(…·ßé+V2Ë‹Ši3† —?•‡„¼îûçåáG0ƒÑžÊ?^±ÅR¤úólè&_‘‡—´Mí]@÷û·ù"Æ ¤!D 9œtÌ^ï`ݵ,*5*#©R®|nIH¸,Â\z‚h,QÂ/ÙH–Éã,$Q4ÞT,.šðïO,‚­™Ç~Úè¨&†L¯„{ú,!Ë—¬`½Zõ_?®_{aåÿÄ œ²¤"Ξ;¤wÛÅìŸaœõ µOÒC<Ã]÷Þ¥ Òü­ !žó¦Ñ/+!ÕxI™P­›ŽýÔúYÎ ¨Q/§º¥>¤#vèðµþiÈšKGEñéÃZ)æ —É¥‘ÇkT| lƒ Ê‚HrEñëâE,³è£ òÕ?vX^¬'þ³ã:ΰw)xG¹ TÔÆ~lï\—Bßø·º:ŽŽÔèrMéQ“ Çã‡Æ¿a°3± Í|3‚Åb"’KÙ^jˆ÷¶Õàd!Eö!v|žð½ƒ'½[+øÑW£ÂÁÛîÐùìf€ÄgL¤éXlakÈfGÜj–c § ú·;TùÛ¯>&ÌGóß›÷ÆÛ¢ÄN0—ž•»ÍOFõu2=”í-É:Û÷¬têâ6/²>¤Ü4‡ I sGƒùvÀS/ d¨æ:Yl‡¸Ñ¸`Χ,<ÊZbᛲðñÀвŽÜÍ”Ãï8½p=Ešµ]8E¬ª¦¥÷Iôtž% Œ«îœÀkKöa{’6Ze+÷Ì”LÛ^åÒ-àüo¬O‡ó‚3„xrà !ré¸9Ñrœ<>fWÆŽŠPã±LcÚ‘uҨʜêÂÍÌl ãÜÞöÇ=.£{Ïä+R êbvB¦Ó“WI±»pÁ ¹¾ÖÄSîo(ãz„ßE Nº©)ae,=ÛÝž(¦S%³M֚߇¹É£è&¼Ç.É™#FF³”Úd¬ÇI29 ŒÓDÐ)U¸’ 7qÓÝfTÓ —ƒ"ÓĦ^èoñ.žÖ{“ëiñaCb$·âÒv/ðR•pnÅ7øgr?Ö™€ 1ÊwÑIÕÓäò­iô7ÝÀSé®®KÊ~7 Ó=GŽù"áú{c½(PcvÖpm/ÁîÓ ›+ªØ³(mËÄ*Ü5²×9<0eÄ.ÞæØ9!¹p†qÀÛÄÜiƺ¢ÏÈ”Nn„Iw6øËÈ 8&Gßš«wä×7^{ÊÔ$Oé’G« ;²Í@ ñyR‡øU(ù¶%;©„“ÎCŒše '’'ìº7¥ –¸™ ­ù¿–®†{‡r•DÞè_Ô¯Wé³úôcf®ýõÓ= —ïìê…ÏÂIhôÜî^¸_{úiýúMJÀiQ’•êM‘0òtYÖ'µŽE/â·ù{'Äî9À¬›w>>‰‡¤ät|±›wë²|¾d™3Ü›-NÆê÷b/uÌ&Ê}oõrÞŒ;óͯ˜AÊùÒ ÑpvùŠz'꘺ð¡ƒTð›uñnºäû4&·|êìç»70LvY€Þ-í3|àJ #u±ÎéKé¾™Kª‹GÐl“M$¨ª[Ì&Jtð^¾Df}“/AO¯b×9ràsÑä÷ËNLX¢Lëâý“)·¤¹^º¾Ro˜3Ê‘pÛ}Ògá¼Qçøfòzßðнè’‚ž'IX…wÛkÒ\þ¯ˆì>²J#ðO6Ÿ§ØE×M¤‰ß 3I*›þ‡G’ÓÆÙf5^'â­äuŽzêu6§(ÑÄŽÈä³WRGuFjöv†‚L¤bø)H-É}Æ“Ý^ï’øF±ße}Ä Mzøe}øšûüð/´dWšTô]}ç¨W{µ¸_túÑ5e{jÎyçLÕÅL q ùZ÷Ü6GH·ÑK=°3i! Í£Ašºék×yÅ|ÔÚåûmž"–!H¯ss -´ñØM;Ü¡©ùÞP¯üJ ¶_ÏÙ+ŒÓªèоÖ=¸©ªhÏDü¯£à9½0ƒat6{ €î«ƒ•7¬endstream endobj 55 0 obj 5895 endobj 59 0 obj <> stream xœíZmܶîçE~„>’áÕ‰ïd‹ÈÅ®}EÔñEÅåÞløÎ{ö½åþ}fHQJÔîÚ¾ú!1¢ÓR9>œyfF«®eU‡ÿú¿G‹½ŸLuvµèªðÿÙâã‚ùUÿçè¢Ú_A'f¡¥ucÕêtÞf•Õ­¬´b-—ÕêbñK}Û(Ù-D}بú¼á­1FÔ7ÍRµRJ§ê“f)´k•rõºœ6Kÿ®þ ópGç‘0²íp¶Õ1ŒŽïÖ¿áå/·pi»Ž±ðà\ ¹°Âfƒü Ð-uó?…_–·œã˜¢µVsV¿¥âJ¸ãBÖð= ?tßÓÀ*ßæ S¶UZ`Â/œ‘×A:Ù !¯¯š%ÍëwQC¨ œÁ¸V ·Ü´Jv™ê.ѵ‚KQÿŠR·RqÏ ¤‚¬¾CÍãK3œ§˜†ù%gãÀÛ8§H¯œ¡âü(#YFšù8 NfžÕ¢2^‹A §$ ¼ä¶í˜ zxß,;Ï8ÝË‚zA8hõ,`¨c:âÇÂÔ½xBÐà± ˜j­Œ[µ6Zzx†mT«2q££Ð†Ù¹©Ž»Zª%ˆd†Ùðú¬@¤lý3üj{M–°ÍqÈŽW«ï«'¿ÔÿCÇ oƒQüï€ðìñüe×Îy?2]ifØšN1“¿8×ÑHöÕMë`[Äÿõ„¸¥ÜñÖFp}õÌå]À[)l>Ò¶®±ÕC5H™Cõîü‡Þ’*æ ;dz$Âo^¯rœà¡ †öz€Ò[¼àéG3E;û.÷x¹Œ¯…§oê$òéÐú.5^WåžçÔúK­Ð~ÔO†ÆÓôöåÐx? àX§Ñ9¿øÐø!“(hHáߦçÇCãMi÷%ANèì`¼ð³³ƒ…zÌø¦#⮲^q÷'­xKD»J}ß4TÆžs‰æ\û´£4Ú*œö˜MÜ´½Ygœû™Àc±9' O5øos5Œß)Ô Zy®ñŠ?$˜‡ ‡Y)?]Ôüо;#¥!>“ø«þÖ0ù#t´š¿¦[2¼l*EºÞœíÀœÃ,ê-ùGÜ&4ã É9JÖ-ë ÒŒÑ¦>@ïoá?Q¯¼³´öþ5ÎBÁ²¿I >; ü—M.E°V(ñq0à釴ûß/RãóØˆ£>_-^->VBzÛÖUK¼Z¢Ô•2Bá_`Žû‹½ƒªëO7'‹½Wl±÷/ûÿúþ<«þ´x~P½še”¹è‘Q¢÷–Âá<-ãT¾D~–Dþ9;A¼CãH÷:õü.Ý”ng×,¹žøøk–€+kò5¯’¤ûéöûtt‰ÝXgVÍë4°_\öi„oSëOéö?ÛõóÚV?¾^óúøµ”¬3ÿo#­+ %œ;oîƒvðë³?ˆÙó]»Ž‰Ûà|¿€¸áe=p±û){Ø‹ðüLŒÜHdžÆÓ„0‘ž¾Œ¤I‡Ú³_HËrjˆ!½)‰“Æ»,Í<’Ö#föÄ Œ²ˆ[\Z¢ÓК[ôŸ“Ôú>Ý’ÖûÔ—háé({¨wˆ(Û½*-÷°Ô˜óÌHúÊ/€mÃÇöðZè|>D.#tO68M@™ D´.•„fñ G<>$¾ã™yŒO+ €ñË ° „··™Þ çáæa1~TBî'º\"d1:Ë7oS wZÚ„óºÖCã] ‡ \g™ Ân³úï0Ÿèüúvhw8ã_LZ®ð¸/‡Ì×q`tMˆ‘“îtÊ3õœî$Í¡¢´¦kõ0t¼IåБÆnã”4„§)†Ä.SŸwÓH y §ó a¿Û‹/}ihêWÈç"Sá„Lûl¨°”qCèVµUØBUŸí U!–ïüÖa’•l¹]²³AI]Ü#L¼æYÚ“Ø9‹ë|Ü}—äJ¯¥WÞö=¹›¦s1ÇÛ+LØa³±5½óÉ’{YÈ›ÇCN8äƒ1ã¯Gç0aÕÑg9à}’9!8\kï‘g)uá{ J HZ%¦£ÔçÅy<û’µ¤ˆº´DWеZÂR =dßQéaI§·ÀjÆa·{÷5áa‹Õl#N%>‘Q¿éý߈;l26z™Nk¡ùtC5è!ÖR8QÆãäóRbç4¾¼%“Üg§Sš¥X¹ÿìÌ]—5ø:œ¬ÙÎþœ\ÌnùÖú¯›s2Ã¥z×]JÈ”¿ÃÏåØ4UBÙ–óß×ͤ>=°¹`¿¥ñ|47öÊðÀ¯¿@b´»"nâ‘ò+VöG!0…Y¸÷ž$ˆ\SqžXbϜߕÅ3ýêÄ–¬x­7}.&Ö!|E;Õ!¢í%!ê M„ô©µDCÖ~È9^2Äô„ýæ•-}“ÚΧ?··ýbr{ûkâ;£Ø zwÎå¿Î:³ó€d£!ãÏ‚$ltÚ¾m’{…^NŽHþ f"ØY6döcFlÄOºÀ­¦ð£¾_y€ &ßôqMl£_Lâç8NWKÁlkúíµáûKÿ]«Åïäµqendstream endobj 60 0 obj 2615 endobj 64 0 obj <> stream xœí\Y“ܶÎó”~Ä<’. …DRy°lÙ^—­øXWœ²S®ñîj¥Ê^ÒîJ¶}ºhàÌì!ùŒ+#.`ãëF÷‡_.YÇ— ÿþ=8]<úÊ./lù1üÿxñrÁ}…åðÏÁéòñ>TâjÉyç´Ëýg‹ð4_ö¦SK£y'Ôrÿtñ]£ZÖIç¬ê›®å”=çP¸â\È®oöÚ•è´SZ6§­êÖ5k¸ê5g®9O i›£v%{Ö1éèC ‚bLè¾ùT°®3V6_µ+hK Ñœç®[7µh®ð.WΈæ…’5Í™¿)¹†~ È «šK(cÎIþßýOñ…{Aç˜ãøÂ‚uš;·Üÿl±ÿÞwÍ>tÞÙž3ÙýL[*b·HÝf‘’(ocö6æáÃ4ßàOv§>‹+Sm2˜å”§“Q‚¶2wEõs2&a°9 ÓýjÃB\oœ÷ܶlSßDþÜ:9¬K¯ ï˜Þǽ՘"¹`$¢ŽÏ@ðw?{»àßh«Êíx?·3 ¢‡x- f6"ëã67+Z N¨P’:¡Å¾°Ô¦“:`ì6Šñ°""kUÃñaÎ\¯ÇÜƒŠ™ê‰‰%è’6¶t¸ý,ªÙx4½ë–gŸªA">6Rb,0ˆW˜°c~^ÛØâàÉfµâùQDð4.$<#1zzÕhçíÒq¨†¨§aôªi=ª¡Z ¡BÜVÉ4>\Ñáx7§ ¨øNxüLóûKBy¦¹‘U¢÷È#up!(D ` n¸iyÏÀ ¯†<]ý æÆê}FjÌm"yð‚Ò>ÓÓ4Õïçùÿ6’èþëšoNbŒ§¹´l*e[Ä1ØÀ €r¤¡"[ÜËNx:fÂ!¥ 1‰ÌܘŒo§ÐÄSdĈb_ERh:ëÆ›õ,§ï+•ãÜøÉyI+¥{ÐÓÉ”_gm©0§ge/È:SÕƒ¢½õ}|¨ 61+-‰ ‡ö™[ï)L€?·¢€.ù‘Ì2´Úz†–@¬ ¤ÕƒÊ:4áUN.BŠNK¯ËÛú~0YÎPæDUqR¤I1èÒb/è{óØTBŸØÔ Kð„(­%­zX/‰¤2=ÏÐL`2õF/rÕë\š¦fœBÇ'v²OTn.E.w—âåéF^)¦GÔìEIÍrEšhÝê©I-“ÿrÙ+9ƒ QªE4×›*²ÜAï$“žõ=Uy]¡2Ñ«ÀÄHÝÏ;K,Ðÿ#·á'bÁˆNG¯p¨V‘ÆÝÖáŽyqÞßJr­Ù:,ñs`+*(V¯ŠzÎG„z$_1 $ÁMùVÁ5Pæ®;ét½˜,)©ë–51­ù‘\ô°X@”+HÞ xžÕƒä@n˜4íY-¦sR,1—R(¯%ѹVÔtN­¡íš ጓ}¿¯ï7ß«ZÚL¯ú˜¸ÃÌx΀¨mÙáe˜}Ç]±¼gö¿ê s)»¹™c½¿27sÅ?uææ8Sß!½wLBêÉQR†«ôgR™À˜›{Í©S ˜·‘2Ç# …eRÈ4câÉ™Rªæ¾¼ v&faš"œ ³ ®Ã$n‡”a¯æ7š2î™5ñÓœgÌoi"?È á¡òjS&v$—ÈÅXÞ¯™¦êFPR„+ÿÐ'­’ xJH•2ãÅ]lj 1ÈÎ.YRW›y°ãà"°äL=²À.ˆ:;ö’,=וµ¹úPt"`á½ ïè@ír:ƒìrsR$ÄxFäøAö‚Ê$/íš9*,Ê­H/‰U ÃE”ƒ]]3âÙEÇ!1gçFCEC\ðI>âÈ›£"sˆÎÀw÷QòLf¶yÙŸ.úo®äBM×EÕ1ξ&Í…Y¼®:t›K”-U<ÑÆr»‘`«mf´UçJ3¥Ör¿u±Ù­KÙ3±Q±iÕ[ï­ÞÞ~‡•âM¶HÆßbÈ–’…D—u´ëÓ¾r8g’üÁÙLRÕÒjŸ§?r DzÂ÷OÂ8¡ló[û“7óé#á¸Pqº"Œ¬øsq^؆š›E­Ö›ÌÔ>IüøÓ 0– ËêZ÷«2h«§kÝç0c4XÂ÷[ *à '¸žà3Î{†¹!º›X#vÛ<òçµtùVŠ…¼u[0UÒ dGêdcþ4Käy²3-EΗçp(f°Q:76·ÎÇ£Y÷wj›Ü‰² ¯S®±†ãýBš>§4²cNU¤ºÐ×Ï«Ì8"œpÚ¬-ÝPTU#³Žüµýö×ö[m¢›ZûpÊ}~-µ4ìÔå*i“®L;ûÙd“nûañ Ñ29-ÅòmïÏnvȪ…sñݨw¾Ó!êÉŽYñšÓÏ¥LÏŽ#Y„ÈxSO¥Ô¼äà}TБŽu÷d˜ÕrRxZ+<£STÝâ iMiï‡5!­kÓNüìum²~ÝmÅæålô:žÊ³ïPG}û×ø“§’(Þï÷Ó¿Š"õdä£n¥J“t„ç€êyU† ÐÓlÿ¤º¼CŸ›¾Tq]ÃìëÚèN(2Èǯˆ˜ÆÀì…ÁÜƥðF>[1²'ãx›Kî38„ Ì¢Gˆ ç¡=±ðåâÿ]ž:endstream endobj 65 0 obj 4174 endobj 69 0 obj <> stream xœÍ\[o·~Wó#ô–s k³¼“R iœ4…‘´¶‚¶H‚À¶dÙ­,9¶åÄÿ¾3$‡îrWçHR9^q¹¼ ç›+É_ÇAŽø_þ÷Ù«ƒO¹Ã³·ãá×ðÿÙÁ/"V8Ìÿ<{uøÅ1T’J†0qxüü }-½ô¡Un°þðøÕÁ›—Û#µ¹ÀŸwÛ##‚Ü<Ç¿_æBµy ?Ã8 ±ùÿ|ƒ?§øóNð'¾xMŸ¥Ê¿áŸ?nð·m0½†V%ô潯SáËZx^ ¡/mÍ0 »¹W Ÿ×š¯Ká»Zø¦Þ‡‰žÜE­ ‰H2Š8—ôþIó~­ðCo §³Þ…f3º¬ß\”³ZsišôørûÓñß”’ƒô¸´Ç'°”¿Õ÷§ ñQ+CÉ¥øõ‘”a£8<j0v”©$ŽOMF&ÇHÁ >ÅîRQá«^á_ª9#ÀuðX¼yß#V]¿“±Ø¢^•ÂóZø¾·’ç“¥Ú¥çLŒ{½ö*㽩…ìý‡fºympApL\><8¾×E¦ê÷xÑãÅZxµ2×%@à»{½º ¬¯*5~ÜÒ#Nó“GÂsÑt2I ûI3hM|øh{4>ŒnDvÖðFH šRã ÀÀ™Hom%ÅæWìÇy@3–êA);j˜£œsHG5ÀÈd‚§²ƒq*¶xN5>Qá§Møpt:˜øEn^ƒ°ÄÉk?)â7(Ë´´‘¹?§ÔæEýšºÖzó¼‡n­Û|"ªz¯6Çiû16eñ»:‡WH`kÕqg[“©#•Þ 0*/)©‚h;§ªyNØ2¢Ü$›¾ÑÈ$7+™Èƒ'µ½2¬?mGøhàæ}¤–°pD6‹’KÀ$HnáíDZ½`4-%’!7#­ÏýáûD[dÓÒôÇyñ¤§Õr‚òr”A±áà‚+ßHN\ǫԄt‚õU»¨=”ÆÞâ*ã¬Ü|J£¤U iL‚6"§}\™µe Ä€j›j)ãfÖ j;˜°IÄJ§¬âåÜ[xe…Qðʰ!¢D•l4=™†I_Û¹¨¯Ùx®ê#›Ï„Ùã“-¨j`ë'`5€5𤴨¬¥÷´úR¹`‹jЄ¬a°½L³@Q¿„ešåX–ÆÃèø²žG0Èõ5¡¡E³´«hN¼b‰õ¬äxxFH‹ÊÎ'8ÕC‘ŒŸËüySõuæ%%+à'!Š—=Ô ÃSä¸*{Qù¼6ô %¢ñE¥Ë‹ÚcxÞ ¶ŠÓ©ÀIIÔiµË“ª¯ó")uý"IÆÅ¿¤Å—ˆ3V7µ‘µ&3™w­çéÂd ´x÷ŠU‹:3H߇²ì=sl+ëÇâô€IÄôËå Ùäêò‰ôCè×yÉ:±±e›ÿd–ZÅ3“à+à@͹ÒÓt¹±.öJ-²Eèd¸eS™ÞœtEKÓ2É>Æ»Ek˜%Ä”õ9“6øþœ) ¨é4bH% à™Žì‰üþŠ*¿±Ä´èè“‹ªE.3+€-é>¡1Bв›üË•;Š„½¯4„w¨§½Aо³À€Vì=î°'㺗UÊ3-ÁŸ™‚ÞÁ4@@¡>êèýz ¶hÑ„>CMø¯gž%â``'ÉÞ#FœðŽþ4Ñ_êh¹)–ì+”÷Ä;Ì”bôc:å;œ¨7ÁwÏèAnö2r3³™˜ßð´²ã̲h½‰ZÆX˜»80$°3­[F`d2±4²‰Ó¢+†cÑ‹¤]p¥žr…I £§@„HZ„V´q™TÖý Ÿ=µµ¸®ÑâfY‰3P^ÌÄb¥‹á£ZxÑc}´ ‚7w5’x572‰v†FµvaâÌ4š¨€à¹%Ü[J@CÔ5‘¦÷Ý(Ø9eÍæ3xT#út›ok…ïëãÃÂ|¸j8=X  P˜ÙÖq'Jïe˜¡miTõ]ä¯+ùû„šŸXd–‰c@ã,õaŒ™ YZz nîæ¿Ì#+À4!¯¹¼'; Æ÷EF¥lÕ×aÊB'Õ¯¡J`”t Íù;CŠH|CHi SÚIkáò+y+­æä8úkm°©*R£cŽÌÄ{AjäÜéž|D+€›5Ô¦MR¼FPç&Ëc©]`f€bÚ¦dubB§¦7–Å´oPØ·’1ÂÔµ’‘ë§N5G 2ºVjfƒaa%:Ö-Ž„7Æ~'>vŠ¢æzÐÚãÞFÍÜxÁEèL¬š£Z*Ø–›²ré&K'gL=ìâ@èÑÃìWŒùÜ?S-ŠzN²å1Ÿ˜×»#­ñ ²g°;Ìy§\Èf ©5f–² ß¦Rö¤JÙž¢lL˜Nا|“cf1PfT 0zÏ"û˜§wÝÚqXµ¢¨ç‘jéUŒT·J7N„{„_•o3` ‰^ºj¤g/ÊT;îù±Œ¢÷ó`• ÌÝЮü­6ú¹aq¹ÆžäÓY³ØG´t–ô˜œÉ ‰D·ŒÇ/ŽÏQ2Gº~ò«-XA X¬]ϼþ¸Jàná*3:L‚í•ì`Ñ©l¸$$%µ´e½LænHÉÍ–§xRn”+8Ú0î›”£‡ü²Ç"à™›ŠÛòó¤¬ô‡%í$ß]ààWÃ*Ò‹"Ò÷«d›Z‚Ÿmê†A˜!B.Å®¹Ð1rO5A]Ôñu°½”/T£°g¥ð²ñµj OŠš¨Tc`@šktHqöIáEX 3s~SäH1_¥!¢Å·-| ÏwИPjšbIEÿ̹Ýhßãöß·4%3ÕJ’»oñãgÊñe¼äÁ©òÝÅrx+&}õNá-n ¡ Tæ‡6Çdohø–"º1/?Ë&²¾wñ0çp4zóÏlïfÅ/º˜ºW5<6±ÙÖådXAS® ^N%¡…w¦FÖÛ-(“Çd}vö tE$Èqj5)%<‡NkÈ`Ü\¨½Rhè99Q83œ )[pp;ú|ÆûÌL}Öè¦ÔN0¹šüÍ¥ðhò·À\– ]˜NÜü„¬q+ZC æÅÉ.ãüÄlO …d‘”-ö.7×®fº møEw<$q¿Ä`H&*—™ê"\+Iˆ»zVêhG2g™k&{/r(¦x¿ËžrðX­aÇ6¨ÔähYÑ:?Ù_äØ!­½ê®‹6·vcw]Ïf,M]%äoÝ5øUÌb,$ÖZ™™k®‰e ©Eç÷s](X¾” ,v)îP ÿqŠi’Ÿ7Óœ®û®ÂL·Š´Ý$×e†!„ØYÂá( ±H\^mÒ%eóý!샙³Ž½&5cý,3)sB.“ž2žUˆx›BídÈXÃbLsÉxËXŠÌ§Ž µkz&„Sð·Õ‚ó4-¹Ð ²W\⥬žãN"£bLé«-¬ˆóÕK#øÔ8M"t½mdmÊóaRµŠɃût÷B¨ñe %Ml˜»¥©7Yç€ãS·G—ð ­~™þ’sïZÄ•¦'ú»­?ÛÙëQ6ɫΦîbª­nåÆÇjݱ–þ´-›¢?k÷z+gÑy˜hœFaP#µÝ©ÀŸŸp‡v4îjÞ&½ZHȦ ‡ôÃBv´Ý°k&fËàn%k¹Œ1ÿ”ß}^?ýW)ü¦>.…b[ŽÜ«¹IKrUö °¨Ba!„4`…7&¬c¸Ð@Ë0`H£ZÕ«Y÷þ'¥{¼’\87ÆOLpÕ@ýr6Z@Óãvj&C¡1ÎÈa@!á@lUá BLÛÅ®¸´z¨ik¶VNÓÀÍð:ESº;2Šàï1§A ¾OÎ$¡i\GSÝ¥g „fgdZ‘QÛ0‰1?úðç×üTz7ýÞÇu~ÄM ÙFšwØ+à«DcÐÜAÅ'™@N´Ø$‰Ú‚“Å:5F¶½ÀéCˆ‘Þu·¥K7Œ.8j뤛>×uëÙñ§öTÕ=]C41¢ÐL¯«7¼ kíœÀi=nûWí¶§×ÉéÇqÏð)ðý¨g QDÕ-ïBW£Š¶‹ç´{eó_vðNZÚß<45ÊÒ“ÓØíb¸8‡1뾤¾šÍ Ìžªç‰ÚÎò‰šnˆ±z{í—7!Ÿ-îr„AEí>š•½c ;+Ò¨zÎwy(ÙÁëåÍz¸£|“,ÎFÛEE³eŠÍG 7Q. PyHÚ’¹Â„1ÚhúLˆÕ‚ `© Šj³ksÐh9Ž›¶!Xcn{ШêXí3ÍÙøl×5ÆSZ!'à‰šÎb&¢ô}[(wöÒö4%'šãNOˆÄˆüêÞƒxâ)$Ü_*ɧçE‚*1®Xú¸2+«€¦žBcÏí²91&Ô’s?Ír‹l¯JTˆL)†…€U ®¯°{\LŒ ‚0u ›tTŒÞã~ìfcE®·š‡DjÛ~Úäö©mä^b6`ñT-œ5è…¬U#,—¶!±Æ&îι;ÅèµmD`Ó!Ë&uÒxl;Db|ÖôÈ—š@–˜È(ןÐ49 Ä8¢Ý“ZŸ)Úøë6žJ.¾~þÙÿ^}¾¼J/{"¹çý÷Åê¹3Aº?ª»É ¾ƒ ž)êwÛ&;ÿüP\…Óÿ8ydÍ}º’?‚eÍÇhåä”áæ üù7þ—<ÀýÃsi#ntªß’ßRÎ}+æmŸÐélù(ÕyÑØ§3󇊧™ã87ƒIUã Ìj<Ü“ëTzgþû…CØ¿÷¿âÏw¥ê£L”½{;éý²gº/¤Ç÷Í`ÒG8¢2aâm7Y—zèúfcû¾%N:ìE:²¾ÃüKG… nÁK§ØkçecäÃ:Ž‡Ä l_×qìk¡‡<íÝtÝ ·WïT Û¹ç…`«·€%Ç7¿ß­_w+Äf93Ðò€ßPìÜœ1ÆêŽþÿý³%£endstream endobj 70 0 obj 4438 endobj 74 0 obj <> stream xœÝXÉ’ÜD嬯ÐQ"PMíËÆšÃØc†îÙ"f³ÇË8þÌZTUju3 ¶xÂÝj©*ëUf¾—YzÕRÂZŠñ{uÕ<3íÙ]CÛïáÿYóªa~@¿VWí£% bîGk—§M˜Íà– ‚·Z1Âe»¼jŽºgý@‰uÔPÝô’HÉ8ïŽ{Õ­ûAI¸!Xw?_ãO˜.T÷¾1¬á] ÷4•ÝEω1FtozA¬ÕœÁAqA”r`qPBJMš#/V\Waº£¸†yð@:ÕÁÏ·ùçeZï8¢ShÕtwýÀ`I£“y.d4WÙüø&®£Ð´ò?Oq·Ìo>O8Ï‹§iÕ}ÏÁŒ6ÝW¶ðOtËà"Îd÷w.ÀT^ðª8ÑÚhéÁãÆ2TV¨–¡hÅ8ÇÒÚܰ8”²¸SÍ©óxÀ½ à÷/—?6–Ôôå‚=n˜*Û½ë…ÇSX,~ÀŽpˆw±NØ‚S2íA0Sܼ¯Ž‹”ƒªÀxñ<ã®LÑA(JoæóÅàtÛ€IË9y…p$chçɲ9l^µ°%ë“|À Æ(ÄζZXÿ ¼y´h?·o^¿=i~kYsð~<úõ[øZ"œŠgÄ0çR.MH¹—šê¹¨Â\§)OsOgs7v«{8 ²ç“»‡3 p+÷¼.˜ðx¼¹~xIÍçˆ-¦¹ÍØœü}Éž™X¢‘ékçÂ8]i~~›Óâ*¹"ŒëyÝÄìÁ1LÂИ¤@7AÛ¡©K Ç=X”e;«æ£¤žâ1*úœ‹-Np ÝU )d.CŒ{3Ì2œàY:/qŠ"œÚâ®n eR¤šÔuå<›½Îk?%ÍLˆï^tãÝüüzŠßàÇEú|NJþ*qí†}40|;˜ºu*\\1#¦³ãZÇò~‡\Úç•I~ÁÑÈ8]öc˜À@¬Å™Ï{ ÈÖêT—{v*B†#@aük:d[èôözb¬²5”{ ©ODÞ2jö ªµu¢êOQiÌ‘‡šÛ‘°¶0÷#c¹·OI§Ý݇ƒÂ%è„o'|0È0Þ û·h‡ÍߣáBÑendstream endobj 75 0 obj 1699 endobj 79 0 obj <> stream xœí\Ys·Îó–+¿awUÚÎTDYJèÈIl3‰S’+ÅK$+â!¢ôïÓ³1ƒY.M)rªl—W# ŽFŸ_70~7gŸ3ü7þ¹:{ò½™]ÍØüðßÑìÝŒûóøÇþé|k:q5ç¼sZ‹ùΛYÍç¶ïÔ¼×¼j¾s:{µPKÖI猲‹nÉ;)-ç ½\q.dg;Kë:Ëìbw©:«3‹½¥èzÓ ±xëôÚ.—+iYÇD¿Ø^®D§ÒrñæVŒ èðWè`Œ“‹ï—+Õ1 ãÏÃÚBšÅŸT‹Å5¾åÊõbqâ§7ýâÌ¿”\Ã:Ðä„Q‹+hcÎIþÓÎ7¸[ ûïsw+X§¹só—³G¯`+ÙË™\/WºSJ9 Ó‹Î è ^KÞi#ð4ì–RБ™ûùéz <±½àeðùR}+©€±=p$6ÓÉÓŒe4®¨€Kð¾4Ò²ï´Ò‹SdgüV~©jº•=2¡¬Fz_ H`>`>¼D¾J©\¢ÃH BEâ…•ŒŸOšŽ3½xæfœã‹K|2½AÁòÎ:*°SÞÿP¨àéÅ-D'¤£ #7¥¡#ÓFy€\Reù ·eá–$÷—¨ ÂÉNXP÷Pðc =eàCd‹M-+D ï=Kaš¹"•çñHLŠ&¸B¾ø®Zépò½@·á6j‹Ó*’Â8•o—Þ Žjø*nr%4tw6ìõß°hþs Yþïc`ÖÕëéŸM;×ýÈr­•-ÜÁKðôýX€8A”º@²nʰi©ã 3Òç~gYov„‘IÃôƒÅ`•fÇ|òŸ•4Aùˆ r¿ÍÝZyÈãî6 ¶ã|w ©ï©I²FôíÑ )pLÉ(’,ÕÊ_œQí =½C¯Jèá.h”U<)7™,ªzgt¨ÀLÎIj‹±_‡Ükʦ…mîuR÷¡~†½˜ÄklD P SËÒHL¤4 (m¸é²@yBž÷àÆdRdƽ¡×Ùy²ÈFHÐØTÍžIÀΑ£5Š)WoO4Vè;kú\#ÞWu‘Õ­|zç0:@Ï„" *X¨é” .ÎtÐ O_Ók†/Äü€1ÒM)Â:T¿KÇ‚ÕdïK’ ß—+ß„ÐKpxÅu‘d"2ú±ÚÆ:Jîr€o¤û•…œÅº"8«7üžÄ  DûÉß/AC!~Z¢o¦r2u©‹_š§ýÏJ×’)šXGO³(æYyÜn=â´ÏwfßÍÞÍ¥òi,›¯ðA¡­1;×Bƒõ[¬[nmÏžl;¿¾¼9œ=ùçœÏžü ¶þö þØþzþ›Ùóíùw“õÌšöTÏTð\Ëà*¾¢¹SÝ*/ ´«aµÇž°ë­æVÿR@ÜÓÒú}yü×ݼÐLÈÿ/4…ÙqS-妖e]•¡V cøš­%úpÁEŒ ¢: ƒÎÑn„>©ÕÛ>â[]!_{Fs´¤Ž¢é=th¹oÒ:À[B¨‰P]Ì­Ø×¸˜8ˆÈUH”½õ!± µé}í2ˆ™WÅi˜Ãy;ŸðvúÝÈÛú€î5æªS*¨òì(ÊÜ¿-ã Ñ'µìB:à‘‘ 5kË!°kê31Ò"W …>î³Ç,঄ɋҗ8pB/‚#œŒŒ Ÿ_ö! :ªûä:,õÆæØUô6–¦üæk(;Т*õ(åû˜ê`T¿®´#¸ö|—§hmú\m†qµ9Õ†c9ÏÐÀ#ØÄ$.ñÐ ‚ ¦Þ¤ å‹Ü\G—¡-ó“Ãp”èê n‡Àƒdo9 =u¹; NÏoj73…ê#K›!Žw–à³\<ÇŸ[ZÜkâÚ=ñ…M¯–´€˜Qñ74C'>H@N êèÕ%[ÌûFÚˆÕÙi‰!¬5Ì›qËù®K˜ƒÿƒé•Ï&šùËéR¡Bɶ¯Â€/}ÉxÃúN¤Ïõ( êÑCUGE ‘¬yaz’âv0šƒûÇrè sA¶ô“ ÝÃZ¦, }7¸; n±çîŽ\:+&0é‹ÀÊ슂dÕdJɺϡÐï« ú†J;ðH%£ŽËal §ÂÉ+ÍeSÅüÍqe‰V×ÊO$\ATR½ˆ™ÊÈr¸Gç®Âs08_aâ‚ÀkaҚȞJ¶"aË=pˆ8¼ÊkFÅúRð¬Ë̱±®2‡Æ‰ÄG¢G[ëHBæÞp$Bªfv®Œá!ù§ñ#Nø÷#G€jµcGb&¦¡èÑ’pXÜ3u\t»šÙïVrCñ@ÒXíêÌÜk£äSæEjP×1¤˜ 1;4•@šU!PÇ•_/²÷èøiIéy¤t? èZcEgñ,Q„ •ƒ9Ò¯—y•ª³â¸ã‘:ß÷È£¦¦5œ·Ž}N×)>DK"(ž¿ô<ÁÑ:gŽÍ8Þƒ21Þ©·—#©ÖùÝDtÿ<\T•Öo0¤3ëËl6”šÉ~e)¡“ªrå¤ä¨Ü¤â§é7‚J@,÷ëDŸÝUY'Ò›Ôî{ÅÖ#±µY wÁœ¢hžcnò#þ` ÀT5–èßâÏó©úª ßâLÃs(T}j€ñJëñ9T¶°::AfJNXÆÑ)ˆTjx?Ê_ «ïGy›SŠæ–ëi +¢¾}ìA2Þ‰³¼Ú¢‰n’ƒ–ЯÊÕ RyYk éŽ+,=œ×¤S¬˜ñÞymͺ&cJ‚Ê#Z€h]‹7)á¦>eþÁ\e‘¸qeÆ3¸:œ]XÚëƒE@[Œ7ÅÚ"•çÈyF‡ºlR±jUÉk=Ì Ko-VëK.è3\F©Éz­î1ïèª|<¦‹÷ /iªuvˆðµkžôUŠëçÕ²Îéü§ÕÀh¹éÛéÿÁ„4½.2Õ¹ìÓ[ÛÈ)X ãEïI)0AcX–ܸL9"Wõ©ž?!êM³î×:“C5â*ËúжÖòëxÈïyƒx=^¸Å ¼ƒ´Ú­?²½ëvðÏ­'¶õ ;¯ÝšúŽEº»±îr'–H¤7>WSá ¶6ÁtR7F‚U¥kâòF>Qãw›Çhδï~²ÞTÞu&«üWÍâÑñ7_c 3£W3¸ãQêÒµ±l.ꓜ֕ËÉ{©œñr¦V¸üp¾Õ¸-Ó k’8ß¡7;ýÁŽþÂÆ¸j|VºæPW ëËõ àõ‹ ˜˜^]÷øÈó1ð3Â0v©€WïíÄQõµl ःâÂuX‹¹ûþbq¿ïÇJ0‚Åi* ka‘m¬Ÿ¦k¨2–P’dZV¾Ñ'‚J×œä ž.E‚~è^Ÿl˜Ž´$®>8XGã»uèAbTƱ}<øh9¼½¶_HZÝ8æbk'~¯‘ß­¹Ž¡t8×X A"ÏðÃÏLÏÆ8lcYÇz÷âS ±5ßàÈåÍp@ÞQ o –ž¤æ’K?ž±rô¢5¼yµd±×exsõƒV¶ª¸fßü¬pwõOßx±¶sZ¬žaýë‡5¦O%&:¦ÛþOŽÜA–„kî·éʃÆz$<†KÊçIȽ_”®,t*ge'-©ãqn$Õă0 ®(ÃaM)×1w~)3¾Áž'T`¿EVÑÊÝJýå_§Èü·-]ÜoUF¯Â®)ÕŠœTÚ™®Ž\Td4..,}w…ÁÀ`ràñžFIrÀC@ ;ñ5]9o^´^»ÙkÊ`rY=^™¾j û²ÅÿꋲoEÝžÞDúö£IZjáE\P¢ž…›²þsM—N_˜Œ¯ŸVŠª"×õ‰hÏ[x}'¯P÷/Zv1õ!HÙ*îïù&ûóŸ)òbs½³Ö¦Ï¨Œw²K¡œŸ”;~Nf¡¯åЭ²³ —o]ºÞµ*9ø’ÅWµ’“_‹-"þø¿Ä¿Š<~Ç·ò& ‹Ë²x¿LßEù¨TÏÔ¿V“u!„Œ'ñíq‰ëMAû"¦T0ÎÛjz¯¥ÖPœÂs×"³· Ïœ)$Êû•„±Æ‚}ÙxŒ¢Kô`¿+ŒD§ïß$™¶-)6ÛÃ$ÃÏvØ"¤úÀ,}KV“‘ÚÏÔµä>2®¸÷r$m£½Žµ¶»ßÚÄ[:w.Ÿ¿,Ëü8Zf/;æëÁà’Á[£Á7Ù¡_µh,„“hQ¸"§§ 4|\Ö*†ý0"æ*ïd£u»ðÿ¡¸kíñg…Úm‚Чè[þ“|¢[}Ey×Ǿ?øæýýóÈý‹o59ê;EûÍ'­Ìâ#Ú|Ñ~ñ­n,Ú?Ñö¹Q}iÑŽ¾ÄPX)œ¯¤w¨<ÀàK ’Ñùk“ïfÿkï,­endstream endobj 80 0 obj 4154 endobj 84 0 obj <> stream xœíkoTǵŸ·ù+õCw{¹óž©TU „Š@§­ÔT‰±mÅ^¶ô×÷œyž¹wîú…ÓP¡(뻳sgΜ÷kx3ï;6ïñ¿øwçxvï¹™ïŸÎúù7ðÿþìÍŒù óøgçxþÕLâF:×;6ßz5 o³9Sªcz®븜oÏþµx»\‰ÅÃåŠõÒtÎ-VË•âýBà0Ç]ß3¶x¹\q˜b­^æÁ3˜ß;x6‹Wyð¨Ì<ɃÛeð,–ÁuÜ÷k.^ç“ÖÎëÆzÿÞú댉N)gç[g[w⌨qX~’̧ºÿQȶӂâ8¾.ƒGyp¯ ¾Ç•lç¬!çÙníù6V§øî£ÐætŠ•ì»Þöl¾âf¾µ uá¾ãÒõL-¶ðû~ÀvŠ9xW,^à÷»eÒ÷áàÛ8Œl²Ø-sÿ¢÷¯Z‡|›Ëàö¥q´ÛBÇiD‡“d¥rrz”ukѳò{y§%ç-˜ ÌMjí·HtT`Þ*£_—ǧáQ »x^F¿«4@m¿T`‘-Ò çÈ BëÎpP³ž NËÏ]~É3Œ®Sz¾B5¥{¦ßGšðc+ŸïE{š8ÔSG ¥Bø¯™Ö„a›ÈÏÜ˃°´ÚoQÞ9hRý´Eõã­ÞµV²'yµÉÙ{‘!˜¼– dìPÖÙ„ é,lÉ)1÷ÆàÇ; ¿*p7’ÑoØ[ý 3¼F8‹ŠÄá"i<§Äl*­tFázHÖO¯¿žØsÓFkŠ\é@»[E€#¦í´E¥ýÖÌúÀ4›Må@a4(ø¶ˆ3AþÉh!¦=Ü׃H޹—´vÔ[/3ÁÏý3ºDÒ qá{Ï™¥îÚŠƒœ3çæ+¡;†^Ix­`,ë=o¨NJÝãy$<1ÎÃJµãÇy°NQ+eűNçÈD-Hëlzy{©¼†„ݤSþ¬„æÆ}gP»Åw=vÞgl´mW2<¢t &):8‰K¿. !„@2Ù P²Üõ‹jm´ŒˆâB ¢³ÖAÆâ{†Ž**Ç+"ï8î9_ÈÖeÉÃ%ïŒ1ÂÏX×À¡FêUǹl`Sô¼“JP·—ÂKGNâ Eœoa&×鵿×h^~ã&ˆRƒj§^ÜŸ,9¸|ñæù L8ƒSÒ«3ç`9ºBä>ÃlÜ«g@&)Òiëò"b'¯è #¾ c|C)V<í 6»H è(T° àˆ‚‹æ^’­MjB¢RCÙAÏôÆ1ñg“$Lu\˜ %—~·B7Ü‚4oQ³« sFXï¡R`âLX—.N% œVzO__qŠ/½C0jò.®ô²Ì>*`âBíå’X¼ôøÀ EdJ,nœ.g&àì‡uƒõj2cÀ¥²0ê}2ÊX²¢…"³"à‘K¸aeñ%@½y;.¥Üš=›½™£ÔûôÄ xÏu§í\jíÿîϾz4»÷è»ùÙÛó½Ù½ÌÙìÞ·øñÕßîßGæ¿›=|4vÅL5ì8nÓñiú•ÅõùPYì6ìÜý:° >€ý åóWq·åC½Ýè‚€zêQGF:¬jQ-e^$ F(֞ř$‰¨ƒ`##Ëå‡ U€ìбss *-¤õ9JêùFë½nظ.™Å篘•>°ã*æŸq?"Û§D„3ªŸ§?.;¹žG¶kíŒÞ®ÅR½85ÑHvã‰Þöâ7½!R½•Ìù7Þ¹M…wT+§z+à©mÄavâsª…OjÛÀû9=ËL³ÎÁq=Ù‡¥')^%Ký°¨bÝqèVâ¯ÓöÌÄwUfGjå=Ò;yðUK “H½„ªw[Ù"¢Ä‡y×ÁFëÖšäõw­Ý-ù©(4…äwÈûÁ)w‹“,ñB?N$ÑtZæþ°¬y$.úë2ÉNf’£O‰I¦Z”6k4݃£ÈäwÏ%`ä9‰½¯Í£ä‚`ªÁN•0è°€†9i‰÷‰MÑ£kBH‘ž{—q}xbU—¢_ZBÖ´<ÒÆX0ÈÊ›ãW¸Fšª6Ô)| ^©q.¤Púª!ÈÆé}ïc¡:²ÈDT͈;‘VT®ò„ë;Dé„¿Ïɶd'rŠ*NSÎ4©8Ë:Æ0Œ‡4Ú`Ò—Á¦ÖŠ”øÁØúnÊp‡KÅai¯n¹Òåaú€,võ‘¦AÓ1õ˜ªè EªZ;¦jp„uø{"*°Ì©2‘¨@½+À¢–ôCˆu4)!Q½ ã¥ý%ñ÷~Y ÿd§!%M`­*ZtœM„ùójð¢ é­'¨þ¾Ä.c¾ž¤ï±7ács’œû9BN31"æÎón Ñ,çJe¦Üµ'\+«¤ŒÏ*M±°PP©®,ÁÉÏWº+,´òòr1ÔàEËcZµ Í*‘º ¡'RXÍ4¦’D ·ËJŠê}XF—ÇåñEU e6et "dÙr†$òpÆIp+™ 4Ε$CL*5'Qsc-/„ö4iIÍ¥TéèJ—ÙC`†sÚš¤}.“­(š­døÆÔ‹Z"t|ŽÅ>Çb¿áX¬ö¦K­¸ÞÞ¯×ô¨N+z0 àzзäR'G·ªºŽ+{ ®{’õšEå·­8¯ªòޱãêÜYdùÄ)uÁ˜8þ«0†iººÜ0‰(8T•tJ”ö¢£>Hp&1|^÷dÆ‘”8ƒŽ…Rû¬_øJàmžÚ@F´è^VŠØs™1ÙÈAÂLÿd¯ ÑÙ›Ø ¼ÜTT5}ôŠ zCUu(&ñk«|e¤njV¼LÎŒ‡æ–VÙX TB8j¾ ÚQ· !ÚaäiX\&¦&Œ´¿Ä¾fE•Yq«°)¹Ö‡©å‰¬N¨Ù®ÁXZrQw7$\À°i’ÑÜÉžùiò̳×u$êD“í¥N¨9¨MæyÃØì`{D˰SÎâ*—l” íTªuHbHy?ŸêË*ÏIJ°¤…ŸLÌýÜBb%YBô£5ëBc`ÂF¥áäŽf©sÆzuÕnëàPå5je>.Íò÷ :j6òª/Ê#}²9¯J˜©êƒäŽù~GÒìE¾v’’ºU£Åkì†X•Ü·2Ž:S³mj-í+[^kiÙìrt}agLn’÷O–¹¬&hPeŽø@ƒÞÃB߬H¼ýsmU˜×7ªå3ø=mÍjØ,Úkª zÅEФ-g8d#×ð3¡Ë)ñä.îe(ÿQVryJ“çDk\¬îÇ}HûþŒWA0ºÓÊ;SÌãÊð £y’ÌÉ¡D ‘ÒWV&×”¡’4êÉ8xöfUÕ7xè+]Õ;àÀöèœo¼/ÿ‹jõåå• õ¡â’÷³ (ÞÙyiíÜ­œ9W@‰¤c[…WV"]¨yŸAÿô œƒErm‡5РP;Ôj†xˆøugè%V! a@B°?aç®õÖ`ÛkŒÅO‰w`É?âX0WÓ^e_Ò¤ˆGkw £e×V:oH=ì¼ÅwS±Š`ÁëT¦"! 8–ƒÈbõ&ïD4ú“ÁŠ$ûÐRQeIÂéžuŒíŒN¬Ó ÝjGÔØÈy¡I€Ð#äý©¥†<Ä–S÷ŒXÀFg3¥ÔË<Xñrÿ”Ùÿ/H?v×Jä# p œè+¦ âÆÁù ˆ«eÄ_€Iß”ÞÒP•Y4¸»ÞóëHðseÁà4QÚ†Õ|iC? à ¦à¡ »nìãoAé¶&<ÕZylõkmvÆLúšyáTlt§å"#t¬íúìãec}ú6µ9ã…|·Á:™µ‹ Y¬xwGõ!C(Ó‹YÆo…e N£ÀQÌð‡ ô.äûÒÝrå°ý‹Ç& *„ø¨±é[ûF)Œ«ÜØÞë¦;-ŠÅ+HÊæ<òê™[\q2{ZÕ“€/êig#Þ(ºÔe¼î„žÉ ÄÂ_ÛäPà¹AJ ‰¼ŠýCô¦°tj]è.†l3^8c|sÔRˆÏ¦&æ#~QF‰} «q²K*rÁB’pºï+üã&¿ªÌ®woè\®lWç|¤WnL.ÚÀR¾{‚Nº iÎ_–ð¯Ñ`-SyÛ¬5tMÈŒãvôÍÍDä†ôÒ½o?¼0ùÁñæ ç>ž–Xüqœ¼(#zãÛª˜ü6/ÊÓ¸ *\”yÒxëb€¹Õa¥[´>`—ü}+gTIÏÊ`™Yò"Í®CS’!1Ö÷Œ¨•¯ªP¦Íe½ÅÖ%`iFKûA”œ›Ð81K›ŽlIzL››4|}u~5·1æGyg‡õ¢xvi~„ Ñt£`gð2gð0†yIâBV÷R³“·µ´w ¹íií©~Ù§¥7àB»!˜EÈßì%ÀùЛ»DÞ7šN” S{™ûy¡Â颣^Û܆æÖéùðn(šLü¼*"/1ûQœ‘õå€Å+3æ{W•¥ñáäð²FS ÒieÀ/ZõíÊÕ\×,NU[ÊAßdHóá?&Ñõ.=Æ“WítW_#m׈®’zó÷ØÕ­&ª`TV—²š0Od Òíü¡^h™EwÁÝÐrǬ7„½a¼Å£»õòfìF¦‰`TodÁ´G0ùŒ¡¬’¼r¥ÆZÊsdëzÓÓädlަ[IÝ *—¾ŽúºéGcU¢*;T¹ 3aiÊfú`½²»‡Dgm¸ºÊxf亟hs3WÝPÜÔâÏu_jJ•’øõ¿wô?WÓ›,Çz‰š;¡ðÏmqp4¦‹°„åÿÉ•$$έ˜×oCÈÑ4ß>„0\÷užˆôƒ‰*„¿TVª#¶TlÜòQ笈2ÞUõlêŸáÝ›62ÔSë iŸ›õ?7ëbÍúþש:øÿӈܼðº®ì@$]Á׺K`þ_“[ŠƒNd.æ’ŽÛÄõ?yÑî9õº2†AÜ|€.r vlŠàzÅÿlö_¦ Ùendstream endobj 85 0 obj 4437 endobj 89 0 obj <> stream xœí]IsGröÖÀxB³k¯¶c¢VNˆ”DAaÙCÇ$ˆK Rœñ¯wfÖ–Ù]ýû PzèW]k®_f%^ƒ:ñ¿üÿŸ=ºÿ$?ÿÛÑxü%ü{~ôúHQƒãü¿Ÿ=~pôO†iœÔñÙ³£ô¶:Ö£¼=öN ÚŸýzôç“ËÍ©ÆQ©“ëÍ©¦)FrU>ßœ:=Âçpò‡úðMkùK}øª÷ð¼=|[~¼9µS„ÏñF£¿o-_Ö‡½^´‡0¦ã0ÅÀ^º/95Á/†ô·^§rIåã»ö1¿eMüõ–tñvƒ§i´œ¾¢SüG;uÉ åãÏíãuk{Ñmû±$d[O•œ›bðwÆýç1îý'*ryzªF3 Œlà`F•NäÉætâ4†wÒÖ*­a,3@7ZáPÚÉáAØÁ œ~…lâk&ÖôEkJl,îUyz¾q¬yþÍ1(‹¤bFk1Z„ΕaS¢=…™+wòÛÆè!„ ò×ÚX Ôò)ŒSN“a0Vóù·÷òXÖEö0M –t3EÖ7öÈväjBÑÙÀÆ$rÓ°C½\µÆyÏã°ÛPaSÝÆBŽXMN°R £Zb! HŠKR%– @ŠŽ‘ÚƒÖòá6úlÿ¥ÿì½ôùvFzØZ>î½nêCÝ£ùµy&y¡Ø@ŸöøèQ{øíV>:ù‘&Ï ëãÆ‰Oã31ábn³Þå”ÊÇG­í·âèÚ¤ŠKªUöãV=í å¨xüÝ*È/Zù•U0†&þv>ŽZŸ'ì<ÎïƒÏ†±QLµMó5ÓW+ØARnÑï…w¿KÆçm5b„‰scÇÄ÷–Âÿ5)l$f úAñ>cÓ¦=$âè÷ª¯Ò5°É¾ÎµQ–¦¾Mˆ™ýU¡Dõ /XpË(1€fI‘ØI§‰„Ô ê¯ ÝK„;Fü{ǵcÝ|µ.8òá°îª˜:߸žw6*–€?iøe»!oõ:4Ôf½…tá°ï»ª¶îòϨø-ŒMv‚#¸CØ1>;‚ë|^ÀeÍuEYã,µ‘?¢CëB›?ÎKÅŠf H ]M‡?ÐÎõB‡á¦ Œ15rSQvey»úd:ùE'9¹÷ …¹n„Á ý—ì””å8(¯¸¸gùI¨h=¯Si^S• t8Œv‰XLèÚì3u, Üñltµ“©˜·@êUFÖ >c Š ·N,LdùpeKÏ,WųsŽ#ù*_lÔ÷ …œ§ÉqkÁ0™aU¢¾Á^f> ›é‰/6ð! `˜×`â4Í#Ü@œQð«î0• „§‚>Q:}@@ÕjS8)z­5Hz? £lÓq6ecînö9í+ßšžýsžÃz¨.3Ó¥…ïÍžÈWµàá^Éod^xÔE¸ZK¦ò?âû8ؼlê kr‰m™³~‘ÉÅ "ú/\î¼CÈCá> ˜ žå8AKLÐêðu@-8OÚØÀhŸøçá_„èh€þDé²"ʘŸ˜Îlê·\7­íOmÔÝŒp J:B½pà Âð†¿ ´Á䛓Z¦Ö3cðHzt‡ë‹ vÑBÖ ÄãL ºÔŽžWµµ—H„#€W†ùt V°ZÔM=£"C”ÅEe},<ö¼â%^;#l"L-Dj'¤ÆÈhUø’VòýÇ"Êæ‹Œr/ͺÿzOH å'ÌkQ  ¬¶(à%-¯ƒ\Yùö"Ç,p—,7= A&èÇæXEzû‡÷û¾ ôU}ÈäÈ“ (.ìu4íLzÖ’£Âáü :«2“š_¨œ£ì ²CÇð¦Ì¼þ8›FšÓ3f’×¢N³–uѺó ÌÍŲ¥,%t”HiÚb03a$Y‰\»½Ð³dܤ¸Ça.Å~Ö$»lÝäV&’ÒwàLfc§ÏGD®#e z-¦÷‚¥\äáhÄU:6¡ËÂe»£ÑDVzSp20<$Šý#ó¾"žFjJ>Ä0Ó5ކËZÅR?Û`,Úƒ cÄúpG 6*—"Œ¼‘€`G´‰RX"\dÞ¤ ž/³p)ÙטN8jбæÐmÐ6X2ƒû=‡êXšäaÐý¨F§ßaXe>|¥î*ó ,Z¨C_iA>NÝ6Ü?,ý7Ϫ:…fÔ;zvF;󌛆 3.£¤Å]W ØE‡ ».¯6Œ™ÐûÁ‚Þ]¥>0ÏC.(ÖoB°íNgŠø×ÅJÒmr<ŠWúÍ6‹BQÜKžŽ`T‚s·eùqƒÙ†diÏ.}ÔŽ-Å$ÕdZn7»}ѱF¶å#r¶ì‚ßÝ o^‰³Ë-H`“k …êÊõ'Ì+‚§œ&£Æ¦«T‡Û+˜>9N{Ú+t½3lB$|°dÓ5ºY`pRb»~Ù§t¬NuW5ë¡Ý™’ªíïÙôÓfO·›îG>J@;:)hEY Šf½0ÎøŽ£ÓŠKö{9Z1 ÒI×–ðMa.Ý‘î 1ŸM‘c[¤¼ÀëŒ"n¤ßI¹ð—ú¡ä›Ð:âÁWÝÐìGJÒ¹mްfJuîÖÖB‹g$žÕ£ÀÃ3†’!waÅYؘ íÕÞ°qâPn*Oñº/!²t*ɱƒ¯Ö¸4 U5£¡a""©x”¬ËêÝœŠ|d½¤™HtÝ'±ˆx~?…¨õ<ó7ÓªïBȓй•p_CÛtúÐ+¥eñC¾Vl¢¨3¶9 Šç‹Y"eÇ%T}—H½©lŸ1lafÆtûVÖ±YFæòýVã±ÚÛ½øÎÖÀ¦ 3»¦ÉÜû· 0—·Ý¿È(ñ.! ‚îD—‹„¬Í©Š¯Ú_KÛe[>R‰ó 3¹qØ7’ô;Y—Ï7"í­Vu·DihÖùm&veè-ôYq,MKzc1_Ñ”Œw Q3L¶c€ìŸÍRÞ*²Æ®˜êEôSä¤d‹c¨~Æ4+‘ šMV$ÊDÏÀ–ï9/„"ãy+èWƒÇ>‰ŽR3â ØÊ„¿\·ƒË$*q°ä"[ðuÍ lï÷ ‚T-gf"<«Ú›q~5©ºCá+¬'ÐÊRéáû•ªK ð"6ßWLÄì˜Bþ+ùUv™aÜP*:"v<ù„’áoFLéÊ„ö{tŽß( ØÕÒhìA·–óóMÛf×ò Û‘vùJÀ®Y(6<òùZÍÈÌÖÇ%×Êå=æIÜŒçºw Ê ˆ1Êä,ÁŒ%Ó{œñ‹ã—׿Q Æs|ôdúD±s+›•‰]•ú-: /Q·“à]cÆjW+,B¤×­È…IÚû{hkVH²Üø¾I¦ÌéµÀ6£KkR†Ñfë–7×nhUMïÞ½ìm0f´â_Ah²0ŒjئLm²šy¿’ƒv‰õK#BTé߀‚}Aå›yºp`¹VCA0¿˜+ücús®/pÕrIº]¿j“`q$‰›k«jMÛæ_鉱¼Ëà[/YÍ?º¾å>ç”ò\ö`&ª—Z!% ãÖ_Ä»Ó"º8‹˜Š›ÇTNˆvV8NŠtÄÕ߈¸¸¥²Õr{w£vÊ6I,¼ñçÓ µ ™$®EóeÃë¼j<Ðȱ» nnsxä?¨nH)4sðê¿hT›•¼nž¿¡ÓwïÔwî4,ì™×г"/䋺iúr©W@þ7–LÃ"Õ¥àrË;'Xê…è-RìáÀ×Í?ìÙmp­ÇXYb :.R¡¶u»Ð¥¿ä²‡sš·aþ÷ŸVd»T¥šn09ÛEß¹=^" tœ¦ùæÐI Ì*ûõ(ü¢]Äžz&YîX¯Äò™¥…Ä„Ì,oä/ ™mz¹èm|ÿ´äK’;+÷tja‡YVéAÙmœçPxyÌLN>;H¿‘'†^-Ùà„Õôó\o¯ÒdÕY§;·‡æ"|a¬*ÕÊ >nv'ûó ?6¼‹ýY„ïÛG½î²£«J£9+=5QÊ+Jç:ä”kJIÇ:§Ûw‹Æ<}Ã3ÒÊÓ–EYÊÁè-µ×òU’.‰ ´'PÉ«ý¹¤ùkˆm÷ñõšìI—7Ìj‰ÃzÕá0W»%hÌK:³Þ.{ !›*>RQëïŽþ†/Y¹endstream endobj 90 0 obj 6091 endobj 94 0 obj <> stream xœíÛn·±Ï§ýˆóÃZ/oK²E_’‹hyhŠ@¾%Dzìº_ß^‡ÜÙs“åÔ…ähÍåò2÷Îð—õ8ˆõˆÿ¥¿_­ü`×ϯWãúÏðÿóÕ/+:¬ÓŸÇ¯Ö_ŸA'é¡eð£ë³g«øµX»iÐëɈAêõÙ«Õ?O~Þœªò#ï›Â¿‡q¢}½ü³oç¶™Ž›ÙÁƒ¶ýp©£ÕâÖíàÕÿô„ÿ:ûËJz98@çÙ“ˆÀÛÍÌcµríH·íгzsÜH¸ñÓ¸óS¡c¼‹x‰Ôt‰?o7§Fxè.Ožá¿_¦FurÝÒ^ý_œ<ÅŸ7¥sÙcüçþ\àÏO'øû¬¼~Yÿ¶4^×F¶çEi„iµÑÃ(¦“{¥ñYíùº4¾­oJã}ØíèNa?±ñ²YR„† ûˆï¯¸…nJã«Úfr€;KFzQߟ—FX‘cXÓ=nõL%+9 “Τüºv|ÚÌ®=PŽÇÉsc;{¦›vz2)ÁHî{ÕÀ4?¶»N}#é 9Œ:ÒÞ4ÊJ{,àGOpÍàœk¼©•dÚäǰ!ô0ýjNØ5Ó%…`~E6>§ÿën"Ü’Ù걯Дêç €} ü>4ðíûÞïdÒÖ™þ÷8ÂÆÁ¨åËŠlí‘hÜNÜžÀ~:•vÂû£YðIa¼‹òô¶<}QCÇ3ß!˜ŸóaK™?<øA8jaŸ*€‚•@zp* 懛S18çÁê•`i £ Þv’} BJ©”Ò@6h+€¸4@Ê>°Þ$DÃxõË‹¬µŠ4½Ý(˜v’½ÒÁl%I~£–¯nê˜ÚÓd'—‹­;Ú¸§o쓇÷&ÓìqV«4š“Gu„n…Ré“!5EXvÞÊdaœŒŽÛ‘ ‡+e(J<‡Å–½Û¨ð$ÈZÎ 5Ùâ Š Ðu[Ü œ ¦Ë uˆÒ„]/#¤øOä@k‘`ÒhS¤9­p¯:áu­ÞèŒWìœðª@ÏfÌ)Iƽª8|T7·•ñŽƒ^ÖAgT<ŠLÄVÐU—·‰z¶£F‘rÊw6U¢xe 4Eñ¹ ¬Å½zšùý{¤ëÄXpˆ<É2" b2O¿E|xoüÉïjk`u†8[Aü?ˆ13"RÖ~Œ7!3](`F­Ä"-Æ%¹½Ø„+*-¢’š4 Ä„ÏpÙe‘ºmgDˆ(pG 6ã3‚lÍßm• ªáÛ·œfúP%6ëO°ò`MÆ=ßJç-Õök’¬ñº ÎÓH 1ÕæžÆÂŠ,rÄLB!Rñ·(#"ãnƒ¿ƒò¾óöÖ ÎN ÚwBÔ‚‹tB{t Ò$v|’>‘v¨*ŠÓúVdXŸåDfUÒ?’m&(4µ¤0‰ó­÷gn$Ò wµÈeq“.ÌV6pQ©XLr“J?ÈÑPå‡0‘‰Ø¬HBÚF~€àŽó4‚25`¦:â\h5´t[M{©Ê£R[dóIÂy‘®<«) ™*"2zÕÊÌ4JÀ®Q{qÚS«1ÒÎqkUŠ'éä`„Çœh/òéu…[•ñ½ô2ãè6I` Hhã—”BšŽQ²äàwßž­¾_ý²кº=Å9J˜Ä­Í¨=þ}üjõõÃÕƒ‡[¿}sótõàǵX=ø¾þû7ðçáŸÖ¿Y}ûpýýQb Ö!Ì‚“„0qµÁÞ4Bu›+ÕÊ\~CfŸ>Á†4 ]6;b½GÄ?Ÿo“ÔjðDPCR¹éi«ÑŒ—œ 6§^¡]äNÎÄß ?9—¯.jÙ¯òÜd3í“}q©ÞX(_ÁbËŽì ”"áZÖLÌë-‹9ÖŒD æÑ ± A”)á5r«ðâVôº.¸vld‹ðèªu²åPýÈÀø>T ¶`9™ž[¤8ÖTƒ%„Ú(Añ~Õ‚ya0r1æØÅÜö[4. ï/7=¢±ƒâEêÎ 4¦´¢˜²“ æÄ¡1sX°¦ ¾Š«Ä€ØñäŸLhÌYÆ”I¬ê5˜o»ÌÔÔxˆ•J‘v¨•ªÝ(îÄPíMçÖ´ÈôÒ½IrBJax_x ð‰WÆH¢âæœú£ŸLDÍI[3qÆ8bxŸƒRÁ:ìÜÒ;S:çc–EbTÑ%§S)iœ5ÖSÔŸGª<ß,ë6/ P!Bû×ÕÙ½/'¼´ã—Þý[oÝõcžÖVņ$g÷¢˜l48^<&">™."NzÖ£ƒÂäùØâcFîÛƒF½á–SÇ{ÍÍÜ­6PÌœ}ɪј »ó„òããJ>mø–é{SûÎbË9”Õƒ—ÌAlGV‰fn Y5qät–rYº´F\‰Ž4Žñ‹º3ž-An\’›ÌÓÎ%ÝÁ©×ɶ}H7x´LÚ³oª±‹úôuT£60°«J…“BPއÙÙJOAç§ð P+ÕôW1$¥Ð:™|q≫a-Vžì"USÐËßmAû“?Ájá3ú8–‡R­ª#¶:»ñj³hYw–(†‰ý¡îgdÕóØ'/æž'9Ô~þ^â‚O%3ÜTü½™QÅ…#´ó¦%ƪhj Þg#Žqâ>޽q¥ÃÈÃüGÄ8rì)ÿ½"D›t§ÄéÚi)Ý]Éöü¼\ ‰6D¯#éþ¸ñ!ÚìØõ¦œ/dÓYʬ”æsGÃyžbYÒ×·VP‘X<=ôK§ö5žópiÑÐešÃ¨ƒƒþá;åM(M{æ“5ꪻ+#ÔQö”(€‹Ä#þ˜…d@Æ"Ïç/´ÛÒ9”´*£)•ˆèmŽ3¯BR¥³†|ÎÖ#ø&1ôHé}Íö%p~¿fjª¶f¶žj)\q+úoMÙÀ\|ôØàøP=Âf_Ó”±‘ÒÄB $5šX@(I[S¬W²ž¹ÖÊ–4O…”Z^–˜[÷­ÞKÃ6¼3~¨s ,mÏçY;3ñšÔÅWeMÜ™Á¶áׄ<Ú³Lm)öÈ9}©ìmòA²$Q“Å\ÿ›[›óJ°èh¥.æ•RdHÁÂÎ ')±2ïimBË[éEÖèj±^p'뀇鉔þ¢„ j2猇`WÅ%S£>“ØÈkDeTH(;ïI%K ž€’~ާû¢0$:ÄÊ0çÒŒUPÏ¥ÛäržÞ2vŸÏÞ© º‹ SHœÏ¾)EÐ/Éh*DZÊ:ùັʪ”úÊ×ɉš}¡vi=šYO‘?ÉV‰òõ†^êÐ+›šCBòsÇ‘†œˆ×#¦qèV¨û@›|ÚTÍ•š—1ZMŠŽÊ>lœ°øíòKÇQW-›µØ›lA÷¾(_ðÆJP¿ýz„‹bÎËhxö åó8 ú|Æ,&X&s뛑‡:ØÇ¦ÐD6˜j|MpÙÛãM¸,B‡ å)ê^\LêbÀq¶3#ãySíÝ–ÊéS½–ï„È€æRŽ:¥@ù/àÏÒE\¥:}ä·Â‰3áškË%ꎞMHU‚юsj¸ºÂ!˜Q9‚H¥‡haú1T‘q)Z4QHz²_´º¼tAÑ;JR{> stream xœÍio·ñ»¡oy/ðÛ,%w hÒMa$­-£(š"¥X"ë)–ÕÄýõ^Cîì;"·h‚(ûvy ‡sÏ?Ÿö:íñßøÿ‹7'Ÿ>ó§W÷'ýé×ðßÕÉÏ'ŠœÆÿ]¼9ýü ©ÞtS?©Ó³W'¡·:]gOÝ :mOÏÞœücu·Þ µÃ Vçëaõv½±1ƒéç›õFwÎygW?®-´SZ¯Þ­M7ŽN+öûÓ™auݮ׺óÞ›Õ¿Ö†žxÓ{lÚwÃ0²‘^0ì4@ËÕ¾OÂeù]ïœvÒqdm,ެ°ß8Ð$ýØ Ö¬¶0È+œSuð_œÓÓΩL7¸au»ÖúõfõP¾ß¤Ý`áÓ&!¿æåþºÞôÖÆOŽ…}´ƒ>ð1ØÎ;°›G}à¤nO ›;ÝOSþŽ«y‡@ØNéåÅG˜ïŸg>1=‚C8»„-_ž:#!¬hlœa v€ìUÛ†ýÜ¿Î}:x«M§•Y­7¦ó£V6Áª‰,✊Í¿{52@âŽk7"%!%¬~)£²ø fDÈ&adƒsÁÄÄ\o Í 5…Pó^ßVˆ3=¤ ‹ s-§´O#9ÇGR3#2éȽÈO¤Z2¯—8$ k0ŒZ^ äó«@:œ~ó×ôj&ðeäÏæÁõjÎëør&é{pÐz{e÷óé‰ïŽa¡ÙÞù¹Õ·kÕMÓh'öùâ=©Îî`’e»†Î Mt$3?MÕ2â+wÞÌÚ!®qíò{K x(´^hu[D¯QžÚ•eª‹Ä†€jXkï¹ØÄq/9»Åå3ñCÂñƒëu@E$QïiËÌ4Ëtklg•]DgÒ}…ïJ§½D¬+ ưy$®#ô ì|Ç÷ ‘Ûí‚e$Ò<v^74'ïÉe}鯹¡Õ[øˆÔc5ÁôR‚ç}V˜q^6†¡nÍ´(ô‚YàhŒ)ØBã£W®7ñ‚õSâ…w8©ë”2\eÔü;÷f³Guk¬µ ²TO;3p©ÏÈÛ>ÊDÛ¥Wf= ÿ4ö~ìmœ$ £Öy@£ž›ø±š’´¿‚~‰.ëF]EoD“—l$Ôð“¡6®þXÌWk|òί¾Aœ“–>+ߟ—BøÇ¬¾Ck4­©„Õu‘ŸÌ€ñ= R¶£ R¶¬ÀåÕLOF@,‘¶h¤àw¯’è„k´LŠy‰¤í°È˜Ïô‚›íGR}/³vy_øû~úLOÜPös`ë7ôÆèžôxÁÚòÛóYx sÔÆ¸™Ü2Ç+l ¦ž ôƒté\œðq»9¸¶ÓcÚÖ&¡ýP zYbgöÂm¡ùÊtÐcƒ±—5€¯D/¡±¸õㆊ±È-üót皀ú´Ÿ|ñ dp'Š (Äì1æbp{ÉÑÿ:’ ¸ƒ• U¹8ÑÏû"ü‡Œ!ݨž0üJïuáAn°ãgíÝê§ÀÈ-+ä‰Á*d†(· Þ`cL¢½þ£èF‰%åÌ,M¤ì}ut «èý’ël\ú •—·­XAŽ@SEÒpœ±žL#øÎ4ØL‹GÛ*C‚ÇïMÜ`A‹#Rú~\¶§¢‰²(M‚o g’ÅJ»HL=t®1¼ƒÄ÷d1 @?ßã´f H‰m,0Ÿš²÷¡\IÜ!ÏÍ6ÁHwÁ5bدíêøËu£úe*-¥Æà6&srôÌ9ö*Î[ì(Qâ `m%’Ðú¶ˆ¦·’l{Ÿ^ŠrvÜLyÔJ³aHÄ{¡f±¤Êý æNã£0C}5%GÉ>ã‚QtÛrw_{ˆ¾q$"U§ú™_;Œä×.Øü,þ¢b¡‘Ÿ‘LÇèWVE0Kb¦$oc1‚h³˜Q¥ Cl+"PnJ.ÏE„HñÑ$žìã PfîˆéEsùXãÆŽv›/‘Þí †ÚàÌ`sÑPy'v—‚±n¡]â–n½•Büìtâ]k'ó@KzÚ®ÍBXæ¶ yEÞWöaÔdЖ5=(DX1£ízºy&Øaaµ$¯]C¦±×“@¨€¯ g4¼æAú ó¢šÒµ†ÍˆtRQ©ê ìËÝÝË" –Mƒ}úñ ÿ­ Pô¶ŸD!=¢ŸäR’Çïv¿|_^Þå—?î’á@îýØgòw;¶rhÇotX>Ô‰¹!ñêYžöüù-þùvÌÉŽlÍ ¯âŸs9ÑSˆ’"¦˜§WJžØèµä¼•^^HØù‘÷!M!Œ{nbÌuáuyY—«Ø½÷ ÍÛÒòZr(*8æÝó]ÊÚáéÉÙ'ǟ㟿'D‡N_ÂHÀ&ˆYôWD‰p•?àú)…0dþŒX)ÃA{ý'üó]nú,‚"cÚ„2{ÙÒ}Ô;•¶õGM†ãELèô]"Al’hî7`æ^Â̰Ú?#?e: )×ñóëÏ…‘ÎE»É¶šüiÚ6ù×eòƒ—ŠÎ眊Ç$ê[˜¸ý€ï‡‡3âïMæ¥$W+6æ;vÃ_í”ó ÎË ÒÚ£ý†].¡–cðþ•Ìg ×£·’w´uÞ¢X á:&Ö¾Èûö"·ÿ—_HñœóÖ’bú*rz˜F”ÝWÛ)˜ªm¨y"c±€™Ûól ÏÈP†;—ˆà!÷éqöÜÚ=\‡—`Ü'»ƒ~#8´Åpy¬OÂj̨É,ÏnC7}æWÉU-'¢ŽeܶUؾuÆx~žÄ€ó`yjöuÞ÷)(žíVfcF‹UœSúvRdßo)xÆìOp$¢3Z ÷쌊°/ø‘uL¤H¤+£'•åQÓ2lðÄÎEÒÆÌf\†!ùkLO…$U–MÏC‰šØAñ¥”e }â"½Ó—KuÊá³u ÷; €÷X1RÒýàÄØègÏTúbæ,ŽƒaP„-‘t)ú› …Aj"Wª) 2[§W¬fi‘°ÃŽˆsúŽ*¢@”÷!™×èêuP83à‘+؆’-Æ2mƒô6UÜŒ`…¹Ð‰ËÄý’ä í½å$ÝóòxVÒÏÊÛoÊ#Ë&|Û.h_ibky@ŠQPCIÈb)ʘàíO0Îr«”N°Š:9=P™ ˆÁt1‚9€×U_9ÛRX›Í{'ðÁ9EÐv±MpôÓf3f $·Ñ^Qö?IMïiË—t¢ƒÀ³˜0f’{)— AîÛº´ê †Ã=ì¢ G,( OîËSŠiÆ´®É¤s`¼¢TLì«Ã@ÁóÐT ’¦…SîµÉ]kEÄX[ôc§´È_Ìx 9ñå_* yw Ò²PøOMõg¯*áRÚWtˆ”À –žT%fýÓ&Kx ‘žBÀÉòé±T’ç;~eù·–‰ yÅÀ[â,4q1Pm7‹e&L3IY½ªJ0ä-YN˜•œF7O×#I”°¯«X=/×óÖ2›§L!ë³—3&KÖGÃSP3EWÊ IcÖu0òúf¹©å2ªëÀy@Ó½eu–ÜC®D?/•oÅ„ä¢äŠE—µ~¨«“Ê[ÅÚ¾d )äáÅ*¨4mV/ÿ9´qÝŽM'ÍŒñÂÄnÕq©¡·êÑ ÉMëÍÿõ„Á+Ô]¶õ=³¼ É­FzlSœ(¶¼‹5ð¸œZy¦i¸PÓ¦C€÷:©=–%ù!ëÃs ˜ž.rょ·9ûKîê%}~%åÑXnî~wË›L¶T;;°€¢˜ËcƒÜIÓ• Ý“C%Yâý÷奨²!‡À`d1ù œ2ÞŸ9kËNsp¸‰ÞxZ´ŽÃ&zÓ® 4Kø•§*~-mï*$¥Ç'5m©i˜y-r®$™a¸¸—p+æ½$ò@Õ[Ò*ð=s`Ž$ó‹lÞäŸùgS±Fdþ6Sø% ±Wîƒ8ãþX}ÊÂÁa2§Ðv¢°ß† "uR¢‰Ôo*JüIJ¶M;ÒnÍQ ? Æ Ä­{‡ÑÁ¶öxô]Tð–¼Ö|7ù¿áØy}…Ów š­´o*¤¤úçÊÛͶEæN»B†õr@fXphfÍ«U¤(#³Y|‚¢z±ô®.= î«]é¹H‘‰W> Eý)¬ü¾íz¨ƒ0 ;+­ê\LSÎ4,DÚ˜GUJb¹ký,ñ‹|Ø“e4hB¬½â Seù¾PÃqלobÜÞ—¢‡{žÏ—“ìóû5¹oÆç““ÙåEyò\¬Í Úä`Nóƪó’´9:á†|nÀ§I¸Á· (Ö€ÒóZñ|£Q>GF²Ö{†1ˆqê}¡}_¹âb^¯:K–X§$ºRÅaŠÂ`ôÃŽi¹Õ‰²ËÚ¿›wdyp6 ¼?:oÖïˆ2Ö¹h]Ý<ñÝNJñ2œ åK cMcƒ/3‡Cþ£eNŒ‡Sã±y15P…J¤z:ñ=˜cù6%À²·uP¢I Æ3ëØHß³‹é3Æ‚³ØY¯x„m!Ã9I]:Ã+Õ`£©5…"ãêxÊmÄ‚›Ÿe­T‰Šð0~Z/ò6¨î€™Vuó¬ížÈËcò3”RrÉVk–@jj°Ï×Õ94FkG¤¬–š…œ†q›?[èðÀF¤–³çëåÀ7ÍâT;éyýSÒ7Œ]+Z GQ^£QË×ùXJ1 EU4;µ×ËzðÒÎí~­ãß;"kœIfõ¡d» À©£Î1Ôh‹!Á8Y¼æAÏK² AÆ`š1‹Á´¤œÒßË»>U\•hD6^ºkÀ‚ ‡¨M ýžc$¯3946·qC¸aIÊ…qëÃ@r‰Ú® ä•š…¯0«²Ý{~¹Y(‘×nbh Ij.òyLºD%m›RxM•йã©WÛ{ªˆª<íš8Ý&ñíM½~ÑBª7ð Ãð1d–YËo"AìšrH¨±û™'Þ²ô•è{X¾ï!\Û©œçtæ Ì…Š œÏ¬„ÁL•­±/þ½dB`‰Šmùd»¦«rúÚÜ~† ˜àÓêE¾5äËPábÅ“@‡ÇQ5“ªJÓE>x*Xñ~?3ÙÚ¬‹Ý$ƒ]=?+ÁVïfŒAœ¼¹¦$’VŠGýåkz¤k€*ža'm.Ë>Ú*ŠÖ[ ôù… U±$¿‘EGǼ!ãB¼ 5O+.=ã®Pq+ZúÒµ”ñž‚B­‹Záe(>DŽ>J–Æ<êŒ#­U-kƒE‡êÚ2 DïøuVûõ\¯IÏq¯N %4䧦 µ)K(ÑÕíXŒ¶ïJ{f&iÎëDê¿JÎãš—’“Õ‰óÿlŽ7pI¹PqØâ ¶È–ŠF ¿/bV²£ [`‰´üá1¶ˆà!>I‘åCÈäø{Ϊž­“<}=[,]f7»ñÏX„[‰-6rÂ.ø¹Rè1w« å’ ÔªŠ;mèy»·Uïúr¥`¨Vc7,YD!µE56{ s^Í-øŠéu“زZù…‡É%Ð*ž.UÞ-ToÍ`X(†I!¦¹¾DƤîx%‹êˆ}. bN¢Èç¹È’)ù(ÙV·P ý=r'?Öt‘Ý/MÆ1ë5?NZ&/ .ÀÐé0û£v7†ž¹°O’Ïa¸@g<‘[¦Z°IUœº,ÜÄFG€Qă˕òIÚæ¼¨òsË?PÌd¼+/£›€¨¨köÅËJš¢úR½ëÚÏ(Ȱ>ÒNä -UÇÚ—æÒ:E\X¸” M©ªæºVøx5H<Íî[ûocNç/öýñÜ0Ù¯>^‡ýêËF…SâmŒïrå~[}cäUîÎÎKªO§N¦¶$ÓF¢¬¡Ò„ؤ¨}~¿¾-óWîK]éæ1Íåºú1Ä8fQ´™Lfýö\‹ËÏvPòcไǙb’Mªj—øNOŠš²]\y¨:ƒ(‘sfLîJLJD`ŒÊ‰ÀqÌÌX]e–€:ÖI‹¡ =Íú“pÏÑUçá¢TU›âu>OHo¼Æ®±ß™Õ_ÝôOV´ÆûC>FMs¸‘tŒTÑnó92æ0ç›”¦Ú©‹5‚{ÊÜ™{À.™zD•¯`hð»@3¢"ƒ ,¹lãºà%}yvòWø÷?¬=XBendstream endobj 100 0 obj 5192 endobj 104 0 obj <> stream xœÍ\{sG±ço‘¡">‡Xë÷,Eî… G¦È-®"ɲ‰Ž,¿ øîLϳ{¶÷œ#•ÊñjwvýüuOÏ~·?b„ÿò¿Ç{÷ºý³ç{ãþgáÿ³½ïöDl°Ÿÿ9¾Øÿä04’S¸3Lã$ö亮ž·ƒÞ·F Rï^ìýyõp} VWðój}`Ä4L“\}ŸÂÏy¹ÆQˆÕ1üy?Oë{—ë=¹aònuþ~ ?Ïà纾ûzždÃ{»H¯ÚÍËzµüI¹ù‡¿Þnv”ûB ÆL~ÿð$¬ã¸ÎçEžTîæ&jÆ)Üp«ÿ —*fR«qú°:½2ôß4rŒoZoþ¾µüC½ù»vó°Þüª ~Ì-ù¼Þ|Ñn^Ô›—åu³zÙž‘÷áR+;8­—‘hV@´ÃßîþøÏ‰ßE¥Á¾^e)=<‚G?®?2ÏC˜ÕG†š5*=­¡½òôÓHÀ•¨Ç6Ïa}`å¤Ã_·`ãÔá&Ryá¤Èqœ\™ç­(„ñÝH\Ò…U^@$&H ÐF%êåUünü½½0ëá§­‡ƒº"Ñ&1vL&êÕêÝ•®tê;ÝÄáÚ®>®7?nMi¯ÂXnoãáIãáŽ#ÍdÜi-·±¹õtÄ’“vóN“I4è³뀡×,ÇoÚåÛöy¯wZ7½;£öóqãÓjloªíª™˜)¬Æ©{e.Ç7ѯ›º"f%³÷3ŽW„gYf¹Ñ/Ș…i+:òÍN ×Ëå\Ï íùú&è{]‰wv+úþ~šÉ}S·¾ŠÃ›Ë×À‰/ZÝY½ùªˆn 2ïÈRVãž®•9+¶=ªÐ¥ù¢n:iïÌâc¶í9ÇåbV±@E$4„1Ô«×ù*i;çf"Nˆ¨”õ6ʽ&zßÈÉúÔ$´èÉÃmLëñ€ M›ŽŠÝî™\._·×nÚk·¤ù˜ÉD²aåj^òEU˜£Ê‡«¬e­»Á½+ÞÝEÄ“ý°*d…ªÑÌøÕ´ˆxN†"MFL:áœ=‹žg/á±½|Ü<_ƒKO¨éËþèšþU{~É zÑø÷ + ×3MÚŠyÕêü|X•­1ë s"wP,ž÷~\ý’xмrJŽì>þ“˜Øu.¿G~)-wµË/¹Ñ¬¿" (—[ÛûEúýê[–KoZÛW¬ñ¼&“Ìm GO*§Ž›¸ xçá‘iÈï“ô7Ax^}Zµ†¨Ã(Ô:¼õ!g3›ùCn ¢Ñ ?I/ƒ®g¶Ê1…_ÍxÞp7 8™[öóLû ‡ïÝœ#۔Ɣ˜É[AÊ‹Yƒ~€ÏÊÚÁëGËFc…HeVcÞV½ydU¨-äanÑÈí}àtðFdû–Þç…µ40íònÓLÔÃàeGVœÞHÉ Çq0½KKXŽZÅ*OÙ‡ý ~ JJ.ãðóQy­‰a³¨éµÒdŽŽ_p2ø÷·zó£z%Ö¼¾ÓqüFùòνzW­NG”)ŒÀù’S¬fßvÁ±’ÄZË¿•<æd¸L¸{9Ó È"‹f¼}Ä]ÀéSB 4o›'³²-råÝiÙûò’£<]9ò¸éênSùcޝכ‡¤î3iðVßxÉ’°ƒYæp6ÚҖFfDE+ /*¢|Ýyª˜ö¸ÛüúEEŽ—]ËG]Ë–5)?Øo!õ²^pXlq³™þ—„yF½¬Í¨¤Î;_«ÁZmM˜¬õŠà꜕0´VvRÒ»j#HA…#ôeǤîáRO&>ømPJOžh!­dŠ>¬uVÇF­³'­£ÓµWa¢|k§@_åàœ*m¡ 7í©D\ pÙÚHÜ'šíóŠNPR`’Ñ/VË‘o³‰%0ë˜T. PÛ6?fòW´_1­1¾'à)Œ¨ãÄ 4â³è×ä4…!Š_Ë«W£ÄKsÂæ©±ÊdEažt@ÂH‰{ƒùI©(Ý:hm4z=3Í §X; bdN*7E+ ™Ô¦iYV†NÑ ¥&£1©ÂhÑî+ðm‡Ì*is[cDfHñy|êu%]'¶§µ%h}:ŒSsM-mƒp‰\Ë"ë]²'ø™¤ìƒÞÞLÑfÙ•¹Šœçx‹”ü’šTõ&YOè\À¡¹)ˆÀÄ·©«PaôHî³ͧc*Ç´YÀ&‰nëD}"Ÿ 4½\KRá¢7ðbBá—®œ öÑU8÷ æäç ѫᚋm™a{$ø¦µ9¯R­§ œZÇa  %MJÏÑU˜(ÑýoµBi4ë  $ð½>VYOK¤'OAŒÍ‹w,Xnng4µË½FA‹³Ävð®‹Ú‰:¡³1Ö¹b P¾#ŠÌ¬A³›I¶%ùSÔ ¬äx (þ˜7y¥‰Š¸Xfr:ðÊÁ‰Àý| PÎë©V#~=†.„nÎÀdï³ÄNÄÇ€UåîÿDfè¯IªƒÇlR–RúN£h㋆¸”‹›ä Fiš—ç Ò‹ã"dG”p §±eÎ%€‚&¨µ³¦`õšù—l»å\ž¿‰kÑAœa_$øÞà9Xùë-z“ßΠ/ oÀ?¶, ox¦½±Y*eçl†Ù‰E°»ÙÐØwgC•‰b¹ÍFÖ. }¤.vªkÙ$_iµúv­â‹‚ˆg‘IðuZF£v´6Ò´6>)m`˜e“Ÿ—¸èÚ"Vñaêã"=¬Xp­Ð¨Œ¢m|KPÀ…ÅõIƒI ¦ ‹Èn—‘ä„„±ƒb¼²âYY7x–$ú)FM«¥`en…pýJŸ5Á®$8¥ˆäxÕcW¿5‚©µ¨éd_­å´KÊôBÖm”Ñ(í"ÍÈ^ƒ‡¢~¾XèÏvÆEN pjƒvCÜ 3¸ !ò ~9žêUzQNG°>¸°vŠuk5Fe ËO=ž*ôŸŒ·u°je€@…·HüY"É4™eà“×ß›‡Qa‰„HÂ"ëÈ*,« ’_%\§iý‹0¦R/[f—¼v,n05 Qóÿ—†6MêŒÑ±fùqFƒÕ¢-Á |Åa§JË??F`• †¾Ò¾V2RÄ'¬dÖnV!©‡äCÌÕZÞ_+I´Q H:õ[úÌYpË4HïìC!KÀ@œ›E„ŸÍ-!Ýy˜ºIy€ñFUª‰€Þ–ÃO÷~Æ © 7Oš"&% ážÇPºLZ<+‡ÉFýÃd7qëZ.ùc‚ËÓTˆNd¬:ÿpicE¢AÁ|ƳÒ_;Êé— %Q©þ%‰˜¨ B朞4 ó¤½Ãa—Y«À“4‡ÃLìã Ü––ïƒßFp¿m`£ò¦ÏëÍû}Ò¤g,›vs2ôÙëBöн2§ƒÐ;ÙA(ÂFW•27s]ðé*ªv•ˆ€Ä‚1:’tañ™S–ŒÎÏ'©Ä0°“Ÿ¬á5i=XL ˆB,€9d: _d>ÎkºGÙ"ÝmŽw³K—Š»&k…¯F”Á¼ª9A;$Œyµ>gn¡û=¨ì€6ß"P…JãÁ± Äð­¦}”í†;…ÐI|àÄa“ÎÄH¸ï@@Í1Ÿ†iL’F( ŒôNó°– {àUåçAu„üŽáyPKüfzzMESafòÑô,ü4¤d£ „¸‘„ÁvŒKiÆÖ)²%Ý„ŠÈyß!Çá‚Iswªgè1zé!°Ï«ÐÝdÜäѶõò¬*°¯²›¸V²+°&¸1‰óUP ÛGy&¨˜é°]þ¼íK=äpž+Äð¯͈&fÞs †hÛŒ~ßfôÅæ2œ±‘bVýR”dKª’ÿT¤w›ÎS¶ÄgP$“tŒÝŸø ½|9—2k—µ0kP—+"ù1ƒ51coÀìÛ’«­CÄþaÏ4 Éü£ºT|o땊Н3 èRJ5ù– HR0±I‹oA®9.6áÏ ùWšü¥Z8;wrcŽGàF+<ΜÎÝUòs웟ޕ„®Fѹ¡[—À³a‰FUqX¢ÇdÜ;ñ¼Ú¼k ÊDbèR¶³@†ò²d´01ÿü/ dâî÷R|Ák~…•@Æq³@ûÉÛ6îJ&«dh4%mù!tçÜ@6_ÊLÑ]í6¯»D32•–Bì'-¼®rÊù`WpêéÑ‚+˜†ÉŽÂ2ð¥ýƒ¡ç“'€¤ëÚmˆwÀsÊÛ¨ d·!o.o+µ¸U4¢Ü8ˆb‘Z™0¯*#óö•¡\ÍŸäåiZ0oB .Q‚—h?!ÍjCyHžko£*wÙ+mÑÎøâ^_ÌG/ Ý·*,Š÷Â#Mÿˆ5µŽ—î»ØšÿMšOšRQgÇ'eÓ½d§BH<íP>‘‹°X,¨J5=H*¶¾ÙÄÿÀ" Sy;P^k‡jnòæ5ߨ躖”s3Òy®ÔbcÑ¥PX¿¹!W ¶@Žs$‘3)[ö›ˆ°Ö}Yé;81“Þ™ÅÇÕÚÐì@õ‘˜TVÜ6›­ÉûÍSg‡rêcÛn.B³Ê‚œèì“‹¥›¹Ë¢tR:2­t&GÇÏÖPCwÒÐn]%ª ›±×Ž™J¨qú}s†úrsæb'û/7êGðéÖ㺛\OðV%¸¸÷åÞwûà¥ã·|àBŽPnÿÚàÉ<|è“{÷|¾sýâtïÞ÷ÅÞ½_ÁÏ'_|þyð‹ýïíݰÿå-?úOØ` Ò‡ƒÚ zŒoÓé¦àË+‚PJÿV¤ýÚ‚–NmÏΞ°{»Š$Ì  \¦=¯*•¥0Íl¨ú&{¶»†"`‚1ËÙõ-›å%.ñ«]¢›V§Q6ë;p„6•·m:o6)@ë7ã#\:¸½øOx(M›§b&Jæ…l â6—Ÿ‚†Ä¡»¡Xn4úyÞ4Ûb}ÇBø,BcÈöo+«{—ÔåR)Õ{-ÕËÅ=\z Õ”"3¾ ‘gißZ:|La3Fµ’:N¡ÅεÃÉÅ`¬ßp¶!ób'™e»nfjØ1+…¤³Hb)b&Ÿ³…éHåê;w )ñöDÛ I)(WÏ=´‚¨…TÕoÖl£ZÚÎG–b'œgæ*®(n†ÊA ­J¯ ÈhN~ ÿ5œÝ[VERf³«¿…Y®žd TmÒ¶©.X´o à ïL8BUÉ’üíbЧ0²Õûl:Þ•nª·1H³tçýWƒ‚ y•qq·m¢¾+\ä:Z5?ò¼M-6£ÑÙï¦9vn¯’ÁniæˆE~éý£†TŸÑB^a‡IL}fn)âÍx`Þl6*AÁ5ß6Í¥A³‡WØôz¸5Fö5õ2?ìý|` çÖÆ:á<¾|ŸÀx„Ú&aÀ1$dÜ<{¼}è¡}ã}Уo æ>ùÇáêT˲ô‘v‰­ë“6´¹MÅ; É]Õ!‹\ÐÉ0ð·¥WµPåÜ;\Tê ž޵ k èÉ^etnL&EâÖ“>·e¶>.¹[…49bPÊb½‡ÏØN1ôM¤ ^jÑÅç ƒÛºšTÄ!Ž—°ÇÌК;?i¯A.šrDÊKbk]}ÛÔZyýl:„l a©ÕÙM¶ã®–[C´Gçz,7¥’l 8ÃÖ%Ì3Ý}BÚb‚¯Ö4Õñ@¢ÉoßTB@†”Õ/–ÝgÞî˜emA¤ 0°‡ÝRf«)­³÷eGýïÅÒ¾8ÌmY|ÄØ,>Ýb¢\èY™Îý rðÎÀÃZqF‹µURum¸Jåÿ`ãÞ¢¤ …P|/‚é‘Ëù›8QKäõä¿ìà´ä¨ úät¤LÍ·—χl¨(ŸYRb U^ÐØjá8KR?Ø–ó¾ltýzU% léèŒTi© ¯-H†“cã!Ô¨’‡J‘ÉV%£:éÏ·(CÁs§å§Cbú,Î9aNýÆê}»ÛöTC\Ëcm3_²[á™F8µ™¾¬u~Ú'¶ã‡·ê'´ÑçˆógáZKôý©_×›w6ÐQCC_¯«Lp á|T‹ßʨªÏñ«} ÝG²†r³~o¡ï‡~ óqb¿«EXËÕoÃøã]þ¤Ô6oZ ñŽÒ%Äé·8‰ÖÅS‹Pg€êÏhùå®#%QíÉ—x0bÔ}ÖÁ^êîŸVéëÝd·Ð¦_S©bu5Ö3v§zñûaÉ[šÜÞð9Šœ+á±Õ<ùM·wK~·Z‰–)™‰94jߘÿ èkù)ý—*æäñòÏ®i;472X,yq©!|ôò]ƨTÿÕ¦ªl'lÞydž Å›‘žÞµ)ŒijÝcÝb°f‚ÜhTZ¤òíÒqº˜îúrïŸÎÉLendstream endobj 105 0 obj 5755 endobj 109 0 obj <> stream xœíXKoE¾¯"~Ãg"ïdúÝ}à 8 V‰ Èöú±Â»v'Æÿ>Uý¬žé]"Kä€b3®®úꫪy·¶ñ¿øïùnñêµY^½_ŒËàÿ«Å»óËøÏùnù털ƒ•ÁŽ-×—‹ð6[Z=È¥Vlàr¹Þ-þè¶ýJt{üyèWйÁ9Þ]âßÛ¸(º÷ð3Œ#cÝ[üó.ðç6øó6 Ÿeá›ôg÷”w/ò.(åp˜µº{ÓåÕ˲ºÍ‹eñ=‘´ð ˜!‚7E’Jv/[šïZšïóâ 8btðlüÂâm‘ÜçÅ+䣗¼Ì‹Û–NrÛ‡¼x_oóâ#µC:38«*;þ\ÿ´pªÑÑõb¸/zj‹ˆ+‰Iø(…Ø”ÏËãu‘=iÀÇ“üˆF­ø8Š/WL J9Œû|–ÅÚ†¸xú~õa³à.Ó}Èûût¶•¿æ’¤ âÌ¢MqñºHžÒX¦{¼@>œzä!œÏà‹ÇLEä¢" ì©¢Aa÷¢²YjËî¹ÔѼ¡'ùüg_‚>âAÿ}$í7‘44¤'K¬q;‚ ¶é‹ˆ¸eÿ3ȃA^½f–6!+6ŠA@àj21ʯ`,ì¡_pGèA OŒsÔÏ FsïV 5ƈŽûGt…„@B·½B³’‚‡^ `Ç`ñÁãi w¥Sµza”×yWö£^=JÐ+ ;Áºý ‘ ãtQº¡Jƒy3.nÃÛ³)Ð ¬9ǺØ&¼Èƒ¸pŠ€5 î,k’©ކx(@RÚ(OE˜8 /-^.øÃáÉ\WPåY¹FÃ&¢…‰#±û3nÂùä źçî4˜ùŧ¡á†Åã4oX,ÜšËXÃl4pŒì,¥I$­. ¶á% ÿU*_B¸qÙÑ ç+Ô£µÑɳc‚Ú“Åö=gà%ƒ1= à-;a¯Çž»3)A.&GƒP"0½ÅEI©ãÙˆNõ]8m¬Þ«€/|—È#Ä|*‘ˆ¡¬/@C„NË9åðÃajxò±†ª;ɺ]P®µÿk_'„ƒ`IÙ½h+OÛ:“y¨¡ò"w=MfÄ)1lèWZx`@X—Ìk¾…v2IËÔ‚o#¶¹·–tã €0)ÊÅÃ47díî{GñK3²‡C‰f¦‹ztÔ&øM*ëÍE1hÇg œå;qmÉáÃYas¸UÝþEÄ“<‰éNJÇG’œØ&Y”°„m ²sê¿h±2Ò DOŠœl€i‚]/ðr2ôŠØ´f`­äȱ*£HU‚û aN°:£•š^„?Þ!p¶fÒûBYŸ0瘗RiCQ7!ɚ͋æ&¤E’{Aß›DÏ(=äúÔRE®ˆ•ZH;°±&áàt_õñÊhòäm Îv„»WŒT`„9)|á(•Ë3‚îºP?É3Ä?¶ºÐ³2ÞFýU_¹A`£«’óAH…Ž,ÌŽë%ÇÈÁ$K6‡5¸¡¦xÁ SìK?²9ˆmí=ÒóX#‘LJ"&ºï{`&c%K‚f~4kþà˜Ÿ§˜S9»+–´£¥$-H‘‰Pb *ëé¥È:(ƒyšŒb”u|Ô[w¥ø„yœTЧáˆY©Ó"Ñ÷êb€}°@b7nJUÄF9VÅtÙic(Šx¦ø›yK=H >ïVmÂôÛVCuHÊŸ9vÕÓ`’}ôã\÷ušÕmÇN_BËÁñ á—Ñþ¾jùË,ü`ãǬðAð>}·2þ\¼ çŠÖP`䦹tû“ºÓ­;͈à–!>0= R„‰]ÇÇ¿4­cÎûß”—~Ï‹?–Å_ó";:ûÂ:uL]áñ–¤â»Ü’ÊÔ¢52›8ðjÚ?gös*Hð”kß F&'Ü ðOšˆÔáHíÏ)¡4Ãhû¼ÛüÑg­ÞvVB/•¯ù±Wª-·"M'Òñv±„/[,ù¼Î&Rk rÌúÞRÄ ÂEx  F"0"á…ƒ\ÌÀ€´žˆv6§¢&y÷×Ä͸ýDÊAC¸R¹;Œq%u J4£Ÿ·~%P¨m˜]RûFáheˆ/¶pül|9úî•ôŸ?“žÄ¥fhœÿл•Æ—“û/<¥Åf¨BIeè?™Ñ´Ú“þ yò[—ªùK9D³Â;gÖÊŽuÒŸ³äÚjÂÈMMI‡Io”E7QSœƒR'ÈZu-Ω¢-dÐÁûÓâæg¯0­ÈŽ‘¤Ø¬ÕõÐ.SlýUÇ·Ê–~ŠQS"ìª9ø¶`‘Ä­4ŠáƒOMñqš†šÉQ^ú0kgïg_©ð%<”Kß©T(KªZ-Dý]µ¯r“yèYÓÃ@Rrl¹’ÆEâÄà Û+Üþn½øþûq"¤endstream endobj 110 0 obj 1916 endobj 114 0 obj <> stream xœíko·±Ÿ…üˆú¡wo½|“Š¢vÜÄmš6©‚¶h‹B‘c[°-;¶•Fÿ¾3Ã×p—{:ÝÉiPAΫ%—ç=C~·±ñ¿ôïù«“û_¹Õ³w'ãêSøÿÙÉw'‚:¬Ò?ç¯VN¡“Ð+!†`Œ\>=‰_‹•·ƒ^Y#©W§¯Nþ¾Ö›qP!8í×ÃF Jy!Öv³BªÁ¯?ÛlÕ`Ýèôú[lžÎ6zðfÝúÉFB«‘¬ñ-|áá+׿ßlå`„öµ_ÓQÖ‰õ¿72 Æ µ~ @èq”ÆãçrÊ ƒo•õL¾~L#eÄú>쥰ë?B¹þj³Õè””|°« Þ{l:P´Jg×—Ô¨„aÀ½ƒwcJüóôwˆCXÂâPް˜V§ŸŸœ~ü÷õ)¢Æy1ªõóÍÖ Zë€cm•4ƒÑzýÆ·`2ë—0¶sNÕ‡×å e˜‹Üpdz£]?ƒfíDö[\„R:Hïªvz¿½òVŠÙ$ OPóS€~kø`±]*ÜXCXWð©ô'‡µD ]‚T&ð8¥ÊÆM4™qÞ€d¤``ØñEã Ö|½ÙŽƒ”°ý6Ò‘”.¢™ÁÃÎ+w-–•¶´ž p%R nð˜çô °ËyàªvdS¦GÔYJs€té•´ƒ¢ûl#ן #ygÃúkøk À‚Ñ‘ødàÄ·Mpl‘¸LðœÁxåG!Ðß@0ÀÇMóòϾÛ~lºÞÌŒpí‡KGwtC¡¤~ÒF‚’ƒÏôtôÌý]ÀG Â¥鮺â"¶q[¡€°Gs”\…t¢ºK”‚*¶ ñ#2:BñFB"¶Ò»çøƒÂ†„@쌟­ßàÏþœçÏbë?ÖΧåíE}ùžÔ뙩õey£kk†ÑÇååÓúõ›òò}}Y¾Éí‹òò²(bH±á_Ôöº¸ëúò‡.¿ü/x¾Ê÷$ ú?ÀKn§Ýæl&ʶ<Ыúøº’ÍÛäüøböû¶+É÷Ê#–A™SÖ~(ì®ü¬÷òª‡×lòcÏØ iIk•%ðW¨ˆ|ݘ%¾pž)侚€UèQà0¬ëÄŠ ®´IÊC·³¡^mXAR«õ7hn ÚHËô<Ù`:xR‰Oq¶mÜøiТ0«qV2•س)žÅÚë;QÏzô¨Ø—óÄl>ü¸Q ôhUÃÌÂ~ [nðÁÔfIõS»Ë’ÈÞZgu²‡ˆ_¡ð [ÈÙ&ÜÏ,-Ñ¿ ¬Û°~„ˆ† ¾ C€æ -¦èÅÍØDs#!]$âˆ)Åm8'<ëEÌ–ÖAÌVŒŠD‘0Eˆ1$p”дC8$ÃÊÄ;`´¯ÆŽÎT¨¤ s«R!çMcÏÚÁ;`lD:¬Ó&ë À »zÅh‚ÙàGÛk™8ŠÑŽÔ‘#"X„Z¿1(µ€ß93Kß~S(ï³y\½[ÉF@NqÝXîe¡·áÂh…ØÁªIx‘-†ãt«•CÏ,;>öõy%ºL­=ãU£™;Š<Ù\“$Ý™ÅNM‚×µï»F}L%¶)ˆ>[šùM儳–7'D]x¯2syU¿Š<@&[•Æò©„ìµÈÿ\ï‰ÔŽ{ŒÅ(¼rr ˜¢x1T|(<Ðwø¦Ã«’ßSú¦ =×ìLè+-‰ŠZ:.dzÕj¦D±æ"›DÉ…Ž—WŸºN {9¤Ézä…è#ÄGÇüÿNÑÿ¢Í)ÂYœ;Ž·rdîùR&2˜?eV‡ü.)óE+%¯;Dysh©¼ìĖ쇅Oz¤uC`äºÈá3dÊ´%Ô~Ù 9‰BM¼„I |U‘õ}ÑqiOz~ß[ˈ8çêåH¥ÑòÞ\'½êÍyÉÉd¾;>h–§Œ)Fèæ ¸Ñ‚2f2fm½ló²eÌÊ…c™¾ÿiG‡¡&U»›\Ç|Ùëù®.T¬÷Ž_6£O4ÁD¥ìæ=Dž0\4ñpÑc¢KN¹½†ä[D­¨ZçùBωr.3!u™ÿ²éÃåG [igj¸*“tÍÆ›,v˜ÿ‹Æå\œ5«`uˆƒÉ‚‹.!MÅ‚ŸÒ~2©¡sþ½›ó;òDLÑÛj(¥s'…:X*ä8kKKà½Ä˜ïÎíåžÎ°ûxûÊ íý ¤ìÏÑæfÚÀrœX6«£wzG"&Œf Ž/½Ð~„\¶¸ù:4õùÝ€ì¨)LèŽ|  W`¾m)0þG5°Ì‚Êqû-æ pz(ÃÃeÛ1ôl¾Èµ i(–]d5L]hP¼ÕÊâ+…b;PéG]Úd‰$!c˜§ún“9ÕÆºÍÜf „³”+Õ xÁxSñÃ0‘ÔI \ÔÚ4Êæ=ð'ÈLžÀ$Î:€m!TÉáJÀ”ìQtOèW“iÁjš {y‰@V£5Í@¼€£ 9 ¯žâ|Ýæ‚r*ÇÙŒ•Y/'eà ÕÞiFùh¿PÀ¢)ýëj$ôQ’p즆¾c´rÕ#áÊ™ž(¶’”pÝ¥Aò\ Éu ÝúÝ÷Zg”io¯S"6C ½3j‰[st,Á†ýU`L*!Aº…œµõJr¹ŸI3€3 c<+yâ ±_ö¸ˆµìÊ5/4 ì<Úae†nÖ¿-2Ü&$´:a±°UúXA)gu¡4+Po§b4·¨Ù¾É P‚݉1$½£ ê.’Mó- pZ\›Áìæ„S^2®Ë%ɹZÄÚB•n]ÁÜBázY¿¯1Y Xü ýNêG*Å 4¯hyÞH匳w•@-zF.ôcºÆËy~˜ÔÌ<©¢«ô4º¾M ±^­Gئå¶ÿÛ'Ó^ùòˆ%ÓÛfíð›TOK}©ÂF‘M+ØBÁsQé£W›Ýˆ’\;ƒÕÒ‚Ñ‹•öbðíÔ.á"α¢ *"L(nžŸm&úв™Xê1u:©Î†geìÏ-,(AÉ®áò¬­nºH’]ÅYeöX !×°NI¶R¥$F£g¨®=ÏHôÏâjÇÑ炬~Ĉ»¿¨8HXÕšSq§J¥pÊri B]Ñ•$="eêZ3I•ý¼rqRŽHEfNgØ5MkG½`Ôüä±NŠ˜Òà³±½©-›l&²L-¹‹&Å#ˆE^<",ºAa" þŸ9çù 7gIMñL>ëD$$M—öÄÆóV•0,Õ}Œ%>yÙ=‰P7´Ì}ù†¸‡-†Œµ_£àB¥­m”r‡jùy-¶ótò¥-wŒ…K$ñøœU.I‡¾¹ï½ÕRm¦»Ñíº¬]ÛŠ?œVßµ yÉS®¢K¢\ |}ªŒŠÐÎ|„-wÙ²e”Še $âl©·•‘t³æ<¾Ú3eB%:;-{×:NV0Ö¯<›Ù™ÄŸTæCb‘)Gß}g¦ôŒ\¡t,ïOÇnZvjuF®2[²×rû>·ÑážÔòÖ¡#t<<6É’oCDZüq–_:GÕ+¡;ÔækÝ5Žøè”(sat¨†" wxcÚ­Áƒðû:_Š×¿ÏO5SÃ8orT§¶1c3Ü›’4m«Ñ¢‹±Öá´–·dËG=q…a#É-Z éH©cг–oGKˆé/¬~–¶!§%h¢˜l@ãE•ò~«‡1ÔÂ1´Å‹|KøOU°®-jJјÑ1v6eÞûj;]µ!!DkT\§ÂËê½^ õäUŒ4;k?º€že Â*:°yKŒwTFDª¹Í)QÒš b —€!FØ|b<Î5@3!Õq-€Û6îÂ&ìºÕ¬NΉ¡8Û^^ã§<ð/w•üú0Œ¾DˆO‹|ùsMíÔ—_Õ—ËË/êËOk–*6ÖÆÏëãk¿O›!óãÃúø›Ú·ŽÐu©X¢ P# ¿BPÁˆšúU̳Ásãu´Ñ=ü†ÅhïíÖµÒlÆœ¹Lºc«ôØœ&¸åÔq.F-_”—»§f1åx†ã _ßÀ¥çqû»°è–‡º x³ß¼öÏùžÏ÷áÓûpåÅ~{,¿Ù“&Ž‚%OöIW´1t=èŠÁG¥ïÞL² †–A{ØíõíŸnmý×ݬl›#?8Ì?˜ÝöÄLŽjŸV‹‰A’æ“$Lçûý0‹;\Â¥(j%‹€wŸUƒb[Ž1;í)QóØÖxfM¢Åóûä­Q°$(‡8Ñ1ÌF¥P%™mÍLëg5sC§ Ëfx#ÚŠ®Ó/€[<2hëÉy³™äQ&ÌÐå–¥(~4@UïK,qÐa)¹ÝŽ™¶UGŸ'èMß šYµÉ€F¯ÂÇ„òE‰×ëJ®hòãU.J-Fbe‚¿Á^èÍ ~VÁÀÅCëNÀªÄăüí÷ÙY—ʣܭDlÈSÿ‡á‘Fw…áñ~½o^O:s¾°ÎÎåLŠv”‰öoç8°ž@¾ÙSP6rÓbƒÀiLéYÂ)v2áh‡1)V·È1<݈ëZÝ LPØÕ£,I ±óµ´Œ•/×*³¶ˆk—Q1N{Ç'7p¼’0§#ɨ,–þØi˜L#ãXÎ ói"7^žªƒYÊžòKWížbq1̉âï°£ž}X¹èpÆXŸ<&Ù„Äx²‰ ÀBæ&ê¥bÑJ‡Ó`[0"}‡G›ØÿÑ®­”ñæ"Ý(UÌy=•ºÞ_³À j½&’ ŠÎ"AX†ê.³à@JL‚²Íݵá©%‘{”±#å¢ó™vl6‘ê&#£«x‡ ‡M2 X"iŬ2QšXW²˜W1 sGJ6LS³ƒË°09@/cĬ“QžÚqñ"Á®„=ìkåT˜%UT!Ýh4~ÒD£¥ñd¢¼nÍÒ6½-l•:…®'—.Ü$ú…ÞE Hw?ðAnºÃ¡¹û ÷Y¹’k./†žú¯XÉÎ'fÕÀ ʇ{W‹Ð(l2µ%K;NÀï—}Èù”Y®<ß:ÑÝÖŽy!ÍT°vÌ ÚVÝÓ•ó]EZoÙÏÊ®v J Û~ê`dǾÚcl_³_×nìÎà {¸§»/]Ó˜dšÞRNt ¯Á€íeÎæœœÓt±š‰K…°tâé¶s¶Iw-ãu.Kr!·ß¶¼7ûBB Ê”…äÑð6+3§´¦¶ršßµ ZYò‚.–ˆõøûмRÉþ(âG7Ù¯>½,D$8½üȼ„Aa(ˆÒ+ñš§ÜT`Ú³S×R%È4ô0rQt½ñ.6¶ÕÊ©Ùu±Ð¯;íz€‡ƒÚvW¡GÖp(êœ!‹+E푉r]Fˆg&uÊK²:ÅÅZ°I]†r˜ÇU‹uÊGonâ°$ßsº r¡§å³n÷‘ ÞÜ 73óUGþycm*?î«8C1Q4‰€U):I.Ù,Ø£³®ªû–À ðnçbN$zã0°’_VKìÀÃ{Þ¨Îÿ²Vz”]œèùt™\WÖ7%ŠoëÚªx>1k¦ó\gS&oÈcó Ìô‚ØáØ"‰Ì»»â3~œPu*~{‚…Ù41»,îÀØ,¼™ÎÃ㆗@~“<˜FÍô|Ý@ÂïÝÅ=··»l– Ç-0¾+Î÷¨ØEú(À±Ìa@¥DÁ—Ýq+[²"ýr„ɧ„˜Và³C•MÚ͹je:Öá]Ôôë•fÅdý} Ýÿ-…îž|yòÝ ˜ÕÓÅÛ[|ÔÀçÁìЯò~ðøäþã?¬Þ¿½úöäþ_VâäþgøóàOáŸÇŸ¬~vòèñêËÅ+¾'æIºâ[ò’€QÈþ£[¾¿È ‡eà,,Û~xà¬C[¿®$=(3I¡á’ëg€%fúDµÄæ÷-0u'iÀn¨^*L8uàZiŠÈíu1ßíDB·¢©ØÂ{ûö `e¯ÝLX¸}ÔIÔ8vïˆB[Ñʆ\–ÄXÝêä²$N®ì]TÜí—) ¼5e­—±]áÅEàõð½é[y%h" *ÄïQu½€ëK«/ à’\º¦ÐÄ#xâ©{è¨ â²<Çy$ŒÌ»s Žà%eD–i“¸:–9ûÉU?‹•&®íž<­¯Z’¾¬„º¤—aòàK×¾ñö£ò[šNy¶ ÙƒBöÝâÅÆóI ÒTbçOÎçŸLÎ’¶>‚m&Wí§¸ûfáüâL Ǩ¢[6ųËTYׯrî˜ê EW#œûŒàã[ÌjK‡²„Åã¯acŠöüòä?¿%Ÿendstream endobj 115 0 obj 5170 endobj 119 0 obj <> stream xœí\Ys$Å~—ý#ôÆ ±jºînÞ° Ž0+Âá0BH{Å®¤eA‹÷ß;³ÎÌ®ª94»8‚¡Õ]]GÖ—wVÿx:âtÄãÿ/¯O>úÆ>ùéd<ýü÷ääÇáœÆÿ]^ŸþéÉî ó8‹ÓóÇ'ámq:ÙAŸZ#©OϯOþ½ú~}¦òæyš¬ÿ{G!øãþÏ®y;2\kä .ŒpüÅ^C§ÅÁ Ý0OfTïô€ÿ9ÿû‰œå0Ávž_… µÑp[­>l½ô²Õý«|ó¬qœ‘P¤û›Ò2Ó@­®òó ö|ÓÍ7­‰<ªFzu™o>-ï\䛯J˲Ìç” ¸¡JÚÁÈ02ø ë3]^´<*w,02ƒ ±£ ]¿Æ»Í;~•fgüìÂcœ<îTœì]F…_õ8¶»¬ZŽ~wʪ/KËÛ|óš­ªš À P_ÏžŸ¶î}ý§÷þ®çïÖéÒW›aRóXÐS÷eÜ‹H{·2ªÉ‡áñ³ÖBÈ’›-_P‚{fö÷ÉŒ ÷åó>* vtfÔú=3¾£Ì¸Y¾¢$Qžêa÷^%ö³[má»­šì0ΠÖ,ÔȽô>úê²Ó2ݼj tO4ÔÌÈq‘.90"2(ߪΤ„˜ç{#ã:oöUn÷8Kãï)¥b»ëüó¨CˆûÀ%!cWyþ[À¥!Q©•W ñ"F.:§%Ù0ÆÁÙ >£>¥Ô€Ë»Ô– <2é…ÈǶ„RKáîô0Ë…¥ÕYÀ¼‡VÙ݆h ø§^ÀÕ²mSçÇ·õ‹}R6¬ Ë÷þ-|×D%§òݤïо {€¥3Ì(iAôÂB`ÿ¹Õ9ç§¥4öÙÚßñÔs•rÚ Æi`Sã78@Éh›Xë¬ö ì}d¯y XTz6¥7¼ç<޵$ —¢Œ_äóµòMq8 -…”Ør¤Tn¶À*r†kçÒÒ„Qök;h[»‰·”ˆ«pJᶦYá‚è ­ù]W* Ó2tåAZºV~È.ŒG#·Žs™û¸+ÏÉ*⥖ w³i¬t~§¨ËѬ>[ D‘žW†0¦Wßæ{N 5N«sĉ›¤È«”žºñ!5'Èÿ1z‘„p$½/°2AX*6kŽ€÷<(–¬ˆHØU+hõ«ç%Wc‘¢=uYç ºr~WS›ÿ’ÉåQ´ ÉM4H¼¦Â2:œÒ`Ô_ÞÇiÙ|YŽŠfN¢¨qθvo‚°ý! ×H"€ŸR+4—œLòý½H†a·,Áh…î`œ„êB?mûú(vÀM©ø¢5ÕSE è¨Å@EåñE-sŒ2)ªÀðIâ|31ž¡o^P€BcM_Dc«ÒS¸û(™¬Ù$bŽÔñ€f­VzõU6"8qFv†}éX9´u0?yÖMÂz§œ©yÝ2ÓY0­²ò[6-,Ý I{}²&Ææ¥H¤»CÁ:õ5n»5”ÏæG¥íFAùÇÁÄdBøm覮Äï$ñÙ4›VRt/௅2 Š l±7*ÇyîCÑ+çöÌœ¢LEpÛp!*åÎTq†( FÑ~cÞ'äŸüz iBŽ Çi·P¦¶·;ã /9W–»àJ¶à’òu3@yq%QÉne¢WZ9¡_ /[»è÷»'WކpQá“§¿ì09PTæÄYªQæ>µåÎ’éójkýQl—kÈ“Y@ïo< pzãIb®€meTŽÆûZ€Ù 3aâ1=ÍT¡Ba4Ç1кңñh\Ü8gK ÌçéêXJ~Æ»q(Aì72sÃÍÆJy‰ 4¢žiOO˜¬Ùkt¥i6]2äe˳ÈþZÚòN%!L¥p¿!=ÈÌÄ /PÆ6õÑ*¨JšÈ$”ôÃÜìZ1=H ££à—ËÍ%œ1o×Êë¬Z™¢ä)í"ݬ>ÁUõöÕZ®¾…ÿ¾æÀ˜nŸQ°øFqÃvN{,# È9Y[éÅòjÅFfÂÖÚ÷ì˜Ì”bávÖÎáÑ9RŽºÇS ÉK'ÎyÞŸ›¨Ëú”ÂÌ\(Ý"À/q#´’Ø.½}IaJ mb”wöH´ø†.q®\à­†¸ÙÞjвüRìŽLçå"„F€ »ÁkŸ©À½)VË"PêÅU3PÚTß8»âÊX4 „}žXiL`Ë×à ‰³MýæwþÍs²[Clƒ["lŒ³-é™g°ºÑS¢©±ž-z•År²ÔÃŽ·:mr>¶H™œœ‡.#¿ár#¼È•K+ûëpiàÎ٭ξ‡Úw=£c\š,˜éåH8[$Í»†VªC—MÒè\?„ÏJ¢Šµ])è T›`Ö#üwÊí¦iP–ËcÝÒ$Œf¹BC`ñViÚ²åAŽJ7»2`«ÎãUIº\±ôÊÒP—ãÝYÇ·tž*†°ãYë&zu¸…%ª[ÉE™]ieË‚ÓI +y;tÑGêc¸ès„ p64DOYÀ›ýFô=¼{®ÑŸ"'O6ª¯¦&#Í? s‘ÁèlêíÚÕQ³X†}[ìòCCºÔfmpW&ï­(‚m,a$µgÈ&STe¢2£ƒKB¼žsœÃL_„É4ãý¤'â¬p‘…újMè]¬ ²à쇙÷d…ugMˆùµšÌRϤ”5ÆX…«sõ%‹C(Æ|›¤‹…í£;Æ/þºF9iÁ÷$C4ØÃ¸0 ]Al JcÑ1D$êô®¯ùK[ L>öqD­v®·´¤ùÕýØGY¹Ü -vLˆ,»&„6AC-ö¢N¢Œb{ïM%1$üà`¿ìžÜî…\|\|ƒ¢õ#9y»agù®íµ·l‚…·i¸ÔÖ¡çí•DÌû¤7ZÄ}’½m0Žàn''Ç–(évUEý"ÌÔw_â&”ÑÂZä@üWE£‡ä|hÝP¯ƒôÖ¬ÆH&A iÇjäY04€áéHذΫ»´zs”'lê,ù>Ù5Xµ³ÄøŠK;?/y_¤+;ùŠŸ†°D¢é‰ƒ?goô@Žžh,]LÞƒ`3Æc@ó6[MXé•Ý+ùˆ›ÆÂŸ7­XTa’Lq½4ë™i›(Ñͽlqžûµg~U4rR¶Ñ‘ߦë«d&vÇòC7ìP1ô6L†ß]‹/:1ì½Ø#F"Ð èöóÔVM­¨GÓ½¬_¹õÂ10ÁLªæx°«¯ ç0Ëâ IÌŠ™ºܲ©úC3-ÜÌÒj°Ãtú»u¾;ÐàèÒ =‹«<“àN£È§ÍÞ|\ð¾Ç8YøëU—’ÜF©LNs÷+IJF#EÀ:ôf÷7…² ã…Vzýˆ%ðu½É"lÐR>²Ù žÊ§".I†ç‚£´‹B ª[Z;ÛXñ6äÃb¢„/÷‡¾Tƒ$2õ³âÏËåÂýó&sp‘¹ ûz°$óyHu“/~£ÅÝËã8gKG%Â_äq¤þ«Ðݤå.ø™oµ þ½peg Pºš`âõÒX¢4+¬,¬úŒ„K¨ Ö“7µâFÒ#žD Q›ÊؤÁ°­ÝÎ(mb?Oà„N>³Ž\.fŒT*U.©“ÆÄšÄÞ4üôdcìvm…O«YÒLW)ߺf R)AbCt„‘@ž”w“ʺNy·ÔÊGž7e[¥Æ<Ì®‡&r…¶[žZh/Ù™xÝìê#)Y'¿wÐ Ðk±:e¦£ôvb7‡䙵)ÞîžkšF“€…#jœŸ ßp”¿#éÙlG "”ãµ—QLvâ;”@ù2Û=ævß¼ÞÈŠƒšulÞvÎYÔ±Í8Þ2½Ï«0—µ§éi£¸šê~Mi´+¥ôYëëµÑÄžh‡/9Š2‡—…‰KCÎmÆÖ5I:Â!TKm:陸è¡GÍRž€5KŒV}N»D-dPBRÁu¦¼U ä;_µ•óþÛ µRIO‘Â[*mÓ!#yR€eM6dÿ·n8ß@¢|ˆnzpÑëüt_áqÍ fÐ>g|½5¼d^͡Ұ¶KøÖ«(ÀY©<‘¿{W[Ô½µ·ì[¶¤M]¦è{·-+…ú¹‡ Äú}*HšCaU¨Õq6U·ÍÀ"ÔÌ~§ÅÏ R¶Ï]…]}1Øî“÷E¶êìGÄ]¯r¿Q¾È²±¬¾~V ­Ž•ñ·kžr“´•›rž“èç<þ\H‘u¼!5žc‹…]-™ÝŠ…t°"€a’Â8‚Om²þ^›5xâ/ošþÊiN±Uó‡5h %¤pm¡Õ>QÈ+5×…Chq8;X×õCnÉ–àÒ.ôIÉä Ëm:–%©µ¸ >@zRIÜph2rÜ¢.醖Š÷êè@jN Ä9ļ”­Î’©’²S¨ Xû’ô ö(„M.U¦K•t7*/t2(ìNšAèïHÑy"‰QƒsŸÏB€ïâ?žrÏÏB—€ŸòÚXžž*ÂáÆ„åÉÖÊÀ/¾x ¹{Ì+¾ƒSÁk6d±ÁE½ÿýÏ2†#ºÀ“Õ÷Mv;¬5í_)z¬£ñ±qkºlKù÷ƒúßö9Â÷¤dÈþRÞØr í"­k:!!Þš:ƒ•O—2—_œœø¾´ê}iÕÛ*­:¤8Æ€ÔW,¼ÈW­/F¿Ê÷ø—jÃÓr„í.ŽÙVùÀ¾ZY…<éKwù&‰æ†‹¾T[à}{Ðõåÿ±Ê_B§—¿ìŠßËÅßö÷;« ©·‘ê[›B„$(˜–S®È‘á(-¾ðéùÉ?àßÿl XÖendstream endobj 120 0 obj 4636 endobj 124 0 obj <> stream xœÍXYo7~ú#ô¸[T 9¼_{ iß(OIQ8r õ¡XvƒþûÎð¦v×j (‚È»ÃÙáðã7ùyÍ™Xsú—þînV¯ÞØõ§ÓНÆÿŸVŸW"(¬ÓŸÝÍúû-* ‡æ¹ëíÕ*~-P$™„µÑ‚ZooVï†GÅœ3Ú ñI)0\À¬µ2‰@ªáa”¤e©ÓJø(5ó^Ž2|#3ÎÀX;|Áã³ÖÃݨ‡ûq£˜”ÊÃpIæ,SZ¶ÒjdWž¦jQ^ ¥šÌ«a‹æÐïŰ¯ ä3hôY ßTicì4nÓÚ;+E]ØV&¬ŸF8¬”Ã!cuÛO' ÓÆ´^V0ñ%ƒUv"hd0óÒ¤™–Ö›Œ4b¾ŒôÅøûöוäœhÀ×ÛK$­[Z&xÜWe˜w&c€ûáˆR‡J“fæ"í>D¼.[áªÚet_A±¢^ò¯±_MD0t'#åÛè—B²¾ŠNÕÞO§¦un¤Àu™õFȰÇq½ÉO­EI+—‰à,y±/™êeìÆY•2•('²‹dŽ|ã ùææ±ÑÖ@ý¸ÆaedÒ<_¿£Wàcå]œ,¬ ìÀñõýXhW?ù²B™liyV˜Fˆ+aœ –'¹ù¡’ºEð–ß,°ZÚ•§´°üaÆRú'“v¼ o2µb4¸¡ýWÅ(’¸ò¬ˆh­Àqh…ˆEpYIi×opzf 2³aÏ ‡£ÏÆ8mHZ à‡,‡òê ø¶ l2B }¨?Ѓò˜njátE?¼üóµÊ½^3ÝÜÌ4¢Õ}¸¤h•x±¢Åü§¹ü_O¹Ìe¦¿xæù] G%]o饪4+†Üs–B‹ìøˆC‰²šÕa¸¢÷CÆdÔÐlG?wôC©–B*ÑqO?‹2ÀŽAF&©âäá«ê硪ðô´æu!3ZW˜¾-C‡ª;gä87Ý}bWžŒ»ÄÄæCžªpVóºÑGÊjÕÇ»ªõ8çNµwlg‡ÐMÇÑù-8˜³å7^‡íuÁ‹äF!Óîb"M~ž}FºXý²8æÈ¾iU»eJ‘ÚäùC¨Ž;é{#X¬u–¸.ÔOJï¥z\S™Q pGjé>«†N„j9)¶Ôe±”Ô 7ÍÀ=æL*xQG˜gÌM –Ã@7šnRg©hY‹eË=[Úkœm¸g›ˆÛ¦Áæ„öÎ ì½äðz´Gʧ£Š5~xQõ΀š>¢y$žºÆ‘ÒÄ®kÚo_¦® sáhl†5ÛŸîiNMq3Ü”ú„¥tÄ”"­ßÓ.ZO@4Br˳žï*z˜±;x¬Ã Z0nŠ2j¶ 'ã©IƦí¼I~=BsB|K Ša\¨Ø©mna'¢ÎÀ‘Y!÷u:·ž!¸f:Þ}ÄE™åÓXÃÝãÜxÃ@:4â9cdø…¼w^p xÎøÿ‚âÂykq9ͺñr0y&8æÎ“A$=º ¥a®þ¦>Õ•¡Þ=4ÌYÊzÎÆÔ“Ïà–H[øwQÇdˆ~;£ù…òÌzÙð0­0óp6>¯§O‘âi•ã%£¨§.ªöƧ·náχß?œLs41ÛàW²MþÔ~`⦣üREŽÎ —¤¾È i9íÇÌU_#êDüåÛò@©ÁÌèÁ/%Òko{Ä<ÔJYK¦ÄÀa–B°Nçɰ¿ehhaø«)Œ87e¨Îd`>8d˜¯ÌOè·W—³4…ã|î¶¢äåØ l§ »NéŠ@NØMßMÏ5»ä’HÛCš"r>­oÎ._ö*aïë5H¾¶RjöÄ|¬?ÛrìêĤT@H 4´‘&t!3éª{?›ù;F!„àüv l—Ͷ­ûáÆHŠ>ïÅÛ4×ÝÏõm½±d&³îàšZaꈀ*bÔ4úÓvõþû¼¸—Ìendstream endobj 125 0 obj 1527 endobj 129 0 obj <> stream xœíÙnÇ1ÏŒ?bß½<úø;·zôêhX}ÿ½8aÂ*ý:½\}z “„^ ÑÆÈÕñ/Gñi±ò¶×+kD/õêøòèÇN¯‡^£Ó¾ë×¢WÊ Ñ¹õF©zß}cÆu×ëiÎváƒ5¾]¯¥Á=M÷f½Qvì½ÖÝwøì ¤ì®âfR¹îf-{ëŒL+ëÑʺ̳üå9ŽŒƒ»W04Œ£ÿ8þ3žÎÃyûqžN½ã¸:þêèø£»cØ»w^ ª{¼Þ˜^k=X]öÎ9Km”½q?Âã,n¥a¢(O˧ë5àÀ[)êÃWkàm”D" Ò0]<¯XŸÆµ„$ #D¶7Út—ë œÝ:@4nÅ–Û(i u72û9|ía=¸|ð%¢U)=f8œRÝI^:Ø)\) »ƒé> sã(º?­ñ“³®{€[ûQ .!4|ÿ°B'ÀªûÂ&{©ÆîÑÚ$\J¥UõyÀ†] ö@ez…ºœ–`©@1{ êã3 c˜9iå€E*ºâdËê£)°:ᬃ øïóÄHr¤¸‰Àl€ü}„éŸIù!ûq„‹÷Ã\ƾ^þ±ïd>l×ÚÙÃ#pi¢Óâà‰®½Ôÿô†¨FY‰êàÛ·€5P;[é ©ù&‚¾ª7vñOP^!»ƒŒ„é²ûÿ~’£<$Äó+þxɧœJ;-“ãŸOóÈ\A¥oê€÷(€ó—2ú¤]_ÕÁæÌ‹2`èá»Êà/uæó2x]_–Á{€‚aD<†£ÅÁg ¤ˆ"E–Õù¤5xS+JZçxGån¢¢ºÅí¼.×Q¯(<ñ†Ë¼§ÖÅo/+¨xQsL>iaò™™HxQ'â=@}owtV¿?i-_¯êàÓÉž{ì‡Wˆ:lª$!×™g•[ %ð óǰ£æP”Ð'Ûâ„Ñâ1É y·“Ù(~¼™=†s‘‰Ì˜R¸·Ai•ÕØÜœ²ƒ%ö3¢À‚¡ÓÖ½ødêš™ i]ZÕXCL2\‹[=yÙ´ƒt‚hwP²Š”{%=0’Ñ=Àì“ 25äÎ*H8/9ÂÁ²­ƒc.}ºK0¦·ì øµt4´XÜh):‰ÁBΜñ¾ÂãìxZ.ƒ†Ø0"a¡ ›¼L*h@g O÷è„­VѳŠjò5Š+Ž ÜÒ—kÙ}³°Ý¿_£õXQ½*Ó“:Æ åÅ[Ö•GwìûÒç•´?©+•“чõã÷õã×en› à UZ¬¹§kHÃ}ïM „¿®%<%Á÷™ØßgÅ]˜¹ FPô§›÷N“-ði (Aç Ÿ7A*5tñ/ŠÿÑ ‹`¹Šì jøfV<Þ|9W¥*à”¥^Uó^,ñÜM<j6­€…¶tš®`º„˜§”T²û¹áûÕUîáÒpaà‹ xìÃäR€¨/ÂÜR=X[!_O¢0Ê qCư•ÄóYRèÂÌ ÙWPàC—eàãgéà•,ÒAi"Pé5¶‹ÆdÄ·&“LD„T™h#P¹^ä³*˜ ò7Ò‚€,¿ÿäSÏ5 '—ÂîRB-©!†¡·Å–Gäü¸?>«Âà/Eïsa‘¿¦ÜTThß{T”—‚ðÉreIFÆæ2B‚dÜ2!WŽ¡!$jÈ÷ÀÇGM(ü*®Ùñ{Ây¸Ã°Ý¯åï?Y D“i8€ öx€€Å³ ÒÜi&ñ,Ú”:Sã< á€6íÔ†€:<Ìü@¶´Ë7xTÀ£“ÝWðÞ6üm™¦@þý:篠›ªB ¤/@,˜)égidt¸¤]aœÄÏ  fš?†˜CƒXH -‘‹ˆüçÂwµ^f†Öc¡¥ Êøex4ȧò³€oDX89ćQ›çë¦:=¡f®FAJ¨a‘ÌZ6ߣˆ8ôëÅ|‚e— ÆéE°ÔS75X’㞨…tšh ©A÷ƒ™Ã¹-8»ÜA”[Ѫ-fOH±ðÚL—ãôÂ%uò _ð"k3u+U•&à?0@>2·©3#ö²0ð£jÐi¾ýjÈ3;_z8¬‘‹d,½xl%½=Ù²¢¥+Z-Þt‚G‡XI’ydÂÕšÑ`œíÔ¤-Ú–Ü•Z_û"çH·0(øw™ßŒ·"hD«’/"Á9\”:²P‡)æ79ÿM¦+_O¨ž(´Ÿ×!Zm$ñ*¨{•¡ãá𖆨áÛæ¾DUÙKµrç!_|æt Fb…xt® ªáó¸ZDEúë»&Sâ÷©LwhG š²ÑDvE´ÝsÆ=šqqf\dlßK¶¼\´Ç‰ŽG¥º-Ë–û[ <½»c':ÚÆŒsçù”¦2rHÛòbÒ7°ÐñP/fKbxNxÂPóç*h“à`^§Ðmƒ×‘Fi¶¤ð:åâ“EN')‹1C2NÄú’a¯GkNWóÌ ì™Msþ¬Lm™ëÖ2SýÞ¸‹aP‹AÍ–=˜È"'ܳ¨1R`Ë“ÐÞ<¼x³ÞIlBª%/ùœ‹íI¬i£´’ÜrÎ,šÝDS­Œƒ ¹ Žyõ[¢å¡#ÊSa?Ç=I¿?â6CϺ,Q…nqêͲñ“–:ã ¤NϰyÍ,a)f¡§pp@UÑÞw!Ú9‘ñ¯áR‰«yÀ´b¢H½°£¸&wÎ4Û’ÏDˆ€äFa‹ 1¸ Zjh¿kÙ?\“@’B!¼$ b<ÀvIßô¼ÁOt–„ëÏðhÝ|ða䱺-þ·Šê¡ziÃMÐ`-?ˆ;~Yw¼_ï*JÊú.B18ò8âÞ*(džV3^È,tð‹´š´³ w°‹š!ªÌqHqÂd¥¾@ ‚I-ªC6»á,Èβ &OJZ‚A¨§YËÛ Dš(U͸‡¾wÞ Z?¸çd4dŒ:Ȭ1»`‰°ËDY®YÙD¾LiCàŒû¿siRÕt4Žæz¤Oû5U`ÎûÄüäo ¿0üÿ0߱绩ę“ßžWˆàÙ÷êO‹à9)ŠT uõH»/$°·A<^œ´]òÖû c—剂ŠYáÎùm±)ÇJsÑË™^´Öd°3Ù…jM*N÷×·)RzÊΞ¹à {>䜛ç6tÈ_`ÇR%pÜÃ!—(çÞ?>úöèÅ s’¡~ƒf3­_)iµKë?}pôñƒ¯W×/oÎ>þa%Ž>þ|úÍgðëÁç«ßݰúv±ä~âi¦’{¡†^IÜLñXtßà“Ê˃Zêå{Ø¢Ì~].ö¸õ’ÄÍ^|÷¨º-9Òm·”X¥Q+¸ÚÔô¢óÁÀ*Eš!æF„nògË»bQ:e]}ÍÀ5®pÖú"×iq»`ÆsÍ‘ñt”dKÚÝШ@+Ôïš+\§zZbA"Õä’ciÖÚ£Ö:·Ýe)XÞ6³ÒR"58,„½¤Œ!P$ÙÉÏ9)pÄc¦&ÅXü°˜÷1H+Šš‘BAó«Ä£}Œ¤A Û[²ê±¹+ˆNéz‘ÍCâ2xý[Rë[’çF…2&‰q÷Ñ&‘˜£f•ƒïDJs(2¥a²RJ€Ú- ˆxßú ’oQ´ò˜RÐ@MŒºEòñí8ì<"–!L‰dÏø²ù\º %Xįâ=Õ²¸A;2‘'‚$Ǹo#àÎ8%ö$¦5O?ëA‡`4+Q„ƒ„úÿó­cìK+á¤e h3?‚¦àD.V)’ä"®­£á4ÆLy³r‘f@Œ@1ûEÉS ïí(ö’<°7ºv2kV‹;• gñäXŒY:fê—4I¡%4Í𙃲¥P™ÐÝœó‘Ú&ÁáÄø€î^ð(râD±,IþЧ”˜‰ˆ²Í°tY9Ùá¬\ÌéKsçôU›âôš#ÍXÀï@#2€tSl6‹ûÐ Âç´ ØßᜅaPJ=Ñç°~ðLO°Jß´m¡ ÝÆC"µÛE¼™ÒÆ.î&!ÐÐZ Õ[¹ ¹nŶä a D¹êOƒ.5é'®…ŸÉS*”æi R5‡i{‡³¶/ è|C? yl8Ò™ö°,:3óö^=F‹ÿ$à‹(„Vís¾mlfX8“Y` Ý6t´J]?–´ó^ýäFÑB†"TK_+úzÌTÓê×&U"¬³5?-çÌüöVm²QÃQ¹šÚÑ£4wz2Á¤sB†|ëb‡¡Ž¬Ó$ýA.Î;E0¥<éÈne…‘ð^Ê­^[Ùèñì®õ¤–¢õÎ…,Œ®"‰×r˜ü…–Ìæ•|ð?¬7Ðp,pQ”t’4iR&e‡¥˜ô3²äñ½Äàå•ó¸Ffð;"ëtÌisßL‰¥ñIQ-“B;¸:êøÅŒ2¼ãøCh$Ôv§W·¥>'d†åáúüÞ RâE5ÎkÁ’CêÒ`³aÉb6JT*n”鲚ûù O}íÝjø–½¼Ìê`ï Á.:Ù6pˆà_H‡4ÖÌ=¥É}éMkÛÝm©¡Ž½>ŒEP`ÑÔÎ úÞŽLcäm)P­»/Ja±O#œÒÈÖ;ÌŒ†™¼„U±òHE„uñEf­|5ÓÍ£ ÔßîBÆð¼ÜAÄõñEt2æƒsüíÑEËŠendstream endobj 130 0 obj 5042 endobj 134 0 obj <> stream xœµ\YsÇ‘ö3Báý ã'Îl­®³«üfÉ²Í {weÂaGXŠ0ð ’D‰KÉ¿~3ë̪Îê€T8d û¨3óË/êïwó$v3þ/ý½z{öÅ_—Ý‹ÎæÝá¿gߟ‰ðÀ.ý¹z»ûòz'ô¤´•»‹çgñm±svÒ;kÄ$õîâíÙ?÷æp.„\&¡ö_üY¬Þÿáp®&'¬TûLJyZŒš•Ù_„«Öjµr8—жÔ>= …Óûÿì2yÓ´ðê ¦úðû7á—zÿ n/jRÊïÿzUÚ±¿„Ûbq^ìßB›v™µ÷ð$¼c­Ýÿ¯8˜’äÁ›8c¾Æ&Ý´è%wn”Kc—±óYëý9­…©¿;œÏ“±Jº:š'-¡Íwÿ•RÀ¤LXH©§Ex¿»øóÙÅâòÍ“ò~Ñn?áD”b/šÂ`I±]µÌN`r’jú…G½\4LEOÎÌó£:דÐÞJ4¶´X˜ž„u0rÿ'/¦9¬LgѤ™8y$ìâ E£§j3oòøÂl=LRNbʦ9:ŸÉÏ^„9Âê+ïòÿ-. NñåáÜLZÃnAS~ )q »IÛýU¹ö'£`[%yðò``–°,ÎJ£“تÂ÷±Q;[œ&6å=.̹¶vLçÚ^?à£vZœÜßB»ïë3±‹E©ý]½ØÜ?ׯMZþ¬^}“‡ó,vl¬ çÙR h-*NåE¼ÛM*MPæx­ø¥å4¿Rnƒl‹É˜öþ5vr2û°©pß{²Xµíºq ¥o¶Ðd;Pù‹kPòçØÒ J Á¼‡-ÀuH(±©¯/ξ9û~§@0hœãå Êí`—Ô¤âЗϾxü—ÝïÞ?;ûâï;qöÅŸðÿ¾ü߯àÏãßï~uöõãÝ7C|jÇ›ñIy‹ÍÛÙÀ4#B]•q¾«ƒV^6SZ?0œ“Vb‰ý²sÒÊ4z^GI¶ãMü©´Ú±¯´´ÂÍ"ïm”ò’$bŽ qèMk§¢¢D9Gˆ®¿nÐi”6‡PùªÜIò hˆâŽ£œ±“u»s¡ ùY“A—¡¾ Lè`gMžF|טË ‚œ+i@?$U”÷6ˆžß!PN°³*Ì–´RGRû¼®mLIÃÒŠ+Û줂þ¹„YdÄIÿÇÁpûƒ?ñá´?h')%X™ÿ;€2;22B²äj§útâÄ>‡`öR–ÉCµý£üÆW±1«ŠxøìÓÚÒÓ´„^LãÔõþ·i Èu¡ÈnÅþkÜ5­XŸÐ ÂoYøc°³éºÐ“whã»Ô „§aãö„új°c_Îy5Ã{4\ui w´„Üì1€YŠpâÄLä&Œl&«fTón¥Õ`â¢_•_õÚ5Ur¼¶,pŸ6¶ÀhØÞŸqvK†¼ ²hÇjct7jgeŠÝlª>7û“¬¤R8®¢FÚp‡lc¢´H÷nÿí¾´÷›üà·X Œt6¬¹#ã¿Ió6d8ϸëíÈ&DÆÙÀûÀºdÞa¼QqqØ$-Ëê´[‘Êá`fž¸®pù3®·¾'ê#káÇÆVÒÍR²Ð'ËíÄqŠˆÃÐxÂáU½×jñ‡dƒD<­›”'ÙR“*ÝŒÀ U`ƒkDúF^šf$¥–lñ-ŽOOH†¯8à©û>Ä)`eId()÷€ÃáB뇥$H“°Ã·¾¨Xý$ ¡Z6pÛœ`* 4¤†…#"NDãƒDxž%Á7“Ì‚_E &­G|!‰hêNZW—H´ÂÑkáQå~R¾"8–U Z;JJ€Ó dÄd»Ì)Aƒððò&껹' ]ð£ÎÁ<‚v62·ÿ¼‡`—ÁÛ„5ÑÉþ†=ìåÊ ˜ñE½ÿ¤¶L%g!R¼Ð(;€,Zc2ÄÛz ð38×HüÐÅR‰š,ËÀæ“®ˆ@2^ OPXµ±ÞáÊi=0C#à[y¯@^P(Pq ö7hž»¾¬®ÊÖulAKϳ`ʙӪò6 Jöûj ȃ¨. 0ã»!DfÆÝk–(TÍ`*dày«ECéfy8²Tf‰^©"®; °LBÁÚ‚bº7Eû$WDa_/Ùô‚NÁû´ !¾È©;¯D–°°,î²âYþÔ,²3ŽÐ½Š`í–i±Å•‹$#i·ÿÛAÂKªýÿÀnqî°%¹#4¾ñŸWkÁì‘Ųø yaã6›PÇÚ‘!-Isj1™.œô.p*⦅s‹n)………­É{þ©Ä¹#[Ó47"ÑIA‘J¡‹8q`C(!QÈVÒFv\Æ(=÷K2C»§·ŠaÕ¯MvtŒ²¶YÓ2ݾŒxGi>Ó ‚ß ìÀ?é–ô.bîì8¾ý96¦¡1ÓÈK˜1Ыft­]äÄâ£kÊêð‘âÃ×ê’„¼(@¹²òŸê5ëˆÃa.-7~U öÁÍEœ£¾sT:TN Kó:•´ËB%< ˜Ó’.=Þx™¼(@¥*á·±aéÔKŒ¸k7H/ tØ’¡»"L ÿˆ^¼w š±"½r,DÏæa2h–ïÚ"íf5MœF`ƒe8ÂJžö&e…õoq ©Nu#“fO‰paì"Ëp :EûIä쮚öJ ªt‘«Cj©.õ—[ó|›Ì¥‰uSbI+hXã —0bU¥ø´ˆ‰]GÞ»°H1¼,ËcBÄ à‚z@„‘T±Æîk'€È0b,ˆ))Bìbè­ñ|¦Œ§Ð‰¨ÕFÔWëuŽŒRYo·Üôh¬5pÄÚf­;šcÈ–ä ¬#³øÀ¯ãø¼ ‘?V $»D#sÐ5ˆú¿Ë¨ËýLLÄQ7ù¦†¶\,’wQ Ö\´ýIUBò$Êè Ht‚_ÐWý_ÙIÎ#(6¨E¤åÖo;ëÅXͺc[£¼–Œb̯oËKÃZ7r£u QÓKcwÌ‹6­*~i†qÐ4HïÛÑz­tPâªK‚ÕÙËÍ\ : £ay,ÉÛÙ÷íâZà.hŸ˃Ž7×|il¢V6yK1̃Mdñ½ÅÛ†r6ðòš¸OàÆ-Ð Ê6‰e½¬BÚ´ ÂEgÜnêÖrM‚¡„Ü­Y ã„é´œk(q๽@ΈÑ8íÂâ…xr¤NÏ1ÿ«‚[q•a„h¥:Ï®¥{„~…¡A#k «†0Qô°t`ÿfºSãØIœú(qMÀ/EÝpѵYÆqšä8àºa ˆ}†.¬f˜8Qg<j"#‰ë„%¼+L¸='Tß^I*TUVÐ  Öm+ÐÎusãˆ[i%[NBCO”’¯¨T²,• €§ä퓚´ŽàD°×-ß°òZw ØJ—Û’‡VÆMŒ±P˜ËÁFJ;u&»™•C˜‡à²Š^Qƒ§)Å´’b­Z*"¼+j|•^Öœç ÅÆ¼ëXd¸ÓÆ"‰gÀÄ]¸ðÎMZ}£ÈÝÛœÃO£nYÃq4,Þìç)×+›8mvùœm½9Á·êB—&¾í% Á½Iô¯Éî‡#¨§%NrŠÀÜð”t™3Âk:‹›óë* 4”·àh{lH>¥é#¤Ö`»Ñ4íúé’8æS^©H-Ÿî­=!*§ÐmD @ˆx`°rÖ2ûec!Tðºýµeã((¶VÛ¥Ûšµã+ åœ?ǼmÍXüè«¶f©–èåŸÌÙ8¬Ë‹£¨Xâr˜XÂ6ôžL­4»_ ›ÒM [Ÿ"«.N‰."4ôܶ¾:0Lk¶$ˆG©öûHG‡CÆ&'’æ0´µÇ ãÅ(Ô0h¬]÷Q™aÆà"ñXYy›!éË|šXÙí¡)‘hÌ¥´>x0ÿÚpºw~ÀJZ©ä/íaå&AË,¥%ålüLÖ˜†gÑ5M"p¤È«¢J´wÄ„®˜6ÁŒ{÷¯rïŸëàݧéïJ³¸`V„¤5Æ F~е¿Ç(g\ŽÖ^ó± .?=ž9ŠÖ0Â2£æ”8•·…U)ÅJ*{RÌWÏ1íè)WÁ*I·¹±ôçZ2É–µ¾)IèT.ž\ R‘/^Õ‹·åbÑ]½ýŽëü®õïòE6 Fû·‡²”0 àÙ¹ý_‘Ž9?/ó€·Thž'%E+~XQC;L é3]_UDÔÎóÕq --èÔ\94m:òQ»@eŠJ„ÖËά×1˜-HecÖ¬³FãqÆÂkGƒ E†¯[-Âw¬e’5¡S(­rÕ¼!û7÷ËxÛÌ.iÒ»£˜}™ôkE 5S Ÿ+¨,=ÆÅ §%àé î=€c>ÿ6º«&ž»°¨%GS/ËÉR,L´cƒÑä¼ÚeýyqpËR¨d¯— E·ñ2h%_‘x6‡G¢ê'”ä‘ÖÈ k0ªçKüI…vã7þÁÕ¿5µõ²õyˆ¿Ž~àÚ Ñ”ŠÇ‹ÜcûÕ+Kê¾ ok¶Úµ²öä¢ÄÄÞG†ÚúÚt²–9Äœ¥·:¸,­”ØHd:OÁ8¢Ø'Vs¶u X-NU£Š ÓÓFÒåâúíj¥c¨¸‹+ÑgHnÖ¼‹z@ ¤n0ùçï@wŸÔ‰Ñ|Œ2ŽØ¡ˆQL‘Ä8 ¶Š—«¯½·2'[²]ºNйî™]ÏŽó‘Yè%­Þ×{q²Àû2ÌôiýÙpú%kÙ6æÜŒ;êlŒóª­3J—†uqúÙÎyIëÚµÍ!j’û/3ÐíÚª!•Ëmnð·‚(‹ê„ÚÛ4ðA¡W•6~]vƒp¥\'[È+ág-â6îô¨x,”ùšÖáužÊõI—RiœŽY´å¢$®Íѧ¹üãóôƒuˆIøÐ£âTÜ4‡ÞÒÅ÷ñ’Ò¯éÈ;¬—“ËW<0Îë&ÕÞ/¹æ[Ç9Ü÷Ó!„t¼£ñÜHþý¨¦cIøâ‚ºW©¨DŽÔ§Ærð'q‰w]Žs!Uî]›£§9TLòÝëÜm‰:ZJÍâ$0CìaKOa6ã S“Ç+JRÐ&ñÀè¦\Ötì~ɨ5kκ¤’Â4Í2Žã¼:r„m#1åôl®ÙýèBjƒÃC|Ú€_¨\ ™¦±âðÅ›Eoé)ce^›šjÏ~‘Xt‚b-¢ÈM¥-Cm¬ØÃr²¥«”“ºÁ¨«©1PÉ×+o•57Í”«µÒ]-Ø!Âñ``™{¥;“–+š·à_Ghab|«yU<±)8ÕWÊ¥½÷=Ú£ñÃ[F¬«¬SeûÑèDÒ¤âfõ5ª$ À}™¡u–æºTGRùÜꌶ€'jQöC£è°§liœ4¨²Ët“‡­|­å9Ðý„S 6üÌ÷ù)ŽðKçÃçî™ÄgB”]p”Î6/ºfÆíÊ媢8®’Û°8Ux} _íËÆ¼Ëâ¤jšuh™)f-5«bu®˜-À"a64F§Ô¼wSþ xµ¨Mù)“Q±ìú“0Ìü1Ìt@‘È9õ}h*­Åù©9BÎ}&;g§C*[?ø![à¾ý5À’é¶î•éÎ階2ŽŒšƒ>á´hx¼;žïŃÜ/¥„y;!]¢† …KÑåWf (·«aã ˆw.ä%á¬kñÄaS×."mœŒ®blðãpRR²@#ØÓ.5ÓáÙ{*Éà éî¸ 1ù÷ÌêÌ|[v;ÒÁ“e%0-åò±I@íM Õ{ +¶êù…Ll2B9XŽúÀŽ©†šŽ¢4_ô‹Í|õL¥*1ˆOBNÍ%4£‰ïR$ÊéSÞ²‘hÝ=Æñú,¶V›ß‹ˆD½¤* œñßP2ÆxT)*9Âìt›-ïüÇS=acè¬IJbXyé´mª$½ýGœ®´®¬u“V%…=òR4%]«Ïy¾-©»ýoËÕ‡“¤îBÐZ|šÔRás)G7ñ )Йî8ù}“wù¼íðt俲 7¶±DXìCNdÍK8¨±…]ÝGÌrܬ?%âvŽ}Ó*Ô(>ó¶;ôùŠHŸÀÂ÷áDšÁ ³¶=ÙÜj±^­F·q|3Ôæo¦à7a‹Ÿæ"Î\DrŒöMƒ²Ü‰ âï+ôݬùèÒxyô-ï s„&qY¤:ñeJÎ91X45S‰Ðý6× @ÃÑÀý=Ý`=ܱx/%A%ØJŸk$›$1‚'™»qüˆ¦]_ÈÉ}àN0æ6ÇRxs?ý«;Û•¾½Fd•DIÉÁ(â2viUæøb÷u*Oª3ßm ±QÛH—•9Ob=kf»»ˆ £5QÄ¡5ÑgOŽù}øFÖ[K·íå5‡ÕÓ7Úæ†¸“ÌÿT<Ü> stream xœÅ\[“·qÎóFUù §òÂsR:ÃÁð[äHSNÉ’Öå*›yXr)’%r—"¹¢È_ŸîÆ­1ƒ™3G$-»,­ç` ðu÷×àçÝ8ˆÝˆÿMÿ~üòâþ÷n÷ôÍŸûüïéÅÏ‚ìÒ¿¿Ü}u „Þ 1cäîòÇ‹ø¶Øy;è5bzwùòâ{s‚Ó~?Ä ”b/G!¤üþ[xæŒnÿêp”nÐZËýl¤Óû›ƒ¬3rÿœÞu¶>yz8ª †Ñ¸ýׇ£”Q^í…vF9§êoà1%öo±0£Õé×`óJêщý7=í<ëâEþ#Îl´z£Pöÿ.ÿWÃÃú a WCŽƒ!ì.ÿ|qùÿØÿ zt—àÙáhðƒ®4ü%¤„5,†¶ûÛƒÁuP~ÐFÚ¶I~ï9 ìðÓ3;Zœ¹á+G·¿ÂÎ4ýùE}éE~é ü,Ô`¬Ý¿ƒçŨjŸo°)ÞJÁf?PþBzh;~y {ü#ö4ް±Ïa‡  \ìôðMyˆ]}}yñÝÅÏ;¥O˜9âu~g` :~õàâþƒÿݽ}}÷äâþßvââþã?¾úËá_þk÷/_?Ø}·ÏÉ|<¥–q˜qp2ô¶ÌóUü“òðfÃä­ýçLÞ†éä»+ÿ¢<|ÒL~†Rh¥BÙÅ/9vjÿGB† …ÿrÖí€Ì>Öeýý‡Š±Øþ£@ªe°& Ö ÃRi@¦)P7jÿš„Vé Îs›ëÔäá*¢uzÿËÁ€Yé©MzÙ ›°ŒNÝŒ(çÊÞ½‡v&¢ÉÖØõpœ·žu𯨫”±AÕ¾ØHå¨ *bT¤QèX77µïWñO jå®>RfÆ€»r”£‚ÜQ, lmF’]cD#» >ÌÀôÄÅeßÅÖò%þb­w–ª 4H¡ôãÛi'òÆ]ã/õOѬ1kxKÂ$Ü úû÷1` ìSÙ)5ß, Â¢¶«ÝàŒ ضúómœfðQOÞt´Û{l¶G®ÃkI•â³§q‘ÇÑϰOÐŽØ÷ ùCZ·ºv ûá¬Nû{.ƒ›²äõ5[SÚ x˜†ñJæ!¤õ4âKl¤` é€OëR! ¹ŒD 2à>ÆNÙÐgW>Øîþt8ޏÎ.X°ëGíPÈ _góA#ÜÓ·Þí(‹ á€.ËPþ¸=(ß5Y­Äù£í#ÆÑ &p¦Ò:—m«ŠÙV\_…ß%²ŽÀ•ÔD:æøxU‡»«OQ*„©Ø¼•W-LP¶¥¡I\µßo€Ú8²Õ¿›Í')úºQNA¸ c¹?¤Ñ’‘P¶±>vPÈeŽ8½²_ÿv0=“‚bãì(AÖãBÁn"J2d–Žï‘ÖIsàÄûŒv¶33áO}äõKo&J'SpFnBp OP#«Õ=ýª<›kÀ !bŸ–‡jËçrÒ[wc™‡l÷¾?EøÊjø—AnëÈ/{´èu‡YÐÞ¢ÿêMìœ@ÞrÉÄ1H ÌÌÄ=Г7œ5ø¥À#©H™<¦2’I[F¼߉~ª­è¢€HõˆbÝ€,‰£6ž¬Ú½¬/xG Œ 0Ñ&/°xô}Pûˆ¯dû8ó#°Û›Ô­j€MŸ?†>î¹*Ò£&.…ëÙh¿:‡"’èÓU‹§@„Qnr’=ªZ׿ÁIP€J°‡ˆS´0ŽøÎÌ‘Ùg2ËÁˆ¤N—LËóEÕ™/f쑌Tšnk£N:LÚ‹ê9Q„… ¾ÁÈU]/Oî%ÐUKö©°ôµ£ËpÍ«Í zÕêBìÈ8róÕF­ÁÒ ÐÅhO+»ôYW‡¾¾ó°àyc‡¢ žVñ¡Qwc >?|”ºƒån‹«]óIX ?Šùtÿ¾:^¶éµ*O¿2Ô3²ŒyÅ]·²a\ŒÈ"a>Î#ØUv·Àê‘×bPeKö&n pÄ€Á™ÇÜÄÞ°Ò|wµíãƒrÔ?î¶Ž60m÷Q:5‘ƒOh½ÓìwTzB.+½Ü·Ø–T­#Gì<%Öã™Eµ´®+ß^ ±k¸RyÔ™2“ܸÄœ ¦­²O 2ËÞ p›=døFgê}êHÙŽG—¬Ç]× Õ/›í )k˜²EJz.0ÃZ}o™1B§âYE³Ž Š·üÎ}èêbç>ok4 ;PÝ¥ìZçi}ëÙ2#¦˜žç÷˜4´_­uÏXÇq«LÔ.‡P kyV_Dª Ä€úx5cõ ˜:¾s‹Ëçv´Û(RkÖYcU¢sÈe#b-hI}R¤W`1ˆ‘+`œó˜@•a“qóW­}ëºô7É¡]¬P¦áquŸ¢LT›>¾GX:K÷ ³µóÎkWw-Tq„wçA6Ôúm !iêäAÓǶJy•&¶¡â² áÏ–ï0gØG`3ºÞ7 uULBEìÏÖ£‰nqª“þ™Ù] K²ýˆ#⨨àטt—µç9ŸdU¹á½üë Þ‰_W;}›¸´œ(l䦧TcÔC°é÷ÊÃj7Ù;9¨(KÂZ÷Ôþd>ï*Fâ9IÉØ/=”þÏŽŸÒ ~ΰLÁO3Ñ·=ÍÛ'ÃZ˜ã˜CG‰ÄïçHÍ!‰%§"/ ðÖr¶„”¬‹àúΗØ7úÑž“¶²Óè‚ òi¯ºžøÁΓFo;‘‘…¬šgä}SœƒÓög½ßnt9ÀÖ×_Ûê°ÿ%͇ÑAÿ3®N|\ÍXÔÙÂMÅàÇ (3ˆ°äIYL¦{$Íæ°”ë(X;"l€gR¶óø,Ý_7à‘Úx–À%MÀoàáí»Î¤Ð’©@ö`q]¤‰‚‹¦ÓDò¼K¡YY³îÞR#2…F΢Õr|&÷¹ ZòÏÝ×#Ë‚6ü ØEïE£rW9ûÆ)F£’ñ©b95Œ EKQ«ÅeÆà 1a"©pøù›ØvLS'Aàð+ÍŒwNÙ¦dûrDŸéè©Pó—s±ˆ3 }ÁþE¬îãÿ¥`,›TÅ:ÑwR{$+åWÔ„wQNó6ùáMyxÕ‹G²‡M`¢D;QR„Ãä"›í¼ŸÛ9qZô•Ö;6`nØ”ÞÇaÓÕéŒyîç9›ë'?|\ÞïÍìIðMïç‡~X´|U¯¥ÝÓfñO´Hu’¬ËëU%zŒ#œ«õüõµâˆLi­d¢Á£ËŒtÏ3ÛʡϺæµÉ¦¨²Û”HÄ0r{´w®ŸòhM‰1Ï!o oð tÊÖg6Ò¬ó’Ë×¼Í6%ü¢)µ˜à,FŸ¸äç?߯¢ áUãÌÍŒ0à¶õ]º^Žý…ÊVœHlòpHGÆ×§€?MSŽp–ÀÈdpCþ{âÎMÁàóÝq‹;“.»3üÊwËu/ñPXÚU¿@3¿ Í´œò9·ûÕEùÝý‚• ¤5ƒeé½7Å2ã~2‹r³.MX)u&ÛÖ“agçºgÎî:-»3rÍâž@ÃZ)Ê”IYÀÐìEa¡Cá~ÚÒY0êtŸË¦œòcÙÚÜgá²>±ùŠ­ !¹Ž¾¥w>Y„ÃbV³-b 6ÏùÁ–ÐÜ=ž,žŸJº8­¯÷ð¡õùˆõó‰7'Ò€ÒÁÃ}Y﫸Þ+¾r¬42m<ÂÀòÌMò˜r7ÏÒêûHù­§pˆ© ±)øéÕ¶=<$±\Ÿ:#%i:õ­…û$IüȤ‡1¢ÕM8MÊ O%ïW f ÷‚'qô—1‡cM¿L„wÒUKóôM'îÛ”3d<?/Nšçz1º'¤øíJ©–è‚‹ÿC>½L‘IÃ̳üæ“ïáKŠ.ÏÇ(¥Âüë n.¦˜ÒúÞÖÒ„¦ÔrS)fšÿ¦Èº¶ž(Õªf§F&lÕ•v‰1Ø{Å.æ»OE¡‡™]ÕXæݨ›`ÛùêQ¸FSê?æ Nç‹´uDŠ…ÉE·º5æt&˜ê&v‘^eÀ^fÒ!¿ yí<Ëyåü¥õËùKöaÌŸ¨M™–˜$ø'zÿ:­`*ÈùÍâ ´Ô´2y¦B °d«}™*Ä€‹ßÄ4=z5ðѱ¾„k¾ëj:Õ6Ó\g~ £ÖAQ¹Pi2£Ts@EJ%ørµ…MËš0t*CµȤ¡yzw]E€I`œO§ê1‡®Þ8Q¸so•˜ÖÆ>ñ¿@¼8“¯½síÂBM휘úYð€ýIRC(T¶É^Áæ D†'ºzV #›ü%X©F™ðH€¦²ÐÖ´ üPä¥ àUš6ŸµÖ†¨¤Qó)#f—+Ú³ó o.UÕce¶0­W3nÝ#è]~3 8tå•“ÂZ ~¸…éˆ&¨f5ù_ÝrY˜)K}.TpszÄ´=–Ý¢ÿnD[yS!1qã°`¿ú¤r¯6>Šr¢¢°àdò±„@W®`U,ãG´Fás:Ø‘€&¿;(b¦SõÏüÿ–]·Gr¬ÅL0„oK.»Œƒý O nˆ“-"1«iý+JæyÀڼ̤wl¥ÿA›%.B¨G„è| ÙҜÒ¾ÖÌK´z®%K;q8Îá6a19˜ ²¾¡@FIèÚ„-µ½ñ+ZM|Û~ïò!šX·•á:%$^KÊT!]sÆbjÞQÿÄ2´g'¨ß?Ù M]ñãaõµ_{yhVå•_rK\»)dJáð³ë&™«I±eQŠHŽ¥Ÿ]¼ñy¤|É*l™ G@)ˆˆ[¾Lá Õ8óŒdÏSUAž"Š— 3u?M¶Ù&¢Ónb @ÿœR*1Ö±¢\i2eI3Sq2x=‹ˆ©’²QÙÓ’‰\÷®â1ªë)0YtNËi¶àg¦_ï–¥¶‰å-W^2o$ù˜¼j §Zë)¡»º$æ!íï ?ƺ\e ú‹Rʧ2m„0÷ùK™Q^´æ\%§ÇÉèËL`kyÔR ÊDètaVÎs±ë¥ãõeóîbŒ5ÝÉÍÂy"g°ZDÅΟ²Á{i¦îÉ;Ü®Fy™ãè?öŽÇNA–;˜Z\©íî»°Ý"1…®?À­‘­È.³í«J–Ž06eꈯ|ðØø îî  Sö‹—dáÑË/ŠV¨kEÁv$Ê´Vk€mS>¹VÈ ¥/•QÕwhð»=ÿ@¬k–§¹gâ71\ îlÂb5yùm9×To®™4Eƒ[ æ¹fεØWôsï y0¾ª{LèjhÅN}þ!7å–Êëë‰EÔ4+<•ž²Ð9kðí²(Yd×+À§gr& ‰»jæ;f¼u˜b%œXÿùɘ&v°–~¶ƒgy1* {^‚ØÍÑþuc¼¤CŽFùŒ×iŒ»‡aP)|ª»@”øçLéB;ùzb—•ÔÔ‡¬–®¦V_t>³›Z…V,1±¡LrVŠŸË$[”†"Iýã†`K?óÈU>Êþ¬=…§Æ/XB¦g&'é;Õ=¤À¨0Mq©~RŤ¦tëÏ¿?|x0ŸD‰`vÅ' !¬šÚýõ° dÊã[®|¯ä­/±ðL·§ÙåE¨Œ8',TîOøÁ"hßeÞ×ÓÕEºðï‡rKÇäÃi¹`4ùm Z·ÑsÒÕ°¶oàó12Ëwà?x`ˆ\f¬Í?ã&˜èf®ë9å0G÷² VÛðqW#?ª)‡ç=}õìT9>¯qZâõéJ³ì.uè;ÀØäá!÷åTR`—|ŠŠ-cölî`cÛÖÉÏלt/I×iÖÝîÓWå ß8 Ë/‡j±šO|ƒmïAƒ3îÊ¡w„èûú]Ä‚]!Ä>*ó[רúxÜ^õᦫ€ÙS\pbFÁ¯:¨RÏÁr,[ ³ó¿˜N1‡¯ëãr1‚aDµlÖ”; f¨-ÁÁQR”íôä ¡ŒÉÔÆÛé\÷Ú‘ÃÁ±T¢ýdÅäU}޳´*V7ž}–VÎÂÕ=]ó@+tâ^4¦wðh3²v™èàX¼{±—c›—°b壎¬ªÑæ¶„ä 8®w'Gh&ðíámú’Ö[_áç;î:ÊUìõ}U*±Ô²á ¹"¿oNAqøn˜9Š·•üZ´&Hî )ºÆ¹§Ä!5>ê©£2Äë;tË¢[›ÓLKù+?r[‚xú>A—Ò™ÿøh ÏWÉæó²µU66áõ/Ù—¾SÜpLó[½Ð¬ÐÒõJÅYÅKïfº¶Gé·ÇOgÇš~ý&3®d4ã-GîÝ~Ñ}¾<3`ꛕ Ãô.¶dWåð$¿5.aubÙ§Féç|-n‰Æ +›‹AzÛz5U;`3ÝSpQbÔ“JGÕIaưºåŸgÝ|nÈj°sÚ';zu(‡—–Q Øöç/£4±l-$áPçKÆâ—‡xï…X,'f6B@{>Å…ªRºPõä­fŒ—ŸÅ4æušÊ¬eÚÛ¦íK›ëK|hÇ!×#åO4j9Êa¢“1¡®´9Å]¹ñ%ã\G”¾¨¥ݳÎ]¿‡yLù‹E[˜°Ôn.ÑýÓñøÅCËiíµî9¦åDt7~–7N”|Q>1Ýå›§Ò¡Ý—®Ó ™˜Ø6»@!¼°ÿ©ãŠñÓ`ï"¬rŒ~×­7ä÷S ¦±çq½º¼îPÎÆ»>ø[^MÊlÓñí&@k%ZW5h "Œ’ÊÑÑq.)W £è( þîâÿ²ÚÒÀendstream endobj 142 0 obj 5222 endobj 146 0 obj <> stream xœÕZ[o·~Wý#Î[v Ÿ ï}HÚ¸H&m¢?È>²¬Z7K–ëô×g†×á.÷ÈŠÕ¢±`{Åå’Î7ß\È·6ñ ßôÿËóƒÏ°›“›¶ù+ü=9x{ÀC‡MúïåùæËCèÄ´Lžy¾9|u¿æÎådÔÆh> µ9ìjk»Åyg°Ñ€N¸~· V.­7¸ ÒMJ²:_㢹É`‘ÒÓ‰Š,iW¬Q0D–åb|~øÍð~’Þƒúw n"\üÚk•Õ‚ÃZîÂÎ6i^¼B}IØÐ,”f>ïö&{PG$ :Šê¤{y>J6IîÝpÛÌšWVæA¶Y‚-€Wkï¢ /â®iapdáE™ ’¶Ui—öqYZöîUg~»Ã!ù¤Lí‡Àb›È$o‰o[àæZËžA>#ûå`V°ÕÛQ†99QfÅj‡yÐNPÆèƒ¦ŠAžU{“nø7|€jñ¼&/ã^ÃÎz¿Žñ¼x²Ue Š·Fþ“°dTž~ÊõË)†8É¿ î?ÿAxÊcÂ:ø8cù–àhc$¶Aióã«úxZÏêãq|T2InÝÕG2î»úø¬~FÆ}Qu}äõQÔÏߣïóÒwdÆìÂLVäùy,:e[ 6¤˜žL´ ÃDì|pá8+êFVÏæ Æô¨KÏB_3qáz5Äë®à—åÙĪ{¨f‡Õºë.Tä¯wK6†Ö»ØúaÌPË`»9ƒ`O²y½÷Ùýû)®EGŸâ¬ØëS”…"DÀ3^ÛAH¥ý:·'Î&º´àÀÒ£0ÞÀŽ»øfO(þæv¼FLRl€ ›++8 3¸bÕÛÆ¸Rãic’š{ð¬¹7½¿¨ïozôz—FØkå<;2ç/Íœ©ñ¸±K°,pÎà›¾=8üã3œPq¯&ÆÑªå`êÛ2‹†ŸR# %Øo];èž-ïbÿÚɘ¤±0k-’FíöSEûoèê!åE!ÿU…”(¤øë幎«ºDY𘷠ìŸc ñÛd|UˆO½ì9åw½Ý¸('U‘W¥ñ²7so7²Œ»ª3ƒò¨ß± ®‚ËÃÜ\ò,iÇôðe\¤iÒF’2¦–&[WJ°‚”ƱÚt­bP1xƒé‡›çN§5cØ ËHÿ6i΀-ýS^-ŒR¦t§L©¿p6Ä;4þŽ! ‡§#&R° ðGæ0·ïÇ40„SûS%œÇbžï:‰~\›_ÏÆ\¬Z\¬……eéïCë¤+Ÿ-rFæYÎŽ åçÆÂ…„ÅÌÿ4bÌæ”¾Ã…óFþ`,0 ,…‡ï€¯È®ý‡C®Ö± à ¦%]âýM0Fî¥Hp5‚Ñ@µJ¿uËȬTkéf·¨ Í+n!ú7˜Áet¢1 $Xåï¸&€ óÏ5•"†ÙX›°,թ礶Bv$l‹Í!*1|‹ýL¨Wj«X=–EJ´:”õ–Å»úA}"Ðb7L|Çz’ÈAN€3Éüï‰Ü<ó} +µ‡¼Ô6:¸É¿$hšÉ›ŒÌ¯‚5‹j´v”ï{Ô¨˜ w„ÒÓ¨PâüP›¾MØ Knk`KP#Æ U24qaå·{ð±î£ ›yq·ŽDÌÓa_á\˜ó|D™8#̃… Ê`À´“˜˜Œ_¶¥§½ð®ƒâÖŠÒ+´K@œÇAþ&wÞˆÖHIÜ·Âj¼$H(Òèä”fÃÒý²ŒK¼{’[r[ý.­WY‚ºËˆ¬I“l?®ÊÁ´ïIé#Š£Ì°R!ˆóDÆ5¶üÙ5ö&2m==ü2&ÆÚ&BØJ®—õƒ²XÌ¢•%ÆCe)S„×H «AެCŠ©…3®æT‹ Î êpÆCðàé»–Ñ- á¡F`—‹P·í"1aÀ;] ¬P+B±þHcñ* UâÕ¹ñ"^  MæC»(-‘½ß ¹à\°î±Pr N R G[:#üjᙵ©„£R7HÁkqN¿!2ô^öÓ'Rú¿K4MЦ!³æ‰Câ¸Bx[BGëÁq˜>ËŸä‡Ïò%IÓ{²ÎìнŸÌzv¶ŒÖg7ypáLÁšsC ùÊ}¤|s‰zs)ç$šçƒZç1Ëx^dµˆ¡ ðý|‰l ál©~œ6Å·Ùg¼_bÉXß+é ûbx?èiL3=ÉÚFØ«Cж¿“bã=ƒY?ü ƒ_bá¢I‰úW!hy!Ô µ_‰`g·ÓZ­w9IÐõ’mÀw ]sŠ.3¶a±ÌqÛÇšˆ9Ø_Cž—ÕÉGo!‘¯*²/Kô¾s#%‘*T•b9ªCM½ä ;|¦À„[X*§|¸§BÝS‡ÄÒéyð°(vëm°*]  o§‰ ×âvZøHënƒëþ@¹YÙw._øÊýÈÞù\ssmy­\6Y™•Üóè²\¬‚>ãT¨ý•´5íC‘û陜uºáF2ä‚áënS¼)ŠvSÌì𪫄Y %ƒ­ß;ÒЂÉzúŠ«Ž-¸A¯žá§¨E¼*&ƒÇ»,ÿ;ç_óðóp _„î‹[0»±sì|^É€zݽˆPµÉôÑHŽ¿„Áèù9]lîÉV5Ø;]õæüÐ[çY¾Â£èÉ|{ß&_„;N×#¸¢Gñ׋Gì{ÔŒ\†øxå] ªŽòÈE>µ§HϺ§¢Ñ= Ì¡îåÿ‰îò>„Naqï.DVZ{"‚IÌnlk/ù³mtàšj²ÝŽÙÍÎÙÅÍ£¦¯òXPðŸ±mZJ³ã ¯WÐá.Ç·t7y§yºt,BPó¸¼ÑwàëI¯±Þµs³„@:˜ÄsÏëÊ*bÈ}ٛʯëûãdî~&¹öšßÀ[Jlד.§©½n!•¨æ´‹Ž–jf@#×…#"æ`§DÍ7ï…˜Œïv1ÀÿSk\Rx¯ÉÎÿž1¿®c–ÆÓh)µXØçYO­«ëÖ¾iL05^ÕÆ.ßw¯CUͼoöµª+/™Ü·îÈùŒg¸Ý¬vßòº«ð£Úw·‚ª°ùý­Àx} /¾úD "=jìÿÕáÁ?àçW÷endstream endobj 147 0 obj 3253 endobj 151 0 obj <> stream xœ½\YoÇ~ü#øæ]Ã;éû0_ ˆ[¤(SŠI.ÍC’ÿ}ªú¬îéÙƒbÃör¦Ïêª¯Ž®šßOØÄOþ“þÿúúÅŸþeO.ï_°“¿Â¿—/~ÁCƒ“ô¿××'ßœB#®N8Ÿ¼Öâäô×±7?qfR'FóI¨“Óë?¯ôšMÒ{«ÜjZóIJÇùJ®7œ 9¹Õ똴WZ®®×jb\X¿:ƒ_NsæW—±·võf½‘ŽMLúÕ_à½VÆñÕ»0¤5««ðÃh·zXoÔÄ•7ºÀCÏ-_Ýá4B®j—›µ˜ŒÕ"L¢Ú½:ýîÌÀ^'Ï<Ç 6iîýÉéß_œ~û‘°è ˜³vÒüÉqcZÀ>VßÃzá±–rõ¦ô°‹““uZÊØd˜–ÆÂv7ðÞzeW¯×z‚} [*é`Åeüøéœ• IôØYѽ•«{Ü3|õZ!Wçá—Z¥·Â*¤$l{·wº-ôñ†‚‰7ÒCcåÄœâ¯8µžŒPi ŽiZ:8AºDOëÍ-/ËèeEé\wFz—àßpøÖ"?½]o4L ¼†üâBàôpΓ6¹Ç©´¶À ·¸(< Gš¾.¿ÞÁJ`L‰[aH»ú×$„0°üòþ&N TFúÃK8i$ž ôæí’`!vÒ@ð›úôl­0‰1Ö„£ÀA4 ½…78½®Ñ"4,{áu¤36¹\Ç™”›´É+±‡ }=P÷üö LH$êxí—a'ea±_· r"u쫼µ7k<~É€ÉéÀGê‡÷ÈWgukw(ì Í<ïïuþ‰¡™ÏËÀ-Xíe\-þi¹K ð:.¡B™I§Çå#<ÖÞçµçl?ãéß• ¶„ª9üvRàæ7i÷.ab&"#&þÒš<䀃ÚïcŽÜ¬²é6>dÌvÌ!™ ÌX…ä#ƒ:@¢»ò‘Q«$Õ&u`)òéA /áŽ(iŽçG¤ªóµ)SL¢ÄJœÉ<‘ƒV"ÃþL\Çm}C~n,Dm¹¹Ž\¤C {ô%ƒ2mÓyÜ&ÞM ¿2—T<…²QBøÕiÄeŠëmeÁ²Nw‚y[U¶®üW˜³neÈ Ý^pä´ª¤î¥HÙä6°rÞcàe¾ƒ— |K>ì:äˆÔ&ø— "¨‚ žˆ ïGÐM΢2écÅsÜÁŽäöÊ”BhcF‹Ä…6.)Ì†é ‡!¿*°”屨8³tÇìÕP¦€AùvËLhƒ"ŒYFJâ-­7#HÆÑ5Ÿ’«­÷DÑ#[C“¹š.73Ôâ= äf-GØ^9ö³Ê¢¥YFáÿwžû£°:±vˆ‡FÄ;r¸JÖ(`¹IpýéŽ44ù¢#ï4G÷^£Ùazu@Ø3‹Kˆg†ú„¦æ9ùxå—Ua&BˆVdfR/¾ªÇ@Ë\Ô³ýeTåç>áC ùu—¸C2ÜY‡º­š2€éJ›€|°½¢éŽéK«aŸ” ·‘’½LûĸtÌÚŸ`xUÛ ›7"„k†¯&J¯®ãQ'Èoçe!R£UÛzF†©ºýËÜQ”†½ y J«±î¨ÂÑ+‘´Ö„ jIÌQM6ò;!üc«/âÚ„"q>4âñ ÃHÀÞߊ¡]YìaÄüFs»z¹ö,Ûåaí’Ï ó¼†¹ÉxÛHC¶k"£»¹ÁÞCŽÞ@È‘,`W·‚mkÇì^Äð† í\»D1à^pÏ} *bCèE*³—Îï–žEum„­«N ï:äOˆ…v a³jµÒPa·C¬Ž“‰wöÕ@aŒlr‚¼r`k€©â©vÈ’É®†t­¬©Á|‹Mxà®]X¦˜Ë^gØ`â-Z>Út#ƒ‡¬œÈ×Cj±2w‚¤`=P~_ã|è § “ LÔèžhþv¸Mt2«?ãRÿÀjæ8 ›¼ÏæU0ô+W^‘_q>àŠù $¦Yqt«Þâ¼Ç8%óâyœC“‡Hb/&Ψ€Õ9“½Ã;–¿¡ÆN<'®A¡Ê§/Ÿ">U; ü àåÝ9ï#ÃqœÅEC&¹È3;›¥²ñ;Sà=’›¸ °ÝÌoµ s§EZ޾C\ƒWbÑÊ&ÆNv»%GŸbÉBÊÞ÷xÙøan.e3hÇŠèå»Þ™™QÖ[9sÁ"HZ÷qc€¢žÅ‰Zýr7R7ÄûN, HÖÈZêS "U„’Ù "*â¶ŠN:t­\ì9 ùćˆLo¥ºà!‡¨1£4êýdäô.| fl`°Ã06˜ÏÌï7ŸÝ?fvy1๙^îX6 ¶w¤O·  `ŠBø5ì½S1šÌ`O ¶ó3Ì#ru‚™xñŒ‹(À‘c¿DŠ´Ÿç>_ÀTŸ9 `ç µAÊè`S9èx.p7ˆ9»‘-0bÞzI3ï’‡áŠwIA:ß–T¦FO1”[ûZ8´!fFuÁ×t–µv"¡JáX卑q%ÂYK‚X·1œÒ¸œëvÖ%)wÀ´ F‘–«ú#¶ƒÓÈÔÂmi Ûã†[lŸœv’Uí4öª7XߢCâ3ïGÅì9³¼Æï´óZ‰±¥HR!{»/bëMäNH[oè*·aLêSÔ‰JG"ùäSÔá)–XD«b¦M0:Þ› ßÜ›Éxo–莾zÀŠ`y6éu]€ D@ò6@n0CF·rÆL¦õùP>GÑËlB-E/1¾h¢JƒGCkÿŠúècŠ•_gh%ßOÀßÅà(çê`¯!¶Ñ{cÝäàA¿ nŸ@÷ÕÏ¥1îvÅð?è3€›ÿåOVÚ¡²°ñVR”‡·oZyyøU}X[šú°Žù Æô.Í(-£ZØ–÷·µÓ›òð¦>„­hpÿ¼AúÜ¿®fÒ‚Ášƒ¿?ÇïnËÃwuìåá›ú(«¹6ø}}úXžÇŸñ¶»<½®?cüN*0äËUäeíDæšÊÏx»€ cÐÐ?' |âùâu?ÐR—ã‰%æçINÞÒóD¿‰´>îYÏb_]šñföÐ,Jm>îášL\I%Hsùáe³®¼„×åý¶¾¿)ÉÁ¿k¶> y€l÷2ñ@P¦™ È\¿v'÷êýÍ-n"žòU¥J8Ü·éèóCÜN8‹Øü‘’$Æ‹–œO‡òðíœb^¶òû*U m²Äu6„;·ö„ën¹MÿH»#ántÎè9ç–¢¾où>3SÑ«1™¤Å]¦Y± ~IP¹,zMÄÌr¦À O×´#Ò?•»ëßès†§^©ŒÝ%‡ß7kK"sI¿¥Ýóà D|›{>Òðô.ëê÷qâËüÓ…dŽŠåȦØ:3<´û“A,^7+0c»/Ðz–E 8+P|q„=ô³‘î³ê¢ûfDþ‹ªù~ízK': ÿo–Q'# ŸÝ]ØàŸÕg°¸áïWU ˆ?÷¬€67N³‚‰÷Øø£‘†ŠkxÀ—Ô‡VNg²/2ó‹¢’³Daˆ¹zÖ,”h`"^E]¢Çø ¦XJ;Aô8 HfÞS}VSXvâáFìýH**ó=¯ :â§™!@ðc‘È{*òÃÚ†ÛIu±¢îÒ³¤v]Z¦ì«îV\àÄKRµ7Ò*’›Ó€w¤É'$åj–ÐI¶rO3 ¸˜¤êX/ªu¾ÑÄûñ’Û¸?ë-–h”{úó!³“¬71KzkòW”À*°ù§7ÛVVò¬!9†(^ïg—Y³»#J4pãVh$Ž˜ßáäùðôG0ƒÛÎÌÈíZî½æì¥‘¹|Sè5_ îgF×\€z4ôV©ø($2º+xÕúŒéá°OUÁ$p[M\âé¿* 8¿þ‚Úʨ`_Ô‡¯uÞkj¬T´å )±BXiîGi~å ‹–c_kÊàoø2#â¾”˜Ï†¢F®(sNÖøJtL„‚ ³”!=-'ÓÛ±£TÚEc'@Ó°®iïçºBN|ØC 9E-äü6̨…u´h3–, \SÀIê(ßD5ëƒ-QÔòȰ©óŠ©Tɵ£-›òHÌððççk8)Zt˜@ˆñ VÎ*#š’Ë›ZúySêAã{ [#Cú fàéÚ㕪ÈKušç¥åU>ïNdúpcH½èU¨V£Ö*Ð:y,KU•~Ò”fàüÀ/#ì)©JÂÆBJ36‰.oî;“á< Í…9#ÎMCùi_[]4Åws3*TBØè”êU®“û CÉœfNÊ䔈erDnço–_#š ÿ fÞG-á[žýýZ+ðsDÎ4–°GHH°ú8·8CÞ°d ò (IŒç³F­#5Adó²± 2°ÔÄ¥šP‚ÆYdÛ•—¢9·ÑÚy*™3£‘«¿¬1¯Çè&;5Uøq8™ÓÖ̪͜8b^"n©ƒi¬B¥íz§áóÖTLý°¼k˜(/^ÌŒ•”òfV°Š_7à 5"5“4)zŠ˜“QÓ¢¾‹mx­}•Dµ¹x]ib6‡®ã±kû£Yä\µçûÈ«¢©ÕrKöŠÏv>%…§‘[>?13O5åRX©÷á.;øñJ6X-URÐÁÚ eœßI Ýc«à1‘]‹vJghÙX.M­ |  &y?Î8µ-8Ï¥M²so°;h”ŸJògeņd(Ø vé1k{95´Ë í"Ñ “ÖÒN’ý·(«ÄŸÂàêå¬)5Ëåt´èÁ™IY?7lG.ñ¸D,Œ­‘f"Q+…ðIÔ©|[©E°šÔ4W˜Ò)0‘ÏÄÐÌiZÅIH±Çc‹ís345£·-ÐËÀÈqFæTg% Ý3Õ ’ˆ9C££Í¥#±¼‹žh¸ƒ~€xêgëRçu–HºÇ9I«ËL½úšã±î!U4þY®T?˜oÑ9QM¼*×ÅñRÍlÀ䆿SýÚª¶«”o ]ŠqÑ”\cý (‹Þ[[y}̆ú ¥;·,Ñ~Ÿ[Ö~‚ÄCh¦iq›Â}Z§0ËJm‹ fIЉ0­(ü´£FOŸÕ´õ¹Ý›ð}˜~ʱsq›_6Ň™jÔG-‰$Àv´EE±\Ö¬ð#V<­Œ9lÀåd\þ 4§U1Tc Öîo ÄÂ=K–ò~P+JSrCæÝP÷Eª’(<É7 ´)¨1ÇÖó”cÕ'vÿbº- W'Fa9—oJëKeB_©Ù|¦ýÂ9UÂÅ9:WtÚô&QïY9ÑÄdXÌ[&v á²T-œƒŽbÌiT'àÇ2p´C Êê11»ÆÀ›»ýO`í"¼DuXÖ×B¾ŒïGl»puá‘ÑJf¨Sб£Ï œhxçtFc5ˆˆ§•ìyÛ|.è6®Eöm©ÇAcl²íÂÏÖt –úè¿a -z qS¡LeLOŽœrcû…„ÔžÉÁseZXIuç;ЇÃáX¯ïMáÏ8©ä2N΢§ÇïyÈô©1=øÒX®JLŸ5:Äd*Ÿ8ùä  Ú1s&/K‘ô‚x-¢¨0Ïn»Žú’JfÉ/×¥ÖþÛj7öv¥—pÞÉħ?ÖAIƒà.ðÆRâMåM€@‚¼Q“Áƒ˜/g* ÔéB]áoö`øa‘Ôåí7NFºhy¯#œ¤¤(n“ímåÖ'­w»ŠÇâò& ‹a•$yHöŸæV̆oÇ̾ZÔ’4﹩Ñ_*œ>4š˜4øX‡Æ8¦ßÕjtüÉ*…AæcÀ?—¯ÂËú€æ¾x÷]yro¤…÷á·g,¡ÏÖ-îïÐÆÎšNÓ`p?­ èúBÉl¸ªÞu­ž<¦gJ¶§ºãOææ6²„îø®]¥ÍDQË¥ÁLÍ>š5ú5±Ã%®ß…¿_Oà½u1ÓŠšxc_Ä—ýÔáS–J-‘1“j_^ (\“€U-´@÷ÁÄÎ÷§/þ ÿü‹‡\§endstream endobj 152 0 obj 5227 endobj 156 0 obj <> stream xœ½[ÙnÇ}'üD^xà÷¾ȃ/°a+ŽÌ$?P¤,)±HÙÚ¬|}ªz­î鹋($FìËYz©®:uj™ßOÙÌOþ“þ{õòäóöôÙëvú üÿÙÉï'<¯‰ŒU“âÃéfÆ8Œ”´Ü„Iµœ…X,§Y¨´³÷Ü—5²NöFƒlãÓ~µ0IB**Ù§Ó/ß/g¦@.®áÔ‰´×Ï!íÔò°z ñ§ÁUÅ)//Êt>nÞâ5B°äâó:ìÓxwrw’蘭ÂfEôZ% ௫<+¾V‡®ÜÖ]Áp(€m’À–KTeñª*|’¿VQ¬Ï–ºC”l†;€&œIØš°³Vvó¶ 4‰ÍYµ9‡÷=*ܺŠ{1kx’H蘭†™jc½0ðÔ«4¬”Ua’0$ì\I¿¢Á;öì=ìZ´:•§|7I˜ÅIG®Á’ñY@o×_¯ñÁxþuÙ#‰ˆÞ”ËÞpÉ/¢†;xÍñ¬âdµ¸ßp* v§2vÏñ]¢ZQ?«R>Åe@ÂËFé‚Eà8ÉNoFo£}{;ã´#£*?Ðæ=…¿…%Å£¦'IU7LDôåâ£qo¨yå)T ãH·ª­R ù=¾"5îS¶”,œáguÊb¸"iÀþÔæñ¦¨Óûp°Д®¾ló ¡VIô.oøy«;¨¦’‡ÉVoQ `ZþsÚâ¥õ†¨ô—‰mô–:xäñTF›ÓÓxÖÜÌà&|‡j $è@ùpðÙ€uõDˆ^/„™Ž÷É@l7uØ›õÛxíÚ‡˜½3t;äÌ«p*•>a⋳­S g¤ùXÚuìÝ,Ÿ¸Nš`xkhÞù÷ÛViˆÞÁ;*ËNÏ«"þ'@ªµt'U—ÈFEÂC@O!PÌ®8ù²Q²cPnbýy¡»}­ˆq½ê³£bpJkÐÓ;pôÉõ¾Áë ý³1h&\#w6Ï«[âjz'ùu(,†L`w­pAQ+Ù¯À7G°µ4NGA3{Z4[òÞe൦LžÞA– KáàÀ!Àt‰B½œ÷@ÿ$neÉö²AH= sÔøøÍè>—VK o¤/·Î¬¹ð¬.#½þ@ èý$<üÉwnà:IÔlÎòž}— 6”Õ}´òü9.Óõ2 ¢kÊ£ˆŠÝËq–ÏOc©mœ¶…Ü3X—^4 Tb€’ÛÊÀA‚@>Êp7Þ@s kŠ?*Ͻ+¿nÏý‚>ªÓ=©?_”‡àE‘#¯˜¯þ\=/Ö‹ànÈ,ùêY¾ÅÒ…˜ ÐåÓ€ nñhËò¢X ¡V¶41Ž’ï´ôvØH¬­“­òHiÄ+6Šzdа‡ñ~ôv"^ñmU‘dÌ’[ª8yÝZ´Š¢ÇUîVVw¶DÈwÕÐÌQÇ#ìñ £*´*s%Ì1aK—èȹ%{4:&–5ð’G3Ž&µtãˆ_¥¨GQ6v—€ÄíŠBh]È8ž"ürÔõ\Z%Ûyx "!ü…ÃOŒ­g©„±ØâIHU¦F!#²€ÖÀàǬ4"*5b¤W­&ú¶1€¼Nrõ²¾Ù„?’û ¹^3D}Ë¥tNÂ8*Ûˆ j/Y5àö“b:ÄóÕO;oQ½*ùóJ!ŠÎœ`žEËa•‰o¾Çý€ÿú¶ êý ê#(Y;é›chÁ*YÂh‚Í|}_P°sž ò¼7¸l×+ô\€}­QÙC]>A’©þ¨X.à¹ä-á`󉺫.CD•_èYË1ˆ!Iƒ)â ‘³qrÍåh׃DDYî%õ!qpelïƒpt»naHùÁù+™dÍ´l #äìàÚ«hþœ“,a,©¼üåH[%à/ÓçÞM@=¬‘’¬Ï6̶8œ³â1DÅ ÷æIaÅ)KÀqF;EbßãàØX0¥¯'Ï!€Ö…ãö¤k\9QU©;í+ ÕaÍš V¹!¤x[¤-øûJÌ~(¿­ïS ò°…Ÿ‚mø.&g8(,ã»á~áGÌŒ¼»gµ_Ô‹?¯­ô]µª²úÓÇŸH'L¹:Ú“u ¢%‰;)š4Jºº´>@JÉ>ß6Fw9ÌŠrÞÄŠ@O»†¾§Éw8“´`Ø*n…h|±t€ D‡„­^L0l%@1 †ax Éaz‡¢á44ƒFù£€0Ñó'ÞÕØtOà2ð4_ ð“æÎª»À ÉÇ‚ÉnVצ:Ÿ×1ôT$r¹"º7$í¶Õ0ƒ+dM„RXâ"6ÍÇÖfO.{M[PŒðŸ¥¦õB q”z´ðÂ9ÂŒA úÄáÊ?W˜´&jˆkk+] %nªåH ²ÚsiÌ ¹‰?Ô¸ Þ=$*oÃ)jNñ2ÉÕ. mT‚¤"®›ÊìÒ17Ö«MÅvcÚŸð‘šw!HÚÇ0ð ÚJP¥q"!a¯í:ÁW1¤Üg4&ºÜ}ñEYb5YfAù…»”Æw9NŒ“\"$)ûµeíBI‚èoÖiª¦}­GFвÍa”ð,Š Õ´å…b]ìù¬z eþèE½zÓø%°J6 J!59ùy}õañ‰˜ÑÌì$NÝx€Õ˜ Ú™Ÿ±àßt *Þ×A9p’1†ˆÉ“—2IdzYÃéæ…×vT ²u…J>Þ”Fìƒ_œŽ.Ù?n>ª4Ê€ŽDµVXÝ 7°è-¤z#`á:yÍ$_ô«Xƒî& Ï 6wHá£\Di qbÿ÷®@N/*Q+tn)2¤»ßDoòH­ZJÁæ&4o\AWYUÓë‹«Õµb«©jì}Ô5gwI dŸÔä  †ÀÍ(£éxHÙ]4A"?Q8B?ÈH6úÅÄ9”H²Ÿ*´%rÉZm–xV9< ¤÷+àEGÚÐ)SVêÁú€­r–ÛF±Õü(<"fÎ(¿º­4´FÇ43ÌS Úg;"4‹d ª14Ù+àÁ"ä+v–êÉÛy‹ÜçˆYôýÛÁ;ã g{½ÍÒ³Yzm<ÃSKR¹ïNÛ|óõà=2v½£ÄQ1mŠÌu<;JµdÛ¹»‡sÆÈôX¥8ëëÁ C 8±ÀÕ‡ PÇz†®-ò1à[†ìh±ÞÈn6:ŒÜǬ·Iq"9 õ•HNxà)ƒ ‡<%?{¯þTu°eH?Íâ5|–8oi&|ìÝ*\—ìV”X–Â; ÿå ±º—ž&<+>|¶’;µ01É€Ì)~åf÷¬ –%´\Ú^¾1 «Ð½˜ÜV­ôSµÍ­GҬǩ±‰(m[I@a¯’„® ”º¸ÐgrF|æú¼G–ghÿFªúì‹~J[I©¹lIŒô  ]”ÓíÚþ„Õ(R {d&P=Īªü儹k|zI³œÇ–ÿóD¯û~8ÑöÞDLt—šÀ>î¦ðÚ‰2lE$$º¤Qe¯5êP}“<ÖfBA ÞÛñ¤+´‡–®f‹õÍ\ŸhóUì-×’ÇbqMšýE8,d±Î§§6וXû.Õæë“þc ¥ÛïmêGj½…0wÙŠZ¥«~}§ËëÜ[S‡Õ³o˜ ë{„îO‚*GìÑi«ƒ,%Úíø‰Q‹ÑÝ?3>d¹>å'`¡(4h‰R ´sä û¢æz’Ä)‘òð2|n)6£ŽvQqW/£¡5FS˜òABýeŒ“yà¯1»G_÷jĵö~5@]øE‡O®¢u¦ƒîǬ2Ò[¯Þ ]Ú…üO}N-*±š_Að`òríF×¢’p±óÆûBÈü²QD°º†°Ö7Ô6é’òÛÆ„&qg`Ѝ‘@?9oóLyè]ÉÿÔSÕEËcp+c¯}⚈|§®©3i¿­æ„8iZ©4Ä®˜ð†`›ýÈ5\Ã3x>WÛ²Œ …&Â.kYŽuºYz²ÔJ‰6ƒ$žPIé¦oR–39ë¸÷eCI3¾ˆþE=ƒþûɽ"¦E®5åŠ|·9(·†j‡¿3šëðå (&?VîÙuStŸla°R>êäc &JÓb½ ™ÚNO…Þëx?†|а ;ãA ÿ*ԤÌÒÎu ¸½3jàéÓ]JH FÍÏ{Vfó î‘kÆi¾|¥U!½ý—ø6ãrÐ>-…˜$ÔÒ÷¸A-æ_÷œU¾ýHwÉêP^J”dɇµ+N¸'mT rY|°’:-ü¢Õ¦ú§Qg¨¢mBðç}tƒR<ˆ=fqºÖÔäšžô«‹“Â?ÿ‘ž:óendstream endobj 157 0 obj 4366 endobj 161 0 obj <> stream xœ½\[s]µ~Ï0Ó¿àN؇֛­»T†™RJ ´\ fÚð`ìÄÉÛ!‰Còï»ÖÒmioéØNLËÎÑ‘´¥¥o}ë¦í_–Y,øOúïÉù½÷¿qgÏï-‡ÿŸÝûåž é?'ç=‚NB1cäÁÑÃ{q´8ðvÖÖˆYꃣó{ßOf·Ì*§ý4ïĬ”bÒ»C!¤šýt´óaö‹ŸŽwzöfYÜôÓNÎÖY)§'4À?=Ø*¿Ì‹´Ó}èh´õbzL?;Ëú½ØêYè`% Æ œ˜žíå,•º¹ ‡9Áúô²Hã<ú·ea£sX‚ÀmÉe6"„ƒ£Þ;z7£`0@/Þ9ØFóU஌œ1}¼;4³6Òùé:=©®à£÷Né0Ób¤ƒÅÀî`ݰÀc˜c.hl-=Oc‡%„é»Ãe¶°&èü?)å§×0Y¹é×t³yà£çe(³h ‡¦ðØû(¬7 —²@¶V¦š×Ê7гYí-—ëád@¦rÁ{›DêW"µ*ø,Ò£ø ±¨é Më`輜³Ó œ·Öàp¹3°:9;çȱt>Ç}XëéX•„þJPïgøUÍôóNÑHsç _㦤”Ö‘Ô|6&Ô0LIS†¦|§>³¬ãÈOI¥y¥Ò|ôãÜ=ÃU€‰žãqhŸžâÁ@B{žé¤|*½Ã¥ÄžH•¡v|Žm€_˜ ‹=±?Íb“l?—´Ì,]g5¶HˆAŸÖËbO­íP²jñ([6as¾ µ(ÐËÄqt TQ7{ÍIãZ.ê’ã–¬„çÆ‡ø”Î@Ú²{'|z(hí˜~•‘(pŒƒƒÉ´TÒäÓÃ)Nkÿ÷w¦YÙ-Îû¨yžŠ{>Ì›> ¦_dÜ{ꀯøÄ'§Ç¾±ð – Ôð6¸Î#R´„Õ˜¯ö>íÉJ±ÖPe‰Íô)RO𰘿!‰ƒ†é;üÙC³î·†ô¢±Z\åbý×£u®=Eé)$âÛ8 dOB¾qÀŸu¯Í ³²p›v­Q_s+“j}æËxÊ[Ÿ„gp•°oÁxìã–• ‰÷ŠS¥ÍSÔQhUqåš1ø˜õ%“,טL;ʘÖÙêøw¶hæ*6ÃG8J æç3œÛ¥˜’%àÇð Z€ªôí¸DmIþ?Å…É”Ñv˜Ì;Í ŸÙÚÛËØˆÒ{Êgeê”ÏqÓ°È=J ´3×Bc5Ië“ P«WVæ[(ˆíÅkª´µpÔ1ÕÁG?ÄI$‰¿nv¿²V=¸¹µ]2§.ÉЫÆyvVè<J™™îw;Ós ð#vNúðÑNr K Çs¨ÇÆ–„ÇÂÍqüˆ‡}±6•8 ÅÂŒ¼±k‘ €ž8¤±‘ØÀbÏ­¿£@êx p““èî‚»¦ÁÿyŸQq—IZ¤Ð"ÂÐØÂÊ"·ÜÖÄæ_´ÌÍ:6øôÖ)2Ô2aôùˆHP-ùÀ/ªY=.KÞõÊG€Sº“4Ì+~tmï¤cÙ®”užâ,Y°‘|–p¤*XWKSCh<ñÒéÚ´åî雽º±ÌYÁAÙ@58²õÓv¹ ½åF`±5¨©1@$Ç1ùMi¬q¶·. ?Ó YYð}„-To=¡«ü…AýªÝöî×ZMºÃ6SävÆæÖ–{o™(’'ð‚ (ƒÇMd6^[:ÝFìèVoÜ=ÄoO;z:p’N]›ÚïUKð]Ï4ueF|#fòÓv×y³­ïÙJiÖ¦VÓ’ÄÐô¼­Ç˜fl™– ˆa›ÍÏ}¸húµsŠhÒèDà[¸\õ´ý T²;ªfx5ïBÐWíLîIµåÓLÁ.°™ÝU˜…¯{.R‹‹‹äÂw›a‡# "˜"f;f ”pµ“æ¢\DP2‘”u\pŽWè¥@§Â^«§7Nmò%iõ-G7òuQæÇC⊎sb/-W@&g¢Ø\ ô¬CºÖ ÜQý/®š³ûCDG÷wˆXg³³ ÿS9‘"ÁÊ|›èOqpßG¤:0_aÚ ;}ƒgムà|“Zkœã칎.jè)ºt®—5A  ÂôÃÔ‰ÈfN×å Ÿ€&ÂLï¼²€âÝ]Y¹ŒÝb±ø Ïq“B`ª¢6æž ¢Úø NZæ¤íirfjc ÇÚŽ^BÇÐãúHßÀ9ÓÕÚu©ATvÜ[ËÐÌ…\;€¿¯¼4´F2uÊ~HßͰg¤^¶/÷ØÏwóé€@ؓߙڞg±zH~æj=$‰³´¥RÚÓÀ…γm&X[Õ§n •\|'æSBé É¡ø·UWú £­µï³wùàA†®Ñ­ã3Xyg?ì ŒòZL˜2 aÇh+Æœ­ùI§.½¹ CæqšYäXƒŽA“»Ü0uÚ}‹ç}V¡XÝ…±ÕãѾò1‹sÏãš 8íuep8Þ5n Kú‚·À/ê¼<#ÝOL1Ëtä;¯œ³ä[œìj%(ÛþånïÍiÓþÞuEZñQN]7á’m逬CȦÊoï'ºÙ  âµR2'ãfé‹ÈTÕ`)¤6³[›Ì§!ßdœ½0¦}œwSƹB€¬¦ÞÒ¨'Ç  ëÐÚ¼AÖ-Iu9ÇþÎ],øº ÎYÌ^/»Û ­öTÈ´û|ö§Ï5é@fS¹¾äر³Ýe¥œ¥H2ñÙôégéÐ=z´Æ–‡‹ÙüC7¥Ò ZÞÊ ÞŸ XûÒR»M¶E*˜XeçBªè÷Þ: ªæ¾4MÝËHLJ*¹^ÂÊ•ê—:¹²ž³QŸàüŽô»öëðÚ°–À6ØÛ+#Yõ،ĭc#4Juò‰}!* öíE/ˆ««nï¾H¨G$ðFÖê úq­6£ö±Ê[C݇iׇ”}ÈD½-,GB„Þ‚ò¤¯Ú¬Üê(ZæÞ…wz“*—!æMBŽÑBÛ‘.CÌó¶ÆœV†(§ñ˜Tf'ÈÔ€!¹W÷ê.&UÄqÂ3s—»!ó2£!!V¦ÿ336ýqàÖ¼w/’¤8Œ¥£_ÛɈ_¹©FQjS,Ffùº‚ Sy}•¦j²© O¹Âv!Ül]n-š§aŠnœEŸ"žÌŠ¢·øB’e .”/{›Ê0x’H›#øjCôÝ¢W+s×)-IÈåþClóÿŸ¬8ì­ÍÊo1Ѳ?3þõ¨ÛÀ SÇÎ"¥`4§8jvîšGÁô\ˆn¬ë±,~HÌ1úˆ¹ä06ɹ¾ÿ…wv*:÷V³‹Mþ¸½]9‘å¼^Ò&½âñ&çØÈN;_n¬‰1n•™fšRÚ6S<&ºú¢ù¸W=w›ÁºcÖÅæßúN´º%u‚÷R`§oÅût±'¬\e(­³'ÈÈõœ ;UÅ|ëªaæUìIÁ´àÔn24åÇ{7—®KìöÌÇèFÝ’WÇ»5MCYžÈÀŽ_íéJÜmƒ`Æ_qìE)‚<›È.¶õîÎ&½VšnÚ¬t†Keÿq×¹§36s-·vóV§¹ä32so„ݲ(ëç¶©ôuj mˆ…Õ1#ÉÚÜ#ºÁË é.ð5/ƒÜ*8IeÄÖH×WVÞÀmC00*X4ªMŸtk±Ó î§Wïf/b#fnŠ©ì9Mc‰cQDÏÂÖHŒ†É©¿\„Ú_ƈ‘‡]‡˜9I¡T·bXÌOUt]„eI—.âJ[mšŠu‘¦U¦„?'Y)§»08Íïó4©Ðmw~¤ >‹k^ÙŒ»LèKw-ü‘»«r†Éí[gRÅë.3 ñìîì¥&¾„d ›—aòÅ7M©ÔRuû²Xõº¶¼/w2YT17K_“ß%hþ°æ»ð£Rt=ŠeÁª:°ªJ|{µ^yjk/x-Á¤KþUyÆÅaØEô›9•ë•o`d‹Å«Ulý¶¯àI±}J”š“ìþPyxgã4)Mk>b³Éºï)ž6– †܇ڄ$èê8ÌÏÓM'X_ã¸æÚ% _5­·*Ž  eLˆv=¸Æ›¢'Èq†/ïø Ë4 4üNá ¾© Ö‰Ö%žxóRÛÑ]£‡t“H÷ßôY¥¹÷›´<;{1ð¦ïi¥ûH×½iÔÏ •UúIáÈž]…éˆ\|ýcC¯ö¸déÀ16º&ŠÂÃ4œ ½\˜ÓÒµ0Ï,Jw雬©ø,#Ì­®7­J n¡úÒýÆÎ«æªã¸ðÉn\ÕqO‹N@¬KB%ƒÊò½÷ýú%VäûU~†—Éèqm5|ø2B wîFV¹¼*¤ð]$,‘efL÷uR˜×¦†˜Æ0”ìOœgƒ>ʦ3ÇãÖ¾Tºþw‹Ô)…´ëÌpråŽKÕR®Rží4Ü5ǰZ{Ê_³·K;(˲^4·)é]츑am³Ôê£Âɰ ?ªî%Q›Æ´Ä¤Ã²¯N“6ÝRz¯H%…pÃȯÐÌø5ë}ÔõåJ€V„ýáœDÓrã: Ïh_Ö _KTï4ð¤ø]wI?ÅÅsþKõnß͈ wŸ|åùaShÖP«ù\n*)t?ž:î²ïÊÐw®"ý¹IÚÈІþ†‰\½‡û=¬…êl¤Ç˜þ2Š£yù¿ã…vŠèkü3"Ÿâ×0ËRïÁG_yøÓŒÿ‚Oð8jü#Í9-e‚·Fd’¥ñGJú:hW&<)¿?«ƒ”ÆãÚø¢4>¨Ïq•ž²)½ß¥]°½}†äÜÕG_ÖOJãUmïIõ?° ±,ÿ¶Îo’K>mžÊª¹ñeoúg œ¶)õž®þ9ú=·>jž”a𬠃èZbÖÚX–Èà:Ù oŒóú±@™’ë¹õuùHVOX;¯/'œ–]>®ã^ö»=+¨Î²d<“\G0 د¸Znð¼êêHÕÙL·‘Pd=>Ï$y²ÙdDåü¤¬ä?uD¥§¯jã·¥ñ»ÚøMiü¤ ïçì^—Æ_|lñ{ZÕãeO§º”XÕc^!ÆCøbÁeRÚo„ŽŠúÿUÅóAZþð—²Øýô_üLá”^VLqÙƒDÝÀëª5×!îI»•Ç^ôDqz=â®1.ÊbÇ÷x^Tï"MÇOíéæcúû^‚yÖa>A*kg¥ÌW™‰ó:>ìÉðÉ~vþ´‚ýš94[Ù¤ÍCL­ƒG Îü"âÞðÍBóìŸÝûüó?±ÕÅ>endstream endobj 162 0 obj 4604 endobj 166 0 obj <> stream xœµ\é·‘ÿ®ø ¹ßgÞ.îlSvÙÜÙåË{Î.Ôù5þ¹Å?/F®ËººóKüýÿ¼Ä?á´ qþüù;üóÿ\áŸ÷øç‡Ã…uz[Vq~ý(ÞÇ.â‹7‡ MÎmaÄØø¢6¾-j#ŒkV·xgÏ*÷Ÿ5÷}˜m¼÷¼Þ{YçuY2ôm}òEi|;zý& ×—›ï“õÀ„ð0K?yàçúö§z™–¤•ÃÉæÖ×åò‡Ëÿ¼'œZÔvv!Ôb¶Už]>‚üÈõäÆ7•¾ïGô½-oúMñ»J÷¯ŽþñhøG´û@c¡q"ùþóŽXH¡gµ×ÏFÄÊsÁgIgäÙ…ö"SVÚHÔ¹X\àï ßàŸ¿•ù…?ÿÅžÿ¥¼þ<ª]|¿¿H¿a¹ß•>.ë¿5þ³4~WAì„1 ~Q±{D· g‹ÇŒ®}ã›»ŠÝ7õ£É¿[ìÒ6·âa¼‹;ùz´ºãL{G:|äqîF²€L¢Cn3O ä¾ÜúîÅâÏ3X„ðþ˜ü±»“¦û¤X l 4CYKWòU|8w“›l F5\ãôzbº#¨i¡§'#£PçúÓ¨{¢D˜åJWOëèõõW£Ž8?5—¸ÏÙ’MÖ`°=öóûOMÂ1ºa¹'#;]»_F´ü@µÛ@x&J†=™ÅlÓzëˆëÿý}á(й ŽF6„ AMY'VLÇ¢õ¶ÆMÇÇ´:Ü0½(¥½„‘åb­U°Ý¦þ¸©¯^A;LûE*qþI¼£=¶¦§±wµA龜7øŠ #ÞÔWpp¤À²öúúÚl6ÏŸÁÉ+8¯Ç ¿¤ÒA×îÒF?<€ ýLúV‹sV)Úa7'¸-£¾\ÇQŠM.¬õ. EÂÁää6îâ*,?R:¼å+þ;u°/àÎKà,@±kÜaò$RCÁ%ºÙYáp½ìƒÝdõwœØ*Âd9ëÏjeguTÉÛf7DÉ¡Fû‘Ÿ3ðИˆ+­€&£Õ!ê³dí|ÊAW«U-­™»ª ¼­Q7yÑN1-Žò¿[ ÿ£ºYE ÛU¸“¦¶I‘è#¤¤Ý¥ÕƵòÓÌYÑo‹¥y]8 ²åV|$î;ê‡BàÇÌK–7bÀWõòm½D³àHÿt ¯€€}ƒ„uðÊ*B&<æW䨩`§Á¿?/³#{[7h‚jÍ©ÚS¹ÀÕ;²l=aÀð/Ã+`/4͉ã ˦Qð2Ù+‚Ó±.R*ë·óï…Ï@”´€Ñ@ ß×U?«üY1ê"%ñnžM½KX´°ô‹r÷míðžô`ËÔiuÈÖp_f¶¾M,ÈuaÁŽs4`YYGoø¤IJºÐzm J©²5g)m K«“>>“§€DÞ¶EiuþõA 9Ò •FfØ<€¼ÜöAµ\Uâ¢PÐfܧ2V¯Sî/BάQ–;°ÙNˆ@¯ÈóÖûŽ þLÒÁ§šÅl¥ÐÙîÙŒl öZ K³ dšÊTyrEò±±ÙŒø™m“TÕ?·PÉj]q¸GiƒŒ›€ØEbÜ8:uœVj ÿWƒ)Ä©Œ}ůµ„ xÖN;#:zÚkatj¨kƶ‡½aªKÃ9Oo2}8bA½‰]‹ñK¶Zü1£ì›xÜ(xäƒóó×{—¿{pn軬¸ÕÎÚsÍJ`)a‚órz7`ùqª|„±hM=ØPÐÊ[Ú½¼ÿ"\Âp [gÂ2`:R® g_Ãtº±×nàWºåéA 0îtWÑcßD/° Ý [T÷Þ‘1j"`ßÙhŽ Ðá…m`àR ÎfÒYM^G_^Û ¸k華 u7\ù }’ ¾AJib\¦·Î8¥‡C€ø˜õ’#V“ÙQÌáŒqÞ¸îy³æEiv"8^ˆÍ<+ˆ1Ž·9–’HR‡FQ8äû•½YÜ*²Ž}Èöp½¸ÆöMê'lÎF)ù°*“~‘ño‹Õúš@ÝÚKiþ@ Ê« ˆiCÐádÊSмäAKgp5ý% ©ù5q®^mÀ7#Ô€»îý‚kt‘OÔÓDT¿Kêh5Á :¸üÜ‘`Ãõ¾öåÛtø4;BâvMaÊ*Ãxß¿®ÍɃâþáq «òDÅÉ‘ªKaŽnR„À¸ºÈAa ÀÃÞ §9Øé–mXEW15ÀwMxÔ†-W!Š^e¨—Ñ}Û6@#^±OÒ¶%â±£–"PÑËIjIûâ`À{û¾ïl ú•ÙBép7úäsô&fä|b %æNAŠ0Í"ÕØ8P7Gq)!|Úé‚ʤ¼Pß{w‹:åZw4e¤¹‰¦ Þ¾ ¤! ¯SøÃaà/±òÛž”Ü=-Ó^æ(ÄX0¢µn”sxJn`þˆ>þ‘Ð’øz942 ¥'"pyÿ—û(…ãouIŽ›b>:L†ÆY¸h$žÆ1ÚU’4 xÒš Ëš;Dë_.õàÍáãÞ–ÇyLJº5hÖ+¦!ðWâ=KYŒ Ô˜¥GLu3Ô¼³0¢gƒóGU­ôb×_•î#¢1°yœM \<ÞñÑìDV‹€x ’uÞÆ§Wa:G£ …ÊÛÒ’™xc8{ÌsD€BmmƬUn®p‡°3o8uÞ‚@ Žuæ~RsÛZlsr \àOB4 àš€YTmº…¦WPÎuù‰më°«Š §;S/r°ªpØ3š¡u…¹¡¨Ý3fƒ:c;ZdF#²ÐU„&%ˆoÔ8 ° ªñ©Ä×D“Xœ‰{> §)“0Þ!¿ò0ÅUw ‹§XxXð)ú~!É›FcÀÕ>Ç#÷„(Ò³MÑ ²ƒù‰3ÍU=6&U/ä£@õÙÑËNî°ûèD MÈ]å°í?¹ÑWH"ä±âØ->ïf…œÿ{PaL ÿª¸"^wõ]ƒû,‹µ K‹Ï›ê¨÷>Ë ªc¦v"-dãÌ÷‰P^ÅPá97ˆ^fÛ5t³¶é¦ æÜUÀ­.Y^Y#_Ä£) ‹)’‰;K㎠&}]I00cë´(Æfùå„ù¹}UE± ዟ³ˆ_S'á^Ñ—Ÿœ¯¹ÿZHÄ3×}^üMi|0êèݨñf¿£jãƒÒHJ?î—Æ/k㟨–¤õ¡d)Þþ¢Þþ¢4šæ3-lÊ:±Pk„ÖììÇÄî2“âj­Y²7;sÕ¦ÀˆÚ±Äu* ø£sßôµ54@\2æ¾>Ÿ@êx„1­¥²ù ç Fý×A–Ÿ ð‡Ÿ hJ¹ìj%æÁ¾Rq0vÌyþªªÕà/2C4rÍ‘³ SáÁ–ÞGatÔƒÖ’)õe€"_ÅrLÝrÀ=r„‰ ßÔ¤ûqšÌiT[QjDz¼HR6ÎvòQ <³VWïNñÁ …&k€s|€ŠÈsw|mþÌ­2¬ãTøPc­w~ÔN¶( ìPŽB€f$BòÛòÛº³ó„µŸsÄèÇIãäŸWÃMÒêkÜb΋½í˜d‹°BIÅd&Ó9ã‹íyN<²ƒpÃÈ’Í’èQÏáxãÃh¹sîNÛc&Ä£œiýÏ.–º–ä= ‘·™4¸8çR˜€çêû"®ÏbDazm'ÇÈŒ+{X‡ƒüLûýAz¸6¦õ»2,ÚNÒ/9øüàTbÝiƒ Çu^Dj*¹^žkÐ!§{Fø¶¢ëýT`Zc38T@næ›øµ#³]Xÿ“ÞV2©®Ç+%šœüèåÁÑ1¹Š†æO‡ù+<‚ÖÃUø ¬‹K>éfza|RŤÏQïð×rå†È;¹ZŒ§y$L±¬+òÞÖhê0áàžÎHÁUšDU„=ÔFñÜH6ºB‡”âUbã=ò­…·Ì²z{,p2¥XH>Á,¡—»á“q"«‹˜ŠÒ oŠ ×`jðwd=]v94Ûq7¶d•ûBÒgã<5h5à”pJåϪíY6¿Ï檮NM¬ »ŸÑ×gy±Ò<Jt8±­¥F´|S#Ëâò¦s(¦¥)9õ!uΉ‡ì—zøCOrÓ˦{O’øz,¤6¼ž¯!UFžä¬»oü0jü¡\ÕS0#ÇÍcÔ:|säR ¬šPÚ-B”# sîó¨j-!’XÞ4U(`šfȰ%`¢û”«ÙÄØxëXnûjh,U‰¡¬TÚ‰í  ‰¼¥Üa+â–Z¬ÁuaKu¬pN$sJRöYŸ˜É$á û¦šó¡vAž +·p…Ä’z;'eçë Í“y„EüÈøþjÈ,$ì#É¡Z>ê˜TBE¤" e±q¿äÝý¼)ÙSí‘ffd ãë~„¼ T¹N‚Þ­¬ ‹¾ ©…é}¹R ¦1®Ì".AËj?G¤a„]I™¹Q_5` Þ“XW£ 1³qYUŸÆ°;¾]Wãn¼7sFLu«ˆËk‘æ ¨š²ÝÿNŸú¨ÓôÙÝñ ô>DjÙa´R01®”åE]+)»ƒ4$iìÙ=x¯ŒßiTHlÑ(¿q¡•~)@d±˜-Ÿ#Óµ(ãÓ\-ƒvb×üF˜ óˆU„»©»¸ù‚f*¿ W)äÔj×èŸ3DÄ*m‰˜ÑjÅQH†Æö2-¸  êÿ¬[ÔбÞÜÂò½,šó8îÄ?M3ò”ºñ|?›Õ•(JÜ5­IŽB?ÌOj›NÊä Ôm˜YÛá ø>D¼§Õ&[,ýÜ7 á!Z|•&ÑX\ãÚ3C'[ÈX;b¹5r°o*SÀÃF-’-%0¨`)·X)ÞÊä*¦"ÉŒtî\mc@uS¡"+ˆEŠ]‡%r<4,œfZHgTŒÃêá›#dIQ^U»pWÇ6†ÒÜHèRhê.š¯uij¢•60æ=µ~ЍéG'*žâè’ü[Ö÷âxñîØíl.+‘J“9_û%<ÐÛ¶or5ÇÐ$°ÉÅ-ªÈÕqEüää4ÈY¬TÇÃ@¯8÷:#ÚeIÌ bƒäéZ#A½ßÖ.må1[‰éNîEà06X"p¿-ñ®¿×pXý"ÇÿÔÆoJ#ù¨Š<ì7èuQä$.¢+q†äÁc†äÕmÐ[oM¤{| ö&6YÑþáà€=ÏN¢iÖåpS>kwÊQiô­5©Þã€ö'üN²ý}õR¼ã~‰ÄQP#,zÁárÔ}iüÀÚ¨,ÚÜY×Ǭ`q¸$Ø8ðI~‘‚O¹Ï] ¦[N¤ÖØR#êq®Vrùà¶•Ä¥g½‰À0°”‡Ï«ökˆ$‘ަŸÆHç{Ö¢×÷ƒÿ1ö ,ÕÝÁç 7!\}õY¤–—Ápr«ÔÁæúïµÇ­¶ ŠI७så¡°&š=€à$)9døA8æ:áJ#‡þ0O¬‡.ž/e‚jÈC§”˜¦Ií|B[Z@9ÖÉè±êÔ*,véSxí³‚ÝaÁ¦õÄÌSV¾6gžb üŽê”žjÁz‘ÜͧŰý™À| 60ËèÛÚúu÷,¢ÎOw“Fc¾«¢1§ªÇ¶:²q5ÖyÌ:Pž5Ïg//êå·õÙ~¼ßálÍlð³˜{Ø\C¦ÈG¯N©Í‘;Û •|üë´ßWÚ0ɤ ö@»hrVžz:^Üeªð«w‘ŠYÒ˜µÂaÖhHr'Õ@ÆC©|Ù½ãG0ÂñRÁ5ýŽögV½§V÷Ó\ÏÞ.½®=™‘òØÇÏÝV%C DJ;ñ<ÆŠùÞt¨}ˆ,óÇbTŸÑ‰ÞÔJ–Ó¯nÄBy-±°{§|!}Jç®ð1·~VEqò¶M!vŽ !¬lÃ]£|‹ÄÔtHhëV¦Œ¡bY'.ê7‡Crˆ8ºäQ´¾ÐF¼Ç)—¡güª4)¾›3;V-â'µöTôŽ4™>¦¡¥ Eq©†ßÔÏÆh<~K Åh”w\Ã?©ÃÜ«áÇÏÔRóZyÁmZWŸÌ€â_ǰJ{͑ϡ…‰æ'.JÏj¿gðÑ ñŸíy¿¼ž{ ÇÃÈ1üO¢Ä£l#p¼îôq, ¨Èt$R«yìÅcðmã‚ §û’gþº«.¿CaHok±ý׊ ?O%|ïT\Ð §ãµZK²ŽEþTúÆ;â­ÅÂ’©q(”ê¿ÿb…Ÿ‡gJ •°prWÑÉ«Ëag'1¸ð)cjcr^,Z˜ƒ#±«Mˆ­üãP H5[á²æü 1äiVPÂ>)2òÉJ‡U¨H64SNÊfÀÄÂa½Ãö°F2FK•.#¦NWñÄ¦Ü 8UkÅ;LúÓZõûÜxrùS‹«oaËÇcÙ‹ØhMÊ0[Þ™|ç1Љ‹_ö ©ŽÍ{)ððóä“<õ\Æ…:0I:˜²Ú5'‹ž6ŸÛ鿱Ðgñb} Å<í×äb¹ LaÒè´m ä ¦,˲Y‰QôDÍNJÝ8rÞ7P„|´ˆÌO7 1âÚÕn¨˜Á©£rõ­y˜¤Qú;Ó0s<ødøè4 ÐÏ–€rÂCVÿ„ÿB yøÃM…¹ê I¿¨…S—ЗÖû«Ë{ÿ ÿþ?äAýendstream endobj 167 0 obj 5562 endobj 171 0 obj <> stream xœ½\{oÇïßD>k£ 醧Û÷]¸ˆ'uá:uª¢Ò%YVCJÖˉ Ÿ½3ûœ½›#¥Ä.‚ÈÔroóžßÌébÞ6bÞâñßÃÍlï;7?¹šµóoàÿ“ÙÅLø óøÏáfþh&‰Fš¾íÅ|ÿÕ,<-`H5JέÔóýÍìûÅ£¥n”Æ.Η+éš¾³ >šÅz)çœZà ­…”‹>[®”q¶~Òø­k´‘–L»\®pM݇'®—ªé:+…"~i[½¸‚‡µlŒ5‹ÃÑÚ6Z‰ÅKºÁ žkŒYÜ,W¦ëÞà†œ•ñRéÅ΄V,NÓ-Îâ˜êâœR‹×e¡´ºÖd¡Ÿ–«¶‘R¹ÞâUÓ\rÁ2—œ„|ÌûŸ“{Åž«¬•¿8jšw‰Ì°Ò“3ÿµÿ§™ìUc$Àþ0<¯kÓ(³øzÙ‹ÆuŠ2È ×4mŸ¥í*™üˆ_ Xü¯£\ÿÈœ£S’®‹KlðkMT³öh`‚é W؇Uà@RètéD¼w+ðN+â­õ|%àn¦ïÂÝâ–ºwµ¯ €Î?†ÕA*6à6¶µ‹¼kÚÖQéCíèšVèÚ¹ù«Ô¿Ìêaý¼J責À…©Þ.n@ä‡NGWÇÑ—E4@iú,!}÷¾“=µ R6½èûù í’úœÁdq?n¦m+ì³Â]áLÑN8ò6~}Œ,ê{¸±0 Â× ex2óI™ù¢š)[Ïœ/ò |-°¬ïý±ÂàYyü<^—ŽóàE™Y]# ®óà=Ü]õõÈFñrÈþÏLê½`§ ÏËÇ'ƒ¹áü¿-¾È‘!(ç¶•óýg³ý‘üë̃«|š+¼aÏ¡IXyk OÎè5$\}uÙùz;cž•™ûc>‡ëgjv¬+*•æÁ|nM¶]¾?àè½·]¬vsS¶®,bϹ›Ïvqó󊛞>A\Óèç3cÑy«Jhåyx9Žæ Õo»­|†“täv'·fò7;˜üc2Yþ’cMaâ5'ƒ;ýŸdÀoYÝýä2ðÍ.xHe¹¬\—|1‘„‡•$¬pÒ*ë|6¸çY0àW+{Sëð9G–½ß–™ßqìý9þÌWBË"nGefvªÓµjÕ%R‘§šd$¥ð—#ó‰}U?&zˆ\õâã2úqEP ¥V&óy–•é„ѲÓLï³Ho qFºÑ¤{Ý…R˜ÿoóà>s‡ŽuùË’ýM|Ã1HÂO”¿I¿~‰÷û碌 ªuñÓª|íÊCËJ*D+@fåâ¿w†ùÊÊ–@ãù2Ä%NÂmá$Qoˆª@… mšŸƒk˜ÎW%2‹á¾´Î‘Œ¤Š HèZ‚7ŒºG~ñižÓ¸ìl É–Ñ-Ü?ÅCCj¦Ÿ ¥¦ ñ‰OÒ‡2-¯†þßjŸJê “<$CšfŽŽÛ @å[ ä’î=žâz]'[üçXAA.h¬Ò¿ rCÑiNBÊÎåö)¼§^²)ÍÎóÚ6ѳ7ceñd ¥R !{2˜iåR"éD7N$[oÐ|®“]äªí|ÖS2£×e‰A~"«6¼Õy-KñcçlJ#1ÓÀäeAf-žL0^—$§JG|©¶hSJú M8 ®RÓqŽ|)¨mVRÏç¥Ö?\VÃ9„/?àÓ @u>'DËB'Õ:¦!ˆfÙù›¥j%œp*Xe!GЄFb(ØÔûxé™IÜGÄhE”…VTâ6¥Â~LF½ßá ôÖÐíey TSÂM~ (¹Ê:kD¡³W¯×œœm£\‡›mM¼ ÈS4=ã7ý´IöY­³#‰Áézø އ§*v°MÒ~X±ó†ŒfÙ>EÇ) ÀI­sç|ºM5¯TC²f MÈ’+­hâ ÕyW²—[<ÐXÆ‘žeîpêœù!Ù ÏÉÊq)OHé ‚)l4üŤ¥‘\­ò1gv {óÃ7•ñ"Üõ×îüÃv°‹œû˜qùáÃpNc$¼ lRí¼ÇÈ‹„8)µ¶Æž 6I¼Õ¸ ®CÅHÏ’h:Z`¼kÒ6ˆí/!”–­QÔ5‡†ÒKÖA¨là^²9a½²Q€kt–¢w7e]rÔl¿V°¦R Á>ô0w‰ÚBÍ]<šXI È0cxQ®û!ŠNUaÌkÀÑþƒšJð§GÓÞjoÚ+¹Múv2´ Ű10²Ô ÷ úïú~dîâ…ˆ,í„-ý2œ&b#µÏ>˜‚¡lhÌ ½ƒl% ý/Ò´ÀvIY†â…Ž“6­ï ŠE¼‹L5Ìë6˜ÝüX q¤ö!{íØ½ÕÒö±büÚ«A$Lí%§‹Ó®ðCú†T$Ä.‚8r¢‡/!l99»n­`œAŠ*£”ðÎuå.&t¦ÀËIV'Øêon%ÉCo— ?µôÜצywÇÍ=Êp”~„Dùt ò`œöXÊï 1-A®¸ìý%‡ò]r8Ú!]œr(B…*)\ÓÒŒ ¢Þ,cq€àå’oÒá×ÃL›ëš,ÆyîÁˆGÜÞrƒW·ˈ³u­ÇÊ÷x°ö®0Rbæjt~`ІÀ;ìéà6fpRq:±zá5¤\ oÿ Ì|à±_»ø7Oy4¢¤,qž9}“IsŒp”óëm~.Ï)èR¨Wˆ–È-‘ð²ŧ ý<…O:r—fE‚¥3,ä:ã ^‰)Á”ƒ3¥«Hw•EælDØÓËýǼ³»S ¬Ÿ,¹¬dŒÐCI_«×dÐÞ;ÒËÄe´ ›î‚™8¯ÈUä6“K»Ë-änÄÞZðÀq´¦¦h¥å¡ÙKºxÔwpØ[!ãÙÉ¢äð‰œµÐ莟&OÓÛZËÍ’þ:sV¼ã0ãVXŽlÆ´ßIðAðqš¿¸ÉŸÁ7tâmc‘ÚªQ“n _/lÚpl"ŠyÊͼ¡ƒãeÃR’Jãm-ñ6JzªaA ƒ|šõ¼®Íï*ÿºNâ\Ç||{:¿Ìßü£èg EwÕU'Qi<<ò¾šé ]nB;6O`Ñî]d Ø¢DÈЙy°‰vÕUõ—Qv^c`°Â{€Á:gXª%ü}¡õýµÞxiÝùÒù¦z>œ˜e0¼ ´kD†ãj@){H· @[W°ÙÁ/ÈcžÜ(x2R©øDÐ包z¡É؉ê)‹®e†hº| -º¶àQ»êÆdQ…¨€.Ú[½øZYSÊ—ƒº€í±Å„Àb8ç‡åîU\ívºˆŽ‘c&ô¼­uvÁ¶˜0¸Öæqª%¬%®Ò‹ªi¿Å!²_í,“ô%Xx÷eî àëFÆÍ«÷rú&€þ[û"Êö'±—@"›9ÔYö­ïC¦ª—dK°±Ù}±‚ƒI9´H+“ÎúóÖ*_Ôæ†èô­§úc‘šïyaâÛ¤œ[–¯¤=’¡.µDE4&÷QÝá+–õ”áÚTyfÄÙ‹²Ä™»‰ï^—þ®2Ÿ§ÆHÍã.×Ô)nÅ&.©Ã—mçÓO’?²! ÿ—¥g ]¿U(àt…§eòó<¸?¹BqÄudS/î^ã4”m‹$dÛÑjI¢uOpÅäJ¯Ê·lÀ¶læ{vXÑË dÙ¯Ëägy4~9E>öš0‹ djÈ|º¿r%»ÜwŠ*À ÀKc?ˆ¢-_ãâd*¡ÔÖ=º4MË8©m_k&vHU pÞg]Š+p¢MÛ÷ ®x4(¢ (ØMËÉWd`9ãÏÆ-Wl/yœ­ÚŒêÐ9f‹EämG:0yø}¼UжXE7Àó ûE¶/ŸûÒ²Ý_¦ºÄ)f ªGÁVYZI_jiÔÜ á2½ú“>¾Oõ×vÒGü’ÛÒ±)v7‚”â¦in3% Ëý”aç†í„¨ÏEjÅFïq·&gi1fëd½Éd Hñc 0H!×ÔЪ]'ˤ{¥?¦Ûž>FvÛ”Ý^²»]ò4<ËYr1¤ëò LILY¤¬ÿj»Ç*Žá(PŒ/ ŒàÍ5GÌc´×V×l¹â6ºáV 7òÀàÔõê+bŒãj…t««Š¯Œ8ð ÷IÅ ‘ïÝ & Îlè8ÍDsNÂò©ŒÓüZ×»c÷aw›îCm¸îCðøbä¨È=Ñ¢5HîªMí:ŸÇÐÛjëßø¼ †›ð¼J¥+Û­­ò]‘1¤ö¿jõqíÜÝü¸ä¿WMœfž ö &¶BN½4èû1%,Tú1ïegWGÚåBµ6tçaºm«Dø„ËU΋tp¡ÿxk.«E#»a£åM ï“h ÝTmiqXiH1Èa:5Á>)ÙMË0×`5Ýü‘¦V …ùÃ;ăzÏ/V‹íFz<®4ìæq–Œ~py[ݳX˯èIÞÓI\ ãîƒòñyÎ…±uß Ãi Ña<ù)ÍMêìMƒ Ô¸upÔŒýû•Á3*çu#Žå}o—®f"Å~ ÖÑ«Á l_æíh0Gš|ÀˆQLhœÁÂáâ–Eš¬ri2g–©ü;öM†ø×BîöñGÈ <~šÞ«ñ^ó8`ü(yʳ"XDVê/aÉÔÆ$ÅšÆ_p!㤃ˆöà ô~ ­e²šô&€©S|9Šò¶F_ÛÓ×Gƽ`¸çȳìès=Eºhª†_É)ÏqkÀ7yhü:½šërõ¡ÕiM¨(uí] A žàR:LÄmÜ,îì—¡ö$½£D«4òcΆÕ|­(¾]¾F%,–Ÿ —­#8n3VÉ2”Þ»Š> stream xœ½\kGý¾øG,A"÷¢ÜÉô»'$¢Ød‚0)Fh½ï’Ø»~`cóë©êgUOÏÌ]‡@d¼ÛÓÓêzœ:]ã—§ã NGü/ý}ñüäÓGîôêõÉxú{øsuòòD„§é¯‹ç§_œA'á¡e˜ÆIœž==‰o‹So}j¤>={~òíîb¯­…”»ó½ÙÝìZaƒÙ=Ù”´‘v÷´J=kwÿÜËÁ9§ §tƒÑ£Úýk¯ï­Ð/ucÕß^ÁûZJúÝ-<À_•”Š?Âz’¤;.äNi)U^—§z2»Ë´D5Íß–Jï^Ԯ鹖<½?ˆÁgéKq7vÒ°˜Ø B¦}9¥v×uÈ, ãñ¹ùÂàÿÞËi£Q°=XœÙ½Ý=À >í%Éì ‡¬G«F0ÎAAÏitJÙÇyˆÜh¾QÄí^¹F˜vïö?ûã‰ý`5œýÙ%œv9¾çûƒ¬uV§¶Éè¸#?f÷Ol¤räqžÛrÝÀŒ‚ôK‡å„=q)XOâ4ãT_‰Ga%´už–ƒ¶äipg¸ÙCÚíA(èä㦣X½]-ûOJë•4Qîh'Œ?íæZ @IŒ‘T^ÄEiЪÌÕ¾Êè÷Z5À§—iJ%È”·T{¸=¥ãnŒã¢¨UU°O`d ú #3m$+¿Å.n…ÉƵøe{G»¨sT{Çß`}ÊØA™lî°Ö`ý]ƒe‹ú,ý€§ùé#91&ô`O OÒ"ž-.uGÎ4Í[17¾ªw¥õm¯ë³òÓ›úø»ÒøÚ(J#ˆVû(··¥ñ¼ö<~LÉÆœ<üŒ&“o{c’¿êÍ^esÑ{çñ>·Faó€q˜Ü`QÌ\ÞƒcsΚ›CÖ̬9:J~œ&µûj/w_߇0yü?ÔIÐ'tïYE´ÔGr§Ÿ]Jœ ì^m¼éyÖËÚˆólà(× · ëºjÿklÁIӠѱ;ÜÛš?Ú3›®= 'ЦíÜ)¿•¢?»{ !κÝо=üOí΢”Bïþš]›$^Eñ$† 1GÎáâYñéÅ+£$ÁËÉQ“÷¯éñé•wÞí#žµ›lŽZÒ‰yxæ!ø§[n‰{²9b†Õ>Ïæ?ÅàëÒ>@)8TÝMš¡Ô¢f`;E;m}@EÔc4¸¾ ì«ÕzmUhŸk¸mÏÍ`èÕ(· K (š“ÿcÊhð(³ÉK fƒ»Æ¶hfaÄ™¢òUû©Ûk_æ,? HqàœÆ F=–ƒ/°ç%QÀ7U«ÊôTñ2% ê)zM­½’ÀƒóÕÞ=áÈoªŒ«ú ÍÌt:¯ ,ÌŒ°-EÖ2”Îi®Öq«óØQÆÝÎ*îy´WràÚƒFÞÇ‚XcÈÂÌûJRö¯¢lçÞû£ªä3óYѺîQK|ô^õñm´®,û¬Ââ´7ÁŠÆ1=ánŒ¤´ÇUfƒU{úRc'à[ ,,©  ²§^€¤=…äÔçñß: Ñ‹é@Ú™®o¡­ D º  []&Ú‚J•MÌÚFñžýRa w£pÔÑâˆ)PÂC¶~~ôɆõpL¨e×Ó¾hŸJ"ÚìÞa~mz©_ÆÈ×\­ˆ#%Q¿eÿèÌ:Ú„TÍŠÁˆ© ChÆP_`õum|Xváç»òB°Ô—P,øáÉÙ¯¾Ý}‰“ݯC<(ï}U¿îMVWÀ§ÍÏ?)ïǃ`obš¢@Üä¢@ˆ¹®gC#äOIïõäZ“TÎ;êEð¹sƒÒ²Ï TyS§#=ÉgËИbÀ¨ìÍÑÌAu2ŒN¢•S“›h⨎ÇA˜éò)þqÛ¶C¨ 1òöbÐO“sÑ^qJ’ýå1FÊÃNƒÈÀ2tpû4ï^„Ð<& ëõ‚¬§hóº†5âVªkâ!±„»Ž£ÃÁ`+;nætpc÷ªbÌPM«> lBȵÎgnÂ;ÆÈöµ´DêÆ€,ç óá¹C=膪hQ/Ž¸Ö·Ì¸iŒæYå6Õ¡õ®ÄU^õ¯1g•Dm²aN;¡úiNw[‡Ý$ú ÓЬvhÒ˜ ¸;—’(ô£ðXZc…Ì`Fás R…ýâó㧆CŒnÏ·TÃG¶Äµ¹Ÿ"c¢%,cÆC5”šsîb¤gÌ­cgBGŸtw¯ÏŠz]%‘$4Ë©jÊ§Rà:‘–{¿÷»W¨M1ŠA“/ö¸Na,ß°ö°aK#.#IÊ;½û!f ñ n W2cÌC¶˜„[LÈÚ#cót?e³ ýfò¤ËWwbÅà1ÑŸ·dD:fLºfŒ±FÀnÞ/Êì­Wð< †goÆXT2çGzGMŽ¡Ñ&ó^@2I:=´&½œÌ~â¬à›ßü¹4>ªbt™ç‚nðóúã/j‡oXk@ º—–ÐT°)Ï©ñLä´DÍ] jHžÞadˆ‚4‰!@0gGs¶ñ]{ªc]£ÑXÝ8J À€*|<}‰þ_/ù®dÛæH$œaOÛˆÖ4h(ú +4÷©üõÈæ‘2ƒ>ú^F"ãeÔÌ-ã€õµkî„d„óöë"ëØl‰8ƆÁ“—8`YÆšþåÄ´K’®eC1ìà_ÇŠà JJ=W>š$ŸÁ¹B\FÞŒÏǯ.jãØË_ÞÑžk½ºu'ï6²ÑѱB²Äç!NÓ<´ÃÀГé_€èlÀ/j¦F×»>¤è#ä?‡Òø[h„HäÉŸlœÇ¶Àý¶׿i2g”ã5J #Œ‚"S¬v ^g>ÖƒÞürn»êøM3‘® ÷x}Û°Ò¸‘àûqèÐx…0E¦J‰È6§xå­«ÒŸ&Êä999ß2J Ãár-;X-›$jyÑF£I=V’¢µfå~̧Š"¾ A¢m¹HÈ[6Å6²G&¥;+¼ŽhÀéJT¼ñ)w§€Jh`̃ý$¢˜Z4«Ìús¾gC¾è.É%f€Þ¿(­ó¾H-QjYTÍ=$¹¡$Bt©$AÃooÍ$kÖ)°§ ¬*®†¿&w¶ùð8÷L$/vkeC¦¿âݯRdñšu¦¢ƒ¸î‚qÏÓöé-k M"Èm!Ò[nBËl¹HBYªi”‚ ØÍ>­dMº”Æ:ÑÄs²"NO´•°©L¦Ø@öu}ñ%¹è™~Æc #¹¼:tR ‰¦vj**í¹òô~àMÔ‡• e|x—‚ŠÿO„øÍz„Ø"ž7ÂFïLÐÿH×Ož×#º®k÷C?áÈKß­ïAlìa»±»‡£¢§l5S“R\¿v¡Äaë~w©"ÒÀ¤¸#e[[ ùVu9=M9Ô*LºÕóÒÙ—s¼Òa«èe;‚öe²AUÉæ,0É@"=:Qês©Ã~YÖ9ÏžsüZ¨—¯ô?­Cȳq Ø@(,XÿVhþé@,oýú>ª¢ —jGBü¬N¦;º 4&–p¯}êÇ+p(ŠÊ—þeôÑn ðœ×jÇ¥ª¶Æ›”È »UL'ø¿±œHÔÑ;<ÓŒ;‘?^ùËEœï\Ä¥“#oââíˆáœ_à2ÌKùÃd'&üç¦èÇÂ[*^\`ûg'ÿþ É endstream endobj 177 0 obj 4229 endobj 181 0 obj <> stream xœÅ\[“5’~ïåGôúa8‡q¥»ô0 c6˜µ{_xhÜÐ8h» 3ÌØ±~2S·”J:ç´iÇT×Qé’ÊË—é—óuç+þ“þÿüåÙÇOÝùÍßÏÖóÏáß›³_Î58Oÿ{þòüÏ—ÐHx³„5ˆóËÏâ×â\*³(ynX¤>¿|yöÍîÛÝþB-ë*Äî?÷r Á{»û±¼¼­/¯ÊË›úòïåå·ûý…þð»?•·ðd”€g»û¾¼õ{Q^®£—¬åÊ[Ƨï.ÿëL¨Å˜àÏ/¿<»ü¨YÏõÛÛòòª¾¼)/af ðìv€G¹ŽçºŽæzä¥hèC£ÝÑG®ô²ŽùæÆDú|üTxÎ 8àBêEˆÎ/¯þ¼×‹RÂØÝ‹½\œsj÷è"Hh£vÀ ­u0» ¡ÖBJ hjxµkdg£Õîyixµ7»WøC€†Öèm¤…Î.” ‹±–½®Ã¼Ž´ñiD©4v’¿îg„¿_cwð• ÔNÆ[` ±û×^†E®F±ÖeþÈ^.RªÝoµ[øZÀ·ÎÊJ’4'+èt¥Á?ÌŸÿ7EJ Ëý0)ìîn_–i’'ø+lŠ‘„uü‚ý¸À¨0””z÷¬N 6gM_ì‘Ôª Ú€v¾Y“);ètÚÁU” +ÐÖ7ÐÕÖw±uî´é%N D -^§¦ÒM[\—ÎpòJŠEÿ¢ÔÛUÆUÄϬsyðeßpQ ŒÖ™4ÒVB§vo÷ÞaC±{ 5þîst!SK\Û’zM’e¹dA;®‰Ì^Aó—áajºýS‡ #¡çÝçÐ'Ÿt4X@¶’ø¨Vbê``Å»Kx‚5•ï_îl+|C¼fp»/Å|Ð+J‹"$É‹ó¸wÐf+å Ï¿BW ´Ç?÷Ö-Aà ¯íƒ_M ¹pФó3Ô1*Xàv6Ûúx|öÝ+xôÞk‹,—t×HOR´w8Ró$aŠwã%ÎÌZgu~ôÎfT«$•Ãô×mUoy«JK’bz½Ìã·hó@ˆØõÓÚSÄ9´ƒ8Ë;•ØqU@y%#ïáœËìê몋%ªÏ•Ó@¡ÕWÏËSU“•)§­s·W.²â¿h{]d(%ˆ‹Ø[¶èÒÿsü\+Mz1Q€µ»*½óÅ"H€AЬ¡t¬Šìã`ÍnàþÀÔ°K£ '¥)ŒÎ Ó±[cMZˆ—0ÂOU½(_¥•HüU‚õYÛ•…[µF½Èú® «–Ž÷ªÕx™è YRÇbU-UQ‡^hÖ]7*„hÓZfföÁßsaÿH„®°Ï¸ ŸÃäÚg͸’Ä%‰_IB‘ÊJ2Ù0oÒ0_ Gû V—„•aÝî¡UL›œV}‹ÃÚEVû(@?6]66Ü‚- |çxƒÖ”çYå? ¨ t é÷\LÙ7²ØÂ/ŽKDNÖ"rò5çïÄŒT{5ø·K€pÂú¤—–o|Ô:Vrãüº5ßlVckMxZNkÃ?Ãrd&íÎ 6ü²rù34Α&Ó¶8Ê÷õŽÒm-//ëËOË˯ÊÓ—õçG|H"Õñ!¿ª/¿nÊ©ÆïÛ¡2¾Ë{!è|0h$·ÔR‘[Lrêƒ èŸHEbKÊBN¬5¨‰YGC+¯íq‡—E¿#(E½±D‹iáà?³RN/jÝâ­»:C^)^©‚óüÛnÀ«6Å1Rñ†P€‰;F Ø %þV,Ø]‡=¢jÜØ ¤ 2º£ks£bŽí—’e¬‰áž~lœ~ í(à6ÜÁ.”ÈtÅD½ŒyeæÊ=ͪBÜVw0s§“ÇÞ:¼™c`QÃÇU¶HæYE1—{´wïÀSP–ëë¡ÿgUg³_Hüc¾øëh^Ñkoó_‚~È¿èOQJÜ÷œÅ ï_!3ý¬ë»pôð#&N˜•^#{?AfÔàmû¾rIgˆbþCyøˆŠ0Þ„‚ŒÅÀuË}l=‡¼€:*Ü¥¨<&:·‘Ÿü½V-d¯–Bsi= …­bä ¶b³óL+ÔˆÍ[$›"®ËÒc|A[Ž 69Ä&ÕžÒÜ )bOK¥OÑÚ[БÁªJpùD¯²j_æ•–/в‹X}À¦½Ôøù ¬4,_aU+8¢°OÝV­ˆ˜Éêȉ Ý0âž.vý3¶ö$Ì5FÄÿ¢±& *›{¥SÓ´Fa¨¦°×%ÕØ†ä%¦h/05œßJFVNo£§y³§V!%Y™žeÌßÄó‹?ùÀ±›ìÏÅ]õ AËSf%)«d§ø™ûº±Ü€x¢jÂ}ÿh¿MLÒ¼bêˇÛT‘nm4Ÿ4ž¶~Xq‡±–±2S\,Ìß$«;Zs¯ÐSkåÈk ÝÀcùÔUéë‰dlV¢ùðÛínÎ2m·´±Òìªh³sU‘Œ‘4Ɇ"ãŸ@¥"µå E¼ÀkŒ:wš}ɽA8î£øº1”Šü­TÅ¿rË€®Ä&h:ºÿòYeUý ÌÎ{ã`¸ ”hG…™jÄ„IH¡NZxëÐÞ'š¹—}3T\Ò b©Vïo»Q¦åN©¾Ž dic÷šbÆÞD¬  ÒÑW-‡½/ÎËûV¿Jóau¾[yG”v‚¼ÛëÌN÷»$ `)x>Ô:ŒC%#87´"C°xÓ"±FMd—a†ÏÇåƒÆEÒœ¤÷‰ðj#_§ï\ÀK¥Ö5eÄ"MZãÀ§¡,54‹UæªTZôà ±öê¡Ò|.Üâû@–¼º†·ýJü>åíTÎÕðFm¢ðy =‘Ï)]àû@ s‡Y@ô~(Ìð`+óg9_7jW IˆáyÏ.y–GxQòUS„þœÄû~8é|$dÄ´ÄÆÇ¦ìõД4¹ªÌËY‹NC¨u>“Ô£ò¯¾)ßTn"¯2/u“®Âßo’ûRâ`['ê(`¶×#ã’©.§Ëî“ ˆôhEàÞÁ v)qÅs³†úü0ê¡Q~y”3Î5”ëJÙ—ã…é°ÃòQ'ß´øãJ׊ødÕƒ|4زRN’¦|Ú@µD…–4ݣů<2, Ñë²úUtTKÓ¦â¬V¼OƒÉT;ªÆ‘_¦ÑQêÚ,›=œjÉÅæ'¦ZªÏC؇E^3ŽC¯%QÏ4,ÏoKG>J:4;ٗ¨ÊÃŬ¹KŸ¯{” Ót‹=ó±ŠÀ2,¥B~|ˆï¯ð¹µ–÷$®T³óëw3{Âù\W9¥›«Ñù¹ƒA íL‹õÎÂt#÷­?æXR,qå³óí¬À5f\—ל¥© O4Nò$³>ÎmXöï._ÑN³ÃYóHsÀ´çA–\QþóÀÇ…¬ÑSf2Ò@j¼ëåïq hRµi›éá±Ê,Öˆ´ +2Á&¬f/¾Ô¹P‰:Çc¸È˜g~C¹(*]Œˆ(λuÚצâ5•›Ž8²‡ÜuõÀ:÷‡R-oçÌä¦GO¹ÕbqþïàÍ?Š1Þàíè#EŶïÞåïÂ!9­ù¹¿ÁIåŒ4ÆÈ|oÃÓLbð-­)aù0a|‹·q$fÅ`y¹î„Œ~2l-¤¿eì™nà„Hg8#NÙÇC4ÄH¡zªÀ­Átný¶=”<Œ4$QŠG0œÊO+oõô¼dVÒ¯ÝTFF±Ú‘Í,2;4¼¢8Î(ç›sL¬pB¾c̶ïN‘Zaºª¼w”¯@/5!&¬çRƒJ£©qOÛõ±^2,BV_´§ ’RLöGù,˜y½tÒšßÓë̓ØuIÝ&‘-GÒÏq-ÇnC$tâB5nSÁÛ(—Û²‰“¢\YŽã+¨¤‡ñ•6Q±)Ïu’H)=«ªk C>–yìL;[S”‰ ñP|,æ“¶Åîˆ';׃n§zò%Uw‘ź:ªß{ŠÊZkVÆ—‰4ˆ¥7çøIç ¦b ¶àÞa=uEAþ,ç'A¬’¢ˆcñw¼’“òïAÙì,zœt6`›¯hê22Ôf÷ å³¥{ì:<ŽŠM‰û; [±Aj$)«ApÓ äêûhÈÿÅ‘1L«xZ;žºIû ÒgÝ៟!"ÁÐiÂr~Ò(r·t›Hìuc°hq¶½~fÊJ¹ðZÇc¼*Ög‹áEǼ1ZŠmé?MV;;|ŒÓÇÈ{Ê€0zÜÕg‹¬åÙÌF _¢çoYrzæPSÀê*¡Ú099(ÑiÄ$‚/‹åèzÔn|œéðûï(”Â↑ì¡å)ß”§4Ï0ä>º‚bx Ѭ§2NÆHé¹U»κàN»N×ûážÑiHÛXÙ]mìþ5vÑZlà‚vñ’CMžÑSXøƒtb½ªífß\.À> stream xœ½]Y“·‘~gèGLðEݱœRá,`ß´kï®÷aeKtÈ ÛC…xŒ$Ò"ýë7gHTwóp0HöTW¡päñå— ÌÏWë"®Vü“þüòÞWßnWÏ~½·^ý7ü}vïç{"Üp•þ{üòê?ÂMÒÕů^\=|z/>-®„´‹vWÖˆE꫇/ïýõðËñZžà?ÏðŸ§ðϲ®B~Ä_à?oÊ-áæ¿Ž×Ú;¼ëp¿\}R„väâ½s¶m-_|Q.Ög^Õ¯oÊÅ—õb½ިݶ¬Âþz¼6 éÕá|”ëá/´éüì»rñ®^ü¥\ÄGWŸ·Ã—zG?þíXnþûÃÿŽÊÀµ^—Õ­âêZÊeÝüvõðÖÿ7ì×æÄªÏ¡­Ekí Œ_Ã'!%ŽT/Ji/Ã"¬j1F’ïoކ¡¶Ec° ¥ èúýcX!%·EJ•˶mqv„ó}˽0¬ºµn³¡mòþŸŽ×+´%í¶áÄ(¹B_ÌœÁ¥É-½9ªÅ¹M)¹ôJ¼ãU½›}‘z¶zúl÷Bü1ug³:õQ*MÞQ¯¥ç6a±sº¶YyXઊ3ð0Ìôæ½hg:L¤™êÜì3èC?%á[å_Ôf^ä[žqñ¥ßo<(}Xänð͘Òëuz‹‡Oyr-TìèüÏa„Wòð6¶» Gžæž¹Å×(ìBèÀ«úùæåH eÒ.™K´CÂ,Öì|t r²¾‡}Ç} M»Ê8ü*\éÅ8ÛËÅ8wNË0¿é…nÓä¹Û$ׯ×ÅÈ ¡Mš’(™oë\csQT¬¤5ò ”í`:M’ª‰vµ'僬å ²äý5œÖgI Á}ùW*Œ°o±ŒÆ}¨Ú¦ï–(æÎ¡#KRþ± †Â›5 [ Ã{Qî!ƒàtæ†4vðë£<|›‘›8üg\e ÿø¨aÐFáG .Õy™&ñ^0ÒRç«H?Η–òn„-vs`ÖEM|Ñóª2µŸI6ËC‡ƒ¤É j`¼‹st[Õ š^â2_qè#›.kÕ6ˆë`8ðVÖ3BõGxÕ§ªIg˜4èѦ‰z=Ù[ØFGs™aÍ&Ü 73['n4ÝÙ@+”Ê-kŽÒæV³–†4öÜØMôߪA.½¬Î{¨ð£èô*B¿ÓÏLGU‘· LJÝWÆÂඃ„;.˜V‰ëÜkµA†!’ ê"ûîNpódn†E¬çIÏ&4ƒC<ϸ‡›lcOƒÝµÁµÂ<®«9¼'8厙þ*‡³-Þ£eYƒe©3Ap:Ø5·„n#˜¥‹D$w]àYtd–IXå 2ånvÕ’¡v4ìàÜÏçóoÐòxŒ÷p¤ï#¢ ¯ÓG ¥ XÓ ðmëÆûjÝ© †±êˆ*pMÕÆðGVlá?ˆõý îú#¶^ñ›#ôtsðéû("ä/y4Ç·~¬ ÞIä·Þù¨Š:AìÀD¹ÜðÖ Þ×îÈŽcowÓçÔŒ'‹©ÿ¨ê÷u dájàß•\„°>C.<àl²>ÀÆ`Uµth Ô}2k`ˆ»>!Jv`ç'ˆ?®o«ámfRi0ö£Zf«™¢û69 Ã;ÓîÆãd§gaÒjˆö»35ä.¡»ØUdÁǶQ!ÍADɈf¯‡K .ç\k´p–JglÂ6ˆ(õGZd4ˆ·ÄN¡üìˆ ÷¾¾IŽð¦éœðÎß’ÅO5€=IÀ%Ž¿µñDìÈ‚`o8W†6$`ÏoDò‚º½Õ°ýUšŽÀ212i\­u'ž!‰[ ëuW¾+†nD #OÈ11bÊ=.M 5ÏÇùØ pŒ0,é[œ`Løž£úÞ윉òk‹hjÏ1BA—©5 ”}zÇôîǶ›„Ê ›G¯©³œi¿õ!4y{«,ä¨S¬3‡æ°üð€LÆ©4¸X_YzBÈ?+ŸÖ‹?–‹/êÅ7L¦á—ú5&2jVaÌ °ï¬/"Œý«rq9»!òJ ãUޏ€ÞW—§$Ü‹k´š¹Ûw‘¯!P²Ñ¬wNí–‹³ Ún=b±hV”¦y,®r3Ãß‹ ºœJ"§\ 󤬖¨§¿6”–V“¾ÌröpÇ_B›V´~Ó¢èÔѨ—'~hŸhY¯¢C£oC]h9/©UXB¶Õ#qU|¶†Ð¾ïŒ=5,Œ¡Xb”\kãùË ò–¨7ºV °{Ú…î•áÊ™HwR" d†l€ñÒz„ë£Ûv E˜*³•×F$-™a ËS‹1vB¡ÉêÁ{üØcS\¦o¨ßÏF.,æ¼'ÁÈ©¤‡ïmé7Ñÿ vÅ̧‰*ÔŠÜY°níÊŒúTMNqU˜Ô ­²ã¥Ó(ÁJàrÌœ¢t¨ª Ë3sŠt{×)âƒKâAæ1J{1:86÷øª2Õ-LÄŽÂHQï(7ÉÓsx™gƒÚÌ]GœEžÛK±1€àv<§,`MnÆJ•Òª<„LÉ>gU #y 7],G¢<ì’‹Lß Ýy$]Fcµ…´G‘Ã>;`˜¨«OÑiò)hR64m®5>éFê‡køÀƒÜ`òa¦Z‘˜°Á31–†*Ú,Õ ³é²¢•ËK)T-¢øÃDo3ñŠNü±~ÿM¹ø]óP®|øáì‡öÎ5ËZ™ð-Š¿óë¶fY›c O¤kyvì “œ_yEïlGˆª±UÈr©œìÉ Às*ƒ•îc8&)&>{°:˜A$ÑÈÖs|Ù@È US À”0Ìæb…™:‡TÍÐ÷qÎ#ǨšF²Ï{i…{¬ývÖæ5Ý{‚C±Ò]ò3óñd¯IÃçàEÜ^6ÅøXj –,V3YéÚ"η½øärg·40:í]˜ O¨—4Õš¡5ê¤BÎK¸ÆvM¸2Ï]š‚¡ñC¨Ý¦EEdâj»ÍÄœ.n„ ~¬ª¶ðŸåß©1Ë´†³»‰„)<Ÿ$0ð^a}/ƒá¡ÑO`aÄéAû@;ó¡ÆW$åÎUòÞÕRGf Iö»R~\NBáÔ×ÑÊDO“ï òÐKòœv¥òN@¢ ÙN¶¼gÕf1¢Òh·óI’)™zB÷–rȉ‹Å½ Ù|ɛﴫŒŒk®!žúùŠSµ*¸jJ¢+ùÚm¦èkaþ’uÉ iCœûËÉO“yÖ„³iì{t7Âò¾‚d³94@0B[gzhý.äÀ±! ›ÖH¥e奣vÐ!yhÉqš’ÖI4Îß:RêÊàŒàíAâ­±Îh¿ä£„¢ìvP냎2Óxbñc„¤>®#ûUùûõÈ$ØþúöUùPTvÓ”zð¡>ƒÙD·f©m§˜gpH„‹a#(Cœo'¤S–¹m]„(>Ã9Ю j±ž&LÏØžbÈé^Ù˜fE%yî÷tG³£m»ãŠ«!úw&+ £tv o+LÏñ§p3§Žì‰›ZiÇ%܉D²û£n½8a;Úýfø@®Ð‰“•$™…7Ø7Ц ¤ñ=Oó*ïºØ»a²!#?G$I ŒÁÇ|øhABý‘qçä ¢KDö›‚8K“(ó©+‚Õ¿¤+~‚žÁ«•IÂÒözR}IþN7ÆŽè´Åi’n{!{Í¿>ú5.Cm*ù‘U ú€*gy\¹Æíù&´ßI)É Ã”˜+»…-)õÉwdÇbWWwÇdÔ]É)žÆ²,v°y`¢° Ê®I·˜hYÊžÒMœÕ§U{”a®ìóêIXm¢ÿñ¹˜Ìɱ¤ÎžnUl¬ñù‚"qbwSN:ø&'¢²¢×Ñóàê ¸ÉÀ_-ü]C*1yX5ö&ÁÕìàJ9ª0ŽßS`pb†Μá!QÜ-[ù’‘Ñ'Ýp«œé-þ%Æ9ìT ¶n´q+(ᯠŠI°±®àuaî‹ªÊžÎÆÕ%À°ÅÖéU3øƒ¹ˆÛÁ¯áǾÌYçjjª4­áõ. UÄz=׎EuÏÞnT4á¤F'ÉÀvHÈvñjÚ¥3Íîë¸kÞŸÜ Õ²%Ú¹ø|ÞÜ òÄæðŽ:™Y³ls•§ÒÙ!f´;*¤Ïw{ª“ß'ž+)…à6“j%Åͼȉ´¾"mg 3j´BJ#ÄÏtoßëc9OEê|±v8ýAïìçI£ü`(’&áS@‘íC²í{àöZeç‘pw„ *<6Ä65˜õbn;Ÿ†q.©ŸQ@’ôs˜키œbZÚƒ8|M4sO»ÍJ1äoE[[³ŠžIl¨–äòµUööù,øb·ÐjéE•”)eÇ}醄ÿ§kÿÚ dëÁ¯åb=¯ñMýz)É~KöˆÈzX"æ ¬ lyÝŽðU½S•‹’{Ñ¿qMӺ؟ì[ød­Ÿ<{‘îpÀCòüßQgÄEÍÛ&ô[fsð¼Ù.ýÆã­1d=Ÿž˜å1g·".²;;‘â~í–©‹G;:Ú‡×täŠÇ\åÑXø 7”%ç;(5šnwPb»C> nB˜E¾ õ{àÎ:Î1ž¹iÍ8A–1~Xæš`äsßS›¹ÆcxÊ{˜\g¨çõ^M63NZ‹ >ChW5½¤þË~ë€[·/u·€ß'Ù¦\9è#ùt¥°š—œLfÉÅž»¸!b(ch5ˆìÀR:qÇ¥ÍeC¡¢0ÖÎ`š‹ä¢È‰Œ¤€3×8оo°?1…Õìúõ.åœòþÆg«+µçÓìBfMjAñ·É°g!qˆ£H{m¦Š;n’ôÙ=žPÌÈ[!D س,ž‘ØŒ³2c>˜$ÊÀÇÕdH“ql’áÛçQ9¬GOMìCªBÜ\0M²nDl1øÔp§LÇYE´ùL…“'ÅäòñSoý2Ù¬ £+a×ì,ŽñCòò¡f¼Û‡×¦ ™H1MàÙñNä•:UèÅÉ*[ ,šêtp®6äž'¼qeôfXIu;ñ2ÍB°n  ¤¹¦ íT,pÓÀ«÷à °;'(6]1…Íîöã1cím&†ª—B©ß9iLÙ6X™"é¶1¯©ç™ÁØëxBÆ£?JIðÕ¸I<ƒ,Ýd_©GUàRŒDSÚ‚+ô¿¶?d~޳qíÞ´®Ø¢¤iu8<=–®Z LhŽÉá$¤½ûQ‡ºDÅGžñœy_~ÙÎe:x?4õàC!ˆ‰ Ê%ÅóEdj%VÛ –Lg·gú’aÝúNšxuî„]&]¨¨u²{¹>M*(XM`Ê«›­ÅêÜAÎã`lùKâ.¶ápÒ O]veÛÕËž›Ä}ÞÀ¬vÕ°üžO?" wöÉ=c ix9îC:PÔ<)%¤N¼l°Ì~V©p GK¡‘÷6F0lzÄSØâ)^·ÂÉ‘ì„sˡ¸S0/ž‚·´çªh8›®Eã—ä¿Ý¼3±³'_™ncÊ'Øx} 1üƒ %›*e7v½E ?1T3Ý—JúÙ¿]uÞ¶†4ÙMð4¦+°£ ¹¤=cs°åËŽ•Hå%ù6´4é÷pœrà”¾†ÜÀéme¡Î®]Þ6Ìì‰öyç Ñîö‰ötOííô(hÈ)Ü£Žf'é$ó˜«Ï™zUœ*¥[ë[ý¡]’QPb£ôËÉM¿R C»ücêT‚.*—Ö*(2$rÀ´³Å§Šë®ž;bÎÕ¤u5<ÅBN·mâ·x®,¦ß5“"¼3šç¯oÖ!L‹Ó®¤—à½ÙÏ`"pRǰgý©4#74NÞ­Ïä;hK‰É„ èƒàß —~VtÉ”5‹ÜÕU˜äš•å_C÷ÈÅÞK†å*ivœ‚Ö°eáÒ¼eÅiVÙ—eûôÉŸ³x!kHzàÒ£JG¼žwyä´™k߃ sÐÙ×2ÇEBº„ÜùÁÄ„ìÅCÆá\µXÔ0üÊ(vμÆ}‡Ímñ_Ξu9Köh$¨´Ò!¤]ïøÍí]ã>"ØÃ•Ä‘ŠuTxÇïÞûüùÓ\Mendstream endobj 187 0 obj 6078 endobj 191 0 obj <> stream xœÕ\mo·þ®æGÐÜÒ†¯K®“uÒ¤E ©"4)’|-Yv{’ü"ù¥èï _‡ÜÙ;)±AΧÝ%—œyfæásÏ÷Å ÷þ—þ}t±÷ñ‘Û?¹'öÿÿŸï=ß“áýôÏ£‹ýÏŽá!5Á•a“Ü?~¼[Ë}©ÆÁøýÑÊA™ý㋽V߬õê ?žâÇ%| BH¹º^'å äêÇÕúÐjènÒ«ïËr}¨à’÷ãêîË)Üÿ'½o•€öfõãz}èüè±³OˇØ+¼@Œ«¯ËÅËÚëYíõY¹ÿ´ÞS.žÕ‹h$<ü¡V/ëÕçõëMüj´_Ô«/Ú׊ :¶ÝÕüõ¼ö@FsU¿Ö9ütü·=©k'¿üÕÞñ½V_5²oSzúEbfî×öª½/&ÒVU  Šô8ZxôWTÑëz•´:­>K îÝ(5P!¿Á·eŒçåªf´ö7Ó Óv(÷‡z¨÷QR˜e;âtñ’Ú{€=˜ëI¹ø‚UõSNºØÑcXsýà³/šÁ˜É “· À ¯x2SëQ2'½z„×e'ÅØÎ‹Òq„vúíÌŽiû #£Ñÿ,`õ°´&ؾálò”N¼SCg&gsÙÃm³#ìá%«œÓY¿zϸg“‡4F¨ì!?+fîúÑ-kéÑ-ñ÷¿+÷Ol¥‹O:Õ¡«2«¿R7‘ï?¡æÃ4êt*­ öQ§¯9—ÉŽã)UtŽN×Í8z;õÓ{ _.á+˜Õ…e²²Ó]ÎóÿLkñÙìf>/x‘}Mì+û#½~×s?Š€™æA‘zø¸iGƒÿÔQÃIÒŃNŽÖ[]×u ñóù}Q<ö&Ë=¶z–§\þ{ß›™+¯÷ÞÞÊ•ßaJ×Å´Z­V…ƇÑ_{ôŒö×Ôj/Šh/;½ÝÑh s™AP¹}ó·\ól#1î ¢òë%É:¢EpÖó·K|ä*9÷á(”û у÷wóF'Té¼~|$=]fxÊ ¹Ü*EôSXb†0ç¼=/Þ1“Éø&• ¢´6°@qYG¡TôQ„¢`ºùñƒµœs( z9 mR‚0=€î®µ¨¢ÜY3„CíEx[íUŒ$Ú ±tp§µeyÅe½v²¶é5N'¯4 ÖØÐÍc|•ŒÈ3ÝPðqØ•„/nTô섌žd’žÒfõíh;Ú4¼[Ÿ»\+úd¾K¦ù |fPÚeà£ß¯%ÃL«##°SCUxP@ Ç}µN ªñrʇy¤—99ÒyÇa¡{MÓvÒÓûqRB.h{KR.ƒ`²&«{«*ÂלåQr~ɹ¢+àÞFë¥1Åv8åÃ8çÃÂ’pêIƒÞ™% zª@e §È]ºó5µò’OP :h Ü¢ü$œ~S J©Ñ¹þ»²ø8UF²> H;Ž‹ö‹¦ŸRòøGЉžÂ`_­­àšïRÌ ÕqSûG A4X:Ql}ZõSU®Ý¼¥ËHQÖ Ú(: :Ê‹ Ù2‚t \"zD‹ù,ÐÞ¿"Þ4ÂËŒøÎ]| r=—A¥M˜GR”vÓØ4u=uÊ(mndÅ]Œ‡®šŽâw9iU”¯,cŠQûö6°OSÀ³§'#²VÀnò´ä*ð…6éÌM9‡M¨ô®Š©"Oš¿x`H›ä`F1²`ÝÝÙ°xLZ5öˆ"ÊØâÞqúçQ¼˜œ ÓÌvÙM3a>O§WGh7²oû€ˆ-«û®®ººTåUp©t´ œ%Jò”ë÷¼7÷%œ1á08Ð ÐH;°Y¿úr ÂvÞ–©I ZI^w8ò§{šôVœÉ¨*ÞЃ³Î¤Cxú©Ì‹ÁC9ˆï#…ùU3œvpÕs\UÃX"ä“xZ_¿òI À~‘ÀwÄ,Afa#g4 Bfr!3/ô eæïÖ ­´œÎH –>²î†CxÅZË_¸öçq>@ÿZ'¼ H oƒ¦ï«Öf#¸BÔìç3ºiжLü(qÈpãã2 Æ`lœF‘ߪӰ7T²bp*[@ÃæLT{ÏøÒp4„˜†O-°£ÏjóZ "8ûEºFai=sêѵ„Ѱ"è¿e¥Jmˆ0NSœ;î á!™Y n~ß!UyÂpœs3–¾Ü‡ñ©1hwÑϧ— S¸ZëDò0d8!–­þ€ožBO'– ‘RK|Ÿ[Æ%ë 9÷»ÝåËL úXù"¹yG]ççq6*Úa勃øPŸ‰\E ^OÚOZr±ÖˆJ ‡ëŽxa,fX¦hó@lÕèÜÁ¦àW–Ÿ´ÖÝaš°º¬ÎÄ;â“"É3ŽvÄ%Ê¡Å?ÑÛŒ"Œ«û¾î9N{&ÄH OØÅwð´s^~½‹Î SÞqæ% C¨ÇÄlw®&Ö ¼cB¡¢½ÂÊµ×¬ÅØÞ³ÚphëµSê³ð"J¿Ý (/61û^ C™-Ï‹C×ãnŠ+" Òä¼5ƒxWÐ!è £#‘ÙArõã0 9÷õݪ\è ¤Ù„Á»~PzÉÜθ¼‹3À0†Ü(Šrüš–È…aYíÒ(€8ñ–Ç$\ƒxRÙ G³¥bå3%üß[Ûž_Ws!á¡èoÆR±Ã{eÔ‡š.B\ »£ïÖ:ˆÊWAŠzÓ§s·›•vËivk;UÉ•î€^ÐøSLÓê èÕZ‡k’§0Ã!óNùHåm:’,…é\&æœN 8˜ežP0Lžª#(wfí!Ç ‡”T’Â|F‡fIœ@ðFY7i:„™m`ûK™8`»@|ycÕŸ7ª)ŽDûG97d åçÙ•|'œ¥ÀlÌØä1>"vé¬îâMMµbg2JlÚf‰ƒ .Eí,•—1jÙÂÄäím€ºlÄ›ö=:­rÞõÖYž6úwxcÉF6RÑÎÃ’Uµ˜ÀÉBê¼e%õÆÕ2:Îæ;*Gp†'Âbõ¸{IuBh{ë’º±“ßå[róaþ-Æ_¯²gƒÒί@_èL`–MöSVPwדdâÂ:g"dNŠCbŠÁGkcÀàÑ,˜I±„”·õ­.SœÅ ‘$>ÿqØFâ~Îö =™P p˜ Âþ J©noyÆÜîE2 =úàjGoʪu*P¯¶]$vÃÆDJTr×·'*a¸ãÒ265̓6ñP‘ ¢\ê¦â¿YããrÄ6ÞÖ]Y½N}¾½Ç ú„ÊØ7Å}ßTbÍ2”„F3Þ§fÄç³á€±Ö-f·IÙàÿù±«~Q‰OÃçò¸¸¿%o¨íÕ-º´ î“3a6?NÀ±@;‚øìÔt©õ« B‘4IÚ-k/‡µƒŸóõ¼ðos\³FlD¼L#ÔjÕ0äGk‰süqP©–w0lЦ1B)mK€Ø>n›‘Œ™§rP¹FµŒ2ù$1u.&=7_" ŽŸØÒlû ²”ø‰rQ[¢Y·ûK^¼¼DH\Ò¢ ±6¯5Ä-¾Lá,f‰ª”`£vY ?x0„1¬d³³0:ˆgk”Â(¢ºdRÎÕëâòYÏd]ðèd\•Ö³"`qÙ ´d5u«û(q’yIƒU#iýŠ$æZLß4KÙGw‡8D²ŸÙø††%I¡‘@xM7ÈH°h“$ÿÒÀT+öl2‰R‰Š‚ÈÚU’p×.ôøÁW݆TÉHÍ—¿X®"±aaÕX¾­û'!a+&Ó æ”ßIL…âQ‘]Y¥9"ØýÞ™@›Ÿ RÓô„B“{Va:_rY›úTÆ•Üý©÷™\U:«„ÒÆ‹Î„€Lû%¬éá‚€Fòœ¨æ¦—yL}†u‘Œ@RcØÄâÐÞÓ·Jb·²7ÔŽ]Hëo¡o»¨ÉÀ·L´3æºë¹ ½”¤/%~Ȇ›"R'"ÀÖ}G¯gl5ºÆC \™;PÄEÂåÍ{šêÞ@ŸÊ‡lÀdaëC9ÅñTL*ƒ¿ÂÍ#Öå?ãÄMLHÆi¶qàƒ8T³\£IönìŽN¿-nWˆaHûÀφ±¬ðX§J´XnQ+C0°”Z­P/ø=þ ±`=x’T…Ëî\[UµxR$WµÛÒ'©ÈåâOpÁ¥‹P…›Ks¿X3µ4µ6„”ìÕŒGÍ“qÌŽÜßÔû›:ÜZÊVÈô9Y×},Ø«åãí²\tµ¹¥h—°8JhÏåLïí/84¿®³­åf7õþ‡ö3îõ¥üÙÐÊnÕÌ4—Õòu·¤Âz^%Fên3ÆÂ¼4¼-KWrU­tS—1ÔÀC€“à¡‚C«uüXM–*#ë¯LÄ‹¡¶ðIr}¯¡p³aö÷‚Æ XN9É‘¹Ô’°ð5»O+ªK“÷^³ËO.!«ZæáÕºaâ^ͼ\[C"È®Šm¢æ¹—;áPü’õ†3‚*4<È1ùà ^qSa›ŸUXÅãêXLŠÐù •–ä'>ÈTÊzçÌ„‰y|âk×›87äË.v–<ä“h/,463yAƒ× òbÂêY «;kýO–°—ûÝÌÞ–fOä…BÚõã×ÜLrÈÙpO6h¬.&ÿîÇÓ™Œãy¹Þˆ âç`>ËìH‚îŸø «‘Á&gº)nô¬<\˜%ÜxSù ôH™_=$ÎWS6¾µ*ø¼ZûNÈ“©<[‚òrD/·û)Š™k|ĉ ù «¹0ÙuŒ¿è÷9ÜvÏ-‰ϛƯe¯ñ˜õ¢›Æ‹v†¼_r£ßpód ÓÀ ù s‘+WƒòO.h?À uT¦†¯Y[lðÅñÞßá¿ÿË=­endstream endobj 192 0 obj 4479 endobj 196 0 obj <> stream xœ¥VKoÛ0 ¾ûW=ÉC­H–Òq‚ Ã†m©²27M‚åÕ$]ûó'ÊÖ«Ö’`EÆ¡(Šü>’òcL0 |ºßf ÆU5¯ŒõÎ ö kÃ^ôö€+«ô§o^å«é;<ŽÃ°ÉM°cö.PzýÙ¯ºv8Zå"„³ã~¡fåš:µú'8}áÚx%úê¶9Þü&’YÅq–ËRq;õp&[” ØâlEo¯å¶œ-K/Í“-éM–v8æg'öw[SÏ«ƒ‡¾®~èmüˆ:× 3z×A¿k õé`#â9@0?ë ßngõkûr?õòt ¾Ï<ð§“[‘2±î˜Ùõœ‡Æ‹F?ö_Dºúï²õ¿ dwº£qèŠõ‘èφàÀ: Ô%¯^Z‹½äcÊÝ×Ü g\^%±¼c2Ìó¶)YR ")À~XGßäç/Çùe endstream endobj 197 0 obj 767 endobj 201 0 obj <> stream xœÝ\iÇ‘ýÎå؀٥U—ò>°ò¯DÛ2¼¶VÛ\ÐvxhH›3C‘"%þñ‘gdVVu÷ˆv‚¤šìª¬<âxñ"²¾9c3?cøOúÿ“«;Ÿ|eÏ.ßÜag¿/ï|s‡‡ÎÒÿž\ýû9ÜÄÕç³×Zœ}'>ÍÏœ™Õ™Ñ|êìüêÎÞØ,½·Êíæ‰ÏR:ΡqϹ³Û}6íÙ¬¥eŽïnâ­BÚÝÕ$ÕÌ¥S»Ç“˜Õb÷"øº“0¥ð.´ Ë“ûxR®¾`Çœ¼íë:öe˜)}Y[Rœ{ /ˆÝ ©òÈ-7µßǸ곒,oÄ]ø‡†U×°¸éæ—øV7 è ÑÊÅ‚ ¬¼àºþLFZ~N '­'ƒ"7’õ‹C-1yö®~ }¼Í'¯–æa¿žP$„c ;”éü)¨ÏÝú¢2ß:Égý"*Y¢ Á2 —ü-¾ÚÎÌ{[c¬Qð ´yüþ£UL[¡…)’glè$IŸå._ ËÓ0½Viáð*Ž“ñ°…î4º4¸‹œ¨ÂóôàÔPw{•kÞôÝ$ü,˜–aõ‡Õ×´Wòþ›°}ž{xhÆ L‘ï‰8âî‘}µºYL­³ù.$ ïÎû @IÄ-,•–DÑoÂ[A¬$“øxÐÁu«´ŽÍvö.h‹d00‘•e¨Y?-ûù´ÊV•ÏAÏ#µñ²Š*1K¥ ¼‚…!1D Üç:‹öXe¿ sß¡0® ˆ*ÚhÁƒ@ƒŠ>É—^æüŠ iþA! qÖÜÆÀ çUn¤ÿ{â5Æ’‚¶~ 68-¨€ í%˜ÇÞñà0œUt³W,xÚØè4…§N“#T0Y¾ÆÉ3ÆQ£`ØÞƒz…Žojã“ÒxS_•ÆòÕÈQk63 (½té‡Qòp//'Ý ãNÖθº›öÅ‹™Öª¤Õ¹,²«µÛß:´K§‚ÖÚúàp£æ;Á©Yo,v0X¯™ñ¸Á0öÏjO¿žÐšXp'ÑÊzp‡IzCëŸjä†?Fã†,ê;è}©FÁW”†;5÷:“úgš‡µ´±±Þeù’68k†v3{Nnˆ™¿©Þ²Ù³Vu4ÈŒ}KÁ0bh-‰^¾­®˜Ìdìï .ª»=´÷rLÂAUí€d½}ÝûnŽ&‹ÝœšFÊ.={o2BFmGE9ëð›¢Ã¨âaFA¯qoP._—V¼ô-ߎ#Dß/Û~•¨(>òvdUæÚ¸mF¶€£Gп‡¹­ZpÓY‘@bezÛâÿìÁuˆâŸne÷÷‹ÞC÷zBž®2ê‰ð¨Å¦E z÷IÂ=NºƒïB`q‘ð#‡à¼>–ü55´¬ä»(‚ïñÊ«âñó€…LhþŒ¶qMOÂêØFa#Âw3D›ßÑ*‹p ë¢"øb²ÖÑSds[ŒE$ظ^ÎÕ§a6ñÙ®ÅïÞ7‡,Y†œ­Ç;Ó{·Âö.ÄAA\`:ŒpG&=í–帵¹¸‡×­Íˆ·_¤ŽF6Cîâž•›ßÕÖÆkjz–ãyTÒAæÆ›Òâ X;X©ó‘º*Ïjã¿•Æ£ÆÿÚÇÏkãë’qRW0pú|"ú^neõV6j|TïE¨1­-0¼¨µÈx©¤ëLr¾|1ºwd”AVAÕa£œ£2ÍÇþMóÒ;gˆ¨Õ7À$:ACÜ?jÝH%P’Àdé–¨YÀ pHºuwŸ€Ûy þFF¾*êÇ îCŸ&ŽË­|htgËœð/!VkŽ"ç`×!PhÍp/Y?òîvÎ<ºŒCˆÕWª´0QÀôÌ\±ËÕFâ9°\·ÄƶáŒÉ ·-›îá½ñ_|¸5ò™…!¹ZýhIU`ƒãì,5”7$Þ0nZ&Q»——ù>¾l2¸…¿L‚þùø“hŸj?÷RÍM'šWäÛGÖqLQŒâ‘å67ˆ#É8þÀœ$/sWÚï X=²Š[aìv'¬Ç¯Š41qÒ‡Õ‘¥º n>ˆ(DZrp!cìü,…Úýöêsä§!Xñ»?O$B—ÄǶé°|7 È¿4«ÔãÂëåiµ¼ÞÅÔ±Ú%ð8%°BUW¡bÊEŒ³lݦˆ¸Ò•ö¢E= ,FPÞ°[RqD°Ä0¦¸˜A°:â È[8<ÀË9¤1Çø Òþ—¡®/kã “\؆é¬-üò°6>3\UæxûÛn„ÉžŽÐ[>?®³xæoƵ2Ùý2΢B3“ü¡!Üê£ ­î…ûQª:ˆ™//ê½—ÍäË%8Ã{—à .WÀ™ŸÍisÎKUÛAæj.ªð£’·üŒJåó0ê,DÇÉŒPÔEâ QZ• #~ܨxÍÊl±ç×ë?£Ƥ&WaóeÌ*‚FØ)‘Äùc…%ÂHâ`¸$ܯ£¾èýÀ±³ÐÒªInéÔòV[€D¦@¬û¶d‘ [ø.ÖÖ½GÝØK‰âZ°‘à-‡FYŠ>þ® ñ‹e ü£l ÌE¼ôÎ åqª¿Ä‡T€#ƒҺ!<1ÐÞ Ë(àÄIrZ°hP\4ä sá=wÂáO"÷½’‘]A~7 ߬E,Âa®u…>'ŒFÃÅP­u¼™Gƒ^OÉl…m¼åìs÷TxB9«»DÀñe„ÒR!§SXda™Âº© ÐJµXJ ;2fÌX ’îFsàÐtpeIȋ鰲ÂoÅk³tŒ.>ñ?aª-Ì«ŽŽ^G—ÔǼ£¤Ñú$–˜J$hª yßÉÛdå·3MÃãŸ%(ÛqcnC—£eãp›: í¼†8“imkoÑp [Œ¥ð¢õ™`¡Ûëú3AÞë~QZ‘P/W„ï$˜ö²4¶|ãh$äñÍ‘ü,é ]FC¶u®_O=úî0ùÏÈk§&v!`?D;˜úÀœ+zƒùcH×T·^ ÕøƒÙƒ€x‘y'ĕڥ\QádùPô±ŠM¶™Ü\Ù6Ä4‹@f•6;ª²'{7¨Æh‹l•’mÖe)Iüx9ÒøïIg†%:’¬áG Ø52ëë.0Z˜VE.Êj6iX»6B_9Àa†º"âvž-ß=¨ vGÈüìÅr‡JƒHÅÃ@gHéÀû"NDen!ØïBMnLÈÂÚ¼›Àt‚¹¶èmƒ‰"~lU1etÛX<oŒæž×å_ÅõŒÍ¶S—œ6>šo[ I™Þ|d*8€D~ƒ/Ü+G™¹¶x%-ÃÁlK‚1y#ÝF€b„Í|qÈ™ñ6¸hkÛâvYnÉv¡Ä—¥ÓÊš»Ux¯??M±„¢ˆ«îñj(Þ,“fM5P-J1tœ[M¼oÌ•YžuS½Îw™z¢.ù&5vFëSªWsþ ä#ý'|o•“Œ4sãÎ|`ï jBÍ ©ÞŸ{ˆtUËSÿ¤åöþ¡vy sÅcP–ªË±D»Vˆ„žGáÎbÔI‘c‰µ×`B}ç6.¦FIò%OfŒøŠ¦Êh„ÃPµE#°AwE•Ê¢:ôZ‡[0µ#ùºGP苯ž7mHAŽ‹§ÉÙUD¦=Ò²ÃΉl]´A¬‰•ôî®–ô*JDM䮳¶Ç8áªÆ¡* +xJyEcî¡ÞbŠáVº×˜Õbvb‚"8;I‹7©ã!á÷{bxé ‚8Ë5Ÿ‘É»ÖO, .`Šû®o=Õ» %¸8.|ƒQ‹åeu>ŒáÈ<ÞöP±yѰ8gϘ-ZàA´ÿjøEäÄ{bÄŽýN@™_C¬å[Ÿnæø›ãžÝ“DeŠt¦­=^šæÞbÀñ™ì  Ý!¸Dúa¹Nù¤ò÷Ì).Cæú¢^Š…ÐÅHSîF”ôðtq'·Õ0?‹¯ÉÔ_#Šæ?¸‡@Êåä;ò”V¹ .Š£â·ïqUñ¬âî¿Ê¥ix?ÉüßÛ;Ûà.ß„ØG¯wp‹#£LË›)$lÙ’ËÂ_(¨Si‚Ä0h |yEG :ôiȦª1“ÝwIn‘Ø_VýƒÆCæFk ÃÚ,ÁÚšíŠ}}à„Í!b6Ù¹¡b÷ì) ?³ÂÄÅÁ(9ƒHlTäöj¶ æ4OŠ8·N‘©ø} º¹Œ~¡£¬ÄƒÌë]Œã>ÐʼnS~tñ&jwp;³.–™õ%ïqN)â;îLT’µÓΪ¤‡Þ÷Y•ÿ±÷êaX€¾(Y_•Æ_Õ;?/¿÷›!LNN솥Z$Ý—FrFöAiü¬\ݯ?ÿ¡öOê°>*­ÕFQÿu8’zd?…šI@Ñ?§¿æg>K ªHÀr E НŽ(Wѵ#ê«ÈbÐûzØ,éà˜ÈÓrë§õwN™|­×ÝÊ¡àñgÿS©áyÂ?Ö`™ÿ¨OìÄ8 ÜÙ2 E/Ô¸xž»Û ϗǼÚO-¤¢ø‹mŽ“6Xph쌟Ü;õ¨n$@ú#gädäÂeª<×W¸rÎ3Ëè±ÊÏc\ŒŸc:©’ßIJšx±rqü£æH‘¡p®Mö¬èÃM-\y>32þæSÜucÚ°ÕZ1+áUó°òl9¹’Ö{•QhÎ¥ˆÙu‘˃Iì>Îkƒ¶Ü%’J¦ò¦¥£ŸtHRŸ»‰Å É‹¡7à1`ØJþ§°~™¿¥[×~³+%ÙȈmG ¹Ö‚ û©¯ é5¯LýÖÙÓP¦ÖU$°Í/"fË_ƒô“ÔéãLAyš3ßÐ8T6„j!)¨@4D~+.â㚥§±¢H¤O»4'«èW£ ké‚b¨±]¤9´™ÉDÇb“Uì¤ã©˜á‡ÒH`«ŽO€Àö!ô]«U\Hw*_>&³†©MáŸv~SO´Øþúk:Uåå£ ÌT!s®Hª2HЦ‘¬WúThyT…;¶<˜…j³è§;ÜÔVâzD6RŸr(αr/Éñ¾—ÉŠñ†P½½qylÖJLDÀ˜8¤¸ G°H„aHD!Š%qnÁ>w4ÉbÆ…¸é?}ñ“}Þﶉ}ÁÇÁB¸ðùÜd9…Âøóýó;ÿ ÿüW£žÜendstream endobj 202 0 obj 5132 endobj 206 0 obj <> stream xœ¥VKo7 ¾/ú#æÖ™"#KÔ;@m‘¾P ˆ»‡ŽÛ»6?oçß—”F¢f;뢈ՒE‘?ÎûN ÕIúŸ¾/nW'§¾Û=®d÷~v«÷+• ºéëâ¶û~FQ"¢Œª[oWy·ê‚¦sV 0ÝúvuÖo‡Q÷7ôØ#ˆCpý#þR*Õ_æžôø<ŒVÆþkZo§MY•Í_ÒÏ“ú¸¦Ç=6ôx,«lü¼¨BQW»¥x¶Göá]nÚí^Ä>6‡7{vIme¾hVdõIpÀ…7ª1|dCv¾¯†b)ò›zྪÏX}ÕDQü°ìn8_ÿº‚„uXÒõ%qß„Svœ/¹~[O¾™åÌ8+ÈôMÏâ?yù"/ý_,}3ðú[^*6v,=ç%¢ÇDŒ#Æ6ŠÛ¶ ÕCS¦Yër_m)-'§*´°!(áL7‚FÇÓµ¦Ôø dB(jŒ“ä„÷>Á¬ÖRÚ j@ÿ4ŒR€ó ms¸ÎygþÅÇ»âãŠ|D,å<©M´|Äo¡ÓŒÆÓÞE ¼¨í!O†ŠmSEœÂºÂ]Òq<¦YÌ@ÔØ!=hƒxµÛß¼¯¹Eã­$ÀØ´‘o)%B¯õa„tW¼Áõ÷ÉÄ”/í£Kü€Ái Éß'%VV×tñE6é") è¼?4%ô¿SM©>®ÿƒ½~—šE" 4Ëš¶{¬ÿU6ô*LɉִùÞ¤`ÑÙ!#þ»æùÏô¯†Q¡ÆzÀ³¡„^¥Ÿ9\e|ÿC† (CŽÓtìF…Hpr¤ ñt_ à£djtjP¦Ý;àT1†ˆ2´KUdá}ÞÍè ‹!¡µ‰Ð~3ØgKëÍQ”–Ã¨Ä ÄØü…3=ÞÞa‚_¢%…±Z|ˆÉ*÷û|Ìa›[KmþÛjýÍ— ·uh}š¦¹KMÜ:ý´ôPÕfì9 m])VC6y¶d)—„/ëpSË{ ãÏÂhȺŽî29\•ÉOB¢od©Lºx6ìÍc°™àWÃÂàÝV!;ÚK<®œˆ*ÆÿÍã$bRë ª¦_îù¦ûHMÆí´h:ŠéŒâ1€=¤ò¨V&ñ¨Å~€Ûõ‰´Q"tAû°0dž æöy7$¶ˆm”›A'œ@Â;Ñã3ƒ‹d”½ÆÃç)>0)6‡Ÿo©5hXtU¿-Yy¹‰B5/7%WùR5„ Ók¤6VhP“bñE™(Ê4L~Ÿê›0‹_?¢ãp¾ÿ…¨5D­UAR5ѹF†F@9¤LéˆY½Ûôzq9q¹>×R5\ Ž6ŒJºœÃEcùµ?Ô<•Ô5±„œÛ,“¦¡î·œ„ç©;'Þú2Ñœœï>÷!Bw†#Dµ C3.½í¢Ô±jy‘ùN¢C àŸ>BÂÐÞ<½k ãà §äzÏÀ* XFû(îF Fx—·h4÷ƒ%ý«õê5þÿíùendstream endobj 207 0 obj 1157 endobj 211 0 obj <> stream xœÍ\YsÜ6~Wí˜GÎÖCÉGÙ²­K±FÞd“-—¬ÑUÖŒäÉŽòëÓ tƒlÎey¸"“@ãú¾¾Pþ4ÈR1ÈìŸæï³éÎo‹Áåb'¼‚ÿ/w>í'0hþ:›žAH¨P©T&Œ/vêÖbPšT Œi®ãéÎo‰Ž„È‹TÈäùPÀ_…QÉËáH¦¥0¹Lö‡YZh™IŒ]©1J&ÇÃQ}çªjrQªäL‘VZ%/†¶>+ªd>e©6¹’Æ? ]šä$²"/\)ŒšV¦òý ˜Ã=Ôk¥„NN‡2EY‰¦,W:y@Á…m®¡¹iVP¬n¡P¤²2É%Ï¡£Ì€Üæ¬òB(ý¿ñ¿-V% —VY%,V9À¦«r0>Øÿó·zÙE)2™\ G:UJUú‚µV©Ö"¹°#ØÒ†ÕÉ L²( ‰·CY&_°›k_1«û3™I.í*ª´*5¬`.M.`å:ù€c†íà% ©s, ª ““ž,HÀ=ê:%s„ò<ÍéZ¸ü2KxTP˜Ke ˆ¤ªrúh×î¨,S™çÝiØžíØøö€ã4$j ö,Œ$æeš P¸ ’¯'‹Š»ò£èÄ®£L•¬PPw­€‡G;¨Jó¬ͱšW25²KOÀ6^ÂL%S€’CŸ YѨCQ:ã µü' 9èYjGÍ`€29²Jé"`Vã0»¬q³E¹)DS«QÆXS$õj2A¥n…kHºî0 }+D™Œ`mRfYi×=ò  ö™åõúk&D^sK n†1Y­Mv,Ԩֵ㒡ª,”›.hM[µQo…¢?Z‡Ê[€¡O‡2³þ®°&#a:7±A9k2¾3NÇšúª,m_i–‰RRIŸT-r½ÿžeg5øXÈŽn±TÆ9 ©‹T™~‹µk3šö¹Žn5ö´p† 3“–JxC¸FO¦A©›—+Dá÷¡í¶J­Ds×`c<øÝH•¥6V—º‚¶cÛƒ_°¼ Y’?ó}£ðCÜa „)§û~­N÷ß–< î¢ÑË¢h¦o Uß¾ùÕhÞ #öí¿ÕWVc>µJ¡Yû釶vˆÚÅB †f²eiÂaEô(ù]ÇŠk?êóP:yá•àXu¿ŠÉÚïÿZkgNԽŮ;ñ1”ÀhÆ.Ãyf]‡%«rv@ˆ±Á9t&ä‡]Y*”¶TÐxâœ<(a‚n³véu¼NòЦ£¼€©d 0¹mè%ƒ:¢X´¥óAÖ[Ô„¸8 “9ߣ*ð„žÛwWmUÜÑY7¹¾2 ð->µäU•…å&H<`!°‘› R‡*ù)ÔŸcýi(œaá5Wxé í²ƒ5ÔYÐÈN%þQ·g*V ç„ÅŒ¼73ˆ$I!dM…—çê·)üûuÄZMÑ¢XO°P½*lj™Y°·îM îÑ>*YÆ]¶ê7­S .Hµ2Œ dD¦,µ‡aÞ¯±qŠÊ9³5(g.—8…sl4§’B7[#U¶\¾³à]ûÃÚla|7ïí«ÝÙ4O&M­*2§Ä¾g8”¨­×V±fvÇY1˜¼ÎJ‹'o°Dâ¶§}Sx‡…Ô£@ ´$9gZ^sž…xŽE3fY9 ÏqN8üU\Ñwù"ÿ8Eõ94Å﹜FÔ?Þ‡Þ ½±?~õµ-zjaË ÛR6Þ¦M”D¢î¹õ]s L(lDTò–#âœRê$ˆ¨¹—¼EL§¡žÀ†fðˆ=½ …û(9…Ç ù0»>òi0i³¯èø÷~¥Ñ¬‰¢ž-ãµkDÔÄÞÂÇW÷z ¿ñ¯É„ ™C®BrÏ8 Ñ6nXrg\£{Î ×çùеÇót…î­mÅÛCïÒ“·±ðn øgµÿn㯿1þØéœÃ?VYDÅ{Á§%¥ñ’“òŸñ¾–¸®÷ç·áÇ¡2Š…Ý ìGû—åŽð~u éz* Þ;®á©«ÙKˆãJb²ú"¨ô^>C¨è‰é}°ß"TL9.>GÚÚ€)ÑÆh¿à%Ï9VØäá'²)ÖuWcDíöb¿Ò£½J¬Ó.¿R{ç ˜»LÖ×Þ nxoú”Á÷©}ö¯3è —§‘ýßÜõ ‡'ÉÏÑŸ.Ë*7s7VÅÝ ŠI$“v&Ï<µð+èW—%!ÉûÙt•“ñ#B8áVĆœ‡Û5e «Û î@Më(oë„’ ¬éÜsÍçœd|ža©¼‰Ál®£qZ¼ö: Ã`$Î VîúxÍ‘×ç…3n•ÈÙz­\ÏûB‡ðl6pt¬2 <âqÔÆ¶Éõzœ·1Þ»ƒà™’˜Rî‡Ú7vwm ¾ê°!96žÐQrío¸Fh1K’MÞ€ÙÈ?§¤´ ~é7Éh˜Qo—ÆÞÓÑŒ†àHöG¬AæV‡8\wÁíK€â­V+›WË;«-|‡Òy„“H%IPÝNã(Èax= ÂÞèlÀK¶?oB£¬Ça0•Øê¸èëñYš±³)Wt°´tÌó6ü˜¸¯cø×É Ê_»ÛYpˆ`O×ÏY°{ÖHa䥭ۈÆÛ*O·G¼¢ª|žÞëANÚ‘ž“À¥¸2ùÅÅʆr„Ô5y” m”­:×rB£ ±"ï·ï8þ‘Ê ŽÊ?04ßn‡··Üµ ünUájóÃν@&¦ïbó9v©¾èå(GŽžnCËf%—ˆñ]W‡­ymOwBŠ8ât'‘Oh¥ Ê݈ҹ1²‹ Ë\™Å,9‚B®ÙT´BN8jøÝP‹Q~ÏæHÚÙ˰D†'ËþÜOAXZq&ÔgÙÍÓŸ\ÖÊvŸ2«ÒÀ‹&–yÊ5ºáV4‰Œ0¤¸ÕÃëSÌI݆úǘ¦W1C Ï⥠)dˆÕdTÿ3,¼âÌ uþ§mYÏ3"µ@sY•9?¥õ3f×¥‰\uGÁf¼/”܉*Ù¬øD#ÏtÕë35òµ¥þuOŸ‰÷dùæ” æˆd«”qý¸Öu1§s7É™ôNï8ØËn ³÷YôXÓ‘–pû”EGÉ…Où>p€M¸­ÜœSH‚ÍŠS–{4ª8/kvã¨Ï䜪ïÊ´« [n}ó¯cLìZ—ÆÖf*ìp«‹®Âº»©U7.+. >Ö¦òeùtøË <¥:ãºæì•¹²ßÜ.Ö¹1#Tk|vwÏfg¨Žw‘äÒÓéÕ_aùÂ8è"Eé†ýûŽ"ÀkÑ»îÇv$3b¼Éáùd£»'Þœ[<æ=Ž“ÿ6Ñ'„åêï’q`Ôa¿- |DSboïָʗøN—œ}.Í×É+]·;W÷•¶1©ñi“/‰%1¯•ÝJÜF€ú¹t7q–TÿbŒ~îì,~ ÊÒºloirߦàç+.Ìâ-坸anßùo©¯8%a0›W²÷ºë_£?¢#b¿‰ º=±gu Œ.¹‰<†Â/œ6Î#Õiiq ¯gá¡î uüéD~ žþØóÓÄÛ65dÿõ³÷Ø®Jô/¸zŒš³n§•â3ª-Õi]l¬­Ûãgïo#µð^ƒ·ßÛµ¡–ßjV÷YÝžST¼=±§6è³?l³Íëû͆%/F#Å:áÝlM;yÜÚçˆø¶÷o5eár”ìÎØÓÛ„ªoAèŠkÕøWÆ–#c|“×±Q˜ý]–°äž{˜ŸC£“8Œ¼°¬çeN²Mf7”sn‘ÑÉRµœrÍÙÃÂõ¿‰æ¿:_ÿ+ÉU#}ê˜1ø4±u;Ýùç G¥¤ªÌDÈ¡†,ßýó /Æ;?ß¿¸óÔ•endstream endobj 212 0 obj 3207 endobj 216 0 obj <> stream xœÝ\ësÚ8ÿÎ_Á·ÂÍ@-?ÀžëÝL4I›4inÚ›NJÍ4Hs¹¿þ,[ÒîÚk zÓ©kV²-ýö½’úXµš¢jÉ?êßÁ°òú´]½™T¬ê^ø÷¦òXQ‡ªúg0¬n÷ÃNvRšˆjÿº?-ªÝ-Ë®¶<Ñ´ÝjXùTÛ®7œÚ–¼ìÊË—ðÒ´,!jïåÏŽ¼ü%/;ò²o:Ÿ†—–ë6-Q³åo«Þ°›Aàû­Z;¼µG6Ýš·ÝAû!^ñÆ/HOÏò›ß® Lû7h¿0Ä1GqŠ¿ ϸA;|»‡Æ9 ?i[áØÝÚwnœ/†ø Ä{n—0ø7¹a|ë:¾|ôQ«-_¥;ŒõPÈL.Hý†KCý»ÿ®"œ¦ç~µXéÿ–ÃâcÍɸ¡£~ºmËâëcÇ6†øÄ[`Â¥d‚ÞûKÀ['ùõz"‚à‰ üá ök`zÁ«¯ú1Q".aîJ¸"HûæÓÐÓ µyéêΚàËÆš–ÆêJ=¸ˆ‹À Äúž8|¿çXÑí×ubˆ·œ¦"â<{-/¨}DžGj…Ì šUZÒ<ü¢5"þnWiIËöU^e«Ü\Ÿ8Kr…&ðʧ0×kÀÿ ²î¹ LY––);㺡?)²3ÛFâ#Í81?ÏÃжÍ*VáE¶Mû´÷±¢jâ!žGÖ$ÂvMJHŸÉ°wMùÁº—0ìk{XwMû´Ÿs èY;ÂóÀÚ)€ÕY;¬(¨ÙÎ8² ;ÆŸa'™e(ÜU |bÚw ýØÏ€üèÿ*(ï•@Ù[Ê{ÿg”#W÷Ö˜ßÈXš~R9qÔ‡ n­jpro9'×â¡!î¦M´¿ Ô£¬+4ö  Þ5îQÔ?Àwë:ÞØÏ6Ñ(WÍ ëì!ê”{ü+ÇÔ+¡…Cn…âÇgˆàذù_fô…`ðQɤgÛ~ $µ 8Ž ñ+—6ƹ1ŸÂeá‡i@„›HûÞ·æãYi0ª‡Lä@sÃØ6P zçù>'¯(#dÓ V{†dšÊx>sü¹ƒŒ‚Ói=Â3«Î<×ï,J¯¹ö'<¤ìDj¤k'S R†ê41—£™æ½g ÍQ]ç4‡JшµÙ$qy–½T>Ï*Œ(Š<2D”è,Ósv ’q2<vläì(•<á¾ ¼YI÷|ØÙö1Ç‹€þ{ÂP¥tnÿŠ*ˆú<8iÁ˜§ðù,×·Hé{$J@ µ†Jƒ¾í1q›2‘©d0å¨=NÐXsH+$K‹¬XÉrB0QaI€IrÁD®žˆ2RkÕ™ /5=/‚®DšËHfÀ«“‡Ê-wò=ÒŠ«z܇î.ÖG_-ç,Um (ã‘5LwÙwBœá «oÔÕ –ïcMÃ)âÊV÷IX¥ÚÏ™ 5Éé0ŒÀ‚ì-D˜i"¾ãžhÉ%ú”dlá2È–¡miOP1¡\¸HÄAA÷¡}×ϸ°aÿ ‹H/TÄ´eˆÈ_îpðËçK ÕCˆ=ÿ¤|wb±™$¾·Ð÷žë[È¿íükoÿdÆ8³&—®®*â Â_†w_t`,«Ú—l¡Œ½«Yk¯ÃBhÁà»Wߢ4þ§á»ö l.¾¤h™YG%¶Ç·oÌ’ì&Õ^gÄ;2ñ1‚XlÄÛœ#>æ ^êªØÃ7&¸Ïà›·IZ$Ñž+:§–%så¦oÀž'eH"D‹ƒå¯ ®×°;ð¦Ü;ﶺ@v3¦yîáõ¬Ÿ@°³Ûf³˜+ѥРԎxñ‹SÄÛj±‚‹²Ò!‡à8!vòDX€~/ÈôÔÔ7‡\Oò€˜†´œ€å›rüÁ»•ÈLlf[¸–X„æ ¼‚´xiÔecÑIÀ¹;W±ž ª6å0á8Í[¸?@¦æªåbt¨ªö¼×wÆÉ*t C¢¬ë\óW]=–ìR-»iœ…ý?ž†6;Ì`ç]¿þð¢Ð;…HVtiñH f”¶H^àöëÌB¬:5üÚÉf•]Àªï¦óL ЖcvþBOXõ­ýo®QÕ<ø‰kPå×@c­ö2Nsœcù“3ƒöô ŒôP]„çØœ¢ÌgŸÃ Œô„î‚Rþƒ Õî0é¥Dö@ÎXª‚%uv•‹-(¨9,Ï€ØH…‹|ˆ!…òOã"QN¤Xaüç»Z±Ðóhê“„ÞÄP½É‰]Ó¹lî22w>L/HP*uPg$·ÔΠK®}Êqzvé½záÞÉ„”a^ü¹–ïN¦ð~n#>èv]yã:ŸèDBâ;Mß×Bò¹ž‡¸µarè\y€M¿¤ÈG2è1­x«oVÍN³ˆÝpnšÝ5óÚ îØÜÜe¤4˜JÙAtHõD™dboÞEaÏz#ÔRŒ+Vò4‘Æ$™Ä6”²’O¥¥|^î£H ߈A+92¸¢U¶Æ:\7ûpA"91Zqb|‘T\•B(³GfŒø–&»Ù¬j"T²Q‘—l)Õ l­ Ð8ö€);9ÖYI¸‰]˜r+tñ%púîp Ñsé f±ß šž­ý{BUy ¨_Ãn7…‚´ohgF(ºæ§4Ÿ*%täotØù¢¢=Sewì+gñ&®Ö¢2Yf™<ì Kl¹#«žŒÌÕ$¦â8^Ekteª|¥áT8ŠÙV@®9e¹â&qIÔ‚š©Ì&4 Ž»€™ŠPï™J"ŒÌÔÏ(wÄh·*[Óf ¾ä\JnI|™`¤»-ާuŒŽ¼ ùsº«@J<¦‚`ùuþÄÄ5*JmŸhbÀ¯O…ÿß‘†#›¶-ª GýÏ#Ñ«œºW êž|¢Ó¯|ÿüÓ ?(endstream endobj 217 0 obj 2457 endobj 221 0 obj <> stream xœÕ[kS7ýî_áv§¸û~Ì´ÓB)-–˜¶iÚÉ8€©1Cþ}¥]I÷ÞÝ£µƒ!ÓN&›µVÒjï9÷)å}?…ý@ÿ1ÿž\õ¾9Êûç‹^ÐßUÏ{ï{aÕ¡oþ9¹êoU§¨T-£2(ÃþxÚ«G‡ý2…Yõ³4EI|Õ{38nă}ÙÕ—·ê2 ‚0l韯õe캼n$yŒ‚pëßÁp#•eQdƒLÝe¬ݹ9néù¥k<£ÆÓáFêGÂ]«ÆH¿#ÑãÛƒ&®ñÔô r=ˆÞi‡ì^È5ªéÓ°•E>˜£wž»Æ 5Ò’/©ñž”…º/ôœöù=Ý^Õ·I\ Þ‰¥Ø[ý)A©fHõ÷ÙÖ©ýÀ{ë²ó²ÉÿÇ?õÂx”¦eÑï÷Æ_½©AÞÔ—ý#ýóP_~·jªëËKuÉ’ñ '¤gô|¶²xg† “Âl‚Ð…˜¤ç„É-'œíùÑð ŒÙ ™i”ˆ1îU€åìãçDH¹z{ûŽðš!hÜ:ÁªtsßiéKba˜!ÄŠÿ bghuÔx…çâEvuka›6j•ñÔá—I‚Qîvhñ=p:7–ønÛ¶õeÏ]Þº¶C×Yñ J‹!]"}Lã‚,k»Q™x-l”g2ìßt¯hжkÜ£Æ=ò H·K9cÕð-”ѧmŽÍTL÷”ÍLå6Íô´ïì:„¶ÎîËÎ5ý LãÈÒ:‚/ ˜êÊtu;GÒ&ÁbpÚí1a#óa7Èž@𑆭ˆæJpÓ!\ÝmIÞ®sä‘3¾vl’+‹”-\CÂõQJåøÎcm`ãS….K8'Mº@ï\ƒ`°uÍgb|²2Ekº%@Š’1«ºÆ­gD1"·º ÒD|±ÝÊöóð4²ûOái86õ¸¸¥€¶}  `ê÷;äÔ%ÍÓ ÙË„.~ÆEjíå$(G&üeÒ[fo Ü31'e¹OQÏi7ßdŠÕЯÿúÍ‘þHF¤0z,#™ìYàÿe|Ä F¼CW°–8ÎAEÛc]ˆHc}çÔiË^8T^r@DFÁàáéâú5³"²SÂûavÕÆ Z§…B”“5ÉLëð°:X¿8°þÖ 'Ð 6@-¿E2¸#Ëtƒ}BÒœ¡¢Ç£`=çíž0ØkÖ9j~AÓ!³ cgâ9C›¥[ÖÌܶ0¡Ø¾R* ŒÿtÚæª"õj*P)/£0_uNÂâ‰C¤™«&>4“ÌfÚ¹ÞY ¬€‡œ¬wap¾{¾¬N!ãS–cÙÖ‘¬ˆõƒ œöÞTH¬öP„çÃî2Ä3#äq‹©&-š$“W°¦BnšÝp!d«nÐûRl6û4Í ëÍwÙMÂÅ”±eÝAmpYȪ.íò±‘Ф–×"“ ;@q×¶µÌÎV–ƒ¼¯ÒÜcXc23$åy·”—jY žpÇ{±ä$¨7§q¨î=3‘Â0å~°ÓGƒ¿Ô|/Š) wÇ«¬¹Fî³t±Ý“ä7Uþúiäã¥%^_ü«ì¼ã\‘ÜjbtÛ5”väΈ–ÑàÎëÉæšCi•ôõ\1*PÃɡԘÓZ¹ÅahºÍg`4æ‚Xvgáuµ{gÁ¨HúA ¤ Iʆ[Ó²*‹÷üÍF˜ç£¬atVPy³\’ÅG± *ÛZ°dÀ¶ý¨XöÊÚÂfg=•L© S"á¢ÁuíoàŽ}× Úþa\$~Ës­Úílj¸ÓëãÌ;á.> stream xœíšÛrÛ6†ïõº«Ô1O"/“Øñ$ulÇVNÓédÉvÝʲ"˧·/@Ø]ò§(ÙIÚf2™Ð¸A|{‚_º¾§º¾ùWþ_tž»gW¿»£ÿŸu¾tT.Ð-ÿŒ/ºÏFZ(Èt‹—ù™êŽN;Åݪ›žJü ›ÄÊ ¢îè¢ó{ïYöžšÃ–9|ÒÏ÷•ê½4?÷Ìad¿™Ã¶9|ì"5 <_õ"óÛï/ËÒ4é…úÔÏBsiì::¦ë3×ø 5.ûƒØOõ¨wî®ÏÄõ²ñ„®qŽOÜYÞ{¦GõþFÝ»Æ[j¼t jœè÷Άù8oÐËM]ã55ê'Å*ó²tÈE¯tkà{Fö\Ì{gs…)ë™è—½u)ûÇèUG…^giw´Ûýºï®ù¹o;æÓ~î„w-òBØrüÄGÜ£ŸÜ7å>O­6Ü™bŒéô¸o ‡Iâ mÓ£‰6á©P€Ayq`4ÁX{.Ó¨/î}'R7øP©‚ßü©è ¢ü±˜‰òÔ]iÏ[á[sxæ°n ˜…°1å8MÑä'ÑM‰N )_ÑÏù‰€«­5ŠŒµ¶øíÜG¥Ëއ14Ë!AüŒÞsR¾Ru,¯_" Üõ0 lyfg9Í,Õï¡ÞÏ‘^•¸ý!ëýÒNw³†Ù7£7b¢7«¢h‰8aØÙ&—Ƚh&—þÈähÄÒóÕ_sI67^…À0úÚ<ׄ¸Õ 1û‘!NЈ¯]£ôu48Ûç ç–ÌyèÌä<½5yö£èA>q&§4m˜–âÁÀ“P­ït}¹ºñžçü™Q¦c¼Ÿb—8x ]g£°X4®7Éyò¼o—¯õà†¾fU­o=34° ¤‹d ÒEr=§H¿4šÀsô LrŽt‚ÌxŒFwE£#ã×LÂ(?»Ÿ ê´ÖZYDNjÖ±ç²Æ×\žN¾sôËØÅ× ï›­# Ž4Ñ7 HØðW…ˆ[Òé b¿†o üïgb³µßûN ø®¢ÛOÎÔöÔ0Gy䄜IæÂ{Vy!§Ï”ÑÌ,ËAŒv¨¯ûQ¾¤€/¸@ó³ uœ?²°¦%›?² È‘‰D†Ù3€l½¹¯8<@¡v()89;$ŠÃÜÑ@ Ñ#PHg¹ó)š:¯•”üô¡”‚¡§T–µfå’ÛÆCiáÌê4›bÑR5Ðå°°,V³öö%šÃ tûã=hÕÚʚǛÔCém¶{É5þ£SvJ¿>H[¢Èc<ïG.Ô„0e ±Þ£W]"º£ ûà†JŸó(qŒzºj˜óú@îPäY ÛÛìkÕ–ÖÀì‰çBØfÏ¢hÌ Ȥÿ²P? g¢˜Å±i 奰H{ƒ‰å,׿°mëàšVY`„³„”ØD4ÔOÈ‹ÆÃÀìú”Ec™ÏÔóÄ¢”\Ü2p%sçÚ±ë®î¸6—GÂÏÆì·7ÛTºáóWIK¡êu›jÉX9å}Âå0{UŽ)BNÏ”‘ÊúI¿ôp K4Ð…Pób¤q%¦Ú:¥•ÝFH¬BÐ6¼¯(D~‡ÜZXCöçOîì­Uæ-l›ŠÃ©ÛgjÏámð{¤#>E·Ãå¾(ÁØÛÛ<ÊB=«©Ÿv äfX Q/8óþÓ¬¡ÞB[FrålýD˜(«³~Í%˜«ëŠ.=.„µÛÛŒ<Ûhj+ ¬¡匞ð]™âÂdßÔû­kü³]q¬;X_YaüŒœþfà›^Û~ fgï…pîõ¥½7¸~¶EZrÌ«%²âs1õ\¹Í`aÑæ*—htÐÇ´—“ÊÊæ©s°;6ôV™P˜Ý—œ^:á2½Ø\aÕl–\Áp•VžIeEÊd«ÕÂÁ1ÆSn4e?Û0 —6Uä-¹Æ­˜˜±«¿`:6ʲ8‘°ZÛKÖØ|ï<é‘£ûÎ }H¢e x›Oý¶à¡ËmÚÀ­›ñ ô¾lú—ÑsÔç„8µjUòÿÕîUÚ¯ ˜1£=t›ÛZy!Ë¿^YâÛÀ¶añ»Á·b×5v›‘•ïm¶Êx#ƒ=È_õ]Y½ŠœåÀ0+ëÒñyäé¤tÖÖLÛ#•å ãä·U­ïæšÝ® ÅÓ÷n@²ðÃÉ*TøÕÿÚÕ>þKJyM,ŸAl¡s ØW83Ñ»Lr£’ܧÎ+åúöAÁfŽœ}2Y%ÎR[šJ¦À-å"7$ë5'±6 }²ñþ_úÎJ Ï3ã[q½bÝeÅÊf¬—:ë'•ÛMÿRUžª”Y=Pqꩤ;’@gkE÷Q?ÖIslä·G7úß?ÛàŠéendstream endobj 227 0 obj 1819 endobj 4 0 obj <> /Contents 5 0 R >> endobj 26 0 obj <> /Contents 27 0 R >> endobj 33 0 obj <> /Contents 34 0 R >> endobj 38 0 obj <> /Contents 39 0 R >> endobj 43 0 obj <> /Contents 44 0 R >> endobj 48 0 obj <> /Contents 49 0 R >> endobj 53 0 obj <> /Contents 54 0 R >> endobj 58 0 obj <> /Contents 59 0 R >> endobj 63 0 obj <> /Contents 64 0 R >> endobj 68 0 obj <> /Contents 69 0 R >> endobj 73 0 obj <> /Contents 74 0 R >> endobj 78 0 obj <> /Contents 79 0 R >> endobj 83 0 obj <> /Contents 84 0 R >> endobj 88 0 obj <> /Contents 89 0 R >> endobj 93 0 obj <> /Contents 94 0 R >> endobj 98 0 obj <> /Contents 99 0 R >> endobj 103 0 obj <> /Contents 104 0 R >> endobj 108 0 obj <> /Contents 109 0 R >> endobj 113 0 obj <> /Contents 114 0 R >> endobj 118 0 obj <> /Contents 119 0 R >> endobj 123 0 obj <> /Contents 124 0 R >> endobj 128 0 obj <> /Contents 129 0 R >> endobj 133 0 obj <> /Contents 134 0 R >> endobj 140 0 obj <> /Contents 141 0 R >> endobj 145 0 obj <> /Contents 146 0 R >> endobj 150 0 obj <> /Contents 151 0 R >> endobj 155 0 obj <> /Contents 156 0 R >> endobj 160 0 obj <> /Contents 161 0 R >> endobj 165 0 obj <> /Contents 166 0 R >> endobj 170 0 obj <> /Contents 171 0 R >> endobj 175 0 obj <> /Contents 176 0 R >> endobj 180 0 obj <> /Contents 181 0 R >> endobj 185 0 obj <> /Contents 186 0 R >> endobj 190 0 obj <> /Contents 191 0 R >> endobj 195 0 obj <> /Contents 196 0 R >> endobj 200 0 obj <> /Contents 201 0 R >> endobj 205 0 obj <> /Contents 206 0 R >> endobj 210 0 obj <> /Contents 211 0 R >> endobj 215 0 obj <> /Contents 216 0 R >> endobj 220 0 obj <> /Contents 221 0 R >> endobj 225 0 obj <> /Contents 226 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R 26 0 R 33 0 R 38 0 R 43 0 R 48 0 R 53 0 R 58 0 R 63 0 R 68 0 R 73 0 R 78 0 R 83 0 R 88 0 R 93 0 R 98 0 R 103 0 R 108 0 R 113 0 R 118 0 R 123 0 R 128 0 R 133 0 R 140 0 R 145 0 R 150 0 R 155 0 R 160 0 R 165 0 R 170 0 R 175 0 R 180 0 R 185 0 R 190 0 R 195 0 R 200 0 R 205 0 R 210 0 R 215 0 R 220 0 R 225 0 R ] /Count 41 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 24 0 obj <> endobj 25 0 obj <> endobj 31 0 obj <> endobj 32 0 obj <> endobj 36 0 obj <> endobj 37 0 obj <> endobj 41 0 obj <> endobj 42 0 obj <> endobj 46 0 obj <> endobj 47 0 obj <> endobj 51 0 obj <> endobj 52 0 obj <> endobj 56 0 obj <> endobj 57 0 obj <> endobj 61 0 obj <> endobj 62 0 obj <> endobj 66 0 obj <> endobj 67 0 obj <> endobj 71 0 obj <> endobj 72 0 obj <> endobj 76 0 obj <> endobj 77 0 obj <> endobj 81 0 obj <> endobj 82 0 obj <> endobj 86 0 obj <> endobj 87 0 obj <> endobj 91 0 obj <> endobj 92 0 obj <> endobj 96 0 obj <> endobj 97 0 obj <> endobj 101 0 obj <> endobj 102 0 obj <> endobj 106 0 obj <> endobj 107 0 obj <> endobj 111 0 obj <> endobj 112 0 obj <> endobj 116 0 obj <> endobj 117 0 obj <> endobj 121 0 obj <> endobj 122 0 obj <> endobj 126 0 obj <> endobj 127 0 obj <> endobj 131 0 obj <> endobj 132 0 obj <> endobj 138 0 obj <> endobj 139 0 obj <> endobj 143 0 obj <> endobj 144 0 obj <> endobj 148 0 obj <> endobj 149 0 obj <> endobj 153 0 obj <> endobj 154 0 obj <> endobj 158 0 obj <> endobj 159 0 obj <> endobj 163 0 obj <> endobj 164 0 obj <> endobj 168 0 obj <> endobj 169 0 obj <> endobj 173 0 obj <> endobj 174 0 obj <> endobj 178 0 obj <> endobj 179 0 obj <> endobj 183 0 obj <> endobj 184 0 obj <> endobj 188 0 obj <> endobj 189 0 obj <> endobj 193 0 obj <> endobj 194 0 obj <> endobj 198 0 obj <> endobj 199 0 obj <> endobj 203 0 obj <> endobj 204 0 obj <> endobj 208 0 obj <> endobj 209 0 obj <> endobj 213 0 obj <> endobj 214 0 obj <> endobj 218 0 obj <> endobj 219 0 obj <> endobj 223 0 obj <> endobj 224 0 obj <> endobj 228 0 obj <> endobj 229 0 obj <> endobj 20 0 obj <> endobj 240 0 obj <> endobj 18 0 obj <> endobj 241 0 obj <> endobj 16 0 obj <> endobj 14 0 obj <> endobj 12 0 obj <> endobj 242 0 obj <> endobj 10 0 obj <> endobj 8 0 obj <> endobj 136 0 obj <> endobj 243 0 obj <> endobj 29 0 obj <> endobj 244 0 obj <> endobj 22 0 obj <> endobj 21 0 obj <> endobj 230 0 obj <>stream xœcd`ab`dddsö Ž4±T~H3þaú!ËÜÝýcåTÖnæn–¹ß_ }·ünÃÿÝR€…‘ÑÍ;*Í9¿ ²(3=£DAÃYSÁÐÒÒ\Á17µ(391OÁ7±$#57±ÈÉQÎOÎL-©ÔSpÌÉQé(VJ-N-*KMÛ윟[PZ’Z¤à›Ÿ’Z”—X dggõg0000230v10122-ãûÏT÷˜aí‚Ró¤~WÖ2§ar7ÇŒyÓ.¨›Ð8A>bAÄüðùß5KÌž8}R÷|Ž…ÓëZ:»šëå~«Îü®Ú;ƒuN͌ʪ꺪ŽÞ†îv¹™¿~«<­ŸÜÙÓÒ-YWQ_Z6½mV«üw-ÿßšþÕ­õ-Ýå’¥óêgLêí™<]î»ÊÓ®ÚöŒ®zÉF-ÖªÙusæÎš1§§éi×¹®ií»fpð/þi¿„í·è4öý\/¸÷Oááa`ðv( endstream endobj 19 0 obj <> endobj 231 0 obj <>stream xœ­zTT×öþGæ^»2¹Ôܱw½$EÝXEª€té0”aÊžz/3Cq@@ *v_Œ1Æn4¶—˜¢‰9—^ò?ÐøÖËË{ëýþkÖæ¶svû¾oêÚ…‰D’…«ÖMž$ü5’(âuáß»cý¯ŠÖD+è)†ž]kM(´æçôCê>hb_J,-^±ea@`dðvoŸÐÁ£Ž¤Þ¥S“¨%Ôdj)µŒšJ-§¦Q+¨éÔJjµŠšI}D͢©þ” Õ…²¥P]©”5ˆ¢)Žb¨íT7j0ÕBõ æP=)ªµ“ú€êMP}¨¾”Õ²¦¤Ô[K½-ê.êAm!a"7ƒÈFt·‹[—3âUâ]—u5[õ±J•t‘JÐÌd&ª[ÿnáÝÎwŸ×ÝØcsç=K{yôú®÷¢Þ7û¼×çj߉}›ûÙõ3÷ûÕÚÃúŠôà[óÞúÝò¶õÛo×_g#±YdsÐ6nÀìͬø|Pô;=ß¹Ëõç®É¦ ¦¯œ3¤ÿ°!/‡®6zØáa·‡~u;¢aÄç#¾I2rËȲQ²Q>£¾2úò˜¸±óǽÿ»h•Õ»5,h³…_fU·Ú‰ù¡­+Ù”+¹|¾`¼{¿Íµuñ+“\×ɽeme´ôgoµü.Ä$A¶þýÁìkXœ+[…o²¸ŸÄIQ#Cåh ý}ÓÄ¥‹6Î.ëÍ«äf~’ITyí¾+æ}ѽ5ê%î…ûÅ"ܳ?CÝP¯¿CRa'Ö¶€¡àDÙŠCÍÆF8ûÃÊ]Ë]a-ñ£78„m sÙºs30¯ƒ…îÝó¿ð÷ØúϦVñžŸÚ]Hœ¾V¤%~ÚW.WÄ)2<ñ2t89tfk4§ä,´7‰‘¸³ÖĨ˜þ2å…AÈ cƒ7Ò¶KêôWȾàJ{„BéTÙ 2ä@w_™E…YZ'XD§^ð»Å­Zç²E!W*!>‰ÛlçU·éè8°Å«ñt<»bw4OF¡™ß!b²!#NŠ, <‹€ùoÚƒZÐ1´qÏÇHôpiébA•L!貎ªÁ,h¼‰·m 6[¿¼Œ ïö—ÞF Ñ#¶ªåHU 0W?žŠ­p¯gÚ¹{öÊb ³¾kZt“×À ?}‡X$û=î:×mkX¸Lúì‡ õp%C±UÖæóª¨öhéÊ¡ZÔµ”ßÁv÷Aìá#¶óZ1 u›‘C–É` ε­—Èq˜•Y’¬vßF³È¢“%m¶m8YH²J#Ç»IŠÁ*X’„eð*`ð,ð×Tg„¹û¼ôqmë<Ö¯Œ~•–¯’²‹ÍAÖ ux šŒçÉð[ÿ̶ç%¿·#Ûœ‡Ëa-‹ö¯Éšs‹#V{o \·v$ÓçÜ+oŽ5‡¬÷ÜE…„nó}?fñ’¿r:Œöœd%}V·íÂû13t,~÷{61ŸíÛ_e’é‘‹‡ÐàëèÌ‚"õøìî·š¦m¢Y%` :gA5{DhÐC´Å,nŒrØ`I0žºÏ'>±í¬4Ã#úYŽï ™K¦ËýÆr“Q²¤£¦Y šë ±Œ1KP˜UÛ¹×…l|í±/ˆwEJËkØ}yéåýþÒƒhþ M$UüðË htœJAL€1ÆTlέ®ö«r]à½Ô5–“^G]h,{ œàtƒ¶YW Ð ¤JvÑvêœ:Á@í9ÁÀf :Ôaàz3fó7[ç°m‡þu‹’Zý Rkûàq{µí ÇC^­ iîÓßf¿2}fÂŽqÜt”ÞizO  fûBÌÓ‰}š Jnâg”X×”†FÑäGéCä6°&åhXÈlòqŸ;ÓûôWœ*O“šL$Gʰ É9iZmI §Ó®¸ä€ÛA‘d.}èoŸ÷ߟ+ÛQí‘é–ÉH¯Ûç,Í;3 ¶|ß}Ô%m²ŸŽÓ&fhaò ­Dö#-€@Šâã8•2!Q©ò¬Ü1$”½=—ÚûT„ɪƒ*ŸÇ’÷=H@$Ñ€‚-ü‹5A’}«ûKcøGؼ°F÷`² ³@†Ð ©iŸÜòÒ¬Wû>šÞ„ªéGz¹—l-mÆ]±41`9ÞRÛ"›kÎýòx2eàÞÄ”@¿‰Q¾Õ'FŒúÏÀS°vCÓðT´îê­ò³{HEÉ_Sr3e@4Ë úé2`#;~8‹†Yð0´2X¢™í?xŒ’ û WѸÏÓøº+•W.r§ƒ×ÓD}z-…ÇE\‡ä8oA{,íip졘o埳uºœë\™E⣲#0ï óÁ‡˜ÔYë8Cqô_^óÔù‚Ðâ^¸µ$uBè„Dè.øëk:PUn k"eA´H‡‰àÞd'ÓhxŽ•…þ0)㈌T ¢ñ¨?²1=ÍqÉ‚™ÊæcúªóÌ PM‘á±ô\˜„ÆŸ:Py¾Š#^Ü>è¤ z(Fa‚åúœ›\¹`Õb“Ìi·ªœ¾©ï´J%ŸÃ ;¾IöÛ7ÛwDÏQuì˜ —ÜȰˆJøX1? Ýg³J‹ö_´G¨z§&BÀY%Ð`½&'" Q­TÊGàLÜU+òH¶êlË ˜$”¿Æ^ à®õ'DH_€TEžŽ‘Mz¬.%ò 5+5[ÀKÑ×T˜é êÊﲈö¡®hÌ}1:‰F³ïn¶ß Xg¼¹c¹»Ëë aÛc·Ú]YýðùÕÏ®åÈ´™d½= ¿†Þ—È’[Õž'½SÁ“˜]Gq>²Jí0«X¦¿£‡lñQK^­`V1+ v‚‹.B0«NcŠ$ß N‰›„³lF£je®F ÷Š0%vj6©CÀvvXU…êì¸4EŽFÄtœb3RrÉ®R_]ßá%lÐz ×…\U®/²Æ¿Ø¤Åê“/èÒÓòDu6Ïq}ª\8d›úvÏÝcв _cÅ£Ã&ë¦ëŽOÐÌËWÍý¥ÑrtÿK6ս­ãÇù·e§‚íéµÁ ùåÁ49ÑDÈ5x×{4l.tföb§eþ†¨òÊbCynJ³VVQ{$‡ˆ›#§=¦È¼héQù&Õ‡ª•þó·o„­Ì{Ï‚/\:ÔØ\Â%£Yì(züÂí.[¶Õ=ÙtÍN'™'îvîÌã‡ó3Y´Ùefo¹-hÛ •/ ¼7¬ƒíÚ6=!:!!)_ÂÇlЕÿcý-¤C4ý2lLOÌŠƒx[¢+4 µ°·]ÄÒ°+Õÿ@'% üdåaQ<»{ïÞ#eå–º}ÍB©ý5A$®tqBÕ™q¤o‰NˆKQ¬šk3÷ÇDAä¥ÛBAA–¡ýzÍ2u4ì'm ×Ï@«i^ý=fmœVƒÚiãÚ5ê]@N”ë,Úr¨‚&u™@óaúä<(SUÍÇŸWydÊ6gÊó¢I¾%&Æ 2|·ö”ÎDdAƒfw‡‘ºÐ*æ˜È üpòj"$‹JˆB;‚æó½XôY§Îj¶§fZ«Í̯hf¤1¡M›¿øJ›ùKæº:EFËô¸EÛh(mNaé“™epê‚Ê<Ë·é×Á6ðR¯Þé²ËÏs‡¸€wYH=‘{z(&:ÙŠ@®»ç: ÷+vÛ¥…|D,Qâ‹H¶u( ~7½ò¿áj,oÕ$òH¢”þ4Æ|±¤S4¹™Šïña}î‰ù©¤JË/´h á5øD‚“.LˆŽESE:±:%~$ÖØ`12)³Õ©¤ìÊë¡„ëOÔàs˜šïƒÆ¶‰lRâbw(âÂÖ,^)¤ãŠ(¶¤fš )( ‹ówiò>zaßéÓeÄ ˆªæI½YDdÜÆ'b„I#·M¥ð‡8&¨8¼²ÜP´ûÓy à~ïb ÷Åo}?𤿀jÔ3;;TjnçÄåñ^Àl˜ºMG3ï4Ϻ ñ®%È$β¼*¤Á•|Ùm1R´ŽaM*²1Ï}-eTt 8 oïGήŽt¨ÆáÐ\!ãë´4Rü£KZ\ÉRÛÐg¦æ Mk/mÛÉ«Bª×ÚÞqü êÿ($¾ìU!â¹’ Mr$h;gÓa9˜ù·H×ÅwóølVŽlL^Drø*‘âÓ‰O^Rº=#‘àê¶^‰rPCŠml‰ºK”øj¢Äq÷][1C,ê.yƒmÛ3™¸µä’ Lúžd—ÑhÔkbäz3«±-=R·ÓµÜa î>t f±ô»ÑHrñàžj³ »b7šä‡Zåïèæ*$myÈÞ }ªÓDöÕëÎU4ZöÖœ ÐÐcqɉ"»Œ|£éTÉÏ®£˜Ö)lb®FA¶ú_•¤ šM©J«¦­ä/ƒPD§¥h5© ~|Û3›¬x­&˜|È(‘ñGè h~A’ÒG³E½vÀÅ/À)PÖ6~fþF´ ½ËM¼D<Ž¢Y“Œß;<#uż;œüðóX"õ{Dâ’ì$]J¢Z‘¤–ù Ÿ °Üw‡Öû†KPÇhl:sϼ˜Ùx ‡¬²ÃÊ[g™…¶rë q«'zÂ"W<ŽtËñ<OÃÛˆN›ˆ'¡Åh9‡¦"…¿fÇá_£|”‹F~z÷¶gábüÎÌw!7¹cÜbAÓîešD¨ë¥'Äh± ã$Ü 1’¯> /€ä.^ÁLhaxEU¡¬Þ«fÇ36 á0=Çï&¾þŸ4GS³·]hoáÐÑbŽ.³h®õDÔí¾ý5~G†_¾1køKQ¡"•v4t%h* Ù⤆§ ¼­­;s¯A©uå±ðkhÁµÚcý¥¿ `4Ÿ?”Vh« ̲ÌÜÒÊF`À¨Ð@oL°,)>4À˜Ñ™lCÀ>U 0O/_¾^]\*«ÛS—V,L @¯‘+SäÏDåÅf—d”ÅW{„oUlsãÜjÜôaÀL\¼øƒ­&Oó.Y\Läða¤­à—çi _åë îÌÂï×£Þ¨ûO-7jc[6Ur*×ÂG]!Y뛺ËÕ ¥EIñïìÈÅ-Çí­? —•ÜG]aºÃ¢Ícd¯‡eíu(êP¨bÞ¥±o·fÂÖÕÑÞŒý(y“dŠþÍÒÈ6¾Dô îq:f±‚«AVó^|[Þ_…BÑKåÒP ¹&}¶® Àä?bñ`Á_Ÿd)|™^y¡Z{BWFp¨¶Ã Ë”i 2é©ü^¶:Øàh ²TšÕ\G„Â,­“*­O•]DŸ^Ü@|r=çmXü–eUÇ 8cûÙ‰o ÷Mx–K:§U€"§³cDÎí=Y²FŸÌù¬ó¯Ú¶o éÉÄ3§™u|Á@Y޲%þ³(Fú´"ywr¥—1(› ³hó™;ç¥ÙÀ­=¡º¨©Ód'êU?ëÔÞÏfhu9hõúšã–í½üïvë;Ôå‡ewf:q°yá×|H»WÜŸûy9ñ˯ÈKðËxÁ/׳„<L»$N_‘ yA\Aª!*˜òHC@@dxÐÆS§¯¿ø˜“¶µNìZR¶sgHÈÎe!UUeeB$èzâøÙFdW/ª3£Ì‡(Ó,nØ:›mC’ˆöQQ>š^PƒÆA1I¼lµQ reHbl‡Ø¡œ»ŸdŸþ9"Ÿ°$†;=ò÷´HÒ,¿85‡$l Û väãéí£€N)IW¡ &ÑËK‚˜,d5º”t¢R¯œËμÐÒ¤3 q§*ˆ ^¥‹à¾D“-‡8'*xîmÇÒZQ5«`74jÕ¯*ê}ñäõ!Möi¥Œ WUjÏêŒDXViª„«¼ < ”Fò¥‡8kµâ,šÅCǾ?Þ w7£ußï?Hï^4‚L€èGO‘¤ˆÓ t•®ƒykÕÛÁuÞ¯yìU´Š”ˆ‰[>l]ÎþóŽëÌ`&ìYÿ0„m[‡å×ê(nñwØüúŠªOµãWA˜wŽ_iŒAD%©j^ѶËÛó:E~{ãYuÌíØÅÄ*GpíØÞ'‚öóD1m¿ÚdD¤©ò tiiù”ÄÎá_^´wéµÿ¿Þü_ß,àåûÀ.Çåõ[†kÿü–á÷®bÂìíÎ+þ5Düëâ¼âÓû³Ýì¯öÓ^Vt8ïoÃÒ´+TIÄycÛ¶Ùài|œ&UNúÛÝg ¼ÝyKÚ“ÂU·M¸ã4!×Ûô¡ –µÙáé¼\£'ÂFÿo®¾©)¹^È©­ÕFŸ¨OÈ—ŒÔ<4›O³Aïµ¥w´í8*ô·¼Ìˆæ¿¡þ&4ß$Føû칃®>‘AAEu†üìt‚i:­V Œb•¾É W®’ÅÇù¦b’Ó”i9w¿DÝ9´áíÿå6²°J~héÝÇfë¦GÈãÉòGý¥mÈÝfËh”ŽúÖµ”5)¶›¸wpñ+‹1îÎj8·õð,üH$hLú+6 fÑS$þæïä>é”o±x‰×&ÇpõÀר•àNQÙ ·Hït£ú‡G…‡`•…+ö‚M„Has”·ÿjg‚~‚3ÂŒü'×s "´è‰˜ä_²YÂ$ÁÈ`¥÷už²„ –ìÀÛªé ³.äåf¤ß€<½îyô, Û1Üe0‚I—C‡à`6×BÃIýÉÌ©¥ù÷œEV/oùƒèþK1Zß:­ , ŒÜÁ5´9jc´I¹`› ú4mÓ€'±ÿ ¼‚ÛZû— =€Ê„í/½Žfòάónå(b>þ¤éÊÕ‹®óp\íÙbØÏëƒKÌ“)§'zÏnb¤Î¥É‰Ë‰¯6öy¸vçtûц<_ú3²úæî/uòƒžM\„1:{E#3Ê­Œjö?ìWÑì1vó7Ξ¾ðüÝ3Õ¿jîØIÝ“{¥üp!€ËŸ À_x1ºÂúÒ8n˜óÚ(Ýž@î@fU‘%¤ ,Ú?Ñcé‰m_‘f¸78_?dÂô§SÖo‰tqå¶¹„ºÁ|÷ûz êúñ¾¦3¥îû Îàw!²ŽÂ8ÍÆúŠ£{ój kÔl/rÉõM] Î̬íc§r˜‚7ÑÙF4±3ˆNµzˆùBdË¢PI~  #ÃÞrÞ Í“tŠ•ái’¨I«Óç’.6'1K­Š“«¸÷ð)+¼æßŸ •ÄF@xx È·ÄO´Âó$1‡òehšd.nÒ¨Uñ ´•g%æêórôÜmtÊ ­ùÓSxú–mßÛšö§½Êð²#_øÞÿšøÆŸÐ3¯²7š-ˆy‚ôOžï®0XŸjÙôä¾åþ“M-ý¥ÿ0¢bt‘E=ƒ3ÆB,u\:'ñC-,n¡§¦9µÄOÕdjR©()©¨ÜU¬pWo™rü]Ô/Iæb9Dÿœuõ)áì».-‰Yî¼³séoljœÿJyxk½R«Ö&àgŽ1ê÷k<[vwM—ôs¦±8aéd˜‹ë‹£özìIj‰cžtÅ}Ê•÷ íŸk>+³³R°ƒ€Oi{D›˜%4?w…]rÒøòù-ÄT©¿pxIi:Ðj¹ mŽ.3ƒéìÆ,ü@ *4‰šîî½€šÑ¹JqëJÔ‹UÍY±Ã`c‹ïÞCÇ?=t³á’±ö¡@†^j‚H˜™S§Cæˆà„”dJ¶~¬Ë× q„·ßÙŠèç>ý’ܡ軋VÙ­â–¾°v ¶ÍÕß×Å9(˜iwV~ÿÕÙý5õÜåÕg£×pá´î>Óæ‰ö±·TgÀÂÜk¬®=ÃÔËÞ›Ĺ¾Ïšœ ü÷¯* ¨ÛXïµbݪä`f…>;q{O݉c-&²òž$ýqëBt‹}Þmßþ‘¨ü7xûºÚþþG¾vxý+¬$”°í¤\¸—ÈŽÀéør1óölyT…wxl‚BÁiÔ5ä§Vg|~á¼,W[=“‘’š"Ÿ5w_]沿¶¸¢\ —ÿå¶Ž·XoüÕÞ úþŒÝÃÉ,шº¨"ÜYû¢µ€&Z°-@}P¿¼Îç(õŠ„ÉK°t · w‰Çb"ææà^'±Õ9Üçþòl`ÒSõ‚£®Ïjrtùñ§&ëSOŒ/—›ŸÝí/Å(éX@ÖϮԖWŒuÐÄœq¿ŽÇ`jÕ’åÛKcK…1ðA7ˆå,ÇÏ4þÁ5Ñ‘‘‘²e ÃÞ%(ëBG‚"7²Š9é?ñô?á€7­CÑļ&¤gá†õZ¬V£>Ó?!õ§P**P—Dʾ}Oì xž^„ûb븎ˆ)R•éÙ>EÒ³\ ê’‹Äp¯³>ä&ÔÍ„..¿E§ÌˆºŒò/#Ê,æ¿"\SªÑ†rQ’hÐhÎ6æ{3|üDl­¿™øâÄ᪦ݲìÇ"öóuþ‹_Pž‡lñt¼ÅS±#^ƒ8ür:v1£à¢¬<õ¬…B&;¢¹DòP5¤¨f¸O ™ ^ŽßF“Ñd†¡hzÍÃ]°âÝäÉË| ¥@¶ø ‘ ŒÝµuå&E80 WßGb$>{ÿjõáhû:Y^éŸ"†GŸùÑ'¼•ŽÉ.•d¥f@®mž¼ :Y A\Hä*çàÈôMA\v\´<>.!sº0ÂDbsÔ ÛhyLœ<5©(I††,òe‰Êdˆ·UCP ‡ÿƒ?°ŠÉKÈ+ÌÉÍËŽCœÚÄõ¾fŸ¦JSéU™Àæäå(3£2;Ë ëß(BÝÅ(ëÙÆ±¿ŽÖˆßù-†îˆÄ,#:؈D¼U£˜Ÿ€¢XTýŠËqU£I>”„‡CD,‡kp ûšÈ7I,D P’Ïýñï9–$¢Ö /‹ÑÊ'BgxÝ凳‡2â¶Épé_µ ¼˜ÆÖ‰Ñ¡mÕ5Ä#½‹»#+É÷÷Ïï®K5pÛÔŠˆfv”Ç•”–î>»¾Én"î± ‹8,ù§iÓŸ­€®Óo¢¿-#豤Õj5±+>Úê$S(ÈâÊv´É½yÑCö¹¿¨ÂÜôÌì7MEJƒ¼ÝPobæ3^JÌüëõùßho…•ô¶’¤¶R盿>3‹ì‡Éþ»Ý#o ‹w‡<ýòÐYXÉ%*£ "3cŠÌ?‡½ ûÔÖD¿ãþì·ñcÝÑ; ïUZ}F”ƒŠÅ¨ ­fÏà⵴™&ðJ1¯D™¬©MF¿RyüOõb'Pœâû‹ùå­NlZž€„Œ eb• *ÿý·)q¤NÔíZ$?5;[Ïu²AŒnøƒpA'šZmL¢†»(ó®˜wEWY¸•rËç çogºÁjX´m¢ï┹ð>ÌO¼oÞþ÷®† ZïKãoª/§Ý€› öÆWYXcŽüV~žÀY¸—2O” ײÌP—"KFgÛÃ> endobj 232 0 obj <>stream xœ•X T×¶­¶¥«TD¥­ jºpBQ‰8c⢉â„"(BQQp@î>ÝL‚‚Ì“(S‡Jœˆš§otÅ FML4/ÆsŠ\ÞÏ¿ 1/yïýõ×_µ nõ¹÷œ½÷Ù§dLÿ~ŒL&cW8yNw0ýh+’I£ûI¯ËxÿúN÷j30—ƒyÿÆÑüCKl†ÞCÐa(#—É–¸z9‡íˆ‹ в™älg3}ΜÙ6‹¶Doñ µYá°Ý7Šþ²ÍfmØ–à€¨¸7lmÛfãfz"ÒÆ- 2 "&À¿/¶sØöÑQ6+Âü"B†™êæ¼Ã%bIäÒ¨è÷bvú.õ‹Ûâ¿2`Õû«݂׮sß¶ýÍ·Þ˜>cæ,G†YÅŒcV3ã™5Œ-³–™È¬c&1îÌzf2ãÁx2NÌTfãÌld3.Ì4f ãÀ,e¦3ï23™eÌ,Æ‘y“YÁ¬d¬kfcÉ(™á ϼÆL¥éaX&šù»l…ì“~^ýÚå#åqýÇ÷¿f6Ü,ÎLTŠÓìrö)—2Àl@Ò€'ƒ1ƒ¶ ºoîl^38ÑbšÅÁ!ŽCR†²Cç ý|Øöa?Y·T[~¢ S^ø›lŸ;cñ[¿ø‡ ˆø¼3Ðh‰ zù ÂJÙÖ&òj¶RÉP pQ[©ãÄ%À¢ìAÇ•Úâ˜*Rºäßavo˜8e½›g¸Jy–,L4S³]™à/.Öâ7ù sS´6#æ‹–8­ðŽ%,N´RJX% â1—±Ï æzÏ÷Z1Y@Å.™Â.Á]îÛYŸGUÏ52=ÊŸ £–üøö—xêx ÊÉUž¸b®Wµ>5¾°¸}@†“ñ* éVR£¤4ʪq8fâp¹Ô€¡<ŽœöœÌ&o9L ÖdèÉøÎýú9Q‘CÄ•'J@æë68_+~Ð\ÜÍм»$¨8Ö7 C”*z®ùz&A”~eWÑ^ÒtÈ»3»§ó…w@«=˜¨zoõŠSï,kb öÄŽø_¤w4à*4Ã!ÈÔïŠ?»tÂA2’ ^i ó`v™Çeõù}wà1|˜ŠÌ•?úøëÃgè†àû%D™«×–W¡7T}u$ëEc”d[-_"CZÎtn¥¼ƒ;ðs õúÜÜÆ¦3%À]ûp%±$c\<–íUùMBBè¡»NsH ¹’m jÝßNþé1 híð¿pý¶¸(Aù}K\~/k€Ð£ÿWнü=ÕTå:³ÏÊh•Ç¢£(ïÄc¼ZMTa3È àÈT¬ëT<ÍöY$ˆX«V,:à3Yµ³qª¡Â) æDÅ6L2û‡ÌTó/hÁ»-¿Éîå™>=Ç­ë4ó%ZXQ°{Mœ…Îìr´øQ¥ÓÅí†PίzçñãÕÅgÝ{¸lÙà¥R¶¡KÞþ*éöëôm†v¨‡«`Ô˜¶ë¨)@©ˆ%¿ošˆ¯ÓŒèžË÷üôj3ŠúÔçÐ €2hÕp"…¥§Ø§Y(‘h– é@¥ó’ô@tÿò˜$£4ªÚ²¾Ù÷&î£ßLûD‘?sÙa¹®'Px§>t]ºJ¿GŸ\ \¤— Ÿ±&<¥h!Ö_ž”±¸íä V[Švíƒê“îî唌IwâW\8 ¢Ç„ßnÙ§JÎM†½ÀEBR”@dl,(È4ÀÑb•JަÚCÎ@pUø mËκ JÁÿxHƼš ¹f…u`1ú‹Ò@ÑÒ„íÉ8vc‡•rO÷˜³|ÕŽKá™ÀåBÎQ½?Ù Í,ð‡5ð¸§rjoË*Eˆ…Pÿ¨ð=!I!àŽÇ7vùtÆß„oû]ø £ñÔÝžÂ/ÿi aÿ̧ ÎÙ”?:2L$[ˆN ÓðpÍ C×) Ù™ÙLR#þ&â‚"Ù Šû¢·Kcx´‰-®U+t7Nš¤á?'ÇX›¯£o~Úvþ¶ê¬Ú“]¶®–ªúH”d #7-ó*p"¡ ÕE@l2Äè95[x\“¨]ò~p$•(±Â율ت®ÓA]äG]eѹÇüHDä€u>d§fs}ŠÖ¤¼»XÞMƒ¤ç¤ºh ¥Ý®‹„ 6D›‚duè4š$FK²ˆkÌ>!:ívð_Ãnºæ"[¼´ ƒÓº¹d݈±xØ´ÌOë§óƒm°ÙÜ» í{fîJÛ_Öå–™ÿŒxIŽüåo&ŽN3£•Ú.âªho´¬ÆóqÎ2õ®ià]~xÿ]uRQtÊJã!^X©§§+å(¨-þˆØ¹‹”™›ëbUU7ŸˆÍ×T•Õú#ÀÝ©ó] SÜ.ÖÌdÂÈ)84îúgbSs‰jNç§²S¦ÅGxn©kEgäžJ5©’ïŸ+*ÅIsx<ˆê’‚f8As**¶hÜ ÀimÙʸòä¼”}ú,M‚tÀÛȈlE€½ì À„Úç¨Ì°õ-ôúêM`ð}öÇ/Д¥'65É:.q'g‚ÊchƒF¸Ð…¡ìzФíËãúCí…(+‘.Éño¨ãq¾–“›‘ùXSÚj=tÉ4 a¦zæÂ푃)ôÓSRfÛ°CÖ¬QT„ë\µ!BA³•.ºÉ¢q%Vdâ®Ø@ðkª¢†3út(‡ Ú"jظØô =è3 ÏP†ýÈkfþjE…þ²¡ª¡M[C×,f_Qn{±ôº×tþµmí­ÒÛÿÙoü…žg"›W˜_WÈ)[u¸?…v/z{”ýwd‚ӆБBéä1=Vwòx'ía@»¨a]¸¿êç.ànÿÑß3CÔFéM ²}\ÊÌMíãR$…ùŸ¸dhƒ}º”ý:@X*CJ,ý\ZÕ3&Ê+Ú+déb°Þ Z}bjVZi.Ôq5‘eÁa¡±þž¢ß¥»ºÎ3iÁo£©lICeõÔ”8á09öHSø¸ÝÚ8À½èÂe¬!KѸ±þn*¾ož@.3w/ìÓiã“Uá®^±ž´§ €Û?| ùº|&Gø#Á¢$ïM°)Nú+UÛ%ý ò½j&ýüç$VÙѰÁ#cë(b;v&CF|;']>YV^%ldqy†YŽ/y’ÊÆÇù­[@#[¾qÎU4Ç›Åì*8!%¡œÅ¯#^Q㬔rVŽçºù„#:} }(ÎòK ˆÖéÂ4‘-Í#aj¬ç©™h†3½šÁÆÁ.}œ!4UG;'±RrÏÙûôº<°>Y¥‚t‡…½¾2µ,Õ•À•‹ŠJ8*?½bZÎ@¾®@{\£×A4×cgÞᦎáZƒo÷YÂÄïå’u„%Ùp¬*éö†SÂûÆõKè6gÍO†‘‘?NFGœÑò2¿ ’wi“w' 1^n!ËèŠ1:´>-Ôô74蛋k*b¥2‰éæLBs·¢±×.B{yw#~Ëã62ÚßG2‰¼O¶  ‡;qªpúªzú“ËüjpªôûtkWâMxWS¿jý¤éòµò‹Ô­\k|¯~yÚ|X .)3|—lrr‰vO¶Ù¯ð¸ƒºú?M@æ±R>Ã"¿D­ø‹á¡¶é²"K-õàç ì÷iVyz:h3U{c!–ó©‹­8Q]ÜÔØ6ÏŽ0¾ÄLe»P}Çäæ-GšÂjÂŽ^7?šŒ¦f©íM‘š‘rÐEA‰ÉÝ¢jÓoÒWäm¡Çñ•¬)þUÖh|Z„žŒÄ¥ÀɰÀy1Ì'Sj܉·§>½iĨ&Ëêï\PŽ‹Q]X)IÀCèÆÏ„kmmpíáCxwÓ&xw¦@,öóí‘§µåTÆwÞ»!FÔìÉNäëµÉÚÄEäÇUTä–•îªóÞ£ÖmVÅñ-^Dë9~Ý<¿"¿ê(!,(i+ÄÀž´!œ²›‰×8ŸŽôì\ˆjt¹wñƉÄ+ïÖªÖV®‚)N»w²~sfB=@vÚÑŒC\q§Z«¨B3XèïN^#æÛÛ/]\JMù¦&Á!b•«ú2ˆp² ÚsÊJ¹ø«p ‹Ž†y+×Â[dŽ€SbxäNœþ>æž“~_’Õªž¡$ÕH“J'šTc_¯¨b•§hü\jT«‚«ƒ¨s‚÷`ãàÖè®êïÉyœWBe$F·?^'$«C£·Ã*8p3¹Y{8ñº.}ïuU>¦"[Þ7'>BË{Tüšä FIëyâdRŽ‹øé*}‡ÁÔùNkTåW°ÊçÙÒ5¾5°Ö×'(Èǧ.¨¥ÙXÛú»ß¢cÓ·X^m÷~†×ŸÍo³RÞ–l¥<™Pµ%km-\¶n©ìúñ³çÁdt©*-´¯ì0.ïõ‡‰:ÝþÕ¦ÍkÚ—eÑ6D¦:O»¬Æ»8ZèØX{e‘œòÉCÚàKbŽî)§â¼Â—Œ[@¦¡]¢JWéѯ¬ñ²^kœe0dRµ·¼ñIRXãœ.4{Žò·ï; ÝMTËî]5‹´½ÅD:DuÏæÿᨈ!ItÏB³ìû8¸»=÷ˆ½Zq.•¢ô"½è휩 öÒ½OYÙïdEï4 j1¥àÇ>ï gM^ëþÿ§gƒY*²DFœµhõ¡JšõíÄT–XÓþ*Ã-èöåäÕ«ºJ:eÈ!#ǨîeüŸÛí)ZÏjýIƒ‰ªíÚZÓ˜obþi÷¿¾5ðíû²Rvü¯o¾îèª-Ù9ÿ?¿9ø?a_x6wðØà®ÚùdZjÌ·M!®œòþ¿¿gn%´à ãIZÑ`y’ŠéJfƒ£­”=èŠßó…, ¢¸%óh™xÎx™rµVS˜·¶sÁ¥a eõ]¾WÆÑdŽ#IW)…¹Yï4-|yƒÊ‰ðôs‰6¶·Éàèµ°ÀWø™\á=`GCbÞîj¸ ;'v~ 'ÚÂ"[Uï~¤ût+Üï`þ÷¦ÏKŠäwg…åC-wãqfã—§ü–n Þªjào«Zá÷“CQÁeî”Í®÷6«”f¿¿ÙmÑH2OäqÖý‡Ø™ÙâÆJY°”¯‹wtnkø ¼¸Ùö»ÝìÜNß»w¶¥®èU¥ÑAvä¸ÿßTçóŠ-uu-¦mR$$‰­E2܇ƒäøK·œ/ìð-< šï6ž !·S]¤ÈƒNýÅB®'—j¶5õ%‚;àeßlcJ?P3~ÇÔ‹²ó8— J.åbÿ5;,ß{0!i!ì¦2;Q!6œii«AÅ—WEøžCvÜQ³1Ø~ÅôÕ'÷”U7–œ:ã›·'Mu¼¬þ°¸íK. Xê²X ÞÄ7~)vZÇI‹ú*Nš5ÜÂ×ëME·§Ihé_§wÚ¨þŒ?ó׋oŸ‡ÜÝ]4ΠyËßñ©ÚQßV^ýÁ÷Ã)zU]eë¡*à¾H]¾5^G¬Æ% ~Z­.Y·_§ÝO†²'!. T­ :óÛyªa¸p´^BMVy94qm!U›}ƒvxN¶ŠVgéí¿é }@•¬/µ(%—"Kêõ‡Ñ)‰rå¹´øgâdiŽâ˜6=,F§Û³OE~êyÏLM”ÍýMîÿʼFøêhv'³Ê'ôYž€¯˜õü2íãq¨åyùÖYÜŠci_¤÷æ‘û„L ]¯ Q«p[™|X[Klû-š•gjïÓБ,Ap‹^Ÿä `}axÖj³4Àí…„Ýi£Þ+¾$Çv(SÕÐ~.›vŒG0óAù«L$æ‘®éç}UFÃñ2zø³>G#÷xXùæ½7q(Îúá1Z¨,w;&Y¸©XA¼3Yq *©öŸ]d> 1ÓÜ•æƒõæ ó?³ËÊ÷ endstream endobj 15 0 obj <> endobj 233 0 obj <>stream xœW TTW¶}eA½'"âð¢Äø œg$ÒIˆQGEEÅ¡@I™•y¬:U ó<#–"…¢QŒCkÔh'Q£Ë!f šNBÎ#—tÿûMV:ý^·X‹ªºõî¹ûì³Ï>2Æh#“ÉX{ÇE›lÞ–þ(Ž–‰o ÇȤþ:¡;ÎLå`jÔøÖˆýðe(n‚³Ì¹Læ°ÊÕ>pOD—wˆådû)–6óçϵ\èïä³Ó-ÀÒÑ-ÄÛÓß-„¾ñ³tÜéã1Ór¡ŸŸå:éÁ–ë<ƒ=ƒÂ<=úζôßâdéèáÀ0Ìô€@û=‹—9‡, ]¶Ïme¸{ÄNÕžkœ¼Öù8¯ßàç?gÖ6o϶ýìaœ˜ñÌZf3‘qf&1ë™ Ìf#3•qa61‹˜éÌfÆžÙÂ,f–0ÖŒ3‹±a–1³™Œ-ó7fãȬfF2£3fcÎ c†3#žyƒ™AbŒ_æcÙJÙÙ#ìpU>A~ÙhˆQ¼ÑçÆoPŒQ²6lgÍ55Pm2ÖDgòÛ S+Óóƒn4“™Eš²zÈ'æ‹Ì]Ì÷›Ì<ÌtضaÝâ ³nc0ˆ&zÊQ†ÛQ&`ÿ­ûY2ÀÞÑûAƒÄ.ÞXÅ^Î%¹é b+t·á]ŸB…š38 ‹Ì½ö«'Ê‚¤ú?7°fÿðv “X/¾©—Õ¡)梩\¬Æ@G[¿ 6d®í8òù|ÚàÜÇ/p˜@td-OÞø þ§¤^YÞxªØBýž¢ÀR/pWnŽð‚Ù¿åÓc˜hº”âŠ2t7È.£•¨m–wÇvÛò*|`ï|fYåB° ñd&™@vwœB¦ E34)JÔŒ…2ŽL'¼‹ ¬€ÙÅÎW¼|/ ð}Á§­¯Þ}™}îv«%‹uqY \è*•F²Ñ€ôâÈzÙOÉtzA1 ãƒÀ{„mZUØ($–j´û ƒ”%aÙpH(ÈÐAa©p¸ä”÷y(‹ 84-ÎìÕï+VºóIß½2gMœá®=…2”§/ Ò Ú¨L‰}eZAÉ kî­.Ö€ Jeÿ¤üÜ,G/qã d<:»)4“]'ONávß'u¬ÕƒÛwZ.ÞÚÝ\Øåþ~kàz…TF冧 XlèÃðŽ’wwä» Šµ%xÑe :NÕEŠÉ=,î2°ú\¢[£ûêéúj(ÒVx ï‘Sÿù9Kë†B˵ý.?Ø%®æ_¥z»`ûj»’«.øK~'A,;ézÀ/•wà¾Aо£À…éÆÖ1N*E#ÊYyUãèð½^êIàF×$𢱢QO'1R±õº—ÐL×K¨—x!=`ÀÚv&©Lä 21^4ã3 Ò2¯g`½Ôjp‡= †uôluyR‚4I±J2d_0(BÔKè–X {é¦+,.î–®Kª‹BÈÔe•r}’Õw@·‡8˜Ï(JÍøH: @E±t‡¨ÞÙ¬³EHŽUŽ%y„Åã Š`µ}þ&Äfº§ƒM?•—š˜ I NIФ, kGK¤Ý!ê¥t·/¸‚ïnœÑ34#"-¡,r(…2K»°xT)Ì •ÞZ”CjzF±$cQÞ£{5ÚêeÇh‚Ü¥î ÂsüóE—‰•31Išëv4¢º¶¦¬¡$¡xŽ Ïª„àn4yÎWîdÉÛdö"Ÿ…ܾO>;ÛÜRªÜª„6EY&”—ÅA¤r• ¡‚#²‹üŒ¹¾[Üõ§¿B¦îûC÷\þ]ÞFÉEñãp{^NVæS°0°kh&¶ƒ?ØAT9TjÇr¶Ç„Ü6Ƈÿ%1w³?>AOrT—’–É1[ TP±Gu_CÔÂ7½ík»’Åæs}´ ò+êZääee~)äLò¡YWA PIYR‚š¾ÔJÛ)“q°qó«LøÃ†Þ·XœEÖѶ7):2!aX¨ØK:ÔQYk†#ô\6<ìP†´™Ê—hŒr2ÚØM¥¨Ô]§ÒWKeLÚ³¤¿„ÞÔã†6ªª˜#5îü;ËÍlQIQIaiÛÆ 1´ ]qŽ™ñŒŒqÚîë®<äÊ?s®¸™~gdøòí°.x—ÒÏuk¬/,…]g"ËûoO¶êÅkY¹Ä…xqŸžŸ–yU"®:ù•¡m…¨””DMŠT‡È¬•*#˜"H1rê­Œ«,:öLHŠŽ HжÛîë°’!bÒuÚÚ\hàôÁeþ~Áa>[[Ü.=8§¥T0S¨ÌÑÛ@MÄR4‘‹Þ8ÏØMt’¾g™5mOV€ÓOuhq$ŽÌèP'i4µF™’u‚8·cû«ÊòZ6}qXB=KÞúÖ'¡Mr•ÎI—dé¥Ô[ûÅg;Z²£Æž3vâlbIƽ˜ƒZKô'•.,:ü.E"Kd=Ïx·Õ›¢hs æ€ÃÿNÝLyƒ²îbGz4AK„~÷JyûØÞ*&¶ÊÑÐ=‡ÍÑh÷Ñßí¥ä½®€Pfor„zŸ&¸•¢B÷y¯Uø¢—¤!¬}pj@šF 在gÅøž¯s¢µš<°¨„ô ¥xŸ…r­öpZ±®T[L‹DH;šŽ@xBh:*ØjÐAeJM²V¡\ÏIe«icAç|¿Ï¹Å=—‹›p/_‘Uµ w·µ*ÝšóÖJ–`Î2ŒXþ8 §á´S]E!ñ€&%*Q¹wÅò0Wºc‚G_TÖéš´'ËêKŽ/7ÐBÌ"¦ÚÍ«ž3Ñ Ýæõ½ömZÉ»+ðk½‰€I &cÈ$âE¼Ð’Xáº,Ñ ½ÒC®ó+`U燮Ÿ&}C­ÓÇ©›n´Ü¼]ÕA Â%UÍöks©æOŽ™·Ù!Èg½ÊN2:r&Aªå‚lïóPØJϤýÿ#ßWà»_?ú™éÈ|eÏô>õPü¹}á›b'Ö0ér˜K¬•D‰íŠ>¯K¶Å·Ÿß=ŠQÇdu0¸+ýßÀü™½¡@*Á ŸÝl ¨ÎVÖV¦éR’R’!Š Ë?|8¿¤¬2⨛Ê=,"Lp¯ôÈÚDÑÖ¿¿Ä/Û½ÙG¹?<›ꚪbWÙàDÇXÇ9][†«ð‡çï>Y[”+¸V®„Ù; I«Êˆn ºœ©-ÈÉãpP:o Ÿœ> Ÿ<~ Û¶ƒ­ò"qå?½åâí½–ºÌQ^®^Éd.˜h}˜Oè±Þ0¬¥´9ü xXÊÍèzým8Ͻû8 =Ưaú©¦ŸûEö;üR4ÂÑèò½µ> Ëèroó9çý@SÜ?sŸåŧF…k¢4ʤÍ~a°®Ç?OlO¸C=-èRž Äzúœ›:ßi½Æ–¼+ùžy1RŶp¼ ’cp·œoÚ]çáîçãéYçÓtR_×$Åd9­ÞŽ?øÇO šÖÎÕ^ÿè(N“d4ÚÐÍ6Ê.?ÃOŸÉ1C\ÅO.O¹ ù\›¾£³óñV2²LH MI¿ëB'Vr )šØ8Aµ%¨lóÉ©tÀ·À†È–ÕoÍTžs9’øSÈËÐ\uyX^TM lâTaï£ÙDY‹ãM1¤î{åúœ V›•-äädåUU}´íA”46Ìú{W×7ŽÏˆ¬Jʈ™—¤OÎÉðsÉœytÏ盤ØGb›Y(Ë|„ã»ßó„LS)îé~„cð1üîIÆfšøäK¿Îœ›Eôz[¹*›N¢Ø×eű§éÅnþÿÒ »¿Ô‰¡,7q-1!öÉøæG‚8ï/z¯ K¨Ç€ÛÐñ!¸† ¯r'v¶õ%ÎÿO=ë£Þ4Ý¢iª†[¯ÇHym ó‡uGߟ¼ûZŸ{œ#F·.õ= x´´`%LÇ0W`e÷Ï]9Qj÷—ìÿ»¡ÄnD¢?&Gêe­È£—ã"üO5éò‘óåÍm'¯ÑR¬O© òL>{8¯ê£‡õE-—v~<– %vv$ŒÅQßNÎrê2hßJ˜³S@¹Ä¯„ óÉ™‘z¸Yi?×ñÞ4Þ'ôGP&æ£In© ¥þ¨¿ã³²i¾hy)€L9­ JS稳97Ån”6ÚìÌ›E9Yé_R;ÆáríˆVQüœœg[¸emY•Ÿ—‘!äR‹Ø8#®ÜåÌÄA¸ø¹,Ûåx óÏI»5ÛŸYZq¼Ão÷Ö£Çn?ww½ßÉÞzì—ÈÔ²_Ke—Åår1®{=(Ò@ÇGfG…'GG& =¦ÿ²MЦž@m‘›W’–SÞÿ[ÊTC ½d$ËñE7ËרÁWX¸’È©¼páªÅqhOoÌãzʉRÅ6ë~†Vºº Yª„1ýé4Á«hÑf]D tÂrQ‡¾tÒM Kp:Ÿ`©ôZ+Ž~õ‚”y£ ¾ãÐÄòJã©+§o4¬¨«/;ÝìWæ—&4žnO+îyËövíÝUJâOöÅÆÑÎa±_œ÷š$'QÀaÇâˆæzÙç8¥Î“éã\·ƒa–§sU² ê –k ¨qw p³~¹Îôó¿øêåÙ o‰uµð¤úãËðw×þ Q£ùNïl>yàpÍñ’ӱǶfÍM7 ¸§ààú¼½>{ÕžêhÍ>M²:1 ™ÛŸ¥¯QE…A\AaýLòwKІï4L*ª4iAj8-Ξ5Æ*X Âõ¦º’s§è pr£5jHжØã ëÀ5gkQ‚.E—\4ÄîW’ª’1¥Ù:JY!7¿¾åf¼gãÈ]«ò?ôQ¶ç5–×ï­Þå¿;b«ísqÎì|Šæh6ï1³Ó5ÞW¥4‹Îí^”K2²pG©‚lË` &($˜Í-5x,ËÔe¦ƒµ¦f ó¿*Ø£ endstream endobj 13 0 obj <> endobj 234 0 obj <>stream xœcd`ab`dddsö Ž´±T~H3þaú!ËÜÝý#ñG*k7s7ËÜï÷„¾Û ~·áÿn)ÀÀÂÈèæ•æœ_PY”™žQ¢ á¬©`hii®à˜›Z”™œ˜§à›X’‘š›Xää(ç'g¦–Tê)8æä(t+¥§•¥¦€mvÎÏ-(-I-RðÍOI-ÊK,²3‹³ú3™»˜™fñýgv`X»à‡Ô|Æï G™¿¯ù^"º´òtü’Ê¥•½Ý“»9æNŸ=knýÄÆ~ù† ÅÓ~3íþ®rZbjÿŒ‰Ýó8&v.Éû­ª1ë»vEùÝ’•ݵ5}µì³~ëü}Z7¥µ»(Z_]S1£uj»üwŸß*Þíu­Ý’­½Eë侫¾«ùmÀÚÆÞÞ2¥dq÷²îþ…s8øŠÿ´_Àö[h2ûN®'Ü;gñð00¸‰F endstream endobj 11 0 obj <> endobj 235 0 obj <>stream xœµ”{PTçÆÏÙ{Ž Ù£ÙƒÍL5blKÄA Bb©\.ÊnË å¾ìîËeeÑpÝ–…]H@.‰PAŠ¢!˜š –ã¨525ޱ¾ƒ{Öë´ÓþÓ™þwÎÌ÷¼ßó¾ßû{HÂAD$)ö s÷°½Ä¯$ùU"þ9 pÌÔyGp¢ÀÉ¡{“ó4’-C›ŸBk—InÙéŸ’šž”¨tyÅßÕÅÝÛÛËÅW!OOŠ“q.!2e¢\!S ?É.á)qIreöZßäd—0»"Ã%Lž!OWÉwÝ»Ú?E‘š©”§»„¤ì’§sA,åÒ3ƒdÙqòíIÉŠ^óx Þ!‰÷‰5„I[w"ˆ!B‰ Ä2b9ñ ±Lè…  ñ#ù>Ù-Z/§^ J¨Û[ÔŽ~bR\$þ‰.»Kn‰%–ܱóXùU&(n‚âßEe¸Ê.®oçþ$pù†â½Œî¶¯*päès†’H›é¨’r´¥b:À #`Ñ2Vz[>aQ(ýÓ—£gÎÔí•âüÿrò·:³ä.™{ú…œ›¦Ð›(Or£ÿÚC誤ÅeûJ!•áZ L¦Úv[jGŒ'·.«TªC”?ûuTœ´ÃyhîÙKûiö°÷;-4ñ+ûvŠþÈûIªiϨ€ÍÞêφ¥è;¯¶×‹ÝhÛnsÚ@þqh„.øØjmmè`ÜiÄp´ÒÅÕC,âé%<¨Lã·ù|+yü&Z3MñKù9I_•~Rj¥ÓµþÀÁnxR+®“¾Z™ŸÀ.DÓ;·G¨¶ÆR›ÚÖ=Œy_[’2-/>`"äòw×O#‘T˜Ñ¬A0rŒm3§Mäáó(vbª…âLažýÑ}‰]QuÑÀxGqƼVsc£y rÙÖO›ú9zJîÎÆÑø÷/x‹Ùô}úøGúÒª ŸÓì©lˆN8ÆÔ4ÅXIã·ïŠ.KÚ'?+7‚ð¢œ6ö€´.tHÒÖ(!Š´ê²Â±ÞS¨­´öCù K7˜„‘¤i#!ä‚ Ì.ƒº6¹.ˆœ£Wƒ¶¬8G‘*&9« Xè®ê6gÕfç¨ 9ù¡øáÑ¡³áYÉþ_…-È:3ÒBvO¡¨‹ú™Kòã!6£1ÇÜj¬³N¾=¸/Zû<~?ówW䈜mÈ©¦¦4E:M¾†Í ˆPDºq½Š6^8Ö{2wWëãÚ©Fäo"mS¨ø Å/G¹’– 0ÞŠ˜Å‹±øõðRìü£¢Ð“GѼ_]UZ¬U«µlš×V¥ ÙKÈ—5ÒåF‰¹_iê€9ØW—' ›/ª÷6}bFV=7N^§‡ÎKÐoÄhÑÜô­nWðJÿ3‰¿ª,Œg:èxM¡¿t/'6WÌ,Ù`Ì÷¶Ü_sà«EF j£?ª¨>,#OÀŽ12Àbìeïæ©;gL?Z~ƒDäY ùñ ‹ª5%-S•ª0g™;›,-R,Å¡Ÿ×” X´=†jP¸î ŒÁÇvxƒÊô},ï@?¬:ïØ¿äæù fQ¹Ðü¸ÀàÖÇ ãQN,¹K­›û—ø±s9/û·Ú²wöíÊ»ÑüK£ÿ!·¨›"BÕ<ÿ++Ùx'šº³ŒŸ‘4 ZMÇÊ…C1Z-DCD@†}³ÇuM{`/¨5ÅÚüêçŒ=yÐUj P¹Â6 f… ­¯„Bš]1 ušƒÙÕ¨N®MÀÏ/„9ã7xµº*ìŠã`J­@Ï#ÅáC9Š\øÙYŸ[UVÐWêëÑF¾Á½¹Ð ÏÕk °¢ªªôõÌýHQ™æŸ5‘SÈ0Eñ%pQýׄ©Ø‹þ-‘ð.pñR‚ CàVí×ÐçóeÆ ¸ ÇNXÇz¾­øÆƒ¿‘ì ¦,Dœ†)ø“°’ß4œjœ<Þù)ô˜Ҹ¾6 6A lŸ‚Ð,, ÎJ„à<º3‹­äÐ,Ú}‘âƒÑ&I¦X“Sü^á¾’¢0PƒCÄí­ãŸ[Ìœ.£'à&ƒè×.`3¯¬ßq*›-õ]YÆ”"-è4R㹑£À\:°Î3Ò7l‹£°Ê1ƒ'é-·_ý½hF‹¯MšÉs×й`„%9º21…zh’_ê}{ þe`bäï¼[¿àØ.µÕžÌV•)%#-OîqÕÏÎû•k·¾÷ýjM£ôrÛè×ðgfÚ{ÌíeßP¿¸Îâúfs½­+£.³ôž©Þs³ 棉\×,M8Ã*¢“4©:f‰°?>ÍØRRˆ±ì m}bâIé^&§E¦'§‰§ÅñO (J endstream endobj 9 0 obj <> endobj 236 0 obj <>stream xœ}•yPwÇ»˜î4šd<*Ú=)oÄ”.¢o¢Þ`"È1ƒ09GaúÍ7à ×r(µHD<’h(³P¨åjÅd£ëf7[Ñ*êÍø£Öýa6ÆÚ­Úê?ºûß{¿÷ý¼÷},ãìİ,+ Zâ=þ5×þkŸádŸ)²Ó±Ú±ÅÜdàæ|jímŒšŒ«ÞBÏIŒŒe×nÚ IÔ%ÇìÖ*ç,P.ñññV®ŠW'ÇDª”*m´:^¥¥?qÊ`MdŒZ«óT®Š‹SŸHQ©SÔÉÕQ/ShâSµêde &JœÀ0Ìä€äµë´©T‘Qê-Ûb‚Cbf6ÌÌcæ3Û™ÌBf5³†ù˜YËx10™¥Ì2f3ó6-‡á˜ æ;v3ûƒÓ'Éé®,Aö•ó ç:çç.rùn7ø‚õø 3ñ…“¥‚ɰ9Üml÷{Êq™ƒu,WX%ã‘|IÊÒ aÞ{¾ÞrÚ¦²˜¸“…‹ÉBü=~Â÷+ƒ¢Ü<(È•Ä<¢œ·Œ0ÀÏ!ÞÃX‰Uèû§ ËƒD¬MY`(¾LVqâ 6Bɀͮ´°ÿìCî– b¶âïçÝ6›¥³©ú¤”ÚœêŠzss[ìñÿ«¢sD Y9á³]’¸ë¥GöФ•SçÝ$$q¦n°A ôÁ oã²àÍá´g Í6¼ÜÌâÔA ±Êìç+c9IòoË!T;Í…fÃZ¡ÅtZá<ôÀy!•ó7”±ô÷¤ô€·hÅJÜ;÷€§°«å¦âs*äè5Ud:o•Ód·¨ˆø¹Í¾à¥ŽRq¯âLañׂK1l‡DÐÀJ£ÚÈ'ä¾7eï7pĉLÉ›MVQ±^—Kx].Ìáþ."¸æþ½–«­bMD³¦øb£ñ7™ó¬vÁ†>ÇÙŸûQ°ÊÐÝ>_JQb Nn˜½ä>ãÒÁ¥qFþzǵáª.˜[›ø©*!òøc†ù×}&ÏbŸÙÉþÒQý2üÂî¯øÂFÎ;tõ*ýÅK>àÈ„q>çà#yÂÁz·i*3›’†á!´—ÔñFO9º–¸Ø¸­¹ÇzD|ÎÑë,•ÃÕ6ÎI†»ívÅ… ¦ÂÅvA }vA¬‰Oâ†+ƱáB³ €bk3õA}ú í5ðì +½.fXŽß³°ç¾Âˆþû´ð1¬PÀ œRý¬=¼,øA>;i8VÙPÒÜ”^~(ÿ¨$ˆu7.[Oß;æ-†q[ kò‚ã7Gëvƒš÷{”Ú?Ð×zµ^0…5Gv_×_uO¼¢ â>IÌËŒ€K]ÂŽFÅÒÀ°ÝQÝ'+û¯µ ='ŠÚL<½UyeõC#V¶ý&ª†eøŸ)Ò5­iÈ«4·žZwÙïý% È»dúß¼žâ¤VäÊ‹¤B½^’2óÅ$ß ´pà7ù]Çù¸hdàúÙké!õâ+<XPÓ9ÚÒ'à Žß erùÅ7}é\Î÷"ÓÈÔ'‹~Ø5h.Ws8áûsnÇØâu‰Ú´˜ø˜£éÀ'̪Æ`Ü…|…­»3iƒXy @÷{5©Õ¸ÆÂž¸‰ú~™}2f)ŠŠÀeüÓí?ùûÞsÉ[dÊOî£èÜ5Zg>½dÈÊR×…Äì„poLìŠëƒëðo¬V˜qöݶsp º7‰3Íátk„ɰ:–[ÇJsGæX†O¨"óГø?2›x‘0†siû/Gœ…^¸O ƒä±‚ÈÉ$”cf㌿þ2ŠÓ‘Ãäy‡œ“økd²óÎ3+¾c±·Óø#èkÁÞ™=¾T®}÷q àBþríCúF¿†¶ÂÊ3B ™X¾ú{àG‹Ñ«¹ Ìú£’Þ êÝ·§ÅÂV8ØŸ~›'ËŠYí>(ü„Ç\œú tÆw•$“¬\ï±>\ø¼/åËÀïMT©µ¥éå™"ΪVDŒ5>4ó|}k]û™›– }%ôÖŒ£iÜ4];qæö)…¼Ø>¦¨×ÕjSÓuÚTkzC}­µA omý•’ÿ²È?B4R‹kŸ”­†c§E»œûµy¨û{4²Ý=x»Gfßø÷?bÈÏÍâ7¨¶5m†és||çÄ™Ã:Tbç§§òþ|ðd^ofYþÕ”“[ ˜Øå·T9ïKTêÉ"õÀçIRšHB9Q:f6·V ÆB0ÕžéÝðÝáà‘½ûxôRú¹l«¨ºZ±·B_h€àªíUZsò MkN´ñß\z8:ø™\-Ò0fàK¡°FüuaQ·à[X¼LmÖɱB16"?D’\¬òJô­jAO°ÒuP"Õ@hù±³Üþ‚ìM’¼ÇØk¼¡Wê‘x›†û° œ q–ƒz¨°•[èIô€ê„JâûÒØÙ/¾´¦Nº©dÔ£k’éè1 Å }SZrµçt±ÍH¥½ ’´Gš¦¡}8nUURYæÓÒÒ%ú´àbÏäˆë«í5öš.Ц º qͦü¢³":qßÞèØÝ±§}×ô ]ÙaÈäuº‚¬W ­Ð)Õи}]ßÅO̰8ü-¤¾5%r^ÊÙÞìwÞtÖiÜÞ°”¹¹õWºM`˜¼n:€ endstream endobj 137 0 obj <> endobj 237 0 obj <>stream xœcd`ab`dddwö Ž441UH3þaú!ËÜý»ï‡ÿÏ&Önæn–%? }·ünÊÿ]_€™‘ÑÍ'Ú9¿ ²(3=£DAÃYSÁÐÒÒ\Á17µ(391OÁ7±$#57±ÈÉQÎOÎL-©ÔSpÌÉQé(VJ-N-*KMX휟[PZ’Z¤à›Ÿ’Z”ÇÀÀÀ’–ÅŸÎÀÃËPÂÇÀ t(Æý OËø~tüî[ð#mñÌùŒßsÎ1_ÿã¸h÷åî…‹—Ì»hñÅþ =ýýÝ9¦5w׫E8wÊýöfïÖí®.̯­-(ðiçhiéjlœØ=µK~[ǃ²nuŽßQìÝÝ™ûÓ¶åži^ÕÍ1}r÷´©­Ý=ò6Òv4­ï˜ÖÝÛ½Žã»{÷Êî}SëÎz/M™ökm÷¥îå|ÿE3õ+è"îÍÌß&ŠÎìžW^Þ]Q+÷ÏŠ½¶»bþüîy3倎?¼àûûùŒ‡ˆ3ÿðÿÞ'úÍø‘ÒoF3#%…Ç&_¾3>xòEêÃŒ?2À|x[´ûh÷Úð +¼§dws46v7@|p«mCÜ”ô¾†îÎî Žß@ævGô6Îð<]¸©á7Wf·Kw>ÇoönçîÒâ¢ÊÊ’b×ö¶®ööîVކ©ÝSß?Ùw¹Wî;0|^vÏ^º|æÌeËNõsLšÔ3âý„>³Ýï9øJþ´_Èö[`ûf®Ür\,æóy87Ïâáa`•BþÇ endstream endobj 30 0 obj <> endobj 238 0 obj <>stream xœz\SWßÿ ›ëVèUPŸ{ݶj[w'®ë@QTPÙ+HB Ìä„ö$Ì0±nʼn#¨­q¶¶Z[Åj§ÚÚçÄúÿüO øÖç}Þ Ú{ïÉ9ç7¿ßï¹áöv‡Ãá-õðôœ6Õü¿L#8¦‘v¦qÓQœißë• ?ô·oùžÑÑä1æ ‚S\gÅê­K#"ãøA‚Qï.}oÔ´¹s?åæÏÚµ3|”ÇNA ØN¾µ!bW¿ îƒQn¡¡£Ö›?=j½´??Ö·uí¥a‘1þ(ˆÝþüp‚ |ÜÂ7/‰Ø²4Ò{YÔrþŠèŸÄ¸Ç®î\%ò[·Ë#~÷ÿO÷¬ X¸>hC°gÈÆÐMa^³?=gÌܱ®ãæŸ?aÁÄ…ï.zoñ¤­“·MÙþ¾Ï¾î˜*ž&™.‘0sAŒ!>%æc‰µ„+1ŽXGÌ#Æë‰ Äb"áI¼Kl$Þ#6“/b2±™XBL!¶K‰÷ obñ±•XN|H¬ ¦ÓˆOˆé„;1ƒXIÌ$V³ˆÕÄlƒøˆXCÌ!†΄áBp‰á„=1‚p F$ñ/‚G0E°DbÑ—Mô#æý‰Äb!1XD "ƒ 7b±p$¶N„ñáKÐÄPÂÇ O&$žsb8¿ÙM³ÓpûpeÜöÓìË\dÏÉT^_^ïWÊ›ªîc×gCŸûF÷ý«Ÿ¼ß/ýô7 ø×€3Ù9ƒ8ƒ¼³¾p9étìù§Ï–D|Ê ánže\yÜû½ÇIÈ›ÌÿÄ'H$b,뚤Γ…_ÓÐ *ÉRóø( aÇ’> ­Uì24a!œà ­ |ë£(ü¨”²U$ìb Ò8Äâh¼n ¾û‡ušh `ŸÂM¿¡M‚˜7™WtYk€>ÇŒPbÜŠ`‚3M'h8„ü®Ò#Ø/Ä};Ž„#è«•GÏ€vêöšˆË XRjÞC (cë:¥¤Ó«È^îQ’ÐárÇ=ãÖk®¬;*¢‘Œ… ù]ÃïÝkg²xáTüÊÀ¹`„5F®)†â?ø Ù#ûÞECÓOS ´ûégèÈ híæq÷Ù׮ݼuuåÔ<»±=„"<ÁZ¼eYZc±ZÜí¼JPÍŽA‰ÒÓ®pN’Î¥ºÒæ@óãj¼y ßE—Ð*>¯çìg›‰W™Ý”h0å8ðúe®IdºG—š°¸´¤”4F‘ ü`ývífœ[46a8Z‰VAü/ ©ï;žì‰rW°)ï¹Fûjê¬?á$øÞ£?;.ŸßîZÂfÅgŠÕ tZ³]ˆo€àõ®¬Tã Ü‡®PC_ºxöÊ‹KfN^¾rù‚ÀÇ'4ÁþÐÎ#ò&@AÎ/?A'8hú¯£·úÄ…±N¿Ô+JüßÈáNýÊa²Ç›—p?öçÓº ¨Aµ/ˆôˆ NNf—ðD fŸy£ÌYXÈC:ã’$ $¹U‚ ¾"÷ææ7±Oy 2(Ä ™¥HÏë™ý–¹—MîÚG)[Ù)!{®  ‡=†£à,8sœ„\XÄë‚o"i8Çæ?4çÙ“esgZÇÜÝ£ ròõ€Ûwîé(ºÀ`el<£ôXŸ$ÔBp¦†íÕñ9Œ0[èŽ[gM¯¹{ÙXƒ|P ôyóiÊÔtJù¶«7›f, D±|òí-Õ}OsVw£®þÕD«Bt P·É²‹Ã¥¬|@Zòê (€;ÍU2ìmb`ïŸ#òÉÉÆèÛ‡è[˜7€ž2cÑ+÷ØŠ RDôº>ÐkaÞuúx×À©6ErMKpLz9¦ÍX=‰8è.âÀ»ú7Fô8«„<ô¬(H tÀ¥T½”e2 œ›pŽËd¼Ó†nWà ¸Û6ö óröÜ4QòVPÎdçdç€2ªZ¤å b$!«?ßö¼ãþ¹̆§ë ›r œ2S"״ݼež/Äá¾JÆE[FÛJnA§”dzmÂqÙ¡¸+… VbLFÊ.Ĥ )%éO;´Z™–ˆz>® ìeÔ‘-È’.AV~¹¡æ±ª$«’R‘9^-¨OvrQ|9(- «,»’êŽý4ÃsƒãyãŽèãk²k¢+CO*JßÓ;“r²’YÊ»¹ñ!·cÛÆ :Ú¸°þEÃ)ÐÓa¿ÙA‘8÷f˜ýmåq(U8ÀŠJ^i7bN´ÃL,Ösõœì]Èg°…²zÈÒ]ësÌXEvºZ™Iu7xÌyƒ¸ð äÓs‡ƒdI]wîõé¦3u¬Û„E/j»‰ êcÛäAöEï¢Áh–Ã.Û]ØÇš± ”ýê@ƒ"º¹ ~ֳƮ®¢ÔAh€=¼C‚Ù°3 Wþ³Æ:Õ¤Äâ–¥­aœZwÂ,dÄ?HÚb›÷Öb«Hަâ¢\S½­—½³m•ÒÒ)Ýc»2õïY\9¸ý c1ȦšùLû œ#þKe.EA {RãRB]”dZ…\—RñLq®y{™6’p z@éü¹ üpÏ…D T9y ˜ª‰+çGÆÇEíÜ·«õù1è\˜Íô0ÛÛF݉äÐúp*NRS˜ÔÑ67@Í^z㇓zȃ#tŸ9« ¬VªZ§©¿=ø ÅŸ¢‘3PÿÇCGÈîûUÓÕµÇaƒs£ Öà|=br eòðÔp\›I'fÀ"…:©š¤€Ú`µWšØN)/$¶Ë˜݉š¢T¼ÂíW‘gvBž Ø?'E\”RŠAI^^I–ú;¨.:K©:£È·~XÊkÒuåßLÒ¥ò([·á! l¾¦uZUÐtñÇgVþ¸ÝÆka&]C­±Beˆ·òGÓ ²R ´ ”ºh£Qþ¨’×Ý5®[’swrþuŠÒƒLoÈ0©ßÓI§Öú`¿²#g²…>™ôgÛáºz= Cì—ñ6øÌY¸ìÓ›?߸vãjëO[Ž>kƒ±ØßëM·hÙ^IV$ >îfì¹ú³Æ™"T$\Ý™QX¦¬. EYX“º†×3bto Pv1¢‘—á;Îù[°â&×4n u ’«~ECQ¿É1óøb¤¡ó‰'5æ´ŠKÎ¥°1›7Ê#Àb°ø”ø{Ju™.¹}éü €Õ?Õ£^ÚŒ°‡&^¤ááX=ò@±‘è:¬‹„pue<Ì ?”GÏ|ì”ì4x΃vp½ðxñ¥Æ¢à.h–—zmÃ+­`YâÆÄ Q±ÓAOôá\Ó«¿<âBµ™² ìUVO÷¾ LzþîfmU™þò< ž·pûLfÓDyÚ'ôÂßjþN袨« C$îN Ü7\¡Â,T!uûɳgnOE‚^ܹSÚ‹ŸCÚ6Yi’ÚÿIþ|dŦM;VLƱ0w¸ËÐíÂùËpûeÇú‹"3/ùìâº[Üþ¥p½q牳Ž=sîð¶Më}}½Øit–†POoßêh×ÇëY]Quv±JY•R(MUQ}•¨qc¢·2h;+. ¬Ø¨÷—-ž½C\*b‘(–Ç„ %ü|™›ø$R³^­ïÀw^µ×wjs“»³r –“É $gšÅ–¬$±D©™ ;³$»€‚ýÐzââ#GË󛚴lMY>¸ ¨èfù.Þ1Ñ¢”XÝ¿{çÀ<ÄÒ¥P¡îO¬d“‹ãö¥-/oο¯>¾Ç©&HqP2ꄳ3Óód…  ÓØwà::„œ„ú¤sòÓà:8ÚÀW'‹ÏWjŸ‚ /\™¿›µ ¡4F²õ‘³¼T©*‘”ÆQš*#+­«½YJ›cáƒ\Ó"xœ¶–À5oÁéÿr ó8ޱªú-]¢Ç“awãN£·1œŠñèùôèÚ­Þ>릲KIèBÞRa‡¨ï=@}´üÿƃƒI§S÷0WoM•± ì+AXEˆ&L/Þ¨+ÕŸhЉ˜Ÿ‡)ÙdÅžøpüì'¯bdõ´°§¶î?w„þÏWàý=ƒí¦á´UßéU-¨ è•ð'm ?†tzaRØëc*#"bb""*côúÊJ=ÓÝÏ\ƒe×ü¯™'o…u´>õ[!˜IyíX;?Â;»n³³.ý°²\©Q–‡tI)älÑR•ê’¦|æ`˜A|k)êÖ㎫‡eŬßÁÈÜå”Ó ×òEþÍà„ËéÖ“7aßÒ÷CÕLVLaª¶[9[õ\Z|X2ã×¼±È'wñüÙŸwÿ6šÍVþ"(É z»ádfqÄ+“}#¦“=Mí|ŸñÀ?*0Ò?³¿p Ë”db0ʹ”^ ‰Äć/ú‚ã÷ÃþW'“é÷·úÆŠµFèb„ÎÝâÁù-ªwÄ[NG\:¥^½ÎÜþ‡üµ6Ì~¸aÚµ™i_ AžCs/ÉñA/D¢ÙhŠ|e]p¥ tZ;¥Þ½tV/•í}ŸüænZOC-®ék›>”ìQw0Ñ ÚÿCqнz)ú‘åîåµiå™3ðÇ3~Û¨ßH4èчϟ?z ýCy}ñf¬,…;K.º×õƒ^1Ô¼Ãd™×•›$ÖýYè¹yÝñÖeu ™]ˆ.%l-JÙaætÍéyË$“‹só?FîÇÉÖ©)ð/õÀ¥T€ü–žòò48žmƒýÌ?æÓ6Ži<­h‚8@…Ø>ŽÚy±]Íä±Õ“± €…óœZ;8TU¿’ARž¨»ãÜ}cÐ’†i-$§‡ù%ìŽ`$û"ʃA“FÇPGÀF¸ÊÀ)4)¹¦ì‹ÂnÂ<¿W3"}Ñ÷ÉkR¼”Ø©W·Ao¥Z^%r¬è„ +ºmh[šf GY‘rÎË4ª7ýo•zϪÈ[ÚœÀj¬Ý\ò1)+Ðf垃 Ù±²Ëö9‡âTŠ\~-ÈÅÏ«AN³•hÀ–v8ûòk(íð²œ&†?Ð%pôƒ} ,1' ÿ— â¨èramVÓÐpnŽÿ @>ŒÓ+”í—ü9¿>„ý!9£ÙyyÅûù0XF¢W‚Ý­BƒB­TãßlgU¾2W¡¹.í—O}yÿì'n³Ü×/µ45©ÅÀ9j¼€³zörC«ƒP$@v”7k4…õLlïÃ%†KÚòÌLPB™ÍgзdjYœY(»³« +¬íàùCi´–Ÿsá5S;}Ö/[.÷Kß”ƒ>ÌôaT~`w¦Ÿ*ª3éý +/ó`æ9Õ5Õ9Õ™ìóà,ÕYô0Ì4ÀíÇ£FOó1¦ù8äX ;é%ÇÚδüúÞ…­^ë=|—°_‡ÒßÔk¨³ï¡~¨ÿGó]×ßòuãôûâØUkŸôlŸ>þåîÊKn:f>j¢ç¸· ¯üðôÂê5+Ü7Ì1ã-¼¯ƒjl‰ãO~âÂpÓU:ëDP^Öüá‰Y¾ÅÈ×Y%ÉŠÕƒS®ÒPp=Üñ¿°2·¶àà½:`Â=l†i¬¥“ÐàïNÆ  Š-ËÎÉQcQP§â ãÃBÊ—a¶ãŒ[ßè£S×8q'ÌÁé@>žíΜÑ:Æ qÙ´ë¦/î<ºÙvëˆ^ ,ckƒ‹6c.¤P*@HË9å¹qýKœtpÌ 8á£å4›¼¹&;øý%YÔ š›Œu'Ëᇓ¶þd äå´DH€K(HWÊ$h€ó¸·Þ]HÊA``3(b¿ ãÐoÛÏH1Ò’Š+‰×5fÕe2ep Ãïo¹†âºøÝ2Ã8 `¸Ã!¸ áÂ{&{º%¬6ÄŸº§!ªé@Mc#ƒ.ÙÿãþäÝ%ƒ)ç±ãÅ««:¾3<ìXuÕÂZÃzúó„#>`3Øì³mU"µŠi$áù¨ý*%§ÕÙy ŠÒGk„ò€ôís..„T"³ÇŒê  ¦Œ9Àƒ+Nn€ÖˆßÐø: V¸›·7ý”´lsRrš $PLëtÕE-_yÞB} ˜ –‡¾˜ñç!»„U‹€ˆVãÏÍ¥nد/Ø´œ'Ol/ ¬´öýïv¯í´§6ú‹$É©Ò ¦$¥ñšÊŸÏAûÏÚü¢"‚"4­W´Ã1í0£Žmç4·µ·ý‰¹¦¥¯‡ÐÙ™9ýË%atŠH–Æ Ú¿—§')Ò@Š‹¨L\Q[ŽÕ;üîúΞK[¶ìYëæÖ²öÔ©–Kw˜™Ëh™¨îèÑŠº¢¢ŠH__Q¤ŒEM÷è{»Û¶zû¯[¼à³ '[\¼k©?z¨¼¡¸¸<ÌÏW!3[›Îä«å´™¦šßS‰éÂÜâ­y svÉÝ Õ€ªÍÑæ±]`ÿ08¶w>í›?1(ü³ÄTœ(»ðìt}YK=8Cµða•6ÚÛ}CHµD§«Òè‹Ò ÒÔLþDîg€zùYHhTŒL”Ä¢ñóÀt°‹Ú 6¨÷1N %ôÛð¨ËŠý˜²½‚—hûmxjÓíÅmр⧠“%…)9,œƒ8¥h–3÷ ˜*Á-H¨dµ°¦îÀ==ßzvÚð_œ£m?´Áå8WÇ™âèŒL3¹¡æ­œ…P¿®wZ> Ý®(FËÐH4 CŸ á@äG=yx¡^’â3@R⟄%1 p |ïÅËßõÇ’ÖT±«ÐMzÛÎË÷?øØÑu®®>ëw˜ùDgŽí‘\ÆÀDÐE¹Å¹¸ú²Aý. ^šY«úÔc~³78ËÃUî™Q "®Hó ¸â$¢ÂÔbxÎZD¬•¥$¤¡K:?ÈÀÁ·QJwî"Á{÷‚½ùõÊϵŒ!höÆÎ:q&È”¶¸¼T#ËW¨X¾æã½Q%æ¶7Çðz,&Å|œ'Ÿ¾@Û¯;œ"aÿ^Å U'íc {/2<åõX3L`Ü^p.Ä o`N «i8Ædh Kæ@ŒH2Ecx=àÇ ±¤ 6ãÁEVÜx-Ðr.š¦pá;¯?¤Ó ’51€Jâã’³“²RYøðïs’òâ+‹¶TSž—^¡fm]››¯ras-ñØ&–¥'eÄ¥¡¥57½<í »?óÝ% ñ¯çïUçª2s›åRœ[ç_î’î½äË”¿Ç¢)½®Ý­ç½æJ¯¾a­Ó¹Øf›Á7mè‹™Bt­7pîš^вÜTa!ò44ÐÝY’œœâ©”‚êlµ*·ˆù³ýÏ5%òL .ÕM¹y¶,—µq7µÿ‹ð€)Ý™ò÷as­Éçõ :·Lp4ƒOLŠ$!ÓÌ¿W¤ˆ•$»Ä•Æk+sK‹Õæ©MÔs¸Çv•ÁL0]é:aUXJš(˜t¯®Èºõõq6/§Àüº§<¾D=zr\زçÐÞòÚê1Ï9e„ŸáÜ 7ô­‡!;d?Ñò­„5/Ñ0híŸÃáË@”G/X‰ƒù.œ`üíÎíèÝ•¨ï‹xÊüÓ-ß44&{³òÊ<Îl”Z«®Æ©·qfijÊT°DPÓx HÄ’-J R…©ÑaÕʶV 9™)äÊaÀçLøaÁù”“€*¯õ|•œE#³0in¤à,¨É8äÙp¸¦t¯ªÆ*ÐL /±[Òð>®v}ùB”*Ã(î?Û+Q¤+cxm~yZiÅ!õ£L§ëTžíD&ÛVFSÉžèX èõº§^þ^Äë]À¢ÏtÀR#÷‹‹´<95 H)ó[>µæem×)µ(‚AròÒéŸï9x¥íøUð ûO¸‹¢¾óçÎÞ£OÔX{s±<—)=~¢ñ< |µ}Ærïuîžos5n»zpÌ«~kíêì@@Åc±U‘Žå1£Àî ¦vÒ®Ò#‚ !Šm B+x  ñ ‹Çñ5~ÒÞ/eUjp è©'<ìÛÒýeûKOªª­¡kˆV%±Ñ*d—©hëbï™—Í_:ÚñiŒ4î2Ë>¢Ûöë/€sÔ%_ ê¿|ëŠà©ÖlOIjAFÓØxÓüîú©Ÿ0I`d ÅW(Ö§K§œ~72sœüíô'ëÖlX=u×ÂÂQlNN®h{ÞYNÿe–þ{úìæ¶Kî –RÁþœGðwó ê/é2I™815-5… ‹ˆK±–MÎO(J(ê‚@$ˆ â…’ð¬*Å¥â²BuŽ:—iÐ×–•€'/–'hc÷: /«ÒhKë+Ay—ð' ¦>8î´qÀ Zž¸‡ç§420½Žõ>±%‘$îÙ®˜¿ô’’ÄDÑ M™ ¤Ð¼NІ|øÒ½äY]Ûh€³ Žg:6¡Ò¢ïL.t ðMñ‹1‹«Û{TiTÁ‹‚¦ò윂<¦®éP9&cN¯[²rÞ²O?ŠX•w>{1/{±^P+ “ïžóp9´‡C~{¹/þŠú2 M°mÈ'Q\.ÏÐרékÑ¿¡cÿñÿ½Xâ6 endstream endobj 23 0 obj <> endobj 239 0 obj <>stream xœ­V{P×Þ5’]¡Š{µ½u7Ó Š¯j­Zl‹PTåÚB±ˆ•‡ `È#$ù%ˆ¼‚ $° U…ÖŠ·z¯Öޭ޽ÚÑÚw­Ö³™ÃLïFlëÌmû×Ìd’™³{Î÷ý¾Ç!‰ñã’$]CB}?¼…¿“³ã„À[%Žp“€ÛøÎgÝfMAªÉh•š÷!!ÉÕÁ›•©ÙéI ‰*Ùì@Ù"_ße²€òô¤¸ØYH¬*Q¾#V%þQÈ”qIrUöY€B! u>±S*ß)Oß%ßæÜ9P¹#5C%O—…(·ÉÓS‚˜¢ L]•¾:Hµ&6nÛ?ä ‰¡IaŠyñ±xƒ˜I¼IxaÄ,b6Nø¯+‰UÄ Äjb ±–XL/!Ä$bº éAfwÇ%»!ñ—t_9^ï2Ç¥G:UZEyR»èUô?'”MøÒµÆõ“‰ž¿«÷_$ãÀ£Í¼ÔH óëMv䀮¸8'Þ™ž¿]•è§§Ô»¥Vè†NhÒéhž 5ìæ¡*eƲ>ÄLGÕÒÓxî¾½-hžÞi¬‚ê-=Ç¡JᆖæwS! ®Ük£±]¨g+¾æ‚ÕR÷_Æ-Çâ!„¿YH4þ Š¿"¶£ n@›²Se“×l‚³:WIë¿•b/µ‹‚ºXYÉáFj‹ÖŠÛô ýÐ5úAçÉÖªá8‡‚©Ÿ?95òAMäçüÉÊH=O‹G oj›0ÇB¶ÝD]7%BJbдçïcìé-ÃSñäû³‘òüñGäÁâLÁl‚X‹ê½´ý ±†-GÚOž¨ë‚a8’ܘÔkˆ€Xˆ‡7Ó£•[¶dÆ‚s—;«‰ Þ1Ÿ'‡ï «Äáïx…©‡Êü"­¶ ˜ðOæC‡¼ái¼¿Œ—à(¼-Ç/¢·ÐòŸÐ 4áTææAQž+Äó°[ÀL —ⵃèê@Áƒ7¾à—¶pÆ<ƒ¦h”™¹1nñFͳ3mäÃ+¨é¦UáeÌI¾Tkš}ûG@£‰hÜ7hšâóv ß”±UÎPx¶“ìKåÅ1ÜhâRè'Xûûg{€þôì"q+iÐâåQòÖÎ\^#¡Á‰º?Æ©±³<:d'‘ì6жI‹P£”¦ãÒñ  ±LúŽ®ÂΡ†»ÔwÕŠ%œ TJ—ä+|بPj7Vô±è)Z¶p–Ñ6©e¸Œ^V4K¯ÕñÜh¯Sû±*…ð©»à-ÊÉ¥‡|xéá´e3GªÐ,$eõ”NŸ“;éTóîfss]{ÇŽö¨ ±±!*V_ŠŸûm k 'á0´èGDÅdR¯k«º¼6\v‚êãÑñ1P‘6‰ðãUfôýÿ=“´·ôœ(’Ãp:E$S Kª»9¤»M}[•¼t ëRuòv*{ŒuŠÍK˜ ³"VѧÞÙ¢rP/Ì|$ž Û¢xP$sx_Ù–§‚µjØÛ` $–ÒŠêni~<·žÂîxäùâ7P÷“aŸÔÊ£þJ‚1h~ E|u¹kÀÆÕ§v%º *M"ä¾n§i$A“QcÉá÷úëË?PÚój¹Ã]}P m¡²iuEVs­é€¹!—K‰R'$²©MÛjÅZ™ôjD{‚i§Ó)E$™¬Ù9qñð½òûP4y<¼z$ëX| Öù&̃LH†BcJy–Uœ†©¬®²†¾W¼ß5Yöú®®ÑZgú6ÌQ©`Î"î8öc:‡~y¨_Ô|Ÿ€¾3¦Ýäž(n§`þ¬»×@d¢"ŒÖ£o¤c}òHL£¦ÿcy?ñIÌ“t’Ÿ‚ž»…î}gæ™'D¢/™¯­Ÿ~ŸÒßãI×ñ,ÿÞ¿ÇC_é p¾Yü~"J)Ï>ä&½ ò}%íñ°VŠh¢ûå}ñg¡ èÏënµ”CµØÉ…zN³^±S!«n,¬/h*¸XÜ[x®à–tÒ˜¬c0H¡ÕXÙ°¯ÒØf o"OÀ>K¢×ãgY:#—xTZÈ $r­·AeÚw¶ìP¨ÒSRšÓùö––vÏÂ!¢!ÏW‹†4ÿÊL¯Ñl8&ÑNâù©à’²÷8ABMH¼q,´‘ÃçÑõóâ½ÆáË4Âþü"½>¿ˆÍË>P³ýíÝoŸ˜/úk²…^¯õm.Óp½Ñ5h¢òzV¥îP’Ao‡7è Hÿ…~XÌßBV_åy@çBa&‡Ã©L(¬®0ª+Øšƒ{ó:·á³½âÂýú‡wÛÙÎÅœ‰ª ®[lžþJcÚy8F_8}þsÄœšë]Ë–f4Õ@×B…ù7dÏëÁÌŸªæ8ôA½~à7ÕŒ=ÃÍÈßÉa°E‚‚M lß%(=­)/ª¨º~¹þ+­{[bVjjjCj§¥®ÎÀºg49V4ak=J©’â­Õïze"ë:~Y£ÛK¹›Û“Û$‚ø/ØyßQ endstream endobj 245 0 obj <>stream 2014-05-12T15:50:46-04:00 2014-05-12T15:50:46-04:00 dvips\(k\) 5.96.1 Copyright 2007 Radical Eye Software quick.dvi endstream endobj 2 0 obj <>endobj xref 0 246 0000000000 65535 f 0000180856 00000 n 0000227596 00000 n 0000180491 00000 n 0000173605 00000 n 0000000015 00000 n 0000002628 00000 n 0000180922 00000 n 0000186676 00000 n 0000211291 00000 n 0000186344 00000 n 0000209096 00000 n 0000186106 00000 n 0000208453 00000 n 0000185712 00000 n 0000203699 00000 n 0000185322 00000 n 0000198600 00000 n 0000184608 00000 n 0000189046 00000 n 0000184370 00000 n 0000188389 00000 n 0000188047 00000 n 0000223225 00000 n 0000180963 00000 n 0000180993 00000 n 0000173773 00000 n 0000002648 00000 n 0000008681 00000 n 0000187421 00000 n 0000214535 00000 n 0000181100 00000 n 0000181130 00000 n 0000173935 00000 n 0000008702 00000 n 0000013140 00000 n 0000181184 00000 n 0000181214 00000 n 0000174097 00000 n 0000013161 00000 n 0000016940 00000 n 0000181268 00000 n 0000181298 00000 n 0000174267 00000 n 0000016961 00000 n 0000022617 00000 n 0000181352 00000 n 0000181382 00000 n 0000174437 00000 n 0000022638 00000 n 0000027776 00000 n 0000181425 00000 n 0000181455 00000 n 0000174607 00000 n 0000027797 00000 n 0000033764 00000 n 0000181509 00000 n 0000181539 00000 n 0000174777 00000 n 0000033785 00000 n 0000036472 00000 n 0000181593 00000 n 0000181623 00000 n 0000174947 00000 n 0000036493 00000 n 0000040739 00000 n 0000181666 00000 n 0000181696 00000 n 0000175117 00000 n 0000040760 00000 n 0000045270 00000 n 0000181750 00000 n 0000181780 00000 n 0000175279 00000 n 0000045291 00000 n 0000047062 00000 n 0000181823 00000 n 0000181853 00000 n 0000175449 00000 n 0000047083 00000 n 0000051309 00000 n 0000181896 00000 n 0000181926 00000 n 0000175619 00000 n 0000051330 00000 n 0000055839 00000 n 0000181980 00000 n 0000182010 00000 n 0000175789 00000 n 0000055860 00000 n 0000062023 00000 n 0000182053 00000 n 0000182083 00000 n 0000175959 00000 n 0000062044 00000 n 0000066472 00000 n 0000182126 00000 n 0000182156 00000 n 0000176129 00000 n 0000066493 00000 n 0000071758 00000 n 0000182199 00000 n 0000182230 00000 n 0000176293 00000 n 0000071780 00000 n 0000077609 00000 n 0000182274 00000 n 0000182305 00000 n 0000176467 00000 n 0000077631 00000 n 0000079621 00000 n 0000182349 00000 n 0000182380 00000 n 0000176633 00000 n 0000079643 00000 n 0000084887 00000 n 0000182424 00000 n 0000182455 00000 n 0000176807 00000 n 0000084909 00000 n 0000089619 00000 n 0000182510 00000 n 0000182541 00000 n 0000176973 00000 n 0000089641 00000 n 0000091242 00000 n 0000182585 00000 n 0000182616 00000 n 0000177139 00000 n 0000091264 00000 n 0000096380 00000 n 0000182660 00000 n 0000182691 00000 n 0000177313 00000 n 0000096402 00000 n 0000102104 00000 n 0000186961 00000 n 0000213641 00000 n 0000182746 00000 n 0000182777 00000 n 0000177487 00000 n 0000102126 00000 n 0000107422 00000 n 0000182845 00000 n 0000182876 00000 n 0000177661 00000 n 0000107444 00000 n 0000110771 00000 n 0000182944 00000 n 0000182975 00000 n 0000177827 00000 n 0000110793 00000 n 0000116094 00000 n 0000183019 00000 n 0000183050 00000 n 0000177993 00000 n 0000116116 00000 n 0000120556 00000 n 0000183116 00000 n 0000183147 00000 n 0000178159 00000 n 0000120578 00000 n 0000125256 00000 n 0000183191 00000 n 0000183222 00000 n 0000178325 00000 n 0000125278 00000 n 0000130914 00000 n 0000183301 00000 n 0000183332 00000 n 0000178491 00000 n 0000130936 00000 n 0000135344 00000 n 0000183400 00000 n 0000183431 00000 n 0000178665 00000 n 0000135366 00000 n 0000139669 00000 n 0000183475 00000 n 0000183506 00000 n 0000178831 00000 n 0000139691 00000 n 0000145193 00000 n 0000183563 00000 n 0000183594 00000 n 0000178997 00000 n 0000145215 00000 n 0000151367 00000 n 0000183649 00000 n 0000183680 00000 n 0000179163 00000 n 0000151389 00000 n 0000155942 00000 n 0000183724 00000 n 0000183755 00000 n 0000179329 00000 n 0000155964 00000 n 0000156805 00000 n 0000183810 00000 n 0000183841 00000 n 0000179495 00000 n 0000156826 00000 n 0000162032 00000 n 0000183885 00000 n 0000183916 00000 n 0000179661 00000 n 0000162054 00000 n 0000163285 00000 n 0000183984 00000 n 0000184015 00000 n 0000179827 00000 n 0000163307 00000 n 0000166588 00000 n 0000184059 00000 n 0000184090 00000 n 0000179993 00000 n 0000166610 00000 n 0000169141 00000 n 0000184145 00000 n 0000184176 00000 n 0000180159 00000 n 0000169163 00000 n 0000171668 00000 n 0000184220 00000 n 0000184251 00000 n 0000180325 00000 n 0000171690 00000 n 0000173583 00000 n 0000184295 00000 n 0000184326 00000 n 0000188591 00000 n 0000189648 00000 n 0000198936 00000 n 0000204046 00000 n 0000208655 00000 n 0000209361 00000 n 0000211552 00000 n 0000213870 00000 n 0000215218 00000 n 0000223498 00000 n 0000184514 00000 n 0000185156 00000 n 0000186250 00000 n 0000187299 00000 n 0000187941 00000 n 0000226163 00000 n trailer << /Size 246 /Root 1 0 R /Info 2 0 R /ID [<87F918090A2088B2D86167079CAFF9CC><87F918090A2088B2D86167079CAFF9CC>] >> startxref 227801 %%EOF cfitsio/docs/quick.ps0000644000225700000360000114204513246025103014417 0ustar cagordonlhea%!PS-Adobe-2.0 %%Creator: dvips(k) 5.96.1 Copyright 2007 Radical Eye Software %%Title: quick.dvi %%CreationDate: Mon May 12 15:50:42 2014 %%Pages: 41 %%PageOrder: Ascend %%BoundingBox: 0 0 612 792 %%DocumentFonts: CMR17 CMR12 CMSY8 CMBX12 CMBX10 CMR10 CMSY6 CMR9 CMTT10 %%+ CMSY10 %%DocumentPaperSizes: Letter %%EndComments %DVIPSWebPage: (www.radicaleye.com) %DVIPSCommandLine: dvips -o quick.ps quick.dvi %DVIPSParameters: dpi=600 %DVIPSSource: TeX output 2014.05.12:1550 %%BeginProcSet: tex.pro 0 0 %! /TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin /FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array /BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get }B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr 1 add N}if}B/CharBuilder{save 3 1 roll S A/base get 2 index get S /BitMaps get S get/Cd X pop/ctr 0 N Cdx 0 Cx Cy Ch sub Cx Cw add Cy setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx sub Cy .1 sub]{Ci}imagemask restore}B/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put }if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X 1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N /p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{ /Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT) (LaserWriter 16/600)]{A length product length le{A length product exch 0 exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot} imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M} B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{ p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end %%EndProcSet %%BeginProcSet: texps.pro 0 0 %! TeXDict begin/rf{findfont dup length 1 add dict begin{1 index/FID ne 2 index/UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]FontType 0 ne{/Metrics exch def dict begin Encoding{exch dup type/integertype ne{ pop pop 1 sub dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def}ifelse}forall Metrics/Metrics currentdict end def}{{1 index type /nametype eq{exit}if exch pop}loop}ifelse[2 index currentdict end definefont 3 -1 roll makefont/setfont cvx]cvx def}def/ObliqueSlant{dup sin S cos div neg}B/SlantFont{4 index mul add}def/ExtendFont{3 -1 roll mul exch}def/ReEncodeFont{CharStrings rcheck{/Encoding false def dup[ exch{dup CharStrings exch known not{pop/.notdef/Encoding true def}if} forall Encoding{]exch pop}{cleartomark}ifelse}if/Encoding exch def}def end %%EndProcSet %%BeginFont: CMSY10 %!PS-AdobeFont-1.1: CMSY10 1.0 %%CreationDate: 1991 Aug 15 07:20:57 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.0) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMSY10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle -14.035 def /isFixedPitch false def end readonly def /FontName /CMSY10 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 15 /bullet put dup 102 /braceleft put dup 103 /braceright put dup 106 /bar put readonly def /FontBBox{-29 -960 1116 775}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052F09F9C8ADE9D907C058B87E9B6964 7D53359E51216774A4EAA1E2B58EC3176BD1184A633B951372B4198D4E8C5EF4 A213ACB58AA0A658908035BF2ED8531779838A960DFE2B27EA49C37156989C85 E21B3ABF72E39A89232CD9F4237FC80C9E64E8425AA3BEF7DED60B122A52922A 221A37D9A807DD01161779DDE7D31FF2B87F97C73D63EECDDA4C49501773468A 27D1663E0B62F461F6E40A5D6676D1D12B51E641C1D4E8E2771864FC104F8CBF 5B78EC1D88228725F1C453A678F58A7E1B7BD7CA700717D288EB8DA1F57C4F09 0ABF1D42C5DDD0C384C7E22F8F8047BE1D4C1CC8E33368FB1AC82B4E96146730 DE3302B2E6B819CB6AE455B1AF3187FFE8071AA57EF8A6616B9CB7941D44EC7A 71A7BB3DF755178D7D2E4BB69859EFA4BBC30BD6BB1531133FD4D9438FF99F09 4ECC068A324D75B5F696B8688EEB2F17E5ED34CCD6D047A4E3806D000C199D7C 515DB70A8D4F6146FE068DC1E5DE8BC57030ACE57A0A31C99BEDB251A0ECAD78 253AB321023D15FF7F55A3CE81514C1E7E76240C1FB36CD4874DDB761CC325F5 D588700B294849D690F93526EF438A42B9B5B0508584EA3766D35F5B8D51C458 ECB9FBD23A49576EAB06BACB7EA6D300985500835F4FE597D4A1110C8EABE6FC CE3E1F95CFD3A42446F25355381D476B2FFB6EF247BF58A6FFC5EC0E4CC207BE 46485F8E07350B37DCA8C1864E62614332A1D3C9DEDDD6492181949A2C3498C9 EC2A81C1F4FF989A4654E375F509D24D969B97D2A9940FAF43BBB286E08559C0 F8D9674B0A294B36D3A050F7DED8C80E1D230812F6B8387B17948FD29FF050E2 AAC5EBE5D96AFD0879534E2F4BB81613A1571750F9CF4215199F93813D815B5D 1C79E11A0FCBB627CDE569F88C741CD502627777BB058ECAC09B6ACCFACA69B9 8F8168B0B5A1A6EB13E884B348FBB2ACF9EB180F6E27D57F8503710CE037A34A F8B157201657C825E2A4B4A7696B58B7A988C05E43E66F0FF277A7694C555C54 AFB1D32F6DE102136FC810E1F3B5CEA42476EAC7AAFB390E3252B2169DCDEE6E 328507BD0E24734A85AAA263E0D2F64BE1607455BC855785BC27F8B30FE917B4 23AB3C812975355942E955501AF85A3C0CE836911AF679EA44AD6A7D042A6549 0C471FE294E8490024D93ADCADED460FAB7FBCDC29EFEBD2A9A127E11869E659 961B29206CE63944B6FA4B9315BCC528EB1E0223CE94C795A5D5231A7FC8545D 6B287B965F8EEDDB67A6774129DD01D5A21694ABE320BB2553043D4C42ACFF91 1009372CB03381035BEEEEFD05631E026A0980A72A67B3703323A4E7C94FFCEE 8D0B7407F9CCC043D3D184BEA4728385D6AB2FB0641DD8F5BA7E04035D30D628 7E97D31C1486DFD5B1D076B84B4ABA4829ED4310321F1F24B847C44E00185A69 37711A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMBX12 %!PS-AdobeFont-1.1: CMBX12 1.0 %%CreationDate: 1991 Aug 20 16:34:54 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.0) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMBX12) readonly def /FamilyName (Computer Modern) readonly def /Weight (Bold) readonly def /ItalicAngle 0 def /isFixedPitch false def end readonly def /FontName /CMBX12 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 45 /hyphen put dup 46 /period put dup 47 /slash put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 55 /seven put dup 67 /C put dup 68 /D put dup 69 /E put dup 70 /F put dup 72 /H put dup 73 /I put dup 75 /K put dup 78 /N put dup 79 /O put dup 80 /P put dup 82 /R put dup 83 /S put dup 84 /T put dup 85 /U put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 103 /g put dup 105 /i put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 118 /v put dup 119 /w put dup 120 /x put dup 121 /y put readonly def /FontBBox{-53 -251 1139 750}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 2BDBF16FBC7512FAA308A093FE5F0364CD5660F74BEE96790DE35AFA90CCF712 B1805DA88AE375A04D99598EADFC625BDC1F9C315B6CF28C9BD427F32C745C99 AEBE70DAAED49EA45AF94F081934AA47894A370D698ABABDA4215500B190AF26 7FCFB7DDA2BC68605A4EF61ECCA3D61C684B47FFB5887A3BEDE0B4D30E8EBABF 20980C23312618EB0EAF289B2924FF4A334B85D98FD68545FDADB47F991E7390 B10EE86A46A5AF8866C010225024D5E5862D49DEB5D8ECCB95D94283C50A363D 68A49071445610F03CE3600945118A6BC0B3AA4593104E727261C68C4A47F809 D77E4CF27B3681F6B6F3AC498E45361BF9E01FAF5527F5E3CC790D3084674B3E 26296F3E03321B5C555D2458578A89E72D3166A3C5D740B3ABB127CF420C316D F957873DA04CF0DB25A73574A4DE2E4F2D5D4E8E0B430654CF7F341A1BDB3E26 77C194764EAD58C585F49EF10843FE020F9FDFD9008D660DE50B9BD7A2A87299 BC319E66D781101BB956E30643A19B93C8967E1AE4719F300BFE5866F0D6DA5E C55E171A24D3B707EFA325D47F473764E99BC8B1108D815CF2ACADFA6C4663E8 30855D673CE98AB78F5F829F7FA226AB57F07B3E7D4E7CE30ED3B7EB0D3035C5 148DA8D9FA34483414FDA8E3DC9E6C479E3EEE9A11A0547FC9085FA4631AD19C E936E0598E3197207FA7BB6E55CFD5EF72AEC12D9A9675241C7A71316B2E148D E2A1732B3627109EA446CB320EBBE2E78281CDF0890E2E72B6711335857F1E23 337C75E729701E93D5BEC0630CDC7F4E957233EC09F917E5CA703C7E93841598 0E73843FC6619DE017C8473A6D1B2BE5142DEBA285B98FA1CC5E64D2ADB981E6 472971848451A245DDF6AA3B8225E9AC8E4630B0FF32D679EC27ACAD85C6394E A6F71023B660EE883D8B676837E9EBA4E42BA8F365433A900F1DC3A9F0E88A26 326BC603CD28B9A6E511975D39BF5957AC2D66D48E75D233CC1B78B0BDE71C21 DF00ADE87769BAF3FF3896F1FE5A8786C78F798741CB0F38300E98711F994F13 37994AF499D5BEF056FCC6F2BEBE3923EE7AC09AC246F5C63106DB4C92DB5DA2 47D1016490CE3A3D571211DA35CA7A7E6FA4CE92074E44590F0E4B4C90834406 EE27172A83A5F1C53F8E474448B21598395590F38D23697E65441DC75FB7294B B560D82E1DDE2EC994ECDCB7F362E60E108B09EEBB71078B84C9070FEAD4F1C4 2332D28EF482E89F064A5F32D95FA80AA2D84CAA27F7B61D457B0DBC7102D70B 3D6274006BA0C4D4731E03CD99E792A76E888922B1DBBB7AFAB73EB3B8306423 25C6856218DA59FA5EB6EFE9FED08048D04842E4D18C13D6DF5F3D92CD3B0706 ABC2024946EA8DDE0ADFFBDD693C08FED862012C73CF7491E1677ADBBDEB1C78 C4791859D9FCF9B153A2A5C3B4B3436254BAF92984DE37309E384D8827978CE7 2B9EF2E4034DDB15418C9C765FECE6FE63BE00659B226092C926F8D652E510C5 B2632A691B7FF8C1ED57C720423CA5BF6F27DAF0C0B90A1C7A568E1C3C21FB0E EB2336F01B06D047EB9E17BFEC91E7994A40165D4DBD085E47C310C0DC0D69C1 FEF02C68B548FD04A31571B0A0ECDF246FB628C9C470B615DC5946D081938DBA 62C43AB08053AE7E3886C50426C64DFA698D9016F6E4421433B2F057FFC237F1 1260F9CA7240208CF50B00AFDA29ABB70231B0886D657F143AF25529AD866823 64D025895B10D19A63C9F07D2730661490DA4E3C3871F38268F5134DD8B67F9A 24A34E18C062E606B06D6287FA2E0336960A11F6B181752772323659BDB9ED0E 96453ED61C7A3CEE10778226B944B46459F36029D48D7A83799979F2162BAF61 83178AB7DEDD28DB42F4CCB6C5F065F4D6F0F97C75D48C2CD500BCC746F45F97 00BB3B543D368B5604B994005587E8158B43CFEB22A43515EF9EDBE9AAC13EB1 6119EB67621D3BD51DDED406D7C7219953BD21F3E8312182CE62BB9F6AEF9199 B64CDBA4C22760D9BE412AFC6E179EBB295A627871A82E88D92FAE94C00BE7EA 581712D8D85FFDA4C8A4EA7421DB198356DCD58F5F2C7058D87959B16199672B 897D985FCBBBCF691A97F9631DD8F5F51134144D3F0BFF482F24C397F3CA59C6 FE739D2D3139574B068E0E7C96B7E1159B79BC024BDE17B54AE59BBD2B0E37A0 F5442F6375D4ADC1D795202B1DA5EE38D0EBE98EE62866718830446C29CB1DCE E31C449C0EC11E936D9F2BC2E38964803852C6550C6E591D3111763BD79B7D14 BECB90421A01B6E242B3D08F90C63815689A90CB904C07BA1D224F790950997A 0AEAE5AC6AE2F213C8E7A418B3F6EADD3BC67596654692F4A61895DAF6D4FA61 459E7E24F2A0E027A5501632188B9348EE4E0D9FCE65FEA80F4281697053210E 73664CDD8A7E2825A308EC570CF22034A51026E13BB004B9F563E3E3F45ACD4A BD3A60D29C82869474E8B523461BA062D2D6A9C98B99B081EEF2DC2739A2860E 769323E29266E24452B9C96FA2B5B6D14FFC5CB45CE9BED68D5DFB5FE278B85C 0E2E0B454A3E657608170E1E0830FA07D09B454F2B1A7792F4BB96E6FE43ED14 4977BBBF88C912DCDFD3D4DEB06B6D1EEA1BB019D19BDC57840A4A3F92AA29D4 AC8A0840A73BB3F118F668D9D4E4C136DFA73CEF0344C2E32C02CEB865FDBEBF 3DBD44B9B6F63EF01C2691F9C7F43309C9EE45DBB423E50505CC6A7165B47ED5 A0311E24203E4CE075F50B36DD2A7DDC85077BC599CC3E00A29C483F1DEB4218 32262EE6B07E54EBA32BE65240B3A47E2B5606674FBC33EB8372B7D39CB2D8FF 6495F31BB367301FC5BAEBE1ED5B854571D4544595D18628C0C789B4AA86CAA7 42C26E3C9CFFF98D224E05E94F5DD426203199FC1DD7B9347B044ED1116D7378 496D80454518EF2A7DC3D2BFBF77EA8227C91E2A8C41B3118E7BCA38B5E8C38A 52587793FA7D5A7B2DBBD8AEB61ADF5F75115DBE4741EEBC0EDE1D74975DF021 49C5E3C4000FA4E4D9E8E6644F21572AB30F6E8CD1886B020198DB7F94F8C722 EC0123D49783351D36BF1AFBB12717E3DFC23063B77388C409A4157C89D552F7 E5B3A2F825A1C8A8524936C2C7872A87C158AAF6AC142D529F0A66CD5495DFA1 BACE93058E8B9D6FD1C62AD19DABEFC18BD047256DFD19B29D88C63ADE376DB2 DC51939606E3EBA52798D23831BBC8E5DC8E6A0DD40D1F434B70CD292EA5E1FE DE034CBC40C250758A3E5300B99CC4342167A4D44784471216C8028E7DC9BA9F E6F540EAE0E87FEFC5BCB5E19650C68FD642F82F3292710AC357F6FCEA4EFD88 6F1049CAE4CCEFFAF6CCC82DDD484D4F7C8F8A825436A6CE713B0A697832BF9B 9BC9BB3A674C608E2913CB52C9471B4F3027124EDB6AAA9A975424A0DB8D63C1 2FEFE0B08D3493A79D685006BEF07C8DD1F2F635309F463025666F2EBCDECC42 B9FFC43D93AD2D4B7F2C0AD302336E8FD7E670E4378BF2052D9B70D25E9D2301 C97C2B9AE8FA1009F7DE7D5AD311F4672CA62775AE5D045E010A031EAC6B266E 7EA68D21B569770452D665DE101075E10E6CEEAF15A6961872A797F9A2E702D7 8FCC9CC526B9764E264FF987591E96482527CE200A0B2D7603BD25547AD258C9 6D8459BAB17C74DDA7101CD13EB38C8DF5A2C9BF87A8D22545B6E8EE6C5D5BB8 F958F433DC59B75F5318882634A85A9FDD941BCD026B75FCC64F068090BC5972 F25E08155D46288E4AD897D72BD07234E04CABEFF5ED56D036786CC07016D92E A638B3BBC6CF15BB6001943D18AB42292A2A8B72FAE9157D2427D375673520D1 850AD7C2A24748951566C61D6B2CFC1818ED0A67F44D07CF80DB914D283E19B7 0A1E167D19FB0BBDDBF65C79BD171B17545CA156096032A60EE45160F77C88A6 9DABD8E12857C244BA0B43394CF491D17C07813B9174EF9D89C9748EABB0F938 157758BAE4E2A4A69C9E460B9E4AD99F23048D258B0D321108EE9B96F843F864 DBD079685328F02EEA46F946A7EF927A1D49DE6DD5D9766420E74C7930895AAD C95C60AC4A1D2FCA0F85072FAE3675EB4DBEC07255C1C0891F87C3DFAF219EF5 1A64166BFA2E77D1ABCCF87DFB1A3BE7F83FCA5FD0F73586D6B0E66B6415EF63 2A7B085D9D61DEEE88BF1A180968C784B175B3D9856A3F9479FDFA071343E654 202EF4CB01815987E628973BC140EEF476CA4CF3E4FB62E657D10E3EBB76CCC6 EB03E73DB444C674EC7737301D62AE46F26A22E049B7AE657194AF8EE17E47BB 2E16CA163719EF4AB0BA827185E862BDEB8E22845FEB1ACE2960E94256D7FBCF 05F2EA5541B861BE2B0D97576E2440555C388B2B3A906DED36206ED6578D1563 8BCD8FFDAE85CF16918B2747CFB5D61DBE55F0E5154910E00CAA6DDF27F8016C 25311A7379F820566CE9D9B27FAA27AA37901EE2A4E72CB77F74879E00140927 89A71148CB996F35E4D2DA6DE9E4B419F1D2387279135677502E169048171730 59ABF7B6EC751302663320C108861037834E28E4457410A2E7BCD9EBA553E4C9 A1927FB48707FF104678AF51681ABB7B728478BBE37726E26A3C545F267FFE88 8E4F2A0EFE2902510D6739A4B201BB1EC21E8CC1E693C7D14819CBD3512A8BEA 3A936897E9EBA3FCDCF0F13A9525F80B182EF1423C5E5A3C82850BE2F7520CE3 0834D1E448235C68F246CBE9420E853F5F22F1404C7A3DE38B8C3D288F7FE595 2D09071B6D22988D80D46D3666E2AEB88872B37B5D5B535D07F61DCF0A29A059 F4E533BC39A06FDB2B45ADDB0190BBB9CA8100EAC30FCC212BE0A475CA57248F E2DF1BAA0729A4A97A479DDBC64573E00DD22FBEABF86F15C60227BC2D074B32 E6F73778F13FA9959FB62F1EA5B2B687F870A7BCA4670C038200D4674E168F9F 684FD2D8C626EDF0465CA01B27978D141722C3FEBF42D86FEF470541590CC184 B487E5816400FD06FFB8C30FED82BACA4671315A7610496DFEB5867A6883DB99 BF42E232663A17F27BDB01C4E2072A7725C02E631B3F85518A00B6E4BFAAD763 8C9E89D64B35F754DAAF4549D4E528941403FF224ACF62E172126CFFCCC4FB6B 68FF632DC25971C19AD4AE284075A7A2DBCC894B5515B5CB914185F388AB124E A1E8BA75BFA9B601724A84A8BBC0CA23716CD9F5B37D0F1DADABF475F23EC122 162BF687970F2E9720B4CF355C5829E395F526FE538CC265C43C916AC1323BDB 543E0DFD699AF2D3AF09BA03B9B7F458FC9073DD02378AA9B70D90A6CCBB2D40 DBF2F4E111C65F8F561BD2004E0DC6BB4DA203D79D11848DB7E224CAF034FACB AF3446FF041FD26C403F31A00DAFDB13BE1CE58B9CE9CE7056C8C2E0C9221987 8E13BD744FC4502135270FF93F8B476A53066B2BD1F7CA457F39B0544C993470 9475861C6B0324C3F9687C0BE4CED83AD7D7B2C2F6D28F4C11F9D61592E6C599 42C152B7204B81F5A64FAF76D0E0CE099F597FED59F4D5EF4947D7994340CA9F D5B0ECBC1B73207A06248B774140E38846BA0B5E6A7A8F88BE3DD277C768FD3A E0D289A8C87CD2F61150EB0F9F30C0745978D3EAF105FA555485877050AC1FC6 A879987588713AE7C38E3639A020382DBFD279AB3236401A954EE71003B9BDD4 95A51D4797188EDFD0144009E3381D7A6A63CCB6E2020F9FD86AB2853407D8EC ADA5D3E7B58066AA797F88FBA287F2C323D340F5E687BA4A08FEA9154ED4F784 5AE1650DC0FDBBA07F733DD26BECD42003F40058DA772D696C4556BE0B9369F6 3E9226DD203FF16C1B38DC8FD4ABDF248EF005295BC9E560598352D2645CEA9B 71A510701EBF4594B2EB118F65426DC4270798402797DB94124CD4079686DF91 9971CCE83DB9DC53A84ECB899FC619D275E7B4F458E80AA3234CF5CAFE573334 D00DC2F92631670510535D8AE7AE12AF46A6208F851ADE39B425E18B65C18072 DFC2816EBC7FBF5D9FAC1C787822B072B739AB88F7FD8DEE48114B45D0E30F71 63A174D8EBAB7C7FE646A6038F7F16A4AB483DD983E57C7DE881F7DBC406AA0A 0BD9B02F1ABF43F390CC750FDED74EB3AE170ECE0468D7DD525543C8DC07AC43 D568BD8749005E1558A811A1A67E2ABC3B8A2680A6EA5E930AA53757897CBACD DC223939F3E07B0BCBD73702A69DC8EFB34896ED2F80523AFCF9E02C37E997F1 9438363D34ED456DBECBC021C4F88CCC95D30F576C026EF40E8886D0F3E11E11 1D28CF7A48786FDC4B2B51B34F19C1D85D118ED41E89F184DD98CE91A33DC5E6 DFB4C390661562E03E83430AB585F4B1247207D22AEF9EAB794E8E2A41C8604B F905C3EC9857FF9D597836999560EF1940A7C64B8FBA9D6B81F4D847E2696F79 B71E7C5CF4AA19F65F9C2CD290ECEE979F7B373F74434D821545F78D295A4536 7045828EC0135DEC4BDC7E7D0E25F90BB531CDD88BB04D16B7DB32231A86B253 AED0F6E049E3601D8CF82B86E55711B1D0DEA05E40ABC9FE0F55F2366B0C2919 051DDB4963B2063FDF8C95AE22AD9CC6F64C78AE0927738CD56492731E54EAB6 C1FE7535949CB688B6D36F1C5D09077C6848631E7CCAEF6BA8B6D09E449DF25C A2E1CB85F5EEEABBB0D892830556D609B1940CDE70ED6C073E1F914D975EF7D4 B7E66E6B6998648AEBC849340619360D69FF7648320E583200740798B2FF1767 E8B46453E37612E7CCDB90E87FA3E1607228AA669263649808BD322EBF924C53 17F38ABFD0740A8A69D86CFEF9EABD0A01A4443B27CF8ACA8A29BAE0EFCBB3F5 A85FE3D3CEEC5962EE8E7368D0140A3E15DE2EC239449F64D7074D2F24215BF2 C71E142773DB4293FC234820E52F1B9E068E86D80DF6F08691A2B4B8694B584D D575CCBFA92640B644697BF687644DFB0E150FF04AE0FB6AA6FF6240A050107D C5F6E4316BEFF51948803156F7C4ADC3D40841982526F125F589D398FA95DCEB 80ADC11560465096F0D5C1C74902CFB4A04C7127BBEEDD068939AD1D345F06E2 D4F7D7AF180E8811716D6F69506FCE9DBFF3EE7FCCD96E745181B24847DC9BE4 F62B1907B0B7612A611578FB82916EBA3717F8F2912D608C4052D2B2B5DCC04F 50524A820AD3D2AC158CAB7E67FA96729A5C22945D5176AB5C276E883FD48294 EF2E1E97EB49FA82D566650259CD9686ADF6D285C4A40F5048BCEEA56EF3EDA3 9F541300644FBCE3CD5F2DD631C1908D2BBAEF439CFD86A577EEDE2EA6AE420C 450A6CF28DE4BCADE38BD15A4C5FCFEC295A2C14A7C99F78D75A7151CC6B5FC1 A95441D26FADF69B58B589B13D3294D6B4167C0A0D39B74FAC3DF4F78ACD895D 5B5B7F4D7925ED66323A408C417DDECFBE5E35527509682E74A9E81F208261F6 443716499B5131978288E6ECCD744F621A0341E400E99B4C4CDBFC764C0209B0 F602296E6F6AAC228282DB7CBD51AFF102A6C7B31EAAC95108DCAD3C97FCC0EF 52CB3B343B5B2F4DDFC39B9BB1D2B2C47955218094DC1374594448205B04F702 6B16F57344D3FABEBEC4387A79D4F135B92F5CCC4D713B1B3EE3F9614F9B9C3E 0E8CC8A1BF6981BCA87E341741224F10FA7A1F74B80D679497C47BDDF3F6F21C 8863E66172417B347E4E19F53998EA8202582B16CDC53906537181BC0640F535 BAB91426DECF471FA5DF51755B0875910C894768C252199554ABD01051380599 4C522244F32179A7104442577AC317ACC38287EADBDCD530C20159431C4BF2CF 1E2AECD88D0521C338B3BC44BAF8233A7E175E6B9DBEB9250309FB3ED820EF83 07F6FEE0A61FFB1E988DF80D11E3F0F62AD3551E0F41CD758BB904C88F816A0D 03D109B3DFBBB87536011EBEBFE0AEBD8EC4FA50EF20C2F256EDC1D7F0A3AF6F 8D10C2F7BE71F206CA45D00A6A34D2786EBDBDB8188BBCB727775AFDB3A49524 CCCFA7AABAED170E1E7EC4D28AADC153A5759830311FB7F25631A90426226517 4FFDD1EA98363A59CC089311D9601B398FC70503669FCCCB1B0D03AA4FA5BF9E 7C176E1CE75A2F1C7D9CFFBD77F8031E4E96C4EECA264B8892801193F1F701D1 573575F9751FCD28BF995E77AF7A72394C442329DE642413F1B647671F573E97 8F4BFB6FF576BEE0C8FB6F0C69A0F4E63719BC5D9568FA1D4F312048BE5604CB FE837ADE17F9D3AC9B443DCC48277D7BC9A8A2E61CF50420DDB4E902791D4753 720D284FFC5A720F0C4278E8FEE55192A28DD49B48A34E4DD203995026B34D2C 0175EBD90BE3F4231A3E28CA35702B6BC05CC6945D804B097D3587A1343935AE 063541A6B114486C87A6EDC4CC6D3C4A82729D3280CF29384F0884AA68954B83 237088C86D58AA5E443CE266681C94D1264207A10FF5E0D274C95F9190EFD560 F0D2D14090D2EF11AED9BB5B64A4FD4BE18DD7EE118DB3014E8F78E8298CAAA7 59C56D8DD2EDCCB625B528DF2C3F52D9092B8C16BF77CF463569F32BECC3FBB7 6D813A2A2E1BC4C4B087BA4C22588349E8DFE84FDC6C94924972C147757AF4D3 6A8CF31BAEC00D5A2F7C7D5CB6062EE8A5B25343843B7F09C001FF5CA1CD3798 03968680DFF00740CB879F36F2536BC35C67DA1ED7FD799F4A71771CC9465B4A FEBAF71098146848359D2FD208B9788F60DBF0E0BDEE9616DFEA61238D49290E C721F0D4253352B1C56387EC8D4DE1E70EE1E30E90F78402261895A74166D150 A82277535A5331CCC170467B469A8D36BC6860A525EF9269CC7A9059D7D29C62 73099824E6B3A08410BAD07601B75DAA79A58D295849BE35BE56F26846D62A7C B523578CB4210E31C61FC784B7F4BE773E78AA4CA142D1A010153F81AC1CAA88 E59E094516F4B8E1D3E183ED5AF7AE7970C2389A78362490379DCA0BD16B9C2D 6CB15F823DDEE982F453C151DB9A4335EDF95DB8EFBA8926CB1751831DC17BF9 9D44041777B5744D4877B57F7EC8D9B1C667F20B6536316801524451089EA76B EFF2691B26676E5B01F86B5FA1FA302FE1529DE451EA1518F4C74EE8215E50AD 386D7E916B1D6C46210228B0CEBD8BBDD8BB90D766DBCC40E31279E7FF519A1C 1B393AD1FAD738BE72E47D40743622A3EAA68B28BB62C816B11903F854FE9ED1 717FB82AFCB6C5AB7EFA6B57B687B2928790F99FEBED5C6153C4EBE542474433 4BCC7DCE4285D3109594339D98E1627C43D1CA82D66F24C0F1AE779D5A84929B 644F23AB2490202E9153756D806A983F4BD669130D7E3E1E112B80EB1F9A2E61 0A57EEBF0D421234DDB6801DA9263E5B7AEF9055F6DD2CA80A4DCB018D1BE7EA 4944FFFDF62F83295CB02931F2AAA43C70D153AC573842833521F7092F390F67 01ACB0D063567FF45192F96D62D95CF756756E1CC4E94AB7D316A831CCC87173 2C0B7DCAB227F4FC95D8F3FA706431B5E0C3361882544F21D5797E65928D1954 64E011ED2FBDA05CEAF274A6BC5F5B0DEF498423C060B386F010FE87CB44587E CDC0D322CA0C0CC9C7E153A463DCBC231C16AA8FBA2D9B893AD442F954391BA4 3C580FB9A98335AB9E28394775D5113DCF63D5A2531E17BDF5554EAA1D4562D0 855779D1DBBF4D065FEA1BB746B2D211A03F7EEF809EC999A7D32A8732505E70 9810C8A4249F87F455A3BAF29A3AAA820E4374E29736A960AEDCF962CB14AD04 06D9AA7722A79EE2894C690F8895F274A9BA733F0C1B7A6AEC56FF1238EADD0C BFA6B7A283D0CD175DFB6153DB8C3B8590421AEF02F8A549C62A9494A06763B4 0D9E865736B91F9022F7047F58498670C533F98E961872339A298A0ABC7CD422 97F0C48DA54EA126B45538584B14599634C6B883602EC1093166A010A740A62A 528150DF94584717C23C1B346D078189320538CB31AF029DB8ACD77DE35921AD A02E3C69497575CD8BCF5B94CFCB84F91CBBFEC7D01E5F1CCA520CBFCA1B85C8 8F4567A6D9569BCDCD573DDE6E78FD88851DB77C61E07C0236F433C69D64AD68 9A31B2FFC998689264B5C8EFA7AB4B41287799DDFC544838A58458B9A39DAD9D 9B30B1E5344F95DEFE5B32D163DF5A671333D6491B5DE96E9E2DB5DC475FA62B 0833525DAC164392A442D0A4ACC95BCEC20994B4FE363C32C34828BE8DBD7F06 EBB3B9E79AED47AEB5C7291EF28BEAFC7457B85C077F6FD1BE613365BC191477 607D6847424C8A25FC6D1F1D5C1E7255309102E1821EFAF81E6AEB3B9DB9D2AB 60490EA74D6E251028BC9C7C8F593319A00D8C1D25D296EBD536352653770268 6F575ADA2CCC98D3C393B046BAE30C833A6BFD12251BB3B5DA36B63EB502A369 3C94C87B26BA40DADDE1162DC60FFF11DE6FF88E1ADE26300B6EAFA3B4E884CB FD5745951839A3ED75436B022326888EF1546263EDD8FF7CACC4D569 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMTT10 %!PS-AdobeFont-1.1: CMTT10 1.00B %%CreationDate: 1992 Apr 26 10:42:42 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.00B) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMTT10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle 0 def /isFixedPitch true def end readonly def /FontName /CMTT10 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 33 /exclam put dup 34 /quotedbl put dup 35 /numbersign put dup 36 /dollar put dup 37 /percent put dup 38 /ampersand put dup 39 /quoteright put dup 40 /parenleft put dup 41 /parenright put dup 42 /asterisk put dup 43 /plus put dup 44 /comma put dup 45 /hyphen put dup 46 /period put dup 47 /slash put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 55 /seven put dup 56 /eight put dup 57 /nine put dup 58 /colon put dup 59 /semicolon put dup 60 /less put dup 61 /equal put dup 62 /greater put dup 63 /question put dup 64 /at put dup 65 /A put dup 66 /B put dup 67 /C put dup 68 /D put dup 69 /E put dup 70 /F put dup 71 /G put dup 72 /H put dup 73 /I put dup 74 /J put dup 75 /K put dup 76 /L put dup 77 /M put dup 78 /N put dup 79 /O put dup 80 /P put dup 81 /Q put dup 82 /R put dup 83 /S put dup 84 /T put dup 85 /U put dup 86 /V put dup 87 /W put dup 88 /X put dup 89 /Y put dup 90 /Z put dup 91 /bracketleft put dup 92 /backslash put dup 93 /bracketright put dup 94 /asciicircum put dup 95 /underscore put dup 96 /quoteleft put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 102 /f put dup 103 /g put dup 104 /h put dup 105 /i put dup 106 /j put dup 107 /k put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 113 /q put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 118 /v put dup 119 /w put dup 120 /x put dup 121 /y put dup 122 /z put dup 123 /braceleft put dup 124 /bar put dup 125 /braceright put dup 126 /asciitilde put readonly def /FontBBox{-4 -235 731 800}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 2BDBF16FBC7512FAA308A093FE5F00F963068B8232429ED8B7CF6A3D879A2D19 38DD5C4467F9DD8C5D1A2000B3A6BF2F25629BAEC199AE8BD4BA6ED9BBF7DABF D0E153BAB1C17900D4FCE209622ACD19E7C74C2807D0397357ED07AB460D5204 EB3A45B7AC4D106B7303AD8348853032A745F417943F9B4FED652B835AA49727 A8B4117AFF1D4BCE831EB510B6851796D0BE6982B76620CB3CE0C22CACDD4593 F244C14EEC0E5A7C4AC42392F81C01BC4257FE12AF33F4BFEA9108FF11CF9714 4DD6EC70A2C4C1E4F328A1EB25E43525FB1E16C07E28CC359DF61F426B7D41EA 6A0C84DD63275395A503AAE908E1C82D389FD12A21E86999799E7F24A994472E A10EAE77096709BE0D11AAD24A30D96E15A51D720AFB3B10D2E0AC8DC1A1204B E8725E00D7E3A96F9978BC19377034D93D080C4391E579C34FF9FC2379CB119F 1E5BBEA91AE20F343C6420BE1E2BD0636B04FCCC0BEE0DC2D56D66F06DB22438 452822CBEAF03EE9EAA8398F276EC0D92A7FB978C17805DB2F4A7DFBA56FD6AF 8670EB364F01DE8FCAFBAF657D68C3A03112915736CEABAA8BA5C0AC25288369 5D49BD891FABEFE8699A0AE3ED85B48ACB22229E15623399C93DE7D935734ADA DA7A1462C111D44AD53EA35B57E5D0B5FC0B481820E43222DB8EFCD5D30E15F9 BA304FA879392EE0BCC0E1A61E74B3A1FC3A3D170218D7244580C7AA0DC65D19 741FA5FE6F8CBF60250ACC27454BBF0897CA4B909C83A56672958752ED4B5E79 E18660764F155E86F09EFA9F7685F2F5027EC85A775287B30E2069DE4E4D5712 E7D033481A53A2702BA7542C71062173039030CF28D8B9C63B5596A9B42B33E7 D922944A38713383D3648A4AF160A3B0C8F3379BA4372BE2E7EA49AABA75AEEE C5DDE1D8BF68483C3D21271280ABB91D54CC819680322EAB72E1250A760BC8DA 726405EFE420635B5B7F0B48752C06083E92BDE06401C42A2C528C8A60381227 CEBEF0C9440DC034DAD9C19FB27DB399BDAEE22053591D6538587C768C1B7B0B 7D1E222D2D8AF3A6473CC4C0D6C3E0DB49068CEB8C9BD1C5CD486A50DAA10BC7 7D6286142355E3F21DD254E27C00C442728A0BAEC9D3F17AE9CE320D365152E9 EB0D5E3874F2BCEDA98521D23FCFC30B4B69DAD2ADBE80E5964ED0ABEF6C73B6 DAD30E2C5061E3747FE536E1A5D190D028F2130AF608F5DDF9DDDF1E77DC8437 ECB3EC93B33505DF47884DDBD1DC6BBE4098DF04A29AF6FA3AE344600D0AAB53 B3820DD7ECB600A3B8001C51AF2CA7A39AE1485A087FD1752DF68F55B52B4DA7 48030F2AA7E570B3D56C4EAD367B9B73FBC0A7356253233006178B9A6BC19081 B815B5988AE76FE6FAFD7AC239072B1106A3F509381AAEE79B2F2154CAC4727B D199CDC8B4D05DF4BA006982512ABD7539E28D937B0F87FF79A3F84C29ECF943 A8DCB8BDF8EA9E7A0E7CD60BC2308C96B3E889C797D0FF28FF4847016B3DA141 E76FC6BE78A6EE9CE07E651FF86E720A1A1F075972D36E5C55162E3FE26BCE3A 814BFEB12D4C5FD24340CFFED499C7CA183E57EC4F12CFFBE3291D43F7270575 C6C3306F832EF182ADD0AA14C4D8669A17C09F632406AFA195F90C4DDC39779E EC0A77E590211592D6EE19563963225C06C2F13265EBB5A6CFB7C17D9E77650D 11958305727AF662AE73AD0E3ED5F7E7086C5A0C3548A8129575980B06C715AF DD55C8DF869BED0A7883491030B1A7E82C5EB04E5A7D952E716DD8F2EF6275EE 087614CFAB55FCE2BBECD7E8D9C90FD8359E929D5E0A416A23BD58158318B4FF 87B095EB63F7F052B3A77F136FD66EB2C52BD46CD7DB3091A4B78A607112B12C 4D171B2A00B78B0E1C44B0D90C20D9244281F5123DC1F6063F91E9E3E48DE78B C862D848BAD073A4FCB5EEC9FF54B5AB8E234CCC3C7439C62ABC4A13EF1B8897 ABBF21F900C564C9A305FC36FC7224932F766E6E72C2EBB55953DFE2AFC2E3FD 33A0C6F0FDFF086E9FD796E7242596AE85B877223532667625E371D2156E4C04 0D7FFCD3337B93DF066CB6FE1E13960719EB7CB409EE805C08ACD2C06303ED9C E34C898787A43C1B428B896551C6FEB50A831C6F8CE2073EFC662EC286CB7555 A3B42E58772E82FEE206948B8C439FEC5E4ECB9E11DC3A4CBC7611E30890E408 637A01A2118441B4F9467A98BB2A1B03BB2F5D8E3DB7D1D15C188D9E856088EC B762F07B1C06024F7EF53A2FBD60C0A1F4C0275D07164545250ECEEF8CB15B04 A2D8AC44DDE818C4E23DFF5B846F412C1D28C52DA1EC7F6B68D2E63E6586EA41 0B01DFF80C744F65C069047200AFBD969234842863A2CF78DD48BC0BA686C91F 3B1382C42DC044F539B7089E055DDDE9E76F7EC4A120B4D8D3E14FEAD686B0F5 3EB80AD386901D788C51B61A9C04955BE06E75B24FB77F501D9937DC244B7446 60E9453930286D8112EDA6EB6291C0BDB909AA3B3EA0578815A4CE3AFC9C699C 54C86466BA0F2FC9BF260DB773E29B2D4AF20562C31E83E45950A3A777E06C18 0F29343F91938126514FB2B4A81C98E9CC420F54C8CCD614FC7AA290B7D42FF0 429259B32D92836F4B71D517C130240B63949875D2423339FDEB14B1F1FEC58D 49BC8B826DFD0C2DF5E94A4B4088A7E4029EF2B97B970A53A43F0D280CCDB41F 8F9F3573F522404F634212E534EF3B2FA648D9BF218BAFA1135F6800478D711B 9E3FC435C0D12C845F0B3E77DDA804A75EA9BE82DCB9435BF16A2B94CF7684E6 748B2BB7C5EB08C5728DE734125E6E48B895FF3483E07558714F68F2FDC0F4F3 D195335C8216499611CF9355764266CFB43B77B30E90BA64BC8EB301B5E2D060 B1C053E8071EE600A76C8309801C7927F77D1FF4CBBDB83573EAF13DB5588412 23B6F8EF8C388136CA0BD33DA6043043163E34E1B647A549136C33DCF3A816B4 BFF8424CBC2C9EA6FBFFD26B7789815EE0D3576FB50A3D0D2101D4C43C0F67BF 16984BAF98F16F7652BD26329516CF3979539C902F5BB43BFA0B1DE623E26CA0 521BE8F6908E249743D1F7E62350986EF4385E7E617B1EC50F7408CB18A0352A 9CF70E0FC30958BD6335211756B872801AA86C2F43801FDD42BE49F16DD74849 40E5F5FE77FF2948CBCC494E3D9259938F26C916EF34919924CEBEA9315B603C 5D618FEA13211BD46B019852FE26E305A4EF2362536C9FEA7475769262D3C2EB E4E5C2334FC9E57F57BA7CFB29AD573D3FC5CB5781419899DED8B473385280A0 B375271DC9550455D9AFE5171CA247F90902D62F65F84D05B5F65B8BC80376EF A0DA23DEE61AEE96577629DA3835F2D50C36D181D714E5CEA92198F4EDBC4A3F 17995EBCA8A6B3C86EFF6EBEA1991D3A3BC2EF33833103F462CDA92BCA15974C 49B3F1E7D585E056666A2CB937B7B49572A12E9953438F334B727200C9D7A86F F995C454EFA2D0A5B6043E85A5D282F6C6CEBF5781A59AC4DEA90A6E4F2BCC54 B77584E08B6FB01CD73D5BAE1AFB220EF723C9F99F0F8ED7EA821FF9BFC9D57B 1F84B91A3CDE5B158D3DB7D1369D51CD9A2822D4CCF0DB935B56CF3A52866394 0899E7A965B08BB808186D885D12335BDF0095C476462297D3AC3BE208B1CA01 54CF223348B87BF3472AA2966C208D7BCC2AA07BE712AB448824D7DE9968C6F5 7B6C957577BEBF7EDCFC01EE0D276501830548E6604D50E4C534CE727BADF7D3 BBEC9CE7E326DCEFF2B5908BCF60495C7CD9E47448434353363A82096FA9E1F2 1F8C780C4917DE4EC79CF95A42CD2D15E3D51BBDB9CD624F9C358390748A9A95 5AB4DFEB92EFEF7FB8907751FA44DA024FA91C6C064B5E61069B2796590202F1 2DFF657471BADB7A62F2ABCB770815750378DDF973CD4E11EFC3D19C27C02171 4AD74C3CC0B96793A7E0EB9A0AA40C7A6D426100FF3FECF3E3CB60ADA80DCDCE 870F74D04ED5B167D965F8AD2677298548FBD803C716488925CCBC9A3C515D3D 86C03CDC708D2F95F403008963361C8E7EE7C5C62C15DBE6B22C2CDB249C4445 21C8AD0C014BBE4B28827A5C84D714327904518E36EFBF4356DE0750B52035E9 2E06426EA0395C4852AD2ED3129F4D43E3BB75B546F092C1E7CDFCFEC2F00331 D9D0BBA5D76287C4CA7088332D5BCCBDBFD20B7A07DC6619A4AD3894C699B01B 045D803FC5E36061648DD13B6BCD95844E171F4380CA89F7A7F948715630A623 DD5E011B419FAAB28B814DAFBD3DA2EBC7B6CA635D62145E87679FC56843AC49 FF421EFC70F30062D749120D1C492EF1070EAA096E283CECD8411964DEA10390 147718F191A0A786C3A9862EDEE74767762BCB27D5621A5562EE1D22BE784FB4 0BEACE3F8A806ED5257A038C8DD59D3D52CDB4EBC501C13CC9DC9BD89A51CF86 B6C3F769C470912FFDA75C99C2EF55D78874558397C923C330CCAC3C149BA314 C6CBCA464B176721E9C04D0C08ADA8BDEFEA62E3231FCA6A646F837115D0F479 E51C7E509BB81045FE2F3DCD4A761E956BAF0561BCE5A0D20C0F1C45F40306B5 B6A834974281675F2A33F258B6BF7F7AB717FB72A96C0D50DA6B6E4D3EDF9416 6640E77C36BC882A09024789FA969E730CAC7948640EC203B610D8B02B0E8897 6E0395D5C45E7D414331145412115E3DDD7D137716192A10F8D1F6E134210034 0AC5572B33F6FD9D2B95D7D62D12919B23F7CBF114A5E1FF5C3C310CB947B914 E7729E00E22E2F5E4614CE226310306FEFA46DC9ACD671478C026A15FD6668D3 3562902F13842676E2A15F813364FBF3751A6BCA132596BB02DC0BCB18463F0F 28C1A0E1DD23BBAB471ED0A91788353A27BDB2D3DF7F547A2E401DD536417F74 5CF1285AACD4D96642200201BAB9EB201272A1D102FA7B4C293787CA1DB59847 482B209F980BA3107F7538C5FA1CDC5DB36C5F0A7917FB0BF90F185CFDEDCDA7 3B1D584F43CE6CFC46EEA3907B6E81BABC903DA628077D83A1F18C291729A92F 77607547D61D0CE06750F927EA4F37AA39C1FFA07EDABD3147228D161F0D0FDA 771EF1F476174134A27076EF9AE92D3F6DA91C9568C0E27BB954E27CA09345FD 2AFB9150ADB7AEE906AEE84C5375F25C2210D3F5A3C57298BE1B6AE3CD38DEB2 97904795D70A9F2082DAA0C6071AB9E8FF71508AC77052A242DF4D01C9139805 C2F5BDEFD7BFA42D3B3335332B37983D213B6F7DDEA6217186A93B911DCC0FE6 42957686973CA3E07AD6EA4895AAAD5D5CD878AD776FB9975EDC7EE3934EB131 37EE8F063BC1EBC11D807BEE136A31A70EF2A46B36D99B98B8B1B933F032FB54 B9EAFB5CFED5D813488D6A28250605034BBF2BEF55108CA0D6FF94BCB1650F91 99071E1A1B3B2F1E8E7C89A5E4DA1F77DBF6AA289D331C35C2C2BFDE4A391C6E FB679CA42BCB2AF018303A3F55EBD657AAD46815B45DD067823B4BC3FE3B4245 C9940627467C5F9AE0EAE53CB7CC118984272BCC5E1B8548494E812676FBCA78 A70C417C270EB6E435A6A75CAB4AE742B1194E3F9811A7B581D9C552A3EE5B1B 98E997DE7F74B3D85B46825B620B19357E4A7D82AE97C3B85609335B1B41A532 FB2F53C79A4064C88C84FCE693FA6EDB086732B6F76D31F8A6FF27DD850DD1CE B9C29258680CE73A371B3613F17A3533C5EF5D4E3F833E563E976FD58B381643 F097AD8D3BBD1E4F0C22A79F464FB1168E6B12E503DEE9D1D563B6F9B5A8D6DB D1FD6BF4A90DA086275F7F7AB784F8F945569601AE0499EFCBC5F5585A759D09 6829A9649317B8C53F66C083170EAD52494006623FFED560D382CE663A1B4BC0 D68B544A2D3F4AF0C1A6E50A4603CD433329F379B960A2E6822A381D91DADA65 E5D973E67820C6AFDFB917126A4C4C7CCE0C00EA9762059E3BA7C3BA56F739CA 2F89F58A2F058A78FA9F0F040A8B04B77F300343CEFEBF9357243118D9B62B83 2EC312A4AEBD8BEEDE4DBF3CBA2F574BF9AD66B43C19615961A00D70ECE67C17 6C93C248AAB0D3F9580ABDC833D52A5BE4A5C7F06C12E934BCB99C8D484A0CB3 BC75FE276F26C6AC861A17CCE8EAE60AD5E4573D4DC2FCE59477702AEA956B2A 0DB471C240961BF1402F6ADC61C3D7B72C78145B5FEB9853485C862FC428BE26 F2FCA109EC1D6F77284C5ABA95359FDB4507D921934DAF4EDE1A1071F7157982 3A9799E17F5377F27700EE7CB253ADB2371B228647FD11DC38F4FCD9D75ACC96 D6B5508773BF71AD6B9D49829D6872CE8271A17C6FC89994159850529D5A8A32 206A8BD5E688D5AEEDBE8E0195DFDD5ED07D11DC54131B7E22958959CD35E529 F9DB957C31AEA4F25811C7E0B9ADCBFCD7AE1BB84D65C7EB2BE322E245F50CE9 D611E6D52493244E89003784149E23DCE1624930D53B937405064775D2CF8103 66D2FE6F360D5AFF017C7CD773F0303CA4F8C9FD08B91E414546CECECC770884 87FA3D4EDA2E7D8474D5C30EBF966C9F40F4707E939C22779BC757DB50E9BACA 80E0AD329BABE0AABBCD5C1C59E80CF55E63F84F49FB24D5F8F953D028568083 015973AD8921C03794814AF609FEE8A5466BB982A15644C00BEDD08D351F661A AB6DE4FD2715935A73399ED21B074120B214C8E6BBDD346CE84E704A8DF4EB4A 73C5ACF8E106D56287BF82A4C04C8AD092B9643CC1512154D04AA5213EC06B2E 6B8A5452428EF353C92B18855E9C7BE2BFE82B568AA0A4B620EAE77EA0D60755 E78C6FF41E2503A3868195127619E97805A628A0348CC7C92C3EBE700EF008A5 86B6B5736A275BEB0431FD754D9866829C9B8218552737AE357B6DEB6DE5B17D 5D86DFE33C9A4C93CAE5DC1777EA1DD2D810FC772C8855B4055A1B520BB0EF02 9B1C32FFFEA106BDE7EEFD7C05FEBEA882C2FE39993EA2BB7CB9DDF009C08642 B3B12A2752F8F6BDFDFDF83B0F8648C309248AC9274C823CEC96A0766C58488B EF98089D39CFFC48DB5076BC1DF598C450E76E32EAC21E2A63ED2F4CD9BFD34A 23731B4BCE26D3500339CE43CCA5FB9FD2CE1BF78DE258A270490158921A8430 BA9F37EA3BAE30895A57D8BE8A3DEA3DA9E35E3AFB9E650815E81F9252427FBD 4B27B5C81F4F6D98CC7B7E289231FDEA58E629C4A414C5635B69B7ED30BD3583 2C0CE0A350FA686F91C11AC4EF37F651FF61BB9D087E42A7ECABB2073D930C03 E206ADC510961C03634984D380EE3604635695DB7B240CC9D60E31E684867FB0 C7AF5D477F96C24D377970A9B0431780F0EADC1FCF162245EEBB2C99946C28D8 E85A85CE650089EDDE2C11C224B3BBC65835D33D25DCDE8C9ECF38FC58D24972 EB715C666E5598E6F6ED4268BBAC9F99D725B95F81B3A93EDEAEA3B33EC2025B C944E72BDEBEB532A01D263064123E1514EA9778E34DAD260C3EFB820E9B7B2C 005FB6B60E44782CBB9AAAD0D84E2A7FB9B9A003B2E9C4BE6528537B909FA590 F2AE7CA038C6912DD59455C76BFA330BD5801BB94B2869F9F4011DC70BD31FEC A18F3944CEE997E9D984425D95C28DD02D8E0E0DED0D1FAF045C6BA250868E80 730180003EEE66D87118E677DB28B9F54AEF115FC1F1BDE48DC42BADB2F70A05 0112E3E69AE8F24E90D2C020131BCB703D4BE761B59237786AA2565B1FBE6F13 66F74844A3B2BD29F9BC483BF9931838BD701F8FE96B0751A3C2E93E326FF14A 037BED6C2D42D93E06082DEF985E39557D9A0A607D5DA570E084CE011B3F96B6 2F3633344FB5DEF35A48F468C019A9A881C036F095A4516AF9289085217C2556 62808AEB100B2D3D049629C688392CC8A62BBC7494881B5F64F71F6A280F86DC 288C82510A59277BBC18751679448EFDDB168F3BD63947E6C96897DDFF56A60E 747AF59AE10C996931ED47E0567A0FB1EB9C2A7F062E04CB75174E05D9571D1C FA2EFBA213E13CA73D9FF1CC4661E04E4D1267CF8E792F6AC270F03C38B7DDFB 9155F17C13DC7EFBEDD541AA9FD866F3214FB78FC78DFD68A4B8819144D9A28C DA70DF8489B06196672EAAA63953DC4987FE1BC025CFC38CAA8DD29A19E0B007 F99DF8D4D56FF048A53A5A4919256A3918ED9C87A681B168120E65E24EBA3060 EBB79FE24DBFCA590B47A732B5A84F68392E5CCD7F0AAF8AE46E8B2F7B9B629D 984BE10229CE058AEBF5A5625F3EDAFC37D75C087BBA244FCDA5C6CA4D02EA1F 3F64D397F84FE2AC9ED7D8F03BB56BB25DAFE7E691DC2F7F42B82B79EDA8111F B98941BF10B58EAF2D86FECA8239774A6AE2AF22F8A4103D0CAA22ED11E639EA 899DC81867C0E3C42F6FEB53370D06AF2975843410C8114F5C1057D53F078FB5 96E572702A18C71E09DD607BD6CCCB2CE9D3C84E9D626CE715805C0697204A81 DBB43CD0B952BCD9EADA1FE80EE1E24B1C328FE08783FE66C8A1F615EAF8CFAA DD5A57695ED5BF8866603CFCB4EDF22FB010CE429278CCCD13B39C7AF2135FE1 DEFED11CD2275ED4C51DAE380DF3CBD87A5502AB213D816FF6ADF4BDFC53F18B 1BA97CCC685B11BB417FEFB94140FCE2733949AC3E2E1D25BEB6E6D2E5D83144 463283C90090E110280FC2C220DA957E4F74568CADA115E02BA45417C09CC34B EE51F2452A50D20A5B8D532C283E46E6AFBBA38DECEB61836673F76E8B20FC0E 238CE894EA5EA7C7D0AD342F87831DBDB01586AF952CA32796A6276B2AFE3269 0A26B0D6473A5FBB2A7FDD47EB4CB0AECFE2EB581146A37B403EDF0E53C2F969 450DD44BB534B0D1F8161CB2B04FBD5FB691FFBFF6AEA8664FD8F776A2C328A7 30E745E7F8D46289C8CB4FCDAF7A42371604E47AA073B7200173E1D0075A7895 747C48506669C5FB8EA2EDAC1BA526BF2A3629C7457CECEC6D8F0296C2107BB4 AB5E3895B2DA8C0B2DD14E756EAE39CC14480AC37EF83226903389C6AE3A4109 C93577F97BC888773C24DD888767B11C9628204AA55DFF463AE17936E6BCDD15 F93C818EB1DF9F2664B1BC06BEEFD54A913448E69BDCBC969B7653B868D54B81 8934B0E26F35BA405917D207E2C02266F89261C2566261D204DF7BE4E4FD30F8 E5914FC6956A02F641A478DCF80C02A2B42BA2A326D2202673C65647475460EC 99999A568C1B4C259E3B7A16B741004FF2901AF4F186D02F44B0C6D3F53A6F5F B4066C137C8687ACDD32F7062884391D6861FF0543A377F06B4F85490F096A1C 6213247A6F0C7DFD5EF4940ACB1562927FC7EC5FFCB07A393CBF6FC21C94BF73 453B75ABAD9FBEDC164EBAA111108CCA28F219C0003C488A54BB9B2BF0858419 538058DEBA6C22CB17B7786C34D3F569B42D7065ED309A5AE6F8D457B9655ABC BF4AB6BA6BA1EB95AFE3CD45B37BCAAD8A715629142D9D1138CD3314CF2E777D BC790A63DD1B724741F23B4D3B39C2D3BED0023BD240C19E129B6CF5741A6ACC D6C0310DF5A560D7CA26AB6AF212131073CDA02C770A275F7DDED8C52D673019 AC4A4D4F036F94FBAA1448A0BE735C2CA1193B0B3795B3B4AB693C5B97EE0DE0 CA05AD896B47D71CE613090AB4B0F5FAFFAC48A7F52EC247ACC0CCB10A9DF052 6D19E742A514CCFD71ED7EC2C7D86118990C93748459293FD21BFBBA03C57C59 18572EAED78F8E0A39A03A7C8C1ACE30AB791FB6C477A4B74F21DBEC1DE8F611 B1C849F0A01F93C4E1D76F5E0AF2537624C2A263EE163734F71701E05D77C1B6 AD220682785BDE886373582908664529C9D081667C7354AB745600E3A610F672 53AF7D1DFBF502594B2B50194406F831251EFE156C063B458BD4F42E7DA02833 23CF0005BE43376DECD1A306F75261D6248A6DEDF5F56AFDC8CD410BE0213C4C BB9304DD363D0D60AB2B2D645A8ADAFAC099847344A7C010CD16E61236DBC4F6 D9EA4FB7563A01E3F799123FAB7977699D1134E49A5E079A69D8E9296A062F30 2F163064A215845D0D65B815FE0082852CABE0481120CFAA3B687B32EECA8F62 CC327D1D7BD071F9945AB8B9539AE8E8C5A717FDA594DEFE8511BBBAAD08D7A2 4072A4E4ECA0F3EA8FAB76883439ACB4727A36DF72DE574418B13CAEB099E9FB 466DED499B8E01942E2D6F72035222BC90E6BBE16ED4FB2DBEFC64CD371A6FE5 97D70A6E6319DAF2AF90064B7A240A6B11493984E63B84DD3D59B4243DE9160F D2657C215AADB68343D6ADA3268E20CD294301ED7C46F137DC50B152A2718BBF 8EBF5880626E9DCA1DFABF1AF6828E8D5AA9150BDAF9701F288F864D8C91E976 9E9BE865B6DEB2796C6C3FFA603A947B9F43790A98058936B3109610B502B2C2 320E75318B535D194D764C0AC7A322B5DD0D4520F96036908CBB808212A7B27E CE14671E77725B8EC619C68EB5657863D3663208D21318F7F9415B93B1E72BB7 83612E137E85645CC4A1327859818781CB1DF455AD4BFC77E49A90F893179F5D ECF976993082E64B63ED0533008AE77515453DA9B07AB2F1F0B1CE816E6E1D4E D0D7A445F75F126538FE849BE9A9CA6BF221DDF53BD7E9A45017D919A46B9287 1D1D98703C6622F41A997BCE4F77456A23418E6BB7C0F9FA957FE88A449DBD23 D713F39CFB2D4A639AB99409DC6DDA631A53CF8F5F617159E03BCBC89C688A22 971129FD158E8AD10D39AD3D2E6A8A469BB27AB8F929B28A3459928FBBD0C33C 4DE82E1E1DBC8DDB977706FC4B5C14087456D9634A65BF0C97D5C49593350CFD 826633734D9B96E850FBD5F3F319ABBA61397724E8D21B14FE56B6367ECEBBE8 2D7D0CCE1C2FBBE5817C3D60CF93CAEDF9886632B27DA37F7C1A0342911D160B E520A5D20B4013983021365E2BA6792766B0541F3262A83C4E863A94FAE921E0 57EB7E291DBE76944B7CF7F0D7363681586B405EEDD879BB508FA7E4203C8854 44027B509D69E1CAF1BAA5C1A239999E190C7B91D315AA81B289FE88E5C43D0B 251FAB17BBF7D49A71F75364C6DCECAC2C22ABD8D215AFD535C9EFD9629F178A A75E11332FF6B05A4B1569306E3F3616EE35D8338F65B6601D3535B2C6EF7EAC C71EF79C4EE2A862A75531E4131866D6836F7569B1659A734F35C78FDA7F3DEF 39397290CF54AA9C263E7AEF736798672CFD722612716938391A1053B727C7B1 BEA9DA04AD5B47C42E7B8A53F98AF379F3353F0FD438D215B517A69DB1CA5F27 B567D55144197A840F0BCF876AF832CF3F620A1E2EB286E45794ACF216062F88 D70270FA4453AE510543FB2E62CAB84A3BD7E2F5881B20B5BFE7FAC1125F075A 84070D639DDF28A73E73478FD27FFDDFC0246B3AAE90143AAA71DEC5E440C660 857432CAB7E1E0DE1F6ECBA47F0E0448E21EA69126434DE576DD22996B9C4671 1B5B07B923B59A56A39F22396B2BE68B14283BC384F7EC76C90DC17BF57AE82E AB5BC5D2F39C916F68167A22824BBDAEF18501224005E4E63D8A357F85CDAC2E 1F7FA28FC65DC65FF10059A658F64A06E98152D580385B2DAA906ADC3840245C 7AAA12C0945F8E14BDD097A4BA5F2BE5F6C1704C256FDE77DE6671FC25B05400 61EB206F67B7C752E406CE88205485A27E626161E3FFEE0153BCA76E4F474E22 57DECDFB9294B874FC26D354787AE7D53389C77AFDF711FA5D7552FE3FCFA9B7 DAC7564C749913F4020389E4C7F4DC4FE13ED85AC8F57D0477D752BE1722B02E E2B54C21DA7A976EAF928B142D2E0A5591DCF14420BABDC027E06CE3CE027336 C20703A85CD2D290AD1DC4D347A05FE5E3BB87889B74B7E0CC251A58B2F999B2 F04EA13EF3C6CE11D6FFDE47712BE6C84428E7D95E26DE1BC6142876868B6929 A8F88012693A34E2740818DE3FA7458EE6160364795A3DF3CE46A3BAEDB5E361 B1BF48DCC0B9B9045F65A4E9D61BDB537FD76AB51C39CC123DDB09534FB63C1E A5F85BA1DF0EC2736D029EBBFA7D935A20B087832EE66475FC2AF6E938363F3F 708949FCCCD04CB56E8A00628106F12D7D6B31D08D8A047C5B9E39F4C8F1A7E9 8A06D46ACF7ABE91EF88322FC5C8346310953F9C61CAAB6B8AF4C489447D6A08 125F9E06EA30D6B07DB76E305626581D69929EA0B06E104674747A436637D015 34A880E798BB653C9AE9E8BD619FFA875FDE8F488CD798DCDB0C63532D0D1A7C C866EB30FAE071B43C02EE5C01198E81CADFF0686839C2D44FED8257A2BE9E88 32A38671E067BE2A49D3BC5C0E7893E12A04355315FB0B46EB033DFB8C101EDD 84749263790C308966FE76F6789F21CBDF83A280C6D6FE8BDB669E2F30795E46 C6EDD896F762C9F3E647BB51E43A7BB4A949F51D5599C25DB872F75D72E9BBA1 616BEA9E026069F0262868FAAA16B44DFD016F80A6DE44A4A69B5AA6AB8C0424 C2932BB816DF4F7F74145AE2A0CCEBB71DDF61B2208823E42D3AEB663E3206F2 340F7369C6645397100FE513FDBA478C5DE5C9A0839B5DD2430725529939B414 89BA91759A62625E40B92E834A9EFB3C68005876010F9CAA8BABEEDB06B6A554 21609C50731E2435361AB8F53BF71B878591F8E0BDECC464736D96271F8872AE ADBE8BE4A26B8145480F7EA4AFBA97EA46F6EFE3A52A20711ACF947EF3F8B580 500DC99468972BB657E57245D4FC01F8665C939D385BEC9126193E1DB54E1078 042F0B0984E812A44726C4B369EE9CE54083A417BC8ABB50A6F2B185E3B8BCBD 53A75936812779305A859E533617E5192DA6C3531189CD57DB856B29807F383B 530DE0218926F7A6FFAA401D3864931FDA344BDA891E32359EC567739B25CEC1 A4C8169F251ADF4594215549F7F225DD1F20F1269CEBFC88CBA7CFF4B7214B3A C111FE9B511A8703810E222406D86F41996815618661ABB2C69F663AB97797B3 81D7BA0172D90246E5B076662ADAA4D2BC8FA1BDA20F13F9CB5A70465667B32F EE2A1FE5DBB8BF41ADA4B7D3970DCE1972508929AB078E35391BD8D8C0FA2FC9 A0C63973A0236E7582D4EF32D3213BEC05DF0ABF760767CC5020B609E8225CAD E64A95D1E7D032833DD90ACCE8B5E40A3D57D6D5F0B36617644E83AD6BB70DF0 DCD7D9410B7F47763F7FE5533806A1DE39BE6241C07B2BEBCE630CF7550B1595 81EE53E4C92D15FE69B8591DDA933337F7F789B3BBDCC5526B10BB959E76225B 2569292E55B90B4465A44624AA45A4327E23650D4C9A941E8D86A2D619CDA196 EEA705015C6EA8330D3C04F293512955F38C4170C12D709C55A2832C58930C13 D9B37FB7D4C8B0FDCAB5BA07FFBFCD805FA6089DC09D2CEBF1DC3C894CFD93C9 9BC945C25591C38596062BCF218F28DE9B4EE244182FDA170A07A7A6CFFFDD8F B08F7AD8857066E582F48C596F3C3B3AF67294D1C45C5E5E6C2B7BF67C8AE472 79835988AAB90BFF38E234EB1F49E67200F77BA40CFE10463DF43FEF5FB13F1A 7CBEDA0B168FB8DF78C793CE54D309AD9212A1EB5883C5FF17CB637390D2DBD6 07F05E04CE60D3211C1A32304D1DF076EFEAEE3ABA07DB78D9C13F58FB5B3DF8 1A92DBEDB9EA5C55E3752855AC1225A2345D3B9E37F4068272AA3E465C74D122 782864FEC675506304AFE1EBF79D0972A652D452FA8F70F9C6BB5F7B521E534B 1EC7CC493DE8D55C2F0007B2204D1E59383FD1380519DC4E699BF7AF8D81DA1F 8B0E9626F17C2F620117230E9BF7C4A58F42F8CC037182D73D7DD884A04E0C38 C9B7B80589278B76C2C858C9735A5816A0CEA72F099E038895151004E1DC8CBC B8D53BDA668D8F985BF4FECA6E8646042DBEAEF1AD6579B60FACA93175F3DA04 40F034036E621E1C7F31A376B3765B285B7E4CA83CB8CC1014658C2004D777E2 2D08F4B307A0E63DBB23B21D2A49101BB7CEACD2B40A686DD7C66F4FBC5B6163 24F3A4F48706C45D54FE0056B5C4E748FF43EE41D34563867E41D8160500122A 2115AB57213917F5B1BEFFDA531DEE363AE61D480B05F7F2F440B851B6CE6265 2FFA0A0FCDACA7C1FB9948A63967B3E4E106A7D2194844E368623FA61D327321 C0949D6495FD37433D8157365435FC316539671407676D347F7841CAF39E315D 00B2F5878D64D0BD920D3E418CBEBE3EF5717D509F0AD20C2B9BF8B481F8D7ED B1ABF3595255DBF1DA8AE4FEB4EF00FCA5E681AC5C80F71ED707CE5B6D0DD8B3 800B87042E1CA1C3FE1AC461FB47E7A8AF5977DEDEBD2B1FAE57780342CAD7B6 205770B6D14E8C4387DF27056D3E3AD60FE0811A1F9D2D7DFB6D1D52CA8F8E6C 3EDF8F78AE862AF1D75546E4C0C624CC57A18FD61968CF742FEA4B45C758CD53 78DA3A32960328BD4079C7280F19AC3FB66D24DA8C9235AE7ECEBA537F09A958 F5FD63C4E3A0C49F44F8CB0A828D2A7DE24949138C7206354D6BE8CDB99BA5D7 C60CB286AE290268214AC0A0C3F775BC92DD5326A100CF4842EDC00AEC236CDC E4F8F8448596B7E59BCB5EFFCB7D8C90837FA5BA690B9FB4D4F24BE0EF5EE864 717394793E045BA233A7B146AFECA0664577795ECACF06E811E1A0147A38A3B9 2941416AFB19B4C82A73921AA970B08D68818AB2F159E527EB7C48B64C43AA2D D5DD0DAD15AD0161667D273BFD59BA13D7AFD709F43DA9E1E5B3B5CCFE7EB38F 08DDDD02CC0CA2A60CEDB070D54AFD8F8EEF0B460E839A2904A8DE16CE73F632 3CBA9A65DDC7DFF06E5FD2B074A6312D01F8D75491B87EDBDAF045FD2093AE79 0C2CDF2CD7677D4639E412812A7E95224C3995631589DCFB5363C82E7D1F66D8 3224A7172E5F0DBB88275EA86428DF0D223AD4079C9D233CCF7C83D3D488EA8E 0D1A5710DB03D00B4729E51803322DB1C649D2C0FD6D3ECDD66DF8EF0FA80B1C C447EBBAFFFE5BCA6262F252CAA42FDB90837425645E57637A4FE5DE5CDF423F 85E41136A2DB6EEF9FF48965C73E07A1FA4C9C0DB88E5FDD963E55528C8986E1 030CD62EF13B3DCD4936080F90EDD2CFBBC294E666E0D78D448CA04113EFF2D9 C467D9E7616C426F93C1AA8C3D31D26B2F14C4B1ED42390E613B4881D137F79C 07A1E8874FB91F8C3F561945FD8903D4BE99F18212E8DB95BE4220E57876DA3F 5D502316602D0CD1B1121FC930F08BCAC9D6E5B9ADF80B3C1CA1215756F11ECC 7D2DA3D97ED094920C38CC4A68D7BFB6F75E8431A3840D5845CA8752F14AAF8D F5A80ACF8E703D88EDCBE251C10238BBAAA923DC490049E76DACCD2FD320C349 7FF97E3E2A9EC49C5EBA951F0EEA06D48727CCEC45DFE86D667725454B700F97 06B1A6521B25A0B5034BB64EFD4C7AD11E83F24BF7ED607789A1AE805881E4FA A5A8610DB42BC7341F81D63CE70A7E37715449BD850A4CA83A0C0EB1A33A29D3 82630F9F62CAA98AF0AEAE3E0F450B925E24A82907A642366EF798CC064FF67A D3BC3D3CF3BD23641A91F2DB09680BBED2586A8869FC8015134901F7F4684B70 73E4D6A466F013F76619BE61A4B9F66BF167EA7FF7DCCFDBDDE96DE78EBBC0C4 A4DAC9DE8D709078F4C134FC1BBF53315977ED4C9C41CC4A02026E4C3443653F 39B23880391A2320170337F211CD83794118E5A014922CFBD8482D88F5622059 3DE77CCE12C636241FAE4F5B91EFEBEFF1EA36C91465BB15A49EE3202451B862 BECD7D819A56F7D7E46F981BD96FF1FC2587943D90F4B0F7B4C6ED4B76D6050B 01C551C265BCFADE1E2D72A0FD4C8AE9559C7F2723769B1E3254E33B7725321A 1E57D149D9A3091EC5714180DD68B89D7BE2AEFEADCA9585069CEF9D5FBC51F6 B526E00E168E72F5CC9A70349DE30D46C50D30536821A4D988488C72AA9A8E87 52DF5FD0ACDBC377A37AB3140D89EE5803A70886696176D2CB7D226443866046 174AF7D525A28D851AE35BC42A2FC7EE4777EFD0E1650F7BCBEF9DF1AB64870B CA1E15C7D67B3FC527B86723054D6C1EF1A869A9FCD5244D0BCE4182BAFF60BA C7DC0ABB04C31C92741C14627D5ABE692403C6624B6CA64544E905B11C6D8FD7 1F28055E4BAA5CB25996FE88F502742F42E11D087F61117F9730652F493329A2 453D9508DE874DD92BE4185F6A7BF99E562EB614DF01385B86F6F271F355FF1E ED5A84D534446E834B5435D483DC20A729E81CEB96EDAEE53D2E431BD905046D 712133BB30F33DAF2FC62BDB3A171BAC8E33297C08360CF255050DDAD58DC96D 280AEE9F9B66D2D8806E2CD32F8A08434FE91B7451AC5948A1DAAFD2D28CCA24 8184E20D0F00EA9F2C663E7C4ECA2F9AF6EEA56F282AF32DBD960D40D4CF055F F33D5C25602C2D6040BDAFBED1926120464F183124F48D34BB54A06A6724DCBD DB2CD715999302DA068272B4E5742DD8D017E604C4114B1DB529A841F633160F CFE80EA9B3B52B940AC0F685DA509ECA4B420A996E8488933EAA721B562450B6 554302451C9AD6A56A84B85EAC18F03535099C8363599D4397454E19C0AB2A34 9EE7A3C94165E396B9EFB97067315FC4762F2BB4EFD7FC635FFF0593528D9079 69A5556D34927059A46525E6445A881CFF4B5B790ECF680068973A47EB6849A0 52B9F18FB039050940EA4F9B51A3B9A099F33147569AE9254322ED47A6C7612C 46EA207F0A0FCB785E1DAEB571BB99C97D296CA1DE3838CAAD06A98FF8146056 ED014E14180D505B17AFAE35F58696C16D8C46F13290F1600075A363489C9D63 6CB4DB7FDCCF49E15B6825CBC4E04A2D6BA136289D198E2C851D794A9A3E8E45 7790862DDC9EC0D12DF50176A194F39C7C13C88150D2DD1208F386BBA3B0FC1A 77F94819F12D78D5C59139A1DE0F2DFB3A7FFEC4FC38067455003968A57F73B3 6C15268401F75B5C843D46EC956AA677A8DB075B61E547DEC35A63124769324D BD64C1B1D38777BE93F60BF4D92C85CB8C9ED2C8A77EEE0A4EBFF3A44F237305 EC57E50E3120CFB0DF8D573A96A740E1260A26C3174AD869CF2EEB226ECD812C 480D45502C3A4BE2B4EF9A8EAC7DB836F0C843971067F690B653D9C722655066 D113AAFB04FBDC5BCEE0FF67A38C1808943882E4CE60A6969939BEFE16C09B59 CE50B529C3BE6377368C3E827E9441D96BB174BAAC8B518671E3A9B95D4F1722 A26F4FFF48348CEDACCC4FD98F71147D0B760B320705C1C13C9815E2CE82C5F9 D6CF04C81F1BCB9F12A188F9828498C220C6DF1738CA9F236B6D6A01D747BB6D F322F38D0D60A2E07E0BF1E259214C3F3EF0A72074C261ED09B05DB3915D0835 B2BB52B6ECCB04E712B6BFE1A0DA7437DDD8C4C05CA45B1D5CA17EA99BCE6428 7E635AAB8F2BA639F28C52CD0800BC348990D0E3832B0303A272D6C99D8A6044 C5093A422D646898EF85ADB647544B2CE33DB5DC66717506CC90ACB01CF58830 D50F4CF7BACAFA2311819C3F50A9F91249C624EEE17EF5752C6AF77D6B852703 81F95A42593045A69334D6DC1280384CDFA0D8088D97332FDB06A02E5DE9F962 1B41C68A0139BC5F03FF841D8E93FAD2DC08E645F476034919C218693989244F DBAFFDB4FC0436DA9D43C8A2D55CF8DDB0E7ACDF9D564BCBE38073E74D65C8AB 0E89D87275D680F0FBC2389D1AABA196474E26BB4BA01527A72E554C29EDD3FE 7B17BEF3AB22F2C7C0EFA69C708C36CDDA24C38A845EBA9E9A3E6052B54C188D 2743EF1487B6DF0E6E622A697BBE91D5627DB3F32A57C0AC98368FE53BD09844 A326B096D01FA3547FAF440D44E079EC0EFC2A482B05052B2D57DA79B8B811E6 DD9D0E46E838F1402F32EC5FB127DF771049F7B79BCF62C14E3FB4D6D7BBDB80 975272E6DEE0109857F51D57E304B74DE4AE99ECFCD0A40E57C5E51283D8F270 291665EE714A6596DBBB5285FDDC4B6328BA6745998EAEF40EE717C63AEF8A59 E87D8E3AC8161B6638FB5D0963F8795587949FFD6F58C5FD18741BA3483B7FD3 FC31F188B096FEC566BA23ABC2B34B79DC293909C9E8393AC9A26E6538672756 3FE2EEF3E04ABA6D344F2DF359AE718C7D0EB5CDA5AB3D09C62C990BD5BD7E73 3F1F8AF93ED0FF3222D7411CB9AD3C3AE9EDA04DD1AFD21A4653AE6A890E6C07 1607F1668E4B62730DA65DF88C3C63FD7816C32F26D21A87522C2097BB925D92 CBB694A7F77E91F3FAB14D0A493384DF902DE5D5F4FEAB5F5BDF567878AC8B4F 98FBFE8FD16D07A58E2211B87983D40D5CE6349A207FF195B7F09B914CB6D688 B103A5206380A90713D3C872EF8C026D2E302BEA473BAB705DE58D802A47C249 9C40EE6F20398E591A3878D4A9DE9F6EC097521DDB694503AA8FE3BBCF24A5FB 3DD6CCF1247B5D9724508C63A3E107DE56F0802CB083399BFC3A9DA62E7575E2 58AA589E85ABFF222717335997260A7F56965DE4DE551885BA8A1DAA5C97AC34 ECDB36FEBE3D8428A4681871FEF7CBF2B5DCFE747550D296B419140C39EB3AD9 D65B6146705DC3FEF0131533283A100D9DBCAEDB8A10CAE4C431136FD94089D7 64402322603B7049D4D10F97FD54D03D81B7B134293004BFB852D50DE5C6C5A8 29F3FC4855C34AE134EF939755B88270B114106573415FB185E395F6FB0A4698 B105964A9F374AF011972D67BBE0B3CDBBD0D9918A0E0D2653726C630FC8A63D 7C5BE82A965EDC1E0A57652688375FA60463EDEF222D4A6D726B768D8EA06584 BE7D23F6FE42CF8541F4BCAE1B01C73D6500207B211720DF98B72D016CC513FF 9109B59C4DBE5108CAE19687C1682A36F39AA8AD09C5AB7D69A13EB0BF2F50A4 0766AC191B105EE28BF0A87862C377E47EDAA69F99B7793F5F76114940848E50 CE05005B4E2C91103DB7BA7BCE79755E4324C0D0305EE203294CC82451EF3780 106156CC6C6BD07296CA7B927B869F8A9755CF9173F22D30EBD3217A98616E3C 8525AC8ACDB07F9311558AB53805673411836886A919BBB916416DC1C2061CF7 448ADED96B2933FD25C207BD374AB495DF564F25554274A3D2129CF7E6562F56 E3D7234B8660A536DF464418BD08E3DB7CC2A2A8B80A0CEA897505ED6367A460 3B6C0CE70E7C5F482C6B3FCFDD8C8266E023C421481CDBD041469219AFAFF611 97F1A2D6B13A90A76AF1FB2520D973DB1CA53BBB11A81115605A9ECEB0AA60CB 972E5FC2C431F1A5EB305D09C8B4C6D5CE1E397CE7FE9DA819F132192B2B91D1 2832F636D75DFC3A82143BDEE17461D536B13D21CDDC295EB617AFD850D59356 7172AD007B843AA74DB797099AB440C40BE561612B4506A8E26D1C4C5A8DD4D6 2B8DA07722FA903A6ADD179E0214071F1AA8A21022283E7380AF0B2656DAF629 50E8EB7C686EDCBAB6E56C5198041DEB47AE8BCDB4C30D318D2CF076491894E9 C9BBA0C6D9DC4B5962350AEF5B9DC1EFFB0C9B8F562660D677F376B2279089D0 294FD57B5ED589C1D28C6E9F02C821134A221334E1B4AFCD618FD86BAEBB31CC 28FF741E785DA99568AC909B091BDDEA56D6E3B75F4307E3A989C1BE6C92546C F518EE6BFA37355BF3A752C26A014FFD48B98F7C1B11B625A43E677DD04B16B5 B1B5F666AA67EBD602583D810578ADF8FBCE669C3913DDFECB2F64745EFDF7DA 13E21B44417230EA477D2E13452EE0E048FFBC3B3F3E32687948361AE63B2F3A C2393837699C356E580C995217D2BCADFDCCE3A6276B86DDA6DF06884B153369 327D3461E0493B6CDAC5102E62040437522DBA5DB6B6A4B30BE8AF1E9AD4DA47 AA79B1AC528F44184C40B9FC2E402F602FA679EFBF9F374BEE06E6332B112399 D18B8822C21B3B1DA3A84B31023D39508C1F0C97CFB05298E67DDF6EE891E261 67C5A17051C6DAEC3924E7E9FC00C98225CCDF01D885724122CBFD1354A59CC2 35EF7E987F633164341E2074B26689C6797F81618EC137BA7AE502904A211920 D7FA213A6F0BE82D49F7237690413AD381F5D2A3BB67D027C48455F48E717DCB E1D0ED373D62E180BF0AE16B91605EBB768E97242CA8DB982AC0C2DCFD4B5EE8 95BDC8910A12F20439946D3CA70A5F67A62B82BEC253FF1C68B1DB9BE887923C 1B4F803DEDBC42CB12082ED81E92F657D30E8652E76C6D93B1C7196BB77C0DBD C2DCB9E8734272157E4BD32B57FAD22278DF0B98DA7ACCE25626F453E8A7387E F75FB71ABECBCE09E6D35C7CDCD550EC6907A8832D6831B8F16C6FF757E3733A 3D028A0456B64C686A35EFFED2BEC9A9A1D93E98745DD6036FD954AAC48ECCC5 470FE468CC4AEEEC6D6E650378E5561990EF37879B517DA5D550B5DABF216D27 26941BDBE7286F95F3DB4673BEA513C8AE8FAABD78ACF6AB6918308627EE223A BFCD0B05C18134AB378AA07512D71E7AF987C925AD05686B6891EA8573FD13E2 790918687BD4DA3C12A9E0F33FCB6AA2BE3E3397B970E80338E5338F0F603B86 A42FA5A6285CDEF0739EBEB1B9133E86BAEE66E1AC48F83BECD4FA2CA3F1D5EE 8EA02DA4925191191A953FE68C13398E2D80796714C07FE16CAE171AC6BB0870 0AA402B06C310DC99F0A07669C57B5292530FB8DF265DB909A86B8D076468B4A B24AA398EE42F29BB41E7A640883F9D6021F4CC7E949670DACA3233FFCBD64F6 AAE2DFBB7B1E69F24A6C0A8D86081B2B09270D561B20EAD4D6B1D40B7F333A0A F1B2E915DA6709BA159E81455907510390AE7C870A4F38BC8DD19149558B9687 37B0777DC5D7964E3B50F4CEF6EF43F38BE9F01A68B60FBAC4BEE09E197C2554 C413B003ED8D8A095BEDCB291ACC0FB3AEC024D779BA9D69FD3D0F5D105F95E0 EA00C1483DC52F2A37BDD09F1F416BF99C1299784AA46D36515387FBD61C1C27 A2B6E55C6B086E87B32921BD7441F10E49DD10D7D82E81AED5FE4C5AC09F617B 9BEED75211D3FED854D9414ADC9B6AA0529863DD90FD48A3F82DF1F7C634D83A 261AB18F257A389AE958DC7315251E670296B0F415AB99D1FFB56AC1E7E61BBE 0DD2A5C6DCB7E270957BAC7584BFA9A6E21CFB293F0F51C58199D2EB431037D2 C44DB61F55B46B3F034CE7127628B7A3549AA2CA1FF18DD7AECFC4EE7B3AEC3D D0A1EBF2F7E045BCF177FFEC6A32B8BD47EDF924EDE5FAE04FFAE9904F4229AA DF5B82485C624F0B7319B147CAB299A6FC7EE302DB985DACE5B13F8FA8E73504 96E522B8D32869418AFE99B2EE70F52CCFE638419454432B9688E631272806CA FDC72B2F2971931F3D32AEE7B8979EF969E122CFB6D7AE0C314C3CF64859DADA 99AF547DF83E7B74AC852752D25B6EE4A29B6CBA28CB35FDCE44C0CF816E1420 9456518D9DC7A31DDA813F7ECE178F6C80A53010BF2272F50E93F5EC18E91D6A BA5DD888E1E9FBAB51276F78875DC0E6EBF759FD1C92A7D9E86D57B9632E5D3B 823FCB477610DEBF376FF0DAAF01A47E0CCBC52F0052C93C35EDAC9BD26C0CC6 5D62756F5476CD1BD7581567F55A6F04352AFB226DC7087F9D5B254E454126DA 1C12C7ECD608698A0B2E3595CAF63B8BB3C1DC9AC379FDB7F99F255C8AC29A46 AA322BD508021592969A16DCBA6959C5B92D0510AC400844405C810D6E34D41F DC8867E6A9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMR9 %!PS-AdobeFont-1.1: CMR9 1.0 %%CreationDate: 1991 Aug 20 16:39:59 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.0) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMR9) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle 0 def /isFixedPitch false def end readonly def /FontName /CMR9 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 44 /comma put dup 65 /A put dup 67 /C put dup 69 /E put dup 70 /F put dup 71 /G put dup 72 /H put dup 78 /N put dup 82 /R put dup 83 /S put dup 97 /a put dup 99 /c put dup 100 /d put dup 101 /e put dup 103 /g put dup 104 /h put dup 105 /i put dup 108 /l put dup 110 /n put dup 111 /o put dup 112 /p put dup 114 /r put dup 116 /t put readonly def /FontBBox{-39 -250 1036 750}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 2BDBF16FBC7512FAA308A093FE5CF7158F1163BC1F3352E22A1452E73FECA8A4 87100FB1FFC4C8AF409B2067537220E605DA0852CA49839E1386AF9D7A1A455F D1F017CE45884D76EF2CB9BC5821FD25365DDEA6E45F332B5F68A44AD8A530F0 92A36FADB679CF58BAFDD3E51DFDD314B91A605515D729EE20C42505FD4E0835 3C9D365B14C003BC6DD352F0228A8C161F172D2551CD1C67CD0B1B21DED53203 046FAFF9B1129167921DD82C5964F9DDDFE0D2686875BD075FC81831A941F20E C5CD90040A092E559F6D1D3B0E9BB71733595AE0EA6093F986377A96060BF12A A1B525CD9FA741FE051DD54A32BECD55A868DD63119A4370F8322CCBEC889BC2 A723CB4015FC4AA90AE873EA14DE13382CA9CF0D8DFB65F0ABEDFD9A64BB3F4D 731E2E1C9A1789228FF44116230A70C339C9819676022AB31B5C9C589AE9094B 09882051AD4637C1710D93E8DD117B4E7B478493B91EA6306FDB3FA6D738AAB1 49FBB21A00AC2A999C21445DE3177F21D8B6AAB33869C882613EA6B5EC56476B 5634181ECBF03BFEDB57F079EACE3B334F6F384BDF9D70AEBD592C8ECF21378B 54A8B5DBF7CB9282E16AA517E14843909339B5E7C55B038BF3BB493F3B884A1C C25F9E8FB912CBE23199AD9D2C3E573727701BA301526C66C3617B9514D6F11F 11930B1D97C17816C85B1BFD9B973A191B33CC3B391815AC46268691C741B2D4 48A840F1128D9B2F9CF07D0709FE796B23A836417BF7B5B12D67F74453C82F5F 25F7B30701D6F6D4F4DC623C0C27D6A6FBECC7312A3CD10932FC7C10851C3C52 24B75DEA8A648B7F34F5711DB0E843C914E25663C510185BC37BDB7593C1C259 21D8DDAD33982C336BF272BAB2F48E68217403FE9F54877B243614A87E64784D 2796EE4179FBF96123D1BEE3EF89D682B427BA4F12A1318A57F18BE5DD903815 2613667F0F25922C8476E353296B5FC2300FB8AE7CE38FF3CE3217A905E88E03 E2B4A68A22673EF30CEB2393FDF6387D8AF7EE943A23A81393BEB6D7033E6D90 A1D645FD1BC4965E6441C6336D5389E0C8EB790F1C97033C7470D8809199A090 63C898472D46F75F3990E561489CACE837690C938A7879B21FBF83AC6E268CFB 03AFBAD3FC5281BC608A9D7B613DBBE356BC7532175E2F8598E647D7F4947DCF 1D9EB823F13E4AFEB0BF3258692EBB2D2F11DF1396852DAD24650A51F63FBA4B 0F74B5294F62BFDDBB56BCD47A4428CD4F2EE44190651208DCB3C6E437971971 8979A4EC9F636B164FE1389FDC539ED9283B76E84266BF0E3EFB8A3C54F52174 E5BE4FF05E7190E4B3655DFAD9FC974681FB61502D974A70BA8949CE6B6D1659 DD840F16AB744D39C53B0753C4EAAB13EE3818898A0DE422FC8A6924CCDE45D7 161678E8F9F7C8BAC0246476A83B413ABDDC8033B5D1BD7C35E8701F0DC63CD1 BDEEE0FEE322C2CB2DDF84D10F97A24FC79E8EFCC492807B07B0E9A887B976E6 820010C4293F27C8B075DC9D1AE3CEDA7BC8B9EC9BB7C4388FD3A78D48FB8556 E49D309C8A1DDD38A1A149E6D39F7F4CC7EC293329B22F88598229196F1587F4 12D9BD35E5FEBC0D2A5813944E6651B7C4E5150C4D7C8AEEE4410F818B70D8C6 CBEFCDDB9B8F47B81B0C15A3054923057AC6D244EF133BBBFAD4EF41D6F41596 28195A27563D3AB6A62FEEE584F9AF0CD0253B7D7BB5E599081EA6657101E980 A558B9531CDC5DADA0D47F1CBB6DE4AC107A5D3AC24D69D0EC9609CC1762A583 121D6D0A48167E60C447D47AF8693A0E7B2796B839500CCE022FCEC5D2C1CA0D 8E8286CD2F31A756E0F3AA641C38ADF5E4926B3C41DB21B320F2EA5BE5D16E71 491B6CD80858B1F44A780DD7F6B77060FCC070FE625A196BD6DDCA6E40015DBD 378FCE94246918B68EDADA6F54B169F0535EF084923DB99FFDCDB9CBA30EFA21 EAE1F01B9AB170E6A1D92859BB2AA023E78D50601D9F33944D50104394EA45E9 EABD98646890231B2B7A5563A099212D51391746B21DE612301614B18E4493E6 BC78BB2D62EDED4D1384D85E7DF873E3A3F8C16FEB39B0EDCDB2CEBEC619E718 DA6EDE026FDCBBEBE75D47EFE7361C91C0B28118EBABE2C2B6078F4F82D925CB 4FE56054E9039C69AE61A0F1E5355E8B590405D36E3D2A2A2A51EF95777D433A 1EA1AFBBB14E0C68E8B751E7BBD06731573197AD614CC21DE871692FBA52BA34 D50E59B29207BCFA4556641ED3E868CB706C373073DA93FF91B2E6242D8A5E80 0F4DC93D6E7E6286D8E66D9126157EB7718B5C57496F3184192A0C61988D0946 2D4335FB6673F2EC4190CEC8C0E501517D1BC92693A73B02A6F6CE64BF7AB782 CFAB7E0BCA8DA23B10DC337CA184CF59C391A3F6399518C76AA0D9199A8614BB 5F0045C05233CC68A0B3DBA0F9D7F9DB81586954D5724B79F765F6BB51A4D330 53B753D84A14E2E4AC83262019E3018AB2EFAE580ED2F6093C0A1787756B33C8 9190925D0CF343543AB8011463206786871B4DFA4BB0CBC408C98DF27C4B70FF C04DA33A6E06259B0226B2DD479D2AD9A9AD51961AB9D861309E73662E78CF01 0979D545153EBC51FF9812BA01F652508505F4A82132331F3E3C74E00E52942C D8FCD78212A74A37247DF714338962F6585B8DB09E1BD63FDC2FC1C5FDFAE77F D12489A28366289F912890BFE5CDADAC498E10F9BCE6D05E1AC790171A484868 1CF5BD642B29E4355E18E3D48D6D5A9D63DC763D50E03C38C98BB908C05BD1C4 5D495B84C6AC10081C83B50B2B5BAAC285210D7D3D79C2151157B8A69839C5E1 691ABE5790C282037A98CA60D2C5E7627640607C35C285E39F3F4AE64533D4BF 65CCB9A11A79260B87F567C7AE128AC2C63C6A1F10C56E82AC562ED2C3A13B6B D7A5A06481890A93B8B2912E5AD052779D909EC758443A79C92535518B61D9AD 0ED1451E969C8E19BD78D3E51AD4B8C72EFD7FEFE8FD3ADE5157AF86CA3DA2D6 1E2B8D5154BF6BFBD8B45A52A095EF38480354F644A41F863119F882C07E48CD 2B64EF986CBBC000706F5B2ADC79D2411E1776F3067DD0CDB73F2B097A09D413 3C2659698D66F86082708B23D87DC0274DCB16EAB89170AEF3C6189DEA0ABC28 3691DA6C145EA5D191073041FA338AF636C4B817E5709D4B367F66A5CA9DCB1A 291F4231B3BECA853D6622E3500FD1842C8999D6412BB35985712C173B1D0684 EE50F6D36DAE6839A625EB242818A7F7D7E88CF3D20D000CC3789912E3FBF566 88F200B29B9422011CBF2EA1EACACADF2E0A44BF84DC296F6D4A7420F44A10AF FE9323E87BC10CC10752266E5EBB9F8DFB805930B77CA360B513A02E6F8D6826 C38F625C95606B5EA05B475DE83149DF464CA3D83C7095427784F6C10B353FD6 5885CA83C893FA30A28D45C69BBBB3F0498CA3B585DF4FCC18D5F55754553D7B B2CA38472D4A2BDB58C811C840FA82BF1A585AE685E848D222B3437D874E0A4C 6BC67DE7EC0F3E34A5A204AC7C4AA41A99503DF5CDD4E8B442212DD94A650A8D 706A0DA0379804FBB248FBC03FBEDD55705654C1962DC7124B4BABE0060EE47E 66F7FE127A645D9D05A88EF0FB573E4F86313C25B78081F2892012E3D429C7C2 322A20B4C11E6F4F54A8888F32C9ACF5A29F996C30BF35A10E15E4DE7E36D64F 530C3B766C110BD64AB6EDA4E7F3AEDB1E2DAA8EC41DA74E57C28284B98833F9 C0FEA33453C4A6BD3E62F488C46141BC8EECB66E291BE50F5017E822AFBB333A 30FD1B0F9F9E66CAC5F58A9B7BD6A4EFA43E74CA4CCEF7920F1128E51ECCCBF2 BB44236C4E4C047C87330822DACAE4F8FEB14C8CC0EF0D7F525CD1A08D07192A AFE999A4B565231B500D0BFC33114E0F6446F7E651D61489BB72EF88FEB7A436 3E04E8B69BEC231DFB97CD6EEBBE7D5E47F39E2121104BD3D6FA169AC8E86DEF A8AFF077E12F7CE025AB3C309D7F81D3196B4D14F3C7F8E2AF906C94CEC37D11 6B4D466A02B4BE6B0B7C9B4BA7A0399950E4D101CAC2C205385DC432ACCC8B76 59C0F9C82DB43C9A9B847997540698FB74107DFF24D1415C7EC8CD9A852AE85B 6EE981A4AECCC1C5123B486770FE6290CF1B3FC5F9B01526F9E9DB2C92C49259 3B9FF825A3C241EC51C85A2273E683B8B8E3ACDAC09D15C2BC69AE4DAC0ABD14 96BA077EAB7DFBE745718B859C711FAE6E3F47FD31E61E31BB7FFD0F467F14D6 6CE8AD12181EAF72449F8E57B2C102C8140F15B7B192DC31A12874BCE4A7AB86 0C4FBCA801F871CD67C92900C720582A59310A3E1A448404CBD62C0C1041A151 9E308E98F470051A07D0832139A4785D5CB07616D16E207E6838EC4A21F85327 F9432A7228EE66B1E989C7DB3B6F9B33AD1F5F0B4393EF820A2AF2517661F287 2BE4466C15E205E5557A0B70736E55F524B8645372AB001F540A3A0AB00CF7DE 1640B3C0CA275E6C75EFCF7A1AD7AEBE7F5CE88DEA735D8313281BF3B6BB0AEC 63F291F499321E58E390E11F7565081506DD5DE9FA7978A76221618185FE1E04 39D9DAC487CFB00EB6DD6E689FDB53C0219FE237F6EEA9C1F042843D3123C144 95CAF35CA462B0D8488D04B656EE64AECCD89AC054801E2463EF52FEE08B730B 58BF9F8600A8E0459D4284D99C009B05733A0302B67234E93735D5D02F1C88B6 65F48C5A80F4D566A4308ADD39C52D53EB6F016483AFA997A4EFF397F64732E6 1702B6D91C73D4FD49D438B9D7B3B770ED5DF0C3ED2891E29B26F5E5AA54B8A4 095CC7A7258E64D14CE7631591FC8C4657532E4431774890ED7C21B5232F4F7D E476260C734FFC1161D8EDB81766B7A85F4982B0007148BA232A5497AF5ECFBF 0C5C52ABAE562097A6170446FFA7DA4C816513A46CD44C1BC551A9153207D132 F77F4EC4FB69723148F9391026B8D694C922947368F5C3EAA437C75722971F1F F250848701DEA51D0E0BCC2003B2968586B2F5186B22B071A3323C92688E7314 6330B2EFC89CD6EE8DA5187C5B9E87C9DCAA7B295D80EFC26BA1CFA8CD89BD45 812C87F043E9CBF8BF047E1D800595C1ECADF24103FEAE5FCE32A9945C2297F5 A431B252800EB9CC44896BF15CF7754A54844DE09701EB22011DE9091C10B55D 9E6737C59654F68369A577C6C3D200DDEBA8BD4FF09915A5A015745809B20E45 04B6B0CE900472B2540CB1D18E60FF8ABA079A81D532395FFDA2FB03AE01999D FF7F199EDEAE47BA5BE4668E1D9B994C565890D4CE2FD7E9646CD3626AAB94CF CB1355CC2D54482F6C5B5745007AEF876C836E7B18D9B5C58448ED7F7ABF1BF2 8EDECB1A18D7DF20ECB502E15B5D471CAEA64EB2182F00F5B5B7BB72E358DA99 CDFF5BD7E274496774EF1155A6F09FDFA539E26BEDA3913D3B6405C9321C9D1B E5A0CE080F57BFE2CF3C80BCF2FF7A7C4924F96B627CFD45E5889996EDFD4E3A 9351034F1277B2D54C0D37783C9B8B07D2976ECE08DAD78FF7DE849DC077BE48 BA4FF934C2749765D4E27D679F94539611F98FE1CA92C52246AD2778652A6BA5 DEE57AAF3854424A78A23B36DB9E6F3364918BE5EE6CEEA1D6D40F8F00A9C116 3E6FDC117CF5B47B5BE09290686EE57D5A9C989F42C0946147B52C10B6996920 6AACAACC50E256B641D12ABF9F6F8546BBE525D57DD449F819A9A678746213FE AD49897C02A4DADE4721B1E1B11EEE9320240B05E9A74B02577DE56780EBAE18 4D810C4142026B75E4545DEF0FFB267DC1F44CE328749B121FA989760108BEF0 C21CB7CD0860B5E215133F66F88E0CB19109D36F47115298ABE66672708CB761 CD0C45CE5A12C237758F3D435F7D310DBF952F149090E9FD8A902AB674CE6A7D 08290FCF67CFA594F322360305C16A060D263D2F0CB6FA9E52CDD10A54F185FF A9AF4F97F64869515EE1DF31C64031DEE3627F46FF45ACB91F0BF272D7DF4D19 693BD2BD45F5308D5C9F71D78BDA39F7D2D0468E9E0548E16A2552C715F1DA8E 849AF2604E4CEF5021D4EA480E255087CE350A139F995BD23FC035EDA3DCC5EB 11FAE15DAD4CE711E12507A630445632FEC5BD2C35CA0F6894A168366207846D 570ADC67DB3BF684C15FFC064E9309F2D2CD794716995E7CB9F804F1955903E6 77D461A24BDEF84D03B167AAF05B8F86DB050D9EC43FB79C7A97AC86E32E0E82 FDC7B0EA5B8E13F09969DB412CB8CD5BC9C61205661EC3565139315DC3E67004 A4AD81E1140EAF34A51DAA72051247A64CD8A321283B05985AACAC914517CE14 AD6324E598C38FF0ECFE3B8DB05D9F6EB6B3C0471C34AC1CF8D9A6380B9D23E4 5A372AD76BEAE61C808DA495B7312F322BAE0C52A312485E4569DF0B8C0D365B 2E9C813851C10F0AAB4ADFF3A6A2B2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMSY6 %!PS-AdobeFont-1.1: CMSY6 1.0 %%CreationDate: 1991 Aug 15 07:21:34 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.0) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMSY6) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle -14.035 def /isFixedPitch false def end readonly def /FontName /CMSY6 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 3 /asteriskmath put readonly def /FontBBox{-4 -948 1329 786}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052F09F9C8ADE9D907C058B87E9B6964 7D53359E51216774A4EAA1E2B58EC3176BD1184A633B951372B4198D4E8C5EF4 A213ACB58AA0A658908035BF2ED8531779838A960DFE2B27EA49C37156989C85 E21B3ABF72E39A89232CD9F4237FC80C9E64E8425AA3BEF7DED60B122A52922A 221A37D9A807DD01161779DDE7D5FC1B2109839E5B52DFB7605D7BA557CC35D6 49F6EB651B83771034BA0C39DB8D426A24543EF4529E2D939125B5157482688E 9045C2242F4AFA4C489D975C029177CD6497EACD181FF151A45F521A4C4043C2 1F3E76EF5B3291A941583E27DFC68B9211105827590393ABFB8AA4D1623D1761 6AC0DF1D3154B0277BE821712BE7B33385E7A4105E8F3370F981B8FE9E3CF3E0 007B8C9F2D934F24D591C330487DDF179CECEC5258C47E4B32538F948AB00673 F9D549C971B0822056B339600FC1E3A5E51844CC8A75B857F15E7276260ED115 C5FD550F53CE5583743B50B0F9B7C4F836DEF7499F439A6EBE9BF559D2EE0571 CE54AEC463244B0F8EAB9E96CB18BD39259CC1FEC10F47FB56A38588CE634209 8F77258607212EE1DCA4F0667B152875B2CF5AC44B930B888ACD9D4B55662542 71239286D82E14CAABE7276AB199E2429C4C3BC32713106A10F5F16C8045A580 86EE21E7783B70FAE03D8D47B5AA13A881D478232DD65DBCD1EB9811C440E362 527EF73FC86FE664ACED80DCD6806CFD932BDEE102B89C22F423992249FC2273 F39C59AEF75B2088527AA973C71A6B134D26EF1ABAB75721971A0E4E52639DA9 2E1C3B2A6FB552CA834F6443E0628DD9CE69E92DA0B9B8ACAF3641FA0A7F1126 8DF8803E683ACCCCDE88C9F6C1838BCE7E8B56A0BC8C5F0300D81479A5087FFD B8B66527B87F7977C31A54E0506C6D33EBC902841AB7B8D75BC8ADE5397905EF BCB96AE4B57D308DCF0F74A93177F2DDF3486642A43834DB5B123CFA402E4BA1 6EB4C27AF21C96932E05B79CF951354FF66668C6503CA6FD2089A91A8D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMR10 %!PS-AdobeFont-1.1: CMR10 1.00B %%CreationDate: 1992 Feb 19 19:54:52 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.00B) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMR10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle 0 def /isFixedPitch false def end readonly def /FontName /CMR10 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 11 /ff put dup 12 /fi put dup 13 /fl put dup 14 /ffi put dup 33 /exclam put dup 34 /quotedblright put dup 35 /numbersign put dup 36 /dollar put dup 38 /ampersand put dup 39 /quoteright put dup 40 /parenleft put dup 41 /parenright put dup 42 /asterisk put dup 43 /plus put dup 44 /comma put dup 45 /hyphen put dup 46 /period put dup 47 /slash put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 55 /seven put dup 56 /eight put dup 57 /nine put dup 58 /colon put dup 59 /semicolon put dup 61 /equal put dup 63 /question put dup 64 /at put dup 65 /A put dup 66 /B put dup 67 /C put dup 68 /D put dup 69 /E put dup 70 /F put dup 71 /G put dup 72 /H put dup 73 /I put dup 74 /J put dup 75 /K put dup 76 /L put dup 77 /M put dup 78 /N put dup 79 /O put dup 80 /P put dup 82 /R put dup 83 /S put dup 84 /T put dup 85 /U put dup 86 /V put dup 87 /W put dup 88 /X put dup 89 /Y put dup 90 /Z put dup 91 /bracketleft put dup 92 /quotedblleft put dup 93 /bracketright put dup 96 /quoteleft put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 102 /f put dup 103 /g put dup 104 /h put dup 105 /i put dup 106 /j put dup 107 /k put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 113 /q put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 118 /v put dup 119 /w put dup 120 /x put dup 121 /y put dup 122 /z put dup 123 /endash put readonly def /FontBBox{-251 -250 1009 969}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 2BDBF16FBC7512FAA308A093FE5CF7158F1163BC1F3352E22A1452E73FECA8A4 87100FB1FFC4C8AF409B2067537220E605DA0852CA49839E1386AF9D7A1A455F D1F017CE45884D76EF2CB9BC5821FD25365DDEA6E45F332B5F68A44AD8A530F0 92A36FAC8D27F9087AFEEA2096F839A2BC4B937F24E080EF7C0F9374A18D565C 295A05210DB96A23175AC59A9BD0147A310EF49C551A417E0A22703F94FF7B75 409A5D417DA6730A69E310FA6A4229FC7E4F620B0FC4C63C50E99E179EB51E4C 4BC45217722F1E8E40F1E1428E792EAFE05C5A50D38C52114DFCD24D54027CBF 2512DD116F0463DE4052A7AD53B641A27E81E481947884CE35661B49153FA19E 0A2A860C7B61558671303DE6AE06A80E4E450E17067676E6BBB42A9A24ACBC3E B0CA7B7A3BFEA84FED39CCFB6D545BB2BCC49E5E16976407AB9D94556CD4F008 24EF579B6800B6DC3AAF840B3FC6822872368E3B4274DD06CA36AF8F6346C11B 43C772CC242F3B212C4BD7018D71A1A74C9A94ED0093A5FB6557F4E0751047AF D72098ECA301B8AE68110F983796E581F106144951DF5B750432A230FDA3B575 5A38B5E7972AABC12306A01A99FCF8189D71B8DBF49550BAEA9CF1B97CBFC7CC 96498ECC938B1A1710B670657DE923A659DB8757147B140A48067328E7E3F9C3 7D1888B284904301450CE0BC15EEEA00E48CCD6388F3FC3BEFD8D9C400015B65 0F2F536D035626B1FF0A69D732C7A1836D635C30C06BED4327737029E5BA5830 B9E88A4024C3326AD2F34F47B54739B48825AD6699F7D117EA4C4AEC4440BF6D AA0099DEFD326235965C63647921828BF269ECC87A2B1C8CAD6C78B6E561B007 97BE2BC7CA32B4534075F6491BE959D1F635463E71679E527F4F456F774B2AF8 FEF3D8C63B2F8B99FE0F73BA44B3CF15A613471EA3C7A1CD783D3EB41F4ACEE5 20759B6A4C4466E2D80EF7C7866BAD06E5DF0434D2C607FC82C9EBD4D8902EE4 0A7617C3AEACCB7CCE00319D0677AA6DB7E0250B51908F966977BD8C8D07FDBD F4D058444E7D7D91788DEA997CBE0545902E67194B7BA3CD0BF454FCA60B9A20 3E6BB526D2D5B5321EE18DD2A0B15E53BCB8E3E01067B30ED2DD2CB9B06D3122 A737435305D42DE9C6B614926BFD44DF10D14402EBEDFF0B144B1C9BD22D7379 5262FEEAFE31C8A721C2D46AA00C10681BA9970D09F1EA4FA77428025D4059BA 2988AC2E3D7246BAAAFB89745F0E38580546045527C8779A254DB08DCC6FB9B9 0E172209FBE3857AF495A7F2B34BC893D942C145C2204CFCD6A5C69FEFC25B60 E412CB2BEAE7F7FAD03AF46344F6A7D483BBB1E896BF16B0F4C363799DF23CE2 E8127996DE841B6F9D8A9E56BD799B6A938582988AF87151BB8D3AEA85C49857 DD862B5E10D9F33D57795D656FB616BC9B8397B3612131A2B0F472656700958F 739A548F7C3A348698AF9F6F9821D7A9FD4131781ACBF7EAB885A3AC254DBF94 02FA697941A0F97F048861788BEACC20DE829764413CA58F9D045A6B38BCD6E6 E4827247EDF1171F64E3B041A69B244308DC07F66643FCD7D5FD37F36EC4CB5F 957D4ADAF91850A3B1A765E0E580EDC77556593D1B2E1C22685268469298688A 45C474C9D0472D019CE1E83F25182D084AD85A49C502E8D679C227DA8E32045F 8055D1622C478F8FDA342685F858DE3F53F1CEA0D70BF54A4B35884FD75D8B36 E54B9393BDC9E020D16B0C20E943CF4E22C0380840DC7628B70C3CE570EE2060 34708F5531EA5E286384292A5BD0E04ABD1165CDDF8C0ED8899A82F64D2C2DD9 90C50E0FD6180D25ED5EF2746914E41E859EDE14FE652EBC40BA85F56F625947 805E6854520522135276AA0AB3956E65553012A51DBA92C0BE18D9A974109FCC 24F2F7EADBEADF14359BB85A0516BF482639761B7C4134B68E863A71DC8C76A8 F7DA8AD952F9428B6B492FD55D800C3FF266774D9807C268FE482333BC9B70FB C55DE4418DC3AB396B4150C4774E01A035DC2EF956FC2A0BD0BFCFDADDCFA8E8 299D6610014F4A73D5641A82528DD45935EAF72CFBB6C95CE320FD5EBE8A9F7A 2BFF5C3A5EEDBAE186F86B95AC394FEA62EC3A756E5DA7AFF8145444A7D632BF F8F6B211BD2D7E4A5A56B235C3912249F53683F9A12AC5E8AEE324000781157E 739C254AD437934D7B83ACDC2D5D7E6779EB15BECAA10B662A8B8A1CC0D6CA60 FEC9AE92613561A80ECB2AEEA335B5BDE2EE3FFFDA3D144DE40B82F93664F07A 7265281680C3153A10DC16C13A3715BAAEE70345F509661D04FE872F66420B6A FD94B36FB9565C4BEF9EDC71B0CFF58437FC06ECA3B15B875AC3690F0D2E596A 55C05FBA3B348B097C1453F27CD6AFD2CA38D3A6002A0ABC3655AC52EC9207D5 6B74AF8B9931BEC0C18E2F1BFD273293AB3593D553A0194D694C4E7036D98DD4 CF5A800D9E729515FF910E63CB3E1060D7F7562F79FE18D45CA52FCE85DA9039 5C414211F00A20DEA60B26994B05D9F5DF57D97EF5086824B4A074C78BF7F845 9C92908BA9F903BEB71D0F70249D69B1A75759225143C842566C031A2D15FF07 2EAB20883AFF604886616903D8B95293F48C1A821C5F2096E88C7CC13EDFFEE6 B0992152E4D6625C612511EE6254D9154E1B7EEB4C64CA40BC6C5BBB3584D7AB 06A2D217BC95F8514FF2FFF8F1D31069E6DD6C215ED4AEA0FBB275161353D2BB 9148067B9C1C0DAEF86F43E907E2BFDBA15788EB4851AFA5900FDBEAC07EF37C F5117A1EDDD3F2C318B7AD11E4813F28E202202AB4B6041138EB93B973E2630F 9FB42C8AE50B8E22CD0A649BD154E965D6F0C378C721FDA4336DFF873BA9EFD9 70D180CACD57A935D5A2053CB80CD378046DCA9C33326BBA1565665D666894DB AC59A68F5A8779738BF5905482D37C304618365B90D8F2425101151993C08F26 B3FBD83D88FE9F5B599CE1D81D10A8E7329409771993331C65FEB8F8C9318B2B 06734219028EC64B67DA6C9EE1EE60DA0E98B762E788D9A670CEC85B1B3111D7 0491C6170259A4644A5B6B31F3C0DC0FFFED687B4D662BE20EDF460636729D16 DCADF1E56B9C92CF29A1BACFB5BF3399A7D8D26C459FED717712065843163C55 516DDEFDFE83E65794C4978393950E703FA69A86987DB4985C4358A52C1654F5 0C8157DD644FB4933CEF46D76F7CD1FC00261C538DDB6650782C98EF66AE0C7B 5DD6CBFC9B1D928F789BAEDE464A3D24548FCE78E1E9C0623B265D8387D2AF84 B95633228DF728614C79AC5C4E311759EAAF4963AE31009BB3543057FB921994 C6E3398260E44A36093277A0926A2A896AD272745C95CADB395EB062B597BCDC E9DEC016EB1BD5DDFA1BA1D1AE892E1FD36E2621716AB74976AD19C95343AC17 7E3B43388419EE16356F1F27FAB39B8B61E0CD78EC781C0A4FFE5376B3DC2728 66B51B26F2E598AE017DB1D3BFCAE34D526FF09DBBB0290C579AE1634EE91A1B 9080E9FC10CC70A925F9AFDC45CE2F14B682AEF58D40319B3FCA0C11D5FD51BF 14C2444E41A92312861C35A4046FF806F01819466244DA99A92C40268E4F0ECE 55981D227074FE1FA9970C21DDF336E901B67DB28CCD3B39F1A7B9F96FCF3379 3336D67B9054C7A8B70F54EFE987915AE2EB57A91126FA770C600EF56B3921B5 14A2754A01319C568882C984D2C383E60FFF9173C172761469BFD19808890843 451E381498EF49EA8B16E5475C932E0311202224194D14DD30A243FEEF7345D4 BF288C6E2B81F4E69224275F2422337BE9A1F794C9BD5A6518EAA88D8524F631 99CD511EA841A35E2EEE8AA366C8A83E2C97CF4A7D71C4CF6BB5F0A60A27FD32 38C860BBD86CEC4250BC156FB8C21B6DB40E627CD537602484E52259DA98E315 605BB00E57E58EFD5C73FB9B2A6410CA3F0E04D3CADA88BD06EB548151DB4956 081E3FBA9551DF06C51273CC8C54E3578C0A345309C2D45F7B6F6DECC9437169 14CDFB887CFF01A102BE870E653961F95483184DF4F23BB6A5E248B18DB2647D 60B3651467CA2BF2A4A2D0AFF286E23A90439FC6CF8FD2C8753EDB90EFF684FA 41FA29F8B2E0B3A27AD75C2001F32FECD8A10973919F3D0C1BC0C9E5EC63D862 5CA28C834B502D01B4CC0731E2043E759A23BEAAB499A032AF9E6804EDF54064 843BCB48501F7EA6C7FA3560A125DA0D737AFD1B95B1DA2F3B750D3051A4F4A0 E53997F0AD82FA4B6B9D74C89DABA8E58C6C00D0439CC48C948EB359A08819D0 48C7D4CD5E25E9E12F6AB3B29FDB31DB521DD21405CA3DF6383F3E056B4FBEDF E12CECB2E3F2107E834A7D97345B55069A9ADBA55A33501F16C426D6ECD3DC89 CF6506A13DB053F87FBA8C4EE8ED91B41879B0422FC897DB3BDEA8CB43DA0358 048997B7A29E967EECF2CC9B72D5F17C5233787DC1D8C622F758DD294D329533 D429D8BC22D8FB3D70AF1A9B56CEA7A99C9425E769AE254B14F243808BA07166 FD066C320202B682AD3E355E351E3A85F1F7CCB4206DED1E073D275A3AE42DF3 282E4556F4D9699BF08243AEA49E49B46C4F6DD498BD95051B5ECACFD7F9E24F C68D7F1129B32A9A8A6105B90D0A13525610780A306D3D08FEA04006EB0D25A0 A0221A02FA7CCD653FFC8A4681E61E119DFBE38F586465DB76E4E448831B4909 C159F6FAACD08EE361DBA21F0562D64FFEF7119343F756DDA0BFDF02D0D522CB 3AAB2050B1AE27D54AA650AA491476766FD9629FBBF8289D43C3EE1EEAF95274 1F211E8BA70CE9E05625BDDA24D9E223D6C61EFEB1630DB948759EB7A4C47DBE 510253CF41BBDD251E3313428C15F8CFA4D91C1B3F3DC222B4A1F59FE1DB20B4 00CFC1130449B672D9BEE105B668BBAD1ABC7DB1D178B3452398F3D5F744E610 5CABB91FC124609C46223554694C982FBB3DF11E7EC223D49796ED707DB63D8D 0EB76516EF6337BBE1C0DF28165736D101433C1AEC5CC5E0506D10B526CA9895 DA3212C6CA69C4E22F3C4EEA3A8BEF8784F4AE2834DD1B0CCEC94E9F558AFE07 3C55181A3DD4B59D66E74077F08A936482664A9788573B4F52D1F83B4B9569BB 1F4CD6047483AD6CC99997D934C437C8F331513C2954368BEEB76F0B9813ED45 6F99BBEE05502EE9CFF20194E5C80DDF2D54AE35400DC46B8EB305B2B1FAA969 0D50193138997801200C9CB2C01DA51131219686AFC5061FD07D65A0A48B679C B53999377CC8D41E5B01166137D0089F7528BA27D956BAE5E2287C5BA4B0A0D1 624CC04BC099FB64C7488BE0A59AEA1897896424A178943EC2DBE462F06273E1 A7D820E895B2139C33A508DBEB9D5DA3DB0B9F386871CA37C2ECD3968FD273DD 3D4D2E44549C2C5A071599627685D416A58EE6F3451E0062123131FCEDF49477 94B0D48AE7272952CB3FE673B1894BA6A3DF9D5513577E4F45C339E68EF964F8 CCA0678E74DA23FFA685812BF4DA30FDBFDA2934CA99292CFCF7EC8823834D1D 57105CF20BC4F51BC677C204038E35AE858B95C8F18613B610DAD20D58F5A7F7 32A339FBF48E60ABE863B5DC39F18CF214CB3B9394D02B5F0E0116EF923F4386 CDBC71A65E88B340B961D78EDBD2188F7378441C1595A9372B3E4A9F3987B1C0 09118E50F4507807077B0712C75C07AD8D79A4E1F372FA47E1D2C16D52BDE1E9 6D5DC79007B6EC2B54CF2DCB26C391A49355050DA57C1FFD90930D63811D78FE 4106E9D8EF7F019AC306B021BC73ECEE85813DBC2E5142C11C414087C11D044F 642920B7102ECFF2D43C0E2965CBAF13104C293B106C2721190372BD666CDD17 5A506CF6C991A9912C213D2FB1321C186FEA1F62DB678B80C948ACB252D364F3 92FD93099D65209786CAFFD0380BB432D9023122ABFE579B71224BD99E5C6929 44164CB829C4796774FED8C762B19C327AFF66606620D7651D32224FD5BEAAA1 40711364D630C023C94AF8D959692A5E973A69E7074A0BA92B52D2BCDDD9A8B4 311601A7407695F370F55E951D4873B8B7864DEB94C591A682393A519676D415 C9D48CF9BB5919CDE4FFEDE5EBE1E31C19B963FB3E4514C97227E772868B7E78 2DD1F64B8A1A59F5270035D286EA7A8A2E9819C5D2EA09F4710F662B32F56125 5A74841A8BC247977AB2DA5A870A24936CA3584CE542E281F0914CD9F58E141A BE8E434304666063BB6521C944B1AE674B623A7155A813FC624359E229E4F24E A7A8C08255B220A300A52ADB791F8A44D1BC46D3983677D60CC5B2A8419AEE66 7ADCD92EFFB7C3BC90410947CA4F9E8292FF2B72ED99D220AD00E2DBB8CBEA25 C000E01C497F94746C68C3C0CD040FB12D59AD7E9CAEB9B63510C56732312C39 AEC21A76E6A16BA4A7A3BA0C1DCDC25ACE7FAE968AB6FF1749D3B0D32BAA78C1 AE9997EF7ADDAF34A9FE3BE747EB44CCC1975F004A053B686BE11889A802CDC1 D2176AAAB3CD0BE0AA56235524D691978A4D4D4080F1F66819DF8324DECB0EFC 264E10E60690E31AFE1E41DFCDFF8533E8ECA0CDE4A399354B055BBCA4032B19 C607B196BC1A1E5A337D4E7FBD723AF1D6A288277EC83A7FF297727DA311FD4F 667ECE9C649A43A6C3863035EF823E71DDBE22DDC00416B3B1857D4C54ED15FC 664ABBD089B1ED429710815DB71927311E2CB28F2DD32AC556C4774FAC84FBBC 8B02D9D5362AAF3D2BA23E9A407763386F94B19C5AC87EDE226D8FF2FD44527D 4C930CF193CFD628D4A611E178F66DD1548B4EDAC700618259406D0D5083484B 41CA554BB87DA00D1764A502807D3C489E56CED505518F73099C9B5E5FA9537C 13F20C4A83931C9A3143E90ADD4E72DBC5006017ABCA949F2EE79138BA6782AD 2A5ECEC5746402681EE1977BB077BB1BC68A8A63E677C602197530EC172EBAA0 FA8131A5FC6F10E6994D7E623D77F4EA5A61E3CB66613A212E2947F63E49E94D 1E612EC3A99FF6A604F3AE1218C5ABFF453026269307061E5FC9CF1250CD45D3 636965F97AE53FF8F8330C6FB1D7721EB3A071E145A2154D31409CACF1C560C4 F898358C4AA08E456178C3E7CF59A83EA098657D8253E64819E5F6E5BE5851B3 AD9109EEC894F8DEFE366C4C9C16781DE0E14B1D51424B6ED025C91DB0FEAD34 930E47F9C11D6B50814AB6109019F20A6D030ADABF57E8EF567F718CFDD9AB3C EC02AE3EA1D1E84BA84CE1A505AD35BFD762F2E12E24CDDF4DC9A0C49AE2B91D 149A89B8279DB8474CE8E1B24C257EE32DC5CF94580131A57B80167E901A057C F1236233EE28368B160196FFF63AE7D42737EA6DCD90C9158D7AC59F399654DE 7034546051E2E5F9AD18B292FABE9556BDC152DD842922CC182F09B65F6D464E 9C50218E2ED2F1FFEE92B14963D06CEBA5AFD9A0A75441B09AA87AF2B4D253F6 340E831087DD7552A5322A3375D0BF870A773D36082AC8D0A0AE309D4E8DF387 26B7767EC42002A9D4EC80A5FCDEB57EBB86A4AD383C1BF85E873DCB73A7DCDE 077745D63CABC0B737550828F7C789470B358586C04395740DE69EBBA502CC2C A79EE29EA969D1986C9C55878E70320ABC50E46DF6362DCD9FAC8A4CE9CD95F4 9041D407809C25F4FDF04EB59BC9F008B34364EBF30BFAB3D2B965A892B9594F CBDDBB718C2D403BF678F998ABD78DAC10AC02D71AE1755DE8DD47CD8B06C0E1 0062A6C1FB2322BE6A26F86CB3A9C9EC950E37BC711D4F32BC878F2801485309 94FFFB772AD0167EC95AABDF0B82CC96FAC9CF45580638CAE52FF27A5853F6DF 13939DF00240882C9AF2DA83D08ECF7A6A40BBBCAB4D9E81700ADC65361E1736 DC0B4D69B52B9BB481061E06FD261EF05D22A1CCFDF59DC63779B4FCE6FBF25D 1243D54B3337D1EFB8F6C68C7CA33EA2392B5C034F514378BCA88CE84AB0C586 F6940D0DCFD14249733A8D4EEC25D494B41EB76F8944B6591A1D69F42A9064A4 4BA19CA154EF1850A4AE3E7F52E6CBC2B6A948740154E159FBB036A21069D105 03C2BD76B5D4930FF4B55593A282071015A7B9C739CB7FD6465AB557DDEF6763 F120F93EA6FAFD06FC2CDD1445A77C43C1F4B765538BF0440CC4C57A97FAF64D 1FADC38AD58E260EF5677ABA6D56A1F0D05639EA526EC7CE1F427CAB2B95AE97 9AB54683F08D3EAA25A9077A9E20162E62E0A32EA3BB577E77DEFDCD7117B53A E891E4A63DB284C45571E82AAE871580CE240E76FF8E0984B31BF119660CF391 41B6DC288A6A171F5270D2E3B0F64373DF64F472B02B7231F0DFD334B1355919 C1C489E2DBC11A2663A173713A6D220A5B25D34F15788640AFE26A9704AF2CFB F839E74BCDB0EF554049319B271BDCB736D775491FAF0D9FABD77E1250DF0AE2 084693EFC96A234331EF04EB85B976DD77AE513507B6669F6FD4BF5FA64E22A1 45A9894ED778FCDF3FE72AFDABE83F7D7E648FB8EC7FF219823088ABCE39211F 8DDB2FFF4793DF5FCDB25183D800ED0357AF5EEA5823CEFA7BC8A99248F91C71 EF0B218ACC2FF17E59C41DBBBF24312A92793829DE450A962033F5EC81F75E6B 9CE808EA804882618F4BB84D241C3E69FBAA333B540132B0466EBFA4B15D8ECA 445B2C013268E00AF58A33B05D6A8FC6931EBA68A5D1EB19BDEB8D6A13D75FC9 8F80ADD36DDAAF016C6E7F60B6726FDD9A9EE8BD042AB26C9E7BFB513FB16198 54566D34BED609703AF75C92D68081B40EDDD8F150CFB6E0A7EFA3A04502A04C C07ECF2136F294A0F9066A2F84C739F1A821FC202E3CBC6D8BFDD4D98C51753F 6400E1A38E91A628710BF3016933910A65913FCCB32E80A422F1432E0DC07145 D519A159053719183BA4AD772F708F86B4074DBE9E2A7DBB7EDA7A707CDDDF16 A4ED69D6A90DF8DB09E06917BE7BF1FAFA8148B2D4DF39C418F81166A0EF337D 78891C561FA087193CFA1D31C2DC7393F6A10786E09A7EDC0018D370071C3EDB BFB42B40AF7199F5CB901CDEFBCAF011ECEC8E390D372CE5D4EA30DDA53CB86B E69B1EC8DE69E84F5F3BABE2632576E7912831836E36DF7AFD3C7794009903E9 D6C0DE85044C3A69AFD7488F586C47B064DC3CEB8BB395FCCC3CF217F4C92CED 3014B8F8ED0D2B38FE1555CE4F026AEE85E4A31E657D8818034E5ABFBED828D8 7FE0E372F506E4EB3A539E738AF1FA5EDC1183C80170023E86AB36B7FFCA23B9 6CB86A39E4F57A3B9E4CC725F13C2C54B8A3E640328B8C0CEA0F95DA5288B615 F068DA3668272764C0CD9347DC0DD834D0D9259AEAB049E7BE906878FDA12C29 47F00E7825BE00DE8CFD5678EA7AE1726F5D665C8F5AE7318A4B65BACB0E8599 6E91BD9406898E88C2C524253A61AB8025DC8A873C53340F3D531718ACFF3218 DB61F8C4D321A343EF919657ACC0CF23AA411799D9DA0BBED27FBCA58B5EC49B 2D00F6B179C72141ECC41626BE0EBB55771546553FC052A858FC06987F5C3E7F 7076838EB3E284D00A5D394083C61CED195B0B7C9B8007C8A6A347EE98261AA9 644CABD5693D277241F3F6FE0ED9B661226F191E8DAADF48E15C63A2BD64B33F A0B5A8BD0AEDD3608ACE5E3F7038DAF3F9BAB659DD2EA4CD13CADAC984DCB03C 0B8D848666D54D21C788F95B400CF6EC834594C8275F51C941A1F5687D5A427E 5E9A93EAAD048F5D141778BFA3792EED2B0B3C37D06605BFA91FE8271CEDC1DD 1E8F3C374AA4BA92F2C9521D87AE6DA5D7791F38ADA438ACFCE4365229930215 894690C75D27BAD65579C588C2872FD26D49FFA96F7937E6FEB5A3820C1AB38B 574C86F272FF25EB6E70BD944635B186DE2AD84A74AE8FF76BCF22B01FB11343 CFB142CA4C3B0068F7215BA640766B2716BF3DF57D830D7AD9B00B39C998ADAE 436FC8B9730151A9C5D080EF2E41171EEB56E9F35A2EEEDD5481349D9AAA1E91 1C10F45F5E5BAC3592326EC5BB841DC70706455954F9827D987158AB480FF3AC 34C0410A9D1CAEC8C6B62A79AC582A75078E63A164387D23E076C54F4471BD88 0248CBD81A2FFAB7926F415E2B237694167BACADA7A71D9017D3200D2874D22D A2129B24F936F750ED529DA69A1A8F6F057338DB2209F221D03F22B383ED29B1 DD71FC1C5036997C0C879E78B542F3918003A7B55370288216F15DB91FE7578E 8C8CFA8E6BFF32C57ED566ADFEF0197826F073D45AF8580BF6B4DCC3F5856F44 2428C6450D2B471F6E1A67C511DD94DAB9273A506D7109DCB33888B76D2F2257 DC6DF167457BDD003DDAB6F3FC1C1121E4E59550A950FD4F713A2AA7CBE97941 5D78F7F17EB30A5CA883D17642E2334D7194A80961F0E2C26091360B805B4CC1 6CD14A722C1A144BBF7FC4061E417148C1E9B750CA0E18EE05485FFF19545794 311472B0EF215EABF1E7A8681CA71FD43FB0301A859CEAC0361B3E0C41736C53 7A9F938B39070AA29F9EA5A7C9219EDBDFA2E9132BF0E49B670057FB23B86B9B B3CC7C0FD12EB309DCF8D1D5967C235CFBCF541B5C191DA128D1DA4BEB088BDC B6ED683BDE7EE18598B9B2B1D233F26693A66B3FC2285444721107C7313F7FB3 201905B38DE3BFED9BA661AD4A3D940C6BFF8A74807F4A6D8348A6246D2CB9F1 D3E4DDE6D7460EDA0026E919EBD0E7305F66FA37D2C7EAFA415E67BE00399C5F 4BFF7851DC10B44A696B2F0952007736416CA5F02D8DF73B60BA764D2C1E978D 3F4DEE50CB7764FF586D1B719E726734625984657FE810FEA022CBFD09F16487 E6033B38A1E111F73B8566E60145A6E6D76E98CBD3F2F70692266012C9204A73 309578178217A109DCAFE3747AE4DDF549737B4DC9647A56D9D3A399663BC417 D83D252E7407E60270D2F592127B5DF30603482F1C17E20F2BFDB2B29E17E55B 100DF6F1E76963B086FF0729AEFEEE7B1283516C6254F0B54B3AE11E456ABF79 9E09F2D983E2F7CD3D056926DDF26E5A6B7E003029536DCB2FDB0BEBB6878448 444EE80334344CA7E42B5371E7C632EF9BFEE36AE2E22E713E7EA69BB2C8B4C3 B5E204981EC1DA73A72E0B0A26406E904DB16DE7303606D4D5F3538E095F5BC2 06917400DD909F3D880F5E6A07B0ADF0E61352872D4A52FC3C8D18293A4B2F94 5D32030E7B925B951F5FE050335123BC96BB5C8D6B6B9C7DBE7C049516854637 82AED9C2D708A8A8137F59F099A7BAF3254E4ADFC81CEFBA89D6C0D11C9A7B10 2F19ED50BCD3521AAB052185BC45EF2F2BDA547C57688219D038D1E5458B2877 7B20CEA17D4EFC5EBEFA32B99AA1BE19FD7AD6255F7E12450DA48C3A7947E5CA 95CADBCF440B38212FF36A840AD4BEF61438F4C08611C2919C1DEBE0B916887F CCF3918EEA989BF0F15FBA52906DA77BD57BA0CCCDE6CFCDAC76A75503040BF9 9728DAEAE729F7DAF8E7511C5F92C10DB4764421F8D968612FE1E01AEB35B067 2CC2D5D1386C0666885750E9F04E1A0407157F60FFE84E585A36714C844A6386 09EC06111CBDA2F6C561694D409D93933EF5A0E25FD7D2BF5A1E5267BD9267B0 151FF2A06D7B7085B8016DD4943AEF5A3274F0828E22CC6C9E68BF182CE6D474 3274F74E64565BF8E64FE4AFD4C98F05487C31A249D5C90F94F9CAC398B2F496 15CC249D62F0C9B9B9F71AD29479E69D5B449D2564802D6576C7584368381F36 E3C22F01AAAFC85D22617D6F6A4E598FA8DF1FACD4C7F205E88026D12F7C509E 38D29C65141EB2D397797FCDA3D2F54651F70FC52E8F4E12C5AA200495825FEB 54855AE33A8ABB57E61394902CAABFD06D42BD1ACA57DD9B81614CD44C822A55 88EBFD1DD771EFD92876B60131D4B86D3617863A1399A8CC1F2FE9EB1AC4C614 1989A0E2960CD5F830D33CE422D5BC52BD7DEE31D2C668E65ADE9220206136D5 7696FA00C4857CBBCE675A0B163AA73EC04A75598D18D82422A54FCA9A27CEE1 B922A0F52968D27616667F660EA1B5BD3BF25519E391FF9958D4A491A9308854 967312DB3174EA973FB5052ED4274F449F3D579EE90B54188F910AC3C69655A1 FBE9E3D09FB0233E3C7A80EEFE4FEDE817A7AFAFFC84E1D48F6E70C41D0226AC 31F46F7B29E99B562E9C4AEC9CF4558321DA229C3A7738B0CAF03C93EE489A2D 72458368E300FE0BCDEF04E7EDA685BEDCCE622C59EA429DDD81356BDB22E830 F65C8904824135F82A1A524C317153B103A0BC804FD186FEBED4AFCE8706EB4F 32DBD3BF2F40C5DF5B85E324D8C140D47F4D2E2DF2304424C327C6D12EE63E15 27BD4EDF53E355AE9A58A4AE77525B70DAA373CE7968CE286967B43F685C267E 7972594FD36DE1E0989111A30F43AF8B63EDAE180502A0D5873029770764B933 F7E43DF0B70A0DEC500AD685A57399DB8433BC975A90B0707C8BCD466D7C657B EC0D58E7CA755BF41D684CBF75D1941DCC4BACCDB5D0E1C0855E8C4C368E535B 327290B67D8CF7E12A2460E6294943BDD6E9BF9CF5A6AF70AD1B96BB33C70195 56AEAE0B1DABB09485C282D79C30517BC34583D16FD2B268F024E0D9654AAF3B 3D8AB3496E7D0622D0455BF82C2BFDE912500E6D5DBBD9546D54362922C9A46C B6D7A01363AF3699466875A416CCA72F97DD327264B3EA16BBBF7E088B47216F 626FEF9AD1034AB0CA82099509C9AF9B70599929CE3D21F612CD40577E9CB7AB A4A79A15A0B03A8B90A424B64E7414196B72ECC9D2632B4D7586700D495DDC0D 367F415737612CB6BA03D726004F8D49B2C5E155464B826349470D9499B60DF7 84764156762F2E38B9440CCE89A9555DB43328B59ED6AE0E53B015492D2455D5 C66E4DB65871164547C34E5D41FC3B9D5440E8D6B7B6E09FCF916BE674A43E36 6FA7A912481905177D896EC126DA80E125ABD27B9BD6D81B474F909DC8590571 6A815BB1F27853BC47EDE4718950C3702A9D27C28D3A0FE73381445B60BB1887 DE62F57BE2E473B1263877A11D766945ACD5310C4B9D2EDBDB5D3DA070814969 7F086E8EF24920F37A23FD09CFDE87F854808DA8FE7E5F2E54BC13CB936D498A 5CE1A7202EABF663BBA01BDBB0B479264BDE90A30543B7CFB8887B52D0F28BD7 8DB8A8438418D50BA775EA58624DE3055B394A9B7D31E268B45E4BE6304C3B3D CB9DDFBF78ACEB72082F2895B99AF925421472DDDCD0C2846E945797284FB405 74A05BE373C99648D46F0911A984AF9F726F28BE6534E2D1838FA129E508F81F B4490FC684E446659151B446B13331D0542223D0F7609A8925808F16E9992FCE 42983CDFDA4C8F3BA175E47F630534B706A3BC38CB3AD3D4AE304EFB9C00BEB2 A830A35B2FFC25F6BA978C28AC71B875C25A7808EC8A5BF619673CF8B8518368 852BC0AB7ADF6CC29D7CF4C31F0D606267DA15469DBFF23DEF654384E6074A55 A5AD235991F25EFB4973E03CC19305EDCF3B46314F1584B7216366C324D1D182 8CB2F48B836CBA52042005C67951904FE2889BEE51B90973202E6280FE134F80 C0EE88917639F293EA1840DE5D654665D5B38FD57B89B3807714FCD9A2510B03 4CFFB3DC6BDB2E5427FC725A91551F2615A5A9C1FD625FAD049CDF42AAF1F98D 9B6E9C29A1C35B51D14608DDECD76BDE9AD08F4D14B3BAAFB4ADE2B2D24E833D 9B520976E1345FDCAEB2FC5A6A7A47DB0EEDC35B0AC9B143C7066DAC1A9F1A3A 6759FCA1AFF0C9C14D7134EDC9AB838DB1A854C10309E456F8571B9DC87EE342 C1B703FFF292EEE81C043C6ABC32F31802981E734B15FA87A6BAA95FD4D4D9E0 7896ED06ED4A60DE13A62CB6C7190AA73D9520AFA10A6827E45BC35F4AE730C5 AD837CEE455989A3EF8B5920A4278082C7CA8582594231614029D6D084474864 3D96D86A4F31E258A49C4771262A64F7445B20E159C024D7A40B623D565A5CCD E4AC3E832F95BB8BA3B9FBBADA1A9DC928035B9FD5D81681362FC7F5E9004050 6538F992ECC8CC0F9A468621546153BB29ABE17CFB7FF412EB4FF42A4E6438A4 01F4D4C6264B4B815572E90327646FE756DAC90C9AB78402F791CB2669AC60F8 39F7902B6A95BD4EF3041C631D37E939518EE97E9B2E52BAB3BA8F2A26C8A9FB EBCE5C7306A617104C0D0C74A4FE03B94390A393498C1619932CC3EE1650404F AB16E40CD3B4870C9F687D11DDAE5C15B0AD50C727B34DED6C37925F1798FA5D 8AA565ABF2D368242F2985EDC4E299E5F93DB82656BBFDA364E2FAEA9893AC3C DDA311C7D6ABC7CA6C759C5DD2DEF44C675F7538EF35AAA5503BC12F311A1058 8DB47F91E9B56CDA671EFDDBFF09AE3D75E30272CA099A7DDEF518DF908687F4 BBBACDF9486E3FAB7B909199A258B6CA6E3B64F30EB8F6F907E7239F0BB4339B 519E733BE3239221256C20854881C6D0F9B974E1C4AE67C5E84BBC72152D7579 40036923F671F9B5C6D7BBA52C145664BC3F10B294A4BD345E019E95A7D7D93C C1DD7AF0929280D01A1AFC83D4FB0AD268502B1811F874AA648F40F5AEBCCB85 5C4C485F5B1031F3FE4B038581E9C0912CC3A877672F3889C32F72219A9A071F 7268F19AAE2F8F6FA3A02287D64E64FAB91252A1534DFD7338AFB26D3ADAA770 F89A63D3FBED4B0914D3A1D64D21864C561CF681D38ECA5AB013BC8E4A3D8E63 4FACA1387B57055E12AEB6E28330B7E679B211D108D6237215D34E8E8475FDC5 D291E6B3A00C1080923642062D15E1DC258D018F9E9138BEC0D1FFF34BEB39A9 573AB74F63651E0CBC8F12D965E255085DBBB4E8BCECCF0B4B5D58EA07C3C69B 97EBC9904E9A4E6F361635FDD544C88120AE84CCF5416E9EE6E9D534780ABF32 8A6EFCFFF3EC1F46E969E97C0F79AC02E2A0CFB7662EE288498182456452E0E3 62B24F03B95E0E70406033353FA3B0DFBB1741024E131710E3355FF2EF1848EC 26AE602D8806E44E38019F7D9865F7EE35A56082403BE5B4D3FFF0D485E5C718 389F5283C688EC02574ECE4C757CEDB01CC8596C6462E19261C6B32867ED7553 0EE2E171CA3ACD4C092AACD751F698E9B18C56FA5A9BC0A8DE405F08C9AF304D D4D481D2A1E93BEE9725025935D71408AABD74F3BAB3AAB21004155FFE19F551 E0E1B682C2F54C92F6B9ED91A38442CFACE98368AEEDA68BD8A28E91B1FAE708 6672771D26AADA36F30EB709FD01683A11B817FF646ED2C3A6FB1101913CB8CC 64C68E37148FEFDDC74F2FBDD70CD8000733D3BC44B6C787D1C7E49AC1D2E2C6 C2ECC696A9722F473EDF681863575E1FB1A54735F5C8136516AFB9A6D4E9A7AA 310A6118B3EF9349D1E96E6EB384D206DBC45B188BA8445738729DE24D48A159 80DABB850435C0A03359291C332C78C1656BE622FF734144AC17BE19D38F9F54 59CFF8FADB2D0164AFC718268AA4B94EE7CCCA7B479A0DC70D9B838D916833D3 6923D4B22126BAA2237DBC3515EEE6111F6F078C904EA4FC5EF00364455976FA E00E5D79C5B57DB1ACC73640A9E37C200A530430E0D7F899AC67F7EFB2F906D2 24722B0A9A35E7DA6571373E2BCB5DC0D5E5D1398B9BE20A2F2A5EBE0464E101 30BE52CF8C12D85B09F5DB9DEBD3ACF320DF140EC32ACACD0DA56642F44BB965 BB769C0AAA298E671A0371DD2CB06ACE542DBB79031312A482B86BE124801EF9 52D425F8F2F3B31598B93C2330E8B08BD1F6A4DB245A19B803EA947A2119DA5D 52A83D5637F85B4ACAA1373930A4674C354EA46BF19B439C764FFEB82F249514 ABE74189D9BFBDA3A8F81CA4A8DB1BF63E10AC6B5B5E0D6FF8CA45ECE9536571 A9E32433CBD5F04D2EFC1BC92D18CEC88D700121BD4923CBA73051595261307A 7B00D14A2300CF78C93EC96326C0D10E58E91A86FCAD94E1A47E34FCFC5C65BC BB7316ECBAA3E35C7D3C0814BF6A2AE8B18121BD68722CB277712D118F1CA88D 31D5EDBFD64D74318E5DA451D12F5CDD0F97258ED25157B1A0ED1994706EDED5 FF6293C9E4F20EDD1315FBE90446A5ED621B4898E4EB9F23927F9D33DFDC62B1 A38C8E7B247BE8511ABA17A2CC52D4AE3A6D7A87220FE1745620A4B3A56F3520 D718E0015A0606E4D187856647CB189D0DFCD96968890561843A9FA21DC5D508 C74D9E33F21EA57B90DFD7637128ED958AC4EE480901F96ADF4FA833143BD85A C7D0B1D132D5C000E1223CCCFCB5AC84A42052FC10113B6AA88189502B56431C 7CAD3A8DBB8D096569314ADC4236129F00A65E1C0B5EF666268AF208006F6A75 136970EAC3A2904C7426A018B751861BB6C46D4D74FDF9A162BB85546F22CF80 B7BBE9C846E8910289EEA599BCD5FF4075C30AA88F93450654EF831645D7383C CC7FEBBA9C0DDF8109581C4A85224F7C9223581FBB201951169DCA18FEE81B48 F2E916BE7E275CF75990102FFFC1DBEB859237F9AA511D4C884419E421DEA2EB 418C6A9318D45D858468323DD803918FA6497A4CE6E7FBF188A67297040712F8 FA68387D28D239AFEC749ACF53A5F72B21AF2C8DE24EDCE7230934E324AC2C89 F35E2F349E92D3927A367C942A9A685A4C28F364D7E61D2DA2604FA80C31BF40 5AC6DD6EFDD8799471B3D8890D93D451306E481CDB71C471D670369CBAB789FE EAFAAB9D94ECECD08F6C8F82BB4DF09BCB02F3E06A126E4E468F059089255F37 7488E957B2B5521A36FF62E26838E06E38719ED72D2A0C7FC560A5ADB530CF22 518CC4B715D7B6DA08217328C4A09C53AE70A7339514B56D13A2F7ECE09220D8 E2EE66CEF5E5D07B1B30BF15C3BEDE12CB52C974198C8F097C3DFC69A3AC2545 41A3913094A42F4A2BBF2CE0CEE9AD7E5A6CD79814CD5DC55C8F3A99FBA341FF 7D844AC9CB0E5BB3FED72ECDD97A8B22183EA6B9D13CDF6EC3DDA3D42515E94A CD45D8FB4CCA4DAB7138E8FC837C89C3E78C2541550F229A4AA9A836A449CA47 B2D77BAB5A7B4D53B3D2F35530523338AD7FFE86A0BD3B0842DA686A4B9B732F 4E81E47D2DA475BE2FBA41F05B9595BAC506F2D8F9C2EB22398342C77E79AFEF 763BDF8269B7688CF98F7823E5096AE4D644D5249F7EA1266ACFE9949AC8A288 D57AB37F51FAF7937F47E41CA2F51EB249A525E91040CC5F4E9322475FE14E87 2444BFE2BCB136FCDC23BDBC4981632CF1FEFBB494F1A3BA16F50DD9BA26DBD3 0CA3C7113A364D0EEFE600C47BD90DF257CECA68B3D173211380487FC90503BC C9FFC27435BDC41EEEF08A8BB309CB2B0C8BC86DA1AA3514B07E97582F3FE4A2 32BF7BAB02CDBA5930DFF4BAEE6F00A21916C9D1D0EE21AEA51AF561EB0113D5 3A0A251D173A77C1795BCC56863200338933817AA0AD96FDD6CE740213CA207C 864A97762A9FCD3EC94FC518E0B9CF871854BE2CCDE4C21C1AB11F6BE66A44F6 7D6751471D4BD779C949CBEF803B4E7672D5D399525FAA9252FF78BF7E7E81AE 10FE4DCFD6BD3CC4C99B2CE818B2B8B45B6C4B131ABF2FC61B71EB3E2BE21D84 F3A5F90B39D76D1618063E8EEC04992AA29CA3216217CAEE3E27B3916E5310DC 5C4E2B489822FE4D6AE8A12FB1589A3790F9FBD105F451637F396E04A13FE1CB 7E1E936F3EE1F37C9B4AEA80994EF8A217DEF96C747B8EDAF048EE8EACBE4757 3A6BA4B9297A4229CECB2719A9346B0D34FCFB9AB7575335EB477F0EA9AE54C8 063F5B3C4E40D158D44CCCA4BC7C7B55687FB89BE7DB9279E34F144247737AAB D3EFFD448FDD211DD3EFDF6750D9232C4AED40C8DCAC19A19CAD81FDC6A02470 7B0F5B743465E0910F67C559A5B25EF09C80BAA80486F04107559D253A9A62ED 7A25BAF326D8569E2DDC14688723C245CD694FBAF14B8BFDFC35038CE3A1BF0E 5D8FA4FD381BDFE34F68C81FA1E87D3A760F48998A443F70D6E38910354E23A6 4449FE903E50D30DF066972927585A61EE674F89B28B7AA90FDB1B94A6A5F1E1 9D6D7313A5389D5BE005CFC1CD4F35A0458B06D62EAAA5DEE8117FDE9BAEB25E A38E0886FEE01E0170C5B6351736816FBEF0351E5471697428F25239953E7FBE B16F4D7E00E81BEA0CA12AF27DC98B3BA32A2A504C8C4B523740FFAF29EA504D D747111DD946EC2034AD209B6645A6F3CB5CF0149A2C9635AA41E88A0938EB87 BB442A48D4B942A08212D1EA498E0C7106C458C857E003E5DD7635B0CC6344D1 C1D4C05A8263414C0340AF765282CAC8367B89FCB66D9D4B958FC981E9CC7785 E993DD791F9CD6B3557FD2F0B87023B6D60BE63DBDABA57C975EE37F44E5DD4F DA1159378A67B6E3D5ADA8E40D59816A584A456AA4D61B3373BF048C3BE6B806 8549DBE89116FCD001D507B7CF32F87B0887705BA11F8DFAABBFDCAA721D38BF 94C61F70A58891E577D7030491D60132C93DA3A80A856111549E02B317CE1035 DA5D9AA8EDC8A63F065EB93032B48869CAE47E94A805F395CFEB064905674633 4D0CED3373E67B52F127A58DD7C2770BF9FAA294C62B9F76F6D47BCA510E11EF 3DC37F5C317442821B2D056993E67646D9B1E5CA929FF709ABA27A27404EC2CB 6EBA02B7A2839955F8E2BB7F59449C1CF39449EF1E94759E6957F1BBB1E4516F 9C07F7578CD268C9D90111648AA654526A5E8351CE12FD3B5FA2DBBAEF8ABCD3 5882795FD9FADEBC8F3B7F9505CD9938D465360157D6DFD90E13D21DAEECE587 43E13F92BE4EB0980319CEB35C11C19B32A5D57B6CA259D4D8921BED9576CB01 4F2AD03704644F1E3C6E50477916D193EC3AE2E82FB86880765CB7E4F69A0F66 D39189F5E7E76136D7CC5E33102572FFC5BC1E2849243C43902F77462C36D42D 8E51F67A343A4070FC2F192E4C2A19C97526C01152A745FC60D4149B3566820B 4F45492B4D3304154F917081A0C7BD0838BEFC96ECD5BF1ADDC743D190FCAB15 77A24B3E0CB72C16F698F8ABDF2A653C8AF374582B3631035A61572421BD9B9F E630BBBF2C4D31C15C608950E5EB054F08C4BFD8C55E9346A023B5A6E384CE5A D45D147AD6A0D83E507D6E7CB4DB9D79BCDBD4DBAC53E4F2F54BC43E6604FF41 694998160DFE2ECE261A4258E6181962B3DF7511FCCBC1AA4BDA31FACB8352B6 00A20481D66FDF1D570C015AC07240E94A41D827BA17D9CEF845715EF094955C 63CD05D6C8F3D68AC0C0C46CFFB463C5E2EE902D6B866D374F01C7C33C42EB6B AEC6044F93F94DFF85ADE2626DEEF3EC73563C6EB2762D3A8E565A4E6FCA4026 9F33EB916C4CEBAC10ACF046C3C2F78397622EBCA2C19002B0BA6C6D74EB8235 AF5ADC77907D394ABF82C7C720D00A71F8C3BD25167F68939C3A61BDE015F57C 15DE3C8E3C211B8C68E6889879062A07E0B6B894D46BB2E0DF34BAD3775FE4C9 4DA40F0218232F7441D78D12611F2438580F4CB4C1E75AEA59898E6056FACFBC 5451492F6E3570287BA00F4EC9DB9A5C2491229324AF55AA7D30AE5420461B9F CEC74BE8C9B9131659625749C7DB4AC76BCD602EC1F8E598C53CCA21826BB99D B448D11D4F03537A14A97D50DE9478DCAE1FEA581EFA9B0E89C7539C09D231DB 748C8329C68B5E9DFBD7319ADE1AD03DB62C8D515F62C37CD84A3155FB80FCA6 474FA2DA6E10139EEFE6D979E8EABE053EA6CE44F447F098485588C92DD71169 F859DA274DE1385BA200EB34E3E612E12B433EE3D8A865B688C38664A0BF64B5 86E0ED0988031BBEEE9817433A39A2EEEB31BF3BA541E52A834F0C227E8AF023 1CEDFAE842A8DFE5CF5300792DC580079B337FA6EC58E12772B08294E75B8332 C827647CBF35832E687FC840EC24825AA13323DA00B2BCD7747C258FE67A5D47 4F26738DDB11A1B0A747EBE8440FD0CE69AF5156FD001136FA1629A048AA1F11 C1C043BB4A938B8D110EE8295571BBE468743D4CD63B8A9FCD8CD5EAF7AE5A6D 92F571A8953AF7C9A94E7B3A2B5D475760F8DA457D8E971BEB4217B626982D43 921EB2495D43846EDC899656D68F10353250F6FD091653FB9DC28192AA6A3D67 257C05AE25B98B1AA908330EC7236D87D9C52CA25B57B5BD5E9268CE92079712 F78911193C69210E5D533CE127B18D98EBFD6A1B27EBF418E9625BB14B478B47 4880A9B11180CCD6C72DEBFB26CD814BA5A70BCDDB7DC75232F1C67BCAC346AE 48608E977D3EA87289F49D51E2EF9BB68803911AF5B377F50B9120A9C825CE10 467FE5351241C8D382BE8D72D4330CAF4A9B39CF1848A1858118CEBF10AA5548 945638D4512D33F0E5CFBFAC4449CEBD93F1F8FC9EAD36F1899A5113920BB91B F7D1EBBC5B1D4BAE4B8766DA0A19644BD7576D4F3E202E157B4C27116A4939AF E8603DD5C3F6D83DE489C04B358AD6B099A1C4D84296CDA43A30FC1DDF90862E 8BE3B80E3A369C8BB4E92A88D6064900D62E95DA803CECDD5290C2B17BB198DD 741E52F6F018CA007FC8641E5233E9C5BFA590E4934B43D375E7B81C4F825F5D DCEB827E5A275F0ACE7AD79CF960F83258A709EE0F43364F5D3BD9DAD16A0881 85B4A339A1FF47A4B99D0367B523C1E290C336E823494A182B221E1D98E29647 43BF0A6438047179D7C8349D99C5317E455666BACECEFE59EEBFA802BE644BAC E8BB4E75C45634D873E6AB3ECDAE27AA3A5E3EA9F940A0E9CA41FDEB43C0ADDF BDE41162E016804DD7565E7E1AE954366E047F3EEB7DB01AE9841D2A56210956 F98D6260643B184E4AD42D6624C42B9001B197685773786B161C2D6054DA48C1 3C15F17B3D2E4A7398385D3AE8D4EE186257848AD0CADBE2F75B4AFE76B688C6 D8EA280780ED1CB990BE38267F3B735066E943A915FA42F29BBEE5E6FC1B4C4D 6F2A674564C5821F57F486B1E9018CD8D17D1E1876ED97F1EA76CDB98F05D9E8 65035F0EDA2CC69C97C8155BF0ADA6A1B2918E185F5FF3A06EF5D1FD4EEDF7A5 9150A04092CBD78E06101F9A47780D6B8BE95BEF38387523BCA92E1DCD2AA0C7 9A264081FFE7590A1402B9AF14522519FF03E6E685E66547F2EE341D99FB971C 826CB8E08AAB90139D1B8D5C9099AFCDD6972FDBE96D3E61F8E05A8AA04CF0F0 92C51CB4E2DF5AEB638EAC13304F09221FC53D95FF5EB888F3148AE6E466E75F 028DCF215DB6CEA0FA674048C5718A5B76137613F0662D5307887B3B4E38674E DFEEB1280F8C8F27E3493D6A7F207F46B4BCE140BF755DD97C183692EA46034A BEB413D09EDD53D247D61BA648EDE7F9EDB327632AB44AAFA8B296E5E70B7876 8CD9F8430A40F33220E92B036D1288B3E014F3BB824FCA9E94B82717F8390EEB 33E9325ABC989C7B8F4EFADE04B06EA3B62DA015E0CA00529FB6FA0D99B01106 5BF61B53ECA3416342C78184F24FA7B6C3587FED766C5E0CD8F9A8F74636095F C500B8883073FC260BF19739373B2C7C7601BC40708931FE8431904683FDDBA4 8656D76F8657DE79F9D6FB1089EFD8CD2EF801DF4576AC25E6B139DD4B376904 A5F0F08AAE17025F7D253A312FB988EEF658F71BA27AC2A5B87B8F8AB72294F9 C4A70110C08EF78F5C32DBFA317C22A91205C75481DDC96CA8BC08C40CE6D3DC 93584F6F75F14110BCD5AF322749B8010522BCBF6BFBA4AE147F116C1402A8D9 1E508ED3D65743BC6EE2C8D4C88545E97286C01CDB0A6953D85348EB082E4069 CAED3F907312DCF53C921C46371B054086CBA983E7CE06C1CF00DC2E4DD80F27 6FE999834EDFF088FE277193B813E231160B5EFD05B456AE9B20F993B2A67D71 9A5C954785FE6A1EC900F764F208553E79192DCE9A8D547D13FB277D28F4E2C5 9C62401D3EE1DC2EAF220F1AAF84C79D6EED2B8DF7E31E53669270C7DB9BCF9F BE74329F292817D2EE2777096BACEC1D52D4098A935B262A2BAE58169730BF90 478D83E60CEFE7E249A39A6CF370B721CA1476246665775213B547D9E9F89BFA 1B58EE8B5F475A7FE4FF94B1646FF075198930700660C0FE16546637E1D80F87 C39381E4DE2379DB83C7A6A5908D523B3D7B9264B8973F78770297C0D31F4B77 BBE4380FF20B0C4909A0CA6141ECF11A2ED1DACBCCBA0E72DBEF51CD8E2D8384 7DC963394F52840C1D70B7ED99E2931CCC36C5AB5451B1529215943C934894AD C1883A86B8C7684ABB0C115625F2ED431252EC74BD4396567344AEADCDBE47D9 389C4F6BD94FD2A8A0374F84C636549974C3B99626AA7CE2A19D5C69117EE444 0811B2CDB5D684E181D1899E33DCF7508BEA8D28EF90659AFE8EA18B5BBE9FC4 2F30348FDA1DD26C216AF5B2B35BD658F6B2F8C42569D2708C69F89B154111E1 F0C98EDDE70C937CC306493FDE8517C1245B2DA6D1583ABE196029CD4CBC54F8 F474FB10937C9121E33CC960DBC1C04E94BD0609BBB0F1216893C7B188223AD6 E9CD2FFA0257B35FA98F9A557865D99E4EA3ECE43461FCEA49277BB4A1BAE648 3E7C022D064240DC00B48AEBF69BC9074E29AF869CB37F4790DC8C4628AEA7C0 D5B96F78A60639863B0C37ABE636A2C2612DF83E47FC5808AAFD014C281A464B CD0F6CCE1941B8D847D488E6D425A7563E1BEA0EA77EF9ED2A1A1080B8E4FE12 0B34DFAFD4F9C324DE3A6E61753F524AACF5352FF05B8D3B2845883286F8AF57 C1E2E0CCD66B06945EC60DEFFBAEACC7FEC78F3165C38785DC2BCD874FB1668C AC46BCD6E09EDC69DDBBDE37FC061014A6252B5D1D52CFF5C8BD65CC3F854686 5724BB70C371E235CB710E18BE356D019DA9B6B70E0A4560A54F0B7A3CA934F0 040A901E078BE86CA8F02E898D99CC62BF056A9CBA3BF3004C885D6419AC5C21 43CF5C84C67EFBA1BE3F645E21FB1BAA00B67464372F04AFA2D88AFB0CE82CE1 A158B26B35C5FA3CEA597C73DD5204AC2F4F2E37A7788B80EC14E9CEB2D3BBE3 178376E87BB14F7C9A75EAD1BE571C01804BC18B1BE136D11E66CDE40FEC9A03 ADF328B9A0A3CCA9421052EF6281E7B7C0DE1DBEC4BC4E64D5EF2226318A54AF 61F4EDEFE8448783E5E32C86DF12AE1B79F7125EBB1C99049C8E8638982FDF77 93E5B8AC73665AC45819B7FC6CFD9A57811C33D018C9AE779281AB249A149CE1 45A4DD65254D1F6ABD1F28123E86D3EEAFEBEB4F9560F0F7256CB1911EF9D1B6 410B48FFADC02E2C7CAC032579E75C369854435051555F99252F757C64A2EFC4 55A09A67342CB362C91BD3E0315B584568873E5377C84272C3995A8D5B1ADF70 A9C4F91972C1E5BB289D407D24FA7744D33FC6D92BDE47E04322DC7EB83B6BAA 442E93178F13036E40BAC6E20E8CF2920F8A1610FBEF3F865D5D177C21422B11 4F160DBF271595289089478E31F9991C85D651A4F2BFBE09933C63DFDCF84D27 34812C6952B2E33F650EACFB44713D635225F83A2C3E8421B2FA9D85C4E31952 FC9594239D48C2F73C3FF5596EFA852B68030AA7BA5577FCEB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMBX10 %!PS-AdobeFont-1.1: CMBX10 1.00B %%CreationDate: 1992 Feb 19 19:54:06 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.00B) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMBX10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Bold) readonly def /ItalicAngle 0 def /isFixedPitch false def end readonly def /FontName /CMBX10 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 46 /period put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 56 /eight put dup 66 /B put dup 67 /C put dup 69 /E put dup 70 /F put dup 71 /G put dup 73 /I put dup 75 /K put dup 78 /N put dup 79 /O put dup 80 /P put dup 82 /R put dup 83 /S put dup 84 /T put dup 85 /U put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 102 /f put dup 103 /g put dup 105 /i put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 118 /v put dup 119 /w put dup 120 /x put dup 121 /y put readonly def /FontBBox{-301 -250 1164 946}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 2BDBF16FBC7512FAA308A093FE5F00F963068B8B731A88D7740B0DDAED1B3F82 7DB9DFB4372D3935C286E39EE7AC9FB6A9B5CE4D2FAE1BC0E55AE02BFC464378 77B9F65C23E3BAB41EFAE344DDC9AB1B3CCBC0618290D83DC756F9D5BEFECB18 2DB0E39997F264D408BD076F65A50E7E94C9C88D849AB2E92005CFA316ACCD91 FF524AAD7262B10351C50EBAD08FB4CD55D2E369F6E836C82C591606E1E5C73F DE3FA3CAD272C67C6CBF43B66FE4B8677DAFEEA19288428D07FEB1F4001BAA68 7AAD6DDBE432714E799CFA49D8A1A128F32E8B280524BC8041F1E64ECE4053C4 9F0AEC699A75B827002E9F95826DB3F643338F858011008E338A899020962176 CF66A62E3AEF046D91C88C87DEB03CE6CCDF4FB651990F0E86D17409F121773D 6877DF0085DFB269A3C07AA6660419BD0F0EF3C53DA2318BA1860AB34E28BAC6 E82DDB1C43E5203AC9DF9277098F2E42C0F7BD03C6D90B629DE97730245B8E8E 8903B9225098079C55A37E4E59AE2A9E36B6349FA2C09BB1F5F4433E4EEFC75E 3F9830EB085E7E6FBE2666AC5A398C2DF228062ACF9FCA5656390A15837C4A99 EC3740D873CFEF2E248B44CA134693A782594DD0692B4DBF1F16C4CDECA692C4 0E44FDBEF704101118BC53575BF22731E7F7717934AD715AC33B5D3679B784C9 4046E6CD3C0AD80ED1F65626B14E33CFDA6EB2825DC444FA6209615BC08173FF 1805BDFCCA4B11F50D6BD483FD8639F9E8D0245B463D65A0F12C26C8A8EE2910 757696C3F13144D8EA5649816AAD61A949C3A723ABB585990593F20A35CD6B7E 0FA0AD8551CEE41F61924DC36A464A10A1B14C33FAFB04862E30C66C1BC55665 6D07D93B8C0D596E109EE2B1AAB479F7FAA35279ADB468A624BE26D527BFF5ED E067598E1B8B781EB59569E3D0D54D8EFAE0F3EDE26279776ABA15341E42E636 6E02817082BE6FE0B04249A4840C11F95F8ADEFF72173E9A5F2AB2F62C427E5B DC010E18641EAC906A5EF0F9BC2108062134A7F10956219C5847C0D82F0E8663 12D963E012DF0DD899911EC5D8096F80B49CA3444CF1294FBFAB57DFACC9D01C 46F3BA2F3D1C14EC30CBF83E5729F1C074D4F1665405C9AAFADB8BE41EEE43AA 16966E2C0CCC853C4C09F245ABFD4603C4AA55EADC0A59AA6E9F5895FAF3D3FA 83EDC6E2540417530AE7DDA8EF33DEB81444316FB3F93EF944D9FB06745BACE4 848398BEB747E58310BBA39C64E341185C82CB77E9D4439EC15BEFF1335F22F8 F036517C436225F4125ED67ACA7A84230D4E2B6CA713FD6B3CA54BEB540D4604 D58A8335BC20052440C4903786FE3E335E331CCE36A13F05F71126F680077AAD ECAE10CB7C057C2D55F384723D58EF3AAE83E9E0B39D6A522667CC5B3257DAFA AC1C3C981B9415967F7F4DECD492A52D35BA7B396815CECCA18146C96709CFF8 62E8552A78B12788A80F068ACBB0C15C55B19DCE5100BF525A59D34EBA5D3A13 73692ED7E2A03532244FA23261C8E5702629C7BE1F33A09F93AFBF3AC607A7F6 FD3D8B19098655B4DED97B03E39E463CAA9DD92C9048EBA53AA76B0BC5C48741 AE3010D21B329E9E6C77CDE3E7C23AAE0B2F5FDD647F031623497C468C4ADA7C A6ECEFC0828FF8214FC6C2605626514112B610FCDE6E3174912BD93E116537F1 5A51218896CB80229A42DC94734B633C98207B81F871FCAE1DA58E4E9F7F0AE6 318F68EC0C22047DF931BFE6838CF1325D3CDE7E16708C02FDA7F4B85C04B987 7C51C13CB4DB516EF9E98538208CFEA698F392BCFF13D221B7497195A0D094FC 9E72EDF09FCBAE6C6FDDEC0518E1CB8D826BDCD34C59FC1E82231670879CE2B9 3E7D5243FABF7CABD16B39C45BB7C243DC390DCF64F899F9537B14005EDDB0D7 F98E90BD5D778E3EFE2616E93D67F52670BB3F476E21ADBB8FCE74076B7457E0 4BBA0B06CEA5BB324B30C5F22BB65FA337951FF7F4345A961FDF86CB5FDB3B5C 19EC0187D603393B63186C84C83A82E55C33BD018456156C0CC12AE262F04F34 8BDFAB8210BA22E314EA054E364844F0BF03BE50426089EC7071143F51776C3D F19EE3CA885FBAE5E0D4A5334D0E957CFD25095B28726D663375530A635E4B8E 7C4743B67C00FB8A600F088414D8992ECDA0ACC39AB210921930855FBCC2E72B 7679DCDC16C306CBAC3C0663A120E5B34F7EE20EA7A172A1EE0D13C2960C12C8 1DB42ADEE49AB99BC309CFD51B5644CEB809BCEB184AF69E06BE34187EBF6F45 6E03911CF01F71E6355631E5A8D5CD2F3B6BF8B78FE5A3E69465E58CF73E5607 B0B18E8749626DD295BF9A8EEF2D106D587DD28F85833BC375462A944F0C5D6E 2B4C9795FF0B0F87E0ECE86CFC8D7D71D73F8FAB6D0BDCA8250D0E561CB64E84 8E1A67E3FF6F3C662158EFC73CBE917A024FF406B6FBE6739CB663D0C9922640 E5FAEF847679EA07ADCF51C43C25FBFF1EC5A742CC0303AD21E70FDFC7D47E8E 426BA2387436930557ED1A11712C9DDC1233AB4ACE7135CF296FD17A81EB3DBE 8F4087D8253365227A41364D01903377F2F0278BE0D7DF9943DED57976E6159B 58DDA467640451D54B35E682993A36718B141979811679C11D5F274542802CD6 CA4C437B6D4C239EE3692F55D3C3CC2B675E18668A8015EA23B6EDF8679114DD 89955A03E23849A40D2D6F29D27F9F7CBC12FC1AA470E554B9089ED64CFC75FB F4A1A3D8337A9D4F313854A2D9C050FF5E3072C65B15FDF82C202F68FB700C14 94CB0BEAC49177A2EC2371EA7AA515534385265044118C801A159351F7A1D71D 0EB50570DF4093E459D3B067823AA3F43F9E72BFB2F77AE2BDFBD917782C5406 03673D21EA2563994CC49D8A2A947808AEADDC87F23E92CF0C0F7B4AAE346C78 536FB8F4A91DCCA4817AB4EAC3EF585A8287A6A6A628E5F0A53C78140EB9FC5A EFB93F761D6ABF9EA3065590CD95903801BE9372B76F1ED79B75D71B9124E643 BA7B5F6BEC678D080058C0489943440360D8F100890F26196F82F88E61BFBF6B CC6907531DE5D5CA4B91E4F9D634A9DD0CD8DE6402E94C756F5904A5BC37A179 A9CC8CC6061ED3BCD51B08C746DBF5D8385AF7389AF4ECC4981D33ED4BC37ACF BD70E1474BAEFC098AA9BF862F153237B0D2EE97E604F8B41741BC38A0B2403C 92B238FE8A3C1456473B6AF6D8F9FD32421B61440B9209B1484F3276BFDABF24 570BAA113D0E06C146B8771F399FCD6906310B8ECEBABDBECD1BCF21EC03D053 60E500F91B4FBB5005D6F4DB331D1B534C15D5C5C04DE155F2808BA11A547E2D F4B6DC0A2A938EAC4612427490F92ECAF7103F55DFCECAD39E76B1355C8EC989 124A09FC9090192F78EDC8E54ECEA741BDBDB8EE8CAB4BA00CBFF9BF98818A65 37CFD9F4302BEC0A7D4E5D770546D77A95D6EE406BDEDC3CDAB1D229A6957474 DD11AFF676C19E4E328C133455152719E95026D4CE07C8DE5E939A69CB8C5D2B CC72BA63102A44B92235A1EBCC109CB8ECA42D9AEF2D7B95EABFD64F3EB225EF E4EBC3FB687CB00513E4014CE228FA3352DEE01A567014F375B77EA45B029451 D8A8E85CD7E3BC527A5E8C44707EDF2E1DE4D476682C609ECDACEE5B5D9284FE 2FCE66AC8900FA34510A458B2EF57CD2E87527CF4C88AD298083D44FCBAF9B98 882614B8B91639DDD9E3D1EDDDB2C137C85455992DC331D6117366B3CEDA8466 071842D5633D709467FD6E44F48C0FDB5528B0AAD26B3958D626569E14EFAA58 B592DBE04142D9B40377F8DF83920C7D979E78F5B63B54B8A478F4A73B5B5905 A06C80E750152AE7C89DC2BCC3A8A7EF592C43FD4624D295A761ED5AE94ABB29 C8B308E10EDB40ADFEABC931078D5C888A85C72451BFD587E73E0491EFBD80BE B0F1E6D9FA7F3DD52561A1D59133EC64BCF2212C82BE4AEE81CF3A20180D032A 267EFDE0D9237B58A48D0E70C92C0C0CC3C46801689118DB38938E7C88C71CFA 91935C2CD9DCC7ABE8F55C74BE28D669F2B51F31838C80ED20BF83291DE67F32 0BD507BD5F27A4C92CD5C2E2ACAC4545B4B62B6040C75F99021E62ACCADD7621 5334B605570F0EBAC7AC6E5E8E7968A8DF189DD604D1CA7D3020551B9189DBEE 079A6D1EE22FBBE1E43BF8D42BB8FB91DD3C1C63E10E99B53CF3135C4553D977 0A7456BE3ED2E2251AD5482F4F51083C8CE3DD2F9348FB6B78233EBB14550E61 E6C598AFED884A6DB3B8D7DF288BE2044CEA11F418EF3B2E6294D9C346564B1B 068C623B971047F0612ECB7157655A06958DACACAFACC0C14CD990FDBFE98C33 024F9D19F939E8A4B7CAE47E0C6F3BD57A2C798243EEDC60195F72DB7C6C13A5 E7968D7436E5962BE4413BC173A4310DB1D012AE618F4C446D40CC395365B7AA 6480A6764396B5093A02C88DB727823721B19CBEECAE261A6F150CDDF3CFEB40 4BBF329CB53724772B35F73DF6B0565A305F2C0BF144750E76624A0EA80786DD A7460E442086D9E463DF4781165AF8D64F5693039903BA8793E8947890823FDE A641E42C221FDCF6832F3744AA1A03717DB22776B34DD116B9AC17A841A3FB3E D627822C0BC41544EE864FA8BACED0FA8C1CB1D1576428269DD2226AEDE06CB9 E2EE674E00B5C43C60D6354340392A8A3A99DCBAE08C2A860AB4AB61C1B5FA27 37987CC398084B20C56C0F7A46305CB266A4128C800F12E5930201D5E7568453 B02D947517639E438DF3306F60F35CBEC1F74335F3F39E803BCE81ED306553C6 6FB6E25837CD62F7B3C573A9547D14998398DEE75CE4ECF0D59AA711AA7C0FA8 2D9F4F7157054C69EAFCAD5C2BD34DECE8411AE76F6140187B34F7159AEA9EAF BFF54D43B9569BF69DEE57D2B72B2FFD226DE355C83E4A2255EC3BF88A36CE9B 26674E8A200B2E8BFC959F8436E01B31483D142D318E221E5A40E637D4760E9A CA70407F57097E56465DD18464CFAE5FA02945D3EC6C45DB6472A2848EC98A66 301C63A761A9F68A23A84A9B01BCA1999AB48318D5556DE86B286127C2FFBFF8 EF6ADE0D8535FEDD63676CA4F2F50FAC64B620DBE16FA0A7BC9F964669ED7E35 B6A9B87C893D96B275FC589770AFE82CA0FC9A5968CD514B778C21F99DEB59C2 1B3F75AA347B576BAA32CF97C0EE9B422CAA852F900212166F0B9CF715F820DC FE222F55980C61F3E6ADB2D6E6268DCBDC2B74A011B41C260EFFE4BFA189D94C 6ABEDC2FC79B8F0807F123D1D928F85775DD2B281C50263E87880A0E60A015D7 3D39C6851D7BEF1E7E0626F4F2579DE80238B932AD5F578D5BFDD585AC3C5BA1 4D013A681B9131C473ED99A248A0B08283A4048B9E5B1A9495389F05E35B9C64 525884AAB12E5A8E058D2E5CF549B11BEB5D084A38CF6C10D393F6BE73D6AFB9 7B2BDDE416711F63A2A06F5ED3D3D065CC139F5392737F59801DC1A2F6B3E712 9EBDE49DD68F804EC60000F3A858182E92DE46DFC5CD036C85613FAEC9694DCF 96A2D8EA8FD5A497406713319809A919BC6185B82FB2BA05BE0D69B7FF2EAA8D 7448E5456C5F241D43517059117587BEF12511472050019422E6CBD2013DC2BE 5B0A099545DA84C8CE959718ACB689AE0DC3C9E96497A108732218BF8AE2BD56 5391BFF57D1F2831B9418AA5FE63608D31EE37361272BA669A7534213EBB09A3 0065C49E4A8EA4FF40181205D3109ACEBBDD8DC9D46F4560BB3250E43320E567 C76836DD711AEABA26BEF38A4244673D1ECD3F13A10C2C3404C823F45ADBEA56 3373BB5C4BCF08FB8F20A8D6E05561381D6ACA2178EC37DF744FFAF9E8E1C2FB A039F33BA035EAF2EB4D4F928274947A0D296454B3905B931C1A3822302A93FE D5131A8FB03BDAE23A1B5F0212F57292C4593480C139C56235696CDA7673B14F 465C951D2369E361E1A39DDC3492D9C5C663268FC6EFE6D6CD7E7CD68FDD996C CA3BC0E32FC249A57C095076A7142B57B48C4BD5C5D056083FE81080E8ECFC2B 87635AD52F0D6A52FDC4AA0029BB9662781E7B0271C9DCD0F1F88436C30E5C1A 3919F6BEC574E5B905E36665CE0EEC42CA0DC0ADED2D3A4707EFF4051F584CF3 321A4DCA23FE91484079FDA322C3421E1F1C9BB5C04338F4C6081426D479F29E 7E819C6C039F2C2FDD140DC5FB836BA352418600AB78ADE5BED20099698C821A D95DB2D024D995F3794021879225B8595E694ACAA2E889B205CDDCAAB4BD95C0 0BC24BC520C5DAD90EA6BBF4AB76310B98DFF30694AD15ABB7E0867D526636B7 EB1F8635A09D3F559EF332201EA72C2C0E752B64DE4CB063DA0E9CB1EA1CCC4A D6C5919D2D86F3870C852B39A61D290D6E64FF77AE711F9D5631553ED0EE0CF8 C430BDA64264EC7085DCAAEACBD2D5BD8CF74157793A1AD75D3DA2912B58BDB9 D47FA8355AE7893F2E316504AFF0787342BA28B5412C5B2C92FA1E1011D2227F 52700351C0660CD64240E6A380ED7E532FB9DAF37DDD353DAB7AA31F005DD9F8 3339C1EE6D184833619538C5FC0EB09CF161E8E0F7BDEF34ACDC2A7AA7DB91B6 6D70DD3C73BFF9CEE0BEF6D6EA61ACF225E8E3768368C638D2C38B81E234A24F 2822E61F61D2BAB5D42222AD8BDC75CE1C19459B4AAA49D8FB785CCA4C1779EE 33D7AB8159C41192AB4E5F6B9217171746BA9A3147D40231B32C6D8C8857ED2C A5E5653B2748E64AFAE309794DFCF61CE1BF97A7DA067E6EB443A41C68CFB47F 1FB598AC5B411F2145769D0EC1CFBEE2C4BD4036E8CE214C5B9A91BE8231B920 7CBA80DEB3029701E61C53DF812A8D4CE9ED206E044B38D0F0651BA2B0D57A65 4D5894C0E934634242420E015F34F24F91275F3B55C4CC76CA06CE07BD0C014D 771070FD248C2F836AE35E2F5BFA2B6EA04983C5B0804ECE338147BEE6BAF694 3CFE3E50410A29D4261FF9B3506B7BE83292D631232438B231BC45EAAF35AF60 CA264092C9A1F30E72EA7AC1A47BDEE830F2318A4F450B6FDCB610BEEB2B2415 4054F4B96962744C23A99EEC2946DD3C27C52268A8992061C746ADF78E34464C D0709A4EC946CA29557F2651B62D4DB764EB51AC8D5F6A9251C67C7358660B64 AEF35020BD35731EA2A3A221E678F222A7A18B35960BB11146AD42A3B7755432 4B8E399C9C73190D55DD532A42C806E61F0376D139733BF8C95AF47894F96C55 C13371B4C23DCE32A9D669F42F1EC62F5B7EDADE0E43E52AD35E64FC2B63419D 6962C4EFAE49EE0171469486A071E124FC152281D42907863987B3298CDAC70F 40227B7EB91B3D2500B5B52C67B0E1C00C00B0FD1C32A31A637488C196A45A68 0796214B5C292308A510AC9F9835829AFFF1D4F0F5070C76BB4D62C43C787EC9 64973716583C3E56CC26D9375AE76BA815E179527D41B08AD9A4799FF43ECFF8 504FF729101081E8297B63FD3E2E4A8A60C2187D56E80AD9BDF773C9DBE12022 D7EED3406C5461A0079837A953A5BD6D856E10CDA9DDCEA668E1A9EF548EAA7F 6323A2581C6F2C3CEFF7AA95990FBAF5CF3C470DB2103A8F613182C40EC2C25E 83FA8BC39B49E89FE2E0F88D1004EF1793D5F1D5FBD7D13CBB8E8314FD2271F5 172B4F0663471BB39112E022156BF755AFCE5539EEA584B38CE90110F5AF981D E38F3C9E0DB13471A69F190F01623CE560631E543D8DD4CD8BF7E8067E2B024D 7844BCB9367B9E9CDF6AB1E051AE7C6AF8BBF0279AB76F91E3096A9B596CD481 ABC06548BBF56D87D68CE8F73CFE1658015612D08B09F9D8A8A94224F3F32306 3A488EF579B9B01F5A20DEDB30461F036C56909A76FA24584B58D1E791DCAB19 A2B879D6CD08433F7B143C34E12E5E6A017FE5A3CED564851F500A2FEA591A73 1402ABA57032E377E88E7D5F7B7667356873639B6576A91EC449679D8A2CFF11 5F06B9EE2AE1F2BA2F2EBE3C679375FE9B552B3387B840DE370E5BCD403AA781 95747DC5B54070B274F63E4CC7CBEBEDECC026F1BA45E0815EA806168B4FCF4A 561B540AFEBF5F20E7900077D3B8B98E2B30542DDCCEF75D31523F6DBDC925DF A219AAEF9050643026C49FF555FA2D545ABCF0C0B583DE9096EF351817993010 A6775D37D4326001B6A514581E2CADF0E90A49D0FC594E77491EFE76166023AF F60B0EEEA9BB4FE37C94C79E4AC5089579CCD9401601BB88842A46B8A889A53C 5AF0DDFAA07309D3709E9B04808E52B65A85C85D4327A70981E43AEAAF8510E4 56633D257C343457094A59410F99ED970EF0650530C9ECF94F54847686F21E79 5E02D132E45F1F430CFC5D5DAD19D075BFAA38699EED9C73276EA7C381A03B1A 4162806EF6E13969EEA1FBC89966B0745BDE1114CE32DBED470F4751DEC36D38 BB1BE46E7E162660DDABA0A9B1EC983DCC7C914AFFE334D658FFF5064A01F6E7 E23D4955DB4AFD2EA0E371F003E68957915893DA2626780FD111EB90CEDB2BF5 CF596382A55F28C43A525E461C8AA9744DB5820AB314B0183B48D1F801509825 FE331F9736D366BB658CBDDF6A4564DA618DECF9CEE7EBFCF1544B1EA1746C51 2E5F7B3A2B2EFCE6C9DB26011523FDD6FA32FC3615CEF4B0739F659D03AB26C3 21728BED1BD965BCF894B654D352B12254F6B204B27611BDD82A2E2DE60CABD9 6EE36EB6D6642D7AB158F8AAE1697CA540C2889BDD9A245BA34440DB21EFF755 15F766B02FB5E6D80AA19982AB19D7F8DA443919848859B103F4EBA3496769AD 496B7E78B3ABD7A95C516854AA97A8F574788729BDD7E04E1D34B640F3080EEC 8F0D6EBD83C496015575FCF9B002BE9AA6BFB7CA9E7CB1B1753B0C95FC9D561B E47D7A5D5A537DA5970C8792488733A277A1AB68F849553BE06E053567E27E75 3AD0FF5A5E249AD9208BB26E948FC9BF854F36CFDE63C2C6EAF3AE98D7A09BCA 93A1E1BDB84617D011DA89F90B350F133F387E734E4B8B70D3F9A6959BCD0679 1914693A5493F7C764507DD95BB903FED1A13289E61AA7CF12DA6D015BCB1E9C 188A823B9B01BDB31F7BDA8000FD5F80FCF92D5A3C199319B6D6863C81C9E0FC A10BA14F42652CAED0F1F7D7642D2EFD4D92B3E781AC03BA7696A87A4553152A 3520C9ED887A3A2535AA2D1F0CEB1D1DAE0708CA0238DE36AC55C535AFABFCAD E30CA91A3A09ADDE7D26281310DB8466E18CA33B43DFBD0FADD4B83016680851 BA9C3CE282ED28F7A200F3FD675D0561FDA731D6AF89045EB5E1F8F9E6C4FE94 2F0FCC80D9BC10A1B6C884F36DE8ABA0BF508F5BD45893B25FDFA559106B067C DF54EB9A3063A15F4769C513B146C382A0AE5429D7C7A912F4A075FC69F58149 B463A4C05CA69B0BF543DE43A11FA9D0B198AF6CAD0743013FA5685EB29C51FB 1CDF0F25D849864B676348D46B843E5AA5F32B5DDC8FD1F583FA666384918A39 50B7643B713C2CF845999B33993CB0928193BDDA2CBCE235C6AE3568EC3B49F6 7A85264646A237758E16CEF056BA5582600D0E269A6F7325DFC3AB3E9D3093C1 352D2D38CF7D20E38297F391D0484B378AD4E52396261EC2DAC5FE88CD47FE05 1A5ACEA9251468753B2889AD6AD61B70821121DA16A547EA99BECA292D8B1EF8 0C3F7AEF8B881E2246F7BF6D1A90E9CA285E7B06423A7012EBD1B224DBA27FDA 2F8E96798705CBDFB1DB849C9376689F6BDE02B9121BA1D2BEB3D1C30B03597D BDC559122BF28348FD4CCB1F0B9761D38C210B8A216937FE2EABBE2E0AD84AC8 E8A18BB49DE6FCB61DC3F92D56A2E932F6F085A9C40F52F734FF3A19F783DF0E 230D2101AA11F06CF5FA6E6A6B7791A6C8B2610B3CB66355C468A7C9C3EAB192 6F8BEBABC4BAE93DC632638DB829DAB434D9E6AF218FCD4BE65BE2DF86AAAF31 E481F80359AFBE9126388BFAED6989F931483CD14FB2500E3233D5539BDE3736 BCBAA1900D8163F501B178C0C2548434C3F68388B19D376F89766123BB78A08C 70BE85F8EB6955C114C9A7C11CFEF270B8BAD791AF4F9B6AF09AD577C28D5758 7ABCB4583129FBEC5E8942BD62A39989731469A762EF902C14AD17E47364658F 6E8DD5726F160024D231440727F1C36448FF44C27BDCA082798AD41456B66957 6FABACD1FAF8311092DC73285C0C6FDD11E974087BF0A987CF8F33A7766C4A76 6A9EEBD28D7E36FCA5A7C97EDBC62360A960220C495709A4BBC799AE67EEAB44 D770D0F38D24E8186A96FBFDBACCFFC67BD72DEBF1A055ADB21CEA9098540C8A D3A2B200963F54BC889CBD250C38065E61588516A25D5E1C502C1835FCD32559 08B04FD75BC68C7A7F90F1EDBA6FBBD166EDEAECF4756CB716A583D2E1438D9A 679EAC8073EF23B44127922BB92227A57B61AD03E8C128EA41E8E91DD30EE885 CF46A93741DCA7F351C98F7EBD4934675F4753798615579B28D7367C65CF012A A960AA3F1D3A9C903EF47A38ACC2434C47E2006F189C10BF5978D7E4978F18AF 382D0A5FB3708A0392A8A87B2FD8C20171DE23BA0C14BE83EB472DF4CC58988F B0D8959109D88C5EA5DF0BF962109263197A51738A00D1A709F3770C691D5E6C F66EDF8F2FA2629F59788B7D811083A8071E6E4D7185117661B366EF5964AC8A AED0F515A063728089FAD3D7586DFB85F0ADBA08517F3C434409300F74DB672E 6DF6BE832D1564C06988DC1469219A24F0233F38C84D721990353B90B2C0EDE7 9F0C3A540D14FA1B7F1CB74936A7B88321CC841CAB20A1E7A92273596A82496E D2401D7456AF4234BB36F7819232C4AB06DBE3F97542CEC05B38B6546269B791 ED2AF1DCB4061D7791F694EE1CCF051590C7F26EE59355DB084E5F609B928A58 B954BCA3E7463BFE064BB7B3DB09773DF3F0ABAEA53AD56F98D7F7BA263304CB AF3390CEF90555746B797084CC0C4996B4F30F54563298A69FBB4013184A1F35 969FF96AE7B3BB247709CB2320A0AD5D619A3E31F49F4CBD03B69C56098A83B3 E4D837861386A976DDFB2DA2A9472F1559943B9794B761898E7375FB2C55E3B5 E605C02952C46F537B2BBFA0B3B357340704448363FC4F20F0245A746E9A18F2 08425531F826E8FCA78866F0402F6D755B39574F57BFFDBB321D435502E0FB60 FBA64BF650EDF8033A246D8544E31C373DB2F250AE2BC5233B85A1290511E588 512035A383C14A2B27363E7C0B2E4DEB8E780FA2A4440CB653CEDF4BDA90945A 4AE0D6343D1B646934DA14505B99E522EE55E02E700B018483E6D10B3E8A6F2D 1001021FB17BDEA02A213BE8A3E33D6200213FDA458D25E8713C18B4EC7E4C6F 98DD981863188AB4EF4846717B770FA9D732C0388C411A0C393713CB4B1549AD 1494D73C958F4DE348C25AF9F845535F111AB37A31874926BAD2ABAF1C9FA2D8 EF4E1EC33232225457B465ECDB466F89BC9DD2A9E82EA7CD2E9BD90403258147 F3F094D3B7F63B576DCFF5E324C82C6801235D0DF850CC6FF7A070EC92456321 BBF4175403ADE97D1F62FD6B1358B7DE7473FF03959C0DD8731D7367D173DA56 170A2F3677A3CBBF9F4D351500860FA504F55FBA655ED5F79AE0E404FC5EA41D BE1334B65CD93468D3B365EF3406777B6CDEB5454945798E6B1FFDA470B089F7 3222BFD4002B7F1E8711E4D1865529C2045B7FD98069CD0674AC9DBC7F31C277 EB88F8BDA01AB9D67611B078D3A72083B6D92F8E96105C15844139424361A983 4B5CD4BE172478E1320D008E73CEB0B5D7DD07C65EAA231B884F822E613ED7C0 A3E24E90BCB4DD0E324A38D133A45704E818ECAFE0C59E420FF122CC71D6E96A A5D5EDD9DBE33296CE6AF62D797F558B884960250F13D11F6DB57BB264A12D89 88856C6B73202A54E9FDFFB7E3FA7E81B21C734B42B44BF2BBA5E8046FDD40FD 923A00084CC2111107D1B8186CD8287FFE1F26993F7D650D73D3A06C93B4B22C 4C64709E8D803BB9A8A3500791260AA785DCF3300E7BE08CAFCBE64A85711461 77543E4117B15B1215DBBAFB64CD4D90B606E42DE9EEA813884CDF19A9AE563D 4D506725A2CEB6D65452E8862D0EAF37AE2D799B7C959D00AFA2AE8C0DC184F5 56780C5EBC3E8AD7D720DA703529CD555CD25491ACA3FE8D9578B07E75FD0F44 98E43F871FCAD2A3F3EDA423A9A2C41B8C388234C9BB7A7D78AF6E5C74B56A42 3D8D31EAAFC3CC1BEB1967859EB33DCE2A51B88A9B5F5B85D13C619BEC3F6CC9 05F02C7C850A341B4B9B4DF952AA66DAB17308CD46913DAC7496CF31A30BB235 997E8D718C6CC2EBD503E131CE11664F4EBF5A0AC3AC0C3BFB2EA6C221AFC902 ABE0DCA95B14F26C7CA969199EE72FB6D2DFF8635703C8EF31C1A934D6BB9164 27C198F43AE7A54E6869E939DE2DBB183766D9F90C7C270EEE0854C72D296A3B 10174961017318135CA16F54C2BB2C422DDA5F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMSY8 %!PS-AdobeFont-1.1: CMSY8 1.0 %%CreationDate: 1991 Aug 15 07:22:10 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.0) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMSY8) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle -14.035 def /isFixedPitch false def end readonly def /FontName /CMSY8 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 3 /asteriskmath put readonly def /FontBBox{-30 -955 1185 779}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052F09F9C8ADE9D907C058B87E9B6964 7D53359E51216774A4EAA1E2B58EC3176BD1184A633B951372B4198D4E8C5EF4 A213ACB58AA0A658908035BF2ED8531779838A960DFE2B27EA49C37156989C85 E21B3ABF72E39A89232CD9F4237FC80C9E64E8425AA3BEF7DED60B122A52922A 221A37D9A807DD01161779DDE7D5FC1B2109839E5B52DFBB2A7C1B5D8E7E8AA0 5B10EA43D6A8ED61AF5B23D49920D8F79DAB6A59062134D84AC0100187A6CD1F 80F5DDD9D222ACB1C23326A7656A635C4A241CCD32CBFDF8363206B8AA36E107 1477F5496111E055C7491002AFF272E46ECC46422F0380D093284870022523FB DA1716CC4F2E2CCAD5F173FCBE6EDDB874AD255CD5E5C0F86214393FCB5F5C20 9C3C2BB5886E36FC3CCC21483C3AC193485A46E9D22BD7201894E4D45ADD9BF1 CC5CF6A5010B5654AC0BE0DA903DB563B13840BA3015F72E51E3BC80156388BA F83C7D393392BCBC227771CDCB976E93302531886DDA73EBC9178917EFD0C20B 133F1E59AA9B568B69ECCFC0900517036FE3D4C09BBFD937BC5A9C0B89894A8F 63BCCA3746BA056D1B408B16E976D7BAA7D0F7693814ECF52D90BDB3398CF007 CAD14DF246B4D1886070D41A28110F88C9D3EB1F30B1823E0EAA1A35733AD321 E6338D62C26AB6FCD4BBB703248CD7C5CEE83E0167A63F89ACC9D09117C4D017 E773665CB7FA79D22231C8F858735B554E2ED612A436D299491FD31F810F202C C865B87083F980C8DF6A3DD43D437617A69D3E58FFE85F106F7E7F6E50D4D25E 328F7A76B73078B3604C51CCDEAEFA74ADFB9A6C3A5A0EBDCFB578CCBC3553F8 44D4B2853DC7C8415AE3174A4C2209F4107C23000ECC343882C5E2ECA42D8B33 F4846EB85076770BD7E5AF795E1EEEFDC5F0229761DE6BA728FA78549D6E31AC 55ECFE0C64351DCC357F619E3771692B7DF8FFD7FAF48B4299C702F866374FDC 696E83BF09BDB1C40B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMR12 %!PS-AdobeFont-1.1: CMR12 1.0 %%CreationDate: 1991 Aug 20 16:38:05 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.0) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMR12) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle 0 def /isFixedPitch false def end readonly def /FontName /CMR12 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 48 /zero put dup 50 /two put dup 51 /three put dup 74 /J put dup 80 /P put dup 87 /W put dup 97 /a put dup 99 /c put dup 101 /e put dup 105 /i put dup 108 /l put dup 109 /m put dup 110 /n put dup 114 /r put dup 117 /u put dup 121 /y put readonly def /FontBBox{-34 -251 988 750}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 2BDBF16FBC7512FAA308A093FE5CF4E9D2405B169CD5365D6ECED5D768D66D6C 68618B8C482B341F8CA38E9BB9BAFCFAAD9C2F3FD033B62690986ED43D9C9361 3645B82392D5CAE11A7CB49D7E2E82DCD485CBA04C77322EB2E6A79D73DC194E 59C120A2DABB9BF72E2CF256DD6EB54EECBA588101ABD933B57CE8A3A0D16B28 51D7494F73096DF53BDC66BBF896B587DF9643317D5F610CD9088F9849126F23 DDE030F7B277DD99055C8B119CAE9C99158AC4E150CDFC2C66ED92EBB4CC092A AA078CE16247A1335AD332DAA950D20395A7384C33FF72EAA31A5B89766E635F 45C4C068AD7EE867398F0381B07CB94D29FF097D59FF9961D195A948E3D87C31 821E9295A56D21875B41988F7A16A1587050C3C71B4E4355BB37F255D6B237CE 96F25467F70FA19E0F85785FF49068949CCC79F2F8AE57D5F79BB9C5CF5EED5D 9857B9967D9B96CDCF73D5D65FF75AFABB66734018BAE264597220C89FD17379 26764A9302D078B4EB0E29178C878FD61007EEA2DDB119AE88C57ECFEF4B71E4 140A34951DDC3568A84CC92371A789021A103A1A347050FDA6ECF7903F67D213 1D0C7C474A9053866E9C88E65E6932BA87A73686EAB0019389F84D159809C498 1E7A30ED942EB211B00DBFF5BCC720F4E276C3339B31B6EABBB078430E6A09BB 377D3061A20B1EB98796B8607EECBC699445EAA866C38E02DF59F5EDD378303A 0733B90E7835C0AAF32BA04F1566D8161EA89CD4D14DDB953F8B910BFC8A7F03 5020F55EF8FC2640ADADA156F6CF8F2EB6610F7EE8874A26CBE7CD154469B9F4 ED76886B3FB679FFDEB59BB6C55AF7087BA48B75EE2FB374B19BCC421A963E15 FE05ECAAF9EECDF4B2715010A320102E6F8CCAA342FA11532671CEBE01C1B982 4B1CF704E817814FF9C921A7DF8CB8898733795DC5382F10417D349D3A7D24B7 E093F2E23BA2C1EE337477E6D51957FEE9206BF92BA12FE5ED4056C4FAB42BCB B9E96E640C88DB1810A0BEC0F3E9F4BF00E642ACEBEF5781F8E57F9B9AF15B57 53572D8E00BEB804C5B7587FF816874FCEE012EE5CCF317AE25E9B3A801A805C 5EA4B24EFB92E54CF85F048BE9DF31C77AB6132EBAC1C124EF5C0DA0719EE902 BFB550602C5A8EA7E31F72207161530AE5DE53624E60A6383DE04E085E20E328 2D3B8009E90861D7309BCAD915694CC31FEABA2FB3DFE8E2C61DC65AB2FEDE93 02327D5B24B0537DA1B1299C9F8D03D6A10055CE522CE067381FFCD4D1E3E173 21CC73B94423D2D44E035E1CDB53846964AD93EB1EB99E6BF51167EFF6A4E33E 71277273918B7F4FCCE3796ACC9725B293CDBF517885C38D66DDDF8FE9D5C98F 771EB2DE9C0993E84AC0486F9361270031C246BBCC721E2D872E45230BFE7B8A 1817A8FAB0C82C2A5B002C9208FD316333C451D59243D312193F38FE79731FA2 BD4FE2DD6A3E4B4FFAABE064F8D2D97628C9FB2428BAAEC5E2AEA4BB1D609B85 2394287D1AA46D8E4B4018A4877F03F6A9E40277EA94C462404537694208AE33 45D7AB349A1916683BFD35479190FDB8E8E1E5F4E5C61774A1D966928E7AE59C 301D1C7D41DB96A94C23F41A650257297F87E726155BE35E84BE5554D97137E6 C0DB7D48CC0B5D6A78428A63A3E594ED30A6F33D6FACD6CD77F69EB2AEDD6767 403F5069AFB93BA02E40A13E9A5899EB68B5FBFB655610CE2FFFD76F0C7C6595 0D8F7BAF05232E793BA4C8C0A8AAA682DFE3E4F4189F9F9EF5785CCFDEE5CA8D E5685C89B52AC73837BC5C6712E4B8480D7EBAD4F54755F8BF549F0B6DEB32BF 7B8A98295BD62F14921F80D98C79BFDBBC84C6EBCDD598B54BD790925C72B0EF 1AE6086B1ACCAE8F9BF52C0AF6DD5FC38190A1457CEEE48DC5193DD6EA1A526F 3EE4CFB5E5EF88A803563D69A720ABFD9FB3AA77CEC8E29F49A9BFADEBA19588 01D88B45D250106F673D7A3F42F0F2539B28D0E6C57DA35B38335DD112CFE6BA D78289AD0B51D642BA212114C64432B8CD80D899FB60BEC1B2887E8AB5E48C58 91D0D4D559ED781196599006B2E3846D836D80DE176660DD8C9ACCD72883B2B4 77D9B991777561D77975456E8D4A7E2ED85FCC0884EB9553A7CD37AB92CE1AA8 009895B4AC7B00DF43FFBA9D96EC702914FFEF294C865B63B2498A54C97F1144 7CBD4DC79C8BD47984A4562F8A6AC40D8DE955EFEFCF78BC66CA604C96161251 420096A2264D7E22B8A3869839FBE8C8CA10082B0253E205500E7F47A03F027A C352CC0FB38F71AAE11F452A3560C63C844018619594C9DB2238162C23083DA6 22A2D92896B83272BE70340A93A08E15834C338077D933AF074372E4B2156190 992182D6AF62272AF7A9C80573D40E5BCD630AECA44FF51531F0028D8F38C91C 0421996D04B5B8FF3FC6435698633A37A84D2C39DF003CB018596F81639B3E86 93CD0F84B1934BAB24DCD0BBB3917E0B44FD109DFC2E437B0B79D37EC708BE69 09DA3B6B9F007B793000AD17A7D351417B6F26E02AD4A6F8BFE1A8C4317F8318 910C5024C8E2C03AAB963055C22D17764C9CEC7DA42FCFBC586DF4F27CB97EDF 91E4533A3151FBCABBF65E59D990719D9282F3CA8AA92D63E3ADDE7A50490CE6 FB007A2A55050A249D0F8A9072F46C99E07FAD9D5F4FC3C8C8B22F6303A1F66A 2F6F1309A9634760C3FE022D0F409D8CA59708FF8E1B719D93385CF45DBF0163 07A656241714503F4B36710123A458BA644307D21FB127E6E5C58BF02B61EDAF EB501080C38A3A8FF84F44B89FF04D247A332B271641B51A7E144437C3061D27 7696FAC42105CB57EF8A9CF333C47A421DC932A6B43D9CCEF85A3411ED5864F9 B298D46E912BBD32B6786E022BAF2ADC7AB7F8BB0C6620CC3214F537D5566B56 3B231615570AF593EE0549761DE550811271E1119CC8D243CD0471A77E7E0EED D8EF19FAE8BF32CAA225305222253C92C38DF2DDDD7AAE446D5458149A190122 A0191DF1015F768D48F3D2178E0C23E1F10317E80302466303A45615A3407436 DA93795EFAA90933030021B6AF5E51D192A3DEB83BBA00736D34F285018980E7 7ED75E6A08CD036B7E5C23C26A2E830B3C80D6CC389D9CD1B2771A87DE65F364 724E7D38003ED421540C5913F7B9011A60FAAF2B8A1A5F23ED9C52B1E109FC76 5C7B5C32328DF9F5568559B6ABFA3027735330B018A1608420FC7ED24A2E15CE 1FFD450A6F30A96B2DFFB53BD7ED444082A11B56291BB7D4314F341BA50E7D3D F9B3EE0EA5644811868C03108E15A6C7205DE872E64E2EE1236B93FC2F67FC40 3BD90F9D5F701AC1341DC7B4CA23551EAE479E1E157198A9F9D769CA701C2F81 0F6DEA36D65978BAD6982DDD54064D3CA2EAC8A92D91C67CFEF3031133D30516 544A4C047D0FAEB451C84DE160382877F7CED5BAE8B0E35B11CBD630999CF4C3 DD0563183FE38F2184BB79A1ED8D8CC73F69840672CCA0691EEFEBFBFD7FE954 ED86CC20598988A79B18766DC512F900775F2822268948701F4CFEF2E401F59C 7F256EFCBE807B84ABE4897D2AF421A1414DDE91124C371DC0A3353B0101F4F7 B1C420A1E72FD9264C626749838A3B708280E7920272DEEF0AA8DA45E0770540 7E86D3C94486AFE3AF466912059792DF482CD577F5C3787262E3ACE8DC9DFE54 96B92F4B030C162FB06E5F27B1CF0AED009EEADCA116694B39AB4EE9524ABFD9 617E98ED071E7E73E7F44005CA35363BD0241BAF45DFC2E4F667A21F9E9BF405 B8E36DEAC34CAF7FA7A6CF3C8BB6AB36F95486824D732818BFAAD9BBA4D455DF E36539DB08E528CA3888C1C59A2A85E0A2BA4CD7BF5C3543B65512BDB08FC111 A2F6A057955C6F707EA439C2AC6C4FB384FFBA470D94EB2487E9801A6AD0B852 557344D11B32B75400EA521DAE97403E8944C3F53E8200CCA04025633B999B82 443115C1FEC7B23A88C01B6CDDF535D284641D2907E108EDD2DF8219B08FCE78 13BBAC3F7AF36ED59F7749B402731F5B5C45517794349397506D893133AC20FA 9638418357ED6BCFBB08D8397661A3B6769A2B3F9A3884977197EACAA0B79F69 7FA986A578B631B64D33AC14946654E88165BD3650CBA76DAF505353AA5903E0 25D21068E4B22A9225A22DD8B1C543E24E3C899F8A23326BA8E47725F0566DE4 F8339574973D0E332853E558CEDB98EDB1E5974070BA39F770A206753178048A 63FD85278038789231B253D8AA40DFBF9F9BD4C6B7AD7004411947DD57ED4136 27746F0D7FC2EDEA705DAD77A20B7DA96312CEA8FDA0F0BB2372E6F3C40B6A21 0877D53D9CBF2EE9655C72D71F98268DF6F5DAF50992E161B2AE95BC12C395BF 2514307964F9A0E0F2F9506E9CDDE5EC3E99B73C3BAC69A0B57FA2A326D3BDEB 3781BE127BEF9D3F5884F21B91491762C545823F756301D0969E74390361D073 C370C66841F77D1D24E00B582DF2AEBD4E100252248C164DEBFAD4BDEEEF8DC0 188C3ED0AE0F97BD176527B68E7D2A7955AA0675A639A42BF5881C282A03B5D9 BEE37474797FFE8B4A1DF9623D7EBFBC7DEEA4AD3F1166547B3F32AF680B9500 1C86D08B4626E26E5C77B1AC7B0CEAC99BF6EED52519BEB561FEE2CB0FE9576C B194B32896B832B4388841C92A80685DB51D72274938 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont %%BeginFont: CMR17 %!PS-AdobeFont-1.1: CMR17 1.0 %%CreationDate: 1991 Aug 20 16:38:24 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.0) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMR17) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle 0 def /isFixedPitch false def end readonly def /FontName /CMR17 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 67 /C put dup 70 /F put dup 71 /G put dup 73 /I put dup 79 /O put dup 81 /Q put dup 83 /S put dup 84 /T put dup 97 /a put dup 99 /c put dup 100 /d put dup 101 /e put dup 105 /i put dup 107 /k put dup 114 /r put dup 116 /t put dup 117 /u put readonly def /FontBBox{-33 -250 945 749}readonly def currentdict end currentfile eexec D9D66F633B846A97B686A97E45A3D0AA052A014267B7904EB3C0D3BD0B83D891 016CA6CA4B712ADEB258FAAB9A130EE605E61F77FC1B738ABC7C51CD46EF8171 9098D5FEE67660E69A7AB91B58F29A4D79E57022F783EB0FBBB6D4F4EC35014F D2DECBA99459A4C59DF0C6EBA150284454E707DC2100C15B76B4C19B84363758 469A6C558785B226332152109871A9883487DD7710949204DDCF837E6A8708B8 2BDBF16FBC7512FAA308A093FE5F075EA0A10A15B0ED05D5039DA41B32B16E95 A3CE9725A429B35BAD796912FC328E3A28F96FCADA20A598E247755E7E7FF801 BDB00E9B9B086BDBE6EDCF841A3EAFC6F5284FED3C634085BA4EE0FC6A026E96 96D55575481B007BF93CA452EE3F71D83FAAB3D9DEDD2A8F96C5840EAE5BE5DC 9322E81DFF5E250DEB386E12A49FC9FBF9B4C25C3283F3CEA74B8278A1B09DA7 E9AE4FBAAF23EDF5A3E07D39385D521547C3AAAB8EB70549756EBA8EF445AF4A 497CA924ACCC3DD5456F8E2C7E36946A5BF14E2E959895F7C94F49137256BE46 4A238684D52792234869EAE1A6D8ADF4E138B79472D2A90A6CA99E2394CC20CD 3841733046175B20CEBE372327BF13428EED6A3E2FDF84C2DBA4B0AD584EE9DF B51828D3B8F385846158C29C9AC3496CB9692DD10219697B2ED4D425C3957FD8 C4600D76E045C561216EF05D38177243C314877A69A1C22E3BEC611A2EE5A216 9B7C264CF6D1839DBBD78A40610F2C0D7C2FE09FFA9822FF55035AD52546970F 83EED2D30EABB1F303091EBC11A5379B12BB3F405E371519A53EA9D66174ED25 A2E55463EC71A97BE4C04B39E68112956117C8252DB6FB14AB64534B4BCD568B 246DB833982B38CDE7268BBF74B6B0C18091E1B1F87D32D66F4DD023D1F10D2A 7736A960F72AC01F733A11023832CD68FB6288A5977743F781214D8FA9C0C3F7 80001321D4397771F728FD9EE57CFE7D9192B887EC883EB1505068261DC40089 7B7D2820F06515CD74513521F6397FEAB3AD3572D9A8269430E407E357422461 1785FC2782047F4C0339D79B16862D939F3A37F78E4E2174E4FBF132539CB760 207999FF86F6A3EBE48EB0A1CA635450FDEEF79EB16D853F3BF4B4156F735FAF A48459456EC1B4D72FF323BEC9D55791F10081E94A83ECDDEE2A3911BE6690D1 2BEDC34E7FB692B36A078DF52E761DA5BCDFFE8C6A64B6E6C633D4656CDB0CEC 198EC18DDD3031695D98888F72AEECD5CFE83260790707C3B471C17575127E2B 4BBAB487E96CEB7AA9346CB3B0C577D55226E44493EA8325E60BA821D9A6A9EE 0F81F3B3B43F30717553D92FE2F68BDEAF47C2C333F2889BA57F977A25424887 F947351DA7609E7D8D22C4F82415A63B83984B040C4C5944C6E36BD9898B0B18 F901B49A3FC5DA8D8DDC72210897B71E4D7DF418A7880B9B174B2A4F328DA7C8 FAD975E5657AF208A8381491BB159576CA96B54D235E6DB1FB320202DE6FE50D 7222DF9D4B745AAA1DC99D233ACEA2308CA87B7672F3057D3AAA3B8EA845F953 404C98E0985BA0BC8B6821F0089F6DB6BADD771406884672C9CEEE3E3136A32A A9DB459E705E041D98756ECB474D11BE8BD55ACCAB3C167B1EA11B7ED5AE6694 91197E9FB37E6AF997D1FF15B186505830789C19821DE5DA62FA888CC2C5AFD3 C0A243E39C48B98F837C87730BBB9A03E8BBDFE260DEB47822BBEA03C0F21FEA B644B1CDD2AEF52E5F2494676DEDEACD9ED89E2FB5FB5FFD14661A8701680FDE F27E716E1FB901227058A4C5C7CCCF9132D643409B46D6AC86828DF63FD40B8A 5D22F0D9B6F00216E3BA318C5B9EFDAD04FD6B1677A5C2A3AB503A436F6A2F55 EE37E9643259976A0A8425ABF863D4C66257E086B6F7811195FC8B20103C40C5 0329309E5C45253372762CA78ADF69AA56B3D642B2D5EAA092369865A2BCBB34 00E9924E31833320B636719A514B977F00261C4F782F63E3CED4B7AB7F58A685 6E529975417F43F801C3205449D4B95B2B1FEFBF1442F33B8A570E30350DB2D2 71CD7E333032367CF335B789D81202E1FE3CEA11382E5BCE751C51396A99FF9F 085D4FBF967AC8452EE633CF741011609A2DF3EB88A35DC3D8B47D1FBDAA8FAA 01EB756739B6AF9462DA13B3CD4DF3DDEE6E682B6500F2BDB6540E7EF295BE67 99D2F86B5A1EC89F20D88DF00962606E0BA15A6BFC772C72E50D4D67DC4B71EF A94FF2339E9377AF27A92BB8B9011338410D30CBCA33C5C90D22BC6C64153708 8EECF6CD2AB2143C6E19F865B11B561B28E5BD2A9271CEB846A588BC34784074 90757581B8DC08CC8D75184991532E9F0D3EA2A142213F0EB8DE2BFEA732B77C 4D854AF02B92AB046123EA0F96544A241BDAFB02B2A9095C342945468C50903D 8E6E8EAE6E72B8F4946DE02DAB91864B53359AE741F095A9D118C42DAD62BC01 DFBB386111F9BFD37B0E8BF85708EEB1B39CE3935288197A5658D74AF4B0E5BA AB39E1B33C8C7021680647E6298B5976C5E7E5A41C478A07A6DF0227630FD1B1 FB3E5E671177D2654598F3EB5393202CE28559AEABD64E343A18AB1664472080 6626EA9B789FC0BB90FA1977514D3C3848163C7CFBCFEBDE0F62C184F83955E4 9306CBE4715809D6789D0A65522229E6D08A139624932EA705229EF99E243DED E125C95EB549BBB9D91B68CD1438EB23BAD1C41762973DC781F324672C3AF537 706A63CBA3090575530CBE5ADA9658C8AB664E475D3F4E83308E82E256A7AD95 E323BB6A94CC0ED154304EAE95EC4175AA24E44C2257B471F14CA9CB6F57BB4D 445E256BA592017F89D45221D3B33A2617C680F5E5292AD80B62DF74195F0FD5 751BCAA8C8D62E0F81AAEE4FCB75A2E12C9C396BB5AD47207ED46FD39C2F03C0 7BE1A50F88BAAA4F639A5DB9807524DED9AEB5FDD9853308CAE5CCCA1D686F7B 65F742D0AD1784A1BF7464373ED630D9DFFD90DE75D664087BED3FB64002FC09 D608A8FB8BEFB9826A20616FA062B878DD536A6698A16107C2BAEAD4DC4A1F9A 762C8BED80715A1CB9280B59C8A239F93817DBAFB78877AB8EBE6D0E06CD47D5 40DA9F1586B227F8F0ABDBDCD2CC96EB61021726CA1C64F06FE173FDE1BFEF53 FE922E4EF539F2F608C745DCFEF232F9E31E4422CC7D234B4199570EEE1A851A 48CB3C0548E5EC973642C70F2341CE45CE1CEDFF5C9CF52E6CE5AE642F20FC76 42FF3636B821A9D200D4917E649C851B79BB6DB61B7BC1FA5DF3574AFAEDB447 F67057131C96B7453F879D0FE8AF4D5291FA4037C4C76CA7BD6C0D9181EE09AA 5C60C008E8A7C4D15748CA6F6FD2B7C6A55CBD816409299616FD4153EF63E121 BDE077D2AF5D2FAEE8B6D6004EB569B398A3ADEE957B2003F524BA8DC248ACC3 9A813584955514610F5ED6CE54ECB06FEAE5638EE92AEDF446D23CB3F7F3F580 B11145C03146D73FA56920AC873813CA164089B9A6C19BAE482B8C94726EAE04 2805019DFF8E8F648FAA35EC7DB1AE3DDAC526ACE937F1DEB3E165699BA5879C 3703AF8BB30CE970E961B253024F82E73356B778BA2B52EF8ED83840E58F35E9 2C3864F74BB81FA96462393371827A3A495F7863B511080A6BEF0F358FC74C3A B69FE66AB8883E2146B42F2B3830F81A320C95CA68A39D7F477E44DBD8E2479B 56D0F614BBE4CC4601C878C8062902FE58978C9C5AD39A6D1F994ED4D0924522 25B011B5FBB553DAAD10CF3A6E26D8DD05F4844028D27DA0838BF0B2BF1B911B 7767E654A897D1C8CA4CAF8350986E853539561E927BC1A080AC4B469B78ED39 A69B5DC9B0D574BDF455EFC6BFA57C51052EBE883EBA245C8CCC570937436480 68BCD6219DB49CD850B41F40829C6F371A8E30249339229560425E452648DC34 FB7F26F92B75C9041F39F535B6755C957008118C634EE6D9109724F0AB20394C 15EDDE5EBA22D8C2FB8ECD7DF64213489A9BE1C7D7349A7564698908F31D40FD 801744BB39011DD455DB7E8D5DC9132FBF394307B6CEF020126C27D09C3B8A94 A48F670A18629AF96288C661284F0255A738E5878D18C0935E5C8979AF0DB055 E40A1E1B43C54743CD0C580CC8816FA290F5607580701433E7D3E478790E601E 3C9FD14BBE364AF5B74709EE37917F2B951A8CE286168981D1C7F47373E2F890 48EE22E3DD583A4FCCF20C5EDF82913664C528AC123F605600505D2A5081EBEB CD70C429F653753449900BD5CFDC00DCDAFFD97DE63002E1501799B7DBD221AE D0CD6AD33125FF1FAF59CF8B4D5E198BCA1C979440C2F9DE7D6C6AD842CA772E 2D8F9F65B1DC63CC3C491ED6AB32E9A215B0A769B44EA1CAC6CFA0E1510DE47E C212486745C14DF4E25EF7BBF691399099B7784329906133CC5196E775FB118E 7B7B0874E7ED63D09BDF212AC3539D13AF2502D417C91D8B32BD547E1D9A6A83 DCFEB61AB6685EF508C4C2501C2595E34ABA0591E6EBBA8CC280EFF9A8E98B41 11B7719DAF2D47900127DDFE0C8E53175F7A47189AFD3D2EB44A7999D7121F44 14A52FDEEC074C08CAF1DAE24CC9409E49E14D5FEE182733A7034293193BEBF7 DD577E6BF8849F541785363CA81DADDCC5F647FB2F9439E6A235E191D56D267C 75BD4FB3A4DB698C89D01E0F2FC151C5CE77C78ABF166532E506AFDF95991554 9E0A103B5059038358CB5E6CAC08201D62B319E2CE16EE236163679DDA3588FB 2BA260BE394C947BE83F2E6355A05A2AE2BB83D857535A75483F247028033D64 EF8657CB9C0ADB35721ABF0120E94750DA098EB448506BABADAC2E57658F7B35 991A4876C41924F45B24D28B9999EC06AFB581A49E2246F19B15CE492F318AE3 364C07D85229D41B91C9156639022FB0845E8E7EA20C1D3E48824842010550B6 4A60DC177B7D081F9FDF00E739C9EEA814A0B7A9F94C67896889367B21D4B8B1 E4916222E5FFD7B01001201F5B820597A872BD8C273EF291D10E1CB3C1EA2078 698B93975D06D3CFDCA014E72059873320E6B3601261A976125F67 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark %%EndFont TeXDict begin 40258431 52099146 1000 600 600 (quick.dvi) @start /Fa 149[25 2[45 45 86[45 15[{}4 90.9091 /CMSY10 rf /Fb 134[59 59 81 59 62 44 44 46 1[62 56 62 93 31 2[31 1[56 1[51 62 1[62 54 11[86 78 1[84 2[84 88 2[88 1[42 88 1[70 74 86 81 11[56 56 56 56 56 56 56 1[56 31 37 45[{}41 99.6264 /CMBX12 rf /Fc 129[48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 33[{}94 90.9091 /CMTT10 rf /Fd 139[30 1[30 1[43 38 43 1[21 2[21 43 38 1[34 43 34 1[38 13[43 57 3[58 5[58 60 50 52 1[55 1[58 20[21 44[{}23 74.7198 /CMR9 rf /Fe 252[32 3[{}1 49.8132 /CMSY6 rf /Ff 132[45 40 48 48 66 48 51 35 36 36 48 51 45 51 76 25 48 28 25 51 45 28 40 51 40 51 45 25 2[25 45 25 56 68 68 93 68 68 66 51 67 1[62 71 68 83 57 71 47 33 68 71 59 62 69 66 64 68 71 43 1[71 1[25 25 45 45 45 45 45 45 45 45 45 45 45 25 30 25 71 45 35 35 25 71 1[45 76 45 25 18[76 51 51 53 11[{}89 90.9091 /CMR10 rf /Fg 134[55 55 76 55 58 41 41 43 1[58 52 58 87 29 2[29 1[52 32 48 58 46 58 51 11[80 73 58 78 1[71 79 82 2[82 1[40 1[82 66 69 1[76 74 9[52 1[52 52 52 52 52 52 2[29 46[{}43 90.9091 /CMBX10 rf /Fh 135[71 2[75 52 53 55 1[75 67 75 112 37 2[37 1[67 1[61 75 60 1[65 11[103 94 75 100 1[92 101 105 4[50 2[85 88 1[97 12[67 67 67 67 67 67 49[{}33 119.552 /CMBX12 rf /Fi 252[35 3[{}1 66.4176 /CMSY8 rf /Fj 134[51 3[54 2[38 3[54 81 27 2[27 3[43 1[43 1[49 9[100 6[66 5[50 22[49 49 1[49 48[{}16 99.6264 /CMR12 rf /Fk 138[73 51 1[51 6[70 1[36 3[58 73 58 1[66 12[96 73 1[103 1[103 5[47 1[104 86 2[96 67[{}17 143.462 /CMR17 rf end %%EndProlog %%BeginSetup %%Feature: *Resolution 600dpi TeXDict begin %%BeginPaperSize: Letter letter %%EndPaperSize end %%EndSetup %%Page: 1 1 TeXDict begin 1 0 bop 1125 937 a Fk(CFITSIO)44 b(Quic)l(k)g(Start)e (Guide)1625 1190 y Fj(William)33 b(P)m(ence)2277 1154 y Fi(\003)1666 1394 y Fj(Jan)m(uary)g(2003)120 1916 y Fh(Con)l(ten)l(ts)120 2120 y Fg(1)84 b(In)m(tro)s(duction)2897 b(2)120 2324 y(2)84 b(Installing)35 b(and)g(Using)h(CFITSIO)2080 b(3)120 2528 y(3)84 b(Example)35 b(Programs)2601 b(4)120 2731 y(4)84 b(CFITSIO)33 b(Routines)2603 b(6)256 2844 y Ff(4.1)94 b(Error)30 b(Rep)s(orting)25 b(.)45 b(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)174 b(6)256 2957 y(4.2)94 b(File)32 b(Op)s(en/Close)e(Routines)58 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.) g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)174 b(6)256 3070 y(4.3)94 b(HDU-lev)m(el)34 b(Routines)86 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)174 b(7)256 3183 y(4.4)94 b(Image)32 b(I/O)e(Routines)80 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)174 b(9)256 3296 y(4.5)94 b(T)-8 b(able)31 b(I/O)g(Routines)e(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 b(12)256 3409 y(4.6)94 b(Header)31 b(Keyw)m(ord)f(I/O)h(Routines)79 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.) h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 b(19)256 3522 y(4.7)94 b(Utilit)m(y)33 b(Routines)27 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g (.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 b(22)120 3726 y Fg(5)84 b(CFITSIO)33 b(File)i(Names)g(and)f(Filters)1907 b(23)256 3839 y Ff(5.1)94 b(Creating)31 b(New)g(Files)45 b(.)h(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 b(23)256 3951 y(5.2)94 b(Op)s(ening)30 b(Existing)g(Files)41 b(.)46 b(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 b(24)256 4064 y(5.3)94 b(Image)32 b(Filtering)56 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 b(26)465 4177 y(5.3.1)106 b(Extracting)32 b(a)f(subsection)f(of)h(an)f (image)77 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)129 b(26)465 4290 y(5.3.2)106 b(Create)32 b(an)e(Image)h(b)m(y)f(Binning)g(T)-8 b(able)31 b(Columns)i(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 b(26)256 4403 y(5.4)94 b(T)-8 b(able)31 b(Filtering)77 b(.)45 b(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.) g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g (.)129 b(28)465 4516 y(5.4.1)106 b(Column)30 b(and)g(Keyw)m(ord)g (Filtering)50 b(.)45 b(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h (.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 b(28)465 4629 y(5.4.2)106 b(Ro)m(w)31 b(Filtering)42 b(.)j(.)h(.)g(.)g(.)f(.)h(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f (.)h(.)g(.)g(.)f(.)h(.)g(.)129 b(29)465 4742 y(5.4.3)106 b(Go)s(o)s(d)30 b(Time)h(In)m(terv)-5 b(al)31 b(Filtering)62 b(.)46 b(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.) h(.)g(.)g(.)f(.)h(.)g(.)129 b(32)465 4855 y(5.4.4)106 b(Spatial)31 b(Region)h(Filtering)59 b(.)46 b(.)f(.)h(.)g(.)f(.)h(.)g (.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.) g(.)129 b(32)465 4968 y(5.4.5)106 b(Example)31 b(Ro)m(w)g(Filters)h(.) 45 b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.) f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 b(34)256 5081 y(5.5)94 b(Com)m(bined)30 b(Filtering)i(Examples)45 b(.)h(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)f(.)h(.)g(.)g(.)f (.)h(.)g(.)f(.)h(.)g(.)g(.)f(.)h(.)g(.)129 b(36)120 5284 y Fg(6)84 b(CFITSIO)33 b(Error)i(Status)f(Co)s(des)2069 b(38)p 120 5346 1465 4 v 222 5400 a Fe(\003)258 5431 y Fd(HEASAR)n(C,)25 b(NASA)f(Go)r(ddard)i(Space)f(Fligh)n(t)h(Cen)n (ter)1928 5809 y Ff(1)p eop end %%Page: 2 2 TeXDict begin 2 1 bop 120 573 a Fh(1)135 b(In)l(tro)t(duction)120 776 y Ff(This)34 b(do)s(cumen)m(t)g(is)g(in)m(tended)g(to)h(help)f(y)m (ou)h(quic)m(kly)g(start)g(writing)f(C)g(programs)g(to)h(read)f(and)g (write)120 889 y(FITS)45 b(\014les)g(using)g(the)g(CFITSIO)f(library)-8 b(.)86 b(It)45 b(co)m(v)m(ers)i(the)f(most)f(imp)s(ortan)m(t)h(CFITSIO) d(routines)120 1002 y(that)i(are)f(needed)g(to)h(p)s(erform)d(most)i(t) m(yp)s(es)h(of)f(op)s(erations)g(on)g(FITS)f(\014les.)82 b(F)-8 b(or)45 b(more)f(complete)120 1115 y(information)d(ab)s(out)e (these)i(and)f(all)h(the)f(other)h(a)m(v)-5 b(ailable)42 b(routines)e(in)g(the)h(library)f(please)h(refer)f(to)120 1227 y(the)c(\\CFITSIO)e(User's)i(Reference)g(Guide",)i(whic)m(h)d(is)g (a)m(v)-5 b(ailable)38 b(from)d(the)h(CFITSIO)e(W)-8 b(eb)36 b(site)h(at)120 1340 y Fc(http://heasarc.gsfc.nasa)o(.gov)o (/fit)o(sio)o Ff(.)261 1453 y(F)-8 b(or)41 b(more)f(general)g (information)g(ab)s(out)g(the)g(FITS)f(data)h(format,)j(refer)d(to)g (the)g(follo)m(wing)h(w)m(eb)120 1566 y(page:)g(h)m (ttp://heasarc.gsfc.nasa.go)m(v/do)s(cs/heasa)q(rc/\014ts.h)m(t)q(ml) 261 1679 y(FITS)27 b(stands)h(for)g(Flexible)h(Image)g(T)-8 b(ransp)s(ort)27 b(System)h(and)f(is)h(the)h(standard)e(\014le)h (format)g(used)g(to)120 1792 y(store)j(most)g(astronomical)h(data)g (\014les.)41 b(There)30 b(are)h(2)g(basic)g(t)m(yp)s(es)f(of)h(FITS)f (\014les:)41 b(images)31 b(and)f(tables.)120 1905 y(FITS)j(images)i (often)f(con)m(tain)h(a)f(2-dimensional)g(arra)m(y)h(of)e(pixels)h (represen)m(ting)g(an)g(image)h(of)e(a)h(piece)120 2018 y(of)f(the)f(sky)-8 b(,)34 b(but)e(FITS)g(images)h(can)g(also)h(con)m (tain)g(1-D)f(arra)m(ys)g(\(i.e,)i(a)e(sp)s(ectrum)e(or)i(ligh)m(t)g (curv)m(e\),)h(or)120 2131 y(3-D)40 b(arra)m(ys)f(\(a)g(data)g(cub)s (e\),)i(or)d(ev)m(en)i(higher)e(dimensional)h(arra)m(ys)f(of)h(data.)66 b(An)38 b(image)i(ma)m(y)f(also)120 2244 y(ha)m(v)m(e)30 b(zero)g(dimensions,)e(in)h(whic)m(h)f(case)i(it)f(is)g(referred)f(to)i (as)f(a)g(n)m(ull)g(or)g(empt)m(y)g(arra)m(y)-8 b(.)41 b(The)28 b(supp)s(orted)120 2357 y(datat)m(yp)s(es)f(for)f(the)h(image) h(arra)m(ys)e(are)h(8,)h(16,)g(and)e(32-bit)i(in)m(tegers,)h(and)c(32)j (and)d(64-bit)j(\015oating)f(p)s(oin)m(t)120 2469 y(real)k(n)m(um)m(b)s (ers.)39 b(Both)31 b(signed)g(and)e(unsigned)h(in)m(tegers)h(are)g (supp)s(orted.)261 2582 y(FITS)j(tables)h(con)m(tain)g(ro)m(ws)f(and)g (columns)g(of)g(data,)i(similar)f(to)g(a)g(spreadsheet.)52 b(All)35 b(the)f(v)-5 b(alues)120 2695 y(in)31 b(a)g(particular)g (column)g(m)m(ust)f(ha)m(v)m(e)j(the)e(same)g(datat)m(yp)s(e.)43 b(A)31 b(cell)h(of)f(a)g(column)g(is)g(not)g(restricted)h(to)120 2808 y(a)g(single)f(n)m(um)m(b)s(er,)g(and)f(instead)i(can)f(con)m (tain)i(an)e(arra)m(y)g(or)h(v)m(ector)g(of)g(n)m(um)m(b)s(ers.)41 b(There)31 b(are)h(actually)120 2921 y(2)43 b(subt)m(yp)s(es)f(of)h (FITS)f(tables:)66 b(ASCI)s(I)41 b(and)i(binary)-8 b(.)77 b(As)43 b(the)g(names)g(imply)-8 b(,)46 b(ASCI)s(I)41 b(tables)j(store)120 3034 y(the)37 b(data)h(v)-5 b(alues)37 b(in)g(an)f(ASCI)s(I)g(represen)m(tation)i(whereas)e(binary)h(tables)g (store)h(the)f(data)g(v)-5 b(alues)38 b(in)120 3147 y(a)33 b(more)f(e\016cien)m(t)i(mac)m(hine-readable)f(binary)f(format.)46 b(Binary)33 b(tables)g(are)f(generally)i(more)e(compact)120 3260 y(and)25 b(supp)s(ort)e(more)j(features)f(\(e.g.,)j(a)e(wider)f (range)g(of)h(datat)m(yp)s(es,)h(and)e(v)m(ector)i(columns\))e(than)g (ASCI)s(I)120 3373 y(tables.)261 3486 y(A)31 b(single)g(FITS)f(\014le)h (man)m(y)g(con)m(tain)h(m)m(ultiple)f(images)h(or)f(tables.)42 b(Eac)m(h)31 b(table)h(or)e(image)i(is)f(called)120 3599 y(a)j(Header-Data)j(Unit,)e(or)f(HDU.)h(The)f(\014rst)f(HDU)i(in)e(a)i (FITS)e(\014le)h(m)m(ust)g(b)s(e)f(an)h(image)i(\(but)d(it)i(ma)m(y)120 3711 y(ha)m(v)m(e)30 b(zero)f(axes\))h(and)e(is)h(called)h(the)f (Primary)f(Arra)m(y)-8 b(.)41 b(An)m(y)28 b(additional)i(HDUs)f(in)g (the)f(\014le)h(\(whic)m(h)g(are)120 3824 y(also)i(referred)f(to)h(as)g (`extensions'\))g(ma)m(y)g(con)m(tain)h(either)f(an)f(image)i(or)e(a)h (table.)261 3937 y(Ev)m(ery)38 b(HDU)g(con)m(tains)h(a)f(header)g(con)m (taining)h(k)m(eyw)m(ord)f(records.)62 b(Eac)m(h)38 b(k)m(eyw)m(ord)g (record)g(is)g(80)120 4050 y(ASCI)s(I)29 b(c)m(haracters)j(long)f(and)e (has)i(the)f(follo)m(wing)i(format:)120 4263 y Fc(KEYWORD)46 b(=)h(value)g(/)g(comment)f(string)261 4475 y Ff(The)23 b(k)m(eyw)m(ord)i(name)f(can)g(b)s(e)f(up)g(to)h(8)g(c)m(haracters)i (long)e(\(all)h(upp)s(ercase\).)38 b(The)23 b(v)-5 b(alue)25 b(can)f(b)s(e)f(either)120 4588 y(an)k(in)m(teger)h(or)e(\015oating)i (p)s(oin)m(t)e(n)m(um)m(b)s(er,)h(a)g(logical)i(v)-5 b(alue)27 b(\(T)g(or)f(F\),)i(or)e(a)h(c)m(haracter)i(string)d (enclosed)i(in)120 4701 y(single)e(quotes.)40 b(Eac)m(h)26 b(header)f(b)s(egins)g(with)g(a)h(series)g(of)g(required)f(k)m(eyw)m (ords)g(to)i(describ)s(e)e(the)g(datat)m(yp)s(e)120 4814 y(and)35 b(format)h(of)f(the)h(follo)m(wing)h(data)f(unit,)g(if)f(an)m (y)-8 b(.)57 b(An)m(y)35 b(n)m(um)m(b)s(er)g(of)g(other)h(optional)g(k) m(eyw)m(ords)g(can)120 4927 y(b)s(e)d(included)g(in)g(the)g(header)h (to)g(pro)m(vide)f(other)h(descriptiv)m(e)h(information)e(ab)s(out)h (the)f(data.)51 b(F)-8 b(or)34 b(the)120 5040 y(most)g(part,)g(the)g (CFITSIO)d(routines)j(automatically)i(write)d(the)h(required)f(FITS)f (k)m(eyw)m(ords)i(for)f(eac)m(h)120 5153 y(HDU,)e(so)g(y)m(ou,)g(the)g (programmer,)f(usually)g(do)g(not)h(need)f(to)h(w)m(orry)f(ab)s(out)g (them.)1928 5809 y(2)p eop end %%Page: 3 3 TeXDict begin 3 2 bop 120 573 a Fh(2)135 b(Installing)46 b(and)f(Using)g(CFITSIO)120 776 y Ff(First,)33 b(y)m(ou)f(should)e(do)m (wnload)i(the)g(CFITSIO)e(soft)m(w)m(are)j(and)e(the)h(set)g(of)g (example)h(FITS)e(utilit)m(y)i(pro-)120 889 y(grams)e(from)f(the)g(w)m (eb)h(site)g(at)h(h)m(ttp://heasarc.gsfc.nasa.go)m(v/\014tsio.)47 b(The)30 b(example)h(programs)f(illus-)120 1002 y(trate)g(ho)m(w)e(to)h (p)s(erform)f(man)m(y)g(common)h(t)m(yp)s(es)f(of)h(op)s(erations)g(on) f(FITS)g(\014les)h(using)f(CFITSIO.)f(They)120 1115 y(are)h(also)h (useful)d(when)h(writing)h(a)g(new)f(program)g(b)s(ecause)h(it)g(is)g (often)g(easier)g(to)h(tak)m(e)g(a)f(cop)m(y)g(of)g(one)g(of)120 1227 y(these)k(utilit)m(y)h(programs)e(as)g(a)h(template)h(and)e(then)g (mo)s(dify)f(it)i(for)f(y)m(our)h(o)m(wn)f(purp)s(oses,)f(rather)i (than)120 1340 y(writing)e(the)h(new)f(program)g(completely)i(from)e (scratc)m(h.)261 1453 y(T)-8 b(o)28 b(build)e(the)i(CFITSIO)d(library)i (on)g(Unix)g(platforms,)i(`un)m(tar')e(the)h(source)f(co)s(de)h (distribution)e(\014le)120 1566 y(and)k(then)g(execute)i(the)e(follo)m (wing)i(commands)e(in)g(the)h(directory)f(con)m(taining)i(the)f(source) g(co)s(de:)120 1779 y Fc(>)95 b(./configure)45 b ([--prefix=/target/instal)o(lati)o(on/)o(path)o(])120 1892 y(>)95 b(make)524 b(\(or)47 b('make)f(shared'\))120 2005 y(>)95 b(make)47 b(install)141 b(\(this)46 b(step)h(is)g (optional\))261 2217 y Ff(The)40 b(optional)i('pre\014x')e(argumen)m(t) h(to)g(con\014gure)f(giv)m(es)i(the)f(path)f(to)h(the)g(directory)g (where)f(the)120 2330 y(CFITSIO)30 b(library)i(and)f(include)h(\014les) g(should)f(b)s(e)g(installed)i(via)g(the)f(later)h('mak)m(e)g(install') g(command.)120 2443 y(F)-8 b(or)31 b(example,)120 2655 y Fc(>)95 b(./configure)45 b(--prefix=/usr1/local)261 2868 y Ff(will)21 b(cause)g(the)g('mak)m(e)h(install')g(command)e(to)h (cop)m(y)h(the)e(CFITSIO)f(lib)s(c\014tsio)i(\014le)g(to)g(/usr1/lo)s (cal/lib)120 2981 y(and)35 b(the)h(necessary)g(include)g(\014les)g(to)g (/usr1/lo)s(cal/include)i(\(assuming)e(of)f(course)h(that)h(the)f(pro)s (cess)120 3094 y(has)30 b(p)s(ermission)f(to)j(write)e(to)h(these)g (directories\).)261 3207 y(Pre-compiled)f(v)m(ersions)g(of)g(the)g (CFITSIO)e(DLL)i(library)f(are)h(a)m(v)-5 b(ailable)32 b(for)d(PCs.)40 b(On)29 b(Macin)m(tosh)120 3320 y(mac)m(hines,)46 b(refer)c(to)g(the)h(README.MacOS)g(\014le)f(for)g(instructions)g(on)g (building)f(CFITSIO)g(using)120 3432 y(Co)s(deW)-8 b(arrior.)261 3545 y(An)m(y)40 b(programs)g(that)h(use)f(CFITSIO)f(m)m(ust)h(of)g (course)h(b)s(e)e(link)m(ed)i(with)f(the)g(CFITSIO)f(library)120 3658 y(when)e(creating)i(the)f(executable)i(\014le.)64 b(The)37 b(exact)j(pro)s(cedure)c(for)i(linking)g(a)h(program)e(dep)s (ends)f(on)120 3771 y(y)m(our)31 b(soft)m(w)m(are)i(en)m(vironmen)m(t,) f(but)f(on)g(Unix)g(platforms,)h(the)f(command)g(line)h(to)g(compile)g (and)f(link)g(a)120 3884 y(program)f(will)h(lo)s(ok)g(something)g(lik)m (e)g(this:)120 4097 y Fc(gcc)47 b(-o)g(myprog)f(myprog.c)g(-L.)h (-lcfitsio)e(-lm)i(-lnsl)f(-lsocket)261 4309 y Ff(Y)-8 b(ou)37 b(ma)m(y)g(not)f(need)g(to)h(include)g(all)g(of)f(the)h('m',)h ('nsl',)g(and)e('so)s(c)m(k)m(et')i(system)f(libraries)f(on)g(y)m(our) 120 4422 y(particular)41 b(mac)m(hine.)73 b(T)-8 b(o)42 b(\014nd)d(out)i(what)g(libraries)g(are)g(required)f(on)h(y)m(our)g (\(Unix\))g(system,)j(t)m(yp)s(e)120 4535 y Fc('make)i(testprog')28 b Ff(and)i(see)h(what)f(libraries)h(are)f(then)h(included)e(on)h(the)h (resulting)g(link)f(line.)1928 5809 y(3)p eop end %%Page: 4 4 TeXDict begin 4 3 bop 120 573 a Fh(3)135 b(Example)46 b(Programs)120 776 y Ff(Before)32 b(describing)f(the)h(individual)f (CFITSIO)e(routines)j(in)f(detail,)i(it)e(is)h(instructiv)m(e)g(to)g (\014rst)f(lo)s(ok)h(at)120 889 y(an)27 b(actual)h(program.)40 b(The)26 b(names)h(of)g(the)g(CFITSIO)f(routines)h(are)g(fairly)g (descriptiv)m(e)h(\(they)g(all)g(b)s(egin)120 1002 y(with)i Fc(fits)p 525 1002 29 4 v 33 w Ff(,)h(so)g(it)f(should)g(b)s(e)g (reasonably)g(clear)i(what)e(this)g(program)g(do)s(es:)120 1202 y Fc(------------------------)o(----)o(----)o(---)o(----)o(----)o (---)o(----)o(----)o(---)o(----)o(---)311 1315 y(#include)45 b()311 1428 y(#include)g()120 1541 y(1:)95 b(#include)45 b("fitsio.h")311 1767 y(int)i(main\(int)e(argc,)i (char)f(*argv[]\))311 1879 y({)120 1992 y(2:)286 b(fitsfile)45 b(*fptr;)502 2105 y(char)h(card[FLEN_CARD];)120 2218 y(3:)286 b(int)47 b(status)f(=)h(0,)95 b(nkeys,)46 b(ii;)95 b(/*)47 b(MUST)g(initialize)e(status)h(*/)120 2444 y(4:)286 b(fits_open_file\(&fptr,)42 b(argv[1],)j(READONLY,)h(&status\);)502 2557 y(fits_get_hdrspace\(fptr,)41 b(&nkeys,)46 b(NULL,)g(&status\);) 502 2783 y(for)h(\(ii)g(=)g(1;)g(ii)g(<=)h(nkeys;)e(ii++\))94 b({)597 2896 y(fits_read_record\(fptr,)42 b(ii,)47 b(card,)f (&status\);)g(/*)h(read)f(keyword)g(*/)597 3009 y(printf\("\045s\\n",)e (card\);)502 3121 y(})502 3234 y(printf\("END\\n\\n"\);)90 b(/*)48 b(terminate)d(listing)h(with)g(END)h(*/)502 3347 y(fits_close_file\(fptr,)42 b(&status\);)502 3573 y(if)47 b(\(status\))475 b(/*)47 b(print)g(any)g(error)f(messages)f(*/)120 3686 y(5:)477 b(fits_report_error\(stder)o(r,)42 b(status\);)502 3799 y(return\(status\);)311 3912 y(})120 4025 y (------------------------)o(----)o(----)o(---)o(----)o(----)o(---)o (----)o(----)o(---)o(----)o(---)261 4225 y Ff(This)29 b(program)g(op)s(ens)f(the)h(sp)s(eci\014ed)g(FITS)f(\014le)i(and)e (prin)m(ts)h(out)g(all)h(the)g(header)f(k)m(eyw)m(ords)g(in)g(the)120 4338 y(curren)m(t)h(HDU.)i(Some)e(other)h(p)s(oin)m(ts)f(to)h(notice)h (ab)s(out)e(the)g(program)g(are:)231 4516 y(1.)46 b(The)30 b Fc(fitsio.h)e Ff(header)i(\014le)g(m)m(ust)h(b)s(e)e(included)h(to)h (de\014ne)e(the)i(v)-5 b(arious)30 b(routines)g(and)g(sym)m(b)s(ols)347 4629 y(used)g(in)g(CFITSIO.)231 4812 y(2.)46 b(The)37 b Fc(fitsfile)e Ff(parameter)i(is)g(the)g(\014rst)g(argumen)m(t)g(in)g (almost)h(ev)m(ery)g(CFITSIO)d(routine.)61 b(It)347 4925 y(is)41 b(a)h(p)s(oin)m(ter)f(to)h(a)g(structure)e(\(de\014ned)g(in)h Fc(fitsio.h)p Ff(\))f(that)h(stores)h(information)f(ab)s(out)g(the)347 5038 y(particular)i(FITS)e(\014le)h(that)h(the)g(routine)f(will)g(op)s (erate)h(on.)76 b(Memory)43 b(for)f(this)g(structure)f(is)347 5151 y(automatically)36 b(allo)s(cated)e(when)e(the)h(\014le)g(is)f (\014rst)g(op)s(ened)g(or)h(created,)h(and)e(is)h(freed)f(when)g(the) 347 5264 y(\014le)f(is)f(closed.)231 5447 y(3.)46 b(Almost)41 b(ev)m(ery)f(CFITSIO)e(routine)h(has)h(a)g Fc(status)d Ff(parameter)j(as)g(the)g(last)g(argumen)m(t.)69 b(The)347 5560 y(status)28 b(v)-5 b(alue)28 b(is)g(also)h(usually)e(returned)g (as)h(the)g(v)-5 b(alue)28 b(of)g(the)f(function)h(itself.)40 b(Normally)29 b(status)1928 5809 y(4)p eop end %%Page: 5 5 TeXDict begin 5 4 bop 347 573 a Ff(=)22 b(0,)i(and)d(a)h(p)s(ositiv)m (e)h(status)f(v)-5 b(alue)22 b(indicates)h(an)f(error)f(of)h(some)g (sort.)38 b(The)22 b(status)g(v)-5 b(ariable)22 b(m)m(ust)347 686 y(alw)m(a)m(ys)33 b(b)s(e)d(initialized)j(to)f(zero)g(b)s(efore)f (use,)g(b)s(ecause)g(if)g(status)g(is)g(greater)i(than)d(zero)i(on)f (input)347 799 y(then)e(the)g(CFITSIO)f(routines)h(will)g(simply)f (return)g(without)h(doing)g(an)m(ything.)41 b(This)28 b(`inherited)347 912 y(status')46 b(feature,)j(where)44 b(eac)m(h)i(CFITSIO)e(routine)h(inherits)f(the)h(status)g(from)g(the)g (previous)347 1024 y(routine,)f(mak)m(es)d(it)g(unnecessary)f(to)i(c)m (hec)m(k)g(the)f(status)g(v)-5 b(alue)41 b(after)g(ev)m(ery)h(single)f (CFITSIO)347 1137 y(routine)e(call.)66 b(Generally)40 b(y)m(ou)f(should)f(c)m(hec)m(k)i(the)e(status)h(after)g(an)g(esp)s (ecially)h(imp)s(ortan)m(t)e(or)347 1250 y(complicated)33 b(routine)e(has)g(b)s(een)g(called,)i(or)e(after)h(a)f(blo)s(c)m(k)h (of)f(closely)i(related)f(CFITSIO)e(calls.)347 1363 y(This)c(example)h (program)g(has)f(tak)m(en)i(this)f(feature)g(to)g(the)g(extreme)g(and)f (only)h(c)m(hec)m(ks)h(the)f(status)347 1476 y(v)-5 b(alue)31 b(at)g(the)g(v)m(ery)g(end)e(of)i(the)f(program.)231 1664 y(4.)46 b(In)37 b(this)f(example)i(program)f(the)g(\014le)g(name)g (to)h(b)s(e)e(op)s(ened)h(is)g(giv)m(en)h(as)f(an)g(argumen)m(t)g(on)g (the)347 1777 y(command)e(line)h(\()p Fc(arg[1])p Ff(\).)53 b(If)35 b(the)g(\014le)h(con)m(tains)g(more)f(than)g(1)g(HDU)h(or)f (extension,)j(y)m(ou)d(can)347 1890 y(sp)s(ecify)20 b(whic)m(h)g (particular)h(HDU)g(to)g(b)s(e)f(op)s(ened)f(b)m(y)h(enclosing)i(the)e (name)g(or)h(n)m(um)m(b)s(er)e(of)h(the)h(HDU)347 2002 y(in)k(square)h(brac)m(k)m(ets)h(follo)m(wing)g(the)e(ro)s(ot)h(name)g (of)f(the)h(\014le.)39 b(F)-8 b(or)26 b(example,)i Fc(file.fts[0])22 b Ff(op)s(ens)347 2115 y(the)31 b(primary)e(arra)m(y)-8 b(,)32 b(while)f Fc(file.fts[2])c Ff(will)k(mo)m(v)m(e)h(to)f(and)f(op) s(en)f(the)i(2nd)f(extension)h(in)f(the)347 2228 y(\014le,)37 b(and)d Fc(file.fit[EVENTS])d Ff(will)k(op)s(en)g(the)g(extension)g (that)h(has)f(a)g Fc(EXTNAME)46 b(=)i('EVENTS')347 2341 y Ff(k)m(eyw)m(ord)31 b(in)f(the)g(header.)41 b(Note)31 b(that)g(on)f(the)h(Unix)f(command)g(line)h(y)m(ou)f(m)m(ust)g(enclose) i(the)e(\014le)347 2454 y(name)h(in)f(single)h(or)g(double)f(quote)i(c) m(haracters)g(if)e(the)h(name)g(con)m(tains)g(sp)s(ecial)h(c)m (haracters)g(suc)m(h)347 2567 y(as)f(`[')g(or)f(`]'.)347 2717 y(All)44 b(of)f(the)h(CFITSIO)d(routines)i(whic)m(h)g(read)g(or)g (write)h(header)f(k)m(eyw)m(ords,)k(image)d(data,)j(or)347 2830 y(table)32 b(data)f(op)s(erate)g(only)g(within)f(the)h(curren)m (tly)g(op)s(ened)f(HDU)h(in)f(the)h(\014le.)42 b(T)-8 b(o)31 b(read)g(or)f(write)347 2943 y(information)38 b(in)f(a)h(di\013eren)m(t)g(HDU)g(y)m(ou)g(m)m(ust)f(\014rst)g (explicitly)i(mo)m(v)m(e)f(to)h(that)f(HDU)g(\(see)g(the)347 3056 y Fc(fits)p 545 3056 29 4 v 34 w(movabs)p 867 3056 V 32 w(hdu)30 b Ff(and)g Fc(fits)p 1442 3056 V 33 w(movrel)p 1763 3056 V 33 w(hdu)f Ff(routines)h(in)g(section)i(4.3\).)231 3244 y(5.)46 b(The)25 b Fc(fits)p 727 3244 V 33 w(report)p 1048 3244 V 33 w(error)e Ff(routine)i(pro)m(vides)g(a)g(con)m(v)m (enien)m(t)i(w)m(a)m(y)f(to)g(prin)m(t)f(out)g(diagnostic)h(mes-)347 3357 y(sages)32 b(ab)s(out)e(an)m(y)g(error)g(that)h(ma)m(y)g(ha)m(v)m (e)h(o)s(ccurred.)261 3544 y(A)f(set)g(of)f(example)h(FITS)f(utilit)m (y)i(programs)e(are)g(a)m(v)-5 b(ailable)33 b(from)d(the)g(CFITSIO)f(w) m(eb)i(site)g(at)120 3657 y(h)m(ttp://heasarc.gsfc.nasa.go)m(v/do)s (cs/soft)n(w)m(are/)q(\014tsio/c)q(exa)q(mples.h)m(tml.)89 b(These)45 b(are)g(real)g(w)m(orking)120 3770 y(programs)d(whic)m(h)f (illustrate)i(ho)m(w)f(to)h(read,)i(write,)g(and)c(mo)s(dify)g(FITS)h (\014les)f(using)h(the)g(CFITSIO)120 3883 y(library)-8 b(.)38 b(Most)24 b(of)g(these)f(programs)g(are)h(v)m(ery)f(short,)i (con)m(taining)g(only)e(a)h(few)f(10s)h(of)f(lines)g(of)h(executable) 120 3996 y(co)s(de)32 b(or)g(less,)h(y)m(et)g(they)f(p)s(erform)e (quite)i(useful)f(op)s(erations)h(on)g(FITS)f(\014les.)45 b(Running)31 b(eac)m(h)i(program)120 4109 y(without)41 b(an)m(y)g(command)f(line)h(argumen)m(ts)g(will)g(pro)s(duce)e(a)i (short)f(description)h(of)g(ho)m(w)g(to)g(use)f(the)120 4222 y(program.)g(The)30 b(curren)m(tly)h(a)m(v)-5 b(ailable)32 b(programs)e(are:)347 4409 y(\014tscop)m(y)h(-)g(cop)m(y)g(a)g(\014le) 347 4522 y(listhead)g(-)g(list)g(header)f(k)m(eyw)m(ords)347 4635 y(liststruc)h(-)g(sho)m(w)f(the)g(structure)g(of)h(a)g(FITS)e (\014le.)347 4748 y(mo)s(dhead)h(-)g(write)h(or)f(mo)s(dify)g(a)h (header)f(k)m(eyw)m(ord)347 4861 y(imarith)h(-)f(add,)g(subtract,)h(m)m (ultiply)-8 b(,)31 b(or)g(divide)f(2)h(images)347 4974 y(imlist)g(-)g(list)g(pixel)g(v)-5 b(alues)30 b(in)g(an)h(image)347 5087 y(imstat)h(-)e(compute)h(mean,)g(min,)f(and)f(max)i(pixel)g(v)-5 b(alues)30 b(in)g(an)h(image)347 5200 y(tablist)h(-)e(displa)m(y)h(the) f(con)m(ten)m(ts)i(of)f(a)g(FITS)e(table)347 5313 y(tab)s(calc)j(-)f (general)g(table)g(calculator)1928 5809 y(5)p eop end %%Page: 6 6 TeXDict begin 6 5 bop 120 573 a Fh(4)135 b(CFITSIO)44 b(Routines)120 776 y Ff(This)37 b(c)m(hapter)h(describ)s(es)f(the)g (main)h(CFITSIO)e(routines)h(that)h(can)g(b)s(e)f(used)g(to)h(p)s (erform)e(the)i(most)120 889 y(common)31 b(t)m(yp)s(es)f(of)h(op)s (erations)f(on)h(FITS)e(\014les.)120 1136 y Fb(4.1)112 b(Error)37 b(Rep)s(orting)120 1310 y Fc(void)47 b (fits_report_error\(FILE)41 b(*stream,)46 b(int)h(status\))120 1423 y(void)g(fits_get_errstatus\(int)41 b(status,)46 b(char)h(*err_text\))120 1536 y(float)f(fits_get_version\(float)c (*version\))261 1748 y Ff(The)24 b(\014rst)g(routine)g(prin)m(ts)g(out) h(information)g(ab)s(out)f(an)m(y)h(error)f(that)h(has)g(o)s(ccurred.) 38 b(Whenev)m(er)25 b(an)m(y)120 1861 y(CFITSIO)f(routine)i(encoun)m (ters)h(an)f(error)f(it)i(usually)e(writes)h(a)h(message)g(describing)e (the)h(nature)g(of)g(the)120 1974 y(error)g(to)i(an)e(in)m(ternal)h (error)g(message)g(stac)m(k)h(and)e(then)h(returns)e(with)h(a)h(p)s (ositiv)m(e)h(in)m(teger)g(status)f(v)-5 b(alue.)120 2087 y(P)m(assing)28 b(the)g(error)f(status)h(v)-5 b(alue)28 b(to)g(this)g(routine)f(will)h(cause)g(a)g(generic)h(description)e(of)h (the)g(error)f(and)120 2200 y(all)g(the)g(messages)h(from)e(the)h(in)m (ternal)g(CFITSIO)e(error)h(stac)m(k)i(to)g(b)s(e)e(prin)m(ted)g(to)h (the)g(sp)s(eci\014ed)f(stream.)120 2313 y(The)k Fc(stream)f Ff(parameter)h(is)h(usually)f(set)h(equal)g(to)g Fc("stdout")d Ff(or)i Fc("stderr")p Ff(.)261 2426 y(The)25 b(second)g(routine)g (simply)f(returns)g(a)h(30-c)m(haracter)j(descriptiv)m(e)e(error)e (message)i(corresp)s(onding)120 2538 y(to)31 b(the)g(input)e(status)i (v)-5 b(alue.)261 2651 y(The)30 b(last)h(routine)g(returns)e(the)h (curren)m(t)g(CFITSIO)f(library)h(v)m(ersion)h(n)m(um)m(b)s(er.)120 2899 y Fb(4.2)112 b(File)39 b(Op)s(en/Close)f(Routines)120 3072 y Fc(int)47 b(fits_open_file\()d(fitsfile)h(**fptr,)h(char)h (*filename,)e(int)h(mode,)h(int)g(*status\))120 3185 y(int)g(fits_open_data\()d(fitsfile)h(**fptr,)h(char)h(*filename,)e (int)h(mode,)h(int)g(*status\))120 3298 y(int)g (fits_open_table\(fitsfile)41 b(**fptr,)46 b(char)h(*filename,)e(int)h (mode,)h(int)g(*status\))120 3411 y(int)g(fits_open_image\(fitsfile)41 b(**fptr,)46 b(char)h(*filename,)e(int)h(mode,)h(int)g(*status\))120 3637 y(int)g(fits_create_file\(fitsfil)o(e)42 b(**fptr,)k(char)g (*filename,)f(int)i(*status\))120 3750 y(int)g (fits_close_file\(fitsfile)41 b(*fptr,)46 b(int)h(*status\))261 3962 y Ff(These)38 b(routines)f(op)s(en)h(or)f(close)j(a)e(\014le.)63 b(The)37 b(\014rst)g Fc(fitsfile)f Ff(parameter)i(in)g(these)g(and)f (nearly)120 4075 y(ev)m(ery)28 b(other)g(CFITSIO)f(routine)g(is)h(a)g (p)s(oin)m(ter)g(to)g(a)g(structure)g(that)g(CFITSIO)e(uses)h(to)i (store)f(relev)-5 b(an)m(t)120 4188 y(parameters)31 b(ab)s(out)f(eac)m (h)i(op)s(ened)e(\014le.)42 b(Y)-8 b(ou)31 b(should)f(nev)m(er)h (directly)g(read)g(or)f(write)h(an)m(y)g(information)120 4301 y(in)24 b(this)h(structure.)38 b(Memory)26 b(for)e(this)h (structure)f(is)h(allo)s(cated)h(automatically)i(when)c(the)h(\014le)f (is)h(op)s(ened)120 4414 y(or)30 b(created,)i(and)e(is)g(freed)g(when)g (the)g(\014le)h(is)f(closed.)261 4527 y(The)e Fc(mode)e Ff(parameter)j(in)e(the)h Fc(fits)p 1552 4527 29 4 v 34 w(open)p 1778 4527 V 33 w(xxxx)f Ff(set)h(of)g(routines)g(can)g(b)s (e)f(set)i(to)f(either)h Fc(READONLY)120 4640 y Ff(or)h Fc(READWRITE)d Ff(to)j(select)h(the)f(t)m(yp)s(e)f(of)h(\014le)g (access)h(that)f(will)g(b)s(e)f(allo)m(w)m(ed.)42 b(These)29 b(sym)m(b)s(olic)h(constan)m(ts)120 4753 y(are)h(de\014ned)e(in)h Fc(fitsio.h)p Ff(.)261 4866 y(The)j Fc(fits)p 649 4866 V 33 w(open)p 874 4866 V 34 w(file)f Ff(routine)i(op)s(ens)e(the)i (\014le)g(and)e(p)s(ositions)i(the)g(in)m(ternal)g(\014le)f(p)s(oin)m (ter)h(to)g(the)120 4979 y(b)s(eginning)23 b(of)h(the)g(\014le,)h(or)f (to)h(the)f(sp)s(eci\014ed)f(extension)h(if)g(an)g(extension)g(name)g (or)g(n)m(um)m(b)s(er)e(is)i(app)s(ended)120 5092 y(to)j(the)f(\014le)h (name)f(\(see)h(the)g(later)g(section)h(on)e(\\CFITSIO)f(File)i(Names)g (and)f(Filters")i(for)e(a)g(description)120 5204 y(of)32 b(the)f(syn)m(tax\).)45 b Fc(fits)p 945 5204 V 33 w(open)p 1170 5204 V 33 w(data)31 b Ff(b)s(eha)m(v)m(es)g(similarly)h(except)h (that)f(it)g(will)f(mo)m(v)m(e)i(to)f(the)g(\014rst)f(HDU)120 5317 y(con)m(taining)37 b(signi\014can)m(t)f(data)g(if)f(a)h(HDU)g (name)g(or)f(n)m(um)m(b)s(er)f(to)i(op)s(en)f(is)g(not)h(explicitly)g (sp)s(eci\014ed)f(as)120 5430 y(part)23 b(of)h(the)g(\014lename.)39 b(It)23 b(will)h(mo)m(v)m(e)h(to)g(the)e(\014rst)g(IMA)m(GE)i(HDU)f (with)f(NAXIS)h(greater)h(than)e(0,)j(or)d(the)1928 5809 y(6)p eop end %%Page: 7 7 TeXDict begin 7 6 bop 120 573 a Ff(\014rst)29 b(table)h(that)h(do)s(es) e(not)h(con)m(tain)h(the)f(strings)f(`GTI')h(\(a)g(Go)s(o)s(d)g(Time)f (In)m(terv)-5 b(al)31 b(extension\))f(or)g(`OB-)120 686 y(ST)-8 b(ABLE')37 b(in)g(the)g(EXTNAME)h(k)m(eyw)m(ord)f(v)-5 b(alue.)62 b(The)36 b Fc(fits)p 2380 686 29 4 v 34 w(open)p 2606 686 V 33 w(table)g Ff(and)g Fc(fits)p 3290 686 V 34 w(open)p 3516 686 V 33 w(image)120 799 y Ff(routines)f(are)h (similar)f(except)i(that)f(they)f(will)h(mo)m(v)m(e)g(to)g(the)g (\014rst)e(signi\014can)m(t)j(table)f(HDU)g(or)f(image)120 912 y(HDU,)c(resp)s(ectiv)m(ely)h(if)e(a)h(HDU)g(name)g(of)f(n)m(um)m (b)s(er)f(is)i(not)f(sp)s(eci\014ed)g(as)h(part)f(of)g(the)h(input)e (\014le)i(name.)261 1024 y(When)d(op)s(ening)g(an)g(existing)h(\014le,) g(the)g Fc(filename)d Ff(can)i(include)g(optional)i(argumen)m(ts,)f (enclosed)g(in)120 1137 y(square)g(brac)m(k)m(ets)i(that)f(sp)s(ecify)f (\014ltering)h(op)s(erations)f(that)h(should)f(b)s(e)g(applied)g(to)h (the)g(input)e(\014le.)41 b(F)-8 b(or)120 1250 y(example,)263 1428 y Fc(myfile.fit[EVENTS][counts)41 b(>)48 b(0])120 1605 y Ff(op)s(ens)27 b(the)i(table)g(in)f(the)h(EVENTS)e(extension)i (and)f(creates)i(a)e(virtual)h(table)g(b)m(y)f(selecting)i(only)f (those)120 1718 y(ro)m(ws)f(where)f(the)i(COUNTS)d(column)i(v)-5 b(alue)29 b(is)f(greater)h(than)f(0.)40 b(See)28 b(section)h(5)g(for)f (more)g(examples)g(of)120 1831 y(these)j(p)s(o)m(w)m(erful)f (\014ltering)g(capabilities.)261 1944 y(In)38 b Fc(fits)p 581 1944 V 33 w(create)p 902 1944 V 33 w(file)p Ff(,)h(the)g Fc(filename)d Ff(is)j(simply)f(the)g(ro)s(ot)h(name)f(of)h(the)g (\014le)f(to)h(b)s(e)f(created.)120 2057 y(Y)-8 b(ou)36 b(can)g(o)m(v)m(erwrite)h(an)f(existing)g(\014le)g(b)m(y)f(pre\014xing) g(the)h(name)g(with)f(a)h(`!')57 b(c)m(haracter)37 b(\(on)f(the)f(Unix) 120 2170 y(command)30 b(line)g(this)g(m)m(ust)f(b)s(e)g(pre\014xed)g (with)h(a)g(bac)m(kslash,)h(as)f(in)f Fc(`\\!file.fit')p Ff(\).)38 b(If)29 b(the)h(\014le)g(name)120 2282 y(ends)e(with)g Fc(.gz)g Ff(the)h(\014le)g(will)g(b)s(e)f(compressed)g(using)g(the)h (gzip)g(algorithm.)41 b(If)29 b(the)f(\014lename)h(is)g Fc(stdout)120 2395 y Ff(or)g Fc("-")e Ff(\(a)j(single)f(dash)f(c)m (haracter\))j(then)d(the)h(output)f(\014le)h(will)g(b)s(e)f(pip)s(ed)f (to)j(the)f(stdout)f(stream.)41 b(Y)-8 b(ou)120 2508 y(can)27 b(c)m(hain)g(sev)m(eral)g(tasks)g(together)h(b)m(y)f(writing)f (the)h(output)f(from)g(the)g(\014rst)g(task)h(to)g Fc(stdout)e Ff(and)h(then)120 2621 y(reading)k(the)h(input)e(\014le)i(in)f(the)h (2nd)e(task)i(from)f Fc(stdin)f Ff(or)h Fc("-")p Ff(.)120 2867 y Fb(4.3)112 b(HDU-lev)m(el)38 b(Routines)261 3040 y Ff(The)30 b(routines)g(listed)h(in)f(this)h(section)g(op)s(erate)g (on)f(Header-Data)j(Units)e(\(HDUs\))g(in)f(a)h(\014le.)120 3153 y Fc(________________________)o(____)o(____)o(___)o(____)o(____)o (___)o(____)o(____)o(___)o(____)o(__)120 3266 y(int)47 b(fits_get_num_hdus\(fitsfi)o(le)42 b(*fptr,)k(int)h(*hdunum,)e(int)i (*status\))120 3379 y(int)g(fits_get_hdu_num\(fitsfil)o(e)42 b(*fptr,)94 b(int)47 b(*hdunum\))261 3579 y Ff(The)39 b(\014rst)f(routines)h(returns)f(the)h(total)i(n)m(um)m(b)s(er)d(of)h (HDUs)h(in)e(the)i(FITS)e(\014le,)k(and)c(the)h(second)120 3692 y(routine)33 b(returns)e(the)i(p)s(osition)g(of)g(the)g(curren)m (tly)f(op)s(ened)g(HDU)i(in)e(the)h(FITS)f(\014le)h(\(starting)g(with)g (1,)120 3805 y(not)e(0\).)120 4005 y Fc(________________________)o (____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o (____)o(___)o(____)o(__)120 4118 y(int)47 b(fits_movabs_hdu\(fitsfile) 41 b(*fptr,)46 b(int)h(hdunum,)f(int)h(*hdutype,)e(int)i(*status\))120 4231 y(int)g(fits_movrel_hdu\(fitsfile)41 b(*fptr,)46 b(int)h(nmove,)94 b(int)47 b(*hdutype,)e(int)i(*status\))120 4344 y(int)g(fits_movnam_hdu\(fitsfile)41 b(*fptr,)46 b(int)h(hdutype,)f(char)g(*extname,)1075 4457 y(int)g(extver,)g(int)h (*status\))261 4657 y Ff(These)31 b(routines)g(enable)h(y)m(ou)f(to)h (mo)m(v)m(e)g(to)g(a)g(di\013eren)m(t)f(HDU)h(in)f(the)g(\014le.)43 b(Most)32 b(of)g(the)f(CFITSIO)120 4770 y(functions)h(whic)m(h)h(read)g (or)g(write)g(k)m(eyw)m(ords)g(or)g(data)h(op)s(erate)f(only)h(on)e (the)h(curren)m(tly)g(op)s(ened)g(HDU)120 4883 y(in)i(the)g(\014le.)54 b(The)34 b(\014rst)g(routine)h(mo)m(v)m(es)h(to)g(the)f(sp)s(eci\014ed) f(absolute)i(HDU)f(n)m(um)m(b)s(er)f(in)g(the)h(FITS)f(\014le)120 4996 y(\(the)e(\014rst)f(HDU)i(=)e(1\),)i(whereas)f(the)g(second)f (routine)h(mo)m(v)m(es)h(a)f(relativ)m(e)i(n)m(um)m(b)s(er)d(of)h(HDUs) g(forw)m(ard)120 5109 y(or)f(bac)m(kw)m(ard)h(from)e(the)i(curren)m (tly)f(op)s(en)f(HDU.)i(The)f Fc(hdutype)e Ff(parameter)i(returns)f (the)i(t)m(yp)s(e)f(of)g(the)120 5222 y(newly)e(op)s(ened)g(HDU,)i(and) e(will)h(b)s(e)f(equal)h(to)g(one)g(of)g(these)g(sym)m(b)s(olic)g (constan)m(t)h(v)-5 b(alues:)41 b Fc(IMAGE)p 3564 5222 V 33 w(HDU,)120 5334 y(ASCII)p 366 5334 V 33 w(TBL,)47 b(or)g(BINARY)p 1069 5334 V 33 w(TBL)p Ff(.)37 b Fc(hdutype)g Ff(ma)m(y)h(b)s(e)g(set)h(to)g(NULL)f(if)g(it)h(is)g(not)f(needed.)64 b(The)38 b(third)120 5447 y(routine)31 b(mo)m(v)m(es)i(to)f(the)f (\(\014rst\))h(HDU)g(that)f(matc)m(hes)i(the)e(input)g(extension)h(t)m (yp)s(e,)f(name,)h(and)f(v)m(ersion)120 5560 y(n)m(um)m(b)s(er,)23 b(as)f(giv)m(en)i(b)m(y)e(the)g Fc(XTENSION,)46 b(EXTNAME)20 b Ff(\(or)j Fc(HDUNAME)p Ff(\))d(and)i Fc(EXTVER)f Ff(k)m(eyw)m(ords.) 38 b(If)22 b(the)g(input)1928 5809 y(7)p eop end %%Page: 8 8 TeXDict begin 8 7 bop 120 573 a Ff(v)-5 b(alue)34 b(of)f Fc(extver)e Ff(=)i(0,)i(then)e(the)g(v)m(ersion)h(n)m(um)m(b)s(er)d (will)j(b)s(e)e(ignored)i(when)e(lo)s(oking)i(for)f(a)g(matc)m(hing)120 686 y(HDU.)120 898 y Fc(________________________)o(____)o(____)o(___)o (____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)120 1011 y(int)47 b(fits_get_hdu_type\(fitsfi)o(le)42 b(*fptr,)93 b(int)47 b(*hdutype,)f(int)g(*status\))261 1224 y Ff(Get)21 b(the)g(t)m(yp)s(e)f(of)h(the)f(curren)m(t)g(HDU)h(in)f(the)h(FITS)e (\014le:)36 b Fc(IMAGE)p 2435 1224 29 4 v 33 w(HDU,)47 b(ASCII)p 2947 1224 V 33 w(TBL,)f(or)h(BINARY)p 3649 1224 V 33 w(TBL)p Ff(.)120 1436 y Fc(________________________)o(____)o (____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)o (___)120 1549 y(int)g(fits_copy_hdu\(fitsfile)42 b(*infptr,)j(fitsfile) h(*outfptr,)f(int)i(morekeys,)979 1662 y(int)g(*status\))120 1775 y(int)g(fits_copy_file\(fitsfile)41 b(*infptr,)46 b(fitsfile)f(*outfptr,)h(int)h(previous,)979 1888 y(int)g(current,)f (int)g(following,)f(>)j(int)f(*status\))261 2100 y Ff(The)34 b(\014rst)g(routine)g(copies)i(the)e(curren)m(t)g(HDU)i(from)e(the)g (FITS)g(\014le)h(asso)s(ciated)g(with)g(infptr)e(and)120 2213 y(app)s(ends)h(it)j(to)g(the)f(end)f(of)h(the)g(FITS)g(\014le)g (asso)s(ciated)h(with)f(outfptr.)57 b(Space)36 b(ma)m(y)h(b)s(e)e (reserv)m(ed)i(for)120 2326 y Fc(morekeys)32 b Ff(additional)k(k)m(eyw) m(ords)f(in)g(the)f(output)h(header.)53 b(The)35 b(second)f(routine)h (copies)h(an)m(y)f(HDUs)120 2439 y(previous)42 b(to)i(the)e(curren)m(t) h(HDU,)h(and/or)e(the)h(curren)m(t)f(HDU,)i(and/or)f(an)m(y)g(HDUs)g (follo)m(wing)h(the)120 2552 y(curren)m(t)22 b(HDU,)h(dep)s(ending)d (on)i(the)g(v)-5 b(alue)23 b(\(T)-8 b(rue)22 b(or)g(F)-8 b(alse\))24 b(of)e Fc(previous,)45 b(current)p Ff(,)22 b(and)g Fc(following)p Ff(,)120 2665 y(resp)s(ectiv)m(ely)-8 b(.)42 b(F)-8 b(or)32 b(example,)215 2853 y Fc(fits_copy_file\(infptr,) 42 b(outfptr,)k(0,)h(1,)g(1,)g(&status\);)120 3040 y Ff(will)35 b(cop)m(y)h(the)f(curren)m(t)g(HDU)g(and)g(an)m(y)g(HDUs)g (that)h(follo)m(w)g(it)f(from)g(the)g(input)f(to)h(the)h(output)e (\014le,)120 3153 y(but)c(it)h(will)f(not)h(cop)m(y)g(an)m(y)g(HDUs)g (preceding)f(the)h(curren)m(t)f(HDU.)1928 5809 y(8)p eop end %%Page: 9 9 TeXDict begin 9 8 bop 120 573 a Fb(4.4)112 b(Image)38 b(I/O)g(Routines)120 744 y Ff(This)30 b(section)h(lists)g(the)g(more)f (imp)s(ortan)m(t)h(CFITSIO)d(routines)j(whic)m(h)f(op)s(erate)h(on)f (FITS)g(images.)120 956 y Fc(________________________)o(____)o(____)o (___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(__)120 1069 y(int)47 b(fits_get_img_type\(fitsfi)o(le)42 b(*fptr,)k(int)h (*bitpix,)e(int)i(*status\))120 1181 y(int)g(fits_get_img_dim\()c (fitsfile)j(*fptr,)g(int)h(*naxis,)93 b(int)47 b(*status\))120 1294 y(int)g(fits_get_img_size\(fitsfi)o(le)42 b(*fptr,)k(int)h (maxdim,)93 b(long)47 b(*naxes,)1170 1407 y(int)g(*status\))120 1520 y(int)g(fits_get_img_param\(fitsf)o(ile)41 b(*fptr,)46 b(int)h(maxdim,)94 b(int)47 b(*bitpix,)1218 1633 y(int)g(*naxis,)e (long)i(*naxes,)f(int)h(*status\))261 1844 y Ff(Get)38 b(information)g(ab)s(out)f(the)g(curren)m(tly)g(op)s(ened)g(image)h (HDU.)g(The)f(\014rst)f(routine)h(returns)f(the)120 1957 y(datat)m(yp)s(e)41 b(of)e(the)h(image)h(as)f(\(de\014ned)f(b)m(y)g (the)h Fc(BITPIX)e Ff(k)m(eyw)m(ord\),)43 b(whic)m(h)c(can)h(ha)m(v)m (e)h(the)f(follo)m(wing)120 2070 y(sym)m(b)s(olic)31 b(constan)m(t)g(v)-5 b(alues:)311 2256 y Fc(BYTE_IMG)284 b(=)143 b(8)g(\()47 b(8-bit)g(byte)f(pixels,)g(0)i(-)f(255\))311 2369 y(SHORT_IMG)236 b(=)95 b(16)143 b(\(16)47 b(bit)g(integer)f (pixels\))311 2482 y(LONG_IMG)284 b(=)95 b(32)143 b(\(32-bit)46 b(integer)g(pixels\))311 2595 y(LONGLONG_IMG)92 b(=)j(64)143 b(\(64-bit)46 b(integer)g(pixels\))311 2708 y(FLOAT_IMG)236 b(=)48 b(-32)142 b(\(32-bit)46 b(floating)f(point)i(pixels\))311 2821 y(DOUBLE_IMG)188 b(=)48 b(-64)142 b(\(64-bit)46 b(floating)f(point)i(pixels\))261 3007 y Ff(The)34 b(second)g(and)f (third)g(routines)h(return)f(the)h(n)m(um)m(b)s(er)e(of)i(dimensions)f (in)h(the)g(image)h(\(from)f(the)120 3120 y Fc(NAXIS)25 b Ff(k)m(eyw)m(ord\),)j(and)e(the)h(sizes)g(of)f(eac)m(h)i(dimension)e (\(from)g(the)g Fc(NAXIS1,)46 b(NAXIS2)p Ff(,)26 b(etc.)40 b(k)m(eyw)m(ords\).)120 3233 y(The)g(last)i(routine)f(simply)g(com)m (bines)g(the)h(function)e(of)h(the)h(\014rst)e(3)h(routines.)73 b(The)40 b(input)g Fc(maxdim)120 3346 y Ff(parameter)28 b(in)g(this)f(routine)h(giv)m(es)h(the)f(maxim)m(um)g(n)m(um)m(b)s(er)e (dimensions)h(that)i(ma)m(y)f(b)s(e)f(returned)g(\(i.e.,)120 3459 y(the)k(dimension)e(of)i(the)f Fc(naxes)f Ff(arra)m(y\))120 3670 y Fc(________________________)o(____)o(____)o(___)o(____)o(____)o (___)o(____)o(____)o(___)o(_)120 3783 y(int)47 b (fits_create_img\(fitsfile)41 b(*fptr,)46 b(int)h(bitpix,)f(int)h (naxis,)1075 3896 y(long)f(*naxes,)g(int)h(*status\))261 4107 y Ff(Create)28 b(an)f(image)i(HDU)f(b)m(y)f(writing)g(the)g (required)g(k)m(eyw)m(ords)g(whic)m(h)g(de\014ne)g(the)g(structure)g (of)g(the)120 4220 y(image.)51 b(The)33 b(2nd)f(through)h(4th)h (parameters)f(sp)s(eci\014ed)g(the)g(datat)m(yp)s(e,)j(the)d(n)m(um)m (b)s(er)f(of)i(dimensions,)120 4333 y(and)26 b(the)h(sizes)g(of)f(the)h (dimensions.)39 b(The)26 b(allo)m(w)m(ed)i(v)-5 b(alues)27 b(of)g(the)f Fc(bitpix)f Ff(parameter)i(are)g(listed)g(ab)s(o)m(v)m(e) 120 4446 y(in)33 b(the)g(description)g(of)g(the)g Fc(fits)p 1319 4446 29 4 v 33 w(get)p 1496 4446 V 33 w(img)p 1673 4446 V 34 w(type)f Ff(routine.)48 b(If)32 b(the)h(FITS)f(\014le)h(p)s (oin)m(ted)g(to)h(b)m(y)f Fc(fptr)e Ff(is)120 4559 y(empt)m(y)c (\(previously)f(created)h(with)f Fc(fits)p 1575 4559 V 33 w(create)p 1896 4559 V 33 w(file)p Ff(\))f(then)h(this)g(routine)g (creates)i(a)f(primary)e(arra)m(y)120 4672 y(in)37 b(the)g(\014le,)i (otherwise)f(a)f(new)g(IMA)m(GE)h(extension)g(is)f(app)s(ended)e(to)j (end)f(of)g(the)g(\014le)h(follo)m(wing)g(the)120 4785 y(other)31 b(HDUs)g(in)f(the)g(\014le.)120 4996 y Fc (________________________)o(____)o(____)o(___)o(____)o(____)o(___)o (____)o(____)o(___)o(____)o(_)120 5109 y(int)47 b (fits_write_pix\(fitsfile)41 b(*fptr,)46 b(int)h(datatype,)f(long)g (*fpixel,)836 5222 y(long)h(nelements,)e(void)h(*array,)g(int)h (*status\);)120 5447 y(int)g(fits_write_pixnull\(fitsf)o(ile)41 b(*fptr,)46 b(int)h(datatype,)f(long)g(*fpixel,)836 5560 y(long)h(nelements,)e(void)h(*array,)g(void)h(*nulval,)e(int)i (*status\);)1928 5809 y Ff(9)p eop end %%Page: 10 10 TeXDict begin 10 9 bop 120 686 a Fc(int)47 b(fits_read_pix\(fitsfile)42 b(*fptr,)k(int)94 b(datatype,)46 b(long)g(*fpixel,)979 799 y(long)h(nelements,)e(void)h(*nulval,)g(void)h(*array,)979 912 y(int)g(*anynul,)f(int)g(*status\))261 1124 y Ff(Read)32 b(or)f(write)g(all)h(or)f(part)h(of)f(the)g(FITS)g(image.)44 b(There)31 b(are)h(2)f(di\013eren)m(t)h('write')g(pixel)f(routines:)120 1237 y(The)23 b(\014rst)g(simply)g(writes)h(the)g(input)f(arra)m(y)h (of)g(pixels)g(to)g(the)g(FITS)f(\014le.)39 b(The)23 b(second)h(is)g(similar,)h(except)120 1350 y(that)30 b(it)f(substitutes)g(the)g(appropriate)g(n)m(ull)g(pixel)g(v)-5 b(alue)30 b(in)f(the)g(FITS)f(\014le)h(for)g(an)m(y)g(pixels)g(whic)m (h)g(ha)m(v)m(e)120 1463 y(a)i(v)-5 b(alue)30 b(equal)h(to)g Fc(*nulval)d Ff(\(note)j(that)g(this)f(parameter)g(giv)m(es)i(the)e (address)f(of)i(the)f(n)m(ull)g(pixel)h(v)-5 b(alue,)120 1576 y(not)35 b(the)g(v)-5 b(alue)35 b(itself)7 b(\).)54 b(Similarly)-8 b(,)37 b(when)c(reading)i(an)g(image,)i(CFITSIO)c(will)i (substitute)f(the)h(v)-5 b(alue)120 1689 y(giv)m(en)30 b(b)m(y)e Fc(nulval)f Ff(for)i(an)m(y)g(unde\014ned)d(pixels)j(in)g (the)g(image,)h(unless)e Fc(nulval)46 b(=)i(NULL)p Ff(,)27 b(in)i(whic)m(h)f(case)120 1802 y(no)i(c)m(hec)m(ks)i(will)f(b)s(e)f (made)g(for)g(unde\014ned)e(pixels)j(when)e(reading)i(the)f(FITS)g (image.)261 1914 y(The)35 b Fc(fpixel)f Ff(parameter)i(in)f(these)h (routines)f(is)h(an)f(arra)m(y)h(whic)m(h)f(giv)m(es)i(the)f(co)s (ordinate)g(in)f(eac)m(h)120 2027 y(dimension)24 b(of)i(the)f(\014rst)f (pixel)i(to)f(b)s(e)g(read)g(or)g(written,)h(and)f Fc(nelements)d Ff(is)j(the)g(total)i(n)m(um)m(b)s(er)d(of)h(pixels)120 2140 y(to)i(read)g(or)f(write.)40 b Fc(array)25 b Ff(is)i(the)f (address)g(of)h(an)f(arra)m(y)h(whic)m(h)f(either)h(con)m(tains)h(the)f (pixel)g(v)-5 b(alues)27 b(to)g(b)s(e)120 2253 y(written,)32 b(or)f(will)h(hold)e(the)i(v)-5 b(alues)31 b(of)h(the)f(pixels)h(that)g (are)f(read.)43 b(When)31 b(reading,)h Fc(array)e Ff(m)m(ust)h(ha)m(v)m (e)120 2366 y(b)s(een)k(allo)s(cated)j(large)f(enough)e(to)i(hold)e (all)i(the)f(returned)f(pixel)h(v)-5 b(alues.)57 b(These)36 b(routines)f(starts)i(at)120 2479 y(the)e Fc(fpixel)d Ff(lo)s(cation)k(and)e(then)g(read)h(or)f(write)h(the)f Fc(nelements)e Ff(pixels,)k(con)m(tin)m(uing)g(on)e(successiv)m(e)120 2592 y(ro)m(ws)f(of)g(the)g(image)h(if)f(necessary)-8 b(.)49 b(F)-8 b(or)34 b(example,)h(to)e(write)g(an)g(en)m(tire)h(2D)g (image,)h(set)e Fc(fpixel[0])46 b(=)120 2705 y(fpixel[1])f(=)j(1)p Ff(,)35 b(and)f Fc(nelements)46 b(=)h(NAXIS1)f(*)i(NAXIS2)p Ff(.)j(Or)34 b(to)i(read)e(just)g(the)h(10th)h(ro)m(w)e(of)h(the)120 2818 y(image,)50 b(set)45 b Fc(fpixel[0])g(=)j(1,)f(fpixel[1])e(=)j(10) p Ff(,)g(and)c Fc(nelements)h(=)i(NAXIS1)p Ff(.)82 b(The)45 b Fc(datatype)120 2931 y Ff(parameter)28 b(sp)s(eci\014es)e(the)i (datat)m(yp)s(e)g(of)f(the)g(C)g Fc(array)e Ff(in)i(the)g(program,)h (whic)m(h)f(need)g(not)g(b)s(e)g(the)g(same)120 3044 y(as)32 b(the)f(datat)m(yp)s(e)i(of)e(the)h(FITS)f(image)h(itself.)45 b(If)31 b(the)h(datat)m(yp)s(es)g(di\013er)f(then)g(CFITSIO)f(will)i (con)m(v)m(ert)120 3156 y(the)f(data)h(as)f(it)h(is)f(read)g(or)g (written.)42 b(The)31 b(follo)m(wing)h(sym)m(b)s(olic)g(constan)m(ts)g (are)f(allo)m(w)m(ed)i(for)e(the)g(v)-5 b(alue)120 3269 y(of)31 b Fc(datatype)p Ff(:)215 3457 y Fc(TBYTE)238 b(unsigned)45 b(char)215 3570 y(TSBYTE)190 b(signed)46 b(char)215 3683 y(TSHORT)190 b(signed)46 b(short)215 3796 y(TUSHORT)142 b(unsigned)45 b(short)215 3909 y(TINT)286 b(signed)46 b(int)215 4022 y(TUINT)238 b(unsigned)45 b(int)215 4134 y(TLONG)238 b(signed)46 b(long)215 4247 y(TLONGLONG)g(signed)g(8-byte)g(integer)215 4360 y(TULONG)190 b(unsigned)45 b(long)215 4473 y(TFLOAT)190 b(float)215 4586 y(TDOUBLE)142 b(double)120 4799 y(________________________)o(____) o(____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)120 4912 y(int)47 b(fits_write_subset\(fitsfi)o(le)42 b(*fptr,)k(int)h (datatype,)e(long)h(*fpixel,)740 5024 y(long)h(*lpixel,)f(DTYPE)g (*array,)g(>)h(int)g(*status\))120 5250 y(int)g (fits_read_subset\(fitsfil)o(e)42 b(*fptr,)k(int)95 b(datatype,)45 b(long)h(*fpixel,)740 5363 y(long)h(*lpixel,)f(long)g(*inc,)h(void)f (*nulval,)94 b(void)46 b(*array,)740 5476 y(int)h(*anynul,)f(int)h (*status\))1905 5809 y Ff(10)p eop end %%Page: 11 11 TeXDict begin 11 10 bop 261 573 a Ff(Read)49 b(or)g(write)f(a)h (rectangular)h(section)g(of)f(the)f(FITS)g(image.)97 b(These)49 b(are)g(v)m(ery)g(similar)g(to)120 686 y Fc(fits)p 318 686 29 4 v 33 w(write)p 591 686 V 33 w(pix)37 b Ff(and)f Fc(fits)p 1180 686 V 34 w(read)p 1406 686 V 33 w(pix)g Ff(except)j(that)f(y)m(ou)f(sp)s(ecify)g(the)h(last)g(pixel)g(co)s (ordinate)g(\(the)120 799 y(upp)s(er)22 b(righ)m(t)i(corner)g(of)g(the) h(section\))g(instead)f(of)g(the)h(n)m(um)m(b)s(er)d(of)i(pixels)h(to)f (b)s(e)g(read.)38 b(The)23 b(read)h(routine)120 912 y(also)39 b(has)e(an)h Fc(inc)f Ff(parameter)h(whic)m(h)f(can)i(b)s(e)e(used)g (to)h(read)g(only)g(ev)m(ery)g Fc(inc-th)e Ff(pixel)i(along)h(eac)m(h) 120 1024 y(dimension)28 b(of)h(the)g(image.)41 b(Normally)30 b Fc(inc[0])46 b(=)h(inc[1])f(=)i(1)28 b Ff(to)i(read)e(ev)m(ery)i (pixel)f(in)f(a)h(2D)h(image.)120 1137 y(T)-8 b(o)31 b(read)f(ev)m(ery)h(other)g(pixel)g(in)f(the)g(en)m(tire)i(2D)f(image,) h(set)311 1325 y Fc(fpixel[0])45 b(=)j(fpixel[1])d(=)i(1)311 1438 y(lpixel[0])e(=)j({NAXIS1})311 1551 y(lpixel[1])d(=)j({NAXIS2})311 1664 y(inc[0])e(=)h(inc[1])g(=)g(2)261 1851 y Ff(Or,)30 b(to)h(read)f(the)h(8th)g(ro)m(w)f(of)h(a)f(2D)i(image,)f(set)311 2039 y Fc(fpixel[0])45 b(=)j(1)311 2152 y(fpixel[1])d(=)j(8)311 2265 y(lpixel[0])d(=)j({NAXIS1})311 2378 y(lpixel[1])d(=)j(8)311 2491 y(inc[0])e(=)h(inc[1])g(=)g(1)1905 5809 y Ff(11)p eop end %%Page: 12 12 TeXDict begin 12 11 bop 120 573 a Fb(4.5)112 b(T)-9 b(able)38 b(I/O)g(Routines)120 744 y Ff(This)30 b(section)h(lists)g(the)g(most)f (imp)s(ortan)m(t)h(CFITSIO)e(routines)h(whic)m(h)g(op)s(erate)h(on)f (FITS)g(tables.)120 957 y Fc(________________________)o(____)o(____)o (___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o (____)o(__)120 1070 y(int)47 b(fits_create_tbl\(fitsfile)41 b(*fptr,)46 b(int)h(tbltype,)f(long)g(nrows,)g(int)h(tfields,)311 1183 y(char)g(*ttype[],char)d(*tform[],)h(char)i(*tunit[],)e(char)i (*extname,)e(int)i(*status\))261 1395 y Ff(Create)e(a)f(new)f(table)i (extension)f(b)m(y)g(writing)g(the)g(required)f(k)m(eyw)m(ords)h(that)g (de\014ne)f(the)h(table)120 1508 y(structure.)38 b(The)22 b(required)f(n)m(ull)i(primary)e(arra)m(y)i(will)g(b)s(e)f(created)i (\014rst)d(if)i(the)g(\014le)f(is)h(initially)h(completely)120 1621 y(empt)m(y)-8 b(.)41 b Fc(tbltype)26 b Ff(de\014nes)i(the)g(t)m (yp)s(e)h(of)g(table)g(and)f(can)g(ha)m(v)m(e)i(v)-5 b(alues)29 b(of)f Fc(ASCII)p 2931 1621 29 4 v 33 w(TBL)47 b(or)g(BINARY)p 3586 1621 V 33 w(TBL)p Ff(.)120 1734 y(Binary)34 b(tables)h(are)g(generally)g(preferred)e(b)s(ecause)h(they) h(are)f(more)h(e\016cien)m(t)g(and)f(supp)s(ort)f(a)h(greater)120 1847 y(range)d(of)f(column)g(datat)m(yp)s(es)i(than)e(ASCI)s(I)f (tables.)261 1960 y(The)c Fc(nrows)f Ff(parameter)i(giv)m(es)h(the)e (initial)i(n)m(um)m(b)s(er)d(of)i(empt)m(y)g(ro)m(ws)f(to)h(b)s(e)f (allo)s(cated)i(for)f(the)f(table;)120 2073 y(this)h(should)g(normally) g(b)s(e)g(set)h(to)g(0.)40 b(The)26 b Fc(tfields)f Ff(parameter)i(giv)m (es)g(the)g(n)m(um)m(b)s(er)e(of)i(columns)f(in)g(the)120 2186 y(table)e(\(maxim)m(um)f(=)f(999\).)40 b(The)22 b Fc(ttype,)46 b(tform)p Ff(,)24 b(and)e Fc(tunit)f Ff(parameters)i (giv)m(e)i(the)e(name,)h(datat)m(yp)s(e,)120 2299 y(and)34 b(ph)m(ysical)h(units)g(of)f(eac)m(h)i(column,)g(and)e Fc(extname)f Ff(giv)m(es)j(the)f(name)g(for)f(the)h(table)h(\(the)f(v) -5 b(alue)35 b(of)120 2412 y(the)i Fc(EXTNAME)e Ff(k)m(eyw)m(ord\).)61 b(The)36 b(FITS)g(Standard)g(recommends)g(that)i(only)f(letters,)j (digits,)f(and)d(the)120 2524 y(underscore)27 b(c)m(haracter)h(b)s(e)f (used)g(in)g(column)g(names)g(with)g(no)g(em)m(b)s(edded)g(spaces.)40 b(It)27 b(is)h(recommended)120 2637 y(that)j(all)g(the)g(column)f (names)g(in)g(a)h(giv)m(en)g(table)h(b)s(e)d(unique)h(within)g(the)g (\014rst)g(8)h(c)m(haracters.)261 2750 y(The)g(follo)m(wing)i(table)g (sho)m(ws)e(the)h(TF)m(ORM)g(column)f(format)h(v)-5 b(alues)32 b(that)g(are)g(allo)m(w)m(ed)i(in)d(ASCI)s(I)120 2863 y(tables)g(and)f(in)g(binary)g(tables:)502 3051 y Fc(ASCII)46 b(Table)h(Column)f(Format)g(Codes)502 3164 y(------------------------)o (---)o(----)502 3277 y(\(w)h(=)g(column)g(width,)f(d)h(=)h(no.)e(of)i (decimal)d(places)i(to)g(display\))693 3390 y(Aw)142 b(-)48 b(character)d(string)693 3502 y(Iw)142 b(-)48 b(integer)693 3615 y(Fw.d)e(-)i(fixed)e(floating)g(point)693 3728 y(Ew.d)g(-)i(exponential)d(floating)g(point)693 3841 y(Dw.d)h(-)i(exponential)d(floating)g(point)502 4067 y(Binary)h(Table)g(Column)g(Format)g(Codes)502 4180 y(------------------------)o(---)o(----)o(-)502 4293 y(\(r)h(=)g(vector)g(length,)e(default)h(=)i(1\))693 4406 y(rA)95 b(-)47 b(character)e(string)693 4519 y(rAw)i(-)g(array)f (of)i(strings,)d(each)i(of)g(length)f(w)693 4632 y(rL)95 b(-)47 b(logical)693 4744 y(rX)95 b(-)47 b(bit)693 4857 y(rB)95 b(-)47 b(unsigned)f(byte)693 4970 y(rS)95 b(-)47 b(signed)f(byte)h(**)693 5083 y(rI)95 b(-)47 b(signed)f(16-bit)g (integer)693 5196 y(rU)95 b(-)47 b(unsigned)f(16-bit)g(integer)g(**)693 5309 y(rJ)95 b(-)47 b(signed)f(32-bit)g(integer)693 5422 y(rV)95 b(-)47 b(unsigned)f(32-bit)g(integer)g(**)693 5535 y(rK)95 b(-)47 b(signed)f(64-bit)g(integer)1905 5809 y Ff(12)p eop end %%Page: 13 13 TeXDict begin 13 12 bop 693 573 a Fc(rE)95 b(-)47 b(32-bit)f(floating)g (point)693 686 y(rD)95 b(-)47 b(64-bit)f(floating)g(point)693 799 y(rC)95 b(-)47 b(32-bit)f(complex)g(pair)693 912 y(rM)95 b(-)47 b(64-bit)f(complex)g(pair)359 1137 y(**)h(The)g(S,)g(U)g (and)g(V)h(format)e(codes)g(are)h(not)g(actual)f(legal)g(TFORMn)h (values.)502 1250 y(CFITSIO)f(substitutes)e(the)j(somewhat)f(more)g (complicated)f(set)i(of)502 1363 y(keywords)e(that)i(are)g(used)g(to)g (represent)e(unsigned)h(integers)f(or)502 1476 y(signed)h(bytes.)261 1777 y Ff(The)27 b Fc(tunit)e Ff(and)h Fc(extname)f Ff(parameters)j (are)f(optional)h(and)f(ma)m(y)g(b)s(e)g(set)g(to)h(NULL)f(if)g(they)g (are)g(not)120 1890 y(needed.)261 2002 y(Note)41 b(that)f(it)f(ma)m(y)h (b)s(e)f(easier)h(to)g(create)h(a)f(new)e(table)i(b)m(y)g(cop)m(ying)g (the)f(header)g(from)g(another)120 2115 y(existing)31 b(table)h(with)e Fc(fits)p 1089 2115 29 4 v 33 w(copy)p 1314 2115 V 33 w(header)f Ff(rather)h(than)g(calling)i(this)e(routine.) 120 2328 y Fc(________________________)o(____)o(____)o(___)o(____)o (____)o(___)o(____)o(____)o(___)o(____)o(__)120 2441 y(int)47 b(fits_get_num_rows\(fitsfi)o(le)42 b(*fptr,)k(long)g(*nrows,) g(int)h(*status\))120 2554 y(int)g(fits_get_num_cols\(fitsfi)o(le)42 b(*fptr,)k(int)94 b(*ncols,)46 b(int)h(*status\))261 2766 y Ff(Get)37 b(the)g(n)m(um)m(b)s(er)d(of)j(ro)m(ws)f(or)g(columns) g(in)f(the)i(curren)m(t)e(FITS)h(table.)59 b(The)35 b(n)m(um)m(b)s(er)g (of)h(ro)m(ws)g(is)120 2879 y(giv)m(en)e(b)m(y)f(the)g Fc(NAXIS2)e Ff(k)m(eyw)m(ord)j(and)e(the)h(n)m(um)m(b)s(er)f(of)h (columns)g(is)g(giv)m(en)h(b)m(y)f(the)g Fc(TFIELDS)e Ff(k)m(eyw)m(ord)120 2992 y(in)f(the)h(header)f(of)g(the)h(table.)120 3205 y Fc(________________________)o(____)o(____)o(___)o(____)o(____)o (___)o(____)o(____)o(___)o(____)o(__)120 3318 y(int)47 b(fits_get_colnum\(fitsfile)41 b(*fptr,)46 b(int)h(casesen,)f(char)g (*template,)1075 3430 y(int)g(*colnum,)g(int)h(*status\))120 3543 y(int)g(fits_get_colname\(fitsfil)o(e)42 b(*fptr,)k(int)h (casesen,)e(char)i(*template,)1075 3656 y(char)f(*colname,)f(int)i (*colnum,)f(int)h(*status\))261 3869 y Ff(Get)33 b(the)e(column)g(n)m (um)m(b)s(er)f(\(starting)j(with)e(1,)h(not)g(0\))g(of)f(the)h(column)f (whose)g(name)h(matc)m(hes)g(the)120 3982 y(sp)s(eci\014ed)38 b(template)i(name.)66 b(The)38 b(only)h(di\013erence)g(in)f(these)h(2)g (routines)g(is)f(that)i(the)e(2nd)g(one)h(also)120 4095 y(returns)29 b(the)i(name)f(of)h(the)f(column)g(that)h(matc)m(hed)h (the)e(template)i(string.)261 4208 y(Normally)-8 b(,)29 b Fc(casesen)24 b Ff(should)h(b)s(e)h(set)h(to)g Fc(CASEINSEN)p Ff(,)d(but)i(it)g(ma)m(y)h(b)s(e)f(set)h(to)g Fc(CASESEN)d Ff(to)j(force)g(the)120 4320 y(name)j(matc)m(hing)i(to)f(b)s(e)f (case-sensitiv)m(e.)261 4433 y(The)22 b(input)f Fc(template)f Ff(string)i(giv)m(es)i(the)e(name)h(of)f(the)h(desired)e(column)h(and)g (ma)m(y)h(include)f(wildcard)120 4546 y(c)m(haracters:)41 b(a)30 b(`*')g(matc)m(hes)g(an)m(y)f(sequence)g(of)h(c)m(haracters)g (\(including)f(zero)h(c)m(haracters\),)h(`?')40 b(matc)m(hes)120 4659 y(an)m(y)45 b(single)g(c)m(haracter,)50 b(and)44 b(`#')h(matc)m(hes)g(an)m(y)g(consecutiv)m(e)i(string)d(of)h(decimal)h (digits)f(\(0-9\).)85 b(If)120 4772 y(more)27 b(than)g(one)g(column)g (name)g(in)g(the)g(table)h(matc)m(hes)g(the)f(template)h(string,)g (then)f(the)g(\014rst)f(matc)m(h)i(is)120 4885 y(returned)22 b(and)h(the)h(status)f(v)-5 b(alue)24 b(will)g(b)s(e)f(set)h(to)g Fc(COL)p 1962 4885 V 33 w(NOT)p 2139 4885 V 34 w(UNIQUE)e Ff(as)h(a)h(w)m(arning)f(that)h(a)g(unique)e(matc)m(h)120 4998 y(w)m(as)34 b(not)g(found.)50 b(T)-8 b(o)35 b(\014nd)d(the)i(next) g(column)g(that)h(matc)m(hes)g(the)f(template,)i(call)g(this)d(routine) h(again)120 5111 y(lea)m(ving)e(the)f(input)e(status)i(v)-5 b(alue)31 b(equal)g(to)g Fc(COL)p 1832 5111 V 33 w(NOT)p 2009 5111 V 34 w(UNIQUE)p Ff(.)e(Rep)s(eat)i(this)f(pro)s(cess)g(un)m (til)h Fc(status)46 b(=)120 5224 y(COL)p 270 5224 V 34 w(NOT)p 448 5224 V 33 w(FOUND)29 b Ff(is)h(returned.)120 5436 y Fc(________________________)o(____)o(____)o(___)o(____)o(____)o (___)o(____)o(____)o(___)o(____)o(__)120 5549 y(int)47 b(fits_get_coltype\(fitsfil)o(e)42 b(*fptr,)k(int)h(colnum,)f(int)h (*typecode,)1905 5809 y Ff(13)p eop end %%Page: 14 14 TeXDict begin 14 13 bop 1122 573 a Fc(long)47 b(*repeat,)e(long)i (*width,)f(int)h(*status\))120 799 y(int)g(fits_get_eqcoltype\(fitsf)o (ile)41 b(*fptr,)46 b(int)h(colnum,)f(int)h(*typecode,)1122 912 y(long)g(*repeat,)e(long)i(*width,)f(int)h(*status\))261 1106 y Ff(Return)41 b(the)h(datat)m(yp)s(e,)k(v)m(ector)d(rep)s(eat)f (coun)m(t,)j(and)c(the)h(width)f(in)g(b)m(ytes)h(of)g(a)g(single)h (column)120 1219 y(elemen)m(t)h(for)d(column)h(n)m(um)m(b)s(er)f Fc(colnum)p Ff(.)74 b(Allo)m(w)m(ed)44 b(v)-5 b(alues)42 b(for)g(the)g(returned)f(datat)m(yp)s(e)i(in)f(ASCI)s(I)120 1332 y(tables)31 b(are:)42 b Fc(TSTRING,)j(TSHORT,)h(TLONG,)g(TFLOAT,)g (and)h(TDOUBLE)p Ff(.)29 b(Binary)i(tables)g(supp)s(ort)e(these)120 1445 y(additional)22 b(t)m(yp)s(es:)36 b Fc(TLOGICAL,)45 b(TBIT,)h(TBYTE,)g(TINT32BIT,)f(TCOMPLEX)h(and)h(TDBLCOMPLEX)p Ff(.)18 b(The)120 1558 y(negativ)m(e)33 b(of)d(the)h(datat)m(yp)s(e)g (co)s(de)g(v)-5 b(alue)30 b(is)h(returned)e(if)h(it)h(is)g(a)f(v)-5 b(ariable)32 b(length)e(arra)m(y)h(column.)261 1671 y(These)36 b(2)h(routines)f(are)h(similar,)h(except)f(that)g(in)f(the)g(case)i(of) e(scaled)h(in)m(teger)h(columns)e(the)g(2nd)120 1784 y(routine,)28 b(\014t)p 547 1784 28 4 v 33 w(get)p 700 1784 V 34 w(eqcolt)m(yp)s(e,)i(returns)c(the)i('equiv)-5 b(alen)m(t')29 b(datat)m(yp)s(e)g(that)f(is)f(needed)h(to)g(store)g (the)g(scaled)120 1897 y(v)-5 b(alues,)34 b(whic)m(h)e(is)h(not)g (necessarily)g(the)g(same)g(as)g(the)g(ph)m(ysical)g(datat)m(yp)s(e)h (of)f(the)g(unscaled)f(v)-5 b(alues)33 b(as)120 2010 y(stored)h(in)g(the)h(FITS)e(table.)54 b(F)-8 b(or)35 b(example)f(if)h(a)f('1I')h(column)f(in)g(a)h(binary)e(table)j(has)e (TSCALn)e(=)i(1)120 2122 y(and)f(TZER)m(On)f(=)h(32768,)k(then)d(this)f (column)h(e\013ectiv)m(ely)i(con)m(tains)f(unsigned)d(short)i(in)m (teger)h(v)-5 b(alues,)120 2235 y(and)32 b(th)m(us)h(the)g(returned)f (v)-5 b(alue)34 b(of)f(t)m(yp)s(eco)s(de)g(will)h(b)s(e)e(TUSHOR)-8 b(T,)32 b(not)i(TSHOR)-8 b(T.)32 b(Or,)h(if)g(TSCALn)120 2348 y(or)g(TZER)m(On)e(are)j(not)f(in)m(tegers,)i(then)d(the)h(equiv) -5 b(alen)m(t)34 b(datat)m(yp)s(e)g(will)f(b)s(e)g(returned)e(as)i (TFLO)m(A)-8 b(T)33 b(or)120 2461 y(TDOUBLE,)e(dep)s(ending)d(on)j(the) f(size)i(of)e(the)h(in)m(teger.)261 2574 y(The)e(rep)s(eat)h(coun)m(t)h (is)e(alw)m(a)m(ys)j(1)e(in)f(ASCI)s(I)f(tables.)42 b(The)29 b('rep)s(eat')h(parameter)g(returns)f(the)h(v)m(ector)120 2687 y(rep)s(eat)23 b(coun)m(t)h(on)f(the)h(binary)e(table)j(TF)m(ORMn) e(k)m(eyw)m(ord)g(v)-5 b(alue.)39 b(\(ASCI)s(I)22 b(table)i(columns)f (alw)m(a)m(ys)i(ha)m(v)m(e)120 2800 y(rep)s(eat)35 b(=)f(1\).)55 b(The)34 b('width')h(parameter)g(returns)f(the)h(width)f(in)g(b)m(ytes) i(of)f(a)g(single)g(column)g(elemen)m(t)120 2913 y(\(e.g.,)h(a)e('10D') h(binary)d(table)i(column)f(will)h(ha)m(v)m(e)g(width)f(=)g(8,)h(an)f (ASCI)s(I)f(table)i('F12.2')i(column)d(will)120 3026 y(ha)m(v)m(e)39 b(width)d(=)h(12,)j(and)d(a)h(binary)f(table'60A')i(c)m (haracter)g(string)f(column)f(will)h(ha)m(v)m(e)g(width)f(=)g(60\);)120 3139 y(Note)43 b(that)g(this)f(routine)f(supp)s(orts)g(the)h(lo)s(cal)h (con)m(v)m(en)m(tion)h(for)e(sp)s(ecifying)f(arra)m(ys)i(of)f(\014xed)f (length)120 3252 y(strings)32 b(within)f(a)h(binary)f(table)i(c)m (haracter)h(column)d(using)h(the)g(syn)m(tax)g(TF)m(ORM)h(=)e('rAw')h (where)f('r')120 3364 y(is)f(the)g(total)i(n)m(um)m(b)s(er)d(of)h(c)m (haracters)i(\(=)e(the)g(width)g(of)g(the)g(column\))h(and)e('w')h(is)g (the)h(width)e(of)h(a)h(unit)120 3477 y(string)h(within)f(the)h (column.)45 b(Th)m(us)31 b(if)h(the)g(column)f(has)h(TF)m(ORM)g(=)f ('60A12')k(then)c(this)h(means)g(that)120 3590 y(eac)m(h)38 b(ro)m(w)f(of)g(the)g(table)h(con)m(tains)g(5)g(12-c)m(haracter)i (substrings)35 b(within)i(the)g(60-c)m(haracter)j(\014eld,)e(and)120 3703 y(th)m(us)33 b(in)g(this)h(case)g(this)g(routine)f(will)h(return)e (t)m(yp)s(eco)s(de)i(=)f(TSTRING,)g(rep)s(eat)h(=)f(60,)i(and)e(width)g (=)120 3816 y(12.)47 b(The)31 b(n)m(um)m(b)s(er)g(of)h(substings)g(in)f (an)m(y)i(binary)e(table)i(c)m(haracter)h(string)e(\014eld)g(can)g(b)s (e)f(calculated)j(b)m(y)120 3929 y(\(rep)s(eat/width\).)47 b(A)33 b(n)m(ull)f(p)s(oin)m(ter)g(ma)m(y)h(b)s(e)f(giv)m(en)h(for)f (an)m(y)h(of)f(the)h(output)f(parameters)g(that)h(are)g(not)120 4042 y(needed.)120 4237 y Fc(________________________)o(____)o(____)o (___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o (____)o(____)120 4349 y(int)47 b(fits_insert_rows\(fitsfil)o(e)42 b(*fptr,)k(long)h(firstrow,)e(long)h(nrows,)h(int)f(*status\))120 4462 y(int)h(fits_delete_rows\(fitsfil)o(e)42 b(*fptr,)k(long)h (firstrow,)e(long)h(nrows,)h(int)f(*status\))120 4575 y(int)h(fits_delete_rowrange\(fit)o(sfil)o(e)42 b(*fptr,)k(char)g (*rangelist,)f(int)i(*status\))120 4688 y(int)g (fits_delete_rowlist\(fits)o(file)41 b(*fptr,)46 b(long)h(*rowlist,)e (long)i(nrows,)f(int)h(*stat\))261 4883 y Ff(Insert)33 b(or)g(delete)h(ro)m(ws)f(in)f(a)i(table.)49 b(The)33 b(blank)f(ro)m(ws)h(are)h(inserted)e(immediately)j(follo)m(wing)f(ro)m (w)120 4996 y Fc(frow)p Ff(.)54 b(Set)35 b Fc(frow)f Ff(=)g(0)i(to)f(insert)g(ro)m(ws)g(at)h(the)f(b)s(eginning)g(of)g(the)g (table.)56 b(The)34 b(\014rst)h('delete')h(routine)120 5109 y(deletes)k Fc(nrows)d Ff(ro)m(ws)i(b)s(eginning)f(with)h(ro)m(w)g Fc(firstrow)p Ff(.)64 b(The)38 b(2nd)g(delete)i(routine)f(tak)m(es)i (an)d(input)120 5222 y(string)27 b(listing)h(the)f(ro)m(ws)f(or)h(ro)m (w)g(ranges)g(to)h(b)s(e)e(deleted)i(\(e.g.,)h('2,4-7,)h(9-12'\).)42 b(The)26 b(last)i(delete)g(routine)120 5334 y(tak)m(es)35 b(an)f(input)e(long)i(in)m(teger)h(arra)m(y)g(that)f(sp)s(eci\014es)f (eac)m(h)i(individual)e(ro)m(w)h(to)g(b)s(e)f(deleted.)51 b(The)33 b(ro)m(w)120 5447 y(lists)j(m)m(ust)f(b)s(e)f(sorted)i(in)f (ascending)g(order.)55 b(All)36 b(these)g(routines)f(up)s(date)f(the)i (v)-5 b(alue)35 b(of)h(the)f Fc(NAXIS2)120 5560 y Ff(k)m(eyw)m(ord)c (to)g(re\015ect)g(the)f(new)g(n)m(um)m(b)s(er)f(of)i(ro)m(ws)f(in)g (the)h(table.)1905 5809 y(14)p eop end %%Page: 15 15 TeXDict begin 15 14 bop 120 573 a Fc(________________________)o(____)o (____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)o (___)o(____)o(_)120 686 y(int)47 b(fits_insert_col\(fitsfile)41 b(*fptr,)46 b(int)h(colnum,)f(char)h(*ttype,)e(char)i(*tform,)1075 799 y(int)f(*status\))120 912 y(int)h(fits_insert_cols\(fitsfil)o(e)42 b(*fptr,)k(int)h(colnum,)f(int)h(ncols,)f(char)g(**ttype,)1122 1024 y(char)h(**tform,)e(int)i(*status\))120 1250 y(int)g (fits_delete_col\(fitsfile)41 b(*fptr,)46 b(int)h(colnum,)f(int)h (*status\))261 1457 y Ff(Insert)25 b(or)g(delete)h(columns)f(in)f(a)i (table.)39 b Fc(colnum)24 b Ff(giv)m(es)i(the)f(p)s(osition)g(of)g(the) h(column)e(to)i(b)s(e)f(inserted)120 1570 y(or)34 b(deleted)g(\(where)g (the)g(\014rst)f(column)h(of)g(the)g(table)h(is)e(at)i(p)s(osition)f (1\).)52 b Fc(ttype)32 b Ff(and)h Fc(tform)g Ff(giv)m(e)i(the)120 1683 y(column)j(name)h(and)f(column)g(format,)j(where)d(the)h(allo)m(w) m(ed)i(format)d(co)s(des)h(are)g(listed)g(ab)s(o)m(v)m(e)h(in)e(the)120 1796 y(description)45 b(of)g(the)h Fc(fits)p 1088 1796 29 4 v 33 w(create)p 1409 1796 V 33 w(table)d Ff(routine.)85 b(The)45 b(2nd)f('insert')i(routine)f(inserts)g(m)m(ultiple)120 1909 y(columns,)33 b(where)g Fc(ncols)e Ff(is)i(the)g(n)m(um)m(b)s(er)e (of)i(columns)g(to)g(insert,)h(and)e Fc(ttype)f Ff(and)h Fc(tform)g Ff(are)h(arra)m(ys)120 2022 y(of)e(string)f(p)s(oin)m(ters)g (in)g(this)g(case.)120 2229 y Fc(________________________)o(____)o (____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)o (___)120 2342 y(int)47 b(fits_copy_col\(fitsfile)42 b(*infptr,)j (fitsfile)h(*outfptr,)f(int)i(incolnum,)502 2455 y(int)g(outcolnum,)e (int)i(create_col,)d(int)j(*status\);)261 2662 y Ff(Cop)m(y)31 b(a)g(column)g(from)f(one)i(table)f(HDU)h(to)g(another.)42 b(If)31 b Fc(create)p 2609 2662 V 32 w(col)f Ff(=)h(TR)m(UE)g(\(i.e.,)i (not)e(equal)120 2775 y(to)42 b(zero\),)k(then)41 b(a)h(new)f(column)g (will)h(b)s(e)f(inserted)g(in)h(the)f(output)g(table)i(at)f(p)s (osition)g Fc(outcolumn)p Ff(,)120 2888 y(otherwise)31 b(the)f(v)-5 b(alues)31 b(in)f(the)h(existing)g(output)f(column)g(will) h(b)s(e)f(o)m(v)m(erwritten.)120 3095 y Fc(________________________)o (____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o (____)o(___)o(____)o(__)120 3208 y(int)47 b(fits_write_col\(fitsfile)41 b(*fptr,)46 b(int)h(datatype,)f(int)h(colnum,)e(long)i(firstrow,)979 3321 y(long)g(firstelem,)e(long)h(nelements,)f(void)i(*array,)f(int)h (*status\))120 3434 y(int)g(fits_write_colnull\(fitsf)o(ile)41 b(*fptr,)46 b(int)h(datatype,)f(int)g(colnum,)979 3547 y(long)h(firstrow,)e(long)i(firstelem,)e(long)h(nelements,)979 3660 y(void)h(*array,)f(void)g(*nulval,)g(int)h(*status\))120 3772 y(int)g(fits_write_col_null\(fits)o(file)41 b(*fptr,)46 b(int)h(colnum,)f(long)g(firstrow,)979 3885 y(long)h(firstelem,)e(long) h(nelements,)f(int)i(*status\))120 4111 y(int)g (fits_read_col\(fitsfile)42 b(*fptr,)k(int)h(datatype,)e(int)i(colnum,) f(long)g(firstrow,)454 4224 y(long)h(firstelem,)e(long)h(nelements,)f (void)i(*nulval,)f(void)g(*array,)454 4337 y(int)h(*anynul,)f(int)g (*status\))261 4657 y Ff(W)-8 b(rite)45 b(or)e(read)g(elemen)m(ts)i(in) e(column)g(n)m(um)m(b)s(er)f Fc(colnum)p Ff(,)j(starting)f(with)f(ro)m (w)g Fc(firstsrow)e Ff(and)120 4770 y(elemen)m(t)34 b Fc(firstelem)c Ff(\(if)j(it)g(is)g(a)g(v)m(ector)h(column\).)47 b Fc(firstelem)30 b Ff(is)j(ignored)g(if)f(it)h(is)g(a)g(scalar)g (column.)120 4883 y(The)c Fc(nelements)f Ff(n)m(um)m(b)s(er)g(of)i (elemen)m(ts)i(are)e(read)g(or)f(written)h(con)m(tin)m(uing)h(on)f (successiv)m(e)h(ro)m(ws)f(of)g(the)120 4996 y(table)37 b(if)f(necessary)-8 b(.)59 b Fc(array)35 b Ff(is)h(the)h(address)e(of)h (an)g(arra)m(y)h(whic)m(h)f(either)h(con)m(tains)g(the)g(v)-5 b(alues)36 b(to)h(b)s(e)120 5109 y(written,)28 b(or)e(will)h(hold)g (the)f(returned)g(v)-5 b(alues)27 b(that)g(are)g(read.)39 b(When)27 b(reading,)h Fc(array)d Ff(m)m(ust)h(ha)m(v)m(e)i(b)s(een)120 5222 y(allo)s(cated)k(large)g(enough)e(to)h(hold)f(all)h(the)g (returned)e(v)-5 b(alues.)261 5334 y(There)40 b(are)h(3)h(di\013eren)m (t)f('write')g(column)g(routines:)61 b(The)40 b(\014rst)g(simply)g (writes)h(the)g(input)f(arra)m(y)120 5447 y(in)m(to)33 b(the)f(column.)44 b(The)31 b(second)h(is)g(similar,)g(except)h(that)f (it)g(substitutes)g(the)g(appropriate)f(n)m(ull)h(pixel)120 5560 y(v)-5 b(alue)36 b(in)e(the)i(column)e(for)h(an)m(y)h(input)e (arra)m(y)h(v)-5 b(alues)36 b(whic)m(h)f(are)g(equal)h(to)g Fc(*nulval)d Ff(\(note)j(that)f(this)1905 5809 y(15)p eop end %%Page: 16 16 TeXDict begin 16 15 bop 120 573 a Ff(parameter)39 b(giv)m(es)g(the)g (address)e(of)i(the)f(n)m(ull)g(pixel)h(v)-5 b(alue,)41 b(not)d(the)h(v)-5 b(alue)38 b(itself)7 b(\).)66 b(The)38 b(third)f(write)120 686 y(routine)28 b(sets)g(the)g(sp)s(eci\014ed)f (table)i(elemen)m(ts)g(to)g(a)f(n)m(ull)g(v)-5 b(alue.)40 b(New)28 b(ro)m(ws)g(will)g(b)s(e)g(automatical)i(added)120 799 y(to)h(the)g(table)g(if)f(the)h(write)f(op)s(eration)h(extends)g(b) s(ey)m(ond)e(the)i(curren)m(t)f(size)h(of)g(the)f(table.)261 912 y(When)42 b(reading)g(a)h(column,)i(CFITSIO)40 b(will)j(substitute) f(the)g(v)-5 b(alue)43 b(giv)m(en)g(b)m(y)f Fc(nulval)e Ff(for)i(an)m(y)120 1024 y(unde\014ned)25 b(elemen)m(ts)j(in)f(the)g (FITS)f(column,)i(unless)e Fc(nulval)f Ff(or)i Fc(*nulval)46 b(=)h(NULL)p Ff(,)26 b(in)h(whic)m(h)f(case)i(no)120 1137 y(c)m(hec)m(ks)k(will)f(b)s(e)e(made)i(for)f(unde\014ned)e(v)-5 b(alues)31 b(when)e(reading)i(the)f(column.)261 1250 y Fc(datatype)i Ff(sp)s(eci\014es)i(the)g(datat)m(yp)s(e)h(of)g(the)f (C)g Fc(array)e Ff(in)i(the)g(program,)i(whic)m(h)d(need)h(not)h(b)s(e) e(the)120 1363 y(same)42 b(as)f(the)g(in)m(trinsic)h(datat)m(yp)s(e)g (of)f(the)h(column)f(in)g(the)g(FITS)g(table.)74 b(The)40 b(follo)m(wing)j(sym)m(b)s(olic)120 1476 y(constan)m(ts)32 b(are)e(allo)m(w)m(ed)j(for)d(the)g(v)-5 b(alue)31 b(of)g Fc(datatype)p Ff(:)215 1650 y Fc(TSTRING)142 b(array)46 b(of)h(character)f(string)g(pointers)215 1763 y(TBYTE)238 b(unsigned)45 b(char)215 1876 y(TSHORT)190 b(signed)46 b(short)215 1989 y(TUSHORT)142 b(unsigned)45 b(short)215 2102 y(TINT)286 b(signed)46 b(int)215 2215 y(TUINT)238 b(unsigned)45 b(int)215 2328 y(TLONG)238 b(signed)46 b(long)215 2441 y(TLONGLONG)g(signed)g(8-byte)g(integer)215 2554 y(TULONG)190 b(unsigned)45 b(long)215 2667 y(TFLOAT)190 b(float)215 2779 y(TDOUBLE)142 b(double)261 2954 y Ff(Note)35 b(that)e Fc(TSTRING)f Ff(corresp)s(onds)g(to)h(the)h(C)f Fc(char**)e Ff(datat)m(yp)s(e,)k(i.e.,)h(a)d(p)s(oin)m(ter)g(to)h(an)f (arra)m(y)h(of)120 3067 y(p)s(oin)m(ters)c(to)h(an)g(arra)m(y)f(of)h(c) m(haracters.)261 3179 y(An)m(y)38 b(column,)j(regardless)d(of)h(it's)g (in)m(trinsic)f(datat)m(yp)s(e,)k(ma)m(y)d(b)s(e)e(read)h(as)h(a)f Fc(TSTRING)f Ff(c)m(haracter)120 3292 y(string.)i(The)24 b(displa)m(y)i(format)f(of)g(the)h(returned)e(strings)g(will)i(b)s(e)e (determined)h(b)m(y)g(the)g Fc(TDISPn)f Ff(k)m(eyw)m(ord,)120 3405 y(if)j(it)h(exists,)h(otherwise)f(a)f(default)h(format)g(will)f(b) s(e)g(used)f(dep)s(ending)g(on)i(the)f(datat)m(yp)s(e)h(of)g(the)f (column.)120 3518 y(The)22 b Fc(tablist)e Ff(example)j(utilit)m(y)h (program)e(\(a)m(v)-5 b(ailable)25 b(from)d(the)h(CFITSIO)e(w)m(eb)h (site\))i(uses)e(this)g(feature)120 3631 y(to)31 b(displa)m(y)g(all)g (the)g(v)-5 b(alues)30 b(in)g(a)h(FITS)f(table.)120 3805 y Fc(________________________)o(____)o(____)o(___)o(____)o(____)o(___)o (____)o(____)o(___)o(____)o(____)o(___)o(_)120 3918 y(int)47 b(fits_select_rows\(fitsfil)o(e)42 b(*infptr,)j(fitsfile)h(*outfptr,)f (char)i(*expr,)1122 4031 y(int)g(*status\))120 4144 y(int)g (fits_calculator\(fitsfile)41 b(*infptr,)46 b(char)g(*expr,)g(fitsfile) g(*outfptr,)1075 4257 y(char)g(*colname,)f(char)i(*tform,)f(int)h (*status\))261 4431 y Ff(These)26 b(are)h(2)g(of)g(the)f(most)h(p)s(o)m (w)m(erful)f(routines)h(in)f(the)h(CFITSIO)d(library)-8 b(.)40 b(\(See)27 b(the)g(full)f(CFITSIO)120 4544 y(Reference)37 b(Guide)f(for)g(a)h(description)f(of)g(sev)m(eral)i(related)f (routines\).)58 b(These)36 b(routines)g(can)h(p)s(erform)120 4657 y(complicated)47 b(transformations)f(on)f(tables)h(based)f(on)g (an)g(input)g(arithmetic)h(expression)f(whic)m(h)g(is)120 4770 y(ev)-5 b(aluated)38 b(for)e(eac)m(h)h(ro)m(w)g(of)g(the)f(table.) 60 b(The)36 b(\014rst)g(routine)g(will)h(select)h(or)f(cop)m(y)g(ro)m (ws)f(of)h(the)f(table)120 4883 y(for)i(whic)m(h)g(the)g(expression)g (ev)-5 b(aluates)40 b(to)f(TR)m(UE)g(\(i.e.,)i(not)e(equal)g(to)g (zero\).)65 b(The)38 b(second)g(routine)120 4996 y(writes)d(the)g(v)-5 b(alue)35 b(of)g(the)g(expression)g(to)h(a)f(column)g(in)f(the)h (output)g(table.)55 b(Rather)35 b(than)g(supplying)120 5109 y(the)j(expression)f(directly)h(to)g(these)g(routines,)i(the)d (expression)h(ma)m(y)g(also)g(b)s(e)f(written)h(to)g(a)g(text)g(\014le) 120 5222 y(\(con)m(tin)m(ued)f(o)m(v)m(er)f(m)m(ultiple)h(lines)e(if)h (necessary\))g(and)f(the)h(name)f(of)h(the)g(\014le,)h(prep)s(ended)c (with)i(a)h('@')120 5334 y(c)m(haracter,)c(ma)m(y)f(b)s(e)f(supplied)f (as)i(the)f(v)-5 b(alue)31 b(of)g(the)f('expr')g(parameter)h(\(e.g.)42 b('@\014lename.txt'\).)261 5447 y(The)26 b(arithmetic)h(expression)f (ma)m(y)h(b)s(e)f(a)g(function)g(of)g(an)m(y)h(column)f(or)g(k)m(eyw)m (ord)h(in)f(the)g(input)f(table)120 5560 y(as)31 b(sho)m(wn)e(in)h (these)h(examples:)1905 5809 y(16)p eop end %%Page: 17 17 TeXDict begin 17 16 bop 120 573 a Fc(Row)47 b(Selection)e(Expressions:) 263 686 y(counts)h(>)i(0)1240 b(uses)47 b(COUNTS)f(column)g(value)263 799 y(sqrt\()h(X**2)f(+)i(Y**2\))e(<)h(10.)572 b(uses)47 b(X)g(and)g(Y)h(column)e(values)263 912 y(\(X)h(>)h(10\))f(||)g(\(X)g (<)h(-10\))e(&&)h(\(Y)h(==)f(0\))142 b(used)47 b('or')g(and)g('and')f (operators)263 1024 y(gtifilter\(\))1190 b(filter)46 b(on)i(Good)e(Time)h(Intervals)263 1137 y(regfilter\("myregion.reg"\)) 518 b(filter)46 b(using)h(a)g(region)f(file)263 1250 y(@select.txt)1190 b(reads)47 b(expression)e(from)h(a)i(text)e(file)120 1363 y(Calculator)f(Expressions:)263 1476 y(#row)i(\045)g(10)1145 b(modulus)46 b(of)h(the)g(row)g(number)263 1589 y(counts/#exposure)807 b(Fn)47 b(of)h(COUNTS)e(column)g(and)h(EXPOSURE)e(keyword)263 1702 y(dec)i(<)h(85)f(?)g(cos\(dec)f(*)h(#deg\))g(:)g(0)143 b(Conditional)45 b(expression:)g(evaluates)g(to)1934 1815 y(cos\(dec\))g(if)i(dec)g(<)h(85,)f(else)f(0)263 1928 y(\(count{-1}+count+count{+1)o(}\)/3)o(.)137 b(running)46 b(mean)h(of)g(the)g(count)f(values)g(in)h(the)1934 2041 y(previous,)e(current,)g(and)i(next)g(rows)263 2154 y(max\(0,)f (min\(X,)g(1000\)\))619 b(returns)46 b(a)h(value)g(between)f(0)h(-)h (1000)263 2267 y(@calc.txt)1143 b(reads)47 b(expression)e(from)h(a)i (text)e(file)261 2479 y Ff(Most)40 b(standard)d(mathematical)k(op)s (erators)e(and)f(functions)g(are)h(supp)s(orted.)64 b(If)38 b(the)h(expression)120 2592 y(includes)34 b(the)h(name)f(of)h(a)f (column,)i(than)e(the)h(v)-5 b(alue)35 b(in)f(the)g(curren)m(t)h(ro)m (w)f(of)h(the)f(table)i(will)e(b)s(e)g(used)120 2705 y(when)f(ev)-5 b(aluating)35 b(the)f(expression)g(on)g(eac)m(h)h(ro)m (w.)51 b(An)34 b(o\013set)h(to)g(an)e(adjacen)m(t)j(ro)m(w)e(can)g(b)s (e)f(sp)s(eci\014ed)120 2818 y(b)m(y)d(including)g(the)g(o\013set)h(v) -5 b(alue)30 b(in)g(curly)g(brac)m(k)m(ets)h(after)g(the)f(column)g (name)g(as)g(sho)m(wn)g(in)g(one)g(of)g(the)120 2931 y(examples.)40 b(Keyw)m(ord)27 b(v)-5 b(alues)28 b(can)f(b)s(e)g (included)f(in)h(the)h(expression)f(b)m(y)g(preceding)g(the)h(k)m(eyw)m (ord)f(name)120 3044 y(with)h(a)h(`#')f(sign.)40 b(See)28 b(Section)i(5)e(of)h(this)f(do)s(cumen)m(t)g(for)g(more)g(discussion)g (of)g(the)h(expression)f(syn)m(tax.)261 3156 y Fc(gtifilter)h Ff(is)i(a)h(sp)s(ecial)g(function)f(whic)m(h)g(tests)h(whether)f(the)h Fc(TIME)e Ff(column)h(v)-5 b(alue)32 b(in)f(the)g(input)120 3269 y(table)39 b(falls)g(within)f(one)h(or)f(more)h(Go)s(o)s(d)f(Time) g(In)m(terv)-5 b(als.)66 b(By)39 b(default,)h(this)f(function)f(lo)s (oks)h(for)f(a)120 3382 y('GTI')27 b(extension)g(in)f(the)h(same)g (\014le)f(as)h(the)g(input)e(table.)41 b(The)26 b('GTI')g(table)i(con)m (tains)g Fc(START)d Ff(and)h Fc(STOP)120 3495 y Ff(columns)g(whic)m(h)h (de\014ne)f(the)g(range)h(of)g(eac)m(h)h(go)s(o)s(d)f(time)g(in)m(terv) -5 b(al.)41 b(See)27 b(section)g(5.4.3)i(for)d(more)h(details.)261 3608 y Fc(regfilter)35 b Ff(is)i(another)g(sp)s(ecial)h(function)f (whic)m(h)g(selects)h(ro)m(ws)g(based)e(on)h(whether)g(the)g(spatial) 120 3721 y(p)s(osition)23 b(asso)s(ciated)i(with)e(eac)m(h)i(ro)m(w)e (is)g(lo)s(cated)i(within)e(in)g(a)g(sp)s(eci\014ed)g(region)h(of)f (the)h(sky)-8 b(.)38 b(By)24 b(default,)120 3834 y(the)35 b Fc(X)g Ff(and)f Fc(Y)h Ff(columns)g(in)g(the)g(input)f(table)i(are)f (assumed)g(to)h(giv)m(e)g(the)f(p)s(osition)g(of)h(eac)m(h)g(ro)m(w.)55 b(The)120 3947 y(spatial)37 b(region)f(is)f(de\014ned)g(in)g(an)g(ASCI) s(I)f(text)j(\014le)e(whose)h(name)f(is)h(giv)m(en)g(as)g(the)g (argumen)m(t)g(to)g(the)120 4060 y Fc(regfilter)28 b Ff(function.)40 b(See)31 b(section)g(5.4.4)i(for)d(more)g(details.)261 4173 y(The)e Fc(infptr)e Ff(and)i Fc(outfptr)e Ff(parameters)j(in)f (these)g(routines)g(ma)m(y)h(p)s(oin)m(t)f(to)h(the)g(same)f(table)h (or)g(to)120 4286 y(di\013eren)m(t)i(tables.)43 b(In)31 b Fc(fits)p 1092 4286 29 4 v 33 w(select)p 1413 4286 V 33 w(rows)p Ff(,)f(if)g(the)i(input)d(and)i(output)f(tables)i(are)f (the)g(same)h(then)e(the)120 4399 y(ro)m(ws)e(that)h(do)f(not)g (satisfy)h(the)f(selection)i(expression)e(will)g(b)s(e)f(deleted)i (from)f(the)g(table.)41 b(Otherwise,)28 b(if)120 4511 y(the)j(output)g(table)h(is)f(di\013eren)m(t)h(from)f(the)g(input)f (table)i(then)f(the)g(selected)i(ro)m(ws)e(will)h(b)s(e)e(copied)i (from)120 4624 y(the)f(input)e(table)i(to)g(the)g(output)f(table.)261 4737 y(The)i(output)g(column)g(in)g Fc(fits)p 1376 4737 V 33 w(calculator)e Ff(ma)m(y)i(or)h(ma)m(y)g(not)f(already)h(exist.)47 b(If)32 b(it)h(exists)g(then)120 4850 y(the)44 b(calculated)h(v)-5 b(alues)44 b(will)g(b)s(e)f(written)h(to)g(that)h(column,)i(o)m(v)m (erwriting)e(the)e(existing)i(v)-5 b(alues.)81 b(If)120 4963 y(the)36 b(column)g(do)s(esn't)g(exist)g(then)g(the)g(new)g (column)f(will)i(b)s(e)e(app)s(ended)f(to)j(the)f(output)g(table.)58 b(The)120 5076 y Fc(tform)37 b Ff(parameter)i(can)f(b)s(e)g(used)g(to)h (sp)s(ecify)f(the)g(datat)m(yp)s(e)i(of)e(the)h(new)f(column)g(\(e.g.,) k(the)d Fc(TFORM)120 5189 y Ff(k)m(eyw)m(ord)26 b(v)-5 b(alue)26 b(as)g(in)g Fc('1E',)46 b(or)h('1J')p Ff(\).)25 b(If)h Fc(tform)e Ff(=)h(NULL)h(then)f(a)h(default)g(datat)m(yp)s(e)h (will)f(b)s(e)f(used,)120 5302 y(dep)s(ending)k(on)h(the)h(expression.) 120 5514 y Fc(________________________)o(____)o(____)o(___)o(____)o (____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(_)1905 5809 y Ff(17)p eop end %%Page: 18 18 TeXDict begin 18 17 bop 120 573 a Fc(int)47 b (fits_read_tblbytes\(fitsf)o(ile)41 b(*fptr,)46 b(long)h(firstrow,)e (long)i(firstchar,)1122 686 y(long)g(nchars,)f(unsigned)f(char)i (*array,)f(int)h(*status\))120 799 y(int)g(fits_write_tblbytes)42 b(\(fitsfile)k(*fptr,)g(long)g(firstrow,)g(long)g(firstchar,)1122 912 y(long)h(nchars,)f(unsigned)f(char)i(*array,)f(int)h(*status\))261 1124 y Ff(These)35 b(2)g(routines)f(pro)m(vide)h(lo)m(w-lev)m(el)j (access)e(to)f(tables)h(and)e(are)h(mainly)g(useful)f(as)h(an)g (e\016cien)m(t)120 1237 y(w)m(a)m(y)i(to)g(cop)m(y)g(ro)m(ws)f(of)g(a)h (table)g(from)f(one)g(\014le)g(to)h(another.)58 b(These)36 b(routines)g(simply)g(read)g(or)g(write)120 1350 y(the)30 b(sp)s(eci\014ed)g(n)m(um)m(b)s(er)f(of)h(consecutiv)m(e)j(c)m (haracters)e(\(b)m(ytes\))h(in)e(a)h(table,)g(without)f(regard)g(for)h (column)120 1463 y(b)s(oundaries.)84 b(F)-8 b(or)47 b(example,)j(to)c (read)f(or)h(write)f(the)h(\014rst)f(ro)m(w)g(of)h(a)g(table,)k(set)c Fc(firstrow)g(=)h(1,)120 1576 y(firstchar)e(=)j(1)p Ff(,)38 b(and)e Fc(nchars)46 b(=)i(NAXIS1)35 b Ff(where)h(the)h(length)g(of)g (a)h(ro)m(w)f(is)f(giv)m(en)i(b)m(y)f(the)g(v)-5 b(alue)37 b(of)120 1689 y(the)31 b Fc(NAXIS1)f Ff(header)h(k)m(eyw)m(ord.)43 b(When)31 b(reading)h(a)f(table,)i Fc(array)d Ff(m)m(ust)h(ha)m(v)m(e)h (b)s(een)f(declared)g(at)h(least)120 1802 y Fc(nchars)d Ff(b)m(ytes)i(long)g(to)g(hold)f(the)g(returned)f(string)i(of)f(b)m (ytes.)1905 5809 y(18)p eop end %%Page: 19 19 TeXDict begin 19 18 bop 120 573 a Fb(4.6)112 b(Header)38 b(Keyw)m(ord)f(I/O)h(Routines)120 744 y Ff(The)30 b(follo)m(wing)i (routines)e(read)g(and)g(write)h(header)f(k)m(eyw)m(ords)g(in)h(the)f (curren)m(t)g(HDU.)120 957 y Fc(________________________)o(____)o(____) o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)120 1070 y(int)47 b(fits_get_hdrspace\(fitsfi)o(le)42 b(*fptr,)k(int)h (*keysexist,)d(int)j(*morekeys,)1170 1183 y(int)g(*status\))120 1395 y Ff(Return)36 b(the)g(n)m(um)m(b)s(er)f(of)i(existing)g(k)m(eyw)m (ords)g(\(not)g(coun)m(ting)g(the)g(mandatory)f(END)h(k)m(eyw)m(ord\))g (and)120 1508 y(the)29 b(amoun)m(t)h(of)f(empt)m(y)h(space)g(curren)m (tly)f(a)m(v)-5 b(ailable)31 b(for)e(more)h(k)m(eyw)m(ords.)40 b(The)29 b Fc(morekeys)e Ff(parameter)120 1621 y(ma)m(y)k(b)s(e)f(set)h (to)g(NULL)f(if)g(it's)h(v)-5 b(alue)31 b(is)g(not)f(needed.)120 1834 y Fc(________________________)o(____)o(____)o(___)o(____)o(____)o (___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(___)120 1947 y(int)47 b(fits_read_record\(fitsfil)o(e)42 b(*fptr,)k(int)h (keynum,)f(char)g(*record,)g(int)h(*status\))120 2060 y(int)g(fits_read_card\(fitsfile)41 b(*fptr,)46 b(char)h(*keyname,)e (char)i(*record,)f(int)g(*status\))120 2172 y(int)h (fits_read_key\(fitsfile)42 b(*fptr,)k(int)h(datatype,)e(char)i (*keyname,)979 2285 y(void)g(*value,)f(char)g(*comment,)f(int)i (*status\))120 2511 y(int)g(fits_find_nextkey\(fitsfi)o(le)42 b(*fptr,)k(char)g(**inclist,)f(int)i(ninc,)1170 2624 y(char)g(**exclist,)e(int)i(nexc,)f(char)h(*card,)f(int)h(*status\))120 2850 y(int)g(fits_read_key_unit\(fitsf)o(ile)41 b(*fptr,)46 b(char)h(*keyname,)e(char)i(*unit,)1218 2963 y(int)g(*status\))261 3175 y Ff(These)d(routines)h(all)g(read)f(a)h(header)f(record)g(in)g (the)h(curren)m(t)f(HDU.)i(The)e(\014rst)f(routine)i(reads)120 3288 y(k)m(eyw)m(ord)40 b(n)m(um)m(b)s(er)f Fc(keynum)f Ff(\(where)i(the)g(\014rst)f(k)m(eyw)m(ord)i(is)f(at)h(p)s(osition)f (1\).)70 b(This)39 b(routine)h(is)g(most)120 3401 y(commonly)29 b(used)f(when)f(sequen)m(tially)j(reading)e(ev)m(ery)i(record)e(in)g (the)h(header)f(from)g(b)s(eginning)g(to)h(end.)120 3514 y(The)d(2nd)f(and)g(3rd)h(routines)g(read)g(the)g(named)f(k)m(eyw)m (ord)i(and)e(return)g(either)i(the)f(whole)g(record,)h(or)f(the)120 3627 y(k)m(eyw)m(ord)g(v)-5 b(alue)26 b(and)e(commen)m(t)j(string.)39 b(In)25 b(eac)m(h)h(case)h(an)m(y)e(non-signi\014can)m(t)h(trailing)h (blank)e(c)m(haracters)120 3740 y(in)30 b(the)h(strings)f(are)h (truncated.)261 3853 y(Wild)c(card)e(c)m(haracters)j(\(*,)g(?,)f(and)e (#\))h(ma)m(y)h(b)s(e)e(used)g(when)g(sp)s(ecifying)h(the)g(name)h(of)f (the)g(k)m(eyw)m(ord)120 3966 y(to)31 b(b)s(e)f(read,)g(in)g(whic)m(h)h (case)g(the)g(\014rst)e(matc)m(hing)j(k)m(eyw)m(ord)e(is)h(returned.) 261 4079 y(The)41 b Fc(datatype)e Ff(parameter)j(sp)s(eci\014es)f(the)g (C)g(datat)m(yp)s(e)h(of)g(the)f(returned)f(k)m(eyw)m(ord)i(v)-5 b(alue)42 b(and)120 4192 y(can)48 b(ha)m(v)m(e)h(one)f(of)g(the)f (follo)m(wing)i(sym)m(b)s(olic)f(constan)m(t)h(v)-5 b(alues:)76 b Fc(TSTRING,)46 b(TLOGICAL)f Ff(\(==)i(in)m(t\),)120 4304 y Fc(TBYTE)p Ff(,)d Fc(TSHORT)p Ff(,)f Fc(TUSHORT)p Ff(,)g Fc(TINT)p Ff(,)h Fc(TUINT)p Ff(,)f Fc(TLONG)p Ff(,)h Fc(TULONG)p Ff(,)f Fc(TFLOAT)p Ff(,)g Fc(TDOUBLE)p Ff(,)g Fc(TCOMPLEX)p Ff(,)g(and)120 4417 y Fc(TDBLCOMPLEX)p Ff(.)e(Data)k(t)m(yp)s(e)f(con)m(v)m(ersion)h(will)f(b)s(e)f(p)s (erformed)f(for)i(n)m(umeric)f(v)-5 b(alues)44 b(if)g(the)g(in)m (trinsic)120 4530 y(FITS)32 b(k)m(eyw)m(ord)h(v)-5 b(alue)33 b(do)s(es)f(not)g(ha)m(v)m(e)i(the)f(same)g(datat)m(yp)s(e.)48 b(The)32 b Fc(comment)e Ff(parameter)j(ma)m(y)g(b)s(e)f(set)120 4643 y(equal)f(to)g(NULL)f(if)h(the)f(commen)m(t)i(string)e(is)g(not)h (needed.)261 4756 y(The)21 b(4th)h(routine)g(pro)m(vides)g(an)g(easy)g (w)m(a)m(y)h(to)f(\014nd)e(all)j(the)f(k)m(eyw)m(ords)g(in)g(the)f (header)h(that)g(matc)m(h)h(one)120 4869 y(of)29 b(the)h(name)f (templates)h(in)f Fc(inclist)e Ff(and)h(do)h(not)h(matc)m(h)g(an)m(y)f (of)g(the)h(name)f(templates)h(in)f Fc(exclist)p Ff(.)120 4982 y Fc(ninc)37 b Ff(and)h Fc(nexc)f Ff(are)i(the)g(n)m(um)m(b)s(er)e (of)h(template)i(strings)e(in)g Fc(inclist)f Ff(and)h Fc(exclist)p Ff(,)g(resp)s(ectiv)m(ely)-8 b(.)120 5095 y(Wild)35 b(cards)f(\(*,)i(?,)f(and)f(#\))g(ma)m(y)h(b)s(e)f(used)f(in) h(the)g(templates)i(to)f(matc)m(h)g(m)m(ultiple)g(k)m(eyw)m(ords.)53 b(Eac)m(h)120 5208 y(time)36 b(this)f(routine)g(is)g(called)h(it)f (returns)f(the)h(next)h(matc)m(hing)g(80-b)m(yte)g(k)m(eyw)m(ord)g (record.)54 b(It)36 b(returns)120 5321 y(status)31 b(=)f Fc(KEY)p 640 5321 29 4 v 33 w(NO)p 769 5321 V 34 w(EXIST)f Ff(if)h(there)h(are)g(no)f(more)g(matc)m(hes.)261 5434 y(The)f(5th)g(routine)g(returns)f(the)i(k)m(eyw)m(ord)g(v)-5 b(alue)29 b(units)g(string,)g(if)h(an)m(y)-8 b(.)41 b(The)28 b(units)h(are)h(recorded)f(at)120 5546 y(the)i(b)s(eginning)e(of)i(the) f(k)m(eyw)m(ord)h(commen)m(t)h(\014eld)e(enclosed)h(in)f(square)g(brac) m(k)m(ets.)1905 5809 y(19)p eop end %%Page: 20 20 TeXDict begin 20 19 bop 120 573 a Fc(________________________)o(____)o (____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(__)120 686 y(int)47 b(fits_write_key\(fitsfile)41 b(*fptr,)46 b(int)h(datatype,)f(char)g(*keyname,)502 799 y(void)g(*value,)g(char)h (*comment,)e(int)i(*status\))120 912 y(int)g(fits_update_key\(fitsfile) 41 b(*fptr,)46 b(int)h(datatype,)e(char)i(*keyname,)502 1024 y(void)f(*value,)g(char)h(*comment,)e(int)i(*status\))120 1137 y(int)g(fits_write_record\(fitsfi)o(le)42 b(*fptr,)k(char)g (*card,)g(int)h(*status\))120 1363 y(int)g(fits_modify_comment\(fits)o (file)41 b(*fptr,)46 b(char)h(*keyname,)e(char)i(*comment,)502 1476 y(int)g(*status\))120 1589 y(int)g(fits_write_key_unit\(fits)o (file)41 b(*fptr,)46 b(char)h(*keyname,)e(char)i(*unit,)502 1702 y(int)g(*status\))261 1975 y Ff(W)-8 b(rite)32 b(or)f(mo)s(dify)g (a)g(k)m(eyw)m(ord)g(in)g(the)g(header)g(of)g(the)g(curren)m(t)g(HDU.)h (The)e(\014rst)g(routine)h(app)s(ends)120 2087 y(the)f(new)g(k)m(eyw)m (ord)g(to)h(the)f(end)g(of)g(the)g(header,)h(whereas)e(the)i(second)f (routine)g(will)g(up)s(date)g(the)g(v)-5 b(alue)120 2200 y(and)40 b(commen)m(t)h(\014elds)f(of)h(the)g(k)m(eyw)m(ord)g(if)f(it)h (already)h(exists,)h(otherwise)e(it)h(b)s(eha)m(v)m(es)f(lik)m(e)g(the) g(\014rst)120 2313 y(routine)33 b(and)f(app)s(ends)f(the)h(new)h(k)m (eyw)m(ord.)48 b(Note)34 b(that)f Fc(value)e Ff(giv)m(es)j(the)f (address)f(to)h(the)g(v)-5 b(alue)33 b(and)120 2426 y(not)e(the)g(v)-5 b(alue)32 b(itself.)43 b(The)31 b Fc(datatype)d Ff(parameter)k(sp)s (eci\014es)e(the)i(C)e(datat)m(yp)s(e)i(of)f(the)g(k)m(eyw)m(ord)h(v)-5 b(alue)120 2539 y(and)38 b(ma)m(y)g(ha)m(v)m(e)i(an)m(y)f(of)f(the)g(v) -5 b(alues)39 b(listed)g(in)f(the)g(description)g(of)h(the)f(k)m(eyw)m (ord)h(reading)f(routines,)120 2652 y(ab)s(o)m(v)m(e.)71 b(A)40 b(NULL)g(ma)m(y)h(b)s(e)e(en)m(tered)i(for)f(the)g(commen)m(t)h (parameter,)i(in)d(whic)m(h)g(case)h(the)f(k)m(eyw)m(ord)120 2765 y(commen)m(t)31 b(\014eld)f(will)h(b)s(e)f(unmo)s(di\014ed)e(or)i (left)i(blank.)261 2878 y(The)25 b(third)g(routine)h(is)g(more)g (primitiv)m(e)h(and)e(simply)g(writes)h(the)g(80-c)m(haracter)j Fc(card)c Ff(record)h(to)g(the)120 2991 y(header.)40 b(It)30 b(is)g(the)g(programmer's)f(resp)s(onsibilit)m(y)h(in)f(this)h (case)g(to)h(ensure)e(that)h(the)g(record)g(conforms)120 3104 y(to)h(all)g(the)g(FITS)f(format)g(requiremen)m(ts)h(for)f(a)h (header)f(record.)261 3217 y(The)42 b(fourth)f(routine)h(mo)s(di\014es) f(the)h(commen)m(t)h(string)f(in)g(an)f(existing)i(k)m(eyw)m(ord,)j (and)41 b(the)h(last)120 3329 y(routine)34 b(writes)g(or)g(up)s(dates)f (the)h(k)m(eyw)m(ord)h(units)e(string)h(for)g(an)g(existing)h(k)m(eyw)m (ord.)52 b(\(The)34 b(units)f(are)120 3442 y(recorded)d(at)h(the)g(b)s (eginning)f(of)g(the)h(k)m(eyw)m(ord)f(commen)m(t)i(\014eld)e(enclosed) h(in)f(square)g(brac)m(k)m(ets\).)120 3621 y Fc (________________________)o(____)o(____)o(___)o(____)o(____)o(___)o (____)o(____)o(___)o(____)o(____)o(__)120 3734 y(int)47 b(fits_write_comment\(fitsf)o(ile)41 b(*fptr,)46 b(char)h(*comment,)93 b(int)47 b(*status\))120 3847 y(int)g(fits_write_history\(fitsf)o(ile) 41 b(*fptr,)46 b(char)h(*history,)93 b(int)47 b(*status\))120 3960 y(int)g(fits_write_date\(fitsfile)41 b(*fptr,)94 b(int)47 b(*status\))261 4139 y Ff(W)-8 b(rite)22 b(a)f Fc(COMMENT,)46 b(HISTORY)p Ff(,)18 b(or)j Fc(DATE)e Ff(k)m(eyw)m(ord)i (to)h(the)f(curren)m(t)f(header.)37 b(The)20 b Fc(COMMENT)f Ff(k)m(eyw)m(ord)120 4252 y(is)38 b(t)m(ypically)i(used)d(to)h(write)h (a)f(commen)m(t)h(ab)s(out)e(the)i(\014le)f(or)f(the)i(data.)64 b(The)37 b Fc(HISTORY)f Ff(k)m(eyw)m(ord)i(is)120 4365 y(t)m(ypically)25 b(used)c(to)j(pro)m(vide)f(information)g(ab)s(out)f (the)h(history)f(of)h(the)g(pro)s(cessing)f(pro)s(cedures)g(that)h(ha)m (v)m(e)120 4478 y(b)s(een)36 b(applied)h(to)g(the)g(data.)61 b(The)36 b Fc(comment)f Ff(or)i Fc(history)e Ff(string)i(will)g(b)s(e)f (con)m(tin)m(ued)i(o)m(v)m(er)g(m)m(ultiple)120 4591 y(k)m(eyw)m(ords)31 b(if)f(it)h(is)f(more)h(than)f(70)h(c)m(haracters)h (long.)261 4704 y(The)k Fc(DATE)f Ff(k)m(eyw)m(ord)i(is)f(used)g(to)h (record)f(the)h(date)g(and)f(time)h(that)g(the)f(FITS)g(\014le)g(w)m (as)h(created.)120 4817 y(Note)f(that)f(this)f(\014le)h(creation)h (date)f(is)g(usually)f(di\013eren)m(t)h(from)f(the)h(date)g(of)g(the)f (observ)-5 b(ation)36 b(whic)m(h)120 4930 y(obtained)e(the)g(data)h(in) e(the)i(FITS)e(\014le.)51 b(The)33 b Fc(DATE)g Ff(k)m(eyw)m(ord)h(v)-5 b(alue)35 b(is)f(a)g(c)m(haracter)i(string)d(in)h('yyyy-)120 5042 y(mm-ddThh:mm:ss')27 b(format.)40 b(If)29 b(a)g Fc(DATE)f Ff(k)m(eyw)m(ord)i(already)f(exists)h(in)f(the)g(header,)h (then)e(this)h(routine)120 5155 y(will)i(up)s(date)e(the)i(v)-5 b(alue)31 b(with)f(the)g(curren)m(t)g(system)h(date.)120 5334 y Fc(________________________)o(____)o(____)o(___)o(____)o(____)o (___)o(____)o(____)o(___)o(____)o(____)o(__)120 5447 y(int)47 b(fits_delete_record\(fitsf)o(ile)41 b(*fptr,)46 b(int)h(keynum,)94 b(int)47 b(*status\))120 5560 y(int)g (fits_delete_key\(fitsfile)41 b(*fptr,)46 b(char)h(*keyname,)93 b(int)47 b(*status\))1905 5809 y Ff(20)p eop end %%Page: 21 21 TeXDict begin 21 20 bop 261 573 a Ff(Delete)33 b(a)e(k)m(eyw)m(ord)h (record.)42 b(The)30 b(\014rst)g(routine)h(deletes)h(a)f(k)m(eyw)m(ord) h(at)f(a)h(sp)s(eci\014ed)e(p)s(osition)h(\(the)120 686 y(\014rst)c(k)m(eyw)m(ord)h(is)f(at)h(p)s(osition)g(1,)h(not)e(0\),)i (whereas)f(the)f(second)h(routine)f(deletes)i(the)f(named)f(k)m(eyw)m (ord.)120 898 y Fc(________________________)o(____)o(____)o(___)o(____) o(____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(___)120 1011 y(int)47 b(fits_copy_header\(fitsfil)o(e)42 b(*infptr,)j(fitsfile) h(*outfptr,)93 b(int)47 b(*status\))261 1224 y Ff(Cop)m(y)26 b(all)h(the)f(header)g(k)m(eyw)m(ords)h(from)e(the)i(curren)m(t)e(HDU)i (asso)s(ciated)h(with)d(infptr)g(to)i(the)g(curren)m(t)120 1337 y(HDU)h(asso)s(ciated)g(with)e(outfptr.)39 b(If)27 b(the)g(curren)m(t)f(output)h(HDU)g(is)g(not)g(empt)m(y)-8 b(,)29 b(then)d(a)h(new)f(HDU)i(will)120 1450 y(b)s(e)34 b(app)s(ended)f(to)j(the)f(output)f(\014le.)54 b(The)35 b(output)f(HDU)i(will)f(then)f(ha)m(v)m(e)i(the)f(iden)m(tical)i (structure)d(as)120 1562 y(the)d(input)e(HDU,)i(but)f(will)h(con)m (tain)g(no)g(data.)1905 5809 y(21)p eop end %%Page: 22 22 TeXDict begin 22 21 bop 120 573 a Fb(4.7)112 b(Utilit)m(y)37 b(Routines)120 744 y Ff(This)30 b(section)h(lists)g(the)g(most)f(imp)s (ortan)m(t)h(CFITSIO)e(general)i(utilit)m(y)h(routines.)120 957 y Fc(________________________)o(____)o(____)o(___)o(____)o(____)o (___)o(____)o(____)o(___)o(____)o(____)o(__)120 1070 y(int)47 b(fits_write_chksum\()c(fitsfile)i(*fptr,)h(int)h(*status\)) 120 1183 y(int)g(fits_verify_chksum\(fitsf)o(ile)41 b(*fptr,)46 b(int)h(*dataok,)f(int)h(*hduok,)f(int)g(*status\))261 1395 y Ff(These)35 b(routines)g(compute)g(or)g(v)-5 b(alidate)36 b(the)g(c)m(hec)m(ksums)f(for)g(the)g(currenrt)f(HDU.)i(The)e Fc(DATASUM)120 1508 y Ff(k)m(eyw)m(ord)d(is)f(used)f(to)i(store)g(the)f (n)m(umerical)h(v)-5 b(alue)30 b(of)h(the)f(32-bit,)i(1's)e(complemen)m (t)h(c)m(hec)m(ksum)g(for)f(the)120 1621 y(data)25 b(unit)f(alone.)40 b(The)24 b Fc(CHECKSUM)f Ff(k)m(eyw)m(ord)i(is)g(used)e(to)j(store)f (the)g(ASCI)s(I)e(enco)s(ded)h(COMPLEMENT)120 1734 y(of)32 b(the)f(c)m(hec)m(ksum)h(for)f(the)h(en)m(tire)g(HDU.)h(Storing)e(the)h (complemen)m(t,)h(rather)e(than)g(the)h(actual)g(c)m(hec)m(k-)120 1847 y(sum,)26 b(forces)g(the)g(c)m(hec)m(ksum)g(for)f(the)h(whole)g (HDU)g(to)g(equal)g(zero.)40 b(If)25 b(the)h(\014le)g(has)f(b)s(een)g (mo)s(di\014ed)f(since)120 1960 y(the)31 b(c)m(hec)m(ksums)f(w)m(ere)h (computed,)g(then)f(the)g(HDU)i(c)m(hec)m(ksum)f(will)f(usually)g(not)h (equal)g(zero.)261 2073 y(The)f(returned)g Fc(dataok)f Ff(and)h Fc(hduok)g Ff(parameters)h(will)g(ha)m(v)m(e)h(a)f(v)-5 b(alue)31 b(=)g(1)g(if)g(the)g(data)g(or)g(HDU)g(is)120 2186 y(v)m(eri\014ed)d(correctly)-8 b(,)31 b(a)d(v)-5 b(alue)29 b(=)f(0)g(if)g(the)h Fc(DATASUM)d Ff(or)i Fc(CHECKSUM)e Ff(k)m(eyw)m(ord)j(is)f(not)g(presen)m(t,)h(or)f(v)-5 b(alue)29 b(=)120 2299 y(-1)i(if)f(the)h(computed)f(c)m(hec)m(ksum)h (is)g(not)f(correct.)120 2511 y Fc(________________________)o(____)o (____)o(___)o(____)o(____)o(___)o(____)o(____)o(___)o(____)o(____)o(__) 120 2624 y(int)47 b(fits_parse_value\(char)42 b(*card,)k(char)h (*value,)e(char)i(*comment,)e(int)i(*status\))120 2737 y(int)g(fits_get_keytype\(char)42 b(*value,)k(char)g(*dtype,)g(int)h (*status\))120 2850 y(int)g(fits_get_keyclass\(char)42 b(*card\))120 2963 y(int)47 b(fits_parse_template\(char)41 b(*template,)k(char)i(*card,)f(int)h(*keytype,)e(int)i(*status\))261 3288 y(fits)p 459 3288 29 4 v 33 w(parse)p 732 3288 V 33 w(value)29 b Ff(parses)h(the)h(input)e(80-c)m(hararacter)k(header)d (k)m(eyw)m(ord)h(record,)g(returning)e(the)120 3401 y(v)-5 b(alue)21 b(\(as)h(a)f(literal)h(c)m(haracter)h(string\))e(and)f (commen)m(t)i(strings.)38 b(If)20 b(the)h(k)m(eyw)m(ord)h(has)e(no)h(v) -5 b(alue)21 b(\(columns)120 3514 y(9-10)38 b(not)e(equal)h(to)g('=)f ('\),)j(then)d(a)g(n)m(ull)h(v)-5 b(alue)36 b(string)h(is)f(returned)f (and)h(the)g(commen)m(t)h(string)g(is)f(set)120 3627 y(equal)31 b(to)g(column)f(9)h(-)g(80)g(of)f(the)h(input)e(string.)261 3740 y Fc(fits)p 459 3740 V 33 w(get)p 636 3740 V 34 w(keytype)41 b Ff(parses)i(the)g(k)m(eyw)m(ord)h(v)-5 b(alue)43 b(string)g(to)h(determine)f(its)h(datat)m(yp)s(e.)80 b Fc(dtype)120 3853 y Ff(returns)34 b(with)g(a)h(v)-5 b(alue)36 b(of)f('C',)g('L',)g('I',)h('F')f(or)g('X',)h(for)f(c)m (haracter)h(string,)g(logical,)j(in)m(teger,)e(\015oating)120 3966 y(p)s(oin)m(t,)31 b(or)f(complex,)h(resp)s(ectiv)m(ely)-8 b(.)261 4079 y Fc(fits)p 459 4079 V 33 w(get)p 636 4079 V 34 w(keyclass)31 b Ff(returns)i(a)h(classi\014cation)h(co)s(de)f (that)g(indicates)h(the)f(classi\014cation)h(t)m(yp)s(e)f(of)120 4192 y(the)41 b(input)e(k)m(eyw)m(ord)i(record)f(\(e.g.,)45 b(a)40 b(required)g(structural)g(k)m(eyw)m(ord,)k(a)d(TDIM)f(k)m(eyw)m (ord,)k(a)c(W)m(CS)120 4304 y(k)m(eyw)m(ord,)49 b(a)d(commen)m(t)g(k)m (eyw)m(ord,)j(etc.)85 b(See)45 b(the)h(CFITSIO)d(Reference)j(Guide)e (for)h(a)g(list)h(of)f(the)120 4417 y(di\013eren)m(t)31 b(classi\014cation)h(co)s(des.)261 4530 y Fc(fits)p 459 4530 V 33 w(parse)p 732 4530 V 33 w(template)37 b Ff(tak)m(es)j(an)e (input)g(free)g(format)h(k)m(eyw)m(ord)g(template)h(string)f(and)f (returns)120 4643 y(a)i(formatted)g(80*c)m(har)h(record)e(that)h (satis\014es)g(all)h(the)e(FITS)g(requiremen)m(ts)h(for)f(a)h(header)f (k)m(eyw)m(ord)120 4756 y(record.)65 b(The)38 b(template)i(should)d (generally)j(con)m(tain)g(3)f(tok)m(ens:)58 b(the)38 b(k)m(eyw)m(ord)h(name,)i(the)e(k)m(eyw)m(ord)120 4869 y(v)-5 b(alue,)29 b(and)e(the)g(k)m(eyw)m(ord)h(commen)m(t)h(string.)40 b(The)27 b(returned)f Fc(keytype)g Ff(parameter)i(indicates)g(whether) 120 4982 y(the)33 b(k)m(eyw)m(ord)g(is)g(a)g(COMMENT)g(k)m(eyw)m(ord)g (or)g(not.)48 b(See)33 b(the)g(CFITSIO)e(Reference)j(Guide)f(for)f (more)120 5095 y(details.)1905 5809 y(22)p eop end %%Page: 23 23 TeXDict begin 23 22 bop 120 573 a Fh(5)135 b(CFITSIO)44 b(File)h(Names)h(and)f(Filters)120 779 y Fb(5.1)112 b(Creating)38 b(New)f(Files)120 951 y Ff(When)43 b(creating)h(a)f(new)g(output)f (\014le)h(on)g(magnetic)i(disk)d(with)h Fc(fits)p 2677 951 29 4 v 33 w(create)p 2998 951 V 33 w(file)f Ff(the)h(follo)m(wing) 120 1064 y(features)31 b(are)f(supp)s(orted.)256 1251 y Fa(\017)46 b Ff(Ov)m(erwriting,)31 b(or)f('Clobb)s(ering')g(an)h (Existing)f(File)347 1402 y(If)d(the)h(\014lename)g(is)g(preceded)f(b)m (y)g(an)h(exclamation)i(p)s(oin)m(t)d(\(!\))41 b(then)27 b(if)h(that)g(\014le)f(already)i(exists)f(it)347 1514 y(will)h(b)s(e)e(deleted)i(prior)e(to)i(creating)g(the)f(new)g(FITS)f (\014le.)40 b(Otherwise)27 b(if)h(there)g(is)g(an)g(existing)h(\014le) 347 1627 y(with)36 b(the)f(same)h(name,)i(CFITSIO)c(will)i(not)g(o)m(v) m(erwrite)h(the)f(existing)g(\014le)g(and)f(will)h(return)e(an)347 1740 y(error)28 b(status)h(co)s(de.)40 b(Note)30 b(that)f(the)f (exclamation)j(p)s(oin)m(t)d(is)g(a)h(sp)s(ecial)g(UNIX)f(c)m (haracter,)j(so)e(if)f(it)347 1853 y(is)f(used)f(on)g(the)h(command)g (line)g(rather)f(than)g(en)m(tered)i(at)f(a)g(task)g(prompt,)g(it)g(m)m (ust)g(b)s(e)f(preceded)347 1966 y(b)m(y)j(a)h(bac)m(kslash)g(to)g (force)g(the)f(UNIX)h(shell)f(to)i(pass)d(it)i(v)m(erbatim)g(to)g(the)g (application)g(program.)256 2154 y Fa(\017)46 b Ff(Compressed)30 b(Output)f(Files)347 2304 y(If)g(the)g(output)f(disk)h(\014le)g(name)g (ends)f(with)g(the)h(su\016x)f('.gz',)j(then)e(CFITSIO)e(will)i (compress)g(the)347 2417 y(\014le)39 b(using)g(the)g(gzip)h (compression)f(algorithm)h(b)s(efore)e(writing)h(it)h(to)g(disk.)66 b(This)38 b(can)i(reduce)347 2530 y(the)h(amoun)m(t)g(of)g(disk)f (space)h(used)f(b)m(y)g(the)h(\014le.)71 b(Note)42 b(that)f(this)g (feature)g(requires)f(that)h(the)347 2643 y(uncompressed)e(\014le)i(b)s (e)f(constructed)h(in)f(memory)g(b)s(efore)g(it)h(is)g(compressed)f (and)g(written)h(to)347 2756 y(disk,)30 b(so)h(it)g(can)g(fail)g(if)f (there)h(is)f(insu\016cien)m(t)h(a)m(v)-5 b(ailable)32 b(memory)-8 b(.)347 2906 y(One)32 b(can)h(also)h(sp)s(ecify)e(that)h (an)m(y)g(images)h(written)f(to)g(the)g(output)f(\014le)h(should)f(b)s (e)g(compressed)347 3019 y(using)23 b(the)g(newly)g(dev)m(elop)s(ed)h (`tile-compression')h(algorithm)f(b)m(y)f(app)s(ending)f(`[compress]')i (to)g(the)347 3132 y(name)36 b(of)h(the)f(disk)g(\014le)g(\(as)h(in)f Fc(myfile.fits[compress])p Ff(\).)52 b(Refer)36 b(to)h(the)g(CFITSIO)d (User's)347 3245 y(Reference)d(Guide)g(for)f(more)g(information)h(ab)s (out)f(this)g(new)g(image)i(compression)e(format.)256 3432 y Fa(\017)46 b Ff(Using)31 b(a)g(T)-8 b(emplate)31 b(to)g(Create)g(a)g(New)g(FITS)e(File)347 3583 y(The)k(structure)g(of)g (an)m(y)h(new)f(FITS)f(\014le)i(that)g(is)f(to)h(b)s(e)f(created)h(ma)m (y)g(b)s(e)f(de\014ned)f(in)h(an)g(ASCI)s(I)347 3695 y(template)d(\014le.)40 b(If)29 b(the)f(name)h(of)g(the)f(template)i (\014le)f(is)g(app)s(ended)d(to)k(the)e(name)h(of)g(the)f(FITS)g (\014le)347 3808 y(itself,)38 b(enclosed)e(in)f(paren)m(thesis)g (\(e.g.,)j Fc('newfile.fits\(template.tx)o(t\)')p Ff(\))29 b(then)35 b(CFITSIO)347 3921 y(will)c(create)i(a)e(FITS)f(\014le)h (with)f(that)i(structure)e(b)s(efore)h(op)s(ening)f(it)h(for)g(the)g (application)h(to)f(use.)347 4034 y(The)h(template)i(\014le)f (basically)g(de\014nes)f(the)h(dimensions)e(and)h(data)h(t)m(yp)s(e)g (of)g(the)f(primary)g(arra)m(y)347 4147 y(and)23 b(an)m(y)h(IMA)m(GE)g (extensions,)i(and)d(the)g(names)g(and)g(data)h(t)m(yp)s(es)g(of)f(the) h(columns)f(in)g(an)m(y)h(ASCI)s(I)347 4260 y(or)35 b(binary)g(table)h (extensions.)55 b(The)35 b(template)h(\014le)f(can)h(also)g(b)s(e)e (used)h(to)g(de\014ne)g(an)m(y)g(optional)347 4373 y(k)m(eyw)m(ords)g (that)g(should)e(b)s(e)h(written)g(in)h(an)m(y)f(of)h(the)f(HDU)h (headers.)53 b(The)34 b(image)h(pixel)g(v)-5 b(alues)347 4486 y(and)38 b(table)i(en)m(try)e(v)-5 b(alues)39 b(are)g(all)g (initialized)i(to)e(zero.)66 b(The)38 b(application)i(program)e(can)h (then)347 4599 y(write)28 b(actual)g(data)g(in)m(to)h(the)e(HDUs.)40 b(See)28 b(the)f(CFITSIO)f(Reference)i(Guide)f(for)g(for)g(a)h (complete)347 4712 y(description)j(of)f(the)h(template)h(\014le)e(syn)m (tax.)256 4899 y Fa(\017)46 b Ff(Creating)31 b(a)g(T)-8 b(emp)s(orary)30 b(Scratc)m(h)h(File)g(in)f(Memory)347 5050 y(It)38 b(is)g(sometimes)h(useful)e(to)i(create)g(a)f(temp)s (orary)g(output)f(\014le)h(when)f(testing)i(an)f(application)347 5162 y(program.)45 b(If)31 b(the)h(name)g(of)g(the)g(\014le)g(to)h(b)s (e)e(created)i(is)f(sp)s(eci\014ed)f(as)h Fc(mem:)42 b Ff(then)32 b(CFITSIO)e(will)347 5275 y(create)39 b(the)e(\014le)h(in) f(memory)g(where)f(it)i(will)g(p)s(ersist)e(only)h(un)m(til)h(the)f (program)g(closes)i(the)e(\014le.)347 5388 y(Use)e(of)g(this)g Fc(mem:)48 b Ff(output)34 b(\014le)h(usually)f(enables)h(the)g(program) f(to)i(run)d(faster,)j(and)e(of)h(course)347 5501 y(the)c(output)f (\014le)g(do)s(es)g(not)h(use)f(up)f(an)m(y)i(disk)f(space.)1905 5809 y(23)p eop end %%Page: 24 24 TeXDict begin 24 23 bop 120 573 a Fb(5.2)112 b(Op)s(ening)39 b(Existing)e(Files)120 744 y Ff(When)h(op)s(ening)f(a)i(\014le)f(with)g Fc(fits)p 1392 744 29 4 v 33 w(open)p 1617 744 V 33 w(file)p Ff(,)h(CFITSIO)e(can)h(read)g(a)g(v)-5 b(ariet)m(y)40 b(of)e(di\013eren)m(t)g(input)120 857 y(\014le)31 b(formats)g(and)g(is) g(not)g(restricted)h(to)g(only)f(reading)g(FITS)g(format)g(\014les)g (from)g(magnetic)h(disk.)43 b(The)120 970 y(follo)m(wing)32 b(t)m(yp)s(es)e(of)h(input)e(\014les)i(are)f(all)i(supp)s(orted:)256 1183 y Fa(\017)46 b Ff(FITS)30 b(\014les)g(compressed)g(with)g Fc(zip,)47 b(gzip)29 b Ff(or)i Fc(compress)347 1333 y Ff(If)36 b(CFITSIO)f(cannot)i(\014nd)e(the)i(sp)s(eci\014ed)f(\014le)g (to)h(op)s(en)f(it)h(will)g(automatically)i(lo)s(ok)e(for)f(a)h(\014le) 347 1446 y(with)k(the)f(same)h(ro)s(otname)h(but)d(with)i(a)g Fc(.gz,)46 b(.zip)p Ff(,)d(or)d Fc(.Z)g Ff(extension.)72 b(If)41 b(it)g(\014nds)e(suc)m(h)h(a)347 1559 y(compressed)d(\014le,)h (it)g(will)f(allo)s(cate)i(a)e(blo)s(c)m(k)g(of)g(memory)g(and)f (uncompress)f(the)i(\014le)g(in)m(to)h(that)347 1672 y(memory)25 b(space.)39 b(The)25 b(application)h(program)e(will)i(then) e(transparen)m(tly)h(op)s(en)f(this)h(virtual)g(FITS)347 1785 y(\014le)36 b(in)f(memory)-8 b(.)56 b(Compressed)35 b(\014les)g(can)h(only)g(b)s(e)e(op)s(ened)h(with)g('readonly',)j(not)e ('readwrite')347 1898 y(\014le)31 b(access.)256 2085 y Fa(\017)46 b Ff(FITS)30 b(\014les)g(on)g(the)h(in)m(ternet,)g(using)f Fc(ftp)g Ff(or)g Fc(http)f Ff(URLs)347 2236 y(Simply)22 b(pro)m(vide)h(the)h(full)e(URL)h(as)g(the)g(name)g(of)h(the)f(\014le)g (that)g(y)m(ou)h(w)m(an)m(t)f(to)h(op)s(en.)38 b(F)-8 b(or)23 b(example,)347 2348 y Fc(ftp://legacy.gsfc.nasa.go)o(v/so)o (ftwa)o(re/)o(fits)o(io/c)o(/te)o(stpr)o(og.s)o(td)347 2461 y Ff(will)37 b(op)s(en)e(the)h(CFITSIO)e(test)j(FITS)e(\014le)h (that)h(is)e(lo)s(cated)j(on)d(the)h Fc(legacy)f Ff(mac)m(hine.)58 b(These)347 2574 y(\014les)31 b(can)f(only)h(b)s(e)e(op)s(ened)h(with)g ('readonly')h(\014le)g(access.)256 2762 y Fa(\017)46 b Ff(FITS)30 b(\014les)g(on)g Fc(stdin)f Ff(or)i Fc(stdout)d Ff(\014le)j(streams)347 2912 y(If)j(the)g(name)h(of)f(the)h(\014le)f (to)h(b)s(e)f(op)s(ened)f(is)h Fc('stdin')f Ff(or)h Fc('-')f Ff(\(a)i(single)g(dash)e(c)m(haracter\))k(then)347 3025 y(CFITSIO)f(will)i(read)g(the)f(\014le)h(from)f(the)h(standard)f(input) f(stream.)63 b(Similarly)-8 b(,)40 b(if)e(the)g(output)347 3138 y(\014le)43 b(name)g(is)g Fc('stdout')e Ff(or)i Fc('-')p Ff(,)j(then)c(the)i(\014le)f(will)g(b)s(e)g(written)g(to)g (the)h(standard)e(output)347 3251 y(stream.)54 b(In)34 b(addition,)i(if)e(the)h(output)f(\014lename)h(is)g Fc('stdout.gz')c Ff(or)k Fc('-.gz')e Ff(then)h(it)h(will)g(b)s(e)347 3364 y(gzip)f(compressed)f(b)s(efore)g(b)s(eing)f(written)h(to)h(stdout.)49 b(This)33 b(mec)m(hanism)g(can)h(b)s(e)e(used)g(to)i(pip)s(e)347 3477 y(FITS)c(\014les)g(from)g(one)h(task)g(to)g(another)f(without)h (ha)m(ving)g(to)g(write)f(an)h(in)m(termediary)g(FITS)e(\014le)347 3590 y(on)i(magnetic)g(disk.)256 3777 y Fa(\017)46 b Ff(FITS)30 b(\014les)g(that)h(exist)g(only)g(in)f(memory)-8 b(,)31 b(or)f(shared)g(memory)-8 b(.)347 3928 y(In)38 b(some)i(applications,)i(suc)m(h)d(as)g(real)g(time)h(data)f (acquisition,)k(y)m(ou)c(ma)m(y)h(w)m(an)m(t)f(to)h(ha)m(v)m(e)g(one) 347 4040 y(pro)s(cess)31 b(write)g(a)h(FITS)e(\014le)h(in)m(to)h(a)g (certain)g(section)g(of)f(computer)g(memory)-8 b(,)32 b(and)f(then)f(b)s(e)h(able)347 4153 y(to)26 b(op)s(en)f(that)g(\014le) g(in)g(memory)g(with)g(another)g(pro)s(cess.)39 b(There)25 b(is)g(a)g(sp)s(ecialized)h(CFITSIO)e(op)s(en)347 4266 y(routine)f(called)i Fc(fits)p 1102 4266 V 33 w(open)p 1327 4266 V 33 w(memfile)d Ff(that)h(can)h(b)s(e)e(used)h(for)g(this)g (purp)s(ose.)37 b(See)23 b(the)g(\\CFITSIO)347 4379 y(User's)31 b(Reference)g(Guide")g(for)f(more)g(details.)256 4567 y Fa(\017)46 b Ff(IRAF)31 b(format)g(images)g(\(with)f Fc(.imh)g Ff(\014le)g(extensions\))347 4717 y(CFITSIO)38 b(supp)s(orts)g(reading)i(IRAF)g(format)g(images)h(b)m(y)f(con)m(v)m (erting)h(them)f(on)f(the)h(\015y)f(in)m(to)347 4830 y(FITS)27 b(images)i(in)e(memory)-8 b(.)40 b(The)28 b(application)g (program)g(then)f(reads)h(this)f(virtual)h(FITS)f(format)347 4943 y(image)36 b(in)f(memory)-8 b(.)55 b(There)34 b(is)h(curren)m(tly) g(no)g(supp)s(ort)e(for)i(writing)g(IRAF)g(format)g(images,)i(or)347 5056 y(for)30 b(reading)h(or)f(writing)h(IRAF)f(tables.)256 5243 y Fa(\017)46 b Ff(Image)31 b(arra)m(ys)g(in)f(ra)m(w)h(binary)e (format)347 5394 y(If)23 b(the)h(input)e(\014le)i(is)f(a)h(ra)m(w)f (binary)g(data)h(arra)m(y)-8 b(,)26 b(then)d(CFITSIO)f(will)h(con)m(v)m (ert)i(it)f(on)f(the)h(\015y)f(in)m(to)h(a)347 5507 y(virtual)g(FITS)e (image)j(with)e(the)h(basic)f(set)h(of)g(required)e(header)h(k)m(eyw)m (ords)h(b)s(efore)f(it)h(is)f(op)s(ened)f(b)m(y)1905 5809 y(24)p eop end %%Page: 25 25 TeXDict begin 25 24 bop 347 573 a Ff(the)31 b(application)g(program.)40 b(In)30 b(this)g(case)h(the)f(data)h(t)m(yp)s(e)g(and)e(dimensions)g (of)i(the)f(image)h(m)m(ust)347 686 y(b)s(e)c(sp)s(eci\014ed)f(in)h (square)g(brac)m(k)m(ets)h(follo)m(wing)h(the)e(\014lename)h(\(e.g.)41 b Fc(rawfile.dat[ib512,512])p Ff(\).)347 799 y(The)30 b(\014rst)g(c)m(haracter)i(inside)e(the)g(brac)m(k)m(ets)i(de\014nes)e (the)g(datat)m(yp)s(e)i(of)e(the)h(arra)m(y:)586 1049 y Fc(b)429 b(8-bit)47 b(unsigned)e(byte)586 1161 y(i)381 b(16-bit)47 b(signed)f(integer)586 1274 y(u)381 b(16-bit)47 b(unsigned)e(integer)586 1387 y(j)381 b(32-bit)47 b(signed)f(integer) 586 1500 y(r)h(or)h(f)142 b(32-bit)47 b(floating)e(point)586 1613 y(d)381 b(64-bit)47 b(floating)e(point)347 1863 y Ff(An)32 b(optional)g(second)g(c)m(haracter)h(sp)s(eci\014es)e(the)h (b)m(yte)h(order)e(of)g(the)h(arra)m(y)g(v)-5 b(alues:)44 b(b)31 b(or)h(B)g(indi-)347 1976 y(cates)27 b(big)e(endian)f(\(as)i(in) f(FITS)f(\014les)h(and)f(the)i(nativ)m(e)g(format)f(of)h(SUN)e(UNIX)i (w)m(orkstations)g(and)347 2089 y(Mac)35 b(PCs\))d(and)h(l)g(or)g(L)g (indicates)h(little)h(endian)e(\(nativ)m(e)i(format)e(of)g(DEC)h(OSF)e (w)m(orkstations)347 2202 y(and)41 b(IBM)g(PCs\).)73 b(If)41 b(this)g(c)m(haracter)h(is)g(omitted)g(then)e(the)i(arra)m(y)f (is)h(assumed)e(to)i(ha)m(v)m(e)g(the)347 2315 y(nativ)m(e)30 b(b)m(yte)f(order)e(of)h(the)h(lo)s(cal)g(mac)m(hine.)41 b(These)28 b(datat)m(yp)s(e)h(c)m(haracters)g(are)g(then)f(follo)m(w)m (ed)h(b)m(y)347 2428 y(a)d(series)g(of)f(one)h(or)f(more)h(in)m(teger)g (v)-5 b(alues)26 b(separated)g(b)m(y)f(commas)h(whic)m(h)f(de\014ne)g (the)g(size)i(of)e(eac)m(h)347 2540 y(dimension)30 b(of)h(the)f(ra)m(w) h(arra)m(y)-8 b(.)41 b(Arra)m(ys)31 b(with)f(up)f(to)i(5)g(dimensions)f (are)g(curren)m(tly)h(supp)s(orted.)347 2691 y(Finally)-8 b(,)35 b(a)e(b)m(yte)g(o\013set)g(to)g(the)g(p)s(osition)f(of)g(the)h (\014rst)f(pixel)g(in)g(the)h(data)g(\014le)f(ma)m(y)h(b)s(e)f(sp)s (eci\014ed)347 2804 y(b)m(y)c(separating)h(it)g(with)e(a)i(':')40 b(from)27 b(the)i(last)f(dimension)g(v)-5 b(alue.)40 b(If)28 b(omitted,)i(it)e(is)g(assumed)g(that)347 2917 y(the)h(o\013set)g(=)f(0.)41 b(This)27 b(parameter)i(ma)m(y)g(b)s(e)f (used)f(to)i(skip)f(o)m(v)m(er)i(an)m(y)e(header)g(information)h(in)f (the)347 3029 y(\014le)j(that)g(precedes)f(the)h(binary)e(data.)42 b(F)-8 b(urther)30 b(examples:)443 3279 y Fc(raw.dat[b10000])473 b(1-dimensional)44 b(10000)i(pixel)h(byte)f(array)443 3392 y(raw.dat[rb400,400,12])185 b(3-dimensional)44 b(floating)i(point) g(big-endian)f(array)443 3505 y(img.fits[ib512,512:2880)o(])d(reads)k (the)h(512)g(x)h(512)e(short)h(integer)f(array)g(in)h(a)1636 3618 y(FITS)g(file,)f(skipping)f(over)i(the)g(2880)g(byte)f(header)1905 5809 y Ff(25)p eop end %%Page: 26 26 TeXDict begin 26 25 bop 120 573 a Fb(5.3)112 b(Image)38 b(Filtering)120 744 y Fg(5.3.1)105 b(Extracting)35 b(a)g(subsection)h (of)f(an)g(image)120 916 y Ff(When)21 b(sp)s(ecifying)g(the)h(name)f (of)g(an)g(image)i(to)f(b)s(e)f(op)s(ened,)h(y)m(ou)g(can)f(select)i(a) f(rectangular)g(subsection)f(of)120 1029 y(the)29 b(image)g(to)g(b)s(e) f(extracted)i(and)e(op)s(ened)f(b)m(y)i(the)f(application)i(program.)40 b(The)28 b(application)i(program)120 1142 y(then)h(op)s(ens)f(a)i (virtual)g(image)g(that)g(only)f(con)m(tains)i(the)e(pixels)h(within)e (the)i(sp)s(eci\014ed)e(subsection.)44 b(T)-8 b(o)120 1255 y(do)33 b(this,)h(sp)s(ecify)f(the)h(the)f(range)h(of)f(pixels)g (\(start:end\))i(along)f(eac)m(h)g(axis)g(to)g(b)s(e)f(extracted)h (from)f(the)120 1368 y(original)e(image)h(enclosed)f(in)f(square)g (brac)m(k)m(ets.)42 b(Y)-8 b(ou)31 b(can)f(also)i(sp)s(ecify)e(an)g (optional)h(pixel)g(incremen)m(t)120 1481 y(\(start:end:step\))37 b(for)f(eac)m(h)g(axis)h(of)e(the)h(input)f(image.)58 b(A)36 b(pixel)g(step)g(=)f(1)h(will)g(b)s(e)f(assumed)g(if)h(it)g(is) 120 1594 y(not)29 b(sp)s(eci\014ed.)39 b(If)28 b(the)h(starting)g (pixel)g(is)f(larger)i(then)e(the)h(end)e(pixel,)j(then)e(the)h(image)h (will)e(b)s(e)g(\015ipp)s(ed)120 1706 y(\(pro)s(ducing)34 b(a)h(mirror)e(image\))j(along)g(that)f(dimension.)53 b(An)34 b(asterisk,)j('*',)g(ma)m(y)e(b)s(e)f(used)f(to)j(sp)s(ecify) 120 1819 y(the)25 b(en)m(tire)h(range)f(of)g(an)g(axis,)i(and)d('-*')i (will)g(\015ip)e(the)h(en)m(tire)h(axis.)39 b(In)24 b(the)h(follo)m (wing)i(examples,)g(assume)120 1932 y(that)k Fc(myfile.fits)c Ff(con)m(tains)32 b(a)f(512)g(x)g(512)g(pixel)g(2D)g(image.)215 2130 y Fc(myfile.fits[201:210,)43 b(251:260])i(-)j(opens)e(a)i(10)f(x)g (10)g(pixel)g(subimage.)215 2356 y(myfile.fits[*,)d(512:257])i(-)h (opens)g(a)g(512)g(x)h(256)e(image)h(consisting)e(of)406 2469 y(all)i(the)g(columns)f(in)h(the)g(input)f(image,)h(but)f(only)h (rows)g(257)406 2582 y(through)f(512.)95 b(The)46 b(image)h(will)f(be)i (flipped)d(along)i(the)g(Y)g(axis)406 2695 y(since)g(the)g(starting)e (row)i(is)g(greater)f(than)h(the)g(ending)406 2808 y(row.)215 3033 y(myfile.fits[*:2,)d(512:257:2])h(-)i(creates)f(a)i(256)e(x)i(128) f(pixel)f(image.)406 3146 y(Similar)g(to)h(the)g(previous)f(example,)f (but)i(only)g(every)f(other)h(row)406 3259 y(and)g(column)f(is)i(read)e (from)h(the)g(input)f(image.)215 3485 y(myfile.fits[-*,)e(*])j(-)h (creates)e(an)h(image)f(containing)f(all)i(the)g(rows)g(and)406 3598 y(columns)f(in)h(the)g(input)g(image,)f(but)h(flips)f(it)h(along)g (the)f(X)406 3711 y(axis.)261 3909 y Ff(If)33 b(the)g(arra)m(y)h(to)g (b)s(e)f(op)s(ened)f(is)i(in)f(an)g(Image)h(extension,)h(and)e(not)g (in)g(the)h(primary)e(arra)m(y)i(of)f(the)120 4022 y(\014le,)d(then)f (y)m(ou)g(need)g(to)h(sp)s(ecify)e(the)i(extension)g(name)f(or)g(n)m (um)m(b)s(er)f(in)g(square)h(brac)m(k)m(ets)i(b)s(efore)e(giving)120 4135 y(the)h(subsection)f(range,)h(as)g(in)f Fc(myfile.fits[1][-*,)42 b(*])29 b Ff(to)h(read)f(the)h(image)h(in)e(the)g(\014rst)g(extension) 120 4248 y(in)h(the)h(\014le.)120 4485 y Fg(5.3.2)105 b(Create)34 b(an)h(Image)g(b)m(y)g(Binning)h(T)-9 b(able)34 b(Columns)120 4657 y Ff(Y)-8 b(ou)40 b(can)f(also)h(create)h(and)d(op)s (en)h(a)g(virtual)h(image)g(b)m(y)f(binning)f(the)i(v)-5 b(alues)39 b(in)g(a)g(pair)g(of)h(columns)120 4770 y(of)f(a)h(FITS)f (table)h(\(in)f(other)h(w)m(ords,)h(create)g(a)e(2-D)i(histogram)f(of)f (the)g(v)-5 b(alues)40 b(in)f(the)g(2)h(columns\).)120 4883 y(This)34 b(tec)m(hnique)h(is)g(often)g(used)f(in)h(X-ra)m(y)h (astronom)m(y)f(where)f(eac)m(h)i(detected)g(X-ra)m(y)g(photon)f (during)120 4996 y(an)29 b(observ)-5 b(ation)29 b(is)g(recorded)g(in)f (a)h(FITS)f(table.)41 b(There)29 b(are)g(t)m(ypically)h(2)g(columns)e (in)g(the)h(table)h(called)120 5109 y Fc(X)35 b Ff(and)h Fc(Y)f Ff(whic)m(h)h(record)f(the)i(pixel)f(lo)s(cation)h(of)f(that)h (ev)m(en)m(t)g(in)e(a)i(virtual)f(2D)g(image.)59 b(T)-8 b(o)36 b(create)h(an)120 5222 y(image)28 b(from)e(this)h(table,)i(one)e (just)f(scans)h(the)g(X)g(and)f(Y)h(columns)g(and)f(coun)m(ts)h(up)f (ho)m(w)h(man)m(y)g(photons)120 5334 y(w)m(ere)k(recorded)g(in)g(eac)m (h)h(pixel)f(of)g(the)g(image.)44 b(When)30 b(table)i(binning)e(is)h (sp)s(eci\014ed,)g(CFITSIO)e(creates)120 5447 y(a)38 b(temp)s(orary)e(FITS)h(primary)f(arra)m(y)i(in)f(memory)g(b)m(y)g (computing)h(the)f(histogram)h(of)g(the)f(v)-5 b(alues)38 b(in)120 5560 y(the)29 b(sp)s(eci\014ed)f(columns.)40 b(After)29 b(the)g(histogram)g(is)g(computed)g(the)g(original)h(FITS)e (\014le)h(con)m(taining)h(the)1905 5809 y(26)p eop end %%Page: 27 27 TeXDict begin 27 26 bop 120 573 a Ff(table)25 b(is)e(closed)i(and)e (the)g(temp)s(orary)h(FITS)e(primary)h(arra)m(y)h(is)g(op)s(ened)f(and) g(passed)g(to)h(the)g(application)120 686 y(program.)39 b(Th)m(us,)27 b(the)g(application)h(program)f(nev)m(er)g(sees)h(the)f (original)h(FITS)e(table)i(and)e(only)h(sees)g(the)120 799 y(image)32 b(in)e(the)g(new)g(temp)s(orary)g(\014le)h(\(whic)m(h)f (has)g(no)g(extensions\).)261 912 y(The)f(table)h(binning)e(sp)s (eci\014er)h(is)h(enclosed)g(in)f(square)g(brac)m(k)m(ets)h(follo)m (wing)h(the)f(ro)s(ot)f(\014lename)h(and)120 1024 y(table)h(extension)g (name)g(or)f(n)m(um)m(b)s(er)f(and)h(b)s(egins)g(with)g(the)g(k)m(eyw)m (ord)h('bin',)g(as)f(in:)120 1137 y Fc('myfile.fits[events][bin)41 b(\(X,Y\)]')p Ff(.)20 b(In)h(this)h(case,)j(the)d(X)g(and)f(Y)h (columns)g(in)g(the)g('ev)m(en)m(ts')h(table)120 1250 y(extension)30 b(are)g(binned)f(up)f(to)j(create)g(the)f(image.)42 b(The)29 b(size)h(of)g(the)g(image)h(is)f(usually)f(determined)g(b)m(y) 120 1363 y(the)22 b Fc(TLMINn)d Ff(and)i Fc(TLMAXn)f Ff(header)h(k)m(eyw)m(ords)h(whic)m(h)f(giv)m(e)i(the)e(minim)m(um)g (and)g(maxim)m(um)g(allo)m(w)m(ed)i(pixel)120 1476 y(v)-5 b(alues)38 b(in)f(the)h(columns.)62 b(F)-8 b(or)38 b(instance)g(if)g Fc(TLMINn)46 b(=)h(1)37 b Ff(and)g Fc(TLMAXn)46 b(=)i(4096)36 b Ff(for)i(b)s(oth)e(columns,)120 1589 y(this)f(w)m(ould)g(generate)h (a)f(4096)i(x)e(4096)h(pixel)g(image)g(b)m(y)f(default.)54 b(This)34 b(is)h(rather)g(large,)j(so)d(y)m(ou)g(can)120 1702 y(also)e(sp)s(ecify)f(a)h(pixel)f(binning)f(factor)j(to)f(reduce)f (the)g(image)i(size.)47 b(F)-8 b(or)33 b(example)g(sp)s(ecifying)f(,)h Fc('[bin)120 1815 y(\(X,Y\))46 b(=)i(16]')29 b Ff(will)h(use)f(a)i (binning)d(factor)j(of)f(16,)h(whic)m(h)f(will)g(pro)s(duce)f(a)h(256)h (x)f(256)h(pixel)g(image)g(in)120 1928 y(the)g(previous)e(example.)261 2041 y(If)35 b(the)g(TLMIN)g(and)g(TLMAX)g(k)m(eyw)m(ords)g(don't)g (exist,)j(or)d(y)m(ou)g(w)m(an)m(t)h(to)g(o)m(v)m(erride)h(their)e(v)-5 b(alues,)120 2154 y(y)m(ou)36 b(can)h(sp)s(ecify)e(the)h(image)i(range) e(and)f(binning)g(factor)i(directly)-8 b(,)39 b(as)d(in)g Fc('[bin)46 b(X)i(=)f(1:4096:16,)120 2267 y(Y=1:4096:16]')p Ff(.)36 b(Y)-8 b(ou)28 b(can)g(also)g(sp)s(ecify)f(the)h(datat)m(yp)s (e)g(of)g(the)g(created)g(image)h(b)m(y)e(app)s(ending)f(a)i(b,)g(i,) 120 2379 y(j,)f(r,)g(or)f(d)f(\(for)h(8-bit)h(b)m(yte,)h(16-bit)g(in)m (tegers,)g(32-bit)f(in)m(teger,)i(32-bit)e(\015oating)g(p)s(oin)m(ts,)g (or)f(64-bit)i(double)120 2492 y(precision)36 b(\015oating)g(p)s(oin)m (t,)h(resp)s(ectiv)m(ely\))g(to)f(the)g('bin')f(k)m(eyw)m(ord)g(\(e.g.) 58 b Fc('[binr)46 b(\(X,Y\)]')33 b Ff(creates)k(a)120 2605 y(\015oating)j(p)s(oin)m(t)e(image\).)67 b(If)38 b(the)h(datat)m(yp)s(e)h(is)e(not)h(sp)s(eci\014ed)f(then)g(a)h(32-bit) h(in)m(teger)g(image)g(will)f(b)s(e)120 2718 y(created)31 b(b)m(y)g(default.)261 2831 y(If)39 b(the)h(column)f(name)g(is)h(not)f (sp)s(eci\014ed,)i(then)e(CFITSIO)f(will)i(\014rst)e(try)i(to)g(use)f (the)g('preferred)120 2944 y(column')c(as)g(sp)s(eci\014ed)f(b)m(y)h (the)g(CPREF)g(k)m(eyw)m(ord)g(if)g(it)h(exists)f(\(e.g.,)j('CPREF)d(=) g('DETX,DETY'\),)120 3057 y(otherwise)c(column)f(names)g('X',)i('Y')e (will)h(b)s(e)f(assumed)g(for)g(the)g(2)h(axes.)261 3170 y(Note)37 b(that)f(this)f(binning)f(sp)s(eci\014er)h(is)g(not)g (restricted)h(to)g(only)g(2D)g(images)g(and)f(can)g(b)s(e)g(used)g(to) 120 3283 y(create)f(1D,)f(3D,)g(or)g(4D)g(images)g(as)f(w)m(ell.)48 b(It)32 b(is)g(also)h(p)s(ossible)f(to)h(sp)s(ecify)f(a)g(w)m(eigh)m (ting)i(factor)g(that)e(is)120 3396 y(applied)d(during)g(the)g (binning.)40 b(Please)30 b(refer)g(to)g(the)g(\\CFITSIO)e(User's)i (Reference)g(Guide")g(for)f(more)120 3509 y(details)i(on)g(these)f(adv) -5 b(anced)31 b(features.)1905 5809 y(27)p eop end %%Page: 28 28 TeXDict begin 28 27 bop 120 573 a Fb(5.4)112 b(T)-9 b(able)38 b(Filtering)120 744 y Fg(5.4.1)105 b(Column)35 b(and)g(Keyw)m(ord)g (Filtering)120 916 y Ff(The)29 b(column)g(or)g(k)m(eyw)m(ord)h (\014ltering)g(sp)s(eci\014er)f(is)g(used)g(to)h(mo)s(dify)e(the)i (column)f(structure)g(and/or)g(the)120 1029 y(header)h(k)m(eyw)m(ords)h (in)f(the)h(HDU)g(that)g(w)m(as)g(selected)h(with)e(the)h(previous)f (HDU)h(lo)s(cation)h(sp)s(eci\014er.)40 b(It)120 1142 y(can)31 b(b)s(e)e(used)h(to)h(p)s(erform)e(the)i(follo)m(wing)g(t)m (yp)s(es)g(of)f(op)s(erations.)256 1354 y Fa(\017)46 b Ff(App)s(end)35 b(a)h(new)g(column)g(to)h(a)f(table)h(b)m(y)g(giving) g(the)f(column)g(name,)i(optionally)g(follo)m(w)m(ed)f(b)m(y)347 1467 y(the)c(datat)m(yp)s(e)h(in)e(paren)m(theses,)i(follo)m(w)m(ed)g (b)m(y)f(an)g(equals)g(sign)g(and)f(the)h(arithmetic)h(expression)347 1580 y(to)c(b)s(e)e(used)g(to)i(compute)f(the)g(v)-5 b(alue.)41 b(The)28 b(datat)m(yp)s(e)i(is)f(sp)s(eci\014ed)f(using)h (the)g(same)g(syn)m(tax)h(that)347 1693 y(is)k(allo)m(w)m(ed)h(for)e (the)g(v)-5 b(alue)34 b(of)g(the)f(FITS)g(TF)m(ORMn)g(k)m(eyw)m(ord)h (\(e.g.,)i('I',)e('J',)g('E',)f('D',)i(etc.)51 b(for)347 1806 y(binary)32 b(tables,)h(and)f('I8',)h(F12.3',)i('E20.12',)g(etc.) 47 b(for)32 b(ASCI)s(I)f(tables\).)47 b(If)32 b(the)g(datat)m(yp)s(e)h (is)f(not)347 1919 y(sp)s(eci\014ed)e(then)g(a)h(default)f(datat)m(yp)s (e)i(will)e(b)s(e)g(c)m(hosen)h(dep)s(ending)e(on)h(the)h(expression.) 256 2107 y Fa(\017)46 b Ff(Create)33 b(a)g(new)f(header)g(k)m(eyw)m (ord)h(b)m(y)f(giving)h(the)g(k)m(eyw)m(ord)g(name,)g(preceded)f(b)m(y) g(a)h(p)s(ound)d(sign)347 2220 y('#',)24 b(follo)m(w)m(ed)e(b)m(y)f(an) g(equals)g(sign)g(and)f(an)h(arithmetic)h(expression)f(for)g(the)g(v)-5 b(alue)21 b(of)g(the)h(k)m(eyw)m(ord.)347 2332 y(The)k(expression)g(ma) m(y)h(b)s(e)f(a)h(function)f(of)h(other)f(header)g(k)m(eyw)m(ord)h(v)-5 b(alues.)40 b(The)26 b(commen)m(t)h(string)347 2445 y(for)40 b(the)h(k)m(eyw)m(ord)g(ma)m(y)g(b)s(e)f(sp)s(eci\014ed)g(in)g(paren)m (theses)h(immediately)g(follo)m(wing)h(the)f(k)m(eyw)m(ord)347 2558 y(name.)256 2746 y Fa(\017)46 b Ff(Ov)m(erwrite)30 b(the)f(v)-5 b(alues)30 b(in)e(an)h(existing)i(column)d(or)i(k)m(eyw)m (ord)f(b)m(y)g(giving)h(the)g(name)f(follo)m(w)m(ed)h(b)m(y)347 2859 y(an)h(equals)f(sign)h(and)e(an)i(arithmetic)g(expression.)256 3046 y Fa(\017)46 b Ff(Select)36 b(a)e(set)g(of)h(columns)e(to)i(b)s(e) e(included)h(in)f(the)i(\014ltered)f(\014le)g(b)m(y)g(listing)g(the)h (column)e(names)347 3159 y(separated)c(with)f(semi-colons.)41 b(Wild)29 b(card)f(c)m(haracters)i(ma)m(y)e(b)s(e)g(used)f(in)h(the)h (column)f(names)g(to)347 3272 y(matc)m(h)33 b(m)m(ultiple)g(columns.)46 b(An)m(y)32 b(other)h(columns)e(in)h(the)h(input)e(table)i(will)f(not)h (app)s(ear)e(in)h(the)347 3385 y(\014ltered)f(\014le.)256 3573 y Fa(\017)46 b Ff(Delete)32 b(a)e(column)g(or)f(k)m(eyw)m(ord)h(b) m(y)g(listing)g(the)g(name)g(preceded)f(b)m(y)h(a)g(min)m(us)f(sign)g (or)h(an)g(excla-)347 3686 y(mation)h(mark)f(\(!\))256 3873 y Fa(\017)46 b Ff(Rename)31 b(an)f(existing)i(column)e(or)g(k)m (eyw)m(ord)h(with)f(the)h(syn)m(tax)g('NewName)g(==)f(OldName'.)261 4086 y(The)20 b(column)g(\014ltering)h(sp)s(eci\014er)e(is)i(enclosed)g (in)f(square)g(brac)m(k)m(ets)h(and)f(b)s(egins)g(with)g(the)g(string)h ('col'.)120 4199 y(Multiple)32 b(op)s(erations)f(can)g(b)s(e)f(p)s (erformed)f(b)m(y)i(separating)g(them)g(with)f(semi-colons.)43 b(F)-8 b(or)32 b(complex)f(or)120 4312 y(commonly)g(used)g(op)s (erations,)g(y)m(ou)h(can)f(write)g(the)g(column)g(\014lter)g(to)h(a)f (text)h(\014le,)f(and)g(then)f(use)h(it)g(b)m(y)120 4425 y(giving)g(the)g(name)f(of)h(the)f(text)i(\014le,)e(preceded)g(b)m(y)h (a)f('@')h(c)m(haracter.)261 4538 y(Some)g(examples:)215 4750 y Fc([col)47 b(PI=PHA)f(*)i(1.1)f(+)g(0.2])285 b(-)48 b(creates)e(new)g(PI)i(column)e(from)g(PHA)h(values)215 4976 y([col)g(rate)g(=)g(counts/exposure])91 b(-)48 b(creates)e(or)h (overwrites)e(the)i(rate)f(column)g(by)1743 5089 y(dividing)f(the)i (counts)f(column)g(by)i(the)1743 5202 y(EXPOSURE)d(keyword)h(value.)215 5428 y([col)h(TIME;)f(X;)i(Y])667 b(-)48 b(only)e(the)h(listed)f (columns)g(will)h(appear)1743 5540 y(in)g(the)g(filtered)e(file)1905 5809 y Ff(28)p eop end %%Page: 29 29 TeXDict begin 29 28 bop 215 686 a Fc([col)47 b(Time;*raw])713 b(-)48 b(include)e(the)g(Time)h(column)f(and)h(any)g(other)1743 799 y(columns)f(whose)g(name)h(ends)f(with)h('raw'.)215 1024 y([col)g(-TIME;)f(Good)h(==)g(STATUS])141 b(-)48 b(deletes)e(the)g(TIME)h(column)f(and)1743 1137 y(renames)g(the)g (STATUS)h(column)f(to)h(GOOD)215 1363 y([col)g(@colfilt.txt])569 b(-)48 b(uses)e(the)h(filtering)f(expression)f(in)1743 1476 y(the)i(colfilt.txt)d(text)j(file)261 1689 y Ff(The)30 b(original)i(\014le)f(is)g(not)g(c)m(hanged)g(b)m(y)g(this)g (\014ltering)g(op)s(eration,)g(and)f(instead)h(the)g(mo)s (di\014cations)120 1802 y(are)36 b(made)f(on)h(a)f(temp)s(orary)h(cop)m (y)g(of)f(the)h(input)e(FITS)h(\014le)h(\(usually)f(in)g(memory\),)j (whic)m(h)d(includes)120 1914 y(a)42 b(cop)m(y)g(of)g(all)g(the)g (other)g(HDUs)g(in)f(the)h(input)f(\014le.)74 b(The)41 b(original)i(input)e(\014le)g(is)h(closed)g(and)f(the)120 2027 y(application)32 b(program)e(op)s(ens)f(the)i(\014ltered)f(cop)m (y)h(of)g(the)g(\014le.)120 2268 y Fg(5.4.2)105 b(Ro)m(w)36 b(Filtering)120 2439 y Ff(The)22 b(ro)m(w)h(\014lter)g(is)g(used)f(to)h (select)h(a)g(subset)e(of)h(the)g(ro)m(ws)f(from)h(a)g(table)g(based)g (on)f(a)i(b)s(o)s(olean)e(expression.)120 2552 y(A)37 b(temp)s(orary)g(new)f(FITS)g(\014le)i(is)f(created)h(on)f(the)g(\015y) f(\(usually)h(in)g(memory\))g(whic)m(h)g(con)m(tains)h(only)120 2665 y(those)30 b(ro)m(ws)g(for)g(whic)m(h)g(the)g(ro)m(w)g(\014lter)g (expression)f(ev)-5 b(aluates)32 b(to)e(true)g(\(i.e.,)i(not)e(equal)g (to)h(zero\).)42 b(The)120 2778 y(primary)25 b(arra)m(y)i(and)e(an)m(y) h(other)h(extensions)f(in)g(the)g(input)f(\014le)h(are)h(also)g(copied) f(to)h(the)f(temp)s(orary)g(\014le.)120 2891 y(The)h(original)i(FITS)e (\014le)h(is)g(closed)g(and)g(the)g(new)f(temp)s(orary)g(\014le)h(is)g (then)f(op)s(ened)g(b)m(y)h(the)g(application)120 3004 y(program.)261 3117 y(The)f(ro)m(w)g(\014lter)g(expression)g(is)g (enclosed)g(in)g(square)g(brac)m(k)m(ets)h(follo)m(wing)h(the)e(\014le) g(name)g(and)f(exten-)120 3230 y(sion)32 b(name.)48 b(F)-8 b(or)33 b(example,)h Fc('file.fits[events][GRAD)o(E==5)o(0]')26 b Ff(selects)34 b(only)f(those)g(ro)m(ws)f(in)g(the)120 3342 y(EVENTS)e(table)h(where)f(the)g(GRADE)h(column)g(v)-5 b(alue)30 b(is)h(equal)g(to)g(50\).)261 3455 y(The)d(ro)m(w)h (\014ltering)f(expression)h(can)f(b)s(e)g(an)h(arbitrarily)f(complex)i (series)e(of)h(op)s(erations)g(p)s(erformed)120 3568 y(on)d(constan)m(ts,)i(k)m(eyw)m(ord)e(v)-5 b(alues,)27 b(and)e(column)h(data)g(tak)m(en)h(from)e(the)h(sp)s(eci\014ed)f(FITS)g (T)-8 b(ABLE)26 b(exten-)120 3681 y(sion.)40 b(The)27 b(expression)g(also)i(can)e(b)s(e)g(written)h(in)m(to)h(a)e(text)i (\014le)f(and)f(then)g(used)g(b)m(y)g(giving)h(the)g(\014lename)120 3794 y(preceded)i(b)m(y)g(a)h('@')g(c)m(haracter,)h(as)e(in)g Fc('[@rowfilt.txt]')p Ff(.)261 3907 y(Keyw)m(ord)40 b(and)f(column)h (data)g(are)h(referenced)f(b)m(y)f(name.)70 b(An)m(y)40 b(string)g(of)g(c)m(haracters)h(not)f(sur-)120 4020 y(rounded)30 b(b)m(y)i(quotes)g(\(ie,)h(a)g(constan)m(t)g(string\))f(or)f(follo)m(w) m(ed)j(b)m(y)d(an)h(op)s(en)f(paren)m(theses)h(\(ie,)i(a)e(function)120 4133 y(name\))e(will)f(b)s(e)g(initially)h(in)m(terpreted)g(as)f(a)h (column)f(name)g(and)g(its)h(con)m(ten)m(ts)h(for)e(the)g(curren)m(t)g (ro)m(w)g(in-)120 4246 y(serted)e(in)m(to)h(the)g(expression.)39 b(If)27 b(no)g(suc)m(h)g(column)g(exists,)i(a)e(k)m(eyw)m(ord)h(of)g (that)f(name)h(will)f(b)s(e)g(searc)m(hed)120 4359 y(for)34 b(and)f(its)h(v)-5 b(alue)35 b(used,)f(if)g(found.)50 b(T)-8 b(o)35 b(force)f(the)g(name)g(to)h(b)s(e)e(in)m(terpreted)h(as)h (a)f(k)m(eyw)m(ord)g(\(in)g(case)120 4472 y(there)28 b(is)g(b)s(oth)f(a)h(column)g(and)f(k)m(eyw)m(ord)h(with)g(the)g(same)g (name\),)h(precede)f(the)g(k)m(eyw)m(ord)h(name)e(with)h(a)120 4584 y(single)k(p)s(ound)d(sign,)j('#',)g(as)g(in)f Fc(#NAXIS2)p Ff(.)41 b(Due)32 b(to)g(the)f(generalities)j(of)d(FITS)g(column)g(and)g (k)m(eyw)m(ord)120 4697 y(names,)c(if)e(the)h(column)g(or)f(k)m(eyw)m (ord)h(name)g(con)m(tains)h(a)f(space)g(or)g(a)g(c)m(haracter)h(whic)m (h)f(migh)m(t)g(app)s(ear)f(as)120 4810 y(an)32 b(arithmetic)h(term)f (then)g(inclose)h(the)f(name)g(in)f('$')i(c)m(haracters)h(as)e(in)g Fc($MAX)46 b(PHA$)31 b Ff(or)h Fc(#$MAX-PHA$)p Ff(.)120 4923 y(The)e(names)g(are)h(case)g(insensitiv)m(e.)261 5036 y(T)-8 b(o)37 b(access)g(a)g(table)g(en)m(try)g(in)f(a)g(ro)m(w)h (other)f(than)g(the)h(curren)m(t)f(one,)i(follo)m(w)g(the)e(column's)g (name)120 5149 y(with)j(a)g(ro)m(w)g(o\013set)g(within)g(curly)f (braces.)66 b(F)-8 b(or)40 b(example,)i Fc('PHA)p Fa(f)p Fc(-3)p Fa(g)p Fc(')c Ff(will)h(ev)-5 b(aluate)40 b(to)g(the)f(v)-5 b(alue)120 5262 y(of)40 b(column)f(PHA,)h(3)g(ro)m(ws)f(ab)s(o)m(v)m(e) i(the)f(ro)m(w)g(curren)m(tly)f(b)s(eing)g(pro)s(cessed.)68 b(One)39 b(cannot)h(sp)s(ecify)f(an)120 5375 y(absolute)33 b(ro)m(w)f(n)m(um)m(b)s(er,)f(only)h(a)h(relativ)m(e)h(o\013set.)47 b(Ro)m(ws)32 b(that)h(fall)f(outside)g(the)h(table)g(will)f(b)s(e)f (treated)120 5488 y(as)g(unde\014ned,)d(or)i(NULLs.)1905 5809 y(29)p eop end %%Page: 30 30 TeXDict begin 30 29 bop 261 573 a Ff(Bo)s(olean)32 b(op)s(erators)f (can)g(b)s(e)g(used)f(in)g(the)h(expression)g(in)f(either)i(their)f(F) -8 b(ortran)31 b(or)g(C)f(forms.)42 b(The)120 686 y(follo)m(wing)32 b(b)s(o)s(olean)e(op)s(erators)h(are)g(a)m(v)-5 b(ailable:)311 886 y Fc("equal")428 b(.eq.)46 b(.EQ.)h(==)95 b("not)46 b(equal")476 b(.ne.)94 b(.NE.)h(!=)311 999 y("less)46 b(than")238 b(.lt.)46 b(.LT.)h(<)143 b("less)46 b(than/equal")188 b(.le.)94 b(.LE.)h(<=)47 b(=<)311 1112 y("greater)e(than")95 b(.gt.)46 b(.GT.)h(>)143 b("greater)45 b(than/equal")g(.ge.)94 b(.GE.)h(>=)47 b(=>)311 1225 y("or")572 b(.or.)46 b(.OR.)h(||)95 b("and")762 b(.and.)46 b(.AND.)h(&&)311 1337 y("negation")236 b(.not.)46 b(.NOT.)h(!)95 b("approx.)45 b(equal\(1e-7\)")92 b(~)261 1537 y Ff(Note)34 b(that)g(the)f(exclamation)i(p)s(oin)m(t,)f (')10 b(!',)34 b(is)f(a)h(sp)s(ecial)f(UNIX)g(c)m(haracter,)j(so)d(if)g (it)g(is)g(used)f(on)h(the)120 1650 y(command)f(line)h(rather)f(than)g (en)m(tered)h(at)g(a)g(task)g(prompt,)f(it)h(m)m(ust)f(b)s(e)g (preceded)g(b)m(y)g(a)h(bac)m(kslash)g(to)120 1763 y(force)e(the)g (UNIX)f(shell)h(to)g(ignore)g(it.)261 1876 y(The)c(expression)f(ma)m(y) i(also)g(include)f(arithmetic)h(op)s(erators)f(and)f(functions.)39 b(T)-8 b(rigonometric)29 b(func-)120 1989 y(tions)f(use)g(radians,)h (not)f(degrees.)40 b(The)28 b(follo)m(wing)i(arithmetic)f(op)s(erators) f(and)g(functions)f(can)i(b)s(e)e(used)120 2102 y(in)j(the)h (expression)f(\(function)g(names)g(are)h(case)h(insensitiv)m(e\):)311 2302 y Fc("addition")522 b(+)477 b("subtraction")d(-)311 2415 y("multiplication")234 b(*)477 b("division")618 b(/)311 2528 y("negation")522 b(-)477 b("exponentiation")330 b(**)143 b(^)311 2641 y("absolute)45 b(value")237 b(abs\(x\))g ("cosine")714 b(cos\(x\))311 2754 y("sine")g(sin\(x\))237 b("tangent")666 b(tan\(x\))311 2867 y("arc)47 b(cosine")427 b(arccos\(x\))93 b("arc)47 b(sine")619 b(arcsin\(x\))311 2979 y("arc)47 b(tangent")379 b(arctan\(x\))93 b("arc)47 b(tangent")475 b(arctan2\(x,y\))311 3092 y("exponential")378 b(exp\(x\))237 b("square)46 b(root")476 b(sqrt\(x\))311 3205 y("natural)45 b(log")381 b(log\(x\))237 b("common)46 b(log")524 b(log10\(x\))311 3318 y("modulus")570 b(i)48 b(\045)f(j)286 b("random)46 b(#)h([0.0,1.0\)")141 b(random\(\))311 3431 y("minimum")570 b(min\(x,y\))141 b("maximum")666 b(max\(x,y\))311 3544 y("if-then-else")330 b(b?x:y)261 3744 y Ff(The)37 b(follo)m(wing)i(t)m(yp)s(e)f(casting)g(op)s(erators)g (are)g(a)m(v)-5 b(ailable,)41 b(where)c(the)h(inclosing)g(paren)m (theses)g(are)120 3857 y(required)23 b(and)h(tak)m(en)h(from)f(the)h(C) f(language)h(usage.)40 b(Also,)26 b(the)e(in)m(teger)i(to)f(real)g (casts)g(v)-5 b(alues)25 b(to)g(double)120 3970 y(precision:)884 4170 y Fc("real)46 b(to)h(integer")189 b(\(int\))46 b(x)239 b(\(INT\))46 b(x)884 4283 y("integer)f(to)i(real")190 b(\(float\))46 b(i)143 b(\(FLOAT\))45 b(i)261 4483 y Ff(Sev)m(eral)32 b(constan)m(ts)f(are)g(built)f(in)g(for)g(use)g(in)g (n)m(umerical)h(expressions:)502 4683 y Fc(#pi)667 b(3.1415...)284 b(#e)620 b(2.7182...)502 4796 y(#deg)f(#pi/180)380 b(#row)524 b(current)46 b(row)h(number)502 4909 y(#null)428 b(undefined)45 b(value)142 b(#snull)428 b(undefined)45 b(string)261 5109 y Ff(A)d(string)g(constan)m(t)h(m)m(ust)f(b)s(e)f(enclosed)i(in)f (quotes)g(as)g(in)g('Crab'.)75 b(The)41 b("n)m(ull")i(constan)m(ts)g (are)120 5222 y(useful)37 b(for)g(conditionally)i(setting)g(table)f(v) -5 b(alues)38 b(to)g(a)g(NULL,)g(or)f(unde\014ned,)h(v)-5 b(alue)38 b(\(F)-8 b(or)38 b(example,)120 5334 y Fc("col1==-99)45 b(?)95 b(#NULL)47 b(:)g(col1")p Ff(\).)261 5447 y(There)33 b(is)h(also)g(a)g(function)g(for)f(testing)i(if)e(t)m(w)m(o)i(v)-5 b(alues)34 b(are)g(close)h(to)f(eac)m(h)h(other,)g(i.e.,)h(if)d(they)h (are)120 5560 y("near")29 b(eac)m(h)g(other)f(to)g(within)g(a)g(user)f (sp)s(eci\014ed)g(tolerance.)42 b(The)27 b(argumen)m(ts,)i Fc(value)p 3184 5560 29 4 v 33 w(1)e Ff(and)h Fc(value)p 3707 5560 V 33 w(2)1905 5809 y Ff(30)p eop end %%Page: 31 31 TeXDict begin 31 30 bop 120 573 a Ff(can)39 b(b)s(e)g(in)m(teger)h(or)f (real)g(and)g(represen)m(t)g(the)g(t)m(w)m(o)h(v)-5 b(alues)39 b(who's)g(pro)m(ximit)m(y)h(is)f(b)s(eing)g(tested)g(to)h(b)s(e)120 686 y(within)30 b(the)g(sp)s(eci\014ed)g(tolerance,)i(also)g(an)e(in)m (teger)i(or)e(real:)1075 880 y Fc(near\(value_1,)44 b(value_2,)h (tolerance\))261 1074 y Ff(When)30 b(a)h(NULL,)f(or)h(unde\014ned,)d(v) -5 b(alue)31 b(is)f(encoun)m(tered)h(in)f(the)g(FITS)g(table,)h(the)g (expression)f(will)120 1186 y(ev)-5 b(aluate)43 b(to)f(NULL)g(unless)e (the)i(unde\014ned)d(v)-5 b(alue)42 b(is)g(not)f(actually)i(required)e (for)g(ev)-5 b(aluation,)46 b(e.g.)120 1299 y("TR)m(UE)c(.or.)76 b(NULL")42 b(ev)-5 b(aluates)44 b(to)f(TR)m(UE.)f(The)f(follo)m(wing)j (t)m(w)m(o)f(functions)f(allo)m(w)h(some)f(NULL)120 1412 y(detection)32 b(and)e(handling:)1027 1606 y Fc(ISNULL\(x\))1027 1719 y(DEFNULL\(x,y\))261 1913 y Ff(The)43 b(former)g(returns)f(a)i(b)s (o)s(olean)f(v)-5 b(alue)44 b(of)f(TR)m(UE)h(if)f(the)h(argumen)m(t)f (x)h(is)f(NULL.)h(The)e(later)120 2026 y("de\014nes")e(a)g(v)-5 b(alue)40 b(to)g(b)s(e)g(substituted)f(for)g(NULL)h(v)-5 b(alues;)45 b(it)40 b(returns)e(the)i(v)-5 b(alue)41 b(of)e(x)h(if)g(x)f(is)h(not)120 2139 y(NULL,)31 b(otherwise)f(it)h (returns)e(the)i(v)-5 b(alue)31 b(of)f(y)-8 b(.)261 2252 y(Bit)32 b(masks)f(can)g(b)s(e)f(used)g(to)h(select)i(out)e(ro)m(ws)g (from)f(bit)h(columns)f(\()p Fc(TFORMn)47 b(=)g(#X)p Ff(\))31 b(in)f(FITS)g(\014les.)120 2365 y(T)-8 b(o)31 b(represen)m(t)f(the)h(mask,)f(binary)-8 b(,)31 b(o)s(ctal,)h(and)d (hex)i(formats)f(are)h(allo)m(w)m(ed:)931 2558 y Fc(binary:)142 b(b0110xx1010000101xxxx00)o(01)931 2671 y(octal:)190 b(o720x1)46 b(->)h(\(b111010000xxx001\))931 2784 y(hex:)286 b(h0FxD)94 b(->)47 b(\(b00001111xxxx1101\))261 2978 y Ff(In)28 b(all)i(the)g(represen)m(tations,)g(an)f(x)g(or)g(X)g(is)g (allo)m(w)m(ed)i(in)e(the)g(mask)g(as)h(a)f(wild)g(card.)40 b(Note)30 b(that)g(the)120 3091 y(x)i(represen)m(ts)f(a)h(di\013eren)m (t)g(n)m(um)m(b)s(er)f(of)h(wild)f(card)h(bits)f(in)g(eac)m(h)i (represen)m(tation.)46 b(All)32 b(represen)m(tations)120 3204 y(are)f(case)g(insensitiv)m(e.)261 3317 y(T)-8 b(o)38 b(construct)f(the)h(b)s(o)s(olean)f(expression)g(using)g(the)g(mask)h (as)f(the)h(b)s(o)s(olean)f(equal)h(op)s(erator)f(de-)120 3430 y(scrib)s(ed)30 b(ab)s(o)m(v)m(e)h(on)g(a)g(bit)g(table)g(column.) 41 b(F)-8 b(or)32 b(example,)f(if)g(y)m(ou)g(had)f(a)h(7)g(bit)f (column)h(named)f(\015ags)h(in)120 3543 y(a)36 b(FITS)e(table)j(and)e (w)m(an)m(ted)h(all)g(ro)m(ws)f(ha)m(ving)h(the)g(bit)f(pattern)h (0010011,)k(the)35 b(selection)j(expression)120 3656 y(w)m(ould)30 b(b)s(e:)1456 3850 y Fc(flags)47 b(==)g(b0010011)311 3962 y(or)1456 4075 y(flags)g(.eq.)f(b10011)261 4269 y Ff(It)32 b(is)f(also)i(p)s(ossible)e(to)h(test)g(if)g(a)g(range)f(of) h(bits)f(is)h(less)g(than,)f(less)h(than)g(equal,)g(greater)h(than)e (and)120 4382 y(greater)h(than)e(equal)h(to)g(a)f(particular)h(b)s(o)s (olean)g(v)-5 b(alue:)1456 4576 y Fc(flags)47 b(<=)g(bxxx010xx)1456 4689 y(flags)g(.gt.)f(bxxx100xx)1456 4802 y(flags)h(.le.)f(b1xxxxxxx) 261 4996 y Ff(Notice)32 b(the)f(use)f(of)h(the)f(x)h(bit)f(v)-5 b(alue)31 b(to)g(limit)g(the)g(range)f(of)h(bits)f(b)s(eing)g (compared.)261 5109 y(It)j(is)g(not)g(necessary)g(to)g(sp)s(ecify)g (the)f(leading)i(\(most)f(signi\014can)m(t\))h(zero)g(\(0\))g(bits)e (in)h(the)g(mask,)g(as)120 5222 y(sho)m(wn)d(in)g(the)g(second)h (expression)f(ab)s(o)m(v)m(e.)261 5334 y(Bit)h(wise)f(AND,)g(OR)g(and)f (NOT)g(op)s(erations)h(are)g(also)h(p)s(ossible)e(on)g(t)m(w)m(o)i(or)f (more)g(bit)g(\014elds)f(using)120 5447 y(the)38 b('&'\(AND\),)h(')p Fa(j)p Ff('\(OR\),)g(and)e(the)h(')10 b(!'\(NOT\))38 b(op)s(erators.)63 b(All)38 b(of)g(these)g(op)s(erators)g(result)f(in)g (a)h(bit)120 5560 y(\014eld)30 b(whic)m(h)g(can)h(then)f(b)s(e)g(used)f (with)h(the)h(equal)g(op)s(erator.)41 b(F)-8 b(or)31 b(example:)1905 5809 y(31)p eop end %%Page: 32 32 TeXDict begin 32 31 bop 1361 573 a Fc(\(!flags\))45 b(==)j(b1101100) 1361 686 y(\(flags)e(&)h(b1000001\))f(==)h(bx000001)261 887 y Ff(Bit)36 b(\014elds)e(can)g(b)s(e)g(app)s(ended)f(as)i(w)m(ell)g (using)f(the)h('+')g(op)s(erator.)53 b(Strings)34 b(can)h(b)s(e)f (concatenated)120 1000 y(this)c(w)m(a)m(y)-8 b(,)32 b(to)s(o.)120 1238 y Fg(5.4.3)105 b(Go)s(o)s(d)36 b(Time)f(In)m(terv)-6 b(al)34 b(Filtering)120 1410 y Ff(A)27 b(common)g(\014ltering)g(metho)s (d)g(in)m(v)m(olv)m(es)i(selecting)g(ro)m(ws)d(whic)m(h)h(ha)m(v)m(e)h (a)g(time)f(v)-5 b(alue)28 b(whic)m(h)e(lies)i(within)120 1523 y(what)38 b(is)f(called)i(a)f(Go)s(o)s(d)g(Time)f(In)m(terv)-5 b(al)39 b(or)e(GTI.)h(The)f(time)i(in)m(terv)-5 b(als)38 b(are)g(de\014ned)f(in)g(a)h(separate)120 1636 y(FITS)31 b(table)i(extension)f(whic)m(h)g(con)m(tains)h(2)f(columns)f(giving)i (the)f(start)g(and)f(stop)h(time)h(of)f(eac)m(h)g(go)s(o)s(d)120 1749 y(in)m(terv)-5 b(al.)61 b(The)37 b(\014ltering)g(op)s(eration)g (accepts)h(only)f(those)g(ro)m(ws)g(of)g(the)g(input)f(table)i(whic)m (h)e(ha)m(v)m(e)i(an)120 1861 y(asso)s(ciated)32 b(time)g(whic)m(h)f (falls)g(within)f(one)i(of)f(the)g(time)g(in)m(terv)-5 b(als)32 b(de\014ned)e(in)h(the)g(GTI)f(extension.)43 b(A)120 1974 y(high)29 b(lev)m(el)j(function,)e (gti\014lter\(a,b,c,d\),)j(is)c(a)m(v)-5 b(ailable)33 b(whic)m(h)c(ev)-5 b(aluates)32 b(eac)m(h)f(ro)m(w)f(of)g(the)g(input)e (table)120 2087 y(and)i(returns)g(TR)m(UE)g(or)h(F)-10 b(ALSE)30 b(dep)s(ending)g(whether)g(the)g(ro)m(w)h(is)g(inside)f(or)h (outside)g(the)g(go)s(o)s(d)g(time)120 2200 y(in)m(terv)-5 b(al.)42 b(The)30 b(syn)m(tax)h(is)406 2401 y Fc(gtifilter\()45 b([)j("gtifile")d([,)i(expr)g([,)g("STARTCOL",)e("STOPCOL")g(])j(])f(]) g(\))120 2603 y Ff(where)35 b(eac)m(h)i("[]")g(demarks)e(optional)h (parameters.)57 b(Note)37 b(that)f(the)g(quotes)g(around)e(the)i (gti\014le)h(and)120 2716 y(ST)-8 b(AR)g(T/STOP)31 b(column)i(are)g (required.)46 b(Either)33 b(single)g(or)f(double)h(quote)g(c)m (haracters)h(ma)m(y)f(b)s(e)f(used.)120 2828 y(The)c(gti\014le,)i(if)e (sp)s(eci\014ed,)h(can)f(b)s(e)g(blank)g(\(""\))i(whic)m(h)e(will)h (mean)g(to)g(use)f(the)g(\014rst)g(extension)h(with)f(the)120 2941 y(name)23 b("*GTI*")i(in)e(the)g(curren)m(t)g(\014le,)i(a)e(plain) g(extension)h(sp)s(eci\014er)f(\(eg,)j("+2",)f("[2]",)i(or)c ("[STDGTI]"\))120 3054 y(whic)m(h)g(will)h(b)s(e)f(used)g(to)i(select)g (an)f(extension)g(in)f(the)h(curren)m(t)g(\014le,)h(or)f(a)g(regular)f (\014lename)h(with)g(or)f(with-)120 3167 y(out)j(an)g(extension)h(sp)s (eci\014er)e(whic)m(h)h(in)f(the)i(latter)g(case)g(will)f(mean)g(to)h (use)f(the)g(\014rst)f(extension)i(with)e(an)120 3280 y(extension)30 b(name)g("*GTI*".)42 b(Expr)28 b(can)i(b)s(e)f(an)m(y)g (arithmetic)i(expression,)f(including)f(simply)g(the)h(time)120 3393 y(column)k(name.)52 b(A)34 b(v)m(ector)i(time)f(expression)f(will) g(pro)s(duce)f(a)i(v)m(ector)g(b)s(o)s(olean)g(result.)51 b(ST)-8 b(AR)g(TCOL)120 3506 y(and)33 b(STOPCOL)f(are)j(the)f(names)g (of)g(the)g(ST)-8 b(AR)g(T/STOP)33 b(columns)h(in)f(the)i(GTI)e (extension.)53 b(If)33 b(one)120 3619 y(of)e(them)f(is)g(sp)s (eci\014ed,)g(they)h(b)s(oth)e(m)m(ust)i(b)s(e.)261 3732 y(In)37 b(its)i(simplest)f(form,)i(no)e(parameters)g(need)g(to)h(b)s(e) e(pro)m(vided)h({)g(default)h(v)-5 b(alues)38 b(will)g(b)s(e)g(used.) 120 3845 y(The)30 b(expression)g Fc("gtifilter\(\)")d Ff(is)j(equiv)-5 b(alen)m(t)32 b(to)454 4046 y Fc(gtifilter\()45 b("",)i(TIME,)f("*START*",)f("*STOP*")h(\))120 4247 y Ff(This)31 b(will)i(searc)m(h)g(the)f(curren)m(t)g(\014le)h(for)f(a)g (GTI)g(extension,)i(\014lter)e(the)g(TIME)g(column)g(in)g(the)h(curren) m(t)120 4360 y(table,)48 b(using)c(ST)-8 b(AR)g(T/STOP)43 b(times)h(tak)m(en)h(from)e(columns)h(in)g(the)g(GTI)f(extension)i (with)e(names)120 4473 y(con)m(taining)32 b(the)f(strings)f("ST)-8 b(AR)g(T")31 b(and)f("STOP".)41 b(The)30 b(wildcards)g(\('*'\))i(allo)m (w)g(sligh)m(t)f(v)-5 b(ariations)32 b(in)120 4586 y(naming)g(con)m(v)m (en)m(tions)h(suc)m(h)f(as)g("TST)-8 b(AR)g(T")32 b(or)g("ST)-8 b(AR)g(TTIME".)45 b(The)31 b(same)i(default)f(v)-5 b(alues)32 b(apply)120 4699 y(for)f(unsp)s(eci\014ed)f(parameters)i(when)e(the)i (\014rst)e(one)i(or)f(t)m(w)m(o)i(parameters)f(are)g(sp)s(eci\014ed.)43 b(The)31 b(function)120 4812 y(automatically)44 b(searc)m(hes)d(for)g (TIMEZER)m(O/I/F)g(k)m(eyw)m(ords)g(in)f(the)h(curren)m(t)g(and)f(GTI)h (extensions,)120 4924 y(applying)30 b(a)h(relativ)m(e)h(time)g (o\013set,)f(if)g(necessary)-8 b(.)120 5163 y Fg(5.4.4)105 b(Spatial)35 b(Region)h(Filtering)120 5334 y Ff(Another)f(common)h (\014ltering)g(metho)s(d)f(selects)h(ro)m(ws)g(based)f(on)g(whether)g (the)h(spatial)g(p)s(osition)f(asso-)120 5447 y(ciated)41 b(with)f(eac)m(h)i(ro)m(w)e(is)g(lo)s(cated)h(within)f(a)g(giv)m(en)i (2-dimensional)f(region.)70 b(The)40 b(syn)m(tax)h(for)e(this)120 5560 y(high-lev)m(el)32 b(\014lter)f(is)1905 5809 y(32)p eop end %%Page: 33 33 TeXDict begin 33 32 bop 454 573 a Fc(regfilter\()45 b("regfilename")f ([)k(,)f(Xexpr,)f(Yexpr)h([)g(,)h("wcs)e(cols")h(])g(])g(\))120 757 y Ff(where)28 b(eac)m(h)i("[)g(]")f(demarks)g(optional)h (parameters.)40 b(The)29 b(region)g(\014le)g(name)g(is)g(required)f (and)g(m)m(ust)h(b)s(e)120 870 y(enclosed)h(in)f(quotes.)41 b(The)29 b(remaining)g(parameters)h(are)f(optional.)42 b(The)29 b(region)h(\014le)f(is)g(an)h(ASCI)s(I)d(text)120 983 y(\014le)37 b(whic)m(h)f(con)m(tains)i(a)f(list)h(of)e(one)h(or)g (more)g(geometric)i(shap)s(es)c(\(circle,)41 b(ellipse,)e(b)s(o)m(x,)f (etc.\))62 b(whic)m(h)120 1096 y(de\014nes)30 b(a)i(region)g(on)f(the)h (celestial)i(sphere)d(or)g(an)g(area)h(within)f(a)h(particular)g(2D)g (image.)45 b(The)31 b(region)120 1209 y(\014le)38 b(is)g(t)m(ypically)i (generated)f(using)f(an)g(image)h(displa)m(y)g(program)f(suc)m(h)f(as)i (fv/PO)m(W)f(\(distribute)g(b)m(y)120 1322 y(the)32 b(HEASAR)m(C\),)g (or)g(ds9)g(\(distributed)f(b)m(y)g(the)h(Smithsonian)g(Astroph)m (ysical)g(Observ)-5 b(atory\).)46 b(Users)120 1435 y(should)41 b(refer)h(to)h(the)f(do)s(cumen)m(tation)h(pro)m(vided)f(with)g(these)g (programs)g(for)g(more)g(details)h(on)f(the)120 1548 y(syn)m(tax)31 b(used)e(in)i(the)f(region)h(\014les.)261 1661 y(In)k(its)h(simpliest)g(form,)h(\(e.g.,)i Fc (regfilter\("region.reg"\))30 b Ff(\))36 b(the)f(co)s(ordinates)i(in)e (the)h(default)120 1774 y('X')24 b(and)e('Y')i(columns)e(will)i(b)s(e)e (used)g(to)i(determine)f(if)g(eac)m(h)h(ro)m(w)f(is)g(inside)g(or)g (outside)g(the)g(area)h(sp)s(eci\014ed)120 1886 y(in)h(the)h(region)g (\014le.)39 b(Alternate)27 b(p)s(osition)e(column)g(names,)i(or)e (expressions,)h(ma)m(y)g(b)s(e)f(en)m(tered)h(if)f(needed,)120 1999 y(as)31 b(in)502 2184 y Fc(regfilter\("region.reg",)41 b(XPOS,)47 b(YPOS\))120 2368 y Ff(Region)39 b(\014ltering)g(can)f(b)s (e)g(applied)g(most)g(unam)m(biguously)g(if)g(the)g(p)s(ositions)h(in)e (the)i(region)g(\014le)f(and)120 2481 y(in)e(the)h(table)h(to)g(b)s(e)e (\014ltered)h(are)g(b)s(oth)f(giv)m(e)i(in)f(terms)f(of)h(absolute)h (celestial)h(co)s(ordinate)f(units.)59 b(In)120 2594 y(this)38 b(case)h(the)g(lo)s(cations)h(and)d(sizes)i(of)g(the)f (geometric)i(shap)s(es)e(in)g(the)g(region)h(\014le)f(are)h(sp)s (eci\014ed)f(in)120 2707 y(angular)d(units)f(on)g(the)h(sky)f(\(e.g.,)j (p)s(ositions)e(giv)m(en)h(in)e(R.A.)h(and)f(Dec.)54 b(and)34 b(sizes)h(in)f(arcseconds)h(or)120 2820 y(arcmin)m(utes\).)k (Similarly)-8 b(,)24 b(eac)m(h)f(ro)m(w)g(of)f(the)g(\014ltered)g (table)h(will)f(ha)m(v)m(e)h(a)g(celestial)h(co)s(ordinate)f(asso)s (ciated)120 2933 y(with)33 b(it.)51 b(This)33 b(asso)s(ciation)i(is)f (usually)f(implemen)m(ted)h(using)g(a)f(set)i(of)e(so-called)j('W)-8 b(orld)34 b(Co)s(ordinate)120 3046 y(System')i(\(or)h(W)m(CS\))f(FITS)f (k)m(eyw)m(ords)i(that)f(de\014ne)g(the)g(co)s(ordinate)h (transformation)f(that)h(m)m(ust)f(b)s(e)120 3159 y(applied)30 b(to)h(the)g(v)-5 b(alues)31 b(in)f(the)g('X')h(and)f('Y')h(columns)f (to)h(calculate)i(the)d(co)s(ordinate.)261 3272 y(Alternativ)m(ely)-8 b(,)40 b(one)c(can)f(p)s(erform)f(spatial)j(\014ltering)e(using)g (unitless)h('pixel')g(co)s(ordinates)g(for)f(the)120 3385 y(regions)c(and)f(ro)m(w)h(p)s(ositions.)42 b(In)30 b(this)g(case)i(the)f(user)f(m)m(ust)h(b)s(e)f(careful)h(to)g(ensure)f (that)h(the)g(p)s(ositions)120 3498 y(in)i(the)g(2)h(\014les)f(are)h (self-consisten)m(t.)51 b(A)34 b(t)m(ypical)g(problem)f(is)g(that)h (the)g(region)g(\014le)f(ma)m(y)h(b)s(e)e(generated)120 3610 y(using)23 b(a)h(binned)f(image,)j(but)d(the)h(un)m(binned)e(co)s (ordinates)i(are)h(giv)m(en)f(in)g(the)g(ev)m(en)m(t)h(table.)39 b(The)24 b(R)m(OSA)-8 b(T)120 3723 y(ev)m(en)m(ts)34 b(\014les,)g(for)f(example,)i(ha)m(v)m(e)f(X)f(and)g(Y)g(pixel)g(co)s (ordinates)h(that)g(range)f(from)g(1)g(-)h(15360.)51 b(These)120 3836 y(co)s(ordinates)33 b(are)g(t)m(ypically)i(binned)c(b) m(y)i(a)g(factor)g(of)g(32)h(to)f(pro)s(duce)f(a)h(480x480)i(pixel)e (image.)49 b(If)32 b(one)120 3949 y(then)f(uses)g(a)g(region)h(\014le)f (generated)i(from)d(this)h(image)i(\(in)e(image)h(pixel)g(units\))f(to) h(\014lter)f(the)h(R)m(OSA)-8 b(T)120 4062 y(ev)m(en)m(ts)33 b(\014le,)f(then)f(the)g(X)g(and)g(Y)h(column)f(v)-5 b(alues)31 b(m)m(ust)h(b)s(e)e(con)m(v)m(erted)j(to)f(corresp)s(onding) e(pixel)i(units)120 4175 y(as)f(in:)502 4360 y Fc (regfilter\("rosat.reg",)42 b(X/32.+.5,)j(Y/32.+.5\))120 4544 y Ff(Note)30 b(that)f(this)f(binning)g(con)m(v)m(ersion)h(is)g (not)g(necessary)g(if)f(the)h(region)g(\014le)f(is)h(sp)s(eci\014ed)f (using)g(celestial)120 4657 y(co)s(ordinate)g(units)f(instead)g(of)g (pixel)h(units)e(b)s(ecause)h(CFITSIO)f(is)h(then)g(able)h(to)g (directly)f(compare)h(the)120 4770 y(celestial)37 b(co)s(ordinate)e(of) f(eac)m(h)h(ro)m(w)f(in)g(the)g(table)h(with)f(the)g(celestial)j(co)s (ordinates)e(in)e(the)i(region)f(\014le)120 4883 y(without)c(ha)m(ving) h(to)g(kno)m(w)g(an)m(ything)g(ab)s(out)f(ho)m(w)g(the)h(image)g(ma)m (y)g(ha)m(v)m(e)h(b)s(een)d(binned.)261 4996 y(The)k(last)h("w)m(cs)f (cols")i(parameter)e(should)f(rarely)h(b)s(e)g(needed.)48 b(If)33 b(supplied,)f(this)h(string)g(con)m(tains)120 5109 y(the)39 b(names)g(of)h(the)f(2)g(columns)g(\(space)h(or)f(comma)h (separated\))g(whic)m(h)f(ha)m(v)m(e)h(the)g(asso)s(ciated)g(W)m(CS)120 5222 y(k)m(eyw)m(ords.)j(If)30 b(not)h(supplied,)f(the)h(\014lter)g (will)g(scan)g(the)g(X)g(and)g(Y)g(expressions)f(for)h(column)g(names.) 42 b(If)120 5334 y(only)33 b(one)f(is)h(found)e(in)h(eac)m(h)i (expression,)f(those)g(columns)f(will)h(b)s(e)f(used,)h(otherwise)g(an) f(error)g(will)h(b)s(e)120 5447 y(returned.)261 5560 y(These)d(region)h(shap)s(es)f(are)g(supp)s(orted)f(\(names)i(are)f (case)i(insensitiv)m(e\):)1905 5809 y(33)p eop end %%Page: 34 34 TeXDict begin 34 33 bop 454 573 a Fc(Point)428 b(\()48 b(X1,)f(Y1)g(\))715 b(<-)48 b(One)f(pixel)f(square)g(region)454 686 y(Line)476 b(\()48 b(X1,)f(Y1,)g(X2,)f(Y2)i(\))333 b(<-)48 b(One)f(pixel)f(wide)h(region)454 799 y(Polygon)332 b(\()48 b(X1,)f(Y1,)g(X2,)f(Y2,)h(...)g(\))95 b(<-)48 b(Rest)e(are)h(interiors)e(with)454 912 y(Rectangle)236 b(\()48 b(X1,)f(Y1,)g(X2,)f(Y2,)h(A)h(\))334 b(|)47 b(boundaries)e (considered)454 1024 y(Box)524 b(\()48 b(Xc,)f(Yc,)g(Wdth,)f(Hght,)g(A) i(\))143 b(V)47 b(within)f(the)h(region)454 1137 y(Diamond)332 b(\()48 b(Xc,)f(Yc,)g(Wdth,)f(Hght,)g(A)i(\))454 1250 y(Circle)380 b(\()48 b(Xc,)f(Yc,)g(R)g(\))454 1363 y(Annulus)332 b(\()48 b(Xc,)f(Yc,)g(Rin,)f(Rout)h(\))454 1476 y(Ellipse)332 b(\()48 b(Xc,)f(Yc,)g(Rx,)f(Ry,)h(A)h(\))454 1589 y(Elliptannulus)c(\() k(Xc,)f(Yc,)g(Rinx,)f(Riny,)g(Routx,)g(Routy,)g(Ain,)h(Aout)g(\))454 1702 y(Sector)380 b(\()48 b(Xc,)f(Yc,)g(Amin,)f(Amax)h(\))120 1914 y Ff(where)33 b(\(Xc,Yc\))j(is)e(the)h(co)s(ordinate)f(of)h(the)f (shap)s(e's)f(cen)m(ter;)k(\(X#,Y#\))e(are)f(the)g(co)s(ordinates)h(of) f(the)120 2027 y(shap)s(e's)22 b(edges;)k(Rxxx)d(are)g(the)h(shap)s (es')e(v)-5 b(arious)23 b(Radii)g(or)g(semima)5 b(jor/minor)23 b(axes;)k(and)22 b(Axxx)h(are)g(the)120 2140 y(angles)j(of)f(rotation)h (\(or)f(b)s(ounding)e(angles)j(for)f(Sector\))h(in)e(degrees.)40 b(F)-8 b(or)26 b(rotated)g(shap)s(es,)f(the)g(rotation)120 2253 y(angle)37 b(can)g(b)s(e)e(left)i(o\013,)h(indicating)f(no)f (rotation.)60 b(Common)35 b(alternate)j(names)e(for)g(the)g(regions)h (can)120 2366 y(also)28 b(b)s(e)e(used:)39 b(rotb)s(o)m(x)27 b(=)f(b)s(o)m(x;)j(rotrectangle)g(=)e(rectangle;)j(\(rot\)rhom)m(bus)c (=)h(\(rot\)diamond;)i(and)d(pie)120 2479 y(=)h(sector.)41 b(When)28 b(a)g(shap)s(e's)f(name)g(is)h(preceded)f(b)m(y)h(a)g(min)m (us)f(sign,)i('-',)g(the)f(de\014ned)e(region)i(is)g(instead)120 2592 y(the)36 b(area)g(*outside*)h(its)f(b)s(oundary)d(\(ie,)38 b(the)e(region)g(is)g(in)m(v)m(erted\).)57 b(All)36 b(the)g(shap)s(es)f (within)g(a)h(single)120 2705 y(region)f(\014le)g(are)g(OR'd)g (together)h(to)f(create)i(the)e(region,)h(and)f(the)g(order)f(is)h (signi\014can)m(t.)55 b(The)34 b(o)m(v)m(erall)120 2818 y(w)m(a)m(y)g(of)g(lo)s(oking)g(at)g(region)g(\014les)f(is)g(that)h(if) f(the)h(\014rst)e(region)i(is)g(an)f(excluded)g(region)h(then)f(a)g (dumm)m(y)120 2931 y(included)c(region)i(of)f(the)g(whole)g(detector)i (is)e(inserted)f(in)h(the)g(fron)m(t.)41 b(Then)29 b(eac)m(h)i(region)g (sp)s(eci\014cation)120 3044 y(as)g(it)h(is)f(pro)s(cessed)g(o)m(v)m (errides)h(an)m(y)f(selections)i(inside)e(of)g(that)h(region)g(sp)s (eci\014ed)e(b)m(y)h(previous)g(regions.)120 3156 y(Another)e(w)m(a)m (y)i(of)e(thinking)g(ab)s(out)g(this)g(is)h(that)f(if)h(a)f(previous)g (excluded)g(region)h(is)g(completely)h(inside)120 3269 y(of)g(a)f(subsequen)m(t)g(included)g(region)h(the)f(excluded)g(region) h(is)g(ignored.)261 3382 y(The)20 b(p)s(ositional)h(co)s(ordinates)g (ma)m(y)g(b)s(e)e(giv)m(en)j(either)e(in)g(pixel)h(units,)h(decimal)f (degrees)g(or)f(hh:mm:ss.s,)120 3495 y(dd:mm:ss.s)25 b(units.)38 b(The)26 b(shap)s(e)f(sizes)h(ma)m(y)h(b)s(e)e(giv)m(en)i (in)e(pixels,)j(degrees,)f(arcmin)m(utes,)h(or)e(arcseconds.)120 3608 y(Lo)s(ok)k(at)i(examples)e(of)h(region)g(\014le)f(pro)s(duced)f (b)m(y)h(fv/PO)m(W)h(or)f(ds9)g(for)g(further)f(details)j(of)e(the)h (region)120 3721 y(\014le)f(format.)120 3961 y Fg(5.4.5)105 b(Example)35 b(Ro)m(w)g(Filters)311 4133 y Fc([double)46 b(&&)h(mag)g(<=)g(5.0])381 b(-)95 b(Extract)46 b(all)h(double)f(stars)g (brighter)1886 4246 y(than)94 b(fifth)47 b(magnitude)311 4472 y([#row)f(>=)h(125)g(&&)h(#row)e(<=)h(175])142 b(-)48 b(Extract)e(row)h(numbers)e(125)i(through)f(175)311 4697 y([abs\(sin\(theta)e(*)j(#deg\)\))f(<)i(0.5])e(-)i(Extract)e(all)h (rows)f(having)g(the)1886 4810 y(absolute)f(value)i(of)g(the)g(sine)g (of)g(theta)1886 4923 y(less)94 b(than)47 b(a)g(half)g(where)f(the)h (angles)1886 5036 y(are)g(tabulated)e(in)i(degrees)311 5262 y([@rowFilter.txt])711 b(-)48 b(Extract)e(rows)g(using)h(the)g (expression)1886 5375 y(contained)e(within)h(the)h(text)g(file)1886 5488 y(rowFilter.txt)1905 5809 y Ff(34)p eop end %%Page: 35 35 TeXDict begin 35 34 bop 311 686 a Fc([gtifilter\(\)])855 b(-)48 b(Search)e(the)h(current)f(file)g(for)h(a)h(GTI)359 799 y(extension,)92 b(filter)i(the)47 b(TIME)359 912 y(column)f(in)h(the)g(current)f(table,)g(using)359 1024 y(START/STOP)f(times)h(taken)g(from)359 1137 y(columns)f(in)j(the)f (GTI)94 b(extension)311 1363 y([regfilter\("pow.reg"\)])423 b(-)48 b(Extract)e(rows)g(which)h(have)f(a)i(coordinate)1886 1476 y(\(as)f(given)f(in)h(the)g(X)h(and)f(Y)g(columns\))1886 1589 y(within)f(the)h(spatial)f(region)g(specified)1886 1702 y(in)h(the)g(pow.reg)f(region)g(file.)1905 5809 y Ff(35)p eop end %%Page: 36 36 TeXDict begin 36 35 bop 120 573 a Fb(5.5)112 b(Com)m(bined)39 b(Filtering)f(Examples)120 744 y Ff(The)29 b(previous)h(sections)g (describ)s(ed)f(all)i(the)f(individual)f(t)m(yp)s(es)h(of)g(\014lters)f (that)i(ma)m(y)f(b)s(e)f(applied)h(to)g(the)120 857 y(input)j(\014le.) 50 b(In)33 b(this)g(section)i(w)m(e)f(sho)m(w)g(examples)g(whic)m(h)f (com)m(bine)i(sev)m(eral)f(di\013eren)m(t)h(\014lters)e(at)h(once.)120 970 y(These)h(examples)g(all)h(use)f(the)g Fc(fitscopy)e Ff(program)i(that)g(is)g(distributed)f(with)h(the)g(CFITSIO)f(co)s(de.) 120 1083 y(It)c(simply)g(copies)i(the)e(input)g(\014le)g(to)h(the)g (output)f(\014le.)120 1268 y Fc(fitscopy)46 b(rosat.fit)f(out.fit)261 1453 y Ff(This)26 b(trivial)i(example)f(simply)g(mak)m(es)g(an)g(iden)m (tical)i(cop)m(y)e(of)g(the)g(input)f(rosat.\014t)h(\014le)g(without)g (an)m(y)120 1566 y(\014ltering.)120 1751 y Fc(fitscopy)46 b('rosat.fit[events][col)41 b(Time;X;Y][#row)j(<)k(1000]')e(out.fit)261 1936 y Ff(The)34 b(output)g(\014le)h(con)m(tains)h(only)e(the)h(Time,)h (X,)f(and)e(Y)i(columns,)h(and)d(only)i(the)g(\014rst)f(999)h(ro)m(ws) 120 2049 y(from)g(the)g('EVENTS')f(table)i(extension)g(of)f(the)g (input)f(\014le.)55 b(All)35 b(the)h(other)f(HDUs)g(in)g(the)g(input)f (\014le)120 2162 y(are)d(copied)g(to)g(the)f(output)g(\014le)h(without) f(an)m(y)h(mo)s(di\014cation.)120 2346 y Fc(fitscopy)46 b('rosat.fit[events][PI)c(<)47 b(50][bin)f(\(Xdet,Ydet\))f(=)i(16]')g (image.fit)261 2531 y Ff(This)30 b(creates)h(an)f(output)g(image)i(b)m (y)e(binning)f(the)h(Xdet)h(and)f(Ydet)g(columns)g(of)g(the)h(ev)m(en)m (ts)g(table)120 2644 y(with)26 b(a)h(pixel)g(binning)e(factor)i(of)g (16.)40 b(Only)26 b(the)h(ro)m(ws)f(whic)m(h)g(ha)m(v)m(e)i(a)e(PI)h (energy)f(less)h(than)f(50)h(are)g(used)120 2757 y(to)33 b(construct)f(this)f(image.)46 b(The)32 b(output)f(image)i(\014le)f (con)m(tains)h(a)f(primary)f(arra)m(y)h(image)h(without)f(an)m(y)120 2870 y(extensions.)120 3055 y Fc(fitscopy)46 b('rosat.fit[events][gtif) o(ilt)o(er\(\))41 b(&&)47 b(regfilter\("pow.reg"\)]')42 b(out.fit)261 3240 y Ff(The)29 b(\014ltering)h(expression)f(in)g(this)h (example)g(uses)f(the)h Fc(gtifilter)d Ff(function)i(to)h(test)g (whether)f(the)120 3353 y(TIME)e(column)g(v)-5 b(alue)27 b(in)g(eac)m(h)i(ro)m(w)e(is)g(within)g(one)g(of)g(the)h(Go)s(o)s(d)f (Time)g(In)m(terv)-5 b(als)27 b(de\014ned)f(in)h(the)h(GTI)120 3466 y(extension)i(in)f(the)h(same)g(input)e(\014le,)i(and)f(also)i (uses)e(the)g Fc(regfilter)e Ff(function)j(to)g(test)g(if)g(the)f(p)s (osition)120 3579 y(asso)s(ciated)j(with)d(eac)m(h)i(ro)m(w)g(\(deriv)m (ed)f(b)m(y)g(default)g(from)g(the)g(v)-5 b(alues)30 b(in)g(the)g(X)h(and)e(Y)h(columns)g(of)g(the)120 3692 y(ev)m(en)m(ts)38 b(table\))f(is)g(lo)s(cated)h(within)d(the)i(area)g (de\014ned)e(in)i(the)f Fc(pow.reg)f Ff(text)i(region)g(\014le)f (\(whic)m(h)h(w)m(as)120 3804 y(previously)h(created)i(with)f(the)f Fc(fv/POW)f Ff(image)j(displa)m(y)f(program\).)66 b(Only)38 b(the)h(ro)m(ws)f(whic)m(h)h(satisfy)120 3917 y(b)s(oth)30 b(tests)h(are)g(copied)f(to)h(the)g(output)f(table.)120 4102 y Fc(fitscopy)46 b('r.fit[evt][PI<50]')c(stdout)k(|)i(fitscopy)d (stdin[evt][col)f(X,Y])j(out.fit)261 4287 y Ff(In)25 b(this)g(somewhat)h(con)m(v)m(oluted)g(example,)i(\014tscop)m(y)d(is)h (used)e(to)i(\014rst)f(select)i(the)e(ro)m(ws)g(from)g(the)h(evt)120 4400 y(extension)k(whic)m(h)g(ha)m(v)m(e)h(PI)e(less)h(than)g(50)g(and) f(write)h(the)g(resulting)g(table)h(out)f(to)g(the)g(stdout)g(stream.) 120 4513 y(This)37 b(is)g(pip)s(ed)f(to)i(a)g(2nd)f(instance)h(of)g (\014tscop)m(y)g(\(with)f(the)h(Unix)f(`)p Fa(j)p Ff(')h(pip)s(e)f (command\))g(whic)m(h)h(reads)120 4626 y(that)31 b(\014ltered)g(FITS)e (\014le)i(from)f(the)h(stdin)f(stream)h(and)f(copies)h(only)g(the)g(X)f (and)g(Y)h(columns)f(from)g(the)120 4739 y(evt)h(table)g(to)g(the)g (output)f(\014le.)120 4924 y Fc(fitscopy)46 b('r.fit[evt][col)d (RAD=sqrt\(\(X-#XCEN\)**2+\(Y-)o(#YCE)o(N\)*)o(*2\)])o([rad)o(<10)o (0]')e(out.fit)261 5109 y Ff(This)24 b(example)i(\014rst)e(creates)i(a) f(new)f(column)h(called)h(RAD)f(whic)m(h)f(giv)m(es)i(the)f(distance)h (b)s(et)m(w)m(een)f(the)120 5222 y(X,Y)k(co)s(ordinate)g(of)f(eac)m(h)i (ev)m(en)m(t)g(and)d(the)i(co)s(ordinate)g(de\014ned)e(b)m(y)h(the)h(X) m(CEN)f(and)g(YCEN)g(k)m(eyw)m(ords)120 5334 y(in)k(the)h(header.)47 b(Then,)32 b(only)h(those)g(ro)m(ws)g(whic)m(h)f(ha)m(v)m(e)i(a)f (distance)g(less)g(than)f(100)i(are)f(copied)g(to)g(the)120 5447 y(output)e(table.)46 b(In)31 b(other)h(w)m(ords,)f(only)h(the)g (ev)m(en)m(ts)h(whic)m(h)f(are)g(lo)s(cated)h(within)e(100)i(pixel)f (units)f(from)120 5560 y(the)g(\(X)m(CEN,)g(YCEN\))f(co)s(ordinate)i (are)e(copied)h(to)g(the)g(output)f(table.)1905 5809 y(36)p eop end %%Page: 37 37 TeXDict begin 37 36 bop 120 573 a Fc(fitscopy)46 b ('ftp://heasarc.gsfc.nas)o(a.g)o(ov/r)o(osat)o(.fi)o(t[ev)o(ents)o(][b) o(in)c(\(X,Y\)=16]')j(img.fit)261 785 y Ff(This)23 b(example)h(bins)e (the)h(X)h(and)f(Y)g(columns)g(of)g(the)h(h)m(yp)s(othetical)g(R)m(OSA) -8 b(T)24 b(\014le)f(at)h(the)f(HEASAR)m(C)120 898 y(ftp)30 b(site)h(to)g(create)h(the)f(output)f(image.)120 1111 y Fc(fitscopy)46 b('raw.fit[i512,512][101:)o(110)o(,51:)o(60]')41 b(image.fit)261 1323 y Ff(This)29 b(example)h(con)m(v)m(erts)h(the)e (512)i(x)e(512)i(pixel)f(ra)m(w)f(binary)g(16-bit)h(in)m(teger)h(image) g(to)f(a)g(FITS)e(\014le)120 1436 y(and)i(copies)h(a)g(10)g(x)f(10)h (pixel)g(subimage)g(from)f(it)g(to)i(the)e(output)g(FITS)g(image.)1905 5809 y(37)p eop end %%Page: 38 38 TeXDict begin 38 37 bop 120 573 a Fh(6)135 b(CFITSIO)44 b(Error)h(Status)g(Co)t(des)120 776 y Ff(The)34 b(follo)m(wing)h(table) g(lists)g(all)g(the)f(error)g(status)g(co)s(des)h(used)e(b)m(y)h (CFITSIO.)f(Programmers)h(are)g(en-)120 889 y(couraged)f(to)g(use)g (the)f(sym)m(b)s(olic)h(mnemonics)g(\(de\014ned)e(in)h(the)h(\014le)g (\014tsio.h\))g(rather)f(than)g(the)h(actual)120 1002 y(in)m(teger)f(status)e(v)-5 b(alues)31 b(to)g(impro)m(v)m(e)g(the)g (readabilit)m(y)h(of)e(their)h(co)s(de.)168 1214 y Fc(Symbolic)45 b(Const)190 b(Value)237 b(Meaning)168 1327 y(--------------)187 b(-----)94 b(------------------------)o(----)o(---)o(----)o(----)o(--) 1122 1440 y(0)191 b(OK,)47 b(no)g(error)168 1553 y(SAME_FILE)427 b(101)190 b(input)46 b(and)h(output)f(files)h(are)g(the)f(same)168 1666 y(TOO_MANY_FILES)187 b(103)j(tried)46 b(to)h(open)g(too)g(many)g (FITS)f(files)h(at)g(once)168 1779 y(FILE_NOT_OPENED)139 b(104)190 b(could)46 b(not)h(open)g(the)g(named)f(file)168 1892 y(FILE_NOT_CREATED)91 b(105)190 b(could)46 b(not)h(create)f(the)h (named)g(file)168 2005 y(WRITE_ERROR)331 b(106)190 b(error)46 b(writing)g(to)h(FITS)g(file)168 2117 y(END_OF_FILE)331 b(107)190 b(tried)46 b(to)h(move)g(past)g(end)g(of)g(file)168 2230 y(READ_ERROR)379 b(108)190 b(error)46 b(reading)g(from)h(FITS)f (file)168 2343 y(FILE_NOT_CLOSED)139 b(110)190 b(could)46 b(not)h(close)g(the)f(file)168 2456 y(ARRAY_TOO_BIG)235 b(111)190 b(array)46 b(dimensions)f(exceed)h(internal)g(limit)168 2569 y(READONLY_FILE)235 b(112)190 b(Cannot)46 b(write)g(to)i(readonly) d(file)168 2682 y(MEMORY_ALLOCATION)e(113)190 b(Could)46 b(not)h(allocate)f(memory)168 2795 y(BAD_FILEPTR)331 b(114)190 b(invalid)46 b(fitsfile)f(pointer)168 2908 y(NULL_INPUT_PTR)187 b(115)j(NULL)47 b(input)f(pointer)g(to)h(routine) 168 3021 y(SEEK_ERROR)379 b(116)190 b(error)46 b(seeking)g(position)g (in)h(file)168 3247 y(BAD_URL_PREFIX)235 b(121)142 b(invalid)46 b(URL)h(prefix)f(on)h(file)g(name)168 3359 y(TOO_MANY_DRIVERS)139 b(122)j(tried)46 b(to)h(register)f(too)h(many)g(IO)g(drivers)168 3472 y(DRIVER_INIT_FAILED)c(123)142 b(driver)46 b(initialization)e (failed)168 3585 y(NO_MATCHING_DRIVER)f(124)142 b(matching)45 b(driver)i(is)g(not)g(registered)168 3698 y(URL_PARSE_ERROR)187 b(125)142 b(failed)46 b(to)h(parse)g(input)f(file)h(URL)168 3924 y(SHARED_BADARG)235 b(151)190 b(bad)47 b(argument)e(in)j(shared)e (memory)g(driver)168 4037 y(SHARED_NULPTR)235 b(152)190 b(null)47 b(pointer)e(passed)h(as)i(an)f(argument)168 4150 y(SHARED_TABFULL)187 b(153)j(no)47 b(more)g(free)f(shared)g (memory)h(handles)168 4263 y(SHARED_NOTINIT)187 b(154)j(shared)46 b(memory)g(driver)g(is)h(not)g(initialized)168 4376 y(SHARED_IPCERR)235 b(155)190 b(IPC)47 b(error)f(returned)g(by)h(a)g(system)f(call)168 4489 y(SHARED_NOMEM)283 b(156)190 b(no)47 b(memory)f(in)h(shared)f (memory)h(driver)168 4601 y(SHARED_AGAIN)283 b(157)190 b(resource)45 b(deadlock)h(would)g(occur)168 4714 y(SHARED_NOFILE)235 b(158)190 b(attempt)46 b(to)h(open/create)e(lock)h(file)h(failed)168 4827 y(SHARED_NORESIZE)139 b(159)190 b(shared)46 b(memory)g(block)g (cannot)h(be)g(resized)f(at)h(the)g(moment)168 5053 y(HEADER_NOT_EMPTY) 91 b(201)190 b(header)46 b(already)g(contains)f(keywords)168 5166 y(KEY_NO_EXIST)283 b(202)190 b(keyword)46 b(not)h(found)f(in)h (header)168 5279 y(KEY_OUT_BOUNDS)187 b(203)j(keyword)46 b(record)g(number)g(is)h(out)g(of)g(bounds)168 5392 y(VALUE_UNDEFINED) 139 b(204)190 b(keyword)46 b(value)g(field)g(is)i(blank)168 5505 y(NO_QUOTE)475 b(205)190 b(string)46 b(is)h(missing)f(the)h (closing)f(quote)1905 5809 y Ff(38)p eop end %%Page: 39 39 TeXDict begin 39 38 bop 168 573 a Fc(BAD_KEYCHAR)331 b(207)190 b(illegal)46 b(character)f(in)i(keyword)f(name)h(or)g(card) 168 686 y(BAD_ORDER)427 b(208)190 b(required)45 b(keywords)h(out)h(of)g (order)168 799 y(NOT_POS_INT)331 b(209)190 b(keyword)46 b(value)g(is)h(not)g(a)h(positive)d(integer)168 912 y(NO_END)571 b(210)190 b(couldn't)45 b(find)i(END)g(keyword)168 1024 y(BAD_BITPIX)379 b(211)190 b(illegal)46 b(BITPIX)g(keyword)g(value)168 1137 y(BAD_NAXIS)427 b(212)190 b(illegal)46 b(NAXIS)g(keyword)g(value) 168 1250 y(BAD_NAXES)427 b(213)190 b(illegal)46 b(NAXISn)g(keyword)g (value)168 1363 y(BAD_PCOUNT)379 b(214)190 b(illegal)46 b(PCOUNT)g(keyword)g(value)168 1476 y(BAD_GCOUNT)379 b(215)190 b(illegal)46 b(GCOUNT)g(keyword)g(value)168 1589 y(BAD_TFIELDS)331 b(216)190 b(illegal)46 b(TFIELDS)g(keyword)f (value)168 1702 y(NEG_WIDTH)427 b(217)190 b(negative)45 b(table)i(row)g(size)168 1815 y(NEG_ROWS)475 b(218)190 b(negative)45 b(number)i(of)g(rows)f(in)i(table)168 1928 y(COL_NOT_FOUND)235 b(219)190 b(column)46 b(with)h(this)f(name)h(not)g (found)f(in)h(table)168 2041 y(BAD_SIMPLE)379 b(220)190 b(illegal)46 b(value)g(of)h(SIMPLE)f(keyword)168 2154 y(NO_SIMPLE)427 b(221)190 b(Primary)46 b(array)g(doesn't)g(start)g (with)h(SIMPLE)168 2267 y(NO_BITPIX)427 b(222)190 b(Second)46 b(keyword)g(not)h(BITPIX)168 2379 y(NO_NAXIS)475 b(223)190 b(Third)46 b(keyword)g(not)h(NAXIS)168 2492 y(NO_NAXES)475 b(224)190 b(Couldn't)45 b(find)i(all)g(the)g(NAXISn)f(keywords)168 2605 y(NO_XTENSION)331 b(225)190 b(HDU)47 b(doesn't)f(start)g(with)h (XTENSION)e(keyword)168 2718 y(NOT_ATABLE)379 b(226)190 b(the)47 b(CHDU)f(is)i(not)f(an)g(ASCII)f(table)g(extension)168 2831 y(NOT_BTABLE)379 b(227)190 b(the)47 b(CHDU)f(is)i(not)f(a)g (binary)f(table)g(extension)168 2944 y(NO_PCOUNT)427 b(228)190 b(couldn't)45 b(find)i(PCOUNT)f(keyword)168 3057 y(NO_GCOUNT)427 b(229)190 b(couldn't)45 b(find)i(GCOUNT)f(keyword) 168 3170 y(NO_TFIELDS)379 b(230)190 b(couldn't)45 b(find)i(TFIELDS)f (keyword)168 3283 y(NO_TBCOL)475 b(231)190 b(couldn't)45 b(find)i(TBCOLn)f(keyword)168 3396 y(NO_TFORM)475 b(232)190 b(couldn't)45 b(find)i(TFORMn)f(keyword)168 3509 y(NOT_IMAGE)427 b(233)190 b(the)47 b(CHDU)f(is)i(not)f(an)g(IMAGE)f(extension)168 3621 y(BAD_TBCOL)427 b(234)190 b(TBCOLn)46 b(keyword)g(value)g(<)i(0)f (or)g(>)h(rowlength)168 3734 y(NOT_TABLE)427 b(235)190 b(the)47 b(CHDU)f(is)i(not)f(a)g(table)168 3847 y(COL_TOO_WIDE)283 b(236)190 b(column)46 b(is)h(too)g(wide)g(to)g(fit)g(in)g(table)168 3960 y(COL_NOT_UNIQUE)187 b(237)j(more)47 b(than)f(1)i(column)e(name)g (matches)g(template)168 4073 y(BAD_ROW_WIDTH)235 b(241)190 b(sum)47 b(of)g(column)f(widths)g(not)h(=)h(NAXIS1)168 4186 y(UNKNOWN_EXT)331 b(251)190 b(unrecognizable)44 b(FITS)i(extension)g(type)168 4299 y(UNKNOWN_REC)331 b(252)190 b(unknown)46 b(record;)g(1st)g(keyword)g(not)h(SIMPLE)f(or)h (XTENSION)168 4412 y(END_JUNK)475 b(253)190 b(END)47 b(keyword)f(is)h(not)g(blank)168 4525 y(BAD_HEADER_FILL)139 b(254)190 b(Header)46 b(fill)h(area)f(contains)g(non-blank)f(chars)168 4638 y(BAD_DATA_FILL)235 b(255)190 b(Illegal)46 b(data)g(fill)h(bytes)f (\(not)h(zero)g(or)g(blank\))168 4751 y(BAD_TFORM)427 b(261)190 b(illegal)46 b(TFORM)g(format)g(code)168 4863 y(BAD_TFORM_DTYPE)139 b(262)190 b(unrecognizable)44 b(TFORM)i(datatype) g(code)168 4976 y(BAD_TDIM)475 b(263)190 b(illegal)46 b(TDIMn)g(keyword)g(value)168 5089 y(BAD_HEAP_PTR)283 b(264)190 b(invalid)46 b(BINTABLE)f(heap)i(pointer)f(is)h(out)g(of)g (range)168 5315 y(BAD_HDU_NUM)331 b(301)190 b(HDU)47 b(number)f(<)h(1)h(or)f(>)g(MAXHDU)168 5428 y(BAD_COL_NUM)331 b(302)190 b(column)46 b(number)g(<)i(1)f(or)g(>)h(tfields)168 5541 y(NEG_FILE_POS)283 b(304)190 b(tried)46 b(to)h(move)g(to)g (negative)f(byte)g(location)g(in)h(file)1905 5809 y Ff(39)p eop end %%Page: 40 40 TeXDict begin 40 39 bop 168 573 a Fc(NEG_BYTES)427 b(306)190 b(tried)46 b(to)h(read)g(or)g(write)g(negative)e(number)h(of)h(bytes) 168 686 y(BAD_ROW_NUM)331 b(307)190 b(illegal)46 b(starting)f(row)i (number)f(in)h(table)168 799 y(BAD_ELEM_NUM)283 b(308)190 b(illegal)46 b(starting)f(element)h(number)g(in)h(vector)168 912 y(NOT_ASCII_COL)235 b(309)190 b(this)47 b(is)g(not)g(an)g(ASCII)f (string)g(column)168 1024 y(NOT_LOGICAL_COL)139 b(310)190 b(this)47 b(is)g(not)g(a)g(logical)f(datatype)f(column)168 1137 y(BAD_ATABLE_FORMAT)e(311)190 b(ASCII)46 b(table)h(column)f(has)h (wrong)f(format)168 1250 y(BAD_BTABLE_FORMAT)d(312)190 b(Binary)46 b(table)g(column)g(has)h(wrong)g(format)168 1363 y(NO_NULL)523 b(314)190 b(null)47 b(value)f(has)h(not)g(been)f (defined)168 1476 y(NOT_VARI_LEN)283 b(317)190 b(this)47 b(is)g(not)g(a)g(variable)f(length)g(column)168 1589 y(BAD_DIMEN)427 b(320)190 b(illegal)46 b(number)g(of)h(dimensions)e(in) i(array)168 1702 y(BAD_PIX_NUM)331 b(321)190 b(first)46 b(pixel)h(number)f(greater)g(than)g(last)h(pixel)168 1815 y(ZERO_SCALE)379 b(322)190 b(illegal)46 b(BSCALE)g(or)h(TSCALn)f (keyword)g(=)h(0)168 1928 y(NEG_AXIS)475 b(323)190 b(illegal)46 b(axis)g(length)g(<)i(1)168 2154 y(NOT_GROUP_TABLE)330 b(340)142 b(Grouping)46 b(function)f(error)168 2267 y (HDU_ALREADY_MEMBER)186 b(341)168 2379 y(MEMBER_NOT_FOUND)282 b(342)168 2492 y(GROUP_NOT_FOUND)330 b(343)168 2605 y(BAD_GROUP_ID)474 b(344)168 2718 y(TOO_MANY_HDUS_TRACKED)42 b(345)168 2831 y(HDU_ALREADY_TRACKED)138 b(346)168 2944 y(BAD_OPTION)570 b(347)168 3057 y(IDENTICAL_POINTERS)186 b(348)168 3170 y(BAD_GROUP_ATTACH)282 b(349)168 3283 y(BAD_GROUP_DETACH)g(350)168 3509 y(NGP_NO_MEMORY)426 b(360)238 b(malloc)46 b(failed)168 3621 y(NGP_READ_ERR)474 b(361)238 b(read)46 b(error)h(from)f(file)168 3734 y(NGP_NUL_PTR)522 b(362)238 b(null)46 b(pointer)g(passed)g(as)h (an)g(argument.)1695 3847 y(Passing)f(null)g(pointer)g(as)h(a)h(name)f (of)1695 3960 y(template)f(file)g(raises)g(this)h(error)168 4073 y(NGP_EMPTY_CURLINE)234 b(363)k(line)46 b(read)h(seems)f(to)h(be)h (empty)e(\(used)1695 4186 y(internally\))168 4299 y (NGP_UNREAD_QUEUE_FULL)c(364)238 b(cannot)46 b(unread)g(more)g(then)h (1)g(line)g(\(or)g(single)1695 4412 y(line)g(twice\))168 4525 y(NGP_INC_NESTING)330 b(365)238 b(too)46 b(deep)h(include)f(file)h (nesting)e(\(infinite)1695 4638 y(loop,)h(template)g(includes)f(itself) i(?\))168 4751 y(NGP_ERR_FOPEN)426 b(366)238 b(fopen\(\))45 b(failed,)h(cannot)g(open)h(template)e(file)168 4863 y(NGP_EOF)714 b(367)238 b(end)46 b(of)i(file)e(encountered)f(and)i(not) g(expected)168 4976 y(NGP_BAD_ARG)522 b(368)238 b(bad)46 b(arguments)g(passed.)g(Usually)f(means)1695 5089 y(internal)h(parser)g (error.)g(Should)g(not)h(happen)168 5202 y(NGP_TOKEN_NOT_EXPECT)90 b(369)238 b(token)46 b(not)h(expected)e(here)168 5428 y(BAD_I2C)523 b(401)190 b(bad)47 b(int)g(to)g(formatted)e(string)h (conversion)168 5541 y(BAD_F2C)523 b(402)190 b(bad)47 b(float)f(to)h(formatted)f(string)g(conversion)1905 5809 y Ff(40)p eop end %%Page: 41 41 TeXDict begin 41 40 bop 168 573 a Fc(BAD_INTKEY)379 b(403)190 b(can't)46 b(interpret)g(keyword)f(value)i(as)g(integer)168 686 y(BAD_LOGICALKEY)187 b(404)j(can't)46 b(interpret)g(keyword)f (value)i(as)g(logical)168 799 y(BAD_FLOATKEY)283 b(405)190 b(can't)46 b(interpret)g(keyword)f(value)i(as)g(float)168 912 y(BAD_DOUBLEKEY)235 b(406)190 b(can't)46 b(interpret)g(keyword)f (value)i(as)g(double)168 1024 y(BAD_C2I)523 b(407)190 b(bad)47 b(formatted)e(string)h(to)h(int)g(conversion)168 1137 y(BAD_C2F)523 b(408)190 b(bad)47 b(formatted)e(string)h(to)h (float)g(conversion)168 1250 y(BAD_C2D)523 b(409)190 b(bad)47 b(formatted)e(string)h(to)h(double)f(conversion)168 1363 y(BAD_DATATYPE)283 b(410)190 b(illegal)46 b(datatype)f(code)i (value)168 1476 y(BAD_DECIM)427 b(411)190 b(bad)47 b(number)f(of)h (decimal)f(places)g(specified)168 1589 y(NUM_OVERFLOW)283 b(412)190 b(overflow)45 b(during)i(datatype)e(conversion)168 1702 y(DATA_COMPRESSION_ERR)137 b(413)95 b(error)46 b(compressing)f (image)168 1815 y(DATA_DECOMPRESSION_ERR)c(414)95 b(error)46 b(uncompressing)f(image)168 2041 y(BAD_DATE)475 b(420)190 b(error)46 b(in)h(date)g(or)g(time)g(conversion)168 2267 y(PARSE_SYNTAX_ERR)91 b(431)190 b(syntax)46 b(error)g(in)i(parser)e (expression)168 2379 y(PARSE_BAD_TYPE)187 b(432)j(expression)45 b(did)i(not)g(evaluate)e(to)i(desired)f(type)168 2492 y(PARSE_LRG_VECTOR)91 b(433)190 b(vector)46 b(result)g(too)h(large)f (to)i(return)e(in)h(array)168 2605 y(PARSE_NO_OUTPUT)139 b(434)190 b(data)47 b(parser)f(failed)g(not)h(sent)f(an)h(out)g(column) 168 2718 y(PARSE_BAD_COL)235 b(435)190 b(bad)47 b(data)f(encounter)g (while)g(parsing)g(column)168 2831 y(PARSE_BAD_OUTPUT)91 b(436)190 b(Output)46 b(file)h(not)g(of)g(proper)f(type)168 3057 y(ANGLE_TOO_BIG)235 b(501)190 b(celestial)45 b(angle)i(too)f (large)h(for)g(projection)168 3170 y(BAD_WCS_VAL)331 b(502)190 b(bad)47 b(celestial)e(coordinate)g(or)i(pixel)g(value)168 3283 y(WCS_ERROR)427 b(503)190 b(error)46 b(in)h(celestial)f (coordinate)f(calculation)168 3396 y(BAD_WCS_PROJ)283 b(504)190 b(unsupported)45 b(type)h(of)h(celestial)f(projection)168 3509 y(NO_WCS_KEY)379 b(505)190 b(celestial)45 b(coordinate)g(keywords) h(not)h(found)168 3621 y(APPROX_WCS_KEY)187 b(506)j(approximate)45 b(wcs)i(keyword)e(values)h(were)h(returned)1905 5809 y Ff(41)p eop end %%Trailer userdict /end-hook known{end-hook}if %%EOF cfitsio/docs/quick.tex0000644000225700000360000030611013246025103014567 0ustar cagordonlhea\documentclass[11pt]{article} \input{html.sty} \htmladdtonavigation {\begin{rawhtml} FITSIO Home \end{rawhtml}} \oddsidemargin=0.20in \evensidemargin=0.20in \textwidth=15.5truecm \textheight=21.5truecm \title{CFITSIO Quick Start Guide} \author{William Pence \thanks{HEASARC, NASA Goddard Space Flight Center}} \date{January 2003} \begin{document} \maketitle \tableofcontents % =================================================================== \section{Introduction} This document is intended to help you quickly start writing C programs to read and write FITS files using the CFITSIO library. It covers the most important CFITSIO routines that are needed to perform most types of operations on FITS files. For more complete information about these and all the other available routines in the library please refer to the ``CFITSIO User's Reference Guide'', which is available from the CFITSIO Web site at {\tt http://heasarc.gsfc.nasa.gov/fitsio}. For more general information about the FITS data format, refer to the following web page: http://heasarc.gsfc.nasa.gov/docs/heasarc/fits.html FITS stands for Flexible Image Transport System and is the standard file format used to store most astronomical data files. There are 2 basic types of FITS files: images and tables. FITS images often contain a 2-dimensional array of pixels representing an image of a piece of the sky, but FITS images can also contain 1-D arrays (i.e, a spectrum or light curve), or 3-D arrays (a data cube), or even higher dimensional arrays of data. An image may also have zero dimensions, in which case it is referred to as a null or empty array. The supported datatypes for the image arrays are 8, 16, and 32-bit integers, and 32 and 64-bit floating point real numbers. Both signed and unsigned integers are supported. FITS tables contain rows and columns of data, similar to a spreadsheet. All the values in a particular column must have the same datatype. A cell of a column is not restricted to a single number, and instead can contain an array or vector of numbers. There are actually 2 subtypes of FITS tables: ASCII and binary. As the names imply, ASCII tables store the data values in an ASCII representation whereas binary tables store the data values in a more efficient machine-readable binary format. Binary tables are generally more compact and support more features (e.g., a wider range of datatypes, and vector columns) than ASCII tables. A single FITS file many contain multiple images or tables. Each table or image is called a Header-Data Unit, or HDU. The first HDU in a FITS file must be an image (but it may have zero axes) and is called the Primary Array. Any additional HDUs in the file (which are also referred to as `extensions') may contain either an image or a table. Every HDU contains a header containing keyword records. Each keyword record is 80 ASCII characters long and has the following format: \begin{verbatim} KEYWORD = value / comment string \end{verbatim} The keyword name can be up to 8 characters long (all uppercase). The value can be either an integer or floating point number, a logical value (T or F), or a character string enclosed in single quotes. Each header begins with a series of required keywords to describe the datatype and format of the following data unit, if any. Any number of other optional keywords can be included in the header to provide other descriptive information about the data. For the most part, the CFITSIO routines automatically write the required FITS keywords for each HDU, so you, the programmer, usually do not need to worry about them. % =================================================================== \section{Installing and Using CFITSIO} First, you should download the CFITSIO software and the set of example FITS utility programs from the web site at http://heasarc.gsfc.nasa.gov/fitsio. The example programs illustrate how to perform many common types of operations on FITS files using CFITSIO. They are also useful when writing a new program because it is often easier to take a copy of one of these utility programs as a template and then modify it for your own purposes, rather than writing the new program completely from scratch. To build the CFITSIO library on Unix platforms, `untar' the source code distribution file and then execute the following commands in the directory containing the source code: \begin{verbatim} > ./configure [--prefix=/target/installation/path] > make (or 'make shared') > make install (this step is optional) \end{verbatim} The optional 'prefix' argument to configure gives the path to the directory where the CFITSIO library and include files should be installed via the later 'make install' command. For example, \begin{verbatim} > ./configure --prefix=/usr1/local \end{verbatim} will cause the 'make install' command to copy the CFITSIO libcfitsio file to /usr1/local/lib and the necessary include files to /usr1/local/include (assuming of course that the process has permission to write to these directories). Pre-compiled versions of the CFITSIO DLL library are available for PCs. On Macintosh machines, refer to the README.MacOS file for instructions on building CFITSIO using CodeWarrior. Any programs that use CFITSIO must of course be linked with the CFITSIO library when creating the executable file. The exact procedure for linking a program depends on your software environment, but on Unix platforms, the command line to compile and link a program will look something like this: \begin{verbatim} gcc -o myprog myprog.c -L. -lcfitsio -lm -lnsl -lsocket \end{verbatim} You may not need to include all of the 'm', 'nsl', and 'socket' system libraries on your particular machine. To find out what libraries are required on your (Unix) system, type {\tt'make testprog'} and see what libraries are then included on the resulting link line. \newpage % =================================================================== \section{Example Programs} Before describing the individual CFITSIO routines in detail, it is instructive to first look at an actual program. The names of the CFITSIO routines are fairly descriptive (they all begin with {\tt fits\_}, so it should be reasonably clear what this program does: \begin{verbatim} ---------------------------------------------------------------- #include #include 1: #include "fitsio.h" int main(int argc, char *argv[]) { 2: fitsfile *fptr; char card[FLEN_CARD]; 3: int status = 0, nkeys, ii; /* MUST initialize status */ 4: fits_open_file(&fptr, argv[1], READONLY, &status); fits_get_hdrspace(fptr, &nkeys, NULL, &status); for (ii = 1; ii <= nkeys; ii++) { fits_read_record(fptr, ii, card, &status); /* read keyword */ printf("%s\n", card); } printf("END\n\n"); /* terminate listing with END */ fits_close_file(fptr, &status); if (status) /* print any error messages */ 5: fits_report_error(stderr, status); return(status); } ---------------------------------------------------------------- \end{verbatim} This program opens the specified FITS file and prints out all the header keywords in the current HDU. Some other points to notice about the program are: \begin{enumerate} \item The {\tt fitsio.h} header file must be included to define the various routines and symbols used in CFITSIO. \item The {\tt fitsfile} parameter is the first argument in almost every CFITSIO routine. It is a pointer to a structure (defined in {\tt fitsio.h}) that stores information about the particular FITS file that the routine will operate on. Memory for this structure is automatically allocated when the file is first opened or created, and is freed when the file is closed. \item Almost every CFITSIO routine has a {\tt status} parameter as the last argument. The status value is also usually returned as the value of the function itself. Normally status = 0, and a positive status value indicates an error of some sort. The status variable must always be initialized to zero before use, because if status is greater than zero on input then the CFITSIO routines will simply return without doing anything. This `inherited status' feature, where each CFITSIO routine inherits the status from the previous routine, makes it unnecessary to check the status value after every single CFITSIO routine call. Generally you should check the status after an especially important or complicated routine has been called, or after a block of closely related CFITSIO calls. This example program has taken this feature to the extreme and only checks the status value at the very end of the program. \item In this example program the file name to be opened is given as an argument on the command line ({\tt arg[1]}). If the file contains more than 1 HDU or extension, you can specify which particular HDU to be opened by enclosing the name or number of the HDU in square brackets following the root name of the file. For example, {\tt file.fts[0]} opens the primary array, while {\tt file.fts[2]} will move to and open the 2nd extension in the file, and {\tt file.fit[EVENTS]} will open the extension that has a {\tt EXTNAME = 'EVENTS'} keyword in the header. Note that on the Unix command line you must enclose the file name in single or double quote characters if the name contains special characters such as `[' or `]'. All of the CFITSIO routines which read or write header keywords, image data, or table data operate only within the currently opened HDU in the file. To read or write information in a different HDU you must first explicitly move to that HDU (see the {\tt fits\_movabs\_hdu} and {\tt fits\_movrel\_hdu} routines in section 4.3). \item The {\tt fits\_report\_error} routine provides a convenient way to print out diagnostic messages about any error that may have occurred. \end{enumerate} A set of example FITS utility programs are available from the CFITSIO web site at \newline http://heasarc.gsfc.nasa.gov/docs/software/fitsio/cexamples.html. These are real working programs which illustrate how to read, write, and modify FITS files using the CFITSIO library. Most of these programs are very short, containing only a few 10s of lines of executable code or less, yet they perform quite useful operations on FITS files. Running each program without any command line arguments will produce a short description of how to use the program. The currently available programs are: \begin{quote} fitscopy - copy a file \newline listhead - list header keywords \newline liststruc - show the structure of a FITS file. \newline modhead - write or modify a header keyword \newline imarith - add, subtract, multiply, or divide 2 images \newline imlist - list pixel values in an image \newline imstat - compute mean, min, and max pixel values in an image \newline tablist - display the contents of a FITS table \newline tabcalc - general table calculator \end{quote} \newpage % =================================================================== \section{CFITSIO Routines} This chapter describes the main CFITSIO routines that can be used to perform the most common types of operations on FITS files. % =================================================================== {\bf \subsection{Error Reporting}} \begin{verbatim} void fits_report_error(FILE *stream, int status) void fits_get_errstatus(int status, char *err_text) float fits_get_version(float *version) \end{verbatim} The first routine prints out information about any error that has occurred. Whenever any CFITSIO routine encounters an error it usually writes a message describing the nature of the error to an internal error message stack and then returns with a positive integer status value. Passing the error status value to this routine will cause a generic description of the error and all the messages from the internal CFITSIO error stack to be printed to the specified stream. The {\tt stream} parameter is usually set equal to {\tt "stdout"} or {\tt "stderr"}. The second routine simply returns a 30-character descriptive error message corresponding to the input status value. The last routine returns the current CFITSIO library version number. % =================================================================== {\bf \subsection{File Open/Close Routines}} \begin{verbatim} int fits_open_file( fitsfile **fptr, char *filename, int mode, int *status) int fits_open_data( fitsfile **fptr, char *filename, int mode, int *status) int fits_open_table(fitsfile **fptr, char *filename, int mode, int *status) int fits_open_image(fitsfile **fptr, char *filename, int mode, int *status) int fits_create_file(fitsfile **fptr, char *filename, int *status) int fits_close_file(fitsfile *fptr, int *status) \end{verbatim} These routines open or close a file. The first {\tt fitsfile} parameter in these and nearly every other CFITSIO routine is a pointer to a structure that CFITSIO uses to store relevant parameters about each opened file. You should never directly read or write any information in this structure. Memory for this structure is allocated automatically when the file is opened or created, and is freed when the file is closed. The {\tt mode} parameter in the {\tt fits\_open\_xxxx} set of routines can be set to either {\tt READONLY} or {\tt READWRITE} to select the type of file access that will be allowed. These symbolic constants are defined in {\tt fitsio.h}. The {\tt fits\_open\_file} routine opens the file and positions the internal file pointer to the beginning of the file, or to the specified extension if an extension name or number is appended to the file name (see the later section on ``CFITSIO File Names and Filters'' for a description of the syntax). {\tt fits\_open\_data} behaves similarly except that it will move to the first HDU containing significant data if a HDU name or number to open is not explicitly specified as part of the filename. It will move to the first IMAGE HDU with NAXIS greater than 0, or the first table that does not contain the strings `GTI' (a Good Time Interval extension) or `OBSTABLE' in the EXTNAME keyword value. The {\tt fits\_open\_table} and {\tt fits\_open\_image} routines are similar except that they will move to the first significant table HDU or image HDU, respectively if a HDU name of number is not specified as part of the input file name. When opening an existing file, the {\tt filename} can include optional arguments, enclosed in square brackets that specify filtering operations that should be applied to the input file. For example, \begin{verbatim} myfile.fit[EVENTS][counts > 0] \end{verbatim} opens the table in the EVENTS extension and creates a virtual table by selecting only those rows where the COUNTS column value is greater than 0. See section 5 for more examples of these powerful filtering capabilities. In {\tt fits\_create\_file}, the {\tt filename} is simply the root name of the file to be created. You can overwrite an existing file by prefixing the name with a `!' character (on the Unix command line this must be prefixed with a backslash, as in \verb+`\!file.fit'+). If the file name ends with {\tt .gz} the file will be compressed using the gzip algorithm. If the filename is {\tt stdout} or {\tt "-"} (a single dash character) then the output file will be piped to the stdout stream. You can chain several tasks together by writing the output from the first task to {\tt stdout} and then reading the input file in the 2nd task from {\tt stdin} or {\tt "-"}. % =================================================================== {\bf \subsection{HDU-level Routines}} The routines listed in this section operate on Header-Data Units (HDUs) in a file. \begin{verbatim} _______________________________________________________________ int fits_get_num_hdus(fitsfile *fptr, int *hdunum, int *status) int fits_get_hdu_num(fitsfile *fptr, int *hdunum) \end{verbatim} The first routines returns the total number of HDUs in the FITS file, and the second routine returns the position of the currently opened HDU in the FITS file (starting with 1, not 0). \begin{verbatim} __________________________________________________________________________ int fits_movabs_hdu(fitsfile *fptr, int hdunum, int *hdutype, int *status) int fits_movrel_hdu(fitsfile *fptr, int nmove, int *hdutype, int *status) int fits_movnam_hdu(fitsfile *fptr, int hdutype, char *extname, int extver, int *status) \end{verbatim} These routines enable you to move to a different HDU in the file. Most of the CFITSIO functions which read or write keywords or data operate only on the currently opened HDU in the file. The first routine moves to the specified absolute HDU number in the FITS file (the first HDU = 1), whereas the second routine moves a relative number of HDUs forward or backward from the currently open HDU. The {\tt hdutype} parameter returns the type of the newly opened HDU, and will be equal to one of these symbolic constant values: {\tt IMAGE\_HDU, ASCII\_TBL, or BINARY\_TBL}. {\tt hdutype} may be set to NULL if it is not needed. The third routine moves to the (first) HDU that matches the input extension type, name, and version number, as given by the {\tt XTENSION, EXTNAME} (or {\tt HDUNAME}) and {\tt EXTVER} keywords. If the input value of {\tt extver} = 0, then the version number will be ignored when looking for a matching HDU. \begin{verbatim} _________________________________________________________________ int fits_get_hdu_type(fitsfile *fptr, int *hdutype, int *status) \end{verbatim} Get the type of the current HDU in the FITS file: {\tt IMAGE\_HDU, ASCII\_TBL, or BINARY\_TBL}. \begin{verbatim} ____________________________________________________________________ int fits_copy_hdu(fitsfile *infptr, fitsfile *outfptr, int morekeys, int *status) int fits_copy_file(fitsfile *infptr, fitsfile *outfptr, int previous, int current, int following, > int *status) \end{verbatim} The first routine copies the current HDU from the FITS file associated with infptr and appends it to the end of the FITS file associated with outfptr. Space may be reserved for {\tt morekeys} additional keywords in the output header. The second routine copies any HDUs previous to the current HDU, and/or the current HDU, and/or any HDUs following the current HDU, depending on the value (True or False) of {\tt previous, current}, and {\tt following}, respectively. For example, \begin{verbatim} fits_copy_file(infptr, outfptr, 0, 1, 1, &status); \end{verbatim} will copy the current HDU and any HDUs that follow it from the input to the output file, but it will not copy any HDUs preceding the current HDU. \newpage % =================================================================== \subsection{Image I/O Routines} This section lists the more important CFITSIO routines which operate on FITS images. \begin{verbatim} _______________________________________________________________ int fits_get_img_type(fitsfile *fptr, int *bitpix, int *status) int fits_get_img_dim( fitsfile *fptr, int *naxis, int *status) int fits_get_img_size(fitsfile *fptr, int maxdim, long *naxes, int *status) int fits_get_img_param(fitsfile *fptr, int maxdim, int *bitpix, int *naxis, long *naxes, int *status) \end{verbatim} Get information about the currently opened image HDU. The first routine returns the datatype of the image as (defined by the {\tt BITPIX} keyword), which can have the following symbolic constant values: \begin{verbatim} BYTE_IMG = 8 ( 8-bit byte pixels, 0 - 255) SHORT_IMG = 16 (16 bit integer pixels) LONG_IMG = 32 (32-bit integer pixels) LONGLONG_IMG = 64 (64-bit integer pixels) FLOAT_IMG = -32 (32-bit floating point pixels) DOUBLE_IMG = -64 (64-bit floating point pixels) \end{verbatim} The second and third routines return the number of dimensions in the image (from the {\tt NAXIS} keyword), and the sizes of each dimension (from the {\tt NAXIS1, NAXIS2}, etc. keywords). The last routine simply combines the function of the first 3 routines. The input {\tt maxdim} parameter in this routine gives the maximum number dimensions that may be returned (i.e., the dimension of the {\tt naxes} array) \begin{verbatim} __________________________________________________________ int fits_create_img(fitsfile *fptr, int bitpix, int naxis, long *naxes, int *status) \end{verbatim} Create an image HDU by writing the required keywords which define the structure of the image. The 2nd through 4th parameters specified the datatype, the number of dimensions, and the sizes of the dimensions. The allowed values of the {\tt bitpix} parameter are listed above in the description of the {\tt fits\_get\_img\_type} routine. If the FITS file pointed to by {\tt fptr} is empty (previously created with {\tt fits\_create\_file}) then this routine creates a primary array in the file, otherwise a new IMAGE extension is appended to end of the file following the other HDUs in the file. \begin{verbatim} ______________________________________________________________ int fits_write_pix(fitsfile *fptr, int datatype, long *fpixel, long nelements, void *array, int *status); int fits_write_pixnull(fitsfile *fptr, int datatype, long *fpixel, long nelements, void *array, void *nulval, int *status); int fits_read_pix(fitsfile *fptr, int datatype, long *fpixel, long nelements, void *nulval, void *array, int *anynul, int *status) \end{verbatim} Read or write all or part of the FITS image. There are 2 different 'write' pixel routines: The first simply writes the input array of pixels to the FITS file. The second is similar, except that it substitutes the appropriate null pixel value in the FITS file for any pixels which have a value equal to {\tt *nulval} (note that this parameter gives the address of the null pixel value, not the value itself). Similarly, when reading an image, CFITSIO will substitute the value given by {\tt nulval} for any undefined pixels in the image, unless {\tt nulval = NULL}, in which case no checks will be made for undefined pixels when reading the FITS image. The {\tt fpixel} parameter in these routines is an array which gives the coordinate in each dimension of the first pixel to be read or written, and {\tt nelements} is the total number of pixels to read or write. {\tt array} is the address of an array which either contains the pixel values to be written, or will hold the values of the pixels that are read. When reading, {\tt array} must have been allocated large enough to hold all the returned pixel values. These routines starts at the {\tt fpixel} location and then read or write the {\tt nelements} pixels, continuing on successive rows of the image if necessary. For example, to write an entire 2D image, set {\tt fpixel[0] = fpixel[1] = 1}, and {\tt nelements = NAXIS1 * NAXIS2}. Or to read just the 10th row of the image, set {\tt fpixel[0] = 1, fpixel[1] = 10}, and {\tt nelements = NAXIS1}. The {\tt datatype} parameter specifies the datatype of the C {\tt array} in the program, which need not be the same as the datatype of the FITS image itself. If the datatypes differ then CFITSIO will convert the data as it is read or written. The following symbolic constants are allowed for the value of {\tt datatype}: \begin{verbatim} TBYTE unsigned char TSBYTE signed char TSHORT signed short TUSHORT unsigned short TINT signed int TUINT unsigned int TLONG signed long TLONGLONG signed 8-byte integer TULONG unsigned long TFLOAT float TDOUBLE double \end{verbatim} \begin{verbatim} _________________________________________________________________ int fits_write_subset(fitsfile *fptr, int datatype, long *fpixel, long *lpixel, DTYPE *array, > int *status) int fits_read_subset(fitsfile *fptr, int datatype, long *fpixel, long *lpixel, long *inc, void *nulval, void *array, int *anynul, int *status) \end{verbatim} Read or write a rectangular section of the FITS image. These are very similar to {\tt fits\_write\_pix} and {\tt fits\_read\_pix} except that you specify the last pixel coordinate (the upper right corner of the section) instead of the number of pixels to be read. The read routine also has an {\tt inc} parameter which can be used to read only every {\tt inc-th} pixel along each dimension of the image. Normally {\tt inc[0] = inc[1] = 1} to read every pixel in a 2D image. To read every other pixel in the entire 2D image, set \begin{verbatim} fpixel[0] = fpixel[1] = 1 lpixel[0] = {NAXIS1} lpixel[1] = {NAXIS2} inc[0] = inc[1] = 2 \end{verbatim} Or, to read the 8th row of a 2D image, set \begin{verbatim} fpixel[0] = 1 fpixel[1] = 8 lpixel[0] = {NAXIS1} lpixel[1] = 8 inc[0] = inc[1] = 1 \end{verbatim} \newpage % =================================================================== \subsection{Table I/O Routines} This section lists the most important CFITSIO routines which operate on FITS tables. \begin{verbatim} __________________________________________________________________________ int fits_create_tbl(fitsfile *fptr, int tbltype, long nrows, int tfields, char *ttype[],char *tform[], char *tunit[], char *extname, int *status) \end{verbatim} Create a new table extension by writing the required keywords that define the table structure. The required null primary array will be created first if the file is initially completely empty. {\tt tbltype} defines the type of table and can have values of {\tt ASCII\_TBL or BINARY\_TBL}. Binary tables are generally preferred because they are more efficient and support a greater range of column datatypes than ASCII tables. The {\tt nrows} parameter gives the initial number of empty rows to be allocated for the table; this should normally be set to 0. The {\tt tfields} parameter gives the number of columns in the table (maximum = 999). The {\tt ttype, tform}, and {\tt tunit} parameters give the name, datatype, and physical units of each column, and {\tt extname} gives the name for the table (the value of the {\tt EXTNAME} keyword). The FITS Standard recommends that only letters, digits, and the underscore character be used in column names with no embedded spaces. It is recommended that all the column names in a given table be unique within the first 8 characters. The following table shows the TFORM column format values that are allowed in ASCII tables and in binary tables: \begin{verbatim} ASCII Table Column Format Codes ------------------------------- (w = column width, d = no. of decimal places to display) Aw - character string Iw - integer Fw.d - fixed floating point Ew.d - exponential floating point Dw.d - exponential floating point Binary Table Column Format Codes -------------------------------- (r = vector length, default = 1) rA - character string rAw - array of strings, each of length w rL - logical rX - bit rB - unsigned byte rS - signed byte ** rI - signed 16-bit integer rU - unsigned 16-bit integer ** rJ - signed 32-bit integer rV - unsigned 32-bit integer ** rK - signed 64-bit integer rE - 32-bit floating point rD - 64-bit floating point rC - 32-bit complex pair rM - 64-bit complex pair ** The S, U and V format codes are not actual legal TFORMn values. CFITSIO substitutes the somewhat more complicated set of keywords that are used to represent unsigned integers or signed bytes. \end{verbatim} The {\tt tunit} and {\tt extname} parameters are optional and may be set to NULL if they are not needed. Note that it may be easier to create a new table by copying the header from another existing table with {\tt fits\_copy\_header} rather than calling this routine. \begin{verbatim} _______________________________________________________________ int fits_get_num_rows(fitsfile *fptr, long *nrows, int *status) int fits_get_num_cols(fitsfile *fptr, int *ncols, int *status) \end{verbatim} Get the number of rows or columns in the current FITS table. The number of rows is given by the {\tt NAXIS2} keyword and the number of columns is given by the {\tt TFIELDS} keyword in the header of the table. \begin{verbatim} _______________________________________________________________ int fits_get_colnum(fitsfile *fptr, int casesen, char *template, int *colnum, int *status) int fits_get_colname(fitsfile *fptr, int casesen, char *template, char *colname, int *colnum, int *status) \end{verbatim} Get the column number (starting with 1, not 0) of the column whose name matches the specified template name. The only difference in these 2 routines is that the 2nd one also returns the name of the column that matched the template string. Normally, {\tt casesen} should be set to {\tt CASEINSEN}, but it may be set to {\tt CASESEN} to force the name matching to be case-sensitive. The input {\tt template} string gives the name of the desired column and may include wildcard characters: a `*' matches any sequence of characters (including zero characters), `?' matches any single character, and `\#' matches any consecutive string of decimal digits (0-9). If more than one column name in the table matches the template string, then the first match is returned and the status value will be set to {\tt COL\_NOT\_UNIQUE} as a warning that a unique match was not found. To find the next column that matches the template, call this routine again leaving the input status value equal to {\tt COL\_NOT\_UNIQUE}. Repeat this process until {\tt status = COL\_NOT\_FOUND} is returned. \begin{verbatim} _______________________________________________________________ int fits_get_coltype(fitsfile *fptr, int colnum, int *typecode, long *repeat, long *width, int *status) int fits_get_eqcoltype(fitsfile *fptr, int colnum, int *typecode, long *repeat, long *width, int *status) \end{verbatim} Return the datatype, vector repeat count, and the width in bytes of a single column element for column number {\tt colnum}. Allowed values for the returned datatype in ASCII tables are: {\tt TSTRING, TSHORT, TLONG, TFLOAT, and TDOUBLE}. Binary tables support these additional types: {\tt TLOGICAL, TBIT, TBYTE, TINT32BIT, TCOMPLEX and TDBLCOMPLEX}. The negative of the datatype code value is returned if it is a variable length array column. These 2 routines are similar, except that in the case of scaled integer columns the 2nd routine, fit\_get\_eqcoltype, returns the 'equivalent' datatype that is needed to store the scaled values, which is not necessarily the same as the physical datatype of the unscaled values as stored in the FITS table. For example if a '1I' column in a binary table has TSCALn = 1 and TZEROn = 32768, then this column effectively contains unsigned short integer values, and thus the returned value of typecode will be TUSHORT, not TSHORT. Or, if TSCALn or TZEROn are not integers, then the equivalent datatype will be returned as TFLOAT or TDOUBLE, depending on the size of the integer. The repeat count is always 1 in ASCII tables. The 'repeat' parameter returns the vector repeat count on the binary table TFORMn keyword value. (ASCII table columns always have repeat = 1). The 'width' parameter returns the width in bytes of a single column element (e.g., a '10D' binary table column will have width = 8, an ASCII table 'F12.2' column will have width = 12, and a binary table'60A' character string column will have width = 60); Note that this routine supports the local convention for specifying arrays of fixed length strings within a binary table character column using the syntax TFORM = 'rAw' where 'r' is the total number of characters (= the width of the column) and 'w' is the width of a unit string within the column. Thus if the column has TFORM = '60A12' then this means that each row of the table contains 5 12-character substrings within the 60-character field, and thus in this case this routine will return typecode = TSTRING, repeat = 60, and width = 12. The number of substings in any binary table character string field can be calculated by (repeat/width). A null pointer may be given for any of the output parameters that are not needed. \begin{verbatim} ____________________________________________________________________________ int fits_insert_rows(fitsfile *fptr, long firstrow, long nrows, int *status) int fits_delete_rows(fitsfile *fptr, long firstrow, long nrows, int *status) int fits_delete_rowrange(fitsfile *fptr, char *rangelist, int *status) int fits_delete_rowlist(fitsfile *fptr, long *rowlist, long nrows, int *stat) \end{verbatim} Insert or delete rows in a table. The blank rows are inserted immediately following row {\tt frow}. Set {\tt frow} = 0 to insert rows at the beginning of the table. The first 'delete' routine deletes {\tt nrows} rows beginning with row {\tt firstrow}. The 2nd delete routine takes an input string listing the rows or row ranges to be deleted (e.g., '2,4-7, 9-12'). The last delete routine takes an input long integer array that specifies each individual row to be deleted. The row lists must be sorted in ascending order. All these routines update the value of the {\tt NAXIS2} keyword to reflect the new number of rows in the table. \begin{verbatim} _________________________________________________________________________ int fits_insert_col(fitsfile *fptr, int colnum, char *ttype, char *tform, int *status) int fits_insert_cols(fitsfile *fptr, int colnum, int ncols, char **ttype, char **tform, int *status) int fits_delete_col(fitsfile *fptr, int colnum, int *status) \end{verbatim} Insert or delete columns in a table. {\tt colnum} gives the position of the column to be inserted or deleted (where the first column of the table is at position 1). {\tt ttype} and {\tt tform} give the column name and column format, where the allowed format codes are listed above in the description of the {\tt fits\_create\_table} routine. The 2nd 'insert' routine inserts multiple columns, where {\tt ncols} is the number of columns to insert, and {\tt ttype} and {\tt tform} are arrays of string pointers in this case. \begin{verbatim} ____________________________________________________________________ int fits_copy_col(fitsfile *infptr, fitsfile *outfptr, int incolnum, int outcolnum, int create_col, int *status); \end{verbatim} Copy a column from one table HDU to another. If {\tt create\_col} = TRUE (i.e., not equal to zero), then a new column will be inserted in the output table at position {\tt outcolumn}, otherwise the values in the existing output column will be overwritten. \begin{verbatim} __________________________________________________________________________ int fits_write_col(fitsfile *fptr, int datatype, int colnum, long firstrow, long firstelem, long nelements, void *array, int *status) int fits_write_colnull(fitsfile *fptr, int datatype, int colnum, long firstrow, long firstelem, long nelements, void *array, void *nulval, int *status) int fits_write_col_null(fitsfile *fptr, int colnum, long firstrow, long firstelem, long nelements, int *status) int fits_read_col(fitsfile *fptr, int datatype, int colnum, long firstrow, long firstelem, long nelements, void *nulval, void *array, int *anynul, int *status) \end{verbatim} Write or read elements in column number {\tt colnum}, starting with row {\tt firstsrow} and element {\tt firstelem} (if it is a vector column). {\tt firstelem} is ignored if it is a scalar column. The {\tt nelements} number of elements are read or written continuing on successive rows of the table if necessary. {\tt array} is the address of an array which either contains the values to be written, or will hold the returned values that are read. When reading, {\tt array} must have been allocated large enough to hold all the returned values. There are 3 different 'write' column routines: The first simply writes the input array into the column. The second is similar, except that it substitutes the appropriate null pixel value in the column for any input array values which are equal to {\tt *nulval} (note that this parameter gives the address of the null pixel value, not the value itself). The third write routine sets the specified table elements to a null value. New rows will be automatical added to the table if the write operation extends beyond the current size of the table. When reading a column, CFITSIO will substitute the value given by {\tt nulval} for any undefined elements in the FITS column, unless {\tt nulval} or {\tt *nulval = NULL}, in which case no checks will be made for undefined values when reading the column. {\tt datatype} specifies the datatype of the C {\tt array} in the program, which need not be the same as the intrinsic datatype of the column in the FITS table. The following symbolic constants are allowed for the value of {\tt datatype}: \begin{verbatim} TSTRING array of character string pointers TBYTE unsigned char TSHORT signed short TUSHORT unsigned short TINT signed int TUINT unsigned int TLONG signed long TLONGLONG signed 8-byte integer TULONG unsigned long TFLOAT float TDOUBLE double \end{verbatim} Note that {\tt TSTRING} corresponds to the C {\tt char**} datatype, i.e., a pointer to an array of pointers to an array of characters. Any column, regardless of it's intrinsic datatype, may be read as a {\tt TSTRING} character string. The display format of the returned strings will be determined by the {\tt TDISPn} keyword, if it exists, otherwise a default format will be used depending on the datatype of the column. The {\tt tablist} example utility program (available from the CFITSIO web site) uses this feature to display all the values in a FITS table. \begin{verbatim} _____________________________________________________________________ int fits_select_rows(fitsfile *infptr, fitsfile *outfptr, char *expr, int *status) int fits_calculator(fitsfile *infptr, char *expr, fitsfile *outfptr, char *colname, char *tform, int *status) \end{verbatim} These are 2 of the most powerful routines in the CFITSIO library. (See the full CFITSIO Reference Guide for a description of several related routines). These routines can perform complicated transformations on tables based on an input arithmetic expression which is evaluated for each row of the table. The first routine will select or copy rows of the table for which the expression evaluates to TRUE (i.e., not equal to zero). The second routine writes the value of the expression to a column in the output table. Rather than supplying the expression directly to these routines, the expression may also be written to a text file (continued over multiple lines if necessary) and the name of the file, prepended with a '@' character, may be supplied as the value of the 'expr' parameter (e.g. '@filename.txt'). The arithmetic expression may be a function of any column or keyword in the input table as shown in these examples: \begin{verbatim} Row Selection Expressions: counts > 0 uses COUNTS column value sqrt( X**2 + Y**2) < 10. uses X and Y column values (X > 10) || (X < -10) && (Y == 0) used 'or' and 'and' operators gtifilter() filter on Good Time Intervals regfilter("myregion.reg") filter using a region file @select.txt reads expression from a text file Calculator Expressions: #row % 10 modulus of the row number counts/#exposure Fn of COUNTS column and EXPOSURE keyword dec < 85 ? cos(dec * #deg) : 0 Conditional expression: evaluates to cos(dec) if dec < 85, else 0 (count{-1}+count+count{+1})/3. running mean of the count values in the previous, current, and next rows max(0, min(X, 1000)) returns a value between 0 - 1000 @calc.txt reads expression from a text file \end{verbatim} Most standard mathematical operators and functions are supported. If the expression includes the name of a column, than the value in the current row of the table will be used when evaluating the expression on each row. An offset to an adjacent row can be specified by including the offset value in curly brackets after the column name as shown in one of the examples. Keyword values can be included in the expression by preceding the keyword name with a `\#' sign. See Section 5 of this document for more discussion of the expression syntax. {\tt gtifilter} is a special function which tests whether the {\tt TIME} column value in the input table falls within one or more Good Time Intervals. By default, this function looks for a 'GTI' extension in the same file as the input table. The 'GTI' table contains {\tt START} and {\tt STOP} columns which define the range of each good time interval. See section 5.4.3 for more details. {\tt regfilter} is another special function which selects rows based on whether the spatial position associated with each row is located within in a specified region of the sky. By default, the {\tt X} and {\tt Y} columns in the input table are assumed to give the position of each row. The spatial region is defined in an ASCII text file whose name is given as the argument to the {\tt regfilter} function. See section 5.4.4 for more details. The {\tt infptr} and {\tt outfptr} parameters in these routines may point to the same table or to different tables. In {\tt fits\_select\_rows}, if the input and output tables are the same then the rows that do not satisfy the selection expression will be deleted from the table. Otherwise, if the output table is different from the input table then the selected rows will be copied from the input table to the output table. The output column in {\tt fits\_calculator} may or may not already exist. If it exists then the calculated values will be written to that column, overwriting the existing values. If the column doesn't exist then the new column will be appended to the output table. The {\tt tform} parameter can be used to specify the datatype of the new column (e.g., the {\tt TFORM} keyword value as in {\tt '1E', or '1J'}). If {\tt tform} = NULL then a default datatype will be used, depending on the expression. \begin{verbatim} _____________________________________________________________________ int fits_read_tblbytes(fitsfile *fptr, long firstrow, long firstchar, long nchars, unsigned char *array, int *status) int fits_write_tblbytes (fitsfile *fptr, long firstrow, long firstchar, long nchars, unsigned char *array, int *status) \end{verbatim} These 2 routines provide low-level access to tables and are mainly useful as an efficient way to copy rows of a table from one file to another. These routines simply read or write the specified number of consecutive characters (bytes) in a table, without regard for column boundaries. For example, to read or write the first row of a table, set {\tt firstrow = 1, firstchar = 1}, and {\tt nchars = NAXIS1} where the length of a row is given by the value of the {\tt NAXIS1} header keyword. When reading a table, {\tt array} must have been declared at least {\tt nchars} bytes long to hold the returned string of bytes. \newpage % =================================================================== \subsection{Header Keyword I/O Routines} \nopagebreak The following routines read and write header keywords in the current HDU. \nopagebreak \begin{verbatim} ____________________________________________________________________ int fits_get_hdrspace(fitsfile *fptr, int *keysexist, int *morekeys, int *status) \end{verbatim} \nopagebreak Return the number of existing keywords (not counting the mandatory END keyword) and the amount of empty space currently available for more keywords. The {\tt morekeys} parameter may be set to NULL if it's value is not needed. \begin{verbatim} ___________________________________________________________________________ int fits_read_record(fitsfile *fptr, int keynum, char *record, int *status) int fits_read_card(fitsfile *fptr, char *keyname, char *record, int *status) int fits_read_key(fitsfile *fptr, int datatype, char *keyname, void *value, char *comment, int *status) int fits_find_nextkey(fitsfile *fptr, char **inclist, int ninc, char **exclist, int nexc, char *card, int *status) int fits_read_key_unit(fitsfile *fptr, char *keyname, char *unit, int *status) \end{verbatim} These routines all read a header record in the current HDU. The first routine reads keyword number {\tt keynum} (where the first keyword is at position 1). This routine is most commonly used when sequentially reading every record in the header from beginning to end. The 2nd and 3rd routines read the named keyword and return either the whole record, or the keyword value and comment string. In each case any non-significant trailing blank characters in the strings are truncated. Wild card characters (*, ?, and \#) may be used when specifying the name of the keyword to be read, in which case the first matching keyword is returned. The {\tt datatype} parameter specifies the C datatype of the returned keyword value and can have one of the following symbolic constant values: {\tt TSTRING, TLOGICAL} (== int), {\tt TBYTE}, {\tt TSHORT}, {\tt TUSHORT}, {\tt TINT}, {\tt TUINT}, {\tt TLONG}, {\tt TULONG}, {\tt TFLOAT}, {\tt TDOUBLE}, {\tt TCOMPLEX}, and {\tt TDBLCOMPLEX}. Data type conversion will be performed for numeric values if the intrinsic FITS keyword value does not have the same datatype. The {\tt comment} parameter may be set equal to NULL if the comment string is not needed. The 4th routine provides an easy way to find all the keywords in the header that match one of the name templates in {\tt inclist} and do not match any of the name templates in {\tt exclist}. {\tt ninc} and {\tt nexc} are the number of template strings in {\tt inclist} and {\tt exclist}, respectively. Wild cards (*, ?, and \#) may be used in the templates to match multiple keywords. Each time this routine is called it returns the next matching 80-byte keyword record. It returns status = {\tt KEY\_NO\_EXIST} if there are no more matches. The 5th routine returns the keyword value units string, if any. The units are recorded at the beginning of the keyword comment field enclosed in square brackets. \begin{verbatim} _______________________________________________________________ int fits_write_key(fitsfile *fptr, int datatype, char *keyname, void *value, char *comment, int *status) int fits_update_key(fitsfile *fptr, int datatype, char *keyname, void *value, char *comment, int *status) int fits_write_record(fitsfile *fptr, char *card, int *status) int fits_modify_comment(fitsfile *fptr, char *keyname, char *comment, int *status) int fits_write_key_unit(fitsfile *fptr, char *keyname, char *unit, int *status) \end{verbatim} Write or modify a keyword in the header of the current HDU. The first routine appends the new keyword to the end of the header, whereas the second routine will update the value and comment fields of the keyword if it already exists, otherwise it behaves like the first routine and appends the new keyword. Note that {\tt value} gives the address to the value and not the value itself. The {\tt datatype} parameter specifies the C datatype of the keyword value and may have any of the values listed in the description of the keyword reading routines, above. A NULL may be entered for the comment parameter, in which case the keyword comment field will be unmodified or left blank. The third routine is more primitive and simply writes the 80-character {\tt card} record to the header. It is the programmer's responsibility in this case to ensure that the record conforms to all the FITS format requirements for a header record. The fourth routine modifies the comment string in an existing keyword, and the last routine writes or updates the keyword units string for an existing keyword. (The units are recorded at the beginning of the keyword comment field enclosed in square brackets). \begin{verbatim} ___________________________________________________________________ int fits_write_comment(fitsfile *fptr, char *comment, int *status) int fits_write_history(fitsfile *fptr, char *history, int *status) int fits_write_date(fitsfile *fptr, int *status) \end{verbatim} Write a {\tt COMMENT, HISTORY}, or {\tt DATE} keyword to the current header. The {\tt COMMENT} keyword is typically used to write a comment about the file or the data. The {\tt HISTORY} keyword is typically used to provide information about the history of the processing procedures that have been applied to the data. The {\tt comment} or {\tt history} string will be continued over multiple keywords if it is more than 70 characters long. The {\tt DATE} keyword is used to record the date and time that the FITS file was created. Note that this file creation date is usually different from the date of the observation which obtained the data in the FITS file. The {\tt DATE} keyword value is a character string in 'yyyy-mm-ddThh:mm:ss' format. If a {\tt DATE} keyword already exists in the header, then this routine will update the value with the current system date. \begin{verbatim} ___________________________________________________________________ int fits_delete_record(fitsfile *fptr, int keynum, int *status) int fits_delete_key(fitsfile *fptr, char *keyname, int *status) \end{verbatim} Delete a keyword record. The first routine deletes a keyword at a specified position (the first keyword is at position 1, not 0), whereas the second routine deletes the named keyword. \begin{verbatim} _______________________________________________________________________ int fits_copy_header(fitsfile *infptr, fitsfile *outfptr, int *status) \end{verbatim} Copy all the header keywords from the current HDU associated with infptr to the current HDU associated with outfptr. If the current output HDU is not empty, then a new HDU will be appended to the output file. The output HDU will then have the identical structure as the input HDU, but will contain no data. \newpage % =================================================================== \subsection{Utility Routines} This section lists the most important CFITSIO general utility routines. \begin{verbatim} ___________________________________________________________________ int fits_write_chksum( fitsfile *fptr, int *status) int fits_verify_chksum(fitsfile *fptr, int *dataok, int *hduok, int *status) \end{verbatim} These routines compute or validate the checksums for the currenrt HDU. The {\tt DATASUM} keyword is used to store the numerical value of the 32-bit, 1's complement checksum for the data unit alone. The {\tt CHECKSUM} keyword is used to store the ASCII encoded COMPLEMENT of the checksum for the entire HDU. Storing the complement, rather than the actual checksum, forces the checksum for the whole HDU to equal zero. If the file has been modified since the checksums were computed, then the HDU checksum will usually not equal zero. The returned {\tt dataok} and {\tt hduok} parameters will have a value = 1 if the data or HDU is verified correctly, a value = 0 if the {\tt DATASUM} or {\tt CHECKSUM} keyword is not present, or value = -1 if the computed checksum is not correct. \begin{verbatim} ___________________________________________________________________ int fits_parse_value(char *card, char *value, char *comment, int *status) int fits_get_keytype(char *value, char *dtype, int *status) int fits_get_keyclass(char *card) int fits_parse_template(char *template, char *card, int *keytype, int *status) \end{verbatim} {\tt fits\_parse\_value} parses the input 80-chararacter header keyword record, returning the value (as a literal character string) and comment strings. If the keyword has no value (columns 9-10 not equal to '= '), then a null value string is returned and the comment string is set equal to column 9 - 80 of the input string. {\tt fits\_get\_keytype} parses the keyword value string to determine its datatype. {\tt dtype} returns with a value of 'C', 'L', 'I', 'F' or 'X', for character string, logical, integer, floating point, or complex, respectively. {\tt fits\_get\_keyclass} returns a classification code that indicates the classification type of the input keyword record (e.g., a required structural keyword, a TDIM keyword, a WCS keyword, a comment keyword, etc. See the CFITSIO Reference Guide for a list of the different classification codes. {\tt fits\_parse\_template} takes an input free format keyword template string and returns a formatted 80*char record that satisfies all the FITS requirements for a header keyword record. The template should generally contain 3 tokens: the keyword name, the keyword value, and the keyword comment string. The returned {\tt keytype} parameter indicates whether the keyword is a COMMENT keyword or not. See the CFITSIO Reference Guide for more details. \newpage % =================================================================== \section{CFITSIO File Names and Filters} \subsection{Creating New Files} When creating a new output file on magnetic disk with {\tt fits\_create\_file} the following features are supported. \begin{itemize} \item Overwriting, or 'Clobbering' an Existing File If the filename is preceded by an exclamation point (!) then if that file already exists it will be deleted prior to creating the new FITS file. Otherwise if there is an existing file with the same name, CFITSIO will not overwrite the existing file and will return an error status code. Note that the exclamation point is a special UNIX character, so if it is used on the command line rather than entered at a task prompt, it must be preceded by a backslash to force the UNIX shell to pass it verbatim to the application program. \item Compressed Output Files If the output disk file name ends with the suffix '.gz', then CFITSIO will compress the file using the gzip compression algorithm before writing it to disk. This can reduce the amount of disk space used by the file. Note that this feature requires that the uncompressed file be constructed in memory before it is compressed and written to disk, so it can fail if there is insufficient available memory. One can also specify that any images written to the output file should be compressed using the newly developed `tile-compression' algorithm by appending `[compress]' to the name of the disk file (as in {\tt myfile.fits[compress]}). Refer to the CFITSIO User's Reference Guide for more information about this new image compression format. \item Using a Template to Create a New FITS File The structure of any new FITS file that is to be created may be defined in an ASCII template file. If the name of the template file is appended to the name of the FITS file itself, enclosed in parenthesis (e.g., {\tt 'newfile.fits(template.txt)'}) then CFITSIO will create a FITS file with that structure before opening it for the application to use. The template file basically defines the dimensions and data type of the primary array and any IMAGE extensions, and the names and data types of the columns in any ASCII or binary table extensions. The template file can also be used to define any optional keywords that should be written in any of the HDU headers. The image pixel values and table entry values are all initialized to zero. The application program can then write actual data into the HDUs. See the CFITSIO Reference Guide for for a complete description of the template file syntax. \item Creating a Temporary Scratch File in Memory It is sometimes useful to create a temporary output file when testing an application program. If the name of the file to be created is specified as {\tt mem:} then CFITSIO will create the file in memory where it will persist only until the program closes the file. Use of this {\tt mem:} output file usually enables the program to run faster, and of course the output file does not use up any disk space. \end{itemize} \subsection{Opening Existing Files} When opening a file with {\tt fits\_open\_file}, CFITSIO can read a variety of different input file formats and is not restricted to only reading FITS format files from magnetic disk. The following types of input files are all supported: \begin{itemize} \item FITS files compressed with {\tt zip, gzip} or {\tt compress} If CFITSIO cannot find the specified file to open it will automatically look for a file with the same rootname but with a {\tt .gz, .zip}, or {\tt .Z} extension. If it finds such a compressed file, it will allocate a block of memory and uncompress the file into that memory space. The application program will then transparently open this virtual FITS file in memory. Compressed files can only be opened with 'readonly', not 'readwrite' file access. \item FITS files on the internet, using {\tt ftp} or {\tt http} URLs Simply provide the full URL as the name of the file that you want to open. For example,\linebreak {\tt ftp://legacy.gsfc.nasa.gov/software/fitsio/c/testprog.std}\linebreak will open the CFITSIO test FITS file that is located on the {\tt legacy} machine. These files can only be opened with 'readonly' file access. \item FITS files on {\tt stdin} or {\tt stdout} file streams If the name of the file to be opened is {\tt 'stdin'} or {\tt '-'} (a single dash character) then CFITSIO will read the file from the standard input stream. Similarly, if the output file name is {\tt 'stdout'} or {\tt '-'}, then the file will be written to the standard output stream. In addition, if the output filename is {\tt 'stdout.gz'} or {\tt '-.gz'} then it will be gzip compressed before being written to stdout. This mechanism can be used to pipe FITS files from one task to another without having to write an intermediary FITS file on magnetic disk. \item FITS files that exist only in memory, or shared memory. In some applications, such as real time data acquisition, you may want to have one process write a FITS file into a certain section of computer memory, and then be able to open that file in memory with another process. There is a specialized CFITSIO open routine called {\tt fits\_open\_memfile} that can be used for this purpose. See the ``CFITSIO User's Reference Guide'' for more details. \item IRAF format images (with {\tt .imh} file extensions) CFITSIO supports reading IRAF format images by converting them on the fly into FITS images in memory. The application program then reads this virtual FITS format image in memory. There is currently no support for writing IRAF format images, or for reading or writing IRAF tables. \item Image arrays in raw binary format If the input file is a raw binary data array, then CFITSIO will convert it on the fly into a virtual FITS image with the basic set of required header keywords before it is opened by the application program. In this case the data type and dimensions of the image must be specified in square brackets following the filename (e.g. {\tt rawfile.dat[ib512,512]}). The first character inside the brackets defines the datatype of the array: \begin{verbatim} b 8-bit unsigned byte i 16-bit signed integer u 16-bit unsigned integer j 32-bit signed integer r or f 32-bit floating point d 64-bit floating point \end{verbatim} An optional second character specifies the byte order of the array values: b or B indicates big endian (as in FITS files and the native format of SUN UNIX workstations and Mac PCs) and l or L indicates little endian (native format of DEC OSF workstations and IBM PCs). If this character is omitted then the array is assumed to have the native byte order of the local machine. These datatype characters are then followed by a series of one or more integer values separated by commas which define the size of each dimension of the raw array. Arrays with up to 5 dimensions are currently supported. Finally, a byte offset to the position of the first pixel in the data file may be specified by separating it with a ':' from the last dimension value. If omitted, it is assumed that the offset = 0. This parameter may be used to skip over any header information in the file that precedes the binary data. Further examples: \begin{verbatim} raw.dat[b10000] 1-dimensional 10000 pixel byte array raw.dat[rb400,400,12] 3-dimensional floating point big-endian array img.fits[ib512,512:2880] reads the 512 x 512 short integer array in a FITS file, skipping over the 2880 byte header \end{verbatim} \end{itemize} \newpage \subsection{Image Filtering} \subsubsection{Extracting a subsection of an image} When specifying the name of an image to be opened, you can select a rectangular subsection of the image to be extracted and opened by the application program. The application program then opens a virtual image that only contains the pixels within the specified subsection. To do this, specify the the range of pixels (start:end) along each axis to be extracted from the original image enclosed in square brackets. You can also specify an optional pixel increment (start:end:step) for each axis of the input image. A pixel step = 1 will be assumed if it is not specified. If the starting pixel is larger then the end pixel, then the image will be flipped (producing a mirror image) along that dimension. An asterisk, '*', may be used to specify the entire range of an axis, and '-*' will flip the entire axis. In the following examples, assume that {\tt myfile.fits} contains a 512 x 512 pixel 2D image. \begin{verbatim} myfile.fits[201:210, 251:260] - opens a 10 x 10 pixel subimage. myfile.fits[*, 512:257] - opens a 512 x 256 image consisting of all the columns in the input image, but only rows 257 through 512. The image will be flipped along the Y axis since the starting row is greater than the ending row. myfile.fits[*:2, 512:257:2] - creates a 256 x 128 pixel image. Similar to the previous example, but only every other row and column is read from the input image. myfile.fits[-*, *] - creates an image containing all the rows and columns in the input image, but flips it along the X axis. \end{verbatim} If the array to be opened is in an Image extension, and not in the primary array of the file, then you need to specify the extension name or number in square brackets before giving the subsection range, as in {\tt myfile.fits[1][-*, *]} to read the image in the first extension in the file. \subsubsection{Create an Image by Binning Table Columns} You can also create and open a virtual image by binning the values in a pair of columns of a FITS table (in other words, create a 2-D histogram of the values in the 2 columns). This technique is often used in X-ray astronomy where each detected X-ray photon during an observation is recorded in a FITS table. There are typically 2 columns in the table called {\tt X} and {\tt Y} which record the pixel location of that event in a virtual 2D image. To create an image from this table, one just scans the X and Y columns and counts up how many photons were recorded in each pixel of the image. When table binning is specified, CFITSIO creates a temporary FITS primary array in memory by computing the histogram of the values in the specified columns. After the histogram is computed the original FITS file containing the table is closed and the temporary FITS primary array is opened and passed to the application program. Thus, the application program never sees the original FITS table and only sees the image in the new temporary file (which has no extensions). The table binning specifier is enclosed in square brackets following the root filename and table extension name or number and begins with the keyword 'bin', as in: \newline {\tt 'myfile.fits[events][bin (X,Y)]'}. In this case, the X and Y columns in the 'events' table extension are binned up to create the image. The size of the image is usually determined by the {\tt TLMINn} and {\tt TLMAXn} header keywords which give the minimum and maximum allowed pixel values in the columns. For instance if {\tt TLMINn = 1} and {\tt TLMAXn = 4096} for both columns, this would generate a 4096 x 4096 pixel image by default. This is rather large, so you can also specify a pixel binning factor to reduce the image size. For example specifying , {\tt '[bin (X,Y) = 16]'} will use a binning factor of 16, which will produce a 256 x 256 pixel image in the previous example. If the TLMIN and TLMAX keywords don't exist, or you want to override their values, you can specify the image range and binning factor directly, as in {\tt '[bin X = 1:4096:16, Y=1:4096:16]'}. You can also specify the datatype of the created image by appending a b, i, j, r, or d (for 8-bit byte, 16-bit integers, 32-bit integer, 32-bit floating points, or 64-bit double precision floating point, respectively) to the 'bin' keyword (e.g. {\tt '[binr (X,Y)]'} creates a floating point image). If the datatype is not specified then a 32-bit integer image will be created by default. If the column name is not specified, then CFITSIO will first try to use the 'preferred column' as specified by the CPREF keyword if it exists (e.g., 'CPREF = 'DETX,DETY'), otherwise column names 'X', 'Y' will be assumed for the 2 axes. Note that this binning specifier is not restricted to only 2D images and can be used to create 1D, 3D, or 4D images as well. It is also possible to specify a weighting factor that is applied during the binning. Please refer to the ``CFITSIO User's Reference Guide'' for more details on these advanced features. \newpage \subsection{Table Filtering} \subsubsection{Column and Keyword Filtering} The column or keyword filtering specifier is used to modify the column structure and/or the header keywords in the HDU that was selected with the previous HDU location specifier. It can be used to perform the following types of operations. \begin{itemize} \item Append a new column to a table by giving the column name, optionally followed by the datatype in parentheses, followed by an equals sign and the arithmetic expression to be used to compute the value. The datatype is specified using the same syntax that is allowed for the value of the FITS TFORMn keyword (e.g., 'I', 'J', 'E', 'D', etc. for binary tables, and 'I8', F12.3', 'E20.12', etc. for ASCII tables). If the datatype is not specified then a default datatype will be chosen depending on the expression. \item Create a new header keyword by giving the keyword name, preceded by a pound sign '\#', followed by an equals sign and an arithmetic expression for the value of the keyword. The expression may be a function of other header keyword values. The comment string for the keyword may be specified in parentheses immediately following the keyword name. \item Overwrite the values in an existing column or keyword by giving the name followed by an equals sign and an arithmetic expression. \item Select a set of columns to be included in the filtered file by listing the column names separated with semi-colons. Wild card characters may be used in the column names to match multiple columns. Any other columns in the input table will not appear in the filtered file. \item Delete a column or keyword by listing the name preceded by a minus sign or an exclamation mark (!) \item Rename an existing column or keyword with the syntax 'NewName == OldName'. \end{itemize} The column filtering specifier is enclosed in square brackets and begins with the string 'col'. Multiple operations can be performed by separating them with semi-colons. For complex or commonly used operations, you can write the column filter to a text file, and then use it by giving the name of the text file, preceded by a '@' character. Some examples: \begin{verbatim} [col PI=PHA * 1.1 + 0.2] - creates new PI column from PHA values [col rate = counts/exposure] - creates or overwrites the rate column by dividing the counts column by the EXPOSURE keyword value. [col TIME; X; Y] - only the listed columns will appear in the filtered file [col Time;*raw] - include the Time column and any other columns whose name ends with 'raw'. [col -TIME; Good == STATUS] - deletes the TIME column and renames the STATUS column to GOOD [col @colfilt.txt] - uses the filtering expression in the colfilt.txt text file \end{verbatim} The original file is not changed by this filtering operation, and instead the modifications are made on a temporary copy of the input FITS file (usually in memory), which includes a copy of all the other HDUs in the input file. The original input file is closed and the application program opens the filtered copy of the file. \subsubsection{Row Filtering} The row filter is used to select a subset of the rows from a table based on a boolean expression. A temporary new FITS file is created on the fly (usually in memory) which contains only those rows for which the row filter expression evaluates to true (i.e., not equal to zero). The primary array and any other extensions in the input file are also copied to the temporary file. The original FITS file is closed and the new temporary file is then opened by the application program. The row filter expression is enclosed in square brackets following the file name and extension name. For example, {\tt 'file.fits[events][GRADE==50]'} selects only those rows in the EVENTS table where the GRADE column value is equal to 50). The row filtering expression can be an arbitrarily complex series of operations performed on constants, keyword values, and column data taken from the specified FITS TABLE extension. The expression also can be written into a text file and then used by giving the filename preceded by a '@' character, as in {\tt '[@rowfilt.txt]'}. Keyword and column data are referenced by name. Any string of characters not surrounded by quotes (ie, a constant string) or followed by an open parentheses (ie, a function name) will be initially interpreted as a column name and its contents for the current row inserted into the expression. If no such column exists, a keyword of that name will be searched for and its value used, if found. To force the name to be interpreted as a keyword (in case there is both a column and keyword with the same name), precede the keyword name with a single pound sign, '\#', as in {\tt \#NAXIS2}. Due to the generalities of FITS column and keyword names, if the column or keyword name contains a space or a character which might appear as an arithmetic term then inclose the name in '\$' characters as in {\tt \$MAX PHA\$} or {\tt \#\$MAX-PHA\$}. The names are case insensitive. To access a table entry in a row other than the current one, follow the column's name with a row offset within curly braces. For example, {\tt'PHA\{-3\}'} will evaluate to the value of column PHA, 3 rows above the row currently being processed. One cannot specify an absolute row number, only a relative offset. Rows that fall outside the table will be treated as undefined, or NULLs. Boolean operators can be used in the expression in either their Fortran or C forms. The following boolean operators are available: \begin{verbatim} "equal" .eq. .EQ. == "not equal" .ne. .NE. != "less than" .lt. .LT. < "less than/equal" .le. .LE. <= =< "greater than" .gt. .GT. > "greater than/equal" .ge. .GE. >= => "or" .or. .OR. || "and" .and. .AND. && "negation" .not. .NOT. ! "approx. equal(1e-7)" ~ \end{verbatim} Note that the exclamation point, '!', is a special UNIX character, so if it is used on the command line rather than entered at a task prompt, it must be preceded by a backslash to force the UNIX shell to ignore it. The expression may also include arithmetic operators and functions. Trigonometric functions use radians, not degrees. The following arithmetic operators and functions can be used in the expression (function names are case insensitive): \begin{verbatim} "addition" + "subtraction" - "multiplication" * "division" / "negation" - "exponentiation" ** ^ "absolute value" abs(x) "cosine" cos(x) "sine" sin(x) "tangent" tan(x) "arc cosine" arccos(x) "arc sine" arcsin(x) "arc tangent" arctan(x) "arc tangent" arctan2(x,y) "exponential" exp(x) "square root" sqrt(x) "natural log" log(x) "common log" log10(x) "modulus" i % j "random # [0.0,1.0)" random() "minimum" min(x,y) "maximum" max(x,y) "if-then-else" b?x:y \end{verbatim} The following type casting operators are available, where the inclosing parentheses are required and taken from the C language usage. Also, the integer to real casts values to double precision: \begin{verbatim} "real to integer" (int) x (INT) x "integer to real" (float) i (FLOAT) i \end{verbatim} Several constants are built in for use in numerical expressions: \begin{verbatim} #pi 3.1415... #e 2.7182... #deg #pi/180 #row current row number #null undefined value #snull undefined string \end{verbatim} A string constant must be enclosed in quotes as in 'Crab'. The "null" constants are useful for conditionally setting table values to a NULL, or undefined, value (For example, {\tt "col1==-99 ? \#NULL : col1"}). There is also a function for testing if two values are close to each other, i.e., if they are "near" each other to within a user specified tolerance. The arguments, {\tt value\_1} and {\tt value\_2} can be integer or real and represent the two values who's proximity is being tested to be within the specified tolerance, also an integer or real: \begin{verbatim} near(value_1, value_2, tolerance) \end{verbatim} When a NULL, or undefined, value is encountered in the FITS table, the expression will evaluate to NULL unless the undefined value is not actually required for evaluation, e.g. "TRUE .or. NULL" evaluates to TRUE. The following two functions allow some NULL detection and handling: \begin{verbatim} ISNULL(x) DEFNULL(x,y) \end{verbatim} The former returns a boolean value of TRUE if the argument x is NULL. The later "defines" a value to be substituted for NULL values; it returns the value of x if x is not NULL, otherwise it returns the value of y. Bit masks can be used to select out rows from bit columns ({\tt TFORMn = \#X}) in FITS files. To represent the mask, binary, octal, and hex formats are allowed: \begin{verbatim} binary: b0110xx1010000101xxxx0001 octal: o720x1 -> (b111010000xxx001) hex: h0FxD -> (b00001111xxxx1101) \end{verbatim} In all the representations, an x or X is allowed in the mask as a wild card. Note that the x represents a different number of wild card bits in each representation. All representations are case insensitive. To construct the boolean expression using the mask as the boolean equal operator described above on a bit table column. For example, if you had a 7 bit column named flags in a FITS table and wanted all rows having the bit pattern 0010011, the selection expression would be: \begin{verbatim} flags == b0010011 or flags .eq. b10011 \end{verbatim} It is also possible to test if a range of bits is less than, less than equal, greater than and greater than equal to a particular boolean value: \begin{verbatim} flags <= bxxx010xx flags .gt. bxxx100xx flags .le. b1xxxxxxx \end{verbatim} Notice the use of the x bit value to limit the range of bits being compared. It is not necessary to specify the leading (most significant) zero (0) bits in the mask, as shown in the second expression above. Bit wise AND, OR and NOT operations are also possible on two or more bit fields using the '\&'(AND), '$|$'(OR), and the '!'(NOT) operators. All of these operators result in a bit field which can then be used with the equal operator. For example: \begin{verbatim} (!flags) == b1101100 (flags & b1000001) == bx000001 \end{verbatim} Bit fields can be appended as well using the '+' operator. Strings can be concatenated this way, too. \subsubsection{Good Time Interval Filtering} A common filtering method involves selecting rows which have a time value which lies within what is called a Good Time Interval or GTI. The time intervals are defined in a separate FITS table extension which contains 2 columns giving the start and stop time of each good interval. The filtering operation accepts only those rows of the input table which have an associated time which falls within one of the time intervals defined in the GTI extension. A high level function, gtifilter(a,b,c,d), is available which evaluates each row of the input table and returns TRUE or FALSE depending whether the row is inside or outside the good time interval. The syntax is \begin{verbatim} gtifilter( [ "gtifile" [, expr [, "STARTCOL", "STOPCOL" ] ] ] ) \end{verbatim} where each "[]" demarks optional parameters. Note that the quotes around the gtifile and START/STOP column are required. Either single or double quote characters may be used. The gtifile, if specified, can be blank ("") which will mean to use the first extension with the name "*GTI*" in the current file, a plain extension specifier (eg, "+2", "[2]", or "[STDGTI]") which will be used to select an extension in the current file, or a regular filename with or without an extension specifier which in the latter case will mean to use the first extension with an extension name "*GTI*". Expr can be any arithmetic expression, including simply the time column name. A vector time expression will produce a vector boolean result. STARTCOL and STOPCOL are the names of the START/STOP columns in the GTI extension. If one of them is specified, they both must be. In its simplest form, no parameters need to be provided -- default values will be used. The expression {\tt "gtifilter()"} is equivalent to \begin{verbatim} gtifilter( "", TIME, "*START*", "*STOP*" ) \end{verbatim} This will search the current file for a GTI extension, filter the TIME column in the current table, using START/STOP times taken from columns in the GTI extension with names containing the strings "START" and "STOP". The wildcards ('*') allow slight variations in naming conventions such as "TSTART" or "STARTTIME". The same default values apply for unspecified parameters when the first one or two parameters are specified. The function automatically searches for TIMEZERO/I/F keywords in the current and GTI extensions, applying a relative time offset, if necessary. \subsubsection{Spatial Region Filtering} Another common filtering method selects rows based on whether the spatial position associated with each row is located within a given 2-dimensional region. The syntax for this high-level filter is \begin{verbatim} regfilter( "regfilename" [ , Xexpr, Yexpr [ , "wcs cols" ] ] ) \end{verbatim} where each "[ ]" demarks optional parameters. The region file name is required and must be enclosed in quotes. The remaining parameters are optional. The region file is an ASCII text file which contains a list of one or more geometric shapes (circle, ellipse, box, etc.) which defines a region on the celestial sphere or an area within a particular 2D image. The region file is typically generated using an image display program such as fv/POW (distribute by the HEASARC), or ds9 (distributed by the Smithsonian Astrophysical Observatory). Users should refer to the documentation provided with these programs for more details on the syntax used in the region files. In its simpliest form, (e.g., {\tt regfilter("region.reg")} ) the coordinates in the default 'X' and 'Y' columns will be used to determine if each row is inside or outside the area specified in the region file. Alternate position column names, or expressions, may be entered if needed, as in \begin{verbatim} regfilter("region.reg", XPOS, YPOS) \end{verbatim} Region filtering can be applied most unambiguously if the positions in the region file and in the table to be filtered are both give in terms of absolute celestial coordinate units. In this case the locations and sizes of the geometric shapes in the region file are specified in angular units on the sky (e.g., positions given in R.A. and Dec. and sizes in arcseconds or arcminutes). Similarly, each row of the filtered table will have a celestial coordinate associated with it. This association is usually implemented using a set of so-called 'World Coordinate System' (or WCS) FITS keywords that define the coordinate transformation that must be applied to the values in the 'X' and 'Y' columns to calculate the coordinate. Alternatively, one can perform spatial filtering using unitless 'pixel' coordinates for the regions and row positions. In this case the user must be careful to ensure that the positions in the 2 files are self-consistent. A typical problem is that the region file may be generated using a binned image, but the unbinned coordinates are given in the event table. The ROSAT events files, for example, have X and Y pixel coordinates that range from 1 - 15360. These coordinates are typically binned by a factor of 32 to produce a 480x480 pixel image. If one then uses a region file generated from this image (in image pixel units) to filter the ROSAT events file, then the X and Y column values must be converted to corresponding pixel units as in: \begin{verbatim} regfilter("rosat.reg", X/32.+.5, Y/32.+.5) \end{verbatim} Note that this binning conversion is not necessary if the region file is specified using celestial coordinate units instead of pixel units because CFITSIO is then able to directly compare the celestial coordinate of each row in the table with the celestial coordinates in the region file without having to know anything about how the image may have been binned. The last "wcs cols" parameter should rarely be needed. If supplied, this string contains the names of the 2 columns (space or comma separated) which have the associated WCS keywords. If not supplied, the filter will scan the X and Y expressions for column names. If only one is found in each expression, those columns will be used, otherwise an error will be returned. These region shapes are supported (names are case insensitive): \begin{verbatim} Point ( X1, Y1 ) <- One pixel square region Line ( X1, Y1, X2, Y2 ) <- One pixel wide region Polygon ( X1, Y1, X2, Y2, ... ) <- Rest are interiors with Rectangle ( X1, Y1, X2, Y2, A ) | boundaries considered Box ( Xc, Yc, Wdth, Hght, A ) V within the region Diamond ( Xc, Yc, Wdth, Hght, A ) Circle ( Xc, Yc, R ) Annulus ( Xc, Yc, Rin, Rout ) Ellipse ( Xc, Yc, Rx, Ry, A ) Elliptannulus ( Xc, Yc, Rinx, Riny, Routx, Routy, Ain, Aout ) Sector ( Xc, Yc, Amin, Amax ) \end{verbatim} where (Xc,Yc) is the coordinate of the shape's center; (X\#,Y\#) are the coordinates of the shape's edges; Rxxx are the shapes' various Radii or semimajor/minor axes; and Axxx are the angles of rotation (or bounding angles for Sector) in degrees. For rotated shapes, the rotation angle can be left off, indicating no rotation. Common alternate names for the regions can also be used: rotbox = box; rotrectangle = rectangle; (rot)rhombus = (rot)diamond; and pie = sector. When a shape's name is preceded by a minus sign, '-', the defined region is instead the area *outside* its boundary (ie, the region is inverted). All the shapes within a single region file are OR'd together to create the region, and the order is significant. The overall way of looking at region files is that if the first region is an excluded region then a dummy included region of the whole detector is inserted in the front. Then each region specification as it is processed overrides any selections inside of that region specified by previous regions. Another way of thinking about this is that if a previous excluded region is completely inside of a subsequent included region the excluded region is ignored. The positional coordinates may be given either in pixel units, decimal degrees or hh:mm:ss.s, dd:mm:ss.s units. The shape sizes may be given in pixels, degrees, arcminutes, or arcseconds. Look at examples of region file produced by fv/POW or ds9 for further details of the region file format. \subsubsection{Example Row Filters} \begin{verbatim} [double && mag <= 5.0] - Extract all double stars brighter than fifth magnitude [#row >= 125 && #row <= 175] - Extract row numbers 125 through 175 [abs(sin(theta * #deg)) < 0.5] - Extract all rows having the absolute value of the sine of theta less than a half where the angles are tabulated in degrees [@rowFilter.txt] - Extract rows using the expression contained within the text file rowFilter.txt [gtifilter()] - Search the current file for a GTI extension, filter the TIME column in the current table, using START/STOP times taken from columns in the GTI extension [regfilter("pow.reg")] - Extract rows which have a coordinate (as given in the X and Y columns) within the spatial region specified in the pow.reg region file. \end{verbatim} \newpage \subsection{Combined Filtering Examples} The previous sections described all the individual types of filters that may be applied to the input file. In this section we show examples which combine several different filters at once. These examples all use the {\tt fitscopy} program that is distributed with the CFITSIO code. It simply copies the input file to the output file. \begin{verbatim} fitscopy rosat.fit out.fit \end{verbatim} This trivial example simply makes an identical copy of the input rosat.fit file without any filtering. \begin{verbatim} fitscopy 'rosat.fit[events][col Time;X;Y][#row < 1000]' out.fit \end{verbatim} The output file contains only the Time, X, and Y columns, and only the first 999 rows from the 'EVENTS' table extension of the input file. All the other HDUs in the input file are copied to the output file without any modification. \begin{verbatim} fitscopy 'rosat.fit[events][PI < 50][bin (Xdet,Ydet) = 16]' image.fit \end{verbatim} This creates an output image by binning the Xdet and Ydet columns of the events table with a pixel binning factor of 16. Only the rows which have a PI energy less than 50 are used to construct this image. The output image file contains a primary array image without any extensions. \begin{verbatim} fitscopy 'rosat.fit[events][gtifilter() && regfilter("pow.reg")]' out.fit \end{verbatim} The filtering expression in this example uses the {\tt gtifilter} function to test whether the TIME column value in each row is within one of the Good Time Intervals defined in the GTI extension in the same input file, and also uses the {\tt regfilter} function to test if the position associated with each row (derived by default from the values in the X and Y columns of the events table) is located within the area defined in the {\tt pow.reg} text region file (which was previously created with the {\tt fv/POW} image display program). Only the rows which satisfy both tests are copied to the output table. \begin{verbatim} fitscopy 'r.fit[evt][PI<50]' stdout | fitscopy stdin[evt][col X,Y] out.fit \end{verbatim} In this somewhat convoluted example, fitscopy is used to first select the rows from the evt extension which have PI less than 50 and write the resulting table out to the stdout stream. This is piped to a 2nd instance of fitscopy (with the Unix `$|$' pipe command) which reads that filtered FITS file from the stdin stream and copies only the X and Y columns from the evt table to the output file. \begin{verbatim} fitscopy 'r.fit[evt][col RAD=sqrt((X-#XCEN)**2+(Y-#YCEN)**2)][rad<100]' out.fit \end{verbatim} This example first creates a new column called RAD which gives the distance between the X,Y coordinate of each event and the coordinate defined by the XCEN and YCEN keywords in the header. Then, only those rows which have a distance less than 100 are copied to the output table. In other words, only the events which are located within 100 pixel units from the (XCEN, YCEN) coordinate are copied to the output table. \begin{verbatim} fitscopy 'ftp://heasarc.gsfc.nasa.gov/rosat.fit[events][bin (X,Y)=16]' img.fit \end{verbatim} This example bins the X and Y columns of the hypothetical ROSAT file at the HEASARC ftp site to create the output image. \begin{verbatim} fitscopy 'raw.fit[i512,512][101:110,51:60]' image.fit \end{verbatim} This example converts the 512 x 512 pixel raw binary 16-bit integer image to a FITS file and copies a 10 x 10 pixel subimage from it to the output FITS image. \newpage \section{CFITSIO Error Status Codes} The following table lists all the error status codes used by CFITSIO. Programmers are encouraged to use the symbolic mnemonics (defined in the file fitsio.h) rather than the actual integer status values to improve the readability of their code. \begin{verbatim} Symbolic Const Value Meaning -------------- ----- ----------------------------------------- 0 OK, no error SAME_FILE 101 input and output files are the same TOO_MANY_FILES 103 tried to open too many FITS files at once FILE_NOT_OPENED 104 could not open the named file FILE_NOT_CREATED 105 could not create the named file WRITE_ERROR 106 error writing to FITS file END_OF_FILE 107 tried to move past end of file READ_ERROR 108 error reading from FITS file FILE_NOT_CLOSED 110 could not close the file ARRAY_TOO_BIG 111 array dimensions exceed internal limit READONLY_FILE 112 Cannot write to readonly file MEMORY_ALLOCATION 113 Could not allocate memory BAD_FILEPTR 114 invalid fitsfile pointer NULL_INPUT_PTR 115 NULL input pointer to routine SEEK_ERROR 116 error seeking position in file BAD_URL_PREFIX 121 invalid URL prefix on file name TOO_MANY_DRIVERS 122 tried to register too many IO drivers DRIVER_INIT_FAILED 123 driver initialization failed NO_MATCHING_DRIVER 124 matching driver is not registered URL_PARSE_ERROR 125 failed to parse input file URL SHARED_BADARG 151 bad argument in shared memory driver SHARED_NULPTR 152 null pointer passed as an argument SHARED_TABFULL 153 no more free shared memory handles SHARED_NOTINIT 154 shared memory driver is not initialized SHARED_IPCERR 155 IPC error returned by a system call SHARED_NOMEM 156 no memory in shared memory driver SHARED_AGAIN 157 resource deadlock would occur SHARED_NOFILE 158 attempt to open/create lock file failed SHARED_NORESIZE 159 shared memory block cannot be resized at the moment HEADER_NOT_EMPTY 201 header already contains keywords KEY_NO_EXIST 202 keyword not found in header KEY_OUT_BOUNDS 203 keyword record number is out of bounds VALUE_UNDEFINED 204 keyword value field is blank NO_QUOTE 205 string is missing the closing quote BAD_KEYCHAR 207 illegal character in keyword name or card BAD_ORDER 208 required keywords out of order NOT_POS_INT 209 keyword value is not a positive integer NO_END 210 couldn't find END keyword BAD_BITPIX 211 illegal BITPIX keyword value BAD_NAXIS 212 illegal NAXIS keyword value BAD_NAXES 213 illegal NAXISn keyword value BAD_PCOUNT 214 illegal PCOUNT keyword value BAD_GCOUNT 215 illegal GCOUNT keyword value BAD_TFIELDS 216 illegal TFIELDS keyword value NEG_WIDTH 217 negative table row size NEG_ROWS 218 negative number of rows in table COL_NOT_FOUND 219 column with this name not found in table BAD_SIMPLE 220 illegal value of SIMPLE keyword NO_SIMPLE 221 Primary array doesn't start with SIMPLE NO_BITPIX 222 Second keyword not BITPIX NO_NAXIS 223 Third keyword not NAXIS NO_NAXES 224 Couldn't find all the NAXISn keywords NO_XTENSION 225 HDU doesn't start with XTENSION keyword NOT_ATABLE 226 the CHDU is not an ASCII table extension NOT_BTABLE 227 the CHDU is not a binary table extension NO_PCOUNT 228 couldn't find PCOUNT keyword NO_GCOUNT 229 couldn't find GCOUNT keyword NO_TFIELDS 230 couldn't find TFIELDS keyword NO_TBCOL 231 couldn't find TBCOLn keyword NO_TFORM 232 couldn't find TFORMn keyword NOT_IMAGE 233 the CHDU is not an IMAGE extension BAD_TBCOL 234 TBCOLn keyword value < 0 or > rowlength NOT_TABLE 235 the CHDU is not a table COL_TOO_WIDE 236 column is too wide to fit in table COL_NOT_UNIQUE 237 more than 1 column name matches template BAD_ROW_WIDTH 241 sum of column widths not = NAXIS1 UNKNOWN_EXT 251 unrecognizable FITS extension type UNKNOWN_REC 252 unknown record; 1st keyword not SIMPLE or XTENSION END_JUNK 253 END keyword is not blank BAD_HEADER_FILL 254 Header fill area contains non-blank chars BAD_DATA_FILL 255 Illegal data fill bytes (not zero or blank) BAD_TFORM 261 illegal TFORM format code BAD_TFORM_DTYPE 262 unrecognizable TFORM datatype code BAD_TDIM 263 illegal TDIMn keyword value BAD_HEAP_PTR 264 invalid BINTABLE heap pointer is out of range BAD_HDU_NUM 301 HDU number < 1 or > MAXHDU BAD_COL_NUM 302 column number < 1 or > tfields NEG_FILE_POS 304 tried to move to negative byte location in file NEG_BYTES 306 tried to read or write negative number of bytes BAD_ROW_NUM 307 illegal starting row number in table BAD_ELEM_NUM 308 illegal starting element number in vector NOT_ASCII_COL 309 this is not an ASCII string column NOT_LOGICAL_COL 310 this is not a logical datatype column BAD_ATABLE_FORMAT 311 ASCII table column has wrong format BAD_BTABLE_FORMAT 312 Binary table column has wrong format NO_NULL 314 null value has not been defined NOT_VARI_LEN 317 this is not a variable length column BAD_DIMEN 320 illegal number of dimensions in array BAD_PIX_NUM 321 first pixel number greater than last pixel ZERO_SCALE 322 illegal BSCALE or TSCALn keyword = 0 NEG_AXIS 323 illegal axis length < 1 NOT_GROUP_TABLE 340 Grouping function error HDU_ALREADY_MEMBER 341 MEMBER_NOT_FOUND 342 GROUP_NOT_FOUND 343 BAD_GROUP_ID 344 TOO_MANY_HDUS_TRACKED 345 HDU_ALREADY_TRACKED 346 BAD_OPTION 347 IDENTICAL_POINTERS 348 BAD_GROUP_ATTACH 349 BAD_GROUP_DETACH 350 NGP_NO_MEMORY 360 malloc failed NGP_READ_ERR 361 read error from file NGP_NUL_PTR 362 null pointer passed as an argument. Passing null pointer as a name of template file raises this error NGP_EMPTY_CURLINE 363 line read seems to be empty (used internally) NGP_UNREAD_QUEUE_FULL 364 cannot unread more then 1 line (or single line twice) NGP_INC_NESTING 365 too deep include file nesting (infinite loop, template includes itself ?) NGP_ERR_FOPEN 366 fopen() failed, cannot open template file NGP_EOF 367 end of file encountered and not expected NGP_BAD_ARG 368 bad arguments passed. Usually means internal parser error. Should not happen NGP_TOKEN_NOT_EXPECT 369 token not expected here BAD_I2C 401 bad int to formatted string conversion BAD_F2C 402 bad float to formatted string conversion BAD_INTKEY 403 can't interpret keyword value as integer BAD_LOGICALKEY 404 can't interpret keyword value as logical BAD_FLOATKEY 405 can't interpret keyword value as float BAD_DOUBLEKEY 406 can't interpret keyword value as double BAD_C2I 407 bad formatted string to int conversion BAD_C2F 408 bad formatted string to float conversion BAD_C2D 409 bad formatted string to double conversion BAD_DATATYPE 410 illegal datatype code value BAD_DECIM 411 bad number of decimal places specified NUM_OVERFLOW 412 overflow during datatype conversion DATA_COMPRESSION_ERR 413 error compressing image DATA_DECOMPRESSION_ERR 414 error uncompressing image BAD_DATE 420 error in date or time conversion PARSE_SYNTAX_ERR 431 syntax error in parser expression PARSE_BAD_TYPE 432 expression did not evaluate to desired type PARSE_LRG_VECTOR 433 vector result too large to return in array PARSE_NO_OUTPUT 434 data parser failed not sent an out column PARSE_BAD_COL 435 bad data encounter while parsing column PARSE_BAD_OUTPUT 436 Output file not of proper type ANGLE_TOO_BIG 501 celestial angle too large for projection BAD_WCS_VAL 502 bad celestial coordinate or pixel value WCS_ERROR 503 error in celestial coordinate calculation BAD_WCS_PROJ 504 unsupported type of celestial projection NO_WCS_KEY 505 celestial coordinate keywords not found APPROX_WCS_KEY 506 approximate wcs keyword values were returned \end{verbatim} \end{document} cfitsio/docs/quick.toc0000644000225700000360000000340313246025103014553 0ustar cagordonlhea\contentsline {section}{\numberline {1}Introduction}{2} \contentsline {section}{\numberline {2}Installing and Using CFITSIO}{3} \contentsline {section}{\numberline {3}Example Programs}{4} \contentsline {section}{\numberline {4}CFITSIO Routines}{6} \contentsline {subsection}{\numberline {4.1}Error Reporting}{6} \contentsline {subsection}{\numberline {4.2}File Open/Close Routines}{6} \contentsline {subsection}{\numberline {4.3}HDU-level Routines}{7} \contentsline {subsection}{\numberline {4.4}Image I/O Routines}{9} \contentsline {subsection}{\numberline {4.5}Table I/O Routines}{12} \contentsline {subsection}{\numberline {4.6}Header Keyword I/O Routines}{19} \contentsline {subsection}{\numberline {4.7}Utility Routines}{22} \contentsline {section}{\numberline {5}CFITSIO File Names and Filters}{23} \contentsline {subsection}{\numberline {5.1}Creating New Files}{23} \contentsline {subsection}{\numberline {5.2}Opening Existing Files}{24} \contentsline {subsection}{\numberline {5.3}Image Filtering}{26} \contentsline {subsubsection}{\numberline {5.3.1}Extracting a subsection of an image}{26} \contentsline {subsubsection}{\numberline {5.3.2}Create an Image by Binning Table Columns}{26} \contentsline {subsection}{\numberline {5.4}Table Filtering}{28} \contentsline {subsubsection}{\numberline {5.4.1}Column and Keyword Filtering}{28} \contentsline {subsubsection}{\numberline {5.4.2}Row Filtering}{29} \contentsline {subsubsection}{\numberline {5.4.3}Good Time Interval Filtering}{32} \contentsline {subsubsection}{\numberline {5.4.4}Spatial Region Filtering}{32} \contentsline {subsubsection}{\numberline {5.4.5}Example Row Filters}{34} \contentsline {subsection}{\numberline {5.5}Combined Filtering Examples}{36} \contentsline {section}{\numberline {6}CFITSIO Error Status Codes}{38} cfitsio/drvrfile.c0000644000225700000360000006744613246025103014002 0ustar cagordonlhea/* This file, drvrfile.c contains driver routines for disk files. */ /* The FITSIO software was written by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ #include #include #include "fitsio2.h" #include "group.h" /* needed for fits_get_cwd in file_create */ #if defined(unix) || defined(__unix__) || defined(__unix) #include /* needed in file_openfile */ #ifdef REPLACE_LINKS #include #include #endif #endif #ifdef HAVE_FTRUNCATE #if defined(unix) || defined(__unix__) || defined(__unix) || defined(HAVE_UNISTD_H) #include /* needed for getcwd prototype on unix machines */ #endif #endif #define IO_SEEK 0 /* last file I/O operation was a seek */ #define IO_READ 1 /* last file I/O operation was a read */ #define IO_WRITE 2 /* last file I/O operation was a write */ static char file_outfile[FLEN_FILENAME]; typedef struct /* structure containing disk file structure */ { FILE *fileptr; LONGLONG currentpos; int last_io_op; } diskdriver; static diskdriver handleTable[NMAXFILES]; /* allocate diskfile handle tables */ /*--------------------------------------------------------------------------*/ int file_init(void) { int ii; for (ii = 0; ii < NMAXFILES; ii++) /* initialize all empty slots in table */ { handleTable[ii].fileptr = 0; } return(0); } /*--------------------------------------------------------------------------*/ int file_setoptions(int options) { /* do something with the options argument, to stop compiler warning */ options = 0; return(options); } /*--------------------------------------------------------------------------*/ int file_getoptions(int *options) { *options = 0; return(0); } /*--------------------------------------------------------------------------*/ int file_getversion(int *version) { *version = 10; return(0); } /*--------------------------------------------------------------------------*/ int file_shutdown(void) { return(0); } /*--------------------------------------------------------------------------*/ int file_open(char *filename, int rwmode, int *handle) { FILE *diskfile; int copyhandle, ii, status; char recbuf[2880]; size_t nread; /* if an output filename has been specified as part of the input file, as in "inputfile.fits(outputfile.fit)" then we have to create the output file, copy the input to it, then reopen the the new copy. */ if (*file_outfile) { /* open the original file, with readonly access */ status = file_openfile(filename, READONLY, &diskfile); if (status) { file_outfile[0] = '\0'; return(status); } /* create the output file */ status = file_create(file_outfile,handle); if (status) { ffpmsg("Unable to create output file for copy of input file:"); ffpmsg(file_outfile); file_outfile[0] = '\0'; return(status); } /* copy the file from input to output */ while(0 != (nread = fread(recbuf,1,2880, diskfile))) { status = file_write(*handle, recbuf, nread); if (status) { file_outfile[0] = '\0'; return(status); } } /* close both files */ fclose(diskfile); copyhandle = *handle; file_close(*handle); *handle = copyhandle; /* reuse the old file handle */ /* reopen the new copy, with correct rwmode */ status = file_openfile(file_outfile, rwmode, &diskfile); file_outfile[0] = '\0'; } else { *handle = -1; for (ii = 0; ii < NMAXFILES; ii++) /* find empty slot in table */ { if (handleTable[ii].fileptr == 0) { *handle = ii; break; } } if (*handle == -1) return(TOO_MANY_FILES); /* too many files opened */ /*open the file */ status = file_openfile(filename, rwmode, &diskfile); } handleTable[*handle].fileptr = diskfile; handleTable[*handle].currentpos = 0; handleTable[*handle].last_io_op = IO_SEEK; return(status); } /*--------------------------------------------------------------------------*/ int file_openfile(char *filename, int rwmode, FILE **diskfile) /* lowest level routine to physically open a disk file */ { char mode[4]; #if defined(unix) || defined(__unix__) || defined(__unix) char tempname[1024], *cptr, user[80]; struct passwd *pwd; int ii = 0; #if defined(REPLACE_LINKS) struct stat stbuf; int success = 0; size_t n; FILE *f1, *f2; char buf[BUFSIZ]; #endif #endif if (rwmode == READWRITE) { strcpy(mode, "r+b"); /* open existing file with read-write */ } else { strcpy(mode, "rb"); /* open existing file readonly */ } #if MACHINE == ALPHAVMS || MACHINE == VAXVMS /* specify VMS record structure: fixed format, 2880 byte records */ /* but force stream mode access to enable random I/O access */ *diskfile = fopen(filename, mode, "rfm=fix", "mrs=2880", "ctx=stm"); #elif defined(unix) || defined(__unix__) || defined(__unix) /* support the ~user/file.fits or ~/file.fits filenames in UNIX */ if (*filename == '~') { if (filename[1] == '/') { cptr = getenv("HOME"); if (cptr) { if (strlen(cptr) + strlen(filename+1) > 1023) return(FILE_NOT_OPENED); strcpy(tempname, cptr); strcat(tempname, filename+1); } else { if (strlen(filename) > 1023) return(FILE_NOT_OPENED); strcpy(tempname, filename); } } else { /* copy user name */ cptr = filename+1; while (*cptr && (*cptr != '/')) { user[ii] = *cptr; cptr++; ii++; } user[ii] = '\0'; /* get structure that includes name of user's home directory */ pwd = getpwnam(user); /* copy user's home directory */ if (strlen(pwd->pw_dir) + strlen(cptr) > 1023) return(FILE_NOT_OPENED); strcpy(tempname, pwd->pw_dir); strcat(tempname, cptr); } *diskfile = fopen(tempname, mode); } else { /* don't need to expand the input file name */ *diskfile = fopen(filename, mode); #if defined(REPLACE_LINKS) if (!(*diskfile) && (rwmode == READWRITE)) { /* failed to open file with READWRITE privilege. Test if */ /* the file we are trying to open is a soft link to a file that */ /* doesn't have write privilege. */ lstat(filename, &stbuf); if ((stbuf.st_mode & S_IFMT) == S_IFLNK) /* is this a soft link? */ { if ((f1 = fopen(filename, "rb")) != 0) /* try opening READONLY */ { if (strlen(filename) + 7 > 1023) return(FILE_NOT_OPENED); strcpy(tempname, filename); strcat(tempname, ".TmxFil"); if ((f2 = fopen(tempname, "wb")) != 0) /* create temp file */ { success = 1; while ((n = fread(buf, 1, BUFSIZ, f1)) > 0) { /* copy linked file to local temporary file */ if (fwrite(buf, 1, n, f2) != n) { success = 0; break; } } fclose(f2); } fclose(f1); if (success) { /* delete link and rename temp file to previous link name */ remove(filename); rename(tempname, filename); /* try once again to open the file with write access */ *diskfile = fopen(filename, mode); } else remove(tempname); /* clean up the failed copy */ } } } #endif } #else /* other non-UNIX machines */ *diskfile = fopen(filename, mode); #endif if (!(*diskfile)) /* couldn't open file */ { return(FILE_NOT_OPENED); } return(0); } /*--------------------------------------------------------------------------*/ int file_create(char *filename, int *handle) { FILE *diskfile; int ii; char mode[4]; int status = 0, rootlen, rootlen2, slen; char *cptr, *cpos; char cwd[FLEN_FILENAME], absURL[FLEN_FILENAME]; char rootstring[256], rootstring2[256]; char username[FLEN_FILENAME], userroot[FLEN_FILENAME], userroot2[FLEN_FILENAME]; cptr = getenv("HERA_DATA_DIRECTORY"); if (cptr) { /* This environment variable is defined in the Hera data analysis environment. */ /* It specifies the root directory path to the users data directories. */ /* CFITSIO will verify that the path to the file that is to be created */ /* is within this root directory + the user's home directory name. */ /* printf("env = %s\n",cptr); */ if (strlen(cptr) > 200) /* guard against possible string overflows */ return(FILE_NOT_CREATED); /* environment variable has the form "path/one/;/path/two/" where the */ /* second path is optional */ strcpy(rootstring, cptr); cpos = strchr(rootstring, ';'); if (cpos) { *cpos = '\0'; cpos++; strcpy(rootstring2, cpos); } else { *rootstring2 = '\0'; } /* printf("%s, %s\n", rootstring, rootstring2); printf("CWD = %s\n", cwd); printf("rootstring=%s, cwd=%s.\n", rootstring, cwd); */ /* Get the current working directory */ fits_get_cwd(cwd, &status); slen = strlen(cwd); if (cwd[slen-1] != '/') strcat(cwd,"/"); /* make sure the CWD ends with slash */ /* check that CWD string matches the rootstring */ rootlen = strlen(rootstring); if (strncmp(rootstring, cwd, rootlen)) { ffpmsg("invalid CWD: does not match root data directory"); return(FILE_NOT_CREATED); } else { /* get the user name from CWD (it follows the root string) */ strncpy(username, cwd+rootlen, 50); /* limit length of user name */ cpos=strchr(username, '/'); if (!cpos) { ffpmsg("invalid CWD: not equal to root data directory + username"); return(FILE_NOT_CREATED); } else { *(cpos+1) = '\0'; /* truncate user name string */ /* construct full user root name */ strcpy(userroot, rootstring); strcat(userroot, username); rootlen = strlen(userroot); /* construct alternate full user root name */ strcpy(userroot2, rootstring2); strcat(userroot2, username); rootlen2 = strlen(userroot2); /* convert the input filename to absolute path relative to the CWD */ fits_relurl2url(cwd, filename, absURL, &status); /* printf("username = %s\n", username); printf("userroot = %s\n", userroot); printf("userroot2 = %s\n", userroot2); printf("filename = %s\n", filename); printf("ABS = %s\n", absURL); */ /* check that CWD string matches the rootstring or alternate root string */ if ( strncmp(userroot, absURL, rootlen) && strncmp(userroot2, absURL, rootlen2) ) { ffpmsg("invalid filename: path not within user directory"); return(FILE_NOT_CREATED); } } } /* if we got here, then the input filename appears to be valid */ } *handle = -1; for (ii = 0; ii < NMAXFILES; ii++) /* find empty slot in table */ { if (handleTable[ii].fileptr == 0) { *handle = ii; break; } } if (*handle == -1) return(TOO_MANY_FILES); /* too many files opened */ strcpy(mode, "w+b"); /* create new file with read-write */ diskfile = fopen(filename, "r"); /* does file already exist? */ if (diskfile) { fclose(diskfile); /* close file and exit with error */ return(FILE_NOT_CREATED); } #if MACHINE == ALPHAVMS || MACHINE == VAXVMS /* specify VMS record structure: fixed format, 2880 byte records */ /* but force stream mode access to enable random I/O access */ diskfile = fopen(filename, mode, "rfm=fix", "mrs=2880", "ctx=stm"); #else diskfile = fopen(filename, mode); #endif if (!(diskfile)) /* couldn't create file */ { return(FILE_NOT_CREATED); } handleTable[ii].fileptr = diskfile; handleTable[ii].currentpos = 0; handleTable[ii].last_io_op = IO_SEEK; return(0); } /*--------------------------------------------------------------------------*/ int file_truncate(int handle, LONGLONG filesize) /* truncate the diskfile to a new smaller size */ { #ifdef HAVE_FTRUNCATE int fdesc; fdesc = fileno(handleTable[handle].fileptr); ftruncate(fdesc, (OFF_T) filesize); file_seek(handle, filesize); handleTable[handle].currentpos = filesize; handleTable[handle].last_io_op = IO_SEEK; #endif return(0); } /*--------------------------------------------------------------------------*/ int file_size(int handle, LONGLONG *filesize) /* return the size of the file in bytes */ { OFF_T position1,position2; FILE *diskfile; diskfile = handleTable[handle].fileptr; #if defined(_MSC_VER) && (_MSC_VER >= 1400) /* call the VISUAL C++ version of the routines which support */ /* Large Files (> 2GB) if they are supported (since VC 8.0) */ position1 = _ftelli64(diskfile); /* save current postion */ if (position1 < 0) return(SEEK_ERROR); if (_fseeki64(diskfile, 0, 2) != 0) /* seek to end of file */ return(SEEK_ERROR); position2 = _ftelli64(diskfile); /* get file size */ if (position2 < 0) return(SEEK_ERROR); if (_fseeki64(diskfile, position1, 0) != 0) /* seek back to original pos */ return(SEEK_ERROR); #elif _FILE_OFFSET_BITS - 0 == 64 /* call the newer ftello and fseeko routines , which support */ /* Large Files (> 2GB) if they are supported. */ position1 = ftello(diskfile); /* save current postion */ if (position1 < 0) return(SEEK_ERROR); if (fseeko(diskfile, 0, 2) != 0) /* seek to end of file */ return(SEEK_ERROR); position2 = ftello(diskfile); /* get file size */ if (position2 < 0) return(SEEK_ERROR); if (fseeko(diskfile, position1, 0) != 0) /* seek back to original pos */ return(SEEK_ERROR); #else position1 = ftell(diskfile); /* save current postion */ if (position1 < 0) return(SEEK_ERROR); if (fseek(diskfile, 0, 2) != 0) /* seek to end of file */ return(SEEK_ERROR); position2 = ftell(diskfile); /* get file size */ if (position2 < 0) return(SEEK_ERROR); if (fseek(diskfile, position1, 0) != 0) /* seek back to original pos */ return(SEEK_ERROR); #endif *filesize = (LONGLONG) position2; return(0); } /*--------------------------------------------------------------------------*/ int file_close(int handle) /* close the file */ { if (fclose(handleTable[handle].fileptr) ) return(FILE_NOT_CLOSED); handleTable[handle].fileptr = 0; return(0); } /*--------------------------------------------------------------------------*/ int file_remove(char *filename) /* delete the file from disk */ { remove(filename); return(0); } /*--------------------------------------------------------------------------*/ int file_flush(int handle) /* flush the file */ { if (fflush(handleTable[handle].fileptr) ) return(WRITE_ERROR); /* The flush operation is not supposed to move the internal */ /* file pointer, but it does on some Windows-95 compilers and */ /* perhaps others, so seek to original position to be sure. */ /* This seek will do no harm on other systems. */ #if MACHINE == IBMPC if (file_seek(handle, handleTable[handle].currentpos)) return(SEEK_ERROR); #endif return(0); } /*--------------------------------------------------------------------------*/ int file_seek(int handle, LONGLONG offset) /* seek to position relative to start of the file */ { #if defined(_MSC_VER) && (_MSC_VER >= 1400) /* Microsoft visual studio C++ */ /* _fseeki64 supported beginning with version 8.0 */ if (_fseeki64(handleTable[handle].fileptr, (OFF_T) offset, 0) != 0) return(SEEK_ERROR); #elif _FILE_OFFSET_BITS - 0 == 64 if (fseeko(handleTable[handle].fileptr, (OFF_T) offset, 0) != 0) return(SEEK_ERROR); #else if (fseek(handleTable[handle].fileptr, (OFF_T) offset, 0) != 0) return(SEEK_ERROR); #endif handleTable[handle].currentpos = offset; return(0); } /*--------------------------------------------------------------------------*/ int file_read(int hdl, void *buffer, long nbytes) /* read bytes from the current position in the file */ { long nread; char *cptr; if (handleTable[hdl].last_io_op == IO_WRITE) { if (file_seek(hdl, handleTable[hdl].currentpos)) return(SEEK_ERROR); } nread = (long) fread(buffer, 1, nbytes, handleTable[hdl].fileptr); if (nread == 1) { cptr = (char *) buffer; /* some editors will add a single end-of-file character to a file */ /* Ignore it if the character is a zero, 10, or 32 */ if (*cptr == 0 || *cptr == 10 || *cptr == 32) return(END_OF_FILE); else return(READ_ERROR); } else if (nread != nbytes) { return(READ_ERROR); } handleTable[hdl].currentpos += nbytes; handleTable[hdl].last_io_op = IO_READ; return(0); } /*--------------------------------------------------------------------------*/ int file_write(int hdl, void *buffer, long nbytes) /* write bytes at the current position in the file */ { if (handleTable[hdl].last_io_op == IO_READ) { if (file_seek(hdl, handleTable[hdl].currentpos)) return(SEEK_ERROR); } if((long) fwrite(buffer, 1, nbytes, handleTable[hdl].fileptr) != nbytes) return(WRITE_ERROR); handleTable[hdl].currentpos += nbytes; handleTable[hdl].last_io_op = IO_WRITE; return(0); } /*--------------------------------------------------------------------------*/ int file_compress_open(char *filename, int rwmode, int *hdl) /* This routine opens the compressed diskfile by creating a new uncompressed file then opening it. The input file name (the name of the compressed file) gets replaced with the name of the uncompressed file, which is initially stored in the global file_outfile string. file_outfile then gets set to a null string. */ { FILE *indiskfile, *outdiskfile; int status; char *cptr; /* open the compressed disk file */ status = file_openfile(filename, READONLY, &indiskfile); if (status) { ffpmsg("failed to open compressed disk file (file_compress_open)"); ffpmsg(filename); return(status); } /* name of the output uncompressed file is stored in the */ /* global variable called 'file_outfile'. */ cptr = file_outfile; if (*cptr == '!') { /* clobber any existing file with the same name */ cptr++; remove(cptr); } else { outdiskfile = fopen(file_outfile, "r"); /* does file already exist? */ if (outdiskfile) { ffpmsg("uncompressed file already exists: (file_compress_open)"); ffpmsg(file_outfile); fclose(outdiskfile); /* close file and exit with error */ file_outfile[0] = '\0'; return(FILE_NOT_CREATED); } } outdiskfile = fopen(cptr, "w+b"); /* create new file */ if (!outdiskfile) { ffpmsg("could not create uncompressed file: (file_compress_open)"); ffpmsg(file_outfile); file_outfile[0] = '\0'; return(FILE_NOT_CREATED); } /* uncompress file into another file */ uncompress2file(filename, indiskfile, outdiskfile, &status); fclose(indiskfile); fclose(outdiskfile); if (status) { ffpmsg("error in file_compress_open: failed to uncompressed file:"); ffpmsg(filename); ffpmsg(" into new output file:"); ffpmsg(file_outfile); file_outfile[0] = '\0'; return(status); } strcpy(filename, cptr); /* switch the names */ file_outfile[0] = '\0'; status = file_open(filename, rwmode, hdl); return(status); } /*--------------------------------------------------------------------------*/ int file_is_compressed(char *filename) /* I - FITS file name */ /* Test if the disk file is compressed. Returns 1 if compressed, 0 if not. This may modify the filename string by appending a compression suffex. */ { FILE *diskfile; unsigned char buffer[2]; char tmpfilename[FLEN_FILENAME]; /* Open file. Try various suffix combinations */ if (file_openfile(filename, 0, &diskfile)) { if (strlen(filename) > FLEN_FILENAME - 1) return(0); strcpy(tmpfilename,filename); strcat(filename,".gz"); if (file_openfile(filename, 0, &diskfile)) { #if HAVE_BZIP2 strcpy(tmpfilename,filename); strcat(filename,".bz2"); if (file_openfile(filename, 0, &diskfile)) { #endif strcpy(filename, tmpfilename); strcat(filename,".Z"); if (file_openfile(filename, 0, &diskfile)) { strcpy(filename, tmpfilename); strcat(filename,".z"); /* it's often lower case on CDROMs */ if (file_openfile(filename, 0, &diskfile)) { strcpy(filename, tmpfilename); strcat(filename,".zip"); if (file_openfile(filename, 0, &diskfile)) { strcpy(filename, tmpfilename); strcat(filename,"-z"); /* VMS suffix */ if (file_openfile(filename, 0, &diskfile)) { strcpy(filename, tmpfilename); strcat(filename,"-gz"); /* VMS suffix */ if (file_openfile(filename, 0, &diskfile)) { strcpy(filename,tmpfilename); /* restore original name */ return(0); /* file not found */ } } } } } #if HAVE_BZIP2 } #endif } } if (fread(buffer, 1, 2, diskfile) != 2) /* read 2 bytes */ { fclose(diskfile); /* error reading file so just return */ return(0); } fclose(diskfile); /* see if the 2 bytes have the magic values for a compressed file */ if ( (memcmp(buffer, "\037\213", 2) == 0) || /* GZIP */ (memcmp(buffer, "\120\113", 2) == 0) || /* PKZIP */ (memcmp(buffer, "\037\036", 2) == 0) || /* PACK */ (memcmp(buffer, "\037\235", 2) == 0) || /* LZW */ #if HAVE_BZIP2 (memcmp(buffer, "BZ", 2) == 0) || /* BZip2 */ #endif (memcmp(buffer, "\037\240", 2) == 0)) /* LZH */ { return(1); /* this is a compressed file */ } else { return(0); /* not a compressed file */ } } /*--------------------------------------------------------------------------*/ int file_checkfile (char *urltype, char *infile, char *outfile) { /* special case: if file:// driver, check if the file is compressed */ if ( file_is_compressed(infile) ) { /* if output file has been specified, save the name for future use: */ /* This is the name of the uncompressed file to be created on disk. */ if (strlen(outfile)) { if (!strncmp(outfile, "mem:", 4) ) { /* uncompress the file in memory, with READ and WRITE access */ strcpy(urltype, "compressmem://"); /* use special driver */ *file_outfile = '\0'; } else { strcpy(urltype, "compressfile://"); /* use special driver */ /* don't copy the "file://" prefix, if present. */ if (!strncmp(outfile, "file://", 7) ) strcpy(file_outfile,outfile+7); else strcpy(file_outfile,outfile); } } else { /* uncompress the file in memory */ strcpy(urltype, "compress://"); /* use special driver */ *file_outfile = '\0'; /* no output file was specified */ } } else /* an ordinary, uncompressed FITS file on disk */ { /* save the output file name for later use when opening the file. */ /* In this case, the file to be opened will be opened READONLY, */ /* and copied to this newly created output file. The original file */ /* will be closed, and the copy will be opened by CFITSIO for */ /* subsequent processing (possibly with READWRITE access). */ if (strlen(outfile)) { file_outfile[0] = '\0'; strncat(file_outfile,outfile,FLEN_FILENAME-1); } } return 0; } /**********************************************************************/ /**********************************************************************/ /**********************************************************************/ /**** driver routines for stream//: device (stdin or stdout) ********/ /*--------------------------------------------------------------------------*/ int stream_open(char *filename, int rwmode, int *handle) { /* read from stdin */ if (filename) rwmode = 1; /* dummy statement to suppress unused parameter compiler warning */ *handle = 1; /* 1 = stdin */ return(0); } /*--------------------------------------------------------------------------*/ int stream_create(char *filename, int *handle) { /* write to stdout */ if (filename) /* dummy statement to suppress unused parameter compiler warning */ *handle = 2; else *handle = 2; /* 2 = stdout */ return(0); } /*--------------------------------------------------------------------------*/ int stream_size(int handle, LONGLONG *filesize) /* return the size of the file in bytes */ { handle = 0; /* suppress unused parameter compiler warning */ /* this operation is not supported in a stream; return large value */ *filesize = LONG_MAX; return(0); } /*--------------------------------------------------------------------------*/ int stream_close(int handle) /* don't have to close stdin or stdout */ { handle = 0; /* suppress unused parameter compiler warning */ return(0); } /*--------------------------------------------------------------------------*/ int stream_flush(int handle) /* flush the file */ { if (handle == 2) fflush(stdout); return(0); } /*--------------------------------------------------------------------------*/ int stream_seek(int handle, LONGLONG offset) /* seeking is not allowed in a stream */ { offset = handle; /* suppress unused parameter compiler warning */ return(1); } /*--------------------------------------------------------------------------*/ int stream_read(int hdl, void *buffer, long nbytes) /* reading from stdin stream */ { long nread; if (hdl != 1) return(1); /* can only read from stdin */ nread = (long) fread(buffer, 1, nbytes, stdin); if (nread != nbytes) { /* return(READ_ERROR); */ return(END_OF_FILE); } return(0); } /*--------------------------------------------------------------------------*/ int stream_write(int hdl, void *buffer, long nbytes) /* write bytes at the current position in the file */ { if (hdl != 2) return(1); /* can only write to stdout */ if((long) fwrite(buffer, 1, nbytes, stdout) != nbytes) return(WRITE_ERROR); return(0); } cfitsio/drvrgsiftp.c0000644000225700000360000003241613246025103014344 0ustar cagordonlhea /* This file, drvrgsiftp.c contains driver routines for gsiftp files. */ /* Andrea Barisani */ /* Taffoni Giuliano */ #ifdef HAVE_NET_SERVICES #ifdef HAVE_GSIFTP #include #include #include #include #include #include "fitsio2.h" #include #define MAXLEN 1200 #define NETTIMEOUT 80 #define MAX_BUFFER_SIZE_R 1024 #define MAX_BUFFER_SIZE_W (64*1024) static int gsiftpopen = 0; static int global_offset = 0; static int gsiftp_get(char *filename, FILE **gsiftpfile, int num_streams); static globus_mutex_t lock; static globus_cond_t cond; static globus_bool_t done; static char *gsiftp_tmpfile; static char *gsiftpurl = NULL; static char gsiftp_tmpdir[MAXLEN]; static jmp_buf env; /* holds the jump buffer for setjmp/longjmp pairs */ static void signal_handler(int sig); int gsiftp_init(void) { if (getenv("GSIFTP_TMPFILE")) { gsiftp_tmpfile = getenv("GSIFTP_TMPFILE"); } else { strncpy(gsiftp_tmpdir, "/tmp/gsiftp_XXXXXX", sizeof gsiftp_tmpdir); if (mkdtemp(gsiftp_tmpdir) == NULL) { ffpmsg("Cannot create temporary directory!"); return (FILE_NOT_OPENED); } gsiftp_tmpfile = malloc(strlen(gsiftp_tmpdir) + strlen("/gsiftp_buffer.tmp")); strcat(gsiftp_tmpfile, gsiftp_tmpdir); strcat(gsiftp_tmpfile, "/gsiftp_buffer.tmp"); } return file_init(); } int gsiftp_shutdown(void) { free(gsiftpurl); free(gsiftp_tmpfile); free(gsiftp_tmpdir); return file_shutdown(); } int gsiftp_setoptions(int options) { return file_setoptions(options); } int gsiftp_getoptions(int *options) { return file_getoptions(options); } int gsiftp_getversion(int *version) { return file_getversion(version); } int gsiftp_checkfile(char *urltype, char *infile, char *outfile) { return file_checkfile(urltype, infile, outfile); } int gsiftp_open(char *filename, int rwmode, int *handle) { FILE *gsiftpfile; int num_streams; if (getenv("GSIFTP_STREAMS")) { num_streams = (int)getenv("GSIFTP_STREAMS"); } else { num_streams = 1; } if (rwmode) { gsiftpopen = 2; } else { gsiftpopen = 1; } if (gsiftpurl) free(gsiftpurl); gsiftpurl = strdup(filename); if (setjmp(env) != 0) { ffpmsg("Timeout (gsiftp_open)"); goto error; } signal(SIGALRM, signal_handler); alarm(NETTIMEOUT); if (gsiftp_get(filename,&gsiftpfile,num_streams)) { alarm(0); ffpmsg("Unable to open gsiftp file (gsiftp_open)"); ffpmsg(filename); goto error; } fclose(gsiftpfile); signal(SIGALRM, SIG_DFL); alarm(0); return file_open(gsiftp_tmpfile, rwmode, handle); error: alarm(0); signal(SIGALRM, SIG_DFL); return (FILE_NOT_OPENED); } int gsiftp_create(char *filename, int *handle) { if (gsiftpurl) free(gsiftpurl); gsiftpurl = strdup(filename); return file_create(gsiftp_tmpfile, handle); } int gsiftp_truncate(int handle, LONGLONG filesize) { return file_truncate(handle, filesize); } int gsiftp_size(int handle, LONGLONG *filesize) { return file_size(handle, filesize); } int gsiftp_flush(int handle) { FILE *gsiftpfile; int num_streams; if (getenv("GSIFTP_STREAMS")) { num_streams = (int)getenv("GSIFTP_STREAMS"); } else { num_streams = 1; } int rc = file_flush(handle); if (gsiftpopen != 1) { if (setjmp(env) != 0) { ffpmsg("Timeout (gsiftp_write)"); goto error; } signal(SIGALRM, signal_handler); alarm(NETTIMEOUT); if (gsiftp_put(gsiftpurl,&gsiftpfile,num_streams)) { alarm(0); ffpmsg("Unable to open gsiftp file (gsiftp_flush)"); ffpmsg(gsiftpurl); goto error; } fclose(gsiftpfile); signal(SIGALRM, SIG_DFL); alarm(0); } return rc; error: alarm(0); signal(SIGALRM, SIG_DFL); return (FILE_NOT_OPENED); } int gsiftp_seek(int handle, LONGLONG offset) { return file_seek(handle, offset); } int gsiftp_read(int hdl, void *buffer, long nbytes) { return file_read(hdl, buffer, nbytes); } int gsiftp_write(int hdl, void *buffer, long nbytes) { return file_write(hdl, buffer, nbytes); } int gsiftp_close(int handle) { unlink(gsiftp_tmpfile); if (gsiftp_tmpdir) rmdir(gsiftp_tmpdir); return file_close(handle); } static void done_cb( void * user_arg, globus_ftp_client_handle_t * handle, globus_object_t * err) { if(err){ fprintf(stderr, "%s", globus_object_printable_to_string(err)); } globus_mutex_lock(&lock); done = GLOBUS_TRUE; globus_cond_signal(&cond); globus_mutex_unlock(&lock); return; } static void data_cb_read( void * user_arg, globus_ftp_client_handle_t * handle, globus_object_t * err, globus_byte_t * buffer, globus_size_t length, globus_off_t offset, globus_bool_t eof) { if(err) { fprintf(stderr, "%s", globus_object_printable_to_string(err)); } else { FILE* fd = (FILE*) user_arg; int rc = fwrite(buffer, 1, length, fd); if (ferror(fd)) { printf("Read error in function data_cb_read; errno = %d\n", errno); return; } if (!eof) { globus_ftp_client_register_read(handle, buffer, MAX_BUFFER_SIZE_R, data_cb_read, (void*) fd); } } return; } static void data_cb_write( void * user_arg, globus_ftp_client_handle_t * handle, globus_object_t * err, globus_byte_t * buffer, globus_size_t length, globus_off_t offset, globus_bool_t eof) { int curr_offset; if(err) { fprintf(stderr, "%s", globus_object_printable_to_string(err)); } else { if (!eof) { FILE* fd = (FILE*) user_arg; int rc; globus_mutex_lock(&lock); curr_offset = global_offset; rc = fread(buffer, 1, MAX_BUFFER_SIZE_W, fd); global_offset += rc; globus_mutex_unlock(&lock); if (ferror(fd)) { printf("Read error in function data_cb_write; errno = %d\n", errno); return; } globus_ftp_client_register_write(handle, buffer, rc, curr_offset, feof(fd) != 0, data_cb_write, (void*) fd); } else { globus_libc_free(buffer); } } return; } int gsiftp_get(char *filename, FILE **gsiftpfile, int num_streams) { char gsiurl[MAXLEN]; globus_ftp_client_handle_t handle; globus_ftp_client_operationattr_t attr; globus_ftp_client_handleattr_t handle_attr; globus_ftp_control_parallelism_t parallelism; globus_ftp_control_layout_t layout; globus_byte_t buffer[MAX_BUFFER_SIZE_R]; globus_size_t buffer_length = sizeof(buffer); globus_result_t result; globus_ftp_client_restart_marker_t restart; globus_ftp_control_type_t filetype; globus_module_activate(GLOBUS_FTP_CLIENT_MODULE); globus_mutex_init(&lock, GLOBUS_NULL); globus_cond_init(&cond, GLOBUS_NULL); globus_ftp_client_handle_init(&handle, GLOBUS_NULL); globus_ftp_client_handleattr_init(&handle_attr); globus_ftp_client_operationattr_init(&attr); layout.mode = GLOBUS_FTP_CONTROL_STRIPING_NONE; globus_ftp_client_restart_marker_init(&restart); globus_ftp_client_operationattr_set_mode( &attr, GLOBUS_FTP_CONTROL_MODE_EXTENDED_BLOCK); if (num_streams >= 1) { parallelism.mode = GLOBUS_FTP_CONTROL_PARALLELISM_FIXED; parallelism.fixed.size = num_streams; globus_ftp_client_operationattr_set_parallelism( &attr, ¶llelism); } globus_ftp_client_operationattr_set_layout(&attr, &layout); filetype = GLOBUS_FTP_CONTROL_TYPE_IMAGE; globus_ftp_client_operationattr_set_type (&attr, filetype); globus_ftp_client_handle_init(&handle, &handle_attr); done = GLOBUS_FALSE; strcpy(gsiurl,"gsiftp://"); strcat(gsiurl,filename); *gsiftpfile = fopen(gsiftp_tmpfile,"w+"); if (!*gsiftpfile) { ffpmsg("Unable to open temporary file!"); return (FILE_NOT_OPENED); } result = globus_ftp_client_get(&handle, gsiurl, &attr, &restart, done_cb, 0); if(result != GLOBUS_SUCCESS) { globus_object_t * err; err = globus_error_get(result); fprintf(stderr, "%s", globus_object_printable_to_string(err)); done = GLOBUS_TRUE; } else { globus_ftp_client_register_read(&handle, buffer, buffer_length, data_cb_read, (void*) *gsiftpfile); } globus_mutex_lock(&lock); while(!done) { globus_cond_wait(&cond, &lock); } globus_mutex_unlock(&lock); globus_ftp_client_handle_destroy(&handle); globus_module_deactivate_all(); return 0; } int gsiftp_put(char *filename, FILE **gsiftpfile, int num_streams) { int i; char gsiurl[MAXLEN]; globus_ftp_client_handle_t handle; globus_ftp_client_operationattr_t attr; globus_ftp_client_handleattr_t handle_attr; globus_ftp_control_parallelism_t parallelism; globus_ftp_control_layout_t layout; globus_byte_t * buffer; globus_size_t buffer_length = sizeof(buffer); globus_result_t result; globus_ftp_client_restart_marker_t restart; globus_ftp_control_type_t filetype; globus_module_activate(GLOBUS_FTP_CLIENT_MODULE); globus_mutex_init(&lock, GLOBUS_NULL); globus_cond_init(&cond, GLOBUS_NULL); globus_ftp_client_handle_init(&handle, GLOBUS_NULL); globus_ftp_client_handleattr_init(&handle_attr); globus_ftp_client_operationattr_init(&attr); layout.mode = GLOBUS_FTP_CONTROL_STRIPING_NONE; globus_ftp_client_restart_marker_init(&restart); globus_ftp_client_operationattr_set_mode( &attr, GLOBUS_FTP_CONTROL_MODE_EXTENDED_BLOCK); if (num_streams >= 1) { parallelism.mode = GLOBUS_FTP_CONTROL_PARALLELISM_FIXED; parallelism.fixed.size = num_streams; globus_ftp_client_operationattr_set_parallelism( &attr, ¶llelism); } globus_ftp_client_operationattr_set_layout(&attr, &layout); filetype = GLOBUS_FTP_CONTROL_TYPE_IMAGE; globus_ftp_client_operationattr_set_type (&attr, filetype); globus_ftp_client_handle_init(&handle, &handle_attr); done = GLOBUS_FALSE; strcpy(gsiurl,"gsiftp://"); strcat(gsiurl,filename); *gsiftpfile = fopen(gsiftp_tmpfile,"r"); if (!*gsiftpfile) { ffpmsg("Unable to open temporary file!"); return (FILE_NOT_OPENED); } result = globus_ftp_client_put(&handle, gsiurl, &attr, &restart, done_cb, 0); if(result != GLOBUS_SUCCESS) { globus_object_t * err; err = globus_error_get(result); fprintf(stderr, "%s", globus_object_printable_to_string(err)); done = GLOBUS_TRUE; } else { int rc; int curr_offset; for (i = 0; i< 2 * num_streams && feof(*gsiftpfile) == 0; i++) { buffer = malloc(MAX_BUFFER_SIZE_W); globus_mutex_lock(&lock); curr_offset = global_offset; rc = fread(buffer, 1, MAX_BUFFER_SIZE_W, *gsiftpfile); global_offset += rc; globus_mutex_unlock(&lock); globus_ftp_client_register_write( &handle, buffer, rc, curr_offset, feof(*gsiftpfile) != 0, data_cb_write, (void*) *gsiftpfile); } } globus_mutex_lock(&lock); while(!done) { globus_cond_wait(&cond, &lock); } globus_mutex_unlock(&lock); globus_ftp_client_handle_destroy(&handle); globus_module_deactivate_all(); return 0; } static void signal_handler(int sig) { switch (sig) { case SIGALRM: /* process for alarm */ longjmp(env,sig); default: { /* Hmm, shouldn't have happend */ exit(sig); } } } #endif #endif cfitsio/drvrgsiftp.h0000644000225700000360000000142313246025103014343 0ustar cagordonlhea#ifndef _GSIFTP_H #define _GSIFTP_H int gsiftp_init(void); int gsiftp_setoptions(int options); int gsiftp_getoptions(int *options); int gsiftp_getversion(int *version); int gsiftp_shutdown(void); int gsiftp_checkfile(char *urltype, char *infile, char *outfile); int gsiftp_open(char *filename, int rwmode, int *driverhandle); int gsiftp_create(char *filename, int *driverhandle); int gsiftp_truncate(int driverhandle, LONGLONG filesize); int gsiftp_size(int driverhandle, LONGLONG *filesize); int gsiftp_close(int driverhandle); int gsiftp_remove(char *filename); int gsiftp_flush(int driverhandle); int gsiftp_seek(int driverhandle, LONGLONG offset); int gsiftp_read (int driverhandle, void *buffer, long nbytes); int gsiftp_write(int driverhandle, void *buffer, long nbytes); #endif cfitsio/drvrmem.c0000644000225700000360000011520113246025103013620 0ustar cagordonlhea/* This file, drvrmem.c, contains driver routines for memory files. */ /* The FITSIO software was written by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ #include #include #include /* apparently needed to define size_t */ #include "fitsio2.h" #if HAVE_BZIP2 #include "bzlib.h" #endif /* prototype for .Z file uncompression function in zuncompress.c */ int zuncompress2mem(char *filename, FILE *diskfile, char **buffptr, size_t *buffsize, void *(*mem_realloc)(void *p, size_t newsize), size_t *filesize, int *status); #if HAVE_BZIP2 /* prototype for .bz2 uncompression function (in this file) */ void bzip2uncompress2mem(char *filename, FILE *diskfile, int hdl, size_t* filesize, int* status); #endif #define RECBUFLEN 1000 static char stdin_outfile[FLEN_FILENAME]; typedef struct /* structure containing mem file structure */ { char **memaddrptr; /* Pointer to memory address pointer; */ /* This may or may not point to memaddr. */ char *memaddr; /* Pointer to starting memory address; may */ /* not always be used, so use *memaddrptr instead */ size_t *memsizeptr; /* Pointer to the size of the memory allocation. */ /* This may or may not point to memsize. */ size_t memsize; /* Size of the memory allocation; this may not */ /* always be used, so use *memsizeptr instead. */ size_t deltasize; /* Suggested increment for reallocating memory */ void *(*mem_realloc)(void *p, size_t newsize); /* realloc function */ LONGLONG currentpos; /* current file position, relative to start */ LONGLONG fitsfilesize; /* size of the FITS file (always <= *memsizeptr) */ FILE *fileptr; /* pointer to compressed output disk file */ } memdriver; static memdriver memTable[NMAXFILES]; /* allocate mem file handle tables */ /*--------------------------------------------------------------------------*/ int mem_init(void) { int ii; for (ii = 0; ii < NMAXFILES; ii++) /* initialize all empty slots in table */ { memTable[ii].memaddrptr = 0; memTable[ii].memaddr = 0; } return(0); } /*--------------------------------------------------------------------------*/ int mem_setoptions(int options) { /* do something with the options argument, to stop compiler warning */ options = 0; return(options); } /*--------------------------------------------------------------------------*/ int mem_getoptions(int *options) { *options = 0; return(0); } /*--------------------------------------------------------------------------*/ int mem_getversion(int *version) { *version = 10; return(0); } /*--------------------------------------------------------------------------*/ int mem_shutdown(void) { return(0); } /*--------------------------------------------------------------------------*/ int mem_create(char *filename, int *handle) /* Create a new empty memory file for subsequent writes. The file name is ignored in this case. */ { int status; /* initially allocate 1 FITS block = 2880 bytes */ status = mem_createmem(2880L, handle); if (status) { ffpmsg("failed to create empty memory file (mem_create)"); return(status); } return(0); } /*--------------------------------------------------------------------------*/ int mem_create_comp(char *filename, int *handle) /* Create a new empty memory file for subsequent writes. Also create an empty compressed .gz file. The memory file will be compressed and written to the disk file when the file is closed. */ { FILE *diskfile; char mode[4]; int status; /* first, create disk file for the compressed output */ if ( !strcmp(filename, "-.gz") || !strcmp(filename, "stdout.gz") || !strcmp(filename, "STDOUT.gz") ) { /* special case: create uncompressed FITS file in memory, then compress it an write it out to 'stdout' when it is closed. */ diskfile = stdout; } else { /* normal case: create disk file for the compressed output */ strcpy(mode, "w+b"); /* create file with read-write */ diskfile = fopen(filename, "r"); /* does file already exist? */ if (diskfile) { fclose(diskfile); /* close file and exit with error */ return(FILE_NOT_CREATED); } #if MACHINE == ALPHAVMS || MACHINE == VAXVMS /* specify VMS record structure: fixed format, 2880 byte records */ /* but force stream mode access to enable random I/O access */ diskfile = fopen(filename, mode, "rfm=fix", "mrs=2880", "ctx=stm"); #else diskfile = fopen(filename, mode); #endif if (!(diskfile)) /* couldn't create file */ { return(FILE_NOT_CREATED); } } /* now create temporary memory file */ /* initially allocate 1 FITS block = 2880 bytes */ status = mem_createmem(2880L, handle); if (status) { ffpmsg("failed to create empty memory file (mem_create_comp)"); return(status); } memTable[*handle].fileptr = diskfile; return(0); } /*--------------------------------------------------------------------------*/ int mem_openmem(void **buffptr, /* I - address of memory pointer */ size_t *buffsize, /* I - size of buffer, in bytes */ size_t deltasize, /* I - increment for future realloc's */ void *(*memrealloc)(void *p, size_t newsize), /* function */ int *handle) /* lowest level routine to open a pre-existing memory file. */ { int ii; *handle = -1; for (ii = 0; ii < NMAXFILES; ii++) /* find empty slot in handle table */ { if (memTable[ii].memaddrptr == 0) { *handle = ii; break; } } if (*handle == -1) return(TOO_MANY_FILES); /* too many files opened */ memTable[ii].memaddrptr = (char **) buffptr; /* pointer to start addres */ memTable[ii].memsizeptr = buffsize; /* allocated size of memory */ memTable[ii].deltasize = deltasize; /* suggested realloc increment */ memTable[ii].fitsfilesize = *buffsize; /* size of FITS file (upper limit) */ memTable[ii].currentpos = 0; /* at beginning of the file */ memTable[ii].mem_realloc = memrealloc; /* memory realloc function */ return(0); } /*--------------------------------------------------------------------------*/ int mem_createmem(size_t msize, int *handle) /* lowest level routine to allocate a memory file. */ { int ii; *handle = -1; for (ii = 0; ii < NMAXFILES; ii++) /* find empty slot in handle table */ { if (memTable[ii].memaddrptr == 0) { *handle = ii; break; } } if (*handle == -1) return(TOO_MANY_FILES); /* too many files opened */ /* use the internally allocated memaddr and memsize variables */ memTable[ii].memaddrptr = &memTable[ii].memaddr; memTable[ii].memsizeptr = &memTable[ii].memsize; /* allocate initial block of memory for the file */ if (msize > 0) { memTable[ii].memaddr = (char *) malloc(msize); if ( !(memTable[ii].memaddr) ) { ffpmsg("malloc of initial memory failed (mem_createmem)"); return(FILE_NOT_OPENED); } } /* set initial state of the file */ memTable[ii].memsize = msize; memTable[ii].deltasize = 2880; memTable[ii].fitsfilesize = 0; memTable[ii].currentpos = 0; memTable[ii].mem_realloc = realloc; return(0); } /*--------------------------------------------------------------------------*/ int mem_truncate(int handle, LONGLONG filesize) /* truncate the file to a new size */ { char *ptr; /* call the memory reallocation function, if defined */ if ( memTable[handle].mem_realloc ) { /* explicit LONGLONG->size_t cast */ ptr = (memTable[handle].mem_realloc)( *(memTable[handle].memaddrptr), (size_t) filesize); if (!ptr) { ffpmsg("Failed to reallocate memory (mem_truncate)"); return(MEMORY_ALLOCATION); } /* if allocated more memory, initialize it to zero */ if ( filesize > *(memTable[handle].memsizeptr) ) { memset(ptr + *(memTable[handle].memsizeptr), 0, ((size_t) filesize) - *(memTable[handle].memsizeptr) ); } *(memTable[handle].memaddrptr) = ptr; *(memTable[handle].memsizeptr) = (size_t) (filesize); } memTable[handle].currentpos = filesize; memTable[handle].fitsfilesize = filesize; return(0); } /*--------------------------------------------------------------------------*/ int stdin_checkfile(char *urltype, char *infile, char *outfile) /* do any special case checking when opening a file on the stdin stream */ { if (strlen(outfile)) { stdin_outfile[0] = '\0'; strncat(stdin_outfile,outfile,FLEN_FILENAME-1); /* an output file is specified */ strcpy(urltype,"stdinfile://"); } else *stdin_outfile = '\0'; /* no output file was specified */ return(0); } /*--------------------------------------------------------------------------*/ int stdin_open(char *filename, int rwmode, int *handle) /* open a FITS file from the stdin file stream by copying it into memory The file name is ignored in this case. */ { int status; char cbuff; if (*stdin_outfile) { /* copy the stdin stream to the specified disk file then open the file */ /* Create the output file */ status = file_create(stdin_outfile,handle); if (status) { ffpmsg("Unable to create output file to copy stdin (stdin_open):"); ffpmsg(stdin_outfile); return(status); } /* copy the whole stdin stream to the file */ status = stdin2file(*handle); file_close(*handle); if (status) { ffpmsg("failed to copy stdin to file (stdin_open)"); ffpmsg(stdin_outfile); return(status); } /* reopen file with proper rwmode attribute */ status = file_open(stdin_outfile, rwmode, handle); } else { /* get the first character, then put it back */ cbuff = fgetc(stdin); ungetc(cbuff, stdin); /* compressed files begin with 037 or 'P' */ if (cbuff == 31 || cbuff == 75) { /* looks like the input stream is compressed */ status = mem_compress_stdin_open(filename, rwmode, handle); } else { /* copy the stdin stream into memory then open file in memory */ if (rwmode != READONLY) { ffpmsg("cannot open stdin with WRITE access"); return(READONLY_FILE); } status = mem_createmem(2880L, handle); if (status) { ffpmsg("failed to create empty memory file (stdin_open)"); return(status); } /* copy the whole stdin stream into memory */ status = stdin2mem(*handle); if (status) { ffpmsg("failed to copy stdin into memory (stdin_open)"); free(memTable[*handle].memaddr); } } } return(status); } /*--------------------------------------------------------------------------*/ int stdin2mem(int hd) /* handle number */ /* Copy the stdin stream into memory. Fill whatever amount of memory has already been allocated, then realloc more memory if necessary. */ { size_t nread, memsize, delta; LONGLONG filesize; char *memptr; char simple[] = "SIMPLE"; int c, ii, jj; memptr = *memTable[hd].memaddrptr; memsize = *memTable[hd].memsizeptr; delta = memTable[hd].deltasize; filesize = 0; ii = 0; for(jj = 0; (c = fgetc(stdin)) != EOF && jj < 2000; jj++) { /* Skip over any garbage at the beginning of the stdin stream by */ /* reading 1 char at a time, looking for 'S', 'I', 'M', 'P', 'L', 'E' */ /* Give up if not found in the first 2000 characters */ if (c == simple[ii]) { ii++; if (ii == 6) /* found the complete string? */ { memcpy(memptr, simple, 6); /* copy "SIMPLE" to buffer */ filesize = 6; break; } } else ii = 0; /* reset search to beginning of the string */ } if (filesize == 0) { ffpmsg("Couldn't find the string 'SIMPLE' in the stdin stream."); ffpmsg("This does not look like a FITS file."); return(FILE_NOT_OPENED); } /* fill up the remainder of the initial memory allocation */ nread = fread(memptr + 6, 1, memsize - 6, stdin); nread += 6; /* add in the 6 characters in 'SIMPLE' */ if (nread < memsize) /* reached the end? */ { memTable[hd].fitsfilesize = nread; return(0); } filesize = nread; while (1) { /* allocate memory for another FITS block */ memptr = realloc(memptr, memsize + delta); if (!memptr) { ffpmsg("realloc failed while copying stdin (stdin2mem)"); return(MEMORY_ALLOCATION); } memsize += delta; /* read another FITS block */ nread = fread(memptr + filesize, 1, delta, stdin); filesize += nread; if (nread < delta) /* reached the end? */ break; } memTable[hd].fitsfilesize = filesize; *memTable[hd].memaddrptr = memptr; *memTable[hd].memsizeptr = memsize; return(0); } /*--------------------------------------------------------------------------*/ int stdin2file(int handle) /* handle number */ /* Copy the stdin stream to a file. . */ { size_t nread; char simple[] = "SIMPLE"; int c, ii, jj, status; char recbuf[RECBUFLEN]; ii = 0; for(jj = 0; (c = fgetc(stdin)) != EOF && jj < 2000; jj++) { /* Skip over any garbage at the beginning of the stdin stream by */ /* reading 1 char at a time, looking for 'S', 'I', 'M', 'P', 'L', 'E' */ /* Give up if not found in the first 2000 characters */ if (c == simple[ii]) { ii++; if (ii == 6) /* found the complete string? */ { memcpy(recbuf, simple, 6); /* copy "SIMPLE" to buffer */ break; } } else ii = 0; /* reset search to beginning of the string */ } if (ii != 6) { ffpmsg("Couldn't find the string 'SIMPLE' in the stdin stream"); return(FILE_NOT_OPENED); } /* fill up the remainder of the buffer */ nread = fread(recbuf + 6, 1, RECBUFLEN - 6, stdin); nread += 6; /* add in the 6 characters in 'SIMPLE' */ status = file_write(handle, recbuf, nread); if (status) return(status); /* copy the rest of stdin stream */ while(0 != (nread = fread(recbuf,1,RECBUFLEN, stdin))) { status = file_write(handle, recbuf, nread); if (status) return(status); } return(status); } /*--------------------------------------------------------------------------*/ int stdout_close(int handle) /* copy the memory file to stdout, then free the memory */ { int status = 0; /* copy from memory to standard out. explicit LONGLONG->size_t cast */ if(fwrite(memTable[handle].memaddr, 1, ((size_t) memTable[handle].fitsfilesize), stdout) != (size_t) memTable[handle].fitsfilesize ) { ffpmsg("failed to copy memory file to stdout (stdout_close)"); status = WRITE_ERROR; } free( memTable[handle].memaddr ); /* free the memory */ memTable[handle].memaddrptr = 0; memTable[handle].memaddr = 0; return(status); } /*--------------------------------------------------------------------------*/ int mem_compress_openrw(char *filename, int rwmode, int *hdl) /* This routine opens the compressed diskfile and creates an empty memory buffer with an appropriate size, then calls mem_uncompress2mem. It allows the memory 'file' to be opened with READWRITE access. */ { return(mem_compress_open(filename, READONLY, hdl)); } /*--------------------------------------------------------------------------*/ int mem_compress_open(char *filename, int rwmode, int *hdl) /* This routine opens the compressed diskfile and creates an empty memory buffer with an appropriate size, then calls mem_uncompress2mem. */ { FILE *diskfile; int status, estimated = 1; unsigned char buffer[4]; size_t finalsize, filesize; LONGLONG llsize = 0; unsigned int modulosize; char *ptr; if (rwmode != READONLY) { ffpmsg( "cannot open compressed file with WRITE access (mem_compress_open)"); ffpmsg(filename); return(READONLY_FILE); } /* open the compressed disk file */ status = file_openfile(filename, READONLY, &diskfile); if (status) { ffpmsg("failed to open compressed disk file (compress_open)"); ffpmsg(filename); return(status); } if (fread(buffer, 1, 2, diskfile) != 2) /* read 2 bytes */ { fclose(diskfile); return(READ_ERROR); } if (memcmp(buffer, "\037\213", 2) == 0) /* GZIP */ { /* the uncompressed file size is give at the end */ /* of the file in the ISIZE field (modulo 2^32) */ fseek(diskfile, 0, 2); /* move to end of file */ filesize = ftell(diskfile); /* position = size of file */ fseek(diskfile, -4L, 1); /* move back 4 bytes */ fread(buffer, 1, 4L, diskfile); /* read 4 bytes */ /* have to worry about integer byte order */ modulosize = buffer[0]; modulosize |= buffer[1] << 8; modulosize |= buffer[2] << 16; modulosize |= buffer[3] << 24; /* the field ISIZE in the gzipped file header only stores 4 bytes and contains the uncompressed file size modulo 2^32. If the uncompressed file size is less than the compressed file size (filesize), then one probably needs to add 2^32 = 4294967296 to the uncompressed file size, assuming that the gzip produces a compressed file that is smaller than the original file. But one must allow for the case of very small files, where the gzipped file may actually be larger then the original uncompressed file. Therefore, only perform the modulo 2^32 correction test if the compressed file is greater than 10,000 bytes in size. (Note: this threhold would fail only if the original file was greater than 2^32 bytes in size AND gzip was able to compress it by more than a factor of 400,000 (!) which seems highly unlikely.) Also, obviously, this 2^32 modulo correction cannot be performed if the finalsize variable is only 32-bits long. Typically, the 'size_t' integer type must be 8 bytes or larger in size to support data files that are greater than 2 GB (2^31 bytes) in size. */ finalsize = modulosize; if (sizeof(size_t) > 4 && filesize > 10000) { llsize = (LONGLONG) finalsize; /* use LONGLONG variable to suppress compiler warning */ while (llsize < (LONGLONG) filesize) llsize += 4294967296; finalsize = (size_t) llsize; } estimated = 0; /* file size is known, not estimated */ } else if (memcmp(buffer, "\120\113", 2) == 0) /* PKZIP */ { /* the uncompressed file size is give at byte 22 the file */ fseek(diskfile, 22L, 0); /* move to byte 22 */ fread(buffer, 1, 4L, diskfile); /* read 4 bytes */ /* have to worry about integer byte order */ modulosize = buffer[0]; modulosize |= buffer[1] << 8; modulosize |= buffer[2] << 16; modulosize |= buffer[3] << 24; finalsize = modulosize; estimated = 0; /* file size is known, not estimated */ } else if (memcmp(buffer, "\037\036", 2) == 0) /* PACK */ finalsize = 0; /* for most methods we can't determine final size */ else if (memcmp(buffer, "\037\235", 2) == 0) /* LZW */ finalsize = 0; /* for most methods we can't determine final size */ else if (memcmp(buffer, "\037\240", 2) == 0) /* LZH */ finalsize = 0; /* for most methods we can't determine final size */ #if HAVE_BZIP2 else if (memcmp(buffer, "BZ", 2) == 0) /* BZip2 */ finalsize = 0; /* for most methods we can't determine final size */ #endif else { /* not a compressed file; this should never happen */ fclose(diskfile); return(1); } if (finalsize == 0) /* estimate uncompressed file size */ { fseek(diskfile, 0, 2); /* move to end of the compressed file */ finalsize = ftell(diskfile); /* position = size of file */ finalsize = finalsize * 3; /* assume factor of 3 compression */ } fseek(diskfile, 0, 0); /* move back to beginning of file */ /* create a memory file big enough (hopefully) for the uncompressed file */ status = mem_createmem(finalsize, hdl); if (status && estimated) { /* memory allocation failed, so try a smaller estimated size */ finalsize = finalsize / 3; status = mem_createmem(finalsize, hdl); } if (status) { fclose(diskfile); ffpmsg("failed to create empty memory file (compress_open)"); return(status); } /* uncompress file into memory */ status = mem_uncompress2mem(filename, diskfile, *hdl); fclose(diskfile); if (status) { mem_close_free(*hdl); /* free up the memory */ ffpmsg("failed to uncompress file into memory (compress_open)"); return(status); } /* if we allocated too much memory initially, then free it */ if (*(memTable[*hdl].memsizeptr) > (( (size_t) memTable[*hdl].fitsfilesize) + 256L) ) { ptr = realloc(*(memTable[*hdl].memaddrptr), ((size_t) memTable[*hdl].fitsfilesize) ); if (!ptr) { ffpmsg("Failed to reduce size of allocated memory (compress_open)"); return(MEMORY_ALLOCATION); } *(memTable[*hdl].memaddrptr) = ptr; *(memTable[*hdl].memsizeptr) = (size_t) (memTable[*hdl].fitsfilesize); } return(0); } /*--------------------------------------------------------------------------*/ int mem_compress_stdin_open(char *filename, int rwmode, int *hdl) /* This routine reads the compressed input stream and creates an empty memory buffer, then calls mem_uncompress2mem. */ { int status; char *ptr; if (rwmode != READONLY) { ffpmsg( "cannot open compressed input stream with WRITE access (mem_compress_stdin_open)"); return(READONLY_FILE); } /* create a memory file for the uncompressed file */ status = mem_createmem(28800, hdl); if (status) { ffpmsg("failed to create empty memory file (compress_stdin_open)"); return(status); } /* uncompress file into memory */ status = mem_uncompress2mem(filename, stdin, *hdl); if (status) { mem_close_free(*hdl); /* free up the memory */ ffpmsg("failed to uncompress stdin into memory (compress_stdin_open)"); return(status); } /* if we allocated too much memory initially, then free it */ if (*(memTable[*hdl].memsizeptr) > (( (size_t) memTable[*hdl].fitsfilesize) + 256L) ) { ptr = realloc(*(memTable[*hdl].memaddrptr), ((size_t) memTable[*hdl].fitsfilesize) ); if (!ptr) { ffpmsg("Failed to reduce size of allocated memory (compress_stdin_open)"); return(MEMORY_ALLOCATION); } *(memTable[*hdl].memaddrptr) = ptr; *(memTable[*hdl].memsizeptr) = (size_t) (memTable[*hdl].fitsfilesize); } return(0); } /*--------------------------------------------------------------------------*/ int mem_iraf_open(char *filename, int rwmode, int *hdl) /* This routine creates an empty memory buffer, then calls iraf2mem to open the IRAF disk file and convert it to a FITS file in memeory. */ { int status; size_t filesize = 0; /* create a memory file with size = 0 for the FITS converted IRAF file */ status = mem_createmem(filesize, hdl); if (status) { ffpmsg("failed to create empty memory file (mem_iraf_open)"); return(status); } /* convert the iraf file into a FITS file in memory */ status = iraf2mem(filename, memTable[*hdl].memaddrptr, memTable[*hdl].memsizeptr, &filesize, &status); if (status) { mem_close_free(*hdl); /* free up the memory */ ffpmsg("failed to convert IRAF file into memory (mem_iraf_open)"); return(status); } memTable[*hdl].currentpos = 0; /* save starting position */ memTable[*hdl].fitsfilesize=filesize; /* and initial file size */ return(0); } /*--------------------------------------------------------------------------*/ int mem_rawfile_open(char *filename, int rwmode, int *hdl) /* This routine creates an empty memory buffer, writes a minimal image header, then copies the image data from the raw file into memory. It will byteswap the pixel values if the raw array is in little endian byte order. */ { FILE *diskfile; fitsfile *fptr; short *sptr; int status, endian, datatype, bytePerPix, naxis; long dim[5] = {1,1,1,1,1}, ii, nvals, offset = 0; size_t filesize = 0, datasize; char rootfile[FLEN_FILENAME], *cptr = 0, *cptr2 = 0; void *ptr; if (rwmode != READONLY) { ffpmsg( "cannot open raw binary file with WRITE access (mem_rawfile_open)"); ffpmsg(filename); return(READONLY_FILE); } cptr = strchr(filename, '['); /* search for opening bracket [ */ if (!cptr) { ffpmsg("binary file name missing '[' character (mem_rawfile_open)"); ffpmsg(filename); return(URL_PARSE_ERROR); } *rootfile = '\0'; strncat(rootfile, filename, cptr - filename); /* store the rootname */ cptr++; while (*cptr == ' ') cptr++; /* skip leading blanks */ /* Get the Data Type of the Image */ if (*cptr == 'b' || *cptr == 'B') { datatype = BYTE_IMG; bytePerPix = 1; } else if (*cptr == 'i' || *cptr == 'I') { datatype = SHORT_IMG; bytePerPix = 2; } else if (*cptr == 'u' || *cptr == 'U') { datatype = USHORT_IMG; bytePerPix = 2; } else if (*cptr == 'j' || *cptr == 'J') { datatype = LONG_IMG; bytePerPix = 4; } else if (*cptr == 'r' || *cptr == 'R' || *cptr == 'f' || *cptr == 'F') { datatype = FLOAT_IMG; bytePerPix = 4; } else if (*cptr == 'd' || *cptr == 'D') { datatype = DOUBLE_IMG; bytePerPix = 8; } else { ffpmsg("error in raw binary file datatype (mem_rawfile_open)"); ffpmsg(filename); return(URL_PARSE_ERROR); } cptr++; /* get Endian: Big or Little; default is same as the local machine */ if (*cptr == 'b' || *cptr == 'B') { endian = 0; cptr++; } else if (*cptr == 'l' || *cptr == 'L') { endian = 1; cptr++; } else endian = BYTESWAPPED; /* byteswapped machines are little endian */ /* read each dimension (up to 5) */ naxis = 1; dim[0] = strtol(cptr, &cptr2, 10); if (cptr2 && *cptr2 == ',') { naxis = 2; dim[1] = strtol(cptr2+1, &cptr, 10); if (cptr && *cptr == ',') { naxis = 3; dim[2] = strtol(cptr+1, &cptr2, 10); if (cptr2 && *cptr2 == ',') { naxis = 4; dim[3] = strtol(cptr2+1, &cptr, 10); if (cptr && *cptr == ',') naxis = 5; dim[4] = strtol(cptr+1, &cptr2, 10); } } } cptr = maxvalue(cptr, cptr2); if (*cptr == ':') /* read starting offset value */ offset = strtol(cptr+1, 0, 10); nvals = dim[0] * dim[1] * dim[2] * dim[3] * dim[4]; datasize = nvals * bytePerPix; filesize = nvals * bytePerPix + 2880; filesize = ((filesize - 1) / 2880 + 1) * 2880; /* open the raw binary disk file */ status = file_openfile(rootfile, READONLY, &diskfile); if (status) { ffpmsg("failed to open raw binary file (mem_rawfile_open)"); ffpmsg(rootfile); return(status); } /* create a memory file with corrct size for the FITS converted raw file */ status = mem_createmem(filesize, hdl); if (status) { ffpmsg("failed to create memory file (mem_rawfile_open)"); fclose(diskfile); return(status); } /* open this piece of memory as a new FITS file */ ffimem(&fptr, (void **) memTable[*hdl].memaddrptr, &filesize, 0, 0, &status); /* write the required header keywords */ ffcrim(fptr, datatype, naxis, dim, &status); /* close the FITS file, but keep the memory allocated */ ffclos(fptr, &status); if (status > 0) { ffpmsg("failed to write basic image header (mem_rawfile_open)"); fclose(diskfile); mem_close_free(*hdl); /* free up the memory */ return(status); } if (offset > 0) fseek(diskfile, offset, 0); /* offset to start of the data */ /* read the raw data into memory */ ptr = *memTable[*hdl].memaddrptr + 2880; if (fread((char *) ptr, 1, datasize, diskfile) != datasize) status = READ_ERROR; fclose(diskfile); /* close the raw binary disk file */ if (status) { mem_close_free(*hdl); /* free up the memory */ ffpmsg("failed to copy raw file data into memory (mem_rawfile_open)"); return(status); } if (datatype == USHORT_IMG) /* have to subtract 32768 from each unsigned */ { /* value to conform to FITS convention. More */ /* efficient way to do this is to just flip */ /* the most significant bit. */ sptr = (short *) ptr; if (endian == BYTESWAPPED) /* working with native format */ { for (ii = 0; ii < nvals; ii++, sptr++) { *sptr = ( *sptr ) ^ 0x8000; } } else /* pixels are byteswapped WRT the native format */ { for (ii = 0; ii < nvals; ii++, sptr++) { *sptr = ( *sptr ) ^ 0x80; } } } if (endian) /* swap the bytes if array is in little endian byte order */ { if (datatype == SHORT_IMG || datatype == USHORT_IMG) { ffswap2( (short *) ptr, nvals); } else if (datatype == LONG_IMG || datatype == FLOAT_IMG) { ffswap4( (INT32BIT *) ptr, nvals); } else if (datatype == DOUBLE_IMG) { ffswap8( (double *) ptr, nvals); } } memTable[*hdl].currentpos = 0; /* save starting position */ memTable[*hdl].fitsfilesize=filesize; /* and initial file size */ return(0); } /*--------------------------------------------------------------------------*/ int mem_uncompress2mem(char *filename, FILE *diskfile, int hdl) { /* lower level routine to uncompress a file into memory. The file has already been opened and the memory buffer has been allocated. */ size_t finalsize; int status; /* uncompress file into memory */ status = 0; if (strstr(filename, ".Z")) { zuncompress2mem(filename, diskfile, memTable[hdl].memaddrptr, /* pointer to memory address */ memTable[hdl].memsizeptr, /* pointer to size of memory */ realloc, /* reallocation function */ &finalsize, &status); /* returned file size nd status*/ #if HAVE_BZIP2 } else if (strstr(filename, ".bz2")) { bzip2uncompress2mem(filename, diskfile, hdl, &finalsize, &status); #endif } else { uncompress2mem(filename, diskfile, memTable[hdl].memaddrptr, /* pointer to memory address */ memTable[hdl].memsizeptr, /* pointer to size of memory */ realloc, /* reallocation function */ &finalsize, &status); /* returned file size nd status*/ } memTable[hdl].currentpos = 0; /* save starting position */ memTable[hdl].fitsfilesize=finalsize; /* and initial file size */ return status; } /*--------------------------------------------------------------------------*/ int mem_size(int handle, LONGLONG *filesize) /* return the size of the file; only called when the file is first opened */ { *filesize = memTable[handle].fitsfilesize; return(0); } /*--------------------------------------------------------------------------*/ int mem_close_free(int handle) /* close the file and free the memory. */ { free( *(memTable[handle].memaddrptr) ); memTable[handle].memaddrptr = 0; memTable[handle].memaddr = 0; return(0); } /*--------------------------------------------------------------------------*/ int mem_close_keep(int handle) /* close the memory file but do not free the memory. */ { memTable[handle].memaddrptr = 0; memTable[handle].memaddr = 0; return(0); } /*--------------------------------------------------------------------------*/ int mem_close_comp(int handle) /* compress the memory file, writing it out to the fileptr (which might be stdout) */ { int status = 0; size_t compsize; /* compress file in memory to a .gz disk file */ if(compress2file_from_mem(memTable[handle].memaddr, (size_t) (memTable[handle].fitsfilesize), memTable[handle].fileptr, &compsize, &status ) ) { ffpmsg("failed to copy memory file to file (mem_close_comp)"); status = WRITE_ERROR; } free( memTable[handle].memaddr ); /* free the memory */ memTable[handle].memaddrptr = 0; memTable[handle].memaddr = 0; /* close the compressed disk file (except if it is 'stdout' */ if (memTable[handle].fileptr != stdout) fclose(memTable[handle].fileptr); return(status); } /*--------------------------------------------------------------------------*/ int mem_seek(int handle, LONGLONG offset) /* seek to position relative to start of the file. */ { if (offset > memTable[handle].fitsfilesize ) return(END_OF_FILE); memTable[handle].currentpos = offset; return(0); } /*--------------------------------------------------------------------------*/ int mem_read(int hdl, void *buffer, long nbytes) /* read bytes from the current position in the file */ { if (memTable[hdl].currentpos + nbytes > memTable[hdl].fitsfilesize) return(END_OF_FILE); memcpy(buffer, *(memTable[hdl].memaddrptr) + memTable[hdl].currentpos, nbytes); memTable[hdl].currentpos += nbytes; return(0); } /*--------------------------------------------------------------------------*/ int mem_write(int hdl, void *buffer, long nbytes) /* write bytes at the current position in the file */ { size_t newsize; char *ptr; if ((size_t) (memTable[hdl].currentpos + nbytes) > *(memTable[hdl].memsizeptr) ) { if (!(memTable[hdl].mem_realloc)) { ffpmsg("realloc function not defined (mem_write)"); return(WRITE_ERROR); } /* Attempt to reallocate additional memory: the memory buffer size is incremented by the larger of: 1 FITS block (2880 bytes) or the defined 'deltasize' parameter */ newsize = maxvalue( (size_t) (((memTable[hdl].currentpos + nbytes - 1) / 2880) + 1) * 2880, *(memTable[hdl].memsizeptr) + memTable[hdl].deltasize); /* call the realloc function */ ptr = (memTable[hdl].mem_realloc)( *(memTable[hdl].memaddrptr), newsize); if (!ptr) { ffpmsg("Failed to reallocate memory (mem_write)"); return(MEMORY_ALLOCATION); } *(memTable[hdl].memaddrptr) = ptr; *(memTable[hdl].memsizeptr) = newsize; } /* now copy the bytes from the buffer into memory */ memcpy( *(memTable[hdl].memaddrptr) + memTable[hdl].currentpos, buffer, nbytes); memTable[hdl].currentpos += nbytes; memTable[hdl].fitsfilesize = maxvalue(memTable[hdl].fitsfilesize, memTable[hdl].currentpos); return(0); } #if HAVE_BZIP2 void bzip2uncompress2mem(char *filename, FILE *diskfile, int hdl, size_t* filesize, int* status) { BZFILE* b; int bzerror; char buf[8192]; size_t total_read = 0; char* errormsg = NULL; *filesize = 0; *status = 0; b = BZ2_bzReadOpen(&bzerror, diskfile, 0, 0, NULL, 0); if (bzerror != BZ_OK) { BZ2_bzReadClose(&bzerror, b); if (bzerror == BZ_MEM_ERROR) ffpmsg("failed to open a bzip2 file: out of memory\n"); else if (bzerror == BZ_CONFIG_ERROR) ffpmsg("failed to open a bzip2 file: miscompiled bzip2 library\n"); else if (bzerror == BZ_IO_ERROR) ffpmsg("failed to open a bzip2 file: I/O error"); else ffpmsg("failed to open a bzip2 file"); *status = READ_ERROR; return; } bzerror = BZ_OK; while (bzerror == BZ_OK) { int nread; nread = BZ2_bzRead(&bzerror, b, buf, sizeof(buf)); if (bzerror == BZ_OK || bzerror == BZ_STREAM_END) { *status = mem_write(hdl, buf, nread); if (*status) { BZ2_bzReadClose(&bzerror, b); if (*status == MEMORY_ALLOCATION) ffpmsg("Failed to reallocate memory while uncompressing bzip2 file"); return; } total_read += nread; } else { if (bzerror == BZ_IO_ERROR) errormsg = "failed to read bzip2 file: I/O error"; else if (bzerror == BZ_UNEXPECTED_EOF) errormsg = "failed to read bzip2 file: unexpected end-of-file"; else if (bzerror == BZ_DATA_ERROR) errormsg = "failed to read bzip2 file: data integrity error"; else if (bzerror == BZ_MEM_ERROR) errormsg = "failed to read bzip2 file: insufficient memory"; } } BZ2_bzReadClose(&bzerror, b); if (bzerror != BZ_OK) { if (errormsg) ffpmsg(errormsg); else ffpmsg("failure closing bzip2 file after reading\n"); *status = READ_ERROR; return; } *filesize = total_read; } #endif cfitsio/drvrnet.c0000644000225700000360000030103013246025103013625 0ustar cagordonlhea/* This file, drvrhttp.c contains driver routines for http, ftp and root files. */ /* This file was written by Bruce O'Neel at the ISDC, Switzerland */ /* The FITSIO software is maintained by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ /* Notes on the drivers: The ftp driver uses passive mode exclusivly. If your remote system can't deal with passive mode then it'll fail. Since Netscape Navigator uses passive mode as well there shouldn't be too many ftp servers which have problems. The http driver works properly with 301 and 302 redirects. For many more gory details see http://www.w3c.org/Protocols/rfc2068/rfc2068. The only catch to the 301/302 redirects is that they have to redirect to another http:// url. If not, things would have to change a lot in cfitsio and this was thought to be too difficult. Redirects look like 301 Moved Permanently

Moved Permanently

The document has moved here.

This redirect was from apache 1.2.5 but most of the other servers produce something very similiar. The parser for the redirects finds the first anchor tag in the body and goes there. If that wasn't what was intended by the remote system then hopefully the error stack, which includes notes about the redirect will help the user fix the problem. **************************************************************** Note added in 2017: The redirect format shown above is actually preceded by 2 lines that look like HTTP/1.1 302 Found LOCATION: http://heasarc.gsfc.nasa.gov/FTP/software/ftools/release/other/image.fits.gz The CFITSIO parser now looks for the "Location:" string, not the html tag. **************************************************************** Root protocal doesn't have any real docs, so, the emperical docs are as follows. First, you must use a slightly modified rootd server. The modifications include implimentation of the stat command which returns the size of the remote file. Without that it's impossible for cfitsio to work properly since fitsfiles don't include any information about the size of the files in the headers. The rootd server closes the connections on any errors, including reading beyond the end of the file or seeking beyond the end of the file. The rootd:// driver doesn't reopen a closed connection, if the connection is closed you're pretty much done. The messages are of the form All binary information is transfered in network format, so use htonl and ntohl to convert back and forth. :== 4 byte length, in network format, the len doesn't include the length of :== one of the message opcodes below, 4 bytes, network format :== depends on opcode The response is of the same form with the same opcode sent. Success is indicated by being 0. Root is a NFSish protocol where each read/write includes the byte offset to read or write to. As a result, seeks will always succeed in the driver even if they would cause a fatal error when you try to read because you're beyond the end of the file. There is file locking on the host such that you need to possibly create /usr/tmp/rootdtab on the host system. There is one file per socket connection, though the rootd daemon can support multiple files open at once. The messages are sent in the following order: ROOTD_USER - user name, is the user name, trailing null is sent though it's not required it seems. A ROOTD_AUTH message is returned with any sort of error meaning that the user name is wrong. ROOTD_PASS - password, ones complemented, stored in . Once again the trailing null is sent. Once again a ROOTD_AUTH message is returned ROOTD_OPEN - includes filename and one of {create|update|read} as the file mode. ~ seems to be dealt with as the username's login directory. A ROOTD_OPEN message is returned. Once the file is opened any of the following can be sent: ROOTD_STAT - file status and size returns a message where is the file length in bytes ROOTD_FLUSH - flushes the file, not sure this has any real effect on the daemon since the daemon uses open/read/write/close rather than the buffered fopen/fread/fwrite/fclose. ROOTD_GET - on send includes a text message of offset and length to get. Return is a status message first with a status value, then, the raw bytes for the length that you requested. It's an error to seek or read past the end of the file, and, the rootd daemon exits and won't respond anymore. Ie, don't do this. ROOTD_PUT - on send includes a text message of offset and length to put. Then send the raw bytes you want to write. Then recieve a status message When you are finished then you send the message: ROOTD_CLOSE - closes the file Once the file is closed then the socket is closed. Revision 1.56 2000/01/04 11:58:31 oneel Updates so that compressed network files are dealt with regardless of their file names and/or mime types. Revision 1.55 2000/01/04 10:52:40 oneel cfitsio 2.034 Revision 1.51 1999/08/10 12:13:40 oneel Make the http code a bit less picky about the types of files it uncompresses. Now it also uncompresses files which end in .Z or .gz. Revision 1.50 1999/08/04 12:38:46 oneel Don's 2.0.32 patch with dal 1.3 Revision 1.39 1998/12/02 15:31:33 oneel Updates to drvrnet.c so that less compiler warnings would be generated. Fixes the signal handling. Revision 1.38 1998/11/23 10:03:24 oneel Added in a useragent string, as suggested by: Tim Kimball Data Systems Division kimball@stsci.edu 410-338-4417 Space Telescope Science Institute http://www.stsci.edu/~kimball/ 3700 San Martin Drive http://archive.stsci.edu/ Baltimore MD 21218 USA http://faxafloi.stsci.edu:4547/ */ #ifdef HAVE_NET_SERVICES #include #include #include #include #include #include #include #include #include #include #include #ifdef CFITSIO_HAVE_CURL #include #endif #if defined(unix) || defined(__unix__) || defined(__unix) || defined(HAVE_UNISTD_H) #include #endif #include #include #include "fitsio2.h" static jmp_buf env; /* holds the jump buffer for setjmp/longjmp pairs */ static void signal_handler(int sig); /* Network routine error codes */ #define NET_OK 0 #define NOT_INET_ADDRESS -1000 #define UNKNOWN_INET_HOST -1001 #define CONNECTION_ERROR -1002 /* Network routine constants */ #define NET_DEFAULT 0 #define NET_OOB 1 #define NET_PEEK 2 #define NETTIMEOUT 180 /* in secs */ /* local defines and variables */ #define MAXLEN 1200 #define SHORTLEN 100 static char netoutfile[MAXLEN]; #define ROOTD_USER 2000 /*user id follows */ #define ROOTD_PASS 2001 /*passwd follows */ #define ROOTD_AUTH 2002 /*authorization status (to client) */ #define ROOTD_FSTAT 2003 /*filename follows */ #define ROOTD_OPEN 2004 /*filename follows + mode */ #define ROOTD_PUT 2005 /*offset, number of bytes and buffer */ #define ROOTD_GET 2006 /*offset, number of bytes */ #define ROOTD_FLUSH 2007 /*flush file */ #define ROOTD_CLOSE 2008 /*close file */ #define ROOTD_STAT 2009 /*return rootd statistics */ #define ROOTD_ACK 2010 /*acknowledgement (all OK) */ #define ROOTD_ERR 2011 /*error code and message follow */ typedef struct /* structure containing disk file structure */ { int sock; LONGLONG currentpos; } rootdriver; typedef struct /* simple mem struct for receiving files from curl */ { char *memory; size_t size; } curlmembuf; static rootdriver handleTable[NMAXFILES]; /* allocate diskfile handle tables */ /* static prototypes */ static int NET_TcpConnect(char *hostname, int port); static int NET_SendRaw(int sock, const void *buf, int length, int opt); static int NET_RecvRaw(int sock, void *buffer, int length); static int NET_ParseUrl(const char *url, char *proto, char *host, int *port, char *fn); static int CreateSocketAddress(struct sockaddr_in *sockaddrPtr, char *host,int port); static int ftp_status(FILE *ftp, char *statusstr); static int http_open_network(char *url, FILE **httpfile, char *contentencoding, int *contentlength); static int https_open_network(char *filename, curlmembuf* buffer); static int ftp_open_network(char *url, FILE **ftpfile, FILE **command, int *sock); static int ftp_file_exist(char *url); static int root_send_buffer(int sock, int op, char *buffer, int buflen); static int root_recv_buffer(int sock, int *op, char *buffer,int buflen); static int root_openfile(char *filename, char *rwmode, int *sock); static int encode64(unsigned s_len, char *src, unsigned d_len, char *dst); static size_t curlToMemCallback(void *buffer, size_t size, size_t nmemb, void *userp); /***************************/ /* Static variables */ static int closehttpfile; static int closememfile; static int closefdiskfile; static int closediskfile; static int closefile; static int closeoutfile; static int closecommandfile; static int closeftpfile; static FILE *diskfile; static FILE *outfile; static int curl_verbose=0; /*--------------------------------------------------------------------------*/ /* This creates a memory file handle with a copy of the URL in filename. The file is uncompressed if necessary */ int http_open(char *filename, int rwmode, int *handle) { FILE *httpfile; char contentencoding[SHORTLEN]; char errorstr[MAXLEN]; char recbuf[MAXLEN]; long len; int contentlength; int status; char firstchar; closehttpfile = 0; closememfile = 0; /* don't do r/w files */ if (rwmode != 0) { ffpmsg("Can't open http:// type file with READWRITE access"); ffpmsg(" Specify an outfile for r/w access (http_open)"); goto error; } /* do the signal handler bits */ if (setjmp(env) != 0) { /* feels like the second time */ /* this means something bad happened */ ffpmsg("Timeout (http_open)"); goto error; } (void) signal(SIGALRM, signal_handler); /* Open the network connection */ if (http_open_network(filename,&httpfile,contentencoding, &contentlength)) { alarm(0); ffpmsg("Unable to open http file (http_open):"); ffpmsg(filename); goto error; } closehttpfile++; /* Create the memory file */ if ((status = mem_create(filename,handle))) { ffpmsg("Unable to create memory file (http_open)"); goto error; } closememfile++; /* Now, what do we do with the file */ /* Check to see what the first character is */ firstchar = fgetc(httpfile); ungetc(firstchar,httpfile); if (!strcmp(contentencoding,"x-gzip") || !strcmp(contentencoding,"x-compress") || strstr(filename,".gz") || strstr(filename,".Z") || ('\037' == firstchar)) { /* do the compress dance, which is the same as the gzip dance */ /* Using the cfitsio routine */ status = 0; /* Ok, this is a tough case, let's be arbritary and say 10*NETTIMEOUT, Given the choices for nettimeout above they'll probaby ^C before, but it's always worth a shot*/ alarm(NETTIMEOUT*10); status = mem_uncompress2mem(filename, httpfile, *handle); alarm(0); if (status) { ffpmsg("Error writing compressed memory file (http_open)"); ffpmsg(filename); goto error; } } else { /* It's not compressed, bad choice, but we'll copy it anyway */ if (contentlength % 2880) { snprintf(errorstr,MAXLEN,"Content-Length not a multiple of 2880 (http_open) %d", contentlength); ffpmsg(errorstr); } /* write a memory file */ alarm(NETTIMEOUT); while(0 != (len = fread(recbuf,1,MAXLEN,httpfile))) { alarm(0); /* cancel alarm */ status = mem_write(*handle,recbuf,len); if (status) { ffpmsg("Error copying http file into memory (http_open)"); ffpmsg(filename); goto error; } alarm(NETTIMEOUT); /* rearm the alarm */ } } fclose(httpfile); signal(SIGALRM, SIG_DFL); alarm(0); return mem_seek(*handle,0); error: alarm(0); /* clear it */ if (closehttpfile) { fclose(httpfile); } if (closememfile) { mem_close_free(*handle); } signal(SIGALRM, SIG_DFL); return (FILE_NOT_OPENED); } /*--------------------------------------------------------------------------*/ /* This creates a memory file handle with a copy of the URL in filename. The file must be compressed and is copied (still compressed) to disk first. The compressed disk file is then uncompressed into memory (READONLY). */ int http_compress_open(char *url, int rwmode, int *handle) { FILE *httpfile; char contentencoding[SHORTLEN]; char recbuf[MAXLEN]; long len; int contentlength; int ii, flen, status; char firstchar; closehttpfile = 0; closediskfile = 0; closefdiskfile = 0; closememfile = 0; flen = strlen(netoutfile); if (!flen) { /* cfileio made a mistake, should set the netoufile first otherwise we don't know where to write the output file */ ffpmsg ("Output file not set, shouldn't have happened (http_compress_open)"); goto error; } if (rwmode != 0) { ffpmsg("Can't open compressed http:// type file with READWRITE access"); ffpmsg(" Specify an UNCOMPRESSED outfile (http_compress_open)"); goto error; } /* do the signal handler bits */ if (setjmp(env) != 0) { /* feels like the second time */ /* this means something bad happened */ ffpmsg("Timeout (http_open)"); goto error; } signal(SIGALRM, signal_handler); /* Open the http connectin */ alarm(NETTIMEOUT); if ((status = http_open_network(url,&httpfile,contentencoding, &contentlength))) { alarm(0); ffpmsg("Unable to open http file (http_compress_open)"); ffpmsg(url); goto error; } closehttpfile++; /* Better be compressed */ firstchar = fgetc(httpfile); ungetc(firstchar,httpfile); if (!strcmp(contentencoding,"x-gzip") || !strcmp(contentencoding,"x-compress") || ('\037' == firstchar)) { if (*netoutfile == '!') { /* user wants to clobber file, if it already exists */ for (ii = 0; ii < flen; ii++) netoutfile[ii] = netoutfile[ii + 1]; /* remove '!' */ status = file_remove(netoutfile); } /* Create the new file */ if ((status = file_create(netoutfile,handle))) { ffpmsg("Unable to create output disk file (http_compress_open):"); ffpmsg(netoutfile); goto error; } closediskfile++; /* write a file */ alarm(NETTIMEOUT); while(0 != (len = fread(recbuf,1,MAXLEN,httpfile))) { alarm(0); status = file_write(*handle,recbuf,len); if (status) { ffpmsg("Error writing disk file (http_compres_open)"); ffpmsg(netoutfile); goto error; } alarm(NETTIMEOUT); } file_close(*handle); fclose(httpfile); closehttpfile--; closediskfile--; /* File is on disk, let's uncompress it into memory */ if (NULL == (diskfile = fopen(netoutfile,"r"))) { ffpmsg("Unable to reopen disk file (http_compress_open)"); ffpmsg(netoutfile); goto error; } closefdiskfile++; /* Create the memory handle to hold it */ if ((status = mem_create(url,handle))) { ffpmsg("Unable to create memory file (http_compress_open)"); goto error; } closememfile++; /* Uncompress it */ status = 0; status = mem_uncompress2mem(url,diskfile,*handle); fclose(diskfile); closefdiskfile--; if (status) { ffpmsg("Error uncompressing disk file to memory (http_compress_open)"); ffpmsg(netoutfile); goto error; } } else { /* Opps, this should not have happened */ ffpmsg("Can only have compressed files here (http_compress_open)"); goto error; } signal(SIGALRM, SIG_DFL); alarm(0); return mem_seek(*handle,0); error: alarm(0); /* clear it */ if (closehttpfile) { fclose(httpfile); } if (closefdiskfile) { fclose(diskfile); } if (closememfile) { mem_close_free(*handle); } if (closediskfile) { file_close(*handle); } signal(SIGALRM, SIG_DFL); return (FILE_NOT_OPENED); } /*--------------------------------------------------------------------------*/ /* This creates a file handle with a copy of the URL in filename. The http file is copied to disk first. If it's compressed then it is uncompressed when copying to the disk */ int http_file_open(char *url, int rwmode, int *handle) { FILE *httpfile; char contentencoding[SHORTLEN]; char errorstr[MAXLEN]; char recbuf[MAXLEN]; long len; int contentlength; int ii, flen, status; char firstchar; /* Check if output file is actually a memory file */ if (!strncmp(netoutfile, "mem:", 4) ) { /* allow the memory file to be opened with write access */ return( http_open(url, READONLY, handle) ); } closehttpfile = 0; closefile = 0; closeoutfile = 0; flen = strlen(netoutfile); if (!flen) { /* cfileio made a mistake, we need to know where to write the file */ ffpmsg("Output file not set, shouldn't have happened (http_file_open)"); return (FILE_NOT_OPENED); } /* do the signal handler bits */ if (setjmp(env) != 0) { /* feels like the second time */ /* this means something bad happened */ ffpmsg("Timeout (http_open)"); goto error; } signal(SIGALRM, signal_handler); /* Open the network connection */ alarm(NETTIMEOUT); if ((status = http_open_network(url,&httpfile,contentencoding, &contentlength))) { alarm(0); ffpmsg("Unable to open http file (http_file_open)"); ffpmsg(url); goto error; } closehttpfile++; if (*netoutfile == '!') { /* user wants to clobber disk file, if it already exists */ for (ii = 0; ii < flen; ii++) netoutfile[ii] = netoutfile[ii + 1]; /* remove '!' */ status = file_remove(netoutfile); } firstchar = fgetc(httpfile); ungetc(firstchar,httpfile); if (!strcmp(contentencoding,"x-gzip") || !strcmp(contentencoding,"x-compress") || ('\037' == firstchar)) { /* to make this more cfitsioish we use the file driver calls to create the disk file */ /* Create the output file */ if ((status = file_create(netoutfile,handle))) { ffpmsg("Unable to create output file (http_file_open)"); ffpmsg(netoutfile); goto error; } file_close(*handle); if (NULL == (outfile = fopen(netoutfile,"w"))) { ffpmsg("Unable to reopen the output file (http_file_open)"); ffpmsg(netoutfile); goto error; } closeoutfile++; status = 0; /* Ok, this is a tough case, let's be arbritary and say 10*NETTIMEOUT, Given the choices for nettimeout above they'll probaby ^C before, but it's always worth a shot*/ alarm(NETTIMEOUT*10); status = uncompress2file(url,httpfile,outfile,&status); alarm(0); if (status) { ffpmsg("Error uncompressing http file to disk file (http_file_open)"); ffpmsg(url); ffpmsg(netoutfile); goto error; } fclose(outfile); closeoutfile--; } else { /* Create the output file */ if ((status = file_create(netoutfile,handle))) { ffpmsg("Unable to create output file (http_file_open)"); ffpmsg(netoutfile); goto error; } /* Give a warning message. This could just be bad padding at the end so don't treat it like an error. */ closefile++; if (contentlength % 2880) { snprintf(errorstr, MAXLEN, "Content-Length not a multiple of 2880 (http_file_open) %d", contentlength); ffpmsg(errorstr); } /* write a file */ alarm(NETTIMEOUT); while(0 != (len = fread(recbuf,1,MAXLEN,httpfile))) { alarm(0); status = file_write(*handle,recbuf,len); if (status) { ffpmsg("Error copying http file to disk file (http_file_open)"); ffpmsg(url); ffpmsg(netoutfile); goto error; } } file_close(*handle); closefile--; } fclose(httpfile); closehttpfile--; signal(SIGALRM, SIG_DFL); alarm(0); return file_open(netoutfile,rwmode,handle); error: alarm(0); /* clear it */ if (closehttpfile) { fclose(httpfile); } if (closeoutfile) { fclose(outfile); } if (closefile) { file_close(*handle); } signal(SIGALRM, SIG_DFL); return (FILE_NOT_OPENED); } /*--------------------------------------------------------------------------*/ /* This is the guts of the code to get a file via http. url is the input url httpfile is set to be the file connected to the socket which you can read the file from contentencoding is the mime type of the file, returned if the http server returns it contentlength is the length of the file, returned if the http server returns it */ static int http_open_network(char *url, FILE **httpfile, char *contentencoding, int *contentlength) { int status; int sock; int tmpint; char recbuf[MAXLEN]; char tmpstr[MAXLEN]; char tmpstr1[SHORTLEN]; char tmpstr2[MAXLEN]; char errorstr[MAXLEN]; char proto[SHORTLEN]; char host[SHORTLEN]; char userpass[MAXLEN]; char fn[MAXLEN]; char turl[MAXLEN]; char *scratchstr; char *scratchstr2; char *saveptr; int port; float version; char pproto[SHORTLEN]; char phost[SHORTLEN]; /* address of the proxy server */ int pport; /* port number of the proxy server */ char pfn[MAXLEN]; char *proxy; /* URL of the proxy server */ /* Parse the URL apart again */ strcpy(turl,"http://"); strncat(turl,url,MAXLEN - 8); if (NET_ParseUrl(turl,proto,host,&port,fn)) { snprintf(errorstr,MAXLEN,"URL Parse Error (http_open) %s",url); ffpmsg(errorstr); return (FILE_NOT_OPENED); } /* Do we have a user:password combo ? */ strcpy(userpass, url); if ((scratchstr = strchr(userpass, '@')) != NULL) { *scratchstr = '\0'; } else { strcpy(userpass, ""); } /* Ph. Prugniel 2003/04/03 Are we using a proxy? We use a proxy if the environment variable "http_proxy" is set to an address, eg. http://wwwcache.nottingham.ac.uk:3128 ("http_proxy" is also used by wget) */ proxy = getenv("http_proxy"); /* Connect to the remote host */ if (proxy) { if (NET_ParseUrl(proxy,pproto,phost,&pport,pfn)) { snprintf(errorstr,MAXLEN,"URL Parse Error (http_open) %s",proxy); ffpmsg(errorstr); return (FILE_NOT_OPENED); } sock = NET_TcpConnect(phost,pport); } else { sock = NET_TcpConnect(host,port); } if (sock < 0) { if (proxy) { ffpmsg("Couldn't connect to host via proxy server (http_open_network)"); ffpmsg(proxy); } return (FILE_NOT_OPENED); } /* Make the socket a stdio file */ if (NULL == (*httpfile = fdopen(sock,"r"))) { ffpmsg ("fdopen failed to convert socket to file (http_open_network)"); close(sock); return (FILE_NOT_OPENED); } /* Send the GET request to the remote server */ /* Ph. Prugniel 2003/04/03 One must add the Host: command because of HTTP 1.1 servers (ie. virtual hosts) */ if (proxy) { snprintf(tmpstr,MAXLEN,"GET http://%s:%-d%s HTTP/1.0\r\n",host,port,fn); } else { snprintf(tmpstr,MAXLEN,"GET %s HTTP/1.0\r\n",fn); } if (strcmp(userpass, "")) { encode64(strlen(userpass), userpass, MAXLEN, tmpstr2); snprintf(tmpstr1, SHORTLEN,"Authorization: Basic %s\r\n", tmpstr2); if (strlen(tmpstr) + strlen(tmpstr1) > MAXLEN - 1) return (FILE_NOT_OPENED); strcat(tmpstr,tmpstr1); } /* snprintf(tmpstr1,SHORTLEN,"User-Agent: HEASARC/CFITSIO/%-8.3f\r\n",ffvers(&version)); */ /* snprintf(tmpstr1,SHORTLEN,"User-Agent: CFITSIO/HEASARC/%-8.3f\r\n",ffvers(&version)); */ snprintf(tmpstr1,SHORTLEN,"User-Agent: FITSIO/HEASARC/%-8.3f\r\n",ffvers(&version)); if (strlen(tmpstr) + strlen(tmpstr1) > MAXLEN - 1) return (FILE_NOT_OPENED); strcat(tmpstr,tmpstr1); /* HTTP 1.1 servers require the following 'Host: ' string */ snprintf(tmpstr1,SHORTLEN,"Host: %s:%-d\r\n\r\n",host,port); if (strlen(tmpstr) + strlen(tmpstr1) > MAXLEN - 1) return (FILE_NOT_OPENED); strcat(tmpstr,tmpstr1); status = NET_SendRaw(sock,tmpstr,strlen(tmpstr),NET_DEFAULT); /* read the header */ if (!(fgets(recbuf,MAXLEN,*httpfile))) { snprintf (errorstr,MAXLEN,"http header short (http_open_network) %s",recbuf); ffpmsg(errorstr); fclose(*httpfile); return (FILE_NOT_OPENED); } *contentlength = 0; contentencoding[0] = '\0'; /* Our choices are 200, ok, 302, temporary redirect, or 301 perm redirect */ sscanf(recbuf,"%s %d",tmpstr,&status); if (status != 200){ if (status == 301 || status == 302) { /* got a redirect */ /* if (status == 302) { ffpmsg("Note: Web server replied with a temporary redirect from"); } else { ffpmsg("Note: Web server replied with a redirect from"); } ffpmsg(turl); */ /* now, let's not write the most sophisticated parser here */ while (fgets(recbuf,MAXLEN,*httpfile)) { scratchstr = strstr(recbuf,"Location: "); if (scratchstr != NULL) { /* Ok, we found the Location line which gives the redirected URL */ /* skip the "Location: " charactrers */ scratchstr += 10; /* strip off any end-of-line characters */ tmpint = strlen(scratchstr); if (scratchstr[tmpint-1] == '\r') scratchstr[tmpint-1] = '\0'; tmpint = strlen(scratchstr); if (scratchstr[tmpint-1] == '\n') scratchstr[tmpint-1] = '\0'; tmpint = strlen(scratchstr); if (scratchstr[tmpint-1] == '\r') scratchstr[tmpint-1] = '\0'; /* ffpmsg("to:"); ffpmsg(scratchstr); ffpmsg(" "); */ scratchstr2 = strstr(scratchstr,"http://"); if (scratchstr2 != NULL) { /* Ok, we found the HTTP redirection is to another HTTP URL. */ /* We can handle this case directly, here */ /* skip the "http://" characters */ scratchstr2 += 7; strcpy(turl, scratchstr2); fclose (*httpfile); /* note the recursive call to itself */ return http_open_network(turl,httpfile,contentencoding,contentlength); } /* It was not a HTTP to HTTP redirection, so see if it HTTP to FTP */ scratchstr2 = strstr(scratchstr,"ftp://"); if (scratchstr2 != NULL) { /* Ok, we found the HTTP redirection is to a FTP URL. */ /* skip the "ftp://" characters */ scratchstr2 += 6; /* return the new URL string, and set contentencoding to "ftp" as a flag to the http_checkfile routine */ strcpy(url, scratchstr2); strcpy(contentencoding,"ftp://"); fclose (*httpfile); return 0; } /* Now check for HTTP to HTTPS redirection. */ scratchstr2 = strstr(scratchstr,"https://"); if (scratchstr2 != NULL) { /* skip the "https://" characters */ scratchstr2 += 8; /* return the new URL string, and set contentencoding to "https" as a flag to the http_checkfile routine */ strcpy(url, scratchstr2); strcpy(contentencoding,"https://"); fclose(*httpfile); return 0; } } } /* if we get here then we couldnt' decide the redirect */ ffpmsg("but we were unable to find the redirected url in the servers response"); } /* error. could not open the http file */ fclose(*httpfile); return (FILE_NOT_OPENED); } /* from here the first word holds the keyword we want */ /* so, read the rest of the header */ while (fgets(recbuf,MAXLEN,*httpfile)) { /* Blank line ends the header */ if (*recbuf == '\r') break; if (strlen(recbuf) > 3) { recbuf[strlen(recbuf)-1] = '\0'; recbuf[strlen(recbuf)-1] = '\0'; } sscanf(recbuf,"%s %d",tmpstr,&tmpint); /* Did we get a content-length header ? */ if (!strcmp(tmpstr,"Content-Length:")) { *contentlength = tmpint; } /* Did we get the content-encoding header ? */ if (!strcmp(tmpstr,"Content-Encoding:")) { if (NULL != (scratchstr = strstr(recbuf,":"))) { /* Found the : */ scratchstr++; /* skip the : */ scratchstr++; /* skip the extra space */ strcpy(contentencoding,scratchstr); } } } /* we're done, so return */ return 0; } /*--------------------------------------------------------------------------*/ /* This creates a memory file handle with a copy of the URL in filename. The curl library called from https_open_network will perform file uncompression if necessary. */ int https_open(char *filename, int rwmode, int *handle) { curlmembuf inmem; char errStr[MAXLEN]; int status=0; /* don't do r/w files */ if (rwmode != 0) { ffpmsg("Can't open https:// type file with READWRITE access"); ffpmsg(" Specify an outfile for r/w access (https_open)"); return (FILE_NOT_OPENED); } inmem.memory=0; inmem.size=0; if (setjmp(env) != 0) { alarm(0); signal(SIGALRM, SIG_DFL); ffpmsg("Timeout (https_open)"); free(inmem.memory); return (FILE_NOT_OPENED); } signal(SIGALRM, signal_handler); alarm(NETTIMEOUT); if (https_open_network(filename, &inmem)) { alarm(0); signal(SIGALRM, SIG_DFL); ffpmsg("Unable to read https file into memory (https_open)"); free(inmem.memory); return (FILE_NOT_OPENED); } alarm(0); signal(SIGALRM, SIG_DFL); /* We now have the file transfered from the https server into the inmem.memory buffer. Now transfer that into a FITS memory file. */ if ((status = mem_create(filename, handle))) { ffpmsg("Unable to create memory file (https_open)"); free(inmem.memory); return (FILE_NOT_OPENED); } if (inmem.size % 2880) { snprintf(errStr,MAXLEN,"Content-Length not a multiple of 2880 (https_open) %u", inmem.size); ffpmsg(errStr); } status = mem_write(*handle, inmem.memory, inmem.size); if (status) { ffpmsg("Error copying https file into memory (https_open)"); ffpmsg(filename); free(inmem.memory); mem_close_free(*handle); return (FILE_NOT_OPENED); } free(inmem.memory); return mem_seek(*handle, 0); } /*--------------------------------------------------------------------------*/ int https_file_open(char *filename, int rwmode, int *handle) { int ii, flen; char errStr[MAXLEN]; curlmembuf inmem; /* Check if output file is actually a memory file */ if (!strncmp(netoutfile, "mem:", 4) ) { /* allow the memory file to be opened with write access */ return( https_open(filename, READONLY, handle) ); } flen = strlen(netoutfile); if (!flen) { /* cfileio made a mistake, we need to know where to write the file */ ffpmsg("Output file not set, shouldn't have happened (https_file_open)"); return (FILE_NOT_OPENED); } inmem.memory=0; inmem.size=0; if (setjmp(env) != 0) { alarm(0); signal(SIGALRM, SIG_DFL); ffpmsg("Timeout (https_file_open)"); free(inmem.memory); return (FILE_NOT_OPENED); } signal(SIGALRM, signal_handler); alarm(NETTIMEOUT); if (https_open_network(filename, &inmem)) { alarm(0); signal(SIGALRM, SIG_DFL); ffpmsg("Unable to read https file into memory (https_file_open)"); free(inmem.memory); return (FILE_NOT_OPENED); } alarm(0); signal(SIGALRM, SIG_DFL); if (*netoutfile == '!') { /* user wants to clobber disk file, if it already exists */ for (ii = 0; ii < flen; ii++) netoutfile[ii] = netoutfile[ii + 1]; /* remove '!' */ file_remove(netoutfile); } /* Create the output file */ if (file_create(netoutfile,handle)) { ffpmsg("Unable to create output file (https_file_open)"); ffpmsg(netoutfile); free(inmem.memory); return (FILE_NOT_OPENED); } if (inmem.size % 2880) { snprintf(errStr, MAXLEN, "Content-Length not a multiple of 2880 (https_file_open) %d", inmem.size); ffpmsg(errStr); } if (file_write(*handle, inmem.memory, inmem.size)) { ffpmsg("Error copying https file to disk file (https_file_open)"); ffpmsg(filename); ffpmsg(netoutfile); free(inmem.memory); file_close(*handle); return (FILE_NOT_OPENED); } free(inmem.memory); file_close(*handle); return file_open(netoutfile, rwmode, handle); } /*--------------------------------------------------------------------------*/ /* Callback function curl library uses during https connection to transfer server file into memory */ size_t curlToMemCallback(void *buffer, size_t size, size_t nmemb, void *userp) { curlmembuf* inmem = (curlmembuf* )userp; size_t transferSize = size*nmemb; if (!inmem->size) { /* First time through - initialize with malloc */ inmem->memory = (char *)malloc(transferSize); } else inmem->memory = realloc(inmem->memory, inmem->size+transferSize); if (inmem->memory == NULL) { ffpmsg("realloc error - not enough memory (curlToMemCallback)\n"); return 0; } memcpy(&(inmem->memory[inmem->size]), buffer, transferSize); inmem->size += transferSize; return transferSize; } /*--------------------------------------------------------------------------*/ int https_open_network(char *filename, curlmembuf* buffer) { char *urlname=0; char errStr[MAXLEN]; char agentStr[MAXLEN]; float version=0.0; char *verify=0; /* These settings will force libcurl to perform host and peer authentication. If it fails, this routine will try again without authentication (unless user forbids this via CFITSIO_VERIFY_HTTPS environment variable). */ long verifyPeer = 1; long verifyHost = 2; #ifdef CFITSIO_HAVE_CURL CURL *curl=0; CURLcode res; char curlErrBuf[CURL_ERROR_SIZE]; if (strstr(filename,".Z")) { ffpmsg("x-compress .Z format not currently supported with https transfers"); return(FILE_NOT_OPENED); } /* Will ASSUME curl_global_init has been called by this point. It is not thread-safe to call it here. */ curl = curl_easy_init(); res = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, verifyPeer); if (res != CURLE_OK) { ffpmsg("ERROR: CFITSIO was built with a libcurl library that "); ffpmsg("does not have SSL support, and therefore can't perform https transfers."); return (FILE_NOT_OPENED); } curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, verifyHost); curl_easy_setopt(curl, CURLOPT_VERBOSE, (long)curl_verbose); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlToMemCallback); snprintf(agentStr,MAXLEN,"User-Agent: FITSIO/HEASARC/%-8.3f",ffvers(&version)); curl_easy_setopt(curl, CURLOPT_USERAGENT,agentStr); buffer->memory = 0; /* malloc/realloc will grow this in the callback function */ buffer->size = 0; curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)buffer); curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curlErrBuf); curlErrBuf[0]=0; /* This is needed for easy_perform to return an error whenever http server returns an error >= 400, ie. if it can't find the requested file. */ curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L); /* This turns on automatic decompression for all recognized types. */ curl_easy_setopt(curl, CURLOPT_ENCODING, ""); /* urlname should be large enough to accomodate "https://"+filename+".gz". */ urlname = (char *)malloc(strlen(filename)+12); strcpy(urlname, "https://"); strcat(urlname, filename); /* Unless filename already contains a .gz or '?' (probably from a cgi script), first try with .gz appended. */ if (!strstr(filename,".gz") && !strstr(filename,"?")) strcat(urlname, ".gz"); /* First attempt: verification on */ curl_easy_setopt(curl, CURLOPT_URL, urlname); res = curl_easy_perform(curl); if (res != CURLE_OK && res != CURLE_HTTP_RETURNED_ERROR) { /* CURLE_HTTP_RETURNED_ERROR is what gets returned if HTTP server returns an error code >= 400. If that's not causing this error, assume it is a verification issue. Try again with verification removed, unless user disallowed it via environment variable. */ verify = getenv("CFITSIO_VERIFY_HTTPS"); if (verify) { if (verify[0] == 'T' || verify[0] == 't') { snprintf(errStr,MAXLEN,"libcurl error: %d",res); ffpmsg(errStr); if (strlen(curlErrBuf)) ffpmsg(curlErrBuf); curl_easy_cleanup(curl); free(urlname); return (FILE_NOT_OPENED); } } verifyPeer = 0; verifyHost = 0; curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, verifyPeer); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, verifyHost); res = curl_easy_perform(curl); if (res != CURLE_OK) { /* Unless original filename already contains a .gz or '?' (probably from a cgi script), try again without.gz appended. */ if (!strstr(filename,".gz") && !strstr(filename,"?")) { strcpy(urlname, "https://"); strcat(urlname, filename); curl_easy_setopt(curl, CURLOPT_URL, urlname); res = curl_easy_perform(curl); if (res != CURLE_OK) { snprintf(errStr,MAXLEN,"libcurl error: %d",res); ffpmsg(errStr); if (strlen(curlErrBuf)) ffpmsg(curlErrBuf); curl_easy_cleanup(curl); free(urlname); return (FILE_NOT_OPENED); } else fprintf(stderr, "Warning: Unable to perform SSL verification on https transfer from: %s\n", urlname); } else { snprintf(errStr,MAXLEN,"libcurl error: %d",res); ffpmsg(errStr); if (strlen(curlErrBuf)) ffpmsg(curlErrBuf); curl_easy_cleanup(curl); free(urlname); return (FILE_NOT_OPENED); } } else fprintf(stderr, "Warning: Unable to perform SSL verification on https transfer from: %s\n", urlname); } else if (res == CURLE_HTTP_RETURNED_ERROR) { /* Verification isn't the problem. No need to relax peer/host checking */ /* Unless filename already contains a .gz or '?' (probably from a cgi script), try again with original filename unappended */ if (!strstr(filename,".gz") && !strstr(filename,"?")) { strcpy(urlname, "https://"); strcat(urlname, filename); curl_easy_setopt(curl, CURLOPT_URL, urlname); res = curl_easy_perform(curl); if (res != CURLE_OK) { snprintf(errStr,MAXLEN,"libcurl error: %d",res); ffpmsg(errStr); if (strlen(curlErrBuf)) ffpmsg(curlErrBuf); curl_easy_cleanup(curl); free(urlname); return (FILE_NOT_OPENED); } } else { snprintf(errStr,MAXLEN,"libcurl error: %d",res); ffpmsg(errStr); if (strlen(curlErrBuf)) ffpmsg(curlErrBuf); curl_easy_cleanup(curl); free(urlname); return (FILE_NOT_OPENED); } } free(urlname); curl_easy_cleanup(curl); return 0; #else ffpmsg("ERROR: This CFITSIO build was not compiled with the libcurl library package "); ffpmsg("and therefore it cannot perform HTTPS connections."); #endif return (FILE_NOT_OPENED); } void https_set_verbose(int flag) { if (!flag) curl_verbose = 0; else curl_verbose = 1; } /*--------------------------------------------------------------------------*/ /* This creates a memory file handle with a copy of the URL in filename. The file is uncompressed if necessary */ int ftp_open(char *filename, int rwmode, int *handle) { FILE *ftpfile; FILE *command; int sock; char recbuf[MAXLEN]; long len; int status; char firstchar; closememfile = 0; closecommandfile = 0; closeftpfile = 0; /* don't do r/w files */ if (rwmode != 0) { ffpmsg("Can't open ftp:// type file with READWRITE access"); ffpmsg("Specify an outfile for r/w access (ftp_open)"); return (FILE_NOT_OPENED); } /* do the signal handler bits */ if (setjmp(env) != 0) { /* feels like the second time */ /* this means something bad happened */ ffpmsg("Timeout (http_open)"); goto error; } signal(SIGALRM, signal_handler); /* Open the ftp connetion. ftpfile is connected to the file port, command is connected to port 21. sock is the socket on port 21 */ if (strlen(filename) > MAXLEN - 4) { ffpmsg("filename too long (ftp_open)"); ffpmsg(filename); goto error; } alarm(NETTIMEOUT); if (ftp_open_network(filename,&ftpfile,&command,&sock)) { alarm(0); ffpmsg("Unable to open following ftp file (ftp_open):"); ffpmsg(filename); goto error; } closeftpfile++; closecommandfile++; /* create the memory file */ if ((status = mem_create(filename,handle))) { ffpmsg ("Could not create memory file to passive port (ftp_open)"); ffpmsg(filename); goto error; } closememfile++; /* This isn't quite right, it'll fail if the file has .gzabc at the end for instance */ /* Decide if the file is compressed */ firstchar = fgetc(ftpfile); ungetc(firstchar,ftpfile); if (strstr(filename,".gz") || strstr(filename,".Z") || ('\037' == firstchar)) { status = 0; /* A bit arbritary really, the user will probably hit ^C */ alarm(NETTIMEOUT*10); status = mem_uncompress2mem(filename, ftpfile, *handle); alarm(0); if (status) { ffpmsg("Error writing compressed memory file (ftp_open)"); ffpmsg(filename); goto error; } } else { /* write a memory file */ alarm(NETTIMEOUT); while(0 != (len = fread(recbuf,1,MAXLEN,ftpfile))) { alarm(0); status = mem_write(*handle,recbuf,len); if (status) { ffpmsg("Error writing memory file (http_open)"); ffpmsg(filename); goto error; } alarm(NETTIMEOUT); } } /* close and clean up */ fclose(ftpfile); closeftpfile--; fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); closecommandfile--; signal(SIGALRM, SIG_DFL); alarm(0); return mem_seek(*handle,0); error: alarm(0); /* clear it */ if (closecommandfile) { fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); } if (closeftpfile) { fclose(ftpfile); } if (closememfile) { mem_close_free(*handle); } signal(SIGALRM, SIG_DFL); return (FILE_NOT_OPENED); } /*--------------------------------------------------------------------------*/ /* This creates a file handle with a copy of the URL in filename. The file must be uncompressed and is copied to disk first */ int ftp_file_open(char *url, int rwmode, int *handle) { FILE *ftpfile; FILE *command; char recbuf[MAXLEN]; long len; int sock; int ii, flen, status; char firstchar; /* Check if output file is actually a memory file */ if (!strncmp(netoutfile, "mem:", 4) ) { /* allow the memory file to be opened with write access */ return( ftp_open(url, READONLY, handle) ); } closeftpfile = 0; closecommandfile = 0; closefile = 0; closeoutfile = 0; /* cfileio made a mistake, need to know where to write the output file */ flen = strlen(netoutfile); if (!flen) { ffpmsg("Output file not set, shouldn't have happened (ftp_file_open)"); return (FILE_NOT_OPENED); } /* do the signal handler bits */ if (setjmp(env) != 0) { /* feels like the second time */ /* this means something bad happened */ ffpmsg("Timeout (http_open)"); goto error; } signal(SIGALRM, signal_handler); /* open the network connection to url. ftpfile holds the connection to the input file, command holds the connection to port 21, and sock is the socket connected to port 21 */ alarm(NETTIMEOUT); if ((status = ftp_open_network(url,&ftpfile,&command,&sock))) { alarm(0); ffpmsg("Unable to open http file (ftp_file_open)"); ffpmsg(url); goto error; } closeftpfile++; closecommandfile++; if (*netoutfile == '!') { /* user wants to clobber file, if it already exists */ for (ii = 0; ii < flen; ii++) netoutfile[ii] = netoutfile[ii + 1]; /* remove '!' */ status = file_remove(netoutfile); } /* Now, what do we do with the file */ firstchar = fgetc(ftpfile); ungetc(firstchar,ftpfile); if (strstr(url,".gz") || strstr(url,".Z") || ('\037' == firstchar)) { /* to make this more cfitsioish we use the file driver calls to create the file */ /* Create the output file */ if ((status = file_create(netoutfile,handle))) { ffpmsg("Unable to create output file (ftp_file_open)"); ffpmsg(netoutfile); goto error; } file_close(*handle); if (NULL == (outfile = fopen(netoutfile,"w"))) { ffpmsg("Unable to reopen the output file (ftp_file_open)"); ffpmsg(netoutfile); goto error; } closeoutfile++; status = 0; /* Ok, this is a tough case, let's be arbritary and say 10*NETTIMEOUT, Given the choices for nettimeout above they'll probaby ^C before, but it's always worth a shot*/ alarm(NETTIMEOUT*10); status = uncompress2file(url,ftpfile,outfile,&status); alarm(0); if (status) { ffpmsg("Unable to uncompress the output file (ftp_file_open)"); ffpmsg(url); ffpmsg(netoutfile); goto error; } fclose(outfile); closeoutfile--; } else { /* Create the output file */ if ((status = file_create(netoutfile,handle))) { ffpmsg("Unable to create output file (ftp_file_open)"); ffpmsg(netoutfile); goto error; } closefile++; /* write a file */ alarm(NETTIMEOUT); while(0 != (len = fread(recbuf,1,MAXLEN,ftpfile))) { alarm(0); status = file_write(*handle,recbuf,len); if (status) { ffpmsg("Error writing file (ftp_file_open)"); ffpmsg(url); ffpmsg(netoutfile); goto error; } alarm(NETTIMEOUT); } file_close(*handle); } fclose(ftpfile); closeftpfile--; fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); closecommandfile--; signal(SIGALRM, SIG_DFL); alarm(0); return file_open(netoutfile,rwmode,handle); error: alarm(0); /* clear it */ if (closeftpfile) { fclose(ftpfile); } if (closecommandfile) { fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); } if (closeoutfile) { fclose(outfile); } if (closefile) { file_close(*handle); } signal(SIGALRM, SIG_DFL); return (FILE_NOT_OPENED); } /*--------------------------------------------------------------------------*/ /* This creates a memory handle with a copy of the URL in filename. The file must be compressed and is copied to disk first */ int ftp_compress_open(char *url, int rwmode, int *handle) { FILE *ftpfile; FILE *command; char recbuf[MAXLEN]; long len; int ii, flen, status; int sock; char firstchar; closeftpfile = 0; closecommandfile = 0; closememfile = 0; closefdiskfile = 0; closediskfile = 0; /* don't do r/w files */ if (rwmode != 0) { ffpmsg("Compressed files must be r/o"); return (FILE_NOT_OPENED); } /* Need to know where to write the output file */ flen = strlen(netoutfile); if (!flen) { ffpmsg( "Output file not set, shouldn't have happened (ftp_compress_open)"); return (FILE_NOT_OPENED); } /* do the signal handler bits */ if (setjmp(env) != 0) { /* feels like the second time */ /* this means something bad happened */ ffpmsg("Timeout (http_open)"); goto error; } signal(SIGALRM, signal_handler); /* Open the network connection to url, ftpfile is connected to the file port, command is connected to port 21. sock is for writing to port 21 */ alarm(NETTIMEOUT); if ((status = ftp_open_network(url,&ftpfile,&command,&sock))) { alarm(0); ffpmsg("Unable to open ftp file (ftp_compress_open)"); ffpmsg(url); goto error; } closeftpfile++; closecommandfile++; /* Now, what do we do with the file */ firstchar = fgetc(ftpfile); ungetc(firstchar,ftpfile); if (strstr(url,".gz") || strstr(url,".Z") || ('\037' == firstchar)) { if (*netoutfile == '!') { /* user wants to clobber file, if it already exists */ for (ii = 0; ii < flen; ii++) netoutfile[ii] = netoutfile[ii + 1]; /* remove '!' */ status = file_remove(netoutfile); } /* Create the output file */ if ((status = file_create(netoutfile,handle))) { ffpmsg("Unable to create output file (ftp_compress_open)"); ffpmsg(netoutfile); goto error; } closediskfile++; /* write a file */ alarm(NETTIMEOUT); while(0 != (len = fread(recbuf,1,MAXLEN,ftpfile))) { alarm(0); status = file_write(*handle,recbuf,len); if (status) { ffpmsg("Error writing file (ftp_compres_open)"); ffpmsg(url); ffpmsg(netoutfile); goto error; } alarm(NETTIMEOUT); } file_close(*handle); closediskfile--; fclose(ftpfile); closeftpfile--; /* Close down the ftp connection */ fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); closecommandfile--; /* File is on disk, let's uncompress it into memory */ if (NULL == (diskfile = fopen(netoutfile,"r"))) { ffpmsg("Unable to reopen disk file (ftp_compress_open)"); ffpmsg(netoutfile); return (FILE_NOT_OPENED); } closefdiskfile++; if ((status = mem_create(url,handle))) { ffpmsg("Unable to create memory file (ftp_compress_open)"); ffpmsg(url); goto error; } closememfile++; status = 0; status = mem_uncompress2mem(url,diskfile,*handle); fclose(diskfile); closefdiskfile--; if (status) { ffpmsg("Error writing compressed memory file (ftp_compress_open)"); goto error; } } else { /* Opps, this should not have happened */ ffpmsg("Can only compressed files here (ftp_compress_open)"); goto error; } signal(SIGALRM, SIG_DFL); alarm(0); return mem_seek(*handle,0); error: alarm(0); /* clear it */ if (closeftpfile) { fclose(ftpfile); } if (closecommandfile) { fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); } if (closefdiskfile) { fclose(diskfile); } if (closememfile) { mem_close_free(*handle); } if (closediskfile) { file_close(*handle); } signal(SIGALRM, SIG_DFL); return (FILE_NOT_OPENED); } /*--------------------------------------------------------------------------*/ /* Open a ftp connection to filename (really a URL), return ftpfile set to the file connection, and command set to the control connection, with sock also set to the control connection */ static int ftp_open_network(char *filename, FILE **ftpfile, FILE **command, int *sock) { int status; int sock1; int tmpint; char recbuf[MAXLEN]; char errorstr[MAXLEN]; char tmpstr[MAXLEN]; char proto[SHORTLEN]; char host[SHORTLEN]; char *newhost; char *username; char *password; char fn[MAXLEN]; char *newfn; char *passive; char *tstr; char *saveptr; char ip[SHORTLEN]; char turl[MAXLEN]; int port; int ii,tryingtologin = 1; /* parse the URL */ if (strlen(filename) > MAXLEN - 7) { ffpmsg("ftp filename is too long (ftp_open_network)"); return (FILE_NOT_OPENED); } strcpy(turl,"ftp://"); strcat(turl,filename); if (NET_ParseUrl(turl,proto,host,&port,fn)) { snprintf(errorstr,MAXLEN,"URL Parse Error (ftp_open) %s",filename); ffpmsg(errorstr); return (FILE_NOT_OPENED); } port = 21; /* we might have a user name */ username = "anonymous"; password = "user@host.com"; /* is there an @ sign */ if (NULL != (newhost = strrchr(host,'@'))) { *newhost = '\0'; /* make it a null, */ newhost++; /* Now newhost points to the host name and host points to the user name, password combo */ username = host; /* is there a : for a password */ if (NULL != strchr(username,':')) { password = strchr(username,':'); *password = '\0'; password++; } } else { newhost = host; } for (ii = 0; ii < 10; ii++) { /* make up to 10 attempts to log in */ /* Connect to the host on the required port */ *sock = NET_TcpConnect(newhost,port); /* convert it to a stdio file */ if (NULL == (*command = fdopen(*sock,"r"))) { ffpmsg ("fdopen failed to convert socket to stdio file (ftp_open_netowrk)"); return (FILE_NOT_OPENED); } /* Wait for the 220 response */ if (ftp_status(*command,"220 ")) { fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); /* ffpmsg("sleeping for 5 in ftp_open_network, then try again"); */ sleep (5); /* take a nap and hope ftp server sorts itself out in the meantime */ } else { tryingtologin = 0; break; } } if (tryingtologin) { /* the 10 attempts were not successful */ ffpmsg ("error connecting to remote server, no 220 seen (ftp_open_network)"); return (FILE_NOT_OPENED); } /* Send the user name and wait for the right response */ snprintf(tmpstr,MAXLEN,"USER %s\r\n",username); status = NET_SendRaw(*sock,tmpstr,strlen(tmpstr),NET_DEFAULT); if (ftp_status(*command,"331 ")) { ffpmsg ("USER error no 331 seen (ftp_open_network)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } /* Send the password and wait for the right response */ snprintf(tmpstr,MAXLEN,"PASS %s\r\n",password); status = NET_SendRaw(*sock,tmpstr,strlen(tmpstr),NET_DEFAULT); if (ftp_status(*command,"230 ")) { ffpmsg ("PASS error, no 230 seen (ftp_open_network)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } /* now do the cwd command */ newfn = strrchr(fn,'/'); if (newfn == NULL) { strcpy(tmpstr,"CWD /\r\n"); newfn = fn; } else { *newfn = '\0'; newfn++; if (strlen(fn) == 0) { strcpy(tmpstr,"CWD /\r\n"); } else { /* remove the leading slash */ if (fn[0] == '/') { snprintf(tmpstr,MAXLEN,"CWD %s\r\n",&fn[1]); } else { snprintf(tmpstr,MAXLEN,"CWD %s\r\n",fn); } } } status = NET_SendRaw(*sock,tmpstr,strlen(tmpstr),NET_DEFAULT); if (ftp_status(*command,"250 ")) { ffpmsg ("CWD error, no 250 seen (ftp_open_network)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } if (!strlen(newfn)) { ffpmsg("Null file name (ftp_open)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } /* Always use binary mode */ snprintf(tmpstr,MAXLEN,"TYPE I\r\n"); status = NET_SendRaw(*sock,tmpstr,strlen(tmpstr),NET_DEFAULT); if (ftp_status(*command,"200 ")) { ffpmsg ("TYPE I error, 200 not seen (ftp_open_network)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } status = NET_SendRaw(*sock,"PASV\r\n",6,NET_DEFAULT); if (!(fgets(recbuf,MAXLEN,*command))) { ffpmsg ("PASV error (ftp_open)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } /* Passive mode response looks like 227 Entering Passive Mode (129,194,67,8,210,80) */ if (recbuf[0] == '2' && recbuf[1] == '2' && recbuf[2] == '7') { /* got a good passive mode response, find the opening ( */ if (!(passive = strchr(recbuf,'('))) { ffpmsg ("PASV error (ftp_open_network)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } *passive = '\0'; passive++; ip[0] = '\0'; /* Messy parsing of response from PASV *command */ if (!(tstr = ffstrtok(passive,",)",&saveptr))) { ffpmsg ("PASV error (ftp_open_network)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } strcpy(ip,tstr); strcat(ip,"."); if (!(tstr = ffstrtok(NULL,",)",&saveptr))) { ffpmsg ("PASV error (ftp_open_network)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } strcat(ip,tstr); strcat(ip,"."); if (!(tstr = ffstrtok(NULL,",)",&saveptr))) { ffpmsg ("PASV error (ftp_open_network)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } strcat(ip,tstr); strcat(ip,"."); if (!(tstr = ffstrtok(NULL,",)",&saveptr))) { ffpmsg ("PASV error (ftp_open_network)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } strcat(ip,tstr); /* Done the ip number, now do the port # */ if (!(tstr = ffstrtok(NULL,",)",&saveptr))) { ffpmsg ("PASV error (ftp_open_network)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } sscanf(tstr,"%d",&port); port *= 256; if (!(tstr = ffstrtok(NULL,",)",&saveptr))) { ffpmsg ("PASV error (ftp_open_network)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } sscanf(tstr,"%d",&tmpint); port += tmpint; if (!strlen(newfn)) { ffpmsg("Null file name (ftp_open_network)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } /* Connect to the data port */ sock1 = NET_TcpConnect(ip,port); if (NULL == (*ftpfile = fdopen(sock1,"r"))) { ffpmsg ("Could not connect to passive port (ftp_open_network)"); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } /* Send the retrieve command */ snprintf(tmpstr,MAXLEN,"RETR %s\r\n",newfn); status = NET_SendRaw(*sock,tmpstr,strlen(tmpstr),NET_DEFAULT); if (ftp_status(*command,"150 ")) { fclose(*ftpfile); NET_SendRaw(sock1,"QUIT\r\n",6,NET_DEFAULT); fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } return 0; /* successfully opened the ftp file */ } /* no passive mode */ fclose(*command); NET_SendRaw(*sock,"QUIT\r\n",6,NET_DEFAULT); return (FILE_NOT_OPENED); } /*--------------------------------------------------------------------------*/ /* Open a ftp connection to see if the file exists (return 1) or not (return 0) */ int ftp_file_exist(char *filename) { FILE *ftpfile; FILE *command; int sock; int status; int sock1; int tmpint; char recbuf[MAXLEN]; char errorstr[MAXLEN]; char tmpstr[MAXLEN]; char proto[SHORTLEN]; char host[SHORTLEN]; char *newhost; char *username; char *password; char fn[MAXLEN]; char *newfn; char *passive; char *tstr; char *saveptr; char ip[SHORTLEN]; char turl[MAXLEN]; int port; int ii, tryingtologin = 1; /* parse the URL */ if (strlen(filename) > MAXLEN - 7) { ffpmsg("ftp filename is too long (ftp_file_exist)"); return 0; } strcpy(turl,"ftp://"); strcat(turl,filename); if (NET_ParseUrl(turl,proto,host,&port,fn)) { snprintf(errorstr,MAXLEN,"URL Parse Error (ftp_file_exist) %s",filename); ffpmsg(errorstr); return 0; } port = 21; /* we might have a user name */ username = "anonymous"; password = "user@host.com"; /* is there an @ sign */ if (NULL != (newhost = strrchr(host,'@'))) { *newhost = '\0'; /* make it a null, */ newhost++; /* Now newhost points to the host name and host points to the user name, password combo */ username = host; /* is there a : for a password */ if (NULL != strchr(username,':')) { password = strchr(username,':'); *password = '\0'; password++; } } else { newhost = host; } for (ii = 0; ii < 10; ii++) { /* make up to 10 attempts to log in */ /* Connect to the host on the required port */ sock = NET_TcpConnect(newhost,port); /* convert it to a stdio file */ if (NULL == (command = fdopen(sock,"r"))) { ffpmsg ("Failed to convert socket to stdio file (ftp_file_exist)"); return 0; } /* Wait for the 220 response */ if (ftp_status(command,"220 ")) { ffpmsg ("error connecting to remote server, no 220 seen (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); /* ffpmsg("sleeping for 5 in ftp_file_exist, then try again"); */ sleep (5); /* take a nap and hope ftp server sorts itself out in the meantime */ } else { tryingtologin = 0; break; } } if (tryingtologin) { /* the 10 attempts were not successful */ ffpmsg ("error connecting to remote server, no 220 seen (ftp_open_network)"); return (0); } /* Send the user name and wait for the right response */ snprintf(tmpstr,MAXLEN,"USER %s\r\n",username); status = NET_SendRaw(sock,tmpstr,strlen(tmpstr),NET_DEFAULT); if (ftp_status(command,"331 ")) { ffpmsg ("USER error no 331 seen (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } /* Send the password and wait for the right response */ snprintf(tmpstr,MAXLEN,"PASS %s\r\n",password); status = NET_SendRaw(sock,tmpstr,strlen(tmpstr),NET_DEFAULT); if (ftp_status(command,"230 ")) { ffpmsg ("PASS error, no 230 seen (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } /* now do the cwd command */ newfn = strrchr(fn,'/'); if (newfn == NULL) { strcpy(tmpstr,"CWD /\r\n"); newfn = fn; } else { *newfn = '\0'; newfn++; if (strlen(fn) == 0) { strcpy(tmpstr,"CWD /\r\n"); } else { /* remove the leading slash */ if (fn[0] == '/') { snprintf(tmpstr,MAXLEN,"CWD %s\r\n",&fn[1]); } else { snprintf(tmpstr,MAXLEN,"CWD %s\r\n",fn); } } } status = NET_SendRaw(sock,tmpstr,strlen(tmpstr),NET_DEFAULT); if (ftp_status(command,"250 ")) { ffpmsg ("CWD error, no 250 seen (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } if (!strlen(newfn)) { ffpmsg("Null file name (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } /* Always use binary mode */ snprintf(tmpstr,MAXLEN,"TYPE I\r\n"); status = NET_SendRaw(sock,tmpstr,strlen(tmpstr),NET_DEFAULT); if (ftp_status(command,"200 ")) { ffpmsg ("TYPE I error, 200 not seen (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } status = NET_SendRaw(sock,"PASV\r\n",6,NET_DEFAULT); if (!(fgets(recbuf,MAXLEN,command))) { ffpmsg ("PASV error (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } /* Passive mode response looks like 227 Entering Passive Mode (129,194,67,8,210,80) */ if (recbuf[0] == '2' && recbuf[1] == '2' && recbuf[2] == '7') { /* got a good passive mode response, find the opening ( */ if (!(passive = strchr(recbuf,'('))) { ffpmsg ("PASV error (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } *passive = '\0'; passive++; ip[0] = '\0'; /* Messy parsing of response from PASV command */ if (!(tstr = ffstrtok(passive,",)",&saveptr))) { ffpmsg ("PASV error (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } strcpy(ip,tstr); strcat(ip,"."); if (!(tstr = ffstrtok(NULL,",)",&saveptr))) { ffpmsg ("PASV error (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } strcat(ip,tstr); strcat(ip,"."); if (!(tstr = ffstrtok(NULL,",)",&saveptr))) { ffpmsg ("PASV error (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } strcat(ip,tstr); strcat(ip,"."); if (!(tstr = ffstrtok(NULL,",)",&saveptr))) { ffpmsg ("PASV error (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } strcat(ip,tstr); /* Done the ip number, now do the port # */ if (!(tstr = ffstrtok(NULL,",)",&saveptr))) { ffpmsg ("PASV error (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } sscanf(tstr,"%d",&port); port *= 256; if (!(tstr = ffstrtok(NULL,",)",&saveptr))) { ffpmsg ("PASV error (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } sscanf(tstr,"%d",&tmpint); port += tmpint; if (!strlen(newfn)) { ffpmsg("Null file name (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } /* Connect to the data port */ sock1 = NET_TcpConnect(ip,port); if (NULL == (ftpfile = fdopen(sock1,"r"))) { ffpmsg ("Could not connect to passive port (ftp_file_exist)"); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } /* Send the retrieve command */ snprintf(tmpstr,MAXLEN,"RETR %s\r\n",newfn); status = NET_SendRaw(sock,tmpstr,strlen(tmpstr),NET_DEFAULT); if (ftp_status(command,"150 ")) { fclose(ftpfile); NET_SendRaw(sock1,"QUIT\r\n",6,NET_DEFAULT); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } /* if we got here then the file probably exists */ fclose(ftpfile); NET_SendRaw(sock1,"QUIT\r\n",6,NET_DEFAULT); fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 1; } /* no passive mode */ fclose(command); NET_SendRaw(sock,"QUIT\r\n",6,NET_DEFAULT); return 0; } /*--------------------------------------------------------------------------*/ /* return a socket which results from connection to hostname on port port */ int NET_TcpConnect(char *hostname, int port) { /* Connect to hostname on port */ struct sockaddr_in sockaddr; int sock; int stat; int val = 1; CreateSocketAddress(&sockaddr,hostname,port); /* Create socket */ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { ffpmsg("ERROR: NET_TcpConnect can't create socket"); return CONNECTION_ERROR; } if ((stat = connect(sock, (struct sockaddr*) &sockaddr, sizeof(sockaddr))) < 0) { close(sock); /* perror("NET_Tcpconnect - Connection error"); ffpmsg("Can't connect to host, connection error"); */ return CONNECTION_ERROR; } setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&val, sizeof(val)); val = 65536; setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&val, sizeof(val)); setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&val, sizeof(val)); return sock; } /*--------------------------------------------------------------------------*/ /* Write len bytes from buffer to socket sock */ static int NET_SendRaw(int sock, const void *buffer, int length, int opt) { char * buf = (char *) buffer; int flag; int n, nsent = 0; switch (opt) { case NET_DEFAULT: flag = 0; break; case NET_OOB: flag = MSG_OOB; break; case NET_PEEK: default: flag = 0; break; } if (sock < 0) return -1; for (n = 0; n < length; n += nsent) { if ((nsent = send(sock, buf+n, length-n, flag)) <= 0) { return nsent; } } return n; } /*--------------------------------------------------------------------------*/ static int NET_RecvRaw(int sock, void *buffer, int length) { /* Receive exactly length bytes into buffer. Returns number of bytes */ /* received. Returns -1 in case of error. */ int nrecv, n; char *buf = (char *)buffer; if (sock < 0) return -1; for (n = 0; n < length; n += nrecv) { while ((nrecv = recv(sock, buf+n, length-n, 0)) == -1 && errno == EINTR) errno = 0; /* probably a SIGCLD that was caught */ if (nrecv < 0) return nrecv; else if (nrecv == 0) break; /*/ EOF */ } return n; } /*--------------------------------------------------------------------------*/ /* Yet Another URL Parser url - input url proto - input protocol host - output host port - output port fn - output filename */ static int NET_ParseUrl(const char *url, char *proto, char *host, int *port, char *fn) { /* parses urls into their bits */ /* returns 1 if error, else 0 */ char *urlcopy, *urlcopyorig; char *ptrstr; char *thost; int isftp = 0; /* figure out if there is a http: or ftp: */ urlcopyorig = urlcopy = (char *) malloc(strlen(url)+1); strcpy(urlcopy,url); /* set some defaults */ *port = 80; strcpy(proto,"http:"); strcpy(host,"localhost"); strcpy(fn,"/"); ptrstr = strstr(urlcopy,"http:"); if (ptrstr == NULL) { /* Nope, not http: */ ptrstr = strstr(urlcopy,"root:"); if (ptrstr == NULL) { /* Nope, not root either */ ptrstr = strstr(urlcopy,"ftp:"); if (ptrstr != NULL) { if (ptrstr == urlcopy) { strcpy(proto,"ftp:"); *port = 21; isftp++; urlcopy += 4; /* move past ftp: */ } else { /* not at the beginning, bad url */ free(urlcopyorig); return 1; } } } else { if (ptrstr == urlcopy) { urlcopy += 5; /* move past root: */ } else { /* not at the beginning, bad url */ free(urlcopyorig); return 1; } } } else { if (ptrstr == urlcopy) { urlcopy += 5; /* move past http: */ } else { free(urlcopyorig); return 1; } } /* got the protocol */ /* get the hostname */ if (urlcopy[0] == '/' && urlcopy[1] == '/') { /* we have a hostname */ urlcopy += 2; /* move past the // */ } /* do this only if http */ if (!strcmp(proto,"http:")) { /* Move past any user:password */ if ((thost = strchr(urlcopy, '@')) != NULL) urlcopy = thost+1; strcpy(host,urlcopy); thost = host; while (*urlcopy != '/' && *urlcopy != ':' && *urlcopy) { thost++; urlcopy++; } /* we should either be at the end of the string, have a /, or have a : */ *thost = '\0'; if (*urlcopy == ':') { /* follows a port number */ urlcopy++; sscanf(urlcopy,"%d",port); while (*urlcopy != '/' && *urlcopy) urlcopy++; /* step to the */ } } else { /* do this for ftp */ strcpy(host,urlcopy); thost = host; while (*urlcopy != '/' && *urlcopy) { thost++; urlcopy++; } *thost = '\0'; /* Now, we should either be at the end of the string, or have a / */ } /* Now the rest is a fn */ if (*urlcopy) { strcpy(fn,urlcopy); } free(urlcopyorig); return 0; } /*--------------------------------------------------------------------------*/ int http_checkfile (char *urltype, char *infile, char *outfile1) { /* Small helper functions to set the netoutfile static string */ /* Called by cfileio after parsing the output file off of the input file url */ char newinfile[MAXLEN]; FILE *httpfile; char contentencoding[MAXLEN]; int contentlength; int foundfile = 0; /* set defaults */ strcpy(urltype,"http://"); if (strlen(outfile1)) { /* don't copy the "file://" prefix, if present. */ if (!strncmp(outfile1, "file://", 7) ) { strcpy(netoutfile,outfile1+7); } else { strcpy(netoutfile,outfile1); } } if (strstr(infile, "?")) { /* Special case where infile name contains a "?". */ /* This is probably a CGI string; no point in testing if it exists */ /* so just set urltype and netoutfile if necessary, then return */ if (strlen(outfile1)) { /* was an outfile specified? */ strcpy(urltype,"httpfile://"); /* don't copy the "file://" prefix, if present. */ if (!strncmp(outfile1, "file://", 7) ) { strcpy(netoutfile,outfile1+7); } else { strcpy(netoutfile,outfile1); } } return 0; /* case where infile name contains "?" */ } /* If the specified infile file name does not contain a .gz or .Z suffix, then first test if a .gz compressed version of the file exists, and if not then test if a .Z version of the file exists. (because it will be much faster to read the compressed file). If the compressed files do not exist, then finally just open the infile name exactly as specified. */ if (!strstr(infile,".gz") && (!strstr(infile,".Z"))) { /* The infile string does not contain the name of a compressed file. */ /* Fisrt, look for a .gz compressed version of the file. */ strcpy(newinfile,infile); strcat(newinfile,".gz"); if (!http_open_network(newinfile,&httpfile,contentencoding, &contentlength)) { if (!strcmp(contentencoding, "ftp://")) { /* this is a signal from http_open_network that indicates that */ /* the http server returned a 301 or 302 redirect to a FTP URL. */ /* Check that the file exists, because redirect many not be reliable */ if (ftp_file_exist(newinfile)) { /* The ftp .gz compressed file is there, all is good! */ strcpy(urltype, "ftp://"); strcpy(infile,newinfile); if (strlen(outfile1)) { /* there is an output file; might need to modify the urltype */ if (!strncmp(outfile1, "mem:", 4) ) { /* copy the file to memory, with READ and WRITE access In this case, it makes no difference whether the ftp file and or the output file are compressed or not. */ strcpy(urltype, "ftpmem://"); /* use special driver */ } else { /* input file is compressed */ if (strstr(outfile1,".gz") || (strstr(outfile1,".Z"))) { strcpy(urltype,"ftpcompress://"); } else { strcpy(urltype,"ftpfile://"); } } } return 0; /* found the .gz compressed ftp file */ } /* fall through to here if ftp redirect does not exist */ } else if (!strcmp(contentencoding, "https://")) { /* the http server returned a 301 or 302 redirect to an HTTPS URL. */ https_checkfile(urltype, infile, outfile1); /* For https we're not testing for compressed extensions at this stage. It will all be done in https_open_network. Therefore leave infile alone and do immediate return. */ return 0; } else { /* found the http .gz compressed file */ fclose(httpfile); foundfile = 1; strcpy(infile,newinfile); } } if (!foundfile) { /* did not find .gz compressed version of the file, so look for .Z file. */ strcpy(newinfile,infile); strcat(newinfile,".Z"); if (!http_open_network(newinfile,&httpfile,contentencoding, &contentlength)) { if (!strcmp(contentencoding, "ftp://")) { /* this is a signal from http_open_network that indicates that */ /* the http server returned a 301 or 302 redirect to a FTP URL. */ /* Check that the file exists, because redirect many not be reliable */ if (ftp_file_exist(newinfile)) { /* The ftp .Z compressed file is there, all is good! */ strcpy(urltype, "ftp://"); strcpy(infile,newinfile); if (strlen(outfile1)) { /* there is an output file; might need to modify the urltype */ if (!strncmp(outfile1, "mem:", 4) ) { /* copy the file to memory, with READ and WRITE access In this case, it makes no difference whether the ftp file and or the output file are compressed or not. */ strcpy(urltype, "ftpmem://"); /* use special driver */ } else { /* input file is compressed */ if (strstr(outfile1,".gz") || (strstr(outfile1,".Z"))) { strcpy(urltype,"ftpcompress://"); } else { strcpy(urltype,"ftpfile://"); } } } return 0; /* found the .gz compressed ftp file */ } /* fall through to here if ftp redirect does not exist */ } else { /* found the http .Z compressed file */ fclose(httpfile); foundfile = 1; strcpy(infile,newinfile); } } } } /* end of case where infile does not contain .gz or .Z */ if (!foundfile) { /* look for the base file.name */ strcpy(newinfile,infile); if (!http_open_network(newinfile,&httpfile,contentencoding, &contentlength)) { if (!strcmp(contentencoding, "ftp://")) { /* this is a signal from http_open_network that indicates that */ /* the http server returned a 301 or 302 redirect to a FTP URL. */ /* Check that the file exists, because redirect many not be reliable */ if (ftp_file_exist(newinfile)) { /* The ftp file is there, all is good! */ strcpy(urltype, "ftp://"); strcpy(infile,newinfile); if (strlen(outfile1)) { /* there is an output file; might need to modify the urltype */ if (!strncmp(outfile1, "mem:", 4) ) { /* copy the file to memory, with READ and WRITE access In this case, it makes no difference whether the ftp file and or the output file are compressed or not. */ strcpy(urltype, "ftpmem://"); /* use special driver */ return 0; } else { /* input file is not compressed */ strcpy(urltype,"ftpfile://"); } } return 0; /* found the ftp file */ } /* fall through to here if ftp redirect does not exist */ } else if (!strcmp(contentencoding, "https://")) { /* the http server returned a 301 or 302 redirect to an HTTPS URL. */ https_checkfile(urltype, infile, outfile1); /* For https we're not testing for compressed extensions at this stage. It will all be done in https_open_network. Therefore leave infile alone and do immediate return. */ return 0; } else { /* found the http .Z compressed file */ fclose(httpfile); foundfile = 1; strcpy(infile,newinfile); } } } if (!foundfile) { return (FILE_NOT_OPENED); } if (strlen(outfile1)) { /* there is an output file */ if (!strncmp(outfile1, "mem:", 4) ) { /* copy the file to memory, with READ and WRITE access In this case, it makes no difference whether the http file and or the output file are compressed or not. */ strcpy(urltype, "httpmem://"); /* use special driver */ return 0; } if (strstr(infile, "?")) { /* file name contains a '?' so probably a cgi string; */ strcpy(urltype,"httpfile://"); return 0; } if (strstr(infile,".gz") || (strstr(infile,".Z"))) { /* It's compressed */ if (strstr(outfile1,".gz") || (strstr(outfile1,".Z"))) { strcpy(urltype,"httpcompress://"); } else { strcpy(urltype,"httpfile://"); } } else { strcpy(urltype,"httpfile://"); } } return 0; } /*--------------------------------------------------------------------------*/ int https_checkfile (char *urltype, char *infile, char *outfile1) { /* set default */ strcpy(urltype,"https://"); if (strlen(outfile1)) { /* don't copy the "file://" prefix, if present. */ if (!strncmp(outfile1, "file://", 7) ) { strcpy(netoutfile,outfile1+7); } else { strcpy(netoutfile,outfile1); } if (!strncmp(outfile1, "mem:", 4)) strcpy(urltype,"httpsmem://"); else strcpy(urltype,"httpsfile://"); } return 0; } /*--------------------------------------------------------------------------*/ int ftp_checkfile (char *urltype, char *infile, char *outfile1) { char newinfile[MAXLEN]; FILE *ftpfile; FILE *command; int sock; int foundfile = 0; /* Small helper functions to set the netoutfile static string */ /* default to ftp:// if no outfile specified */ strcpy(urltype,"ftp://"); if (!strstr(infile,".gz") && (!strstr(infile,".Z"))) { /* The infile string does not contain the name of a compressed file. */ /* Fisrt, look for a .gz compressed version of the file. */ strcpy(newinfile,infile); strcat(newinfile,".gz"); /* look for .gz version of the file */ if (ftp_file_exist(newinfile)) { foundfile = 1; strcpy(infile,newinfile); } if (!foundfile) { strcpy(newinfile,infile); strcat(newinfile,".Z"); /* look for .Z version of the file */ if (ftp_file_exist(newinfile)) { foundfile = 1; strcpy(infile,newinfile); } } } if (!foundfile) { strcpy(newinfile,infile); /* look for the base file */ if (ftp_file_exist(newinfile)) { foundfile = 1; strcpy(infile,newinfile); } } if (!foundfile) { return (FILE_NOT_OPENED); } if (strlen(outfile1)) { /* there is an output file; might need to modify the urltype */ /* don't copy the "file://" prefix, if present. */ if (!strncmp(outfile1, "file://", 7) ) strcpy(netoutfile,outfile1+7); else strcpy(netoutfile,outfile1); if (!strncmp(outfile1, "mem:", 4) ) { /* copy the file to memory, with READ and WRITE access In this case, it makes no difference whether the ftp file and or the output file are compressed or not. */ strcpy(urltype, "ftpmem://"); /* use special driver */ return 0; } if (strstr(infile,".gz") || (strstr(infile,".Z"))) { /* input file is compressed */ if (strstr(outfile1,".gz") || (strstr(outfile1,".Z"))) { strcpy(urltype,"ftpcompress://"); } else { strcpy(urltype,"ftpfile://"); } } else { strcpy(urltype,"ftpfile://"); } } return 0; } /*--------------------------------------------------------------------------*/ /* A small helper function to wait for a particular status on the ftp connectino */ static int ftp_status(FILE *ftp, char *statusstr) { /* read through until we find a string beginning with statusstr */ /* This needs a timeout */ char recbuf[MAXLEN], errorstr[SHORTLEN]; int len; len = strlen(statusstr); while (1) { if (!(fgets(recbuf,MAXLEN,ftp))) { snprintf(errorstr,SHORTLEN,"ERROR: ftp_status wants %s but fgets returned 0",statusstr); ffpmsg(errorstr); return 1; /* error reading */ } recbuf[len] = '\0'; /* make it short */ if (!strcmp(recbuf,statusstr)) { return 0; /* we're ok */ } if (recbuf[0] > '3') { /* oh well, some sort of error */ snprintf(errorstr,SHORTLEN,"ERROR ftp_status wants %s but got %s", statusstr, recbuf); ffpmsg(errorstr); return 1; } snprintf(errorstr,SHORTLEN,"ERROR ftp_status wants %s but got unexpected %s", statusstr, recbuf); ffpmsg(errorstr); } } /* *---------------------------------------------------------------------- * * CreateSocketAddress -- * * This function initializes a sockaddr structure for a host and port. * * Results: * 1 if the host was valid, 0 if the host could not be converted to * an IP address. * * Side effects: * Fills in the *sockaddrPtr structure. * *---------------------------------------------------------------------- */ static int CreateSocketAddress( struct sockaddr_in *sockaddrPtr, /* Socket address */ char *host, /* Host. NULL implies INADDR_ANY */ int port) /* Port number */ { struct hostent *hostent; /* Host database entry */ struct in_addr addr; /* For 64/32 bit madness */ char localhost[MAXLEN]; strcpy(localhost,host); memset((void *) sockaddrPtr, '\0', sizeof(struct sockaddr_in)); sockaddrPtr->sin_family = AF_INET; sockaddrPtr->sin_port = htons((unsigned short) (port & 0xFFFF)); if (host == NULL) { addr.s_addr = INADDR_ANY; } else { addr.s_addr = inet_addr(localhost); if (addr.s_addr == 0xFFFFFFFF) { hostent = gethostbyname(localhost); if (hostent != NULL) { memcpy((void *) &addr, (void *) hostent->h_addr_list[0], (size_t) hostent->h_length); } else { #ifdef EHOSTUNREACH errno = EHOSTUNREACH; #else #ifdef ENXIO errno = ENXIO; #endif #endif return 0; /* error */ } } } /* * NOTE: On 64 bit machines the assignment below is rumored to not * do the right thing. Please report errors related to this if you * observe incorrect behavior on 64 bit machines such as DEC Alphas. * Should we modify this code to do an explicit memcpy? */ sockaddrPtr->sin_addr.s_addr = addr.s_addr; return 1; /* Success. */ } /* Signal handler for timeouts */ static void signal_handler(int sig) { switch (sig) { case SIGALRM: /* process for alarm */ longjmp(env,sig); default: { /* Hmm, shouldn't have happend */ exit(sig); } } } /**************************************************************/ /* Root driver */ /*--------------------------------------------------------------------------*/ int root_init(void) { int ii; for (ii = 0; ii < NMAXFILES; ii++) /* initialize all empty slots in table */ { handleTable[ii].sock = 0; handleTable[ii].currentpos = 0; } return(0); } /*--------------------------------------------------------------------------*/ int root_setoptions(int options) { /* do something with the options argument, to stop compiler warning */ options = 0; return(options); } /*--------------------------------------------------------------------------*/ int root_getoptions(int *options) { *options = 0; return(0); } /*--------------------------------------------------------------------------*/ int root_getversion(int *version) { *version = 10; return(0); } /*--------------------------------------------------------------------------*/ int root_shutdown(void) { return(0); } /*--------------------------------------------------------------------------*/ int root_open(char *url, int rwmode, int *handle) { int ii, status; int sock; *handle = -1; for (ii = 0; ii < NMAXFILES; ii++) /* find empty slot in table */ { if (handleTable[ii].sock == 0) { *handle = ii; break; } } if (*handle == -1) return(TOO_MANY_FILES); /* too many files opened */ /*open the file */ if (rwmode) { status = root_openfile(url, "update", &sock); } else { status = root_openfile(url, "read", &sock); } if (status) return(status); handleTable[ii].sock = sock; handleTable[ii].currentpos = 0; return(0); } /*--------------------------------------------------------------------------*/ int root_create(char *filename, int *handle) { int ii, status; int sock; *handle = -1; for (ii = 0; ii < NMAXFILES; ii++) /* find empty slot in table */ { if (handleTable[ii].sock == 0) { *handle = ii; break; } } if (*handle == -1) return(TOO_MANY_FILES); /* too many files opened */ /*open the file */ status = root_openfile(filename, "create", &sock); if (status) { ffpmsg("Unable to create file"); return(status); } handleTable[ii].sock = sock; handleTable[ii].currentpos = 0; return(0); } /*--------------------------------------------------------------------------*/ int root_size(int handle, LONGLONG *filesize) /* return the size of the file in bytes */ { int sock; int offset; int status; int op; sock = handleTable[handle].sock; status = root_send_buffer(sock,ROOTD_STAT,NULL,0); status = root_recv_buffer(sock,&op,(char *)&offset, 4); *filesize = (LONGLONG) ntohl(offset); return(0); } /*--------------------------------------------------------------------------*/ int root_close(int handle) /* close the file */ { int status; int sock; sock = handleTable[handle].sock; status = root_send_buffer(sock,ROOTD_CLOSE,NULL,0); close(sock); handleTable[handle].sock = 0; return(0); } /*--------------------------------------------------------------------------*/ int root_flush(int handle) /* flush the file */ { int status; int sock; sock = handleTable[handle].sock; status = root_send_buffer(sock,ROOTD_FLUSH,NULL,0); return(0); } /*--------------------------------------------------------------------------*/ int root_seek(int handle, LONGLONG offset) /* seek to position relative to start of the file */ { handleTable[handle].currentpos = offset; return(0); } /*--------------------------------------------------------------------------*/ int root_read(int hdl, void *buffer, long nbytes) /* read bytes from the current position in the file */ { char msg[SHORTLEN]; int op; int status; int astat; /* we presume here that the file position will never be > 2**31 = 2.1GB */ snprintf(msg,SHORTLEN,"%ld %ld ",(long) handleTable[hdl].currentpos,nbytes); status = root_send_buffer(handleTable[hdl].sock,ROOTD_GET,msg,strlen(msg)); if ((unsigned) status != strlen(msg)) { return (READ_ERROR); } astat = 0; status = root_recv_buffer(handleTable[hdl].sock,&op,(char *) &astat,4); if (astat != 0) { return (READ_ERROR); } status = NET_RecvRaw(handleTable[hdl].sock,buffer,nbytes); if (status != nbytes) { return (READ_ERROR); } handleTable[hdl].currentpos += nbytes; return(0); } /*--------------------------------------------------------------------------*/ int root_write(int hdl, void *buffer, long nbytes) /* write bytes at the current position in the file */ { char msg[SHORTLEN]; int len; int sock; int status; int astat; int op; sock = handleTable[hdl].sock; /* we presume here that the file position will never be > 2**31 = 2.1GB */ snprintf(msg,SHORTLEN,"%ld %ld ",(long) handleTable[hdl].currentpos,nbytes); len = strlen(msg); status = root_send_buffer(sock,ROOTD_PUT,msg,len+1); if (status != len+1) { return (WRITE_ERROR); } status = NET_SendRaw(sock,buffer,nbytes,NET_DEFAULT); if (status != nbytes) { return (WRITE_ERROR); } astat = 0; status = root_recv_buffer(handleTable[hdl].sock,&op,(char *) &astat,4); if (astat != 0) { return (WRITE_ERROR); } handleTable[hdl].currentpos += nbytes; return(0); } /*--------------------------------------------------------------------------*/ int root_openfile(char *url, char *rwmode, int *sock) /* lowest level routine to physically open a root file */ { int status; char recbuf[MAXLEN]; char errorstr[MAXLEN]; char proto[SHORTLEN]; char host[SHORTLEN]; char fn[MAXLEN]; char turl[MAXLEN]; int port; int op; int ii; int authstat; /* Parse the URL apart again */ strcpy(turl,"root://"); strcat(turl,url); if (NET_ParseUrl(turl,proto,host,&port,fn)) { snprintf(errorstr,MAXLEN,"URL Parse Error (root_open) %s",url); ffpmsg(errorstr); return (FILE_NOT_OPENED); } /* Connect to the remote host */ *sock = NET_TcpConnect(host,port); if (*sock < 0) { ffpmsg("Couldn't connect to host (root_openfile)"); return (FILE_NOT_OPENED); } /* get the username */ if (NULL != getenv("ROOTUSERNAME")) { strcpy(recbuf,getenv("ROOTUSERNAME")); } else { printf("Username: "); fgets(recbuf,MAXLEN,stdin); recbuf[strlen(recbuf)-1] = '\0'; } status = root_send_buffer(*sock, ROOTD_USER, recbuf,strlen(recbuf)); if (status < 0) { ffpmsg("error talking to remote system on username "); return (FILE_NOT_OPENED); } status = root_recv_buffer(*sock,&op,(char *)&authstat,4); if (!status) { ffpmsg("error talking to remote system on username"); return (FILE_NOT_OPENED); } if (op != ROOTD_AUTH) { ffpmsg("ERROR on ROOTD_USER"); ffpmsg(recbuf); return (FILE_NOT_OPENED); } /* now the password */ if (NULL != getenv("ROOTPASSWORD")) { strcpy(recbuf,getenv("ROOTPASSWORD")); } else { printf("Password: "); fgets(recbuf,MAXLEN,stdin); recbuf[strlen(recbuf)-1] = '\0'; } /* ones complement the password */ for (ii=0;(unsigned) ii includes the 4 bytes for the op, the length bytes (4) are implicit if buffer is null don't send it, not everything needs something sent */ int len; int status; int hdr[2]; len = 4; if (buffer != NULL) { len += buflen; } hdr[0] = htonl(len); hdr[1] = htonl(op); status = NET_SendRaw(sock,hdr,sizeof(hdr),NET_DEFAULT); if (status < 0) { return status; } if (buffer != NULL) { status = NET_SendRaw(sock,buffer,buflen,NET_DEFAULT); } return status; } static int root_recv_buffer(int sock, int *op, char *buffer, int buflen) { /* recv a buffer, the form is */ int recv1 = 0; int len; int status; char recbuf[MAXLEN]; status = NET_RecvRaw(sock,&len,4); if (status < 0) { return status; } recv1 += status; len = ntohl(len); /* ok, have the length, recive the operation */ len -= 4; status = NET_RecvRaw(sock,op,4); if (status < 0) { return status; } recv1 += status; *op = ntohl(*op); if (len > MAXLEN) { len = MAXLEN; } if (len > 0) { /* Get the rest of the message */ status = NET_RecvRaw(sock,recbuf,len); if (len > buflen) { len = buflen; } memcpy(buffer,recbuf,len); if (status < 0) { return status; } } recv1 += status; return recv1; } /*****************************************************************************/ /* Encode a string into MIME Base64 format string */ static int encode64(unsigned s_len, char *src, unsigned d_len, char *dst) { static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789" "+/"; unsigned triad; for (triad = 0; triad < s_len; triad += 3) { unsigned long int sr; unsigned byte; for (byte = 0; (byte<3) && (triad+byte #include #include #include #include #include #include #if defined(unix) || defined(__unix__) || defined(__unix) || defined(HAVE_UNISTD_H) #include #endif static int shared_kbase = 0; /* base for shared memory handles */ static int shared_maxseg = 0; /* max number of shared memory blocks */ static int shared_range = 0; /* max number of tried entries */ static int shared_fd = SHARED_INVALID; /* handle of global access lock file */ static int shared_gt_h = SHARED_INVALID; /* handle of global table segment */ static SHARED_LTAB *shared_lt = NULL; /* local table pointer */ static SHARED_GTAB *shared_gt = NULL; /* global table pointer */ static int shared_create_mode = 0666; /* permission flags for created objects */ static int shared_debug = 1; /* simple debugging tool, set to 0 to disable messages */ static int shared_init_called = 0; /* flag whether shared_init() has been called, used for delayed init */ /* static support routines prototypes */ static int shared_clear_entry(int idx); /* unconditionally clear entry */ static int shared_destroy_entry(int idx); /* unconditionally destroy sema & shseg and clear entry */ static int shared_mux(int idx, int mode); /* obtain exclusive access to specified segment */ static int shared_demux(int idx, int mode); /* free exclusive access to specified segment */ static int shared_process_count(int sem); /* valid only for time of invocation */ static int shared_delta_process(int sem, int delta); /* change number of processes hanging on segment */ static int shared_attach_process(int sem); static int shared_detach_process(int sem); static int shared_get_free_entry(int newhandle); /* get free entry in shared_key, or -1, entry is set rw locked */ static int shared_get_hash(long size, int idx);/* return hash value for malloc */ static long shared_adjust_size(long size); /* size must be >= 0 !!! */ static int shared_check_locked_index(int idx); /* verify that given idx is valid */ static int shared_map(int idx); /* map all tables for given idx, check for validity */ static int shared_validate(int idx, int mode); /* use intrnally inside crit.sect !!! */ /* support routines - initialization */ static int shared_clear_entry(int idx) /* unconditionally clear entry */ { if ((idx < 0) || (idx >= shared_maxseg)) return(SHARED_BADARG); shared_gt[idx].key = SHARED_INVALID; /* clear entries in global table */ shared_gt[idx].handle = SHARED_INVALID; shared_gt[idx].sem = SHARED_INVALID; shared_gt[idx].semkey = SHARED_INVALID; shared_gt[idx].nprocdebug = 0; shared_gt[idx].size = 0; shared_gt[idx].attr = 0; return(SHARED_OK); } static int shared_destroy_entry(int idx) /* unconditionally destroy sema & shseg and clear entry */ { int r, r2; union semun filler; if ((idx < 0) || (idx >= shared_maxseg)) return(SHARED_BADARG); r2 = r = SHARED_OK; filler.val = 0; /* this is to make cc happy (warning otherwise) */ if (SHARED_INVALID != shared_gt[idx].sem) r = semctl(shared_gt[idx].sem, 0, IPC_RMID, filler); /* destroy semaphore */ if (SHARED_INVALID != shared_gt[idx].handle) r2 = shmctl(shared_gt[idx].handle, IPC_RMID, 0); /* destroy shared memory segment */ if (SHARED_OK == r) r = r2; /* accumulate error code in r, free r2 */ r2 = shared_clear_entry(idx); return((SHARED_OK == r) ? r2 : r); } void shared_cleanup(void) /* this must (should) be called during exit/abort */ { int i, j, r, oktodelete, filelocked, segmentspresent; flock_t flk; struct shmid_ds ds; if (shared_debug) printf("shared_cleanup:"); if (NULL != shared_lt) { if (shared_debug) printf(" deleting segments:"); for (i=0; i>\n"); return; } int shared_init(int debug_msgs) /* initialize shared memory stuff, you have to call this routine once */ { int i; char buf[1000], *p; mode_t oldumask; shared_init_called = 1; /* tell everybody no need to call us for the 2nd time */ shared_debug = debug_msgs; /* set required debug mode */ if (shared_debug) printf("shared_init:"); shared_kbase = 0; /* adapt to current env. settings */ if (NULL != (p = getenv(SHARED_ENV_KEYBASE))) shared_kbase = atoi(p); if (0 == shared_kbase) shared_kbase = SHARED_KEYBASE; if (shared_debug) printf(" keybase=%d", shared_kbase); shared_maxseg = 0; if (NULL != (p = getenv(SHARED_ENV_MAXSEG))) shared_maxseg = atoi(p); if (0 == shared_maxseg) shared_maxseg = SHARED_MAXSEG; if (shared_debug) printf(" maxseg=%d", shared_maxseg); shared_range = 3 * shared_maxseg; if (SHARED_INVALID == shared_fd) /* create rw locking file (this file is never deleted) */ { if (shared_debug) printf(" lockfileinit="); snprintf(buf, 1000,"%s.%d.%d", SHARED_FDNAME, shared_kbase, shared_maxseg); oldumask = umask(0); shared_fd = open(buf, O_TRUNC | O_EXCL | O_CREAT | O_RDWR, shared_create_mode); umask(oldumask); if (SHARED_INVALID == shared_fd) /* or just open rw locking file, in case it already exists */ { shared_fd = open(buf, O_TRUNC | O_RDWR, shared_create_mode); if (SHARED_INVALID == shared_fd) return(SHARED_NOFILE); if (shared_debug) printf("slave"); } else { if (shared_debug) printf("master"); } } if (SHARED_INVALID == shared_gt_h) /* global table not attached, try to create it in shared memory */ { if (shared_debug) printf(" globalsharedtableinit="); shared_gt_h = shmget(shared_kbase, shared_maxseg * sizeof(SHARED_GTAB), IPC_CREAT | IPC_EXCL | shared_create_mode); /* try open as a master */ if (SHARED_INVALID == shared_gt_h) /* if failed, try to open as a slave */ { shared_gt_h = shmget(shared_kbase, shared_maxseg * sizeof(SHARED_GTAB), shared_create_mode); if (SHARED_INVALID == shared_gt_h) return(SHARED_IPCERR); /* means deleted ID residing in system, shared mem unusable ... */ shared_gt = (SHARED_GTAB *)shmat(shared_gt_h, 0, 0); /* attach segment */ if (((SHARED_GTAB *)SHARED_INVALID) == shared_gt) return(SHARED_IPCERR); if (shared_debug) printf("slave"); } else { shared_gt = (SHARED_GTAB *)shmat(shared_gt_h, 0, 0); /* attach segment */ if (((SHARED_GTAB *)SHARED_INVALID) == shared_gt) return(SHARED_IPCERR); for (i=0; i>\n"); return(SHARED_OK); } int shared_recover(int id) /* try to recover dormant segments after applic crash */ { int i, r, r2; if (NULL == shared_gt) return(SHARED_NOTINIT); /* not initialized */ if (NULL == shared_lt) return(SHARED_NOTINIT); /* not initialized */ r = SHARED_OK; for (i=0; i r2) || (0 == r2)) { if (shared_debug) printf("Bogus handle=%d nproc=%d sema=%d:", i, shared_gt[i].nprocdebug, r2); r = shared_destroy_entry(i); if (shared_debug) { printf("%s", r ? "error couldn't clear handle" : "handle cleared"); } } shared_demux(i, SHARED_RDWRITE); } return(r); /* table full */ } /* API routines - mutexes and locking */ static int shared_mux(int idx, int mode) /* obtain exclusive access to specified segment */ { flock_t flk; int r; if (0 == shared_init_called) /* delayed initialization */ { if (SHARED_OK != (r = shared_init(0))) return(r); } if (SHARED_INVALID == shared_fd) return(SHARED_NOTINIT); if ((idx < 0) || (idx >= shared_maxseg)) return(SHARED_BADARG); flk.l_type = ((mode & SHARED_RDWRITE) ? F_WRLCK : F_RDLCK); flk.l_whence = 0; flk.l_start = idx; flk.l_len = 1; if (shared_debug) printf(" [mux (%d): ", idx); if (-1 == fcntl(shared_fd, ((mode & SHARED_NOWAIT) ? F_SETLK : F_SETLKW), &flk)) { switch (errno) { case EAGAIN: ; case EACCES: if (shared_debug) printf("again]"); return(SHARED_AGAIN); default: if (shared_debug) printf("err]"); return(SHARED_IPCERR); } } if (shared_debug) printf("ok]"); return(SHARED_OK); } static int shared_demux(int idx, int mode) /* free exclusive access to specified segment */ { flock_t flk; if (SHARED_INVALID == shared_fd) return(SHARED_NOTINIT); if ((idx < 0) || (idx >= shared_maxseg)) return(SHARED_BADARG); flk.l_type = F_UNLCK; flk.l_whence = 0; flk.l_start = idx; flk.l_len = 1; if (shared_debug) printf(" [demux (%d): ", idx); if (-1 == fcntl(shared_fd, F_SETLKW, &flk)) { switch (errno) { case EAGAIN: ; case EACCES: if (shared_debug) printf("again]"); return(SHARED_AGAIN); default: if (shared_debug) printf("err]"); return(SHARED_IPCERR); } } if (shared_debug) printf("mode=%d ok]", mode); return(SHARED_OK); } static int shared_process_count(int sem) /* valid only for time of invocation */ { union semun su; su.val = 0; /* to force compiler not to give warning messages */ return(semctl(sem, 0, GETVAL, su)); /* su is unused here */ } static int shared_delta_process(int sem, int delta) /* change number of processes hanging on segment */ { struct sembuf sb; if (SHARED_INVALID == sem) return(SHARED_BADARG); /* semaphore not attached */ sb.sem_num = 0; sb.sem_op = delta; sb.sem_flg = SEM_UNDO; return((-1 == semop(sem, &sb, 1)) ? SHARED_IPCERR : SHARED_OK); } static int shared_attach_process(int sem) { if (shared_debug) printf(" [attach process]"); return(shared_delta_process(sem, 1)); } static int shared_detach_process(int sem) { if (shared_debug) printf(" [detach process]"); return(shared_delta_process(sem, -1)); } /* API routines - hashing and searching */ static int shared_get_free_entry(int newhandle) /* get newhandle, or -1, entry is set rw locked */ { if (NULL == shared_gt) return(-1); /* not initialized */ if (NULL == shared_lt) return(-1); /* not initialized */ if (newhandle < 0) return(-1); if (newhandle >= shared_maxseg) return(-1); if (shared_lt[newhandle].tcnt) return(-1); /* somebody (we) is using it */ if (shared_mux(newhandle, SHARED_NOWAIT | SHARED_RDWRITE)) return(-1); /* used by others */ if (SHARED_INVALID == shared_gt[newhandle].key) return(newhandle); /* we have found free slot, lock it and return index */ shared_demux(newhandle, SHARED_RDWRITE); if (shared_debug) printf("[free_entry - ERROR - entry unusable]"); return(-1); /* table full */ } static int shared_get_hash(long size, int idx) /* return hash value for malloc */ { static int counter = 0; int hash; hash = (counter + size * idx) % shared_range; counter = (counter + 1) % shared_range; return(hash); } static long shared_adjust_size(long size) /* size must be >= 0 !!! */ { return(((size + sizeof(BLKHEAD) + SHARED_GRANUL - 1) / SHARED_GRANUL) * SHARED_GRANUL); } /* API routines - core : malloc/realloc/free/attach/detach/lock/unlock */ int shared_malloc(long size, int mode, int newhandle) /* return idx or SHARED_INVALID */ { int h, i, r, idx, key; union semun filler; BLKHEAD *bp; if (0 == shared_init_called) /* delayed initialization */ { if (SHARED_OK != (r = shared_init(0))) return(r); } if (shared_debug) printf("malloc (size = %ld, mode = %d):", size, mode); if (size < 0) return(SHARED_INVALID); if (-1 == (idx = shared_get_free_entry(newhandle))) return(SHARED_INVALID); if (shared_debug) printf(" idx=%d", idx); for (i = 0; ; i++) { if (i >= shared_range) /* table full, signal error & exit */ { shared_demux(idx, SHARED_RDWRITE); return(SHARED_INVALID); } key = shared_kbase + ((i + shared_get_hash(size, idx)) % shared_range); if (shared_debug) printf(" key=%d", key); h = shmget(key, shared_adjust_size(size), IPC_CREAT | IPC_EXCL | shared_create_mode); if (shared_debug) printf(" handle=%d", h); if (SHARED_INVALID == h) continue; /* segment already accupied */ bp = (BLKHEAD *)shmat(h, 0, 0); /* try attach */ if (shared_debug) printf(" p=%p", bp); if (((BLKHEAD *)SHARED_INVALID) == bp) /* cannot attach, delete segment, try with another key */ { shmctl(h, IPC_RMID, 0); continue; } /* now create semaphor counting number of processes attached */ if (SHARED_INVALID == (shared_gt[idx].sem = semget(key, 1, IPC_CREAT | IPC_EXCL | shared_create_mode))) { shmdt((void *)bp); /* cannot create segment, delete everything */ shmctl(h, IPC_RMID, 0); continue; /* try with another key */ } if (shared_debug) printf(" sem=%d", shared_gt[idx].sem); if (shared_attach_process(shared_gt[idx].sem)) /* try attach process */ { semctl(shared_gt[idx].sem, 0, IPC_RMID, filler); /* destroy semaphore */ shmdt((char *)bp); /* detach shared mem segment */ shmctl(h, IPC_RMID, 0); /* destroy shared mem segment */ continue; /* try with another key */ } bp->s.tflag = BLOCK_SHARED; /* fill in data in segment's header (this is really not necessary) */ bp->s.ID[0] = SHARED_ID_0; bp->s.ID[1] = SHARED_ID_1; bp->s.handle = idx; /* used in yorick */ if (mode & SHARED_RESIZE) { if (shmdt((char *)bp)) r = SHARED_IPCERR; /* if segment is resizable, then detach segment */ shared_lt[idx].p = NULL; } else { shared_lt[idx].p = bp; } shared_lt[idx].tcnt = 1; /* one thread using segment */ shared_lt[idx].lkcnt = 0; /* no locks at the moment */ shared_lt[idx].seekpos = 0L; /* r/w pointer positioned at beg of block */ shared_gt[idx].handle = h; /* fill in data in global table */ shared_gt[idx].size = size; shared_gt[idx].attr = mode; shared_gt[idx].semkey = key; shared_gt[idx].key = key; shared_gt[idx].nprocdebug = 0; break; } shared_demux(idx, SHARED_RDWRITE); /* hope this will not fail */ return(idx); } int shared_attach(int idx) { int r, r2; if (SHARED_OK != (r = shared_mux(idx, SHARED_RDWRITE | SHARED_WAIT))) return(r); if (SHARED_OK != (r = shared_map(idx))) { shared_demux(idx, SHARED_RDWRITE); return(r); } if (shared_attach_process(shared_gt[idx].sem)) /* try attach process */ { shmdt((char *)(shared_lt[idx].p)); /* cannot attach process, detach everything */ shared_lt[idx].p = NULL; shared_demux(idx, SHARED_RDWRITE); return(SHARED_BADARG); } shared_lt[idx].tcnt++; /* one more thread is using segment */ if (shared_gt[idx].attr & SHARED_RESIZE) /* if resizeable, detach and return special pointer */ { if (shmdt((char *)(shared_lt[idx].p))) r = SHARED_IPCERR; /* if segment is resizable, then detach segment */ shared_lt[idx].p = NULL; } shared_lt[idx].seekpos = 0L; /* r/w pointer positioned at beg of block */ r2 = shared_demux(idx, SHARED_RDWRITE); return(r ? r : r2); } static int shared_check_locked_index(int idx) /* verify that given idx is valid */ { int r; if (0 == shared_init_called) /* delayed initialization */ { if (SHARED_OK != (r = shared_init(0))) return(r); } if ((idx < 0) || (idx >= shared_maxseg)) return(SHARED_BADARG); if (NULL == shared_lt[idx].p) return(SHARED_BADARG); /* NULL pointer, not attached ?? */ if (0 == shared_lt[idx].lkcnt) return(SHARED_BADARG); /* not locked ?? */ if ((SHARED_ID_0 != (shared_lt[idx].p)->s.ID[0]) || (SHARED_ID_1 != (shared_lt[idx].p)->s.ID[1]) || (BLOCK_SHARED != (shared_lt[idx].p)->s.tflag)) /* invalid data in segment */ return(SHARED_BADARG); return(SHARED_OK); } static int shared_map(int idx) /* map all tables for given idx, check for validity */ { int h; /* have to obtain excl. access before calling shared_map */ BLKHEAD *bp; if ((idx < 0) || (idx >= shared_maxseg)) return(SHARED_BADARG); if (SHARED_INVALID == shared_gt[idx].key) return(SHARED_BADARG); if (SHARED_INVALID == (h = shmget(shared_gt[idx].key, 1, shared_create_mode))) return(SHARED_BADARG); if (((BLKHEAD *)SHARED_INVALID) == (bp = (BLKHEAD *)shmat(h, 0, 0))) return(SHARED_BADARG); if ((SHARED_ID_0 != bp->s.ID[0]) || (SHARED_ID_1 != bp->s.ID[1]) || (BLOCK_SHARED != bp->s.tflag) || (h != shared_gt[idx].handle)) { shmdt((char *)bp); /* invalid segment, detach everything */ return(SHARED_BADARG); } if (shared_gt[idx].sem != semget(shared_gt[idx].semkey, 1, shared_create_mode)) /* check if sema is still there */ { shmdt((char *)bp); /* cannot attach semaphore, detach everything */ return(SHARED_BADARG); } shared_lt[idx].p = bp; /* store pointer to shmem data */ return(SHARED_OK); } static int shared_validate(int idx, int mode) /* use intrnally inside crit.sect !!! */ { int r; if (SHARED_OK != (r = shared_mux(idx, mode))) return(r); /* idx checked by shared_mux */ if (NULL == shared_lt[idx].p) if (SHARED_OK != (r = shared_map(idx))) { shared_demux(idx, mode); return(r); } if ((SHARED_ID_0 != (shared_lt[idx].p)->s.ID[0]) || (SHARED_ID_1 != (shared_lt[idx].p)->s.ID[1]) || (BLOCK_SHARED != (shared_lt[idx].p)->s.tflag)) { shared_demux(idx, mode); return(r); } return(SHARED_OK); } SHARED_P shared_realloc(int idx, long newsize) /* realloc shared memory segment */ { int h, key, i, r; BLKHEAD *bp; long transfersize; r = SHARED_OK; if (newsize < 0) return(NULL); if (shared_check_locked_index(idx)) return(NULL); if (0 == (shared_gt[idx].attr & SHARED_RESIZE)) return(NULL); if (-1 != shared_lt[idx].lkcnt) return(NULL); /* check for RW lock */ if (shared_adjust_size(shared_gt[idx].size) == shared_adjust_size(newsize)) { shared_gt[idx].size = newsize; return((SHARED_P)((shared_lt[idx].p) + 1)); } for (i = 0; ; i++) { if (i >= shared_range) return(NULL); /* table full, signal error & exit */ key = shared_kbase + ((i + shared_get_hash(newsize, idx)) % shared_range); h = shmget(key, shared_adjust_size(newsize), IPC_CREAT | IPC_EXCL | shared_create_mode); if (SHARED_INVALID == h) continue; /* segment already accupied */ bp = (BLKHEAD *)shmat(h, 0, 0); /* try attach */ if (((BLKHEAD *)SHARED_INVALID) == bp) /* cannot attach, delete segment, try with another key */ { shmctl(h, IPC_RMID, 0); continue; } *bp = *(shared_lt[idx].p); /* copy header, then data */ transfersize = ((newsize < shared_gt[idx].size) ? newsize : shared_gt[idx].size); if (transfersize > 0) memcpy((void *)(bp + 1), (void *)((shared_lt[idx].p) + 1), transfersize); if (shmdt((char *)(shared_lt[idx].p))) r = SHARED_IPCERR; /* try to detach old segment */ if (shmctl(shared_gt[idx].handle, IPC_RMID, 0)) if (SHARED_OK == r) r = SHARED_IPCERR; /* destroy old shared memory segment */ shared_gt[idx].size = newsize; /* signal new size */ shared_gt[idx].handle = h; /* signal new handle */ shared_gt[idx].key = key; /* signal new key */ shared_lt[idx].p = bp; break; } return((SHARED_P)(bp + 1)); } int shared_free(int idx) /* detach segment, if last process & !PERSIST, destroy segment */ { int cnt, r, r2; if (SHARED_OK != (r = shared_validate(idx, SHARED_RDWRITE | SHARED_WAIT))) return(r); if (SHARED_OK != (r = shared_detach_process(shared_gt[idx].sem))) /* update number of processes using segment */ { shared_demux(idx, SHARED_RDWRITE); return(r); } shared_lt[idx].tcnt--; /* update number of threads using segment */ if (shared_lt[idx].tcnt > 0) return(shared_demux(idx, SHARED_RDWRITE)); /* if more threads are using segment we are done */ if (shmdt((char *)(shared_lt[idx].p))) /* if, we are the last thread, try to detach segment */ { shared_demux(idx, SHARED_RDWRITE); return(SHARED_IPCERR); } shared_lt[idx].p = NULL; /* clear entry in local table */ shared_lt[idx].seekpos = 0L; /* r/w pointer positioned at beg of block */ if (-1 == (cnt = shared_process_count(shared_gt[idx].sem))) /* get number of processes hanging on segment */ { shared_demux(idx, SHARED_RDWRITE); return(SHARED_IPCERR); } if ((0 == cnt) && (0 == (shared_gt[idx].attr & SHARED_PERSIST))) r = shared_destroy_entry(idx); /* no procs on seg, destroy it */ r2 = shared_demux(idx, SHARED_RDWRITE); return(r ? r : r2); } SHARED_P shared_lock(int idx, int mode) /* lock given segment for exclusive access */ { int r; if (shared_mux(idx, mode)) return(NULL); /* idx checked by shared_mux */ if (0 != shared_lt[idx].lkcnt) /* are we already locked ?? */ if (SHARED_OK != (r = shared_map(idx))) { shared_demux(idx, mode); return(NULL); } if (NULL == shared_lt[idx].p) /* stupid pointer ?? */ if (SHARED_OK != (r = shared_map(idx))) { shared_demux(idx, mode); return(NULL); } if ((SHARED_ID_0 != (shared_lt[idx].p)->s.ID[0]) || (SHARED_ID_1 != (shared_lt[idx].p)->s.ID[1]) || (BLOCK_SHARED != (shared_lt[idx].p)->s.tflag)) { shared_demux(idx, mode); return(NULL); } if (mode & SHARED_RDWRITE) { shared_lt[idx].lkcnt = -1; shared_gt[idx].nprocdebug++; } else shared_lt[idx].lkcnt++; shared_lt[idx].seekpos = 0L; /* r/w pointer positioned at beg of block */ return((SHARED_P)((shared_lt[idx].p) + 1)); } int shared_unlock(int idx) /* unlock given segment, assumes seg is locked !! */ { int r, r2, mode; if (SHARED_OK != (r = shared_check_locked_index(idx))) return(r); if (shared_lt[idx].lkcnt > 0) { shared_lt[idx].lkcnt--; /* unlock read lock */ mode = SHARED_RDONLY; } else { shared_lt[idx].lkcnt = 0; /* unlock write lock */ shared_gt[idx].nprocdebug--; mode = SHARED_RDWRITE; } if (0 == shared_lt[idx].lkcnt) if (shared_gt[idx].attr & SHARED_RESIZE) { if (shmdt((char *)(shared_lt[idx].p))) r = SHARED_IPCERR; /* segment is resizable, then detach segment */ shared_lt[idx].p = NULL; /* signal detachment in local table */ } r2 = shared_demux(idx, mode); /* unlock segment, rest is only parameter checking */ return(r ? r : r2); } /* API routines - support and info routines */ int shared_attr(int idx) /* get the attributes of the shared memory segment */ { int r; if (shared_check_locked_index(idx)) return(SHARED_INVALID); r = shared_gt[idx].attr; return(r); } int shared_set_attr(int idx, int newattr) /* get the attributes of the shared memory segment */ { int r; if (shared_check_locked_index(idx)) return(SHARED_INVALID); if (-1 != shared_lt[idx].lkcnt) return(SHARED_INVALID); /* ADDED - check for RW lock */ r = shared_gt[idx].attr; shared_gt[idx].attr = newattr; return(r); } int shared_set_debug(int mode) /* set/reset debug mode */ { int r = shared_debug; shared_debug = mode; return(r); } int shared_set_createmode(int mode) /* set/reset debug mode */ { int r = shared_create_mode; shared_create_mode = mode; return(r); } int shared_list(int id) { int i, r; if (NULL == shared_gt) return(SHARED_NOTINIT); /* not initialized */ if (NULL == shared_lt) return(SHARED_NOTINIT); /* not initialized */ if (shared_debug) printf("shared_list:"); r = SHARED_OK; printf(" Idx Key Nproc Size Flags\n"); printf("==============================================\n"); for (i=0; i= SHARED_ERRBASE) { printf(" cannot clear PERSIST attribute"); } if (shared_free(i)) { printf(" delete failed\n"); } else { printf(" deleted\n"); } } if (shared_debug) printf(" done\n"); return(r); /* table full */ } /************************* CFITSIO DRIVER FUNCTIONS ***************************/ int smem_init(void) { return(0); } int smem_shutdown(void) { if (shared_init_called) shared_cleanup(); return(0); } int smem_setoptions(int option) { option = 0; return(0); } int smem_getoptions(int *options) { if (NULL == options) return(SHARED_NULPTR); *options = 0; return(0); } int smem_getversion(int *version) { if (NULL == version) return(SHARED_NULPTR); *version = 10; return(0); } int smem_open(char *filename, int rwmode, int *driverhandle) { int h, nitems, r; DAL_SHM_SEGHEAD *sp; if (NULL == filename) return(SHARED_NULPTR); if (NULL == driverhandle) return(SHARED_NULPTR); nitems = sscanf(filename, "h%d", &h); if (1 != nitems) return(SHARED_BADARG); if (SHARED_OK != (r = shared_attach(h))) return(r); if (NULL == (sp = (DAL_SHM_SEGHEAD *)shared_lock(h, ((READWRITE == rwmode) ? SHARED_RDWRITE : SHARED_RDONLY)))) { shared_free(h); return(SHARED_BADARG); } if ((h != sp->h) || (DAL_SHM_SEGHEAD_ID != sp->ID)) { shared_unlock(h); shared_free(h); return(SHARED_BADARG); } *driverhandle = h; return(0); } int smem_create(char *filename, int *driverhandle) { DAL_SHM_SEGHEAD *sp; int h, sz, nitems; if (NULL == filename) return(SHARED_NULPTR); /* currently ignored */ if (NULL == driverhandle) return(SHARED_NULPTR); nitems = sscanf(filename, "h%d", &h); if (1 != nitems) return(SHARED_BADARG); if (SHARED_INVALID == (h = shared_malloc(sz = 2880 + sizeof(DAL_SHM_SEGHEAD), SHARED_RESIZE | SHARED_PERSIST, h))) return(SHARED_NOMEM); if (NULL == (sp = (DAL_SHM_SEGHEAD *)shared_lock(h, SHARED_RDWRITE))) { shared_free(h); return(SHARED_BADARG); } sp->ID = DAL_SHM_SEGHEAD_ID; sp->h = h; sp->size = sz; sp->nodeidx = -1; *driverhandle = h; return(0); } int smem_close(int driverhandle) { int r; if (SHARED_OK != (r = shared_unlock(driverhandle))) return(r); return(shared_free(driverhandle)); } int smem_remove(char *filename) { int nitems, h, r; if (NULL == filename) return(SHARED_NULPTR); nitems = sscanf(filename, "h%d", &h); if (1 != nitems) return(SHARED_BADARG); if (0 == shared_check_locked_index(h)) /* are we locked ? */ { if (-1 != shared_lt[h].lkcnt) /* are we locked RO ? */ { if (SHARED_OK != (r = shared_unlock(h))) return(r); /* yes, so relock in RW */ if (NULL == shared_lock(h, SHARED_RDWRITE)) return(SHARED_BADARG); } } else /* not locked */ { if (SHARED_OK != (r = smem_open(filename, READWRITE, &h))) return(r); /* so open in RW mode */ } shared_set_attr(h, SHARED_RESIZE); /* delete PERSIST attribute */ return(smem_close(h)); /* detach segment (this will delete it) */ } int smem_size(int driverhandle, LONGLONG *size) { if (NULL == size) return(SHARED_NULPTR); if (shared_check_locked_index(driverhandle)) return(SHARED_INVALID); *size = (LONGLONG) (shared_gt[driverhandle].size - sizeof(DAL_SHM_SEGHEAD)); return(0); } int smem_flush(int driverhandle) { if (shared_check_locked_index(driverhandle)) return(SHARED_INVALID); return(0); } int smem_seek(int driverhandle, LONGLONG offset) { if (offset < 0) return(SHARED_BADARG); if (shared_check_locked_index(driverhandle)) return(SHARED_INVALID); shared_lt[driverhandle].seekpos = offset; return(0); } int smem_read(int driverhandle, void *buffer, long nbytes) { if (NULL == buffer) return(SHARED_NULPTR); if (shared_check_locked_index(driverhandle)) return(SHARED_INVALID); if (nbytes < 0) return(SHARED_BADARG); if ((shared_lt[driverhandle].seekpos + nbytes) > shared_gt[driverhandle].size) return(SHARED_BADARG); /* read beyond EOF */ memcpy(buffer, ((char *)(((DAL_SHM_SEGHEAD *)(shared_lt[driverhandle].p + 1)) + 1)) + shared_lt[driverhandle].seekpos, nbytes); shared_lt[driverhandle].seekpos += nbytes; return(0); } int smem_write(int driverhandle, void *buffer, long nbytes) { if (NULL == buffer) return(SHARED_NULPTR); if (shared_check_locked_index(driverhandle)) return(SHARED_INVALID); if (-1 != shared_lt[driverhandle].lkcnt) return(SHARED_INVALID); /* are we locked RW ? */ if (nbytes < 0) return(SHARED_BADARG); if ((unsigned long)(shared_lt[driverhandle].seekpos + nbytes) > (unsigned long)(shared_gt[driverhandle].size - sizeof(DAL_SHM_SEGHEAD))) { /* need to realloc shmem */ if (NULL == shared_realloc(driverhandle, shared_lt[driverhandle].seekpos + nbytes + sizeof(DAL_SHM_SEGHEAD))) return(SHARED_NOMEM); } memcpy(((char *)(((DAL_SHM_SEGHEAD *)(shared_lt[driverhandle].p + 1)) + 1)) + shared_lt[driverhandle].seekpos, buffer, nbytes); shared_lt[driverhandle].seekpos += nbytes; return(0); } #endif cfitsio/drvrsmem.h0000644000225700000360000001461013246025103014012 0ustar cagordonlhea/* S H A R E D M E M O R Y D R I V E R ======================================= by Jerzy.Borkowski@obs.unige.ch 09-Mar-98 : initial version 1.0 released 23-Mar-98 : shared_malloc now accepts new handle as an argument */ #include /* this is necessary for Solaris/Linux */ #include #include #ifdef _AIX #include #else #include #endif /* configuration parameters */ #define SHARED_MAXSEG (16) /* maximum number of shared memory blocks */ #define SHARED_KEYBASE (14011963) /* base for shared memory keys, may be overriden by getenv */ #define SHARED_FDNAME ("/tmp/.shmem-lockfile") /* template for lock file name */ #define SHARED_ENV_KEYBASE ("SHMEM_LIB_KEYBASE") /* name of environment variable */ #define SHARED_ENV_MAXSEG ("SHMEM_LIB_MAXSEG") /* name of environment variable */ /* useful constants */ #define SHARED_RDONLY (0) /* flag for shared_(un)lock, lock for read */ #define SHARED_RDWRITE (1) /* flag for shared_(un)lock, lock for write */ #define SHARED_WAIT (0) /* flag for shared_lock, block if cannot lock immediate */ #define SHARED_NOWAIT (2) /* flag for shared_lock, fail if cannot lock immediate */ #define SHARED_NOLOCK (0x100) /* flag for shared_validate function */ #define SHARED_RESIZE (4) /* flag for shared_malloc, object is resizeable */ #define SHARED_PERSIST (8) /* flag for shared_malloc, object is not deleted after last proc detaches */ #define SHARED_INVALID (-1) /* invalid handle for semaphore/shared memory */ #define SHARED_EMPTY (0) /* entries for shared_used table */ #define SHARED_USED (1) #define SHARED_GRANUL (16384) /* granularity of shared_malloc allocation = phys page size, system dependent */ /* checkpoints in shared memory segments - might be omitted */ #define SHARED_ID_0 ('J') /* first byte of identifier in BLKHEAD */ #define SHARED_ID_1 ('B') /* second byte of identifier in BLKHEAD */ #define BLOCK_REG (0) /* value for tflag member of BLKHEAD */ #define BLOCK_SHARED (1) /* value for tflag member of BLKHEAD */ /* generic error codes */ #define SHARED_OK (0) #define SHARED_ERR_MIN_IDX SHARED_BADARG #define SHARED_ERR_MAX_IDX SHARED_NORESIZE #define DAL_SHM_FREE (0) #define DAL_SHM_USED (1) #define DAL_SHM_ID0 ('D') #define DAL_SHM_ID1 ('S') #define DAL_SHM_ID2 ('M') #define DAL_SHM_SEGHEAD_ID (0x19630114) /* data types */ /* BLKHEAD object is placed at the beginning of every memory segment (both shared and regular) to allow automatic recognition of segments type */ typedef union { struct BLKHEADstruct { char ID[2]; /* ID = 'JB', just as a checkpoint */ char tflag; /* is it shared memory or regular one ? */ int handle; /* this is not necessary, used only for non-resizeable objects via ptr */ } s; double d; /* for proper alignment on every machine */ } BLKHEAD; typedef void *SHARED_P; /* generic type of shared memory pointer */ typedef struct SHARED_GTABstruct /* data type used in global table */ { int sem; /* access semaphore (1 field): process count */ int semkey; /* key value used to generate semaphore handle */ int key; /* key value used to generate shared memory handle (realloc changes it) */ int handle; /* handle of shared memory segment */ int size; /* size of shared memory segment */ int nprocdebug; /* attached proc counter, helps remove zombie segments */ char attr; /* attributes of shared memory object */ } SHARED_GTAB; typedef struct SHARED_LTABstruct /* data type used in local table */ { BLKHEAD *p; /* pointer to segment (may be null) */ int tcnt; /* number of threads in this process attached to segment */ int lkcnt; /* >=0 <- number of read locks, -1 - write lock */ long seekpos; /* current pointer position, read/write/seek operations change it */ } SHARED_LTAB; /* system dependent definitions */ #ifndef HAVE_FLOCK_T typedef struct flock flock_t; #define HAVE_FLOCK_T #endif #ifndef HAVE_UNION_SEMUN union semun { int val; struct semid_ds *buf; unsigned short *array; }; #define HAVE_UNION_SEMUN #endif typedef struct DAL_SHM_SEGHEAD_STRUCT DAL_SHM_SEGHEAD; struct DAL_SHM_SEGHEAD_STRUCT { int ID; /* ID for debugging */ int h; /* handle of sh. mem */ int size; /* size of data area */ int nodeidx; /* offset of root object (node struct typically) */ }; /* API routines */ #ifdef __cplusplus extern "C" { #endif void shared_cleanup(void); /* must be called at exit/abort */ int shared_init(int debug_msgs); /* must be called before any other shared memory routine */ int shared_recover(int id); /* try to recover dormant segment(s) after applic crash */ int shared_malloc(long size, int mode, int newhandle); /* allocate n-bytes of shared memory */ int shared_attach(int idx); /* attach to segment given index to table */ int shared_free(int idx); /* release shared memory */ SHARED_P shared_lock(int idx, int mode); /* lock segment for reading */ SHARED_P shared_realloc(int idx, long newsize); /* reallocate n-bytes of shared memory (ON LOCKED SEGMENT ONLY) */ int shared_size(int idx); /* get size of attached shared memory segment (ON LOCKED SEGMENT ONLY) */ int shared_attr(int idx); /* get attributes of attached shared memory segment (ON LOCKED SEGMENT ONLY) */ int shared_set_attr(int idx, int newattr); /* set attributes of attached shared memory segment (ON LOCKED SEGMENT ONLY) */ int shared_unlock(int idx); /* unlock segment (ON LOCKED SEGMENT ONLY) */ int shared_set_debug(int debug_msgs); /* set/reset debug mode */ int shared_set_createmode(int mode); /* set/reset debug mode */ int shared_list(int id); /* list segment(s) */ int shared_uncond_delete(int id); /* uncondintionally delete (NOWAIT operation) segment(s) */ int shared_getaddr(int id, char **address); /* get starting address of FITS file in segment */ int smem_init(void); int smem_shutdown(void); int smem_setoptions(int options); int smem_getoptions(int *options); int smem_getversion(int *version); int smem_open(char *filename, int rwmode, int *driverhandle); int smem_create(char *filename, int *driverhandle); int smem_close(int driverhandle); int smem_remove(char *filename); int smem_size(int driverhandle, LONGLONG *size); int smem_flush(int driverhandle); int smem_seek(int driverhandle, LONGLONG offset); int smem_read(int driverhandle, void *buffer, long nbytes); int smem_write(int driverhandle, void *buffer, long nbytes); #ifdef __cplusplus } #endif cfitsio/editcol.c0000644000225700000360000024700213246025103013574 0ustar cagordonlhea/* This file, editcol.c, contains the set of FITSIO routines that */ /* insert or delete rows or columns in a table or resize an image */ /* The FITSIO software was written by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ #include #include #include #include "fitsio2.h" /*--------------------------------------------------------------------------*/ int ffrsim(fitsfile *fptr, /* I - FITS file pointer */ int bitpix, /* I - bits per pixel */ int naxis, /* I - number of axes in the array */ long *naxes, /* I - size of each axis */ int *status) /* IO - error status */ /* resize an existing primary array or IMAGE extension. */ { LONGLONG tnaxes[99]; int ii; if (*status > 0) return(*status); for (ii = 0; (ii < naxis) && (ii < 99); ii++) tnaxes[ii] = naxes[ii]; ffrsimll(fptr, bitpix, naxis, tnaxes, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffrsimll(fitsfile *fptr, /* I - FITS file pointer */ int bitpix, /* I - bits per pixel */ int naxis, /* I - number of axes in the array */ LONGLONG *naxes, /* I - size of each axis */ int *status) /* IO - error status */ /* resize an existing primary array or IMAGE extension. */ { int ii, simple, obitpix, onaxis, extend, nmodify; long nblocks, longval; long pcount, gcount, longbitpix; LONGLONG onaxes[99], newsize, oldsize; char comment[FLEN_COMMENT], keyname[FLEN_KEYWORD], message[FLEN_ERRMSG]; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } /* rescan header if data structure is undefined */ else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) return(*status); /* get current image size parameters */ if (ffghprll(fptr, 99, &simple, &obitpix, &onaxis, onaxes, &pcount, &gcount, &extend, status) > 0) return(*status); longbitpix = bitpix; /* test for the 2 special cases that represent unsigned integers */ if (longbitpix == USHORT_IMG) longbitpix = SHORT_IMG; else if (longbitpix == ULONG_IMG) longbitpix = LONG_IMG; /* test that the new values are legal */ if (longbitpix != BYTE_IMG && longbitpix != SHORT_IMG && longbitpix != LONG_IMG && longbitpix != LONGLONG_IMG && longbitpix != FLOAT_IMG && longbitpix != DOUBLE_IMG) { snprintf(message, FLEN_ERRMSG, "Illegal value for BITPIX keyword: %d", bitpix); ffpmsg(message); return(*status = BAD_BITPIX); } if (naxis < 0 || naxis > 999) { snprintf(message, FLEN_ERRMSG, "Illegal value for NAXIS keyword: %d", naxis); ffpmsg(message); return(*status = BAD_NAXIS); } if (naxis == 0) newsize = 0; else newsize = 1; for (ii = 0; ii < naxis; ii++) { if (naxes[ii] < 0) { snprintf(message, FLEN_ERRMSG, "Illegal value for NAXIS%d keyword: %.0f", ii + 1, (double) (naxes[ii])); ffpmsg(message); return(*status = BAD_NAXES); } newsize *= naxes[ii]; /* compute new image size, in pixels */ } /* compute size of old image, in bytes */ if (onaxis == 0) oldsize = 0; else { oldsize = 1; for (ii = 0; ii < onaxis; ii++) oldsize *= onaxes[ii]; oldsize = (oldsize + pcount) * gcount * (abs(obitpix) / 8); } oldsize = (oldsize + 2879) / 2880; /* old size, in blocks */ newsize = (newsize + pcount) * gcount * (abs(longbitpix) / 8); newsize = (newsize + 2879) / 2880; /* new size, in blocks */ if (newsize > oldsize) /* have to insert new blocks for image */ { nblocks = (long) (newsize - oldsize); if (ffiblk(fptr, nblocks, 1, status) > 0) return(*status); } else if (oldsize > newsize) /* have to delete blocks from image */ { nblocks = (long) (oldsize - newsize); if (ffdblk(fptr, nblocks, status) > 0) return(*status); } /* now update the header keywords */ strcpy(comment,"&"); /* special value to leave comments unchanged */ if (longbitpix != obitpix) { /* update BITPIX value */ ffmkyj(fptr, "BITPIX", longbitpix, comment, status); } if (naxis != onaxis) { /* update NAXIS value */ longval = naxis; ffmkyj(fptr, "NAXIS", longval, comment, status); } /* modify the existing NAXISn keywords */ nmodify = minvalue(naxis, onaxis); for (ii = 0; ii < nmodify; ii++) { ffkeyn("NAXIS", ii+1, keyname, status); ffmkyj(fptr, keyname, naxes[ii], comment, status); } if (naxis > onaxis) /* insert additional NAXISn keywords */ { strcpy(comment,"length of data axis"); for (ii = onaxis; ii < naxis; ii++) { ffkeyn("NAXIS", ii+1, keyname, status); ffikyj(fptr, keyname, naxes[ii], comment, status); } } else if (onaxis > naxis) /* delete old NAXISn keywords */ { for (ii = naxis; ii < onaxis; ii++) { ffkeyn("NAXIS", ii+1, keyname, status); ffdkey(fptr, keyname, status); } } /* Update the BSCALE and BZERO keywords, if an unsigned integer image */ if (bitpix == USHORT_IMG) { strcpy(comment, "offset data range to that of unsigned short"); ffukyg(fptr, "BZERO", 32768., 0, comment, status); strcpy(comment, "default scaling factor"); ffukyg(fptr, "BSCALE", 1.0, 0, comment, status); } else if (bitpix == ULONG_IMG) { strcpy(comment, "offset data range to that of unsigned long"); ffukyg(fptr, "BZERO", 2147483648., 0, comment, status); strcpy(comment, "default scaling factor"); ffukyg(fptr, "BSCALE", 1.0, 0, comment, status); } /* re-read the header, to make sure structures are updated */ ffrdef(fptr, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffirow(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG firstrow, /* I - insert space AFTER this row */ /* 0 = insert space at beginning of table */ LONGLONG nrows, /* I - number of rows to insert */ int *status) /* IO - error status */ /* insert NROWS blank rows immediated after row firstrow (1 = first row). Set firstrow = 0 to insert space at the beginning of the table. */ { int tstatus; LONGLONG naxis1, naxis2; LONGLONG datasize, firstbyte, nshift, nbytes; LONGLONG freespace; long nblock; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } /* rescan header if data structure is undefined */ else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) return(*status); if ((fptr->Fptr)->hdutype == IMAGE_HDU) { ffpmsg("Can only add rows to TABLE or BINTABLE extension (ffirow)"); return(*status = NOT_TABLE); } if (nrows < 0 ) return(*status = NEG_BYTES); else if (nrows == 0) return(*status); /* no op, so just return */ /* get the current size of the table */ /* use internal structure since NAXIS2 keyword may not be up to date */ naxis1 = (fptr->Fptr)->rowlength; naxis2 = (fptr->Fptr)->numrows; if (firstrow > naxis2) { ffpmsg( "Insert position greater than the number of rows in the table (ffirow)"); return(*status = BAD_ROW_NUM); } else if (firstrow < 0) { ffpmsg("Insert position is less than 0 (ffirow)"); return(*status = BAD_ROW_NUM); } /* current data size */ datasize = (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize; freespace = ( ( (datasize + 2879) / 2880) * 2880) - datasize; nshift = naxis1 * nrows; /* no. of bytes to add to table */ if ( (freespace - nshift) < 0) /* not enough existing space? */ { nblock = (long) ((nshift - freespace + 2879) / 2880); /* number of blocks */ ffiblk(fptr, nblock, 1, status); /* insert the blocks */ } firstbyte = naxis1 * firstrow; /* relative insert position */ nbytes = datasize - firstbyte; /* no. of bytes to shift down */ firstbyte += ((fptr->Fptr)->datastart); /* absolute insert position */ ffshft(fptr, firstbyte, nbytes, nshift, status); /* shift rows and heap */ /* update the heap starting address */ (fptr->Fptr)->heapstart += nshift; /* update the THEAP keyword if it exists */ tstatus = 0; ffmkyj(fptr, "THEAP", (fptr->Fptr)->heapstart, "&", &tstatus); /* update the NAXIS2 keyword */ ffmkyj(fptr, "NAXIS2", naxis2 + nrows, "&", status); ((fptr->Fptr)->numrows) += nrows; ((fptr->Fptr)->origrows) += nrows; return(*status); } /*--------------------------------------------------------------------------*/ int ffdrow(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG firstrow, /* I - first row to delete (1 = first) */ LONGLONG nrows, /* I - number of rows to delete */ int *status) /* IO - error status */ /* delete NROWS rows from table starting with firstrow (1 = first row of table). */ { int tstatus; LONGLONG naxis1, naxis2; LONGLONG datasize, firstbyte, nbytes, nshift; LONGLONG freespace; long nblock; char comm[FLEN_COMMENT]; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } /* rescan header if data structure is undefined */ else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) return(*status); if ((fptr->Fptr)->hdutype == IMAGE_HDU) { ffpmsg("Can only delete rows in TABLE or BINTABLE extension (ffdrow)"); return(*status = NOT_TABLE); } if (nrows < 0 ) return(*status = NEG_BYTES); else if (nrows == 0) return(*status); /* no op, so just return */ ffgkyjj(fptr, "NAXIS1", &naxis1, comm, status); /* get the current */ /* ffgkyj(fptr, "NAXIS2", &naxis2, comm, status);*/ /* size of the table */ /* the NAXIS2 keyword may not be up to date, so use the structure value */ naxis2 = (fptr->Fptr)->numrows; if (firstrow > naxis2) { ffpmsg( "Delete position greater than the number of rows in the table (ffdrow)"); return(*status = BAD_ROW_NUM); } else if (firstrow < 1) { ffpmsg("Delete position is less than 1 (ffdrow)"); return(*status = BAD_ROW_NUM); } else if (firstrow + nrows - 1 > naxis2) { ffpmsg("No. of rows to delete exceeds size of table (ffdrow)"); return(*status = BAD_ROW_NUM); } nshift = naxis1 * nrows; /* no. of bytes to delete from table */ /* cur size of data */ datasize = (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize; firstbyte = naxis1 * (firstrow + nrows - 1); /* relative del pos */ nbytes = datasize - firstbyte; /* no. of bytes to shift up */ firstbyte += ((fptr->Fptr)->datastart); /* absolute delete position */ ffshft(fptr, firstbyte, nbytes, nshift * (-1), status); /* shift data */ freespace = ( ( (datasize + 2879) / 2880) * 2880) - datasize; nblock = (long) ((nshift + freespace) / 2880); /* number of blocks */ /* delete integral number blocks */ if (nblock > 0) ffdblk(fptr, nblock, status); /* update the heap starting address */ (fptr->Fptr)->heapstart -= nshift; /* update the THEAP keyword if it exists */ tstatus = 0; ffmkyj(fptr, "THEAP", (long)(fptr->Fptr)->heapstart, "&", &tstatus); /* update the NAXIS2 keyword */ ffmkyj(fptr, "NAXIS2", naxis2 - nrows, "&", status); ((fptr->Fptr)->numrows) -= nrows; ((fptr->Fptr)->origrows) -= nrows; /* Update the heap data, if any. This will remove any orphaned data */ /* that was only pointed to by the rows that have been deleted */ ffcmph(fptr, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffdrrg(fitsfile *fptr, /* I - FITS file pointer to table */ char *ranges, /* I - ranges of rows to delete (1 = first) */ int *status) /* IO - error status */ /* delete the ranges of rows from the table (1 = first row of table). The 'ranges' parameter typically looks like: '10-20, 30 - 40, 55' or '50-' and gives a list of rows or row ranges separated by commas. */ { char *cptr; int nranges, nranges2, ii; long *minrow, *maxrow, nrows, *rowarray, jj, kk; LONGLONG naxis2; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } /* rescan header if data structure is undefined */ else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) return(*status); if ((fptr->Fptr)->hdutype == IMAGE_HDU) { ffpmsg("Can only delete rows in TABLE or BINTABLE extension (ffdrrg)"); return(*status = NOT_TABLE); } /* the NAXIS2 keyword may not be up to date, so use the structure value */ naxis2 = (fptr->Fptr)->numrows; /* find how many ranges were specified ( = no. of commas in string + 1) */ cptr = ranges; for (nranges = 1; (cptr = strchr(cptr, ',')); nranges++) cptr++; minrow = calloc(nranges, sizeof(long)); maxrow = calloc(nranges, sizeof(long)); if (!minrow || !maxrow) { *status = MEMORY_ALLOCATION; ffpmsg("failed to allocate memory for row ranges (ffdrrg)"); if (maxrow) free(maxrow); if (minrow) free(minrow); return(*status); } /* parse range list into array of range min and max values */ ffrwrg(ranges, naxis2, nranges, &nranges2, minrow, maxrow, status); if (*status > 0 || nranges2 == 0) { free(maxrow); free(minrow); return(*status); } /* determine total number or rows to delete */ nrows = 0; for (ii = 0; ii < nranges2; ii++) { nrows = nrows + maxrow[ii] - minrow[ii] + 1; } rowarray = calloc(nrows, sizeof(long)); if (!rowarray) { *status = MEMORY_ALLOCATION; ffpmsg("failed to allocate memory for row array (ffdrrg)"); return(*status); } for (kk = 0, ii = 0; ii < nranges2; ii++) { for (jj = minrow[ii]; jj <= maxrow[ii]; jj++) { rowarray[kk] = jj; kk++; } } /* delete the rows */ ffdrws(fptr, rowarray, nrows, status); free(rowarray); free(maxrow); free(minrow); return(*status); } /*--------------------------------------------------------------------------*/ int ffdrws(fitsfile *fptr, /* I - FITS file pointer */ long *rownum, /* I - list of rows to delete (1 = first) */ long nrows, /* I - number of rows to delete */ int *status) /* IO - error status */ /* delete the list of rows from the table (1 = first row of table). */ { LONGLONG naxis1, naxis2, insertpos, nextrowpos; long ii, nextrow; char comm[FLEN_COMMENT]; unsigned char *buffer; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); /* rescan header if data structure is undefined */ if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) return(*status); if ((fptr->Fptr)->hdutype == IMAGE_HDU) { ffpmsg("Can only delete rows in TABLE or BINTABLE extension (ffdrws)"); return(*status = NOT_TABLE); } if (nrows < 0 ) return(*status = NEG_BYTES); else if (nrows == 0) return(*status); /* no op, so just return */ ffgkyjj(fptr, "NAXIS1", &naxis1, comm, status); /* row width */ ffgkyjj(fptr, "NAXIS2", &naxis2, comm, status); /* number of rows */ /* check that input row list is in ascending order */ for (ii = 1; ii < nrows; ii++) { if (rownum[ii - 1] >= rownum[ii]) { ffpmsg("row numbers are not in increasing order (ffdrws)"); return(*status = BAD_ROW_NUM); } } if (rownum[0] < 1) { ffpmsg("first row to delete is less than 1 (ffdrws)"); return(*status = BAD_ROW_NUM); } else if (rownum[nrows - 1] > naxis2) { ffpmsg("last row to delete exceeds size of table (ffdrws)"); return(*status = BAD_ROW_NUM); } buffer = (unsigned char *) malloc( (size_t) naxis1); /* buffer for one row */ if (!buffer) { ffpmsg("malloc failed (ffdrws)"); return(*status = MEMORY_ALLOCATION); } /* byte location to start of first row to delete, and the next row */ insertpos = (fptr->Fptr)->datastart + ((rownum[0] - 1) * naxis1); nextrowpos = insertpos + naxis1; nextrow = rownum[0] + 1; /* work through the list of rows to delete */ for (ii = 1; ii < nrows; nextrow++, nextrowpos += naxis1) { if (nextrow < rownum[ii]) { /* keep this row, so copy it to the new position */ ffmbyt(fptr, nextrowpos, REPORT_EOF, status); ffgbyt(fptr, naxis1, buffer, status); /* read the bytes */ ffmbyt(fptr, insertpos, IGNORE_EOF, status); ffpbyt(fptr, naxis1, buffer, status); /* write the bytes */ if (*status > 0) { ffpmsg("error while copying good rows in table (ffdrws)"); free(buffer); return(*status); } insertpos += naxis1; } else { /* skip over this row since it is in the list */ ii++; } } /* finished with all the rows to delete; copy remaining rows */ while(nextrow <= naxis2) { ffmbyt(fptr, nextrowpos, REPORT_EOF, status); ffgbyt(fptr, naxis1, buffer, status); /* read the bytes */ ffmbyt(fptr, insertpos, IGNORE_EOF, status); ffpbyt(fptr, naxis1, buffer, status); /* write the bytes */ if (*status > 0) { ffpmsg("failed to copy remaining rows in table (ffdrws)"); free(buffer); return(*status); } insertpos += naxis1; nextrowpos += naxis1; nextrow++; } free(buffer); /* now delete the empty rows at the end of the table */ ffdrow(fptr, naxis2 - nrows + 1, nrows, status); /* Update the heap data, if any. This will remove any orphaned data */ /* that was only pointed to by the rows that have been deleted */ ffcmph(fptr, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffdrwsll(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG *rownum, /* I - list of rows to delete (1 = first) */ LONGLONG nrows, /* I - number of rows to delete */ int *status) /* IO - error status */ /* delete the list of rows from the table (1 = first row of table). */ { LONGLONG insertpos, nextrowpos; LONGLONG naxis1, naxis2, ii, nextrow; char comm[FLEN_COMMENT]; unsigned char *buffer; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); /* rescan header if data structure is undefined */ if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) return(*status); if ((fptr->Fptr)->hdutype == IMAGE_HDU) { ffpmsg("Can only delete rows in TABLE or BINTABLE extension (ffdrws)"); return(*status = NOT_TABLE); } if (nrows < 0 ) return(*status = NEG_BYTES); else if (nrows == 0) return(*status); /* no op, so just return */ ffgkyjj(fptr, "NAXIS1", &naxis1, comm, status); /* row width */ ffgkyjj(fptr, "NAXIS2", &naxis2, comm, status); /* number of rows */ /* check that input row list is in ascending order */ for (ii = 1; ii < nrows; ii++) { if (rownum[ii - 1] >= rownum[ii]) { ffpmsg("row numbers are not in increasing order (ffdrws)"); return(*status = BAD_ROW_NUM); } } if (rownum[0] < 1) { ffpmsg("first row to delete is less than 1 (ffdrws)"); return(*status = BAD_ROW_NUM); } else if (rownum[nrows - 1] > naxis2) { ffpmsg("last row to delete exceeds size of table (ffdrws)"); return(*status = BAD_ROW_NUM); } buffer = (unsigned char *) malloc( (size_t) naxis1); /* buffer for one row */ if (!buffer) { ffpmsg("malloc failed (ffdrwsll)"); return(*status = MEMORY_ALLOCATION); } /* byte location to start of first row to delete, and the next row */ insertpos = (fptr->Fptr)->datastart + ((rownum[0] - 1) * naxis1); nextrowpos = insertpos + naxis1; nextrow = rownum[0] + 1; /* work through the list of rows to delete */ for (ii = 1; ii < nrows; nextrow++, nextrowpos += naxis1) { if (nextrow < rownum[ii]) { /* keep this row, so copy it to the new position */ ffmbyt(fptr, nextrowpos, REPORT_EOF, status); ffgbyt(fptr, naxis1, buffer, status); /* read the bytes */ ffmbyt(fptr, insertpos, IGNORE_EOF, status); ffpbyt(fptr, naxis1, buffer, status); /* write the bytes */ if (*status > 0) { ffpmsg("error while copying good rows in table (ffdrws)"); free(buffer); return(*status); } insertpos += naxis1; } else { /* skip over this row since it is in the list */ ii++; } } /* finished with all the rows to delete; copy remaining rows */ while(nextrow <= naxis2) { ffmbyt(fptr, nextrowpos, REPORT_EOF, status); ffgbyt(fptr, naxis1, buffer, status); /* read the bytes */ ffmbyt(fptr, insertpos, IGNORE_EOF, status); ffpbyt(fptr, naxis1, buffer, status); /* write the bytes */ if (*status > 0) { ffpmsg("failed to copy remaining rows in table (ffdrws)"); free(buffer); return(*status); } insertpos += naxis1; nextrowpos += naxis1; nextrow++; } free(buffer); /* now delete the empty rows at the end of the table */ ffdrow(fptr, naxis2 - nrows + 1, nrows, status); /* Update the heap data, if any. This will remove any orphaned data */ /* that was only pointed to by the rows that have been deleted */ ffcmph(fptr, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffrwrg( char *rowlist, /* I - list of rows and row ranges */ LONGLONG maxrows, /* I - number of rows in the table */ int maxranges, /* I - max number of ranges to be returned */ int *numranges, /* O - number ranges returned */ long *minrow, /* O - first row in each range */ long *maxrow, /* O - last row in each range */ int *status) /* IO - status value */ { /* parse the input list of row ranges, returning the number of ranges, and the min and max row value in each range. The only characters allowed in the input rowlist are decimal digits, minus sign, and comma (and non-significant spaces) Example: list = "10-20, 30-35,50" would return numranges = 3, minrow[] = {10, 30, 50}, maxrow[] = {20, 35, 50} error is returned if min value of range is > max value of range or if the ranges are not monotonically increasing. */ char *next; long minval, maxval; if (*status > 0) return(*status); if (maxrows <= 0 ) { *status = RANGE_PARSE_ERROR; ffpmsg("Input maximum range value is <= 0 (fits_parse_ranges)"); return(*status); } next = rowlist; *numranges = 0; while (*next == ' ')next++; /* skip spaces */ while (*next != '\0') { /* find min value of next range; *next must be '-' or a digit */ if (*next == '-') { minval = 1; /* implied minrow value = 1 */ } else if ( isdigit((int) *next) ) { minval = strtol(next, &next, 10); } else { *status = RANGE_PARSE_ERROR; ffpmsg("Syntax error in this row range list:"); ffpmsg(rowlist); return(*status); } while (*next == ' ')next++; /* skip spaces */ /* find max value of next range; *next must be '-', or ',' */ if (*next == '-') { next++; while (*next == ' ')next++; /* skip spaces */ if ( isdigit((int) *next) ) { maxval = strtol(next, &next, 10); } else if (*next == ',' || *next == '\0') { maxval = (long) maxrows; /* implied max value */ } else { *status = RANGE_PARSE_ERROR; ffpmsg("Syntax error in this row range list:"); ffpmsg(rowlist); return(*status); } } else if (*next == ',' || *next == '\0') { maxval = minval; /* only a single integer in this range */ } else { *status = RANGE_PARSE_ERROR; ffpmsg("Syntax error in this row range list:"); ffpmsg(rowlist); return(*status); } if (*numranges + 1 > maxranges) { *status = RANGE_PARSE_ERROR; ffpmsg("Overflowed maximum number of ranges (fits_parse_ranges)"); return(*status); } if (minval < 1 ) { *status = RANGE_PARSE_ERROR; ffpmsg("Syntax error in this row range list: row number < 1"); ffpmsg(rowlist); return(*status); } if (maxval < minval) { *status = RANGE_PARSE_ERROR; ffpmsg("Syntax error in this row range list: min > max"); ffpmsg(rowlist); return(*status); } if (*numranges > 0) { if (minval <= maxrow[(*numranges) - 1]) { *status = RANGE_PARSE_ERROR; ffpmsg("Syntax error in this row range list. Range minimum is"); ffpmsg(" less than or equal to previous range maximum"); ffpmsg(rowlist); return(*status); } } if (minval <= maxrows) { /* ignore range if greater than maxrows */ if (maxval > maxrows) maxval = (long) maxrows; minrow[*numranges] = minval; maxrow[*numranges] = maxval; (*numranges)++; } while (*next == ' ')next++; /* skip spaces */ if (*next == ',') { next++; while (*next == ' ')next++; /* skip more spaces */ } } if (*numranges == 0) { /* a null string was entered */ minrow[0] = 1; maxrow[0] = (long) maxrows; *numranges = 1; } return(*status); } /*--------------------------------------------------------------------------*/ int ffrwrgll( char *rowlist, /* I - list of rows and row ranges */ LONGLONG maxrows, /* I - number of rows in the list */ int maxranges, /* I - max number of ranges to be returned */ int *numranges, /* O - number ranges returned */ LONGLONG *minrow, /* O - first row in each range */ LONGLONG *maxrow, /* O - last row in each range */ int *status) /* IO - status value */ { /* parse the input list of row ranges, returning the number of ranges, and the min and max row value in each range. The only characters allowed in the input rowlist are decimal digits, minus sign, and comma (and non-significant spaces) Example: list = "10-20, 30-35,50" would return numranges = 3, minrow[] = {10, 30, 50}, maxrow[] = {20, 35, 50} error is returned if min value of range is > max value of range or if the ranges are not monotonically increasing. */ char *next; LONGLONG minval, maxval; double dvalue; if (*status > 0) return(*status); if (maxrows <= 0 ) { *status = RANGE_PARSE_ERROR; ffpmsg("Input maximum range value is <= 0 (fits_parse_ranges)"); return(*status); } next = rowlist; *numranges = 0; while (*next == ' ')next++; /* skip spaces */ while (*next != '\0') { /* find min value of next range; *next must be '-' or a digit */ if (*next == '-') { minval = 1; /* implied minrow value = 1 */ } else if ( isdigit((int) *next) ) { /* read as a double, because the string to LONGLONG function */ /* is platform dependent (strtoll, strtol, _atoI64) */ dvalue = strtod(next, &next); minval = (LONGLONG) (dvalue + 0.1); } else { *status = RANGE_PARSE_ERROR; ffpmsg("Syntax error in this row range list:"); ffpmsg(rowlist); return(*status); } while (*next == ' ')next++; /* skip spaces */ /* find max value of next range; *next must be '-', or ',' */ if (*next == '-') { next++; while (*next == ' ')next++; /* skip spaces */ if ( isdigit((int) *next) ) { /* read as a double, because the string to LONGLONG function */ /* is platform dependent (strtoll, strtol, _atoI64) */ dvalue = strtod(next, &next); maxval = (LONGLONG) (dvalue + 0.1); } else if (*next == ',' || *next == '\0') { maxval = maxrows; /* implied max value */ } else { *status = RANGE_PARSE_ERROR; ffpmsg("Syntax error in this row range list:"); ffpmsg(rowlist); return(*status); } } else if (*next == ',' || *next == '\0') { maxval = minval; /* only a single integer in this range */ } else { *status = RANGE_PARSE_ERROR; ffpmsg("Syntax error in this row range list:"); ffpmsg(rowlist); return(*status); } if (*numranges + 1 > maxranges) { *status = RANGE_PARSE_ERROR; ffpmsg("Overflowed maximum number of ranges (fits_parse_ranges)"); return(*status); } if (minval < 1 ) { *status = RANGE_PARSE_ERROR; ffpmsg("Syntax error in this row range list: row number < 1"); ffpmsg(rowlist); return(*status); } if (maxval < minval) { *status = RANGE_PARSE_ERROR; ffpmsg("Syntax error in this row range list: min > max"); ffpmsg(rowlist); return(*status); } if (*numranges > 0) { if (minval <= maxrow[(*numranges) - 1]) { *status = RANGE_PARSE_ERROR; ffpmsg("Syntax error in this row range list. Range minimum is"); ffpmsg(" less than or equal to previous range maximum"); ffpmsg(rowlist); return(*status); } } if (minval <= maxrows) { /* ignore range if greater than maxrows */ if (maxval > maxrows) maxval = maxrows; minrow[*numranges] = minval; maxrow[*numranges] = maxval; (*numranges)++; } while (*next == ' ')next++; /* skip spaces */ if (*next == ',') { next++; while (*next == ' ')next++; /* skip more spaces */ } } if (*numranges == 0) { /* a null string was entered */ minrow[0] = 1; maxrow[0] = maxrows; *numranges = 1; } return(*status); } /*--------------------------------------------------------------------------*/ int fficol(fitsfile *fptr, /* I - FITS file pointer */ int numcol, /* I - position for new col. (1 = 1st) */ char *ttype, /* I - name of column (TTYPE keyword) */ char *tform, /* I - format of column (TFORM keyword) */ int *status) /* IO - error status */ /* Insert a new column into an existing table at position numcol. If numcol is greater than the number of existing columns in the table then the new column will be appended as the last column in the table. */ { char *name, *format; name = ttype; format = tform; fficls(fptr, numcol, 1, &name, &format, status); return(*status); } /*--------------------------------------------------------------------------*/ int fficls(fitsfile *fptr, /* I - FITS file pointer */ int fstcol, /* I - position for first new col. (1 = 1st) */ int ncols, /* I - number of columns to insert */ char **ttype, /* I - array of column names(TTYPE keywords) */ char **tform, /* I - array of formats of column (TFORM) */ int *status) /* IO - error status */ /* Insert 1 or more new columns into an existing table at position numcol. If fstcol is greater than the number of existing columns in the table then the new column will be appended as the last column in the table. */ { int colnum, datacode, decims, tfields, tstatus, ii; LONGLONG datasize, firstbyte, nbytes, nadd, naxis1, naxis2, freespace; LONGLONG tbcol, firstcol, delbyte; long nblock, width, repeat; char tfm[FLEN_VALUE], keyname[FLEN_KEYWORD], comm[FLEN_COMMENT], *cptr; tcolumn *colptr; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } /* rescan header if data structure is undefined */ else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) return(*status); if ((fptr->Fptr)->hdutype == IMAGE_HDU) { ffpmsg("Can only add columns to TABLE or BINTABLE extension (fficol)"); return(*status = NOT_TABLE); } /* is the column number valid? */ tfields = (fptr->Fptr)->tfield; if (fstcol < 1 ) return(*status = BAD_COL_NUM); else if (fstcol > tfields) colnum = tfields + 1; /* append as last column */ else colnum = fstcol; /* parse the tform value and calc number of bytes to add to each row */ delbyte = 0; for (ii = 0; ii < ncols; ii++) { strcpy(tfm, tform[ii]); ffupch(tfm); /* make sure format is in upper case */ if ((fptr->Fptr)->hdutype == ASCII_TBL) { ffasfm(tfm, &datacode, &width, &decims, status); delbyte += width + 1; /* add one space between the columns */ } else { ffbnfm(tfm, &datacode, &repeat, &width, status); if (datacode < 0) { /* variable length array column */ if (strchr(tfm, 'Q')) delbyte += 16; else delbyte += 8; } else if (datacode == 1) /* bit column; round up */ delbyte += (repeat + 7) / 8; /* to multiple of 8 bits */ else if (datacode == 16) /* ASCII string column */ delbyte += repeat; else /* numerical data type */ delbyte += (datacode / 10) * repeat; } } if (*status > 0) return(*status); /* get the current size of the table */ /* use internal structure since NAXIS2 keyword may not be up to date */ naxis1 = (fptr->Fptr)->rowlength; naxis2 = (fptr->Fptr)->numrows; /* current size of data */ datasize = (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize; freespace = ( ( (datasize + 2879) / 2880) * 2880) - datasize; nadd = delbyte * naxis2; /* no. of bytes to add to table */ if ( (freespace - nadd) < 0) /* not enough existing space? */ { nblock = (long) ((nadd - freespace + 2879) / 2880); /* number of blocks */ if (ffiblk(fptr, nblock, 1, status) > 0) /* insert the blocks */ return(*status); } /* shift heap down (if it exists) */ if ((fptr->Fptr)->heapsize > 0) { nbytes = (fptr->Fptr)->heapsize; /* no. of bytes to shift down */ /* absolute heap pos */ firstbyte = (fptr->Fptr)->datastart + (fptr->Fptr)->heapstart; if (ffshft(fptr, firstbyte, nbytes, nadd, status) > 0) /* move heap */ return(*status); } /* update the heap starting address */ (fptr->Fptr)->heapstart += nadd; /* update the THEAP keyword if it exists */ tstatus = 0; ffmkyj(fptr, "THEAP", (fptr->Fptr)->heapstart, "&", &tstatus); /* calculate byte position in the row where to insert the new column */ if (colnum > tfields) firstcol = naxis1; else { colptr = (fptr->Fptr)->tableptr; colptr += (colnum - 1); firstcol = colptr->tbcol; } /* insert delbyte bytes in every row, at byte position firstcol */ ffcins(fptr, naxis1, naxis2, delbyte, firstcol, status); if ((fptr->Fptr)->hdutype == ASCII_TBL) { /* adjust the TBCOL values of the existing columns */ for(ii = 0; ii < tfields; ii++) { ffkeyn("TBCOL", ii + 1, keyname, status); ffgkyjj(fptr, keyname, &tbcol, comm, status); if (tbcol > firstcol) { tbcol += delbyte; ffmkyj(fptr, keyname, tbcol, "&", status); } } } /* update the mandatory keywords */ ffmkyj(fptr, "TFIELDS", tfields + ncols, "&", status); ffmkyj(fptr, "NAXIS1", naxis1 + delbyte, "&", status); /* increment the index value on any existing column keywords */ if(colnum <= tfields) ffkshf(fptr, colnum, tfields, ncols, status); /* add the required keywords for the new columns */ for (ii = 0; ii < ncols; ii++, colnum++) { strcpy(comm, "label for field"); ffkeyn("TTYPE", colnum, keyname, status); ffpkys(fptr, keyname, ttype[ii], comm, status); strcpy(comm, "format of field"); strcpy(tfm, tform[ii]); ffupch(tfm); /* make sure format is in upper case */ ffkeyn("TFORM", colnum, keyname, status); if (abs(datacode) == TSBYTE) { /* Replace the 'S' with an 'B' in the TFORMn code */ cptr = tfm; while (*cptr != 'S') cptr++; *cptr = 'B'; ffpkys(fptr, keyname, tfm, comm, status); /* write the TZEROn and TSCALn keywords */ ffkeyn("TZERO", colnum, keyname, status); strcpy(comm, "offset for signed bytes"); ffpkyg(fptr, keyname, -128., 0, comm, status); ffkeyn("TSCAL", colnum, keyname, status); strcpy(comm, "data are not scaled"); ffpkyg(fptr, keyname, 1., 0, comm, status); } else if (abs(datacode) == TUSHORT) { /* Replace the 'U' with an 'I' in the TFORMn code */ cptr = tfm; while (*cptr != 'U') cptr++; *cptr = 'I'; ffpkys(fptr, keyname, tfm, comm, status); /* write the TZEROn and TSCALn keywords */ ffkeyn("TZERO", colnum, keyname, status); strcpy(comm, "offset for unsigned integers"); ffpkyg(fptr, keyname, 32768., 0, comm, status); ffkeyn("TSCAL", colnum, keyname, status); strcpy(comm, "data are not scaled"); ffpkyg(fptr, keyname, 1., 0, comm, status); } else if (abs(datacode) == TULONG) { /* Replace the 'V' with an 'J' in the TFORMn code */ cptr = tfm; while (*cptr != 'V') cptr++; *cptr = 'J'; ffpkys(fptr, keyname, tfm, comm, status); /* write the TZEROn and TSCALn keywords */ ffkeyn("TZERO", colnum, keyname, status); strcpy(comm, "offset for unsigned integers"); ffpkyg(fptr, keyname, 2147483648., 0, comm, status); ffkeyn("TSCAL", colnum, keyname, status); strcpy(comm, "data are not scaled"); ffpkyg(fptr, keyname, 1., 0, comm, status); } else { ffpkys(fptr, keyname, tfm, comm, status); } if ((fptr->Fptr)->hdutype == ASCII_TBL) /* write the TBCOL keyword */ { if (colnum == tfields + 1) tbcol = firstcol + 2; /* allow space between preceding col */ else tbcol = firstcol + 1; strcpy(comm, "beginning column of field"); ffkeyn("TBCOL", colnum, keyname, status); ffpkyj(fptr, keyname, tbcol, comm, status); /* increment the column starting position for the next column */ ffasfm(tfm, &datacode, &width, &decims, status); firstcol += width + 1; /* add one space between the columns */ } } ffrdef(fptr, status); /* initialize the new table structure */ return(*status); } /*--------------------------------------------------------------------------*/ int ffmvec(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - position of col to be modified */ LONGLONG newveclen, /* I - new vector length of column (TFORM) */ int *status) /* IO - error status */ /* Modify the vector length of a column in a binary table, larger or smaller. E.g., change a column from TFORMn = '1E' to '20E'. */ { int datacode, tfields, tstatus; LONGLONG datasize, size, firstbyte, nbytes, nadd, ndelete; LONGLONG naxis1, naxis2, firstcol, freespace; LONGLONG width, delbyte, repeat; long nblock; char tfm[FLEN_VALUE], keyname[FLEN_KEYWORD], tcode[2]; tcolumn *colptr; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } /* rescan header if data structure is undefined */ else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) return(*status); if ((fptr->Fptr)->hdutype != BINARY_TBL) { ffpmsg( "Can only change vector length of a column in BINTABLE extension (ffmvec)"); return(*status = NOT_TABLE); } /* is the column number valid? */ tfields = (fptr->Fptr)->tfield; if (colnum < 1 || colnum > tfields) return(*status = BAD_COL_NUM); /* look up the current vector length and element width */ colptr = (fptr->Fptr)->tableptr; colptr += (colnum - 1); datacode = colptr->tdatatype; /* datatype of the column */ repeat = colptr->trepeat; /* field repeat count */ width = colptr->twidth; /* width of a single element in chars */ if (datacode < 0) { ffpmsg( "Can't modify vector length of variable length column (ffmvec)"); return(*status = BAD_TFORM); } if (repeat == newveclen) return(*status); /* column already has the desired vector length */ if (datacode == TSTRING) width = 1; /* width was equal to width of unit string */ naxis1 = (fptr->Fptr)->rowlength; /* current width of the table */ naxis2 = (fptr->Fptr)->numrows; delbyte = (newveclen - repeat) * width; /* no. of bytes to insert */ if (datacode == TBIT) /* BIT column is a special case */ delbyte = ((newveclen + 7) / 8) - ((repeat + 7) / 8); if (delbyte > 0) /* insert space for more elements */ { /* current size of data */ datasize = (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize; freespace = ( ( (datasize + 2879) / 2880) * 2880) - datasize; nadd = (LONGLONG)delbyte * naxis2; /* no. of bytes to add to table */ if ( (freespace - nadd) < 0) /* not enough existing space? */ { nblock = (long) ((nadd - freespace + 2879) / 2880); /* number of blocks */ if (ffiblk(fptr, nblock, 1, status) > 0) /* insert the blocks */ return(*status); } /* shift heap down (if it exists) */ if ((fptr->Fptr)->heapsize > 0) { nbytes = (fptr->Fptr)->heapsize; /* no. of bytes to shift down */ /* absolute heap pos */ firstbyte = (fptr->Fptr)->datastart + (fptr->Fptr)->heapstart; if (ffshft(fptr, firstbyte, nbytes, nadd, status) > 0) /* move heap */ return(*status); } /* update the heap starting address */ (fptr->Fptr)->heapstart += nadd; /* update the THEAP keyword if it exists */ tstatus = 0; ffmkyj(fptr, "THEAP", (fptr->Fptr)->heapstart, "&", &tstatus); /* Must reset colptr before using it again. (fptr->Fptr)->tableptr may have been reallocated down in ffbinit via the call to ffiblk above.*/ colptr = (fptr->Fptr)->tableptr; colptr += (colnum - 1); firstcol = colptr->tbcol + (repeat * width); /* insert position */ /* insert delbyte bytes in every row, at byte position firstcol */ ffcins(fptr, naxis1, naxis2, delbyte, firstcol, status); } else if (delbyte < 0) { /* current size of table */ size = (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize; freespace = ((size + 2879) / 2880) * 2880 - size - ((LONGLONG)delbyte * naxis2); nblock = (long) (freespace / 2880); /* number of empty blocks to delete */ firstcol = colptr->tbcol + (newveclen * width); /* delete position */ /* delete elements from the vector */ ffcdel(fptr, naxis1, naxis2, -delbyte, firstcol, status); /* abs heap pos */ firstbyte = (fptr->Fptr)->datastart + (fptr->Fptr)->heapstart; ndelete = (LONGLONG)delbyte * naxis2; /* size of shift (negative) */ /* shift heap up (if it exists) */ if ((fptr->Fptr)->heapsize > 0) { nbytes = (fptr->Fptr)->heapsize; /* no. of bytes to shift up */ if (ffshft(fptr, firstbyte, nbytes, ndelete, status) > 0) return(*status); } /* delete the empty blocks at the end of the HDU */ if (nblock > 0) ffdblk(fptr, nblock, status); /* update the heap starting address */ (fptr->Fptr)->heapstart += ndelete; /* ndelete is negative */ /* update the THEAP keyword if it exists */ tstatus = 0; ffmkyj(fptr, "THEAP", (fptr->Fptr)->heapstart, "&", &tstatus); } /* construct the new TFORM keyword for the column */ if (datacode == TBIT) strcpy(tcode,"X"); else if (datacode == TBYTE) strcpy(tcode,"B"); else if (datacode == TLOGICAL) strcpy(tcode,"L"); else if (datacode == TSTRING) strcpy(tcode,"A"); else if (datacode == TSHORT) strcpy(tcode,"I"); else if (datacode == TLONG) strcpy(tcode,"J"); else if (datacode == TLONGLONG) strcpy(tcode,"K"); else if (datacode == TFLOAT) strcpy(tcode,"E"); else if (datacode == TDOUBLE) strcpy(tcode,"D"); else if (datacode == TCOMPLEX) strcpy(tcode,"C"); else if (datacode == TDBLCOMPLEX) strcpy(tcode,"M"); /* write as a double value because the LONGLONG conversion */ /* character in snprintf is platform dependent ( %lld, %ld, %I64d ) */ snprintf(tfm,FLEN_VALUE,"%.0f%s",(double) newveclen, tcode); ffkeyn("TFORM", colnum, keyname, status); /* Keyword name */ ffmkys(fptr, keyname, tfm, "&", status); /* modify TFORM keyword */ ffmkyj(fptr, "NAXIS1", naxis1 + delbyte, "&", status); /* modify NAXIS1 */ ffrdef(fptr, status); /* reinitialize the new table structure */ return(*status); } /*--------------------------------------------------------------------------*/ int ffcpcl(fitsfile *infptr, /* I - FITS file pointer to input file */ fitsfile *outfptr, /* I - FITS file pointer to output file */ int incol, /* I - number of input column */ int outcol, /* I - number for output column */ int create_col, /* I - create new col if TRUE, else overwrite */ int *status) /* IO - error status */ /* copy a column from infptr and insert it in the outfptr table. */ { int tstatus, colnum, typecode, otypecode, anynull; int inHduType, outHduType; long tfields, repeat, orepeat, width, owidth, nrows, outrows; long inloop, outloop, maxloop, ndone, ntodo, npixels; long firstrow, firstelem, ii; char keyname[FLEN_KEYWORD], ttype[FLEN_VALUE], tform[FLEN_VALUE]; char ttype_comm[FLEN_COMMENT],tform_comm[FLEN_COMMENT]; char *lvalues = 0, nullflag, **strarray = 0; char nulstr[] = {'\5', '\0'}; /* unique null string value */ double dnull = 0.l, *dvalues = 0; float fnull = 0., *fvalues = 0; if (*status > 0) return(*status); if (infptr->HDUposition != (infptr->Fptr)->curhdu) { ffmahd(infptr, (infptr->HDUposition) + 1, NULL, status); } else if ((infptr->Fptr)->datastart == DATA_UNDEFINED) ffrdef(infptr, status); /* rescan header */ inHduType = (infptr->Fptr)->hdutype; if (outfptr->HDUposition != (outfptr->Fptr)->curhdu) { ffmahd(outfptr, (outfptr->HDUposition) + 1, NULL, status); } else if ((outfptr->Fptr)->datastart == DATA_UNDEFINED) ffrdef(outfptr, status); /* rescan header */ outHduType = (outfptr->Fptr)->hdutype; if (*status > 0) return(*status); if (inHduType == IMAGE_HDU || outHduType == IMAGE_HDU) { ffpmsg ("Can not copy columns to or from IMAGE HDUs (ffcpcl)"); return(*status = NOT_TABLE); } if ( inHduType == BINARY_TBL && outHduType == ASCII_TBL) { ffpmsg ("Copying from Binary table to ASCII table is not supported (ffcpcl)"); return(*status = NOT_BTABLE); } /* get the datatype and vector repeat length of the column */ ffgtcl(infptr, incol, &typecode, &repeat, &width, status); if (typecode < 0) { ffpmsg("Variable-length columns are not supported (ffcpcl)"); return(*status = BAD_TFORM); } if (create_col) /* insert new column in output table? */ { tstatus = 0; ffkeyn("TTYPE", incol, keyname, &tstatus); ffgkys(infptr, keyname, ttype, ttype_comm, &tstatus); ffkeyn("TFORM", incol, keyname, &tstatus); if (ffgkys(infptr, keyname, tform, tform_comm, &tstatus) ) { ffpmsg ("Could not find TTYPE and TFORM keywords in input table (ffcpcl)"); return(*status = NO_TFORM); } if (inHduType == ASCII_TBL && outHduType == BINARY_TBL) { /* convert from ASCII table to BINARY table format string */ if (typecode == TSTRING) ffnkey(width, "A", tform, status); else if (typecode == TLONG) strcpy(tform, "1J"); else if (typecode == TSHORT) strcpy(tform, "1I"); else if (typecode == TFLOAT) strcpy(tform,"1E"); else if (typecode == TDOUBLE) strcpy(tform,"1D"); } if (ffgkyj(outfptr, "TFIELDS", &tfields, 0, &tstatus)) { ffpmsg ("Could not read TFIELDS keyword in output table (ffcpcl)"); return(*status = NO_TFIELDS); } colnum = minvalue((int) tfields + 1, outcol); /* output col. number */ /* create the empty column */ if (fficol(outfptr, colnum, ttype, tform, status) > 0) { ffpmsg ("Could not append new column to output file (ffcpcl)"); return(*status); } if ((infptr->Fptr == outfptr->Fptr) && (infptr->HDUposition == outfptr->HDUposition) && (colnum <= incol)) { incol++; /* the input column has been shifted over */ } /* copy the comment strings from the input file for TTYPE and TFORM */ tstatus = 0; ffkeyn("TTYPE", colnum, keyname, &tstatus); ffmcom(outfptr, keyname, ttype_comm, &tstatus); ffkeyn("TFORM", colnum, keyname, &tstatus); ffmcom(outfptr, keyname, tform_comm, &tstatus); /* copy other column-related keywords if they exist */ ffcpky(infptr, outfptr, incol, colnum, "TUNIT", status); ffcpky(infptr, outfptr, incol, colnum, "TSCAL", status); ffcpky(infptr, outfptr, incol, colnum, "TZERO", status); ffcpky(infptr, outfptr, incol, colnum, "TDISP", status); ffcpky(infptr, outfptr, incol, colnum, "TLMIN", status); ffcpky(infptr, outfptr, incol, colnum, "TLMAX", status); ffcpky(infptr, outfptr, incol, colnum, "TDIM", status); /* WCS keywords */ ffcpky(infptr, outfptr, incol, colnum, "TCTYP", status); ffcpky(infptr, outfptr, incol, colnum, "TCUNI", status); ffcpky(infptr, outfptr, incol, colnum, "TCRVL", status); ffcpky(infptr, outfptr, incol, colnum, "TCRPX", status); ffcpky(infptr, outfptr, incol, colnum, "TCDLT", status); ffcpky(infptr, outfptr, incol, colnum, "TCROT", status); if (inHduType == ASCII_TBL && outHduType == BINARY_TBL) { /* binary tables only have TNULLn keyword for integer columns */ if (typecode == TLONG || typecode == TSHORT) { /* check if null string is defined; replace with integer */ ffkeyn("TNULL", incol, keyname, &tstatus); if (ffgkys(infptr, keyname, ttype, 0, &tstatus) <= 0) { ffkeyn("TNULL", colnum, keyname, &tstatus); if (typecode == TLONG) ffpkyj(outfptr, keyname, -9999999L, "Null value", status); else ffpkyj(outfptr, keyname, -32768L, "Null value", status); } } } else { ffcpky(infptr, outfptr, incol, colnum, "TNULL", status); } /* rescan header to recognize the new keywords */ if (ffrdef(outfptr, status) ) return(*status); } else { colnum = outcol; /* get the datatype and vector repeat length of the output column */ ffgtcl(outfptr, outcol, &otypecode, &orepeat, &owidth, status); if (orepeat != repeat) { ffpmsg("Input and output vector columns must have same length (ffcpcl)"); return(*status = BAD_TFORM); } } ffgkyj(infptr, "NAXIS2", &nrows, 0, status); /* no. of input rows */ ffgkyj(outfptr, "NAXIS2", &outrows, 0, status); /* no. of output rows */ nrows = minvalue(nrows, outrows); if (typecode == TBIT) repeat = (repeat + 7) / 8; /* convert from bits to bytes */ else if (typecode == TSTRING && inHduType == BINARY_TBL) repeat = repeat / width; /* convert from chars to unit strings */ /* get optimum number of rows to copy at one time */ ffgrsz(infptr, &inloop, status); ffgrsz(outfptr, &outloop, status); /* adjust optimum number, since 2 tables are open at once */ maxloop = minvalue(inloop, outloop); /* smallest of the 2 tables */ maxloop = maxvalue(1, maxloop / 2); /* at least 1 row */ maxloop = minvalue(maxloop, nrows); /* max = nrows to be copied */ maxloop *= repeat; /* mult by no of elements in a row */ /* allocate memory for arrays */ if (typecode == TLOGICAL) { lvalues = (char *) calloc(maxloop, sizeof(char) ); if (!lvalues) { ffpmsg ("malloc failed to get memory for logicals (ffcpcl)"); return(*status = ARRAY_TOO_BIG); } } else if (typecode == TSTRING) { /* allocate array of pointers */ strarray = (char **) calloc(maxloop, sizeof(strarray)); /* allocate space for each string */ for (ii = 0; ii < maxloop; ii++) strarray[ii] = (char *) calloc(width+1, sizeof(char)); } else if (typecode == TCOMPLEX) { fvalues = (float *) calloc(maxloop * 2, sizeof(float) ); if (!fvalues) { ffpmsg ("malloc failed to get memory for complex (ffcpcl)"); return(*status = ARRAY_TOO_BIG); } fnull = 0.; } else if (typecode == TDBLCOMPLEX) { dvalues = (double *) calloc(maxloop * 2, sizeof(double) ); if (!dvalues) { ffpmsg ("malloc failed to get memory for dbl complex (ffcpcl)"); return(*status = ARRAY_TOO_BIG); } dnull = 0.; } else /* numerical datatype; read them all as doubles */ { dvalues = (double *) calloc(maxloop, sizeof(double) ); if (!dvalues) { ffpmsg ("malloc failed to get memory for doubles (ffcpcl)"); return(*status = ARRAY_TOO_BIG); } dnull = -9.99991999E31; /* use an unlikely value for nulls */ } npixels = nrows * repeat; /* total no. of pixels to copy */ ntodo = minvalue(npixels, maxloop); /* no. to copy per iteration */ ndone = 0; /* total no. of pixels that have been copied */ while (ntodo) /* iterate through the table */ { firstrow = ndone / repeat + 1; firstelem = ndone - ((firstrow - 1) * repeat) + 1; /* read from input table */ if (typecode == TLOGICAL) ffgcl(infptr, incol, firstrow, firstelem, ntodo, lvalues, status); else if (typecode == TSTRING) ffgcvs(infptr, incol, firstrow, firstelem, ntodo, nulstr, strarray, &anynull, status); else if (typecode == TCOMPLEX) ffgcvc(infptr, incol, firstrow, firstelem, ntodo, fnull, fvalues, &anynull, status); else if (typecode == TDBLCOMPLEX) ffgcvm(infptr, incol, firstrow, firstelem, ntodo, dnull, dvalues, &anynull, status); else /* all numerical types */ ffgcvd(infptr, incol, firstrow, firstelem, ntodo, dnull, dvalues, &anynull, status); if (*status > 0) { ffpmsg("Error reading input copy of column (ffcpcl)"); break; } /* write to output table */ if (typecode == TLOGICAL) { nullflag = 2; ffpcnl(outfptr, colnum, firstrow, firstelem, ntodo, lvalues, nullflag, status); } else if (typecode == TSTRING) { if (anynull) ffpcns(outfptr, colnum, firstrow, firstelem, ntodo, strarray, nulstr, status); else ffpcls(outfptr, colnum, firstrow, firstelem, ntodo, strarray, status); } else if (typecode == TCOMPLEX) { /* doesn't support writing nulls */ ffpclc(outfptr, colnum, firstrow, firstelem, ntodo, fvalues, status); } else if (typecode == TDBLCOMPLEX) { /* doesn't support writing nulls */ ffpclm(outfptr, colnum, firstrow, firstelem, ntodo, dvalues, status); } else /* all other numerical types */ { if (anynull) ffpcnd(outfptr, colnum, firstrow, firstelem, ntodo, dvalues, dnull, status); else ffpcld(outfptr, colnum, firstrow, firstelem, ntodo, dvalues, status); } if (*status > 0) { ffpmsg("Error writing output copy of column (ffcpcl)"); break; } npixels -= ntodo; ndone += ntodo; ntodo = minvalue(npixels, maxloop); } /* free the previously allocated memory */ if (typecode == TLOGICAL) { free(lvalues); } else if (typecode == TSTRING) { for (ii = 0; ii < maxloop; ii++) free(strarray[ii]); free(strarray); } else { free(dvalues); } return(*status); } /*--------------------------------------------------------------------------*/ int ffcprw(fitsfile *infptr, /* I - FITS file pointer to input file */ fitsfile *outfptr, /* I - FITS file pointer to output file */ LONGLONG firstrow, /* I - number of first row to copy (1 based) */ LONGLONG nrows, /* I - number of rows to copy */ int *status) /* IO - error status */ /* copy consecutive set of rows from infptr and append it in the outfptr table. */ { LONGLONG innaxis1, innaxis2, outnaxis1, outnaxis2, ii, jj; unsigned char *buffer; if (*status > 0) return(*status); if (infptr->HDUposition != (infptr->Fptr)->curhdu) { ffmahd(infptr, (infptr->HDUposition) + 1, NULL, status); } else if ((infptr->Fptr)->datastart == DATA_UNDEFINED) ffrdef(infptr, status); /* rescan header */ if (outfptr->HDUposition != (outfptr->Fptr)->curhdu) { ffmahd(outfptr, (outfptr->HDUposition) + 1, NULL, status); } else if ((outfptr->Fptr)->datastart == DATA_UNDEFINED) ffrdef(outfptr, status); /* rescan header */ if (*status > 0) return(*status); if ((infptr->Fptr)->hdutype == IMAGE_HDU || (outfptr->Fptr)->hdutype == IMAGE_HDU) { ffpmsg ("Can not copy rows to or from IMAGE HDUs (ffcprw)"); return(*status = NOT_TABLE); } if ( ((infptr->Fptr)->hdutype == BINARY_TBL && (outfptr->Fptr)->hdutype == ASCII_TBL) || ((infptr->Fptr)->hdutype == ASCII_TBL && (outfptr->Fptr)->hdutype == BINARY_TBL) ) { ffpmsg ("Copying rows between Binary and ASCII tables is not supported (ffcprw)"); return(*status = NOT_BTABLE); } ffgkyjj(infptr, "NAXIS1", &innaxis1, 0, status); /* width of input rows */ ffgkyjj(infptr, "NAXIS2", &innaxis2, 0, status); /* no. of input rows */ ffgkyjj(outfptr, "NAXIS1", &outnaxis1, 0, status); /* width of output rows */ ffgkyjj(outfptr, "NAXIS2", &outnaxis2, 0, status); /* no. of output rows */ if (*status > 0) return(*status); if (outnaxis1 > innaxis1) { ffpmsg ("Input and output tables do not have same width (ffcprw)"); return(*status = BAD_ROW_WIDTH); } if (firstrow + nrows - 1 > innaxis2) { ffpmsg ("Not enough rows in input table to copy (ffcprw)"); return(*status = BAD_ROW_NUM); } /* allocate buffer to hold 1 row of data */ buffer = malloc( (size_t) innaxis1); if (!buffer) { ffpmsg ("Unable to allocate memory (ffcprw)"); return(*status = MEMORY_ALLOCATION); } /* copy the rows, 1 at a time */ jj = outnaxis2 + 1; for (ii = firstrow; ii < firstrow + nrows; ii++) { fits_read_tblbytes (infptr, ii, 1, innaxis1, buffer, status); fits_write_tblbytes(outfptr, jj, 1, innaxis1, buffer, status); jj++; } outnaxis2 += nrows; fits_update_key(outfptr, TLONGLONG, "NAXIS2", &outnaxis2, 0, status); free(buffer); return(*status); } /*--------------------------------------------------------------------------*/ int ffcpky(fitsfile *infptr, /* I - FITS file pointer to input file */ fitsfile *outfptr, /* I - FITS file pointer to output file */ int incol, /* I - input index number */ int outcol, /* I - output index number */ char *rootname, /* I - root name of the keyword to be copied */ int *status) /* IO - error status */ /* copy an indexed keyword from infptr to outfptr. */ { int tstatus = 0; char keyname[FLEN_KEYWORD]; char value[FLEN_VALUE], comment[FLEN_COMMENT], card[FLEN_CARD]; ffkeyn(rootname, incol, keyname, &tstatus); if (ffgkey(infptr, keyname, value, comment, &tstatus) <= 0) { ffkeyn(rootname, outcol, keyname, &tstatus); ffmkky(keyname, value, comment, card, status); ffprec(outfptr, card, status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffdcol(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column to delete (1 = 1st) */ int *status) /* IO - error status */ /* Delete a column from a table. */ { int ii, tstatus; LONGLONG firstbyte, size, ndelete, nbytes, naxis1, naxis2, firstcol, delbyte, freespace; LONGLONG tbcol; long nblock, nspace; char keyname[FLEN_KEYWORD], comm[FLEN_COMMENT]; tcolumn *colptr, *nextcol; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } /* rescan header if data structure is undefined */ else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) return(*status); if ((fptr->Fptr)->hdutype == IMAGE_HDU) { ffpmsg ("Can only delete column from TABLE or BINTABLE extension (ffdcol)"); return(*status = NOT_TABLE); } if (colnum < 1 || colnum > (fptr->Fptr)->tfield ) return(*status = BAD_COL_NUM); colptr = (fptr->Fptr)->tableptr; colptr += (colnum - 1); firstcol = colptr->tbcol; /* starting byte position of the column */ /* use column width to determine how many bytes to delete in each row */ if ((fptr->Fptr)->hdutype == ASCII_TBL) { delbyte = colptr->twidth; /* width of ASCII column */ if (colnum < (fptr->Fptr)->tfield) /* check for space between next column */ { nextcol = colptr + 1; nspace = (long) ((nextcol->tbcol) - (colptr->tbcol) - delbyte); if (nspace > 0) delbyte++; } else if (colnum > 1) /* check for space between last 2 columns */ { nextcol = colptr - 1; nspace = (long) ((colptr->tbcol) - (nextcol->tbcol) - (nextcol->twidth)); if (nspace > 0) { delbyte++; firstcol--; /* delete the leading space */ } } } else /* a binary table */ { if (colnum < (fptr->Fptr)->tfield) { nextcol = colptr + 1; delbyte = (nextcol->tbcol) - (colptr->tbcol); } else { delbyte = ((fptr->Fptr)->rowlength) - (colptr->tbcol); } } naxis1 = (fptr->Fptr)->rowlength; /* current width of the table */ naxis2 = (fptr->Fptr)->numrows; /* current size of table */ size = (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize; freespace = ((LONGLONG)delbyte * naxis2) + ((size + 2879) / 2880) * 2880 - size; nblock = (long) (freespace / 2880); /* number of empty blocks to delete */ ffcdel(fptr, naxis1, naxis2, delbyte, firstcol, status); /* delete col */ /* absolute heap position */ firstbyte = (fptr->Fptr)->datastart + (fptr->Fptr)->heapstart; ndelete = (LONGLONG)delbyte * naxis2; /* size of shift */ /* shift heap up (if it exists) */ if ((fptr->Fptr)->heapsize > 0) { nbytes = (fptr->Fptr)->heapsize; /* no. of bytes to shift up */ if (ffshft(fptr, firstbyte, nbytes, -ndelete, status) > 0) /* mv heap */ return(*status); } /* delete the empty blocks at the end of the HDU */ if (nblock > 0) ffdblk(fptr, nblock, status); /* update the heap starting address */ (fptr->Fptr)->heapstart -= ndelete; /* update the THEAP keyword if it exists */ tstatus = 0; ffmkyj(fptr, "THEAP", (long)(fptr->Fptr)->heapstart, "&", &tstatus); if ((fptr->Fptr)->hdutype == ASCII_TBL) { /* adjust the TBCOL values of the remaining columns */ for (ii = 1; ii <= (fptr->Fptr)->tfield; ii++) { ffkeyn("TBCOL", ii, keyname, status); ffgkyjj(fptr, keyname, &tbcol, comm, status); if (tbcol > firstcol) { tbcol = tbcol - delbyte; ffmkyj(fptr, keyname, tbcol, "&", status); } } } /* update the mandatory keywords */ ffmkyj(fptr, "TFIELDS", ((fptr->Fptr)->tfield) - 1, "&", status); ffmkyj(fptr, "NAXIS1", naxis1 - delbyte, "&", status); /* delete the index keywords starting with 'T' associated with the deleted column and subtract 1 from index of all higher keywords */ ffkshf(fptr, colnum, (fptr->Fptr)->tfield, -1, status); ffrdef(fptr, status); /* initialize the new table structure */ return(*status); } /*--------------------------------------------------------------------------*/ int ffcins(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG naxis1, /* I - width of the table, in bytes */ LONGLONG naxis2, /* I - number of rows in the table */ LONGLONG ninsert, /* I - number of bytes to insert in each row */ LONGLONG bytepos, /* I - rel. position in row to insert bytes */ int *status) /* IO - error status */ /* Insert 'ninsert' bytes into each row of the table at position 'bytepos'. */ { unsigned char buffer[10000], cfill; LONGLONG newlen, fbyte, nbytes, irow, nseg, ii; if (*status > 0) return(*status); if (naxis2 == 0) return(*status); /* just return if there are 0 rows in the table */ /* select appropriate fill value */ if ((fptr->Fptr)->hdutype == ASCII_TBL) cfill = 32; /* ASCII tables use blank fill */ else cfill = 0; /* primary array and binary tables use zero fill */ newlen = naxis1 + ninsert; if (newlen <= 10000) { /******************************************************************* CASE #1: optimal case where whole new row fits in the work buffer *******************************************************************/ for (ii = 0; ii < ninsert; ii++) buffer[ii] = cfill; /* initialize buffer with fill value */ /* first move the trailing bytes (if any) in the last row */ fbyte = bytepos + 1; nbytes = naxis1 - bytepos; ffgtbb(fptr, naxis2, fbyte, nbytes, &buffer[ninsert], status); (fptr->Fptr)->rowlength = newlen; /* new row length */ /* write the row (with leading fill bytes) in the new place */ nbytes += ninsert; ffptbb(fptr, naxis2, fbyte, nbytes, buffer, status); (fptr->Fptr)->rowlength = naxis1; /* reset to orig. value */ /* now move the rest of the rows */ for (irow = naxis2 - 1; irow > 0; irow--) { /* read the row to be shifted (work backwards thru the table) */ ffgtbb(fptr, irow, fbyte, naxis1, &buffer[ninsert], status); (fptr->Fptr)->rowlength = newlen; /* new row length */ /* write the row (with the leading fill bytes) in the new place */ ffptbb(fptr, irow, fbyte, newlen, buffer, status); (fptr->Fptr)->rowlength = naxis1; /* reset to orig value */ } } else { /***************************************************************** CASE #2: whole row doesn't fit in work buffer; move row in pieces ****************************************************************** first copy the data, then go back and write fill into the new column start by copying the trailing bytes (if any) in the last row. */ nbytes = naxis1 - bytepos; nseg = (nbytes + 9999) / 10000; fbyte = (nseg - 1) * 10000 + bytepos + 1; nbytes = naxis1 - fbyte + 1; for (ii = 0; ii < nseg; ii++) { ffgtbb(fptr, naxis2, fbyte, nbytes, buffer, status); (fptr->Fptr)->rowlength = newlen; /* new row length */ ffptbb(fptr, naxis2, fbyte + ninsert, nbytes, buffer, status); (fptr->Fptr)->rowlength = naxis1; /* reset to orig value */ fbyte -= 10000; nbytes = 10000; } /* now move the rest of the rows */ nseg = (naxis1 + 9999) / 10000; for (irow = naxis2 - 1; irow > 0; irow--) { fbyte = (nseg - 1) * 10000 + bytepos + 1; nbytes = naxis1 - (nseg - 1) * 10000; for (ii = 0; ii < nseg; ii++) { /* read the row to be shifted (work backwards thru the table) */ ffgtbb(fptr, irow, fbyte, nbytes, buffer, status); (fptr->Fptr)->rowlength = newlen; /* new row length */ /* write the row in the new place */ ffptbb(fptr, irow, fbyte + ninsert, nbytes, buffer, status); (fptr->Fptr)->rowlength = naxis1; /* reset to orig value */ fbyte -= 10000; nbytes = 10000; } } /* now write the fill values into the new column */ nbytes = minvalue(ninsert, 10000); memset(buffer, cfill, (size_t) nbytes); /* initialize with fill value */ nseg = (ninsert + 9999) / 10000; (fptr->Fptr)->rowlength = newlen; /* new row length */ for (irow = 1; irow <= naxis2; irow++) { fbyte = bytepos + 1; nbytes = ninsert - ((nseg - 1) * 10000); for (ii = 0; ii < nseg; ii++) { ffptbb(fptr, irow, fbyte, nbytes, buffer, status); fbyte += nbytes; nbytes = 10000; } } (fptr->Fptr)->rowlength = naxis1; /* reset to orig value */ } return(*status); } /*--------------------------------------------------------------------------*/ int ffcdel(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG naxis1, /* I - width of the table, in bytes */ LONGLONG naxis2, /* I - number of rows in the table */ LONGLONG ndelete, /* I - number of bytes to delete in each row */ LONGLONG bytepos, /* I - rel. position in row to delete bytes */ int *status) /* IO - error status */ /* delete 'ndelete' bytes from each row of the table at position 'bytepos'. */ { unsigned char buffer[10000]; LONGLONG i1, i2, ii, irow, nseg; LONGLONG newlen, remain, nbytes; if (*status > 0) return(*status); if (naxis2 == 0) return(*status); /* just return if there are 0 rows in the table */ newlen = naxis1 - ndelete; if (newlen <= 10000) { /******************************************************************* CASE #1: optimal case where whole new row fits in the work buffer *******************************************************************/ i1 = bytepos + 1; i2 = i1 + ndelete; for (irow = 1; irow < naxis2; irow++) { ffgtbb(fptr, irow, i2, newlen, buffer, status); /* read row */ (fptr->Fptr)->rowlength = newlen; /* new row length */ ffptbb(fptr, irow, i1, newlen, buffer, status); /* write row */ (fptr->Fptr)->rowlength = naxis1; /* reset to orig value */ } /* now do the last row */ remain = naxis1 - (bytepos + ndelete); if (remain > 0) { ffgtbb(fptr, naxis2, i2, remain, buffer, status); /* read row */ (fptr->Fptr)->rowlength = newlen; /* new row length */ ffptbb(fptr, naxis2, i1, remain, buffer, status); /* write row */ (fptr->Fptr)->rowlength = naxis1; /* reset to orig value */ } } else { /***************************************************************** CASE #2: whole row doesn't fit in work buffer; move row in pieces ******************************************************************/ nseg = (newlen + 9999) / 10000; for (irow = 1; irow < naxis2; irow++) { i1 = bytepos + 1; i2 = i1 + ndelete; nbytes = newlen - (nseg - 1) * 10000; for (ii = 0; ii < nseg; ii++) { ffgtbb(fptr, irow, i2, nbytes, buffer, status); /* read bytes */ (fptr->Fptr)->rowlength = newlen; /* new row length */ ffptbb(fptr, irow, i1, nbytes, buffer, status); /* rewrite bytes */ (fptr->Fptr)->rowlength = naxis1; /* reset to orig value */ i1 += nbytes; i2 += nbytes; nbytes = 10000; } } /* now do the last row */ remain = naxis1 - (bytepos + ndelete); if (remain > 0) { nseg = (remain + 9999) / 10000; i1 = bytepos + 1; i2 = i1 + ndelete; nbytes = remain - (nseg - 1) * 10000; for (ii = 0; ii < nseg; ii++) { ffgtbb(fptr, naxis2, i2, nbytes, buffer, status); (fptr->Fptr)->rowlength = newlen; /* new row length */ ffptbb(fptr, naxis2, i1, nbytes, buffer, status); /* write row */ (fptr->Fptr)->rowlength = naxis1; /* reset to orig value */ i1 += nbytes; i2 += nbytes; nbytes = 10000; } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffkshf(fitsfile *fptr, /* I - FITS file pointer */ int colmin, /* I - starting col. to be incremented; 1 = 1st */ int colmax, /* I - last column to be incremented */ int incre, /* I - shift index number by this amount */ int *status) /* IO - error status */ /* shift the index value on any existing column keywords This routine will modify the name of any keyword that begins with 'T' and has an index number in the range COLMIN - COLMAX, inclusive. if incre is positive, then the index values will be incremented. if incre is negative, then the kewords with index = COLMIN will be deleted and the index of higher numbered keywords will be decremented. */ { int nkeys, nmore, nrec, tstatus, i1; long ivalue; char rec[FLEN_CARD], q[FLEN_KEYWORD], newkey[FLEN_KEYWORD]; ffghsp(fptr, &nkeys, &nmore, status); /* get number of keywords */ /* go thru header starting with the 9th keyword looking for 'TxxxxNNN' */ for (nrec = 9; nrec <= nkeys; nrec++) { ffgrec(fptr, nrec, rec, status); if (rec[0] == 'T') { i1 = 0; strncpy(q, &rec[1], 4); if (!strncmp(q, "BCOL", 4) || !strncmp(q, "FORM", 4) || !strncmp(q, "TYPE", 4) || !strncmp(q, "SCAL", 4) || !strncmp(q, "UNIT", 4) || !strncmp(q, "NULL", 4) || !strncmp(q, "ZERO", 4) || !strncmp(q, "DISP", 4) || !strncmp(q, "LMIN", 4) || !strncmp(q, "LMAX", 4) || !strncmp(q, "DMIN", 4) || !strncmp(q, "DMAX", 4) || !strncmp(q, "CTYP", 4) || !strncmp(q, "CRPX", 4) || !strncmp(q, "CRVL", 4) || !strncmp(q, "CDLT", 4) || !strncmp(q, "CROT", 4) || !strncmp(q, "CUNI", 4) ) i1 = 5; else if (!strncmp(rec, "TDIM", 4) ) i1 = 4; if (i1) { /* try reading the index number suffix */ q[0] = '\0'; strncat(q, &rec[i1], 8 - i1); tstatus = 0; ffc2ii(q, &ivalue, &tstatus); if (tstatus == 0 && ivalue >= colmin && ivalue <= colmax) { if (incre <= 0 && ivalue == colmin) { ffdrec(fptr, nrec, status); /* delete keyword */ nkeys = nkeys - 1; nrec = nrec - 1; } else { ivalue = ivalue + incre; q[0] = '\0'; strncat(q, rec, i1); ffkeyn(q, ivalue, newkey, status); strncpy(rec, " ", 8); /* erase old keyword name */ i1 = strlen(newkey); strncpy(rec, newkey, i1); /* overwrite new keyword name */ ffmrec(fptr, nrec, rec, status); /* modify the record */ } } } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffshft(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG firstbyte, /* I - position of first byte in block to shift */ LONGLONG nbytes, /* I - size of block of bytes to shift */ LONGLONG nshift, /* I - size of shift in bytes (+ or -) */ int *status) /* IO - error status */ /* Shift block of bytes by nshift bytes (positive or negative). A positive nshift value moves the block down further in the file, while a negative value shifts the block towards the beginning of the file. */ { #define shftbuffsize 100000 long ntomov; LONGLONG ptr, ntodo; char buffer[shftbuffsize]; if (*status > 0) return(*status); ntodo = nbytes; /* total number of bytes to shift */ if (nshift > 0) /* start at the end of the block and work backwards */ ptr = firstbyte + nbytes; else /* start at the beginning of the block working forwards */ ptr = firstbyte; while (ntodo) { /* number of bytes to move at one time */ ntomov = (long) (minvalue(ntodo, shftbuffsize)); if (nshift > 0) /* if moving block down ... */ ptr -= ntomov; /* move to position and read the bytes to be moved */ ffmbyt(fptr, ptr, REPORT_EOF, status); ffgbyt(fptr, ntomov, buffer, status); /* move by shift amount and write the bytes */ ffmbyt(fptr, ptr + nshift, IGNORE_EOF, status); if (ffpbyt(fptr, ntomov, buffer, status) > 0) { ffpmsg("Error while shifting block (ffshft)"); return(*status); } ntodo -= ntomov; if (nshift < 0) /* if moving block up ... */ ptr += ntomov; } /* now overwrite the old data with fill */ if ((fptr->Fptr)->hdutype == ASCII_TBL) memset(buffer, 32, shftbuffsize); /* fill ASCII tables with spaces */ else memset(buffer, 0, shftbuffsize); /* fill other HDUs with zeros */ if (nshift < 0) { ntodo = -nshift; /* point to the end of the shifted block */ ptr = firstbyte + nbytes + nshift; } else { ntodo = nshift; /* point to original beginning of the block */ ptr = firstbyte; } ffmbyt(fptr, ptr, REPORT_EOF, status); while (ntodo) { ntomov = (long) (minvalue(ntodo, shftbuffsize)); ffpbyt(fptr, ntomov, buffer, status); ntodo -= ntomov; } return(*status); } cfitsio/edithdu.c0000644000225700000360000007506213246025103013604 0ustar cagordonlhea/* This file, edithdu.c, contains the FITSIO routines related to */ /* copying, inserting, or deleting HDUs in a FITS file */ /* The FITSIO software was written by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ #include #include #include "fitsio2.h" /*--------------------------------------------------------------------------*/ int ffcopy(fitsfile *infptr, /* I - FITS file pointer to input file */ fitsfile *outfptr, /* I - FITS file pointer to output file */ int morekeys, /* I - reserve space in output header */ int *status) /* IO - error status */ /* copy the CHDU from infptr to the CHDU of outfptr. This will also allocate space in the output header for MOREKY keywords */ { int nspace; if (*status > 0) return(*status); if (infptr == outfptr) return(*status = SAME_FILE); if (ffcphd(infptr, outfptr, status) > 0) /* copy the header keywords */ return(*status); if (morekeys > 0) { ffhdef(outfptr, morekeys, status); /* reserve space for more keywords */ } else { if (ffghsp(infptr, NULL, &nspace, status) > 0) /* get existing space */ return(*status); if (nspace > 0) { ffhdef(outfptr, nspace, status); /* preserve same amount of space */ if (nspace >= 35) { /* There is at least 1 full empty FITS block in the header. */ /* Physically write the END keyword at the beginning of the */ /* last block to preserve this extra space now rather than */ /* later. This is needed by the stream: driver which cannot */ /* seek back to the header to write the END keyword later. */ ffwend(outfptr, status); } } } ffcpdt(infptr, outfptr, status); /* now copy the data unit */ return(*status); } /*--------------------------------------------------------------------------*/ int ffcpfl(fitsfile *infptr, /* I - FITS file pointer to input file */ fitsfile *outfptr, /* I - FITS file pointer to output file */ int previous, /* I - copy any previous HDUs? */ int current, /* I - copy the current HDU? */ int following, /* I - copy any following HDUs? */ int *status) /* IO - error status */ /* copy all or part of the input file to the output file. */ { int hdunum, ii; if (*status > 0) return(*status); if (infptr == outfptr) return(*status = SAME_FILE); ffghdn(infptr, &hdunum); if (previous) { /* copy any previous HDUs */ for (ii=1; ii < hdunum; ii++) { ffmahd(infptr, ii, NULL, status); ffcopy(infptr, outfptr, 0, status); } } if (current && (*status <= 0) ) { /* copy current HDU */ ffmahd(infptr, hdunum, NULL, status); ffcopy(infptr, outfptr, 0, status); } if (following && (*status <= 0) ) { /* copy any remaining HDUs */ ii = hdunum + 1; while (1) { if (ffmahd(infptr, ii, NULL, status) ) { /* reset expected end of file status */ if (*status == END_OF_FILE) *status = 0; break; } if (ffcopy(infptr, outfptr, 0, status)) break; /* quit on unexpected error */ ii++; } } ffmahd(infptr, hdunum, NULL, status); /* restore initial position */ return(*status); } /*--------------------------------------------------------------------------*/ int ffcphd(fitsfile *infptr, /* I - FITS file pointer to input file */ fitsfile *outfptr, /* I - FITS file pointer to output file */ int *status) /* IO - error status */ /* copy the header keywords from infptr to outfptr. */ { int nkeys, ii, inPrim = 0, outPrim = 0; long naxis, naxes[1]; char *card, comm[FLEN_COMMENT]; char *tmpbuff; if (*status > 0) return(*status); if (infptr == outfptr) return(*status = SAME_FILE); /* set the input pointer to the correct HDU */ if (infptr->HDUposition != (infptr->Fptr)->curhdu) ffmahd(infptr, (infptr->HDUposition) + 1, NULL, status); if (ffghsp(infptr, &nkeys, NULL, status) > 0) /* get no. of keywords */ return(*status); /* create a memory buffer to hold the header records */ tmpbuff = (char*) malloc(nkeys*FLEN_CARD*sizeof(char)); if (!tmpbuff) return(*status = MEMORY_ALLOCATION); /* read all of the header records in the input HDU */ for (ii = 0; ii < nkeys; ii++) ffgrec(infptr, ii+1, tmpbuff + (ii * FLEN_CARD), status); if (infptr->HDUposition == 0) /* set flag if this is the Primary HDU */ inPrim = 1; /* if input is an image hdu, get the number of axes */ naxis = -1; /* negative if HDU is a table */ if ((infptr->Fptr)->hdutype == IMAGE_HDU) ffgkyj(infptr, "NAXIS", &naxis, NULL, status); /* set the output pointer to the correct HDU */ if (outfptr->HDUposition != (outfptr->Fptr)->curhdu) ffmahd(outfptr, (outfptr->HDUposition) + 1, NULL, status); /* check if output header is empty; if not create new empty HDU */ if ((outfptr->Fptr)->headend != (outfptr->Fptr)->headstart[(outfptr->Fptr)->curhdu] ) ffcrhd(outfptr, status); if (outfptr->HDUposition == 0) { if (naxis < 0) { /* the input HDU is a table, so we have to create */ /* a dummy Primary array before copying it to the output */ ffcrim(outfptr, 8, 0, naxes, status); ffcrhd(outfptr, status); /* create new empty HDU */ } else { /* set flag that this is the Primary HDU */ outPrim = 1; } } if (*status > 0) /* check for errors before proceeding */ { free(tmpbuff); return(*status); } if ( inPrim == 1 && outPrim == 0 ) { /* copying from primary array to image extension */ strcpy(comm, "IMAGE extension"); ffpkys(outfptr, "XTENSION", "IMAGE", comm, status); /* copy BITPIX through NAXISn keywords */ for (ii = 1; ii < 3 + naxis; ii++) { card = tmpbuff + (ii * FLEN_CARD); ffprec(outfptr, card, status); } strcpy(comm, "number of random group parameters"); ffpkyj(outfptr, "PCOUNT", 0, comm, status); strcpy(comm, "number of random groups"); ffpkyj(outfptr, "GCOUNT", 1, comm, status); /* copy remaining keywords, excluding EXTEND, and reference COMMENT keywords */ for (ii = 3 + naxis ; ii < nkeys; ii++) { card = tmpbuff+(ii * FLEN_CARD); if (FSTRNCMP(card, "EXTEND ", 8) && FSTRNCMP(card, "COMMENT FITS (Flexible Image Transport System) format is", 58) && FSTRNCMP(card, "COMMENT and Astrophysics', volume 376, page 3", 47) ) { ffprec(outfptr, card, status); } } } else if ( inPrim == 0 && outPrim == 1 ) { /* copying between image extension and primary array */ strcpy(comm, "file does conform to FITS standard"); ffpkyl(outfptr, "SIMPLE", TRUE, comm, status); /* copy BITPIX through NAXISn keywords */ for (ii = 1; ii < 3 + naxis; ii++) { card = tmpbuff + (ii * FLEN_CARD); ffprec(outfptr, card, status); } /* add the EXTEND keyword */ strcpy(comm, "FITS dataset may contain extensions"); ffpkyl(outfptr, "EXTEND", TRUE, comm, status); /* write standard block of self-documentating comments */ ffprec(outfptr, "COMMENT FITS (Flexible Image Transport System) format is defined in 'Astronomy", status); ffprec(outfptr, "COMMENT and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H", status); /* copy remaining keywords, excluding pcount, gcount */ for (ii = 3 + naxis; ii < nkeys; ii++) { card = tmpbuff+(ii * FLEN_CARD); if (FSTRNCMP(card, "PCOUNT ", 8) && FSTRNCMP(card, "GCOUNT ", 8)) { ffprec(outfptr, card, status); } } } else { /* input and output HDUs are same type; simply copy all keywords */ for (ii = 0; ii < nkeys; ii++) { card = tmpbuff+(ii * FLEN_CARD); ffprec(outfptr, card, status); } } free(tmpbuff); return(*status); } /*--------------------------------------------------------------------------*/ int ffcpdt(fitsfile *infptr, /* I - FITS file pointer to input file */ fitsfile *outfptr, /* I - FITS file pointer to output file */ int *status) /* IO - error status */ { /* copy the data unit from the CHDU of infptr to the CHDU of outfptr. This will overwrite any data already in the outfptr CHDU. */ long nb, ii; LONGLONG indatastart, indataend, outdatastart; char buffer[2880]; if (*status > 0) return(*status); if (infptr == outfptr) return(*status = SAME_FILE); ffghadll(infptr, NULL, &indatastart, &indataend, status); ffghadll(outfptr, NULL, &outdatastart, NULL, status); /* Calculate the number of blocks to be copied */ nb = (long) ((indataend - indatastart) / 2880); if (nb > 0) { if (infptr->Fptr == outfptr->Fptr) { /* copying between 2 HDUs in the SAME file */ for (ii = 0; ii < nb; ii++) { ffmbyt(infptr, indatastart, REPORT_EOF, status); ffgbyt(infptr, 2880L, buffer, status); /* read input block */ ffmbyt(outfptr, outdatastart, IGNORE_EOF, status); ffpbyt(outfptr, 2880L, buffer, status); /* write output block */ indatastart += 2880; /* move address */ outdatastart += 2880; /* move address */ } } else { /* copying between HDUs in separate files */ /* move to the initial copy position in each of the files */ ffmbyt(infptr, indatastart, REPORT_EOF, status); ffmbyt(outfptr, outdatastart, IGNORE_EOF, status); for (ii = 0; ii < nb; ii++) { ffgbyt(infptr, 2880L, buffer, status); /* read input block */ ffpbyt(outfptr, 2880L, buffer, status); /* write output block */ } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffwrhdu(fitsfile *infptr, /* I - FITS file pointer to input file */ FILE *outstream, /* I - stream to write HDU to */ int *status) /* IO - error status */ { /* write the data unit from the CHDU of infptr to the output file stream */ long nb, ii; LONGLONG hdustart, hduend; char buffer[2880]; if (*status > 0) return(*status); ffghadll(infptr, &hdustart, NULL, &hduend, status); nb = (long) ((hduend - hdustart) / 2880); /* number of blocks to copy */ if (nb > 0) { /* move to the start of the HDU */ ffmbyt(infptr, hdustart, REPORT_EOF, status); for (ii = 0; ii < nb; ii++) { ffgbyt(infptr, 2880L, buffer, status); /* read input block */ fwrite(buffer, 1, 2880, outstream ); /* write to output stream */ } } return(*status); } /*--------------------------------------------------------------------------*/ int ffiimg(fitsfile *fptr, /* I - FITS file pointer */ int bitpix, /* I - bits per pixel */ int naxis, /* I - number of axes in the array */ long *naxes, /* I - size of each axis */ int *status) /* IO - error status */ /* insert an IMAGE extension following the current HDU */ { LONGLONG tnaxes[99]; int ii; if (*status > 0) return(*status); if (naxis > 99) { ffpmsg("NAXIS value is too large (>99) (ffiimg)"); return(*status = 212); } for (ii = 0; (ii < naxis); ii++) tnaxes[ii] = naxes[ii]; ffiimgll(fptr, bitpix, naxis, tnaxes, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffiimgll(fitsfile *fptr, /* I - FITS file pointer */ int bitpix, /* I - bits per pixel */ int naxis, /* I - number of axes in the array */ LONGLONG *naxes, /* I - size of each axis */ int *status) /* IO - error status */ /* insert an IMAGE extension following the current HDU */ { int bytlen, nexthdu, maxhdu, ii, onaxis; long nblocks; LONGLONG npixels, newstart, datasize; char errmsg[FLEN_ERRMSG], card[FLEN_CARD], naxiskey[FLEN_KEYWORD]; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); maxhdu = (fptr->Fptr)->maxhdu; if (*status != PREPEND_PRIMARY) { /* if the current header is completely empty ... */ if (( (fptr->Fptr)->headend == (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu]) /* or, if we are at the end of the file, ... */ || ( (((fptr->Fptr)->curhdu) == maxhdu ) && ((fptr->Fptr)->headstart[maxhdu + 1] >= (fptr->Fptr)->logfilesize ) ) ) { /* then simply append new image extension */ ffcrimll(fptr, bitpix, naxis, naxes, status); return(*status); } } if (bitpix == 8) bytlen = 1; else if (bitpix == 16) bytlen = 2; else if (bitpix == 32 || bitpix == -32) bytlen = 4; else if (bitpix == 64 || bitpix == -64) bytlen = 8; else { snprintf(errmsg, FLEN_ERRMSG, "Illegal value for BITPIX keyword: %d", bitpix); ffpmsg(errmsg); return(*status = BAD_BITPIX); /* illegal bitpix value */ } if (naxis < 0 || naxis > 999) { snprintf(errmsg, FLEN_ERRMSG, "Illegal value for NAXIS keyword: %d", naxis); ffpmsg(errmsg); return(*status = BAD_NAXIS); } for (ii = 0; ii < naxis; ii++) { if (naxes[ii] < 0) { snprintf(errmsg, FLEN_ERRMSG, "Illegal value for NAXIS%d keyword: %ld", ii + 1, (long) naxes[ii]); ffpmsg(errmsg); return(*status = BAD_NAXES); } } /* calculate number of pixels in the image */ if (naxis == 0) npixels = 0; else npixels = naxes[0]; for (ii = 1; ii < naxis; ii++) npixels = npixels * naxes[ii]; datasize = npixels * bytlen; /* size of image in bytes */ nblocks = (long) (((datasize + 2879) / 2880) + 1); /* +1 for the header */ if ((fptr->Fptr)->writemode == READWRITE) /* must have write access */ { /* close the CHDU */ ffrdef(fptr, status); /* scan header to redefine structure */ ffpdfl(fptr, status); /* insure correct data file values */ } else return(*status = READONLY_FILE); if (*status == PREPEND_PRIMARY) { /* inserting a new primary array; the current primary */ /* array must be transformed into an image extension. */ *status = 0; ffmahd(fptr, 1, NULL, status); /* move to the primary array */ ffgidm(fptr, &onaxis, status); if (onaxis > 0) ffkeyn("NAXIS",onaxis, naxiskey, status); else strcpy(naxiskey, "NAXIS"); ffgcrd(fptr, naxiskey, card, status); /* read last NAXIS keyword */ ffikyj(fptr, "PCOUNT", 0, "required keyword", status); /* add PCOUNT and */ ffikyj(fptr, "GCOUNT", 1, "required keyword", status); /* GCOUNT keywords */ if (*status > 0) return(*status); if (ffdkey(fptr, "EXTEND", status) ) /* delete the EXTEND keyword */ *status = 0; /* redefine internal structure for this HDU */ ffrdef(fptr, status); /* insert space for the primary array */ if (ffiblk(fptr, nblocks, -1, status) > 0) /* insert the blocks */ return(*status); nexthdu = 0; /* number of the new hdu */ newstart = 0; /* starting addr of HDU */ } else { nexthdu = ((fptr->Fptr)->curhdu) + 1; /* number of the next (new) hdu */ newstart = (fptr->Fptr)->headstart[nexthdu]; /* save starting addr of HDU */ (fptr->Fptr)->hdutype = IMAGE_HDU; /* so that correct fill value is used */ /* ffiblk also increments headstart for all following HDUs */ if (ffiblk(fptr, nblocks, 1, status) > 0) /* insert the blocks */ return(*status); } ((fptr->Fptr)->maxhdu)++; /* increment known number of HDUs in the file */ for (ii = (fptr->Fptr)->maxhdu; ii > (fptr->Fptr)->curhdu; ii--) (fptr->Fptr)->headstart[ii + 1] = (fptr->Fptr)->headstart[ii]; /* incre start addr */ if (nexthdu == 0) (fptr->Fptr)->headstart[1] = nblocks * 2880; /* start of the old Primary array */ (fptr->Fptr)->headstart[nexthdu] = newstart; /* set starting addr of HDU */ /* set default parameters for this new empty HDU */ (fptr->Fptr)->curhdu = nexthdu; /* we are now located at the next HDU */ fptr->HDUposition = nexthdu; /* we are now located at the next HDU */ (fptr->Fptr)->nextkey = (fptr->Fptr)->headstart[nexthdu]; (fptr->Fptr)->headend = (fptr->Fptr)->headstart[nexthdu]; (fptr->Fptr)->datastart = ((fptr->Fptr)->headstart[nexthdu]) + 2880; (fptr->Fptr)->hdutype = IMAGE_HDU; /* might need to be reset... */ /* write the required header keywords */ ffphprll(fptr, TRUE, bitpix, naxis, naxes, 0, 1, TRUE, status); /* redefine internal structure for this HDU */ ffrdef(fptr, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffitab(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG naxis1, /* I - width of row in the table */ LONGLONG naxis2, /* I - number of rows in the table */ int tfields, /* I - number of columns in the table */ char **ttype, /* I - name of each column */ long *tbcol, /* I - byte offset in row to each column */ char **tform, /* I - value of TFORMn keyword for each column */ char **tunit, /* I - value of TUNITn keyword for each column */ const char *extnmx, /* I - value of EXTNAME keyword, if any */ int *status) /* IO - error status */ /* insert an ASCII table extension following the current HDU */ { int nexthdu, maxhdu, ii, nunit, nhead, ncols, gotmem = 0; long nblocks, rowlen; LONGLONG datasize, newstart; char errmsg[FLEN_ERRMSG], extnm[FLEN_VALUE]; if (*status > 0) return(*status); extnm[0] = '\0'; if (extnmx) strncat(extnm, extnmx, FLEN_VALUE-1); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); maxhdu = (fptr->Fptr)->maxhdu; /* if the current header is completely empty ... */ if (( (fptr->Fptr)->headend == (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] ) /* or, if we are at the end of the file, ... */ || ( (((fptr->Fptr)->curhdu) == maxhdu ) && ((fptr->Fptr)->headstart[maxhdu + 1] >= (fptr->Fptr)->logfilesize ) ) ) { /* then simply append new image extension */ ffcrtb(fptr, ASCII_TBL, naxis2, tfields, ttype, tform, tunit, extnm, status); return(*status); } if (naxis1 < 0) return(*status = NEG_WIDTH); else if (naxis2 < 0) return(*status = NEG_ROWS); else if (tfields < 0 || tfields > 999) { snprintf(errmsg, FLEN_ERRMSG, "Illegal value for TFIELDS keyword: %d", tfields); ffpmsg(errmsg); return(*status = BAD_TFIELDS); } /* count number of optional TUNIT keywords to be written */ nunit = 0; for (ii = 0; ii < tfields; ii++) { if (tunit && *tunit && *tunit[ii]) nunit++; } if (*extnm) nunit++; /* add one for the EXTNAME keyword */ rowlen = (long) naxis1; if (!tbcol || !tbcol[0] || (!naxis1 && tfields)) /* spacing not defined? */ { /* allocate mem for tbcol; malloc may have problems allocating small */ /* arrays, so allocate at least 20 bytes */ ncols = maxvalue(5, tfields); tbcol = (long *) calloc(ncols, sizeof(long)); if (tbcol) { gotmem = 1; /* calculate width of a row and starting position of each column. */ /* Each column will be separated by 1 blank space */ ffgabc(tfields, tform, 1, &rowlen, tbcol, status); } } nhead = (9 + (3 * tfields) + nunit + 35) / 36; /* no. of header blocks */ datasize = (LONGLONG)rowlen * naxis2; /* size of table in bytes */ nblocks = (long) (((datasize + 2879) / 2880) + nhead); /* size of HDU */ if ((fptr->Fptr)->writemode == READWRITE) /* must have write access */ { /* close the CHDU */ ffrdef(fptr, status); /* scan header to redefine structure */ ffpdfl(fptr, status); /* insure correct data file values */ } else return(*status = READONLY_FILE); nexthdu = ((fptr->Fptr)->curhdu) + 1; /* number of the next (new) hdu */ newstart = (fptr->Fptr)->headstart[nexthdu]; /* save starting addr of HDU */ (fptr->Fptr)->hdutype = ASCII_TBL; /* so that correct fill value is used */ /* ffiblk also increments headstart for all following HDUs */ if (ffiblk(fptr, nblocks, 1, status) > 0) /* insert the blocks */ { if (gotmem) free(tbcol); return(*status); } ((fptr->Fptr)->maxhdu)++; /* increment known number of HDUs in the file */ for (ii = (fptr->Fptr)->maxhdu; ii > (fptr->Fptr)->curhdu; ii--) (fptr->Fptr)->headstart[ii + 1] = (fptr->Fptr)->headstart[ii]; /* incre start addr */ (fptr->Fptr)->headstart[nexthdu] = newstart; /* set starting addr of HDU */ /* set default parameters for this new empty HDU */ (fptr->Fptr)->curhdu = nexthdu; /* we are now located at the next HDU */ fptr->HDUposition = nexthdu; /* we are now located at the next HDU */ (fptr->Fptr)->nextkey = (fptr->Fptr)->headstart[nexthdu]; (fptr->Fptr)->headend = (fptr->Fptr)->headstart[nexthdu]; (fptr->Fptr)->datastart = ((fptr->Fptr)->headstart[nexthdu]) + (nhead * 2880); (fptr->Fptr)->hdutype = ASCII_TBL; /* might need to be reset... */ /* write the required header keywords */ ffphtb(fptr, rowlen, naxis2, tfields, ttype, tbcol, tform, tunit, extnm, status); if (gotmem) free(tbcol); /* redefine internal structure for this HDU */ ffrdef(fptr, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffibin(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG naxis2, /* I - number of rows in the table */ int tfields, /* I - number of columns in the table */ char **ttype, /* I - name of each column */ char **tform, /* I - value of TFORMn keyword for each column */ char **tunit, /* I - value of TUNITn keyword for each column */ const char *extnmx, /* I - value of EXTNAME keyword, if any */ LONGLONG pcount, /* I - size of special data area (heap) */ int *status) /* IO - error status */ /* insert a Binary table extension following the current HDU */ { int nexthdu, maxhdu, ii, nunit, nhead, datacode; LONGLONG naxis1; long nblocks, repeat, width; LONGLONG datasize, newstart; char errmsg[FLEN_ERRMSG], extnm[FLEN_VALUE]; if (*status > 0) return(*status); extnm[0] = '\0'; if (extnmx) strncat(extnm, extnmx, FLEN_VALUE-1); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); maxhdu = (fptr->Fptr)->maxhdu; /* if the current header is completely empty ... */ if (( (fptr->Fptr)->headend == (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] ) /* or, if we are at the end of the file, ... */ || ( (((fptr->Fptr)->curhdu) == maxhdu ) && ((fptr->Fptr)->headstart[maxhdu + 1] >= (fptr->Fptr)->logfilesize ) ) ) { /* then simply append new image extension */ ffcrtb(fptr, BINARY_TBL, naxis2, tfields, ttype, tform, tunit, extnm, status); return(*status); } if (naxis2 < 0) return(*status = NEG_ROWS); else if (tfields < 0 || tfields > 999) { snprintf(errmsg, FLEN_ERRMSG, "Illegal value for TFIELDS keyword: %d", tfields); ffpmsg(errmsg); return(*status = BAD_TFIELDS); } /* count number of optional TUNIT keywords to be written */ nunit = 0; for (ii = 0; ii < tfields; ii++) { if (tunit && *tunit && *tunit[ii]) nunit++; } if (*extnm) nunit++; /* add one for the EXTNAME keyword */ nhead = (9 + (2 * tfields) + nunit + 35) / 36; /* no. of header blocks */ /* calculate total width of the table */ naxis1 = 0; for (ii = 0; ii < tfields; ii++) { ffbnfm(tform[ii], &datacode, &repeat, &width, status); if (datacode == TBIT) naxis1 = naxis1 + ((repeat + 7) / 8); else if (datacode == TSTRING) naxis1 += repeat; else naxis1 = naxis1 + (repeat * width); } datasize = ((LONGLONG)naxis1 * naxis2) + pcount; /* size of table in bytes */ nblocks = (long) ((datasize + 2879) / 2880) + nhead; /* size of HDU */ if ((fptr->Fptr)->writemode == READWRITE) /* must have write access */ { /* close the CHDU */ ffrdef(fptr, status); /* scan header to redefine structure */ ffpdfl(fptr, status); /* insure correct data file values */ } else return(*status = READONLY_FILE); nexthdu = ((fptr->Fptr)->curhdu) + 1; /* number of the next (new) hdu */ newstart = (fptr->Fptr)->headstart[nexthdu]; /* save starting addr of HDU */ (fptr->Fptr)->hdutype = BINARY_TBL; /* so that correct fill value is used */ /* ffiblk also increments headstart for all following HDUs */ if (ffiblk(fptr, nblocks, 1, status) > 0) /* insert the blocks */ return(*status); ((fptr->Fptr)->maxhdu)++; /* increment known number of HDUs in the file */ for (ii = (fptr->Fptr)->maxhdu; ii > (fptr->Fptr)->curhdu; ii--) (fptr->Fptr)->headstart[ii + 1] = (fptr->Fptr)->headstart[ii]; /* incre start addr */ (fptr->Fptr)->headstart[nexthdu] = newstart; /* set starting addr of HDU */ /* set default parameters for this new empty HDU */ (fptr->Fptr)->curhdu = nexthdu; /* we are now located at the next HDU */ fptr->HDUposition = nexthdu; /* we are now located at the next HDU */ (fptr->Fptr)->nextkey = (fptr->Fptr)->headstart[nexthdu]; (fptr->Fptr)->headend = (fptr->Fptr)->headstart[nexthdu]; (fptr->Fptr)->datastart = ((fptr->Fptr)->headstart[nexthdu]) + (nhead * 2880); (fptr->Fptr)->hdutype = BINARY_TBL; /* might need to be reset... */ /* write the required header keywords. This will write PCOUNT = 0 */ /* so that the variable length data will be written at the right place */ ffphbn(fptr, naxis2, tfields, ttype, tform, tunit, extnm, pcount, status); /* redefine internal structure for this HDU (with PCOUNT = 0) */ ffrdef(fptr, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffdhdu(fitsfile *fptr, /* I - FITS file pointer */ int *hdutype, /* O - type of the new CHDU after deletion */ int *status) /* IO - error status */ /* Delete the CHDU. If the CHDU is the primary array, then replace the HDU with an empty primary array with no data. Return the type of the new CHDU after the old CHDU is deleted. */ { int tmptype = 0; long nblocks, ii, naxes[1]; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); if ((fptr->Fptr)->curhdu == 0) /* replace primary array with null image */ { /* ignore any existing keywords */ (fptr->Fptr)->headend = 0; (fptr->Fptr)->nextkey = 0; /* write default primary array header */ ffphpr(fptr,1,8,0,naxes,0,1,1,status); /* calc number of blocks to delete (leave just 1 block) */ nblocks = (long) (( (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu + 1] - 2880 ) / 2880); /* ffdblk also updates the starting address of all following HDUs */ if (nblocks > 0) { if (ffdblk(fptr, nblocks, status) > 0) /* delete the HDU */ return(*status); } /* this might not be necessary, but is doesn't hurt */ (fptr->Fptr)->datastart = DATA_UNDEFINED; ffrdef(fptr, status); /* reinitialize the primary array */ } else { /* calc number of blocks to delete */ nblocks = (long) (( (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu + 1] - (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] ) / 2880); /* ffdblk also updates the starting address of all following HDUs */ if (ffdblk(fptr, nblocks, status) > 0) /* delete the HDU */ return(*status); /* delete the CHDU from the list of HDUs */ for (ii = (fptr->Fptr)->curhdu + 1; ii <= (fptr->Fptr)->maxhdu; ii++) (fptr->Fptr)->headstart[ii] = (fptr->Fptr)->headstart[ii + 1]; (fptr->Fptr)->headstart[(fptr->Fptr)->maxhdu + 1] = 0; ((fptr->Fptr)->maxhdu)--; /* decrement the known number of HDUs */ if (ffrhdu(fptr, &tmptype, status) > 0) /* initialize next HDU */ { /* failed (end of file?), so move back one HDU */ *status = 0; ffcmsg(); /* clear extraneous error messages */ ffgext(fptr, ((fptr->Fptr)->curhdu) - 1, &tmptype, status); } } if (hdutype) *hdutype = tmptype; return(*status); } cfitsio/eval.l0000644000225700000360000003572313246025103013116 0ustar cagordonlhea%{ /************************************************************************/ /* */ /* CFITSIO Lexical Parser */ /* */ /* This file is one of 3 files containing code which parses an */ /* arithmetic expression and evaluates it in the context of an input */ /* FITS file table extension. The CFITSIO lexical parser is divided */ /* into the following 3 parts/files: the CFITSIO "front-end", */ /* eval_f.c, contains the interface between the user/CFITSIO and the */ /* real core of the parser; the FLEX interpreter, eval_l.c, takes the */ /* input string and parses it into tokens and identifies the FITS */ /* information required to evaluate the expression (ie, keywords and */ /* columns); and, the BISON grammar and evaluation routines, eval_y.c, */ /* receives the FLEX output and determines and performs the actual */ /* operations. The files eval_l.c and eval_y.c are produced from */ /* running flex and bison on the files eval.l and eval.y, respectively. */ /* (flex and bison are available from any GNU archive: see www.gnu.org) */ /* */ /* The grammar rules, rather than evaluating the expression in situ, */ /* builds a tree, or Nodal, structure mapping out the order of */ /* operations and expression dependencies. This "compilation" process */ /* allows for much faster processing of multiple rows. This technique */ /* was developed by Uwe Lammers of the XMM Science Analysis System, */ /* although the CFITSIO implementation is entirely code original. */ /* */ /* */ /* Modification History: */ /* */ /* Kent Blackburn c1992 Original parser code developed for the */ /* FTOOLS software package, in particular, */ /* the fselect task. */ /* Kent Blackburn c1995 BIT column support added */ /* Peter D Wilson Feb 1998 Vector column support added */ /* Peter D Wilson May 1998 Ported to CFITSIO library. User */ /* interface routines written, in essence */ /* making fselect, fcalc, and maketime */ /* capabilities available to all tools */ /* via single function calls. */ /* Peter D Wilson Jun 1998 Major rewrite of parser core, so as to */ /* create a run-time evaluation tree, */ /* inspired by the work of Uwe Lammers, */ /* resulting in a speed increase of */ /* 10-100 times. */ /* Peter D Wilson Jul 1998 gtifilter(a,b,c,d) function added */ /* Peter D Wilson Aug 1998 regfilter(a,b,c,d) function added */ /* Peter D Wilson Jul 1999 Make parser fitsfile-independent, */ /* allowing a purely vector-based usage */ /* */ /************************************************************************/ #include #include #include #ifdef sparc #include #else #include #endif #include "eval_defs.h" ParseData gParse; /* Global structure holding all parser information */ /***** Internal functions *****/ int yyGetVariable( char *varName, YYSTYPE *varVal ); static int find_variable( char *varName ); static int expr_read( char *buf, int nbytes ); /***** Definitions *****/ #define YY_NO_UNPUT /* Don't include YYUNPUT function */ #define YY_NEVER_INTERACTIVE 1 #define MAXCHR 256 #define MAXBIT 128 #define OCT_0 "000" #define OCT_1 "001" #define OCT_2 "010" #define OCT_3 "011" #define OCT_4 "100" #define OCT_5 "101" #define OCT_6 "110" #define OCT_7 "111" #define OCT_X "xxx" #define HEX_0 "0000" #define HEX_1 "0001" #define HEX_2 "0010" #define HEX_3 "0011" #define HEX_4 "0100" #define HEX_5 "0101" #define HEX_6 "0110" #define HEX_7 "0111" #define HEX_8 "1000" #define HEX_9 "1001" #define HEX_A "1010" #define HEX_B "1011" #define HEX_C "1100" #define HEX_D "1101" #define HEX_E "1110" #define HEX_F "1111" #define HEX_X "xxxx" /* MJT - 13 June 1996 read from buffer instead of stdin (as per old ftools.skel) */ #undef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( (result = expr_read( (char *) buf, max_size )) < 0 ) \ YY_FATAL_ERROR( "read() in flex scanner failed" ); %} bit ([bB][01xX]+) oct ([oO][01234567xX]+) hex ([hH][0123456789aAbBcCdDeEfFxX]+) integer [0-9]+ boolean (t|f|T|F) real ([0-9]*"."[0-9]+)|([0-9]*"."*[0-9]+[eEdD][+-]?[0-9]+)|([0-9]*".") constant ("#"[a-zA-Z0-9_]+)|("#""$"[^\n]*"$") string ([\"][^\"\n]*[\"])|([\'][^\'\n]*[\']) variable ([a-zA-Z_][a-zA-Z0-9_]*)|("$"[^$\n]*"$") function [a-zA-Z][a-zA-Z0-9]+"(" intcast ("(int)"|"(INT)") fltcast ("(float)"|"(FLOAT)"|"(double)"|"(DOUBLE)") power ("^"|"**") not ("!"|".not."|".NOT."|"not."|"NOT.") or ("||"|".or."|".OR."|"or."|"OR.") and ("&&"|".and."|".AND."|"and."|"AND.") equal ("=="|".eq."|".EQ."|"eq."|"EQ.") not_equal ("!="|".ne."|".NE."|"ne."|"NE.") greater (">"|".gt."|".GT."|"gt."|"GT.") lesser ("<"|".lt."|".LT."|"lt."|"LT.") greater_eq (">="|"=>"|".ge."|".GE."|"ge."|"GE.") lesser_eq ("<="|"=<"|".le."|".LE."|"le."|"LE.") nl \n %% [ \t]+ ; {bit} { int len; len = strlen(yytext); while (yytext[len] == ' ') len--; len = len - 1; strncpy(yylval.str,&yytext[1],len); yylval.str[len] = '\0'; return( BITSTR ); } {oct} { int len; char tmpstring[256]; char bitstring[256]; len = strlen(yytext); if (len >= 256) { char errMsg[100]; gParse.status = PARSE_SYNTAX_ERR; strcpy (errMsg,"Bit string exceeds maximum length: '"); strncat(errMsg, &(yytext[0]), 20); strcat (errMsg,"...'"); ffpmsg (errMsg); len = 0; } else { while (yytext[len] == ' ') len--; len = len - 1; strncpy(tmpstring,&yytext[1],len); } tmpstring[len] = '\0'; bitstring[0] = '\0'; len = 0; while ( tmpstring[len] != '\0') { switch ( tmpstring[len] ) { case '0': strcat(bitstring,OCT_0); break; case '1': strcat(bitstring,OCT_1); break; case '2': strcat(bitstring,OCT_2); break; case '3': strcat(bitstring,OCT_3); break; case '4': strcat(bitstring,OCT_4); break; case '5': strcat(bitstring,OCT_5); break; case '6': strcat(bitstring,OCT_6); break; case '7': strcat(bitstring,OCT_7); break; case 'x': case 'X': strcat(bitstring,OCT_X); break; } len++; } strcpy( yylval.str, bitstring ); return( BITSTR ); } {hex} { int len; char tmpstring[256]; char bitstring[256]; len = strlen(yytext); if (len >= 256) { char errMsg[100]; gParse.status = PARSE_SYNTAX_ERR; strcpy (errMsg,"Hex string exceeds maximum length: '"); strncat(errMsg, &(yytext[0]), 20); strcat (errMsg,"...'"); ffpmsg (errMsg); len = 0; } else { while (yytext[len] == ' ') len--; len = len - 1; strncpy(tmpstring,&yytext[1],len); } tmpstring[len] = '\0'; bitstring[0] = '\0'; len = 0; while ( tmpstring[len] != '\0') { switch ( tmpstring[len] ) { case '0': strcat(bitstring,HEX_0); break; case '1': strcat(bitstring,HEX_1); break; case '2': strcat(bitstring,HEX_2); break; case '3': strcat(bitstring,HEX_3); break; case '4': strcat(bitstring,HEX_4); break; case '5': strcat(bitstring,HEX_5); break; case '6': strcat(bitstring,HEX_6); break; case '7': strcat(bitstring,HEX_7); break; case '8': strcat(bitstring,HEX_8); break; case '9': strcat(bitstring,HEX_9); break; case 'a': case 'A': strcat(bitstring,HEX_A); break; case 'b': case 'B': strcat(bitstring,HEX_B); break; case 'c': case 'C': strcat(bitstring,HEX_C); break; case 'd': case 'D': strcat(bitstring,HEX_D); break; case 'e': case 'E': strcat(bitstring,HEX_E); break; case 'f': case 'F': strcat(bitstring,HEX_F); break; case 'x': case 'X': strcat(bitstring,HEX_X); break; } len++; } strcpy( yylval.str, bitstring ); return( BITSTR ); } {integer} { yylval.lng = atol(yytext); return( LONG ); } {boolean} { if ((yytext[0] == 't') || (yytext[0] == 'T')) yylval.log = 1; else yylval.log = 0; return( BOOLEAN ); } {real} { yylval.dbl = atof(yytext); return( DOUBLE ); } {constant} { if( !fits_strcasecmp(yytext,"#PI") ) { yylval.dbl = (double)(4) * atan((double)(1)); return( DOUBLE ); } else if( !fits_strcasecmp(yytext,"#E") ) { yylval.dbl = exp((double)(1)); return( DOUBLE ); } else if( !fits_strcasecmp(yytext,"#DEG") ) { yylval.dbl = ((double)4)*atan((double)1)/((double)180); return( DOUBLE ); } else if( !fits_strcasecmp(yytext,"#ROW") ) { return( ROWREF ); } else if( !fits_strcasecmp(yytext,"#NULL") ) { return( NULLREF ); } else if( !fits_strcasecmp(yytext,"#SNULL") ) { return( SNULLREF ); } else { int len; if (yytext[1] == '$') { len = strlen(yytext) - 3; yylval.str[0] = '#'; strncpy(yylval.str+1,&yytext[2],len); yylval.str[len+1] = '\0'; yytext = yylval.str; } return( (*gParse.getData)(yytext, &yylval) ); } } {string} { int len; len = strlen(yytext) - 2; if (len >= MAX_STRLEN) { char errMsg[100]; gParse.status = PARSE_SYNTAX_ERR; strcpy (errMsg,"String exceeds maximum length: '"); strncat(errMsg, &(yytext[1]), 20); strcat (errMsg,"...'"); ffpmsg (errMsg); len = 0; } else { strncpy(yylval.str,&yytext[1],len); } yylval.str[len] = '\0'; return( STRING ); } {variable} { int len,type; if (yytext[0] == '$') { len = strlen(yytext) - 2; strncpy(yylval.str,&yytext[1],len); yylval.str[len] = '\0'; yytext = yylval.str; } type = yyGetVariable(yytext, &yylval); return( type ); } {function} { char *fname; int len=0; fname = &yylval.str[0]; while( (fname[len]=toupper(yytext[len])) ) len++; if( FSTRCMP(fname,"BOX(")==0 || FSTRCMP(fname,"CIRCLE(")==0 || FSTRCMP(fname,"ELLIPSE(")==0 || FSTRCMP(fname,"NEAR(")==0 || FSTRCMP(fname,"ISNULL(")==0 ) /* Return type is always boolean */ return( BFUNCTION ); else if( FSTRCMP(fname,"GTIFILTER(")==0 ) return( GTIFILTER ); else if( FSTRCMP(fname,"REGFILTER(")==0 ) return( REGFILTER ); else if( FSTRCMP(fname,"STRSTR(")==0 ) return( IFUNCTION ); /* Returns integer */ else return( FUNCTION ); } {intcast} { return( INTCAST ); } {fltcast} { return( FLTCAST ); } {power} { return( POWER ); } {not} { return( NOT ); } {or} { return( OR ); } {and} { return( AND ); } {equal} { return( EQ ); } {not_equal} { return( NE ); } {greater} { return( GT ); } {lesser} { return( LT ); } {greater_eq} { return( GTE ); } {lesser_eq} { return( LTE ); } {nl} { return( '\n' ); } . { return( yytext[0] ); } %% int yywrap() { /* MJT -- 13 June 1996 Supplied for compatibility with pre-2.5.1 versions of flex which do not recognize %option noyywrap */ return(1); } /* expr_read is lifted from old ftools.skel. Now we can use any version of flex with no .skel file necessary! MJT - 13 June 1996 keep a memory of how many bytes have been read previously, so that an unlimited-sized buffer can be supported. PDW - 28 Feb 1998 */ static int expr_read(char *buf, int nbytes) { int n; n = 0; if( !gParse.is_eobuf ) { do { buf[n++] = gParse.expr[gParse.index++]; } while ((nlng = varNum; } return( type ); } static int find_variable(char *varName) { int i; if( gParse.nCols ) for( i=0; i #include #ifndef alloca #define alloca malloc #endif /* Random number generators for various distributions */ #include "simplerng.h" /* Shrink the initial stack depth to keep local data <32K (mac limit) */ /* yacc will allocate more space if needed, though. */ #define YYINITDEPTH 100 /***************************************************************/ /* Replace Bison's BACKUP macro with one that fixes a bug -- */ /* must update state after popping the stack -- and allows */ /* popping multiple terms at one time. */ /***************************************************************/ #define YYNEWBACKUP(token, value) \ do \ if (yychar == YYEMPTY ) \ { yychar = (token); \ memcpy( &yylval, &(value), sizeof(value) ); \ yychar1 = YYTRANSLATE (yychar); \ while (yylen--) YYPOPSTACK; \ yystate = *yyssp; \ goto yybackup; \ } \ else \ { yyerror ("syntax error: cannot back up"); YYERROR; } \ while (0) /***************************************************************/ /* Useful macros for accessing/testing Nodes */ /***************************************************************/ #define TEST(a) if( (a)<0 ) YYERROR #define SIZE(a) gParse.Nodes[ a ].value.nelem #define TYPE(a) gParse.Nodes[ a ].type #define OPER(a) gParse.Nodes[ a ].operation #define PROMOTE(a,b) if( TYPE(a) > TYPE(b) ) \ b = New_Unary( TYPE(a), 0, b ); \ else if( TYPE(a) < TYPE(b) ) \ a = New_Unary( TYPE(b), 0, a ); /***** Internal functions *****/ #ifdef __cplusplus extern "C" { #endif static int Alloc_Node ( void ); static void Free_Last_Node( void ); static void Evaluate_Node ( int thisNode ); static int New_Const ( int returnType, void *value, long len ); static int New_Column( int ColNum ); static int New_Offset( int ColNum, int offset ); static int New_Unary ( int returnType, int Op, int Node1 ); static int New_BinOp ( int returnType, int Node1, int Op, int Node2 ); static int New_Func ( int returnType, funcOp Op, int nNodes, int Node1, int Node2, int Node3, int Node4, int Node5, int Node6, int Node7 ); static int New_FuncSize( int returnType, funcOp Op, int nNodes, int Node1, int Node2, int Node3, int Node4, int Node5, int Node6, int Node7, int Size); static int New_Deref ( int Var, int nDim, int Dim1, int Dim2, int Dim3, int Dim4, int Dim5 ); static int New_GTI ( char *fname, int Node1, char *start, char *stop ); static int New_REG ( char *fname, int NodeX, int NodeY, char *colNames ); static int New_Vector( int subNode ); static int Close_Vec ( int vecNode ); static int Locate_Col( Node *this ); static int Test_Dims ( int Node1, int Node2 ); static void Copy_Dims ( int Node1, int Node2 ); static void Allocate_Ptrs( Node *this ); static void Do_Unary ( Node *this ); static void Do_Offset ( Node *this ); static void Do_BinOp_bit ( Node *this ); static void Do_BinOp_str ( Node *this ); static void Do_BinOp_log ( Node *this ); static void Do_BinOp_lng ( Node *this ); static void Do_BinOp_dbl ( Node *this ); static void Do_Func ( Node *this ); static void Do_Deref ( Node *this ); static void Do_GTI ( Node *this ); static void Do_REG ( Node *this ); static void Do_Vector ( Node *this ); static long Search_GTI ( double evtTime, long nGTI, double *start, double *stop, int ordered ); static char saobox (double xcen, double ycen, double xwid, double ywid, double rot, double xcol, double ycol); static char ellipse(double xcen, double ycen, double xrad, double yrad, double rot, double xcol, double ycol); static char circle (double xcen, double ycen, double rad, double xcol, double ycol); static char bnear (double x, double y, double tolerance); static char bitcmp (char *bitstrm1, char *bitstrm2); static char bitlgte(char *bits1, int oper, char *bits2); static void bitand(char *result, char *bitstrm1, char *bitstrm2); static void bitor (char *result, char *bitstrm1, char *bitstrm2); static void bitnot(char *result, char *bits); static int cstrmid(char *dest_str, int dest_len, char *src_str, int src_len, int pos); static void yyerror(char *msg); #ifdef __cplusplus } #endif %} %union { int Node; /* Index of Node */ double dbl; /* real value */ long lng; /* integer value */ char log; /* logical value */ char str[MAX_STRLEN]; /* string value */ } %token BOOLEAN /* First 3 must be in order of */ %token LONG /* increasing promotion for later use */ %token DOUBLE %token STRING %token BITSTR %token FUNCTION %token BFUNCTION /* Bit function */ %token IFUNCTION /* Integer function */ %token GTIFILTER %token REGFILTER %token COLUMN %token BCOLUMN %token SCOLUMN %token BITCOL %token ROWREF %token NULLREF %token SNULLREF %type expr %type bexpr %type sexpr %type bits %type vector %type bvector %left ',' '=' ':' '{' '}' %right '?' %left OR %left AND %left EQ NE '~' %left GT LT LTE GTE %left '+' '-' '%' %left '*' '/' %left '|' '&' %right POWER %left NOT %left INTCAST FLTCAST %left UMINUS %left '[' %right ACCUM DIFF %% lines: /* nothing ; was | lines line */ | lines line ; line: '\n' {} | expr '\n' { if( $1<0 ) { yyerror("Couldn't build node structure: out of memory?"); YYERROR; } gParse.resultNode = $1; } | bexpr '\n' { if( $1<0 ) { yyerror("Couldn't build node structure: out of memory?"); YYERROR; } gParse.resultNode = $1; } | sexpr '\n' { if( $1<0 ) { yyerror("Couldn't build node structure: out of memory?"); YYERROR; } gParse.resultNode = $1; } | bits '\n' { if( $1<0 ) { yyerror("Couldn't build node structure: out of memory?"); YYERROR; } gParse.resultNode = $1; } | error '\n' { yyerrok; } ; bvector: '{' bexpr { $$ = New_Vector( $2 ); TEST($$); } | bvector ',' bexpr { if( gParse.Nodes[$1].nSubNodes >= MAXSUBS ) { $1 = Close_Vec( $1 ); TEST($1); $$ = New_Vector( $1 ); TEST($$); } else { $$ = $1; } gParse.Nodes[$$].SubNodes[ gParse.Nodes[$$].nSubNodes++ ] = $3; } ; vector: '{' expr { $$ = New_Vector( $2 ); TEST($$); } | vector ',' expr { if( TYPE($1) < TYPE($3) ) TYPE($1) = TYPE($3); if( gParse.Nodes[$1].nSubNodes >= MAXSUBS ) { $1 = Close_Vec( $1 ); TEST($1); $$ = New_Vector( $1 ); TEST($$); } else { $$ = $1; } gParse.Nodes[$$].SubNodes[ gParse.Nodes[$$].nSubNodes++ ] = $3; } | vector ',' bexpr { if( gParse.Nodes[$1].nSubNodes >= MAXSUBS ) { $1 = Close_Vec( $1 ); TEST($1); $$ = New_Vector( $1 ); TEST($$); } else { $$ = $1; } gParse.Nodes[$$].SubNodes[ gParse.Nodes[$$].nSubNodes++ ] = $3; } | bvector ',' expr { TYPE($1) = TYPE($3); if( gParse.Nodes[$1].nSubNodes >= MAXSUBS ) { $1 = Close_Vec( $1 ); TEST($1); $$ = New_Vector( $1 ); TEST($$); } else { $$ = $1; } gParse.Nodes[$$].SubNodes[ gParse.Nodes[$$].nSubNodes++ ] = $3; } ; expr: vector '}' { $$ = Close_Vec( $1 ); TEST($$); } ; bexpr: bvector '}' { $$ = Close_Vec( $1 ); TEST($$); } ; bits: BITSTR { $$ = New_Const( BITSTR, $1, strlen($1)+1 ); TEST($$); SIZE($$) = strlen($1); } | BITCOL { $$ = New_Column( $1 ); TEST($$); } | BITCOL '{' expr '}' { if( TYPE($3) != LONG || OPER($3) != CONST_OP ) { yyerror("Offset argument must be a constant integer"); YYERROR; } $$ = New_Offset( $1, $3 ); TEST($$); } | bits '&' bits { $$ = New_BinOp( BITSTR, $1, '&', $3 ); TEST($$); SIZE($$) = ( SIZE($1)>SIZE($3) ? SIZE($1) : SIZE($3) ); } | bits '|' bits { $$ = New_BinOp( BITSTR, $1, '|', $3 ); TEST($$); SIZE($$) = ( SIZE($1)>SIZE($3) ? SIZE($1) : SIZE($3) ); } | bits '+' bits { if (SIZE($1)+SIZE($3) >= MAX_STRLEN) { yyerror("Combined bit string size exceeds " MAX_STRLEN_S " bits"); YYERROR; } $$ = New_BinOp( BITSTR, $1, '+', $3 ); TEST($$); SIZE($$) = SIZE($1) + SIZE($3); } | bits '[' expr ']' { $$ = New_Deref( $1, 1, $3, 0, 0, 0, 0 ); TEST($$); } | bits '[' expr ',' expr ']' { $$ = New_Deref( $1, 2, $3, $5, 0, 0, 0 ); TEST($$); } | bits '[' expr ',' expr ',' expr ']' { $$ = New_Deref( $1, 3, $3, $5, $7, 0, 0 ); TEST($$); } | bits '[' expr ',' expr ',' expr ',' expr ']' { $$ = New_Deref( $1, 4, $3, $5, $7, $9, 0 ); TEST($$); } | bits '[' expr ',' expr ',' expr ',' expr ',' expr ']' { $$ = New_Deref( $1, 5, $3, $5, $7, $9, $11 ); TEST($$); } | NOT bits { $$ = New_Unary( BITSTR, NOT, $2 ); TEST($$); } | '(' bits ')' { $$ = $2; } ; expr: LONG { $$ = New_Const( LONG, &($1), sizeof(long) ); TEST($$); } | DOUBLE { $$ = New_Const( DOUBLE, &($1), sizeof(double) ); TEST($$); } | COLUMN { $$ = New_Column( $1 ); TEST($$); } | COLUMN '{' expr '}' { if( TYPE($3) != LONG || OPER($3) != CONST_OP ) { yyerror("Offset argument must be a constant integer"); YYERROR; } $$ = New_Offset( $1, $3 ); TEST($$); } | ROWREF { $$ = New_Func( LONG, row_fct, 0, 0, 0, 0, 0, 0, 0, 0 ); } | NULLREF { $$ = New_Func( LONG, null_fct, 0, 0, 0, 0, 0, 0, 0, 0 ); } | expr '%' expr { PROMOTE($1,$3); $$ = New_BinOp( TYPE($1), $1, '%', $3 ); TEST($$); } | expr '+' expr { PROMOTE($1,$3); $$ = New_BinOp( TYPE($1), $1, '+', $3 ); TEST($$); } | expr '-' expr { PROMOTE($1,$3); $$ = New_BinOp( TYPE($1), $1, '-', $3 ); TEST($$); } | expr '*' expr { PROMOTE($1,$3); $$ = New_BinOp( TYPE($1), $1, '*', $3 ); TEST($$); } | expr '/' expr { PROMOTE($1,$3); $$ = New_BinOp( TYPE($1), $1, '/', $3 ); TEST($$); } | expr POWER expr { PROMOTE($1,$3); $$ = New_BinOp( TYPE($1), $1, POWER, $3 ); TEST($$); } | '+' expr %prec UMINUS { $$ = $2; } | '-' expr %prec UMINUS { $$ = New_Unary( TYPE($2), UMINUS, $2 ); TEST($$); } | '(' expr ')' { $$ = $2; } | expr '*' bexpr { $3 = New_Unary( TYPE($1), 0, $3 ); $$ = New_BinOp( TYPE($1), $1, '*', $3 ); TEST($$); } | bexpr '*' expr { $1 = New_Unary( TYPE($3), 0, $1 ); $$ = New_BinOp( TYPE($3), $1, '*', $3 ); TEST($$); } | bexpr '?' expr ':' expr { PROMOTE($3,$5); if( ! Test_Dims($3,$5) ) { yyerror("Incompatible dimensions in '?:' arguments"); YYERROR; } $$ = New_Func( 0, ifthenelse_fct, 3, $3, $5, $1, 0, 0, 0, 0 ); TEST($$); if( SIZE($3)=SIZE($4) && Test_Dims( $2, $4 ) ) { PROMOTE($2,$4); $$ = New_Func( 0, defnull_fct, 2, $2, $4, 0, 0, 0, 0, 0 ); TEST($$); } else { yyerror("Dimensions of DEFNULL arguments " "are not compatible"); YYERROR; } } else if (FSTRCMP($1,"ARCTAN2(") == 0) { if( TYPE($2) != DOUBLE ) $2 = New_Unary( DOUBLE, 0, $2 ); if( TYPE($4) != DOUBLE ) $4 = New_Unary( DOUBLE, 0, $4 ); if( Test_Dims( $2, $4 ) ) { $$ = New_Func( 0, atan2_fct, 2, $2, $4, 0, 0, 0, 0, 0 ); TEST($$); if( SIZE($2)=SIZE($4) && Test_Dims( $2, $4 ) ) { $$ = New_Func( 0, defnull_fct, 2, $2, $4, 0, 0, 0, 0, 0 ); TEST($$); } else { yyerror("Dimensions of DEFNULL arguments are not compatible"); YYERROR; } } else { yyerror("Boolean Function(expr,expr) not supported"); YYERROR; } } | BFUNCTION expr ',' expr ',' expr ')' { if( TYPE($2) != DOUBLE ) $2 = New_Unary( DOUBLE, 0, $2 ); if( TYPE($4) != DOUBLE ) $4 = New_Unary( DOUBLE, 0, $4 ); if( TYPE($6) != DOUBLE ) $6 = New_Unary( DOUBLE, 0, $6 ); if( ! (Test_Dims( $2, $4 ) && Test_Dims( $4, $6 ) ) ) { yyerror("Dimensions of NEAR arguments " "are not compatible"); YYERROR; } else { if (FSTRCMP($1,"NEAR(") == 0) { $$ = New_Func( BOOLEAN, near_fct, 3, $2, $4, $6, 0, 0, 0, 0 ); } else { yyerror("Boolean Function not supported"); YYERROR; } TEST($$); if( SIZE($$)= MAX_STRLEN) { yyerror("Combined string size exceeds " MAX_STRLEN_S " characters"); YYERROR; } $$ = New_BinOp( STRING, $1, '+', $3 ); TEST($$); SIZE($$) = SIZE($1) + SIZE($3); } | bexpr '?' sexpr ':' sexpr { int outSize; if( SIZE($1)!=1 ) { yyerror("Cannot have a vector string column"); YYERROR; } /* Since the output can be calculated now, as a constant scalar, we must precalculate the output size, in order to avoid an overflow. */ outSize = SIZE($3); if (SIZE($5) > outSize) outSize = SIZE($5); $$ = New_FuncSize( 0, ifthenelse_fct, 3, $3, $5, $1, 0, 0, 0, 0, outSize); TEST($$); if( SIZE($3) outSize) outSize = SIZE($4); $$ = New_FuncSize( 0, defnull_fct, 2, $2, $4, 0, 0, 0, 0, 0, outSize ); TEST($$); if( SIZE($4)>SIZE($2) ) SIZE($$) = SIZE($4); } else { yyerror("Function(string,string) not supported"); YYERROR; } } | FUNCTION sexpr ',' expr ',' expr ')' { if (FSTRCMP($1,"STRMID(") == 0) { int len; if( TYPE($4) != LONG || SIZE($4) != 1 || TYPE($6) != LONG || SIZE($6) != 1) { yyerror("When using STRMID(S,P,N), P and N must be integers (and not vector columns)"); YYERROR; } if (OPER($6) == CONST_OP) { /* Constant value: use that directly */ len = (gParse.Nodes[$6].value.data.lng); } else { /* Variable value: use the maximum possible (from $2) */ len = SIZE($2); } if (len <= 0 || len >= MAX_STRLEN) { yyerror("STRMID(S,P,N), N must be 1-" MAX_STRLEN_S); YYERROR; } $$ = New_FuncSize( 0, strmid_fct, 3, $2, $4,$6,0,0,0,0,len); TEST($$); } else { yyerror("Function(string,expr,expr) not supported"); YYERROR; } } ; %% /*************************************************************************/ /* Start of "New" routines which build the expression Nodal structure */ /*************************************************************************/ static int Alloc_Node( void ) { /* Use this for allocation to guarantee *Nodes */ Node *newNodePtr; /* survives on failure, making it still valid */ /* while working our way out of this error */ if( gParse.nNodes == gParse.nNodesAlloc ) { if( gParse.Nodes ) { gParse.nNodesAlloc += gParse.nNodesAlloc; newNodePtr = (Node *)realloc( gParse.Nodes, sizeof(Node)*gParse.nNodesAlloc ); } else { gParse.nNodesAlloc = 100; newNodePtr = (Node *)malloc ( sizeof(Node)*gParse.nNodesAlloc ); } if( newNodePtr ) { gParse.Nodes = newNodePtr; } else { gParse.status = MEMORY_ALLOCATION; return( -1 ); } } return ( gParse.nNodes++ ); } static void Free_Last_Node( void ) { if( gParse.nNodes ) gParse.nNodes--; } static int New_Const( int returnType, void *value, long len ) { Node *this; int n; n = Alloc_Node(); if( n>=0 ) { this = gParse.Nodes + n; this->operation = CONST_OP; /* Flag a constant */ this->DoOp = NULL; this->nSubNodes = 0; this->type = returnType; memcpy( &(this->value.data), value, len ); this->value.undef = NULL; this->value.nelem = 1; this->value.naxis = 1; this->value.naxes[0] = 1; } return(n); } static int New_Column( int ColNum ) { Node *this; int n, i; n = Alloc_Node(); if( n>=0 ) { this = gParse.Nodes + n; this->operation = -ColNum; this->DoOp = NULL; this->nSubNodes = 0; this->type = gParse.varData[ColNum].type; this->value.nelem = gParse.varData[ColNum].nelem; this->value.naxis = gParse.varData[ColNum].naxis; for( i=0; ivalue.naxes[i] = gParse.varData[ColNum].naxes[i]; } return(n); } static int New_Offset( int ColNum, int offsetNode ) { Node *this; int n, i, colNode; colNode = New_Column( ColNum ); if( colNode<0 ) return(-1); n = Alloc_Node(); if( n>=0 ) { this = gParse.Nodes + n; this->operation = '{'; this->DoOp = Do_Offset; this->nSubNodes = 2; this->SubNodes[0] = colNode; this->SubNodes[1] = offsetNode; this->type = gParse.varData[ColNum].type; this->value.nelem = gParse.varData[ColNum].nelem; this->value.naxis = gParse.varData[ColNum].naxis; for( i=0; ivalue.naxes[i] = gParse.varData[ColNum].naxes[i]; } return(n); } static int New_Unary( int returnType, int Op, int Node1 ) { Node *this, *that; int i,n; if( Node1<0 ) return(-1); that = gParse.Nodes + Node1; if( !Op ) Op = returnType; if( (Op==DOUBLE || Op==FLTCAST) && that->type==DOUBLE ) return( Node1 ); if( (Op==LONG || Op==INTCAST) && that->type==LONG ) return( Node1 ); if( (Op==BOOLEAN ) && that->type==BOOLEAN ) return( Node1 ); n = Alloc_Node(); if( n>=0 ) { this = gParse.Nodes + n; this->operation = Op; this->DoOp = Do_Unary; this->nSubNodes = 1; this->SubNodes[0] = Node1; this->type = returnType; that = gParse.Nodes + Node1; /* Reset in case .Nodes mv'd */ this->value.nelem = that->value.nelem; this->value.naxis = that->value.naxis; for( i=0; ivalue.naxis; i++ ) this->value.naxes[i] = that->value.naxes[i]; if( that->operation==CONST_OP ) this->DoOp( this ); } return( n ); } static int New_BinOp( int returnType, int Node1, int Op, int Node2 ) { Node *this,*that1,*that2; int n,i,constant; if( Node1<0 || Node2<0 ) return(-1); n = Alloc_Node(); if( n>=0 ) { this = gParse.Nodes + n; this->operation = Op; this->nSubNodes = 2; this->SubNodes[0]= Node1; this->SubNodes[1]= Node2; this->type = returnType; that1 = gParse.Nodes + Node1; that2 = gParse.Nodes + Node2; constant = (that1->operation==CONST_OP && that2->operation==CONST_OP); if( that1->type!=STRING && that1->type!=BITSTR ) if( !Test_Dims( Node1, Node2 ) ) { Free_Last_Node(); yyerror("Array sizes/dims do not match for binary operator"); return(-1); } if( that1->value.nelem == 1 ) that1 = that2; this->value.nelem = that1->value.nelem; this->value.naxis = that1->value.naxis; for( i=0; ivalue.naxis; i++ ) this->value.naxes[i] = that1->value.naxes[i]; if ( Op == ACCUM && that1->type == BITSTR ) { /* ACCUM is rank-reducing on bit strings */ this->value.nelem = 1; this->value.naxis = 1; this->value.naxes[0] = 1; } /* Both subnodes should be of same time */ switch( that1->type ) { case BITSTR: this->DoOp = Do_BinOp_bit; break; case STRING: this->DoOp = Do_BinOp_str; break; case BOOLEAN: this->DoOp = Do_BinOp_log; break; case LONG: this->DoOp = Do_BinOp_lng; break; case DOUBLE: this->DoOp = Do_BinOp_dbl; break; } if( constant ) this->DoOp( this ); } return( n ); } static int New_Func( int returnType, funcOp Op, int nNodes, int Node1, int Node2, int Node3, int Node4, int Node5, int Node6, int Node7 ) { return New_FuncSize(returnType, Op, nNodes, Node1, Node2, Node3, Node4, Node5, Node6, Node7, 0); } static int New_FuncSize( int returnType, funcOp Op, int nNodes, int Node1, int Node2, int Node3, int Node4, int Node5, int Node6, int Node7, int Size ) /* If returnType==0 , use Node1's type and vector sizes as returnType, */ /* else return a single value of type returnType */ { Node *this, *that; int i,n,constant; if( Node1<0 || Node2<0 || Node3<0 || Node4<0 || Node5<0 || Node6<0 || Node7<0 ) return(-1); n = Alloc_Node(); if( n>=0 ) { this = gParse.Nodes + n; this->operation = (int)Op; this->DoOp = Do_Func; this->nSubNodes = nNodes; this->SubNodes[0] = Node1; this->SubNodes[1] = Node2; this->SubNodes[2] = Node3; this->SubNodes[3] = Node4; this->SubNodes[4] = Node5; this->SubNodes[5] = Node6; this->SubNodes[6] = Node7; i = constant = nNodes; /* Functions with zero params are not const */ if (Op == poirnd_fct) constant = 0; /* Nor is Poisson deviate */ while( i-- ) constant = ( constant && OPER(this->SubNodes[i]) == CONST_OP ); if( returnType ) { this->type = returnType; this->value.nelem = 1; this->value.naxis = 1; this->value.naxes[0] = 1; } else { that = gParse.Nodes + Node1; this->type = that->type; this->value.nelem = that->value.nelem; this->value.naxis = that->value.naxis; for( i=0; ivalue.naxis; i++ ) this->value.naxes[i] = that->value.naxes[i]; } /* Force explicit size before evaluating */ if (Size > 0) this->value.nelem = Size; if( constant ) this->DoOp( this ); } return( n ); } static int New_Deref( int Var, int nDim, int Dim1, int Dim2, int Dim3, int Dim4, int Dim5 ) { int n, idx, constant; long elem=0; Node *this, *theVar, *theDim[MAXDIMS]; if( Var<0 || Dim1<0 || Dim2<0 || Dim3<0 || Dim4<0 || Dim5<0 ) return(-1); theVar = gParse.Nodes + Var; if( theVar->operation==CONST_OP || theVar->value.nelem==1 ) { yyerror("Cannot index a scalar value"); return(-1); } n = Alloc_Node(); if( n>=0 ) { this = gParse.Nodes + n; this->nSubNodes = nDim+1; theVar = gParse.Nodes + (this->SubNodes[0]=Var); theDim[0] = gParse.Nodes + (this->SubNodes[1]=Dim1); theDim[1] = gParse.Nodes + (this->SubNodes[2]=Dim2); theDim[2] = gParse.Nodes + (this->SubNodes[3]=Dim3); theDim[3] = gParse.Nodes + (this->SubNodes[4]=Dim4); theDim[4] = gParse.Nodes + (this->SubNodes[5]=Dim5); constant = theVar->operation==CONST_OP; for( idx=0; idxoperation==CONST_OP); for( idx=0; idxvalue.nelem>1 ) { Free_Last_Node(); yyerror("Cannot use an array as an index value"); return(-1); } else if( theDim[idx]->type!=LONG ) { Free_Last_Node(); yyerror("Index value must be an integer type"); return(-1); } this->operation = '['; this->DoOp = Do_Deref; this->type = theVar->type; if( theVar->value.naxis == nDim ) { /* All dimensions specified */ this->value.nelem = 1; this->value.naxis = 1; this->value.naxes[0] = 1; } else if( nDim==1 ) { /* Dereference only one dimension */ elem=1; this->value.naxis = theVar->value.naxis-1; for( idx=0; idxvalue.naxis; idx++ ) { elem *= ( this->value.naxes[idx] = theVar->value.naxes[idx] ); } this->value.nelem = elem; } else { Free_Last_Node(); yyerror("Must specify just one or all indices for vector"); return(-1); } if( constant ) this->DoOp( this ); } return(n); } extern int yyGetVariable( char *varName, YYSTYPE *varVal ); static int New_GTI( char *fname, int Node1, char *start, char *stop ) { fitsfile *fptr; Node *this, *that0, *that1; int type,i,n, startCol, stopCol, Node0; int hdutype, hdunum, evthdu, samefile, extvers, movetotype, tstat; char extname[100]; long nrows; double timeZeroI[2], timeZeroF[2], dt, timeSpan; char xcol[20], xexpr[20]; YYSTYPE colVal; if( Node1==-99 ) { type = yyGetVariable( "TIME", &colVal ); if( type==COLUMN ) { Node1 = New_Column( (int)colVal.lng ); } else { yyerror("Could not build TIME column for GTIFILTER"); return(-1); } } Node1 = New_Unary( DOUBLE, 0, Node1 ); Node0 = Alloc_Node(); /* This will hold the START/STOP times */ if( Node1<0 || Node0<0 ) return(-1); /* Record current HDU number in case we need to move within this file */ fptr = gParse.def_fptr; ffghdn( fptr, &evthdu ); /* Look for TIMEZERO keywords in current extension */ tstat = 0; if( ffgkyd( fptr, "TIMEZERO", timeZeroI, NULL, &tstat ) ) { tstat = 0; if( ffgkyd( fptr, "TIMEZERI", timeZeroI, NULL, &tstat ) ) { timeZeroI[0] = timeZeroF[0] = 0.0; } else if( ffgkyd( fptr, "TIMEZERF", timeZeroF, NULL, &tstat ) ) { timeZeroF[0] = 0.0; } } else { timeZeroF[0] = 0.0; } /* Resolve filename parameter */ switch( fname[0] ) { case '\0': samefile = 1; hdunum = 1; break; case '[': samefile = 1; i = 1; while( fname[i] != '\0' && fname[i] != ']' ) i++; if( fname[i] ) { fname[i] = '\0'; fname++; ffexts( fname, &hdunum, extname, &extvers, &movetotype, xcol, xexpr, &gParse.status ); if( *extname ) { ffmnhd( fptr, movetotype, extname, extvers, &gParse.status ); ffghdn( fptr, &hdunum ); } else if( hdunum ) { ffmahd( fptr, ++hdunum, &hdutype, &gParse.status ); } else if( !gParse.status ) { yyerror("Cannot use primary array for GTI filter"); return( -1 ); } } else { yyerror("File extension specifier lacks closing ']'"); return( -1 ); } break; case '+': samefile = 1; hdunum = atoi( fname ) + 1; if( hdunum>1 ) ffmahd( fptr, hdunum, &hdutype, &gParse.status ); else { yyerror("Cannot use primary array for GTI filter"); return( -1 ); } break; default: samefile = 0; if( ! ffopen( &fptr, fname, READONLY, &gParse.status ) ) ffghdn( fptr, &hdunum ); break; } if( gParse.status ) return(-1); /* If at primary, search for GTI extension */ if( hdunum==1 ) { while( 1 ) { hdunum++; if( ffmahd( fptr, hdunum, &hdutype, &gParse.status ) ) break; if( hdutype==IMAGE_HDU ) continue; tstat = 0; if( ffgkys( fptr, "EXTNAME", extname, NULL, &tstat ) ) continue; ffupch( extname ); if( strstr( extname, "GTI" ) ) break; } if( gParse.status ) { if( gParse.status==END_OF_FILE ) yyerror("GTI extension not found in this file"); return(-1); } } /* Locate START/STOP Columns */ ffgcno( fptr, CASEINSEN, start, &startCol, &gParse.status ); ffgcno( fptr, CASEINSEN, stop, &stopCol, &gParse.status ); if( gParse.status ) return(-1); /* Look for TIMEZERO keywords in GTI extension */ tstat = 0; if( ffgkyd( fptr, "TIMEZERO", timeZeroI+1, NULL, &tstat ) ) { tstat = 0; if( ffgkyd( fptr, "TIMEZERI", timeZeroI+1, NULL, &tstat ) ) { timeZeroI[1] = timeZeroF[1] = 0.0; } else if( ffgkyd( fptr, "TIMEZERF", timeZeroF+1, NULL, &tstat ) ) { timeZeroF[1] = 0.0; } } else { timeZeroF[1] = 0.0; } n = Alloc_Node(); if( n >= 0 ) { this = gParse.Nodes + n; this->nSubNodes = 2; this->SubNodes[1] = Node1; this->operation = (int)gtifilt_fct; this->DoOp = Do_GTI; this->type = BOOLEAN; that1 = gParse.Nodes + Node1; this->value.nelem = that1->value.nelem; this->value.naxis = that1->value.naxis; for( i=0; i < that1->value.naxis; i++ ) this->value.naxes[i] = that1->value.naxes[i]; /* Init START/STOP node to be treated as a "constant" */ this->SubNodes[0] = Node0; that0 = gParse.Nodes + Node0; that0->operation = CONST_OP; that0->DoOp = NULL; that0->value.data.ptr= NULL; /* Read in START/STOP times */ if( ffgkyj( fptr, "NAXIS2", &nrows, NULL, &gParse.status ) ) return(-1); that0->value.nelem = nrows; if( nrows ) { that0->value.data.dblptr = (double*)malloc( 2*nrows*sizeof(double) ); if( !that0->value.data.dblptr ) { gParse.status = MEMORY_ALLOCATION; return(-1); } ffgcvd( fptr, startCol, 1L, 1L, nrows, 0.0, that0->value.data.dblptr, &i, &gParse.status ); ffgcvd( fptr, stopCol, 1L, 1L, nrows, 0.0, that0->value.data.dblptr+nrows, &i, &gParse.status ); if( gParse.status ) { free( that0->value.data.dblptr ); return(-1); } /* Test for fully time-ordered GTI... both START && STOP */ that0->type = 1; /* Assume yes */ i = nrows; while( --i ) if( that0->value.data.dblptr[i-1] >= that0->value.data.dblptr[i] || that0->value.data.dblptr[i-1+nrows] >= that0->value.data.dblptr[i+nrows] ) { that0->type = 0; break; } /* Handle TIMEZERO offset, if any */ dt = (timeZeroI[1] - timeZeroI[0]) + (timeZeroF[1] - timeZeroF[0]); timeSpan = that0->value.data.dblptr[nrows+nrows-1] - that0->value.data.dblptr[0]; if( fabs( dt / timeSpan ) > 1e-12 ) { for( i=0; i<(nrows+nrows); i++ ) that0->value.data.dblptr[i] += dt; } } if( OPER(Node1)==CONST_OP ) this->DoOp( this ); } if( samefile ) ffmahd( fptr, evthdu, &hdutype, &gParse.status ); else ffclos( fptr, &gParse.status ); return( n ); } static int New_REG( char *fname, int NodeX, int NodeY, char *colNames ) { Node *this, *that0; int type, n, Node0; int Xcol, Ycol, tstat; WCSdata wcs; SAORegion *Rgn; char *cX, *cY; YYSTYPE colVal; if( NodeX==-99 ) { type = yyGetVariable( "X", &colVal ); if( type==COLUMN ) { NodeX = New_Column( (int)colVal.lng ); } else { yyerror("Could not build X column for REGFILTER"); return(-1); } } if( NodeY==-99 ) { type = yyGetVariable( "Y", &colVal ); if( type==COLUMN ) { NodeY = New_Column( (int)colVal.lng ); } else { yyerror("Could not build Y column for REGFILTER"); return(-1); } } NodeX = New_Unary( DOUBLE, 0, NodeX ); NodeY = New_Unary( DOUBLE, 0, NodeY ); Node0 = Alloc_Node(); /* This will hold the Region Data */ if( NodeX<0 || NodeY<0 || Node0<0 ) return(-1); if( ! (Test_Dims( NodeX, NodeY ) ) ) { yyerror("Dimensions of REGFILTER arguments are not compatible"); return (-1); } n = Alloc_Node(); if( n >= 0 ) { this = gParse.Nodes + n; this->nSubNodes = 3; this->SubNodes[0] = Node0; this->SubNodes[1] = NodeX; this->SubNodes[2] = NodeY; this->operation = (int)regfilt_fct; this->DoOp = Do_REG; this->type = BOOLEAN; this->value.nelem = 1; this->value.naxis = 1; this->value.naxes[0] = 1; Copy_Dims(n, NodeX); if( SIZE(NodeX)operation = CONST_OP; that0->DoOp = NULL; /* Identify what columns to use for WCS information */ Xcol = Ycol = 0; if( *colNames ) { /* Use the column names in this string for WCS info */ while( *colNames==' ' ) colNames++; cX = cY = colNames; while( *cY && *cY!=' ' && *cY!=',' ) cY++; if( *cY ) *(cY++) = '\0'; while( *cY==' ' ) cY++; if( !*cY ) { yyerror("Could not extract valid pair of column names from REGFILTER"); Free_Last_Node(); return( -1 ); } fits_get_colnum( gParse.def_fptr, CASEINSEN, cX, &Xcol, &gParse.status ); fits_get_colnum( gParse.def_fptr, CASEINSEN, cY, &Ycol, &gParse.status ); if( gParse.status ) { yyerror("Could not locate columns indicated for WCS info"); Free_Last_Node(); return( -1 ); } } else { /* Try to find columns used in X/Y expressions */ Xcol = Locate_Col( gParse.Nodes + NodeX ); Ycol = Locate_Col( gParse.Nodes + NodeY ); if( Xcol<0 || Ycol<0 ) { yyerror("Found multiple X/Y column references in REGFILTER"); Free_Last_Node(); return( -1 ); } } /* Now, get the WCS info, if it exists, from the indicated columns */ wcs.exists = 0; if( Xcol>0 && Ycol>0 ) { tstat = 0; ffgtcs( gParse.def_fptr, Xcol, Ycol, &wcs.xrefval, &wcs.yrefval, &wcs.xrefpix, &wcs.yrefpix, &wcs.xinc, &wcs.yinc, &wcs.rot, wcs.type, &tstat ); if( tstat==NO_WCS_KEY ) { wcs.exists = 0; } else if( tstat ) { gParse.status = tstat; Free_Last_Node(); return( -1 ); } else { wcs.exists = 1; } } /* Read in Region file */ fits_read_rgnfile( fname, &wcs, &Rgn, &gParse.status ); if( gParse.status ) { Free_Last_Node(); return( -1 ); } that0->value.data.ptr = Rgn; if( OPER(NodeX)==CONST_OP && OPER(NodeY)==CONST_OP ) this->DoOp( this ); } return( n ); } static int New_Vector( int subNode ) { Node *this, *that; int n; n = Alloc_Node(); if( n >= 0 ) { this = gParse.Nodes + n; that = gParse.Nodes + subNode; this->type = that->type; this->nSubNodes = 1; this->SubNodes[0] = subNode; this->operation = '{'; this->DoOp = Do_Vector; } return( n ); } static int Close_Vec( int vecNode ) { Node *this; int n, nelem=0; this = gParse.Nodes + vecNode; for( n=0; n < this->nSubNodes; n++ ) { if( TYPE( this->SubNodes[n] ) != this->type ) { this->SubNodes[n] = New_Unary( this->type, 0, this->SubNodes[n] ); if( this->SubNodes[n]<0 ) return(-1); } nelem += SIZE(this->SubNodes[n]); } this->value.naxis = 1; this->value.nelem = nelem; this->value.naxes[0] = nelem; return( vecNode ); } static int Locate_Col( Node *this ) /* Locate the TABLE column number of any columns in "this" calculation. */ /* Return ZERO if none found, or negative if more than 1 found. */ { Node *that; int i, col=0, newCol, nfound=0; if( this->nSubNodes==0 && this->operation<=0 && this->operation!=CONST_OP ) return gParse.colData[ - this->operation].colnum; for( i=0; inSubNodes; i++ ) { that = gParse.Nodes + this->SubNodes[i]; if( that->operation>0 ) { newCol = Locate_Col( that ); if( newCol<=0 ) { nfound += -newCol; } else { if( !nfound ) { col = newCol; nfound++; } else if( col != newCol ) { nfound++; } } } else if( that->operation!=CONST_OP ) { /* Found a Column */ newCol = gParse.colData[- that->operation].colnum; if( !nfound ) { col = newCol; nfound++; } else if( col != newCol ) { nfound++; } } } if( nfound!=1 ) return( - nfound ); else return( col ); } static int Test_Dims( int Node1, int Node2 ) { Node *that1, *that2; int valid, i; if( Node1<0 || Node2<0 ) return(0); that1 = gParse.Nodes + Node1; that2 = gParse.Nodes + Node2; if( that1->value.nelem==1 || that2->value.nelem==1 ) valid = 1; else if( that1->type==that2->type && that1->value.nelem==that2->value.nelem && that1->value.naxis==that2->value.naxis ) { valid = 1; for( i=0; ivalue.naxis; i++ ) { if( that1->value.naxes[i]!=that2->value.naxes[i] ) valid = 0; } } else valid = 0; return( valid ); } static void Copy_Dims( int Node1, int Node2 ) { Node *that1, *that2; int i; if( Node1<0 || Node2<0 ) return; that1 = gParse.Nodes + Node1; that2 = gParse.Nodes + Node2; that1->value.nelem = that2->value.nelem; that1->value.naxis = that2->value.naxis; for( i=0; ivalue.naxis; i++ ) that1->value.naxes[i] = that2->value.naxes[i]; } /********************************************************************/ /* Routines for actually evaluating the expression start here */ /********************************************************************/ void Evaluate_Parser( long firstRow, long nRows ) /***********************************************************************/ /* Reset the parser for processing another batch of data... */ /* firstRow: Row number of the first element to evaluate */ /* nRows: Number of rows to be processed */ /* Initialize each COLUMN node so that its UNDEF and DATA pointers */ /* point to the appropriate column arrays. */ /* Finally, call Evaluate_Node for final node. */ /***********************************************************************/ { int i, column; long offset, rowOffset; static int rand_initialized = 0; /* Initialize the random number generator once and only once */ if (rand_initialized == 0) { simplerng_srand( (unsigned int) time(NULL) ); rand_initialized = 1; } gParse.firstRow = firstRow; gParse.nRows = nRows; /* Reset Column Nodes' pointers to point to right data and UNDEF arrays */ rowOffset = firstRow - gParse.firstDataRow; for( i=0; i 0 || OPER(i) == CONST_OP ) continue; column = -OPER(i); offset = gParse.varData[column].nelem * rowOffset; gParse.Nodes[i].value.undef = gParse.varData[column].undef + offset; switch( gParse.Nodes[i].type ) { case BITSTR: gParse.Nodes[i].value.data.strptr = (char**)gParse.varData[column].data + rowOffset; gParse.Nodes[i].value.undef = NULL; break; case STRING: gParse.Nodes[i].value.data.strptr = (char**)gParse.varData[column].data + rowOffset; gParse.Nodes[i].value.undef = gParse.varData[column].undef + rowOffset; break; case BOOLEAN: gParse.Nodes[i].value.data.logptr = (char*)gParse.varData[column].data + offset; break; case LONG: gParse.Nodes[i].value.data.lngptr = (long*)gParse.varData[column].data + offset; break; case DOUBLE: gParse.Nodes[i].value.data.dblptr = (double*)gParse.varData[column].data + offset; break; } } Evaluate_Node( gParse.resultNode ); } static void Evaluate_Node( int thisNode ) /**********************************************************************/ /* Recursively evaluate thisNode's subNodes, then call one of the */ /* Do_ functions pointed to by thisNode's DoOp element. */ /**********************************************************************/ { Node *this; int i; if( gParse.status ) return; this = gParse.Nodes + thisNode; if( this->operation>0 ) { /* <=0 indicate constants and columns */ i = this->nSubNodes; while( i-- ) { Evaluate_Node( this->SubNodes[i] ); if( gParse.status ) return; } this->DoOp( this ); } } static void Allocate_Ptrs( Node *this ) { long elem, row, size; if( this->type==BITSTR || this->type==STRING ) { this->value.data.strptr = (char**)malloc( gParse.nRows * sizeof(char*) ); if( this->value.data.strptr ) { this->value.data.strptr[0] = (char*)malloc( gParse.nRows * (this->value.nelem+2) * sizeof(char) ); if( this->value.data.strptr[0] ) { row = 0; while( (++row)value.data.strptr[row] = this->value.data.strptr[row-1] + this->value.nelem+1; } if( this->type==STRING ) { this->value.undef = this->value.data.strptr[row-1] + this->value.nelem+1; } else { this->value.undef = NULL; /* BITSTRs don't use undef array */ } } else { gParse.status = MEMORY_ALLOCATION; free( this->value.data.strptr ); } } else { gParse.status = MEMORY_ALLOCATION; } } else { elem = this->value.nelem * gParse.nRows; switch( this->type ) { case DOUBLE: size = sizeof( double ); break; case LONG: size = sizeof( long ); break; case BOOLEAN: size = sizeof( char ); break; default: size = 1; break; } this->value.data.ptr = calloc(size+1, elem); if( this->value.data.ptr==NULL ) { gParse.status = MEMORY_ALLOCATION; } else { this->value.undef = (char *)this->value.data.ptr + elem*size; } } } static void Do_Unary( Node *this ) { Node *that; long elem; that = gParse.Nodes + this->SubNodes[0]; if( that->operation==CONST_OP ) { /* Operating on a constant! */ switch( this->operation ) { case DOUBLE: case FLTCAST: if( that->type==LONG ) this->value.data.dbl = (double)that->value.data.lng; else if( that->type==BOOLEAN ) this->value.data.dbl = ( that->value.data.log ? 1.0 : 0.0 ); break; case LONG: case INTCAST: if( that->type==DOUBLE ) this->value.data.lng = (long)that->value.data.dbl; else if( that->type==BOOLEAN ) this->value.data.lng = ( that->value.data.log ? 1L : 0L ); break; case BOOLEAN: if( that->type==DOUBLE ) this->value.data.log = ( that->value.data.dbl != 0.0 ); else if( that->type==LONG ) this->value.data.log = ( that->value.data.lng != 0L ); break; case UMINUS: if( that->type==DOUBLE ) this->value.data.dbl = - that->value.data.dbl; else if( that->type==LONG ) this->value.data.lng = - that->value.data.lng; break; case NOT: if( that->type==BOOLEAN ) this->value.data.log = ( ! that->value.data.log ); else if( that->type==BITSTR ) bitnot( this->value.data.str, that->value.data.str ); break; } this->operation = CONST_OP; } else { Allocate_Ptrs( this ); if( !gParse.status ) { if( this->type!=BITSTR ) { elem = gParse.nRows; if( this->type!=STRING ) elem *= this->value.nelem; while( elem-- ) this->value.undef[elem] = that->value.undef[elem]; } elem = gParse.nRows * this->value.nelem; switch( this->operation ) { case BOOLEAN: if( that->type==DOUBLE ) while( elem-- ) this->value.data.logptr[elem] = ( that->value.data.dblptr[elem] != 0.0 ); else if( that->type==LONG ) while( elem-- ) this->value.data.logptr[elem] = ( that->value.data.lngptr[elem] != 0L ); break; case DOUBLE: case FLTCAST: if( that->type==LONG ) while( elem-- ) this->value.data.dblptr[elem] = (double)that->value.data.lngptr[elem]; else if( that->type==BOOLEAN ) while( elem-- ) this->value.data.dblptr[elem] = ( that->value.data.logptr[elem] ? 1.0 : 0.0 ); break; case LONG: case INTCAST: if( that->type==DOUBLE ) while( elem-- ) this->value.data.lngptr[elem] = (long)that->value.data.dblptr[elem]; else if( that->type==BOOLEAN ) while( elem-- ) this->value.data.lngptr[elem] = ( that->value.data.logptr[elem] ? 1L : 0L ); break; case UMINUS: if( that->type==DOUBLE ) { while( elem-- ) this->value.data.dblptr[elem] = - that->value.data.dblptr[elem]; } else if( that->type==LONG ) { while( elem-- ) this->value.data.lngptr[elem] = - that->value.data.lngptr[elem]; } break; case NOT: if( that->type==BOOLEAN ) { while( elem-- ) this->value.data.logptr[elem] = ( ! that->value.data.logptr[elem] ); } else if( that->type==BITSTR ) { elem = gParse.nRows; while( elem-- ) bitnot( this->value.data.strptr[elem], that->value.data.strptr[elem] ); } break; } } } if( that->operation>0 ) { free( that->value.data.ptr ); } } static void Do_Offset( Node *this ) { Node *col; long fRow, nRowOverlap, nRowReload, rowOffset; long nelem, elem, offset, nRealElem; int status; col = gParse.Nodes + this->SubNodes[0]; rowOffset = gParse.Nodes[ this->SubNodes[1] ].value.data.lng; Allocate_Ptrs( this ); fRow = gParse.firstRow + rowOffset; if( this->type==STRING || this->type==BITSTR ) nRealElem = 1; else nRealElem = this->value.nelem; nelem = nRealElem; if( fRow < gParse.firstDataRow ) { /* Must fill in data at start of array */ nRowReload = gParse.firstDataRow - fRow; if( nRowReload > gParse.nRows ) nRowReload = gParse.nRows; nRowOverlap = gParse.nRows - nRowReload; offset = 0; /* NULLify any values falling out of bounds */ while( fRow<1 && nRowReload>0 ) { if( this->type == BITSTR ) { nelem = this->value.nelem; this->value.data.strptr[offset][ nelem ] = '\0'; while( nelem-- ) this->value.data.strptr[offset][nelem] = '0'; offset++; } else { while( nelem-- ) this->value.undef[offset++] = 1; } nelem = nRealElem; fRow++; nRowReload--; } } else if( fRow + gParse.nRows > gParse.firstDataRow + gParse.nDataRows ) { /* Must fill in data at end of array */ nRowReload = (fRow+gParse.nRows) - (gParse.firstDataRow+gParse.nDataRows); if( nRowReload>gParse.nRows ) { nRowReload = gParse.nRows; } else { fRow = gParse.firstDataRow + gParse.nDataRows; } nRowOverlap = gParse.nRows - nRowReload; offset = nRowOverlap * nelem; /* NULLify any values falling out of bounds */ elem = gParse.nRows * nelem; while( fRow+nRowReload>gParse.totalRows && nRowReload>0 ) { if( this->type == BITSTR ) { nelem = this->value.nelem; elem--; this->value.data.strptr[elem][ nelem ] = '\0'; while( nelem-- ) this->value.data.strptr[elem][nelem] = '0'; } else { while( nelem-- ) this->value.undef[--elem] = 1; } nelem = nRealElem; nRowReload--; } } else { nRowReload = 0; nRowOverlap = gParse.nRows; offset = 0; } if( nRowReload>0 ) { switch( this->type ) { case BITSTR: case STRING: status = (*gParse.loadData)( -col->operation, fRow, nRowReload, this->value.data.strptr+offset, this->value.undef+offset ); break; case BOOLEAN: status = (*gParse.loadData)( -col->operation, fRow, nRowReload, this->value.data.logptr+offset, this->value.undef+offset ); break; case LONG: status = (*gParse.loadData)( -col->operation, fRow, nRowReload, this->value.data.lngptr+offset, this->value.undef+offset ); break; case DOUBLE: status = (*gParse.loadData)( -col->operation, fRow, nRowReload, this->value.data.dblptr+offset, this->value.undef+offset ); break; } } /* Now copy over the overlapping region, if any */ if( nRowOverlap <= 0 ) return; if( rowOffset>0 ) elem = nRowOverlap * nelem; else elem = gParse.nRows * nelem; offset = nelem * rowOffset; while( nRowOverlap-- && !gParse.status ) { while( nelem-- && !gParse.status ) { elem--; if( this->type != BITSTR ) this->value.undef[elem] = col->value.undef[elem+offset]; switch( this->type ) { case BITSTR: strcpy( this->value.data.strptr[elem ], col->value.data.strptr[elem+offset] ); break; case STRING: strcpy( this->value.data.strptr[elem ], col->value.data.strptr[elem+offset] ); break; case BOOLEAN: this->value.data.logptr[elem] = col->value.data.logptr[elem+offset]; break; case LONG: this->value.data.lngptr[elem] = col->value.data.lngptr[elem+offset]; break; case DOUBLE: this->value.data.dblptr[elem] = col->value.data.dblptr[elem+offset]; break; } } nelem = nRealElem; } } static void Do_BinOp_bit( Node *this ) { Node *that1, *that2; char *sptr1=NULL, *sptr2=NULL; int const1, const2; long rows; that1 = gParse.Nodes + this->SubNodes[0]; that2 = gParse.Nodes + this->SubNodes[1]; const1 = ( that1->operation==CONST_OP ); const2 = ( that2->operation==CONST_OP ); sptr1 = ( const1 ? that1->value.data.str : NULL ); sptr2 = ( const2 ? that2->value.data.str : NULL ); if( const1 && const2 ) { switch( this->operation ) { case NE: this->value.data.log = !bitcmp( sptr1, sptr2 ); break; case EQ: this->value.data.log = bitcmp( sptr1, sptr2 ); break; case GT: case LT: case LTE: case GTE: this->value.data.log = bitlgte( sptr1, this->operation, sptr2 ); break; case '|': bitor( this->value.data.str, sptr1, sptr2 ); break; case '&': bitand( this->value.data.str, sptr1, sptr2 ); break; case '+': strcpy( this->value.data.str, sptr1 ); strcat( this->value.data.str, sptr2 ); break; case ACCUM: this->value.data.lng = 0; while( *sptr1 ) { if ( *sptr1 == '1' ) this->value.data.lng ++; sptr1 ++; } break; } this->operation = CONST_OP; } else { Allocate_Ptrs( this ); if( !gParse.status ) { rows = gParse.nRows; switch( this->operation ) { /* BITSTR comparisons */ case NE: case EQ: case GT: case LT: case LTE: case GTE: while( rows-- ) { if( !const1 ) sptr1 = that1->value.data.strptr[rows]; if( !const2 ) sptr2 = that2->value.data.strptr[rows]; switch( this->operation ) { case NE: this->value.data.logptr[rows] = !bitcmp( sptr1, sptr2 ); break; case EQ: this->value.data.logptr[rows] = bitcmp( sptr1, sptr2 ); break; case GT: case LT: case LTE: case GTE: this->value.data.logptr[rows] = bitlgte( sptr1, this->operation, sptr2 ); break; } this->value.undef[rows] = 0; } break; /* BITSTR AND/ORs ... no UNDEFS in or out */ case '|': case '&': case '+': while( rows-- ) { if( !const1 ) sptr1 = that1->value.data.strptr[rows]; if( !const2 ) sptr2 = that2->value.data.strptr[rows]; if( this->operation=='|' ) bitor( this->value.data.strptr[rows], sptr1, sptr2 ); else if( this->operation=='&' ) bitand( this->value.data.strptr[rows], sptr1, sptr2 ); else { strcpy( this->value.data.strptr[rows], sptr1 ); strcat( this->value.data.strptr[rows], sptr2 ); } } break; /* Accumulate 1 bits */ case ACCUM: { long i, previous, curr; previous = that2->value.data.lng; /* Cumulative sum of this chunk */ for (i=0; ivalue.data.strptr[i]; for (curr = 0; *sptr1; sptr1 ++) { if ( *sptr1 == '1' ) curr ++; } previous += curr; this->value.data.lngptr[i] = previous; this->value.undef[i] = 0; } /* Store final cumulant for next pass */ that2->value.data.lng = previous; } } } } if( that1->operation>0 ) { free( that1->value.data.strptr[0] ); free( that1->value.data.strptr ); } if( that2->operation>0 ) { free( that2->value.data.strptr[0] ); free( that2->value.data.strptr ); } } static void Do_BinOp_str( Node *this ) { Node *that1, *that2; char *sptr1, *sptr2, null1=0, null2=0; int const1, const2, val; long rows; that1 = gParse.Nodes + this->SubNodes[0]; that2 = gParse.Nodes + this->SubNodes[1]; const1 = ( that1->operation==CONST_OP ); const2 = ( that2->operation==CONST_OP ); sptr1 = ( const1 ? that1->value.data.str : NULL ); sptr2 = ( const2 ? that2->value.data.str : NULL ); if( const1 && const2 ) { /* Result is a constant */ switch( this->operation ) { /* Compare Strings */ case NE: case EQ: val = ( FSTRCMP( sptr1, sptr2 ) == 0 ); this->value.data.log = ( this->operation==EQ ? val : !val ); break; case GT: this->value.data.log = ( FSTRCMP( sptr1, sptr2 ) > 0 ); break; case LT: this->value.data.log = ( FSTRCMP( sptr1, sptr2 ) < 0 ); break; case GTE: this->value.data.log = ( FSTRCMP( sptr1, sptr2 ) >= 0 ); break; case LTE: this->value.data.log = ( FSTRCMP( sptr1, sptr2 ) <= 0 ); break; /* Concat Strings */ case '+': strcpy( this->value.data.str, sptr1 ); strcat( this->value.data.str, sptr2 ); break; } this->operation = CONST_OP; } else { /* Not a constant */ Allocate_Ptrs( this ); if( !gParse.status ) { rows = gParse.nRows; switch( this->operation ) { /* Compare Strings */ case NE: case EQ: while( rows-- ) { if( !const1 ) null1 = that1->value.undef[rows]; if( !const2 ) null2 = that2->value.undef[rows]; this->value.undef[rows] = (null1 || null2); if( ! this->value.undef[rows] ) { if( !const1 ) sptr1 = that1->value.data.strptr[rows]; if( !const2 ) sptr2 = that2->value.data.strptr[rows]; val = ( FSTRCMP( sptr1, sptr2 ) == 0 ); this->value.data.logptr[rows] = ( this->operation==EQ ? val : !val ); } } break; case GT: case LT: while( rows-- ) { if( !const1 ) null1 = that1->value.undef[rows]; if( !const2 ) null2 = that2->value.undef[rows]; this->value.undef[rows] = (null1 || null2); if( ! this->value.undef[rows] ) { if( !const1 ) sptr1 = that1->value.data.strptr[rows]; if( !const2 ) sptr2 = that2->value.data.strptr[rows]; val = ( FSTRCMP( sptr1, sptr2 ) ); this->value.data.logptr[rows] = ( this->operation==GT ? val>0 : val<0 ); } } break; case GTE: case LTE: while( rows-- ) { if( !const1 ) null1 = that1->value.undef[rows]; if( !const2 ) null2 = that2->value.undef[rows]; this->value.undef[rows] = (null1 || null2); if( ! this->value.undef[rows] ) { if( !const1 ) sptr1 = that1->value.data.strptr[rows]; if( !const2 ) sptr2 = that2->value.data.strptr[rows]; val = ( FSTRCMP( sptr1, sptr2 ) ); this->value.data.logptr[rows] = ( this->operation==GTE ? val>=0 : val<=0 ); } } break; /* Concat Strings */ case '+': while( rows-- ) { if( !const1 ) null1 = that1->value.undef[rows]; if( !const2 ) null2 = that2->value.undef[rows]; this->value.undef[rows] = (null1 || null2); if( ! this->value.undef[rows] ) { if( !const1 ) sptr1 = that1->value.data.strptr[rows]; if( !const2 ) sptr2 = that2->value.data.strptr[rows]; strcpy( this->value.data.strptr[rows], sptr1 ); strcat( this->value.data.strptr[rows], sptr2 ); } } break; } } } if( that1->operation>0 ) { free( that1->value.data.strptr[0] ); free( that1->value.data.strptr ); } if( that2->operation>0 ) { free( that2->value.data.strptr[0] ); free( that2->value.data.strptr ); } } static void Do_BinOp_log( Node *this ) { Node *that1, *that2; int vector1, vector2; char val1=0, val2=0, null1=0, null2=0; long rows, nelem, elem; that1 = gParse.Nodes + this->SubNodes[0]; that2 = gParse.Nodes + this->SubNodes[1]; vector1 = ( that1->operation!=CONST_OP ); if( vector1 ) vector1 = that1->value.nelem; else { val1 = that1->value.data.log; } vector2 = ( that2->operation!=CONST_OP ); if( vector2 ) vector2 = that2->value.nelem; else { val2 = that2->value.data.log; } if( !vector1 && !vector2 ) { /* Result is a constant */ switch( this->operation ) { case OR: this->value.data.log = (val1 || val2); break; case AND: this->value.data.log = (val1 && val2); break; case EQ: this->value.data.log = ( (val1 && val2) || (!val1 && !val2) ); break; case NE: this->value.data.log = ( (val1 && !val2) || (!val1 && val2) ); break; case ACCUM: this->value.data.lng = val1; break; } this->operation=CONST_OP; } else if (this->operation == ACCUM) { long i, previous, curr; rows = gParse.nRows; nelem = this->value.nelem; elem = this->value.nelem * rows; Allocate_Ptrs( this ); if( !gParse.status ) { previous = that2->value.data.lng; /* Cumulative sum of this chunk */ for (i=0; ivalue.undef[i]) { curr = that1->value.data.logptr[i]; previous += curr; } this->value.data.lngptr[i] = previous; this->value.undef[i] = 0; } /* Store final cumulant for next pass */ that2->value.data.lng = previous; } } else { rows = gParse.nRows; nelem = this->value.nelem; elem = this->value.nelem * rows; Allocate_Ptrs( this ); if( !gParse.status ) { if (this->operation == ACCUM) { long i, previous, curr; previous = that2->value.data.lng; /* Cumulative sum of this chunk */ for (i=0; ivalue.undef[i]) { curr = that1->value.data.logptr[i]; previous += curr; } this->value.data.lngptr[i] = previous; this->value.undef[i] = 0; } /* Store final cumulant for next pass */ that2->value.data.lng = previous; } while( rows-- ) { while( nelem-- ) { elem--; if( vector1>1 ) { val1 = that1->value.data.logptr[elem]; null1 = that1->value.undef[elem]; } else if( vector1 ) { val1 = that1->value.data.logptr[rows]; null1 = that1->value.undef[rows]; } if( vector2>1 ) { val2 = that2->value.data.logptr[elem]; null2 = that2->value.undef[elem]; } else if( vector2 ) { val2 = that2->value.data.logptr[rows]; null2 = that2->value.undef[rows]; } this->value.undef[elem] = (null1 || null2); switch( this->operation ) { case OR: /* This is more complicated than others to suppress UNDEFs */ /* in those cases where the other argument is DEF && TRUE */ if( !null1 && !null2 ) { this->value.data.logptr[elem] = (val1 || val2); } else if( (null1 && !null2 && val2) || ( !null1 && null2 && val1 ) ) { this->value.data.logptr[elem] = 1; this->value.undef[elem] = 0; } break; case AND: /* This is more complicated than others to suppress UNDEFs */ /* in those cases where the other argument is DEF && FALSE */ if( !null1 && !null2 ) { this->value.data.logptr[elem] = (val1 && val2); } else if( (null1 && !null2 && !val2) || ( !null1 && null2 && !val1 ) ) { this->value.data.logptr[elem] = 0; this->value.undef[elem] = 0; } break; case EQ: this->value.data.logptr[elem] = ( (val1 && val2) || (!val1 && !val2) ); break; case NE: this->value.data.logptr[elem] = ( (val1 && !val2) || (!val1 && val2) ); break; } } nelem = this->value.nelem; } } } if( that1->operation>0 ) { free( that1->value.data.ptr ); } if( that2->operation>0 ) { free( that2->value.data.ptr ); } } static void Do_BinOp_lng( Node *this ) { Node *that1, *that2; int vector1, vector2; long val1=0, val2=0; char null1=0, null2=0; long rows, nelem, elem; that1 = gParse.Nodes + this->SubNodes[0]; that2 = gParse.Nodes + this->SubNodes[1]; vector1 = ( that1->operation!=CONST_OP ); if( vector1 ) vector1 = that1->value.nelem; else { val1 = that1->value.data.lng; } vector2 = ( that2->operation!=CONST_OP ); if( vector2 ) vector2 = that2->value.nelem; else { val2 = that2->value.data.lng; } if( !vector1 && !vector2 ) { /* Result is a constant */ switch( this->operation ) { case '~': /* Treat as == for LONGS */ case EQ: this->value.data.log = (val1 == val2); break; case NE: this->value.data.log = (val1 != val2); break; case GT: this->value.data.log = (val1 > val2); break; case LT: this->value.data.log = (val1 < val2); break; case LTE: this->value.data.log = (val1 <= val2); break; case GTE: this->value.data.log = (val1 >= val2); break; case '+': this->value.data.lng = (val1 + val2); break; case '-': this->value.data.lng = (val1 - val2); break; case '*': this->value.data.lng = (val1 * val2); break; case '%': if( val2 ) this->value.data.lng = (val1 % val2); else yyerror("Divide by Zero"); break; case '/': if( val2 ) this->value.data.lng = (val1 / val2); else yyerror("Divide by Zero"); break; case POWER: this->value.data.lng = (long)pow((double)val1,(double)val2); break; case ACCUM: this->value.data.lng = val1; break; case DIFF: this->value.data.lng = 0; break; } this->operation=CONST_OP; } else if ((this->operation == ACCUM) || (this->operation == DIFF)) { long i, previous, curr; long undef; rows = gParse.nRows; nelem = this->value.nelem; elem = this->value.nelem * rows; Allocate_Ptrs( this ); if( !gParse.status ) { previous = that2->value.data.lng; undef = (long) that2->value.undef; if (this->operation == ACCUM) { /* Cumulative sum of this chunk */ for (i=0; ivalue.undef[i]) { curr = that1->value.data.lngptr[i]; previous += curr; } this->value.data.lngptr[i] = previous; this->value.undef[i] = 0; } } else { /* Sequential difference for this chunk */ for (i=0; ivalue.data.lngptr[i]; if (that1->value.undef[i] || undef) { /* Either this, or previous, value was undefined */ this->value.data.lngptr[i] = 0; this->value.undef[i] = 1; } else { /* Both defined, we are okay! */ this->value.data.lngptr[i] = curr - previous; this->value.undef[i] = 0; } previous = curr; undef = that1->value.undef[i]; } } /* Store final cumulant for next pass */ that2->value.data.lng = previous; that2->value.undef = (char *) undef; /* XXX evil, but no harm here */ } } else { rows = gParse.nRows; nelem = this->value.nelem; elem = this->value.nelem * rows; Allocate_Ptrs( this ); while( rows-- && !gParse.status ) { while( nelem-- && !gParse.status ) { elem--; if( vector1>1 ) { val1 = that1->value.data.lngptr[elem]; null1 = that1->value.undef[elem]; } else if( vector1 ) { val1 = that1->value.data.lngptr[rows]; null1 = that1->value.undef[rows]; } if( vector2>1 ) { val2 = that2->value.data.lngptr[elem]; null2 = that2->value.undef[elem]; } else if( vector2 ) { val2 = that2->value.data.lngptr[rows]; null2 = that2->value.undef[rows]; } this->value.undef[elem] = (null1 || null2); switch( this->operation ) { case '~': /* Treat as == for LONGS */ case EQ: this->value.data.logptr[elem] = (val1 == val2); break; case NE: this->value.data.logptr[elem] = (val1 != val2); break; case GT: this->value.data.logptr[elem] = (val1 > val2); break; case LT: this->value.data.logptr[elem] = (val1 < val2); break; case LTE: this->value.data.logptr[elem] = (val1 <= val2); break; case GTE: this->value.data.logptr[elem] = (val1 >= val2); break; case '+': this->value.data.lngptr[elem] = (val1 + val2); break; case '-': this->value.data.lngptr[elem] = (val1 - val2); break; case '*': this->value.data.lngptr[elem] = (val1 * val2); break; case '%': if( val2 ) this->value.data.lngptr[elem] = (val1 % val2); else { this->value.data.lngptr[elem] = 0; this->value.undef[elem] = 1; } break; case '/': if( val2 ) this->value.data.lngptr[elem] = (val1 / val2); else { this->value.data.lngptr[elem] = 0; this->value.undef[elem] = 1; } break; case POWER: this->value.data.lngptr[elem] = (long)pow((double)val1,(double)val2); break; } } nelem = this->value.nelem; } } if( that1->operation>0 ) { free( that1->value.data.ptr ); } if( that2->operation>0 ) { free( that2->value.data.ptr ); } } static void Do_BinOp_dbl( Node *this ) { Node *that1, *that2; int vector1, vector2; double val1=0.0, val2=0.0; char null1=0, null2=0; long rows, nelem, elem; that1 = gParse.Nodes + this->SubNodes[0]; that2 = gParse.Nodes + this->SubNodes[1]; vector1 = ( that1->operation!=CONST_OP ); if( vector1 ) vector1 = that1->value.nelem; else { val1 = that1->value.data.dbl; } vector2 = ( that2->operation!=CONST_OP ); if( vector2 ) vector2 = that2->value.nelem; else { val2 = that2->value.data.dbl; } if( !vector1 && !vector2 ) { /* Result is a constant */ switch( this->operation ) { case '~': this->value.data.log = ( fabs(val1-val2) < APPROX ); break; case EQ: this->value.data.log = (val1 == val2); break; case NE: this->value.data.log = (val1 != val2); break; case GT: this->value.data.log = (val1 > val2); break; case LT: this->value.data.log = (val1 < val2); break; case LTE: this->value.data.log = (val1 <= val2); break; case GTE: this->value.data.log = (val1 >= val2); break; case '+': this->value.data.dbl = (val1 + val2); break; case '-': this->value.data.dbl = (val1 - val2); break; case '*': this->value.data.dbl = (val1 * val2); break; case '%': if( val2 ) this->value.data.dbl = val1 - val2*((int)(val1/val2)); else yyerror("Divide by Zero"); break; case '/': if( val2 ) this->value.data.dbl = (val1 / val2); else yyerror("Divide by Zero"); break; case POWER: this->value.data.dbl = (double)pow(val1,val2); break; case ACCUM: this->value.data.dbl = val1; break; case DIFF: this->value.data.dbl = 0; break; } this->operation=CONST_OP; } else if ((this->operation == ACCUM) || (this->operation == DIFF)) { long i; long undef; double previous, curr; rows = gParse.nRows; nelem = this->value.nelem; elem = this->value.nelem * rows; Allocate_Ptrs( this ); if( !gParse.status ) { previous = that2->value.data.dbl; undef = (long) that2->value.undef; if (this->operation == ACCUM) { /* Cumulative sum of this chunk */ for (i=0; ivalue.undef[i]) { curr = that1->value.data.dblptr[i]; previous += curr; } this->value.data.dblptr[i] = previous; this->value.undef[i] = 0; } } else { /* Sequential difference for this chunk */ for (i=0; ivalue.data.dblptr[i]; if (that1->value.undef[i] || undef) { /* Either this, or previous, value was undefined */ this->value.data.dblptr[i] = 0; this->value.undef[i] = 1; } else { /* Both defined, we are okay! */ this->value.data.dblptr[i] = curr - previous; this->value.undef[i] = 0; } previous = curr; undef = that1->value.undef[i]; } } /* Store final cumulant for next pass */ that2->value.data.dbl = previous; that2->value.undef = (char *) undef; /* XXX evil, but no harm here */ } } else { rows = gParse.nRows; nelem = this->value.nelem; elem = this->value.nelem * rows; Allocate_Ptrs( this ); while( rows-- && !gParse.status ) { while( nelem-- && !gParse.status ) { elem--; if( vector1>1 ) { val1 = that1->value.data.dblptr[elem]; null1 = that1->value.undef[elem]; } else if( vector1 ) { val1 = that1->value.data.dblptr[rows]; null1 = that1->value.undef[rows]; } if( vector2>1 ) { val2 = that2->value.data.dblptr[elem]; null2 = that2->value.undef[elem]; } else if( vector2 ) { val2 = that2->value.data.dblptr[rows]; null2 = that2->value.undef[rows]; } this->value.undef[elem] = (null1 || null2); switch( this->operation ) { case '~': this->value.data.logptr[elem] = ( fabs(val1-val2) < APPROX ); break; case EQ: this->value.data.logptr[elem] = (val1 == val2); break; case NE: this->value.data.logptr[elem] = (val1 != val2); break; case GT: this->value.data.logptr[elem] = (val1 > val2); break; case LT: this->value.data.logptr[elem] = (val1 < val2); break; case LTE: this->value.data.logptr[elem] = (val1 <= val2); break; case GTE: this->value.data.logptr[elem] = (val1 >= val2); break; case '+': this->value.data.dblptr[elem] = (val1 + val2); break; case '-': this->value.data.dblptr[elem] = (val1 - val2); break; case '*': this->value.data.dblptr[elem] = (val1 * val2); break; case '%': if( val2 ) this->value.data.dblptr[elem] = val1 - val2*((int)(val1/val2)); else { this->value.data.dblptr[elem] = 0.0; this->value.undef[elem] = 1; } break; case '/': if( val2 ) this->value.data.dblptr[elem] = (val1 / val2); else { this->value.data.dblptr[elem] = 0.0; this->value.undef[elem] = 1; } break; case POWER: this->value.data.dblptr[elem] = (double)pow(val1,val2); break; } } nelem = this->value.nelem; } } if( that1->operation>0 ) { free( that1->value.data.ptr ); } if( that2->operation>0 ) { free( that2->value.data.ptr ); } } /* * This Quickselect routine is based on the algorithm described in * "Numerical recipes in C", Second Edition, * Cambridge University Press, 1992, Section 8.5, ISBN 0-521-43108-5 * This code by Nicolas Devillard - 1998. Public domain. * http://ndevilla.free.fr/median/median/src/quickselect.c */ #define ELEM_SWAP(a,b) { register long t=(a);(a)=(b);(b)=t; } /* * qselect_median_lng - select the median value of a long array * * This routine selects the median value of the long integer array * arr[]. If there are an even number of elements, the "lower median" * is selected. * * The array arr[] is scrambled, so users must operate on a scratch * array if they wish the values to be preserved. * * long arr[] - array of values * int n - number of elements in arr * * RETURNS: the lower median value of arr[] * */ long qselect_median_lng(long arr[], int n) { int low, high ; int median; int middle, ll, hh; low = 0 ; high = n-1 ; median = (low + high) / 2; for (;;) { if (high <= low) { /* One element only */ return arr[median]; } if (high == low + 1) { /* Two elements only */ if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]) ; return arr[median]; } /* Find median of low, middle and high items; swap into position low */ middle = (low + high) / 2; if (arr[middle] > arr[high]) ELEM_SWAP(arr[middle], arr[high]) ; if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]) ; if (arr[middle] > arr[low]) ELEM_SWAP(arr[middle], arr[low]) ; /* Swap low item (now in position middle) into position (low+1) */ ELEM_SWAP(arr[middle], arr[low+1]) ; /* Nibble from each end towards middle, swapping items when stuck */ ll = low + 1; hh = high; for (;;) { do ll++; while (arr[low] > arr[ll]) ; do hh--; while (arr[hh] > arr[low]) ; if (hh < ll) break; ELEM_SWAP(arr[ll], arr[hh]) ; } /* Swap middle item (in position low) back into correct position */ ELEM_SWAP(arr[low], arr[hh]) ; /* Re-set active partition */ if (hh <= median) low = ll; if (hh >= median) high = hh - 1; } } #undef ELEM_SWAP #define ELEM_SWAP(a,b) { register double t=(a);(a)=(b);(b)=t; } /* * qselect_median_dbl - select the median value of a double array * * This routine selects the median value of the double array * arr[]. If there are an even number of elements, the "lower median" * is selected. * * The array arr[] is scrambled, so users must operate on a scratch * array if they wish the values to be preserved. * * double arr[] - array of values * int n - number of elements in arr * * RETURNS: the lower median value of arr[] * */ double qselect_median_dbl(double arr[], int n) { int low, high ; int median; int middle, ll, hh; low = 0 ; high = n-1 ; median = (low + high) / 2; for (;;) { if (high <= low) { /* One element only */ return arr[median] ; } if (high == low + 1) { /* Two elements only */ if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]) ; return arr[median] ; } /* Find median of low, middle and high items; swap into position low */ middle = (low + high) / 2; if (arr[middle] > arr[high]) ELEM_SWAP(arr[middle], arr[high]) ; if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]) ; if (arr[middle] > arr[low]) ELEM_SWAP(arr[middle], arr[low]) ; /* Swap low item (now in position middle) into position (low+1) */ ELEM_SWAP(arr[middle], arr[low+1]) ; /* Nibble from each end towards middle, swapping items when stuck */ ll = low + 1; hh = high; for (;;) { do ll++; while (arr[low] > arr[ll]) ; do hh--; while (arr[hh] > arr[low]) ; if (hh < ll) break; ELEM_SWAP(arr[ll], arr[hh]) ; } /* Swap middle item (in position low) back into correct position */ ELEM_SWAP(arr[low], arr[hh]) ; /* Re-set active partition */ if (hh <= median) low = ll; if (hh >= median) high = hh - 1; } } #undef ELEM_SWAP /* * angsep_calc - compute angular separation between celestial coordinates * * This routine computes the angular separation between to coordinates * on the celestial sphere (i.e. RA and Dec). Note that all units are * in DEGREES, unlike the other trig functions in the calculator. * * double ra1, dec1 - RA and Dec of the first position in degrees * double ra2, dec2 - RA and Dec of the second position in degrees * * RETURNS: (double) angular separation in degrees * */ double angsep_calc(double ra1, double dec1, double ra2, double dec2) { /* double cd; */ static double deg = 0; double a, sdec, sra; if (deg == 0) deg = ((double)4)*atan((double)1)/((double)180); /* deg = 1.0; **** UNCOMMENT IF YOU WANT RADIANS */ /* The algorithm is the law of Haversines. This algorithm is stable even when the points are close together. The normal Law of Cosines fails for angles around 0.1 arcsec. */ sra = sin( (ra2 - ra1)*deg / 2 ); sdec = sin( (dec2 - dec1)*deg / 2); a = sdec*sdec + cos(dec1*deg)*cos(dec2*deg)*sra*sra; /* Sanity checking to avoid a range error in the sqrt()'s below */ if (a < 0) { a = 0; } if (a > 1) { a = 1; } return 2.0*atan2(sqrt(a), sqrt(1.0 - a)) / deg; } static void Do_Func( Node *this ) { Node *theParams[MAXSUBS]; int vector[MAXSUBS], allConst; lval pVals[MAXSUBS]; char pNull[MAXSUBS]; long ival; double dval; int i, valInit; long row, elem, nelem; i = this->nSubNodes; allConst = 1; while( i-- ) { theParams[i] = gParse.Nodes + this->SubNodes[i]; vector[i] = ( theParams[i]->operation!=CONST_OP ); if( vector[i] ) { allConst = 0; vector[i] = theParams[i]->value.nelem; } else { if( theParams[i]->type==DOUBLE ) { pVals[i].data.dbl = theParams[i]->value.data.dbl; } else if( theParams[i]->type==LONG ) { pVals[i].data.lng = theParams[i]->value.data.lng; } else if( theParams[i]->type==BOOLEAN ) { pVals[i].data.log = theParams[i]->value.data.log; } else strcpy(pVals[i].data.str, theParams[i]->value.data.str); pNull[i] = 0; } } if( this->nSubNodes==0 ) allConst = 0; /* These do produce scalars */ /* Random numbers are *never* constant !! */ if( this->operation == poirnd_fct ) allConst = 0; if( this->operation == gasrnd_fct ) allConst = 0; if( this->operation == rnd_fct ) allConst = 0; if( allConst ) { switch( this->operation ) { /* Non-Trig single-argument functions */ case sum_fct: if( theParams[0]->type==BOOLEAN ) this->value.data.lng = ( pVals[0].data.log ? 1 : 0 ); else if( theParams[0]->type==LONG ) this->value.data.lng = pVals[0].data.lng; else if( theParams[0]->type==DOUBLE ) this->value.data.dbl = pVals[0].data.dbl; else if( theParams[0]->type==BITSTR ) strcpy(this->value.data.str, pVals[0].data.str); break; case average_fct: if( theParams[0]->type==LONG ) this->value.data.dbl = pVals[0].data.lng; else if( theParams[0]->type==DOUBLE ) this->value.data.dbl = pVals[0].data.dbl; break; case stddev_fct: this->value.data.dbl = 0; /* Standard deviation of a constant = 0 */ break; case median_fct: if( theParams[0]->type==BOOLEAN ) this->value.data.lng = ( pVals[0].data.log ? 1 : 0 ); else if( theParams[0]->type==LONG ) this->value.data.lng = pVals[0].data.lng; else this->value.data.dbl = pVals[0].data.dbl; break; case poirnd_fct: if( theParams[0]->type==DOUBLE ) this->value.data.lng = simplerng_getpoisson(pVals[0].data.dbl); else this->value.data.lng = simplerng_getpoisson(pVals[0].data.lng); break; case abs_fct: if( theParams[0]->type==DOUBLE ) { dval = pVals[0].data.dbl; this->value.data.dbl = (dval>0.0 ? dval : -dval); } else { ival = pVals[0].data.lng; this->value.data.lng = (ival> 0 ? ival : -ival); } break; /* Special Null-Handling Functions */ case nonnull_fct: this->value.data.lng = 1; /* Constants are always 1-element and defined */ break; case isnull_fct: /* Constants are always defined */ this->value.data.log = 0; break; case defnull_fct: if( this->type==BOOLEAN ) this->value.data.log = pVals[0].data.log; else if( this->type==LONG ) this->value.data.lng = pVals[0].data.lng; else if( this->type==DOUBLE ) this->value.data.dbl = pVals[0].data.dbl; else if( this->type==STRING ) strcpy(this->value.data.str,pVals[0].data.str); break; /* Math functions with 1 double argument */ case sin_fct: this->value.data.dbl = sin( pVals[0].data.dbl ); break; case cos_fct: this->value.data.dbl = cos( pVals[0].data.dbl ); break; case tan_fct: this->value.data.dbl = tan( pVals[0].data.dbl ); break; case asin_fct: dval = pVals[0].data.dbl; if( dval<-1.0 || dval>1.0 ) yyerror("Out of range argument to arcsin"); else this->value.data.dbl = asin( dval ); break; case acos_fct: dval = pVals[0].data.dbl; if( dval<-1.0 || dval>1.0 ) yyerror("Out of range argument to arccos"); else this->value.data.dbl = acos( dval ); break; case atan_fct: this->value.data.dbl = atan( pVals[0].data.dbl ); break; case sinh_fct: this->value.data.dbl = sinh( pVals[0].data.dbl ); break; case cosh_fct: this->value.data.dbl = cosh( pVals[0].data.dbl ); break; case tanh_fct: this->value.data.dbl = tanh( pVals[0].data.dbl ); break; case exp_fct: this->value.data.dbl = exp( pVals[0].data.dbl ); break; case log_fct: dval = pVals[0].data.dbl; if( dval<=0.0 ) yyerror("Out of range argument to log"); else this->value.data.dbl = log( dval ); break; case log10_fct: dval = pVals[0].data.dbl; if( dval<=0.0 ) yyerror("Out of range argument to log10"); else this->value.data.dbl = log10( dval ); break; case sqrt_fct: dval = pVals[0].data.dbl; if( dval<0.0 ) yyerror("Out of range argument to sqrt"); else this->value.data.dbl = sqrt( dval ); break; case ceil_fct: this->value.data.dbl = ceil( pVals[0].data.dbl ); break; case floor_fct: this->value.data.dbl = floor( pVals[0].data.dbl ); break; case round_fct: this->value.data.dbl = floor( pVals[0].data.dbl + 0.5 ); break; /* Two-argument Trig Functions */ case atan2_fct: this->value.data.dbl = atan2( pVals[0].data.dbl, pVals[1].data.dbl ); break; /* Four-argument ANGSEP function */ case angsep_fct: this->value.data.dbl = angsep_calc(pVals[0].data.dbl, pVals[1].data.dbl, pVals[2].data.dbl, pVals[3].data.dbl); /* Min/Max functions taking 1 or 2 arguments */ case min1_fct: /* No constant vectors! */ if( this->type == DOUBLE ) this->value.data.dbl = pVals[0].data.dbl; else if( this->type == LONG ) this->value.data.lng = pVals[0].data.lng; else if( this->type == BITSTR ) strcpy(this->value.data.str, pVals[0].data.str); break; case min2_fct: if( this->type == DOUBLE ) this->value.data.dbl = minvalue( pVals[0].data.dbl, pVals[1].data.dbl ); else if( this->type == LONG ) this->value.data.lng = minvalue( pVals[0].data.lng, pVals[1].data.lng ); break; case max1_fct: /* No constant vectors! */ if( this->type == DOUBLE ) this->value.data.dbl = pVals[0].data.dbl; else if( this->type == LONG ) this->value.data.lng = pVals[0].data.lng; else if( this->type == BITSTR ) strcpy(this->value.data.str, pVals[0].data.str); break; case max2_fct: if( this->type == DOUBLE ) this->value.data.dbl = maxvalue( pVals[0].data.dbl, pVals[1].data.dbl ); else if( this->type == LONG ) this->value.data.lng = maxvalue( pVals[0].data.lng, pVals[1].data.lng ); break; /* Boolean SAO region Functions... scalar or vector dbls */ case near_fct: this->value.data.log = bnear( pVals[0].data.dbl, pVals[1].data.dbl, pVals[2].data.dbl ); break; case circle_fct: this->value.data.log = circle( pVals[0].data.dbl, pVals[1].data.dbl, pVals[2].data.dbl, pVals[3].data.dbl, pVals[4].data.dbl ); break; case box_fct: this->value.data.log = saobox( pVals[0].data.dbl, pVals[1].data.dbl, pVals[2].data.dbl, pVals[3].data.dbl, pVals[4].data.dbl, pVals[5].data.dbl, pVals[6].data.dbl ); break; case elps_fct: this->value.data.log = ellipse( pVals[0].data.dbl, pVals[1].data.dbl, pVals[2].data.dbl, pVals[3].data.dbl, pVals[4].data.dbl, pVals[5].data.dbl, pVals[6].data.dbl ); break; /* C Conditional expression: bool ? expr : expr */ case ifthenelse_fct: switch( this->type ) { case BOOLEAN: this->value.data.log = ( pVals[2].data.log ? pVals[0].data.log : pVals[1].data.log ); break; case LONG: this->value.data.lng = ( pVals[2].data.log ? pVals[0].data.lng : pVals[1].data.lng ); break; case DOUBLE: this->value.data.dbl = ( pVals[2].data.log ? pVals[0].data.dbl : pVals[1].data.dbl ); break; case STRING: strcpy(this->value.data.str, ( pVals[2].data.log ? pVals[0].data.str : pVals[1].data.str ) ); break; } break; /* String functions */ case strmid_fct: cstrmid(this->value.data.str, this->value.nelem, pVals[0].data.str, pVals[0].nelem, pVals[1].data.lng); break; case strpos_fct: { char *res = strstr(pVals[0].data.str, pVals[1].data.str); if (res == NULL) { this->value.data.lng = 0; } else { this->value.data.lng = (res - pVals[0].data.str) + 1; } break; } } this->operation = CONST_OP; } else { Allocate_Ptrs( this ); row = gParse.nRows; elem = row * this->value.nelem; if( !gParse.status ) { switch( this->operation ) { /* Special functions with no arguments */ case row_fct: while( row-- ) { this->value.data.lngptr[row] = gParse.firstRow + row; this->value.undef[row] = 0; } break; case null_fct: if( this->type==LONG ) { while( row-- ) { this->value.data.lngptr[row] = 0; this->value.undef[row] = 1; } } else if( this->type==STRING ) { while( row-- ) { this->value.data.strptr[row][0] = '\0'; this->value.undef[row] = 1; } } break; case rnd_fct: while( elem-- ) { this->value.data.dblptr[elem] = simplerng_getuniform(); this->value.undef[elem] = 0; } break; case gasrnd_fct: while( elem-- ) { this->value.data.dblptr[elem] = simplerng_getnorm(); this->value.undef[elem] = 0; } break; case poirnd_fct: if( theParams[0]->type==DOUBLE ) { if (theParams[0]->operation == CONST_OP) { while( elem-- ) { this->value.undef[elem] = (pVals[0].data.dbl < 0); if (! this->value.undef[elem]) { this->value.data.lngptr[elem] = simplerng_getpoisson(pVals[0].data.dbl); } } } else { while( elem-- ) { this->value.undef[elem] = theParams[0]->value.undef[elem]; if (theParams[0]->value.data.dblptr[elem] < 0) this->value.undef[elem] = 1; if (! this->value.undef[elem]) { this->value.data.lngptr[elem] = simplerng_getpoisson(theParams[0]->value.data.dblptr[elem]); } } /* while */ } /* ! CONST_OP */ } else { /* LONG */ if (theParams[0]->operation == CONST_OP) { while( elem-- ) { this->value.undef[elem] = (pVals[0].data.lng < 0); if (! this->value.undef[elem]) { this->value.data.lngptr[elem] = simplerng_getpoisson(pVals[0].data.lng); } } } else { while( elem-- ) { this->value.undef[elem] = theParams[0]->value.undef[elem]; if (theParams[0]->value.data.lngptr[elem] < 0) this->value.undef[elem] = 1; if (! this->value.undef[elem]) { this->value.data.lngptr[elem] = simplerng_getpoisson(theParams[0]->value.data.lngptr[elem]); } } /* while */ } /* ! CONST_OP */ } /* END LONG */ break; /* Non-Trig single-argument functions */ case sum_fct: elem = row * theParams[0]->value.nelem; if( theParams[0]->type==BOOLEAN ) { while( row-- ) { this->value.data.lngptr[row] = 0; /* Default is UNDEF until a defined value is found */ this->value.undef[row] = 1; nelem = theParams[0]->value.nelem; while( nelem-- ) { elem--; if ( ! theParams[0]->value.undef[elem] ) { this->value.data.lngptr[row] += ( theParams[0]->value.data.logptr[elem] ? 1 : 0 ); this->value.undef[row] = 0; } } } } else if( theParams[0]->type==LONG ) { while( row-- ) { this->value.data.lngptr[row] = 0; /* Default is UNDEF until a defined value is found */ this->value.undef[row] = 1; nelem = theParams[0]->value.nelem; while( nelem-- ) { elem--; if ( ! theParams[0]->value.undef[elem] ) { this->value.data.lngptr[row] += theParams[0]->value.data.lngptr[elem]; this->value.undef[row] = 0; } } } } else if( theParams[0]->type==DOUBLE ){ while( row-- ) { this->value.data.dblptr[row] = 0.0; /* Default is UNDEF until a defined value is found */ this->value.undef[row] = 1; nelem = theParams[0]->value.nelem; while( nelem-- ) { elem--; if ( ! theParams[0]->value.undef[elem] ) { this->value.data.dblptr[row] += theParams[0]->value.data.dblptr[elem]; this->value.undef[row] = 0; } } } } else { /* BITSTR */ nelem = theParams[0]->value.nelem; while( row-- ) { char *sptr1 = theParams[0]->value.data.strptr[row]; this->value.data.lngptr[row] = 0; this->value.undef[row] = 0; while (*sptr1) { if (*sptr1 == '1') this->value.data.lngptr[row] ++; sptr1++; } } } break; case average_fct: elem = row * theParams[0]->value.nelem; if( theParams[0]->type==LONG ) { while( row-- ) { int count = 0; this->value.data.dblptr[row] = 0; nelem = theParams[0]->value.nelem; while( nelem-- ) { elem--; if (theParams[0]->value.undef[elem] == 0) { this->value.data.dblptr[row] += theParams[0]->value.data.lngptr[elem]; count ++; } } if (count == 0) { this->value.undef[row] = 1; } else { this->value.undef[row] = 0; this->value.data.dblptr[row] /= count; } } } else if( theParams[0]->type==DOUBLE ){ while( row-- ) { int count = 0; this->value.data.dblptr[row] = 0; nelem = theParams[0]->value.nelem; while( nelem-- ) { elem--; if (theParams[0]->value.undef[elem] == 0) { this->value.data.dblptr[row] += theParams[0]->value.data.dblptr[elem]; count ++; } } if (count == 0) { this->value.undef[row] = 1; } else { this->value.undef[row] = 0; this->value.data.dblptr[row] /= count; } } } break; case stddev_fct: elem = row * theParams[0]->value.nelem; if( theParams[0]->type==LONG ) { /* Compute the mean value */ while( row-- ) { int count = 0; double sum = 0, sum2 = 0; nelem = theParams[0]->value.nelem; while( nelem-- ) { elem--; if (theParams[0]->value.undef[elem] == 0) { sum += theParams[0]->value.data.lngptr[elem]; count ++; } } if (count > 1) { sum /= count; /* Compute the sum of squared deviations */ nelem = theParams[0]->value.nelem; elem += nelem; /* Reset elem for second pass */ while( nelem-- ) { elem--; if (theParams[0]->value.undef[elem] == 0) { double dx = (theParams[0]->value.data.lngptr[elem] - sum); sum2 += (dx*dx); } } sum2 /= (double)count-1; this->value.undef[row] = 0; this->value.data.dblptr[row] = sqrt(sum2); } else { this->value.undef[row] = 0; /* STDDEV => 0 */ this->value.data.dblptr[row] = 0; } } } else if( theParams[0]->type==DOUBLE ){ /* Compute the mean value */ while( row-- ) { int count = 0; double sum = 0, sum2 = 0; nelem = theParams[0]->value.nelem; while( nelem-- ) { elem--; if (theParams[0]->value.undef[elem] == 0) { sum += theParams[0]->value.data.dblptr[elem]; count ++; } } if (count > 1) { sum /= count; /* Compute the sum of squared deviations */ nelem = theParams[0]->value.nelem; elem += nelem; /* Reset elem for second pass */ while( nelem-- ) { elem--; if (theParams[0]->value.undef[elem] == 0) { double dx = (theParams[0]->value.data.dblptr[elem] - sum); sum2 += (dx*dx); } } sum2 /= (double)count-1; this->value.undef[row] = 0; this->value.data.dblptr[row] = sqrt(sum2); } else { this->value.undef[row] = 0; /* STDDEV => 0 */ this->value.data.dblptr[row] = 0; } } } break; case median_fct: elem = row * theParams[0]->value.nelem; nelem = theParams[0]->value.nelem; if( theParams[0]->type==LONG ) { long *dptr = theParams[0]->value.data.lngptr; char *uptr = theParams[0]->value.undef; long *mptr = (long *) malloc(sizeof(long)*nelem); int irow; /* Allocate temporary storage for this row, since the quickselect function will scramble the contents */ if (mptr == 0) { yyerror("Could not allocate temporary memory in median function"); free( this->value.data.ptr ); break; } for (irow=0; irow 0) { this->value.undef[irow] = 0; this->value.data.lngptr[irow] = qselect_median_lng(mptr, nelem1); } else { this->value.undef[irow] = 1; this->value.data.lngptr[irow] = 0; } } free(mptr); } else { double *dptr = theParams[0]->value.data.dblptr; char *uptr = theParams[0]->value.undef; double *mptr = (double *) malloc(sizeof(double)*nelem); int irow; /* Allocate temporary storage for this row, since the quickselect function will scramble the contents */ if (mptr == 0) { yyerror("Could not allocate temporary memory in median function"); free( this->value.data.ptr ); break; } for (irow=0; irow 0) { this->value.undef[irow] = 0; this->value.data.dblptr[irow] = qselect_median_dbl(mptr, nelem1); } else { this->value.undef[irow] = 1; this->value.data.dblptr[irow] = 0; } } free(mptr); } break; case abs_fct: if( theParams[0]->type==DOUBLE ) while( elem-- ) { dval = theParams[0]->value.data.dblptr[elem]; this->value.data.dblptr[elem] = (dval>0.0 ? dval : -dval); this->value.undef[elem] = theParams[0]->value.undef[elem]; } else while( elem-- ) { ival = theParams[0]->value.data.lngptr[elem]; this->value.data.lngptr[elem] = (ival> 0 ? ival : -ival); this->value.undef[elem] = theParams[0]->value.undef[elem]; } break; /* Special Null-Handling Functions */ case nonnull_fct: nelem = theParams[0]->value.nelem; if ( theParams[0]->type==STRING ) nelem = 1; elem = row * nelem; while( row-- ) { int nelem1 = nelem; this->value.undef[row] = 0; /* Initialize to 0 (defined) */ this->value.data.lngptr[row] = 0; while( nelem1-- ) { elem --; if ( theParams[0]->value.undef[elem] == 0 ) this->value.data.lngptr[row] ++; } } break; case isnull_fct: if( theParams[0]->type==STRING ) elem = row; while( elem-- ) { this->value.data.logptr[elem] = theParams[0]->value.undef[elem]; this->value.undef[elem] = 0; } break; case defnull_fct: switch( this->type ) { case BOOLEAN: while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; i=2; while( i-- ) if( vector[i]>1 ) { pNull[i] = theParams[i]->value.undef[elem]; pVals[i].data.log = theParams[i]->value.data.logptr[elem]; } else if( vector[i] ) { pNull[i] = theParams[i]->value.undef[row]; pVals[i].data.log = theParams[i]->value.data.logptr[row]; } if( pNull[0] ) { this->value.undef[elem] = pNull[1]; this->value.data.logptr[elem] = pVals[1].data.log; } else { this->value.undef[elem] = 0; this->value.data.logptr[elem] = pVals[0].data.log; } } } break; case LONG: while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; i=2; while( i-- ) if( vector[i]>1 ) { pNull[i] = theParams[i]->value.undef[elem]; pVals[i].data.lng = theParams[i]->value.data.lngptr[elem]; } else if( vector[i] ) { pNull[i] = theParams[i]->value.undef[row]; pVals[i].data.lng = theParams[i]->value.data.lngptr[row]; } if( pNull[0] ) { this->value.undef[elem] = pNull[1]; this->value.data.lngptr[elem] = pVals[1].data.lng; } else { this->value.undef[elem] = 0; this->value.data.lngptr[elem] = pVals[0].data.lng; } } } break; case DOUBLE: while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; i=2; while( i-- ) if( vector[i]>1 ) { pNull[i] = theParams[i]->value.undef[elem]; pVals[i].data.dbl = theParams[i]->value.data.dblptr[elem]; } else if( vector[i] ) { pNull[i] = theParams[i]->value.undef[row]; pVals[i].data.dbl = theParams[i]->value.data.dblptr[row]; } if( pNull[0] ) { this->value.undef[elem] = pNull[1]; this->value.data.dblptr[elem] = pVals[1].data.dbl; } else { this->value.undef[elem] = 0; this->value.data.dblptr[elem] = pVals[0].data.dbl; } } } break; case STRING: while( row-- ) { i=2; while( i-- ) if( vector[i] ) { pNull[i] = theParams[i]->value.undef[row]; strcpy(pVals[i].data.str, theParams[i]->value.data.strptr[row]); } if( pNull[0] ) { this->value.undef[row] = pNull[1]; strcpy(this->value.data.strptr[row],pVals[1].data.str); } else { this->value.undef[elem] = 0; strcpy(this->value.data.strptr[row],pVals[0].data.str); } } } break; /* Math functions with 1 double argument */ case sin_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { this->value.data.dblptr[elem] = sin( theParams[0]->value.data.dblptr[elem] ); } break; case cos_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { this->value.data.dblptr[elem] = cos( theParams[0]->value.data.dblptr[elem] ); } break; case tan_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { this->value.data.dblptr[elem] = tan( theParams[0]->value.data.dblptr[elem] ); } break; case asin_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { dval = theParams[0]->value.data.dblptr[elem]; if( dval<-1.0 || dval>1.0 ) { this->value.data.dblptr[elem] = 0.0; this->value.undef[elem] = 1; } else this->value.data.dblptr[elem] = asin( dval ); } break; case acos_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { dval = theParams[0]->value.data.dblptr[elem]; if( dval<-1.0 || dval>1.0 ) { this->value.data.dblptr[elem] = 0.0; this->value.undef[elem] = 1; } else this->value.data.dblptr[elem] = acos( dval ); } break; case atan_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { dval = theParams[0]->value.data.dblptr[elem]; this->value.data.dblptr[elem] = atan( dval ); } break; case sinh_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { this->value.data.dblptr[elem] = sinh( theParams[0]->value.data.dblptr[elem] ); } break; case cosh_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { this->value.data.dblptr[elem] = cosh( theParams[0]->value.data.dblptr[elem] ); } break; case tanh_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { this->value.data.dblptr[elem] = tanh( theParams[0]->value.data.dblptr[elem] ); } break; case exp_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { dval = theParams[0]->value.data.dblptr[elem]; this->value.data.dblptr[elem] = exp( dval ); } break; case log_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { dval = theParams[0]->value.data.dblptr[elem]; if( dval<=0.0 ) { this->value.data.dblptr[elem] = 0.0; this->value.undef[elem] = 1; } else this->value.data.dblptr[elem] = log( dval ); } break; case log10_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { dval = theParams[0]->value.data.dblptr[elem]; if( dval<=0.0 ) { this->value.data.dblptr[elem] = 0.0; this->value.undef[elem] = 1; } else this->value.data.dblptr[elem] = log10( dval ); } break; case sqrt_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { dval = theParams[0]->value.data.dblptr[elem]; if( dval<0.0 ) { this->value.data.dblptr[elem] = 0.0; this->value.undef[elem] = 1; } else this->value.data.dblptr[elem] = sqrt( dval ); } break; case ceil_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { this->value.data.dblptr[elem] = ceil( theParams[0]->value.data.dblptr[elem] ); } break; case floor_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { this->value.data.dblptr[elem] = floor( theParams[0]->value.data.dblptr[elem] ); } break; case round_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { this->value.data.dblptr[elem] = floor( theParams[0]->value.data.dblptr[elem] + 0.5); } break; /* Two-argument Trig Functions */ case atan2_fct: while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; i=2; while( i-- ) if( vector[i]>1 ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[elem]; pNull[i] = theParams[i]->value.undef[elem]; } else if( vector[i] ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[row]; pNull[i] = theParams[i]->value.undef[row]; } if( !(this->value.undef[elem] = (pNull[0] || pNull[1]) ) ) this->value.data.dblptr[elem] = atan2( pVals[0].data.dbl, pVals[1].data.dbl ); } } break; /* Four-argument ANGSEP Function */ case angsep_fct: while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; i=4; while( i-- ) if( vector[i]>1 ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[elem]; pNull[i] = theParams[i]->value.undef[elem]; } else if( vector[i] ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[row]; pNull[i] = theParams[i]->value.undef[row]; } if( !(this->value.undef[elem] = (pNull[0] || pNull[1] || pNull[2] || pNull[3]) ) ) this->value.data.dblptr[elem] = angsep_calc(pVals[0].data.dbl, pVals[1].data.dbl, pVals[2].data.dbl, pVals[3].data.dbl); } } break; /* Min/Max functions taking 1 or 2 arguments */ case min1_fct: elem = row * theParams[0]->value.nelem; if( this->type==LONG ) { long minVal=0; while( row-- ) { valInit = 1; this->value.undef[row] = 1; nelem = theParams[0]->value.nelem; while( nelem-- ) { elem--; if ( !theParams[0]->value.undef[elem] ) { if ( valInit ) { valInit = 0; minVal = theParams[0]->value.data.lngptr[elem]; } else { minVal = minvalue( minVal, theParams[0]->value.data.lngptr[elem] ); } this->value.undef[row] = 0; } } this->value.data.lngptr[row] = minVal; } } else if( this->type==DOUBLE ) { double minVal=0.0; while( row-- ) { valInit = 1; this->value.undef[row] = 1; nelem = theParams[0]->value.nelem; while( nelem-- ) { elem--; if ( !theParams[0]->value.undef[elem] ) { if ( valInit ) { valInit = 0; minVal = theParams[0]->value.data.dblptr[elem]; } else { minVal = minvalue( minVal, theParams[0]->value.data.dblptr[elem] ); } this->value.undef[row] = 0; } } this->value.data.dblptr[row] = minVal; } } else if( this->type==BITSTR ) { char minVal; while( row-- ) { char *sptr1 = theParams[0]->value.data.strptr[row]; minVal = '1'; while (*sptr1) { if (*sptr1 == '0') minVal = '0'; sptr1++; } this->value.data.strptr[row][0] = minVal; this->value.data.strptr[row][1] = 0; /* Null terminate */ } } break; case min2_fct: if( this->type==LONG ) { while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; i=2; while( i-- ) if( vector[i]>1 ) { pVals[i].data.lng = theParams[i]->value.data.lngptr[elem]; pNull[i] = theParams[i]->value.undef[elem]; } else if( vector[i] ) { pVals[i].data.lng = theParams[i]->value.data.lngptr[row]; pNull[i] = theParams[i]->value.undef[row]; } if( pNull[0] && pNull[1] ) { this->value.undef[elem] = 1; this->value.data.lngptr[elem] = 0; } else if (pNull[0]) { this->value.undef[elem] = 0; this->value.data.lngptr[elem] = pVals[1].data.lng; } else if (pNull[1]) { this->value.undef[elem] = 0; this->value.data.lngptr[elem] = pVals[0].data.lng; } else { this->value.undef[elem] = 0; this->value.data.lngptr[elem] = minvalue( pVals[0].data.lng, pVals[1].data.lng ); } } } } else if( this->type==DOUBLE ) { while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; i=2; while( i-- ) if( vector[i]>1 ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[elem]; pNull[i] = theParams[i]->value.undef[elem]; } else if( vector[i] ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[row]; pNull[i] = theParams[i]->value.undef[row]; } if( pNull[0] && pNull[1] ) { this->value.undef[elem] = 1; this->value.data.dblptr[elem] = 0; } else if (pNull[0]) { this->value.undef[elem] = 0; this->value.data.dblptr[elem] = pVals[1].data.dbl; } else if (pNull[1]) { this->value.undef[elem] = 0; this->value.data.dblptr[elem] = pVals[0].data.dbl; } else { this->value.undef[elem] = 0; this->value.data.dblptr[elem] = minvalue( pVals[0].data.dbl, pVals[1].data.dbl ); } } } } break; case max1_fct: elem = row * theParams[0]->value.nelem; if( this->type==LONG ) { long maxVal=0; while( row-- ) { valInit = 1; this->value.undef[row] = 1; nelem = theParams[0]->value.nelem; while( nelem-- ) { elem--; if ( !theParams[0]->value.undef[elem] ) { if ( valInit ) { valInit = 0; maxVal = theParams[0]->value.data.lngptr[elem]; } else { maxVal = maxvalue( maxVal, theParams[0]->value.data.lngptr[elem] ); } this->value.undef[row] = 0; } } this->value.data.lngptr[row] = maxVal; } } else if( this->type==DOUBLE ) { double maxVal=0.0; while( row-- ) { valInit = 1; this->value.undef[row] = 1; nelem = theParams[0]->value.nelem; while( nelem-- ) { elem--; if ( !theParams[0]->value.undef[elem] ) { if ( valInit ) { valInit = 0; maxVal = theParams[0]->value.data.dblptr[elem]; } else { maxVal = maxvalue( maxVal, theParams[0]->value.data.dblptr[elem] ); } this->value.undef[row] = 0; } } this->value.data.dblptr[row] = maxVal; } } else if( this->type==BITSTR ) { char maxVal; while( row-- ) { char *sptr1 = theParams[0]->value.data.strptr[row]; maxVal = '0'; while (*sptr1) { if (*sptr1 == '1') maxVal = '1'; sptr1++; } this->value.data.strptr[row][0] = maxVal; this->value.data.strptr[row][1] = 0; /* Null terminate */ } } break; case max2_fct: if( this->type==LONG ) { while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; i=2; while( i-- ) if( vector[i]>1 ) { pVals[i].data.lng = theParams[i]->value.data.lngptr[elem]; pNull[i] = theParams[i]->value.undef[elem]; } else if( vector[i] ) { pVals[i].data.lng = theParams[i]->value.data.lngptr[row]; pNull[i] = theParams[i]->value.undef[row]; } if( pNull[0] && pNull[1] ) { this->value.undef[elem] = 1; this->value.data.lngptr[elem] = 0; } else if (pNull[0]) { this->value.undef[elem] = 0; this->value.data.lngptr[elem] = pVals[1].data.lng; } else if (pNull[1]) { this->value.undef[elem] = 0; this->value.data.lngptr[elem] = pVals[0].data.lng; } else { this->value.undef[elem] = 0; this->value.data.lngptr[elem] = maxvalue( pVals[0].data.lng, pVals[1].data.lng ); } } } } else if( this->type==DOUBLE ) { while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; i=2; while( i-- ) if( vector[i]>1 ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[elem]; pNull[i] = theParams[i]->value.undef[elem]; } else if( vector[i] ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[row]; pNull[i] = theParams[i]->value.undef[row]; } if( pNull[0] && pNull[1] ) { this->value.undef[elem] = 1; this->value.data.dblptr[elem] = 0; } else if (pNull[0]) { this->value.undef[elem] = 0; this->value.data.dblptr[elem] = pVals[1].data.dbl; } else if (pNull[1]) { this->value.undef[elem] = 0; this->value.data.dblptr[elem] = pVals[0].data.dbl; } else { this->value.undef[elem] = 0; this->value.data.dblptr[elem] = maxvalue( pVals[0].data.dbl, pVals[1].data.dbl ); } } } } break; /* Boolean SAO region Functions... scalar or vector dbls */ case near_fct: while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; i=3; while( i-- ) if( vector[i]>1 ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[elem]; pNull[i] = theParams[i]->value.undef[elem]; } else if( vector[i] ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[row]; pNull[i] = theParams[i]->value.undef[row]; } if( !(this->value.undef[elem] = (pNull[0] || pNull[1] || pNull[2]) ) ) this->value.data.logptr[elem] = bnear( pVals[0].data.dbl, pVals[1].data.dbl, pVals[2].data.dbl ); } } break; case circle_fct: while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; i=5; while( i-- ) if( vector[i]>1 ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[elem]; pNull[i] = theParams[i]->value.undef[elem]; } else if( vector[i] ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[row]; pNull[i] = theParams[i]->value.undef[row]; } if( !(this->value.undef[elem] = (pNull[0] || pNull[1] || pNull[2] || pNull[3] || pNull[4]) ) ) this->value.data.logptr[elem] = circle( pVals[0].data.dbl, pVals[1].data.dbl, pVals[2].data.dbl, pVals[3].data.dbl, pVals[4].data.dbl ); } } break; case box_fct: while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; i=7; while( i-- ) if( vector[i]>1 ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[elem]; pNull[i] = theParams[i]->value.undef[elem]; } else if( vector[i] ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[row]; pNull[i] = theParams[i]->value.undef[row]; } if( !(this->value.undef[elem] = (pNull[0] || pNull[1] || pNull[2] || pNull[3] || pNull[4] || pNull[5] || pNull[6] ) ) ) this->value.data.logptr[elem] = saobox( pVals[0].data.dbl, pVals[1].data.dbl, pVals[2].data.dbl, pVals[3].data.dbl, pVals[4].data.dbl, pVals[5].data.dbl, pVals[6].data.dbl ); } } break; case elps_fct: while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; i=7; while( i-- ) if( vector[i]>1 ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[elem]; pNull[i] = theParams[i]->value.undef[elem]; } else if( vector[i] ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[row]; pNull[i] = theParams[i]->value.undef[row]; } if( !(this->value.undef[elem] = (pNull[0] || pNull[1] || pNull[2] || pNull[3] || pNull[4] || pNull[5] || pNull[6] ) ) ) this->value.data.logptr[elem] = ellipse( pVals[0].data.dbl, pVals[1].data.dbl, pVals[2].data.dbl, pVals[3].data.dbl, pVals[4].data.dbl, pVals[5].data.dbl, pVals[6].data.dbl ); } } break; /* C Conditional expression: bool ? expr : expr */ case ifthenelse_fct: switch( this->type ) { case BOOLEAN: while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; if( vector[2]>1 ) { pVals[2].data.log = theParams[2]->value.data.logptr[elem]; pNull[2] = theParams[2]->value.undef[elem]; } else if( vector[2] ) { pVals[2].data.log = theParams[2]->value.data.logptr[row]; pNull[2] = theParams[2]->value.undef[row]; } i=2; while( i-- ) if( vector[i]>1 ) { pVals[i].data.log = theParams[i]->value.data.logptr[elem]; pNull[i] = theParams[i]->value.undef[elem]; } else if( vector[i] ) { pVals[i].data.log = theParams[i]->value.data.logptr[row]; pNull[i] = theParams[i]->value.undef[row]; } if( !(this->value.undef[elem] = pNull[2]) ) { if( pVals[2].data.log ) { this->value.data.logptr[elem] = pVals[0].data.log; this->value.undef[elem] = pNull[0]; } else { this->value.data.logptr[elem] = pVals[1].data.log; this->value.undef[elem] = pNull[1]; } } } } break; case LONG: while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; if( vector[2]>1 ) { pVals[2].data.log = theParams[2]->value.data.logptr[elem]; pNull[2] = theParams[2]->value.undef[elem]; } else if( vector[2] ) { pVals[2].data.log = theParams[2]->value.data.logptr[row]; pNull[2] = theParams[2]->value.undef[row]; } i=2; while( i-- ) if( vector[i]>1 ) { pVals[i].data.lng = theParams[i]->value.data.lngptr[elem]; pNull[i] = theParams[i]->value.undef[elem]; } else if( vector[i] ) { pVals[i].data.lng = theParams[i]->value.data.lngptr[row]; pNull[i] = theParams[i]->value.undef[row]; } if( !(this->value.undef[elem] = pNull[2]) ) { if( pVals[2].data.log ) { this->value.data.lngptr[elem] = pVals[0].data.lng; this->value.undef[elem] = pNull[0]; } else { this->value.data.lngptr[elem] = pVals[1].data.lng; this->value.undef[elem] = pNull[1]; } } } } break; case DOUBLE: while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; if( vector[2]>1 ) { pVals[2].data.log = theParams[2]->value.data.logptr[elem]; pNull[2] = theParams[2]->value.undef[elem]; } else if( vector[2] ) { pVals[2].data.log = theParams[2]->value.data.logptr[row]; pNull[2] = theParams[2]->value.undef[row]; } i=2; while( i-- ) if( vector[i]>1 ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[elem]; pNull[i] = theParams[i]->value.undef[elem]; } else if( vector[i] ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[row]; pNull[i] = theParams[i]->value.undef[row]; } if( !(this->value.undef[elem] = pNull[2]) ) { if( pVals[2].data.log ) { this->value.data.dblptr[elem] = pVals[0].data.dbl; this->value.undef[elem] = pNull[0]; } else { this->value.data.dblptr[elem] = pVals[1].data.dbl; this->value.undef[elem] = pNull[1]; } } } } break; case STRING: while( row-- ) { if( vector[2] ) { pVals[2].data.log = theParams[2]->value.data.logptr[row]; pNull[2] = theParams[2]->value.undef[row]; } i=2; while( i-- ) if( vector[i] ) { strcpy( pVals[i].data.str, theParams[i]->value.data.strptr[row] ); pNull[i] = theParams[i]->value.undef[row]; } if( !(this->value.undef[row] = pNull[2]) ) { if( pVals[2].data.log ) { strcpy( this->value.data.strptr[row], pVals[0].data.str ); this->value.undef[row] = pNull[0]; } else { strcpy( this->value.data.strptr[row], pVals[1].data.str ); this->value.undef[row] = pNull[1]; } } else { this->value.data.strptr[row][0] = '\0'; } } break; } break; /* String functions */ case strmid_fct: { int strconst = theParams[0]->operation == CONST_OP; int posconst = theParams[1]->operation == CONST_OP; int lenconst = theParams[2]->operation == CONST_OP; int dest_len = this->value.nelem; int src_len = theParams[0]->value.nelem; while (row--) { int pos; int len; char *str; int undef = 0; if (posconst) { pos = theParams[1]->value.data.lng; } else { pos = theParams[1]->value.data.lngptr[row]; if (theParams[1]->value.undef[row]) undef = 1; } if (strconst) { str = theParams[0]->value.data.str; if (src_len == 0) src_len = strlen(str); } else { str = theParams[0]->value.data.strptr[row]; if (theParams[0]->value.undef[row]) undef = 1; } if (lenconst) { len = dest_len; } else { len = theParams[2]->value.data.lngptr[row]; if (theParams[2]->value.undef[row]) undef = 1; } this->value.data.strptr[row][0] = '\0'; if (pos == 0) undef = 1; if (! undef ) { if (cstrmid(this->value.data.strptr[row], len, str, src_len, pos) < 0) break; } this->value.undef[row] = undef; } } break; /* String functions */ case strpos_fct: { int const1 = theParams[0]->operation == CONST_OP; int const2 = theParams[1]->operation == CONST_OP; while (row--) { char *str1, *str2; int undef = 0; if (const1) { str1 = theParams[0]->value.data.str; } else { str1 = theParams[0]->value.data.strptr[row]; if (theParams[0]->value.undef[row]) undef = 1; } if (const2) { str2 = theParams[1]->value.data.str; } else { str2 = theParams[1]->value.data.strptr[row]; if (theParams[1]->value.undef[row]) undef = 1; } this->value.data.lngptr[row] = 0; if (! undef ) { char *res = strstr(str1, str2); if (res == NULL) { undef = 1; this->value.data.lngptr[row] = 0; } else { this->value.data.lngptr[row] = (res - str1) + 1; } } this->value.undef[row] = undef; } } break; } /* End switch(this->operation) */ } /* End if (!gParse.status) */ } /* End non-constant operations */ i = this->nSubNodes; while( i-- ) { if( theParams[i]->operation>0 ) { /* Currently only numeric params allowed */ free( theParams[i]->value.data.ptr ); } } } static void Do_Deref( Node *this ) { Node *theVar, *theDims[MAXDIMS]; int isConst[MAXDIMS], allConst; long dimVals[MAXDIMS]; int i, nDims; long row, elem, dsize; theVar = gParse.Nodes + this->SubNodes[0]; i = nDims = this->nSubNodes-1; allConst = 1; while( i-- ) { theDims[i] = gParse.Nodes + this->SubNodes[i+1]; isConst[i] = ( theDims[i]->operation==CONST_OP ); if( isConst[i] ) dimVals[i] = theDims[i]->value.data.lng; else allConst = 0; } if( this->type==DOUBLE ) { dsize = sizeof( double ); } else if( this->type==LONG ) { dsize = sizeof( long ); } else if( this->type==BOOLEAN ) { dsize = sizeof( char ); } else dsize = 0; Allocate_Ptrs( this ); if( !gParse.status ) { if( allConst && theVar->value.naxis==nDims ) { /* Dereference completely using constant indices */ elem = 0; i = nDims; while( i-- ) { if( dimVals[i]<1 || dimVals[i]>theVar->value.naxes[i] ) break; elem = theVar->value.naxes[i]*elem + dimVals[i]-1; } if( i<0 ) { for( row=0; rowtype==STRING ) this->value.undef[row] = theVar->value.undef[row]; else if( this->type==BITSTR ) this->value.undef; /* Dummy - BITSTRs do not have undefs */ else this->value.undef[row] = theVar->value.undef[elem]; if( this->type==DOUBLE ) this->value.data.dblptr[row] = theVar->value.data.dblptr[elem]; else if( this->type==LONG ) this->value.data.lngptr[row] = theVar->value.data.lngptr[elem]; else if( this->type==BOOLEAN ) this->value.data.logptr[row] = theVar->value.data.logptr[elem]; else { /* XXX Note, the below expression uses knowledge of the layout of the string format, namely (nelem+1) characters per string, followed by (nelem+1) "undef" values. */ this->value.data.strptr[row][0] = theVar->value.data.strptr[0][elem+row]; this->value.data.strptr[row][1] = 0; /* Null terminate */ } elem += theVar->value.nelem; } } else { yyerror("Index out of range"); free( this->value.data.ptr ); } } else if( allConst && nDims==1 ) { /* Reduce dimensions by 1, using a constant index */ if( dimVals[0] < 1 || dimVals[0] > theVar->value.naxes[ theVar->value.naxis-1 ] ) { yyerror("Index out of range"); free( this->value.data.ptr ); } else if ( this->type == BITSTR || this->type == STRING ) { elem = this->value.nelem * (dimVals[0]-1); for( row=0; rowvalue.undef) this->value.undef[row] = theVar->value.undef[row]; memcpy( (char*)this->value.data.strptr[0] + row*sizeof(char)*(this->value.nelem+1), (char*)theVar->value.data.strptr[0] + elem*sizeof(char), this->value.nelem * sizeof(char) ); /* Null terminate */ this->value.data.strptr[row][this->value.nelem] = 0; elem += theVar->value.nelem+1; } } else { elem = this->value.nelem * (dimVals[0]-1); for( row=0; rowvalue.undef + row*this->value.nelem, theVar->value.undef + elem, this->value.nelem * sizeof(char) ); memcpy( (char*)this->value.data.ptr + row*dsize*this->value.nelem, (char*)theVar->value.data.ptr + elem*dsize, this->value.nelem * dsize ); elem += theVar->value.nelem; } } } else if( theVar->value.naxis==nDims ) { /* Dereference completely using an expression for the indices */ for( row=0; rowvalue.undef[row] ) { yyerror("Null encountered as vector index"); free( this->value.data.ptr ); break; } else dimVals[i] = theDims[i]->value.data.lngptr[row]; } } if( gParse.status ) break; elem = 0; i = nDims; while( i-- ) { if( dimVals[i]<1 || dimVals[i]>theVar->value.naxes[i] ) break; elem = theVar->value.naxes[i]*elem + dimVals[i]-1; } if( i<0 ) { elem += row*theVar->value.nelem; if( this->type==STRING ) this->value.undef[row] = theVar->value.undef[row]; else if( this->type==BITSTR ) this->value.undef; /* Dummy - BITSTRs do not have undefs */ else this->value.undef[row] = theVar->value.undef[elem]; if( this->type==DOUBLE ) this->value.data.dblptr[row] = theVar->value.data.dblptr[elem]; else if( this->type==LONG ) this->value.data.lngptr[row] = theVar->value.data.lngptr[elem]; else if( this->type==BOOLEAN ) this->value.data.logptr[row] = theVar->value.data.logptr[elem]; else { /* XXX Note, the below expression uses knowledge of the layout of the string format, namely (nelem+1) characters per string, followed by (nelem+1) "undef" values. */ this->value.data.strptr[row][0] = theVar->value.data.strptr[0][elem+row]; this->value.data.strptr[row][1] = 0; /* Null terminate */ } } else { yyerror("Index out of range"); free( this->value.data.ptr ); } } } else { /* Reduce dimensions by 1, using a nonconstant expression */ for( row=0; rowvalue.undef[row] ) { yyerror("Null encountered as vector index"); free( this->value.data.ptr ); break; } else dimVals[0] = theDims[0]->value.data.lngptr[row]; if( dimVals[0] < 1 || dimVals[0] > theVar->value.naxes[ theVar->value.naxis-1 ] ) { yyerror("Index out of range"); free( this->value.data.ptr ); } else if ( this->type == BITSTR || this->type == STRING ) { elem = this->value.nelem * (dimVals[0]-1); elem += row*(theVar->value.nelem+1); if (this->value.undef) this->value.undef[row] = theVar->value.undef[row]; memcpy( (char*)this->value.data.strptr[0] + row*sizeof(char)*(this->value.nelem+1), (char*)theVar->value.data.strptr[0] + elem*sizeof(char), this->value.nelem * sizeof(char) ); /* Null terminate */ this->value.data.strptr[row][this->value.nelem] = 0; } else { elem = this->value.nelem * (dimVals[0]-1); elem += row*theVar->value.nelem; memcpy( this->value.undef + row*this->value.nelem, theVar->value.undef + elem, this->value.nelem * sizeof(char) ); memcpy( (char*)this->value.data.ptr + row*dsize*this->value.nelem, (char*)theVar->value.data.ptr + elem*dsize, this->value.nelem * dsize ); } } } } if( theVar->operation>0 ) { if (theVar->type == STRING || theVar->type == BITSTR) free(theVar->value.data.strptr[0] ); else free( theVar->value.data.ptr ); } for( i=0; ioperation>0 ) { free( theDims[i]->value.data.ptr ); } } static void Do_GTI( Node *this ) { Node *theExpr, *theTimes; double *start, *stop, *times; long elem, nGTI, gti; int ordered; theTimes = gParse.Nodes + this->SubNodes[0]; theExpr = gParse.Nodes + this->SubNodes[1]; nGTI = theTimes->value.nelem; start = theTimes->value.data.dblptr; stop = theTimes->value.data.dblptr + nGTI; ordered = theTimes->type; if( theExpr->operation==CONST_OP ) { this->value.data.log = (Search_GTI( theExpr->value.data.dbl, nGTI, start, stop, ordered )>=0); this->operation = CONST_OP; } else { Allocate_Ptrs( this ); times = theExpr->value.data.dblptr; if( !gParse.status ) { elem = gParse.nRows * this->value.nelem; if( nGTI ) { gti = -1; while( elem-- ) { if( (this->value.undef[elem] = theExpr->value.undef[elem]) ) continue; /* Before searching entire GTI, check the GTI found last time */ if( gti<0 || times[elem]stop[gti] ) { gti = Search_GTI( times[elem], nGTI, start, stop, ordered ); } this->value.data.logptr[elem] = ( gti>=0 ); } } else while( elem-- ) { this->value.data.logptr[elem] = 0; this->value.undef[elem] = 0; } } } if( theExpr->operation>0 ) free( theExpr->value.data.ptr ); } static long Search_GTI( double evtTime, long nGTI, double *start, double *stop, int ordered ) { long gti, step; if( ordered && nGTI>15 ) { /* If time-ordered and lots of GTIs, */ /* use "FAST" Binary search algorithm */ if( evtTime>=start[0] && evtTime<=stop[nGTI-1] ) { gti = step = (nGTI >> 1); while(1) { if( step>1L ) step >>= 1; if( evtTime>stop[gti] ) { if( evtTime>=start[gti+1] ) gti += step; else { gti = -1L; break; } } else if( evtTime=start[gti] && evtTime<=stop[gti] ) break; } return( gti ); } static void Do_REG( Node *this ) { Node *theRegion, *theX, *theY; double Xval=0.0, Yval=0.0; char Xnull=0, Ynull=0; int Xvector, Yvector; long nelem, elem, rows; theRegion = gParse.Nodes + this->SubNodes[0]; theX = gParse.Nodes + this->SubNodes[1]; theY = gParse.Nodes + this->SubNodes[2]; Xvector = ( theX->operation!=CONST_OP ); if( Xvector ) Xvector = theX->value.nelem; else { Xval = theX->value.data.dbl; } Yvector = ( theY->operation!=CONST_OP ); if( Yvector ) Yvector = theY->value.nelem; else { Yval = theY->value.data.dbl; } if( !Xvector && !Yvector ) { this->value.data.log = ( fits_in_region( Xval, Yval, (SAORegion *)theRegion->value.data.ptr ) != 0 ); this->operation = CONST_OP; } else { Allocate_Ptrs( this ); if( !gParse.status ) { rows = gParse.nRows; nelem = this->value.nelem; elem = rows*nelem; while( rows-- ) { while( nelem-- ) { elem--; if( Xvector>1 ) { Xval = theX->value.data.dblptr[elem]; Xnull = theX->value.undef[elem]; } else if( Xvector ) { Xval = theX->value.data.dblptr[rows]; Xnull = theX->value.undef[rows]; } if( Yvector>1 ) { Yval = theY->value.data.dblptr[elem]; Ynull = theY->value.undef[elem]; } else if( Yvector ) { Yval = theY->value.data.dblptr[rows]; Ynull = theY->value.undef[rows]; } this->value.undef[elem] = ( Xnull || Ynull ); if( this->value.undef[elem] ) continue; this->value.data.logptr[elem] = ( fits_in_region( Xval, Yval, (SAORegion *)theRegion->value.data.ptr ) != 0 ); } nelem = this->value.nelem; } } } if( theX->operation>0 ) free( theX->value.data.ptr ); if( theY->operation>0 ) free( theY->value.data.ptr ); } static void Do_Vector( Node *this ) { Node *that; long row, elem, idx, jdx, offset=0; int node; Allocate_Ptrs( this ); if( !gParse.status ) { for( node=0; nodenSubNodes; node++ ) { that = gParse.Nodes + this->SubNodes[node]; if( that->operation == CONST_OP ) { idx = gParse.nRows*this->value.nelem + offset; while( (idx-=this->value.nelem)>=0 ) { this->value.undef[idx] = 0; switch( this->type ) { case BOOLEAN: this->value.data.logptr[idx] = that->value.data.log; break; case LONG: this->value.data.lngptr[idx] = that->value.data.lng; break; case DOUBLE: this->value.data.dblptr[idx] = that->value.data.dbl; break; } } } else { row = gParse.nRows; idx = row * that->value.nelem; while( row-- ) { elem = that->value.nelem; jdx = row*this->value.nelem + offset; while( elem-- ) { this->value.undef[jdx+elem] = that->value.undef[--idx]; switch( this->type ) { case BOOLEAN: this->value.data.logptr[jdx+elem] = that->value.data.logptr[idx]; break; case LONG: this->value.data.lngptr[jdx+elem] = that->value.data.lngptr[idx]; break; case DOUBLE: this->value.data.dblptr[jdx+elem] = that->value.data.dblptr[idx]; break; } } } } offset += that->value.nelem; } } for( node=0; node < this->nSubNodes; node++ ) if( OPER(this->SubNodes[node])>0 ) free( gParse.Nodes[this->SubNodes[node]].value.data.ptr ); } /*****************************************************************************/ /* Utility routines which perform the calculations on bits and SAO regions */ /*****************************************************************************/ static char bitlgte(char *bits1, int oper, char *bits2) { int val1, val2, nextbit; char result; int i, l1, l2, length, ldiff; char *stream=0; char chr1, chr2; l1 = strlen(bits1); l2 = strlen(bits2); length = (l1 > l2) ? l1 : l2; stream = (char *)malloc(sizeof(char)*(length+1)); if (l1 < l2) { ldiff = l2 - l1; i=0; while( ldiff-- ) stream[i++] = '0'; while( l1-- ) stream[i++] = *(bits1++); stream[i] = '\0'; bits1 = stream; } else if (l2 < l1) { ldiff = l1 - l2; i=0; while( ldiff-- ) stream[i++] = '0'; while( l2-- ) stream[i++] = *(bits2++); stream[i] = '\0'; bits2 = stream; } val1 = val2 = 0; nextbit = 1; while( length-- ) { chr1 = bits1[length]; chr2 = bits2[length]; if ((chr1 != 'x')&&(chr1 != 'X')&&(chr2 != 'x')&&(chr2 != 'X')) { if (chr1 == '1') val1 += nextbit; if (chr2 == '1') val2 += nextbit; nextbit *= 2; } } result = 0; switch (oper) { case LT: if (val1 < val2) result = 1; break; case LTE: if (val1 <= val2) result = 1; break; case GT: if (val1 > val2) result = 1; break; case GTE: if (val1 >= val2) result = 1; break; } free(stream); return (result); } static void bitand(char *result,char *bitstrm1,char *bitstrm2) { int i, l1, l2, ldiff, largestStream; char *stream=0; char chr1, chr2; l1 = strlen(bitstrm1); l2 = strlen(bitstrm2); largestStream = (l1 > l2) ? l1 : l2; stream = (char *)malloc(sizeof(char)*(largestStream+1)); if (l1 < l2) { ldiff = l2 - l1; i=0; while( ldiff-- ) stream[i++] = '0'; while( l1-- ) stream[i++] = *(bitstrm1++); stream[i] = '\0'; bitstrm1 = stream; } else if (l2 < l1) { ldiff = l1 - l2; i=0; while( ldiff-- ) stream[i++] = '0'; while( l2-- ) stream[i++] = *(bitstrm2++); stream[i] = '\0'; bitstrm2 = stream; } while ( (chr1 = *(bitstrm1++)) ) { chr2 = *(bitstrm2++); if ((chr1 == 'x') || (chr2 == 'x')) *result = 'x'; else if ((chr1 == '1') && (chr2 == '1')) *result = '1'; else *result = '0'; result++; } free(stream); *result = '\0'; } static void bitor(char *result,char *bitstrm1,char *bitstrm2) { int i, l1, l2, ldiff, largestStream; char *stream=0; char chr1, chr2; l1 = strlen(bitstrm1); l2 = strlen(bitstrm2); largestStream = (l1 > l2) ? l1 : l2; stream = (char *)malloc(sizeof(char)*(largestStream+1)); if (l1 < l2) { ldiff = l2 - l1; i=0; while( ldiff-- ) stream[i++] = '0'; while( l1-- ) stream[i++] = *(bitstrm1++); stream[i] = '\0'; bitstrm1 = stream; } else if (l2 < l1) { ldiff = l1 - l2; i=0; while( ldiff-- ) stream[i++] = '0'; while( l2-- ) stream[i++] = *(bitstrm2++); stream[i] = '\0'; bitstrm2 = stream; } while ( (chr1 = *(bitstrm1++)) ) { chr2 = *(bitstrm2++); if ((chr1 == '1') || (chr2 == '1')) *result = '1'; else if ((chr1 == '0') || (chr2 == '0')) *result = '0'; else *result = 'x'; result++; } free(stream); *result = '\0'; } static void bitnot(char *result,char *bits) { int length; char chr; length = strlen(bits); while( length-- ) { chr = *(bits++); *(result++) = ( chr=='1' ? '0' : ( chr=='0' ? '1' : chr ) ); } *result = '\0'; } static char bitcmp(char *bitstrm1, char *bitstrm2) { int i, l1, l2, ldiff, largestStream; char *stream=0; char chr1, chr2; l1 = strlen(bitstrm1); l2 = strlen(bitstrm2); largestStream = (l1 > l2) ? l1 : l2; stream = (char *)malloc(sizeof(char)*(largestStream+1)); if (l1 < l2) { ldiff = l2 - l1; i=0; while( ldiff-- ) stream[i++] = '0'; while( l1-- ) stream[i++] = *(bitstrm1++); stream[i] = '\0'; bitstrm1 = stream; } else if (l2 < l1) { ldiff = l1 - l2; i=0; while( ldiff-- ) stream[i++] = '0'; while( l2-- ) stream[i++] = *(bitstrm2++); stream[i] = '\0'; bitstrm2 = stream; } while( (chr1 = *(bitstrm1++)) ) { chr2 = *(bitstrm2++); if ( ((chr1 == '0') && (chr2 == '1')) || ((chr1 == '1') && (chr2 == '0')) ) { free(stream); return( 0 ); } } free(stream); return( 1 ); } static char bnear(double x, double y, double tolerance) { if (fabs(x - y) < tolerance) return ( 1 ); else return ( 0 ); } static char saobox(double xcen, double ycen, double xwid, double ywid, double rot, double xcol, double ycol) { double x,y,xprime,yprime,xmin,xmax,ymin,ymax,theta; theta = (rot / 180.0) * myPI; xprime = xcol - xcen; yprime = ycol - ycen; x = xprime * cos(theta) + yprime * sin(theta); y = -xprime * sin(theta) + yprime * cos(theta); xmin = - 0.5 * xwid; xmax = 0.5 * xwid; ymin = - 0.5 * ywid; ymax = 0.5 * ywid; if ((x >= xmin) && (x <= xmax) && (y >= ymin) && (y <= ymax)) return ( 1 ); else return ( 0 ); } static char circle(double xcen, double ycen, double rad, double xcol, double ycol) { double r2,dx,dy,dlen; dx = xcol - xcen; dy = ycol - ycen; dx *= dx; dy *= dy; dlen = dx + dy; r2 = rad * rad; if (dlen <= r2) return ( 1 ); else return ( 0 ); } static char ellipse(double xcen, double ycen, double xrad, double yrad, double rot, double xcol, double ycol) { double x,y,xprime,yprime,dx,dy,dlen,theta; theta = (rot / 180.0) * myPI; xprime = xcol - xcen; yprime = ycol - ycen; x = xprime * cos(theta) + yprime * sin(theta); y = -xprime * sin(theta) + yprime * cos(theta); dx = x / xrad; dy = y / yrad; dx *= dx; dy *= dy; dlen = dx + dy; if (dlen <= 1.0) return ( 1 ); else return ( 0 ); } /* * Extract substring */ int cstrmid(char *dest_str, int dest_len, char *src_str, int src_len, int pos) { /* char fill_char = ' '; */ char fill_char = '\0'; if (src_len == 0) { src_len = strlen(src_str); } /* .. if constant */ /* Fill destination with blanks */ if (pos < 0) { yyerror("STRMID(S,P,N) P must be 0 or greater"); return -1; } if (pos > src_len || pos == 0) { /* pos==0: blank string requested */ memset(dest_str, fill_char, dest_len); } else if (pos+dest_len > src_len) { /* Copy a subset */ int nsub = src_len-pos+1; int npad = dest_len - nsub; memcpy(dest_str, src_str+pos-1, nsub); /* Fill remaining string with blanks */ memset(dest_str+nsub, fill_char, npad); } else { /* Full string copy */ memcpy(dest_str, src_str+pos-1, dest_len); } dest_str[dest_len] = '\0'; /* Null-terminate */ return 0; } static void yyerror(char *s) { char msg[80]; if( !gParse.status ) gParse.status = PARSE_SYNTAX_ERR; strncpy(msg, s, 80); msg[79] = '\0'; ffpmsg(msg); } cfitsio/eval_defs.h0000644000225700000360000001023613246025103014103 0ustar cagordonlhea#include #include #include #include #if defined(__sgi) || defined(__hpux) #include #endif #ifdef sparc #include #endif #include "fitsio2.h" #define MAXDIMS 5 #define MAXSUBS 10 #define MAXVARNAME 80 #define CONST_OP -1000 #define pERROR -1 #define MAX_STRLEN 256 #define MAX_STRLEN_S "255" #ifndef FFBISON #include "eval_tab.h" #endif typedef struct { char name[MAXVARNAME+1]; int type; long nelem; int naxis; long naxes[MAXDIMS]; char *undef; void *data; } DataInfo; typedef struct { long nelem; int naxis; long naxes[MAXDIMS]; char *undef; union { double dbl; long lng; char log; char str[MAX_STRLEN]; double *dblptr; long *lngptr; char *logptr; char **strptr; void *ptr; } data; } lval; typedef struct Node { int operation; void (*DoOp)(struct Node *this); int nSubNodes; int SubNodes[MAXSUBS]; int type; lval value; } Node; typedef struct { fitsfile *def_fptr; int (*getData)( char *dataName, void *dataValue ); int (*loadData)( int varNum, long fRow, long nRows, void *data, char *undef ); int compressed; int timeCol; int parCol; int valCol; char *expr; int index; int is_eobuf; Node *Nodes; int nNodes; int nNodesAlloc; int resultNode; long firstRow; long nRows; int nCols; iteratorCol *colData; DataInfo *varData; PixelFilter *pixFilter; long firstDataRow; long nDataRows; long totalRows; int datatype; int hdutype; int status; } ParseData; typedef enum { rnd_fct = 1001, sum_fct, nelem_fct, sin_fct, cos_fct, tan_fct, asin_fct, acos_fct, atan_fct, sinh_fct, cosh_fct, tanh_fct, exp_fct, log_fct, log10_fct, sqrt_fct, abs_fct, atan2_fct, ceil_fct, floor_fct, round_fct, min1_fct, min2_fct, max1_fct, max2_fct, near_fct, circle_fct, box_fct, elps_fct, isnull_fct, defnull_fct, gtifilt_fct, regfilt_fct, ifthenelse_fct, row_fct, null_fct, median_fct, average_fct, stddev_fct, nonnull_fct, angsep_fct, gasrnd_fct, poirnd_fct, strmid_fct, strpos_fct } funcOp; extern ParseData gParse; #ifdef __cplusplus extern "C" { #endif int ffparse(void); int fflex(void); void ffrestart(FILE*); void Evaluate_Parser( long firstRow, long nRows ); #ifdef __cplusplus } #endif cfitsio/eval_f.c0000644000225700000360000030076213246025103013410 0ustar cagordonlhea/************************************************************************/ /* */ /* CFITSIO Lexical Parser */ /* */ /* This file is one of 3 files containing code which parses an */ /* arithmetic expression and evaluates it in the context of an input */ /* FITS file table extension. The CFITSIO lexical parser is divided */ /* into the following 3 parts/files: the CFITSIO "front-end", */ /* eval_f.c, contains the interface between the user/CFITSIO and the */ /* real core of the parser; the FLEX interpreter, eval_l.c, takes the */ /* input string and parses it into tokens and identifies the FITS */ /* information required to evaluate the expression (ie, keywords and */ /* columns); and, the BISON grammar and evaluation routines, eval_y.c, */ /* receives the FLEX output and determines and performs the actual */ /* operations. The files eval_l.c and eval_y.c are produced from */ /* running flex and bison on the files eval.l and eval.y, respectively. */ /* (flex and bison are available from any GNU archive: see www.gnu.org) */ /* */ /* The grammar rules, rather than evaluating the expression in situ, */ /* builds a tree, or Nodal, structure mapping out the order of */ /* operations and expression dependencies. This "compilation" process */ /* allows for much faster processing of multiple rows. This technique */ /* was developed by Uwe Lammers of the XMM Science Analysis System, */ /* although the CFITSIO implementation is entirely code original. */ /* */ /* */ /* Modification History: */ /* */ /* Kent Blackburn c1992 Original parser code developed for the */ /* FTOOLS software package, in particular, */ /* the fselect task. */ /* Kent Blackburn c1995 BIT column support added */ /* Peter D Wilson Feb 1998 Vector column support added */ /* Peter D Wilson May 1998 Ported to CFITSIO library. User */ /* interface routines written, in essence */ /* making fselect, fcalc, and maketime */ /* capabilities available to all tools */ /* via single function calls. */ /* Peter D Wilson Jun 1998 Major rewrite of parser core, so as to */ /* create a run-time evaluation tree, */ /* inspired by the work of Uwe Lammers, */ /* resulting in a speed increase of */ /* 10-100 times. */ /* Peter D Wilson Jul 1998 gtifilter(a,b,c,d) function added */ /* Peter D Wilson Aug 1998 regfilter(a,b,c,d) function added */ /* Peter D Wilson Jul 1999 Make parser fitsfile-independent, */ /* allowing a purely vector-based usage */ /* Peter D Wilson Aug 1999 Add row-offset capability */ /* Peter D Wilson Sep 1999 Add row-range capability to ffcalc_rng */ /* */ /************************************************************************/ #include #include #include "eval_defs.h" #include "region.h" typedef struct { int datatype; /* Data type to cast parse results into for user */ void *dataPtr; /* Pointer to array of results, NULL if to use iterCol */ void *nullPtr; /* Pointer to nulval, use zero if NULL */ long maxRows; /* Max No. of rows to process, -1=all, 0=1 iteration */ int anyNull; /* Flag indicating at least 1 undef value encountered */ } parseInfo; /* Internal routines needed to allow the evaluator to operate on FITS data */ static void Setup_DataArrays( int nCols, iteratorCol *cols, long fRow, long nRows ); static int find_column( char *colName, void *itslval ); static int find_keywd ( char *key, void *itslval ); static int allocateCol( int nCol, int *status ); static int load_column( int varNum, long fRow, long nRows, void *data, char *undef ); static int DEBUG_PIXFILTER; #define FREE(x) { if (x) free(x); else printf("invalid free(" #x ") at %s:%d\n", __FILE__, __LINE__); } /*---------------------------------------------------------------------------*/ int fffrow( fitsfile *fptr, /* I - Input FITS file */ char *expr, /* I - Boolean expression */ long firstrow, /* I - First row of table to eval */ long nrows, /* I - Number of rows to evaluate */ long *n_good_rows, /* O - Number of rows eval to True */ char *row_status, /* O - Array of boolean results */ int *status ) /* O - Error status */ /* */ /* Evaluate a boolean expression using the indicated rows, returning an */ /* array of flags indicating which rows evaluated to TRUE/FALSE */ /*---------------------------------------------------------------------------*/ { parseInfo Info; int naxis, constant; long nelem, naxes[MAXDIMS], elem; char result; if( *status ) return( *status ); FFLOCK; if( ffiprs( fptr, 0, expr, MAXDIMS, &Info.datatype, &nelem, &naxis, naxes, status ) ) { ffcprs(); FFUNLOCK; return( *status ); } if( nelem<0 ) { constant = 1; nelem = -nelem; } else constant = 0; if( Info.datatype!=TLOGICAL || nelem!=1 ) { ffcprs(); ffpmsg("Expression does not evaluate to a logical scalar."); FFUNLOCK; return( *status = PARSE_BAD_TYPE ); } if( constant ) { /* No need to call parser... have result from ffiprs */ result = gParse.Nodes[gParse.resultNode].value.data.log; *n_good_rows = nrows; for( elem=0; elem1 ? firstrow : 1); Info.dataPtr = row_status; Info.nullPtr = NULL; Info.maxRows = nrows; if( ffiter( gParse.nCols, gParse.colData, firstrow-1, 0, parse_data, (void*)&Info, status ) == -1 ) *status = 0; /* -1 indicates exitted without error before end... OK */ if( *status ) { /***********************/ /* Error... Do nothing */ /***********************/ } else { /***********************************/ /* Count number of good rows found */ /***********************************/ *n_good_rows = 0L; for( elem=0; elemHDUposition != (infptr->Fptr)->curhdu ) ffmahd( infptr, (infptr->HDUposition) + 1, NULL, status ); if( *status ) { ffcprs(); FFUNLOCK; return( *status ); } inExt.rowLength = (long) (infptr->Fptr)->rowlength; inExt.numRows = (infptr->Fptr)->numrows; inExt.heapSize = (infptr->Fptr)->heapsize; if( inExt.numRows == 0 ) { /* Nothing to copy */ ffcprs(); FFUNLOCK; return( *status ); } if( outfptr->HDUposition != (outfptr->Fptr)->curhdu ) ffmahd( outfptr, (outfptr->HDUposition) + 1, NULL, status ); if( (outfptr->Fptr)->datastart < 0 ) ffrdef( outfptr, status ); if( *status ) { ffcprs(); FFUNLOCK; return( *status ); } outExt.rowLength = (long) (outfptr->Fptr)->rowlength; outExt.numRows = (outfptr->Fptr)->numrows; if( !outExt.numRows ) (outfptr->Fptr)->heapsize = 0L; outExt.heapSize = (outfptr->Fptr)->heapsize; if( inExt.rowLength != outExt.rowLength ) { ffpmsg("Output table has different row length from input"); ffcprs(); FFUNLOCK; return( *status = PARSE_BAD_OUTPUT ); } /***********************************/ /* Fill out Info data for parser */ /***********************************/ Info.dataPtr = (char *)malloc( (size_t) ((inExt.numRows + 1) * sizeof(char)) ); Info.nullPtr = NULL; Info.maxRows = (long) inExt.numRows; if( !Info.dataPtr ) { ffpmsg("Unable to allocate memory for row selection"); ffcprs(); FFUNLOCK; return( *status = MEMORY_ALLOCATION ); } /* make sure array is zero terminated */ ((char*)Info.dataPtr)[inExt.numRows] = 0; if( constant ) { /* Set all rows to the same value from constant result */ result = gParse.Nodes[gParse.resultNode].value.data.log; for( ntodo = 0; ntodo 1) ffirow( outfptr, outExt.numRows, nGood, status ); } do { if( ((char*)Info.dataPtr)[inloc-1] ) { ffgtbb( infptr, inloc, 1L, rdlen, buffer+rdlen*nbuff, status ); nbuff++; if( nbuff==maxrows ) { ffptbb( outfptr, outloc, 1L, rdlen*nbuff, buffer, status ); outloc += nbuff; nbuff = 0; } } inloc++; } while( !*status && inloc<=inExt.numRows ); if( nbuff ) { ffptbb( outfptr, outloc, 1L, rdlen*nbuff, buffer, status ); outloc += nbuff; } if( infptr==outfptr ) { if( outloc<=inExt.numRows ) ffdrow( infptr, outloc, inExt.numRows-outloc+1, status ); } else if( inExt.heapSize && nGood ) { /* Copy heap, if it exists and at least one row copied */ /********************************************************/ /* Get location information from the output extension */ /********************************************************/ if( outfptr->HDUposition != (outfptr->Fptr)->curhdu ) ffmahd( outfptr, (outfptr->HDUposition) + 1, NULL, status ); outExt.dataStart = (outfptr->Fptr)->datastart; outExt.heapStart = (outfptr->Fptr)->heapstart; /*************************************************/ /* Insert more space into outfptr if necessary */ /*************************************************/ hsize = outExt.heapStart + outExt.heapSize; freespace = (long) (( ( (hsize + 2879) / 2880) * 2880) - hsize); ntodo = inExt.heapSize; if ( (freespace - ntodo) < 0) { /* not enough existing space? */ ntodo = (ntodo - freespace + 2879) / 2880; /* number of blocks */ ffiblk(outfptr, (long) ntodo, 1, status); /* insert the blocks */ } ffukyj( outfptr, "PCOUNT", inExt.heapSize+outExt.heapSize, NULL, status ); /*******************************************************/ /* Get location information from the input extension */ /*******************************************************/ if( infptr->HDUposition != (infptr->Fptr)->curhdu ) ffmahd( infptr, (infptr->HDUposition) + 1, NULL, status ); inExt.dataStart = (infptr->Fptr)->datastart; inExt.heapStart = (infptr->Fptr)->heapstart; /**********************************/ /* Finally copy heap to outfptr */ /**********************************/ ntodo = inExt.heapSize; inbyteloc = inExt.heapStart + inExt.dataStart; outbyteloc = outExt.heapStart + outExt.dataStart + outExt.heapSize; while ( ntodo && !*status ) { rdlen = (long) minvalue(ntodo,500000); ffmbyt( infptr, inbyteloc, REPORT_EOF, status ); ffgbyt( infptr, rdlen, buffer, status ); ffmbyt( outfptr, outbyteloc, IGNORE_EOF, status ); ffpbyt( outfptr, rdlen, buffer, status ); inbyteloc += rdlen; outbyteloc += rdlen; ntodo -= rdlen; } /***********************************************************/ /* But must update DES if data is being appended to a */ /* pre-existing heap space. Edit each new entry in file */ /***********************************************************/ if( outExt.heapSize ) { LONGLONG repeat, offset, j; int i; for( i=1; i<=(outfptr->Fptr)->tfield; i++ ) { if( (outfptr->Fptr)->tableptr[i-1].tdatatype<0 ) { for( j=outExt.numRows+1; j<=outExt.numRows+nGood; j++ ) { ffgdesll( outfptr, i, j, &repeat, &offset, status ); offset += outExt.heapSize; ffpdes( outfptr, i, j, repeat, offset, status ); } } } } } /* End of HEAP copy */ FREE(buffer); } FREE(Info.dataPtr); ffcprs(); ffcmph(outfptr, status); /* compress heap, deleting any orphaned data */ FFUNLOCK; return(*status); } /*---------------------------------------------------------------------------*/ int ffcrow( fitsfile *fptr, /* I - Input FITS file */ int datatype, /* I - Datatype to return results as */ char *expr, /* I - Arithmetic expression */ long firstrow, /* I - First row to evaluate */ long nelements, /* I - Number of elements to return */ void *nulval, /* I - Ptr to value to use as UNDEF */ void *array, /* O - Array of results */ int *anynul, /* O - Were any UNDEFs encountered? */ int *status ) /* O - Error status */ /* */ /* Calculate an expression for the indicated rows of a table, returning */ /* the results, cast as datatype (TSHORT, TDOUBLE, etc), in array. If */ /* nulval==NULL, UNDEFs will be zeroed out. For vector results, the number */ /* of elements returned may be less than nelements if nelements is not an */ /* even multiple of the result dimension. Call fftexp to obtain the */ /* dimensions of the results. */ /*---------------------------------------------------------------------------*/ { parseInfo Info; int naxis; long nelem1, naxes[MAXDIMS]; if( *status ) return( *status ); FFLOCK; if( ffiprs( fptr, 0, expr, MAXDIMS, &Info.datatype, &nelem1, &naxis, naxes, status ) ) { ffcprs(); FFUNLOCK; return( *status ); } if( nelem1<0 ) nelem1 = - nelem1; if( nelements1 ? firstrow : 1); if( datatype ) Info.datatype = datatype; Info.dataPtr = array; Info.nullPtr = nulval; Info.maxRows = nelements / nelem1; if( ffiter( gParse.nCols, gParse.colData, firstrow-1, 0, parse_data, (void*)&Info, status ) == -1 ) *status=0; /* -1 indicates exitted without error before end... OK */ *anynul = Info.anyNull; ffcprs(); FFUNLOCK; return( *status ); } /*--------------------------------------------------------------------------*/ int ffcalc( fitsfile *infptr, /* I - Input FITS file */ char *expr, /* I - Arithmetic expression */ fitsfile *outfptr, /* I - Output fits file */ char *parName, /* I - Name of output parameter */ char *parInfo, /* I - Extra information on parameter */ int *status ) /* O - Error status */ /* */ /* Evaluate an expression for all rows of a table. Call ffcalc_rng with */ /* a row range of 1-MAX. */ { long start=1, end=LONG_MAX; return ffcalc_rng( infptr, expr, outfptr, parName, parInfo, 1, &start, &end, status ); } /*--------------------------------------------------------------------------*/ int ffcalc_rng( fitsfile *infptr, /* I - Input FITS file */ char *expr, /* I - Arithmetic expression */ fitsfile *outfptr, /* I - Output fits file */ char *parName, /* I - Name of output parameter */ char *parInfo, /* I - Extra information on parameter */ int nRngs, /* I - Row range info */ long *start, /* I - Row range info */ long *end, /* I - Row range info */ int *status ) /* O - Error status */ /* */ /* Evaluate an expression using the data in the input FITS file and place */ /* the results into either a column or keyword in the output fits file, */ /* depending on the value of parName (keywords normally prefixed with '#') */ /* and whether the expression evaluates to a constant or a table column. */ /* The logic is as follows: */ /* (1) If a column exists with name, parName, put results there. */ /* (2) If parName starts with '#', as in #NAXIS, put result there, */ /* with parInfo used as the comment. If expression does not evaluate */ /* to a constant, flag an error. */ /* (3) If a keyword exists with name, parName, and expression is a */ /* constant, put result there, using parInfo as the new comment. */ /* (4) Else, create a new column with name parName and TFORM parInfo. */ /* If parInfo is NULL, use a default data type for the column. */ /*--------------------------------------------------------------------------*/ { parseInfo Info; int naxis, constant, typecode, newNullKwd=0; long nelem, naxes[MAXDIMS], repeat, width; int col_cnt, colNo; Node *result; char card[81], tform[16], nullKwd[9], tdimKwd[9]; if( *status ) return( *status ); FFLOCK; if( ffiprs( infptr, 0, expr, MAXDIMS, &Info.datatype, &nelem, &naxis, naxes, status ) ) { ffcprs(); FFUNLOCK; return( *status ); } if( nelem<0 ) { constant = 1; nelem = -nelem; } else constant = 0; /* Case (1): If column exists put it there */ colNo = 0; if( ffgcno( outfptr, CASEINSEN, parName, &colNo, status )==COL_NOT_FOUND ) { /* Output column doesn't exist. Test for keyword. */ /* Case (2): Does parName indicate result should be put into keyword */ *status = 0; if( parName[0]=='#' ) { if( ! constant ) { ffcprs(); ffpmsg( "Cannot put tabular result into keyword (ffcalc)" ); FFUNLOCK; return( *status = PARSE_BAD_TYPE ); } parName++; /* Advance past '#' */ if ( (fits_strcasecmp(parName,"HISTORY") == 0 || fits_strcasecmp(parName,"COMMENT") == 0) && Info.datatype != TSTRING ) { ffcprs(); ffpmsg( "HISTORY and COMMENT values must be strings (ffcalc)" ); FFUNLOCK; return( *status = PARSE_BAD_TYPE ); } } else if( constant ) { /* Case (3): Does a keyword named parName already exist */ if( ffgcrd( outfptr, parName, card, status )==KEY_NO_EXIST ) { colNo = -1; } else if( *status ) { ffcprs(); FFUNLOCK; return( *status ); } } else colNo = -1; if( colNo<0 ) { /* Case (4): Create new column */ *status = 0; ffgncl( outfptr, &colNo, status ); colNo++; if( parInfo==NULL || *parInfo=='\0' ) { /* Figure out best default column type */ if( gParse.hdutype==BINARY_TBL ) { snprintf(tform,16,"%ld",nelem); switch( Info.datatype ) { case TLOGICAL: strcat(tform,"L"); break; case TLONG: strcat(tform,"J"); break; case TDOUBLE: strcat(tform,"D"); break; case TSTRING: strcat(tform,"A"); break; case TBIT: strcat(tform,"X"); break; case TLONGLONG: strcat(tform,"K"); break; } } else { switch( Info.datatype ) { case TLOGICAL: ffcprs(); ffpmsg("Cannot create LOGICAL column in ASCII table"); FFUNLOCK; return( *status = NOT_BTABLE ); case TLONG: strcpy(tform,"I11"); break; case TDOUBLE: strcpy(tform,"D23.15"); break; case TSTRING: case TBIT: snprintf(tform,16,"A%ld",nelem); break; } } parInfo = tform; } else if( !(isdigit((int) *parInfo)) && gParse.hdutype==BINARY_TBL ) { if( Info.datatype==TBIT && *parInfo=='B' ) nelem = (nelem+7)/8; snprintf(tform,16,"%ld%s",nelem,parInfo); parInfo = tform; } fficol( outfptr, colNo, parName, parInfo, status ); if( naxis>1 ) ffptdm( outfptr, colNo, naxis, naxes, status ); /* Setup TNULLn keyword in case NULLs are encountered */ ffkeyn("TNULL", colNo, nullKwd, status); if( ffgcrd( outfptr, nullKwd, card, status )==KEY_NO_EXIST ) { *status = 0; if( gParse.hdutype==BINARY_TBL ) { LONGLONG nullVal=0; fits_binary_tform( parInfo, &typecode, &repeat, &width, status ); if( typecode==TBYTE ) nullVal = UCHAR_MAX; else if( typecode==TSHORT ) nullVal = SHRT_MIN; else if( typecode==TINT ) nullVal = INT_MIN; else if( typecode==TLONG ) nullVal = LONG_MIN; else if( typecode==TLONGLONG ) nullVal = LONGLONG_MIN; if( nullVal ) { ffpkyj( outfptr, nullKwd, nullVal, "Null value", status ); fits_set_btblnull( outfptr, colNo, nullVal, status ); newNullKwd = 1; } } else if( gParse.hdutype==ASCII_TBL ) { ffpkys( outfptr, nullKwd, "NULL", "Null value string", status ); fits_set_atblnull( outfptr, colNo, "NULL", status ); newNullKwd = 1; } } } } else if( *status ) { ffcprs(); FFUNLOCK; return( *status ); } else { /********************************************************/ /* Check if a TDIM keyword should be written/updated. */ /********************************************************/ ffkeyn("TDIM", colNo, tdimKwd, status); ffgcrd( outfptr, tdimKwd, card, status ); if( *status==0 ) { /* TDIM exists, so update it with result's dimension */ ffptdm( outfptr, colNo, naxis, naxes, status ); } else if( *status==KEY_NO_EXIST ) { /* TDIM does not exist, so clear error stack and */ /* write a TDIM only if result is multi-dimensional */ *status = 0; ffcmsg(); if( naxis>1 ) ffptdm( outfptr, colNo, naxis, naxes, status ); } if( *status ) { /* Either some other error happened in ffgcrd */ /* or one happened in ffptdm */ ffcprs(); FFUNLOCK; return( *status ); } } if( colNo>0 ) { /* Output column exists (now)... put results into it */ int anyNull = 0; int nPerLp, i; long totaln; ffgkyj(infptr, "NAXIS2", &totaln, 0, status); /*************************************/ /* Create new iterator Output Column */ /*************************************/ col_cnt = gParse.nCols; if( allocateCol( col_cnt, status ) ) { ffcprs(); FFUNLOCK; return( *status ); } fits_iter_set_by_num( gParse.colData+col_cnt, outfptr, colNo, 0, OutputCol ); gParse.nCols++; for( i=0; i= 10) && (nRngs == 1) && (start[0] == 1) && (end[0] == totaln)) nPerLp = 0; else nPerLp = Info.maxRows; if( ffiter( gParse.nCols, gParse.colData, start[i]-1, nPerLp, parse_data, (void*)&Info, status ) == -1 ) *status = 0; else if( *status ) { ffcprs(); FFUNLOCK; return( *status ); } if( Info.anyNull ) anyNull = 1; } if( newNullKwd && !anyNull ) { ffdkey( outfptr, nullKwd, status ); } } else { /* Put constant result into keyword */ result = gParse.Nodes + gParse.resultNode; switch( Info.datatype ) { case TDOUBLE: ffukyd( outfptr, parName, result->value.data.dbl, 15, parInfo, status ); break; case TLONG: ffukyj( outfptr, parName, result->value.data.lng, parInfo, status ); break; case TLOGICAL: ffukyl( outfptr, parName, result->value.data.log, parInfo, status ); break; case TBIT: case TSTRING: if (fits_strcasecmp(parName,"HISTORY") == 0) { ffphis( outfptr, result->value.data.str, status); } else if (fits_strcasecmp(parName,"COMMENT") == 0) { ffpcom( outfptr, result->value.data.str, status); } else { ffukys( outfptr, parName, result->value.data.str, parInfo, status ); } break; } } ffcprs(); FFUNLOCK; return( *status ); } /*--------------------------------------------------------------------------*/ int fftexp( fitsfile *fptr, /* I - Input FITS file */ char *expr, /* I - Arithmetic expression */ int maxdim, /* I - Max Dimension of naxes */ int *datatype, /* O - Data type of result */ long *nelem, /* O - Vector length of result */ int *naxis, /* O - # of dimensions of result */ long *naxes, /* O - Size of each dimension */ int *status ) /* O - Error status */ /* */ /* Evaluate the given expression and return information on the result. */ /*--------------------------------------------------------------------------*/ { FFLOCK; ffiprs( fptr, 0, expr, maxdim, datatype, nelem, naxis, naxes, status ); ffcprs(); FFUNLOCK; return( *status ); } /*--------------------------------------------------------------------------*/ int ffiprs( fitsfile *fptr, /* I - Input FITS file */ int compressed, /* I - Is FITS file hkunexpanded? */ char *expr, /* I - Arithmetic expression */ int maxdim, /* I - Max Dimension of naxes */ int *datatype, /* O - Data type of result */ long *nelem, /* O - Vector length of result */ int *naxis, /* O - # of dimensions of result */ long *naxes, /* O - Size of each dimension */ int *status ) /* O - Error status */ /* */ /* Initialize the parser and determine what type of result the expression */ /* produces. */ /*--------------------------------------------------------------------------*/ { Node *result; int i,lexpr, tstatus = 0; int xaxis, bitpix; long xaxes[9]; static iteratorCol dmyCol; if( *status ) return( *status ); /* make sure all internal structures for this HDU are current */ if ( ffrdef(fptr, status) ) return(*status); /* Initialize the Parser structure */ gParse.def_fptr = fptr; gParse.compressed = compressed; gParse.nCols = 0; gParse.colData = NULL; gParse.varData = NULL; gParse.getData = find_column; gParse.loadData = load_column; gParse.Nodes = NULL; gParse.nNodesAlloc= 0; gParse.nNodes = 0; gParse.hdutype = 0; gParse.status = 0; fits_get_hdu_type(fptr, &gParse.hdutype, status ); if (gParse.hdutype == IMAGE_HDU) { fits_get_img_param(fptr, 9, &bitpix, &xaxis, xaxes, status); if (*status) { ffpmsg("ffiprs: unable to get image dimensions"); return( *status ); } gParse.totalRows = xaxis > 0 ? 1 : 0; for (i = 0; i < xaxis; ++i) gParse.totalRows *= xaxes[i]; if (DEBUG_PIXFILTER) printf("naxis=%d, gParse.totalRows=%ld\n", xaxis, gParse.totalRows); } else if( ffgkyj(fptr, "NAXIS2", &gParse.totalRows, 0, &tstatus) ) { /* this might be a 1D or null image with no NAXIS2 keyword */ gParse.totalRows = 0; } /* Copy expression into parser... read from file if necessary */ if( expr[0]=='@' ) { if( ffimport_file( expr+1, &gParse.expr, status ) ) return( *status ); lexpr = strlen(gParse.expr); } else { lexpr = strlen(expr); gParse.expr = (char*)malloc( (2+lexpr)*sizeof(char)); strcpy(gParse.expr,expr); } strcat(gParse.expr + lexpr,"\n"); gParse.index = 0; gParse.is_eobuf = 0; /* Parse the expression, building the Nodes and determing */ /* which columns are needed and what data type is returned */ ffrestart(NULL); if( ffparse() ) { return( *status = PARSE_SYNTAX_ERR ); } /* Check results */ *status = gParse.status; if( *status ) return(*status); if( !gParse.nNodes ) { ffpmsg("Blank expression"); return( *status = PARSE_SYNTAX_ERR ); } if( !gParse.nCols ) { dmyCol.fptr = fptr; /* This allows iterator to know value of */ gParse.colData = &dmyCol; /* fptr when no columns are referenced */ } result = gParse.Nodes + gParse.resultNode; *naxis = result->value.naxis; *nelem = result->value.nelem; for( i=0; i<*naxis && ivalue.naxes[i]; switch( result->type ) { case BOOLEAN: *datatype = TLOGICAL; break; case LONG: *datatype = TLONG; break; case DOUBLE: *datatype = TDOUBLE; break; case BITSTR: *datatype = TBIT; break; case STRING: *datatype = TSTRING; break; default: *datatype = 0; ffpmsg("Bad return data type"); *status = gParse.status = PARSE_BAD_TYPE; break; } gParse.datatype = *datatype; FREE(gParse.expr); if( result->operation==CONST_OP ) *nelem = - *nelem; return(*status); } /*--------------------------------------------------------------------------*/ void ffcprs( void ) /* No parameters */ /* */ /* Clear the parser, making it ready to accept a new expression. */ /*--------------------------------------------------------------------------*/ { int col, node, i; if( gParse.nCols > 0 ) { FREE( gParse.colData ); for( col=0; col 0 ) { node = gParse.nNodes; while( node-- ) { if( gParse.Nodes[node].operation==gtifilt_fct ) { i = gParse.Nodes[node].SubNodes[0]; if (gParse.Nodes[ i ].value.data.ptr) FREE( gParse.Nodes[ i ].value.data.ptr ); } else if( gParse.Nodes[node].operation==regfilt_fct ) { i = gParse.Nodes[node].SubNodes[0]; fits_free_region( (SAORegion *)gParse.Nodes[ i ].value.data.ptr ); } } gParse.nNodes = 0; } if( gParse.Nodes ) free( gParse.Nodes ); gParse.Nodes = NULL; gParse.hdutype = ANY_HDU; gParse.pixFilter = 0; } /*---------------------------------------------------------------------------*/ int parse_data( long totalrows, /* I - Total rows to be processed */ long offset, /* I - Number of rows skipped at start*/ long firstrow, /* I - First row of this iteration */ long nrows, /* I - Number of rows in this iter */ int nCols, /* I - Number of columns in use */ iteratorCol *colData, /* IO- Column information/data */ void *userPtr ) /* I - Data handling instructions */ /* */ /* Iterator work function which calls the parser and copies the results */ /* into either an OutputCol or a data pointer supplied in the userPtr */ /* structure. */ /*---------------------------------------------------------------------------*/ { int status, constant=0, anyNullThisTime=0; long jj, kk, idx, remain, ntodo; Node *result; iteratorCol * outcol; /* declare variables static to preserve their values between calls */ static void *Data, *Null; static int datasize; static long lastRow, repeat, resDataSize; static LONGLONG jnull; static parseInfo *userInfo; static long zeros[4] = {0,0,0,0}; if (DEBUG_PIXFILTER) printf("parse_data(total=%ld, offset=%ld, first=%ld, rows=%ld, cols=%d)\n", totalrows, offset, firstrow, nrows, nCols); /*--------------------------------------------------------*/ /* Initialization procedures: execute on the first call */ /*--------------------------------------------------------*/ outcol = colData + (nCols - 1); if (firstrow == offset+1) { userInfo = (parseInfo*)userPtr; userInfo->anyNull = 0; if( userInfo->maxRows>0 ) userInfo->maxRows = minvalue(totalrows,userInfo->maxRows); else if( userInfo->maxRows<0 ) userInfo->maxRows = totalrows; else userInfo->maxRows = nrows; lastRow = firstrow + userInfo->maxRows - 1; if( userInfo->dataPtr==NULL ) { if( outcol->iotype == InputCol ) { ffpmsg("Output column for parser results not found!"); return( PARSE_NO_OUTPUT ); } /* Data gets set later */ Null = outcol->array; userInfo->datatype = outcol->datatype; /* Check for a TNULL/BLANK keyword for output column/image */ status = 0; jnull = 0; if (gParse.hdutype == IMAGE_HDU) { if (gParse.pixFilter->blank) jnull = (LONGLONG) gParse.pixFilter->blank; } else { ffgknjj( outcol->fptr, "TNULL", outcol->colnum, 1, &jnull, (int*)&jj, &status ); if( status==BAD_INTKEY ) { /* Probably ASCII table with text TNULL keyword */ switch( userInfo->datatype ) { case TSHORT: jnull = (LONGLONG) SHRT_MIN; break; case TINT: jnull = (LONGLONG) INT_MIN; break; case TLONG: jnull = (LONGLONG) LONG_MIN; break; } } } repeat = outcol->repeat; /* if (DEBUG_PIXFILTER) printf("parse_data: using null value %ld\n", jnull); */ } else { Data = userInfo->dataPtr; Null = (userInfo->nullPtr ? userInfo->nullPtr : zeros); repeat = gParse.Nodes[gParse.resultNode].value.nelem; } /* Determine the size of each element of the returned result */ switch( userInfo->datatype ) { case TBIT: /* Fall through to TBYTE */ case TLOGICAL: /* Fall through to TBYTE */ case TBYTE: datasize = sizeof(char); break; case TSHORT: datasize = sizeof(short); break; case TINT: datasize = sizeof(int); break; case TLONG: datasize = sizeof(long); break; case TLONGLONG: datasize = sizeof(LONGLONG); break; case TFLOAT: datasize = sizeof(float); break; case TDOUBLE: datasize = sizeof(double); break; case TSTRING: datasize = sizeof(char*); break; } /* Determine the size of each element of the calculated result */ /* (only matters for numeric/logical data) */ switch( gParse.Nodes[gParse.resultNode].type ) { case BOOLEAN: resDataSize = sizeof(char); break; case LONG: resDataSize = sizeof(long); break; case DOUBLE: resDataSize = sizeof(double); break; } } /*-------------------------------------------*/ /* Main loop: process all the rows of data */ /*-------------------------------------------*/ /* If writing to output column, set first element to appropriate */ /* null value. If no NULLs encounter, zero out before returning. */ /* if (DEBUG_PIXFILTER) printf("parse_data: using null value %ld\n", jnull); */ if( userInfo->dataPtr == NULL ) { /* First, reset Data pointer to start of output array */ Data = (char*) outcol->array + datasize; switch( userInfo->datatype ) { case TLOGICAL: *(char *)Null = 'U'; break; case TBYTE: *(char *)Null = (char )jnull; break; case TSHORT: *(short *)Null = (short)jnull; break; case TINT: *(int *)Null = (int )jnull; break; case TLONG: *(long *)Null = (long )jnull; break; case TLONGLONG: *(LONGLONG *)Null = (LONGLONG )jnull; break; case TFLOAT: *(float *)Null = FLOATNULLVALUE; break; case TDOUBLE: *(double*)Null = DOUBLENULLVALUE; break; case TSTRING: (*(char **)Null)[0] = '\1'; (*(char **)Null)[1] = '\0'; break; } } /* Alter nrows in case calling routine didn't want to do all rows */ nrows = minvalue(nrows,lastRow-firstrow+1); Setup_DataArrays( nCols, colData, firstrow, nrows ); /* Parser allocates arrays for each column and calculation it performs. */ /* Limit number of rows processed during each pass to reduce memory */ /* requirements... In most cases, iterator will limit rows to less */ /* than 2500 rows per iteration, so this is really only relevant for */ /* hk-compressed files which must be decompressed in memory and sent */ /* whole to parse_data in a single iteration. */ remain = nrows; while( remain ) { ntodo = minvalue(remain,2500); Evaluate_Parser ( firstrow, ntodo ); if( gParse.status ) break; firstrow += ntodo; remain -= ntodo; /* Copy results into data array */ result = gParse.Nodes + gParse.resultNode; if( result->operation==CONST_OP ) constant = 1; switch( result->type ) { case BOOLEAN: case LONG: case DOUBLE: if( constant ) { char undef=0; for( kk=0; kkvalue.data), &undef, result->value.nelem /* 1 */, userInfo->datatype, Null, (char*)Data + (kk*repeat+jj)*datasize, &anyNullThisTime, &gParse.status ); } else { if ( repeat == result->value.nelem ) { ffcvtn( gParse.datatype, result->value.data.ptr, result->value.undef, result->value.nelem*ntodo, userInfo->datatype, Null, Data, &anyNullThisTime, &gParse.status ); } else if( result->value.nelem == 1 ) { for( kk=0; kkvalue.data.ptr + kk*resDataSize, (char*)result->value.undef + kk, 1, userInfo->datatype, Null, (char*)Data + (kk*repeat+jj)*datasize, &anyNullThisTime, &gParse.status ); } } else { int nCopy; nCopy = minvalue( repeat, result->value.nelem ); for( kk=0; kkvalue.data.ptr + kk*result->value.nelem*resDataSize, (char*)result->value.undef + kk*result->value.nelem, nCopy, userInfo->datatype, Null, (char*)Data + (kk*repeat)*datasize, &anyNullThisTime, &gParse.status ); if( nCopy < repeat ) { memset( (char*)Data + (kk*repeat+nCopy)*datasize, 0, (repeat-nCopy)*datasize); } } } if( result->operation>0 ) { FREE( result->value.data.ptr ); } } if( gParse.status==OVERFLOW_ERR ) { gParse.status = NUM_OVERFLOW; ffpmsg("Numerical overflow while converting expression to necessary datatype"); } break; case BITSTR: switch( userInfo->datatype ) { case TBYTE: idx = -1; for( kk=0; kkvalue.nelem; jj++ ) { if( jj%8 == 0 ) ((char*)Data)[++idx] = 0; if( constant ) { if( result->value.data.str[jj]=='1' ) ((char*)Data)[idx] |= 128>>(jj%8); } else { if( result->value.data.strptr[kk][jj]=='1' ) ((char*)Data)[idx] |= 128>>(jj%8); } } } break; case TBIT: case TLOGICAL: if( constant ) { for( kk=0; kkvalue.nelem; jj++ ) { ((char*)Data)[ jj+kk*result->value.nelem ] = ( result->value.data.str[jj]=='1' ); } } else { for( kk=0; kkvalue.nelem; jj++ ) { ((char*)Data)[ jj+kk*result->value.nelem ] = ( result->value.data.strptr[kk][jj]=='1' ); } } break; case TSTRING: if( constant ) { for( jj=0; jjvalue.data.str ); } } else { for( jj=0; jjvalue.data.strptr[jj] ); } } break; default: ffpmsg("Cannot convert bit expression to desired type."); gParse.status = PARSE_BAD_TYPE; break; } if( result->operation>0 ) { FREE( result->value.data.strptr[0] ); FREE( result->value.data.strptr ); } break; case STRING: if( userInfo->datatype==TSTRING ) { if( constant ) { for( jj=0; jjvalue.data.str ); } else { for( jj=0; jjvalue.undef[jj] ) { anyNullThisTime = 1; strcpy( ((char**)Data)[jj], *(char **)Null ); } else { strcpy( ((char**)Data)[jj], result->value.data.strptr[jj] ); } } } else { ffpmsg("Cannot convert string expression to desired type."); gParse.status = PARSE_BAD_TYPE; } if( result->operation>0 ) { FREE( result->value.data.strptr[0] ); FREE( result->value.data.strptr ); } break; } if( gParse.status ) break; /* Increment Data to point to where the next block should go */ if( result->type==BITSTR && userInfo->datatype==TBYTE ) Data = (char*)Data + datasize * ( (result->value.nelem+7)/8 ) * ntodo; else if( result->type==STRING ) Data = (char*)Data + datasize * ntodo; else Data = (char*)Data + datasize * ntodo * repeat; } /* If no NULLs encountered during this pass, set Null value to */ /* zero to make the writing of the output column data faster */ if( anyNullThisTime ) userInfo->anyNull = 1; else if( userInfo->dataPtr == NULL ) { if( userInfo->datatype == TSTRING ) memcpy( *(char **)Null, zeros, 2 ); else memcpy( Null, zeros, datasize ); } /*-------------------------------------------------------*/ /* Clean up procedures: after processing all the rows */ /*-------------------------------------------------------*/ /* if the calling routine specified that only a limited number */ /* of rows in the table should be processed, return a value of -1 */ /* once all the rows have been done, if no other error occurred. */ if (gParse.hdutype != IMAGE_HDU && firstrow - 1 == lastRow) { if (!gParse.status && userInfo->maxRowsiotype == OutputCol ) continue; nelem = varData->nelem; len = nelem * nRows; switch ( varData->type ) { case BITSTR: /* No need for UNDEF array, but must make string DATA array */ len = (nelem+1)*nRows; /* Count '\0' */ bitStrs = (char**)varData->data; if( bitStrs ) FREE( bitStrs[0] ); free( bitStrs ); bitStrs = (char**)malloc( nRows*sizeof(char*) ); if( bitStrs==NULL ) { varData->data = varData->undef = NULL; gParse.status = MEMORY_ALLOCATION; break; } bitStrs[0] = (char*)malloc( len*sizeof(char) ); if( bitStrs[0]==NULL ) { free( bitStrs ); varData->data = varData->undef = NULL; gParse.status = MEMORY_ALLOCATION; break; } for( row=0; rowarray)[idx] & (1<<(7-len%8)) ) bitStrs[row][len] = '1'; else bitStrs[row][len] = '0'; if( len%8==7 ) idx++; } bitStrs[row][len] = '\0'; } varData->undef = (char*)bitStrs; varData->data = (char*)bitStrs; break; case STRING: sptr = (char**)icol->array; if (varData->undef) free( varData->undef ); varData->undef = (char*)malloc( nRows*sizeof(char) ); if( varData->undef==NULL ) { gParse.status = MEMORY_ALLOCATION; break; } row = nRows; while( row-- ) varData->undef[row] = ( **sptr != '\0' && FSTRCMP( sptr[0], sptr[row+1] )==0 ); varData->data = sptr + 1; break; case BOOLEAN: barray = (char*)icol->array; if (varData->undef) free( varData->undef ); varData->undef = (char*)malloc( len*sizeof(char) ); if( varData->undef==NULL ) { gParse.status = MEMORY_ALLOCATION; break; } while( len-- ) { varData->undef[len] = ( barray[0]!=0 && barray[0]==barray[len+1] ); } varData->data = barray + 1; break; case LONG: iarray = (long*)icol->array; if (varData->undef) free( varData->undef ); varData->undef = (char*)malloc( len*sizeof(char) ); if( varData->undef==NULL ) { gParse.status = MEMORY_ALLOCATION; break; } while( len-- ) { varData->undef[len] = ( iarray[0]!=0L && iarray[0]==iarray[len+1] ); } varData->data = iarray + 1; break; case DOUBLE: rarray = (double*)icol->array; if (varData->undef) free( varData->undef ); varData->undef = (char*)malloc( len*sizeof(char) ); if( varData->undef==NULL ) { gParse.status = MEMORY_ALLOCATION; break; } while( len-- ) { varData->undef[len] = ( rarray[0]!=0.0 && rarray[0]==rarray[len+1]); } varData->data = rarray + 1; break; default: snprintf(msg, 80, "SetupDataArrays, unhandled type %d\n", varData->type); ffpmsg(msg); } if( gParse.status ) { /* Deallocate NULL arrays of previous columns */ while( i-- ) { varData = gParse.varData + i; if( varData->type==BITSTR ) FREE( ((char**)varData->data)[0] ); FREE( varData->undef ); varData->undef = NULL; } return; } } } /*--------------------------------------------------------------------------*/ int ffcvtn( int inputType, /* I - Data type of input array */ void *input, /* I - Input array of type inputType */ char *undef, /* I - Array of flags indicating UNDEF elems */ long ntodo, /* I - Number of elements to process */ int outputType, /* I - Data type of output array */ void *nulval, /* I - Ptr to value to use for UNDEF elements */ void *output, /* O - Output array of type outputType */ int *anynull, /* O - Any nulls flagged? */ int *status ) /* O - Error status */ /* */ /* Convert an array of any input data type to an array of any output */ /* data type, using an array of UNDEF flags to assign nulvals to */ /*--------------------------------------------------------------------------*/ { long i; switch( outputType ) { case TLOGICAL: switch( inputType ) { case TLOGICAL: case TBYTE: for( i=0; i UCHAR_MAX ) { *status = OVERFLOW_ERR; ((unsigned char*)output)[i] = UCHAR_MAX; } else ((unsigned char*)output)[i] = (unsigned char) ((long*)input)[i]; } } return( *status ); case TFLOAT: fffr4i1((float*)input,ntodo,1.,0.,0,0,NULL,NULL, (unsigned char*)output,status); break; case TDOUBLE: fffr8i1((double*)input,ntodo,1.,0.,0,0,NULL,NULL, (unsigned char*)output,status); break; default: *status = BAD_DATATYPE; break; } for(i=0;i SHRT_MAX ) { *status = OVERFLOW_ERR; ((short*)output)[i] = SHRT_MAX; } else ((short*)output)[i] = (short) ((long*)input)[i]; } } return( *status ); case TFLOAT: fffr4i2((float*)input,ntodo,1.,0.,0,0,NULL,NULL, (short*)output,status); break; case TDOUBLE: fffr8i2((double*)input,ntodo,1.,0.,0,0,NULL,NULL, (short*)output,status); break; default: *status = BAD_DATATYPE; break; } for(i=0;i=0 ) { found[parNo] = 1; /* Flag this parameter as found */ switch( gParse.colData[parNo].datatype ) { case TLONG: ffgcvj( fptr, gParse.valCol, row, 1L, 1L, ((long*)gParse.colData[parNo].array)[0], ((long*)gParse.colData[parNo].array)+currelem, &anynul, status ); break; case TDOUBLE: ffgcvd( fptr, gParse.valCol, row, 1L, 1L, ((double*)gParse.colData[parNo].array)[0], ((double*)gParse.colData[parNo].array)+currelem, &anynul, status ); break; case TSTRING: ffgcvs( fptr, gParse.valCol, row, 1L, 1L, ((char**)gParse.colData[parNo].array)[0], ((char**)gParse.colData[parNo].array)+currelem, &anynul, status ); break; } if( *status ) return( *status ); } } if( currelemoperation==CONST_OP ) { if( result->value.data.log ) { *(long*)userPtr = firstrow; return( -1 ); } } else { for( idx=0; idxvalue.data.logptr[idx] && !result->value.undef[idx] ) { *(long*)userPtr = firstrow + idx; return( -1 ); } } } return( gParse.status ); } static int set_image_col_types (fitsfile * fptr, const char * name, int bitpix, DataInfo * varInfo, iteratorCol *colIter) { int istatus; double tscale, tzero; char temp[80]; switch (bitpix) { case BYTE_IMG: case SHORT_IMG: case LONG_IMG: istatus = 0; if (fits_read_key(fptr, TDOUBLE, "BZERO", &tzero, NULL, &istatus)) tzero = 0.0; istatus = 0; if (fits_read_key(fptr, TDOUBLE, "BSCALE", &tscale, NULL, &istatus)) tscale = 1.0; if (tscale == 1.0 && (tzero == 0.0 || tzero == 32768.0 )) { varInfo->type = LONG; colIter->datatype = TLONG; } else { varInfo->type = DOUBLE; colIter->datatype = TDOUBLE; if (DEBUG_PIXFILTER) printf("use DOUBLE for %s with BSCALE=%g/BZERO=%g\n", name, tscale, tzero); } break; case LONGLONG_IMG: case FLOAT_IMG: case DOUBLE_IMG: varInfo->type = DOUBLE; colIter->datatype = TDOUBLE; break; default: snprintf(temp, 80,"set_image_col_types: unrecognized image bitpix [%d]\n", bitpix); ffpmsg(temp); return gParse.status = PARSE_BAD_TYPE; } return 0; } /************************************************************************* Functions used by the evaluator to access FITS data (find_column, find_keywd, allocateCol, load_column) *************************************************************************/ static int find_column( char *colName, void *itslval ) { FFSTYPE *thelval = (FFSTYPE*)itslval; int col_cnt, status; int colnum, typecode, type; long repeat, width; fitsfile *fptr; char temp[80]; double tzero,tscale; int istatus; DataInfo *varInfo; iteratorCol *colIter; if (DEBUG_PIXFILTER) printf("find_column(%s)\n", colName); if( *colName == '#' ) return( find_keywd( colName + 1, itslval ) ); fptr = gParse.def_fptr; status = 0; col_cnt = gParse.nCols; if (gParse.hdutype == IMAGE_HDU) { int i; if (!gParse.pixFilter) { gParse.status = COL_NOT_FOUND; ffpmsg("find_column: IMAGE_HDU but no PixelFilter"); return pERROR; } colnum = -1; for (i = 0; i < gParse.pixFilter->count; ++i) { if (!fits_strcasecmp(colName, gParse.pixFilter->tag[i])) colnum = i; } if (colnum < 0) { snprintf(temp, 80, "find_column: PixelFilter tag %s not found", colName); ffpmsg(temp); gParse.status = COL_NOT_FOUND; return pERROR; } if( allocateCol( col_cnt, &gParse.status ) ) return pERROR; varInfo = gParse.varData + col_cnt; colIter = gParse.colData + col_cnt; fptr = gParse.pixFilter->ifptr[colnum]; fits_get_img_param(fptr, MAXDIMS, &typecode, /* actually bitpix */ &varInfo->naxis, &varInfo->naxes[0], &status); varInfo->nelem = 1; type = COLUMN; if (set_image_col_types(fptr, colName, typecode, varInfo, colIter)) return pERROR; colIter->fptr = fptr; colIter->iotype = InputCol; } else { /* HDU holds a table */ if( gParse.compressed ) colnum = gParse.valCol; else if( fits_get_colnum( fptr, CASEINSEN, colName, &colnum, &status ) ) { if( status == COL_NOT_FOUND ) { type = find_keywd( colName, itslval ); if( type != pERROR ) ffcmsg(); return( type ); } gParse.status = status; return pERROR; } if( fits_get_coltype( fptr, colnum, &typecode, &repeat, &width, &status ) ) { gParse.status = status; return pERROR; } if( allocateCol( col_cnt, &gParse.status ) ) return pERROR; varInfo = gParse.varData + col_cnt; colIter = gParse.colData + col_cnt; fits_iter_set_by_num( colIter, fptr, colnum, 0, InputCol ); } /* Make sure we don't overflow variable name array */ strncpy(varInfo->name,colName,MAXVARNAME); varInfo->name[MAXVARNAME] = '\0'; if (gParse.hdutype != IMAGE_HDU) { switch( typecode ) { case TBIT: varInfo->type = BITSTR; colIter->datatype = TBYTE; type = BITCOL; break; case TBYTE: case TSHORT: case TLONG: /* The datatype of column with TZERO and TSCALE keywords might be float or double. */ snprintf(temp,80,"TZERO%d",colnum); istatus = 0; if(fits_read_key(fptr,TDOUBLE,temp,&tzero,NULL,&istatus)) { tzero = 0.0; } snprintf(temp,80,"TSCAL%d",colnum); istatus = 0; if(fits_read_key(fptr,TDOUBLE,temp,&tscale,NULL,&istatus)) { tscale = 1.0; } if (tscale == 1.0 && (tzero == 0.0 || tzero == 32768.0 )) { varInfo->type = LONG; colIter->datatype = TLONG; /* Reading an unsigned long column as a long can cause overflow errors. Treat the column as a double instead. } else if (tscale == 1.0 && tzero == 2147483648.0 ) { varInfo->type = LONG; colIter->datatype = TULONG; */ } else { varInfo->type = DOUBLE; colIter->datatype = TDOUBLE; } type = COLUMN; break; /* For now, treat 8-byte integer columns as type double. This can lose precision, so the better long term solution will be to add support for TLONGLONG as a separate datatype. */ case TLONGLONG: case TFLOAT: case TDOUBLE: varInfo->type = DOUBLE; colIter->datatype = TDOUBLE; type = COLUMN; break; case TLOGICAL: varInfo->type = BOOLEAN; colIter->datatype = TLOGICAL; type = BCOLUMN; break; case TSTRING: varInfo->type = STRING; colIter->datatype = TSTRING; type = SCOLUMN; if ( width >= MAX_STRLEN ) { snprintf(temp, 80, "column %d is wider than maximum %d characters", colnum, MAX_STRLEN-1); ffpmsg(temp); gParse.status = PARSE_LRG_VECTOR; return pERROR; } if( gParse.hdutype == ASCII_TBL ) repeat = width; break; default: if (typecode < 0) { snprintf(temp, 80,"variable-length array columns are not supported. typecode = %d", typecode); ffpmsg(temp); } gParse.status = PARSE_BAD_TYPE; return pERROR; } varInfo->nelem = repeat; if( repeat>1 && typecode!=TSTRING ) { if( fits_read_tdim( fptr, colnum, MAXDIMS, &varInfo->naxis, &varInfo->naxes[0], &status ) ) { gParse.status = status; return pERROR; } } else { varInfo->naxis = 1; varInfo->naxes[0] = 1; } } gParse.nCols++; thelval->lng = col_cnt; return( type ); } static int find_keywd(char *keyname, void *itslval ) { FFSTYPE *thelval = (FFSTYPE*)itslval; int status, type; char keyvalue[FLEN_VALUE], dtype; fitsfile *fptr; double rval; int bval; long ival; status = 0; fptr = gParse.def_fptr; if( fits_read_keyword( fptr, keyname, keyvalue, NULL, &status ) ) { if( status == KEY_NO_EXIST ) { /* Do this since ffgkey doesn't put an error message on stack */ snprintf(keyvalue,FLEN_VALUE, "ffgkey could not find keyword: %s",keyname); ffpmsg(keyvalue); } gParse.status = status; return( pERROR ); } if( fits_get_keytype( keyvalue, &dtype, &status ) ) { gParse.status = status; return( pERROR ); } switch( dtype ) { case 'C': fits_read_key_str( fptr, keyname, keyvalue, NULL, &status ); type = STRING; strcpy( thelval->str , keyvalue ); break; case 'L': fits_read_key_log( fptr, keyname, &bval, NULL, &status ); type = BOOLEAN; thelval->log = bval; break; case 'I': fits_read_key_lng( fptr, keyname, &ival, NULL, &status ); type = LONG; thelval->lng = ival; break; case 'F': fits_read_key_dbl( fptr, keyname, &rval, NULL, &status ); type = DOUBLE; thelval->dbl = rval; break; default: type = pERROR; break; } if( status ) { gParse.status=status; return pERROR; } return( type ); } static int allocateCol( int nCol, int *status ) { if( (nCol%25)==0 ) { if( nCol ) { gParse.colData = (iteratorCol*) realloc( gParse.colData, (nCol+25)*sizeof(iteratorCol) ); gParse.varData = (DataInfo *) realloc( gParse.varData, (nCol+25)*sizeof(DataInfo) ); } else { gParse.colData = (iteratorCol*) malloc( 25*sizeof(iteratorCol) ); gParse.varData = (DataInfo *) malloc( 25*sizeof(DataInfo) ); } if( gParse.colData == NULL || gParse.varData == NULL ) { if( gParse.colData ) free(gParse.colData); if( gParse.varData ) free(gParse.varData); gParse.colData = NULL; gParse.varData = NULL; return( *status = MEMORY_ALLOCATION ); } } gParse.varData[nCol].data = NULL; gParse.varData[nCol].undef = NULL; return 0; } static int load_column( int varNum, long fRow, long nRows, void *data, char *undef ) { iteratorCol *var = gParse.colData+varNum; long nelem,nbytes,row,len,idx; char **bitStrs, msg[80]; unsigned char *bytes; int status = 0, anynul; if (gParse.hdutype == IMAGE_HDU) { /* This test would need to be on a per varNum basis to support * cross HDU operations */ fits_read_imgnull(var->fptr, var->datatype, fRow, nRows, data, undef, &anynul, &status); if (DEBUG_PIXFILTER) printf("load_column: IMAGE_HDU fRow=%ld, nRows=%ld => %d\n", fRow, nRows, status); } else { nelem = nRows * var->repeat; switch( var->datatype ) { case TBYTE: nbytes = ((var->repeat+7)/8) * nRows; bytes = (unsigned char *)malloc( nbytes * sizeof(char) ); ffgcvb(var->fptr, var->colnum, fRow, 1L, nbytes, 0, bytes, &anynul, &status); nelem = var->repeat; bitStrs = (char **)data; for( row=0; rowfptr, var->colnum, fRow, 1L, nRows, (char **)data, undef, &anynul, &status); break; case TLOGICAL: ffgcfl(var->fptr, var->colnum, fRow, 1L, nelem, (char *)data, undef, &anynul, &status); break; case TLONG: ffgcfj(var->fptr, var->colnum, fRow, 1L, nelem, (long *)data, undef, &anynul, &status); break; case TDOUBLE: ffgcfd(var->fptr, var->colnum, fRow, 1L, nelem, (double *)data, undef, &anynul, &status); break; default: snprintf(msg,80,"load_column: unexpected datatype %d", var->datatype); ffpmsg(msg); } } if( status ) { gParse.status = status; return pERROR; } return 0; } /*--------------------------------------------------------------------------*/ int fits_pixel_filter (PixelFilter * filter, int * status) /* Evaluate an expression using the data in the input FITS file(s) */ /*--------------------------------------------------------------------------*/ { parseInfo Info = { 0 }; int naxis, bitpix; long nelem, naxes[MAXDIMS]; int col_cnt; Node *result; int datatype; fitsfile * infptr; fitsfile * outfptr; char * DEFAULT_TAGS[] = { "X" }; char msg[256]; int writeBlankKwd = 0; /* write BLANK if any output nulls? */ DEBUG_PIXFILTER = getenv("DEBUG_PIXFILTER") ? 1 : 0; if (*status) return (*status); FFLOCK; if (!filter->tag || !filter->tag[0] || !filter->tag[0][0]) { filter->tag = DEFAULT_TAGS; if (DEBUG_PIXFILTER) printf("using default tag '%s'\n", filter->tag[0]); } infptr = filter->ifptr[0]; outfptr = filter->ofptr; gParse.pixFilter = filter; if (ffiprs(infptr, 0, filter->expression, MAXDIMS, &Info.datatype, &nelem, &naxis, naxes, status)) { goto CLEANUP; } if (nelem < 0) { nelem = -nelem; } { /* validate result type */ const char * type = 0; switch (Info.datatype) { case TLOGICAL: type = "LOGICAL"; break; case TLONG: type = "LONG"; break; case TDOUBLE: type = "DOUBLE"; break; case TSTRING: type = "STRING"; *status = pERROR; ffpmsg("pixel_filter: cannot have string image"); case TBIT: type = "BIT"; if (DEBUG_PIXFILTER) printf("hmm, image from bits?\n"); break; default: type = "UNKNOWN?!"; *status = pERROR; ffpmsg("pixel_filter: unexpected result datatype"); } if (DEBUG_PIXFILTER) printf("result type is %s [%d]\n", type, Info.datatype); if (*status) goto CLEANUP; } if (fits_get_img_param(infptr, MAXDIMS, &bitpix, &naxis, &naxes[0], status)) { ffpmsg("pixel_filter: unable to read input image parameters"); goto CLEANUP; } if (DEBUG_PIXFILTER) printf("input bitpix %d\n", bitpix); if (Info.datatype == TDOUBLE) { /* for floating point expressions, set the default output image to bitpix = -32 (float) unless the default is already a double */ if (bitpix != DOUBLE_IMG) bitpix = FLOAT_IMG; } /* override output image bitpix if specified by caller */ if (filter->bitpix) bitpix = filter->bitpix; if (DEBUG_PIXFILTER) printf("output bitpix %d\n", bitpix); if (fits_create_img(outfptr, bitpix, naxis, naxes, status)) { ffpmsg("pixel_filter: unable to create output image"); goto CLEANUP; } /* transfer keycards */ { int i, ncards, more; if (fits_get_hdrspace(infptr, &ncards, &more, status)) { ffpmsg("pixel_filter: unable to determine number of keycards"); goto CLEANUP; } for (i = 1; i <= ncards; ++i) { int keyclass; char card[FLEN_CARD]; if (fits_read_record(infptr, i, card, status)) { snprintf(msg, 256,"pixel_filter: unable to read keycard %d", i); ffpmsg(msg); goto CLEANUP; } keyclass = fits_get_keyclass(card); if (keyclass == TYP_STRUC_KEY) { /* output structure defined by fits_create_img */ } else if (keyclass == TYP_COMM_KEY && i < 12) { /* assume this is one of the FITS standard comments */ } else if (keyclass == TYP_NULL_KEY && bitpix < 0) { /* do not transfer BLANK to real output image */ } else if (keyclass == TYP_SCAL_KEY && bitpix < 0) { /* do not transfer BZERO, BSCALE to real output image */ } else if (fits_write_record(outfptr, card, status)) { snprintf(msg,256, "pixel_filter: unable to write keycard '%s' [%d]\n", card, *status); ffpmsg(msg); goto CLEANUP; } } } switch (bitpix) { case BYTE_IMG: datatype = TLONG; Info.datatype = TBYTE; break; case SHORT_IMG: datatype = TLONG; Info.datatype = TSHORT; break; case LONG_IMG: datatype = TLONG; Info.datatype = TLONG; break; case FLOAT_IMG: datatype = TDOUBLE; Info.datatype = TFLOAT; break; case DOUBLE_IMG: datatype = TDOUBLE; Info.datatype = TDOUBLE; break; default: snprintf(msg, 256,"pixel_filter: unexpected output bitpix %d\n", bitpix); ffpmsg(msg); *status = pERROR; goto CLEANUP; } if (bitpix > 0) { /* arrange for NULLs in output */ long nullVal = filter->blank; if (!filter->blank) { int tstatus = 0; if (fits_read_key_lng(infptr, "BLANK", &nullVal, 0, &tstatus)) { writeBlankKwd = 1; if (bitpix == BYTE_IMG) nullVal = UCHAR_MAX; else if (bitpix == SHORT_IMG) nullVal = SHRT_MIN; else if (bitpix == LONG_IMG) nullVal = LONG_MIN; else printf("unhandled positive output BITPIX %d\n", bitpix); } filter->blank = nullVal; } fits_set_imgnull(outfptr, filter->blank, status); if (DEBUG_PIXFILTER) printf("using blank %ld\n", nullVal); } if (!filter->keyword[0]) { iteratorCol * colIter; DataInfo * varInfo; /*************************************/ /* Create new iterator Output Column */ /*************************************/ col_cnt = gParse.nCols; if (allocateCol(col_cnt, status)) goto CLEANUP; gParse.nCols++; colIter = &gParse.colData[col_cnt]; colIter->fptr = filter->ofptr; colIter->iotype = OutputCol; varInfo = &gParse.varData[col_cnt]; set_image_col_types(colIter->fptr, "CREATED", bitpix, varInfo, colIter); Info.maxRows = -1; if (ffiter(gParse.nCols, gParse.colData, 0, 0, parse_data, &Info, status) == -1) *status = 0; else if (*status) goto CLEANUP; if (Info.anyNull) { if (writeBlankKwd) { fits_update_key_lng(outfptr, "BLANK", filter->blank, "NULL pixel value", status); if (*status) ffpmsg("pixel_filter: unable to write BLANK keyword"); if (DEBUG_PIXFILTER) { printf("output has NULLs\n"); printf("wrote blank [%d]\n", *status); } } } else if (bitpix > 0) /* never used a null */ if (fits_set_imgnull(outfptr, -1234554321, status)) ffpmsg("pixel_filter: unable to reset imgnull"); } else { /* Put constant result into keyword */ char * parName = filter->keyword; char * parInfo = filter->comment; result = gParse.Nodes + gParse.resultNode; switch (Info.datatype) { case TDOUBLE: ffukyd(outfptr, parName, result->value.data.dbl, 15, parInfo, status); break; case TLONG: ffukyj(outfptr, parName, result->value.data.lng, parInfo, status); break; case TLOGICAL: ffukyl(outfptr, parName, result->value.data.log, parInfo, status); break; case TBIT: case TSTRING: ffukys(outfptr, parName, result->value.data.str, parInfo, status); break; default: snprintf(msg, 256,"pixel_filter: unexpected constant result type [%d]\n", Info.datatype); ffpmsg(msg); } } CLEANUP: ffcprs(); FFUNLOCK; return (*status); } cfitsio/eval_l.c0000644000225700000360000020446713246025103013423 0ustar cagordonlhea #line 3 "" #define FF_INT_ALIGNED short int /* A lexical scanner generated by flex */ #define FLEX_SCANNER #define FF_FLEX_MAJOR_VERSION 2 #define FF_FLEX_MINOR_VERSION 5 #define FF_FLEX_SUBMINOR_VERSION 35 #if FF_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif /* First, we deal with platform-specific or compiler-specific issues. */ /* begin standard C headers. */ #include #include #include #include /* end standard C headers. */ /* flex integer type definitions */ #ifndef FLEXINT_H #define FLEXINT_H /* C99 systems have . Non-C99 systems may or may not. */ #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, * if you want the limit (max/min) macros for int types. */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 #endif #include typedef int8_t flex_int8_t; typedef uint8_t flex_uint8_t; typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; #endif /* ! C99 */ /* Limits of integral types. */ #ifndef INT8_MIN #define INT8_MIN (-128) #endif #ifndef INT16_MIN #define INT16_MIN (-32767-1) #endif #ifndef INT32_MIN #define INT32_MIN (-2147483647-1) #endif #ifndef INT8_MAX #define INT8_MAX (127) #endif #ifndef INT16_MAX #define INT16_MAX (32767) #endif #ifndef INT32_MAX #define INT32_MAX (2147483647) #endif #ifndef UINT8_MAX #define UINT8_MAX (255U) #endif #ifndef UINT16_MAX #define UINT16_MAX (65535U) #endif #ifndef UINT32_MAX #define UINT32_MAX (4294967295U) #endif #endif /* ! FLEXINT_H */ #ifdef __cplusplus /* The "const" storage-class-modifier is valid. */ #define FF_USE_CONST #else /* ! __cplusplus */ /* C99 requires __STDC__ to be defined as 1. */ #if defined (__STDC__) #define FF_USE_CONST #endif /* defined (__STDC__) */ #endif /* ! __cplusplus */ #ifdef FF_USE_CONST #define ffconst const #else #define ffconst #endif /* Returned upon end-of-file. */ #define FF_NULL 0 /* Promotes a possibly negative, possibly signed char to an unsigned * integer for use as an array index. If the signed char is negative, * we want to instead treat it as an 8-bit unsigned char, hence the * double cast. */ #define FF_SC_TO_UI(c) ((unsigned int) (unsigned char) c) /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN (ff_start) = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The FFSTATE alias is for lex * compatibility. */ #define FF_START (((ff_start) - 1) / 2) #define FFSTATE FF_START /* Action number for EOF rule of a given start state. */ #define FF_STATE_EOF(state) (FF_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define FF_NEW_FILE ffrestart(ffin ) #define FF_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #ifndef FF_BUF_SIZE #define FF_BUF_SIZE 16384 #endif /* The state buf must be large enough to hold one state per character in the main buffer. */ #define FF_STATE_BUF_SIZE ((FF_BUF_SIZE + 2) * sizeof(ff_state_type)) #ifndef FF_TYPEDEF_FF_BUFFER_STATE #define FF_TYPEDEF_FF_BUFFER_STATE typedef struct ff_buffer_state *FF_BUFFER_STATE; #endif extern int ffleng; extern FILE *ffin, *ffout; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 #define FF_LESS_LINENO(n) /* Return all but the first "n" matched characters back to the input stream. */ #define ffless(n) \ do \ { \ /* Undo effects of setting up fftext. */ \ int ffless_macro_arg = (n); \ FF_LESS_LINENO(ffless_macro_arg);\ *ff_cp = (ff_hold_char); \ FF_RESTORE_FF_MORE_OFFSET \ (ff_c_buf_p) = ff_cp = ff_bp + ffless_macro_arg - FF_MORE_ADJ; \ FF_DO_BEFORE_ACTION; /* set up fftext again */ \ } \ while ( 0 ) #define unput(c) ffunput( c, (fftext_ptr) ) #ifndef FF_TYPEDEF_FF_SIZE_T #define FF_TYPEDEF_FF_SIZE_T typedef size_t ff_size_t; #endif #ifndef FF_STRUCT_FF_BUFFER_STATE #define FF_STRUCT_FF_BUFFER_STATE struct ff_buffer_state { FILE *ff_input_file; char *ff_ch_buf; /* input buffer */ char *ff_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ ff_size_t ff_buf_size; /* Number of characters read into ff_ch_buf, not including EOB * characters. */ int ff_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int ff_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int ff_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int ff_at_bol; int ff_bs_lineno; /**< The line count. */ int ff_bs_column; /**< The column count. */ /* Whether to try to fill the input buffer when we reach the * end of it. */ int ff_fill_buffer; int ff_buffer_status; #define FF_BUFFER_NEW 0 #define FF_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as FF_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via ffrestart()), so that the user can continue scanning by * just pointing ffin at a new input file. */ #define FF_BUFFER_EOF_PENDING 2 }; #endif /* !FF_STRUCT_FF_BUFFER_STATE */ /* Stack of input buffers. */ static size_t ff_buffer_stack_top = 0; /**< index of top of stack. */ static size_t ff_buffer_stack_max = 0; /**< capacity of stack. */ static FF_BUFFER_STATE * ff_buffer_stack = 0; /**< Stack as an array. */ /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". * * Returns the top of the stack, or NULL. */ #define FF_CURRENT_BUFFER ( (ff_buffer_stack) \ ? (ff_buffer_stack)[(ff_buffer_stack_top)] \ : NULL) /* Same as previous macro, but useful when we know that the buffer stack is not * NULL or when we need an lvalue. For internal use only. */ #define FF_CURRENT_BUFFER_LVALUE (ff_buffer_stack)[(ff_buffer_stack_top)] /* ff_hold_char holds the character lost when fftext is formed. */ static char ff_hold_char; static int ff_n_chars; /* number of characters read into ff_ch_buf */ int ffleng; /* Points to current character in buffer. */ static char *ff_c_buf_p = (char *) 0; static int ff_init = 0; /* whether we need to initialize */ static int ff_start = 0; /* start state number */ /* Flag which is used to allow ffwrap()'s to do buffer switches * instead of setting up a fresh ffin. A bit of a hack ... */ static int ff_did_buffer_switch_on_eof; void ffrestart (FILE *input_file ); void ff_switch_to_buffer (FF_BUFFER_STATE new_buffer ); FF_BUFFER_STATE ff_create_buffer (FILE *file,int size ); void ff_delete_buffer (FF_BUFFER_STATE b ); void ff_flush_buffer (FF_BUFFER_STATE b ); void ffpush_buffer_state (FF_BUFFER_STATE new_buffer ); void ffpop_buffer_state (void ); static void ffensure_buffer_stack (void ); static void ff_load_buffer_state (void ); static void ff_init_buffer (FF_BUFFER_STATE b,FILE *file ); #define FF_FLUSH_BUFFER ff_flush_buffer(FF_CURRENT_BUFFER ) FF_BUFFER_STATE ff_scan_buffer (char *base,ff_size_t size ); FF_BUFFER_STATE ff_scan_string (ffconst char *ff_str ); FF_BUFFER_STATE ff_scan_bytes (ffconst char *bytes,int len ); void *ffalloc (ff_size_t ); void *ffrealloc (void *,ff_size_t ); void yyfffree (void * ); #define ff_new_buffer ff_create_buffer #define ff_set_interactive(is_interactive) \ { \ if ( ! FF_CURRENT_BUFFER ){ \ ffensure_buffer_stack (); \ FF_CURRENT_BUFFER_LVALUE = \ ff_create_buffer(ffin,FF_BUF_SIZE ); \ } \ FF_CURRENT_BUFFER_LVALUE->ff_is_interactive = is_interactive; \ } #define ff_set_bol(at_bol) \ { \ if ( ! FF_CURRENT_BUFFER ){\ ffensure_buffer_stack (); \ FF_CURRENT_BUFFER_LVALUE = \ ff_create_buffer(ffin,FF_BUF_SIZE ); \ } \ FF_CURRENT_BUFFER_LVALUE->ff_at_bol = at_bol; \ } #define FF_AT_BOL() (FF_CURRENT_BUFFER_LVALUE->ff_at_bol) /* Begin user sect3 */ typedef unsigned char FF_CHAR; FILE *ffin = (FILE *) 0, *ffout = (FILE *) 0; typedef int ff_state_type; extern int fflineno; int fflineno = 1; extern char *fftext; #define fftext_ptr fftext static ff_state_type ff_get_previous_state (void ); static ff_state_type ff_try_NUL_trans (ff_state_type current_state ); static int ff_get_next_buffer (void ); static void ff_fatal_error (ffconst char msg[] ); /* Done after the current pattern has been matched and before the * corresponding action - sets up fftext. */ #define FF_DO_BEFORE_ACTION \ (fftext_ptr) = ff_bp; \ ffleng = (size_t) (ff_cp - ff_bp); \ (ff_hold_char) = *ff_cp; \ *ff_cp = '\0'; \ (ff_c_buf_p) = ff_cp; #define FF_NUM_RULES 26 #define FF_END_OF_BUFFER 27 /* This struct is not used in this scanner, but its presence is necessary. */ struct ff_trans_info { flex_int32_t ff_verify; flex_int32_t ff_nxt; }; static ffconst flex_int16_t ff_accept[160] = { 0, 0, 0, 27, 25, 1, 24, 15, 25, 25, 25, 25, 25, 25, 25, 7, 5, 21, 25, 20, 10, 10, 10, 10, 6, 10, 10, 10, 10, 10, 14, 10, 10, 10, 10, 10, 10, 10, 25, 1, 19, 0, 9, 0, 8, 0, 10, 17, 0, 0, 0, 0, 0, 0, 0, 14, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 5, 0, 23, 18, 22, 10, 10, 10, 2, 10, 10, 10, 4, 10, 10, 10, 10, 3, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 16, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 11, 10, 20, 21, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0 } ; static ffconst flex_int32_t ff_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 5, 6, 7, 1, 8, 9, 10, 11, 12, 13, 1, 13, 14, 1, 15, 15, 16, 16, 16, 16, 16, 16, 17, 17, 1, 1, 18, 19, 20, 1, 1, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 30, 31, 30, 32, 33, 30, 34, 35, 30, 36, 37, 30, 30, 38, 30, 30, 1, 1, 1, 39, 40, 1, 41, 42, 23, 43, 44, 45, 46, 28, 47, 30, 30, 48, 30, 49, 50, 30, 51, 52, 30, 53, 54, 30, 30, 38, 30, 30, 1, 55, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static ffconst flex_int32_t ff_meta[56] = { 0, 1, 1, 2, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 1, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1 } ; static ffconst flex_int16_t ff_base[167] = { 0, 0, 0, 367, 368, 364, 368, 346, 359, 356, 355, 353, 351, 32, 347, 66, 103, 339, 44, 338, 25, 52, 316, 26, 315, 34, 133, 48, 61, 125, 368, 0, 29, 45, 60, 81, 82, 93, 299, 351, 368, 347, 368, 344, 343, 342, 368, 368, 339, 314, 315, 313, 294, 295, 293, 368, 121, 164, 307, 301, 70, 117, 43, 296, 276, 271, 58, 86, 79, 269, 152, 168, 181, 368, 368, 368, 151, 162, 0, 180, 189, 190, 191, 309, 196, 199, 205, 204, 211, 214, 207, 223, 224, 232, 238, 243, 245, 222, 246, 368, 311, 310, 279, 282, 278, 259, 262, 258, 252, 286, 295, 294, 293, 292, 291, 290, 267, 288, 258, 285, 284, 278, 270, 268, 259, 218, 252, 264, 272, 368, 251, 368, 368, 260, 280, 283, 236, 222, 230, 193, 184, 212, 208, 202, 173, 156, 368, 133, 126, 368, 104, 98, 119, 132, 80, 94, 92, 368, 78, 368, 323, 325, 329, 333, 68, 67, 337 } ; static ffconst flex_int16_t ff_def[167] = { 0, 159, 1, 159, 159, 159, 159, 159, 160, 161, 162, 159, 163, 159, 159, 159, 159, 159, 159, 159, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 159, 165, 164, 164, 164, 164, 164, 164, 159, 159, 159, 160, 159, 166, 161, 162, 159, 159, 163, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 164, 164, 165, 164, 164, 164, 164, 26, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 159, 166, 166, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 164, 159, 159, 164, 164, 164, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 0, 159, 159, 159, 159, 159, 159, 159 } ; static ffconst flex_int16_t ff_nxt[424] = { 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 4, 14, 4, 15, 16, 16, 16, 17, 18, 19, 20, 21, 22, 22, 23, 24, 25, 26, 22, 22, 27, 28, 29, 22, 22, 24, 22, 22, 30, 31, 32, 21, 22, 33, 24, 34, 22, 35, 36, 37, 22, 22, 24, 22, 38, 49, 77, 50, 81, 80, 51, 73, 74, 75, 78, 78, 79, 115, 78, 82, 78, 76, 84, 78, 52, 116, 53, 90, 54, 56, 57, 57, 57, 85, 78, 86, 58, 78, 157, 79, 59, 78, 60, 87, 111, 91, 61, 62, 63, 78, 78, 120, 157, 92, 157, 112, 64, 88, 88, 65, 121, 66, 93, 67, 68, 69, 70, 71, 71, 71, 78, 78, 124, 158, 94, 96, 72, 72, 125, 122, 88, 97, 78, 95, 56, 108, 108, 108, 123, 88, 88, 113, 157, 156, 98, 72, 72, 83, 83, 83, 155, 154, 114, 83, 83, 83, 83, 83, 83, 89, 129, 153, 88, 152, 78, 56, 57, 57, 57, 146, 83, 129, 78, 83, 83, 83, 83, 83, 57, 57, 57, 70, 71, 71, 71, 130, 47, 72, 72, 129, 78, 72, 72, 127, 79, 128, 128, 128, 129, 129, 129, 78, 74, 75, 131, 129, 72, 72, 129, 73, 72, 72, 132, 129, 129, 146, 129, 79, 40, 78, 129, 47, 149, 129, 151, 88, 88, 99, 78, 78, 78, 129, 129, 129, 150, 78, 74, 75, 78, 133, 149, 129, 148, 78, 78, 131, 78, 129, 88, 134, 78, 73, 129, 78, 129, 129, 132, 147, 40, 99, 129, 78, 78, 78, 47, 99, 108, 108, 108, 129, 145, 78, 40, 146, 135, 72, 72, 78, 128, 128, 128, 132, 78, 73, 78, 78, 128, 128, 128, 129, 78, 131, 129, 47, 72, 72, 146, 75, 74, 78, 144, 99, 143, 40, 132, 73, 131, 75, 74, 142, 141, 140, 139, 138, 137, 136, 101, 101, 129, 78, 126, 119, 78, 41, 118, 41, 41, 44, 44, 45, 117, 45, 45, 48, 110, 48, 48, 100, 109, 100, 100, 107, 106, 105, 104, 103, 102, 42, 46, 159, 101, 42, 39, 99, 78, 78, 75, 73, 55, 42, 47, 46, 43, 42, 40, 39, 159, 3, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159 } ; static ffconst flex_int16_t ff_chk[424] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 20, 13, 25, 23, 13, 18, 18, 18, 20, 23, 21, 62, 32, 25, 165, 164, 27, 25, 13, 62, 13, 32, 13, 15, 15, 15, 15, 27, 33, 28, 15, 27, 158, 21, 15, 21, 15, 28, 60, 33, 15, 15, 15, 34, 28, 66, 156, 34, 155, 60, 15, 37, 37, 15, 66, 15, 34, 15, 15, 15, 16, 16, 16, 16, 35, 36, 68, 154, 35, 36, 16, 16, 68, 67, 37, 36, 37, 35, 56, 56, 56, 56, 67, 29, 29, 61, 153, 152, 37, 16, 16, 26, 26, 26, 151, 150, 61, 26, 26, 26, 26, 26, 26, 29, 76, 148, 29, 147, 29, 70, 70, 70, 70, 145, 26, 77, 26, 26, 26, 26, 26, 26, 57, 57, 57, 71, 71, 71, 71, 77, 144, 57, 57, 79, 76, 71, 71, 72, 79, 72, 72, 72, 80, 81, 82, 77, 80, 81, 82, 84, 57, 57, 85, 84, 71, 71, 85, 87, 86, 143, 90, 79, 86, 79, 88, 142, 141, 89, 140, 88, 88, 89, 80, 81, 82, 97, 91, 92, 139, 84, 91, 92, 85, 87, 138, 93, 137, 87, 86, 93, 90, 94, 88, 90, 88, 94, 95, 89, 96, 98, 95, 136, 96, 98, 130, 97, 91, 92, 130, 126, 108, 108, 108, 133, 125, 93, 124, 133, 97, 108, 108, 94, 127, 127, 127, 123, 95, 122, 96, 98, 128, 128, 128, 134, 130, 121, 135, 134, 108, 108, 135, 120, 119, 133, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 107, 106, 105, 104, 103, 102, 101, 100, 83, 134, 69, 65, 135, 160, 64, 160, 160, 161, 161, 162, 63, 162, 162, 163, 59, 163, 163, 166, 58, 166, 166, 54, 53, 52, 51, 50, 49, 48, 45, 44, 43, 41, 39, 38, 24, 22, 19, 17, 14, 12, 11, 10, 9, 8, 7, 5, 3, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159 } ; static ff_state_type ff_last_accepting_state; static char *ff_last_accepting_cpos; extern int ff_flex_debug; int ff_flex_debug = 0; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ #define REJECT reject_used_but_not_detected #define ffmore() ffmore_used_but_not_detected #define FF_MORE_ADJ 0 #define FF_RESTORE_FF_MORE_OFFSET char *fftext; #line 1 "eval.l" #line 2 "eval.l" /************************************************************************/ /* */ /* CFITSIO Lexical Parser */ /* */ /* This file is one of 3 files containing code which parses an */ /* arithmetic expression and evaluates it in the context of an input */ /* FITS file table extension. The CFITSIO lexical parser is divided */ /* into the following 3 parts/files: the CFITSIO "front-end", */ /* eval_f.c, contains the interface between the user/CFITSIO and the */ /* real core of the parser; the FLEX interpreter, eval_l.c, takes the */ /* input string and parses it into tokens and identifies the FITS */ /* information required to evaluate the expression (ie, keywords and */ /* columns); and, the BISON grammar and evaluation routines, eval_y.c, */ /* receives the FLEX output and determines and performs the actual */ /* operations. The files eval_l.c and eval_y.c are produced from */ /* running flex and bison on the files eval.l and eval.y, respectively. */ /* (flex and bison are available from any GNU archive: see www.gnu.org) */ /* */ /* The grammar rules, rather than evaluating the expression in situ, */ /* builds a tree, or Nodal, structure mapping out the order of */ /* operations and expression dependencies. This "compilation" process */ /* allows for much faster processing of multiple rows. This technique */ /* was developed by Uwe Lammers of the XMM Science Analysis System, */ /* although the CFITSIO implementation is entirely code original. */ /* */ /* */ /* Modification History: */ /* */ /* Kent Blackburn c1992 Original parser code developed for the */ /* FTOOLS software package, in particular, */ /* the fselect task. */ /* Kent Blackburn c1995 BIT column support added */ /* Peter D Wilson Feb 1998 Vector column support added */ /* Peter D Wilson May 1998 Ported to CFITSIO library. User */ /* interface routines written, in essence */ /* making fselect, fcalc, and maketime */ /* capabilities available to all tools */ /* via single function calls. */ /* Peter D Wilson Jun 1998 Major rewrite of parser core, so as to */ /* create a run-time evaluation tree, */ /* inspired by the work of Uwe Lammers, */ /* resulting in a speed increase of */ /* 10-100 times. */ /* Peter D Wilson Jul 1998 gtifilter(a,b,c,d) function added */ /* Peter D Wilson Aug 1998 regfilter(a,b,c,d) function added */ /* Peter D Wilson Jul 1999 Make parser fitsfile-independent, */ /* allowing a purely vector-based usage */ /* */ /************************************************************************/ #include #include #include #ifdef sparc #include #else #include #endif #include "eval_defs.h" ParseData gParse; /* Global structure holding all parser information */ /***** Internal functions *****/ int ffGetVariable( char *varName, FFSTYPE *varVal ); static int find_variable( char *varName ); static int expr_read( char *buf, int nbytes ); /***** Definitions *****/ #define FF_NO_UNPUT /* Don't include FFUNPUT function */ #define FF_NEVER_INTERACTIVE 1 #define MAXCHR 256 #define MAXBIT 128 #define OCT_0 "000" #define OCT_1 "001" #define OCT_2 "010" #define OCT_3 "011" #define OCT_4 "100" #define OCT_5 "101" #define OCT_6 "110" #define OCT_7 "111" #define OCT_X "xxx" #define HEX_0 "0000" #define HEX_1 "0001" #define HEX_2 "0010" #define HEX_3 "0011" #define HEX_4 "0100" #define HEX_5 "0101" #define HEX_6 "0110" #define HEX_7 "0111" #define HEX_8 "1000" #define HEX_9 "1001" #define HEX_A "1010" #define HEX_B "1011" #define HEX_C "1100" #define HEX_D "1101" #define HEX_E "1110" #define HEX_F "1111" #define HEX_X "xxxx" /* MJT - 13 June 1996 read from buffer instead of stdin (as per old ftools.skel) */ #undef FF_INPUT #define FF_INPUT(buf,result,max_size) \ if ( (result = expr_read( (char *) buf, max_size )) < 0 ) \ FF_FATAL_ERROR( "read() in flex scanner failed" ); #line 712 "" #define INITIAL 0 #ifndef FF_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way * down here because we want the user's section 1 to have been scanned first. * The user has a chance to override it with an option. */ #include #endif #ifndef FF_EXTRA_TYPE #define FF_EXTRA_TYPE void * #endif static int ff_init_globals (void ); /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ int fflex_destroy (void ); int ffget_debug (void ); void ffset_debug (int debug_flag ); FF_EXTRA_TYPE ffget_extra (void ); void ffset_extra (FF_EXTRA_TYPE user_defined ); FILE *ffget_in (void ); void ffset_in (FILE * in_str ); FILE *ffget_out (void ); void ffset_out (FILE * out_str ); int ffget_leng (void ); char *ffget_text (void ); int ffget_lineno (void ); void ffset_lineno (int line_number ); /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef FF_SKIP_FFWRAP #ifdef __cplusplus extern "C" int ffwrap (void ); #else extern int ffwrap (void ); #endif #endif static void ffunput (int c,char *buf_ptr ); #ifndef fftext_ptr static void ff_flex_strncpy (char *,ffconst char *,int ); #endif #ifdef FF_NEED_STRLEN static int ff_flex_strlen (ffconst char * ); #endif #ifndef FF_NO_INPUT #ifdef __cplusplus static int ffinput (void ); #else static int input (void ); #endif #endif /* Amount of stuff to slurp up with each read. */ #ifndef FF_READ_BUF_SIZE #define FF_READ_BUF_SIZE 8192 #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ #define ECHO do { if (fwrite( fftext, ffleng, 1, ffout )) {} } while (0) #endif /* Gets input and stuffs it into "buf". number of characters read, or FF_NULL, * is returned in "result". */ #ifndef FF_INPUT #define FF_INPUT(buf,result,max_size) \ if ( FF_CURRENT_BUFFER_LVALUE->ff_is_interactive ) \ { \ int c = '*'; \ unsigned n; \ for ( n = 0; n < max_size && \ (c = getc( ffin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ if ( c == '\n' ) \ buf[n++] = (char) c; \ if ( c == EOF && ferror( ffin ) ) \ FF_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ else \ { \ errno=0; \ while ( (result = fread(buf, 1, max_size, ffin))==0 && ferror(ffin)) \ { \ if( errno != EINTR) \ { \ FF_FATAL_ERROR( "input in flex scanner failed" ); \ break; \ } \ errno=0; \ clearerr(ffin); \ } \ }\ \ #endif /* No semi-colon after return; correct usage is to write "ffterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef ffterminate #define ffterminate() return FF_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef FF_START_STACK_INCR #define FF_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef FF_FATAL_ERROR #define FF_FATAL_ERROR(msg) ff_fatal_error( msg ) #endif /* end tables serialization structures and prototypes */ /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef FF_DECL #define FF_DECL_IS_OURS 1 extern int fflex (void); #define FF_DECL int fflex (void) #endif /* !FF_DECL */ /* Code executed at the beginning of each rule, after fftext and ffleng * have been set up. */ #ifndef FF_USER_ACTION #define FF_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef FF_BREAK #define FF_BREAK break; #endif #define FF_RULE_SETUP \ FF_USER_ACTION /** The main scanner function which does all the work. */ FF_DECL { register ff_state_type ff_current_state; register char *ff_cp, *ff_bp; register int ff_act; #line 142 "eval.l" #line 897 "" if ( !(ff_init) ) { (ff_init) = 1; #ifdef FF_USER_INIT FF_USER_INIT; #endif if ( ! (ff_start) ) (ff_start) = 1; /* first start state */ if ( ! ffin ) ffin = stdin; if ( ! ffout ) ffout = stdout; if ( ! FF_CURRENT_BUFFER ) { ffensure_buffer_stack (); FF_CURRENT_BUFFER_LVALUE = ff_create_buffer(ffin,FF_BUF_SIZE ); } ff_load_buffer_state( ); } while ( 1 ) /* loops until end-of-file is reached */ { ff_cp = (ff_c_buf_p); /* Support of fftext. */ *ff_cp = (ff_hold_char); /* ff_bp points to the position in ff_ch_buf of the start of * the current run. */ ff_bp = ff_cp; ff_current_state = (ff_start); ff_match: do { register FF_CHAR ff_c = ff_ec[FF_SC_TO_UI(*ff_cp)]; if ( ff_accept[ff_current_state] ) { (ff_last_accepting_state) = ff_current_state; (ff_last_accepting_cpos) = ff_cp; } while ( ff_chk[ff_base[ff_current_state] + ff_c] != ff_current_state ) { ff_current_state = (int) ff_def[ff_current_state]; if ( ff_current_state >= 160 ) ff_c = ff_meta[(unsigned int) ff_c]; } ff_current_state = ff_nxt[ff_base[ff_current_state] + (unsigned int) ff_c]; ++ff_cp; } while ( ff_base[ff_current_state] != 368 ); ff_find_action: ff_act = ff_accept[ff_current_state]; if ( ff_act == 0 ) { /* have to back up */ ff_cp = (ff_last_accepting_cpos); ff_current_state = (ff_last_accepting_state); ff_act = ff_accept[ff_current_state]; } FF_DO_BEFORE_ACTION; do_action: /* This label is used only to access EOF actions. */ switch ( ff_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of FF_DO_BEFORE_ACTION */ *ff_cp = (ff_hold_char); ff_cp = (ff_last_accepting_cpos); ff_current_state = (ff_last_accepting_state); goto ff_find_action; case 1: FF_RULE_SETUP #line 144 "eval.l" ; FF_BREAK case 2: FF_RULE_SETUP #line 145 "eval.l" { int len; len = strlen(fftext); while (fftext[len] == ' ') len--; len = len - 1; strncpy(fflval.str,&fftext[1],len); fflval.str[len] = '\0'; return( BITSTR ); } FF_BREAK case 3: FF_RULE_SETUP #line 155 "eval.l" { int len; char tmpstring[256]; char bitstring[256]; len = strlen(fftext); if (len >= 256) { char errMsg[100]; gParse.status = PARSE_SYNTAX_ERR; strcpy (errMsg,"Bit string exceeds maximum length: '"); strncat(errMsg, &(fftext[0]), 20); strcat (errMsg,"...'"); ffpmsg (errMsg); len = 0; } else { while (fftext[len] == ' ') len--; len = len - 1; strncpy(tmpstring,&fftext[1],len); } tmpstring[len] = '\0'; bitstring[0] = '\0'; len = 0; while ( tmpstring[len] != '\0') { switch ( tmpstring[len] ) { case '0': strcat(bitstring,OCT_0); break; case '1': strcat(bitstring,OCT_1); break; case '2': strcat(bitstring,OCT_2); break; case '3': strcat(bitstring,OCT_3); break; case '4': strcat(bitstring,OCT_4); break; case '5': strcat(bitstring,OCT_5); break; case '6': strcat(bitstring,OCT_6); break; case '7': strcat(bitstring,OCT_7); break; case 'x': case 'X': strcat(bitstring,OCT_X); break; } len++; } strcpy( fflval.str, bitstring ); return( BITSTR ); } FF_BREAK case 4: FF_RULE_SETUP #line 215 "eval.l" { int len; char tmpstring[256]; char bitstring[256]; len = strlen(fftext); if (len >= 256) { char errMsg[100]; gParse.status = PARSE_SYNTAX_ERR; strcpy (errMsg,"Hex string exceeds maximum length: '"); strncat(errMsg, &(fftext[0]), 20); strcat (errMsg,"...'"); ffpmsg (errMsg); len = 0; } else { while (fftext[len] == ' ') len--; len = len - 1; strncpy(tmpstring,&fftext[1],len); } tmpstring[len] = '\0'; bitstring[0] = '\0'; len = 0; while ( tmpstring[len] != '\0') { switch ( tmpstring[len] ) { case '0': strcat(bitstring,HEX_0); break; case '1': strcat(bitstring,HEX_1); break; case '2': strcat(bitstring,HEX_2); break; case '3': strcat(bitstring,HEX_3); break; case '4': strcat(bitstring,HEX_4); break; case '5': strcat(bitstring,HEX_5); break; case '6': strcat(bitstring,HEX_6); break; case '7': strcat(bitstring,HEX_7); break; case '8': strcat(bitstring,HEX_8); break; case '9': strcat(bitstring,HEX_9); break; case 'a': case 'A': strcat(bitstring,HEX_A); break; case 'b': case 'B': strcat(bitstring,HEX_B); break; case 'c': case 'C': strcat(bitstring,HEX_C); break; case 'd': case 'D': strcat(bitstring,HEX_D); break; case 'e': case 'E': strcat(bitstring,HEX_E); break; case 'f': case 'F': strcat(bitstring,HEX_F); break; case 'x': case 'X': strcat(bitstring,HEX_X); break; } len++; } strcpy( fflval.str, bitstring ); return( BITSTR ); } FF_BREAK case 5: FF_RULE_SETUP #line 306 "eval.l" { fflval.lng = atol(fftext); return( LONG ); } FF_BREAK case 6: FF_RULE_SETUP #line 310 "eval.l" { if ((fftext[0] == 't') || (fftext[0] == 'T')) fflval.log = 1; else fflval.log = 0; return( BOOLEAN ); } FF_BREAK case 7: FF_RULE_SETUP #line 317 "eval.l" { fflval.dbl = atof(fftext); return( DOUBLE ); } FF_BREAK case 8: FF_RULE_SETUP #line 321 "eval.l" { if( !fits_strcasecmp(fftext,"#PI") ) { fflval.dbl = (double)(4) * atan((double)(1)); return( DOUBLE ); } else if( !fits_strcasecmp(fftext,"#E") ) { fflval.dbl = exp((double)(1)); return( DOUBLE ); } else if( !fits_strcasecmp(fftext,"#DEG") ) { fflval.dbl = ((double)4)*atan((double)1)/((double)180); return( DOUBLE ); } else if( !fits_strcasecmp(fftext,"#ROW") ) { return( ROWREF ); } else if( !fits_strcasecmp(fftext,"#NULL") ) { return( NULLREF ); } else if( !fits_strcasecmp(fftext,"#SNULL") ) { return( SNULLREF ); } else { int len; if (fftext[1] == '$') { len = strlen(fftext) - 3; fflval.str[0] = '#'; strncpy(fflval.str+1,&fftext[2],len); fflval.str[len+1] = '\0'; fftext = fflval.str; } return( (*gParse.getData)(fftext, &fflval) ); } } FF_BREAK case 9: FF_RULE_SETUP #line 349 "eval.l" { int len; len = strlen(fftext) - 2; if (len >= MAX_STRLEN) { char errMsg[100]; gParse.status = PARSE_SYNTAX_ERR; strcpy (errMsg,"String exceeds maximum length: '"); strncat(errMsg, &(fftext[1]), 20); strcat (errMsg,"...'"); ffpmsg (errMsg); len = 0; } else { strncpy(fflval.str,&fftext[1],len); } fflval.str[len] = '\0'; return( STRING ); } FF_BREAK case 10: FF_RULE_SETUP #line 366 "eval.l" { int len,type; if (fftext[0] == '$') { len = strlen(fftext) - 2; strncpy(fflval.str,&fftext[1],len); fflval.str[len] = '\0'; fftext = fflval.str; } type = ffGetVariable(fftext, &fflval); return( type ); } FF_BREAK case 11: FF_RULE_SETUP #line 378 "eval.l" { char *fname; int len=0; fname = &fflval.str[0]; while( (fname[len]=toupper(fftext[len])) ) len++; if( FSTRCMP(fname,"BOX(")==0 || FSTRCMP(fname,"CIRCLE(")==0 || FSTRCMP(fname,"ELLIPSE(")==0 || FSTRCMP(fname,"NEAR(")==0 || FSTRCMP(fname,"ISNULL(")==0 ) /* Return type is always boolean */ return( BFUNCTION ); else if( FSTRCMP(fname,"GTIFILTER(")==0 ) return( GTIFILTER ); else if( FSTRCMP(fname,"REGFILTER(")==0 ) return( REGFILTER ); else if( FSTRCMP(fname,"STRSTR(")==0 ) return( IFUNCTION ); /* Returns integer */ else return( FUNCTION ); } FF_BREAK case 12: FF_RULE_SETUP #line 405 "eval.l" { return( INTCAST ); } FF_BREAK case 13: FF_RULE_SETUP #line 406 "eval.l" { return( FLTCAST ); } FF_BREAK case 14: FF_RULE_SETUP #line 407 "eval.l" { return( POWER ); } FF_BREAK case 15: FF_RULE_SETUP #line 408 "eval.l" { return( NOT ); } FF_BREAK case 16: FF_RULE_SETUP #line 409 "eval.l" { return( OR ); } FF_BREAK case 17: FF_RULE_SETUP #line 410 "eval.l" { return( AND ); } FF_BREAK case 18: FF_RULE_SETUP #line 411 "eval.l" { return( EQ ); } FF_BREAK case 19: FF_RULE_SETUP #line 412 "eval.l" { return( NE ); } FF_BREAK case 20: FF_RULE_SETUP #line 413 "eval.l" { return( GT ); } FF_BREAK case 21: FF_RULE_SETUP #line 414 "eval.l" { return( LT ); } FF_BREAK case 22: FF_RULE_SETUP #line 415 "eval.l" { return( GTE ); } FF_BREAK case 23: FF_RULE_SETUP #line 416 "eval.l" { return( LTE ); } FF_BREAK case 24: /* rule 24 can match eol */ FF_RULE_SETUP #line 417 "eval.l" { return( '\n' ); } FF_BREAK case 25: FF_RULE_SETUP #line 418 "eval.l" { return( fftext[0] ); } FF_BREAK case 26: FF_RULE_SETUP #line 419 "eval.l" ECHO; FF_BREAK #line 1361 "" case FF_STATE_EOF(INITIAL): ffterminate(); case FF_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int ff_amount_of_matched_text = (int) (ff_cp - (fftext_ptr)) - 1; /* Undo the effects of FF_DO_BEFORE_ACTION. */ *ff_cp = (ff_hold_char); FF_RESTORE_FF_MORE_OFFSET if ( FF_CURRENT_BUFFER_LVALUE->ff_buffer_status == FF_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed ffin at a new source and called * fflex(). If so, then we have to assure * consistency between FF_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ (ff_n_chars) = FF_CURRENT_BUFFER_LVALUE->ff_n_chars; FF_CURRENT_BUFFER_LVALUE->ff_input_file = ffin; FF_CURRENT_BUFFER_LVALUE->ff_buffer_status = FF_BUFFER_NORMAL; } /* Note that here we test for ff_c_buf_p "<=" to the position * of the first EOB in the buffer, since ff_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( (ff_c_buf_p) <= &FF_CURRENT_BUFFER_LVALUE->ff_ch_buf[(ff_n_chars)] ) { /* This was really a NUL. */ ff_state_type ff_next_state; (ff_c_buf_p) = (fftext_ptr) + ff_amount_of_matched_text; ff_current_state = ff_get_previous_state( ); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * ff_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ ff_next_state = ff_try_NUL_trans( ff_current_state ); ff_bp = (fftext_ptr) + FF_MORE_ADJ; if ( ff_next_state ) { /* Consume the NUL. */ ff_cp = ++(ff_c_buf_p); ff_current_state = ff_next_state; goto ff_match; } else { ff_cp = (ff_c_buf_p); goto ff_find_action; } } else switch ( ff_get_next_buffer( ) ) { case EOB_ACT_END_OF_FILE: { (ff_did_buffer_switch_on_eof) = 0; if ( ffwrap( ) ) { /* Note: because we've taken care in * ff_get_next_buffer() to have set up * fftext, we can now set up * ff_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * FF_NULL, it'll still work - another * FF_NULL will get returned. */ (ff_c_buf_p) = (fftext_ptr) + FF_MORE_ADJ; ff_act = FF_STATE_EOF(FF_START); goto do_action; } else { if ( ! (ff_did_buffer_switch_on_eof) ) FF_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: (ff_c_buf_p) = (fftext_ptr) + ff_amount_of_matched_text; ff_current_state = ff_get_previous_state( ); ff_cp = (ff_c_buf_p); ff_bp = (fftext_ptr) + FF_MORE_ADJ; goto ff_match; case EOB_ACT_LAST_MATCH: (ff_c_buf_p) = &FF_CURRENT_BUFFER_LVALUE->ff_ch_buf[(ff_n_chars)]; ff_current_state = ff_get_previous_state( ); ff_cp = (ff_c_buf_p); ff_bp = (fftext_ptr) + FF_MORE_ADJ; goto ff_find_action; } break; } default: FF_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of fflex */ /* ff_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ static int ff_get_next_buffer (void) { register char *dest = FF_CURRENT_BUFFER_LVALUE->ff_ch_buf; register char *source = (fftext_ptr); register int number_to_move, i; int ret_val; if ( (ff_c_buf_p) > &FF_CURRENT_BUFFER_LVALUE->ff_ch_buf[(ff_n_chars) + 1] ) FF_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( FF_CURRENT_BUFFER_LVALUE->ff_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( (ff_c_buf_p) - (fftext_ptr) - FF_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (int) ((ff_c_buf_p) - (fftext_ptr)) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( FF_CURRENT_BUFFER_LVALUE->ff_buffer_status == FF_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ FF_CURRENT_BUFFER_LVALUE->ff_n_chars = (ff_n_chars) = 0; else { int num_to_read = FF_CURRENT_BUFFER_LVALUE->ff_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ FF_BUFFER_STATE b = FF_CURRENT_BUFFER; int ff_c_buf_p_offset = (int) ((ff_c_buf_p) - b->ff_ch_buf); if ( b->ff_is_our_buffer ) { int new_size = b->ff_buf_size * 2; if ( new_size <= 0 ) b->ff_buf_size += b->ff_buf_size / 8; else b->ff_buf_size *= 2; b->ff_ch_buf = (char *) /* Include room in for 2 EOB chars. */ ffrealloc((void *) b->ff_ch_buf,b->ff_buf_size + 2 ); } else /* Can't grow it, we don't own it. */ b->ff_ch_buf = 0; if ( ! b->ff_ch_buf ) FF_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); (ff_c_buf_p) = &b->ff_ch_buf[ff_c_buf_p_offset]; num_to_read = FF_CURRENT_BUFFER_LVALUE->ff_buf_size - number_to_move - 1; } if ( num_to_read > FF_READ_BUF_SIZE ) num_to_read = FF_READ_BUF_SIZE; /* Read in more data. */ FF_INPUT( (&FF_CURRENT_BUFFER_LVALUE->ff_ch_buf[number_to_move]), (ff_n_chars), (size_t) num_to_read ); FF_CURRENT_BUFFER_LVALUE->ff_n_chars = (ff_n_chars); } if ( (ff_n_chars) == 0 ) { if ( number_to_move == FF_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; ffrestart(ffin ); } else { ret_val = EOB_ACT_LAST_MATCH; FF_CURRENT_BUFFER_LVALUE->ff_buffer_status = FF_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; if ((ff_size_t) ((ff_n_chars) + number_to_move) > FF_CURRENT_BUFFER_LVALUE->ff_buf_size) { /* Extend the array by 50%, plus the number we really need. */ ff_size_t new_size = (ff_n_chars) + number_to_move + ((ff_n_chars) >> 1); FF_CURRENT_BUFFER_LVALUE->ff_ch_buf = (char *) ffrealloc((void *) FF_CURRENT_BUFFER_LVALUE->ff_ch_buf,new_size ); if ( ! FF_CURRENT_BUFFER_LVALUE->ff_ch_buf ) FF_FATAL_ERROR( "out of dynamic memory in ff_get_next_buffer()" ); } (ff_n_chars) += number_to_move; FF_CURRENT_BUFFER_LVALUE->ff_ch_buf[(ff_n_chars)] = FF_END_OF_BUFFER_CHAR; FF_CURRENT_BUFFER_LVALUE->ff_ch_buf[(ff_n_chars) + 1] = FF_END_OF_BUFFER_CHAR; (fftext_ptr) = &FF_CURRENT_BUFFER_LVALUE->ff_ch_buf[0]; return ret_val; } /* ff_get_previous_state - get the state just before the EOB char was reached */ static ff_state_type ff_get_previous_state (void) { register ff_state_type ff_current_state; register char *ff_cp; ff_current_state = (ff_start); for ( ff_cp = (fftext_ptr) + FF_MORE_ADJ; ff_cp < (ff_c_buf_p); ++ff_cp ) { register FF_CHAR ff_c = (*ff_cp ? ff_ec[FF_SC_TO_UI(*ff_cp)] : 1); if ( ff_accept[ff_current_state] ) { (ff_last_accepting_state) = ff_current_state; (ff_last_accepting_cpos) = ff_cp; } while ( ff_chk[ff_base[ff_current_state] + ff_c] != ff_current_state ) { ff_current_state = (int) ff_def[ff_current_state]; if ( ff_current_state >= 160 ) ff_c = ff_meta[(unsigned int) ff_c]; } ff_current_state = ff_nxt[ff_base[ff_current_state] + (unsigned int) ff_c]; } return ff_current_state; } /* ff_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = ff_try_NUL_trans( current_state ); */ static ff_state_type ff_try_NUL_trans (ff_state_type ff_current_state ) { register int ff_is_jam; register char *ff_cp = (ff_c_buf_p); register FF_CHAR ff_c = 1; if ( ff_accept[ff_current_state] ) { (ff_last_accepting_state) = ff_current_state; (ff_last_accepting_cpos) = ff_cp; } while ( ff_chk[ff_base[ff_current_state] + ff_c] != ff_current_state ) { ff_current_state = (int) ff_def[ff_current_state]; if ( ff_current_state >= 160 ) ff_c = ff_meta[(unsigned int) ff_c]; } ff_current_state = ff_nxt[ff_base[ff_current_state] + (unsigned int) ff_c]; ff_is_jam = (ff_current_state == 159); return ff_is_jam ? 0 : ff_current_state; } static void ffunput (int c, register char * ff_bp ) { register char *ff_cp; ff_cp = (ff_c_buf_p); /* undo effects of setting up fftext */ *ff_cp = (ff_hold_char); if ( ff_cp < FF_CURRENT_BUFFER_LVALUE->ff_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ register int number_to_move = (ff_n_chars) + 2; register char *dest = &FF_CURRENT_BUFFER_LVALUE->ff_ch_buf[ FF_CURRENT_BUFFER_LVALUE->ff_buf_size + 2]; register char *source = &FF_CURRENT_BUFFER_LVALUE->ff_ch_buf[number_to_move]; while ( source > FF_CURRENT_BUFFER_LVALUE->ff_ch_buf ) *--dest = *--source; ff_cp += (int) (dest - source); ff_bp += (int) (dest - source); FF_CURRENT_BUFFER_LVALUE->ff_n_chars = (ff_n_chars) = FF_CURRENT_BUFFER_LVALUE->ff_buf_size; if ( ff_cp < FF_CURRENT_BUFFER_LVALUE->ff_ch_buf + 2 ) FF_FATAL_ERROR( "flex scanner push-back overflow" ); } *--ff_cp = (char) c; (fftext_ptr) = ff_bp; (ff_hold_char) = *ff_cp; (ff_c_buf_p) = ff_cp; } #ifndef FF_NO_INPUT #ifdef __cplusplus static int ffinput (void) #else static int input (void) #endif { int c; *(ff_c_buf_p) = (ff_hold_char); if ( *(ff_c_buf_p) == FF_END_OF_BUFFER_CHAR ) { /* ff_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( (ff_c_buf_p) < &FF_CURRENT_BUFFER_LVALUE->ff_ch_buf[(ff_n_chars)] ) /* This was really a NUL. */ *(ff_c_buf_p) = '\0'; else { /* need more input */ int offset = (ff_c_buf_p) - (fftext_ptr); ++(ff_c_buf_p); switch ( ff_get_next_buffer( ) ) { case EOB_ACT_LAST_MATCH: /* This happens because ff_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ ffrestart(ffin ); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { if ( ffwrap( ) ) return EOF; if ( ! (ff_did_buffer_switch_on_eof) ) FF_NEW_FILE; #ifdef __cplusplus return ffinput(); #else return input(); #endif } case EOB_ACT_CONTINUE_SCAN: (ff_c_buf_p) = (fftext_ptr) + offset; break; } } } c = *(unsigned char *) (ff_c_buf_p); /* cast for 8-bit char's */ *(ff_c_buf_p) = '\0'; /* preserve fftext */ (ff_hold_char) = *++(ff_c_buf_p); return c; } #endif /* ifndef FF_NO_INPUT */ /** Immediately switch to a different input stream. * @param input_file A readable stream. * * @note This function does not reset the start condition to @c INITIAL . */ void ffrestart (FILE * input_file ) { if ( ! FF_CURRENT_BUFFER ){ ffensure_buffer_stack (); FF_CURRENT_BUFFER_LVALUE = ff_create_buffer(ffin,FF_BUF_SIZE ); } ff_init_buffer(FF_CURRENT_BUFFER,input_file ); ff_load_buffer_state( ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * */ void ff_switch_to_buffer (FF_BUFFER_STATE new_buffer ) { /* TODO. We should be able to replace this entire function body * with * ffpop_buffer_state(); * ffpush_buffer_state(new_buffer); */ ffensure_buffer_stack (); if ( FF_CURRENT_BUFFER == new_buffer ) return; if ( FF_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(ff_c_buf_p) = (ff_hold_char); FF_CURRENT_BUFFER_LVALUE->ff_buf_pos = (ff_c_buf_p); FF_CURRENT_BUFFER_LVALUE->ff_n_chars = (ff_n_chars); } FF_CURRENT_BUFFER_LVALUE = new_buffer; ff_load_buffer_state( ); /* We don't actually know whether we did this switch during * EOF (ffwrap()) processing, but the only time this flag * is looked at is after ffwrap() is called, so it's safe * to go ahead and always set it. */ (ff_did_buffer_switch_on_eof) = 1; } static void ff_load_buffer_state (void) { (ff_n_chars) = FF_CURRENT_BUFFER_LVALUE->ff_n_chars; (fftext_ptr) = (ff_c_buf_p) = FF_CURRENT_BUFFER_LVALUE->ff_buf_pos; ffin = FF_CURRENT_BUFFER_LVALUE->ff_input_file; (ff_hold_char) = *(ff_c_buf_p); } /** Allocate and initialize an input buffer state. * @param file A readable stream. * @param size The character buffer size in bytes. When in doubt, use @c FF_BUF_SIZE. * * @return the allocated buffer state. */ FF_BUFFER_STATE ff_create_buffer (FILE * file, int size ) { FF_BUFFER_STATE b; b = (FF_BUFFER_STATE) ffalloc(sizeof( struct ff_buffer_state ) ); if ( ! b ) FF_FATAL_ERROR( "out of dynamic memory in ff_create_buffer()" ); b->ff_buf_size = size; /* ff_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->ff_ch_buf = (char *) ffalloc(b->ff_buf_size + 2 ); if ( ! b->ff_ch_buf ) FF_FATAL_ERROR( "out of dynamic memory in ff_create_buffer()" ); b->ff_is_our_buffer = 1; ff_init_buffer(b,file ); return b; } /** Destroy the buffer. * @param b a buffer created with ff_create_buffer() * */ void ff_delete_buffer (FF_BUFFER_STATE b ) { if ( ! b ) return; if ( b == FF_CURRENT_BUFFER ) /* Not sure if we should pop here. */ FF_CURRENT_BUFFER_LVALUE = (FF_BUFFER_STATE) 0; if ( b->ff_is_our_buffer ) yyfffree((void *) b->ff_ch_buf ); yyfffree((void *) b ); } #ifndef __cplusplus extern int isatty (int ); #endif /* __cplusplus */ /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a ffrestart() or at EOF. */ static void ff_init_buffer (FF_BUFFER_STATE b, FILE * file ) { int oerrno = errno; ff_flush_buffer(b ); b->ff_input_file = file; b->ff_fill_buffer = 1; /* If b is the current buffer, then ff_init_buffer was _probably_ * called from ffrestart() or through ff_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != FF_CURRENT_BUFFER){ b->ff_bs_lineno = 1; b->ff_bs_column = 0; } b->ff_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; errno = oerrno; } /** Discard all buffered characters. On the next scan, FF_INPUT will be called. * @param b the buffer state to be flushed, usually @c FF_CURRENT_BUFFER. * */ void ff_flush_buffer (FF_BUFFER_STATE b ) { if ( ! b ) return; b->ff_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->ff_ch_buf[0] = FF_END_OF_BUFFER_CHAR; b->ff_ch_buf[1] = FF_END_OF_BUFFER_CHAR; b->ff_buf_pos = &b->ff_ch_buf[0]; b->ff_at_bol = 1; b->ff_buffer_status = FF_BUFFER_NEW; if ( b == FF_CURRENT_BUFFER ) ff_load_buffer_state( ); } /** Pushes the new state onto the stack. The new state becomes * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. * */ void ffpush_buffer_state (FF_BUFFER_STATE new_buffer ) { if (new_buffer == NULL) return; ffensure_buffer_stack(); /* This block is copied from ff_switch_to_buffer. */ if ( FF_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(ff_c_buf_p) = (ff_hold_char); FF_CURRENT_BUFFER_LVALUE->ff_buf_pos = (ff_c_buf_p); FF_CURRENT_BUFFER_LVALUE->ff_n_chars = (ff_n_chars); } /* Only push if top exists. Otherwise, replace top. */ if (FF_CURRENT_BUFFER) (ff_buffer_stack_top)++; FF_CURRENT_BUFFER_LVALUE = new_buffer; /* copied from ff_switch_to_buffer. */ ff_load_buffer_state( ); (ff_did_buffer_switch_on_eof) = 1; } /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. * */ void ffpop_buffer_state (void) { if (!FF_CURRENT_BUFFER) return; ff_delete_buffer(FF_CURRENT_BUFFER ); FF_CURRENT_BUFFER_LVALUE = NULL; if ((ff_buffer_stack_top) > 0) --(ff_buffer_stack_top); if (FF_CURRENT_BUFFER) { ff_load_buffer_state( ); (ff_did_buffer_switch_on_eof) = 1; } } /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ static void ffensure_buffer_stack (void) { int num_to_alloc; if (!(ff_buffer_stack)) { /* First allocation is just for 2 elements, since we don't know if this * scanner will even need a stack. We use 2 instead of 1 to avoid an * immediate realloc on the next call. */ num_to_alloc = 1; (ff_buffer_stack) = (struct ff_buffer_state**)ffalloc (num_to_alloc * sizeof(struct ff_buffer_state*) ); if ( ! (ff_buffer_stack) ) FF_FATAL_ERROR( "out of dynamic memory in ffensure_buffer_stack()" ); memset((ff_buffer_stack), 0, num_to_alloc * sizeof(struct ff_buffer_state*)); (ff_buffer_stack_max) = num_to_alloc; (ff_buffer_stack_top) = 0; return; } if ((ff_buffer_stack_top) >= ((ff_buffer_stack_max)) - 1){ /* Increase the buffer to prepare for a possible push. */ int grow_size = 8 /* arbitrary grow size */; num_to_alloc = (ff_buffer_stack_max) + grow_size; (ff_buffer_stack) = (struct ff_buffer_state**)ffrealloc ((ff_buffer_stack), num_to_alloc * sizeof(struct ff_buffer_state*) ); if ( ! (ff_buffer_stack) ) FF_FATAL_ERROR( "out of dynamic memory in ffensure_buffer_stack()" ); /* zero only the new slots.*/ memset((ff_buffer_stack) + (ff_buffer_stack_max), 0, grow_size * sizeof(struct ff_buffer_state*)); (ff_buffer_stack_max) = num_to_alloc; } } /** Setup the input buffer state to scan directly from a user-specified character buffer. * @param base the character buffer * @param size the size in bytes of the character buffer * * @return the newly allocated buffer state object. */ FF_BUFFER_STATE ff_scan_buffer (char * base, ff_size_t size ) { FF_BUFFER_STATE b; if ( size < 2 || base[size-2] != FF_END_OF_BUFFER_CHAR || base[size-1] != FF_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return 0; b = (FF_BUFFER_STATE) ffalloc(sizeof( struct ff_buffer_state ) ); if ( ! b ) FF_FATAL_ERROR( "out of dynamic memory in ff_scan_buffer()" ); b->ff_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->ff_buf_pos = b->ff_ch_buf = base; b->ff_is_our_buffer = 0; b->ff_input_file = 0; b->ff_n_chars = b->ff_buf_size; b->ff_is_interactive = 0; b->ff_at_bol = 1; b->ff_fill_buffer = 0; b->ff_buffer_status = FF_BUFFER_NEW; ff_switch_to_buffer(b ); return b; } /** Setup the input buffer state to scan a string. The next call to fflex() will * scan from a @e copy of @a str. * @param ffstr a NUL-terminated string to scan * * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use * ff_scan_bytes() instead. */ FF_BUFFER_STATE ff_scan_string (ffconst char * ffstr ) { return ff_scan_bytes(ffstr,strlen(ffstr) ); } /** Setup the input buffer state to scan the given bytes. The next call to fflex() will * scan from a @e copy of @a bytes. * @param bytes the byte buffer to scan * @param len the number of bytes in the buffer pointed to by @a bytes. * * @return the newly allocated buffer state object. */ FF_BUFFER_STATE ff_scan_bytes (ffconst char * ffbytes, int _ffbytes_len ) { FF_BUFFER_STATE b; char *buf; ff_size_t n; int i; /* Get memory for full buffer, including space for trailing EOB's. */ n = _ffbytes_len + 2; buf = (char *) ffalloc(n ); if ( ! buf ) FF_FATAL_ERROR( "out of dynamic memory in ff_scan_bytes()" ); for ( i = 0; i < _ffbytes_len; ++i ) buf[i] = ffbytes[i]; buf[_ffbytes_len] = buf[_ffbytes_len+1] = FF_END_OF_BUFFER_CHAR; b = ff_scan_buffer(buf,n ); if ( ! b ) FF_FATAL_ERROR( "bad buffer in ff_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. */ b->ff_is_our_buffer = 1; return b; } #ifndef FF_EXIT_FAILURE #define FF_EXIT_FAILURE 2 #endif static void ff_fatal_error (ffconst char* msg ) { (void) fprintf( stderr, "%s\n", msg ); exit( FF_EXIT_FAILURE ); } /* Redefine ffless() so it works in section 3 code. */ #undef ffless #define ffless(n) \ do \ { \ /* Undo effects of setting up fftext. */ \ int ffless_macro_arg = (n); \ FF_LESS_LINENO(ffless_macro_arg);\ fftext[ffleng] = (ff_hold_char); \ (ff_c_buf_p) = fftext + ffless_macro_arg; \ (ff_hold_char) = *(ff_c_buf_p); \ *(ff_c_buf_p) = '\0'; \ ffleng = ffless_macro_arg; \ } \ while ( 0 ) /* Accessor methods (get/set functions) to struct members. */ /** Get the current line number. * */ int ffget_lineno (void) { return fflineno; } /** Get the input stream. * */ FILE *ffget_in (void) { return ffin; } /** Get the output stream. * */ FILE *ffget_out (void) { return ffout; } /** Get the length of the current token. * */ int ffget_leng (void) { return ffleng; } /** Get the current token. * */ char *ffget_text (void) { return fftext; } /** Set the current line number. * @param line_number * */ void ffset_lineno (int line_number ) { fflineno = line_number; } /** Set the input stream. This does not discard the current * input buffer. * @param in_str A readable stream. * * @see ff_switch_to_buffer */ void ffset_in (FILE * in_str ) { ffin = in_str ; } void ffset_out (FILE * out_str ) { ffout = out_str ; } int ffget_debug (void) { return ff_flex_debug; } void ffset_debug (int bdebug ) { ff_flex_debug = bdebug ; } static int ff_init_globals (void) { /* Initialization is the same as for the non-reentrant scanner. * This function is called from fflex_destroy(), so don't allocate here. */ (ff_buffer_stack) = 0; (ff_buffer_stack_top) = 0; (ff_buffer_stack_max) = 0; (ff_c_buf_p) = (char *) 0; (ff_init) = 0; (ff_start) = 0; /* Defined in main.c */ #ifdef FF_STDINIT ffin = stdin; ffout = stdout; #else ffin = (FILE *) 0; ffout = (FILE *) 0; #endif /* For future reference: Set errno on error, since we are called by * fflex_init() */ return 0; } /* fflex_destroy is for both reentrant and non-reentrant scanners. */ int fflex_destroy (void) { /* Pop the buffer stack, destroying each element. */ while(FF_CURRENT_BUFFER){ ff_delete_buffer(FF_CURRENT_BUFFER ); FF_CURRENT_BUFFER_LVALUE = NULL; ffpop_buffer_state(); } /* Destroy the stack itself. */ yyfffree((ff_buffer_stack) ); (ff_buffer_stack) = NULL; /* Reset the globals. This is important in a non-reentrant scanner so the next time * fflex() is called, initialization will occur. */ ff_init_globals( ); return 0; } /* * Internal utility routines. */ #ifndef fftext_ptr static void ff_flex_strncpy (char* s1, ffconst char * s2, int n ) { register int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef FF_NEED_STRLEN static int ff_flex_strlen (ffconst char * s ) { register int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif void *ffalloc (ff_size_t size ) { return (void *) malloc( size ); } void *ffrealloc (void * ptr, ff_size_t size ) { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); } void yyfffree (void * ptr ) { free( (char *) ptr ); /* see ffrealloc() for (char *) cast */ } #define FFTABLES_NAME "fftables" #line 419 "eval.l" int ffwrap() { /* MJT -- 13 June 1996 Supplied for compatibility with pre-2.5.1 versions of flex which do not recognize %option noffwrap */ return(1); } /* expr_read is lifted from old ftools.skel. Now we can use any version of flex with no .skel file necessary! MJT - 13 June 1996 keep a memory of how many bytes have been read previously, so that an unlimited-sized buffer can be supported. PDW - 28 Feb 1998 */ static int expr_read(char *buf, int nbytes) { int n; n = 0; if( !gParse.is_eobuf ) { do { buf[n++] = gParse.expr[gParse.index++]; } while ((nlng = varNum; } return( type ); } static int find_variable(char *varName) { int i; if( gParse.nCols ) for( i=0; i. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* Tokens. */ #ifndef FFTOKENTYPE # define FFTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum fftokentype { BOOLEAN = 258, LONG = 259, DOUBLE = 260, STRING = 261, BITSTR = 262, FUNCTION = 263, BFUNCTION = 264, IFUNCTION = 265, GTIFILTER = 266, REGFILTER = 267, COLUMN = 268, BCOLUMN = 269, SCOLUMN = 270, BITCOL = 271, ROWREF = 272, NULLREF = 273, SNULLREF = 274, OR = 275, AND = 276, NE = 277, EQ = 278, GTE = 279, LTE = 280, LT = 281, GT = 282, POWER = 283, NOT = 284, FLTCAST = 285, INTCAST = 286, UMINUS = 287, DIFF = 288, ACCUM = 289 }; #endif /* Tokens. */ #define BOOLEAN 258 #define LONG 259 #define DOUBLE 260 #define STRING 261 #define BITSTR 262 #define FUNCTION 263 #define BFUNCTION 264 #define IFUNCTION 265 #define GTIFILTER 266 #define REGFILTER 267 #define COLUMN 268 #define BCOLUMN 269 #define SCOLUMN 270 #define BITCOL 271 #define ROWREF 272 #define NULLREF 273 #define SNULLREF 274 #define OR 275 #define AND 276 #define NE 277 #define EQ 278 #define GTE 279 #define LTE 280 #define LT 281 #define GT 282 #define POWER 283 #define NOT 284 #define FLTCAST 285 #define INTCAST 286 #define UMINUS 287 #define DIFF 288 #define ACCUM 289 #if ! defined FFSTYPE && ! defined FFSTYPE_IS_DECLARED typedef union FFSTYPE { /* Line 1676 of yacc.c */ #line 192 "eval.y" int Node; /* Index of Node */ double dbl; /* real value */ long lng; /* integer value */ char log; /* logical value */ char str[MAX_STRLEN]; /* string value */ /* Line 1676 of yacc.c */ #line 130 "y.tab.h" } FFSTYPE; # define FFSTYPE_IS_TRIVIAL 1 # define ffstype FFSTYPE /* obsolescent; will be withdrawn */ # define FFSTYPE_IS_DECLARED 1 #endif extern FFSTYPE fflval; cfitsio/eval_y.c0000644000225700000360000103471213246025103013433 0ustar cagordonlhea /* A Bison parser, made by GNU Bison 2.4.1. */ /* Skeleton implementation for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* C LALR(1) parser skeleton written by Richard Stallman, by simplifying the original so-called "semantic" parser. */ /* All symbols defined below should begin with ff or FF, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. There are some unavoidable exceptions within include files to define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ /* Identify Bison output. */ #define FFBISON 1 /* Bison version. */ #define FFBISON_VERSION "2.4.1" /* Skeleton name. */ #define FFSKELETON_NAME "yacc.c" /* Pure parsers. */ #define FFPURE 0 /* Push parsers. */ #define FFPUSH 0 /* Pull parsers. */ #define FFPULL 1 /* Using locations. */ #define FFLSP_NEEDED 0 /* Copy the first part of user declarations. */ /* Line 189 of yacc.c */ #line 1 "eval.y" /************************************************************************/ /* */ /* CFITSIO Lexical Parser */ /* */ /* This file is one of 3 files containing code which parses an */ /* arithmetic expression and evaluates it in the context of an input */ /* FITS file table extension. The CFITSIO lexical parser is divided */ /* into the following 3 parts/files: the CFITSIO "front-end", */ /* eval_f.c, contains the interface between the user/CFITSIO and the */ /* real core of the parser; the FLEX interpreter, eval_l.c, takes the */ /* input string and parses it into tokens and identifies the FITS */ /* information required to evaluate the expression (ie, keywords and */ /* columns); and, the BISON grammar and evaluation routines, eval_y.c, */ /* receives the FLEX output and determines and performs the actual */ /* operations. The files eval_l.c and eval_y.c are produced from */ /* running flex and bison on the files eval.l and eval.y, respectively. */ /* (flex and bison are available from any GNU archive: see www.gnu.org) */ /* */ /* The grammar rules, rather than evaluating the expression in situ, */ /* builds a tree, or Nodal, structure mapping out the order of */ /* operations and expression dependencies. This "compilation" process */ /* allows for much faster processing of multiple rows. This technique */ /* was developed by Uwe Lammers of the XMM Science Analysis System, */ /* although the CFITSIO implementation is entirely code original. */ /* */ /* */ /* Modification History: */ /* */ /* Kent Blackburn c1992 Original parser code developed for the */ /* FTOOLS software package, in particular, */ /* the fselect task. */ /* Kent Blackburn c1995 BIT column support added */ /* Peter D Wilson Feb 1998 Vector column support added */ /* Peter D Wilson May 1998 Ported to CFITSIO library. User */ /* interface routines written, in essence */ /* making fselect, fcalc, and maketime */ /* capabilities available to all tools */ /* via single function calls. */ /* Peter D Wilson Jun 1998 Major rewrite of parser core, so as to */ /* create a run-time evaluation tree, */ /* inspired by the work of Uwe Lammers, */ /* resulting in a speed increase of */ /* 10-100 times. */ /* Peter D Wilson Jul 1998 gtifilter(a,b,c,d) function added */ /* Peter D Wilson Aug 1998 regfilter(a,b,c,d) function added */ /* Peter D Wilson Jul 1999 Make parser fitsfile-independent, */ /* allowing a purely vector-based usage */ /* Craig B Markwardt Jun 2004 Add MEDIAN() function */ /* Craig B Markwardt Jun 2004 Add SUM(), and MIN/MAX() for bit arrays */ /* Craig B Markwardt Jun 2004 Allow subscripting of nX bit arrays */ /* Craig B Markwardt Jun 2004 Implement statistical functions */ /* NVALID(), AVERAGE(), and STDDEV() */ /* for integer and floating point vectors */ /* Craig B Markwardt Jun 2004 Use NULL values for range errors instead*/ /* of throwing a parse error */ /* Craig B Markwardt Oct 2004 Add ACCUM() and SEQDIFF() functions */ /* Craig B Markwardt Feb 2005 Add ANGSEP() function */ /* Craig B Markwardt Aug 2005 CIRCLE, BOX, ELLIPSE, NEAR and REGFILTER*/ /* functions now accept vector arguments */ /* Craig B Markwardt Sum 2006 Add RANDOMN() and RANDOMP() functions */ /* Craig B Markwardt Mar 2007 Allow arguments to RANDOM and RANDOMN to*/ /* determine the output dimensions */ /* Craig B Markwardt Aug 2009 Add substring STRMID() and string search*/ /* STRSTR() functions; more overflow checks*/ /* */ /************************************************************************/ #define APPROX 1.0e-7 #include "eval_defs.h" #include "region.h" #include #include #ifndef alloca #define alloca malloc #endif /* Random number generators for various distributions */ #include "simplerng.h" /* Shrink the initial stack depth to keep local data <32K (mac limit) */ /* yacc will allocate more space if needed, though. */ #define FFINITDEPTH 100 /***************************************************************/ /* Replace Bison's BACKUP macro with one that fixes a bug -- */ /* must update state after popping the stack -- and allows */ /* popping multiple terms at one time. */ /***************************************************************/ #define FFNEWBACKUP(token, value) \ do \ if (ffchar == FFEMPTY ) \ { ffchar = (token); \ memcpy( &fflval, &(value), sizeof(value) ); \ ffchar1 = FFTRANSLATE (ffchar); \ while (fflen--) FFPOPSTACK; \ ffstate = *ffssp; \ goto ffbackup; \ } \ else \ { fferror ("syntax error: cannot back up"); FFERROR; } \ while (0) /***************************************************************/ /* Useful macros for accessing/testing Nodes */ /***************************************************************/ #define TEST(a) if( (a)<0 ) FFERROR #define SIZE(a) gParse.Nodes[ a ].value.nelem #define TYPE(a) gParse.Nodes[ a ].type #define OPER(a) gParse.Nodes[ a ].operation #define PROMOTE(a,b) if( TYPE(a) > TYPE(b) ) \ b = New_Unary( TYPE(a), 0, b ); \ else if( TYPE(a) < TYPE(b) ) \ a = New_Unary( TYPE(b), 0, a ); /***** Internal functions *****/ #ifdef __cplusplus extern "C" { #endif static int Alloc_Node ( void ); static void Free_Last_Node( void ); static void Evaluate_Node ( int thisNode ); static int New_Const ( int returnType, void *value, long len ); static int New_Column( int ColNum ); static int New_Offset( int ColNum, int offset ); static int New_Unary ( int returnType, int Op, int Node1 ); static int New_BinOp ( int returnType, int Node1, int Op, int Node2 ); static int New_Func ( int returnType, funcOp Op, int nNodes, int Node1, int Node2, int Node3, int Node4, int Node5, int Node6, int Node7 ); static int New_FuncSize( int returnType, funcOp Op, int nNodes, int Node1, int Node2, int Node3, int Node4, int Node5, int Node6, int Node7, int Size); static int New_Deref ( int Var, int nDim, int Dim1, int Dim2, int Dim3, int Dim4, int Dim5 ); static int New_GTI ( char *fname, int Node1, char *start, char *stop ); static int New_REG ( char *fname, int NodeX, int NodeY, char *colNames ); static int New_Vector( int subNode ); static int Close_Vec ( int vecNode ); static int Locate_Col( Node *this ); static int Test_Dims ( int Node1, int Node2 ); static void Copy_Dims ( int Node1, int Node2 ); static void Allocate_Ptrs( Node *this ); static void Do_Unary ( Node *this ); static void Do_Offset ( Node *this ); static void Do_BinOp_bit ( Node *this ); static void Do_BinOp_str ( Node *this ); static void Do_BinOp_log ( Node *this ); static void Do_BinOp_lng ( Node *this ); static void Do_BinOp_dbl ( Node *this ); static void Do_Func ( Node *this ); static void Do_Deref ( Node *this ); static void Do_GTI ( Node *this ); static void Do_REG ( Node *this ); static void Do_Vector ( Node *this ); static long Search_GTI ( double evtTime, long nGTI, double *start, double *stop, int ordered ); static char saobox (double xcen, double ycen, double xwid, double ywid, double rot, double xcol, double ycol); static char ellipse(double xcen, double ycen, double xrad, double yrad, double rot, double xcol, double ycol); static char circle (double xcen, double ycen, double rad, double xcol, double ycol); static char bnear (double x, double y, double tolerance); static char bitcmp (char *bitstrm1, char *bitstrm2); static char bitlgte(char *bits1, int oper, char *bits2); static void bitand(char *result, char *bitstrm1, char *bitstrm2); static void bitor (char *result, char *bitstrm1, char *bitstrm2); static void bitnot(char *result, char *bits); static int cstrmid(char *dest_str, int dest_len, char *src_str, int src_len, int pos); static void fferror(char *msg); #ifdef __cplusplus } #endif /* Line 189 of yacc.c */ #line 265 "y.tab.c" /* Enabling traces. */ #ifndef FFDEBUG # define FFDEBUG 0 #endif /* Enabling verbose error messages. */ #ifdef FFERROR_VERBOSE # undef FFERROR_VERBOSE # define FFERROR_VERBOSE 1 #else # define FFERROR_VERBOSE 0 #endif /* Enabling the token table. */ #ifndef FFTOKEN_TABLE # define FFTOKEN_TABLE 0 #endif /* Tokens. */ #ifndef FFTOKENTYPE # define FFTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum fftokentype { BOOLEAN = 258, LONG = 259, DOUBLE = 260, STRING = 261, BITSTR = 262, FUNCTION = 263, BFUNCTION = 264, IFUNCTION = 265, GTIFILTER = 266, REGFILTER = 267, COLUMN = 268, BCOLUMN = 269, SCOLUMN = 270, BITCOL = 271, ROWREF = 272, NULLREF = 273, SNULLREF = 274, OR = 275, AND = 276, NE = 277, EQ = 278, GTE = 279, LTE = 280, LT = 281, GT = 282, POWER = 283, NOT = 284, FLTCAST = 285, INTCAST = 286, UMINUS = 287, DIFF = 288, ACCUM = 289 }; #endif /* Tokens. */ #define BOOLEAN 258 #define LONG 259 #define DOUBLE 260 #define STRING 261 #define BITSTR 262 #define FUNCTION 263 #define BFUNCTION 264 #define IFUNCTION 265 #define GTIFILTER 266 #define REGFILTER 267 #define COLUMN 268 #define BCOLUMN 269 #define SCOLUMN 270 #define BITCOL 271 #define ROWREF 272 #define NULLREF 273 #define SNULLREF 274 #define OR 275 #define AND 276 #define NE 277 #define EQ 278 #define GTE 279 #define LTE 280 #define LT 281 #define GT 282 #define POWER 283 #define NOT 284 #define FLTCAST 285 #define INTCAST 286 #define UMINUS 287 #define DIFF 288 #define ACCUM 289 #if ! defined FFSTYPE && ! defined FFSTYPE_IS_DECLARED typedef union FFSTYPE { /* Line 214 of yacc.c */ #line 192 "eval.y" int Node; /* Index of Node */ double dbl; /* real value */ long lng; /* integer value */ char log; /* logical value */ char str[MAX_STRLEN]; /* string value */ /* Line 214 of yacc.c */ #line 379 "y.tab.c" } FFSTYPE; # define FFSTYPE_IS_TRIVIAL 1 # define ffstype FFSTYPE /* obsolescent; will be withdrawn */ # define FFSTYPE_IS_DECLARED 1 #endif /* Copy the second part of user declarations. */ /* Line 264 of yacc.c */ #line 391 "y.tab.c" #ifdef short # undef short #endif #ifdef FFTYPE_UINT8 typedef FFTYPE_UINT8 fftype_uint8; #else typedef unsigned char fftype_uint8; #endif #ifdef FFTYPE_INT8 typedef FFTYPE_INT8 fftype_int8; #elif (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) typedef signed char fftype_int8; #else typedef short int fftype_int8; #endif #ifdef FFTYPE_UINT16 typedef FFTYPE_UINT16 fftype_uint16; #else typedef unsigned short int fftype_uint16; #endif #ifdef FFTYPE_INT16 typedef FFTYPE_INT16 fftype_int16; #else typedef short int fftype_int16; #endif #ifndef FFSIZE_T # ifdef __SIZE_TYPE__ # define FFSIZE_T __SIZE_TYPE__ # elif defined size_t # define FFSIZE_T size_t # elif ! defined FFSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # define FFSIZE_T size_t # else # define FFSIZE_T unsigned int # endif #endif #define FFSIZE_MAXIMUM ((FFSIZE_T) -1) #ifndef FF_ # if FFENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define FF_(msgid) dgettext ("bison-runtime", msgid) # endif # endif # ifndef FF_ # define FF_(msgid) msgid # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define FFUSE(e) ((void) (e)) #else # define FFUSE(e) /* empty */ #endif /* Identity function, used to suppress warnings about constant conditions. */ #ifndef lint # define FFID(n) (n) #else #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static int FFID (int ffi) #else static int FFID (ffi) int ffi; #endif { return ffi; } #endif #if ! defined ffoverflow || FFERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ # ifdef FFSTACK_USE_ALLOCA # if FFSTACK_USE_ALLOCA # ifdef __GNUC__ # define FFSTACK_ALLOC __builtin_alloca # elif defined __BUILTIN_VA_ARG_INCR # include /* INFRINGES ON USER NAME SPACE */ # elif defined _AIX # define FFSTACK_ALLOC __alloca # elif defined _MSC_VER # include /* INFRINGES ON USER NAME SPACE */ # define alloca _alloca # else # define FFSTACK_ALLOC alloca # if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # endif # endif # endif # ifdef FFSTACK_ALLOC /* Pacify GCC's `empty if-body' warning. */ # define FFSTACK_FREE(Ptr) do { /* empty */; } while (FFID (0)) # ifndef FFSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely invoke alloca (N) if N exceeds 4096. Use a slightly smaller number to allow for a few compiler-allocated temporary stack slots. */ # define FFSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ # endif # else # define FFSTACK_ALLOC FFMALLOC # define FFSTACK_FREE FFFREE # ifndef FFSTACK_ALLOC_MAXIMUM # define FFSTACK_ALLOC_MAXIMUM FFSIZE_MAXIMUM # endif # if (defined __cplusplus && ! defined _STDLIB_H \ && ! ((defined FFMALLOC || defined malloc) \ && (defined FFFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # ifndef FFMALLOC # define FFMALLOC malloc # if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void *malloc (FFSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef FFFREE # define FFFREE free # if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif # endif #endif /* ! defined ffoverflow || FFERROR_VERBOSE */ #if (! defined ffoverflow \ && (! defined __cplusplus \ || (defined FFSTYPE_IS_TRIVIAL && FFSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union ffalloc { fftype_int16 ffss_alloc; FFSTYPE ffvs_alloc; }; /* The size of the maximum gap between one aligned stack and the next. */ # define FFSTACK_GAP_MAXIMUM (sizeof (union ffalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define FFSTACK_BYTES(N) \ ((N) * (sizeof (fftype_int16) + sizeof (FFSTYPE)) \ + FFSTACK_GAP_MAXIMUM) /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ # ifndef FFCOPY # if defined __GNUC__ && 1 < __GNUC__ # define FFCOPY(To, From, Count) \ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) # else # define FFCOPY(To, From, Count) \ do \ { \ FFSIZE_T ffi; \ for (ffi = 0; ffi < (Count); ffi++) \ (To)[ffi] = (From)[ffi]; \ } \ while (FFID (0)) # endif # endif /* Relocate STACK from its old location to the new one. The local variables FFSIZE and FFSTACKSIZE give the old and new number of elements in the stack, and FFPTR gives the new location of the stack. Advance FFPTR to a properly aligned location for the next stack. */ # define FFSTACK_RELOCATE(Stack_alloc, Stack) \ do \ { \ FFSIZE_T ffnewbytes; \ FFCOPY (&ffptr->Stack_alloc, Stack, ffsize); \ Stack = &ffptr->Stack_alloc; \ ffnewbytes = ffstacksize * sizeof (*Stack) + FFSTACK_GAP_MAXIMUM; \ ffptr += ffnewbytes / sizeof (*ffptr); \ } \ while (FFID (0)) #endif /* FFFINAL -- State number of the termination state. */ #define FFFINAL 2 /* FFLAST -- Last index in FFTABLE. */ #define FFLAST 1603 /* FFNTOKENS -- Number of terminals. */ #define FFNTOKENS 54 /* FFNNTS -- Number of nonterminals. */ #define FFNNTS 9 /* FFNRULES -- Number of rules. */ #define FFNRULES 125 /* FFNRULES -- Number of states. */ #define FFNSTATES 290 /* FFTRANSLATE(FFLEX) -- Bison symbol number corresponding to FFLEX. */ #define FFUNDEFTOK 2 #define FFMAXUTOK 289 #define FFTRANSLATE(FFX) \ ((unsigned int) (FFX) <= FFMAXUTOK ? fftranslate[FFX] : FFUNDEFTOK) /* FFTRANSLATE[FFLEX] -- Bison symbol number corresponding to FFLEX. */ static const fftype_uint8 fftranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 50, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 37, 41, 2, 52, 53, 38, 35, 20, 36, 2, 39, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 21, 2, 25, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 47, 2, 51, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 23, 40, 24, 28, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 26, 27, 29, 30, 31, 32, 33, 34, 42, 43, 44, 45, 46, 48, 49 }; #if FFDEBUG /* FFPRHS[FFN] -- Index of the first RHS symbol of rule number FFN in FFRHS. */ static const fftype_uint16 ffprhs[] = { 0, 0, 3, 4, 7, 9, 12, 15, 18, 21, 24, 27, 31, 34, 38, 42, 46, 49, 52, 54, 56, 61, 65, 69, 73, 78, 85, 94, 105, 118, 121, 125, 127, 129, 131, 136, 138, 140, 144, 148, 152, 156, 160, 164, 167, 170, 174, 178, 182, 188, 194, 200, 203, 207, 211, 215, 219, 225, 231, 241, 246, 253, 262, 273, 286, 289, 292, 295, 298, 300, 302, 307, 311, 315, 319, 323, 327, 331, 335, 339, 343, 347, 351, 355, 359, 363, 367, 371, 375, 379, 383, 387, 391, 395, 399, 405, 411, 415, 419, 423, 429, 437, 449, 465, 468, 472, 478, 488, 492, 500, 510, 515, 522, 531, 542, 555, 558, 562, 564, 566, 571, 573, 577, 581, 587, 593 }; /* FFRHS -- A `-1'-separated list of the rules' RHS. */ static const fftype_int8 ffrhs[] = { 55, 0, -1, -1, 55, 56, -1, 50, -1, 59, 50, -1, 60, 50, -1, 62, 50, -1, 61, 50, -1, 1, 50, -1, 23, 60, -1, 57, 20, 60, -1, 23, 59, -1, 58, 20, 59, -1, 58, 20, 60, -1, 57, 20, 59, -1, 58, 24, -1, 57, 24, -1, 7, -1, 16, -1, 16, 23, 59, 24, -1, 61, 41, 61, -1, 61, 40, 61, -1, 61, 35, 61, -1, 61, 47, 59, 51, -1, 61, 47, 59, 20, 59, 51, -1, 61, 47, 59, 20, 59, 20, 59, 51, -1, 61, 47, 59, 20, 59, 20, 59, 20, 59, 51, -1, 61, 47, 59, 20, 59, 20, 59, 20, 59, 20, 59, 51, -1, 43, 61, -1, 52, 61, 53, -1, 4, -1, 5, -1, 13, -1, 13, 23, 59, 24, -1, 17, -1, 18, -1, 59, 37, 59, -1, 59, 35, 59, -1, 59, 36, 59, -1, 59, 38, 59, -1, 59, 39, 59, -1, 59, 42, 59, -1, 35, 59, -1, 36, 59, -1, 52, 59, 53, -1, 59, 38, 60, -1, 60, 38, 59, -1, 60, 25, 59, 22, 59, -1, 60, 25, 60, 22, 59, -1, 60, 25, 59, 22, 60, -1, 8, 53, -1, 8, 60, 53, -1, 8, 62, 53, -1, 8, 61, 53, -1, 8, 59, 53, -1, 10, 62, 20, 62, 53, -1, 8, 59, 20, 59, 53, -1, 8, 59, 20, 59, 20, 59, 20, 59, 53, -1, 59, 47, 59, 51, -1, 59, 47, 59, 20, 59, 51, -1, 59, 47, 59, 20, 59, 20, 59, 51, -1, 59, 47, 59, 20, 59, 20, 59, 20, 59, 51, -1, 59, 47, 59, 20, 59, 20, 59, 20, 59, 20, 59, 51, -1, 45, 59, -1, 45, 60, -1, 44, 59, -1, 44, 60, -1, 3, -1, 14, -1, 14, 23, 59, 24, -1, 61, 30, 61, -1, 61, 29, 61, -1, 61, 33, 61, -1, 61, 32, 61, -1, 61, 34, 61, -1, 61, 31, 61, -1, 59, 34, 59, -1, 59, 33, 59, -1, 59, 31, 59, -1, 59, 32, 59, -1, 59, 28, 59, -1, 59, 30, 59, -1, 59, 29, 59, -1, 62, 30, 62, -1, 62, 29, 62, -1, 62, 34, 62, -1, 62, 31, 62, -1, 62, 33, 62, -1, 62, 32, 62, -1, 60, 27, 60, -1, 60, 26, 60, -1, 60, 30, 60, -1, 60, 29, 60, -1, 59, 21, 59, 22, 59, -1, 60, 25, 60, 22, 60, -1, 9, 59, 53, -1, 9, 60, 53, -1, 9, 62, 53, -1, 8, 60, 20, 60, 53, -1, 9, 59, 20, 59, 20, 59, 53, -1, 9, 59, 20, 59, 20, 59, 20, 59, 20, 59, 53, -1, 9, 59, 20, 59, 20, 59, 20, 59, 20, 59, 20, 59, 20, 59, 53, -1, 11, 53, -1, 11, 6, 53, -1, 11, 6, 20, 59, 53, -1, 11, 6, 20, 59, 20, 6, 20, 6, 53, -1, 12, 6, 53, -1, 12, 6, 20, 59, 20, 59, 53, -1, 12, 6, 20, 59, 20, 59, 20, 6, 53, -1, 60, 47, 59, 51, -1, 60, 47, 59, 20, 59, 51, -1, 60, 47, 59, 20, 59, 20, 59, 51, -1, 60, 47, 59, 20, 59, 20, 59, 20, 59, 51, -1, 60, 47, 59, 20, 59, 20, 59, 20, 59, 20, 59, 51, -1, 43, 60, -1, 52, 60, 53, -1, 6, -1, 15, -1, 15, 23, 59, 24, -1, 19, -1, 52, 62, 53, -1, 62, 35, 62, -1, 60, 25, 62, 22, 62, -1, 8, 62, 20, 62, 53, -1, 8, 62, 20, 59, 20, 59, 53, -1 }; /* FFRLINE[FFN] -- source line where rule number FFN was defined. */ static const fftype_uint16 ffrline[] = { 0, 244, 244, 245, 248, 249, 255, 261, 267, 273, 276, 278, 291, 293, 306, 317, 331, 335, 339, 343, 345, 354, 357, 360, 369, 371, 373, 375, 377, 379, 382, 386, 388, 390, 392, 401, 403, 405, 408, 411, 414, 417, 420, 423, 425, 427, 429, 433, 437, 456, 475, 494, 505, 519, 531, 562, 657, 665, 727, 751, 753, 755, 757, 759, 761, 763, 765, 767, 771, 773, 775, 784, 787, 790, 793, 796, 799, 802, 805, 808, 811, 814, 817, 820, 823, 826, 829, 832, 835, 838, 841, 843, 845, 847, 850, 857, 874, 887, 900, 911, 927, 951, 979, 1016, 1020, 1024, 1027, 1031, 1035, 1038, 1042, 1044, 1046, 1048, 1050, 1052, 1054, 1058, 1061, 1063, 1072, 1074, 1076, 1085, 1104, 1123 }; #endif #if FFDEBUG || FFERROR_VERBOSE || FFTOKEN_TABLE /* FFTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at FFNTOKENS, nonterminals. */ static const char *const fftname[] = { "$end", "error", "$undefined", "BOOLEAN", "LONG", "DOUBLE", "STRING", "BITSTR", "FUNCTION", "BFUNCTION", "IFUNCTION", "GTIFILTER", "REGFILTER", "COLUMN", "BCOLUMN", "SCOLUMN", "BITCOL", "ROWREF", "NULLREF", "SNULLREF", "','", "'='", "':'", "'{'", "'}'", "'?'", "OR", "AND", "'~'", "NE", "EQ", "GTE", "LTE", "LT", "GT", "'+'", "'-'", "'%'", "'*'", "'/'", "'|'", "'&'", "POWER", "NOT", "FLTCAST", "INTCAST", "UMINUS", "'['", "DIFF", "ACCUM", "'\\n'", "']'", "'('", "')'", "$accept", "lines", "line", "bvector", "vector", "expr", "bexpr", "bits", "sexpr", 0 }; #endif # ifdef FFPRINT /* FFTOKNUM[FFLEX-NUM] -- Internal token number corresponding to token FFLEX-NUM. */ static const fftype_uint16 fftoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 44, 61, 58, 123, 125, 63, 275, 276, 126, 277, 278, 279, 280, 281, 282, 43, 45, 37, 42, 47, 124, 38, 283, 284, 285, 286, 287, 91, 288, 289, 10, 93, 40, 41 }; # endif /* FFR1[FFN] -- Symbol number of symbol that rule FFN derives. */ static const fftype_uint8 ffr1[] = { 0, 54, 55, 55, 56, 56, 56, 56, 56, 56, 57, 57, 58, 58, 58, 58, 59, 60, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 62, 62, 62, 62, 62, 62, 62, 62, 62 }; /* FFR2[FFN] -- Number of symbols composing right hand side of rule FFN. */ static const fftype_uint8 ffr2[] = { 0, 2, 0, 2, 1, 2, 2, 2, 2, 2, 2, 3, 2, 3, 3, 3, 2, 2, 1, 1, 4, 3, 3, 3, 4, 6, 8, 10, 12, 2, 3, 1, 1, 1, 4, 1, 1, 3, 3, 3, 3, 3, 3, 2, 2, 3, 3, 3, 5, 5, 5, 2, 3, 3, 3, 3, 5, 5, 9, 4, 6, 8, 10, 12, 2, 2, 2, 2, 1, 1, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 3, 3, 3, 5, 7, 11, 15, 2, 3, 5, 9, 3, 7, 9, 4, 6, 8, 10, 12, 2, 3, 1, 1, 4, 1, 3, 3, 5, 5, 7 }; /* FFDEFACT[STATE-NAME] -- Default rule to reduce with in state STATE-NUM when FFTABLE doesn't specify something else to do. Zero means the default is an error. */ static const fftype_uint8 ffdefact[] = { 2, 0, 1, 0, 68, 31, 32, 117, 18, 0, 0, 0, 0, 0, 33, 69, 118, 19, 35, 36, 120, 0, 0, 0, 0, 0, 0, 4, 0, 3, 0, 0, 0, 0, 0, 0, 9, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 12, 10, 0, 43, 44, 115, 29, 66, 67, 64, 65, 0, 0, 0, 0, 0, 17, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 7, 0, 55, 0, 52, 54, 0, 53, 0, 96, 97, 98, 0, 0, 104, 0, 107, 0, 0, 0, 0, 45, 116, 30, 121, 15, 11, 13, 14, 0, 81, 83, 82, 79, 80, 78, 77, 38, 39, 37, 40, 46, 41, 42, 0, 0, 0, 0, 91, 90, 93, 92, 47, 0, 0, 0, 72, 71, 76, 74, 73, 75, 23, 22, 21, 0, 85, 84, 87, 89, 88, 86, 122, 0, 0, 0, 0, 0, 0, 0, 0, 34, 70, 119, 20, 0, 0, 59, 0, 0, 0, 0, 110, 29, 0, 0, 24, 0, 57, 99, 0, 124, 0, 56, 0, 105, 0, 94, 0, 48, 50, 49, 95, 123, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 111, 0, 25, 0, 125, 0, 100, 0, 0, 108, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 112, 0, 26, 58, 0, 106, 109, 0, 0, 0, 0, 0, 62, 0, 113, 0, 27, 0, 101, 0, 0, 0, 0, 63, 114, 28, 0, 0, 102 }; /* FFDEFGOTO[NTERM-NUM]. */ static const fftype_int8 ffdefgoto[] = { -1, 1, 29, 30, 31, 46, 47, 44, 58 }; /* FFPACT[STATE-NUM] -- Index in FFTABLE of the portion describing STATE-NUM. */ #define FFPACT_NINF -46 static const fftype_int16 ffpact[] = { -46, 297, -46, -45, -46, -46, -46, -46, -46, 347, 398, 398, -5, 0, -4, 5, 19, 23, -46, -46, -46, 398, 398, 398, 398, 398, 398, -46, 398, -46, 6, 17, 1088, 296, 1468, 1490, -46, -46, 424, 9, 1374, 135, 452, 168, 1518, 344, 1355, 1449, 1555, -10, -46, -9, 398, 398, 398, 398, 1355, 1449, 250, -2, -2, 10, 11, -2, 10, -2, 10, 619, 240, 1399, 1424, 398, -46, 398, -46, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, -46, 398, 398, 398, 398, 398, 398, 398, -46, -3, -3, -3, -3, -3, -3, -3, -3, -3, 398, -46, 398, 398, 398, 398, 398, 398, 398, -46, 398, -46, 398, -46, -46, 398, -46, 398, -46, -46, -46, 398, 398, -46, 398, -46, 1231, 1251, 1271, 1291, -46, -46, -46, -46, 1355, 1449, 1355, 1449, 1313, 1535, 1535, 1535, 1556, 1556, 1556, 1556, 55, 55, 55, -40, 10, -40, -40, 728, 1335, 400, 201, 74, 111, -35, -35, -40, 752, -3, -3, 24, 24, 24, 24, 24, 24, 79, 11, 11, 776, -17, -17, 28, 28, 28, 28, -46, 480, 342, 1111, 1431, 1131, 1438, 508, 1151, -46, -46, -46, -46, 398, 398, -46, 398, 398, 398, 398, -46, 11, 20, 398, -46, 398, -46, -46, 398, -46, 398, -46, 60, -46, 398, 1499, 800, 1499, 1449, 1499, 1449, 250, 824, 848, 1171, 646, 536, 48, 564, 398, -46, 398, -46, 398, -46, 398, -46, 398, -46, 63, 83, -46, 872, 896, 920, 673, 1191, 39, 45, 398, -46, 398, -46, 398, -46, -46, 398, -46, -46, 944, 968, 992, 592, 398, -46, 398, -46, 398, -46, 398, -46, 1016, 1040, 1064, 1211, -46, -46, -46, 398, 700, -46 }; /* FFPGOTO[NTERM-NUM]. */ static const fftype_int16 ffpgoto[] = { -46, -46, -46, -46, -46, -1, 90, 147, 22 }; /* FFTABLE[FFPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what FFDEFACT says. If FFTABLE_NINF, syntax error. */ #define FFTABLE_NINF -1 static const fftype_uint16 fftable[] = { 32, 49, 88, 96, 8, 36, 51, 89, 38, 42, 130, 132, 97, 17, 112, 113, 114, 115, 116, 52, 56, 59, 60, 35, 63, 65, 71, 67, 53, 120, 72, 41, 45, 48, 91, 92, 93, 73, 94, 95, 171, 74, 54, 131, 133, 89, 55, 96, 50, 172, 70, 134, 135, 136, 137, 105, 97, 97, 108, 105, 106, 107, 121, 116, 106, 107, 236, 108, 248, 256, 142, 108, 144, 140, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 159, 160, 161, 257, 162, 33, 266, 86, 87, 169, 170, 88, 267, 39, 43, 93, 89, 94, 95, 0, 0, 182, 0, 0, 0, 57, 96, 164, 61, 64, 66, 190, 68, 106, 107, 97, 192, 0, 194, 0, 108, 0, 0, 196, 0, 197, 183, 184, 185, 186, 187, 188, 189, 0, 94, 95, 0, 0, 0, 193, 0, 0, 34, 96, 0, 195, 0, 0, 0, 123, 40, 0, 97, 0, 0, 143, 0, 145, 110, 111, 112, 113, 114, 115, 116, 62, 0, 0, 0, 69, 158, 0, 0, 0, 0, 163, 165, 166, 167, 168, 0, 0, 124, 0, 0, 0, 0, 91, 92, 93, 0, 94, 95, 0, 0, 224, 225, 0, 226, 228, 96, 231, 0, 0, 191, 232, 0, 233, 0, 97, 234, 0, 235, 0, 0, 127, 237, 207, 0, 0, 0, 0, 0, 230, 110, 111, 112, 113, 114, 115, 116, 251, 0, 252, 0, 253, 0, 254, 0, 255, 173, 174, 175, 176, 177, 178, 179, 180, 181, 0, 0, 268, 0, 269, 0, 270, 0, 0, 271, 91, 92, 93, 0, 94, 95, 280, 0, 281, 0, 282, 0, 283, 96, 110, 111, 112, 113, 114, 115, 116, 288, 97, 0, 0, 0, 0, 0, 139, 0, 227, 229, 2, 3, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 210, 211, 21, 91, 92, 93, 0, 94, 95, 0, 0, 0, 0, 0, 22, 23, 96, 0, 0, 0, 0, 0, 24, 25, 26, 97, 0, 0, 98, 27, 0, 28, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 91, 92, 93, 21, 94, 95, 110, 111, 112, 113, 114, 115, 116, 96, 0, 22, 23, 0, 0, 0, 0, 0, 97, 24, 25, 26, 0, 0, 216, 0, 128, 0, 28, 37, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 0, 0, 21, 206, 0, 0, 91, 92, 93, 0, 94, 95, 0, 0, 22, 23, 0, 0, 0, 96, 0, 0, 24, 25, 26, 118, 75, 0, 97, 0, 0, 28, 0, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, 0, 0, 0, 89, 125, 75, 0, 0, 0, 119, 0, 0, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, 0, 0, 0, 89, 214, 75, 0, 0, 0, 126, 0, 0, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, 0, 0, 0, 89, 221, 75, 0, 0, 0, 215, 0, 0, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, 0, 0, 0, 89, 246, 75, 0, 0, 0, 222, 0, 0, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, 0, 0, 0, 89, 249, 75, 0, 0, 0, 247, 0, 0, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, 0, 0, 0, 89, 278, 75, 0, 0, 0, 250, 0, 0, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, 0, 0, 0, 89, 75, 0, 0, 0, 0, 279, 0, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, 0, 0, 0, 89, 75, 0, 0, 0, 0, 138, 0, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, 0, 0, 0, 89, 75, 0, 0, 0, 0, 245, 0, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, 0, 0, 0, 89, 75, 0, 0, 0, 0, 264, 0, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, 0, 0, 0, 89, 203, 75, 0, 0, 0, 289, 0, 0, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, 208, 75, 0, 89, 0, 0, 0, 204, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, 212, 75, 0, 89, 0, 0, 0, 209, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, 238, 75, 0, 89, 0, 0, 0, 213, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, 240, 75, 0, 89, 0, 0, 0, 239, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, 242, 75, 0, 89, 0, 0, 0, 241, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, 258, 75, 0, 89, 0, 0, 0, 243, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, 260, 75, 0, 89, 0, 0, 0, 259, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, 262, 75, 0, 89, 0, 0, 0, 261, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, 272, 75, 0, 89, 0, 0, 0, 263, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, 274, 75, 0, 89, 0, 0, 0, 273, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, 276, 75, 0, 89, 0, 0, 0, 275, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, 0, 75, 0, 89, 0, 0, 0, 277, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, 0, 75, 0, 89, 0, 0, 0, 284, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, 0, 75, 0, 89, 0, 0, 0, 285, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, 0, 75, 0, 89, 0, 0, 0, 286, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 217, 75, 0, 0, 89, 0, 0, 90, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 219, 75, 88, 0, 0, 0, 0, 89, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 223, 75, 88, 0, 0, 0, 0, 89, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 244, 75, 88, 0, 0, 0, 0, 89, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 265, 75, 88, 0, 0, 0, 0, 89, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 287, 75, 88, 0, 0, 0, 0, 89, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 75, 88, 0, 198, 0, 0, 89, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 75, 88, 0, 199, 0, 0, 89, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 75, 88, 0, 200, 0, 0, 89, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 75, 88, 0, 201, 0, 0, 89, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 75, 202, 0, 0, 89, 0, 0, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 75, 205, 0, 0, 89, 0, 0, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 75, 88, 0, 0, 0, 0, 89, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 0, 88, 0, 0, 0, 0, 89, 99, 100, 101, 102, 103, 104, 105, 0, 0, 0, 0, 106, 107, 0, 0, 0, 0, 0, 108, 0, 0, 0, 0, 0, 122, 99, 100, 101, 102, 103, 104, 105, 0, 0, 0, 0, 106, 107, 0, 0, 0, 0, 0, 108, 0, 0, 0, 0, 0, 140, 110, 111, 112, 113, 114, 115, 116, 110, 111, 112, 113, 114, 115, 116, 110, 111, 112, 113, 114, 115, 116, 91, 92, 93, 141, 94, 95, 0, 0, 0, 0, 218, 0, 0, 96, 0, 0, 0, 220, 0, 0, 0, 0, 97, 99, 100, 101, 102, 103, 104, 105, 0, 0, 0, 0, 106, 107, 0, 0, 0, 0, 0, 108, 0, 0, 109, 110, 111, 112, 113, 114, 115, 116, 0, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 0, 117, 88, 0, 0, 0, 0, 89, 99, 100, 101, 102, 103, 104, 105, 0, 0, 0, 0, 106, 107, 0, 0, 0, 0, 0, 108, 79, 80, 81, 82, 83, 84, 85, 86, 87, 129, 0, 88, 0, 0, 0, 0, 89, 0, 110, 111, 112, 113, 114, 115, 116, 83, 84, 85, 86, 87, 0, 0, 88, 0, 0, 0, 0, 89 }; static const fftype_int16 ffcheck[] = { 1, 6, 42, 38, 7, 50, 6, 47, 9, 10, 20, 20, 47, 16, 31, 32, 33, 34, 35, 23, 21, 22, 23, 1, 25, 26, 20, 28, 23, 20, 24, 9, 10, 11, 25, 26, 27, 20, 29, 30, 43, 24, 23, 53, 53, 47, 23, 38, 53, 52, 28, 52, 53, 54, 55, 35, 47, 47, 47, 35, 40, 41, 53, 35, 40, 41, 6, 47, 20, 6, 71, 47, 73, 53, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 6, 91, 1, 53, 38, 39, 96, 97, 42, 53, 9, 10, 27, 47, 29, 30, -1, -1, 108, -1, -1, -1, 21, 38, 91, 24, 25, 26, 118, 28, 40, 41, 47, 123, -1, 125, -1, 47, -1, -1, 130, -1, 132, 110, 111, 112, 113, 114, 115, 116, -1, 29, 30, -1, -1, -1, 123, -1, -1, 1, 38, -1, 129, -1, -1, -1, 20, 9, -1, 47, -1, -1, 71, -1, 73, 29, 30, 31, 32, 33, 34, 35, 24, -1, -1, -1, 28, 86, -1, -1, -1, -1, 91, 92, 93, 94, 95, -1, -1, 53, -1, -1, -1, -1, 25, 26, 27, -1, 29, 30, -1, -1, 202, 203, -1, 205, 206, 38, 208, -1, -1, 120, 212, -1, 214, -1, 47, 217, -1, 219, -1, -1, 53, 223, 22, -1, -1, -1, -1, -1, 207, 29, 30, 31, 32, 33, 34, 35, 238, -1, 240, -1, 242, -1, 244, -1, 246, 99, 100, 101, 102, 103, 104, 105, 106, 107, -1, -1, 258, -1, 260, -1, 262, -1, -1, 265, 25, 26, 27, -1, 29, 30, 272, -1, 274, -1, 276, -1, 278, 38, 29, 30, 31, 32, 33, 34, 35, 287, 47, -1, -1, -1, -1, -1, 53, -1, 205, 206, 0, 1, -1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -1, 171, 172, 23, 25, 26, 27, -1, 29, 30, -1, -1, -1, -1, -1, 35, 36, 38, -1, -1, -1, -1, -1, 43, 44, 45, 47, -1, -1, 50, 50, -1, 52, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 25, 26, 27, 23, 29, 30, 29, 30, 31, 32, 33, 34, 35, 38, -1, 35, 36, -1, -1, -1, -1, -1, 47, 43, 44, 45, -1, -1, 53, -1, 53, -1, 52, 53, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -1, -1, -1, 23, 22, -1, -1, 25, 26, 27, -1, 29, 30, -1, -1, 35, 36, -1, -1, -1, 38, -1, -1, 43, 44, 45, 20, 21, -1, 47, -1, -1, 52, -1, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, -1, -1, -1, 47, 20, 21, -1, -1, -1, 53, -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, -1, -1, -1, 47, 20, 21, -1, -1, -1, 53, -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, -1, -1, -1, 47, 20, 21, -1, -1, -1, 53, -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, -1, -1, -1, 47, 20, 21, -1, -1, -1, 53, -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, -1, -1, -1, 47, 20, 21, -1, -1, -1, 53, -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, -1, -1, -1, 47, 20, 21, -1, -1, -1, 53, -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, -1, -1, -1, 47, 21, -1, -1, -1, -1, 53, -1, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, -1, -1, -1, 47, 21, -1, -1, -1, -1, 53, -1, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, -1, -1, -1, 47, 21, -1, -1, -1, -1, 53, -1, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, -1, -1, -1, 47, 21, -1, -1, -1, -1, 53, -1, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, -1, -1, -1, 47, 20, 21, -1, -1, -1, 53, -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, 20, 21, -1, 47, -1, -1, -1, 51, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, 20, 21, -1, 47, -1, -1, -1, 51, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, 20, 21, -1, 47, -1, -1, -1, 51, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, 20, 21, -1, 47, -1, -1, -1, 51, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, 20, 21, -1, 47, -1, -1, -1, 51, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, 20, 21, -1, 47, -1, -1, -1, 51, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, 20, 21, -1, 47, -1, -1, -1, 51, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, 20, 21, -1, 47, -1, -1, -1, 51, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, 20, 21, -1, 47, -1, -1, -1, 51, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, 20, 21, -1, 47, -1, -1, -1, 51, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, 20, 21, -1, 47, -1, -1, -1, 51, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, -1, 21, -1, 47, -1, -1, -1, 51, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, -1, 21, -1, 47, -1, -1, -1, 51, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, -1, 21, -1, 47, -1, -1, -1, 51, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, -1, 21, -1, 47, -1, -1, -1, 51, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, 20, 21, -1, -1, 47, -1, -1, 50, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 20, 21, 42, -1, -1, -1, -1, 47, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 20, 21, 42, -1, -1, -1, -1, 47, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 20, 21, 42, -1, -1, -1, -1, 47, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 20, 21, 42, -1, -1, -1, -1, 47, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 20, 21, 42, -1, -1, -1, -1, 47, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, 21, 42, -1, 24, -1, -1, 47, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, 21, 42, -1, 24, -1, -1, 47, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, 21, 42, -1, 24, -1, -1, 47, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, 21, 42, -1, 24, -1, -1, 47, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, 21, 22, -1, -1, 47, -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, 21, 22, -1, -1, 47, -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, 21, 42, -1, -1, -1, -1, 47, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 42, -1, -1, -1, -1, 47, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, 40, 41, -1, -1, -1, -1, -1, 47, -1, -1, -1, -1, -1, 53, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, 40, 41, -1, -1, -1, -1, -1, 47, -1, -1, -1, -1, -1, 53, 29, 30, 31, 32, 33, 34, 35, 29, 30, 31, 32, 33, 34, 35, 29, 30, 31, 32, 33, 34, 35, 25, 26, 27, 53, 29, 30, -1, -1, -1, -1, 53, -1, -1, 38, -1, -1, -1, 53, -1, -1, -1, -1, 47, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, 40, 41, -1, -1, -1, -1, -1, 47, -1, -1, 50, 29, 30, 31, 32, 33, 34, 35, -1, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, 50, 42, -1, -1, -1, -1, 47, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, 40, 41, -1, -1, -1, -1, -1, 47, 31, 32, 33, 34, 35, 36, 37, 38, 39, 20, -1, 42, -1, -1, -1, -1, 47, -1, 29, 30, 31, 32, 33, 34, 35, 35, 36, 37, 38, 39, -1, -1, 42, -1, -1, -1, -1, 47 }; /* FFSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const fftype_uint8 ffstos[] = { 0, 55, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 23, 35, 36, 43, 44, 45, 50, 52, 56, 57, 58, 59, 60, 61, 62, 50, 53, 59, 60, 61, 62, 59, 60, 61, 62, 59, 60, 62, 6, 53, 6, 23, 23, 23, 23, 59, 60, 62, 59, 59, 60, 61, 59, 60, 59, 60, 59, 60, 61, 62, 20, 24, 20, 24, 21, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 42, 47, 50, 25, 26, 27, 29, 30, 38, 47, 50, 29, 30, 31, 32, 33, 34, 35, 40, 41, 47, 50, 29, 30, 31, 32, 33, 34, 35, 50, 20, 53, 20, 53, 53, 20, 53, 20, 53, 53, 53, 20, 20, 53, 20, 53, 59, 59, 59, 59, 53, 53, 53, 53, 59, 60, 59, 60, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 60, 59, 59, 59, 59, 60, 62, 60, 60, 60, 60, 59, 59, 43, 52, 61, 61, 61, 61, 61, 61, 61, 61, 61, 59, 62, 62, 62, 62, 62, 62, 62, 59, 60, 59, 62, 59, 62, 59, 59, 24, 24, 24, 24, 22, 20, 51, 22, 22, 22, 20, 51, 61, 61, 20, 51, 20, 53, 53, 20, 53, 20, 53, 20, 53, 20, 59, 59, 59, 60, 59, 60, 62, 59, 59, 59, 59, 59, 6, 59, 20, 51, 20, 51, 20, 51, 20, 53, 20, 53, 20, 20, 53, 59, 59, 59, 59, 59, 6, 6, 20, 51, 20, 51, 20, 51, 53, 20, 53, 53, 59, 59, 59, 59, 20, 51, 20, 51, 20, 51, 20, 53, 59, 59, 59, 59, 51, 51, 51, 20, 59, 53 }; #define fferrok (fferrstatus = 0) #define ffclearin (ffchar = FFEMPTY) #define FFEMPTY (-2) #define FFEOF 0 #define FFACCEPT goto ffacceptlab #define FFABORT goto ffabortlab #define FFERROR goto fferrorlab /* Like FFERROR except do call fferror. This remains here temporarily to ease the transition to the new meaning of FFERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ #define FFFAIL goto fferrlab #define FFRECOVERING() (!!fferrstatus) #define FFBACKUP(Token, Value) \ do \ if (ffchar == FFEMPTY && fflen == 1) \ { \ ffchar = (Token); \ fflval = (Value); \ fftoken = FFTRANSLATE (ffchar); \ FFPOPSTACK (1); \ goto ffbackup; \ } \ else \ { \ fferror (FF_("syntax error: cannot back up")); \ FFERROR; \ } \ while (FFID (0)) #define FFTERROR 1 #define FFERRCODE 256 /* FFLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. If N is 0, then set CURRENT to the empty location which ends the previous symbol: RHS[0] (always defined). */ #define FFRHSLOC(Rhs, K) ((Rhs)[K]) #ifndef FFLLOC_DEFAULT # define FFLLOC_DEFAULT(Current, Rhs, N) \ do \ if (FFID (N)) \ { \ (Current).first_line = FFRHSLOC (Rhs, 1).first_line; \ (Current).first_column = FFRHSLOC (Rhs, 1).first_column; \ (Current).last_line = FFRHSLOC (Rhs, N).last_line; \ (Current).last_column = FFRHSLOC (Rhs, N).last_column; \ } \ else \ { \ (Current).first_line = (Current).last_line = \ FFRHSLOC (Rhs, 0).last_line; \ (Current).first_column = (Current).last_column = \ FFRHSLOC (Rhs, 0).last_column; \ } \ while (FFID (0)) #endif /* FF_LOCATION_PRINT -- Print the location on the stream. This macro was not mandated originally: define only if we know we won't break user code: when these are the locations we know. */ #ifndef FF_LOCATION_PRINT # if FFLTYPE_IS_TRIVIAL # define FF_LOCATION_PRINT(File, Loc) \ fprintf (File, "%d.%d-%d.%d", \ (Loc).first_line, (Loc).first_column, \ (Loc).last_line, (Loc).last_column) # else # define FF_LOCATION_PRINT(File, Loc) ((void) 0) # endif #endif /* FFLEX -- calling `fflex' with the right arguments. */ #ifdef FFLEX_PARAM # define FFLEX fflex (FFLEX_PARAM) #else # define FFLEX fflex () #endif /* Enable debugging if requested. */ #if FFDEBUG # ifndef FFFPRINTF # include /* INFRINGES ON USER NAME SPACE */ # define FFFPRINTF fprintf # endif # define FFDPRINTF(Args) \ do { \ if (ffdebug) \ FFFPRINTF Args; \ } while (FFID (0)) # define FF_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ if (ffdebug) \ { \ FFFPRINTF (stderr, "%s ", Title); \ ff_symbol_print (stderr, \ Type, Value); \ FFFPRINTF (stderr, "\n"); \ } \ } while (FFID (0)) /*--------------------------------. | Print this symbol on FFOUTPUT. | `--------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void ff_symbol_value_print (FILE *ffoutput, int fftype, FFSTYPE const * const ffvaluep) #else static void ff_symbol_value_print (ffoutput, fftype, ffvaluep) FILE *ffoutput; int fftype; FFSTYPE const * const ffvaluep; #endif { if (!ffvaluep) return; # ifdef FFPRINT if (fftype < FFNTOKENS) FFPRINT (ffoutput, fftoknum[fftype], *ffvaluep); # else FFUSE (ffoutput); # endif switch (fftype) { default: break; } } /*--------------------------------. | Print this symbol on FFOUTPUT. | `--------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void ff_symbol_print (FILE *ffoutput, int fftype, FFSTYPE const * const ffvaluep) #else static void ff_symbol_print (ffoutput, fftype, ffvaluep) FILE *ffoutput; int fftype; FFSTYPE const * const ffvaluep; #endif { if (fftype < FFNTOKENS) FFFPRINTF (ffoutput, "token %s (", fftname[fftype]); else FFFPRINTF (ffoutput, "nterm %s (", fftname[fftype]); ff_symbol_value_print (ffoutput, fftype, ffvaluep); FFFPRINTF (ffoutput, ")"); } /*------------------------------------------------------------------. | ff_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void ff_stack_print (fftype_int16 *ffbottom, fftype_int16 *fftop) #else static void ff_stack_print (ffbottom, fftop) fftype_int16 *ffbottom; fftype_int16 *fftop; #endif { FFFPRINTF (stderr, "Stack now"); for (; ffbottom <= fftop; ffbottom++) { int ffbot = *ffbottom; FFFPRINTF (stderr, " %d", ffbot); } FFFPRINTF (stderr, "\n"); } # define FF_STACK_PRINT(Bottom, Top) \ do { \ if (ffdebug) \ ff_stack_print ((Bottom), (Top)); \ } while (FFID (0)) /*------------------------------------------------. | Report that the FFRULE is going to be reduced. | `------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void ff_reduce_print (FFSTYPE *ffvsp, int ffrule) #else static void ff_reduce_print (ffvsp, ffrule) FFSTYPE *ffvsp; int ffrule; #endif { int ffnrhs = ffr2[ffrule]; int ffi; unsigned long int fflno = ffrline[ffrule]; FFFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", ffrule - 1, fflno); /* The symbols being reduced. */ for (ffi = 0; ffi < ffnrhs; ffi++) { FFFPRINTF (stderr, " $%d = ", ffi + 1); ff_symbol_print (stderr, ffrhs[ffprhs[ffrule] + ffi], &(ffvsp[(ffi + 1) - (ffnrhs)]) ); FFFPRINTF (stderr, "\n"); } } # define FF_REDUCE_PRINT(Rule) \ do { \ if (ffdebug) \ ff_reduce_print (ffvsp, Rule); \ } while (FFID (0)) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int ffdebug; #else /* !FFDEBUG */ # define FFDPRINTF(Args) # define FF_SYMBOL_PRINT(Title, Type, Value, Location) # define FF_STACK_PRINT(Bottom, Top) # define FF_REDUCE_PRINT(Rule) #endif /* !FFDEBUG */ /* FFINITDEPTH -- initial size of the parser's stacks. */ #ifndef FFINITDEPTH # define FFINITDEPTH 200 #endif /* FFMAXDEPTH -- maximum size the stacks can grow to (effective only if the built-in stack extension method is used). Do not make this value too large; the results are undefined if FFSTACK_ALLOC_MAXIMUM < FFSTACK_BYTES (FFMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #ifndef FFMAXDEPTH # define FFMAXDEPTH 10000 #endif #if FFERROR_VERBOSE # ifndef ffstrlen # if defined __GLIBC__ && defined _STRING_H # define ffstrlen strlen # else /* Return the length of FFSTR. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static FFSIZE_T ffstrlen (const char *ffstr) #else static FFSIZE_T ffstrlen (ffstr) const char *ffstr; #endif { FFSIZE_T fflen; for (fflen = 0; ffstr[fflen]; fflen++) continue; return fflen; } # endif # endif # ifndef ffstpcpy # if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE # define ffstpcpy stpcpy # else /* Copy FFSRC to FFDEST, returning the address of the terminating '\0' in FFDEST. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static char * ffstpcpy (char *ffdest, const char *ffsrc) #else static char * ffstpcpy (ffdest, ffsrc) char *ffdest; const char *ffsrc; #endif { char *ffd = ffdest; const char *ffs = ffsrc; while ((*ffd++ = *ffs++) != '\0') continue; return ffd - 1; } # endif # endif # ifndef fftnamerr /* Copy to FFRES the contents of FFSTR after stripping away unnecessary quotes and backslashes, so that it's suitable for fferror. The heuristic is that double-quoting is unnecessary unless the string contains an apostrophe, a comma, or backslash (other than backslash-backslash). FFSTR is taken from fftname. If FFRES is null, do not copy; instead, return the length of what the result would have been. */ static FFSIZE_T fftnamerr (char *ffres, const char *ffstr) { if (*ffstr == '"') { FFSIZE_T ffn = 0; char const *ffp = ffstr; for (;;) switch (*++ffp) { case '\'': case ',': goto do_not_strip_quotes; case '\\': if (*++ffp != '\\') goto do_not_strip_quotes; /* Fall through. */ default: if (ffres) ffres[ffn] = *ffp; ffn++; break; case '"': if (ffres) ffres[ffn] = '\0'; return ffn; } do_not_strip_quotes: ; } if (! ffres) return ffstrlen (ffstr); return ffstpcpy (ffres, ffstr) - ffres; } # endif /* Copy into FFRESULT an error message about the unexpected token FFCHAR while in state FFSTATE. Return the number of bytes copied, including the terminating null byte. If FFRESULT is null, do not copy anything; just return the number of bytes that would be copied. As a special case, return 0 if an ordinary "syntax error" message will do. Return FFSIZE_MAXIMUM if overflow occurs during size calculation. */ static FFSIZE_T ffsyntax_error (char *ffresult, int ffstate, int ffchar) { int ffn = ffpact[ffstate]; if (! (FFPACT_NINF < ffn && ffn <= FFLAST)) return 0; else { int fftype = FFTRANSLATE (ffchar); FFSIZE_T ffsize0 = fftnamerr (0, fftname[fftype]); FFSIZE_T ffsize = ffsize0; FFSIZE_T ffsize1; int ffsize_overflow = 0; enum { FFERROR_VERBOSE_ARGS_MAXIMUM = 5 }; char const *ffarg[FFERROR_VERBOSE_ARGS_MAXIMUM]; int ffx; # if 0 /* This is so xgettext sees the translatable formats that are constructed on the fly. */ FF_("syntax error, unexpected %s"); FF_("syntax error, unexpected %s, expecting %s"); FF_("syntax error, unexpected %s, expecting %s or %s"); FF_("syntax error, unexpected %s, expecting %s or %s or %s"); FF_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); # endif char *fffmt; char const *fff; static char const ffunexpected[] = "syntax error, unexpected %s"; static char const ffexpecting[] = ", expecting %s"; static char const ffor[] = " or %s"; char ffformat[sizeof ffunexpected + sizeof ffexpecting - 1 + ((FFERROR_VERBOSE_ARGS_MAXIMUM - 2) * (sizeof ffor - 1))]; char const *ffprefix = ffexpecting; /* Start FFX at -FFN if negative to avoid negative indexes in FFCHECK. */ int ffxbegin = ffn < 0 ? -ffn : 0; /* Stay within bounds of both ffcheck and fftname. */ int ffchecklim = FFLAST - ffn + 1; int ffxend = ffchecklim < FFNTOKENS ? ffchecklim : FFNTOKENS; int ffcount = 1; ffarg[0] = fftname[fftype]; fffmt = ffstpcpy (ffformat, ffunexpected); for (ffx = ffxbegin; ffx < ffxend; ++ffx) if (ffcheck[ffx + ffn] == ffx && ffx != FFTERROR) { if (ffcount == FFERROR_VERBOSE_ARGS_MAXIMUM) { ffcount = 1; ffsize = ffsize0; ffformat[sizeof ffunexpected - 1] = '\0'; break; } ffarg[ffcount++] = fftname[ffx]; ffsize1 = ffsize + fftnamerr (0, fftname[ffx]); ffsize_overflow |= (ffsize1 < ffsize); ffsize = ffsize1; fffmt = ffstpcpy (fffmt, ffprefix); ffprefix = ffor; } fff = FF_(ffformat); ffsize1 = ffsize + ffstrlen (fff); ffsize_overflow |= (ffsize1 < ffsize); ffsize = ffsize1; if (ffsize_overflow) return FFSIZE_MAXIMUM; if (ffresult) { /* Avoid sprintf, as that infringes on the user's name space. Don't have undefined behavior even if the translation produced a string with the wrong number of "%s"s. */ char *ffp = ffresult; int ffi = 0; while ((*ffp = *fff) != '\0') { if (*ffp == '%' && fff[1] == 's' && ffi < ffcount) { ffp += fftnamerr (ffp, ffarg[ffi++]); fff += 2; } else { ffp++; fff++; } } } return ffsize; } } #endif /* FFERROR_VERBOSE */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void ffdestruct (const char *ffmsg, int fftype, FFSTYPE *ffvaluep) #else static void ffdestruct (ffmsg, fftype, ffvaluep) const char *ffmsg; int fftype; FFSTYPE *ffvaluep; #endif { FFUSE (ffvaluep); if (!ffmsg) ffmsg = "Deleting"; FF_SYMBOL_PRINT (ffmsg, fftype, ffvaluep, fflocationp); switch (fftype) { default: break; } } /* Prevent warnings from -Wmissing-prototypes. */ #ifdef FFPARSE_PARAM #if defined __STDC__ || defined __cplusplus int ffparse (void *FFPARSE_PARAM); #else int ffparse (); #endif #else /* ! FFPARSE_PARAM */ #if defined __STDC__ || defined __cplusplus int ffparse (void); #else int ffparse (); #endif #endif /* ! FFPARSE_PARAM */ /* The lookahead symbol. */ int ffchar; /* The semantic value of the lookahead symbol. */ FFSTYPE fflval; /* Number of syntax errors so far. */ int ffnerrs; /*-------------------------. | ffparse or ffpush_parse. | `-------------------------*/ #ifdef FFPARSE_PARAM #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int ffparse (void *FFPARSE_PARAM) #else int ffparse (FFPARSE_PARAM) void *FFPARSE_PARAM; #endif #else /* ! FFPARSE_PARAM */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int ffparse (void) #else int ffparse () #endif #endif { int ffstate; /* Number of tokens to shift before error messages enabled. */ int fferrstatus; /* The stacks and their tools: `ffss': related to states. `ffvs': related to semantic values. Refer to the stacks thru separate pointers, to allow ffoverflow to reallocate them elsewhere. */ /* The state stack. */ fftype_int16 ffssa[FFINITDEPTH]; fftype_int16 *ffss; fftype_int16 *ffssp; /* The semantic value stack. */ FFSTYPE ffvsa[FFINITDEPTH]; FFSTYPE *ffvs; FFSTYPE *ffvsp; FFSIZE_T ffstacksize; int ffn; int ffresult; /* Lookahead token as an internal (translated) token number. */ int fftoken; /* The variables used to return semantic value and location from the action routines. */ FFSTYPE ffval; #if FFERROR_VERBOSE /* Buffer for error messages, and its allocated size. */ char ffmsgbuf[128]; char *ffmsg = ffmsgbuf; FFSIZE_T ffmsg_alloc = sizeof ffmsgbuf; #endif #define FFPOPSTACK(N) (ffvsp -= (N), ffssp -= (N)) /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int fflen = 0; fftoken = 0; ffss = ffssa; ffvs = ffvsa; ffstacksize = FFINITDEPTH; FFDPRINTF ((stderr, "Starting parse\n")); ffstate = 0; fferrstatus = 0; ffnerrs = 0; ffchar = FFEMPTY; /* Cause a token to be read. */ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. The wasted elements are never initialized. */ ffssp = ffss; ffvsp = ffvs; goto ffsetstate; /*------------------------------------------------------------. | ffnewstate -- Push a new state, which is found in ffstate. | `------------------------------------------------------------*/ ffnewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ ffssp++; ffsetstate: *ffssp = ffstate; if (ffss + ffstacksize - 1 <= ffssp) { /* Get the current used size of the three stacks, in elements. */ FFSIZE_T ffsize = ffssp - ffss + 1; #ifdef ffoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ FFSTYPE *ffvs1 = ffvs; fftype_int16 *ffss1 = ffss; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if ffoverflow is a macro. */ ffoverflow (FF_("memory exhausted"), &ffss1, ffsize * sizeof (*ffssp), &ffvs1, ffsize * sizeof (*ffvsp), &ffstacksize); ffss = ffss1; ffvs = ffvs1; } #else /* no ffoverflow */ # ifndef FFSTACK_RELOCATE goto ffexhaustedlab; # else /* Extend the stack our own way. */ if (FFMAXDEPTH <= ffstacksize) goto ffexhaustedlab; ffstacksize *= 2; if (FFMAXDEPTH < ffstacksize) ffstacksize = FFMAXDEPTH; { fftype_int16 *ffss1 = ffss; union ffalloc *ffptr = (union ffalloc *) FFSTACK_ALLOC (FFSTACK_BYTES (ffstacksize)); if (! ffptr) goto ffexhaustedlab; FFSTACK_RELOCATE (ffss_alloc, ffss); FFSTACK_RELOCATE (ffvs_alloc, ffvs); # undef FFSTACK_RELOCATE if (ffss1 != ffssa) FFSTACK_FREE (ffss1); } # endif #endif /* no ffoverflow */ ffssp = ffss + ffsize - 1; ffvsp = ffvs + ffsize - 1; FFDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) ffstacksize)); if (ffss + ffstacksize - 1 <= ffssp) FFABORT; } FFDPRINTF ((stderr, "Entering state %d\n", ffstate)); if (ffstate == FFFINAL) FFACCEPT; goto ffbackup; /*-----------. | ffbackup. | `-----------*/ ffbackup: /* Do appropriate processing given the current state. Read a lookahead token if we need one and don't already have one. */ /* First try to decide what to do without reference to lookahead token. */ ffn = ffpact[ffstate]; if (ffn == FFPACT_NINF) goto ffdefault; /* Not known => get a lookahead token if don't already have one. */ /* FFCHAR is either FFEMPTY or FFEOF or a valid lookahead symbol. */ if (ffchar == FFEMPTY) { FFDPRINTF ((stderr, "Reading a token: ")); ffchar = FFLEX; } if (ffchar <= FFEOF) { ffchar = fftoken = FFEOF; FFDPRINTF ((stderr, "Now at end of input.\n")); } else { fftoken = FFTRANSLATE (ffchar); FF_SYMBOL_PRINT ("Next token is", fftoken, &fflval, &fflloc); } /* If the proper action on seeing token FFTOKEN is to reduce or to detect an error, take that action. */ ffn += fftoken; if (ffn < 0 || FFLAST < ffn || ffcheck[ffn] != fftoken) goto ffdefault; ffn = fftable[ffn]; if (ffn <= 0) { if (ffn == 0 || ffn == FFTABLE_NINF) goto fferrlab; ffn = -ffn; goto ffreduce; } /* Count tokens shifted since error; after three, turn off error status. */ if (fferrstatus) fferrstatus--; /* Shift the lookahead token. */ FF_SYMBOL_PRINT ("Shifting", fftoken, &fflval, &fflloc); /* Discard the shifted token. */ ffchar = FFEMPTY; ffstate = ffn; *++ffvsp = fflval; goto ffnewstate; /*-----------------------------------------------------------. | ffdefault -- do the default action for the current state. | `-----------------------------------------------------------*/ ffdefault: ffn = ffdefact[ffstate]; if (ffn == 0) goto fferrlab; goto ffreduce; /*-----------------------------. | ffreduce -- Do a reduction. | `-----------------------------*/ ffreduce: /* ffn is the number of a rule to reduce with. */ fflen = ffr2[ffn]; /* If FFLEN is nonzero, implement the default value of the action: `$$ = $1'. Otherwise, the following line sets FFVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. Assigning to FFVAL unconditionally makes the parser a bit smaller, and it avoids a GCC warning that FFVAL may be used uninitialized. */ ffval = ffvsp[1-fflen]; FF_REDUCE_PRINT (ffn); switch (ffn) { case 4: /* Line 1455 of yacc.c */ #line 248 "eval.y" {} break; case 5: /* Line 1455 of yacc.c */ #line 250 "eval.y" { if( (ffvsp[(1) - (2)].Node)<0 ) { fferror("Couldn't build node structure: out of memory?"); FFERROR; } gParse.resultNode = (ffvsp[(1) - (2)].Node); } break; case 6: /* Line 1455 of yacc.c */ #line 256 "eval.y" { if( (ffvsp[(1) - (2)].Node)<0 ) { fferror("Couldn't build node structure: out of memory?"); FFERROR; } gParse.resultNode = (ffvsp[(1) - (2)].Node); } break; case 7: /* Line 1455 of yacc.c */ #line 262 "eval.y" { if( (ffvsp[(1) - (2)].Node)<0 ) { fferror("Couldn't build node structure: out of memory?"); FFERROR; } gParse.resultNode = (ffvsp[(1) - (2)].Node); } break; case 8: /* Line 1455 of yacc.c */ #line 268 "eval.y" { if( (ffvsp[(1) - (2)].Node)<0 ) { fferror("Couldn't build node structure: out of memory?"); FFERROR; } gParse.resultNode = (ffvsp[(1) - (2)].Node); } break; case 9: /* Line 1455 of yacc.c */ #line 273 "eval.y" { fferrok; } break; case 10: /* Line 1455 of yacc.c */ #line 277 "eval.y" { (ffval.Node) = New_Vector( (ffvsp[(2) - (2)].Node) ); TEST((ffval.Node)); } break; case 11: /* Line 1455 of yacc.c */ #line 279 "eval.y" { if( gParse.Nodes[(ffvsp[(1) - (3)].Node)].nSubNodes >= MAXSUBS ) { (ffvsp[(1) - (3)].Node) = Close_Vec( (ffvsp[(1) - (3)].Node) ); TEST((ffvsp[(1) - (3)].Node)); (ffval.Node) = New_Vector( (ffvsp[(1) - (3)].Node) ); TEST((ffval.Node)); } else { (ffval.Node) = (ffvsp[(1) - (3)].Node); } gParse.Nodes[(ffval.Node)].SubNodes[ gParse.Nodes[(ffval.Node)].nSubNodes++ ] = (ffvsp[(3) - (3)].Node); } break; case 12: /* Line 1455 of yacc.c */ #line 292 "eval.y" { (ffval.Node) = New_Vector( (ffvsp[(2) - (2)].Node) ); TEST((ffval.Node)); } break; case 13: /* Line 1455 of yacc.c */ #line 294 "eval.y" { if( TYPE((ffvsp[(1) - (3)].Node)) < TYPE((ffvsp[(3) - (3)].Node)) ) TYPE((ffvsp[(1) - (3)].Node)) = TYPE((ffvsp[(3) - (3)].Node)); if( gParse.Nodes[(ffvsp[(1) - (3)].Node)].nSubNodes >= MAXSUBS ) { (ffvsp[(1) - (3)].Node) = Close_Vec( (ffvsp[(1) - (3)].Node) ); TEST((ffvsp[(1) - (3)].Node)); (ffval.Node) = New_Vector( (ffvsp[(1) - (3)].Node) ); TEST((ffval.Node)); } else { (ffval.Node) = (ffvsp[(1) - (3)].Node); } gParse.Nodes[(ffval.Node)].SubNodes[ gParse.Nodes[(ffval.Node)].nSubNodes++ ] = (ffvsp[(3) - (3)].Node); } break; case 14: /* Line 1455 of yacc.c */ #line 307 "eval.y" { if( gParse.Nodes[(ffvsp[(1) - (3)].Node)].nSubNodes >= MAXSUBS ) { (ffvsp[(1) - (3)].Node) = Close_Vec( (ffvsp[(1) - (3)].Node) ); TEST((ffvsp[(1) - (3)].Node)); (ffval.Node) = New_Vector( (ffvsp[(1) - (3)].Node) ); TEST((ffval.Node)); } else { (ffval.Node) = (ffvsp[(1) - (3)].Node); } gParse.Nodes[(ffval.Node)].SubNodes[ gParse.Nodes[(ffval.Node)].nSubNodes++ ] = (ffvsp[(3) - (3)].Node); } break; case 15: /* Line 1455 of yacc.c */ #line 318 "eval.y" { TYPE((ffvsp[(1) - (3)].Node)) = TYPE((ffvsp[(3) - (3)].Node)); if( gParse.Nodes[(ffvsp[(1) - (3)].Node)].nSubNodes >= MAXSUBS ) { (ffvsp[(1) - (3)].Node) = Close_Vec( (ffvsp[(1) - (3)].Node) ); TEST((ffvsp[(1) - (3)].Node)); (ffval.Node) = New_Vector( (ffvsp[(1) - (3)].Node) ); TEST((ffval.Node)); } else { (ffval.Node) = (ffvsp[(1) - (3)].Node); } gParse.Nodes[(ffval.Node)].SubNodes[ gParse.Nodes[(ffval.Node)].nSubNodes++ ] = (ffvsp[(3) - (3)].Node); } break; case 16: /* Line 1455 of yacc.c */ #line 332 "eval.y" { (ffval.Node) = Close_Vec( (ffvsp[(1) - (2)].Node) ); TEST((ffval.Node)); } break; case 17: /* Line 1455 of yacc.c */ #line 336 "eval.y" { (ffval.Node) = Close_Vec( (ffvsp[(1) - (2)].Node) ); TEST((ffval.Node)); } break; case 18: /* Line 1455 of yacc.c */ #line 340 "eval.y" { (ffval.Node) = New_Const( BITSTR, (ffvsp[(1) - (1)].str), strlen((ffvsp[(1) - (1)].str))+1 ); TEST((ffval.Node)); SIZE((ffval.Node)) = strlen((ffvsp[(1) - (1)].str)); } break; case 19: /* Line 1455 of yacc.c */ #line 344 "eval.y" { (ffval.Node) = New_Column( (ffvsp[(1) - (1)].lng) ); TEST((ffval.Node)); } break; case 20: /* Line 1455 of yacc.c */ #line 346 "eval.y" { if( TYPE((ffvsp[(3) - (4)].Node)) != LONG || OPER((ffvsp[(3) - (4)].Node)) != CONST_OP ) { fferror("Offset argument must be a constant integer"); FFERROR; } (ffval.Node) = New_Offset( (ffvsp[(1) - (4)].lng), (ffvsp[(3) - (4)].Node) ); TEST((ffval.Node)); } break; case 21: /* Line 1455 of yacc.c */ #line 355 "eval.y" { (ffval.Node) = New_BinOp( BITSTR, (ffvsp[(1) - (3)].Node), '&', (ffvsp[(3) - (3)].Node) ); TEST((ffval.Node)); SIZE((ffval.Node)) = ( SIZE((ffvsp[(1) - (3)].Node))>SIZE((ffvsp[(3) - (3)].Node)) ? SIZE((ffvsp[(1) - (3)].Node)) : SIZE((ffvsp[(3) - (3)].Node)) ); } break; case 22: /* Line 1455 of yacc.c */ #line 358 "eval.y" { (ffval.Node) = New_BinOp( BITSTR, (ffvsp[(1) - (3)].Node), '|', (ffvsp[(3) - (3)].Node) ); TEST((ffval.Node)); SIZE((ffval.Node)) = ( SIZE((ffvsp[(1) - (3)].Node))>SIZE((ffvsp[(3) - (3)].Node)) ? SIZE((ffvsp[(1) - (3)].Node)) : SIZE((ffvsp[(3) - (3)].Node)) ); } break; case 23: /* Line 1455 of yacc.c */ #line 361 "eval.y" { if (SIZE((ffvsp[(1) - (3)].Node))+SIZE((ffvsp[(3) - (3)].Node)) >= MAX_STRLEN) { fferror("Combined bit string size exceeds " MAX_STRLEN_S " bits"); FFERROR; } (ffval.Node) = New_BinOp( BITSTR, (ffvsp[(1) - (3)].Node), '+', (ffvsp[(3) - (3)].Node) ); TEST((ffval.Node)); SIZE((ffval.Node)) = SIZE((ffvsp[(1) - (3)].Node)) + SIZE((ffvsp[(3) - (3)].Node)); } break; case 24: /* Line 1455 of yacc.c */ #line 370 "eval.y" { (ffval.Node) = New_Deref( (ffvsp[(1) - (4)].Node), 1, (ffvsp[(3) - (4)].Node), 0, 0, 0, 0 ); TEST((ffval.Node)); } break; case 25: /* Line 1455 of yacc.c */ #line 372 "eval.y" { (ffval.Node) = New_Deref( (ffvsp[(1) - (6)].Node), 2, (ffvsp[(3) - (6)].Node), (ffvsp[(5) - (6)].Node), 0, 0, 0 ); TEST((ffval.Node)); } break; case 26: /* Line 1455 of yacc.c */ #line 374 "eval.y" { (ffval.Node) = New_Deref( (ffvsp[(1) - (8)].Node), 3, (ffvsp[(3) - (8)].Node), (ffvsp[(5) - (8)].Node), (ffvsp[(7) - (8)].Node), 0, 0 ); TEST((ffval.Node)); } break; case 27: /* Line 1455 of yacc.c */ #line 376 "eval.y" { (ffval.Node) = New_Deref( (ffvsp[(1) - (10)].Node), 4, (ffvsp[(3) - (10)].Node), (ffvsp[(5) - (10)].Node), (ffvsp[(7) - (10)].Node), (ffvsp[(9) - (10)].Node), 0 ); TEST((ffval.Node)); } break; case 28: /* Line 1455 of yacc.c */ #line 378 "eval.y" { (ffval.Node) = New_Deref( (ffvsp[(1) - (12)].Node), 5, (ffvsp[(3) - (12)].Node), (ffvsp[(5) - (12)].Node), (ffvsp[(7) - (12)].Node), (ffvsp[(9) - (12)].Node), (ffvsp[(11) - (12)].Node) ); TEST((ffval.Node)); } break; case 29: /* Line 1455 of yacc.c */ #line 380 "eval.y" { (ffval.Node) = New_Unary( BITSTR, NOT, (ffvsp[(2) - (2)].Node) ); TEST((ffval.Node)); } break; case 30: /* Line 1455 of yacc.c */ #line 383 "eval.y" { (ffval.Node) = (ffvsp[(2) - (3)].Node); } break; case 31: /* Line 1455 of yacc.c */ #line 387 "eval.y" { (ffval.Node) = New_Const( LONG, &((ffvsp[(1) - (1)].lng)), sizeof(long) ); TEST((ffval.Node)); } break; case 32: /* Line 1455 of yacc.c */ #line 389 "eval.y" { (ffval.Node) = New_Const( DOUBLE, &((ffvsp[(1) - (1)].dbl)), sizeof(double) ); TEST((ffval.Node)); } break; case 33: /* Line 1455 of yacc.c */ #line 391 "eval.y" { (ffval.Node) = New_Column( (ffvsp[(1) - (1)].lng) ); TEST((ffval.Node)); } break; case 34: /* Line 1455 of yacc.c */ #line 393 "eval.y" { if( TYPE((ffvsp[(3) - (4)].Node)) != LONG || OPER((ffvsp[(3) - (4)].Node)) != CONST_OP ) { fferror("Offset argument must be a constant integer"); FFERROR; } (ffval.Node) = New_Offset( (ffvsp[(1) - (4)].lng), (ffvsp[(3) - (4)].Node) ); TEST((ffval.Node)); } break; case 35: /* Line 1455 of yacc.c */ #line 402 "eval.y" { (ffval.Node) = New_Func( LONG, row_fct, 0, 0, 0, 0, 0, 0, 0, 0 ); } break; case 36: /* Line 1455 of yacc.c */ #line 404 "eval.y" { (ffval.Node) = New_Func( LONG, null_fct, 0, 0, 0, 0, 0, 0, 0, 0 ); } break; case 37: /* Line 1455 of yacc.c */ #line 406 "eval.y" { PROMOTE((ffvsp[(1) - (3)].Node),(ffvsp[(3) - (3)].Node)); (ffval.Node) = New_BinOp( TYPE((ffvsp[(1) - (3)].Node)), (ffvsp[(1) - (3)].Node), '%', (ffvsp[(3) - (3)].Node) ); TEST((ffval.Node)); } break; case 38: /* Line 1455 of yacc.c */ #line 409 "eval.y" { PROMOTE((ffvsp[(1) - (3)].Node),(ffvsp[(3) - (3)].Node)); (ffval.Node) = New_BinOp( TYPE((ffvsp[(1) - (3)].Node)), (ffvsp[(1) - (3)].Node), '+', (ffvsp[(3) - (3)].Node) ); TEST((ffval.Node)); } break; case 39: /* Line 1455 of yacc.c */ #line 412 "eval.y" { PROMOTE((ffvsp[(1) - (3)].Node),(ffvsp[(3) - (3)].Node)); (ffval.Node) = New_BinOp( TYPE((ffvsp[(1) - (3)].Node)), (ffvsp[(1) - (3)].Node), '-', (ffvsp[(3) - (3)].Node) ); TEST((ffval.Node)); } break; case 40: /* Line 1455 of yacc.c */ #line 415 "eval.y" { PROMOTE((ffvsp[(1) - (3)].Node),(ffvsp[(3) - (3)].Node)); (ffval.Node) = New_BinOp( TYPE((ffvsp[(1) - (3)].Node)), (ffvsp[(1) - (3)].Node), '*', (ffvsp[(3) - (3)].Node) ); TEST((ffval.Node)); } break; case 41: /* Line 1455 of yacc.c */ #line 418 "eval.y" { PROMOTE((ffvsp[(1) - (3)].Node),(ffvsp[(3) - (3)].Node)); (ffval.Node) = New_BinOp( TYPE((ffvsp[(1) - (3)].Node)), (ffvsp[(1) - (3)].Node), '/', (ffvsp[(3) - (3)].Node) ); TEST((ffval.Node)); } break; case 42: /* Line 1455 of yacc.c */ #line 421 "eval.y" { PROMOTE((ffvsp[(1) - (3)].Node),(ffvsp[(3) - (3)].Node)); (ffval.Node) = New_BinOp( TYPE((ffvsp[(1) - (3)].Node)), (ffvsp[(1) - (3)].Node), POWER, (ffvsp[(3) - (3)].Node) ); TEST((ffval.Node)); } break; case 43: /* Line 1455 of yacc.c */ #line 424 "eval.y" { (ffval.Node) = (ffvsp[(2) - (2)].Node); } break; case 44: /* Line 1455 of yacc.c */ #line 426 "eval.y" { (ffval.Node) = New_Unary( TYPE((ffvsp[(2) - (2)].Node)), UMINUS, (ffvsp[(2) - (2)].Node) ); TEST((ffval.Node)); } break; case 45: /* Line 1455 of yacc.c */ #line 428 "eval.y" { (ffval.Node) = (ffvsp[(2) - (3)].Node); } break; case 46: /* Line 1455 of yacc.c */ #line 430 "eval.y" { (ffvsp[(3) - (3)].Node) = New_Unary( TYPE((ffvsp[(1) - (3)].Node)), 0, (ffvsp[(3) - (3)].Node) ); (ffval.Node) = New_BinOp( TYPE((ffvsp[(1) - (3)].Node)), (ffvsp[(1) - (3)].Node), '*', (ffvsp[(3) - (3)].Node) ); TEST((ffval.Node)); } break; case 47: /* Line 1455 of yacc.c */ #line 434 "eval.y" { (ffvsp[(1) - (3)].Node) = New_Unary( TYPE((ffvsp[(3) - (3)].Node)), 0, (ffvsp[(1) - (3)].Node) ); (ffval.Node) = New_BinOp( TYPE((ffvsp[(3) - (3)].Node)), (ffvsp[(1) - (3)].Node), '*', (ffvsp[(3) - (3)].Node) ); TEST((ffval.Node)); } break; case 48: /* Line 1455 of yacc.c */ #line 438 "eval.y" { PROMOTE((ffvsp[(3) - (5)].Node),(ffvsp[(5) - (5)].Node)); if( ! Test_Dims((ffvsp[(3) - (5)].Node),(ffvsp[(5) - (5)].Node)) ) { fferror("Incompatible dimensions in '?:' arguments"); FFERROR; } (ffval.Node) = New_Func( 0, ifthenelse_fct, 3, (ffvsp[(3) - (5)].Node), (ffvsp[(5) - (5)].Node), (ffvsp[(1) - (5)].Node), 0, 0, 0, 0 ); TEST((ffval.Node)); if( SIZE((ffvsp[(3) - (5)].Node))=SIZE((ffvsp[(4) - (5)].Node)) && Test_Dims( (ffvsp[(2) - (5)].Node), (ffvsp[(4) - (5)].Node) ) ) { PROMOTE((ffvsp[(2) - (5)].Node),(ffvsp[(4) - (5)].Node)); (ffval.Node) = New_Func( 0, defnull_fct, 2, (ffvsp[(2) - (5)].Node), (ffvsp[(4) - (5)].Node), 0, 0, 0, 0, 0 ); TEST((ffval.Node)); } else { fferror("Dimensions of DEFNULL arguments " "are not compatible"); FFERROR; } } else if (FSTRCMP((ffvsp[(1) - (5)].str),"ARCTAN2(") == 0) { if( TYPE((ffvsp[(2) - (5)].Node)) != DOUBLE ) (ffvsp[(2) - (5)].Node) = New_Unary( DOUBLE, 0, (ffvsp[(2) - (5)].Node) ); if( TYPE((ffvsp[(4) - (5)].Node)) != DOUBLE ) (ffvsp[(4) - (5)].Node) = New_Unary( DOUBLE, 0, (ffvsp[(4) - (5)].Node) ); if( Test_Dims( (ffvsp[(2) - (5)].Node), (ffvsp[(4) - (5)].Node) ) ) { (ffval.Node) = New_Func( 0, atan2_fct, 2, (ffvsp[(2) - (5)].Node), (ffvsp[(4) - (5)].Node), 0, 0, 0, 0, 0 ); TEST((ffval.Node)); if( SIZE((ffvsp[(2) - (5)].Node))=SIZE((ffvsp[(4) - (5)].Node)) && Test_Dims( (ffvsp[(2) - (5)].Node), (ffvsp[(4) - (5)].Node) ) ) { (ffval.Node) = New_Func( 0, defnull_fct, 2, (ffvsp[(2) - (5)].Node), (ffvsp[(4) - (5)].Node), 0, 0, 0, 0, 0 ); TEST((ffval.Node)); } else { fferror("Dimensions of DEFNULL arguments are not compatible"); FFERROR; } } else { fferror("Boolean Function(expr,expr) not supported"); FFERROR; } } break; case 100: /* Line 1455 of yacc.c */ #line 928 "eval.y" { if( TYPE((ffvsp[(2) - (7)].Node)) != DOUBLE ) (ffvsp[(2) - (7)].Node) = New_Unary( DOUBLE, 0, (ffvsp[(2) - (7)].Node) ); if( TYPE((ffvsp[(4) - (7)].Node)) != DOUBLE ) (ffvsp[(4) - (7)].Node) = New_Unary( DOUBLE, 0, (ffvsp[(4) - (7)].Node) ); if( TYPE((ffvsp[(6) - (7)].Node)) != DOUBLE ) (ffvsp[(6) - (7)].Node) = New_Unary( DOUBLE, 0, (ffvsp[(6) - (7)].Node) ); if( ! (Test_Dims( (ffvsp[(2) - (7)].Node), (ffvsp[(4) - (7)].Node) ) && Test_Dims( (ffvsp[(4) - (7)].Node), (ffvsp[(6) - (7)].Node) ) ) ) { fferror("Dimensions of NEAR arguments " "are not compatible"); FFERROR; } else { if (FSTRCMP((ffvsp[(1) - (7)].str),"NEAR(") == 0) { (ffval.Node) = New_Func( BOOLEAN, near_fct, 3, (ffvsp[(2) - (7)].Node), (ffvsp[(4) - (7)].Node), (ffvsp[(6) - (7)].Node), 0, 0, 0, 0 ); } else { fferror("Boolean Function not supported"); FFERROR; } TEST((ffval.Node)); if( SIZE((ffval.Node))= MAX_STRLEN) { fferror("Combined string size exceeds " MAX_STRLEN_S " characters"); FFERROR; } (ffval.Node) = New_BinOp( STRING, (ffvsp[(1) - (3)].Node), '+', (ffvsp[(3) - (3)].Node) ); TEST((ffval.Node)); SIZE((ffval.Node)) = SIZE((ffvsp[(1) - (3)].Node)) + SIZE((ffvsp[(3) - (3)].Node)); } break; case 123: /* Line 1455 of yacc.c */ #line 1086 "eval.y" { int outSize; if( SIZE((ffvsp[(1) - (5)].Node))!=1 ) { fferror("Cannot have a vector string column"); FFERROR; } /* Since the output can be calculated now, as a constant scalar, we must precalculate the output size, in order to avoid an overflow. */ outSize = SIZE((ffvsp[(3) - (5)].Node)); if (SIZE((ffvsp[(5) - (5)].Node)) > outSize) outSize = SIZE((ffvsp[(5) - (5)].Node)); (ffval.Node) = New_FuncSize( 0, ifthenelse_fct, 3, (ffvsp[(3) - (5)].Node), (ffvsp[(5) - (5)].Node), (ffvsp[(1) - (5)].Node), 0, 0, 0, 0, outSize); TEST((ffval.Node)); if( SIZE((ffvsp[(3) - (5)].Node)) outSize) outSize = SIZE((ffvsp[(4) - (5)].Node)); (ffval.Node) = New_FuncSize( 0, defnull_fct, 2, (ffvsp[(2) - (5)].Node), (ffvsp[(4) - (5)].Node), 0, 0, 0, 0, 0, outSize ); TEST((ffval.Node)); if( SIZE((ffvsp[(4) - (5)].Node))>SIZE((ffvsp[(2) - (5)].Node)) ) SIZE((ffval.Node)) = SIZE((ffvsp[(4) - (5)].Node)); } else { fferror("Function(string,string) not supported"); FFERROR; } } break; case 125: /* Line 1455 of yacc.c */ #line 1124 "eval.y" { if (FSTRCMP((ffvsp[(1) - (7)].str),"STRMID(") == 0) { int len; if( TYPE((ffvsp[(4) - (7)].Node)) != LONG || SIZE((ffvsp[(4) - (7)].Node)) != 1 || TYPE((ffvsp[(6) - (7)].Node)) != LONG || SIZE((ffvsp[(6) - (7)].Node)) != 1) { fferror("When using STRMID(S,P,N), P and N must be integers (and not vector columns)"); FFERROR; } if (OPER((ffvsp[(6) - (7)].Node)) == CONST_OP) { /* Constant value: use that directly */ len = (gParse.Nodes[(ffvsp[(6) - (7)].Node)].value.data.lng); } else { /* Variable value: use the maximum possible (from $2) */ len = SIZE((ffvsp[(2) - (7)].Node)); } if (len <= 0 || len >= MAX_STRLEN) { fferror("STRMID(S,P,N), N must be 1-" MAX_STRLEN_S); FFERROR; } (ffval.Node) = New_FuncSize( 0, strmid_fct, 3, (ffvsp[(2) - (7)].Node), (ffvsp[(4) - (7)].Node),(ffvsp[(6) - (7)].Node),0,0,0,0,len); TEST((ffval.Node)); } else { fferror("Function(string,expr,expr) not supported"); FFERROR; } } break; /* Line 1455 of yacc.c */ #line 3584 "y.tab.c" default: break; } FF_SYMBOL_PRINT ("-> $$ =", ffr1[ffn], &ffval, &ffloc); FFPOPSTACK (fflen); fflen = 0; FF_STACK_PRINT (ffss, ffssp); *++ffvsp = ffval; /* Now `shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ ffn = ffr1[ffn]; ffstate = ffpgoto[ffn - FFNTOKENS] + *ffssp; if (0 <= ffstate && ffstate <= FFLAST && ffcheck[ffstate] == *ffssp) ffstate = fftable[ffstate]; else ffstate = ffdefgoto[ffn - FFNTOKENS]; goto ffnewstate; /*------------------------------------. | fferrlab -- here on detecting error | `------------------------------------*/ fferrlab: /* If not already recovering from an error, report this error. */ if (!fferrstatus) { ++ffnerrs; #if ! FFERROR_VERBOSE fferror (FF_("syntax error")); #else { FFSIZE_T ffsize = ffsyntax_error (0, ffstate, ffchar); if (ffmsg_alloc < ffsize && ffmsg_alloc < FFSTACK_ALLOC_MAXIMUM) { FFSIZE_T ffalloc = 2 * ffsize; if (! (ffsize <= ffalloc && ffalloc <= FFSTACK_ALLOC_MAXIMUM)) ffalloc = FFSTACK_ALLOC_MAXIMUM; if (ffmsg != ffmsgbuf) FFSTACK_FREE (ffmsg); ffmsg = (char *) FFSTACK_ALLOC (ffalloc); if (ffmsg) ffmsg_alloc = ffalloc; else { ffmsg = ffmsgbuf; ffmsg_alloc = sizeof ffmsgbuf; } } if (0 < ffsize && ffsize <= ffmsg_alloc) { (void) ffsyntax_error (ffmsg, ffstate, ffchar); fferror (ffmsg); } else { fferror (FF_("syntax error")); if (ffsize != 0) goto ffexhaustedlab; } } #endif } if (fferrstatus == 3) { /* If just tried and failed to reuse lookahead token after an error, discard it. */ if (ffchar <= FFEOF) { /* Return failure if at end of input. */ if (ffchar == FFEOF) FFABORT; } else { ffdestruct ("Error: discarding", fftoken, &fflval); ffchar = FFEMPTY; } } /* Else will try to reuse lookahead token after shifting the error token. */ goto fferrlab1; /*---------------------------------------------------. | fferrorlab -- error raised explicitly by FFERROR. | `---------------------------------------------------*/ fferrorlab: /* Pacify compilers like GCC when the user code never invokes FFERROR and the label fferrorlab therefore never appears in user code. */ if (/*CONSTCOND*/ 0) goto fferrorlab; /* Do not reclaim the symbols of the rule which action triggered this FFERROR. */ FFPOPSTACK (fflen); fflen = 0; FF_STACK_PRINT (ffss, ffssp); ffstate = *ffssp; goto fferrlab1; /*-------------------------------------------------------------. | fferrlab1 -- common code for both syntax error and FFERROR. | `-------------------------------------------------------------*/ fferrlab1: fferrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { ffn = ffpact[ffstate]; if (ffn != FFPACT_NINF) { ffn += FFTERROR; if (0 <= ffn && ffn <= FFLAST && ffcheck[ffn] == FFTERROR) { ffn = fftable[ffn]; if (0 < ffn) break; } } /* Pop the current state because it cannot handle the error token. */ if (ffssp == ffss) FFABORT; ffdestruct ("Error: popping", ffstos[ffstate], ffvsp); FFPOPSTACK (1); ffstate = *ffssp; FF_STACK_PRINT (ffss, ffssp); } *++ffvsp = fflval; /* Shift the error token. */ FF_SYMBOL_PRINT ("Shifting", ffstos[ffn], ffvsp, fflsp); ffstate = ffn; goto ffnewstate; /*-------------------------------------. | ffacceptlab -- FFACCEPT comes here. | `-------------------------------------*/ ffacceptlab: ffresult = 0; goto ffreturn; /*-----------------------------------. | ffabortlab -- FFABORT comes here. | `-----------------------------------*/ ffabortlab: ffresult = 1; goto ffreturn; #if !defined(ffoverflow) || FFERROR_VERBOSE /*-------------------------------------------------. | ffexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ ffexhaustedlab: fferror (FF_("memory exhausted")); ffresult = 2; /* Fall through. */ #endif ffreturn: if (ffchar != FFEMPTY) ffdestruct ("Cleanup: discarding lookahead", fftoken, &fflval); /* Do not reclaim the symbols of the rule which action triggered this FFABORT or FFACCEPT. */ FFPOPSTACK (fflen); FF_STACK_PRINT (ffss, ffssp); while (ffssp != ffss) { ffdestruct ("Cleanup: popping", ffstos[*ffssp], ffvsp); FFPOPSTACK (1); } #ifndef ffoverflow if (ffss != ffssa) FFSTACK_FREE (ffss); #endif #if FFERROR_VERBOSE if (ffmsg != ffmsgbuf) FFSTACK_FREE (ffmsg); #endif /* Make sure FFID is used. */ return FFID (ffresult); } /* Line 1675 of yacc.c */ #line 1153 "eval.y" /*************************************************************************/ /* Start of "New" routines which build the expression Nodal structure */ /*************************************************************************/ static int Alloc_Node( void ) { /* Use this for allocation to guarantee *Nodes */ Node *newNodePtr; /* survives on failure, making it still valid */ /* while working our way out of this error */ if( gParse.nNodes == gParse.nNodesAlloc ) { if( gParse.Nodes ) { gParse.nNodesAlloc += gParse.nNodesAlloc; newNodePtr = (Node *)realloc( gParse.Nodes, sizeof(Node)*gParse.nNodesAlloc ); } else { gParse.nNodesAlloc = 100; newNodePtr = (Node *)malloc ( sizeof(Node)*gParse.nNodesAlloc ); } if( newNodePtr ) { gParse.Nodes = newNodePtr; } else { gParse.status = MEMORY_ALLOCATION; return( -1 ); } } return ( gParse.nNodes++ ); } static void Free_Last_Node( void ) { if( gParse.nNodes ) gParse.nNodes--; } static int New_Const( int returnType, void *value, long len ) { Node *this; int n; n = Alloc_Node(); if( n>=0 ) { this = gParse.Nodes + n; this->operation = CONST_OP; /* Flag a constant */ this->DoOp = NULL; this->nSubNodes = 0; this->type = returnType; memcpy( &(this->value.data), value, len ); this->value.undef = NULL; this->value.nelem = 1; this->value.naxis = 1; this->value.naxes[0] = 1; } return(n); } static int New_Column( int ColNum ) { Node *this; int n, i; n = Alloc_Node(); if( n>=0 ) { this = gParse.Nodes + n; this->operation = -ColNum; this->DoOp = NULL; this->nSubNodes = 0; this->type = gParse.varData[ColNum].type; this->value.nelem = gParse.varData[ColNum].nelem; this->value.naxis = gParse.varData[ColNum].naxis; for( i=0; ivalue.naxes[i] = gParse.varData[ColNum].naxes[i]; } return(n); } static int New_Offset( int ColNum, int offsetNode ) { Node *this; int n, i, colNode; colNode = New_Column( ColNum ); if( colNode<0 ) return(-1); n = Alloc_Node(); if( n>=0 ) { this = gParse.Nodes + n; this->operation = '{'; this->DoOp = Do_Offset; this->nSubNodes = 2; this->SubNodes[0] = colNode; this->SubNodes[1] = offsetNode; this->type = gParse.varData[ColNum].type; this->value.nelem = gParse.varData[ColNum].nelem; this->value.naxis = gParse.varData[ColNum].naxis; for( i=0; ivalue.naxes[i] = gParse.varData[ColNum].naxes[i]; } return(n); } static int New_Unary( int returnType, int Op, int Node1 ) { Node *this, *that; int i,n; if( Node1<0 ) return(-1); that = gParse.Nodes + Node1; if( !Op ) Op = returnType; if( (Op==DOUBLE || Op==FLTCAST) && that->type==DOUBLE ) return( Node1 ); if( (Op==LONG || Op==INTCAST) && that->type==LONG ) return( Node1 ); if( (Op==BOOLEAN ) && that->type==BOOLEAN ) return( Node1 ); n = Alloc_Node(); if( n>=0 ) { this = gParse.Nodes + n; this->operation = Op; this->DoOp = Do_Unary; this->nSubNodes = 1; this->SubNodes[0] = Node1; this->type = returnType; that = gParse.Nodes + Node1; /* Reset in case .Nodes mv'd */ this->value.nelem = that->value.nelem; this->value.naxis = that->value.naxis; for( i=0; ivalue.naxis; i++ ) this->value.naxes[i] = that->value.naxes[i]; if( that->operation==CONST_OP ) this->DoOp( this ); } return( n ); } static int New_BinOp( int returnType, int Node1, int Op, int Node2 ) { Node *this,*that1,*that2; int n,i,constant; if( Node1<0 || Node2<0 ) return(-1); n = Alloc_Node(); if( n>=0 ) { this = gParse.Nodes + n; this->operation = Op; this->nSubNodes = 2; this->SubNodes[0]= Node1; this->SubNodes[1]= Node2; this->type = returnType; that1 = gParse.Nodes + Node1; that2 = gParse.Nodes + Node2; constant = (that1->operation==CONST_OP && that2->operation==CONST_OP); if( that1->type!=STRING && that1->type!=BITSTR ) if( !Test_Dims( Node1, Node2 ) ) { Free_Last_Node(); fferror("Array sizes/dims do not match for binary operator"); return(-1); } if( that1->value.nelem == 1 ) that1 = that2; this->value.nelem = that1->value.nelem; this->value.naxis = that1->value.naxis; for( i=0; ivalue.naxis; i++ ) this->value.naxes[i] = that1->value.naxes[i]; if ( Op == ACCUM && that1->type == BITSTR ) { /* ACCUM is rank-reducing on bit strings */ this->value.nelem = 1; this->value.naxis = 1; this->value.naxes[0] = 1; } /* Both subnodes should be of same time */ switch( that1->type ) { case BITSTR: this->DoOp = Do_BinOp_bit; break; case STRING: this->DoOp = Do_BinOp_str; break; case BOOLEAN: this->DoOp = Do_BinOp_log; break; case LONG: this->DoOp = Do_BinOp_lng; break; case DOUBLE: this->DoOp = Do_BinOp_dbl; break; } if( constant ) this->DoOp( this ); } return( n ); } static int New_Func( int returnType, funcOp Op, int nNodes, int Node1, int Node2, int Node3, int Node4, int Node5, int Node6, int Node7 ) { return New_FuncSize(returnType, Op, nNodes, Node1, Node2, Node3, Node4, Node5, Node6, Node7, 0); } static int New_FuncSize( int returnType, funcOp Op, int nNodes, int Node1, int Node2, int Node3, int Node4, int Node5, int Node6, int Node7, int Size ) /* If returnType==0 , use Node1's type and vector sizes as returnType, */ /* else return a single value of type returnType */ { Node *this, *that; int i,n,constant; if( Node1<0 || Node2<0 || Node3<0 || Node4<0 || Node5<0 || Node6<0 || Node7<0 ) return(-1); n = Alloc_Node(); if( n>=0 ) { this = gParse.Nodes + n; this->operation = (int)Op; this->DoOp = Do_Func; this->nSubNodes = nNodes; this->SubNodes[0] = Node1; this->SubNodes[1] = Node2; this->SubNodes[2] = Node3; this->SubNodes[3] = Node4; this->SubNodes[4] = Node5; this->SubNodes[5] = Node6; this->SubNodes[6] = Node7; i = constant = nNodes; /* Functions with zero params are not const */ if (Op == poirnd_fct) constant = 0; /* Nor is Poisson deviate */ while( i-- ) constant = ( constant && OPER(this->SubNodes[i]) == CONST_OP ); if( returnType ) { this->type = returnType; this->value.nelem = 1; this->value.naxis = 1; this->value.naxes[0] = 1; } else { that = gParse.Nodes + Node1; this->type = that->type; this->value.nelem = that->value.nelem; this->value.naxis = that->value.naxis; for( i=0; ivalue.naxis; i++ ) this->value.naxes[i] = that->value.naxes[i]; } /* Force explicit size before evaluating */ if (Size > 0) this->value.nelem = Size; if( constant ) this->DoOp( this ); } return( n ); } static int New_Deref( int Var, int nDim, int Dim1, int Dim2, int Dim3, int Dim4, int Dim5 ) { int n, idx, constant; long elem=0; Node *this, *theVar, *theDim[MAXDIMS]; if( Var<0 || Dim1<0 || Dim2<0 || Dim3<0 || Dim4<0 || Dim5<0 ) return(-1); theVar = gParse.Nodes + Var; if( theVar->operation==CONST_OP || theVar->value.nelem==1 ) { fferror("Cannot index a scalar value"); return(-1); } n = Alloc_Node(); if( n>=0 ) { this = gParse.Nodes + n; this->nSubNodes = nDim+1; theVar = gParse.Nodes + (this->SubNodes[0]=Var); theDim[0] = gParse.Nodes + (this->SubNodes[1]=Dim1); theDim[1] = gParse.Nodes + (this->SubNodes[2]=Dim2); theDim[2] = gParse.Nodes + (this->SubNodes[3]=Dim3); theDim[3] = gParse.Nodes + (this->SubNodes[4]=Dim4); theDim[4] = gParse.Nodes + (this->SubNodes[5]=Dim5); constant = theVar->operation==CONST_OP; for( idx=0; idxoperation==CONST_OP); for( idx=0; idxvalue.nelem>1 ) { Free_Last_Node(); fferror("Cannot use an array as an index value"); return(-1); } else if( theDim[idx]->type!=LONG ) { Free_Last_Node(); fferror("Index value must be an integer type"); return(-1); } this->operation = '['; this->DoOp = Do_Deref; this->type = theVar->type; if( theVar->value.naxis == nDim ) { /* All dimensions specified */ this->value.nelem = 1; this->value.naxis = 1; this->value.naxes[0] = 1; } else if( nDim==1 ) { /* Dereference only one dimension */ elem=1; this->value.naxis = theVar->value.naxis-1; for( idx=0; idxvalue.naxis; idx++ ) { elem *= ( this->value.naxes[idx] = theVar->value.naxes[idx] ); } this->value.nelem = elem; } else { Free_Last_Node(); fferror("Must specify just one or all indices for vector"); return(-1); } if( constant ) this->DoOp( this ); } return(n); } extern int ffGetVariable( char *varName, FFSTYPE *varVal ); static int New_GTI( char *fname, int Node1, char *start, char *stop ) { fitsfile *fptr; Node *this, *that0, *that1; int type,i,n, startCol, stopCol, Node0; int hdutype, hdunum, evthdu, samefile, extvers, movetotype, tstat; char extname[100]; long nrows; double timeZeroI[2], timeZeroF[2], dt, timeSpan; char xcol[20], xexpr[20]; FFSTYPE colVal; if( Node1==-99 ) { type = ffGetVariable( "TIME", &colVal ); if( type==COLUMN ) { Node1 = New_Column( (int)colVal.lng ); } else { fferror("Could not build TIME column for GTIFILTER"); return(-1); } } Node1 = New_Unary( DOUBLE, 0, Node1 ); Node0 = Alloc_Node(); /* This will hold the START/STOP times */ if( Node1<0 || Node0<0 ) return(-1); /* Record current HDU number in case we need to move within this file */ fptr = gParse.def_fptr; ffghdn( fptr, &evthdu ); /* Look for TIMEZERO keywords in current extension */ tstat = 0; if( ffgkyd( fptr, "TIMEZERO", timeZeroI, NULL, &tstat ) ) { tstat = 0; if( ffgkyd( fptr, "TIMEZERI", timeZeroI, NULL, &tstat ) ) { timeZeroI[0] = timeZeroF[0] = 0.0; } else if( ffgkyd( fptr, "TIMEZERF", timeZeroF, NULL, &tstat ) ) { timeZeroF[0] = 0.0; } } else { timeZeroF[0] = 0.0; } /* Resolve filename parameter */ switch( fname[0] ) { case '\0': samefile = 1; hdunum = 1; break; case '[': samefile = 1; i = 1; while( fname[i] != '\0' && fname[i] != ']' ) i++; if( fname[i] ) { fname[i] = '\0'; fname++; ffexts( fname, &hdunum, extname, &extvers, &movetotype, xcol, xexpr, &gParse.status ); if( *extname ) { ffmnhd( fptr, movetotype, extname, extvers, &gParse.status ); ffghdn( fptr, &hdunum ); } else if( hdunum ) { ffmahd( fptr, ++hdunum, &hdutype, &gParse.status ); } else if( !gParse.status ) { fferror("Cannot use primary array for GTI filter"); return( -1 ); } } else { fferror("File extension specifier lacks closing ']'"); return( -1 ); } break; case '+': samefile = 1; hdunum = atoi( fname ) + 1; if( hdunum>1 ) ffmahd( fptr, hdunum, &hdutype, &gParse.status ); else { fferror("Cannot use primary array for GTI filter"); return( -1 ); } break; default: samefile = 0; if( ! ffopen( &fptr, fname, READONLY, &gParse.status ) ) ffghdn( fptr, &hdunum ); break; } if( gParse.status ) return(-1); /* If at primary, search for GTI extension */ if( hdunum==1 ) { while( 1 ) { hdunum++; if( ffmahd( fptr, hdunum, &hdutype, &gParse.status ) ) break; if( hdutype==IMAGE_HDU ) continue; tstat = 0; if( ffgkys( fptr, "EXTNAME", extname, NULL, &tstat ) ) continue; ffupch( extname ); if( strstr( extname, "GTI" ) ) break; } if( gParse.status ) { if( gParse.status==END_OF_FILE ) fferror("GTI extension not found in this file"); return(-1); } } /* Locate START/STOP Columns */ ffgcno( fptr, CASEINSEN, start, &startCol, &gParse.status ); ffgcno( fptr, CASEINSEN, stop, &stopCol, &gParse.status ); if( gParse.status ) return(-1); /* Look for TIMEZERO keywords in GTI extension */ tstat = 0; if( ffgkyd( fptr, "TIMEZERO", timeZeroI+1, NULL, &tstat ) ) { tstat = 0; if( ffgkyd( fptr, "TIMEZERI", timeZeroI+1, NULL, &tstat ) ) { timeZeroI[1] = timeZeroF[1] = 0.0; } else if( ffgkyd( fptr, "TIMEZERF", timeZeroF+1, NULL, &tstat ) ) { timeZeroF[1] = 0.0; } } else { timeZeroF[1] = 0.0; } n = Alloc_Node(); if( n >= 0 ) { this = gParse.Nodes + n; this->nSubNodes = 2; this->SubNodes[1] = Node1; this->operation = (int)gtifilt_fct; this->DoOp = Do_GTI; this->type = BOOLEAN; that1 = gParse.Nodes + Node1; this->value.nelem = that1->value.nelem; this->value.naxis = that1->value.naxis; for( i=0; i < that1->value.naxis; i++ ) this->value.naxes[i] = that1->value.naxes[i]; /* Init START/STOP node to be treated as a "constant" */ this->SubNodes[0] = Node0; that0 = gParse.Nodes + Node0; that0->operation = CONST_OP; that0->DoOp = NULL; that0->value.data.ptr= NULL; /* Read in START/STOP times */ if( ffgkyj( fptr, "NAXIS2", &nrows, NULL, &gParse.status ) ) return(-1); that0->value.nelem = nrows; if( nrows ) { that0->value.data.dblptr = (double*)malloc( 2*nrows*sizeof(double) ); if( !that0->value.data.dblptr ) { gParse.status = MEMORY_ALLOCATION; return(-1); } ffgcvd( fptr, startCol, 1L, 1L, nrows, 0.0, that0->value.data.dblptr, &i, &gParse.status ); ffgcvd( fptr, stopCol, 1L, 1L, nrows, 0.0, that0->value.data.dblptr+nrows, &i, &gParse.status ); if( gParse.status ) { free( that0->value.data.dblptr ); return(-1); } /* Test for fully time-ordered GTI... both START && STOP */ that0->type = 1; /* Assume yes */ i = nrows; while( --i ) if( that0->value.data.dblptr[i-1] >= that0->value.data.dblptr[i] || that0->value.data.dblptr[i-1+nrows] >= that0->value.data.dblptr[i+nrows] ) { that0->type = 0; break; } /* Handle TIMEZERO offset, if any */ dt = (timeZeroI[1] - timeZeroI[0]) + (timeZeroF[1] - timeZeroF[0]); timeSpan = that0->value.data.dblptr[nrows+nrows-1] - that0->value.data.dblptr[0]; if( fabs( dt / timeSpan ) > 1e-12 ) { for( i=0; i<(nrows+nrows); i++ ) that0->value.data.dblptr[i] += dt; } } if( OPER(Node1)==CONST_OP ) this->DoOp( this ); } if( samefile ) ffmahd( fptr, evthdu, &hdutype, &gParse.status ); else ffclos( fptr, &gParse.status ); return( n ); } static int New_REG( char *fname, int NodeX, int NodeY, char *colNames ) { Node *this, *that0; int type, n, Node0; int Xcol, Ycol, tstat; WCSdata wcs; SAORegion *Rgn; char *cX, *cY; FFSTYPE colVal; if( NodeX==-99 ) { type = ffGetVariable( "X", &colVal ); if( type==COLUMN ) { NodeX = New_Column( (int)colVal.lng ); } else { fferror("Could not build X column for REGFILTER"); return(-1); } } if( NodeY==-99 ) { type = ffGetVariable( "Y", &colVal ); if( type==COLUMN ) { NodeY = New_Column( (int)colVal.lng ); } else { fferror("Could not build Y column for REGFILTER"); return(-1); } } NodeX = New_Unary( DOUBLE, 0, NodeX ); NodeY = New_Unary( DOUBLE, 0, NodeY ); Node0 = Alloc_Node(); /* This will hold the Region Data */ if( NodeX<0 || NodeY<0 || Node0<0 ) return(-1); if( ! (Test_Dims( NodeX, NodeY ) ) ) { fferror("Dimensions of REGFILTER arguments are not compatible"); return (-1); } n = Alloc_Node(); if( n >= 0 ) { this = gParse.Nodes + n; this->nSubNodes = 3; this->SubNodes[0] = Node0; this->SubNodes[1] = NodeX; this->SubNodes[2] = NodeY; this->operation = (int)regfilt_fct; this->DoOp = Do_REG; this->type = BOOLEAN; this->value.nelem = 1; this->value.naxis = 1; this->value.naxes[0] = 1; Copy_Dims(n, NodeX); if( SIZE(NodeX)operation = CONST_OP; that0->DoOp = NULL; /* Identify what columns to use for WCS information */ Xcol = Ycol = 0; if( *colNames ) { /* Use the column names in this string for WCS info */ while( *colNames==' ' ) colNames++; cX = cY = colNames; while( *cY && *cY!=' ' && *cY!=',' ) cY++; if( *cY ) *(cY++) = '\0'; while( *cY==' ' ) cY++; if( !*cY ) { fferror("Could not extract valid pair of column names from REGFILTER"); Free_Last_Node(); return( -1 ); } fits_get_colnum( gParse.def_fptr, CASEINSEN, cX, &Xcol, &gParse.status ); fits_get_colnum( gParse.def_fptr, CASEINSEN, cY, &Ycol, &gParse.status ); if( gParse.status ) { fferror("Could not locate columns indicated for WCS info"); Free_Last_Node(); return( -1 ); } } else { /* Try to find columns used in X/Y expressions */ Xcol = Locate_Col( gParse.Nodes + NodeX ); Ycol = Locate_Col( gParse.Nodes + NodeY ); if( Xcol<0 || Ycol<0 ) { fferror("Found multiple X/Y column references in REGFILTER"); Free_Last_Node(); return( -1 ); } } /* Now, get the WCS info, if it exists, from the indicated columns */ wcs.exists = 0; if( Xcol>0 && Ycol>0 ) { tstat = 0; ffgtcs( gParse.def_fptr, Xcol, Ycol, &wcs.xrefval, &wcs.yrefval, &wcs.xrefpix, &wcs.yrefpix, &wcs.xinc, &wcs.yinc, &wcs.rot, wcs.type, &tstat ); if( tstat==NO_WCS_KEY ) { wcs.exists = 0; } else if( tstat ) { gParse.status = tstat; Free_Last_Node(); return( -1 ); } else { wcs.exists = 1; } } /* Read in Region file */ fits_read_rgnfile( fname, &wcs, &Rgn, &gParse.status ); if( gParse.status ) { Free_Last_Node(); return( -1 ); } that0->value.data.ptr = Rgn; if( OPER(NodeX)==CONST_OP && OPER(NodeY)==CONST_OP ) this->DoOp( this ); } return( n ); } static int New_Vector( int subNode ) { Node *this, *that; int n; n = Alloc_Node(); if( n >= 0 ) { this = gParse.Nodes + n; that = gParse.Nodes + subNode; this->type = that->type; this->nSubNodes = 1; this->SubNodes[0] = subNode; this->operation = '{'; this->DoOp = Do_Vector; } return( n ); } static int Close_Vec( int vecNode ) { Node *this; int n, nelem=0; this = gParse.Nodes + vecNode; for( n=0; n < this->nSubNodes; n++ ) { if( TYPE( this->SubNodes[n] ) != this->type ) { this->SubNodes[n] = New_Unary( this->type, 0, this->SubNodes[n] ); if( this->SubNodes[n]<0 ) return(-1); } nelem += SIZE(this->SubNodes[n]); } this->value.naxis = 1; this->value.nelem = nelem; this->value.naxes[0] = nelem; return( vecNode ); } static int Locate_Col( Node *this ) /* Locate the TABLE column number of any columns in "this" calculation. */ /* Return ZERO if none found, or negative if more than 1 found. */ { Node *that; int i, col=0, newCol, nfound=0; if( this->nSubNodes==0 && this->operation<=0 && this->operation!=CONST_OP ) return gParse.colData[ - this->operation].colnum; for( i=0; inSubNodes; i++ ) { that = gParse.Nodes + this->SubNodes[i]; if( that->operation>0 ) { newCol = Locate_Col( that ); if( newCol<=0 ) { nfound += -newCol; } else { if( !nfound ) { col = newCol; nfound++; } else if( col != newCol ) { nfound++; } } } else if( that->operation!=CONST_OP ) { /* Found a Column */ newCol = gParse.colData[- that->operation].colnum; if( !nfound ) { col = newCol; nfound++; } else if( col != newCol ) { nfound++; } } } if( nfound!=1 ) return( - nfound ); else return( col ); } static int Test_Dims( int Node1, int Node2 ) { Node *that1, *that2; int valid, i; if( Node1<0 || Node2<0 ) return(0); that1 = gParse.Nodes + Node1; that2 = gParse.Nodes + Node2; if( that1->value.nelem==1 || that2->value.nelem==1 ) valid = 1; else if( that1->type==that2->type && that1->value.nelem==that2->value.nelem && that1->value.naxis==that2->value.naxis ) { valid = 1; for( i=0; ivalue.naxis; i++ ) { if( that1->value.naxes[i]!=that2->value.naxes[i] ) valid = 0; } } else valid = 0; return( valid ); } static void Copy_Dims( int Node1, int Node2 ) { Node *that1, *that2; int i; if( Node1<0 || Node2<0 ) return; that1 = gParse.Nodes + Node1; that2 = gParse.Nodes + Node2; that1->value.nelem = that2->value.nelem; that1->value.naxis = that2->value.naxis; for( i=0; ivalue.naxis; i++ ) that1->value.naxes[i] = that2->value.naxes[i]; } /********************************************************************/ /* Routines for actually evaluating the expression start here */ /********************************************************************/ void Evaluate_Parser( long firstRow, long nRows ) /***********************************************************************/ /* Reset the parser for processing another batch of data... */ /* firstRow: Row number of the first element to evaluate */ /* nRows: Number of rows to be processed */ /* Initialize each COLUMN node so that its UNDEF and DATA pointers */ /* point to the appropriate column arrays. */ /* Finally, call Evaluate_Node for final node. */ /***********************************************************************/ { int i, column; long offset, rowOffset; static int rand_initialized = 0; /* Initialize the random number generator once and only once */ if (rand_initialized == 0) { simplerng_srand( (unsigned int) time(NULL) ); rand_initialized = 1; } gParse.firstRow = firstRow; gParse.nRows = nRows; /* Reset Column Nodes' pointers to point to right data and UNDEF arrays */ rowOffset = firstRow - gParse.firstDataRow; for( i=0; i 0 || OPER(i) == CONST_OP ) continue; column = -OPER(i); offset = gParse.varData[column].nelem * rowOffset; gParse.Nodes[i].value.undef = gParse.varData[column].undef + offset; switch( gParse.Nodes[i].type ) { case BITSTR: gParse.Nodes[i].value.data.strptr = (char**)gParse.varData[column].data + rowOffset; gParse.Nodes[i].value.undef = NULL; break; case STRING: gParse.Nodes[i].value.data.strptr = (char**)gParse.varData[column].data + rowOffset; gParse.Nodes[i].value.undef = gParse.varData[column].undef + rowOffset; break; case BOOLEAN: gParse.Nodes[i].value.data.logptr = (char*)gParse.varData[column].data + offset; break; case LONG: gParse.Nodes[i].value.data.lngptr = (long*)gParse.varData[column].data + offset; break; case DOUBLE: gParse.Nodes[i].value.data.dblptr = (double*)gParse.varData[column].data + offset; break; } } Evaluate_Node( gParse.resultNode ); } static void Evaluate_Node( int thisNode ) /**********************************************************************/ /* Recursively evaluate thisNode's subNodes, then call one of the */ /* Do_ functions pointed to by thisNode's DoOp element. */ /**********************************************************************/ { Node *this; int i; if( gParse.status ) return; this = gParse.Nodes + thisNode; if( this->operation>0 ) { /* <=0 indicate constants and columns */ i = this->nSubNodes; while( i-- ) { Evaluate_Node( this->SubNodes[i] ); if( gParse.status ) return; } this->DoOp( this ); } } static void Allocate_Ptrs( Node *this ) { long elem, row, size; if( this->type==BITSTR || this->type==STRING ) { this->value.data.strptr = (char**)malloc( gParse.nRows * sizeof(char*) ); if( this->value.data.strptr ) { this->value.data.strptr[0] = (char*)malloc( gParse.nRows * (this->value.nelem+2) * sizeof(char) ); if( this->value.data.strptr[0] ) { row = 0; while( (++row)value.data.strptr[row] = this->value.data.strptr[row-1] + this->value.nelem+1; } if( this->type==STRING ) { this->value.undef = this->value.data.strptr[row-1] + this->value.nelem+1; } else { this->value.undef = NULL; /* BITSTRs don't use undef array */ } } else { gParse.status = MEMORY_ALLOCATION; free( this->value.data.strptr ); } } else { gParse.status = MEMORY_ALLOCATION; } } else { elem = this->value.nelem * gParse.nRows; switch( this->type ) { case DOUBLE: size = sizeof( double ); break; case LONG: size = sizeof( long ); break; case BOOLEAN: size = sizeof( char ); break; default: size = 1; break; } this->value.data.ptr = calloc(size+1, elem); if( this->value.data.ptr==NULL ) { gParse.status = MEMORY_ALLOCATION; } else { this->value.undef = (char *)this->value.data.ptr + elem*size; } } } static void Do_Unary( Node *this ) { Node *that; long elem; that = gParse.Nodes + this->SubNodes[0]; if( that->operation==CONST_OP ) { /* Operating on a constant! */ switch( this->operation ) { case DOUBLE: case FLTCAST: if( that->type==LONG ) this->value.data.dbl = (double)that->value.data.lng; else if( that->type==BOOLEAN ) this->value.data.dbl = ( that->value.data.log ? 1.0 : 0.0 ); break; case LONG: case INTCAST: if( that->type==DOUBLE ) this->value.data.lng = (long)that->value.data.dbl; else if( that->type==BOOLEAN ) this->value.data.lng = ( that->value.data.log ? 1L : 0L ); break; case BOOLEAN: if( that->type==DOUBLE ) this->value.data.log = ( that->value.data.dbl != 0.0 ); else if( that->type==LONG ) this->value.data.log = ( that->value.data.lng != 0L ); break; case UMINUS: if( that->type==DOUBLE ) this->value.data.dbl = - that->value.data.dbl; else if( that->type==LONG ) this->value.data.lng = - that->value.data.lng; break; case NOT: if( that->type==BOOLEAN ) this->value.data.log = ( ! that->value.data.log ); else if( that->type==BITSTR ) bitnot( this->value.data.str, that->value.data.str ); break; } this->operation = CONST_OP; } else { Allocate_Ptrs( this ); if( !gParse.status ) { if( this->type!=BITSTR ) { elem = gParse.nRows; if( this->type!=STRING ) elem *= this->value.nelem; while( elem-- ) this->value.undef[elem] = that->value.undef[elem]; } elem = gParse.nRows * this->value.nelem; switch( this->operation ) { case BOOLEAN: if( that->type==DOUBLE ) while( elem-- ) this->value.data.logptr[elem] = ( that->value.data.dblptr[elem] != 0.0 ); else if( that->type==LONG ) while( elem-- ) this->value.data.logptr[elem] = ( that->value.data.lngptr[elem] != 0L ); break; case DOUBLE: case FLTCAST: if( that->type==LONG ) while( elem-- ) this->value.data.dblptr[elem] = (double)that->value.data.lngptr[elem]; else if( that->type==BOOLEAN ) while( elem-- ) this->value.data.dblptr[elem] = ( that->value.data.logptr[elem] ? 1.0 : 0.0 ); break; case LONG: case INTCAST: if( that->type==DOUBLE ) while( elem-- ) this->value.data.lngptr[elem] = (long)that->value.data.dblptr[elem]; else if( that->type==BOOLEAN ) while( elem-- ) this->value.data.lngptr[elem] = ( that->value.data.logptr[elem] ? 1L : 0L ); break; case UMINUS: if( that->type==DOUBLE ) { while( elem-- ) this->value.data.dblptr[elem] = - that->value.data.dblptr[elem]; } else if( that->type==LONG ) { while( elem-- ) this->value.data.lngptr[elem] = - that->value.data.lngptr[elem]; } break; case NOT: if( that->type==BOOLEAN ) { while( elem-- ) this->value.data.logptr[elem] = ( ! that->value.data.logptr[elem] ); } else if( that->type==BITSTR ) { elem = gParse.nRows; while( elem-- ) bitnot( this->value.data.strptr[elem], that->value.data.strptr[elem] ); } break; } } } if( that->operation>0 ) { free( that->value.data.ptr ); } } static void Do_Offset( Node *this ) { Node *col; long fRow, nRowOverlap, nRowReload, rowOffset; long nelem, elem, offset, nRealElem; int status; col = gParse.Nodes + this->SubNodes[0]; rowOffset = gParse.Nodes[ this->SubNodes[1] ].value.data.lng; Allocate_Ptrs( this ); fRow = gParse.firstRow + rowOffset; if( this->type==STRING || this->type==BITSTR ) nRealElem = 1; else nRealElem = this->value.nelem; nelem = nRealElem; if( fRow < gParse.firstDataRow ) { /* Must fill in data at start of array */ nRowReload = gParse.firstDataRow - fRow; if( nRowReload > gParse.nRows ) nRowReload = gParse.nRows; nRowOverlap = gParse.nRows - nRowReload; offset = 0; /* NULLify any values falling out of bounds */ while( fRow<1 && nRowReload>0 ) { if( this->type == BITSTR ) { nelem = this->value.nelem; this->value.data.strptr[offset][ nelem ] = '\0'; while( nelem-- ) this->value.data.strptr[offset][nelem] = '0'; offset++; } else { while( nelem-- ) this->value.undef[offset++] = 1; } nelem = nRealElem; fRow++; nRowReload--; } } else if( fRow + gParse.nRows > gParse.firstDataRow + gParse.nDataRows ) { /* Must fill in data at end of array */ nRowReload = (fRow+gParse.nRows) - (gParse.firstDataRow+gParse.nDataRows); if( nRowReload>gParse.nRows ) { nRowReload = gParse.nRows; } else { fRow = gParse.firstDataRow + gParse.nDataRows; } nRowOverlap = gParse.nRows - nRowReload; offset = nRowOverlap * nelem; /* NULLify any values falling out of bounds */ elem = gParse.nRows * nelem; while( fRow+nRowReload>gParse.totalRows && nRowReload>0 ) { if( this->type == BITSTR ) { nelem = this->value.nelem; elem--; this->value.data.strptr[elem][ nelem ] = '\0'; while( nelem-- ) this->value.data.strptr[elem][nelem] = '0'; } else { while( nelem-- ) this->value.undef[--elem] = 1; } nelem = nRealElem; nRowReload--; } } else { nRowReload = 0; nRowOverlap = gParse.nRows; offset = 0; } if( nRowReload>0 ) { switch( this->type ) { case BITSTR: case STRING: status = (*gParse.loadData)( -col->operation, fRow, nRowReload, this->value.data.strptr+offset, this->value.undef+offset ); break; case BOOLEAN: status = (*gParse.loadData)( -col->operation, fRow, nRowReload, this->value.data.logptr+offset, this->value.undef+offset ); break; case LONG: status = (*gParse.loadData)( -col->operation, fRow, nRowReload, this->value.data.lngptr+offset, this->value.undef+offset ); break; case DOUBLE: status = (*gParse.loadData)( -col->operation, fRow, nRowReload, this->value.data.dblptr+offset, this->value.undef+offset ); break; } } /* Now copy over the overlapping region, if any */ if( nRowOverlap <= 0 ) return; if( rowOffset>0 ) elem = nRowOverlap * nelem; else elem = gParse.nRows * nelem; offset = nelem * rowOffset; while( nRowOverlap-- && !gParse.status ) { while( nelem-- && !gParse.status ) { elem--; if( this->type != BITSTR ) this->value.undef[elem] = col->value.undef[elem+offset]; switch( this->type ) { case BITSTR: strcpy( this->value.data.strptr[elem ], col->value.data.strptr[elem+offset] ); break; case STRING: strcpy( this->value.data.strptr[elem ], col->value.data.strptr[elem+offset] ); break; case BOOLEAN: this->value.data.logptr[elem] = col->value.data.logptr[elem+offset]; break; case LONG: this->value.data.lngptr[elem] = col->value.data.lngptr[elem+offset]; break; case DOUBLE: this->value.data.dblptr[elem] = col->value.data.dblptr[elem+offset]; break; } } nelem = nRealElem; } } static void Do_BinOp_bit( Node *this ) { Node *that1, *that2; char *sptr1=NULL, *sptr2=NULL; int const1, const2; long rows; that1 = gParse.Nodes + this->SubNodes[0]; that2 = gParse.Nodes + this->SubNodes[1]; const1 = ( that1->operation==CONST_OP ); const2 = ( that2->operation==CONST_OP ); sptr1 = ( const1 ? that1->value.data.str : NULL ); sptr2 = ( const2 ? that2->value.data.str : NULL ); if( const1 && const2 ) { switch( this->operation ) { case NE: this->value.data.log = !bitcmp( sptr1, sptr2 ); break; case EQ: this->value.data.log = bitcmp( sptr1, sptr2 ); break; case GT: case LT: case LTE: case GTE: this->value.data.log = bitlgte( sptr1, this->operation, sptr2 ); break; case '|': bitor( this->value.data.str, sptr1, sptr2 ); break; case '&': bitand( this->value.data.str, sptr1, sptr2 ); break; case '+': strcpy( this->value.data.str, sptr1 ); strcat( this->value.data.str, sptr2 ); break; case ACCUM: this->value.data.lng = 0; while( *sptr1 ) { if ( *sptr1 == '1' ) this->value.data.lng ++; sptr1 ++; } break; } this->operation = CONST_OP; } else { Allocate_Ptrs( this ); if( !gParse.status ) { rows = gParse.nRows; switch( this->operation ) { /* BITSTR comparisons */ case NE: case EQ: case GT: case LT: case LTE: case GTE: while( rows-- ) { if( !const1 ) sptr1 = that1->value.data.strptr[rows]; if( !const2 ) sptr2 = that2->value.data.strptr[rows]; switch( this->operation ) { case NE: this->value.data.logptr[rows] = !bitcmp( sptr1, sptr2 ); break; case EQ: this->value.data.logptr[rows] = bitcmp( sptr1, sptr2 ); break; case GT: case LT: case LTE: case GTE: this->value.data.logptr[rows] = bitlgte( sptr1, this->operation, sptr2 ); break; } this->value.undef[rows] = 0; } break; /* BITSTR AND/ORs ... no UNDEFS in or out */ case '|': case '&': case '+': while( rows-- ) { if( !const1 ) sptr1 = that1->value.data.strptr[rows]; if( !const2 ) sptr2 = that2->value.data.strptr[rows]; if( this->operation=='|' ) bitor( this->value.data.strptr[rows], sptr1, sptr2 ); else if( this->operation=='&' ) bitand( this->value.data.strptr[rows], sptr1, sptr2 ); else { strcpy( this->value.data.strptr[rows], sptr1 ); strcat( this->value.data.strptr[rows], sptr2 ); } } break; /* Accumulate 1 bits */ case ACCUM: { long i, previous, curr; previous = that2->value.data.lng; /* Cumulative sum of this chunk */ for (i=0; ivalue.data.strptr[i]; for (curr = 0; *sptr1; sptr1 ++) { if ( *sptr1 == '1' ) curr ++; } previous += curr; this->value.data.lngptr[i] = previous; this->value.undef[i] = 0; } /* Store final cumulant for next pass */ that2->value.data.lng = previous; } } } } if( that1->operation>0 ) { free( that1->value.data.strptr[0] ); free( that1->value.data.strptr ); } if( that2->operation>0 ) { free( that2->value.data.strptr[0] ); free( that2->value.data.strptr ); } } static void Do_BinOp_str( Node *this ) { Node *that1, *that2; char *sptr1, *sptr2, null1=0, null2=0; int const1, const2, val; long rows; that1 = gParse.Nodes + this->SubNodes[0]; that2 = gParse.Nodes + this->SubNodes[1]; const1 = ( that1->operation==CONST_OP ); const2 = ( that2->operation==CONST_OP ); sptr1 = ( const1 ? that1->value.data.str : NULL ); sptr2 = ( const2 ? that2->value.data.str : NULL ); if( const1 && const2 ) { /* Result is a constant */ switch( this->operation ) { /* Compare Strings */ case NE: case EQ: val = ( FSTRCMP( sptr1, sptr2 ) == 0 ); this->value.data.log = ( this->operation==EQ ? val : !val ); break; case GT: this->value.data.log = ( FSTRCMP( sptr1, sptr2 ) > 0 ); break; case LT: this->value.data.log = ( FSTRCMP( sptr1, sptr2 ) < 0 ); break; case GTE: this->value.data.log = ( FSTRCMP( sptr1, sptr2 ) >= 0 ); break; case LTE: this->value.data.log = ( FSTRCMP( sptr1, sptr2 ) <= 0 ); break; /* Concat Strings */ case '+': strcpy( this->value.data.str, sptr1 ); strcat( this->value.data.str, sptr2 ); break; } this->operation = CONST_OP; } else { /* Not a constant */ Allocate_Ptrs( this ); if( !gParse.status ) { rows = gParse.nRows; switch( this->operation ) { /* Compare Strings */ case NE: case EQ: while( rows-- ) { if( !const1 ) null1 = that1->value.undef[rows]; if( !const2 ) null2 = that2->value.undef[rows]; this->value.undef[rows] = (null1 || null2); if( ! this->value.undef[rows] ) { if( !const1 ) sptr1 = that1->value.data.strptr[rows]; if( !const2 ) sptr2 = that2->value.data.strptr[rows]; val = ( FSTRCMP( sptr1, sptr2 ) == 0 ); this->value.data.logptr[rows] = ( this->operation==EQ ? val : !val ); } } break; case GT: case LT: while( rows-- ) { if( !const1 ) null1 = that1->value.undef[rows]; if( !const2 ) null2 = that2->value.undef[rows]; this->value.undef[rows] = (null1 || null2); if( ! this->value.undef[rows] ) { if( !const1 ) sptr1 = that1->value.data.strptr[rows]; if( !const2 ) sptr2 = that2->value.data.strptr[rows]; val = ( FSTRCMP( sptr1, sptr2 ) ); this->value.data.logptr[rows] = ( this->operation==GT ? val>0 : val<0 ); } } break; case GTE: case LTE: while( rows-- ) { if( !const1 ) null1 = that1->value.undef[rows]; if( !const2 ) null2 = that2->value.undef[rows]; this->value.undef[rows] = (null1 || null2); if( ! this->value.undef[rows] ) { if( !const1 ) sptr1 = that1->value.data.strptr[rows]; if( !const2 ) sptr2 = that2->value.data.strptr[rows]; val = ( FSTRCMP( sptr1, sptr2 ) ); this->value.data.logptr[rows] = ( this->operation==GTE ? val>=0 : val<=0 ); } } break; /* Concat Strings */ case '+': while( rows-- ) { if( !const1 ) null1 = that1->value.undef[rows]; if( !const2 ) null2 = that2->value.undef[rows]; this->value.undef[rows] = (null1 || null2); if( ! this->value.undef[rows] ) { if( !const1 ) sptr1 = that1->value.data.strptr[rows]; if( !const2 ) sptr2 = that2->value.data.strptr[rows]; strcpy( this->value.data.strptr[rows], sptr1 ); strcat( this->value.data.strptr[rows], sptr2 ); } } break; } } } if( that1->operation>0 ) { free( that1->value.data.strptr[0] ); free( that1->value.data.strptr ); } if( that2->operation>0 ) { free( that2->value.data.strptr[0] ); free( that2->value.data.strptr ); } } static void Do_BinOp_log( Node *this ) { Node *that1, *that2; int vector1, vector2; char val1=0, val2=0, null1=0, null2=0; long rows, nelem, elem; that1 = gParse.Nodes + this->SubNodes[0]; that2 = gParse.Nodes + this->SubNodes[1]; vector1 = ( that1->operation!=CONST_OP ); if( vector1 ) vector1 = that1->value.nelem; else { val1 = that1->value.data.log; } vector2 = ( that2->operation!=CONST_OP ); if( vector2 ) vector2 = that2->value.nelem; else { val2 = that2->value.data.log; } if( !vector1 && !vector2 ) { /* Result is a constant */ switch( this->operation ) { case OR: this->value.data.log = (val1 || val2); break; case AND: this->value.data.log = (val1 && val2); break; case EQ: this->value.data.log = ( (val1 && val2) || (!val1 && !val2) ); break; case NE: this->value.data.log = ( (val1 && !val2) || (!val1 && val2) ); break; case ACCUM: this->value.data.lng = val1; break; } this->operation=CONST_OP; } else if (this->operation == ACCUM) { long i, previous, curr; rows = gParse.nRows; nelem = this->value.nelem; elem = this->value.nelem * rows; Allocate_Ptrs( this ); if( !gParse.status ) { previous = that2->value.data.lng; /* Cumulative sum of this chunk */ for (i=0; ivalue.undef[i]) { curr = that1->value.data.logptr[i]; previous += curr; } this->value.data.lngptr[i] = previous; this->value.undef[i] = 0; } /* Store final cumulant for next pass */ that2->value.data.lng = previous; } } else { rows = gParse.nRows; nelem = this->value.nelem; elem = this->value.nelem * rows; Allocate_Ptrs( this ); if( !gParse.status ) { if (this->operation == ACCUM) { long i, previous, curr; previous = that2->value.data.lng; /* Cumulative sum of this chunk */ for (i=0; ivalue.undef[i]) { curr = that1->value.data.logptr[i]; previous += curr; } this->value.data.lngptr[i] = previous; this->value.undef[i] = 0; } /* Store final cumulant for next pass */ that2->value.data.lng = previous; } while( rows-- ) { while( nelem-- ) { elem--; if( vector1>1 ) { val1 = that1->value.data.logptr[elem]; null1 = that1->value.undef[elem]; } else if( vector1 ) { val1 = that1->value.data.logptr[rows]; null1 = that1->value.undef[rows]; } if( vector2>1 ) { val2 = that2->value.data.logptr[elem]; null2 = that2->value.undef[elem]; } else if( vector2 ) { val2 = that2->value.data.logptr[rows]; null2 = that2->value.undef[rows]; } this->value.undef[elem] = (null1 || null2); switch( this->operation ) { case OR: /* This is more complicated than others to suppress UNDEFs */ /* in those cases where the other argument is DEF && TRUE */ if( !null1 && !null2 ) { this->value.data.logptr[elem] = (val1 || val2); } else if( (null1 && !null2 && val2) || ( !null1 && null2 && val1 ) ) { this->value.data.logptr[elem] = 1; this->value.undef[elem] = 0; } break; case AND: /* This is more complicated than others to suppress UNDEFs */ /* in those cases where the other argument is DEF && FALSE */ if( !null1 && !null2 ) { this->value.data.logptr[elem] = (val1 && val2); } else if( (null1 && !null2 && !val2) || ( !null1 && null2 && !val1 ) ) { this->value.data.logptr[elem] = 0; this->value.undef[elem] = 0; } break; case EQ: this->value.data.logptr[elem] = ( (val1 && val2) || (!val1 && !val2) ); break; case NE: this->value.data.logptr[elem] = ( (val1 && !val2) || (!val1 && val2) ); break; } } nelem = this->value.nelem; } } } if( that1->operation>0 ) { free( that1->value.data.ptr ); } if( that2->operation>0 ) { free( that2->value.data.ptr ); } } static void Do_BinOp_lng( Node *this ) { Node *that1, *that2; int vector1, vector2; long val1=0, val2=0; char null1=0, null2=0; long rows, nelem, elem; that1 = gParse.Nodes + this->SubNodes[0]; that2 = gParse.Nodes + this->SubNodes[1]; vector1 = ( that1->operation!=CONST_OP ); if( vector1 ) vector1 = that1->value.nelem; else { val1 = that1->value.data.lng; } vector2 = ( that2->operation!=CONST_OP ); if( vector2 ) vector2 = that2->value.nelem; else { val2 = that2->value.data.lng; } if( !vector1 && !vector2 ) { /* Result is a constant */ switch( this->operation ) { case '~': /* Treat as == for LONGS */ case EQ: this->value.data.log = (val1 == val2); break; case NE: this->value.data.log = (val1 != val2); break; case GT: this->value.data.log = (val1 > val2); break; case LT: this->value.data.log = (val1 < val2); break; case LTE: this->value.data.log = (val1 <= val2); break; case GTE: this->value.data.log = (val1 >= val2); break; case '+': this->value.data.lng = (val1 + val2); break; case '-': this->value.data.lng = (val1 - val2); break; case '*': this->value.data.lng = (val1 * val2); break; case '%': if( val2 ) this->value.data.lng = (val1 % val2); else fferror("Divide by Zero"); break; case '/': if( val2 ) this->value.data.lng = (val1 / val2); else fferror("Divide by Zero"); break; case POWER: this->value.data.lng = (long)pow((double)val1,(double)val2); break; case ACCUM: this->value.data.lng = val1; break; case DIFF: this->value.data.lng = 0; break; } this->operation=CONST_OP; } else if ((this->operation == ACCUM) || (this->operation == DIFF)) { long i, previous, curr; long undef; rows = gParse.nRows; nelem = this->value.nelem; elem = this->value.nelem * rows; Allocate_Ptrs( this ); if( !gParse.status ) { previous = that2->value.data.lng; undef = (long) that2->value.undef; if (this->operation == ACCUM) { /* Cumulative sum of this chunk */ for (i=0; ivalue.undef[i]) { curr = that1->value.data.lngptr[i]; previous += curr; } this->value.data.lngptr[i] = previous; this->value.undef[i] = 0; } } else { /* Sequential difference for this chunk */ for (i=0; ivalue.data.lngptr[i]; if (that1->value.undef[i] || undef) { /* Either this, or previous, value was undefined */ this->value.data.lngptr[i] = 0; this->value.undef[i] = 1; } else { /* Both defined, we are okay! */ this->value.data.lngptr[i] = curr - previous; this->value.undef[i] = 0; } previous = curr; undef = that1->value.undef[i]; } } /* Store final cumulant for next pass */ that2->value.data.lng = previous; that2->value.undef = (char *) undef; /* XXX evil, but no harm here */ } } else { rows = gParse.nRows; nelem = this->value.nelem; elem = this->value.nelem * rows; Allocate_Ptrs( this ); while( rows-- && !gParse.status ) { while( nelem-- && !gParse.status ) { elem--; if( vector1>1 ) { val1 = that1->value.data.lngptr[elem]; null1 = that1->value.undef[elem]; } else if( vector1 ) { val1 = that1->value.data.lngptr[rows]; null1 = that1->value.undef[rows]; } if( vector2>1 ) { val2 = that2->value.data.lngptr[elem]; null2 = that2->value.undef[elem]; } else if( vector2 ) { val2 = that2->value.data.lngptr[rows]; null2 = that2->value.undef[rows]; } this->value.undef[elem] = (null1 || null2); switch( this->operation ) { case '~': /* Treat as == for LONGS */ case EQ: this->value.data.logptr[elem] = (val1 == val2); break; case NE: this->value.data.logptr[elem] = (val1 != val2); break; case GT: this->value.data.logptr[elem] = (val1 > val2); break; case LT: this->value.data.logptr[elem] = (val1 < val2); break; case LTE: this->value.data.logptr[elem] = (val1 <= val2); break; case GTE: this->value.data.logptr[elem] = (val1 >= val2); break; case '+': this->value.data.lngptr[elem] = (val1 + val2); break; case '-': this->value.data.lngptr[elem] = (val1 - val2); break; case '*': this->value.data.lngptr[elem] = (val1 * val2); break; case '%': if( val2 ) this->value.data.lngptr[elem] = (val1 % val2); else { this->value.data.lngptr[elem] = 0; this->value.undef[elem] = 1; } break; case '/': if( val2 ) this->value.data.lngptr[elem] = (val1 / val2); else { this->value.data.lngptr[elem] = 0; this->value.undef[elem] = 1; } break; case POWER: this->value.data.lngptr[elem] = (long)pow((double)val1,(double)val2); break; } } nelem = this->value.nelem; } } if( that1->operation>0 ) { free( that1->value.data.ptr ); } if( that2->operation>0 ) { free( that2->value.data.ptr ); } } static void Do_BinOp_dbl( Node *this ) { Node *that1, *that2; int vector1, vector2; double val1=0.0, val2=0.0; char null1=0, null2=0; long rows, nelem, elem; that1 = gParse.Nodes + this->SubNodes[0]; that2 = gParse.Nodes + this->SubNodes[1]; vector1 = ( that1->operation!=CONST_OP ); if( vector1 ) vector1 = that1->value.nelem; else { val1 = that1->value.data.dbl; } vector2 = ( that2->operation!=CONST_OP ); if( vector2 ) vector2 = that2->value.nelem; else { val2 = that2->value.data.dbl; } if( !vector1 && !vector2 ) { /* Result is a constant */ switch( this->operation ) { case '~': this->value.data.log = ( fabs(val1-val2) < APPROX ); break; case EQ: this->value.data.log = (val1 == val2); break; case NE: this->value.data.log = (val1 != val2); break; case GT: this->value.data.log = (val1 > val2); break; case LT: this->value.data.log = (val1 < val2); break; case LTE: this->value.data.log = (val1 <= val2); break; case GTE: this->value.data.log = (val1 >= val2); break; case '+': this->value.data.dbl = (val1 + val2); break; case '-': this->value.data.dbl = (val1 - val2); break; case '*': this->value.data.dbl = (val1 * val2); break; case '%': if( val2 ) this->value.data.dbl = val1 - val2*((int)(val1/val2)); else fferror("Divide by Zero"); break; case '/': if( val2 ) this->value.data.dbl = (val1 / val2); else fferror("Divide by Zero"); break; case POWER: this->value.data.dbl = (double)pow(val1,val2); break; case ACCUM: this->value.data.dbl = val1; break; case DIFF: this->value.data.dbl = 0; break; } this->operation=CONST_OP; } else if ((this->operation == ACCUM) || (this->operation == DIFF)) { long i; long undef; double previous, curr; rows = gParse.nRows; nelem = this->value.nelem; elem = this->value.nelem * rows; Allocate_Ptrs( this ); if( !gParse.status ) { previous = that2->value.data.dbl; undef = (long) that2->value.undef; if (this->operation == ACCUM) { /* Cumulative sum of this chunk */ for (i=0; ivalue.undef[i]) { curr = that1->value.data.dblptr[i]; previous += curr; } this->value.data.dblptr[i] = previous; this->value.undef[i] = 0; } } else { /* Sequential difference for this chunk */ for (i=0; ivalue.data.dblptr[i]; if (that1->value.undef[i] || undef) { /* Either this, or previous, value was undefined */ this->value.data.dblptr[i] = 0; this->value.undef[i] = 1; } else { /* Both defined, we are okay! */ this->value.data.dblptr[i] = curr - previous; this->value.undef[i] = 0; } previous = curr; undef = that1->value.undef[i]; } } /* Store final cumulant for next pass */ that2->value.data.dbl = previous; that2->value.undef = (char *) undef; /* XXX evil, but no harm here */ } } else { rows = gParse.nRows; nelem = this->value.nelem; elem = this->value.nelem * rows; Allocate_Ptrs( this ); while( rows-- && !gParse.status ) { while( nelem-- && !gParse.status ) { elem--; if( vector1>1 ) { val1 = that1->value.data.dblptr[elem]; null1 = that1->value.undef[elem]; } else if( vector1 ) { val1 = that1->value.data.dblptr[rows]; null1 = that1->value.undef[rows]; } if( vector2>1 ) { val2 = that2->value.data.dblptr[elem]; null2 = that2->value.undef[elem]; } else if( vector2 ) { val2 = that2->value.data.dblptr[rows]; null2 = that2->value.undef[rows]; } this->value.undef[elem] = (null1 || null2); switch( this->operation ) { case '~': this->value.data.logptr[elem] = ( fabs(val1-val2) < APPROX ); break; case EQ: this->value.data.logptr[elem] = (val1 == val2); break; case NE: this->value.data.logptr[elem] = (val1 != val2); break; case GT: this->value.data.logptr[elem] = (val1 > val2); break; case LT: this->value.data.logptr[elem] = (val1 < val2); break; case LTE: this->value.data.logptr[elem] = (val1 <= val2); break; case GTE: this->value.data.logptr[elem] = (val1 >= val2); break; case '+': this->value.data.dblptr[elem] = (val1 + val2); break; case '-': this->value.data.dblptr[elem] = (val1 - val2); break; case '*': this->value.data.dblptr[elem] = (val1 * val2); break; case '%': if( val2 ) this->value.data.dblptr[elem] = val1 - val2*((int)(val1/val2)); else { this->value.data.dblptr[elem] = 0.0; this->value.undef[elem] = 1; } break; case '/': if( val2 ) this->value.data.dblptr[elem] = (val1 / val2); else { this->value.data.dblptr[elem] = 0.0; this->value.undef[elem] = 1; } break; case POWER: this->value.data.dblptr[elem] = (double)pow(val1,val2); break; } } nelem = this->value.nelem; } } if( that1->operation>0 ) { free( that1->value.data.ptr ); } if( that2->operation>0 ) { free( that2->value.data.ptr ); } } /* * This Quickselect routine is based on the algorithm described in * "Numerical recipes in C", Second Edition, * Cambridge University Press, 1992, Section 8.5, ISBN 0-521-43108-5 * This code by Nicolas Devillard - 1998. Public domain. * http://ndevilla.free.fr/median/median/src/quickselect.c */ #define ELEM_SWAP(a,b) { register long t=(a);(a)=(b);(b)=t; } /* * qselect_median_lng - select the median value of a long array * * This routine selects the median value of the long integer array * arr[]. If there are an even number of elements, the "lower median" * is selected. * * The array arr[] is scrambled, so users must operate on a scratch * array if they wish the values to be preserved. * * long arr[] - array of values * int n - number of elements in arr * * RETURNS: the lower median value of arr[] * */ long qselect_median_lng(long arr[], int n) { int low, high ; int median; int middle, ll, hh; low = 0 ; high = n-1 ; median = (low + high) / 2; for (;;) { if (high <= low) { /* One element only */ return arr[median]; } if (high == low + 1) { /* Two elements only */ if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]) ; return arr[median]; } /* Find median of low, middle and high items; swap into position low */ middle = (low + high) / 2; if (arr[middle] > arr[high]) ELEM_SWAP(arr[middle], arr[high]) ; if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]) ; if (arr[middle] > arr[low]) ELEM_SWAP(arr[middle], arr[low]) ; /* Swap low item (now in position middle) into position (low+1) */ ELEM_SWAP(arr[middle], arr[low+1]) ; /* Nibble from each end towards middle, swapping items when stuck */ ll = low + 1; hh = high; for (;;) { do ll++; while (arr[low] > arr[ll]) ; do hh--; while (arr[hh] > arr[low]) ; if (hh < ll) break; ELEM_SWAP(arr[ll], arr[hh]) ; } /* Swap middle item (in position low) back into correct position */ ELEM_SWAP(arr[low], arr[hh]) ; /* Re-set active partition */ if (hh <= median) low = ll; if (hh >= median) high = hh - 1; } } #undef ELEM_SWAP #define ELEM_SWAP(a,b) { register double t=(a);(a)=(b);(b)=t; } /* * qselect_median_dbl - select the median value of a double array * * This routine selects the median value of the double array * arr[]. If there are an even number of elements, the "lower median" * is selected. * * The array arr[] is scrambled, so users must operate on a scratch * array if they wish the values to be preserved. * * double arr[] - array of values * int n - number of elements in arr * * RETURNS: the lower median value of arr[] * */ double qselect_median_dbl(double arr[], int n) { int low, high ; int median; int middle, ll, hh; low = 0 ; high = n-1 ; median = (low + high) / 2; for (;;) { if (high <= low) { /* One element only */ return arr[median] ; } if (high == low + 1) { /* Two elements only */ if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]) ; return arr[median] ; } /* Find median of low, middle and high items; swap into position low */ middle = (low + high) / 2; if (arr[middle] > arr[high]) ELEM_SWAP(arr[middle], arr[high]) ; if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]) ; if (arr[middle] > arr[low]) ELEM_SWAP(arr[middle], arr[low]) ; /* Swap low item (now in position middle) into position (low+1) */ ELEM_SWAP(arr[middle], arr[low+1]) ; /* Nibble from each end towards middle, swapping items when stuck */ ll = low + 1; hh = high; for (;;) { do ll++; while (arr[low] > arr[ll]) ; do hh--; while (arr[hh] > arr[low]) ; if (hh < ll) break; ELEM_SWAP(arr[ll], arr[hh]) ; } /* Swap middle item (in position low) back into correct position */ ELEM_SWAP(arr[low], arr[hh]) ; /* Re-set active partition */ if (hh <= median) low = ll; if (hh >= median) high = hh - 1; } } #undef ELEM_SWAP /* * angsep_calc - compute angular separation between celestial coordinates * * This routine computes the angular separation between to coordinates * on the celestial sphere (i.e. RA and Dec). Note that all units are * in DEGREES, unlike the other trig functions in the calculator. * * double ra1, dec1 - RA and Dec of the first position in degrees * double ra2, dec2 - RA and Dec of the second position in degrees * * RETURNS: (double) angular separation in degrees * */ double angsep_calc(double ra1, double dec1, double ra2, double dec2) { /* double cd; */ static double deg = 0; double a, sdec, sra; if (deg == 0) deg = ((double)4)*atan((double)1)/((double)180); /* deg = 1.0; **** UNCOMMENT IF YOU WANT RADIANS */ /* The algorithm is the law of Haversines. This algorithm is stable even when the points are close together. The normal Law of Cosines fails for angles around 0.1 arcsec. */ sra = sin( (ra2 - ra1)*deg / 2 ); sdec = sin( (dec2 - dec1)*deg / 2); a = sdec*sdec + cos(dec1*deg)*cos(dec2*deg)*sra*sra; /* Sanity checking to avoid a range error in the sqrt()'s below */ if (a < 0) { a = 0; } if (a > 1) { a = 1; } return 2.0*atan2(sqrt(a), sqrt(1.0 - a)) / deg; } static void Do_Func( Node *this ) { Node *theParams[MAXSUBS]; int vector[MAXSUBS], allConst; lval pVals[MAXSUBS]; char pNull[MAXSUBS]; long ival; double dval; int i, valInit; long row, elem, nelem; i = this->nSubNodes; allConst = 1; while( i-- ) { theParams[i] = gParse.Nodes + this->SubNodes[i]; vector[i] = ( theParams[i]->operation!=CONST_OP ); if( vector[i] ) { allConst = 0; vector[i] = theParams[i]->value.nelem; } else { if( theParams[i]->type==DOUBLE ) { pVals[i].data.dbl = theParams[i]->value.data.dbl; } else if( theParams[i]->type==LONG ) { pVals[i].data.lng = theParams[i]->value.data.lng; } else if( theParams[i]->type==BOOLEAN ) { pVals[i].data.log = theParams[i]->value.data.log; } else strcpy(pVals[i].data.str, theParams[i]->value.data.str); pNull[i] = 0; } } if( this->nSubNodes==0 ) allConst = 0; /* These do produce scalars */ /* Random numbers are *never* constant !! */ if( this->operation == poirnd_fct ) allConst = 0; if( this->operation == gasrnd_fct ) allConst = 0; if( this->operation == rnd_fct ) allConst = 0; if( allConst ) { switch( this->operation ) { /* Non-Trig single-argument functions */ case sum_fct: if( theParams[0]->type==BOOLEAN ) this->value.data.lng = ( pVals[0].data.log ? 1 : 0 ); else if( theParams[0]->type==LONG ) this->value.data.lng = pVals[0].data.lng; else if( theParams[0]->type==DOUBLE ) this->value.data.dbl = pVals[0].data.dbl; else if( theParams[0]->type==BITSTR ) strcpy(this->value.data.str, pVals[0].data.str); break; case average_fct: if( theParams[0]->type==LONG ) this->value.data.dbl = pVals[0].data.lng; else if( theParams[0]->type==DOUBLE ) this->value.data.dbl = pVals[0].data.dbl; break; case stddev_fct: this->value.data.dbl = 0; /* Standard deviation of a constant = 0 */ break; case median_fct: if( theParams[0]->type==BOOLEAN ) this->value.data.lng = ( pVals[0].data.log ? 1 : 0 ); else if( theParams[0]->type==LONG ) this->value.data.lng = pVals[0].data.lng; else this->value.data.dbl = pVals[0].data.dbl; break; case poirnd_fct: if( theParams[0]->type==DOUBLE ) this->value.data.lng = simplerng_getpoisson(pVals[0].data.dbl); else this->value.data.lng = simplerng_getpoisson(pVals[0].data.lng); break; case abs_fct: if( theParams[0]->type==DOUBLE ) { dval = pVals[0].data.dbl; this->value.data.dbl = (dval>0.0 ? dval : -dval); } else { ival = pVals[0].data.lng; this->value.data.lng = (ival> 0 ? ival : -ival); } break; /* Special Null-Handling Functions */ case nonnull_fct: this->value.data.lng = 1; /* Constants are always 1-element and defined */ break; case isnull_fct: /* Constants are always defined */ this->value.data.log = 0; break; case defnull_fct: if( this->type==BOOLEAN ) this->value.data.log = pVals[0].data.log; else if( this->type==LONG ) this->value.data.lng = pVals[0].data.lng; else if( this->type==DOUBLE ) this->value.data.dbl = pVals[0].data.dbl; else if( this->type==STRING ) strcpy(this->value.data.str,pVals[0].data.str); break; /* Math functions with 1 double argument */ case sin_fct: this->value.data.dbl = sin( pVals[0].data.dbl ); break; case cos_fct: this->value.data.dbl = cos( pVals[0].data.dbl ); break; case tan_fct: this->value.data.dbl = tan( pVals[0].data.dbl ); break; case asin_fct: dval = pVals[0].data.dbl; if( dval<-1.0 || dval>1.0 ) fferror("Out of range argument to arcsin"); else this->value.data.dbl = asin( dval ); break; case acos_fct: dval = pVals[0].data.dbl; if( dval<-1.0 || dval>1.0 ) fferror("Out of range argument to arccos"); else this->value.data.dbl = acos( dval ); break; case atan_fct: this->value.data.dbl = atan( pVals[0].data.dbl ); break; case sinh_fct: this->value.data.dbl = sinh( pVals[0].data.dbl ); break; case cosh_fct: this->value.data.dbl = cosh( pVals[0].data.dbl ); break; case tanh_fct: this->value.data.dbl = tanh( pVals[0].data.dbl ); break; case exp_fct: this->value.data.dbl = exp( pVals[0].data.dbl ); break; case log_fct: dval = pVals[0].data.dbl; if( dval<=0.0 ) fferror("Out of range argument to log"); else this->value.data.dbl = log( dval ); break; case log10_fct: dval = pVals[0].data.dbl; if( dval<=0.0 ) fferror("Out of range argument to log10"); else this->value.data.dbl = log10( dval ); break; case sqrt_fct: dval = pVals[0].data.dbl; if( dval<0.0 ) fferror("Out of range argument to sqrt"); else this->value.data.dbl = sqrt( dval ); break; case ceil_fct: this->value.data.dbl = ceil( pVals[0].data.dbl ); break; case floor_fct: this->value.data.dbl = floor( pVals[0].data.dbl ); break; case round_fct: this->value.data.dbl = floor( pVals[0].data.dbl + 0.5 ); break; /* Two-argument Trig Functions */ case atan2_fct: this->value.data.dbl = atan2( pVals[0].data.dbl, pVals[1].data.dbl ); break; /* Four-argument ANGSEP function */ case angsep_fct: this->value.data.dbl = angsep_calc(pVals[0].data.dbl, pVals[1].data.dbl, pVals[2].data.dbl, pVals[3].data.dbl); /* Min/Max functions taking 1 or 2 arguments */ case min1_fct: /* No constant vectors! */ if( this->type == DOUBLE ) this->value.data.dbl = pVals[0].data.dbl; else if( this->type == LONG ) this->value.data.lng = pVals[0].data.lng; else if( this->type == BITSTR ) strcpy(this->value.data.str, pVals[0].data.str); break; case min2_fct: if( this->type == DOUBLE ) this->value.data.dbl = minvalue( pVals[0].data.dbl, pVals[1].data.dbl ); else if( this->type == LONG ) this->value.data.lng = minvalue( pVals[0].data.lng, pVals[1].data.lng ); break; case max1_fct: /* No constant vectors! */ if( this->type == DOUBLE ) this->value.data.dbl = pVals[0].data.dbl; else if( this->type == LONG ) this->value.data.lng = pVals[0].data.lng; else if( this->type == BITSTR ) strcpy(this->value.data.str, pVals[0].data.str); break; case max2_fct: if( this->type == DOUBLE ) this->value.data.dbl = maxvalue( pVals[0].data.dbl, pVals[1].data.dbl ); else if( this->type == LONG ) this->value.data.lng = maxvalue( pVals[0].data.lng, pVals[1].data.lng ); break; /* Boolean SAO region Functions... scalar or vector dbls */ case near_fct: this->value.data.log = bnear( pVals[0].data.dbl, pVals[1].data.dbl, pVals[2].data.dbl ); break; case circle_fct: this->value.data.log = circle( pVals[0].data.dbl, pVals[1].data.dbl, pVals[2].data.dbl, pVals[3].data.dbl, pVals[4].data.dbl ); break; case box_fct: this->value.data.log = saobox( pVals[0].data.dbl, pVals[1].data.dbl, pVals[2].data.dbl, pVals[3].data.dbl, pVals[4].data.dbl, pVals[5].data.dbl, pVals[6].data.dbl ); break; case elps_fct: this->value.data.log = ellipse( pVals[0].data.dbl, pVals[1].data.dbl, pVals[2].data.dbl, pVals[3].data.dbl, pVals[4].data.dbl, pVals[5].data.dbl, pVals[6].data.dbl ); break; /* C Conditional expression: bool ? expr : expr */ case ifthenelse_fct: switch( this->type ) { case BOOLEAN: this->value.data.log = ( pVals[2].data.log ? pVals[0].data.log : pVals[1].data.log ); break; case LONG: this->value.data.lng = ( pVals[2].data.log ? pVals[0].data.lng : pVals[1].data.lng ); break; case DOUBLE: this->value.data.dbl = ( pVals[2].data.log ? pVals[0].data.dbl : pVals[1].data.dbl ); break; case STRING: strcpy(this->value.data.str, ( pVals[2].data.log ? pVals[0].data.str : pVals[1].data.str ) ); break; } break; /* String functions */ case strmid_fct: cstrmid(this->value.data.str, this->value.nelem, pVals[0].data.str, pVals[0].nelem, pVals[1].data.lng); break; case strpos_fct: { char *res = strstr(pVals[0].data.str, pVals[1].data.str); if (res == NULL) { this->value.data.lng = 0; } else { this->value.data.lng = (res - pVals[0].data.str) + 1; } break; } } this->operation = CONST_OP; } else { Allocate_Ptrs( this ); row = gParse.nRows; elem = row * this->value.nelem; if( !gParse.status ) { switch( this->operation ) { /* Special functions with no arguments */ case row_fct: while( row-- ) { this->value.data.lngptr[row] = gParse.firstRow + row; this->value.undef[row] = 0; } break; case null_fct: if( this->type==LONG ) { while( row-- ) { this->value.data.lngptr[row] = 0; this->value.undef[row] = 1; } } else if( this->type==STRING ) { while( row-- ) { this->value.data.strptr[row][0] = '\0'; this->value.undef[row] = 1; } } break; case rnd_fct: while( elem-- ) { this->value.data.dblptr[elem] = simplerng_getuniform(); this->value.undef[elem] = 0; } break; case gasrnd_fct: while( elem-- ) { this->value.data.dblptr[elem] = simplerng_getnorm(); this->value.undef[elem] = 0; } break; case poirnd_fct: if( theParams[0]->type==DOUBLE ) { if (theParams[0]->operation == CONST_OP) { while( elem-- ) { this->value.undef[elem] = (pVals[0].data.dbl < 0); if (! this->value.undef[elem]) { this->value.data.lngptr[elem] = simplerng_getpoisson(pVals[0].data.dbl); } } } else { while( elem-- ) { this->value.undef[elem] = theParams[0]->value.undef[elem]; if (theParams[0]->value.data.dblptr[elem] < 0) this->value.undef[elem] = 1; if (! this->value.undef[elem]) { this->value.data.lngptr[elem] = simplerng_getpoisson(theParams[0]->value.data.dblptr[elem]); } } /* while */ } /* ! CONST_OP */ } else { /* LONG */ if (theParams[0]->operation == CONST_OP) { while( elem-- ) { this->value.undef[elem] = (pVals[0].data.lng < 0); if (! this->value.undef[elem]) { this->value.data.lngptr[elem] = simplerng_getpoisson(pVals[0].data.lng); } } } else { while( elem-- ) { this->value.undef[elem] = theParams[0]->value.undef[elem]; if (theParams[0]->value.data.lngptr[elem] < 0) this->value.undef[elem] = 1; if (! this->value.undef[elem]) { this->value.data.lngptr[elem] = simplerng_getpoisson(theParams[0]->value.data.lngptr[elem]); } } /* while */ } /* ! CONST_OP */ } /* END LONG */ break; /* Non-Trig single-argument functions */ case sum_fct: elem = row * theParams[0]->value.nelem; if( theParams[0]->type==BOOLEAN ) { while( row-- ) { this->value.data.lngptr[row] = 0; /* Default is UNDEF until a defined value is found */ this->value.undef[row] = 1; nelem = theParams[0]->value.nelem; while( nelem-- ) { elem--; if ( ! theParams[0]->value.undef[elem] ) { this->value.data.lngptr[row] += ( theParams[0]->value.data.logptr[elem] ? 1 : 0 ); this->value.undef[row] = 0; } } } } else if( theParams[0]->type==LONG ) { while( row-- ) { this->value.data.lngptr[row] = 0; /* Default is UNDEF until a defined value is found */ this->value.undef[row] = 1; nelem = theParams[0]->value.nelem; while( nelem-- ) { elem--; if ( ! theParams[0]->value.undef[elem] ) { this->value.data.lngptr[row] += theParams[0]->value.data.lngptr[elem]; this->value.undef[row] = 0; } } } } else if( theParams[0]->type==DOUBLE ){ while( row-- ) { this->value.data.dblptr[row] = 0.0; /* Default is UNDEF until a defined value is found */ this->value.undef[row] = 1; nelem = theParams[0]->value.nelem; while( nelem-- ) { elem--; if ( ! theParams[0]->value.undef[elem] ) { this->value.data.dblptr[row] += theParams[0]->value.data.dblptr[elem]; this->value.undef[row] = 0; } } } } else { /* BITSTR */ nelem = theParams[0]->value.nelem; while( row-- ) { char *sptr1 = theParams[0]->value.data.strptr[row]; this->value.data.lngptr[row] = 0; this->value.undef[row] = 0; while (*sptr1) { if (*sptr1 == '1') this->value.data.lngptr[row] ++; sptr1++; } } } break; case average_fct: elem = row * theParams[0]->value.nelem; if( theParams[0]->type==LONG ) { while( row-- ) { int count = 0; this->value.data.dblptr[row] = 0; nelem = theParams[0]->value.nelem; while( nelem-- ) { elem--; if (theParams[0]->value.undef[elem] == 0) { this->value.data.dblptr[row] += theParams[0]->value.data.lngptr[elem]; count ++; } } if (count == 0) { this->value.undef[row] = 1; } else { this->value.undef[row] = 0; this->value.data.dblptr[row] /= count; } } } else if( theParams[0]->type==DOUBLE ){ while( row-- ) { int count = 0; this->value.data.dblptr[row] = 0; nelem = theParams[0]->value.nelem; while( nelem-- ) { elem--; if (theParams[0]->value.undef[elem] == 0) { this->value.data.dblptr[row] += theParams[0]->value.data.dblptr[elem]; count ++; } } if (count == 0) { this->value.undef[row] = 1; } else { this->value.undef[row] = 0; this->value.data.dblptr[row] /= count; } } } break; case stddev_fct: elem = row * theParams[0]->value.nelem; if( theParams[0]->type==LONG ) { /* Compute the mean value */ while( row-- ) { int count = 0; double sum = 0, sum2 = 0; nelem = theParams[0]->value.nelem; while( nelem-- ) { elem--; if (theParams[0]->value.undef[elem] == 0) { sum += theParams[0]->value.data.lngptr[elem]; count ++; } } if (count > 1) { sum /= count; /* Compute the sum of squared deviations */ nelem = theParams[0]->value.nelem; elem += nelem; /* Reset elem for second pass */ while( nelem-- ) { elem--; if (theParams[0]->value.undef[elem] == 0) { double dx = (theParams[0]->value.data.lngptr[elem] - sum); sum2 += (dx*dx); } } sum2 /= (double)count-1; this->value.undef[row] = 0; this->value.data.dblptr[row] = sqrt(sum2); } else { this->value.undef[row] = 0; /* STDDEV => 0 */ this->value.data.dblptr[row] = 0; } } } else if( theParams[0]->type==DOUBLE ){ /* Compute the mean value */ while( row-- ) { int count = 0; double sum = 0, sum2 = 0; nelem = theParams[0]->value.nelem; while( nelem-- ) { elem--; if (theParams[0]->value.undef[elem] == 0) { sum += theParams[0]->value.data.dblptr[elem]; count ++; } } if (count > 1) { sum /= count; /* Compute the sum of squared deviations */ nelem = theParams[0]->value.nelem; elem += nelem; /* Reset elem for second pass */ while( nelem-- ) { elem--; if (theParams[0]->value.undef[elem] == 0) { double dx = (theParams[0]->value.data.dblptr[elem] - sum); sum2 += (dx*dx); } } sum2 /= (double)count-1; this->value.undef[row] = 0; this->value.data.dblptr[row] = sqrt(sum2); } else { this->value.undef[row] = 0; /* STDDEV => 0 */ this->value.data.dblptr[row] = 0; } } } break; case median_fct: elem = row * theParams[0]->value.nelem; nelem = theParams[0]->value.nelem; if( theParams[0]->type==LONG ) { long *dptr = theParams[0]->value.data.lngptr; char *uptr = theParams[0]->value.undef; long *mptr = (long *) malloc(sizeof(long)*nelem); int irow; /* Allocate temporary storage for this row, since the quickselect function will scramble the contents */ if (mptr == 0) { fferror("Could not allocate temporary memory in median function"); free( this->value.data.ptr ); break; } for (irow=0; irow 0) { this->value.undef[irow] = 0; this->value.data.lngptr[irow] = qselect_median_lng(mptr, nelem1); } else { this->value.undef[irow] = 1; this->value.data.lngptr[irow] = 0; } } free(mptr); } else { double *dptr = theParams[0]->value.data.dblptr; char *uptr = theParams[0]->value.undef; double *mptr = (double *) malloc(sizeof(double)*nelem); int irow; /* Allocate temporary storage for this row, since the quickselect function will scramble the contents */ if (mptr == 0) { fferror("Could not allocate temporary memory in median function"); free( this->value.data.ptr ); break; } for (irow=0; irow 0) { this->value.undef[irow] = 0; this->value.data.dblptr[irow] = qselect_median_dbl(mptr, nelem1); } else { this->value.undef[irow] = 1; this->value.data.dblptr[irow] = 0; } } free(mptr); } break; case abs_fct: if( theParams[0]->type==DOUBLE ) while( elem-- ) { dval = theParams[0]->value.data.dblptr[elem]; this->value.data.dblptr[elem] = (dval>0.0 ? dval : -dval); this->value.undef[elem] = theParams[0]->value.undef[elem]; } else while( elem-- ) { ival = theParams[0]->value.data.lngptr[elem]; this->value.data.lngptr[elem] = (ival> 0 ? ival : -ival); this->value.undef[elem] = theParams[0]->value.undef[elem]; } break; /* Special Null-Handling Functions */ case nonnull_fct: nelem = theParams[0]->value.nelem; if ( theParams[0]->type==STRING ) nelem = 1; elem = row * nelem; while( row-- ) { int nelem1 = nelem; this->value.undef[row] = 0; /* Initialize to 0 (defined) */ this->value.data.lngptr[row] = 0; while( nelem1-- ) { elem --; if ( theParams[0]->value.undef[elem] == 0 ) this->value.data.lngptr[row] ++; } } break; case isnull_fct: if( theParams[0]->type==STRING ) elem = row; while( elem-- ) { this->value.data.logptr[elem] = theParams[0]->value.undef[elem]; this->value.undef[elem] = 0; } break; case defnull_fct: switch( this->type ) { case BOOLEAN: while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; i=2; while( i-- ) if( vector[i]>1 ) { pNull[i] = theParams[i]->value.undef[elem]; pVals[i].data.log = theParams[i]->value.data.logptr[elem]; } else if( vector[i] ) { pNull[i] = theParams[i]->value.undef[row]; pVals[i].data.log = theParams[i]->value.data.logptr[row]; } if( pNull[0] ) { this->value.undef[elem] = pNull[1]; this->value.data.logptr[elem] = pVals[1].data.log; } else { this->value.undef[elem] = 0; this->value.data.logptr[elem] = pVals[0].data.log; } } } break; case LONG: while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; i=2; while( i-- ) if( vector[i]>1 ) { pNull[i] = theParams[i]->value.undef[elem]; pVals[i].data.lng = theParams[i]->value.data.lngptr[elem]; } else if( vector[i] ) { pNull[i] = theParams[i]->value.undef[row]; pVals[i].data.lng = theParams[i]->value.data.lngptr[row]; } if( pNull[0] ) { this->value.undef[elem] = pNull[1]; this->value.data.lngptr[elem] = pVals[1].data.lng; } else { this->value.undef[elem] = 0; this->value.data.lngptr[elem] = pVals[0].data.lng; } } } break; case DOUBLE: while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; i=2; while( i-- ) if( vector[i]>1 ) { pNull[i] = theParams[i]->value.undef[elem]; pVals[i].data.dbl = theParams[i]->value.data.dblptr[elem]; } else if( vector[i] ) { pNull[i] = theParams[i]->value.undef[row]; pVals[i].data.dbl = theParams[i]->value.data.dblptr[row]; } if( pNull[0] ) { this->value.undef[elem] = pNull[1]; this->value.data.dblptr[elem] = pVals[1].data.dbl; } else { this->value.undef[elem] = 0; this->value.data.dblptr[elem] = pVals[0].data.dbl; } } } break; case STRING: while( row-- ) { i=2; while( i-- ) if( vector[i] ) { pNull[i] = theParams[i]->value.undef[row]; strcpy(pVals[i].data.str, theParams[i]->value.data.strptr[row]); } if( pNull[0] ) { this->value.undef[row] = pNull[1]; strcpy(this->value.data.strptr[row],pVals[1].data.str); } else { this->value.undef[elem] = 0; strcpy(this->value.data.strptr[row],pVals[0].data.str); } } } break; /* Math functions with 1 double argument */ case sin_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { this->value.data.dblptr[elem] = sin( theParams[0]->value.data.dblptr[elem] ); } break; case cos_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { this->value.data.dblptr[elem] = cos( theParams[0]->value.data.dblptr[elem] ); } break; case tan_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { this->value.data.dblptr[elem] = tan( theParams[0]->value.data.dblptr[elem] ); } break; case asin_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { dval = theParams[0]->value.data.dblptr[elem]; if( dval<-1.0 || dval>1.0 ) { this->value.data.dblptr[elem] = 0.0; this->value.undef[elem] = 1; } else this->value.data.dblptr[elem] = asin( dval ); } break; case acos_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { dval = theParams[0]->value.data.dblptr[elem]; if( dval<-1.0 || dval>1.0 ) { this->value.data.dblptr[elem] = 0.0; this->value.undef[elem] = 1; } else this->value.data.dblptr[elem] = acos( dval ); } break; case atan_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { dval = theParams[0]->value.data.dblptr[elem]; this->value.data.dblptr[elem] = atan( dval ); } break; case sinh_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { this->value.data.dblptr[elem] = sinh( theParams[0]->value.data.dblptr[elem] ); } break; case cosh_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { this->value.data.dblptr[elem] = cosh( theParams[0]->value.data.dblptr[elem] ); } break; case tanh_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { this->value.data.dblptr[elem] = tanh( theParams[0]->value.data.dblptr[elem] ); } break; case exp_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { dval = theParams[0]->value.data.dblptr[elem]; this->value.data.dblptr[elem] = exp( dval ); } break; case log_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { dval = theParams[0]->value.data.dblptr[elem]; if( dval<=0.0 ) { this->value.data.dblptr[elem] = 0.0; this->value.undef[elem] = 1; } else this->value.data.dblptr[elem] = log( dval ); } break; case log10_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { dval = theParams[0]->value.data.dblptr[elem]; if( dval<=0.0 ) { this->value.data.dblptr[elem] = 0.0; this->value.undef[elem] = 1; } else this->value.data.dblptr[elem] = log10( dval ); } break; case sqrt_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { dval = theParams[0]->value.data.dblptr[elem]; if( dval<0.0 ) { this->value.data.dblptr[elem] = 0.0; this->value.undef[elem] = 1; } else this->value.data.dblptr[elem] = sqrt( dval ); } break; case ceil_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { this->value.data.dblptr[elem] = ceil( theParams[0]->value.data.dblptr[elem] ); } break; case floor_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { this->value.data.dblptr[elem] = floor( theParams[0]->value.data.dblptr[elem] ); } break; case round_fct: while( elem-- ) if( !(this->value.undef[elem] = theParams[0]->value.undef[elem]) ) { this->value.data.dblptr[elem] = floor( theParams[0]->value.data.dblptr[elem] + 0.5); } break; /* Two-argument Trig Functions */ case atan2_fct: while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; i=2; while( i-- ) if( vector[i]>1 ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[elem]; pNull[i] = theParams[i]->value.undef[elem]; } else if( vector[i] ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[row]; pNull[i] = theParams[i]->value.undef[row]; } if( !(this->value.undef[elem] = (pNull[0] || pNull[1]) ) ) this->value.data.dblptr[elem] = atan2( pVals[0].data.dbl, pVals[1].data.dbl ); } } break; /* Four-argument ANGSEP Function */ case angsep_fct: while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; i=4; while( i-- ) if( vector[i]>1 ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[elem]; pNull[i] = theParams[i]->value.undef[elem]; } else if( vector[i] ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[row]; pNull[i] = theParams[i]->value.undef[row]; } if( !(this->value.undef[elem] = (pNull[0] || pNull[1] || pNull[2] || pNull[3]) ) ) this->value.data.dblptr[elem] = angsep_calc(pVals[0].data.dbl, pVals[1].data.dbl, pVals[2].data.dbl, pVals[3].data.dbl); } } break; /* Min/Max functions taking 1 or 2 arguments */ case min1_fct: elem = row * theParams[0]->value.nelem; if( this->type==LONG ) { long minVal=0; while( row-- ) { valInit = 1; this->value.undef[row] = 1; nelem = theParams[0]->value.nelem; while( nelem-- ) { elem--; if ( !theParams[0]->value.undef[elem] ) { if ( valInit ) { valInit = 0; minVal = theParams[0]->value.data.lngptr[elem]; } else { minVal = minvalue( minVal, theParams[0]->value.data.lngptr[elem] ); } this->value.undef[row] = 0; } } this->value.data.lngptr[row] = minVal; } } else if( this->type==DOUBLE ) { double minVal=0.0; while( row-- ) { valInit = 1; this->value.undef[row] = 1; nelem = theParams[0]->value.nelem; while( nelem-- ) { elem--; if ( !theParams[0]->value.undef[elem] ) { if ( valInit ) { valInit = 0; minVal = theParams[0]->value.data.dblptr[elem]; } else { minVal = minvalue( minVal, theParams[0]->value.data.dblptr[elem] ); } this->value.undef[row] = 0; } } this->value.data.dblptr[row] = minVal; } } else if( this->type==BITSTR ) { char minVal; while( row-- ) { char *sptr1 = theParams[0]->value.data.strptr[row]; minVal = '1'; while (*sptr1) { if (*sptr1 == '0') minVal = '0'; sptr1++; } this->value.data.strptr[row][0] = minVal; this->value.data.strptr[row][1] = 0; /* Null terminate */ } } break; case min2_fct: if( this->type==LONG ) { while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; i=2; while( i-- ) if( vector[i]>1 ) { pVals[i].data.lng = theParams[i]->value.data.lngptr[elem]; pNull[i] = theParams[i]->value.undef[elem]; } else if( vector[i] ) { pVals[i].data.lng = theParams[i]->value.data.lngptr[row]; pNull[i] = theParams[i]->value.undef[row]; } if( pNull[0] && pNull[1] ) { this->value.undef[elem] = 1; this->value.data.lngptr[elem] = 0; } else if (pNull[0]) { this->value.undef[elem] = 0; this->value.data.lngptr[elem] = pVals[1].data.lng; } else if (pNull[1]) { this->value.undef[elem] = 0; this->value.data.lngptr[elem] = pVals[0].data.lng; } else { this->value.undef[elem] = 0; this->value.data.lngptr[elem] = minvalue( pVals[0].data.lng, pVals[1].data.lng ); } } } } else if( this->type==DOUBLE ) { while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; i=2; while( i-- ) if( vector[i]>1 ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[elem]; pNull[i] = theParams[i]->value.undef[elem]; } else if( vector[i] ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[row]; pNull[i] = theParams[i]->value.undef[row]; } if( pNull[0] && pNull[1] ) { this->value.undef[elem] = 1; this->value.data.dblptr[elem] = 0; } else if (pNull[0]) { this->value.undef[elem] = 0; this->value.data.dblptr[elem] = pVals[1].data.dbl; } else if (pNull[1]) { this->value.undef[elem] = 0; this->value.data.dblptr[elem] = pVals[0].data.dbl; } else { this->value.undef[elem] = 0; this->value.data.dblptr[elem] = minvalue( pVals[0].data.dbl, pVals[1].data.dbl ); } } } } break; case max1_fct: elem = row * theParams[0]->value.nelem; if( this->type==LONG ) { long maxVal=0; while( row-- ) { valInit = 1; this->value.undef[row] = 1; nelem = theParams[0]->value.nelem; while( nelem-- ) { elem--; if ( !theParams[0]->value.undef[elem] ) { if ( valInit ) { valInit = 0; maxVal = theParams[0]->value.data.lngptr[elem]; } else { maxVal = maxvalue( maxVal, theParams[0]->value.data.lngptr[elem] ); } this->value.undef[row] = 0; } } this->value.data.lngptr[row] = maxVal; } } else if( this->type==DOUBLE ) { double maxVal=0.0; while( row-- ) { valInit = 1; this->value.undef[row] = 1; nelem = theParams[0]->value.nelem; while( nelem-- ) { elem--; if ( !theParams[0]->value.undef[elem] ) { if ( valInit ) { valInit = 0; maxVal = theParams[0]->value.data.dblptr[elem]; } else { maxVal = maxvalue( maxVal, theParams[0]->value.data.dblptr[elem] ); } this->value.undef[row] = 0; } } this->value.data.dblptr[row] = maxVal; } } else if( this->type==BITSTR ) { char maxVal; while( row-- ) { char *sptr1 = theParams[0]->value.data.strptr[row]; maxVal = '0'; while (*sptr1) { if (*sptr1 == '1') maxVal = '1'; sptr1++; } this->value.data.strptr[row][0] = maxVal; this->value.data.strptr[row][1] = 0; /* Null terminate */ } } break; case max2_fct: if( this->type==LONG ) { while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; i=2; while( i-- ) if( vector[i]>1 ) { pVals[i].data.lng = theParams[i]->value.data.lngptr[elem]; pNull[i] = theParams[i]->value.undef[elem]; } else if( vector[i] ) { pVals[i].data.lng = theParams[i]->value.data.lngptr[row]; pNull[i] = theParams[i]->value.undef[row]; } if( pNull[0] && pNull[1] ) { this->value.undef[elem] = 1; this->value.data.lngptr[elem] = 0; } else if (pNull[0]) { this->value.undef[elem] = 0; this->value.data.lngptr[elem] = pVals[1].data.lng; } else if (pNull[1]) { this->value.undef[elem] = 0; this->value.data.lngptr[elem] = pVals[0].data.lng; } else { this->value.undef[elem] = 0; this->value.data.lngptr[elem] = maxvalue( pVals[0].data.lng, pVals[1].data.lng ); } } } } else if( this->type==DOUBLE ) { while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; i=2; while( i-- ) if( vector[i]>1 ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[elem]; pNull[i] = theParams[i]->value.undef[elem]; } else if( vector[i] ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[row]; pNull[i] = theParams[i]->value.undef[row]; } if( pNull[0] && pNull[1] ) { this->value.undef[elem] = 1; this->value.data.dblptr[elem] = 0; } else if (pNull[0]) { this->value.undef[elem] = 0; this->value.data.dblptr[elem] = pVals[1].data.dbl; } else if (pNull[1]) { this->value.undef[elem] = 0; this->value.data.dblptr[elem] = pVals[0].data.dbl; } else { this->value.undef[elem] = 0; this->value.data.dblptr[elem] = maxvalue( pVals[0].data.dbl, pVals[1].data.dbl ); } } } } break; /* Boolean SAO region Functions... scalar or vector dbls */ case near_fct: while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; i=3; while( i-- ) if( vector[i]>1 ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[elem]; pNull[i] = theParams[i]->value.undef[elem]; } else if( vector[i] ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[row]; pNull[i] = theParams[i]->value.undef[row]; } if( !(this->value.undef[elem] = (pNull[0] || pNull[1] || pNull[2]) ) ) this->value.data.logptr[elem] = bnear( pVals[0].data.dbl, pVals[1].data.dbl, pVals[2].data.dbl ); } } break; case circle_fct: while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; i=5; while( i-- ) if( vector[i]>1 ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[elem]; pNull[i] = theParams[i]->value.undef[elem]; } else if( vector[i] ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[row]; pNull[i] = theParams[i]->value.undef[row]; } if( !(this->value.undef[elem] = (pNull[0] || pNull[1] || pNull[2] || pNull[3] || pNull[4]) ) ) this->value.data.logptr[elem] = circle( pVals[0].data.dbl, pVals[1].data.dbl, pVals[2].data.dbl, pVals[3].data.dbl, pVals[4].data.dbl ); } } break; case box_fct: while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; i=7; while( i-- ) if( vector[i]>1 ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[elem]; pNull[i] = theParams[i]->value.undef[elem]; } else if( vector[i] ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[row]; pNull[i] = theParams[i]->value.undef[row]; } if( !(this->value.undef[elem] = (pNull[0] || pNull[1] || pNull[2] || pNull[3] || pNull[4] || pNull[5] || pNull[6] ) ) ) this->value.data.logptr[elem] = saobox( pVals[0].data.dbl, pVals[1].data.dbl, pVals[2].data.dbl, pVals[3].data.dbl, pVals[4].data.dbl, pVals[5].data.dbl, pVals[6].data.dbl ); } } break; case elps_fct: while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; i=7; while( i-- ) if( vector[i]>1 ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[elem]; pNull[i] = theParams[i]->value.undef[elem]; } else if( vector[i] ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[row]; pNull[i] = theParams[i]->value.undef[row]; } if( !(this->value.undef[elem] = (pNull[0] || pNull[1] || pNull[2] || pNull[3] || pNull[4] || pNull[5] || pNull[6] ) ) ) this->value.data.logptr[elem] = ellipse( pVals[0].data.dbl, pVals[1].data.dbl, pVals[2].data.dbl, pVals[3].data.dbl, pVals[4].data.dbl, pVals[5].data.dbl, pVals[6].data.dbl ); } } break; /* C Conditional expression: bool ? expr : expr */ case ifthenelse_fct: switch( this->type ) { case BOOLEAN: while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; if( vector[2]>1 ) { pVals[2].data.log = theParams[2]->value.data.logptr[elem]; pNull[2] = theParams[2]->value.undef[elem]; } else if( vector[2] ) { pVals[2].data.log = theParams[2]->value.data.logptr[row]; pNull[2] = theParams[2]->value.undef[row]; } i=2; while( i-- ) if( vector[i]>1 ) { pVals[i].data.log = theParams[i]->value.data.logptr[elem]; pNull[i] = theParams[i]->value.undef[elem]; } else if( vector[i] ) { pVals[i].data.log = theParams[i]->value.data.logptr[row]; pNull[i] = theParams[i]->value.undef[row]; } if( !(this->value.undef[elem] = pNull[2]) ) { if( pVals[2].data.log ) { this->value.data.logptr[elem] = pVals[0].data.log; this->value.undef[elem] = pNull[0]; } else { this->value.data.logptr[elem] = pVals[1].data.log; this->value.undef[elem] = pNull[1]; } } } } break; case LONG: while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; if( vector[2]>1 ) { pVals[2].data.log = theParams[2]->value.data.logptr[elem]; pNull[2] = theParams[2]->value.undef[elem]; } else if( vector[2] ) { pVals[2].data.log = theParams[2]->value.data.logptr[row]; pNull[2] = theParams[2]->value.undef[row]; } i=2; while( i-- ) if( vector[i]>1 ) { pVals[i].data.lng = theParams[i]->value.data.lngptr[elem]; pNull[i] = theParams[i]->value.undef[elem]; } else if( vector[i] ) { pVals[i].data.lng = theParams[i]->value.data.lngptr[row]; pNull[i] = theParams[i]->value.undef[row]; } if( !(this->value.undef[elem] = pNull[2]) ) { if( pVals[2].data.log ) { this->value.data.lngptr[elem] = pVals[0].data.lng; this->value.undef[elem] = pNull[0]; } else { this->value.data.lngptr[elem] = pVals[1].data.lng; this->value.undef[elem] = pNull[1]; } } } } break; case DOUBLE: while( row-- ) { nelem = this->value.nelem; while( nelem-- ) { elem--; if( vector[2]>1 ) { pVals[2].data.log = theParams[2]->value.data.logptr[elem]; pNull[2] = theParams[2]->value.undef[elem]; } else if( vector[2] ) { pVals[2].data.log = theParams[2]->value.data.logptr[row]; pNull[2] = theParams[2]->value.undef[row]; } i=2; while( i-- ) if( vector[i]>1 ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[elem]; pNull[i] = theParams[i]->value.undef[elem]; } else if( vector[i] ) { pVals[i].data.dbl = theParams[i]->value.data.dblptr[row]; pNull[i] = theParams[i]->value.undef[row]; } if( !(this->value.undef[elem] = pNull[2]) ) { if( pVals[2].data.log ) { this->value.data.dblptr[elem] = pVals[0].data.dbl; this->value.undef[elem] = pNull[0]; } else { this->value.data.dblptr[elem] = pVals[1].data.dbl; this->value.undef[elem] = pNull[1]; } } } } break; case STRING: while( row-- ) { if( vector[2] ) { pVals[2].data.log = theParams[2]->value.data.logptr[row]; pNull[2] = theParams[2]->value.undef[row]; } i=2; while( i-- ) if( vector[i] ) { strcpy( pVals[i].data.str, theParams[i]->value.data.strptr[row] ); pNull[i] = theParams[i]->value.undef[row]; } if( !(this->value.undef[row] = pNull[2]) ) { if( pVals[2].data.log ) { strcpy( this->value.data.strptr[row], pVals[0].data.str ); this->value.undef[row] = pNull[0]; } else { strcpy( this->value.data.strptr[row], pVals[1].data.str ); this->value.undef[row] = pNull[1]; } } else { this->value.data.strptr[row][0] = '\0'; } } break; } break; /* String functions */ case strmid_fct: { int strconst = theParams[0]->operation == CONST_OP; int posconst = theParams[1]->operation == CONST_OP; int lenconst = theParams[2]->operation == CONST_OP; int dest_len = this->value.nelem; int src_len = theParams[0]->value.nelem; while (row--) { int pos; int len; char *str; int undef = 0; if (posconst) { pos = theParams[1]->value.data.lng; } else { pos = theParams[1]->value.data.lngptr[row]; if (theParams[1]->value.undef[row]) undef = 1; } if (strconst) { str = theParams[0]->value.data.str; if (src_len == 0) src_len = strlen(str); } else { str = theParams[0]->value.data.strptr[row]; if (theParams[0]->value.undef[row]) undef = 1; } if (lenconst) { len = dest_len; } else { len = theParams[2]->value.data.lngptr[row]; if (theParams[2]->value.undef[row]) undef = 1; } this->value.data.strptr[row][0] = '\0'; if (pos == 0) undef = 1; if (! undef ) { if (cstrmid(this->value.data.strptr[row], len, str, src_len, pos) < 0) break; } this->value.undef[row] = undef; } } break; /* String functions */ case strpos_fct: { int const1 = theParams[0]->operation == CONST_OP; int const2 = theParams[1]->operation == CONST_OP; while (row--) { char *str1, *str2; int undef = 0; if (const1) { str1 = theParams[0]->value.data.str; } else { str1 = theParams[0]->value.data.strptr[row]; if (theParams[0]->value.undef[row]) undef = 1; } if (const2) { str2 = theParams[1]->value.data.str; } else { str2 = theParams[1]->value.data.strptr[row]; if (theParams[1]->value.undef[row]) undef = 1; } this->value.data.lngptr[row] = 0; if (! undef ) { char *res = strstr(str1, str2); if (res == NULL) { undef = 1; this->value.data.lngptr[row] = 0; } else { this->value.data.lngptr[row] = (res - str1) + 1; } } this->value.undef[row] = undef; } } break; } /* End switch(this->operation) */ } /* End if (!gParse.status) */ } /* End non-constant operations */ i = this->nSubNodes; while( i-- ) { if( theParams[i]->operation>0 ) { /* Currently only numeric params allowed */ free( theParams[i]->value.data.ptr ); } } } static void Do_Deref( Node *this ) { Node *theVar, *theDims[MAXDIMS]; int isConst[MAXDIMS], allConst; long dimVals[MAXDIMS]; int i, nDims; long row, elem, dsize; theVar = gParse.Nodes + this->SubNodes[0]; i = nDims = this->nSubNodes-1; allConst = 1; while( i-- ) { theDims[i] = gParse.Nodes + this->SubNodes[i+1]; isConst[i] = ( theDims[i]->operation==CONST_OP ); if( isConst[i] ) dimVals[i] = theDims[i]->value.data.lng; else allConst = 0; } if( this->type==DOUBLE ) { dsize = sizeof( double ); } else if( this->type==LONG ) { dsize = sizeof( long ); } else if( this->type==BOOLEAN ) { dsize = sizeof( char ); } else dsize = 0; Allocate_Ptrs( this ); if( !gParse.status ) { if( allConst && theVar->value.naxis==nDims ) { /* Dereference completely using constant indices */ elem = 0; i = nDims; while( i-- ) { if( dimVals[i]<1 || dimVals[i]>theVar->value.naxes[i] ) break; elem = theVar->value.naxes[i]*elem + dimVals[i]-1; } if( i<0 ) { for( row=0; rowtype==STRING ) this->value.undef[row] = theVar->value.undef[row]; else if( this->type==BITSTR ) this->value.undef; /* Dummy - BITSTRs do not have undefs */ else this->value.undef[row] = theVar->value.undef[elem]; if( this->type==DOUBLE ) this->value.data.dblptr[row] = theVar->value.data.dblptr[elem]; else if( this->type==LONG ) this->value.data.lngptr[row] = theVar->value.data.lngptr[elem]; else if( this->type==BOOLEAN ) this->value.data.logptr[row] = theVar->value.data.logptr[elem]; else { /* XXX Note, the below expression uses knowledge of the layout of the string format, namely (nelem+1) characters per string, followed by (nelem+1) "undef" values. */ this->value.data.strptr[row][0] = theVar->value.data.strptr[0][elem+row]; this->value.data.strptr[row][1] = 0; /* Null terminate */ } elem += theVar->value.nelem; } } else { fferror("Index out of range"); free( this->value.data.ptr ); } } else if( allConst && nDims==1 ) { /* Reduce dimensions by 1, using a constant index */ if( dimVals[0] < 1 || dimVals[0] > theVar->value.naxes[ theVar->value.naxis-1 ] ) { fferror("Index out of range"); free( this->value.data.ptr ); } else if ( this->type == BITSTR || this->type == STRING ) { elem = this->value.nelem * (dimVals[0]-1); for( row=0; rowvalue.undef) this->value.undef[row] = theVar->value.undef[row]; memcpy( (char*)this->value.data.strptr[0] + row*sizeof(char)*(this->value.nelem+1), (char*)theVar->value.data.strptr[0] + elem*sizeof(char), this->value.nelem * sizeof(char) ); /* Null terminate */ this->value.data.strptr[row][this->value.nelem] = 0; elem += theVar->value.nelem+1; } } else { elem = this->value.nelem * (dimVals[0]-1); for( row=0; rowvalue.undef + row*this->value.nelem, theVar->value.undef + elem, this->value.nelem * sizeof(char) ); memcpy( (char*)this->value.data.ptr + row*dsize*this->value.nelem, (char*)theVar->value.data.ptr + elem*dsize, this->value.nelem * dsize ); elem += theVar->value.nelem; } } } else if( theVar->value.naxis==nDims ) { /* Dereference completely using an expression for the indices */ for( row=0; rowvalue.undef[row] ) { fferror("Null encountered as vector index"); free( this->value.data.ptr ); break; } else dimVals[i] = theDims[i]->value.data.lngptr[row]; } } if( gParse.status ) break; elem = 0; i = nDims; while( i-- ) { if( dimVals[i]<1 || dimVals[i]>theVar->value.naxes[i] ) break; elem = theVar->value.naxes[i]*elem + dimVals[i]-1; } if( i<0 ) { elem += row*theVar->value.nelem; if( this->type==STRING ) this->value.undef[row] = theVar->value.undef[row]; else if( this->type==BITSTR ) this->value.undef; /* Dummy - BITSTRs do not have undefs */ else this->value.undef[row] = theVar->value.undef[elem]; if( this->type==DOUBLE ) this->value.data.dblptr[row] = theVar->value.data.dblptr[elem]; else if( this->type==LONG ) this->value.data.lngptr[row] = theVar->value.data.lngptr[elem]; else if( this->type==BOOLEAN ) this->value.data.logptr[row] = theVar->value.data.logptr[elem]; else { /* XXX Note, the below expression uses knowledge of the layout of the string format, namely (nelem+1) characters per string, followed by (nelem+1) "undef" values. */ this->value.data.strptr[row][0] = theVar->value.data.strptr[0][elem+row]; this->value.data.strptr[row][1] = 0; /* Null terminate */ } } else { fferror("Index out of range"); free( this->value.data.ptr ); } } } else { /* Reduce dimensions by 1, using a nonconstant expression */ for( row=0; rowvalue.undef[row] ) { fferror("Null encountered as vector index"); free( this->value.data.ptr ); break; } else dimVals[0] = theDims[0]->value.data.lngptr[row]; if( dimVals[0] < 1 || dimVals[0] > theVar->value.naxes[ theVar->value.naxis-1 ] ) { fferror("Index out of range"); free( this->value.data.ptr ); } else if ( this->type == BITSTR || this->type == STRING ) { elem = this->value.nelem * (dimVals[0]-1); elem += row*(theVar->value.nelem+1); if (this->value.undef) this->value.undef[row] = theVar->value.undef[row]; memcpy( (char*)this->value.data.strptr[0] + row*sizeof(char)*(this->value.nelem+1), (char*)theVar->value.data.strptr[0] + elem*sizeof(char), this->value.nelem * sizeof(char) ); /* Null terminate */ this->value.data.strptr[row][this->value.nelem] = 0; } else { elem = this->value.nelem * (dimVals[0]-1); elem += row*theVar->value.nelem; memcpy( this->value.undef + row*this->value.nelem, theVar->value.undef + elem, this->value.nelem * sizeof(char) ); memcpy( (char*)this->value.data.ptr + row*dsize*this->value.nelem, (char*)theVar->value.data.ptr + elem*dsize, this->value.nelem * dsize ); } } } } if( theVar->operation>0 ) { if (theVar->type == STRING || theVar->type == BITSTR) free(theVar->value.data.strptr[0] ); else free( theVar->value.data.ptr ); } for( i=0; ioperation>0 ) { free( theDims[i]->value.data.ptr ); } } static void Do_GTI( Node *this ) { Node *theExpr, *theTimes; double *start, *stop, *times; long elem, nGTI, gti; int ordered; theTimes = gParse.Nodes + this->SubNodes[0]; theExpr = gParse.Nodes + this->SubNodes[1]; nGTI = theTimes->value.nelem; start = theTimes->value.data.dblptr; stop = theTimes->value.data.dblptr + nGTI; ordered = theTimes->type; if( theExpr->operation==CONST_OP ) { this->value.data.log = (Search_GTI( theExpr->value.data.dbl, nGTI, start, stop, ordered )>=0); this->operation = CONST_OP; } else { Allocate_Ptrs( this ); times = theExpr->value.data.dblptr; if( !gParse.status ) { elem = gParse.nRows * this->value.nelem; if( nGTI ) { gti = -1; while( elem-- ) { if( (this->value.undef[elem] = theExpr->value.undef[elem]) ) continue; /* Before searching entire GTI, check the GTI found last time */ if( gti<0 || times[elem]stop[gti] ) { gti = Search_GTI( times[elem], nGTI, start, stop, ordered ); } this->value.data.logptr[elem] = ( gti>=0 ); } } else while( elem-- ) { this->value.data.logptr[elem] = 0; this->value.undef[elem] = 0; } } } if( theExpr->operation>0 ) free( theExpr->value.data.ptr ); } static long Search_GTI( double evtTime, long nGTI, double *start, double *stop, int ordered ) { long gti, step; if( ordered && nGTI>15 ) { /* If time-ordered and lots of GTIs, */ /* use "FAST" Binary search algorithm */ if( evtTime>=start[0] && evtTime<=stop[nGTI-1] ) { gti = step = (nGTI >> 1); while(1) { if( step>1L ) step >>= 1; if( evtTime>stop[gti] ) { if( evtTime>=start[gti+1] ) gti += step; else { gti = -1L; break; } } else if( evtTime=start[gti] && evtTime<=stop[gti] ) break; } return( gti ); } static void Do_REG( Node *this ) { Node *theRegion, *theX, *theY; double Xval=0.0, Yval=0.0; char Xnull=0, Ynull=0; int Xvector, Yvector; long nelem, elem, rows; theRegion = gParse.Nodes + this->SubNodes[0]; theX = gParse.Nodes + this->SubNodes[1]; theY = gParse.Nodes + this->SubNodes[2]; Xvector = ( theX->operation!=CONST_OP ); if( Xvector ) Xvector = theX->value.nelem; else { Xval = theX->value.data.dbl; } Yvector = ( theY->operation!=CONST_OP ); if( Yvector ) Yvector = theY->value.nelem; else { Yval = theY->value.data.dbl; } if( !Xvector && !Yvector ) { this->value.data.log = ( fits_in_region( Xval, Yval, (SAORegion *)theRegion->value.data.ptr ) != 0 ); this->operation = CONST_OP; } else { Allocate_Ptrs( this ); if( !gParse.status ) { rows = gParse.nRows; nelem = this->value.nelem; elem = rows*nelem; while( rows-- ) { while( nelem-- ) { elem--; if( Xvector>1 ) { Xval = theX->value.data.dblptr[elem]; Xnull = theX->value.undef[elem]; } else if( Xvector ) { Xval = theX->value.data.dblptr[rows]; Xnull = theX->value.undef[rows]; } if( Yvector>1 ) { Yval = theY->value.data.dblptr[elem]; Ynull = theY->value.undef[elem]; } else if( Yvector ) { Yval = theY->value.data.dblptr[rows]; Ynull = theY->value.undef[rows]; } this->value.undef[elem] = ( Xnull || Ynull ); if( this->value.undef[elem] ) continue; this->value.data.logptr[elem] = ( fits_in_region( Xval, Yval, (SAORegion *)theRegion->value.data.ptr ) != 0 ); } nelem = this->value.nelem; } } } if( theX->operation>0 ) free( theX->value.data.ptr ); if( theY->operation>0 ) free( theY->value.data.ptr ); } static void Do_Vector( Node *this ) { Node *that; long row, elem, idx, jdx, offset=0; int node; Allocate_Ptrs( this ); if( !gParse.status ) { for( node=0; nodenSubNodes; node++ ) { that = gParse.Nodes + this->SubNodes[node]; if( that->operation == CONST_OP ) { idx = gParse.nRows*this->value.nelem + offset; while( (idx-=this->value.nelem)>=0 ) { this->value.undef[idx] = 0; switch( this->type ) { case BOOLEAN: this->value.data.logptr[idx] = that->value.data.log; break; case LONG: this->value.data.lngptr[idx] = that->value.data.lng; break; case DOUBLE: this->value.data.dblptr[idx] = that->value.data.dbl; break; } } } else { row = gParse.nRows; idx = row * that->value.nelem; while( row-- ) { elem = that->value.nelem; jdx = row*this->value.nelem + offset; while( elem-- ) { this->value.undef[jdx+elem] = that->value.undef[--idx]; switch( this->type ) { case BOOLEAN: this->value.data.logptr[jdx+elem] = that->value.data.logptr[idx]; break; case LONG: this->value.data.lngptr[jdx+elem] = that->value.data.lngptr[idx]; break; case DOUBLE: this->value.data.dblptr[jdx+elem] = that->value.data.dblptr[idx]; break; } } } } offset += that->value.nelem; } } for( node=0; node < this->nSubNodes; node++ ) if( OPER(this->SubNodes[node])>0 ) free( gParse.Nodes[this->SubNodes[node]].value.data.ptr ); } /*****************************************************************************/ /* Utility routines which perform the calculations on bits and SAO regions */ /*****************************************************************************/ static char bitlgte(char *bits1, int oper, char *bits2) { int val1, val2, nextbit; char result; int i, l1, l2, length, ldiff; char *stream=0; char chr1, chr2; l1 = strlen(bits1); l2 = strlen(bits2); length = (l1 > l2) ? l1 : l2; stream = (char *)malloc(sizeof(char)*(length+1)); if (l1 < l2) { ldiff = l2 - l1; i=0; while( ldiff-- ) stream[i++] = '0'; while( l1-- ) stream[i++] = *(bits1++); stream[i] = '\0'; bits1 = stream; } else if (l2 < l1) { ldiff = l1 - l2; i=0; while( ldiff-- ) stream[i++] = '0'; while( l2-- ) stream[i++] = *(bits2++); stream[i] = '\0'; bits2 = stream; } val1 = val2 = 0; nextbit = 1; while( length-- ) { chr1 = bits1[length]; chr2 = bits2[length]; if ((chr1 != 'x')&&(chr1 != 'X')&&(chr2 != 'x')&&(chr2 != 'X')) { if (chr1 == '1') val1 += nextbit; if (chr2 == '1') val2 += nextbit; nextbit *= 2; } } result = 0; switch (oper) { case LT: if (val1 < val2) result = 1; break; case LTE: if (val1 <= val2) result = 1; break; case GT: if (val1 > val2) result = 1; break; case GTE: if (val1 >= val2) result = 1; break; } free(stream); return (result); } static void bitand(char *result,char *bitstrm1,char *bitstrm2) { int i, l1, l2, ldiff, largestStream; char *stream=0; char chr1, chr2; l1 = strlen(bitstrm1); l2 = strlen(bitstrm2); largestStream = (l1 > l2) ? l1 : l2; stream = (char *)malloc(sizeof(char)*(largestStream+1)); if (l1 < l2) { ldiff = l2 - l1; i=0; while( ldiff-- ) stream[i++] = '0'; while( l1-- ) stream[i++] = *(bitstrm1++); stream[i] = '\0'; bitstrm1 = stream; } else if (l2 < l1) { ldiff = l1 - l2; i=0; while( ldiff-- ) stream[i++] = '0'; while( l2-- ) stream[i++] = *(bitstrm2++); stream[i] = '\0'; bitstrm2 = stream; } while ( (chr1 = *(bitstrm1++)) ) { chr2 = *(bitstrm2++); if ((chr1 == 'x') || (chr2 == 'x')) *result = 'x'; else if ((chr1 == '1') && (chr2 == '1')) *result = '1'; else *result = '0'; result++; } free(stream); *result = '\0'; } static void bitor(char *result,char *bitstrm1,char *bitstrm2) { int i, l1, l2, ldiff, largestStream; char *stream=0; char chr1, chr2; l1 = strlen(bitstrm1); l2 = strlen(bitstrm2); largestStream = (l1 > l2) ? l1 : l2; stream = (char *)malloc(sizeof(char)*(largestStream+1)); if (l1 < l2) { ldiff = l2 - l1; i=0; while( ldiff-- ) stream[i++] = '0'; while( l1-- ) stream[i++] = *(bitstrm1++); stream[i] = '\0'; bitstrm1 = stream; } else if (l2 < l1) { ldiff = l1 - l2; i=0; while( ldiff-- ) stream[i++] = '0'; while( l2-- ) stream[i++] = *(bitstrm2++); stream[i] = '\0'; bitstrm2 = stream; } while ( (chr1 = *(bitstrm1++)) ) { chr2 = *(bitstrm2++); if ((chr1 == '1') || (chr2 == '1')) *result = '1'; else if ((chr1 == '0') || (chr2 == '0')) *result = '0'; else *result = 'x'; result++; } free(stream); *result = '\0'; } static void bitnot(char *result,char *bits) { int length; char chr; length = strlen(bits); while( length-- ) { chr = *(bits++); *(result++) = ( chr=='1' ? '0' : ( chr=='0' ? '1' : chr ) ); } *result = '\0'; } static char bitcmp(char *bitstrm1, char *bitstrm2) { int i, l1, l2, ldiff, largestStream; char *stream=0; char chr1, chr2; l1 = strlen(bitstrm1); l2 = strlen(bitstrm2); largestStream = (l1 > l2) ? l1 : l2; stream = (char *)malloc(sizeof(char)*(largestStream+1)); if (l1 < l2) { ldiff = l2 - l1; i=0; while( ldiff-- ) stream[i++] = '0'; while( l1-- ) stream[i++] = *(bitstrm1++); stream[i] = '\0'; bitstrm1 = stream; } else if (l2 < l1) { ldiff = l1 - l2; i=0; while( ldiff-- ) stream[i++] = '0'; while( l2-- ) stream[i++] = *(bitstrm2++); stream[i] = '\0'; bitstrm2 = stream; } while( (chr1 = *(bitstrm1++)) ) { chr2 = *(bitstrm2++); if ( ((chr1 == '0') && (chr2 == '1')) || ((chr1 == '1') && (chr2 == '0')) ) { free(stream); return( 0 ); } } free(stream); return( 1 ); } static char bnear(double x, double y, double tolerance) { if (fabs(x - y) < tolerance) return ( 1 ); else return ( 0 ); } static char saobox(double xcen, double ycen, double xwid, double ywid, double rot, double xcol, double ycol) { double x,y,xprime,yprime,xmin,xmax,ymin,ymax,theta; theta = (rot / 180.0) * myPI; xprime = xcol - xcen; yprime = ycol - ycen; x = xprime * cos(theta) + yprime * sin(theta); y = -xprime * sin(theta) + yprime * cos(theta); xmin = - 0.5 * xwid; xmax = 0.5 * xwid; ymin = - 0.5 * ywid; ymax = 0.5 * ywid; if ((x >= xmin) && (x <= xmax) && (y >= ymin) && (y <= ymax)) return ( 1 ); else return ( 0 ); } static char circle(double xcen, double ycen, double rad, double xcol, double ycol) { double r2,dx,dy,dlen; dx = xcol - xcen; dy = ycol - ycen; dx *= dx; dy *= dy; dlen = dx + dy; r2 = rad * rad; if (dlen <= r2) return ( 1 ); else return ( 0 ); } static char ellipse(double xcen, double ycen, double xrad, double yrad, double rot, double xcol, double ycol) { double x,y,xprime,yprime,dx,dy,dlen,theta; theta = (rot / 180.0) * myPI; xprime = xcol - xcen; yprime = ycol - ycen; x = xprime * cos(theta) + yprime * sin(theta); y = -xprime * sin(theta) + yprime * cos(theta); dx = x / xrad; dy = y / yrad; dx *= dx; dy *= dy; dlen = dx + dy; if (dlen <= 1.0) return ( 1 ); else return ( 0 ); } /* * Extract substring */ int cstrmid(char *dest_str, int dest_len, char *src_str, int src_len, int pos) { /* char fill_char = ' '; */ char fill_char = '\0'; if (src_len == 0) { src_len = strlen(src_str); } /* .. if constant */ /* Fill destination with blanks */ if (pos < 0) { fferror("STRMID(S,P,N) P must be 0 or greater"); return -1; } if (pos > src_len || pos == 0) { /* pos==0: blank string requested */ memset(dest_str, fill_char, dest_len); } else if (pos+dest_len > src_len) { /* Copy a subset */ int nsub = src_len-pos+1; int npad = dest_len - nsub; memcpy(dest_str, src_str+pos-1, nsub); /* Fill remaining string with blanks */ memset(dest_str+nsub, fill_char, npad); } else { /* Full string copy */ memcpy(dest_str, src_str+pos-1, dest_len); } dest_str[dest_len] = '\0'; /* Null-terminate */ return 0; } static void fferror(char *s) { char msg[80]; if( !gParse.status ) gParse.status = PARSE_SYNTAX_ERR; strncpy(msg, s, 80); msg[79] = '\0'; ffpmsg(msg); } cfitsio/f77.inc0000644000225700000360000000152513246025103013101 0ustar cagordonlheaC Codes for FITS extension types integer IMAGE_HDU, ASCII_TBL, BINARY_TBL parameter ( & IMAGE_HDU = 0, & ASCII_TBL = 1, & BINARY_TBL = 2 ) C Codes for FITS table data types integer TBIT,TBYTE,TLOGICAL,TSTRING,TSHORT,TINT integer TFLOAT,TDOUBLE,TCOMPLEX,TDBLCOMPLEX parameter ( & TBIT = 1, & TBYTE = 11, & TLOGICAL = 14, & TSTRING = 16, & TSHORT = 21, & TINT = 31, & TFLOAT = 42, & TDOUBLE = 82, & TCOMPLEX = 83, & TDBLCOMPLEX = 163 ) C Codes for iterator column types integer InputCol, InputOutputCol, OutputCol parameter ( & InputCol = 0, & InputOutputCol = 1, & OutputCol = 2 ) cfitsio/f77_wrap.h0000644000225700000360000002427613246025103013620 0ustar cagordonlhea#define UNSIGNED_BYTE #include "cfortran.h" /************************************************************************ Some platforms creates longs as 8-byte integers. On other machines, ints and longs are both 4-bytes, so both are compatible with Fortrans default integer which is 4-bytes. To support 8-byte longs, we must redefine LONGs and convert them to 8-bytes when going to C, and restore them to 4-bytes when returning to Fortran. Ugh!!! *************************************************************************/ #if defined(DECFortran) || (defined(__alpha) && defined(g77Fortran)) \ || (defined(mipsFortran) && _MIPS_SZLONG==64) \ || (defined(IBMR2Fortran) && defined(__64BIT__)) \ || defined(__ia64__) \ || defined (__sparcv9) || (defined(__sparc__) && defined(__arch64__)) \ || defined (__x86_64__) \ || defined (_SX) \ || defined (__powerpc64__)\ || defined (__s390x__) #define LONG8BYTES_INT4BYTES #undef LONGV_cfSTR #undef PLONG_cfSTR #undef LONGVVVVVVV_cfTYPE #undef PLONG_cfTYPE #undef LONGV_cfT #undef PLONG_cfT #define LONGV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,LONGV,A,B,C,D,E) #define PLONG_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,PLONG,A,B,C,D,E) #define LONGVVVVVVV_cfTYPE int #define PLONG_cfTYPE int #define LONGV_cfQ(B) long *B, _(B,N); #define PLONG_cfQ(B) long B; #define LONGV_cfT(M,I,A,B,D) ( (_(B,N) = * _3(M,_LONGV_A,I)), \ B = F2Clongv(_(B,N),A) ) #define PLONG_cfT(M,I,A,B,D) ((B=*A),&B) #define LONGV_cfR(A,B,D) C2Flongv(_(B,N),A,B); #define PLONG_cfR(A,B,D) *A=B; #define LONGV_cfH(S,U,B) #define PLONG_cfH(S,U,B) static long *F2Clongv(long size, int *A) { long i; long *B; B=(long *)malloc( size*sizeof(long) ); for(i=0;idsc$a_pointer /* We want single strings to be equivalent to string vectors with */ /* a single element, so ignore the number of elements info in the */ /* vector structure, and rely on the NUM_ELEM definitions. */ #undef STRINGV_cfT #define STRINGV_cfT(M,I,A,B,D) TTTTSTRV(A->dsc$a_pointer, B, \ A->dsc$w_length, \ num_elem(A->dsc$a_pointer, \ A->dsc$w_length, \ _3(M,_STRV_A,I) ) ) #else #ifdef CRAYFortran #define PPSTRING_cfT(M,I,A,B,D) (unsigned char*)_fcdtocp(A) #else #define PPSTRING_cfT(M,I,A,B,D) (unsigned char*)A #endif #endif #define _cfMAX(A,B) ( (A>B) ? A : B ) #define STRINGV_cfQ(B) char **B; unsigned int _(B,N), _(B,M); #define STRINGV_cfR(A,B,D) free(B[0]); free(B); #define TTSTR( A,B,D) \ ((B=(char*)malloc(_cfMAX(D,gMinStrLen)+1))[D]='\0',memcpy(B,A,D), \ kill_trailing(B,' ')) #define TTTTSTRV( A,B,D,E) ( \ _(B,N)=_cfMAX(E,1), \ _(B,M)=_cfMAX(D,gMinStrLen)+1, \ B=(char**)malloc(_(B,N)*sizeof(char*)), \ B[0]=(char*)malloc(_(B,N)*_(B,M)), \ vindex(B,_(B,M),_(B,N),f2cstrv2(A,B[0],D,_(B,M),_(B,N))) \ ) #define RRRRPSTRV(A,B,D) \ c2fstrv2(B[0],A,_(B,M),D,_(B,N)), \ free(B[0]), \ free(B); static char **vindex(char **B, int elem_len, int nelem, char *B0) { int i; if( nelem ) for( i=0;idsc$a_pointer)[0]) #define BYTEV_cfT(M,I,A,B,D) (INTEGER_BYTE*)A->dsc$a_pointer #else #ifdef CRAYFortran #define BYTE_cfN(T,A) _fcd A #define BYTEV_cfN(T,A) _fcd A #define BYTE_cfT(M,I,A,B,D) (INTEGER_BYTE)((_fcdtocp(A))[0]) #define BYTEV_cfT(M,I,A,B,D) (INTEGER_BYTE*)_fcdtocp(A) #else #define BYTE_cfN(T,A) INTEGER_BYTE * A #define BYTEV_cfN(T,A) INTEGER_BYTE * A #define BYTE_cfT(M,I,A,B,D) A[0] #define BYTEV_cfT(M,I,A,B,D) A #endif #endif /************************************************************************ The following definitions and functions handle conversions between C and Fortran arrays of LOGICALS. Individually, LOGICALS are treated as int's but as char's when in an array. cfortran defines (F2C/C2F)LOGICALV but never uses them, so these routines also handle TRUE/FALSE conversions. *************************************************************************/ #undef LOGICALV_cfSTR #undef LOGICALV_cfT #define LOGICALV_cfSTR(N,T,A,B,C,D,E) _(CFARGS,N)(T,LOGICALV,A,B,C,D,E) #define LOGICALV_cfQ(B) char *B; unsigned int _(B,N); #define LOGICALV_cfT(M,I,A,B,D) (_(B,N)= * _3(M,_LOGV_A,I), \ B=F2CcopyLogVect(_(B,N),A)) #define LOGICALV_cfR(A,B,D) C2FcopyLogVect(_(B,N),A,B); #define LOGICALV_cfH(S,U,B) static char *F2CcopyLogVect(long size, int *A) { long i; char *B; B=(char *)malloc(size*sizeof(char)); for( i=0; i0 ) return; for( i=50;i0 ) return; if( unit == -1 ) { int i; for( i=50; i=NMAXFILES ) { *status = BAD_FILEPTR; ffpmsg("Cfffiou was sent an unacceptable unit number."); } else gFitsFiles[unit]=NULL; } FCALLSCSUB2(Cfffiou,FTFIOU,ftfiou,INT,PINT) int CFITS2Unit( fitsfile *fptr ) /* Utility routine to convert a fitspointer to a Fortran unit number */ /* for use when a C program is calling a Fortran routine which could */ /* in turn call CFITSIO... Modelled after code by Ning Gan. */ { static fitsfile *last_fptr = (fitsfile *)NULL; /* Remember last fptr */ static int last_unit = 0; /* Remember last unit */ int status = 0; /* Test whether we are repeating the last lookup */ if( last_unit && fptr==gFitsFiles[last_unit] ) return( last_unit ); /* Check if gFitsFiles has an entry for this fptr. */ /* Allows Fortran to call C to call Fortran to */ /* call CFITSIO... OUCH!!! */ last_fptr = fptr; for( last_unit=1; last_unit=NMAXFILES ) return(0); return(gFitsFiles[unit]); } /**************************************************/ /* Start of wrappers for routines in fitsio.h */ /**************************************************/ /*---------------- FITS file URL parsing routines -------------*/ FCALLSCSUB9(ffiurl,FTIURL,ftiurl,STRING,PSTRING,PSTRING,PSTRING,PSTRING,PSTRING,PSTRING,PSTRING,PINT) FCALLSCSUB3(ffrtnm,FTRTNM,ftrtnm,STRING,PSTRING,PINT) FCALLSCSUB3(ffexist,FTEXIST,ftexist,STRING,PINT,PINT) FCALLSCSUB3(ffextn,FTEXTN,ftextn,STRING,PINT,PINT) FCALLSCSUB7(ffrwrg,FTRWRG,ftrwrg,STRING,LONG,INT,PINT,PLONG,PLONG,PINT) /*---------------- FITS file I/O routines ---------------*/ void Cffopen( fitsfile **fptr, const char *filename, int iomode, int *blocksize, int *status ); void Cffopen( fitsfile **fptr, const char *filename, int iomode, int *blocksize, int *status ) { int hdutype; if( *fptr==NULL || *fptr==(fitsfile*)1 ) { ffopen( fptr, filename, iomode, status ); ffmahd( *fptr, 1, &hdutype, status ); *blocksize = 1; } else { *status = FILE_NOT_OPENED; ffpmsg("Cffopen tried to use an already opened unit."); } } FCALLSCSUB5(Cffopen,FTOPEN,ftopen,PFITSUNIT,STRING,INT,PINT,PINT) void Cffdkopn( fitsfile **fptr, const char *filename, int iomode, int *blocksize, int *status ); void Cffdkopn( fitsfile **fptr, const char *filename, int iomode, int *blocksize, int *status ) { int hdutype; if( *fptr==NULL || *fptr==(fitsfile*)1 ) { ffdkopn( fptr, filename, iomode, status ); ffmahd( *fptr, 1, &hdutype, status ); *blocksize = 1; } else { *status = FILE_NOT_OPENED; ffpmsg("Cffdkopn tried to use an already opened unit."); } } FCALLSCSUB5(Cffdkopn,FTDKOPN,ftdkopn,PFITSUNIT,STRING,INT,PINT,PINT) void Cffnopn( fitsfile **fptr, const char *filename, int iomode, int *status ); void Cffnopn( fitsfile **fptr, const char *filename, int iomode, int *status ) { if( *fptr==NULL || *fptr==(fitsfile*)1 ) { ffopen( fptr, filename, iomode, status ); } else { *status = FILE_NOT_OPENED; ffpmsg("Cffnopn tried to use an already opened unit."); } } FCALLSCSUB4(Cffnopn,FTNOPN,ftnopn,PFITSUNIT,STRING,INT,PINT) void Cffdopn( fitsfile **fptr, const char *filename, int iomode, int *status ); void Cffdopn( fitsfile **fptr, const char *filename, int iomode, int *status ) { if( *fptr==NULL || *fptr==(fitsfile*)1 ) { ffdopn( fptr, filename, iomode, status ); } else { *status = FILE_NOT_OPENED; ffpmsg("Cffdopn tried to use an already opened unit."); } } FCALLSCSUB4(Cffdopn,FTDOPN,ftdopn,PFITSUNIT,STRING,INT,PINT) void Cfftopn( fitsfile **fptr, const char *filename, int iomode, int *status ); void Cfftopn( fitsfile **fptr, const char *filename, int iomode, int *status ) { if( *fptr==NULL || *fptr==(fitsfile*)1 ) { fftopn( fptr, filename, iomode, status ); } else { *status = FILE_NOT_OPENED; ffpmsg("Cfftopn tried to use an already opened unit."); } } FCALLSCSUB4(Cfftopn,FTTOPN,fttopn,PFITSUNIT,STRING,INT,PINT) void Cffiopn( fitsfile **fptr, const char *filename, int iomode, int *status ); void Cffiopn( fitsfile **fptr, const char *filename, int iomode, int *status ) { if( *fptr==NULL || *fptr==(fitsfile*)1 ) { ffiopn( fptr, filename, iomode, status ); } else { *status = FILE_NOT_OPENED; ffpmsg("Cffiopn tried to use an already opened unit."); } } FCALLSCSUB4(Cffiopn,FTIOPN,ftiopn,PFITSUNIT,STRING,INT,PINT) void Cffreopen( fitsfile *openfptr, fitsfile **newfptr, int *status ); void Cffreopen( fitsfile *openfptr, fitsfile **newfptr, int *status ) { if( *newfptr==NULL || *newfptr==(fitsfile*)1 ) { ffreopen( openfptr, newfptr, status ); } else { *status = FILE_NOT_OPENED; ffpmsg("Cffreopen tried to use an already opened unit."); } } FCALLSCSUB3(Cffreopen,FTREOPEN,ftreopen,FITSUNIT,PFITSUNIT,PINT) void Cffinit( fitsfile **fptr, const char *filename, int blocksize, int *status ); void Cffinit( fitsfile **fptr, const char *filename, int blocksize, int *status ) { if( *fptr==NULL || *fptr==(fitsfile*)1 ) { ffinit( fptr, filename, status ); } else { *status = FILE_NOT_CREATED; ffpmsg("Cffinit tried to use an already opened unit."); } } FCALLSCSUB4(Cffinit,FTINIT,ftinit,PFITSUNIT,STRING,INT,PINT) void Cffdkinit( fitsfile **fptr, const char *filename, int blocksize, int *status ); void Cffdkinit( fitsfile **fptr, const char *filename, int blocksize, int *status ) { if( *fptr==NULL || *fptr==(fitsfile*)1 ) { ffdkinit( fptr, filename, status ); } else { *status = FILE_NOT_CREATED; ffpmsg("Cffdkinit tried to use an already opened unit."); } } FCALLSCSUB4(Cffdkinit,FTDKINIT,ftdkinit,PFITSUNIT,STRING,INT,PINT) void Cfftplt( fitsfile **fptr, const char *filename, const char *tempname, int *status ); void Cfftplt( fitsfile **fptr, const char *filename, const char *tempname, int *status ) { if( *fptr==NULL || *fptr==(fitsfile*)1 ) { fftplt( fptr, filename, tempname, status ); } else { *status = FILE_NOT_CREATED; ffpmsg("Cfftplt tried to use an already opened unit."); } } FCALLSCSUB4(Cfftplt,FTTPLT,fttplt,PFITSUNIT,STRING,STRING,PINT) FCALLSCSUB2(ffflus,FTFLUS,ftflus,FITSUNIT,PINT) FCALLSCSUB3(ffflsh,FTFLSH,ftflsh,FITSUNIT, INT, PINT) void Cffclos( int unit, int *status ); void Cffclos( int unit, int *status ) { if( gFitsFiles[unit]!=NULL && gFitsFiles[unit]!=(void*)1 ) { ffclos( gFitsFiles[unit], status ); /* Flag unit number as unavailable */ gFitsFiles[unit]=(fitsfile*)1; /* in case want to reuse it */ } } FCALLSCSUB2(Cffclos,FTCLOS,ftclos,INT,PINT) void Cffdelt( int unit, int *status ); void Cffdelt( int unit, int *status ) { if( gFitsFiles[unit]!=NULL && gFitsFiles[unit]!=(void*)1 ) { ffdelt( gFitsFiles[unit], status ); /* Flag unit number as unavailable */ gFitsFiles[unit]=(fitsfile*)1; /* in case want to reuse it */ } } FCALLSCSUB2(Cffdelt,FTDELT,ftdelt,INT,PINT) FCALLSCSUB3(ffflnm,FTFLNM,ftflnm,FITSUNIT,PSTRING,PINT) FCALLSCSUB3(ffflmd,FTFLMD,ftflmd,FITSUNIT,PINT,PINT) /*--------------- utility routines ---------------*/ FCALLSCSUB1(ffvers,FTVERS,ftvers,PFLOAT) FCALLSCSUB1(ffupch,FTUPCH,ftupch,PSTRING) FCALLSCSUB2(ffgerr,FTGERR,ftgerr,INT,PSTRING) FCALLSCSUB1(ffpmsg,FTPMSG,ftpmsg,STRING) FCALLSCSUB1(ffgmsg,FTGMSG,ftgmsg,PSTRING) FCALLSCSUB0(ffcmsg,FTCMSG,ftcmsg) FCALLSCSUB0(ffpmrk,FTPMRK,ftpmrk) FCALLSCSUB0(ffcmrk,FTCMRK,ftcmrk) void Cffrprt( char *fname, int status ); void Cffrprt( char *fname, int status ) { if( !strcmp(fname,"STDOUT") || !strcmp(fname,"stdout") ) ffrprt( stdout, status ); else if( !strcmp(fname,"STDERR") || !strcmp(fname,"stderr") ) ffrprt( stderr, status ); else { FILE *fptr; fptr = fopen(fname, "a"); if (fptr==NULL) printf("file pointer is null.\n"); else { ffrprt(fptr,status); fclose(fptr); } } } FCALLSCSUB2(Cffrprt,FTRPRT,ftrprt,STRING,INT) FCALLSCSUB5(ffcmps,FTCMPS,ftcmps,STRING,STRING,LOGICAL,PLOGICAL,PLOGICAL) FCALLSCSUB2(fftkey,FTTKEY,fttkey,STRING,PINT) FCALLSCSUB2(fftrec,FTTREC,fttrec,STRING,PINT) FCALLSCSUB2(ffnchk,FTNCHK,ftnchk,FITSUNIT,PINT) FCALLSCSUB4(ffkeyn,FTKEYN,ftkeyn,STRING,INT,PSTRING,PINT) FCALLSCSUB4(ffgknm,FTGKNM,ftgknm,STRING,PSTRING, PINT, PINT) FCALLSCSUB4(ffnkey,FTNKEY,ftnkey,INT,STRING,PSTRING,PINT) FCALLSCSUB3(ffdtyp,FTDTYP,ftdtyp,STRING,PSTRING,PINT) FCALLSCFUN1(INT,ffgkcl,FTGKCL,ftgkcl,STRING) FCALLSCSUB5(ffmkky,FTMKKY,ftmkky,STRING,STRING,STRING,PSTRING,PINT) FCALLSCSUB4(ffpsvc,FTPSVC,ftpsvc,STRING,PSTRING,PSTRING,PINT) FCALLSCSUB4(ffgthd,FTGTHD,ftgthd,STRING,PSTRING,PINT,PINT) FCALLSCSUB5(ffasfm,FTASFM,ftasfm,STRING,PINT,PLONG,PINT,PINT) FCALLSCSUB5(ffbnfm,FTBNFM,ftbnfm,STRING,PINT,PLONG,PLONG,PINT) #define ftgabc_STRV_A2 NUM_ELEM_ARG(1) #define ftgabc_LONGV_A5 A1 FCALLSCSUB6(ffgabc,FTGABC,ftgabc,INT,STRINGV,INT,PLONG,LONGV,PINT) cfitsio/f77_wrap2.c0000644000225700000360000007720113246025103013671 0ustar cagordonlhea/************************************************************************ f77_wrap1.c and f77_wrap2.c have now been split into 4 files to prevent compile-time memory errors (from expansion of compiler commands). f77_wrap1.c was split into f77_wrap1.c and f77_wrap3.c, and f77_wrap2.c was split into f77_wrap2.c and f77_wrap4.c: f77_wrap1.c contains routines operating on whole files and some utility routines. f77_wrap2.c contains routines operating on primary array, image, or column elements. f77_wrap3.c contains routines operating on headers & keywords. f77_wrap4.c contains miscellaneous routines. Peter's original comments: Together, f77_wrap1.c and f77_wrap2.c contain C wrappers for all the CFITSIO routines prototyped in fitsio.h, except for the generic datatype routines and features not supported in fortran (eg, unsigned integers), a few routines prototyped in fitsio2.h, which only a handful of FTOOLS use, plus a few obsolete FITSIO routines not present in CFITSIO. This file allows Fortran code to use the CFITSIO library instead of the FITSIO library without modification. It also gives access to new routines not present in FITSIO. Fortran FTOOLS must continue using the old routine names from FITSIO (ie, ftxxxx), but most of the C-wrappers simply redirect those calls to the corresponding CFITSIO routines (ie, ffxxxx), with appropriate parameter massaging where necessary. The main exception are read/write routines ending in j (ie, long data) which get redirected to C routines ending in k (ie, int data). This is more consistent with the default integer type in Fortran. f77_wrap1.c primarily holds routines operating on whole files and extension headers. f77_wrap2.c handle routines which read and write the data portion, plus miscellaneous extra routines. File created by Peter Wilson (HSTX), Oct-Dec. 1997 ************************************************************************/ #include "fitsio2.h" #include "f77_wrap.h" FCALLSCSUB5(ffgextn,FTGEXTN,ftgextn,FITSUNIT,LONG,LONG,BYTEV,PINT) FCALLSCSUB5(ffpextn,FTPEXTN,ftpextn,FITSUNIT,LONG,LONG,BYTEV,PINT) /*------------ read primary array or image elements -------------*/ FCALLSCSUB8(ffgpvb,FTGPVB,ftgpvb,FITSUNIT,LONG,LONG,LONG,BYTE,BYTEV,PLOGICAL,PINT) FCALLSCSUB8(ffgpvi,FTGPVI,ftgpvi,FITSUNIT,LONG,LONG,LONG,SHORT,SHORTV,PLOGICAL,PINT) FCALLSCSUB8(ffgpvk,FTGPVJ,ftgpvj,FITSUNIT,LONG,LONG,LONG,INT,INTV,PLOGICAL,PINT) FCALLSCSUB8(ffgpvjj,FTGPVK,ftgpvk,FITSUNIT,LONG,LONG,LONG,LONGLONG,LONGLONGV,PLOGICAL,PINT) FCALLSCSUB8(ffgpve,FTGPVE,ftgpve,FITSUNIT,LONG,LONG,LONG,FLOAT,FLOATV,PLOGICAL,PINT) FCALLSCSUB8(ffgpvd,FTGPVD,ftgpvd,FITSUNIT,LONG,LONG,LONG,DOUBLE,DOUBLEV,PLOGICAL,PINT) #define ftgpfb_LOGV_A6 A4 FCALLSCSUB8(ffgpfb,FTGPFB,ftgpfb,FITSUNIT,LONG,LONG,LONG,BYTEV,LOGICALV,PLOGICAL,PINT) #define ftgpfi_LOGV_A6 A4 FCALLSCSUB8(ffgpfi,FTGPFI,ftgpfi,FITSUNIT,LONG,LONG,LONG,SHORTV,LOGICALV,PLOGICAL,PINT) #define ftgpfj_LOGV_A6 A4 FCALLSCSUB8(ffgpfk,FTGPFJ,ftgpfj,FITSUNIT,LONG,LONG,LONG,INTV,LOGICALV,PLOGICAL,PINT) #define ftgpfk_LOGV_A6 A4 FCALLSCSUB8(ffgpfjj,FTGPFK,ftgpfk,FITSUNIT,LONG,LONG,LONG,LONGLONGV,LOGICALV,PLOGICAL,PINT) #define ftgpfe_LOGV_A6 A4 FCALLSCSUB8(ffgpfe,FTGPFE,ftgpfe,FITSUNIT,LONG,LONG,LONG,FLOATV,LOGICALV,PLOGICAL,PINT) #define ftgpfd_LOGV_A6 A4 FCALLSCSUB8(ffgpfd,FTGPFD,ftgpfd,FITSUNIT,LONG,LONG,LONG,DOUBLEV,LOGICALV,PLOGICAL,PINT) FCALLSCSUB9(ffg2db,FTG2DB,ftg2db,FITSUNIT,LONG,BYTE,LONG,LONG,LONG,BYTEV,PLOGICAL,PINT) FCALLSCSUB9(ffg2di,FTG2DI,ftg2di,FITSUNIT,LONG,SHORT,LONG,LONG,LONG,SHORTV,PLOGICAL,PINT) FCALLSCSUB9(ffg2dk,FTG2DJ,ftg2dj,FITSUNIT,LONG,INT,LONG,LONG,LONG,INTV,PLOGICAL,PINT) FCALLSCSUB9(ffg2djj,FTG2DK,ftg2dk,FITSUNIT,LONG,LONGLONG,LONG,LONG,LONG,LONGLONGV,PLOGICAL,PINT) FCALLSCSUB9(ffg2de,FTG2DE,ftg2de,FITSUNIT,LONG,FLOAT,LONG,LONG,LONG,FLOATV,PLOGICAL,PINT) FCALLSCSUB9(ffg2dd,FTG2DD,ftg2dd,FITSUNIT,LONG,DOUBLE,LONG,LONG,LONG,DOUBLEV,PLOGICAL,PINT) FCALLSCSUB11(ffg3db,FTG3DB,ftg3db,FITSUNIT,LONG,BYTE,LONG,LONG,LONG,LONG,LONG,BYTEV,PLOGICAL,PINT) FCALLSCSUB11(ffg3di,FTG3DI,ftg3di,FITSUNIT,LONG,SHORT,LONG,LONG,LONG,LONG,LONG,SHORTV,PLOGICAL,PINT) FCALLSCSUB11(ffg3dk,FTG3DJ,ftg3dj,FITSUNIT,LONG,INT,LONG,LONG,LONG,LONG,LONG,INTV,PLOGICAL,PINT) FCALLSCSUB11(ffg3djj,FTG3DK,ftg3dk,FITSUNIT,LONG,LONGLONG,LONG,LONG,LONG,LONG,LONG,LONGLONGV,PLOGICAL,PINT) FCALLSCSUB11(ffg3de,FTG3DE,ftg3de,FITSUNIT,LONG,FLOAT,LONG,LONG,LONG,LONG,LONG,FLOATV,PLOGICAL,PINT) FCALLSCSUB11(ffg3dd,FTG3DD,ftg3dd,FITSUNIT,LONG,DOUBLE,LONG,LONG,LONG,LONG,LONG,DOUBLEV,PLOGICAL,PINT) /* The follow LONGV definitions have +1 appended because the */ /* routines use of NAXIS+1 elements of the long vectors. */ #define ftgsvb_LONGV_A4 A3+1 #define ftgsvb_LONGV_A5 A3+1 #define ftgsvb_LONGV_A6 A3+1 #define ftgsvb_LONGV_A7 A3+1 FCALLSCSUB11(ffgsvb,FTGSVB,ftgsvb,FITSUNIT,INT,INT,LONGV,LONGV,LONGV,LONGV,BYTE,BYTEV,PLOGICAL,PINT) #define ftgsvi_LONGV_A4 A3+1 #define ftgsvi_LONGV_A5 A3+1 #define ftgsvi_LONGV_A6 A3+1 #define ftgsvi_LONGV_A7 A3+1 FCALLSCSUB11(ffgsvi,FTGSVI,ftgsvi,FITSUNIT,INT,INT,LONGV,LONGV,LONGV,LONGV,SHORT,SHORTV,PLOGICAL,PINT) #define ftgsvj_LONGV_A4 A3+1 #define ftgsvj_LONGV_A5 A3+1 #define ftgsvj_LONGV_A6 A3+1 #define ftgsvj_LONGV_A7 A3+1 FCALLSCSUB11(ffgsvk,FTGSVJ,ftgsvj,FITSUNIT,INT,INT,LONGV,LONGV,LONGV,LONGV,INT,INTV,PLOGICAL,PINT) #define ftgsvk_LONGV_A4 A3+1 #define ftgsvk_LONGV_A5 A3+1 #define ftgsvk_LONGV_A6 A3+1 #define ftgsvk_LONGV_A7 A3+1 FCALLSCSUB11(ffgsvjj,FTGSVK,ftgsvk,FITSUNIT,INT,INT,LONGV,LONGV,LONGV,LONGV,LONGLONG,LONGLONGV,PLOGICAL,PINT) #define ftgsve_LONGV_A4 A3+1 #define ftgsve_LONGV_A5 A3+1 #define ftgsve_LONGV_A6 A3+1 #define ftgsve_LONGV_A7 A3+1 FCALLSCSUB11(ffgsve,FTGSVE,ftgsve,FITSUNIT,INT,INT,LONGV,LONGV,LONGV,LONGV,FLOAT,FLOATV,PLOGICAL,PINT) #define ftgsvd_LONGV_A4 A3+1 #define ftgsvd_LONGV_A5 A3+1 #define ftgsvd_LONGV_A6 A3+1 #define ftgsvd_LONGV_A7 A3+1 FCALLSCSUB11(ffgsvd,FTGSVD,ftgsvd,FITSUNIT,INT,INT,LONGV,LONGV,LONGV,LONGV,DOUBLE,DOUBLEV,PLOGICAL,PINT) /* Must handle LOGICALV conversion manually */ void Cffgsfb( fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, unsigned char *array, int *flagval, int *anynul, int *status ); void Cffgsfb( fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, unsigned char *array, int *flagval, int *anynul, int *status ) { char *Cflagval; long nflagval; int i; for( nflagval=1, i=0; iFwork_fn(&a1,&a2,&a3,&a4,&n_cols,units,colnum,datatype, iotype,repeat,&status,f->userData, ptrs[ 0], ptrs[ 1], ptrs[ 2], ptrs[ 3], ptrs[ 4], ptrs[ 5], ptrs[ 6], ptrs[ 7], ptrs[ 8], ptrs[ 9], ptrs[10], ptrs[11], ptrs[12], ptrs[13], ptrs[14], ptrs[15], ptrs[16], ptrs[17], ptrs[18], ptrs[19], ptrs[20], ptrs[21], ptrs[22], ptrs[23], ptrs[24] ); } /* Check whether there are any LOGICAL or STRING columns being outputted */ nstr=0; for( i=0;i #include #include #include #include "fitsio2.h" static long noutchar; static long noutmax; static int htrans(int a[],int nx,int ny); static void digitize(int a[], int nx, int ny, int scale); static int encode(char *outfile, long *nlen, int a[], int nx, int ny, int scale); static void shuffle(int a[], int n, int n2, int tmp[]); static int htrans64(LONGLONG a[],int nx,int ny); static void digitize64(LONGLONG a[], int nx, int ny, int scale); static int encode64(char *outfile, long *nlen, LONGLONG a[], int nx, int ny, int scale); static void shuffle64(LONGLONG a[], int n, int n2, LONGLONG tmp[]); static void writeint(char *outfile, int a); static void writelonglong(char *outfile, LONGLONG a); static int doencode(char *outfile, int a[], int nx, int ny, unsigned char nbitplanes[3]); static int doencode64(char *outfile, LONGLONG a[], int nx, int ny, unsigned char nbitplanes[3]); static int qwrite(char *file, char buffer[], int n); static int qtree_encode(char *outfile, int a[], int n, int nqx, int nqy, int nbitplanes); static int qtree_encode64(char *outfile, LONGLONG a[], int n, int nqx, int nqy, int nbitplanes); static void start_outputing_bits(void); static void done_outputing_bits(char *outfile); static void output_nbits(char *outfile, int bits, int n); static void qtree_onebit(int a[], int n, int nx, int ny, unsigned char b[], int bit); static void qtree_onebit64(LONGLONG a[], int n, int nx, int ny, unsigned char b[], int bit); static void qtree_reduce(unsigned char a[], int n, int nx, int ny, unsigned char b[]); static int bufcopy(unsigned char a[], int n, unsigned char buffer[], int *b, int bmax); static void write_bdirect(char *outfile, int a[], int n,int nqx, int nqy, unsigned char scratch[], int bit); static void write_bdirect64(char *outfile, LONGLONG a[], int n,int nqx, int nqy, unsigned char scratch[], int bit); /* #define output_nybble(outfile,c) output_nbits(outfile,c,4) */ static void output_nybble(char *outfile, int bits); static void output_nnybble(char *outfile, int n, unsigned char array[]); #define output_huffman(outfile,c) output_nbits(outfile,code[c],ncode[c]) /* ---------------------------------------------------------------------- */ int fits_hcompress(int *a, int ny, int nx, int scale, char *output, long *nbytes, int *status) { /* compress the input image using the H-compress algorithm a - input image array nx - size of X axis of image ny - size of Y axis of image scale - quantization scale factor. Larger values results in more (lossy) compression scale = 0 does lossless compression output - pre-allocated array to hold the output compressed stream of bytes nbyts - input value = size of the output buffer; returned value = size of the compressed byte stream, in bytes NOTE: the nx and ny dimensions as defined within this code are reversed from the usual FITS notation. ny is the fastest varying dimension, which is usually considered the X axis in the FITS image display */ int stat; if (*status > 0) return(*status); /* H-transform */ stat = htrans(a, nx, ny); if (stat) { *status = stat; return(*status); } /* digitize */ digitize(a, nx, ny, scale); /* encode and write to output array */ FFLOCK; noutmax = *nbytes; /* input value is the allocated size of the array */ *nbytes = 0; /* reset */ stat = encode(output, nbytes, a, nx, ny, scale); FFUNLOCK; *status = stat; return(*status); } /* ---------------------------------------------------------------------- */ int fits_hcompress64(LONGLONG *a, int ny, int nx, int scale, char *output, long *nbytes, int *status) { /* compress the input image using the H-compress algorithm a - input image array nx - size of X axis of image ny - size of Y axis of image scale - quantization scale factor. Larger values results in more (lossy) compression scale = 0 does lossless compression output - pre-allocated array to hold the output compressed stream of bytes nbyts - size of the compressed byte stream, in bytes NOTE: the nx and ny dimensions as defined within this code are reversed from the usual FITS notation. ny is the fastest varying dimension, which is usually considered the X axis in the FITS image display */ int stat; if (*status > 0) return(*status); /* H-transform */ stat = htrans64(a, nx, ny); if (stat) { *status = stat; return(*status); } /* digitize */ digitize64(a, nx, ny, scale); /* encode and write to output array */ FFLOCK; noutmax = *nbytes; /* input value is the allocated size of the array */ *nbytes = 0; /* reset */ stat = encode64(output, nbytes, a, nx, ny, scale); FFUNLOCK; *status = stat; return(*status); } /* Copyright (c) 1993 Association of Universities for Research * in Astronomy. All rights reserved. Produced under National * Aeronautics and Space Administration Contract No. NAS5-26555. */ /* htrans.c H-transform of NX x NY integer image * * Programmer: R. White Date: 11 May 1992 */ /* ######################################################################### */ static int htrans(int a[],int nx,int ny) { int nmax, log2n, h0, hx, hy, hc, nxtop, nytop, i, j, k; int oddx, oddy; int shift, mask, mask2, prnd, prnd2, nrnd2; int s10, s00; int *tmp; /* * log2n is log2 of max(nx,ny) rounded up to next power of 2 */ nmax = (nx>ny) ? nx : ny; log2n = (int) (log((float) nmax)/log(2.0)+0.5); if ( nmax > (1<> shift; hx = (a[s10+1] + a[s10] - a[s00+1] - a[s00]) >> shift; hy = (a[s10+1] - a[s10] + a[s00+1] - a[s00]) >> shift; hc = (a[s10+1] - a[s10] - a[s00+1] + a[s00]) >> shift; /* * Throw away the 2 bottom bits of h0, bottom bit of hx,hy. * To get rounding to be same for positive and negative * numbers, nrnd2 = prnd2 - 1. */ a[s10+1] = hc; a[s10 ] = ( (hx>=0) ? (hx+prnd) : hx ) & mask ; a[s00+1] = ( (hy>=0) ? (hy+prnd) : hy ) & mask ; a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2; s00 += 2; s10 += 2; } if (oddy) { /* * do last element in row if row length is odd * s00+1, s10+1 are off edge */ h0 = (a[s10] + a[s00]) << (1-shift); hx = (a[s10] - a[s00]) << (1-shift); a[s10 ] = ( (hx>=0) ? (hx+prnd) : hx ) & mask ; a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2; s00 += 1; s10 += 1; } } if (oddx) { /* * do last row if column length is odd * s10, s10+1 are off edge */ s00 = i*ny; for (j = 0; j=0) ? (hy+prnd) : hy ) & mask ; a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2; s00 += 2; } if (oddy) { /* * do corner element if both row and column lengths are odd * s00+1, s10, s10+1 are off edge */ h0 = a[s00] << (2-shift); a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2; } } /* * now shuffle in each dimension to group coefficients by order */ for (i = 0; i>1; nytop = (nytop+1)>>1; /* * divisor doubles after first reduction */ shift = 1; /* * masks, rounding values double after each iteration */ mask = mask2; prnd = prnd2; mask2 = mask2 << 1; prnd2 = prnd2 << 1; nrnd2 = prnd2 - 1; } free(tmp); return(0); } /* ######################################################################### */ static int htrans64(LONGLONG a[],int nx,int ny) { int nmax, log2n, nxtop, nytop, i, j, k; int oddx, oddy; int shift; int s10, s00; LONGLONG h0, hx, hy, hc, prnd, prnd2, nrnd2, mask, mask2; LONGLONG *tmp; /* * log2n is log2 of max(nx,ny) rounded up to next power of 2 */ nmax = (nx>ny) ? nx : ny; log2n = (int) (log((float) nmax)/log(2.0)+0.5); if ( nmax > (1<> shift; hx = (a[s10+1] + a[s10] - a[s00+1] - a[s00]) >> shift; hy = (a[s10+1] - a[s10] + a[s00+1] - a[s00]) >> shift; hc = (a[s10+1] - a[s10] - a[s00+1] + a[s00]) >> shift; /* * Throw away the 2 bottom bits of h0, bottom bit of hx,hy. * To get rounding to be same for positive and negative * numbers, nrnd2 = prnd2 - 1. */ a[s10+1] = hc; a[s10 ] = ( (hx>=0) ? (hx+prnd) : hx ) & mask ; a[s00+1] = ( (hy>=0) ? (hy+prnd) : hy ) & mask ; a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2; s00 += 2; s10 += 2; } if (oddy) { /* * do last element in row if row length is odd * s00+1, s10+1 are off edge */ h0 = (a[s10] + a[s00]) << (1-shift); hx = (a[s10] - a[s00]) << (1-shift); a[s10 ] = ( (hx>=0) ? (hx+prnd) : hx ) & mask ; a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2; s00 += 1; s10 += 1; } } if (oddx) { /* * do last row if column length is odd * s10, s10+1 are off edge */ s00 = i*ny; for (j = 0; j=0) ? (hy+prnd) : hy ) & mask ; a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2; s00 += 2; } if (oddy) { /* * do corner element if both row and column lengths are odd * s00+1, s10, s10+1 are off edge */ h0 = a[s00] << (2-shift); a[s00 ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2; } } /* * now shuffle in each dimension to group coefficients by order */ for (i = 0; i>1; nytop = (nytop+1)>>1; /* * divisor doubles after first reduction */ shift = 1; /* * masks, rounding values double after each iteration */ mask = mask2; prnd = prnd2; mask2 = mask2 << 1; prnd2 = prnd2 << 1; nrnd2 = prnd2 - 1; } free(tmp); return(0); } /* ######################################################################### */ static void shuffle(int a[], int n, int n2, int tmp[]) { /* int a[]; array to shuffle int n; number of elements to shuffle int n2; second dimension int tmp[]; scratch storage */ int i; int *p1, *p2, *pt; /* * copy odd elements to tmp */ pt = tmp; p1 = &a[n2]; for (i=1; i < n; i += 2) { *pt = *p1; pt += 1; p1 += (n2+n2); } /* * compress even elements into first half of A */ p1 = &a[n2]; p2 = &a[n2+n2]; for (i=2; i0) ? (*p+d) : (*p-d))/scale; } /* ######################################################################### */ static void digitize64(LONGLONG a[], int nx, int ny, int scale) { LONGLONG d, *p, scale64; /* * round to multiple of scale */ if (scale <= 1) return; d=(scale+1)/2-1; scale64 = scale; /* use a 64-bit int for efficiency in the big loop */ for (p=a; p <= &a[nx*ny-1]; p++) *p = ((*p>0) ? (*p+d) : (*p-d))/scale64; } /* ######################################################################### */ /* ######################################################################### */ /* Copyright (c) 1993 Association of Universities for Research * in Astronomy. All rights reserved. Produced under National * Aeronautics and Space Administration Contract No. NAS5-26555. */ /* encode.c encode H-transform and write to outfile * * Programmer: R. White Date: 2 February 1994 */ static char code_magic[2] = { (char)0xDD, (char)0x99 }; /* ######################################################################### */ static int encode(char *outfile, long *nlength, int a[], int nx, int ny, int scale) { /* FILE *outfile; - change outfile to a char array */ /* long * nlength returned length (in bytes) of the encoded array) int a[]; input H-transform array (nx,ny) int nx,ny; size of H-transform array int scale; scale factor for digitization */ int nel, nx2, ny2, i, j, k, q, vmax[3], nsign, bits_to_go; unsigned char nbitplanes[3]; unsigned char *signbits; int stat; noutchar = 0; /* initialize the number of compressed bytes that have been written */ nel = nx*ny; /* * write magic value */ qwrite(outfile, code_magic, sizeof(code_magic)); writeint(outfile, nx); /* size of image */ writeint(outfile, ny); writeint(outfile, scale); /* scale factor for digitization */ /* * write first value of A (sum of all pixels -- the only value * which does not compress well) */ writelonglong(outfile, (LONGLONG) a[0]); a[0] = 0; /* * allocate array for sign bits and save values, 8 per byte (initialize to all zeros) */ signbits = (unsigned char *) calloc(1, (nel+7)/8); if (signbits == (unsigned char *) NULL) { ffpmsg("encode: insufficient memory"); return(DATA_COMPRESSION_ERR); } nsign = 0; bits_to_go = 8; /* signbits[0] = 0; */ for (i=0; i 0) { /* * positive element, put zero at end of buffer */ signbits[nsign] <<= 1; bits_to_go -= 1; } else if (a[i] < 0) { /* * negative element, shift in a one */ signbits[nsign] <<= 1; signbits[nsign] |= 1; bits_to_go -= 1; /* * replace a by absolute value */ a[i] = -a[i]; } if (bits_to_go == 0) { /* * filled up this byte, go to the next one */ bits_to_go = 8; nsign += 1; /* signbits[nsign] = 0; */ } } if (bits_to_go != 8) { /* * some bits in last element * move bits in last byte to bottom and increment nsign */ signbits[nsign] <<= bits_to_go; nsign += 1; } /* * calculate number of bit planes for 3 quadrants * * quadrant 0=bottom left, 1=bottom right or top left, 2=top right, */ for (q=0; q<3; q++) { vmax[q] = 0; } /* * get maximum absolute value in each quadrant */ nx2 = (nx+1)/2; ny2 = (ny+1)/2; j=0; /* column counter */ k=0; /* row counter */ for (i=0; i=ny2) + (k>=nx2); if (vmax[q] < a[i]) vmax[q] = a[i]; if (++j >= ny) { j = 0; k += 1; } } /* * now calculate number of bits for each quadrant */ /* this is a more efficient way to do this, */ for (q = 0; q < 3; q++) { for (nbitplanes[q] = 0; vmax[q]>0; vmax[q] = vmax[q]>>1, nbitplanes[q]++) ; } /* for (q = 0; q < 3; q++) { nbitplanes[q] = (int) (log((float) (vmax[q]+1))/log(2.0)+0.5); if ( (vmax[q]+1) > (1< 0) { if ( 0 == qwrite(outfile, (char *) signbits, nsign)) { free(signbits); *nlength = noutchar; ffpmsg("encode: output buffer too small"); return(DATA_COMPRESSION_ERR); } } free(signbits); *nlength = noutchar; if (noutchar >= noutmax) { ffpmsg("encode: output buffer too small"); return(DATA_COMPRESSION_ERR); } return(stat); } /* ######################################################################### */ static int encode64(char *outfile, long *nlength, LONGLONG a[], int nx, int ny, int scale) { /* FILE *outfile; - change outfile to a char array */ /* long * nlength returned length (in bytes) of the encoded array) LONGLONG a[]; input H-transform array (nx,ny) int nx,ny; size of H-transform array int scale; scale factor for digitization */ int nel, nx2, ny2, i, j, k, q, nsign, bits_to_go; LONGLONG vmax[3]; unsigned char nbitplanes[3]; unsigned char *signbits; int stat; noutchar = 0; /* initialize the number of compressed bytes that have been written */ nel = nx*ny; /* * write magic value */ qwrite(outfile, code_magic, sizeof(code_magic)); writeint(outfile, nx); /* size of image */ writeint(outfile, ny); writeint(outfile, scale); /* scale factor for digitization */ /* * write first value of A (sum of all pixels -- the only value * which does not compress well) */ writelonglong(outfile, a[0]); a[0] = 0; /* * allocate array for sign bits and save values, 8 per byte */ signbits = (unsigned char *) calloc(1, (nel+7)/8); if (signbits == (unsigned char *) NULL) { ffpmsg("encode64: insufficient memory"); return(DATA_COMPRESSION_ERR); } nsign = 0; bits_to_go = 8; /* signbits[0] = 0; */ for (i=0; i 0) { /* * positive element, put zero at end of buffer */ signbits[nsign] <<= 1; bits_to_go -= 1; } else if (a[i] < 0) { /* * negative element, shift in a one */ signbits[nsign] <<= 1; signbits[nsign] |= 1; bits_to_go -= 1; /* * replace a by absolute value */ a[i] = -a[i]; } if (bits_to_go == 0) { /* * filled up this byte, go to the next one */ bits_to_go = 8; nsign += 1; /* signbits[nsign] = 0; */ } } if (bits_to_go != 8) { /* * some bits in last element * move bits in last byte to bottom and increment nsign */ signbits[nsign] <<= bits_to_go; nsign += 1; } /* * calculate number of bit planes for 3 quadrants * * quadrant 0=bottom left, 1=bottom right or top left, 2=top right, */ for (q=0; q<3; q++) { vmax[q] = 0; } /* * get maximum absolute value in each quadrant */ nx2 = (nx+1)/2; ny2 = (ny+1)/2; j=0; /* column counter */ k=0; /* row counter */ for (i=0; i=ny2) + (k>=nx2); if (vmax[q] < a[i]) vmax[q] = a[i]; if (++j >= ny) { j = 0; k += 1; } } /* * now calculate number of bits for each quadrant */ /* this is a more efficient way to do this, */ for (q = 0; q < 3; q++) { for (nbitplanes[q] = 0; vmax[q]>0; vmax[q] = vmax[q]>>1, nbitplanes[q]++) ; } /* for (q = 0; q < 3; q++) { nbitplanes[q] = log((float) (vmax[q]+1))/log(2.0)+0.5; if ( (vmax[q]+1) > (((LONGLONG) 1)< 0) { if ( 0 == qwrite(outfile, (char *) signbits, nsign)) { free(signbits); *nlength = noutchar; ffpmsg("encode: output buffer too small"); return(DATA_COMPRESSION_ERR); } } free(signbits); *nlength = noutchar; if (noutchar >= noutmax) { ffpmsg("encode64: output buffer too small"); return(DATA_COMPRESSION_ERR); } return(stat); } /* ######################################################################### */ /* ######################################################################### */ /* Copyright (c) 1993 Association of Universities for Research * in Astronomy. All rights reserved. Produced under National * Aeronautics and Space Administration Contract No. NAS5-26555. */ /* qwrite.c Write binary data * * Programmer: R. White Date: 11 March 1991 */ /* ######################################################################### */ static void writeint(char *outfile, int a) { int i; unsigned char b[4]; /* Write integer A one byte at a time to outfile. * * This is portable from Vax to Sun since it eliminates the * need for byte-swapping. */ for (i=3; i>=0; i--) { b[i] = a & 0x000000ff; a >>= 8; } for (i=0; i<4; i++) qwrite(outfile, (char *) &b[i],1); } /* ######################################################################### */ static void writelonglong(char *outfile, LONGLONG a) { int i; unsigned char b[8]; /* Write integer A one byte at a time to outfile. * * This is portable from Vax to Sun since it eliminates the * need for byte-swapping. */ for (i=7; i>=0; i--) { b[i] = (unsigned char) (a & 0x000000ff); a >>= 8; } for (i=0; i<8; i++) qwrite(outfile, (char *) &b[i],1); } /* ######################################################################### */ static int qwrite(char *file, char buffer[], int n){ /* * write n bytes from buffer into file * returns number of bytes read (=n) if successful, <=0 if not */ if (noutchar + n > noutmax) return(0); /* buffer overflow */ memcpy(&file[noutchar], buffer, n); noutchar += n; return(n); } /* ######################################################################### */ /* ######################################################################### */ /* Copyright (c) 1993 Association of Universities for Research * in Astronomy. All rights reserved. Produced under National * Aeronautics and Space Administration Contract No. NAS5-26555. */ /* doencode.c Encode 2-D array and write stream of characters on outfile * * This version assumes that A is positive. * * Programmer: R. White Date: 7 May 1991 */ /* ######################################################################### */ static int doencode(char *outfile, int a[], int nx, int ny, unsigned char nbitplanes[3]) { /* char *outfile; output data stream int a[]; Array of values to encode int nx,ny; Array dimensions [nx][ny] unsigned char nbitplanes[3]; Number of bit planes in quadrants */ int nx2, ny2, stat; nx2 = (nx+1)/2; ny2 = (ny+1)/2; /* * Initialize bit output */ start_outputing_bits(); /* * write out the bit planes for each quadrant */ stat = qtree_encode(outfile, &a[0], ny, nx2, ny2, nbitplanes[0]); if (!stat) stat = qtree_encode(outfile, &a[ny2], ny, nx2, ny/2, nbitplanes[1]); if (!stat) stat = qtree_encode(outfile, &a[ny*nx2], ny, nx/2, ny2, nbitplanes[1]); if (!stat) stat = qtree_encode(outfile, &a[ny*nx2+ny2], ny, nx/2, ny/2, nbitplanes[2]); /* * Add zero as an EOF symbol */ output_nybble(outfile, 0); done_outputing_bits(outfile); return(stat); } /* ######################################################################### */ static int doencode64(char *outfile, LONGLONG a[], int nx, int ny, unsigned char nbitplanes[3]) { /* char *outfile; output data stream LONGLONG a[]; Array of values to encode int nx,ny; Array dimensions [nx][ny] unsigned char nbitplanes[3]; Number of bit planes in quadrants */ int nx2, ny2, stat; nx2 = (nx+1)/2; ny2 = (ny+1)/2; /* * Initialize bit output */ start_outputing_bits(); /* * write out the bit planes for each quadrant */ stat = qtree_encode64(outfile, &a[0], ny, nx2, ny2, nbitplanes[0]); if (!stat) stat = qtree_encode64(outfile, &a[ny2], ny, nx2, ny/2, nbitplanes[1]); if (!stat) stat = qtree_encode64(outfile, &a[ny*nx2], ny, nx/2, ny2, nbitplanes[1]); if (!stat) stat = qtree_encode64(outfile, &a[ny*nx2+ny2], ny, nx/2, ny/2, nbitplanes[2]); /* * Add zero as an EOF symbol */ output_nybble(outfile, 0); done_outputing_bits(outfile); return(stat); } /* ######################################################################### */ /* ######################################################################### */ /* Copyright (c) 1993 Association of Universities for Research * in Astronomy. All rights reserved. Produced under National * Aeronautics and Space Administration Contract No. NAS5-26555. */ /* BIT OUTPUT ROUTINES */ static LONGLONG bitcount; /* THE BIT BUFFER */ static int buffer2; /* Bits buffered for output */ static int bits_to_go2; /* Number of bits free in buffer */ /* ######################################################################### */ /* INITIALIZE FOR BIT OUTPUT */ static void start_outputing_bits(void) { buffer2 = 0; /* Buffer is empty to start */ bits_to_go2 = 8; /* with */ bitcount = 0; } /* ######################################################################### */ /* OUTPUT N BITS (N must be <= 8) */ static void output_nbits(char *outfile, int bits, int n) { /* AND mask for the right-most n bits */ static int mask[9] = {0, 1, 3, 7, 15, 31, 63, 127, 255}; /* * insert bits at end of buffer */ buffer2 <<= n; /* buffer2 |= ( bits & ((1<>(-bits_to_go2)) & 0xff); if (noutchar < noutmax) noutchar++; bits_to_go2 += 8; } bitcount += n; } /* ######################################################################### */ /* OUTPUT a 4 bit nybble */ static void output_nybble(char *outfile, int bits) { /* * insert 4 bits at end of buffer */ buffer2 = (buffer2<<4) | ( bits & 15 ); bits_to_go2 -= 4; if (bits_to_go2 <= 0) { /* * buffer2 full, put out top 8 bits */ outfile[noutchar] = ((buffer2>>(-bits_to_go2)) & 0xff); if (noutchar < noutmax) noutchar++; bits_to_go2 += 8; } bitcount += 4; } /* ############################################################################ */ /* OUTPUT array of 4 BITS */ static void output_nnybble(char *outfile, int n, unsigned char array[]) { /* pack the 4 lower bits in each element of the array into the outfile array */ int ii, jj, kk = 0, shift; if (n == 1) { output_nybble(outfile, (int) array[0]); return; } /* forcing byte alignment doesn;t help, and even makes it go slightly slower if (bits_to_go2 != 8) output_nbits(outfile, kk, bits_to_go2); */ if (bits_to_go2 <= 4) { /* just room for 1 nybble; write it out separately */ output_nybble(outfile, array[0]); kk++; /* index to next array element */ if (n == 2) /* only 1 more nybble to write out */ { output_nybble(outfile, (int) array[1]); return; } } /* bits_to_go2 is now in the range 5 - 8 */ shift = 8 - bits_to_go2; /* now write out pairs of nybbles; this does not affect value of bits_to_go2 */ jj = (n - kk) / 2; if (bits_to_go2 == 8) { /* special case if nybbles are aligned on byte boundary */ /* this actually seems to make very little differnece in speed */ buffer2 = 0; for (ii = 0; ii < jj; ii++) { outfile[noutchar] = ((array[kk] & 15)<<4) | (array[kk+1] & 15); kk += 2; noutchar++; } } else { for (ii = 0; ii < jj; ii++) { buffer2 = (buffer2<<8) | ((array[kk] & 15)<<4) | (array[kk+1] & 15); kk += 2; /* buffer2 full, put out top 8 bits */ outfile[noutchar] = ((buffer2>>shift) & 0xff); noutchar++; } } bitcount += (8 * (ii - 1)); /* write out last odd nybble, if present */ if (kk != n) output_nybble(outfile, (int) array[n - 1]); return; } /* ######################################################################### */ /* FLUSH OUT THE LAST BITS */ static void done_outputing_bits(char *outfile) { if(bits_to_go2 < 8) { /* putc(buffer2<nqy) ? nqx : nqy; log2n = (int) (log((float) nqmax)/log(2.0)+0.5); if (nqmax > (1<= 0; bit--) { /* * initial bit buffer */ b = 0; bitbuffer = 0; bits_to_go3 = 0; /* * on first pass copy A to scratch array */ qtree_onebit(a,n,nqx,nqy,scratch,bit); nx = (nqx+1)>>1; ny = (nqy+1)>>1; /* * copy non-zero values to output buffer, which will be written * in reverse order */ if (bufcopy(scratch,nx*ny,buffer,&b,bmax)) { /* * quadtree is expanding data, * change warning code and just fill buffer with bit-map */ write_bdirect(outfile,a,n,nqx,nqy,scratch,bit); goto bitplane_done; } /* * do log2n reductions */ for (k = 1; k>1; ny = (ny+1)>>1; if (bufcopy(scratch,nx*ny,buffer,&b,bmax)) { write_bdirect(outfile,a,n,nqx,nqy,scratch,bit); goto bitplane_done; } } /* * OK, we've got the code in buffer * Write quadtree warning code, then write buffer in reverse order */ output_nybble(outfile,0xF); if (b==0) { if (bits_to_go3>0) { /* * put out the last few bits */ output_nbits(outfile, bitbuffer & ((1<0) { /* * put out the last few bits */ output_nbits(outfile, bitbuffer & ((1<=0; i--) { output_nbits(outfile,buffer[i],8); } } bitplane_done: ; } free(buffer); free(scratch); return(0); } /* ######################################################################### */ static int qtree_encode64(char *outfile, LONGLONG a[], int n, int nqx, int nqy, int nbitplanes) { /* LONGLONG a[]; int n; physical dimension of row in a int nqx; length of row int nqy; length of column (<=n) int nbitplanes; number of bit planes to output */ int log2n, i, k, bit, b, nqmax, nqx2, nqy2, nx, ny; int bmax; /* this potentially needs to be made a 64-bit int to support large arrays */ unsigned char *scratch, *buffer; /* * log2n is log2 of max(nqx,nqy) rounded up to next power of 2 */ nqmax = (nqx>nqy) ? nqx : nqy; log2n = (int) (log((float) nqmax)/log(2.0)+0.5); if (nqmax > (1<= 0; bit--) { /* * initial bit buffer */ b = 0; bitbuffer = 0; bits_to_go3 = 0; /* * on first pass copy A to scratch array */ qtree_onebit64(a,n,nqx,nqy,scratch,bit); nx = (nqx+1)>>1; ny = (nqy+1)>>1; /* * copy non-zero values to output buffer, which will be written * in reverse order */ if (bufcopy(scratch,nx*ny,buffer,&b,bmax)) { /* * quadtree is expanding data, * change warning code and just fill buffer with bit-map */ write_bdirect64(outfile,a,n,nqx,nqy,scratch,bit); goto bitplane_done; } /* * do log2n reductions */ for (k = 1; k>1; ny = (ny+1)>>1; if (bufcopy(scratch,nx*ny,buffer,&b,bmax)) { write_bdirect64(outfile,a,n,nqx,nqy,scratch,bit); goto bitplane_done; } } /* * OK, we've got the code in buffer * Write quadtree warning code, then write buffer in reverse order */ output_nybble(outfile,0xF); if (b==0) { if (bits_to_go3>0) { /* * put out the last few bits */ output_nbits(outfile, bitbuffer & ((1<0) { /* * put out the last few bits */ output_nbits(outfile, bitbuffer & ((1<=0; i--) { output_nbits(outfile,buffer[i],8); } } bitplane_done: ; } free(buffer); free(scratch); return(0); } /* ######################################################################### */ /* * copy non-zero codes from array to buffer */ static int bufcopy(unsigned char a[], int n, unsigned char buffer[], int *b, int bmax) { int i; for (i = 0; i < n; i++) { if (a[i] != 0) { /* * add Huffman code for a[i] to buffer */ bitbuffer |= code[a[i]] << bits_to_go3; bits_to_go3 += ncode[a[i]]; if (bits_to_go3 >= 8) { buffer[*b] = bitbuffer & 0xFF; *b += 1; /* * return warning code if we fill buffer */ if (*b >= bmax) return(1); bitbuffer >>= 8; bits_to_go3 -= 8; } } } return(0); } /* ######################################################################### */ /* * Do first quadtree reduction step on bit BIT of array A. * Results put into B. * */ static void qtree_onebit(int a[], int n, int nx, int ny, unsigned char b[], int bit) { int i, j, k; int b0, b1, b2, b3; int s10, s00; /* * use selected bit to get amount to shift */ b0 = 1<> bit; k += 1; s00 += 2; s10 += 2; } if (j < ny) { /* * row size is odd, do last element in row * s00+1,s10+1 are off edge */ b[k] = ( ((a[s10 ]<<1) & b1) | ((a[s00 ]<<3) & b3) ) >> bit; k += 1; } } if (i < nx) { /* * column size is odd, do last row * s10,s10+1 are off edge */ s00 = n*i; for (j = 0; j> bit; k += 1; s00 += 2; } if (j < ny) { /* * both row and column size are odd, do corner element * s00+1, s10, s10+1 are off edge */ b[k] = ( ((a[s00 ]<<3) & b3) ) >> bit; k += 1; } } } /* ######################################################################### */ /* * Do first quadtree reduction step on bit BIT of array A. * Results put into B. * */ static void qtree_onebit64(LONGLONG a[], int n, int nx, int ny, unsigned char b[], int bit) { int i, j, k; LONGLONG b0, b1, b2, b3; int s10, s00; /* * use selected bit to get amount to shift */ b0 = ((LONGLONG) 1)<> bit); k += 1; s00 += 2; s10 += 2; } if (j < ny) { /* * row size is odd, do last element in row * s00+1,s10+1 are off edge */ b[k] = (unsigned char) (( ((a[s10 ]<<1) & b1) | ((a[s00 ]<<3) & b3) ) >> bit); k += 1; } } if (i < nx) { /* * column size is odd, do last row * s10,s10+1 are off edge */ s00 = n*i; for (j = 0; j> bit); k += 1; s00 += 2; } if (j < ny) { /* * both row and column size are odd, do corner element * s00+1, s10, s10+1 are off edge */ b[k] = (unsigned char) (( ((a[s00 ]<<3) & b3) ) >> bit); k += 1; } } } /* ######################################################################### */ /* * do one quadtree reduction step on array a * results put into b (which may be the same as a) */ static void qtree_reduce(unsigned char a[], int n, int nx, int ny, unsigned char b[]) { int i, j, k; int s10, s00; k = 0; /* k is index of b[i/2,j/2] */ for (i = 0; i #include #include #include #include "fitsio2.h" /* WDP added test to see if min and max are already defined */ #ifndef min #define min(a,b) (((a)<(b))?(a):(b)) #endif #ifndef max #define max(a,b) (((a)>(b))?(a):(b)) #endif static long nextchar; static int decode(unsigned char *infile, int *a, int *nx, int *ny, int *scale); static int decode64(unsigned char *infile, LONGLONG *a, int *nx, int *ny, int *scale); static int hinv(int a[], int nx, int ny, int smooth ,int scale); static int hinv64(LONGLONG a[], int nx, int ny, int smooth ,int scale); static void undigitize(int a[], int nx, int ny, int scale); static void undigitize64(LONGLONG a[], int nx, int ny, int scale); static void unshuffle(int a[], int n, int n2, int tmp[]); static void unshuffle64(LONGLONG a[], int n, int n2, LONGLONG tmp[]); static void hsmooth(int a[], int nxtop, int nytop, int ny, int scale); static void hsmooth64(LONGLONG a[], int nxtop, int nytop, int ny, int scale); static void qread(unsigned char *infile,char *a, int n); static int readint(unsigned char *infile); static LONGLONG readlonglong(unsigned char *infile); static int dodecode(unsigned char *infile, int a[], int nx, int ny, unsigned char nbitplanes[3]); static int dodecode64(unsigned char *infile, LONGLONG a[], int nx, int ny, unsigned char nbitplanes[3]); static int qtree_decode(unsigned char *infile, int a[], int n, int nqx, int nqy, int nbitplanes); static int qtree_decode64(unsigned char *infile, LONGLONG a[], int n, int nqx, int nqy, int nbitplanes); static void start_inputing_bits(void); static int input_bit(unsigned char *infile); static int input_nbits(unsigned char *infile, int n); /* make input_nybble a separate routine, for added effiency */ /* #define input_nybble(infile) input_nbits(infile,4) */ static int input_nybble(unsigned char *infile); static int input_nnybble(unsigned char *infile, int n, unsigned char *array); static void qtree_expand(unsigned char *infile, unsigned char a[], int nx, int ny, unsigned char b[]); static void qtree_bitins(unsigned char a[], int nx, int ny, int b[], int n, int bit); static void qtree_bitins64(unsigned char a[], int nx, int ny, LONGLONG b[], int n, int bit); static void qtree_copy(unsigned char a[], int nx, int ny, unsigned char b[], int n); static void read_bdirect(unsigned char *infile, int a[], int n, int nqx, int nqy, unsigned char scratch[], int bit); static void read_bdirect64(unsigned char *infile, LONGLONG a[], int n, int nqx, int nqy, unsigned char scratch[], int bit); static int input_huffman(unsigned char *infile); /* ---------------------------------------------------------------------- */ int fits_hdecompress(unsigned char *input, int smooth, int *a, int *ny, int *nx, int *scale, int *status) { /* decompress the input byte stream using the H-compress algorithm input - input array of compressed bytes a - pre-allocated array to hold the output uncompressed image nx - returned X axis size ny - returned Y axis size NOTE: the nx and ny dimensions as defined within this code are reversed from the usual FITS notation. ny is the fastest varying dimension, which is usually considered the X axis in the FITS image display */ int stat; if (*status > 0) return(*status); /* decode the input array */ FFLOCK; /* decode uses the nextchar global variable */ stat = decode(input, a, nx, ny, scale); FFUNLOCK; *status = stat; if (stat) return(*status); /* * Un-Digitize */ undigitize(a, *nx, *ny, *scale); /* * Inverse H-transform */ stat = hinv(a, *nx, *ny, smooth, *scale); *status = stat; return(*status); } /* ---------------------------------------------------------------------- */ int fits_hdecompress64(unsigned char *input, int smooth, LONGLONG *a, int *ny, int *nx, int *scale, int *status) { /* decompress the input byte stream using the H-compress algorithm input - input array of compressed bytes a - pre-allocated array to hold the output uncompressed image nx - returned X axis size ny - returned Y axis size NOTE: the nx and ny dimensions as defined within this code are reversed from the usual FITS notation. ny is the fastest varying dimension, which is usually considered the X axis in the FITS image display */ int stat, *iarray, ii, nval; if (*status > 0) return(*status); /* decode the input array */ FFLOCK; /* decode uses the nextchar global variable */ stat = decode64(input, a, nx, ny, scale); FFUNLOCK; *status = stat; if (stat) return(*status); /* * Un-Digitize */ undigitize64(a, *nx, *ny, *scale); /* * Inverse H-transform */ stat = hinv64(a, *nx, *ny, smooth, *scale); *status = stat; /* pack the I*8 values back into an I*4 array */ iarray = (int *) a; nval = (*nx) * (*ny); for (ii = 0; ii < nval; ii++) iarray[ii] = (int) a[ii]; return(*status); } /* ############################################################################ */ /* ############################################################################ */ /* Copyright (c) 1993 Association of Universities for Research * in Astronomy. All rights reserved. Produced under National * Aeronautics and Space Administration Contract No. NAS5-26555. */ /* hinv.c Inverse H-transform of NX x NY integer image * * Programmer: R. White Date: 23 July 1993 */ /* ############################################################################ */ static int hinv(int a[], int nx, int ny, int smooth ,int scale) /* int smooth; 0 for no smoothing, else smooth during inversion int scale; used if smoothing is specified */ { int nmax, log2n, i, j, k; int nxtop,nytop,nxf,nyf,c; int oddx,oddy; int shift, bit0, bit1, bit2, mask0, mask1, mask2, prnd0, prnd1, prnd2, nrnd0, nrnd1, nrnd2, lowbit0, lowbit1; int h0, hx, hy, hc; int s10, s00; int *tmp; /* * log2n is log2 of max(nx,ny) rounded up to next power of 2 */ nmax = (nx>ny) ? nx : ny; log2n = (int) (log((float) nmax)/log(2.0)+0.5); if ( nmax > (1<> 1; prnd1 = bit1 >> 1; prnd2 = bit2 >> 1; nrnd0 = prnd0 - 1; nrnd1 = prnd1 - 1; nrnd2 = prnd2 - 1; /* * round h0 to multiple of bit2 */ a[0] = (a[0] + ((a[0] >= 0) ? prnd2 : nrnd2)) & mask2; /* * do log2n expansions * * We're indexing a as a 2-D array with dimensions (nx,ny). */ nxtop = 1; nytop = 1; nxf = nx; nyf = ny; c = 1<=0; k--) { /* * this somewhat cryptic code generates the sequence * ntop[k-1] = (ntop[k]+1)/2, where ntop[log2n] = n */ c = c>>1; nxtop = nxtop<<1; nytop = nytop<<1; if (nxf <= c) { nxtop -= 1; } else { nxf -= c; } if (nyf <= c) { nytop -= 1; } else { nyf -= c; } /* * double shift and fix nrnd0 (because prnd0=0) on last pass */ if (k == 0) { nrnd0 = 0; shift = 2; } /* * unshuffle in each dimension to interleave coefficients */ for (i = 0; i= 0) ? prnd1 : nrnd1)) & mask1; hy = (hy + ((hy >= 0) ? prnd1 : nrnd1)) & mask1; hc = (hc + ((hc >= 0) ? prnd0 : nrnd0)) & mask0; /* * propagate bit0 of hc to hx,hy */ lowbit0 = hc & bit0; hx = (hx >= 0) ? (hx - lowbit0) : (hx + lowbit0); hy = (hy >= 0) ? (hy - lowbit0) : (hy + lowbit0); /* * Propagate bits 0 and 1 of hc,hx,hy to h0. * This could be simplified if we assume h0>0, but then * the inversion would not be lossless for images with * negative pixels. */ lowbit1 = (hc ^ hx ^ hy) & bit1; h0 = (h0 >= 0) ? (h0 + lowbit0 - lowbit1) : (h0 + ((lowbit0 == 0) ? lowbit1 : (lowbit0-lowbit1))); /* * Divide sums by 2 (4 last time) */ a[s10+1] = (h0 + hx + hy + hc) >> shift; a[s10 ] = (h0 + hx - hy - hc) >> shift; a[s00+1] = (h0 - hx + hy - hc) >> shift; a[s00 ] = (h0 - hx - hy + hc) >> shift; s00 += 2; s10 += 2; } if (oddy) { /* * do last element in row if row length is odd * s00+1, s10+1 are off edge */ h0 = a[s00 ]; hx = a[s10 ]; hx = ((hx >= 0) ? (hx+prnd1) : (hx+nrnd1)) & mask1; lowbit1 = hx & bit1; h0 = (h0 >= 0) ? (h0 - lowbit1) : (h0 + lowbit1); a[s10 ] = (h0 + hx) >> shift; a[s00 ] = (h0 - hx) >> shift; } } if (oddx) { /* * do last row if column length is odd * s10, s10+1 are off edge */ s00 = ny*i; for (j = 0; j= 0) ? (hy+prnd1) : (hy+nrnd1)) & mask1; lowbit1 = hy & bit1; h0 = (h0 >= 0) ? (h0 - lowbit1) : (h0 + lowbit1); a[s00+1] = (h0 + hy) >> shift; a[s00 ] = (h0 - hy) >> shift; s00 += 2; } if (oddy) { /* * do corner element if both row and column lengths are odd * s00+1, s10, s10+1 are off edge */ h0 = a[s00 ]; a[s00 ] = h0 >> shift; } } /* * divide all the masks and rounding values by 2 */ bit2 = bit1; bit1 = bit0; bit0 = bit0 >> 1; mask1 = mask0; mask0 = mask0 >> 1; prnd1 = prnd0; prnd0 = prnd0 >> 1; nrnd1 = nrnd0; nrnd0 = prnd0 - 1; } free(tmp); return(0); } /* ############################################################################ */ static int hinv64(LONGLONG a[], int nx, int ny, int smooth ,int scale) /* int smooth; 0 for no smoothing, else smooth during inversion int scale; used if smoothing is specified */ { int nmax, log2n, i, j, k; int nxtop,nytop,nxf,nyf,c; int oddx,oddy; int shift; LONGLONG mask0, mask1, mask2, prnd0, prnd1, prnd2, bit0, bit1, bit2; LONGLONG nrnd0, nrnd1, nrnd2, lowbit0, lowbit1; LONGLONG h0, hx, hy, hc; int s10, s00; LONGLONG *tmp; /* * log2n is log2 of max(nx,ny) rounded up to next power of 2 */ nmax = (nx>ny) ? nx : ny; log2n = (int) (log((float) nmax)/log(2.0)+0.5); if ( nmax > (1<> 1; prnd1 = bit1 >> 1; prnd2 = bit2 >> 1; nrnd0 = prnd0 - 1; nrnd1 = prnd1 - 1; nrnd2 = prnd2 - 1; /* * round h0 to multiple of bit2 */ a[0] = (a[0] + ((a[0] >= 0) ? prnd2 : nrnd2)) & mask2; /* * do log2n expansions * * We're indexing a as a 2-D array with dimensions (nx,ny). */ nxtop = 1; nytop = 1; nxf = nx; nyf = ny; c = 1<=0; k--) { /* * this somewhat cryptic code generates the sequence * ntop[k-1] = (ntop[k]+1)/2, where ntop[log2n] = n */ c = c>>1; nxtop = nxtop<<1; nytop = nytop<<1; if (nxf <= c) { nxtop -= 1; } else { nxf -= c; } if (nyf <= c) { nytop -= 1; } else { nyf -= c; } /* * double shift and fix nrnd0 (because prnd0=0) on last pass */ if (k == 0) { nrnd0 = 0; shift = 2; } /* * unshuffle in each dimension to interleave coefficients */ for (i = 0; i= 0) ? prnd1 : nrnd1)) & mask1; hy = (hy + ((hy >= 0) ? prnd1 : nrnd1)) & mask1; hc = (hc + ((hc >= 0) ? prnd0 : nrnd0)) & mask0; /* * propagate bit0 of hc to hx,hy */ lowbit0 = hc & bit0; hx = (hx >= 0) ? (hx - lowbit0) : (hx + lowbit0); hy = (hy >= 0) ? (hy - lowbit0) : (hy + lowbit0); /* * Propagate bits 0 and 1 of hc,hx,hy to h0. * This could be simplified if we assume h0>0, but then * the inversion would not be lossless for images with * negative pixels. */ lowbit1 = (hc ^ hx ^ hy) & bit1; h0 = (h0 >= 0) ? (h0 + lowbit0 - lowbit1) : (h0 + ((lowbit0 == 0) ? lowbit1 : (lowbit0-lowbit1))); /* * Divide sums by 2 (4 last time) */ a[s10+1] = (h0 + hx + hy + hc) >> shift; a[s10 ] = (h0 + hx - hy - hc) >> shift; a[s00+1] = (h0 - hx + hy - hc) >> shift; a[s00 ] = (h0 - hx - hy + hc) >> shift; s00 += 2; s10 += 2; } if (oddy) { /* * do last element in row if row length is odd * s00+1, s10+1 are off edge */ h0 = a[s00 ]; hx = a[s10 ]; hx = ((hx >= 0) ? (hx+prnd1) : (hx+nrnd1)) & mask1; lowbit1 = hx & bit1; h0 = (h0 >= 0) ? (h0 - lowbit1) : (h0 + lowbit1); a[s10 ] = (h0 + hx) >> shift; a[s00 ] = (h0 - hx) >> shift; } } if (oddx) { /* * do last row if column length is odd * s10, s10+1 are off edge */ s00 = ny*i; for (j = 0; j= 0) ? (hy+prnd1) : (hy+nrnd1)) & mask1; lowbit1 = hy & bit1; h0 = (h0 >= 0) ? (h0 - lowbit1) : (h0 + lowbit1); a[s00+1] = (h0 + hy) >> shift; a[s00 ] = (h0 - hy) >> shift; s00 += 2; } if (oddy) { /* * do corner element if both row and column lengths are odd * s00+1, s10, s10+1 are off edge */ h0 = a[s00 ]; a[s00 ] = h0 >> shift; } } /* * divide all the masks and rounding values by 2 */ bit2 = bit1; bit1 = bit0; bit0 = bit0 >> 1; mask1 = mask0; mask0 = mask0 >> 1; prnd1 = prnd0; prnd0 = prnd0 >> 1; nrnd1 = nrnd0; nrnd0 = prnd0 - 1; } free(tmp); return(0); } /* ############################################################################ */ static void unshuffle(int a[], int n, int n2, int tmp[]) /* int a[]; array to shuffle int n; number of elements to shuffle int n2; second dimension int tmp[]; scratch storage */ { int i; int nhalf; int *p1, *p2, *pt; /* * copy 2nd half of array to tmp */ nhalf = (n+1)>>1; pt = tmp; p1 = &a[n2*nhalf]; /* pointer to a[i] */ for (i=nhalf; i= 0; i--) { *p1 = *p2; p2 -= n2; p1 -= (n2+n2); } /* * now distribute 2nd half of array (in tmp) to odd elements */ pt = tmp; p1 = &a[n2]; /* pointer to a[i] */ for (i=1; i>1; pt = tmp; p1 = &a[n2*nhalf]; /* pointer to a[i] */ for (i=nhalf; i= 0; i--) { *p1 = *p2; p2 -= n2; p1 -= (n2+n2); } /* * now distribute 2nd half of array (in tmp) to odd elements */ pt = tmp; p1 = &a[n2]; /* pointer to a[i] */ for (i=1; i> 1); if (smax <= 0) return; ny2 = ny << 1; /* * We're indexing a as a 2-D array with dimensions (nxtop,ny) of which * only (nxtop,nytop) are used. The coefficients on the edge of the * array are not adjusted (which is why the loops below start at 2 * instead of 0 and end at nxtop-2 instead of nxtop.) */ /* * Adjust x difference hx */ for (i = 2; i=0, dmin<=0. */ if (dmin < dmax) { diff = max( min(diff, dmax), dmin); /* * Compute change in slope limited to range +/- smax. * Careful with rounding negative numbers when using * shift for divide by 8. */ s = diff-(a[s10]<<3); s = (s>=0) ? (s>>3) : ((s+7)>>3) ; s = max( min(s, smax), -smax); a[s10] = a[s10]+s; } s00 += 2; s10 += 2; } } /* * Adjust y difference hy */ for (i = 0; i=0) ? (s>>3) : ((s+7)>>3) ; s = max( min(s, smax), -smax); a[s00+1] = a[s00+1]+s; } s00 += 2; s10 += 2; } } /* * Adjust curvature difference hc */ for (i = 2; i=0, dmin<=0. */ if (dmin < dmax) { diff = max( min(diff, dmax), dmin); /* * Compute change in slope limited to range +/- smax. * Careful with rounding negative numbers when using * shift for divide by 64. */ s = diff-(a[s10+1]<<6); s = (s>=0) ? (s>>6) : ((s+63)>>6) ; s = max( min(s, smax), -smax); a[s10+1] = a[s10+1]+s; } s00 += 2; s10 += 2; } } } /* ############################################################################ */ static void hsmooth64(LONGLONG a[], int nxtop, int nytop, int ny, int scale) /* LONGLONG a[]; array of H-transform coefficients int nxtop,nytop; size of coefficient block to use int ny; actual 1st dimension of array int scale; truncation scale factor that was used */ { int i, j; int ny2, s10, s00; LONGLONG hm, h0, hp, hmm, hpm, hmp, hpp, hx2, hy2, diff, dmax, dmin, s, smax, m1, m2; /* * Maximum change in coefficients is determined by scale factor. * Since we rounded during division (see digitize.c), the biggest * permitted change is scale/2. */ smax = (scale >> 1); if (smax <= 0) return; ny2 = ny << 1; /* * We're indexing a as a 2-D array with dimensions (nxtop,ny) of which * only (nxtop,nytop) are used. The coefficients on the edge of the * array are not adjusted (which is why the loops below start at 2 * instead of 0 and end at nxtop-2 instead of nxtop.) */ /* * Adjust x difference hx */ for (i = 2; i=0, dmin<=0. */ if (dmin < dmax) { diff = max( min(diff, dmax), dmin); /* * Compute change in slope limited to range +/- smax. * Careful with rounding negative numbers when using * shift for divide by 8. */ s = diff-(a[s10]<<3); s = (s>=0) ? (s>>3) : ((s+7)>>3) ; s = max( min(s, smax), -smax); a[s10] = a[s10]+s; } s00 += 2; s10 += 2; } } /* * Adjust y difference hy */ for (i = 0; i=0) ? (s>>3) : ((s+7)>>3) ; s = max( min(s, smax), -smax); a[s00+1] = a[s00+1]+s; } s00 += 2; s10 += 2; } } /* * Adjust curvature difference hc */ for (i = 2; i=0, dmin<=0. */ if (dmin < dmax) { diff = max( min(diff, dmax), dmin); /* * Compute change in slope limited to range +/- smax. * Careful with rounding negative numbers when using * shift for divide by 64. */ s = diff-(a[s10+1]<<6); s = (s>=0) ? (s>>6) : ((s+63)>>6) ; s = max( min(s, smax), -smax); a[s10+1] = a[s10+1]+s; } s00 += 2; s10 += 2; } } } /* ############################################################################ */ /* ############################################################################ */ /* Copyright (c) 1993 Association of Universities for Research * in Astronomy. All rights reserved. Produced under National * Aeronautics and Space Administration Contract No. NAS5-26555. */ /* undigitize.c undigitize H-transform * * Programmer: R. White Date: 9 May 1991 */ /* ############################################################################ */ static void undigitize(int a[], int nx, int ny, int scale) { int *p; /* * multiply by scale */ if (scale <= 1) return; for (p=a; p <= &a[nx*ny-1]; p++) *p = (*p)*scale; } /* ############################################################################ */ static void undigitize64(LONGLONG a[], int nx, int ny, int scale) { LONGLONG *p, scale64; /* * multiply by scale */ if (scale <= 1) return; scale64 = (LONGLONG) scale; /* use a 64-bit int for efficiency in the big loop */ for (p=a; p <= &a[nx*ny-1]; p++) *p = (*p)*scale64; } /* ############################################################################ */ /* ############################################################################ */ /* Copyright (c) 1993 Association of Universities for Research * in Astronomy. All rights reserved. Produced under National * Aeronautics and Space Administration Contract No. NAS5-26555. */ /* decode.c read codes from infile and construct array * * Programmer: R. White Date: 2 February 1994 */ static char code_magic[2] = { (char)0xDD, (char)0x99 }; /* ############################################################################ */ static int decode(unsigned char *infile, int *a, int *nx, int *ny, int *scale) /* char *infile; input file int *a; address of output array [nx][ny] int *nx,*ny; size of output array int *scale; scale factor for digitization */ { LONGLONG sumall; int stat; unsigned char nbitplanes[3]; char tmagic[2]; /* initialize the byte read position to the beginning of the array */; nextchar = 0; /* * File starts either with special 2-byte magic code or with * FITS keyword "SIMPLE =" */ qread(infile, tmagic, sizeof(tmagic)); /* * check for correct magic code value */ if (memcmp(tmagic,code_magic,sizeof(code_magic)) != 0) { ffpmsg("bad file format"); return(DATA_DECOMPRESSION_ERR); } *nx =readint(infile); /* x size of image */ *ny =readint(infile); /* y size of image */ *scale=readint(infile); /* scale factor for digitization */ /* sum of all pixels */ sumall=readlonglong(infile); /* # bits in quadrants */ qread(infile, (char *) nbitplanes, sizeof(nbitplanes)); stat = dodecode(infile, a, *nx, *ny, nbitplanes); /* * put sum of all pixels back into pixel 0 */ a[0] = (int) sumall; return(stat); } /* ############################################################################ */ static int decode64(unsigned char *infile, LONGLONG *a, int *nx, int *ny, int *scale) /* char *infile; input file LONGLONG *a; address of output array [nx][ny] int *nx,*ny; size of output array int *scale; scale factor for digitization */ { int stat; LONGLONG sumall; unsigned char nbitplanes[3]; char tmagic[2]; /* initialize the byte read position to the beginning of the array */; nextchar = 0; /* * File starts either with special 2-byte magic code or with * FITS keyword "SIMPLE =" */ qread(infile, tmagic, sizeof(tmagic)); /* * check for correct magic code value */ if (memcmp(tmagic,code_magic,sizeof(code_magic)) != 0) { ffpmsg("bad file format"); return(DATA_DECOMPRESSION_ERR); } *nx =readint(infile); /* x size of image */ *ny =readint(infile); /* y size of image */ *scale=readint(infile); /* scale factor for digitization */ /* sum of all pixels */ sumall=readlonglong(infile); /* # bits in quadrants */ qread(infile, (char *) nbitplanes, sizeof(nbitplanes)); stat = dodecode64(infile, a, *nx, *ny, nbitplanes); /* * put sum of all pixels back into pixel 0 */ a[0] = sumall; return(stat); } /* ############################################################################ */ /* ############################################################################ */ /* Copyright (c) 1993 Association of Universities for Research * in Astronomy. All rights reserved. Produced under National * Aeronautics and Space Administration Contract No. NAS5-26555. */ /* dodecode.c Decode stream of characters on infile and return array * * This version encodes the different quadrants separately * * Programmer: R. White Date: 9 May 1991 */ /* ############################################################################ */ static int dodecode(unsigned char *infile, int a[], int nx, int ny, unsigned char nbitplanes[3]) /* int a[]; int nx,ny; Array dimensions are [nx][ny] unsigned char nbitplanes[3]; Number of bit planes in quadrants */ { int i, nel, nx2, ny2, stat; nel = nx*ny; nx2 = (nx+1)/2; ny2 = (ny+1)/2; /* * initialize a to zero */ for (i=0; inqy) ? nqx : nqy; log2n = (int) (log((float) nqmax)/log(2.0)+0.5); if (nqmax > (1<= 0; bit--) { /* * Was bitplane was quadtree-coded or written directly? */ b = input_nybble(infile); if(b == 0) { /* * bit map was written directly */ read_bdirect(infile,a,n,nqx,nqy,scratch,bit); } else if (b != 0xf) { ffpmsg("qtree_decode: bad format code"); return(DATA_DECOMPRESSION_ERR); } else { /* * bitmap was quadtree-coded, do log2n expansions * * read first code */ scratch[0] = input_huffman(infile); /* * now do log2n expansions, reading codes from file as necessary */ nx = 1; ny = 1; nfx = nqx; nfy = nqy; c = 1<>1; nx = nx<<1; ny = ny<<1; if (nfx <= c) { nx -= 1; } else { nfx -= c; } if (nfy <= c) { ny -= 1; } else { nfy -= c; } qtree_expand(infile,scratch,nx,ny,scratch); } /* * now copy last set of 4-bit codes to bitplane bit of array a */ qtree_bitins(scratch,nqx,nqy,a,n,bit); } } free(scratch); return(0); } /* ############################################################################ */ static int qtree_decode64(unsigned char *infile, LONGLONG a[], int n, int nqx, int nqy, int nbitplanes) /* char *infile; LONGLONG a[]; a is 2-D array with dimensions (n,n) int n; length of full row in a int nqx; partial length of row to decode int nqy; partial length of column (<=n) int nbitplanes; number of bitplanes to decode */ { int log2n, k, bit, b, nqmax; int nx,ny,nfx,nfy,c; int nqx2, nqy2; unsigned char *scratch; /* * log2n is log2 of max(nqx,nqy) rounded up to next power of 2 */ nqmax = (nqx>nqy) ? nqx : nqy; log2n = (int) (log((float) nqmax)/log(2.0)+0.5); if (nqmax > (1<= 0; bit--) { /* * Was bitplane was quadtree-coded or written directly? */ b = input_nybble(infile); if(b == 0) { /* * bit map was written directly */ read_bdirect64(infile,a,n,nqx,nqy,scratch,bit); } else if (b != 0xf) { ffpmsg("qtree_decode64: bad format code"); return(DATA_DECOMPRESSION_ERR); } else { /* * bitmap was quadtree-coded, do log2n expansions * * read first code */ scratch[0] = input_huffman(infile); /* * now do log2n expansions, reading codes from file as necessary */ nx = 1; ny = 1; nfx = nqx; nfy = nqy; c = 1<>1; nx = nx<<1; ny = ny<<1; if (nfx <= c) { nx -= 1; } else { nfx -= c; } if (nfy <= c) { ny -= 1; } else { nfy -= c; } qtree_expand(infile,scratch,nx,ny,scratch); } /* * now copy last set of 4-bit codes to bitplane bit of array a */ qtree_bitins64(scratch,nqx,nqy,a,n,bit); } } free(scratch); return(0); } /* ############################################################################ */ /* * do one quadtree expansion step on array a[(nqx+1)/2,(nqy+1)/2] * results put into b[nqx,nqy] (which may be the same as a) */ static void qtree_expand(unsigned char *infile, unsigned char a[], int nx, int ny, unsigned char b[]) { int i; /* * first copy a to b, expanding each 4-bit value */ qtree_copy(a,nx,ny,b,ny); /* * now read new 4-bit values into b for each non-zero element */ for (i = nx*ny-1; i >= 0; i--) { if (b[i]) b[i] = input_huffman(infile); } } /* ############################################################################ */ /* * copy 4-bit values from a[(nx+1)/2,(ny+1)/2] to b[nx,ny], expanding * each value to 2x2 pixels * a,b may be same array */ static void qtree_copy(unsigned char a[], int nx, int ny, unsigned char b[], int n) /* int n; declared y dimension of b */ { int i, j, k, nx2, ny2; int s00, s10; /* * first copy 4-bit values to b * start at end in case a,b are same array */ nx2 = (nx+1)/2; ny2 = (ny+1)/2; k = ny2*(nx2-1)+ny2-1; /* k is index of a[i,j] */ for (i = nx2-1; i >= 0; i--) { s00 = 2*(n*i+ny2-1); /* s00 is index of b[2*i,2*j] */ for (j = ny2-1; j >= 0; j--) { b[s00] = a[k]; k -= 1; s00 -= 2; } } /* * now expand each 2x2 block */ for (i = 0; i>1) & 1; b[s00+1] = (b[s00]>>2) & 1; b[s00 ] = (b[s00]>>3) & 1; */ s00 += 2; s10 += 2; } if (j < ny) { /* * row size is odd, do last element in row * s00+1, s10+1 are off edge */ /* not worth converting this to use 16 case statements */ b[s10 ] = (b[s00]>>1) & 1; b[s00 ] = (b[s00]>>3) & 1; } } if (i < nx) { /* * column size is odd, do last row * s10, s10+1 are off edge */ s00 = n*i; for (j = 0; j>2) & 1; b[s00 ] = (b[s00]>>3) & 1; s00 += 2; } if (j < ny) { /* * both row and column size are odd, do corner element * s00+1, s10, s10+1 are off edge */ /* not worth converting this to use 16 case statements */ b[s00 ] = (b[s00]>>3) & 1; } } } /* ############################################################################ */ /* * Copy 4-bit values from a[(nx+1)/2,(ny+1)/2] to b[nx,ny], expanding * each value to 2x2 pixels and inserting into bitplane BIT of B. * A,B may NOT be same array (it wouldn't make sense to be inserting * bits into the same array anyway.) */ static void qtree_bitins(unsigned char a[], int nx, int ny, int b[], int n, int bit) /* int n; declared y dimension of b */ { int i, j, k; int s00; int plane_val; plane_val = 1 << bit; /* * expand each 2x2 block */ k = 0; /* k is index of a[i/2,j/2] */ for (i = 0; i>1) & 1) << bit; b[s00+1] |= ((a[k]>>2) & 1) << bit; b[s00 ] |= ((a[k]>>3) & 1) << bit; */ s00 += 2; /* s10 += 2; */ k += 1; } if (j < ny) { /* * row size is odd, do last element in row * s00+1, s10+1 are off edge */ switch (a[k]) { case(0): break; case(1): break; case(2): b[s00+n ] |= plane_val; break; case(3): b[s00+n ] |= plane_val; break; case(4): break; case(5): break; case(6): b[s00+n ] |= plane_val; break; case(7): b[s00+n ] |= plane_val; break; case(8): b[s00 ] |= plane_val; break; case(9): b[s00 ] |= plane_val; break; case(10): b[s00+n ] |= plane_val; b[s00 ] |= plane_val; break; case(11): b[s00+n ] |= plane_val; b[s00 ] |= plane_val; break; case(12): b[s00 ] |= plane_val; break; case(13): b[s00 ] |= plane_val; break; case(14): b[s00+n ] |= plane_val; b[s00 ] |= plane_val; break; case(15): b[s00+n ] |= plane_val; b[s00 ] |= plane_val; break; } /* b[s10 ] |= ((a[k]>>1) & 1) << bit; b[s00 ] |= ((a[k]>>3) & 1) << bit; */ k += 1; } } if (i < nx) { /* * column size is odd, do last row * s10, s10+1 are off edge */ s00 = n*i; for (j = 0; j>2) & 1) << bit; b[s00 ] |= ((a[k]>>3) & 1) << bit; */ s00 += 2; k += 1; } if (j < ny) { /* * both row and column size are odd, do corner element * s00+1, s10, s10+1 are off edge */ switch (a[k]) { case(0): break; case(1): break; case(2): break; case(3): break; case(4): break; case(5): break; case(6): break; case(7): break; case(8): b[s00 ] |= plane_val; break; case(9): b[s00 ] |= plane_val; break; case(10): b[s00 ] |= plane_val; break; case(11): b[s00 ] |= plane_val; break; case(12): b[s00 ] |= plane_val; break; case(13): b[s00 ] |= plane_val; break; case(14): b[s00 ] |= plane_val; break; case(15): b[s00 ] |= plane_val; break; } /* b[s00 ] |= ((a[k]>>3) & 1) << bit; */ k += 1; } } } /* ############################################################################ */ /* * Copy 4-bit values from a[(nx+1)/2,(ny+1)/2] to b[nx,ny], expanding * each value to 2x2 pixels and inserting into bitplane BIT of B. * A,B may NOT be same array (it wouldn't make sense to be inserting * bits into the same array anyway.) */ static void qtree_bitins64(unsigned char a[], int nx, int ny, LONGLONG b[], int n, int bit) /* int n; declared y dimension of b */ { int i, j, k; int s00; LONGLONG plane_val; plane_val = ((LONGLONG) 1) << bit; /* * expand each 2x2 block */ k = 0; /* k is index of a[i/2,j/2] */ for (i = 0; i>1) & 1) << bit; b[s00+1] |= ((((LONGLONG)a[k])>>2) & 1) << bit; b[s00 ] |= ((((LONGLONG)a[k])>>3) & 1) << bit; */ s00 += 2; /* s10 += 2; */ k += 1; } if (j < ny) { /* * row size is odd, do last element in row * s00+1, s10+1 are off edge */ switch (a[k]) { case(0): break; case(1): break; case(2): b[s00+n ] |= plane_val; break; case(3): b[s00+n ] |= plane_val; break; case(4): break; case(5): break; case(6): b[s00+n ] |= plane_val; break; case(7): b[s00+n ] |= plane_val; break; case(8): b[s00 ] |= plane_val; break; case(9): b[s00 ] |= plane_val; break; case(10): b[s00+n ] |= plane_val; b[s00 ] |= plane_val; break; case(11): b[s00+n ] |= plane_val; b[s00 ] |= plane_val; break; case(12): b[s00 ] |= plane_val; break; case(13): b[s00 ] |= plane_val; break; case(14): b[s00+n ] |= plane_val; b[s00 ] |= plane_val; break; case(15): b[s00+n ] |= plane_val; b[s00 ] |= plane_val; break; } /* b[s10 ] |= ((((LONGLONG)a[k])>>1) & 1) << bit; b[s00 ] |= ((((LONGLONG)a[k])>>3) & 1) << bit; */ k += 1; } } if (i < nx) { /* * column size is odd, do last row * s10, s10+1 are off edge */ s00 = n*i; for (j = 0; j>2) & 1) << bit; b[s00 ] |= ((((LONGLONG)a[k])>>3) & 1) << bit; */ s00 += 2; k += 1; } if (j < ny) { /* * both row and column size are odd, do corner element * s00+1, s10, s10+1 are off edge */ switch (a[k]) { case(0): break; case(1): break; case(2): break; case(3): break; case(4): break; case(5): break; case(6): break; case(7): break; case(8): b[s00 ] |= plane_val; break; case(9): b[s00 ] |= plane_val; break; case(10): b[s00 ] |= plane_val; break; case(11): b[s00 ] |= plane_val; break; case(12): b[s00 ] |= plane_val; break; case(13): b[s00 ] |= plane_val; break; case(14): b[s00 ] |= plane_val; break; case(15): b[s00 ] |= plane_val; break; } /* b[s00 ] |= ((((LONGLONG)a[k])>>3) & 1) << bit; */ k += 1; } } } /* ############################################################################ */ static void read_bdirect(unsigned char *infile, int a[], int n, int nqx, int nqy, unsigned char scratch[], int bit) { /* * read bit image packed 4 pixels/nybble */ /* int i; for (i = 0; i < ((nqx+1)/2) * ((nqy+1)/2); i++) { scratch[i] = input_nybble(infile); } */ input_nnybble(infile, ((nqx+1)/2) * ((nqy+1)/2), scratch); /* * insert in bitplane BIT of image A */ qtree_bitins(scratch,nqx,nqy,a,n,bit); } /* ############################################################################ */ static void read_bdirect64(unsigned char *infile, LONGLONG a[], int n, int nqx, int nqy, unsigned char scratch[], int bit) { /* * read bit image packed 4 pixels/nybble */ /* int i; for (i = 0; i < ((nqx+1)/2) * ((nqy+1)/2); i++) { scratch[i] = input_nybble(infile); } */ input_nnybble(infile, ((nqx+1)/2) * ((nqy+1)/2), scratch); /* * insert in bitplane BIT of image A */ qtree_bitins64(scratch,nqx,nqy,a,n,bit); } /* ############################################################################ */ /* * Huffman decoding for fixed codes * * Coded values range from 0-15 * * Huffman code values (hex): * * 3e, 00, 01, 08, 02, 09, 1a, 1b, * 03, 1c, 0a, 1d, 0b, 1e, 3f, 0c * * and number of bits in each code: * * 6, 3, 3, 4, 3, 4, 5, 5, * 3, 5, 4, 5, 4, 5, 6, 4 */ static int input_huffman(unsigned char *infile) { int c; /* * get first 3 bits to start */ c = input_nbits(infile,3); if (c < 4) { /* * this is all we need * return 1,2,4,8 for c=0,1,2,3 */ return(1<>bits_to_go) & 1); } /* ############################################################################ */ /* INPUT N BITS (N must be <= 8) */ static int input_nbits(unsigned char *infile, int n) { /* AND mask for retreiving the right-most n bits */ static int mask[9] = {0, 1, 3, 7, 15, 31, 63, 127, 255}; if (bits_to_go < n) { /* * need another byte's worth of bits */ buffer2 = (buffer2<<8) | (int) infile[nextchar]; nextchar++; bits_to_go += 8; } /* * now pick off the first n bits */ bits_to_go -= n; /* there was a slight gain in speed by replacing the following line */ /* return( (buffer2>>bits_to_go) & ((1<>bits_to_go) & (*(mask+n)) ); } /* ############################################################################ */ /* INPUT 4 BITS */ static int input_nybble(unsigned char *infile) { if (bits_to_go < 4) { /* * need another byte's worth of bits */ buffer2 = (buffer2<<8) | (int) infile[nextchar]; nextchar++; bits_to_go += 8; } /* * now pick off the first 4 bits */ bits_to_go -= 4; return( (buffer2>>bits_to_go) & 15 ); } /* ############################################################################ */ /* INPUT array of 4 BITS */ static int input_nnybble(unsigned char *infile, int n, unsigned char array[]) { /* copy n 4-bit nybbles from infile to the lower 4 bits of array */ int ii, kk, shift1, shift2; /* forcing byte alignment doesn;t help, and even makes it go slightly slower if (bits_to_go != 8) input_nbits(infile, bits_to_go); */ if (n == 1) { array[0] = input_nybble(infile); return(0); } if (bits_to_go == 8) { /* already have 2 full nybbles in buffer2, so backspace the infile array to reuse last char */ nextchar--; bits_to_go = 0; } /* bits_to_go now has a value in the range 0 - 7. After adding */ /* another byte, bits_to_go effectively will be in range 8 - 15 */ shift1 = bits_to_go + 4; /* shift1 will be in range 4 - 11 */ shift2 = bits_to_go; /* shift2 will be in range 0 - 7 */ kk = 0; /* special case */ if (bits_to_go == 0) { for (ii = 0; ii < n/2; ii++) { /* * refill the buffer with next byte */ buffer2 = (buffer2<<8) | (int) infile[nextchar]; nextchar++; array[kk] = (int) ((buffer2>>4) & 15); array[kk + 1] = (int) ((buffer2) & 15); /* no shift required */ kk += 2; } } else { for (ii = 0; ii < n/2; ii++) { /* * refill the buffer with next byte */ buffer2 = (buffer2<<8) | (int) infile[nextchar]; nextchar++; array[kk] = (int) ((buffer2>>shift1) & 15); array[kk + 1] = (int) ((buffer2>>shift2) & 15); kk += 2; } } if (ii * 2 != n) { /* have to read last odd byte */ array[n-1] = input_nybble(infile); } return( (buffer2>>bits_to_go) & 15 ); } cfitsio/fitscopy.c0000644000225700000360000000512213246025103014004 0ustar cagordonlhea#include #include "fitsio.h" int main(int argc, char *argv[]) { fitsfile *infptr, *outfptr; /* FITS file pointers defined in fitsio.h */ int status = 0; /* status must always be initialized = 0 */ if (argc != 3) { printf("Usage: fitscopy inputfile outputfile\n"); printf("\n"); printf("Copy an input file to an output file, optionally filtering\n"); printf("the file in the process. This seemingly simple program can\n"); printf("apply powerful filters which transform the input file as\n"); printf("it is being copied. Filters may be used to extract a\n"); printf("subimage from a larger image, select rows from a table,\n"); printf("filter a table with a GTI time extension or a SAO region file,\n"); printf("create or delete columns in a table, create an image by\n"); printf("binning (histogramming) 2 table columns, and convert IRAF\n"); printf("format *.imh or raw binary data files into FITS images.\n"); printf("See the CFITSIO User's Guide for a complete description of\n"); printf("the Extended File Name filtering syntax.\n"); printf("\n"); printf("Examples:\n"); printf("\n"); printf("fitscopy in.fit out.fit (simple file copy)\n"); printf("fitscopy - - (stdin to stdout)\n"); printf("fitscopy in.fit[11:50,21:60] out.fit (copy a subimage)\n"); printf("fitscopy iniraf.imh out.fit (IRAF image to FITS)\n"); printf("fitscopy in.dat[i512,512] out.fit (raw array to FITS)\n"); printf("fitscopy in.fit[events][pi>35] out.fit (copy rows with pi>35)\n"); printf("fitscopy in.fit[events][bin X,Y] out.fit (bin an image) \n"); printf("fitscopy in.fit[events][col x=.9*y] out.fit (new x column)\n"); printf("fitscopy in.fit[events][gtifilter()] out.fit (time filter)\n"); printf("fitscopy in.fit[2][regfilter(\"pow.reg\")] out.fit (spatial filter)\n"); printf("\n"); printf("Note that it may be necessary to enclose the input file name\n"); printf("in single quote characters on the Unix command line.\n"); return(0); } /* Open the input file */ if ( !fits_open_file(&infptr, argv[1], READONLY, &status) ) { /* Create the output file */ if ( !fits_create_file(&outfptr, argv[2], &status) ) { /* copy the previous, current, and following HDUs */ fits_copy_file(infptr, outfptr, 1, 1, 1, &status); fits_close_file(outfptr, &status); } fits_close_file(infptr, &status); } /* if error occured, print out error message */ if (status) fits_report_error(stderr, status); return(status); } cfitsio/fitscore.c0000644000225700000360000113470113246025103013771 0ustar cagordonlhea/* This file, fitscore.c, contains the core set of FITSIO routines. */ /* The FITSIO software was written by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ /* Copyright (Unpublished--all rights reserved under the copyright laws of the United States), U.S. Government as represented by the Administrator of the National Aeronautics and Space Administration. No copyright is claimed in the United States under Title 17, U.S. Code. Permission to freely use, copy, modify, and distribute this software and its documentation without fee is hereby granted, provided that this copyright notice and disclaimer of warranty appears in all copies. DISCLAIMER: THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT SHALL NASA BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT , OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER." */ #include #include #include #include #include #include /* stddef.h is apparently needed to define size_t with some compilers ?? */ #include #include #include "fitsio2.h" #define errmsgsiz 25 #define ESMARKER 27 /* Escape character is used as error stack marker */ #define DelAll 1 /* delete all messages on the error stack */ #define DelMark 2 /* delete newest messages back to and including marker */ #define DelNewest 3 /* delete the newest message from the stack */ #define GetMesg 4 /* pop and return oldest message, ignoring marks */ #define PutMesg 5 /* add a new message to the stack */ #define PutMark 6 /* add a marker to the stack */ #ifdef _REENTRANT /* Fitsio_Lock and Fitsio_Pthread_Status are declared in fitsio2.h. */ pthread_mutex_t Fitsio_Lock; int Fitsio_Pthread_Status = 0; #endif int STREAM_DRIVER = 0; struct lconv *lcxxx; /*--------------------------------------------------------------------------*/ float ffvers(float *version) /* IO - version number */ /* return the current version number of the FITSIO software */ { *version = (float) 3.43; /* Mar 2018 Previous releases: *version = 3.42 Mar 2017 *version = 3.41 Nov 2016 *version = 3.40 Oct 2016 *version = 3.39 Apr 2016 *version = 3.38 Feb 2016 *version = 3.37 3 Jun 2014 *version = 3.36 6 Dec 2013 *version = 3.35 23 May 2013 *version = 3.34 20 Mar 2013 *version = 3.33 14 Feb 2013 *version = 3.32 Oct 2012 *version = 3.31 18 Jul 2012 *version = 3.30 11 Apr 2012 *version = 3.29 22 Sep 2011 *version = 3.28 12 May 2011 *version = 3.27 3 Mar 2011 *version = 3.26 30 Dec 2010 *version = 3.25 9 June 2010 *version = 3.24 26 Jan 2010 *version = 3.23 7 Jan 2010 *version = 3.22 28 Oct 2009 *version = 3.21 24 Sep 2009 *version = 3.20 31 Aug 2009 *version = 3.18 12 May 2009 (beta version) *version = 3.14 18 Mar 2009 *version = 3.13 5 Jan 2009 *version = 3.12 8 Oct 2008 *version = 3.11 19 Sep 2008 *version = 3.10 20 Aug 2008 *version = 3.09 3 Jun 2008 *version = 3.08 15 Apr 2007 (internal release) *version = 3.07 5 Nov 2007 (internal release) *version = 3.06 27 Aug 2007 *version = 3.05 12 Jul 2007 (internal release) *version = 3.03 11 Dec 2006 *version = 3.02 18 Sep 2006 *version = 3.01 May 2006 included in FTOOLS 6.1 release *version = 3.006 20 Feb 2006 *version = 3.005 20 Dec 2005 (beta, in heasoft swift release *version = 3.004 16 Sep 2005 (beta, in heasoft swift release *version = 3.003 28 Jul 2005 (beta, in heasoft swift release *version = 3.002 15 Apr 2005 (beta) *version = 3.001 15 Mar 2005 (beta) released with heasoft 6.0 *version = 3.000 1 Mar 2005 (internal release only) *version = 2.51 2 Dec 2004 *version = 2.50 28 Jul 2004 *version = 2.49 11 Feb 2004 *version = 2.48 28 Jan 2004 *version = 2.470 18 Aug 2003 *version = 2.460 20 May 2003 *version = 2.450 30 Apr 2003 (internal release only) *version = 2.440 8 Jan 2003 *version = 2.430; 4 Nov 2002 *version = 2.420; 19 Jul 2002 *version = 2.410; 22 Apr 2002 used in ftools v5.2 *version = 2.401; 28 Jan 2002 *version = 2.400; 18 Jan 2002 *version = 2.301; 7 Dec 2001 *version = 2.300; 23 Oct 2001 *version = 2.204; 26 Jul 2001 *version = 2.203; 19 Jul 2001 used in ftools v5.1 *version = 2.202; 22 May 2001 *version = 2.201; 15 Mar 2001 *version = 2.200; 26 Jan 2001 *version = 2.100; 26 Sep 2000 *version = 2.037; 6 Jul 2000 *version = 2.036; 1 Feb 2000 *version = 2.035; 7 Dec 1999 (internal release only) *version = 2.034; 23 Nov 1999 *version = 2.033; 17 Sep 1999 *version = 2.032; 25 May 1999 *version = 2.031; 31 Mar 1999 *version = 2.030; 24 Feb 1999 *version = 2.029; 11 Feb 1999 *version = 2.028; 26 Jan 1999 *version = 2.027; 12 Jan 1999 *version = 2.026; 23 Dec 1998 *version = 2.025; 1 Dec 1998 *version = 2.024; 9 Nov 1998 *version = 2.023; 1 Nov 1998 first full release of V2.0 *version = 1.42; 30 Apr 1998 *version = 1.40; 6 Feb 1998 *version = 1.33; 16 Dec 1997 (internal release only) *version = 1.32; 21 Nov 1997 (internal release only) *version = 1.31; 4 Nov 1997 (internal release only) *version = 1.30; 11 Sep 1997 *version = 1.27; 3 Sep 1997 (internal release only) *version = 1.25; 2 Jul 1997 *version = 1.24; 2 May 1997 *version = 1.23; 24 Apr 1997 *version = 1.22; 18 Apr 1997 *version = 1.21; 26 Mar 1997 *version = 1.2; 29 Jan 1997 *version = 1.11; 04 Dec 1996 *version = 1.101; 13 Nov 1996 *version = 1.1; 6 Nov 1996 *version = 1.04; 17 Sep 1996 *version = 1.03; 20 Aug 1996 *version = 1.02; 15 Aug 1996 *version = 1.01; 12 Aug 1996 */ return(*version); } /*--------------------------------------------------------------------------*/ int ffflnm(fitsfile *fptr, /* I - FITS file pointer */ char *filename, /* O - name of the file */ int *status) /* IO - error status */ /* return the name of the FITS file */ { strcpy(filename,(fptr->Fptr)->filename); return(*status); } /*--------------------------------------------------------------------------*/ int ffflmd(fitsfile *fptr, /* I - FITS file pointer */ int *filemode, /* O - open mode of the file */ int *status) /* IO - error status */ /* return the access mode of the FITS file */ { *filemode = (fptr->Fptr)->writemode; return(*status); } /*--------------------------------------------------------------------------*/ void ffgerr(int status, /* I - error status value */ char *errtext) /* O - error message (max 30 char long + null) */ /* Return a short descriptive error message that corresponds to the input error status value. The message may be up to 30 characters long, plus the terminating null character. */ { errtext[0] = '\0'; if (status >= 0 && status < 300) { switch (status) { case 0: strcpy(errtext, "OK - no error"); break; case 1: strcpy(errtext, "non-CFITSIO program error"); break; case 101: strcpy(errtext, "same input and output files"); break; case 103: strcpy(errtext, "attempt to open too many files"); break; case 104: strcpy(errtext, "could not open the named file"); break; case 105: strcpy(errtext, "couldn't create the named file"); break; case 106: strcpy(errtext, "error writing to FITS file"); break; case 107: strcpy(errtext, "tried to move past end of file"); break; case 108: strcpy(errtext, "error reading from FITS file"); break; case 110: strcpy(errtext, "could not close the file"); break; case 111: strcpy(errtext, "array dimensions too big"); break; case 112: strcpy(errtext, "cannot write to readonly file"); break; case 113: strcpy(errtext, "could not allocate memory"); break; case 114: strcpy(errtext, "invalid fitsfile pointer"); break; case 115: strcpy(errtext, "NULL input pointer"); break; case 116: strcpy(errtext, "error seeking file position"); break; case 121: strcpy(errtext, "invalid URL prefix"); break; case 122: strcpy(errtext, "too many I/O drivers"); break; case 123: strcpy(errtext, "I/O driver init failed"); break; case 124: strcpy(errtext, "no I/O driver for this URLtype"); break; case 125: strcpy(errtext, "parse error in input file URL"); break; case 126: strcpy(errtext, "parse error in range list"); break; case 151: strcpy(errtext, "bad argument (shared mem drvr)"); break; case 152: strcpy(errtext, "null ptr arg (shared mem drvr)"); break; case 153: strcpy(errtext, "no free shared memory handles"); break; case 154: strcpy(errtext, "share mem drvr not initialized"); break; case 155: strcpy(errtext, "IPC system error (shared mem)"); break; case 156: strcpy(errtext, "no memory (shared mem drvr)"); break; case 157: strcpy(errtext, "share mem resource deadlock"); break; case 158: strcpy(errtext, "lock file open/create failed"); break; case 159: strcpy(errtext, "can't resize share mem block"); break; case 201: strcpy(errtext, "header already has keywords"); break; case 202: strcpy(errtext, "keyword not found in header"); break; case 203: strcpy(errtext, "keyword number out of bounds"); break; case 204: strcpy(errtext, "keyword value is undefined"); break; case 205: strcpy(errtext, "string missing closing quote"); break; case 206: strcpy(errtext, "error in indexed keyword name"); break; case 207: strcpy(errtext, "illegal character in keyword"); break; case 208: strcpy(errtext, "required keywords out of order"); break; case 209: strcpy(errtext, "keyword value not positive int"); break; case 210: strcpy(errtext, "END keyword not found"); break; case 211: strcpy(errtext, "illegal BITPIX keyword value"); break; case 212: strcpy(errtext, "illegal NAXIS keyword value"); break; case 213: strcpy(errtext, "illegal NAXISn keyword value"); break; case 214: strcpy(errtext, "illegal PCOUNT keyword value"); break; case 215: strcpy(errtext, "illegal GCOUNT keyword value"); break; case 216: strcpy(errtext, "illegal TFIELDS keyword value"); break; case 217: strcpy(errtext, "negative table row size"); break; case 218: strcpy(errtext, "negative number of rows"); break; case 219: strcpy(errtext, "named column not found"); break; case 220: strcpy(errtext, "illegal SIMPLE keyword value"); break; case 221: strcpy(errtext, "first keyword not SIMPLE"); break; case 222: strcpy(errtext, "second keyword not BITPIX"); break; case 223: strcpy(errtext, "third keyword not NAXIS"); break; case 224: strcpy(errtext, "missing NAXISn keywords"); break; case 225: strcpy(errtext, "first keyword not XTENSION"); break; case 226: strcpy(errtext, "CHDU not an ASCII table"); break; case 227: strcpy(errtext, "CHDU not a binary table"); break; case 228: strcpy(errtext, "PCOUNT keyword not found"); break; case 229: strcpy(errtext, "GCOUNT keyword not found"); break; case 230: strcpy(errtext, "TFIELDS keyword not found"); break; case 231: strcpy(errtext, "missing TBCOLn keyword"); break; case 232: strcpy(errtext, "missing TFORMn keyword"); break; case 233: strcpy(errtext, "CHDU not an IMAGE extension"); break; case 234: strcpy(errtext, "illegal TBCOLn keyword value"); break; case 235: strcpy(errtext, "CHDU not a table extension"); break; case 236: strcpy(errtext, "column exceeds width of table"); break; case 237: strcpy(errtext, "more than 1 matching col. name"); break; case 241: strcpy(errtext, "row width not = field widths"); break; case 251: strcpy(errtext, "unknown FITS extension type"); break; case 252: strcpy(errtext, "1st key not SIMPLE or XTENSION"); break; case 253: strcpy(errtext, "END keyword is not blank"); break; case 254: strcpy(errtext, "Header fill area not blank"); break; case 255: strcpy(errtext, "Data fill area invalid"); break; case 261: strcpy(errtext, "illegal TFORM format code"); break; case 262: strcpy(errtext, "unknown TFORM datatype code"); break; case 263: strcpy(errtext, "illegal TDIMn keyword value"); break; case 264: strcpy(errtext, "invalid BINTABLE heap pointer"); break; default: strcpy(errtext, "unknown error status"); break; } } else if (status < 600) { switch(status) { case 301: strcpy(errtext, "illegal HDU number"); break; case 302: strcpy(errtext, "column number < 1 or > tfields"); break; case 304: strcpy(errtext, "negative byte address"); break; case 306: strcpy(errtext, "negative number of elements"); break; case 307: strcpy(errtext, "bad first row number"); break; case 308: strcpy(errtext, "bad first element number"); break; case 309: strcpy(errtext, "not an ASCII (A) column"); break; case 310: strcpy(errtext, "not a logical (L) column"); break; case 311: strcpy(errtext, "bad ASCII table datatype"); break; case 312: strcpy(errtext, "bad binary table datatype"); break; case 314: strcpy(errtext, "null value not defined"); break; case 317: strcpy(errtext, "not a variable length column"); break; case 320: strcpy(errtext, "illegal number of dimensions"); break; case 321: strcpy(errtext, "1st pixel no. > last pixel no."); break; case 322: strcpy(errtext, "BSCALE or TSCALn = 0."); break; case 323: strcpy(errtext, "illegal axis length < 1"); break; case 340: strcpy(errtext, "not group table"); break; case 341: strcpy(errtext, "HDU already member of group"); break; case 342: strcpy(errtext, "group member not found"); break; case 343: strcpy(errtext, "group not found"); break; case 344: strcpy(errtext, "bad group id"); break; case 345: strcpy(errtext, "too many HDUs tracked"); break; case 346: strcpy(errtext, "HDU alread tracked"); break; case 347: strcpy(errtext, "bad Grouping option"); break; case 348: strcpy(errtext, "identical pointers (groups)"); break; case 360: strcpy(errtext, "malloc failed in parser"); break; case 361: strcpy(errtext, "file read error in parser"); break; case 362: strcpy(errtext, "null pointer arg (parser)"); break; case 363: strcpy(errtext, "empty line (parser)"); break; case 364: strcpy(errtext, "cannot unread > 1 line"); break; case 365: strcpy(errtext, "parser too deeply nested"); break; case 366: strcpy(errtext, "file open failed (parser)"); break; case 367: strcpy(errtext, "hit EOF (parser)"); break; case 368: strcpy(errtext, "bad argument (parser)"); break; case 369: strcpy(errtext, "unexpected token (parser)"); break; case 401: strcpy(errtext, "bad int to string conversion"); break; case 402: strcpy(errtext, "bad float to string conversion"); break; case 403: strcpy(errtext, "keyword value not integer"); break; case 404: strcpy(errtext, "keyword value not logical"); break; case 405: strcpy(errtext, "keyword value not floating pt"); break; case 406: strcpy(errtext, "keyword value not double"); break; case 407: strcpy(errtext, "bad string to int conversion"); break; case 408: strcpy(errtext, "bad string to float conversion"); break; case 409: strcpy(errtext, "bad string to double convert"); break; case 410: strcpy(errtext, "illegal datatype code value"); break; case 411: strcpy(errtext, "illegal no. of decimals"); break; case 412: strcpy(errtext, "datatype conversion overflow"); break; case 413: strcpy(errtext, "error compressing image"); break; case 414: strcpy(errtext, "error uncompressing image"); break; case 420: strcpy(errtext, "bad date or time conversion"); break; case 431: strcpy(errtext, "syntax error in expression"); break; case 432: strcpy(errtext, "expression result wrong type"); break; case 433: strcpy(errtext, "vector result too large"); break; case 434: strcpy(errtext, "missing output column"); break; case 435: strcpy(errtext, "bad data in parsed column"); break; case 436: strcpy(errtext, "output extension of wrong type"); break; case 501: strcpy(errtext, "WCS angle too large"); break; case 502: strcpy(errtext, "bad WCS coordinate"); break; case 503: strcpy(errtext, "error in WCS calculation"); break; case 504: strcpy(errtext, "bad WCS projection type"); break; case 505: strcpy(errtext, "WCS keywords not found"); break; default: strcpy(errtext, "unknown error status"); break; } } else { strcpy(errtext, "unknown error status"); } return; } /*--------------------------------------------------------------------------*/ void ffpmsg(const char *err_message) /* put message on to error stack */ { ffxmsg(PutMesg, (char *)err_message); return; } /*--------------------------------------------------------------------------*/ void ffpmrk(void) /* write a marker to the stack. It is then possible to pop only those messages following the marker off of the stack, leaving the previous messages unaffected. The marker is ignored by the ffgmsg routine. */ { char *dummy = 0; ffxmsg(PutMark, dummy); return; } /*--------------------------------------------------------------------------*/ int ffgmsg(char *err_message) /* get oldest message from error stack, ignoring markers */ { ffxmsg(GetMesg, err_message); return(*err_message); } /*--------------------------------------------------------------------------*/ void ffcmsg(void) /* erase all messages in the error stack */ { char *dummy = 0; ffxmsg(DelAll, dummy); return; } /*--------------------------------------------------------------------------*/ void ffcmrk(void) /* erase newest messages in the error stack, stopping if a marker is found. The marker is also erased in this case. */ { char *dummy = 0; ffxmsg(DelMark, dummy); return; } /*--------------------------------------------------------------------------*/ void ffxmsg( int action, char *errmsg) /* general routine to get, put, or clear the error message stack. Use a static array rather than allocating memory as needed for the error messages because it is likely to be more efficient and simpler to implement. Action Code: DelAll 1 delete all messages on the error stack DelMark 2 delete messages back to and including the 1st marker DelNewest 3 delete the newest message from the stack GetMesg 4 pop and return oldest message, ignoring marks PutMesg 5 add a new message to the stack PutMark 6 add a marker to the stack */ { int ii; char markflag; static char *txtbuff[errmsgsiz], *tmpbuff, *msgptr; static char errbuff[errmsgsiz][81]; /* initialize all = \0 */ static int nummsg = 0; FFLOCK; if (action == DelAll) /* clear the whole message stack */ { for (ii = 0; ii < nummsg; ii ++) *txtbuff[ii] = '\0'; nummsg = 0; } else if (action == DelMark) /* clear up to and including first marker */ { while (nummsg > 0) { nummsg--; markflag = *txtbuff[nummsg]; /* store possible marker character */ *txtbuff[nummsg] = '\0'; /* clear the buffer for this msg */ if (markflag == ESMARKER) break; /* found a marker, so quit */ } } else if (action == DelNewest) /* remove newest message from stack */ { if (nummsg > 0) { nummsg--; *txtbuff[nummsg] = '\0'; /* clear the buffer for this msg */ } } else if (action == GetMesg) /* pop and return oldest message from stack */ { /* ignoring markers */ while (nummsg > 0) { strcpy(errmsg, txtbuff[0]); /* copy oldest message to output */ *txtbuff[0] = '\0'; /* clear the buffer for this msg */ nummsg--; for (ii = 0; ii < nummsg; ii++) txtbuff[ii] = txtbuff[ii + 1]; /* shift remaining pointers */ if (errmsg[0] != ESMARKER) { /* quit if this is not a marker */ FFUNLOCK; return; } } errmsg[0] = '\0'; /* no messages in the stack */ } else if (action == PutMesg) /* add new message to stack */ { msgptr = errmsg; while (strlen(msgptr)) { if (nummsg == errmsgsiz) { tmpbuff = txtbuff[0]; /* buffers full; reuse oldest buffer */ *txtbuff[0] = '\0'; /* clear the buffer for this msg */ nummsg--; for (ii = 0; ii < nummsg; ii++) txtbuff[ii] = txtbuff[ii + 1]; /* shift remaining pointers */ txtbuff[nummsg] = tmpbuff; /* set pointer for the new message */ } else { for (ii = 0; ii < errmsgsiz; ii++) { if (*errbuff[ii] == '\0') /* find first empty buffer */ { txtbuff[nummsg] = errbuff[ii]; break; } } } strncat(txtbuff[nummsg], msgptr, 80); nummsg++; msgptr += minvalue(80, strlen(msgptr)); } } else if (action == PutMark) /* put a marker on the stack */ { if (nummsg == errmsgsiz) { tmpbuff = txtbuff[0]; /* buffers full; reuse oldest buffer */ *txtbuff[0] = '\0'; /* clear the buffer for this msg */ nummsg--; for (ii = 0; ii < nummsg; ii++) txtbuff[ii] = txtbuff[ii + 1]; /* shift remaining pointers */ txtbuff[nummsg] = tmpbuff; /* set pointer for the new message */ } else { for (ii = 0; ii < errmsgsiz; ii++) { if (*errbuff[ii] == '\0') /* find first empty buffer */ { txtbuff[nummsg] = errbuff[ii]; break; } } } *txtbuff[nummsg] = ESMARKER; /* write the marker */ *(txtbuff[nummsg] + 1) = '\0'; nummsg++; } FFUNLOCK; return; } /*--------------------------------------------------------------------------*/ int ffpxsz(int datatype) /* return the number of bytes per pixel associated with the datatype */ { if (datatype == TBYTE) return(sizeof(char)); else if (datatype == TUSHORT) return(sizeof(short)); else if (datatype == TSHORT) return(sizeof(short)); else if (datatype == TULONG) return(sizeof(long)); else if (datatype == TLONG) return(sizeof(long)); else if (datatype == TINT) return(sizeof(int)); else if (datatype == TUINT) return(sizeof(int)); else if (datatype == TFLOAT) return(sizeof(float)); else if (datatype == TDOUBLE) return(sizeof(double)); else if (datatype == TLOGICAL) return(sizeof(char)); else return(0); } /*--------------------------------------------------------------------------*/ int fftkey(const char *keyword, /* I - keyword name */ int *status) /* IO - error status */ /* Test that the keyword name conforms to the FITS standard. Must contain only capital letters, digits, minus or underscore chars. Trailing spaces are allowed. If the input status value is less than zero, then the test is modified so that upper or lower case letters are allowed, and no error messages are printed if the keyword is not legal. */ { size_t maxchr, ii; int spaces=0; char msg[FLEN_ERRMSG], testchar; if (*status > 0) /* inherit input status value if > 0 */ return(*status); maxchr=strlen(keyword); if (maxchr > 8) maxchr = 8; for (ii = 0; ii < maxchr; ii++) { if (*status == 0) testchar = keyword[ii]; else testchar = toupper(keyword[ii]); if ( (testchar >= 'A' && testchar <= 'Z') || (testchar >= '0' && testchar <= '9') || testchar == '-' || testchar == '_' ) { if (spaces) { if (*status == 0) { /* don't print error message if status < 0 */ snprintf(msg, FLEN_ERRMSG, "Keyword name contains embedded space(s): %.8s", keyword); ffpmsg(msg); } return(*status = BAD_KEYCHAR); } } else if (keyword[ii] == ' ') spaces = 1; else { if (*status == 0) { /* don't print error message if status < 0 */ snprintf(msg, FLEN_ERRMSG,"Character %d in this keyword is illegal: %.8s", (int) (ii+1), keyword); ffpmsg(msg); /* explicitly flag the 2 most common cases */ if (keyword[ii] == 0) ffpmsg(" (This a NULL (0) character)."); else if (keyword[ii] == 9) ffpmsg(" (This an ASCII TAB (9) character)."); } return(*status = BAD_KEYCHAR); } } return(*status); } /*--------------------------------------------------------------------------*/ int fftrec(char *card, /* I - keyword card to test */ int *status) /* IO - error status */ /* Test that the keyword card conforms to the FITS standard. Must contain only printable ASCII characters; */ { size_t ii, maxchr; char msg[FLEN_ERRMSG]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); maxchr = strlen(card); for (ii = 8; ii < maxchr; ii++) { if (card[ii] < 32 || card[ii] > 126) { snprintf(msg, FLEN_ERRMSG, "Character %d in this keyword is illegal. Hex Value = %X", (int) (ii+1), (int) card[ii] ); if (card[ii] == 0) strcat(msg, " (NULL char.)"); else if (card[ii] == 9) strcat(msg, " (TAB char.)"); else if (card[ii] == 10) strcat(msg, " (Line Feed char.)"); else if (card[ii] == 11) strcat(msg, " (Vertical Tab)"); else if (card[ii] == 12) strcat(msg, " (Form Feed char.)"); else if (card[ii] == 13) strcat(msg, " (Carriage Return)"); else if (card[ii] == 27) strcat(msg, " (Escape char.)"); else if (card[ii] == 127) strcat(msg, " (Delete char.)"); ffpmsg(msg); strncpy(msg, card, 80); msg[80] = '\0'; ffpmsg(msg); return(*status = BAD_KEYCHAR); } } return(*status); } /*--------------------------------------------------------------------------*/ void ffupch(char *string) /* convert string to upper case, in place. */ { size_t len, ii; len = strlen(string); for (ii = 0; ii < len; ii++) string[ii] = toupper(string[ii]); return; } /*--------------------------------------------------------------------------*/ int ffmkky(const char *keyname, /* I - keyword name */ char *value, /* I - keyword value */ const char *comm, /* I - keyword comment */ char *card, /* O - constructed keyword card */ int *status) /* IO - status value */ /* Make a complete FITS 80-byte keyword card from the input name, value and comment strings. Output card is null terminated without any trailing blanks. */ { size_t namelen, len, ii; char tmpname[FLEN_KEYWORD], tmpname2[FLEN_KEYWORD],*cptr; char *saveptr; int tstatus = -1, nblank = 0, ntoken = 0, maxlen = 0, specialchar = 0; if (*status > 0) return(*status); *tmpname = '\0'; *tmpname2 = '\0'; *card = '\0'; /* skip leading blanks in the name */ while(*(keyname + nblank) == ' ') nblank++; strncat(tmpname, keyname + nblank, FLEN_KEYWORD - 1); len = strlen(value); namelen = strlen(tmpname); /* delete non-significant trailing blanks in the name */ if (namelen) { cptr = tmpname + namelen - 1; while(*cptr == ' ') { *cptr = '\0'; cptr--; } namelen = cptr - tmpname + 1; } /* check that the name does not contain an '=' (equals sign) */ if (strchr(tmpname, '=') ) { ffpmsg("Illegal keyword name; contains an equals sign (=)"); ffpmsg(tmpname); return(*status = BAD_KEYCHAR); } if (namelen <= 8 && fftkey(tmpname, &tstatus) <= 0 ) { /* a normal 8-char (or less) FITS keyword. */ strcat(card, tmpname); /* copy keyword name to buffer */ for (ii = namelen; ii < 8; ii++) card[ii] = ' '; /* pad keyword name with spaces */ card[8] = '='; /* append '= ' in columns 9-10 */ card[9] = ' '; card[10] = '\0'; /* terminate the partial string */ namelen = 10; } else if ((FSTRNCMP(tmpname, "HIERARCH ", 9) == 0) || (FSTRNCMP(tmpname, "hierarch ", 9) == 0) ) { /* this is an explicit ESO HIERARCH keyword */ strcat(card, tmpname); /* copy keyword name to buffer */ if (namelen + 3 + len > 80) { /* save 1 char by not putting a space before the equals sign */ strcat(card, "= "); namelen += 2; } else { strcat(card, " = "); namelen += 3; } } else { /* scan the keyword name to determine the number and max length of the tokens */ /* and test if any of the tokens contain nonstandard characters */ strncat(tmpname2, tmpname, FLEN_KEYWORD - 1); cptr = ffstrtok(tmpname2, " ",&saveptr); while (cptr) { if (strlen(cptr) > maxlen) maxlen = strlen(cptr); /* find longest token */ /* name contains special characters? */ tstatus = -1; /* suppress any error message */ if (fftkey(cptr, &tstatus) > 0) specialchar = 1; cptr = ffstrtok(NULL, " ",&saveptr); ntoken++; } tstatus = -1; /* suppress any error message */ /* if (ntoken > 1) { */ if (ntoken > 0) { /* temporarily change so that this case should always be true */ /* for now at least, treat all cases as an implicit ESO HIERARCH keyword. */ /* This could change if FITS is ever expanded to directly support longer keywords. */ strcat(card, "HIERARCH "); strcat(card, tmpname); namelen += 9; if (namelen + 3 + len > 80) { /* save 1 char by not putting a space before the equals sign */ strcat(card, "= "); namelen += 2; } else { strcat(card, " = "); namelen += 3; } } else if ((fftkey(tmpname, &tstatus) <= 0)) { /* should never get here (at least for now) */ /* allow keyword names longer than 8 characters */ strncat(card, tmpname, FLEN_KEYWORD - 1); strcat(card, "= "); namelen += 2; } else { /* should never get here (at least for now) */ ffpmsg("Illegal keyword name:"); ffpmsg(tmpname); return(*status = BAD_KEYCHAR); } } if (len > 0) /* now process the value string */ { if (value[0] == '\'') /* is this a quoted string value? */ { if (namelen > 77) { ffpmsg( "The following keyword + value is too long to fit on a card:"); ffpmsg(keyname); ffpmsg(value); return(*status = BAD_KEYCHAR); } strncat(card, value, 80 - namelen); /* append the value string */ len = minvalue(80, namelen + len); /* restore the closing quote if it got truncated */ if (len == 80) { card[79] = '\''; } if (comm) { if (comm[0] != 0) { if (len < 30) { for (ii = len; ii < 30; ii++) card[ii] = ' '; /* fill with spaces to col 30 */ card[30] = '\0'; len = 30; } } } } else { if (namelen + len > 80) { ffpmsg( "The following keyword + value is too long to fit on a card:"); ffpmsg(keyname); ffpmsg(value); return(*status = BAD_KEYCHAR); } else if (namelen + len < 30) { /* add spaces so field ends at least in col 30 */ strncat(card, " ", 30 - (namelen + len)); } strncat(card, value, 80 - namelen); /* append the value string */ len = minvalue(80, namelen + len); len = maxvalue(30, len); } if (comm) { if ((len < 77) && ( strlen(comm) > 0) ) /* room for a comment? */ { strcat(card, " / "); /* append comment separator */ strncat(card, comm, 77 - len); /* append comment (what fits) */ } } } else { if (namelen == 10) /* This case applies to normal keywords only */ { card[8] = ' '; /* keywords with no value have no '=' */ if (comm) { strncat(card, comm, 80 - namelen); /* append comment (what fits) */ } } } /* issue a warning if this keyword does not strictly conform to the standard HIERARCH convention, which requires, 1) at least 2 tokens in the name, 2) no tokens longer than 8 characters, and 3) no special characters in any of the tokens */ if (ntoken == 1 || specialchar == 1) { ffpmsg("Warning: the following keyword does not conform to the HIERARCH convention"); /* ffpmsg(" (e.g., name is not hierarchical or contains non-standard characters)."); */ ffpmsg(card); } return(*status); } /*--------------------------------------------------------------------------*/ int ffmkey(fitsfile *fptr, /* I - FITS file pointer */ const char *card, /* I - card string value */ int *status) /* IO - error status */ /* replace the previously read card (i.e. starting 80 bytes before the (fptr->Fptr)->nextkey position) with the contents of the input card. */ { char tcard[81]; size_t len, ii; int keylength = 8; /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); strncpy(tcard,card,80); tcard[80] = '\0'; len = strlen(tcard); /* silently replace any illegal characters with a space */ for (ii=0; ii < len; ii++) if (tcard[ii] < ' ' || tcard[ii] > 126) tcard[ii] = ' '; for (ii=len; ii < 80; ii++) /* fill card with spaces if necessary */ tcard[ii] = ' '; keylength = strcspn(tcard, "="); if (keylength == 80) keylength = 8; for (ii=0; ii < keylength; ii++) /* make sure keyword name is uppercase */ tcard[ii] = toupper(tcard[ii]); fftkey(tcard, status); /* test keyword name contains legal chars */ /* no need to do this any more, since any illegal characters have been removed fftrec(tcard, status); */ /* test rest of keyword for legal chars */ /* move position of keyword to be over written */ ffmbyt(fptr, ((fptr->Fptr)->nextkey) - 80, REPORT_EOF, status); ffpbyt(fptr, 80, tcard, status); /* write the 80 byte card */ return(*status); } /*--------------------------------------------------------------------------*/ int ffkeyn(const char *keyroot, /* I - root string for keyword name */ int value, /* I - index number to be appended to root name */ char *keyname, /* O - output root + index keyword name */ int *status) /* IO - error status */ /* Construct a keyword name string by appending the index number to the root. e.g., if root = "TTYPE" and value = 12 then keyname = "TTYPE12". Note: this allows keyword names longer than 8 characters. */ { char suffix[16]; size_t rootlen; keyname[0] = '\0'; /* initialize output name to null */ rootlen = strlen(keyroot); if (rootlen == 0 || value < 0 ) return(*status = 206); snprintf(suffix, 16, "%d", value); /* construct keyword suffix */ strcpy(keyname, keyroot); /* copy root string to name string */ while (rootlen > 0 && keyname[rootlen - 1] == ' ') { rootlen--; /* remove trailing spaces in root name */ keyname[rootlen] = '\0'; } strcat(keyname, suffix); /* append suffix to the root */ return(*status); } /*--------------------------------------------------------------------------*/ int ffnkey(int value, /* I - index number to be appended to root name */ const char *keyroot, /* I - root string for keyword name */ char *keyname, /* O - output root + index keyword name */ int *status) /* IO - error status */ /* Construct a keyword name string by appending the root string to the index number. e.g., if root = "TTYPE" and value = 12 then keyname = "12TTYPE". */ { size_t rootlen; keyname[0] = '\0'; /* initialize output name to null */ rootlen = strlen(keyroot); if (rootlen == 0 || rootlen > 7 || value < 0 ) return(*status = 206); snprintf(keyname, FLEN_VALUE,"%d", value); /* construct keyword prefix */ if (rootlen + strlen(keyname) > 8) return(*status = 206); strcat(keyname, keyroot); /* append root to the prefix */ return(*status); } /*--------------------------------------------------------------------------*/ int ffpsvc(char *card, /* I - FITS header card (nominally 80 bytes long) */ char *value, /* O - value string parsed from the card */ char *comm, /* O - comment string parsed from the card */ int *status) /* IO - error status */ /* ParSe the Value and Comment strings from the input header card string. If the card contains a quoted string value, the returned value string includes the enclosing quote characters. If comm = NULL, don't return the comment string. */ { int jj; size_t ii, cardlen, nblank, valpos; if (*status > 0) return(*status); value[0] = '\0'; if (comm) comm[0] = '\0'; cardlen = strlen(card); /* support for ESO HIERARCH keywords; find the '=' */ if (FSTRNCMP(card, "HIERARCH ", 9) == 0) { valpos = strcspn(card, "="); if (valpos == cardlen) /* no value indicator ??? */ { if (comm != NULL) { if (cardlen > 8) { strcpy(comm, &card[8]); jj=cardlen - 8; for (jj--; jj >= 0; jj--) /* replace trailing blanks with nulls */ { if (comm[jj] == ' ') comm[jj] = '\0'; else break; } } } return(*status); /* no value indicator */ } valpos++; /* point to the position after the '=' */ } else if (cardlen < 9 || FSTRNCMP(card, "COMMENT ", 8) == 0 || /* keywords with no value */ FSTRNCMP(card, "HISTORY ", 8) == 0 || FSTRNCMP(card, "END ", 8) == 0 || FSTRNCMP(card, "CONTINUE", 8) == 0 || FSTRNCMP(card, " ", 8) == 0 ) { /* no value, so the comment extends from cols 9 - 80 */ if (comm != NULL) { if (cardlen > 8) { strcpy(comm, &card[8]); jj=cardlen - 8; for (jj--; jj >= 0; jj--) /* replace trailing blanks with nulls */ { if (comm[jj] == ' ') comm[jj] = '\0'; else break; } } } return(*status); } else if (FSTRNCMP(&card[8], "= ", 2) == 0 ) { /* normal keyword with '= ' in cols 9-10 */ valpos = 10; /* starting position of the value field */ } else { valpos = strcspn(card, "="); if (valpos == cardlen) /* no value indicator ??? */ { if (comm != NULL) { if (cardlen > 8) { strcpy(comm, &card[8]); jj=cardlen - 8; for (jj--; jj >= 0; jj--) /* replace trailing blanks with nulls */ { if (comm[jj] == ' ') comm[jj] = '\0'; else break; } } } return(*status); /* no value indicator */ } valpos++; /* point to the position after the '=' */ } nblank = strspn(&card[valpos], " "); /* find number of leading blanks */ if (nblank + valpos == cardlen) { /* the absence of a value string is legal, and simply indicates that the keyword value is undefined. Don't write an error message in this case. */ return(*status); } ii = valpos + nblank; if (card[ii] == '/' ) /* slash indicates start of the comment */ { ii++; } else if (card[ii] == '\'' ) /* is this a quoted string value? */ { value[0] = card[ii]; for (jj=1, ii++; ii < cardlen; ii++, jj++) { if (card[ii] == '\'') /* is this the closing quote? */ { if (card[ii+1] == '\'') /* 2 successive quotes? */ { value[jj] = card[ii]; ii++; jj++; } else { value[jj] = card[ii]; break; /* found the closing quote, so exit this loop */ } } value[jj] = card[ii]; /* copy the next character to the output */ } if (ii == cardlen) { jj = minvalue(jj, 69); /* don't exceed 70 char string length */ value[jj] = '\''; /* close the bad value string */ value[jj+1] = '\0'; /* terminate the bad value string */ ffpmsg("This keyword string value has no closing quote:"); ffpmsg(card); /* May 2008 - modified to not fail on this minor error */ /* return(*status = NO_QUOTE); */ } else { value[jj+1] = '\0'; /* terminate the good value string */ ii++; /* point to the character following the value */ } } else if (card[ii] == '(' ) /* is this a complex value? */ { nblank = strcspn(&card[ii], ")" ); /* find closing ) */ if (nblank == strlen( &card[ii] ) ) { ffpmsg("This complex keyword value has no closing ')':"); ffpmsg(card); return(*status = NO_QUOTE); } nblank++; strncpy(value, &card[ii], nblank); value[nblank] = '\0'; ii = ii + nblank; } else /* an integer, floating point, or logical FITS value string */ { nblank = strcspn(&card[ii], " /"); /* find the end of the token */ strncpy(value, &card[ii], nblank); value[nblank] = '\0'; ii = ii + nblank; } /* now find the comment string, if any */ if (comm) { nblank = strspn(&card[ii], " "); /* find next non-space character */ ii = ii + nblank; if (ii < 80) { if (card[ii] == '/') /* ignore the slash separator */ { ii++; if (card[ii] == ' ') /* also ignore the following space */ ii++; } strcat(comm, &card[ii]); /* copy the remaining characters */ jj=strlen(comm); for (jj--; jj >= 0; jj--) /* replace trailing blanks with nulls */ { if (comm[jj] == ' ') comm[jj] = '\0'; else break; } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffgthd(char *tmplt, /* I - input header template string */ char *card, /* O - returned FITS header record */ int *hdtype, /* O - how to interpreter the returned card string */ /* -2 = modify the name of a keyword; the old keyword name is returned starting at address chars[0]; the new name is returned starting at address char[40] (to be consistent with the Fortran version). Both names are null terminated. -1 = card contains the name of a keyword that is to be deleted 0 = append this keyword if it doesn't already exist, or modify the value if the keyword already exists. 1 = append this comment keyword ('HISTORY', 'COMMENT', or blank keyword name) 2 = this is the END keyword; do not write it to the header */ int *status) /* IO - error status */ /* 'Get Template HeaDer' parse a template header line and create a formated character string which is suitable for appending to a FITS header */ { char keyname[FLEN_KEYWORD], value[140], comment[140]; char *tok, *suffix, *loc, tvalue[140]; int len, vlen, more, tstatus; double dval; if (*status > 0) return(*status); card[0] = '\0'; *hdtype = 0; if (!FSTRNCMP(tmplt, " ", 8) ) { /* if first 8 chars of template are blank, then this is a comment */ strncat(card, tmplt, 80); *hdtype = 1; return(*status); } tok = tmplt; /* point to start of template string */ keyname[0] = '\0'; value[0] = '\0'; comment[0] = '\0'; len = strspn(tok, " "); /* no. of spaces before keyword */ tok += len; /* test for pecular case where token is a string of dashes */ if (strncmp(tok, "--------------------", 20) == 0) return(*status = BAD_KEYCHAR); if (tok[0] == '-') /* is there a leading minus sign? */ { /* first token is name of keyword to be deleted or renamed */ *hdtype = -1; tok++; len = strspn(tok, " "); /* no. of spaces before keyword */ tok += len; if (len < 8) /* not a blank name? */ { len = strcspn(tok, " ="); /* length of name */ if (len >= FLEN_KEYWORD) return(*status = BAD_KEYCHAR); strncat(card, tok, len); /* The HIERARCH convention supports non-standard characters in the keyword name, so don't always convert to upper case or abort if there are illegal characters in the name or if the name is greater than 8 characters long. */ if (len < 9) /* this is possibly a normal FITS keyword name */ { ffupch(card); tstatus = 0; if (fftkey(card, &tstatus) > 0) { /* name contained non-standard characters, so reset */ card[0] = '\0'; strncat(card, tok, len); } } tok += len; } /* second token, if present, is the new name for the keyword */ len = strspn(tok, " "); /* no. of spaces before next token */ tok += len; if (tok[0] == '\0' || tok[0] == '=') return(*status); /* no second token */ *hdtype = -2; len = strcspn(tok, " "); /* length of new name */ if (len > 40) /* name has to fit on columns 41-80 of card */ return(*status = BAD_KEYCHAR); /* copy the new name to card + 40; This is awkward, */ /* but is consistent with the way the Fortran FITSIO works */ strcat(card," "); strncpy(&card[40], tok, len+1); /* copy len+1 to get terminator */ /* The HIERARCH convention supports non-standard characters in the keyword name, so don't always convert to upper case or abort if there are illegal characters in the name or if the name is greater than 8 characters long. */ if (len < 9) /* this is possibly a normal FITS keyword name */ { ffupch(&card[40]); tstatus = 0; if (fftkey(&card[40], &tstatus) > 0) { /* name contained non-standard characters, so reset */ strncpy(&card[40], tok, len); } } } else /* no negative sign at beginning of template */ { /* get the keyword name token */ len = strcspn(tok, " ="); /* length of keyword name */ if (len >= FLEN_KEYWORD) return(*status = BAD_KEYCHAR); strncat(keyname, tok, len); /* The HIERARCH convention supports non-standard characters in the keyword name, so don't always convert to upper case or abort if there are illegal characters in the name or if the name is greater than 8 characters long. */ if (len < 9) /* this is possibly a normal FITS keyword name */ { ffupch(keyname); tstatus = 0; if (fftkey(keyname, &tstatus) > 0) { /* name contained non-standard characters, so reset */ keyname[0] = '\0'; strncat(keyname, tok, len); } } if (!FSTRCMP(keyname, "END") ) { strcpy(card, "END"); *hdtype = 2; return(*status); } tok += len; /* move token pointer to end of the keyword */ if (!FSTRCMP(keyname, "COMMENT") || !FSTRCMP(keyname, "HISTORY") || !FSTRCMP(keyname, "HIERARCH") ) { *hdtype = 1; /* simply append COMMENT and HISTORY keywords */ strcpy(card, keyname); strncat(card, tok, 73); return(*status); } /* look for the value token */ len = strspn(tok, " ="); /* spaces or = between name and value */ tok += len; if (*tok == '\'') /* is value enclosed in quotes? */ { more = TRUE; while (more) { tok++; /* temporarily move past the quote char */ len = strcspn(tok, "'"); /* length of quoted string */ tok--; strncat(value, tok, len + 2); tok += len + 1; if (tok[0] != '\'') /* check there is a closing quote */ return(*status = NO_QUOTE); tok++; if (tok[0] != '\'') /* 2 quote chars = literal quote */ more = FALSE; } } else if (*tok == '/' || *tok == '\0') /* There is no value */ { strcat(value, " "); } else /* not a quoted string value */ { len = strcspn(tok, " /"); /* length of value string */ strncat(value, tok, len); if (!( (tok[0] == 'T' || tok[0] == 'F') && (tok[1] == ' ' || tok[1] == '/' || tok[1] == '\0') )) { /* not a logical value */ dval = strtod(value, &suffix); /* try to read value as number */ if (*suffix != '\0' && *suffix != ' ' && *suffix != '/') { /* value not recognized as a number; might be because it */ /* contains a 'd' or 'D' exponent character */ strcpy(tvalue, value); if ((loc = strchr(tvalue, 'D'))) { *loc = 'E'; /* replace D's with E's. */ dval = strtod(tvalue, &suffix); /* read value again */ } else if ((loc = strchr(tvalue, 'd'))) { *loc = 'E'; /* replace d's with E's. */ dval = strtod(tvalue, &suffix); /* read value again */ } else if ((loc = strchr(tvalue, '.'))) { *loc = ','; /* replace period with a comma */ dval = strtod(tvalue, &suffix); /* read value again */ } } if (*suffix != '\0' && *suffix != ' ' && *suffix != '/') { /* value is not a number; must enclose it in quotes */ strcpy(value, "'"); strncat(value, tok, len); strcat(value, "'"); /* the following useless statement stops the compiler warning */ /* that dval is not used anywhere */ if (dval == 0.) len += (int) dval; } else { /* value is a number; convert any 'e' to 'E', or 'd' to 'D' */ loc = strchr(value, 'e'); if (loc) { *loc = 'E'; } else { loc = strchr(value, 'd'); if (loc) { *loc = 'D'; } } } } tok += len; } len = strspn(tok, " /"); /* no. of spaces between value and comment */ tok += len; vlen = strlen(value); if (vlen > 0 && vlen < 10 && value[0] == '\'') { /* pad quoted string with blanks so it is at least 8 chars long */ value[vlen-1] = '\0'; strncat(value, " ", 10 - vlen); strcat(&value[9], "'"); } /* get the comment string */ strncat(comment, tok, 70); /* construct the complete FITS header card */ ffmkky(keyname, value, comment, card, status); } return(*status); } /*--------------------------------------------------------------------------*/ int fits_translate_keyword( char *inrec, /* I - input string */ char *outrec, /* O - output converted string, or */ /* a null string if input does not */ /* match any of the patterns */ char *patterns[][2],/* I - pointer to input / output string */ /* templates */ int npat, /* I - number of templates passed */ int n_value, /* I - base 'n' template value of interest */ int n_offset, /* I - offset to be applied to the 'n' */ /* value in the output string */ int n_range, /* I - controls range of 'n' template */ /* values of interest (-1,0, or +1) */ int *pat_num, /* O - matched pattern number (0 based) or -1 */ int *i, /* O - value of i, if any, else 0 */ int *j, /* O - value of j, if any, else 0 */ int *m, /* O - value of m, if any, else 0 */ int *n, /* O - value of n, if any, else 0 */ int *status) /* IO - error status */ /* Translate a keyword name to a new name, based on a set of patterns. The user passes an array of patterns to be matched. Input pattern number i is pattern[i][0], and output pattern number i is pattern[i][1]. Keywords are matched against the input patterns. If a match is found then the keyword is re-written according to the output pattern. Order is important. The first match is accepted. The fastest match will be made when templates with the same first character are grouped together. Several characters have special meanings: i,j - single digits, preserved in output template n - column number of one or more digits, preserved in output template m - generic number of one or more digits, preserved in output template a - coordinate designator, preserved in output template # - number of one or more digits ? - any character * - only allowed in first character position, to match all keywords; only useful as last pattern in the list i, j, n, and m are returned by the routine. For example, the input pattern "iCTYPn" will match "1CTYP5" (if n_value is 5); the output pattern "CTYPEi" will be re-written as "CTYPE1". Notice that "i" is preserved. The following output patterns are special Special output pattern characters: "-" - do not copy a keyword that matches the corresponding input pattern "+" - copy the input unchanged The inrec string could be just the 8-char keyword name, or the entire 80-char header record. Characters 9 = 80 in the input string simply get appended to the translated keyword name. If n_range = 0, then only keywords with 'n' equal to n_value will be considered as a pattern match. If n_range = +1, then all values of 'n' greater than or equal to n_value will be a match, and if -1, then values of 'n' less than or equal to n_value will match. This routine was written by Craig Markwardt, GSFC */ { int i1 = 0, j1 = 0, n1 = 0, m1 = 0; int fac; char a = ' '; char oldp; char c, s; int ip, ic, pat, pass = 0, firstfail; char *spat; if (*status > 0) return(*status); if ((inrec == 0) || (outrec == 0)) return (*status = NULL_INPUT_PTR); *outrec = '\0'; /* if (*inrec == '\0') return 0; */ if (*inrec == '\0') /* expand to full 8 char blank keyword name */ strcpy(inrec, " "); oldp = '\0'; firstfail = 0; /* ===== Pattern match stage */ for (pat=0; pat < npat; pat++) { spat = patterns[pat][0]; i1 = 0; j1 = 0; m1 = -1; n1 = -1; a = ' '; /* Initialize the place-holders */ pass = 0; /* Pass the wildcard pattern */ if (spat[0] == '*') { pass = 1; break; } /* Optimization: if we have seen this initial pattern character before, then it must have failed, and we can skip the pattern */ if (firstfail && spat[0] == oldp) continue; oldp = spat[0]; /* ip = index of pattern character being matched ic = index of keyname character being matched firstfail = 1 if we fail on the first characteor (0=not) */ for (ip=0, ic=0, firstfail=1; (spat[ip]) && (ic < 8); ip++, ic++, firstfail=0) { c = inrec[ic]; s = spat[ip]; if (s == 'i') { /* Special pattern: 'i' placeholder */ if (isdigit(c)) { i1 = c - '0'; pass = 1;} } else if (s == 'j') { /* Special pattern: 'j' placeholder */ if (isdigit(c)) { j1 = c - '0'; pass = 1;} } else if ((s == 'n')||(s == 'm')||(s == '#')) { /* Special patterns: multi-digit number */ int val = 0; pass = 0; if (isdigit(c)) { pass = 1; /* NOTE, could fail below */ /* Parse decimal number */ while (ic<8 && isdigit(c)) { val = val*10 + (c - '0'); ic++; c = inrec[ic]; } ic--; c = inrec[ic]; if (s == 'n') { /* Is it a column number? */ if ( val >= 1 && val <= 999 && /* Row range check */ (((n_range == 0) && (val == n_value)) || /* Strict equality */ ((n_range == -1) && (val <= n_value)) || /* n <= n_value */ ((n_range == +1) && (val >= n_value))) ) { /* n >= n_value */ n1 = val; } else { pass = 0; } } else if (s == 'm') { /* Generic number */ m1 = val; } } } else if (s == 'a') { /* Special pattern: coordinate designator */ if (isupper(c) || c == ' ') { a = c; pass = 1;} } else if (s == '?') { /* Match any individual character */ pass = 1; } else if (c == s) { /* Match a specific character */ pass = 1; } else { /* FAIL */ pass = 0; } if (!pass) break; } /* Must pass to the end of the keyword. No partial matches allowed */ if (pass && (ic >= 8 || inrec[ic] == ' ')) break; } /* Transfer the pattern-matched numbers to the output parameters */ if (i) { *i = i1; } if (j) { *j = j1; } if (n) { *n = n1; } if (m) { *m = m1; } if (pat_num) { *pat_num = pat; } /* ===== Keyword rewriting and output stage */ spat = patterns[pat][1]; /* Return case: no match, or explicit deletion pattern */ if (pass == 0 || spat[0] == '\0' || spat[0] == '-') return 0; /* A match: we start by copying the input record to the output */ strcpy(outrec, inrec); /* Return case: return the input record unchanged */ if (spat[0] == '+') return 0; /* Final case: a new output pattern */ for (ip=0, ic=0; spat[ip]; ip++, ic++) { s = spat[ip]; if (s == 'i') { outrec[ic] = (i1+'0'); } else if (s == 'j') { outrec[ic] = (j1+'0'); } else if (s == 'n') { if (n1 == -1) { n1 = n_value; } if (n1 > 0) { n1 += n_offset; for (fac = 1; (n1/fac) > 0; fac *= 10); fac /= 10; while(fac > 0) { outrec[ic] = ((n1/fac) % 10) + '0'; fac /= 10; ic ++; } ic--; } } else if (s == 'm' && m1 >= 0) { for (fac = 1; (m1/fac) > 0; fac *= 10); fac /= 10; while(fac > 0) { outrec[ic] = ((m1/fac) % 10) + '0'; fac /= 10; ic ++; } ic --; } else if (s == 'a') { outrec[ic] = a; } else { outrec[ic] = s; } } /* Pad the keyword name with spaces */ for ( ; ic<8; ic++) { outrec[ic] = ' '; } return(*status); } /*--------------------------------------------------------------------------*/ int fits_translate_keywords( fitsfile *infptr, /* I - pointer to input HDU */ fitsfile *outfptr, /* I - pointer to output HDU */ int firstkey, /* I - first HDU record number to start with */ char *patterns[][2],/* I - pointer to input / output keyword templates */ int npat, /* I - number of templates passed */ int n_value, /* I - base 'n' template value of interest */ int n_offset, /* I - offset to be applied to the 'n' */ /* value in the output string */ int n_range, /* I - controls range of 'n' template */ /* values of interest (-1,0, or +1) */ int *status) /* IO - error status */ /* Copy relevant keywords from the table header into the newly created primary array header. Convert names of keywords where appropriate. See fits_translate_keyword() for the definitions. Translation begins at header record number 'firstkey', and continues to the end of the header. This routine was written by Craig Markwardt, GSFC */ { int nrec, nkeys, nmore; char rec[FLEN_CARD]; int i = 0, j = 0, n = 0, m = 0; int pat_num = 0, maxchr, ii; char outrec[FLEN_CARD]; if (*status > 0) return(*status); ffghsp(infptr, &nkeys, &nmore, status); /* get number of keywords */ for (nrec = firstkey; nrec <= nkeys; nrec++) { outrec[0] = '\0'; ffgrec(infptr, nrec, rec, status); /* silently overlook any illegal ASCII characters in the value or */ /* comment fields of the record. It is usually not appropriate to */ /* abort the process because of this minor transgression of the FITS rules. */ /* Set the offending character to a blank */ maxchr = strlen(rec); for (ii = 8; ii < maxchr; ii++) { if (rec[ii] < 32 || rec[ii] > 126) rec[ii] = ' '; } fits_translate_keyword(rec, outrec, patterns, npat, n_value, n_offset, n_range, &pat_num, &i, &j, &m, &n, status); if (outrec[0]) { ffprec(outfptr, outrec, status); /* copy the keyword */ rec[8] = 0; outrec[8] = 0; } else { rec[8] = 0; outrec[8] = 0; } } return(*status); } /*--------------------------------------------------------------------------*/ int fits_copy_pixlist2image( fitsfile *infptr, /* I - pointer to input HDU */ fitsfile *outfptr, /* I - pointer to output HDU */ int firstkey, /* I - first HDU record number to start with */ int naxis, /* I - number of axes in the image */ int *colnum, /* I - numbers of the columns to be binned */ int *status) /* IO - error status */ /* Copy relevant keywords from the pixel list table header into a newly created primary array header. Convert names of keywords where appropriate. See fits_translate_pixkeyword() for the definitions. Translation begins at header record number 'firstkey', and continues to the end of the header. */ { int nrec, nkeys, nmore; char rec[FLEN_CARD], outrec[FLEN_CARD]; int pat_num = 0, npat; int iret, jret, nret, mret, lret; char *patterns[][2] = { {"TCTYPn", "CTYPEn" }, {"TCTYna", "CTYPEna" }, {"TCUNIn", "CUNITn" }, {"TCUNna", "CUNITna" }, {"TCRVLn", "CRVALn" }, {"TCRVna", "CRVALna" }, {"TCDLTn", "CDELTn" }, {"TCDEna", "CDELTna" }, {"TCRPXn", "CRPIXn" }, {"TCRPna", "CRPIXna" }, {"TCROTn", "CROTAn" }, {"TPn_ma", "PCn_ma" }, {"TPCn_m", "PCn_ma" }, {"TCn_ma", "CDn_ma" }, {"TCDn_m", "CDn_ma" }, {"TVn_la", "PVn_la" }, {"TPVn_l", "PVn_la" }, {"TSn_la", "PSn_la" }, {"TPSn_l", "PSn_la" }, {"TWCSna", "WCSNAMEa" }, {"TCNAna", "CNAMEna" }, {"TCRDna", "CRDERna" }, {"TCSYna", "CSYERna" }, {"LONPna", "LONPOLEa" }, {"LATPna", "LATPOLEa" }, {"EQUIna", "EQUINOXa" }, {"MJDOBn", "MJD-OBS" }, {"MJDAn", "MJD-AVG" }, {"DAVGn", "DATE-AVG" }, {"RADEna", "RADESYSa" }, {"RFRQna", "RESTFRQa" }, {"RWAVna", "RESTWAVa" }, {"SPECna", "SPECSYSa" }, {"SOBSna", "SSYSOBSa" }, {"SSRCna", "SSYSSRCa" }, /* preserve common keywords */ {"LONPOLEa", "+" }, {"LATPOLEa", "+" }, {"EQUINOXa", "+" }, {"EPOCH", "+" }, {"MJD-????", "+" }, {"DATE????", "+" }, {"TIME????", "+" }, {"RADESYSa", "+" }, {"RADECSYS", "+" }, {"TELESCOP", "+" }, {"INSTRUME", "+" }, {"OBSERVER", "+" }, {"OBJECT", "+" }, /* Delete general table column keywords */ {"XTENSION", "-" }, {"BITPIX", "-" }, {"NAXIS", "-" }, {"NAXISi", "-" }, {"PCOUNT", "-" }, {"GCOUNT", "-" }, {"TFIELDS", "-" }, {"TDIM#", "-" }, {"THEAP", "-" }, {"EXTNAME", "-" }, {"EXTVER", "-" }, {"EXTLEVEL","-" }, {"CHECKSUM","-" }, {"DATASUM", "-" }, {"NAXLEN", "-" }, {"AXLEN#", "-" }, {"CPREF", "-" }, /* Delete table keywords related to other columns */ {"T????#a", "-" }, {"TC??#a", "-" }, {"T??#_#", "-" }, {"TWCS#a", "-" }, {"LONP#a", "-" }, {"LATP#a", "-" }, {"EQUI#a", "-" }, {"MJDOB#", "-" }, {"MJDA#", "-" }, {"RADE#a", "-" }, {"DAVG#", "-" }, {"iCTYP#", "-" }, {"iCTY#a", "-" }, {"iCUNI#", "-" }, {"iCUN#a", "-" }, {"iCRVL#", "-" }, {"iCDLT#", "-" }, {"iCRPX#", "-" }, {"iCTY#a", "-" }, {"iCUN#a", "-" }, {"iCRV#a", "-" }, {"iCDE#a", "-" }, {"iCRP#a", "-" }, {"ijPC#a", "-" }, {"ijCD#a", "-" }, {"iV#_#a", "-" }, {"iS#_#a", "-" }, {"iCRD#a", "-" }, {"iCSY#a", "-" }, {"iCROT#", "-" }, {"WCAX#a", "-" }, {"WCSN#a", "-" }, {"iCNA#a", "-" }, {"*", "+" }}; /* copy all other keywords */ if (*status > 0) return(*status); npat = sizeof(patterns)/sizeof(patterns[0][0])/2; ffghsp(infptr, &nkeys, &nmore, status); /* get number of keywords */ for (nrec = firstkey; nrec <= nkeys; nrec++) { outrec[0] = '\0'; ffgrec(infptr, nrec, rec, status); fits_translate_pixkeyword(rec, outrec, patterns, npat, naxis, colnum, &pat_num, &iret, &jret, &nret, &mret, &lret, status); if (outrec[0]) { ffprec(outfptr, outrec, status); /* copy the keyword */ } rec[8] = 0; outrec[8] = 0; } return(*status); } /*--------------------------------------------------------------------------*/ int fits_translate_pixkeyword( char *inrec, /* I - input string */ char *outrec, /* O - output converted string, or */ /* a null string if input does not */ /* match any of the patterns */ char *patterns[][2],/* I - pointer to input / output string */ /* templates */ int npat, /* I - number of templates passed */ int naxis, /* I - number of columns to be binned */ int *colnum, /* I - numbers of the columns to be binned */ int *pat_num, /* O - matched pattern number (0 based) or -1 */ int *i, int *j, int *n, int *m, int *l, int *status) /* IO - error status */ /* Translate a keyword name to a new name, based on a set of patterns. The user passes an array of patterns to be matched. Input pattern number i is pattern[i][0], and output pattern number i is pattern[i][1]. Keywords are matched against the input patterns. If a match is found then the keyword is re-written according to the output pattern. Order is important. The first match is accepted. The fastest match will be made when templates with the same first character are grouped together. Several characters have special meanings: i,j - single digits, preserved in output template n, m - column number of one or more digits, preserved in output template k - generic number of one or more digits, preserved in output template a - coordinate designator, preserved in output template # - number of one or more digits ? - any character * - only allowed in first character position, to match all keywords; only useful as last pattern in the list i, j, n, and m are returned by the routine. For example, the input pattern "iCTYPn" will match "1CTYP5" (if n_value is 5); the output pattern "CTYPEi" will be re-written as "CTYPE1". Notice that "i" is preserved. The following output patterns are special Special output pattern characters: "-" - do not copy a keyword that matches the corresponding input pattern "+" - copy the input unchanged The inrec string could be just the 8-char keyword name, or the entire 80-char header record. Characters 9 = 80 in the input string simply get appended to the translated keyword name. If n_range = 0, then only keywords with 'n' equal to n_value will be considered as a pattern match. If n_range = +1, then all values of 'n' greater than or equal to n_value will be a match, and if -1, then values of 'n' less than or equal to n_value will match. */ { int i1 = 0, j1 = 0, val; int fac, nval = 0, mval = 0, lval = 0; char a = ' '; char oldp; char c, s; int ip, ic, pat, pass = 0, firstfail; char *spat; if (*status > 0) return(*status); if ((inrec == 0) || (outrec == 0)) return (*status = NULL_INPUT_PTR); *outrec = '\0'; if (*inrec == '\0') return 0; oldp = '\0'; firstfail = 0; /* ===== Pattern match stage */ for (pat=0; pat < npat; pat++) { spat = patterns[pat][0]; i1 = 0; j1 = 0; a = ' '; /* Initialize the place-holders */ pass = 0; /* Pass the wildcard pattern */ if (spat[0] == '*') { pass = 1; break; } /* Optimization: if we have seen this initial pattern character before, then it must have failed, and we can skip the pattern */ if (firstfail && spat[0] == oldp) continue; oldp = spat[0]; /* ip = index of pattern character being matched ic = index of keyname character being matched firstfail = 1 if we fail on the first characteor (0=not) */ for (ip=0, ic=0, firstfail=1; (spat[ip]) && (ic < 8); ip++, ic++, firstfail=0) { c = inrec[ic]; s = spat[ip]; if (s == 'i') { /* Special pattern: 'i' placeholder */ if (isdigit(c)) { i1 = c - '0'; pass = 1;} } else if (s == 'j') { /* Special pattern: 'j' placeholder */ if (isdigit(c)) { j1 = c - '0'; pass = 1;} } else if ((s == 'n')||(s == 'm')||(s == 'l')||(s == '#')) { /* Special patterns: multi-digit number */ val = 0; pass = 0; if (isdigit(c)) { pass = 1; /* NOTE, could fail below */ /* Parse decimal number */ while (ic<8 && isdigit(c)) { val = val*10 + (c - '0'); ic++; c = inrec[ic]; } ic--; c = inrec[ic]; if (s == 'n' || s == 'm') { /* Is it a column number? */ if ( val >= 1 && val <= 999) { if (val == colnum[0]) val = 1; else if (val == colnum[1]) val = 2; else if (val == colnum[2]) val = 3; else if (val == colnum[3]) val = 4; else { pass = 0; val = 0; } if (s == 'n') nval = val; else mval = val; } else { pass = 0; } } else if (s == 'l') { /* Generic number */ lval = val; } } } else if (s == 'a') { /* Special pattern: coordinate designator */ if (isupper(c) || c == ' ') { a = c; pass = 1;} } else if (s == '?') { /* Match any individual character */ pass = 1; } else if (c == s) { /* Match a specific character */ pass = 1; } else { /* FAIL */ pass = 0; } if (!pass) break; } /* Must pass to the end of the keyword. No partial matches allowed */ if (pass && (ic >= 8 || inrec[ic] == ' ')) break; } /* Transfer the pattern-matched numbers to the output parameters */ if (i) { *i = i1; } if (j) { *j = j1; } if (n) { *n = nval; } if (m) { *m = mval; } if (l) { *l = lval; } if (pat_num) { *pat_num = pat; } /* ===== Keyword rewriting and output stage */ spat = patterns[pat][1]; /* Return case: no match, or explicit deletion pattern */ if (pass == 0 || spat[0] == '\0' || spat[0] == '-') return 0; /* A match: we start by copying the input record to the output */ strcpy(outrec, inrec); /* Return case: return the input record unchanged */ if (spat[0] == '+') return 0; /* Final case: a new output pattern */ for (ip=0, ic=0; spat[ip]; ip++, ic++) { s = spat[ip]; if (s == 'i') { outrec[ic] = (i1+'0'); } else if (s == 'j') { outrec[ic] = (j1+'0'); } else if (s == 'n' && nval > 0) { for (fac = 1; (nval/fac) > 0; fac *= 10); fac /= 10; while(fac > 0) { outrec[ic] = ((nval/fac) % 10) + '0'; fac /= 10; ic ++; } ic--; } else if (s == 'm' && mval > 0) { for (fac = 1; (mval/fac) > 0; fac *= 10); fac /= 10; while(fac > 0) { outrec[ic] = ((mval/fac) % 10) + '0'; fac /= 10; ic ++; } ic--; } else if (s == 'l' && lval >= 0) { for (fac = 1; (lval/fac) > 0; fac *= 10); fac /= 10; while(fac > 0) { outrec[ic] = ((lval/fac) % 10) + '0'; fac /= 10; ic ++; } ic --; } else if (s == 'a') { outrec[ic] = a; } else { outrec[ic] = s; } } /* Pad the keyword name with spaces */ for ( ; ic<8; ic++) { outrec[ic] = ' '; } return(*status); } /*--------------------------------------------------------------------------*/ int ffasfm(char *tform, /* I - format code from the TFORMn keyword */ int *dtcode, /* O - numerical datatype code */ long *twidth, /* O - width of the field, in chars */ int *decimals, /* O - number of decimal places (F, E, D format) */ int *status) /* IO - error status */ { /* parse the ASCII table TFORM column format to determine the data type, the field width, and number of decimal places (if relevant) */ int ii, datacode; long longval, width; float fwidth; char *form, temp[FLEN_VALUE], message[FLEN_ERRMSG]; if (*status > 0) return(*status); if (dtcode) *dtcode = 0; if (twidth) *twidth = 0; if (decimals) *decimals = 0; ii = 0; while (tform[ii] != 0 && tform[ii] == ' ') /* find first non-blank char */ ii++; strcpy(temp, &tform[ii]); /* copy format string */ ffupch(temp); /* make sure it is in upper case */ form = temp; /* point to start of format string */ if (form[0] == 0) { ffpmsg("Error: ASCII table TFORM code is blank"); return(*status = BAD_TFORM); } /*-----------------------------------------------*/ /* determine default datatype code */ /*-----------------------------------------------*/ if (form[0] == 'A') datacode = TSTRING; else if (form[0] == 'I') datacode = TLONG; else if (form[0] == 'F') datacode = TFLOAT; else if (form[0] == 'E') datacode = TFLOAT; else if (form[0] == 'D') datacode = TDOUBLE; else { snprintf(message, FLEN_ERRMSG, "Illegal ASCII table TFORMn datatype: \'%s\'", tform); ffpmsg(message); return(*status = BAD_TFORM_DTYPE); } if (dtcode) *dtcode = datacode; form++; /* point to the start of field width */ if (datacode == TSTRING || datacode == TLONG) { /*-----------------------------------------------*/ /* A or I data formats: */ /*-----------------------------------------------*/ if (ffc2ii(form, &width, status) <= 0) /* read the width field */ { if (width <= 0) { width = 0; *status = BAD_TFORM; } else { /* set to shorter precision if I4 or less */ if (width <= 4 && datacode == TLONG) datacode = TSHORT; } } } else { /*-----------------------------------------------*/ /* F, E or D data formats: */ /*-----------------------------------------------*/ if (ffc2rr(form, &fwidth, status) <= 0) /* read ww.dd width field */ { if (fwidth <= 0.) *status = BAD_TFORM; else { width = (long) fwidth; /* convert from float to long */ if (width > 7 && *temp == 'F') datacode = TDOUBLE; /* type double if >7 digits */ if (width < 10) form = form + 1; /* skip 1 digit */ else form = form + 2; /* skip 2 digits */ if (form[0] == '.') /* should be a decimal point here */ { form++; /* point to start of decimals field */ if (ffc2ii(form, &longval, status) <= 0) /* read decimals */ { if (decimals) *decimals = longval; /* long to short convertion */ if (longval >= width) /* width < no. of decimals */ *status = BAD_TFORM; if (longval > 6 && *temp == 'E') datacode = TDOUBLE; /* type double if >6 digits */ } } } } } if (*status > 0) { *status = BAD_TFORM; snprintf(message,FLEN_ERRMSG,"Illegal ASCII table TFORMn code: \'%s\'", tform); ffpmsg(message); } if (dtcode) *dtcode = datacode; if (twidth) *twidth = width; return(*status); } /*--------------------------------------------------------------------------*/ int ffbnfm(char *tform, /* I - format code from the TFORMn keyword */ int *dtcode, /* O - numerical datatype code */ long *trepeat, /* O - repeat count of the field */ long *twidth, /* O - width of the field, in chars */ int *status) /* IO - error status */ { /* parse the binary table TFORM column format to determine the data type, repeat count, and the field width (if it is an ASCII (A) field) */ size_t ii, nchar; int datacode, variable, iread; long width, repeat; char *form, temp[FLEN_VALUE], message[FLEN_ERRMSG]; if (*status > 0) return(*status); if (dtcode) *dtcode = 0; if (trepeat) *trepeat = 0; if (twidth) *twidth = 0; nchar = strlen(tform); for (ii = 0; ii < nchar; ii++) { if (tform[ii] != ' ') /* find first non-space char */ break; } if (ii == nchar) { ffpmsg("Error: binary table TFORM code is blank (ffbnfm)."); return(*status = BAD_TFORM); } strcpy(temp, &tform[ii]); /* copy format string */ ffupch(temp); /* make sure it is in upper case */ form = temp; /* point to start of format string */ /*-----------------------------------------------*/ /* get the repeat count */ /*-----------------------------------------------*/ ii = 0; while(isdigit((int) form[ii])) ii++; /* look for leading digits in the field */ if (ii == 0) repeat = 1; /* no explicit repeat count */ else sscanf(form,"%ld", &repeat); /* read repeat count */ /*-----------------------------------------------*/ /* determine datatype code */ /*-----------------------------------------------*/ form = form + ii; /* skip over the repeat field */ if (form[0] == 'P' || form[0] == 'Q') { variable = 1; /* this is a variable length column */ /* repeat = 1; */ /* disregard any other repeat value */ form++; /* move to the next data type code char */ } else variable = 0; if (form[0] == 'U') /* internal code to signify unsigned integer */ { datacode = TUSHORT; width = 2; } else if (form[0] == 'I') { datacode = TSHORT; width = 2; } else if (form[0] == 'V') /* internal code to signify unsigned integer */ { datacode = TULONG; width = 4; } else if (form[0] == 'J') { datacode = TLONG; width = 4; } else if (form[0] == 'K') { datacode = TLONGLONG; width = 8; } else if (form[0] == 'E') { datacode = TFLOAT; width = 4; } else if (form[0] == 'D') { datacode = TDOUBLE; width = 8; } else if (form[0] == 'A') { datacode = TSTRING; /* the following code is used to support the non-standard datatype of the form rAw where r = total width of the field and w = width of fixed-length substrings within the field. */ iread = 0; if (form[1] != 0) { if (form[1] == '(' ) /* skip parenthesis around */ form++; /* variable length column width */ iread = sscanf(&form[1],"%ld", &width); } if (iread != 1 || (!variable && (width > repeat)) ) width = repeat; } else if (form[0] == 'L') { datacode = TLOGICAL; width = 1; } else if (form[0] == 'X') { datacode = TBIT; width = 1; } else if (form[0] == 'B') { datacode = TBYTE; width = 1; } else if (form[0] == 'S') /* internal code to signify signed byte */ { datacode = TSBYTE; width = 1; } else if (form[0] == 'C') { datacode = TCOMPLEX; width = 8; } else if (form[0] == 'M') { datacode = TDBLCOMPLEX; width = 16; } else { snprintf(message, FLEN_ERRMSG, "Illegal binary table TFORMn datatype: \'%s\' ", tform); ffpmsg(message); return(*status = BAD_TFORM_DTYPE); } if (variable) datacode = datacode * (-1); /* flag variable cols w/ neg type code */ if (dtcode) *dtcode = datacode; if (trepeat) *trepeat = repeat; if (twidth) *twidth = width; return(*status); } /*--------------------------------------------------------------------------*/ int ffbnfmll(char *tform, /* I - format code from the TFORMn keyword */ int *dtcode, /* O - numerical datatype code */ LONGLONG *trepeat, /* O - repeat count of the field */ long *twidth, /* O - width of the field, in chars */ int *status) /* IO - error status */ { /* parse the binary table TFORM column format to determine the data type, repeat count, and the field width (if it is an ASCII (A) field) */ size_t ii, nchar; int datacode, variable, iread; long width; LONGLONG repeat; char *form, temp[FLEN_VALUE], message[FLEN_ERRMSG]; double drepeat; if (*status > 0) return(*status); if (dtcode) *dtcode = 0; if (trepeat) *trepeat = 0; if (twidth) *twidth = 0; nchar = strlen(tform); for (ii = 0; ii < nchar; ii++) { if (tform[ii] != ' ') /* find first non-space char */ break; } if (ii == nchar) { ffpmsg("Error: binary table TFORM code is blank (ffbnfmll)."); return(*status = BAD_TFORM); } strcpy(temp, &tform[ii]); /* copy format string */ ffupch(temp); /* make sure it is in upper case */ form = temp; /* point to start of format string */ /*-----------------------------------------------*/ /* get the repeat count */ /*-----------------------------------------------*/ ii = 0; while(isdigit((int) form[ii])) ii++; /* look for leading digits in the field */ if (ii == 0) repeat = 1; /* no explicit repeat count */ else { /* read repeat count */ /* print as double, because the string-to-64-bit int conversion */ /* character is platform dependent (%lld, %ld, %I64d) */ sscanf(form,"%lf", &drepeat); repeat = (LONGLONG) (drepeat + 0.1); } /*-----------------------------------------------*/ /* determine datatype code */ /*-----------------------------------------------*/ form = form + ii; /* skip over the repeat field */ if (form[0] == 'P' || form[0] == 'Q') { variable = 1; /* this is a variable length column */ /* repeat = 1; */ /* disregard any other repeat value */ form++; /* move to the next data type code char */ } else variable = 0; if (form[0] == 'U') /* internal code to signify unsigned integer */ { datacode = TUSHORT; width = 2; } else if (form[0] == 'I') { datacode = TSHORT; width = 2; } else if (form[0] == 'V') /* internal code to signify unsigned integer */ { datacode = TULONG; width = 4; } else if (form[0] == 'J') { datacode = TLONG; width = 4; } else if (form[0] == 'K') { datacode = TLONGLONG; width = 8; } else if (form[0] == 'E') { datacode = TFLOAT; width = 4; } else if (form[0] == 'D') { datacode = TDOUBLE; width = 8; } else if (form[0] == 'A') { datacode = TSTRING; /* the following code is used to support the non-standard datatype of the form rAw where r = total width of the field and w = width of fixed-length substrings within the field. */ iread = 0; if (form[1] != 0) { if (form[1] == '(' ) /* skip parenthesis around */ form++; /* variable length column width */ iread = sscanf(&form[1],"%ld", &width); } if (iread != 1 || (!variable && (width > repeat)) ) width = (long) repeat; } else if (form[0] == 'L') { datacode = TLOGICAL; width = 1; } else if (form[0] == 'X') { datacode = TBIT; width = 1; } else if (form[0] == 'B') { datacode = TBYTE; width = 1; } else if (form[0] == 'S') /* internal code to signify signed byte */ { datacode = TSBYTE; width = 1; } else if (form[0] == 'C') { datacode = TCOMPLEX; width = 8; } else if (form[0] == 'M') { datacode = TDBLCOMPLEX; width = 16; } else { snprintf(message, FLEN_ERRMSG, "Illegal binary table TFORMn datatype: \'%s\' ", tform); ffpmsg(message); return(*status = BAD_TFORM_DTYPE); } if (variable) datacode = datacode * (-1); /* flag variable cols w/ neg type code */ if (dtcode) *dtcode = datacode; if (trepeat) *trepeat = repeat; if (twidth) *twidth = width; return(*status); } /*--------------------------------------------------------------------------*/ void ffcfmt(char *tform, /* value of an ASCII table TFORMn keyword */ char *cform) /* equivalent format code in C language syntax */ /* convert the FITS format string for an ASCII Table extension column into the equivalent C format string that can be used in a printf statement, after the values have been read as a double. */ { int ii; cform[0] = '\0'; ii = 0; while (tform[ii] != 0 && tform[ii] == ' ') /* find first non-blank char */ ii++; if (tform[ii] == 0) return; /* input format string was blank */ cform[0] = '%'; /* start the format string */ strcpy(&cform[1], &tform[ii + 1]); /* append the width and decimal code */ if (tform[ii] == 'A') strcat(cform, "s"); else if (tform[ii] == 'I') strcat(cform, ".0f"); /* 0 precision to suppress decimal point */ if (tform[ii] == 'F') strcat(cform, "f"); if (tform[ii] == 'E') strcat(cform, "E"); if (tform[ii] == 'D') strcat(cform, "E"); return; } /*--------------------------------------------------------------------------*/ void ffcdsp(char *tform, /* value of an ASCII table TFORMn keyword */ char *cform) /* equivalent format code in C language syntax */ /* convert the FITS TDISPn display format into the equivalent C format suitable for use in a printf statement. */ { int ii; cform[0] = '\0'; ii = 0; while (tform[ii] != 0 && tform[ii] == ' ') /* find first non-blank char */ ii++; if (tform[ii] == 0) { cform[0] = '\0'; return; /* input format string was blank */ } if (strchr(tform+ii, '%')) /* is there a % character in the string?? */ { cform[0] = '\0'; return; /* illegal TFORM string (possibly even harmful) */ } cform[0] = '%'; /* start the format string */ strcpy(&cform[1], &tform[ii + 1]); /* append the width and decimal code */ if (tform[ii] == 'A' || tform[ii] == 'a') strcat(cform, "s"); else if (tform[ii] == 'I' || tform[ii] == 'i') strcat(cform, "d"); else if (tform[ii] == 'O' || tform[ii] == 'o') strcat(cform, "o"); else if (tform[ii] == 'Z' || tform[ii] == 'z') strcat(cform, "X"); else if (tform[ii] == 'F' || tform[ii] == 'f') strcat(cform, "f"); else if (tform[ii] == 'E' || tform[ii] == 'e') strcat(cform, "E"); else if (tform[ii] == 'D' || tform[ii] == 'd') strcat(cform, "E"); else if (tform[ii] == 'G' || tform[ii] == 'g') strcat(cform, "G"); else cform[0] = '\0'; /* unrecognized tform code */ return; } /*--------------------------------------------------------------------------*/ int ffgcno( fitsfile *fptr, /* I - FITS file pionter */ int casesen, /* I - case sensitive string comparison? 0=no */ char *templt, /* I - input name of column (w/wildcards) */ int *colnum, /* O - number of the named column; 1=first col */ int *status) /* IO - error status */ /* Determine the column number corresponding to an input column name. The first column of the table = column 1; This supports the * and ? wild cards in the input template. */ { char colname[FLEN_VALUE]; /* temporary string to hold column name */ ffgcnn(fptr, casesen, templt, colname, colnum, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgcnn( fitsfile *fptr, /* I - FITS file pointer */ int casesen, /* I - case sensitive string comparison? 0=no */ char *templt, /* I - input name of column (w/wildcards) */ char *colname, /* O - full column name up to 68 + 1 chars long*/ int *colnum, /* O - number of the named column; 1=first col */ int *status) /* IO - error status */ /* Return the full column name and column number of the next column whose TTYPEn keyword value matches the input template string. The template may contain the * and ? wildcards. Status = 237 is returned if the match is not unique. If so, one may call this routine again with input status=237 to get the next match. A status value of 219 is returned when there are no more matching columns. */ { char errmsg[FLEN_ERRMSG]; int tstatus, ii, founde, foundw, match, exact, unique; long ivalue; tcolumn *colptr; if (*status <= 0) { (fptr->Fptr)->startcol = 0; /* start search with first column */ tstatus = 0; } else if (*status == COL_NOT_UNIQUE) /* start search from previous spot */ { tstatus = COL_NOT_UNIQUE; *status = 0; } else return(*status); /* bad input status value */ colname[0] = 0; /* initialize null return */ *colnum = 0; /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header to get col struct */ return(*status); colptr = (fptr->Fptr)->tableptr; /* pointer to first column */ colptr += ((fptr->Fptr)->startcol); /* offset to starting column */ founde = FALSE; /* initialize 'found exact match' flag */ foundw = FALSE; /* initialize 'found wildcard match' flag */ unique = FALSE; for (ii = (fptr->Fptr)->startcol; ii < (fptr->Fptr)->tfield; ii++, colptr++) { ffcmps(templt, colptr->ttype, casesen, &match, &exact); if (match) { if (founde && exact) { /* warning: this is the second exact match we've found */ /*reset pointer to first match so next search starts there */ (fptr->Fptr)->startcol = *colnum; return(*status = COL_NOT_UNIQUE); } else if (founde) /* a wildcard match */ { /* already found exact match so ignore this non-exact match */ } else if (exact) { /* this is the first exact match we have found, so save it. */ strcpy(colname, colptr->ttype); *colnum = ii + 1; founde = TRUE; } else if (foundw) { /* we have already found a wild card match, so not unique */ /* continue searching for other matches */ unique = FALSE; } else { /* this is the first wild card match we've found. save it */ strcpy(colname, colptr->ttype); *colnum = ii + 1; (fptr->Fptr)->startcol = *colnum; foundw = TRUE; unique = TRUE; } } } /* OK, we've checked all the names now see if we got any matches */ if (founde) { if (tstatus == COL_NOT_UNIQUE) /* we did find 1 exact match but */ *status = COL_NOT_UNIQUE; /* there was a previous match too */ } else if (foundw) { /* found one or more wildcard matches; report error if not unique */ if (!unique || tstatus == COL_NOT_UNIQUE) *status = COL_NOT_UNIQUE; } else { /* didn't find a match; check if template is a positive integer */ ffc2ii(templt, &ivalue, &tstatus); if (tstatus == 0 && ivalue <= (fptr->Fptr)->tfield && ivalue > 0) { *colnum = ivalue; colptr = (fptr->Fptr)->tableptr; /* pointer to first column */ colptr += (ivalue - 1); /* offset to correct column */ strcpy(colname, colptr->ttype); } else { *status = COL_NOT_FOUND; if (tstatus != COL_NOT_UNIQUE) { snprintf(errmsg, FLEN_ERRMSG, "ffgcnn could not find column: %.45s", templt); ffpmsg(errmsg); } } } (fptr->Fptr)->startcol = *colnum; /* save pointer for next time */ return(*status); } /*--------------------------------------------------------------------------*/ void ffcmps(char *templt, /* I - input template (may have wildcards) */ char *colname, /* I - full column name up to 68 + 1 chars long */ int casesen, /* I - case sensitive string comparison? 1=yes */ int *match, /* O - do template and colname match? 1=yes */ int *exact) /* O - do strings exactly match, or wildcards */ /* compare the template to the string and test if they match. The strings are limited to 68 characters or less (the max. length of a FITS string keyword value. This routine reports whether the two strings match and whether the match is exact or involves wildcards. This algorithm is very similar to the way unix filename wildcards work except that this first treats a wild card as a literal character when looking for a match. If there is no literal match, then it interpretes it as a wild card. So the template 'AB*DE' is considered to be an exact rather than a wild card match to the string 'AB*DE'. The '#' wild card in the template string will match any consecutive string of decimal digits in the colname. */ { int ii, found, t1, s1, wildsearch = 0, tsave = 0, ssave = 0; char temp[FLEN_VALUE], col[FLEN_VALUE]; *match = FALSE; *exact = TRUE; strncpy(temp, templt, FLEN_VALUE); /* copy strings to work area */ strncpy(col, colname, FLEN_VALUE); temp[FLEN_VALUE - 1] = '\0'; /* make sure strings are terminated */ col[FLEN_VALUE - 1] = '\0'; /* truncate trailing non-significant blanks */ for (ii = strlen(temp) - 1; ii >= 0 && temp[ii] == ' '; ii--) temp[ii] = '\0'; for (ii = strlen(col) - 1; ii >= 0 && col[ii] == ' '; ii--) col[ii] = '\0'; if (!casesen) { /* convert both strings to uppercase before comparison */ ffupch(temp); ffupch(col); } if (!FSTRCMP(temp, col) ) { *match = TRUE; /* strings exactly match */ return; } *exact = FALSE; /* strings don't exactly match */ t1 = 0; /* start comparison with 1st char of each string */ s1 = 0; while(1) /* compare corresponding chars in each string */ { if (temp[t1] == '\0' && col[s1] == '\0') { /* completely scanned both strings so they match */ *match = TRUE; return; } else if (temp[t1] == '\0') { if (wildsearch) { /* the previous wildcard search may have been going down a blind alley. Backtrack, and resume the wildcard search with the next character in the string. */ t1 = tsave; s1 = ssave + 1; } else { /* reached end of template string so they don't match */ return; } } else if (col[s1] == '\0') { /* reached end of other string; they match if the next */ /* character in the template string is a '*' wild card */ if (temp[t1] == '*' && temp[t1 + 1] == '\0') { *match = TRUE; } return; } if (temp[t1] == col[s1] || (temp[t1] == '?') ) { s1++; /* corresponding chars in the 2 strings match */ t1++; /* increment both pointers and loop back again */ } else if (temp[t1] == '#' && isdigit((int) col[s1]) ) { s1++; /* corresponding chars in the 2 strings match */ t1++; /* increment both pointers */ /* find the end of the string of digits */ while (isdigit((int) col[s1]) ) s1++; } else if (temp[t1] == '*') { /* save current string locations, in case we need to restart */ wildsearch = 1; tsave = t1; ssave = s1; /* get next char from template and look for it in the col name */ t1++; if (temp[t1] == '\0' || temp[t1] == ' ') { /* reached end of template so strings match */ *match = TRUE; return; } found = FALSE; while (col[s1] && !found) { if (temp[t1] == col[s1]) { t1++; /* found matching characters; incre both pointers */ s1++; /* and loop back to compare next chars */ found = TRUE; } else s1++; /* increment the column name pointer and try again */ } if (!found) { return; /* hit end of column name and failed to find a match */ } } else { if (wildsearch) { /* the previous wildcard search may have been going down a blind alley. Backtrack, and resume the wildcard search with the next character in the string. */ t1 = tsave; s1 = ssave + 1; } else { return; /* strings don't match */ } } } } /*--------------------------------------------------------------------------*/ int ffgtcl( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number */ int *typecode, /* O - datatype code (21 = short, etc) */ long *repeat, /* O - repeat count of field */ long *width, /* O - if ASCII, width of field or unit string */ int *status) /* IO - error status */ /* Get Type of table column. Returns the datatype code of the column, as well as the vector repeat count and (if it is an ASCII character column) the width of the field or a unit string within the field. This supports the TFORMn = 'rAw' syntax for specifying arrays of substrings, so if TFORMn = '60A12' then repeat = 60 and width = 12. */ { LONGLONG trepeat, twidth; ffgtclll(fptr, colnum, typecode, &trepeat, &twidth, status); if (*status > 0) return(*status); if (repeat) *repeat= (long) trepeat; if (width) *width = (long) twidth; return(*status); } /*--------------------------------------------------------------------------*/ int ffgtclll( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number */ int *typecode, /* O - datatype code (21 = short, etc) */ LONGLONG *repeat, /* O - repeat count of field */ LONGLONG *width, /* O - if ASCII, width of field or unit string */ int *status) /* IO - error status */ /* Get Type of table column. Returns the datatype code of the column, as well as the vector repeat count and (if it is an ASCII character column) the width of the field or a unit string within the field. This supports the TFORMn = 'rAw' syntax for specifying arrays of substrings, so if TFORMn = '60A12' then repeat = 60 and width = 12. */ { tcolumn *colptr; int hdutype, decims; long tmpwidth; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); if (colnum < 1 || colnum > (fptr->Fptr)->tfield) return(*status = BAD_COL_NUM); colptr = (fptr->Fptr)->tableptr; /* pointer to first column */ colptr += (colnum - 1); /* offset to correct column */ if (ffghdt(fptr, &hdutype, status) > 0) return(*status); if (hdutype == ASCII_TBL) { ffasfm(colptr->tform, typecode, &tmpwidth, &decims, status); *width = tmpwidth; if (repeat) *repeat = 1; } else { if (typecode) *typecode = colptr->tdatatype; if (width) *width = colptr->twidth; if (repeat) *repeat = colptr->trepeat; } return(*status); } /*--------------------------------------------------------------------------*/ int ffeqty( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number */ int *typecode, /* O - datatype code (21 = short, etc) */ long *repeat, /* O - repeat count of field */ long *width, /* O - if ASCII, width of field or unit string */ int *status) /* IO - error status */ /* Get the 'equivalent' table column type. This routine is similar to the ffgtcl routine (which returns the physical datatype of the column, as stored in the FITS file) except that if the TSCALn and TZEROn keywords are defined for the column, then it returns the 'equivalent' datatype. Thus, if the column is defined as '1I' (short integer) this routine may return the type as 'TUSHORT' or as 'TFLOAT' depending on the TSCALn and TZEROn values. Returns the datatype code of the column, as well as the vector repeat count and (if it is an ASCII character column) the width of the field or a unit string within the field. This supports the TFORMn = 'rAw' syntax for specifying arrays of substrings, so if TFORMn = '60A12' then repeat = 60 and width = 12. */ { LONGLONG trepeat, twidth; ffeqtyll(fptr, colnum, typecode, &trepeat, &twidth, status); if (repeat) *repeat= (long) trepeat; if (width) *width = (long) twidth; return(*status); } /*--------------------------------------------------------------------------*/ int ffeqtyll( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number */ int *typecode, /* O - datatype code (21 = short, etc) */ LONGLONG *repeat, /* O - repeat count of field */ LONGLONG *width, /* O - if ASCII, width of field or unit string */ int *status) /* IO - error status */ /* Get the 'equivalent' table column type. This routine is similar to the ffgtcl routine (which returns the physical datatype of the column, as stored in the FITS file) except that if the TSCALn and TZEROn keywords are defined for the column, then it returns the 'equivalent' datatype. Thus, if the column is defined as '1I' (short integer) this routine may return the type as 'TUSHORT' or as 'TFLOAT' depending on the TSCALn and TZEROn values. Returns the datatype code of the column, as well as the vector repeat count and (if it is an ASCII character column) the width of the field or a unit string within the field. This supports the TFORMn = 'rAw' syntax for specifying arrays of substrings, so if TFORMn = '60A12' then repeat = 60 and width = 12. */ { tcolumn *colptr; int hdutype, decims, tcode, effcode; double tscale, tzero, min_val, max_val; long lngscale, lngzero = 0, tmpwidth; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); if (colnum < 1 || colnum > (fptr->Fptr)->tfield) return(*status = BAD_COL_NUM); colptr = (fptr->Fptr)->tableptr; /* pointer to first column */ colptr += (colnum - 1); /* offset to correct column */ if (ffghdt(fptr, &hdutype, status) > 0) return(*status); if (hdutype == ASCII_TBL) { ffasfm(colptr->tform, typecode, &tmpwidth, &decims, status); if (width) *width = tmpwidth; if (repeat) *repeat = 1; } else { if (typecode) *typecode = colptr->tdatatype; if (width) *width = colptr->twidth; if (repeat) *repeat = colptr->trepeat; } /* return if caller is not interested in the typecode value */ if (!typecode) return(*status); /* check if the tscale and tzero keywords are defined, which might change the effective datatype of the column */ tscale = colptr->tscale; tzero = colptr->tzero; if (tscale == 1.0 && tzero == 0.0) /* no scaling */ return(*status); tcode = abs(*typecode); switch (tcode) { case TBYTE: /* binary table 'rB' column */ min_val = 0.; max_val = 255.0; break; case TSHORT: min_val = -32768.0; max_val = 32767.0; break; case TLONG: min_val = -2147483648.0; max_val = 2147483647.0; break; case TLONGLONG: /* simply reuse the TLONG values */ min_val = -2147483648.0; max_val = 2147483647.0; break; default: /* don't have to deal with other data types */ return(*status); } if (tscale >= 0.) { min_val = tzero + tscale * min_val; max_val = tzero + tscale * max_val; } else { max_val = tzero + tscale * min_val; min_val = tzero + tscale * max_val; } if (tzero < 2147483648.) /* don't exceed range of 32-bit integer */ lngzero = (long) tzero; lngscale = (long) tscale; if ((tzero != 2147483648.) && /* special value that exceeds integer range */ (lngzero != tzero || lngscale != tscale)) { /* not integers? */ /* floating point scaled values; just decide on required precision */ if (tcode == TBYTE || tcode == TSHORT) effcode = TFLOAT; else effcode = TDOUBLE; /* In all the remaining cases, TSCALn and TZEROn are integers, and not equal to 1 and 0, respectively. */ } else if ((min_val == -128.) && (max_val == 127.)) { effcode = TSBYTE; } else if ((min_val >= -32768.0) && (max_val <= 32767.0)) { effcode = TSHORT; } else if ((min_val >= 0.0) && (max_val <= 65535.0)) { effcode = TUSHORT; } else if ((min_val >= -2147483648.0) && (max_val <= 2147483647.0)) { effcode = TLONG; } else if ((min_val >= 0.0) && (max_val < 4294967296.0)) { effcode = TULONG; } else { /* exceeds the range of a 32-bit integer */ effcode = TDOUBLE; } /* return the effective datatype code (negative if variable length col.) */ if (*typecode < 0) /* variable length array column */ *typecode = -effcode; else *typecode = effcode; return(*status); } /*--------------------------------------------------------------------------*/ int ffgncl( fitsfile *fptr, /* I - FITS file pointer */ int *ncols, /* O - number of columns in the table */ int *status) /* IO - error status */ /* Get the number of columns in the table (= TFIELDS keyword) */ { if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); if ((fptr->Fptr)->hdutype == IMAGE_HDU) return(*status = NOT_TABLE); *ncols = (fptr->Fptr)->tfield; return(*status); } /*--------------------------------------------------------------------------*/ int ffgnrw( fitsfile *fptr, /* I - FITS file pointer */ long *nrows, /* O - number of rows in the table */ int *status) /* IO - error status */ /* Get the number of rows in the table (= NAXIS2 keyword) */ { if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); if ((fptr->Fptr)->hdutype == IMAGE_HDU) return(*status = NOT_TABLE); /* the NAXIS2 keyword may not be up to date, so use the structure value */ *nrows = (long) (fptr->Fptr)->numrows; return(*status); } /*--------------------------------------------------------------------------*/ int ffgnrwll( fitsfile *fptr, /* I - FITS file pointer */ LONGLONG *nrows, /* O - number of rows in the table */ int *status) /* IO - error status */ /* Get the number of rows in the table (= NAXIS2 keyword) */ { if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); if ((fptr->Fptr)->hdutype == IMAGE_HDU) return(*status = NOT_TABLE); /* the NAXIS2 keyword may not be up to date, so use the structure value */ *nrows = (fptr->Fptr)->numrows; return(*status); } /*--------------------------------------------------------------------------*/ int ffgacl( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number */ char *ttype, /* O - TTYPEn keyword value */ long *tbcol, /* O - TBCOLn keyword value */ char *tunit, /* O - TUNITn keyword value */ char *tform, /* O - TFORMn keyword value */ double *tscal, /* O - TSCALn keyword value */ double *tzero, /* O - TZEROn keyword value */ char *tnull, /* O - TNULLn keyword value */ char *tdisp, /* O - TDISPn keyword value */ int *status) /* IO - error status */ /* get ASCII column keyword values */ { char name[FLEN_KEYWORD], comm[FLEN_COMMENT]; tcolumn *colptr; int tstatus; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); if (colnum < 1 || colnum > (fptr->Fptr)->tfield) return(*status = BAD_COL_NUM); /* get what we can from the column structure */ colptr = (fptr->Fptr)->tableptr; /* pointer to first column */ colptr += (colnum -1); /* offset to correct column */ if (ttype) strcpy(ttype, colptr->ttype); if (tbcol) *tbcol = (long) ((colptr->tbcol) + 1); /* first col is 1, not 0 */ if (tform) strcpy(tform, colptr->tform); if (tscal) *tscal = colptr->tscale; if (tzero) *tzero = colptr->tzero; if (tnull) strcpy(tnull, colptr->strnull); /* read keywords to get additional parameters */ if (tunit) { ffkeyn("TUNIT", colnum, name, status); tstatus = 0; *tunit = '\0'; ffgkys(fptr, name, tunit, comm, &tstatus); } if (tdisp) { ffkeyn("TDISP", colnum, name, status); tstatus = 0; *tdisp = '\0'; ffgkys(fptr, name, tdisp, comm, &tstatus); } return(*status); } /*--------------------------------------------------------------------------*/ int ffgbcl( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number */ char *ttype, /* O - TTYPEn keyword value */ char *tunit, /* O - TUNITn keyword value */ char *dtype, /* O - datatype char: I, J, E, D, etc. */ long *repeat, /* O - vector column repeat count */ double *tscal, /* O - TSCALn keyword value */ double *tzero, /* O - TZEROn keyword value */ long *tnull, /* O - TNULLn keyword value integer cols only */ char *tdisp, /* O - TDISPn keyword value */ int *status) /* IO - error status */ /* get BINTABLE column keyword values */ { LONGLONG trepeat, ttnull; if (*status > 0) return(*status); ffgbclll(fptr, colnum, ttype, tunit, dtype, &trepeat, tscal, tzero, &ttnull, tdisp, status); if (repeat) *repeat = (long) trepeat; if (tnull) *tnull = (long) ttnull; return(*status); } /*--------------------------------------------------------------------------*/ int ffgbclll( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number */ char *ttype, /* O - TTYPEn keyword value */ char *tunit, /* O - TUNITn keyword value */ char *dtype, /* O - datatype char: I, J, E, D, etc. */ LONGLONG *repeat, /* O - vector column repeat count */ double *tscal, /* O - TSCALn keyword value */ double *tzero, /* O - TZEROn keyword value */ LONGLONG *tnull, /* O - TNULLn keyword value integer cols only */ char *tdisp, /* O - TDISPn keyword value */ int *status) /* IO - error status */ /* get BINTABLE column keyword values */ { char name[FLEN_KEYWORD], comm[FLEN_COMMENT]; tcolumn *colptr; int tstatus; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); if (colnum < 1 || colnum > (fptr->Fptr)->tfield) return(*status = BAD_COL_NUM); /* get what we can from the column structure */ colptr = (fptr->Fptr)->tableptr; /* pointer to first column */ colptr += (colnum -1); /* offset to correct column */ if (ttype) strcpy(ttype, colptr->ttype); if (dtype) { if (colptr->tdatatype < 0) /* add the "P" prefix for */ strcpy(dtype, "P"); /* variable length columns */ else dtype[0] = 0; if (abs(colptr->tdatatype) == TBIT) strcat(dtype, "X"); else if (abs(colptr->tdatatype) == TBYTE) strcat(dtype, "B"); else if (abs(colptr->tdatatype) == TLOGICAL) strcat(dtype, "L"); else if (abs(colptr->tdatatype) == TSTRING) strcat(dtype, "A"); else if (abs(colptr->tdatatype) == TSHORT) strcat(dtype, "I"); else if (abs(colptr->tdatatype) == TLONG) strcat(dtype, "J"); else if (abs(colptr->tdatatype) == TLONGLONG) strcat(dtype, "K"); else if (abs(colptr->tdatatype) == TFLOAT) strcat(dtype, "E"); else if (abs(colptr->tdatatype) == TDOUBLE) strcat(dtype, "D"); else if (abs(colptr->tdatatype) == TCOMPLEX) strcat(dtype, "C"); else if (abs(colptr->tdatatype) == TDBLCOMPLEX) strcat(dtype, "M"); } if (repeat) *repeat = colptr->trepeat; if (tscal) *tscal = colptr->tscale; if (tzero) *tzero = colptr->tzero; if (tnull) *tnull = colptr->tnull; /* read keywords to get additional parameters */ if (tunit) { ffkeyn("TUNIT", colnum, name, status); tstatus = 0; *tunit = '\0'; ffgkys(fptr, name, tunit, comm, &tstatus); } if (tdisp) { ffkeyn("TDISP", colnum, name, status); tstatus = 0; *tdisp = '\0'; ffgkys(fptr, name, tdisp, comm, &tstatus); } return(*status); } /*--------------------------------------------------------------------------*/ int ffghdn(fitsfile *fptr, /* I - FITS file pointer */ int *chdunum) /* O - number of the CHDU; 1 = primary array */ /* Return the number of the Current HDU in the FITS file. The primary array is HDU number 1. Note that this is one of the few cfitsio routines that does not return the error status value as the value of the function. */ { *chdunum = (fptr->HDUposition) + 1; return(*chdunum); } /*--------------------------------------------------------------------------*/ int ffghadll(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG *headstart, /* O - byte offset to beginning of CHDU */ LONGLONG *datastart, /* O - byte offset to beginning of next HDU */ LONGLONG *dataend, /* O - byte offset to beginning of next HDU */ int *status) /* IO - error status */ /* Return the address (= byte offset) in the FITS file to the beginning of the current HDU, the beginning of the data unit, and the end of the data unit. */ { if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) { if (ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status) > 0) return(*status); } else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) { if (ffrdef(fptr, status) > 0) /* rescan header */ return(*status); } if (headstart) *headstart = (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu]; if (datastart) *datastart = (fptr->Fptr)->datastart; if (dataend) *dataend = (fptr->Fptr)->headstart[((fptr->Fptr)->curhdu) + 1]; return(*status); } /*--------------------------------------------------------------------------*/ int ffghof(fitsfile *fptr, /* I - FITS file pointer */ OFF_T *headstart, /* O - byte offset to beginning of CHDU */ OFF_T *datastart, /* O - byte offset to beginning of next HDU */ OFF_T *dataend, /* O - byte offset to beginning of next HDU */ int *status) /* IO - error status */ /* Return the address (= byte offset) in the FITS file to the beginning of the current HDU, the beginning of the data unit, and the end of the data unit. */ { if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) { if (ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status) > 0) return(*status); } else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) { if (ffrdef(fptr, status) > 0) /* rescan header */ return(*status); } if (headstart) *headstart = (OFF_T) (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu]; if (datastart) *datastart = (OFF_T) (fptr->Fptr)->datastart; if (dataend) *dataend = (OFF_T) (fptr->Fptr)->headstart[((fptr->Fptr)->curhdu) + 1]; return(*status); } /*--------------------------------------------------------------------------*/ int ffghad(fitsfile *fptr, /* I - FITS file pointer */ long *headstart, /* O - byte offset to beginning of CHDU */ long *datastart, /* O - byte offset to beginning of next HDU */ long *dataend, /* O - byte offset to beginning of next HDU */ int *status) /* IO - error status */ /* Return the address (= byte offset) in the FITS file to the beginning of the current HDU, the beginning of the data unit, and the end of the data unit. */ { LONGLONG shead, sdata, edata; if (*status > 0) return(*status); ffghadll(fptr, &shead, &sdata, &edata, status); if (headstart) { if (shead > LONG_MAX) *status = NUM_OVERFLOW; else *headstart = (long) shead; } if (datastart) { if (sdata > LONG_MAX) *status = NUM_OVERFLOW; else *datastart = (long) sdata; } if (dataend) { if (edata > LONG_MAX) *status = NUM_OVERFLOW; else *dataend = (long) edata; } return(*status); } /*--------------------------------------------------------------------------*/ int ffrhdu(fitsfile *fptr, /* I - FITS file pointer */ int *hdutype, /* O - type of HDU */ int *status) /* IO - error status */ /* read the required keywords of the CHDU and initialize the corresponding structure elements that describe the format of the HDU */ { int ii, tstatus; char card[FLEN_CARD]; char name[FLEN_KEYWORD], value[FLEN_VALUE], comm[FLEN_COMMENT]; char xname[FLEN_VALUE], *xtension, urltype[20]; if (*status > 0) return(*status); if (ffgrec(fptr, 1, card, status) > 0 ) /* get the 80-byte card */ { ffpmsg("Cannot read first keyword in header (ffrhdu)."); return(*status); } strncpy(name,card,8); /* first 8 characters = the keyword name */ name[8] = '\0'; for (ii=7; ii >= 0; ii--) /* replace trailing blanks with nulls */ { if (name[ii] == ' ') name[ii] = '\0'; else break; } if (ffpsvc(card, value, comm, status) > 0) /* parse value and comment */ { ffpmsg("Cannot read value of first keyword in header (ffrhdu):"); ffpmsg(card); return(*status); } if (!strcmp(name, "SIMPLE")) /* this is the primary array */ { ffpinit(fptr, status); /* initialize the primary array */ if (hdutype != NULL) *hdutype = 0; } else if (!strcmp(name, "XTENSION")) /* this is an XTENSION keyword */ { if (ffc2s(value, xname, status) > 0) /* get the value string */ { ffpmsg("Bad value string for XTENSION keyword:"); ffpmsg(value); return(*status); } xtension = xname; while (*xtension == ' ') /* ignore any leading spaces in name */ xtension++; if (!strcmp(xtension, "TABLE")) { ffainit(fptr, status); /* initialize the ASCII table */ if (hdutype != NULL) *hdutype = 1; } else if (!strcmp(xtension, "BINTABLE") || !strcmp(xtension, "A3DTABLE") || !strcmp(xtension, "3DTABLE") ) { ffbinit(fptr, status); /* initialize the binary table */ if (hdutype != NULL) *hdutype = 2; } else { tstatus = 0; ffpinit(fptr, &tstatus); /* probably an IMAGE extension */ if (tstatus == UNKNOWN_EXT && hdutype != NULL) *hdutype = -1; /* don't recognize this extension type */ else { *status = tstatus; if (hdutype != NULL) *hdutype = 0; } } } else /* not the start of a new extension */ { if (card[0] == 0 || card[0] == 10) /* some editors append this character to EOF */ { *status = END_OF_FILE; } else { *status = UNKNOWN_REC; /* found unknown type of record */ ffpmsg ("Extension doesn't start with SIMPLE or XTENSION keyword. (ffrhdu)"); ffpmsg(card); } } /* compare the starting position of the next HDU (if any) with the size */ /* of the whole file to see if this is the last HDU in the file */ if ((fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1] < (fptr->Fptr)->logfilesize ) { (fptr->Fptr)->lasthdu = 0; /* no, not the last HDU */ } else { (fptr->Fptr)->lasthdu = 1; /* yes, this is the last HDU */ /* special code for mem:// type files (FITS file in memory) */ /* Allocate enough memory to hold the entire HDU. */ /* Without this code, CFITSIO would repeatedly realloc memory */ /* to incrementally increase the size of the file by 2880 bytes */ /* at a time, until it reached the final size */ ffurlt(fptr, urltype, status); if (!strcmp(urltype,"mem://") || !strcmp(urltype,"memkeep://")) { fftrun(fptr, (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1], status); } } return(*status); } /*--------------------------------------------------------------------------*/ int ffpinit(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ /* initialize the parameters defining the structure of the primary array or an Image extension */ { int groups, tstatus, simple, bitpix, naxis, extend, nspace; int ttype = 0, bytlen = 0, ii, ntilebins; long pcount, gcount; LONGLONG naxes[999], npix, blank; double bscale, bzero; char comm[FLEN_COMMENT]; tcolumn *colptr; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); (fptr->Fptr)->hdutype = IMAGE_HDU; /* primary array or IMAGE extension */ (fptr->Fptr)->headend = (fptr->Fptr)->logfilesize; /* set max size */ groups = 0; tstatus = *status; /* get all the descriptive info about this HDU */ ffgphd(fptr, 999, &simple, &bitpix, &naxis, naxes, &pcount, &gcount, &extend, &bscale, &bzero, &blank, &nspace, status); if (*status == NOT_IMAGE) *status = tstatus; /* ignore 'unknown extension type' error */ else if (*status > 0) return(*status); /* the logical end of the header is 80 bytes before the current position, minus any trailing blank keywords just before the END keyword. */ (fptr->Fptr)->headend = (fptr->Fptr)->nextkey - (80 * (nspace + 1)); /* the data unit begins at the beginning of the next logical block */ (fptr->Fptr)->datastart = (((fptr->Fptr)->nextkey - 80) / 2880 + 1) * 2880; if (naxis > 0 && naxes[0] == 0) /* test for 'random groups' */ { tstatus = 0; ffmaky(fptr, 2, status); /* reset to beginning of header */ if (ffgkyl(fptr, "GROUPS", &groups, comm, &tstatus)) groups = 0; /* GROUPS keyword not found */ } if (bitpix == BYTE_IMG) /* test bitpix and set the datatype code */ { ttype=TBYTE; bytlen=1; } else if (bitpix == SHORT_IMG) { ttype=TSHORT; bytlen=2; } else if (bitpix == LONG_IMG) { ttype=TLONG; bytlen=4; } else if (bitpix == LONGLONG_IMG) { ttype=TLONGLONG; bytlen=8; } else if (bitpix == FLOAT_IMG) { ttype=TFLOAT; bytlen=4; } else if (bitpix == DOUBLE_IMG) { ttype=TDOUBLE; bytlen=8; } /* calculate the size of the primary array */ (fptr->Fptr)->imgdim = naxis; if (naxis == 0) { npix = 0; } else { if (groups) { npix = 1; /* NAXIS1 = 0 is a special flag for 'random groups' */ } else { npix = naxes[0]; } (fptr->Fptr)->imgnaxis[0] = naxes[0]; for (ii=1; ii < naxis; ii++) { npix = npix*naxes[ii]; /* calc number of pixels in the array */ (fptr->Fptr)->imgnaxis[ii] = naxes[ii]; } } /* now we know everything about the array; just fill in the parameters: the next HDU begins in the next logical block after the data */ (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1] = (fptr->Fptr)->datastart + ( ((LONGLONG) pcount + npix) * bytlen * gcount + 2879) / 2880 * 2880; /* initialize the fictitious heap starting address (immediately following the array data) and a zero length heap. This is used to find the end of the data when checking the fill values in the last block. */ (fptr->Fptr)->heapstart = (npix + pcount) * bytlen * gcount; (fptr->Fptr)->heapsize = 0; (fptr->Fptr)->compressimg = 0; /* this is not a compressed image */ if (naxis == 0) { (fptr->Fptr)->rowlength = 0; /* rows have zero length */ (fptr->Fptr)->tfield = 0; /* table has no fields */ /* free the tile-compressed image cache, if it exists */ if ((fptr->Fptr)->tilerow) { ntilebins = (((fptr->Fptr)->znaxis[0] - 1) / ((fptr->Fptr)->tilesize[0])) + 1; for (ii = 0; ii < ntilebins; ii++) { if ((fptr->Fptr)->tiledata[ii]) { free((fptr->Fptr)->tiledata[ii]); } if ((fptr->Fptr)->tilenullarray[ii]) { free((fptr->Fptr)->tilenullarray[ii]); } } free((fptr->Fptr)->tileanynull); free((fptr->Fptr)->tiletype); free((fptr->Fptr)->tiledatasize); free((fptr->Fptr)->tilenullarray); free((fptr->Fptr)->tiledata); free((fptr->Fptr)->tilerow); (fptr->Fptr)->tileanynull = 0; (fptr->Fptr)->tiletype = 0; (fptr->Fptr)->tiledatasize = 0; (fptr->Fptr)->tilenullarray = 0; (fptr->Fptr)->tiledata = 0; (fptr->Fptr)->tilerow = 0; } if ((fptr->Fptr)->tableptr) free((fptr->Fptr)->tableptr); /* free memory for the old CHDU */ (fptr->Fptr)->tableptr = 0; /* set a null table structure pointer */ (fptr->Fptr)->numrows = 0; (fptr->Fptr)->origrows = 0; } else { /* The primary array is actually interpreted as a binary table. There are two columns: the first column contains the group parameters if any. The second column contains the primary array of data as a single vector column element. In the case of 'random grouped' format, each group is stored in a separate row of the table. */ /* the number of rows is equal to the number of groups */ (fptr->Fptr)->numrows = gcount; (fptr->Fptr)->origrows = gcount; (fptr->Fptr)->rowlength = (npix + pcount) * bytlen; /* total size */ (fptr->Fptr)->tfield = 2; /* 2 fields: group params and the image */ /* free the tile-compressed image cache, if it exists */ if ((fptr->Fptr)->tilerow) { ntilebins = (((fptr->Fptr)->znaxis[0] - 1) / ((fptr->Fptr)->tilesize[0])) + 1; for (ii = 0; ii < ntilebins; ii++) { if ((fptr->Fptr)->tiledata[ii]) { free((fptr->Fptr)->tiledata[ii]); } if ((fptr->Fptr)->tilenullarray[ii]) { free((fptr->Fptr)->tilenullarray[ii]); } } free((fptr->Fptr)->tileanynull); free((fptr->Fptr)->tiletype); free((fptr->Fptr)->tiledatasize); free((fptr->Fptr)->tilenullarray); free((fptr->Fptr)->tiledata); free((fptr->Fptr)->tilerow); (fptr->Fptr)->tileanynull = 0; (fptr->Fptr)->tiletype = 0; (fptr->Fptr)->tiledatasize = 0; (fptr->Fptr)->tilenullarray = 0; (fptr->Fptr)->tiledata = 0; (fptr->Fptr)->tilerow = 0; } if ((fptr->Fptr)->tableptr) free((fptr->Fptr)->tableptr); /* free memory for the old CHDU */ colptr = (tcolumn *) calloc(2, sizeof(tcolumn) ) ; if (!colptr) { ffpmsg ("malloc failed to get memory for FITS array descriptors (ffpinit)"); (fptr->Fptr)->tableptr = 0; /* set a null table structure pointer */ return(*status = ARRAY_TOO_BIG); } /* copy the table structure address to the fitsfile structure */ (fptr->Fptr)->tableptr = colptr; /* the first column represents the group parameters, if any */ colptr->tbcol = 0; colptr->tdatatype = ttype; colptr->twidth = bytlen; colptr->trepeat = (LONGLONG) pcount; colptr->tscale = 1.; colptr->tzero = 0.; colptr->tnull = blank; colptr++; /* increment pointer to the second column */ /* the second column represents the image array */ colptr->tbcol = pcount * bytlen; /* col starts after the group parms */ colptr->tdatatype = ttype; colptr->twidth = bytlen; colptr->trepeat = npix; colptr->tscale = bscale; colptr->tzero = bzero; colptr->tnull = blank; } /* reset next keyword pointer to the start of the header */ (fptr->Fptr)->nextkey = (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu ]; return(*status); } /*--------------------------------------------------------------------------*/ int ffainit(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ { /* initialize the parameters defining the structure of an ASCII table */ int ii, nspace, ntilebins; long tfield; LONGLONG pcount, rowlen, nrows, tbcoln; tcolumn *colptr = 0; char name[FLEN_KEYWORD], value[FLEN_VALUE], comm[FLEN_COMMENT]; char message[FLEN_ERRMSG], errmsg[FLEN_ERRMSG]; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); (fptr->Fptr)->hdutype = ASCII_TBL; /* set that this is an ASCII table */ (fptr->Fptr)->headend = (fptr->Fptr)->logfilesize; /* set max size */ /* get table parameters and test that the header is a valid: */ if (ffgttb(fptr, &rowlen, &nrows, &pcount, &tfield, status) > 0) return(*status); if (pcount != 0) { ffpmsg("PCOUNT keyword not equal to 0 in ASCII table (ffainit)."); snprintf(errmsg, FLEN_ERRMSG," PCOUNT = %ld", (long) pcount); ffpmsg(errmsg); return(*status = BAD_PCOUNT); } (fptr->Fptr)->rowlength = rowlen; /* store length of a row */ (fptr->Fptr)->tfield = tfield; /* store number of table fields in row */ /* free the tile-compressed image cache, if it exists */ if ((fptr->Fptr)->tilerow) { ntilebins = (((fptr->Fptr)->znaxis[0] - 1) / ((fptr->Fptr)->tilesize[0])) + 1; for (ii = 0; ii < ntilebins; ii++) { if ((fptr->Fptr)->tiledata[ii]) { free((fptr->Fptr)->tiledata[ii]); } if ((fptr->Fptr)->tilenullarray[ii]) { free((fptr->Fptr)->tilenullarray[ii]); } } free((fptr->Fptr)->tileanynull); free((fptr->Fptr)->tiletype); free((fptr->Fptr)->tiledatasize); free((fptr->Fptr)->tilenullarray); free((fptr->Fptr)->tiledata); free((fptr->Fptr)->tilerow); (fptr->Fptr)->tileanynull = 0; (fptr->Fptr)->tiletype = 0; (fptr->Fptr)->tiledatasize = 0; (fptr->Fptr)->tilenullarray = 0; (fptr->Fptr)->tiledata = 0; (fptr->Fptr)->tilerow = 0; } if ((fptr->Fptr)->tableptr) free((fptr->Fptr)->tableptr); /* free memory for the old CHDU */ /* mem for column structures ; space is initialized = 0 */ if (tfield > 0) { colptr = (tcolumn *) calloc(tfield, sizeof(tcolumn) ); if (!colptr) { ffpmsg ("malloc failed to get memory for FITS table descriptors (ffainit)"); (fptr->Fptr)->tableptr = 0; /* set a null table structure pointer */ return(*status = ARRAY_TOO_BIG); } } /* copy the table structure address to the fitsfile structure */ (fptr->Fptr)->tableptr = colptr; /* initialize the table field parameters */ for (ii = 0; ii < tfield; ii++, colptr++) { colptr->ttype[0] = '\0'; /* null column name */ colptr->tscale = 1.; colptr->tzero = 0.; colptr->strnull[0] = ASCII_NULL_UNDEFINED; /* null value undefined */ colptr->tbcol = -1; /* initialize to illegal value */ colptr->tdatatype = -9999; /* initialize to illegal value */ } /* Initialize the fictitious heap starting address (immediately following the table data) and a zero length heap. This is used to find the end of the table data when checking the fill values in the last block. There is no special data following an ASCII table. */ (fptr->Fptr)->numrows = nrows; (fptr->Fptr)->origrows = nrows; (fptr->Fptr)->heapstart = rowlen * nrows; (fptr->Fptr)->heapsize = 0; (fptr->Fptr)->compressimg = 0; /* this is not a compressed image */ /* now search for the table column keywords and the END keyword */ for (nspace = 0, ii = 8; 1; ii++) /* infinite loop */ { ffgkyn(fptr, ii, name, value, comm, status); /* try to ignore minor syntax errors */ if (*status == NO_QUOTE) { strcat(value, "'"); *status = 0; } else if (*status == BAD_KEYCHAR) { *status = 0; } if (*status == END_OF_FILE) { ffpmsg("END keyword not found in ASCII table header (ffainit)."); return(*status = NO_END); } else if (*status > 0) return(*status); else if (name[0] == 'T') /* keyword starts with 'T' ? */ ffgtbp(fptr, name, value, status); /* test if column keyword */ else if (!FSTRCMP(name, "END")) /* is this the END keyword? */ break; if (!name[0] && !value[0] && !comm[0]) /* a blank keyword? */ nspace++; else nspace = 0; } /* test that all required keywords were found and have legal values */ colptr = (fptr->Fptr)->tableptr; for (ii = 0; ii < tfield; ii++, colptr++) { tbcoln = colptr->tbcol; /* the starting column number (zero based) */ if (colptr->tdatatype == -9999) { ffkeyn("TFORM", ii+1, name, status); /* construct keyword name */ snprintf(message,FLEN_ERRMSG,"Required %s keyword not found (ffainit).", name); ffpmsg(message); return(*status = NO_TFORM); } else if (tbcoln == -1) { ffkeyn("TBCOL", ii+1, name, status); /* construct keyword name */ snprintf(message,FLEN_ERRMSG,"Required %s keyword not found (ffainit).", name); ffpmsg(message); return(*status = NO_TBCOL); } else if ((fptr->Fptr)->rowlength != 0 && (tbcoln < 0 || tbcoln >= (fptr->Fptr)->rowlength ) ) { ffkeyn("TBCOL", ii+1, name, status); /* construct keyword name */ snprintf(message,FLEN_ERRMSG,"Value of %s keyword out of range: %ld (ffainit).", name, (long) tbcoln); ffpmsg(message); return(*status = BAD_TBCOL); } else if ((fptr->Fptr)->rowlength != 0 && tbcoln + colptr->twidth > (fptr->Fptr)->rowlength ) { snprintf(message,FLEN_ERRMSG,"Column %d is too wide to fit in table (ffainit)", ii+1); ffpmsg(message); snprintf(message, FLEN_ERRMSG," TFORM = %s and NAXIS1 = %ld", colptr->tform, (long) (fptr->Fptr)->rowlength); ffpmsg(message); return(*status = COL_TOO_WIDE); } } /* now we know everything about the table; just fill in the parameters: the 'END' record is 80 bytes before the current position, minus any trailing blank keywords just before the END keyword. */ (fptr->Fptr)->headend = (fptr->Fptr)->nextkey - (80 * (nspace + 1)); /* the data unit begins at the beginning of the next logical block */ (fptr->Fptr)->datastart = (((fptr->Fptr)->nextkey - 80) / 2880 + 1) * 2880; /* the next HDU begins in the next logical block after the data */ (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1] = (fptr->Fptr)->datastart + ( ((LONGLONG)rowlen * nrows + 2879) / 2880 * 2880 ); /* reset next keyword pointer to the start of the header */ (fptr->Fptr)->nextkey = (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu ]; return(*status); } /*--------------------------------------------------------------------------*/ int ffbinit(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ { /* initialize the parameters defining the structure of a binary table */ int ii, nspace, ntilebins; long tfield; LONGLONG pcount, rowlen, nrows, totalwidth; tcolumn *colptr = 0; char name[FLEN_KEYWORD], value[FLEN_VALUE], comm[FLEN_COMMENT]; char message[FLEN_ERRMSG]; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); (fptr->Fptr)->hdutype = BINARY_TBL; /* set that this is a binary table */ (fptr->Fptr)->headend = (fptr->Fptr)->logfilesize; /* set max size */ /* get table parameters and test that the header is valid: */ if (ffgttb(fptr, &rowlen, &nrows, &pcount, &tfield, status) > 0) return(*status); (fptr->Fptr)->rowlength = rowlen; /* store length of a row */ (fptr->Fptr)->tfield = tfield; /* store number of table fields in row */ /* free the tile-compressed image cache, if it exists */ if ((fptr->Fptr)->tilerow) { ntilebins = (((fptr->Fptr)->znaxis[0] - 1) / ((fptr->Fptr)->tilesize[0])) + 1; for (ii = 0; ii < ntilebins; ii++) { if ((fptr->Fptr)->tiledata[ii]) { free((fptr->Fptr)->tiledata[ii]); } if ((fptr->Fptr)->tilenullarray[ii]) { free((fptr->Fptr)->tilenullarray[ii]); } } free((fptr->Fptr)->tileanynull); free((fptr->Fptr)->tiletype); free((fptr->Fptr)->tiledatasize); free((fptr->Fptr)->tilenullarray); free((fptr->Fptr)->tiledata); free((fptr->Fptr)->tilerow); (fptr->Fptr)->tileanynull = 0; (fptr->Fptr)->tiletype = 0; (fptr->Fptr)->tiledatasize = 0; (fptr->Fptr)->tilenullarray = 0; (fptr->Fptr)->tiledata = 0; (fptr->Fptr)->tilerow = 0; } if ((fptr->Fptr)->tableptr) free((fptr->Fptr)->tableptr); /* free memory for the old CHDU */ /* mem for column structures ; space is initialized = 0 */ if (tfield > 0) { colptr = (tcolumn *) calloc(tfield, sizeof(tcolumn) ); if (!colptr) { ffpmsg ("malloc failed to get memory for FITS table descriptors (ffbinit)"); (fptr->Fptr)->tableptr = 0; /* set a null table structure pointer */ return(*status = ARRAY_TOO_BIG); } } /* copy the table structure address to the fitsfile structure */ (fptr->Fptr)->tableptr = colptr; /* initialize the table field parameters */ for (ii = 0; ii < tfield; ii++, colptr++) { colptr->ttype[0] = '\0'; /* null column name */ colptr->tscale = 1.; colptr->tzero = 0.; colptr->tnull = NULL_UNDEFINED; /* (integer) null value undefined */ colptr->tdatatype = -9999; /* initialize to illegal value */ colptr->trepeat = 1; colptr->strnull[0] = '\0'; /* for ASCII string columns (TFORM = rA) */ } /* Initialize the heap starting address (immediately following the table data) and the size of the heap. This is used to find the end of the table data when checking the fill values in the last block. */ (fptr->Fptr)->numrows = nrows; (fptr->Fptr)->origrows = nrows; (fptr->Fptr)->heapstart = rowlen * nrows; (fptr->Fptr)->heapsize = pcount; (fptr->Fptr)->compressimg = 0; /* initialize as not a compressed image */ /* now search for the table column keywords and the END keyword */ for (nspace = 0, ii = 8; 1; ii++) /* infinite loop */ { ffgkyn(fptr, ii, name, value, comm, status); /* try to ignore minor syntax errors */ if (*status == NO_QUOTE) { strcat(value, "'"); *status = 0; } else if (*status == BAD_KEYCHAR) { *status = 0; } if (*status == END_OF_FILE) { ffpmsg("END keyword not found in binary table header (ffbinit)."); return(*status = NO_END); } else if (*status > 0) return(*status); else if (name[0] == 'T') /* keyword starts with 'T' ? */ ffgtbp(fptr, name, value, status); /* test if column keyword */ else if (!FSTRCMP(name, "ZIMAGE")) { if (value[0] == 'T') (fptr->Fptr)->compressimg = 1; /* this is a compressed image */ } else if (!FSTRCMP(name, "END")) /* is this the END keyword? */ break; if (!name[0] && !value[0] && !comm[0]) /* a blank keyword? */ nspace++; else nspace = 0; /* reset number of consecutive spaces before END */ } /* test that all the required keywords were found and have legal values */ colptr = (fptr->Fptr)->tableptr; /* set pointer to first column */ for (ii = 0; ii < tfield; ii++, colptr++) { if (colptr->tdatatype == -9999) { ffkeyn("TFORM", ii+1, name, status); /* construct keyword name */ snprintf(message,FLEN_ERRMSG,"Required %s keyword not found (ffbinit).", name); ffpmsg(message); return(*status = NO_TFORM); } } /* now we know everything about the table; just fill in the parameters: the 'END' record is 80 bytes before the current position, minus any trailing blank keywords just before the END keyword. */ (fptr->Fptr)->headend = (fptr->Fptr)->nextkey - (80 * (nspace + 1)); /* the data unit begins at the beginning of the next logical block */ (fptr->Fptr)->datastart = (((fptr->Fptr)->nextkey - 80) / 2880 + 1) * 2880; /* the next HDU begins in the next logical block after the data */ (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1] = (fptr->Fptr)->datastart + ( ((fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize + 2879) / 2880 * 2880 ); /* determine the byte offset to the beginning of each column */ ffgtbc(fptr, &totalwidth, status); if (totalwidth != rowlen) { snprintf(message,FLEN_ERRMSG, "NAXIS1 = %ld is not equal to the sum of column widths: %ld", (long) rowlen, (long) totalwidth); ffpmsg(message); *status = BAD_ROW_WIDTH; } /* reset next keyword pointer to the start of the header */ (fptr->Fptr)->nextkey = (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu ]; if ( (fptr->Fptr)->compressimg == 1) /* Is this a compressed image */ imcomp_get_compressed_image_par(fptr, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffgabc(int tfields, /* I - number of columns in the table */ char **tform, /* I - value of TFORMn keyword for each column */ int space, /* I - number of spaces to leave between cols */ long *rowlen, /* O - total width of a table row */ long *tbcol, /* O - starting byte in row for each column */ int *status) /* IO - error status */ /* calculate the starting byte offset of each column of an ASCII table and the total length of a row, in bytes. The input space value determines how many blank spaces to leave between each column (1 is recommended). */ { int ii, datacode, decims; long width; if (*status > 0) return(*status); *rowlen=0; if (tfields <= 0) return(*status); tbcol[0] = 1; for (ii = 0; ii < tfields; ii++) { tbcol[ii] = *rowlen + 1; /* starting byte in row of column */ ffasfm(tform[ii], &datacode, &width, &decims, status); *rowlen += (width + space); /* total length of row */ } *rowlen -= space; /* don't add space after the last field */ return (*status); } /*--------------------------------------------------------------------------*/ int ffgtbc(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG *totalwidth, /* O - total width of a table row */ int *status) /* IO - error status */ { /* calculate the starting byte offset of each column of a binary table. Use the values of the datatype code and repeat counts in the column structure. Return the total length of a row, in bytes. */ int tfields, ii; LONGLONG nbytes; tcolumn *colptr; char message[FLEN_ERRMSG], *cptr; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); tfields = (fptr->Fptr)->tfield; colptr = (fptr->Fptr)->tableptr; /* point to first column structure */ *totalwidth = 0; for (ii = 0; ii < tfields; ii++, colptr++) { colptr->tbcol = *totalwidth; /* byte offset in row to this column */ if (colptr->tdatatype == TSTRING) { nbytes = colptr->trepeat; /* one byte per char */ } else if (colptr->tdatatype == TBIT) { nbytes = ( colptr->trepeat + 7) / 8; } else if (colptr->tdatatype > 0) { nbytes = colptr->trepeat * (colptr->tdatatype / 10); } else { cptr = colptr->tform; while (isdigit(*cptr)) cptr++; if (*cptr == 'P') /* this is a 'P' variable length descriptor (neg. tdatatype) */ nbytes = colptr->trepeat * 8; else if (*cptr == 'Q') /* this is a 'Q' variable length descriptor (neg. tdatatype) */ nbytes = colptr->trepeat * 16; else { snprintf(message,FLEN_ERRMSG, "unknown binary table column type: %s", colptr->tform); ffpmsg(message); *status = BAD_TFORM; return(*status); } } *totalwidth = *totalwidth + nbytes; } return(*status); } /*--------------------------------------------------------------------------*/ int ffgtbp(fitsfile *fptr, /* I - FITS file pointer */ char *name, /* I - name of the keyword */ char *value, /* I - value string of the keyword */ int *status) /* IO - error status */ { /* Get TaBle Parameter. The input keyword name begins with the letter T. Test if the keyword is one of the table column definition keywords of an ASCII or binary table. If so, decode it and update the value in the structure. */ int tstatus, datacode, decimals; long width, repeat, nfield, ivalue; LONGLONG jjvalue; double dvalue; char tvalue[FLEN_VALUE], *loc; char message[FLEN_ERRMSG]; tcolumn *colptr; if (*status > 0) return(*status); tstatus = 0; /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); if(!FSTRNCMP(name + 1, "TYPE", 4) ) { /* get the index number */ if( ffc2ii(name + 5, &nfield, &tstatus) > 0) /* read index no. */ return(*status); /* must not be an indexed keyword */ if (nfield < 1 || nfield > (fptr->Fptr)->tfield ) /* out of range */ return(*status); colptr = (fptr->Fptr)->tableptr; /* get pointer to columns */ colptr = colptr + nfield - 1; /* point to the correct column */ if (ffc2s(value, tvalue, &tstatus) > 0) /* remove quotes */ return(*status); strcpy(colptr->ttype, tvalue); /* copy col name to structure */ } else if(!FSTRNCMP(name + 1, "FORM", 4) ) { /* get the index number */ if( ffc2ii(name + 5, &nfield, &tstatus) > 0) /* read index no. */ return(*status); /* must not be an indexed keyword */ if (nfield < 1 || nfield > (fptr->Fptr)->tfield ) /* out of range */ return(*status); colptr = (fptr->Fptr)->tableptr; /* get pointer to columns */ colptr = colptr + nfield - 1; /* point to the correct column */ if (ffc2s(value, tvalue, &tstatus) > 0) /* remove quotes */ return(*status); strncpy(colptr->tform, tvalue, 9); /* copy TFORM to structure */ colptr->tform[9] = '\0'; /* make sure it is terminated */ if ((fptr->Fptr)->hdutype == ASCII_TBL) /* ASCII table */ { if (ffasfm(tvalue, &datacode, &width, &decimals, status) > 0) return(*status); /* bad format code */ colptr->tdatatype = TSTRING; /* store datatype code */ colptr->trepeat = 1; /* field repeat count == 1 */ colptr->twidth = width; /* the width of the field, in bytes */ } else /* binary table */ { if (ffbnfm(tvalue, &datacode, &repeat, &width, status) > 0) return(*status); /* bad format code */ colptr->tdatatype = datacode; /* store datatype code */ colptr->trepeat = (LONGLONG) repeat; /* field repeat count */ /* Don't overwrite the unit string width if it was previously */ /* set by a TDIMn keyword and has a legal value */ if (datacode == TSTRING) { if (colptr->twidth == 0 || colptr->twidth > repeat) colptr->twidth = width; /* width of a unit string */ } else { colptr->twidth = width; /* width of a unit value in chars */ } } } else if(!FSTRNCMP(name + 1, "BCOL", 4) ) { /* get the index number */ if( ffc2ii(name + 5, &nfield, &tstatus) > 0) /* read index no. */ return(*status); /* must not be an indexed keyword */ if (nfield < 1 || nfield > (fptr->Fptr)->tfield ) /* out of range */ return(*status); colptr = (fptr->Fptr)->tableptr; /* get pointer to columns */ colptr = colptr + nfield - 1; /* point to the correct column */ if ((fptr->Fptr)->hdutype == BINARY_TBL) return(*status); /* binary tables don't have TBCOL keywords */ if (ffc2ii(value, &ivalue, status) > 0) { snprintf(message, FLEN_ERRMSG, "Error reading value of %s as an integer: %s", name, value); ffpmsg(message); return(*status); } colptr->tbcol = ivalue - 1; /* convert to zero base */ } else if(!FSTRNCMP(name + 1, "SCAL", 4) ) { /* get the index number */ if( ffc2ii(name + 5, &nfield, &tstatus) > 0) /* read index no. */ return(*status); /* must not be an indexed keyword */ if (nfield < 1 || nfield > (fptr->Fptr)->tfield ) /* out of range */ return(*status); colptr = (fptr->Fptr)->tableptr; /* get pointer to columns */ colptr = colptr + nfield - 1; /* point to the correct column */ if (ffc2dd(value, &dvalue, &tstatus) > 0) { snprintf(message,FLEN_ERRMSG, "Error reading value of %s as a double: %s", name, value); ffpmsg(message); /* ignore this error, so don't return error status */ return(*status); } colptr->tscale = dvalue; } else if(!FSTRNCMP(name + 1, "ZERO", 4) ) { /* get the index number */ if( ffc2ii(name + 5, &nfield, &tstatus) > 0) /* read index no. */ return(*status); /* must not be an indexed keyword */ if (nfield < 1 || nfield > (fptr->Fptr)->tfield ) /* out of range */ return(*status); colptr = (fptr->Fptr)->tableptr; /* get pointer to columns */ colptr = colptr + nfield - 1; /* point to the correct column */ if (ffc2dd(value, &dvalue, &tstatus) > 0) { snprintf(message,FLEN_ERRMSG, "Error reading value of %s as a double: %s", name, value); ffpmsg(message); /* ignore this error, so don't return error status */ return(*status); } colptr->tzero = dvalue; } else if(!FSTRNCMP(name + 1, "NULL", 4) ) { /* get the index number */ if( ffc2ii(name + 5, &nfield, &tstatus) > 0) /* read index no. */ return(*status); /* must not be an indexed keyword */ if (nfield < 1 || nfield > (fptr->Fptr)->tfield ) /* out of range */ return(*status); colptr = (fptr->Fptr)->tableptr; /* get pointer to columns */ colptr = colptr + nfield - 1; /* point to the correct column */ if ((fptr->Fptr)->hdutype == ASCII_TBL) /* ASCII table */ { if (ffc2s(value, tvalue, &tstatus) > 0) /* remove quotes */ return(*status); strncpy(colptr->strnull, tvalue, 17); /* copy TNULL string */ colptr->strnull[17] = '\0'; /* terminate the strnull field */ } else /* binary table */ { if (ffc2jj(value, &jjvalue, &tstatus) > 0) { snprintf(message,FLEN_ERRMSG, "Error reading value of %s as an integer: %s", name, value); ffpmsg(message); /* ignore this error, so don't return error status */ return(*status); } colptr->tnull = jjvalue; /* null value for integer column */ } } else if(!FSTRNCMP(name + 1, "DIM", 3) ) { if ((fptr->Fptr)->hdutype == ASCII_TBL) /* ASCII table */ return(*status); /* ASCII tables don't support TDIMn keyword */ /* get the index number */ if( ffc2ii(name + 4, &nfield, &tstatus) > 0) /* read index no. */ return(*status); /* must not be an indexed keyword */ if (nfield < 1 || nfield > (fptr->Fptr)->tfield ) /* out of range */ return(*status); colptr = (fptr->Fptr)->tableptr; /* get pointer to columns */ colptr = colptr + nfield - 1; /* point to the correct column */ /* uninitialized columns have tdatatype set = -9999 */ if (colptr->tdatatype != -9999 && colptr->tdatatype != TSTRING) return(*status); /* this is not an ASCII string column */ loc = strchr(value, '(' ); /* find the opening parenthesis */ if (!loc) return(*status); /* not a proper TDIM keyword */ loc++; width = strtol(loc, &loc, 10); /* read size of first dimension */ if (colptr->trepeat != 1 && colptr->trepeat < width) return(*status); /* string length is greater than column width */ colptr->twidth = width; /* set width of a unit string in chars */ } else if (!FSTRNCMP(name + 1, "HEAP", 4) ) { if ((fptr->Fptr)->hdutype == ASCII_TBL) /* ASCII table */ return(*status); /* ASCII tables don't have a heap */ if (ffc2jj(value, &jjvalue, &tstatus) > 0) { snprintf(message,FLEN_ERRMSG, "Error reading value of %s as an integer: %s", name, value); ffpmsg(message); /* ignore this error, so don't return error status */ return(*status); } (fptr->Fptr)->heapstart = jjvalue; /* starting byte of the heap */ return(*status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffgcprll( fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number (1 = 1st column of table) */ LONGLONG firstrow, /* I - first row (1 = 1st row of table) */ LONGLONG firstelem, /* I - first element within vector (1 = 1st) */ LONGLONG nelem, /* I - number of elements to read or write */ int writemode, /* I - = 1 if writing data, = 0 if reading data */ /* If = 2, then writing data, but don't modify */ /* the returned values of repeat and incre. */ /* If = -1, then reading data in reverse */ /* direction. */ double *scale, /* O - FITS scaling factor (TSCALn keyword value) */ double *zero, /* O - FITS scaling zero pt (TZEROn keyword value) */ char *tform, /* O - ASCII column format: value of TFORMn keyword */ long *twidth, /* O - width of ASCII column (characters) */ int *tcode, /* O - column datatype code: I*4=41, R*4=42, etc */ int *maxelem, /* O - max number of elements that fit in buffer */ LONGLONG *startpos,/* O - offset in file to starting row & column */ LONGLONG *elemnum, /* O - starting element number ( 0 = 1st element) */ long *incre, /* O - byte offset between elements within a row */ LONGLONG *repeat, /* O - number of elements in a row (vector column) */ LONGLONG *rowlen, /* O - length of a row, in bytes */ int *hdutype, /* O - HDU type: 0, 1, 2 = primary, table, bintable */ LONGLONG *tnull, /* O - null value for integer columns */ char *snull, /* O - null value for ASCII table columns */ int *status) /* IO - error status */ /* Get Column PaRameters, and test starting row and element numbers for validity. This is a workhorse routine that is call by nearly every other routine that reads or writes to FITS files. */ { int nulpos, rangecheck = 1, tstatus = 0; LONGLONG datastart, endpos; long nblock; LONGLONG heapoffset, lrepeat, endrow, nrows, tbcol; char message[FLEN_ERRMSG]; tcolumn *colptr; if (fptr->HDUposition != (fptr->Fptr)->curhdu) { /* reset position to the correct HDU if necessary */ ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) { /* rescan header if data structure is undefined */ if ( ffrdef(fptr, status) > 0) return(*status); } else if (writemode > 0) { /* Only terminate the header with the END card if */ /* writing to the stdout stream (don't have random access). */ /* Initialize STREAM_DRIVER to be the device number for */ /* writing FITS files directly out to the stdout stream. */ /* This only needs to be done once and is thread safe. */ if (STREAM_DRIVER <= 0 || STREAM_DRIVER > 40) { urltype2driver("stream://", &STREAM_DRIVER); } if ((fptr->Fptr)->driver == STREAM_DRIVER) { if ((fptr->Fptr)->ENDpos != maxvalue((fptr->Fptr)->headend , (fptr->Fptr)->datastart -2880)) { ffwend(fptr, status); } } } /* Do sanity check of input parameters */ if (firstrow < 1) { if ((fptr->Fptr)->hdutype == IMAGE_HDU) /* Primary Array or IMAGE */ { snprintf(message,FLEN_ERRMSG, "Image group number is less than 1: %.0f", (double) firstrow); ffpmsg(message); return(*status = BAD_ROW_NUM); } else { snprintf(message, FLEN_ERRMSG,"Starting row number is less than 1: %.0f", (double) firstrow); ffpmsg(message); return(*status = BAD_ROW_NUM); } } else if ((fptr->Fptr)->hdutype != ASCII_TBL && firstelem < 1) { snprintf(message, FLEN_ERRMSG,"Starting element number less than 1: %ld", (long) firstelem); ffpmsg(message); return(*status = BAD_ELEM_NUM); } else if (nelem < 0) { snprintf(message, FLEN_ERRMSG,"Tried to read or write less than 0 elements: %.0f", (double) nelem); ffpmsg(message); return(*status = NEG_BYTES); } else if (colnum < 1 || colnum > (fptr->Fptr)->tfield) { snprintf(message, FLEN_ERRMSG,"Specified column number is out of range: %d", colnum); ffpmsg(message); snprintf(message, FLEN_ERRMSG," There are %d columns in this table.", (fptr->Fptr)->tfield ); ffpmsg(message); return(*status = BAD_COL_NUM); } /* copy relevant parameters from the structure */ *hdutype = (fptr->Fptr)->hdutype; /* image, ASCII table, or BINTABLE */ *rowlen = (fptr->Fptr)->rowlength; /* width of the table, in bytes */ datastart = (fptr->Fptr)->datastart; /* offset in file to start of table */ colptr = (fptr->Fptr)->tableptr; /* point to first column */ colptr += (colnum - 1); /* offset to correct column structure */ *scale = colptr->tscale; /* value scaling factor; default = 1.0 */ *zero = colptr->tzero; /* value scaling zeropoint; default = 0.0 */ *tnull = colptr->tnull; /* null value for integer columns */ tbcol = colptr->tbcol; /* offset to start of column within row */ *twidth = colptr->twidth; /* width of a single datum, in bytes */ *incre = colptr->twidth; /* increment between datums, in bytes */ *tcode = colptr->tdatatype; *repeat = colptr->trepeat; strcpy(tform, colptr->tform); /* value of TFORMn keyword */ strcpy(snull, colptr->strnull); /* null value for ASCII table columns */ if (*hdutype == ASCII_TBL && snull[0] == '\0') { /* In ASCII tables, a null value is equivalent to all spaces */ strcpy(snull, " "); /* maximum of 17 spaces */ nulpos = minvalue(17, *twidth); /* truncate to width of column */ snull[nulpos] = '\0'; } /* Special case: interpret writemode = -1 as reading data, but */ /* don't do error check for exceeding the range of pixels */ if (writemode == -1) { writemode = 0; rangecheck = 0; } /* Special case: interprete 'X' column as 'B' */ if (abs(*tcode) == TBIT) { *tcode = *tcode / TBIT * TBYTE; *repeat = (*repeat + 7) / 8; } /* Special case: support the 'rAw' format in BINTABLEs */ if (*hdutype == BINARY_TBL && *tcode == TSTRING) { *repeat = *repeat / *twidth; /* repeat = # of unit strings in field */ } else if (*hdutype == BINARY_TBL && *tcode == -TSTRING) { /* variable length string */ *incre = 1; *twidth = (long) nelem; } if (*hdutype == ASCII_TBL) *elemnum = 0; /* ASCII tables don't have vector elements */ else *elemnum = firstelem - 1; /* interprete complex and double complex as pairs of floats or doubles */ if (abs(*tcode) >= TCOMPLEX) { if (*tcode > 0) *tcode = (*tcode + 1) / 2; else *tcode = (*tcode - 1) / 2; *repeat = *repeat * 2; *twidth = *twidth / 2; *incre = *incre / 2; } /* calculate no. of pixels that fit in buffer */ /* allow for case where floats are 8 bytes long */ if (abs(*tcode) == TFLOAT) *maxelem = DBUFFSIZE / sizeof(float); else if (abs(*tcode) == TDOUBLE) *maxelem = DBUFFSIZE / sizeof(double); else if (abs(*tcode) == TSTRING) { *maxelem = (DBUFFSIZE - 1)/ *twidth; /* leave room for final \0 */ if (*maxelem == 0) { snprintf(message,FLEN_ERRMSG, "ASCII string column is too wide: %ld; max supported width is %d", *twidth, DBUFFSIZE - 1); ffpmsg(message); return(*status = COL_TOO_WIDE); } } else *maxelem = DBUFFSIZE / *twidth; /* calc starting byte position to 1st element of col */ /* (this does not apply to variable length columns) */ *startpos = datastart + ((LONGLONG)(firstrow - 1) * *rowlen) + tbcol; if (*hdutype == IMAGE_HDU && writemode) /* Primary Array or IMAGE */ { /* For primary arrays, set the repeat count greater than the total number of pixels to be written. This prevents an out-of-range error message in cases where the final image array size is not yet known or defined. */ if (*repeat < *elemnum + nelem) *repeat = *elemnum + nelem; } else if (*tcode > 0) /* Fixed length table column */ { if (*elemnum >= *repeat) { snprintf(message,FLEN_ERRMSG, "First element to write is too large: %ld; max allowed value is %ld", (long) ((*elemnum) + 1), (long) *repeat); ffpmsg(message); return(*status = BAD_ELEM_NUM); } /* last row number to be read or written */ endrow = ((*elemnum + nelem - 1) / *repeat) + firstrow; if (writemode) { /* check if we are writing beyond the current end of table */ if ((endrow > (fptr->Fptr)->numrows) && (nelem > 0) ) { /* if there are more HDUs following the current one, or */ /* if there is a data heap, then we must insert space */ /* for the new rows. */ if ( !((fptr->Fptr)->lasthdu) || (fptr->Fptr)->heapsize > 0) { nrows = endrow - ((fptr->Fptr)->numrows); if (ffirow(fptr, (fptr->Fptr)->numrows, nrows, status) > 0) { snprintf(message,FLEN_ERRMSG, "Failed to add space for %.0f new rows in table.", (double) nrows); ffpmsg(message); return(*status); } } else { /* update heap starting address */ (fptr->Fptr)->heapstart += ((LONGLONG)(endrow - (fptr->Fptr)->numrows) * (fptr->Fptr)->rowlength ); (fptr->Fptr)->numrows = endrow; /* update number of rows */ } } } else /* reading from the file */ { if ( endrow > (fptr->Fptr)->numrows && rangecheck) { if (*hdutype == IMAGE_HDU) /* Primary Array or IMAGE */ { if (firstrow > (fptr->Fptr)->numrows) { snprintf(message, FLEN_ERRMSG, "Attempted to read from group %ld of the HDU,", (long) firstrow); ffpmsg(message); snprintf(message, FLEN_ERRMSG, "however the HDU only contains %ld group(s).", (long) ((fptr->Fptr)->numrows) ); ffpmsg(message); } else { ffpmsg("Attempt to read past end of array:"); snprintf(message, FLEN_ERRMSG, " Image has %ld elements;", (long) *repeat); ffpmsg(message); snprintf(message, FLEN_ERRMSG, " Tried to read %ld elements starting at element %ld.", (long) nelem, (long) firstelem); ffpmsg(message); } } else { ffpmsg("Attempt to read past end of table:"); snprintf(message, FLEN_ERRMSG, " Table has %.0f rows with %.0f elements per row;", (double) ((fptr->Fptr)->numrows), (double) *repeat); ffpmsg(message); snprintf(message, FLEN_ERRMSG, " Tried to read %.0f elements starting at row %.0f, element %.0f.", (double) nelem, (double) firstrow, (double) ((*elemnum) + 1)); ffpmsg(message); } return(*status = BAD_ROW_NUM); } } if (*repeat == 1 && nelem > 1 && writemode != 2) { /* When accessing a scalar column, fool the calling routine into thinking that this is a vector column with very big elements. This allows multiple values (up to the maxelem number of elements that will fit in the buffer) to be read or written with a single routine call, which increases the efficiency. If writemode == 2, then the calling program does not want to have this efficiency trick applied. */ if (*rowlen <= LONG_MAX) { *incre = (long) *rowlen; *repeat = nelem; } } } else /* Variable length Binary Table column */ { *tcode *= (-1); if (writemode) /* return next empty heap address for writing */ { *repeat = nelem + *elemnum; /* total no. of elements in the field */ /* first, check if we are overwriting an existing row, and */ /* if so, if the existing space is big enough for the new vector */ if ( firstrow <= (fptr->Fptr)->numrows ) { ffgdesll(fptr, colnum, firstrow, &lrepeat, &heapoffset, &tstatus); if (!tstatus) { if (colptr->tdatatype <= -TCOMPLEX) lrepeat = lrepeat * 2; /* no. of float or double values */ else if (colptr->tdatatype == -TBIT) lrepeat = (lrepeat + 7) / 8; /* convert from bits to bytes */ if (lrepeat >= *repeat) /* enough existing space? */ { *startpos = datastart + heapoffset + (fptr->Fptr)->heapstart; /* write the descriptor into the fixed length part of table */ if (colptr->tdatatype <= -TCOMPLEX) { /* divide repeat count by 2 to get no. of complex values */ ffpdes(fptr, colnum, firstrow, *repeat / 2, heapoffset, status); } else { ffpdes(fptr, colnum, firstrow, *repeat, heapoffset, status); } return(*status); } } } /* Add more rows to the table, if writing beyond the end. */ /* It is necessary to shift the heap down in this case */ if ( firstrow > (fptr->Fptr)->numrows) { nrows = firstrow - ((fptr->Fptr)->numrows); if (ffirow(fptr, (fptr->Fptr)->numrows, nrows, status) > 0) { snprintf(message,FLEN_ERRMSG, "Failed to add space for %.0f new rows in table.", (double) nrows); ffpmsg(message); return(*status); } } /* calculate starting position (for writing new data) in the heap */ *startpos = datastart + (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize; /* write the descriptor into the fixed length part of table */ if (colptr->tdatatype <= -TCOMPLEX) { /* divide repeat count by 2 to get no. of complex values */ ffpdes(fptr, colnum, firstrow, *repeat / 2, (fptr->Fptr)->heapsize, status); } else { ffpdes(fptr, colnum, firstrow, *repeat, (fptr->Fptr)->heapsize, status); } /* If this is not the last HDU in the file, then check if */ /* extending the heap would overwrite the following header. */ /* If so, then have to insert more blocks. */ if ( !((fptr->Fptr)->lasthdu) ) { endpos = datastart + (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize + ( *repeat * (*incre)); if (endpos > (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1]) { /* calc the number of blocks that need to be added */ nblock = (long) (((endpos - 1 - (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1] ) / 2880) + 1); if (ffiblk(fptr, nblock, 1, status) > 0) /* insert blocks */ { snprintf(message,FLEN_ERRMSG, "Failed to extend the size of the variable length heap by %ld blocks.", nblock); ffpmsg(message); return(*status); } } } /* increment the address to the next empty heap position */ (fptr->Fptr)->heapsize += ( *repeat * (*incre)); } else /* get the read start position in the heap */ { if ( firstrow > (fptr->Fptr)->numrows) { ffpmsg("Attempt to read past end of table"); snprintf(message,FLEN_ERRMSG, " Table has %.0f rows and tried to read row %.0f.", (double) ((fptr->Fptr)->numrows), (double) firstrow); ffpmsg(message); return(*status = BAD_ROW_NUM); } ffgdesll(fptr, colnum, firstrow, &lrepeat, &heapoffset, status); *repeat = lrepeat; if (colptr->tdatatype <= -TCOMPLEX) *repeat = *repeat * 2; /* no. of float or double values */ else if (colptr->tdatatype == -TBIT) *repeat = (*repeat + 7) / 8; /* convert from bits to bytes */ if (*elemnum >= *repeat) { snprintf(message,FLEN_ERRMSG, "Starting element to read in variable length column is too large: %ld", (long) firstelem); ffpmsg(message); snprintf(message,FLEN_ERRMSG, " This row only contains %ld elements", (long) *repeat); ffpmsg(message); return(*status = BAD_ELEM_NUM); } *startpos = datastart + heapoffset + (fptr->Fptr)->heapstart; } } return(*status); } /*---------------------------------------------------------------------------*/ int fftheap(fitsfile *fptr, /* I - FITS file pointer */ LONGLONG *heapsz, /* O - current size of the heap */ LONGLONG *unused, /* O - no. of unused bytes in the heap */ LONGLONG *overlap, /* O - no. of bytes shared by > 1 descriptors */ int *valid, /* O - are all the heap addresses valid? */ int *status) /* IO - error status */ /* Tests the contents of the binary table variable length array heap. Returns the number of bytes that are currently not pointed to by any of the descriptors, and also the number of bytes that are pointed to by more than one descriptor. It returns valid = FALSE if any of the descriptors point to addresses that are out of the bounds of the heap. */ { int jj, typecode, pixsize; long ii, kk, theapsz, nbytes; LONGLONG repeat, offset, tunused = 0, toverlap = 0; char *buffer, message[FLEN_ERRMSG]; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if ( fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); /* rescan header to make sure everything is up to date */ else if ( ffrdef(fptr, status) > 0) return(*status); if (valid) *valid = TRUE; if (heapsz) *heapsz = (fptr->Fptr)->heapsize; if (unused) *unused = 0; if (overlap) *overlap = 0; /* return if this is not a binary table HDU or if the heap is empty */ if ( (fptr->Fptr)->hdutype != BINARY_TBL || (fptr->Fptr)->heapsize == 0 ) return(*status); if ((fptr->Fptr)->heapsize > LONG_MAX) { ffpmsg("Heap is too big to test ( > 2**31 bytes). (fftheap)"); return(*status = MEMORY_ALLOCATION); } theapsz = (long) (fptr->Fptr)->heapsize; buffer = calloc(1, theapsz); /* allocate temp space */ if (!buffer ) { snprintf(message,FLEN_ERRMSG,"Failed to allocate buffer to test the heap"); ffpmsg(message); return(*status = MEMORY_ALLOCATION); } /* loop over all cols */ for (jj = 1; jj <= (fptr->Fptr)->tfield && *status <= 0; jj++) { ffgtcl(fptr, jj, &typecode, NULL, NULL, status); if (typecode > 0) continue; /* ignore fixed length columns */ pixsize = -typecode / 10; for (ii = 1; ii <= (fptr->Fptr)->numrows; ii++) { ffgdesll(fptr, jj, ii, &repeat, &offset, status); if (typecode == -TBIT) nbytes = (long) (repeat + 7) / 8; else nbytes = (long) repeat * pixsize; if (offset < 0 || offset + nbytes > theapsz) { if (valid) *valid = FALSE; /* address out of bounds */ snprintf(message,FLEN_ERRMSG, "Descriptor in row %ld, column %d has invalid heap address", ii, jj); ffpmsg(message); } else { for (kk = 0; kk < nbytes; kk++) buffer[kk + offset]++; /* increment every used byte */ } } } for (kk = 0; kk < theapsz; kk++) { if (buffer[kk] == 0) tunused++; else if (buffer[kk] > 1) toverlap++; } if (heapsz) *heapsz = theapsz; if (unused) *unused = tunused; if (overlap) *overlap = toverlap; free(buffer); return(*status); } /*--------------------------------------------------------------------------*/ int ffcmph(fitsfile *fptr, /* I -FITS file pointer */ int *status) /* IO - error status */ /* compress the binary table heap by reordering the contents heap and recovering any unused space */ { fitsfile *tptr; int jj, typecode, pixsize, valid; long ii, buffsize = 10000, nblock, nbytes; LONGLONG unused, overlap; LONGLONG repeat, offset; char *buffer, *tbuff, comm[FLEN_COMMENT]; char message[FLEN_ERRMSG]; LONGLONG pcount; LONGLONG readheapstart, writeheapstart, endpos, t1heapsize, t2heapsize; if (*status > 0) return(*status); /* get information about the current heap */ fftheap(fptr, NULL, &unused, &overlap, &valid, status); if (!valid) return(*status = BAD_HEAP_PTR); /* bad heap pointers */ /* return if this is not a binary table HDU or if the heap is OK as is */ if ( (fptr->Fptr)->hdutype != BINARY_TBL || (fptr->Fptr)->heapsize == 0 || (unused == 0 && overlap == 0) || *status > 0 ) return(*status); /* copy the current HDU to a temporary file in memory */ if (ffinit( &tptr, "mem://tempheapfile", status) ) { snprintf(message,FLEN_ERRMSG,"Failed to create temporary file for the heap"); ffpmsg(message); return(*status); } if ( ffcopy(fptr, tptr, 0, status) ) { snprintf(message,FLEN_ERRMSG,"Failed to create copy of the heap"); ffpmsg(message); ffclos(tptr, status); return(*status); } buffer = (char *) malloc(buffsize); /* allocate initial buffer */ if (!buffer) { snprintf(message,FLEN_ERRMSG,"Failed to allocate buffer to copy the heap"); ffpmsg(message); ffclos(tptr, status); return(*status = MEMORY_ALLOCATION); } readheapstart = (tptr->Fptr)->datastart + (tptr->Fptr)->heapstart; writeheapstart = (fptr->Fptr)->datastart + (fptr->Fptr)->heapstart; t1heapsize = (fptr->Fptr)->heapsize; /* save original heap size */ (fptr->Fptr)->heapsize = 0; /* reset heap to zero */ /* loop over all cols */ for (jj = 1; jj <= (fptr->Fptr)->tfield && *status <= 0; jj++) { ffgtcl(tptr, jj, &typecode, NULL, NULL, status); if (typecode > 0) continue; /* ignore fixed length columns */ pixsize = -typecode / 10; /* copy heap data, row by row */ for (ii = 1; ii <= (fptr->Fptr)->numrows; ii++) { ffgdesll(tptr, jj, ii, &repeat, &offset, status); if (typecode == -TBIT) nbytes = (long) (repeat + 7) / 8; else nbytes = (long) repeat * pixsize; /* increase size of buffer if necessary to read whole array */ if (nbytes > buffsize) { tbuff = realloc(buffer, nbytes); if (tbuff) { buffer = tbuff; buffsize = nbytes; } else *status = MEMORY_ALLOCATION; } /* If this is not the last HDU in the file, then check if */ /* extending the heap would overwrite the following header. */ /* If so, then have to insert more blocks. */ if ( !((fptr->Fptr)->lasthdu) ) { endpos = writeheapstart + (fptr->Fptr)->heapsize + nbytes; if (endpos > (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1]) { /* calc the number of blocks that need to be added */ nblock = (long) (((endpos - 1 - (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1] ) / 2880) + 1); if (ffiblk(fptr, nblock, 1, status) > 0) /* insert blocks */ { snprintf(message,FLEN_ERRMSG, "Failed to extend the size of the variable length heap by %ld blocks.", nblock); ffpmsg(message); } } } /* read arrray of bytes from temporary copy */ ffmbyt(tptr, readheapstart + offset, REPORT_EOF, status); ffgbyt(tptr, nbytes, buffer, status); /* write arrray of bytes back to original file */ ffmbyt(fptr, writeheapstart + (fptr->Fptr)->heapsize, IGNORE_EOF, status); ffpbyt(fptr, nbytes, buffer, status); /* write descriptor */ ffpdes(fptr, jj, ii, repeat, (fptr->Fptr)->heapsize, status); (fptr->Fptr)->heapsize += nbytes; /* update heapsize */ if (*status > 0) { free(buffer); ffclos(tptr, status); return(*status); } } } free(buffer); ffclos(tptr, status); /* delete any empty blocks at the end of the HDU */ nblock = (long) (( (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1] - (writeheapstart + (fptr->Fptr)->heapsize) ) / 2880); if (nblock > 0) { t2heapsize = (fptr->Fptr)->heapsize; /* save new heap size */ (fptr->Fptr)->heapsize = t1heapsize; /* restore original heap size */ ffdblk(fptr, nblock, status); (fptr->Fptr)->heapsize = t2heapsize; /* reset correct heap size */ } /* update the PCOUNT value (size of heap) */ ffmaky(fptr, 2, status); /* reset to beginning of header */ ffgkyjj(fptr, "PCOUNT", &pcount, comm, status); if ((fptr->Fptr)->heapsize != pcount) { ffmkyj(fptr, "PCOUNT", (fptr->Fptr)->heapsize, comm, status); } ffrdef(fptr, status); /* rescan new HDU structure */ return(*status); } /*--------------------------------------------------------------------------*/ int ffgdes(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number (1 = 1st column of table) */ LONGLONG rownum, /* I - row number (1 = 1st row of table) */ long *length, /* O - number of elements in the row */ long *heapaddr, /* O - heap pointer to the data */ int *status) /* IO - error status */ /* get (read) the variable length vector descriptor from the table. */ { LONGLONG lengthjj, heapaddrjj; if (ffgdesll(fptr, colnum, rownum, &lengthjj, &heapaddrjj, status) > 0) return(*status); /* convert the temporary 8-byte values to 4-byte values */ /* check for overflow */ if (length) { if (lengthjj > LONG_MAX) *status = NUM_OVERFLOW; else *length = (long) lengthjj; } if (heapaddr) { if (heapaddrjj > LONG_MAX) *status = NUM_OVERFLOW; else *heapaddr = (long) heapaddrjj; } return(*status); } /*--------------------------------------------------------------------------*/ int ffgdesll(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number (1 = 1st column of table) */ LONGLONG rownum, /* I - row number (1 = 1st row of table) */ LONGLONG *length, /* O - number of elements in the row */ LONGLONG *heapaddr, /* O - heap pointer to the data */ int *status) /* IO - error status */ /* get (read) the variable length vector descriptor from the binary table. This is similar to ffgdes, except it supports the full 8-byte range of the length and offset values in 'Q' columns, as well as 'P' columns. */ { LONGLONG bytepos; unsigned int descript4[2] = {0,0}; LONGLONG descript8[2] = {0,0}; tcolumn *colptr; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); colptr = (fptr->Fptr)->tableptr; /* point to first column structure */ colptr += (colnum - 1); /* offset to the correct column */ if (colptr->tdatatype >= 0) { *status = NOT_VARI_LEN; return(*status); } bytepos = (fptr->Fptr)->datastart + ((fptr->Fptr)->rowlength * (rownum - 1)) + colptr->tbcol; if (colptr->tform[0] == 'P' || colptr->tform[1] == 'P') { /* read 4-byte descriptor */ if (ffgi4b(fptr, bytepos, 2, 4, (INT32BIT *) descript4, status) <= 0) { if (length) *length = (LONGLONG) descript4[0]; /* 1st word is the length */ if (heapaddr) *heapaddr = (LONGLONG) descript4[1]; /* 2nd word is the address */ } } else /* this is for 'Q' columns */ { /* read 8 byte descriptor */ if (ffgi8b(fptr, bytepos, 2, 8, (long *) descript8, status) <= 0) { if (length) *length = descript8[0]; /* 1st word is the length */ if (heapaddr) *heapaddr = descript8[1]; /* 2nd word is the address */ } } return(*status); } /*--------------------------------------------------------------------------*/ int ffgdess(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number (1 = 1st column of table) */ LONGLONG firstrow, /* I - first row (1 = 1st row of table) */ LONGLONG nrows, /* I - number or rows to read */ long *length, /* O - number of elements in the row */ long *heapaddr, /* O - heap pointer to the data */ int *status) /* IO - error status */ /* get (read) a range of variable length vector descriptors from the table. */ { LONGLONG rowsize, bytepos; long ii; INT32BIT descript4[2] = {0,0}; LONGLONG descript8[2] = {0,0}; tcolumn *colptr; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); colptr = (fptr->Fptr)->tableptr; /* point to first column structure */ colptr += (colnum - 1); /* offset to the correct column */ if (colptr->tdatatype >= 0) { *status = NOT_VARI_LEN; return(*status); } rowsize = (fptr->Fptr)->rowlength; bytepos = (fptr->Fptr)->datastart + (rowsize * (firstrow - 1)) + colptr->tbcol; if (colptr->tform[0] == 'P' || colptr->tform[1] == 'P') { /* read 4-byte descriptors */ for (ii = 0; ii < nrows; ii++) { /* read descriptors */ if (ffgi4b(fptr, bytepos, 2, 4, descript4, status) <= 0) { if (length) { *length = (long) descript4[0]; /* 1st word is the length */ length++; } if (heapaddr) { *heapaddr = (long) descript4[1]; /* 2nd word is the address */ heapaddr++; } bytepos += rowsize; } else return(*status); } } else /* this is for 'Q' columns */ { /* read 8-byte descriptors */ for (ii = 0; ii < nrows; ii++) { /* read descriptors */ if (ffgi8b(fptr, bytepos, 2, 8, (long *) descript8, status) <= 0) { if (length) { if (descript8[0] > LONG_MAX)*status = NUM_OVERFLOW; *length = (long) descript8[0]; /* 1st word is the length */ length++; } if (heapaddr) { if (descript8[1] > LONG_MAX)*status = NUM_OVERFLOW; *heapaddr = (long) descript8[1]; /* 2nd word is the address */ heapaddr++; } bytepos += rowsize; } else return(*status); } } return(*status); } /*--------------------------------------------------------------------------*/ int ffgdessll(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number (1 = 1st column of table) */ LONGLONG firstrow, /* I - first row (1 = 1st row of table) */ LONGLONG nrows, /* I - number or rows to read */ LONGLONG *length, /* O - number of elements in the row */ LONGLONG *heapaddr, /* O - heap pointer to the data */ int *status) /* IO - error status */ /* get (read) a range of variable length vector descriptors from the table. */ { LONGLONG rowsize, bytepos; long ii; unsigned int descript4[2] = {0,0}; LONGLONG descript8[2] = {0,0}; tcolumn *colptr; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); colptr = (fptr->Fptr)->tableptr; /* point to first column structure */ colptr += (colnum - 1); /* offset to the correct column */ if (colptr->tdatatype >= 0) { *status = NOT_VARI_LEN; return(*status); } rowsize = (fptr->Fptr)->rowlength; bytepos = (fptr->Fptr)->datastart + (rowsize * (firstrow - 1)) + colptr->tbcol; if (colptr->tform[0] == 'P' || colptr->tform[1] == 'P') { /* read 4-byte descriptors */ for (ii = 0; ii < nrows; ii++) { /* read descriptors */ if (ffgi4b(fptr, bytepos, 2, 4, (INT32BIT *) descript4, status) <= 0) { if (length) { *length = (LONGLONG) descript4[0]; /* 1st word is the length */ length++; } if (heapaddr) { *heapaddr = (LONGLONG) descript4[1]; /* 2nd word is the address */ heapaddr++; } bytepos += rowsize; } else return(*status); } } else /* this is for 'Q' columns */ { /* read 8-byte descriptors */ for (ii = 0; ii < nrows; ii++) { /* read descriptors */ /* cast to type (long *) even though it is actually (LONGLONG *) */ if (ffgi8b(fptr, bytepos, 2, 8, (long *) descript8, status) <= 0) { if (length) { *length = descript8[0]; /* 1st word is the length */ length++; } if (heapaddr) { *heapaddr = descript8[1]; /* 2nd word is the address */ heapaddr++; } bytepos += rowsize; } else return(*status); } } return(*status); } /*--------------------------------------------------------------------------*/ int ffpdes(fitsfile *fptr, /* I - FITS file pointer */ int colnum, /* I - column number (1 = 1st column of table) */ LONGLONG rownum, /* I - row number (1 = 1st row of table) */ LONGLONG length, /* I - number of elements in the row */ LONGLONG heapaddr, /* I - heap pointer to the data */ int *status) /* IO - error status */ /* put (write) the variable length vector descriptor to the table. */ { LONGLONG bytepos; unsigned int descript4[2]; LONGLONG descript8[2]; tcolumn *colptr; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); colptr = (fptr->Fptr)->tableptr; /* point to first column structure */ colptr += (colnum - 1); /* offset to the correct column */ if (colptr->tdatatype >= 0) *status = NOT_VARI_LEN; bytepos = (fptr->Fptr)->datastart + ((fptr->Fptr)->rowlength * (rownum - 1)) + colptr->tbcol; ffmbyt(fptr, bytepos, IGNORE_EOF, status); /* move to element */ if (colptr->tform[0] == 'P' || colptr->tform[1] == 'P') { if (length > UINT_MAX || length < 0 || heapaddr > UINT_MAX || heapaddr < 0) { ffpmsg("P variable length column descriptor is out of range"); *status = NUM_OVERFLOW; return(*status); } descript4[0] = (unsigned int) length; /* 1st word is the length */ descript4[1] = (unsigned int) heapaddr; /* 2nd word is the address */ ffpi4b(fptr, 2, 4, (INT32BIT *) descript4, status); /* write the descriptor */ } else /* this is a 'Q' descriptor column */ { descript8[0] = length; /* 1st word is the length */ descript8[1] = heapaddr; /* 2nd word is the address */ ffpi8b(fptr, 2, 8, (long *) descript8, status); /* write the descriptor */ } return(*status); } /*--------------------------------------------------------------------------*/ int ffchdu(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ { /* close the current HDU. If we have write access to the file, then: - write the END keyword and pad header with blanks if necessary - check the data fill values, and rewrite them if not correct */ char message[FLEN_ERRMSG]; int ii, stdriver, ntilebins; /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); /* no need to do any further updating of the HDU */ } else if ((fptr->Fptr)->writemode == 1) { urltype2driver("stream://", &stdriver); /* don't rescan header in special case of writing to stdout */ if (((fptr->Fptr)->driver != stdriver)) ffrdef(fptr, status); if ((fptr->Fptr)->heapsize > 0) { ffuptf(fptr, status); /* update the variable length TFORM values */ } ffpdfl(fptr, status); /* insure correct data fill values */ } if ((fptr->Fptr)->open_count == 1) { /* free memory for the CHDU structure only if no other files are using it */ if ((fptr->Fptr)->tableptr) { free((fptr->Fptr)->tableptr); (fptr->Fptr)->tableptr = NULL; /* free the tile-compressed image cache, if it exists */ if ((fptr->Fptr)->tilerow) { ntilebins = (((fptr->Fptr)->znaxis[0] - 1) / ((fptr->Fptr)->tilesize[0])) + 1; for (ii = 0; ii < ntilebins; ii++) { if ((fptr->Fptr)->tiledata[ii]) { free((fptr->Fptr)->tiledata[ii]); } if ((fptr->Fptr)->tilenullarray[ii]) { free((fptr->Fptr)->tilenullarray[ii]); } } free((fptr->Fptr)->tileanynull); free((fptr->Fptr)->tiletype); free((fptr->Fptr)->tiledatasize); free((fptr->Fptr)->tilenullarray); free((fptr->Fptr)->tiledata); free((fptr->Fptr)->tilerow); (fptr->Fptr)->tileanynull = 0; (fptr->Fptr)->tiletype = 0; (fptr->Fptr)->tiledatasize = 0; (fptr->Fptr)->tilenullarray = 0; (fptr->Fptr)->tiledata = 0; (fptr->Fptr)->tilerow = 0; } } } if (*status > 0 && *status != NO_CLOSE_ERROR) { snprintf(message,FLEN_ERRMSG, "Error while closing HDU number %d (ffchdu).", (fptr->Fptr)->curhdu); ffpmsg(message); } return(*status); } /*--------------------------------------------------------------------------*/ int ffuptf(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ /* Update the value of the TFORM keywords for the variable length array columns to make sure they all have the form 1Px(len) or Px(len) where 'len' is the maximum length of the vector in the table (e.g., '1PE(400)') */ { int ii; long tflds; LONGLONG length, addr, maxlen, naxis2, jj; char comment[FLEN_COMMENT], keyname[FLEN_KEYWORD]; char tform[FLEN_VALUE], newform[FLEN_VALUE], lenval[40]; char card[FLEN_CARD]; char message[FLEN_ERRMSG]; char *tmp; ffmaky(fptr, 2, status); /* reset to beginning of header */ ffgkyjj(fptr, "NAXIS2", &naxis2, comment, status); ffgkyj(fptr, "TFIELDS", &tflds, comment, status); for (ii = 1; ii <= tflds; ii++) /* loop over all the columns */ { ffkeyn("TFORM", ii, keyname, status); /* construct name */ if (ffgkys(fptr, keyname, tform, comment, status) > 0) { snprintf(message,FLEN_ERRMSG, "Error while updating variable length vector TFORMn values (ffuptf)."); ffpmsg(message); return(*status); } /* is this a variable array length column ? */ if (tform[0] == 'P' || tform[1] == 'P' || tform[0] == 'Q' || tform[1] == 'Q') { /* get the max length */ maxlen = 0; for (jj=1; jj <= naxis2; jj++) { ffgdesll(fptr, ii, jj, &length, &addr, status); if (length > maxlen) maxlen = length; } /* construct the new keyword value */ strcpy(newform, "'"); tmp = strchr(tform, '('); /* truncate old length, if present */ if (tmp) *tmp = 0; strcat(newform, tform); /* print as double, because the string-to-64-bit */ /* conversion is platform dependent (%lld, %ld, %I64d) */ snprintf(lenval,40, "(%.0f)", (double) maxlen); strcat(newform,lenval); while(strlen(newform) < 9) strcat(newform," "); /* append spaces 'till length = 8 */ strcat(newform,"'" ); /* append closing parenthesis */ /* would be simpler to just call ffmkyj here, but this */ /* would force linking in all the modkey & putkey routines */ ffmkky(keyname, newform, comment, card, status); /* make new card */ ffmkey(fptr, card, status); /* replace last read keyword */ } } return(*status); } /*--------------------------------------------------------------------------*/ int ffrdef(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ /* ReDEFine the structure of a data unit. This routine re-reads the CHDU header keywords to determine the structure and length of the current data unit. This redefines the start of the next HDU. */ { int dummy, tstatus = 0; LONGLONG naxis2; LONGLONG pcount; char card[FLEN_CARD], comm[FLEN_COMMENT], valstring[FLEN_VALUE]; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } else if ((fptr->Fptr)->writemode == 1) /* write access to the file? */ { /* don't need to check NAXIS2 and PCOUNT if data hasn't been written */ if ((fptr->Fptr)->datastart != DATA_UNDEFINED) { /* update NAXIS2 keyword if more rows were written to the table */ /* and if the user has not explicitly reset the NAXIS2 value */ if ((fptr->Fptr)->hdutype != IMAGE_HDU) { ffmaky(fptr, 2, status); if (ffgkyjj(fptr, "NAXIS2", &naxis2, comm, &tstatus) > 0) { /* Couldn't read NAXIS2 (odd!); in certain circumstances */ /* this may be normal, so ignore the error. */ naxis2 = (fptr->Fptr)->numrows; } if ((fptr->Fptr)->numrows > naxis2 && (fptr->Fptr)->origrows == naxis2) /* if origrows is not equal to naxis2, then the user must */ /* have manually modified the NAXIS2 keyword value, and */ /* we will assume that the current value is correct. */ { /* would be simpler to just call ffmkyj here, but this */ /* would force linking in all the modkey & putkey routines */ /* print as double because the 64-bit int conversion */ /* is platform dependent (%lld, %ld, %I64 ) */ snprintf(valstring,FLEN_VALUE, "%.0f", (double) ((fptr->Fptr)->numrows)); ffmkky("NAXIS2", valstring, comm, card, status); ffmkey(fptr, card, status); } } /* if data has been written to variable length columns in a */ /* binary table, then we may need to update the PCOUNT value */ if ((fptr->Fptr)->heapsize > 0) { ffmaky(fptr, 2, status); ffgkyjj(fptr, "PCOUNT", &pcount, comm, status); if ((fptr->Fptr)->heapsize != pcount) { ffmkyj(fptr, "PCOUNT", (fptr->Fptr)->heapsize, comm, status); } } } if (ffwend(fptr, status) <= 0) /* rewrite END keyword and fill */ { ffrhdu(fptr, &dummy, status); /* re-scan the header keywords */ } } return(*status); } /*--------------------------------------------------------------------------*/ int ffhdef(fitsfile *fptr, /* I - FITS file pointer */ int morekeys, /* I - reserve space for this many keywords */ int *status) /* IO - error status */ /* based on the number of keywords which have already been written, plus the number of keywords to reserve space for, we then can define where the data unit should start (it must start at the beginning of a 2880-byte logical block). This routine will only have any effect if the starting location of the data unit following the header is not already defined. In any case, it is always possible to add more keywords to the header even if the data has already been written. It is just more efficient to reserve the space in advance. */ { LONGLONG delta; if (*status > 0 || morekeys < 1) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) { ffrdef(fptr, status); /* ffrdef defines the offset to datastart and the start of */ /* the next HDU based on the number of existing keywords. */ /* We need to increment both of these values based on */ /* the number of new keywords to be added. */ delta = (((fptr->Fptr)->headend + (morekeys * 80)) / 2880 + 1) * 2880 - (fptr->Fptr)->datastart; (fptr->Fptr)->datastart += delta; (fptr->Fptr)->headstart[ (fptr->Fptr)->curhdu + 1] += delta; } return(*status); } /*--------------------------------------------------------------------------*/ int ffwend(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ /* write the END card and following fill (space chars) in the current header */ { int ii, tstatus; LONGLONG endpos; long nspace; char blankkey[FLEN_CARD], endkey[FLEN_CARD], keyrec[FLEN_CARD] = ""; if (*status > 0) return(*status); endpos = (fptr->Fptr)->headend; /* we assume that the HDUposition == curhdu in all cases */ /* calc the data starting position if not currently defined */ if ((fptr->Fptr)->datastart == DATA_UNDEFINED) (fptr->Fptr)->datastart = ( endpos / 2880 + 1 ) * 2880; /* calculate the number of blank keyword slots in the header */ nspace = (long) (( (fptr->Fptr)->datastart - endpos ) / 80); /* construct a blank and END keyword (80 spaces ) */ strcpy(blankkey, " "); strcat(blankkey, " "); strcpy(endkey, "END "); strcat(endkey, " "); /* check if header is already correctly terminated with END and fill */ tstatus=0; ffmbyt(fptr, endpos, REPORT_EOF, &tstatus); /* move to header end */ for (ii=0; ii < nspace; ii++) { ffgbyt(fptr, 80, keyrec, &tstatus); /* get next keyword */ if (tstatus) break; if (strncmp(keyrec, blankkey, 80) && strncmp(keyrec, endkey, 80)) break; } if (ii == nspace && !tstatus) { /* check if the END keyword exists at the correct position */ endpos=maxvalue( endpos, ( (fptr->Fptr)->datastart - 2880 ) ); ffmbyt(fptr, endpos, REPORT_EOF, &tstatus); /* move to END position */ ffgbyt(fptr, 80, keyrec, &tstatus); /* read the END keyword */ if ( !strncmp(keyrec, endkey, 80) && !tstatus) { /* store this position, for later reference */ (fptr->Fptr)->ENDpos = endpos; return(*status); /* END card was already correct */ } } /* header was not correctly terminated, so write the END and blank fill */ endpos = (fptr->Fptr)->headend; ffmbyt(fptr, endpos, IGNORE_EOF, status); /* move to header end */ for (ii=0; ii < nspace; ii++) ffpbyt(fptr, 80, blankkey, status); /* write the blank keywords */ /* The END keyword must either be placed immediately after the last keyword that was written (as indicated by the headend value), or must be in the first 80 bytes of the 2880-byte FITS record immediately preceeding the data unit, whichever is further in the file. The latter will occur if space has been reserved for more header keywords which have not yet been written. */ endpos=maxvalue( endpos, ( (fptr->Fptr)->datastart - 2880 ) ); ffmbyt(fptr, endpos, REPORT_EOF, status); /* move to END position */ ffpbyt(fptr, 80, endkey, status); /* write the END keyword to header */ /* store this position, for later reference */ (fptr->Fptr)->ENDpos = endpos; if (*status > 0) ffpmsg("Error while writing END card (ffwend)."); return(*status); } /*--------------------------------------------------------------------------*/ int ffpdfl(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ /* Write the Data Unit Fill values if they are not already correct. The fill values are used to fill out the last 2880 byte block of the HDU. Fill the data unit with zeros or blanks depending on the type of HDU from the end of the data to the end of the current FITS 2880 byte block */ { char chfill, fill[2880]; LONGLONG fillstart; int nfill, tstatus, ii; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) return(*status); /* fill has already been correctly written */ if ((fptr->Fptr)->heapstart == 0) return(*status); /* null data unit, so there is no fill */ fillstart = (fptr->Fptr)->datastart + (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize; nfill = (long) ((fillstart + 2879) / 2880 * 2880 - fillstart); if ((fptr->Fptr)->hdutype == ASCII_TBL) chfill = 32; /* ASCII tables are filled with spaces */ else chfill = 0; /* all other extensions are filled with zeros */ tstatus = 0; if (!nfill) /* no fill bytes; just check that entire table exists */ { fillstart--; nfill = 1; ffmbyt(fptr, fillstart, REPORT_EOF, &tstatus); /* move to last byte */ ffgbyt(fptr, nfill, fill, &tstatus); /* get the last byte */ if (tstatus == 0) return(*status); /* no EOF error, so everything is OK */ } else { ffmbyt(fptr, fillstart, REPORT_EOF, &tstatus); /* move to fill area */ ffgbyt(fptr, nfill, fill, &tstatus); /* get the fill bytes */ if (tstatus == 0) { for (ii = 0; ii < nfill; ii++) { if (fill[ii] != chfill) break; } if (ii == nfill) return(*status); /* all the fill values were correct */ } } /* fill values are incorrect or have not been written, so write them */ memset(fill, chfill, nfill); /* fill the buffer with the fill value */ ffmbyt(fptr, fillstart, IGNORE_EOF, status); /* move to fill area */ ffpbyt(fptr, nfill, fill, status); /* write the fill bytes */ if (*status > 0) ffpmsg("Error writing Data Unit fill bytes (ffpdfl)."); return(*status); } /********************************************************************** ffchfl : Check Header Fill values Check that the header unit is correctly filled with blanks from the END card to the end of the current FITS 2880-byte block Function parameters: fptr Fits file pointer status output error status Translated ftchfl into C by Peter Wilson, Oct. 1997 **********************************************************************/ int ffchfl( fitsfile *fptr, int *status) { int nblank,i,gotend; LONGLONG endpos; char rec[FLEN_CARD]; char *blanks=" "; /* 80 spaces */ if( *status > 0 ) return (*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); /* calculate the number of blank keyword slots in the header */ endpos=(fptr->Fptr)->headend; nblank=(long) (((fptr->Fptr)->datastart-endpos)/80); /* move the i/o pointer to the end of the header keywords */ ffmbyt(fptr,endpos,TRUE,status); /* find the END card (there may be blank keywords perceeding it) */ gotend=FALSE; for(i=0;i 0 ) { rec[FLEN_CARD - 1] = '\0'; /* make sure string is null terminated */ ffpmsg(rec); return( *status ); } } return( *status ); } /********************************************************************** ffcdfl : Check Data Unit Fill values Check that the data unit is correctly filled with zeros or blanks from the end of the data to the end of the current FITS 2880 byte block Function parameters: fptr Fits file pointer status output error status Translated ftcdfl into C by Peter Wilson, Oct. 1997 **********************************************************************/ int ffcdfl( fitsfile *fptr, int *status) { int nfill,i; LONGLONG filpos; char chfill,chbuff[2880]; if( *status > 0 ) return( *status ); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); /* check if the data unit is null */ if( (fptr->Fptr)->heapstart==0 ) return( *status ); /* calculate starting position of the fill bytes, if any */ filpos = (fptr->Fptr)->datastart + (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize; /* calculate the number of fill bytes */ nfill = (long) ((filpos + 2879) / 2880 * 2880 - filpos); if( nfill == 0 ) return( *status ); /* move to the beginning of the fill bytes */ ffmbyt(fptr, filpos, FALSE, status); if( ffgbyt(fptr, nfill, chbuff, status) > 0) { ffpmsg("Error reading data unit fill bytes (ffcdfl)."); return( *status ); } if( (fptr->Fptr)->hdutype==ASCII_TBL ) chfill = 32; /* ASCII tables are filled with spaces */ else chfill = 0; /* all other extensions are filled with zeros */ /* check for all zeros or blanks */ for(i=0;iFptr)->hdutype==ASCII_TBL ) ffpmsg("Warning: remaining bytes following ASCII table data are not filled with blanks."); else ffpmsg("Warning: remaining bytes following data are not filled with zeros."); return( *status ); } } return( *status ); } /*--------------------------------------------------------------------------*/ int ffcrhd(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ /* CReate Header Data unit: Create, initialize, and move the i/o pointer to a new extension appended to the end of the FITS file. */ { int tstatus = 0; LONGLONG bytepos, *ptr; if (*status > 0) return(*status); if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); /* If the current header is empty, we don't have to do anything */ if ((fptr->Fptr)->headend == (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] ) return(*status); while (ffmrhd(fptr, 1, 0, &tstatus) == 0); /* move to end of file */ if ((fptr->Fptr)->maxhdu == (fptr->Fptr)->MAXHDU) { /* allocate more space for the headstart array */ ptr = (LONGLONG*) realloc( (fptr->Fptr)->headstart, ((fptr->Fptr)->MAXHDU + 1001) * sizeof(LONGLONG) ); if (ptr == NULL) return (*status = MEMORY_ALLOCATION); else { (fptr->Fptr)->MAXHDU = (fptr->Fptr)->MAXHDU + 1000; (fptr->Fptr)->headstart = ptr; } } if (ffchdu(fptr, status) <= 0) /* close the current HDU */ { bytepos = (fptr->Fptr)->headstart[(fptr->Fptr)->maxhdu + 1]; /* last */ ffmbyt(fptr, bytepos, IGNORE_EOF, status); /* move file ptr to it */ (fptr->Fptr)->maxhdu++; /* increment the known number of HDUs */ (fptr->Fptr)->curhdu = (fptr->Fptr)->maxhdu; /* set current HDU loc */ fptr->HDUposition = (fptr->Fptr)->maxhdu; /* set current HDU loc */ (fptr->Fptr)->nextkey = bytepos; /* next keyword = start of header */ (fptr->Fptr)->headend = bytepos; /* end of header */ (fptr->Fptr)->datastart = DATA_UNDEFINED; /* start data unit undefined */ /* any other needed resets */ /* reset the dithering offset that may have been calculated for the */ /* previous HDU back to the requested default value */ (fptr->Fptr)->dither_seed = (fptr->Fptr)->request_dither_seed; } return(*status); } /*--------------------------------------------------------------------------*/ int ffdblk(fitsfile *fptr, /* I - FITS file pointer */ long nblocks, /* I - number of 2880-byte blocks to delete */ int *status) /* IO - error status */ /* Delete the specified number of 2880-byte blocks from the end of the CHDU by shifting all following extensions up this number of blocks. */ { char buffer[2880]; int tstatus, ii; LONGLONG readpos, writepos; if (*status > 0 || nblocks <= 0) return(*status); tstatus = 0; /* pointers to the read and write positions */ readpos = (fptr->Fptr)->datastart + (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize; readpos = ((readpos + 2879) / 2880) * 2880; /* start of block */ /* the following formula is wrong because the current data unit may have been extended without updating the headstart value of the following HDU. readpos = (fptr->Fptr)->headstart[((fptr->Fptr)->curhdu) + 1]; */ writepos = readpos - ((LONGLONG)nblocks * 2880); while ( !ffmbyt(fptr, readpos, REPORT_EOF, &tstatus) && !ffgbyt(fptr, 2880L, buffer, &tstatus) ) { ffmbyt(fptr, writepos, REPORT_EOF, status); ffpbyt(fptr, 2880L, buffer, status); if (*status > 0) { ffpmsg("Error deleting FITS blocks (ffdblk)"); return(*status); } readpos += 2880; /* increment to next block to transfer */ writepos += 2880; } /* now fill the last nblock blocks with zeros */ memset(buffer, 0, 2880); ffmbyt(fptr, writepos, REPORT_EOF, status); for (ii = 0; ii < nblocks; ii++) ffpbyt(fptr, 2880L, buffer, status); /* move back before the deleted blocks, since they may be deleted */ /* and we do not want to delete the current active buffer */ ffmbyt(fptr, writepos - 1, REPORT_EOF, status); /* truncate the file to the new size, if supported on this device */ fftrun(fptr, writepos, status); /* recalculate the starting location of all subsequent HDUs */ for (ii = (fptr->Fptr)->curhdu; ii <= (fptr->Fptr)->maxhdu; ii++) (fptr->Fptr)->headstart[ii + 1] -= ((LONGLONG)nblocks * 2880); return(*status); } /*--------------------------------------------------------------------------*/ int ffghdt(fitsfile *fptr, /* I - FITS file pointer */ int *exttype, /* O - type of extension, 0, 1, or 2 */ /* for IMAGE_HDU, ASCII_TBL, or BINARY_TBL */ int *status) /* IO - error status */ /* Return the type of the CHDU. This returns the 'logical' type of the HDU, not necessarily the physical type, so in the case of a compressed image stored in a binary table, this will return the type as an Image, not a binary table. */ { if (*status > 0) return(*status); if (fptr->HDUposition == 0 && (fptr->Fptr)->headend == 0) { /* empty primary array is alway an IMAGE_HDU */ *exttype = IMAGE_HDU; } else { /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) { /* rescan header if data structure is undefined */ if ( ffrdef(fptr, status) > 0) return(*status); } *exttype = (fptr->Fptr)->hdutype; /* return the type of HDU */ /* check if this is a compressed image */ if ((fptr->Fptr)->compressimg) *exttype = IMAGE_HDU; } return(*status); } /*--------------------------------------------------------------------------*/ int fits_is_reentrant(void) /* Was CFITSIO compiled with the -D_REENTRANT flag? 1 = yes, 0 = no. Note that specifying the -D_REENTRANT flag is required, but may not be sufficient, to ensure that CFITSIO can be safely used in a multi-threaded environoment. */ { #ifdef _REENTRANT return(1); #else return(0); #endif } /*--------------------------------------------------------------------------*/ int fits_is_compressed_image(fitsfile *fptr, /* I - FITS file pointer */ int *status) /* IO - error status */ /* Returns TRUE if the CHDU is a compressed image, else returns zero. */ { if (*status > 0) return(0); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) { ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); } else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) { /* rescan header if data structure is undefined */ if ( ffrdef(fptr, status) > 0) return(*status); } /* check if this is a compressed image */ if ((fptr->Fptr)->compressimg) return(1); return(0); } /*--------------------------------------------------------------------------*/ int ffgipr(fitsfile *infptr, /* I - FITS file pointer */ int maxaxis, /* I - max number of axes to return */ int *bitpix, /* O - image data type */ int *naxis, /* O - image dimension (NAXIS value) */ long *naxes, /* O - size of image dimensions */ int *status) /* IO - error status */ /* get the datatype and size of the input image */ { if (*status > 0) return(*status); /* don't return the parameter if a null pointer was given */ if (bitpix) fits_get_img_type(infptr, bitpix, status); /* get BITPIX value */ if (naxis) fits_get_img_dim(infptr, naxis, status); /* get NAXIS value */ if (naxes) fits_get_img_size(infptr, maxaxis, naxes, status); /* get NAXISn values */ return(*status); } /*--------------------------------------------------------------------------*/ int ffgiprll(fitsfile *infptr, /* I - FITS file pointer */ int maxaxis, /* I - max number of axes to return */ int *bitpix, /* O - image data type */ int *naxis, /* O - image dimension (NAXIS value) */ LONGLONG *naxes, /* O - size of image dimensions */ int *status) /* IO - error status */ /* get the datatype and size of the input image */ { if (*status > 0) return(*status); /* don't return the parameter if a null pointer was given */ if (bitpix) fits_get_img_type(infptr, bitpix, status); /* get BITPIX value */ if (naxis) fits_get_img_dim(infptr, naxis, status); /* get NAXIS value */ if (naxes) fits_get_img_sizell(infptr, maxaxis, naxes, status); /* get NAXISn values */ return(*status); } /*--------------------------------------------------------------------------*/ int ffgidt( fitsfile *fptr, /* I - FITS file pointer */ int *imgtype, /* O - image data type */ int *status) /* IO - error status */ /* Get the datatype of the image (= BITPIX keyword for normal image, or ZBITPIX for a compressed image) */ { if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); /* reset to beginning of header */ ffmaky(fptr, 1, status); /* simply move to beginning of header */ if ((fptr->Fptr)->hdutype == IMAGE_HDU) { ffgky(fptr, TINT, "BITPIX", imgtype, NULL, status); } else if ((fptr->Fptr)->compressimg) { /* this is a binary table containing a compressed image */ ffgky(fptr, TINT, "ZBITPIX", imgtype, NULL, status); } else { *status = NOT_IMAGE; } return(*status); } /*--------------------------------------------------------------------------*/ int ffgiet( fitsfile *fptr, /* I - FITS file pointer */ int *imgtype, /* O - image data type */ int *status) /* IO - error status */ /* Get the effective datatype of the image (= BITPIX keyword for normal image, or ZBITPIX for a compressed image) */ { int tstatus; long lngscale, lngzero = 0; double bscale, bzero, min_val, max_val; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); /* reset to beginning of header */ ffmaky(fptr, 2, status); /* simply move to beginning of header */ if ((fptr->Fptr)->hdutype == IMAGE_HDU) { ffgky(fptr, TINT, "BITPIX", imgtype, NULL, status); } else if ((fptr->Fptr)->compressimg) { /* this is a binary table containing a compressed image */ ffgky(fptr, TINT, "ZBITPIX", imgtype, NULL, status); } else { *status = NOT_IMAGE; return(*status); } /* check if the BSCALE and BZERO keywords are defined, which might change the effective datatype of the image */ tstatus = 0; ffgky(fptr, TDOUBLE, "BSCALE", &bscale, NULL, &tstatus); if (tstatus) bscale = 1.0; tstatus = 0; ffgky(fptr, TDOUBLE, "BZERO", &bzero, NULL, &tstatus); if (tstatus) bzero = 0.0; if (bscale == 1.0 && bzero == 0.0) /* no scaling */ return(*status); switch (*imgtype) { case BYTE_IMG: /* 8-bit image */ min_val = 0.; max_val = 255.0; break; case SHORT_IMG: min_val = -32768.0; max_val = 32767.0; break; case LONG_IMG: min_val = -2147483648.0; max_val = 2147483647.0; break; default: /* don't have to deal with other data types */ return(*status); } if (bscale >= 0.) { min_val = bzero + bscale * min_val; max_val = bzero + bscale * max_val; } else { max_val = bzero + bscale * min_val; min_val = bzero + bscale * max_val; } if (bzero < 2147483648.) /* don't exceed range of 32-bit integer */ lngzero = (long) bzero; lngscale = (long) bscale; if ((bzero != 2147483648.) && /* special value that exceeds integer range */ (lngzero != bzero || lngscale != bscale)) { /* not integers? */ /* floating point scaled values; just decide on required precision */ if (*imgtype == BYTE_IMG || *imgtype == SHORT_IMG) *imgtype = FLOAT_IMG; else *imgtype = DOUBLE_IMG; /* In all the remaining cases, BSCALE and BZERO are integers, and not equal to 1 and 0, respectively. */ } else if ((min_val == -128.) && (max_val == 127.)) { *imgtype = SBYTE_IMG; } else if ((min_val >= -32768.0) && (max_val <= 32767.0)) { *imgtype = SHORT_IMG; } else if ((min_val >= 0.0) && (max_val <= 65535.0)) { *imgtype = USHORT_IMG; } else if ((min_val >= -2147483648.0) && (max_val <= 2147483647.0)) { *imgtype = LONG_IMG; } else if ((min_val >= 0.0) && (max_val < 4294967296.0)) { *imgtype = ULONG_IMG; } else { /* exceeds the range of a 32-bit integer */ *imgtype = DOUBLE_IMG; } return(*status); } /*--------------------------------------------------------------------------*/ int ffgidm( fitsfile *fptr, /* I - FITS file pointer */ int *naxis , /* O - image dimension (NAXIS value) */ int *status) /* IO - error status */ /* Get the dimension of the image (= NAXIS keyword for normal image, or ZNAXIS for a compressed image) These values are cached for faster access. */ { if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); if ((fptr->Fptr)->hdutype == IMAGE_HDU) { *naxis = (fptr->Fptr)->imgdim; } else if ((fptr->Fptr)->compressimg) { *naxis = (fptr->Fptr)->zndim; } else { *status = NOT_IMAGE; } return(*status); } /*--------------------------------------------------------------------------*/ int ffgisz( fitsfile *fptr, /* I - FITS file pointer */ int nlen, /* I - number of axes to return */ long *naxes, /* O - size of image dimensions */ int *status) /* IO - error status */ /* Get the size of the image dimensions (= NAXISn keywords for normal image, or ZNAXISn for a compressed image) These values are cached for faster access. */ { int ii, naxis; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); if ((fptr->Fptr)->hdutype == IMAGE_HDU) { naxis = minvalue((fptr->Fptr)->imgdim, nlen); for (ii = 0; ii < naxis; ii++) { naxes[ii] = (long) (fptr->Fptr)->imgnaxis[ii]; } } else if ((fptr->Fptr)->compressimg) { naxis = minvalue( (fptr->Fptr)->zndim, nlen); for (ii = 0; ii < naxis; ii++) { naxes[ii] = (long) (fptr->Fptr)->znaxis[ii]; } } else { *status = NOT_IMAGE; } return(*status); } /*--------------------------------------------------------------------------*/ int ffgiszll( fitsfile *fptr, /* I - FITS file pointer */ int nlen, /* I - number of axes to return */ LONGLONG *naxes, /* O - size of image dimensions */ int *status) /* IO - error status */ /* Get the size of the image dimensions (= NAXISn keywords for normal image, or ZNAXISn for a compressed image) */ { int ii, naxis; if (*status > 0) return(*status); /* reset position to the correct HDU if necessary */ if (fptr->HDUposition != (fptr->Fptr)->curhdu) ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status); else if ((fptr->Fptr)->datastart == DATA_UNDEFINED) if ( ffrdef(fptr, status) > 0) /* rescan header */ return(*status); if ((fptr->Fptr)->hdutype == IMAGE_HDU) { naxis = minvalue((fptr->Fptr)->imgdim, nlen); for (ii = 0; ii < naxis; ii++) { naxes[ii] = (fptr->Fptr)->imgnaxis[ii]; } } else if ((fptr->Fptr)->compressimg) { naxis = minvalue( (fptr->Fptr)->zndim, nlen); for (ii = 0; ii < naxis; ii++) { naxes[ii] = (fptr->Fptr)->znaxis[ii]; } } else { *status = NOT_IMAGE; } return(*status); }/*--------------------------------------------------------------------------*/ int ffmahd(fitsfile *fptr, /* I - FITS file pointer */ int hdunum, /* I - number of the HDU to move to */ int *exttype, /* O - type of extension, 0, 1, or 2 */ int *status) /* IO - error status */ /* Move to Absolute Header Data unit. Move to the specified HDU and read the header to initialize the table structure. Note that extnum is one based, so the primary array is extnum = 1. */ { int moveto, tstatus; char message[FLEN_ERRMSG]; LONGLONG *ptr; if (*status > 0) return(*status); else if (hdunum < 1 ) return(*status = BAD_HDU_NUM); else if (hdunum >= (fptr->Fptr)->MAXHDU ) { /* allocate more space for the headstart array */ ptr = (LONGLONG*) realloc( (fptr->Fptr)->headstart, (hdunum + 1001) * sizeof(LONGLONG) ); if (ptr == NULL) return (*status = MEMORY_ALLOCATION); else { (fptr->Fptr)->MAXHDU = hdunum + 1000; (fptr->Fptr)->headstart = ptr; } } /* set logical HDU position to the actual position, in case they differ */ fptr->HDUposition = (fptr->Fptr)->curhdu; while( ((fptr->Fptr)->curhdu) + 1 != hdunum) /* at the correct HDU? */ { /* move directly to the extension if we know that it exists, otherwise move to the highest known extension. */ moveto = minvalue(hdunum - 1, ((fptr->Fptr)->maxhdu) + 1); /* test if HDU exists */ if ((fptr->Fptr)->headstart[moveto] < (fptr->Fptr)->logfilesize ) { if (ffchdu(fptr, status) <= 0) /* close out the current HDU */ { if (ffgext(fptr, moveto, exttype, status) > 0) { /* failed to get the requested extension */ tstatus = 0; ffrhdu(fptr, exttype, &tstatus); /* restore the CHDU */ } } } else *status = END_OF_FILE; if (*status > 0) { if (*status != END_OF_FILE) { /* don't clutter up the message stack in the common case of */ /* simply hitting the end of file (often an expected error) */ snprintf(message,FLEN_ERRMSG, "Failed to move to HDU number %d (ffmahd).", hdunum); ffpmsg(message); } return(*status); } } /* return the type of HDU; tile compressed images which are stored */ /* in a binary table will return exttype = IMAGE_HDU, not BINARY_TBL */ if (exttype != NULL) ffghdt(fptr, exttype, status); return(*status); } /*--------------------------------------------------------------------------*/ int ffmrhd(fitsfile *fptr, /* I - FITS file pointer */ int hdumov, /* I - rel. no. of HDUs to move by (+ or -) */ int *exttype, /* O - type of extension, 0, 1, or 2 */ int *status) /* IO - error status */ /* Move a Relative number of Header Data units. Offset to the specified extension and read the header to initialize the HDU structure. */ { int extnum; if (*status > 0) return(*status); extnum = fptr->HDUposition + 1 + hdumov; /* the absolute HDU number */ ffmahd(fptr, extnum, exttype, status); /* move to the HDU */ return(*status); } /*--------------------------------------------------------------------------*/ int ffmnhd(fitsfile *fptr, /* I - FITS file pointer */ int exttype, /* I - desired extension type */ char *hduname, /* I - desired EXTNAME value for the HDU */ int hduver, /* I - desired EXTVERS value for the HDU */ int *status) /* IO - error status */ /* Move to the next HDU with a given extension type (IMAGE_HDU, ASCII_TBL, BINARY_TBL, or ANY_HDU), extension name (EXTNAME or HDUNAME keyword), and EXTVERS keyword values. If hduvers = 0, then move to the first HDU with the given type and name regardless of EXTVERS value. If no matching HDU is found in the file, then the current open HDU will remain unchanged. */ { char extname[FLEN_VALUE]; int ii, hdutype, alttype, extnum, tstatus, match, exact; int slen, putback = 0, chopped = 0; long extver; if (*status > 0) return(*status); extnum = fptr->HDUposition + 1; /* save the current HDU number */ /* This is a kludge to deal with a special case where the user specified a hduname that ended with a # character, which CFITSIO previously interpreted as a flag to mean "don't copy any other HDUs in the file into the virtual file in memory. If the remaining hduname does not end with a # character (meaning that the user originally entered a hduname ending in 2 # characters) then there is the possibility that the # character should be treated literally, if the actual EXTNAME also ends with a #. Setting putback = 1 means that we need to test for this case later on. */ if ((fptr->Fptr)->only_one) { /* if true, name orignally ended with a # */ slen = strlen(hduname); if (hduname[slen - 1] != '#') /* This will fail if real EXTNAME value */ putback = 1; /* ends with 2 # characters. */ } for (ii=1; 1; ii++) /* loop over all HDUs until EOF */ { tstatus = 0; if (ffmahd(fptr, ii, &hdutype, &tstatus)) /* move to next HDU */ { ffmahd(fptr, extnum, 0, status); /* restore original file position */ return(*status = BAD_HDU_NUM); /* couldn't find desired HDU */ } alttype = -1; if (fits_is_compressed_image(fptr, status)) alttype = BINARY_TBL; /* Does this HDU have a matching type? */ if (exttype == ANY_HDU || hdutype == exttype || hdutype == alttype) { ffmaky(fptr, 2, status); /* reset to the 2nd keyword in the header */ if (ffgkys(fptr, "EXTNAME", extname, 0, &tstatus) <= 0) /* get keyword */ { if (putback) { /* more of the kludge */ /* test if the EXTNAME value ends with a #; if so, chop it */ /* off before comparing the strings */ chopped = 0; slen = strlen(extname); if (extname[slen - 1] == '#') { extname[slen - 1] = '\0'; chopped = 1; } } /* see if the strings are an exact match */ ffcmps(extname, hduname, CASEINSEN, &match, &exact); } /* if EXTNAME keyword doesn't exist, or it does not match, then try HDUNAME */ if (tstatus || !exact) { tstatus = 0; if (ffgkys(fptr, "HDUNAME", extname, 0, &tstatus) <= 0) { if (putback) { /* more of the kludge */ chopped = 0; slen = strlen(extname); if (extname[slen - 1] == '#') { extname[slen - 1] = '\0'; /* chop off the # */ chopped = 1; } } /* see if the strings are an exact match */ ffcmps(extname, hduname, CASEINSEN, &match, &exact); } } if (!tstatus && exact) /* found a matching name */ { if (hduver) /* need to check if version numbers match? */ { if (ffgkyj(fptr, "EXTVER", &extver, 0, &tstatus) > 0) extver = 1; /* assume default EXTVER value */ if ( (int) extver == hduver) { if (chopped) { /* The # was literally part of the name, not a flag */ (fptr->Fptr)->only_one = 0; } return(*status); /* found matching name and vers */ } } else { if (chopped) { /* The # was literally part of the name, not a flag */ (fptr->Fptr)->only_one = 0; } return(*status); /* found matching name */ } } /* end of !tstatus && exact */ } /* end of matching HDU type */ } /* end of loop over HDUs */ } /*--------------------------------------------------------------------------*/ int ffthdu(fitsfile *fptr, /* I - FITS file pointer */ int *nhdu, /* O - number of HDUs in the file */ int *status) /* IO - error status */ /* Return the number of HDUs that currently exist in the file. */ { int ii, extnum, tstatus; if (*status > 0) return(*status); extnum = fptr->HDUposition + 1; /* save the current HDU number */ *nhdu = extnum - 1; /* if the CHDU is empty or not completely defined, just return */ if ((fptr->Fptr)->datastart == DATA_UNDEFINED) return(*status); tstatus = 0; /* loop until EOF */ for (ii=extnum; ffmahd(fptr, ii, 0, &tstatus) <= 0; ii++) { *nhdu = ii; } ffmahd(fptr, extnum, 0, status); /* restore orig file position */ return(*status); } /*--------------------------------------------------------------------------*/ int ffgext(fitsfile *fptr, /* I - FITS file pointer */ int hdunum, /* I - no. of HDU to move get (0 based) */ int *exttype, /* O - type of extension, 0, 1, or 2 */ int *status) /* IO - error status */ /* Get Extension. Move to the specified extension and initialize the HDU structure. */ { int xcurhdu, xmaxhdu; LONGLONG xheadend; if (*status > 0) return(*status); if (ffmbyt(fptr, (fptr->Fptr)->headstart[hdunum], REPORT_EOF, status) <= 0) { /* temporarily save current values, in case of error */ xcurhdu = (fptr->Fptr)->curhdu; xmaxhdu = (fptr->Fptr)->maxhdu; xheadend = (fptr->Fptr)->headend; /* set new parameter values */ (fptr->Fptr)->curhdu = hdunum; fptr->HDUposition = hdunum; (fptr->Fptr)->maxhdu = maxvalue((fptr->Fptr)->maxhdu, hdunum); (fptr->Fptr)->headend = (fptr->Fptr)->logfilesize; /* set max size */ if (ffrhdu(fptr, exttype, status) > 0) { /* failed to get the new HDU, so restore previous values */ (fptr->Fptr)->curhdu = xcurhdu; fptr->HDUposition = xcurhdu; (fptr->Fptr)->maxhdu = xmaxhdu; (fptr->Fptr)->headend = xheadend; } } return(*status); } /*--------------------------------------------------------------------------*/ int ffiblk(fitsfile *fptr, /* I - FITS file pointer */ long nblock, /* I - no. of blocks to insert */ int headdata, /* I - insert where? 0=header, 1=data */ /* -1=beginning of file */ int *status) /* IO - error status */ /* insert 2880-byte blocks at the end of the current header or data unit */ { int tstatus, savehdu, typhdu; LONGLONG insertpt, jpoint; long ii, nshift; char charfill; char buff1[2880], buff2[2880]; char *inbuff, *outbuff, *tmpbuff; char card[FLEN_CARD]; if (*status > 0 || nblock <= 0) return(*status); tstatus = *status; if (headdata == 0 || (fptr->Fptr)->hdutype == ASCII_TBL) charfill = 32; /* headers and ASCII tables have space (32) fill */ else charfill = 0; /* images and binary tables have zero fill */ if (headdata == 0) insertpt = (fptr->Fptr)->datastart; /* insert just before data, or */ else if (headdata == -1) { insertpt = 0; strcpy(card, "XTENSION= 'IMAGE ' / IMAGE extension"); } else /* at end of data, */ { insertpt = (fptr->Fptr)->datastart + (fptr->Fptr)->heapstart + (fptr->Fptr)->heapsize; insertpt = ((insertpt + 2879) / 2880) * 2880; /* start of block */ /* the following formula is wrong because the current data unit may have been extended without updating the headstart value of the following HDU. */ /* insertpt = (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu + 1]; */ } inbuff = buff1; /* set pointers to input and output buffers */ outbuff = buff2; memset(outbuff, charfill, 2880); /* initialize buffer with fill */ if (nblock == 1) /* insert one block */ { if (headdata == -1) ffmrec(fptr, 1, card, status); /* change SIMPLE -> XTENSION */ ffmbyt(fptr, insertpt, REPORT_EOF, status); /* move to 1st point */ ffgbyt(fptr, 2880, inbuff, status); /* read first block of bytes */ while (*status <= 0) { ffmbyt(fptr, insertpt, REPORT_EOF, status); /* insert point */ ffpbyt(fptr, 2880, outbuff, status); /* write the output buffer */ if (*status > 0) return(*status); tmpbuff = inbuff; /* swap input and output pointers */ inbuff = outbuff; outbuff = tmpbuff; insertpt += 2880; /* increment insert point by 1 block */ ffmbyt(fptr, insertpt, REPORT_EOF, status); /* move to next block */ ffgbyt(fptr, 2880, inbuff, status); /* read block of bytes */ } *status = tstatus; /* reset status value */ ffmbyt(fptr, insertpt, IGNORE_EOF, status); /* move back to insert pt */ ffpbyt(fptr, 2880, outbuff, status); /* write the final block */ } else /* inserting more than 1 block */ { savehdu = (fptr->Fptr)->curhdu; /* save the current HDU number */ tstatus = *status; while(*status <= 0) /* find the last HDU in file */ ffmrhd(fptr, 1, &typhdu, status); if (*status == END_OF_FILE) { *status = tstatus; } ffmahd(fptr, savehdu + 1, &typhdu, status); /* move back to CHDU */ if (headdata == -1) ffmrec(fptr, 1, card, status); /* NOW change SIMPLE -> XTENSION */ /* number of 2880-byte blocks that have to be shifted down */ nshift = (long) (((fptr->Fptr)->headstart[(fptr->Fptr)->maxhdu + 1] - insertpt) / 2880); /* position of last block in file to be shifted */ jpoint = (fptr->Fptr)->headstart[(fptr->Fptr)->maxhdu + 1] - 2880; /* move all the blocks starting at end of file working backwards */ for (ii = 0; ii < nshift; ii++) { /* move to the read start position */ if (ffmbyt(fptr, jpoint, REPORT_EOF, status) > 0) return(*status); ffgbyt(fptr, 2880, inbuff,status); /* read one record */ /* move forward to the write postion */ ffmbyt(fptr, jpoint + ((LONGLONG) nblock * 2880), IGNORE_EOF, status); ffpbyt(fptr, 2880, inbuff, status); /* write the record */ jpoint -= 2880; } /* move back to the write start postion (might be EOF) */ ffmbyt(fptr, insertpt, IGNORE_EOF, status); for (ii = 0; ii < nblock; ii++) /* insert correct fill value */ ffpbyt(fptr, 2880, outbuff, status); } if (headdata == 0) /* update data start address */ (fptr->Fptr)->datastart += ((LONGLONG) nblock * 2880); /* update following HDU addresses */ for (ii = (fptr->Fptr)->curhdu; ii <= (fptr->Fptr)->maxhdu; ii++) (fptr->Fptr)->headstart[ii + 1] += ((LONGLONG) nblock * 2880); return(*status); } /*--------------------------------------------------------------------------*/ int ffgkcl(char *tcard) /* Return the type classification of the input header record TYP_STRUC_KEY: SIMPLE, BITPIX, NAXIS, NAXISn, EXTEND, BLOCKED, GROUPS, PCOUNT, GCOUNT, END XTENSION, TFIELDS, TTYPEn, TBCOLn, TFORMn, THEAP, and the first 4 COMMENT keywords in the primary array that define the FITS format. TYP_CMPRS_KEY: The keywords used in the compressed image format ZIMAGE, ZCMPTYPE, ZNAMEn, ZVALn, ZTILEn, ZBITPIX, ZNAXISn, ZSCALE, ZZERO, ZBLANK, EXTNAME = 'COMPRESSED_IMAGE' ZSIMPLE, ZTENSION, ZEXTEND, ZBLOCKED, ZPCOUNT, ZGCOUNT ZQUANTIZ, ZDITHER0 TYP_SCAL_KEY: BSCALE, BZERO, TSCALn, TZEROn TYP_NULL_KEY: BLANK, TNULLn TYP_DIM_KEY: TDIMn TYP_RANG_KEY: TLMINn, TLMAXn, TDMINn, TDMAXn, DATAMIN, DATAMAX TYP_UNIT_KEY: BUNIT, TUNITn TYP_DISP_KEY: TDISPn TYP_HDUID_KEY: EXTNAME, EXTVER, EXTLEVEL, HDUNAME, HDUVER, HDULEVEL TYP_CKSUM_KEY CHECKSUM, DATASUM TYP_WCS_KEY: Primary array: WCAXES, CTYPEn, CUNITn, CRVALn, CRPIXn, CROTAn, CDELTn CDj_is, PVj_ms, LONPOLEs, LATPOLEs Pixel list: TCTYPn, TCTYns, TCUNIn, TCUNns, TCRVLn, TCRVns, TCRPXn, TCRPks, TCDn_k, TCn_ks, TPVn_m, TPn_ms, TCDLTn, TCROTn Bintable vector: jCTYPn, jCTYns, jCUNIn, jCUNns, jCRVLn, jCRVns, iCRPXn, iCRPns, jiCDn, jiCDns, jPVn_m, jPn_ms, jCDLTn, jCROTn TYP_REFSYS_KEY: EQUINOXs, EPOCH, MJD-OBSs, RADECSYS, RADESYSs TYP_COMM_KEY: COMMENT, HISTORY, (blank keyword) TYP_CONT_KEY: CONTINUE TYP_USER_KEY: all other keywords */ { char card[20], *card1, *card5; card[0] = '\0'; strncat(card, tcard, 8); /* copy the keyword name */ strcat(card, " "); /* append blanks to make at least 8 chars long */ ffupch(card); /* make sure it is in upper case */ card1 = card + 1; /* pointer to 2nd character */ card5 = card + 5; /* pointer to 6th character */ /* the strncmp function is slow, so try to be more efficient */ if (*card == 'Z') { if (FSTRNCMP (card1, "IMAGE ", 7) == 0) return (TYP_CMPRS_KEY); else if (FSTRNCMP (card1, "CMPTYPE", 7) == 0) return (TYP_CMPRS_KEY); else if (FSTRNCMP (card1, "NAME", 4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_CMPRS_KEY); } else if (FSTRNCMP (card1, "VAL", 3) == 0) { if (*(card + 4) >= '0' && *(card + 4) <= '9') return (TYP_CMPRS_KEY); } else if (FSTRNCMP (card1, "TILE", 4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_CMPRS_KEY); } else if (FSTRNCMP (card1, "BITPIX ", 7) == 0) return (TYP_CMPRS_KEY); else if (FSTRNCMP (card1, "NAXIS", 5) == 0) { if ( ( *(card + 6) >= '0' && *(card + 6) <= '9' ) || (*(card + 6) == ' ') ) return (TYP_CMPRS_KEY); } else if (FSTRNCMP (card1, "SCALE ", 7) == 0) return (TYP_CMPRS_KEY); else if (FSTRNCMP (card1, "ZERO ", 7) == 0) return (TYP_CMPRS_KEY); else if (FSTRNCMP (card1, "BLANK ", 7) == 0) return (TYP_CMPRS_KEY); else if (FSTRNCMP (card1, "SIMPLE ", 7) == 0) return (TYP_CMPRS_KEY); else if (FSTRNCMP (card1, "TENSION", 7) == 0) return (TYP_CMPRS_KEY); else if (FSTRNCMP (card1, "EXTEND ", 7) == 0) return (TYP_CMPRS_KEY); else if (FSTRNCMP (card1, "BLOCKED", 7) == 0) return (TYP_CMPRS_KEY); else if (FSTRNCMP (card1, "PCOUNT ", 7) == 0) return (TYP_CMPRS_KEY); else if (FSTRNCMP (card1, "GCOUNT ", 7) == 0) return (TYP_CMPRS_KEY); else if (FSTRNCMP (card1, "QUANTIZ", 7) == 0) return (TYP_CMPRS_KEY); else if (FSTRNCMP (card1, "DITHER0", 7) == 0) return (TYP_CMPRS_KEY); } else if (*card == ' ') { return (TYP_COMM_KEY); } else if (*card == 'B') { if (FSTRNCMP (card1, "ITPIX ", 7) == 0) return (TYP_STRUC_KEY); if (FSTRNCMP (card1, "LOCKED ", 7) == 0) return (TYP_STRUC_KEY); if (FSTRNCMP (card1, "LANK ", 7) == 0) return (TYP_NULL_KEY); if (FSTRNCMP (card1, "SCALE ", 7) == 0) return (TYP_SCAL_KEY); if (FSTRNCMP (card1, "ZERO ", 7) == 0) return (TYP_SCAL_KEY); if (FSTRNCMP (card1, "UNIT ", 7) == 0) return (TYP_UNIT_KEY); } else if (*card == 'C') { if (FSTRNCMP (card1, "OMMENT",6) == 0) { /* new comment string starting Oct 2001 */ if (FSTRNCMP (tcard, "COMMENT and Astrophysics', volume 376, page 3", 47) == 0) return (TYP_STRUC_KEY); /* original COMMENT strings from 1993 - 2001 */ if (FSTRNCMP (tcard, "COMMENT FITS (Flexible Image Transport System", 47) == 0) return (TYP_STRUC_KEY); if (FSTRNCMP (tcard, "COMMENT Astrophysics Supplement Series v44/p3", 47) == 0) return (TYP_STRUC_KEY); if (FSTRNCMP (tcard, "COMMENT Contact the NASA Science Office of St", 47) == 0) return (TYP_STRUC_KEY); if (FSTRNCMP (tcard, "COMMENT FITS Definition document #100 and oth", 47) == 0) return (TYP_STRUC_KEY); if (*(card + 7) == ' ') return (TYP_COMM_KEY); else return (TYP_USER_KEY); } if (FSTRNCMP (card1, "HECKSUM", 7) == 0) return (TYP_CKSUM_KEY); if (FSTRNCMP (card1, "ONTINUE", 7) == 0) return (TYP_CONT_KEY); if (FSTRNCMP (card1, "TYPE",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "UNIT",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "RVAL",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "RPIX",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "ROTA",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "RDER",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "SYER",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "DELT",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (*card1 == 'D') { if (*(card + 2) >= '0' && *(card + 2) <= '9') return (TYP_WCS_KEY); } } else if (*card == 'D') { if (FSTRNCMP (card1, "ATASUM ", 7) == 0) return (TYP_CKSUM_KEY); if (FSTRNCMP (card1, "ATAMIN ", 7) == 0) return (TYP_RANG_KEY); if (FSTRNCMP (card1, "ATAMAX ", 7) == 0) return (TYP_RANG_KEY); if (FSTRNCMP (card1, "ATE-OBS", 7) == 0) return (TYP_REFSYS_KEY); } else if (*card == 'E') { if (FSTRNCMP (card1, "XTEND ", 7) == 0) return (TYP_STRUC_KEY); if (FSTRNCMP (card1, "ND ", 7) == 0) return (TYP_STRUC_KEY); if (FSTRNCMP (card1, "XTNAME ", 7) == 0) { /* check for special compressed image value */ if (FSTRNCMP(tcard, "EXTNAME = 'COMPRESSED_IMAGE'", 28) == 0) return (TYP_CMPRS_KEY); else return (TYP_HDUID_KEY); } if (FSTRNCMP (card1, "XTVER ", 7) == 0) return (TYP_HDUID_KEY); if (FSTRNCMP (card1, "XTLEVEL", 7) == 0) return (TYP_HDUID_KEY); if (FSTRNCMP (card1, "QUINOX", 6) == 0) return (TYP_REFSYS_KEY); if (FSTRNCMP (card1, "QUI",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_REFSYS_KEY); } if (FSTRNCMP (card1, "POCH ", 7) == 0) return (TYP_REFSYS_KEY); } else if (*card == 'G') { if (FSTRNCMP (card1, "COUNT ", 7) == 0) return (TYP_STRUC_KEY); if (FSTRNCMP (card1, "ROUPS ", 7) == 0) return (TYP_STRUC_KEY); } else if (*card == 'H') { if (FSTRNCMP (card1, "DUNAME ", 7) == 0) return (TYP_HDUID_KEY); if (FSTRNCMP (card1, "DUVER ", 7) == 0) return (TYP_HDUID_KEY); if (FSTRNCMP (card1, "DULEVEL", 7) == 0) return (TYP_HDUID_KEY); if (FSTRNCMP (card1, "ISTORY",6) == 0) { if (*(card + 7) == ' ') return (TYP_COMM_KEY); else return (TYP_USER_KEY); } } else if (*card == 'L') { if (FSTRNCMP (card1, "ONPOLE",6) == 0) return (TYP_WCS_KEY); if (FSTRNCMP (card1, "ATPOLE",6) == 0) return (TYP_WCS_KEY); if (FSTRNCMP (card1, "ONP",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "ATP",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } } else if (*card == 'M') { if (FSTRNCMP (card1, "JD-OBS ", 7) == 0) return (TYP_REFSYS_KEY); if (FSTRNCMP (card1, "JDOB",4) == 0) { if (*(card+5) >= '0' && *(card+5) <= '9') return (TYP_REFSYS_KEY); } } else if (*card == 'N') { if (FSTRNCMP (card1, "AXIS", 4) == 0) { if ((*card5 >= '0' && *card5 <= '9') || (*card5 == ' ')) return (TYP_STRUC_KEY); } } else if (*card == 'P') { if (FSTRNCMP (card1, "COUNT ", 7) == 0) return (TYP_STRUC_KEY); if (*card1 == 'C') { if (*(card + 2) >= '0' && *(card + 2) <= '9') return (TYP_WCS_KEY); } else if (*card1 == 'V') { if (*(card + 2) >= '0' && *(card + 2) <= '9') return (TYP_WCS_KEY); } else if (*card1 == 'S') { if (*(card + 2) >= '0' && *(card + 2) <= '9') return (TYP_WCS_KEY); } } else if (*card == 'R') { if (FSTRNCMP (card1, "ADECSYS", 7) == 0) return (TYP_REFSYS_KEY); if (FSTRNCMP (card1, "ADESYS", 6) == 0) return (TYP_REFSYS_KEY); if (FSTRNCMP (card1, "ADE",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_REFSYS_KEY); } } else if (*card == 'S') { if (FSTRNCMP (card1, "IMPLE ", 7) == 0) return (TYP_STRUC_KEY); } else if (*card == 'T') { if (FSTRNCMP (card1, "TYPE", 4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_STRUC_KEY); } else if (FSTRNCMP (card1, "FORM", 4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_STRUC_KEY); } else if (FSTRNCMP (card1, "BCOL", 4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_STRUC_KEY); } else if (FSTRNCMP (card1, "FIELDS ", 7) == 0) return (TYP_STRUC_KEY); else if (FSTRNCMP (card1, "HEAP ", 7) == 0) return (TYP_STRUC_KEY); else if (FSTRNCMP (card1, "NULL", 4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_NULL_KEY); } else if (FSTRNCMP (card1, "DIM", 3) == 0) { if (*(card + 4) >= '0' && *(card + 4) <= '9') return (TYP_DIM_KEY); } else if (FSTRNCMP (card1, "UNIT", 4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_UNIT_KEY); } else if (FSTRNCMP (card1, "DISP", 4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_DISP_KEY); } else if (FSTRNCMP (card1, "SCAL", 4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_SCAL_KEY); } else if (FSTRNCMP (card1, "ZERO", 4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_SCAL_KEY); } else if (FSTRNCMP (card1, "LMIN", 4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_RANG_KEY); } else if (FSTRNCMP (card1, "LMAX", 4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_RANG_KEY); } else if (FSTRNCMP (card1, "DMIN", 4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_RANG_KEY); } else if (FSTRNCMP (card1, "DMAX", 4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_RANG_KEY); } else if (FSTRNCMP (card1, "CTYP",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CTY",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CUNI",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CUN",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CRVL",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CRV",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CRPX",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CRP",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CROT",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CDLT",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CDE",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CRD",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CSY",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "WCS",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "C",1) == 0) { if (*(card + 2) >= '0' && *(card + 2) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "P",1) == 0) { if (*(card + 2) >= '0' && *(card + 2) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "V",1) == 0) { if (*(card + 2) >= '0' && *(card + 2) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "S",1) == 0) { if (*(card + 2) >= '0' && *(card + 2) <= '9') return (TYP_WCS_KEY); } } else if (*card == 'X') { if (FSTRNCMP (card1, "TENSION", 7) == 0) return (TYP_STRUC_KEY); } else if (*card == 'W') { if (FSTRNCMP (card1, "CSAXES", 6) == 0) return (TYP_WCS_KEY); if (FSTRNCMP (card1, "CSNAME", 6) == 0) return (TYP_WCS_KEY); if (FSTRNCMP (card1, "CAX", 3) == 0) { if (*(card + 4) >= '0' && *(card + 4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CSN", 3) == 0) { if (*(card + 4) >= '0' && *(card + 4) <= '9') return (TYP_WCS_KEY); } } else if (*card >= '0' && *card <= '9') { if (*card1 == 'C') { if (FSTRNCMP (card1, "CTYP",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CTY",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CUNI",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CUN",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CRVL",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CRV",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CRPX",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CRP",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CROT",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CDLT",4) == 0) { if (*card5 >= '0' && *card5 <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CDE",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CRD",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "CSY",3) == 0) { if (*(card+4) >= '0' && *(card+4) <= '9') return (TYP_WCS_KEY); } } else if (FSTRNCMP (card1, "V",1) == 0) { if (*(card + 2) >= '0' && *(card + 2) <= '9') return (TYP_WCS_KEY); } else if (FSTRNCMP (card1, "S",1) == 0) { if (*(card + 2) >= '0' && *(card + 2) <= '9') return (TYP_WCS_KEY); } else if (*card1 >= '0' && *card1 <= '9') { /* 2 digits at beginning of keyword */ if ( (*(card + 2) == 'P') && (*(card + 3) == 'C') ) { if (*(card + 4) >= '0' && *(card + 4) <= '9') return (TYP_WCS_KEY); /* ijPCn keyword */ } else if ( (*(card + 2) == 'C') && (*(card + 3) == 'D') ) { if (*(card + 4) >= '0' && *(card + 4) <= '9') return (TYP_WCS_KEY); /* ijCDn keyword */ } } } return (TYP_USER_KEY); /* by default all others are user keywords */ } /*--------------------------------------------------------------------------*/ int ffdtyp(const char *cval, /* I - formatted string representation of the value */ char *dtype, /* O - datatype code: C, L, F, I, or X */ int *status) /* IO - error status */ /* determine implicit datatype of input string. This assumes that the string conforms to the FITS standard for keyword values, so may not detect all invalid formats. */ { if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (cval[0] == '\0') return(*status = VALUE_UNDEFINED); else if (cval[0] == '\'') *dtype = 'C'; /* character string starts with a quote */ else if (cval[0] == 'T' || cval[0] == 'F') *dtype = 'L'; /* logical = T or F character */ else if (cval[0] == '(') *dtype = 'X'; /* complex datatype "(1.2, -3.4)" */ else if (strchr(cval,'.')) *dtype = 'F'; /* float usualy contains a decimal point */ else if (strchr(cval,'E') || strchr(cval,'D') ) *dtype = 'F'; /* exponential contains a E or D */ else *dtype = 'I'; /* if none of the above assume it is integer */ return(*status); } /*--------------------------------------------------------------------------*/ int ffinttyp(char *cval, /* I - formatted string representation of the integer */ int *dtype, /* O - datatype code: TBYTE, TSHORT, TUSHORT, etc */ int *negative, /* O - is cval negative? */ int *status) /* IO - error status */ /* determine implicit datatype of input integer string. This assumes that the string conforms to the FITS standard for integer keyword value, so may not detect all invalid formats. */ { int ii, len; char *p; if (*status > 0) /* inherit input status value if > 0 */ return(*status); *dtype = 0; /* initialize to NULL */ *negative = 0; p = cval; if (*p == '+') { p++; /* ignore leading + sign */ } else if (*p == '-') { p++; *negative = 1; /* this is a negative number */ } if (*p == '0') { while (*p == '0') p++; /* skip leading zeros */ if (*p == 0) { /* the value is a string of 1 or more zeros */ *dtype = TSBYTE; return(*status); } } len = strlen(p); for (ii = 0; ii < len; ii++) { if (!isdigit(*(p+ii))) { *status = BAD_INTKEY; return(*status); } } /* check for unambiguous cases, based on length of the string */ if (len == 0) { *status = VALUE_UNDEFINED; } else if (len < 3) { *dtype = TSBYTE; } else if (len == 4) { *dtype = TSHORT; } else if (len > 5 && len < 10) { *dtype = TINT; } else if (len > 10 && len < 19) { *dtype = TLONGLONG; } else if (len > 19) { *status = BAD_INTKEY; } else { if (!(*negative)) { /* positive integers */ if (len == 3) { if (strcmp(p,"127") <= 0 ) { *dtype = TSBYTE; } else if (strcmp(p,"255") <= 0 ) { *dtype = TBYTE; } else { *dtype = TSHORT; } } else if (len == 5) { if (strcmp(p,"32767") <= 0 ) { *dtype = TSHORT; } else if (strcmp(p,"65535") <= 0 ) { *dtype = TUSHORT; } else { *dtype = TINT; } } else if (len == 10) { if (strcmp(p,"2147483647") <= 0 ) { *dtype = TINT; } else if (strcmp(p,"4294967295") <= 0 ) { *dtype = TUINT; } else { *dtype = TLONGLONG; } } else if (len == 19) { if (strcmp(p,"9223372036854775807") <= 0 ) { *dtype = TLONGLONG; } else { *status = BAD_INTKEY; } } } else { /* negative integers */ if (len == 3) { if (strcmp(p,"128") <= 0 ) { *dtype = TSBYTE; } else { *dtype = TSHORT; } } else if (len == 5) { if (strcmp(p,"32768") <= 0 ) { *dtype = TSHORT; } else { *dtype = TINT; } } else if (len == 10) { if (strcmp(p,"2147483648") <= 0 ) { *dtype = TINT; } else { *dtype = TLONGLONG; } } else if (len == 19) { if (strcmp(p,"9223372036854775808") <= 0 ) { *dtype = TLONGLONG; } else { *status = BAD_INTKEY; } } } } return(*status); } /*--------------------------------------------------------------------------*/ int ffc2x(const char *cval, /* I - formatted string representation of the value */ char *dtype, /* O - datatype code: C, L, F, I or X */ /* Only one of the following will be defined, depending on datatype */ long *ival, /* O - integer value */ int *lval, /* O - logical value */ char *sval, /* O - string value */ double *dval, /* O - double value */ int *status) /* IO - error status */ /* high level routine to convert formatted character string to its intrinsic data type */ { ffdtyp(cval, dtype, status); /* determine the datatype */ if (*dtype == 'I') ffc2ii(cval, ival, status); else if (*dtype == 'F') ffc2dd(cval, dval, status); else if (*dtype == 'L') ffc2ll(cval, lval, status); else ffc2s(cval, sval, status); /* C and X formats */ return(*status); } /*--------------------------------------------------------------------------*/ int ffc2xx(const char *cval, /* I - formatted string representation of the value */ char *dtype, /* O - datatype code: C, L, F, I or X */ /* Only one of the following will be defined, depending on datatype */ LONGLONG *ival, /* O - integer value */ int *lval, /* O - logical value */ char *sval, /* O - string value */ double *dval, /* O - double value */ int *status) /* IO - error status */ /* high level routine to convert formatted character string to its intrinsic data type */ { ffdtyp(cval, dtype, status); /* determine the datatype */ if (*dtype == 'I') ffc2jj(cval, ival, status); else if (*dtype == 'F') ffc2dd(cval, dval, status); else if (*dtype == 'L') ffc2ll(cval, lval, status); else ffc2s(cval, sval, status); /* C and X formats */ return(*status); } /*--------------------------------------------------------------------------*/ int ffc2i(const char *cval, /* I - string representation of the value */ long *ival, /* O - numerical value of the input string */ int *status) /* IO - error status */ /* convert formatted string to an integer value, doing implicit datatype conversion if necessary. */ { char dtype, sval[81], msg[81]; int lval; double dval; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (cval[0] == '\0') return(*status = VALUE_UNDEFINED); /* null value string */ /* convert the keyword to its native datatype */ ffc2x(cval, &dtype, ival, &lval, sval, &dval, status); if (dtype == 'X' ) { *status = BAD_INTKEY; } else if (dtype == 'C') { /* try reading the string as a number */ if (ffc2dd(sval, &dval, status) <= 0) { if (dval > (double) LONG_MAX || dval < (double) LONG_MIN) *status = NUM_OVERFLOW; else *ival = (long) dval; } } else if (dtype == 'F') { if (dval > (double) LONG_MAX || dval < (double) LONG_MIN) *status = NUM_OVERFLOW; else *ival = (long) dval; } else if (dtype == 'L') { *ival = (long) lval; } if (*status > 0) { *ival = 0; strcpy(msg,"Error in ffc2i evaluating string as an integer: "); strncat(msg,cval,30); ffpmsg(msg); return(*status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffc2j(const char *cval, /* I - string representation of the value */ LONGLONG *ival, /* O - numerical value of the input string */ int *status) /* IO - error status */ /* convert formatted string to a LONGLONG integer value, doing implicit datatype conversion if necessary. */ { char dtype, sval[81], msg[81]; int lval; double dval; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (cval[0] == '\0') return(*status = VALUE_UNDEFINED); /* null value string */ /* convert the keyword to its native datatype */ ffc2xx(cval, &dtype, ival, &lval, sval, &dval, status); if (dtype == 'X' ) { *status = BAD_INTKEY; } else if (dtype == 'C') { /* try reading the string as a number */ if (ffc2dd(sval, &dval, status) <= 0) { if (dval > (double) LONGLONG_MAX || dval < (double) LONGLONG_MIN) *status = NUM_OVERFLOW; else *ival = (LONGLONG) dval; } } else if (dtype == 'F') { if (dval > (double) LONGLONG_MAX || dval < (double) LONGLONG_MIN) *status = NUM_OVERFLOW; else *ival = (LONGLONG) dval; } else if (dtype == 'L') { *ival = (LONGLONG) lval; } if (*status > 0) { *ival = 0; strcpy(msg,"Error in ffc2j evaluating string as a long integer: "); strncat(msg,cval,30); ffpmsg(msg); return(*status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffc2l(const char *cval, /* I - string representation of the value */ int *lval, /* O - numerical value of the input string */ int *status) /* IO - error status */ /* convert formatted string to a logical value, doing implicit datatype conversion if necessary */ { char dtype, sval[81], msg[81]; long ival; double dval; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (cval[0] == '\0') return(*status = VALUE_UNDEFINED); /* null value string */ /* convert the keyword to its native datatype */ ffc2x(cval, &dtype, &ival, lval, sval, &dval, status); if (dtype == 'C' || dtype == 'X' ) *status = BAD_LOGICALKEY; if (*status > 0) { *lval = 0; strcpy(msg,"Error in ffc2l evaluating string as a logical: "); strncat(msg,cval,30); ffpmsg(msg); return(*status); } if (dtype == 'I') { if (ival) *lval = 1; else *lval = 0; } else if (dtype == 'F') { if (dval) *lval = 1; else *lval = 0; } return(*status); } /*--------------------------------------------------------------------------*/ int ffc2r(const char *cval, /* I - string representation of the value */ float *fval, /* O - numerical value of the input string */ int *status) /* IO - error status */ /* convert formatted string to a real float value, doing implicit datatype conversion if necessary */ { char dtype, sval[81], msg[81]; int lval; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (cval[0] == '\0') return(*status = VALUE_UNDEFINED); /* null value string */ ffdtyp(cval, &dtype, status); /* determine the datatype */ if (dtype == 'I' || dtype == 'F') ffc2rr(cval, fval, status); else if (dtype == 'L') { ffc2ll(cval, &lval, status); *fval = (float) lval; } else if (dtype == 'C') { /* try reading the string as a number */ ffc2s(cval, sval, status); ffc2rr(sval, fval, status); } else *status = BAD_FLOATKEY; if (*status > 0) { *fval = 0.; strcpy(msg,"Error in ffc2r evaluating string as a float: "); strncat(msg,cval,30); ffpmsg(msg); return(*status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffc2d(const char *cval, /* I - string representation of the value */ double *dval, /* O - numerical value of the input string */ int *status) /* IO - error status */ /* convert formatted string to a double value, doing implicit datatype conversion if necessary */ { char dtype, sval[81], msg[81]; int lval; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (cval[0] == '\0') return(*status = VALUE_UNDEFINED); /* null value string */ ffdtyp(cval, &dtype, status); /* determine the datatype */ if (dtype == 'I' || dtype == 'F') ffc2dd(cval, dval, status); else if (dtype == 'L') { ffc2ll(cval, &lval, status); *dval = (double) lval; } else if (dtype == 'C') { /* try reading the string as a number */ ffc2s(cval, sval, status); ffc2dd(sval, dval, status); } else *status = BAD_DOUBLEKEY; if (*status > 0) { *dval = 0.; strcpy(msg,"Error in ffc2d evaluating string as a double: "); strncat(msg,cval,30); ffpmsg(msg); return(*status); } return(*status); } /*--------------------------------------------------------------------------*/ int ffc2ii(const char *cval, /* I - string representation of the value */ long *ival, /* O - numerical value of the input string */ int *status) /* IO - error status */ /* convert null-terminated formatted string to an integer value */ { char *loc, msg[81]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); errno = 0; *ival = 0; *ival = strtol(cval, &loc, 10); /* read the string as an integer */ /* check for read error, or junk following the integer */ if (*loc != '\0' && *loc != ' ' ) *status = BAD_C2I; if (errno == ERANGE) { strcpy(msg,"Range Error in ffc2ii converting string to long int: "); strncat(msg,cval,25); ffpmsg(msg); *status = NUM_OVERFLOW; errno = 0; } return(*status); } /*--------------------------------------------------------------------------*/ int ffc2jj(const char *cval, /* I - string representation of the value */ LONGLONG *ival, /* O - numerical value of the input string */ int *status) /* IO - error status */ /* convert null-terminated formatted string to an long long integer value */ { char *loc, msg[81]; if (*status > 0) /* inherit input status value if > 0 */ return(*status); errno = 0; *ival = 0; #if defined(_MSC_VER) /* Microsoft Visual C++ 6.0 does not have the strtoll function */ *ival = _atoi64(cval); loc = (char *) cval; while (*loc == ' ') loc++; /* skip spaces */ if (*loc == '-') loc++; /* skip minus sign */ if (*loc == '+') loc++; /* skip plus sign */ while (isdigit(*loc)) loc++; /* skip digits */ #elif (USE_LL_SUFFIX == 1) *ival = strtoll(cval, &loc, 10); /* read the string as an integer */ #else *ival = strtol(cval, &loc, 10); /* read the string as an integer */ #endif /* check for read error, or junk following the integer */ if (*loc != '\0' && *loc != ' ' ) *status = BAD_C2I; if (errno == ERANGE) { strcpy(msg,"Range Error in ffc2jj converting string to longlong int: "); strncat(msg,cval,25); ffpmsg(msg); *status = NUM_OVERFLOW; errno = 0; } return(*status); } /*--------------------------------------------------------------------------*/ int ffc2ll(const char *cval, /* I - string representation of the value: T or F */ int *lval, /* O - numerical value of the input string: 1 or 0 */ int *status) /* IO - error status */ /* convert null-terminated formatted string to a logical value */ { if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (cval[0] == 'T') *lval = 1; else *lval = 0; /* any character besides T is considered false */ return(*status); } /*--------------------------------------------------------------------------*/ int ffc2s(const char *instr, /* I - null terminated quoted input string */ char *outstr, /* O - null terminated output string without quotes */ int *status) /* IO - error status */ /* convert an input quoted string to an unquoted string by removing the leading and trailing quote character. Also, replace any pairs of single quote characters with just a single quote character (FITS used a pair of single quotes to represent a literal quote character within the string). */ { int jj; size_t len, ii; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (instr[0] != '\'') { if (instr[0] == '\0') { outstr[0] = '\0'; return(*status = VALUE_UNDEFINED); /* null value string */ } else { strcpy(outstr, instr); /* no leading quote, so return input string */ return(*status); } } len = strlen(instr); for (ii=1, jj=0; ii < len; ii++, jj++) { if (instr[ii] == '\'') /* is this the closing quote? */ { if (instr[ii+1] == '\'') /* 2 successive quotes? */ ii++; /* copy only one of the quotes */ else break; /* found the closing quote, so exit this loop */ } outstr[jj] = instr[ii]; /* copy the next character to the output */ } outstr[jj] = '\0'; /* terminate the output string */ if (ii == len) { ffpmsg("This string value has no closing quote (ffc2s):"); ffpmsg(instr); return(*status = 205); } for (jj--; jj >= 0; jj--) /* replace trailing blanks with nulls */ { if (outstr[jj] == ' ') outstr[jj] = 0; else break; } return(*status); } /*--------------------------------------------------------------------------*/ int ffc2rr(const char *cval, /* I - string representation of the value */ float *fval, /* O - numerical value of the input string */ int *status) /* IO - error status */ /* convert null-terminated formatted string to a float value */ { char *loc, msg[81], tval[73]; struct lconv *lcc = 0; static char decimalpt = 0; short *sptr, iret; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (!decimalpt) { /* only do this once for efficiency */ lcc = localeconv(); /* set structure containing local decimal point symbol */ decimalpt = *(lcc->decimal_point); } errno = 0; *fval = 0.; if (strchr(cval, 'D') || decimalpt == ',') { /* strtod expects a comma, not a period, as the decimal point */ strcpy(tval, cval); /* The C language does not support a 'D'; replace with 'E' */ if ((loc = strchr(tval, 'D'))) *loc = 'E'; if (decimalpt == ',') { /* strtod expects a comma, not a period, as the decimal point */ if ((loc = strchr(tval, '.'))) *loc = ','; } *fval = (float) strtod(tval, &loc); /* read the string as an float */ } else { *fval = (float) strtod(cval, &loc); } /* check for read error, or junk following the value */ if (*loc != '\0' && *loc != ' ' ) { strcpy(msg,"Error in ffc2rr converting string to float: "); strncat(msg,cval,30); ffpmsg(msg); *status = BAD_C2F; } sptr = (short *) fval; #if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS sptr++; /* point to MSBs */ #endif iret = fnan(*sptr); /* if iret == 1, then the float value is a NaN */ if (errno == ERANGE || (iret == 1) ) { strcpy(msg,"Error in ffc2rr converting string to float: "); strncat(msg,cval,30); ffpmsg(msg); *fval = 0.; *status = NUM_OVERFLOW; errno = 0; } return(*status); } /*--------------------------------------------------------------------------*/ int ffc2dd(const char *cval, /* I - string representation of the value */ double *dval, /* O - numerical value of the input string */ int *status) /* IO - error status */ /* convert null-terminated formatted string to a double value */ { char *loc, msg[81], tval[73]; struct lconv *lcc = 0; static char decimalpt = 0; short *sptr, iret; if (*status > 0) /* inherit input status value if > 0 */ return(*status); if (!decimalpt) { /* only do this once for efficiency */ lcc = localeconv(); /* set structure containing local decimal point symbol */ decimalpt = *(lcc->decimal_point); } errno = 0; *dval = 0.; if (strchr(cval, 'D') || decimalpt == ',') { /* need to modify a temporary copy of the string before parsing it */ strcpy(tval, cval); /* The C language does not support a 'D'; replace with 'E' */ if ((loc = strchr(tval, 'D'))) *loc = 'E'; if (decimalpt == ',') { /* strtod expects a comma, not a period, as the decimal point */ if ((loc = strchr(tval, '.'))) *loc = ','; } *dval = strtod(tval, &loc); /* read the string as an double */ } else { *dval = strtod(cval, &loc); } /* check for read error, or junk following the value */ if (*loc != '\0' && *loc != ' ' ) { strcpy(msg,"Error in ffc2dd converting string to double: "); strncat(msg,cval,30); ffpmsg(msg); *status = BAD_C2D; } sptr = (short *) dval; #if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS sptr += 3; /* point to MSBs */ #endif iret = dnan(*sptr); /* if iret == 1, then the double value is a NaN */ if (errno == ERANGE || (iret == 1) ) { strcpy(msg,"Error in ffc2dd converting string to double: "); strncat(msg,cval,30); ffpmsg(msg); *dval = 0.; *status = NUM_OVERFLOW; errno = 0; } return(*status); } /* ================================================================== */ /* A hack for nonunix machines, which lack strcasecmp and strncasecmp */ /* ================================================================== */ int fits_strcasecmp(const char *s1, const char *s2) { char c1, c2; for (;;) { c1 = toupper( *s1 ); c2 = toupper( *s2 ); if (c1 < c2) return(-1); if (c1 > c2) return(1); if (c1 == 0) return(0); s1++; s2++; } } int fits_strncasecmp(const char *s1, const char *s2, size_t n) { char c1, c2; for (; n-- ;) { c1 = toupper( *s1 ); c2 = toupper( *s2 ); if (c1 < c2) return(-1); if (c1 > c2) return(1); if (c1 == 0) return(0); s1++; s2++; } return(0); } cfitsio/fitsio.h0000644000225700000360000034031713246025103013456 0ustar cagordonlhea/* The FITSIO software was written by William Pence at the High Energy */ /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */ /* Goddard Space Flight Center. */ /* Copyright (Unpublished--all rights reserved under the copyright laws of the United States), U.S. Government as represented by the Administrator of the National Aeronautics and Space Administration. No copyright is claimed in the United States under Title 17, U.S. Code. Permission to freely use, copy, modify, and distribute this software and its documentation without fee is hereby granted, provided that this copyright notice and disclaimer of warranty appears in all copies. DISCLAIMER: THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT SHALL NASA BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT , OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER." */ #ifndef _FITSIO_H #define _FITSIO_H #define CFITSIO_VERSION 3.43 #define CFITSIO_MINOR 43 #define CFITSIO_MAJOR 3 #define CFITSIO_SONAME 5 /* the SONAME is incremented in a new release if the binary shared */ /* library (on linux and Mac systems) is not backward compatible */ /* with the previous release of CFITSIO */ /* CFITS_API is defined below for use on Windows systems. */ /* It is used to identify the public functions which should be exported. */ /* This has no effect on non-windows platforms where "WIN32" is not defined */ #if defined (WIN32) #if defined(cfitsio_EXPORTS) #define CFITS_API __declspec(dllexport) #else #define CFITS_API /* __declspec(dllimport) */ #endif /* CFITS_API */ #else /* defined (WIN32) */ #define CFITS_API #endif #include /* the following was provided by Michael Greason (GSFC) to fix a */ /* C/Fortran compatibility problem on an SGI Altix system running */ /* SGI ProPack 4 [this is a Novell SuSE Enterprise 9 derivative] */ /* and using the Intel C++ and Fortran compilers (version 9.1) */ #if defined(__INTEL_COMPILER) && defined(__itanium__) # define mipsFortran 1 # define _MIPS_SZLONG 64 #endif #if defined(linux) || defined(__APPLE__) || defined(__sgi) # include /* apparently needed on debian linux systems */ #endif /* to define off_t */ #include /* apparently needed to define size_t with gcc 2.8.1 */ #include /* needed for LLONG_MAX and INT64_MAX definitions */ /* Define the datatype for variables which store file offset values. */ /* The newer 'off_t' datatype should be used for this purpose, but some */ /* older compilers do not recognize this type, in which case we use 'long' */ /* instead. Note that _OFF_T is defined (or not) in stdio.h depending */ /* on whether _LARGEFILE_SOURCE is defined in sys/feature_tests.h */ /* (at least on Solaris platforms using cc) */ /* Debian systems require: "(defined(linux) && defined(__off_t_defined))" */ /* the mingw-w64 compiler requires: "(defined(__MINGW32__) && defined(_OFF_T_DEFINED))" */ #if defined(_OFF_T) \ || (defined(linux) && defined(__off_t_defined)) \ || (defined(__MINGW32__) && defined(_OFF_T_DEFINED)) \ || defined(_MIPS_SZLONG) || defined(__APPLE__) || defined(_AIX) # define OFF_T off_t #elif defined(__BORLANDC__) || (defined(_MSC_VER) && (_MSC_VER>= 1400)) # define OFF_T long long #else # define OFF_T long #endif /* this block determines if the the string function name is strtol or strtoll, and whether to use %ld or %lld in printf statements */ /* The following 2 cases for that Athon64 were removed on 4 Jan 2006; they appear to be incorrect now that LONGLONG is always typedef'ed to 'long long' || defined(__ia64__) \ || defined(__x86_64__) \ */ #if (defined(__alpha) && ( defined(__unix__) || defined(__NetBSD__) )) \ || defined(__sparcv9) || (defined(__sparc__) && defined(__arch64__)) \ || defined(__powerpc64__) || defined(__64BIT__) \ || (defined(_MIPS_SZLONG) && _MIPS_SZLONG == 64) \ || defined( _MSC_VER)|| defined(__BORLANDC__) # define USE_LL_SUFFIX 0 #else # define USE_LL_SUFFIX 1 #endif /* Determine what 8-byte integer data type is available. 'long long' is now supported by most compilers, but older MS Visual C++ compilers before V7.0 use '__int64' instead. */ #ifndef LONGLONG_TYPE /* this may have been previously defined */ #if defined(_MSC_VER) /* Microsoft Visual C++ */ #if (_MSC_VER < 1300) /* versions earlier than V7.0 do not have 'long long' */ typedef __int64 LONGLONG; #else /* newer versions do support 'long long' */ typedef long long LONGLONG; #endif #elif defined( __BORLANDC__) /* for the Borland 5.5 compiler, in particular */ typedef __int64 LONGLONG; #else typedef long long LONGLONG; #endif #define LONGLONG_TYPE #endif #ifndef LONGLONG_MAX #ifdef LLONG_MAX /* Linux and Solaris definition */ #define LONGLONG_MAX LLONG_MAX #define LONGLONG_MIN LLONG_MIN #elif defined(LONG_LONG_MAX) #define LONGLONG_MAX LONG_LONG_MAX #define LONGLONG_MIN LONG_LONG_MIN #elif defined(__LONG_LONG_MAX__) /* Mac OS X & CYGWIN defintion */ #define LONGLONG_MAX __LONG_LONG_MAX__ #define LONGLONG_MIN (-LONGLONG_MAX -1LL) #elif defined(INT64_MAX) /* windows definition */ #define LONGLONG_MAX INT64_MAX #define LONGLONG_MIN INT64_MIN #elif defined(_I64_MAX) /* windows definition */ #define LONGLONG_MAX _I64_MAX #define LONGLONG_MIN _I64_MIN #elif (defined(__alpha) && ( defined(__unix__) || defined(__NetBSD__) )) \ || defined(__sparcv9) \ || defined(__ia64__) \ || defined(__x86_64__) \ || defined(_SX) \ || defined(__powerpc64__) || defined(__64BIT__) \ || (defined(_MIPS_SZLONG) && _MIPS_SZLONG == 64) /* sizeof(long) = 64 */ #define LONGLONG_MAX 9223372036854775807L /* max 64-bit integer */ #define LONGLONG_MIN (-LONGLONG_MAX -1L) /* min 64-bit integer */ #else /* define a default value, even if it is never used */ #define LONGLONG_MAX 9223372036854775807LL /* max 64-bit integer */ #define LONGLONG_MIN (-LONGLONG_MAX -1LL) /* min 64-bit integer */ #endif #endif /* end of ndef LONGLONG_MAX section */ /* ================================================================= */ /* The following exclusion if __CINT__ is defined is needed for ROOT */ #ifndef __CINT__ #include "longnam.h" #endif #define NIOBUF 40 /* number of IO buffers to create (default = 40) */ /* !! Significantly increasing NIOBUF may degrade performance !! */ #define IOBUFLEN 2880 /* size in bytes of each IO buffer (DONT CHANGE!) */ /* global variables */ #define FLEN_FILENAME 1025 /* max length of a filename */ #define FLEN_KEYWORD 75 /* max length of a keyword (HIERARCH convention) */ #define FLEN_CARD 81 /* length of a FITS header card */ #define FLEN_VALUE 71 /* max length of a keyword value string */ #define FLEN_COMMENT 73 /* max length of a keyword comment string */ #define FLEN_ERRMSG 81 /* max length of a FITSIO error message */ #define FLEN_STATUS 31 /* max length of a FITSIO status text string */ #define TBIT 1 /* codes for FITS table data types */ #define TBYTE 11 #define TSBYTE 12 #define TLOGICAL 14 #define TSTRING 16 #define TUSHORT 20 #define TSHORT 21 #define TUINT 30 #define TINT 31 #define TULONG 40 #define TLONG 41 #define TINT32BIT 41 /* used when returning datatype of a column */ #define TFLOAT 42 #define TLONGLONG 81 #define TDOUBLE 82 #define TCOMPLEX 83 #define TDBLCOMPLEX 163 #define TYP_STRUC_KEY 10 #define TYP_CMPRS_KEY 20 #define TYP_SCAL_KEY 30 #define TYP_NULL_KEY 40 #define TYP_DIM_KEY 50 #define TYP_RANG_KEY 60 #define TYP_UNIT_KEY 70 #define TYP_DISP_KEY 80 #define TYP_HDUID_KEY 90 #define TYP_CKSUM_KEY 100 #define TYP_WCS_KEY 110 #define TYP_REFSYS_KEY 120 #define TYP_COMM_KEY 130 #define TYP_CONT_KEY 140 #define TYP_USER_KEY 150 #define INT32BIT int /* 32-bit integer datatype. Currently this */ /* datatype is an 'int' on all useful platforms */ /* however, it is possible that that are cases */ /* where 'int' is a 2-byte integer, in which case */ /* INT32BIT would need to be defined as 'long'. */ #define BYTE_IMG 8 /* BITPIX code values for FITS image types */ #define SHORT_IMG 16 #define LONG_IMG 32 #define LONGLONG_IMG 64 #define FLOAT_IMG -32 #define DOUBLE_IMG -64 /* The following 2 codes are not true FITS */ /* datatypes; these codes are only used internally */ /* within cfitsio to make it easier for users */ /* to deal with unsigned integers. */ #define SBYTE_IMG 10 #define USHORT_IMG 20 #define ULONG_IMG 40 #define IMAGE_HDU 0 /* Primary Array or IMAGE HDU */ #define ASCII_TBL 1 /* ASCII table HDU */ #define BINARY_TBL 2 /* Binary table HDU */ #define ANY_HDU -1 /* matches any HDU type */ #define READONLY 0 /* options when opening a file */ #define READWRITE 1 /* adopt a hopefully obscure number to use as a null value flag */ /* could be problems if the FITS files contain data with these values */ #define FLOATNULLVALUE -9.11912E-36F #define DOUBLENULLVALUE -9.1191291391491E-36 /* compression algorithm codes */ #define NO_DITHER -1 #define SUBTRACTIVE_DITHER_1 1 #define SUBTRACTIVE_DITHER_2 2 #define MAX_COMPRESS_DIM 6 #define RICE_1 11 #define GZIP_1 21 #define GZIP_2 22 #define PLIO_1 31 #define HCOMPRESS_1 41 #define BZIP2_1 51 /* not publicly supported; only for test purposes */ #define NOCOMPRESS -1 #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #define CASESEN 1 /* do case-sensitive string match */ #define CASEINSEN 0 /* do case-insensitive string match */ #define GT_ID_ALL_URI 0 /* hierarchical grouping parameters */ #define GT_ID_REF 1 #define GT_ID_POS 2 #define GT_ID_ALL 3 #define GT_ID_REF_URI 11 #define GT_ID_POS_URI 12 #define OPT_RM_GPT 0 #define OPT_RM_ENTRY 1 #define OPT_RM_MBR 2 #define OPT_RM_ALL 3 #define OPT_GCP_GPT 0 #define OPT_GCP_MBR 1 #define OPT_GCP_ALL 2 #define OPT_MCP_ADD 0 #define OPT_MCP_NADD 1 #define OPT_MCP_REPL 2 #define OPT_MCP_MOV 3 #define OPT_MRG_COPY 0 #define OPT_MRG_MOV 1 #define OPT_CMT_MBR 1 #define OPT_CMT_MBR_DEL 11 typedef struct /* structure used to store table column information */ { char ttype[70]; /* column name = FITS TTYPEn keyword; */ LONGLONG tbcol; /* offset in row to first byte of each column */ int tdatatype; /* datatype code of each column */ LONGLONG trepeat; /* repeat count of column; number of elements */ double tscale; /* FITS TSCALn linear scaling factor */ double tzero; /* FITS TZEROn linear scaling zero point */ LONGLONG tnull; /* FITS null value for int image or binary table cols */ char strnull[20]; /* FITS null value string for ASCII table columns */ char tform[10]; /* FITS tform keyword value */ long twidth; /* width of each ASCII table column */ }tcolumn; #define VALIDSTRUC 555 /* magic value used to identify if structure is valid */ typedef struct /* structure used to store basic FITS file information */ { int filehandle; /* handle returned by the file open function */ int driver; /* defines which set of I/O drivers should be used */ int open_count; /* number of opened 'fitsfiles' using this structure */ char *filename; /* file name */ int validcode; /* magic value used to verify that structure is valid */ int only_one; /* flag meaning only copy the specified extension */ LONGLONG filesize; /* current size of the physical disk file in bytes */ LONGLONG logfilesize; /* logical size of file, including unflushed buffers */ int lasthdu; /* is this the last HDU in the file? 0 = no, else yes */ LONGLONG bytepos; /* current logical I/O pointer position in file */ LONGLONG io_pos; /* current I/O pointer position in the physical file */ int curbuf; /* number of I/O buffer currently in use */ int curhdu; /* current HDU number; 0 = primary array */ int hdutype; /* 0 = primary array, 1 = ASCII table, 2 = binary table */ int writemode; /* 0 = readonly, 1 = readwrite */ int maxhdu; /* highest numbered HDU known to exist in the file */ int MAXHDU; /* dynamically allocated dimension of headstart array */ LONGLONG *headstart; /* byte offset in file to start of each HDU */ LONGLONG headend; /* byte offest in file to end of the current HDU header */ LONGLONG ENDpos; /* byte offest to where the END keyword was last written */ LONGLONG nextkey; /* byte offset in file to beginning of next keyword */ LONGLONG datastart; /* byte offset in file to start of the current data unit */ int imgdim; /* dimension of image; cached for fast access */ LONGLONG imgnaxis[99]; /* length of each axis; cached for fast access */ int tfield; /* number of fields in the table (primary array has 2 */ int startcol; /* used by ffgcnn to record starting column number */ LONGLONG origrows; /* original number of rows (value of NAXIS2 keyword) */ LONGLONG numrows; /* number of rows in the table (dynamically updated) */ LONGLONG rowlength; /* length of a table row or image size (bytes) */ tcolumn *tableptr; /* pointer to the table structure */ LONGLONG heapstart; /* heap start byte relative to start of data unit */ LONGLONG heapsize; /* size of the heap, in bytes */ /* the following elements are related to compressed images */ /* these record the 'requested' options to be used when the image is compressed */ int request_compress_type; /* requested image compression algorithm */ long request_tilesize[MAX_COMPRESS_DIM]; /* requested tiling size */ float request_quantize_level; /* requested quantize level */ int request_quantize_method ; /* requested quantizing method */ int request_dither_seed; /* starting offset into the array of random dithering */ int request_lossy_int_compress; /* lossy compress integer image as if float image? */ int request_huge_hdu; /* use '1Q' rather then '1P' variable length arrays */ float request_hcomp_scale; /* requested HCOMPRESS scale factor */ int request_hcomp_smooth; /* requested HCOMPRESS smooth parameter */ /* these record the actual options that were used when the image was compressed */ int compress_type; /* type of compression algorithm */ long tilesize[MAX_COMPRESS_DIM]; /* size of compression tiles */ float quantize_level; /* floating point quantization level */ int quantize_method; /* floating point pixel quantization algorithm */ int dither_seed; /* starting offset into the array of random dithering */ /* other compression parameters */ int compressimg; /* 1 if HDU contains a compressed image, else 0 */ char zcmptype[12]; /* compression type string */ int zbitpix; /* FITS data type of image (BITPIX) */ int zndim; /* dimension of image */ long znaxis[MAX_COMPRESS_DIM]; /* length of each axis */ long maxtilelen; /* max number of pixels in each image tile */ long maxelem; /* maximum byte length of tile compressed arrays */ int cn_compressed; /* column number for COMPRESSED_DATA column */ int cn_uncompressed; /* column number for UNCOMPRESSED_DATA column */ int cn_gzip_data; /* column number for GZIP2 lossless compressed data */ int cn_zscale; /* column number for ZSCALE column */ int cn_zzero; /* column number for ZZERO column */ int cn_zblank; /* column number for the ZBLANK column */ double zscale; /* scaling value, if same for all tiles */ double zzero; /* zero pt, if same for all tiles */ double cn_bscale; /* value of the BSCALE keyword in header */ double cn_bzero; /* value of the BZERO keyword (may be reset) */ double cn_actual_bzero; /* actual value of the BZERO keyword */ int zblank; /* value for null pixels, if not a column */ int rice_blocksize; /* first compression parameter: Rice pixels/block */ int rice_bytepix; /* 2nd compression parameter: Rice bytes/pixel */ float hcomp_scale; /* 1st hcompress compression parameter */ int hcomp_smooth; /* 2nd hcompress compression parameter */ int *tilerow; /* row number of the array of uncompressed tiledata */ long *tiledatasize; /* length of the array of tile data in bytes */ int *tiletype; /* datatype of the array of tile (TINT, TSHORT, etc) */ void **tiledata; /* array of uncompressed tile of data, for row *tilerow */ void **tilenullarray; /* array of optional array of null value flags */ int *tileanynull; /* anynulls in the array of tile? */ char *iobuffer; /* pointer to FITS file I/O buffers */ long bufrecnum[NIOBUF]; /* file record number of each of the buffers */ int dirty[NIOBUF]; /* has the corresponding buffer been modified? */ int ageindex[NIOBUF]; /* relative age of each buffer */ } FITSfile; typedef struct /* structure used to store basic HDU information */ { int HDUposition; /* HDU position in file; 0 = first HDU */ FITSfile *Fptr; /* pointer to FITS file structure */ }fitsfile; typedef struct /* structure for the iterator function column information */ { /* elements required as input to fits_iterate_data: */ fitsfile *fptr; /* pointer to the HDU containing the column */ int colnum; /* column number in the table (use name if < 1) */ char colname[70]; /* name (= TTYPEn value) of the column (optional) */ int datatype; /* output datatype (converted if necessary */ int iotype; /* = InputCol, InputOutputCol, or OutputCol */ /* output elements that may be useful for the work function: */ void *array; /* pointer to the array (and the null value) */ long repeat; /* binary table vector repeat value */ long tlmin; /* legal minimum data value */ long tlmax; /* legal maximum data value */ char tunit[70]; /* physical unit string */ char tdisp[70]; /* suggested display format */ } iteratorCol; #define InputCol 0 /* flag for input only iterator column */ #define InputOutputCol 1 /* flag for input and output iterator column */ #define OutputCol 2 /* flag for output only iterator column */ /*============================================================================= * * The following wtbarr typedef is used in the fits_read_wcstab() routine, * which is intended for use with the WCSLIB library written by Mark * Calabretta, http://www.atnf.csiro.au/~mcalabre/index.html * * In order to maintain WCSLIB and CFITSIO as independent libraries it * was not permissible for any CFITSIO library code to include WCSLIB * header files, or vice versa. However, the CFITSIO function * fits_read_wcstab() accepts an array of structs defined by wcs.h within * WCSLIB. The problem then was to define this struct within fitsio.h * without including wcs.h, especially noting that wcs.h will often (but * not always) be included together with fitsio.h in an applications * program that uses fits_read_wcstab(). * * Of the various possibilities, the solution adopted was for WCSLIB to * define "struct wtbarr" while fitsio.h defines "typedef wtbarr", a * untagged struct with identical members. This allows both wcs.h and * fitsio.h to define a wtbarr data type without conflict by virtue of * the fact that structure tags and typedef names share different * namespaces in C. Therefore, declarations within WCSLIB look like * * struct wtbarr *w; * * while within CFITSIO they are simply * * wtbarr *w; * * but as suggested by the commonality of the names, these are really the * same aggregate data type. However, in passing a (struct wtbarr *) to * fits_read_wcstab() a cast to (wtbarr *) is formally required. *===========================================================================*/ #ifndef WCSLIB_GETWCSTAB #define WCSLIB_GETWCSTAB typedef struct { int i; /* Image axis number. */ int m; /* Array axis number for index vectors. */ int kind; /* Array type, 'c' (coord) or 'i' (index). */ char extnam[72]; /* EXTNAME of binary table extension. */ int extver; /* EXTVER of binary table extension. */ int extlev; /* EXTLEV of binary table extension. */ char ttype[72]; /* TTYPEn of column containing the array. */ long row; /* Table row number. */ int ndim; /* Expected array dimensionality. */ int *dimlen; /* Where to write the array axis lengths. */ double **arrayp; /* Where to write the address of the array */ /* allocated to store the array. */ } wtbarr; /* The following exclusion if __CINT__ is defined is needed for ROOT */ #ifndef __CINT__ /* the following 3 lines are needed to support C++ compilers */ #ifdef __cplusplus extern "C" { #endif #endif int CFITS_API fits_read_wcstab(fitsfile *fptr, int nwtb, wtbarr *wtb, int *status); /* The following exclusion if __CINT__ is defined is needed for ROOT */ #ifndef __CINT__ #ifdef __cplusplus } #endif #endif #endif /* WCSLIB_GETWCSTAB */ /* error status codes */ #define CREATE_DISK_FILE -106 /* create disk file, without extended filename syntax */ #define OPEN_DISK_FILE -105 /* open disk file, without extended filename syntax */ #define SKIP_TABLE -104 /* move to 1st image when opening file */ #define SKIP_IMAGE -103 /* move to 1st table when opening file */ #define SKIP_NULL_PRIMARY -102 /* skip null primary array when opening file */ #define USE_MEM_BUFF -101 /* use memory buffer when opening file */ #define OVERFLOW_ERR -11 /* overflow during datatype conversion */ #define PREPEND_PRIMARY -9 /* used in ffiimg to insert new primary array */ #define SAME_FILE 101 /* input and output files are the same */ #define TOO_MANY_FILES 103 /* tried to open too many FITS files */ #define FILE_NOT_OPENED 104 /* could not open the named file */ #define FILE_NOT_CREATED 105 /* could not create the named file */ #define WRITE_ERROR 106 /* error writing to FITS file */ #define END_OF_FILE 107 /* tried to move past end of file */ #define READ_ERROR 108 /* error reading from FITS file */ #define FILE_NOT_CLOSED 110 /* could not close the file */ #define ARRAY_TOO_BIG 111 /* array dimensions exceed internal limit */ #define READONLY_FILE 112 /* Cannot write to readonly file */ #define MEMORY_ALLOCATION 113 /* Could not allocate memory */ #define BAD_FILEPTR 114 /* invalid fitsfile pointer */ #define NULL_INPUT_PTR 115 /* NULL input pointer to routine */ #define SEEK_ERROR 116 /* error seeking position in file */ #define BAD_URL_PREFIX 121 /* invalid URL prefix on file name */ #define TOO_MANY_DRIVERS 122 /* tried to register too many IO drivers */ #define DRIVER_INIT_FAILED 123 /* driver initialization failed */ #define NO_MATCHING_DRIVER 124 /* matching driver is not registered */ #define URL_PARSE_ERROR 125 /* failed to parse input file URL */ #define RANGE_PARSE_ERROR 126 /* failed to parse input file URL */ #define SHARED_ERRBASE (150) #define SHARED_BADARG (SHARED_ERRBASE + 1) #define SHARED_NULPTR (SHARED_ERRBASE + 2) #define SHARED_TABFULL (SHARED_ERRBASE + 3) #define SHARED_NOTINIT (SHARED_ERRBASE + 4) #define SHARED_IPCERR (SHARED_ERRBASE + 5) #define SHARED_NOMEM (SHARED_ERRBASE + 6) #define SHARED_AGAIN (SHARED_ERRBASE + 7) #define SHARED_NOFILE (SHARED_ERRBASE + 8) #define SHARED_NORESIZE (SHARED_ERRBASE + 9) #define HEADER_NOT_EMPTY 201 /* header already contains keywords */ #define KEY_NO_EXIST 202 /* keyword not found in header */ #define KEY_OUT_BOUNDS 203 /* keyword record number is out of bounds */ #define VALUE_UNDEFINED 204 /* keyword value field is blank */ #define NO_QUOTE 205 /* string is missing the closing quote */ #define BAD_INDEX_KEY 206 /* illegal indexed keyword name */ #define BAD_KEYCHAR 207 /* illegal character in keyword name or card */ #define BAD_ORDER 208 /* required keywords out of order */ #define NOT_POS_INT 209 /* keyword value is not a positive integer */ #define NO_END 210 /* couldn't find END keyword */ #define BAD_BITPIX 211 /* illegal BITPIX keyword value*/ #define BAD_NAXIS 212 /* illegal NAXIS keyword value */ #define BAD_NAXES 213 /* illegal NAXISn keyword value */ #define BAD_PCOUNT 214 /* illegal PCOUNT keyword value */ #define BAD_GCOUNT 215 /* illegal GCOUNT keyword value */ #define BAD_TFIELDS 216 /* illegal TFIELDS keyword value */ #define NEG_WIDTH 217 /* negative table row size */ #define NEG_ROWS 218 /* negative number of rows in table */ #define COL_NOT_FOUND 219 /* column with this name not found in table */ #define BAD_SIMPLE 220 /* illegal value of SIMPLE keyword */ #define NO_SIMPLE 221 /* Primary array doesn't start with SIMPLE */ #define NO_BITPIX 222 /* Second keyword not BITPIX */ #define NO_NAXIS 223 /* Third keyword not NAXIS */ #define NO_NAXES 224 /* Couldn't find all the NAXISn keywords */ #define NO_XTENSION 225 /* HDU doesn't start with XTENSION keyword */ #define NOT_ATABLE 226 /* the CHDU is not an ASCII table extension */ #define NOT_BTABLE 227 /* the CHDU is not a binary table extension */ #define NO_PCOUNT 228 /* couldn't find PCOUNT keyword */ #define NO_GCOUNT 229 /* couldn't find GCOUNT keyword */ #define NO_TFIELDS 230 /* couldn't find TFIELDS keyword */ #define NO_TBCOL 231 /* couldn't find TBCOLn keyword */ #define NO_TFORM 232 /* couldn't find TFORMn keyword */ #define NOT_IMAGE 233 /* the CHDU is not an IMAGE extension */ #define BAD_TBCOL 234 /* TBCOLn keyword value < 0 or > rowlength */ #define NOT_TABLE 235 /* the CHDU is not a table */ #define COL_TOO_WIDE 236 /* column is too wide to fit in table */ #define COL_NOT_UNIQUE 237 /* more than 1 column name matches template */ #define BAD_ROW_WIDTH 241 /* sum of column widths not = NAXIS1 */ #define UNKNOWN_EXT 251 /* unrecognizable FITS extension type */ #define UNKNOWN_REC 252 /* unrecognizable FITS record */ #define END_JUNK 253 /* END keyword is not blank */ #define BAD_HEADER_FILL 254 /* Header fill area not blank */ #define BAD_DATA_FILL 255 /* Data fill area not blank or zero */ #define BAD_TFORM 261 /* illegal TFORM format code */ #define BAD_TFORM_DTYPE 262 /* unrecognizable TFORM datatype code */ #define BAD_TDIM 263 /* illegal TDIMn keyword value */ #define BAD_HEAP_PTR 264 /* invalid BINTABLE heap address */ #define BAD_HDU_NUM 301 /* HDU number < 1 or > MAXHDU */ #define BAD_COL_NUM 302 /* column number < 1 or > tfields */ #define NEG_FILE_POS 304 /* tried to move before beginning of file */ #define NEG_BYTES 306 /* tried to read or write negative bytes */ #define BAD_ROW_NUM 307 /* illegal starting row number in table */ #define BAD_ELEM_NUM 308 /* illegal starting element number in vector */ #define NOT_ASCII_COL 309 /* this is not an ASCII string column */ #define NOT_LOGICAL_COL 310 /* this is not a logical datatype column */ #define BAD_ATABLE_FORMAT 311 /* ASCII table column has wrong format */ #define BAD_BTABLE_FORMAT 312 /* Binary table column has wrong format */ #define NO_NULL 314 /* null value has not been defined */ #define NOT_VARI_LEN 317 /* this is not a variable length column */ #define BAD_DIMEN 320 /* illegal number of dimensions in array */ #define BAD_PIX_NUM 321 /* first pixel number greater than last pixel */ #define ZERO_SCALE 322 /* illegal BSCALE or TSCALn keyword = 0 */ #define NEG_AXIS 323 /* illegal axis length < 1 */ #define NOT_GROUP_TABLE 340 #define HDU_ALREADY_MEMBER 341 #define MEMBER_NOT_FOUND 342 #define GROUP_NOT_FOUND 343 #define BAD_GROUP_ID 344 #define TOO_MANY_HDUS_TRACKED 345 #define HDU_ALREADY_TRACKED 346 #define BAD_OPTION 347 #define IDENTICAL_POINTERS 348 #define BAD_GROUP_ATTACH 349 #define BAD_GROUP_DETACH 350 #define BAD_I2C 401 /* bad int to formatted string conversion */ #define BAD_F2C 402 /* bad float to formatted string conversion */ #define BAD_INTKEY 403 /* can't interprete keyword value as integer */ #define BAD_LOGICALKEY 404 /* can't interprete keyword value as logical */ #define BAD_FLOATKEY 405 /* can't interprete keyword value as float */ #define BAD_DOUBLEKEY 406 /* can't interprete keyword value as double */ #define BAD_C2I 407 /* bad formatted string to int conversion */ #define BAD_C2F 408 /* bad formatted string to float conversion */ #define BAD_C2D 409 /* bad formatted string to double conversion */ #define BAD_DATATYPE 410 /* bad keyword datatype code */ #define BAD_DECIM 411 /* bad number of decimal places specified */ #define NUM_OVERFLOW 412 /* overflow during datatype conversion */ # define DATA_COMPRESSION_ERR 413 /* error in imcompress routines */ # define DATA_DECOMPRESSION_ERR 414 /* error in imcompress routines */ # define NO_COMPRESSED_TILE 415 /* compressed tile doesn't exist */ #define BAD_DATE 420 /* error in date or time conversion */ #define PARSE_SYNTAX_ERR 431 /* syntax error in parser expression */ #define PARSE_BAD_TYPE 432 /* expression did not evaluate to desired type */ #define PARSE_LRG_VECTOR 433 /* vector result too large to return in array */ #define PARSE_NO_OUTPUT 434 /* data parser failed not sent an out column */ #define PARSE_BAD_COL 435 /* bad data encounter while parsing column */ #define PARSE_BAD_OUTPUT 436 /* Output file not of proper type */ #define ANGLE_TOO_BIG 501 /* celestial angle too large for projection */ #define BAD_WCS_VAL 502 /* bad celestial coordinate or pixel value */ #define WCS_ERROR 503 /* error in celestial coordinate calculation */ #define BAD_WCS_PROJ 504 /* unsupported type of celestial projection */ #define NO_WCS_KEY 505 /* celestial coordinate keywords not found */ #define APPROX_WCS_KEY 506 /* approximate WCS keywords were calculated */ #define NO_CLOSE_ERROR 999 /* special value used internally to switch off */ /* the error message from ffclos and ffchdu */ /*------- following error codes are used in the grparser.c file -----------*/ #define NGP_ERRBASE (360) /* base chosen so not to interfere with CFITSIO */ #define NGP_OK (0) #define NGP_NO_MEMORY (NGP_ERRBASE + 0) /* malloc failed */ #define NGP_READ_ERR (NGP_ERRBASE + 1) /* read error from file */ #define NGP_NUL_PTR (NGP_ERRBASE + 2) /* null pointer passed as argument */ #define NGP_EMPTY_CURLINE (NGP_ERRBASE + 3) /* line read seems to be empty */ #define NGP_UNREAD_QUEUE_FULL (NGP_ERRBASE + 4) /* cannot unread more then 1 line (or single line twice) */ #define NGP_INC_NESTING (NGP_ERRBASE + 5) /* too deep include file nesting (inf. loop ?) */ #define NGP_ERR_FOPEN (NGP_ERRBASE + 6) /* fopen() failed, cannot open file */ #define NGP_EOF (NGP_ERRBASE + 7) /* end of file encountered */ #define NGP_BAD_ARG (NGP_ERRBASE + 8) /* bad arguments passed */ #define NGP_TOKEN_NOT_EXPECT (NGP_ERRBASE + 9) /* token not expected here */ /* The following exclusion if __CINT__ is defined is needed for ROOT */ #ifndef __CINT__ /* the following 3 lines are needed to support C++ compilers */ #ifdef __cplusplus extern "C" { #endif #endif int CFITS2Unit( fitsfile *fptr ); CFITS_API fitsfile* CUnit2FITS(int unit); /*---------------- FITS file URL parsing routines -------------*/ int CFITS_API fits_get_token (char **ptr, char *delimiter, char *token, int *isanumber); int CFITS_API fits_get_token2(char **ptr, char *delimiter, char **token, int *isanumber, int *status); char CFITS_API *fits_split_names(char *list); int CFITS_API ffiurl( char *url, char *urltype, char *infile, char *outfile, char *extspec, char *rowfilter, char *binspec, char *colspec, int *status); int CFITS_API ffifile (char *url, char *urltype, char *infile, char *outfile, char *extspec, char *rowfilter, char *binspec, char *colspec, char *pixfilter, int *status); int CFITS_API ffifile2 (char *url, char *urltype, char *infile, char *outfile, char *extspec, char *rowfilter, char *binspec, char *colspec, char *pixfilter, char *compspec, int *status); int CFITS_API ffrtnm(char *url, char *rootname, int *status); int CFITS_API ffexist(const char *infile, int *exists, int *status); int CFITS_API ffexts(char *extspec, int *extnum, char *extname, int *extvers, int *hdutype, char *colname, char *rowexpress, int *status); int CFITS_API ffextn(char *url, int *extension_num, int *status); int CFITS_API ffurlt(fitsfile *fptr, char *urlType, int *status); int CFITS_API ffbins(char *binspec, int *imagetype, int *haxis, char colname[4][FLEN_VALUE], double *minin, double *maxin, double *binsizein, char minname[4][FLEN_VALUE], char maxname[4][FLEN_VALUE], char binname[4][FLEN_VALUE], double *weight, char *wtname, int *recip, int *status); int CFITS_API ffbinr(char **binspec, char *colname, double *minin, double *maxin, double *binsizein, char *minname, char *maxname, char *binname, int *status); int CFITS_API fits_copy_cell2image(fitsfile *fptr, fitsfile *newptr, char *colname, long rownum, int *status); int CFITS_API fits_copy_image2cell(fitsfile *fptr, fitsfile *newptr, char *colname, long rownum, int copykeyflag, int *status); int CFITS_API fits_copy_pixlist2image(fitsfile *infptr, fitsfile *outfptr, int firstkey, /* I - first HDU record number to start with */ int naxis, int *colnum, int *status); int CFITS_API ffimport_file( char *filename, char **contents, int *status ); int CFITS_API ffrwrg( char *rowlist, LONGLONG maxrows, int maxranges, int *numranges, long *minrow, long *maxrow, int *status); int CFITS_API ffrwrgll( char *rowlist, LONGLONG maxrows, int maxranges, int *numranges, LONGLONG *minrow, LONGLONG *maxrow, int *status); /*---------------- FITS file I/O routines -------------*/ int CFITS_API fits_init_cfitsio(void); int CFITS_API ffomem(fitsfile **fptr, const char *name, int mode, void **buffptr, size_t *buffsize, size_t deltasize, void *(*mem_realloc)(void *p, size_t newsize), int *status); int CFITS_API ffopen(fitsfile **fptr, const char *filename, int iomode, int *status); int CFITS_API ffopentest(int soname, fitsfile **fptr, const char *filename, int iomode, int *status); int CFITS_API ffdopn(fitsfile **fptr, const char *filename, int iomode, int *status); int CFITS_API ffeopn(fitsfile **fptr, const char *filename, int iomode, char *extlist, int *hdutype, int *status); int CFITS_API fftopn(fitsfile **fptr, const char *filename, int iomode, int *status); int CFITS_API ffiopn(fitsfile **fptr, const char *filename, int iomode, int *status); int CFITS_API ffdkopn(fitsfile **fptr, const char *filename, int iomode, int *status); int CFITS_API ffreopen(fitsfile *openfptr, fitsfile **newfptr, int *status); int CFITS_API ffinit( fitsfile **fptr, const char *filename, int *status); int CFITS_API ffdkinit(fitsfile **fptr, const char *filename, int *status); int CFITS_API ffimem(fitsfile **fptr, void **buffptr, size_t *buffsize, size_t deltasize, void *(*mem_realloc)(void *p, size_t newsize), int *status); int CFITS_API fftplt(fitsfile **fptr, const char *filename, const char *tempname, int *status); int CFITS_API ffflus(fitsfile *fptr, int *status); int CFITS_API ffflsh(fitsfile *fptr, int clearbuf, int *status); int CFITS_API ffclos(fitsfile *fptr, int *status); int CFITS_API ffdelt(fitsfile *fptr, int *status); int CFITS_API ffflnm(fitsfile *fptr, char *filename, int *status); int CFITS_API ffflmd(fitsfile *fptr, int *filemode, int *status); int CFITS_API fits_delete_iraf_file(const char *filename, int *status); /*---------------- utility routines -------------*/ float CFITS_API ffvers(float *version); void CFITS_API ffupch(char *string); void CFITS_API ffgerr(int status, char *errtext); void CFITS_API ffpmsg(const char *err_message); void CFITS_API ffpmrk(void); int CFITS_API ffgmsg(char *err_message); void CFITS_API ffcmsg(void); void CFITS_API ffcmrk(void); void CFITS_API ffrprt(FILE *stream, int status); void CFITS_API ffcmps(char *templt, char *colname, int casesen, int *match, int *exact); int CFITS_API fftkey(const char *keyword, int *status); int CFITS_API fftrec(char *card, int *status); int CFITS_API ffnchk(fitsfile *fptr, int *status); int CFITS_API ffkeyn(const char *keyroot, int value, char *keyname, int *status); int CFITS_API ffnkey(int value, const char *keyroot, char *keyname, int *status); int CFITS_API ffgkcl(char *card); int CFITS_API ffdtyp(const char *cval, char *dtype, int *status); int CFITS_API ffinttyp(char *cval, int *datatype, int *negative, int *status); int CFITS_API ffpsvc(char *card, char *value, char *comm, int *status); int CFITS_API ffgknm(char *card, char *name, int *length, int *status); int CFITS_API ffgthd(char *tmplt, char *card, int *hdtype, int *status); int CFITS_API ffmkky(const char *keyname, char *keyval, const char *comm, char *card, int *status); int CFITS_API fits_translate_keyword(char *inrec, char *outrec, char *patterns[][2], int npat, int n_value, int n_offset, int n_range, int *pat_num, int *i, int *j, int *m, int *n, int *status); int CFITS_API fits_translate_keywords(fitsfile *infptr, fitsfile *outfptr, int firstkey, char *patterns[][2], int npat, int n_value, int n_offset, int n_range, int *status); int CFITS_API ffasfm(char *tform, int *datacode, long *width, int *decim, int *status); int CFITS_API ffbnfm(char *tform, int *datacode, long *repeat, long *width, int *status); int CFITS_API ffbnfmll(char *tform, int *datacode, LONGLONG *repeat, long *width, int *status); int CFITS_API ffgabc(int tfields, char **tform, int space, long *rowlen, long *tbcol, int *status); int CFITS_API fits_get_section_range(char **ptr,long *secmin,long *secmax,long *incre, int *status); /* ffmbyt should not normally be used in application programs, but it is defined here as a publicly available routine because there are a few rare cases where it is needed */ int CFITS_API ffmbyt(fitsfile *fptr, LONGLONG bytpos, int ignore_err, int *status); /*----------------- write single keywords --------------*/ int CFITS_API ffpky(fitsfile *fptr, int datatype, const char *keyname, void *value, const char *comm, int *status); int CFITS_API ffprec(fitsfile *fptr, const char *card, int *status); int CFITS_API ffpcom(fitsfile *fptr, const char *comm, int *status); int CFITS_API ffpunt(fitsfile *fptr, const char *keyname, const char *unit, int *status); int CFITS_API ffphis(fitsfile *fptr, const char *history, int *status); int CFITS_API ffpdat(fitsfile *fptr, int *status); int CFITS_API ffverifydate(int year, int month, int day, int *status); int CFITS_API ffgstm(char *timestr, int *timeref, int *status); int CFITS_API ffgsdt(int *day, int *month, int *year, int *status); int CFITS_API ffdt2s(int year, int month, int day, char *datestr, int *status); int CFITS_API fftm2s(int year, int month, int day, int hour, int minute, double second, int decimals, char *datestr, int *status); int CFITS_API ffs2dt(char *datestr, int *year, int *month, int *day, int *status); int CFITS_API ffs2tm(char *datestr, int *year, int *month, int *day, int *hour, int *minute, double *second, int *status); int CFITS_API ffpkyu(fitsfile *fptr, const char *keyname, const char *comm, int *status); int CFITS_API ffpkys(fitsfile *fptr, const char *keyname, const char *value, const char *comm,int *status); int CFITS_API ffpkls(fitsfile *fptr, const char *keyname, const char *value, const char *comm,int *status); int CFITS_API ffplsw(fitsfile *fptr, int *status); int CFITS_API ffpkyl(fitsfile *fptr, const char *keyname, int value, const char *comm, int *status); int CFITS_API ffpkyj(fitsfile *fptr, const char *keyname, LONGLONG value, const char *comm, int *status); int CFITS_API ffpkyf(fitsfile *fptr, const char *keyname, float value, int decim, const char *comm, int *status); int CFITS_API ffpkye(fitsfile *fptr, const char *keyname, float value, int decim, const char *comm, int *status); int CFITS_API ffpkyg(fitsfile *fptr, const char *keyname, double value, int decim, const char *comm, int *status); int CFITS_API ffpkyd(fitsfile *fptr, const char *keyname, double value, int decim, const char *comm, int *status); int CFITS_API ffpkyc(fitsfile *fptr, const char *keyname, float *value, int decim, const char *comm, int *status); int CFITS_API ffpkym(fitsfile *fptr, const char *keyname, double *value, int decim, const char *comm, int *status); int CFITS_API ffpkfc(fitsfile *fptr, const char *keyname, float *value, int decim, const char *comm, int *status); int CFITS_API ffpkfm(fitsfile *fptr, const char *keyname, double *value, int decim, const char *comm, int *status); int CFITS_API ffpkyt(fitsfile *fptr, const char *keyname, long intval, double frac, const char *comm, int *status); int CFITS_API ffptdm( fitsfile *fptr, int colnum, int naxis, long naxes[], int *status); int CFITS_API ffptdmll( fitsfile *fptr, int colnum, int naxis, LONGLONG naxes[], int *status); /*----------------- write array of keywords --------------*/ int CFITS_API ffpkns(fitsfile *fptr, const char *keyroot, int nstart, int nkey, char *value[], char *comm[], int *status); int CFITS_API ffpknl(fitsfile *fptr, const char *keyroot, int nstart, int nkey, int *value, char *comm[], int *status); int CFITS_API ffpknj(fitsfile *fptr, const char *keyroot, int nstart, int nkey, long *value, char *comm[], int *status); int CFITS_API ffpknjj(fitsfile *fptr, const char *keyroot, int nstart, int nkey, LONGLONG *value, char *comm[], int *status); int CFITS_API ffpknf(fitsfile *fptr, const char *keyroot, int nstart, int nkey, float *value, int decim, char *comm[], int *status); int CFITS_API ffpkne(fitsfile *fptr, const char *keyroot, int nstart, int nkey, float *value, int decim, char *comm[], int *status); int CFITS_API ffpkng(fitsfile *fptr, const char *keyroot, int nstart, int nkey, double *value, int decim, char *comm[], int *status); int CFITS_API ffpknd(fitsfile *fptr, const char *keyroot, int nstart, int nkey, double *value, int decim, char *comm[], int *status); int CFITS_API ffcpky(fitsfile *infptr,fitsfile *outfptr,int incol,int outcol, char *rootname, int *status); /*----------------- write required header keywords --------------*/ int CFITS_API ffphps( fitsfile *fptr, int bitpix, int naxis, long naxes[], int *status); int CFITS_API ffphpsll( fitsfile *fptr, int bitpix, int naxis, LONGLONG naxes[], int *status); int CFITS_API ffphpr( fitsfile *fptr, int simple, int bitpix, int naxis, long naxes[], LONGLONG pcount, LONGLONG gcount, int extend, int *status); int CFITS_API ffphprll( fitsfile *fptr, int simple, int bitpix, int naxis, LONGLONG naxes[], LONGLONG pcount, LONGLONG gcount, int extend, int *status); int CFITS_API ffphtb(fitsfile *fptr, LONGLONG naxis1, LONGLONG naxis2, int tfields, char **ttype, long *tbcol, char **tform, char **tunit, const char *extname, int *status); int CFITS_API ffphbn(fitsfile *fptr, LONGLONG naxis2, int tfields, char **ttype, char **tform, char **tunit, const char *extname, LONGLONG pcount, int *status); int CFITS_API ffphext( fitsfile *fptr, const char *xtension, int bitpix, int naxis, long naxes[], LONGLONG pcount, LONGLONG gcount, int *status); /*----------------- write template keywords --------------*/ int CFITS_API ffpktp(fitsfile *fptr, const char *filename, int *status); /*------------------ get header information --------------*/ int CFITS_API ffghsp(fitsfile *fptr, int *nexist, int *nmore, int *status); int CFITS_API ffghps(fitsfile *fptr, int *nexist, int *position, int *status); /*------------------ move position in header -------------*/ int CFITS_API ffmaky(fitsfile *fptr, int nrec, int *status); int CFITS_API ffmrky(fitsfile *fptr, int nrec, int *status); /*------------------ read single keywords -----------------*/ int CFITS_API ffgnxk(fitsfile *fptr, char **inclist, int ninc, char **exclist, int nexc, char *card, int *status); int CFITS_API ffgrec(fitsfile *fptr, int nrec, char *card, int *status); int CFITS_API ffgcrd(fitsfile *fptr, const char *keyname, char *card, int *status); int CFITS_API ffgstr(fitsfile *fptr, const char *string, char *card, int *status); int CFITS_API ffgunt(fitsfile *fptr, const char *keyname, char *unit, int *status); int CFITS_API ffgkyn(fitsfile *fptr, int nkey, char *keyname, char *keyval, char *comm, int *status); int CFITS_API ffgkey(fitsfile *fptr, const char *keyname, char *keyval, char *comm, int *status); int CFITS_API ffgky( fitsfile *fptr, int datatype, const char *keyname, void *value, char *comm, int *status); int CFITS_API ffgkys(fitsfile *fptr, const char *keyname, char *value, char *comm, int *status); int CFITS_API ffgksl(fitsfile *fptr, const char *keyname, int *length, int *status); int CFITS_API ffgkls(fitsfile *fptr, const char *keyname, char **value, char *comm, int *status); int CFITS_API ffgsky(fitsfile *fptr, const char *keyname, int firstchar, int maxchar, char *value, int *valuelen, char *comm, int *status); int CFITS_API fffree(void *value, int *status); int CFITS_API fffkls(char *value, int *status); int CFITS_API ffgkyl(fitsfile *fptr, const char *keyname, int *value, char *comm, int *status); int CFITS_API ffgkyj(fitsfile *fptr, const char *keyname, long *value, char *comm, int *status); int CFITS_API ffgkyjj(fitsfile *fptr, const char *keyname, LONGLONG *value, char *comm, int *status); int CFITS_API ffgkye(fitsfile *fptr, const char *keyname, float *value, char *comm,int *status); int CFITS_API ffgkyd(fitsfile *fptr, const char *keyname, double *value,char *comm,int *status); int CFITS_API ffgkyc(fitsfile *fptr, const char *keyname, float *value, char *comm,int *status); int CFITS_API ffgkym(fitsfile *fptr, const char *keyname, double *value,char *comm,int *status); int CFITS_API ffgkyt(fitsfile *fptr, const char *keyname, long *ivalue, double *dvalue, char *comm, int *status); int CFITS_API ffgtdm(fitsfile *fptr, int colnum, int maxdim, int *naxis, long naxes[], int *status); int CFITS_API ffgtdmll(fitsfile *fptr, int colnum, int maxdim, int *naxis, LONGLONG naxes[], int *status); int CFITS_API ffdtdm(fitsfile *fptr, char *tdimstr, int colnum, int maxdim, int *naxis, long naxes[], int *status); int CFITS_API ffdtdmll(fitsfile *fptr, char *tdimstr, int colnum, int maxdim, int *naxis, LONGLONG naxes[], int *status); /*------------------ read array of keywords -----------------*/ int CFITS_API ffgkns(fitsfile *fptr, const char *keyname, int nstart, int nmax, char *value[], int *nfound, int *status); int CFITS_API ffgknl(fitsfile *fptr, const char *keyname, int nstart, int nmax, int *value, int *nfound, int *status); int CFITS_API ffgknj(fitsfile *fptr, const char *keyname, int nstart, int nmax, long *value, int *nfound, int *status); int CFITS_API ffgknjj(fitsfile *fptr, const char *keyname, int nstart, int nmax, LONGLONG *value, int *nfound, int *status); int CFITS_API ffgkne(fitsfile *fptr, const char *keyname, int nstart, int nmax, float *value, int *nfound, int *status); int CFITS_API ffgknd(fitsfile *fptr, const char *keyname, int nstart, int nmax, double *value, int *nfound, int *status); int CFITS_API ffh2st(fitsfile *fptr, char **header, int *status); int CFITS_API ffhdr2str( fitsfile *fptr, int exclude_comm, char **exclist, int nexc, char **header, int *nkeys, int *status); int CFITS_API ffcnvthdr2str( fitsfile *fptr, int exclude_comm, char **exclist, int nexc, char **header, int *nkeys, int *status); /*----------------- read required header keywords --------------*/ int CFITS_API ffghpr(fitsfile *fptr, int maxdim, int *simple, int *bitpix, int *naxis, long naxes[], long *pcount, long *gcount, int *extend, int *status); int CFITS_API ffghprll(fitsfile *fptr, int maxdim, int *simple, int *bitpix, int *naxis, LONGLONG naxes[], long *pcount, long *gcount, int *extend, int *status); int CFITS_API ffghtb(fitsfile *fptr,int maxfield, long *naxis1, long *naxis2, int *tfields, char **ttype, long *tbcol, char **tform, char **tunit, char *extname, int *status); int CFITS_API ffghtbll(fitsfile *fptr,int maxfield, LONGLONG *naxis1, LONGLONG *naxis2, int *tfields, char **ttype, LONGLONG *tbcol, char **tform, char **tunit, char *extname, int *status); int CFITS_API ffghbn(fitsfile *fptr, int maxfield, long *naxis2, int *tfields, char **ttype, char **tform, char **tunit, char *extname, long *pcount, int *status); int CFITS_API ffghbnll(fitsfile *fptr, int maxfield, LONGLONG *naxis2, int *tfields, char **ttype, char **tform, char **tunit, char *extname, LONGLONG *pcount, int *status); /*--------------------- update keywords ---------------*/ int CFITS_API ffuky(fitsfile *fptr, int datatype, const char *keyname, void *value, const char *comm, int *status); int CFITS_API ffucrd(fitsfile *fptr, const char *keyname, const char *card, int *status); int CFITS_API ffukyu(fitsfile *fptr, const char *keyname, const char *comm, int *status); int CFITS_API ffukys(fitsfile *fptr, const char *keyname, const char *value, const char *comm, int *status); int CFITS_API ffukls(fitsfile *fptr, const char *keyname, const char *value, const char *comm, int *status); int CFITS_API ffukyl(fitsfile *fptr, const char *keyname, int value, const char *comm, int *status); int CFITS_API ffukyj(fitsfile *fptr, const char *keyname, LONGLONG value, const char *comm, int *status); int CFITS_API ffukyf(fitsfile *fptr, const char *keyname, float value, int decim, const char *comm, int *status); int CFITS_API ffukye(fitsfile *fptr, const char *keyname, float value, int decim, const char *comm, int *status); int CFITS_API ffukyg(fitsfile *fptr, const char *keyname, double value, int decim, const char *comm, int *status); int CFITS_API ffukyd(fitsfile *fptr, const char *keyname, double value, int decim, const char *comm, int *status); int CFITS_API ffukyc(fitsfile *fptr, const char *keyname, float *value, int decim, const char *comm, int *status); int CFITS_API ffukym(fitsfile *fptr, const char *keyname, double *value, int decim, const char *comm, int *status); int CFITS_API ffukfc(fitsfile *fptr, const char *keyname, float *value, int decim, const char *comm, int *status); int CFITS_API ffukfm(fitsfile *fptr, const char *keyname, double *value, int decim, const char *comm, int *status); /*--------------------- modify keywords ---------------*/ int CFITS_API ffmrec(fitsfile *fptr, int nkey, const char *card, int *status); int CFITS_API ffmcrd(fitsfile *fptr, const char *keyname, const char *card, int *status); int CFITS_API ffmnam(fitsfile *fptr, const char *oldname, const char *newname, int *status); int CFITS_API ffmcom(fitsfile *fptr, const char *keyname, const char *comm, int *status); int CFITS_API ffmkyu(fitsfile *fptr, const char *keyname, const char *comm, int *status); int CFITS_API ffmkys(fitsfile *fptr, const char *keyname, const char *value, const char *comm,int *status); int CFITS_API ffmkls(fitsfile *fptr, const char *keyname, const char *value, const char *comm,int *status); int CFITS_API ffmkyl(fitsfile *fptr, const char *keyname, int value, const char *comm, int *status); int CFITS_API ffmkyj(fitsfile *fptr, const char *keyname, LONGLONG value, const char *comm, int *status); int CFITS_API ffmkyf(fitsfile *fptr, const char *keyname, float value, int decim, const char *comm, int *status); int CFITS_API ffmkye(fitsfile *fptr, const char *keyname, float value, int decim, const char *comm, int *status); int CFITS_API ffmkyg(fitsfile *fptr, const char *keyname, double value, int decim, const char *comm, int *status); int CFITS_API ffmkyd(fitsfile *fptr, const char *keyname, double value, int decim, const char *comm, int *status); int CFITS_API ffmkyc(fitsfile *fptr, const char *keyname, float *value, int decim, const char *comm, int *status); int CFITS_API ffmkym(fitsfile *fptr, const char *keyname, double *value, int decim, const char *comm, int *status); int CFITS_API ffmkfc(fitsfile *fptr, const char *keyname, float *value, int decim, const char *comm, int *status); int CFITS_API ffmkfm(fitsfile *fptr, const char *keyname, double *value, int decim, const char *comm, int *status); /*--------------------- insert keywords ---------------*/ int CFITS_API ffirec(fitsfile *fptr, int nkey, const char *card, int *status); int CFITS_API ffikey(fitsfile *fptr, const char *card, int *status); int CFITS_API ffikyu(fitsfile *fptr, const char *keyname, const char *comm, int *status); int CFITS_API ffikys(fitsfile *fptr, const char *keyname, const char *value, const char *comm,int *status); int CFITS_API ffikls(fitsfile *fptr, const char *keyname, const char *value, const char *comm,int *status); int CFITS_API ffikyl(fitsfile *fptr, const char *keyname, int value, const char *comm, int *status); int CFITS_API ffikyj(fitsfile *fptr, const char *keyname, LONGLONG value, const char *comm, int *status); int CFITS_API ffikyf(fitsfile *fptr, const char *keyname, float value, int decim, const char *comm, int *status); int CFITS_API ffikye(fitsfile *fptr, const char *keyname, float value, int decim, const char *comm, int *status); int CFITS_API ffikyg(fitsfile *fptr, const char *keyname, double value, int decim, const char *comm, int *status); int CFITS_API ffikyd(fitsfile *fptr, const char *keyname, double value, int decim, const char *comm, int *status); int CFITS_API ffikyc(fitsfile *fptr, const char *keyname, float *value, int decim, const char *comm, int *status); int CFITS_API ffikym(fitsfile *fptr, const char *keyname, double *value, int decim, const char *comm, int *status); int CFITS_API ffikfc(fitsfile *fptr, const char *keyname, float *value, int decim, const char *comm, int *status); int CFITS_API ffikfm(fitsfile *fptr, const char *keyname, double *value, int decim, const char *comm, int *status); /*--------------------- delete keywords ---------------*/ int CFITS_API ffdkey(fitsfile *fptr, const char *keyname, int *status); int CFITS_API ffdstr(fitsfile *fptr, const char *string, int *status); int CFITS_API ffdrec(fitsfile *fptr, int keypos, int *status); /*--------------------- get HDU information -------------*/ int CFITS_API ffghdn(fitsfile *fptr, int *chdunum); int CFITS_API ffghdt(fitsfile *fptr, int *exttype, int *status); int CFITS_API ffghad(fitsfile *fptr, long *headstart, long *datastart, long *dataend, int *status); int CFITS_API ffghadll(fitsfile *fptr, LONGLONG *headstart, LONGLONG *datastart, LONGLONG *dataend, int *status); int CFITS_API ffghof(fitsfile *fptr, OFF_T *headstart, OFF_T *datastart, OFF_T *dataend, int *status); int CFITS_API ffgipr(fitsfile *fptr, int maxaxis, int *imgtype, int *naxis, long *naxes, int *status); int CFITS_API ffgiprll(fitsfile *fptr, int maxaxis, int *imgtype, int *naxis, LONGLONG *naxes, int *status); int CFITS_API ffgidt(fitsfile *fptr, int *imgtype, int *status); int CFITS_API ffgiet(fitsfile *fptr, int *imgtype, int *status); int CFITS_API ffgidm(fitsfile *fptr, int *naxis, int *status); int CFITS_API ffgisz(fitsfile *fptr, int nlen, long *naxes, int *status); int CFITS_API ffgiszll(fitsfile *fptr, int nlen, LONGLONG *naxes, int *status); /*--------------------- HDU operations -------------*/ int CFITS_API ffmahd(fitsfile *fptr, int hdunum, int *exttype, int *status); int CFITS_API ffmrhd(fitsfile *fptr, int hdumov, int *exttype, int *status); int CFITS_API ffmnhd(fitsfile *fptr, int exttype, char *hduname, int hduvers, int *status); int CFITS_API ffthdu(fitsfile *fptr, int *nhdu, int *status); int CFITS_API ffcrhd(fitsfile *fptr, int *status); int CFITS_API ffcrim(fitsfile *fptr, int bitpix, int naxis, long *naxes, int *status); int CFITS_API ffcrimll(fitsfile *fptr, int bitpix, int naxis, LONGLONG *naxes, int *status); int CFITS_API ffcrtb(fitsfile *fptr, int tbltype, LONGLONG naxis2, int tfields, char **ttype, char **tform, char **tunit, const char *extname, int *status); int CFITS_API ffiimg(fitsfile *fptr, int bitpix, int naxis, long *naxes, int *status); int CFITS_API ffiimgll(fitsfile *fptr, int bitpix, int naxis, LONGLONG *naxes, int *status); int CFITS_API ffitab(fitsfile *fptr, LONGLONG naxis1, LONGLONG naxis2, int tfields, char **ttype, long *tbcol, char **tform, char **tunit, const char *extname, int *status); int CFITS_API ffibin(fitsfile *fptr, LONGLONG naxis2, int tfields, char **ttype, char **tform, char **tunit, const char *extname, LONGLONG pcount, int *status); int CFITS_API ffrsim(fitsfile *fptr, int bitpix, int naxis, long *naxes, int *status); int CFITS_API ffrsimll(fitsfile *fptr, int bitpix, int naxis, LONGLONG *naxes, int *status); int CFITS_API ffdhdu(fitsfile *fptr, int *hdutype, int *status); int CFITS_API ffcopy(fitsfile *infptr, fitsfile *outfptr, int morekeys, int *status); int CFITS_API ffcpfl(fitsfile *infptr, fitsfile *outfptr, int prev, int cur, int follow, int *status); int CFITS_API ffcphd(fitsfile *infptr, fitsfile *outfptr, int *status); int CFITS_API ffcpdt(fitsfile *infptr, fitsfile *outfptr, int *status); int CFITS_API ffchfl(fitsfile *fptr, int *status); int CFITS_API ffcdfl(fitsfile *fptr, int *status); int CFITS_API ffwrhdu(fitsfile *fptr, FILE *outstream, int *status); int CFITS_API ffrdef(fitsfile *fptr, int *status); int CFITS_API ffrhdu(fitsfile *fptr, int *hdutype, int *status); int CFITS_API ffhdef(fitsfile *fptr, int morekeys, int *status); int CFITS_API ffpthp(fitsfile *fptr, long theap, int *status); int CFITS_API ffcsum(fitsfile *fptr, long nrec, unsigned long *sum, int *status); void CFITS_API ffesum(unsigned long sum, int complm, char *ascii); unsigned long CFITS_API ffdsum(char *ascii, int complm, unsigned long *sum); int CFITS_API ffpcks(fitsfile *fptr, int *status); int CFITS_API ffupck(fitsfile *fptr, int *status); int CFITS_API ffvcks(fitsfile *fptr, int *datastatus, int *hdustatus, int *status); int CFITS_API ffgcks(fitsfile *fptr, unsigned long *datasum, unsigned long *hdusum, int *status); /*--------------------- define scaling or null values -------------*/ int CFITS_API ffpscl(fitsfile *fptr, double scale, double zeroval, int *status); int CFITS_API ffpnul(fitsfile *fptr, LONGLONG nulvalue, int *status); int CFITS_API fftscl(fitsfile *fptr, int colnum, double scale, double zeroval, int *status); int CFITS_API fftnul(fitsfile *fptr, int colnum, LONGLONG nulvalue, int *status); int CFITS_API ffsnul(fitsfile *fptr, int colnum, char *nulstring, int *status); /*--------------------- get column information -------------*/ int CFITS_API ffgcno(fitsfile *fptr, int casesen, char *templt, int *colnum, int *status); int CFITS_API ffgcnn(fitsfile *fptr, int casesen, char *templt, char *colname, int *colnum, int *status); int CFITS_API ffgtcl(fitsfile *fptr, int colnum, int *typecode, long *repeat, long *width, int *status); int CFITS_API ffgtclll(fitsfile *fptr, int colnum, int *typecode, LONGLONG *repeat, LONGLONG *width, int *status); int CFITS_API ffeqty(fitsfile *fptr, int colnum, int *typecode, long *repeat, long *width, int *status); int CFITS_API ffeqtyll(fitsfile *fptr, int colnum, int *typecode, LONGLONG *repeat, LONGLONG *width, int *status); int CFITS_API ffgncl(fitsfile *fptr, int *ncols, int *status); int CFITS_API ffgnrw(fitsfile *fptr, long *nrows, int *status); int CFITS_API ffgnrwll(fitsfile *fptr, LONGLONG *nrows, int *status); int CFITS_API ffgacl(fitsfile *fptr, int colnum, char *ttype, long *tbcol, char *tunit, char *tform, double *tscal, double *tzero, char *tnull, char *tdisp, int *status); int CFITS_API ffgbcl(fitsfile *fptr, int colnum, char *ttype, char *tunit, char *dtype, long *repeat, double *tscal, double *tzero, long *tnull, char *tdisp, int *status); int CFITS_API ffgbclll(fitsfile *fptr, int colnum, char *ttype, char *tunit, char *dtype, LONGLONG *repeat, double *tscal, double *tzero, LONGLONG *tnull, char *tdisp, int *status); int CFITS_API ffgrsz(fitsfile *fptr, long *nrows, int *status); int CFITS_API ffgcdw(fitsfile *fptr, int colnum, int *width, int *status); /*--------------------- read primary array or image elements -------------*/ int CFITS_API ffgpxv(fitsfile *fptr, int datatype, long *firstpix, LONGLONG nelem, void *nulval, void *array, int *anynul, int *status); int CFITS_API ffgpxvll(fitsfile *fptr, int datatype, LONGLONG *firstpix, LONGLONG nelem, void *nulval, void *array, int *anynul, int *status); int CFITS_API ffgpxf(fitsfile *fptr, int datatype, long *firstpix, LONGLONG nelem, void *array, char *nullarray, int *anynul, int *status); int CFITS_API ffgpxfll(fitsfile *fptr, int datatype, LONGLONG *firstpix, LONGLONG nelem, void *array, char *nullarray, int *anynul, int *status); int CFITS_API ffgsv(fitsfile *fptr, int datatype, long *blc, long *trc, long *inc, void *nulval, void *array, int *anynul, int *status); int CFITS_API ffgpv(fitsfile *fptr, int datatype, LONGLONG firstelem, LONGLONG nelem, void *nulval, void *array, int *anynul, int *status); int CFITS_API ffgpf(fitsfile *fptr, int datatype, LONGLONG firstelem, LONGLONG nelem, void *array, char *nullarray, int *anynul, int *status); int CFITS_API ffgpvb(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned char nulval, unsigned char *array, int *anynul, int *status); int CFITS_API ffgpvsb(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, signed char nulval, signed char *array, int *anynul, int *status); int CFITS_API ffgpvui(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned short nulval, unsigned short *array, int *anynul, int *status); int CFITS_API ffgpvi(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, short nulval, short *array, int *anynul, int *status); int CFITS_API ffgpvuj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned long nulval, unsigned long *array, int *anynul, int *status); int CFITS_API ffgpvj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, long nulval, long *array, int *anynul, int *status); int CFITS_API ffgpvjj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, LONGLONG nulval, LONGLONG *array, int *anynul, int *status); int CFITS_API ffgpvuk(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned int nulval, unsigned int *array, int *anynul, int *status); int CFITS_API ffgpvk(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, int nulval, int *array, int *anynul, int *status); int CFITS_API ffgpve(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, float nulval, float *array, int *anynul, int *status); int CFITS_API ffgpvd(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, double nulval, double *array, int *anynul, int *status); int CFITS_API ffgpfb(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned char *array, char *nularray, int *anynul, int *status); int CFITS_API ffgpfsb(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, signed char *array, char *nularray, int *anynul, int *status); int CFITS_API ffgpfui(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned short *array, char *nularray, int *anynul, int *status); int CFITS_API ffgpfi(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, short *array, char *nularray, int *anynul, int *status); int CFITS_API ffgpfuj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned long *array, char *nularray, int *anynul, int *status); int CFITS_API ffgpfj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, long *array, char *nularray, int *anynul, int *status); int CFITS_API ffgpfjj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, LONGLONG *array, char *nularray, int *anynul, int *status); int CFITS_API ffgpfuk(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned int *array, char *nularray, int *anynul, int *status); int CFITS_API ffgpfk(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, int *array, char *nularray, int *anynul, int *status); int CFITS_API ffgpfe(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, float *array, char *nularray, int *anynul, int *status); int CFITS_API ffgpfd(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, double *array, char *nularray, int *anynul, int *status); int CFITS_API ffg2db(fitsfile *fptr, long group, unsigned char nulval, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, unsigned char *array, int *anynul, int *status); int CFITS_API ffg2dsb(fitsfile *fptr, long group, signed char nulval, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, signed char *array, int *anynul, int *status); int CFITS_API ffg2dui(fitsfile *fptr, long group, unsigned short nulval, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, unsigned short *array, int *anynul, int *status); int CFITS_API ffg2di(fitsfile *fptr, long group, short nulval, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, short *array, int *anynul, int *status); int CFITS_API ffg2duj(fitsfile *fptr, long group, unsigned long nulval, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, unsigned long *array, int *anynul, int *status); int CFITS_API ffg2dj(fitsfile *fptr, long group, long nulval, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, long *array, int *anynul, int *status); int CFITS_API ffg2djj(fitsfile *fptr, long group, LONGLONG nulval, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, LONGLONG *array, int *anynul, int *status); int CFITS_API ffg2duk(fitsfile *fptr, long group, unsigned int nulval, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, unsigned int *array, int *anynul, int *status); int CFITS_API ffg2dk(fitsfile *fptr, long group, int nulval, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, int *array, int *anynul, int *status); int CFITS_API ffg2de(fitsfile *fptr, long group, float nulval, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, float *array, int *anynul, int *status); int CFITS_API ffg2dd(fitsfile *fptr, long group, double nulval, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, double *array, int *anynul, int *status); int CFITS_API ffg3db(fitsfile *fptr, long group, unsigned char nulval, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, unsigned char *array, int *anynul, int *status); int CFITS_API ffg3dsb(fitsfile *fptr, long group, signed char nulval, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, signed char *array, int *anynul, int *status); int CFITS_API ffg3dui(fitsfile *fptr, long group, unsigned short nulval, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, unsigned short *array, int *anynul, int *status); int CFITS_API ffg3di(fitsfile *fptr, long group, short nulval, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, short *array, int *anynul, int *status); int CFITS_API ffg3duj(fitsfile *fptr, long group, unsigned long nulval, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, unsigned long *array, int *anynul, int *status); int CFITS_API ffg3dj(fitsfile *fptr, long group, long nulval, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, long *array, int *anynul, int *status); int CFITS_API ffg3djj(fitsfile *fptr, long group, LONGLONG nulval, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, LONGLONG *array, int *anynul, int *status); int CFITS_API ffg3duk(fitsfile *fptr, long group, unsigned int nulval, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, unsigned int *array, int *anynul, int *status); int CFITS_API ffg3dk(fitsfile *fptr, long group, int nulval, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, int *array, int *anynul, int *status); int CFITS_API ffg3de(fitsfile *fptr, long group, float nulval, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, float *array, int *anynul, int *status); int CFITS_API ffg3dd(fitsfile *fptr, long group, double nulval, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, double *array, int *anynul, int *status); int CFITS_API ffgsvb(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, unsigned char nulval, unsigned char *array, int *anynul, int *status); int CFITS_API ffgsvsb(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, signed char nulval, signed char *array, int *anynul, int *status); int CFITS_API ffgsvui(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, unsigned short nulval, unsigned short *array, int *anynul, int *status); int CFITS_API ffgsvi(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, short nulval, short *array, int *anynul, int *status); int CFITS_API ffgsvuj(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, unsigned long nulval, unsigned long *array, int *anynul, int *status); int CFITS_API ffgsvj(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, long nulval, long *array, int *anynul, int *status); int CFITS_API ffgsvjj(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, LONGLONG nulval, LONGLONG *array, int *anynul, int *status); int CFITS_API ffgsvuk(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, unsigned int nulval, unsigned int *array, int *anynul, int *status); int CFITS_API ffgsvk(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, int nulval, int *array, int *anynul, int *status); int CFITS_API ffgsve(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, float nulval, float *array, int *anynul, int *status); int CFITS_API ffgsvd(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, double nulval, double *array, int *anynul, int *status); int CFITS_API ffgsfb(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, unsigned char *array, char *flagval, int *anynul, int *status); int CFITS_API ffgsfsb(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, signed char *array, char *flagval, int *anynul, int *status); int CFITS_API ffgsfui(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, unsigned short *array, char *flagval, int *anynul, int *status); int CFITS_API ffgsfi(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, short *array, char *flagval, int *anynul, int *status); int CFITS_API ffgsfuj(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, unsigned long *array, char *flagval, int *anynul, int *status); int CFITS_API ffgsfj(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, long *array, char *flagval, int *anynul, int *status); int CFITS_API ffgsfjj(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, LONGLONG *array, char *flagval, int *anynul, int *status); int CFITS_API ffgsfuk(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, unsigned int *array, char *flagval, int *anynul, int *status); int CFITS_API ffgsfk(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, int *array, char *flagval, int *anynul, int *status); int CFITS_API ffgsfe(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, float *array, char *flagval, int *anynul, int *status); int CFITS_API ffgsfd(fitsfile *fptr, int colnum, int naxis, long *naxes, long *blc, long *trc, long *inc, double *array, char *flagval, int *anynul, int *status); int CFITS_API ffggpb(fitsfile *fptr, long group, long firstelem, long nelem, unsigned char *array, int *status); int CFITS_API ffggpsb(fitsfile *fptr, long group, long firstelem, long nelem, signed char *array, int *status); int CFITS_API ffggpui(fitsfile *fptr, long group, long firstelem, long nelem, unsigned short *array, int *status); int CFITS_API ffggpi(fitsfile *fptr, long group, long firstelem, long nelem, short *array, int *status); int CFITS_API ffggpuj(fitsfile *fptr, long group, long firstelem, long nelem, unsigned long *array, int *status); int CFITS_API ffggpj(fitsfile *fptr, long group, long firstelem, long nelem, long *array, int *status); int CFITS_API ffggpjj(fitsfile *fptr, long group, long firstelem, long nelem, LONGLONG *array, int *status); int CFITS_API ffggpuk(fitsfile *fptr, long group, long firstelem, long nelem, unsigned int *array, int *status); int CFITS_API ffggpk(fitsfile *fptr, long group, long firstelem, long nelem, int *array, int *status); int CFITS_API ffggpe(fitsfile *fptr, long group, long firstelem, long nelem, float *array, int *status); int CFITS_API ffggpd(fitsfile *fptr, long group, long firstelem, long nelem, double *array, int *status); /*--------------------- read column elements -------------*/ int CFITS_API ffgcv( fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, void *nulval, void *array, int *anynul, int *status); int CFITS_API ffgcf( fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, void *array, char *nullarray, int *anynul, int *status); int CFITS_API ffgcvs(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, char *nulval, char **array, int *anynul, int *status); int CFITS_API ffgcl (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, char *array, int *status); int CFITS_API ffgcvl (fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, char nulval, char *array, int *anynul, int *status); int CFITS_API ffgcvb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned char nulval, unsigned char *array, int *anynul, int *status); int CFITS_API ffgcvsb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, signed char nulval, signed char *array, int *anynul, int *status); int CFITS_API ffgcvui(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned short nulval, unsigned short *array, int *anynul, int *status); int CFITS_API ffgcvi(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, short nulval, short *array, int *anynul, int *status); int CFITS_API ffgcvuj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned long nulval, unsigned long *array, int *anynul, int *status); int CFITS_API ffgcvj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long nulval, long *array, int *anynul, int *status); int CFITS_API ffgcvjj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, LONGLONG nulval, LONGLONG *array, int *anynul, int *status); int CFITS_API ffgcvuk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned int nulval, unsigned int *array, int *anynul, int *status); int CFITS_API ffgcvk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, int nulval, int *array, int *anynul, int *status); int CFITS_API ffgcve(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, float nulval, float *array, int *anynul, int *status); int CFITS_API ffgcvd(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, double nulval, double *array, int *anynul, int *status); int CFITS_API ffgcvc(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, float nulval, float *array, int *anynul, int *status); int CFITS_API ffgcvm(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, double nulval, double *array, int *anynul, int *status); int CFITS_API ffgcx(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstbit, LONGLONG nbits, char *larray, int *status); int CFITS_API ffgcxui(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG nrows, long firstbit, int nbits, unsigned short *array, int *status); int CFITS_API ffgcxuk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG nrows, long firstbit, int nbits, unsigned int *array, int *status); int CFITS_API ffgcfs(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, char **array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfl(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, char *array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned char *array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfsb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, signed char *array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfui(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned short *array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfi(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, short *array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfuj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned long *array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long *array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfjj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, LONGLONG *array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfuk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned int *array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, int *array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfe(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, float *array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfd(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, double *array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfc(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, float *array, char *nularray, int *anynul, int *status); int CFITS_API ffgcfm(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, double *array, char *nularray, int *anynul, int *status); int CFITS_API ffgdes(fitsfile *fptr, int colnum, LONGLONG rownum, long *length, long *heapaddr, int *status); int CFITS_API ffgdesll(fitsfile *fptr, int colnum, LONGLONG rownum, LONGLONG *length, LONGLONG *heapaddr, int *status); int CFITS_API ffgdess(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG nrows, long *length, long *heapaddr, int *status); int CFITS_API ffgdessll(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG nrows, LONGLONG *length, LONGLONG *heapaddr, int *status); int CFITS_API ffpdes(fitsfile *fptr, int colnum, LONGLONG rownum, LONGLONG length, LONGLONG heapaddr, int *status); int CFITS_API fftheap(fitsfile *fptr, LONGLONG *heapsize, LONGLONG *unused, LONGLONG *overlap, int *valid, int *status); int CFITS_API ffcmph(fitsfile *fptr, int *status); int CFITS_API ffgtbb(fitsfile *fptr, LONGLONG firstrow, LONGLONG firstchar, LONGLONG nchars, unsigned char *values, int *status); int CFITS_API ffgextn(fitsfile *fptr, LONGLONG offset, LONGLONG nelem, void *array, int *status); int CFITS_API ffpextn(fitsfile *fptr, LONGLONG offset, LONGLONG nelem, void *array, int *status); /*------------ write primary array or image elements -------------*/ int CFITS_API ffppx(fitsfile *fptr, int datatype, long *firstpix, LONGLONG nelem, void *array, int *status); int CFITS_API ffppxll(fitsfile *fptr, int datatype, LONGLONG *firstpix, LONGLONG nelem, void *array, int *status); int CFITS_API ffppxn(fitsfile *fptr, int datatype, long *firstpix, LONGLONG nelem, void *array, void *nulval, int *status); int CFITS_API ffppxnll(fitsfile *fptr, int datatype, LONGLONG *firstpix, LONGLONG nelem, void *array, void *nulval, int *status); int CFITS_API ffppr(fitsfile *fptr, int datatype, LONGLONG firstelem, LONGLONG nelem, void *array, int *status); int CFITS_API ffpprb(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned char *array, int *status); int CFITS_API ffpprsb(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, signed char *array, int *status); int CFITS_API ffpprui(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned short *array, int *status); int CFITS_API ffppri(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, short *array, int *status); int CFITS_API ffppruj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned long *array, int *status); int CFITS_API ffpprj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, long *array, int *status); int CFITS_API ffppruk(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned int *array, int *status); int CFITS_API ffpprk(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, int *array, int *status); int CFITS_API ffppre(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, float *array, int *status); int CFITS_API ffpprd(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, double *array, int *status); int CFITS_API ffpprjj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, LONGLONG *array, int *status); int CFITS_API ffppru(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, int *status); int CFITS_API ffpprn(fitsfile *fptr, LONGLONG firstelem, LONGLONG nelem, int *status); int CFITS_API ffppn(fitsfile *fptr, int datatype, LONGLONG firstelem, LONGLONG nelem, void *array, void *nulval, int *status); int CFITS_API ffppnb(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned char *array, unsigned char nulval, int *status); int CFITS_API ffppnsb(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, signed char *array, signed char nulval, int *status); int CFITS_API ffppnui(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned short *array, unsigned short nulval, int *status); int CFITS_API ffppni(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, short *array, short nulval, int *status); int CFITS_API ffppnj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, long *array, long nulval, int *status); int CFITS_API ffppnuj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned long *array, unsigned long nulval, int *status); int CFITS_API ffppnuk(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, unsigned int *array, unsigned int nulval, int *status); int CFITS_API ffppnk(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, int *array, int nulval, int *status); int CFITS_API ffppne(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, float *array, float nulval, int *status); int CFITS_API ffppnd(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, double *array, double nulval, int *status); int CFITS_API ffppnjj(fitsfile *fptr, long group, LONGLONG firstelem, LONGLONG nelem, LONGLONG *array, LONGLONG nulval, int *status); int CFITS_API ffp2db(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, unsigned char *array, int *status); int CFITS_API ffp2dsb(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, signed char *array, int *status); int CFITS_API ffp2dui(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, unsigned short *array, int *status); int CFITS_API ffp2di(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, short *array, int *status); int CFITS_API ffp2duj(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, unsigned long *array, int *status); int CFITS_API ffp2dj(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, long *array, int *status); int CFITS_API ffp2duk(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, unsigned int *array, int *status); int CFITS_API ffp2dk(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, int *array, int *status); int CFITS_API ffp2de(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, float *array, int *status); int CFITS_API ffp2dd(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, double *array, int *status); int CFITS_API ffp2djj(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG naxis1, LONGLONG naxis2, LONGLONG *array, int *status); int CFITS_API ffp3db(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, unsigned char *array, int *status); int CFITS_API ffp3dsb(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, signed char *array, int *status); int CFITS_API ffp3dui(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, unsigned short *array, int *status); int CFITS_API ffp3di(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, short *array, int *status); int CFITS_API ffp3duj(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, unsigned long *array, int *status); int CFITS_API ffp3dj(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, long *array, int *status); int CFITS_API ffp3duk(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, unsigned int *array, int *status); int CFITS_API ffp3dk(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, int *array, int *status); int CFITS_API ffp3de(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, float *array, int *status); int CFITS_API ffp3dd(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, double *array, int *status); int CFITS_API ffp3djj(fitsfile *fptr, long group, LONGLONG ncols, LONGLONG nrows, LONGLONG naxis1, LONGLONG naxis2, LONGLONG naxis3, LONGLONG *array, int *status); int CFITS_API ffpss(fitsfile *fptr, int datatype, long *fpixel, long *lpixel, void *array, int *status); int CFITS_API ffpssb(fitsfile *fptr, long group, long naxis, long *naxes, long *fpixel, long *lpixel, unsigned char *array, int *status); int CFITS_API ffpsssb(fitsfile *fptr, long group, long naxis, long *naxes, long *fpixel, long *lpixel, signed char *array, int *status); int CFITS_API ffpssui(fitsfile *fptr, long group, long naxis, long *naxes, long *fpixel, long *lpixel, unsigned short *array, int *status); int CFITS_API ffpssi(fitsfile *fptr, long group, long naxis, long *naxes, long *fpixel, long *lpixel, short *array, int *status); int CFITS_API ffpssuj(fitsfile *fptr, long group, long naxis, long *naxes, long *fpixel, long *lpixel, unsigned long *array, int *status); int CFITS_API ffpssj(fitsfile *fptr, long group, long naxis, long *naxes, long *fpixel, long *lpixel, long *array, int *status); int CFITS_API ffpssuk(fitsfile *fptr, long group, long naxis, long *naxes, long *fpixel, long *lpixel, unsigned int *array, int *status); int CFITS_API ffpssk(fitsfile *fptr, long group, long naxis, long *naxes, long *fpixel, long *lpixel, int *array, int *status); int CFITS_API ffpsse(fitsfile *fptr, long group, long naxis, long *naxes, long *fpixel, long *lpixel, float *array, int *status); int CFITS_API ffpssd(fitsfile *fptr, long group, long naxis, long *naxes, long *fpixel, long *lpixel, double *array, int *status); int CFITS_API ffpssjj(fitsfile *fptr, long group, long naxis, long *naxes, long *fpixel, long *lpixel, LONGLONG *array, int *status); int CFITS_API ffpgpb(fitsfile *fptr, long group, long firstelem, long nelem, unsigned char *array, int *status); int CFITS_API ffpgpsb(fitsfile *fptr, long group, long firstelem, long nelem, signed char *array, int *status); int CFITS_API ffpgpui(fitsfile *fptr, long group, long firstelem, long nelem, unsigned short *array, int *status); int CFITS_API ffpgpi(fitsfile *fptr, long group, long firstelem, long nelem, short *array, int *status); int CFITS_API ffpgpuj(fitsfile *fptr, long group, long firstelem, long nelem, unsigned long *array, int *status); int CFITS_API ffpgpj(fitsfile *fptr, long group, long firstelem, long nelem, long *array, int *status); int CFITS_API ffpgpuk(fitsfile *fptr, long group, long firstelem, long nelem, unsigned int *array, int *status); int CFITS_API ffpgpk(fitsfile *fptr, long group, long firstelem, long nelem, int *array, int *status); int CFITS_API ffpgpe(fitsfile *fptr, long group, long firstelem, long nelem, float *array, int *status); int CFITS_API ffpgpd(fitsfile *fptr, long group, long firstelem, long nelem, double *array, int *status); int CFITS_API ffpgpjj(fitsfile *fptr, long group, long firstelem, long nelem, LONGLONG *array, int *status); /*--------------------- iterator functions -------------*/ int CFITS_API fits_iter_set_by_name(iteratorCol *col, fitsfile *fptr, char *colname, int datatype, int iotype); int CFITS_API fits_iter_set_by_num(iteratorCol *col, fitsfile *fptr, int colnum, int datatype, int iotype); int CFITS_API fits_iter_set_file(iteratorCol *col, fitsfile *fptr); int CFITS_API fits_iter_set_colname(iteratorCol *col, char *colname); int CFITS_API fits_iter_set_colnum(iteratorCol *col, int colnum); int CFITS_API fits_iter_set_datatype(iteratorCol *col, int datatype); int CFITS_API fits_iter_set_iotype(iteratorCol *col, int iotype); CFITS_API fitsfile * fits_iter_get_file(iteratorCol *col); char CFITS_API * fits_iter_get_colname(iteratorCol *col); int CFITS_API fits_iter_get_colnum(iteratorCol *col); int CFITS_API fits_iter_get_datatype(iteratorCol *col); int CFITS_API fits_iter_get_iotype(iteratorCol *col); void CFITS_API *fits_iter_get_array(iteratorCol *col); long CFITS_API fits_iter_get_tlmin(iteratorCol *col); long CFITS_API fits_iter_get_tlmax(iteratorCol *col); long CFITS_API fits_iter_get_repeat(iteratorCol *col); char CFITS_API *fits_iter_get_tunit(iteratorCol *col); char CFITS_API *fits_iter_get_tdisp(iteratorCol *col); int CFITS_API ffiter(int ncols, iteratorCol *data, long offset, long nPerLoop, int (*workFn)( long totaln, long offset, long firstn, long nvalues, int narrays, iteratorCol *data, void *userPointer), void *userPointer, int *status); /*--------------------- write column elements -------------*/ int CFITS_API ffpcl(fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, void *array, int *status); int CFITS_API ffpcls(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, char **array, int *status); int CFITS_API ffpcll(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, char *array, int *status); int CFITS_API ffpclb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned char *array, int *status); int CFITS_API ffpclsb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, signed char *array, int *status); int CFITS_API ffpclui(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned short *array, int *status); int CFITS_API ffpcli(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, short *array, int *status); int CFITS_API ffpcluj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned long *array, int *status); int CFITS_API ffpclj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long *array, int *status); int CFITS_API ffpcluk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned int *array, int *status); int CFITS_API ffpclk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, int *array, int *status); int CFITS_API ffpcle(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, float *array, int *status); int CFITS_API ffpcld(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, double *array, int *status); int CFITS_API ffpclc(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, float *array, int *status); int CFITS_API ffpclm(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, double *array, int *status); int CFITS_API ffpclu(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, int *status); int CFITS_API ffprwu(fitsfile *fptr, LONGLONG firstrow, LONGLONG nrows, int *status); int CFITS_API ffpcljj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, LONGLONG *array, int *status); int CFITS_API ffpclx(fitsfile *fptr, int colnum, LONGLONG frow, long fbit, long nbit, char *larray, int *status); int CFITS_API ffpcn(fitsfile *fptr, int datatype, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, void *array, void *nulval, int *status); int CFITS_API ffpcns( fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, char **array, char *nulvalue, int *status); int CFITS_API ffpcnl( fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, char *array, char nulvalue, int *status); int CFITS_API ffpcnb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned char *array, unsigned char nulvalue, int *status); int CFITS_API ffpcnsb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, signed char *array, signed char nulvalue, int *status); int CFITS_API ffpcnui(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned short *array, unsigned short nulvalue, int *status); int CFITS_API ffpcni(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, short *array, short nulvalue, int *status); int CFITS_API ffpcnuj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned long *array, unsigned long nulvalue, int *status); int CFITS_API ffpcnj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long *array, long nulvalue, int *status); int CFITS_API ffpcnuk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, unsigned int *array, unsigned int nulvalue, int *status); int CFITS_API ffpcnk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, int *array, int nulvalue, int *status); int CFITS_API ffpcne(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, float *array, float nulvalue, int *status); int CFITS_API ffpcnd(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, double *array, double nulvalue, int *status); int CFITS_API ffpcnjj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, LONGLONG *array, LONGLONG nulvalue, int *status); int CFITS_API ffptbb(fitsfile *fptr, LONGLONG firstrow, LONGLONG firstchar, LONGLONG nchars, unsigned char *values, int *status); int CFITS_API ffirow(fitsfile *fptr, LONGLONG firstrow, LONGLONG nrows, int *status); int CFITS_API ffdrow(fitsfile *fptr, LONGLONG firstrow, LONGLONG nrows, int *status); int CFITS_API ffdrrg(fitsfile *fptr, char *ranges, int *status); int CFITS_API ffdrws(fitsfile *fptr, long *rownum, long nrows, int *status); int CFITS_API ffdrwsll(fitsfile *fptr, LONGLONG *rownum, LONGLONG nrows, int *status); int CFITS_API fficol(fitsfile *fptr, int numcol, char *ttype, char *tform, int *status); int CFITS_API fficls(fitsfile *fptr, int firstcol, int ncols, char **ttype, char **tform, int *status); int CFITS_API ffmvec(fitsfile *fptr, int colnum, LONGLONG newveclen, int *status); int CFITS_API ffdcol(fitsfile *fptr, int numcol, int *status); int CFITS_API ffcpcl(fitsfile *infptr, fitsfile *outfptr, int incol, int outcol, int create_col, int *status); int CFITS_API ffcprw(fitsfile *infptr, fitsfile *outfptr, LONGLONG firstrow, LONGLONG nrows, int *status); /*--------------------- WCS Utilities ------------------*/ int CFITS_API ffgics(fitsfile *fptr, double *xrval, double *yrval, double *xrpix, double *yrpix, double *xinc, double *yinc, double *rot, char *type, int *status); int CFITS_API ffgicsa(fitsfile *fptr, char version, double *xrval, double *yrval, double *xrpix, double *yrpix, double *xinc, double *yinc, double *rot, char *type, int *status); int CFITS_API ffgtcs(fitsfile *fptr, int xcol, int ycol, double *xrval, double *yrval, double *xrpix, double *yrpix, double *xinc, double *yinc, double *rot, char *type, int *status); int CFITS_API ffwldp(double xpix, double ypix, double xref, double yref, double xrefpix, double yrefpix, double xinc, double yinc, double rot, char *type, double *xpos, double *ypos, int *status); int CFITS_API ffxypx(double xpos, double ypos, double xref, double yref, double xrefpix, double yrefpix, double xinc, double yinc, double rot, char *type, double *xpix, double *ypix, int *status); /* WCS support routines (provide interface to Doug Mink's WCS library */ int CFITS_API ffgiwcs(fitsfile *fptr, char **header, int *status); int CFITS_API ffgtwcs(fitsfile *fptr, int xcol, int ycol, char **header, int *status); /*--------------------- lexical parsing routines ------------------*/ int CFITS_API fftexp( fitsfile *fptr, char *expr, int maxdim, int *datatype, long *nelem, int *naxis, long *naxes, int *status ); int CFITS_API fffrow( fitsfile *infptr, char *expr, long firstrow, long nrows, long *n_good_rows, char *row_status, int *status); int CFITS_API ffffrw( fitsfile *fptr, char *expr, long *rownum, int *status); int CFITS_API fffrwc( fitsfile *fptr, char *expr, char *timeCol, char *parCol, char *valCol, long ntimes, double *times, char *time_status, int *status ); int CFITS_API ffsrow( fitsfile *infptr, fitsfile *outfptr, char *expr, int *status); int CFITS_API ffcrow( fitsfile *fptr, int datatype, char *expr, long firstrow, long nelements, void *nulval, void *array, int *anynul, int *status ); int CFITS_API ffcalc_rng( fitsfile *infptr, char *expr, fitsfile *outfptr, char *parName, char *parInfo, int nRngs, long *start, long *end, int *status ); int CFITS_API ffcalc( fitsfile *infptr, char *expr, fitsfile *outfptr, char *parName, char *parInfo, int *status ); /* ffhist is not really intended as a user-callable routine */ /* but it may be useful for some specialized applications */ /* ffhist2 is a newer version which is strongly recommended instead of ffhist */ int CFITS_API ffhist(fitsfile **fptr, char *outfile, int imagetype, int naxis, char colname[4][FLEN_VALUE], double *minin, double *maxin, double *binsizein, char minname[4][FLEN_VALUE], char maxname[4][FLEN_VALUE], char binname[4][FLEN_VALUE], double weightin, char wtcol[FLEN_VALUE], int recip, char *rowselect, int *status); int CFITS_API ffhist2(fitsfile **fptr, char *outfile, int imagetype, int naxis, char colname[4][FLEN_VALUE], double *minin, double *maxin, double *binsizein, char minname[4][FLEN_VALUE], char maxname[4][FLEN_VALUE], char binname[4][FLEN_VALUE], double weightin, char wtcol[FLEN_VALUE], int recip, char *rowselect, int *status); CFITS_API fitsfile *ffhist3(fitsfile *fptr, char *outfile, int imagetype, int naxis, char colname[4][FLEN_VALUE], double *minin, double *maxin, double *binsizein, char minname[4][FLEN_VALUE], char maxname[4][FLEN_VALUE], char binname[4][FLEN_VALUE], double weightin, char wtcol[FLEN_VALUE], int recip, char *selectrow, int *status); int CFITS_API fits_select_image_section(fitsfile **fptr, char *outfile, char *imagesection, int *status); int CFITS_API fits_copy_image_section(fitsfile *infptr, fitsfile *outfile, char *imagesection, int *status); int CFITS_API fits_calc_binning(fitsfile *fptr, int naxis, char colname[4][FLEN_VALUE], double *minin, double *maxin, double *binsizein, char minname[4][FLEN_VALUE], char maxname[4][FLEN_VALUE], char binname[4][FLEN_VALUE], int *colnum, long *haxes, float *amin, float *amax, float *binsize, int *status); int CFITS_API fits_write_keys_histo(fitsfile *fptr, fitsfile *histptr, int naxis, int *colnum, int *status); int CFITS_API fits_rebin_wcs( fitsfile *fptr, int naxis, float *amin, float *binsize, int *status); int CFITS_API fits_make_hist(fitsfile *fptr, fitsfile *histptr, int bitpix,int naxis, long *naxes, int *colnum, float *amin, float *amax, float *binsize, float weight, int wtcolnum, int recip, char *selectrow, int *status); typedef struct { /* input(s) */ int count; char ** path; char ** tag; fitsfile ** ifptr; char * expression; /* output control */ int bitpix; long blank; fitsfile * ofptr; char keyword[FLEN_KEYWORD]; char comment[FLEN_COMMENT]; } PixelFilter; int CFITS_API fits_pixel_filter (PixelFilter * filter, int * status); /*--------------------- grouping routines ------------------*/ int CFITS_API ffgtcr(fitsfile *fptr, char *grpname, int grouptype, int *status); int CFITS_API ffgtis(fitsfile *fptr, char *grpname, int grouptype, int *status); int CFITS_API ffgtch(fitsfile *gfptr, int grouptype, int *status); int CFITS_API ffgtrm(fitsfile *gfptr, int rmopt, int *status); int CFITS_API ffgtcp(fitsfile *infptr, fitsfile *outfptr, int cpopt, int *status); int CFITS_API ffgtmg(fitsfile *infptr, fitsfile *outfptr, int mgopt, int *status); int CFITS_API ffgtcm(fitsfile *gfptr, int cmopt, int *status); int CFITS_API ffgtvf(fitsfile *gfptr, long *firstfailed, int *status); int CFITS_API ffgtop(fitsfile *mfptr,int group,fitsfile **gfptr,int *status); int CFITS_API ffgtam(fitsfile *gfptr, fitsfile *mfptr, int hdupos, int *status); int CFITS_API ffgtnm(fitsfile *gfptr, long *nmembers, int *status); int CFITS_API ffgmng(fitsfile *mfptr, long *nmembers, int *status); int CFITS_API ffgmop(fitsfile *gfptr, long member, fitsfile **mfptr, int *status); int CFITS_API ffgmcp(fitsfile *gfptr, fitsfile *mfptr, long member, int cpopt, int *status); int CFITS_API ffgmtf(fitsfile *infptr, fitsfile *outfptr, long member, int tfopt, int *status); int CFITS_API ffgmrm(fitsfile *fptr, long member, int rmopt, int *status); /*--------------------- group template parser routines ------------------*/ int CFITS_API fits_execute_template(fitsfile *ff, char *ngp_template, int *status); int CFITS_API fits_img_stats_short(short *array,long nx, long ny, int nullcheck, short nullvalue,long *ngoodpix, short *minvalue, short *maxvalue, double *mean, double *sigma, double *noise1, double *noise2, double *noise3, double *noise5, int *status); int CFITS_API fits_img_stats_int(int *array,long nx, long ny, int nullcheck, int nullvalue,long *ngoodpix, int *minvalue, int *maxvalue, double *mean, double *sigma, double *noise1, double *noise2, double *noise3, double *noise5, int *status); int CFITS_API fits_img_stats_float(float *array, long nx, long ny, int nullcheck, float nullvalue,long *ngoodpix, float *minvalue, float *maxvalue, double *mean, double *sigma, double *noise1, double *noise2, double *noise3, double *noise5, int *status); /*--------------------- image compression routines ------------------*/ int CFITS_API fits_set_compression_type(fitsfile *fptr, int ctype, int *status); int CFITS_API fits_set_tile_dim(fitsfile *fptr, int ndim, long *dims, int *status); int CFITS_API fits_set_noise_bits(fitsfile *fptr, int noisebits, int *status); int CFITS_API fits_set_quantize_level(fitsfile *fptr, float qlevel, int *status); int CFITS_API fits_set_hcomp_scale(fitsfile *fptr, float scale, int *status); int CFITS_API fits_set_hcomp_smooth(fitsfile *fptr, int smooth, int *status); int CFITS_API fits_set_quantize_method(fitsfile *fptr, int method, int *status); int CFITS_API fits_set_quantize_dither(fitsfile *fptr, int dither, int *status); int CFITS_API fits_set_dither_seed(fitsfile *fptr, int seed, int *status); int CFITS_API fits_set_dither_offset(fitsfile *fptr, int offset, int *status); int CFITS_API fits_set_lossy_int(fitsfile *fptr, int lossy_int, int *status); int CFITS_API fits_set_huge_hdu(fitsfile *fptr, int huge, int *status); int CFITS_API fits_set_compression_pref(fitsfile *infptr, fitsfile *outfptr, int *status); int CFITS_API fits_get_compression_type(fitsfile *fptr, int *ctype, int *status); int CFITS_API fits_get_tile_dim(fitsfile *fptr, int ndim, long *dims, int *status); int CFITS_API fits_get_quantize_level(fitsfile *fptr, float *qlevel, int *status); int CFITS_API fits_get_noise_bits(fitsfile *fptr, int *noisebits, int *status); int CFITS_API fits_get_hcomp_scale(fitsfile *fptr, float *scale, int *status); int CFITS_API fits_get_hcomp_smooth(fitsfile *fptr, int *smooth, int *status); int CFITS_API fits_get_dither_seed(fitsfile *fptr, int *seed, int *status); int CFITS_API fits_img_compress(fitsfile *infptr, fitsfile *outfptr, int *status); int CFITS_API fits_compress_img(fitsfile *infptr, fitsfile *outfptr, int compress_type, long *tilesize, int parm1, int parm2, int *status); int CFITS_API fits_is_compressed_image(fitsfile *fptr, int *status); int CFITS_API fits_is_reentrant(void); int CFITS_API fits_decompress_img (fitsfile *infptr, fitsfile *outfptr, int *status); int CFITS_API fits_img_decompress_header(fitsfile *infptr, fitsfile *outfptr, int *status); int CFITS_API fits_img_decompress (fitsfile *infptr, fitsfile *outfptr, int *status); /* H-compress routines */ int CFITS_API fits_hcompress(int *a, int nx, int ny, int scale, char *output, long *nbytes, int *status); int CFITS_API fits_hcompress64(LONGLONG *a, int nx, int ny, int scale, char *output, long *nbytes, int *status); int CFITS_API fits_hdecompress(unsigned char *input, int smooth, int *a, int *nx, int *ny, int *scale, int *status); int CFITS_API fits_hdecompress64(unsigned char *input, int smooth, LONGLONG *a, int *nx, int *ny, int *scale, int *status); int CFITS_API fits_compress_table (fitsfile *infptr, fitsfile *outfptr, int *status); int CFITS_API fits_uncompress_table(fitsfile *infptr, fitsfile *outfptr, int *status); /* curl library wrapper routines (for https access) */ int CFITS_API fits_init_https(); int CFITS_API fits_cleanup_https(); void CFITS_API fits_verbose_https(int flag); /* The following exclusion if __CINT__ is defined is needed for ROOT */ #ifndef __CINT__ #ifdef __cplusplus } #endif #endif #endif cfitsio/fitsio2.h0000644000225700000360000016406513246025103013544 0ustar cagordonlhea#ifndef _FITSIO2_H #define _FITSIO2_H #include "fitsio.h" /* Threading support using POSIX threads programming interface (supplied by Bruce O'Neel) All threaded programs MUST have the -D_REENTRANT on the compile line and must link with -lpthread. This means that when one builds cfitsio for threads you must have -D_REENTRANT on the gcc or cc command line. */ #ifdef _REENTRANT #include /* #include not needed any more */ extern pthread_mutex_t Fitsio_Lock; extern int Fitsio_Pthread_Status; #define FFLOCK1(lockname) (Fitsio_Pthread_Status = pthread_mutex_lock(&lockname)) #define FFUNLOCK1(lockname) (Fitsio_Pthread_Status = pthread_mutex_unlock(&lockname)) #define FFLOCK FFLOCK1(Fitsio_Lock) #define FFUNLOCK FFUNLOCK1(Fitsio_Lock) #define ffstrtok(str, tok, save) strtok_r(str, tok, save) #else #define FFLOCK #define FFUNLOCK #define ffstrtok(str, tok, save) strtok(str, tok) #endif /* If REPLACE_LINKS is defined, then whenever CFITSIO fails to open a file with write access because it is a soft link to a file that only has read access, then CFITSIO will attempt to replace the link with a local copy of the file, with write access. This feature was originally added to support the ftools in the Hera environment, where many of the user's data file are soft links. */ #if defined(BUILD_HERA) #define REPLACE_LINKS 1 #endif #define USE_LARGE_VALUE -99 /* flag used when writing images */ #define DBUFFSIZE 28800 /* size of data buffer in bytes */ #define NMAXFILES 1000 /* maximum number of FITS files that can be opened */ /* CFITSIO will allocate (NMAXFILES * 80) bytes of memory */ /* plus each file that is opened will use NIOBUF * 2880 bytes of memeory */ /* where NIOBUF is defined in fitio.h and has a default value of 40 */ #define MINDIRECT 8640 /* minimum size for direct reads and writes */ /* MINDIRECT must have a value >= 8640 */ /* it is useful to identify certain specific types of machines */ #define NATIVE 0 /* machine that uses non-byteswapped IEEE formats */ #define OTHERTYPE 1 /* any other type of machine */ #define VAXVMS 3 /* uses an odd floating point format */ #define ALPHAVMS 4 /* uses an odd floating point format */ #define IBMPC 5 /* used in drvrfile.c to work around a bug on PCs */ #define CRAY 6 /* requires a special NaN test algorithm */ #define GFLOAT 1 /* used for VMS */ #define IEEEFLOAT 2 /* used for VMS */ /* ======================================================================= */ /* The following logic is used to determine the type machine, */ /* whether the bytes are swapped, and the number of bits in a long value */ /* ======================================================================= */ /* The following platforms have sizeof(long) == 8 */ /* This block of code should match a similar block in fitsio.h */ /* and the block of code at the beginning of f77_wrap.h */ #if defined(__alpha) && ( defined(__unix__) || defined(__NetBSD__) ) /* old Dec Alpha platforms running OSF */ #define BYTESWAPPED TRUE #define LONGSIZE 64 #elif defined(__sparcv9) || (defined(__sparc__) && defined(__arch64__)) /* SUN Solaris7 in 64-bit mode */ #define BYTESWAPPED FALSE #define MACHINE NATIVE #define LONGSIZE 64 /* IBM System z mainframe support */ #elif defined(__s390x__) #define BYTESWAPPED FALSE #define LONGSIZE 64 #elif defined(__s390__) #define BYTESWAPPED FALSE #define LONGSIZE 32 #elif defined(__ia64__) || defined(__x86_64__) || defined(__AARCH64EL__) /* Intel itanium 64-bit PC, or AMD opteron 64-bit PC */ #define BYTESWAPPED TRUE #define LONGSIZE 64 #elif defined(_SX) /* Nec SuperUx */ #define BYTESWAPPED FALSE #define MACHINE NATIVE #define LONGSIZE 64 #elif defined(__powerpc64__) || defined(__64BIT__) || defined(__AARCH64EB__) /* IBM 64-bit AIX powerpc*/ /* could also test for __ppc64__ or __PPC64 */ # if defined(__LITTLE_ENDIAN__) # define BYTESWAPPED TRUE # else # define BYTESWAPPED FALSE # define MACHINE NATIVE # endif # define LONGSIZE 64 #elif defined(_MIPS_SZLONG) # if defined(MIPSEL) # define BYTESWAPPED TRUE # else # define BYTESWAPPED FALSE # define MACHINE NATIVE # endif # if _MIPS_SZLONG == 32 # define LONGSIZE 32 # elif _MIPS_SZLONG == 64 # define LONGSIZE 64 # else # error "can't handle long size given by _MIPS_SZLONG" # endif /* ============================================================== */ /* the following are all 32-bit byteswapped platforms */ #elif defined(vax) && defined(VMS) #define MACHINE VAXVMS #define BYTESWAPPED TRUE #elif defined(__alpha) && defined(__VMS) #if (__D_FLOAT == TRUE) /* this float option is the same as for VAX/VMS machines. */ #define MACHINE VAXVMS #define BYTESWAPPED TRUE #elif (__G_FLOAT == TRUE) /* G_FLOAT is the default for ALPHA VMS systems */ #define MACHINE ALPHAVMS #define BYTESWAPPED TRUE #define FLOATTYPE GFLOAT #elif (__IEEE_FLOAT == TRUE) #define MACHINE ALPHAVMS #define BYTESWAPPED TRUE #define FLOATTYPE IEEEFLOAT #endif /* end of alpha VMS case */ #elif defined(ultrix) && defined(unix) /* old Dec ultrix machines */ #define BYTESWAPPED TRUE #elif defined(__i386) || defined(__i386__) || defined(__i486__) || defined(__i586__) \ || defined(_MSC_VER) || defined(__BORLANDC__) || defined(__TURBOC__) \ || defined(_NI_mswin_) || defined(__EMX__) /* generic 32-bit IBM PC */ #define MACHINE IBMPC #define BYTESWAPPED TRUE #elif defined(__arm__) /* This assumes all ARM are little endian. In the future, it might be */ /* necessary to use "if defined(__ARMEL__)" to distinguish little from big. */ /* (__ARMEL__ would be defined on little-endian, but not on big-endian). */ #define BYTESWAPPED TRUE #elif defined(__tile__) /* 64-core 8x8-architecture Tile64 platform */ #define BYTESWAPPED TRUE #elif defined(__sh__) /* SuperH CPU can be used in both little and big endian modes */ #if defined(__LITTLE_ENDIAN__) #define BYTESWAPPED TRUE #else #define BYTESWAPPED FALSE #endif #else /* assume all other machine uses the same IEEE formats as used in FITS files */ /* e.g., Macs fall into this category */ #define MACHINE NATIVE #define BYTESWAPPED FALSE #endif #ifndef MACHINE #define MACHINE OTHERTYPE #endif /* assume longs are 4 bytes long, unless previously set otherwise */ #ifndef LONGSIZE #define LONGSIZE 32 #endif /* end of block that determine long size and byte swapping */ /* ==================================================================== */ #define IGNORE_EOF 1 #define REPORT_EOF 0 #define DATA_UNDEFINED -1 #define NULL_UNDEFINED 1234554321 #define ASCII_NULL_UNDEFINED 1 /* indicate no defined null value */ #define maxvalue(A,B) ((A) > (B) ? (A) : (B)) #define minvalue(A,B) ((A) < (B) ? (A) : (B)) /* faster string comparison macros */ #define FSTRCMP(a,b) ((a)[0]<(b)[0]? -1:(a)[0]>(b)[0]?1:strcmp((a),(b))) #define FSTRNCMP(a,b,n) ((a)[0]<(b)[0]?-1:(a)[0]>(b)[0]?1:strncmp((a),(b),(n))) #if defined(__VMS) || defined(VMS) #define FNANMASK 0xFFFF /* mask all bits */ #define DNANMASK 0xFFFF /* mask all bits */ #else #define FNANMASK 0x7F80 /* mask bits 1 - 8; all set on NaNs */ /* all 0 on underflow or 0. */ #define DNANMASK 0x7FF0 /* mask bits 1 - 11; all set on NaNs */ /* all 0 on underflow or 0. */ #endif #if MACHINE == CRAY /* Cray machines: the large negative integer corresponds to the 3 most sig digits set to 1. If these 3 bits are set in a floating point number (64 bits), then it represents a reserved value (i.e., a NaN) */ #define fnan(L) ( (L) >= 0xE000000000000000 ? 1 : 0) ) #else /* these functions work for both big and little endian machines */ /* that use the IEEE floating point format for internal numbers */ /* These functions tests whether the float value is a reserved IEEE */ /* value such as a Not-a-Number (NaN), or underflow, overflow, or */ /* infinity. The functions returns 1 if the value is a NaN, overflow */ /* or infinity; it returns 2 if the value is an denormalized underflow */ /* value; otherwise it returns 0. fnan tests floats, dnan tests doubles */ #define fnan(L) \ ( (L & FNANMASK) == FNANMASK ? 1 : (L & FNANMASK) == 0 ? 2 : 0) #define dnan(L) \ ( (L & DNANMASK) == DNANMASK ? 1 : (L & DNANMASK) == 0 ? 2 : 0) #endif #define DSCHAR_MAX 127.49 /* max double value that fits in an signed char */ #define DSCHAR_MIN -128.49 /* min double value that fits in an signed char */ #define DUCHAR_MAX 255.49 /* max double value that fits in an unsigned char */ #define DUCHAR_MIN -0.49 /* min double value that fits in an unsigned char */ #define DUSHRT_MAX 65535.49 /* max double value that fits in a unsigned short*/ #define DUSHRT_MIN -0.49 /* min double value that fits in an unsigned short */ #define DSHRT_MAX 32767.49 /* max double value that fits in a short */ #define DSHRT_MIN -32768.49 /* min double value that fits in a short */ #if LONGSIZE == 32 # define DLONG_MAX 2147483647.49 /* max double value that fits in a long */ # define DLONG_MIN -2147483648.49 /* min double value that fits in a long */ # define DULONG_MAX 4294967295.49 /* max double that fits in a unsigned long */ #else # define DLONG_MAX 9.2233720368547752E18 /* max double value long */ # define DLONG_MIN -9.2233720368547752E18 /* min double value long */ # define DULONG_MAX 1.84467440737095504E19 /* max double value ulong */ #endif #define DULONG_MIN -0.49 /* min double value that fits in an unsigned long */ #define DLONGLONG_MAX 9.2233720368547755807E18 /* max double value longlong */ #define DLONGLONG_MIN -9.2233720368547755808E18 /* min double value longlong */ #define DUINT_MAX 4294967295.49 /* max dbl that fits in a unsigned 4-byte int */ #define DUINT_MIN -0.49 /* min dbl that fits in an unsigned 4-byte int */ #define DINT_MAX 2147483647.49 /* max double value that fits in a 4-byte int */ #define DINT_MIN -2147483648.49 /* min double value that fits in a 4-byte int */ #ifndef UINT32_MAX #define UINT32_MAX 4294967295U /* max unsigned 32-bit integer */ #endif #ifndef INT32_MAX #define INT32_MAX 2147483647 /* max 32-bit integer */ #endif #ifndef INT32_MIN #define INT32_MIN (-INT32_MAX -1) /* min 32-bit integer */ #endif #define COMPRESS_NULL_VALUE -2147483647 #define N_RANDOM 10000 /* DO NOT CHANGE THIS; used when quantizing real numbers */ int ffgnky(fitsfile *fptr, char *card, int *status); void ffcfmt(char *tform, char *cform); void ffcdsp(char *tform, char *cform); void ffswap2(short *values, long nvalues); void ffswap4(INT32BIT *values, long nvalues); void ffswap8(double *values, long nvalues); int ffi2c(LONGLONG ival, char *cval, int *status); int ffl2c(int lval, char *cval, int *status); int ffs2c(const char *instr, char *outstr, int *status); int ffr2f(float fval, int decim, char *cval, int *status); int ffr2e(float fval, int decim, char *cval, int *status); int ffd2f(double dval, int decim, char *cval, int *status); int ffd2e(double dval, int decim, char *cval, int *status); int ffc2ii(const char *cval, long *ival, int *status); int ffc2jj(const char *cval, LONGLONG *ival, int *status); int ffc2ll(const char *cval, int *lval, int *status); int ffc2rr(const char *cval, float *fval, int *status); int ffc2dd(const char *cval, double *dval, int *status); int ffc2x(const char *cval, char *dtype, long *ival, int *lval, char *sval, double *dval, int *status); int ffc2xx(const char *cval, char *dtype, LONGLONG *ival, int *lval, char *sval, double *dval, int *status); int ffc2s(const char *instr, char *outstr, int *status); int ffc2i(const char *cval, long *ival, int *status); int ffc2j(const char *cval, LONGLONG *ival, int *status); int ffc2r(const char *cval, float *fval, int *status); int ffc2d(const char *cval, double *dval, int *status); int ffc2l(const char *cval, int *lval, int *status); void ffxmsg(int action, char *err_message); int ffgcnt(fitsfile *fptr, char *value, char *comm, int *status); int ffgtkn(fitsfile *fptr, int numkey, char *keyname, long *value, int *status); int ffgtknjj(fitsfile *fptr, int numkey, char *keyname, LONGLONG *value, int *status); int fftkyn(fitsfile *fptr, int numkey, char *keyname, char *value, int *status); int ffgphd(fitsfile *fptr, int maxdim, int *simple, int *bitpix, int *naxis, LONGLONG naxes[], long *pcount, long *gcount, int *extend, double *bscale, double *bzero, LONGLONG *blank, int *nspace, int *status); int ffgttb(fitsfile *fptr, LONGLONG *rowlen, LONGLONG *nrows, LONGLONG *pcount, long *tfield, int *status); int ffmkey(fitsfile *fptr, const char *card, int *status); /* ffmbyt has been moved to fitsio.h */ int ffgbyt(fitsfile *fptr, LONGLONG nbytes, void *buffer, int *status); int ffpbyt(fitsfile *fptr, LONGLONG nbytes, void *buffer, int *status); int ffgbytoff(fitsfile *fptr, long gsize, long ngroups, long offset, void *buffer, int *status); int ffpbytoff(fitsfile *fptr, long gsize, long ngroups, long offset, void *buffer, int *status); int ffldrc(fitsfile *fptr, long record, int err_mode, int *status); int ffwhbf(fitsfile *fptr, int *nbuff); int ffbfeof(fitsfile *fptr, int *status); int ffbfwt(FITSfile *Fptr, int nbuff, int *status); int ffpxsz(int datatype); int ffourl(char *url, char *urltype, char *outfile, char *tmplfile, char *compspec, int *status); int ffparsecompspec(fitsfile *fptr, char *compspec, int *status); int ffoptplt(fitsfile *fptr, const char *tempname, int *status); int fits_is_this_a_copy(char *urltype); int fits_store_Fptr(FITSfile *Fptr, int *status); int fits_clear_Fptr(FITSfile *Fptr, int *status); int fits_already_open(fitsfile **fptr, char *url, char *urltype, char *infile, char *extspec, char *rowfilter, char *binspec, char *colspec, int mode,int *isopen, int *status); int ffedit_columns(fitsfile **fptr, char *outfile, char *expr, int *status); int fits_get_col_minmax(fitsfile *fptr, int colnum, float *datamin, float *datamax, int *status); int ffwritehisto(long totaln, long offset, long firstn, long nvalues, int narrays, iteratorCol *imagepars, void *userPointer); int ffcalchist(long totalrows, long offset, long firstrow, long nrows, int ncols, iteratorCol *colpars, void *userPointer); int ffpinit(fitsfile *fptr, int *status); int ffainit(fitsfile *fptr, int *status); int ffbinit(fitsfile *fptr, int *status); int ffchdu(fitsfile *fptr, int *status); int ffwend(fitsfile *fptr, int *status); int ffpdfl(fitsfile *fptr, int *status); int ffuptf(fitsfile *fptr, int *status); int ffdblk(fitsfile *fptr, long nblocks, int *status); int ffgext(fitsfile *fptr, int moveto, int *exttype, int *status); int ffgtbc(fitsfile *fptr, LONGLONG *totalwidth, int *status); int ffgtbp(fitsfile *fptr, char *name, char *value, int *status); int ffiblk(fitsfile *fptr, long nblock, int headdata, int *status); int ffshft(fitsfile *fptr, LONGLONG firstbyte, LONGLONG nbytes, LONGLONG nshift, int *status); int ffgcprll(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, int writemode, double *scale, double *zero, char *tform, long *twidth, int *tcode, int *maxelem, LONGLONG *startpos, LONGLONG *elemnum, long *incre, LONGLONG *repeat, LONGLONG *rowlen, int *hdutype, LONGLONG *tnull, char *snull, int *status); int ffflushx(FITSfile *fptr); int ffseek(FITSfile *fptr, LONGLONG position); int ffread(FITSfile *fptr, long nbytes, void *buffer, int *status); int ffwrite(FITSfile *fptr, long nbytes, void *buffer, int *status); int fftrun(fitsfile *fptr, LONGLONG filesize, int *status); int ffpcluc(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, int *status); int ffgcll(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, int nultyp, char nulval, char *array, char *nularray, int *anynul, int *status); int ffgcls(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, int nultyp, char *nulval, char **array, char *nularray, int *anynul, int *status); int ffgcls2(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, int nultyp, char *nulval, char **array, char *nularray, int *anynul, int *status); int ffgclb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long elemincre, int nultyp, unsigned char nulval, unsigned char *array, char *nularray, int *anynul, int *status); int ffgclsb(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long elemincre, int nultyp, signed char nulval, signed char *array, char *nularray, int *anynul, int *status); int ffgclui(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long elemincre, int nultyp, unsigned short nulval, unsigned short *array, char *nularray, int *anynul, int *status); int ffgcli(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long elemincre, int nultyp, short nulval, short *array, char *nularray, int *anynul, int *status); int ffgcluj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long elemincre, int nultyp, unsigned long nulval, unsigned long *array, char *nularray, int *anynul, int *status); int ffgcljj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long elemincre, int nultyp, LONGLONG nulval, LONGLONG *array, char *nularray, int *anynul, int *status); int ffgclj(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long elemincre, int nultyp, long nulval, long *array, char *nularray, int *anynul, int *status); int ffgcluk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long elemincre, int nultyp, unsigned int nulval, unsigned int *array, char *nularray, int *anynul, int *status); int ffgclk(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long elemincre, int nultyp, int nulval, int *array, char *nularray, int *anynul, int *status); int 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); int ffgcld(fitsfile *fptr, int colnum, LONGLONG firstrow, LONGLONG firstelem, LONGLONG nelem, long elemincre, int nultyp, double nulval, double *array, char *nularray, int *anynul, int *status); int ffpi1b(fitsfile *fptr, long nelem, long incre, unsigned char *buffer, int *status); int ffpi2b(fitsfile *fptr, long nelem, long incre, short *buffer, int *status); int ffpi4b(fitsfile *fptr, long nelem, long incre, INT32BIT *buffer, int *status); int ffpi8b(fitsfile *fptr, long nelem, long incre, long *buffer, int *status); int ffpr4b(fitsfile *fptr, long nelem, long incre, float *buffer, int *status); int ffpr8b(fitsfile *fptr, long nelem, long incre, double *buffer, int *status); int ffgi1b(fitsfile *fptr, LONGLONG pos, long nelem, long incre, unsigned char *buffer, int *status); int ffgi2b(fitsfile *fptr, LONGLONG pos, long nelem, long incre, short *buffer, int *status); int ffgi4b(fitsfile *fptr, LONGLONG pos, long nelem, long incre, INT32BIT *buffer, int *status); int ffgi8b(fitsfile *fptr, LONGLONG pos, long nelem, long incre, long *buffer, int *status); int ffgr4b(fitsfile *fptr, LONGLONG pos, long nelem, long incre, float *buffer, int *status); int ffgr8b(fitsfile *fptr, LONGLONG pos, long nelem, long incre, double *buffer, int *status); int ffcins(fitsfile *fptr, LONGLONG naxis1, LONGLONG naxis2, LONGLONG nbytes, LONGLONG bytepos, int *status); int ffcdel(fitsfile *fptr, LONGLONG naxis1, LONGLONG naxis2, LONGLONG nbytes, LONGLONG bytepos, int *status); int ffkshf(fitsfile *fptr, int firstcol, int tfields, int nshift, int *status); int fffi1i1(unsigned char *input, long ntodo, double scale, double zero, int nullcheck, unsigned char tnull, unsigned char nullval, char *nullarray, int *anynull, unsigned char *output, int *status); int fffi2i1(short *input, long ntodo, double scale, double zero, int nullcheck, short tnull, unsigned char nullval, char *nullarray, int *anynull, unsigned char *output, int *status); int fffi4i1(INT32BIT *input, long ntodo, double scale, double zero, int nullcheck, INT32BIT tnull, unsigned char nullval, char *nullarray, int *anynull, unsigned char *output, int *status); int fffi8i1(LONGLONG *input, long ntodo, double scale, double zero, int nullcheck, LONGLONG tnull, unsigned char nullval, char *nullarray, int *anynull, unsigned char *output, int *status); int fffr4i1(float *input, long ntodo, double scale, double zero, int nullcheck, unsigned char nullval, char *nullarray, int *anynull, unsigned char *output, int *status); int fffr8i1(double *input, long ntodo, double scale, double zero, int nullcheck, unsigned char nullval, char *nullarray, int *anynull, unsigned char *output, int *status); int fffstri1(char *input, long ntodo, double scale, double zero, long twidth, double power, int nullcheck, char *snull, unsigned char nullval, char *nullarray, int *anynull, unsigned char *output, int *status); int fffi1s1(unsigned char *input, long ntodo, double scale, double zero, int nullcheck, unsigned char tnull, signed char nullval, char *nullarray, int *anynull, signed char *output, int *status); int fffi2s1(short *input, long ntodo, double scale, double zero, int nullcheck, short tnull, signed char nullval, char *nullarray, int *anynull, signed char *output, int *status); int fffi4s1(INT32BIT *input, long ntodo, double scale, double zero, int nullcheck, INT32BIT tnull, signed char nullval, char *nullarray, int *anynull, signed char *output, int *status); int fffi8s1(LONGLONG *input, long ntodo, double scale, double zero, int nullcheck, LONGLONG tnull, signed char nullval, char *nullarray, int *anynull, signed char *output, int *status); int fffr4s1(float *input, long ntodo, double scale, double zero, int nullcheck, signed char nullval, char *nullarray, int *anynull, signed char *output, int *status); int fffr8s1(double *input, long ntodo, double scale, double zero, int nullcheck, signed char nullval, char *nullarray, int *anynull, signed char *output, int *status); int fffstrs1(char *input, long ntodo, double scale, double zero, long twidth, double power, int nullcheck, char *snull, signed char nullval, char *nullarray, int *anynull, signed char *output, int *status); int fffi1u2(unsigned char *input, long ntodo, double scale, double zero, int nullcheck, unsigned char tnull, unsigned short nullval, char *nullarray, int *anynull, unsigned short *output, int *status); int fffi2u2(short *input, long ntodo, double scale, double zero, int nullcheck, short tnull, unsigned short nullval, char *nullarray, int *anynull, unsigned short *output, int *status); int fffi4u2(INT32BIT *input, long ntodo, double scale, double zero, int nullcheck, INT32BIT tnull, unsigned short nullval, char *nullarray, int *anynull, unsigned short *output, int *status); int fffi8u2(LONGLONG *input, long ntodo, double scale, double zero, int nullcheck, LONGLONG tnull, unsigned short nullval, char *nullarray, int *anynull, unsigned short *output, int *status); int fffr4u2(float *input, long ntodo, double scale, double zero, int nullcheck, unsigned short nullval, char *nullarray, int *anynull, unsigned short *output, int *status); int fffr8u2(double *input, long ntodo, double scale, double zero, int nullcheck, unsigned short nullval, char *nullarray, int *anynull, unsigned short *output, int *status); int fffstru2(char *input, long ntodo, double scale, double zero, long twidth, double power, int nullcheck, char *snull, unsigned short nullval, char *nullarray, int *anynull, unsigned short *output, int *status); int fffi1i2(unsigned char *input, long ntodo, double scale, double zero, int nullcheck, unsigned char tnull, short nullval, char *nullarray, int *anynull, short *output, int *status); int fffi2i2(short *input, long ntodo, double scale, double zero, int nullcheck, short tnull, short nullval, char *nullarray, int *anynull, short *output, int *status); int fffi4i2(INT32BIT *input, long ntodo, double scale, double zero, int nullcheck, INT32BIT tnull, short nullval, char *nullarray, int *anynull, short *output, int *status); int fffi8i2(LONGLONG *input, long ntodo, double scale, double zero, int nullcheck, LONGLONG tnull, short nullval, char *nullarray, int *anynull, short *output, int *status); int fffr4i2(float *input, long ntodo, double scale, double zero, int nullcheck, short nullval, char *nullarray, int *anynull, short *output, int *status); int fffr8i2(double *input, long ntodo, double scale, double zero, int nullcheck, short nullval, char *nullarray, int *anynull, short *output, int *status); int fffstri2(char *input, long ntodo, double scale, double zero, long twidth, double power, int nullcheck, char *snull, short nullval, char *nullarray, int *anynull, short *output, int *status); int fffi1u4(unsigned char *input, long ntodo, double scale, double zero, int nullcheck, unsigned char tnull, unsigned long nullval, char *nullarray, int *anynull, unsigned long *output, int *status); int fffi2u4(short *input, long ntodo, double scale, double zero, int nullcheck, short tnull, unsigned long nullval, char *nullarray, int *anynull, unsigned long *output, int *status); int fffi4u4(INT32BIT *input, long ntodo, double scale, double zero, int nullcheck, INT32BIT tnull, unsigned long nullval, char *nullarray, int *anynull, unsigned long *output, int *status); int fffi8u4(LONGLONG *input, long ntodo, double scale, double zero, int nullcheck, LONGLONG tnull, unsigned long nullval, char *nullarray, int *anynull, unsigned long *output, int *status); int fffr4u4(float *input, long ntodo, double scale, double zero, int nullcheck, unsigned long nullval, char *nullarray, int *anynull, unsigned long *output, int *status); int fffr8u4(double *input, long ntodo, double scale, double zero, int nullcheck, unsigned long nullval, char *nullarray, int *anynull, unsigned long *output, int *status); int fffstru4(char *input, long ntodo, double scale, double zero, long twidth, double power, int nullcheck, char *snull, unsigned long nullval, char *nullarray, int *anynull, unsigned long *output, int *status); int fffi1i4(unsigned char *input, long ntodo, double scale, double zero, int nullcheck, unsigned char tnull, long nullval, char *nullarray, int *anynull, long *output, int *status); int fffi2i4(short *input, long ntodo, double scale, double zero, int nullcheck, short tnull, long nullval, char *nullarray, int *anynull, long *output, int *status); int fffi4i4(INT32BIT *input, long ntodo, double scale, double zero, int nullcheck, INT32BIT tnull, long nullval, char *nullarray, int *anynull, long *output, int *status); int fffi8i4(LONGLONG *input, long ntodo, double scale, double zero, int nullcheck, LONGLONG tnull, long nullval, char *nullarray, int *anynull, long *output, int *status); int fffr4i4(float *input, long ntodo, double scale, double zero, int nullcheck, long nullval, char *nullarray, int *anynull, long *output, int *status); int fffr8i4(double *input, long ntodo, double scale, double zero, int nullcheck, long nullval, char *nullarray, int *anynull, long *output, int *status); int fffstri4(char *input, long ntodo, double scale, double zero, long twidth, double power, int nullcheck, char *snull, long nullval, char *nullarray, int *anynull, long *output, int *status); int fffi1int(unsigned char *input, long ntodo, double scale, double zero, int nullcheck, unsigned char tnull, int nullval, char *nullarray, int *anynull, int *output, int *status); int fffi2int(short *input, long ntodo, double scale, double zero, int nullcheck, short tnull, int nullval, char *nullarray, int *anynull, int *output, int *status); int fffi4int(INT32BIT *input, long ntodo, double scale, double zero, int nullcheck, INT32BIT tnull, int nullval, char *nullarray, int *anynull, int *output, int *status); int fffi8int(LONGLONG *input, long ntodo, double scale, double zero, int nullcheck, LONGLONG tnull, int nullval, char *nullarray, int *anynull, int *output, int *status); int fffr4int(float *input, long ntodo, double scale, double zero, int nullcheck, int nullval, char *nullarray, int *anynull, int *output, int *status); int fffr8int(double *input, long ntodo, double scale, double zero, int nullcheck, int nullval, char *nullarray, int *anynull, int *output, int *status); int fffstrint(char *input, long ntodo, double scale, double zero, long twidth, double power, int nullcheck, char *snull, int nullval, char *nullarray, int *anynull, int *output, int *status); int fffi1uint(unsigned char *input, long ntodo, double scale, double zero, int nullcheck, unsigned char tnull, unsigned int nullval, char *nullarray, int *anynull, unsigned int *output, int *status); int fffi2uint(short *input, long ntodo, double scale, double zero, int nullcheck, short tnull, unsigned int nullval, char *nullarray, int *anynull, unsigned int *output, int *status); int fffi4uint(INT32BIT *input, long ntodo, double scale, double zero, int nullcheck, INT32BIT tnull, unsigned int nullval, char *nullarray, int *anynull, unsigned int *output, int *status); int fffi8uint(LONGLONG *input, long ntodo, double scale, double zero, int nullcheck, LONGLONG tnull, unsigned int nullval, char *nullarray, int *anynull, unsigned int *output, int *status); int fffr4uint(float *input, long ntodo, double scale, double zero, int nullcheck, unsigned int nullval, char *nullarray, int *anynull, unsigned int *output, int *status); int fffr8uint(double *input, long ntodo, double scale, double zero, int nullcheck, unsigned int nullval, char *nullarray, int *anynull, unsigned int *output, int *status); int fffstruint(char *input, long ntodo, double scale, double zero, long twidth, double power, int nullcheck, char *snull, unsigned int nullval, char *nullarray, int *anynull, unsigned int *output, int *status); int fffi1i8(unsigned char *input, long ntodo, double scale, double zero, int nullcheck, unsigned char tnull, LONGLONG nullval, char *nullarray, int *anynull, LONGLONG *output, int *status); int fffi2i8(short *input, long ntodo, double scale, double zero, int nullcheck, short tnull, LONGLONG nullval, char *nullarray, int *anynull, LONGLONG *output, int *status); int fffi4i8(INT32BIT *input, long ntodo, double scale, double zero, int nullcheck, INT32BIT tnull, LONGLONG nullval, char *nullarray, int *anynull, LONGLONG *output, int *status); int fffi8i8(LONGLONG *input, long ntodo, double scale, double zero, int nullcheck, LONGLONG tnull, LONGLONG nullval, char *nullarray, int *anynull, LONGLONG *output, int *status); int fffr4i8(float *input, long ntodo, double scale, double zero, int nullcheck, LONGLONG nullval, char *nullarray, int *anynull, LONGLONG *output, int *status); int fffr8i8(double *input, long ntodo, double scale, double zero, int nullcheck, LONGLONG nullval, char *nullarray, int *anynull, LONGLONG *output, int *status); int fffstri8(char *input, long ntodo, double scale, double zero, long twidth, double power, int nullcheck, char *snull, LONGLONG nullval, char *nullarray, int *anynull, LONGLONG *output, int *status); int 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); int fffi2r4(short *input, long ntodo, double scale, double zero, int nullcheck, short tnull, float nullval, char *nullarray, int *anynull, float *output, int *status); int fffi4r4(INT32BIT *input, long ntodo, double scale, double zero, int nullcheck, INT32BIT tnull, float nullval, char *nullarray, int *anynull, float *output, int *status); int fffi8r4(LONGLONG *input, long ntodo, double scale, double zero, int nullcheck, LONGLONG tnull, float nullval, char *nullarray, int *anynull, float *output, int *status); int fffr4r4(float *input, long ntodo, double scale, double zero, int nullcheck, float nullval, char *nullarray, int *anynull, float *output, int *status); int fffr8r4(double *input, long ntodo, double scale, double zero, int nullcheck, float nullval, char *nullarray, int *anynull, float *output, int *status); int fffstrr4(char *input, long ntodo, double scale, double zero, long twidth, double power, int nullcheck, char *snull, float nullval, char *nullarray, int *anynull, float *output, int *status); int fffi1r8(unsigned char *input, long ntodo, double scale, double zero, int nullcheck, unsigned char tnull, double nullval, char *nullarray, int *anynull, double *output, int *status); int fffi2r8(short *input, long ntodo, double scale, double zero, int nullcheck, short tnull, double nullval, char *nullarray, int *anynull, double *output, int *status); int fffi4r8(INT32BIT *input, long ntodo, double scale, double zero, int nullcheck, INT32BIT tnull, double nullval, char *nullarray, int *anynull, double *output, int *status); int fffi8r8(LONGLONG *input, long ntodo, double scale, double zero, int nullcheck, LONGLONG tnull, double nullval, char *nullarray, int *anynull, double *output, int *status); int fffr4r8(float *input, long ntodo, double scale, double zero, int nullcheck, double nullval, char *nullarray, int *anynull, double *output, int *status); int fffr8r8(double *input, long ntodo, double scale, double zero, int nullcheck, double nullval, char *nullarray, int *anynull, double *output, int *status); int fffstrr8(char *input, long ntodo, double scale, double zero, long twidth, double power, int nullcheck, char *snull, double nullval, char *nullarray, int *anynull, double *output, int *status); int ffi1fi1(unsigned char *array, long ntodo, double scale, double zero, unsigned char *buffer, int *status); int ffs1fi1(signed char *array, long ntodo, double scale, double zero, unsigned char *buffer, int *status); int ffu2fi1(unsigned short *array, long ntodo, double scale, double zero, unsigned char *buffer, int *status); int ffi2fi1(short *array, long ntodo, double scale, double zero, unsigned char *buffer, int *status); int ffu4fi1(unsigned long *array, long ntodo, double scale, double zero, unsigned char *buffer, int *status); int ffi4fi1(long *array, long ntodo, double scale, double zero, unsigned char *buffer, int *status); int ffi8fi1(LONGLONG *array, long ntodo, double scale, double zero, unsigned char *buffer, int *status); int ffuintfi1(unsigned int *array, long ntodo, double scale, double zero, unsigned char *buffer, int *status); int ffintfi1(int *array, long ntodo, double scale, double zero, unsigned char *buffer, int *status); int ffr4fi1(float *array, long ntodo, double scale, double zero, unsigned char *buffer, int *status); int ffr8fi1(double *array, long ntodo, double scale, double zero, unsigned char *buffer, int *status); int ffi1fi2(unsigned char *array, long ntodo, double scale, double zero, short *buffer, int *status); int ffs1fi2(signed char *array, long ntodo, double scale, double zero, short *buffer, int *status); int ffu2fi2(unsigned short *array, long ntodo, double scale, double zero, short *buffer, int *status); int ffi2fi2(short *array, long ntodo, double scale, double zero, short *buffer, int *status); int ffu4fi2(unsigned long *array, long ntodo, double scale, double zero, short *buffer, int *status); int ffi4fi2(long *array, long ntodo, double scale, double zero, short *buffer, int *status); int ffi8fi2(LONGLONG *array, long ntodo, double scale, double zero, short *buffer, int *status); int ffuintfi2(unsigned int *array, long ntodo, double scale, double zero, short *buffer, int *status); int ffintfi2(int *array, long ntodo, double scale, double zero, short *buffer, int *status); int ffr4fi2(float *array, long ntodo, double scale, double zero, short *buffer, int *status); int ffr8fi2(double *array, long ntodo, double scale, double zero, short *buffer, int *status); int ffi1fi4(unsigned char *array, long ntodo, double scale, double zero, INT32BIT *buffer, int *status); int ffs1fi4(signed char *array, long ntodo, double scale, double zero, INT32BIT *buffer, int *status); int ffu2fi4(unsigned short *array, long ntodo, double scale, double zero, INT32BIT *buffer, int *status); int ffi2fi4(short *array, long ntodo, double scale, double zero, INT32BIT *buffer, int *status); int ffu4fi4(unsigned long *array, long ntodo, double scale, double zero, INT32BIT *buffer, int *status); int ffi4fi4(long *array, long ntodo, double scale, double zero, INT32BIT *buffer, int *status); int ffi8fi4(LONGLONG *array, long ntodo, double scale, double zero, INT32BIT *buffer, int *status); int ffuintfi4(unsigned int *array, long ntodo, double scale, double zero, INT32BIT *buffer, int *status); int ffintfi4(int *array, long ntodo, double scale, double zero, INT32BIT *buffer, int *status); int ffr4fi4(float *array, long ntodo, double scale, double zero, INT32BIT *buffer, int *status); int ffr8fi4(double *array, long ntodo, double scale, double zero, INT32BIT *buffer, int *status); int fflongfi8(long *array, long ntodo, double scale, double zero, LONGLONG *buffer, int *status); int ffi8fi8(LONGLONG *array, long ntodo, double scale, double zero, LONGLONG *buffer, int *status); int ffi2fi8(short *array, long ntodo, double scale, double zero, LONGLONG *buffer, int *status); int ffi1fi8(unsigned char *array, long ntodo, double scale, double zero, LONGLONG *buffer, int *status); int ffs1fi8(signed char *array, long ntodo, double scale, double zero, LONGLONG *buffer, int *status); int ffr4fi8(float *array, long ntodo, double scale, double zero, LONGLONG *buffer, int *status); int ffr8fi8(double *array, long ntodo, double scale, double zero, LONGLONG *buffer, int *status); int ffintfi8(int *array, long ntodo, double scale, double zero, LONGLONG *buffer, int *status); int ffu2fi8(unsigned short *array, long ntodo, double scale, double zero, LONGLONG *buffer, int *status); int ffu4fi8(unsigned long *array, long ntodo, double scale, double zero, LONGLONG *buffer, int *status); int ffuintfi8(unsigned int *array, long ntodo, double scale, double zero, LONGLONG *buffer, int *status); int ffi1fr4(unsigned char *array, long ntodo, double scale, double zero, float *buffer, int *status); int ffs1fr4(signed char *array, long ntodo, double scale, double zero, float *buffer, int *status); int ffu2fr4(unsigned short *array, long ntodo, double scale, double zero, float *buffer, int *status); int ffi2fr4(short *array, long ntodo, double scale, double zero, float *buffer, int *status); int ffu4fr4(unsigned long *array, long ntodo, double scale, double zero, float *buffer, int *status); int ffi4fr4(long *array, long ntodo, double scale, double zero, float *buffer, int *status); int ffi8fr4(LONGLONG *array, long ntodo, double scale, double zero, float *buffer, int *status); int ffuintfr4(unsigned int *array, long ntodo, double scale, double zero, float *buffer, int *status); int ffintfr4(int *array, long ntodo, double scale, double zero, float *buffer, int *status); int ffr4fr4(float *array, long ntodo, double scale, double zero, float *buffer, int *status); int ffr8fr4(double *array, long ntodo, double scale, double zero, float *buffer, int *status); int ffi1fr8(unsigned char *array, long ntodo, double scale, double zero, double *buffer, int *status); int ffs1fr8(signed char *array, long ntodo, double scale, double zero, double *buffer, int *status); int ffu2fr8(unsigned short *array, long ntodo, double scale, double zero, double *buffer, int *status); int ffi2fr8(short *array, long ntodo, double scale, double zero, double *buffer, int *status); int ffu4fr8(unsigned long *array, long ntodo, double scale, double zero, double *buffer, int *status); int ffi4fr8(long *array, long ntodo, double scale, double zero, double *buffer, int *status); int ffi8fr8(LONGLONG *array, long ntodo, double scale, double zero, double *buffer, int *status); int ffuintfr8(unsigned int *array, long ntodo, double scale, double zero, double *buffer, int *status); int ffintfr8(int *array, long ntodo, double scale, double zero, double *buffer, int *status); int ffr4fr8(float *array, long ntodo, double scale, double zero, double *buffer, int *status); int ffr8fr8(double *array, long ntodo, double scale, double zero, double *buffer, int *status); int ffi1fstr(unsigned char *input, long ntodo, double scale, double zero, char *cform, long twidth, char *output, int *status); int ffs1fstr(signed char *input, long ntodo, double scale, double zero, char *cform, long twidth, char *output, int *status); int ffu2fstr(unsigned short *input, long ntodo, double scale, double zero, char *cform, long twidth, char *output, int *status); int ffi2fstr(short *input, long ntodo, double scale, double zero, char *cform, long twidth, char *output, int *status); int ffu4fstr(unsigned long *input, long ntodo, double scale, double zero, char *cform, long twidth, char *output, int *status); int ffi4fstr(long *input, long ntodo, double scale, double zero, char *cform, long twidth, char *output, int *status); int ffi8fstr(LONGLONG *input, long ntodo, double scale, double zero, char *cform, long twidth, char *output, int *status); int ffintfstr(int *input, long ntodo, double scale, double zero, char *cform, long twidth, char *output, int *status); int ffuintfstr(unsigned int *input, long ntodo, double scale, double zero, char *cform, long twidth, char *output, int *status); int ffr4fstr(float *input, long ntodo, double scale, double zero, char *cform, long twidth, char *output, int *status); int ffr8fstr(double *input, long ntodo, double scale, double zero, char *cform, long twidth, char *output, int *status); /* the following 4 routines are VMS macros used on VAX or Alpha VMS */ void ieevpd(double *inarray, double *outarray, long *nvals); void ieevud(double *inarray, double *outarray, long *nvals); void ieevpr(float *inarray, float *outarray, long *nvals); void ieevur(float *inarray, float *outarray, long *nvals); /* routines related to the lexical parser */ int ffselect_table(fitsfile **fptr, char *outfile, char *expr, int *status); int ffiprs( fitsfile *fptr, int compressed, char *expr, int maxdim, int *datatype, long *nelem, int *naxis, long *naxes, int *status ); void ffcprs( void ); int ffcvtn( int inputType, void *input, char *undef, long ntodo, int outputType, void *nulval, void *output, int *anynull, int *status ); int parse_data( long totalrows, long offset, long firstrow, long nrows, int nCols, iteratorCol *colData, void *userPtr ); int uncompress_hkdata( fitsfile *fptr, long ntimes, double *times, int *status ); int ffffrw_work( long totalrows, long offset, long firstrow, long nrows, int nCols, iteratorCol *colData, void *userPtr ); int fits_translate_pixkeyword(char *inrec, char *outrec,char *patterns[][2], int npat, int naxis, int *colnum, int *pat_num, int *i, int *j, int *n, int *m, int *l, int *status); /* image compression routines */ int fits_write_compressed_img(fitsfile *fptr, int datatype, long *fpixel, long *lpixel, int nullcheck, void *array, void *nulval, int *status); int fits_write_compressed_pixels(fitsfile *fptr, int datatype, LONGLONG fpixel, LONGLONG npixels, int nullcheck, void *array, void *nulval, int *status); int fits_write_compressed_img_plane(fitsfile *fptr, int datatype, int bytesperpixel, long nplane, long *firstcoord, long *lastcoord, long *naxes, int nullcheck, void *array, void *nullval, long *nread, int *status); int imcomp_init_table(fitsfile *outfptr, int bitpix, int naxis,long *naxes, int writebitpix, int *status); int imcomp_calc_max_elem (int comptype, int nx, int zbitpix, int blocksize); int imcomp_copy_imheader(fitsfile *infptr, fitsfile *outfptr, int *status); int imcomp_copy_img2comp(fitsfile *infptr, fitsfile *outfptr, int *status); int imcomp_copy_comp2img(fitsfile *infptr, fitsfile *outfptr, int norec, int *status); int imcomp_copy_prime2img(fitsfile *infptr, fitsfile *outfptr, int *status); int imcomp_compress_image (fitsfile *infptr, fitsfile *outfptr, int *status); int imcomp_compress_tile (fitsfile *outfptr, long row, int datatype, void *tiledata, long tilelen, long nx, long ny, int nullcheck, void *nullval, int *status); int imcomp_nullscale(int *idata, long tilelen, int nullflagval, int nullval, double scale, double zero, int * status); int imcomp_nullvalues(int *idata, long tilelen, int nullflagval, int nullval, int * status); int imcomp_scalevalues(int *idata, long tilelen, double scale, double zero, int * status); int imcomp_nullscalefloats(float *fdata, long tilelen, int *idata, double scale, double zero, int nullcheck, float nullflagval, int nullval, int *status); int imcomp_nullfloats(float *fdata, long tilelen, int *idata, int nullcheck, float nullflagval, int nullval, int *status); int imcomp_nullscaledoubles(double *fdata, long tilelen, int *idata, double scale, double zero, int nullcheck, double nullflagval, int nullval, int *status); int imcomp_nulldoubles(double *fdata, long tilelen, int *idata, int nullcheck, double nullflagval, int nullval, int *status); /* image decompression routines */ int fits_read_compressed_img(fitsfile *fptr, int datatype, LONGLONG *fpixel,LONGLONG *lpixel,long *inc, int nullcheck, void *nulval, void *array, char *nullarray, int *anynul, int *status); int fits_read_compressed_pixels(fitsfile *fptr, int datatype, LONGLONG fpixel, LONGLONG npixels, int nullcheck, void *nulval, void *array, char *nullarray, int *anynul, int *status); int fits_read_compressed_img_plane(fitsfile *fptr, int datatype, int bytesperpixel, long nplane, LONGLONG *firstcoord, LONGLONG *lastcoord, long *inc, long *naxes, int nullcheck, void *nullval, void *array, char *nullarray, int *anynul, long *nread, int *status); int imcomp_get_compressed_image_par(fitsfile *infptr, int *status); int imcomp_decompress_tile (fitsfile *infptr, int nrow, int tilesize, int datatype, int nullcheck, void *nulval, void *buffer, char *bnullarray, int *anynul, int *status); int imcomp_copy_overlap (char *tile, int pixlen, int ndim, long *tfpixel, long *tlpixel, char *bnullarray, char *image, long *fpixel, long *lpixel, long *inc, int nullcheck, char *nullarray, int *status); int imcomp_test_overlap (int ndim, long *tfpixel, long *tlpixel, long *fpixel, long *lpixel, long *inc, int *status); int imcomp_merge_overlap (char *tile, int pixlen, int ndim, long *tfpixel, long *tlpixel, char *bnullarray, char *image, long *fpixel, long *lpixel, int nullcheck, int *status); int imcomp_decompress_img(fitsfile *infptr, fitsfile *outfptr, int datatype, int *status); int fits_quantize_float (long row, float fdata[], long nx, long ny, int nullcheck, float in_null_value, float quantize_level, int dither_method, int idata[], double *bscale, double *bzero, int *iminval, int *imaxval); int fits_quantize_double (long row, double fdata[], long nx, long ny, int nullcheck, double in_null_value, float quantize_level, int dither_method, int idata[], double *bscale, double *bzero, int *iminval, int *imaxval); int fits_rcomp(int a[], int nx, unsigned char *c, int clen,int nblock); int fits_rcomp_short(short a[], int nx, unsigned char *c, int clen,int nblock); int fits_rcomp_byte(signed char a[], int nx, unsigned char *c, int clen,int nblock); int fits_rdecomp (unsigned char *c, int clen, unsigned int array[], int nx, int nblock); int fits_rdecomp_short (unsigned char *c, int clen, unsigned short array[], int nx, int nblock); int fits_rdecomp_byte (unsigned char *c, int clen, unsigned char array[], int nx, int nblock); int pl_p2li (int *pxsrc, int xs, short *lldst, int npix); int pl_l2pi (short *ll_src, int xs, int *px_dst, int npix); int fits_init_randoms(void); int fits_unset_compression_param( fitsfile *fptr, int *status); int fits_unset_compression_request( fitsfile *fptr, int *status); int fitsio_init_lock(void); /* general driver routines */ int urltype2driver(char *urltype, int *driver); int fits_register_driver( char *prefix, int (*init)(void), int (*fitsshutdown)(void), int (*setoptions)(int option), int (*getoptions)(int *options), int (*getversion)(int *version), int (*checkfile) (char *urltype, char *infile, char *outfile), int (*fitsopen)(char *filename, int rwmode, int *driverhandle), int (*fitscreate)(char *filename, int *driverhandle), int (*fitstruncate)(int driverhandle, LONGLONG filesize), int (*fitsclose)(int driverhandle), int (*fremove)(char *filename), int (*size)(int driverhandle, LONGLONG *sizex), int (*flush)(int driverhandle), int (*seek)(int driverhandle, LONGLONG offset), int (*fitsread) (int driverhandle, void *buffer, long nbytes), int (*fitswrite)(int driverhandle, void *buffer, long nbytes)); /* file driver I/O routines */ int file_init(void); int file_setoptions(int options); int file_getoptions(int *options); int file_getversion(int *version); int file_shutdown(void); int file_checkfile(char *urltype, char *infile, char *outfile); int file_open(char *filename, int rwmode, int *driverhandle); int file_compress_open(char *filename, int rwmode, int *hdl); int file_openfile(char *filename, int rwmode, FILE **diskfile); int file_create(char *filename, int *driverhandle); int file_truncate(int driverhandle, LONGLONG filesize); int file_size(int driverhandle, LONGLONG *filesize); int file_close(int driverhandle); int file_remove(char *filename); int file_flush(int driverhandle); int file_seek(int driverhandle, LONGLONG offset); int file_read (int driverhandle, void *buffer, long nbytes); int file_write(int driverhandle, void *buffer, long nbytes); int file_is_compressed(char *filename); /* stream driver I/O routines */ int stream_open(char *filename, int rwmode, int *driverhandle); int stream_create(char *filename, int *driverhandle); int stream_size(int driverhandle, LONGLONG *filesize); int stream_close(int driverhandle); int stream_flush(int driverhandle); int stream_seek(int driverhandle, LONGLONG offset); int stream_read (int driverhandle, void *buffer, long nbytes); int stream_write(int driverhandle, void *buffer, long nbytes); /* memory driver I/O routines */ int mem_init(void); int mem_setoptions(int options); int mem_getoptions(int *options); int mem_getversion(int *version); int mem_shutdown(void); int mem_create(char *filename, int *handle); int mem_create_comp(char *filename, int *handle); int mem_openmem(void **buffptr, size_t *buffsize, size_t deltasize, void *(*memrealloc)(void *p, size_t newsize), int *handle); int mem_createmem(size_t memsize, int *handle); int stdin_checkfile(char *urltype, char *infile, char *outfile); int stdin_open(char *filename, int rwmode, int *handle); int stdin2mem(int hd); int stdin2file(int hd); int stdout_close(int handle); int mem_compress_openrw(char *filename, int rwmode, int *hdl); int mem_compress_open(char *filename, int rwmode, int *hdl); int mem_compress_stdin_open(char *filename, int rwmode, int *hdl); int mem_iraf_open(char *filename, int rwmode, int *hdl); int mem_rawfile_open(char *filename, int rwmode, int *hdl); int mem_size(int handle, LONGLONG *filesize); int mem_truncate(int handle, LONGLONG filesize); int mem_close_free(int handle); int mem_close_keep(int handle); int mem_close_comp(int handle); int mem_seek(int handle, LONGLONG offset); int mem_read(int hdl, void *buffer, long nbytes); int mem_write(int hdl, void *buffer, long nbytes); int mem_uncompress2mem(char *filename, FILE *diskfile, int hdl); int iraf2mem(char *filename, char **buffptr, size_t *buffsize, size_t *filesize, int *status); /* root driver I/O routines */ int root_init(void); int root_setoptions(int options); int root_getoptions(int *options); int root_getversion(int *version); int root_shutdown(void); int root_open(char *filename, int rwmode, int *driverhandle); int root_create(char *filename, int *driverhandle); int root_close(int driverhandle); int root_flush(int driverhandle); int root_seek(int driverhandle, LONGLONG offset); int root_read (int driverhandle, void *buffer, long nbytes); int root_write(int driverhandle, void *buffer, long nbytes); int root_size(int handle, LONGLONG *filesize); /* http driver I/O routines */ int http_checkfile(char *urltype, char *infile, char *outfile); int http_open(char *filename, int rwmode, int *driverhandle); int http_file_open(char *filename, int rwmode, int *driverhandle); int http_compress_open(char *filename, int rwmode, int *driverhandle); /* https driver I/O routines */ int https_checkfile(char* urltype, char *infile, char *outfile); int https_open(char *filename, int rwmode, int *driverhandle); int https_file_open(char *filename, int rwmode, int *driverhandle); void https_set_verbose(int flag); /* ftp driver I/O routines */ int ftp_checkfile(char *urltype, char *infile, char *outfile); int ftp_open(char *filename, int rwmode, int *driverhandle); int ftp_file_open(char *filename, int rwmode, int *driverhandle); int ftp_compress_open(char *filename, int rwmode, int *driverhandle); int uncompress2mem(char *filename, FILE *diskfile, char **buffptr, size_t *buffsize, void *(*mem_realloc)(void *p, size_t newsize), size_t *filesize, int *status); int uncompress2mem_from_mem( char *inmemptr, size_t inmemsize, char **buffptr, size_t *buffsize, void *(*mem_realloc)(void *p, size_t newsize), size_t *filesize, int *status); int uncompress2file(char *filename, FILE *indiskfile, FILE *outdiskfile, int *status); int compress2mem_from_mem( char *inmemptr, size_t inmemsize, char **buffptr, size_t *buffsize, void *(*mem_realloc)(void *p, size_t newsize), size_t *filesize, int *status); int compress2file_from_mem( char *inmemptr, size_t inmemsize, FILE *outdiskfile, size_t *filesize, /* O - size of file, in bytes */ int *status); #ifdef HAVE_GSIFTP /* prototypes for gsiftp driver I/O routines */ #include "drvrgsiftp.h" #endif #ifdef HAVE_SHMEM_SERVICES /* prototypes for shared memory driver I/O routines */ #include "drvrsmem.h" #endif /* A hack for nonunix machines, which lack strcasecmp and strncasecmp */ /* these functions are in fitscore.c */ int fits_strcasecmp (const char *s1, const char *s2 ); int fits_strncasecmp(const char *s1, const char *s2, size_t n); /* end of the entire "ifndef _FITSIO2_H" block */ #endif cfitsio/fpack.c0000644000225700000360000003425313246025103013237 0ustar cagordonlhea/* FPACK * R. Seaman, NOAO, with a few enhancements by W. Pence, HEASARC * * Calls fits_img_compress in the CFITSIO library by W. Pence, HEASARC */ #include /* #include */ #include "fitsio.h" #include "fpack.h" /* ================================================================== */ int main(int argc, char *argv[]) { fpstate fpvar; if (argc <= 1) { fp_usage (); fp_hint (); exit (-1); } fp_init (&fpvar); fp_get_param (argc, argv, &fpvar); if (fpvar.listonly) { fp_list (argc, argv, fpvar); } else { fp_preflight (argc, argv, FPACK, &fpvar); fp_loop (argc, argv, FPACK, fpvar); } exit (0); } /* ================================================================== */ int fp_get_param (int argc, char *argv[], fpstate *fpptr) { int gottype=0, gottile=0, wholetile=0, iarg, len, ndim, ii, doffset; char tmp[SZ_STR], tile[SZ_STR]; if (fpptr->initialized != FP_INIT_MAGIC) { fp_msg ("Error: internal initialization error\n"); exit (-1); } tile[0] = 0; /* flags must come first and be separately specified */ for (iarg = 1; iarg < argc; iarg++) { if ((argv[iarg][0] == '-' && strlen (argv[iarg]) == 2) || !strncmp(argv[iarg], "-q", 2) || !strncmp(argv[iarg], "-qz", 3) || !strncmp(argv[iarg], "-g1", 3) || !strncmp(argv[iarg], "-g2", 3) || !strncmp(argv[iarg], "-i2f", 4) || !strncmp(argv[iarg], "-n3ratio", 8) || !strncmp(argv[iarg], "-n3min", 6) || !strncmp(argv[iarg], "-tableonly", 10) || !strncmp(argv[iarg], "-table", 6) ) { /* Rice is the default, so -r is superfluous */ if ( argv[iarg][1] == 'r') { fpptr->comptype = RICE_1; if (gottype) { fp_msg ("Error: multiple compression flags\n"); fp_usage (); exit (-1); } else gottype++; } else if (argv[iarg][1] == 'p') { fpptr->comptype = PLIO_1; if (gottype) { fp_msg ("Error: multiple compression flags\n"); fp_usage (); exit (-1); } else gottype++; } else if (argv[iarg][1] == 'g') { /* test for modifiers following the 'g' */ if (argv[iarg][2] == '2') fpptr->comptype = GZIP_2; else fpptr->comptype = GZIP_1; if (gottype) { fp_msg ("Error: multiple compression flags\n"); fp_usage (); exit (-1); } else gottype++; /* } else if (argv[iarg][1] == 'b') { fpptr->comptype = BZIP2_1; if (gottype) { fp_msg ("Error: multiple compression flags\n"); fp_usage (); exit (-1); } else gottype++; */ } else if (argv[iarg][1] == 'h') { fpptr->comptype = HCOMPRESS_1; if (gottype) { fp_msg ("Error: multiple compression flags\n"); fp_usage (); exit (-1); } else gottype++; } else if (argv[iarg][1] == 'd') { fpptr->comptype = NOCOMPRESS; if (gottype) { fp_msg ("Error: multiple compression flags\n"); fp_usage (); exit (-1); } else gottype++; } else if (!strcmp(argv[iarg], "-i2f")) { /* this means convert integer images to float, and then */ /* quantize and compress the float image. This lossy */ /* compression method may give higher compression than the */ /* lossless compression method that is usually applied to */ /* integer images. */ fpptr->int_to_float = 1; } else if (!strcmp(argv[iarg], "-n3ratio")) { /* this is the minimum ratio between the MAD noise sigma */ /* and the q parameter value in the case where the integer */ /* image is quantized and compressed like a float image. */ if (++iarg >= argc) { fp_usage (); exit (-1); } else { fpptr->n3ratio = (float) atof (argv[iarg]); } } else if (!strcmp(argv[iarg], "-n3min")) { /* this is the minimum MAD noise sigma in the case where the */ /* integer image is quantized and compressed like a float image. */ if (++iarg >= argc) { fp_usage (); exit (-1); } else { fpptr->n3min = (float) atof (argv[iarg]); } } else if (argv[iarg][1] == 'q') { /* test for modifiers following the 'q' */ if (argv[iarg][2] == 'z') { fpptr->dither_method = 2; /* preserve zero pixels */ if (argv[iarg][3] == 't') { fpptr->dither_offset = -1; /* dither based on tile checksum */ } else if (isdigit(argv[iarg][3])) { /* is a number appended to q? */ doffset = atoi(argv[iarg]+3); if (doffset == 0) { fpptr->no_dither = 1; /* don't dither the quantized values */ } else if (doffset > 0 && doffset <= 10000) { fpptr->dither_offset = doffset; } else { fp_msg ("Error: invalid q suffix\n"); fp_usage (); exit (-1); } } } else { if (argv[iarg][2] == 't') { fpptr->dither_offset = -1; /* dither based on tile checksum */ } else if (isdigit(argv[iarg][2])) { /* is a number appended to q? */ doffset = atoi(argv[iarg]+2); if (doffset == 0) { fpptr->no_dither = 1; /* don't dither the quantized values */ } else if (doffset > 0 && doffset <= 10000) { fpptr->dither_offset = doffset; } else { fp_msg ("Error: invalid q suffix\n"); fp_usage (); exit (-1); } } } if (++iarg >= argc) { fp_usage (); exit (-1); } else { fpptr->quantize_level = (float) atof (argv[iarg]); } } else if (argv[iarg][1] == 'n') { if (++iarg >= argc) { fp_usage (); exit (-1); } else { fpptr->rescale_noise = (float) atof (argv[iarg]); } } else if (argv[iarg][1] == 's') { if (++iarg >= argc) { fp_usage (); exit (-1); } else { fpptr->scale = (float) atof (argv[iarg]); } } else if (!strcmp(argv[iarg], "-tableonly")) { fpptr->do_tables = 1; fpptr->do_images = 0; fp_msg ("Note: -tableonly is intended for feasibility studies, not general use.\n"); } else if (!strcmp(argv[iarg], "-table")) { fpptr->do_tables = 1; fp_msg ("Note: -table is intended for feasibility studies, not general use.\n"); } else if (argv[iarg][1] == 't') { if (gottile) { fp_msg ("Error: multiple tile specifications\n"); fp_usage (); exit (-1); } else gottile++; if (++iarg >= argc) { fp_usage (); exit (-1); } else strncpy (tile, argv[iarg], SZ_STR); /* checked below */ } else if (argv[iarg][1] == 'v') { fpptr->verbose = 1; } else if (argv[iarg][1] == 'w') { wholetile++; if (gottile) { fp_msg ("Error: multiple tile specifications\n"); fp_usage (); exit (-1); } else gottile++; } else if (argv[iarg][1] == 'F') { fpptr->clobber++; /* overwrite existing file */ } else if (argv[iarg][1] == 'D') { fpptr->delete_input++; } else if (argv[iarg][1] == 'Y') { fpptr->do_not_prompt++; } else if (argv[iarg][1] == 'S') { fpptr->to_stdout++; } else if (argv[iarg][1] == 'L') { fpptr->listonly++; } else if (argv[iarg][1] == 'C') { fpptr->do_checksums = 0; } else if (argv[iarg][1] == 'T') { fpptr->test_all = 1; } else if (argv[iarg][1] == 'R') { if (++iarg >= argc) { fp_usage (); fp_hint (); exit (-1); } else strncpy (fpptr->outfile, argv[iarg], SZ_STR); } else if (argv[iarg][1] == 'H') { fp_help (); exit (0); } else if (argv[iarg][1] == 'V') { fp_version (); exit (0); } else { fp_msg ("Error: unknown command line flag `"); fp_msg (argv[iarg]); fp_msg ("'\n"); fp_usage (); fp_hint (); exit (-1); } } else break; } if (fpptr->scale != 0. && fpptr->comptype != HCOMPRESS_1 && fpptr->test_all != 1) { fp_msg ("Error: `-s' requires `-h or -T'\n"); exit (-1); } if (fpptr->quantize_level == 0) { if ((fpptr->comptype != GZIP_1) && (fpptr->comptype != GZIP_2)) { fp_msg ("Error: `-q 0' only allowed with GZIP\n"); exit (-1); } if (fpptr->int_to_float == 1) { fp_msg ("Error: `-q 0' not allowed with -i2f\n"); exit (-1); } } if (wholetile) { for (ndim=0; ndim < MAX_COMPRESS_DIM; ndim++) fpptr->ntile[ndim] = (long) -1; } else if (gottile) { len = strlen (tile); for (ii=0, ndim=0; ii < len; ) { if (! (isdigit (tile[ii]) || tile[ii] == ',')) { fp_msg ("Error: `-t' requires comma separated tile dims, "); fp_msg ("e.g., `-t 100,100'\n"); exit (-1); } if (tile[ii] == ',') { ii++; continue; } fpptr->ntile[ndim] = atol (&tile[ii]); for ( ; isdigit(tile[ii]); ii++); if (++ndim > MAX_COMPRESS_DIM) { fp_msg ("Error: too many dimensions for `-t', max="); snprintf (tmp, SZ_STR,"%d\n", MAX_COMPRESS_DIM); fp_msg (tmp); exit (-1); } } } if (iarg >= argc) { fp_msg ("Error: no FITS files to compress\n"); fp_usage (); exit (-1); } else fpptr->firstfile = iarg; return(0); } /* ================================================================== */ int fp_usage (void) { fp_msg ("usage: fpack "); fp_msg ( "[-r|-h|-g|-p] [-w|-t ] [-q ] [-s ] [-n ] -v \n"); fp_msg ("more: [-T] [-R] [-F] [-D] [-Y] [-S] [-L] [-C] [-H] [-V] [-i2f]\n"); return(0); } /* ================================================================== */ int fp_hint (void) { fp_msg (" `fpack -H' for help\n"); return(0); } /* ================================================================== */ int fp_help (void) { fp_msg ("fpack, a FITS image compression program. Version "); fp_version (); fp_usage (); fp_msg ("\n"); fp_msg ("NOTE: the compression parameters specified on the fpack command line may\n"); fp_msg ("be over-ridden by compression directive keywords in the header of each HDU\n"); fp_msg ("of the input file(s). See the fpack User's Guide for more details\n"); fp_msg ("\n"); fp_msg ("Flags must be separate and appear before filenames:\n"); fp_msg (" -r Rice compression [default], or\n"); fp_msg (" -h Hcompress compression, or\n"); fp_msg (" -g or -g1 GZIP_1 (per-tile) compression, or\n"); fp_msg (" -g2 GZIP_2 (per-tile) compression (with byte shuffling), or\n"); /* fp_msg (" -b BZIP2 (per-tile) compression, or\n"); */ fp_msg (" -p PLIO compression (only for positive 8 or 16-bit integer images).\n"); fp_msg (" -d Tile the image without compression (debugging mode).\n"); fp_msg (" -w Compress the whole image as a single large tile.\n"); fp_msg (" -t Comma separated list of tile dimensions [default is row by row].\n"); fp_msg (" -q Quantized level spacing when converting floating point images to\n"); fp_msg (" scaled integers. (+value relative to sigma of background noise;\n"); fp_msg (" -value is absolute). Default q value of 4 gives a compression ratio\n"); fp_msg (" of about 6 with very high fidelity (only 0.26% increase in noise).\n"); fp_msg (" Using q values of 2, or 1 will give compression ratios of\n"); fp_msg (" about 8, or 10, respectively (with 1.0% or 4.1% noise increase).\n"); fp_msg (" The scaled quantized values are randomly dithered using a seed \n"); fp_msg (" value determined from the system clock at run time.\n"); fp_msg (" Use -q0 instead of -q to suppress random dithering.\n"); fp_msg (" Use -qz instead of -q to not dither zero-valued pixels.\n"); fp_msg (" Use -qt or -qzt to compute random dithering seed from first tile checksum.\n"); fp_msg (" Use -qN or -qzN, (N in range 1 to 10000) to use a specific dithering seed.\n"); fp_msg (" Floating-point images can be losslessly compressed by selecting\n"); fp_msg (" the GZIP algorithm and specifying -q 0, but this is slower and often\n"); fp_msg (" produces much less compression than the default quantization method.\n"); fp_msg (" -i2f Convert integer images to floating point, then quantize and compress\n"); fp_msg (" using the specified q level. When used appropriately, this lossy\n"); fp_msg (" compression method can give much better compression than the normal\n"); fp_msg (" lossless compression methods without significant loss of information.\n"); fp_msg (" The -n3ratio and -n3min flags control the minimum noise thresholds;\n"); fp_msg (" Images below these thresholds will be losslessly compressed.\n"); fp_msg (" -n3ratio Minimum ratio of background noise sigma divided by q. Default = 2.0.\n"); fp_msg (" -n3min Minimum background noise sigma. Default = 6. The -i2f flag will be ignored\n"); fp_msg (" if the noise level in the image does not exceed both thresholds.\n"); fp_msg (" -s Scale factor for lossy Hcompress [default = 0 = lossless]\n"); fp_msg (" (+values relative to RMS noise; -value is absolute)\n"); fp_msg (" -n Rescale scaled-integer images to reduce noise and improve compression.\n"); fp_msg (" -v Verbose mode; list each file as it is processed.\n"); fp_msg (" -T Show compression algorithm comparison test statistics; files unchanged.\n"); fp_msg (" -R Write the comparison test report (above) to a text file.\n"); fp_msg (" -table Compress FITS binary tables as well as compress any image HDUs.\n"); fp_msg (" -tableonly Compress only FITS binary tables; do not compress any image HDUs.\n"); fp_msg (" \n"); fp_msg ("\nkeywords shared with funpack:\n"); fp_msg (" -F Overwrite input file by output file with same name.\n"); fp_msg (" -D Delete input file after writing output.\n"); fp_msg (" -Y Suppress prompts to confirm -F or -D options.\n"); fp_msg (" -S Output compressed FITS files to STDOUT.\n"); fp_msg (" -L List contents; files unchanged.\n"); fp_msg (" -C Don't update FITS checksum keywords.\n"); fp_msg (" -H Show this message.\n"); fp_msg (" -V Show version number.\n"); fp_msg ("\n FITS files to pack; enter '-' (a hyphen) to read input from stdin stream.\n"); fp_msg (" Refer to the fpack User's Guide for more extensive help.\n"); return(0); } cfitsio/fpack.h0000644000225700000360000001576313246025103013251 0ustar cagordonlhea/* used by FPACK and FUNPACK * R. Seaman, NOAO * W. Pence, NASA/GSFC */ #include #include #include /* not needed any more */ /* #include */ /* #include */ /* #include */ #define FPACK_VERSION "1.7.0 (Dec 2013)" /* VERSION History 1.7.0 (Dec 2013) - extensive changes to the binary table compression method. All types of binary table columns, including variable length array columns are now supported. The command line table compression flag has been changed to "-table" instead of "-BETAtable", and a new "-tableonly" flag has been introduced to only compress the binary tables in the input files(s) and not the image HDUs. 1.6.1 (Mar 2013) - numerous changes to the BETAtable compression method used to compress binary tables - added support for compression 'steering' keywords that specify the desired compression parameters that should be used when compressing that particular HDU, thus overriding the fpack command line parameter values. 1.6.0 (June 2012) - Fixed behavior of the "rename" function on Windows platforms so that it will clobber/delete an existing file before renaming a file to that name (the rename command behaves differently on POSIX and non-POSIX environments). 1.6.0 (February 2011) - Added full support for compressing and uncompressing FITS binary tables using a newly proposed format convention. This is intended only for further feasibility studies, and is not recommended for use with publicly distributed FITS files. - Use the minimum of the MAD 2nd, 3rd, and 5th order values as a more conservative extimate of the noise when quantizing floating point images. - Enhanced the tile compression routines so that a tile that contains all NaN pixel values will be compressed. - When uncompressing an image that was originally in a FITS primary array, funpack will also append any new keywords that were written into the primary array of the compressed FITS file after the file was compressed. - Added support for the GZIP_2 algorithm, which shuffles the bytes in the pixel values prior to compressing them with gzip. 1.5.1 (December 2010) Added prototype, mainly hidden, support for compressing binary tables. 1.5.0 (August 2010) Added the -i2f option to lossy compress integer images. 1.4.0 (Jan 2010) Reduced the default value for the q floating point image quantization parameter from 16 to 4. This results in about 50% better compression (from about 4.6x to 6.4) with no lost of significant information (with the new subtractive dithering enhancement). Replaced the code for generating temporary filenames to make the code more portable (to Windows). Replaced calls to the unix 'access' and 'stat' functions with more portable code. When unpacking a file, write it first to a temporary file, then rename it when finished, so that other tasks cannot try to read the file before it is complete. 1.3.0 (Oct 2009) added randomization to the dithering pattern so that the same pattern is not used for every image; also added an option for losslessly compressing floating point images with GZIP for test purposes (not recommended for general use). Also added support for reading the input FITS file from the stdin file streams. 1.2.0 (Sept 2009) added subtractive dithering feature (in CFITSIO) when quantizing floating point images; When packing an IRAF .imh + .pix image, the file name is changed to FILE.fits.fz, and if the original file is deleted, then both the .imh and .pix files are deleted. 1.1.4 (May 2009) added -E option to funpack to unpack a list of HDUs 1.1.3 (March 2009) minor modifications to the content and format of the -T report 1.1.2 (September 2008) */ #define FP_INIT_MAGIC 42 #define FPACK 0 #define FUNPACK 1 /* changed from 16 in Jan. 2010 */ #define DEF_QLEVEL 4. #define DEF_HCOMP_SCALE 0. #define DEF_HCOMP_SMOOTH 0 #define DEF_RESCALE_NOISE 0 #define SZ_STR 513 #define SZ_CARD 81 typedef struct { int comptype; float quantize_level; int no_dither; int dither_offset; int dither_method; float scale; float rescale_noise; int smooth; int int_to_float; float n3ratio; float n3min; long ntile[MAX_COMPRESS_DIM]; int to_stdout; int listonly; int clobber; int delete_input; int do_not_prompt; int do_checksums; int do_gzip_file; int do_images; int do_tables; int test_all; int verbose; char prefix[SZ_STR]; char extname[SZ_STR]; int delete_suffix; char outfile[SZ_STR]; int firstfile; int initialized; int preflight_checked; } fpstate; typedef struct { int n_nulls; double minval; double maxval; double mean; double sigma; double noise1; double noise2; double noise3; double noise5; } imgstats; int fp_get_param (int argc, char *argv[], fpstate *fpptr); void abort_fpack(int sig); void fp_abort_output (fitsfile *infptr, fitsfile *outfptr, int stat); int fp_usage (void); int fp_help (void); int fp_hint (void); int fp_init (fpstate *fpptr); int fp_list (int argc, char *argv[], fpstate fpvar); int fp_info (char *infits); int fp_info_hdu (fitsfile *infptr); int fp_preflight (int argc, char *argv[], int unpack, fpstate *fpptr); int fp_loop (int argc, char *argv[], int unpack, fpstate fpvar); int fp_pack (char *infits, char *outfits, fpstate fpvar, int *islossless); int fp_unpack (char *infits, char *outfits, fpstate fpvar); int fp_test (char *infits, char *outfits, char *outfits2, fpstate fpvar); int fp_pack_hdu (fitsfile *infptr, fitsfile *outfptr, fpstate fpvar, int *islossless, int *status); int fp_unpack_hdu (fitsfile *infptr, fitsfile *outfptr, fpstate fpvar, int *status); int fits_read_image_speed (fitsfile *infptr, float *whole_elapse, float *whole_cpu, float *row_elapse, float *row_cpu, int *status); int fp_test_hdu (fitsfile *infptr, fitsfile *outfptr, fitsfile *outfptr2, fpstate fpvar, int *status); int fp_test_table (fitsfile *infptr, fitsfile *outfptr, fitsfile *outfptr2, fpstate fpvar, int *status); int marktime(int *status); int gettime(float *elapse, float *elapscpu, int *status); int fits_read_image_speed (fitsfile *infptr, float *whole_elapse, float *whole_cpu, float *row_elapse, float *row_cpu, int *status); int fp_i2stat(fitsfile *infptr, int naxis, long *naxes, imgstats *imagestats, int *status); int fp_i4stat(fitsfile *infptr, int naxis, long *naxes, imgstats *imagestats, int *status); int fp_r4stat(fitsfile *infptr, int naxis, long *naxes, imgstats *imagestats, int *status); int fp_i2rescale(fitsfile *infptr, int naxis, long *naxes, double rescale, fitsfile *outfptr, int *status); int fp_i4rescale(fitsfile *infptr, int naxis, long *naxes, double rescale, fitsfile *outfptr, int *status); int fp_msg (char *msg); int fp_version (void); int fp_noop (void); int fu_get_param (int argc, char *argv[], fpstate *fpptr); int fu_usage (void); int fu_hint (void); int fu_help (void); cfitsio/fpackutil.c0000644000225700000360000022100013246025103014121 0ustar cagordonlhea/* FPACK utility routines R. Seaman, NOAO & W. Pence, NASA/GSFC */ #include #include #include #include /* #include "bzlib.h" only for experimental purposes */ #if defined(unix) || defined(__unix__) || defined(__unix) #include #endif #include #include "fitsio.h" #include "fpack.h" /* these filename buffer are used to delete temporary files */ /* in case the program is aborted */ char tempfilename[SZ_STR]; char tempfilename2[SZ_STR]; char tempfilename3[SZ_STR]; /* nearest integer function */ # define NINT(x) ((x >= 0.) ? (int) (x + 0.5) : (int) (x - 0.5)) # define NSHRT(x) ((x >= 0.) ? (short) (x + 0.5) : (short) (x - 0.5)) /* define variables for measuring elapsed time */ clock_t scpu, ecpu; long startsec; /* start of elapsed time interval */ int startmilli; /* start of elapsed time interval */ /* CLOCKS_PER_SEC should be defined by most compilers */ #if defined(CLOCKS_PER_SEC) #define CLOCKTICKS CLOCKS_PER_SEC #else /* on SUN OS machine, CLOCKS_PER_SEC is not defined, so set its value */ #define CLOCKTICKS 1000000 #endif FILE *outreport; /* dimension of central image area to be sampled for test statistics */ int XSAMPLE = 4100; int YSAMPLE = 4100; int fp_msg (char *msg) { printf ("%s", msg); return(0); } /*--------------------------------------------------------------------------*/ int fp_noop (void) { fp_msg ("Input and output files are unchanged.\n"); return(0); } /*--------------------------------------------------------------------------*/ void fp_abort_output (fitsfile *infptr, fitsfile *outfptr, int stat) { int status = 0, hdunum; char msg[SZ_STR]; fits_file_name(infptr, tempfilename, &status); fits_get_hdu_num(infptr, &hdunum); fits_close_file (infptr, &status); snprintf(msg, SZ_STR,"Error processing file: %s\n", tempfilename); fp_msg (msg); snprintf(msg, SZ_STR," in HDU number %d\n", hdunum); fp_msg (msg); fits_report_error (stderr, stat); if (outfptr) { fits_delete_file(outfptr, &status); fp_msg ("Input file is unchanged.\n"); } exit (stat); } /*--------------------------------------------------------------------------*/ int fp_version (void) { float version; char cfitsioversion[40]; fp_msg (FPACK_VERSION); fits_get_version(&version); snprintf(cfitsioversion, 40," CFITSIO version %5.3f", version); fp_msg(cfitsioversion); fp_msg ("\n"); return(0); } /*--------------------------------------------------------------------------*/ int fp_access (char *filename) { /* test if a file exists */ FILE *diskfile; diskfile = fopen(filename, "r"); if (diskfile) { fclose(diskfile); return(0); } else { return(-1); } } /*--------------------------------------------------------------------------*/ int fp_tmpnam(char *suffix, char *rootname, char *tmpnam) { /* create temporary file name */ int maxtry = 30, ii; if (strlen(suffix) + strlen(rootname) > SZ_STR-5) { fp_msg ("Error: filename is too long to create tempory file\n"); exit (-1); } strcpy (tmpnam, rootname); /* start with rootname */ strcat(tmpnam, suffix); /* append the suffix */ maxtry = SZ_STR - strlen(tmpnam) - 1; for (ii = 0; ii < maxtry; ii++) { if (fp_access(tmpnam)) break; /* good, the file does not exist */ strcat(tmpnam, "x"); /* append an x to the name, and try again */ } if (ii == maxtry) { fp_msg ("\nCould not create temporary file name:\n"); fp_msg (tmpnam); fp_msg ("\n"); exit (-1); } return(0); } /*--------------------------------------------------------------------------*/ int fp_init (fpstate *fpptr) { int ii; fpptr->comptype = RICE_1; fpptr->quantize_level = DEF_QLEVEL; fpptr->no_dither = 0; fpptr->dither_method = 1; fpptr->dither_offset = 0; fpptr->int_to_float = 0; /* thresholds when using the -i2f flag */ fpptr->n3ratio = 2.0; /* minimum ratio of image noise sigma / q */ fpptr->n3min = 6.; /* minimum noise sigma. */ fpptr->scale = DEF_HCOMP_SCALE; fpptr->smooth = DEF_HCOMP_SMOOTH; fpptr->rescale_noise = DEF_RESCALE_NOISE; fpptr->ntile[0] = (long) -1; /* -1 means extent of axis */ for (ii=1; ii < MAX_COMPRESS_DIM; ii++) fpptr->ntile[ii] = (long) 1; fpptr->to_stdout = 0; fpptr->listonly = 0; fpptr->clobber = 0; fpptr->delete_input = 0; fpptr->do_not_prompt = 0; fpptr->do_checksums = 1; fpptr->do_gzip_file = 0; fpptr->do_tables = 0; /* this is intended for testing purposes */ fpptr->do_images = 1; /* can be turned off with -tableonly switch */ fpptr->test_all = 0; fpptr->verbose = 0; fpptr->prefix[0] = 0; fpptr->extname[0] = 0; fpptr->delete_suffix = 0; fpptr->outfile[0] = 0; fpptr->firstfile = 1; /* magic number for initialization check, boolean for preflight */ fpptr->initialized = FP_INIT_MAGIC; fpptr->preflight_checked = 0; return(0); } /*--------------------------------------------------------------------------*/ int fp_list (int argc, char *argv[], fpstate fpvar) { fitsfile *infptr; char infits[SZ_STR], msg[SZ_STR]; int hdunum, iarg, stat=0; LONGLONG sizell; if (fpvar.initialized != FP_INIT_MAGIC) { fp_msg ("Error: internal initialization error\n"); exit (-1); } for (iarg=fpvar.firstfile; iarg < argc; iarg++) { strncpy (infits, argv[iarg], SZ_STR); if (strchr (infits, '[') || strchr (infits, ']')) { fp_msg ("Error: section/extension notation not supported: "); fp_msg (infits); fp_msg ("\n"); exit (-1); } if (fp_access (infits) != 0) { fp_msg ("Error: can't find or read input file "); fp_msg (infits); fp_msg ("\n"); fp_noop (); exit (-1); } fits_open_file (&infptr, infits, READONLY, &stat); if (stat) { fits_report_error (stderr, stat); exit (stat); } /* move to the end of file, to get the total size in bytes */ fits_get_num_hdus (infptr, &hdunum, &stat); fits_movabs_hdu (infptr, hdunum, NULL, &stat); fits_get_hduaddrll(infptr, NULL, NULL, &sizell, &stat); if (stat) { fp_abort_output(infptr, NULL, stat); } snprintf (msg, SZ_STR,"# %s (", infits); fp_msg (msg); #if defined(_MSC_VER) /* Microsoft Visual C++ 6.0 uses '%I64d' syntax for 8-byte integers */ snprintf(msg, SZ_STR,"%I64d bytes)\n", sizell); fp_msg (msg); #elif (USE_LL_SUFFIX == 1) snprintf(msg, SZ_STR,"%lld bytes)\n", sizell); fp_msg (msg); #else snprintf(msg, SZ_STR,"%ld bytes)\n", sizell); fp_msg (msg); #endif fp_info_hdu (infptr); fits_close_file (infptr, &stat); if (stat) { fits_report_error (stderr, stat); exit (stat); } } return(0); } /*--------------------------------------------------------------------------*/ int fp_info_hdu (fitsfile *infptr) { long naxes[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1}; char msg[SZ_STR], val[SZ_CARD], com[SZ_CARD]; int naxis=0, hdutype, bitpix, hdupos, stat=0, ii; unsigned long datasum, hdusum; fits_movabs_hdu (infptr, 1, NULL, &stat); if (stat) { fp_abort_output(infptr, NULL, stat); } for (hdupos=1; ! stat; hdupos++) { fits_get_hdu_type (infptr, &hdutype, &stat); if (stat) { fp_abort_output(infptr, NULL, stat); } /* fits_get_hdu_type calls unknown extensions "IMAGE_HDU" * so consult XTENSION keyword itself */ fits_read_keyword (infptr, "XTENSION", val, com, &stat); if (stat == KEY_NO_EXIST) { /* in primary HDU which by definition is an "image" */ stat=0; /* clear for later error handling */ } else if (stat) { fp_abort_output(infptr, NULL, stat); } else if (hdutype == IMAGE_HDU) { /* that is, if XTENSION != "IMAGE" AND != "BINTABLE" */ if (strncmp (val+1, "IMAGE", 5) && strncmp (val+1, "BINTABLE", 5)) { /* assign something other than any of these */ hdutype = IMAGE_HDU + ASCII_TBL + BINARY_TBL; } } fits_get_chksum(infptr, &datasum, &hdusum, &stat); if (hdutype == IMAGE_HDU) { snprintf (msg, SZ_STR," %d IMAGE", hdupos); fp_msg (msg); snprintf (msg, SZ_STR," SUMS=%lu/%lu", (unsigned long) (~((int) hdusum)), datasum); fp_msg (msg); fits_get_img_param (infptr, 9, &bitpix, &naxis, naxes, &stat); snprintf (msg, SZ_STR," BITPIX=%d", bitpix); fp_msg (msg); if (naxis == 0) { snprintf (msg, SZ_STR," [no_pixels]"); fp_msg (msg); } else if (naxis == 1) { snprintf (msg, SZ_STR," [%ld]", naxes[1]); fp_msg (msg); } else { snprintf (msg, SZ_STR," [%ld", naxes[0]); fp_msg (msg); for (ii=1; ii < naxis; ii++) { snprintf (msg, SZ_STR,"x%ld", naxes[ii]); fp_msg (msg); } fp_msg ("]"); } if (fits_is_compressed_image (infptr, &stat)) { fits_read_keyword (infptr, "ZCMPTYPE", val, com, &stat); /* allow for quote in keyword value */ if (! strncmp (val+1, "RICE_1", 6)) fp_msg (" tiled_rice\n"); else if (! strncmp (val+1, "GZIP_1", 6)) fp_msg (" tiled_gzip_1\n"); else if (! strncmp (val+1, "GZIP_2", 6)) fp_msg (" tiled_gzip_2\n"); else if (! strncmp (val+1, "PLIO_1", 6)) fp_msg (" tiled_plio\n"); else if (! strncmp (val+1, "HCOMPRESS_1", 11)) fp_msg (" tiled_hcompress\n"); else fp_msg (" unknown\n"); } else fp_msg (" not_tiled\n"); } else if (hdutype == ASCII_TBL) { snprintf (msg, SZ_STR," %d ASCII_TBL", hdupos); fp_msg (msg); snprintf (msg, SZ_STR," SUMS=%lu/%lu\n", (unsigned long) (~((int) hdusum)), datasum); fp_msg (msg); } else if (hdutype == BINARY_TBL) { snprintf (msg, SZ_STR," %d BINARY_TBL", hdupos); fp_msg (msg); snprintf (msg, SZ_STR," SUMS=%lu/%lu\n", (unsigned long) (~((int) hdusum)), datasum); fp_msg (msg); } else { snprintf (msg, SZ_STR," %d OTHER", hdupos); fp_msg (msg); snprintf (msg, SZ_STR," SUMS=%lu/%lu", (unsigned long) (~((int) hdusum)), datasum); fp_msg (msg); snprintf (msg, SZ_STR," %s\n", val); fp_msg (msg); } fits_movrel_hdu (infptr, 1, NULL, &stat); } return(0); } /*--------------------------------------------------------------------------*/ int fp_preflight (int argc, char *argv[], int unpack, fpstate *fpptr) { char infits[SZ_STR], outfits[SZ_STR]; int iarg, namelen, nfiles = 0; if (fpptr->initialized != FP_INIT_MAGIC) { fp_msg ("Error: internal initialization error\n"); exit (-1); } for (iarg=fpptr->firstfile; iarg < argc; iarg++) { outfits[0] = '\0'; if (strlen(argv[iarg]) > SZ_STR - 4) { /* allow for .fz or .gz suffix */ fp_msg ("Error: input file name\n "); fp_msg (argv[iarg]); fp_msg ("\n is too long\n"); fp_noop (); exit (-1); } strncpy (infits, argv[iarg], SZ_STR); if (infits[0] == '-' && infits[1] != '\0') { /* don't interpret this as intending to read input file from stdin */ fp_msg ("Error: invalid input file name\n "); fp_msg (argv[iarg]); fp_msg ("\n"); fp_noop (); exit (-1); } if (strchr (infits, '[') || strchr (infits, ']')) { fp_msg ("Error: section/extension notation not supported: "); fp_msg (infits); fp_msg ("\n"); fp_noop (); exit (-1); } if (unpack) { /* ********** This section applies to funpack ************ */ /* check that input file exists */ if (infits[0] != '-') { /* if not reading from stdin stream */ if (fp_access (infits) != 0) { /* if not, then check if */ strcat(infits, ".fz"); /* a .fz version exsits */ if (fp_access (infits) != 0) { namelen = strlen(infits); infits[namelen - 3] = '\0'; /* remove the .fz suffix */ fp_msg ("Error: can't find or read input file "); fp_msg (infits); fp_msg ("\n"); fp_noop (); exit (-1); } } else { /* make sure a .fz version of the same file doesn't exist */ namelen = strlen(infits); strcat(infits, ".fz"); if (fp_access (infits) == 0) { infits[namelen] = '\0'; /* remove the .fz suffix */ fp_msg ("Error: ambiguous input file name. Which file should be unpacked?:\n "); fp_msg (infits); fp_msg ("\n "); fp_msg (infits); fp_msg (".fz\n"); fp_noop (); exit (-1); } else { infits[namelen] = '\0'; /* remove the .fz suffix */ } } } /* if writing to stdout, then we are all done */ if (fpptr->to_stdout) { continue; } if (fpptr->outfile[0]) { /* user specified output file name */ nfiles++; if (nfiles > 1) { fp_msg ("Error: cannot use same output file name for multiple files:\n "); fp_msg (fpptr->outfile); fp_msg ("\n"); fp_noop (); exit (-1); } /* check that output file doesn't exist */ if (fp_access (fpptr->outfile) == 0) { fp_msg ("Error: output file already exists:\n "); fp_msg (fpptr->outfile); fp_msg ("\n "); fp_noop (); exit (-1); } continue; } /* construct output file name to test */ if (fpptr->prefix[0]) { if (strlen(fpptr->prefix) + strlen(infits) > SZ_STR - 1) { fp_msg ("Error: output file name for\n "); fp_msg (infits); fp_msg ("\n is too long with the prefix\n"); fp_noop (); exit (-1); } strcat(outfits,fpptr->prefix); } /* construct output file name */ if (infits[0] == '-') { strcpy(outfits, "output.fits"); } else { strcpy(outfits, infits); } /* remove .gz suffix, if present (output is not gzipped) */ namelen = strlen(outfits); if ( !strcmp(".gz", outfits + namelen - 3) ) { outfits[namelen - 3] = '\0'; } /* check for .fz suffix that is sometimes required */ /* and remove it if present */ if (infits[0] != '-') { /* if not reading from stdin stream */ namelen = strlen(outfits); if ( !strcmp(".fz", outfits + namelen - 3) ) { /* suffix is present */ outfits[namelen - 3] = '\0'; } else if (fpptr->delete_suffix) { /* required suffix is missing */ fp_msg ("Error: input compressed file "); fp_msg (infits); fp_msg ("\n does not have the default .fz suffix.\n"); fp_noop (); exit (-1); } } /* if infits != outfits, make sure outfits doesn't already exist */ if (strcmp(infits, outfits)) { if (fp_access (outfits) == 0) { fp_msg ("Error: output file already exists:\n "); fp_msg (outfits); fp_msg ("\n "); fp_noop (); exit (-1); } } /* if gzipping the output, make sure .gz file doesn't exist */ if (fpptr->do_gzip_file) { strcat(outfits, ".gz"); if (fp_access (outfits) == 0) { fp_msg ("Error: output file already exists:\n "); fp_msg (outfits); fp_msg ("\n "); fp_noop (); exit (-1); } namelen = strlen(outfits); outfits[namelen - 3] = '\0'; /* remove the .gz suffix again */ } } else { /* ********** This section applies to fpack ************ */ /* check that input file exists */ if (infits[0] != '-') { /* if not reading from stdin stream */ if (fp_access (infits) != 0) { /* if not, then check if */ strcat(infits, ".gz"); /* a gzipped version exsits */ if (fp_access (infits) != 0) { namelen = strlen(infits); infits[namelen - 3] = '\0'; /* remove the .gz suffix */ fp_msg ("Error: can't find or read input file "); fp_msg (infits); fp_msg ("\n"); fp_noop (); exit (-1); } } } /* make sure the file to pack does not already have a .fz suffix */ namelen = strlen(infits); if ( !strcmp(".fz", infits + namelen - 3) ) { fp_msg ("Error: fpack input file already has '.fz' suffix\n" ); fp_msg (infits); fp_msg ("\n"); fp_noop (); exit (-1); } /* if writing to stdout, or just testing the files, then we are all done */ if (fpptr->to_stdout || fpptr->test_all) { continue; } /* construct output file name */ if (infits[0] == '-') { strcpy(outfits, "input.fits"); } else { strcpy(outfits, infits); } /* remove .gz suffix, if present (output is not gzipped) */ namelen = strlen(outfits); if ( !strcmp(".gz", outfits + namelen - 3) ) { outfits[namelen - 3] = '\0'; } /* remove .imh suffix (IRAF format image), and replace with .fits */ namelen = strlen(outfits); if ( !strcmp(".imh", outfits + namelen - 4) ) { outfits[namelen - 4] = '\0'; strcat(outfits, ".fits"); } /* If not clobbering the input file, add .fz suffix to output name */ if (! fpptr->clobber) strcat(outfits, ".fz"); /* if infits != outfits, make sure outfits doesn't already exist */ if (strcmp(infits, outfits)) { if (fp_access (outfits) == 0) { fp_msg ("Error: output file already exists:\n "); fp_msg (outfits); fp_msg ("\n "); fp_noop (); exit (-1); } } } /* end of fpack section */ } fpptr->preflight_checked++; return(0); } /*--------------------------------------------------------------------------*/ /* must run fp_preflight() before fp_loop() */ int fp_loop (int argc, char *argv[], int unpack, fpstate fpvar) { char infits[SZ_STR], outfits[SZ_STR]; char temp[SZ_STR], answer[30]; int iarg, islossless, namelen, iraf_infile = 0, status = 0, ifail; if (fpvar.initialized != FP_INIT_MAGIC) { fp_msg ("Error: internal initialization error\n"); exit (-1); } else if (! fpvar.preflight_checked) { fp_msg ("Error: internal preflight error\n"); exit (-1); } if (fpvar.test_all && fpvar.outfile[0]) { outreport = fopen(fpvar.outfile, "w"); fprintf(outreport," Filename Extension BITPIX NAXIS1 NAXIS2 Size N_nulls Minval Maxval Mean Sigm Noise1 Noise2 Noise3 Noise5 T_whole T_rowbyrow "); fprintf(outreport,"[Comp_ratio, Pack_cpu, Unpack_cpu, Lossless readtimes] (repeated for Rice, Hcompress, and GZIP)\n"); } tempfilename[0] = '\0'; tempfilename2[0] = '\0'; tempfilename3[0] = '\0'; /* set up signal handler to delete temporary file on abort */ #ifdef SIGINT if (signal(SIGINT, SIG_IGN) != SIG_IGN) { (void) signal(SIGINT, abort_fpack); } #endif #ifdef SIGTERM if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { (void) signal(SIGTERM, abort_fpack); } #endif #ifdef SIGHUP if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { (void) signal(SIGHUP, abort_fpack); } #endif for (iarg=fpvar.firstfile; iarg < argc; iarg++) { temp[0] = '\0'; outfits[0] = '\0'; islossless = 1; strncpy (infits, argv[iarg], SZ_STR - 1); if (unpack) { /* ********** This section applies to funpack ************ */ /* find input file */ if (infits[0] != '-') { /* if not reading from stdin stream */ if (fp_access (infits) != 0) { /* if not, then */ strcat(infits, ".fz"); /* a .fz version must exsit */ } } if (fpvar.to_stdout) { strcpy(outfits, "-"); } else if (fpvar.outfile[0]) { /* user specified output file name */ strcpy(outfits, fpvar.outfile); } else { /* construct output file name */ if (fpvar.prefix[0]) { strcat(outfits,fpvar.prefix); } /* construct output file name */ if (infits[0] == '-') { strcpy(outfits, "output.fits"); } else { strcpy(outfits, infits); } /* remove .gz suffix, if present (output is not gzipped) */ namelen = strlen(outfits); if ( !strcmp(".gz", outfits + namelen - 3) ) { outfits[namelen - 3] = '\0'; } /* check for .fz suffix that is sometimes required */ /* and remove it if present */ namelen = strlen(outfits); if ( !strcmp(".fz", outfits + namelen - 3) ) { /* suffix is present */ outfits[namelen - 3] = '\0'; } } } else { /* ********** This section applies to fpack ************ */ if (fpvar.to_stdout) { strcpy(outfits, "-"); } else if (! fpvar.test_all) { /* construct output file name */ if (infits[0] == '-') { strcpy(outfits, "input.fits"); } else { strcpy(outfits, infits); } /* remove .gz suffix, if present (output is not gzipped) */ namelen = strlen(outfits); if ( !strcmp(".gz", outfits + namelen - 3) ) { outfits[namelen - 3] = '\0'; } /* remove .imh suffix (IRAF format image), and replace with .fits */ namelen = strlen(outfits); if ( !strcmp(".imh", outfits + namelen - 4) ) { outfits[namelen - 4] = '\0'; strcat(outfits, ".fits"); iraf_infile = 1; /* this is an IRAF format input file */ /* change the output name to "NAME.fits.fz" */ } /* If not clobbering the input file, add .fz suffix to output name */ if (! fpvar.clobber) strcat(outfits, ".fz"); } } strncpy(temp, outfits, SZ_STR-1); if (infits[0] != '-') { /* if not reading from stdin stream */ if (!strcmp(infits, outfits) ) { /* are input and output names the same? */ /* clobber the input file with the output file with the same name */ if (! fpvar.clobber) { fp_msg ("\nError: must use -F flag to clobber input file.\n"); exit (-1); } /* create temporary file name in the output directory (same as input directory)*/ fp_tmpnam("Tmp1", infits, outfits); strcpy(tempfilename, outfits); /* store temp file name, in case of abort */ } } /* *************** now do the real work ********************* */ if (fpvar.verbose && ! fpvar.to_stdout) printf("%s ", infits); if (fpvar.test_all) { /* compare all the algorithms */ /* create 2 temporary file names, in the CWD */ fp_tmpnam("Tmpfile1", "", tempfilename); fp_tmpnam("Tmpfile2", "", tempfilename2); fp_test (infits, tempfilename, tempfilename2, fpvar); remove(tempfilename); tempfilename[0] = '\0'; /* clear the temp file name */ remove(tempfilename2); tempfilename2[0] = '\0'; continue; } else if (unpack) { if (fpvar.to_stdout) { /* unpack the input file to the stdout stream */ fp_unpack (infits, outfits, fpvar); } else { /* unpack to temporary file, so other tasks can't open it until it is renamed */ /* create temporary file name, in the output directory */ fp_tmpnam("Tmp2", outfits, tempfilename2); /* unpack the input file to the temporary file */ fp_unpack (infits, tempfilename2, fpvar); /* rename the temporary file to it's real name */ ifail = rename(tempfilename2, outfits); if (ifail) { fp_msg("Failed to rename temporary file name:\n "); fp_msg(tempfilename2); fp_msg(" -> "); fp_msg(outfits); fp_msg("\n"); exit (-1); } else { tempfilename2[0] = '\0'; /* clear temporary file name */ } } } else { fp_pack (infits, outfits, fpvar, &islossless); } if (fpvar.to_stdout) { continue; } /* ********** clobber and/or delete files, if needed ************** */ if (!strcmp(infits, temp) && fpvar.clobber ) { if (!islossless && ! fpvar.do_not_prompt) { fp_msg ("\nFile "); fp_msg (infits); fp_msg ("\nwas compressed with a LOSSY method. Overwrite the\n"); fp_msg ("original file with the compressed version? (Y/N) "); fgets(answer, 29, stdin); if (answer[0] != 'Y' && answer[0] != 'y') { fp_msg ("\noriginal file NOT overwritten!\n"); remove(outfits); continue; } } if (iraf_infile) { /* special case of deleting an IRAF format header and pixel file */ if (fits_delete_iraf_file(infits, &status)) { fp_msg("\nError deleting IRAF .imh and .pix files.\n"); fp_msg(infits); fp_msg ("\n"); exit (-1); } } #if defined(unix) || defined(__unix__) || defined(__unix) /* rename clobbers input on Unix platforms */ if (rename (outfits, temp) != 0) { fp_msg ("\nError renaming tmp file to "); fp_msg (temp); fp_msg ("\n"); exit (-1); } #else /* rename DOES NOT clobber existing files on Windows platforms */ /* so explicitly remove any existing file before renaming the file */ remove(temp); if (rename (outfits, temp) != 0) { fp_msg ("\nError renaming tmp file to "); fp_msg (temp); fp_msg ("\n"); exit (-1); } #endif tempfilename[0] = '\0'; /* clear temporary file name */ strcpy(outfits, temp); } else if (fpvar.clobber || fpvar.delete_input) { /* delete the input file */ if (!islossless && !fpvar.do_not_prompt) { /* user did not turn off delete prompt */ fp_msg ("\nFile "); fp_msg (infits); fp_msg ("\nwas compressed with a LOSSY method. \n"); fp_msg ("Delete the original file? (Y/N) "); fgets(answer, 29, stdin); if (answer[0] != 'Y' && answer[0] != 'y') { /* user abort */ fp_msg ("\noriginal file NOT deleted!\n"); } else { if (iraf_infile) { /* special case of deleting an IRAF format header and pixel file */ if (fits_delete_iraf_file(infits, &status)) { fp_msg("\nError deleting IRAF .imh and .pix files.\n"); fp_msg(infits); fp_msg ("\n"); exit (-1); } } else if (remove(infits) != 0) { /* normal case of deleting input FITS file */ fp_msg ("\nError deleting input file "); fp_msg (infits); fp_msg ("\n"); exit (-1); } } } else { /* user said don't prompt, so just delete the input file */ if (iraf_infile) { /* special case of deleting an IRAF format header and pixel file */ if (fits_delete_iraf_file(infits, &status)) { fp_msg("\nError deleting IRAF .imh and .pix files.\n"); fp_msg(infits); fp_msg ("\n"); exit (-1); } } else if (remove(infits) != 0) { /* normal case of deleting input FITS file */ fp_msg ("\nError deleting input file "); fp_msg (infits); fp_msg ("\n"); exit (-1); } } } iraf_infile = 0; if (fpvar.do_gzip_file) { /* gzip the output file */ strcpy(temp, "gzip -1 "); strcat(temp,outfits); system(temp); strcat(outfits, ".gz"); /* only possibible with funpack */ } if (fpvar.verbose && ! fpvar.to_stdout) printf("-> %s\n", outfits); } if (fpvar.test_all && fpvar.outfile[0]) fclose(outreport); return(0); } /*--------------------------------------------------------------------------*/ /* fp_pack assumes the output file does not exist (checked by preflight) */ int fp_pack (char *infits, char *outfits, fpstate fpvar, int *islossless) { fitsfile *infptr, *outfptr; int stat=0; fits_open_file (&infptr, infits, READONLY, &stat); if (stat) { fits_report_error (stderr, stat); exit (stat); } fits_create_file (&outfptr, outfits, &stat); if (stat) { fp_abort_output(infptr, NULL, stat); } if (stat) { fp_abort_output(infptr, outfptr, stat); } while (! stat) { /* LOOP OVER EACH HDU */ fits_set_lossy_int (outfptr, fpvar.int_to_float, &stat); fits_set_compression_type (outfptr, fpvar.comptype, &stat); fits_set_tile_dim (outfptr, 6, fpvar.ntile, &stat); if (fpvar.no_dither) fits_set_quantize_method(outfptr, -1, &stat); else fits_set_quantize_method(outfptr, fpvar.dither_method, &stat); fits_set_quantize_level (outfptr, fpvar.quantize_level, &stat); fits_set_dither_offset(outfptr, fpvar.dither_offset, &stat); fits_set_hcomp_scale (outfptr, fpvar.scale, &stat); fits_set_hcomp_smooth (outfptr, fpvar.smooth, &stat); fp_pack_hdu (infptr, outfptr, fpvar, islossless, &stat); if (fpvar.do_checksums) { fits_write_chksum (outfptr, &stat); } fits_movrel_hdu (infptr, 1, NULL, &stat); } if (stat == END_OF_FILE) stat = 0; /* set checksum for case of newly created primary HDU */ if (fpvar.do_checksums) { fits_movabs_hdu (outfptr, 1, NULL, &stat); fits_write_chksum (outfptr, &stat); } if (stat) { fp_abort_output(infptr, outfptr, stat); } fits_close_file (outfptr, &stat); fits_close_file (infptr, &stat); return(0); } /*--------------------------------------------------------------------------*/ /* fp_unpack assumes the output file does not exist */ int fp_unpack (char *infits, char *outfits, fpstate fpvar) { fitsfile *infptr, *outfptr; int stat=0, hdutype, extnum, single = 0; char *loc, *hduloc, hduname[SZ_STR]; fits_open_file (&infptr, infits, READONLY, &stat); fits_create_file (&outfptr, outfits, &stat); if (stat) { fp_abort_output(infptr, outfptr, stat); } if (fpvar.extname[0]) { /* unpack a list of HDUs? */ /* move to the first HDU in the list */ hduloc = fpvar.extname; loc = strchr(hduloc, ','); /* look for 'comma' delimiter between names */ if (loc) *loc = '\0'; /* terminate the first name in the string */ strcpy(hduname, hduloc); /* copy the first name into temporary string */ if (loc) hduloc = loc + 1; /* advance to the beginning of the next name, if any */ else { hduloc += strlen(hduname); /* end of the list */ single = 1; /* only 1 HDU is being unpacked */ } if (isdigit( (int) hduname[0]) ) { extnum = strtol(hduname, &loc, 10); /* read the string as an integer */ /* check for junk following the integer */ if (*loc == '\0' ) /* no junk, so move to this HDU number (+1) */ { fits_movabs_hdu(infptr, extnum + 1, &hdutype, &stat); /* move to HDU number */ if (hdutype != IMAGE_HDU) stat = NOT_IMAGE; } else { /* the string is not an integer, so must be the column name */ hdutype = IMAGE_HDU; fits_movnam_hdu(infptr, hdutype, hduname, 0, &stat); } } else { /* move to the named image extension */ hdutype = IMAGE_HDU; fits_movnam_hdu(infptr, hdutype, hduname, 0, &stat); } } if (stat) { fp_msg ("Unable to find and move to extension '"); fp_msg(hduname); fp_msg("'\n"); fp_abort_output(infptr, outfptr, stat); } while (! stat) { if (single) stat = -1; /* special status flag to force output primary array */ fp_unpack_hdu (infptr, outfptr, fpvar, &stat); if (fpvar.do_checksums) { fits_write_chksum (outfptr, &stat); } /* move to the next HDU */ if (fpvar.extname[0]) { /* unpack a list of HDUs? */ if (!(*hduloc)) { stat = END_OF_FILE; /* we reached the end of the list */ } else { /* parse the next HDU name and move to it */ loc = strchr(hduloc, ','); if (loc) /* look for 'comma' delimiter between names */ *loc = '\0'; /* terminate the first name in the string */ strcpy(hduname, hduloc); /* copy the next name into temporary string */ if (loc) hduloc = loc + 1; /* advance to the beginning of the next name, if any */ else *hduloc = '\0'; /* end of the list */ if (isdigit( (int) hduname[0]) ) { extnum = strtol(hduname, &loc, 10); /* read the string as an integer */ /* check for junk following the integer */ if (*loc == '\0' ) /* no junk, so move to this HDU number (+1) */ { fits_movabs_hdu(infptr, extnum + 1, &hdutype, &stat); /* move to HDU number */ if (hdutype != IMAGE_HDU) stat = NOT_IMAGE; } else { /* the string is not an integer, so must be the column name */ hdutype = IMAGE_HDU; fits_movnam_hdu(infptr, hdutype, hduname, 0, &stat); } } else { /* move to the named image extension */ hdutype = IMAGE_HDU; fits_movnam_hdu(infptr, hdutype, hduname, 0, &stat); } if (stat) { fp_msg ("Unable to find and move to extension '"); fp_msg(hduname); fp_msg("'\n"); } } } else { /* increment to the next HDU */ fits_movrel_hdu (infptr, 1, NULL, &stat); } } if (stat == END_OF_FILE) stat = 0; /* set checksum for case of newly created primary HDU */ if (fpvar.do_checksums) { fits_movabs_hdu (outfptr, 1, NULL, &stat); fits_write_chksum (outfptr, &stat); } if (stat) { fp_abort_output(infptr, outfptr, stat); } fits_close_file (outfptr, &stat); fits_close_file (infptr, &stat); return(0); } /*--------------------------------------------------------------------------*/ /* fp_test assumes the output files do not exist */ int fp_test (char *infits, char *outfits, char *outfits2, fpstate fpvar) { fitsfile *inputfptr, *infptr, *outfptr, *outfptr2, *tempfile; long naxes[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1}; int stat=0, totpix=0, naxis=0, ii, hdutype, bitpix = 0, extnum = 0, len; int tstatus = 0, hdunum, rescale_flag, bpix, ncols; char dtype[8], dimen[100]; double bscale, rescale, noisemin; long headstart, datastart, dataend; float origdata = 0., whole_cpu, whole_elapse, row_elapse, row_cpu, xbits; LONGLONG nrows; /* structure to hold image statistics (defined in fpack.h) */ imgstats imagestats; fits_open_file (&inputfptr, infits, READONLY, &stat); fits_create_file (&outfptr, outfits, &stat); fits_create_file (&outfptr2, outfits2, &stat); if (stat) { fits_report_error (stderr, stat); exit (stat); } while (! stat) { /* LOOP OVER EACH HDU */ rescale_flag = 0; fits_get_hdu_type (inputfptr, &hdutype, &stat); if (hdutype == IMAGE_HDU) { fits_get_img_param (inputfptr, 9, &bitpix, &naxis, naxes, &stat); for (totpix=1, ii=0; ii < 9; ii++) totpix *= naxes[ii]; } if (!fits_is_compressed_image (inputfptr, &stat) && hdutype == IMAGE_HDU && naxis != 0 && totpix != 0 && fpvar.do_images) { /* rescale a scaled integer image to reduce noise? */ if (fpvar.rescale_noise != 0. && bitpix > 0 && bitpix < LONGLONG_IMG) { tstatus = 0; fits_read_key(inputfptr, TDOUBLE, "BSCALE", &bscale, 0, &tstatus); if (tstatus == 0 && bscale != 1.0) { /* image must be scaled */ if (bitpix == LONG_IMG) fp_i4stat(inputfptr, naxis, naxes, &imagestats, &stat); else fp_i2stat(inputfptr, naxis, naxes, &imagestats, &stat); /* use the minimum of the MAD 2nd, 3rd, and 5th order noise estimates */ noisemin = imagestats.noise3; if (imagestats.noise2 != 0. && imagestats.noise2 < noisemin) noisemin = imagestats.noise2; if (imagestats.noise5 != 0. && imagestats.noise5 < noisemin) noisemin = imagestats.noise5; rescale = noisemin / fpvar.rescale_noise; if (rescale > 1.0) { /* all the criteria are met, so create a temporary file that */ /* contains a rescaled version of the image, in CWD */ /* create temporary file name */ fp_tmpnam("Tmpfile3", "", tempfilename3); fits_create_file(&tempfile, tempfilename3, &stat); fits_get_hdu_num(inputfptr, &hdunum); if (hdunum != 1) { /* the input hdu is an image extension, so create dummy primary */ fits_create_img(tempfile, 8, 0, naxes, &stat); } fits_copy_header(inputfptr, tempfile, &stat); /* copy the header */ /* rescale the data, so that it will compress more efficiently */ if (bitpix == LONG_IMG) fp_i4rescale(inputfptr, naxis, naxes, rescale, tempfile, &stat); else fp_i2rescale(inputfptr, naxis, naxes, rescale, tempfile, &stat); /* scale the BSCALE keyword by the inverse factor */ bscale = bscale * rescale; fits_update_key(tempfile, TDOUBLE, "BSCALE", &bscale, 0, &stat); /* rescan the header, to reset the actual scaling parameters */ fits_set_hdustruc(tempfile, &stat); infptr = tempfile; rescale_flag = 1; } } } if (!rescale_flag) /* just compress the input file, without rescaling */ infptr = inputfptr; /* compute basic statistics about the input image */ if (bitpix == BYTE_IMG) { bpix = 8; strcpy(dtype, "8 "); fp_i2stat(infptr, naxis, naxes, &imagestats, &stat); } else if (bitpix == SHORT_IMG) { bpix = 16; strcpy(dtype, "16 "); fp_i2stat(infptr, naxis, naxes, &imagestats, &stat); } else if (bitpix == LONG_IMG) { bpix = 32; strcpy(dtype, "32 "); fp_i4stat(infptr, naxis, naxes, &imagestats, &stat); } else if (bitpix == LONGLONG_IMG) { bpix = 64; strcpy(dtype, "64 "); } else if (bitpix == FLOAT_IMG) { bpix = 32; strcpy(dtype, "-32"); fp_r4stat(infptr, naxis, naxes, &imagestats, &stat); } else if (bitpix == DOUBLE_IMG) { bpix = 64; strcpy(dtype, "-64"); fp_r4stat(infptr, naxis, naxes, &imagestats, &stat); } /* use the minimum of the MAD 2nd, 3rd, and 5th order noise estimates */ noisemin = imagestats.noise3; if (imagestats.noise2 != 0. && imagestats.noise2 < noisemin) noisemin = imagestats.noise2; if (imagestats.noise5 != 0. && imagestats.noise5 < noisemin) noisemin = imagestats.noise5; xbits = (float) (log10(noisemin)/.301 + 1.792); printf("\n File: %s\n", infits); printf(" Ext BITPIX Dimens. Nulls Min Max Mean Sigma Noise2 Noise3 Noise5 Nbits MaxR\n"); printf(" %3d %s", extnum, dtype); snprintf(dimen,100," (%ld", naxes[0]); len =strlen(dimen); for (ii = 1; ii < naxis; ii++) { if (len < 100) snprintf(dimen+len,100-len,",%ld", naxes[ii]); len =strlen(dimen); } strcat(dimen, ")"); printf("%-12s",dimen); fits_get_hduaddr(inputfptr, &headstart, &datastart, &dataend, &stat); origdata = (float) ((dataend - datastart)/1000000.); /* get elapsed and cpu times need to read the uncompressed image */ fits_read_image_speed (infptr, &whole_elapse, &whole_cpu, &row_elapse, &row_cpu, &stat); printf(" %5d %6.0f %6.0f %8.1f %#8.2g %#7.3g %#7.3g %#7.3g %#5.1f %#6.2f\n", imagestats.n_nulls, imagestats.minval, imagestats.maxval, imagestats.mean, imagestats.sigma, imagestats.noise2, imagestats.noise3, imagestats.noise5, xbits, bpix/xbits); printf("\n Type Ratio Size (MB) Pk (Sec) UnPk Exact ElpN CPUN Elp1 CPU1\n"); printf(" Native %5.3f %5.3f %5.3f %5.3f\n", whole_elapse, whole_cpu, row_elapse, row_cpu); if (fpvar.outfile[0]) { fprintf(outreport, " %s %d %d %ld %ld %#10.4g %d %#10.4g %#10.4g %#10.4g %#10.4g %#10.4g %#10.4g %#10.4g %#10.4g %#10.4g %#10.4g %#10.4g %#10.4g", infits, extnum, bitpix, naxes[0], naxes[1], origdata, imagestats.n_nulls, imagestats.minval, imagestats.maxval, imagestats.mean, imagestats.sigma, imagestats.noise1, imagestats.noise2, imagestats.noise3, imagestats.noise5, whole_elapse, whole_cpu, row_elapse, row_cpu); } fits_set_lossy_int (outfptr, fpvar.int_to_float, &stat); if ( (bitpix > 0) && (fpvar.int_to_float != 0) ) { if ( (noisemin < (fpvar.n3ratio * fpvar.quantize_level) ) || (noisemin < fpvar.n3min)) { /* image contains too little noise to quantize effectively */ fits_set_lossy_int (outfptr, 0, &stat); fits_get_hdu_num(infptr, &hdunum); printf(" HDU %d does not meet noise criteria to be quantized, so losslessly compressed.\n", hdunum); } } /* test compression ratio and speed for each algorithm */ if (fpvar.quantize_level != 0) { fits_set_compression_type (outfptr, RICE_1, &stat); fits_set_tile_dim (outfptr, 6, fpvar.ntile, &stat); if (fpvar.no_dither) fits_set_quantize_method(outfptr, -1, &stat); else fits_set_quantize_method(outfptr, fpvar.dither_method, &stat); fits_set_quantize_level (outfptr, fpvar.quantize_level, &stat); fits_set_dither_offset(outfptr, fpvar.dither_offset, &stat); fits_set_hcomp_scale (outfptr, fpvar.scale, &stat); fits_set_hcomp_smooth (outfptr, fpvar.smooth, &stat); fp_test_hdu(infptr, outfptr, outfptr2, fpvar, &stat); } if (fpvar.quantize_level != 0) { \ fits_set_compression_type (outfptr, HCOMPRESS_1, &stat); fits_set_tile_dim (outfptr, 6, fpvar.ntile, &stat); if (fpvar.no_dither) fits_set_quantize_method(outfptr, -1, &stat); else fits_set_quantize_method(outfptr, fpvar.dither_method, &stat); fits_set_quantize_level (outfptr, fpvar.quantize_level, &stat); fits_set_dither_offset(outfptr, fpvar.dither_offset, &stat); fits_set_hcomp_scale (outfptr, fpvar.scale, &stat); fits_set_hcomp_smooth (outfptr, fpvar.smooth, &stat); fp_test_hdu(infptr, outfptr, outfptr2, fpvar, &stat); } if (fpvar.comptype == GZIP_2) { fits_set_compression_type (outfptr, GZIP_2, &stat); } else { fits_set_compression_type (outfptr, GZIP_1, &stat); } fits_set_tile_dim (outfptr, 6, fpvar.ntile, &stat); if (fpvar.no_dither) fits_set_quantize_method(outfptr, -1, &stat); else fits_set_quantize_method(outfptr, fpvar.dither_method, &stat); fits_set_quantize_level (outfptr, fpvar.quantize_level, &stat); fits_set_dither_offset(outfptr, fpvar.dither_offset, &stat); fits_set_hcomp_scale (outfptr, fpvar.scale, &stat); fits_set_hcomp_smooth (outfptr, fpvar.smooth, &stat); fp_test_hdu(infptr, outfptr, outfptr2, fpvar, &stat); /* fits_set_compression_type (outfptr, BZIP2_1, &stat); fits_set_tile_dim (outfptr, 6, fpvar.ntile, &stat); fp_test_hdu(infptr, outfptr, outfptr2, fpvar, &stat); */ /* fits_set_compression_type (outfptr, PLIO_1, &stat); fits_set_tile_dim (outfptr, 6, fpvar.ntile, &stat); fp_test_hdu(infptr, outfptr, outfptr2, fpvar, &stat); */ /* if (bitpix == SHORT_IMG || bitpix == LONG_IMG) { fits_set_compression_type (outfptr, NOCOMPRESS, &stat); fits_set_tile_dim (outfptr, 6, fpvar.ntile, &stat); fp_test_hdu(infptr, outfptr, outfptr2, fpvar, &stat); } */ if (fpvar.outfile[0]) fprintf(outreport,"\n"); /* delete the temporary file */ if (rescale_flag) { fits_delete_file (infptr, &stat); tempfilename3[0] = '\0'; /* clear the temp filename */ } } else if ( (hdutype == BINARY_TBL) && fpvar.do_tables) { fits_get_num_rowsll(inputfptr, &nrows, &stat); fits_get_num_cols(inputfptr, &ncols, &stat); #if defined(_MSC_VER) /* Microsoft Visual C++ 6.0 uses '%I64d' syntax for 8-byte integers */ printf("\n File: %s, HDU %d, %d cols X %I64d rows\n", infits, extnum, ncols, nrows); #elif (USE_LL_SUFFIX == 1) printf("\n File: %s, HDU %d, %d cols X %lld rows\n", infits, extnum, ncols, nrows); #else printf("\n File: %s, HDU %d, %d cols X %ld rows\n", infits, extnum, ncols, nrows); #endif fp_test_table(inputfptr, outfptr, outfptr2, fpvar, &stat); } else { fits_copy_hdu (inputfptr, outfptr, 0, &stat); fits_copy_hdu (inputfptr, outfptr2, 0, &stat); } fits_movrel_hdu (inputfptr, 1, NULL, &stat); extnum++; } if (stat == END_OF_FILE) stat = 0; fits_close_file (outfptr2, &stat); fits_close_file (outfptr, &stat); fits_close_file (inputfptr, &stat); if (stat) { fits_report_error (stderr, stat); } return(0); } /*--------------------------------------------------------------------------*/ int fp_pack_hdu (fitsfile *infptr, fitsfile *outfptr, fpstate fpvar, int *islossless, int *status) { fitsfile *tempfile; long naxes[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1}; int stat=0, totpix=0, naxis=0, ii, hdutype, bitpix; int tstatus, hdunum; double bscale, rescale; char outfits[SZ_STR], fzalgor[FLEN_VALUE]; long headstart, datastart, dataend, datasize; double noisemin; /* structure to hold image statistics (defined in fpack.h) */ imgstats imagestats; if (*status) return(0); fits_get_hdu_type (infptr, &hdutype, &stat); if (hdutype == IMAGE_HDU) { fits_get_img_param (infptr, 9, &bitpix, &naxis, naxes, &stat); for (totpix=1, ii=0; ii < 9; ii++) totpix *= naxes[ii]; } /* check directive keyword to see if this HDU should not be compressed */ tstatus = 0; if (!fits_read_key(infptr, TSTRING, "FZALGOR", fzalgor, NULL, &tstatus) ) { if (!strcmp(fzalgor, "NONE") || !strcmp(fzalgor, "none") ) { fits_copy_hdu (infptr, outfptr, 0, &stat); *status = stat; return(0); } } /* =============================================================== */ /* This block is only for binary table compression */ if (hdutype == BINARY_TBL && fpvar.do_tables) { fits_get_hduaddr(infptr, &headstart, &datastart, &dataend, status); datasize = dataend - datastart; if (datasize <= 2880) { /* data is less than 1 FITS block in size, so don't compress */ fits_copy_hdu (infptr, outfptr, 0, &stat); } else { fits_compress_table (infptr, outfptr, &stat); } *status = stat; return(0); } /* =============================================================== */ /* If this is not a non-null image HDU, just copy it verbatim */ if (fits_is_compressed_image (infptr, &stat) || hdutype != IMAGE_HDU || naxis == 0 || totpix == 0 || !fpvar.do_images) { fits_copy_hdu (infptr, outfptr, 0, &stat); } else { /* remaining code deals only with IMAGE HDUs */ /* special case: rescale a scaled integer image to reduce noise? */ if (fpvar.rescale_noise != 0. && bitpix > 0 && bitpix < LONGLONG_IMG) { tstatus = 0; fits_read_key(infptr, TDOUBLE, "BSCALE", &bscale, 0, &tstatus); if (tstatus == 0 && bscale != 1.0) { /* image must be scaled */ if (bitpix == LONG_IMG) fp_i4stat(infptr, naxis, naxes, &imagestats, &stat); else fp_i2stat(infptr, naxis, naxes, &imagestats, &stat); /* use the minimum of the MAD 2nd, 3rd, and 5th order noise estimates */ noisemin = imagestats.noise3; if (imagestats.noise2 != 0. && imagestats.noise2 < noisemin) noisemin = imagestats.noise2; if (imagestats.noise5 != 0. && imagestats.noise5 < noisemin) noisemin = imagestats.noise5; rescale = noisemin / fpvar.rescale_noise; if (rescale > 1.0) { /* all the criteria are met, so create a temporary file that */ /* contains a rescaled version of the image, in output directory */ /* create temporary file name */ fits_file_name(outfptr, outfits, &stat); /* get the output file name */ fp_tmpnam("Tmp3", outfits, tempfilename3); fits_create_file(&tempfile, tempfilename3, &stat); fits_get_hdu_num(infptr, &hdunum); if (hdunum != 1) { /* the input hdu is an image extension, so create dummy primary */ fits_create_img(tempfile, 8, 0, naxes, &stat); } fits_copy_header(infptr, tempfile, &stat); /* copy the header */ /* rescale the data, so that it will compress more efficiently */ if (bitpix == LONG_IMG) fp_i4rescale(infptr, naxis, naxes, rescale, tempfile, &stat); else fp_i2rescale(infptr, naxis, naxes, rescale, tempfile, &stat); /* scale the BSCALE keyword by the inverse factor */ bscale = bscale * rescale; fits_update_key(tempfile, TDOUBLE, "BSCALE", &bscale, 0, &stat); /* rescan the header, to reset the actual scaling parameters */ fits_set_hdustruc(tempfile, &stat); fits_img_compress (tempfile, outfptr, &stat); fits_delete_file (tempfile, &stat); tempfilename3[0] = '\0'; /* clear the temp filename */ *islossless = 0; /* used a lossy compression method */ *status = stat; return(0); } } } /* if requested to do lossy compression of integer images (by */ /* converting to float), then check if this HDU qualifies */ if ( (bitpix > 0) && (fpvar.int_to_float != 0) ) { if (bitpix >= LONG_IMG) fp_i4stat(infptr, naxis, naxes, &imagestats, &stat); else fp_i2stat(infptr, naxis, naxes, &imagestats, &stat); /* rescan the image header to reset scaling values (changed by fp_iNstat) */ ffrhdu(infptr, &hdutype, &stat); /* use the minimum of the MAD 2nd, 3rd, and 5th order noise estimates */ noisemin = imagestats.noise3; if (imagestats.noise2 != 0. && imagestats.noise2 < noisemin) noisemin = imagestats.noise2; if (imagestats.noise5 != 0. && imagestats.noise5 < noisemin) noisemin = imagestats.noise5; if ( (noisemin < (fpvar.n3ratio * fpvar.quantize_level) ) || (imagestats.noise3 < fpvar.n3min)) { /* image contains too little noise to quantize effectively */ fits_set_lossy_int (outfptr, 0, &stat); fits_get_hdu_num(infptr, &hdunum); printf(" HDU %d does not meet noise criteria to be quantized, so losslessly compressed.\n", hdunum); } else { /* compressed image is not identical to original */ *islossless = 0; } } /* finally, do the actual image compression */ fits_img_compress (infptr, outfptr, &stat); if (bitpix < 0 || (fpvar.comptype == HCOMPRESS_1 && fpvar.scale != 0.)) { /* compressed image is not identical to original */ *islossless = 0; } } *status = stat; return(0); } /*--------------------------------------------------------------------------*/ int fp_unpack_hdu (fitsfile *infptr, fitsfile *outfptr, fpstate fpvar, int *status) { int hdutype, lval; if (*status > 0) return(0); fits_get_hdu_type (infptr, &hdutype, status); /* =============================================================== */ /* This block is only for beta testing of binary table compression */ if (hdutype == BINARY_TBL) { fits_read_key(infptr, TLOGICAL, "ZTABLE", &lval, NULL, status); if (*status == 0 && lval != 0) { /* uncompress the table */ fits_uncompress_table (infptr, outfptr, status); } else { if (*status == KEY_NO_EXIST) /* table is not compressed */ *status = 0; fits_copy_hdu (infptr, outfptr, 0, status); } return(0); /* =============================================================== */ } else if (fits_is_compressed_image (infptr, status)) { /* uncompress the compressed image HDU */ fits_img_decompress (infptr, outfptr, status); } else { /* not a compressed image HDU, so just copy it to the output */ fits_copy_hdu (infptr, outfptr, 0, status); } return(0); } /*--------------------------------------------------------------------------*/ int fits_read_image_speed (fitsfile *infptr, float *whole_elapse, float *whole_cpu, float *row_elapse, float *row_cpu, int *status) { unsigned char *carray, cnull = 0; short *sarray, snull=0; int bitpix, naxis, anynull, *iarray, inull = 0; long ii, naxes[9], fpixel[9]={1,1,1,1,1,1,1,1,1}, lpixel[9]={1,1,1,1,1,1,1,1,1}; long inc[9]={1,1,1,1,1,1,1,1,1} ; float *earray, enull = 0, filesize; double *darray, dnull = 0; if (*status) return(*status); fits_get_img_param (infptr, 9, &bitpix, &naxis, naxes, status); if (naxis != 2)return(*status); lpixel[0] = naxes[0]; lpixel[1] = naxes[1]; /* filesize in MB */ filesize = (float) (naxes[0] * abs(bitpix) / 8000000. * naxes[1]); /* measure time required to read the raw image */ fits_set_bscale(infptr, 1.0, 0.0, status); *whole_elapse = 0.; *whole_cpu = 0; if (bitpix == BYTE_IMG) { carray = calloc(naxes[1]*naxes[0], sizeof(char)); /* remove any cached uncompressed tile (dangerous to directly modify the structure!) */ /* (infptr->Fptr)->tilerow = 0; */ marktime(status); fits_read_subset(infptr, TBYTE, fpixel, lpixel, inc, &cnull, carray, &anynull, status); /* get elapsped times */ gettime(whole_elapse, whole_cpu, status); /* now read the image again, row by row */ if (row_elapse) { /* remove any cached uncompressed tile (dangerous to directly modify the structure!) */ /* (infptr->Fptr)->tilerow = 0; */ marktime(status); for (ii = 0; ii < naxes[1]; ii++) { fpixel[1] = ii+1; fits_read_pix(infptr, TBYTE, fpixel, naxes[0], &cnull, carray, &anynull, status); } /* get elapsped times */ gettime(row_elapse, row_cpu, status); } free(carray); } else if (bitpix == SHORT_IMG) { sarray = calloc(naxes[0]*naxes[1], sizeof(short)); marktime(status); fits_read_subset(infptr, TSHORT, fpixel, lpixel, inc, &snull, sarray, &anynull, status); gettime(whole_elapse, whole_cpu, status); /* get elapsped times */ /* now read the image again, row by row */ if (row_elapse) { marktime(status); for (ii = 0; ii < naxes[1]; ii++) { fpixel[1] = ii+1; fits_read_pix(infptr, TSHORT, fpixel, naxes[0], &snull, sarray, &anynull, status); } /* get elapsped times */ gettime(row_elapse, row_cpu, status); } free(sarray); } else if (bitpix == LONG_IMG) { iarray = calloc(naxes[0]*naxes[1], sizeof(int)); marktime(status); fits_read_subset(infptr, TINT, fpixel, lpixel, inc, &inull, iarray, &anynull, status); /* get elapsped times */ gettime(whole_elapse, whole_cpu, status); /* now read the image again, row by row */ if (row_elapse) { marktime(status); for (ii = 0; ii < naxes[1]; ii++) { fpixel[1] = ii+1; fits_read_pix(infptr, TINT, fpixel, naxes[0], &inull, iarray, &anynull, status); } /* get elapsped times */ gettime(row_elapse, row_cpu, status); } free(iarray); } else if (bitpix == FLOAT_IMG) { earray = calloc(naxes[1]*naxes[0], sizeof(float)); marktime(status); fits_read_subset(infptr, TFLOAT, fpixel, lpixel, inc, &enull, earray, &anynull, status); /* get elapsped times */ gettime(whole_elapse, whole_cpu, status); /* now read the image again, row by row */ if (row_elapse) { marktime(status); for (ii = 0; ii < naxes[1]; ii++) { fpixel[1] = ii+1; fits_read_pix(infptr, TFLOAT, fpixel, naxes[0], &enull, earray, &anynull, status); } /* get elapsped times */ gettime(row_elapse, row_cpu, status); } free(earray); } else if (bitpix == DOUBLE_IMG) { darray = calloc(naxes[1]*naxes[0], sizeof(double)); marktime(status); fits_read_subset(infptr, TDOUBLE, fpixel, lpixel, inc, &dnull, darray, &anynull, status); /* get elapsped times */ gettime(whole_elapse, whole_cpu, status); /* now read the image again, row by row */ if (row_elapse) { marktime(status); for (ii = 0; ii < naxes[1]; ii++) { fpixel[1] = ii+1; fits_read_pix(infptr, TDOUBLE, fpixel, naxes[0], &dnull, darray, &anynull, status); } /* get elapsped times */ gettime(row_elapse, row_cpu, status); } free(darray); } if (whole_elapse) *whole_elapse = *whole_elapse / filesize; if (row_elapse) *row_elapse = *row_elapse / filesize; if (whole_cpu) *whole_cpu = *whole_cpu / filesize; if (row_cpu) *row_cpu = *row_cpu / filesize; return(*status); } /*--------------------------------------------------------------------------*/ int fp_test_hdu (fitsfile *infptr, fitsfile *outfptr, fitsfile *outfptr2, fpstate fpvar, int *status) { /* This routine is only used for performance testing of image HDUs. */ /* Use fp_test_table for testing binary table HDUs. */ int stat = 0, hdutype, comptype; char ctype[20], lossless[4]; long headstart, datastart, dataend; float origdata = 0., compressdata = 0.; float compratio = 0., packcpu = 0., unpackcpu = 0.; float elapse, whole_elapse, row_elapse, whole_cpu, row_cpu; unsigned long datasum1, datasum2, hdusum; if (*status) return(0); origdata = 0; compressdata = 0; compratio = 0.; lossless[0] = '\0'; fits_get_compression_type(outfptr, &comptype, &stat); if (comptype == RICE_1) strcpy(ctype, "RICE"); else if (comptype == GZIP_1) strcpy(ctype, "GZIP1"); else if (comptype == GZIP_2) strcpy(ctype, "GZIP2");/* else if (comptype == BZIP2_1) strcpy(ctype, "BZIP2"); */ else if (comptype == PLIO_1) strcpy(ctype, "PLIO"); else if (comptype == HCOMPRESS_1) strcpy(ctype, "HCOMP"); else if (comptype == NOCOMPRESS) strcpy(ctype, "NONE"); else { fp_msg ("Error: unsupported image compression type "); *status = DATA_COMPRESSION_ERR; return(0); } /* -------------- COMPRESS the image ------------------ */ marktime(&stat); fits_img_compress (infptr, outfptr, &stat); /* get elapsped times */ gettime(&elapse, &packcpu, &stat); /* get elapsed and cpu times need to read the compressed image */ fits_read_image_speed (outfptr, &whole_elapse, &whole_cpu, &row_elapse, &row_cpu, &stat); if (!stat) { /* -------------- UNCOMPRESS the image ------------------ */ /* remove any cached uncompressed tile (dangerous to directly modify the structure!) */ /* (outfptr->Fptr)->tilerow = 0; */ marktime(&stat); fits_img_decompress (outfptr, outfptr2, &stat); /* get elapsped times */ gettime(&elapse, &unpackcpu, &stat); /* ----------------------------------------------------- */ /* get sizes of original and compressed images */ fits_get_hduaddr(infptr, &headstart, &datastart, &dataend, &stat); origdata = (float) ((dataend - datastart)/1000000.); fits_get_hduaddr(outfptr, &headstart, &datastart, &dataend, &stat); compressdata = (float) ((dataend - datastart)/1000000.); if (compressdata != 0) compratio = (float) origdata / (float) compressdata; /* is this uncompressed image identical to the original? */ fits_get_chksum(infptr, &datasum1, &hdusum, &stat); fits_get_chksum(outfptr2, &datasum2, &hdusum, &stat); if ( datasum1 == datasum2) { strcpy(lossless, "Yes"); } else { strcpy(lossless, "No"); } printf(" %-5s %6.2f %7.2f ->%7.2f %7.2f %7.2f %s %5.3f %5.3f %5.3f %5.3f\n", ctype, compratio, origdata, compressdata, packcpu, unpackcpu, lossless, whole_elapse, whole_cpu, row_elapse, row_cpu); if (fpvar.outfile[0]) { fprintf(outreport," %6.3f %5.2f %5.2f %s %7.3f %7.3f %7.3f %7.3f", compratio, packcpu, unpackcpu, lossless, whole_elapse, whole_cpu, row_elapse, row_cpu); } /* delete the output HDUs to concerve disk space */ fits_delete_hdu(outfptr, &hdutype, &stat); fits_delete_hdu(outfptr2, &hdutype, &stat); } else { printf(" %-5s (unable to compress image)\n", ctype); } /* try to recover from any compression errors */ if (stat == DATA_COMPRESSION_ERR) stat = 0; *status = stat; return(0); } /*--------------------------------------------------------------------------*/ int fp_test_table (fitsfile *infptr, fitsfile *outfptr, fitsfile *outfptr2, fpstate fpvar, int *status) { /* this routine is for performance testing of the table compression methods */ int stat = 0, hdutype, tstatus = 0; char fzalgor[FLEN_VALUE]; LONGLONG headstart, datastart, dataend; float elapse, cpu; if (*status) return(0); /* check directive keyword to see if this HDU should not be compressed */ if (!fits_read_key(infptr, TSTRING, "FZALGOR", fzalgor, NULL, &tstatus) ) { if (!strcmp(fzalgor, "NONE") || !strcmp(fzalgor, "none")) { return(0); } } fits_get_hduaddrll(infptr, &headstart, &datastart, &dataend, status); /* can't compress small tables with less than 2880 bytes of data */ if (dataend - datastart <= 2880) { return(0); } marktime(&stat); stat= -999; /* set special flag value */ fits_compress_table (infptr, outfptr, &stat); /* get elapsped times */ gettime(&elapse, &cpu, &stat); fits_delete_hdu(outfptr, &hdutype, &stat); printf("\nElapsed time = %f, cpu = %f\n", elapse, cpu); fits_report_error (stderr, stat); return(0); } /*--------------------------------------------------------------------------*/ int marktime(int *status) { #if defined(unix) || defined(__unix__) || defined(__unix) struct timeval tv; /* struct timezone tz; */ /* gettimeofday (&tv, &tz); */ gettimeofday (&tv, NULL); startsec = tv.tv_sec; startmilli = tv.tv_usec/1000; scpu = clock(); #else /* don't support high timing precision on Windows machines */ startsec = 0; startmilli = 0; scpu = clock(); #endif return( *status ); } /*--------------------------------------------------------------------------*/ int gettime(float *elapse, float *elapscpu, int *status) { #if defined(unix) || defined(__unix__) || defined(__unix) struct timeval tv; /* struct timezone tz; */ int stopmilli; long stopsec; /* gettimeofday (&tv, &tz); */ gettimeofday (&tv, NULL); ecpu = clock(); stopmilli = tv.tv_usec/1000; stopsec = tv.tv_sec; *elapse = (stopsec - startsec) + (stopmilli - startmilli)/1000.; *elapscpu = (ecpu - scpu) * 1.0 / CLOCKTICKS; /* printf(" (start: %ld + %d), stop: (%ld + %d) elapse: %f\n ", startsec,startmilli,stopsec, stopmilli, *elapse); */ #else /* set the elapsed time the same as the CPU time on Windows machines */ *elapscpu = (float) ((ecpu - scpu) * 1.0 / CLOCKTICKS); *elapse = *elapscpu; #endif return( *status ); } /*--------------------------------------------------------------------------*/ int fp_i2stat(fitsfile *infptr, int naxis, long *naxes, imgstats *imagestats, int *status) { /* read the central XSAMPLE by YSAMPLE region of pixels in the int*2 image, and then compute basic statistics: min, max, mean, sigma, mean diff, etc. */ long fpixel[9] = {1,1,1,1,1,1,1,1,1}; long lpixel[9] = {1,1,1,1,1,1,1,1,1}; long inc[9] = {1,1,1,1,1,1,1,1,1}; long i1, i2, npix, ngood, nx, ny; short *intarray, minvalue, maxvalue, nullvalue; int anynul, tstatus, checknull = 1; double mean, sigma, noise1, noise2, noise3, noise5; /* select the middle XSAMPLE by YSAMPLE area of the image */ i1 = naxes[0]/2 - (XSAMPLE/2 - 1); i2 = naxes[0]/2 + (XSAMPLE/2); if (i1 < 1) i1 = 1; if (i2 > naxes[0]) i2 = naxes[0]; fpixel[0] = i1; lpixel[0] = i2; nx = i2 - i1 +1; if (naxis > 1) { i1 = naxes[1]/2 - (YSAMPLE/2 - 1); i2 = naxes[1]/2 + (YSAMPLE/2); if (i1 < 1) i1 = 1; if (i2 > naxes[1]) i2 = naxes[1]; fpixel[1] = i1; lpixel[1] = i2; } ny = i2 - i1 +1; npix = nx * ny; /* if there are higher dimensions, read the middle plane of the cube */ if (naxis > 2) { fpixel[2] = naxes[2]/2 + 1; lpixel[2] = naxes[2]/2 + 1; } intarray = calloc(npix, sizeof(short)); if (!intarray) { *status = MEMORY_ALLOCATION; return(*status); } /* turn off any scaling of the integer pixel values */ fits_set_bscale(infptr, 1.0, 0.0, status); fits_read_subset_sht(infptr, 0, naxis, naxes, fpixel, lpixel, inc, 0, intarray, &anynul, status); /* read the null value keyword (BLANK) if present */ tstatus = 0; fits_read_key(infptr, TSHORT, "BLANK", &nullvalue, 0, &tstatus); if (tstatus) { nullvalue = 0; checknull = 0; } /* compute statistics of the image */ fits_img_stats_short(intarray, nx, ny, checknull, nullvalue, &ngood, &minvalue, &maxvalue, &mean, &sigma, &noise1, &noise2, &noise3, &noise5, status); imagestats->n_nulls = npix - ngood; imagestats->minval = minvalue; imagestats->maxval = maxvalue; imagestats->mean = mean; imagestats->sigma = sigma; imagestats->noise1 = noise1; imagestats->noise2 = noise2; imagestats->noise3 = noise3; imagestats->noise5 = noise5; free(intarray); return(*status); } /*--------------------------------------------------------------------------*/ int fp_i4stat(fitsfile *infptr, int naxis, long *naxes, imgstats *imagestats, int *status) { /* read the central XSAMPLE by YSAMPLE region of pixels in the int*2 image, and then compute basic statistics: min, max, mean, sigma, mean diff, etc. */ long fpixel[9] = {1,1,1,1,1,1,1,1,1}; long lpixel[9] = {1,1,1,1,1,1,1,1,1}; long inc[9] = {1,1,1,1,1,1,1,1,1}; long i1, i2, npix, ngood, nx, ny; int *intarray, minvalue, maxvalue, nullvalue; int anynul, tstatus, checknull = 1; double mean, sigma, noise1, noise2, noise3, noise5; /* select the middle XSAMPLE by YSAMPLE area of the image */ i1 = naxes[0]/2 - (XSAMPLE/2 - 1); i2 = naxes[0]/2 + (XSAMPLE/2); if (i1 < 1) i1 = 1; if (i2 > naxes[0]) i2 = naxes[0]; fpixel[0] = i1; lpixel[0] = i2; nx = i2 - i1 +1; if (naxis > 1) { i1 = naxes[1]/2 - (YSAMPLE/2 - 1); i2 = naxes[1]/2 + (YSAMPLE/2); if (i1 < 1) i1 = 1; if (i2 > naxes[1]) i2 = naxes[1]; fpixel[1] = i1; lpixel[1] = i2; } ny = i2 - i1 +1; npix = nx * ny; /* if there are higher dimensions, read the middle plane of the cube */ if (naxis > 2) { fpixel[2] = naxes[2]/2 + 1; lpixel[2] = naxes[2]/2 + 1; } intarray = calloc(npix, sizeof(int)); if (!intarray) { *status = MEMORY_ALLOCATION; return(*status); } /* turn off any scaling of the integer pixel values */ fits_set_bscale(infptr, 1.0, 0.0, status); fits_read_subset_int(infptr, 0, naxis, naxes, fpixel, lpixel, inc, 0, intarray, &anynul, status); /* read the null value keyword (BLANK) if present */ tstatus = 0; fits_read_key(infptr, TINT, "BLANK", &nullvalue, 0, &tstatus); if (tstatus) { nullvalue = 0; checknull = 0; } /* compute statistics of the image */ fits_img_stats_int(intarray, nx, ny, checknull, nullvalue, &ngood, &minvalue, &maxvalue, &mean, &sigma, &noise1, &noise2, &noise3, &noise5, status); imagestats->n_nulls = npix - ngood; imagestats->minval = minvalue; imagestats->maxval = maxvalue; imagestats->mean = mean; imagestats->sigma = sigma; imagestats->noise1 = noise1; imagestats->noise2 = noise2; imagestats->noise3 = noise3; imagestats->noise5 = noise5; free(intarray); return(*status); } /*--------------------------------------------------------------------------*/ int fp_r4stat(fitsfile *infptr, int naxis, long *naxes, imgstats *imagestats, int *status) { /* read the central XSAMPLE by YSAMPLE region of pixels in the int*2 image, and then compute basic statistics: min, max, mean, sigma, mean diff, etc. */ long fpixel[9] = {1,1,1,1,1,1,1,1,1}; long lpixel[9] = {1,1,1,1,1,1,1,1,1}; long inc[9] = {1,1,1,1,1,1,1,1,1}; long i1, i2, npix, ngood, nx, ny; float *array, minvalue, maxvalue, nullvalue = FLOATNULLVALUE; int anynul,checknull = 1; double mean, sigma, noise1, noise2, noise3, noise5; /* select the middle XSAMPLE by YSAMPLE area of the image */ i1 = naxes[0]/2 - (XSAMPLE/2 - 1); i2 = naxes[0]/2 + (XSAMPLE/2); if (i1 < 1) i1 = 1; if (i2 > naxes[0]) i2 = naxes[0]; fpixel[0] = i1; lpixel[0] = i2; nx = i2 - i1 +1; if (naxis > 1) { i1 = naxes[1]/2 - (YSAMPLE/2 - 1); i2 = naxes[1]/2 + (YSAMPLE/2); if (i1 < 1) i1 = 1; if (i2 > naxes[1]) i2 = naxes[1]; fpixel[1] = i1; lpixel[1] = i2; } ny = i2 - i1 +1; npix = nx * ny; /* if there are higher dimensions, read the middle plane of the cube */ if (naxis > 2) { fpixel[2] = naxes[2]/2 + 1; lpixel[2] = naxes[2]/2 + 1; } array = calloc(npix, sizeof(float)); if (!array) { *status = MEMORY_ALLOCATION; return(*status); } fits_read_subset_flt(infptr, 0, naxis, naxes, fpixel, lpixel, inc, nullvalue, array, &anynul, status); /* are there any null values in the array? */ if (!anynul) { nullvalue = 0.; checknull = 0; } /* compute statistics of the image */ fits_img_stats_float(array, nx, ny, checknull, nullvalue, &ngood, &minvalue, &maxvalue, &mean, &sigma, &noise1, &noise2, &noise3, &noise5, status); imagestats->n_nulls = npix - ngood; imagestats->minval = minvalue; imagestats->maxval = maxvalue; imagestats->mean = mean; imagestats->sigma = sigma; imagestats->noise1 = noise1; imagestats->noise2 = noise2; imagestats->noise3 = noise3; imagestats->noise5 = noise5; free(array); return(*status); } /*--------------------------------------------------------------------------*/ int fp_i2rescale(fitsfile *infptr, int naxis, long *naxes, double rescale, fitsfile *outfptr, int *status) { /* divide the integer pixel values in the input file by rescale, and write back out to the output file.. */ long ii, jj, nelem = 1, nx, ny; short *intarray, nullvalue; int anynul, tstatus, checknull = 1; nx = naxes[0]; ny = 1; for (ii = 1; ii < naxis; ii++) { ny = ny * naxes[ii]; } intarray = calloc(nx, sizeof(short)); if (!intarray) { *status = MEMORY_ALLOCATION; return(*status); } /* read the null value keyword (BLANK) if present */ tstatus = 0; fits_read_key(infptr, TSHORT, "BLANK", &nullvalue, 0, &tstatus); if (tstatus) { checknull = 0; } /* turn off any scaling of the integer pixel values */ fits_set_bscale(infptr, 1.0, 0.0, status); fits_set_bscale(outfptr, 1.0, 0.0, status); for (ii = 0; ii < ny; ii++) { fits_read_img_sht(infptr, 1, nelem, nx, 0, intarray, &anynul, status); if (checknull) { for (jj = 0; jj < nx; jj++) { if (intarray[jj] != nullvalue) intarray[jj] = NSHRT( (intarray[jj] / rescale) ); } } else { for (jj = 0; jj < nx; jj++) intarray[jj] = NSHRT( (intarray[jj] / rescale) ); } fits_write_img_sht(outfptr, 1, nelem, nx, intarray, status); nelem += nx; } free(intarray); return(*status); } /*--------------------------------------------------------------------------*/ int fp_i4rescale(fitsfile *infptr, int naxis, long *naxes, double rescale, fitsfile *outfptr, int *status) { /* divide the integer pixel values in the input file by rescale, and write back out to the output file.. */ long ii, jj, nelem = 1, nx, ny; int *intarray, nullvalue; int anynul, tstatus, checknull = 1; nx = naxes[0]; ny = 1; for (ii = 1; ii < naxis; ii++) { ny = ny * naxes[ii]; } intarray = calloc(nx, sizeof(int)); if (!intarray) { *status = MEMORY_ALLOCATION; return(*status); } /* read the null value keyword (BLANK) if present */ tstatus = 0; fits_read_key(infptr, TINT, "BLANK", &nullvalue, 0, &tstatus); if (tstatus) { checknull = 0; } /* turn off any scaling of the integer pixel values */ fits_set_bscale(infptr, 1.0, 0.0, status); fits_set_bscale(outfptr, 1.0, 0.0, status); for (ii = 0; ii < ny; ii++) { fits_read_img_int(infptr, 1, nelem, nx, 0, intarray, &anynul, status); if (checknull) { for (jj = 0; jj < nx; jj++) { if (intarray[jj] != nullvalue) intarray[jj] = NINT( (intarray[jj] / rescale) ); } } else { for (jj = 0; jj < nx; jj++) intarray[jj] = NINT( (intarray[jj] / rescale) ); } fits_write_img_int(outfptr, 1, nelem, nx, intarray, status); nelem += nx; } free(intarray); return(*status); } /* ======================================================================== * Signal and error handler. */ void abort_fpack(int sig) { /* clean up by deleting temporary files */ if (tempfilename[0]) { remove(tempfilename); } if (tempfilename2[0]) { remove(tempfilename2); } if (tempfilename3[0]) { remove(tempfilename3); } exit(-1); } cfitsio/funpack.c0000644000225700000360000001051513246025103013575 0ustar cagordonlhea/* FUNPACK * R. Seaman, NOAO * uses fits_img_compress by W. Pence, HEASARC */ #include "fitsio.h" #include "fpack.h" int main (int argc, char *argv[]) { fpstate fpvar; if (argc <= 1) { fu_usage (); fu_hint (); exit (-1); } fp_init (&fpvar); fu_get_param (argc, argv, &fpvar); if (fpvar.listonly) { fp_list (argc, argv, fpvar); } else { fp_preflight (argc, argv, FUNPACK, &fpvar); fp_loop (argc, argv, FUNPACK, fpvar); } exit (0); } int fu_get_param (int argc, char *argv[], fpstate *fpptr) { int iarg; char tile[SZ_STR]; if (fpptr->initialized != FP_INIT_MAGIC) { fp_msg ("Error: internal initialization error\n"); exit (-1); } tile[0] = 0; /* by default, .fz suffix characters to be deleted from compressed file */ fpptr->delete_suffix = 1; /* flags must come first and be separately specified */ for (iarg = 1; iarg < argc; iarg++) { if (argv[iarg][0] == '-' && strlen (argv[iarg]) == 2) { if (argv[iarg][1] == 'F') { fpptr->clobber++; fpptr->delete_suffix = 0; /* no suffix in this case */ } else if (argv[iarg][1] == 'D') { fpptr->delete_input++; } else if (argv[iarg][1] == 'P') { if (++iarg >= argc) { fu_usage (); fu_hint (); exit (-1); } else strncpy (fpptr->prefix, argv[iarg], SZ_STR); } else if (argv[iarg][1] == 'E') { if (++iarg >= argc) { fu_usage (); fu_hint (); exit (-1); } else strncpy (fpptr->extname, argv[iarg], SZ_STR); } else if (argv[iarg][1] == 'S') { fpptr->to_stdout++; } else if (argv[iarg][1] == 'L') { fpptr->listonly++; } else if (argv[iarg][1] == 'C') { fpptr->do_checksums = 0; } else if (argv[iarg][1] == 'H') { fu_help (); exit (0); } else if (argv[iarg][1] == 'V') { fp_version (); exit (0); } else if (argv[iarg][1] == 'Z') { fpptr->do_gzip_file++; } else if (argv[iarg][1] == 'v') { fpptr->verbose = 1; } else if (argv[iarg][1] == 'O') { if (++iarg >= argc) { fu_usage (); fu_hint (); exit (-1); } else strncpy (fpptr->outfile, argv[iarg], SZ_STR); } else { fp_msg ("Error: unknown command line flag `"); fp_msg (argv[iarg]); fp_msg ("'\n"); fu_usage (); fu_hint (); exit (-1); } } else break; } if (fpptr->extname[0] && (fpptr->clobber || fpptr->delete_input)) { fp_msg ("Error: -E option may not be used with -F or -D\n"); fu_usage (); exit (-1); } if (fpptr->to_stdout && (fpptr->outfile[0] || fpptr->prefix[0]) ) { fp_msg ("Error: -S option may not be used with -P or -O\n"); fu_usage (); exit (-1); } if (fpptr->outfile[0] && fpptr->prefix[0] ) { fp_msg ("Error: -P and -O options may not be used together\n"); fu_usage (); exit (-1); } if (iarg >= argc) { fp_msg ("Error: no FITS files to uncompress\n"); fu_usage (); exit (-1); } else fpptr->firstfile = iarg; return(0); } int fu_usage (void) { fp_msg ("usage: funpack [-E ] [-P

] [-O ] [-Z] -v \n");
        fp_msg ("more:   [-F] [-D] [-S] [-L] [-C] [-H] [-V] \n");
	return(0);
}

int fu_hint (void)
{
	fp_msg ("      `funpack -H' for help\n");
	return(0);
}

int fu_help (void)
{
fp_msg ("funpack, decompress fpacked files.  Version ");
fp_version ();
fu_usage ();
fp_msg ("\n");

fp_msg ("Flags must be separate and appear before filenames:\n");
fp_msg (" -E  Unpack only the list of HDU names or numbers in the file.\n");
fp_msg (" -P 
    Prepend 
 to create new output filenames.\n");
fp_msg (" -O    Specify full output file name.\n");
fp_msg (" -Z          Recompress the output file with host GZIP program.\n");
fp_msg (" -F          Overwrite input file by output file with same name.\n");
fp_msg (" -D          Delete input file after writing output.\n");
fp_msg (" -S          Output uncompressed file to STDOUT file stream.\n");
fp_msg (" -L          List contents, files unchanged.\n");

fp_msg (" -C          Don't update FITS checksum keywords.\n");

fp_msg (" -v          Verbose mode; list each file as it is processed.\n");
fp_msg (" -H          Show this message.\n");
fp_msg (" -V          Show version number.\n");

fp_msg (" \n       FITS files to unpack; enter '-' (a hyphen) to read from stdin.\n");
fp_msg (" Refer to the fpack User's Guide for more extensive help.\n");
	return(0);
}
cfitsio/getcol.c0000644000225700000360000011541413246025103013427 0ustar  cagordonlhea
/*  This file, getcol.c, contains routines that read data elements from    */
/*  a FITS image or table.  There are generic datatype routines.           */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int ffgpxv( fitsfile *fptr,   /* I - FITS file pointer                       */
            int  datatype,    /* I - datatype of the value                   */
            long *firstpix,   /* I - coord of first pixel to read (1s based) */
            LONGLONG nelem,   /* I - number of values to read                */
            void *nulval,     /* I - value for undefined pixels              */
            void *array,      /* O - array of values that are returned       */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. The datatype of the
  input array is defined by the 2nd argument.  Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Undefined elements will be set equal to NULVAL, unless NULVAL=0
  in which case no checking for undefined values will be performed.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    LONGLONG tfirstpix[99];
    int naxis, ii;

    if (*status > 0 || nelem == 0)   /* inherit input status value if > 0 */
        return(*status);

    /* get the size of the image */
    ffgidm(fptr, &naxis, status);
    
    for (ii=0; ii < naxis; ii++)
       tfirstpix[ii] = firstpix[ii];

    ffgpxvll(fptr, datatype, tfirstpix, nelem, nulval, array, anynul, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgpxvll( fitsfile *fptr, /* I - FITS file pointer                       */
            int  datatype,    /* I - datatype of the value                   */
            LONGLONG *firstpix, /* I - coord of first pixel to read (1s based) */
            LONGLONG nelem,   /* I - number of values to read                */
            void *nulval,     /* I - value for undefined pixels              */
            void *array,      /* O - array of values that are returned       */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. The datatype of the
  input array is defined by the 2nd argument.  Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Undefined elements will be set equal to NULVAL, unless NULVAL=0
  in which case no checking for undefined values will be performed.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    int naxis, ii;
    char cdummy;
    int nullcheck = 1;
    LONGLONG naxes[9], trc[9]= {1,1,1,1,1,1,1,1,1};
    long inc[9]= {1,1,1,1,1,1,1,1,1};
    LONGLONG dimsize = 1, firstelem;

    if (*status > 0 || nelem == 0)   /* inherit input status value if > 0 */
        return(*status);

    /* get the size of the image */
    ffgidm(fptr, &naxis, status);

    ffgiszll(fptr, 9, naxes, status);

    if (naxis == 0 || naxes[0] == 0) {
       *status = BAD_DIMEN;
       return(*status);
    }

    /* calculate the position of the first element in the array */
    firstelem = 0;
    for (ii=0; ii < naxis; ii++)
    {
        firstelem += ((firstpix[ii] - 1) * dimsize);
        dimsize *= naxes[ii];
        trc[ii] = firstpix[ii];
    }
    firstelem++;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        /* test for special case of reading an integral number of */
        /* rows in a 2D or 3D image (which includes reading the whole image */

	if (naxis > 1 && naxis < 4 && firstpix[0] == 1 &&
            (nelem / naxes[0]) * naxes[0] == nelem) {

                /* calculate coordinate of last pixel */
		trc[0] = naxes[0];  /* reading whole rows */
		trc[1] = firstpix[1] + (nelem / naxes[0] - 1);
                while (trc[1] > naxes[1])  {
		    trc[1] = trc[1] - naxes[1];
		    trc[2] = trc[2] + 1;  /* increment to next plane of cube */
                }

                fits_read_compressed_img(fptr, datatype, firstpix, trc, inc,
                   1, nulval, array, NULL, anynul, status);

        } else {

                fits_read_compressed_pixels(fptr, datatype, firstelem,
                   nelem, nullcheck, nulval, array, NULL, anynul, status);
        }

        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (datatype == TBYTE)
    {
      if (nulval == 0)
        ffgclb(fptr, 2, 1, firstelem, nelem, 1, 1, 0,
               (unsigned char *) array, &cdummy, anynul, status);
      else
        ffgclb(fptr, 2, 1, firstelem, nelem, 1, 1, *(unsigned char *) nulval,
               (unsigned char *) array, &cdummy, anynul, status);
    }
    else if (datatype == TSBYTE)
    {
      if (nulval == 0)
        ffgclsb(fptr, 2, 1, firstelem, nelem, 1, 1, 0,
               (signed char *) array, &cdummy, anynul, status);
      else
        ffgclsb(fptr, 2, 1, firstelem, nelem, 1, 1, *(signed char *) nulval,
               (signed char *) array, &cdummy, anynul, status);
    }
    else if (datatype == TUSHORT)
    {
      if (nulval == 0)
        ffgclui(fptr, 2, 1, firstelem, nelem, 1, 1, 0,
               (unsigned short *) array, &cdummy, anynul, status);
      else
        ffgclui(fptr, 2, 1, firstelem, nelem, 1, 1, *(unsigned short *) nulval,
               (unsigned short *) array, &cdummy, anynul, status);
    }
    else if (datatype == TSHORT)
    {
      if (nulval == 0)
        ffgcli(fptr, 2, 1, firstelem, nelem, 1, 1, 0,
               (short *) array, &cdummy, anynul, status);
      else
        ffgcli(fptr, 2, 1, firstelem, nelem, 1, 1, *(short *) nulval,
               (short *) array, &cdummy, anynul, status);
    }
    else if (datatype == TUINT)
    {
      if (nulval == 0)
        ffgcluk(fptr, 2, 1, firstelem, nelem, 1, 1, 0,
               (unsigned int *) array, &cdummy, anynul, status);
      else
        ffgcluk(fptr, 2, 1, firstelem, nelem, 1, 1, *(unsigned int *) nulval,
               (unsigned int *) array, &cdummy, anynul, status);
    }
    else if (datatype == TINT)
    {
      if (nulval == 0)
        ffgclk(fptr, 2, 1, firstelem, nelem, 1, 1, 0,
               (int *) array, &cdummy, anynul, status);
      else
        ffgclk(fptr, 2, 1, firstelem, nelem, 1, 1, *(int *) nulval,
               (int *) array, &cdummy, anynul, status);
    }
    else if (datatype == TULONG)
    {
      if (nulval == 0)
        ffgcluj(fptr, 2, 1, firstelem, nelem, 1, 1, 0,
               (unsigned long *) array, &cdummy, anynul, status);
      else
        ffgcluj(fptr, 2, 1, firstelem, nelem, 1, 1, *(unsigned long *) nulval,
               (unsigned long *) array, &cdummy, anynul, status);
    }
    else if (datatype == TLONG)
    {
      if (nulval == 0)
        ffgclj(fptr, 2, 1, firstelem, nelem, 1, 1, 0,
               (long *) array, &cdummy, anynul, status);
      else
        ffgclj(fptr, 2, 1, firstelem, nelem, 1, 1, *(long *) nulval,
               (long *) array, &cdummy, anynul, status);
    }
    else if (datatype == TLONGLONG)
    {
      if (nulval == 0)
        ffgcljj(fptr, 2, 1, firstelem, nelem, 1, 1, 0,
               (LONGLONG *) array, &cdummy, anynul, status);
      else
        ffgcljj(fptr, 2, 1, firstelem, nelem, 1, 1, *(LONGLONG *) nulval,
               (LONGLONG *) array, &cdummy, anynul, status);
    }
    else if (datatype == TFLOAT)
    {
      if (nulval == 0)
        ffgcle(fptr, 2, 1, firstelem, nelem, 1, 1, 0,
               (float *) array, &cdummy, anynul, status);
      else
        ffgcle(fptr, 2, 1, firstelem, nelem, 1, 1, *(float *) nulval,
               (float *) array, &cdummy, anynul, status);
    }
    else if (datatype == TDOUBLE)
    {
      if (nulval == 0)
        ffgcld(fptr, 2, 1, firstelem, nelem, 1, 1, 0,
               (double *) array, &cdummy, anynul, status);
      else
        ffgcld(fptr, 2, 1, firstelem, nelem, 1, 1, *(double *) nulval,
               (double *) array, &cdummy, anynul, status);
    }
    else
      *status = BAD_DATATYPE;

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgpxf( fitsfile *fptr,   /* I - FITS file pointer                       */
            int  datatype,    /* I - datatype of the value                   */
            long *firstpix,   /* I - coord of first pixel to read (1s based) */
            LONGLONG nelem,       /* I - number of values to read            */
            void *array,      /* O - array of values that are returned       */
            char *nullarray,  /* O - returned array of null value flags      */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. The datatype of the
  input array is defined by the 2nd argument.  Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  The nullarray values will = 1 if the corresponding array value is null.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    LONGLONG tfirstpix[99];
    int naxis, ii;

    if (*status > 0 || nelem == 0)   /* inherit input status value if > 0 */
        return(*status);

    /* get the size of the image */
    ffgidm(fptr, &naxis, status);

    for (ii=0; ii < naxis; ii++)
       tfirstpix[ii] = firstpix[ii];

    ffgpxfll(fptr, datatype, tfirstpix, nelem, array, nullarray, anynul, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgpxfll( fitsfile *fptr, /* I - FITS file pointer                       */
            int  datatype,    /* I - datatype of the value                   */
            LONGLONG *firstpix, /* I - coord of first pixel to read (1s based) */
            LONGLONG nelem,       /* I - number of values to read              */
            void *array,      /* O - array of values that are returned       */
            char *nullarray,  /* O - returned array of null value flags      */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. The datatype of the
  input array is defined by the 2nd argument.  Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  The nullarray values will = 1 if the corresponding array value is null.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    int naxis, ii;
    int nullcheck = 2;
    LONGLONG naxes[9];
    LONGLONG dimsize = 1, firstelem;

    if (*status > 0 || nelem == 0)   /* inherit input status value if > 0 */
        return(*status);

    /* get the size of the image */
    ffgidm(fptr, &naxis, status);
    ffgiszll(fptr, 9, naxes, status);

    /* calculate the position of the first element in the array */
    firstelem = 0;
    for (ii=0; ii < naxis; ii++)
    {
        firstelem += ((firstpix[ii] - 1) * dimsize);
        dimsize *= naxes[ii];
    }
    firstelem++;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_read_compressed_pixels(fptr, datatype, firstelem, nelem,
            nullcheck, NULL, array, nullarray, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (datatype == TBYTE)
    {
        ffgclb(fptr, 2, 1, firstelem, nelem, 1, 2, 0,
               (unsigned char *) array, nullarray, anynul, status);
    }
    else if (datatype == TSBYTE)
    {
        ffgclsb(fptr, 2, 1, firstelem, nelem, 1, 2, 0,
               (signed char *) array, nullarray, anynul, status);
    }
    else if (datatype == TUSHORT)
    {
        ffgclui(fptr, 2, 1, firstelem, nelem, 1, 2, 0,
               (unsigned short *) array, nullarray, anynul, status);
    }
    else if (datatype == TSHORT)
    {
        ffgcli(fptr, 2, 1, firstelem, nelem, 1, 2, 0,
               (short *) array, nullarray, anynul, status);
    }
    else if (datatype == TUINT)
    {
        ffgcluk(fptr, 2, 1, firstelem, nelem, 1, 2, 0,
               (unsigned int *) array, nullarray, anynul, status);
    }
    else if (datatype == TINT)
    {
        ffgclk(fptr, 2, 1, firstelem, nelem, 1, 2, 0,
               (int *) array, nullarray, anynul, status);
    }
    else if (datatype == TULONG)
    {
        ffgcluj(fptr, 2, 1, firstelem, nelem, 1, 2, 0,
               (unsigned long *) array, nullarray, anynul, status);
    }
    else if (datatype == TLONG)
    {
        ffgclj(fptr, 2, 1, firstelem, nelem, 1, 2, 0,
               (long *) array, nullarray, anynul, status);
    }
    else if (datatype == TLONGLONG)
    {
        ffgcljj(fptr, 2, 1, firstelem, nelem, 1, 2, 0,
               (LONGLONG *) array, nullarray, anynul, status);
    }
    else if (datatype == TFLOAT)
    {
        ffgcle(fptr, 2, 1, firstelem, nelem, 1, 2, 0,
               (float *) array, nullarray, anynul, status);
    }
    else if (datatype == TDOUBLE)
    {
        ffgcld(fptr, 2, 1, firstelem, nelem, 1, 2, 0,
               (double *) array, nullarray, anynul, status);
    }
    else
      *status = BAD_DATATYPE;

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsv(  fitsfile *fptr,   /* I - FITS file pointer                       */
            int  datatype,    /* I - datatype of the value                   */
            long *blc,        /* I - 'bottom left corner' of the subsection  */
            long *trc ,       /* I - 'top right corner' of the subsection    */
            long *inc,        /* I - increment to be applied in each dim.    */
            void *nulval,     /* I - value for undefined pixels              */
            void *array,      /* O - array of values that are returned       */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an section of values from the primary array. The datatype of the
  input array is defined by the 2nd argument.  Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Undefined elements will be set equal to NULVAL, unless NULVAL=0
  in which case no checking for undefined values will be performed.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    int naxis, ii;
    long naxes[9];
    LONGLONG nelem = 1;

    if (*status > 0)   /* inherit input status value if > 0 */
        return(*status);

    /* get the size of the image */
    ffgidm(fptr, &naxis, status);
    ffgisz(fptr, 9, naxes, status);

    /* test for the important special case where we are reading the whole image */
    /* this is only useful for images that are not tile-compressed */
    if (!fits_is_compressed_image(fptr, status)) {
        for (ii = 0; ii < naxis; ii++) {
            if (inc[ii] != 1 || blc[ii] !=1 || trc[ii] != naxes[ii])
                break;

            nelem = nelem * naxes[ii];
        }

        if (ii == naxis) {
            /* read the whole image more efficiently */
            ffgpxv(fptr, datatype, blc, nelem, nulval, array, anynul, status);
            return(*status);
        }
    }

    if (datatype == TBYTE)
    {
      if (nulval == 0)
        ffgsvb(fptr, 1, naxis, naxes, blc, trc, inc, 0,
               (unsigned char *) array, anynul, status);
      else
        ffgsvb(fptr, 1, naxis, naxes, blc, trc, inc, *(unsigned char *) nulval,
               (unsigned char *) array, anynul, status);
    }
    else if (datatype == TSBYTE)
    {
      if (nulval == 0)
        ffgsvsb(fptr, 1, naxis, naxes, blc, trc, inc, 0,
               (signed char *) array, anynul, status);
      else
        ffgsvsb(fptr, 1, naxis, naxes, blc, trc, inc, *(signed char *) nulval,
               (signed char *) array, anynul, status);
    }
    else if (datatype == TUSHORT)
    {
      if (nulval == 0)
        ffgsvui(fptr, 1, naxis, naxes, blc, trc, inc, 0,
               (unsigned short *) array, anynul, status);
      else
        ffgsvui(fptr, 1, naxis, naxes,blc, trc, inc, *(unsigned short *) nulval,
               (unsigned short *) array, anynul, status);
    }
    else if (datatype == TSHORT)
    {
      if (nulval == 0)
        ffgsvi(fptr, 1, naxis, naxes, blc, trc, inc, 0,
               (short *) array, anynul, status);
      else
        ffgsvi(fptr, 1, naxis, naxes, blc, trc, inc, *(short *) nulval,
               (short *) array, anynul, status);
    }
    else if (datatype == TUINT)
    {
      if (nulval == 0)
        ffgsvuk(fptr, 1, naxis, naxes, blc, trc, inc, 0,
               (unsigned int *) array, anynul, status);
      else
        ffgsvuk(fptr, 1, naxis, naxes, blc, trc, inc, *(unsigned int *) nulval,
               (unsigned int *) array, anynul, status);
    }
    else if (datatype == TINT)
    {
      if (nulval == 0)
        ffgsvk(fptr, 1, naxis, naxes, blc, trc, inc, 0,
               (int *) array, anynul, status);
      else
        ffgsvk(fptr, 1, naxis, naxes, blc, trc, inc, *(int *) nulval,
               (int *) array, anynul, status);
    }
    else if (datatype == TULONG)
    {
      if (nulval == 0)
        ffgsvuj(fptr, 1, naxis, naxes, blc, trc, inc, 0,
               (unsigned long *) array, anynul, status);
      else
        ffgsvuj(fptr, 1, naxis, naxes, blc, trc, inc, *(unsigned long *) nulval,
               (unsigned long *) array, anynul, status);
    }
    else if (datatype == TLONG)
    {
      if (nulval == 0)
        ffgsvj(fptr, 1, naxis, naxes, blc, trc, inc, 0,
               (long *) array, anynul, status);
      else
        ffgsvj(fptr, 1, naxis, naxes, blc, trc, inc, *(long *) nulval,
               (long *) array, anynul, status);
    }
    else if (datatype == TLONGLONG)
    {
      if (nulval == 0)
        ffgsvjj(fptr, 1, naxis, naxes, blc, trc, inc, 0,
               (LONGLONG *) array, anynul, status);
      else
        ffgsvjj(fptr, 1, naxis, naxes, blc, trc, inc, *(LONGLONG *) nulval,
               (LONGLONG *) array, anynul, status);
    }
    else if (datatype == TFLOAT)
    {
      if (nulval == 0)
        ffgsve(fptr, 1, naxis, naxes, blc, trc, inc, 0,
               (float *) array, anynul, status);
      else
        ffgsve(fptr, 1, naxis, naxes, blc, trc, inc, *(float *) nulval,
               (float *) array, anynul, status);
    }
    else if (datatype == TDOUBLE)
    {
      if (nulval == 0)
        ffgsvd(fptr, 1, naxis, naxes, blc, trc, inc, 0,
               (double *) array, anynul, status);
      else
        ffgsvd(fptr, 1, naxis, naxes, blc, trc, inc, *(double *) nulval,
               (double *) array, anynul, status);
    }
    else
      *status = BAD_DATATYPE;

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgpv(  fitsfile *fptr,   /* I - FITS file pointer                       */
            int  datatype,    /* I - datatype of the value                   */
            LONGLONG firstelem,   /* I - first vector element to read (1 = 1st)  */
            LONGLONG nelem,       /* I - number of values to read                */
            void *nulval,     /* I - value for undefined pixels              */
            void *array,      /* O - array of values that are returned       */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. The datatype of the
  input array is defined by the 2nd argument.  Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Undefined elements will be set equal to NULVAL, unless NULVAL=0
  in which case no checking for undefined values will be performed.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{

    if (*status > 0 || nelem == 0)   /* inherit input status value if > 0 */
        return(*status);

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (datatype == TBYTE)
    {
      if (nulval == 0)
        ffgpvb(fptr, 1, firstelem, nelem, 0,
               (unsigned char *) array, anynul, status);
      else
        ffgpvb(fptr, 1, firstelem, nelem, *(unsigned char *) nulval,
               (unsigned char *) array, anynul, status);
    }
    else if (datatype == TSBYTE)
    {
      if (nulval == 0)
        ffgpvsb(fptr, 1, firstelem, nelem, 0,
               (signed char *) array, anynul, status);
      else
        ffgpvsb(fptr, 1, firstelem, nelem, *(signed char *) nulval,
               (signed char *) array, anynul, status);
    }
    else if (datatype == TUSHORT)
    {
      if (nulval == 0)
        ffgpvui(fptr, 1, firstelem, nelem, 0,
               (unsigned short *) array, anynul, status);
      else
        ffgpvui(fptr, 1, firstelem, nelem, *(unsigned short *) nulval,
               (unsigned short *) array, anynul, status);
    }
    else if (datatype == TSHORT)
    {
      if (nulval == 0)
        ffgpvi(fptr, 1, firstelem, nelem, 0,
               (short *) array, anynul, status);
      else
        ffgpvi(fptr, 1, firstelem, nelem, *(short *) nulval,
               (short *) array, anynul, status);
    }
    else if (datatype == TUINT)
    {
      if (nulval == 0)
        ffgpvuk(fptr, 1, firstelem, nelem, 0,
               (unsigned int *) array, anynul, status);
      else
        ffgpvuk(fptr, 1, firstelem, nelem, *(unsigned int *) nulval,
               (unsigned int *) array, anynul, status);
    }
    else if (datatype == TINT)
    {
      if (nulval == 0)
        ffgpvk(fptr, 1, firstelem, nelem, 0,
               (int *) array, anynul, status);
      else
        ffgpvk(fptr, 1, firstelem, nelem, *(int *) nulval,
               (int *) array, anynul, status);
    }
    else if (datatype == TULONG)
    {
      if (nulval == 0)
        ffgpvuj(fptr, 1, firstelem, nelem, 0,
               (unsigned long *) array, anynul, status);
      else
        ffgpvuj(fptr, 1, firstelem, nelem, *(unsigned long *) nulval,
               (unsigned long *) array, anynul, status);
    }
    else if (datatype == TLONG)
    {
      if (nulval == 0)
        ffgpvj(fptr, 1, firstelem, nelem, 0,
               (long *) array, anynul, status);
      else
        ffgpvj(fptr, 1, firstelem, nelem, *(long *) nulval,
               (long *) array, anynul, status);
    }
    else if (datatype == TLONGLONG)
    {
      if (nulval == 0)
        ffgpvjj(fptr, 1, firstelem, nelem, 0,
               (LONGLONG *) array, anynul, status);
      else
        ffgpvjj(fptr, 1, firstelem, nelem, *(LONGLONG *) nulval,
               (LONGLONG *) array, anynul, status);
    }
    else if (datatype == TFLOAT)
    {
      if (nulval == 0)
        ffgpve(fptr, 1, firstelem, nelem, 0,
               (float *) array, anynul, status);
      else
        ffgpve(fptr, 1, firstelem, nelem, *(float *) nulval,
               (float *) array, anynul, status);
    }
    else if (datatype == TDOUBLE)
    {
      if (nulval == 0)
        ffgpvd(fptr, 1, firstelem, nelem, 0,
               (double *) array, anynul, status);
      else
      {
        ffgpvd(fptr, 1, firstelem, nelem, *(double *) nulval,
               (double *) array, anynul, status);
      }
    }
    else
      *status = BAD_DATATYPE;

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgpf(  fitsfile *fptr,   /* I - FITS file pointer                       */
            int  datatype,    /* I - datatype of the value                   */
            LONGLONG firstelem,   /* I - first vector element to read (1 = 1st)  */
            LONGLONG nelem,       /* I - number of values to read                */
            void *array,      /* O - array of values that are returned       */
            char *nullarray,  /* O - array of null value flags               */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. The datatype of the
  input array is defined by the 2nd argument.  Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  The nullarray values will = 1 if the corresponding array value is null.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{

    if (*status > 0 || nelem == 0)   /* inherit input status value if > 0 */
        return(*status);

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (datatype == TBYTE)
    {
        ffgpfb(fptr, 1, firstelem, nelem, 
               (unsigned char *) array, nullarray, anynul, status);
    }
    else if (datatype == TSBYTE)
    {
        ffgpfsb(fptr, 1, firstelem, nelem, 
               (signed char *) array, nullarray, anynul, status);
    }
    else if (datatype == TUSHORT)
    {
        ffgpfui(fptr, 1, firstelem, nelem, 
               (unsigned short *) array, nullarray, anynul, status);
    }
    else if (datatype == TSHORT)
    {
        ffgpfi(fptr, 1, firstelem, nelem, 
               (short *) array, nullarray, anynul, status);
    }
    else if (datatype == TUINT)
    {
        ffgpfuk(fptr, 1, firstelem, nelem, 
               (unsigned int *) array, nullarray, anynul, status);
    }
    else if (datatype == TINT)
    {
        ffgpfk(fptr, 1, firstelem, nelem, 
               (int *) array, nullarray, anynul, status);
    }
    else if (datatype == TULONG)
    {
        ffgpfuj(fptr, 1, firstelem, nelem, 
               (unsigned long *) array, nullarray, anynul, status);
    }
    else if (datatype == TLONG)
    {
        ffgpfj(fptr, 1, firstelem, nelem,
               (long *) array, nullarray, anynul, status);
    }
    else if (datatype == TLONGLONG)
    {
        ffgpfjj(fptr, 1, firstelem, nelem,
               (LONGLONG *) array, nullarray, anynul, status);
    }
    else if (datatype == TFLOAT)
    {
        ffgpfe(fptr, 1, firstelem, nelem, 
               (float *) array, nullarray, anynul, status);
    }
    else if (datatype == TDOUBLE)
    {
        ffgpfd(fptr, 1, firstelem, nelem,
               (double *) array, nullarray, anynul, status);
    }
    else
      *status = BAD_DATATYPE;

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcv(  fitsfile *fptr,   /* I - FITS file pointer                       */
            int  datatype,    /* I - datatype of the value                   */
            int  colnum,      /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,   /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG nelem,       /* I - number of values to read                */
            void *nulval,     /* I - value for undefined pixels              */
            void *array,      /* O - array of values that are returned       */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from a table column. The datatype of the
  input array is defined by the 2nd argument.  Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Undefined elements will be set equal to NULVAL, unless NULVAL=0
  in which case no checking for undefined values will be performed.
  ANYNUL is returned with a value of true if any pixels are undefined.
*/
{
    char cdummy[2];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (datatype == TBIT)
    {
      ffgcx(fptr, colnum, firstrow, firstelem, nelem, (char *) array, status);
    }
    else if (datatype == TBYTE)
    {
      if (nulval == 0)
        ffgclb(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0,
              (unsigned char *) array, cdummy, anynul, status);
      else
       ffgclb(fptr, colnum, firstrow, firstelem, nelem, 1, 1, *(unsigned char *)
              nulval, (unsigned char *) array, cdummy, anynul, status);
    }
    else if (datatype == TSBYTE)
    {
      if (nulval == 0)
        ffgclsb(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0,
              (signed char *) array, cdummy, anynul, status);
      else
       ffgclsb(fptr, colnum, firstrow, firstelem, nelem, 1, 1, *(signed char *)
              nulval, (signed char *) array, cdummy, anynul, status);
    }
    else if (datatype == TUSHORT)
    {
      if (nulval == 0)
        ffgclui(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0,
               (unsigned short *) array, cdummy, anynul, status);
      else
        ffgclui(fptr, colnum, firstrow, firstelem, nelem, 1, 1,
               *(unsigned short *) nulval,
               (unsigned short *) array, cdummy, anynul, status);
    }
    else if (datatype == TSHORT)
    {
      if (nulval == 0)
        ffgcli(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0,
              (short *) array, cdummy, anynul, status);
      else
        ffgcli(fptr, colnum, firstrow, firstelem, nelem, 1, 1, *(short *)
              nulval, (short *) array, cdummy, anynul, status);
    }
    else if (datatype == TUINT)
    {
      if (nulval == 0)
        ffgcluk(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0,
              (unsigned int *) array, cdummy, anynul, status);
      else
        ffgcluk(fptr, colnum, firstrow, firstelem, nelem, 1, 1,
         *(unsigned int *) nulval, (unsigned int *) array, cdummy, anynul,
         status);
    }
    else if (datatype == TINT)
    {
      if (nulval == 0)
        ffgclk(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0,
              (int *) array, cdummy, anynul, status);
      else
        ffgclk(fptr, colnum, firstrow, firstelem, nelem, 1, 1, *(int *)
            nulval, (int *) array, cdummy, anynul, status);
    }
    else if (datatype == TULONG)
    {
      if (nulval == 0)
        ffgcluj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0,
               (unsigned long *) array, cdummy, anynul, status);
      else
        ffgcluj(fptr, colnum, firstrow, firstelem, nelem, 1, 1,
               *(unsigned long *) nulval, 
               (unsigned long *) array, cdummy, anynul, status);
    }
    else if (datatype == TLONG)
    {
      if (nulval == 0)
        ffgclj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0,
              (long *) array, cdummy, anynul, status);
      else
        ffgclj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, *(long *)
              nulval, (long *) array, cdummy, anynul, status);
    }
    else if (datatype == TLONGLONG)
    {
      if (nulval == 0)
        ffgcljj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0,
              (LONGLONG *) array, cdummy, anynul, status);
      else
        ffgcljj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, *(LONGLONG *)
              nulval, (LONGLONG *) array, cdummy, anynul, status);
    }
    else if (datatype == TFLOAT)
    {
      if (nulval == 0)
        ffgcle(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0.,
              (float *) array, cdummy, anynul, status);
      else
      ffgcle(fptr, colnum, firstrow, firstelem, nelem, 1, 1, *(float *)
               nulval,(float *) array, cdummy, anynul, status);
    }
    else if (datatype == TDOUBLE)
    {
      if (nulval == 0)
        ffgcld(fptr, colnum, firstrow, firstelem, nelem, 1, 1, 0.,
              (double *) array, cdummy, anynul, status);
      else
        ffgcld(fptr, colnum, firstrow, firstelem, nelem, 1, 1, *(double *)
              nulval, (double *) array, cdummy, anynul, status);
    }
    else if (datatype == TCOMPLEX)
    {
      if (nulval == 0)
        ffgcle(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2,
           1, 1, 0., (float *) array, cdummy, anynul, status);
      else
        ffgcle(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2,
           1, 1, *(float *) nulval, (float *) array, cdummy, anynul, status);
    }
    else if (datatype == TDBLCOMPLEX)
    {
      if (nulval == 0)
        ffgcld(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2, 
         1, 1, 0., (double *) array, cdummy, anynul, status);
      else
        ffgcld(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2, 
         1, 1, *(double *) nulval, (double *) array, cdummy, anynul, status);
    }

    else if (datatype == TLOGICAL)
    {
      if (nulval == 0)
        ffgcll(fptr, colnum, firstrow, firstelem, nelem, 1, 0,
          (char *) array, cdummy, anynul, status);
      else
        ffgcll(fptr, colnum, firstrow, firstelem, nelem, 1, *(char *) nulval,
          (char *) array, cdummy, anynul, status);
    }
    else if (datatype == TSTRING)
    {
      if (nulval == 0)
      {
        cdummy[0] = '\0';
        ffgcls(fptr, colnum, firstrow, firstelem, nelem, 1, 
             cdummy, (char **) array, cdummy, anynul, status);
      }
      else
        ffgcls(fptr, colnum, firstrow, firstelem, nelem, 1, (char *)
             nulval, (char **) array, cdummy, anynul, status);
    }
    else
      *status = BAD_DATATYPE;

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcf(  fitsfile *fptr,   /* I - FITS file pointer                       */
            int  datatype,    /* I - datatype of the value                   */
            int  colnum,      /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,   /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG nelem,       /* I - number of values to read                */
            void *array,      /* O - array of values that are returned       */
            char *nullarray,  /* O - array of null value flags               */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from a table column. The datatype of the
  input array is defined by the 2nd argument.  Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  ANYNUL is returned with a value of true if any pixels are undefined.
*/
{
    double nulval = 0.;
    char cnulval[2];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (datatype == TBIT)
    {
      ffgcx(fptr, colnum, firstrow, firstelem, nelem, (char *) array, status);
    }
    else if (datatype == TBYTE)
    {
       ffgclb(fptr, colnum, firstrow, firstelem, nelem, 1, 2, (unsigned char )
              nulval, (unsigned char *) array, nullarray, anynul, status);
    }
    else if (datatype == TSBYTE)
    {
       ffgclsb(fptr, colnum, firstrow, firstelem, nelem, 1, 2, (signed char )
              nulval, (signed char *) array, nullarray, anynul, status);
    }
    else if (datatype == TUSHORT)
    {
        ffgclui(fptr, colnum, firstrow, firstelem, nelem, 1, 2,
               (unsigned short ) nulval,
               (unsigned short *) array, nullarray, anynul, status);
    }
    else if (datatype == TSHORT)
    {
        ffgcli(fptr, colnum, firstrow, firstelem, nelem, 1, 2, (short )
              nulval, (short *) array, nullarray, anynul, status);
    }
    else if (datatype == TUINT)
    {
        ffgcluk(fptr, colnum, firstrow, firstelem, nelem, 1, 2,
         (unsigned int ) nulval, (unsigned int *) array, nullarray, anynul,
         status);
    }
    else if (datatype == TINT)
    {
        ffgclk(fptr, colnum, firstrow, firstelem, nelem, 1, 2, (int )
            nulval, (int *) array, nullarray, anynul, status);
    }
    else if (datatype == TULONG)
    {
        ffgcluj(fptr, colnum, firstrow, firstelem, nelem, 1, 2,
               (unsigned long ) nulval, 
               (unsigned long *) array, nullarray, anynul, status);
    }
    else if (datatype == TLONG)
    {
        ffgclj(fptr, colnum, firstrow, firstelem, nelem, 1, 2, (long )
              nulval, (long *) array, nullarray, anynul, status);
    }
    else if (datatype == TLONGLONG)
    {
        ffgcljj(fptr, colnum, firstrow, firstelem, nelem, 1, 2, (LONGLONG )
              nulval, (LONGLONG *) array, nullarray, anynul, status);
    }
    else if (datatype == TFLOAT)
    {
      ffgcle(fptr, colnum, firstrow, firstelem, nelem, 1, 2, (float )
               nulval,(float *) array, nullarray, anynul, status);
    }
    else if (datatype == TDOUBLE)
    {
        ffgcld(fptr, colnum, firstrow, firstelem, nelem, 1, 2, 
              nulval, (double *) array, nullarray, anynul, status);
    }
    else if (datatype == TCOMPLEX)
    {
        ffgcfc(fptr, colnum, firstrow, firstelem, nelem,
           (float *) array, nullarray, anynul, status);
    }
    else if (datatype == TDBLCOMPLEX)
    {
        ffgcfm(fptr, colnum, firstrow, firstelem, nelem, 
           (double *) array, nullarray, anynul, status);
    }

    else if (datatype == TLOGICAL)
    {
        ffgcll(fptr, colnum, firstrow, firstelem, nelem, 2, (char ) nulval,
          (char *) array, nullarray, anynul, status);
    }
    else if (datatype == TSTRING)
    {
        ffgcls(fptr, colnum, firstrow, firstelem, nelem, 2, 
             cnulval, (char **) array, nullarray, anynul, status);
    }
    else
      *status = BAD_DATATYPE;

    return(*status);
}

cfitsio/getcolb.c0000644000225700000360000022573113246025103013575 0ustar  cagordonlhea/*  This file, getcolb.c, contains routines that read data elements from   */
/*  a FITS image or table, with unsigned char (unsigned byte) data type.   */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include 
#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int ffgpvb( fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            unsigned char nulval, /* I - value for undefined pixels          */
            unsigned char *array, /* O - array of values that are returned   */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Undefined elements will be set equal to NULVAL, unless NULVAL=0
  in which case no checking for undefined values will be performed.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    long row;
    char cdummy;
    int nullcheck = 1;
    unsigned char nullvalue;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */
         nullvalue = nulval;  /* set local variable */

        fits_read_compressed_pixels(fptr, TBYTE, firstelem, nelem,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }
    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgclb(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
               array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgpfb( fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            unsigned char *array, /* O - array of values that are returned   */
            char *nularray,   /* O - array of null pixel flags               */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Any undefined pixels in the returned array will be set = 0 and the 
  corresponding nularray value will be set = 1.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    long row;
    int nullcheck = 2;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_read_compressed_pixels(fptr, TBYTE, firstelem, nelem,
            nullcheck, NULL, array, nularray, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgclb(fptr, 2, row, firstelem, nelem, 1, 2, 0,
               array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffg2db(fitsfile *fptr,  /* I - FITS file pointer                       */
           long  group,     /* I - group to read (1 = 1st group)           */
           unsigned char nulval, /* set undefined pixels equal to this     */
           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
           unsigned char *array, /* O - array to be filled and returned    */
           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
           int  *status)    /* IO - error status                           */
/*
  Read an entire 2-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being read).  Any null
  values in the array will be set equal to the value of nulval, unless
  nulval = 0 in which case no null checking will be performed.
*/
{
    /* call the 3D reading routine, with the 3rd dimension = 1 */

    ffg3db(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, 
           anynul, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffg3db(fitsfile *fptr,  /* I - FITS file pointer                       */
           long  group,     /* I - group to read (1 = 1st group)           */
           unsigned char nulval, /* set undefined pixels equal to this     */
           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
           LONGLONG  nrows,     /* I - number of rows in each plane of array   */
           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
           LONGLONG  naxis3,    /* I - FITS image NAXIS3 value                 */
           unsigned char *array, /* O - array to be filled and returned    */
           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
           int  *status)    /* IO - error status                           */
/*
  Read an entire 3-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being read).  Any null
  values in the array will be set equal to the value of nulval, unless
  nulval = 0 in which case no null checking will be performed.
*/
{
    long tablerow, ii, jj;
    LONGLONG narray, nfits;
    char cdummy;
    int  nullcheck = 1;
    long inc[] = {1,1,1};
    LONGLONG fpixel[] = {1,1,1};
    LONGLONG lpixel[3];
    unsigned char nullvalue;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        lpixel[0] = ncols;
        lpixel[1] = nrows;
        lpixel[2] = naxis3;
        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_img(fptr, TBYTE, fpixel, lpixel, inc,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */
    tablerow=maxvalue(1,group);

    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
    {
       /* all the image pixels are contiguous, so read all at once */
       ffgclb(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval,
               array, &cdummy, anynul, status);
       return(*status);
    }

    if (ncols < naxis1 || nrows < naxis2)
       return(*status = BAD_DIMEN);

    nfits = 1;   /* next pixel in FITS image to read */
    narray = 0;  /* next pixel in output array to be filled */

    /* loop over naxis3 planes in the data cube */
    for (jj = 0; jj < naxis3; jj++)
    {
      /* loop over the naxis2 rows in the FITS image, */
      /* reading naxis1 pixels to each row            */

      for (ii = 0; ii < naxis2; ii++)
      {
       if (ffgclb(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval,
          &array[narray], &cdummy, anynul, status) > 0)
          return(*status);

       nfits += naxis1;
       narray += ncols;
      }
      narray += (nrows - naxis2) * ncols;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsvb(fitsfile *fptr, /* I - FITS file pointer                         */
           int  colnum,    /* I - number of the column to read (1 = 1st)    */
           int naxis,      /* I - number of dimensions in the FITS array    */
           long  *naxes,   /* I - size of each dimension                    */
           long  *blc,     /* I - 'bottom left corner' of the subsection    */
           long  *trc,     /* I - 'top right corner' of the subsection      */
           long  *inc,     /* I - increment to be applied in each dimension */
           unsigned char nulval, /* I - value to set undefined pixels       */
           unsigned char *array, /* O - array to be filled and returned     */
           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
           int  *status)   /* IO - error status                             */
/*
  Read a subsection of data values from an image or a table column.
  This routine is set up to handle a maximum of nine dimensions.
*/
{
    long ii, i0, i1, i2, i3, i4, i5, i6, i7, i8, row, rstr, rstp, rinc;
    long str[9], stp[9], incr[9], dir[9];
    long nelem, nultyp, ninc, numcol;
    LONGLONG felem, dsize[10], blcll[9], trcll[9];
    int hdutype, anyf;
    char ldummy, msg[FLEN_ERRMSG];
    int  nullcheck = 1;
    unsigned char nullvalue;

    if (naxis < 1 || naxis > 9)
    {
        snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvb is out of range", naxis);
        ffpmsg(msg);
        return(*status = BAD_DIMEN);
    }

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        for (ii=0; ii < naxis; ii++) {
	    blcll[ii] = blc[ii];
	    trcll[ii] = trc[ii];
	}

        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_img(fptr, TBYTE, blcll, trcll, inc,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

/*
    if this is a primary array, then the input COLNUM parameter should
    be interpreted as the row number, and we will alway read the image
    data from column 2 (any group parameters are in column 1).
*/
    if (ffghdt(fptr, &hdutype, status) > 0)
        return(*status);

    if (hdutype == IMAGE_HDU)
    {
        /* this is a primary array, or image extension */
        if (colnum == 0)
        {
            rstr = 1;
            rstp = 1;
        }
        else
        {
            rstr = colnum;
            rstp = colnum;
        }
        rinc = 1;
        numcol = 2;
    }
    else
    {
        /* this is a table, so the row info is in the (naxis+1) elements */
        rstr = blc[naxis];
        rstp = trc[naxis];
        rinc = inc[naxis];
        numcol = colnum;
    }

    nultyp = 1;
    if (anynul)
        *anynul = FALSE;

    i0 = 0;
    for (ii = 0; ii < 9; ii++)
    {
        str[ii] = 1;
        stp[ii] = 1;
        incr[ii] = 1;
        dsize[ii] = 1;
        dir[ii] = 1;
    }

    for (ii = 0; ii < naxis; ii++)
    {
      if (trc[ii] < blc[ii])
      {
        if (hdutype == IMAGE_HDU)
        {
           dir[ii] = -1;
        }
        else
        {
          snprintf(msg, FLEN_ERRMSG,"ffgsvb: illegal range specified for axis %ld", ii + 1);
          ffpmsg(msg);
          return(*status = BAD_PIX_NUM);
        }
      }

      str[ii] = blc[ii];
      stp[ii] = trc[ii];
      incr[ii] = inc[ii];
      dsize[ii + 1] = dsize[ii] * naxes[ii];
      dsize[ii] = dsize[ii] * dir[ii];
    }
    dsize[naxis] = dsize[naxis] * dir[naxis];

    if (naxis == 1 && naxes[0] == 1)
    {
      /* This is not a vector column, so read all the rows at once */
      nelem = (rstp - rstr) / rinc + 1;
      ninc = rinc;
      rstp = rstr;
    }
    else
    {
      /* have to read each row individually, in all dimensions */
      nelem = (stp[0]*dir[0] - str[0]*dir[0]) / inc[0] + 1;
      ninc = incr[0] * dir[0];
    }

    for (row = rstr; row <= rstp; row += rinc)
    {
     for (i8 = str[8]*dir[8]; i8 <= stp[8]*dir[8]; i8 += incr[8])
     {
      for (i7 = str[7]*dir[7]; i7 <= stp[7]*dir[7]; i7 += incr[7])
      {
       for (i6 = str[6]*dir[6]; i6 <= stp[6]*dir[6]; i6 += incr[6])
       {
        for (i5 = str[5]*dir[5]; i5 <= stp[5]*dir[5]; i5 += incr[5])
        {
         for (i4 = str[4]*dir[4]; i4 <= stp[4]*dir[4]; i4 += incr[4])
         {
          for (i3 = str[3]*dir[3]; i3 <= stp[3]*dir[3]; i3 += incr[3])
          {
           for (i2 = str[2]*dir[2]; i2 <= stp[2]*dir[2]; i2 += incr[2])
           {
            for (i1 = str[1]*dir[1]; i1 <= stp[1]*dir[1]; i1 += incr[1])
            {

              felem=str[0] + (i1 - dir[1]) * dsize[1] + (i2 - dir[2]) * dsize[2] + 
                             (i3 - dir[3]) * dsize[3] + (i4 - dir[4]) * dsize[4] +
                             (i5 - dir[5]) * dsize[5] + (i6 - dir[6]) * dsize[6] +
                             (i7 - dir[7]) * dsize[7] + (i8 - dir[8]) * dsize[8];

              if ( ffgclb(fptr, numcol, row, felem, nelem, ninc, nultyp,
                   nulval, &array[i0], &ldummy, &anyf, status) > 0)
                   return(*status);

              if (anyf && anynul)
                  *anynul = TRUE;

              i0 += nelem;
            }
           }
          }
         }
        }
       }
      }
     }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsfb(fitsfile *fptr, /* I - FITS file pointer                         */
           int  colnum,    /* I - number of the column to read (1 = 1st)    */
           int naxis,      /* I - number of dimensions in the FITS array    */
           long  *naxes,   /* I - size of each dimension                    */
           long  *blc,     /* I - 'bottom left corner' of the subsection    */
           long  *trc,     /* I - 'top right corner' of the subsection      */
           long  *inc,     /* I - increment to be applied in each dimension */
           unsigned char *array, /* O - array to be filled and returned     */
           char *flagval,  /* O - set to 1 if corresponding value is null   */
           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
           int  *status)   /* IO - error status                             */
/*
  Read a subsection of data values from an image or a table column.
  This routine is set up to handle a maximum of nine dimensions.
*/
{
    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
    long str[9],stp[9],incr[9],dsize[10];
    LONGLONG blcll[9], trcll[9];
    long felem, nelem, nultyp, ninc, numcol;
    int hdutype, anyf;
    unsigned char nulval = 0;
    char msg[FLEN_ERRMSG];
    int  nullcheck = 2;

    if (naxis < 1 || naxis > 9)
    {
        snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvb is out of range", naxis);
        ffpmsg(msg);
        return(*status = BAD_DIMEN);
    }

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        for (ii=0; ii < naxis; ii++) {
	    blcll[ii] = blc[ii];
	    trcll[ii] = trc[ii];
	}

        fits_read_compressed_img(fptr, TBYTE, blcll, trcll, inc,
            nullcheck, NULL, array, flagval, anynul, status);
        return(*status);
    }

/*
    if this is a primary array, then the input COLNUM parameter should
    be interpreted as the row number, and we will alway read the image
    data from column 2 (any group parameters are in column 1).
*/
    if (ffghdt(fptr, &hdutype, status) > 0)
        return(*status);

    if (hdutype == IMAGE_HDU)
    {
        /* this is a primary array, or image extension */
        if (colnum == 0)
        {
            rstr = 1;
            rstp = 1;
        }
        else
        {
            rstr = colnum;
            rstp = colnum;
        }
        rinc = 1;
        numcol = 2;
    }
    else
    {
        /* this is a table, so the row info is in the (naxis+1) elements */
        rstr = blc[naxis];
        rstp = trc[naxis];
        rinc = inc[naxis];
        numcol = colnum;
    }

    nultyp = 2;
    if (anynul)
        *anynul = FALSE;

    i0 = 0;
    for (ii = 0; ii < 9; ii++)
    {
        str[ii] = 1;
        stp[ii] = 1;
        incr[ii] = 1;
        dsize[ii] = 1;
    }

    for (ii = 0; ii < naxis; ii++)
    {
      if (trc[ii] < blc[ii])
      {
        snprintf(msg, FLEN_ERRMSG,"ffgsvb: illegal range specified for axis %ld", ii + 1);
        ffpmsg(msg);
        return(*status = BAD_PIX_NUM);
      }

      str[ii] = blc[ii];
      stp[ii] = trc[ii];
      incr[ii] = inc[ii];
      dsize[ii + 1] = dsize[ii] * naxes[ii];
    }

    if (naxis == 1 && naxes[0] == 1)
    {
      /* This is not a vector column, so read all the rows at once */
      nelem = (rstp - rstr) / rinc + 1;
      ninc = rinc;
      rstp = rstr;
    }
    else
    {
      /* have to read each row individually, in all dimensions */
      nelem = (stp[0] - str[0]) / inc[0] + 1;
      ninc = incr[0];
    }

    for (row = rstr; row <= rstp; row += rinc)
    {
     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
     {
      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
      {
       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
       {
        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
        {
         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
         {
          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
          {
           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
           {
            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
            {
              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];

              if ( ffgclb(fptr, numcol, row, felem, nelem, ninc, nultyp,
                   nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
                   return(*status);

              if (anyf && anynul)
                  *anynul = TRUE;

              i0 += nelem;
            }
           }
          }
         }
        }
       }
      }
     }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffggpb( fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            long  firstelem,  /* I - first vector element to read (1 = 1st)  */
            long  nelem,      /* I - number of values to read                */
            unsigned char *array, /* O - array of values that are returned   */
            int  *status)     /* IO - error status                           */
/*
  Read an array of group parameters from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
*/
{
    long row;
    int idummy;
    char cdummy;
    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgclb(fptr, 1, row, firstelem, nelem, 1, 1, 0,
               array, &cdummy, &idummy, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcvb(fitsfile *fptr,   /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
           unsigned char nulval, /* I - value for null pixels               */
           unsigned char *array, /* O - array of values that are read       */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Any undefined pixels will be set equal to the value of 'nulval' unless
  nulval = 0 in which case no checks for undefined pixels will be made.
*/
{
    char cdummy;

    ffgclb(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
           array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcfb(fitsfile *fptr,   /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
           unsigned char *array, /* O - array of values that are read       */
           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Nularray will be set = 1 if the corresponding array pixel is undefined, 
  otherwise nularray will = 0.
*/
{
    unsigned char dummy = 0;

    ffgclb(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
           array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgclb( fitsfile *fptr,   /* I - FITS file pointer                       */
            int  colnum,      /* I - number of column to read (1 = 1st col)  */
            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
            LONGLONG firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
            int   nultyp,     /* I - null value handling code:               */
                              /*     1: set undefined pixels = nulval        */
                              /*     2: set nularray=1 for undefined pixels  */
            unsigned char nulval, /* I - value for null pixels if nultyp = 1 */
            unsigned char *array, /* O - array of values that are read       */
            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU.
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer be a virtual column in a 1 or more grouped FITS primary
  array or image extension.  FITSIO treats a primary array as a binary table
  with 2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.

  The output array of values will be converted from the datatype of the column 
  and will be scaled by the FITS TSCALn and TZEROn values if necessary.
*/
{
    double scale, zero, power = 1., dtemp;
    int tcode, maxelem2, hdutype, xcode, decimals;
    long twidth, incre, ntodo;
    long ii, xwidth;
    int convert, nulcheck, readcheck = 0;
    LONGLONG repeat, startpos, elemnum, readptr, tnull;
    LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
    char tform[20];
    char message[FLEN_ERRMSG];
    char snull[20];   /*  the FITS null value if reading from ASCII table  */

    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
    void *buffer;

    union u_tag {
       char charval;
       unsigned char ucharval;
    } u;

    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
        return(*status);

    buffer = cbuff;

    if (anynul)
        *anynul = 0;

    if (nultyp == 2)      
       memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if (elemincre < 0)
        readcheck = -1;  /* don't do range checking in this case */

    ffgcprll( fptr, colnum, firstrow, firstelem, nelem, readcheck, &scale, &zero,
         tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
         &repeat, &rowlen, &hdutype, &tnull, snull, status);
    maxelem = maxelem2;

    /* special case */
    if (tcode == TLOGICAL && elemincre == 1)
    {
        u.ucharval = nulval;
        ffgcll(fptr, colnum, firstrow, firstelem, nelem, nultyp,
               u.charval, (char *) array, nularray, anynul, status);

        return(*status);
    }

    if (strchr(tform,'A') != NULL) 
    {
        if (*status == BAD_ELEM_NUM)
        {
            /* ignore this error message */
            *status = 0;
            ffcmsg();   /* clear error stack */
        }

        /*  interpret a 'A' ASCII column as a 'B' byte column ('8A' == '8B') */
        /*  This is an undocumented 'feature' in CFITSIO */

        /*  we have to reset some of the values returned by ffgcpr */
        
        tcode = TBYTE;
        incre = 1;         /* each element is 1 byte wide */
        repeat = twidth;   /* total no. of chars in the col */
        twidth = 1;        /* width of each element */
        scale = 1.0;       /* no scaling */
        zero  = 0.0;
        tnull = NULL_UNDEFINED;  /* don't test for nulls */
        maxelem = DBUFFSIZE;
    }

    if (*status > 0)
        return(*status);
        
    incre *= elemincre;   /* multiply incre to just get every nth pixel */

    if (tcode == TSTRING && hdutype == ASCII_TBL) /* setup for ASCII tables */
    {
      /* get the number of implied decimal places if no explicit decmal point */
      ffasfm(tform, &xcode, &xwidth, &decimals, status); 
      for(ii = 0; ii < decimals; ii++)
        power *= 10.;
    }
    /*------------------------------------------------------------------*/
    /*  Decide whether to check for null values in the input FITS file: */
    /*------------------------------------------------------------------*/
    nulcheck = nultyp; /* by default, check for null values in the FITS file */

    if (nultyp == 1 && nulval == 0)
       nulcheck = 0;    /* calling routine does not want to check for nulls */

    else if (tcode%10 == 1 &&        /* if reading an integer column, and  */ 
            tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
            nulcheck = 0;            /* then do not check for null values. */

    else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
            nulcheck = 0;            /* Impossible null value */

    else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
            nulcheck = 0;            /* Impossible null value */

    else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
         nulcheck = 0;

    /*----------------------------------------------------------------------*/
    /*  If FITS column and output data array have same datatype, then we do */
    /*  not need to use a temporary buffer to store intermediate datatype.  */
    /*----------------------------------------------------------------------*/
    convert = 1;
    if (tcode == TBYTE) /* Special Case:                        */
    {                             /* no type convertion required, so read */
                                  /* data directly into output buffer.    */

        if (nelem < (LONGLONG)INT32_MAX) {
            maxelem = nelem;
        } else {
            maxelem = INT32_MAX;
        }

        if (nulcheck == 0 && scale == 1. && zero == 0.)
            convert = 0;  /* no need to scale data or find nulls */
    }

    /*---------------------------------------------------------------------*/
    /*  Now read the pixels from the FITS column. If the column does not   */
    /*  have the same datatype as the output array, then we have to read   */
    /*  the raw values into a temporary buffer (of limited size).  In      */
    /*  the case of a vector colum read only 1 vector of values at a time  */
    /*  then skip to the next row if more values need to be read.          */
    /*  After reading the raw values, then call the fffXXYY routine to (1) */
    /*  test for undefined values, (2) convert the datatype if necessary,  */
    /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
    /*  scaling parameters.                                                */
    /*---------------------------------------------------------------------*/
    remain = nelem;           /* remaining number of values to read */
    next = 0;                 /* next element in array to be read   */
    rownum = 0;               /* row number, relative to firstrow   */

    while (remain)
    {
        /* limit the number of pixels to read at one time to the number that
           will fit in the buffer or to the number of pixels that remain in
           the current vector, which ever is smaller.
        */
        ntodo = (long) minvalue(remain, maxelem);
        if (elemincre >= 0)
        {
          ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));
        }
        else
        {
          ntodo = (long) minvalue(ntodo, (elemnum/(-elemincre) +1));
        }

        readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));

        switch (tcode) 
        {
            case (TBYTE):
                ffgi1b(fptr, readptr, ntodo, incre, &array[next], status);
                if (convert)
                    fffi1i1(&array[next], ntodo, scale, zero, nulcheck, 
                    (unsigned char) tnull, nulval, &nularray[next], anynul, 
                           &array[next], status);
                break;
            case (TSHORT):
                ffgi2b(fptr, readptr, ntodo, incre, (short *) buffer, status);
                fffi2i1((short  *) buffer, ntodo, scale, zero, nulcheck, 
                       (short) tnull, nulval, &nularray[next], anynul, 
                       &array[next], status);
                break;
            case (TLONG):
                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer,
                       status);
                fffi4i1((INT32BIT *) buffer, ntodo, scale, zero, nulcheck, 
                       (INT32BIT) tnull, nulval, &nularray[next], anynul, 
                       &array[next], status);
                break;
            case (TLONGLONG):
                ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status);
                fffi8i1( (LONGLONG *) buffer, ntodo, scale, zero, 
                           nulcheck, tnull, nulval, &nularray[next], 
                            anynul, &array[next], status);
                break;
            case (TFLOAT):
                ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
                fffr4i1((float  *) buffer, ntodo, scale, zero, nulcheck, 
                       nulval, &nularray[next], anynul, 
                       &array[next], status);
                break;
            case (TDOUBLE):
                ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
                fffr8i1((double *) buffer, ntodo, scale, zero, nulcheck, 
                          nulval, &nularray[next], anynul, 
                          &array[next], status);
                break;
            case (TSTRING):
                ffmbyt(fptr, readptr, REPORT_EOF, status);
       
                if (incre == twidth)    /* contiguous bytes */
                     ffgbyt(fptr, ntodo * twidth, buffer, status);
                else
                     ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
                               status);

                /* interpret the string as an ASCII formated number */
                fffstri1((char *) buffer, ntodo, scale, zero, twidth, power,
                      nulcheck, snull, nulval, &nularray[next], anynul,
                      &array[next], status);
                break;

            default:  /*  error trap for invalid column format */
                snprintf(message, FLEN_ERRMSG,
                   "Cannot read bytes from column %d which has format %s",
                    colnum, tform);
                ffpmsg(message);
                if (hdutype == ASCII_TBL)
                    return(*status = BAD_ATABLE_FORMAT);
                else
                    return(*status = BAD_BTABLE_FORMAT);

        } /* End of switch block */

        /*-------------------------*/
        /*  Check for fatal error  */
        /*-------------------------*/
        if (*status > 0)  /* test for error during previous read operation */
        {
	  dtemp = (double) next;
          if (hdutype > 0)
            snprintf(message,FLEN_ERRMSG,
            "Error reading elements %.0f thru %.0f from column %d (ffgclb).",
              dtemp+1., dtemp+ntodo, colnum);
          else
            snprintf(message,FLEN_ERRMSG,
            "Error reading elements %.0f thru %.0f from image (ffgclb).",
              dtemp+1., dtemp+ntodo);

         ffpmsg(message);
         return(*status);
        }

        /*--------------------------------------------*/
        /*  increment the counters for the next loop  */
        /*--------------------------------------------*/
        remain -= ntodo;
        if (remain)
        {
            next += ntodo;
            elemnum = elemnum + (ntodo * elemincre);

            if (elemnum >= repeat)  /* completed a row; start on later row */
            {
                rowincre = elemnum / repeat;
                rownum += rowincre;
                elemnum = elemnum - (rowincre * repeat);
            }
            else if (elemnum < 0)  /* completed a row; start on a previous row */
            {
                rowincre = (-elemnum - 1) / repeat + 1;
                rownum -= rowincre;
                elemnum = (rowincre * repeat) + elemnum;
            }
        }
    }  /*  End of main while Loop  */


    /*--------------------------------*/
    /*  check for numerical overflow  */
    /*--------------------------------*/
    if (*status == OVERFLOW_ERR)
    {
        ffpmsg(
        "Numerical overflow during type conversion while reading FITS data.");
        *status = NUM_OVERFLOW;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgextn( fitsfile *fptr,        /* I - FITS file pointer                        */
            LONGLONG  offset,      /* I - byte offset from start of extension data */
            LONGLONG  nelem,       /* I - number of elements to read               */
            void *buffer,          /* I - stream of bytes to read                  */
            int  *status)          /* IO - error status                            */
/*
  Read a stream of bytes from the current FITS HDU.  This primative routine is mainly
  for reading non-standard "conforming" extensions and should not be used
  for standard IMAGE, TABLE or BINTABLE extensions.
*/
{
    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /* reset position to the correct HDU if necessary */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    /* rescan header if data structure is undefined */
    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
        if ( ffrdef(fptr, status) > 0)               
            return(*status);

    /* move to write position */
    ffmbyt(fptr, (fptr->Fptr)->datastart+ offset, IGNORE_EOF, status);
    
    /* read the buffer */
    ffgbyt(fptr, nelem, buffer, status); 

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi1i1(unsigned char *input, /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
            unsigned char nullval,/* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            unsigned char *output,/* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {              /* this routine is normally not called in this case */
           memmove(output, input, ntodo );
        }
        else             /* must scale the data */
        {                
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DUCHAR_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DUCHAR_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = UCHAR_MAX;
                }
                else
                    output[ii] = (unsigned char) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DUCHAR_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DUCHAR_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UCHAR_MAX;
                    }
                    else
                        output[ii] = (unsigned char) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi2i1(short *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            short tnull,          /* I - value of FITS TNULLn keyword if any */
            unsigned char nullval,/* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            unsigned char *output,/* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < 0)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (input[ii] > UCHAR_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = UCHAR_MAX;
                }
                else
                    output[ii] = (unsigned char) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DUCHAR_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DUCHAR_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = UCHAR_MAX;
                }
                else
                    output[ii] = (unsigned char) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }

                else
                {
                    if (input[ii] < 0)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (input[ii] > UCHAR_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UCHAR_MAX;
                    }
                    else
                        output[ii] = (unsigned char) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DUCHAR_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DUCHAR_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UCHAR_MAX;
                    }
                    else
                        output[ii] = (unsigned char) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi4i1(INT32BIT *input,          /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
            unsigned char nullval,/* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            unsigned char *output,/* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < 0)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (input[ii] > UCHAR_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = UCHAR_MAX;
                }
                else
                    output[ii] = (unsigned char) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DUCHAR_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DUCHAR_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = UCHAR_MAX;
                }
                else
                    output[ii] = (unsigned char) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    if (input[ii] < 0)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (input[ii] > UCHAR_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UCHAR_MAX;
                    }
                    else
                        output[ii] = (unsigned char) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DUCHAR_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DUCHAR_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UCHAR_MAX;
                    }
                    else
                        output[ii] = (unsigned char) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi8i1(LONGLONG *input,      /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
            unsigned char nullval,/* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            unsigned char *output,/* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < 0)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (input[ii] > UCHAR_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = UCHAR_MAX;
                }
                else
                    output[ii] = (unsigned char) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DUCHAR_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DUCHAR_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = UCHAR_MAX;
                }
                else
                    output[ii] = (unsigned char) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    if (input[ii] < 0)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (input[ii] > UCHAR_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UCHAR_MAX;
                    }
                    else
                        output[ii] = (unsigned char) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DUCHAR_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DUCHAR_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UCHAR_MAX;
                    }
                    else
                        output[ii] = (unsigned char) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffr4i1(float *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            unsigned char nullval,/* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            unsigned char *output,/* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to NaN.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;
    short *sptr, iret;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < DUCHAR_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (input[ii] > DUCHAR_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = UCHAR_MAX;
                }
                else
                    output[ii] = (unsigned char) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DUCHAR_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DUCHAR_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = UCHAR_MAX;
                }
                else
                    output[ii] = (unsigned char) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        sptr = (short *) input;

#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
        sptr++;       /* point to MSBs */
#endif
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++, sptr += 2)
            {
              /* use redundant boolean logic in following statement */
              /* to suppress irritating Borland compiler warning message */
              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                     output[ii] = 0;
              }
              else
                {
                    if (input[ii] < DUCHAR_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (input[ii] > DUCHAR_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UCHAR_MAX;
                    }
                    else
                        output[ii] = (unsigned char) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++, sptr += 2)
            {
              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {  
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                  {
                    if (zero < DUCHAR_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (zero > DUCHAR_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UCHAR_MAX;
                    }
                    else
                        output[ii] = (unsigned char) zero;
                  }
              }
              else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DUCHAR_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DUCHAR_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UCHAR_MAX;
                    }
                    else
                        output[ii] = (unsigned char) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffr8i1(double *input,        /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            unsigned char nullval,/* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            unsigned char *output,/* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to NaN.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;
    short *sptr, iret;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < DUCHAR_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (input[ii] > DUCHAR_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = UCHAR_MAX;
                }
                else
                    output[ii] = (unsigned char) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DUCHAR_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DUCHAR_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = UCHAR_MAX;
                }
                else
                    output[ii] = (unsigned char) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        sptr = (short *) input;

#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
        sptr += 3;       /* point to MSBs */
#endif
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++, sptr += 4)
            {
              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                     output[ii] = 0;
              }
              else
                {
                    if (input[ii] < DUCHAR_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (input[ii] > DUCHAR_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UCHAR_MAX;
                    }
                    else
                        output[ii] = (unsigned char) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++, sptr += 4)
            {
              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {  
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                  {
                    if (zero < DUCHAR_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (zero > DUCHAR_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UCHAR_MAX;
                    }
                    else
                        output[ii] = (unsigned char) zero;
                  }
              }
              else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DUCHAR_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DUCHAR_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UCHAR_MAX;
                    }
                    else
                        output[ii] = (unsigned char) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffstri1(char *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            long twidth,          /* I - width of each substring of chars    */
            double implipower,    /* I - power of 10 of implied decimal      */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            char  *snull,         /* I - value of FITS null string, if any   */
            unsigned char nullval, /* I - set null pixels, if nullcheck = 1  */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            unsigned char *output, /* O - array of converted pixels          */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file. Check
  for null values and do scaling if required. The nullcheck code value
  determines how any null values in the input array are treated. A null
  value is an input pixel that is equal to snull.  If nullcheck= 0, then
  no special checking for nulls is performed.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    int  nullen;
    long ii;
    double dvalue;
    char *cstring, message[FLEN_ERRMSG];
    char *cptr, *tpos;
    char tempstore, chrzero = '0';
    double val, power;
    int exponent, sign, esign, decpt;

    nullen = strlen(snull);
    cptr = input;  /* pointer to start of input string */
    for (ii = 0; ii < ntodo; ii++)
    {
      cstring = cptr;
      /* temporarily insert a null terminator at end of the string */
      tpos = cptr + twidth;
      tempstore = *tpos;
      *tpos = 0;

      /* check if null value is defined, and if the    */
      /* column string is identical to the null string */
      if (snull[0] != ASCII_NULL_UNDEFINED && 
         !strncmp(snull, cptr, nullen) )
      {
        if (nullcheck)  
        {
          *anynull = 1;    
          if (nullcheck == 1)
            output[ii] = nullval;
          else
            nullarray[ii] = 1;
        }
        cptr += twidth;
      }
      else
      {
        /* value is not the null value, so decode it */
        /* remove any embedded blank characters from the string */

        decpt = 0;
        sign = 1;
        val  = 0.;
        power = 1.;
        exponent = 0;
        esign = 1;

        while (*cptr == ' ')               /* skip leading blanks */
           cptr++;

        if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
        {
          if (*cptr == '-')
             sign = -1;

          cptr++;

          while (*cptr == ' ')         /* skip blanks between sign and value */
            cptr++;
        }

        while (*cptr >= '0' && *cptr <= '9')
        {
          val = val * 10. + *cptr - chrzero;  /* accumulate the value */
          cptr++;

          while (*cptr == ' ')         /* skip embedded blanks in the value */
            cptr++;
        }

        if (*cptr == '.' || *cptr == ',')       /* check for decimal point */
        {
          decpt = 1;
          cptr++;
          while (*cptr == ' ')         /* skip any blanks */
            cptr++;

          while (*cptr >= '0' && *cptr <= '9')
          {
            val = val * 10. + *cptr - chrzero;  /* accumulate the value */
            power = power * 10.;
            cptr++;

            while (*cptr == ' ')         /* skip embedded blanks in the value */
              cptr++;
          }
        }

        if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
        {
          cptr++;
          while (*cptr == ' ')         /* skip blanks */
              cptr++;
  
          if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
          {
            if (*cptr == '-')
               esign = -1;

            cptr++;

            while (*cptr == ' ')        /* skip blanks between sign and exp */
              cptr++;
          }

          while (*cptr >= '0' && *cptr <= '9')
          {
            exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
            cptr++;

            while (*cptr == ' ')         /* skip embedded blanks */
              cptr++;
          }
        }

        if (*cptr  != 0)  /* should end up at the null terminator */
        {
          snprintf(message, FLEN_ERRMSG,"Cannot read number from ASCII table");
          ffpmsg(message);
          snprintf(message, FLEN_ERRMSG,"Column field = %s.", cstring);
          ffpmsg(message);
          /* restore the char that was overwritten by the null */
          *tpos = tempstore;
          return(*status = BAD_C2D);
        }

        if (!decpt)  /* if no explicit decimal, use implied */
           power = implipower;

        dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));

        dvalue = dvalue * scale + zero;   /* apply the scaling */

        if (dvalue < DUCHAR_MIN)
        {
            *status = OVERFLOW_ERR;
            output[ii] = 0;
        }
        else if (dvalue > DUCHAR_MAX)
        {
            *status = OVERFLOW_ERR;
            output[ii] = UCHAR_MAX;
        }
        else
            output[ii] = (unsigned char) dvalue;
      }
      /* restore the char that was overwritten by the null */
      *tpos = tempstore;
    }
    return(*status);
}
cfitsio/getcold.c0000644000225700000360000020354413246025103013575 0ustar  cagordonlhea/*  This file, getcold.c, contains routines that read data elements from   */
/*  a FITS image or table, with double datatype.                           */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include 
#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int ffgpvd( fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            double nulval,    /* I - value for undefined pixels              */
            double *array,    /* O - array of values that are returned       */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Undefined elements will be set equal to NULVAL, unless NULVAL=0
  in which case no checking for undefined values will be performed.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    long row;
    char cdummy;
    int nullcheck = 1;
    double nullvalue;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */
         nullvalue = nulval;  /* set local variable */

        fits_read_compressed_pixels(fptr, TDOUBLE, firstelem, nelem,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgcld(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
               array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgpfd( fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            double *array,    /* O - array of values that are returned       */
            char *nularray,   /* O - array of null pixel flags               */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Any undefined pixels in the returned array will be set = 0 and the 
  corresponding nularray value will be set = 1.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    long row;
    int nullcheck = 2;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_read_compressed_pixels(fptr, TDOUBLE, firstelem, nelem,
            nullcheck, NULL, array, nularray, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgcld(fptr, 2, row, firstelem, nelem, 1, 2, 0.,
               array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffg2dd(fitsfile *fptr,  /* I - FITS file pointer                       */
           long  group,     /* I - group to read (1 = 1st group)           */
           double nulval,   /* set undefined pixels equal to this          */
           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
           double *array,   /* O - array to be filled and returned         */
           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
           int  *status)    /* IO - error status                           */
/*
  Read an entire 2-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being read).  Any null
  values in the array will be set equal to the value of nulval, unless
  nulval = 0 in which case no null checking will be performed.
*/
{
    /* call the 3D reading routine, with the 3rd dimension = 1 */

    ffg3dd(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, 
           anynul, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffg3dd(fitsfile *fptr,  /* I - FITS file pointer                       */
           long  group,     /* I - group to read (1 = 1st group)           */
           double nulval,   /* set undefined pixels equal to this          */
           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
           LONGLONG  nrows,     /* I - number of rows in each plane of array   */
           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
           LONGLONG  naxis3,    /* I - FITS image NAXIS3 value                 */
           double *array,   /* O - array to be filled and returned         */
           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
           int  *status)    /* IO - error status                           */
/*
  Read an entire 3-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being read).  Any null
  values in the array will be set equal to the value of nulval, unless
  nulval = 0 in which case no null checking will be performed.
*/
{
    LONGLONG nfits, narray;
    long tablerow, ii, jj;
    char cdummy;
    int nullcheck = 1;
    long inc[] = {1,1,1};
    LONGLONG fpixel[] = {1,1,1};
    LONGLONG lpixel[3];
    double nullvalue;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        lpixel[0] =  (long) ncols;
        lpixel[1] = (long) nrows;
        lpixel[2] = (long) naxis3;
        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_img(fptr, TDOUBLE, fpixel, lpixel, inc,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */
    tablerow=maxvalue(1,group);

    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
    {
       /* all the image pixels are contiguous, so read all at once */
       ffgcld(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval,
               array, &cdummy, anynul, status);
       return(*status);
    }

    if (ncols < naxis1 || nrows < naxis2)
       return(*status = BAD_DIMEN);

    nfits = 1;   /* next pixel in FITS image to read */
    narray = 0;  /* next pixel in output array to be filled */

    /* loop over naxis3 planes in the data cube */
    for (jj = 0; jj < naxis3; jj++)
    {
      /* loop over the naxis2 rows in the FITS image, */
      /* reading naxis1 pixels to each row            */

      for (ii = 0; ii < naxis2; ii++)
      {
       if (ffgcld(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval,
          &array[narray], &cdummy, anynul, status) > 0)
          return(*status);

       nfits += naxis1;
       narray += ncols;
      }
      narray += (nrows - naxis2) * ncols;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsvd(fitsfile *fptr, /* I - FITS file pointer                         */
           int  colnum,    /* I - number of the column to read (1 = 1st)    */
           int naxis,      /* I - number of dimensions in the FITS array    */
           long  *naxes,   /* I - size of each dimension                    */
           long  *blc,     /* I - 'bottom left corner' of the subsection    */
           long  *trc,     /* I - 'top right corner' of the subsection      */
           long  *inc,     /* I - increment to be applied in each dimension */
           double nulval,  /* I - value to set undefined pixels             */
           double *array,  /* O - array to be filled and returned           */
           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
           int  *status)   /* IO - error status                             */
/*
  Read a subsection of data values from an image or a table column.
  This routine is set up to handle a maximum of nine dimensions.
*/
{
    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
    long str[9],stp[9],incr[9],dir[9];
    long nelem, nultyp, ninc, numcol;
    LONGLONG felem, dsize[10], blcll[9], trcll[9];
    int hdutype, anyf;
    char ldummy, msg[FLEN_ERRMSG];
    int nullcheck = 1;
    double nullvalue;

    if (naxis < 1 || naxis > 9)
    {
        snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvd is out of range", naxis);
        ffpmsg(msg);
        return(*status = BAD_DIMEN);
    }

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        for (ii=0; ii < naxis; ii++) {
	    blcll[ii] = blc[ii];
	    trcll[ii] = trc[ii];
	}

        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_img(fptr, TDOUBLE, blcll, trcll, inc,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

/*
    if this is a primary array, then the input COLNUM parameter should
    be interpreted as the row number, and we will alway read the image
    data from column 2 (any group parameters are in column 1).
*/
    if (ffghdt(fptr, &hdutype, status) > 0)
        return(*status);

    if (hdutype == IMAGE_HDU)
    {
        /* this is a primary array, or image extension */
        if (colnum == 0)
        {
            rstr = 1;
            rstp = 1;
        }
        else
        {
            rstr = colnum;
            rstp = colnum;
        }
        rinc = 1;
        numcol = 2;
    }
    else
    {
        /* this is a table, so the row info is in the (naxis+1) elements */
        rstr = blc[naxis];
        rstp = trc[naxis];
        rinc = inc[naxis];
        numcol = colnum;
    }

    nultyp = 1;
    if (anynul)
        *anynul = FALSE;

    i0 = 0;
    for (ii = 0; ii < 9; ii++)
    {
        str[ii] = 1;
        stp[ii] = 1;
        incr[ii] = 1;
        dsize[ii] = 1;
        dir[ii] = 1;
    }

    for (ii = 0; ii < naxis; ii++)
    {
      if (trc[ii] < blc[ii])
      {
        if (hdutype == IMAGE_HDU)
        {
           dir[ii] = -1;
        }
        else
        {
          snprintf(msg, FLEN_ERRMSG,"ffgsvd: illegal range specified for axis %ld", ii + 1);
          ffpmsg(msg);
          return(*status = BAD_PIX_NUM);
        }
      }

      str[ii] = blc[ii];
      stp[ii] = trc[ii];
      incr[ii] = inc[ii];
      dsize[ii + 1] = dsize[ii] * naxes[ii];
      dsize[ii] = dsize[ii] * dir[ii];
    }
    dsize[naxis] = dsize[naxis] * dir[naxis];

    if (naxis == 1 && naxes[0] == 1)
    {
      /* This is not a vector column, so read all the rows at once */
      nelem = (rstp - rstr) / rinc + 1;
      ninc = rinc;
      rstp = rstr;
    }
    else
    {
      /* have to read each row individually, in all dimensions */
      nelem = (stp[0]*dir[0] - str[0]*dir[0]) / inc[0] + 1;
      ninc = incr[0] * dir[0];
    }

    for (row = rstr; row <= rstp; row += rinc)
    {
     for (i8 = str[8]*dir[8]; i8 <= stp[8]*dir[8]; i8 += incr[8])
     {
      for (i7 = str[7]*dir[7]; i7 <= stp[7]*dir[7]; i7 += incr[7])
      {
       for (i6 = str[6]*dir[6]; i6 <= stp[6]*dir[6]; i6 += incr[6])
       {
        for (i5 = str[5]*dir[5]; i5 <= stp[5]*dir[5]; i5 += incr[5])
        {
         for (i4 = str[4]*dir[4]; i4 <= stp[4]*dir[4]; i4 += incr[4])
         {
          for (i3 = str[3]*dir[3]; i3 <= stp[3]*dir[3]; i3 += incr[3])
          {
           for (i2 = str[2]*dir[2]; i2 <= stp[2]*dir[2]; i2 += incr[2])
           {
            for (i1 = str[1]*dir[1]; i1 <= stp[1]*dir[1]; i1 += incr[1])
            {

              felem=str[0] + (i1 - dir[1]) * dsize[1] + (i2 - dir[2]) * dsize[2] + 
                             (i3 - dir[3]) * dsize[3] + (i4 - dir[4]) * dsize[4] +
                             (i5 - dir[5]) * dsize[5] + (i6 - dir[6]) * dsize[6] +
                             (i7 - dir[7]) * dsize[7] + (i8 - dir[8]) * dsize[8];

              if ( ffgcld(fptr, numcol, row, felem, nelem, ninc, nultyp,
                   nulval, &array[i0], &ldummy, &anyf, status) > 0)
                   return(*status);

              if (anyf && anynul)
                  *anynul = TRUE;

              i0 += nelem;
            }
           }
          }
         }
        }
       }
      }
     }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsfd(fitsfile *fptr, /* I - FITS file pointer                         */
           int  colnum,    /* I - number of the column to read (1 = 1st)    */
           int naxis,      /* I - number of dimensions in the FITS array    */
           long  *naxes,   /* I - size of each dimension                    */
           long  *blc,     /* I - 'bottom left corner' of the subsection    */
           long  *trc,     /* I - 'top right corner' of the subsection      */
           long  *inc,     /* I - increment to be applied in each dimension */
           double *array,  /* O - array to be filled and returned           */
           char *flagval,  /* O - set to 1 if corresponding value is null   */
           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
           int  *status)   /* IO - error status                             */
/*
  Read a subsection of data values from an image or a table column.
  This routine is set up to handle a maximum of nine dimensions.
*/
{
    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
    long str[9],stp[9],incr[9],dsize[10];
    LONGLONG blcll[9], trcll[9];
    long felem, nelem, nultyp, ninc, numcol;
    int hdutype, anyf;
    double nulval = 0;
    char msg[FLEN_ERRMSG];
    int nullcheck = 2;

    if (naxis < 1 || naxis > 9)
    {
        snprintf(msg,FLEN_ERRMSG, "NAXIS = %d in call to ffgsvd is out of range", naxis);
        ffpmsg(msg);
        return(*status = BAD_DIMEN);
    }

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        for (ii=0; ii < naxis; ii++) {
	    blcll[ii] = blc[ii];
	    trcll[ii] = trc[ii];
	}

        fits_read_compressed_img(fptr, TDOUBLE, blcll, trcll, inc,
            nullcheck, NULL, array, flagval, anynul, status);
        return(*status);
    }
/*
    if this is a primary array, then the input COLNUM parameter should
    be interpreted as the row number, and we will alway read the image
    data from column 2 (any group parameters are in column 1).
*/
    if (ffghdt(fptr, &hdutype, status) > 0)
        return(*status);

    if (hdutype == IMAGE_HDU)
    {
        /* this is a primary array, or image extension */
        if (colnum == 0)
        {
            rstr = 1;
            rstp = 1;
        }
        else
        {
            rstr = colnum;
            rstp = colnum;
        }
        rinc = 1;
        numcol = 2;
    }
    else
    {
        /* this is a table, so the row info is in the (naxis+1) elements */
        rstr = blc[naxis];
        rstp = trc[naxis];
        rinc = inc[naxis];
        numcol = colnum;
    }

    nultyp = 2;
    if (anynul)
        *anynul = FALSE;

    i0 = 0;
    for (ii = 0; ii < 9; ii++)
    {
        str[ii] = 1;
        stp[ii] = 1;
        incr[ii] = 1;
        dsize[ii] = 1;
    }

    for (ii = 0; ii < naxis; ii++)
    {
      if (trc[ii] < blc[ii])
      {
        snprintf(msg, FLEN_ERRMSG,"ffgsvd: illegal range specified for axis %ld", ii + 1);
        ffpmsg(msg);
        return(*status = BAD_PIX_NUM);
      }

      str[ii] = blc[ii];
      stp[ii] = trc[ii];
      incr[ii] = inc[ii];
      dsize[ii + 1] = dsize[ii] * naxes[ii];
    }

    if (naxis == 1 && naxes[0] == 1)
    {
      /* This is not a vector column, so read all the rows at once */
      nelem = (rstp - rstr) / rinc + 1;
      ninc = rinc;
      rstp = rstr;
    }
    else
    {
      /* have to read each row individually, in all dimensions */
      nelem = (stp[0] - str[0]) / inc[0] + 1;
      ninc = incr[0];
    }

    for (row = rstr; row <= rstp; row += rinc)
    {
     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
     {
      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
      {
       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
       {
        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
        {
         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
         {
          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
          {
           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
           {
            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
            {
              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];

              if ( ffgcld(fptr, numcol, row, felem, nelem, ninc, nultyp,
                   nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
                   return(*status);

              if (anyf && anynul)
                  *anynul = TRUE;

              i0 += nelem;
            }
           }
          }
         }
        }
       }
      }
     }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffggpd( fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            long  firstelem,  /* I - first vector element to read (1 = 1st)  */
            long  nelem,      /* I - number of values to read                */
            double *array,    /* O - array of values that are returned       */
            int  *status)     /* IO - error status                           */
/*
  Read an array of group parameters from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
*/
{
    long row;
    int idummy;
    char cdummy;
    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgcld(fptr, 1, row, firstelem, nelem, 1, 1, 0.,
               array, &cdummy, &idummy, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcvd(fitsfile *fptr,   /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
           double nulval,    /* I - value for null pixels                   */
           double *array,    /* O - array of values that are read           */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Any undefined pixels will be set equal to the value of 'nulval' unless
  nulval = 0 in which case no checks for undefined pixels will be made.
*/
{
    char cdummy;

    ffgcld(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
           array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcvm(fitsfile *fptr,   /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
           double nulval,    /* I - value for null pixels                   */
           double *array,    /* O - array of values that are read           */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Any undefined pixels will be set equal to the value of 'nulval' unless
  nulval = 0 in which case no checks for undefined pixels will be made.

  TSCAL and ZERO should not be used with complex values. 
*/
{
    char cdummy;

    /* a complex double value is interpreted as a pair of double values,   */
    /* thus need to multiply the first element and number of elements by 2 */

    ffgcld(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2,
        1, 1, nulval, array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcfd(fitsfile *fptr,   /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
           double *array,    /* O - array of values that are read           */
           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Nularray will be set = 1 if the corresponding array pixel is undefined, 
  otherwise nularray will = 0.
*/
{
    double dummy = 0;

    ffgcld(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
           array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcfm(fitsfile *fptr,   /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
           double *array,    /* O - array of values that are read           */
           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Nularray will be set = 1 if the corresponding array pixel is undefined, 
  otherwise nularray will = 0.

  TSCAL and ZERO should not be used with complex values. 
*/
{
    LONGLONG ii, jj;
    float dummy = 0;
    char *carray;

    /* a complex double value is interpreted as a pair of double values,   */
    /* thus need to multiply the first element and number of elements by 2 */

    /* allocate temporary array */
    carray = (char *) calloc( (size_t) (nelem * 2), 1); 

    ffgcld(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2,
     1, 2, dummy, array, carray, anynul, status);

    for (ii = 0, jj = 0; jj < nelem; ii += 2, jj++)
    {
       if (carray[ii] || carray[ii + 1])
          nularray[jj] = 1;
       else
          nularray[jj] = 0;
    }

    free(carray);    
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcld( fitsfile *fptr,   /* I - FITS file pointer                       */
            int  colnum,      /* I - number of column to read (1 = 1st col)  */
            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
            LONGLONG firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
            int   nultyp,     /* I - null value handling code:               */
                              /*     1: set undefined pixels = nulval        */
                              /*     2: set nularray=1 for undefined pixels  */
            double nulval,    /* I - value for null pixels if nultyp = 1     */
            double *array,    /* O - array of values that are read           */
            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU.
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer be a virtual column in a 1 or more grouped FITS primary
  array or image extension.  FITSIO treats a primary array as a binary table
  with 2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.

  The output array of values will be converted from the datatype of the column
  and will be scaled by the FITS TSCALn and TZEROn values if necessary.
*/
{
    double scale, zero, power = 1, dtemp;
    int tcode, hdutype, xcode, decimals, maxelem2;
    long twidth, incre;
    long ii, xwidth, ntodo;
    int convert, nulcheck, readcheck = 0;
    LONGLONG repeat, startpos, elemnum, readptr, tnull;
    LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
    char tform[20];
    char message[FLEN_ERRMSG];
    char snull[20];   /*  the FITS null value if reading from ASCII table  */

    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
    void *buffer;

    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
        return(*status);

    buffer = cbuff;

    if (anynul)
        *anynul = 0;

    if (nultyp == 2)
        memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if (elemincre < 0)
        readcheck = -1;  /* don't do range checking in this case */

    if ( ffgcprll( fptr, colnum, firstrow, firstelem, nelem, readcheck, &scale, &zero,
         tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
         return(*status);
    maxelem = maxelem2;

    incre *= elemincre;   /* multiply incre to just get every nth pixel */

    if (tcode == TSTRING)    /* setup for ASCII tables */
    {
      /* get the number of implied decimal places if no explicit decmal point */
      ffasfm(tform, &xcode, &xwidth, &decimals, status); 
      for(ii = 0; ii < decimals; ii++)
        power *= 10.;
    }

    /*------------------------------------------------------------------*/
    /*  Decide whether to check for null values in the input FITS file: */
    /*------------------------------------------------------------------*/
    nulcheck = nultyp; /* by default check for null values in the FITS file */

    if (nultyp == 1 && nulval == 0)
       nulcheck = 0;    /* calling routine does not want to check for nulls */

    else if (tcode%10 == 1 &&        /* if reading an integer column, and  */ 
            tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
            nulcheck = 0;            /* then do not check for null values. */

    else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
            nulcheck = 0;            /* Impossible null value */

    else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
            nulcheck = 0;            /* Impossible null value */

    else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
         nulcheck = 0;

    /*----------------------------------------------------------------------*/
    /*  If FITS column and output data array have same datatype, then we do */
    /*  not need to use a temporary buffer to store intermediate datatype.  */
    /*----------------------------------------------------------------------*/
    convert = 1;
    if (tcode == TDOUBLE) /* Special Case:                        */
    {                              /* no type convertion required, so read */
                                  /* data directly into output buffer.    */

        if (nelem < (LONGLONG)INT32_MAX/8) {
            maxelem = nelem;
        } else {
            maxelem = INT32_MAX/8;
        }

        if (nulcheck == 0 && scale == 1. && zero == 0.)
            convert = 0;  /* no need to scale data or find nulls */
    }

    /*---------------------------------------------------------------------*/
    /*  Now read the pixels from the FITS column. If the column does not   */
    /*  have the same datatype as the output array, then we have to read   */
    /*  the raw values into a temporary buffer (of limited size).  In      */
    /*  the case of a vector colum read only 1 vector of values at a time  */
    /*  then skip to the next row if more values need to be read.          */
    /*  After reading the raw values, then call the fffXXYY routine to (1) */
    /*  test for undefined values, (2) convert the datatype if necessary,  */
    /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
    /*  scaling parameters.                                                */
    /*---------------------------------------------------------------------*/
    remain = nelem;           /* remaining number of values to read */
    next = 0;                 /* next element in array to be read   */
    rownum = 0;               /* row number, relative to firstrow   */

    while (remain)
    {
        /* limit the number of pixels to read at one time to the number that
           will fit in the buffer or to the number of pixels that remain in
           the current vector, which ever is smaller.
        */
        ntodo = (long) minvalue(remain, maxelem);
        if (elemincre >= 0)
        {
          ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));
        }
        else
        {
          ntodo = (long) minvalue(ntodo, (elemnum/(-elemincre) +1));
        }

        readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));

        switch (tcode) 
        {
            case (TDOUBLE):
                ffgr8b(fptr, readptr, ntodo, incre, &array[next], status);
                if (convert)
                    fffr8r8(&array[next], ntodo, scale, zero, nulcheck, 
                           nulval, &nularray[next], anynul, 
                           &array[next], status);
                break;
            case (TBYTE):
                ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer,
                       status);
                fffi1r8((unsigned char *) buffer, ntodo, scale, zero, nulcheck, 
                   (unsigned char) tnull, nulval, &nularray[next], anynul, 
                   &array[next], status);
                break;
            case (TSHORT):
                ffgi2b(fptr, readptr, ntodo, incre, (short  *) buffer, status);
                fffi2r8((short  *) buffer, ntodo, scale, zero, nulcheck, 
                    (short) tnull, nulval, &nularray[next], anynul, 
                       &array[next], status);
                break;
            case (TLONG):
                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer,
                       status);
                fffi4r8((INT32BIT *) buffer, ntodo, scale, zero, nulcheck, 
                       (INT32BIT) tnull, nulval, &nularray[next], anynul, 
                       &array[next], status);
                break;
            case (TLONGLONG):
                ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status);
                fffi8r8( (LONGLONG *) buffer, ntodo, scale, zero, 
                           nulcheck, tnull, nulval, &nularray[next], 
                            anynul, &array[next], status);
                break;
            case (TFLOAT):
                ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
                fffr4r8((float  *) buffer, ntodo, scale, zero, nulcheck, 
                          nulval, &nularray[next], anynul, 
                          &array[next], status);
                break;
            case (TSTRING):
                ffmbyt(fptr, readptr, REPORT_EOF, status);
       
                if (incre == twidth)    /* contiguous bytes */
                     ffgbyt(fptr, ntodo * twidth, buffer, status);
                else
                     ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
                               status);

                fffstrr8((char *) buffer, ntodo, scale, zero, twidth, power,
                     nulcheck, snull, nulval, &nularray[next], anynul,
                     &array[next], status);
                break;


            default:  /*  error trap for invalid column format */
                snprintf(message, FLEN_ERRMSG,
                   "Cannot read numbers from column %d which has format %s",
                    colnum, tform);
                ffpmsg(message);
                if (hdutype == ASCII_TBL)
                    return(*status = BAD_ATABLE_FORMAT);
                else
                    return(*status = BAD_BTABLE_FORMAT);

        } /* End of switch block */

        /*-------------------------*/
        /*  Check for fatal error  */
        /*-------------------------*/
        if (*status > 0)  /* test for error during previous read operation */
        {
	  dtemp = (double) next;
          if (hdutype > 0)
            snprintf(message,FLEN_ERRMSG,
            "Error reading elements %.0f thru %.0f from column %d (ffgcld).",
              dtemp+1., dtemp+ntodo, colnum);
          else
            snprintf(message,FLEN_ERRMSG,
            "Error reading elements %.0f thru %.0f from image (ffgcld).",
              dtemp+1., dtemp+ntodo);

          ffpmsg(message);
          return(*status);
        }

        /*--------------------------------------------*/
        /*  increment the counters for the next loop  */
        /*--------------------------------------------*/
        remain -= ntodo;
        if (remain)
        {
            next += ntodo;
            elemnum = elemnum + (ntodo * elemincre);

            if (elemnum >= repeat)  /* completed a row; start on later row */
            {
                rowincre = (long) (elemnum / repeat);
                rownum += rowincre;
                elemnum = elemnum - (rowincre * repeat);
            }
            else if (elemnum < 0)  /* completed a row; start on a previous row */
            {
                rowincre = (long) ((-elemnum - 1) / repeat + 1);
                rownum -= rowincre;
                elemnum = (rowincre * repeat) + elemnum;
            }
        }
    }  /*  End of main while Loop  */


    /*--------------------------------*/
    /*  check for numerical overflow  */
    /*--------------------------------*/
    if (*status == OVERFLOW_ERR)
    {
        ffpmsg(
        "Numerical overflow during type conversion while reading FITS data.");
        *status = NUM_OVERFLOW;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi1r8(unsigned char *input, /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
            double nullval,       /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            double *output,       /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
                output[ii] = (double) input[ii]; /* copy input to output */
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                output[ii] = input[ii] * scale + zero;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = (double) input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    output[ii] = input[ii] * scale + zero;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi2r8(short *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            short tnull,          /* I - value of FITS TNULLn keyword if any */
            double nullval,       /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            double *output,       /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
                output[ii] = (double) input[ii]; /* copy input to output */
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                output[ii] = input[ii] * scale + zero;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = (double) input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    output[ii] = input[ii] * scale + zero;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi4r8(INT32BIT *input,      /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
            double nullval,       /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            double *output,       /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
                output[ii] = (double) input[ii]; /* copy input to output */
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                output[ii] = input[ii] * scale + zero;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = (double) input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    output[ii] = input[ii] * scale + zero;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi8r8(LONGLONG *input,      /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
            double nullval,       /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            double *output,       /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
                output[ii] = (double) input[ii]; /* copy input to output */
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                output[ii] = input[ii] * scale + zero;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = (double) input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    output[ii] = input[ii] * scale + zero;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffr4r8(float *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            double nullval,       /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            double *output,       /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to NaN.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    short *sptr, iret;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
                output[ii] = (double) input[ii]; /* copy input to output */
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                output[ii] = input[ii] * scale + zero;
            }
        }
    }
    else        /* must check for null values */
    {
        sptr = (short *) input;

#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
        sptr++;       /* point to MSBs */
#endif
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++, sptr += 2)
            {
              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                     output[ii] = 0;
              }
              else
                output[ii] = (double) input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++, sptr += 2)
            {
              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {  
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                     output[ii] = zero;
              }
              else
                  output[ii] = input[ii] * scale + zero;
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffr8r8(double *input,        /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            double nullval,       /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            double *output,       /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to NaN.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    short *sptr, iret;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            memmove(output, input, ntodo * sizeof(double) );
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                output[ii] = input[ii] * scale + zero;
            }
        }
    }
    else        /* must check for null values */
    {
        sptr = (short *) input;

#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
        sptr += 3;       /* point to MSBs */
#endif

        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++, sptr += 4)
            {
              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                    {
                        nullarray[ii] = 1;
                       /* explicitly set value in case output contains a NaN */
                        output[ii] = DOUBLENULLVALUE;
                    }
                  }
                  else            /* it's an underflow */
                     output[ii] = 0;
              }
              else
                  output[ii] = input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++, sptr += 4)
            {
              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {  
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                    {
                        nullarray[ii] = 1;
                       /* explicitly set value in case output contains a NaN */
                        output[ii] = DOUBLENULLVALUE;
                    }
                  }
                  else            /* it's an underflow */
                     output[ii] = zero;
              }
              else
                  output[ii] = input[ii] * scale + zero;
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffstrr8(char *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            long twidth,          /* I - width of each substring of chars    */
            double implipower,    /* I - power of 10 of implied decimal      */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            char  *snull,         /* I - value of FITS null string, if any   */
            double nullval,       /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            double *output,       /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file. Check
  for null values and do scaling if required. The nullcheck code value
  determines how any null values in the input array are treated. A null
  value is an input pixel that is equal to snull.  If nullcheck= 0, then
  no special checking for nulls is performed.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    int nullen;
    long ii;
    double dvalue;
    char *cstring, message[FLEN_ERRMSG];
    char *cptr, *tpos;
    char tempstore, chrzero = '0';
    double val, power;
    int exponent, sign, esign, decpt;

    nullen = strlen(snull);
    cptr = input;  /* pointer to start of input string */
    for (ii = 0; ii < ntodo; ii++)
    {
      cstring = cptr;
      /* temporarily insert a null terminator at end of the string */
      tpos = cptr + twidth;
      tempstore = *tpos;
      *tpos = 0;

      /* check if null value is defined, and if the    */
      /* column string is identical to the null string */
      if (snull[0] != ASCII_NULL_UNDEFINED && 
         !strncmp(snull, cptr, nullen) )
      {
        if (nullcheck)  
        {
          *anynull = 1;    
          if (nullcheck == 1)
            output[ii] = nullval;
          else
            nullarray[ii] = 1;
        }
        cptr += twidth;
      }
      else
      {
        /* value is not the null value, so decode it */
        /* remove any embedded blank characters from the string */

        decpt = 0;
        sign = 1;
        val  = 0.;
        power = 1.;
        exponent = 0;
        esign = 1;

        while (*cptr == ' ')               /* skip leading blanks */
           cptr++;

        if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
        {
          if (*cptr == '-')
             sign = -1;

          cptr++;

          while (*cptr == ' ')         /* skip blanks between sign and value */
            cptr++;
        }

        while (*cptr >= '0' && *cptr <= '9')
        {
          val = val * 10. + *cptr - chrzero;  /* accumulate the value */
          cptr++;

          while (*cptr == ' ')         /* skip embedded blanks in the value */
            cptr++;
        }

        if (*cptr == '.' || *cptr == ',')              /* check for decimal point */
        {
          decpt = 1;       /* set flag to show there was a decimal point */
          cptr++;
          while (*cptr == ' ')         /* skip any blanks */
            cptr++;

          while (*cptr >= '0' && *cptr <= '9')
          {
            val = val * 10. + *cptr - chrzero;  /* accumulate the value */
            power = power * 10.;
            cptr++;

            while (*cptr == ' ')         /* skip embedded blanks in the value */
              cptr++;
          }
        }

        if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
        {
          cptr++;
          while (*cptr == ' ')         /* skip blanks */
              cptr++;
  
          if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
          {
            if (*cptr == '-')
               esign = -1;

            cptr++;

            while (*cptr == ' ')        /* skip blanks between sign and exp */
              cptr++;
          }

          while (*cptr >= '0' && *cptr <= '9')
          {
            exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
            cptr++;

            while (*cptr == ' ')         /* skip embedded blanks */
              cptr++;
          }
        }

        if (*cptr  != 0)  /* should end up at the null terminator */
        {
          snprintf(message, FLEN_ERRMSG,"Cannot read number from ASCII table");
          ffpmsg(message);
          snprintf(message,FLEN_ERRMSG, "Column field = %s.", cstring);
          ffpmsg(message);
          /* restore the char that was overwritten by the null */
          *tpos = tempstore;
          return(*status = BAD_C2D);
        }

        if (!decpt)  /* if no explicit decimal, use implied */
           power = implipower;

        dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));

        output[ii] = (dvalue * scale + zero);   /* apply the scaling */
      }
      /* restore the char that was overwritten by the null */
      *tpos = tempstore;
    }
    return(*status);
}
cfitsio/getcole.c0000644000225700000360000020371713246025103013600 0ustar  cagordonlhea/*  This file, getcole.c, contains routines that read data elements from   */
/*  a FITS image or table, with float datatype                             */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include 
#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int ffgpve( fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            float nulval,     /* I - value for undefined pixels              */
            float *array,     /* O - array of values that are returned       */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Undefined elements will be set equal to NULVAL, unless NULVAL=0
  in which case no checking for undefined values will be performed.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    long row;
    char cdummy;
    int nullcheck = 1;
    float nullvalue;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */
         nullvalue = nulval;  /* set local variable */

        fits_read_compressed_pixels(fptr, TFLOAT, firstelem, nelem,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgcle(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
               array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgpfe( fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            float *array,     /* O - array of values that are returned       */
            char *nularray,   /* O - array of null pixel flags               */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Any undefined pixels in the returned array will be set = 0 and the 
  corresponding nularray value will be set = 1.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    long row;
    int nullcheck = 2;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_read_compressed_pixels(fptr, TFLOAT, firstelem, nelem,
            nullcheck, NULL, array, nularray, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgcle(fptr, 2, row, firstelem, nelem, 1, 2, 0.F,
               array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffg2de(fitsfile *fptr,  /* I - FITS file pointer                       */
           long  group,     /* I - group to read (1 = 1st group)           */
           float nulval,    /* set undefined pixels equal to this          */
           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
           float *array,    /* O - array to be filled and returned         */
           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
           int  *status)    /* IO - error status                           */
/*
  Read an entire 2-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being read).  Any null
  values in the array will be set equal to the value of nulval, unless
  nulval = 0 in which case no null checking will be performed.
*/
{
    /* call the 3D reading routine, with the 3rd dimension = 1 */

    ffg3de(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, 
           anynul, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffg3de(fitsfile *fptr,  /* I - FITS file pointer                       */
           long  group,     /* I - group to read (1 = 1st group)           */
           float nulval,    /* set undefined pixels equal to this          */
           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
           LONGLONG  nrows,     /* I - number of rows in each plane of array   */
           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
           LONGLONG  naxis3,    /* I - FITS image NAXIS3 value                 */
           float *array,    /* O - array to be filled and returned         */
           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
           int  *status)    /* IO - error status                           */
/*
  Read an entire 3-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being read).  Any null
  values in the array will be set equal to the value of nulval, unless
  nulval = 0 in which case no null checking will be performed.
*/
{
    long tablerow;
    LONGLONG narray, nfits, ii, jj;
    char cdummy;
    int nullcheck = 1;
    long inc[] = {1,1,1};
    LONGLONG fpixel[] = {1,1,1};
    LONGLONG lpixel[3];
    float nullvalue;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        lpixel[0] = ncols;
        lpixel[1] = nrows;
        lpixel[2] = naxis3;
        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_img(fptr, TFLOAT, fpixel, lpixel, inc,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */
    tablerow=maxvalue(1,group);

    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
    {
       /* all the image pixels are contiguous, so read all at once */
       ffgcle(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval,
               array, &cdummy, anynul, status);
       return(*status);
    }

    if (ncols < naxis1 || nrows < naxis2)
       return(*status = BAD_DIMEN);

    nfits = 1;   /* next pixel in FITS image to read */
    narray = 0;  /* next pixel in output array to be filled */

    /* loop over naxis3 planes in the data cube */
    for (jj = 0; jj < naxis3; jj++)
    {
      /* loop over the naxis2 rows in the FITS image, */
      /* reading naxis1 pixels to each row            */

      for (ii = 0; ii < naxis2; ii++)
      {
       if (ffgcle(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval,
          &array[narray], &cdummy, anynul, status) > 0)
          return(*status);

       nfits += naxis1;
       narray += ncols;
      }
      narray += (nrows - naxis2) * ncols;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsve(fitsfile *fptr, /* I - FITS file pointer                         */
           int  colnum,    /* I - number of the column to read (1 = 1st)    */
           int naxis,      /* I - number of dimensions in the FITS array    */
           long  *naxes,   /* I - size of each dimension                    */
           long  *blc,     /* I - 'bottom left corner' of the subsection    */
           long  *trc,     /* I - 'top right corner' of the subsection      */
           long  *inc,     /* I - increment to be applied in each dimension */
           float nulval,   /* I - value to set undefined pixels             */
           float *array,   /* O - array to be filled and returned           */
           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
           int  *status)   /* IO - error status                             */
/*
  Read a subsection of data values from an image or a table column.
  This routine is set up to handle a maximum of nine dimensions.
*/
{
    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
    long str[9],stp[9],incr[9],dir[9];
    long nelem, nultyp, ninc, numcol;
    LONGLONG felem, dsize[10], blcll[9], trcll[9];
    int hdutype, anyf;
    char ldummy, msg[FLEN_ERRMSG];
    int nullcheck = 1;
    float nullvalue;

    if (naxis < 1 || naxis > 9)
    {
        snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsve is out of range", naxis);
        ffpmsg(msg);
        return(*status = BAD_DIMEN);
    }

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        for (ii=0; ii < naxis; ii++) {
	    blcll[ii] = blc[ii];
	    trcll[ii] = trc[ii];
	}

        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_img(fptr, TFLOAT, blcll, trcll, inc,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

/*
    if this is a primary array, then the input COLNUM parameter should
    be interpreted as the row number, and we will alway read the image
    data from column 2 (any group parameters are in column 1).
*/
    if (ffghdt(fptr, &hdutype, status) > 0)
        return(*status);

    if (hdutype == IMAGE_HDU)
    {
        /* this is a primary array, or image extension */
        if (colnum == 0)
        {
            rstr = 1;
            rstp = 1;
        }
        else
        {
            rstr = colnum;
            rstp = colnum;
        }
        rinc = 1;
        numcol = 2;
    }
    else
    {
        /* this is a table, so the row info is in the (naxis+1) elements */
        rstr = blc[naxis];
        rstp = trc[naxis];
        rinc = inc[naxis];
        numcol = colnum;
    }

    nultyp = 1;
    if (anynul)
        *anynul = FALSE;

    i0 = 0;
    for (ii = 0; ii < 9; ii++)
    {
        str[ii] = 1;
        stp[ii] = 1;
        incr[ii] = 1;
        dsize[ii] = 1;
        dir[ii] = 1;
    }

    for (ii = 0; ii < naxis; ii++)
    {
      if (trc[ii] < blc[ii])
      {
        if (hdutype == IMAGE_HDU)
        {
           dir[ii] = -1;
        }
        else
        {
          snprintf(msg, FLEN_ERRMSG,"ffgsve: illegal range specified for axis %ld", ii + 1);
          ffpmsg(msg);
          return(*status = BAD_PIX_NUM);
        }
      }

      str[ii] = blc[ii];
      stp[ii] = trc[ii];
      incr[ii] = inc[ii];
      dsize[ii + 1] = dsize[ii] * naxes[ii];
      dsize[ii] = dsize[ii] * dir[ii];
    }
    dsize[naxis] = dsize[naxis] * dir[naxis];

    if (naxis == 1 && naxes[0] == 1)
    {
      /* This is not a vector column, so read all the rows at once */
      nelem = (rstp - rstr) / rinc + 1;
      ninc = rinc;
      rstp = rstr;
    }
    else
    {
      /* have to read each row individually, in all dimensions */
      nelem = (stp[0]*dir[0] - str[0]*dir[0]) / inc[0] + 1;
      ninc = incr[0] * dir[0];
    }

    for (row = rstr; row <= rstp; row += rinc)
    {
     for (i8 = str[8]*dir[8]; i8 <= stp[8]*dir[8]; i8 += incr[8])
     {
      for (i7 = str[7]*dir[7]; i7 <= stp[7]*dir[7]; i7 += incr[7])
      {
       for (i6 = str[6]*dir[6]; i6 <= stp[6]*dir[6]; i6 += incr[6])
       {
        for (i5 = str[5]*dir[5]; i5 <= stp[5]*dir[5]; i5 += incr[5])
        {
         for (i4 = str[4]*dir[4]; i4 <= stp[4]*dir[4]; i4 += incr[4])
         {
          for (i3 = str[3]*dir[3]; i3 <= stp[3]*dir[3]; i3 += incr[3])
          {
           for (i2 = str[2]*dir[2]; i2 <= stp[2]*dir[2]; i2 += incr[2])
           {
            for (i1 = str[1]*dir[1]; i1 <= stp[1]*dir[1]; i1 += incr[1])
            {

              felem=str[0] + (i1 - dir[1]) * dsize[1] + (i2 - dir[2]) * dsize[2] + 
                             (i3 - dir[3]) * dsize[3] + (i4 - dir[4]) * dsize[4] +
                             (i5 - dir[5]) * dsize[5] + (i6 - dir[6]) * dsize[6] +
                             (i7 - dir[7]) * dsize[7] + (i8 - dir[8]) * dsize[8];

              if ( ffgcle(fptr, numcol, row, felem, nelem, ninc, nultyp,
                   nulval, &array[i0], &ldummy, &anyf, status) > 0)
                   return(*status);

              if (anyf && anynul)
                  *anynul = TRUE;

              i0 += nelem;
            }
           }
          }
         }
        }
       }
      }
     }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsfe(fitsfile *fptr, /* I - FITS file pointer                         */
           int  colnum,    /* I - number of the column to read (1 = 1st)    */
           int naxis,      /* I - number of dimensions in the FITS array    */
           long  *naxes,   /* I - size of each dimension                    */
           long  *blc,     /* I - 'bottom left corner' of the subsection    */
           long  *trc,     /* I - 'top right corner' of the subsection      */
           long  *inc,     /* I - increment to be applied in each dimension */
           float *array,   /* O - array to be filled and returned           */
           char *flagval,  /* O - set to 1 if corresponding value is null   */
           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
           int  *status)   /* IO - error status                             */
/*
  Read a subsection of data values from an image or a table column.
  This routine is set up to handle a maximum of nine dimensions.
*/
{
    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
    long str[9],stp[9],incr[9],dsize[10];
    LONGLONG blcll[9], trcll[9];
    long felem, nelem, nultyp, ninc, numcol;
    int hdutype, anyf;
    float nulval = 0;
    char msg[FLEN_ERRMSG];
    int nullcheck = 2;

    if (naxis < 1 || naxis > 9)
    {
        snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsve is out of range", naxis);
        ffpmsg(msg);
        return(*status = BAD_DIMEN);
    }

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        for (ii=0; ii < naxis; ii++) {
	    blcll[ii] = blc[ii];
	    trcll[ii] = trc[ii];
	}

        fits_read_compressed_img(fptr, TFLOAT, blcll, trcll, inc,
            nullcheck, NULL, array, flagval, anynul, status);
        return(*status);
    }

/*
    if this is a primary array, then the input COLNUM parameter should
    be interpreted as the row number, and we will alway read the image
    data from column 2 (any group parameters are in column 1).
*/
    if (ffghdt(fptr, &hdutype, status) > 0)
        return(*status);

    if (hdutype == IMAGE_HDU)
    {
        /* this is a primary array, or image extension */
        if (colnum == 0)
        {
            rstr = 1;
            rstp = 1;
        }
        else
        {
            rstr = colnum;
            rstp = colnum;
        }
        rinc = 1;
        numcol = 2;
    }
    else
    {
        /* this is a table, so the row info is in the (naxis+1) elements */
        rstr = blc[naxis];
        rstp = trc[naxis];
        rinc = inc[naxis];
        numcol = colnum;
    }

    nultyp = 2;
    if (anynul)
        *anynul = FALSE;

    i0 = 0;
    for (ii = 0; ii < 9; ii++)
    {
        str[ii] = 1;
        stp[ii] = 1;
        incr[ii] = 1;
        dsize[ii] = 1;
    }

    for (ii = 0; ii < naxis; ii++)
    {
      if (trc[ii] < blc[ii])
      {
        snprintf(msg, FLEN_ERRMSG,"ffgsve: illegal range specified for axis %ld", ii + 1);
        ffpmsg(msg);
        return(*status = BAD_PIX_NUM);
      }

      str[ii] = blc[ii];
      stp[ii] = trc[ii];
      incr[ii] = inc[ii];
      dsize[ii + 1] = dsize[ii] * naxes[ii];
    }

    if (naxis == 1 && naxes[0] == 1)
    {
      /* This is not a vector column, so read all the rows at once */
      nelem = (rstp - rstr) / rinc + 1;
      ninc = rinc;
      rstp = rstr;
    }
    else
    {
      /* have to read each row individually, in all dimensions */
      nelem = (stp[0] - str[0]) / inc[0] + 1;
      ninc = incr[0];
    }

    for (row = rstr; row <= rstp; row += rinc)
    {
     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
     {
      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
      {
       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
       {
        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
        {
         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
         {
          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
          {
           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
           {
            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
            {
              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];

              if ( ffgcle(fptr, numcol, row, felem, nelem, ninc, nultyp,
                   nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
                   return(*status);

              if (anyf && anynul)
                  *anynul = TRUE;

              i0 += nelem;
            }
           }
          }
         }
        }
       }
      }
     }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffggpe( fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            long  firstelem,  /* I - first vector element to read (1 = 1st)  */
            long  nelem,      /* I - number of values to read                */
            float *array,     /* O - array of values that are returned       */
            int  *status)     /* IO - error status                           */
/*
  Read an array of group parameters from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
*/
{
    long row;
    int idummy;
    char cdummy;
    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgcle(fptr, 1, row, firstelem, nelem, 1, 1, 0.F,
               array, &cdummy, &idummy, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcve(fitsfile *fptr,   /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
           float nulval,     /* I - value for null pixels                   */
           float *array,     /* O - array of values that are read           */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Any undefined pixels will be set equal to the value of 'nulval' unless
  nulval = 0 in which case no checks for undefined pixels will be made.
*/
{
    char cdummy;

    ffgcle(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
           array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcvc(fitsfile *fptr,   /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
           float nulval,     /* I - value for null pixels                   */
           float *array,     /* O - array of values that are read           */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Any undefined pixels will be set equal to the value of 'nulval' unless
  nulval = 0 in which case no checks for undefined pixels will be made.

  TSCAL and ZERO should not be used with complex values. 
*/
{
    char cdummy;

    /* a complex value is interpreted as a pair of float values, thus */
    /* need to multiply the first element and number of elements by 2 */

    ffgcle(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem *2,
           1, 1, nulval, array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcfe(fitsfile *fptr,   /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
           float *array,     /* O - array of values that are read           */
           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Nularray will be set = 1 if the corresponding array pixel is undefined, 
  otherwise nularray will = 0.
*/
{
    float dummy = 0;

    ffgcle(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
           array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcfc(fitsfile *fptr,   /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
           float *array,     /* O - array of values that are read           */
           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Nularray will be set = 1 if the corresponding array pixel is undefined, 
  otherwise nularray will = 0.

  TSCAL and ZERO should not be used with complex values. 
*/
{
    LONGLONG ii, jj;
    float dummy = 0;
    char *carray;

    /* a complex value is interpreted as a pair of float values, thus */
    /* need to multiply the first element and number of elements by 2 */
    
    /* allocate temporary array */
    carray = (char *) calloc( (size_t) (nelem * 2), 1); 

    ffgcle(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2,
           1, 2, dummy, array, carray, anynul, status);

    for (ii = 0, jj = 0; jj < nelem; ii += 2, jj++)
    {
       if (carray[ii] || carray[ii + 1])
          nularray[jj] = 1;
       else
          nularray[jj] = 0;
    }

    free(carray);    
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcle( fitsfile *fptr,   /* I - FITS file pointer                       */
            int  colnum,      /* I - number of column to read (1 = 1st col)  */
            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
            LONGLONG firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
            int   nultyp,     /* I - null value handling code:               */
                              /*     1: set undefined pixels = nulval        */
                              /*     2: set nularray=1 for undefined pixels  */
            float nulval,     /* I - value for null pixels if nultyp = 1     */
            float *array,     /* O - array of values that are read           */
            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU.
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer be a virtual column in a 1 or more grouped FITS primary
  array or image extension.  FITSIO treats a primary array as a binary table
  with 2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.

  The output array of values will be converted from the datatype of the column 
  and will be scaled by the FITS TSCALn and TZEROn values if necessary.
*/
{
    double scale, zero, power = 1., dtemp;
    int tcode, maxelem2, hdutype, xcode, decimals;
    long twidth, incre;
    long ii, xwidth, ntodo;
    int convert, nulcheck, readcheck = 0;
    LONGLONG repeat, startpos, elemnum, readptr, tnull;
    LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
    char tform[20];
    char message[FLEN_ERRMSG];
    char snull[20];   /*  the FITS null value if reading from ASCII table  */

    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
    void *buffer;

    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
        return(*status);

    buffer = cbuff;

    if (anynul)
       *anynul = 0;

    if (nultyp == 2)
        memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if (elemincre < 0)
        readcheck = -1;  /* don't do range checking in this case */

    if ( ffgcprll( fptr, colnum, firstrow, firstelem, nelem, readcheck, &scale, &zero,
         tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
         return(*status);
    maxelem = maxelem2;

    incre *= elemincre;   /* multiply incre to just get every nth pixel */

    if (tcode == TSTRING)    /* setup for ASCII tables */
    {
      /* get the number of implied decimal places if no explicit decmal point */
      ffasfm(tform, &xcode, &xwidth, &decimals, status); 
      for(ii = 0; ii < decimals; ii++)
        power *= 10.;
    }

    /*------------------------------------------------------------------*/
    /*  Decide whether to check for null values in the input FITS file: */
    /*------------------------------------------------------------------*/
    nulcheck = nultyp; /* by default check for null values in the FITS file */

    if (nultyp == 1 && nulval == 0)
       nulcheck = 0;    /* calling routine does not want to check for nulls */

    else if (tcode%10 == 1 &&        /* if reading an integer column, and  */ 
            tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
            nulcheck = 0;            /* then do not check for null values. */

    else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
            nulcheck = 0;            /* Impossible null value */

    else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
            nulcheck = 0;            /* Impossible null value */

    else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
         nulcheck = 0;

    /*----------------------------------------------------------------------*/
    /*  If FITS column and output data array have same datatype, then we do */
    /*  not need to use a temporary buffer to store intermediate datatype.  */
    /*----------------------------------------------------------------------*/
    convert = 1;
    if (tcode == TFLOAT) /* Special Case:                        */
    {                             /* no type convertion required, so read */
                                  /* data directly into output buffer.    */

        if (nelem < (LONGLONG)INT32_MAX/4) {
            maxelem = nelem;
        } else {
            maxelem = INT32_MAX/4;
        }

        if (nulcheck == 0 && scale == 1. && zero == 0.)
            convert = 0;  /* no need to scale data or find nulls */
    }

    /*---------------------------------------------------------------------*/
    /*  Now read the pixels from the FITS column. If the column does not   */
    /*  have the same datatype as the output array, then we have to read   */
    /*  the raw values into a temporary buffer (of limited size).  In      */
    /*  the case of a vector colum read only 1 vector of values at a time  */
    /*  then skip to the next row if more values need to be read.          */
    /*  After reading the raw values, then call the fffXXYY routine to (1) */
    /*  test for undefined values, (2) convert the datatype if necessary,  */
    /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
    /*  scaling parameters.                                                */
    /*---------------------------------------------------------------------*/
    remain = nelem;           /* remaining number of values to read */
    next = 0;                 /* next element in array to be read   */
    rownum = 0;               /* row number, relative to firstrow   */

    while (remain)
    {
        /* limit the number of pixels to read at one time to the number that
           will fit in the buffer or to the number of pixels that remain in
           the current vector, which ever is smaller.
        */
        ntodo = (long) minvalue(remain, maxelem);
        if (elemincre >= 0)
        {
          ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));
        }
        else
        {
          ntodo = (long) minvalue(ntodo, (elemnum/(-elemincre) +1));
        }

        readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));

        switch (tcode) 
        {
            case (TFLOAT):
                ffgr4b(fptr, readptr, ntodo, incre, &array[next], status);
                if (convert)
                    fffr4r4(&array[next], ntodo, scale, zero, nulcheck, 
                           nulval, &nularray[next], anynul, 
                           &array[next], status);
                break;
            case (TBYTE):
                ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer,
                       status);
                fffi1r4((unsigned char *) buffer, ntodo, scale, zero, nulcheck, 
                    (unsigned char) tnull, nulval, &nularray[next], anynul, 
                     &array[next], status);
                break;
            case (TSHORT):
                ffgi2b(fptr, readptr, ntodo, incre, (short  *) buffer, status);
                fffi2r4((short  *) buffer, ntodo, scale, zero, nulcheck, 
                       (short) tnull, nulval, &nularray[next], anynul, 
                       &array[next], status);
                break;
            case (TLONG):
                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer,
                       status);
                fffi4r4((INT32BIT *) buffer, ntodo, scale, zero, nulcheck, 
                       (INT32BIT) tnull, nulval, &nularray[next], anynul, 
                       &array[next], status);
                break;

            case (TLONGLONG):
                ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status);
                fffi8r4( (LONGLONG *) buffer, ntodo, scale, zero, 
                           nulcheck, tnull, nulval, &nularray[next], 
                            anynul, &array[next], status);
                break;
            case (TDOUBLE):
                ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
                fffr8r4((double *) buffer, ntodo, scale, zero, nulcheck, 
                          nulval, &nularray[next], anynul, 
                          &array[next], status);
                break;
            case (TSTRING):
                ffmbyt(fptr, readptr, REPORT_EOF, status);
       
                if (incre == twidth)    /* contiguous bytes */
                     ffgbyt(fptr, ntodo * twidth, buffer, status);
                else
                     ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
                               status);

                fffstrr4((char *) buffer, ntodo, scale, zero, twidth, power,
                     nulcheck, snull, nulval, &nularray[next], anynul,
                     &array[next], status);
                break;


            default:  /*  error trap for invalid column format */
                snprintf(message, FLEN_ERRMSG,
                   "Cannot read numbers from column %d which has format %s",
                    colnum, tform);
                ffpmsg(message);
                if (hdutype == ASCII_TBL)
                    return(*status = BAD_ATABLE_FORMAT);
                else
                    return(*status = BAD_BTABLE_FORMAT);

        } /* End of switch block */

        /*-------------------------*/
        /*  Check for fatal error  */
        /*-------------------------*/
        if (*status > 0)  /* test for error during previous read operation */
        {
	  dtemp = (double) next;
          if (hdutype > 0)
            snprintf(message,FLEN_ERRMSG,
            "Error reading elements %.0f thru %.0f from column %d (ffgcle).",
              dtemp+1., dtemp+ntodo, colnum);
          else
            snprintf(message,FLEN_ERRMSG,
            "Error reading elements %.0f thru %.0f from image (ffgcle).",
              dtemp+1., dtemp+ntodo);

          ffpmsg(message);
          return(*status);
        }

        /*--------------------------------------------*/
        /*  increment the counters for the next loop  */
        /*--------------------------------------------*/
        remain -= ntodo;
        if (remain)
        {
            next += ntodo;
            elemnum = elemnum + (ntodo * elemincre);

            if (elemnum >= repeat)  /* completed a row; start on later row */
            {
                rowincre = elemnum / repeat;
                rownum += rowincre;
                elemnum = elemnum - (rowincre * repeat);
            }
            else if (elemnum < 0)  /* completed a row; start on a previous row */
            {
                rowincre = (-elemnum - 1) / repeat + 1;
                rownum -= rowincre;
                elemnum = (rowincre * repeat) + elemnum;
            }
        }
    }  /*  End of main while Loop  */


    /*--------------------------------*/
    /*  check for numerical overflow  */
    /*--------------------------------*/
    if (*status == OVERFLOW_ERR)
    {
        ffpmsg(
        "Numerical overflow during type conversion while reading FITS data.");
        *status = NUM_OVERFLOW;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi1r4(unsigned char *input, /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
            float nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            float *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
                output[ii] = (float) input[ii];  /* copy input to output */
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                output[ii] = (float) (( (double) input[ii] ) * scale + zero);
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = (float) input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    output[ii] = (float) (( (double) input[ii] ) * scale + zero);
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi2r4(short *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            short tnull,          /* I - value of FITS TNULLn keyword if any */
            float nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            float *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
                output[ii] = (float) input[ii];  /* copy input to output */
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                output[ii] = (float) (input[ii] * scale + zero);
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = (float) input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    output[ii] = (float) (input[ii] * scale + zero);
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi4r4(INT32BIT *input,      /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
            float nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            float *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
                output[ii] = (float) input[ii];  /* copy input to output */
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                output[ii] = (float) (input[ii] * scale + zero);
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = (float) input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    output[ii] = (float) (input[ii] * scale + zero);
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi8r4(LONGLONG *input,      /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
            float nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            float *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
                output[ii] = (float) input[ii];  /* copy input to output */
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                output[ii] = (float) (input[ii] * scale + zero);
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = (float) input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    output[ii] = (float) (input[ii] * scale + zero);
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffr4r4(float *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            float nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            float *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to NaN.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    short *sptr, iret;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            memmove(output, input, ntodo * sizeof(float) );
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                output[ii] = (float) (input[ii] * scale + zero);
            }
        }
    }
    else        /* must check for null values */
    {
        sptr = (short *) input;

#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
        sptr++;       /* point to MSBs */
#endif

        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++, sptr += 2)
            {
              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                    {
                        nullarray[ii] = 1;
                       /* explicitly set value in case output contains a NaN */
                        output[ii] = FLOATNULLVALUE;
                    }
                  }
                  else            /* it's an underflow */
                     output[ii] = 0;
              }
              else
                output[ii] = input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++, sptr += 2)
            {
              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {  
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                    {
                        nullarray[ii] = 1;
                       /* explicitly set value in case output contains a NaN */
                        output[ii] = FLOATNULLVALUE;
                    }
                  }
                  else            /* it's an underflow */
                     output[ii] = (float) zero;
              }
              else
                  output[ii] = (float) (input[ii] * scale + zero);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffr8r4(double *input,        /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            float nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            float *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to NaN.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    short *sptr, iret;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
                output[ii] = (float) input[ii]; /* copy input to output */
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                output[ii] = (float) (input[ii] * scale + zero);
            }
        }
    }
    else        /* must check for null values */
    {
        sptr = (short *) input;

#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
        sptr += 3;       /* point to MSBs */
#endif
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++, sptr += 4)
            {
              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                     output[ii] = 0;
              }
              else
                  output[ii] = (float) input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++, sptr += 4)
            {
              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {  
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                     output[ii] = (float) zero;
              }
              else
                  output[ii] = (float) (input[ii] * scale + zero);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffstrr4(char *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            long twidth,          /* I - width of each substring of chars    */
            double implipower,    /* I - power of 10 of implied decimal      */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            char  *snull,         /* I - value of FITS null string, if any   */
            float nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            float *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file. Check
  for null values and do scaling if required. The nullcheck code value
  determines how any null values in the input array are treated. A null
  value is an input pixel that is equal to snull.  If nullcheck= 0, then
  no special checking for nulls is performed.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    int nullen;
    long ii;
    double dvalue;
    char *cstring, message[FLEN_ERRMSG];
    char *cptr, *tpos;
    char tempstore, chrzero = '0';
    double val, power;
    int exponent, sign, esign, decpt;

    nullen = strlen(snull);
    cptr = input;  /* pointer to start of input string */
    for (ii = 0; ii < ntodo; ii++)
    {
      cstring = cptr;
      /* temporarily insert a null terminator at end of the string */
      tpos = cptr + twidth;
      tempstore = *tpos;
      *tpos = 0;

      /* check if null value is defined, and if the    */
      /* column string is identical to the null string */
      if (snull[0] != ASCII_NULL_UNDEFINED && 
         !strncmp(snull, cptr, nullen) )
      {
        if (nullcheck)  
        {
          *anynull = 1;    
          if (nullcheck == 1)
            output[ii] = nullval;
          else
            nullarray[ii] = 1;
        }
        cptr += twidth;
      }
      else
      {
        /* value is not the null value, so decode it */
        /* remove any embedded blank characters from the string */

        decpt = 0;
        sign = 1;
        val  = 0.;
        power = 1.;
        exponent = 0;
        esign = 1;

        while (*cptr == ' ')               /* skip leading blanks */
           cptr++;

        if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
        {
          if (*cptr == '-')
             sign = -1;

          cptr++;

          while (*cptr == ' ')         /* skip blanks between sign and value */
            cptr++;
        }

        while (*cptr >= '0' && *cptr <= '9')
        {
          val = val * 10. + *cptr - chrzero;  /* accumulate the value */
          cptr++;

          while (*cptr == ' ')         /* skip embedded blanks in the value */
            cptr++;
        }

        if (*cptr == '.' || *cptr == ',')       /* check for decimal point */
        {
          decpt = 1;       /* set flag to show there was a decimal point */
          cptr++;
          while (*cptr == ' ')         /* skip any blanks */
            cptr++;

          while (*cptr >= '0' && *cptr <= '9')
          {
            val = val * 10. + *cptr - chrzero;  /* accumulate the value */
            power = power * 10.;
            cptr++;

            while (*cptr == ' ')         /* skip embedded blanks in the value */
              cptr++;
          }
        }

        if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
        {
          cptr++;
          while (*cptr == ' ')         /* skip blanks */
              cptr++;
  
          if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
          {
            if (*cptr == '-')
               esign = -1;

            cptr++;

            while (*cptr == ' ')        /* skip blanks between sign and exp */
              cptr++;
          }

          while (*cptr >= '0' && *cptr <= '9')
          {
            exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
            cptr++;

            while (*cptr == ' ')         /* skip embedded blanks */
              cptr++;
          }
        }

        if (*cptr  != 0)  /* should end up at the null terminator */
        {
          snprintf(message, FLEN_ERRMSG,"Cannot read number from ASCII table");
          ffpmsg(message);
          snprintf(message, FLEN_ERRMSG, "Column field = %s.", cstring);
          ffpmsg(message);
          /* restore the char that was overwritten by the null */
          *tpos = tempstore;
          return(*status = BAD_C2D);
        }

        if (!decpt)  /* if no explicit decimal, use implied */
           power = implipower;

        dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));

        output[ii] = (float) (dvalue * scale + zero);   /* apply the scaling */

      }
      /* restore the char that was overwritten by the null */
      *tpos = tempstore;
    }
    return(*status);
}
cfitsio/getcoli.c0000644000225700000360000021657213246025103013607 0ustar  cagordonlhea/*  This file, getcoli.c, contains routines that read data elements from   */
/*  a FITS image or table, with short datatype.                            */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include 
#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int ffgpvi( fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            short nulval,     /* I - value for undefined pixels              */
            short *array,     /* O - array of values that are returned       */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Undefined elements will be set equal to NULVAL, unless NULVAL=0
  in which case no checking for undefined values will be performed.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    long row;
    char cdummy;
    int nullcheck = 1;
    short nullvalue;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */
         nullvalue = nulval;  /* set local variable */
        fits_read_compressed_pixels(fptr, TSHORT, firstelem, nelem,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }
    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgcli(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
               array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgpfi( fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            short *array,     /* O - array of values that are returned       */
            char *nularray,   /* O - array of null pixel flags               */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Any undefined pixels in the returned array will be set = 0 and the 
  corresponding nularray value will be set = 1.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    long row;
    int nullcheck = 2;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_read_compressed_pixels(fptr, TSHORT, firstelem, nelem,
            nullcheck, NULL, array, nularray, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgcli(fptr, 2, row, firstelem, nelem, 1, 2, 0,
               array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffg2di(fitsfile *fptr,  /* I - FITS file pointer                       */
           long  group,     /* I - group to read (1 = 1st group)           */
           short nulval,    /* set undefined pixels equal to this          */
           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
           short *array,    /* O - array to be filled and returned         */
           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
           int  *status)    /* IO - error status                           */
/*
  Read an entire 2-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being read).  Any null
  values in the array will be set equal to the value of nulval, unless
  nulval = 0 in which case no null checking will be performed.
*/
{
    /* call the 3D reading routine, with the 3rd dimension = 1 */

    ffg3di(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, 
           anynul, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffg3di(fitsfile *fptr,  /* I - FITS file pointer                       */
           long  group,     /* I - group to read (1 = 1st group)           */
           short nulval,    /* set undefined pixels equal to this          */
           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
           LONGLONG  nrows,     /* I - number of rows in each plane of array   */
           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
           LONGLONG  naxis3,    /* I - FITS image NAXIS3 value                 */
           short *array,    /* O - array to be filled and returned         */
           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
           int  *status)    /* IO - error status                           */
/*
  Read an entire 3-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being read).  Any null
  values in the array will be set equal to the value of nulval, unless
  nulval = 0 in which case no null checking will be performed.
*/
{
    long tablerow, ii, jj;
    LONGLONG nfits, narray;
    char cdummy;
    int nullcheck = 1;
    long inc[] = {1,1,1};
    LONGLONG fpixel[] = {1,1,1};
    LONGLONG lpixel[3];
    short nullvalue;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        lpixel[0] = ncols;
        lpixel[1] = nrows;
        lpixel[2] = naxis3;
        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_img(fptr, TSHORT, fpixel, lpixel, inc,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */
    tablerow=maxvalue(1,group);

    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
    {
       /* all the image pixels are contiguous, so read all at once */
       ffgcli(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval,
               array, &cdummy, anynul, status);
       return(*status);
    }

    if (ncols < naxis1 || nrows < naxis2)
       return(*status = BAD_DIMEN);

    nfits = 1;   /* next pixel in FITS image to read */
    narray = 0;  /* next pixel in output array to be filled */

    /* loop over naxis3 planes in the data cube */
    for (jj = 0; jj < naxis3; jj++)
    {
      /* loop over the naxis2 rows in the FITS image, */
      /* reading naxis1 pixels to each row            */

      for (ii = 0; ii < naxis2; ii++)
      {
       if (ffgcli(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval,
          &array[narray], &cdummy, anynul, status) > 0)
          return(*status);

       nfits += naxis1;
       narray += ncols;
      }
      narray += (nrows - naxis2) * ncols;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsvi(fitsfile *fptr, /* I - FITS file pointer                         */
           int  colnum,    /* I - number of the column to read (1 = 1st)    */
           int naxis,      /* I - number of dimensions in the FITS array    */
           long  *naxes,   /* I - size of each dimension                    */
           long  *blc,     /* I - 'bottom left corner' of the subsection    */
           long  *trc,     /* I - 'top right corner' of the subsection      */
           long  *inc,     /* I - increment to be applied in each dimension */
           short nulval,   /* I - value to set undefined pixels             */
           short *array,   /* O - array to be filled and returned           */
           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
           int  *status)   /* IO - error status                             */
/*
  Read a subsection of data values from an image or a table column.
  This routine is set up to handle a maximum of nine dimensions.
*/
{
    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
    long str[9],stp[9],incr[9],dir[9];
    long nelem, nultyp, ninc, numcol;
    LONGLONG felem, dsize[10], blcll[9], trcll[9];
    int hdutype, anyf;
    char ldummy, msg[FLEN_ERRMSG];
    int nullcheck = 1;
    short nullvalue;

    if (naxis < 1 || naxis > 9)
    {
        snprintf(msg,FLEN_ERRMSG, "NAXIS = %d in call to ffgsvi is out of range", naxis);
        ffpmsg(msg);
        return(*status = BAD_DIMEN);
    }

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        for (ii=0; ii < naxis; ii++) {
	    blcll[ii] = blc[ii];
	    trcll[ii] = trc[ii];
	}

        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_img(fptr, TSHORT, blcll, trcll, inc,
            nullcheck, &nullvalue, array, NULL, anynul, status);

        return(*status);
    }

/*
    if this is a primary array, then the input COLNUM parameter should
    be interpreted as the row number, and we will alway read the image
    data from column 2 (any group parameters are in column 1).
*/
    if (ffghdt(fptr, &hdutype, status) > 0)
        return(*status);

    if (hdutype == IMAGE_HDU)
    {
        /* this is a primary array, or image extension */
        if (colnum == 0)
        {
            rstr = 1;
            rstp = 1;
        }
        else
        {
            rstr = colnum;
            rstp = colnum;
        }
        rinc = 1;
        numcol = 2;
    }
    else
    {
        /* this is a table, so the row info is in the (naxis+1) elements */
        rstr = blc[naxis];
        rstp = trc[naxis];
        rinc = inc[naxis];
        numcol = colnum;
    }

    nultyp = 1;
    if (anynul)
        *anynul = FALSE;

    i0 = 0;
    for (ii = 0; ii < 9; ii++)
    {
        str[ii] = 1;
        stp[ii] = 1;
        incr[ii] = 1;
        dsize[ii] = 1;
        dir[ii] = 1;
    }

    for (ii = 0; ii < naxis; ii++)
    {
      if (trc[ii] < blc[ii])
      {
        if (hdutype == IMAGE_HDU)
        {
           dir[ii] = -1;
        }
        else
        {
          snprintf(msg, FLEN_ERRMSG,"ffgsvi: illegal range specified for axis %ld", ii + 1);
          ffpmsg(msg);
          return(*status = BAD_PIX_NUM);
        }
      }

      str[ii] = blc[ii];
      stp[ii] = trc[ii];
      incr[ii] = inc[ii];
      dsize[ii + 1] = dsize[ii] * naxes[ii];
      dsize[ii] = dsize[ii] * dir[ii];
    }
    dsize[naxis] = dsize[naxis] * dir[naxis];

    if (naxis == 1 && naxes[0] == 1)
    {
      /* This is not a vector column, so read all the rows at once */
      nelem = (rstp - rstr) / rinc + 1;
      ninc = rinc;
      rstp = rstr;
    }
    else
    {
      /* have to read each row individually, in all dimensions */
      nelem = (stp[0]*dir[0] - str[0]*dir[0]) / inc[0] + 1;
      ninc = incr[0] * dir[0];
    }

    for (row = rstr; row <= rstp; row += rinc)
    {
     for (i8 = str[8]*dir[8]; i8 <= stp[8]*dir[8]; i8 += incr[8])
     {
      for (i7 = str[7]*dir[7]; i7 <= stp[7]*dir[7]; i7 += incr[7])
      {
       for (i6 = str[6]*dir[6]; i6 <= stp[6]*dir[6]; i6 += incr[6])
       {
        for (i5 = str[5]*dir[5]; i5 <= stp[5]*dir[5]; i5 += incr[5])
        {
         for (i4 = str[4]*dir[4]; i4 <= stp[4]*dir[4]; i4 += incr[4])
         {
          for (i3 = str[3]*dir[3]; i3 <= stp[3]*dir[3]; i3 += incr[3])
          {
           for (i2 = str[2]*dir[2]; i2 <= stp[2]*dir[2]; i2 += incr[2])
           {
            for (i1 = str[1]*dir[1]; i1 <= stp[1]*dir[1]; i1 += incr[1])
            {

              felem=str[0] + (i1 - dir[1]) * dsize[1] + (i2 - dir[2]) * dsize[2] + 
                             (i3 - dir[3]) * dsize[3] + (i4 - dir[4]) * dsize[4] +
                             (i5 - dir[5]) * dsize[5] + (i6 - dir[6]) * dsize[6] +
                             (i7 - dir[7]) * dsize[7] + (i8 - dir[8]) * dsize[8];

              if ( ffgcli(fptr, numcol, row, felem, nelem, ninc, nultyp,
                   nulval, &array[i0], &ldummy, &anyf, status) > 0)
                   return(*status);

              if (anyf && anynul)
                  *anynul = TRUE;

              i0 += nelem;
            }
           }
          }
         }
        }
       }
      }
     }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsfi(fitsfile *fptr, /* I - FITS file pointer                         */
           int  colnum,    /* I - number of the column to read (1 = 1st)    */
           int naxis,      /* I - number of dimensions in the FITS array    */
           long  *naxes,   /* I - size of each dimension                    */
           long  *blc,     /* I - 'bottom left corner' of the subsection    */
           long  *trc,     /* I - 'top right corner' of the subsection      */
           long  *inc,     /* I - increment to be applied in each dimension */
           short *array,   /* O - array to be filled and returned           */
           char *flagval,  /* O - set to 1 if corresponding value is null   */
           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
           int  *status)   /* IO - error status                             */
/*
  Read a subsection of data values from an image or a table column.
  This routine is set up to handle a maximum of nine dimensions.
*/
{
    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
    long str[9],stp[9],incr[9],dsize[10];
    LONGLONG blcll[9], trcll[9];
    long felem, nelem, nultyp, ninc, numcol;
    int hdutype, anyf;
    short nulval = 0;
    char msg[FLEN_ERRMSG];
    int nullcheck = 2;

    if (naxis < 1 || naxis > 9)
    {
        snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvi is out of range", naxis);
        ffpmsg(msg);
        return(*status = BAD_DIMEN);
    }

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        for (ii=0; ii < naxis; ii++) {
	    blcll[ii] = blc[ii];
	    trcll[ii] = trc[ii];
	}

        fits_read_compressed_img(fptr, TSHORT, blcll, trcll, inc,
            nullcheck, NULL, array, flagval, anynul, status);
        return(*status);
    }

/*
    if this is a primary array, then the input COLNUM parameter should
    be interpreted as the row number, and we will alway read the image
    data from column 2 (any group parameters are in column 1).
*/
    if (ffghdt(fptr, &hdutype, status) > 0)
        return(*status);

    if (hdutype == IMAGE_HDU)
    {
        /* this is a primary array, or image extension */
        if (colnum == 0)
        {
            rstr = 1;
            rstp = 1;
        }
        else
        {
            rstr = colnum;
            rstp = colnum;
        }
        rinc = 1;
        numcol = 2;
    }
    else
    {
        /* this is a table, so the row info is in the (naxis+1) elements */
        rstr = blc[naxis];
        rstp = trc[naxis];
        rinc = inc[naxis];
        numcol = colnum;
    }

    nultyp = 2;
    if (anynul)
        *anynul = FALSE;

    i0 = 0;
    for (ii = 0; ii < 9; ii++)
    {
        str[ii] = 1;
        stp[ii] = 1;
        incr[ii] = 1;
        dsize[ii] = 1;
    }

    for (ii = 0; ii < naxis; ii++)
    {
      if (trc[ii] < blc[ii])
      {
        snprintf(msg, FLEN_ERRMSG,"ffgsvi: illegal range specified for axis %ld", ii + 1);
        ffpmsg(msg);
        return(*status = BAD_PIX_NUM);
      }

      str[ii] = blc[ii];
      stp[ii] = trc[ii];
      incr[ii] = inc[ii];
      dsize[ii + 1] = dsize[ii] * naxes[ii];
    }

    if (naxis == 1 && naxes[0] == 1)
    {
      /* This is not a vector column, so read all the rows at once */
      nelem = (rstp - rstr) / rinc + 1;
      ninc = rinc;
      rstp = rstr;
    }
    else
    {
      /* have to read each row individually, in all dimensions */
      nelem = (stp[0] - str[0]) / inc[0] + 1;
      ninc = incr[0];
    }

    for (row = rstr; row <= rstp; row += rinc)
    {
     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
     {
      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
      {
       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
       {
        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
        {
         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
         {
          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
          {
           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
           {
            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
            {
              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];

              if ( ffgcli(fptr, numcol, row, felem, nelem, ninc, nultyp,
                   nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
                   return(*status);

              if (anyf && anynul)
                  *anynul = TRUE;

              i0 += nelem;
            }
           }
          }
         }
        }
       }
      }
     }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffggpi( fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            long  firstelem,  /* I - first vector element to read (1 = 1st)  */
            long  nelem,      /* I - number of values to read                */
            short *array,     /* O - array of values that are returned       */
            int  *status)     /* IO - error status                           */
/*
  Read an array of group parameters from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
*/
{
    long row;
    int idummy;
    char cdummy;
    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgcli(fptr, 1, row, firstelem, nelem, 1, 1, 0,
               array, &cdummy, &idummy, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcvi(fitsfile *fptr,   /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
           short nulval,     /* I - value for null pixels                   */
           short *array,     /* O - array of values that are read           */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Any undefined pixels will be set equal to the value of 'nulval' unless
  nulval = 0 in which case no checks for undefined pixels will be made.
*/
{
    char cdummy;

    ffgcli(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
           array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcfi(fitsfile *fptr,   /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
           short *array,     /* O - array of values that are read           */
           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Nularray will be set = 1 if the corresponding array pixel is undefined, 
  otherwise nularray will = 0.
*/
{
    short dummy = 0;

    ffgcli(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
           array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcli( fitsfile *fptr,   /* I - FITS file pointer                       */
            int  colnum,      /* I - number of column to read (1 = 1st col)  */
            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
            LONGLONG  firstelem, /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
            int   nultyp,     /* I - null value handling code:               */
                              /*     1: set undefined pixels = nulval        */
                              /*     2: set nularray=1 for undefined pixels  */
            short nulval,     /* I - value for null pixels if nultyp = 1     */
            short *array,     /* O - array of values that are read           */
            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU.
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer be a virtual column in a 1 or more grouped FITS primary
  array or image extension.  FITSIO treats a primary array as a binary table
  with 2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.

  The output array of values will be converted from the datatype of the column 
  and will be scaled by the FITS TSCALn and TZEROn values if necessary.
*/
{
    double scale, zero, power = 1., dtemp;
    int tcode, maxelem2, hdutype, xcode, decimals;
    long twidth, incre;
    long ii, xwidth, ntodo;
    int convert, nulcheck, readcheck = 0;
    LONGLONG repeat, startpos, elemnum, readptr, tnull;
    LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
    char tform[20];
    char message[FLEN_ERRMSG];
    char snull[20];   /*  the FITS null value if reading from ASCII table  */

    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
    void *buffer;

    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
        return(*status);

    buffer = cbuff;

    if (anynul)
        *anynul = 0;

    if (nultyp == 2)
        memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if (elemincre < 0)
        readcheck = -1;  /* don't do range checking in this case */

    if ( ffgcprll( fptr, colnum, firstrow, firstelem, nelem, readcheck, &scale, &zero,
         tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
         return(*status);
    maxelem = maxelem2;

    incre *= elemincre;   /* multiply incre to just get every nth pixel */

    if (tcode == TSTRING)    /* setup for ASCII tables */
    {
      /* get the number of implied decimal places if no explicit decmal point */
      ffasfm(tform, &xcode, &xwidth, &decimals, status); 
      for(ii = 0; ii < decimals; ii++)
        power *= 10.;
    }
    /*------------------------------------------------------------------*/
    /*  Decide whether to check for null values in the input FITS file: */
    /*------------------------------------------------------------------*/
    nulcheck = nultyp; /* by default check for null values in the FITS file */

    if (nultyp == 1 && nulval == 0)
       nulcheck = 0;    /* calling routine does not want to check for nulls */

    else if (tcode%10 == 1 &&        /* if reading an integer column, and  */ 
            tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
            nulcheck = 0;            /* then do not check for null values. */

    else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
            nulcheck = 0;            /* Impossible null value */

    else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
            nulcheck = 0;            /* Impossible null value */

    else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
         nulcheck = 0;

    /*----------------------------------------------------------------------*/
    /*  If FITS column and output data array have same datatype, then we do */
    /*  not need to use a temporary buffer to store intermediate datatype.  */
    /*----------------------------------------------------------------------*/
    convert = 1;
    if (tcode == TSHORT) /* Special Case:                        */
    {                             /* no type convertion required, so read */
                                  /* data directly into output buffer.    */

        if (nelem < (LONGLONG)INT32_MAX/2) {
            maxelem = nelem;
        } else {
            maxelem = INT32_MAX/2;
        }

        if (nulcheck == 0 && scale == 1. && zero == 0.)
            convert = 0;  /* no need to scale data or find nulls */
    }

    /*---------------------------------------------------------------------*/
    /*  Now read the pixels from the FITS column. If the column does not   */
    /*  have the same datatype as the output array, then we have to read   */
    /*  the raw values into a temporary buffer (of limited size).  In      */
    /*  the case of a vector colum read only 1 vector of values at a time  */
    /*  then skip to the next row if more values need to be read.          */
    /*  After reading the raw values, then call the fffXXYY routine to (1) */
    /*  test for undefined values, (2) convert the datatype if necessary,  */
    /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
    /*  scaling parameters.                                                */
    /*---------------------------------------------------------------------*/
    remain = nelem;           /* remaining number of values to read */
    next = 0;                 /* next element in array to be read   */
    rownum = 0;               /* row number, relative to firstrow   */

    while (remain)
    {
        /* limit the number of pixels to read at one time to the number that
           will fit in the buffer or to the number of pixels that remain in
           the current vector, which ever is smaller.
        */
        ntodo = (long) minvalue(remain, maxelem);
        if (elemincre >= 0)
        {
          ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));
        }
        else
        {
          ntodo = (long) minvalue(ntodo, (elemnum/(-elemincre) +1));
        }

        readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));

        switch (tcode) 
        {
            case (TSHORT):
                ffgi2b(fptr, readptr, ntodo, incre, &array[next], status);
                if (convert)
                    fffi2i2(&array[next], ntodo, scale, zero, nulcheck, 
                           (short) tnull, nulval, &nularray[next], anynul, 
                           &array[next], status);
                break;
            case (TLONGLONG):

                ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status);
                fffi8i2( (LONGLONG *) buffer, ntodo, scale, zero, 
                           nulcheck, tnull, nulval, &nularray[next], 
                            anynul, &array[next], status);
                break;
            case (TBYTE):
                ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer,
                      status);
                fffi1i2((unsigned char *) buffer, ntodo, scale, zero, nulcheck, 
                    (unsigned char) tnull, nulval, &nularray[next], anynul, 
                    &array[next], status);
                break;
            case (TLONG):
                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer,
                       status);
                fffi4i2((INT32BIT *) buffer, ntodo, scale, zero, nulcheck, 
                       (INT32BIT) tnull, nulval, &nularray[next], anynul, 
                       &array[next], status);
                break;
            case (TFLOAT):
                ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
                fffr4i2((float  *) buffer, ntodo, scale, zero, nulcheck, 
                       nulval, &nularray[next], anynul, 
                       &array[next], status);
                break;
            case (TDOUBLE):
                ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
                fffr8i2((double *) buffer, ntodo, scale, zero, nulcheck, 
                          nulval, &nularray[next], anynul, 
                          &array[next], status);
                break;
            case (TSTRING):
                ffmbyt(fptr, readptr, REPORT_EOF, status);
       
                if (incre == twidth)    /* contiguous bytes */
                     ffgbyt(fptr, ntodo * twidth, buffer, status);
                else
                     ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
                               status);

                fffstri2((char *) buffer, ntodo, scale, zero, twidth, power,
                     nulcheck, snull, nulval, &nularray[next], anynul,
                     &array[next], status);
                break;

            default:  /*  error trap for invalid column format */
                snprintf(message, FLEN_ERRMSG,
                   "Cannot read numbers from column %d which has format %s",
                    colnum, tform);
                ffpmsg(message);
                if (hdutype == ASCII_TBL)
                    return(*status = BAD_ATABLE_FORMAT);
                else
                    return(*status = BAD_BTABLE_FORMAT);

        } /* End of switch block */

        /*-------------------------*/
        /*  Check for fatal error  */
        /*-------------------------*/
        if (*status > 0)  /* test for error during previous read operation */
        {
	  dtemp = (double) next;
          if (hdutype > 0)
            snprintf(message,FLEN_ERRMSG,
            "Error reading elements %.0f thru %.0f from column %d (ffgcli).",
              dtemp+1, dtemp+ntodo, colnum);
          else
            snprintf(message,FLEN_ERRMSG,
            "Error reading elements %.0f thru %.0f from image (ffgcli).",
              dtemp+1, dtemp+ntodo);

          ffpmsg(message);
          return(*status);
        }

        /*--------------------------------------------*/
        /*  increment the counters for the next loop  */
        /*--------------------------------------------*/
        remain -= ntodo;
        if (remain)
        {
            next += ntodo;
            elemnum = elemnum + (ntodo * elemincre);

            if (elemnum >= repeat)  /* completed a row; start on later row */
            {
                rowincre = elemnum / repeat;
                rownum += rowincre;
                elemnum = elemnum - (rowincre * repeat);
            }
            else if (elemnum < 0) /* completed a row; start on a previous row */
            {
                rowincre = (-elemnum - 1) / repeat + 1;
                rownum -= rowincre;
                elemnum = (rowincre * repeat) + elemnum;
            }
        }
    }  /*  End of main while Loop  */


    /*--------------------------------*/
    /*  check for numerical overflow  */
    /*--------------------------------*/
    if (*status == OVERFLOW_ERR)
    {
        ffpmsg(
        "Numerical overflow during type conversion while reading FITS data.");
        *status = NUM_OVERFLOW;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi1i2(unsigned char *input, /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
            short nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            short *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
                output[ii] = (short) input[ii];  /* copy input to output */
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DSHRT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MIN;
                }
                else if (dvalue > DSHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MAX;
                }
                else
                    output[ii] = (short) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = (short) input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MIN;
                    }
                    else if (dvalue > DSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MAX;
                    }
                    else
                        output[ii] = (short) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi2i2(short *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            short tnull,          /* I - value of FITS TNULLn keyword if any */
            short nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            short *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            memmove(output, input, ntodo * sizeof(short) );
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DSHRT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MIN;
                }
                else if (dvalue > DSHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MAX;
                }
                else
                    output[ii] = (short) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MIN;
                    }
                    else if (dvalue > DSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MAX;
                    }
                    else
                        output[ii] = (short) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi4i2(INT32BIT *input,      /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
            short nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            short *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < SHRT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MIN;
                }
                else if (input[ii] > SHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MAX;
                }
                else
                    output[ii] = (short) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DSHRT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MIN;
                }
                else if (dvalue > DSHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MAX;
                }
                else
                    output[ii] = (short) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    if (input[ii] < SHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MIN;
                    }
                    else if (input[ii] > SHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MAX;
                    }
                    else
                        output[ii] = (short) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MIN;
                    }
                    else if (dvalue > DSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MAX;
                    }
                    else
                        output[ii] = (short) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi8i2(LONGLONG *input,      /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
            short nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            short *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < SHRT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MIN;
                }
                else if (input[ii] > SHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MAX;
                }
                else
                    output[ii] = (short) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DSHRT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MIN;
                }
                else if (dvalue > DSHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MAX;
                }
                else
                    output[ii] = (short) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    if (input[ii] < SHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MIN;
                    }
                    else if (input[ii] > SHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MAX;
                    }
                    else
                        output[ii] = (short) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MIN;
                    }
                    else if (dvalue > DSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MAX;
                    }
                    else
                        output[ii] = (short) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffr4i2(float *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            short nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            short *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to NaN.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;
    short *sptr, iret;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < DSHRT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MIN;
                }
                else if (input[ii] > DSHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MAX;
                }
                else
                    output[ii] = (short) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DSHRT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MIN;
                }
                else if (dvalue > DSHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MAX;
                }
                else
                    output[ii] = (short) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        sptr = (short *) input;

#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
        sptr++;       /* point to MSBs */
#endif

        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++, sptr += 2)
            {
              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                     output[ii] = 0;
              }
              else
                {
                    if (input[ii] < DSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MIN;
                    }
                    else if (input[ii] > DSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MAX;
                    }
                    else
                        output[ii] = (short) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++, sptr += 2)
            {
              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {  
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                  {
                    if (zero < DSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MIN;
                    }
                    else if (zero > DSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MAX;
                    }
                    else
                        output[ii] = (short) zero;
                  }
              }
              else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MIN;
                    }
                    else if (dvalue > DSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MAX;
                    }
                    else
                        output[ii] = (short) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffr8i2(double *input,        /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            short nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            short *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to NaN.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;
    short *sptr, iret;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < DSHRT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MIN;
                }
                else if (input[ii] > DSHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MAX;
                }
                else
                    output[ii] = (short) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DSHRT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MIN;
                }
                else if (dvalue > DSHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = SHRT_MAX;
                }
                else
                    output[ii] = (short) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        sptr = (short *) input;

#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
        sptr += 3;       /* point to MSBs */
#endif
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++, sptr += 4)
            {
              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                     output[ii] = 0;
              }
              else
                {
                    if (input[ii] < DSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MIN;
                    }
                    else if (input[ii] > DSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MAX;
                    }
                    else
                        output[ii] = (short) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++, sptr += 4)
            {
              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {  
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                  {
                    if (zero < DSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MIN;
                    }
                    else if (zero > DSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MAX;
                    }
                    else
                        output[ii] = (short) zero;
                  }
              }
              else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MIN;
                    }
                    else if (dvalue > DSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = SHRT_MAX;
                    }
                    else
                        output[ii] = (short) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffstri2(char *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            long twidth,          /* I - width of each substring of chars    */
            double implipower,    /* I - power of 10 of implied decimal      */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            char  *snull,         /* I - value of FITS null string, if any   */
            short nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            short *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file. Check
  for null values and do scaling if required. The nullcheck code value
  determines how any null values in the input array are treated. A null
  value is an input pixel that is equal to snull.  If nullcheck= 0, then
  no special checking for nulls is performed.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    int nullen;
    long ii;
    double dvalue;
    char *cstring, message[FLEN_ERRMSG];
    char *cptr, *tpos;
    char tempstore, chrzero = '0';
    double val, power;
    int exponent, sign, esign, decpt;

    nullen = strlen(snull);
    cptr = input;  /* pointer to start of input string */
    for (ii = 0; ii < ntodo; ii++)
    {
      cstring = cptr;
      /* temporarily insert a null terminator at end of the string */
      tpos = cptr + twidth;
      tempstore = *tpos;
      *tpos = 0;

      /* check if null value is defined, and if the    */
      /* column string is identical to the null string */
      if (snull[0] != ASCII_NULL_UNDEFINED && 
         !strncmp(snull, cptr, nullen) )
      {
        if (nullcheck)  
        {
          *anynull = 1;    
          if (nullcheck == 1)
            output[ii] = nullval;
          else
            nullarray[ii] = 1;
        }
        cptr += twidth;
      }
      else
      {
        /* value is not the null value, so decode it */
        /* remove any embedded blank characters from the string */

        decpt = 0;
        sign = 1;
        val  = 0.;
        power = 1.;
        exponent = 0;
        esign = 1;

        while (*cptr == ' ')               /* skip leading blanks */
           cptr++;

        if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
        {
          if (*cptr == '-')
             sign = -1;

          cptr++;

          while (*cptr == ' ')         /* skip blanks between sign and value */
            cptr++;
        }

        while (*cptr >= '0' && *cptr <= '9')
        {
          val = val * 10. + *cptr - chrzero;  /* accumulate the value */
          cptr++;

          while (*cptr == ' ')         /* skip embedded blanks in the value */
            cptr++;
        }

        if (*cptr == '.' || *cptr == ',')       /* check for decimal point */
        {
          decpt = 1;       /* set flag to show there was a decimal point */
          cptr++;
          while (*cptr == ' ')         /* skip any blanks */
            cptr++;

          while (*cptr >= '0' && *cptr <= '9')
          {
            val = val * 10. + *cptr - chrzero;  /* accumulate the value */
            power = power * 10.;
            cptr++;

            while (*cptr == ' ')         /* skip embedded blanks in the value */
              cptr++;
          }
        }

        if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
        {
          cptr++;
          while (*cptr == ' ')         /* skip blanks */
              cptr++;
  
          if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
          {
            if (*cptr == '-')
               esign = -1;

            cptr++;

            while (*cptr == ' ')        /* skip blanks between sign and exp */
              cptr++;
          }

          while (*cptr >= '0' && *cptr <= '9')
          {
            exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
            cptr++;

            while (*cptr == ' ')         /* skip embedded blanks */
              cptr++;
          }
        }

        if (*cptr  != 0)  /* should end up at the null terminator */
        {
          snprintf(message, FLEN_ERRMSG,"Cannot read number from ASCII table");
          ffpmsg(message);
          snprintf(message, FLEN_ERRMSG,"Column field = %s.", cstring);
          ffpmsg(message);
          /* restore the char that was overwritten by the null */
          *tpos = tempstore;
          return(*status = BAD_C2D);
        }

        if (!decpt)  /* if no explicit decimal, use implied */
           power = implipower;

        dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));

        dvalue = dvalue * scale + zero;   /* apply the scaling */

        if (dvalue < DSHRT_MIN)
        {
            *status = OVERFLOW_ERR;
            output[ii] = SHRT_MIN;
        }
        else if (dvalue > DSHRT_MAX)
        {
            *status = OVERFLOW_ERR;
            output[ii] = SHRT_MAX;
        }
        else
            output[ii] = (short) dvalue;
      }
      /* restore the char that was overwritten by the null */
      *tpos = tempstore;
    }
    return(*status);
}
cfitsio/getcolj.c0000644000225700000360000043227413246025103013607 0ustar  cagordonlhea/*  This file, getcolj.c, contains routines that read data elements from   */
/*  a FITS image or table, with long data type.                            */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include 
#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int ffgpvj( fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            long  nulval,     /* I - value for undefined pixels              */
            long  *array,     /* O - array of values that are returned       */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Undefined elements will be set equal to NULVAL, unless NULVAL=0
  in which case no checking for undefined values will be performed.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    long row;
    char cdummy;
    int nullcheck = 1;
    long nullvalue;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */
         nullvalue = nulval;  /* set local variable */

        fits_read_compressed_pixels(fptr, TLONG, firstelem, nelem,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgclj(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
               array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgpfj( fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            long  *array,     /* O - array of values that are returned       */
            char *nularray,   /* O - array of null pixel flags               */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Any undefined pixels in the returned array will be set = 0 and the 
  corresponding nularray value will be set = 1.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    long row;
    int nullcheck = 2;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_read_compressed_pixels(fptr, TLONG, firstelem, nelem,
            nullcheck, NULL, array, nularray, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgclj(fptr, 2, row, firstelem, nelem, 1, 2, 0L,
               array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffg2dj(fitsfile *fptr,  /* I - FITS file pointer                       */
           long  group,     /* I - group to read (1 = 1st group)           */
           long  nulval,    /* set undefined pixels equal to this          */
           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
           long  *array,    /* O - array to be filled and returned         */
           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
           int  *status)    /* IO - error status                           */
/*
  Read an entire 2-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being read).  Any null
  values in the array will be set equal to the value of nulval, unless
  nulval = 0 in which case no null checking will be performed.
*/
{
    /* call the 3D reading routine, with the 3rd dimension = 1 */

    ffg3dj(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, 
           anynul, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffg3dj(fitsfile *fptr,  /* I - FITS file pointer                       */
           long  group,     /* I - group to read (1 = 1st group)           */
           long  nulval,    /* set undefined pixels equal to this          */
           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
           LONGLONG  nrows,     /* I - number of rows in each plane of array   */
           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
           LONGLONG  naxis3,    /* I - FITS image NAXIS3 value                 */
           long  *array,    /* O - array to be filled and returned         */
           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
           int  *status)    /* IO - error status                           */
/*
  Read an entire 3-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being read).  Any null
  values in the array will be set equal to the value of nulval, unless
  nulval = 0 in which case no null checking will be performed.
*/
{
    long tablerow, ii, jj;
    char cdummy;
    int nullcheck = 1;
    long inc[] = {1,1,1};
    LONGLONG fpixel[] = {1,1,1}, nfits, narray;
    LONGLONG lpixel[3], nullvalue;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        lpixel[0] = ncols;
        lpixel[1] = nrows;
        lpixel[2] = naxis3;
        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_img(fptr, TLONG, fpixel, lpixel, inc,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */
    tablerow=maxvalue(1,group);

    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
    {
       /* all the image pixels are contiguous, so read all at once */
       ffgclj(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval,
               array, &cdummy, anynul, status);
       return(*status);
    }

    if (ncols < naxis1 || nrows < naxis2)
       return(*status = BAD_DIMEN);

    nfits = 1;   /* next pixel in FITS image to read */
    narray = 0;  /* next pixel in output array to be filled */

    /* loop over naxis3 planes in the data cube */
    for (jj = 0; jj < naxis3; jj++)
    {
      /* loop over the naxis2 rows in the FITS image, */
      /* reading naxis1 pixels to each row            */

      for (ii = 0; ii < naxis2; ii++)
      {
       if (ffgclj(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval,
          &array[narray], &cdummy, anynul, status) > 0)
          return(*status);

       nfits += naxis1;
       narray += ncols;
      }
      narray += (nrows - naxis2) * ncols;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsvj(fitsfile *fptr, /* I - FITS file pointer                         */
           int  colnum,    /* I - number of the column to read (1 = 1st)    */
           int naxis,      /* I - number of dimensions in the FITS array    */
           long  *naxes,   /* I - size of each dimension                    */
           long  *blc,     /* I - 'bottom left corner' of the subsection    */
           long  *trc,     /* I - 'top right corner' of the subsection      */
           long  *inc,     /* I - increment to be applied in each dimension */
           long nulval,    /* I - value to set undefined pixels             */
           long *array,    /* O - array to be filled and returned           */
           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
           int  *status)   /* IO - error status                             */
/*
  Read a subsection of data values from an image or a table column.
  This routine is set up to handle a maximum of nine dimensions.
*/
{
    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
    long str[9],stp[9],incr[9],dir[9];
    long nelem, nultyp, ninc, numcol;
    LONGLONG felem, dsize[10], blcll[9], trcll[9];
    int hdutype, anyf;
    char ldummy, msg[FLEN_ERRMSG];
    int nullcheck = 1;
    long nullvalue;

    if (naxis < 1 || naxis > 9)
    {
        snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvj is out of range", naxis);
        ffpmsg(msg);
        return(*status = BAD_DIMEN);
    }

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        for (ii=0; ii < naxis; ii++) {
	    blcll[ii] = blc[ii];
	    trcll[ii] = trc[ii];
	}

        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_img(fptr, TLONG, blcll, trcll, inc,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

/*
    if this is a primary array, then the input COLNUM parameter should
    be interpreted as the row number, and we will alway read the image
    data from column 2 (any group parameters are in column 1).
*/
    if (ffghdt(fptr, &hdutype, status) > 0)
        return(*status);

    if (hdutype == IMAGE_HDU)
    {
        /* this is a primary array, or image extension */
        if (colnum == 0)
        {
            rstr = 1;
            rstp = 1;
        }
        else
        {
            rstr = colnum;
            rstp = colnum;
        }
        rinc = 1;
        numcol = 2;
    }
    else
    {
        /* this is a table, so the row info is in the (naxis+1) elements */
        rstr = blc[naxis];
        rstp = trc[naxis];
        rinc = inc[naxis];
        numcol = colnum;
    }

    nultyp = 1;
    if (anynul)
        *anynul = FALSE;

    i0 = 0;
    for (ii = 0; ii < 9; ii++)
    {
        str[ii] = 1;
        stp[ii] = 1;
        incr[ii] = 1;
        dsize[ii] = 1;
        dir[ii] = 1;
    }

    for (ii = 0; ii < naxis; ii++)
    {
      if (trc[ii] < blc[ii])
      {
        if (hdutype == IMAGE_HDU)
        {
           dir[ii] = -1;
        }
        else
        {
          snprintf(msg, FLEN_ERRMSG,"ffgsvj: illegal range specified for axis %ld", ii + 1);
          ffpmsg(msg);
          return(*status = BAD_PIX_NUM);
        }
      }

      str[ii] = blc[ii];
      stp[ii] = trc[ii];
      incr[ii] = inc[ii];
      dsize[ii + 1] = dsize[ii] * naxes[ii];
      dsize[ii] = dsize[ii] * dir[ii];
    }
    dsize[naxis] = dsize[naxis] * dir[naxis];

    if (naxis == 1 && naxes[0] == 1)
    {
      /* This is not a vector column, so read all the rows at once */
      nelem = (rstp - rstr) / rinc + 1;
      ninc = rinc;
      rstp = rstr;
    }
    else
    {
      /* have to read each row individually, in all dimensions */
      nelem = (stp[0]*dir[0] - str[0]*dir[0]) / inc[0] + 1;
      ninc = incr[0] * dir[0];
    }

    for (row = rstr; row <= rstp; row += rinc)
    {
     for (i8 = str[8]*dir[8]; i8 <= stp[8]*dir[8]; i8 += incr[8])
     {
      for (i7 = str[7]*dir[7]; i7 <= stp[7]*dir[7]; i7 += incr[7])
      {
       for (i6 = str[6]*dir[6]; i6 <= stp[6]*dir[6]; i6 += incr[6])
       {
        for (i5 = str[5]*dir[5]; i5 <= stp[5]*dir[5]; i5 += incr[5])
        {
         for (i4 = str[4]*dir[4]; i4 <= stp[4]*dir[4]; i4 += incr[4])
         {
          for (i3 = str[3]*dir[3]; i3 <= stp[3]*dir[3]; i3 += incr[3])
          {
           for (i2 = str[2]*dir[2]; i2 <= stp[2]*dir[2]; i2 += incr[2])
           {
            for (i1 = str[1]*dir[1]; i1 <= stp[1]*dir[1]; i1 += incr[1])
            {

              felem=str[0] + (i1 - dir[1]) * dsize[1] + (i2 - dir[2]) * dsize[2] + 
                             (i3 - dir[3]) * dsize[3] + (i4 - dir[4]) * dsize[4] +
                             (i5 - dir[5]) * dsize[5] + (i6 - dir[6]) * dsize[6] +
                             (i7 - dir[7]) * dsize[7] + (i8 - dir[8]) * dsize[8];

              if ( ffgclj(fptr, numcol, row, felem, nelem, ninc, nultyp,
                   nulval, &array[i0], &ldummy, &anyf, status) > 0)
                   return(*status);

              if (anyf && anynul)
                  *anynul = TRUE;

              i0 += nelem;
            }
           }
          }
         }
        }
       }
      }
     }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsfj(fitsfile *fptr, /* I - FITS file pointer                         */
           int  colnum,    /* I - number of the column to read (1 = 1st)    */
           int naxis,      /* I - number of dimensions in the FITS array    */
           long  *naxes,   /* I - size of each dimension                    */
           long  *blc,     /* I - 'bottom left corner' of the subsection    */
           long  *trc,     /* I - 'top right corner' of the subsection      */
           long  *inc,     /* I - increment to be applied in each dimension */
           long *array,    /* O - array to be filled and returned           */
           char *flagval,  /* O - set to 1 if corresponding value is null   */
           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
           int  *status)   /* IO - error status                             */
/*
  Read a subsection of data values from an image or a table column.
  This routine is set up to handle a maximum of nine dimensions.
*/
{
    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
    long str[9],stp[9],incr[9],dsize[10];
    LONGLONG blcll[9], trcll[9];
    long felem, nelem, nultyp, ninc, numcol;
    long nulval = 0;
    int hdutype, anyf;
    char msg[FLEN_ERRMSG];
    int nullcheck = 2;

    if (naxis < 1 || naxis > 9)
    {
        snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvj is out of range", naxis);
        ffpmsg(msg);
        return(*status = BAD_DIMEN);
    }

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        for (ii=0; ii < naxis; ii++) {
	    blcll[ii] = blc[ii];
	    trcll[ii] = trc[ii];
	}

        fits_read_compressed_img(fptr, TLONG, blcll, trcll, inc,
            nullcheck, NULL, array, flagval, anynul, status);
        return(*status);
    }

/*
    if this is a primary array, then the input COLNUM parameter should
    be interpreted as the row number, and we will alway read the image
    data from column 2 (any group parameters are in column 1).
*/
    if (ffghdt(fptr, &hdutype, status) > 0)
        return(*status);

    if (hdutype == IMAGE_HDU)
    {
        /* this is a primary array, or image extension */
        if (colnum == 0)
        {
            rstr = 1;
            rstp = 1;
        }
        else
        {
            rstr = colnum;
            rstp = colnum;
        }
        rinc = 1;
        numcol = 2;
    }
    else
    {
        /* this is a table, so the row info is in the (naxis+1) elements */
        rstr = blc[naxis];
        rstp = trc[naxis];
        rinc = inc[naxis];
        numcol = colnum;
    }

    nultyp = 2;
    if (anynul)
        *anynul = FALSE;

    i0 = 0;
    for (ii = 0; ii < 9; ii++)
    {
        str[ii] = 1;
        stp[ii] = 1;
        incr[ii] = 1;
        dsize[ii] = 1;
    }

    for (ii = 0; ii < naxis; ii++)
    {
      if (trc[ii] < blc[ii])
      {
        snprintf(msg, FLEN_ERRMSG,"ffgsvj: illegal range specified for axis %ld", ii + 1);
        ffpmsg(msg);
        return(*status = BAD_PIX_NUM);
      }

      str[ii] = blc[ii];
      stp[ii] = trc[ii];
      incr[ii] = inc[ii];
      dsize[ii + 1] = dsize[ii] * naxes[ii];
    }

    if (naxis == 1 && naxes[0] == 1)
    {
      /* This is not a vector column, so read all the rows at once */
      nelem = (rstp - rstr) / rinc + 1;
      ninc = rinc;
      rstp = rstr;
    }
    else
    {
      /* have to read each row individually, in all dimensions */
      nelem = (stp[0] - str[0]) / inc[0] + 1;
      ninc = incr[0];
    }

    for (row = rstr; row <= rstp; row += rinc)
    {
     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
     {
      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
      {
       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
       {
        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
        {
         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
         {
          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
          {
           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
           {
            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
            {
              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];

              if ( ffgclj(fptr, numcol, row, felem, nelem, ninc, nultyp,
                   nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
                   return(*status);

              if (anyf && anynul)
                  *anynul = TRUE;

              i0 += nelem;
            }
           }
          }
         }
        }
       }
      }
     }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffggpj( fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            long  firstelem,  /* I - first vector element to read (1 = 1st)  */
            long  nelem,      /* I - number of values to read                */
            long  *array,     /* O - array of values that are returned       */
            int  *status)     /* IO - error status                           */
/*
  Read an array of group parameters from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
*/
{
    long row;
    int idummy;
    char cdummy;
    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgclj(fptr, 1, row, firstelem, nelem, 1, 1, 0L,
               array, &cdummy, &idummy, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcvj(fitsfile *fptr,   /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
           long  nulval,     /* I - value for null pixels                   */
           long *array,      /* O - array of values that are read           */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Any undefined pixels will be set equal to the value of 'nulval' unless
  nulval = 0 in which case no checks for undefined pixels will be made.
*/
{
    char cdummy;

    ffgclj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
           array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcfj(fitsfile *fptr,   /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
           long  *array,     /* O - array of values that are read           */
           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Nularray will be set = 1 if the corresponding array pixel is undefined, 
  otherwise nularray will = 0.
*/
{
    long dummy = 0;

    ffgclj(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
           array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgclj( fitsfile *fptr,   /* I - FITS file pointer                       */
            int  colnum,      /* I - number of column to read (1 = 1st col)  */
            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
            LONGLONG firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
            int   nultyp,     /* I - null value handling code:               */
                              /*     1: set undefined pixels = nulval        */
                              /*     2: set nularray=1 for undefined pixels  */
            long  nulval,     /* I - value for null pixels if nultyp = 1     */
            long  *array,     /* O - array of values that are read           */
            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU.
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer be a virtual column in a 1 or more grouped FITS primary
  array or image extension.  FITSIO treats a primary array as a binary table
  with 2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.

  The output array of values will be converted from the datatype of the column 
  and will be scaled by the FITS TSCALn and TZEROn values if necessary.
*/
{
    double scale, zero, power = 1., dtemp;
    int tcode, maxelem2, hdutype, xcode, decimals;
    long twidth, incre;
    long ii, xwidth, ntodo;
    int convert, nulcheck, readcheck = 0;
    LONGLONG repeat, startpos, elemnum, readptr, tnull;
    LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
    char tform[20];
    char message[FLEN_ERRMSG];
    char snull[20];   /*  the FITS null value if reading from ASCII table  */

    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
    void *buffer;

    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
        return(*status);

    buffer = cbuff;

    if (anynul)
        *anynul = 0;

    if (nultyp == 2)
        memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if (elemincre < 0)
        readcheck = -1;  /* don't do range checking in this case */

    if (ffgcprll(fptr, colnum, firstrow, firstelem, nelem, readcheck, &scale, &zero,
         tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
         return(*status);
    maxelem = maxelem2;

    incre *= elemincre;   /* multiply incre to just get every nth pixel */

    if (tcode == TSTRING)    /* setup for ASCII tables */
    {
      /* get the number of implied decimal places if no explicit decmal point */
      ffasfm(tform, &xcode, &xwidth, &decimals, status); 
      for(ii = 0; ii < decimals; ii++)
        power *= 10.;
    }
    /*------------------------------------------------------------------*/
    /*  Decide whether to check for null values in the input FITS file: */
    /*------------------------------------------------------------------*/
    nulcheck = nultyp; /* by default check for null values in the FITS file */

    if (nultyp == 1 && nulval == 0)
       nulcheck = 0;    /* calling routine does not want to check for nulls */

    else if (tcode%10 == 1 &&        /* if reading an integer column, and  */ 
            tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
            nulcheck = 0;            /* then do not check for null values. */

    else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
            nulcheck = 0;            /* Impossible null value */

    else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
            nulcheck = 0;            /* Impossible null value */

    else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
         nulcheck = 0;

    /*----------------------------------------------------------------------*/
    /*  If FITS column and output data array have same datatype, then we do */
    /*  not need to use a temporary buffer to store intermediate datatype.  */
    /*----------------------------------------------------------------------*/
    convert = 1;
    if ((tcode == TLONG) && (LONGSIZE == 32))  /* Special Case:                        */
    {                             /* no type convertion required, so read */
                                  /* data directly into output buffer.    */

        if (nelem < (LONGLONG)INT32_MAX/4) {
            maxelem = nelem;
        } else {
            maxelem = INT32_MAX/4;   
        }

        if (nulcheck == 0 && scale == 1. && zero == 0. )
            convert = 0;  /* no need to scale data or find nulls */
    }

    /*---------------------------------------------------------------------*/
    /*  Now read the pixels from the FITS column. If the column does not   */
    /*  have the same datatype as the output array, then we have to read   */
    /*  the raw values into a temporary buffer (of limited size).  In      */
    /*  the case of a vector colum read only 1 vector of values at a time  */
    /*  then skip to the next row if more values need to be read.          */
    /*  After reading the raw values, then call the fffXXYY routine to (1) */
    /*  test for undefined values, (2) convert the datatype if necessary,  */
    /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
    /*  scaling parameters.                                                */
    /*---------------------------------------------------------------------*/
    remain = nelem;           /* remaining number of values to read */
    next = 0;                 /* next element in array to be read   */
    rownum = 0;               /* row number, relative to firstrow   */

    while (remain)
    {
        /* limit the number of pixels to read at one time to the number that
           will fit in the buffer or to the number of pixels that remain in
           the current vector, which ever is smaller.
        */
        ntodo = (long) minvalue(remain, maxelem);
        if (elemincre >= 0)
        {
          ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));
        }
        else
        {
          ntodo = (long) minvalue(ntodo, (elemnum/(-elemincre) +1));
        }

        readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));

        switch (tcode) 
        {
            case (TLONG):
	      if (LONGSIZE == 32) {
                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) &array[next],
                       status);
                if (convert)
                    fffi4i4((INT32BIT *) &array[next], ntodo, scale, zero, 
                           nulcheck, (INT32BIT) tnull, nulval, &nularray[next], 
                            anynul, &array[next], status);
	      } else { /* case where sizeof(long) = 8 */
                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer,
                       status);
                if (convert)
                    fffi4i4((INT32BIT *) buffer, ntodo, scale, zero, 
                           nulcheck, (INT32BIT) tnull, nulval, &nularray[next], 
                            anynul, &array[next], status);
	      }

                break;
            case (TLONGLONG):
                ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status);
                fffi8i4((LONGLONG *) buffer, ntodo, scale, zero, 
                           nulcheck, tnull, nulval, &nularray[next], 
                            anynul, &array[next], status);
                break;
            case (TBYTE):
                ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer,
                       status);
                fffi1i4((unsigned char *) buffer, ntodo, scale, zero, nulcheck, 
                     (unsigned char) tnull, nulval, &nularray[next], anynul, 
                     &array[next], status);
                break;
            case (TSHORT):
                ffgi2b(fptr, readptr, ntodo, incre, (short  *) buffer, status);
                fffi2i4((short  *) buffer, ntodo, scale, zero, nulcheck, 
                      (short) tnull, nulval, &nularray[next], anynul, 
                      &array[next], status);
                break;
            case (TFLOAT):
                ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
                fffr4i4((float  *) buffer, ntodo, scale, zero, nulcheck, 
                       nulval, &nularray[next], anynul, 
                       &array[next], status);
                break;
            case (TDOUBLE):
                ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
                fffr8i4((double *) buffer, ntodo, scale, zero, nulcheck, 
                          nulval, &nularray[next], anynul, 
                          &array[next], status);
                break;
            case (TSTRING):
                ffmbyt(fptr, readptr, REPORT_EOF, status);
       
                if (incre == twidth)    /* contiguous bytes */
                     ffgbyt(fptr, ntodo * twidth, buffer, status);
                else
                     ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
                               status);

                fffstri4((char *) buffer, ntodo, scale, zero, twidth, power,
                     nulcheck, snull, nulval, &nularray[next], anynul,
                     &array[next], status);
                break;

            default:  /*  error trap for invalid column format */
                snprintf(message, FLEN_ERRMSG,
                   "Cannot read numbers from column %d which has format %s",
                    colnum, tform);
                ffpmsg(message);
                if (hdutype == ASCII_TBL)
                    return(*status = BAD_ATABLE_FORMAT);
                else
                    return(*status = BAD_BTABLE_FORMAT);

        } /* End of switch block */

        /*-------------------------*/
        /*  Check for fatal error  */
        /*-------------------------*/
        if (*status > 0)  /* test for error during previous read operation */
        {
	  dtemp = (double) next;
          if (hdutype > 0)
            snprintf(message,FLEN_ERRMSG,
            "Error reading elements %.0f thru %.0f from column %d (ffgclj).",
              dtemp+1., dtemp+ntodo, colnum);
          else
            snprintf(message,FLEN_ERRMSG,
            "Error reading elements %.0f thru %.0f from image (ffgclj).",
              dtemp+1., dtemp+ntodo);

          ffpmsg(message);
          return(*status);
        }

        /*--------------------------------------------*/
        /*  increment the counters for the next loop  */
        /*--------------------------------------------*/
        remain -= ntodo;
        if (remain)
        {
            next += ntodo;
            elemnum = elemnum + (ntodo * elemincre);

            if (elemnum >= repeat)  /* completed a row; start on later row */
            {
                rowincre = elemnum / repeat;
                rownum += rowincre;
                elemnum = elemnum - (rowincre * repeat);
            }
            else if (elemnum < 0)  /* completed a row; start on a previous row */
            {
                rowincre = (-elemnum - 1) / repeat + 1;
                rownum -= rowincre;
                elemnum = (rowincre * repeat) + elemnum;
            }
        }
    }  /*  End of main while Loop  */


    /*--------------------------------*/
    /*  check for numerical overflow  */
    /*--------------------------------*/
    if (*status == OVERFLOW_ERR)
    {
        ffpmsg(
        "Numerical overflow during type conversion while reading FITS data.");
        *status = NUM_OVERFLOW;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi1i4(unsigned char *input, /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
            long nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            long *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
                output[ii] = (long) input[ii];  /* copy input to output */
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DLONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONG_MIN;
                }
                else if (dvalue > DLONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONG_MAX;
                }
                else
                    output[ii] = (long) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = (long) input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DLONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONG_MIN;
                    }
                    else if (dvalue > DLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONG_MAX;
                    }
                    else
                        output[ii] = (long) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi2i4(short *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            short tnull,          /* I - value of FITS TNULLn keyword if any */
            long nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            long *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
                output[ii] = (long) input[ii];   /* copy input to output */
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DLONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONG_MIN;
                }
                else if (dvalue > DLONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONG_MAX;
                }
                else
                    output[ii] = (long) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = (long) input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DLONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONG_MIN;
                    }
                    else if (dvalue > DLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONG_MAX;
                    }
                    else
                        output[ii] = (long) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi4i4(INT32BIT *input,      /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
            long nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            long *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++) { 
                 output[ii] = (long) input[ii];   /* copy input to output */
	    }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DLONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONG_MIN;
                }
                else if (dvalue > DLONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONG_MAX;
                }
                else
                    output[ii] = (long) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DLONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONG_MIN;
                    }
                    else if (dvalue > DLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONG_MAX;
                    }
                    else
                        output[ii] = (long) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi8i4(LONGLONG *input,      /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
            long nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            long *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < LONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONG_MIN;
                }
                else if (input[ii] > LONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONG_MAX;
                }
                else
                    output[ii] = (long) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DLONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONG_MIN;
                }
                else if (dvalue > DLONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONG_MAX;
                }
                else
                    output[ii] = (long) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    if (input[ii] < LONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONG_MIN;
                    }
                    else if (input[ii] > LONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONG_MAX;
                    }
                    else
                        output[ii] = (long) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DLONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONG_MIN;
                    }
                    else if (dvalue > DLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONG_MAX;
                    }
                    else
                        output[ii] = (long) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffr4i4(float *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            long nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            long *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to NaN.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;
    short *sptr, iret;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < DLONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONG_MIN;
                }
                else if (input[ii] > DLONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONG_MAX;
                }
                else
                    output[ii] = (long) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DLONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONG_MIN;
                }
                else if (dvalue > DLONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONG_MAX;
                }
                else
                    output[ii] = (long) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        sptr = (short *) input;

#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
        sptr++;       /* point to MSBs */
#endif

        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++, sptr += 2)
            {
              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                     output[ii] = 0;
              }
              else
                {
                    if (input[ii] < DLONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONG_MIN;
                    }
                    else if (input[ii] > DLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONG_MAX;
                    }
                    else
                        output[ii] = (long) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++, sptr += 2)
            {
              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {  
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                  {
                    if (zero < DLONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONG_MIN;
                    }
                    else if (zero > DLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONG_MAX;
                    }
                    else
                        output[ii] = (long) zero;
                  }
              }
              else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DLONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONG_MIN;
                    }
                    else if (dvalue > DLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONG_MAX;
                    }
                    else
                        output[ii] = (long) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffr8i4(double *input,        /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            long nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            long *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to NaN.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;
    short *sptr, iret;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < DLONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONG_MIN;
                }
                else if (input[ii] > DLONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONG_MAX;
                }
                else
                    output[ii] = (long) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DLONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONG_MIN;
                }
                else if (dvalue > DLONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONG_MAX;
                }
                else
                    output[ii] = (long) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        sptr = (short *) input;

#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
        sptr += 3;       /* point to MSBs */
#endif
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++, sptr += 4)
            {
              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                     output[ii] = 0;
              }
              else
                {
                    if (input[ii] < DLONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONG_MIN;
                    }
                    else if (input[ii] > DLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONG_MAX;
                    }
                    else
                        output[ii] = (long) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++, sptr += 4)
            {
              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {  
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                  {
                    if (zero < DLONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONG_MIN;
                    }
                    else if (zero > DLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONG_MAX;
                    }
                    else
                        output[ii] = (long) zero;
                  }
              }
              else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DLONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONG_MIN;
                    }
                    else if (dvalue > DLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONG_MAX;
                    }
                    else
                        output[ii] = (long) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffstri4(char *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            long twidth,          /* I - width of each substring of chars    */
            double implipower,    /* I - power of 10 of implied decimal      */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            char  *snull,         /* I - value of FITS null string, if any   */
            long nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            long *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file. Check
  for null values and do scaling if required. The nullcheck code value
  determines how any null values in the input array are treated. A null
  value is an input pixel that is equal to snull.  If nullcheck= 0, then
  no special checking for nulls is performed.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    int nullen;
    long ii;
    double dvalue;
    char *cstring, message[FLEN_ERRMSG];
    char *cptr, *tpos;
    char tempstore, chrzero = '0';
    double val, power;
    int exponent, sign, esign, decpt;

    nullen = strlen(snull);
    cptr = input;  /* pointer to start of input string */
    for (ii = 0; ii < ntodo; ii++)
    {
      cstring = cptr;
      /* temporarily insert a null terminator at end of the string */
      tpos = cptr + twidth;
      tempstore = *tpos;
      *tpos = 0;

      /* check if null value is defined, and if the    */
      /* column string is identical to the null string */
      if (snull[0] != ASCII_NULL_UNDEFINED && 
         !strncmp(snull, cptr, nullen) )
      {
        if (nullcheck)  
        {
          *anynull = 1;    
          if (nullcheck == 1)
            output[ii] = nullval;
          else
            nullarray[ii] = 1;
        }
        cptr += twidth;
      }
      else
      {
        /* value is not the null value, so decode it */
        /* remove any embedded blank characters from the string */

        decpt = 0;
        sign = 1;
        val  = 0.;
        power = 1.;
        exponent = 0;
        esign = 1;

        while (*cptr == ' ')               /* skip leading blanks */
           cptr++;

        if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
        {
          if (*cptr == '-')
             sign = -1;

          cptr++;

          while (*cptr == ' ')         /* skip blanks between sign and value */
            cptr++;
        }

        while (*cptr >= '0' && *cptr <= '9')
        {
          val = val * 10. + *cptr - chrzero;  /* accumulate the value */
          cptr++;

          while (*cptr == ' ')         /* skip embedded blanks in the value */
            cptr++;
        }

        if (*cptr == '.' || *cptr == ',')    /* check for decimal point */
        {
          decpt = 1;       /* set flag to show there was a decimal point */
          cptr++;
          while (*cptr == ' ')         /* skip any blanks */
            cptr++;

          while (*cptr >= '0' && *cptr <= '9')
          {
            val = val * 10. + *cptr - chrzero;  /* accumulate the value */
            power = power * 10.;
            cptr++;

            while (*cptr == ' ')         /* skip embedded blanks in the value */
              cptr++;
          }
        }

        if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
        {
          cptr++;
          while (*cptr == ' ')         /* skip blanks */
              cptr++;
  
          if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
          {
            if (*cptr == '-')
               esign = -1;

            cptr++;

            while (*cptr == ' ')        /* skip blanks between sign and exp */
              cptr++;
          }

          while (*cptr >= '0' && *cptr <= '9')
          {
            exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
            cptr++;

            while (*cptr == ' ')         /* skip embedded blanks */
              cptr++;
          }
        }

        if (*cptr  != 0)  /* should end up at the null terminator */
        {
          snprintf(message, FLEN_ERRMSG,"Cannot read number from ASCII table");
          ffpmsg(message);
          snprintf(message, FLEN_ERRMSG,"Column field = %s.", cstring);
          ffpmsg(message);
          /* restore the char that was overwritten by the null */
          *tpos = tempstore;
          return(*status = BAD_C2D);
        }

        if (!decpt)  /* if no explicit decimal, use implied */
           power = implipower;

        dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));

        dvalue = dvalue * scale + zero;   /* apply the scaling */

        if (dvalue < DLONG_MIN)
        {
            *status = OVERFLOW_ERR;
            output[ii] = LONG_MIN;
        }
        else if (dvalue > DLONG_MAX)
        {
            *status = OVERFLOW_ERR;
            output[ii] = LONG_MAX;
        }
        else
            output[ii] = (long) dvalue;
      }
      /* restore the char that was overwritten by the null */
      *tpos = tempstore;
    }
    return(*status);
}

/* ======================================================================== */
/*      the following routines support the 'long long' data type            */
/* ======================================================================== */

/*--------------------------------------------------------------------------*/
int ffgpvjj(fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            LONGLONG  nulval, /* I - value for undefined pixels              */
            LONGLONG  *array, /* O - array of values that are returned       */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Undefined elements will be set equal to NULVAL, unless NULVAL=0
  in which case no checking for undefined values will be performed.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    long row;
    char cdummy;
    int nullcheck = 1;
    LONGLONG nullvalue;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */
         nullvalue = nulval;  /* set local variable */

        fits_read_compressed_pixels(fptr, TLONGLONG, firstelem, nelem,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgcljj(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
               array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgpfjj(fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            LONGLONG  *array, /* O - array of values that are returned       */
            char *nularray,   /* O - array of null pixel flags               */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Any undefined pixels in the returned array will be set = 0 and the 
  corresponding nularray value will be set = 1.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    long row;
    int nullcheck = 2;
    LONGLONG dummy = 0;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_read_compressed_pixels(fptr, TLONGLONG, firstelem, nelem,
            nullcheck, NULL, array, nularray, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgcljj(fptr, 2, row, firstelem, nelem, 1, 2, dummy,
               array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffg2djj(fitsfile *fptr, /* I - FITS file pointer                       */
           long  group,     /* I - group to read (1 = 1st group)           */
           LONGLONG nulval ,/* set undefined pixels equal to this          */
           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
           LONGLONG  *array,/* O - array to be filled and returned         */
           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
           int  *status)    /* IO - error status                           */
/*
  Read an entire 2-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being read).  Any null
  values in the array will be set equal to the value of nulval, unless
  nulval = 0 in which case no null checking will be performed.
*/
{
    /* call the 3D reading routine, with the 3rd dimension = 1 */

    ffg3djj(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, 
           anynul, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffg3djj(fitsfile *fptr, /* I - FITS file pointer                       */
           long  group,     /* I - group to read (1 = 1st group)           */
           LONGLONG nulval, /* set undefined pixels equal to this          */
           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
           LONGLONG  nrows,     /* I - number of rows in each plane of array   */
           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
           LONGLONG  naxis3,    /* I - FITS image NAXIS3 value                 */
           LONGLONG  *array,/* O - array to be filled and returned         */
           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
           int  *status)    /* IO - error status                           */
/*
  Read an entire 3-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being read).  Any null
  values in the array will be set equal to the value of nulval, unless
  nulval = 0 in which case no null checking will be performed.
*/
{
    long tablerow, ii, jj;
    char cdummy;
    int nullcheck = 1;
    long inc[] = {1,1,1};
    LONGLONG fpixel[] = {1,1,1}, nfits, narray;
    LONGLONG lpixel[3];
    LONGLONG nullvalue;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        lpixel[0] = ncols;
        lpixel[1] = nrows;
        lpixel[2] = naxis3;
        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_img(fptr, TLONGLONG, fpixel, lpixel, inc,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */
    tablerow=maxvalue(1,group);

    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
    {
       /* all the image pixels are contiguous, so read all at once */
       ffgcljj(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval,
               array, &cdummy, anynul, status);
       return(*status);
    }

    if (ncols < naxis1 || nrows < naxis2)
       return(*status = BAD_DIMEN);

    nfits = 1;   /* next pixel in FITS image to read */
    narray = 0;  /* next pixel in output array to be filled */

    /* loop over naxis3 planes in the data cube */
    for (jj = 0; jj < naxis3; jj++)
    {
      /* loop over the naxis2 rows in the FITS image, */
      /* reading naxis1 pixels to each row            */

      for (ii = 0; ii < naxis2; ii++)
      {
       if (ffgcljj(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval,
          &array[narray], &cdummy, anynul, status) > 0)
          return(*status);

       nfits += naxis1;
       narray += ncols;
      }
      narray += (nrows - naxis2) * ncols;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsvjj(fitsfile *fptr, /* I - FITS file pointer                         */
           int  colnum,    /* I - number of the column to read (1 = 1st)    */
           int naxis,      /* I - number of dimensions in the FITS array    */
           long  *naxes,   /* I - size of each dimension                    */
           long  *blc,     /* I - 'bottom left corner' of the subsection    */
           long  *trc,     /* I - 'top right corner' of the subsection      */
           long  *inc,     /* I - increment to be applied in each dimension */
           LONGLONG nulval,/* I - value to set undefined pixels             */
           LONGLONG *array,/* O - array to be filled and returned           */
           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
           int  *status)   /* IO - error status                             */
/*
  Read a subsection of data values from an image or a table column.
  This routine is set up to handle a maximum of nine dimensions.
*/
{
    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
    long str[9],stp[9],incr[9],dir[9];
    long nelem, nultyp, ninc, numcol;
    LONGLONG felem, dsize[10], blcll[9], trcll[9];
    int hdutype, anyf;
    char ldummy, msg[FLEN_ERRMSG];
    int nullcheck = 1;
    LONGLONG nullvalue;

    if (naxis < 1 || naxis > 9)
    {
        snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvj is out of range", naxis);
        ffpmsg(msg);
        return(*status = BAD_DIMEN);
    }

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        for (ii=0; ii < naxis; ii++) {
	    blcll[ii] = blc[ii];
	    trcll[ii] = trc[ii];
	}

        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_img(fptr, TLONGLONG, blcll, trcll, inc,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

/*
    if this is a primary array, then the input COLNUM parameter should
    be interpreted as the row number, and we will alway read the image
    data from column 2 (any group parameters are in column 1).
*/
    if (ffghdt(fptr, &hdutype, status) > 0)
        return(*status);

    if (hdutype == IMAGE_HDU)
    {
        /* this is a primary array, or image extension */
        if (colnum == 0)
        {
            rstr = 1;
            rstp = 1;
        }
        else
        {
            rstr = colnum;
            rstp = colnum;
        }
        rinc = 1;
        numcol = 2;
    }
    else
    {
        /* this is a table, so the row info is in the (naxis+1) elements */
        rstr = blc[naxis];
        rstp = trc[naxis];
        rinc = inc[naxis];
        numcol = colnum;
    }

    nultyp = 1;
    if (anynul)
        *anynul = FALSE;

    i0 = 0;
    for (ii = 0; ii < 9; ii++)
    {
        str[ii] = 1;
        stp[ii] = 1;
        incr[ii] = 1;
        dsize[ii] = 1;
        dir[ii] = 1;
    }

    for (ii = 0; ii < naxis; ii++)
    {
      if (trc[ii] < blc[ii])
      {
        if (hdutype == IMAGE_HDU)
        {
           dir[ii] = -1;
        }
        else
        {
          snprintf(msg, FLEN_ERRMSG,"ffgsvj: illegal range specified for axis %ld", ii + 1);
          ffpmsg(msg);
          return(*status = BAD_PIX_NUM);
        }
      }

      str[ii] = blc[ii];
      stp[ii] = trc[ii];
      incr[ii] = inc[ii];
      dsize[ii + 1] = dsize[ii] * naxes[ii];
      dsize[ii] = dsize[ii] * dir[ii];
    }
    dsize[naxis] = dsize[naxis] * dir[naxis];

    if (naxis == 1 && naxes[0] == 1)
    {
      /* This is not a vector column, so read all the rows at once */
      nelem = (rstp - rstr) / rinc + 1;
      ninc = rinc;
      rstp = rstr;
    }
    else
    {
      /* have to read each row individually, in all dimensions */
      nelem = (stp[0]*dir[0] - str[0]*dir[0]) / inc[0] + 1;
      ninc = incr[0] * dir[0];
    }

    for (row = rstr; row <= rstp; row += rinc)
    {
     for (i8 = str[8]*dir[8]; i8 <= stp[8]*dir[8]; i8 += incr[8])
     {
      for (i7 = str[7]*dir[7]; i7 <= stp[7]*dir[7]; i7 += incr[7])
      {
       for (i6 = str[6]*dir[6]; i6 <= stp[6]*dir[6]; i6 += incr[6])
       {
        for (i5 = str[5]*dir[5]; i5 <= stp[5]*dir[5]; i5 += incr[5])
        {
         for (i4 = str[4]*dir[4]; i4 <= stp[4]*dir[4]; i4 += incr[4])
         {
          for (i3 = str[3]*dir[3]; i3 <= stp[3]*dir[3]; i3 += incr[3])
          {
           for (i2 = str[2]*dir[2]; i2 <= stp[2]*dir[2]; i2 += incr[2])
           {
            for (i1 = str[1]*dir[1]; i1 <= stp[1]*dir[1]; i1 += incr[1])
            {

              felem=str[0] + (i1 - dir[1]) * dsize[1] + (i2 - dir[2]) * dsize[2] + 
                             (i3 - dir[3]) * dsize[3] + (i4 - dir[4]) * dsize[4] +
                             (i5 - dir[5]) * dsize[5] + (i6 - dir[6]) * dsize[6] +
                             (i7 - dir[7]) * dsize[7] + (i8 - dir[8]) * dsize[8];

              if ( ffgcljj(fptr, numcol, row, felem, nelem, ninc, nultyp,
                   nulval, &array[i0], &ldummy, &anyf, status) > 0)
                   return(*status);

              if (anyf && anynul)
                  *anynul = TRUE;

              i0 += nelem;
            }
           }
          }
         }
        }
       }
      }
     }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsfjj(fitsfile *fptr, /* I - FITS file pointer                         */
           int  colnum,    /* I - number of the column to read (1 = 1st)    */
           int naxis,      /* I - number of dimensions in the FITS array    */
           long  *naxes,   /* I - size of each dimension                    */
           long  *blc,     /* I - 'bottom left corner' of the subsection    */
           long  *trc,     /* I - 'top right corner' of the subsection      */
           long  *inc,     /* I - increment to be applied in each dimension */
           LONGLONG *array,/* O - array to be filled and returned           */
           char *flagval,  /* O - set to 1 if corresponding value is null   */
           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
           int  *status)   /* IO - error status                             */
/*
  Read a subsection of data values from an image or a table column.
  This routine is set up to handle a maximum of nine dimensions.
*/
{
    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
    long str[9],stp[9],incr[9],dsize[10];
    LONGLONG blcll[9], trcll[9];
    long felem, nelem, nultyp, ninc, numcol;
    LONGLONG nulval = 0;
    int hdutype, anyf;
    char msg[FLEN_ERRMSG];
    int nullcheck = 2;

    if (naxis < 1 || naxis > 9)
    {
        snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvj is out of range", naxis);
        ffpmsg(msg);
        return(*status = BAD_DIMEN);
    }

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        for (ii=0; ii < naxis; ii++) {
	    blcll[ii] = blc[ii];
	    trcll[ii] = trc[ii];
	}

         fits_read_compressed_img(fptr, TLONGLONG, blcll, trcll, inc,
            nullcheck, NULL, array, flagval, anynul, status);
        return(*status);
    }

/*
    if this is a primary array, then the input COLNUM parameter should
    be interpreted as the row number, and we will alway read the image
    data from column 2 (any group parameters are in column 1).
*/
    if (ffghdt(fptr, &hdutype, status) > 0)
        return(*status);

    if (hdutype == IMAGE_HDU)
    {
        /* this is a primary array, or image extension */
        if (colnum == 0)
        {
            rstr = 1;
            rstp = 1;
        }
        else
        {
            rstr = colnum;
            rstp = colnum;
        }
        rinc = 1;
        numcol = 2;
    }
    else
    {
        /* this is a table, so the row info is in the (naxis+1) elements */
        rstr = blc[naxis];
        rstp = trc[naxis];
        rinc = inc[naxis];
        numcol = colnum;
    }

    nultyp = 2;
    if (anynul)
        *anynul = FALSE;

    i0 = 0;
    for (ii = 0; ii < 9; ii++)
    {
        str[ii] = 1;
        stp[ii] = 1;
        incr[ii] = 1;
        dsize[ii] = 1;
    }

    for (ii = 0; ii < naxis; ii++)
    {
      if (trc[ii] < blc[ii])
      {
        snprintf(msg, FLEN_ERRMSG,"ffgsvj: illegal range specified for axis %ld", ii + 1);
        ffpmsg(msg);
        return(*status = BAD_PIX_NUM);
      }

      str[ii] = blc[ii];
      stp[ii] = trc[ii];
      incr[ii] = inc[ii];
      dsize[ii + 1] = dsize[ii] * naxes[ii];
    }

    if (naxis == 1 && naxes[0] == 1)
    {
      /* This is not a vector column, so read all the rows at once */
      nelem = (rstp - rstr) / rinc + 1;
      ninc = rinc;
      rstp = rstr;
    }
    else
    {
      /* have to read each row individually, in all dimensions */
      nelem = (stp[0] - str[0]) / inc[0] + 1;
      ninc = incr[0];
    }

    for (row = rstr; row <= rstp; row += rinc)
    {
     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
     {
      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
      {
       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
       {
        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
        {
         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
         {
          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
          {
           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
           {
            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
            {
              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];

              if ( ffgcljj(fptr, numcol, row, felem, nelem, ninc, nultyp,
                   nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
                   return(*status);

              if (anyf && anynul)
                  *anynul = TRUE;

              i0 += nelem;
            }
           }
          }
         }
        }
       }
      }
     }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffggpjj(fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            long  firstelem,  /* I - first vector element to read (1 = 1st)  */
            long  nelem,      /* I - number of values to read                */
            LONGLONG  *array, /* O - array of values that are returned       */
            int  *status)     /* IO - error status                           */
/*
  Read an array of group parameters from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
*/
{
    long row;
    int idummy;
    char cdummy;
    LONGLONG dummy = 0;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgcljj(fptr, 1, row, firstelem, nelem, 1, 1, dummy,
               array, &cdummy, &idummy, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcvjj(fitsfile *fptr,  /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
           LONGLONG  nulval, /* I - value for null pixels                   */
           LONGLONG *array,  /* O - array of values that are read           */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Any undefined pixels will be set equal to the value of 'nulval' unless
  nulval = 0 in which case no checks for undefined pixels will be made.
*/
{
    char cdummy;

    ffgcljj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
           array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcfjj(fitsfile *fptr,  /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
           LONGLONG  *array, /* O - array of values that are read           */
           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Nularray will be set = 1 if the corresponding array pixel is undefined, 
  otherwise nularray will = 0.
*/
{
    LONGLONG dummy = 0;

    ffgcljj(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
           array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcljj( fitsfile *fptr,   /* I - FITS file pointer                       */
            int  colnum,      /* I - number of column to read (1 = 1st col)  */
            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
            LONGLONG firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
            int   nultyp,     /* I - null value handling code:               */
                              /*     1: set undefined pixels = nulval        */
                              /*     2: set nularray=1 for undefined pixels  */
            LONGLONG  nulval, /* I - value for null pixels if nultyp = 1     */
            LONGLONG  *array, /* O - array of values that are read           */
            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU.
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer be a virtual column in a 1 or more grouped FITS primary
  array or image extension.  FITSIO treats a primary array as a binary table
  with 2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.

  The output array of values will be converted from the datatype of the column 
  and will be scaled by the FITS TSCALn and TZEROn values if necessary.
*/
{
    double scale, zero, power = 1., dtemp;
    int tcode, maxelem2, hdutype, xcode, decimals;
    long twidth, incre;
    long ii, xwidth, ntodo;
    int convert, nulcheck, readcheck = 0;
    LONGLONG repeat, startpos, elemnum, readptr, tnull;
    LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
    char tform[20];
    char message[FLEN_ERRMSG];
    char snull[20];   /*  the FITS null value if reading from ASCII table  */

    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
    void *buffer;

    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
        return(*status);

    buffer = cbuff;

    if (anynul)
        *anynul = 0;

    if (nultyp == 2)
        memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if (elemincre < 0)
        readcheck = -1;  /* don't do range checking in this case */

    if (ffgcprll(fptr, colnum, firstrow, firstelem, nelem, readcheck, &scale, &zero,
         tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
         return(*status);
    maxelem = maxelem2;

    incre *= elemincre;   /* multiply incre to just get every nth pixel */

    if (tcode == TSTRING)    /* setup for ASCII tables */
    {
      /* get the number of implied decimal places if no explicit decmal point */
      ffasfm(tform, &xcode, &xwidth, &decimals, status); 
      for(ii = 0; ii < decimals; ii++)
        power *= 10.;
    }
    /*------------------------------------------------------------------*/
    /*  Decide whether to check for null values in the input FITS file: */
    /*------------------------------------------------------------------*/
    nulcheck = nultyp; /* by default check for null values in the FITS file */

    if (nultyp == 1 && nulval == 0)
       nulcheck = 0;    /* calling routine does not want to check for nulls */

    else if (tcode%10 == 1 &&        /* if reading an integer column, and  */ 
            tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
            nulcheck = 0;            /* then do not check for null values. */

    else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
            nulcheck = 0;            /* Impossible null value */

    else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
            nulcheck = 0;            /* Impossible null value */

    else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
         nulcheck = 0;

    /*----------------------------------------------------------------------*/
    /*  If FITS column and output data array have same datatype, then we do */
    /*  not need to use a temporary buffer to store intermediate datatype.  */
    /*----------------------------------------------------------------------*/
    convert = 1;
    if (tcode == TLONGLONG)  /* Special Case:                        */
    {                             /* no type convertion required, so read */
                                  /* data directly into output buffer.    */

        if (nelem < (LONGLONG)INT32_MAX/8) {
            maxelem = nelem;
        } else {
            maxelem = INT32_MAX/8;
        }

        if (nulcheck == 0 && scale == 1. && zero == 0.)
            convert = 0;  /* no need to scale data or find nulls */
    }

    /*---------------------------------------------------------------------*/
    /*  Now read the pixels from the FITS column. If the column does not   */
    /*  have the same datatype as the output array, then we have to read   */
    /*  the raw values into a temporary buffer (of limited size).  In      */
    /*  the case of a vector colum read only 1 vector of values at a time  */
    /*  then skip to the next row if more values need to be read.          */
    /*  After reading the raw values, then call the fffXXYY routine to (1) */
    /*  test for undefined values, (2) convert the datatype if necessary,  */
    /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
    /*  scaling parameters.                                                */
    /*---------------------------------------------------------------------*/
    remain = nelem;           /* remaining number of values to read */
    next = 0;                 /* next element in array to be read   */
    rownum = 0;               /* row number, relative to firstrow   */

    while (remain)
    {
        /* limit the number of pixels to read at one time to the number that
           will fit in the buffer or to the number of pixels that remain in
           the current vector, which ever is smaller.
        */
        ntodo = (long) minvalue(remain, maxelem);
        if (elemincre >= 0)
        {
          ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));
        }
        else
        {
          ntodo = (long) minvalue(ntodo, (elemnum/(-elemincre) +1));
        }

        readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));

        switch (tcode) 
        {
            case (TLONGLONG):
                ffgi8b(fptr, readptr, ntodo, incre, (long *) &array[next],
                       status);
                if (convert)
                    fffi8i8((LONGLONG *) &array[next], ntodo, scale, zero, 
                           nulcheck, tnull, nulval, &nularray[next], 
                           anynul, &array[next], status);
                break;
            case (TLONG):
                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer,
                       status);
                fffi4i8((INT32BIT *) buffer, ntodo, scale, zero, 
                        nulcheck, (INT32BIT) tnull, nulval, &nularray[next], 
                        anynul, &array[next], status);
                break;
            case (TBYTE):
                ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer,
                       status);
                fffi1i8((unsigned char *) buffer, ntodo, scale, zero, nulcheck, 
                     (unsigned char) tnull, nulval, &nularray[next], anynul, 
                     &array[next], status);
                break;
            case (TSHORT):
                ffgi2b(fptr, readptr, ntodo, incre, (short  *) buffer, status);
                fffi2i8((short  *) buffer, ntodo, scale, zero, nulcheck, 
                      (short) tnull, nulval, &nularray[next], anynul, 
                      &array[next], status);
                break;
            case (TFLOAT):
                ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
                fffr4i8((float  *) buffer, ntodo, scale, zero, nulcheck, 
                       nulval, &nularray[next], anynul, 
                       &array[next], status);
                break;
            case (TDOUBLE):
                ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
                fffr8i8((double *) buffer, ntodo, scale, zero, nulcheck, 
                          nulval, &nularray[next], anynul, 
                          &array[next], status);
                break;
            case (TSTRING):
                ffmbyt(fptr, readptr, REPORT_EOF, status);
       
                if (incre == twidth)    /* contiguous bytes */
                     ffgbyt(fptr, ntodo * twidth, buffer, status);
                else
                     ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
                               status);

                fffstri8((char *) buffer, ntodo, scale, zero, twidth, power,
                     nulcheck, snull, nulval, &nularray[next], anynul,
                     &array[next], status);
                break;

            default:  /*  error trap for invalid column format */
                snprintf(message,FLEN_ERRMSG, 
                   "Cannot read numbers from column %d which has format %s",
                    colnum, tform);
                ffpmsg(message);
                if (hdutype == ASCII_TBL)
                    return(*status = BAD_ATABLE_FORMAT);
                else
                    return(*status = BAD_BTABLE_FORMAT);

        } /* End of switch block */

        /*-------------------------*/
        /*  Check for fatal error  */
        /*-------------------------*/
        if (*status > 0)  /* test for error during previous read operation */
        {
	  dtemp = (double) next;
          if (hdutype > 0)
            snprintf(message,FLEN_ERRMSG,
            "Error reading elements %.0f thru %.0f from column %d (ffgclj).",
              dtemp+1., dtemp+ntodo, colnum);
          else
            snprintf(message,FLEN_ERRMSG,
            "Error reading elements %.0f thru %.0f from image (ffgclj).",
              dtemp+1., dtemp+ntodo);

          ffpmsg(message);
          return(*status);
        }

        /*--------------------------------------------*/
        /*  increment the counters for the next loop  */
        /*--------------------------------------------*/
        remain -= ntodo;
        if (remain)
        {
            next += ntodo;
            elemnum = elemnum + (ntodo * elemincre);

            if (elemnum >= repeat)  /* completed a row; start on later row */
            {
                rowincre = elemnum / repeat;
                rownum += rowincre;
                elemnum = elemnum - (rowincre * repeat);
            }
            else if (elemnum < 0)  /* completed a row; start on a previous row */
            {
                rowincre = (-elemnum - 1) / repeat + 1;
                rownum -= rowincre;
                elemnum = (rowincre * repeat) + elemnum;
            }
        }
    }  /*  End of main while Loop  */


    /*--------------------------------*/
    /*  check for numerical overflow  */
    /*--------------------------------*/
    if (*status == OVERFLOW_ERR)
    {
        ffpmsg(
        "Numerical overflow during type conversion while reading FITS data.");
        *status = NUM_OVERFLOW;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi1i8(unsigned char *input, /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
            LONGLONG nullval,     /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            LONGLONG *output,     /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
                output[ii] = (LONGLONG) input[ii];  /* copy input to output */
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DLONGLONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONGLONG_MIN;
                }
                else if (dvalue > DLONGLONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONGLONG_MAX;
                }
                else
                    output[ii] = (LONGLONG) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = (LONGLONG) input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DLONGLONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONGLONG_MIN;
                    }
                    else if (dvalue > DLONGLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONGLONG_MAX;
                    }
                    else
                        output[ii] = (LONGLONG) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi2i8(short *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            short tnull,          /* I - value of FITS TNULLn keyword if any */
            LONGLONG nullval,     /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            LONGLONG *output,     /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
                output[ii] = (LONGLONG) input[ii];   /* copy input to output */
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DLONGLONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONGLONG_MIN;
                }
                else if (dvalue > DLONGLONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONGLONG_MAX;
                }
                else
                    output[ii] = (LONGLONG) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = (LONGLONG) input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DLONGLONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONGLONG_MIN;
                    }
                    else if (dvalue > DLONGLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONGLONG_MAX;
                    }
                    else
                        output[ii] = (LONGLONG) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi4i8(INT32BIT *input,      /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
            LONGLONG nullval,     /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            LONGLONG *output,     /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
                output[ii] = (LONGLONG) input[ii];   /* copy input to output */
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DLONGLONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONGLONG_MIN;
                }
                else if (dvalue > DLONGLONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONGLONG_MAX;
                }
                else
                    output[ii] = (LONGLONG) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = (LONGLONG) input[ii];

            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DLONGLONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONGLONG_MIN;
                    }
                    else if (dvalue > DLONGLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONGLONG_MAX;
                    }
                    else
                        output[ii] = (LONGLONG) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi8i8(LONGLONG *input,      /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
            LONGLONG nullval,     /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            LONGLONG *output,     /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
                output[ii] =  input[ii];   /* copy input to output */
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DLONGLONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONGLONG_MIN;
                }
                else if (dvalue > DLONGLONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONGLONG_MAX;
                }
                else
                    output[ii] = (LONGLONG) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = input[ii];

            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DLONGLONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONGLONG_MIN;
                    }
                    else if (dvalue > DLONGLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONGLONG_MAX;
                    }
                    else
                        output[ii] = (LONGLONG) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffr4i8(float *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            LONGLONG nullval,     /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            LONGLONG *output,     /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to NaN.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;
    short *sptr, iret;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < DLONGLONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONGLONG_MIN;
                }
                else if (input[ii] > DLONGLONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONGLONG_MAX;
                }
                else
                    output[ii] = (LONGLONG) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DLONGLONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONGLONG_MIN;
                }
                else if (dvalue > DLONGLONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONGLONG_MAX;
                }
                else
                    output[ii] = (LONGLONG) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        sptr = (short *) input;

#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
        sptr++;       /* point to MSBs */
#endif

        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++, sptr += 2)
            {
              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                     output[ii] = 0;
              }
              else
                {
                    if (input[ii] < DLONGLONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONGLONG_MIN;
                    }
                    else if (input[ii] > DLONGLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONGLONG_MAX;
                    }
                    else
                        output[ii] = (LONGLONG) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++, sptr += 2)
            {
              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {  
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                  {
                    if (zero < DLONGLONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONGLONG_MIN;
                    }
                    else if (zero > DLONGLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONGLONG_MAX;
                    }
                    else
                        output[ii] = (LONGLONG) zero;
                  }
              }
              else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DLONGLONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONGLONG_MIN;
                    }
                    else if (dvalue > DLONGLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONGLONG_MAX;
                    }
                    else
                        output[ii] = (LONGLONG) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffr8i8(double *input,        /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            LONGLONG nullval,     /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            LONGLONG *output,     /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to NaN.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;
    short *sptr, iret;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < DLONGLONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONGLONG_MIN;
                }
                else if (input[ii] > DLONGLONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONGLONG_MAX;
                }
                else
                    output[ii] = (LONGLONG) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DLONGLONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONGLONG_MIN;
                }
                else if (dvalue > DLONGLONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = LONGLONG_MAX;
                }
                else
                    output[ii] = (LONGLONG) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        sptr = (short *) input;

#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
        sptr += 3;       /* point to MSBs */
#endif
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++, sptr += 4)
            {
              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                     output[ii] = 0;
              }
              else
                {
                    if (input[ii] < DLONGLONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONGLONG_MIN;
                    }
                    else if (input[ii] > DLONGLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONGLONG_MAX;
                    }
                    else
                        output[ii] = (LONGLONG) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++, sptr += 4)
            {
              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {  
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                  {
                    if (zero < DLONGLONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONGLONG_MIN;
                    }
                    else if (zero > DLONGLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONGLONG_MAX;
                    }
                    else
                        output[ii] = (LONGLONG) zero;
                  }
              }
              else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DLONGLONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONGLONG_MIN;
                    }
                    else if (dvalue > DLONGLONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = LONGLONG_MAX;
                    }
                    else
                        output[ii] = (LONGLONG) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffstri8(char *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            long twidth,          /* I - width of each substring of chars    */
            double implipower,    /* I - power of 10 of implied decimal      */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            char  *snull,         /* I - value of FITS null string, if any   */
            LONGLONG nullval,     /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            LONGLONG *output,     /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file. Check
  for null values and do scaling if required. The nullcheck code value
  determines how any null values in the input array are treated. A null
  value is an input pixel that is equal to snull.  If nullcheck= 0, then
  no special checking for nulls is performed.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    int nullen;
    long ii;
    double dvalue;
    char *cstring, message[FLEN_ERRMSG];
    char *cptr, *tpos;
    char tempstore, chrzero = '0';
    double val, power;
    int exponent, sign, esign, decpt;

    nullen = strlen(snull);
    cptr = input;  /* pointer to start of input string */
    for (ii = 0; ii < ntodo; ii++)
    {
      cstring = cptr;
      /* temporarily insert a null terminator at end of the string */
      tpos = cptr + twidth;
      tempstore = *tpos;
      *tpos = 0;

      /* check if null value is defined, and if the    */
      /* column string is identical to the null string */
      if (snull[0] != ASCII_NULL_UNDEFINED && 
         !strncmp(snull, cptr, nullen) )
      {
        if (nullcheck)  
        {
          *anynull = 1;    
          if (nullcheck == 1)
            output[ii] = nullval;
          else
            nullarray[ii] = 1;
        }
        cptr += twidth;
      }
      else
      {
        /* value is not the null value, so decode it */
        /* remove any embedded blank characters from the string */

        decpt = 0;
        sign = 1;
        val  = 0.;
        power = 1.;
        exponent = 0;
        esign = 1;

        while (*cptr == ' ')               /* skip leading blanks */
           cptr++;

        if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
        {
          if (*cptr == '-')
             sign = -1;

          cptr++;

          while (*cptr == ' ')         /* skip blanks between sign and value */
            cptr++;
        }

        while (*cptr >= '0' && *cptr <= '9')
        {
          val = val * 10. + *cptr - chrzero;  /* accumulate the value */
          cptr++;

          while (*cptr == ' ')         /* skip embedded blanks in the value */
            cptr++;
        }

        if (*cptr == '.' || *cptr == ',')    /* check for decimal point */
        {
          decpt = 1;       /* set flag to show there was a decimal point */
          cptr++;
          while (*cptr == ' ')         /* skip any blanks */
            cptr++;

          while (*cptr >= '0' && *cptr <= '9')
          {
            val = val * 10. + *cptr - chrzero;  /* accumulate the value */
            power = power * 10.;
            cptr++;

            while (*cptr == ' ')         /* skip embedded blanks in the value */
              cptr++;
          }
        }

        if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
        {
          cptr++;
          while (*cptr == ' ')         /* skip blanks */
              cptr++;
  
          if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
          {
            if (*cptr == '-')
               esign = -1;

            cptr++;

            while (*cptr == ' ')        /* skip blanks between sign and exp */
              cptr++;
          }

          while (*cptr >= '0' && *cptr <= '9')
          {
            exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
            cptr++;

            while (*cptr == ' ')         /* skip embedded blanks */
              cptr++;
          }
        }

        if (*cptr  != 0)  /* should end up at the null terminator */
        {
          snprintf(message, FLEN_ERRMSG, "Cannot read number from ASCII table");
          ffpmsg(message);
          snprintf(message, FLEN_ERRMSG,"Column field = %s.", cstring);
          ffpmsg(message);
          /* restore the char that was overwritten by the null */
          *tpos = tempstore;
          return(*status = BAD_C2D);
        }

        if (!decpt)  /* if no explicit decimal, use implied */
           power = implipower;

        dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));

        dvalue = dvalue * scale + zero;   /* apply the scaling */

        if (dvalue < DLONGLONG_MIN)
        {
            *status = OVERFLOW_ERR;
            output[ii] = LONGLONG_MIN;
        }
        else if (dvalue > DLONGLONG_MAX)
        {
            *status = OVERFLOW_ERR;
            output[ii] = LONGLONG_MAX;
        }
        else
            output[ii] = (LONGLONG) dvalue;
      }
      /* restore the char that was overwritten by the null */
      *tpos = tempstore;
    }
    return(*status);
}
cfitsio/getcolk.c0000644000225700000360000021637413246025103013611 0ustar  cagordonlhea/*  This file, getcolk.c, contains routines that read data elements from   */
/*  a FITS image or table, with 'int' data type.                           */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include 
#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int ffgpvk( fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            int   nulval,     /* I - value for undefined pixels              */
            int   *array,     /* O - array of values that are returned       */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Undefined elements will be set equal to NULVAL, unless NULVAL=0
  in which case no checking for undefined values will be performed.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    long row;
    char cdummy;
    int nullcheck = 1;
    int nullvalue;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */
         nullvalue = nulval;  /* set local variable */

        fits_read_compressed_pixels(fptr, TINT, firstelem, nelem,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgclk(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
               array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgpfk( fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            int   *array,     /* O - array of values that are returned       */
            char *nularray,   /* O - array of null pixel flags               */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Any undefined pixels in the returned array will be set = 0 and the 
  corresponding nularray value will be set = 1.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    long row;
    int nullcheck = 2;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_read_compressed_pixels(fptr, TINT, firstelem, nelem,
            nullcheck, NULL, array, nularray, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgclk(fptr, 2, row, firstelem, nelem, 1, 2, 0L,
               array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffg2dk(fitsfile *fptr,  /* I - FITS file pointer                       */
           long  group,     /* I - group to read (1 = 1st group)           */
           int  nulval,    /* set undefined pixels equal to this          */
           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
           int  *array,    /* O - array to be filled and returned         */
           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
           int  *status)    /* IO - error status                           */
/*
  Read an entire 2-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being read).  Any null
  values in the array will be set equal to the value of nulval, unless
  nulval = 0 in which case no null checking will be performed.
*/
{
    /* call the 3D reading routine, with the 3rd dimension = 1 */

    ffg3dk(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, 
           anynul, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffg3dk(fitsfile *fptr,  /* I - FITS file pointer                       */
           long  group,     /* I - group to read (1 = 1st group)           */
           int   nulval,    /* set undefined pixels equal to this          */
           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
           LONGLONG  nrows,     /* I - number of rows in each plane of array   */
           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
           LONGLONG  naxis3,    /* I - FITS image NAXIS3 value                 */
           int   *array,    /* O - array to be filled and returned         */
           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
           int  *status)    /* IO - error status                           */
/*
  Read an entire 3-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being read).  Any null
  values in the array will be set equal to the value of nulval, unless
  nulval = 0 in which case no null checking will be performed.
*/
{
    long tablerow, ii, jj;
    char cdummy;
    int nullcheck = 1;
    long inc[] = {1,1,1};
    LONGLONG fpixel[] = {1,1,1}, nfits, narray;
    LONGLONG lpixel[3];
    int nullvalue;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        lpixel[0] = ncols;
        lpixel[1] = nrows;
        lpixel[2] = naxis3;
        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_img(fptr, TINT, fpixel, lpixel, inc,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */
    tablerow=maxvalue(1,group);

    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
    {
       /* all the image pixels are contiguous, so read all at once */
       ffgclk(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval,
               array, &cdummy, anynul, status);
       return(*status);
    }

    if (ncols < naxis1 || nrows < naxis2)
       return(*status = BAD_DIMEN);

    nfits = 1;   /* next pixel in FITS image to read */
    narray = 0;  /* next pixel in output array to be filled */

    /* loop over naxis3 planes in the data cube */
    for (jj = 0; jj < naxis3; jj++)
    {
      /* loop over the naxis2 rows in the FITS image, */
      /* reading naxis1 pixels to each row            */

      for (ii = 0; ii < naxis2; ii++)
      {
       if (ffgclk(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval,
          &array[narray], &cdummy, anynul, status) > 0)
          return(*status);

       nfits += naxis1;
       narray += ncols;
      }
      narray += (nrows - naxis2) * ncols;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsvk(fitsfile *fptr, /* I - FITS file pointer                         */
           int  colnum,    /* I - number of the column to read (1 = 1st)    */
           int naxis,      /* I - number of dimensions in the FITS array    */
           long  *naxes,   /* I - size of each dimension                    */
           long  *blc,     /* I - 'bottom left corner' of the subsection    */
           long  *trc,     /* I - 'top right corner' of the subsection      */
           long  *inc,     /* I - increment to be applied in each dimension */
           int  nulval,    /* I - value to set undefined pixels             */
           int  *array,    /* O - array to be filled and returned           */
           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
           int  *status)   /* IO - error status                             */
/*
  Read a subsection of data values from an image or a table column.
  This routine is set up to handle a maximum of nine dimensions.
*/
{
    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
    long str[9],stp[9],incr[9],dir[9];
    long nelem, nultyp, ninc, numcol;
    LONGLONG felem, dsize[10], blcll[9], trcll[9];
    int hdutype, anyf;
    char ldummy, msg[FLEN_ERRMSG];
    int nullcheck = 1;
    int nullvalue;

    if (naxis < 1 || naxis > 9)
    {
        snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvj is out of range", naxis);
        ffpmsg(msg);
        return(*status = BAD_DIMEN);
    }

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        for (ii=0; ii < naxis; ii++) {
	    blcll[ii] = blc[ii];
	    trcll[ii] = trc[ii];
	}

        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_img(fptr, TINT, blcll, trcll, inc,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

/*
    if this is a primary array, then the input COLNUM parameter should
    be interpreted as the row number, and we will alway read the image
    data from column 2 (any group parameters are in column 1).
*/
    if (ffghdt(fptr, &hdutype, status) > 0)
        return(*status);

    if (hdutype == IMAGE_HDU)
    {
        /* this is a primary array, or image extension */
        if (colnum == 0)
        {
            rstr = 1;
            rstp = 1;
        }
        else
        {
            rstr = colnum;
            rstp = colnum;
        }
        rinc = 1;
        numcol = 2;
    }
    else
    {
        /* this is a table, so the row info is in the (naxis+1) elements */
        rstr = blc[naxis];
        rstp = trc[naxis];
        rinc = inc[naxis];
        numcol = colnum;
    }

    nultyp = 1;
    if (anynul)
        *anynul = FALSE;

    i0 = 0;
    for (ii = 0; ii < 9; ii++)
    {
        str[ii] = 1;
        stp[ii] = 1;
        incr[ii] = 1;
        dsize[ii] = 1;
        dir[ii] = 1;
    }

    for (ii = 0; ii < naxis; ii++)
    {
      if (trc[ii] < blc[ii])
      {
        if (hdutype == IMAGE_HDU)
        {
           dir[ii] = -1;
        }
        else
        {
          snprintf(msg, FLEN_ERRMSG,"ffgsvk: illegal range specified for axis %ld", ii + 1);
          ffpmsg(msg);
          return(*status = BAD_PIX_NUM);
        }
      }

      str[ii] = blc[ii];
      stp[ii] = trc[ii];
      incr[ii] = inc[ii];
      dsize[ii + 1] = dsize[ii] * naxes[ii];
      dsize[ii] = dsize[ii] * dir[ii];
    }
    dsize[naxis] = dsize[naxis] * dir[naxis];

    if (naxis == 1 && naxes[0] == 1)
    {
      /* This is not a vector column, so read all the rows at once */
      nelem = (rstp - rstr) / rinc + 1;
      ninc = rinc;
      rstp = rstr;
    }
    else
    {
      /* have to read each row individually, in all dimensions */
      nelem = (stp[0]*dir[0] - str[0]*dir[0]) / inc[0] + 1;
      ninc = incr[0] * dir[0];
    }

    for (row = rstr; row <= rstp; row += rinc)
    {
     for (i8 = str[8]*dir[8]; i8 <= stp[8]*dir[8]; i8 += incr[8])
     {
      for (i7 = str[7]*dir[7]; i7 <= stp[7]*dir[7]; i7 += incr[7])
      {
       for (i6 = str[6]*dir[6]; i6 <= stp[6]*dir[6]; i6 += incr[6])
       {
        for (i5 = str[5]*dir[5]; i5 <= stp[5]*dir[5]; i5 += incr[5])
        {
         for (i4 = str[4]*dir[4]; i4 <= stp[4]*dir[4]; i4 += incr[4])
         {
          for (i3 = str[3]*dir[3]; i3 <= stp[3]*dir[3]; i3 += incr[3])
          {
           for (i2 = str[2]*dir[2]; i2 <= stp[2]*dir[2]; i2 += incr[2])
           {
            for (i1 = str[1]*dir[1]; i1 <= stp[1]*dir[1]; i1 += incr[1])
            {

              felem=str[0] + (i1 - dir[1]) * dsize[1] + (i2 - dir[2]) * dsize[2] + 
                             (i3 - dir[3]) * dsize[3] + (i4 - dir[4]) * dsize[4] +
                             (i5 - dir[5]) * dsize[5] + (i6 - dir[6]) * dsize[6] +
                             (i7 - dir[7]) * dsize[7] + (i8 - dir[8]) * dsize[8];

              if ( ffgclk(fptr, numcol, row, felem, nelem, ninc, nultyp,
                   nulval, &array[i0], &ldummy, &anyf, status) > 0)
                   return(*status);

              if (anyf && anynul)
                  *anynul = TRUE;

              i0 += nelem;
            }
           }
          }
         }
        }
       }
      }
     }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsfk(fitsfile *fptr, /* I - FITS file pointer                         */
           int  colnum,    /* I - number of the column to read (1 = 1st)    */
           int naxis,      /* I - number of dimensions in the FITS array    */
           long  *naxes,   /* I - size of each dimension                    */
           long  *blc,     /* I - 'bottom left corner' of the subsection    */
           long  *trc,     /* I - 'top right corner' of the subsection      */
           long  *inc,     /* I - increment to be applied in each dimension */
           int  *array,    /* O - array to be filled and returned           */
           char *flagval,  /* O - set to 1 if corresponding value is null   */
           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
           int  *status)   /* IO - error status                             */
/*
  Read a subsection of data values from an image or a table column.
  This routine is set up to handle a maximum of nine dimensions.
*/
{
    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
    long str[9],stp[9],incr[9],dsize[10];
    LONGLONG blcll[9], trcll[9];
    long felem, nelem, nultyp, ninc, numcol;
    long nulval = 0;
    int hdutype, anyf;
    char msg[FLEN_ERRMSG];
    int nullcheck = 2;

    if (naxis < 1 || naxis > 9)
    {
        snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvj is out of range", naxis);
        ffpmsg(msg);
        return(*status = BAD_DIMEN);
    }

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        for (ii=0; ii < naxis; ii++) {
	    blcll[ii] = blc[ii];
	    trcll[ii] = trc[ii];
	}

        fits_read_compressed_img(fptr, TINT, blcll, trcll, inc,
            nullcheck, NULL, array, flagval, anynul, status);
        return(*status);
    }

/*
    if this is a primary array, then the input COLNUM parameter should
    be interpreted as the row number, and we will alway read the image
    data from column 2 (any group parameters are in column 1).
*/
    if (ffghdt(fptr, &hdutype, status) > 0)
        return(*status);

    if (hdutype == IMAGE_HDU)
    {
        /* this is a primary array, or image extension */
        if (colnum == 0)
        {
            rstr = 1;
            rstp = 1;
        }
        else
        {
            rstr = colnum;
            rstp = colnum;
        }
        rinc = 1;
        numcol = 2;
    }
    else
    {
        /* this is a table, so the row info is in the (naxis+1) elements */
        rstr = blc[naxis];
        rstp = trc[naxis];
        rinc = inc[naxis];
        numcol = colnum;
    }

    nultyp = 2;
    if (anynul)
        *anynul = FALSE;

    i0 = 0;
    for (ii = 0; ii < 9; ii++)
    {
        str[ii] = 1;
        stp[ii] = 1;
        incr[ii] = 1;
        dsize[ii] = 1;
    }

    for (ii = 0; ii < naxis; ii++)
    {
      if (trc[ii] < blc[ii])
      {
        snprintf(msg, FLEN_ERRMSG,"ffgsvj: illegal range specified for axis %ld", ii + 1);
        ffpmsg(msg);
        return(*status = BAD_PIX_NUM);
      }

      str[ii] = blc[ii];
      stp[ii] = trc[ii];
      incr[ii] = inc[ii];
      dsize[ii + 1] = dsize[ii] * naxes[ii];
    }

    if (naxis == 1 && naxes[0] == 1)
    {
      /* This is not a vector column, so read all the rows at once */
      nelem = (rstp - rstr) / rinc + 1;
      ninc = rinc;
      rstp = rstr;
    }
    else
    {
      /* have to read each row individually, in all dimensions */
      nelem = (stp[0] - str[0]) / inc[0] + 1;
      ninc = incr[0];
    }

    for (row = rstr; row <= rstp; row += rinc)
    {
     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
     {
      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
      {
       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
       {
        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
        {
         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
         {
          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
          {
           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
           {
            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
            {
              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];

              if ( ffgclk(fptr, numcol, row, felem, nelem, ninc, nultyp,
                   nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
                   return(*status);

              if (anyf && anynul)
                  *anynul = TRUE;

              i0 += nelem;
            }
           }
          }
         }
        }
       }
      }
     }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffggpk( fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            long  firstelem,  /* I - first vector element to read (1 = 1st)  */
            long  nelem,      /* I - number of values to read                */
            int  *array,     /* O - array of values that are returned       */
            int  *status)     /* IO - error status                           */
/*
  Read an array of group parameters from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
*/
{
    long row;
    int idummy;
    char cdummy;
    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgclk(fptr, 1, row, firstelem, nelem, 1, 1, 0L,
               array, &cdummy, &idummy, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcvk(fitsfile *fptr,   /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
           int   nulval,     /* I - value for null pixels                   */
           int  *array,      /* O - array of values that are read           */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Any undefined pixels will be set equal to the value of 'nulval' unless
  nulval = 0 in which case no checks for undefined pixels will be made.
*/
{
    char cdummy;

    ffgclk(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
           array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcfk(fitsfile *fptr,   /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
           int   *array,     /* O - array of values that are read           */
           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Nularray will be set = 1 if the corresponding array pixel is undefined, 
  otherwise nularray will = 0.
*/
{
    int dummy = 0;

    ffgclk(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
           array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgclk( fitsfile *fptr,   /* I - FITS file pointer                       */
            int  colnum,      /* I - number of column to read (1 = 1st col)  */
            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
            LONGLONG firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
            int   nultyp,     /* I - null value handling code:               */
                              /*     1: set undefined pixels = nulval        */
                              /*     2: set nularray=1 for undefined pixels  */
            int   nulval,     /* I - value for null pixels if nultyp = 1     */
            int  *array,      /* O - array of values that are read           */
            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU.
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer be a virtual column in a 1 or more grouped FITS primary
  array or image extension.  FITSIO treats a primary array as a binary table
  with 2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.

  The output array of values will be converted from the datatype of the column 
  and will be scaled by the FITS TSCALn and TZEROn values if necessary.
*/
{
    double scale, zero, power, dtemp;
    int tcode, maxelem2, hdutype, xcode, decimals;
    long twidth, incre;
    long ii, xwidth, ntodo;
    int convert, nulcheck, readcheck = 0;
    LONGLONG repeat, startpos, elemnum, readptr, tnull;
    LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
    char tform[20];
    char message[FLEN_ERRMSG];
    char snull[20];   /*  the FITS null value if reading from ASCII table  */

    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
    void *buffer;

    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
        return(*status);

    /* call the 'short' or 'long' version of this routine, if possible */
    if (sizeof(int) == sizeof(short))
        ffgcli(fptr, colnum, firstrow, firstelem, nelem, elemincre, nultyp,
              (short) nulval, (short *) array, nularray, anynul, status);
    else if (sizeof(int) == sizeof(long))
        ffgclj(fptr, colnum, firstrow, firstelem, nelem, elemincre, nultyp,
              (long) nulval, (long *) array, nularray, anynul, status);
    else
    {
    /*
      This is a special case: sizeof(int) is not equal to sizeof(short) or
      sizeof(long).  This occurs on Alpha OSF systems where short = 2 bytes,
      int = 4 bytes, and long = 8 bytes.
    */

    buffer = cbuff;
    power = 1.;

    if (anynul)
        *anynul = 0;

    if (nultyp == 2)
        memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if (elemincre < 0)
        readcheck = -1;  /* don't do range checking in this case */

    if ( ffgcprll( fptr, colnum, firstrow, firstelem, nelem, readcheck, &scale, &zero,
         tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
         return(*status);
    maxelem = maxelem2;

    incre *= elemincre;   /* multiply incre to just get every nth pixel */

    if (tcode == TSTRING)    /* setup for ASCII tables */
    {
      /* get the number of implied decimal places if no explicit decmal point */
      ffasfm(tform, &xcode, &xwidth, &decimals, status); 
      for(ii = 0; ii < decimals; ii++)
        power *= 10.;
    }
    /*------------------------------------------------------------------*/
    /*  Decide whether to check for null values in the input FITS file: */
    /*------------------------------------------------------------------*/
    nulcheck = nultyp; /* by default check for null values in the FITS file */

    if (nultyp == 1 && nulval == 0)
       nulcheck = 0;    /* calling routine does not want to check for nulls */

    else if (tcode%10 == 1 &&        /* if reading an integer column, and  */ 
            tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
            nulcheck = 0;            /* then do not check for null values. */

    else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
            nulcheck = 0;            /* Impossible null value */

    else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
            nulcheck = 0;            /* Impossible null value */

    else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
         nulcheck = 0;

    /*----------------------------------------------------------------------*/
    /*  If FITS column and output data array have same datatype, then we do */
    /*  not need to use a temporary buffer to store intermediate datatype.  */
    /*----------------------------------------------------------------------*/
    convert = 1;
    if (tcode == TLONG)           /* Special Case:                        */
    {                             /* no type convertion required, so read */
                                  /* data directly into output buffer.    */

        if (nelem < (LONGLONG)INT32_MAX/4) {
            maxelem = nelem;
        } else {
            maxelem = INT32_MAX/4;
        }

        if (nulcheck == 0 && scale == 1. && zero == 0.)
            convert = 0;  /* no need to scale data or find nulls */
    }

    /*---------------------------------------------------------------------*/
    /*  Now read the pixels from the FITS column. If the column does not   */
    /*  have the same datatype as the output array, then we have to read   */
    /*  the raw values into a temporary buffer (of limited size).  In      */
    /*  the case of a vector colum read only 1 vector of values at a time  */
    /*  then skip to the next row if more values need to be read.          */
    /*  After reading the raw values, then call the fffXXYY routine to (1) */
    /*  test for undefined values, (2) convert the datatype if necessary,  */
    /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
    /*  scaling parameters.                                                */
    /*---------------------------------------------------------------------*/
    remain = nelem;           /* remaining number of values to read */
    next = 0;                 /* next element in array to be read   */
    rownum = 0;               /* row number, relative to firstrow   */

    while (remain)
    {
        /* limit the number of pixels to read at one time to the number that
           will fit in the buffer or to the number of pixels that remain in
           the current vector, which ever is smaller.
        */
        ntodo = (long) minvalue(remain, maxelem);
        if (elemincre >= 0)
        {
          ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));
        }
        else
        {
          ntodo = (long) minvalue(ntodo, (elemnum/(-elemincre) +1));
        }

        readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));

        switch (tcode) 
        {
            case (TLONG):
                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) &array[next],
                       status);
                if (convert)
                    fffi4int((INT32BIT *) &array[next], ntodo, scale, zero, 
                             nulcheck, (INT32BIT) tnull, nulval,
                             &nularray[next], anynul, &array[next], status);
                break;
            case (TLONGLONG):

                ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status);
                fffi8int( (LONGLONG *) buffer, ntodo, scale, zero, 
                           nulcheck, tnull, nulval, &nularray[next], 
                            anynul, &array[next], status);
                break;
            case (TBYTE):
                ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer,
                       status);
                fffi1int((unsigned char *) buffer, ntodo, scale, zero, nulcheck,
                     (unsigned char) tnull, nulval, &nularray[next], anynul, 
                     &array[next], status);
                break;
            case (TSHORT):
                ffgi2b(fptr, readptr, ntodo, incre, (short  *) buffer, status);
                fffi2int((short  *) buffer, ntodo, scale, zero, nulcheck, 
                      (short) tnull, nulval, &nularray[next], anynul, 
                      &array[next], status);
                break;
            case (TFLOAT):
                ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
                fffr4int((float  *) buffer, ntodo, scale, zero, nulcheck, 
                       nulval, &nularray[next], anynul, 
                       &array[next], status);
                break;
            case (TDOUBLE):
                ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
                fffr8int((double *) buffer, ntodo, scale, zero, nulcheck, 
                          nulval, &nularray[next], anynul, 
                          &array[next], status);
                break;
            case (TSTRING):
                ffmbyt(fptr, readptr, REPORT_EOF, status);
       
                if (incre == twidth)    /* contiguous bytes */
                     ffgbyt(fptr, ntodo * twidth, buffer, status);
                else
                     ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
                               status);

                fffstrint((char *) buffer, ntodo, scale, zero, twidth, power,
                     nulcheck, snull, nulval, &nularray[next], anynul,
                     &array[next], status);
                break;

            default:  /*  error trap for invalid column format */
                snprintf(message, FLEN_ERRMSG,
                   "Cannot read numbers from column %d which has format %s",
                    colnum, tform);
                ffpmsg(message);
                if (hdutype == ASCII_TBL)
                    return(*status = BAD_ATABLE_FORMAT);
                else
                    return(*status = BAD_BTABLE_FORMAT);

        } /* End of switch block */

        /*-------------------------*/
        /*  Check for fatal error  */
        /*-------------------------*/
        if (*status > 0)  /* test for error during previous read operation */
        {
	  dtemp = (double) next;
          if (hdutype > 0)
            snprintf(message, FLEN_ERRMSG,
            "Error reading elements %.0f thru %.0f from column %d (ffgclk).",
              dtemp+1., dtemp+ntodo, colnum);
          else
            snprintf(message, FLEN_ERRMSG,
            "Error reading elements %.0f thru %.0f from image (ffgclk).",
              dtemp+1., dtemp+ntodo);

          ffpmsg(message);
          return(*status);
        }

        /*--------------------------------------------*/
        /*  increment the counters for the next loop  */
        /*--------------------------------------------*/
        remain -= ntodo;
        if (remain)
        {
            next += ntodo;
            elemnum = elemnum + (ntodo * elemincre);

            if (elemnum >= repeat)  /* completed a row; start on later row */
            {
                rowincre = elemnum / repeat;
                rownum += rowincre;
                elemnum = elemnum - (rowincre * repeat);
            }
            else if (elemnum < 0)  /* completed a row; start on a previous row */
            {
                rowincre = (-elemnum - 1) / repeat + 1;
                rownum -= rowincre;
                elemnum = (rowincre * repeat) + elemnum;
            }
        }
    }  /*  End of main while Loop  */


    /*--------------------------------*/
    /*  check for numerical overflow  */
    /*--------------------------------*/
    if (*status == OVERFLOW_ERR)
    {
        ffpmsg(
        "Numerical overflow during type conversion while reading FITS data.");
        *status = NUM_OVERFLOW;
    }

    }  /* end of DEC Alpha special case */

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi1int(unsigned char *input,/* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
            int  nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            int  *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
                output[ii] = (int) input[ii];  /* copy input to output */
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DINT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = INT_MIN;
                }
                else if (dvalue > DINT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = INT_MAX;
                }
                else
                    output[ii] = (int) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = (int) input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DINT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = INT_MIN;
                    }
                    else if (dvalue > DINT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = INT_MAX;
                    }
                    else
                        output[ii] = (int) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi2int(short *input,        /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            short tnull,          /* I - value of FITS TNULLn keyword if any */
            int  nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            int  *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
                output[ii] = (int) input[ii];   /* copy input to output */
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DINT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = INT_MIN;
                }
                else if (dvalue > DINT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = INT_MAX;
                }
                else
                    output[ii] = (int) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = (int) input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DINT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = INT_MIN;
                    }
                    else if (dvalue > DINT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = INT_MAX;
                    }
                    else
                        output[ii] = (int) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi4int(INT32BIT *input,     /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
            int  nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            int  *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;
    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
                output[ii] = (int) input[ii];   /* copy input to output */
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DINT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = INT_MIN;
                }
                else if (dvalue > DINT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = INT_MAX;
                }
                else
                    output[ii] = (int) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = (int) input[ii];

            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DINT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = INT_MIN;
                    }
                    else if (dvalue > DINT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = INT_MAX;
                    }
                    else
                        output[ii] = (int) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi8int(LONGLONG *input,     /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
            int  nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            int  *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < INT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = INT_MIN;
                }
                else if (input[ii] > INT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = INT_MAX;
                }
                else
                    output[ii] = (int) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DINT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = INT_MIN;
                }
                else if (dvalue > DINT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = INT_MAX;
                }
                else
                    output[ii] = (int) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    if (input[ii] < INT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = INT_MIN;
                    }
                    else if (input[ii] > INT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = INT_MAX;
                    }
                    else
                        output[ii] = (int) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DINT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = INT_MIN;
                    }
                    else if (dvalue > DINT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = INT_MAX;
                    }
                    else
                        output[ii] = (int) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffr4int(float *input,        /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            int  nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            int  *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to NaN.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;
    short *sptr, iret;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < DINT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = INT_MIN;
                }
                else if (input[ii] > DINT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = INT_MAX;
                }
                else
                    output[ii] = (int) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DINT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = INT_MIN;
                }
                else if (dvalue > DINT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = INT_MAX;
                }
                else
                    output[ii] = (int) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        sptr = (short *) input;

#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
        sptr++;       /* point to MSBs */
#endif

        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++, sptr += 2)
            {
              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                     output[ii] = 0;
              }
              else
                {
                    if (input[ii] < DINT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = INT_MIN;
                    }
                    else if (input[ii] > DINT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = INT_MAX;
                    }
                    else
                        output[ii] = (int) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++, sptr += 2)
            {
              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {  
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                  { 
                    if (zero < DINT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = INT_MIN;
                    }
                    else if (zero > DINT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = INT_MAX;
                    }
                    else
                      output[ii] = (int) zero;
                  }
              }
              else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DINT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = INT_MIN;
                    }
                    else if (dvalue > DINT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = INT_MAX;
                    }
                    else
                        output[ii] = (int) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffr8int(double *input,       /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            int  nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            int  *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to NaN.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;
    short *sptr, iret;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < DINT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = INT_MIN;
                }
                else if (input[ii] > DINT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = INT_MAX;
                }
                else
                    output[ii] = (int) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DINT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = INT_MIN;
                }
                else if (dvalue > DINT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = INT_MAX;
                }
                else
                    output[ii] = (int) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        sptr = (short *) input;

#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
        sptr += 3;       /* point to MSBs */
#endif
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++, sptr += 4)
            {
              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                     output[ii] = 0;
              }
              else
                {
                    if (input[ii] < DINT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = INT_MIN;
                    }
                    else if (input[ii] > DINT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = INT_MAX;
                    }
                    else
                        output[ii] = (int) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++, sptr += 4)
            {
              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {  
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                  { 
                    if (zero < DINT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = INT_MIN;
                    }
                    else if (zero > DINT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = INT_MAX;
                    }
                    else
                      output[ii] = (int) zero;
                  }
              }
              else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DINT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = INT_MIN;
                    }
                    else if (dvalue > DINT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = INT_MAX;
                    }
                    else
                        output[ii] = (int) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffstrint(char *input,        /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            long twidth,          /* I - width of each substring of chars    */
            double implipower,    /* I - power of 10 of implied decimal      */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            char  *snull,         /* I - value of FITS null string, if any   */
            int nullval,          /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            int *output,          /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file. Check
  for null values and do scaling if required. The nullcheck code value
  determines how any null values in the input array are treated. A null
  value is an input pixel that is equal to snull.  If nullcheck= 0, then
  no special checking for nulls is performed.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    int nullen;
    long ii;
    double dvalue;
    char *cstring, message[FLEN_ERRMSG];
    char *cptr, *tpos;
    char tempstore, chrzero = '0';
    double val, power;
    int exponent, sign, esign, decpt;

    nullen = strlen(snull);
    cptr = input;  /* pointer to start of input string */
    for (ii = 0; ii < ntodo; ii++)
    {
      cstring = cptr;
      /* temporarily insert a null terminator at end of the string */
      tpos = cptr + twidth;
      tempstore = *tpos;
      *tpos = 0;

      /* check if null value is defined, and if the    */
      /* column string is identical to the null string */
      if (snull[0] != ASCII_NULL_UNDEFINED && 
         !strncmp(snull, cptr, nullen) )
      {
        if (nullcheck)  
        {
          *anynull = 1;    
          if (nullcheck == 1)
            output[ii] = nullval;
          else
            nullarray[ii] = 1;
        }
        cptr += twidth;
      }
      else
      {
        /* value is not the null value, so decode it */
        /* remove any embedded blank characters from the string */

        decpt = 0;
        sign = 1;
        val  = 0.;
        power = 1.;
        exponent = 0;
        esign = 1;

        while (*cptr == ' ')               /* skip leading blanks */
           cptr++;

        if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
        {
          if (*cptr == '-')
             sign = -1;

          cptr++;

          while (*cptr == ' ')         /* skip blanks between sign and value */
            cptr++;
        }

        while (*cptr >= '0' && *cptr <= '9')
        {
          val = val * 10. + *cptr - chrzero;  /* accumulate the value */
          cptr++;

          while (*cptr == ' ')         /* skip embedded blanks in the value */
            cptr++;
        }

        if (*cptr == '.' || *cptr == ',')       /* check for decimal point */
        {
          decpt = 1;       /* set flag to show there was a decimal point */
          cptr++;
          while (*cptr == ' ')         /* skip any blanks */
            cptr++;

          while (*cptr >= '0' && *cptr <= '9')
          {
            val = val * 10. + *cptr - chrzero;  /* accumulate the value */
            power = power * 10.;
            cptr++;

            while (*cptr == ' ')         /* skip embedded blanks in the value */
              cptr++;
          }
        }

        if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
        {
          cptr++;
          while (*cptr == ' ')         /* skip blanks */
              cptr++;
  
          if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
          {
            if (*cptr == '-')
               esign = -1;

            cptr++;

            while (*cptr == ' ')        /* skip blanks between sign and exp */
              cptr++;
          }

          while (*cptr >= '0' && *cptr <= '9')
          {
            exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
            cptr++;

            while (*cptr == ' ')         /* skip embedded blanks */
              cptr++;
          }
        }

        if (*cptr  != 0)  /* should end up at the null terminator */
        {
          snprintf(message, FLEN_ERRMSG,"Cannot read number from ASCII table");
          ffpmsg(message);
          snprintf(message, FLEN_ERRMSG,"Column field = %s.", cstring);
          ffpmsg(message);
          /* restore the char that was overwritten by the null */
          *tpos = tempstore;
          return(*status = BAD_C2D);
        }

        if (!decpt)  /* if no explicit decimal, use implied */
           power = implipower;

        dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));

        dvalue = dvalue * scale + zero;   /* apply the scaling */

        if (dvalue < DINT_MIN)
        {
            *status = OVERFLOW_ERR;
            output[ii] = INT_MIN;
        }
        else if (dvalue > DINT_MAX)
        {
            *status = OVERFLOW_ERR;
            output[ii] = INT_MAX;
        }
        else
            output[ii] = (long) dvalue;
      }
      /* restore the char that was overwritten by the null */
      *tpos = tempstore;
    }
    return(*status);
}
cfitsio/getcoll.c0000644000225700000360000005540213246025103013603 0ustar  cagordonlhea/*  This file, getcoll.c, contains routines that read data elements from   */
/*  a FITS image or table, with logical datatype.                          */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include "fitsio2.h"
/*--------------------------------------------------------------------------*/
int ffgcvl( fitsfile *fptr,   /* I - FITS file pointer                       */
            int  colnum,      /* I - number of column to read (1 = 1st col)  */
            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            char  nulval,     /* I - value for null pixels                   */
            char *array,      /* O - array of values                         */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of logical values from a column in the current FITS HDU.
  Any undefined pixels will be set equal to the value of 'nulval' unless
  nulval = 0 in which case no checks for undefined pixels will be made.
*/
{
    char cdummy;

    ffgcll( fptr, colnum, firstrow, firstelem, nelem, 1, nulval, array,
            &cdummy, anynul, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcl(  fitsfile *fptr,   /* I - FITS file pointer                       */
            int  colnum,      /* I - number of column to read (1 = 1st col)  */
            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            char *array,      /* O - array of values                         */
            int  *status)     /* IO - error status                           */
/*
  !!!! THIS ROUTINE IS DEPRECATED AND SHOULD NOT BE USED !!!!!!
                  !!!! USE ffgcvl INSTEAD  !!!!!!
  Read an array of logical values from a column in the current FITS HDU.
  No checking for null values will be performed.
*/
{
    char nulval = 0;
    int anynul;

    ffgcvl( fptr, colnum, firstrow, firstelem, nelem, nulval, array,
            &anynul, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcfl( fitsfile *fptr,   /* I - FITS file pointer                       */
            int  colnum,      /* I - number of column to read (1 = 1st col)  */
            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            char *array,      /* O - array of values                         */
            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of logical values from a column in the current FITS HDU.
*/
{
    char nulval = 0;

    ffgcll( fptr, colnum, firstrow, firstelem, nelem, 2, nulval, array,
            nularray, anynul, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcll( fitsfile *fptr,   /* I - FITS file pointer                       */
            int  colnum,      /* I - number of column to read (1 = 1st col)  */
            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
            LONGLONG  firstelem, /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            int   nultyp,     /* I - null value handling code:               */
                              /*     1: set undefined pixels = nulval        */
                              /*     2: set nularray=1 for undefined pixels  */
            char nulval,      /* I - value for null pixels if nultyp = 1     */
            char *array,      /* O - array of values                         */
            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of logical values from a column in the current FITS HDU.
*/
{
    double dtemp;
    int tcode, maxelem, hdutype, ii, nulcheck;
    long twidth, incre;
    long ntodo;
    LONGLONG repeat, startpos, elemnum, readptr, tnull, rowlen, rownum, remain, next;
    double scale, zero;
    char tform[20];
    char message[FLEN_ERRMSG];
    char snull[20];   /*  the FITS null value  */
    unsigned char buffer[DBUFFSIZE], *buffptr;

    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
        return(*status);

    if (anynul)
       *anynul = 0;

    if (nultyp == 2)      
       memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 0, &scale, &zero,
        tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
        return(*status);

    if (tcode != TLOGICAL)   
        return(*status = NOT_LOGICAL_COL);
 
    /*------------------------------------------------------------------*/
    /*  Decide whether to check for null values in the input FITS file: */
    /*------------------------------------------------------------------*/
    nulcheck = nultyp; /* by default, check for null values in the FITS file */

    if (nultyp == 1 && nulval == 0)
       nulcheck = 0;    /* calling routine does not want to check for nulls */

    /*---------------------------------------------------------------------*/
    /*  Now read the logical values from the FITS column.                  */
    /*---------------------------------------------------------------------*/

    remain = nelem;           /* remaining number of values to read */
    next = 0;                 /* next element in array to be read   */
    rownum = 0;               /* row number, relative to firstrow   */
    ntodo = (long) remain;           /* max number of elements to read at one time */

    while (ntodo)
    {
      /*
         limit the number of pixels to read at one time to the number that
         remain in the current vector.    
      */
      ntodo = (long) minvalue(ntodo, maxelem);      
      ntodo = (long) minvalue(ntodo, (repeat - elemnum));

      readptr = startpos + (rowlen * rownum) + (elemnum * incre);

      ffgi1b(fptr, readptr, ntodo, incre, buffer, status);

      /* convert from T or F to 1 or 0 */
      buffptr = buffer;
      for (ii = 0; ii < ntodo; ii++, next++, buffptr++)
      {
        if (*buffptr == 'T')
          array[next] = 1;
        else if (*buffptr =='F') 
          array[next] = 0;
        else if (*buffptr == 0)
        {
          array[next] = nulval;  /* set null values to input nulval */
          if (anynul)
              *anynul = 1;

          if (nulcheck == 2)
          {
            nularray[next] = 1;  /* set null flags */
          }
        }
        else  /* some other illegal character; return the char value */
        {
          if (*buffptr == 1) {
            /* this is an unfortunate case where the illegal value is the same
               as what we set True values to, so set the value to the character '1'
               instead, which has ASCII value 49.  */
            array[next] = 49;
          } else {
            array[next] = (char) *buffptr;
          }
        }
      }

      if (*status > 0)  /* test for error during previous read operation */
      {
	dtemp = (double) next;
        snprintf(message,FLEN_ERRMSG,
          "Error reading elements %.0f thruough %.0f of logical array (ffgcl).",
           dtemp+1., dtemp + ntodo);
        ffpmsg(message);
        return(*status);
      }

      /*--------------------------------------------*/
      /*  increment the counters for the next loop  */
      /*--------------------------------------------*/
      remain -= ntodo;
      if (remain)
      {
        elemnum += ntodo;

        if (elemnum == repeat)  /* completed a row; start on later row */
          {
            elemnum = 0;
            rownum++;
          }
      }
      ntodo = (long) remain;  /* this is the maximum number to do in next loop */

    }  /*  End of main while Loop  */

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcx(  fitsfile *fptr,  /* I - FITS file pointer                       */
            int   colnum,    /* I - number of column to write (1 = 1st col) */
            LONGLONG  frow,      /* I - first row to write (1 = 1st row)        */
            LONGLONG  fbit,      /* I - first bit to write (1 = 1st)            */
            LONGLONG  nbit,      /* I - number of bits to write                 */
            char *larray,    /* O - array of logicals corresponding to bits */
            int  *status)    /* IO - error status                           */
/*
  read an array of logical values from a specified bit or byte
  column of the binary table.    larray is set = TRUE, if the corresponding
  bit = 1, otherwise it is set to FALSE.
  The binary table column being read from must have datatype 'B' or 'X'. 
*/
{
    LONGLONG bstart;
    long offset, ndone, ii, repeat, bitloc, fbyte;
    LONGLONG  rstart, estart;
    int tcode, descrp;
    unsigned char cbuff;
    static unsigned char onbit[8] = {128,  64,  32,  16,   8,   4,   2,   1};
    tcolumn *colptr;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /*  check input parameters */
    if (nbit < 1)
        return(*status);
    else if (frow < 1)
        return(*status = BAD_ROW_NUM);
    else if (fbit < 1)
        return(*status = BAD_ELEM_NUM);

    /* position to the correct HDU */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    /* rescan header if data structure is undefined */
    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
        if ( ffrdef(fptr, status) > 0)               
            return(*status);

    fbyte = (long) ((fbit + 7) / 8);
    bitloc = (long) (fbit - 1 - ((fbit - 1) / 8 * 8));
    ndone = 0;
    rstart = frow - 1;
    estart = fbyte - 1;

    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
    colptr += (colnum - 1);     /* offset to correct column structure */

    tcode = colptr->tdatatype;

    if (abs(tcode) > TBYTE)
        return(*status = NOT_LOGICAL_COL); /* not correct datatype column */

    if (tcode > 0)
    {
        descrp = FALSE;  /* not a variable length descriptor column */
        /* N.B: REPEAT is the number of bytes, not number of bits */
        repeat = (long) colptr->trepeat;

        if (tcode == TBIT)
            repeat = (repeat + 7) / 8;  /* convert from bits to bytes */

        if (fbyte > repeat)
            return(*status = BAD_ELEM_NUM);

        /* calc the i/o pointer location to start of sequence of pixels */
        bstart = (fptr->Fptr)->datastart + ((fptr->Fptr)->rowlength * rstart) +
               colptr->tbcol + estart;
    }
    else
    {
        descrp = TRUE;  /* a variable length descriptor column */
        /* only bit arrays (tform = 'X') are supported for variable */
        /* length arrays.  REPEAT is the number of BITS in the array. */

        ffgdes(fptr, colnum, frow, &repeat, &offset, status);

        if (tcode == -TBIT)
            repeat = (repeat + 7) / 8;

        if ((fbit + nbit + 6) / 8 > repeat)
            return(*status = BAD_ELEM_NUM);

        /* calc the i/o pointer location to start of sequence of pixels */
        bstart = (fptr->Fptr)->datastart + offset + (fptr->Fptr)->heapstart + estart;
    }

    /* move the i/o pointer to the start of the pixel sequence */
    if (ffmbyt(fptr, bstart, REPORT_EOF, status) > 0)
        return(*status);

    /* read the next byte */
    while (1)
    {
      if (ffgbyt(fptr, 1, &cbuff, status) > 0)
        return(*status);

      for (ii = bitloc; (ii < 8) && (ndone < nbit); ii++, ndone++)
      {
        if(cbuff & onbit[ii])       /* test if bit is set */
          larray[ndone] = TRUE;
        else
          larray[ndone] = FALSE;
      }

      if (ndone == nbit)   /* finished all the bits */
        return(*status);

      /* not done, so get the next byte */
      if (!descrp)
      {
        estart++;
        if (estart == repeat) 
        {
          /* move the i/o pointer to the next row of pixels */
          estart = 0;
          rstart = rstart + 1;
          bstart = (fptr->Fptr)->datastart + ((fptr->Fptr)->rowlength * rstart) +
               colptr->tbcol;

          ffmbyt(fptr, bstart, REPORT_EOF, status);
        }
      }
      bitloc = 0;
    }
}
/*--------------------------------------------------------------------------*/
int ffgcxui(fitsfile *fptr,   /* I - FITS file pointer                       */
            int  colnum,      /* I - number of column to read (1 = 1st col)  */
            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
            LONGLONG  nrows,      /* I - no. of rows to read                     */
            long  input_first_bit, /* I - first bit to read (1 = 1st)        */
            int   input_nbits,     /* I - number of bits to read (<= 32)     */
            unsigned short *array, /* O - array of integer values            */
            int  *status)     /* IO - error status                           */
/*
  Read a consecutive string of bits from an 'X' or 'B' column and
  interprete them as an unsigned integer.  The number of bits must be
  less than or equal to 16 or the total number of bits in the column, 
  which ever is less.
*/
{
    int ii, firstbit, nbits, bytenum, startbit, numbits, endbit;
    int firstbyte, lastbyte, nbytes, rshift, lshift;
    unsigned short colbyte[5];
    tcolumn *colptr;
    char message[FLEN_ERRMSG];

    if (*status > 0 || nrows == 0)
        return(*status);

    /*  check input parameters */
    if (firstrow < 1)
    {
          snprintf(message,FLEN_ERRMSG, "Starting row number is less than 1: %ld (ffgcxui)",
                (long) firstrow);
          ffpmsg(message);
          return(*status = BAD_ROW_NUM);
    }
    else if (input_first_bit < 1)
    {
          snprintf(message,FLEN_ERRMSG, "Starting bit number is less than 1: %ld (ffgcxui)",
                input_first_bit);
          ffpmsg(message);
          return(*status = BAD_ELEM_NUM);
    }
    else if (input_nbits > 16)
    {
          snprintf(message, FLEN_ERRMSG,"Number of bits to read is > 16: %d (ffgcxui)",
                input_nbits);
          ffpmsg(message);
          return(*status = BAD_ELEM_NUM);
    }

    /* position to the correct HDU */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    /* rescan header if data structure is undefined */
    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
        if ( ffrdef(fptr, status) > 0)               
            return(*status);

    if ((fptr->Fptr)->hdutype != BINARY_TBL)
    {
        ffpmsg("This is not a binary table extension (ffgcxui)");
        return(*status = NOT_BTABLE);
    }

    if (colnum > (fptr->Fptr)->tfield)
    {
      snprintf(message, FLEN_ERRMSG,"Specified column number is out of range: %d (ffgcxui)",
                colnum);
        ffpmsg(message);
        snprintf(message, FLEN_ERRMSG,"  There are %d columns in this table.",
                (fptr->Fptr)->tfield );
        ffpmsg(message);

        return(*status = BAD_COL_NUM);
    }       

    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
    colptr += (colnum - 1);     /* offset to correct column structure */

    if (abs(colptr->tdatatype) > TBYTE)
    {
        ffpmsg("Can only read bits from X or B type columns. (ffgcxui)");
        return(*status = NOT_LOGICAL_COL); /* not correct datatype column */
    }

    firstbyte = (input_first_bit - 1              ) / 8 + 1;
    lastbyte  = (input_first_bit + input_nbits - 2) / 8 + 1;
    nbytes = lastbyte - firstbyte + 1;

    if (colptr->tdatatype == TBIT && 
        input_first_bit + input_nbits - 1 > (long) colptr->trepeat)
    {
        ffpmsg("Too many bits. Tried to read past width of column (ffgcxui)");
        return(*status = BAD_ELEM_NUM);
    }
    else if (colptr->tdatatype == TBYTE && lastbyte > (long) colptr->trepeat)
    {
        ffpmsg("Too many bits. Tried to read past width of column (ffgcxui)");
        return(*status = BAD_ELEM_NUM);
    }

    for (ii = 0; ii < nrows; ii++)
    {
        /* read the relevant bytes from the row */
        if (ffgcvui(fptr, colnum, firstrow+ii, firstbyte, nbytes, 0, 
               colbyte, NULL, status) > 0)
        {
             ffpmsg("Error reading bytes from column (ffgcxui)");
             return(*status);
        }

        firstbit = (input_first_bit - 1) % 8; /* modulus operator */
        nbits = input_nbits;

        array[ii] = 0;

        /* select and shift the bits from each byte into the output word */
        while(nbits)
        {
            bytenum = firstbit / 8;

            startbit = firstbit % 8;  
            numbits = minvalue(nbits, 8 - startbit);
            endbit = startbit + numbits - 1;

            rshift = 7 - endbit;
            lshift = nbits - numbits;

            array[ii] = ((colbyte[bytenum] >> rshift) << lshift) | array[ii];

            nbits -= numbits;
            firstbit += numbits;
        }
    }

    return(*status);
}

/*--------------------------------------------------------------------------*/
int ffgcxuk(fitsfile *fptr,   /* I - FITS file pointer                       */
            int  colnum,      /* I - number of column to read (1 = 1st col)  */
            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
            LONGLONG  nrows,      /* I - no. of rows to read                     */
            long  input_first_bit, /* I - first bit to read (1 = 1st)        */
            int   input_nbits,     /* I - number of bits to read (<= 32)     */
            unsigned int *array,   /* O - array of integer values            */
            int  *status)     /* IO - error status                           */
/*
  Read a consecutive string of bits from an 'X' or 'B' column and
  interprete them as an unsigned integer.  The number of bits must be
  less than or equal to 32 or the total number of bits in the column, 
  which ever is less.
*/
{
    int ii, firstbit, nbits, bytenum, startbit, numbits, endbit;
    int firstbyte, lastbyte, nbytes, rshift, lshift;
    unsigned int colbyte[5];
    tcolumn *colptr;
    char message[FLEN_ERRMSG];

    if (*status > 0 || nrows == 0)
        return(*status);

    /*  check input parameters */
    if (firstrow < 1)
    {
          snprintf(message, FLEN_ERRMSG,"Starting row number is less than 1: %ld (ffgcxuk)",
                (long) firstrow);
          ffpmsg(message);
          return(*status = BAD_ROW_NUM);
    }
    else if (input_first_bit < 1)
    {
          snprintf(message, FLEN_ERRMSG,"Starting bit number is less than 1: %ld (ffgcxuk)",
                input_first_bit);
          ffpmsg(message);
          return(*status = BAD_ELEM_NUM);
    }
    else if (input_nbits > 32)
    {
          snprintf(message, FLEN_ERRMSG,"Number of bits to read is > 32: %d (ffgcxuk)",
                input_nbits);
          ffpmsg(message);
          return(*status = BAD_ELEM_NUM);
    }

    /* position to the correct HDU */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    /* rescan header if data structure is undefined */
    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
        if ( ffrdef(fptr, status) > 0)               
            return(*status);

    if ((fptr->Fptr)->hdutype != BINARY_TBL)
    {
        ffpmsg("This is not a binary table extension (ffgcxuk)");
        return(*status = NOT_BTABLE);
    }

    if (colnum > (fptr->Fptr)->tfield)
    {
      snprintf(message, FLEN_ERRMSG,"Specified column number is out of range: %d (ffgcxuk)",
                colnum);
        ffpmsg(message);
        snprintf(message, FLEN_ERRMSG,"  There are %d columns in this table.",
                (fptr->Fptr)->tfield );
        ffpmsg(message);

        return(*status = BAD_COL_NUM);
    }       

    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
    colptr += (colnum - 1);     /* offset to correct column structure */

    if (abs(colptr->tdatatype) > TBYTE)
    {
        ffpmsg("Can only read bits from X or B type columns. (ffgcxuk)");
        return(*status = NOT_LOGICAL_COL); /* not correct datatype column */
    }

    firstbyte = (input_first_bit - 1              ) / 8 + 1;
    lastbyte  = (input_first_bit + input_nbits - 2) / 8 + 1;
    nbytes = lastbyte - firstbyte + 1;

    if (colptr->tdatatype == TBIT && 
        input_first_bit + input_nbits - 1 > (long) colptr->trepeat)
    {
        ffpmsg("Too many bits. Tried to read past width of column (ffgcxuk)");
        return(*status = BAD_ELEM_NUM);
    }
    else if (colptr->tdatatype == TBYTE && lastbyte > (long) colptr->trepeat)
    {
        ffpmsg("Too many bits. Tried to read past width of column (ffgcxuk)");
        return(*status = BAD_ELEM_NUM);
    }

    for (ii = 0; ii < nrows; ii++)
    {
        /* read the relevant bytes from the row */
        if (ffgcvuk(fptr, colnum, firstrow+ii, firstbyte, nbytes, 0, 
               colbyte, NULL, status) > 0)
        {
             ffpmsg("Error reading bytes from column (ffgcxuk)");
             return(*status);
        }

        firstbit = (input_first_bit - 1) % 8; /* modulus operator */
        nbits = input_nbits;

        array[ii] = 0;

        /* select and shift the bits from each byte into the output word */
        while(nbits)
        {
            bytenum = firstbit / 8;

            startbit = firstbit % 8;  
            numbits = minvalue(nbits, 8 - startbit);
            endbit = startbit + numbits - 1;

            rshift = 7 - endbit;
            lshift = nbits - numbits;

            array[ii] = ((colbyte[bytenum] >> rshift) << lshift) | array[ii];

            nbits -= numbits;
            firstbit += numbits;
        }
    }

    return(*status);
}
cfitsio/getcols.c0000644000225700000360000007273713246025103013624 0ustar  cagordonlhea/*  This file, getcols.c, contains routines that read data elements from   */
/*  a FITS image or table, with a character string datatype.               */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
/* stddef.h is apparently needed to define size_t */
#include 
#include 
#include "fitsio2.h"
/*--------------------------------------------------------------------------*/
int ffgcvs( fitsfile *fptr,   /* I - FITS file pointer                       */
            int  colnum,      /* I - number of column to read (1 = 1st col)  */
            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of strings to read               */
            char *nulval,     /* I - string for null pixels                  */
            char **array,     /* O - array of values that are read           */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of string values from a column in the current FITS HDU.
  Any undefined pixels will be set equal to the value of 'nulval' unless
  nulval = null in which case no checks for undefined pixels will be made.
*/
{
    char cdummy[2];

    ffgcls(fptr, colnum, firstrow, firstelem, nelem, 1, nulval,
           array, cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcfs( fitsfile *fptr,   /* I - FITS file pointer                       */
            int  colnum,      /* I - number of column to read (1 = 1st col) */
            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)        */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st) */
            LONGLONG  nelem,      /* I - number of strings to read              */
            char **array,     /* O - array of values that are read           */
            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of string values from a column in the current FITS HDU.
  Nularray will be set = 1 if the corresponding array pixel is undefined, 
  otherwise nularray will = 0.
*/
{
    char dummy[2];

    ffgcls(fptr, colnum, firstrow, firstelem, nelem, 2, dummy,
           array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcls( fitsfile *fptr,   /* I - FITS file pointer                       */
            int  colnum,      /* I - number of column to read (1 = 1st col) */
            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)        */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st) */
            LONGLONG  nelem,      /* I - number of strings to read              */
            int   nultyp,     /* I - null value handling code:               */
                              /*     1: set undefined pixels = nulval        */
                              /*     2: set nularray=1 for undefined pixels  */
            char  *nulval,    /* I - value for null pixels if nultyp = 1     */
            char **array,     /* O - array of values that are read           */
            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of string values from a column in the current FITS HDU.
  Returns a formated string value, regardless of the datatype of the column
*/
{
    int tcode, hdutype, tstatus, scaled, intcol, dwidth, nulwidth, ll, dlen;
    int equivtype;
    long ii, jj;
    tcolumn *colptr;
    char message[FLEN_ERRMSG], *carray, keyname[FLEN_KEYWORD];
    char cform[20], dispfmt[20], tmpstr[400], *flgarray, tmpnull[80];
    unsigned char byteval;
    float *earray;
    double *darray, tscale = 1.0;
    LONGLONG *llarray;

    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
        return(*status);

    /* reset position to the correct HDU if necessary */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    /* rescan header if data structure is undefined */
    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
        if ( ffrdef(fptr, status) > 0)               
            return(*status);

    if (colnum < 1 || colnum > (fptr->Fptr)->tfield)
    {
        snprintf(message, FLEN_ERRMSG,"Specified column number is out of range: %d",
                colnum);
        ffpmsg(message);
        return(*status = BAD_COL_NUM);
    }

    /* get equivalent dataype of column (only needed for TLONGLONG columns) */
    ffeqtyll(fptr, colnum, &equivtype, NULL, NULL, status);
    if (equivtype < 0) equivtype = abs(equivtype);
    
    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
    colptr += (colnum - 1);     /* offset to correct column structure */
    tcode = abs(colptr->tdatatype);

    if (tcode == TSTRING)
    {
      /* simply call the string column reading routine */
      ffgcls2(fptr, colnum, firstrow, firstelem, nelem, nultyp, nulval,
           array, nularray, anynul, status);
    }
    else if (tcode == TLOGICAL)
    {
      /* allocate memory for the array of logical values */
      carray = (char *) malloc((size_t) nelem);

      /*  call the logical column reading routine */
      ffgcll(fptr, colnum, firstrow, firstelem, nelem, nultyp, *nulval,
           carray, nularray, anynul, status); 

      if (*status <= 0)
      {
         /* convert logical values to "T", "F", or "N" (Null) */
         for (ii = 0; ii < nelem; ii++)
         {
           if (carray[ii] == 1)
              strcpy(array[ii], "T");
           else if (carray[ii] == 0)
              strcpy(array[ii], "F");
           else  /* undefined values = 2 */
              strcpy(array[ii],"N");
         }
      }

      free(carray);  /* free the memory */
    }
    else if (tcode == TCOMPLEX)
    {
      /* allocate memory for the array of double values */
      earray = (float *) calloc((size_t) (nelem * 2), sizeof(float) );
      
      ffgcle(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2,
        1, 1, FLOATNULLVALUE, earray, nularray, anynul, status);

      if (*status <= 0)
      {

         /* determine the format for the output strings */

         ffgcdw(fptr, colnum, &dwidth, status);
         dwidth = (dwidth - 3) / 2;
 
         /* use the TDISPn keyword if it exists */
         ffkeyn("TDISP", colnum, keyname, status);
         tstatus = 0;
         cform[0] = '\0';

         if (ffgkys(fptr, keyname, dispfmt, NULL, &tstatus) == 0)
         {
             /* convert the Fortran style format to a C style format */
             ffcdsp(dispfmt, cform);
         }

         if (!cform[0])
             strcpy(cform, "%14.6E");

         /* write the formated string for each value:  "(real,imag)" */
         jj = 0;
         for (ii = 0; ii < nelem; ii++)
         {
           strcpy(array[ii], "(");

           /* test for null value */
           if (earray[jj] == FLOATNULLVALUE)
           {
             strcpy(tmpstr, "NULL");
             if (nultyp == 2)
                nularray[ii] = 1;
           }
           else
             snprintf(tmpstr, 400,cform, earray[jj]);

           strncat(array[ii], tmpstr, dwidth);
           strcat(array[ii], ",");
           jj++;

           /* test for null value */
           if (earray[jj] == FLOATNULLVALUE)
           {
             strcpy(tmpstr, "NULL");
             if (nultyp == 2)
                nularray[ii] = 1;
           }
           else
             snprintf(tmpstr, 400,cform, earray[jj]);

           strncat(array[ii], tmpstr, dwidth);
           strcat(array[ii], ")");
           jj++;
         }
      }

      free(earray);  /* free the memory */
    }
    else if (tcode == TDBLCOMPLEX)
    {
      /* allocate memory for the array of double values */
      darray = (double *) calloc((size_t) (nelem * 2), sizeof(double) );
      
      ffgcld(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2,
        1, 1, DOUBLENULLVALUE, darray, nularray, anynul, status);

      if (*status <= 0)
      {
         /* determine the format for the output strings */

         ffgcdw(fptr, colnum, &dwidth, status);
         dwidth = (dwidth - 3) / 2;

         /* use the TDISPn keyword if it exists */
         ffkeyn("TDISP", colnum, keyname, status);
         tstatus = 0;
         cform[0] = '\0';
 
         if (ffgkys(fptr, keyname, dispfmt, NULL, &tstatus) == 0)
         {
             /* convert the Fortran style format to a C style format */
             ffcdsp(dispfmt, cform);
         }

         if (!cform[0])
            strcpy(cform, "%23.15E");

         /* write the formated string for each value:  "(real,imag)" */
         jj = 0;
         for (ii = 0; ii < nelem; ii++)
         {
           strcpy(array[ii], "(");

           /* test for null value */
           if (darray[jj] == DOUBLENULLVALUE)
           {
             strcpy(tmpstr, "NULL");
             if (nultyp == 2)
                nularray[ii] = 1;
           }
           else
             snprintf(tmpstr, 400,cform, darray[jj]);

           strncat(array[ii], tmpstr, dwidth);
           strcat(array[ii], ",");
           jj++;

           /* test for null value */
           if (darray[jj] == DOUBLENULLVALUE)
           {
             strcpy(tmpstr, "NULL");
             if (nultyp == 2)
                nularray[ii] = 1;
           }
           else
             snprintf(tmpstr, 400,cform, darray[jj]);

           strncat(array[ii], tmpstr, dwidth);
           strcat(array[ii], ")");
           jj++;
         }
      }

      free(darray);  /* free the memory */
    }
    else if (tcode == TLONGLONG && equivtype == TLONGLONG)
    {
      /* allocate memory for the array of LONGLONG values */
      llarray = (LONGLONG *) calloc((size_t) nelem, sizeof(LONGLONG) );
      flgarray = (char *) calloc((size_t) nelem, sizeof(char) );
      dwidth = 20;  /* max width of displayed long long integer value */

      if (ffgcfjj(fptr, colnum, firstrow, firstelem, nelem,
            llarray, flgarray, anynul, status) > 0)
      {
         free(flgarray);
         free(llarray);
         return(*status);
      }

      /* write the formated string for each value */
      if (nulval) {
          strcpy(tmpnull, nulval);
          nulwidth = strlen(nulval);
      } else {
          strcpy(tmpnull, " ");
          nulwidth = 1;
      }

      for (ii = 0; ii < nelem; ii++)
      {
           if ( flgarray[ii] )
           {
              *array[ii] = '\0';
              if (dwidth < nulwidth)
                  strncat(array[ii], tmpnull, dwidth);
              else
                  sprintf(array[ii],"%*s",dwidth,tmpnull);
		  
              if (nultyp == 2)
	          nularray[ii] = 1;
           }
           else
           {	   

#if defined(_MSC_VER)
    /* Microsoft Visual C++ 6.0 uses '%I64d' syntax  for 8-byte integers */
        snprintf(tmpstr, 400,"%20I64d", llarray[ii]);
#elif (USE_LL_SUFFIX == 1)
        snprintf(tmpstr, 400,"%20lld", llarray[ii]);
#else
        snprintf(tmpstr, 400,"%20ld", llarray[ii]);
#endif
              *array[ii] = '\0';
              strncat(array[ii], tmpstr, 20);
           }
      }

      free(flgarray);
      free(llarray);  /* free the memory */

    }
    else
    {
      /* allocate memory for the array of double values */
      darray = (double *) calloc((size_t) nelem, sizeof(double) );
      
      /* read all other numeric type columns as doubles */
      if (ffgcld(fptr, colnum, firstrow, firstelem, nelem, 1, nultyp, 
           DOUBLENULLVALUE, darray, nularray, anynul, status) > 0)
      {
         free(darray);
         return(*status);
      }

      /* determine the format for the output strings */

      ffgcdw(fptr, colnum, &dwidth, status);

      /* check if  column is scaled */
      ffkeyn("TSCAL", colnum, keyname, status);
      tstatus = 0;
      scaled = 0;
      if (ffgkyd(fptr, keyname, &tscale, NULL, &tstatus) == 0)
      {
            if (tscale != 1.0)
                scaled = 1;    /* yes, this is a scaled column */
      }

      intcol = 0;
      if (tcode <= TLONG && !scaled)
             intcol = 1;   /* this is an unscaled integer column */

      /* use the TDISPn keyword if it exists */
      ffkeyn("TDISP", colnum, keyname, status);
      tstatus = 0;
      cform[0] = '\0';

      if (ffgkys(fptr, keyname, dispfmt, NULL, &tstatus) == 0)
      {
           /* convert the Fortran style TDISPn to a C style format */
           ffcdsp(dispfmt, cform);
      }

      if (!cform[0])
      {
            /* no TDISPn keyword; use TFORMn instead */

            ffkeyn("TFORM", colnum, keyname, status);
            ffgkys(fptr, keyname, dispfmt, NULL, status);

            if (scaled && tcode <= TSHORT)
            {
                  /* scaled short integer column == float */
                  strcpy(cform, "%#14.6G");
            }
            else if (scaled && tcode == TLONG)
            {
                  /* scaled long integer column == double */
                  strcpy(cform, "%#23.15G");
            }
            else if (scaled && tcode == TLONGLONG)
            {
                  /* scaled long long integer column == double */
                  strcpy(cform, "%#23.15G");
            }
            else
            {
               ffghdt(fptr, &hdutype, status);
               if (hdutype == ASCII_TBL)
               {
                  /* convert the Fortran style TFORMn to a C style format */
                  ffcdsp(dispfmt, cform);
               }
               else
               {
                 /* this is a binary table, need to convert the format */
                  if (tcode == TBIT) {            /* 'X' */
                     strcpy(cform, "%4d");
                  } else if (tcode == TBYTE) {    /* 'B' */
                     strcpy(cform, "%4d");
                  } else if (tcode == TSHORT) {   /* 'I' */
                     strcpy(cform, "%6d");
                  } else if (tcode == TLONG) {    /* 'J' */
                     strcpy(cform, "%11.0f");
                     intcol = 0;  /* needed to support unsigned int */
                  } else if (tcode == TFLOAT) {   /* 'E' */
                     strcpy(cform, "%#14.6G");
                  } else if (tcode == TDOUBLE) {  /* 'D' */
                     strcpy(cform, "%#23.15G");
                  }
               }
            }
      } 

      if (nulval) {
          strcpy(tmpnull, nulval);
          nulwidth = strlen(nulval);
      } else {
          strcpy(tmpnull, " ");
          nulwidth = 1;
      }

      /* write the formated string for each value */
      for (ii = 0; ii < nelem; ii++)
      {
           if (tcode == TBIT)
           {
               byteval = (char) darray[ii];

               for (ll=0; ll < 8; ll++)
               {
                   if ( ((unsigned char) (byteval << ll)) >> 7 )
                       *(array[ii] + ll) = '1';
                   else
                       *(array[ii] + ll) = '0';
               }
               *(array[ii] + 8) = '\0';
           }
           /* test for null value */
           else if ( (nultyp == 1 && darray[ii] == DOUBLENULLVALUE) ||
                (nultyp == 2 && nularray[ii]) )
           {
              *array[ii] = '\0';
              if (dwidth < nulwidth)
                  strncat(array[ii], tmpnull, dwidth);
              else
                  sprintf(array[ii],"%*s",dwidth,tmpnull);
           }
           else
           {	   
              if (intcol) {
                snprintf(tmpstr, 400,cform, (int) darray[ii]);
              } else {
                snprintf(tmpstr, 400,cform, darray[ii]);
              }
	      
              /* fill field with '*' if number is too wide */
              dlen = strlen(tmpstr);
	      if (dlen > dwidth) {
	         memset(tmpstr, '*', dwidth);
              }

              *array[ii] = '\0';
              strncat(array[ii], tmpstr, dwidth);
           }
      }

      free(darray);  /* free the memory */
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcdw( fitsfile *fptr,   /* I - FITS file pointer                       */
            int  colnum,      /* I - number of column (1 = 1st col)      */
            int  *width,      /* O - display width                       */
            int  *status)     /* IO - error status                           */
/*
  Get Column Display Width.
*/
{
    tcolumn *colptr;
    char *cptr;
    char message[FLEN_ERRMSG], keyname[FLEN_KEYWORD], dispfmt[20];
    int tcode, hdutype, tstatus, scaled;
    double tscale;

    if (*status > 0)  /* inherit input status value if > 0 */
        return(*status);

    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    if (colnum < 1 || colnum > (fptr->Fptr)->tfield)
    {
        snprintf(message, FLEN_ERRMSG,"Specified column number is out of range: %d",
                colnum);
        ffpmsg(message);
        return(*status = BAD_COL_NUM);
    }

    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
    colptr += (colnum - 1);     /* offset to correct column structure */
    tcode = abs(colptr->tdatatype);

    /* use the TDISPn keyword if it exists */
    ffkeyn("TDISP", colnum, keyname, status);

    *width = 0;
    tstatus = 0;
    if (ffgkys(fptr, keyname, dispfmt, NULL, &tstatus) == 0)
    {
          /* parse TDISPn get the display width */
          cptr = dispfmt;
          while(*cptr == ' ') /* skip leading blanks */
              cptr++;

          if (*cptr == 'A' || *cptr == 'a' ||
              *cptr == 'I' || *cptr == 'i' ||
              *cptr == 'O' || *cptr == 'o' ||
              *cptr == 'Z' || *cptr == 'z' ||
              *cptr == 'F' || *cptr == 'f' ||
              *cptr == 'E' || *cptr == 'e' ||
              *cptr == 'D' || *cptr == 'd' ||
              *cptr == 'G' || *cptr == 'g')
          {

            while(!isdigit((int) *cptr) && *cptr != '\0') /* find 1st digit */
              cptr++;

            *width = atoi(cptr);
            if (tcode >= TCOMPLEX)
              *width = (2 * (*width)) + 3;
          }
    }

    if (*width == 0)
    {
        /* no valid TDISPn keyword; use TFORMn instead */

        ffkeyn("TFORM", colnum, keyname, status);
        ffgkys(fptr, keyname, dispfmt, NULL, status);

        /* check if  column is scaled */
        ffkeyn("TSCAL", colnum, keyname, status);
        tstatus = 0;
        scaled = 0;

        if (ffgkyd(fptr, keyname, &tscale, NULL, &tstatus) == 0)
        {
            if (tscale != 1.0)
                scaled = 1;    /* yes, this is a scaled column */
        }

        if (scaled && tcode <= TSHORT)
        {
            /* scaled short integer col == float; default format is 14.6G */
            *width = 14;
        }
        else if (scaled && tcode == TLONG)
        {
            /* scaled long integer col == double; default format is 23.15G */
            *width = 23;
        }
        else if (scaled && tcode == TLONGLONG)
        {
            /* scaled long long integer col == double; default format is 23.15G */
            *width = 23;
        }

        else
        {
           ffghdt(fptr, &hdutype, status);  /* get type of table */
           if (hdutype == ASCII_TBL)
           {
              /* parse TFORMn get the display width */
              cptr = dispfmt;
              while(!isdigit((int) *cptr) && *cptr != '\0') /* find 1st digit */
                 cptr++;

              *width = atoi(cptr);
           }
           else
           {
                 /* this is a binary table */
                  if (tcode == TBIT)           /* 'X' */
                     *width = 8;
                  else if (tcode == TBYTE)     /* 'B' */
                     *width = 4;
                  else if (tcode == TSHORT)    /* 'I' */
                     *width = 6;
                  else if (tcode == TLONG)     /* 'J' */
                     *width = 11;
                  else if (tcode == TLONGLONG) /* 'K' */
                     *width = 20;
                  else if (tcode == TFLOAT)    /* 'E' */
                     *width = 14;
                  else if (tcode == TDOUBLE)   /* 'D' */
                     *width = 23;
                  else if (tcode == TCOMPLEX)  /* 'C' */
                     *width = 31;
                  else if (tcode == TDBLCOMPLEX)  /* 'M' */
                     *width = 49;
                  else if (tcode == TLOGICAL)  /* 'L' */
                     *width = 1;
                  else if (tcode == TSTRING)   /* 'A' */
                  {
		    int typecode;
		    long int repeat = 0, rwidth = 0;
		    int gstatus = 0;

		    /* Deal with possible vector string with repeat / width  by parsing
		       the TFORM=rAw keyword */
		    if (ffgtcl(fptr, colnum, &typecode, &repeat, &rwidth, &gstatus) == 0 &&
			rwidth >= 1 && rwidth < repeat) {
		      *width = rwidth;

		    } else {
		      
		      /* Hmmm, we couldn't parse the TFORM keyword by standard, so just do
			 simple parsing */
		      cptr = dispfmt;
		      while(!isdigit((int) *cptr) && *cptr != '\0') 
			cptr++;
		      
		      *width = atoi(cptr);
		    }

                    if (*width < 1)
                         *width = 1;  /* default is at least 1 column */
                  }
            }
        }
    } 
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcls2 ( fitsfile *fptr,   /* I - FITS file pointer                       */
            int  colnum,      /* I - number of column to read (1 = 1st col) */
            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)        */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st) */
            LONGLONG  nelem,      /* I - number of strings to read              */
            int   nultyp,     /* I - null value handling code:               */
                              /*     1: set undefined pixels = nulval        */
                              /*     2: set nularray=1 for undefined pixels  */
            char  *nulval,    /* I - value for null pixels if nultyp = 1     */
            char **array,     /* O - array of values that are read           */
            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of string values from a column in the current FITS HDU.
*/
{
    double dtemp;
    long nullen; 
    int tcode, maxelem, hdutype, nulcheck;
    long twidth, incre;
    long ii, jj, ntodo;
    LONGLONG repeat, startpos, elemnum, readptr, tnull, rowlen, rownum, remain, next;
    double scale, zero;
    char tform[20];
    char message[FLEN_ERRMSG];
    char snull[20];   /*  the FITS null value  */
    tcolumn *colptr;

    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
    char *buffer, *arrayptr;

    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
        return(*status);

    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    if (anynul)
        *anynul = 0;

    if (nultyp == 2)
        memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if (colnum < 1 || colnum > (fptr->Fptr)->tfield)
    {
        snprintf(message, FLEN_ERRMSG,"Specified column number is out of range: %d",
                colnum);
        ffpmsg(message);
        return(*status = BAD_COL_NUM);
    }

    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
    colptr += (colnum - 1);     /* offset to correct column structure */
    tcode = colptr->tdatatype;

    if (tcode == -TSTRING) /* variable length column in a binary table? */
    {
      /* only read a single string; ignore value of firstelem */

      if (ffgcprll( fptr, colnum, firstrow, 1, 1, 0, &scale, &zero,
        tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
        return(*status);

      remain = 1;
      twidth = (long) repeat;  
    }
    else if (tcode == TSTRING)
    {
      if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 0, &scale, &zero,
        tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
        return(*status);

      /* if string length is greater than a FITS block (2880 char) then must */
      /* only read 1 string at a time, to force reading by ffgbyt instead of */
      /* ffgbytoff (ffgbytoff can't handle this case) */
      if (twidth > IOBUFLEN) {
        maxelem = 1;
        incre = twidth;
        repeat = 1;
      }   

      remain = nelem;
    }
    else
        return(*status = NOT_ASCII_COL);

    nullen = strlen(snull);   /* length of the undefined pixel string */
    if (nullen == 0)
        nullen = 1;
 
    /*------------------------------------------------------------------*/
    /*  Decide whether to check for null values in the input FITS file: */
    /*------------------------------------------------------------------*/
    nulcheck = nultyp; /* by default check for null values in the FITS file */

    if (nultyp == 1 && nulval == 0)
       nulcheck = 0;    /* calling routine does not want to check for nulls */

    else if (nultyp == 1 && nulval && nulval[0] == 0)
       nulcheck = 0;    /* calling routine does not want to check for nulls */

    else if (snull[0] == ASCII_NULL_UNDEFINED)
       nulcheck = 0;   /* null value string in ASCII table not defined */

    else if (nullen > twidth)
       nulcheck = 0;   /* null value string is longer than width of column  */
                       /* thus impossible for any column elements to = null */

    /*---------------------------------------------------------------------*/
    /*  Now read the strings one at a time from the FITS column.           */
    /*---------------------------------------------------------------------*/
    next = 0;                 /* next element in array to be read  */
    rownum = 0;               /* row number, relative to firstrow     */

    while (remain)
    {
      /* limit the number of pixels to process at one time to the number that
         will fit in the buffer space or to the number of pixels that remain
         in the current vector, which ever is smaller.
      */
      ntodo = (long) minvalue(remain, maxelem);      
      ntodo = (long) minvalue(ntodo, (repeat - elemnum));

      readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);
      ffmbyt(fptr, readptr, REPORT_EOF, status);  /* move to read position */

      /* read the array of strings from the FITS file into the buffer */

      if (incre == twidth)
         ffgbyt(fptr, ntodo * twidth, cbuff, status);
      else
         ffgbytoff(fptr, twidth, ntodo, incre - twidth, cbuff, status);

      /* copy from the buffer into the user's array of strings */
      /* work backwards from last char of last string to 1st char of 1st */

      buffer = ((char *) cbuff) + (ntodo * twidth) - 1;

      for (ii = (long) (next + ntodo - 1); ii >= next; ii--)
      {
         arrayptr = array[ii] + twidth - 1;

         for (jj = twidth - 1; jj > 0; jj--)  /* ignore trailing blanks */
         {
            if (*buffer == ' ')
            {
              buffer--;
              arrayptr--;
            }
            else
              break;
         }
         *(arrayptr + 1) = 0;  /* write the string terminator */
         
         for (; jj >= 0; jj--)    /* copy the string itself */
         {
           *arrayptr = *buffer;
           buffer--;
           arrayptr--;
         }

         /* check if null value is defined, and if the   */
         /* column string is identical to the null string */
         if (nulcheck && !strncmp(snull, array[ii], nullen) )
         {
           *anynul = 1;   /* this is a null value */
           if (nultyp == 1) {
	   
	     if (nulval)
                strcpy(array[ii], nulval);
	     else
	        strcpy(array[ii], " ");
	     
           } else
             nularray[ii] = 1;
         }
      }
    
      if (*status > 0)  /* test for error during previous read operation */
      {
         dtemp = (double) next;
         snprintf(message,FLEN_ERRMSG,
          "Error reading elements %.0f thru %.0f of data array (ffpcls).",
             dtemp+1., dtemp+ntodo);

         ffpmsg(message);
         return(*status);
      }

      /*--------------------------------------------*/
      /*  increment the counters for the next loop  */
      /*--------------------------------------------*/
      next += ntodo;
      remain -= ntodo;
      if (remain)
      {
          elemnum += ntodo;
          if (elemnum == repeat)  /* completed a row; start on next row */
          {
              elemnum = 0;
              rownum++;
          }
      }
    }  /*  End of main while Loop  */

    return(*status);
}

cfitsio/getcolsb.c0000644000225700000360000022345413246025103013760 0ustar  cagordonlhea/*  This file, getcolsb.c, contains routines that read data elements from   */
/*  a FITS image or table, with signed char (signed byte) data type.        */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include 
#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int ffgpvsb(fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            signed char nulval, /* I - value for undefined pixels            */
            signed char *array, /* O - array of values that are returned     */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Undefined elements will be set equal to NULVAL, unless NULVAL=0
  in which case no checking for undefined values will be performed.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    long row;
    char cdummy;
    int nullcheck = 1;
    signed char nullvalue;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */
         nullvalue = nulval;  /* set local variable */

        fits_read_compressed_pixels(fptr, TSBYTE, firstelem, nelem,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }
    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgclsb(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
               array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgpfsb(fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            signed char *array, /* O - array of values that are returned     */
            char *nularray,   /* O - array of null pixel flags               */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Any undefined pixels in the returned array will be set = 0 and the 
  corresponding nularray value will be set = 1.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    long row;
    int nullcheck = 2;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_read_compressed_pixels(fptr, TSBYTE, firstelem, nelem,
            nullcheck, NULL, array, nularray, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgclsb(fptr, 2, row, firstelem, nelem, 1, 2, 0,
               array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffg2dsb(fitsfile *fptr, /* I - FITS file pointer                       */
           long  group,     /* I - group to read (1 = 1st group)           */
           signed char nulval,   /* set undefined pixels equal to this     */
           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
           signed char *array,   /* O - array to be filled and returned    */
           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
           int  *status)    /* IO - error status                           */
/*
  Read an entire 2-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being read).  Any null
  values in the array will be set equal to the value of nulval, unless
  nulval = 0 in which case no null checking will be performed.
*/
{
    /* call the 3D reading routine, with the 3rd dimension = 1 */

    ffg3dsb(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, 
           anynul, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffg3dsb(fitsfile *fptr, /* I - FITS file pointer                       */
           long  group,     /* I - group to read (1 = 1st group)           */
           signed char nulval,   /* set undefined pixels equal to this     */
           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
           LONGLONG  nrows,     /* I - number of rows in each plane of array   */
           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
           LONGLONG  naxis3,    /* I - FITS image NAXIS3 value                 */
           signed char *array,   /* O - array to be filled and returned    */
           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
           int  *status)    /* IO - error status                           */
/*
  Read an entire 3-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being read).  Any null
  values in the array will be set equal to the value of nulval, unless
  nulval = 0 in which case no null checking will be performed.
*/
{
    long tablerow, ii, jj;
    LONGLONG  nfits, narray;
    char cdummy;
    int  nullcheck = 1;
    long inc[] = {1,1,1};
    LONGLONG fpixel[] = {1,1,1};
    LONGLONG lpixel[3];
    signed char nullvalue;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        lpixel[0] = ncols;
        lpixel[1] = nrows;
        lpixel[2] = naxis3;
        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_img(fptr, TSBYTE, fpixel, lpixel, inc,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */
    tablerow=maxvalue(1,group);

    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
    {
       /* all the image pixels are contiguous, so read all at once */
       ffgclsb(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval,
               array, &cdummy, anynul, status);
       return(*status);
    }

    if (ncols < naxis1 || nrows < naxis2)
       return(*status = BAD_DIMEN);

    nfits = 1;   /* next pixel in FITS image to read */
    narray = 0;  /* next pixel in output array to be filled */

    /* loop over naxis3 planes in the data cube */
    for (jj = 0; jj < naxis3; jj++)
    {
      /* loop over the naxis2 rows in the FITS image, */
      /* reading naxis1 pixels to each row            */

      for (ii = 0; ii < naxis2; ii++)
      {
       if (ffgclsb(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval,
          &array[narray], &cdummy, anynul, status) > 0)
          return(*status);

       nfits += naxis1;
       narray += ncols;
      }
      narray += (nrows - naxis2) * ncols;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsvsb(fitsfile *fptr, /* I - FITS file pointer                        */
           int  colnum,    /* I - number of the column to read (1 = 1st)    */
           int naxis,      /* I - number of dimensions in the FITS array    */
           long  *naxes,   /* I - size of each dimension                    */
           long  *blc,     /* I - 'bottom left corner' of the subsection    */
           long  *trc,     /* I - 'top right corner' of the subsection      */
           long  *inc,     /* I - increment to be applied in each dimension */
           signed char nulval, /* I - value to set undefined pixels         */
           signed char *array, /* O - array to be filled and returned       */
           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
           int  *status)   /* IO - error status                             */
/*
  Read a subsection of data values from an image or a table column.
  This routine is set up to handle a maximum of nine dimensions.
*/
{
    long ii, i0, i1, i2, i3, i4, i5, i6, i7, i8, row, rstr, rstp, rinc;
    long str[9], stp[9], incr[9], dir[9];
    long nelem, nultyp, ninc, numcol;
    LONGLONG felem, dsize[10], blcll[9], trcll[9];
    int hdutype, anyf;
    char ldummy, msg[FLEN_ERRMSG];
    int  nullcheck = 1;
    signed char nullvalue;

    if (naxis < 1 || naxis > 9)
    {
        snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvsb is out of range", naxis);
        ffpmsg(msg);
        return(*status = BAD_DIMEN);
    }

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        for (ii=0; ii < naxis; ii++) {
	    blcll[ii] = blc[ii];
	    trcll[ii] = trc[ii];
	}

        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_img(fptr, TSBYTE, blcll, trcll, inc,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

/*
    if this is a primary array, then the input COLNUM parameter should
    be interpreted as the row number, and we will alway read the image
    data from column 2 (any group parameters are in column 1).
*/
    if (ffghdt(fptr, &hdutype, status) > 0)
        return(*status);

    if (hdutype == IMAGE_HDU)
    {
        /* this is a primary array, or image extension */
        if (colnum == 0)
        {
            rstr = 1;
            rstp = 1;
        }
        else
        {
            rstr = colnum;
            rstp = colnum;
        }
        rinc = 1;
        numcol = 2;
    }
    else
    {
        /* this is a table, so the row info is in the (naxis+1) elements */
        rstr = blc[naxis];
        rstp = trc[naxis];
        rinc = inc[naxis];
        numcol = colnum;
    }

    nultyp = 1;
    if (anynul)
        *anynul = FALSE;

    i0 = 0;
    for (ii = 0; ii < 9; ii++)
    {
        str[ii] = 1;
        stp[ii] = 1;
        incr[ii] = 1;
        dsize[ii] = 1;
        dir[ii] = 1;
    }

    for (ii = 0; ii < naxis; ii++)
    {
      if (trc[ii] < blc[ii])
      {
        if (hdutype == IMAGE_HDU)
        {
           dir[ii] = -1;
        }
        else
        {
          snprintf(msg, FLEN_ERRMSG,"ffgsvsb: illegal range specified for axis %ld", ii + 1);
          ffpmsg(msg);
          return(*status = BAD_PIX_NUM);
        }
      }

      str[ii] = blc[ii];
      stp[ii] = trc[ii];
      incr[ii] = inc[ii];
      dsize[ii + 1] = dsize[ii] * naxes[ii];
      dsize[ii] = dsize[ii] * dir[ii];
    }
    dsize[naxis] = dsize[naxis] * dir[naxis];

    if (naxis == 1 && naxes[0] == 1)
    {
      /* This is not a vector column, so read all the rows at once */
      nelem = (rstp - rstr) / rinc + 1;
      ninc = rinc;
      rstp = rstr;
    }
    else
    {
      /* have to read each row individually, in all dimensions */
      nelem = (stp[0]*dir[0] - str[0]*dir[0]) / inc[0] + 1;
      ninc = incr[0] * dir[0];
    }

    for (row = rstr; row <= rstp; row += rinc)
    {
     for (i8 = str[8]*dir[8]; i8 <= stp[8]*dir[8]; i8 += incr[8])
     {
      for (i7 = str[7]*dir[7]; i7 <= stp[7]*dir[7]; i7 += incr[7])
      {
       for (i6 = str[6]*dir[6]; i6 <= stp[6]*dir[6]; i6 += incr[6])
       {
        for (i5 = str[5]*dir[5]; i5 <= stp[5]*dir[5]; i5 += incr[5])
        {
         for (i4 = str[4]*dir[4]; i4 <= stp[4]*dir[4]; i4 += incr[4])
         {
          for (i3 = str[3]*dir[3]; i3 <= stp[3]*dir[3]; i3 += incr[3])
          {
           for (i2 = str[2]*dir[2]; i2 <= stp[2]*dir[2]; i2 += incr[2])
           {
            for (i1 = str[1]*dir[1]; i1 <= stp[1]*dir[1]; i1 += incr[1])
            {

              felem=str[0] + (i1 - dir[1]) * dsize[1] + (i2 - dir[2]) * dsize[2] + 
                             (i3 - dir[3]) * dsize[3] + (i4 - dir[4]) * dsize[4] +
                             (i5 - dir[5]) * dsize[5] + (i6 - dir[6]) * dsize[6] +
                             (i7 - dir[7]) * dsize[7] + (i8 - dir[8]) * dsize[8];

              if ( ffgclsb(fptr, numcol, row, felem, nelem, ninc, nultyp,
                   nulval, &array[i0], &ldummy, &anyf, status) > 0)
                   return(*status);

              if (anyf && anynul)
                  *anynul = TRUE;

              i0 += nelem;
            }
           }
          }
         }
        }
       }
      }
     }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsfsb(fitsfile *fptr, /* I - FITS file pointer                        */
           int  colnum,    /* I - number of the column to read (1 = 1st)    */
           int naxis,      /* I - number of dimensions in the FITS array    */
           long  *naxes,   /* I - size of each dimension                    */
           long  *blc,     /* I - 'bottom left corner' of the subsection    */
           long  *trc,     /* I - 'top right corner' of the subsection      */
           long  *inc,     /* I - increment to be applied in each dimension */
           signed char *array,   /* O - array to be filled and returned     */
           char *flagval,  /* O - set to 1 if corresponding value is null   */
           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
           int  *status)   /* IO - error status                             */
/*
  Read a subsection of data values from an image or a table column.
  This routine is set up to handle a maximum of nine dimensions.
*/
{
    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
    long str[9],stp[9],incr[9],dsize[10];
    LONGLONG blcll[9], trcll[9];
    long felem, nelem, nultyp, ninc, numcol;
    int hdutype, anyf;
    signed char nulval = 0;
    char msg[FLEN_ERRMSG];
    int  nullcheck = 2;

    if (naxis < 1 || naxis > 9)
    {
        snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvsb is out of range", naxis);
        ffpmsg(msg);
        return(*status = BAD_DIMEN);
    }

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        for (ii=0; ii < naxis; ii++) {
	    blcll[ii] = blc[ii];
	    trcll[ii] = trc[ii];
	}

        fits_read_compressed_img(fptr, TSBYTE, blcll, trcll, inc,
            nullcheck, NULL, array, flagval, anynul, status);
        return(*status);
    }

/*
    if this is a primary array, then the input COLNUM parameter should
    be interpreted as the row number, and we will alway read the image
    data from column 2 (any group parameters are in column 1).
*/
    if (ffghdt(fptr, &hdutype, status) > 0)
        return(*status);

    if (hdutype == IMAGE_HDU)
    {
        /* this is a primary array, or image extension */
        if (colnum == 0)
        {
            rstr = 1;
            rstp = 1;
        }
        else
        {
            rstr = colnum;
            rstp = colnum;
        }
        rinc = 1;
        numcol = 2;
    }
    else
    {
        /* this is a table, so the row info is in the (naxis+1) elements */
        rstr = blc[naxis];
        rstp = trc[naxis];
        rinc = inc[naxis];
        numcol = colnum;
    }

    nultyp = 2;
    if (anynul)
        *anynul = FALSE;

    i0 = 0;
    for (ii = 0; ii < 9; ii++)
    {
        str[ii] = 1;
        stp[ii] = 1;
        incr[ii] = 1;
        dsize[ii] = 1;
    }

    for (ii = 0; ii < naxis; ii++)
    {
      if (trc[ii] < blc[ii])
      {
        snprintf(msg, FLEN_ERRMSG,"ffgsvsb: illegal range specified for axis %ld", ii + 1);
        ffpmsg(msg);
        return(*status = BAD_PIX_NUM);
      }

      str[ii] = blc[ii];
      stp[ii] = trc[ii];
      incr[ii] = inc[ii];
      dsize[ii + 1] = dsize[ii] * naxes[ii];
    }

    if (naxis == 1 && naxes[0] == 1)
    {
      /* This is not a vector column, so read all the rows at once */
      nelem = (rstp - rstr) / rinc + 1;
      ninc = rinc;
      rstp = rstr;
    }
    else
    {
      /* have to read each row individually, in all dimensions */
      nelem = (stp[0] - str[0]) / inc[0] + 1;
      ninc = incr[0];
    }

    for (row = rstr; row <= rstp; row += rinc)
    {
     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
     {
      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
      {
       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
       {
        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
        {
         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
         {
          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
          {
           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
           {
            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
            {
              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];

              if ( ffgclsb(fptr, numcol, row, felem, nelem, ninc, nultyp,
                   nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
                   return(*status);

              if (anyf && anynul)
                  *anynul = TRUE;

              i0 += nelem;
            }
           }
          }
         }
        }
       }
      }
     }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffggpsb( fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            long  firstelem,  /* I - first vector element to read (1 = 1st)  */
            long  nelem,      /* I - number of values to read                */
            signed char *array,   /* O - array of values that are returned   */
            int  *status)     /* IO - error status                           */
/*
  Read an array of group parameters from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
*/
{
    long row;
    int idummy;
    char cdummy;
    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgclsb(fptr, 1, row, firstelem, nelem, 1, 1, 0,
               array, &cdummy, &idummy, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcvsb(fitsfile *fptr,  /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
           signed char nulval,   /* I - value for null pixels               */
           signed char *array,   /* O - array of values that are read       */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Any undefined pixels will be set equal to the value of 'nulval' unless
  nulval = 0 in which case no checks for undefined pixels will be made.
*/
{
    char cdummy;

    ffgclsb(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
           array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcfsb(fitsfile *fptr,  /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
           signed char *array,   /* O - array of values that are read       */
           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Nularray will be set = 1 if the corresponding array pixel is undefined, 
  otherwise nularray will = 0.
*/
{
    signed char dummy = 0;

    ffgclsb(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
           array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgclsb(fitsfile *fptr,   /* I - FITS file pointer                       */
            int  colnum,      /* I - number of column to read (1 = 1st col)  */
            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
            LONGLONG firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
            int   nultyp,     /* I - null value handling code:               */
                              /*     1: set undefined pixels = nulval        */
                              /*     2: set nularray=1 for undefined pixels  */
            signed char nulval,   /* I - value for null pixels if nultyp = 1 */
            signed char *array,   /* O - array of values that are read       */
            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU.
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer be a virtual column in a 1 or more grouped FITS primary
  array or image extension.  FITSIO treats a primary array as a binary table
  with 2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.

  The output array of values will be converted from the datatype of the column 
  and will be scaled by the FITS TSCALn and TZEROn values if necessary.
*/
{
    double scale, zero, power = 1., dtemp;
    int tcode, maxelem, hdutype, xcode, decimals;
    long twidth, incre;
    long ii, xwidth, ntodo;
    int nulcheck, readcheck = 0;
    LONGLONG repeat, startpos, elemnum, readptr, tnull;
    LONGLONG rowlen, rownum, remain, next, rowincre;
    char tform[20];
    char message[FLEN_ERRMSG];
    char snull[20];   /*  the FITS null value if reading from ASCII table  */

    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
    void *buffer;

    union u_tag {
       char charval;
       signed char scharval;
    } u;

    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
        return(*status);

    buffer = cbuff;

    if (anynul)
        *anynul = 0;

    if (nultyp == 2)      
       memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if (elemincre < 0)
        readcheck = -1;  /* don't do range checking in this case */

    ffgcprll( fptr, colnum, firstrow, firstelem, nelem, readcheck, &scale, &zero,
         tform, &twidth, &tcode, &maxelem, &startpos, &elemnum, &incre,
         &repeat, &rowlen, &hdutype, &tnull, snull, status);

    /* special case: read column of T/F logicals */
    if (tcode == TLOGICAL && elemincre == 1)
    {
        u.scharval = nulval;
        ffgcll(fptr, colnum, firstrow, firstelem, nelem, nultyp,
               u.charval, (char *) array, nularray, anynul, status);

        return(*status);
    }

    if (strchr(tform,'A') != NULL) 
    {
        if (*status == BAD_ELEM_NUM)
        {
            /* ignore this error message */
            *status = 0;
            ffcmsg();   /* clear error stack */
        }

        /*  interpret a 'A' ASCII column as a 'B' byte column ('8A' == '8B') */
        /*  This is an undocumented 'feature' in CFITSIO */

        /*  we have to reset some of the values returned by ffgcpr */
        
        tcode = TBYTE;
        incre = 1;         /* each element is 1 byte wide */
        repeat = twidth;   /* total no. of chars in the col */
        twidth = 1;        /* width of each element */
        scale = 1.0;       /* no scaling */
        zero  = 0.0;
        tnull = NULL_UNDEFINED;  /* don't test for nulls */
        maxelem = DBUFFSIZE;
    }

    if (*status > 0)
        return(*status);
        
    incre *= elemincre;   /* multiply incre to just get every nth pixel */

    if (tcode == TSTRING && hdutype == ASCII_TBL) /* setup for ASCII tables */
    {
      /* get the number of implied decimal places if no explicit decmal point */
      ffasfm(tform, &xcode, &xwidth, &decimals, status); 
      for(ii = 0; ii < decimals; ii++)
        power *= 10.;
    }
    /*------------------------------------------------------------------*/
    /*  Decide whether to check for null values in the input FITS file: */
    /*------------------------------------------------------------------*/
    nulcheck = nultyp; /* by default, check for null values in the FITS file */

    if (nultyp == 1 && nulval == 0)
       nulcheck = 0;    /* calling routine does not want to check for nulls */

    else if (tcode%10 == 1 &&        /* if reading an integer column, and  */ 
            tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
            nulcheck = 0;            /* then do not check for null values. */

    else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
            nulcheck = 0;            /* Impossible null value */

    else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
            nulcheck = 0;            /* Impossible null value */

    else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
         nulcheck = 0;

    /*---------------------------------------------------------------------*/
    /*  Now read the pixels from the FITS column. If the column does not   */
    /*  have the same datatype as the output array, then we have to read   */
    /*  the raw values into a temporary buffer (of limited size).  In      */
    /*  the case of a vector colum read only 1 vector of values at a time  */
    /*  then skip to the next row if more values need to be read.          */
    /*  After reading the raw values, then call the fffXXYY routine to (1) */
    /*  test for undefined values, (2) convert the datatype if necessary,  */
    /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
    /*  scaling parameters.                                                */
    /*---------------------------------------------------------------------*/
    remain = nelem;           /* remaining number of values to read */
    next = 0;                 /* next element in array to be read   */
    rownum = 0;               /* row number, relative to firstrow   */

    while (remain)
    {
        /* limit the number of pixels to read at one time to the number that
           will fit in the buffer or to the number of pixels that remain in
           the current vector, which ever is smaller.
        */
        ntodo = (long) minvalue(remain, maxelem);
        if (elemincre >= 0)
        {
          ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));
        }
        else
        {
          ntodo = (long) minvalue(ntodo, (elemnum/(-elemincre) +1));
        }

        readptr = startpos + (rownum * rowlen) + (elemnum * (incre / elemincre));

        switch (tcode) 
        {
            case (TBYTE):
                ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) &array[next], status);
                fffi1s1((unsigned char *)&array[next], ntodo, scale, zero,
                        nulcheck, (unsigned char) tnull, nulval, &nularray[next], 
                        anynul, &array[next], status);
                break;
            case (TSHORT):
                ffgi2b(fptr, readptr, ntodo, incre, (short *) buffer, status);
                fffi2s1((short  *) buffer, ntodo, scale, zero, nulcheck, 
                       (short) tnull, nulval, &nularray[next], anynul, 
                       &array[next], status);
                break;
            case (TLONG):
                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer,
                       status);
                fffi4s1((INT32BIT *) buffer, ntodo, scale, zero, nulcheck, 
                       (INT32BIT) tnull, nulval, &nularray[next], anynul, 
                       &array[next], status);
                break;
            case (TLONGLONG):
                ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status);
                fffi8s1( (LONGLONG *) buffer, ntodo, scale, zero, 
                           nulcheck, tnull, nulval, &nularray[next], 
                            anynul, &array[next], status);
                break;
            case (TFLOAT):
                ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
                fffr4s1((float  *) buffer, ntodo, scale, zero, nulcheck, 
                       nulval, &nularray[next], anynul, 
                       &array[next], status);
                break;
            case (TDOUBLE):
                ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
                fffr8s1((double *) buffer, ntodo, scale, zero, nulcheck, 
                          nulval, &nularray[next], anynul, 
                          &array[next], status);
                break;
            case (TSTRING):
                ffmbyt(fptr, readptr, REPORT_EOF, status);
       
                if (incre == twidth)    /* contiguous bytes */
                     ffgbyt(fptr, ntodo * twidth, buffer, status);
                else
                     ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
                               status);

                /* interpret the string as an ASCII formated number */
                fffstrs1((char *) buffer, ntodo, scale, zero, twidth, power,
                      nulcheck, snull, nulval, &nularray[next], anynul,
                      &array[next], status);
                break;

            default:  /*  error trap for invalid column format */
                snprintf(message, FLEN_ERRMSG,
                   "Cannot read bytes from column %d which has format %s",
                    colnum, tform);
                ffpmsg(message);
                if (hdutype == ASCII_TBL)
                    return(*status = BAD_ATABLE_FORMAT);
                else
                    return(*status = BAD_BTABLE_FORMAT);

        } /* End of switch block */

        /*-------------------------*/
        /*  Check for fatal error  */
        /*-------------------------*/
        if (*status > 0)  /* test for error during previous read operation */
        {
	  dtemp = (double) next;
          if (hdutype > 0)
            snprintf(message,FLEN_ERRMSG,
            "Error reading elements %.0f thru %.0f from column %d (ffgclsb).",
              dtemp+1., dtemp+ntodo, colnum);
          else
            snprintf(message,FLEN_ERRMSG,
            "Error reading elements %.0f thru %.0f from image (ffgclsb).",
              dtemp+1., dtemp+ntodo);

         ffpmsg(message);
         return(*status);
        }

        /*--------------------------------------------*/
        /*  increment the counters for the next loop  */
        /*--------------------------------------------*/
        remain -= ntodo;
        if (remain)
        {
            next += ntodo;
            elemnum = elemnum + (ntodo * elemincre);

            if (elemnum >= repeat)  /* completed a row; start on later row */
            {
                rowincre = elemnum / repeat;
                rownum += rowincre;
                elemnum = elemnum - (rowincre * repeat);
            }
            else if (elemnum < 0)  /* completed a row; start on a previous row */
            {
                rowincre = (-elemnum - 1) / repeat + 1;
                rownum -= rowincre;
                elemnum = (rowincre * repeat) + elemnum;
            }
        }
    }  /*  End of main while Loop  */


    /*--------------------------------*/
    /*  check for numerical overflow  */
    /*--------------------------------*/
    if (*status == OVERFLOW_ERR)
    {
        ffpmsg(
        "Numerical overflow during type conversion while reading FITS data.");
        *status = NUM_OVERFLOW;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi1s1(unsigned char *input, /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
            signed char nullval,  /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            signed char *output,  /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == -128.)
        {
            /* Instead of subtracting 128, it is more efficient */
            /* to just flip the sign bit with the XOR operator */

            for (ii = 0; ii < ntodo; ii++)
                 output[ii] =  ( *(signed char *) &input[ii] ) ^ 0x80;
        }
        else if (scale == 1. && zero == 0.)      /* no scaling */
        { 
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] > 127)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 127;
                }
                else
                    output[ii] = (signed char) input[ii]; /* copy input */
            }
        }
        else             /* must scale the data */
        {                
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DSCHAR_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = -128;
                }
                else if (dvalue > DSCHAR_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 127;
                }
                else
                    output[ii] = (signed char) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == -128.)
        {
            /* Instead of subtracting 128, it is more efficient */
            /* to just flip the sign bit with the XOR operator */

            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] =  ( *(signed char *) &input[ii] ) ^ 0x80;
            }
        }
        else if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = (signed char) input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DSCHAR_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = -128;
                    }
                    else if (dvalue > DSCHAR_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 127;
                    }
                    else
                        output[ii] = (signed char) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi2s1(short *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            short tnull,          /* I - value of FITS TNULLn keyword if any */
            signed char nullval,  /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            signed char *output,  /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < -128)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = -128;
                }
                else if (input[ii] > 127)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 127;
                }
                else
                    output[ii] = (signed char) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DSCHAR_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = -128;
                }
                else if (dvalue > DSCHAR_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 127;
                }
                else
                    output[ii] = (signed char) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }

                else
                {
                    if (input[ii] < -128)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = -128;
                    }
                    else if (input[ii] > 127)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 127;
                    }
                    else
                        output[ii] = (signed char) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DSCHAR_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = -128;
                    }
                    else if (dvalue > DSCHAR_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 127;
                    }
                    else
                        output[ii] = (signed char) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi4s1(INT32BIT *input,      /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
            signed char nullval,  /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            signed char *output,  /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < -128)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = -128;
                }
                else if (input[ii] > 127)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 127;
                }
                else
                    output[ii] = (signed char) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DSCHAR_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = -128;
                }
                else if (dvalue > DSCHAR_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 127;
                }
                else
                    output[ii] = (signed char) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    if (input[ii] < -128)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = -128;
                    }
                    else if (input[ii] > 127)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 127;
                    }
                    else
                        output[ii] = (signed char) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DSCHAR_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = -128;
                    }
                    else if (dvalue > DSCHAR_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 127;
                    }
                    else
                        output[ii] = (signed char) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi8s1(LONGLONG *input,      /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
            signed char nullval,  /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            signed char *output,  /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < -128)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = -128;
                }
                else if (input[ii] > 127)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 127;
                }
                else
                    output[ii] = (signed char) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DSCHAR_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = -128;
                }
                else if (dvalue > DSCHAR_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 127;
                }
                else
                    output[ii] = (signed char) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    if (input[ii] < -128)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = -128;
                    }
                    else if (input[ii] > 127)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 127;
                    }
                    else
                        output[ii] = (signed char) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DSCHAR_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = -128;
                    }
                    else if (dvalue > DSCHAR_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 127;
                    }
                    else
                        output[ii] = (signed char) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffr4s1(float *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            signed char nullval,  /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            signed char *output,  /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to NaN.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;
    short *sptr, iret;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < DSCHAR_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = -128;
                }
                else if (input[ii] > DSCHAR_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 127;
                }
                else
                    output[ii] = (signed char) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DSCHAR_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = -128;
                }
                else if (dvalue > DSCHAR_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 127;
                }
                else
                    output[ii] = (signed char) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        sptr = (short *) input;

#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
        sptr++;       /* point to MSBs */
#endif
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++, sptr += 2)
            {
              /* use redundant boolean logic in following statement */
              /* to suppress irritating Borland compiler warning message */
              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                     output[ii] = 0;
              }
              else
                {
                    if (input[ii] < DSCHAR_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = -128;
                    }
                    else if (input[ii] > DSCHAR_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 127;
                    }
                    else
                        output[ii] = (signed char) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++, sptr += 2)
            {
              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {  
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                  {
                    if (zero < DSCHAR_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = -128;
                    }
                    else if (zero > DSCHAR_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 127;
                    }
                    else
                        output[ii] = (signed char) zero;
                  }
              }
              else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DSCHAR_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = -128;
                    }
                    else if (dvalue > DSCHAR_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 127;
                    }
                    else
                        output[ii] = (signed char) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffr8s1(double *input,        /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            signed char nullval,  /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            signed char *output,  /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to NaN.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;
    short *sptr, iret;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < DSCHAR_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = -128;
                }
                else if (input[ii] > DSCHAR_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 127;
                }
                else
                    output[ii] = (signed char) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DSCHAR_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = -128;
                }
                else if (dvalue > DSCHAR_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 127;
                }
                else
                    output[ii] = (signed char) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        sptr = (short *) input;

#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
        sptr += 3;       /* point to MSBs */
#endif
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++, sptr += 4)
            {
              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                     output[ii] = 0;
              }
              else
                {
                    if (input[ii] < DSCHAR_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = -128;
                    }
                    else if (input[ii] > DSCHAR_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 127;
                    }
                    else
                        output[ii] = (signed char) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++, sptr += 4)
            {
              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {  
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                  {
                    if (zero < DSCHAR_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = -128;
                    }
                    else if (zero > DSCHAR_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 127;
                    }
                    else
                        output[ii] = (signed char) zero;
                  }
              }
              else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DSCHAR_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = -128;
                    }
                    else if (dvalue > DSCHAR_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 127;
                    }
                    else
                        output[ii] = (signed char) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffstrs1(char *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            long twidth,          /* I - width of each substring of chars    */
            double implipower,    /* I - power of 10 of implied decimal      */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            char  *snull,         /* I - value of FITS null string, if any   */
            signed char nullval,  /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            signed char *output,  /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file. Check
  for null values and do scaling if required. The nullcheck code value
  determines how any null values in the input array are treated. A null
  value is an input pixel that is equal to snull.  If nullcheck= 0, then
  no special checking for nulls is performed.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    int  nullen;
    long ii;
    double dvalue;
    char *cstring, message[FLEN_ERRMSG];
    char *cptr, *tpos;
    char tempstore, chrzero = '0';
    double val, power;
    int exponent, sign, esign, decpt;

    nullen = strlen(snull);
    cptr = input;  /* pointer to start of input string */
    for (ii = 0; ii < ntodo; ii++)
    {
      cstring = cptr;
      /* temporarily insert a null terminator at end of the string */
      tpos = cptr + twidth;
      tempstore = *tpos;
      *tpos = 0;

      /* check if null value is defined, and if the    */
      /* column string is identical to the null string */
      if (snull[0] != ASCII_NULL_UNDEFINED && 
         !strncmp(snull, cptr, nullen) )
      {
        if (nullcheck)  
        {
          *anynull = 1;    
          if (nullcheck == 1)
            output[ii] = nullval;
          else
            nullarray[ii] = 1;
        }
        cptr += twidth;
      }
      else
      {
        /* value is not the null value, so decode it */
        /* remove any embedded blank characters from the string */

        decpt = 0;
        sign = 1;
        val  = 0.;
        power = 1.;
        exponent = 0;
        esign = 1;

        while (*cptr == ' ')               /* skip leading blanks */
           cptr++;

        if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
        {
          if (*cptr == '-')
             sign = -1;

          cptr++;

          while (*cptr == ' ')         /* skip blanks between sign and value */
            cptr++;
        }

        while (*cptr >= '0' && *cptr <= '9')
        {
          val = val * 10. + *cptr - chrzero;  /* accumulate the value */
          cptr++;

          while (*cptr == ' ')         /* skip embedded blanks in the value */
            cptr++;
        }

        if (*cptr == '.' || *cptr == ',')       /* check for decimal point */
        {
          decpt = 1;
          cptr++;
          while (*cptr == ' ')         /* skip any blanks */
            cptr++;

          while (*cptr >= '0' && *cptr <= '9')
          {
            val = val * 10. + *cptr - chrzero;  /* accumulate the value */
            power = power * 10.;
            cptr++;

            while (*cptr == ' ')         /* skip embedded blanks in the value */
              cptr++;
          }
        }

        if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
        {
          cptr++;
          while (*cptr == ' ')         /* skip blanks */
              cptr++;
  
          if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
          {
            if (*cptr == '-')
               esign = -1;

            cptr++;

            while (*cptr == ' ')        /* skip blanks between sign and exp */
              cptr++;
          }

          while (*cptr >= '0' && *cptr <= '9')
          {
            exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
            cptr++;

            while (*cptr == ' ')         /* skip embedded blanks */
              cptr++;
          }
        }

        if (*cptr  != 0)  /* should end up at the null terminator */
        {
          snprintf(message, FLEN_ERRMSG,"Cannot read number from ASCII table");
          ffpmsg(message);
          snprintf(message, FLEN_ERRMSG,"Column field = %s.", cstring);
          ffpmsg(message);
          /* restore the char that was overwritten by the null */
          *tpos = tempstore;
          return(*status = BAD_C2D);
        }

        if (!decpt)  /* if no explicit decimal, use implied */
           power = implipower;

        dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));

        dvalue = dvalue * scale + zero;   /* apply the scaling */

        if (dvalue < DSCHAR_MIN)
        {
            *status = OVERFLOW_ERR;
            output[ii] = -128;
        }
        else if (dvalue > DSCHAR_MAX)
        {
            *status = OVERFLOW_ERR;
            output[ii] = 127;
        }
        else
            output[ii] = (signed char) dvalue;
      }
      /* restore the char that was overwritten by the null */
      *tpos = tempstore;
    }
    return(*status);
}
cfitsio/getcolui.c0000644000225700000360000021735713246025103013776 0ustar  cagordonlhea/*  This file, getcolui.c, contains routines that read data elements from   */
/*  a FITS image or table, with unsigned short datatype.                    */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include 
#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int ffgpvui( fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
   unsigned short nulval,     /* I - value for undefined pixels              */
   unsigned short *array,     /* O - array of values that are returned       */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Undefined elements will be set equal to NULVAL, unless NULVAL=0
  in which case no checking for undefined values will be performed.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    long row;
    char cdummy;
    int nullcheck = 1;
    unsigned short nullvalue;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */
         nullvalue = nulval;  /* set local variable */

        fits_read_compressed_pixels(fptr, TUSHORT, firstelem, nelem,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgclui(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
               array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgpfui( fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
   unsigned short *array,     /* O - array of values that are returned       */
            char *nularray,   /* O - array of null pixel flags               */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Any undefined pixels in the returned array will be set = 0 and the 
  corresponding nularray value will be set = 1.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    long row;
    int nullcheck = 2;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_read_compressed_pixels(fptr, TUSHORT, firstelem, nelem,
            nullcheck, NULL, array, nularray, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgclui(fptr, 2, row, firstelem, nelem, 1, 2, 0,
               array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffg2dui(fitsfile *fptr,  /* I - FITS file pointer                       */
           long  group,     /* I - group to read (1 = 1st group)           */
  unsigned short nulval,    /* set undefined pixels equal to this          */
           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
  unsigned short *array,    /* O - array to be filled and returned         */
           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
           int  *status)    /* IO - error status                           */
/*
  Read an entire 2-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being read).  Any null
  values in the array will be set equal to the value of nulval, unless
  nulval = 0 in which case no null checking will be performed.
*/
{
    /* call the 3D reading routine, with the 3rd dimension = 1 */

    ffg3dui(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, 
           anynul, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffg3dui(fitsfile *fptr,  /* I - FITS file pointer                       */
           long  group,     /* I - group to read (1 = 1st group)           */
  unsigned short nulval,    /* set undefined pixels equal to this          */
           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
           LONGLONG  nrows,     /* I - number of rows in each plane of array   */
           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
           LONGLONG  naxis3,    /* I - FITS image NAXIS3 value                 */
  unsigned short *array,    /* O - array to be filled and returned         */
           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
           int  *status)    /* IO - error status                           */
/*
  Read an entire 3-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being read).  Any null
  values in the array will be set equal to the value of nulval, unless
  nulval = 0 in which case no null checking will be performed.
*/
{
    long tablerow, ii, jj;
    char cdummy;
    int nullcheck = 1;
    long inc[] = {1,1,1};
    LONGLONG fpixel[] = {1,1,1}, nfits, narray;
    LONGLONG lpixel[3];
    unsigned short nullvalue;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        lpixel[0] = ncols;
        lpixel[1] = nrows;
        lpixel[2] = naxis3;
        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_img(fptr, TUSHORT, fpixel, lpixel, inc,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */
    tablerow=maxvalue(1,group);

    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
    {
       /* all the image pixels are contiguous, so read all at once */
       ffgclui(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval,
               array, &cdummy, anynul, status);
       return(*status);
    }

    if (ncols < naxis1 || nrows < naxis2)
       return(*status = BAD_DIMEN);

    nfits = 1;   /* next pixel in FITS image to read */
    narray = 0;  /* next pixel in output array to be filled */

    /* loop over naxis3 planes in the data cube */
    for (jj = 0; jj < naxis3; jj++)
    {
      /* loop over the naxis2 rows in the FITS image, */
      /* reading naxis1 pixels to each row            */

      for (ii = 0; ii < naxis2; ii++)
      {
       if (ffgclui(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval,
          &array[narray], &cdummy, anynul, status) > 0)
          return(*status);

       nfits += naxis1;
       narray += ncols;
      }
      narray += (nrows - naxis2) * ncols;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsvui(fitsfile *fptr, /* I - FITS file pointer                         */
           int  colnum,    /* I - number of the column to read (1 = 1st)    */
           int naxis,      /* I - number of dimensions in the FITS array    */
           long  *naxes,   /* I - size of each dimension                    */
           long  *blc,     /* I - 'bottom left corner' of the subsection    */
           long  *trc,     /* I - 'top right corner' of the subsection      */
           long  *inc,     /* I - increment to be applied in each dimension */
  unsigned short nulval,   /* I - value to set undefined pixels             */
  unsigned short *array,   /* O - array to be filled and returned           */
           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
           int  *status)   /* IO - error status                             */
/*
  Read a subsection of data values from an image or a table column.
  This routine is set up to handle a maximum of nine dimensions.
*/
{
    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
    long str[9],stp[9],incr[9];
    long nelem, nultyp, ninc, numcol;
    LONGLONG felem, dsize[10], blcll[9], trcll[9];
    int hdutype, anyf;
    char ldummy, msg[FLEN_ERRMSG];
    int nullcheck = 1;
    unsigned short nullvalue;

    if (naxis < 1 || naxis > 9)
    {
        snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvui is out of range", naxis);
        ffpmsg(msg);
        return(*status = BAD_DIMEN);
    }

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        for (ii=0; ii < naxis; ii++) {
	    blcll[ii] = blc[ii];
	    trcll[ii] = trc[ii];
	}

        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_img(fptr, TUSHORT, blcll, trcll, inc,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

/*
    if this is a primary array, then the input COLNUM parameter should
    be interpreted as the row number, and we will alway read the image
    data from column 2 (any group parameters are in column 1).
*/
    if (ffghdt(fptr, &hdutype, status) > 0)
        return(*status);

    if (hdutype == IMAGE_HDU)
    {
        /* this is a primary array, or image extension */
        if (colnum == 0)
        {
            rstr = 1;
            rstp = 1;
        }
        else
        {
            rstr = colnum;
            rstp = colnum;
        }
        rinc = 1;
        numcol = 2;
    }
    else
    {
        /* this is a table, so the row info is in the (naxis+1) elements */
        rstr = blc[naxis];
        rstp = trc[naxis];
        rinc = inc[naxis];
        numcol = colnum;
    }

    nultyp = 1;
    if (anynul)
        *anynul = FALSE;

    i0 = 0;
    for (ii = 0; ii < 9; ii++)
    {
        str[ii] = 1;
        stp[ii] = 1;
        incr[ii] = 1;
        dsize[ii] = 1;
    }

    for (ii = 0; ii < naxis; ii++)
    {
      if (trc[ii] < blc[ii])
      {
        snprintf(msg, FLEN_ERRMSG,"ffgsvui: illegal range specified for axis %ld", ii + 1);
        ffpmsg(msg);
        return(*status = BAD_PIX_NUM);
      }

      str[ii] = blc[ii];
      stp[ii] = trc[ii];
      incr[ii] = inc[ii];
      dsize[ii + 1] = dsize[ii] * naxes[ii];
    }

    if (naxis == 1 && naxes[0] == 1)
    {
      /* This is not a vector column, so read all the rows at once */
      nelem = (rstp - rstr) / rinc + 1;
      ninc = rinc;
      rstp = rstr;
    }
    else
    {
      /* have to read each row individually, in all dimensions */
      nelem = (stp[0] - str[0]) / inc[0] + 1;
      ninc = incr[0];
    }

    for (row = rstr; row <= rstp; row += rinc)
    {
     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
     {
      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
      {
       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
       {
        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
        {
         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
         {
          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
          {
           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
           {
            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
            {
              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];
              if ( ffgclui(fptr, numcol, row, felem, nelem, ninc, nultyp,
                   nulval, &array[i0], &ldummy, &anyf, status) > 0)
                   return(*status);

              if (anyf && anynul)
                  *anynul = TRUE;

              i0 += nelem;
            }
           }
          }
         }
        }
       }
      }
     }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsfui(fitsfile *fptr, /* I - FITS file pointer                         */
           int  colnum,    /* I - number of the column to read (1 = 1st)    */
           int naxis,      /* I - number of dimensions in the FITS array    */
           long  *naxes,   /* I - size of each dimension                    */
           long  *blc,     /* I - 'bottom left corner' of the subsection    */
           long  *trc,     /* I - 'top right corner' of the subsection      */
           long  *inc,     /* I - increment to be applied in each dimension */
  unsigned short *array,   /* O - array to be filled and returned           */
           char *flagval,  /* O - set to 1 if corresponding value is null   */
           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
           int  *status)   /* IO - error status                             */
/*
  Read a subsection of data values from an image or a table column.
  This routine is set up to handle a maximum of nine dimensions.
*/
{
    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
    long str[9],stp[9],incr[9],dsize[10];
    LONGLONG blcll[9], trcll[9];
    long felem, nelem, nultyp, ninc, numcol;
    int hdutype, anyf;
    unsigned short nulval = 0;
    char msg[FLEN_ERRMSG];
    int nullcheck = 2;

    if (naxis < 1 || naxis > 9)
    {
        snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvi is out of range", naxis);
        ffpmsg(msg);
        return(*status = BAD_DIMEN);
    }

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        for (ii=0; ii < naxis; ii++) {
	    blcll[ii] = blc[ii];
	    trcll[ii] = trc[ii];
	}

        fits_read_compressed_img(fptr, TUSHORT, blcll, trcll, inc,
            nullcheck, NULL, array, flagval, anynul, status);
        return(*status);
    }

/*
    if this is a primary array, then the input COLNUM parameter should
    be interpreted as the row number, and we will alway read the image
    data from column 2 (any group parameters are in column 1).
*/
    if (ffghdt(fptr, &hdutype, status) > 0)
        return(*status);

    if (hdutype == IMAGE_HDU)
    {
        /* this is a primary array, or image extension */
        if (colnum == 0)
        {
            rstr = 1;
            rstp = 1;
        }
        else
        {
            rstr = colnum;
            rstp = colnum;
        }
        rinc = 1;
        numcol = 2;
    }
    else
    {
        /* this is a table, so the row info is in the (naxis+1) elements */
        rstr = blc[naxis];
        rstp = trc[naxis];
        rinc = inc[naxis];
        numcol = colnum;
    }

    nultyp = 2;
    if (anynul)
        *anynul = FALSE;

    i0 = 0;
    for (ii = 0; ii < 9; ii++)
    {
        str[ii] = 1;
        stp[ii] = 1;
        incr[ii] = 1;
        dsize[ii] = 1;
    }

    for (ii = 0; ii < naxis; ii++)
    {
      if (trc[ii] < blc[ii])
      {
        snprintf(msg, FLEN_ERRMSG,"ffgsvi: illegal range specified for axis %ld", ii + 1);
        ffpmsg(msg);
        return(*status = BAD_PIX_NUM);
      }

      str[ii] = blc[ii];
      stp[ii] = trc[ii];
      incr[ii] = inc[ii];
      dsize[ii + 1] = dsize[ii] * naxes[ii];
    }

    if (naxis == 1 && naxes[0] == 1)
    {
      /* This is not a vector column, so read all the rows at once */
      nelem = (rstp - rstr) / rinc + 1;
      ninc = rinc;
      rstp = rstr;
    }
    else
    {
      /* have to read each row individually, in all dimensions */
      nelem = (stp[0] - str[0]) / inc[0] + 1;
      ninc = incr[0];
    }

    for (row = rstr; row <= rstp; row += rinc)
    {
     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
     {
      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
      {
       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
       {
        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
        {
         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
         {
          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
          {
           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
           {
            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
            {
              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];

              if ( ffgclui(fptr, numcol, row, felem, nelem, ninc, nultyp,
                   nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
                   return(*status);

              if (anyf && anynul)
                  *anynul = TRUE;

              i0 += nelem;
            }
           }
          }
         }
        }
       }
      }
     }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffggpui( fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            long  firstelem,  /* I - first vector element to read (1 = 1st)  */
            long  nelem,      /* I - number of values to read                */
   unsigned short *array,     /* O - array of values that are returned       */
            int  *status)     /* IO - error status                           */
/*
  Read an array of group parameters from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
*/
{
    long row;
    int idummy;
    char cdummy;
    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgclui(fptr, 1, row, firstelem, nelem, 1, 1, 0,
               array, &cdummy, &idummy, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcvui(fitsfile *fptr,   /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
  unsigned short nulval,     /* I - value for null pixels                   */
  unsigned short *array,     /* O - array of values that are read           */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Any undefined pixels will be set equal to the value of 'nulval' unless
  nulval = 0 in which case no checks for undefined pixels will be made.
*/
{
    char cdummy;

    ffgclui(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
           array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcfui(fitsfile *fptr,   /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
  unsigned short *array,     /* O - array of values that are read           */
           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Nularray will be set = 1 if the corresponding array pixel is undefined, 
  otherwise nularray will = 0.
*/
{
    unsigned short dummy = 0;

    ffgclui(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
           array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgclui( fitsfile *fptr,   /* I - FITS file pointer                       */
            int  colnum,      /* I - number of column to read (1 = 1st col)  */
            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
            LONGLONG firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
            int   nultyp,     /* I - null value handling code:               */
                              /*     1: set undefined pixels = nulval        */
                              /*     2: set nularray=1 for undefined pixels  */
   unsigned short nulval,     /* I - value for null pixels if nultyp = 1     */
   unsigned short *array,     /* O - array of values that are read           */
            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU.
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer be a virtual column in a 1 or more grouped FITS primary
  array or image extension.  FITSIO treats a primary array as a binary table
  with 2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.

  The output array of values will be converted from the datatype of the column 
  and will be scaled by the FITS TSCALn and TZEROn values if necessary.
*/
{
    double scale, zero, power = 1., dtemp;
    int tcode, maxelem2, hdutype, xcode, decimals;
    long twidth, incre;
    long ii, xwidth, ntodo;
    int nulcheck;
    LONGLONG repeat, startpos, elemnum, readptr, tnull;
    LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
    char tform[20];
    char message[FLEN_ERRMSG];
    char snull[20];   /*  the FITS null value if reading from ASCII table  */

    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
    void *buffer;

    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
        return(*status);

    buffer = cbuff;

    if (anynul)
        *anynul = 0;

    if (nultyp == 2)
        memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if ( ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 0, &scale, &zero,
         tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
         return(*status);
    maxelem = maxelem2;

    incre *= elemincre;   /* multiply incre to just get every nth pixel */

    if (tcode == TSTRING)    /* setup for ASCII tables */
    {
      /* get the number of implied decimal places if no explicit decmal point */
      ffasfm(tform, &xcode, &xwidth, &decimals, status); 
      for(ii = 0; ii < decimals; ii++)
        power *= 10.;
    }
    /*------------------------------------------------------------------*/
    /*  Decide whether to check for null values in the input FITS file: */
    /*------------------------------------------------------------------*/
    nulcheck = nultyp; /* by default check for null values in the FITS file */

    if (nultyp == 1 && nulval == 0)
       nulcheck = 0;    /* calling routine does not want to check for nulls */

    else if (tcode%10 == 1 &&        /* if reading an integer column, and  */ 
            tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
            nulcheck = 0;            /* then do not check for null values. */

    else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
            nulcheck = 0;            /* Impossible null value */

    else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
            nulcheck = 0;            /* Impossible null value */

    else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
         nulcheck = 0;

    /*----------------------------------------------------------------------*/
    /*  If FITS column and output data array have same datatype, then we do */
    /*  not need to use a temporary buffer to store intermediate datatype.  */
    /*----------------------------------------------------------------------*/
    if (tcode == TSHORT) /* Special Case:                        */
    {                             /* no type convertion required, so read */
                                  /* data directly into output buffer.    */

        if (nelem < (LONGLONG)INT32_MAX/2) {
            maxelem = nelem;
        } else {
            maxelem = INT32_MAX/2;
        }
    }

    /*---------------------------------------------------------------------*/
    /*  Now read the pixels from the FITS column. If the column does not   */
    /*  have the same datatype as the output array, then we have to read   */
    /*  the raw values into a temporary buffer (of limited size).  In      */
    /*  the case of a vector colum read only 1 vector of values at a time  */
    /*  then skip to the next row if more values need to be read.          */
    /*  After reading the raw values, then call the fffXXYY routine to (1) */
    /*  test for undefined values, (2) convert the datatype if necessary,  */
    /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
    /*  scaling parameters.                                                */
    /*---------------------------------------------------------------------*/
    remain = nelem;           /* remaining number of values to read */
    next = 0;                 /* next element in array to be read   */
    rownum = 0;               /* row number, relative to firstrow   */

    while (remain)
    {
        /* limit the number of pixels to read at one time to the number that
           will fit in the buffer or to the number of pixels that remain in
           the current vector, which ever is smaller.
        */
        ntodo = (long) minvalue(remain, maxelem);      
        ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));

        readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));

        switch (tcode) 
        {
            case (TSHORT):
                ffgi2b(fptr, readptr, ntodo, incre,
                       (short *) &array[next], status);
                fffi2u2((short *) &array[next], ntodo, scale,
                       zero, nulcheck, (short) tnull, nulval, &nularray[next],
                       anynul, &array[next], status);
                break;
            case (TLONGLONG):

                ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status);
                fffi8u2( (LONGLONG *) buffer, ntodo, scale, zero, 
                           nulcheck, tnull, nulval, &nularray[next], 
                            anynul, &array[next], status);
                break;
            case (TBYTE):
                ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer,
                      status);
                fffi1u2((unsigned char *) buffer, ntodo, scale, zero, nulcheck, 
                    (unsigned char) tnull, nulval, &nularray[next], anynul, 
                    &array[next], status);
                break;
            case (TLONG):
                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer,
                       status);
                fffi4u2((INT32BIT *) buffer, ntodo, scale, zero, nulcheck, 
                       (INT32BIT) tnull, nulval, &nularray[next], anynul, 
                       &array[next], status);
                break;
            case (TFLOAT):
                ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
                fffr4u2((float  *) buffer, ntodo, scale, zero, nulcheck, 
                       nulval, &nularray[next], anynul, 
                       &array[next], status);
                break;
            case (TDOUBLE):
                ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
                fffr8u2((double *) buffer, ntodo, scale, zero, nulcheck, 
                          nulval, &nularray[next], anynul, 
                          &array[next], status);
                break;
            case (TSTRING):
                ffmbyt(fptr, readptr, REPORT_EOF, status);
       
                if (incre == twidth)    /* contiguous bytes */
                     ffgbyt(fptr, ntodo * twidth, buffer, status);
                else
                     ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
                               status);

                fffstru2((char *) buffer, ntodo, scale, zero, twidth, power,
                     nulcheck, snull, nulval, &nularray[next], anynul,
                     &array[next], status);
                break;

            default:  /*  error trap for invalid column format */
                snprintf(message, FLEN_ERRMSG, 
                   "Cannot read numbers from column %d which has format %s",
                    colnum, tform);
                ffpmsg(message);
                if (hdutype == ASCII_TBL)
                    return(*status = BAD_ATABLE_FORMAT);
                else
                    return(*status = BAD_BTABLE_FORMAT);

        } /* End of switch block */

        /*-------------------------*/
        /*  Check for fatal error  */
        /*-------------------------*/
        if (*status > 0)  /* test for error during previous read operation */
        {
	  dtemp = (double) next;
          if (hdutype > 0)
            snprintf(message,FLEN_ERRMSG,
            "Error reading elements %.0f thru %.0f from column %d (ffgclui).",
              dtemp+1., dtemp+ntodo, colnum);
          else
            snprintf(message,FLEN_ERRMSG,
            "Error reading elements %.0f thru %.0f from image (ffgclui).",
              dtemp+1., dtemp+ntodo);

          ffpmsg(message);
          return(*status);
        }

        /*--------------------------------------------*/
        /*  increment the counters for the next loop  */
        /*--------------------------------------------*/
        remain -= ntodo;
        if (remain)
        {
            next += ntodo;
            elemnum = elemnum + (ntodo * elemincre);

            if (elemnum >= repeat)  /* completed a row; start on later row */
            {
                rowincre = elemnum / repeat;
                rownum += rowincre;
                elemnum = elemnum - (rowincre * repeat);
            }
        }
    }  /*  End of main while Loop  */


    /*--------------------------------*/
    /*  check for numerical overflow  */
    /*--------------------------------*/
    if (*status == OVERFLOW_ERR)
    {
        ffpmsg(
        "Numerical overflow during type conversion while reading FITS data.");
        *status = NUM_OVERFLOW;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi1u2(unsigned char *input, /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
   unsigned short nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
   unsigned short *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
                output[ii] = (unsigned short) input[ii]; /* copy input */
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DUSHRT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DUSHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = USHRT_MAX;
                }
                else
                    output[ii] = (unsigned short) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = (unsigned short) input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DUSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DUSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = USHRT_MAX;
                    }
                    else
                        output[ii] = (unsigned short) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi2u2(short *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            short tnull,          /* I - value of FITS TNULLn keyword if any */
   unsigned short nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
   unsigned short *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 32768.) 
        {       
           /* Instead of adding 32768, it is more efficient */
           /* to just flip the sign bit with the XOR operator */

           for (ii = 0; ii < ntodo; ii++)
              output[ii] =  ( *(unsigned short *) &input[ii] ) ^ 0x8000;
        }
        else if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < 0)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else
                    output[ii] = (unsigned short) input[ii]; /* copy input */
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DUSHRT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DUSHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = USHRT_MAX;
                }
                else
                    output[ii] = (unsigned short) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 32768.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] =  ( *(unsigned short *) &input[ii] ) ^ 0x8000;
            }
        }
        else if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else if (input[ii] < 0)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else
                    output[ii] = (unsigned short) input[ii]; /* copy input */
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DUSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DUSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = USHRT_MAX;
                    }
                    else
                        output[ii] = (unsigned short) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi4u2(INT32BIT *input,      /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
   unsigned short nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
   unsigned short *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < 0)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (input[ii] > USHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = USHRT_MAX;
                }
                else
                    output[ii] = (unsigned short) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DUSHRT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DUSHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = USHRT_MAX;
                }
                else
                    output[ii] = (unsigned short) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    if (input[ii] < 0)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (input[ii] > USHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = USHRT_MAX;
                    }
                    else
                        output[ii] = (unsigned short) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DUSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DUSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = USHRT_MAX;
                    }
                    else
                        output[ii] = (unsigned short) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi8u2(LONGLONG *input,      /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
   unsigned short nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
   unsigned short *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < 0)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (input[ii] > USHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = USHRT_MAX;
                }
                else
                    output[ii] = (unsigned short) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DUSHRT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DUSHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = USHRT_MAX;
                }
                else
                    output[ii] = (unsigned short) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    if (input[ii] < 0)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (input[ii] > USHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = USHRT_MAX;
                    }
                    else
                        output[ii] = (unsigned short) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DUSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DUSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = USHRT_MAX;
                    }
                    else
                        output[ii] = (unsigned short) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffr4u2(float *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
   unsigned short nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
   unsigned short *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to NaN.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;
    short *sptr, iret;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < DUSHRT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (input[ii] > DUSHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = USHRT_MAX;
                }
                else
                    output[ii] = (unsigned short) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DUSHRT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DUSHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = USHRT_MAX;
                }
                else
                    output[ii] = (unsigned short) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        sptr = (short *) input;

#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
        sptr++;       /* point to MSBs */
#endif

        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++, sptr += 2)
            {
              if (0 != (iret = fnan(*sptr) ) )   /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                     output[ii] = 0;
              }
              else
                {
                    if (input[ii] < DUSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (input[ii] > DUSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = USHRT_MAX;
                    }
                    else
                        output[ii] = (unsigned short) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++, sptr += 2)
            {
              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {  
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                  { 
                    if (zero < DUSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (zero > DUSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = USHRT_MAX;
                    }
                    else
                      output[ii] = (unsigned short) zero;
                  }
              }
              else
              {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DUSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DUSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = USHRT_MAX;
                    }
                    else
                        output[ii] = (unsigned short) dvalue;
              }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffr8u2(double *input,        /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
   unsigned short nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
   unsigned short *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to NaN.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;
    short *sptr, iret;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < DUSHRT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (input[ii] > DUSHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = USHRT_MAX;
                }
                else
                    output[ii] = (unsigned short) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DUSHRT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DUSHRT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = USHRT_MAX;
                }
                else
                    output[ii] = (unsigned short) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        sptr = (short *) input;

#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
        sptr += 3;       /* point to MSBs */
#endif
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++, sptr += 4)
            {
              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                     output[ii] = 0;
              }
              else
                {
                    if (input[ii] < DUSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (input[ii] > DUSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = USHRT_MAX;
                    }
                    else
                        output[ii] = (unsigned short) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++, sptr += 4)
            {
              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {  
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                  { 
                    if (zero < DUSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (zero > DUSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = USHRT_MAX;
                    }
                    else
                      output[ii] = (unsigned short) zero;
                  }
              }
              else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DUSHRT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DUSHRT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = USHRT_MAX;
                    }
                    else
                        output[ii] = (unsigned short) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffstru2(char *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            long twidth,          /* I - width of each substring of chars    */
            double implipower,    /* I - power of 10 of implied decimal      */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            char  *snull,         /* I - value of FITS null string, if any   */
   unsigned short nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
   unsigned short *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file. Check
  for null values and do scaling if required. The nullcheck code value
  determines how any null values in the input array are treated. A null
  value is an input pixel that is equal to snull.  If nullcheck= 0, then
  no special checking for nulls is performed.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    int nullen;
    long ii;
    double dvalue;
    char *cstring, message[FLEN_ERRMSG];
    char *cptr, *tpos;
    char tempstore, chrzero = '0';
    double val, power;
    int exponent, sign, esign, decpt;

    nullen = strlen(snull);
    cptr = input;  /* pointer to start of input string */
    for (ii = 0; ii < ntodo; ii++)
    {
      cstring = cptr;
      /* temporarily insert a null terminator at end of the string */
      tpos = cptr + twidth;
      tempstore = *tpos;
      *tpos = 0;

      /* check if null value is defined, and if the    */
      /* column string is identical to the null string */
      if (snull[0] != ASCII_NULL_UNDEFINED && 
         !strncmp(snull, cptr, nullen) )
      {
        if (nullcheck)  
        {
          *anynull = 1;    
          if (nullcheck == 1)
            output[ii] = nullval;
          else
            nullarray[ii] = 1;
        }
        cptr += twidth;
      }
      else
      {
        /* value is not the null value, so decode it */
        /* remove any embedded blank characters from the string */

        decpt = 0;
        sign = 1;
        val  = 0.;
        power = 1.;
        exponent = 0;
        esign = 1;

        while (*cptr == ' ')               /* skip leading blanks */
           cptr++;

        if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
        {
          if (*cptr == '-')
             sign = -1;

          cptr++;

          while (*cptr == ' ')         /* skip blanks between sign and value */
            cptr++;
        }

        while (*cptr >= '0' && *cptr <= '9')
        {
          val = val * 10. + *cptr - chrzero;  /* accumulate the value */
          cptr++;

          while (*cptr == ' ')         /* skip embedded blanks in the value */
            cptr++;
        }

        if (*cptr == '.' || *cptr == ',')       /* check for decimal point */
        {
          decpt = 1;       /* set flag to show there was a decimal point */
          cptr++;
          while (*cptr == ' ')         /* skip any blanks */
            cptr++;

          while (*cptr >= '0' && *cptr <= '9')
          {
            val = val * 10. + *cptr - chrzero;  /* accumulate the value */
            power = power * 10.;
            cptr++;

            while (*cptr == ' ')         /* skip embedded blanks in the value */
              cptr++;
          }
        }

        if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
        {
          cptr++;
          while (*cptr == ' ')         /* skip blanks */
              cptr++;
  
          if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
          {
            if (*cptr == '-')
               esign = -1;

            cptr++;

            while (*cptr == ' ')        /* skip blanks between sign and exp */
              cptr++;
          }

          while (*cptr >= '0' && *cptr <= '9')
          {
            exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
            cptr++;

            while (*cptr == ' ')         /* skip embedded blanks */
              cptr++;
          }
        }

        if (*cptr  != 0)  /* should end up at the null terminator */
        {
          snprintf(message,FLEN_ERRMSG, "Cannot read number from ASCII table");
          ffpmsg(message);
          snprintf(message, FLEN_ERRMSG,"Column field = %s.", cstring);
          ffpmsg(message);
          /* restore the char that was overwritten by the null */
          *tpos = tempstore;
          return(*status = BAD_C2D);
        }

        if (!decpt)  /* if no explicit decimal, use implied */
           power = implipower;

        dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));

        dvalue = dvalue * scale + zero;   /* apply the scaling */

        if (dvalue < DUSHRT_MIN)
        {
            *status = OVERFLOW_ERR;
            output[ii] = 0;
        }
        else if (dvalue > DUSHRT_MAX)
        {
            *status = OVERFLOW_ERR;
            output[ii] = USHRT_MAX;
        }
        else
            output[ii] = (unsigned short) dvalue;
      }
      /* restore the char that was overwritten by the null */
      *tpos = tempstore;
    }
    return(*status);
}
cfitsio/getcoluj.c0000644000225700000360000021737413246025103013776 0ustar  cagordonlhea/*  This file, getcoluj.c, contains routines that read data elements from  */
/*  a FITS image or table, with unsigned long data type.                   */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include 
#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int ffgpvuj(fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
   unsigned long  nulval,     /* I - value for undefined pixels              */
   unsigned long  *array,     /* O - array of values that are returned       */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Undefined elements will be set equal to NULVAL, unless NULVAL=0
  in which case no checking for undefined values will be performed.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    long row;
    char cdummy;
    int nullcheck = 1;
    unsigned long nullvalue;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */
        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_pixels(fptr, TULONG, firstelem, nelem,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgcluj(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
               array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgpfuj(fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
   unsigned long  *array,     /* O - array of values that are returned       */
            char *nularray,   /* O - array of null pixel flags               */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Any undefined pixels in the returned array will be set = 0 and the 
  corresponding nularray value will be set = 1.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    long row;
    int nullcheck = 2;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_read_compressed_pixels(fptr, TULONG, firstelem, nelem,
            nullcheck, NULL, array, nularray, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgcluj(fptr, 2, row, firstelem, nelem, 1, 2, 0L,
               array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffg2duj(fitsfile *fptr,  /* I - FITS file pointer                       */
           long  group,     /* I - group to read (1 = 1st group)           */
  unsigned long  nulval,    /* set undefined pixels equal to this          */
           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
  unsigned long  *array,    /* O - array to be filled and returned         */
           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
           int  *status)    /* IO - error status                           */
/*
  Read an entire 2-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being read).  Any null
  values in the array will be set equal to the value of nulval, unless
  nulval = 0 in which case no null checking will be performed.
*/
{
    /* call the 3D reading routine, with the 3rd dimension = 1 */

    ffg3duj(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, 
           anynul, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffg3duj(fitsfile *fptr,  /* I - FITS file pointer                       */
           long  group,     /* I - group to read (1 = 1st group)           */
  unsigned long  nulval,    /* set undefined pixels equal to this          */
           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
           LONGLONG  nrows,     /* I - number of rows in each plane of array   */
           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
           LONGLONG  naxis3,    /* I - FITS image NAXIS3 value                 */
  unsigned long  *array,    /* O - array to be filled and returned         */
           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
           int  *status)    /* IO - error status                           */
/*
  Read an entire 3-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being read).  Any null
  values in the array will be set equal to the value of nulval, unless
  nulval = 0 in which case no null checking will be performed.
*/
{
    long tablerow, ii, jj;
    char cdummy;
    int nullcheck = 1;
    long inc[] = {1,1,1};
    LONGLONG fpixel[] = {1,1,1}, nfits, narray;
    LONGLONG lpixel[3];
    unsigned long nullvalue;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        lpixel[0] = ncols;
        lpixel[1] = nrows;
        lpixel[2] = naxis3;
        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_img(fptr, TULONG, fpixel, lpixel, inc,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */
    tablerow=maxvalue(1,group);

    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
    {
       /* all the image pixels are contiguous, so read all at once */
       ffgcluj(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval,
               array, &cdummy, anynul, status);
       return(*status);
    }

    if (ncols < naxis1 || nrows < naxis2)
       return(*status = BAD_DIMEN);

    nfits = 1;   /* next pixel in FITS image to read */
    narray = 0;  /* next pixel in output array to be filled */

    /* loop over naxis3 planes in the data cube */
    for (jj = 0; jj < naxis3; jj++)
    {
      /* loop over the naxis2 rows in the FITS image, */
      /* reading naxis1 pixels to each row            */

      for (ii = 0; ii < naxis2; ii++)
      {
       if (ffgcluj(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval,
          &array[narray], &cdummy, anynul, status) > 0)
          return(*status);

       nfits += naxis1;
       narray += ncols;
      }
      narray += (nrows - naxis2) * ncols;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsvuj(fitsfile *fptr, /* I - FITS file pointer                         */
           int  colnum,    /* I - number of the column to read (1 = 1st)    */
           int naxis,      /* I - number of dimensions in the FITS array    */
           long  *naxes,   /* I - size of each dimension                    */
           long  *blc,     /* I - 'bottom left corner' of the subsection    */
           long  *trc,     /* I - 'top right corner' of the subsection      */
           long  *inc,     /* I - increment to be applied in each dimension */
  unsigned long nulval,    /* I - value to set undefined pixels             */
  unsigned long *array,    /* O - array to be filled and returned           */
           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
           int  *status)   /* IO - error status                             */
/*
  Read a subsection of data values from an image or a table column.
  This routine is set up to handle a maximum of nine dimensions.
*/
{
    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
    long str[9],stp[9],incr[9];
    long nelem, nultyp, ninc, numcol;
    LONGLONG felem, dsize[10], blcll[9], trcll[9];
    int hdutype, anyf;
    char ldummy, msg[FLEN_ERRMSG];
    int nullcheck = 1;
    unsigned long nullvalue;

    if (naxis < 1 || naxis > 9)
    {
        snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvuj is out of range", naxis);
        ffpmsg(msg);
        return(*status = BAD_DIMEN);
    }

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        for (ii=0; ii < naxis; ii++) {
	    blcll[ii] = blc[ii];
	    trcll[ii] = trc[ii];
	}

        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_img(fptr, TULONG, blcll, trcll, inc,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

/*
    if this is a primary array, then the input COLNUM parameter should
    be interpreted as the row number, and we will alway read the image
    data from column 2 (any group parameters are in column 1).
*/
    if (ffghdt(fptr, &hdutype, status) > 0)
        return(*status);

    if (hdutype == IMAGE_HDU)
    {
        /* this is a primary array, or image extension */
        if (colnum == 0)
        {
            rstr = 1;
            rstp = 1;
        }
        else
        {
            rstr = colnum;
            rstp = colnum;
        }
        rinc = 1;
        numcol = 2;
    }
    else
    {
        /* this is a table, so the row info is in the (naxis+1) elements */
        rstr = blc[naxis];
        rstp = trc[naxis];
        rinc = inc[naxis];
        numcol = colnum;
    }

    nultyp = 1;
    if (anynul)
        *anynul = FALSE;

    i0 = 0;
    for (ii = 0; ii < 9; ii++)
    {
        str[ii] = 1;
        stp[ii] = 1;
        incr[ii] = 1;
        dsize[ii] = 1;
    }

    for (ii = 0; ii < naxis; ii++)
    {
      if (trc[ii] < blc[ii])
      {
        snprintf(msg, FLEN_ERRMSG,"ffgsvuj: illegal range specified for axis %ld", ii + 1);
        ffpmsg(msg);
        return(*status = BAD_PIX_NUM);
      }

      str[ii] = blc[ii];
      stp[ii] = trc[ii];
      incr[ii] = inc[ii];
      dsize[ii + 1] = dsize[ii] * naxes[ii];
    }

    if (naxis == 1 && naxes[0] == 1)
    {
      /* This is not a vector column, so read all the rows at once */
      nelem = (rstp - rstr) / rinc + 1;
      ninc = rinc;
      rstp = rstr;
    }
    else
    {
      /* have to read each row individually, in all dimensions */
      nelem = (stp[0] - str[0]) / inc[0] + 1;
      ninc = incr[0];
    }

    for (row = rstr; row <= rstp; row += rinc)
    {
     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
     {
      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
      {
       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
       {
        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
        {
         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
         {
          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
          {
           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
           {
            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
            {
              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];

              if ( ffgcluj(fptr, numcol, row, felem, nelem, ninc, nultyp,
                   nulval, &array[i0], &ldummy, &anyf, status) > 0)
                   return(*status);

              if (anyf && anynul)
                  *anynul = TRUE;

              i0 += nelem;
            }
           }
          }
         }
        }
       }
      }
     }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsfuj(fitsfile *fptr, /* I - FITS file pointer                         */
           int  colnum,    /* I - number of the column to read (1 = 1st)    */
           int naxis,      /* I - number of dimensions in the FITS array    */
           long  *naxes,   /* I - size of each dimension                    */
           long  *blc,     /* I - 'bottom left corner' of the subsection    */
           long  *trc,     /* I - 'top right corner' of the subsection      */
           long  *inc,     /* I - increment to be applied in each dimension */
  unsigned long *array,    /* O - array to be filled and returned           */
           char *flagval,  /* O - set to 1 if corresponding value is null   */
           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
           int  *status)   /* IO - error status                             */
/*
  Read a subsection of data values from an image or a table column.
  This routine is set up to handle a maximum of nine dimensions.
*/
{
    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
    long str[9],stp[9],incr[9],dsize[10];
    LONGLONG blcll[9], trcll[9];
    long felem, nelem, nultyp, ninc, numcol;
    unsigned long nulval = 0;
    int hdutype, anyf;
    char msg[FLEN_ERRMSG];
    int nullcheck = 2;

    if (naxis < 1 || naxis > 9)
    {
        snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvj is out of range", naxis);
        ffpmsg(msg);
        return(*status = BAD_DIMEN);
    }

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        for (ii=0; ii < naxis; ii++) {
	    blcll[ii] = blc[ii];
	    trcll[ii] = trc[ii];
	}

        fits_read_compressed_img(fptr, TULONG, blcll, trcll, inc,
            nullcheck, NULL, array, flagval, anynul, status);
        return(*status);
    }

/*
    if this is a primary array, then the input COLNUM parameter should
    be interpreted as the row number, and we will alway read the image
    data from column 2 (any group parameters are in column 1).
*/
    if (ffghdt(fptr, &hdutype, status) > 0)
        return(*status);

    if (hdutype == IMAGE_HDU)
    {
        /* this is a primary array, or image extension */
        if (colnum == 0)
        {
            rstr = 1;
            rstp = 1;
        }
        else
        {
            rstr = colnum;
            rstp = colnum;
        }
        rinc = 1;
        numcol = 2;
    }
    else
    {
        /* this is a table, so the row info is in the (naxis+1) elements */
        rstr = blc[naxis];
        rstp = trc[naxis];
        rinc = inc[naxis];
        numcol = colnum;
    }

    nultyp = 2;
    if (anynul)
        *anynul = FALSE;

    i0 = 0;
    for (ii = 0; ii < 9; ii++)
    {
        str[ii] = 1;
        stp[ii] = 1;
        incr[ii] = 1;
        dsize[ii] = 1;
    }

    for (ii = 0; ii < naxis; ii++)
    {
      if (trc[ii] < blc[ii])
      {
        snprintf(msg, FLEN_ERRMSG,"ffgsvj: illegal range specified for axis %ld", ii + 1);
        ffpmsg(msg);
        return(*status = BAD_PIX_NUM);
      }

      str[ii] = blc[ii];
      stp[ii] = trc[ii];
      incr[ii] = inc[ii];
      dsize[ii + 1] = dsize[ii] * naxes[ii];
    }

    if (naxis == 1 && naxes[0] == 1)
    {
      /* This is not a vector column, so read all the rows at once */
      nelem = (rstp - rstr) / rinc + 1;
      ninc = rinc;
      rstp = rstr;
    }
    else
    {
      /* have to read each row individually, in all dimensions */
      nelem = (stp[0] - str[0]) / inc[0] + 1;
      ninc = incr[0];
    }

    for (row = rstr; row <= rstp; row += rinc)
    {
     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
     {
      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
      {
       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
       {
        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
        {
         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
         {
          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
          {
           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
           {
            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
            {
              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];

              if ( ffgcluj(fptr, numcol, row, felem, nelem, ninc, nultyp,
                   nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
                   return(*status);

              if (anyf && anynul)
                  *anynul = TRUE;

              i0 += nelem;
            }
           }
          }
         }
        }
       }
      }
     }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffggpuj(fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            long  firstelem,  /* I - first vector element to read (1 = 1st)  */
            long  nelem,      /* I - number of values to read                */
   unsigned long  *array,     /* O - array of values that are returned       */
            int  *status)     /* IO - error status                           */
/*
  Read an array of group parameters from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
*/
{
    long row;
    int idummy;
    char cdummy;
    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgcluj(fptr, 1, row, firstelem, nelem, 1, 1, 0L,
               array, &cdummy, &idummy, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcvuj(fitsfile *fptr,   /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
  unsigned long  nulval,     /* I - value for null pixels                   */
  unsigned long *array,      /* O - array of values that are read           */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Any undefined pixels will be set equal to the value of 'nulval' unless
  nulval = 0 in which case no checks for undefined pixels will be made.
*/
{
    char cdummy;

    ffgcluj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
           array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcfuj(fitsfile *fptr,   /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
  unsigned long  *array,     /* O - array of values that are read           */
           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Nularray will be set = 1 if the corresponding array pixel is undefined, 
  otherwise nularray will = 0.
*/
{
    unsigned long dummy = 0;

    ffgcluj(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
           array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcluj(fitsfile *fptr,   /* I - FITS file pointer                       */
            int  colnum,      /* I - number of column to read (1 = 1st col)  */
            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
            LONGLONG  firstelem, /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
            int   nultyp,     /* I - null value handling code:               */
                              /*     1: set undefined pixels = nulval        */
                              /*     2: set nularray=1 for undefined pixels  */
   unsigned long  nulval,     /* I - value for null pixels if nultyp = 1     */
   unsigned long  *array,     /* O - array of values that are read           */
            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU.
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer be a virtual column in a 1 or more grouped FITS primary
  array or image extension.  FITSIO treats a primary array as a binary table
  with 2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.

  The output array of values will be converted from the datatype of the column 
  and will be scaled by the FITS TSCALn and TZEROn values if necessary.
*/
{
    double scale, zero, power = 1., dtemp;
    int tcode, maxelem2, hdutype, xcode, decimals;
    long twidth, incre;
    long ii, xwidth, ntodo;
    int nulcheck;
    LONGLONG repeat, startpos, elemnum, readptr, tnull;
    LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
    char tform[20];
    char message[FLEN_ERRMSG];
    char snull[20];   /*  the FITS null value if reading from ASCII table  */

    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
    void *buffer;

    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
        return(*status);

    buffer = cbuff;

    if (anynul)
        *anynul = 0;

    if (nultyp == 2)
        memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if ( ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 0, &scale, &zero,
         tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
         return(*status);
    maxelem = maxelem2;

    incre *= elemincre;   /* multiply incre to just get every nth pixel */

    if (tcode == TSTRING)    /* setup for ASCII tables */
    {
      /* get the number of implied decimal places if no explicit decmal point */
      ffasfm(tform, &xcode, &xwidth, &decimals, status); 
      for(ii = 0; ii < decimals; ii++)
        power *= 10.;
    }
    /*------------------------------------------------------------------*/
    /*  Decide whether to check for null values in the input FITS file: */
    /*------------------------------------------------------------------*/
    nulcheck = nultyp; /* by default check for null values in the FITS file */

    if (nultyp == 1 && nulval == 0)
       nulcheck = 0;    /* calling routine does not want to check for nulls */

    else if (tcode%10 == 1 &&        /* if reading an integer column, and  */ 
            tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
            nulcheck = 0;            /* then do not check for null values. */

    else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
            nulcheck = 0;            /* Impossible null value */

    else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
            nulcheck = 0;            /* Impossible null value */

    else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
         nulcheck = 0;

    /*----------------------------------------------------------------------*/
    /*  If FITS column and output data array have same datatype, then we do */
    /*  not need to use a temporary buffer to store intermediate datatype.  */
    /*----------------------------------------------------------------------*/
    if ((tcode == TLONG) && (LONGSIZE == 32))  /* Special Case:                        */
    {                             /* no type convertion required, so read */
                                  /* data directly into output buffer.    */

        if (nelem < (LONGLONG)INT32_MAX/4) {
            maxelem = nelem;
        } else {
            maxelem = INT32_MAX/4;
        }
    }

    /*---------------------------------------------------------------------*/
    /*  Now read the pixels from the FITS column. If the column does not   */
    /*  have the same datatype as the output array, then we have to read   */
    /*  the raw values into a temporary buffer (of limited size).  In      */
    /*  the case of a vector colum read only 1 vector of values at a time  */
    /*  then skip to the next row if more values need to be read.          */
    /*  After reading the raw values, then call the fffXXYY routine to (1) */
    /*  test for undefined values, (2) convert the datatype if necessary,  */
    /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
    /*  scaling parameters.                                                */
    /*---------------------------------------------------------------------*/
    remain = nelem;           /* remaining number of values to read */
    next = 0;                 /* next element in array to be read   */
    rownum = 0;               /* row number, relative to firstrow   */

    while (remain)
    {
        /* limit the number of pixels to read at one time to the number that
           will fit in the buffer or to the number of pixels that remain in
           the current vector, which ever is smaller.
        */
        ntodo = (long) minvalue(remain, maxelem);      
        ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));

        readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));

        switch (tcode) 
        {
            case (TLONG):
	      if (LONGSIZE == 32) {
                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) &array[next],
                       status);
                fffi4u4((INT32BIT *) &array[next], ntodo, scale, zero,
                         nulcheck, (INT32BIT) tnull, nulval, &nularray[next],
                         anynul, &array[next], status);
	      } else { /* case where sizeof(long) = 8 */
                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer,
                       status);
                fffi4u4((INT32BIT *) buffer, ntodo, scale, zero,
                         nulcheck, (INT32BIT) tnull, nulval, &nularray[next],
                         anynul, &array[next], status);
	      }


                break;
            case (TLONGLONG):

                ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status);
                fffi8u4( (LONGLONG *) buffer, ntodo, scale, zero, 
                           nulcheck, tnull, nulval, &nularray[next], 
                            anynul, &array[next], status);
                break;
            case (TBYTE):
                ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer,
                       status);
                fffi1u4((unsigned char *) buffer, ntodo, scale, zero, nulcheck, 
                     (unsigned char) tnull, nulval, &nularray[next], anynul, 
                     &array[next], status);
                break;
            case (TSHORT):
                ffgi2b(fptr, readptr, ntodo, incre, (short  *) buffer, status);
                fffi2u4((short  *) buffer, ntodo, scale, zero, nulcheck, 
                      (short) tnull, nulval, &nularray[next], anynul, 
                      &array[next], status);
                break;
            case (TFLOAT):
                ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
                fffr4u4((float  *) buffer, ntodo, scale, zero, nulcheck, 
                       nulval, &nularray[next], anynul, 
                       &array[next], status);
                break;
            case (TDOUBLE):
                ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
                fffr8u4((double *) buffer, ntodo, scale, zero, nulcheck, 
                          nulval, &nularray[next], anynul, 
                          &array[next], status);
                break;
            case (TSTRING):
                ffmbyt(fptr, readptr, REPORT_EOF, status);
       
                if (incre == twidth)    /* contiguous bytes */
                     ffgbyt(fptr, ntodo * twidth, buffer, status);
                else
                     ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
                               status);

                fffstru4((char *) buffer, ntodo, scale, zero, twidth, power,
                     nulcheck, snull, nulval, &nularray[next], anynul,
                     &array[next], status);
                break;

            default:  /*  error trap for invalid column format */
                snprintf(message,FLEN_ERRMSG, 
                   "Cannot read numbers from column %d which has format %s",
                    colnum, tform);
                ffpmsg(message);
                if (hdutype == ASCII_TBL)
                    return(*status = BAD_ATABLE_FORMAT);
                else
                    return(*status = BAD_BTABLE_FORMAT);

        } /* End of switch block */

        /*-------------------------*/
        /*  Check for fatal error  */
        /*-------------------------*/
        if (*status > 0)  /* test for error during previous read operation */
        {
	  dtemp = (double) next;
          if (hdutype > 0)
            snprintf(message,FLEN_ERRMSG,
            "Error reading elements %.0f thru %.0f from column %d (ffgcluj).",
              dtemp+1., dtemp+ntodo, colnum);
          else
            snprintf(message,FLEN_ERRMSG,
            "Error reading elements %.0f thru %.0f from image (ffgcluj).",
              dtemp+1., dtemp+ntodo);

          ffpmsg(message);
          return(*status);
        }

        /*--------------------------------------------*/
        /*  increment the counters for the next loop  */
        /*--------------------------------------------*/
        remain -= ntodo;
        if (remain)
        {
            next += ntodo;
            elemnum = elemnum + (ntodo * elemincre);

            if (elemnum >= repeat)  /* completed a row; start on later row */
            {
                rowincre = elemnum / repeat;
                rownum += rowincre;
                elemnum = elemnum - (rowincre * repeat);
            }
        }
    }  /*  End of main while Loop  */


    /*--------------------------------*/
    /*  check for numerical overflow  */
    /*--------------------------------*/
    if (*status == OVERFLOW_ERR)
    {
        ffpmsg(
        "Numerical overflow during type conversion while reading FITS data.");
        *status = NUM_OVERFLOW;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi1u4(unsigned char *input, /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
   unsigned long nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
   unsigned long *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
                output[ii] = (unsigned long) input[ii];  /* copy input */
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DULONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DULONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = ULONG_MAX;
                }
                else
                    output[ii] = (unsigned long) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = (unsigned long) input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DULONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DULONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = ULONG_MAX;
                    }
                    else
                        output[ii] = (unsigned long) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi2u4(short *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            short tnull,          /* I - value of FITS TNULLn keyword if any */
   unsigned long nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
   unsigned long *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < 0)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else
                    output[ii] = (unsigned long) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DULONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DULONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = ULONG_MAX;
                }
                else
                    output[ii] = (unsigned long) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    if (input[ii] < 0)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else
                        output[ii] = (unsigned long) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DULONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DULONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = ULONG_MAX;
                    }
                    else
                        output[ii] = (unsigned long) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi4u4(INT32BIT *input,      /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
   unsigned long nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
   unsigned long *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 2147483648.)
        {       
           /* Instead of adding 2147483648, it is more efficient */
           /* to just flip the sign bit with the XOR operator */

            for (ii = 0; ii < ntodo; ii++) {
               output[ii] =  ( *(unsigned int *) &input[ii] ) ^ 0x80000000;
	    }
        }
        else if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < 0)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else
                    output[ii] = (unsigned long) input[ii]; /* copy input */
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DULONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DULONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = ULONG_MAX;
                }
                else
                    output[ii] = (unsigned long) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 2147483648.) 
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                   output[ii] =  ( *(unsigned int *) &input[ii] ) ^ 0x80000000;
            }
        }
        else if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else if (input[ii] < 0)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else
                    output[ii] = (unsigned long) input[ii]; /* copy input */
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DULONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DULONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = ULONG_MAX;
                    }
                    else
                        output[ii] = (unsigned long) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi8u4(LONGLONG *input,      /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
   unsigned long nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
   unsigned long *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < 0)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (input[ii] > ULONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = ULONG_MAX;
                }
                else
                    output[ii] = (unsigned long) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DULONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DULONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = ULONG_MAX;
                }
                else
                    output[ii] = (unsigned long) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    if (input[ii] < 0)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (input[ii] > ULONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = ULONG_MAX;
                    }
                    else
                        output[ii] = (unsigned long) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DULONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DULONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = ULONG_MAX;
                    }
                    else
                        output[ii] = (unsigned long) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffr4u4(float *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
   unsigned long nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
   unsigned long *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to NaN.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;
    short *sptr, iret;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < DULONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (input[ii] > DULONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = ULONG_MAX;
                }
                else
                    output[ii] = (unsigned long) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DULONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DULONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = ULONG_MAX;
                }
                else
                    output[ii] = (unsigned long) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        sptr = (short *) input;

#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
        sptr++;       /* point to MSBs */
#endif

        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++, sptr += 2)
            {
              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                     output[ii] = 0;
              }
              else
                {
                    if (input[ii] < DULONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (input[ii] > DULONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = ULONG_MAX;
                    }
                    else
                        output[ii] = (unsigned long) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++, sptr += 2)
            {
              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {  
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                  { 
                    if (zero < DULONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (zero > DULONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = ULONG_MAX;
                    }
                    else
                      output[ii] = (unsigned long) zero;
                  }
              }
              else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DULONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DULONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = ULONG_MAX;
                    }
                    else
                        output[ii] = (unsigned long) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffr8u4(double *input,        /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
   unsigned long nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
   unsigned long *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to NaN.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;
    short *sptr, iret;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < DULONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (input[ii] > DULONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = ULONG_MAX;
                }
                else
                    output[ii] = (unsigned long) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DULONG_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DULONG_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = ULONG_MAX;
                }
                else
                    output[ii] = (unsigned long) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        sptr = (short *) input;

#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
        sptr += 3;       /* point to MSBs */
#endif
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++, sptr += 4)
            {
              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                     output[ii] = 0;
              }
              else
                {
                    if (input[ii] < DULONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (input[ii] > DULONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = ULONG_MAX;
                    }
                    else
                        output[ii] = (unsigned long) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++, sptr += 4)
            {
              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {  
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                  { 
                    if (zero < DULONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (zero > DULONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = ULONG_MAX;
                    }
                    else
                      output[ii] = (unsigned long) zero;
                  }
              }
              else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DULONG_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DULONG_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = ULONG_MAX;
                    }
                    else
                        output[ii] = (unsigned long) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffstru4(char *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            long twidth,          /* I - width of each substring of chars    */
            double implipower,    /* I - power of 10 of implied decimal      */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            char  *snull,         /* I - value of FITS null string, if any   */
   unsigned long nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
   unsigned long *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file. Check
  for null values and do scaling if required. The nullcheck code value
  determines how any null values in the input array are treated. A null
  value is an input pixel that is equal to snull.  If nullcheck= 0, then
  no special checking for nulls is performed.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    int nullen;
    long ii;
    double dvalue;
    char *cstring, message[FLEN_ERRMSG];
    char *cptr, *tpos;
    char tempstore, chrzero = '0';
    double val, power;
    int exponent, sign, esign, decpt;

    nullen = strlen(snull);
    cptr = input;  /* pointer to start of input string */
    for (ii = 0; ii < ntodo; ii++)
    {
      cstring = cptr;
      /* temporarily insert a null terminator at end of the string */
      tpos = cptr + twidth;
      tempstore = *tpos;
      *tpos = 0;

      /* check if null value is defined, and if the    */
      /* column string is identical to the null string */
      if (snull[0] != ASCII_NULL_UNDEFINED && 
         !strncmp(snull, cptr, nullen) )
      {
        if (nullcheck)  
        {
          *anynull = 1;    
          if (nullcheck == 1)
            output[ii] = nullval;
          else
            nullarray[ii] = 1;
        }
        cptr += twidth;
      }
      else
      {
        /* value is not the null value, so decode it */
        /* remove any embedded blank characters from the string */

        decpt = 0;
        sign = 1;
        val  = 0.;
        power = 1.;
        exponent = 0;
        esign = 1;

        while (*cptr == ' ')               /* skip leading blanks */
           cptr++;

        if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
        {
          if (*cptr == '-')
             sign = -1;

          cptr++;

          while (*cptr == ' ')         /* skip blanks between sign and value */
            cptr++;
        }

        while (*cptr >= '0' && *cptr <= '9')
        {
          val = val * 10. + *cptr - chrzero;  /* accumulate the value */
          cptr++;

          while (*cptr == ' ')         /* skip embedded blanks in the value */
            cptr++;
        }

        if (*cptr == '.' || *cptr == ',')       /* check for decimal point */
        {
          decpt = 1;       /* set flag to show there was a decimal point */
          cptr++;
          while (*cptr == ' ')         /* skip any blanks */
            cptr++;

          while (*cptr >= '0' && *cptr <= '9')
          {
            val = val * 10. + *cptr - chrzero;  /* accumulate the value */
            power = power * 10.;
            cptr++;

            while (*cptr == ' ')         /* skip embedded blanks in the value */
              cptr++;
          }
        }

        if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
        {
          cptr++;
          while (*cptr == ' ')         /* skip blanks */
              cptr++;
  
          if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
          {
            if (*cptr == '-')
               esign = -1;

            cptr++;

            while (*cptr == ' ')        /* skip blanks between sign and exp */
              cptr++;
          }

          while (*cptr >= '0' && *cptr <= '9')
          {
            exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
            cptr++;

            while (*cptr == ' ')         /* skip embedded blanks */
              cptr++;
          }
        }

        if (*cptr  != 0)  /* should end up at the null terminator */
        {
          snprintf(message, FLEN_ERRMSG,"Cannot read number from ASCII table");
          ffpmsg(message);
          snprintf(message, FLEN_ERRMSG,"Column field = %s.", cstring);
          ffpmsg(message);
          /* restore the char that was overwritten by the null */
          *tpos = tempstore;
          return(*status = BAD_C2D);
        }

        if (!decpt)  /* if no explicit decimal, use implied */
           power = implipower;

        dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));

        dvalue = dvalue * scale + zero;   /* apply the scaling */

        if (dvalue < DULONG_MIN)
        {
            *status = OVERFLOW_ERR;
            output[ii] = 0;
        }
        else if (dvalue > DULONG_MAX)
        {
            *status = OVERFLOW_ERR;
            output[ii] = ULONG_MAX;
        }
        else
            output[ii] = (unsigned long) dvalue;
      }
      /* restore the char that was overwritten by the null */
      *tpos = tempstore;
    }
    return(*status);
}
cfitsio/getcoluk.c0000644000225700000360000021771313246025103013774 0ustar  cagordonlhea/*  This file, getcolk.c, contains routines that read data elements from   */
/*  a FITS image or table, with 'unsigned int' data type.                  */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include 
#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int ffgpvuk( fitsfile *fptr,   /* I - FITS file pointer                      */
            long  group,      /* I - group to read (1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
   unsigned int   nulval,     /* I - value for undefined pixels              */
   unsigned int   *array,     /* O - array of values that are returned       */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Undefined elements will be set equal to NULVAL, unless NULVAL=0
  in which case no checking for undefined values will be performed.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    long row;
    char cdummy;
    int nullcheck = 1;
    unsigned int nullvalue;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */
         nullvalue = nulval;  /* set local variable */

        fits_read_compressed_pixels(fptr, TUINT, firstelem, nelem,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgcluk(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
               array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgpfuk(fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
   unsigned int   *array,     /* O - array of values that are returned       */
            char *nularray,   /* O - array of null pixel flags               */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
  Any undefined pixels in the returned array will be set = 0 and the 
  corresponding nularray value will be set = 1.
  ANYNUL is returned with a value of .true. if any pixels are undefined.
*/
{
    long row;
    int nullcheck = 2;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_read_compressed_pixels(fptr, TUINT, firstelem, nelem,
            nullcheck, NULL, array, nularray, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgcluk(fptr, 2, row, firstelem, nelem, 1, 2, 0L,
               array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffg2duk(fitsfile *fptr,  /* I - FITS file pointer                       */
           long  group,     /* I - group to read (1 = 1st group)           */
  unsigned int  nulval,    /* set undefined pixels equal to this          */
           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
  unsigned int  *array,    /* O - array to be filled and returned         */
           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
           int  *status)    /* IO - error status                           */
/*
  Read an entire 2-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being read).  Any null
  values in the array will be set equal to the value of nulval, unless
  nulval = 0 in which case no null checking will be performed.
*/
{
    /* call the 3D reading routine, with the 3rd dimension = 1 */

    ffg3duk(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, 
           anynul, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffg3duk(fitsfile *fptr,  /* I - FITS file pointer                       */
           long  group,     /* I - group to read (1 = 1st group)           */
  unsigned int   nulval,    /* set undefined pixels equal to this          */
           LONGLONG  ncols,     /* I - number of pixels in each row of array   */
           LONGLONG  nrows,     /* I - number of rows in each plane of array   */
           LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
           LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
           LONGLONG  naxis3,    /* I - FITS image NAXIS3 value                 */
  unsigned int   *array,    /* O - array to be filled and returned         */
           int  *anynul,    /* O - set to 1 if any values are null; else 0 */
           int  *status)    /* IO - error status                           */
/*
  Read an entire 3-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being read).  Any null
  values in the array will be set equal to the value of nulval, unless
  nulval = 0 in which case no null checking will be performed.
*/
{
    long tablerow, ii, jj;
    char cdummy;
    int nullcheck = 1;
    long inc[] = {1,1,1};
    LONGLONG fpixel[] = {1,1,1}, nfits, narray;
    LONGLONG lpixel[3];
    unsigned int nullvalue;

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        lpixel[0] = ncols;
        lpixel[1] = nrows;
        lpixel[2] = naxis3;
        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_img(fptr, TUINT, fpixel, lpixel, inc,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */
    tablerow=maxvalue(1,group);

    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
    {
       /* all the image pixels are contiguous, so read all at once */
       ffgcluk(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval,
               array, &cdummy, anynul, status);
       return(*status);
    }

    if (ncols < naxis1 || nrows < naxis2)
       return(*status = BAD_DIMEN);

    nfits = 1;   /* next pixel in FITS image to read */
    narray = 0;  /* next pixel in output array to be filled */

    /* loop over naxis3 planes in the data cube */
    for (jj = 0; jj < naxis3; jj++)
    {
      /* loop over the naxis2 rows in the FITS image, */
      /* reading naxis1 pixels to each row            */

      for (ii = 0; ii < naxis2; ii++)
      {
       if (ffgcluk(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval,
          &array[narray], &cdummy, anynul, status) > 0)
          return(*status);

       nfits += naxis1;
       narray += ncols;
      }
      narray += (nrows - naxis2) * ncols;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsvuk(fitsfile *fptr, /* I - FITS file pointer                         */
           int  colnum,    /* I - number of the column to read (1 = 1st)    */
           int naxis,      /* I - number of dimensions in the FITS array    */
           long  *naxes,   /* I - size of each dimension                    */
           long  *blc,     /* I - 'bottom left corner' of the subsection    */
           long  *trc,     /* I - 'top right corner' of the subsection      */
           long  *inc,     /* I - increment to be applied in each dimension */
  unsigned int  nulval,    /* I - value to set undefined pixels             */
  unsigned int  *array,    /* O - array to be filled and returned           */
           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
           int  *status)   /* IO - error status                             */
/*
  Read a subsection of data values from an image or a table column.
  This routine is set up to handle a maximum of nine dimensions.
*/
{
    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
    long str[9],stp[9],incr[9];
    long nelem, nultyp, ninc, numcol;
    LONGLONG felem, dsize[10], blcll[9], trcll[9];
    int hdutype, anyf;
    char ldummy, msg[FLEN_ERRMSG];
    int nullcheck = 1;
    unsigned int nullvalue;

    if (naxis < 1 || naxis > 9)
    {
        snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvuk is out of range", naxis);
        ffpmsg(msg);
        return(*status = BAD_DIMEN);
    }

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        for (ii=0; ii < naxis; ii++) {
	    blcll[ii] = blc[ii];
	    trcll[ii] = trc[ii];
	}

        nullvalue = nulval;  /* set local variable */

        fits_read_compressed_img(fptr, TUINT, blcll, trcll, inc,
            nullcheck, &nullvalue, array, NULL, anynul, status);
        return(*status);
    }

/*
    if this is a primary array, then the input COLNUM parameter should
    be interpreted as the row number, and we will alway read the image
    data from column 2 (any group parameters are in column 1).
*/
    if (ffghdt(fptr, &hdutype, status) > 0)
        return(*status);

    if (hdutype == IMAGE_HDU)
    {
        /* this is a primary array, or image extension */
        if (colnum == 0)
        {
            rstr = 1;
            rstp = 1;
        }
        else
        {
            rstr = colnum;
            rstp = colnum;
        }
        rinc = 1;
        numcol = 2;
    }
    else
    {
        /* this is a table, so the row info is in the (naxis+1) elements */
        rstr = blc[naxis];
        rstp = trc[naxis];
        rinc = inc[naxis];
        numcol = colnum;
    }

    nultyp = 1;
    if (anynul)
        *anynul = FALSE;

    i0 = 0;
    for (ii = 0; ii < 9; ii++)
    {
        str[ii] = 1;
        stp[ii] = 1;
        incr[ii] = 1;
        dsize[ii] = 1;
    }

    for (ii = 0; ii < naxis; ii++)
    {
      if (trc[ii] < blc[ii])
      {
        snprintf(msg, FLEN_ERRMSG,"ffgsvuk: illegal range specified for axis %ld", ii + 1);
        ffpmsg(msg);
        return(*status = BAD_PIX_NUM);
      }

      str[ii] = blc[ii];
      stp[ii] = trc[ii];
      incr[ii] = inc[ii];
      dsize[ii + 1] = dsize[ii] * naxes[ii];
    }

    if (naxis == 1 && naxes[0] == 1)
    {
      /* This is not a vector column, so read all the rows at once */
      nelem = (rstp - rstr) / rinc + 1;
      ninc = rinc;
      rstp = rstr;
    }
    else
    {
      /* have to read each row individually, in all dimensions */
      nelem = (stp[0] - str[0]) / inc[0] + 1;
      ninc = incr[0];
    }

    for (row = rstr; row <= rstp; row += rinc)
    {
     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
     {
      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
      {
       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
       {
        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
        {
         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
         {
          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
          {
           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
           {
            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
            {
              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];

              if ( ffgcluk(fptr, numcol, row, felem, nelem, ninc, nultyp,
                   nulval, &array[i0], &ldummy, &anyf, status) > 0)
                   return(*status);

              if (anyf && anynul)
                  *anynul = TRUE;

              i0 += nelem;
            }
           }
          }
         }
        }
       }
      }
     }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsfuk(fitsfile *fptr, /* I - FITS file pointer                         */
           int  colnum,    /* I - number of the column to read (1 = 1st)    */
           int naxis,      /* I - number of dimensions in the FITS array    */
           long  *naxes,   /* I - size of each dimension                    */
           long  *blc,     /* I - 'bottom left corner' of the subsection    */
           long  *trc,     /* I - 'top right corner' of the subsection      */
           long  *inc,     /* I - increment to be applied in each dimension */
  unsigned int  *array,    /* O - array to be filled and returned           */
           char *flagval,  /* O - set to 1 if corresponding value is null   */
           int  *anynul,   /* O - set to 1 if any values are null; else 0   */
           int  *status)   /* IO - error status                             */
/*
  Read a subsection of data values from an image or a table column.
  This routine is set up to handle a maximum of nine dimensions.
*/
{
    long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
    long str[9],stp[9],incr[9],dsize[10];
    LONGLONG blcll[9], trcll[9];
    long felem, nelem, nultyp, ninc, numcol;
    long nulval = 0;
    int hdutype, anyf;
    char msg[FLEN_ERRMSG];
    int nullcheck = 2;

    if (naxis < 1 || naxis > 9)
    {
        snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvj is out of range", naxis);
        ffpmsg(msg);
        return(*status = BAD_DIMEN);
    }

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        for (ii=0; ii < naxis; ii++) {
	    blcll[ii] = blc[ii];
	    trcll[ii] = trc[ii];
	}

        fits_read_compressed_img(fptr, TUINT, blcll, trcll, inc,
            nullcheck, NULL, array, flagval, anynul, status);
        return(*status);
    }

/*
    if this is a primary array, then the input COLNUM parameter should
    be interpreted as the row number, and we will alway read the image
    data from column 2 (any group parameters are in column 1).
*/
    if (ffghdt(fptr, &hdutype, status) > 0)
        return(*status);

    if (hdutype == IMAGE_HDU)
    {
        /* this is a primary array, or image extension */
        if (colnum == 0)
        {
            rstr = 1;
            rstp = 1;
        }
        else
        {
            rstr = colnum;
            rstp = colnum;
        }
        rinc = 1;
        numcol = 2;
    }
    else
    {
        /* this is a table, so the row info is in the (naxis+1) elements */
        rstr = blc[naxis];
        rstp = trc[naxis];
        rinc = inc[naxis];
        numcol = colnum;
    }

    nultyp = 2;
    if (anynul)
        *anynul = FALSE;

    i0 = 0;
    for (ii = 0; ii < 9; ii++)
    {
        str[ii] = 1;
        stp[ii] = 1;
        incr[ii] = 1;
        dsize[ii] = 1;
    }

    for (ii = 0; ii < naxis; ii++)
    {
      if (trc[ii] < blc[ii])
      {
        snprintf(msg, FLEN_ERRMSG,"ffgsvj: illegal range specified for axis %ld", ii + 1);
        ffpmsg(msg);
        return(*status = BAD_PIX_NUM);
      }

      str[ii] = blc[ii];
      stp[ii] = trc[ii];
      incr[ii] = inc[ii];
      dsize[ii + 1] = dsize[ii] * naxes[ii];
    }

    if (naxis == 1 && naxes[0] == 1)
    {
      /* This is not a vector column, so read all the rows at once */
      nelem = (rstp - rstr) / rinc + 1;
      ninc = rinc;
      rstp = rstr;
    }
    else
    {
      /* have to read each row individually, in all dimensions */
      nelem = (stp[0] - str[0]) / inc[0] + 1;
      ninc = incr[0];
    }

    for (row = rstr; row <= rstp; row += rinc)
    {
     for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
     {
      for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
      {
       for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
       {
        for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
        {
         for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
         {
          for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
          {
           for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
           {
            for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
            {
              felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
                             (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
                             (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
                             (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];

              if ( ffgcluk(fptr, numcol, row, felem, nelem, ninc, nultyp,
                   nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
                   return(*status);

              if (anyf && anynul)
                  *anynul = TRUE;

              i0 += nelem;
            }
           }
          }
         }
        }
       }
      }
     }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffggpuk( fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to read (1 = 1st group)           */
            long  firstelem,  /* I - first vector element to read (1 = 1st)  */
            long  nelem,      /* I - number of values to read                */
   unsigned int  *array,     /* O - array of values that are returned       */
            int  *status)     /* IO - error status                           */
/*
  Read an array of group parameters from the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being read).
*/
{
    long row;
    int idummy;
    char cdummy;
    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffgcluk(fptr, 1, row, firstelem, nelem, 1, 1, 0L,
               array, &cdummy, &idummy, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcvuk(fitsfile *fptr,   /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
  unsigned int   nulval,     /* I - value for null pixels                   */
  unsigned int  *array,      /* O - array of values that are read           */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Any undefined pixels will be set equal to the value of 'nulval' unless
  nulval = 0 in which case no checks for undefined pixels will be made.
*/
{
    char cdummy;

    ffgcluk(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
           array, &cdummy, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcfuk(fitsfile *fptr,   /* I - FITS file pointer                       */
           int  colnum,      /* I - number of column to read (1 = 1st col)  */
           LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
           LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
           LONGLONG  nelem,      /* I - number of values to read                */
  unsigned int   *array,     /* O - array of values that are read           */
           char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
           int  *anynul,     /* O - set to 1 if any values are null; else 0 */
           int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU. Automatic
  datatype conversion will be performed if the datatype of the column does not
  match the datatype of the array parameter. The output values will be scaled 
  by the FITS TSCALn and TZEROn values if these values have been defined.
  Nularray will be set = 1 if the corresponding array pixel is undefined, 
  otherwise nularray will = 0.
*/
{
    int dummy = 0;

    ffgcluk(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
           array, nularray, anynul, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcluk( fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,      /* I - number of column to read (1 = 1st col)  */
            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
            LONGLONG firstelem,  /* I - first vector element to read (1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to read                */
            long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
            int   nultyp,     /* I - null value handling code:               */
                              /*     1: set undefined pixels = nulval        */
                              /*     2: set nularray=1 for undefined pixels  */
   unsigned int   nulval,     /* I - value for null pixels if nultyp = 1     */
   unsigned int  *array,      /* O - array of values that are read           */
            char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
  Read an array of values from a column in the current FITS HDU.
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer be a virtual column in a 1 or more grouped FITS primary
  array or image extension.  FITSIO treats a primary array as a binary table
  with 2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.

  The output array of values will be converted from the datatype of the column 
  and will be scaled by the FITS TSCALn and TZEROn values if necessary.
*/
{
    double scale, zero, power = 1., dtemp;
    int tcode, maxelem2, hdutype, xcode, decimals;
    long twidth, incre;
    long ii, xwidth, ntodo;
    int nulcheck;
    LONGLONG repeat, startpos, elemnum, readptr, tnull;
    LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
    char tform[20];
    char message[FLEN_ERRMSG];
    char snull[20];   /*  the FITS null value if reading from ASCII table  */

    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
    void *buffer;

    if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
        return(*status);

    /* call the 'short' or 'long' version of this routine, if possible */
    if (sizeof(int) == sizeof(short))
        ffgclui(fptr, colnum, firstrow, firstelem, nelem, elemincre, nultyp,
          (unsigned short) nulval, (unsigned short *) array, nularray, anynul,
           status);
    else if (sizeof(int) == sizeof(long))
        ffgcluj(fptr, colnum, firstrow, firstelem, nelem, elemincre, nultyp,
          (unsigned long) nulval, (unsigned long *) array, nularray, anynul,
          status);
    else
    {
    /*
      This is a special case: sizeof(int) is not equal to sizeof(short) or
      sizeof(long).  This occurs on Alpha OSF systems where short = 2 bytes,
      int = 4 bytes, and long = 8 bytes.
    */

    buffer = cbuff;

    if (anynul)
        *anynul = 0;

    if (nultyp == 2)
        memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if ( ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 0, &scale, &zero,
         tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
         return(*status);
    maxelem = maxelem2;

    incre *= elemincre;   /* multiply incre to just get every nth pixel */

    if (tcode == TSTRING)    /* setup for ASCII tables */
    {
      /* get the number of implied decimal places if no explicit decmal point */
      ffasfm(tform, &xcode, &xwidth, &decimals, status); 
      for(ii = 0; ii < decimals; ii++)
        power *= 10.;
    }
    /*------------------------------------------------------------------*/
    /*  Decide whether to check for null values in the input FITS file: */
    /*------------------------------------------------------------------*/
    nulcheck = nultyp; /* by default check for null values in the FITS file */

    if (nultyp == 1 && nulval == 0)
       nulcheck = 0;    /* calling routine does not want to check for nulls */

    else if (tcode%10 == 1 &&        /* if reading an integer column, and  */ 
            tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
            nulcheck = 0;            /* then do not check for null values. */

    else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
            nulcheck = 0;            /* Impossible null value */

    else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
            nulcheck = 0;            /* Impossible null value */

    else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
         nulcheck = 0;

    /*----------------------------------------------------------------------*/
    /*  If FITS column and output data array have same datatype, then we do */
    /*  not need to use a temporary buffer to store intermediate datatype.  */
    /*----------------------------------------------------------------------*/
    if (tcode == TLONG)  /* Special Case: */
    {                             /* data are 4-bytes long, so read       */
                                  /* data directly into output buffer.    */

        if (nelem < (LONGLONG)INT32_MAX/4) {
            maxelem = nelem;
        } else {
            maxelem = INT32_MAX/4;
        }
    }

    /*---------------------------------------------------------------------*/
    /*  Now read the pixels from the FITS column. If the column does not   */
    /*  have the same datatype as the output array, then we have to read   */
    /*  the raw values into a temporary buffer (of limited size).  In      */
    /*  the case of a vector colum read only 1 vector of values at a time  */
    /*  then skip to the next row if more values need to be read.          */
    /*  After reading the raw values, then call the fffXXYY routine to (1) */
    /*  test for undefined values, (2) convert the datatype if necessary,  */
    /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
    /*  scaling parameters.                                                */
    /*---------------------------------------------------------------------*/
    remain = nelem;           /* remaining number of values to read */
    next = 0;                 /* next element in array to be read   */
    rownum = 0;               /* row number, relative to firstrow   */

    while (remain)
    {
        /* limit the number of pixels to read at one time to the number that
           will fit in the buffer or to the number of pixels that remain in
           the current vector, which ever is smaller.
        */
        ntodo = (long) minvalue(remain, maxelem);      
        ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));

        readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));

        switch (tcode) 
        {
            case (TLONG):
                ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) &array[next],
                       status);
                    fffi4uint((INT32BIT *) &array[next], ntodo, scale, zero, 
                           nulcheck, (INT32BIT) tnull, nulval, &nularray[next],
                           anynul, &array[next], status);
                break;
            case (TLONGLONG):

                ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status);
                fffi8uint( (LONGLONG *) buffer, ntodo, scale, zero, 
                           nulcheck, tnull, nulval, &nularray[next], 
                            anynul, &array[next], status);
                break;
            case (TBYTE):
                ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer,
                       status);
                fffi1uint((unsigned char *) buffer, ntodo, scale, zero,nulcheck,
                     (unsigned char) tnull, nulval, &nularray[next], anynul, 
                     &array[next], status);
                break;
            case (TSHORT):
                ffgi2b(fptr, readptr, ntodo, incre, (short  *) buffer, status);
                fffi2uint((short  *) buffer, ntodo, scale, zero, nulcheck, 
                      (short) tnull, nulval, &nularray[next], anynul, 
                      &array[next], status);
                break;
            case (TFLOAT):
                ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
                fffr4uint((float  *) buffer, ntodo, scale, zero, nulcheck, 
                       nulval, &nularray[next], anynul, 
                       &array[next], status);
                break;
            case (TDOUBLE):
                ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
                fffr8uint((double *) buffer, ntodo, scale, zero, nulcheck, 
                          nulval, &nularray[next], anynul, 
                          &array[next], status);
                break;
            case (TSTRING):
                ffmbyt(fptr, readptr, REPORT_EOF, status);
       
                if (incre == twidth)    /* contiguous bytes */
                     ffgbyt(fptr, ntodo * twidth, buffer, status);
                else
                     ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
                               status);

                fffstruint((char *) buffer, ntodo, scale, zero, twidth, power,
                     nulcheck, snull, nulval, &nularray[next], anynul,
                     &array[next], status);
                break;

            default:  /*  error trap for invalid column format */
                snprintf(message, FLEN_ERRMSG,
                   "Cannot read numbers from column %d which has format %s",
                    colnum, tform);
                ffpmsg(message);
                if (hdutype == ASCII_TBL)
                    return(*status = BAD_ATABLE_FORMAT);
                else
                    return(*status = BAD_BTABLE_FORMAT);

        } /* End of switch block */

        /*-------------------------*/
        /*  Check for fatal error  */
        /*-------------------------*/
        if (*status > 0)  /* test for error during previous read operation */
        {
	  dtemp = (double) next;
          if (hdutype > 0)
            snprintf(message,FLEN_ERRMSG,
            "Error reading elements %.0f thru %.0f from column %d (ffgcluk).",
              dtemp+1., dtemp+ntodo, colnum);
          else
            snprintf(message,FLEN_ERRMSG,
            "Error reading elements %.0f thru %.0f from image (ffgcluk).",
              dtemp+1., dtemp+ntodo);

          ffpmsg(message);
          return(*status);
        }

        /*--------------------------------------------*/
        /*  increment the counters for the next loop  */
        /*--------------------------------------------*/
        remain -= ntodo;
        if (remain)
        {
            next += ntodo;
            elemnum = elemnum + (ntodo * elemincre);

            if (elemnum >= repeat)  /* completed a row; start on later row */
            {
                rowincre = elemnum / repeat;
                rownum += rowincre;
                elemnum = elemnum - (rowincre * repeat);
            }
        }
    }  /*  End of main while Loop  */


    /*--------------------------------*/
    /*  check for numerical overflow  */
    /*--------------------------------*/
    if (*status == OVERFLOW_ERR)
    {
        ffpmsg(
        "Numerical overflow during type conversion while reading FITS data.");
        *status = NUM_OVERFLOW;
    }

    }  /* end of DEC Alpha special case */

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi1uint(unsigned char *input,/* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
   unsigned int  nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
   unsigned int  *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
                output[ii] = (unsigned int) input[ii];  /* copy input */
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DUINT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DUINT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = UINT_MAX;
                }
                else
                    output[ii] = (unsigned int) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                    output[ii] = (unsigned int) input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DUINT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DUINT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UINT_MAX;
                    }
                    else
                        output[ii] = (unsigned int) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi2uint(short *input,        /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            short tnull,          /* I - value of FITS TNULLn keyword if any */
   unsigned int  nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
   unsigned int  *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < 0)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else
                    output[ii] = (unsigned int) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DUINT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DUINT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = UINT_MAX;
                }
                else
                    output[ii] = (unsigned int) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    if (input[ii] < 0)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else
                        output[ii] = (unsigned int) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DUINT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DUINT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UINT_MAX;
                    }
                    else
                        output[ii] = (unsigned int) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi4uint(INT32BIT *input,    /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
   unsigned int  nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
   unsigned int  *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 2147483648.)
        {       
           /* Instead of adding 2147483648, it is more efficient */
           /* to just flip the sign bit with the XOR operator */

            for (ii = 0; ii < ntodo; ii++)
               output[ii] =  ( *(unsigned int *) &input[ii] ) ^ 0x80000000;
        }
        else if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < 0)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else
                    output[ii] = (unsigned int) input[ii]; /* copy to output */
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DUINT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DUINT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = UINT_MAX;
                }
                else
                    output[ii] = (unsigned int) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 2147483648.) 
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                   output[ii] =  ( *(unsigned int *) &input[ii] ) ^ 0x80000000;
            }
        }
        else if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else if (input[ii] < 0)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else
                    output[ii] = (unsigned int) input[ii];
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DUINT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DUINT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UINT_MAX;
                    }
                    else
                        output[ii] = (unsigned int) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffi8uint(LONGLONG *input,    /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
   unsigned int  nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
   unsigned int  *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to tnull.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < 0)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (input[ii] > UINT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = UINT_MAX;
                }
                else
                    output[ii] = (unsigned int) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DUINT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DUINT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = UINT_MAX;
                }
                else
                    output[ii] = (unsigned int) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    if (input[ii] < 0)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (input[ii] > UINT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UINT_MAX;
                    }
                    else
                        output[ii] = (unsigned int) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DUINT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DUINT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UINT_MAX;
                    }
                    else
                        output[ii] = (unsigned int) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffr4uint(float *input,        /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
   unsigned int  nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
   unsigned int  *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to NaN.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;
    short *sptr, iret;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < DUINT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (input[ii] > DUINT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = UINT_MAX;
                }
                else
                    output[ii] = (unsigned int) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DUINT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DUINT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = UINT_MAX;
                }
                else
                    output[ii] = (unsigned int) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        sptr = (short *) input;

#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
        sptr++;       /* point to MSBs */
#endif

        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++, sptr += 2)
            {
              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                     output[ii] = 0;
              }
              else
                {
                    if (input[ii] < DUINT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (input[ii] > DUINT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UINT_MAX;
                    }
                    else
                        output[ii] = (unsigned int) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++, sptr += 2)
            {
              if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {  
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                  { 
                    if (zero < DUINT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (zero > DUINT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UINT_MAX;
                    }
                    else
                      output[ii] = (unsigned int) zero;
                  }
              }
              else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DUINT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DUINT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UINT_MAX;
                    }
                    else
                        output[ii] = (unsigned int) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffr8uint(double *input,       /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
   unsigned int  nullval,         /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
   unsigned int  *output,         /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file.
  Check for null values and do datatype conversion and scaling if required.
  The nullcheck code value determines how any null values in the input array
  are treated.  A null value is an input pixel that is equal to NaN.  If 
  nullcheck = 0, then no checking for nulls is performed and any null values
  will be transformed just like any other pixel.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    long ii;
    double dvalue;
    short *sptr, iret;

    if (nullcheck == 0)     /* no null checking required */
    {
        if (scale == 1. && zero == 0.)      /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] < DUINT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (input[ii] > DUINT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = UINT_MAX;
                }
                else
                    output[ii] = (unsigned int) input[ii];
            }
        }
        else             /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++)
            {
                dvalue = input[ii] * scale + zero;

                if (dvalue < DUINT_MIN)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = 0;
                }
                else if (dvalue > DUINT_MAX)
                {
                    *status = OVERFLOW_ERR;
                    output[ii] = UINT_MAX;
                }
                else
                    output[ii] = (unsigned int) dvalue;
            }
        }
    }
    else        /* must check for null values */
    {
        sptr = (short *) input;

#if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
        sptr += 3;       /* point to MSBs */
#endif
        if (scale == 1. && zero == 0.)  /* no scaling */
        {       
            for (ii = 0; ii < ntodo; ii++, sptr += 4)
            {
              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                     output[ii] = 0;
              }
              else
                {
                    if (input[ii] < DUINT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (input[ii] > DUINT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UINT_MAX;
                    }
                    else
                        output[ii] = (unsigned int) input[ii];
                }
            }
        }
        else                  /* must scale the data */
        {
            for (ii = 0; ii < ntodo; ii++, sptr += 4)
            {
              if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
              {
                  if (iret == 1)  /* is it a NaN? */
                  {  
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                  }
                  else            /* it's an underflow */
                  { 
                    if (zero < DUINT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (zero > DUINT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UINT_MAX;
                    }
                    else
                      output[ii] = (unsigned int) zero;
                  }
              }
              else
                {
                    dvalue = input[ii] * scale + zero;

                    if (dvalue < DUINT_MIN)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = 0;
                    }
                    else if (dvalue > DUINT_MAX)
                    {
                        *status = OVERFLOW_ERR;
                        output[ii] = UINT_MAX;
                    }
                    else
                        output[ii] = (unsigned int) dvalue;
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffstruint(char *input,        /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            long twidth,          /* I - width of each substring of chars    */
            double implipower,    /* I - power of 10 of implied decimal      */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            char  *snull,         /* I - value of FITS null string, if any   */
   unsigned int nullval,          /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
   unsigned int *output,          /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
  Copy input to output following reading of the input from a FITS file. Check
  for null values and do scaling if required. The nullcheck code value
  determines how any null values in the input array are treated. A null
  value is an input pixel that is equal to snull.  If nullcheck= 0, then
  no special checking for nulls is performed.  If nullcheck = 1, then the
  output pixel will be set = nullval if the corresponding input pixel is null.
  If nullcheck = 2, then if the pixel is null then the corresponding value of
  nullarray will be set to 1; the value of nullarray for non-null pixels 
  will = 0.  The anynull parameter will be set = 1 if any of the returned
  pixels are null, otherwise anynull will be returned with a value = 0;
*/
{
    int nullen;
    long ii;
    double dvalue;
    char *cstring, message[FLEN_ERRMSG];
    char *cptr, *tpos;
    char tempstore, chrzero = '0';
    double val, power;
    int exponent, sign, esign, decpt;

    nullen = strlen(snull);
    cptr = input;  /* pointer to start of input string */
    for (ii = 0; ii < ntodo; ii++)
    {
      cstring = cptr;
      /* temporarily insert a null terminator at end of the string */
      tpos = cptr + twidth;
      tempstore = *tpos;
      *tpos = 0;

      /* check if null value is defined, and if the    */
      /* column string is identical to the null string */
      if (snull[0] != ASCII_NULL_UNDEFINED && 
         !strncmp(snull, cptr, nullen) )
      {
        if (nullcheck)  
        {
          *anynull = 1;    
          if (nullcheck == 1)
            output[ii] = nullval;
          else
            nullarray[ii] = 1;
        }
        cptr += twidth;
      }
      else
      {
        /* value is not the null value, so decode it */
        /* remove any embedded blank characters from the string */

        decpt = 0;
        sign = 1;
        val  = 0.;
        power = 1.;
        exponent = 0;
        esign = 1;

        while (*cptr == ' ')               /* skip leading blanks */
           cptr++;

        if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
        {
          if (*cptr == '-')
             sign = -1;

          cptr++;

          while (*cptr == ' ')         /* skip blanks between sign and value */
            cptr++;
        }

        while (*cptr >= '0' && *cptr <= '9')
        {
          val = val * 10. + *cptr - chrzero;  /* accumulate the value */
          cptr++;

          while (*cptr == ' ')         /* skip embedded blanks in the value */
            cptr++;
        }

        if (*cptr == '.' || *cptr == ',')       /* check for decimal point */
        {
          decpt = 1;       /* set flag to show there was a decimal point */
          cptr++;
          while (*cptr == ' ')         /* skip any blanks */
            cptr++;

          while (*cptr >= '0' && *cptr <= '9')
          {
            val = val * 10. + *cptr - chrzero;  /* accumulate the value */
            power = power * 10.;
            cptr++;

            while (*cptr == ' ')         /* skip embedded blanks in the value */
              cptr++;
          }
        }

        if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
        {
          cptr++;
          while (*cptr == ' ')         /* skip blanks */
              cptr++;
  
          if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
          {
            if (*cptr == '-')
               esign = -1;

            cptr++;

            while (*cptr == ' ')        /* skip blanks between sign and exp */
              cptr++;
          }

          while (*cptr >= '0' && *cptr <= '9')
          {
            exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
            cptr++;

            while (*cptr == ' ')         /* skip embedded blanks */
              cptr++;
          }
        }

        if (*cptr  != 0)  /* should end up at the null terminator */
        {
          snprintf(message, FLEN_ERRMSG,"Cannot read number from ASCII table");
          ffpmsg(message);
          snprintf(message, FLEN_ERRMSG,"Column field = %s.", cstring);
          ffpmsg(message);
          /* restore the char that was overwritten by the null */
          *tpos = tempstore;
          return(*status = BAD_C2D);
        }

        if (!decpt)  /* if no explicit decimal, use implied */
           power = implipower;

        dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));

        dvalue = dvalue * scale + zero;   /* apply the scaling */

        if (dvalue < DUINT_MIN)
        {
            *status = OVERFLOW_ERR;
            output[ii] = 0;
        }
        else if (dvalue > DUINT_MAX)
        {
            *status = OVERFLOW_ERR;
            output[ii] = UINT_MAX;
        }
        else
            output[ii] = (long) dvalue;
      }
      /* restore the char that was overwritten by the null */
      *tpos = tempstore;
    }
    return(*status);
}
cfitsio/group.c0000644000225700000360000052614013246025103013310 0ustar  cagordonlhea/*  This file, group.c, contains the grouping convention suport routines.  */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */
/*                                                                         */
/*  The group.c module of CFITSIO was written by Donald G. Jennings of     */
/*  the INTEGRAL Science Data Centre (ISDC) under NASA contract task       */
/*  66002J6. The above copyright laws apply. Copyright guidelines of The   */
/*  University of Geneva might also apply.                                 */

/*  The following routines are designed to create, read, and manipulate    */
/*  FITS Grouping Tables as defined in the FITS Grouping Convention paper  */
/*  by Jennings, Pence, Folk and Schlesinger. The development of the       */
/*  grouping structure was partially funded under the NASA AISRP Program.  */ 
    
#include "fitsio2.h"
#include "group.h"
#include 
#include 
#include 

#if defined(WIN32) || defined(__WIN32__)
#include    /* defines the getcwd function on Windows PCs */
#endif

#if defined(unix) || defined(__unix__)  || defined(__unix) || defined(HAVE_UNISTD_H)
#include   /* needed for getcwd prototype on unix machines */
#endif

#define HEX_ESCAPE '%'

/*---------------------------------------------------------------------------
 Change record:

D. Jennings, 18/06/98, version 1.0 of group module delivered to B. Pence for
                       integration into CFITSIO 2.005

D. Jennings, 17/11/98, fixed bug in ffgtcpr(). Now use fits_find_nextkey()
                       correctly and insert auxiliary keyword records 
		       directly before the TTYPE1 keyword in the copied
		       group table.

D. Jennings, 22/01/99, ffgmop() now looks for relative file paths when 
                       the MEMBER_LOCATION information is given in a 
		       grouping table.

D. Jennings, 01/02/99, ffgtop() now looks for relatve file paths when 
                       the GRPLCn keyword value is supplied in the member
		       HDU header.

D. Jennings, 01/02/99, ffgtam() now trys to construct relative file paths
                       from the member's file to the group table's file
		       (and visa versa) when both the member's file and
		       group table file are of access type FILE://.

D. Jennings, 05/05/99, removed the ffgtcn() function; made obsolete by
                       fits_get_url().

D. Jennings, 05/05/99, updated entire module to handle partial URLs and
                       absolute URLs more robustly. Host dependent directory
		       paths are now converted to true URLs before being
		       read from/written to grouping tables.

D. Jennings, 05/05/99, added the following new functions (note, none of these
                       are directly callable by the application)

		       int fits_path2url()
		       int fits_url2path()
		       int fits_get_cwd()
		       int fits_get_url()
		       int fits_clean_url()
		       int fits_relurl2url()
		       int fits_encode_url()
		       int fits_unencode_url()
		       int fits_is_url_absolute()

-----------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
int ffgtcr(fitsfile *fptr,      /* FITS file pointer                         */
	   char    *grpname,    /* name of the grouping table                */
	   int      grouptype,  /* code specifying the type of
				   grouping table information:
				   GT_ID_ALL_URI  0 ==> defualt (all columns)
				   GT_ID_REF      1 ==> ID by reference
				   GT_ID_POS      2 ==> ID by position
				   GT_ID_ALL      3 ==> ID by ref. and position
				   GT_ID_REF_URI 11 ==> (1) + URI info 
				   GT_ID_POS_URI 12 ==> (2) + URI info       */
	   int      *status    )/* return status code                        */

/* 
   create a grouping table at the end of the current FITS file. This
   function makes the last HDU in the file the CHDU, then calls the
   fits_insert_group() function to actually create the new grouping table.
*/

{
  int hdutype;
  int hdunum;


  if(*status != 0) return(*status);


  *status = fits_get_num_hdus(fptr,&hdunum,status);

  /* If hdunum is 0 then we are at the beginning of the file and
     we actually haven't closed the first header yet, so don't do
     anything more */

  if (0 != hdunum) {

      *status = fits_movabs_hdu(fptr,hdunum,&hdutype,status);
  }

  /* Now, the whole point of the above two fits_ calls was to get to
     the end of file.  Let's ignore errors at this point and keep
     going since any error is likely to mean that we are already at the 
     EOF, or the file is fatally corrupted.  If we are at the EOF then
     the next fits_ call will be ok.  If it's corrupted then the
     next call will fail, but that's not big deal at this point.
  */

  if (0 != *status ) *status = 0;

  *status = fits_insert_group(fptr,grpname,grouptype,status);

  return(*status);
}

/*---------------------------------------------------------------------------*/
int ffgtis(fitsfile *fptr,      /* FITS file pointer                         */
	   char    *grpname,    /* name of the grouping table                */
	   int      grouptype,  /* code specifying the type of
				   grouping table information:
				   GT_ID_ALL_URI  0 ==> defualt (all columns)
				   GT_ID_REF      1 ==> ID by reference
				   GT_ID_POS      2 ==> ID by position
				   GT_ID_ALL      3 ==> ID by ref. and position
				   GT_ID_REF_URI 11 ==> (1) + URI info 
				   GT_ID_POS_URI 12 ==> (2) + URI info       */
	   int      *status)     /* return status code                       */
	   
/* 
   insert a grouping table just after the current HDU of the current FITS file.
   This is the same as fits_create_group() only it allows the user to select
   the place within the FITS file to add the grouping table.
*/

{

  int tfields  = 0;
  int hdunum   = 0;
  int hdutype  = 0;
  int extver;
  int i;
  
  long pcount  = 0;

  char *ttype[6];
  char *tform[6];

  char ttypeBuff[102];  
  char tformBuff[54];  

  char  extname[] = "GROUPING";
  char  keyword[FLEN_KEYWORD];
  char  keyvalue[FLEN_VALUE];
  char  comment[FLEN_COMMENT];
    
  do
    {

      /* set up the ttype and tform character buffers */

      for(i = 0; i < 6; ++i)
	{
	  ttype[i] = ttypeBuff+(i*17);
	  tform[i] = tformBuff+(i*9);
	}

      /* define the columns required according to the grouptype parameter */

      *status = ffgtdc(grouptype,0,0,0,0,0,0,ttype,tform,&tfields,status);

      /* create the grouping table using the columns defined above */

      *status = fits_insert_btbl(fptr,0,tfields,ttype,tform,NULL,
				 NULL,pcount,status);

      if(*status != 0) continue;

      /*
	 retrieve the hdu position of the new grouping table for
	 future use
      */

      fits_get_hdu_num(fptr,&hdunum);

      /*
	 add the EXTNAME and EXTVER keywords to the HDU just after the 
	 TFIELDS keyword; for now the EXTVER value is set to 0, it will be 
	 set to the correct value later on
      */

      fits_read_keyword(fptr,"TFIELDS",keyvalue,comment,status);

      fits_insert_key_str(fptr,"EXTNAME",extname,
			  "HDU contains a Grouping Table",status);
      fits_insert_key_lng(fptr,"EXTVER",0,"Grouping Table vers. (this file)",
			  status);

      /* 
	 if the grpname parameter value was defined (Non NULL and non zero
	 length) then add the GRPNAME keyword and value
      */

      if(grpname != NULL && strlen(grpname) > 0)
	fits_insert_key_str(fptr,"GRPNAME",grpname,"Grouping Table name",
			    status);

      /* 
	 add the TNULL keywords and values for each integer column defined;
	 integer null values are zero (0) for the MEMBER_POSITION and 
	 MEMBER_VERSION columns.
      */

      for(i = 0; i < tfields && *status == 0; ++i)
	{	  
	  if(fits_strcasecmp(ttype[i],"MEMBER_POSITION") == 0 ||
	     fits_strcasecmp(ttype[i],"MEMBER_VERSION")  == 0)
	    {
	      snprintf(keyword,FLEN_KEYWORD,"TFORM%d",i+1);
	      *status = fits_read_key_str(fptr,keyword,keyvalue,comment,
					  status);
	 
	      snprintf(keyword,FLEN_KEYWORD,"TNULL%d",i+1);

	      *status = fits_insert_key_lng(fptr,keyword,0,"Column Null Value",
					    status);
	    }
	}

      /*
	 determine the correct EXTVER value for the new grouping table
	 by finding the highest numbered grouping table EXTVER value
	 the currently exists
      */

      for(extver = 1;
	  (fits_movnam_hdu(fptr,ANY_HDU,"GROUPING",extver,status)) == 0; 
	  ++extver);

      if(*status == BAD_HDU_NUM) *status = 0;

      /*
	 move back to the new grouping table HDU and update the EXTVER
	 keyword value
      */

      fits_movabs_hdu(fptr,hdunum,&hdutype,status);

      fits_modify_key_lng(fptr,"EXTVER",extver,"&",status);

    }while(0);


  return(*status);
}

/*---------------------------------------------------------------------------*/
int ffgtch(fitsfile *gfptr,     /* FITS pointer to group                     */
	   int       grouptype, /* code specifying the type of
				   grouping table information:
				   GT_ID_ALL_URI  0 ==> defualt (all columns)
				   GT_ID_REF      1 ==> ID by reference
				   GT_ID_POS      2 ==> ID by position
				   GT_ID_ALL      3 ==> ID by ref. and position
				   GT_ID_REF_URI 11 ==> (1) + URI info 
				   GT_ID_POS_URI 12 ==> (2) + URI info       */
	   int      *status)     /* return status code                       */


/* 
   Change the grouping table structure of the grouping table pointed to by
   gfptr. The grouptype code specifies the new structure of the table. This
   operation only adds or removes grouping table columns, it does not add
   or delete group members (i.e., table rows). If the grouping table already
   has the desired structure then no operations are performed and function   
   simply returns with a (0) success status code. If the requested structure
   change creates new grouping table columns, then the column values for all
   existing members will be filled with the appropriate null values.
*/

{
  int xtensionCol, extnameCol, extverCol, positionCol, locationCol, uriCol;
  int ncols    = 0;
  int colnum   = 0;
  int nrows    = 0;
  int grptype  = 0;
  int i,j;

  long intNull  = 0;
  long tfields  = 0;
  
  char *tform[6];
  char *ttype[6];

  unsigned char  charNull[1] = {'\0'};

  char ttypeBuff[102];  
  char tformBuff[54];  

  char  keyword[FLEN_KEYWORD];
  char  keyvalue[FLEN_VALUE];
  char  comment[FLEN_COMMENT];


  if(*status != 0) return(*status);

  do
    {
      /* set up the ttype and tform character buffers */

      for(i = 0; i < 6; ++i)
	{
	  ttype[i] = ttypeBuff+(i*17);
	  tform[i] = tformBuff+(i*9);
	}

      /* retrieve positions of all Grouping table reserved columns */

      *status = ffgtgc(gfptr,&xtensionCol,&extnameCol,&extverCol,&positionCol,
		       &locationCol,&uriCol,&grptype,status);

      if(*status != 0) continue;

      /* determine the total number of grouping table columns */

      *status = fits_read_key_lng(gfptr,"TFIELDS",&tfields,comment,status);

      /* define grouping table columns to be added to the configuration */

      *status = ffgtdc(grouptype,xtensionCol,extnameCol,extverCol,positionCol,
		       locationCol,uriCol,ttype,tform,&ncols,status);

      /*
	delete any grouping tables columns that exist but do not belong to
	new desired configuration; note that we delete before creating new
	columns for (file size) efficiency reasons
      */

      switch(grouptype)
	{

	case GT_ID_ALL_URI:

	  /* no columns to be deleted in this case */

	  break;

	case GT_ID_REF:

	  if(positionCol != 0) 
	    {
	      *status = fits_delete_col(gfptr,positionCol,status);
	      --tfields;
	      if(uriCol      > positionCol)  --uriCol;
	      if(locationCol > positionCol) --locationCol;
	    }
	  if(uriCol      != 0)
	    { 
	    *status = fits_delete_col(gfptr,uriCol,status);
	      --tfields;
	      if(locationCol > uriCol) --locationCol;
	    }
	  if(locationCol != 0) 
	    *status = fits_delete_col(gfptr,locationCol,status);

	  break;

	case  GT_ID_POS:

	  if(xtensionCol != 0) 
	    {
	      *status = fits_delete_col(gfptr,xtensionCol,status);
	      --tfields;
	      if(extnameCol  > xtensionCol)  --extnameCol;
	      if(extverCol   > xtensionCol)  --extverCol;
	      if(uriCol      > xtensionCol)  --uriCol;
	      if(locationCol > xtensionCol)  --locationCol;
	    }
	  if(extnameCol  != 0) 
	    {
	      *status = fits_delete_col(gfptr,extnameCol,status);
	      --tfields;
	      if(extverCol   > extnameCol)  --extverCol;
	      if(uriCol      > extnameCol)  --uriCol;
	      if(locationCol > extnameCol)  --locationCol;
	    }
	  if(extverCol   != 0)
	    { 
	      *status = fits_delete_col(gfptr,extverCol,status);
	      --tfields;
	      if(uriCol      > extverCol)  --uriCol;
	      if(locationCol > extverCol)  --locationCol;
	    }
	  if(uriCol      != 0)
	    { 
	      *status = fits_delete_col(gfptr,uriCol,status);
	      --tfields;
	      if(locationCol > uriCol)  --locationCol;
	    }
	  if(locationCol != 0)
	    { 
	      *status = fits_delete_col(gfptr,locationCol,status);
	      --tfields;
	    }
	  
	  break;

	case  GT_ID_ALL:

	  if(uriCol      != 0) 
	    {
	      *status = fits_delete_col(gfptr,uriCol,status);
	      --tfields;
	      if(locationCol > uriCol)  --locationCol;
	    }
	  if(locationCol != 0)
	    { 
	      *status = fits_delete_col(gfptr,locationCol,status);
	      --tfields;
	    }

	  break;

	case GT_ID_REF_URI:

	  if(positionCol != 0)
	    { 
	      *status = fits_delete_col(gfptr,positionCol,status);
	      --tfields;
	    }

	  break;

	case  GT_ID_POS_URI:

	  if(xtensionCol != 0) 
	    {
	      *status = fits_delete_col(gfptr,xtensionCol,status);
	      --tfields;
	      if(extnameCol > xtensionCol)  --extnameCol;
	      if(extverCol  > xtensionCol)  --extverCol;
	    }
	  if(extnameCol  != 0)
	    { 
	      *status = fits_delete_col(gfptr,extnameCol,status);
	      --tfields;
	      if(extverCol > extnameCol)  --extverCol;
	    }
	  if(extverCol   != 0)
	    { 
	      *status = fits_delete_col(gfptr,extverCol,status);
	      --tfields;
	    }

	  break;

	default:

	  *status = BAD_OPTION;
	  ffpmsg("Invalid value for grouptype parameter specified (ffgtch)");
	  break;

	}

      /*
	add all the new grouping table columns that were not there
	previously but are called for by the grouptype parameter
      */

      for(i = 0; i < ncols && *status == 0; ++i)
	*status = fits_insert_col(gfptr,tfields+i+1,ttype[i],tform[i],status);

      /* 
	 add the TNULL keywords and values for each new integer column defined;
	 integer null values are zero (0) for the MEMBER_POSITION and 
	 MEMBER_VERSION columns. Insert a null ("/0") into each new string
	 column defined: MEMBER_XTENSION, MEMBER_NAME, MEMBER_URI_TYPE and
	 MEMBER_LOCATION. Note that by convention a null string is the
	 TNULL value for character fields so no TNULL is required.
      */

      for(i = 0; i < ncols && *status == 0; ++i)
	{	  
	  if(fits_strcasecmp(ttype[i],"MEMBER_POSITION") == 0 ||
	     fits_strcasecmp(ttype[i],"MEMBER_VERSION")  == 0)
	    {
	      /* col contains int data; set TNULL and insert 0 for each col */

	      *status = fits_get_colnum(gfptr,CASESEN,ttype[i],&colnum,
					status);
	      
	      snprintf(keyword,FLEN_KEYWORD,"TFORM%d",colnum);

	      *status = fits_read_key_str(gfptr,keyword,keyvalue,comment,
					  status);
	 
	      snprintf(keyword,FLEN_KEYWORD,"TNULL%d",colnum);

	      *status = fits_insert_key_lng(gfptr,keyword,0,
					    "Column Null Value",status);

	      for(j = 1; j <= nrows && *status == 0; ++j)
		*status = fits_write_col_lng(gfptr,colnum,j,1,1,&intNull,
					     status);
	    }
	  else if(fits_strcasecmp(ttype[i],"MEMBER_XTENSION") == 0 ||
		  fits_strcasecmp(ttype[i],"MEMBER_NAME")     == 0 ||
		  fits_strcasecmp(ttype[i],"MEMBER_URI_TYPE") == 0 ||
		  fits_strcasecmp(ttype[i],"MEMBER_LOCATION") == 0)
	    {

	      /* new col contains character data; insert NULLs into each col */

	      *status = fits_get_colnum(gfptr,CASESEN,ttype[i],&colnum,
					status);

	      for(j = 1; j <= nrows && *status == 0; ++j)
	    /* WILL THIS WORK FOR VAR LENTH CHAR COLS??????*/
		*status = fits_write_col_byt(gfptr,colnum,j,1,1,charNull,
					     status);
	    }
	}

    }while(0);

  return(*status);
}

/*---------------------------------------------------------------------------*/
int ffgtrm(fitsfile *gfptr,  /* FITS file pointer to group                   */
	   int       rmopt,  /* code specifying if member
				elements are to be deleted:
				OPT_RM_GPT ==> remove only group table
				OPT_RM_ALL ==> recursively remove members
				and their members (if groups)                */
	   int      *status) /* return status code                           */
	    
/*
  remove a grouping table, and optionally all its members. Any groups 
  containing the grouping table are updated, and all members (if not 
  deleted) have their GRPIDn and GRPLCn keywords updated accordingly. 
  If the (deleted) members are members of another grouping table then those
  tables are also updated. The CHDU of the FITS file pointed to by gfptr must 
  be positioned to the grouping table to be deleted.
*/

{
  int hdutype;

  long i;
  long nmembers = 0;

  HDUtracker HDU;
  

  if(*status != 0) return(*status);

  /*
     remove the grouping table depending upon the rmopt parameter
  */

  switch(rmopt)
    {

    case OPT_RM_GPT:

      /*
	 for this option, the grouping table is deleted, but the member
	 HDUs remain; in this case we only have to remove each member from
	 the grouping table by calling fits_remove_member() with the
	 OPT_RM_ENTRY option
      */

      /* get the number of members contained by this table */

      *status = fits_get_num_members(gfptr,&nmembers,status);

      /* loop over all grouping table members and remove them */

      for(i = nmembers; i > 0 && *status == 0; --i)
	*status = fits_remove_member(gfptr,i,OPT_RM_ENTRY,status);
      
	break;

    case OPT_RM_ALL:

      /*
	for this option the entire Group is deleted -- this includes all
	members and their members (if grouping tables themselves). Call 
	the recursive form of this function to perform the removal.
      */

      /* add the current grouping table to the HDUtracker struct */

      HDU.nHDU = 0;

      *status = fftsad(gfptr,&HDU,NULL,NULL);

      /* call the recursive group remove function */

      *status = ffgtrmr(gfptr,&HDU,status);

      /* free the memory allocated to the HDUtracker struct */

      for(i = 0; i < HDU.nHDU; ++i)
	{
	  free(HDU.filename[i]);
	  free(HDU.newFilename[i]);
	}

      break;

    default:
      
      *status = BAD_OPTION;
      ffpmsg("Invalid value for the rmopt parameter specified (ffgtrm)");
      break;

     }

  /*
     if all went well then unlink and delete the grouping table HDU
  */

  *status = ffgmul(gfptr,0,status);

  *status = fits_delete_hdu(gfptr,&hdutype,status);
      
  return(*status);
}

/*---------------------------------------------------------------------------*/
int ffgtcp(fitsfile *infptr,  /* input FITS file pointer                     */
	   fitsfile *outfptr, /* output FITS file pointer                    */
	   int        cpopt,  /* code specifying copy options:
				OPT_GCP_GPT (0) ==> copy only grouping table
				OPT_GCP_ALL (2) ==> recusrively copy members 
				                    and their members (if 
						    groups)                  */
	   int      *status)  /* return status code                          */

/*
  copy a grouping table, and optionally all its members, to a new FITS file.
  If the cpopt is set to OPT_GCP_GPT (copy grouping table only) then the 
  existing members have their GRPIDn and GRPLCn keywords updated to reflect 
  the existance of the new group, since they now belong to another group. If 
  cpopt is set to OPT_GCP_ALL (copy grouping table and members recursively) 
  then the original members are not updated; the new grouping table is 
  modified to include only the copied member HDUs and not the original members.

  Note that the recursive version of this function, ffgtcpr(), is called
  to perform the group table copy. In the case of cpopt == OPT_GCP_GPT
  ffgtcpr() does not actually use recursion.
*/

{
  int i;

  HDUtracker HDU;


  if(*status != 0) return(*status);

  /* make sure infptr and outfptr are not the same pointer */

  if(infptr == outfptr) *status = IDENTICAL_POINTERS;
  else
    {

      /* initialize the HDUtracker struct */
      
      HDU.nHDU = 0;
      
      *status = fftsad(infptr,&HDU,NULL,NULL);
      
      /* 
	 call the recursive form of this function to copy the grouping table. 
	 If the cpopt is OPT_GCP_GPT then there is actually no recursion
	 performed
      */

      *status = ffgtcpr(infptr,outfptr,cpopt,&HDU,status);
  
      /* free memory allocated for the HDUtracker struct */

      for(i = 0; i < HDU.nHDU; ++i) 
	{
	  free(HDU.filename[i]);
	  free(HDU.newFilename[i]);
	}
    }

  return(*status);
}

/*---------------------------------------------------------------------------*/
int ffgtmg(fitsfile *infptr,  /* FITS file ptr to source grouping table      */
	   fitsfile *outfptr, /* FITS file ptr to target grouping table      */
	   int       mgopt,   /* code specifying merge options:
				 OPT_MRG_COPY (0) ==> copy members to target
				                      group, leaving source 
						      group in place
				 OPT_MRG_MOV  (1) ==> move members to target
				                      group, source group is
						      deleted after merge    */
	   int      *status)   /* return status code                         */
     

/*
  merge two grouping tables by combining their members into a single table. 
  The source grouping table must be the CHDU of the fitsfile pointed to by 
  infptr, and the target grouping table must be the CHDU of the fitsfile to by 
  outfptr. All members of the source grouping table shall be copied to the
  target grouping table. If the mgopt parameter is OPT_MRG_COPY then the source
  grouping table continues to exist after the merge. If the mgopt parameter
  is OPT_MRG_MOV then the source grouping table is deleted after the merge, 
  and all member HDUs are updated accordingly.
*/
{
  long i ;
  long nmembers = 0;

  fitsfile *tmpfptr = NULL;


  if(*status != 0) return(*status);

  do
    {

      *status = fits_get_num_members(infptr,&nmembers,status);

      for(i = 1; i <= nmembers && *status == 0; ++i)
	{
	  *status = fits_open_member(infptr,i,&tmpfptr,status);
	  *status = fits_add_group_member(outfptr,tmpfptr,0,status);

	  if(*status == HDU_ALREADY_MEMBER) *status = 0;

	  if(tmpfptr != NULL)
	    {
	      fits_close_file(tmpfptr,status);
	      tmpfptr = NULL;
	    }
	}

      if(*status != 0) continue;

      if(mgopt == OPT_MRG_MOV) 
	*status = fits_remove_group(infptr,OPT_RM_GPT,status);

    }while(0);

  if(tmpfptr != NULL)
    {
      fits_close_file(tmpfptr,status);
    }

  return(*status);
}

/*---------------------------------------------------------------------------*/
int ffgtcm(fitsfile *gfptr,  /* FITS file pointer to grouping table          */
	   int       cmopt,  /* code specifying compact options
				OPT_CMT_MBR      (1) ==> compact only direct 
			                                 members (if groups)
				OPT_CMT_MBR_DEL (11) ==> (1) + delete all 
				                         compacted groups    */
	   int      *status) /* return status code                           */
    
/*
  "Compact" a group pointed to by the FITS file pointer gfptr. This 
  is achieved by flattening the tree structure of a group and its 
  (grouping table) members. All members HDUs of a grouping table which is 
  itself a member of the grouping table gfptr are added to gfptr. Optionally,
  the grouping tables which are "compacted" are deleted. If the grouping 
  table contains no members that are themselves grouping tables then this 
  function performs a NOOP.
*/

{
  long i;
  long nmembers = 0;

  char keyvalue[FLEN_VALUE];
  char comment[FLEN_COMMENT];

  fitsfile *mfptr = NULL;


  if(*status != 0) return(*status);

  do
    {
      if(cmopt != OPT_CMT_MBR && cmopt != OPT_CMT_MBR_DEL)
	{
	  *status = BAD_OPTION;
	  ffpmsg("Invalid value for cmopt parameter specified (ffgtcm)");
	  continue;
	}

      /* reteive the number of grouping table members */

      *status = fits_get_num_members(gfptr,&nmembers,status);

      /*
	loop over all the grouping table members; if the member is a 
	grouping table then merge its members with the parent grouping 
	table 
      */

      for(i = 1; i <= nmembers && *status == 0; ++i)
	{
	  *status = fits_open_member(gfptr,i,&mfptr,status);

	  if(*status != 0) continue;

	  *status = fits_read_key_str(mfptr,"EXTNAME",keyvalue,comment,status);

	  /* if no EXTNAME keyword then cannot be a grouping table */

	  if(*status == KEY_NO_EXIST) 
	    {
	      *status = 0;
	      continue;
	    }
	  prepare_keyvalue(keyvalue);

	  if(*status != 0) continue;

	  /* if EXTNAME == "GROUPING" then process member as grouping table */

	  if(fits_strcasecmp(keyvalue,"GROUPING") == 0)
	    {
	      /* merge the member (grouping table) into the grouping table */

	      *status = fits_merge_groups(mfptr,gfptr,OPT_MRG_COPY,status);

	      *status = fits_close_file(mfptr,status);
	      mfptr = NULL;

	      /* 
		 remove the member from the grouping table now that all of
		 its members have been transferred; if cmopt is set to
		 OPT_CMT_MBR_DEL then remove and delete the member
	      */

	      if(cmopt == OPT_CMT_MBR)
		*status = fits_remove_member(gfptr,i,OPT_RM_ENTRY,status);
	      else
		*status = fits_remove_member(gfptr,i,OPT_RM_MBR,status);
	    }
	  else
	    {
	      /* not a grouping table; just close the opened member */

	      *status = fits_close_file(mfptr,status);
	      mfptr = NULL;
	    }
	}

    }while(0);

  return(*status);
}

/*--------------------------------------------------------------------------*/
int ffgtvf(fitsfile *gfptr,       /* FITS file pointer to group             */
	   long     *firstfailed, /* Member ID (if positive) of first failed
				     member HDU verify check or GRPID index
				     (if negitive) of first failed group
				     link verify check.                     */
	   int      *status)      /* return status code                     */

/*
 check the integrity of a grouping table to make sure that all group members 
 are accessible and all the links to other grouping tables are valid. The
 firstfailed parameter returns the member ID of the first member HDU to fail
 verification if positive or the first group link to fail if negative; 
 otherwise firstfailed contains a return value of 0.
*/

{
  long i;
  long nmembers = 0;
  long ngroups  = 0;

  char errstr[FLEN_VALUE];

  fitsfile *fptr = NULL;


  if(*status != 0) return(*status);

  *firstfailed = 0;

  do
    {
      /*
	attempt to open all the members of the grouping table. We stop
	at the first member which cannot be opened (which implies that it
	cannot be located)
      */

      *status = fits_get_num_members(gfptr,&nmembers,status);

      for(i = 1; i <= nmembers && *status == 0; ++i)
	{
	  *status = fits_open_member(gfptr,i,&fptr,status);
	  fits_close_file(fptr,status);
	}

      /*
	if the status is non-zero from the above loop then record the
	member index that caused the error
      */

      if(*status != 0)
	{
	  *firstfailed = i;
	  snprintf(errstr,FLEN_VALUE,"Group table verify failed for member %ld (ffgtvf)",
		  i);
	  ffpmsg(errstr);
	  continue;
	}

      /*
	attempt to open all the groups linked to this grouping table. We stop
	at the first group which cannot be opened (which implies that it
	cannot be located)
      */

      *status = fits_get_num_groups(gfptr,&ngroups,status);

      for(i = 1; i <= ngroups && *status == 0; ++i)
	{
	  *status = fits_open_group(gfptr,i,&fptr,status);
	  fits_close_file(fptr,status);
	}

      /*
	if the status from the above loop is non-zero, then record the
	GRPIDn index of the group that caused the failure
      */

      if(*status != 0)
	{
	  *firstfailed = -1*i;
	  snprintf(errstr,FLEN_VALUE,
		  "Group table verify failed for GRPID index %ld (ffgtvf)",i);
	  ffpmsg(errstr);
	  continue;
	}

    }while(0);

  return(*status);
}

/*---------------------------------------------------------------------------*/
int ffgtop(fitsfile *mfptr,  /* FITS file pointer to the member HDU          */
	   int       grpid,  /* group ID (GRPIDn index) within member HDU    */
	   fitsfile **gfptr, /* FITS file pointer to grouping table HDU      */
	   int      *status) /* return status code                           */

/*
  open the grouping table that contains the member HDU. The member HDU must
  be the CHDU of the FITS file pointed to by mfptr, and the grouping table
  is identified by the Nth index number of the GRPIDn keywords specified in 
  the member HDU's header. The fitsfile gfptr pointer is positioned with the
  appropriate FITS file with the grouping table as the CHDU. If the group
  grouping table resides in a file other than the member then an attempt
  is first made to open the file readwrite, and failing that readonly.
 
  Note that it is possible for the GRPIDn/GRPLCn keywords in a member 
  header to be non-continuous, e.g., GRPID1, GRPID2, GRPID5, GRPID6. In 
  such cases, the grpid index value specified in the function call shall
  identify the (grpid)th GRPID value. In the above example, if grpid == 3,
  then the group specified by GRPID5 would be opened.
*/
{
  int i;
  int found;

  long ngroups   = 0;
  long grpExtver = 0;

  char keyword[FLEN_KEYWORD];
  char keyvalue[FLEN_FILENAME];
  char *tkeyvalue;
  char location[FLEN_FILENAME];
  char location1[FLEN_FILENAME];
  char location2[FLEN_FILENAME];
  char comment[FLEN_COMMENT];

  char *url[2];


  if(*status != 0) return(*status);

  do
    {
      /* set the grouping table pointer to NULL for error checking later */

      *gfptr = NULL;

      /*
	make sure that the group ID requested is valid ==> cannot be
	larger than the number of GRPIDn keywords in the member HDU header
      */

      *status = fits_get_num_groups(mfptr,&ngroups,status);

      if(grpid > ngroups)
	{
	  *status = BAD_GROUP_ID;
	  snprintf(comment,FLEN_COMMENT,
		  "GRPID index %d larger total GRPID keywords %ld (ffgtop)",
		  grpid,ngroups);
	  ffpmsg(comment);
	  continue;
	}

      /*
	find the (grpid)th group that the member HDU belongs to and read
	the value of the GRPID(grpid) keyword; fits_get_num_groups()
	automatically re-enumerates the GRPIDn/GRPLCn keywords to fill in
	any gaps
      */

      snprintf(keyword,FLEN_KEYWORD,"GRPID%d",grpid);

      *status = fits_read_key_lng(mfptr,keyword,&grpExtver,comment,status);

      if(*status != 0) continue;

      /*
	if the value of the GRPIDn keyword is positive then the member is
	in the same FITS file as the grouping table and we only have to
	reopen the current FITS file. Else the member and grouping table
	HDUs reside in different files and another FITS file must be opened
	as specified by the corresponding GRPLCn keyword
	
	The DO WHILE loop only executes once and is used to control the
	file opening logic.
      */

      do
	{
	  if(grpExtver > 0) 
	    {
	      /*
		the member resides in the same file as the grouping
		 table, so just reopen the grouping table file
	      */

	      *status = fits_reopen_file(mfptr,gfptr,status);
	      continue;
	    }

	  else if(grpExtver == 0)
	    {
	      /* a GRPIDn value of zero (0) is undefined */

	      *status = BAD_GROUP_ID;
	      snprintf(comment,FLEN_COMMENT,"Invalid value of %ld for GRPID%d (ffgtop)",
		      grpExtver,grpid);
	      ffpmsg(comment);
	      continue;
	    }

	  /* 
	     The GRPLCn keyword value is negative, which implies that
	     the grouping table must reside in another FITS file;
	     search for the corresponding GRPLCn keyword 
	  */
	  
	  /* set the grpExtver value positive */
  
	  grpExtver = -1*grpExtver;

	  /* read the GRPLCn keyword value */

	  snprintf(keyword,FLEN_KEYWORD,"GRPLC%d",grpid);
	  /* SPR 1738 */
	  *status = fits_read_key_longstr(mfptr,keyword,&tkeyvalue,comment,
				      status);
	  if (0 == *status) {
	    strcpy(keyvalue,tkeyvalue);
	    free(tkeyvalue);
	  }
	  

	  /* if the GRPLCn keyword was not found then there is a problem */

	  if(*status == KEY_NO_EXIST)
	    {
	      *status = BAD_GROUP_ID;

	      snprintf(comment,FLEN_COMMENT,"Cannot find GRPLC%d keyword (ffgtop)",
		      grpid);
	      ffpmsg(comment);

	      continue;
	    }

	  prepare_keyvalue(keyvalue);

	  /*
	    if the GRPLCn keyword value specifies an absolute URL then
	    try to open the file; we cannot attempt any relative URL
	    or host-dependent file path reconstruction
	  */

	  if(fits_is_url_absolute(keyvalue))
	    {
	      ffpmsg("Try to open group table file as absolute URL (ffgtop)");

	      *status = fits_open_file(gfptr,keyvalue,READWRITE,status);

	      /* if the open was successful then continue */

	      if(*status == 0) continue;

	      /* if READWRITE failed then try opening it READONLY */

	      ffpmsg("OK, try open group table file as READONLY (ffgtop)");
	      
	      *status = 0;
	      *status = fits_open_file(gfptr,keyvalue,READONLY,status);

	      /* continue regardless of the outcome */

	      continue;
	    }

	  /*
	    see if the URL gives a file path that is absolute on the
	    host machine 
	  */

	  *status = fits_url2path(keyvalue,location1,status);

	  *status = fits_open_file(gfptr,location1,READWRITE,status);

	  /* if the file opened then continue */

	  if(*status == 0) continue;

	  /* if READWRITE failed then try opening it READONLY */

	  ffpmsg("OK, try open group table file as READONLY (ffgtop)");
	  
	  *status = 0;
	  *status = fits_open_file(gfptr,location1,READONLY,status);

	  /* if the file opened then continue */

	  if(*status == 0) continue;

	  /*
	    the grouping table location given by GRPLCn must specify a 
	    relative URL. We assume that this URL is relative to the 
	    member HDU's FITS file. Try to construct a full URL location 
	    for the grouping table's FITS file and then open it
	  */

	  *status = 0;
		  
	  /* retrieve the URL information for the member HDU's file */
		  
	  url[0] = location1; url[1] = location2;
		  
	  *status = fits_get_url(mfptr,url[0],url[1],NULL,NULL,NULL,status);

	  /*
	    It is possible that the member HDU file has an initial
	    URL it was opened with and a real URL that the file actually
	    exists at (e.g., an HTTP accessed file copied to a local
	    file). For each possible URL try to construct a
	  */
		  
	  for(i = 0, found = 0, *gfptr = NULL; i < 2 && !found; ++i)
	    {
	      
	      /* the url string could be empty */
	      
	      if(*url[i] == 0) continue;
	      
	      /* 
		 create a full URL from the partial and the member
		 HDU file URL
	      */
	      
	      *status = fits_relurl2url(url[i],keyvalue,location,status);
	      
	      /* if an error occured then contniue */
	      
	      if(*status != 0) 
		{
		  *status = 0;
		  continue;
		}
	      
	      /*
		if the location does not specify an access method
		then turn it into a host dependent path
	      */

	      if(! fits_is_url_absolute(location))
		{
		  *status = fits_url2path(location,url[i],status);
		  strcpy(location,url[i]);
		}
	      
	      /* try to open the grouping table file READWRITE */
	      
	      *status = fits_open_file(gfptr,location,READWRITE,status);
	      
	      if(*status != 0)
		{    
		  /* try to open the grouping table file READONLY */
		  
		  ffpmsg("opening file as READWRITE failed (ffgtop)");
		  ffpmsg("OK, try to open file as READONLY (ffgtop)");
		  *status = 0;
		  *status = fits_open_file(gfptr,location,READONLY,status);
		}
	      
	      /* either set the found flag or reset the status flag */
	      
	      if(*status == 0) 
		found = 1;
	      else
		*status = 0;
	    }

	}while(0); /* end of file opening loop */

      /* if an error occured with the file opening then exit */

      if(*status != 0) continue;
  
      if(*gfptr == NULL)
	{
	  ffpmsg("Cannot open or find grouping table FITS file (ffgtop)");
	  *status = GROUP_NOT_FOUND;
	  continue;
	}

      /* search for the grouping table in its FITS file */

      *status = fits_movnam_hdu(*gfptr,ANY_HDU,"GROUPING",(int)grpExtver,
				status);

      if(*status != 0) *status = GROUP_NOT_FOUND;

    }while(0);

  if(*status != 0 && *gfptr != NULL) 
    {
      fits_close_file(*gfptr,status);
      *gfptr = NULL;
    }

  return(*status);
}
/*---------------------------------------------------------------------------*/
int ffgtam(fitsfile *gfptr,   /* FITS file pointer to grouping table HDU     */
	   fitsfile *mfptr,   /* FITS file pointer to member HDU             */
	   int       hdupos,  /* member HDU position IF in the same file as
			         the grouping table AND mfptr == NULL        */
	   int      *status)  /* return status code                          */
 
/*
  add a member HDU to an existing grouping table. The fitsfile pointer gfptr
  must be positioned with the grouping table as the CHDU. The member HDU
  may either be identifed with the fitsfile *mfptr (which must be positioned
  to the member HDU) or the hdupos parameter (the HDU number of the member 
  HDU) if both reside in the same FITS file. The hdupos value is only used
  if the mfptr parameter has a value of NULL (0). The new member HDU shall 
  have the appropriate GRPIDn and GRPLCn keywords created in its header.

  Note that if the member HDU to be added to the grouping table is already
  a member of the group then it will not be added a sceond time.
*/

{
  int xtensionCol,extnameCol,extverCol,positionCol,locationCol,uriCol;
  int memberPosition = 0;
  int grptype        = 0;
  int hdutype        = 0;
  int useLocation    = 0;
  int nkeys          = 6;
  int found;
  int i;

  int memberIOstate;
  int groupIOstate;
  int iomode;

  long memberExtver = 0;
  long groupExtver  = 0;
  long memberID     = 0;
  long nmembers     = 0;
  long ngroups      = 0;
  long grpid        = 0;

  char memberAccess1[FLEN_VALUE];
  char memberAccess2[FLEN_VALUE];
  char memberFileName[FLEN_FILENAME];
  char memberLocation[FLEN_FILENAME];
  char grplc[FLEN_FILENAME];
  char *tgrplc;
  char memberHDUtype[FLEN_VALUE];
  char memberExtname[FLEN_VALUE];
  char memberURI[] = "URL";

  char groupAccess1[FLEN_VALUE];
  char groupAccess2[FLEN_VALUE];
  char groupFileName[FLEN_FILENAME];
  char groupLocation[FLEN_FILENAME];
  char tmprootname[FLEN_FILENAME], grootname[FLEN_FILENAME];
  char cwd[FLEN_FILENAME];

  char *keys[] = {"GRPNAME","EXTVER","EXTNAME","TFIELDS","GCOUNT","EXTEND"};
  char *tmpPtr[1];

  char keyword[FLEN_KEYWORD];
  char card[FLEN_CARD];

  unsigned char charNull[]  = {'\0'};

  fitsfile *tmpfptr = NULL;

  int parentStatus = 0;

  if(*status != 0) return(*status);

  do
    {
      /*
	make sure the grouping table can be modified before proceeding
      */

      fits_file_mode(gfptr,&iomode,status);

      if(iomode != READWRITE)
	{
	  ffpmsg("cannot modify grouping table (ffgtam)");
	  *status = BAD_GROUP_ATTACH;
	  continue;
	}

      /*
	 if the calling function supplied the HDU position of the member
	 HDU instead of fitsfile pointer then get a fitsfile pointer
      */

      if(mfptr == NULL)
	{
	  *status = fits_reopen_file(gfptr,&tmpfptr,status);
	  *status = fits_movabs_hdu(tmpfptr,hdupos,&hdutype,status);

	  if(*status != 0) continue;
	}
      else
	tmpfptr = mfptr;

      /*
	 determine all the information about the member HDU that will
	 be needed later; note that we establish the default values for
	 all information values that are not explicitly found
      */

      *status = fits_read_key_str(tmpfptr,"XTENSION",memberHDUtype,card,
				  status);

      if(*status == KEY_NO_EXIST) 
	{
	  strcpy(memberHDUtype,"PRIMARY");
	  *status = 0;
	}
      prepare_keyvalue(memberHDUtype);

      *status = fits_read_key_lng(tmpfptr,"EXTVER",&memberExtver,card,status);

      if(*status == KEY_NO_EXIST) 
	{
	  memberExtver = 1;
	  *status      = 0;
	}

      *status = fits_read_key_str(tmpfptr,"EXTNAME",memberExtname,card,
				  status);

      if(*status == KEY_NO_EXIST) 
	{
	  memberExtname[0] = 0;
	  *status          = 0;
	}
      prepare_keyvalue(memberExtname);

      fits_get_hdu_num(tmpfptr,&memberPosition);

      /*
	Determine if the member HDU's FITS file location needs to be
	taken into account when building its grouping table reference

	If the member location needs to be used (==> grouping table and member
	HDU reside in different files) then create an appropriate URL for
	the member HDU's file and grouping table's file. Note that the logic
	for this is rather complicated
      */

      /* SPR 3463, don't do this 
	 if(tmpfptr->Fptr == gfptr->Fptr)
	 {  */
	  /*
	    member HDU and grouping table reside in the same file, no need
	    to use the location information */
	  
      /* printf ("same file\n");
	   
	   useLocation     = 0;
	   memberIOstate   = 1;
	   *memberFileName = 0;
	}
      else
      { */ 
	  /*
	     the member HDU and grouping table FITS file location information 
	     must be used.

	     First determine the correct driver and file name for the group
	     table and member HDU files. If either are disk files then
	     construct an absolute file path for them. Finally, if both are
	     disk files construct relative file paths from the group(member)
	     file to the member(group) file.

	  */

	  /* set the USELOCATION flag to true */

	  useLocation = 1;

	  /* 
	     get the location, access type and iostate (RO, RW) of the
	     member HDU file
	  */

	  *status = fits_get_url(tmpfptr,memberFileName,memberLocation,
				 memberAccess1,memberAccess2,&memberIOstate,
				 status);

	  /*
	     if the memberFileName string is empty then use the values of
	     the memberLocation string. This corresponds to a file where
	     the "real" file is a temporary memory file, and we must assume
	     the the application really wants the original file to be the
	     group member
	   */

	  if(strlen(memberFileName) == 0)
	    {
	      strcpy(memberFileName,memberLocation);
	      strcpy(memberAccess1,memberAccess2);
	    }

	  /* 
	     get the location, access type and iostate (RO, RW) of the
	     grouping table file
	  */

	  *status = fits_get_url(gfptr,groupFileName,groupLocation,
				 groupAccess1,groupAccess2,&groupIOstate,
				 status);
	  
	  if(*status != 0) continue;

	  /*
	    the grouping table file must be writable to continue
	  */

	  if(groupIOstate == 0)
	    {
	      ffpmsg("cannot modify grouping table (ffgtam)");
	      *status = BAD_GROUP_ATTACH;
	      continue;
	    }

	  /*
	    determine how to construct the resulting URLs for the member and
	    group files
	  */

	  if(fits_strcasecmp(groupAccess1,"file://")  &&
	                                   fits_strcasecmp(memberAccess1,"file://"))
	    {
              *cwd = 0;
	      /* 
		 nothing to do in this case; both the member and group files
		 must be of an access type that already gives valid URLs;
		 i.e., URLs that we can pass directly to the file drivers
	      */
	    }
	  else
	    {
	      /*
		 retrieve the Current Working Directory as a Unix-like
		 URL standard string
	      */

	      *status = fits_get_cwd(cwd,status);

	      /*
		 create full file path for the member HDU FITS file URL
		 if it is of access type file://
	      */
	      
	      if(fits_strcasecmp(memberAccess1,"file://") == 0)
		{
		  if(*memberFileName == '/')
		    {
		      strcpy(memberLocation,memberFileName);
		    }
		  else
		    {
		      strcpy(memberLocation,cwd);
		      strcat(memberLocation,"/");
		      strcat(memberLocation,memberFileName);
		    }
		  
		  *status = fits_clean_url(memberLocation,memberFileName,
					   status);
		}

	      /*
		 create full file path for the grouping table HDU FITS file URL
		 if it is of access type file://
	      */

	      if(fits_strcasecmp(groupAccess1,"file://") == 0)
		{
		  if(*groupFileName == '/')
		    {
		      strcpy(groupLocation,groupFileName);
		    }
		  else
		    {
		      strcpy(groupLocation,cwd);
		      strcat(groupLocation,"/");
		      strcat(groupLocation,groupFileName);
		    }
		  
		  *status = fits_clean_url(groupLocation,groupFileName,status);
		}

	      /*
		if both the member and group files are disk files then 
		create a relative path (relative URL) strings with 
		respect to the grouping table's file and the grouping table's 
		file with respect to the member HDU's file
	      */
	      
	      if(fits_strcasecmp(groupAccess1,"file://") == 0 &&
		                      fits_strcasecmp(memberAccess1,"file://") == 0)
		{
		  fits_url2relurl(memberFileName,groupFileName,
				                  groupLocation,status);
		  fits_url2relurl(groupFileName,memberFileName,
				                  memberLocation,status);

		  /*
		     copy the resulting partial URL strings to the
		     memberFileName and groupFileName variables for latter
		     use in the function
		   */
		    
		  strcpy(memberFileName,memberLocation);
		  strcpy(groupFileName,groupLocation);		  
		}
	    }
	  /* beo done */
	  /* }  */
      

      /* retrieve the grouping table's EXTVER value */

      *status = fits_read_key_lng(gfptr,"EXTVER",&groupExtver,card,status);

      /* 
	 if useLocation is true then make the group EXTVER value negative
	 for the subsequent GRPIDn/GRPLCn matching
      */
      /* SPR 3463 change test;  WDP added test for same filename */
      /* Now, if either the Fptr values are the same, or the root filenames
         are the same, then assume these refer to the same file.
      */
      fits_parse_rootname(tmpfptr->Fptr->filename, tmprootname, status);
      fits_parse_rootname(gfptr->Fptr->filename, grootname, status);

      if((tmpfptr->Fptr != gfptr->Fptr) && 
          strncmp(tmprootname, grootname, FLEN_FILENAME))
	   groupExtver = -1*groupExtver;

      /* retrieve the number of group members */

      *status = fits_get_num_members(gfptr,&nmembers,status);
	      
    do {

      /*
	 make sure the member HDU is not already an entry in the
	 grouping table before adding it
      */

      *status = ffgmf(gfptr,memberHDUtype,memberExtname,memberExtver,
		      memberPosition,memberFileName,&memberID,status);

      if(*status == MEMBER_NOT_FOUND) *status = 0;
      else if(*status == 0)
	{  
	  parentStatus = HDU_ALREADY_MEMBER;
    ffpmsg("Specified HDU is already a member of the Grouping table (ffgtam)");
	  continue;
	}
      else continue;

      /*
	 if the member HDU is not already recorded in the grouping table
	 then add it 
      */

      /* add a new row to the grouping table */

      *status = fits_insert_rows(gfptr,nmembers,1,status);
      ++nmembers;

      /* retrieve the grouping table column IDs and structure type */

      *status = ffgtgc(gfptr,&xtensionCol,&extnameCol,&extverCol,&positionCol,
		       &locationCol,&uriCol,&grptype,status);

      /* fill in the member HDU data in the new grouping table row */

      *tmpPtr = memberHDUtype; 

      if(xtensionCol != 0)
	fits_write_col_str(gfptr,xtensionCol,nmembers,1,1,tmpPtr,status);

      *tmpPtr = memberExtname; 

      if(extnameCol  != 0)
	{
	  if(strlen(memberExtname) != 0)
	    fits_write_col_str(gfptr,extnameCol,nmembers,1,1,tmpPtr,status);
	  else
	    /* WILL THIS WORK FOR VAR LENTH CHAR COLS??????*/
	    fits_write_col_byt(gfptr,extnameCol,nmembers,1,1,charNull,status);
	}

      if(extverCol   != 0)
	fits_write_col_lng(gfptr,extverCol,nmembers,1,1,&memberExtver,
			   status);

      if(positionCol != 0)
	fits_write_col_int(gfptr,positionCol,nmembers,1,1,
			   &memberPosition,status);

      *tmpPtr = memberFileName; 

      if(locationCol != 0)
	{
	  /* Change the test for SPR 3463 */
	  /* Now, if either the Fptr values are the same, or the root filenames
	     are the same, then assume these refer to the same file.
	  */
	  fits_parse_rootname(tmpfptr->Fptr->filename, tmprootname, status);
	  fits_parse_rootname(gfptr->Fptr->filename, grootname, status);

	  if((tmpfptr->Fptr != gfptr->Fptr) && 
	          strncmp(tmprootname, grootname, FLEN_FILENAME))
	    fits_write_col_str(gfptr,locationCol,nmembers,1,1,tmpPtr,status);
	  else
	    /* WILL THIS WORK FOR VAR LENTH CHAR COLS??????*/
	    fits_write_col_byt(gfptr,locationCol,nmembers,1,1,charNull,status);
	}

      *tmpPtr = memberURI;

      if(uriCol      != 0)
	{

	  /* Change the test for SPR 3463 */
	  /* Now, if either the Fptr values are the same, or the root filenames
	     are the same, then assume these refer to the same file.
	  */
	  fits_parse_rootname(tmpfptr->Fptr->filename, tmprootname, status);
	  fits_parse_rootname(gfptr->Fptr->filename, grootname, status);

	  if((tmpfptr->Fptr != gfptr->Fptr) && 
	          strncmp(tmprootname, grootname, FLEN_FILENAME))
	    fits_write_col_str(gfptr,uriCol,nmembers,1,1,tmpPtr,status);
	  else
	    /* WILL THIS WORK FOR VAR LENTH CHAR COLS??????*/
	    fits_write_col_byt(gfptr,uriCol,nmembers,1,1,charNull,status);
	}
    } while(0);

      if(0 != *status) continue;
      /*
	 add GRPIDn/GRPLCn keywords to the member HDU header to link
	 it to the grouing table if the they do not already exist and
	 the member file is RW
      */

      fits_file_mode(tmpfptr,&iomode,status);
 
     if(memberIOstate == 0 || iomode != READWRITE) 
	{
	  ffpmsg("cannot add GRPID/LC keywords to member HDU: (ffgtam)");
	  ffpmsg(memberFileName);
	  continue;
	}

      *status = fits_get_num_groups(tmpfptr,&ngroups,status);

      /* 
	 look for the GRPID/LC keywords in the member HDU; if the keywords
	 for the back-link to the grouping table already exist then no
	 need to add them again
       */

      for(i = 1, found = 0; i <= ngroups && !found && *status == 0; ++i)
	{
	  snprintf(keyword,FLEN_KEYWORD,"GRPID%d",(int)ngroups);
	  *status = fits_read_key_lng(tmpfptr,keyword,&grpid,card,status);

	  if(grpid == groupExtver)
	    {
	      if(grpid < 0)
		{

		  /* have to make sure the GRPLCn keyword matches too */

		  snprintf(keyword,FLEN_KEYWORD,"GRPLC%d",(int)ngroups);
		  /* SPR 1738 */
		  *status = fits_read_key_longstr(mfptr,keyword,&tgrplc,card,
						  status);
		  if (0 == *status) {
		    strcpy(grplc,tgrplc);
		    free(tgrplc);
		  }
		  
		  /*
		     always compare files using absolute paths
                     the presence of a non-empty cwd indicates
                     that the file names may require conversion
                     to absolute paths
                  */

                  if(0 < strlen(cwd)) {
                    /* temp buffer for use in assembling abs. path(s) */
                    char tmp[FLEN_FILENAME];

                    /* make grplc absolute if necessary */
                    if(!fits_is_url_absolute(grplc)) {
		      fits_path2url(grplc,groupLocation,status);

		      if(groupLocation[0] != '/')
			{
			  strcpy(tmp, cwd);
			  strcat(tmp,"/");
			  strcat(tmp,groupLocation);
			  fits_clean_url(tmp,grplc,status);
			}
                    }

                    /* make groupFileName absolute if necessary */
                    if(!fits_is_url_absolute(groupFileName)) {
		      fits_path2url(groupFileName,groupLocation,status);

		      if(groupLocation[0] != '/')
			{
			  strcpy(tmp, cwd);
			  strcat(tmp,"/");
			  strcat(tmp,groupLocation);
                          /*
                             note: use groupLocation (which is not used
                             below this block), to store the absolute
                             file name instead of using groupFileName.
                             The latter may be needed unaltered if the
                             GRPLC is written below
                          */

			  fits_clean_url(tmp,groupLocation,status);
			}
                    }
                  }
		  /*
		    see if the grplc value and the group file name match
		  */

		  if(strcmp(grplc,groupLocation) == 0) found = 1;
		}
	      else
		{
		  /* the match is found with GRPIDn alone */
		  found = 1;
		}
	    }
	}

      /*
	 if FOUND is true then no need to continue
      */

      if(found)
	{
	  ffpmsg("HDU already has GRPID/LC keywords for group table (ffgtam)");
	  continue;
	}

      /*
	 add the GRPID/LC keywords to the member header for this grouping
	 table
	 
	 If NGROUPS == 0 then we must position the header pointer to the
	 record where we want to insert the GRPID/LC keywords (the pointer
	 is already correctly positioned if the above search loop activiated)
      */

      if(ngroups == 0)
	{
	  /* 
	     no GRPIDn/GRPLCn keywords currently exist in header so try
	     to position the header pointer to a desirable position
	  */
	  
	  for(i = 0, *status = KEY_NO_EXIST; 
	                       i < nkeys && *status == KEY_NO_EXIST; ++i)
	    {
	      *status = 0;
	      *status = fits_read_card(tmpfptr,keys[i],card,status);
	    }
	      
	  /* all else fails: move write pointer to end of header */
	      
	  if(*status == KEY_NO_EXIST)
	    {
	      *status = 0;
	      fits_get_hdrspace(tmpfptr,&nkeys,&i,status);
	      ffgrec(tmpfptr,nkeys,card,status);
	    }
	  
	  /* any other error status then abort */
	  
	  if(*status != 0) continue;
	}
      
      /* 
	 now that the header pointer is positioned for the GRPID/LC 
	 keyword insertion increment the number of group links counter for 
	 the member HDU 
      */

      ++ngroups;

      /*
	 if the member HDU and grouping table reside in the same FITS file
	 then there is no need to add a GRPLCn keyword
      */
      /* SPR 3463 change test */
      /* Now, if either the Fptr values are the same, or the root filenames
	 are the same, then assume these refer to the same file.
      */
      fits_parse_rootname(tmpfptr->Fptr->filename, tmprootname, status);
      fits_parse_rootname(gfptr->Fptr->filename, grootname, status);

      if((tmpfptr->Fptr == gfptr->Fptr) || 
	          strncmp(tmprootname, grootname, FLEN_FILENAME) == 0)
	{
	  /* add the GRPIDn keyword only */

	  snprintf(keyword,FLEN_KEYWORD,"GRPID%d",(int)ngroups);
	  fits_insert_key_lng(tmpfptr,keyword,groupExtver,
			      "EXTVER of Group containing this HDU",status);
	}
      else 
	{
	  /* add the GRPIDn and GRPLCn keywords */

	  snprintf(keyword,FLEN_KEYWORD,"GRPID%d",(int)ngroups);
	  fits_insert_key_lng(tmpfptr,keyword,groupExtver,
			      "EXTVER of Group containing this HDU",status);

	  snprintf(keyword,FLEN_KEYWORD,"GRPLC%d",(int)ngroups);
	  /* SPR 1738 */
	  fits_insert_key_longstr(tmpfptr,keyword,groupFileName,
			      "URL of file containing Group",status);
	  fits_write_key_longwarn(tmpfptr,status);

	}

    }while(0);

  /* close the tmpfptr pointer if it was opened in this function */

  if(mfptr == NULL)
    {
      *status = fits_close_file(tmpfptr,status);
    }

  *status = 0 == *status ? parentStatus : *status;

  return(*status);
}

/*---------------------------------------------------------------------------*/
int ffgtnm(fitsfile *gfptr,    /* FITS file pointer to grouping table        */
	   long     *nmembers, /* member count  of the groping table         */
	   int      *status)   /* return status code                         */

/*
  return the number of member HDUs in a grouping table. The fitsfile pointer
  gfptr must be positioned with the grouping table as the CHDU. The number
  of grouping table member HDUs is just the NAXIS2 value of the grouping
  table.
*/

{
  char keyvalue[FLEN_VALUE];
  char comment[FLEN_COMMENT];
  

  if(*status != 0) return(*status);

  *status = fits_read_keyword(gfptr,"EXTNAME",keyvalue,comment,status);
  
  if(*status == KEY_NO_EXIST)
    *status = NOT_GROUP_TABLE;
  else
    {
      prepare_keyvalue(keyvalue);

      if(fits_strcasecmp(keyvalue,"GROUPING") != 0)
	{
	  *status = NOT_GROUP_TABLE;
	  ffpmsg("Specified HDU is not a Grouping table (ffgtnm)");
	}

      *status = fits_read_key_lng(gfptr,"NAXIS2",nmembers,comment,status);
    }

  return(*status);
}

/*--------------------------------------------------------------------------*/
int ffgmng(fitsfile *mfptr,   /* FITS file pointer to member HDU            */
	   long     *ngroups, /* total number of groups linked to HDU       */
	   int      *status)  /* return status code                         */

/*
  return the number of groups to which a HDU belongs, as defined by the number
  of GRPIDn/GRPLCn keyword records that appear in the HDU header. The 
  fitsfile pointer mfptr must be positioned with the member HDU as the CHDU. 
  Each time this function is called, the indicies of the GRPIDn/GRPLCn
  keywords are checked to make sure they are continuous (ie no gaps) and
  are re-enumerated to eliminate gaps if gaps are found to be present.
*/

{
  int offset;
  int index;
  int newIndex;
  int i;
  
  long grpid;

  char *inclist[] = {"GRPID#"};
  char keyword[FLEN_KEYWORD];
  char newKeyword[FLEN_KEYWORD];
  char card[FLEN_CARD];
  char comment[FLEN_COMMENT];
  char *tkeyvalue;

  if(*status != 0) return(*status);

  *ngroups = 0;

  /* reset the member HDU keyword counter to the beginning */

  *status = ffgrec(mfptr,0,card,status);
  
  /*
    search for the number of GRPIDn keywords in the member HDU header
    and count them with the ngroups variable
  */
  
  while(*status == 0)
    {
      /* read the next GRPIDn keyword in the series */

      *status = fits_find_nextkey(mfptr,inclist,1,NULL,0,card,status);
      
      if(*status != 0) continue;
      
      ++(*ngroups);
    }

  if(*status == KEY_NO_EXIST) *status = 0;
      
  /*
     read each GRPIDn/GRPLCn keyword and adjust their index values so that
     there are no gaps in the index count
  */

  for(index = 1, offset = 0, i = 1; i <= *ngroups && *status == 0; ++index)
    {	  
      snprintf(keyword,FLEN_KEYWORD,"GRPID%d",index);

      /* try to read the next GRPIDn keyword in the series */

      *status = fits_read_key_lng(mfptr,keyword,&grpid,card,status);

      /* if not found then increment the offset counter and continue */

      if(*status == KEY_NO_EXIST) 
	{
	  *status = 0;
	  ++offset;
	}
      else
	{
	  /* 
	     increment the number_keys_found counter and see if the index
	     of the keyword needs to be updated
	  */

	  ++i;

	  if(offset > 0)
	    {
	      /* compute the new index for the GRPIDn/GRPLCn keywords */
	      newIndex = index - offset;

	      /* update the GRPIDn keyword index */

	      snprintf(newKeyword,FLEN_KEYWORD,"GRPID%d",newIndex);
	      fits_modify_name(mfptr,keyword,newKeyword,status);

	      /* If present, update the GRPLCn keyword index */

	      snprintf(keyword,FLEN_KEYWORD,"GRPLC%d",index);
	      snprintf(newKeyword,FLEN_KEYWORD,"GRPLC%d",newIndex);
	      /* SPR 1738 */
	      *status = fits_read_key_longstr(mfptr,keyword,&tkeyvalue,comment,
					      status);
	      if (0 == *status) {
		fits_delete_key(mfptr,keyword,status);
		fits_insert_key_longstr(mfptr,newKeyword,tkeyvalue,comment,status);
		fits_write_key_longwarn(mfptr,status);
		free(tkeyvalue);
	      }
	      

	      if(*status == KEY_NO_EXIST) *status = 0;
	    }
	}
    }

  return(*status);
}

/*---------------------------------------------------------------------------*/
int ffgmop(fitsfile *gfptr,  /* FITS file pointer to grouping table          */
	   long      member, /* member ID (row num) within grouping table    */
	   fitsfile **mfptr, /* FITS file pointer to member HDU              */
	   int      *status) /* return status code                           */

/*
  open a grouping table member, returning a pointer to the member's FITS file
  with the CHDU set to the member HDU. The grouping table must be the CHDU of
  the FITS file pointed to by gfptr. The member to open is identified by its
  row number within the grouping table (first row/member == 1).

  If the member resides in a FITS file different from the grouping
  table the member file is first opened readwrite and if this fails then
  it is opened readonly. For access type of FILE:// the member file is
  searched for assuming (1) an absolute path is given, (2) a path relative
  to the CWD is given, and (3) a path relative to the grouping table file
  but not relative to the CWD is given. If all of these fail then the
  error FILE_NOT_FOUND is returned.
*/

{
  int xtensionCol,extnameCol,extverCol,positionCol,locationCol,uriCol;
  int grptype,hdutype;
  int dummy;

  long hdupos = 0;
  long extver = 0;

  char  xtension[FLEN_VALUE];
  char  extname[FLEN_VALUE];
  char  uri[FLEN_VALUE];
  char  grpLocation1[FLEN_FILENAME];
  char  grpLocation2[FLEN_FILENAME];
  char  mbrLocation1[FLEN_FILENAME];
  char  mbrLocation2[FLEN_FILENAME];
  char  mbrLocation3[FLEN_FILENAME];
  char  cwd[FLEN_FILENAME];
  char  card[FLEN_CARD];
  char  nstr[] = {'\0'};
  char *tmpPtr[1];


  if(*status != 0) return(*status);

  do
    {
      /*
	retrieve the Grouping Convention reserved column positions within
	the grouping table
      */

      *status = ffgtgc(gfptr,&xtensionCol,&extnameCol,&extverCol,&positionCol,
		       &locationCol,&uriCol,&grptype,status);

      if(*status != 0) continue;

      /*
	 extract the member information from grouping table
      */

      tmpPtr[0] = xtension;

      if(xtensionCol != 0)
	{

	  *status = fits_read_col_str(gfptr,xtensionCol,member,1,1,nstr,
				      tmpPtr,&dummy,status);

	  /* convert the xtension string to a hdutype code */

	  if(fits_strcasecmp(xtension,"PRIMARY")       == 0) hdutype = IMAGE_HDU; 
	  else if(fits_strcasecmp(xtension,"IMAGE")    == 0) hdutype = IMAGE_HDU; 
	  else if(fits_strcasecmp(xtension,"TABLE")    == 0) hdutype = ASCII_TBL; 
	  else if(fits_strcasecmp(xtension,"BINTABLE") == 0) hdutype = BINARY_TBL; 
	  else hdutype = ANY_HDU; 
	}

      tmpPtr[0] = extname;

      if(extnameCol  != 0)
	  *status = fits_read_col_str(gfptr,extnameCol,member,1,1,nstr,
				      tmpPtr,&dummy,status);

      if(extverCol   != 0)
	  *status = fits_read_col_lng(gfptr,extverCol,member,1,1,0,
				      (long*)&extver,&dummy,status);

      if(positionCol != 0)
	  *status = fits_read_col_lng(gfptr,positionCol,member,1,1,0,
				      (long*)&hdupos,&dummy,status);

      tmpPtr[0] = mbrLocation1;

      if(locationCol != 0)
	*status = fits_read_col_str(gfptr,locationCol,member,1,1,nstr,
				    tmpPtr,&dummy,status);
      tmpPtr[0] = uri;

      if(uriCol != 0)
	*status = fits_read_col_str(gfptr,uriCol,member,1,1,nstr,
				    tmpPtr,&dummy,status);

      if(*status != 0) continue;

      /* 
	 decide what FITS file the member HDU resides in and open the file
	 using the fitsfile* pointer mfptr; note that this logic is rather
	 complicated and is based primiarly upon if a URL specifier is given
	 for the member file in the grouping table
      */

      switch(grptype)
	{

	case GT_ID_POS:
	case GT_ID_REF:
	case GT_ID_ALL:

	  /*
	     no location information is given so we must assume that the
	     member HDU resides in the same FITS file as the grouping table;
	     if the grouping table was incorrectly constructed then this
	     assumption will be false, but there is nothing to be done about
	     it at this point
	  */

	  *status = fits_reopen_file(gfptr,mfptr,status);
	  
	  break;

	case GT_ID_REF_URI:
	case GT_ID_POS_URI:
	case GT_ID_ALL_URI:

	  /*
	    The member location column exists. Determine if the member 
	    resides in the same file as the grouping table or in a
	    separate file; open the member file in either case
	  */

	  if(strlen(mbrLocation1) == 0)
	    {
	      /*
		 since no location information was given we must assume
		 that the member is in the same FITS file as the grouping
		 table
	      */

	      *status = fits_reopen_file(gfptr,mfptr,status);
	    }
	  else
	    {
	      /*
		make sure the location specifiation is "URL"; we cannot
		decode any other URI types at this time
	      */

	      if(fits_strcasecmp(uri,"URL") != 0)
		{
		  *status = FILE_NOT_OPENED;
		  snprintf(card,FLEN_CARD,
		  "Cannot open member HDU file with URI type %s (ffgmop)",
			  uri);
		  ffpmsg(card);

		  continue;
		}

	      /*
		The location string for the member is not NULL, so it 
		does not necessially reside in the same FITS file as the
		grouping table. 

		Three cases are attempted for opening the member's file
		in the following order:

		1. The URL given for the member's file is absolute (i.e.,
		access method supplied); try to open the member

		2. The URL given for the member's file is not absolute but
		is an absolute file path; try to open the member as a file
		after the file path is converted to a host-dependent form

		3. The URL given for the member's file is not absolute
	        and is given as a relative path to the location of the 
		grouping table's file. Create an absolute URL using the 
		grouping table's file URL and try to open the member.
		
		If all three cases fail then an error is returned. In each
		case the file is first opened in read/write mode and failing
		that readonly mode.
		
		The following DO loop is only used as a mechanism to break
		(continue) when the proper file opening method is found
	       */

	      do
		{
		  /*
		     CASE 1:

		     See if the member URL is absolute (i.e., includes a
		     access directive) and if so open the file
		   */

		  if(fits_is_url_absolute(mbrLocation1))
		    {
		      /*
			 the URL must specify an access method, which 
			 implies that its an absolute reference
			 
			 regardless of the access method, pass the whole
			 URL to the open function for processing
		       */
		      
		      ffpmsg("member URL is absolute, try open R/W (ffgmop)");

		      *status = fits_open_file(mfptr,mbrLocation1,READWRITE,
					       status);

		      if(*status == 0) continue;

		      *status = 0;

		      /* 
			 now try to open file using full URL specs in 
			 readonly mode 
		      */ 

		      ffpmsg("OK, now try to open read-only (ffgmop)");

		      *status = fits_open_file(mfptr,mbrLocation1,READONLY,
					       status);

		      /* break from DO loop regardless of status */

		      continue;
		    }

		  /*
		     CASE 2:

		     If we got this far then the member URL location 
		     has no access type ==> FILE:// Try to open the member 
		     file using the URL as is, i.e., assume that it is given 
		     as absolute, if it starts with a '/' character
		   */

		  ffpmsg("Member URL is of type FILE (ffgmop)");

		  if(*mbrLocation1 == '/')
		    {
		      ffpmsg("Member URL specifies abs file path (ffgmop)");

		      /* 
			 convert the URL path to a host dependent path
		      */

		      *status = fits_url2path(mbrLocation1,mbrLocation2,
					      status);

		      ffpmsg("Try to open member URL in R/W mode (ffgmop)");

		      *status = fits_open_file(mfptr,mbrLocation2,READWRITE,
					       status);

		      if(*status == 0) continue;

		      *status = 0;

		      /* 
			 now try to open file using the URL as an absolute 
			 path in readonly mode 
		      */
 
		      ffpmsg("OK, now try to open read-only (ffgmop)");

		      *status = fits_open_file(mfptr,mbrLocation2,READONLY,
					       status);

		      /* break from the Do loop regardless of the status */

		      continue;
		    }
		  
		  /* 
		     CASE 3:

		     If we got this far then the URL does not specify an
		     absoulte file path or URL with access method. Since 
		     the path to the group table's file is (obviously) valid 
		     for the CWD, create a full location string for the
		     member HDU using the grouping table URL as a basis

		     The only problem is that the grouping table file might
		     have two URLs, the original one used to open it and
		     the one that points to the real file being accessed
		     (i.e., a file accessed via HTTP but transferred to a
		     local disk file). Have to attempt to build a URL to
		     the member HDU file using both of these URLs if
		     defined.
		  */

		  ffpmsg("Try to open member file as relative URL (ffgmop)");

		  /* get the URL information for the grouping table file */

		  *status = fits_get_url(gfptr,grpLocation1,grpLocation2,
					 NULL,NULL,NULL,status);

		  /* 
		     if the "real" grouping table file URL is defined then
		     build a full url for the member HDU file using it
		     and try to open the member HDU file
		  */

		  if(*grpLocation1)
		    {
		      /* make sure the group location is absolute */

		      if(! fits_is_url_absolute(grpLocation1) &&
			                              *grpLocation1 != '/')
			{
			  fits_get_cwd(cwd,status);
			  strcat(cwd,"/");
			  strcat(cwd,grpLocation1);
			  strcpy(grpLocation1,cwd);
			}

		      /* create a full URL for the member HDU file */

		      *status = fits_relurl2url(grpLocation1,mbrLocation1,
						mbrLocation2,status);

		      if(*status != 0) continue;

		      /*
			if the URL does not have an access method given then
			translate it into a host dependent file path
		      */

		      if(! fits_is_url_absolute(mbrLocation2))
			{
			  *status = fits_url2path(mbrLocation2,mbrLocation3,
						  status);
			  strcpy(mbrLocation2,mbrLocation3);
			}

		      /* try to open the member file READWRITE */

		      *status = fits_open_file(mfptr,mbrLocation2,READWRITE,
					       status);

		      if(*status == 0) continue;

		      *status = 0;
		  
		      /* now try to open in readonly mode */ 

		      ffpmsg("now try to open file as READONLY (ffgmop)");

		      *status = fits_open_file(mfptr,mbrLocation2,READONLY,
					       status);

		      if(*status == 0) continue;

		      *status = 0;
		    }

		  /* 
		     if we got this far then either the "real" grouping table
		     file URL was not defined or all attempts to open the
		     resulting member HDU file URL failed.

		     if the "original" grouping table file URL is defined then
		     build a full url for the member HDU file using it
		     and try to open the member HDU file
		  */

		  if(*grpLocation2)
		    {
		      /* make sure the group location is absolute */

		      if(! fits_is_url_absolute(grpLocation2) &&
			                              *grpLocation2 != '/')
			{
			  fits_get_cwd(cwd,status);
			  strcat(cwd,"/");
			  strcat(cwd,grpLocation2);
			  strcpy(grpLocation2,cwd);
			}

		      /* create an absolute URL for the member HDU file */

		      *status = fits_relurl2url(grpLocation2,mbrLocation1,
						mbrLocation2,status);
		      if(*status != 0) continue;

		      /*
			if the URL does not have an access method given then
			translate it into a host dependent file path
		      */

		      if(! fits_is_url_absolute(mbrLocation2))
			{
			  *status = fits_url2path(mbrLocation2,mbrLocation3,
						  status);
			  strcpy(mbrLocation2,mbrLocation3);
			}

		      /* try to open the member file READWRITE */

		      *status = fits_open_file(mfptr,mbrLocation2,READWRITE,
					       status);

		      if(*status == 0) continue;

		      *status = 0;
		  
		      /* now try to open in readonly mode */ 

		      ffpmsg("now try to open file as READONLY (ffgmop)");

		      *status = fits_open_file(mfptr,mbrLocation2,READONLY,
					       status);

		      if(*status == 0) continue;

		      *status = 0;
		    }

		  /*
		     if we got this far then the member HDU file could not
		     be opened using any method. Log the error.
		  */

		  ffpmsg("Cannot open member HDU FITS file (ffgmop)");
		  *status = MEMBER_NOT_FOUND;
		  
		}while(0);
	    }

	  break;

	default:

	  /* no default action */
	  
	  break;
	}
	  
      if(*status != 0) continue;

      /*
	 attempt to locate the member HDU within its FITS file as determined
	 and opened above
      */

      switch(grptype)
	{

	case GT_ID_POS:
	case GT_ID_POS_URI:

	  /*
	    try to find the member hdu in the the FITS file pointed to
	    by mfptr based upon its HDU posistion value. Note that is 
	    impossible to verify if the HDU is actually the correct HDU due 
	    to a lack of information.
	  */
	  
	  *status = fits_movabs_hdu(*mfptr,(int)hdupos,&hdutype,status);

	  break;

	case GT_ID_REF:
	case GT_ID_REF_URI:

	  /*
	     try to find the member hdu in the FITS file pointed to
	     by mfptr based upon its XTENSION, EXTNAME and EXTVER keyword 
	     values
	  */

	  *status = fits_movnam_hdu(*mfptr,hdutype,extname,extver,status);

	  if(*status == BAD_HDU_NUM) 
	    {
	      *status = MEMBER_NOT_FOUND;
	      ffpmsg("Cannot find specified member HDU (ffgmop)");
	    }

	  /*
	     if the above function returned without error then the
	     mfptr is pointed to the member HDU
	  */

	  break;

	case GT_ID_ALL:
	case GT_ID_ALL_URI:

	  /*
	     if the member entry has reference information then use it
             (ID by reference is safer than ID by position) else use
	     the position information
	  */

	  if(strlen(xtension) > 0 && strlen(extname) > 0 && extver > 0)
	    {
	      /* valid reference info exists so use it */
	      
	      /* try to find the member hdu in the grouping table's file */

	      *status = fits_movnam_hdu(*mfptr,hdutype,extname,extver,status);

	      if(*status == BAD_HDU_NUM) 
		{
		  *status = MEMBER_NOT_FOUND;
		  ffpmsg("Cannot find specified member HDU (ffgmop)");
		}
	    }
	  else
	      {
		  *status = fits_movabs_hdu(*mfptr,(int)hdupos,&hdutype,
					    status);
		  if(*status == END_OF_FILE) *status = MEMBER_NOT_FOUND;
	      }

	  /*
	     if the above function returned without error then the
	     mfptr is pointed to the member HDU
	  */

	  break;

	default:

	  /* no default action */

	  break;
	}
      
    }while(0);

  if(*status != 0 && *mfptr != NULL) 
    {
      fits_close_file(*mfptr,status);
    }

  return(*status);
}

/*---------------------------------------------------------------------------*/
int ffgmcp(fitsfile *gfptr,  /* FITS file pointer to group                   */
	   fitsfile *mfptr,  /* FITS file pointer to new member
				FITS file                                    */
	   long      member, /* member ID (row num) within grouping table    */
	   int       cpopt,  /* code specifying copy options:
				OPT_MCP_ADD  (0) ==> add copied member to the
 				                     grouping table
				OPT_MCP_NADD (1) ==> do not add member copy to
				                     the grouping table
				OPT_MCP_REPL (2) ==> replace current member
				                     entry with member copy  */
	   int      *status) /* return status code                           */
	   
/*
  copy a member HDU of a grouping table to a new FITS file. The grouping table
  must be the CHDU of the FITS file pointed to by gfptr. The copy of the
  group member shall be appended to the end of the FITS file pointed to by
  mfptr. If the cpopt parameter is set to OPT_MCP_ADD then the copy of the 
  member is added to the grouping table as a new member, if OPT_MCP_NADD 
  then the copied member is not added to the grouping table, and if 
  OPT_MCP_REPL then the copied member is used to replace the original member.
  The copied member HDU also has its EXTVER value updated so that its
  combination of XTENSION, EXTNAME and EXVTER is unique within its new
  FITS file.
*/

{
  int numkeys = 0;
  int keypos  = 0;
  int hdunum  = 0;
  int hdutype = 0;
  int i;
  
  char *incList[] = {"GRPID#","GRPLC#"};
  char  extname[FLEN_VALUE];
  char  card[FLEN_CARD];
  char  comment[FLEN_COMMENT];
  char  keyname[FLEN_CARD];
  char  value[FLEN_CARD];

  fitsfile *tmpfptr = NULL;


  if(*status != 0) return(*status);

  do
    {
      /* open the member HDU to be copied */

      *status = fits_open_member(gfptr,member,&tmpfptr,status);

      if(*status != 0) continue;

      /*
	if the member is a grouping table then copy it with a call to
	fits_copy_group() using the "copy only the grouping table" option

	if it is not a grouping table then copy the hdu with fits_copy_hdu()
	remove all GRPIDn and GRPLCn keywords, and update the EXTVER keyword
	value
      */

      /* get the member HDU's EXTNAME value */

      *status = fits_read_key_str(tmpfptr,"EXTNAME",extname,comment,status);

      /* if no EXTNAME value was found then set the extname to a null string */

      if(*status == KEY_NO_EXIST) 
	{
	  extname[0] = 0;
	  *status    = 0;
	}
      else if(*status != 0) continue;

      prepare_keyvalue(extname);

      /* if a grouping table then copy with fits_copy_group() */

      if(fits_strcasecmp(extname,"GROUPING") == 0)
	*status = fits_copy_group(tmpfptr,mfptr,OPT_GCP_GPT,status);
      else
	{
	  /* copy the non-grouping table HDU the conventional way */

	  *status = fits_copy_hdu(tmpfptr,mfptr,0,status);

	  ffgrec(mfptr,0,card,status);

	  /* delete all the GRPIDn and GRPLCn keywords in the copied HDU */

	  while(*status == 0)
	    {
	      *status = fits_find_nextkey(mfptr,incList,2,NULL,0,card,status);
	      *status = fits_get_hdrpos(mfptr,&numkeys,&keypos,status);  
	      /* SPR 1738 */
	      *status = fits_read_keyn(mfptr,keypos-1,keyname,value,
				       comment,status);
	      *status = fits_read_record(mfptr,keypos-1,card,status);
	      *status = fits_delete_key(mfptr,keyname,status);
	    }

	  if(*status == KEY_NO_EXIST) *status = 0;
	  if(*status != 0) continue;
	}

      /* 
	 if the member HDU does not have an EXTNAME keyword then add one
	 with a default value
      */

      if(strlen(extname) == 0)
	{
	  if(fits_get_hdu_num(tmpfptr,&hdunum) == 1)
	    {
	      strcpy(extname,"PRIMARY");
	      *status = fits_write_key_str(mfptr,"EXTNAME",extname,
					   "HDU was Formerly a Primary Array",
					   status);
	    }
	  else
	    {
	      strcpy(extname,"DEFAULT");
	      *status = fits_write_key_str(mfptr,"EXTNAME",extname,
					   "default EXTNAME set by CFITSIO",
					   status);
	    }
	}

      /* 
	 update the member HDU's EXTVER value (add it if not present)
      */

      fits_get_hdu_num(mfptr,&hdunum);
      fits_get_hdu_type(mfptr,&hdutype,status);

      /* set the EXTVER value to 0 for now */

      *status = fits_modify_key_lng(mfptr,"EXTVER",0,NULL,status);

      /* if the EXTVER keyword was not found then add it */

      if(*status == KEY_NO_EXIST)
	{
	  *status = 0;
	  *status = fits_read_key_str(mfptr,"EXTNAME",extname,comment,
				      status);
	  *status = fits_insert_key_lng(mfptr,"EXTVER",0,
					"Extension version ID",status);
	}

      if(*status != 0) continue;

      /* find the first available EXTVER value for the copied HDU */
 
      for(i = 1; fits_movnam_hdu(mfptr,hdutype,extname,i,status) == 0; ++i);

      *status = 0;

      fits_movabs_hdu(mfptr,hdunum,&hdutype,status);

      /* reset the copied member HDUs EXTVER value */

      *status = fits_modify_key_lng(mfptr,"EXTVER",(long)i,NULL,status);    

      /*
	perform member copy operations that are dependent upon the cpopt
	parameter value
      */

      switch(cpopt)
	{
	case OPT_MCP_ADD:

	  /*
	    add the copied member to the grouping table, leaving the
	    entry for the original member in place
	  */

	  *status = fits_add_group_member(gfptr,mfptr,0,status);

	  break;

	case OPT_MCP_NADD:

	  /*
	    nothing to do for this copy option
	  */

	  break;

	case OPT_MCP_REPL:

	  /*
	    remove the original member from the grouping table and add the
	    copied member in its place
	  */

	  *status = fits_remove_member(gfptr,member,OPT_RM_ENTRY,status);
	  *status = fits_add_group_member(gfptr,mfptr,0,status);

	  break;

	default:

	  *status = BAD_OPTION;
	  ffpmsg("Invalid value specified for the cmopt parameter (ffgmcp)");

	  break;
	}

    }while(0);
      
  if(tmpfptr != NULL) 
    {
      fits_close_file(tmpfptr,status);
    }

  return(*status);
}		     

/*---------------------------------------------------------------------------*/
int ffgmtf(fitsfile *infptr,   /* FITS file pointer to source grouping table */
	   fitsfile *outfptr,  /* FITS file pointer to target grouping table */
	   long      member,   /* member ID within source grouping table     */
	   int       tfopt,    /* code specifying transfer opts:
				  OPT_MCP_ADD (0) ==> copy member to dest.
				  OPT_MCP_MOV (3) ==> move member to dest.   */
	   int      *status)   /* return status code                         */

/*
  transfer a group member from one grouping table to another. The source
  grouping table must be the CHDU of the fitsfile pointed to by infptr, and 
  the destination grouping table must be the CHDU of the fitsfile to by 
  outfptr. If the tfopt parameter is OPT_MCP_ADD then the member is made a 
  member of the target group and remains a member of the source group. If
  the tfopt parameter is OPT_MCP_MOV then the member is deleted from the 
  source group after the transfer to the destination group. The member to be
  transfered is identified by its row number within the source grouping table.
*/

{
  fitsfile *mfptr = NULL;


  if(*status != 0) return(*status);

  if(tfopt != OPT_MCP_MOV && tfopt != OPT_MCP_ADD)
    {
      *status = BAD_OPTION;
      ffpmsg("Invalid value specified for the tfopt parameter (ffgmtf)");
    }
  else
    {
      /* open the member of infptr to be transfered */

      *status = fits_open_member(infptr,member,&mfptr,status);
      
      /* add the member to the outfptr grouping table */
      
      *status = fits_add_group_member(outfptr,mfptr,0,status);
      
      /* close the member HDU */
      
      *status = fits_close_file(mfptr,status);
      
      /* 
	 if the tfopt is "move member" then remove it from the infptr 
	 grouping table
      */

      if(tfopt == OPT_MCP_MOV)
	*status = fits_remove_member(infptr,member,OPT_RM_ENTRY,status);
    }
  
  return(*status);
}

/*---------------------------------------------------------------------------*/
int ffgmrm(fitsfile *gfptr,  /* FITS file pointer to group table             */
	   long      member, /* member ID (row num) in the group             */
	   int       rmopt,  /* code specifying the delete option:
				OPT_RM_ENTRY ==> delete the member entry
				OPT_RM_MBR   ==> delete entry and member HDU */
	   int      *status)  /* return status code                          */

/*
  remove a member HDU from a grouping table. The fitsfile pointer gfptr must
  be positioned with the grouping table as the CHDU, and the member to 
  delete is identified by its row number in the table (first member == 1).
  The rmopt parameter determines if the member entry is deleted from the
  grouping table (in which case GRPIDn and GRPLCn keywords in the member 
  HDU's header shall be updated accordingly) or if the member HDU shall 
  itself be removed from its FITS file.
*/

{
  int found;
  int hdutype   = 0;
  int index;
  int iomode    = 0;

  long i;
  long ngroups      = 0;
  long nmembers     = 0;
  long groupExtver  = 0;
  long grpid        = 0;

  char grpLocation1[FLEN_FILENAME];
  char grpLocation2[FLEN_FILENAME];
  char grpLocation3[FLEN_FILENAME];
  char cwd[FLEN_FILENAME];
  char keyword[FLEN_KEYWORD];
  /* SPR 1738 This can now be longer */
  char grplc[FLEN_FILENAME];
  char *tgrplc;
  char keyvalue[FLEN_VALUE];
  char card[FLEN_CARD];
  char *editLocation;
  char mrootname[FLEN_FILENAME], grootname[FLEN_FILENAME];

  fitsfile *mfptr  = NULL;


  if(*status != 0) return(*status);

  do
    {
      /*
	make sure the grouping table can be modified before proceeding
      */

      fits_file_mode(gfptr,&iomode,status);

      if(iomode != READWRITE)
	{
	  ffpmsg("cannot modify grouping table (ffgtam)");
	  *status = BAD_GROUP_DETACH;
	  continue;
	}

      /* open the group member to be deleted and get its IOstatus*/

      *status = fits_open_member(gfptr,member,&mfptr,status);
      *status = fits_file_mode(mfptr,&iomode,status);

      /*
	 if the member HDU is to be deleted then call fits_unlink_member()
	 to remove it from all groups to which it belongs (including
	 this one) and then delete it. Note that if the member is a
	 grouping table then we have to recursively call fits_remove_member()
	 for each member of the member before we delete the member itself.
      */

      if(rmopt == OPT_RM_MBR)
	{
	    /* cannot delete a PHDU */
	    if(fits_get_hdu_num(mfptr,&hdutype) == 1)
		{
		    *status = BAD_HDU_NUM;
		    continue;
		}

	  /* determine if the member HDU is itself a grouping table */

	  *status = fits_read_key_str(mfptr,"EXTNAME",keyvalue,card,status);

	  /* if no EXTNAME is found then the HDU cannot be a grouping table */ 

	  if(*status == KEY_NO_EXIST) 
	    {
	      keyvalue[0] = 0;
	      *status = 0;
	    }
	  prepare_keyvalue(keyvalue);

	  /* Any other error is a reason to abort */

	  if(*status != 0) continue;

	  /* if the EXTNAME == GROUPING then the member is a grouping table */
	  
	  if(fits_strcasecmp(keyvalue,"GROUPING") == 0)
	    {
	      /* remove each of the grouping table members */
	      
	      *status = fits_get_num_members(mfptr,&nmembers,status);
	      
	      for(i = nmembers; i > 0 && *status == 0; --i)
		*status = fits_remove_member(mfptr,i,OPT_RM_ENTRY,status);
	      
	      if(*status != 0) continue;
	    }

	  /* unlink the member HDU from all groups that contain it */

	  *status = ffgmul(mfptr,0,status);

	  if(*status != 0) continue;
 
	  /* reset the grouping table HDU struct */

	  fits_set_hdustruc(gfptr,status);

	  /* delete the member HDU */

	  if(iomode != READONLY)
	    *status = fits_delete_hdu(mfptr,&hdutype,status);
	}
      else if(rmopt == OPT_RM_ENTRY)
	{
	  /* 
	     The member HDU is only to be removed as an entry from this
	     grouping table. Actions are (1) find the GRPIDn/GRPLCn 
	     keywords that link the member to the grouping table, (2)
	     remove the GRPIDn/GRPLCn keyword from the member HDU header
	     and (3) remove the member entry from the grouping table
	  */

	  /*
	    there is no need to seach for and remove the GRPIDn/GRPLCn
	    keywords from the member HDU if it has not been opened
	    in READWRITE mode
	  */

	  if(iomode == READWRITE)
	    {	  	      
	      /* 
		 determine the group EXTVER value of the grouping table; if
		 the member HDU and grouping table HDU do not reside in the 
		 same file then set the groupExtver value to its negative 
	      */
	      
	      *status = fits_read_key_lng(gfptr,"EXTVER",&groupExtver,card,
					  status);
	      /* Now, if either the Fptr values are the same, or the root filenames
	         are the same, then assume these refer to the same file.
	      */
	      fits_parse_rootname(mfptr->Fptr->filename, mrootname, status);
	      fits_parse_rootname(gfptr->Fptr->filename, grootname, status);

	      if((mfptr->Fptr != gfptr->Fptr) && 
	          strncmp(mrootname, grootname, FLEN_FILENAME))
                       groupExtver = -1*groupExtver;
	      
	      /*
		retrieve the URLs for the grouping table; note that it is 
		possible that the grouping table file has two URLs, the 
		one used to open it and the "real" one pointing to the 
		actual file being accessed
	      */
	      
	      *status = fits_get_url(gfptr,grpLocation1,grpLocation2,NULL,
				     NULL,NULL,status);
	      
	      if(*status != 0) continue;
	      
	      /*
		if either of the group location strings specify a relative
		file path then convert them into absolute file paths
	      */

	      *status = fits_get_cwd(cwd,status);
	      
	      if(*grpLocation1 != 0 && *grpLocation1 != '/' &&
		 !fits_is_url_absolute(grpLocation1))
		{
		  strcpy(grpLocation3,cwd);
		  strcat(grpLocation3,"/");
		  strcat(grpLocation3,grpLocation1);
		  fits_clean_url(grpLocation3,grpLocation1,status);
		}
	      
	      if(*grpLocation2 != 0 && *grpLocation2 != '/' &&
		 !fits_is_url_absolute(grpLocation2))
		{
		  strcpy(grpLocation3,cwd);
		  strcat(grpLocation3,"/");
		  strcat(grpLocation3,grpLocation2);
		  fits_clean_url(grpLocation3,grpLocation2,status);
		}
	      
	      /*
		determine the number of groups to which the member HDU 
		belongs
	      */
	      
	      *status = fits_get_num_groups(mfptr,&ngroups,status);
	      
	      /* reset the HDU keyword position counter to the beginning */
	      
	      *status = ffgrec(mfptr,0,card,status);
	      
	      /*
		loop over all the GRPIDn keywords in the member HDU header 
		and find the appropriate GRPIDn and GRPLCn keywords that 
		identify it as belonging to the group
	      */
	      
	      for(index = 1, found = 0; index <= ngroups && *status == 0 && 
		    !found; ++index)
		{	  
		  /* read the next GRPIDn keyword in the series */
		  
		  snprintf(keyword,FLEN_KEYWORD,"GRPID%d",index);
		  
		  *status = fits_read_key_lng(mfptr,keyword,&grpid,card,
					      status);
		  if(*status != 0) continue;
		  
		  /* 
		     grpid value == group EXTVER value then we could have a 
		     match
		  */
		  
		  if(grpid == groupExtver && grpid > 0)
		    {
		      /*
			if GRPID is positive then its a match because 
			both the member HDU and grouping table HDU reside
			in the same FITS file
		      */
		      
		      found = index;
		    }
		  else if(grpid == groupExtver && grpid < 0)
		    {
		      /* 
			 have to look at the GRPLCn value to determine a 
			 match because the member HDU and grouping table 
			 HDU reside in different FITS files
		      */
		      
		      snprintf(keyword,FLEN_KEYWORD,"GRPLC%d",index);
		      
		      /* SPR 1738 */
		      *status = fits_read_key_longstr(mfptr,keyword,&tgrplc,
						      card, status);
		      if (0 == *status) {
			strcpy(grplc,tgrplc);
			free(tgrplc);
		      }
		      		      
		      if(*status == KEY_NO_EXIST)
			{
			  /* 
			     no GRPLCn keyword value found ==> grouping
			     convention not followed; nothing we can do 
			     about it, so just continue
			  */
			  
			  snprintf(card,FLEN_CARD,"No GRPLC%d found for GRPID%d",
				  index,index);
			  ffpmsg(card);
			  *status = 0;
			  continue;
			}
		      else if (*status != 0) continue;
		      
		      /* construct the URL for the GRPLCn value */
		      
		      prepare_keyvalue(grplc);
		      
		      /*
			if the grplc value specifies a relative path then
			turn it into a absolute file path for comparison
			purposes
		      */
		      
		      if(*grplc != 0 && !fits_is_url_absolute(grplc) &&
			 *grplc != '/')
			{
			    /* No, wrong, 
			       strcpy(grpLocation3,cwd);
			       should be */
			    *status = fits_file_name(mfptr,grpLocation3,status);
			    /* Remove everything after the last / */
			    if (NULL != (editLocation = strrchr(grpLocation3,'/'))) {
				*editLocation = '\0';
			    }
				
			  strcat(grpLocation3,"/");
			  strcat(grpLocation3,grplc);
			  *status = fits_clean_url(grpLocation3,grplc,
						   status);
			}
		      
		      /*
			if the absolute value of GRPIDn is equal to the
			EXTVER value of the grouping table and (one of the 
			possible two) grouping table file URL matches the
			GRPLCn keyword value then we hava a match
		      */
		      
		      if(strcmp(grplc,grpLocation1) == 0  || 
			 strcmp(grplc,grpLocation2) == 0) 
			found = index; 
		    }
		}

	      /*
		if found == 0 (false) after the above search then we assume 
		that it is due to an inpromper updating of the GRPIDn and 
		GRPLCn keywords in the member header ==> nothing to delete 
		in the header. Else delete the GRPLCn and GRPIDn keywords 
		that identify the member HDU with the group HDU and 
		re-enumerate the remaining GRPIDn and GRPLCn keywords
	      */

	      if(found != 0)
		{
		  snprintf(keyword,FLEN_KEYWORD,"GRPID%d",found);
		  *status = fits_delete_key(mfptr,keyword,status);
		  
		  snprintf(keyword,FLEN_KEYWORD,"GRPLC%d",found);
		  *status = fits_delete_key(mfptr,keyword,status);
		  
		  *status = 0;
		  
		  /* call fits_get_num_groups() to re-enumerate the GRPIDn */
		  
		  *status = fits_get_num_groups(mfptr,&ngroups,status);
		} 
	    }

	  /*
	     finally, remove the member entry from the current grouping table
	     pointed to by gfptr
	  */

	  *status = fits_delete_rows(gfptr,member,1,status);
	}
      else
	{
	  *status = BAD_OPTION;
	  ffpmsg("Invalid value specified for the rmopt parameter (ffgmrm)");
	}

    }while(0);

  if(mfptr != NULL) 
    {
      fits_close_file(mfptr,status);
    }

  return(*status);
}

/*---------------------------------------------------------------------------
                 Grouping Table support functions
  ---------------------------------------------------------------------------*/
int ffgtgc(fitsfile *gfptr,  /* pointer to the grouping table                */
	   int *xtensionCol, /* column ID of the MEMBER_XTENSION column      */
	   int *extnameCol,  /* column ID of the MEMBER_NAME column          */
	   int *extverCol,   /* column ID of the MEMBER_VERSION column       */
	   int *positionCol, /* column ID of the MEMBER_POSITION column      */
	   int *locationCol, /* column ID of the MEMBER_LOCATION column      */
	   int *uriCol,      /* column ID of the MEMBER_URI_TYPE column      */
	   int *grptype,     /* group structure type code specifying the
				grouping table columns that are defined:
				GT_ID_ALL_URI  (0) ==> all columns defined   
				GT_ID_REF      (1) ==> reference cols only   
				GT_ID_POS      (2) ==> position col only     
				GT_ID_ALL      (3) ==> ref & pos cols        
				GT_ID_REF_URI (11) ==> ref & loc cols        
				GT_ID_POS_URI (12) ==> pos & loc cols        */
	   int *status)      /* return status code                           */
/*
   examine the grouping table pointed to by gfptr and determine the column
   index ID of each possible grouping column. If a column is not found then
   an index of 0 is returned. the grptype parameter returns the structure
   of the grouping table ==> what columns are defined.
*/

{

  char keyvalue[FLEN_VALUE];
  char comment[FLEN_COMMENT];


  if(*status != 0) return(*status);

  do
    {
      /*
	if the HDU does not have an extname of "GROUPING" then it is not
	a grouping table
      */

      *status = fits_read_key_str(gfptr,"EXTNAME",keyvalue,comment,status);
  
      if(*status == KEY_NO_EXIST) 
	{
	  *status = NOT_GROUP_TABLE;
	  ffpmsg("Specified HDU is not a Grouping Table (ffgtgc)");
	}
      if(*status != 0) continue;

      prepare_keyvalue(keyvalue);

      if(fits_strcasecmp(keyvalue,"GROUPING") != 0)
	{
	  *status = NOT_GROUP_TABLE;
	  continue;
	}

      /*
        search for the MEMBER_XTENSION, MEMBER_NAME, MEMBER_VERSION,
	MEMBER_POSITION, MEMBER_LOCATION and MEMBER_URI_TYPE columns
	and determine their column index ID
      */

      *status = fits_get_colnum(gfptr,CASESEN,"MEMBER_XTENSION",xtensionCol,
				status);

      if(*status == COL_NOT_FOUND)
	{
	  *status      = 0;
 	  *xtensionCol = 0;
	}

      if(*status != 0) continue;

      *status = fits_get_colnum(gfptr,CASESEN,"MEMBER_NAME",extnameCol,status);

      if(*status == COL_NOT_FOUND)
	{
	  *status     = 0;
	  *extnameCol = 0;
	}

      if(*status != 0) continue;

      *status = fits_get_colnum(gfptr,CASESEN,"MEMBER_VERSION",extverCol,
				status);

      if(*status == COL_NOT_FOUND)
	{
	  *status    = 0;
	  *extverCol = 0;
	}

      if(*status != 0) continue;

      *status = fits_get_colnum(gfptr,CASESEN,"MEMBER_POSITION",positionCol,
				status);

      if(*status == COL_NOT_FOUND)
	{
	  *status      = 0;
	  *positionCol = 0;
	}

      if(*status != 0) continue;

      *status = fits_get_colnum(gfptr,CASESEN,"MEMBER_LOCATION",locationCol,
				status);

      if(*status == COL_NOT_FOUND)
	{
	  *status      = 0;
	  *locationCol = 0;
	}

      if(*status != 0) continue;

      *status = fits_get_colnum(gfptr,CASESEN,"MEMBER_URI_TYPE",uriCol,
				status);

      if(*status == COL_NOT_FOUND)
	{
	  *status = 0;
	  *uriCol = 0;
	}

      if(*status != 0) continue;

      /*
	 determine the type of grouping table structure used by this
	 grouping table and record it in the grptype parameter
      */

      if(*xtensionCol && *extnameCol && *extverCol && *positionCol &&
	 *locationCol && *uriCol) 
	*grptype = GT_ID_ALL_URI;
      
      else if(*xtensionCol && *extnameCol && *extverCol &&
	      *locationCol && *uriCol) 
	*grptype = GT_ID_REF_URI;

      else if(*xtensionCol && *extnameCol && *extverCol && *positionCol)
	*grptype = GT_ID_ALL;
      
      else if(*xtensionCol && *extnameCol && *extverCol)
	*grptype = GT_ID_REF;
      
      else if(*positionCol && *locationCol && *uriCol) 
	*grptype = GT_ID_POS_URI;
      
      else if(*positionCol)
	*grptype = GT_ID_POS;
      
      else
	*status = NOT_GROUP_TABLE;
      
    }while(0);

  /*
    if the table contained more than one column with a reserved name then
    this cannot be considered a vailid grouping table
  */

  if(*status == COL_NOT_UNIQUE) 
    {
      *status = NOT_GROUP_TABLE;
      ffpmsg("Specified HDU has multipule Group table cols defined (ffgtgc)");
    }

  return(*status);
}

/*****************************************************************************/
int ffgtdc(int   grouptype,     /* code specifying the type of
				   grouping table information:
				   GT_ID_ALL_URI  0 ==> defualt (all columns)
				   GT_ID_REF      1 ==> ID by reference
				   GT_ID_POS      2 ==> ID by position
				   GT_ID_ALL      3 ==> ID by ref. and position
				   GT_ID_REF_URI 11 ==> (1) + URI info 
				   GT_ID_POS_URI 12 ==> (2) + URI info       */
	   int   xtensioncol, /* does MEMBER_XTENSION already exist?         */
	   int   extnamecol,  /* does MEMBER_NAME aleady exist?              */
	   int   extvercol,   /* does MEMBER_VERSION already exist?          */
	   int   positioncol, /* does MEMBER_POSITION already exist?         */
	   int   locationcol, /* does MEMBER_LOCATION already exist?         */
	   int   uricol,      /* does MEMBER_URI_TYPE aleardy exist?         */
	   char *ttype[],     /* array of grouping table column TTYPE names
				 to define (if *col var false)               */
	   char *tform[],     /* array of grouping table column TFORM values
				 to define (if*col variable false)           */
	   int  *ncols,       /* number of TTYPE and TFORM values returned   */
	   int  *status)      /* return status code                          */

/*
  create the TTYPE and TFORM values for the grouping table according to the
  value of the grouptype parameter and the values of the *col flags. The
  resulting TTYPE and TFORM are returned in ttype[] and tform[] respectively.
  The number of TTYPE and TFORMs returned is given by ncols. Both the TTYPE[]
  and TTFORM[] arrays must contain enough pre-allocated strings to hold
  the returned information.
*/

{

  int i = 0;

  char  xtension[]  = "MEMBER_XTENSION";
  char  xtenTform[] = "8A";
  
  char  name[]      = "MEMBER_NAME";
  char  nameTform[] = "32A";

  char  version[]   = "MEMBER_VERSION";
  char  verTform[]  = "1J";
  
  char  position[]  = "MEMBER_POSITION";
  char  posTform[]  = "1J";

  char  URI[]       = "MEMBER_URI_TYPE";
  char  URITform[]  = "3A";

  char  location[]  = "MEMBER_LOCATION";
  /* SPR 01720, move from 160A to 256A */
  char  locTform[]  = "256A";


  if(*status != 0) return(*status);

  switch(grouptype)
    {
      
    case GT_ID_ALL_URI:

      if(xtensioncol == 0)
	{
	  strcpy(ttype[i],xtension);
	  strcpy(tform[i],xtenTform);
	  ++i;
	}
      if(extnamecol == 0)
	{
	  strcpy(ttype[i],name);
	  strcpy(tform[i],nameTform);
	  ++i;
	}
      if(extvercol == 0)
	{
	  strcpy(ttype[i],version);
	  strcpy(tform[i],verTform);
	  ++i;
	}
      if(positioncol == 0)
	{
	  strcpy(ttype[i],position);
	  strcpy(tform[i],posTform);
	  ++i;
	}
      if(locationcol == 0)
	{
	  strcpy(ttype[i],location);
	  strcpy(tform[i],locTform);
	  ++i;
	}
      if(uricol == 0)
	{
	  strcpy(ttype[i],URI);
	  strcpy(tform[i],URITform);
	  ++i;
	}
      break;
      
    case GT_ID_REF:
      
      if(xtensioncol == 0)
	{
	  strcpy(ttype[i],xtension);
	  strcpy(tform[i],xtenTform);
	  ++i;
	}
      if(extnamecol == 0)
	{
	  strcpy(ttype[i],name);
	  strcpy(tform[i],nameTform);
	  ++i;
	}
      if(extvercol == 0)
	{
	  strcpy(ttype[i],version);
	  strcpy(tform[i],verTform);
	  ++i;
	}
      break;
      
    case GT_ID_POS:
      
      if(positioncol == 0)
	{
	  strcpy(ttype[i],position);
	  strcpy(tform[i],posTform);
	  ++i;
	}	  
      break;
      
    case GT_ID_ALL:
      
      if(xtensioncol == 0)
	{
	  strcpy(ttype[i],xtension);
	  strcpy(tform[i],xtenTform);
	  ++i;
	}
      if(extnamecol == 0)
	{
	  strcpy(ttype[i],name);
	  strcpy(tform[i],nameTform);
	  ++i;
	}
      if(extvercol == 0)
	{
	  strcpy(ttype[i],version);
	  strcpy(tform[i],verTform);
	  ++i;
	}
      if(positioncol == 0)
	{
	  strcpy(ttype[i],position);
	  strcpy(tform[i], posTform);
	  ++i;
	}	  
      
      break;
      
    case GT_ID_REF_URI:
      
      if(xtensioncol == 0)
	{
	  strcpy(ttype[i],xtension);
	  strcpy(tform[i],xtenTform);
	  ++i;
	}
      if(extnamecol == 0)
	{
	  strcpy(ttype[i],name);
	  strcpy(tform[i],nameTform);
	  ++i;
	}
      if(extvercol == 0)
	{
	  strcpy(ttype[i],version);
	  strcpy(tform[i],verTform);
	  ++i;
	}
      if(locationcol == 0)
	{
	  strcpy(ttype[i],location);
	  strcpy(tform[i],locTform);
	  ++i;
	}
      if(uricol == 0)
	{
	  strcpy(ttype[i],URI);
	  strcpy(tform[i],URITform);
	  ++i;
	}
      break;
      
    case GT_ID_POS_URI:
      
      if(positioncol == 0)
	{
	  strcpy(ttype[i],position);
	  strcpy(tform[i],posTform);
	  ++i;
	}
      if(locationcol == 0)
	{
	  strcpy(ttype[i],location);
	  strcpy(tform[i],locTform);
	  ++i;
	}
      if(uricol == 0)
	{
	  strcpy(ttype[i],URI);
	  strcpy(tform[i],URITform);
	  ++i;
	}
      break;
      
    default:
      
      *status = BAD_OPTION;
      ffpmsg("Invalid value specified for the grouptype parameter (ffgtdc)");

      break;

    }

  *ncols = i;
  
  return(*status);
}

/*****************************************************************************/
int ffgmul(fitsfile *mfptr,   /* pointer to the grouping table member HDU    */
           int       rmopt,   /* 0 ==> leave GRPIDn/GRPLCn keywords,
				 1 ==> remove GRPIDn/GRPLCn keywords         */
	   int      *status) /* return status code                          */

/*
   examine all the GRPIDn and GRPLCn keywords in the member HDUs header
   and remove the member from the grouping tables referenced; This
   effectively "unlinks" the member from all of its groups. The rmopt 
   specifies if the GRPIDn/GRPLCn keywords are to be removed from the
   member HDUs header after the unlinking.
*/

{
  int memberPosition = 0;
  int iomode;

  long index;
  long ngroups      = 0;
  long memberExtver = 0;
  long memberID     = 0;

  char mbrLocation1[FLEN_FILENAME];
  char mbrLocation2[FLEN_FILENAME];
  char memberHDUtype[FLEN_VALUE];
  char memberExtname[FLEN_VALUE];
  char keyword[FLEN_KEYWORD];
  char card[FLEN_CARD];

  fitsfile *gfptr = NULL;


  if(*status != 0) return(*status);

  do
    {
      /* 
	 determine location parameters of the member HDU; note that
	 default values are supplied if the expected keywords are not
	 found
      */

      *status = fits_read_key_str(mfptr,"XTENSION",memberHDUtype,card,status);

      if(*status == KEY_NO_EXIST) 
	{
	  strcpy(memberHDUtype,"PRIMARY");
	  *status = 0;
	}
      prepare_keyvalue(memberHDUtype);

      *status = fits_read_key_lng(mfptr,"EXTVER",&memberExtver,card,status);

      if(*status == KEY_NO_EXIST) 
	{
	  memberExtver = 1;
	  *status      = 0;
	}

      *status = fits_read_key_str(mfptr,"EXTNAME",memberExtname,card,status);

      if(*status == KEY_NO_EXIST) 
	{
	  memberExtname[0] = 0;
	  *status          = 0;
	}
      prepare_keyvalue(memberExtname);

      fits_get_hdu_num(mfptr,&memberPosition);

      *status = fits_get_url(mfptr,mbrLocation1,mbrLocation2,NULL,NULL,
			     NULL,status);

      if(*status != 0) continue;

      /*
	 open each grouping table linked to this HDU and remove the member 
	 from the grouping tables
      */

      *status = fits_get_num_groups(mfptr,&ngroups,status);

      /* loop over each group linked to the member HDU */

      for(index = 1; index <= ngroups && *status == 0; ++index)
	{
	  /* open the (index)th group linked to the member HDU */ 

	  *status = fits_open_group(mfptr,index,&gfptr,status);

	  /* if the group could not be opened then just skip it */

	  if(*status != 0)
	    {
	      *status = 0;
	      snprintf(card,FLEN_CARD,"Cannot open the %dth group table (ffgmul)",
		      (int)index);
	      ffpmsg(card);
	      continue;
	    }

	  /*
	    make sure the grouping table can be modified before proceeding
	  */
	  
	  fits_file_mode(gfptr,&iomode,status);

	  if(iomode != READWRITE)
	    {
	      snprintf(card,FLEN_CARD,"The %dth group cannot be modified (ffgtam)",
		      (int)index);
	      ffpmsg(card);
	      continue;
	    }

	  /* 
	     try to find the member's row within the grouping table; first 
	     try using the member HDU file's "real" URL string then try
	     using its originally opened URL string if either string exist
	   */
	     
	  memberID = 0;
 
	  if(strlen(mbrLocation1) != 0)
	    {
	      *status = ffgmf(gfptr,memberHDUtype,memberExtname,memberExtver,
			      memberPosition,mbrLocation1,&memberID,status);
	    }

	  if(*status == MEMBER_NOT_FOUND && strlen(mbrLocation2) != 0)
	    {
	      *status = 0;
	      *status = ffgmf(gfptr,memberHDUtype,memberExtname,memberExtver,
			      memberPosition,mbrLocation2,&memberID,status);
	    }

	  /* if the member was found then delete it from the grouping table */

	  if(*status == 0)
	    *status = fits_delete_rows(gfptr,memberID,1,status);

	  /*
	     continue the loop over all member groups even if an error
	     was generated
	  */

	  if(*status == MEMBER_NOT_FOUND)
	    {
	      ffpmsg("cannot locate member's entry in group table (ffgmul)");
	    }
	  *status = 0;

	  /*
	     close the file pointed to by gfptr if it is non NULL to
	     prepare for the next loop iterration
	  */

	  if(gfptr != NULL)
	    {
	      fits_close_file(gfptr,status);
	      gfptr = NULL;
	    }
	}

      if(*status != 0) continue;

      /*
	 if rmopt is non-zero then find and delete the GRPIDn/GRPLCn 
	 keywords from the member HDU header
      */

      if(rmopt != 0)
	{
	  fits_file_mode(mfptr,&iomode,status);

	  if(iomode == READONLY)
	    {
	      ffpmsg("Cannot modify member HDU, opened READONLY (ffgmul)");
	      continue;
	    }

	  /* delete all the GRPIDn/GRPLCn keywords */

	  for(index = 1; index <= ngroups && *status == 0; ++index)
	    {
	      snprintf(keyword,FLEN_KEYWORD,"GRPID%d",(int)index);
	      fits_delete_key(mfptr,keyword,status);
	      
	      snprintf(keyword,FLEN_KEYWORD,"GRPLC%d",(int)index);
	      fits_delete_key(mfptr,keyword,status);

	      if(*status == KEY_NO_EXIST) *status = 0;
	    }
	}
    }while(0);

  /* make sure the gfptr has been closed */

  if(gfptr != NULL)
    { 
      fits_close_file(gfptr,status);
    }

return(*status);
}

/*--------------------------------------------------------------------------*/
int ffgmf(fitsfile *gfptr, /* pointer to grouping table HDU to search       */
	   char *xtension,  /* XTENSION value for member HDU                */
	   char *extname,   /* EXTNAME value for member HDU                 */
	   int   extver,    /* EXTVER value for member HDU                  */
	   int   position,  /* HDU position value for member HDU            */
	   char *location,  /* FITS file location value for member HDU      */
	   long *member,    /* member HDU ID within group table (if found)  */
	   int  *status)    /* return status code                           */

/*
   try to find the entry for the member HDU defined by the xtension, extname,
   extver, position, and location parameters within the grouping table
   pointed to by gfptr. If the member HDU is found then its ID (row number)
   within the grouping table is returned in the member variable; if not
   found then member is returned with a value of 0 and the status return
   code will be set to MEMBER_NOT_FOUND.

   Note that the member HDU postion information is used to obtain a member
   match only if the grouping table type is GT_ID_POS_URI or GT_ID_POS. This
   is because the position information can become invalid much more
   easily then the reference information for a group member.
*/

{
  int xtensionCol,extnameCol,extverCol,positionCol,locationCol,uriCol;
  int mposition = 0;
  int grptype;
  int dummy;
  int i;

  long nmembers = 0;
  long mextver  = 0;
 
  char  charBuff1[FLEN_FILENAME];
  char  charBuff2[FLEN_FILENAME];
  char  tmpLocation[FLEN_FILENAME];
  char  mbrLocation1[FLEN_FILENAME];
  char  mbrLocation2[FLEN_FILENAME];
  char  mbrLocation3[FLEN_FILENAME];
  char  grpLocation1[FLEN_FILENAME];
  char  grpLocation2[FLEN_FILENAME];
  char  cwd[FLEN_FILENAME];

  char  nstr[] = {'\0'};
  char *tmpPtr[2];

  if(*status != 0) return(*status);

  *member = 0;

  tmpPtr[0] = charBuff1;
  tmpPtr[1] = charBuff2;


  if(*status != 0) return(*status);

  /*
    if the passed LOCATION value is not an absolute URL then turn it
    into an absolute path
  */

  if(location == NULL)
    {
      *tmpLocation = 0;
    }

  else if(*location == 0)
    {
      *tmpLocation = 0;
    }

  else if(!fits_is_url_absolute(location))
    {
      fits_path2url(location,tmpLocation,status);

      if(*tmpLocation != '/')
	{
	  fits_get_cwd(cwd,status);
	  strcat(cwd,"/");
	  strcat(cwd,tmpLocation);
	  fits_clean_url(cwd,tmpLocation,status);
	}
    }

  else
    strcpy(tmpLocation,location);

  /*
     retrieve the Grouping Convention reserved column positions within
     the grouping table
  */

  *status = ffgtgc(gfptr,&xtensionCol,&extnameCol,&extverCol,&positionCol,
		   &locationCol,&uriCol,&grptype,status);

  /* retrieve the number of group members */

  *status = fits_get_num_members(gfptr,&nmembers,status);
	      
  /* 
     loop over all grouping table rows until the member HDU is found 
  */

  for(i = 1; i <= nmembers && *member == 0 && *status == 0; ++i)
    {
      if(xtensionCol != 0)
	{
	  fits_read_col_str(gfptr,xtensionCol,i,1,1,nstr,tmpPtr,&dummy,status);
	  if(fits_strcasecmp(tmpPtr[0],xtension) != 0) continue;
	}
	  
      if(extnameCol  != 0)
	{
	  fits_read_col_str(gfptr,extnameCol,i,1,1,nstr,tmpPtr,&dummy,status);
	  if(fits_strcasecmp(tmpPtr[0],extname) != 0) continue;
	}
	  
      if(extverCol   != 0)
	{
	  fits_read_col_lng(gfptr,extverCol,i,1,1,0,
			    (long*)&mextver,&dummy,status);
	  if(extver != mextver) continue;
	}
      
      /* note we only use postionCol if we have to */

      if(positionCol != 0 && 
	            (grptype == GT_ID_POS || grptype == GT_ID_POS_URI))
	{
	  fits_read_col_int(gfptr,positionCol,i,1,1,0,
			    &mposition,&dummy,status);
	  if(position != mposition) continue;
	}
      
      /*
	if no location string was passed to the function then assume that
	the calling application does not wish to use it as a comparision
	critera ==> if we got this far then we have a match
      */

      if(location == NULL)
	{
	  ffpmsg("NULL Location string given ==> ingore location (ffgmf)");
	  *member = i;
	  continue;
	}

      /*
	if the grouping table MEMBER_LOCATION column exists then read the
	location URL for the member, else set the location string to
	a zero-length string for subsequent comparisions
      */

      if(locationCol != 0)
	{
	  fits_read_col_str(gfptr,locationCol,i,1,1,nstr,tmpPtr,&dummy,status);
	  strcpy(mbrLocation1,tmpPtr[0]);
	  *mbrLocation2 = 0;
	}
      else
	*mbrLocation1 = 0;

      /* 
	 if the member location string from the grouping table is zero 
	 length (either implicitly or explicitly) then assume that the 
	 member HDU is in the same file as the grouping table HDU; retrieve
	 the possible URL values of the grouping table HDU file 
       */

      if(*mbrLocation1 == 0)
	{
	  /* retrieve the possible URLs of the grouping table file */
	  *status = fits_get_url(gfptr,mbrLocation1,mbrLocation2,NULL,NULL,
				 NULL,status);

	  /* if non-NULL, make sure the first URL is absolute or a full path */
	  if(*mbrLocation1 != 0 && !fits_is_url_absolute(mbrLocation1) &&
	     *mbrLocation1 != '/')
	    {
	      fits_get_cwd(cwd,status);
	      strcat(cwd,"/");
	      strcat(cwd,mbrLocation1);
	      fits_clean_url(cwd,mbrLocation1,status);
	    }

	  /* if non-NULL, make sure the first URL is absolute or a full path */
	  if(*mbrLocation2 != 0 && !fits_is_url_absolute(mbrLocation2) &&
	     *mbrLocation2 != '/')
	    {
	      fits_get_cwd(cwd,status);
	      strcat(cwd,"/");
	      strcat(cwd,mbrLocation2);
	      fits_clean_url(cwd,mbrLocation2,status);
	    }
	}

      /*
	if the member location was specified, then make sure that it is
	either an absolute URL or specifies a full path
      */

      else if(!fits_is_url_absolute(mbrLocation1) && *mbrLocation1 != '/')
	{
	  strcpy(mbrLocation2,mbrLocation1);

	  /* get the possible URLs for the grouping table file */
	  *status = fits_get_url(gfptr,grpLocation1,grpLocation2,NULL,NULL,
				 NULL,status);
	  
	  if(*grpLocation1 != 0)
	    {
	      /* make sure the first grouping table URL is absolute */
	      if(!fits_is_url_absolute(grpLocation1) && *grpLocation1 != '/')
		{
		  fits_get_cwd(cwd,status);
		  strcat(cwd,"/");
		  strcat(cwd,grpLocation1);
		  fits_clean_url(cwd,grpLocation1,status);
		}
	      
	      /* create an absoute URL for the member */

	      fits_relurl2url(grpLocation1,mbrLocation1,mbrLocation3,status);
	      
	      /* 
		 if URL construction succeeded then copy it to the
		 first location string; else set the location string to 
		 empty
	      */

	      if(*status == 0)
		{
		  strcpy(mbrLocation1,mbrLocation3);
		}

	      else if(*status == URL_PARSE_ERROR)
		{
		  *status       = 0;
		  *mbrLocation1 = 0;
		}
	    }
	  else
	    *mbrLocation1 = 0;

	  if(*grpLocation2 != 0)
	    {
	      /* make sure the second grouping table URL is absolute */
	      if(!fits_is_url_absolute(grpLocation2) && *grpLocation2 != '/')
		{
		  fits_get_cwd(cwd,status);
		  strcat(cwd,"/");
		  strcat(cwd,grpLocation2);
		  fits_clean_url(cwd,grpLocation2,status);
		}
	      
	      /* create an absolute URL for the member */

	      fits_relurl2url(grpLocation2,mbrLocation2,mbrLocation3,status);
	      
	      /* 
		 if URL construction succeeded then copy it to the
		 second location string; else set the location string to 
		 empty
	      */

	      if(*status == 0)
		{
		  strcpy(mbrLocation2,mbrLocation3);
		}

	      else if(*status == URL_PARSE_ERROR)
		{
		  *status       = 0;
		  *mbrLocation2 = 0;
		}
	    }
	  else
	    *mbrLocation2 = 0;
	}

      /*
	compare the passed member HDU file location string with the
	(possibly two) member location strings to see if there is a match
       */

      if(strcmp(mbrLocation1,tmpLocation) != 0 && 
	 strcmp(mbrLocation2,tmpLocation) != 0   ) continue;
  
      /* if we made it this far then a match to the member HDU was found */
      
      *member = i;
    }

  /* if a match was not found then set the return status code */

  if(*member == 0 && *status == 0) 
    {
      *status = MEMBER_NOT_FOUND;
      ffpmsg("Cannot find specified member HDU (ffgmf)");
    }

  return(*status);
}

/*--------------------------------------------------------------------------
                        Recursive Group Functions
  --------------------------------------------------------------------------*/
int ffgtrmr(fitsfile   *gfptr,  /* FITS file pointer to group               */
	    HDUtracker *HDU,    /* list of processed HDUs                   */
	    int        *status) /* return status code                       */
	    
/*
  recursively remove a grouping table and all its members. Each member of
  the grouping table pointed to by gfptr it processed. If the member is itself
  a grouping table then ffgtrmr() is recursively called to process all
  of its members. The HDUtracker struct *HDU is used to make sure a member
  is not processed twice, thus avoiding an infinite loop (e.g., a grouping
  table contains itself as a member).
*/

{
  int i;
  int hdutype;

  long nmembers = 0;

  char keyvalue[FLEN_VALUE];
  char comment[FLEN_COMMENT];
  
  fitsfile *mfptr = NULL;


  if(*status != 0) return(*status);

  /* get the number of members contained by this grouping table */

  *status = fits_get_num_members(gfptr,&nmembers,status);

  /* loop over all group members and delete them */

  for(i = nmembers; i > 0 && *status == 0; --i)
    {
      /* open the member HDU */

      *status = fits_open_member(gfptr,i,&mfptr,status);

      /* if the member cannot be opened then just skip it and continue */

      if(*status == MEMBER_NOT_FOUND) 
	{
	  *status = 0;
	  continue;
	}

      /* Any other error is a reason to abort */
      
      if(*status != 0) continue;

      /* add the member HDU to the HDUtracker struct */

      *status = fftsad(mfptr,HDU,NULL,NULL);

      /* status == HDU_ALREADY_TRACKED ==> HDU has already been processed */

      if(*status == HDU_ALREADY_TRACKED) 
	{
	  *status = 0;
	  fits_close_file(mfptr,status);
	  continue;
	}
      else if(*status != 0) continue;

      /* determine if the member HDU is itself a grouping table */

      *status = fits_read_key_str(mfptr,"EXTNAME",keyvalue,comment,status);

      /* if no EXTNAME is found then the HDU cannot be a grouping table */ 

      if(*status == KEY_NO_EXIST) 
	{
	  *status     = 0;
	  keyvalue[0] = 0;
	}
      prepare_keyvalue(keyvalue);

      /* Any other error is a reason to abort */
      
      if(*status != 0) continue;

      /* 
	 if the EXTNAME == GROUPING then the member is a grouping table 
	 and we must call ffgtrmr() to process its members
      */

      if(fits_strcasecmp(keyvalue,"GROUPING") == 0)
	  *status = ffgtrmr(mfptr,HDU,status);  

      /* 
	 unlink all the grouping tables that contain this HDU as a member 
	 and then delete the HDU (if not a PHDU)
      */

      if(fits_get_hdu_num(mfptr,&hdutype) == 1)
	      *status = ffgmul(mfptr,1,status);
      else
	  {
	      *status = ffgmul(mfptr,0,status);
	      *status = fits_delete_hdu(mfptr,&hdutype,status);
	  }

      /* close the fitsfile pointer */

      fits_close_file(mfptr,status);
    }

  return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgtcpr(fitsfile   *infptr,  /* input FITS file pointer                 */
	    fitsfile   *outfptr, /* output FITS file pointer                */
	    int         cpopt,   /* code specifying copy options:
				    OPT_GCP_GPT (0) ==> cp only grouping table
				    OPT_GCP_ALL (2) ==> recusrively copy 
				    members and their members (if groups)   */
	    HDUtracker *HDU,     /* list of already copied HDUs             */
	    int        *status)  /* return status code                      */

/*
  copy a Group to a new FITS file. If the cpopt parameter is set to 
  OPT_GCP_GPT (copy grouping table only) then the existing members have their 
  GRPIDn and GRPLCn keywords updated to reflect the existance of the new group,
  since they now belong to another group. If cpopt is set to OPT_GCP_ALL 
  (copy grouping table and members recursively) then the original members are 
  not updated; the new grouping table is modified to include only the copied 
  member HDUs and not the original members.

  Note that this function is recursive. When copt is OPT_GCP_ALL it will call
  itself whenever a member HDU of the current grouping table is itself a
  grouping table (i.e., EXTNAME = 'GROUPING').
*/

{

  int i;
  int nexclude     = 8;
  int hdutype      = 0;
  int groupHDUnum  = 0;
  int numkeys      = 0;
  int keypos       = 0;
  int startSearch  = 0;
  int newPosition  = 0;

  long nmembers    = 0;
  long tfields     = 0;
  long newTfields  = 0;

  char keyword[FLEN_KEYWORD];
  char keyvalue[FLEN_VALUE];
  char card[FLEN_CARD];
  char comment[FLEN_CARD];
  char *tkeyvalue;

  char *includeList[] = {"*"};
  char *excludeList[] = {"EXTNAME","EXTVER","GRPNAME","GRPID#","GRPLC#",
			 "THEAP","TDIM#","T????#"};

  fitsfile *mfptr = NULL;


  if(*status != 0) return(*status);

  do
    {
      /*
	create a new grouping table in the FITS file pointed to by outptr
      */

      *status = fits_get_num_members(infptr,&nmembers,status);

      *status = fits_read_key_str(infptr,"GRPNAME",keyvalue,card,status);

      if(*status == KEY_NO_EXIST)
	{
	  keyvalue[0] = 0;
	  *status     = 0;
	}
      prepare_keyvalue(keyvalue);

      *status = fits_create_group(outfptr,keyvalue,GT_ID_ALL_URI,status);
     
      /* save the new grouping table's HDU position for future use */

      fits_get_hdu_num(outfptr,&groupHDUnum);

      /* update the HDUtracker struct with the grouping table's new position */
      
      *status = fftsud(infptr,HDU,groupHDUnum,NULL);

      /*
	Now populate the copied grouping table depending upon the 
	copy option parameter value
      */

      switch(cpopt)
	{

	  /*
	    for the "copy grouping table only" option we only have to
	    add the members of the original grouping table to the new
	    grouping table
	  */

	case OPT_GCP_GPT:

	  for(i = 1; i <= nmembers && *status == 0; ++i)
	    {
	      *status = fits_open_member(infptr,i,&mfptr,status);
	      *status = fits_add_group_member(outfptr,mfptr,0,status);

	      fits_close_file(mfptr,status);
	      mfptr = NULL;
	    }

	  break;

	case OPT_GCP_ALL:
      
	  /*
	    for the "copy the entire group" option
 	  */

	  /* loop over all the grouping table members */

	  for(i = 1; i <= nmembers && *status == 0; ++i)
	    {
	      /* open the ith member */

	      *status = fits_open_member(infptr,i,&mfptr,status);

	      if(*status != 0) continue;

	      /* add it to the HDUtracker struct */

	      *status = fftsad(mfptr,HDU,&newPosition,NULL);

	      /* if already copied then just add the member to the group */

	      if(*status == HDU_ALREADY_TRACKED)
		{
		  *status = 0;
		  *status = fits_add_group_member(outfptr,NULL,newPosition,
						  status);
		  fits_close_file(mfptr,status);
                  mfptr = NULL;
		  continue;
		}
	      else if(*status != 0) continue;

	      /* see if the member is a grouping table */

	      *status = fits_read_key_str(mfptr,"EXTNAME",keyvalue,card,
					  status);

	      if(*status == KEY_NO_EXIST)
		{
		  keyvalue[0] = 0;
		  *status     = 0;
		}
	      prepare_keyvalue(keyvalue);

	      /*
		if the member is a grouping table then copy it and all of
		its members using ffgtcpr(), else copy it using
		fits_copy_member(); the outptr will point to the newly
		copied member upon return from both functions
	      */

	      if(fits_strcasecmp(keyvalue,"GROUPING") == 0)
		*status = ffgtcpr(mfptr,outfptr,OPT_GCP_ALL,HDU,status);
	      else
		*status = fits_copy_member(infptr,outfptr,i,OPT_MCP_NADD,
					   status);

	      /* retrieve the position of the newly copied member */

	      fits_get_hdu_num(outfptr,&newPosition);

	      /* update the HDUtracker struct with member's new position */
	      
	      if(fits_strcasecmp(keyvalue,"GROUPING") != 0)
		*status = fftsud(mfptr,HDU,newPosition,NULL);

	      /* move the outfptr back to the copied grouping table HDU */

	      *status = fits_movabs_hdu(outfptr,groupHDUnum,&hdutype,status);

	      /* add the copied member HDU to the copied grouping table */

	      *status = fits_add_group_member(outfptr,NULL,newPosition,status);

	      /* close the mfptr pointer */

	      fits_close_file(mfptr,status);
	      mfptr = NULL;
	    }

	  break;

	default:
	  
	  *status = BAD_OPTION;
	  ffpmsg("Invalid value specified for cmopt parameter (ffgtcpr)");
	  break;
	}

      if(*status != 0) continue; 

      /* 
	 reposition the outfptr to the grouping table so that the grouping
	 table is the CHDU upon return to the calling function
      */

      fits_movabs_hdu(outfptr,groupHDUnum,&hdutype,status);

      /*
	 copy all auxiliary keyword records from the original grouping table
	 to the new grouping table; they are copied in their original order
	 and inserted just before the TTYPE1 keyword record
      */

      *status = fits_read_card(outfptr,"TTYPE1",card,status);
      *status = fits_get_hdrpos(outfptr,&numkeys,&keypos,status);
      --keypos;

      startSearch = 8;

      while(*status == 0)
	{
	  ffgrec(infptr,startSearch,card,status);

	  *status = fits_find_nextkey(infptr,includeList,1,excludeList,
				      nexclude,card,status);

	  *status = fits_get_hdrpos(infptr,&numkeys,&startSearch,status);

	  --startSearch;
	  /* SPR 1738 */
	  if (strncmp(card,"GRPLC",5)) {
	    /* Not going to be a long string so we're ok */
	    *status = fits_insert_record(outfptr,keypos,card,status);
	  } else {
	    /* We could have a long string */
	    *status = fits_read_record(infptr,startSearch,card,status);
	    card[9] = '\0';
	    *status = fits_read_key_longstr(infptr,card,&tkeyvalue,comment,
					    status);
	    if (0 == *status) {
	      fits_insert_key_longstr(outfptr,card,tkeyvalue,comment,status);
	      fits_write_key_longwarn(outfptr,status);
	      free(tkeyvalue);
	    }
	  }
	  
	  ++keypos;
	}
      
	  
      if(*status == KEY_NO_EXIST) 
	*status = 0;
      else if(*status != 0) continue;

      /*
	 search all the columns of the original grouping table and copy
	 those to the new grouping table that were not part of the grouping
	 convention. Note that is legal to have additional columns in a
	 grouping table. Also note that the order of the columns may
	 not be the same in the original and copied grouping table.
      */

      /* retrieve the number of columns in the original and new group tables */

      *status = fits_read_key_lng(infptr,"TFIELDS",&tfields,card,status);
      *status = fits_read_key_lng(outfptr,"TFIELDS",&newTfields,card,status);

      for(i = 1; i <= tfields; ++i)
	{
	  snprintf(keyword,FLEN_KEYWORD,"TTYPE%d",i);
	  *status = fits_read_key_str(infptr,keyword,keyvalue,card,status);
	  
	  if(*status == KEY_NO_EXIST)
	    {
	      *status = 0;
              keyvalue[0] = 0;
	    }
	  prepare_keyvalue(keyvalue);

	  if(fits_strcasecmp(keyvalue,"MEMBER_XTENSION") != 0 &&
	     fits_strcasecmp(keyvalue,"MEMBER_NAME")     != 0 &&
	     fits_strcasecmp(keyvalue,"MEMBER_VERSION")  != 0 &&
	     fits_strcasecmp(keyvalue,"MEMBER_POSITION") != 0 &&
	     fits_strcasecmp(keyvalue,"MEMBER_LOCATION") != 0 &&
	     fits_strcasecmp(keyvalue,"MEMBER_URI_TYPE") != 0   )
	    {
 
	      /* SPR 3956, add at the end of the table */
	      *status = fits_copy_col(infptr,outfptr,i,newTfields+1,1,status);
	      ++newTfields;
	    }
	}

    }while(0);

  if(mfptr != NULL) 
    {
      fits_close_file(mfptr,status);
    }

  return(*status);
}

/*--------------------------------------------------------------------------
                HDUtracker struct manipulation functions
  --------------------------------------------------------------------------*/
int fftsad(fitsfile   *mfptr,       /* pointer to an member HDU             */
	   HDUtracker *HDU,         /* pointer to an HDU tracker struct     */
	   int        *newPosition, /* new HDU position of the member HDU   */
	   char       *newFileName) /* file containing member HDU           */

/*
  add an HDU to the HDUtracker struct pointed to by HDU. The HDU is only 
  added if it does not already reside in the HDUtracker. If it already
  resides in the HDUtracker then the new HDU postion and file name are
  returned in  newPosition and newFileName (if != NULL)
*/

{
  int i;
  int hdunum;
  int status = 0;

  char filename1[FLEN_FILENAME];
  char filename2[FLEN_FILENAME];

  do
    {
      /* retrieve the HDU's position within the FITS file */

      fits_get_hdu_num(mfptr,&hdunum);
      
      /* retrieve the HDU's file name */
      
      status = fits_file_name(mfptr,filename1,&status);
      
      /* parse the file name and construct the "standard" URL for it */
      
      status = ffrtnm(filename1,filename2,&status);
      
      /* 
	 examine all the existing HDUs in the HDUtracker an see if this HDU
	 has already been registered
      */

      for(i = 0; 
       i < HDU->nHDU &&  !(HDU->position[i] == hdunum 
			   && strcmp(HDU->filename[i],filename2) == 0);
	  ++i);

      if(i != HDU->nHDU) 
	{
	  status = HDU_ALREADY_TRACKED;
	  if(newPosition != NULL) *newPosition = HDU->newPosition[i];
	  if(newFileName != NULL) strcpy(newFileName,HDU->newFilename[i]);
	  continue;
	}

      if(HDU->nHDU == MAX_HDU_TRACKER) 
	{
	  status = TOO_MANY_HDUS_TRACKED;
	  continue;
	}

      HDU->filename[i] = (char*) malloc(FLEN_FILENAME * sizeof(char));

      if(HDU->filename[i] == NULL)
	{
	  status = MEMORY_ALLOCATION;
	  continue;
	}

      HDU->newFilename[i] = (char*) malloc(FLEN_FILENAME * sizeof(char));

      if(HDU->newFilename[i] == NULL)
	{
	  status = MEMORY_ALLOCATION;
	  free(HDU->filename[i]);
	  continue;
	}

      HDU->position[i]    = hdunum;
      HDU->newPosition[i] = hdunum;

      strcpy(HDU->filename[i],filename2);
      strcpy(HDU->newFilename[i],filename2);
 
       ++(HDU->nHDU);

    }while(0);

  return(status);
}
/*--------------------------------------------------------------------------*/
int fftsud(fitsfile   *mfptr,       /* pointer to an member HDU             */
	   HDUtracker *HDU,         /* pointer to an HDU tracker struct     */
	   int         newPosition, /* new HDU position of the member HDU   */
	   char       *newFileName) /* file containing member HDU           */

/*
  update the HDU information in the HDUtracker struct pointed to by HDU. The 
  HDU to update is pointed to by mfptr. If non-zero, the value of newPosition
  is used to update the HDU->newPosition[] value for the mfptr, and if
  non-NULL the newFileName value is used to update the HDU->newFilename[]
  value for mfptr.
*/

{
  int i;
  int hdunum;
  int status = 0;

  char filename1[FLEN_FILENAME];
  char filename2[FLEN_FILENAME];


  /* retrieve the HDU's position within the FITS file */
  
  fits_get_hdu_num(mfptr,&hdunum);
  
  /* retrieve the HDU's file name */
  
  status = fits_file_name(mfptr,filename1,&status);
  
  /* parse the file name and construct the "standard" URL for it */
      
  status = ffrtnm(filename1,filename2,&status);

  /* 
     examine all the existing HDUs in the HDUtracker an see if this HDU
     has already been registered
  */

  for(i = 0; i < HDU->nHDU && 
      !(HDU->position[i] == hdunum && strcmp(HDU->filename[i],filename2) == 0);
      ++i);

  /* if previously registered then change newPosition and newFileName */

  if(i != HDU->nHDU) 
    {
      if(newPosition  != 0) HDU->newPosition[i] = newPosition;
      if(newFileName  != NULL) 
	{
	  strcpy(HDU->newFilename[i],newFileName);
	}
    }
  else
    status = MEMBER_NOT_FOUND;
 
  return(status);
}

/*---------------------------------------------------------------------------*/

void prepare_keyvalue(char *keyvalue) /* string containing keyword value     */

/*
  strip off all single quote characters "'" and blank spaces from a keyword
  value retrieved via fits_read_key*() routines

  this is necessary so that a standard comparision of keyword values may
  be made
*/

{

  int i;
  int length;

  /*
    strip off any leading or trailing single quotes (`) and (') from
    the keyword value
  */

  length = strlen(keyvalue) - 1;

  if(keyvalue[0] == '\'' && keyvalue[length] == '\'')
    {
      for(i = 0; i < length - 1; ++i) keyvalue[i] = keyvalue[i+1];
      keyvalue[length-1] = 0;
    }
  
  /*
    strip off any trailing blanks from the keyword value; note that if the
    keyvalue consists of nothing but blanks then no blanks are stripped
  */

  length = strlen(keyvalue) - 1;

  for(i = 0; i < length && keyvalue[i] == ' '; ++i);

  if(i != length)
    {
      for(i = length; i >= 0 && keyvalue[i] == ' '; --i) keyvalue[i] = '\0';
    }
}

/*---------------------------------------------------------------------------
        Host dependent directory path to/from URL functions
  --------------------------------------------------------------------------*/
int fits_path2url(char *inpath,  /* input file path string                  */
		  char *outpath, /* output file path string                 */
		  int  *status)
  /*
     convert a file path into its Unix-style equivelent for URL 
     purposes. Note that this process is platform dependent. This
     function supports Unix, MSDOS/WIN32, VMS and Macintosh platforms. 
     The plaform dependant code is conditionally compiled depending upon
     the setting of the appropriate C preprocessor macros.
   */
{
  char buff[FLEN_FILENAME];

#if defined(WINNT) || defined(__WINNT__)

  /*
    Microsoft Windows NT case. We assume input file paths of the form:

    //disk/path/filename

     All path segments may be null, so that a single file name is the
     simplist case.

     The leading "//" becomes a single "/" if present. If no "//" is present,
     then make sure the resulting URL path is relative, i.e., does not
     begin with a "/". In other words, the only way that an absolute URL
     file path may be generated is if the drive specification is given.
  */

  if(*status > 0) return(*status);

  if(inpath[0] == '/')
    {
      strcpy(buff,inpath+1);
    }
  else
    {
      strcpy(buff,inpath);
    }

#elif defined(MSDOS) || defined(__WIN32__) || defined(WIN32)

  /*
     MSDOS or Microsoft windows/NT case. The assumed form of the
     input path is:

     disk:\path\filename

     All path segments may be null, so that a single file name is the
     simplist case.

     All back-slashes '\' become slashes '/'; if the path starts with a
     string of the form "X:" then it is replaced with "/X/"
  */

  int i,j,k;
  int size;
  if(*status > 0) return(*status);

  for(i = 0, j = 0, size = strlen(inpath), buff[0] = 0; 
                                           i < size; j = strlen(buff))
    {
      switch(inpath[i])
	{

	case ':':

	  /*
	     must be a disk desiginator; add a slash '/' at the start of
	     outpath to designate that the path is absolute, then change
	     the colon ':' to a slash '/'
	   */

	  for(k = j; k >= 0; --k) buff[k+1] = buff[k];
	  buff[0] = '/';
	  strcat(buff,"/");
	  ++i;
	  
	  break;

	case '\\':

	  /* just replace the '\' with a '/' IF its not the first character */

	  if(i != 0 && buff[(j == 0 ? 0 : j-1)] != '/')
	    {
	      buff[j] = '/';
	      buff[j+1] = 0;
	    }

	  ++i;

	  break;

	default:

	  /* copy the character from inpath to buff as is */

	  buff[j]   = inpath[i];
	  buff[j+1] = 0;
	  ++i;

	  break;
	}
    }

#elif defined(VMS) || defined(vms) || defined(__vms)

  /*
     VMS case. Assumed format of the input path is:

     node::disk:[path]filename.ext;version

     Any part of the file path may be missing, so that in the simplist
     case a single file name/extension is given.

     all brackets "[", "]" and dots "." become "/"; dashes "-" become "..", 
     all single colons ":" become ":/", all double colons "::" become
     "FILE://"
   */

  int i,j,k;
  int done;
  int size;

  if(*status > 0) return(*status);
     
  /* see if inpath contains a directory specification */

  if(strchr(inpath,']') == NULL) 
    done = 1;
  else
    done = 0;

  for(i = 0, j = 0, size = strlen(inpath), buff[0] = 0; 
                           i < size && j < FLEN_FILENAME - 8; j = strlen(buff))
    {
      switch(inpath[i])
	{

	case ':':

	  /*
	     must be a logical/symbol separator or (in the case of a double
	     colon "::") machine node separator
	   */

	  if(inpath[i+1] == ':')
	    {
	      /* insert a "FILE://" at the start of buff ==> machine given */

	      for(k = j; k >= 0; --k) buff[k+7] = buff[k];
	      strncpy(buff,"FILE://",7);
	      i += 2;
	    }
	  else if(strstr(buff,"FILE://") == NULL)
	    {
	      /* insert a "/" at the start of buff ==> absolute path */

	      for(k = j; k >= 0; --k) buff[k+1] = buff[k];
	      buff[0] = '/';
	      ++i;
	    }
	  else
	    ++i;

	  /* a colon always ==> path separator */

	  strcat(buff,"/");

	  break;
  
	case ']':

	  /* end of directory spec, file name spec begins after this */

	  done = 1;

	  buff[j]   = '/';
	  buff[j+1] = 0;
	  ++i;

	  break;

	case '[':

	  /* 
	     begin directory specification; add a '/' only if the last char 
	     is not '/' 
	  */

	  if(i != 0 && buff[(j == 0 ? 0 : j-1)] != '/')
	    {
	      buff[j]   = '/';
	      buff[j+1] = 0;
	    }

	  ++i;

	  break;

	case '.':

	  /* 
	     directory segment separator or file name/extension separator;
	     we decide which by looking at the value of done
	  */

	  if(!done)
	    {
	    /* must be a directory segment separator */
	      if(inpath[i-1] == '[')
		{
		  strcat(buff,"./");
		  ++j;
		}
	      else
		buff[j] = '/';
	    }
	  else
	    /* must be a filename/extension separator */
	    buff[j] = '.';

	  buff[j+1] = 0;

	  ++i;

	  break;

	case '-':

	  /* 
	     a dash is the same as ".." in Unix speak, but lets make sure
	     that its not part of the file name first!
	   */

	  if(!done)
	    /* must be part of the directory path specification */
	    strcat(buff,"..");
	  else
	    {
	      /* the dash is part of the filename, so just copy it as is */
	      buff[j] = '-';
	      buff[j+1] = 0;
	    }

	  ++i;

	  break;

	default:

	  /* nothing special, just copy the character as is */

	  buff[j]   = inpath[i];
	  buff[j+1] = 0;

	  ++i;

	  break;

	}
    }

  if(j > FLEN_FILENAME - 8)
    {
      *status = URL_PARSE_ERROR;
      ffpmsg("resulting path to URL conversion too big (fits_path2url)");
    }

#elif defined(macintosh)

  /*
     MacOS case. The assumed form of the input path is:

     disk:path:filename

     It is assumed that all paths are absolute with disk and path specified,
     unless no colons ":" are supplied with the string ==> a single file name
     only. All colons ":" become slashes "/", and if one or more colon is 
     encountered then the path is specified as absolute.
  */

  int i,j,k;
  int firstColon;
  int size;

  if(*status > 0) return(*status);

  for(i = 0, j = 0, firstColon = 1, size = strlen(inpath), buff[0] = 0; 
                                                   i < size; j = strlen(buff))
    {
      switch(inpath[i])
	{

	case ':':

	  /*
	     colons imply path separators. If its the first colon encountered
	     then assume that its the disk designator and add a slash to the
	     beginning of the buff string
	   */
	  
	  if(firstColon)
	    {
	      firstColon = 0;

	      for(k = j; k >= 0; --k) buff[k+1] = buff[k];
	      buff[0] = '/';
	    }

	  /* all colons become slashes */

	  strcat(buff,"/");

	  ++i;
	  
	  break;

	default:

	  /* copy the character from inpath to buff as is */

	  buff[j]   = inpath[i];
	  buff[j+1] = 0;

	  ++i;

	  break;
	}
    }

#else 

  /*
     Default Unix case.

     Nothing special to do here except to remove the double or more // and 
     replace them with single /
   */

  int ii = 0;
  int jj = 0;

  if(*status > 0) return(*status);

  while (inpath[ii]) {
      if (inpath[ii] == '/' && inpath[ii+1] == '/') {
	  /* do nothing */
      } else {
	  buff[jj] = inpath[ii];
	  jj++;
      }
      ii++;
  }
  buff[jj] = '\0';
  /* printf("buff is %s\ninpath is %s\n",buff,inpath); */
  /* strcpy(buff,inpath); */

#endif

  /*
    encode all "unsafe" and "reserved" URL characters
  */

  *status = fits_encode_url(buff,outpath,status);

  return(*status);
}

/*---------------------------------------------------------------------------*/
int fits_url2path(char *inpath,  /* input file path string  */
		  char *outpath, /* output file path string */
		  int  *status)
  /*
     convert a Unix-style URL into a platform dependent directory path. 
     Note that this process is platform dependent. This
     function supports Unix, MSDOS/WIN32, VMS and Macintosh platforms. Each
     platform dependent code segment is conditionally compiled depending 
     upon the setting of the appropriate C preprocesser macros.
   */
{
  char buff[FLEN_FILENAME];
  int absolute;

#if defined(MSDOS) || defined(__WIN32__) || defined(WIN32)
  char *tmpStr, *saveptr;
#elif defined(VMS) || defined(vms) || defined(__vms)
  int i;
  char *tmpStr, *saveptr;
#elif defined(macintosh)
  char *tmpStr, *saveptr;
#endif

  if(*status != 0) return(*status);

  /*
    make a copy of the inpath so that we can manipulate it
  */

  strcpy(buff,inpath);

  /*
    convert any encoded characters to their unencoded values
  */

  *status = fits_unencode_url(inpath,buff,status);

  /*
    see if the URL is given as absolute w.r.t. the "local" file system
  */

  if(buff[0] == '/') 
    absolute = 1;
  else
    absolute = 0;

#if defined(WINNT) || defined(__WINNT__)

  /*
    Microsoft Windows NT case. We create output paths of the form

    //disk/path/filename

     All path segments but the last may be null, so that a single file name 
     is the simplist case.     
  */

  if(absolute)
    {
      strcpy(outpath,"/");
      strcat(outpath,buff);
    }
  else
    {
      strcpy(outpath,buff);
    }

#elif defined(MSDOS) || defined(__WIN32__) || defined(WIN32)

  /*
     MSDOS or Microsoft windows/NT case. The output path will be of the
     form

     disk:\path\filename

     All path segments but the last may be null, so that a single file name 
     is the simplist case.
  */

  /*
    separate the URL into tokens at each slash '/' and process until
    all tokens have been examined
  */

  for(tmpStr = ffstrtok(buff,"/",&saveptr), outpath[0] = 0;
                                 tmpStr != NULL; tmpStr = ffstrtok(NULL,"/",&saveptr))
    {
      strcat(outpath,tmpStr);

      /* 
	 if the absolute flag is set then process the token as a disk 
	 specification; else just process it as a directory path or filename
      */

      if(absolute)
	{
	  strcat(outpath,":\\");
	  absolute = 0;
	}
      else
	strcat(outpath,"\\");
    }

  /* remove the last "\" from the outpath, it does not belong there */

  outpath[strlen(outpath)-1] = 0;

#elif defined(VMS) || defined(vms) || defined(__vms)

  /*
     VMS case. The output path will be of the form:

     node::disk:[path]filename.ext;version

     Any part of the file path may be missing execpt filename.ext, so that in 
     the simplist case a single file name/extension is given.

     if the path is specified as relative starting with "./" then the first
     part of the VMS path is "[.". If the path is relative and does not start
     with "./" (e.g., "a/b/c") then the VMS path is constructed as
     "[a.b.c]"
   */
     
  /*
    separate the URL into tokens at each slash '/' and process until
    all tokens have been examined
  */

  for(tmpStr = ffstrtok(buff,"/",&saveptr), outpath[0] = 0; 
                                 tmpStr != NULL; tmpStr = ffstrtok(NULL,"/",&saveptr))
    {

      if(fits_strcasecmp(tmpStr,"FILE:") == 0)
	{
	  /* the next token should contain the DECnet machine name */

	  tmpStr = ffstrtok(NULL,"/",&saveptr);
	  if(tmpStr == NULL) continue;

	  strcat(outpath,tmpStr);
	  strcat(outpath,"::");

	  /* set the absolute flag to true for the next token */
	  absolute = 1;
	}

      else if(strcmp(tmpStr,"..") == 0)
	{
	  /* replace all Unix-like ".." with VMS "-" */

	  if(strlen(outpath) == 0) strcat(outpath,"[");
	  strcat(outpath,"-.");
	}

      else if(strcmp(tmpStr,".") == 0 && strlen(outpath) == 0)
	{
	  /*
	    must indicate a relative path specifier
	  */

	  strcat(outpath,"[.");
	}
  
      else if(strchr(tmpStr,'.') != NULL)
	{
	  /* 
	     must be up to the file name; turn the last "." path separator
	     into a "]" and then add the file name to the outpath
	  */
	  
	  i = strlen(outpath);
	  if(i > 0 && outpath[i-1] == '.') outpath[i-1] = ']';

	  strcat(outpath,tmpStr);
	}

      else
	{
	  /*
	    process the token as a a directory path segement
	  */

	  if(absolute)
	    {
	      /* treat the token as a disk specifier */
	      absolute = 0;
	      strcat(outpath,tmpStr);
	      strcat(outpath,":[");
	    }
	  else if(strlen(outpath) == 0)
	    {
	      /* treat the token as the first directory path specifier */
	      strcat(outpath,"[");
	      strcat(outpath,tmpStr);
	      strcat(outpath,".");
	    }
	  else
	    {
	      /* treat the token as an imtermediate path specifier */
	      strcat(outpath,tmpStr);
	      strcat(outpath,".");
	    }
	}
    }

#elif defined(macintosh)

  /*
     MacOS case. The output path will be of the form

     disk:path:filename

     All path segments but the last may be null, so that a single file name 
     is the simplist case.
  */

  /*
    separate the URL into tokens at each slash '/' and process until
    all tokens have been examined
  */

  for(tmpStr = ffstrtok(buff,"/",&saveptr), outpath[0] = 0;
                                 tmpStr != NULL; tmpStr = ffstrtok(NULL,"/",&saveptr))
    {
      strcat(outpath,tmpStr);
      strcat(outpath,":");
    }

  /* remove the last ":" from the outpath, it does not belong there */

  outpath[strlen(outpath)-1] = 0;

#else

  /*
     Default Unix case.

     Nothing special to do here
   */

  strcpy(outpath,buff);

#endif

  return(*status);
}

/****************************************************************************/
int fits_get_cwd(char *cwd,  /* IO current working directory string */
		 int  *status)
  /*
     retrieve the string containing the current working directory absolute
     path in Unix-like URL standard notation. It is assumed that the CWD
     string has a size of at least FLEN_FILENAME.

     Note that this process is platform dependent. This
     function supports Unix, MSDOS/WIN32, VMS and Macintosh platforms. Each
     platform dependent code segment is conditionally compiled depending 
     upon the setting of the appropriate C preprocesser macros.
   */
{

  char buff[FLEN_FILENAME];


  if(*status != 0) return(*status);

#if defined(macintosh)

  /*
     MacOS case. Currently unknown !!!!
  */

  *buff = 0;

#else
  /*
    Good old getcwd() seems to work with all other platforms
  */

  getcwd(buff,FLEN_FILENAME);

#endif

  /*
    convert the cwd string to a URL standard path string
  */

  fits_path2url(buff,cwd,status);

  return(*status);
}

/*---------------------------------------------------------------------------*/
int  fits_get_url(fitsfile *fptr,       /* I ptr to FITS file to evaluate    */
		  char     *realURL,    /* O URL of real FITS file           */
		  char     *startURL,   /* O URL of starting FITS file       */
		  char     *realAccess, /* O true access method of FITS file */
		  char     *startAccess,/* O "official" access of FITS file  */
		  int      *iostate,    /* O can this file be modified?      */
		  int      *status)
/*
  For grouping convention purposes, determine the URL of the FITS file
  associated with the fitsfile pointer fptr. The true access type (file://,
  mem://, shmem://, root://), starting "official" access type, and iostate 
  (0 ==> readonly, 1 ==> readwrite) are also returned.

  It is assumed that the url string has enough room to hold the resulting
  URL, and the the accessType string has enough room to hold the access type.
*/
{
  int i;
  int tmpIOstate = 0;

  char infile[FLEN_FILENAME];
  char outfile[FLEN_FILENAME];
  char tmpStr1[FLEN_FILENAME];
  char tmpStr2[FLEN_FILENAME];
  char tmpStr3[FLEN_FILENAME];
  char tmpStr4[FLEN_FILENAME];
  char *tmpPtr;


  if(*status != 0) return(*status);

  do
    {
      /* 
	 retrieve the member HDU's file name as opened by ffopen() 
	 and parse it into its constitutent pieces; get the currently
	 active driver token too
       */
	  
      *tmpStr1 = *tmpStr2 = *tmpStr3 = *tmpStr4 = 0;

      *status = fits_file_name(fptr,tmpStr1,status);

      *status = ffiurl(tmpStr1,NULL,infile,outfile,NULL,tmpStr2,tmpStr3,
		       tmpStr4,status);

      if((*tmpStr2) || (*tmpStr3) || (*tmpStr4)) tmpIOstate = -1;
 
      *status = ffurlt(fptr,tmpStr3,status);

      strcpy(tmpStr4,tmpStr3);

      *status = ffrtnm(tmpStr1,tmpStr2,status);
      strcpy(tmpStr1,tmpStr2);

      /*
	for grouping convention purposes (only) determine the URL of the
	actual FITS file being used for the given fptr, its true access 
	type (file://, mem://, shmem://, root://) and its iostate (0 ==>
	read only, 1 ==> readwrite)
      */

      /*
	The first set of access types are "simple" in that they do not
	use any redirection to temporary memory or outfiles
       */

      /* standard disk file driver is in use */
      
      if(fits_strcasecmp(tmpStr3,"file://")              == 0)         
	{
	  tmpIOstate = 1;
	  
	  if(strlen(outfile)) strcpy(tmpStr1,outfile);
	  else *tmpStr2 = 0;

	  /*
	    make sure no FILE:// specifier is given in the tmpStr1
	    or tmpStr2 strings; the convention calls for local files
	    to have no access specification
	  */

	  if((tmpPtr = strstr(tmpStr1,"://")) != NULL)
	    {
	      strcpy(infile,tmpPtr+3);
	      strcpy(tmpStr1,infile);
	    }

	  if((tmpPtr = strstr(tmpStr2,"://")) != NULL)
	    {
	      strcpy(infile,tmpPtr+3);
	      strcpy(tmpStr2,infile);
	    }
	}

      /* file stored in conventional memory */
	  
      else if(fits_strcasecmp(tmpStr3,"mem://")          == 0)          
	{
	  if(tmpIOstate < 0)
	    {
	      /* file is a temp mem file only */
	      ffpmsg("cannot make URL from temp MEM:// file (fits_get_url)");
	      *status = URL_PARSE_ERROR;
	    }
	  else
	    {
	      /* file is a "perminate" mem file for this process */
	      tmpIOstate = 1;
	      *tmpStr2 = 0;
	    }
	}

      /* file stored in conventional memory */
 
     else if(fits_strcasecmp(tmpStr3,"memkeep://")      == 0)      
	{
	  strcpy(tmpStr3,"mem://");
	  *tmpStr4 = 0;
	  *tmpStr2 = 0;
	  tmpIOstate = 1;
	}

      /* file residing in shared memory */

      else if(fits_strcasecmp(tmpStr3,"shmem://")        == 0)        
	{
	  *tmpStr4   = 0;
	  *tmpStr2   = 0;
	  tmpIOstate = 1;
	}
      
      /* file accessed via the ROOT network protocol */

      else if(fits_strcasecmp(tmpStr3,"root://")         == 0)         
	{
	  *tmpStr4   = 0;
	  *tmpStr2   = 0;
	  tmpIOstate = 1;
	}
  
      /*
	the next set of access types redirect the contents of the original
	file to an special outfile because the original could not be
	directly modified (i.e., resides on the network, was compressed).
	In these cases the URL string takes on the value of the OUTFILE,
	the access type becomes file://, and the iostate is set to 1 (can
	read/write to the file).
      */

      /* compressed file uncompressed and written to disk */

      else if(fits_strcasecmp(tmpStr3,"compressfile://") == 0) 
	{
	  strcpy(tmpStr1,outfile);
	  strcpy(tmpStr2,infile);
	  strcpy(tmpStr3,"file://");
	  strcpy(tmpStr4,"file://");
	  tmpIOstate = 1;
	}

      /* HTTP accessed file written locally to disk */

      else if(fits_strcasecmp(tmpStr3,"httpfile://")     == 0)     
	{
	  strcpy(tmpStr1,outfile);
	  strcpy(tmpStr3,"file://");
	  strcpy(tmpStr4,"http://");
	  tmpIOstate = 1;
	}
      
      /* FTP accessd file written locally to disk */

      else if(fits_strcasecmp(tmpStr3,"ftpfile://")      == 0)      
	{
	  strcpy(tmpStr1,outfile);
	  strcpy(tmpStr3,"file://");
	  strcpy(tmpStr4,"ftp://");
	  tmpIOstate = 1;
	}
      
      /* file from STDIN written to disk */

      else if(fits_strcasecmp(tmpStr3,"stdinfile://")    == 0)    
	{
	  strcpy(tmpStr1,outfile);
	  strcpy(tmpStr3,"file://");
	  strcpy(tmpStr4,"stdin://");
	  tmpIOstate = 1;
	}

      /* 
	 the following access types use memory resident files as temporary
	 storage; they cannot be modified or be made group members for 
	 grouping conventions purposes, but their original files can be.
	 Thus, their tmpStr3s are reset to mem://, their iostate
	 values are set to 0 (for no-modification), and their URL string
	 values remain set to their original values
       */

      /* compressed disk file uncompressed into memory */

      else if(fits_strcasecmp(tmpStr3,"compress://")     == 0)     
	{
	  *tmpStr1 = 0;
	  strcpy(tmpStr2,infile);
	  strcpy(tmpStr3,"mem://");
	  strcpy(tmpStr4,"file://");
	  tmpIOstate = 0;
	}
      
      /* HTTP accessed file transferred into memory */

      else if(fits_strcasecmp(tmpStr3,"http://")         == 0)         
	{
	  *tmpStr1 = 0;
	  strcpy(tmpStr3,"mem://");
	  strcpy(tmpStr4,"http://");
	  tmpIOstate = 0;
	}
      
      /* HTTP accessed compressed file transferred into memory */

      else if(fits_strcasecmp(tmpStr3,"httpcompress://") == 0) 
	{
	  *tmpStr1 = 0;
	  strcpy(tmpStr3,"mem://");
	  strcpy(tmpStr4,"http://");
	  tmpIOstate = 0;
	}
      
      /* FTP accessed file transferred into memory */
      
      else if(fits_strcasecmp(tmpStr3,"ftp://")          == 0)          
	{
	  *tmpStr1 = 0;
	  strcpy(tmpStr3,"mem://");
	  strcpy(tmpStr4,"ftp://");
	  tmpIOstate = 0;
	}
      
      /* FTP accessed compressed file transferred into memory */

      else if(fits_strcasecmp(tmpStr3,"ftpcompress://")  == 0)  
	{
	  *tmpStr1 = 0;
	  strcpy(tmpStr3,"mem://");
	  strcpy(tmpStr4,"ftp://");
	  tmpIOstate = 0;
	}	
      
      /*
	The last set of access types cannot be used to make a meaningful URL 
	strings from; thus an error is generated
       */

      else if(fits_strcasecmp(tmpStr3,"stdin://")        == 0)        
	{
	  *status = URL_PARSE_ERROR;
	  ffpmsg("cannot make vaild URL from stdin:// (fits_get_url)");
	  *tmpStr1 = *tmpStr2 = 0;
	}

      else if(fits_strcasecmp(tmpStr3,"stdout://")       == 0)       
	{
	  *status = URL_PARSE_ERROR;
	  ffpmsg("cannot make vaild URL from stdout:// (fits_get_url)");
	  *tmpStr1 = *tmpStr2 = 0;
	}

      else if(fits_strcasecmp(tmpStr3,"irafmem://")      == 0)      
	{
	  *status = URL_PARSE_ERROR;
	  ffpmsg("cannot make vaild URL from irafmem:// (fits_get_url)");
	  *tmpStr1 = *tmpStr2 = 0;
	}

      if(*status != 0) continue;

      /*
	 assign values to the calling parameters if they are non-NULL
      */

      if(realURL != NULL)
	{
	  if(strlen(tmpStr1) == 0)
	    *realURL = 0;
	  else
	    {
	      if((tmpPtr = strstr(tmpStr1,"://")) != NULL)
		{
		  tmpPtr += 3;
		  i = (long)tmpPtr - (long)tmpStr1;
		  strncpy(realURL,tmpStr1,i);
		}
	      else
		{
		  tmpPtr = tmpStr1;
		  i = 0;
		}

	      *status = fits_path2url(tmpPtr,realURL+i,status);
	    }
	}

      if(startURL != NULL)
	{
	  if(strlen(tmpStr2) == 0)
	    *startURL = 0;
	  else
	    {
	      if((tmpPtr = strstr(tmpStr2,"://")) != NULL)
		{
		  tmpPtr += 3;
		  i = (long)tmpPtr - (long)tmpStr2;
		  strncpy(startURL,tmpStr2,i);
		}
	      else
		{
		  tmpPtr = tmpStr2;
		  i = 0;
		}

	      *status = fits_path2url(tmpPtr,startURL+i,status);
	    }
	}

      if(realAccess  != NULL)  strcpy(realAccess,tmpStr3);
      if(startAccess != NULL)  strcpy(startAccess,tmpStr4);
      if(iostate     != NULL) *iostate = tmpIOstate;

    }while(0);

  return(*status);
}

/*--------------------------------------------------------------------------
                           URL parse support functions
  --------------------------------------------------------------------------*/

/* simple push/pop/shift/unshift string stack for use by fits_clean_url */
typedef char* grp_stack_data; /* type of data held by grp_stack */

typedef struct grp_stack_item_struct {
  grp_stack_data data; /* value of this stack item */
  struct grp_stack_item_struct* next; /* next stack item */
  struct grp_stack_item_struct* prev; /* previous stack item */
} grp_stack_item;

typedef struct grp_stack_struct {
  size_t stack_size; /* number of items on stack */
  grp_stack_item* top; /* top item */
} grp_stack;

static char* grp_stack_default = NULL; /* initial value for new instances
                                          of grp_stack_data */

/* the following functions implement the group string stack grp_stack */
static void delete_grp_stack(grp_stack** mystack);
static grp_stack_item* grp_stack_append(
  grp_stack_item* last, grp_stack_data data
);
static grp_stack_data grp_stack_remove(grp_stack_item* last);
static grp_stack* new_grp_stack(void);
static grp_stack_data pop_grp_stack(grp_stack* mystack);
static void push_grp_stack(grp_stack* mystack, grp_stack_data data);
static grp_stack_data shift_grp_stack(grp_stack* mystack);
/* static void unshift_grp_stack(grp_stack* mystack, grp_stack_data data); */

int fits_clean_url(char *inURL,  /* I input URL string                      */
		   char *outURL, /* O output URL string                     */
		   int  *status)
/*
  clean the URL by eliminating any ".." or "." specifiers in the inURL
  string, and write the output to the outURL string.

  Note that this function must have a valid Unix-style URL as input; platform
  dependent path strings are not allowed.
 */
{
  grp_stack* mystack; /* stack to hold pieces of URL */
  char* tmp;
  char *saveptr;

  if(*status) return *status;

  mystack = new_grp_stack();
  *outURL = 0;

  do {
    /* handle URL scheme and domain if they exist */
    tmp = strstr(inURL, "://");
    if(tmp) {
      /* there is a URL scheme, so look for the end of the domain too */
      tmp = strchr(tmp + 3, '/');
      if(tmp) {
        /* tmp is now the end of the domain, so
         * copy URL scheme and domain as is, and terminate by hand */
        size_t string_size = (size_t) (tmp - inURL);
        strncpy(outURL, inURL, string_size);
        outURL[string_size] = 0;

        /* now advance the input pointer to just after the domain and go on */
        inURL = tmp;
      } else {
        /* '/' was not found, which means there are no path-like
         * portions, so copy whole inURL to outURL and we're done */
        strcpy(outURL, inURL);
        continue; /* while(0) */
      }
    }

    /* explicitly copy a leading / (absolute path) */
    if('/' == *inURL) strcat(outURL, "/");

    /* now clean the remainder of the inURL. push URL segments onto
     * stack, dealing with .. and . as we go */
    tmp = ffstrtok(inURL, "/",&saveptr); /* finds first / */
    while(tmp) {
      if(!strcmp(tmp, "..")) {
        /* discard previous URL segment, if there was one. if not,
         * add the .. to the stack if this is *not* an absolute path
         * (for absolute paths, leading .. has no effect, so skip it) */
        if(0 < mystack->stack_size) pop_grp_stack(mystack);
        else if('/' != *inURL) push_grp_stack(mystack, tmp);
      } else {
        /* always just skip ., but otherwise add segment to stack */
        if(strcmp(tmp, ".")) push_grp_stack(mystack, tmp);
      }
      tmp = ffstrtok(NULL, "/",&saveptr); /* get the next segment */
    }

    /* stack now has pieces of cleaned URL, so just catenate them
     * onto output string until stack is empty */
    while(0 < mystack->stack_size) {
      tmp = shift_grp_stack(mystack);
      strcat(outURL, tmp);
      strcat(outURL, "/");
    }
    outURL[strlen(outURL) - 1] = 0; /* blank out trailing / */
  } while(0);
  delete_grp_stack(&mystack);
  return *status;
}

/* free all stack contents using pop_grp_stack before freeing the
 * grp_stack itself */
static void delete_grp_stack(grp_stack** mystack) {
  if(!mystack || !*mystack) return;
  while((*mystack)->stack_size) pop_grp_stack(*mystack);
  free(*mystack);
  *mystack = NULL;
}

/* append an item to the stack, handling the special case of the first
 * item appended */
static grp_stack_item* grp_stack_append(
  grp_stack_item* last, grp_stack_data data
) {
  /* first create a new stack item, and copy data to it */
  grp_stack_item* new_item = (grp_stack_item*) malloc(sizeof(grp_stack_item));
  new_item->data = data;
  if(last) {
    /* attach this item between the "last" item and its "next" item */
    new_item->next = last->next;
    new_item->prev = last;
    last->next->prev = new_item;
    last->next = new_item;
  } else {
    /* stack is empty, so "next" and "previous" both point back to it */
    new_item->next = new_item;
    new_item->prev = new_item;
  }
  return new_item;
}

/* remove an item from the stack, handling the special case of the last
 * item removed */
static grp_stack_data grp_stack_remove(grp_stack_item* last) {
  grp_stack_data retval = last->data;
  last->prev->next = last->next;
  last->next->prev = last->prev;
  free(last);
  return retval;
}

/* create new stack dynamically, and give it valid initial values */
static grp_stack* new_grp_stack(void) {
  grp_stack* retval = (grp_stack*) malloc(sizeof(grp_stack));
  if(retval) {
    retval->stack_size = 0;
    retval->top = NULL;
  }
  return retval;
}

/* return the value at the top of the stack and remove it, updating
 * stack_size. top->prev becomes the new "top" */
static grp_stack_data pop_grp_stack(grp_stack* mystack) {
  grp_stack_data retval = grp_stack_default;
  if(mystack && mystack->top) {
    grp_stack_item* newtop = mystack->top->prev;
    retval = grp_stack_remove(mystack->top);
    mystack->top = newtop;
    if(0 == --mystack->stack_size) mystack->top = NULL;
  }
  return retval;
}

/* add to the stack after the top element. the added element becomes
 * the new "top" */
static void push_grp_stack(grp_stack* mystack, grp_stack_data data) {
  if(!mystack) return;
  mystack->top = grp_stack_append(mystack->top, data);
  ++mystack->stack_size;
  return;
}

/* return the value at the bottom of the stack and remove it, updating
 * stack_size. "top" pointer is unaffected */
static grp_stack_data shift_grp_stack(grp_stack* mystack) {
  grp_stack_data retval = grp_stack_default;
  if(mystack && mystack->top) {
    retval = grp_stack_remove(mystack->top->next); /* top->next == bottom */
    if(0 == --mystack->stack_size) mystack->top = NULL;
  }
  return retval;
}

/* add to the stack after the top element. "top" is unaffected, except
 * in the special case of an initially empty stack */
/* static void unshift_grp_stack(grp_stack* mystack, grp_stack_data data) {
   if(!mystack) return;
   if(mystack->top) grp_stack_append(mystack->top, data);
   else mystack->top = grp_stack_append(NULL, data);
   ++mystack->stack_size;
   return;
   } */

/*--------------------------------------------------------------------------*/
int fits_url2relurl(char     *refURL, /* I reference URL string             */
		    char     *absURL, /* I absoulute URL string to process  */
		    char     *relURL, /* O resulting relative URL string    */
		    int      *status)
/*
  create a relative URL to the file referenced by absURL with respect to the
  reference URL refURL. The relative URL is returned in relURL.

  Both refURL and absURL must be absolute URL strings; i.e. either begin
  with an access method specification "XXX://" or with a '/' character
  signifiying that they are absolute file paths.

  Note that it is possible to make a relative URL from two input URLs
  (absURL and refURL) that are not compatable. This function does not
  check to see if the resulting relative URL makes any sence. For instance,
  it is impossible to make a relative URL from the following two inputs:

  absURL = ftp://a.b.c.com/x/y/z/foo.fits
  refURL = /a/b/c/ttt.fits

  The resulting relURL will be:

  ../../../ftp://a.b.c.com/x/y/z/foo.fits 

  Which is syntically correct but meaningless. The problem is that a file
  with an access method of ftp:// cannot be expressed a a relative URL to
  a local disk file.
*/

{
  int i,j;
  int refcount,abscount;
  int refsize,abssize;
  int done;


  if(*status != 0) return(*status);

  /* initialize the relative URL string */
  relURL[0] = 0;

  do
    {
      /*
	refURL and absURL must be absolute to process
      */

      if(!(fits_is_url_absolute(refURL) || *refURL == '/') ||
	 !(fits_is_url_absolute(absURL) || *absURL == '/'))
	{
	  *status = URL_PARSE_ERROR;
	  ffpmsg("Cannot make rel. URL from non abs. URLs (fits_url2relurl)");
	  continue;
	}

      /* determine the size of the refURL and absURL strings */

      refsize = strlen(refURL);
      abssize = strlen(absURL);

      /* process the two URL strings and build the relative URL between them */
		

      for(done = 0, refcount = 0, abscount = 0; 
	  !done && refcount < refsize && abscount < abssize; 
	  ++refcount, ++abscount)
	{
	  for(; abscount < abssize && absURL[abscount] == '/'; ++abscount);
	  for(; refcount < refsize && refURL[refcount] == '/'; ++refcount);

	  /* find the next path segment in absURL */ 
	  for(i = abscount; absURL[i] != '/' && i < abssize; ++i);
	  
	  /* find the next path segment in refURL */
	  for(j = refcount; refURL[j] != '/' && j < refsize; ++j);
	  
	  /* do the two path segments match? */
	  if(i == j && 
	     strncmp(absURL+abscount, refURL+refcount,i-refcount) == 0)
	    {
	      /* they match, so ignore them and continue */
	      abscount = i; refcount = j;
	      continue;
	    }
	  
	  /* We found a difference in the paths in refURL and absURL.
	     For every path segment remaining in the refURL string, append
	     a "../" path segment to the relataive URL relURL.
	  */

	  for(j = refcount; j < refsize; ++j)
	    if(refURL[j] == '/') strcat(relURL,"../");
	  
	  /* copy all remaining characters of absURL to the output relURL */

	  strcat(relURL,absURL+abscount);
	  
	  /* we are done building the relative URL */
	  done = 1;
	}

    }while(0);

  return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_relurl2url(char     *refURL, /* I reference URL string             */
		    char     *relURL, /* I relative URL string to process   */
		    char     *absURL, /* O absolute URL string              */
		    int      *status)
/*
  create an absolute URL from a relative url and a reference URL. The 
  reference URL is given by the FITS file pointed to by fptr.

  The construction of the absolute URL from the partial and reference URl
  is performed using the rules set forth in:
 
  http://www.w3.org/Addressing/URL/URL_TOC.html
  and
  http://www.w3.org/Addressing/URL/4_3_Partial.html

  Note that the relative URL string relURL must conform to the Unix-like
  URL syntax; host dependent partial URL strings are not allowed.
*/
{
  int i;

  char tmpStr[FLEN_FILENAME];

  char *tmpStr1, *tmpStr2;


  if(*status != 0) return(*status);
  
  do
    {

      /*
	make a copy of the reference URL string refURL for parsing purposes
      */

      strcpy(tmpStr,refURL);

      /*
	if the reference file has an access method of mem:// or shmem://
	then we cannot use it as the basis of an absolute URL construction
	for a partial URL
      */
	  
      if(fits_strncasecmp(tmpStr,"MEM:",4)   == 0 ||
                	                fits_strncasecmp(tmpStr,"SHMEM:",6) == 0)
	{
	  ffpmsg("ref URL has access mem:// or shmem:// (fits_relurl2url)");
	  ffpmsg("   cannot construct full URL from a partial URL and ");
	  ffpmsg("   MEM/SHMEM base URL");
	  *status = URL_PARSE_ERROR;
	  continue;
	}

      if(relURL[0] != '/')
	{
	  /*
	    just append the relative URL string to the reference URL
	    string (minus the reference URL file name) to form the 
	    absolute URL string
	  */
	      
	  tmpStr1 = strrchr(tmpStr,'/');
	  
	  if(tmpStr1 != NULL) tmpStr1[1] = 0;
	  else                tmpStr[0]  = 0;
	  
	  strcat(tmpStr,relURL);
	}
      else
	{
	  /*
	    have to parse the refURL string for the first occurnace of the 
	    same number of '/' characters as contained in the beginning of
	    location that is not followed by a greater number of consective 
	    '/' charaters (yes, that is a confusing statement); this is the 
	    location in the refURL string where the relURL string is to
	    be appended to form the new absolute URL string
	   */
	  
	  /*
	    first, build up a slash pattern string that has one more
	    slash in it than the starting slash pattern of the
	    relURL string
	  */
	  
	  strcpy(absURL,"/");
	  
	  for(i = 0; relURL[i] == '/'; ++i) strcat(absURL,"/");
	  
	  /*
	    loop over the refURL string until the slash pattern stored
	    in absURL is no longer found
	  */

	  for(tmpStr1 = tmpStr, i = strlen(absURL); 
	      (tmpStr2 = strstr(tmpStr1,absURL)) != NULL;
	      tmpStr1 = tmpStr2 + i);
	  
	  /* reduce the slash pattern string by one slash */
	  
	  absURL[i-1] = 0;
	  
	  /* 
	     search for the slash pattern in the remaining portion
	     of the refURL string
	  */

	  tmpStr2 = strstr(tmpStr1,absURL);
	  
	  /* if no slash pattern match was found */
	  
	  if(tmpStr2 == NULL)
	    {
	      /* just strip off the file name from the refURL  */
	      
	      tmpStr2 = strrchr(tmpStr1,'/');
	      
	      if(tmpStr2 != NULL) tmpStr2[0] = 0;
	      else                tmpStr[0]  = 0;
	    }
	  else
	    {
	      /* set a string terminator at the slash pattern match */
	      
	      *tmpStr2 = 0;
	    }
	  
	  /* 
	    conatenate the relURL string to the refURL string to form
	    the absURL
	   */

	  strcat(tmpStr,relURL);
	}

      /*
	normalize the absURL by removing any ".." or "." specifiers
	in the string
      */

      *status = fits_clean_url(tmpStr,absURL,status);

    }while(0);

  return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_encode_url(char *inpath,  /* I URL  to be encoded                  */ 
		    char *outpath, /* O output encoded URL                  */
		    int *status)
     /*
       encode all URL "unsafe" and "reserved" characters using the "%XX"
       convention, where XX stand for the two hexidecimal digits of the
       encode character's ASCII code.

       Note that the output path is at least as large as, if not larger than
       the input path, so that OUTPATH should be passed to this function
       with room for growth. If not a runtime error could result. It is
       assumed that OUTPATH has been allocated with enough room to hold
       the resulting encoded URL.

       This function was adopted from code in the libwww.a library available
       via the W3 consortium 
     */
{
  unsigned char a;
  
  char *p;
  char *q;
  char *hex = "0123456789ABCDEF";
  
unsigned const char isAcceptable[96] =
{/* 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xA 0xB 0xC 0xD 0xE 0xF */
  
    0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xF,0xE,0x0,0xF,0xF,0xC, 
                                           /* 2x  !"#$%&'()*+,-./   */
    0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0x8,0x0,0x0,0x0,0x0,0x0,
                                           /* 3x 0123456789:;<=>?   */
    0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF, 
                                           /* 4x @ABCDEFGHIJKLMNO   */
    0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0x0,0x0,0x0,0x0,0xF,
                                           /* 5X PQRSTUVWXYZ[\]^_   */
    0x0,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,
                                           /* 6x `abcdefghijklmno   */
    0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0x0,0x0,0x0,0x0,0x0  
                                           /* 7X pqrstuvwxyz{\}~DEL */
};

  if(*status != 0) return(*status);
  
  /* loop over all characters in inpath until '\0' is encountered */

  for(q = outpath, p = inpath; *p; p++)
    {
      a = (unsigned char)*p;

      /* if the charcter requires encoding then process it */

      if(!( a>=32 && a<128 && (isAcceptable[a-32])))
	{
	  /* add a '%' character to the outpath */
	  *q++ = HEX_ESCAPE;
	  /* add the most significant ASCII code hex value */
	  *q++ = hex[a >> 4];
	  /* add the least significant ASCII code hex value */
	  *q++ = hex[a & 15];
	}
      /* else just copy the character as is */
      else *q++ = *p;
    }

  /* null terminate the outpath string */

  *q++ = 0; 
  
  return(*status);
}

/*---------------------------------------------------------------------------*/
int fits_unencode_url(char *inpath,  /* I input URL with encoding            */
		      char *outpath, /* O unencoded URL                      */
		      int  *status)
     /*
       unencode all URL "unsafe" and "reserved" characters to their actual
       ASCII representation. All tokens of the form "%XX" where XX is the
       hexidecimal code for an ASCII character, are searched for and
       translated into the actuall ASCII character (so three chars become
       1 char).

       It is assumed that OUTPATH has enough room to hold the unencoded
       URL.

       This function was adopted from code in the libwww.a library available
       via the W3 consortium 
     */

{
    char *p;
    char *q;
    char  c;

    if(*status != 0) return(*status);

    p = inpath;
    q = outpath;

    /* 
       loop over all characters in the inpath looking for the '%' escape
       character; if found the process the escape sequence
    */

    while(*p != 0) 
      {
	/* 
	   if the character is '%' then unencode the sequence, else
	   just copy the character from inpath to outpath
        */

        if (*p == HEX_ESCAPE)
	  {
            if((c = *(++p)) != 0)
	      { 
		*q = (
		      (c >= '0' && c <= '9') ?
		      (c - '0') : ((c >= 'A' && c <= 'F') ?
				   (c - 'A' + 10) : (c - 'a' + 10))
		      )*16;

		if((c = *(++p)) != 0)
		  {
		    *q = *q + (
			       (c >= '0' && c <= '9') ? 
		               (c - '0') : ((c >= 'A' && c <= 'F') ? 
					    (c - 'A' + 10) : (c - 'a' + 10))
			       );
		    p++, q++;
		  }
	      }
	  } 
	else
	  *q++ = *p++; 
      }
 
    /* terminate the outpath */
    *q = 0;

    return(*status);   
}
/*---------------------------------------------------------------------------*/

int fits_is_url_absolute(char *url)
/*
  Return a True (1) or False (0) value indicating whether or not the passed
  URL string contains an access method specifier or not. Note that this is
  a boolean function and it neither reads nor returns the standard error
  status parameter
*/
{
  char *tmpStr1, *tmpStr2;

  char reserved[] = {':',';','/','?','@','&','=','+','$',','};

  /*
    The rule for determing if an URL is relative or absolute is that it (1)
    must have a colon ":" and (2) that the colon must appear before any other
    reserved URL character in the URL string. We first see if a colon exists,
    get its position in the string, and then check to see if any of the other
    reserved characters exists and if their position in the string is greater
    than that of the colons. 
   */

  if( (tmpStr1 = strchr(url,reserved[0])) != NULL                       &&
     ((tmpStr2 = strchr(url,reserved[1])) == NULL || tmpStr2 > tmpStr1) &&
     ((tmpStr2 = strchr(url,reserved[2])) == NULL || tmpStr2 > tmpStr1) &&
     ((tmpStr2 = strchr(url,reserved[3])) == NULL || tmpStr2 > tmpStr1) &&
     ((tmpStr2 = strchr(url,reserved[4])) == NULL || tmpStr2 > tmpStr1) &&
     ((tmpStr2 = strchr(url,reserved[5])) == NULL || tmpStr2 > tmpStr1) &&
     ((tmpStr2 = strchr(url,reserved[6])) == NULL || tmpStr2 > tmpStr1) &&
     ((tmpStr2 = strchr(url,reserved[7])) == NULL || tmpStr2 > tmpStr1) &&
     ((tmpStr2 = strchr(url,reserved[8])) == NULL || tmpStr2 > tmpStr1) &&
     ((tmpStr2 = strchr(url,reserved[9])) == NULL || tmpStr2 > tmpStr1)   )
    {
      return(1);
    }
  else
    {
      return(0);
    }
}
cfitsio/group.h0000644000225700000360000000360613246025103013312 0ustar  cagordonlhea#define MAX_HDU_TRACKER 1000

typedef struct _HDUtracker HDUtracker;

struct _HDUtracker
{
  int nHDU;

  char *filename[MAX_HDU_TRACKER];
  int  position[MAX_HDU_TRACKER];

  char *newFilename[MAX_HDU_TRACKER];
  int  newPosition[MAX_HDU_TRACKER];
};

/* functions used internally in the grouping convention module */

int ffgtdc(int grouptype, int xtensioncol, int extnamecol, int extvercol,
	   int positioncol, int locationcol, int uricol, char *ttype[],
	   char *tform[], int *ncols, int  *status);

int ffgtgc(fitsfile *gfptr, int *xtensionCol, int *extnameCol, int *extverCol,
	   int *positionCol, int *locationCol, int *uriCol, int *grptype,
	   int *status);

int ffgmul(fitsfile *mfptr, int rmopt, int *status);

int ffgmf(fitsfile *gfptr, char *xtension, char *extname, int extver,	   
	  int position,	char *location,	long *member, int *status);

int ffgtrmr(fitsfile *gfptr, HDUtracker *HDU, int *status);

int ffgtcpr(fitsfile *infptr, fitsfile *outfptr, int cpopt, HDUtracker *HDU,
	    int *status);

int fftsad(fitsfile *mfptr, HDUtracker *HDU, int *newPosition, 
	   char *newFileName);

int fftsud(fitsfile *mfptr, HDUtracker *HDU, int newPosition, 
	   char *newFileName);

void prepare_keyvalue(char *keyvalue);

int fits_path2url(char *inpath, char *outpath, int  *status);

int fits_url2path(char *inpath, char *outpath, int  *status);

int fits_get_cwd(char *cwd, int *status);

int fits_get_url(fitsfile *fptr, char *realURL, char *startURL, 
		 char *realAccess, char *startAccess, int *iostate, 
		 int *status);

int fits_clean_url(char *inURL, char *outURL, int *status);

int fits_relurl2url(char *refURL, char *relURL, char *absURL, int *status);

int fits_url2relurl(char *refURL, char *absURL, char *relURL, int *status);

int fits_encode_url(char *inpath, char *outpath, int *status);

int fits_unencode_url(char *inpath, char *outpath, int *status);

int fits_is_url_absolute(char *url);

cfitsio/grparser.c0000644000225700000360000013173013246025103013776 0ustar  cagordonlhea/*		T E M P L A T E   P A R S E R
		=============================

		by Jerzy.Borkowski@obs.unige.ch

		Integral Science Data Center
		ch. d'Ecogia 16
		1290 Versoix
		Switzerland

14-Oct-98: initial release
16-Oct-98: code cleanup, #include  included, now gcc -Wall prints no
		warnings during compilation. Bugfix: now one can specify additional
		columns in group HDU. Autoindexing also works in this situation
		(colunms are number from 7 however).
17-Oct-98: bugfix: complex keywords were incorrectly written (was TCOMPLEX should
		be TDBLCOMPLEX).
20-Oct-98: bugfix: parser was writing EXTNAME twice, when first HDU in template is
		defined with XTENSION IMAGE then parser creates now dummy PHDU,
		SIMPLE T is now allowed only at most once and in first HDU only.
		WARNING: one should not define EXTNAME keyword for GROUP HDUs, as
		they have them already defined by parser (EXTNAME = GROUPING).
		Parser accepts EXTNAME oin GROUP HDU definition, but in this
		case multiple EXTNAME keywords will present in HDU header.
23-Oct-98: bugfix: unnecessary space was written to FITS file for blank
		keywords.
24-Oct-98: syntax change: empty lines and lines with only whitespaces are 
		written to FITS files as blank keywords (if inside group/hdu
		definition). Previously lines had to have at least 8 spaces.
		Please note, that due to pecularities of CFITSIO if the
		last keyword(s) defined for given HDU are blank keywords
		consisting of only 80 spaces, then (some of) those keywords
		may be silently deleted by CFITSIO.
13-Nov-98: bugfix: parser was writing GRPNAME twice. Parser still creates
                GRPNAME keywords for GROUP HDU's which do not specify them.
                However, values (of form DEFAULT_GROUP_XXX) are assigned
                not necessarily in order HDUs appear in template file, but
                rather in order parser completes their creation in FITS
                file. Also, when including files, if fopen fails, parser
                tries to open file with a name = directory_of_top_level
                file + name of file to be included, as long as name
                of file to be included does not specify absolute pathname.
16-Nov-98: bugfix to bugfix from 13-Nov-98
19-Nov-98: EXTVER keyword is now automatically assigned value by parser.
17-Dev-98: 2 new things added: 1st: CFITSIO_INCLUDE_FILES environment
		variable can contain a colon separated list of directories
		to look for when looking for template include files (and master
		template also). 2nd: it is now possible to append template
		to nonempty FITS. file. fitsfile *ff no longer needs to point
		to an empty FITS file with 0 HDUs in it. All data written by
		parser will simple be appended at the end of file.
22-Jan-99: changes to parser: when in append mode parser initially scans all
		existing HDUs to built a list of already used EXTNAME/EXTVERs
22-Jan-99: Bruce O'Neel, bugfix : TLONG should always reference long type
		variable on OSF/Alpha and on 64-bit archs in general
20-Jun-2002 Wm Pence, added support for the HIERARCH keyword convention in
                which keyword names can effectively be longer than 8 characters.
                Example:
                HIERARCH  LongKeywordName = 'value' / comment
30-Jan-2003 Wm Pence, bugfix: ngp_read_xtension was testing for "ASCIITABLE" 
                instead of "TABLE" as the XTENSION value of an ASCII table,
                and it did not allow for optional trailing spaces in the
                "IMAGE" or "TABLE" string. 
16-Dec-2003 James Peachey: ngp_keyword_all_write was modified to apply
                comments from the template file to the output file in
                the case of reserved keywords (e.g. tform#, ttype# etcetera).
*/


#include 
#include 

#ifdef sparc
#include 
#include 
#endif

#include 
#include "fitsio2.h"
#include "grparser.h"

NGP_RAW_LINE	ngp_curline = { NULL, NULL, NULL, NGP_TTYPE_UNKNOWN, NULL, NGP_FORMAT_OK, 0 };
NGP_RAW_LINE	ngp_prevline = { NULL, NULL, NULL, NGP_TTYPE_UNKNOWN, NULL, NGP_FORMAT_OK, 0 };

int		ngp_inclevel = 0;		/* number of included files, 1 - means mean file */
int		ngp_grplevel = 0;		/* group nesting level, 0 - means no grouping */

FILE		*ngp_fp[NGP_MAX_INCLUDE];	/* stack of included file handles */
int		ngp_keyidx = NGP_TOKEN_UNKNOWN;	/* index of token in current line */
NGP_TOKEN	ngp_linkey;			/* keyword after line analyze */

char            ngp_master_dir[NGP_MAX_FNAME];  /* directory of top level include file */

NGP_TKDEF	ngp_tkdef[] = 			/* tokens recognized by parser */
      { {	"\\INCLUDE",	NGP_TOKEN_INCLUDE },
	{	"\\GROUP",	NGP_TOKEN_GROUP },
	{	"\\END",	NGP_TOKEN_END },
	{	"XTENSION",	NGP_TOKEN_XTENSION },
	{	"SIMPLE",	NGP_TOKEN_SIMPLE },
	{	NULL,		NGP_TOKEN_UNKNOWN }
      };

int	master_grp_idx = 1;			/* current unnamed group in object */

int		ngp_extver_tab_size = 0;
NGP_EXTVER_TAB	*ngp_extver_tab = NULL;


int	ngp_get_extver(char *extname, int *version)
 { NGP_EXTVER_TAB *p;
   char 	*p2;
   int		i;

   if ((NULL == extname) || (NULL == version)) return(NGP_BAD_ARG);
   if ((NULL == ngp_extver_tab) && (ngp_extver_tab_size > 0)) return(NGP_BAD_ARG);
   if ((NULL != ngp_extver_tab) && (ngp_extver_tab_size <= 0)) return(NGP_BAD_ARG);

   for (i=0; i 0)) return(NGP_BAD_ARG);
   if ((NULL != ngp_extver_tab) && (ngp_extver_tab_size <= 0)) return(NGP_BAD_ARG);

   for (i=0; i ngp_extver_tab[i].version)  ngp_extver_tab[i].version = version;
          return(NGP_OK);
        }
    }

   if (NULL == ngp_extver_tab)
     { p = (NGP_EXTVER_TAB *)ngp_alloc(sizeof(NGP_EXTVER_TAB)); }
   else
     { p = (NGP_EXTVER_TAB *)ngp_realloc(ngp_extver_tab, (ngp_extver_tab_size + 1) * sizeof(NGP_EXTVER_TAB)); }

   if (NULL == p) return(NGP_NO_MEMORY);

   p2 = ngp_alloc(strlen(extname) + 1);
   if (NULL == p2)
     { ngp_free(p);
       return(NGP_NO_MEMORY);
     }

   strcpy(p2, extname);
   ngp_extver_tab = p;
   ngp_extver_tab[ngp_extver_tab_size].extname = p2;
   ngp_extver_tab[ngp_extver_tab_size].version = version;

   ngp_extver_tab_size++;

   return(NGP_OK);
 }


int	ngp_delete_extver_tab(void)
 { int i;

   if ((NULL == ngp_extver_tab) && (ngp_extver_tab_size > 0)) return(NGP_BAD_ARG);
   if ((NULL != ngp_extver_tab) && (ngp_extver_tab_size <= 0)) return(NGP_BAD_ARG);
   if ((NULL == ngp_extver_tab) && (0 == ngp_extver_tab_size)) return(NGP_OK);

   for (i=0; i allocsize)
        { p2 = (char *)ngp_realloc(*p, alen);	/* realloc buffer, if there is need */
          if (NULL == p2)
            { r = NGP_NO_MEMORY;
              break;
            }
	  *p = p2;
          allocsize = alen;
        }
      (*p)[llen - 1] = c;			/* copy character to buffer */
    }

   llen++;					/* place for terminating \0 */
   if (llen != allocsize)
     { p2 = (char *)ngp_realloc(*p, llen);
       if (NULL == p2) r = NGP_NO_MEMORY;
       else
         { *p = p2;
           (*p)[llen - 1] = 0;			/* copy \0 to buffer */
         }         
     }
   else
     { (*p)[llen - 1] = 0;			/* necessary when line read was empty */
     }

   if ((NGP_EOF != r) && (NGP_OK != r))		/* in case of errors free resources */
     { ngp_free(*p);
       *p = NULL;
     }
   
   return(r);					/* return  status code */
 }

	/* free current line structure */

int	ngp_free_line(void)
 {
   if (NULL != ngp_curline.line)
     { ngp_free(ngp_curline.line);
       ngp_curline.line = NULL;
       ngp_curline.name = NULL;
       ngp_curline.value = NULL;
       ngp_curline.comment = NULL;
       ngp_curline.type = NGP_TTYPE_UNKNOWN;
       ngp_curline.format = NGP_FORMAT_OK;
       ngp_curline.flags = 0;
     }
   return(NGP_OK);
 }

	/* free cached line structure */

int	ngp_free_prevline(void)
 {
   if (NULL != ngp_prevline.line)
     { ngp_free(ngp_prevline.line);
       ngp_prevline.line = NULL;
       ngp_prevline.name = NULL;
       ngp_prevline.value = NULL;
       ngp_prevline.comment = NULL;
       ngp_prevline.type = NGP_TTYPE_UNKNOWN;
       ngp_prevline.format = NGP_FORMAT_OK;
       ngp_prevline.flags = 0;
     }
   return(NGP_OK);
 }

	/* read one line */

int	ngp_read_line_buffered(FILE *fp)
 {
   ngp_free_line();				/* first free current line (if any) */
   
   if (NULL != ngp_prevline.line)		/* if cached, return cached line */
     { ngp_curline = ngp_prevline;
       ngp_prevline.line = NULL;
       ngp_prevline.name = NULL;
       ngp_prevline.value = NULL;
       ngp_prevline.comment = NULL;
       ngp_prevline.type = NGP_TTYPE_UNKNOWN;
       ngp_prevline.format = NGP_FORMAT_OK;
       ngp_prevline.flags = 0;
       ngp_curline.flags = NGP_LINE_REREAD;
       return(NGP_OK);
     }

   ngp_curline.flags = 0;   			/* if not cached really read line from file */
   return(ngp_line_from_file(fp, &(ngp_curline.line)));
 }

	/* unread line */

int	ngp_unread_line(void)
 {
   if (NULL == ngp_curline.line)		/* nothing to unread */
     return(NGP_EMPTY_CURLINE);

   if (NULL != ngp_prevline.line)		/* we cannot unread line twice */
     return(NGP_UNREAD_QUEUE_FULL);

   ngp_prevline = ngp_curline;
   ngp_curline.line = NULL;
   return(NGP_OK);
 }

	/* a first guess line decomposition */

int	ngp_extract_tokens(NGP_RAW_LINE *cl)
 { char *p, *s;
   int	cl_flags, i;

   p = cl->line;				/* start from beginning of line */
   if (NULL == p) return(NGP_NUL_PTR);

   cl->name = cl->value = cl->comment = NULL;
   cl->type = NGP_TTYPE_UNKNOWN;
   cl->format = NGP_FORMAT_OK;

   cl_flags = 0;

   for (i=0;; i++)				/* if 8 spaces at beginning then line is comment */
    { if ((0 == *p) || ('\n' == *p))
        {					/* if line has only blanks -> write blank keyword */
          cl->line[0] = 0;			/* create empty name (0 length string) */
          cl->comment = cl->name = cl->line;
	  cl->type = NGP_TTYPE_RAW;		/* signal write unformatted to FITS file */
          return(NGP_OK);
        }
      if ((' ' != *p) && ('\t' != *p)) break;
      if (i >= 7)
        { 
          cl->comment = p + 1;
          for (s = cl->comment;; s++)		/* filter out any EOS characters in comment */
           { if ('\n' == *s) *s = 0;
	     if (0 == *s) break;
           }
          cl->line[0] = 0;			/* create empty name (0 length string) */
          cl->name = cl->line;
	  cl->type = NGP_TTYPE_RAW;
          return(NGP_OK);
        }
      p++;
    }

   cl->name = p;

   for (;;)					/* we need to find 1st whitespace */
    { if ((0 == *p) || ('\n' == *p))
        { *p = 0;
          break;
        }

      /*
        from Richard Mathar, 2002-05-03, add 10 lines:
        if upper/lowercase HIERARCH followed also by an equal sign...
      */
      if( fits_strncasecmp("HIERARCH",p,strlen("HIERARCH")) == 0 )
      {
           char * const eqsi=strchr(p,'=') ;
           if( eqsi )
           {
              cl_flags |= NGP_FOUND_EQUAL_SIGN ;
              p=eqsi ;
              break ;
           }
      }

      if ((' ' == *p) || ('\t' == *p)) break;
      if ('=' == *p)
        { cl_flags |= NGP_FOUND_EQUAL_SIGN;
          break;
        }

      p++;
    }

   if (*p) *(p++) = 0;				/* found end of keyname so terminate string with zero */

   if ((!fits_strcasecmp("HISTORY", cl->name))
    || (!fits_strcasecmp("COMMENT", cl->name))
    || (!fits_strcasecmp("CONTINUE", cl->name)))
     { cl->comment = p;
       for (s = cl->comment;; s++)		/* filter out any EOS characters in comment */
        { if ('\n' == *s) *s = 0;
	  if (0 == *s) break;
        }
       cl->type = NGP_TTYPE_RAW;
       return(NGP_OK);
     }

   if (!fits_strcasecmp("\\INCLUDE", cl->name))
     {
       for (;; p++)  if ((' ' != *p) && ('\t' != *p)) break; /* skip whitespace */

       cl->value = p;
       for (s = cl->value;; s++)		/* filter out any EOS characters */
        { if ('\n' == *s) *s = 0;
	  if (0 == *s) break;
        }
       cl->type = NGP_TTYPE_UNKNOWN;
       return(NGP_OK);
     }
       
   for (;; p++)
    { if ((0 == *p) || ('\n' == *p))  return(NGP_OK);	/* test if at end of string */
      if ((' ' == *p) || ('\t' == *p)) continue; /* skip whitespace */
      if (cl_flags & NGP_FOUND_EQUAL_SIGN) break;
      if ('=' != *p) break;			/* ignore initial equal sign */
      cl_flags |= NGP_FOUND_EQUAL_SIGN;
    }
      
   if ('/' == *p)				/* no value specified, comment only */
     { p++;
       if ((' ' == *p) || ('\t' == *p)) p++;
       cl->comment = p;
       for (s = cl->comment;; s++)		/* filter out any EOS characters in comment */
        { if ('\n' == *s) *s = 0;
	  if (0 == *s) break;
        }
       return(NGP_OK);
     }

   if ('\'' == *p)				/* we have found string within quotes */
     { cl->value = s = ++p;			/* set pointer to beginning of that string */
       cl->type = NGP_TTYPE_STRING;		/* signal that it is of string type */

       for (;;)					/* analyze it */
        { if ((0 == *p) || ('\n' == *p))	/* end of line -> end of string */
            { *s = 0; return(NGP_OK); }

          if ('\'' == *p)			/* we have found doublequote */
            { if ((0 == p[1]) || ('\n' == p[1]))/* doublequote is the last character in line */
                { *s = 0; return(NGP_OK); }
              if (('\t' == p[1]) || (' ' == p[1])) /* duoblequote was string terminator */
                { *s = 0; p++; break; }
              if ('\'' == p[1]) p++;		/* doublequote is inside string, convert "" -> " */ 
            }

          *(s++) = *(p++);			/* compact string in place, necess. by "" -> " conversion */
        }
     }
   else						/* regular token */
     { 
       cl->value = p;				/* set pointer to token */
       cl->type = NGP_TTYPE_UNKNOWN;		/* we dont know type at the moment */
       for (;; p++)				/* we need to find 1st whitespace */
        { if ((0 == *p) || ('\n' == *p))
            { *p = 0; return(NGP_OK); }
          if ((' ' == *p) || ('\t' == *p)) break;
        }
       if (*p)  *(p++) = 0;			/* found so terminate string with zero */
     }
       
   for (;; p++)
    { if ((0 == *p) || ('\n' == *p))  return(NGP_OK);	/* test if at end of string */
      if ((' ' != *p) && ('\t' != *p)) break;	/* skip whitespace */
    }
      
   if ('/' == *p)				/* no value specified, comment only */
     { p++;
       if ((' ' == *p) || ('\t' == *p)) p++;
       cl->comment = p;
       for (s = cl->comment;; s++)		/* filter out any EOS characters in comment */
        { if ('\n' == *s) *s = 0;
	  if (0 == *s) break;
        }
       return(NGP_OK);
     }

   cl->format = NGP_FORMAT_ERROR;
   return(NGP_OK);				/* too many tokens ... */
 }

/*      try to open include file. If open fails and fname
        does not specify absolute pathname, try to open fname
        in any directory specified in CFITSIO_INCLUDE_FILES
        environment variable. Finally try to open fname
        relative to ngp_master_dir, which is directory of top
        level include file
*/

int	ngp_include_file(char *fname)		/* try to open include file */
 { char *p, *p2, *cp, *envar, envfiles[NGP_MAX_ENVFILES];
   char *saveptr;

   if (NULL == fname) return(NGP_NUL_PTR);

   if (ngp_inclevel >= NGP_MAX_INCLUDE)		/* too many include files */
     return(NGP_INC_NESTING);

   if (NULL == (ngp_fp[ngp_inclevel] = fopen(fname, "r")))
     {                                          /* if simple open failed .. */
       envar = getenv("CFITSIO_INCLUDE_FILES");	/* scan env. variable, and retry to open */

       if (NULL != envar)			/* is env. variable defined ? */
         { strncpy(envfiles, envar, NGP_MAX_ENVFILES - 1);
           envfiles[NGP_MAX_ENVFILES - 1] = 0;	/* copy search path to local variable, env. is fragile */

           for (p2 = ffstrtok(envfiles, ":",&saveptr); NULL != p2; p2 = ffstrtok(NULL, ":",&saveptr))
            {
	      cp = (char *)ngp_alloc(strlen(fname) + strlen(p2) + 2);
	      if (NULL == cp) return(NGP_NO_MEMORY);

	      strcpy(cp, p2);
#ifdef  MSDOS
              strcat(cp, "\\");			/* abs. pathname for MSDOS */
               
#else
              strcat(cp, "/");			/* and for unix */
#endif
	      strcat(cp, fname);
	  
	      ngp_fp[ngp_inclevel] = fopen(cp, "r");
	      ngp_free(cp);

	      if (NULL != ngp_fp[ngp_inclevel]) break;
	    }
        }
                                      
       if (NULL == ngp_fp[ngp_inclevel])	/* finally try to open relative to top level */
         {
#ifdef  MSDOS
           if ('\\' == fname[0]) return(NGP_ERR_FOPEN); /* abs. pathname for MSDOS, does not support C:\\PATH */
#else
           if ('/' == fname[0]) return(NGP_ERR_FOPEN); /* and for unix */
#endif
           if (0 == ngp_master_dir[0]) return(NGP_ERR_FOPEN);

	   p = ngp_alloc(strlen(fname) + strlen(ngp_master_dir) + 1);
           if (NULL == p) return(NGP_NO_MEMORY);

           strcpy(p, ngp_master_dir);		/* construct composite pathname */
           strcat(p, fname);			/* comp = master + fname */

           ngp_fp[ngp_inclevel] = fopen(p, "r");/* try to open composite */
           ngp_free(p);				/* we don't need buffer anymore */

           if (NULL == ngp_fp[ngp_inclevel])
             return(NGP_ERR_FOPEN);		/* fail if error */
         }
     }

   ngp_inclevel++;
   return(NGP_OK);
 }


/* read line in the intelligent way. All \INCLUDE directives are handled,
   empty and comment line skipped. If this function returns NGP_OK, than
   decomposed line (name, type, value in proper type and comment) are
   stored in ngp_linkey structure. ignore_blank_lines parameter is zero
   when parser is inside GROUP or HDU definition. Nonzero otherwise.
*/

int	ngp_read_line(int ignore_blank_lines)
 { int r, nc, savec;
   unsigned k;

   if (ngp_inclevel <= 0)		/* do some sanity checking first */
     { ngp_keyidx = NGP_TOKEN_EOF;	/* no parents, so report error */
       return(NGP_OK);	
     }
   if (ngp_inclevel > NGP_MAX_INCLUDE)  return(NGP_INC_NESTING);
   if (NULL == ngp_fp[ngp_inclevel - 1]) return(NGP_NUL_PTR);

   for (;;)
    { switch (r = ngp_read_line_buffered(ngp_fp[ngp_inclevel - 1]))
       { case NGP_EOF:
		ngp_inclevel--;			/* end of file, revert to parent */
		if (ngp_fp[ngp_inclevel])	/* we can close old file */
		  fclose(ngp_fp[ngp_inclevel]);

		ngp_fp[ngp_inclevel] = NULL;
		if (ngp_inclevel <= 0)
		  { ngp_keyidx = NGP_TOKEN_EOF;	/* no parents, so report error */
		    return(NGP_OK);	
		  }
		continue;

	 case NGP_OK:
		if (ngp_curline.flags & NGP_LINE_REREAD) return(r);
		break;
	 default:
		return(r);
       }
      
      switch (ngp_curline.line[0])
       { case 0: if (0 == ignore_blank_lines) break; /* ignore empty lines if told so */
         case '#': continue;			/* ignore comment lines */
       }
      
      r = ngp_extract_tokens(&ngp_curline);	/* analyse line, extract tokens and comment */
      if (NGP_OK != r) return(r);

      if (NULL == ngp_curline.name)  continue;	/* skip lines consisting only of whitespaces */

      for (k = 0; k < strlen(ngp_curline.name); k++)
       { if ((ngp_curline.name[k] >= 'a') && (ngp_curline.name[k] <= 'z')) 
           ngp_curline.name[k] += 'A' - 'a';	/* force keyword to be upper case */
         if (k == 7) break;  /* only first 8 chars are required to be upper case */
       }

      for (k=0;; k++)				/* find index of keyword in keyword table */
       { if (NGP_TOKEN_UNKNOWN == ngp_tkdef[k].code) break;
         if (0 == strcmp(ngp_curline.name, ngp_tkdef[k].name)) break;
       }

      ngp_keyidx = ngp_tkdef[k].code;		/* save this index, grammar parser will need this */

      if (NGP_TOKEN_INCLUDE == ngp_keyidx)	/* if this is \INCLUDE keyword, try to include file */
        { if (NGP_OK != (r = ngp_include_file(ngp_curline.value))) return(r);
	  continue;				/* and read next line */
        }

      ngp_linkey.type = NGP_TTYPE_UNKNOWN;	/* now, get the keyword type, it's a long story ... */

      if (NULL != ngp_curline.value)		/* if no value given signal it */
        { if (NGP_TTYPE_STRING == ngp_curline.type)  /* string type test */
            { ngp_linkey.type = NGP_TTYPE_STRING;
              ngp_linkey.value.s = ngp_curline.value;
            }
          if (NGP_TTYPE_UNKNOWN == ngp_linkey.type) /* bool type test */
            { if ((!fits_strcasecmp("T", ngp_curline.value)) || (!fits_strcasecmp("F", ngp_curline.value)))
                { ngp_linkey.type = NGP_TTYPE_BOOL;
                  ngp_linkey.value.b = (fits_strcasecmp("T", ngp_curline.value) ? 0 : 1);
                }
            }
          if (NGP_TTYPE_UNKNOWN == ngp_linkey.type) /* complex type test */
            { if (2 == sscanf(ngp_curline.value, "(%lg,%lg)%n", &(ngp_linkey.value.c.re), &(ngp_linkey.value.c.im), &nc))
                { if ((' ' == ngp_curline.value[nc]) || ('\t' == ngp_curline.value[nc])
                   || ('\n' == ngp_curline.value[nc]) || (0 == ngp_curline.value[nc]))
                    { ngp_linkey.type = NGP_TTYPE_COMPLEX;
                    }
                }
            }
          if (NGP_TTYPE_UNKNOWN == ngp_linkey.type) /* real type test */
            { if (strchr(ngp_curline.value, '.') && (1 == sscanf(ngp_curline.value, "%lg%n", &(ngp_linkey.value.d), &nc)))
                {
		 if ('D' == ngp_curline.value[nc]) {
		   /* test if template used a 'D' rather than an 'E' as the exponent character (added by WDP in 12/2010) */
                   savec = nc;
		   ngp_curline.value[nc] = 'E';
		   sscanf(ngp_curline.value, "%lg%n", &(ngp_linkey.value.d), &nc);
		   if ((' ' == ngp_curline.value[nc]) || ('\t' == ngp_curline.value[nc])
                    || ('\n' == ngp_curline.value[nc]) || (0 == ngp_curline.value[nc]))  {
                       ngp_linkey.type = NGP_TTYPE_REAL;
                     } else {  /* no, this is not a real value */
		       ngp_curline.value[savec] = 'D';  /* restore the original D character */
 		     }
		 } else {
		  if ((' ' == ngp_curline.value[nc]) || ('\t' == ngp_curline.value[nc])
                   || ('\n' == ngp_curline.value[nc]) || (0 == ngp_curline.value[nc]))
                    { ngp_linkey.type = NGP_TTYPE_REAL;
                    }
                 } 
                }
            }
          if (NGP_TTYPE_UNKNOWN == ngp_linkey.type) /* integer type test */
            { if (1 == sscanf(ngp_curline.value, "%d%n", &(ngp_linkey.value.i), &nc))
                { if ((' ' == ngp_curline.value[nc]) || ('\t' == ngp_curline.value[nc])
                   || ('\n' == ngp_curline.value[nc]) || (0 == ngp_curline.value[nc]))
                    { ngp_linkey.type = NGP_TTYPE_INT;
                    }
                }
            }
          if (NGP_TTYPE_UNKNOWN == ngp_linkey.type) /* force string type */
            { ngp_linkey.type = NGP_TTYPE_STRING;
              ngp_linkey.value.s = ngp_curline.value;
            }
        }
      else
        { if (NGP_TTYPE_RAW == ngp_curline.type) ngp_linkey.type = NGP_TTYPE_RAW;
	  else ngp_linkey.type = NGP_TTYPE_NULL;
	}

      if (NULL != ngp_curline.comment)
        { strncpy(ngp_linkey.comment, ngp_curline.comment, NGP_MAX_COMMENT); /* store comment */
	  ngp_linkey.comment[NGP_MAX_COMMENT - 1] = 0;
	}
      else
        { ngp_linkey.comment[0] = 0;
        }

      strncpy(ngp_linkey.name, ngp_curline.name, NGP_MAX_NAME); /* and keyword's name */
      ngp_linkey.name[NGP_MAX_NAME - 1] = 0;

      if (strlen(ngp_linkey.name) > FLEN_KEYWORD)  /* WDP: 20-Jun-2002:  mod to support HIERARCH */
        { 
           return(NGP_BAD_ARG);		/* cfitsio does not allow names > 8 chars */
        }
      
      return(NGP_OK);			/* we have valid non empty line, so return success */
    }
 }

	/* check whether keyword can be written as is */

int	ngp_keyword_is_write(NGP_TOKEN *ngp_tok)
 { int i, j, l, spc;
                        /* indexed variables not to write */

   static char *nm[] = { "NAXIS", "TFORM", "TTYPE", NULL } ;

                        /* non indexed variables not allowed to write */
  
   static char *nmni[] = { "SIMPLE", "XTENSION", "BITPIX", "NAXIS", "PCOUNT",
                           "GCOUNT", "TFIELDS", "THEAP", "EXTEND", "EXTVER",
                           NULL } ;

   if (NULL == ngp_tok) return(NGP_NUL_PTR);

   for (j = 0; ; j++)           /* first check non indexed */
    { if (NULL == nmni[j]) break;
      if (0 == strcmp(nmni[j], ngp_tok->name)) return(NGP_BAD_ARG);
    } 

   for (j = 0; ; j++)           /* now check indexed */
    { if (NULL == nm[j]) return(NGP_OK);
      l = strlen(nm[j]);
      if ((l < 1) || (l > 5)) continue;
      if (0 == strncmp(nm[j], ngp_tok->name, l)) break;
    } 

   if ((ngp_tok->name[l] < '1') || (ngp_tok->name[l] > '9')) return(NGP_OK);
   spc = 0;
   for (i = l + 1; i < 8; i++)
    { if (spc) { if (' ' != ngp_tok->name[i]) return(NGP_OK); }
      else
       { if ((ngp_tok->name[i] >= '0') && (ngp_tok->name[i] <= '9')) continue;
         if (' ' == ngp_tok->name[i]) { spc = 1; continue; }
         if (0 == ngp_tok->name[i]) break;
         return(NGP_OK);
       }
    }
   return(NGP_BAD_ARG);
 }

	/* write (almost) all keywords from given HDU to disk */

int     ngp_keyword_all_write(NGP_HDU *ngph, fitsfile *ffp, int mode)
 { int		i, r, ib;
   char		buf[200];
   long		l;


   if (NULL == ngph) return(NGP_NUL_PTR);
   if (NULL == ffp) return(NGP_NUL_PTR);
   r = NGP_OK;
   
   for (i=0; itokcnt; i++)
    { r = ngp_keyword_is_write(&(ngph->tok[i]));
      if ((NGP_REALLY_ALL & mode) || (NGP_OK == r))
        { switch (ngph->tok[i].type)
           { case NGP_TTYPE_BOOL:
			ib = ngph->tok[i].value.b;
			fits_write_key(ffp, TLOGICAL, ngph->tok[i].name, &ib, ngph->tok[i].comment, &r);
			break;
             case NGP_TTYPE_STRING:
			fits_write_key_longstr(ffp, ngph->tok[i].name, ngph->tok[i].value.s, ngph->tok[i].comment, &r);
			break;
             case NGP_TTYPE_INT:
			l = ngph->tok[i].value.i;	/* bugfix - 22-Jan-99, BO - nonalignment of OSF/Alpha */
			fits_write_key(ffp, TLONG, ngph->tok[i].name, &l, ngph->tok[i].comment, &r);
			break;
             case NGP_TTYPE_REAL:
			fits_write_key(ffp, TDOUBLE, ngph->tok[i].name, &(ngph->tok[i].value.d), ngph->tok[i].comment, &r);
			break;
             case NGP_TTYPE_COMPLEX:
			fits_write_key(ffp, TDBLCOMPLEX, ngph->tok[i].name, &(ngph->tok[i].value.c), ngph->tok[i].comment, &r);
			break;
             case NGP_TTYPE_NULL:
			fits_write_key_null(ffp, ngph->tok[i].name, ngph->tok[i].comment, &r);
			break;
             case NGP_TTYPE_RAW:
			if (0 == strcmp("HISTORY", ngph->tok[i].name))
			  { fits_write_history(ffp, ngph->tok[i].comment, &r);
			    break;
			  }
			if (0 == strcmp("COMMENT", ngph->tok[i].name))
			  { fits_write_comment(ffp, ngph->tok[i].comment, &r);
			    break;
			  }
			snprintf(buf,200, "%-8.8s%s", ngph->tok[i].name, ngph->tok[i].comment);
			fits_write_record(ffp, buf, &r);
                        break;
           }
        }
      else if (NGP_BAD_ARG == r) /* enhancement 10 dec 2003, James Peachey: template comments replace defaults */
        { r = NGP_OK;						/* update comments of special keywords like TFORM */
          if (ngph->tok[i].comment && *ngph->tok[i].comment)	/* do not update with a blank comment */
            { fits_modify_comment(ffp, ngph->tok[i].name, ngph->tok[i].comment, &r);
            }
        }
      else /* other problem, typically a blank token */
        { r = NGP_OK;						/* skip this token, but continue */
        }
      if (r) return(r);
    }
     
   fits_set_hdustruc(ffp, &r);				/* resync cfitsio */
   return(r);
 }

	/* init HDU structure */

int	ngp_hdu_init(NGP_HDU *ngph)
 { if (NULL == ngph) return(NGP_NUL_PTR);
   ngph->tok = NULL;
   ngph->tokcnt = 0;
   return(NGP_OK);
 }

	/* clear HDU structure */

int	ngp_hdu_clear(NGP_HDU *ngph)
 { int i;

   if (NULL == ngph) return(NGP_NUL_PTR);

   for (i=0; itokcnt; i++)
    { if (NGP_TTYPE_STRING == ngph->tok[i].type)
        if (NULL != ngph->tok[i].value.s)
          { ngp_free(ngph->tok[i].value.s);
            ngph->tok[i].value.s = NULL;
          }
    }

   if (NULL != ngph->tok) ngp_free(ngph->tok);

   ngph->tok = NULL;
   ngph->tokcnt = 0;

   return(NGP_OK);
 }

	/* insert new token to HDU structure */

int	ngp_hdu_insert_token(NGP_HDU *ngph, NGP_TOKEN *newtok)
 { NGP_TOKEN *tkp;
   
   if (NULL == ngph) return(NGP_NUL_PTR);
   if (NULL == newtok) return(NGP_NUL_PTR);

   if (0 == ngph->tokcnt)
     tkp = (NGP_TOKEN *)ngp_alloc((ngph->tokcnt + 1) * sizeof(NGP_TOKEN));
   else
     tkp = (NGP_TOKEN *)ngp_realloc(ngph->tok, (ngph->tokcnt + 1) * sizeof(NGP_TOKEN));

   if (NULL == tkp) return(NGP_NO_MEMORY);
       
   ngph->tok = tkp;
   ngph->tok[ngph->tokcnt] = *newtok;

   if (NGP_TTYPE_STRING == newtok->type)
     { if (NULL != newtok->value.s)
         { ngph->tok[ngph->tokcnt].value.s = (char *)ngp_alloc(1 + strlen(newtok->value.s));
           if (NULL == ngph->tok[ngph->tokcnt].value.s) return(NGP_NO_MEMORY);
           strcpy(ngph->tok[ngph->tokcnt].value.s, newtok->value.s);
         }
     }

   ngph->tokcnt++;
   return(NGP_OK);
 }


int	ngp_append_columns(fitsfile *ff, NGP_HDU *ngph, int aftercol)
 { int		r, i, j, exitflg, ngph_i;
   char 	*my_tform, *my_ttype;
   char		ngph_ctmp;


   if (NULL == ff) return(NGP_NUL_PTR);
   if (NULL == ngph) return(NGP_NUL_PTR);
   if (0 == ngph->tokcnt) return(NGP_OK);	/* nothing to do ! */

   r = NGP_OK;
   exitflg = 0;

   for (j=aftercol; jtok[i].name, "TFORM%d%c", &ngph_i, &ngph_ctmp))
           { if ((NGP_TTYPE_STRING == ngph->tok[i].type) && (ngph_i == (j + 1)))
   	    { my_tform = ngph->tok[i].value.s;
   	    }
                }
         else if (1 == sscanf(ngph->tok[i].name, "TTYPE%d%c", &ngph_i, &ngph_ctmp))
           { if ((NGP_TTYPE_STRING == ngph->tok[i].type) && (ngph_i == (j + 1)))
               { my_ttype = ngph->tok[i].value.s;
               }
           }
         
         if ((NULL != my_tform) && (my_ttype[0])) break;
         
         if (i < (ngph->tokcnt - 1)) continue;
         exitflg = 1;
         break;
       }
      if ((NGP_OK == r) && (NULL != my_tform))
        fits_insert_col(ff, j + 1, my_ttype, my_tform, &r);

      if ((NGP_OK != r) || exitflg) break;
    }
   return(r);
 }

	/* read complete HDU */

int	ngp_read_xtension(fitsfile *ff, int parent_hn, int simple_mode)
 { int		r, exflg, l, my_hn, tmp0, incrementor_index, i, j;
   int		ngph_dim, ngph_bitpix, ngph_node_type, my_version;
   char		incrementor_name[NGP_MAX_STRING], ngph_ctmp;
   char 	*ngph_extname = 0;
   long		ngph_size[NGP_MAX_ARRAY_DIM];
   NGP_HDU	ngph;
   long		lv;

   incrementor_name[0] = 0;			/* signal no keyword+'#' found yet */
   incrementor_index = 0;

   if (NGP_OK != (r = ngp_hdu_init(&ngph))) return(r);

   if (NGP_OK != (r = ngp_read_line(0))) return(r);	/* EOF always means error here */
   switch (NGP_XTENSION_SIMPLE & simple_mode)
     {
       case 0:  if (NGP_TOKEN_XTENSION != ngp_keyidx) return(NGP_TOKEN_NOT_EXPECT);
		break;
       default:	if (NGP_TOKEN_SIMPLE != ngp_keyidx) return(NGP_TOKEN_NOT_EXPECT);
		break;
     }
       	
   if (NGP_OK != (r = ngp_hdu_insert_token(&ngph, &ngp_linkey))) return(r);

   for (;;)
    { if (NGP_OK != (r = ngp_read_line(0))) return(r);	/* EOF always means error here */
      exflg = 0;
      switch (ngp_keyidx)
       { 
	 case NGP_TOKEN_SIMPLE:
	 		r = NGP_TOKEN_NOT_EXPECT;
			break;
	 		                        
	 case NGP_TOKEN_END:
         case NGP_TOKEN_XTENSION:
         case NGP_TOKEN_GROUP:
         		r = ngp_unread_line();	/* WARNING - not break here .... */
         case NGP_TOKEN_EOF:
			exflg = 1;
 			break;

         default:	l = strlen(ngp_linkey.name);
			if ((l >= 2) && (l <= 6))
			  { if ('#' == ngp_linkey.name[l - 1])
			      { if (0 == incrementor_name[0])
			          { memcpy(incrementor_name, ngp_linkey.name, l - 1);
			            incrementor_name[l - 1] = 0;
			          }
			        if (((l - 1) == (int)strlen(incrementor_name)) && (0 == memcmp(incrementor_name, ngp_linkey.name, l - 1)))
			          { incrementor_index++;
			          }
			        snprintf(ngp_linkey.name + l - 1, NGP_MAX_NAME-l+1,"%d", incrementor_index);
			      }
			  }
			r = ngp_hdu_insert_token(&ngph, &ngp_linkey);
 			break;
       }
      if ((NGP_OK != r) || exflg) break;
    }

   if (NGP_OK == r)
     { 				/* we should scan keywords, and calculate HDU's */
				/* structure ourselves .... */

       ngph_node_type = NGP_NODE_INVALID;	/* init variables */
       ngph_bitpix = 0;
       ngph_extname = NULL;
       for (i=0; i=1) && (j <= NGP_MAX_ARRAY_DIM))
		  { ngph_size[j - 1] = ngph.tok[i].value.i;
		  }
            }
        }

       switch (ngph_node_type)
        { case NGP_NODE_IMAGE:
			if (NGP_XTENSION_FIRST == ((NGP_XTENSION_FIRST | NGP_XTENSION_SIMPLE) & simple_mode))
			  { 		/* if caller signals that this is 1st HDU in file */
					/* and it is IMAGE defined with XTENSION, then we */
					/* need create dummy Primary HDU */			  
			    fits_create_img(ff, 16, 0, NULL, &r);
			  }
					/* create image */
			fits_create_img(ff, ngph_bitpix, ngph_dim, ngph_size, &r);

					/* update keywords */
			if (NGP_OK == r)  r = ngp_keyword_all_write(&ngph, ff, NGP_NON_SYSTEM_ONLY);
			break;

          case NGP_NODE_ATABLE:
          case NGP_NODE_BTABLE:
					/* create table, 0 rows and 0 columns for the moment */
			fits_create_tbl(ff, ((NGP_NODE_ATABLE == ngph_node_type)
					     ? ASCII_TBL : BINARY_TBL),
					0, 0, NULL, NULL, NULL, NULL, &r);
			if (NGP_OK != r) break;

					/* add columns ... */
			r = ngp_append_columns(ff, &ngph, 0);
			if (NGP_OK != r) break;

					/* add remaining keywords */
			r = ngp_keyword_all_write(&ngph, ff, NGP_NON_SYSTEM_ONLY);
			if (NGP_OK != r) break;

					/* if requested add rows */
			if (ngph_size[1] > 0) fits_insert_rows(ff, 0, ngph_size[1], &r);
			break;

	  default:	r = NGP_BAD_ARG;
	  		break;
	}

     }

   if ((NGP_OK == r) && (NULL != ngph_extname))
     { r = ngp_get_extver(ngph_extname, &my_version);	/* write correct ext version number */
       lv = my_version;		/* bugfix - 22-Jan-99, BO - nonalignment of OSF/Alpha */
       fits_write_key(ff, TLONG, "EXTVER", &lv, "auto assigned by template parser", &r); 
     }

   if (NGP_OK == r)
     { if (parent_hn > 0)
         { fits_get_hdu_num(ff, &my_hn);
           fits_movabs_hdu(ff, parent_hn, &tmp0, &r);	/* link us to parent */
           fits_add_group_member(ff, NULL, my_hn, &r);
           fits_movabs_hdu(ff, my_hn, &tmp0, &r);
           if (NGP_OK != r) return(r);
         }
     }

   if (NGP_OK != r)					/* in case of error - delete hdu */
     { tmp0 = 0;
       fits_delete_hdu(ff, NULL, &tmp0);
     }

   ngp_hdu_clear(&ngph);
   return(r);
 }

	/* read complete GROUP */

int	ngp_read_group(fitsfile *ff, char *grpname, int parent_hn)
 { int		r, exitflg, l, my_hn, tmp0, incrementor_index;
   char		grnm[NGP_MAX_STRING];			/* keyword holding group name */
   char		incrementor_name[NGP_MAX_STRING];
   NGP_HDU	ngph;

   incrementor_name[0] = 0;			/* signal no keyword+'#' found yet */
   incrementor_index = 6;			/* first 6 cols are used by group */

   ngp_grplevel++;
   if (NGP_OK != (r = ngp_hdu_init(&ngph))) return(r);

   r = NGP_OK;
   if (NGP_OK != (r = fits_create_group(ff, grpname, GT_ID_ALL_URI, &r))) return(r);
   fits_get_hdu_num(ff, &my_hn);
   if (parent_hn > 0)
     { fits_movabs_hdu(ff, parent_hn, &tmp0, &r);	/* link us to parent */
       fits_add_group_member(ff, NULL, my_hn, &r);
       fits_movabs_hdu(ff, my_hn, &tmp0, &r);
       if (NGP_OK != r) return(r);
     }

   for (exitflg = 0; 0 == exitflg;)
    { if (NGP_OK != (r = ngp_read_line(0))) break;	/* EOF always means error here */
      switch (ngp_keyidx)
       {
	 case NGP_TOKEN_SIMPLE:
	 case NGP_TOKEN_EOF:
			r = NGP_TOKEN_NOT_EXPECT;
			break;

         case NGP_TOKEN_END:
         		ngp_grplevel--;
			exitflg = 1;
			break;

         case NGP_TOKEN_GROUP:
			if (NGP_TTYPE_STRING == ngp_linkey.type)
			  { strncpy(grnm, ngp_linkey.value.s, NGP_MAX_STRING);
			  }
			else
			  { snprintf(grnm, NGP_MAX_STRING,"DEFAULT_GROUP_%d", master_grp_idx++);
			  }
			grnm[NGP_MAX_STRING - 1] = 0;
			r = ngp_read_group(ff, grnm, my_hn);
			break;			/* we can have many subsequent GROUP defs */

         case NGP_TOKEN_XTENSION:
         		r = ngp_unread_line();
         		if (NGP_OK != r) break;
         		r = ngp_read_xtension(ff, my_hn, 0);
			break;			/* we can have many subsequent HDU defs */

         default:	l = strlen(ngp_linkey.name);
			if ((l >= 2) && (l <= 6))
			  { if ('#' == ngp_linkey.name[l - 1])
			      { if (0 == incrementor_name[0])
			          { memcpy(incrementor_name, ngp_linkey.name, l - 1);
			            incrementor_name[l - 1] = 0;
			          }
			        if (((l - 1) == (int)strlen(incrementor_name)) && (0 == memcmp(incrementor_name, ngp_linkey.name, l - 1)))
			          { incrementor_index++;
			          }
			        snprintf(ngp_linkey.name + l - 1, NGP_MAX_NAME-l+1,"%d", incrementor_index);
			      }
			  }
         		r = ngp_hdu_insert_token(&ngph, &ngp_linkey); 
			break;			/* here we can add keyword */
       }
      if (NGP_OK != r) break;
    }

   fits_movabs_hdu(ff, my_hn, &tmp0, &r);	/* back to our HDU */

   if (NGP_OK == r)				/* create additional columns, if requested */
     r = ngp_append_columns(ff, &ngph, 6);

   if (NGP_OK == r)				/* and write keywords */
     r = ngp_keyword_all_write(&ngph, ff, NGP_NON_SYSTEM_ONLY);

   if (NGP_OK != r)			/* delete group in case of error */
     { tmp0 = 0;
       fits_remove_group(ff, OPT_RM_GPT, &tmp0);
     }

   ngp_hdu_clear(&ngph);		/* we are done with this HDU, so delete it */
   return(r);
 }

		/* top level API functions */

/* read whole template. ff should point to the opened empty fits file. */

int	fits_execute_template(fitsfile *ff, char *ngp_template, int *status)
 { int		r, exit_flg, first_extension, i, my_hn, tmp0, keys_exist, more_keys, used_ver;
   char		grnm[NGP_MAX_STRING], used_name[NGP_MAX_STRING];
   long		luv;

   if (NULL == status) return(NGP_NUL_PTR);
   if (NGP_OK != *status) return(*status);

   if ((NULL == ff) || (NULL == ngp_template))
     { *status = NGP_NUL_PTR;
       return(*status);
     }

   ngp_inclevel = 0;				/* initialize things, not all should be zero */
   ngp_grplevel = 0;
   master_grp_idx = 1;
   exit_flg = 0;
   ngp_master_dir[0] = 0;			/* this should be before 1st call to ngp_include_file */
   first_extension = 1;				/* we need to create PHDU */

   if (NGP_OK != (r = ngp_delete_extver_tab()))
     { *status = r;
       return(r);
     }

   fits_get_hdu_num(ff, &my_hn);		/* our HDU position */
   if (my_hn <= 1)				/* check whether we really need to create PHDU */
     { fits_movabs_hdu(ff, 1, &tmp0, status);
       fits_get_hdrspace(ff, &keys_exist, &more_keys, status);
       fits_movabs_hdu(ff, my_hn, &tmp0, status);
       if (NGP_OK != *status) return(*status);	/* error here means file is corrupted */
       if (keys_exist > 0) first_extension = 0;	/* if keywords exist assume PHDU already exist */
     }
   else
     { first_extension = 0;			/* PHDU (followed by 1+ extensions) exist */

       for (i = 2; i<= my_hn; i++)
        { *status = NGP_OK;
          fits_movabs_hdu(ff, 1, &tmp0, status);
          if (NGP_OK != *status) break;

          fits_read_key(ff, TSTRING, "EXTNAME", used_name, NULL, status);
          if (NGP_OK != *status)  continue;

          fits_read_key(ff, TLONG, "EXTVER", &luv, NULL, status);
          used_ver = luv;			/* bugfix - 22-Jan-99, BO - nonalignment of OSF/Alpha */
          if (VALUE_UNDEFINED == *status)
            { used_ver = 1;
              *status = NGP_OK;
            }

          if (NGP_OK == *status) *status = ngp_set_extver(used_name, used_ver);
        }

       fits_movabs_hdu(ff, my_hn, &tmp0, status);
     }
   if (NGP_OK != *status) return(*status);
                                                                          
   if (NGP_OK != (*status = ngp_include_file(ngp_template))) return(*status);

   for (i = strlen(ngp_template) - 1; i >= 0; i--) /* strlen is > 0, otherwise fopen failed */
    { 
#ifdef MSDOS
      if ('\\' == ngp_template[i]) break;
#else
      if ('/' == ngp_template[i]) break;
#endif
    } 
      
   i++;
   if (i > (NGP_MAX_FNAME - 1)) i = NGP_MAX_FNAME - 1;

   if (i > 0)
     { memcpy(ngp_master_dir, ngp_template, i);
       ngp_master_dir[i] = 0;
     }


   for (;;)
    { if (NGP_OK != (r = ngp_read_line(1))) break;	/* EOF always means error here */
      switch (ngp_keyidx)
       {
         case NGP_TOKEN_SIMPLE:
			if (0 == first_extension)	/* simple only allowed in first HDU */
			  { r = NGP_TOKEN_NOT_EXPECT;
			    break;
			  }
			if (NGP_OK != (r = ngp_unread_line())) break;
			r = ngp_read_xtension(ff, 0, NGP_XTENSION_SIMPLE | NGP_XTENSION_FIRST);
			first_extension = 0;
			break;

         case NGP_TOKEN_XTENSION:
			if (NGP_OK != (r = ngp_unread_line())) break;
			r = ngp_read_xtension(ff, 0, (first_extension ? NGP_XTENSION_FIRST : 0));
			first_extension = 0;
			break;

         case NGP_TOKEN_GROUP:
			if (NGP_TTYPE_STRING == ngp_linkey.type)
			  { strncpy(grnm, ngp_linkey.value.s, NGP_MAX_STRING); }
			else
			  { snprintf(grnm,NGP_MAX_STRING, "DEFAULT_GROUP_%d", master_grp_idx++); }
			grnm[NGP_MAX_STRING - 1] = 0;
			r = ngp_read_group(ff, grnm, 0);
			first_extension = 0;
			break;

	 case NGP_TOKEN_EOF:
			exit_flg = 1;
			break;

         default:	r = NGP_TOKEN_NOT_EXPECT;
			break;
       }
      if (exit_flg || (NGP_OK != r)) break;
    }

/* all top level HDUs up to faulty one are left intact in case of i/o error. It is up
   to the caller to call fits_close_file or fits_delete_file when this function returns
   error. */

   ngp_free_line();		/* deallocate last line (if any) */
   ngp_free_prevline();		/* deallocate cached line (if any) */
   ngp_delete_extver_tab();	/* delete extver table (if present), error ignored */
   
   *status = r;
   return(r);
 }
cfitsio/grparser.h0000644000225700000360000001313513246025103014001 0ustar  cagordonlhea/*		T E M P L A T E   P A R S E R   H E A D E R   F I L E
		=====================================================

		by Jerzy.Borkowski@obs.unige.ch

		Integral Science Data Center
		ch. d'Ecogia 16
		1290 Versoix
		Switzerland

14-Oct-98: initial release
16-Oct-98: reference to fitsio.h removed, also removed strings after #endif
		directives to make gcc -Wall not to complain
20-Oct-98: added declarations NGP_XTENSION_SIMPLE and NGP_XTENSION_FIRST
24-Oct-98: prototype of ngp_read_line() function updated.
22-Jan-99: prototype for ngp_set_extver() function added.
20-Jun-2002 Wm Pence, added support for the HIERARCH keyword convention
            (changed NGP_MAX_NAME from (20) to FLEN_KEYWORD)
*/

#ifndef	GRPARSER_H_INCLUDED
#define	GRPARSER_H_INCLUDED

#ifdef __cplusplus
extern "C" {
#endif

	/* error codes  - now defined in fitsio.h */

	/* common constants definitions */

#define	NGP_ALLOCCHUNK		(1000)
#define	NGP_MAX_INCLUDE		(10)			/* include file nesting limit */
#define	NGP_MAX_COMMENT		(80)			/* max size for comment */
#define	NGP_MAX_NAME		FLEN_KEYWORD		/* max size for KEYWORD (FITS limits it to 8 chars) */
                                                        /* except HIERARCH can have longer effective keyword names */
#define	NGP_MAX_STRING		(80)			/* max size for various strings */
#define	NGP_MAX_ARRAY_DIM	(999)			/* max. number of dimensions in array */
#define NGP_MAX_FNAME           (1000)                  /* max size of combined path+fname */
#define	NGP_MAX_ENVFILES	(10000)			/* max size of CFITSIO_INCLUDE_FILES env. variable */

#define	NGP_TOKEN_UNKNOWN	(-1)			/* token type unknown */
#define	NGP_TOKEN_INCLUDE	(0)			/* \INCLUDE token */
#define	NGP_TOKEN_GROUP		(1)			/* \GROUP token */
#define	NGP_TOKEN_END		(2)			/* \END token */
#define	NGP_TOKEN_XTENSION	(3)			/* XTENSION token */
#define	NGP_TOKEN_SIMPLE	(4)			/* SIMPLE token */
#define	NGP_TOKEN_EOF		(5)			/* End Of File pseudo token */

#define	NGP_TTYPE_UNKNOWN	(0)			/* undef (yet) token type - invalid to print/write to disk */
#define	NGP_TTYPE_BOOL		(1)			/* boolean, it is 'T' or 'F' */
#define	NGP_TTYPE_STRING	(2)			/* something withing "" or starting with letter */
#define	NGP_TTYPE_INT		(3)			/* starting with digit and not with '.' */
#define	NGP_TTYPE_REAL		(4)			/* digits + '.' */
#define	NGP_TTYPE_COMPLEX	(5)			/* 2 reals, separated with ',' */
#define	NGP_TTYPE_NULL		(6)			/* NULL token, format is : NAME = / comment */
#define	NGP_TTYPE_RAW		(7)			/* HISTORY/COMMENT/8SPACES + comment string without / */

#define	NGP_FOUND_EQUAL_SIGN	(1)			/* line contains '=' after keyword name */

#define	NGP_FORMAT_OK		(0)			/* line format OK */
#define	NGP_FORMAT_ERROR	(1)			/* line format error */

#define	NGP_NODE_INVALID	(0)			/* default node type - invalid (to catch errors) */
#define	NGP_NODE_IMAGE		(1)			/* IMAGE type */
#define	NGP_NODE_ATABLE		(2)			/* ASCII table type */
#define	NGP_NODE_BTABLE		(3)			/* BINARY table type */

#define	NGP_NON_SYSTEM_ONLY	(0)			/* save all keywords except NAXIS,BITPIX,etc.. */
#define	NGP_REALLY_ALL		(1)			/* save really all keywords */

#define	NGP_XTENSION_SIMPLE	(1)			/* HDU defined with SIMPLE T */
#define	NGP_XTENSION_FIRST	(2)			/* this is first extension in template */

#define	NGP_LINE_REREAD		(1)			/* reread line */

#define	NGP_BITPIX_INVALID	(-12345)		/* default BITPIX (to catch errors) */

	/* common macro definitions */

#ifdef	NGP_PARSER_DEBUG_MALLOC

#define	ngp_alloc(x)		dal_malloc(x)
#define	ngp_free(x)		dal_free(x)
#define	ngp_realloc(x,y)	dal_realloc(x,y)

#else

#define	ngp_alloc(x)		malloc(x)
#define	ngp_free(x)		free(x)
#define	ngp_realloc(x,y)	realloc(x,y)

#endif

	/* type definitions */

typedef struct NGP_RAW_LINE_STRUCT
      {	char	*line;
	char	*name;
	char	*value;
	int	type;
	char	*comment;
	int	format;
	int	flags;
      } NGP_RAW_LINE;


typedef union NGP_TOKVAL_UNION
      {	char	*s;		/* space allocated separately, be careful !!! */
	char	b;
	int	i;
	double	d;
	struct NGP_COMPLEX_STRUCT
	 { double re;
	   double im;
	 } c;			/* complex value */
      } NGP_TOKVAL;


typedef struct NGP_TOKEN_STRUCT
      { int		type;
        char		name[NGP_MAX_NAME];
        NGP_TOKVAL	value;
        char		comment[NGP_MAX_COMMENT];
      } NGP_TOKEN;


typedef struct NGP_HDU_STRUCT
      {	int		tokcnt;
        NGP_TOKEN	*tok;
      } NGP_HDU;


typedef struct NGP_TKDEF_STRUCT
      {	char	*name;
	int	code;
      } NGP_TKDEF;


typedef struct NGP_EXTVER_TAB_STRUCT
      {	char	*extname;
	int	version;
      } NGP_EXTVER_TAB;


	/* globally visible variables declarations */

extern	NGP_RAW_LINE	ngp_curline;
extern	NGP_RAW_LINE	ngp_prevline;

extern	int		ngp_extver_tab_size;
extern	NGP_EXTVER_TAB	*ngp_extver_tab;


	/* globally visible functions declarations */

int	ngp_get_extver(char *extname, int *version);
int	ngp_set_extver(char *extname, int version);
int	ngp_delete_extver_tab(void);
int	ngp_line_from_file(FILE *fp, char **p);
int	ngp_free_line(void);
int	ngp_free_prevline(void);
int	ngp_read_line_buffered(FILE *fp);
int	ngp_unread_line(void);
int	ngp_extract_tokens(NGP_RAW_LINE *cl);
int	ngp_include_file(char *fname);
int	ngp_read_line(int ignore_blank_lines);
int	ngp_keyword_is_write(NGP_TOKEN *ngp_tok);
int     ngp_keyword_all_write(NGP_HDU *ngph, fitsfile *ffp, int mode);
int	ngp_hdu_init(NGP_HDU *ngph);
int	ngp_hdu_clear(NGP_HDU *ngph);
int	ngp_hdu_insert_token(NGP_HDU *ngph, NGP_TOKEN *newtok);
int	ngp_append_columns(fitsfile *ff, NGP_HDU *ngph, int aftercol);
int	ngp_read_xtension(fitsfile *ff, int parent_hn, int simple_mode);
int	ngp_read_group(fitsfile *ff, char *grpname, int parent_hn);

		/* top level API function - now defined in fitsio.h */

#ifdef __cplusplus
}
#endif

#endif
cfitsio/histo.c0000644000225700000360000023426713246025103013310 0ustar  cagordonlhea/*   Globally defined histogram parameters */
#include 
#include 
#include 
#include 
#include "fitsio2.h"

typedef struct {  /*  Structure holding all the histogramming information   */
   union {        /*  the iterator work functions (ffwritehist, ffcalchist) */
      char   *b;  /*  need to do their job... passed via *userPointer.      */
      short  *i;
      int    *j;
      float  *r;
      double *d;
   } hist;

   fitsfile *tblptr;

   int   haxis, hcolnum[4], himagetype;
   long  haxis1, haxis2, haxis3, haxis4;
   float amin1, amin2, amin3, amin4;
   float maxbin1, maxbin2, maxbin3, maxbin4;
   float binsize1, binsize2, binsize3, binsize4;
   int   wtrecip, wtcolnum;
   float weight;
   char  *rowselector;

} histType;

/*--------------------------------------------------------------------------*/
int ffbins(char *binspec,   /* I - binning specification */
                   int *imagetype,      /* O - image type, TINT or TSHORT */
                   int *histaxis,       /* O - no. of axes in the histogram */
                   char colname[4][FLEN_VALUE],  /* column name for axis */
                   double *minin,        /* minimum value for each axis */
                   double *maxin,        /* maximum value for each axis */
                   double *binsizein,    /* size of bins on each axis */
                   char minname[4][FLEN_VALUE],  /* keyword name for min */
                   char maxname[4][FLEN_VALUE],  /* keyword name for max */
                   char binname[4][FLEN_VALUE],  /* keyword name for binsize */
                   double *wt,          /* weighting factor          */
                   char *wtname,        /* keyword or column name for weight */
                   int *recip,          /* the reciprocal of the weight? */
                   int *status)
{
/*
   Parse the input binning specification string, returning the binning
   parameters.  Supports up to 4 dimensions.  The binspec string has
   one of these forms:

   bin binsize                  - 2D histogram with binsize on each axis
   bin xcol                     - 1D histogram on column xcol
   bin (xcol, ycol) = binsize   - 2D histogram with binsize on each axis
   bin x=min:max:size, y=min:max:size, z..., t... 
   bin x=:max, y=::size
   bin x=size, y=min::size

   most other reasonable combinations are supported.        
*/
    int ii, slen, defaulttype;
    char *ptr, tmpname[30], *file_expr = NULL;
    double  dummy;

    if (*status > 0)
         return(*status);

    /* set the default values */
    *histaxis = 2;
    *imagetype = TINT;
    defaulttype = 1;
    *wt = 1.;
    *recip = 0;
    *wtname = '\0';

    /* set default values */
    for (ii = 0; ii < 4; ii++)
    {
        *colname[ii] = '\0';
        *minname[ii] = '\0';
        *maxname[ii] = '\0';
        *binname[ii] = '\0';
        minin[ii] = DOUBLENULLVALUE;  /* undefined values */
        maxin[ii] = DOUBLENULLVALUE;
        binsizein[ii] = DOUBLENULLVALUE;
    }

    ptr = binspec + 3;  /* skip over 'bin' */

    if (*ptr == 'i' )  /* bini */
    {
        *imagetype = TSHORT;
        defaulttype = 0;
        ptr++;
    }
    else if (*ptr == 'j' )  /* binj; same as default */
    {
        defaulttype = 0;
        ptr ++;
    }
    else if (*ptr == 'r' )  /* binr */
    {
        *imagetype = TFLOAT;
        defaulttype = 0;
        ptr ++;
    }
    else if (*ptr == 'd' )  /* bind */
    {
        *imagetype = TDOUBLE;
        defaulttype = 0;
        ptr ++;
    }
    else if (*ptr == 'b' )  /* binb */
    {
        *imagetype = TBYTE;
        defaulttype = 0;
        ptr ++;
    }

    if (*ptr == '\0')  /* use all defaults for other parameters */
        return(*status);
    else if (*ptr != ' ')  /* must be at least one blank */
    {
        ffpmsg("binning specification syntax error:");
        ffpmsg(binspec);
        return(*status = URL_PARSE_ERROR);
    }

    while (*ptr == ' ')  /* skip over blanks */
           ptr++;

    if (*ptr == '\0')   /* no other parameters; use defaults */
        return(*status);

    /* Check if need to import expression from a file */

    if( *ptr=='@' ) {
       if( ffimport_file( ptr+1, &file_expr, status ) ) return(*status);
       ptr = file_expr;
       while (*ptr == ' ')
               ptr++;       /* skip leading white space... again */
    }

    if (*ptr == '(' )
    {
        /* this must be the opening parenthesis around a list of column */
        /* names, optionally followed by a '=' and the binning spec. */

        for (ii = 0; ii < 4; ii++)
        {
            ptr++;               /* skip over the '(', ',', or ' ') */
            while (*ptr == ' ')  /* skip over blanks */
                ptr++;

            slen = strcspn(ptr, " ,)");
            strncat(colname[ii], ptr, slen); /* copy 1st column name */

            ptr += slen;
            while (*ptr == ' ')  /* skip over blanks */
                ptr++;

            if (*ptr == ')' )   /* end of the list of names */
            {
                *histaxis = ii + 1;
                break;
            }
        }

        if (ii == 4)   /* too many names in the list , or missing ')'  */
        {
            ffpmsg(
 "binning specification has too many column names or is missing closing ')':");
            ffpmsg(binspec);
	    if( file_expr ) free( file_expr );
            return(*status = URL_PARSE_ERROR);
        }

        ptr++;  /* skip over the closing parenthesis */
        while (*ptr == ' ')  /* skip over blanks */
            ptr++;

        if (*ptr == '\0') {
	    if( file_expr ) free( file_expr );
            return(*status);  /* parsed the entire string */
	}

        else if (*ptr != '=')  /* must be an equals sign now*/
        {
            ffpmsg("illegal binning specification in URL:");
            ffpmsg(" an equals sign '=' must follow the column names");
            ffpmsg(binspec);
	    if( file_expr ) free( file_expr );
            return(*status = URL_PARSE_ERROR);
        }

        ptr++;  /* skip over the equals sign */
        while (*ptr == ' ')  /* skip over blanks */
            ptr++;

        /* get the single range specification for all the columns */
        ffbinr(&ptr, tmpname, minin,
                                     maxin, binsizein, minname[0],
                                     maxname[0], binname[0], status);
        if (*status > 0)
        {
            ffpmsg("illegal binning specification in URL:");
            ffpmsg(binspec);
	    if( file_expr ) free( file_expr );
            return(*status);
        }

        for (ii = 1; ii < *histaxis; ii++)
        {
            minin[ii] = minin[0];
            maxin[ii] = maxin[0];
            binsizein[ii] = binsizein[0];
            strcpy(minname[ii], minname[0]);
            strcpy(maxname[ii], maxname[0]);
            strcpy(binname[ii], binname[0]);
        }

        while (*ptr == ' ')  /* skip over blanks */
            ptr++;

        if (*ptr == ';')
            goto getweight;   /* a weighting factor is specified */

        if (*ptr != '\0')  /* must have reached end of string */
        {
            ffpmsg("illegal syntax after binning range specification in URL:");
            ffpmsg(binspec);
	    if( file_expr ) free( file_expr );
            return(*status = URL_PARSE_ERROR);
        }

        return(*status);
    }             /* end of case with list of column names in ( )  */

    /* if we've reached this point, then the binning specification */
    /* must be of the form: XCOL = min:max:binsize, YCOL = ...     */
    /* where the column name followed by '=' are optional.         */
    /* If the column name is not specified, then use the default name */

    for (ii = 0; ii < 4; ii++) /* allow up to 4 histogram dimensions */
    {
        ffbinr(&ptr, colname[ii], &minin[ii],
                                     &maxin[ii], &binsizein[ii], minname[ii],
                                     maxname[ii], binname[ii], status);

        if (*status > 0)
        {
            ffpmsg("illegal syntax in binning range specification in URL:");
            ffpmsg(binspec);
	    if( file_expr ) free( file_expr );
            return(*status);
        }

        if (*ptr == '\0' || *ptr == ';')
            break;        /* reached the end of the string */

        if (*ptr == ' ')
        {
            while (*ptr == ' ')  /* skip over blanks */
                ptr++;

            if (*ptr == '\0' || *ptr == ';')
                break;        /* reached the end of the string */

            if (*ptr == ',')
                ptr++;  /* comma separates the next column specification */
        }
        else if (*ptr == ',')
        {          
            ptr++;  /* comma separates the next column specification */
        }
        else
        {
            ffpmsg("illegal characters following binning specification in URL:");
            ffpmsg(binspec);
	    if( file_expr ) free( file_expr );
            return(*status = URL_PARSE_ERROR);
        }
    }

    if (ii == 4)
    {
        /* there are yet more characters in the string */
        ffpmsg("illegal binning specification in URL:");
        ffpmsg("apparently greater than 4 histogram dimensions");
        ffpmsg(binspec);
        return(*status = URL_PARSE_ERROR);
    }
    else
        *histaxis = ii + 1;

    /* special case: if a single number was entered it should be      */
    /* interpreted as the binning factor for the default X and Y axes */

    if (*histaxis == 1 && *colname[0] == '\0' && 
         minin[0] == DOUBLENULLVALUE && maxin[0] == DOUBLENULLVALUE)
    {
        *histaxis = 2;
        binsizein[1] = binsizein[0];
    }

getweight:
    if (*ptr == ';')  /* looks like a weighting factor is given */
    {
        ptr++;
       
        while (*ptr == ' ')  /* skip over blanks */
            ptr++;

        recip = 0;
        if (*ptr == '/')
        {
            *recip = 1;  /* the reciprocal of the weight is entered */
            ptr++;

            while (*ptr == ' ')  /* skip over blanks */
                ptr++;
        }

        /* parse the weight as though it were a binrange. */
        /* either a column name or a numerical value will be returned */

        ffbinr(&ptr, wtname, &dummy, &dummy, wt, tmpname,
                                     tmpname, tmpname, status);

        if (*status > 0)
        {
            ffpmsg("illegal binning weight specification in URL:");
            ffpmsg(binspec);
	    if( file_expr ) free( file_expr );
            return(*status);
        }

        /* creat a float datatype histogram by default, if weight */
        /* factor is not = 1.0  */

        if ( (defaulttype && *wt != 1.0) || (defaulttype && *wtname) )
            *imagetype = TFLOAT;
    }

    while (*ptr == ' ')  /* skip over blanks */
         ptr++;

    if (*ptr != '\0')  /* should have reached the end of string */
    {
        ffpmsg("illegal syntax after binning weight specification in URL:");
        ffpmsg(binspec);
        *status = URL_PARSE_ERROR;
    }

    if( file_expr ) free( file_expr );
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffbinr(char **ptr, 
                   char *colname, 
                   double *minin,
                   double *maxin, 
                   double *binsizein,
                   char *minname,
                   char *maxname,
                   char *binname,
                   int *status)
/*
   Parse the input binning range specification string, returning 
   the column name, histogram min and max values, and bin size.
*/
{
    int slen, isanumber;
    char token[FLEN_VALUE];

    if (*status > 0)
        return(*status);

    slen = fits_get_token(ptr, " ,=:;", token, &isanumber); /* get 1st token */

    if (slen == 0 && (**ptr == '\0' || **ptr == ',' || **ptr == ';') )
        return(*status);   /* a null range string */

    if (!isanumber && **ptr != ':')
    {
        /* this looks like the column name */

        if (token[0] == '#' && isdigit((int) token[1]) )
        {
            /* omit the leading '#' in the column number */
            strcpy(colname, token+1);
        }
        else
            strcpy(colname, token);

        while (**ptr == ' ')  /* skip over blanks */
             (*ptr)++;

        if (**ptr != '=')
            return(*status);  /* reached the end */

        (*ptr)++;   /* skip over the = sign */

        while (**ptr == ' ')  /* skip over blanks */
             (*ptr)++;

        slen = fits_get_token(ptr, " ,:;", token, &isanumber); /* get token */
    }

    if (**ptr != ':')
    {
        /* this is the first token, and since it is not followed by */
        /* a ':' this must be the binsize token */
        if (!isanumber)
            strcpy(binname, token);
        else
            *binsizein =  strtod(token, NULL);

        return(*status);  /* reached the end */
    }
    else
    {
        /* the token contains the min value */
        if (slen)
        {
            if (!isanumber)
                strcpy(minname, token);
            else
                *minin = strtod(token, NULL);
        }
    }

    (*ptr)++;  /* skip the colon between the min and max values */
    slen = fits_get_token(ptr, " ,:;", token, &isanumber); /* get token */

    /* the token contains the max value */
    if (slen)
    {
        if (!isanumber)
            strcpy(maxname, token);
        else
            *maxin = strtod(token, NULL);
    }

    if (**ptr != ':')
        return(*status);  /* reached the end; no binsize token */

    (*ptr)++;  /* skip the colon between the max and binsize values */
    slen = fits_get_token(ptr, " ,:;", token, &isanumber); /* get token */

    /* the token contains the binsize value */
    if (slen)
    {
        if (!isanumber)
            strcpy(binname, token);
        else
            *binsizein = strtod(token, NULL);
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffhist2(fitsfile **fptr,  /* IO - pointer to table with X and Y cols;    */
                             /*     on output, points to histogram image    */
           char *outfile,    /* I - name for the output histogram file      */
           int imagetype,    /* I - datatype for image: TINT, TSHORT, etc   */
           int naxis,        /* I - number of axes in the histogram image   */
           char colname[4][FLEN_VALUE],   /* I - column names               */
           double *minin,     /* I - minimum histogram value, for each axis */
           double *maxin,     /* I - maximum histogram value, for each axis */
           double *binsizein, /* I - bin size along each axis               */
           char minname[4][FLEN_VALUE], /* I - optional keywords for min    */
           char maxname[4][FLEN_VALUE], /* I - optional keywords for max    */
           char binname[4][FLEN_VALUE], /* I - optional keywords for binsize */
           double weightin,        /* I - binning weighting factor          */
           char wtcol[FLEN_VALUE], /* I - optional keyword or col for weight*/
           int recip,              /* I - use reciprocal of the weight?     */
           char *selectrow,        /* I - optional array (length = no. of   */
                             /* rows in the table).  If the element is true */
                             /* then the corresponding row of the table will*/
                             /* be included in the histogram, otherwise the */
                             /* row will be skipped.  Ingnored if *selectrow*/
                             /* is equal to NULL.                           */
           int *status)
{
    fitsfile *histptr;
    int   bitpix, colnum[4], wtcolnum;
    long haxes[4];
    float amin[4], amax[4], binsize[4],  weight;

    if (*status > 0)
        return(*status);

    if (naxis > 4)
    {
        ffpmsg("histogram has more than 4 dimensions");
        return(*status = BAD_DIMEN);
    }

    /* reset position to the correct HDU if necessary */
    if ((*fptr)->HDUposition != ((*fptr)->Fptr)->curhdu)
        ffmahd(*fptr, ((*fptr)->HDUposition) + 1, NULL, status);

    if (imagetype == TBYTE)
        bitpix = BYTE_IMG;
    else if (imagetype == TSHORT)
        bitpix = SHORT_IMG;
    else if (imagetype == TINT)
        bitpix = LONG_IMG;
    else if (imagetype == TFLOAT)
        bitpix = FLOAT_IMG;
    else if (imagetype == TDOUBLE)
        bitpix = DOUBLE_IMG;
    else
        return(*status = BAD_DATATYPE);

    
    /*    Calculate the binning parameters:    */
    /*   columm numbers, axes length, min values,  max values, and binsizes.  */

    if (fits_calc_binning(
      *fptr, naxis, colname, minin, maxin, binsizein, minname, maxname, binname,
      colnum,  haxes, amin, amax, binsize, status) > 0)
    {
        ffpmsg("failed to determine binning parameters");
        return(*status);
    }
 
    /* get the histogramming weighting factor, if any */
    if (*wtcol)
    {
        /* first, look for a keyword with the weight value */
        if (ffgky(*fptr, TFLOAT, wtcol, &weight, NULL, status) )
        {
            /* not a keyword, so look for column with this name */
            *status = 0;

            /* get the column number in the table */
            if (ffgcno(*fptr, CASEINSEN, wtcol, &wtcolnum, status) > 0)
            {
               ffpmsg(
               "keyword or column for histogram weights doesn't exist: ");
               ffpmsg(wtcol);
               return(*status);
            }

            weight = FLOATNULLVALUE;
        }
    }
    else
        weight = (float) weightin;

    if (weight <= 0. && weight != FLOATNULLVALUE)
    {
        ffpmsg("Illegal histogramming weighting factor <= 0.");
        return(*status = URL_PARSE_ERROR);
    }

    if (recip && weight != FLOATNULLVALUE)
       /* take reciprocal of weight */
       weight = (float) (1.0 / weight);

    /* size of histogram is now known, so create temp output file */
    if (fits_create_file(&histptr, outfile, status) > 0)
    {
        ffpmsg("failed to create temp output file for histogram");
        return(*status);
    }

    /* create output FITS image HDU */
    if (ffcrim(histptr, bitpix, naxis, haxes, status) > 0)
    {
        ffpmsg("failed to create output histogram FITS image");
        return(*status);
    }

    /* copy header keywords, converting pixel list WCS keywords to image WCS form */
    if (fits_copy_pixlist2image(*fptr, histptr, 9, naxis, colnum, status) > 0)
    {
        ffpmsg("failed to copy pixel list keywords to new histogram header");
        return(*status);
    }

    /* if the table columns have no WCS keywords, then write default keywords */
    fits_write_keys_histo(*fptr, histptr, naxis, colnum, status);
    
    /* update the WCS keywords for the ref. pixel location, and pixel size */
    fits_rebin_wcs(histptr, naxis, amin, binsize,  status);      
    
    /* now compute the output image by binning the column values */
    if (fits_make_hist(*fptr, histptr, bitpix, naxis, haxes, colnum, amin, amax,
        binsize, weight, wtcolnum, recip, selectrow, status) > 0)
    {
        ffpmsg("failed to calculate new histogram values");
        return(*status);
    }
              
    /* finally, close the original file and return ptr to the new image */
    ffclos(*fptr, status);
    *fptr = histptr;

    return(*status);
}
/*--------------------------------------------------------------------------*/

/* ffhist3: same as ffhist2, but does not close the original file */
/*  and/or replace the original file pointer */
fitsfile *ffhist3(fitsfile *fptr, /* I - ptr to table with X and Y cols*/
           char *outfile,    /* I - name for the output histogram file      */
           int imagetype,    /* I - datatype for image: TINT, TSHORT, etc   */
           int naxis,        /* I - number of axes in the histogram image   */
           char colname[4][FLEN_VALUE],   /* I - column names               */
           double *minin,     /* I - minimum histogram value, for each axis */
           double *maxin,     /* I - maximum histogram value, for each axis */
           double *binsizein, /* I - bin size along each axis               */
           char minname[4][FLEN_VALUE], /* I - optional keywords for min    */
           char maxname[4][FLEN_VALUE], /* I - optional keywords for max    */
           char binname[4][FLEN_VALUE], /* I - optional keywords for binsize */
           double weightin,        /* I - binning weighting factor          */
           char wtcol[FLEN_VALUE], /* I - optional keyword or col for weight*/
           int recip,              /* I - use reciprocal of the weight?     */
           char *selectrow,        /* I - optional array (length = no. of   */
                             /* rows in the table).  If the element is true */
                             /* then the corresponding row of the table will*/
                             /* be included in the histogram, otherwise the */
                             /* row will be skipped.  Ingnored if *selectrow*/
                             /* is equal to NULL.                           */
           int *status)
{
    fitsfile *histptr;
    int   bitpix, colnum[4], wtcolnum;
    long haxes[4];
    float amin[4], amax[4], binsize[4],  weight;

    if (*status > 0)
        return(NULL);

    if (naxis > 4)
    {
        ffpmsg("histogram has more than 4 dimensions");
	*status = BAD_DIMEN;
        return(NULL);
    }

    /* reset position to the correct HDU if necessary */
    if ((fptr)->HDUposition != ((fptr)->Fptr)->curhdu)
        ffmahd(fptr, ((fptr)->HDUposition) + 1, NULL, status);

    if (imagetype == TBYTE)
        bitpix = BYTE_IMG;
    else if (imagetype == TSHORT)
        bitpix = SHORT_IMG;
    else if (imagetype == TINT)
        bitpix = LONG_IMG;
    else if (imagetype == TFLOAT)
        bitpix = FLOAT_IMG;
    else if (imagetype == TDOUBLE)
        bitpix = DOUBLE_IMG;
    else{
        *status = BAD_DATATYPE;
        return(NULL);
    }
    
    /*    Calculate the binning parameters:    */
    /*   columm numbers, axes length, min values,  max values, and binsizes.  */

    if (fits_calc_binning(
      fptr, naxis, colname, minin, maxin, binsizein, minname, maxname, binname,
      colnum, haxes, amin, amax, binsize, status) > 0)
    {
       ffpmsg("failed to determine binning parameters");
        return(NULL);
    }
 
    /* get the histogramming weighting factor, if any */
    if (*wtcol)
    {
        /* first, look for a keyword with the weight value */
        if (fits_read_key(fptr, TFLOAT, wtcol, &weight, NULL, status) )
        {
            /* not a keyword, so look for column with this name */
            *status = 0;

            /* get the column number in the table */
            if (ffgcno(fptr, CASEINSEN, wtcol, &wtcolnum, status) > 0)
            {
               ffpmsg(
               "keyword or column for histogram weights doesn't exist: ");
               ffpmsg(wtcol);
               return(NULL);
            }

            weight = FLOATNULLVALUE;
        }
    }
    else
        weight = (float) weightin;

    if (weight <= 0. && weight != FLOATNULLVALUE)
    {
        ffpmsg("Illegal histogramming weighting factor <= 0.");
	*status = URL_PARSE_ERROR;
        return(NULL);
    }

    if (recip && weight != FLOATNULLVALUE)
       /* take reciprocal of weight */
       weight = (float) (1.0 / weight);

    /* size of histogram is now known, so create temp output file */
    if (fits_create_file(&histptr, outfile, status) > 0)
    {
        ffpmsg("failed to create temp output file for histogram");
        return(NULL);
    }

    /* create output FITS image HDU */
    if (ffcrim(histptr, bitpix, naxis, haxes, status) > 0)
    {
        ffpmsg("failed to create output histogram FITS image");
        return(NULL);
    }

    /* copy header keywords, converting pixel list WCS keywords to image WCS */
    if (fits_copy_pixlist2image(fptr, histptr, 9, naxis, colnum, status) > 0)
    {
        ffpmsg("failed to copy pixel list keywords to new histogram header");
        return(NULL);
    }

    /* if the table columns have no WCS keywords, then write default keywords */
    fits_write_keys_histo(fptr, histptr, naxis, colnum, status);
    
    /* update the WCS keywords for the ref. pixel location, and pixel size */
    fits_rebin_wcs(histptr, naxis, amin, binsize,  status);      
    
    /* now compute the output image by binning the column values */
    if (fits_make_hist(fptr, histptr, bitpix, naxis, haxes, colnum, amin, amax,
        binsize, weight, wtcolnum, recip, selectrow, status) > 0)
    {
        ffpmsg("failed to calculate new histogram values");
        return(NULL);
    }
              
    return(histptr);
}
/*--------------------------------------------------------------------------*/
int ffhist(fitsfile **fptr,  /* IO - pointer to table with X and Y cols;    */
                             /*     on output, points to histogram image    */
           char *outfile,    /* I - name for the output histogram file      */
           int imagetype,    /* I - datatype for image: TINT, TSHORT, etc   */
           int naxis,        /* I - number of axes in the histogram image   */
           char colname[4][FLEN_VALUE],   /* I - column names               */
           double *minin,     /* I - minimum histogram value, for each axis */
           double *maxin,     /* I - maximum histogram value, for each axis */
           double *binsizein, /* I - bin size along each axis               */
           char minname[4][FLEN_VALUE], /* I - optional keywords for min    */
           char maxname[4][FLEN_VALUE], /* I - optional keywords for max    */
           char binname[4][FLEN_VALUE], /* I - optional keywords for binsize */
           double weightin,        /* I - binning weighting factor          */
           char wtcol[FLEN_VALUE], /* I - optional keyword or col for weight*/
           int recip,              /* I - use reciprocal of the weight?     */
           char *selectrow,        /* I - optional array (length = no. of   */
                             /* rows in the table).  If the element is true */
                             /* then the corresponding row of the table will*/
                             /* be included in the histogram, otherwise the */
                             /* row will be skipped.  Ingnored if *selectrow*/
                             /* is equal to NULL.                           */
           int *status)
{
    int ii, datatype, repeat, imin, imax, ibin, bitpix, tstatus, use_datamax = 0;
    long haxes[4];
    fitsfile *histptr;
    char errmsg[FLEN_ERRMSG], keyname[FLEN_KEYWORD], card[FLEN_CARD];
    tcolumn *colptr;
    iteratorCol imagepars[1];
    int n_cols = 1, nkeys;
    long  offset = 0;
    long n_per_loop = -1;  /* force whole array to be passed at one time */
    histType histData;    /* Structure holding histogram info for iterator */
    
    float amin[4], amax[4], binsize[4], maxbin[4];
    float datamin = FLOATNULLVALUE, datamax = FLOATNULLVALUE;
    char svalue[FLEN_VALUE];
    double dvalue;
    char cpref[4][FLEN_VALUE];
    char *cptr;

    if (*status > 0)
        return(*status);

    if (naxis > 4)
    {
        ffpmsg("histogram has more than 4 dimensions");
        return(*status = BAD_DIMEN);
    }

    /* reset position to the correct HDU if necessary */
    if ((*fptr)->HDUposition != ((*fptr)->Fptr)->curhdu)
        ffmahd(*fptr, ((*fptr)->HDUposition) + 1, NULL, status);

    histData.tblptr     = *fptr;
    histData.himagetype = imagetype;
    histData.haxis      = naxis;
    histData.rowselector = selectrow;

    if (imagetype == TBYTE)
        bitpix = BYTE_IMG;
    else if (imagetype == TSHORT)
        bitpix = SHORT_IMG;
    else if (imagetype == TINT)
        bitpix = LONG_IMG;
    else if (imagetype == TFLOAT)
        bitpix = FLOAT_IMG;
    else if (imagetype == TDOUBLE)
        bitpix = DOUBLE_IMG;
    else
        return(*status = BAD_DATATYPE);

    /* The CPREF keyword, if it exists, gives the preferred columns. */
    /* Otherwise, assume "X", "Y", "Z", and "T"  */

    tstatus = 0;
    ffgky(*fptr, TSTRING, "CPREF", cpref[0], NULL, &tstatus);

    if (!tstatus)
    {
        /* Preferred column names are given;  separate them */
        cptr = cpref[0];

        /* the first preferred axis... */
        while (*cptr != ',' && *cptr != '\0')
           cptr++;

        if (*cptr != '\0')
        {
           *cptr = '\0';
           cptr++;
           while (*cptr == ' ')
               cptr++;

           strcpy(cpref[1], cptr);
           cptr = cpref[1];

          /* the second preferred axis... */
          while (*cptr != ',' && *cptr != '\0')
             cptr++;

          if (*cptr != '\0')
          {
             *cptr = '\0';
             cptr++;
             while (*cptr == ' ')
                 cptr++;

             strcpy(cpref[2], cptr);
             cptr = cpref[2];

            /* the third preferred axis... */
            while (*cptr != ',' && *cptr != '\0')
               cptr++;

            if (*cptr != '\0')
            {
               *cptr = '\0';
               cptr++;
               while (*cptr == ' ')
                   cptr++;

               strcpy(cpref[3], cptr);

            }
          }
        }
    }

    for (ii = 0; ii < naxis; ii++)
    {

      /* get the min, max, and binsize values from keywords, if specified */

      if (*minname[ii])
      {
         if (ffgky(*fptr, TDOUBLE, minname[ii], &minin[ii], NULL, status) )
         {
             ffpmsg("error reading histogramming minimum keyword");
             ffpmsg(minname[ii]);
             return(*status);
         }
      }

      if (*maxname[ii])
      {
         if (ffgky(*fptr, TDOUBLE, maxname[ii], &maxin[ii], NULL, status) )
         {
             ffpmsg("error reading histogramming maximum keyword");
             ffpmsg(maxname[ii]);
             return(*status);
         }
      }

      if (*binname[ii])
      {
         if (ffgky(*fptr, TDOUBLE, binname[ii], &binsizein[ii], NULL, status) )
         {
             ffpmsg("error reading histogramming binsize keyword");
             ffpmsg(binname[ii]);
             return(*status);
         }
      }

      if (binsizein[ii] == 0.)
      {
        ffpmsg("error: histogram binsize = 0");
        return(*status = ZERO_SCALE);
      }

      if (*colname[ii] == '\0')
      {
         strcpy(colname[ii], cpref[ii]); /* try using the preferred column */
         if (*colname[ii] == '\0')
         {
           if (ii == 0)
              strcpy(colname[ii], "X");
           else if (ii == 1)
              strcpy(colname[ii], "Y");
           else if (ii == 2)
              strcpy(colname[ii], "Z");
           else if (ii == 3)
              strcpy(colname[ii], "T");
         }
      }

      /* get the column number in the table */
      if (ffgcno(*fptr, CASEINSEN, colname[ii], histData.hcolnum+ii, status)
              > 0)
      {
        strcpy(errmsg, "column for histogram axis doesn't exist: ");
        strcat(errmsg, colname[ii]);
        ffpmsg(errmsg);
        return(*status);
      }

      colptr = ((*fptr)->Fptr)->tableptr;
      colptr += (histData.hcolnum[ii] - 1);

      repeat = (int) colptr->trepeat;  /* vector repeat factor of the column */
      if (repeat > 1)
      {
        strcpy(errmsg, "Can't bin a vector column: ");
        strcat(errmsg, colname[ii]);
        ffpmsg(errmsg);
        return(*status = BAD_DATATYPE);
      }

      /* get the datatype of the column */
      fits_get_coltype(*fptr, histData.hcolnum[ii], &datatype,
         NULL, NULL, status);

      if (datatype < 0 || datatype == TSTRING)
      {
        strcpy(errmsg, "Inappropriate datatype; can't bin this column: ");
        strcat(errmsg, colname[ii]);
        ffpmsg(errmsg);
        return(*status = BAD_DATATYPE);
      }

      /* use TLMINn and TLMAXn keyword values if min and max were not given */
      /* else use actual data min and max if TLMINn and TLMAXn don't exist */
 
      if (minin[ii] == DOUBLENULLVALUE)
      {
        ffkeyn("TLMIN", histData.hcolnum[ii], keyname, status);
        if (ffgky(*fptr, TFLOAT, keyname, amin+ii, NULL, status) > 0)
        {
            /* use actual data minimum value for the histogram minimum */
            *status = 0;
            if (fits_get_col_minmax(*fptr, histData.hcolnum[ii], amin+ii, &datamax, status) > 0)
            {
                strcpy(errmsg, "Error calculating datamin and datamax for column: ");
                strcat(errmsg, colname[ii]);
                ffpmsg(errmsg);
                return(*status);
            }
         }
      }
      else
      {
        amin[ii] = (float) minin[ii];
      }

      if (maxin[ii] == DOUBLENULLVALUE)
      {
        ffkeyn("TLMAX", histData.hcolnum[ii], keyname, status);
        if (ffgky(*fptr, TFLOAT, keyname, &amax[ii], NULL, status) > 0)
        {
          *status = 0;
          if(datamax != FLOATNULLVALUE)  /* already computed max value */
          {
             amax[ii] = datamax;
          }
          else
          {
             /* use actual data maximum value for the histogram maximum */
             if (fits_get_col_minmax(*fptr, histData.hcolnum[ii], &datamin, &amax[ii], status) > 0)
             {
                 strcpy(errmsg, "Error calculating datamin and datamax for column: ");
                 strcat(errmsg, colname[ii]);
                 ffpmsg(errmsg);
                 return(*status);
             }
          }
        }
        use_datamax = 1;  /* flag that the max was determined by the data values */
                          /* and not specifically set by the calling program */
      }
      else
      {
        amax[ii] = (float) maxin[ii];
      }

      /* use TDBINn keyword or else 1 if bin size is not given */
      if (binsizein[ii] == DOUBLENULLVALUE)
      {
         tstatus = 0;
         ffkeyn("TDBIN", histData.hcolnum[ii], keyname, &tstatus);

         if (ffgky(*fptr, TDOUBLE, keyname, binsizein + ii, NULL, &tstatus) > 0)
         {
	    /* make at least 10 bins */
            binsizein[ii] = (amax[ii] - amin[ii]) / 10. ;
            if (binsizein[ii] > 1.)
                binsizein[ii] = 1.;  /* use default bin size */
         }
      }

      if ( (amin[ii] > amax[ii] && binsizein[ii] > 0. ) ||
           (amin[ii] < amax[ii] && binsizein[ii] < 0. ) )
          binsize[ii] = (float) -binsizein[ii];  /* reverse the sign of binsize */
      else
          binsize[ii] =  (float) binsizein[ii];  /* binsize has the correct sign */

      ibin = (int) binsize[ii];
      imin = (int) amin[ii];
      imax = (int) amax[ii];

      /* Determine the range and number of bins in the histogram. This  */
      /* depends on whether the input columns are integer or floats, so */
      /* treat each case separately.                                    */

      if (datatype <= TLONG && (float) imin == amin[ii] &&
                               (float) imax == amax[ii] &&
                               (float) ibin == binsize[ii] )
      {
        /* This is an integer column and integer limits were entered. */
        /* Shift the lower and upper histogramming limits by 0.5, so that */
        /* the values fall in the center of the bin, not on the edge. */

        haxes[ii] = (imax - imin) / ibin + 1;  /* last bin may only */
                                               /* be partially full */
        maxbin[ii] = (float) (haxes[ii] + 1.);  /* add 1. instead of .5 to avoid roundoff */

        if (amin[ii] < amax[ii])
        {
          amin[ii] = (float) (amin[ii] - 0.5);
          amax[ii] = (float) (amax[ii] + 0.5);
        }
        else
        {
          amin[ii] = (float) (amin[ii] + 0.5);
          amax[ii] = (float) (amax[ii] - 0.5);
        }
      }
      else if (use_datamax)  
      {
        /* Either the column datatype and/or the limits are floating point, */
        /* and the histogram limits are being defined by the min and max */
        /* values of the array.  Add 1 to the number of histogram bins to */
        /* make sure that pixels that are equal to the maximum or are */
        /* in the last partial bin are included.  */

        maxbin[ii] = (amax[ii] - amin[ii]) / binsize[ii]; 
        haxes[ii] = (long) (maxbin[ii] + 1);
      }
      else  
      {
        /*  float datatype column and/or limits, and the maximum value to */
        /*  include in the histogram is specified by the calling program. */
        /*  The lower limit is inclusive, but upper limit is exclusive    */
        maxbin[ii] = (amax[ii] - amin[ii]) / binsize[ii];
        haxes[ii] = (long) maxbin[ii];

        if (amin[ii] < amax[ii])
        {
          if (amin[ii] + (haxes[ii] * binsize[ii]) < amax[ii])
            haxes[ii]++;   /* need to include another partial bin */
        }
        else
        {
          if (amin[ii] + (haxes[ii] * binsize[ii]) > amax[ii])
            haxes[ii]++;   /* need to include another partial bin */
        }
      }
    }

       /* get the histogramming weighting factor */
    if (*wtcol)
    {
        /* first, look for a keyword with the weight value */
        if (ffgky(*fptr, TFLOAT, wtcol, &histData.weight, NULL, status) )
        {
            /* not a keyword, so look for column with this name */
            *status = 0;

            /* get the column number in the table */
            if (ffgcno(*fptr, CASEINSEN, wtcol, &histData.wtcolnum, status) > 0)
            {
               ffpmsg(
               "keyword or column for histogram weights doesn't exist: ");
               ffpmsg(wtcol);
               return(*status);
            }

            histData.weight = FLOATNULLVALUE;
        }
    }
    else
        histData.weight = (float) weightin;

    if (histData.weight <= 0. && histData.weight != FLOATNULLVALUE)
    {
        ffpmsg("Illegal histogramming weighting factor <= 0.");
        return(*status = URL_PARSE_ERROR);
    }

    if (recip && histData.weight != FLOATNULLVALUE)
       /* take reciprocal of weight */
       histData.weight = (float) (1.0 / histData.weight);

    histData.wtrecip = recip;
        
    /* size of histogram is now known, so create temp output file */
    if (ffinit(&histptr, outfile, status) > 0)
    {
        ffpmsg("failed to create temp output file for histogram");
        return(*status);
    }

    if (ffcrim(histptr, bitpix, histData.haxis, haxes, status) > 0)
    {
        ffpmsg("failed to create primary array histogram in temp file");
        ffclos(histptr, status);
        return(*status);
    }

    /* copy all non-structural keywords from the table to the image */
    fits_get_hdrspace(*fptr, &nkeys, NULL, status);
    for (ii = 1; ii <= nkeys; ii++)
    {
       fits_read_record(*fptr, ii, card, status);
       if (fits_get_keyclass(card) >= 120)
           fits_write_record(histptr, card, status);
    }           

    /* Set global variables with histogram parameter values.    */
    /* Use separate scalar variables rather than arrays because */
    /* it is more efficient when computing the histogram.       */

    histData.amin1 = amin[0];
    histData.maxbin1 = maxbin[0];
    histData.binsize1 = binsize[0];
    histData.haxis1 = haxes[0];

    if (histData.haxis > 1)
    {
      histData.amin2 = amin[1];
      histData.maxbin2 = maxbin[1];
      histData.binsize2 = binsize[1];
      histData.haxis2 = haxes[1];

      if (histData.haxis > 2)
      {
        histData.amin3 = amin[2];
        histData.maxbin3 = maxbin[2];
        histData.binsize3 = binsize[2];
        histData.haxis3 = haxes[2];

        if (histData.haxis > 3)
        {
          histData.amin4 = amin[3];
          histData.maxbin4 = maxbin[3];
          histData.binsize4 = binsize[3];
          histData.haxis4 = haxes[3];
        }
      }
    }

    /* define parameters of image for the iterator function */
    fits_iter_set_file(imagepars, histptr);        /* pointer to image */
    fits_iter_set_datatype(imagepars, imagetype);  /* image datatype   */
    fits_iter_set_iotype(imagepars, OutputCol);    /* image is output  */

    /* call the iterator function to write out the histogram image */
    if (fits_iterate_data(n_cols, imagepars, offset, n_per_loop,
                          ffwritehisto, (void*)&histData, status) )
         return(*status);

    /* write the World Coordinate System (WCS) keywords */
    /* create default values if WCS keywords are not present in the table */
    for (ii = 0; ii < histData.haxis; ii++)
    {
     /*  CTYPEn  */
       tstatus = 0;
       ffkeyn("TCTYP", histData.hcolnum[ii], keyname, &tstatus);
       ffgky(*fptr, TSTRING, keyname, svalue, NULL, &tstatus);
       if (tstatus)
       {               /* just use column name as the type */
          tstatus = 0;
          ffkeyn("TTYPE", histData.hcolnum[ii], keyname, &tstatus);
          ffgky(*fptr, TSTRING, keyname, svalue, NULL, &tstatus);
       }

       if (!tstatus)
       {
        ffkeyn("CTYPE", ii + 1, keyname, &tstatus);
        ffpky(histptr, TSTRING, keyname, svalue, "Coordinate Type", &tstatus);
       }
       else
          tstatus = 0;

     /*  CUNITn  */
       ffkeyn("TCUNI", histData.hcolnum[ii], keyname, &tstatus);
       ffgky(*fptr, TSTRING, keyname, svalue, NULL, &tstatus);
       if (tstatus)
       {         /* use the column units */
          tstatus = 0;
          ffkeyn("TUNIT", histData.hcolnum[ii], keyname, &tstatus);
          ffgky(*fptr, TSTRING, keyname, svalue, NULL, &tstatus);
       }

       if (!tstatus)
       {
        ffkeyn("CUNIT", ii + 1, keyname, &tstatus);
        ffpky(histptr, TSTRING, keyname, svalue, "Coordinate Units", &tstatus);
       }
       else
         tstatus = 0;

     /*  CRPIXn  - Reference Pixel  */
       ffkeyn("TCRPX", histData.hcolnum[ii], keyname, &tstatus);
       ffgky(*fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus);
       if (tstatus)
       {
         dvalue = 1.0; /* choose first pixel in new image as ref. pix. */
         tstatus = 0;
       }
       else
       {
           /* calculate locate of the ref. pix. in the new image */
           dvalue = (dvalue - amin[ii]) / binsize[ii] + .5;
       }

       ffkeyn("CRPIX", ii + 1, keyname, &tstatus);
       ffpky(histptr, TDOUBLE, keyname, &dvalue, "Reference Pixel", &tstatus);

     /*  CRVALn - Value at the location of the reference pixel */
       ffkeyn("TCRVL", histData.hcolnum[ii], keyname, &tstatus);
       ffgky(*fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus);
       if (tstatus)
       {
         /* calculate value at ref. pix. location (at center of 1st pixel) */
         dvalue = amin[ii] + binsize[ii]/2.;
         tstatus = 0;
       }

       ffkeyn("CRVAL", ii + 1, keyname, &tstatus);
       ffpky(histptr, TDOUBLE, keyname, &dvalue, "Reference Value", &tstatus);

     /*  CDELTn - unit size of pixels  */
       ffkeyn("TCDLT", histData.hcolnum[ii], keyname, &tstatus);
       ffgky(*fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus);
       if (tstatus)
       {
         dvalue = 1.0;  /* use default pixel size */
         tstatus = 0;
       }

       dvalue = dvalue * binsize[ii];
       ffkeyn("CDELT", ii + 1, keyname, &tstatus);
       ffpky(histptr, TDOUBLE, keyname, &dvalue, "Pixel size", &tstatus);

     /*  CROTAn - Rotation angle (degrees CCW)  */
     /*  There should only be a CROTA2 keyword, and only for 2+ D images */
       if (ii == 1)
       {
         ffkeyn("TCROT", histData.hcolnum[ii], keyname, &tstatus);
         ffgky(*fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus);
         if (!tstatus && dvalue != 0.)  /* only write keyword if angle != 0 */
         {
           ffkeyn("CROTA", ii + 1, keyname, &tstatus);
           ffpky(histptr, TDOUBLE, keyname, &dvalue,
                 "Rotation angle", &tstatus);
         }
         else
         {
            /* didn't find CROTA for the 2nd axis, so look for one */
            /* on the first axis */
           tstatus = 0;
           ffkeyn("TCROT", histData.hcolnum[0], keyname, &tstatus);
           ffgky(*fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus);
           if (!tstatus && dvalue != 0.)  /* only write keyword if angle != 0 */
           {
             dvalue *= -1.;   /* negate the value, because mirror image */
             ffkeyn("CROTA", ii + 1, keyname, &tstatus);
             ffpky(histptr, TDOUBLE, keyname, &dvalue,
                   "Rotation angle", &tstatus);
           }
         }
       }
    }

    /* convert any TPn_k keywords to PCi_j; the value remains unchanged */
    /* also convert any TCn_k to CDi_j; the value is modified by n binning size */
    /* This is a bit of a kludge, and only works for 2D WCS */

    if (histData.haxis == 2) {

      /* PC1_1 */
      tstatus = 0;
      ffkeyn("TP", histData.hcolnum[0], card, &tstatus);
      strcat(card,"_");
      ffkeyn(card, histData.hcolnum[0], keyname, &tstatus);
      ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus);
      if (!tstatus) 
         ffpky(histptr, TDOUBLE, "PC1_1", &dvalue, card, &tstatus);

      tstatus = 0;
      keyname[1] = 'C';
      ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus);
      if (!tstatus) {
         dvalue *=  binsize[0];
         ffpky(histptr, TDOUBLE, "CD1_1", &dvalue, card, &tstatus);
      }

      /* PC1_2 */
      tstatus = 0;
      ffkeyn("TP", histData.hcolnum[0], card, &tstatus);
      strcat(card,"_");
      ffkeyn(card, histData.hcolnum[1], keyname, &tstatus);
      ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus);
      if (!tstatus) 
         ffpky(histptr, TDOUBLE, "PC1_2", &dvalue, card, &tstatus);
 
      tstatus = 0;
      keyname[1] = 'C';
      ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus);
      if (!tstatus) {
        dvalue *=  binsize[0];
        ffpky(histptr, TDOUBLE, "CD1_2", &dvalue, card, &tstatus);
      }
       
      /* PC2_1 */
      tstatus = 0;
      ffkeyn("TP", histData.hcolnum[1], card, &tstatus);
      strcat(card,"_");
      ffkeyn(card, histData.hcolnum[0], keyname, &tstatus);
      ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus);
      if (!tstatus) 
         ffpky(histptr, TDOUBLE, "PC2_1", &dvalue, card, &tstatus);
 
      tstatus = 0;
      keyname[1] = 'C';
      ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus);
      if (!tstatus) {
         dvalue *=  binsize[1];
         ffpky(histptr, TDOUBLE, "CD2_1", &dvalue, card, &tstatus);
      }
       
       /* PC2_2 */
      tstatus = 0;
      ffkeyn("TP", histData.hcolnum[1], card, &tstatus);
      strcat(card,"_");
      ffkeyn(card, histData.hcolnum[1], keyname, &tstatus);
      ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus);
      if (!tstatus) 
         ffpky(histptr, TDOUBLE, "PC2_2", &dvalue, card, &tstatus);
        
      tstatus = 0;
      keyname[1] = 'C';
      ffgky(*fptr, TDOUBLE, keyname, &dvalue, card, &tstatus);
      if (!tstatus) {
         dvalue *=  binsize[1];
         ffpky(histptr, TDOUBLE, "CD2_2", &dvalue, card, &tstatus);
      }
    }   
       
    /* finally, close the original file and return ptr to the new image */
    ffclos(*fptr, status);
    *fptr = histptr;

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_calc_binning(
      fitsfile *fptr,  /* IO - pointer to table to be binned      ;       */
      int naxis,       /* I - number of axes/columns in the binned image  */
      char colname[4][FLEN_VALUE],   /* I - optional column names         */
      double *minin,     /* I - optional lower bound value for each axis  */
      double *maxin,     /* I - optional upper bound value, for each axis */
      double *binsizein, /* I - optional bin size along each axis         */
      char minname[4][FLEN_VALUE], /* I - optional keywords for min       */
      char maxname[4][FLEN_VALUE], /* I - optional keywords for max       */
      char binname[4][FLEN_VALUE], /* I - optional keywords for binsize   */

    /* The returned parameters for each axis of the n-dimensional histogram are */

      int *colnum,     /* O - column numbers, to be binned */
      long *haxes,     /* O - number of bins in each histogram axis */
      float *amin,     /* O - lower bound of the histogram axes */
      float *amax,     /* O - upper bound of the histogram axes */
      float *binsize,  /* O - width of histogram bins/pixels on each axis */
      int *status)
/*_
    Calculate the actual binning parameters, based on various user input
    options.
*/
{
    tcolumn *colptr;
    char *cptr, cpref[4][FLEN_VALUE];
    char errmsg[FLEN_ERRMSG], keyname[FLEN_KEYWORD];
    int tstatus, ii;
    int datatype, repeat, imin, imax, ibin,  use_datamax = 0;
    float datamin, datamax;

    /* check inputs */
    
    if (*status > 0)
        return(*status);

    if (naxis > 4)
    {
        ffpmsg("histograms with more than 4 dimensions are not supported");
        return(*status = BAD_DIMEN);
    }

    /* reset position to the correct HDU if necessary */
    if ((fptr)->HDUposition != ((fptr)->Fptr)->curhdu)
        ffmahd(fptr, ((fptr)->HDUposition) + 1, NULL, status);
    
    /* ============================================================= */
    /* The CPREF keyword, if it exists, gives the preferred columns. */
    /* Otherwise, assume "X", "Y", "Z", and "T"  */

    *cpref[0] = '\0';
    *cpref[1] = '\0';
    *cpref[2] = '\0';
    *cpref[3] = '\0';

    tstatus = 0;
    ffgky(fptr, TSTRING, "CPREF", cpref[0], NULL, &tstatus);

    if (!tstatus)
    {
        /* Preferred column names are given;  separate them */
        cptr = cpref[0];

        /* the first preferred axis... */
        while (*cptr != ',' && *cptr != '\0')
           cptr++;

        if (*cptr != '\0')
        {
           *cptr = '\0';
           cptr++;
           while (*cptr == ' ')
               cptr++;

           strcpy(cpref[1], cptr);
           cptr = cpref[1];

          /* the second preferred axis... */
          while (*cptr != ',' && *cptr != '\0')
             cptr++;

          if (*cptr != '\0')
          {
             *cptr = '\0';
             cptr++;
             while (*cptr == ' ')
                 cptr++;

             strcpy(cpref[2], cptr);
             cptr = cpref[2];

            /* the third preferred axis... */
            while (*cptr != ',' && *cptr != '\0')
               cptr++;

            if (*cptr != '\0')
            {
               *cptr = '\0';
               cptr++;
               while (*cptr == ' ')
                   cptr++;

               strcpy(cpref[3], cptr);

            }
          }
        }
    }

    /* ============================================================= */
    /* Main Loop for calculating parameters for each column          */

    for (ii = 0; ii < naxis; ii++)
    {

      /* =========================================================== */
      /* Determine column Number, based on, in order of priority,
         1  input column name, or
	 2  name given by CPREF keyword, or
	 3  assume X, Y, Z and T for the name
      */
	  
      if (*colname[ii] == '\0')
      {
         strcpy(colname[ii], cpref[ii]); /* try using the preferred column */
         if (*colname[ii] == '\0')
         {
           if (ii == 0)
              strcpy(colname[ii], "X");
           else if (ii == 1)
              strcpy(colname[ii], "Y");
           else if (ii == 2)
              strcpy(colname[ii], "Z");
           else if (ii == 3)
              strcpy(colname[ii], "T");
         }
      }

      /* get the column number in the table */
      if (ffgcno(fptr, CASEINSEN, colname[ii], colnum+ii, status)
              > 0)
      {
          strcpy(errmsg, "column for histogram axis doesn't exist: ");
          strcat(errmsg, colname[ii]);
          ffpmsg(errmsg);
          return(*status);
      }

      /* ================================================================ */
      /* check tha column is not a vector or a string                     */

      colptr = ((fptr)->Fptr)->tableptr;
      colptr += (colnum[ii] - 1);

      repeat = (int) colptr->trepeat;  /* vector repeat factor of the column */
      if (repeat > 1)
      {
        strcpy(errmsg, "Can't bin a vector column: ");
        strcat(errmsg, colname[ii]);
        ffpmsg(errmsg);
        return(*status = BAD_DATATYPE);
      }

      /* get the datatype of the column */
      fits_get_coltype(fptr, colnum[ii], &datatype,
         NULL, NULL, status);

      if (datatype < 0 || datatype == TSTRING)
      {
        strcpy(errmsg, "Inappropriate datatype; can't bin this column: ");
        strcat(errmsg, colname[ii]);
        ffpmsg(errmsg);
        return(*status = BAD_DATATYPE);
      }

      /* ================================================================ */
      /* get the minimum value */

      datamin = FLOATNULLVALUE;
      datamax = FLOATNULLVALUE;
      
      if (*minname[ii])
      {
         if (ffgky(fptr, TDOUBLE, minname[ii], &minin[ii], NULL, status) )
         {
             ffpmsg("error reading histogramming minimum keyword");
             ffpmsg(minname[ii]);
             return(*status);
         }
      }

      if (minin[ii] != DOUBLENULLVALUE)
      {
        amin[ii] = (float) minin[ii];
      }
      else
      {
        ffkeyn("TLMIN", colnum[ii], keyname, status);
        if (ffgky(fptr, TFLOAT, keyname, amin+ii, NULL, status) > 0)
        {
            /* use actual data minimum value for the histogram minimum */
            *status = 0;
            if (fits_get_col_minmax(fptr, colnum[ii], amin+ii, &datamax, status) > 0)
            {
                strcpy(errmsg, "Error calculating datamin and datamax for column: ");
                strcat(errmsg, colname[ii]);
                ffpmsg(errmsg);
                return(*status);
            }
         }
      }

      /* ================================================================ */
      /* get the maximum value */

      if (*maxname[ii])
      {
         if (ffgky(fptr, TDOUBLE, maxname[ii], &maxin[ii], NULL, status) )
         {
             ffpmsg("error reading histogramming maximum keyword");
             ffpmsg(maxname[ii]);
             return(*status);
         }
      }

      if (maxin[ii] != DOUBLENULLVALUE)
      {
        amax[ii] = (float) maxin[ii];
      }
      else
      {
        ffkeyn("TLMAX", colnum[ii], keyname, status);
        if (ffgky(fptr, TFLOAT, keyname, &amax[ii], NULL, status) > 0)
        {
          *status = 0;
          if(datamax != FLOATNULLVALUE)  /* already computed max value */
          {
             amax[ii] = datamax;
          }
          else
          {
             /* use actual data maximum value for the histogram maximum */
             if (fits_get_col_minmax(fptr, colnum[ii], &datamin, &amax[ii], status) > 0)
             {
                 strcpy(errmsg, "Error calculating datamin and datamax for column: ");
                 strcat(errmsg, colname[ii]);
                 ffpmsg(errmsg);
                 return(*status);
             }
          }
        }
        use_datamax = 1;  /* flag that the max was determined by the data values */
                          /* and not specifically set by the calling program */
      }


      /* ================================================================ */
      /* determine binning size and range                                 */

      if (*binname[ii])
      {
         if (ffgky(fptr, TDOUBLE, binname[ii], &binsizein[ii], NULL, status) )
         {
             ffpmsg("error reading histogramming binsize keyword");
             ffpmsg(binname[ii]);
             return(*status);
         }
      }

      if (binsizein[ii] == 0.)
      {
        ffpmsg("error: histogram binsize = 0");
        return(*status = ZERO_SCALE);
      }

      /* use TDBINn keyword or else 1 if bin size is not given */
      if (binsizein[ii] != DOUBLENULLVALUE)
      { 
         binsize[ii] = (float) binsizein[ii];
      }
      else
      {
         tstatus = 0;
         ffkeyn("TDBIN", colnum[ii], keyname, &tstatus);

         if (ffgky(fptr, TDOUBLE, keyname, binsizein + ii, NULL, &tstatus) > 0)
         {
	    /* make at least 10 bins */
            binsize[ii] = (amax[ii] - amin[ii]) / 10.F ;
            if (binsize[ii] > 1.)
                binsize[ii] = 1.;  /* use default bin size */
         }
      }

      /* ================================================================ */
      /* if the min is greater than the max, make the binsize negative */
      if ( (amin[ii] > amax[ii] && binsize[ii] > 0. ) ||
           (amin[ii] < amax[ii] && binsize[ii] < 0. ) )
          binsize[ii] =  -binsize[ii];  /* reverse the sign of binsize */


      ibin = (int) binsize[ii];
      imin = (int) amin[ii];
      imax = (int) amax[ii];

      /* Determine the range and number of bins in the histogram. This  */
      /* depends on whether the input columns are integer or floats, so */
      /* treat each case separately.                                    */

      if (datatype <= TLONG && (float) imin == amin[ii] &&
                               (float) imax == amax[ii] &&
                               (float) ibin == binsize[ii] )
      {
        /* This is an integer column and integer limits were entered. */
        /* Shift the lower and upper histogramming limits by 0.5, so that */
        /* the values fall in the center of the bin, not on the edge. */

        haxes[ii] = (imax - imin) / ibin + 1;  /* last bin may only */
                                               /* be partially full */
        if (amin[ii] < amax[ii])
        {
          amin[ii] = (float) (amin[ii] - 0.5);
          amax[ii] = (float) (amax[ii] + 0.5);
        }
        else
        {
          amin[ii] = (float) (amin[ii] + 0.5);
          amax[ii] = (float) (amax[ii] - 0.5);
        }
      }
      else if (use_datamax)  
      {
        /* Either the column datatype and/or the limits are floating point, */
        /* and the histogram limits are being defined by the min and max */
        /* values of the array.  Add 1 to the number of histogram bins to */
        /* make sure that pixels that are equal to the maximum or are */
        /* in the last partial bin are included.  */

        haxes[ii] = (long) (((amax[ii] - amin[ii]) / binsize[ii]) + 1.); 
      }
      else  
      {
        /*  float datatype column and/or limits, and the maximum value to */
        /*  include in the histogram is specified by the calling program. */
        /*  The lower limit is inclusive, but upper limit is exclusive    */
        haxes[ii] = (long) ((amax[ii] - amin[ii]) / binsize[ii]);

        if (amin[ii] < amax[ii])
        {
          if (amin[ii] + (haxes[ii] * binsize[ii]) < amax[ii])
            haxes[ii]++;   /* need to include another partial bin */
        }
        else
        {
          if (amin[ii] + (haxes[ii] * binsize[ii]) > amax[ii])
            haxes[ii]++;   /* need to include another partial bin */
        }
      }
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_write_keys_histo(
      fitsfile *fptr,   /* I - pointer to table to be binned              */
      fitsfile *histptr,  /* I - pointer to output histogram image HDU      */
      int naxis,        /* I - number of axes in the histogram image      */
      int *colnum,      /* I - column numbers (array length = naxis)      */
      int *status)     
{      
   /*  Write default WCS keywords in the output histogram image header */
   /*  if the keywords do not already exist.   */

    int ii, tstatus;
    char keyname[FLEN_KEYWORD], svalue[FLEN_VALUE];
    double dvalue;
    
    if (*status > 0)
        return(*status);

    for (ii = 0; ii < naxis; ii++)
    {
     /*  CTYPEn  */
       tstatus = 0;
       ffkeyn("CTYPE", ii+1, keyname, &tstatus);
       ffgky(histptr, TSTRING, keyname, svalue, NULL, &tstatus);
       
       if (!tstatus) continue;  /* keyword already exists, so skip to next axis */
       
       /* use column name as the axis name */
       tstatus = 0;
       ffkeyn("TTYPE", colnum[ii], keyname, &tstatus);
       ffgky(fptr, TSTRING, keyname, svalue, NULL, &tstatus);

       if (!tstatus)
       {
         ffkeyn("CTYPE", ii + 1, keyname, &tstatus);
         ffpky(histptr, TSTRING, keyname, svalue, "Coordinate Type", &tstatus);
       }

       /*  CUNITn,  use the column units */
       tstatus = 0;
       ffkeyn("TUNIT", colnum[ii], keyname, &tstatus);
       ffgky(fptr, TSTRING, keyname, svalue, NULL, &tstatus);

       if (!tstatus)
       {
         ffkeyn("CUNIT", ii + 1, keyname, &tstatus);
         ffpky(histptr, TSTRING, keyname, svalue, "Coordinate Units", &tstatus);
       }

       /*  CRPIXn  - Reference Pixel choose first pixel in new image as ref. pix. */
       dvalue = 1.0;
       tstatus = 0;
       ffkeyn("CRPIX", ii + 1, keyname, &tstatus);
       ffpky(histptr, TDOUBLE, keyname, &dvalue, "Reference Pixel", &tstatus);

       /*  CRVALn - Value at the location of the reference pixel */
       dvalue = 1.0;
       tstatus = 0;
       ffkeyn("CRVAL", ii + 1, keyname, &tstatus);
       ffpky(histptr, TDOUBLE, keyname, &dvalue, "Reference Value", &tstatus);

       /*  CDELTn - unit size of pixels  */
       dvalue = 1.0;  
       tstatus = 0;
       dvalue = 1.;
       ffkeyn("CDELT", ii + 1, keyname, &tstatus);
       ffpky(histptr, TDOUBLE, keyname, &dvalue, "Pixel size", &tstatus);

    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_rebin_wcs(
      fitsfile *fptr,   /* I - pointer to table to be binned           */
      int naxis,        /* I - number of axes in the histogram image   */
      float *amin,        /* I - first pixel include in each axis        */
      float *binsize,     /* I - binning factor for each axis            */
      int *status)      
{      
   /*  Update the  WCS keywords that define the location of the reference */
   /*  pixel, and the pixel size, along each axis.   */

    int ii, jj, tstatus, reset ;
    char keyname[FLEN_KEYWORD], svalue[FLEN_VALUE];
    double dvalue;
    
    if (*status > 0)
        return(*status);
  
    for (ii = 0; ii < naxis; ii++)
    {
       reset = 0;  /* flag to reset the reference pixel */
       tstatus = 0;
       ffkeyn("CRVAL", ii + 1, keyname, &tstatus);
       /* get previous (pre-binning) value */
       ffgky(fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus); 
       if (!tstatus && dvalue == 1.0)
           reset = 1;

       tstatus = 0;
       /*  CRPIXn - update location of the ref. pix. in the binned image */
       ffkeyn("CRPIX", ii + 1, keyname, &tstatus);

       /* get previous (pre-binning) value */
       ffgky(fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus); 

       if (!tstatus)
       {
           if (dvalue != 1.0)
	      reset = 0;

           /* updated value to give pixel location after binning */
           dvalue = (dvalue - amin[ii]) / ((double) binsize[ii]) + .5;  

           fits_modify_key_dbl(fptr, keyname, dvalue, -14, NULL, &tstatus);
       } else {
          reset = 0;
       }

       /*  CDELTn - update unit size of pixels  */
       tstatus = 0;
       ffkeyn("CDELT", ii + 1, keyname, &tstatus);

       /* get previous (pre-binning) value */
       ffgky(fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus); 

       if (!tstatus)
       {
           if (dvalue != 1.0)
	      reset = 0;

           /* updated to give post-binning value */
           dvalue = dvalue * binsize[ii];  

           fits_modify_key_dbl(fptr, keyname, dvalue, -14, NULL, &tstatus);
       }
       else
       {   /* no CDELTn keyword, so look for a CDij keywords */
          reset = 0;

          for (jj = 0; jj < naxis; jj++)
	  {
             tstatus = 0;
             ffkeyn("CD", jj + 1, svalue, &tstatus);
	     strcat(svalue,"_");
	     ffkeyn(svalue, ii + 1, keyname, &tstatus);

             /* get previous (pre-binning) value */
             ffgky(fptr, TDOUBLE, keyname, &dvalue, NULL, &tstatus); 

             if (!tstatus)
             {
                /* updated to give post-binning value */
               dvalue = dvalue * binsize[ii];  

               fits_modify_key_dbl(fptr, keyname, dvalue, -14, NULL, &tstatus);
             }
	  }
       }

       if (reset) {
          /* the original CRPIX, CRVAL, and CDELT keywords were all = 1.0 */
	  /* In this special case, reset the reference pixel to be the */
	  /* first pixel in the array (instead of possibly far off the array) */
 
           dvalue = 1.0;
           ffkeyn("CRPIX", ii + 1, keyname, &tstatus);
           fits_modify_key_dbl(fptr, keyname, dvalue, -14, NULL, &tstatus);

           ffkeyn("CRVAL", ii + 1, keyname, &tstatus);
	   dvalue = amin[ii] + (binsize[ii] / 2.0);	  
           fits_modify_key_dbl(fptr, keyname, dvalue, -14, NULL, &tstatus);
	}

    }
    return(*status);
}
/*--------------------------------------------------------------------------*/

int fits_make_hist(fitsfile *fptr, /* IO - pointer to table with X and Y cols; */
    fitsfile *histptr, /* I - pointer to output FITS image      */
    int bitpix,       /* I - datatype for image: 16, 32, -32, etc    */
    int naxis,        /* I - number of axes in the histogram image   */
    long *naxes,      /* I - size of axes in the histogram image   */
    int *colnum,    /* I - column numbers (array length = naxis)   */
    float *amin,     /* I - minimum histogram value, for each axis */
    float *amax,     /* I - maximum histogram value, for each axis */
    float *binsize, /* I - bin size along each axis               */
    float weight,        /* I - binning weighting factor          */
    int wtcolnum, /* I - optional keyword or col for weight*/
    int recip,              /* I - use reciprocal of the weight?     */
    char *selectrow,        /* I - optional array (length = no. of   */
                             /* rows in the table).  If the element is true */
                             /* then the corresponding row of the table will*/
                             /* be included in the histogram, otherwise the */
                             /* row will be skipped.  Ingnored if *selectrow*/
                             /* is equal to NULL.                           */
    int *status)
{		  
    int ii, imagetype, datatype;
    int n_cols = 1;
    long imin, imax, ibin;
    long  offset = 0;
    long n_per_loop = -1;  /* force whole array to be passed at one time */
    float taxes[4], tmin[4], tmax[4], tbin[4], maxbin[4];
    histType histData;    /* Structure holding histogram info for iterator */
    iteratorCol imagepars[1];

    /* check inputs */
    
    if (*status > 0)
        return(*status);

    if (naxis > 4)
    {
        ffpmsg("histogram has more than 4 dimensions");
        return(*status = BAD_DIMEN);
    }

    if   (bitpix == BYTE_IMG)
         imagetype = TBYTE;
    else if (bitpix == SHORT_IMG)
         imagetype = TSHORT;
    else if (bitpix == LONG_IMG)
         imagetype = TINT;    
    else if (bitpix == FLOAT_IMG)
         imagetype = TFLOAT;    
    else if (bitpix == DOUBLE_IMG)
         imagetype = TDOUBLE;    
    else
        return(*status = BAD_DATATYPE);

    /* reset position to the correct HDU if necessary */
    if ((fptr)->HDUposition != ((fptr)->Fptr)->curhdu)
        ffmahd(fptr, ((fptr)->HDUposition) + 1, NULL, status);

    histData.weight     = weight;
    histData.wtcolnum   = wtcolnum;
    histData.wtrecip    = recip;
    histData.tblptr     = fptr;
    histData.himagetype = imagetype;
    histData.haxis      = naxis;
    histData.rowselector = selectrow;

    for (ii = 0; ii < naxis; ii++)
    {
      taxes[ii] = (float) naxes[ii];
      tmin[ii] = amin[ii];
      tmax[ii] = amax[ii];
      if ( (amin[ii] > amax[ii] && binsize[ii] > 0. ) ||
           (amin[ii] < amax[ii] && binsize[ii] < 0. ) )
          tbin[ii] =  -binsize[ii];  /* reverse the sign of binsize */
      else
          tbin[ii] =   binsize[ii];  /* binsize has the correct sign */
          
      imin = (long) tmin[ii];
      imax = (long) tmax[ii];
      ibin = (long) tbin[ii];
    
      /* get the datatype of the column */
      fits_get_coltype(fptr, colnum[ii], &datatype, NULL, NULL, status);

      if (datatype <= TLONG && (float) imin == tmin[ii] &&
                               (float) imax == tmax[ii] &&
                               (float) ibin == tbin[ii] )
      {
        /* This is an integer column and integer limits were entered. */
        /* Shift the lower and upper histogramming limits by 0.5, so that */
        /* the values fall in the center of the bin, not on the edge. */

        maxbin[ii] = (taxes[ii] + 1.F);  /* add 1. instead of .5 to avoid roundoff */

        if (tmin[ii] < tmax[ii])
        {
          tmin[ii] = tmin[ii] - 0.5F;
          tmax[ii] = tmax[ii] + 0.5F;
        }
        else
        {
          tmin[ii] = tmin[ii] + 0.5F;
          tmax[ii] = tmax[ii] - 0.5F;
        }
      } else {  /* not an integer column with integer limits */
          maxbin[ii] = (tmax[ii] - tmin[ii]) / tbin[ii]; 
      }
    }

    /* Set global variables with histogram parameter values.    */
    /* Use separate scalar variables rather than arrays because */
    /* it is more efficient when computing the histogram.       */

    histData.hcolnum[0]  = colnum[0];
    histData.amin1 = tmin[0];
    histData.maxbin1 = maxbin[0];
    histData.binsize1 = tbin[0];
    histData.haxis1 = (long) taxes[0];

    if (histData.haxis > 1)
    {
      histData.hcolnum[1]  = colnum[1];
      histData.amin2 = tmin[1];
      histData.maxbin2 = maxbin[1];
      histData.binsize2 = tbin[1];
      histData.haxis2 = (long) taxes[1];

      if (histData.haxis > 2)
      {
        histData.hcolnum[2]  = colnum[2];
        histData.amin3 = tmin[2];
        histData.maxbin3 = maxbin[2];
        histData.binsize3 = tbin[2];
        histData.haxis3 = (long) taxes[2];

        if (histData.haxis > 3)
        {
          histData.hcolnum[3]  = colnum[3];
          histData.amin4 = tmin[3];
          histData.maxbin4 = maxbin[3];
          histData.binsize4 = tbin[3];
          histData.haxis4 = (long) taxes[3];
        }
      }
    }

    /* define parameters of image for the iterator function */
    fits_iter_set_file(imagepars, histptr);        /* pointer to image */
    fits_iter_set_datatype(imagepars, imagetype);  /* image datatype   */
    fits_iter_set_iotype(imagepars, OutputCol);    /* image is output  */

    /* call the iterator function to write out the histogram image */
    fits_iterate_data(n_cols, imagepars, offset, n_per_loop,
                          ffwritehisto, (void*)&histData, status);
       
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_get_col_minmax(fitsfile *fptr, int colnum, float *datamin, 
                     float *datamax, int *status)
/* 
   Simple utility routine to compute the min and max value in a column
*/
{
    int anynul;
    long nrows, ntodo, firstrow, ii;
    float array[1000], nulval;

    ffgky(fptr, TLONG, "NAXIS2", &nrows, NULL, status); /* no. of rows */

    firstrow = 1;
    nulval = FLOATNULLVALUE;
    *datamin =  9.0E36F;
    *datamax = -9.0E36F;

    while(nrows)
    {
        ntodo = minvalue(nrows, 100);
        ffgcv(fptr, TFLOAT, colnum, firstrow, 1, ntodo, &nulval, array,
              &anynul, status);

        for (ii = 0; ii < ntodo; ii++)
        {
            if (array[ii] != nulval)
            {
                *datamin = minvalue(*datamin, array[ii]);
                *datamax = maxvalue(*datamax, array[ii]);
            }
        }

        nrows -= ntodo;
        firstrow += ntodo;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffwritehisto(long totaln, long pixoffset, long firstn, long nvalues,
             int narrays, iteratorCol *imagepars, void *userPointer)
/*
   Interator work function that writes out the histogram.
   The histogram values are calculated by another work function, ffcalchisto.
   This work function only gets called once, and totaln = nvalues.
*/
{
    iteratorCol colpars[5];
    int ii, status = 0, ncols;
    long rows_per_loop = 0, offset = 0;
    histType *histData;

    histData = (histType *)userPointer;

    /* store pointer to the histogram array, and initialize to zero */

    switch( histData->himagetype ) {
    case TBYTE:
       histData->hist.b = (char *  ) fits_iter_get_array(imagepars);
       break;
    case TSHORT:
       histData->hist.i = (short * ) fits_iter_get_array(imagepars);
       break;
    case TINT:
       histData->hist.j = (int *   ) fits_iter_get_array(imagepars);
       break;
    case TFLOAT:
       histData->hist.r = (float * ) fits_iter_get_array(imagepars);
       break;
    case TDOUBLE:
       histData->hist.d = (double *) fits_iter_get_array(imagepars);
       break;
    }

    /* set the column parameters for the iterator function */
    for (ii = 0; ii < histData->haxis; ii++)
    {
      fits_iter_set_by_num(&colpars[ii], histData->tblptr,
			   histData->hcolnum[ii], TFLOAT, InputCol);
    }
    ncols = histData->haxis;

    if (histData->weight == FLOATNULLVALUE)
    {
      fits_iter_set_by_num(&colpars[histData->haxis], histData->tblptr,
			   histData->wtcolnum, TFLOAT, InputCol);
      ncols = histData->haxis + 1;
    }

    /* call iterator function to calc the histogram pixel values */

    /* must lock this call in multithreaded environoments because */
    /* the ffcalchist work routine uses static vaiables that would */
    /* get clobbered if multiple threads were running at the same time */
    FFLOCK;
    fits_iterate_data(ncols, colpars, offset, rows_per_loop,
                          ffcalchist, (void*)histData, &status);
    FFUNLOCK;

    return(status);
}
/*--------------------------------------------------------------------------*/
int ffcalchist(long totalrows, long offset, long firstrow, long nrows,
             int ncols, iteratorCol *colpars, void *userPointer)
/*
   Interator work function that calculates values for the 2D histogram.
*/
{
    long ii, ipix, iaxisbin;
    float pix, axisbin;
    static float *col1, *col2, *col3, *col4; /* static to preserve values */
    static float *wtcol;
    static long incr2, incr3, incr4;
    static histType histData;
    static char *rowselect;

    /*  Initialization procedures: execute on the first call  */
    if (firstrow == 1)
    {

      /*  Copy input histogram data to static local variable so we */
      /*  don't have to constantly dereference it.                 */

      histData = *(histType*)userPointer;
      rowselect = histData.rowselector;

      /* assign the input array pointers to local pointers */
      col1 = (float *) fits_iter_get_array(&colpars[0]);
      if (histData.haxis > 1)
      {
        col2 = (float *) fits_iter_get_array(&colpars[1]);
        incr2 = histData.haxis1;

        if (histData.haxis > 2)
        {
          col3 = (float *) fits_iter_get_array(&colpars[2]);
          incr3 = incr2 * histData.haxis2;

          if (histData.haxis > 3)
          {
            col4 = (float *) fits_iter_get_array(&colpars[3]);
            incr4 = incr3 * histData.haxis3;
          }
        }
      }

      if (ncols > histData.haxis)  /* then weights are give in a column */
      {
        wtcol = (float *) fits_iter_get_array(&colpars[histData.haxis]);
      }
    }   /* end of Initialization procedures */

    /*  Main loop: increment the histogram at position of each event */
    for (ii = 1; ii <= nrows; ii++) 
    {
        if (rowselect)     /* if a row selector array is supplied... */
        {
           if (*rowselect)
           {
               rowselect++;   /* this row is included in the histogram */
           }
           else
           {
               rowselect++;   /* this row is excluded from the histogram */
               continue;
           }
        }

        if (col1[ii] == FLOATNULLVALUE)  /* test for null value */
            continue;

        pix = (col1[ii] - histData.amin1) / histData.binsize1;
        ipix = (long) (pix + 1.); /* add 1 because the 1st pixel is the null value */

	/* test if bin is within range */
        if (ipix < 1 || ipix > histData.haxis1 || pix > histData.maxbin1)
            continue;

        if (histData.haxis > 1)
        {
          if (col2[ii] == FLOATNULLVALUE)
              continue;

          axisbin = (col2[ii] - histData.amin2) / histData.binsize2;
          iaxisbin = (long) axisbin;

          if (axisbin < 0. || iaxisbin >= histData.haxis2 || axisbin > histData.maxbin2)
              continue;

          ipix += (iaxisbin * incr2);

          if (histData.haxis > 2)
          {
            if (col3[ii] == FLOATNULLVALUE)
                continue;

            axisbin = (col3[ii] - histData.amin3) / histData.binsize3;
            iaxisbin = (long) axisbin;
            if (axisbin < 0. || iaxisbin >= histData.haxis3 || axisbin > histData.maxbin3)
                continue;

            ipix += (iaxisbin * incr3);
 
            if (histData.haxis > 3)
            {
              if (col4[ii] == FLOATNULLVALUE)
                  continue;

              axisbin = (col4[ii] - histData.amin4) / histData.binsize4;
              iaxisbin = (long) axisbin;
              if (axisbin < 0. || iaxisbin >= histData.haxis4 || axisbin > histData.maxbin4)
                  continue;

              ipix += (iaxisbin * incr4);

            }  /* end of haxis > 3 case */
          }    /* end of haxis > 2 case */
        }      /* end of haxis > 1 case */

        /* increment the histogram pixel */
        if (histData.weight != FLOATNULLVALUE) /* constant weight factor */
        {
            if (histData.himagetype == TINT)
              histData.hist.j[ipix] += (int) histData.weight;
            else if (histData.himagetype == TSHORT)
              histData.hist.i[ipix] += (short) histData.weight;
            else if (histData.himagetype == TFLOAT)
              histData.hist.r[ipix] += histData.weight;
            else if (histData.himagetype == TDOUBLE)
              histData.hist.d[ipix] += histData.weight;
            else if (histData.himagetype == TBYTE)
              histData.hist.b[ipix] += (char) histData.weight;
        }
        else if (histData.wtrecip) /* use reciprocal of the weight */
        {
            if (histData.himagetype == TINT)
              histData.hist.j[ipix] += (int) (1./wtcol[ii]);
            else if (histData.himagetype == TSHORT)
              histData.hist.i[ipix] += (short) (1./wtcol[ii]);
            else if (histData.himagetype == TFLOAT)
              histData.hist.r[ipix] += (float) (1./wtcol[ii]);
            else if (histData.himagetype == TDOUBLE)
              histData.hist.d[ipix] += 1./wtcol[ii];
            else if (histData.himagetype == TBYTE)
              histData.hist.b[ipix] += (char) (1./wtcol[ii]);
        }
        else   /* no weights */
        {
            if (histData.himagetype == TINT)
              histData.hist.j[ipix] += (int) wtcol[ii];
            else if (histData.himagetype == TSHORT)
              histData.hist.i[ipix] += (short) wtcol[ii];
            else if (histData.himagetype == TFLOAT)
              histData.hist.r[ipix] += wtcol[ii];
            else if (histData.himagetype == TDOUBLE)
              histData.hist.d[ipix] += wtcol[ii];
            else if (histData.himagetype == TBYTE)
              histData.hist.b[ipix] += (char) wtcol[ii];
        }

    }  /* end of main loop over all rows */

    return(0);
}

cfitsio/imcompress.c0000644000225700000360000133202513246025103014333 0ustar  cagordonlhea# include 
# include 
# include 
# include 
# include 
# include 
# include "fitsio2.h"

#define NULL_VALUE -2147483647 /* value used to represent undefined pixels */
#define ZERO_VALUE -2147483646 /* value used to represent zero-valued pixels */

/* nearest integer function */
# define NINT(x)  ((x >= 0.) ? (int) (x + 0.5) : (int) (x - 0.5))

/* special quantize level value indicates that floating point image pixels */
/* should not be quantized and instead losslessly compressed (with GZIP) */
#define NO_QUANTIZE 9999

/* string array for storing the individual column compression stats */
char results[999][30];

float *fits_rand_value = 0;

int imcomp_write_nocompress_tile(fitsfile *outfptr, long row, int datatype, 
    void *tiledata, long tilelen, int nullcheck, void *nullflagval, int *status);
int imcomp_convert_tile_tshort(fitsfile *outfptr, void *tiledata, long tilelen,
    int nullcheck, void *nullflagval, int nullval, int zbitpix, double scale,
    double zero, double actual_bzero, int *intlength, int *status);
int imcomp_convert_tile_tushort(fitsfile *outfptr, void *tiledata, long tilelen,
    int nullcheck, void *nullflagval, int nullval, int zbitpix, double scale,
    double zero, int *intlength, int *status);
int imcomp_convert_tile_tint(fitsfile *outfptr, void *tiledata, long tilelen,
    int nullcheck, void *nullflagval, int nullval, int zbitpix, double scale,
    double zero, int *intlength, int *status);
int imcomp_convert_tile_tuint(fitsfile *outfptr, void *tiledata, long tilelen,
    int nullcheck, void *nullflagval, int nullval, int zbitpix, double scale,
    double zero, int *intlength, int *status);
int imcomp_convert_tile_tbyte(fitsfile *outfptr, void *tiledata, long tilelen,
    int nullcheck, void *nullflagval, int nullval, int zbitpix, double scale,
    double zero, int *intlength, int *status);
int imcomp_convert_tile_tsbyte(fitsfile *outfptr, void *tiledata, long tilelen,
    int nullcheck, void *nullflagval, int nullval, int zbitpix, double scale,
    double zero, int *intlength, int *status);
int imcomp_convert_tile_tfloat(fitsfile *outfptr, long row, void *tiledata, long tilelen,
    long tilenx, long tileny, int nullcheck, void *nullflagval, int nullval, int zbitpix,
    double scale, double zero, int *intlength, int *flag, double *bscale, double *bzero,int *status);
int imcomp_convert_tile_tdouble(fitsfile *outfptr, long row, void *tiledata, long tilelen,
    long tilenx, long tileny, int nullcheck, void *nullflagval, int nullval, int zbitpix, 
    double scale, double zero, int *intlength, int *flag, double *bscale, double *bzero, int *status);

static int unquantize_i1r4(long row,
            unsigned char *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int dither_method,    /* I - which subtractive dither method to use */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            unsigned char tnull,          /* I - value of FITS TNULLn keyword if any */
            float nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            float *output,        /* O - array of converted pixels           */
            int *status);          /* IO - error status                       */
static int unquantize_i2r4(long row,
            short *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int dither_method,    /* I - which subtractive dither method to use */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            short tnull,          /* I - value of FITS TNULLn keyword if any */
            float nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            float *output,        /* O - array of converted pixels           */
            int *status);          /* IO - error status                       */
static int unquantize_i4r4(long row,
            INT32BIT *input,      /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int dither_method,    /* I - which subtractive dither method to use */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
            float nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            float *output,        /* O - array of converted pixels           */
            int *status);          /* IO - error status                       */
static int unquantize_i1r8(long row,
            unsigned char *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int dither_method,    /* I - which subtractive dither method to use */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            unsigned char tnull,          /* I - value of FITS TNULLn keyword if any */
            double nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            double *output,        /* O - array of converted pixels           */
            int *status);          /* IO - error status                       */
static int unquantize_i2r8(long row,
            short *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int dither_method,    /* I - which subtractive dither method to use */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            short tnull,          /* I - value of FITS TNULLn keyword if any */
            double nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            double *output,        /* O - array of converted pixels           */
            int *status);          /* IO - error status                       */
static int unquantize_i4r8(long row,
            INT32BIT *input,      /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int dither_method,    /* I - which subtractive dither method to use */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
            double nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            double *output,        /* O - array of converted pixels           */
            int *status);          /* IO - error status                       */
static int imcomp_float2nan(float *indata, long tilelen, int *outdata,
    float nullflagval,  int *status);
static int imcomp_double2nan(double *indata, long tilelen, LONGLONG *outdata,
    double nullflagval,  int *status);    
static int fits_read_write_compressed_img(fitsfile *fptr,   /* I - FITS file pointer */
            int  datatype,  /* I - datatype of the array to be returned      */
            LONGLONG  *infpixel, /* I - 'bottom left corner' of the subsection    */
            LONGLONG  *inlpixel, /* I - 'top right corner' of the subsection      */
            long  *ininc,    /* I - increment to be applied in each dimension */
            int  nullcheck,  /* I - 0 for no null checking                   */
                              /*     1: set undefined pixels = nullval       */
            void *nullval,    /* I - value for undefined pixels              */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            fitsfile *outfptr,   /* I - FITS file pointer                    */
            int  *status);

static int fits_shuffle_8bytes(char *heap, LONGLONG length, int *status);
static int fits_shuffle_4bytes(char *heap, LONGLONG length, int *status);
static int fits_shuffle_2bytes(char *heap, LONGLONG length, int *status);
static int fits_unshuffle_8bytes(char *heap, LONGLONG length, int *status);
static int fits_unshuffle_4bytes(char *heap, LONGLONG length, int *status);
static int fits_unshuffle_2bytes(char *heap, LONGLONG length, int *status);

static int fits_int_to_longlong_inplace(int *intarray, long length, int *status);
static int fits_short_to_int_inplace(short *intarray, long length, int *status);
static int fits_ushort_to_int_inplace(unsigned short *intarray, long length, int *status);
static int fits_sbyte_to_int_inplace(signed char *intarray, long length, int *status);
static int fits_ubyte_to_int_inplace(unsigned char *intarray, long length, int *status);

/* only used for diagnoitic purposes */
/* int fits_get_case(int *c1, int*c2, int*c3); */ 
/*---------------------------------------------------------------------------*/
int fits_init_randoms(void) {

/* initialize an array of random numbers */

    int ii;
    double a = 16807.0;
    double m = 2147483647.0;
    double temp, seed;

    FFLOCK;
 
    if (fits_rand_value) {
       FFUNLOCK;
       return(0);  /* array is already initialized */
    }

    /* allocate array for the random number sequence */
    /* THIS MEMORY IS NEVER FREED */
    fits_rand_value = calloc(N_RANDOM, sizeof(float));

    if (!fits_rand_value) {
        FFUNLOCK;
	return(MEMORY_ALLOCATION);
    }
		       
    /*  We need a portable algorithm that anyone can use to generate this
        exact same sequence of random number.  The C 'rand' function is not
	suitable because it is not available to Fortran or Java programmers.
	Instead, use a well known simple algorithm published here: 
	"Random number generators: good ones are hard to find", Communications of the ACM,
        Volume 31 ,  Issue 10  (October 1988) Pages: 1192 - 1201 
    */  

    /* initialize the random numbers */
    seed = 1;
    for (ii = 0; ii < N_RANDOM; ii++) {
        temp = a * seed;
	seed = temp -m * ((int) (temp / m) );
	fits_rand_value[ii] = (float) (seed / m);
    }

    FFUNLOCK;

    /* 
    IMPORTANT NOTE: the 10000th seed value must have the value 1043618065 if the 
       algorithm has been implemented correctly */
    
    if ( (int) seed != 1043618065) {
        ffpmsg("fits_init_randoms generated incorrect random number sequence");
	return(1);
    } else {
        return(0);
    }
}
/*--------------------------------------------------------------------------*/
void bz_internal_error(int errcode)
{
    /* external function declared by the bzip2 code in bzlib_private.h */
    ffpmsg("bzip2 returned an internal error");
    ffpmsg("This should never happen");
    return;
}
/*--------------------------------------------------------------------------*/
int fits_set_compression_type(fitsfile *fptr,  /* I - FITS file pointer     */
       int ctype,    /* image compression type code;                        */
                     /* allowed values: RICE_1, GZIP_1, GZIP_2, PLIO_1,     */
                     /*  HCOMPRESS_1, BZIP2_1, and NOCOMPRESS               */
       int *status)  /* IO - error status                                   */
{
/*
   This routine specifies the image compression algorithm that should be
   used when writing a FITS image.  The image is divided into tiles, and
   each tile is compressed and stored in a row of at variable length binary
   table column.
*/

    if (ctype != RICE_1 && 
        ctype != GZIP_1 && 
        ctype != GZIP_2 && 
        ctype != PLIO_1 && 
        ctype != HCOMPRESS_1 && 
        ctype != BZIP2_1 && 
        ctype != NOCOMPRESS &&
	ctype != 0)
    {
	ffpmsg("unknown compression algorithm (fits_set_compression_type)");
	*status = DATA_COMPRESSION_ERR; 
    } else {
        (fptr->Fptr)->request_compress_type = ctype;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_set_tile_dim(fitsfile *fptr,  /* I - FITS file pointer             */
           int ndim,   /* number of dimensions in the compressed image      */
           long *dims, /* size of image compression tile in each dimension  */
                      /* default tile size = (NAXIS1, 1, 1, ...)            */
           int *status)         /* IO - error status                        */
{
/*
   This routine specifies the size (dimension) of the image
   compression  tiles that should be used when writing a FITS
   image.  The image is divided into tiles, and each tile is compressed
   and stored in a row of at variable length binary table column.
*/
    int ii;

    if (ndim < 0 || ndim > MAX_COMPRESS_DIM)
    {
        *status = BAD_DIMEN;
	ffpmsg("illegal number of tile dimensions (fits_set_tile_dim)");
        return(*status);
    }

    for (ii = 0; ii < ndim; ii++)
    {
        (fptr->Fptr)->request_tilesize[ii] = dims[ii];
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_set_quantize_level(fitsfile *fptr,  /* I - FITS file pointer   */
           float qlevel,        /* floating point quantization level      */
           int *status)         /* IO - error status                */
{
/*
   This routine specifies the value of the quantization level, q,  that
   should be used when compressing floating point images.  The image is
   divided into tiles, and each tile is compressed and stored in a row
   of at variable length binary table column.
*/
    if (qlevel == 0.)
    {
        /* this means don't quantize the floating point values. Instead, */
	/* the floating point values will be losslessly compressed */
       (fptr->Fptr)->request_quantize_level = NO_QUANTIZE;
    } else {

        (fptr->Fptr)->request_quantize_level = qlevel;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_set_quantize_method(fitsfile *fptr,  /* I - FITS file pointer   */
           int method,          /* quantization method       */
           int *status)         /* IO - error status                */
{
/*
   This routine specifies what type of dithering (randomization) should
   be performed when quantizing floating point images to integer prior to
   compression.   A value of -1 means do no dithering.  A value of 0 means
   use the default SUBTRACTIVE_DITHER_1 (which is equivalent to dither = 1).
   A value of 2 means use SUBTRACTIVE_DITHER_2.
*/

    if (method < -1 || method > 2)
    {
	ffpmsg("illegal dithering value (fits_set_quantize_method)");
	*status = DATA_COMPRESSION_ERR; 
    } else {
       
        if (method == 0) method = 1;
        (fptr->Fptr)->request_quantize_method = method;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_set_quantize_dither(fitsfile *fptr,  /* I - FITS file pointer   */
           int dither,        /* dither type      */
           int *status)         /* IO - error status                */
{
/*
   the name of this routine has changed.  This is kept here only for backwards
   compatibility for any software that may be calling the old routine.
*/

    fits_set_quantize_method(fptr, dither, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_set_dither_seed(fitsfile *fptr,  /* I - FITS file pointer   */
           int seed,        /* random dithering seed value (1 to 10000) */
           int *status)         /* IO - error status                */
{
/*
   This routine specifies the value of the offset that should be applied when
   calculating the random dithering when quantizing floating point iamges.
   A random offset should be applied to each image to avoid quantization 
   effects when taking the difference of 2 images, or co-adding a set of
   images.  Without this random offset, the corresponding pixel in every image
   will have exactly the same dithering.
   
   offset = 0 means use the default random dithering based on system time
   offset = negative means randomly chose dithering based on 1st tile checksum
   offset = [1 - 10000] means use that particular dithering pattern

*/
    /* if positive, ensure that the value is in the range 1 to 10000 */
    if (seed > 10000) {
	ffpmsg("illegal dithering seed value (fits_set_dither_seed)");
	*status = DATA_COMPRESSION_ERR;
    } else {
       (fptr->Fptr)->request_dither_seed = seed; 
    }
    
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_set_dither_offset(fitsfile *fptr,  /* I - FITS file pointer   */
           int offset,        /* random dithering offset value (1 to 10000) */
           int *status)         /* IO - error status                */
{
/*
    The name of this routine has changed.  This is kept just for
    backwards compatibility with any software that calls the old name
*/

    fits_set_dither_seed(fptr, offset, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_set_noise_bits(fitsfile *fptr,  /* I - FITS file pointer   */
           int noisebits,       /* noise_bits parameter value       */
                                /* (default = 4)                    */
           int *status)         /* IO - error status                */
{
/*
   ********************************************************************
   ********************************************************************
   THIS ROUTINE IS PROVIDED ONLY FOR BACKWARDS COMPATIBILITY;
   ALL NEW SOFTWARE SHOULD CALL fits_set_quantize_level INSTEAD
   ********************************************************************
   ********************************************************************

   This routine specifies the value of the noice_bits parameter that
   should be used when compressing floating point images.  The image is
   divided into tiles, and each tile is compressed and stored in a row
   of at variable length binary table column.

   Feb 2008:  the "noisebits" parameter has been replaced with the more
   general "quantize level" parameter.
*/
    float qlevel;

    if (noisebits < 1 || noisebits > 16)
    {
        *status = DATA_COMPRESSION_ERR;
	ffpmsg("illegal number of noise bits (fits_set_noise_bits)");
        return(*status);
    }

    qlevel = (float) pow (2., (double)noisebits);
    fits_set_quantize_level(fptr, qlevel, status);
    
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_set_hcomp_scale(fitsfile *fptr,  /* I - FITS file pointer   */
           float scale,       /* hcompress scale parameter value       */
                                /* (default = 0.)                    */
           int *status)         /* IO - error status                */
{
/*
   This routine specifies the value of the hcompress scale parameter.
*/
    (fptr->Fptr)->request_hcomp_scale = scale;
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_set_hcomp_smooth(fitsfile *fptr,  /* I - FITS file pointer   */
           int smooth,       /* hcompress smooth parameter value       */
                                /* if scale > 1 and smooth != 0, then */
				/*  the image will be smoothed when it is */
				/* decompressed to remove some of the */
				/* 'blockiness' in the image produced */
				/* by the lossy compression    */
           int *status)         /* IO - error status                */
{
/*
   This routine specifies the value of the hcompress scale parameter.
*/

    (fptr->Fptr)->request_hcomp_smooth = smooth;
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_set_lossy_int(fitsfile *fptr,  /* I - FITS file pointer   */
           int lossy_int,       /* I - True (!= 0) or False (0) */
           int *status)         /* IO - error status                */
{
/*
   This routine specifies whether images with integer pixel values should
   quantized and compressed the same way float images are compressed.
   The default is to not do this, and instead apply a lossless compression
   algorithm to integer images.
*/

    (fptr->Fptr)->request_lossy_int_compress = lossy_int;
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_set_huge_hdu(fitsfile *fptr,  /* I - FITS file pointer   */
           int huge,       /* I - True (!= 0) or False (0) */
           int *status)         /* IO - error status                */
{
/*
   This routine specifies whether the HDU that is being compressed is so large
   (i.e., > 4 GB) that the 'Q' type variable length array columns should be used
   rather than the normal 'P' type.  The allows the heap pointers to be stored
   as 64-bit quantities, rather than just 32-bits.
*/

    (fptr->Fptr)->request_huge_hdu = huge;
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_get_compression_type(fitsfile *fptr,  /* I - FITS file pointer     */
       int *ctype,   /* image compression type code;                        */
                     /* allowed values:                                     */
		     /* RICE_1, GZIP_1, GZIP_2, PLIO_1, HCOMPRESS_1, BZIP2_1 */
       int *status)  /* IO - error status                                   */
{
/*
   This routine returns the image compression algorithm that should be
   used when writing a FITS image.  The image is divided into tiles, and
   each tile is compressed and stored in a row of at variable length binary
   table column.
*/
    *ctype = (fptr->Fptr)->request_compress_type;

    if (*ctype != RICE_1 && 
        *ctype != GZIP_1 && 
        *ctype != GZIP_2 && 
        *ctype != PLIO_1 && 
        *ctype != HCOMPRESS_1 && 
        *ctype != BZIP2_1 && 
        *ctype != NOCOMPRESS &&
	*ctype != 0   ) 

    {
	ffpmsg("unknown compression algorithm (fits_get_compression_type)");
	*status = DATA_COMPRESSION_ERR; 
    }
 
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_get_tile_dim(fitsfile *fptr,  /* I - FITS file pointer             */
           int ndim,   /* number of dimensions in the compressed image      */
           long *dims, /* size of image compression tile in each dimension  */
                       /* default tile size = (NAXIS1, 1, 1, ...)           */
           int *status)         /* IO - error status                        */
{
/*
   This routine returns the size (dimension) of the image
   compression  tiles that should be used when writing a FITS
   image.  The image is divided into tiles, and each tile is compressed
   and stored in a row of at variable length binary table column.
*/
    int ii;

    if (ndim < 0 || ndim > MAX_COMPRESS_DIM)
    {
        *status = BAD_DIMEN;
	ffpmsg("illegal number of tile dimensions (fits_get_tile_dim)");
        return(*status);
    }

    for (ii = 0; ii < ndim; ii++)
    {
        dims[ii] = (fptr->Fptr)->request_tilesize[ii];
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_unset_compression_param(
      fitsfile *fptr,
      int *status) 
{
    int ii;

    (fptr->Fptr)->compress_type = 0;
    (fptr->Fptr)->quantize_level = 0;
    (fptr->Fptr)->quantize_method = 0;
    (fptr->Fptr)->dither_seed = 0; 
    (fptr->Fptr)->hcomp_scale = 0;

    for (ii = 0; ii < MAX_COMPRESS_DIM; ii++)
    {
        (fptr->Fptr)->tilesize[ii] = 0;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_unset_compression_request(
      fitsfile *fptr,
      int *status) 
{
    int ii;

    (fptr->Fptr)->request_compress_type = 0;
    (fptr->Fptr)->request_quantize_level = 0;
    (fptr->Fptr)->request_quantize_method = 0;
    (fptr->Fptr)->request_dither_seed = 0; 
    (fptr->Fptr)->request_hcomp_scale = 0;
    (fptr->Fptr)->request_lossy_int_compress = 0;
    (fptr->Fptr)->request_huge_hdu = 0;

    for (ii = 0; ii < MAX_COMPRESS_DIM; ii++)
    {
        (fptr->Fptr)->request_tilesize[ii] = 0;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_set_compression_pref(
      fitsfile *infptr,
      fitsfile *outfptr,
      int *status) 
{
/*
   Set the preference for various compression options, based
   on keywords in the input file that
   provide guidance about how the HDU should be compressed when written
   to the output file.
*/

    int ii, naxis, nkeys, comptype;
    int  ivalue;
    long tiledim[6]= {1,1,1,1,1,1};
    char card[FLEN_CARD], value[FLEN_VALUE];
    double  qvalue;
    float hscale;
    LONGLONG datastart, dataend; 
    if (*status > 0)
        return(*status);

    /* check the size of the HDU that is to be compressed */
    fits_get_hduaddrll(infptr, NULL, &datastart, &dataend, status);
    if ( (LONGLONG)(dataend - datastart) > UINT32_MAX) {
       /* use 64-bit '1Q' variable length columns instead of '1P' columns */
       /* for large files, in case the heap size becomes larger than 2**32 bytes*/
       fits_set_huge_hdu(outfptr, 1, status);
    }

    fits_get_hdrspace(infptr, &nkeys, NULL, status);
 
   /* look for a image compression directive keywords (begin with 'FZ') */
    for (ii = 2; ii <= nkeys; ii++) {
        
	fits_read_record(infptr, ii, card, status);

	if (!strncmp(card, "FZ", 2) ){
	
            /* get the keyword value string */
            fits_parse_value(card, value, NULL, status);
	    
	    if      (!strncmp(card+2, "ALGOR", 5) ) {

	        /* set the desired compression algorithm */
                /* allowed values: RICE_1, GZIP_1, GZIP_2, PLIO_1,     */
                /*  HCOMPRESS_1, BZIP2_1, and NOCOMPRESS               */

                if        (!fits_strncasecmp(value, "'RICE_1", 7) ) {
		    comptype = RICE_1;
                } else if (!fits_strncasecmp(value, "'GZIP_1", 7) ) {
		    comptype = GZIP_1;
                } else if (!fits_strncasecmp(value, "'GZIP_2", 7) ) {
		    comptype = GZIP_2;
                } else if (!fits_strncasecmp(value, "'PLIO_1", 7) ) {
		    comptype = PLIO_1;
                } else if (!fits_strncasecmp(value, "'HCOMPRESS_1", 12) ) {
		    comptype = HCOMPRESS_1;
                } else if (!fits_strncasecmp(value, "'NONE", 5) ) {
		    comptype = NOCOMPRESS;
		} else {
			ffpmsg("Unknown FZALGOR keyword compression algorithm:");
			ffpmsg(value);
			return(*status = DATA_COMPRESSION_ERR);
		}  

	        fits_set_compression_type (outfptr, comptype, status);

	    } else if (!strncmp(card+2, "TILE  ", 6) ) {

                if (!fits_strncasecmp(value, "'row", 4) ) {
                   tiledim[0] = -1;
		} else if (!fits_strncasecmp(value, "'whole", 6) ) {
                   tiledim[0] = -1;
                   tiledim[1] = -1;
                   tiledim[2] = -1;
                } else {
		   ffdtdm(infptr, value, 0,6, &naxis, tiledim, status);
                }

	        /* set the desired tile size */
		fits_set_tile_dim (outfptr, 6, tiledim, status);

	    } else if (!strncmp(card+2, "QVALUE", 6) ) {

	        /* set the desired Q quantization value */
		qvalue = atof(value);
		fits_set_quantize_level (outfptr, (float) qvalue, status);

	    } else if (!strncmp(card+2, "QMETHD", 6) ) {

                    if (!fits_strncasecmp(value, "'no_dither", 10) ) {
                        ivalue = -1; /* just quantize, with no dithering */
		    } else if (!fits_strncasecmp(value, "'subtractive_dither_1", 21) ) {
                        ivalue = SUBTRACTIVE_DITHER_1; /* use subtractive dithering */
		    } else if (!fits_strncasecmp(value, "'subtractive_dither_2", 21) ) {
                        ivalue = SUBTRACTIVE_DITHER_2; /* dither, except preserve zero-valued pixels */
		    } else {
		        ffpmsg("Unknown value for FZQUANT keyword: (set_compression_pref)");
			ffpmsg(value);
                        return(*status = DATA_COMPRESSION_ERR);
		    }

		    fits_set_quantize_method(outfptr, ivalue, status);
		    
	    } else if (!strncmp(card+2, "DTHRSD", 6) ) {

                if (!fits_strncasecmp(value, "'checksum", 9) ) {
                    ivalue = -1; /* use checksum of first tile */
		} else if (!fits_strncasecmp(value, "'clock", 6) ) {
                    ivalue = 0; /* set dithering seed based on system clock */
		} else {  /* read integer value */
		    if (*value == '\'')
                        ivalue = (int) atol(value+1); /* allow for leading quote character */
                    else 
                        ivalue = (int) atol(value); 

                    if (ivalue < 1 || ivalue > 10000) {
		        ffpmsg("Invalid value for FZDTHRSD keyword: (set_compression_pref)");
			ffpmsg(value);
                        return(*status = DATA_COMPRESSION_ERR);
                    }
		}

	        /* set the desired dithering */
		fits_set_dither_seed(outfptr, ivalue, status);

	    } else if (!strncmp(card+2, "I2F", 3) ) {

	        /* set whether to convert integers to float then use lossy compression */
                if (!fits_strcasecmp(value, "t") ) {
		    fits_set_lossy_int (outfptr, 1, status);
		} else if (!fits_strcasecmp(value, "f") ) {
		    fits_set_lossy_int (outfptr, 0, status);
		} else {
		        ffpmsg("Unknown value for FZI2F keyword: (set_compression_pref)");
			ffpmsg(value);
                        return(*status = DATA_COMPRESSION_ERR);
                }

	    } else if (!strncmp(card+2, "HSCALE ", 6) ) {

	        /* set the desired Hcompress scale value */
		hscale = (float) atof(value);
		fits_set_hcomp_scale (outfptr, hscale, status);
            }
	}    
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_get_noise_bits(fitsfile *fptr,  /* I - FITS file pointer   */
           int *noisebits,       /* noise_bits parameter value       */
                                /* (default = 4)                    */
           int *status)         /* IO - error status                */
{
/*
   ********************************************************************
   ********************************************************************
   THIS ROUTINE IS PROVIDED ONLY FOR BACKWARDS COMPATIBILITY;
   ALL NEW SOFTWARE SHOULD CALL fits_set_quantize_level INSTEAD
   ********************************************************************
   ********************************************************************


   This routine returns the value of the noice_bits parameter that
   should be used when compressing floating point images.  The image is
   divided into tiles, and each tile is compressed and stored in a row
   of at variable length binary table column.

   Feb 2008: code changed to use the more general "quantize level" parameter
   rather than the "noise bits" parameter.  If quantize level is greater than
   zero, then the previous noisebits parameter is approximately given by
   
   noise bits = natural logarithm (quantize level) / natural log (2)
   
   This result is rounded to the nearest integer.
*/
    double qlevel;

    qlevel = (fptr->Fptr)->request_quantize_level;

    if (qlevel > 0. && qlevel < 65537. )
         *noisebits =  (int) ((log(qlevel) / log(2.0)) + 0.5);
    else 
        *noisebits = 0;

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_get_quantize_level(fitsfile *fptr,  /* I - FITS file pointer   */
           float *qlevel,       /* quantize level parameter value       */
           int *status)         /* IO - error status                */
{
/*
   This routine returns the value of the noice_bits parameter that
   should be used when compressing floating point images.  The image is
   divided into tiles, and each tile is compressed and stored in a row
   of at variable length binary table column.
*/

    if ((fptr->Fptr)->request_quantize_level == NO_QUANTIZE) {
      *qlevel = 0;
    } else {
      *qlevel = (fptr->Fptr)->request_quantize_level;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_get_dither_seed(fitsfile *fptr,  /* I - FITS file pointer   */
           int *offset,       /* dithering offset parameter value       */
           int *status)         /* IO - error status                */
{
/*
   This routine returns the value of the dithering offset parameter that
   is used when compressing floating point images.  The image is
   divided into tiles, and each tile is compressed and stored in a row
   of at variable length binary table column.
*/

    *offset = (fptr->Fptr)->request_dither_seed;
    return(*status);
}/*--------------------------------------------------------------------------*/
int fits_get_hcomp_scale(fitsfile *fptr,  /* I - FITS file pointer   */
           float *scale,          /* Hcompress scale parameter value       */
           int *status)         /* IO - error status                */

{
/*
   This routine returns the value of the noice_bits parameter that
   should be used when compressing floating point images.  The image is
   divided into tiles, and each tile is compressed and stored in a row
   of at variable length binary table column.
*/

    *scale = (fptr->Fptr)->request_hcomp_scale;
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_get_hcomp_smooth(fitsfile *fptr,  /* I - FITS file pointer   */
           int *smooth,          /* Hcompress smooth parameter value       */
           int *status)         /* IO - error status                */

{
    *smooth = (fptr->Fptr)->request_hcomp_smooth;
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_img_compress(fitsfile *infptr, /* pointer to image to be compressed */
                 fitsfile *outfptr, /* empty HDU for output compressed image */
                 int *status)       /* IO - error status               */

/*
   This routine initializes the output table, copies all the keywords,
   and  loops through the input image, compressing the data and
   writing the compressed tiles to the output table.
   
   This is a high level routine that is called by the fpack and funpack
   FITS compression utilities.
*/
{
    int bitpix, naxis;
    long naxes[MAX_COMPRESS_DIM];
/*    int c1, c2, c3; */

    if (*status > 0)
        return(*status);


    /* get datatype and size of input image */
    if (fits_get_img_param(infptr, MAX_COMPRESS_DIM, &bitpix, 
                       &naxis, naxes, status) > 0)
        return(*status);

    if (naxis < 1 || naxis > MAX_COMPRESS_DIM)
    {
        ffpmsg("Image cannot be compressed: NAXIS out of range");
        return(*status = BAD_NAXIS);
    }

    /* create a new empty HDU in the output file now, before setting the */
    /* compression preferences.  This HDU will become a binary table that */
    /* contains the compressed image.  If necessary, create a dummy primary */
    /* array, which much precede the binary table extension. */
    
    ffcrhd(outfptr, status);  /* this does nothing if the output file is empty */

    if ((outfptr->Fptr)->curhdu == 0)  /* have to create dummy primary array */
    {
       ffcrim(outfptr, 16, 0, NULL, status);
       ffcrhd(outfptr, status);
    } else {
        /* unset any compress parameter preferences that may have been
           set when closing the previous HDU in the output file */
        fits_unset_compression_param(outfptr, status);
    }
    
    /* set any compress parameter preferences as given in the input file */
    fits_set_compression_pref(infptr, outfptr, status);

    /* special case: the quantization level is not given by a keyword in  */
    /* the HDU header, so we have to explicitly copy the requested value */
    /* to the actual value */
/* do this in imcomp_get_compressed_image_par, instead
    if ( (outfptr->Fptr)->request_quantize_level != 0.)
        (outfptr->Fptr)->quantize_level = (outfptr->Fptr)->request_quantize_level;
*/
    /* if requested, treat integer images same as a float image. */
    /* Then the pixels will be quantized (lossy algorithm) to achieve */
    /* higher amounts of compression than with lossless algorithms */

    if ( (outfptr->Fptr)->request_lossy_int_compress != 0  && bitpix > 0) 
	bitpix = FLOAT_IMG;  /* compress integer images as if float */

    /* initialize output table */
    if (imcomp_init_table(outfptr, bitpix, naxis, naxes, 0, status) > 0)
        return (*status);    

    /* Copy the image header keywords to the table header. */
    if (imcomp_copy_img2comp(infptr, outfptr, status) > 0)
	    return (*status);

    /* turn off any intensity scaling (defined by BSCALE and BZERO */
    /* keywords) so that unscaled values will be read by CFITSIO */
    /* (except if quantizing an int image, same as a float image) */
    if ( (outfptr->Fptr)->request_lossy_int_compress == 0 && bitpix > 0) 
        ffpscl(infptr, 1.0, 0.0, status);

    /* force a rescan of the output file keywords, so that */
    /* the compression parameters will be copied to the internal */
    /* fitsfile structure used by CFITSIO */
    ffrdef(outfptr, status);

    /* turn off any intensity scaling (defined by BSCALE and BZERO */
    /* keywords) so that unscaled values will be written by CFITSIO */
    /* (except if quantizing an int image, same as a float image) */
    if ( (outfptr->Fptr)->request_lossy_int_compress == 0 && bitpix > 0) 
        ffpscl(outfptr, 1.0, 0.0, status);

    /* Read each image tile, compress, and write to a table row. */
    imcomp_compress_image (infptr, outfptr, status);

    /* force another rescan of the output file keywords, to */
    /* update PCOUNT and TFORMn = '1PB(iii)' keyword values. */
    ffrdef(outfptr, status);

    /* unset any previously set compress parameter preferences */
    fits_unset_compression_request(outfptr, status);

/*
    fits_get_case(&c1, &c2, &c3);
    printf("c1, c2, c3 = %d, %d, %d\n", c1, c2, c3); 
*/

    return (*status);
}
/*--------------------------------------------------------------------------*/
int imcomp_init_table(fitsfile *outfptr,
        int inbitpix,
        int naxis,
        long *naxes,
	int writebitpix,    /* write the ZBITPIX, ZNAXIS, and ZNAXES keyword? */
        int *status)
/* 
  create a BINTABLE extension for the output compressed image.
*/
{
    char keyname[FLEN_KEYWORD], zcmptype[12];
    int ii,  remain,  ncols, bitpix;
    long nrows;
    char *ttype[] = {"COMPRESSED_DATA", "ZSCALE", "ZZERO"};
    char *tform[3];
    char tf0[4], tf1[4], tf2[4];
    char *tunit[] = {"\0",            "\0",            "\0"  };
    char comm[FLEN_COMMENT];
    long actual_tilesize[MAX_COMPRESS_DIM]; /* Actual size to use for tiles */
    int is_primary=0; /* Is this attempting to write to the primary? */
    
    if (*status > 0)
        return(*status);

    /* check for special case of losslessly compressing floating point */
    /* images.  Only compression algorithm that supports this is GZIP */
    if ( (inbitpix < 0) && ((outfptr->Fptr)->request_quantize_level == NO_QUANTIZE) ) {
       if (((outfptr->Fptr)->request_compress_type != GZIP_1) &&
           ((outfptr->Fptr)->request_compress_type != GZIP_2)) {
         ffpmsg("Lossless compression of floating point images must use GZIP (imcomp_init_table)");
         return(*status = DATA_COMPRESSION_ERR);
       }
    }
 
     /* set default compression parameter values, if undefined */
    
    if ( (outfptr->Fptr)->request_compress_type == 0) {
	/* use RICE_1 by default */
	(outfptr->Fptr)->request_compress_type = RICE_1;
    }

    if (inbitpix < 0 && (outfptr->Fptr)->request_quantize_level != NO_QUANTIZE) {  
	/* set defaults for quantizing floating point images */
	if ( (outfptr->Fptr)->request_quantize_method == 0) {
	      /* set default dithering method */
              (outfptr->Fptr)->request_quantize_method = SUBTRACTIVE_DITHER_1;
	}

	if ( (outfptr->Fptr)->request_quantize_level == 0) {
	    if ((outfptr->Fptr)->request_quantize_method == NO_DITHER) {
	        /* must use finer quantization if no dithering is done */
	        (outfptr->Fptr)->request_quantize_level = 16; 
	    } else {
	        (outfptr->Fptr)->request_quantize_level = 4; 
	    }
        }
    }

    /* special case: the quantization level is not given by a keyword in  */
    /* the HDU header, so we have to explicitly copy the requested value */
    /* to the actual value */
/* do this in imcomp_get_compressed_image_par, instead
    if ( (outfptr->Fptr)->request_quantize_level != 0.)
        (outfptr->Fptr)->quantize_level = (outfptr->Fptr)->request_quantize_level;
*/
    /* test for the 2 special cases that represent unsigned integers */
    if (inbitpix == USHORT_IMG)
        bitpix = SHORT_IMG;
    else if (inbitpix == ULONG_IMG)
        bitpix = LONG_IMG;
    else if (inbitpix == SBYTE_IMG)
        bitpix = BYTE_IMG;
    else 
        bitpix = inbitpix;

    /* reset default tile dimensions too if required */
    memcpy(actual_tilesize, outfptr->Fptr->request_tilesize, MAX_COMPRESS_DIM * sizeof(long));

    if ((outfptr->Fptr)->request_compress_type == HCOMPRESS_1) {

         if (naxis < 2 ) {
            ffpmsg("Hcompress cannot be used with 1-dimensional images (imcomp_init_table)");
            return(*status = DATA_COMPRESSION_ERR);

	 } else if  (naxes[0] < 4 || naxes[1] < 4) {
            ffpmsg("Hcompress minimum image dimension is 4 pixels (imcomp_init_table)");
            return(*status = DATA_COMPRESSION_ERR);
         }

         if ((actual_tilesize[0] <= 0) &&
             (actual_tilesize[1] == -1) ){
	     
	    /* compress the whole image as a single tile */
             actual_tilesize[0] = naxes[0];
             actual_tilesize[1] = naxes[1];

              for (ii = 2; ii < naxis; ii++) {
	             /* set all higher tile dimensions = 1 */
                     actual_tilesize[ii] = 1;
	      }

         } else if ((actual_tilesize[0] <= 0) &&
             (actual_tilesize[1] == 0 || actual_tilesize[1] == 1) ){
	     
             /*
              The Hcompress algorithm is inherently 2D in nature, so the row by row
	      tiling that is used for other compression algorithms is not appropriate.
	      If the image has less than 30 rows, then the entire image will be compressed
	      as a single tile.  Otherwise the tiles will consist of 16 rows of the image. 
	      This keeps the tiles to a reasonable size, and it also includes enough rows
	      to allow good compression efficiency.  If the last tile of the image 
	      happens to contain less than 4 rows, then find another tile size with
	      between 14 and 30 rows (preferably even), so that the last tile has 
	      at least 4 rows
	     */ 
	      
             /* 1st tile dimension is the row length of the image */
             actual_tilesize[0] = naxes[0];

              if (naxes[1] <= 30) {  /* use whole image if it is small */
                   actual_tilesize[1] = naxes[1];
	      } else {
                /* look for another good tile dimension */
	          if        (naxes[1] % 16 == 0 || naxes[1] % 16 > 3) {
                      actual_tilesize[1] = 16;
		  } else if (naxes[1] % 24 == 0 || naxes[1] % 24 > 3) {
                      actual_tilesize[1] = 24;
		  } else if (naxes[1] % 20 == 0 || naxes[1] % 20 > 3) {
                      actual_tilesize[1] = 20;
		  } else if (naxes[1] % 30 == 0 || naxes[1] % 30 > 3) {
                      actual_tilesize[1] = 30;
		  } else if (naxes[1] % 28 == 0 || naxes[1] % 28 > 3) {
                      actual_tilesize[1] = 28;
		  } else if (naxes[1] % 26 == 0 || naxes[1] % 26 > 3) {
                      actual_tilesize[1] = 26;
		  } else if (naxes[1] % 22 == 0 || naxes[1] % 22 > 3) {
                      actual_tilesize[1] = 22;
		  } else if (naxes[1] % 18 == 0 || naxes[1] % 18 > 3) {
                      actual_tilesize[1] = 18;
		  } else if (naxes[1] % 14 == 0 || naxes[1] % 14 > 3) {
                      actual_tilesize[1] = 14;
		  } else  {
                      actual_tilesize[1] = 17;
		  }
	      }
        } else if (actual_tilesize[0] < 4 ||
                   actual_tilesize[1] < 4) {

            /* user-specified tile size is too small */
            ffpmsg("Hcompress minimum tile dimension is 4 pixels (imcomp_init_table)");
            return(*status = DATA_COMPRESSION_ERR);
	}
	
        /* check if requested tile size causes the last tile to to have less than 4 pixels */
        remain = naxes[0] % (actual_tilesize[0]);  /* 1st dimension */
        if (remain > 0 && remain < 4) {
            (actual_tilesize[0])++; /* try increasing tile size by 1 */
	   
            remain = naxes[0] % (actual_tilesize[0]);
            if (remain > 0 && remain < 4) {
                ffpmsg("Last tile along 1st dimension has less than 4 pixels (imcomp_init_table)");
                return(*status = DATA_COMPRESSION_ERR);	
            }        
        }

        remain = naxes[1] % (actual_tilesize[1]);  /* 2nd dimension */
        if (remain > 0 && remain < 4) {
            (actual_tilesize[1])++; /* try increasing tile size by 1 */
	   
            remain = naxes[1] % (actual_tilesize[1]);
            if (remain > 0 && remain < 4) {
                ffpmsg("Last tile along 2nd dimension has less than 4 pixels (imcomp_init_table)");
                return(*status = DATA_COMPRESSION_ERR);	
            }        
        }

    } /* end, if HCOMPRESS_1 */
    
    for (ii = 0; ii < naxis; ii++) {
	if (ii == 0) { /* first axis is different */
	    if (actual_tilesize[ii] <= 0) {
                actual_tilesize[ii] = naxes[ii]; 
	    }
	} else {
	    if (actual_tilesize[ii] < 0) {
                actual_tilesize[ii] = naxes[ii];  /* negative value maean use whole length */
	    } else if (actual_tilesize[ii] == 0) {
                actual_tilesize[ii] = 1;  /* zero value means use default value = 1 */
	    }
	}
    }

    /* ---- set up array of TFORM strings -------------------------------*/
    if ( (outfptr->Fptr)->request_huge_hdu != 0) {
        strcpy(tf0, "1QB");
    } else {
        strcpy(tf0, "1PB");
    }
    strcpy(tf1, "1D");
    strcpy(tf2, "1D");

    tform[0] = tf0;
    tform[1] = tf1;
    tform[2] = tf2;

    /* calculate number of rows in output table */
    nrows = 1;
    for (ii = 0; ii < naxis; ii++)
    {
        nrows = nrows * ((naxes[ii] - 1)/ (actual_tilesize[ii]) + 1);
    }

    /* determine the default  number of columns in the output table */
    if (bitpix < 0 && (outfptr->Fptr)->request_quantize_level != NO_QUANTIZE)  
        ncols = 3;  /* quantized and scaled floating point image */
    else
        ncols = 1; /* default table has just one 'COMPRESSED_DATA' column */

    if ((outfptr->Fptr)->request_compress_type == RICE_1)
    {
        strcpy(zcmptype, "RICE_1");
    }
    else if ((outfptr->Fptr)->request_compress_type == GZIP_1)
    {
        strcpy(zcmptype, "GZIP_1");
    }
    else if ((outfptr->Fptr)->request_compress_type == GZIP_2)
    {
        strcpy(zcmptype, "GZIP_2");
    }
    else if ((outfptr->Fptr)->request_compress_type == BZIP2_1)
    {
        strcpy(zcmptype, "BZIP2_1");
    }
    else if ((outfptr->Fptr)->request_compress_type == PLIO_1)
    {
        strcpy(zcmptype, "PLIO_1");
       /* the PLIO compression algorithm outputs short integers, not bytes */
        if ( (outfptr->Fptr)->request_huge_hdu != 0) {
            strcpy(tform[0], "1QI");
        } else {
            strcpy(tform[0], "1PI");
        }
    }
    else if ((outfptr->Fptr)->request_compress_type == HCOMPRESS_1)
    {
        strcpy(zcmptype, "HCOMPRESS_1");
    }
    else if ((outfptr->Fptr)->request_compress_type == NOCOMPRESS)
    {
        strcpy(zcmptype, "NOCOMPRESS");
    }    
    else
    {
        ffpmsg("unknown compression type (imcomp_init_table)");
        return(*status = DATA_COMPRESSION_ERR);
    }

    /* If attempting to write compressed image to primary, the
       call to ffcrtb will increment Fptr->curhdu to 1.  Therefore
       we need to test now for setting is_primary */
    is_primary = (outfptr->Fptr->curhdu == 0);
    /* create the bintable extension to contain the compressed image */
    ffcrtb(outfptr, BINARY_TBL, nrows, ncols, ttype, 
                tform, tunit, 0, status);

    /* Add standard header keywords. */
    ffpkyl (outfptr, "ZIMAGE", 1, 
           "extension contains compressed image", status);  

    if (writebitpix) {
        /*  write the keywords defining the datatype and dimensions of */
	/*  the uncompressed image.  If not, these keywords will be */
        /*  copied later from the input uncompressed image  */
	
        if (is_primary)   
            ffpkyl (outfptr, "ZSIMPLE", 1,
			"file does conform to FITS standard", status);
        ffpkyj (outfptr, "ZBITPIX", bitpix,
			"data type of original image", status);
        ffpkyj (outfptr, "ZNAXIS", naxis,
			"dimension of original image", status);

        for (ii = 0;  ii < naxis;  ii++)
        {
            snprintf (keyname, FLEN_KEYWORD,"ZNAXIS%d", ii+1);
            ffpkyj (outfptr, keyname, naxes[ii],
			"length of original image axis", status);
        }
    }
                      
    for (ii = 0;  ii < naxis;  ii++)
    {
        snprintf (keyname, FLEN_KEYWORD,"ZTILE%d", ii+1);
        ffpkyj (outfptr, keyname, actual_tilesize[ii],
			"size of tiles to be compressed", status);
    }

    if (bitpix < 0) {
       
	if ((outfptr->Fptr)->request_quantize_level == NO_QUANTIZE) {
	    ffpkys(outfptr, "ZQUANTIZ", "NONE", 
	      "Lossless compression without quantization", status);
	} else {
	    
	    /* Unless dithering has been specifically turned off by setting */
	    /* request_quantize_method = -1, use dithering by default */
	    /* when quantizing floating point images. */
	
	    if ( (outfptr->Fptr)->request_quantize_method == 0) 
              (outfptr->Fptr)->request_quantize_method = SUBTRACTIVE_DITHER_1;
       
	    if ((outfptr->Fptr)->request_quantize_method == SUBTRACTIVE_DITHER_1) {
	      ffpkys(outfptr, "ZQUANTIZ", "SUBTRACTIVE_DITHER_1", 
	        "Pixel Quantization Algorithm", status);

	      /* also write the associated ZDITHER0 keyword with a default value */
	      /* which may get updated later. */
              ffpky(outfptr, TINT, "ZDITHER0", &((outfptr->Fptr)->request_dither_seed), 
	       "dithering offset when quantizing floats", status);
 
            } else if ((outfptr->Fptr)->request_quantize_method == SUBTRACTIVE_DITHER_2) {
	      ffpkys(outfptr, "ZQUANTIZ", "SUBTRACTIVE_DITHER_2", 
	        "Pixel Quantization Algorithm", status);

	      /* also write the associated ZDITHER0 keyword with a default value */
	      /* which may get updated later. */
              ffpky(outfptr, TINT, "ZDITHER0", &((outfptr->Fptr)->request_dither_seed), 
	       "dithering offset when quantizing floats", status);

	      if (!strcmp(zcmptype, "RICE_1"))  {
	        /* when using this new dithering method, change the compression type */
		/* to an alias, so that old versions of funpack will not be able to */
		/* created a corrupted uncompressed image. */
		/* ******* can remove this cludge after about June 2015, after most old versions of fpack are gone */
        	strcpy(zcmptype, "RICE_ONE");
	      }

            } else if ((outfptr->Fptr)->request_quantize_method == NO_DITHER) {
	      ffpkys(outfptr, "ZQUANTIZ", "NO_DITHER", 
	        "No dithering during quantization", status);
	    }

	}
    }

    ffpkys (outfptr, "ZCMPTYPE", zcmptype,
	          "compression algorithm", status);

    /* write any algorithm-specific keywords */
    if ((outfptr->Fptr)->request_compress_type == RICE_1)
    {
        ffpkys (outfptr, "ZNAME1", "BLOCKSIZE",
            "compression block size", status);

        /* for now at least, the block size is always 32 */
        ffpkyj (outfptr, "ZVAL1", 32,
			"pixels per block", status);

        ffpkys (outfptr, "ZNAME2", "BYTEPIX",
            "bytes per pixel (1, 2, 4, or 8)", status);

        if (bitpix == BYTE_IMG)
            ffpkyj (outfptr, "ZVAL2", 1,
			"bytes per pixel (1, 2, 4, or 8)", status);
        else if (bitpix == SHORT_IMG)
            ffpkyj (outfptr, "ZVAL2", 2,
			"bytes per pixel (1, 2, 4, or 8)", status);
        else 
            ffpkyj (outfptr, "ZVAL2", 4,
			"bytes per pixel (1, 2, 4, or 8)", status);

    }
    else if ((outfptr->Fptr)->request_compress_type == HCOMPRESS_1)
    {
        ffpkys (outfptr, "ZNAME1", "SCALE",
            "HCOMPRESS scale factor", status);
        ffpkye (outfptr, "ZVAL1", (outfptr->Fptr)->request_hcomp_scale,
		7, "HCOMPRESS scale factor", status);

        ffpkys (outfptr, "ZNAME2", "SMOOTH",
            "HCOMPRESS smooth option", status);
        ffpkyj (outfptr, "ZVAL2", (long) (outfptr->Fptr)->request_hcomp_smooth,
			"HCOMPRESS smooth option", status);
    }

    /* Write the BSCALE and BZERO keywords, if an unsigned integer image */
    if (inbitpix == USHORT_IMG)
    {
        strcpy(comm, "offset data range to that of unsigned short");
        ffpkyg(outfptr, "BZERO", 32768., 0, comm, status);
        strcpy(comm, "default scaling factor");
        ffpkyg(outfptr, "BSCALE", 1.0, 0, comm, status);
    }
    else if (inbitpix == SBYTE_IMG)
    {
        strcpy(comm, "offset data range to that of signed byte");
        ffpkyg(outfptr, "BZERO", -128., 0, comm, status);
        strcpy(comm, "default scaling factor");
        ffpkyg(outfptr, "BSCALE", 1.0, 0, comm, status);
    }
    else if (inbitpix == ULONG_IMG)
    {
        strcpy(comm, "offset data range to that of unsigned long");
        ffpkyg(outfptr, "BZERO", 2147483648., 0, comm, status);
        strcpy(comm, "default scaling factor");
        ffpkyg(outfptr, "BSCALE", 1.0, 0, comm, status);
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int imcomp_calc_max_elem (int comptype, int nx, int zbitpix, int blocksize)

/* This function returns the maximum number of bytes in a compressed
   image line.

    nx = maximum number of pixels in a tile
    blocksize is only relevant for RICE compression
*/
{    
    if (comptype == RICE_1)
    {
        if (zbitpix == 16)
            return (sizeof(short) * nx + nx / blocksize + 2 + 4);
	else
            return (sizeof(float) * nx + nx / blocksize + 2 + 4);
    }
    else if ((comptype == GZIP_1) || (comptype == GZIP_2))
    {
        /* gzip usually compressed by at least a factor of 2 for I*4 images */
        /* and somewhat less for I*2 images */
        /* If this size turns out to be too small, then the gzip */
        /* compression routine will allocate more space as required */
        /* to be on the safe size, allocate buffer same size as input */
	
        if (zbitpix == 16)
            return(nx * 2);
	else if (zbitpix == 8)
            return(nx);
	else
            return(nx * 4);
    }
    else if (comptype == BZIP2_1)
    {
        /* To guarantee that the compressed data will fit, allocate an output
	   buffer of size 1% larger than the uncompressed data, plus 600 bytes */

            return((int) (nx * 1.01 * zbitpix / 8. + 601.));
    }
     else if (comptype == HCOMPRESS_1)
    {
        /* Imperical evidence suggests in the worst case, 
	   the compressed stream could be up to 10% larger than the original
	   image.  Add 26 byte overhead, only significant for very small tiles
	   
         Possible improvement: may need to allow a larger size for 32-bit images */

        if (zbitpix == 16 || zbitpix == 8)
	
            return( (int) (nx * 2.2 + 26));   /* will be compressing 16-bit int array */
        else
            return( (int) (nx * 4.4 + 26));   /* will be compressing 32-bit int array */
    }
    else
        return(nx * sizeof(int));
}
/*--------------------------------------------------------------------------*/
int imcomp_compress_image (fitsfile *infptr, fitsfile *outfptr, int *status)

/* This routine does the following:
        - reads an image one tile at a time
        - if it is a float or double image, then it tries to quantize the pixels
          into scaled integers.
        - it then compressess the integer pixels, or if the it was not
	  possible to quantize the floating point pixels, then it losslessly
	  compresses them with gzip
	- writes the compressed byte stream to the output FITS file
*/
{
    double *tiledata;
    int anynul, gotnulls = 0, datatype;
    long ii, row;
    int naxis;
    double dummy = 0., dblnull = DOUBLENULLVALUE;
    float fltnull = FLOATNULLVALUE;
    long maxtilelen, tilelen, incre[] = {1, 1, 1, 1, 1, 1};
    long naxes[MAX_COMPRESS_DIM], fpixel[MAX_COMPRESS_DIM];
    long lpixel[MAX_COMPRESS_DIM], tile[MAX_COMPRESS_DIM];
    long tilesize[MAX_COMPRESS_DIM];
    long i0, i1, i2, i3, i4, i5;
    char card[FLEN_CARD];

    if (*status > 0)
        return(*status);

    maxtilelen = (outfptr->Fptr)->maxtilelen;

    /* 
     Allocate buffer to hold 1 tile of data; size depends on which compression 
     algorithm is used:

      Rice and GZIP will compress byte, short, or int arrays without conversion.
      PLIO requires 4-byte int values, so byte and short arrays must be converted to int.
      HCompress internally converts byte or short values to ints, and
         converts int values to 8-byte longlong integers.
    */
    
    if ((outfptr->Fptr)->zbitpix == FLOAT_IMG)
    {
        datatype = TFLOAT;

        if ( (outfptr->Fptr)->compress_type == HCOMPRESS_1) {
	    /* need twice as much scratch space (8 bytes per pixel) */
            tiledata = (double*) malloc (maxtilelen * 2 *sizeof (float));	
	} else {
            tiledata = (double*) malloc (maxtilelen * sizeof (float));
	}
    }
    else if ((outfptr->Fptr)->zbitpix == DOUBLE_IMG)
    {
        datatype = TDOUBLE;
        tiledata = (double*) malloc (maxtilelen * sizeof (double));
    }
    else if ((outfptr->Fptr)->zbitpix == SHORT_IMG)
    {
        datatype = TSHORT;
        if ( (outfptr->Fptr)->compress_type == RICE_1  ||
	     (outfptr->Fptr)->compress_type == GZIP_1  ||
	     (outfptr->Fptr)->compress_type == GZIP_2  ||
	     (outfptr->Fptr)->compress_type == BZIP2_1 ||
             (outfptr->Fptr)->compress_type == NOCOMPRESS) {
	    /* only need  buffer of I*2 pixels for gzip, bzip2, and Rice */

            tiledata = (double*) malloc (maxtilelen * sizeof (short));	
	} else {
 	    /*  need  buffer of I*4 pixels for Hcompress and PLIO */
            tiledata = (double*) malloc (maxtilelen * sizeof (int));
        }
    }
    else if ((outfptr->Fptr)->zbitpix == BYTE_IMG)
    {

        datatype = TBYTE;
        if ( (outfptr->Fptr)->compress_type == RICE_1  ||
	     (outfptr->Fptr)->compress_type == BZIP2_1 ||
	     (outfptr->Fptr)->compress_type == GZIP_1  ||
	     (outfptr->Fptr)->compress_type == GZIP_2) {
	    /* only need  buffer of I*1 pixels for gzip, bzip2, and Rice */

            tiledata = (double*) malloc (maxtilelen);	
	} else {
 	    /*  need  buffer of I*4 pixels for Hcompress and PLIO */
            tiledata = (double*) malloc (maxtilelen * sizeof (int));
        }
    }
    else if ((outfptr->Fptr)->zbitpix == LONG_IMG)
    {
        datatype = TINT;
        if ( (outfptr->Fptr)->compress_type == HCOMPRESS_1) {
	    /* need twice as much scratch space (8 bytes per pixel) */

            tiledata = (double*) malloc (maxtilelen * 2 * sizeof (int));	
	} else {
 	    /* only need  buffer of I*4 pixels for gzip, bzip2,  Rice, and PLIO */

            tiledata = (double*) malloc (maxtilelen * sizeof (int));
        }
    }
    else
    {
	ffpmsg("Bad image datatype. (imcomp_compress_image)");
	return (*status = MEMORY_ALLOCATION);
    }
    
    if (tiledata == NULL)
    {
	ffpmsg("Out of memory. (imcomp_compress_image)");
	return (*status = MEMORY_ALLOCATION);
    }

    /*  calculate size of tile in each dimension */
    naxis = (outfptr->Fptr)->zndim;
    for (ii = 0; ii < MAX_COMPRESS_DIM; ii++)
    {
        if (ii < naxis)
        {
             naxes[ii] = (outfptr->Fptr)->znaxis[ii];
             tilesize[ii] = (outfptr->Fptr)->tilesize[ii];
        }
        else
        {
            naxes[ii] = 1;
            tilesize[ii] = 1;
        }
    }
    row = 1;

    /* set up big loop over up to 6 dimensions */
    for (i5 = 1; i5 <= naxes[5]; i5 += tilesize[5])
    {
     fpixel[5] = i5;
     lpixel[5] = minvalue(i5 + tilesize[5] - 1, naxes[5]);
     tile[5] = lpixel[5] - fpixel[5] + 1;
     for (i4 = 1; i4 <= naxes[4]; i4 += tilesize[4])
     {
      fpixel[4] = i4;
      lpixel[4] = minvalue(i4 + tilesize[4] - 1, naxes[4]);
      tile[4] = lpixel[4] - fpixel[4] + 1;
      for (i3 = 1; i3 <= naxes[3]; i3 += tilesize[3])
      {
       fpixel[3] = i3;
       lpixel[3] = minvalue(i3 + tilesize[3] - 1, naxes[3]);
       tile[3] = lpixel[3] - fpixel[3] + 1;
       for (i2 = 1; i2 <= naxes[2]; i2 += tilesize[2])
       {
        fpixel[2] = i2;
        lpixel[2] = minvalue(i2 + tilesize[2] - 1, naxes[2]);
        tile[2] = lpixel[2] - fpixel[2] + 1;
        for (i1 = 1; i1 <= naxes[1]; i1 += tilesize[1])
        {
         fpixel[1] = i1;
         lpixel[1] = minvalue(i1 + tilesize[1] - 1, naxes[1]);
         tile[1] = lpixel[1] - fpixel[1] + 1;
         for (i0 = 1; i0 <= naxes[0]; i0 += tilesize[0])
         {
          fpixel[0] = i0;
          lpixel[0] = minvalue(i0 + tilesize[0] - 1, naxes[0]);
          tile[0] = lpixel[0] - fpixel[0] + 1;

          /* number of pixels in this tile */
          tilelen = tile[0];
          for (ii = 1; ii < naxis; ii++)
          {
             tilelen *= tile[ii];
          }

          /* read next tile of data from image */
	  anynul = 0;
          if (datatype == TFLOAT)
          {
              ffgsve(infptr, 1, naxis, naxes, fpixel, lpixel, incre, 
                  FLOATNULLVALUE, (float *) tiledata,  &anynul, status);
          }
          else if (datatype == TDOUBLE)
          {
              ffgsvd(infptr, 1, naxis, naxes, fpixel, lpixel, incre, 
                  DOUBLENULLVALUE, tiledata, &anynul, status);
          }
          else if (datatype == TINT)
          {
              ffgsvk(infptr, 1, naxis, naxes, fpixel, lpixel, incre, 
                  0, (int *) tiledata,  &anynul, status);
          }
          else if (datatype == TSHORT)
          {
              ffgsvi(infptr, 1, naxis, naxes, fpixel, lpixel, incre, 
                  0, (short *) tiledata,  &anynul, status);
          }
          else if (datatype == TBYTE)
          {
              ffgsvb(infptr, 1, naxis, naxes, fpixel, lpixel, incre, 
                  0, (unsigned char *) tiledata,  &anynul, status);
          }
          else 
          {
              ffpmsg("Error bad datatype of image tile to compress");
              free(tiledata);
              return (*status);
          }

          /* now compress the tile, and write to row of binary table */
          /*   NOTE: we don't have to worry about the presence of null values in the
	       array if it is an integer array:  the null value is simply encoded
	       in the compressed array just like any other pixel value.  
	       
	       If it is a floating point array, then we need to check for null
	       only if the anynul parameter returned a true value when reading the tile
	  */
          if (anynul && datatype == TFLOAT) {
              imcomp_compress_tile(outfptr, row, datatype, tiledata, tilelen,
                               tile[0], tile[1], 1, &fltnull, status);
          } else if (anynul && datatype == TDOUBLE) {
              imcomp_compress_tile(outfptr, row, datatype, tiledata, tilelen,
                               tile[0], tile[1], 1, &dblnull, status);
          } else {
              imcomp_compress_tile(outfptr, row, datatype, tiledata, tilelen,
                               tile[0], tile[1], 0, &dummy, status);
          }

          /* set flag if we found any null values */
          if (anynul)
              gotnulls = 1;

          /* check for any error in the previous operations */
          if (*status > 0)
          {
              ffpmsg("Error writing compressed image to table");
              free(tiledata);
              return (*status);
          }

	  row++;
         }
        }
       }
      }
     }
    }

    free (tiledata);  /* finished with this buffer */

    /* insert ZBLANK keyword if necessary; only for TFLOAT or TDOUBLE images */
    if (gotnulls)
    {
          ffgcrd(outfptr, "ZCMPTYPE", card, status);
          ffikyj(outfptr, "ZBLANK", COMPRESS_NULL_VALUE, 
             "null value in the compressed integer array", status);
    }

    return (*status);
}
/*--------------------------------------------------------------------------*/
int imcomp_compress_tile (fitsfile *outfptr,
    long row,  /* tile number = row in the binary table that holds the compressed data */
    int datatype, 
    void *tiledata, 
    long tilelen,
    long tilenx,
    long tileny,
    int nullcheck,
    void *nullflagval,
    int *status)

/*
   This is the main compression routine.

   This routine does the following to the input tile of pixels:
        - if it is a float or double image, then it quantizes the pixels
        - compresses the integer pixel values
        - writes the compressed byte stream to the FITS file.

   If the tile cannot be quantized than the raw float or double values
   are losslessly compressed with gzip and then written to the output table.
   
   This input array may be modified by this routine.  If the array is of type TINT
   or TFLOAT, and the compression type is HCOMPRESS, then it must have been 
   allocated to be twice as large (8 bytes per pixel) to provide scratch space.

  Note that this routine does not fully support the implicit datatype conversion that
  is supported when writing to normal FITS images.  The datatype of the input array
  must have the same datatype (either signed or unsigned) as the output (compressed)
  FITS image in some cases.
*/
{
    int *idata;		/* quantized integer data */
    int cn_zblank, zbitpix, nullval;
    int flag = 1;  /* true by default; only = 0 if float data couldn't be quantized */
    int intlength;      /* size of integers to be compressed */
    double scale, zero, actual_bzero;
    long ii;
    size_t clen;		/* size of cbuf */
    short *cbuf;	/* compressed data */
    int  nelem = 0;		/* number of bytes */
    int tilecol;
    size_t gzip_nelem = 0;
    unsigned int bzlen;
    int ihcompscale;
    float hcompscale;
    double noise2, noise3, noise5;
    double bscale[1] = {1.}, bzero[1] = {0.};	/* scaling parameters */
    long  hcomp_len;
    LONGLONG *lldata;

    if (*status > 0)
        return(*status);

    /* check for special case of losslessly compressing floating point */
    /* images.  Only compression algorithm that supports this is GZIP */
    if ( (outfptr->Fptr)->quantize_level == NO_QUANTIZE) {
       if (((outfptr->Fptr)->compress_type != GZIP_1) &&
           ((outfptr->Fptr)->compress_type != GZIP_2)) {
           switch (datatype) {
            case TFLOAT:
            case TDOUBLE:
            case TCOMPLEX:
            case TDBLCOMPLEX:
              ffpmsg("Lossless compression of floating point images must use GZIP (imcomp_compress_tile)");
              return(*status = DATA_COMPRESSION_ERR);
            default:
              break;
          }
       }
    }

    /* free the previously saved tile if the input tile is for the same row */
    if ((outfptr->Fptr)->tilerow) {  /* has the tile cache been allocated? */

      /* calculate the column bin of the compressed tile */
      tilecol = (row - 1) % ((long)(((outfptr->Fptr)->znaxis[0] - 1) / ((outfptr->Fptr)->tilesize[0])) + 1);
      
      if ((outfptr->Fptr)->tilerow[tilecol] == row) {
        if (((outfptr->Fptr)->tiledata)[tilecol]) {
            free(((outfptr->Fptr)->tiledata)[tilecol]);
        }
	  
        if (((outfptr->Fptr)->tilenullarray)[tilecol]) {
            free(((outfptr->Fptr)->tilenullarray)[tilecol]);
        }

        ((outfptr->Fptr)->tiledata)[tilecol] = 0;
        ((outfptr->Fptr)->tilenullarray)[tilecol] = 0;
        (outfptr->Fptr)->tilerow[tilecol] = 0;
        (outfptr->Fptr)->tiledatasize[tilecol] = 0;
        (outfptr->Fptr)->tiletype[tilecol] = 0;
        (outfptr->Fptr)->tileanynull[tilecol] = 0;
      }
    }

    if ( (outfptr->Fptr)->compress_type == NOCOMPRESS) {
         /* Special case when using NOCOMPRESS for diagnostic purposes in fpack */
         if (imcomp_write_nocompress_tile(outfptr, row, datatype, tiledata, tilelen, 
	     nullcheck, nullflagval, status) > 0) {
             return(*status);
         }
         return(*status);
    }

    /* =========================================================================== */
    /* initialize various parameters */
    idata = (int *) tiledata;   /* may overwrite the input tiledata in place */

    /* zbitpix is the BITPIX keyword value in the uncompressed FITS image */
    zbitpix = (outfptr->Fptr)->zbitpix;

    /* if the tile/image has an integer datatype, see if a null value has */
    /* been defined (with the BLANK keyword in a normal FITS image).  */
    /* If so, and if the input tile array also contains null pixels, */
    /* (represented by pixels that have a value = nullflagval) then  */
    /* any pixels whose value = nullflagval, must be set to the value = nullval */
    /* before the pixel array is compressed.  These null pixel values must */
    /* not be inverse scaled by the BSCALE/BZERO values, if present. */

    cn_zblank = (outfptr->Fptr)->cn_zblank;
    nullval = (outfptr->Fptr)->zblank;

    if (zbitpix > 0 && cn_zblank != -1)  /* If the integer image has no defined null */
        nullcheck = 0;    /* value, then don't bother checking input array for nulls. */

    /* if the BSCALE and BZERO keywords exist, then the input values must */
    /* be inverse scaled by this factor, before the values are compressed. */
    /* (The program may have turned off scaling, which over rides the keywords) */
    
    scale = (outfptr->Fptr)->cn_bscale;
    zero  = (outfptr->Fptr)->cn_bzero;
    actual_bzero = (outfptr->Fptr)->cn_actual_bzero;

    /* =========================================================================== */
    /* prepare the tile of pixel values for compression */
    if (datatype == TSHORT) {
       imcomp_convert_tile_tshort(outfptr, tiledata, tilelen, nullcheck, nullflagval,
           nullval, zbitpix, scale, zero, actual_bzero, &intlength, status);
    } else if (datatype == TUSHORT) {
       imcomp_convert_tile_tushort(outfptr, tiledata, tilelen, nullcheck, nullflagval,
           nullval, zbitpix, scale, zero, &intlength, status);
    } else if (datatype == TBYTE) {
       imcomp_convert_tile_tbyte(outfptr, tiledata, tilelen, nullcheck, nullflagval,
           nullval, zbitpix, scale, zero,  &intlength, status);
    } else if (datatype == TSBYTE) {
       imcomp_convert_tile_tsbyte(outfptr, tiledata, tilelen, nullcheck, nullflagval,
           nullval, zbitpix, scale, zero,  &intlength, status);
    } else if (datatype == TINT) {
       imcomp_convert_tile_tint(outfptr, tiledata, tilelen, nullcheck, nullflagval,
           nullval, zbitpix, scale, zero, &intlength, status);
    } else if (datatype == TUINT) {
       imcomp_convert_tile_tuint(outfptr, tiledata, tilelen, nullcheck, nullflagval,
           nullval, zbitpix, scale, zero, &intlength, status);
    } else if (datatype == TLONG && sizeof(long) == 8) {
           ffpmsg("Integer*8 Long datatype is not supported when writing to compressed images");
           return(*status = BAD_DATATYPE);
    } else if (datatype == TULONG && sizeof(long) == 8) {
           ffpmsg("Unsigned integer*8 datatype is not supported when writing to compressed images");
           return(*status = BAD_DATATYPE);
    } else if (datatype == TFLOAT) {
        imcomp_convert_tile_tfloat(outfptr, row, tiledata, tilelen, tilenx, tileny, nullcheck,
        nullflagval, nullval, zbitpix, scale, zero, &intlength, &flag, bscale, bzero, status);
    } else if (datatype == TDOUBLE) {
       imcomp_convert_tile_tdouble(outfptr, row, tiledata, tilelen, tilenx, tileny, nullcheck,
       nullflagval, nullval, zbitpix, scale, zero, &intlength, &flag, bscale, bzero, status);
    } else {
          ffpmsg("unsupported image datatype (imcomp_compress_tile)");
          return(*status = BAD_DATATYPE);
    }

    if (*status > 0)
      return(*status);      /* return if error occurs */

    /* =========================================================================== */
    if (flag)   /* now compress the integer data array */
    {
        /* allocate buffer for the compressed tile bytes */
        clen = (outfptr->Fptr)->maxelem;
        cbuf = (short *) calloc (clen, sizeof (unsigned char));

        if (cbuf == NULL) {
            ffpmsg("Memory allocation failure. (imcomp_compress_tile)");
	    return (*status = MEMORY_ALLOCATION);
        }

        /* =========================================================================== */
        if ( (outfptr->Fptr)->compress_type == RICE_1)
        {
            if (intlength == 2) {
  	        nelem = fits_rcomp_short ((short *)idata, tilelen, (unsigned char *) cbuf,
                       clen, (outfptr->Fptr)->rice_blocksize);
            } else if (intlength == 1) {
  	        nelem = fits_rcomp_byte ((signed char *)idata, tilelen, (unsigned char *) cbuf,
                       clen, (outfptr->Fptr)->rice_blocksize);
            } else {
  	        nelem = fits_rcomp (idata, tilelen, (unsigned char *) cbuf,
                       clen, (outfptr->Fptr)->rice_blocksize);
            }

	    if (nelem < 0)  /* data compression error condition */
            {
	        free (cbuf);
                ffpmsg("error Rice compressing image tile (imcomp_compress_tile)");
                return (*status = DATA_COMPRESSION_ERR);
            }

	    /* Write the compressed byte stream. */
            ffpclb(outfptr, (outfptr->Fptr)->cn_compressed, row, 1,
                     nelem, (unsigned char *) cbuf, status);
        }

        /* =========================================================================== */
        else if ( (outfptr->Fptr)->compress_type == PLIO_1)
        {
              for (ii = 0; ii < tilelen; ii++)  {
                if (idata[ii] < 0 || idata[ii] > 16777215)
                {
                   /* plio algorithn only supports positive 24 bit ints */
                   ffpmsg("data out of range for PLIO compression (0 - 2**24)");
                   return(*status = DATA_COMPRESSION_ERR);
                }
              }

  	      nelem = pl_p2li (idata, 1, cbuf, tilelen);

	      if (nelem < 0)  /* data compression error condition */
              {
	        free (cbuf);
                ffpmsg("error PLIO compressing image tile (imcomp_compress_tile)");
                return (*status = DATA_COMPRESSION_ERR);
              }

	      /* Write the compressed byte stream. */
              ffpcli(outfptr, (outfptr->Fptr)->cn_compressed, row, 1,
                     nelem, cbuf, status);
        }

        /* =========================================================================== */
        else if ( ((outfptr->Fptr)->compress_type == GZIP_1) ||
                  ((outfptr->Fptr)->compress_type == GZIP_2) )   {

	    if ((outfptr->Fptr)->quantize_level == NO_QUANTIZE && datatype == TFLOAT) {
	      /* Special case of losslessly compressing floating point pixels with GZIP */
	      /* In this case we compress the input tile array directly */

#if BYTESWAPPED
               ffswap4((int*) tiledata, tilelen); 
#endif
               if ( (outfptr->Fptr)->compress_type == GZIP_2 )
		    fits_shuffle_4bytes((char *) tiledata, tilelen, status);

                compress2mem_from_mem((char *) tiledata, tilelen * sizeof(float),
                    (char **) &cbuf,  &clen, realloc, &gzip_nelem, status);

	    } else if ((outfptr->Fptr)->quantize_level == NO_QUANTIZE && datatype == TDOUBLE) {
	      /* Special case of losslessly compressing double pixels with GZIP */
	      /* In this case we compress the input tile array directly */

#if BYTESWAPPED
               ffswap8((double *) tiledata, tilelen); 
#endif
               if ( (outfptr->Fptr)->compress_type == GZIP_2 )
		    fits_shuffle_8bytes((char *) tiledata, tilelen, status);

                compress2mem_from_mem((char *) tiledata, tilelen * sizeof(double),
                    (char **) &cbuf,  &clen, realloc, &gzip_nelem, status);

	    } else {

	        /* compress the integer idata array */

#if BYTESWAPPED
	       if (intlength == 2)
                 ffswap2((short *) idata, tilelen); 
	       else if (intlength == 4)
                 ffswap4(idata, tilelen); 
#endif

               if (intlength == 2) {

                  if ( (outfptr->Fptr)->compress_type == GZIP_2 )
		    fits_shuffle_2bytes((char *) tiledata, tilelen, status);

                  compress2mem_from_mem((char *) idata, tilelen * sizeof(short),
                   (char **) &cbuf,  &clen, realloc, &gzip_nelem, status);

               } else if (intlength == 1) {

                  compress2mem_from_mem((char *) idata, tilelen * sizeof(unsigned char),
                   (char **) &cbuf,  &clen, realloc, &gzip_nelem, status);

               } else {

                  if ( (outfptr->Fptr)->compress_type == GZIP_2 )
		    fits_shuffle_4bytes((char *) tiledata, tilelen, status);

                  compress2mem_from_mem((char *) idata, tilelen * sizeof(int),
                   (char **) &cbuf,  &clen, realloc, &gzip_nelem, status);
               }
            }

	    /* Write the compressed byte stream. */
            ffpclb(outfptr, (outfptr->Fptr)->cn_compressed, row, 1,
                     gzip_nelem, (unsigned char *) cbuf, status);

        /* =========================================================================== */
        } else if ( (outfptr->Fptr)->compress_type == BZIP2_1) {

#if BYTESWAPPED
	   if (intlength == 2)
               ffswap2((short *) idata, tilelen); 
	   else if (intlength == 4)
               ffswap4(idata, tilelen); 
#endif

           bzlen = (unsigned int) clen;
	   
           /* call bzip2 with blocksize = 900K, verbosity = 0, and default workfactor */

/*  bzip2 is not supported in the public release.  This is only for test purposes.
           if (BZ2_bzBuffToBuffCompress( (char *) cbuf, &bzlen,
	         (char *) idata, (unsigned int) (tilelen * intlength), 9, 0, 0) ) 
*/
	   {
                   ffpmsg("bzip2 compression error");
                   return(*status = DATA_COMPRESSION_ERR);
           }

	    /* Write the compressed byte stream. */
            ffpclb(outfptr, (outfptr->Fptr)->cn_compressed, row, 1,
                     bzlen, (unsigned char *) cbuf, status);

        /* =========================================================================== */
        }  else if ( (outfptr->Fptr)->compress_type == HCOMPRESS_1)     {
	    /*
	      if hcompscale is positive, then we have to multiply
	      the value by the RMS background noise to get the 
	      absolute scale value.  If negative, then it gives the
	      absolute scale value directly.
	    */
            hcompscale = (outfptr->Fptr)->hcomp_scale;

	    if (hcompscale > 0.) {
	       fits_img_stats_int(idata, tilenx, tileny, nullcheck,
	                nullval, 0,0,0,0,0,0,&noise2,&noise3,&noise5,status);

		/* use the minimum of the 3 noise estimates */
		if (noise2 != 0. && noise2 < noise3) noise3 = noise2;
		if (noise5 != 0. && noise5 < noise3) noise3 = noise5;
		
		hcompscale = (float) (hcompscale * noise3);

	    } else if (hcompscale < 0.) {

		hcompscale = hcompscale * -1.0F;
	    }

	    ihcompscale = (int) (hcompscale + 0.5);

            hcomp_len = clen;  /* allocated size of the buffer */
	    
            if (zbitpix == BYTE_IMG || zbitpix == SHORT_IMG) {
                fits_hcompress(idata, tilenx, tileny, 
		  ihcompscale, (char *) cbuf, &hcomp_len, status);

            } else {
                 /* have to convert idata to an I*8 array, in place */
                 /* idata must have been allocated large enough to do this */

                fits_int_to_longlong_inplace(idata, tilelen, status);
                lldata = (LONGLONG *) idata;		

                fits_hcompress64(lldata, tilenx, tileny, 
		  ihcompscale, (char *) cbuf, &hcomp_len, status);
            }

	    /* Write the compressed byte stream. */
            ffpclb(outfptr, (outfptr->Fptr)->cn_compressed, row, 1,
                     hcomp_len, (unsigned char *) cbuf, status);
        }

        /* =========================================================================== */
        if ((outfptr->Fptr)->cn_zscale > 0)
        {
              /* write the linear scaling parameters for this tile */
	      ffpcld (outfptr, (outfptr->Fptr)->cn_zscale, row, 1, 1,
                      bscale, status);
	      ffpcld (outfptr, (outfptr->Fptr)->cn_zzero,  row, 1, 1,
                      bzero,  status);
        }

        free(cbuf);  /* finished with this buffer */

    /* =========================================================================== */
    } else {    /* if flag == 0., floating point data couldn't be quantized */

	 /* losslessly compress the data with gzip. */

         /* if gzip2 compressed data column doesn't exist, create it */
         if ((outfptr->Fptr)->cn_gzip_data < 1) {
              if ( (outfptr->Fptr)->request_huge_hdu != 0) {
                 fits_insert_col(outfptr, 999, "GZIP_COMPRESSED_DATA", "1QB", status);
              } else {
                 fits_insert_col(outfptr, 999, "GZIP_COMPRESSED_DATA", "1PB", status);
              }

                 if (*status <= 0)  /* save the number of this column */
                       ffgcno(outfptr, CASEINSEN, "GZIP_COMPRESSED_DATA",
                                &(outfptr->Fptr)->cn_gzip_data, status);
         }

         if (datatype == TFLOAT)  {
               /* allocate buffer for the compressed tile bytes */
	       /* make it 10% larger than the original uncompressed data */
               clen = (size_t) (tilelen * sizeof(float) * 1.1);
               cbuf = (short *) calloc (clen, sizeof (unsigned char));

               if (cbuf == NULL)
               {
                   ffpmsg("Memory allocation error. (imcomp_compress_tile)");
	           return (*status = MEMORY_ALLOCATION);
               }

	       /* convert null values to NaNs in place, if necessary */
	       if (nullcheck == 1) {
	           imcomp_float2nan((float *) tiledata, tilelen, (int *) tiledata,
	               *(float *) (nullflagval), status);
	       }

#if BYTESWAPPED
               ffswap4((int*) tiledata, tilelen); 
#endif
               compress2mem_from_mem((char *) tiledata, tilelen * sizeof(float),
                    (char **) &cbuf,  &clen, realloc, &gzip_nelem, status);

         } else {  /* datatype == TDOUBLE */

               /* allocate buffer for the compressed tile bytes */
	       /* make it 10% larger than the original uncompressed data */
               clen = (size_t) (tilelen * sizeof(double) * 1.1);
               cbuf = (short *) calloc (clen, sizeof (unsigned char));

               if (cbuf == NULL)
               {
                   ffpmsg("Memory allocation error. (imcomp_compress_tile)");
	           return (*status = MEMORY_ALLOCATION);
               }

	       /* convert null values to NaNs in place, if necessary */
	       if (nullcheck == 1) {
	           imcomp_double2nan((double *) tiledata, tilelen, (LONGLONG *) tiledata,
	               *(double *) (nullflagval), status);
	       }

#if BYTESWAPPED
               ffswap8((double*) tiledata, tilelen); 
#endif
               compress2mem_from_mem((char *) tiledata, tilelen * sizeof(double),
                    (char **) &cbuf,  &clen, realloc, &gzip_nelem, status);
        }

	/* Write the compressed byte stream. */
        ffpclb(outfptr, (outfptr->Fptr)->cn_gzip_data, row, 1,
             gzip_nelem, (unsigned char *) cbuf, status);

        free(cbuf);  /* finished with this buffer */
    }

    return(*status);
}

/*--------------------------------------------------------------------------*/
int imcomp_write_nocompress_tile(fitsfile *outfptr,
    long row,
    int datatype, 
    void *tiledata, 
    long tilelen,
    int nullcheck,
    void *nullflagval,
    int *status)
{
    char coltype[4];

    /* Write the uncompressed image tile pixels to the tile-compressed image file. */
    /* This is a special case when using NOCOMPRESS for diagnostic purposes in fpack. */ 
    /* Currently, this only supports a limited number of data types and */
    /* does not fully support null-valued pixels in the image. */

    if ((outfptr->Fptr)->cn_uncompressed < 1) {
        /* uncompressed data column doesn't exist, so append new column to table */
        if (datatype == TSHORT) {
	    strcpy(coltype, "1PI");
	} else if (datatype == TINT) {
	    strcpy(coltype, "1PJ");
	} else if (datatype == TFLOAT) {
	    strcpy(coltype, "1QE");
        } else {
	    ffpmsg("NOCOMPRESSION option only supported for int*2, int*4, and float*4 images");
            return(*status = DATA_COMPRESSION_ERR);
        }

        fits_insert_col(outfptr, 999, "UNCOMPRESSED_DATA", coltype, status); /* create column */
    }

    fits_get_colnum(outfptr, CASEINSEN, "UNCOMPRESSED_DATA",
                    &(outfptr->Fptr)->cn_uncompressed, status);  /* save col. num. */
    
    fits_write_col(outfptr, datatype, (outfptr->Fptr)->cn_uncompressed, row, 1,
                      tilelen, tiledata, status);  /* write the tile data */
    return (*status);
}
 /*--------------------------------------------------------------------------*/
int imcomp_convert_tile_tshort(
    fitsfile *outfptr,
    void *tiledata, 
    long tilelen,
    int nullcheck,
    void *nullflagval,
    int nullval,
    int zbitpix,
    double scale,
    double zero,
    double actual_bzero,
    int *intlength,
    int *status)
{
    /*  Prepare the input tile array of pixels for compression. */
    /*  Convert input integer*2 tile array in place to 4 or 8-byte ints for compression, */
    /*  If needed, convert 4 or 8-byte ints and do null value substitution. */
    /*  Note that the calling routine must have allocated the input array big enough */
    /* to be able to do this.  */

    short *sbuff;
    int flagval, *idata;
    long ii;
    
       /* We only support writing this integer*2 tile data to a FITS image with 
          BITPIX = 16 and with BZERO = 0 and BSCALE = 1.  */
	  
       if (zbitpix != SHORT_IMG || scale != 1.0 || zero != 0.0) {
           ffpmsg("Datatype conversion/scaling is not supported when writing to compressed images");
           return(*status = DATA_COMPRESSION_ERR);
       } 

       sbuff = (short *) tiledata;
       idata = (int *) tiledata;
       
       if ( (outfptr->Fptr)->compress_type == RICE_1 || (outfptr->Fptr)->compress_type == GZIP_1
         || (outfptr->Fptr)->compress_type == GZIP_2 || (outfptr->Fptr)->compress_type == BZIP2_1 ) 
       {
           /* don't have to convert to int if using gzip, bzip2 or Rice compression */
           *intlength = 2;
             
           if (nullcheck == 1) {
               /* reset pixels equal to flagval to the FITS null value, prior to compression */
               flagval = *(short *) (nullflagval);
               if (flagval != nullval) {
                  for (ii = tilelen - 1; ii >= 0; ii--) {
	            if (sbuff[ii] == (short) flagval)
		       sbuff[ii] = (short) nullval;
                  }
               }
           }
       } else if ((outfptr->Fptr)->compress_type == HCOMPRESS_1) {
           /* have to convert to int if using HCOMPRESS */
           *intlength = 4;

           if (nullcheck == 1) {
               /* reset pixels equal to flagval to the FITS null value, prior to compression */
               flagval = *(short *) (nullflagval);
               for (ii = tilelen - 1; ii >= 0; ii--) {
	            if (sbuff[ii] == (short) flagval)
		       idata[ii] = nullval;
                    else 
                       idata[ii] = (int) sbuff[ii];
               }
           } else {  /* just do the data type conversion to int */
                 /* have to convert sbuff to an I*4 array, in place */
                 /* sbuff must have been allocated large enough to do this */
                 fits_short_to_int_inplace(sbuff, tilelen, status);
           }
       } else {
           /* have to convert to int if using PLIO */
           *intlength = 4;
           if (zero == 0. && actual_bzero == 32768.) {
             /* Here we are compressing unsigned 16-bit integers that have */
	     /* been offset by -32768 using the standard FITS convention. */
	     /* Since PLIO cannot deal with negative values, we must apply */
	     /* the shift of 32786 to the values to make them all positive. */
	     /* The inverse negative shift will be applied in */
	     /* imcomp_decompress_tile when reading the compressed tile. */
             if (nullcheck == 1) {
               /* reset pixels equal to flagval to the FITS null value, prior to compression */
               flagval = *(short *) (nullflagval);
               for (ii = tilelen - 1; ii >= 0; ii--) {
	            if (sbuff[ii] == (short) flagval)
		       idata[ii] = nullval;
                    else
                       idata[ii] = (int) sbuff[ii] + 32768;
               }
             } else {  /* just do the data type conversion to int */
                 /* have to convert sbuff to an I*4 array, in place */
                 /* sbuff must have been allocated large enough to do this */
                 fits_short_to_int_inplace(sbuff, tilelen, status);
             }
           } else {
	     /* This is not an unsigned 16-bit integer array, so process normally */
             if (nullcheck == 1) {
               /* reset pixels equal to flagval to the FITS null value, prior to compression */
               flagval = *(short *) (nullflagval);
               for (ii = tilelen - 1; ii >= 0; ii--) {
	            if (sbuff[ii] == (short) flagval)
		       idata[ii] = nullval;
                    else
                       idata[ii] = (int) sbuff[ii];
               }
             } else {  /* just do the data type conversion to int */
                 /* have to convert sbuff to an I*4 array, in place */
                 /* sbuff must have been allocated large enough to do this */
                 fits_short_to_int_inplace(sbuff, tilelen, status);
             }
           }
        }
        return(*status);
}
 /*--------------------------------------------------------------------------*/
int imcomp_convert_tile_tushort(
    fitsfile *outfptr,
    void *tiledata, 
    long tilelen,
    int nullcheck,
    void *nullflagval,
    int nullval,
    int zbitpix,
    double scale,
    double zero,
    int *intlength,
    int *status)
{
    /*  Prepare the input  tile array of pixels for compression. */
    /*  Convert input unsigned integer*2 tile array in place to 4 or 8-byte ints for compression, */
    /*  If needed, convert 4 or 8-byte ints and do null value substitution. */
    /*  Note that the calling routine must have allocated the input array big enough */
    /* to be able to do this.  */

    unsigned short *usbuff;
    short *sbuff;
    int flagval, *idata;
    long ii;
    
       /* datatype of input array is unsigned short.  We only support writing this datatype
          to a FITS image with BITPIX = 16 and with BZERO = 0 and BSCALE = 32768.  */

       if (zbitpix != SHORT_IMG || scale != 1.0 || zero != 32768.) {
           ffpmsg("Implicit datatype conversion is not supported when writing to compressed images");
           return(*status = DATA_COMPRESSION_ERR);
       } 

       usbuff = (unsigned short *) tiledata;
       sbuff = (short *) tiledata;
       idata = (int *) tiledata;

       if ((outfptr->Fptr)->compress_type == RICE_1 || (outfptr->Fptr)->compress_type == GZIP_1
        || (outfptr->Fptr)->compress_type == GZIP_2 || (outfptr->Fptr)->compress_type == BZIP2_1) 
       {
           /* don't have to convert to int if using gzip, bzip2, or Rice compression */
           *intlength = 2;

          /* offset the unsigned value by -32768 to a signed short value. */
	  /* It is more efficient to do this by just flipping the most significant of the 16 bits */

           if (nullcheck == 1) {
               /* reset pixels equal to flagval to the FITS null value, prior to compression  */
               flagval = *(unsigned short *) (nullflagval);
               for (ii = tilelen - 1; ii >= 0; ii--) {
	            if (usbuff[ii] == (unsigned short) flagval)
		       sbuff[ii] = (short) nullval;
                    else
		       usbuff[ii] =  (usbuff[ii]) ^ 0x8000;
               }
           } else {
               /* just offset the pixel values by 32768 (by flipping the MSB */
               for (ii = tilelen - 1; ii >= 0; ii--)
		       usbuff[ii] =  (usbuff[ii]) ^ 0x8000;
           }
       } else {
           /* have to convert to int if using HCOMPRESS or PLIO */
           *intlength = 4;

           if (nullcheck == 1) {
               /* offset the pixel values by 32768, and */
               /* reset pixels equal to flagval to nullval */
               flagval = *(unsigned short *) (nullflagval);
               for (ii = tilelen - 1; ii >= 0; ii--) {
	            if (usbuff[ii] == (unsigned short) flagval)
		       idata[ii] = nullval;
                    else
		       idata[ii] = ((int) usbuff[ii]) - 32768;
               }
           } else {  /* just do the data type conversion to int */
                 /* have to convert usbuff to an I*4 array, in place */
                 /* usbuff must have been allocated large enough to do this */
                 fits_ushort_to_int_inplace(usbuff, tilelen, status);
           }
        }

        return(*status);
}
 /*--------------------------------------------------------------------------*/
int imcomp_convert_tile_tint(
    fitsfile *outfptr,
    void *tiledata, 
    long tilelen,
    int nullcheck,
    void *nullflagval,
    int nullval,
    int zbitpix,
    double scale,
    double zero,
    int *intlength,
    int *status)
{
    /*  Prepare the input tile array of pixels for compression. */
    /*  Convert input integer tile array in place to 4 or 8-byte ints for compression, */
    /*  If needed, do null value substitution. */
   
    int flagval, *idata;
    long ii;
    
 
        /* datatype of input array is int.  We only support writing this datatype
           to a FITS image with BITPIX = 32 and with BZERO = 0 and BSCALE = 1.  */

       if (zbitpix != LONG_IMG || scale != 1.0 || zero != 0.) {
           ffpmsg("Implicit datatype conversion is not supported when writing to compressed images");
           return(*status = DATA_COMPRESSION_ERR);
       } 

       idata = (int *) tiledata;
       *intlength = 4;

       if (nullcheck == 1) {
               /* no datatype conversion is required for any of the compression algorithms,
	         except possibly for HCOMPRESS (to I*8), which is handled later.
		 Just reset pixels equal to flagval to the FITS null value */
               flagval = *(int *) (nullflagval);
               if (flagval != nullval) {
                  for (ii = tilelen - 1; ii >= 0; ii--) {
	            if (idata[ii] == flagval)
		       idata[ii] = nullval;
                  }
               }
       }

       return(*status);
}
 /*--------------------------------------------------------------------------*/
int imcomp_convert_tile_tuint(
    fitsfile *outfptr,
    void *tiledata, 
    long tilelen,
    int nullcheck,
    void *nullflagval,
    int nullval,
    int zbitpix,
    double scale,
    double zero,
    int *intlength,
    int *status)
{
    /*  Prepare the input tile array of pixels for compression. */
    /*  Convert input unsigned integer tile array in place to 4 or 8-byte ints for compression, */
    /*  If needed, do null value substitution. */


    int *idata;
    unsigned int *uintbuff, uintflagval;
    long ii;
 
       /* datatype of input array is unsigned int.  We only support writing this datatype
          to a FITS image with BITPIX = 32 and with BZERO = 0 and BSCALE = 2147483648.  */

       if (zbitpix != LONG_IMG || scale != 1.0 || zero != 2147483648.) {
           ffpmsg("Implicit datatype conversion is not supported when writing to compressed images");
           return(*status = DATA_COMPRESSION_ERR);
       } 

       *intlength = 4;
       idata = (int *) tiledata;
       uintbuff = (unsigned int *) tiledata;

       /* offset the unsigned value by -2147483648 to a signed int value. */
       /* It is more efficient to do this by just flipping the most significant of the 32 bits */

       if (nullcheck == 1) {
               /* reset pixels equal to flagval to nullval and */
               /* offset the other pixel values (by flipping the MSB) */
               uintflagval = *(unsigned int *) (nullflagval);
               for (ii = tilelen - 1; ii >= 0; ii--) {
	            if (uintbuff[ii] == uintflagval)
		       idata[ii] = nullval;
                    else
		       uintbuff[ii] = (uintbuff[ii]) ^ 0x80000000;
               }
       } else {
               /* just offset the pixel values (by flipping the MSB) */
               for (ii = tilelen - 1; ii >= 0; ii--)
		       uintbuff[ii] = (uintbuff[ii]) ^ 0x80000000;
       }

       return(*status);
}
 /*--------------------------------------------------------------------------*/
int imcomp_convert_tile_tbyte(
    fitsfile *outfptr,
    void *tiledata, 
    long tilelen,
    int nullcheck,
    void *nullflagval,
    int nullval,
    int zbitpix,
    double scale,
    double zero,
    int *intlength,
    int *status)
{
    /*  Prepare the input tile array of pixels for compression. */
    /*  Convert input unsigned integer*1 tile array in place to 4 or 8-byte ints for compression, */
    /*  If needed, convert 4 or 8-byte ints and do null value substitution. */
    /*  Note that the calling routine must have allocated the input array big enough */
    /* to be able to do this.  */

    int flagval, *idata;
    long ii;
    unsigned char *usbbuff;
        
       /* datatype of input array is unsigned byte.  We only support writing this datatype
          to a FITS image with BITPIX = 8 and with BZERO = 0 and BSCALE = 1.  */

       if (zbitpix != BYTE_IMG || scale != 1.0 || zero != 0.) {
           ffpmsg("Implicit datatype conversion is not supported when writing to compressed images");
           return(*status = DATA_COMPRESSION_ERR);
       } 

       idata = (int *) tiledata;
       usbbuff = (unsigned char *) tiledata;

       if ( (outfptr->Fptr)->compress_type == RICE_1 || (outfptr->Fptr)->compress_type == GZIP_1
         || (outfptr->Fptr)->compress_type == GZIP_2 || (outfptr->Fptr)->compress_type == BZIP2_1 ) 
       {
           /* don't have to convert to int if using gzip, bzip2, or Rice compression */
           *intlength = 1;
             
           if (nullcheck == 1) {
               /* reset pixels equal to flagval to the FITS null value, prior to compression */
               flagval = *(unsigned char *) (nullflagval);
               if (flagval != nullval) {
                  for (ii = tilelen - 1; ii >= 0; ii--) {
	            if (usbbuff[ii] == (unsigned char) flagval)
		       usbbuff[ii] = (unsigned char) nullval;
                    }
               }
           }
       } else {
           /* have to convert to int if using HCOMPRESS or PLIO */
           *intlength = 4;

           if (nullcheck == 1) {
               /* reset pixels equal to flagval to the FITS null value, prior to compression */
               flagval = *(unsigned char *) (nullflagval);
               for (ii = tilelen - 1; ii >= 0; ii--) {
	            if (usbbuff[ii] == (unsigned char) flagval)
		       idata[ii] = nullval;
                    else
                       idata[ii] = (int) usbbuff[ii];
               }
           } else {  /* just do the data type conversion to int */
                 /* have to convert usbbuff to an I*4 array, in place */
                 /* usbbuff must have been allocated large enough to do this */
                 fits_ubyte_to_int_inplace(usbbuff, tilelen, status);
           }
       }

       return(*status);
}
 /*--------------------------------------------------------------------------*/
int imcomp_convert_tile_tsbyte(
    fitsfile *outfptr,
    void *tiledata, 
    long tilelen,
    int nullcheck,
    void *nullflagval,
    int nullval,
    int zbitpix,
    double scale,
    double zero,
    int *intlength,
    int *status)
{
    /*  Prepare the input tile array of pixels for compression. */
    /*  Convert input integer*1 tile array in place to 4 or 8-byte ints for compression, */
    /*  If needed, convert 4 or 8-byte ints and do null value substitution. */
    /*  Note that the calling routine must have allocated the input array big enough */
    /* to be able to do this.  */

    int flagval, *idata;
    long ii;
    signed char *sbbuff;

       /* datatype of input array is signed byte.  We only support writing this datatype
          to a FITS image with BITPIX = 8 and with BZERO = 0 and BSCALE = -128.  */

       if (zbitpix != BYTE_IMG|| scale != 1.0 || zero != -128.) {
           ffpmsg("Implicit datatype conversion is not supported when writing to compressed images");
           return(*status = DATA_COMPRESSION_ERR);
       }

       idata = (int *) tiledata;
       sbbuff = (signed char *) tiledata;

       if ( (outfptr->Fptr)->compress_type == RICE_1 || (outfptr->Fptr)->compress_type == GZIP_1
         || (outfptr->Fptr)->compress_type == GZIP_2 || (outfptr->Fptr)->compress_type == BZIP2_1 ) 
       {
           /* don't have to convert to int if using gzip, bzip2 or Rice compression */
           *intlength = 1;
             
           if (nullcheck == 1) {
               /* reset pixels equal to flagval to the FITS null value, prior to compression */
               /* offset the other pixel values (by flipping the MSB) */

               flagval = *(signed char *) (nullflagval);
               for (ii = tilelen - 1; ii >= 0; ii--) {
	            if (sbbuff[ii] == (signed char) flagval)
		       sbbuff[ii] = (signed char) nullval;
                    else
		       sbbuff[ii] = (sbbuff[ii]) ^ 0x80;               }
           } else {  /* just offset the pixel values (by flipping the MSB) */
               for (ii = tilelen - 1; ii >= 0; ii--) 
		       sbbuff[ii] = (sbbuff[ii]) ^ 0x80;
           }

       } else {
           /* have to convert to int if using HCOMPRESS or PLIO */
           *intlength = 4;

           if (nullcheck == 1) {
               /* reset pixels equal to flagval to the FITS null value, prior to compression */
               flagval = *(signed char *) (nullflagval);
               for (ii = tilelen - 1; ii >= 0; ii--) {
	            if (sbbuff[ii] == (signed char) flagval)
		       idata[ii] = nullval;
                    else
                       idata[ii] = ((int) sbbuff[ii]) + 128;
               }
           } else {  /* just do the data type conversion to int */
                 /* have to convert sbbuff to an I*4 array, in place */
                 /* sbbuff must have been allocated large enough to do this */
                 fits_sbyte_to_int_inplace(sbbuff, tilelen, status);
           }
       }
 
       return(*status);
}
 /*--------------------------------------------------------------------------*/
int imcomp_convert_tile_tfloat(
    fitsfile *outfptr,
    long row,
    void *tiledata, 
    long tilelen,
    long tilenx,
    long tileny,
    int nullcheck,
    void *nullflagval,
    int nullval,
    int zbitpix,
    double scale,
    double zero,
    int *intlength,
    int *flag,
    double *bscale,
    double *bzero,
    int *status)
{
    /*  Prepare the input tile array of pixels for compression. */
    /*  Convert input float tile array in place to 4 or 8-byte ints for compression, */
    /*  If needed, convert 4 or 8-byte ints and do null value substitution. */
    /*  Note that the calling routine must have allocated the input array big enough */
    /* to be able to do this.  */

    int *idata;
    long irow, ii;
    float floatnull;
    unsigned char *usbbuff;
    unsigned long dithersum;
    int iminval = 0, imaxval = 0;  /* min and max quantized integers */

        /* datatype of input array is double.  We only support writing this datatype
           to a FITS image with BITPIX = -64 or -32, except we also support the special case where
	   BITPIX = 32 and BZERO = 0 and BSCALE = 1.  */

       if ((zbitpix != LONG_IMG && zbitpix != DOUBLE_IMG && zbitpix != FLOAT_IMG) || scale != 1.0 || zero != 0.) {
           ffpmsg("Implicit datatype conversion is not supported when writing to compressed images");
           return(*status = DATA_COMPRESSION_ERR);
       } 

           *intlength = 4;
           idata = (int *) tiledata;

          /* if the tile-compressed table contains zscale and zzero columns */
          /* then scale and quantize the input floating point data.    */

          if ((outfptr->Fptr)->cn_zscale > 0) {
	    /* quantize the float values into integers */

            if (nullcheck == 1)
	      floatnull = *(float *) (nullflagval);
	    else
	      floatnull = FLOATNULLVALUE;  /* NaNs are represented by this, by default */

            if ((outfptr->Fptr)->quantize_method == SUBTRACTIVE_DITHER_1  ||
	        (outfptr->Fptr)->quantize_method == SUBTRACTIVE_DITHER_2) {
	      
	          /* see if the dithering offset value needs to be initialized */                  
	          if ((outfptr->Fptr)->request_dither_seed == 0 && (outfptr->Fptr)->dither_seed == 0) {

		     /* This means randomly choose the dithering offset based on the system time. */
		     /* The offset will have a value between 1 and 10000, inclusive. */
		     /* The time function returns an integer value that is incremented each second. */
		     /* The clock function returns the elapsed CPU time, in integer CLOCKS_PER_SEC units. */
		     /* The CPU time returned by clock is typically (on linux PC) only good to 0.01 sec */
		     /* Summing the 2 quantities may help avoid cases where 2 executions of the program */
		     /* (perhaps in a multithreaded environoment) end up with exactly the same dither seed */
		     /* value.  The sum is incremented by the current HDU number in the file to provide */
		     /* further randomization.  This randomization is desireable if multiple compressed */
		     /* images will be summed (or differenced). In such cases, the benefits of dithering */
		     /* may be lost if all the images use exactly the same sequence of random numbers when */
		     /* calculating the dithering offsets. */	     
		     
		     (outfptr->Fptr)->dither_seed = 
		       (( (int)time(NULL) + ( (int) clock() / (int) (CLOCKS_PER_SEC / 100)) + (outfptr->Fptr)->curhdu) % 10000) + 1;
		     
                     /* update the header keyword with this new value */
		     fits_update_key(outfptr, TINT, "ZDITHER0", &((outfptr->Fptr)->dither_seed), 
	                        NULL, status);

	          } else if ((outfptr->Fptr)->request_dither_seed < 0 && (outfptr->Fptr)->dither_seed < 0) {

		     /* this means randomly choose the dithering offset based on some hash function */
		     /* of the first input tile of data to be quantized and compressed.  This ensures that */
                     /* the same offset value is used for a given image every time it is compressed. */

		     usbbuff = (unsigned char *) tiledata;
		     dithersum = 0;
		     for (ii = 0; ii < 4 * tilelen; ii++) {
		         dithersum += usbbuff[ii];  /* doesn't matter if there is an integer overflow */
	             }
		     (outfptr->Fptr)->dither_seed = ((int) (dithersum % 10000)) + 1;
		
                     /* update the header keyword with this new value */
		     fits_update_key(outfptr, TINT, "ZDITHER0", &((outfptr->Fptr)->dither_seed), 
	                        NULL, status);
		  }

                  /* subtract 1 to convert from 1-based to 0-based element number */
	          irow = row + (outfptr->Fptr)->dither_seed - 1; /* dither the quantized values */

	      } else if ((outfptr->Fptr)->quantize_method == -1) {
	          irow = 0;  /* do not dither the quantized values */
              } else {
                  ffpmsg("Unknown dithering method.");
                  ffpmsg("May need to install a newer version of CFITSIO.");
                  return(*status = DATA_COMPRESSION_ERR);
              }

              *flag = fits_quantize_float (irow, (float *) tiledata, tilenx, tileny,
                   nullcheck, floatnull, (outfptr->Fptr)->quantize_level, 
		   (outfptr->Fptr)->quantize_method, idata, bscale, bzero, &iminval, &imaxval);

              if (*flag > 1)
		   return(*status = *flag);
          }
          else if ((outfptr->Fptr)->quantize_level != NO_QUANTIZE)
	  {
	    /* if floating point pixels are not being losslessly compressed, then */
	    /* input float data is implicitly converted (truncated) to integers */
            if ((scale != 1. || zero != 0.))  /* must scale the values */
	       imcomp_nullscalefloats((float *) tiledata, tilelen, idata, scale, zero,
	           nullcheck, *(float *) (nullflagval), nullval, status);
             else
	       imcomp_nullfloats((float *) tiledata, tilelen, idata,
	           nullcheck, *(float *) (nullflagval), nullval,  status);
          }
          else if ((outfptr->Fptr)->quantize_level == NO_QUANTIZE)
	  {
	      /* just convert null values to NaNs in place, if necessary, then do lossless gzip compression */
		if (nullcheck == 1) {
	            imcomp_float2nan((float *) tiledata, tilelen, (int *) tiledata,
	                *(float *) (nullflagval), status);
		}
          }

          return(*status);
}
 /*--------------------------------------------------------------------------*/
int imcomp_convert_tile_tdouble(
    fitsfile *outfptr,
    long row,
    void *tiledata, 
    long tilelen,
    long tilenx,
    long tileny,
    int nullcheck,
    void *nullflagval,
    int nullval,
    int zbitpix,
    double scale,
    double zero,
    int *intlength,
    int *flag,
    double *bscale,
    double *bzero,
    int *status)
{
    /*  Prepare the input tile array of pixels for compression. */
    /*  Convert input double tile array in place to 4-byte ints for compression, */
    /*  If needed, convert 4 or 8-byte ints and do null value substitution. */
    /*  Note that the calling routine must have allocated the input array big enough */
    /* to be able to do this.  */

    int *idata;
    long irow, ii;
    double doublenull;
    unsigned char *usbbuff;
    unsigned long dithersum;
    int iminval = 0, imaxval = 0;  /* min and max quantized integers */

        /* datatype of input array is double.  We only support writing this datatype
           to a FITS image with BITPIX = -64 or -32, except we also support the special case where
	   BITPIX = 32 and BZERO = 0 and BSCALE = 1.  */

       if ((zbitpix != LONG_IMG && zbitpix != DOUBLE_IMG && zbitpix != FLOAT_IMG) || scale != 1.0 || zero != 0.) {
           ffpmsg("Implicit datatype conversion is not supported when writing to compressed images");
           return(*status = DATA_COMPRESSION_ERR);
       } 

           *intlength = 4;
           idata = (int *) tiledata;

          /* if the tile-compressed table contains zscale and zzero columns */
          /* then scale and quantize the input floating point data.    */
          /* Otherwise, just truncate the floats to integers.          */

          if ((outfptr->Fptr)->cn_zscale > 0)
          {
            if (nullcheck == 1)
	      doublenull = *(double *) (nullflagval);
	    else
	      doublenull = DOUBLENULLVALUE;

            /* quantize the double values into integers */
              if ((outfptr->Fptr)->quantize_method == SUBTRACTIVE_DITHER_1 ||
	          (outfptr->Fptr)->quantize_method == SUBTRACTIVE_DITHER_2) {

	          /* see if the dithering offset value needs to be initialized (see above) */                  
	          if ((outfptr->Fptr)->request_dither_seed == 0 && (outfptr->Fptr)->dither_seed == 0) {

		     (outfptr->Fptr)->dither_seed = 
		       (( (int)time(NULL) + ( (int) clock() / (int) (CLOCKS_PER_SEC / 100)) + (outfptr->Fptr)->curhdu) % 10000) + 1;
		     
                     /* update the header keyword with this new value */
		     fits_update_key(outfptr, TINT, "ZDITHER0", &((outfptr->Fptr)->dither_seed), 
	                        NULL, status);

	          } else if ((outfptr->Fptr)->request_dither_seed < 0 && (outfptr->Fptr)->dither_seed < 0) {

		     usbbuff = (unsigned char *) tiledata;
		     dithersum = 0;
		     for (ii = 0; ii < 8 * tilelen; ii++) {
		         dithersum += usbbuff[ii];
	             }
		     (outfptr->Fptr)->dither_seed = ((int) (dithersum % 10000)) + 1;
		
                     /* update the header keyword with this new value */
		     fits_update_key(outfptr, TINT, "ZDITHER0", &((outfptr->Fptr)->dither_seed), 
	                        NULL, status);
		  }

	          irow = row + (outfptr->Fptr)->dither_seed - 1; /* dither the quantized values */

	      } else if ((outfptr->Fptr)->quantize_method == -1) {
	          irow = 0;  /* do not dither the quantized values */
              } else {
                  ffpmsg("Unknown subtractive dithering method.");
                  ffpmsg("May need to install a newer version of CFITSIO.");
                  return(*status = DATA_COMPRESSION_ERR);
              }

            *flag = fits_quantize_double (irow, (double *) tiledata, tilenx, tileny,
               nullcheck, doublenull, (outfptr->Fptr)->quantize_level, 
	       (outfptr->Fptr)->quantize_method, idata,
               bscale, bzero, &iminval, &imaxval);

            if (*flag > 1)
		return(*status = *flag);
          }
          else if ((outfptr->Fptr)->quantize_level != NO_QUANTIZE)
	  {
	    /* if floating point pixels are not being losslessly compressed, then */
	    /* input float data is implicitly converted (truncated) to integers */
             if ((scale != 1. || zero != 0.))  /* must scale the values */
	       imcomp_nullscaledoubles((double *) tiledata, tilelen, idata, scale, zero,
	           nullcheck, *(double *) (nullflagval), nullval, status);
             else
	       imcomp_nulldoubles((double *) tiledata, tilelen, idata,
	           nullcheck, *(double *) (nullflagval), nullval,  status);
          }
          else if ((outfptr->Fptr)->quantize_level == NO_QUANTIZE)
	  {
	      /* just convert null values to NaNs in place, if necessary, then do lossless gzip compression */
		if (nullcheck == 1) {
	            imcomp_double2nan((double *) tiledata, tilelen, (LONGLONG *) tiledata,
	                *(double *) (nullflagval), status);
		}
          }
 
          return(*status);
}
/*---------------------------------------------------------------------------*/
int imcomp_nullscale(
     int *idata, 
     long tilelen,
     int nullflagval,
     int nullval,
     double scale,
     double zero,
     int *status)
/*
   do null value substitution AND scaling of the integer array.
   If array value = nullflagval, then set the value to nullval.
   Otherwise, inverse scale the integer value.
*/
{
    long ii;
    double dvalue;
    
    for (ii=0; ii < tilelen; ii++)
    {
        if (idata[ii] == nullflagval)
	    idata[ii] = nullval;
	else 
	{
            dvalue = (idata[ii] - zero) / scale;

            if (dvalue < DINT_MIN)
            {
                *status = OVERFLOW_ERR;
                idata[ii] = INT32_MIN;
            }
            else if (dvalue > DINT_MAX)
            {
                *status = OVERFLOW_ERR;
                idata[ii] = INT32_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    idata[ii] = (int) (dvalue + .5);
                else
                    idata[ii] = (int) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*---------------------------------------------------------------------------*/
int imcomp_nullvalues(
     int *idata, 
     long tilelen,
     int nullflagval,
     int nullval,
     int *status)
/*
   do null value substitution.
   If array value = nullflagval, then set the value to nullval.
*/
{
    long ii;
    
    for (ii=0; ii < tilelen; ii++)
    {
        if (idata[ii] == nullflagval)
	    idata[ii] = nullval;
    }
    return(*status);
}
/*---------------------------------------------------------------------------*/
int imcomp_scalevalues(
     int *idata, 
     long tilelen,
     double scale,
     double zero,
     int *status)
/*
   do inverse scaling the integer values.
*/
{
    long ii;
    double dvalue;
    
    for (ii=0; ii < tilelen; ii++)
    {
            dvalue = (idata[ii] - zero) / scale;

            if (dvalue < DINT_MIN)
            {
                *status = OVERFLOW_ERR;
                idata[ii] = INT32_MIN;
            }
            else if (dvalue > DINT_MAX)
            {
                *status = OVERFLOW_ERR;
                idata[ii] = INT32_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    idata[ii] = (int) (dvalue + .5);
                else
                    idata[ii] = (int) (dvalue - .5);
            }
    }
    return(*status);
}
/*---------------------------------------------------------------------------*/
int imcomp_nullscalei2(
     short *idata, 
     long tilelen,
     short nullflagval,
     short nullval,
     double scale,
     double zero,
     int *status)
/*
   do null value substitution AND scaling of the integer array.
   If array value = nullflagval, then set the value to nullval.
   Otherwise, inverse scale the integer value.
*/
{
    long ii;
    double dvalue;
    
    for (ii=0; ii < tilelen; ii++)
    {
        if (idata[ii] == nullflagval)
	    idata[ii] = nullval;
	else 
	{
            dvalue = (idata[ii] - zero) / scale;

            if (dvalue < DSHRT_MIN)
            {
                *status = OVERFLOW_ERR;
                idata[ii] = SHRT_MIN;
            }
            else if (dvalue > DSHRT_MAX)
            {
                *status = OVERFLOW_ERR;
                idata[ii] = SHRT_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    idata[ii] = (int) (dvalue + .5);
                else
                    idata[ii] = (int) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*---------------------------------------------------------------------------*/
int imcomp_nullvaluesi2(
     short *idata, 
     long tilelen,
     short nullflagval,
     short nullval,
     int *status)
/*
   do null value substitution.
   If array value = nullflagval, then set the value to nullval.
*/
{
    long ii;
    
    for (ii=0; ii < tilelen; ii++)
    {
        if (idata[ii] == nullflagval)
	    idata[ii] = nullval;
    }
    return(*status);
}
/*---------------------------------------------------------------------------*/
int imcomp_scalevaluesi2(
     short *idata, 
     long tilelen,
     double scale,
     double zero,
     int *status)
/*
   do inverse scaling the integer values.
*/
{
    long ii;
    double dvalue;
    
    for (ii=0; ii < tilelen; ii++)
    {
            dvalue = (idata[ii] - zero) / scale;

            if (dvalue < DSHRT_MIN)
            {
                *status = OVERFLOW_ERR;
                idata[ii] = SHRT_MIN;
            }
            else if (dvalue > DSHRT_MAX)
            {
                *status = OVERFLOW_ERR;
                idata[ii] = SHRT_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    idata[ii] = (int) (dvalue + .5);
                else
                    idata[ii] = (int) (dvalue - .5);
            }
    }
    return(*status);
}
/*---------------------------------------------------------------------------*/
int imcomp_nullfloats(
     float *fdata,
     long tilelen,
     int *idata, 
     int nullcheck,
     float nullflagval,
     int nullval,
     int *status)
/*
   do null value substitution  of the float array.
   If array value = nullflagval, then set the output value to FLOATNULLVALUE.
*/
{
    long ii;
    double dvalue;
    
    if (nullcheck == 1) /* must check for null values */
    {
      for (ii=0; ii < tilelen; ii++)
      {
        if (fdata[ii] == nullflagval)
	    idata[ii] = nullval;
	else 
	{
            dvalue = fdata[ii];

            if (dvalue < DINT_MIN)
            {
                *status = OVERFLOW_ERR;
                idata[ii] = INT32_MIN;
            }
            else if (dvalue > DINT_MAX)
            {
                *status = OVERFLOW_ERR;
                idata[ii] = INT32_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    idata[ii] = (int) (dvalue + .5);
                else
                    idata[ii] = (int) (dvalue - .5);
            }
        }
      }
    }
    else  /* don't have to worry about null values */
    {
      for (ii=0; ii < tilelen; ii++)
      {
            dvalue = fdata[ii];

            if (dvalue < DINT_MIN)
            {
                *status = OVERFLOW_ERR;
                idata[ii] = INT32_MIN;
            }
            else if (dvalue > DINT_MAX)
            {
                *status = OVERFLOW_ERR;
                idata[ii] = INT32_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    idata[ii] = (int) (dvalue + .5);
                else
                    idata[ii] = (int) (dvalue - .5);
            }
      }
    }
    return(*status);
}
/*---------------------------------------------------------------------------*/
int imcomp_nullscalefloats(
     float *fdata,
     long tilelen,
     int *idata, 
     double scale,
     double zero,
     int nullcheck,
     float nullflagval,
     int nullval,
     int *status)
/*
   do null value substitution  of the float array.
   If array value = nullflagval, then set the output value to FLOATNULLVALUE.
   Otherwise, inverse scale the integer value.
*/
{
    long ii;
    double dvalue;
    
    if (nullcheck == 1) /* must check for null values */
    {
      for (ii=0; ii < tilelen; ii++)
      {
        if (fdata[ii] == nullflagval)
	    idata[ii] = nullval;
	else 
	{
            dvalue = (fdata[ii] - zero) / scale;

            if (dvalue < DINT_MIN)
            {
                *status = OVERFLOW_ERR;
                idata[ii] = INT32_MIN;
            }
            else if (dvalue > DINT_MAX)
            {
                *status = OVERFLOW_ERR;
                idata[ii] = INT32_MAX;
            }
            else
            {
                if (dvalue >= 0.)
                    idata[ii] = (int) (dvalue + .5);
                else
                    idata[ii] = (int) (dvalue - .5);
            }
        }
      }
    }
    else  /* don't have to worry about null values */
    {
      for (ii=0; ii < tilelen; ii++)
      {
            dvalue = (fdata[ii] - zero) / scale;

            if (dvalue < DINT_MIN)
            {
                *status = OVERFLOW_ERR;
                idata[ii] = INT32_MIN;
            }
            else if (dvalue > DINT_MAX)
            {
                *status = OVERFLOW_ERR;
                idata[ii] = INT32_MAX;
            }
            else
            {
                if (dvalue >= 0.)
                    idata[ii] = (int) (dvalue + .5);
                else
                    idata[ii] = (int) (dvalue - .5);
            }
      }
    }
    return(*status);
}
/*---------------------------------------------------------------------------*/
int imcomp_nulldoubles(
     double *fdata,
     long tilelen,
     int *idata, 
     int nullcheck,
     double nullflagval,
     int nullval,
     int *status)
/*
   do null value substitution  of the float array.
   If array value = nullflagval, then set the output value to FLOATNULLVALUE.
   Otherwise, inverse scale the integer value.
*/
{
    long ii;
    double dvalue;
    
    if (nullcheck == 1) /* must check for null values */
    {
      for (ii=0; ii < tilelen; ii++)
      {
        if (fdata[ii] == nullflagval)
	    idata[ii] = nullval;
	else 
	{
            dvalue = fdata[ii];

            if (dvalue < DINT_MIN)
            {
                *status = OVERFLOW_ERR;
                idata[ii] = INT32_MIN;
            }
            else if (dvalue > DINT_MAX)
            {
                *status = OVERFLOW_ERR;
                idata[ii] = INT32_MAX;
            }
            else
            {
                if (dvalue >= 0.)
                    idata[ii] = (int) (dvalue + .5);
                else
                    idata[ii] = (int) (dvalue - .5);
            }
        }
      }
    }
    else  /* don't have to worry about null values */
    {
      for (ii=0; ii < tilelen; ii++)
      {
            dvalue = fdata[ii];

            if (dvalue < DINT_MIN)
            {
                *status = OVERFLOW_ERR;
                idata[ii] = INT32_MIN;
            }
            else if (dvalue > DINT_MAX)
            {
                *status = OVERFLOW_ERR;
                idata[ii] = INT32_MAX;
            }
            else
            {
                if (dvalue >= 0.)
                    idata[ii] = (int) (dvalue + .5);
                else
                    idata[ii] = (int) (dvalue - .5);
            }
      }
    }
    return(*status);
}
/*---------------------------------------------------------------------------*/
int imcomp_nullscaledoubles(
     double *fdata,
     long tilelen,
     int *idata, 
     double scale,
     double zero,
     int nullcheck,
     double nullflagval,
     int nullval,
     int *status)
/*
   do null value substitution  of the float array.
   If array value = nullflagval, then set the output value to FLOATNULLVALUE.
   Otherwise, inverse scale the integer value.
*/
{
    long ii;
    double dvalue;
    
    if (nullcheck == 1) /* must check for null values */
    {
      for (ii=0; ii < tilelen; ii++)
      {
        if (fdata[ii] == nullflagval)
	    idata[ii] = nullval;
	else 
	{
            dvalue = (fdata[ii] - zero) / scale;

            if (dvalue < DINT_MIN)
            {
                *status = OVERFLOW_ERR;
                idata[ii] = INT32_MIN;
            }
            else if (dvalue > DINT_MAX)
            {
                *status = OVERFLOW_ERR;
                idata[ii] = INT32_MAX;
            }
            else
            {
                if (dvalue >= 0.)
                    idata[ii] = (int) (dvalue + .5);
                else
                    idata[ii] = (int) (dvalue - .5);
            }
        }
      }
    }
    else  /* don't have to worry about null values */
    {
      for (ii=0; ii < tilelen; ii++)
      {
            dvalue = (fdata[ii] - zero) / scale;

            if (dvalue < DINT_MIN)
            {
                *status = OVERFLOW_ERR;
                idata[ii] = INT32_MIN;
            }
            else if (dvalue > DINT_MAX)
            {
                *status = OVERFLOW_ERR;
                idata[ii] = INT32_MAX;
            }
            else
            {
                if (dvalue >= 0.)
                    idata[ii] = (int) (dvalue + .5);
                else
                    idata[ii] = (int) (dvalue - .5);
            }
      }
    }
    return(*status);
}
/*---------------------------------------------------------------------------*/
int fits_write_compressed_img(fitsfile *fptr,   /* I - FITS file pointer     */
            int  datatype,   /* I - datatype of the array to be written      */
            long  *infpixel, /* I - 'bottom left corner' of the subsection   */
            long  *inlpixel, /* I - 'top right corner' of the subsection     */
            int  nullcheck,  /* I - 0 for no null checking                   */
                             /*     1: pixels that are = nullval will be     */
                             /*     written with the FITS null pixel value   */
                             /*     (floating point arrays only)             */
            void *array,     /* I - array of values to be written            */
            void *nullval,   /* I - undefined pixel value                    */
            int  *status)    /* IO - error status                            */
/*
   Write a section of a compressed image.
*/
{
    int  tiledim[MAX_COMPRESS_DIM];
    long naxis[MAX_COMPRESS_DIM];
    long tilesize[MAX_COMPRESS_DIM], thistilesize[MAX_COMPRESS_DIM];
    long ftile[MAX_COMPRESS_DIM], ltile[MAX_COMPRESS_DIM];
    long tfpixel[MAX_COMPRESS_DIM], tlpixel[MAX_COMPRESS_DIM];
    long rowdim[MAX_COMPRESS_DIM], offset[MAX_COMPRESS_DIM],ntemp;
    long fpixel[MAX_COMPRESS_DIM], lpixel[MAX_COMPRESS_DIM];
    long i5, i4, i3, i2, i1, i0, irow;
    int ii, ndim, pixlen, tilenul;
    int  tstatus, buffpixsiz;
    void *buffer;
    char *bnullarray = 0, card[FLEN_CARD];

    if (*status > 0) 
        return(*status);

    if (!fits_is_compressed_image(fptr, status) )
    {
        ffpmsg("CHDU is not a compressed image (fits_write_compressed_img)");
        return(*status = DATA_COMPRESSION_ERR);
    }

    /* reset position to the correct HDU if necessary */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    /* rescan header if data structure is undefined */
    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
        if ( ffrdef(fptr, status) > 0)               
            return(*status);


    /* ===================================================================== */


    if (datatype == TSHORT || datatype == TUSHORT)
    {
       pixlen = sizeof(short);
    }
    else if (datatype == TINT || datatype == TUINT)
    {
       pixlen = sizeof(int);
    }
    else if (datatype == TBYTE || datatype == TSBYTE)
    {
       pixlen = 1;
    }
    else if (datatype == TLONG || datatype == TULONG)
    {
       pixlen = sizeof(long);
    }
    else if (datatype == TFLOAT)
    {
       pixlen = sizeof(float);
    }
    else if (datatype == TDOUBLE)
    {
       pixlen = sizeof(double);
    }
    else
    {
        ffpmsg("unsupported datatype for compressing image");
        return(*status = BAD_DATATYPE);
    }

    /* ===================================================================== */

    /* allocate scratch space for processing one tile of the image */
    buffpixsiz = pixlen;  /* this is the minimum pixel size */
    
    if ( (fptr->Fptr)->compress_type == HCOMPRESS_1) { /* need 4 or 8 bytes per pixel */
        if ((fptr->Fptr)->zbitpix == BYTE_IMG ||
	    (fptr->Fptr)->zbitpix == SHORT_IMG )
                buffpixsiz = maxvalue(buffpixsiz, 4);
        else
	        buffpixsiz = 8;
    }
    else if ( (fptr->Fptr)->compress_type == PLIO_1) { /* need 4 bytes per pixel */
                buffpixsiz = maxvalue(buffpixsiz, 4);
    }
    else if ( (fptr->Fptr)->compress_type == RICE_1  ||
              (fptr->Fptr)->compress_type == GZIP_1 ||
              (fptr->Fptr)->compress_type == GZIP_2 ||
              (fptr->Fptr)->compress_type == BZIP2_1) {  /* need 1, 2, or 4 bytes per pixel */
        if ((fptr->Fptr)->zbitpix == BYTE_IMG)
            buffpixsiz = maxvalue(buffpixsiz, 1);
        else if ((fptr->Fptr)->zbitpix == SHORT_IMG)
            buffpixsiz = maxvalue(buffpixsiz, 2);
        else 
            buffpixsiz = maxvalue(buffpixsiz, 4);
    }
    else
    {
        ffpmsg("unsupported image compression algorithm");
        return(*status = BAD_DATATYPE);
    }
    
    /* cast to double to force alignment on 8-byte addresses */
    buffer = (double *) calloc ((fptr->Fptr)->maxtilelen, buffpixsiz);

    if (buffer == NULL)
    {
	    ffpmsg("Out of memory (fits_write_compress_img)");
	    return (*status = MEMORY_ALLOCATION);
    }

    /* ===================================================================== */

    /* initialize all the arrays */
    for (ii = 0; ii < MAX_COMPRESS_DIM; ii++)
    {
        naxis[ii] = 1;
        tiledim[ii] = 1;
        tilesize[ii] = 1;
        ftile[ii] = 1;
        ltile[ii] = 1;
        rowdim[ii] = 1;
    }

    ndim = (fptr->Fptr)->zndim;
    ntemp = 1;
    for (ii = 0; ii < ndim; ii++)
    {
        fpixel[ii] = infpixel[ii];
        lpixel[ii] = inlpixel[ii];

        /* calc number of tiles in each dimension, and tile containing */
        /* the first and last pixel we want to read in each dimension  */
        naxis[ii] = (fptr->Fptr)->znaxis[ii];
        if (fpixel[ii] < 1)
        {
            free(buffer);
            return(*status = BAD_PIX_NUM);
        }

        tilesize[ii] = (fptr->Fptr)->tilesize[ii];
        tiledim[ii] = (naxis[ii] - 1) / tilesize[ii] + 1;
        ftile[ii]   = (fpixel[ii] - 1)   / tilesize[ii] + 1;
        ltile[ii]   = minvalue((lpixel[ii] - 1) / tilesize[ii] + 1, 
                                tiledim[ii]);
        rowdim[ii]  = ntemp;  /* total tiles in each dimension */
        ntemp *= tiledim[ii];
    }

    /* support up to 6 dimensions for now */
    /* tfpixel and tlpixel are the first and last image pixels */
    /* along each dimension of the compression tile */
    for (i5 = ftile[5]; i5 <= ltile[5]; i5++)
    {
     tfpixel[5] = (i5 - 1) * tilesize[5] + 1;
     tlpixel[5] = minvalue(tfpixel[5] + tilesize[5] - 1, 
                            naxis[5]);
     thistilesize[5] = tlpixel[5] - tfpixel[5] + 1;
     offset[5] = (i5 - 1) * rowdim[5];
     for (i4 = ftile[4]; i4 <= ltile[4]; i4++)
     {
      tfpixel[4] = (i4 - 1) * tilesize[4] + 1;
      tlpixel[4] = minvalue(tfpixel[4] + tilesize[4] - 1, 
                            naxis[4]);
      thistilesize[4] = thistilesize[5] * (tlpixel[4] - tfpixel[4] + 1);
      offset[4] = (i4 - 1) * rowdim[4] + offset[5];
      for (i3 = ftile[3]; i3 <= ltile[3]; i3++)
      {
        tfpixel[3] = (i3 - 1) * tilesize[3] + 1;
        tlpixel[3] = minvalue(tfpixel[3] + tilesize[3] - 1, 
                              naxis[3]);
        thistilesize[3] = thistilesize[4] * (tlpixel[3] - tfpixel[3] + 1);
        offset[3] = (i3 - 1) * rowdim[3] + offset[4];
        for (i2 = ftile[2]; i2 <= ltile[2]; i2++)
        {
          tfpixel[2] = (i2 - 1) * tilesize[2] + 1;
          tlpixel[2] = minvalue(tfpixel[2] + tilesize[2] - 1, 
                                naxis[2]);
          thistilesize[2] = thistilesize[3] * (tlpixel[2] - tfpixel[2] + 1);
          offset[2] = (i2 - 1) * rowdim[2] + offset[3];
          for (i1 = ftile[1]; i1 <= ltile[1]; i1++)
          {
            tfpixel[1] = (i1 - 1) * tilesize[1] + 1;
            tlpixel[1] = minvalue(tfpixel[1] + tilesize[1] - 1, 
                                  naxis[1]);
            thistilesize[1] = thistilesize[2] * (tlpixel[1] - tfpixel[1] + 1);
            offset[1] = (i1 - 1) * rowdim[1] + offset[2];
            for (i0 = ftile[0]; i0 <= ltile[0]; i0++)
            {
              tfpixel[0] = (i0 - 1) * tilesize[0] + 1;
              tlpixel[0] = minvalue(tfpixel[0] + tilesize[0] - 1, 
                                    naxis[0]);
              thistilesize[0] = thistilesize[1] * (tlpixel[0] - tfpixel[0] + 1);
              /* calculate row of table containing this tile */
              irow = i0 + offset[1];

              /* read and uncompress this row (tile) of the table */
              /* also do type conversion and undefined pixel substitution */
              /* at this point */
              imcomp_decompress_tile(fptr, irow, thistilesize[0],
                    datatype, nullcheck, nullval, buffer, bnullarray, &tilenul,
                     status);

              if (*status == NO_COMPRESSED_TILE)
              {
                   /* tile doesn't exist, so initialize to zero */
                   memset(buffer, 0, pixlen * thistilesize[0]);
                   *status = 0;
              }

              /* copy the intersecting pixels to this tile from the input */
              imcomp_merge_overlap(buffer, pixlen, ndim, tfpixel, tlpixel, 
                     bnullarray, array, fpixel, lpixel, nullcheck, status);

              /* compress the tile again, and write it back to the FITS file */
              imcomp_compress_tile (fptr, irow, datatype, buffer, 
                                    thistilesize[0],
				    tlpixel[0] - tfpixel[0] + 1,
				    tlpixel[1] - tfpixel[1] + 1,
				    nullcheck, nullval, 
				    status);
            }
          }
        }
      }
     }
    }
    free(buffer);
    

    if ((fptr->Fptr)->zbitpix < 0 && nullcheck != 0) { 
/*
     This is a floating point FITS image with possible null values.
     It is too messy to test if any null values are actually written, so 
     just assume so.  We need to make sure that the
     ZBLANK keyword is present in the compressed image header.  If it is not
     there then we need to insert the keyword. 
*/   
        tstatus = 0;
        ffgcrd(fptr, "ZBLANK", card, &tstatus);

	if (tstatus) {   /* have to insert the ZBLANK keyword */
           ffgcrd(fptr, "ZCMPTYPE", card, status);
           ffikyj(fptr, "ZBLANK", COMPRESS_NULL_VALUE, 
                "null value in the compressed integer array", status);
	
           /* set this value into the internal structure; it is used if */
	   /* the program reads back the values from the array */
	 
          (fptr->Fptr)->zblank = COMPRESS_NULL_VALUE;
          (fptr->Fptr)->cn_zblank = -1;  /* flag for a constant ZBLANK */
        }  
    }  
    
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_write_compressed_pixels(fitsfile *fptr, /* I - FITS file pointer   */
            int  datatype,  /* I - datatype of the array to be written      */
            LONGLONG   fpixel,  /* I - 'first pixel to write          */
            LONGLONG   npixel,  /* I - number of pixels to write      */
            int  nullcheck,  /* I - 0 for no null checking                   */
                             /*     1: pixels that are = nullval will be     */
                             /*     written with the FITS null pixel value   */
                             /*     (floating point arrays only)             */
            void *array,      /* I - array of values to write                */
            void *nullval,    /* I - value used to represent undefined pixels*/
            int  *status)     /* IO - error status                           */
/*
   Write a consecutive set of pixels to a compressed image.  This routine
   interpretes the n-dimensional image as a long one-dimensional array. 
   This is actually a rather inconvenient way to write compressed images in
   general, and could be rather inefficient if the requested pixels to be
   written are located in many different image compression tiles.    

   The general strategy used here is to write the requested pixels in blocks
   that correspond to rectangular image sections.  
*/
{
    int naxis, ii, bytesperpixel;
    long naxes[MAX_COMPRESS_DIM], nread;
    LONGLONG tfirst, tlast, last0, last1, dimsize[MAX_COMPRESS_DIM];
    long nplane, firstcoord[MAX_COMPRESS_DIM], lastcoord[MAX_COMPRESS_DIM];
    char *arrayptr;

    if (*status > 0)
        return(*status);

    arrayptr = (char *) array;

    /* get size of array pixels, in bytes */
    bytesperpixel = ffpxsz(datatype);

    for (ii = 0; ii < MAX_COMPRESS_DIM; ii++)
    {
        naxes[ii] = 1;
        firstcoord[ii] = 0;
        lastcoord[ii] = 0;
    }

    /*  determine the dimensions of the image to be written */
    ffgidm(fptr, &naxis, status);
    ffgisz(fptr, MAX_COMPRESS_DIM, naxes, status);

    /* calc the cumulative number of pixels in each successive dimension */
    dimsize[0] = 1;
    for (ii = 1; ii < MAX_COMPRESS_DIM; ii++)
         dimsize[ii] = dimsize[ii - 1] * naxes[ii - 1];

    /*  determine the coordinate of the first and last pixel in the image */
    /*  Use zero based indexes here */
    tfirst = fpixel - 1;
    tlast = tfirst + npixel - 1;
    for (ii = naxis - 1; ii >= 0; ii--)
    {
        firstcoord[ii] = (long) (tfirst / dimsize[ii]);
        lastcoord[ii]  = (long) (tlast / dimsize[ii]);
        tfirst = tfirst - firstcoord[ii] * dimsize[ii];
        tlast = tlast - lastcoord[ii] * dimsize[ii];
    }

    /* to simplify things, treat 1-D, 2-D, and 3-D images as separate cases */

    if (naxis == 1)
    {
        /* Simple: just write the requested range of pixels */

        firstcoord[0] = firstcoord[0] + 1;
        lastcoord[0] = lastcoord[0] + 1;
        fits_write_compressed_img(fptr, datatype, firstcoord, lastcoord,
            nullcheck, array, nullval, status);
        return(*status);
    }
    else if (naxis == 2)
    {
        nplane = 0;  /* write 1st (and only) plane of the image */
        fits_write_compressed_img_plane(fptr, datatype, bytesperpixel,
          nplane, firstcoord, lastcoord, naxes, nullcheck,
          array, nullval, &nread, status);
    }
    else if (naxis == 3)
    {
        /* test for special case: writing an integral number of planes */
        if (firstcoord[0] == 0 && firstcoord[1] == 0 &&
            lastcoord[0] == naxes[0] - 1 && lastcoord[1] == naxes[1] - 1)
        {
            for (ii = 0; ii < MAX_COMPRESS_DIM; ii++)
            {
                /* convert from zero base to 1 base */
                (firstcoord[ii])++;
                (lastcoord[ii])++;
            }

            /* we can write the contiguous block of pixels in one go */
            fits_write_compressed_img(fptr, datatype, firstcoord, lastcoord,
                nullcheck, array, nullval, status);
            return(*status);
        }

        /* save last coordinate in temporary variables */
        last0 = lastcoord[0];
        last1 = lastcoord[1];

        if (firstcoord[2] < lastcoord[2])
        {
            /* we will write up to the last pixel in all but the last plane */
            lastcoord[0] = naxes[0] - 1;
            lastcoord[1] = naxes[1] - 1;
        }

        /* write one plane of the cube at a time, for simplicity */
        for (nplane = firstcoord[2]; nplane <= lastcoord[2]; nplane++)
        {
            if (nplane == lastcoord[2])
            {
                lastcoord[0] = (long) last0;
                lastcoord[1] = (long) last1;
            }

            fits_write_compressed_img_plane(fptr, datatype, bytesperpixel,
              nplane, firstcoord, lastcoord, naxes, nullcheck,
              arrayptr, nullval, &nread, status);

            /* for all subsequent planes, we start with the first pixel */
            firstcoord[0] = 0;
            firstcoord[1] = 0;

            /* increment pointers to next elements to be written */
            arrayptr = arrayptr + nread * bytesperpixel;
        }
    }
    else
    {
        ffpmsg("only 1D, 2D, or 3D images are currently supported");
        return(*status = DATA_COMPRESSION_ERR);
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_write_compressed_img_plane(fitsfile *fptr, /* I - FITS file    */
            int  datatype,  /* I - datatype of the array to be written    */
            int  bytesperpixel, /* I - number of bytes per pixel in array */
            long   nplane,  /* I - which plane of the cube to write      */
            long *firstcoord, /* I coordinate of first pixel to write */
            long *lastcoord,  /* I coordinate of last pixel to write */
            long *naxes,     /* I size of each image dimension */
            int  nullcheck,  /* I - 0 for no null checking                   */
                             /*     1: pixels that are = nullval will be     */
                             /*     written with the FITS null pixel value   */
                             /*     (floating point arrays only)             */
            void *array,      /* I - array of values that are written        */
            void *nullval,    /* I - value for undefined pixels              */
            long *nread,      /* O - total number of pixels written          */
            int  *status)     /* IO - error status                           */

   /*
           in general we have to write the first partial row of the image,
           followed by the middle complete rows, followed by the last
           partial row of the image.  If the first or last rows are complete,
           then write them at the same time as all the middle rows.
    */
{
    /* bottom left coord. and top right coord. */
    long blc[MAX_COMPRESS_DIM], trc[MAX_COMPRESS_DIM]; 
    char *arrayptr;

    *nread = 0;

    arrayptr = (char *) array;

    blc[2] = nplane + 1;
    trc[2] = nplane + 1;

    if (firstcoord[0] != 0)
    { 
            /* have to read a partial first row */
            blc[0] = firstcoord[0] + 1;
            blc[1] = firstcoord[1] + 1;
            trc[1] = blc[1];  
            if (lastcoord[1] == firstcoord[1])
               trc[0] = lastcoord[0] + 1; /* 1st and last pixels in same row */
            else
               trc[0] = naxes[0];  /* read entire rest of the row */

            fits_write_compressed_img(fptr, datatype, blc, trc,
                nullcheck, arrayptr, nullval, status);

            *nread = *nread + trc[0] - blc[0] + 1;

            if (lastcoord[1] == firstcoord[1])
            {
               return(*status);  /* finished */
            }

            /* set starting coord to beginning of next line */
            firstcoord[0] = 0;
            firstcoord[1] += 1;
            arrayptr = arrayptr + (trc[0] - blc[0] + 1) * bytesperpixel;
    }

    /* write contiguous complete rows of the image, if any */
    blc[0] = 1;
    blc[1] = firstcoord[1] + 1;
    trc[0] = naxes[0];

    if (lastcoord[0] + 1 == naxes[0])
    {
            /* can write the last complete row, too */
            trc[1] = lastcoord[1] + 1;
    }
    else
    {
            /* last row is incomplete; have to read it separately */
            trc[1] = lastcoord[1];
    }

    if (trc[1] >= blc[1])  /* must have at least one whole line to read */
    {
        fits_write_compressed_img(fptr, datatype, blc, trc,
                nullcheck, arrayptr, nullval, status);

        *nread = *nread + (trc[1] - blc[1] + 1) * naxes[0];

        if (lastcoord[1] + 1 == trc[1])
               return(*status);  /* finished */

        /* increment pointers for the last partial row */
        arrayptr = arrayptr + (trc[1] - blc[1] + 1) * naxes[0] * bytesperpixel;

     }

    if (trc[1] == lastcoord[1] + 1)
        return(*status);           /* all done */

    /* set starting and ending coord to last line */

    trc[0] = lastcoord[0] + 1;
    trc[1] = lastcoord[1] + 1;
    blc[1] = trc[1];

    fits_write_compressed_img(fptr, datatype, blc, trc,
                nullcheck, arrayptr, nullval, status);

    *nread = *nread + trc[0] - blc[0] + 1;

    return(*status);
}

/* ######################################################################## */
/* ###                 Image Decompression Routines                     ### */
/* ######################################################################## */

/*--------------------------------------------------------------------------*/
int fits_img_decompress (fitsfile *infptr, /* image (bintable) to uncompress */
              fitsfile *outfptr,   /* empty HDU for output uncompressed image */
              int *status)         /* IO - error status               */

/* 
  This routine decompresses the whole image and writes it to the output file.
*/

{
    int ii, datatype = 0;
    int nullcheck, anynul;
    LONGLONG fpixel[MAX_COMPRESS_DIM], lpixel[MAX_COMPRESS_DIM];
    long inc[MAX_COMPRESS_DIM];
    long imgsize;
    float *nulladdr, fnulval;
    double dnulval;

    if (fits_img_decompress_header(infptr, outfptr, status) > 0)
    {
    	return (*status);
    }

    /* force a rescan of the output header keywords, then reset the scaling */
    /* in case the BSCALE and BZERO keywords are present, so that the       */
    /* decompressed values won't be scaled when written to the output image */
    ffrdef(outfptr, status);
    ffpscl(outfptr, 1.0, 0.0, status);
    ffpscl(infptr, 1.0, 0.0, status);

    /* initialize; no null checking is needed for integer images */
    nullcheck = 0;
    nulladdr =  &fnulval;

    /* determine datatype for image */
    if ((infptr->Fptr)->zbitpix == BYTE_IMG)
    {
        datatype = TBYTE;
    }
    else if ((infptr->Fptr)->zbitpix == SHORT_IMG)
    {
        datatype = TSHORT;
    }
    else if ((infptr->Fptr)->zbitpix == LONG_IMG)
    {
        datatype = TINT;
    }
    else if ((infptr->Fptr)->zbitpix == FLOAT_IMG)
    {
        /* In the case of float images we must check for NaNs  */
        nullcheck = 1;
        fnulval = FLOATNULLVALUE;
        nulladdr =  &fnulval;
        datatype = TFLOAT;
    }
    else if ((infptr->Fptr)->zbitpix == DOUBLE_IMG)
    {
        /* In the case of double images we must check for NaNs  */
        nullcheck = 1;
        dnulval = DOUBLENULLVALUE;
        nulladdr = (float *) &dnulval;
        datatype = TDOUBLE;
    }

    /* calculate size of the image (in pixels) */
    imgsize = 1;
    for (ii = 0; ii < (infptr->Fptr)->zndim; ii++)
    {
        imgsize *= (infptr->Fptr)->znaxis[ii];
        fpixel[ii] = 1;              /* Set first and last pixel to */
        lpixel[ii] = (infptr->Fptr)->znaxis[ii]; /* include the entire image. */
        inc[ii] = 1;
    }

    /* uncompress the input image and write to output image, one tile at a time */

    fits_read_write_compressed_img(infptr, datatype, fpixel, lpixel, inc,  
            nullcheck, nulladdr, &anynul, outfptr, status);

    return (*status);
}
/*--------------------------------------------------------------------------*/
int fits_decompress_img (fitsfile *infptr, /* image (bintable) to uncompress */
              fitsfile *outfptr,   /* empty HDU for output uncompressed image */
              int *status)         /* IO - error status               */

/* 
  THIS IS AN OBSOLETE ROUTINE.  USE fits_img_decompress instead!!!
  
  This routine decompresses the whole image and writes it to the output file.
*/

{
    double *data;
    int ii, datatype = 0, byte_per_pix = 0;
    int nullcheck, anynul;
    LONGLONG fpixel[MAX_COMPRESS_DIM], lpixel[MAX_COMPRESS_DIM];
    long inc[MAX_COMPRESS_DIM];
    long imgsize, memsize;
    float *nulladdr, fnulval;
    double dnulval;

    if (*status > 0)
        return(*status);

    if (!fits_is_compressed_image(infptr, status) )
    {
        ffpmsg("CHDU is not a compressed image (fits_decompress_img)");
        return(*status = DATA_DECOMPRESSION_ERR);
    }

    /* create an empty output image with the correct dimensions */
    if (ffcrim(outfptr, (infptr->Fptr)->zbitpix, (infptr->Fptr)->zndim, 
       (infptr->Fptr)->znaxis, status) > 0)
    {
        ffpmsg("error creating output decompressed image HDU");
    	return (*status);
    }
    /* Copy the table header to the image header. */
    if (imcomp_copy_imheader(infptr, outfptr, status) > 0)
    {
        ffpmsg("error copying header of compressed image");
    	return (*status);
    }

    /* force a rescan of the output header keywords, then reset the scaling */
    /* in case the BSCALE and BZERO keywords are present, so that the       */
    /* decompressed values won't be scaled when written to the output image */
    ffrdef(outfptr, status);
    ffpscl(outfptr, 1.0, 0.0, status);
    ffpscl(infptr, 1.0, 0.0, status);

    /* initialize; no null checking is needed for integer images */
    nullcheck = 0;
    nulladdr =  &fnulval;

    /* determine datatype for image */
    if ((infptr->Fptr)->zbitpix == BYTE_IMG)
    {
        datatype = TBYTE;
        byte_per_pix = 1;
    }
    else if ((infptr->Fptr)->zbitpix == SHORT_IMG)
    {
        datatype = TSHORT;
        byte_per_pix = sizeof(short);
    }
    else if ((infptr->Fptr)->zbitpix == LONG_IMG)
    {
        datatype = TINT;
        byte_per_pix = sizeof(int);
    }
    else if ((infptr->Fptr)->zbitpix == FLOAT_IMG)
    {
        /* In the case of float images we must check for NaNs  */
        nullcheck = 1;
        fnulval = FLOATNULLVALUE;
        nulladdr =  &fnulval;
        datatype = TFLOAT;
        byte_per_pix = sizeof(float);
    }
    else if ((infptr->Fptr)->zbitpix == DOUBLE_IMG)
    {
        /* In the case of double images we must check for NaNs  */
        nullcheck = 1;
        dnulval = DOUBLENULLVALUE;
        nulladdr = (float *) &dnulval;
        datatype = TDOUBLE;
        byte_per_pix = sizeof(double);
    }

    /* calculate size of the image (in pixels) */
    imgsize = 1;
    for (ii = 0; ii < (infptr->Fptr)->zndim; ii++)
    {
        imgsize *= (infptr->Fptr)->znaxis[ii];
        fpixel[ii] = 1;              /* Set first and last pixel to */
        lpixel[ii] = (infptr->Fptr)->znaxis[ii]; /* include the entire image. */
        inc[ii] = 1;
    }
    /* Calc equivalent number of double pixels same size as whole the image. */
    /* We use double datatype to force the memory to be aligned properly */
    memsize = ((imgsize * byte_per_pix) - 1) / sizeof(double) + 1;

    /* allocate memory for the image */
    data = (double*) calloc (memsize, sizeof(double));
    if (!data)
    { 
        ffpmsg("Couldn't allocate memory for the uncompressed image");
        return(*status = MEMORY_ALLOCATION);
    }

    /* uncompress the entire image into memory */
    /* This routine should be enhanced sometime to only need enough */
    /* memory to uncompress one tile at a time.  */
    fits_read_compressed_img(infptr, datatype, fpixel, lpixel, inc,  
            nullcheck, nulladdr, data, NULL, &anynul, status);

    /* write the image to the output file */
    if (anynul)
        fits_write_imgnull(outfptr, datatype, 1, imgsize, data, nulladdr, 
                          status);
    else
        fits_write_img(outfptr, datatype, 1, imgsize, data, status);

    free(data);
    return (*status);
}
/*--------------------------------------------------------------------------*/
int fits_img_decompress_header(fitsfile *infptr, /* image (bintable) to uncompress */
              fitsfile *outfptr,   /* empty HDU for output uncompressed image */
              int *status)         /* IO - error status               */

/* 
  This routine reads the header of the input tile compressed image and 
  converts it to that of a standard uncompress FITS image.
*/

{
    int writeprime = 0;
    int hdupos, inhdupos, numkeys;
    int nullprime = 0, copyprime = 0, norec = 0, tstatus;
    char card[FLEN_CARD];
    int ii, naxis, bitpix;
    long naxes[MAX_COMPRESS_DIM];

    if (*status > 0)
        return(*status);
    else if (*status == -1) {
        *status = 0;
	writeprime = 1;
    }

    if (!fits_is_compressed_image(infptr, status) )
    {
        ffpmsg("CHDU is not a compressed image (fits_img_decompress)");
        return(*status = DATA_DECOMPRESSION_ERR);
    }

    /* get information about the state of the output file; does it already */
    /* contain any keywords and HDUs?  */
    fits_get_hdu_num(infptr, &inhdupos);  /* Get the current output HDU position */
    fits_get_hdu_num(outfptr, &hdupos);  /* Get the current output HDU position */
    fits_get_hdrspace(outfptr, &numkeys, 0, status);

    /* Was the input compressed HDU originally the primary array image? */
    tstatus = 0;
    if (!fits_read_card(infptr, "ZSIMPLE", card, &tstatus)) { 
      /* yes, input HDU was a primary array (not an IMAGE extension) */
      /* Now determine if we can uncompress it into the primary array of */
      /* the output file.  This is only possible if the output file */
      /* currently only contains a null primary array, with no addition */
      /* header keywords and with no following extension in the FITS file. */
      
      if (hdupos == 1) {  /* are we positioned at the primary array? */
            if (numkeys == 0) { /* primary HDU is completely empty */
	        nullprime = 1;
            } else {
                fits_get_img_param(outfptr, MAX_COMPRESS_DIM, &bitpix, &naxis, naxes, status);
	
	        if (naxis == 0) { /* is this a null image? */
                   nullprime = 1;

		   if (inhdupos == 2)  /* must be at the first extension */
		      copyprime = 1;
		}
           }
      }
    } 

    if (nullprime) {  
       /* We will delete the existing keywords in the null primary array
          and uncompress the input image into the primary array of the output.
	  Some of these keywords may be added back to the uncompressed image
	  header later.
       */

       for (ii = numkeys; ii > 0; ii--)
          fits_delete_record(outfptr, ii, status);

    } else  {

       /* if the ZTENSION keyword doesn't exist, then we have to 
          write the required keywords manually */
       tstatus = 0;
       if (fits_read_card(infptr, "ZTENSION", card, &tstatus)) {

          /* create an empty output image with the correct dimensions */
          if (ffcrim(outfptr, (infptr->Fptr)->zbitpix, (infptr->Fptr)->zndim, 
             (infptr->Fptr)->znaxis, status) > 0)
          {
             ffpmsg("error creating output decompressed image HDU");
    	     return (*status);
          }

	  norec = 1;  /* the required keywords have already been written */

       } else {  /* the input compressed image does have ZTENSION keyword */
       
          if (writeprime) {  /* convert the image extension to a primary array */
	      /* have to write the required keywords manually */

              /* create an empty output image with the correct dimensions */
              if (ffcrim(outfptr, (infptr->Fptr)->zbitpix, (infptr->Fptr)->zndim, 
                 (infptr->Fptr)->znaxis, status) > 0)
              {
                 ffpmsg("error creating output decompressed image HDU");
    	         return (*status);
              }

	      norec = 1;  /* the required keywords have already been written */

          } else {  /* write the input compressed image to an image extension */

              if (numkeys == 0) {  /* the output file is currently completely empty */
	  
	         /* In this case, the input is a compressed IMAGE extension. */
	         /* Since the uncompressed output file is currently completely empty, */
	         /* we need to write a null primary array before uncompressing the */
                 /* image extension */
	     
                 ffcrim(outfptr, 8, 0, naxes, status); /* naxes is not used */
	     
	         /* now create the empty extension to uncompress into */
                 if (fits_create_hdu(outfptr, status) > 0)
                 {
                      ffpmsg("error creating output decompressed image HDU");
    	              return (*status);
                 }
	  
	      } else {
                  /* just create a new empty extension, then copy all the required */
	          /* keywords into it.  */
                 fits_create_hdu(outfptr, status);
	      }
           }
       }

    }

    if (*status > 0)  {
        ffpmsg("error creating output decompressed image HDU");
    	return (*status);
    }

    /* Copy the table header to the image header. */

    if (imcomp_copy_comp2img(infptr, outfptr, norec, status) > 0)
    {
        ffpmsg("error copying header keywords from compressed image");
    }

    if (copyprime) {  
	/* append any unexpected keywords from the primary array.
	   This includes any keywords except SIMPLE, BITPIX, NAXIS,
	   EXTEND, COMMENT, HISTORY, CHECKSUM, and DATASUM.
	*/

        fits_movabs_hdu(infptr, 1, NULL, status);  /* move to primary array */
	
        /* do this so that any new keywords get written before any blank
	   keywords that may have been appended by imcomp_copy_comp2img  */
        fits_set_hdustruc(outfptr, status);

        if (imcomp_copy_prime2img(infptr, outfptr, status) > 0)
        {
            ffpmsg("error copying primary keywords from compressed file");
        }

        fits_movabs_hdu(infptr, 2, NULL, status); /* move back to where we were */
    }

    return (*status);
}
/*---------------------------------------------------------------------------*/
int fits_read_compressed_img(fitsfile *fptr,   /* I - FITS file pointer      */
            int  datatype,  /* I - datatype of the array to be returned      */
            LONGLONG  *infpixel, /* I - 'bottom left corner' of the subsection    */
            LONGLONG  *inlpixel, /* I - 'top right corner' of the subsection      */
            long  *ininc,    /* I - increment to be applied in each dimension */
            int  nullcheck,  /* I - 0 for no null checking                   */
                              /*     1: set undefined pixels = nullval       */
                              /*     2: set nullarray=1 for undefined pixels */
            void *nullval,    /* I - value for undefined pixels              */
            void *array,      /* O - array of values that are returned       */
            char *nullarray,  /* O - array of flags = 1 if nullcheck = 2     */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
   Read a section of a compressed image;  Note: lpixel may be larger than the 
   size of the uncompressed image.  Only the pixels within the image will be
   returned.
*/
{
    long naxis[MAX_COMPRESS_DIM], tiledim[MAX_COMPRESS_DIM];
    long tilesize[MAX_COMPRESS_DIM], thistilesize[MAX_COMPRESS_DIM];
    long ftile[MAX_COMPRESS_DIM], ltile[MAX_COMPRESS_DIM];
    long tfpixel[MAX_COMPRESS_DIM], tlpixel[MAX_COMPRESS_DIM];
    long rowdim[MAX_COMPRESS_DIM], offset[MAX_COMPRESS_DIM],ntemp;
    long fpixel[MAX_COMPRESS_DIM], lpixel[MAX_COMPRESS_DIM];
    long inc[MAX_COMPRESS_DIM];
    long i5, i4, i3, i2, i1, i0, irow;
    int ii, ndim, pixlen, tilenul;
    void *buffer;
    char *bnullarray = 0;
    double testnullval = 0.;

    if (*status > 0) 
        return(*status);

    if (!fits_is_compressed_image(fptr, status) )
    {
        ffpmsg("CHDU is not a compressed image (fits_read_compressed_img)");
        return(*status = DATA_DECOMPRESSION_ERR);
    }

    /* get temporary space for uncompressing one image tile */
    if (datatype == TSHORT)
    {
       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (short)); 
       pixlen = sizeof(short);
       if (nullval)
           testnullval = *(short *) nullval;
    }
    else if (datatype == TINT)
    {
       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (int));
       pixlen = sizeof(int);
       if (nullval)
           testnullval = *(int *) nullval;
    }
    else if (datatype == TLONG)
    {
       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (long));
       pixlen = sizeof(long);
       if (nullval)
           testnullval = *(long *) nullval;
    }
    else if (datatype == TFLOAT)
    {
       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (float));
       pixlen = sizeof(float);
       if (nullval)
           testnullval = *(float *) nullval;
    }
    else if (datatype == TDOUBLE)
    {
       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (double));
       pixlen = sizeof(double);
       if (nullval)
           testnullval = *(double *) nullval;
    }
    else if (datatype == TUSHORT)
    {
       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (unsigned short));
       pixlen = sizeof(short);
       if (nullval)
           testnullval = *(unsigned short *) nullval;
    }
    else if (datatype == TUINT)
    {
       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (unsigned int));
       pixlen = sizeof(int);
       if (nullval)
           testnullval = *(unsigned int *) nullval;
    }
    else if (datatype == TULONG)
    {
       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (unsigned long));
       pixlen = sizeof(long);
       if (nullval)
           testnullval = *(unsigned long *) nullval;
    }
    else if (datatype == TBYTE || datatype == TSBYTE)
    {
       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (char));
       pixlen = 1;
       if (nullval)
           testnullval = *(unsigned char *) nullval;
    }
    else
    {
        ffpmsg("unsupported datatype for uncompressing image");
        return(*status = BAD_DATATYPE);
    }

    /* If nullcheck ==1 and nullval == 0, then this means that the */
    /* calling routine does not want to check for null pixels in the array */
    if (nullcheck == 1 && testnullval == 0.)
        nullcheck = 0;

    if (buffer == NULL)
    {
	    ffpmsg("Out of memory (fits_read_compress_img)");
	    return (*status = MEMORY_ALLOCATION);
    }
	
    /* allocate memory for a null flag array, if needed */
    if (nullcheck == 2)
    {
        bnullarray = calloc ((fptr->Fptr)->maxtilelen, sizeof (char));

        if (bnullarray == NULL)
        {
	    ffpmsg("Out of memory (fits_read_compress_img)");
            free(buffer);
	    return (*status = MEMORY_ALLOCATION);
        }
    }

    /* initialize all the arrays */
    for (ii = 0; ii < MAX_COMPRESS_DIM; ii++)
    {
        naxis[ii] = 1;
        tiledim[ii] = 1;
        tilesize[ii] = 1;
        ftile[ii] = 1;
        ltile[ii] = 1;
        rowdim[ii] = 1;
    }

    ndim = (fptr->Fptr)->zndim;
    ntemp = 1;
    for (ii = 0; ii < ndim; ii++)
    {
        /* support for mirror-reversed image sections */
        if (infpixel[ii] <= inlpixel[ii])
        {
           fpixel[ii] = (long) infpixel[ii];
           lpixel[ii] = (long) inlpixel[ii];
           inc[ii]    = ininc[ii];
        }
        else
        {
           fpixel[ii] = (long) inlpixel[ii];
           lpixel[ii] = (long) infpixel[ii];
           inc[ii]    = -ininc[ii];
        }

        /* calc number of tiles in each dimension, and tile containing */
        /* the first and last pixel we want to read in each dimension  */
        naxis[ii] = (fptr->Fptr)->znaxis[ii];
        if (fpixel[ii] < 1)
        {
            if (nullcheck == 2)
            {
                free(bnullarray);
            }
            free(buffer);
            return(*status = BAD_PIX_NUM);
        }

        tilesize[ii] = (fptr->Fptr)->tilesize[ii];
        tiledim[ii] = (naxis[ii] - 1) / tilesize[ii] + 1;
        ftile[ii]   = (fpixel[ii] - 1)   / tilesize[ii] + 1;
        ltile[ii]   = minvalue((lpixel[ii] - 1) / tilesize[ii] + 1, 
                                tiledim[ii]);
        rowdim[ii]  = ntemp;  /* total tiles in each dimension */
        ntemp *= tiledim[ii];
    }

    if (anynul)
       *anynul = 0;  /* initialize */

    /* support up to 6 dimensions for now */
    /* tfpixel and tlpixel are the first and last image pixels */
    /* along each dimension of the compression tile */
    for (i5 = ftile[5]; i5 <= ltile[5]; i5++)
    {
     tfpixel[5] = (i5 - 1) * tilesize[5] + 1;
     tlpixel[5] = minvalue(tfpixel[5] + tilesize[5] - 1, 
                            naxis[5]);
     thistilesize[5] = tlpixel[5] - tfpixel[5] + 1;
     offset[5] = (i5 - 1) * rowdim[5];
     for (i4 = ftile[4]; i4 <= ltile[4]; i4++)
     {
      tfpixel[4] = (i4 - 1) * tilesize[4] + 1;
      tlpixel[4] = minvalue(tfpixel[4] + tilesize[4] - 1, 
                            naxis[4]);
      thistilesize[4] = thistilesize[5] * (tlpixel[4] - tfpixel[4] + 1);
      offset[4] = (i4 - 1) * rowdim[4] + offset[5];
      for (i3 = ftile[3]; i3 <= ltile[3]; i3++)
      {
        tfpixel[3] = (i3 - 1) * tilesize[3] + 1;
        tlpixel[3] = minvalue(tfpixel[3] + tilesize[3] - 1, 
                              naxis[3]);
        thistilesize[3] = thistilesize[4] * (tlpixel[3] - tfpixel[3] + 1);
        offset[3] = (i3 - 1) * rowdim[3] + offset[4];
        for (i2 = ftile[2]; i2 <= ltile[2]; i2++)
        {
          tfpixel[2] = (i2 - 1) * tilesize[2] + 1;
          tlpixel[2] = minvalue(tfpixel[2] + tilesize[2] - 1, 
                                naxis[2]);
          thistilesize[2] = thistilesize[3] * (tlpixel[2] - tfpixel[2] + 1);
          offset[2] = (i2 - 1) * rowdim[2] + offset[3];
          for (i1 = ftile[1]; i1 <= ltile[1]; i1++)
          {
            tfpixel[1] = (i1 - 1) * tilesize[1] + 1;
            tlpixel[1] = minvalue(tfpixel[1] + tilesize[1] - 1, 
                                  naxis[1]);
            thistilesize[1] = thistilesize[2] * (tlpixel[1] - tfpixel[1] + 1);
            offset[1] = (i1 - 1) * rowdim[1] + offset[2];
            for (i0 = ftile[0]; i0 <= ltile[0]; i0++)
            {
             tfpixel[0] = (i0 - 1) * tilesize[0] + 1;
             tlpixel[0] = minvalue(tfpixel[0] + tilesize[0] - 1, 
                                    naxis[0]);
              thistilesize[0] = thistilesize[1] * (tlpixel[0] - tfpixel[0] + 1);
              /* calculate row of table containing this tile */
              irow = i0 + offset[1];

/*
printf("row %d, %d %d, %d %d, %d %d; %d\n",
              irow, tfpixel[0],tlpixel[0],tfpixel[1],tlpixel[1],tfpixel[2],tlpixel[2],
	      thistilesize[0]);
*/   
              /* test if there are any intersecting pixels in this tile and the output image */
              if (imcomp_test_overlap(ndim, tfpixel, tlpixel, 
                      fpixel, lpixel, inc, status)) {
                  /* read and uncompress this row (tile) of the table */
                  /* also do type conversion and undefined pixel substitution */
                  /* at this point */

                  imcomp_decompress_tile(fptr, irow, thistilesize[0],
                    datatype, nullcheck, nullval, buffer, bnullarray, &tilenul,
                     status);

                  if (tilenul && anynul)
                      *anynul = 1;  /* there are null pixels */
/*
printf(" pixlen=%d, ndim=%d, %d %d %d, %d %d %d, %d %d %d\n",
     pixlen, ndim, fpixel[0],lpixel[0],inc[0],fpixel[1],lpixel[1],inc[1],
     fpixel[2],lpixel[2],inc[2]);
*/
                  /* copy the intersecting pixels from this tile to the output */
                  imcomp_copy_overlap(buffer, pixlen, ndim, tfpixel, tlpixel, 
                     bnullarray, array, fpixel, lpixel, inc, nullcheck, 
                     nullarray, status);
               }
            }
          }
        }
      }
     }
    }
    if (nullcheck == 2)
    {
        free(bnullarray);
    }
    free(buffer);

    return(*status);
}
/*---------------------------------------------------------------------------*/
int fits_read_write_compressed_img(fitsfile *fptr,   /* I - FITS file pointer      */
            int  datatype,  /* I - datatype of the array to be returned      */
            LONGLONG  *infpixel, /* I - 'bottom left corner' of the subsection    */
            LONGLONG  *inlpixel, /* I - 'top right corner' of the subsection      */
            long  *ininc,    /* I - increment to be applied in each dimension */
            int  nullcheck,  /* I - 0 for no null checking                   */
                              /*     1: set undefined pixels = nullval       */
            void *nullval,    /* I - value for undefined pixels              */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            fitsfile *outfptr,   /* I - FITS file pointer                    */
            int  *status)     /* IO - error status                           */
/*
   This is similar to fits_read_compressed_img, except that it writes
   the pixels to the output image, on a tile by tile basis instead of returning
   the array.
*/
{
    long naxis[MAX_COMPRESS_DIM], tiledim[MAX_COMPRESS_DIM];
    long tilesize[MAX_COMPRESS_DIM], thistilesize[MAX_COMPRESS_DIM];
    long ftile[MAX_COMPRESS_DIM], ltile[MAX_COMPRESS_DIM];
    long tfpixel[MAX_COMPRESS_DIM], tlpixel[MAX_COMPRESS_DIM];
    long rowdim[MAX_COMPRESS_DIM], offset[MAX_COMPRESS_DIM],ntemp;
    long fpixel[MAX_COMPRESS_DIM], lpixel[MAX_COMPRESS_DIM];
    long inc[MAX_COMPRESS_DIM];
    long i5, i4, i3, i2, i1, i0, irow;
    int ii, ndim, tilenul;
    void *buffer;
    char *bnullarray = 0, *cnull;
    LONGLONG firstelem;

    if (*status > 0) 
        return(*status);

    if (!fits_is_compressed_image(fptr, status) )
    {
        ffpmsg("CHDU is not a compressed image (fits_read_compressed_img)");
        return(*status = DATA_DECOMPRESSION_ERR);
    }

    cnull = (char *) nullval;  /* used to test if the nullval = 0 */
    
    /* get temporary space for uncompressing one image tile */
    /* If nullval == 0, then this means that the */
    /* calling routine does not want to check for null pixels in the array */
    if (datatype == TSHORT)
    {
       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (short)); 
       if (cnull) {
         if (cnull[0] == 0 && cnull[1] == 0 ) {
           nullcheck = 0;
	 }
       }
    }
    else if (datatype == TINT)
    {
       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (int));
       if (cnull) {
         if (cnull[0] == 0 && cnull[1] == 0 && cnull[2] == 0 && cnull[3] == 0 ) {
           nullcheck = 0;
	 }
       }
    }
    else if (datatype == TLONG)
    {
       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (long));
       if (cnull) {
         if (cnull[0] == 0 && cnull[1] == 0 && cnull[2] == 0 && cnull[3] == 0 ) {
           nullcheck = 0;
	 }
       }
    }
    else if (datatype == TFLOAT)
    {
       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (float));
       if (cnull) {
         if (cnull[0] == 0 && cnull[1] == 0 && cnull[2] == 0 && cnull[3] == 0  ) {
           nullcheck = 0;
	 }
       }
    }
    else if (datatype == TDOUBLE)
    {
       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (double));
       if (cnull) {
         if (cnull[0] == 0 && cnull[1] == 0 && cnull[2] == 0 && cnull[3] == 0 &&
	     cnull[4] == 0 && cnull[5] == 0 && cnull[6] == 0 && cnull[7] == 0 ) {
           nullcheck = 0;
	 }
       }
    }
    else if (datatype == TUSHORT)
    {
       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (unsigned short));
       if (cnull) {
         if (cnull[0] == 0 && cnull[1] == 0 ){
           nullcheck = 0;
	 }
       }
    }
    else if (datatype == TUINT)
    {
       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (unsigned int));
       if (cnull) {
         if (cnull[0] == 0 && cnull[1] == 0 && cnull[2] == 0 && cnull[3] == 0 ){
           nullcheck = 0;
	 }
       }
    }
    else if (datatype == TULONG)
    {
       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (unsigned long));
       if (cnull) {
         if (cnull[0] == 0 && cnull[1] == 0 && cnull[2] == 0 && cnull[3] == 0 ){
           nullcheck = 0;
	 }
       }
    }
    else if (datatype == TBYTE || datatype == TSBYTE)
    {
       buffer =  malloc ((fptr->Fptr)->maxtilelen * sizeof (char));
       if (cnull) {
         if (cnull[0] == 0){
           nullcheck = 0;
	 }
       }
    }
    else
    {
        ffpmsg("unsupported datatype for uncompressing image");
        return(*status = BAD_DATATYPE);
    }

    if (buffer == NULL)
    {
	    ffpmsg("Out of memory (fits_read_compress_img)");
	    return (*status = MEMORY_ALLOCATION);
    }

    /* initialize all the arrays */
    for (ii = 0; ii < MAX_COMPRESS_DIM; ii++)
    {
        naxis[ii] = 1;
        tiledim[ii] = 1;
        tilesize[ii] = 1;
        ftile[ii] = 1;
        ltile[ii] = 1;
        rowdim[ii] = 1;
    }

    ndim = (fptr->Fptr)->zndim;
    ntemp = 1;
    for (ii = 0; ii < ndim; ii++)
    {
        /* support for mirror-reversed image sections */
        if (infpixel[ii] <= inlpixel[ii])
        {
           fpixel[ii] = (long) infpixel[ii];
           lpixel[ii] = (long) inlpixel[ii];
           inc[ii]    = ininc[ii];
        }
        else
        {
           fpixel[ii] = (long) inlpixel[ii];
           lpixel[ii] = (long) infpixel[ii];
           inc[ii]    = -ininc[ii];
        }

        /* calc number of tiles in each dimension, and tile containing */
        /* the first and last pixel we want to read in each dimension  */
        naxis[ii] = (fptr->Fptr)->znaxis[ii];
        if (fpixel[ii] < 1)
        {
            free(buffer);
            return(*status = BAD_PIX_NUM);
        }

        tilesize[ii] = (fptr->Fptr)->tilesize[ii];
        tiledim[ii] = (naxis[ii] - 1) / tilesize[ii] + 1;
        ftile[ii]   = (fpixel[ii] - 1)   / tilesize[ii] + 1;
        ltile[ii]   = minvalue((lpixel[ii] - 1) / tilesize[ii] + 1, 
                                tiledim[ii]);
        rowdim[ii]  = ntemp;  /* total tiles in each dimension */
        ntemp *= tiledim[ii];
    }

    if (anynul)
       *anynul = 0;  /* initialize */

    firstelem = 1;

    /* support up to 6 dimensions for now */
    /* tfpixel and tlpixel are the first and last image pixels */
    /* along each dimension of the compression tile */
    for (i5 = ftile[5]; i5 <= ltile[5]; i5++)
    {
     tfpixel[5] = (i5 - 1) * tilesize[5] + 1;
     tlpixel[5] = minvalue(tfpixel[5] + tilesize[5] - 1, 
                            naxis[5]);
     thistilesize[5] = tlpixel[5] - tfpixel[5] + 1;
     offset[5] = (i5 - 1) * rowdim[5];
     for (i4 = ftile[4]; i4 <= ltile[4]; i4++)
     {
      tfpixel[4] = (i4 - 1) * tilesize[4] + 1;
      tlpixel[4] = minvalue(tfpixel[4] + tilesize[4] - 1, 
                            naxis[4]);
      thistilesize[4] = thistilesize[5] * (tlpixel[4] - tfpixel[4] + 1);
      offset[4] = (i4 - 1) * rowdim[4] + offset[5];
      for (i3 = ftile[3]; i3 <= ltile[3]; i3++)
      {
        tfpixel[3] = (i3 - 1) * tilesize[3] + 1;
        tlpixel[3] = minvalue(tfpixel[3] + tilesize[3] - 1, 
                              naxis[3]);
        thistilesize[3] = thistilesize[4] * (tlpixel[3] - tfpixel[3] + 1);
        offset[3] = (i3 - 1) * rowdim[3] + offset[4];
        for (i2 = ftile[2]; i2 <= ltile[2]; i2++)
        {
          tfpixel[2] = (i2 - 1) * tilesize[2] + 1;
          tlpixel[2] = minvalue(tfpixel[2] + tilesize[2] - 1, 
                                naxis[2]);
          thistilesize[2] = thistilesize[3] * (tlpixel[2] - tfpixel[2] + 1);
          offset[2] = (i2 - 1) * rowdim[2] + offset[3];
          for (i1 = ftile[1]; i1 <= ltile[1]; i1++)
          {
            tfpixel[1] = (i1 - 1) * tilesize[1] + 1;
            tlpixel[1] = minvalue(tfpixel[1] + tilesize[1] - 1, 
                                  naxis[1]);
            thistilesize[1] = thistilesize[2] * (tlpixel[1] - tfpixel[1] + 1);
            offset[1] = (i1 - 1) * rowdim[1] + offset[2];
            for (i0 = ftile[0]; i0 <= ltile[0]; i0++)
            {
              tfpixel[0] = (i0 - 1) * tilesize[0] + 1;
              tlpixel[0] = minvalue(tfpixel[0] + tilesize[0] - 1, 
                                    naxis[0]);
              thistilesize[0] = thistilesize[1] * (tlpixel[0] - tfpixel[0] + 1);
              /* calculate row of table containing this tile */
              irow = i0 + offset[1];
 
              /* read and uncompress this row (tile) of the table */
              /* also do type conversion and undefined pixel substitution */
              /* at this point */

              imcomp_decompress_tile(fptr, irow, thistilesize[0],
                    datatype, nullcheck, nullval, buffer, bnullarray, &tilenul,
                     status);

               /* write the image to the output file */

              if (tilenul && anynul) {     
                   /* this assumes that the tiled pixels are in the same order
		      as in the uncompressed FITS image.  This is not necessarily
		      the case, but it almost alway is in practice.  
		      Note that null checking is not performed for integer images,
		      so this could only be a problem for tile compressed floating
		      point images that use an unconventional tiling pattern.
		   */
                   fits_write_imgnull(outfptr, datatype, firstelem, thistilesize[0],
		      buffer, nullval, status);
              } else {
                  fits_write_subset(outfptr, datatype, tfpixel, tlpixel, 
		      buffer, status);
              }

              firstelem += thistilesize[0];

            }
          }
        }
      }
     }
    }

    free(buffer);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_read_compressed_pixels(fitsfile *fptr, /* I - FITS file pointer    */
            int  datatype,  /* I - datatype of the array to be returned     */
            LONGLONG   fpixel, /* I - 'first pixel to read          */
            LONGLONG   npixel,  /* I - number of pixels to read      */
            int  nullcheck,  /* I - 0 for no null checking                   */
                              /*     1: set undefined pixels = nullval       */
                              /*     2: set nullarray=1 for undefined pixels */
            void *nullval,    /* I - value for undefined pixels              */
            void *array,      /* O - array of values that are returned       */
            char *nullarray,  /* O - array of flags = 1 if nullcheck = 2     */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            int  *status)     /* IO - error status                           */
/*
   Read a consecutive set of pixels from a compressed image.  This routine
   interpretes the n-dimensional image as a long one-dimensional array. 
   This is actually a rather inconvenient way to read compressed images in
   general, and could be rather inefficient if the requested pixels to be
   read are located in many different image compression tiles.    

   The general strategy used here is to read the requested pixels in blocks
   that correspond to rectangular image sections.  
*/
{
    int naxis, ii, bytesperpixel, planenul;
    long naxes[MAX_COMPRESS_DIM], nread;
    long nplane, inc[MAX_COMPRESS_DIM];
    LONGLONG tfirst, tlast, last0, last1, dimsize[MAX_COMPRESS_DIM];
    LONGLONG firstcoord[MAX_COMPRESS_DIM], lastcoord[MAX_COMPRESS_DIM];
    char *arrayptr, *nullarrayptr;

    if (*status > 0)
        return(*status);

    arrayptr = (char *) array;
    nullarrayptr = nullarray;

    /* get size of array pixels, in bytes */
    bytesperpixel = ffpxsz(datatype);

    for (ii = 0; ii < MAX_COMPRESS_DIM; ii++)
    {
        naxes[ii] = 1;
        firstcoord[ii] = 0;
        lastcoord[ii] = 0;
        inc[ii] = 1;
    }

    /*  determine the dimensions of the image to be read */
    ffgidm(fptr, &naxis, status);
    ffgisz(fptr, MAX_COMPRESS_DIM, naxes, status);

    /* calc the cumulative number of pixels in each successive dimension */
    dimsize[0] = 1;
    for (ii = 1; ii < MAX_COMPRESS_DIM; ii++)
         dimsize[ii] = dimsize[ii - 1] * naxes[ii - 1];

    /*  determine the coordinate of the first and last pixel in the image */
    /*  Use zero based indexes here */
    tfirst = fpixel - 1;
    tlast = tfirst + npixel - 1;
    for (ii = naxis - 1; ii >= 0; ii--)
    {
        firstcoord[ii] = tfirst / dimsize[ii];
        lastcoord[ii] =  tlast / dimsize[ii];
        tfirst = tfirst - firstcoord[ii] * dimsize[ii];
        tlast = tlast - lastcoord[ii] * dimsize[ii];
    }

    /* to simplify things, treat 1-D, 2-D, and 3-D images as separate cases */

    if (naxis == 1)
    {
        /* Simple: just read the requested range of pixels */

        firstcoord[0] = firstcoord[0] + 1;
        lastcoord[0] = lastcoord[0] + 1;
        fits_read_compressed_img(fptr, datatype, firstcoord, lastcoord, inc,
            nullcheck, nullval, array, nullarray, anynul, status);
        return(*status);
    }
    else if (naxis == 2)
    {
        nplane = 0;  /* read 1st (and only) plane of the image */

        fits_read_compressed_img_plane(fptr, datatype, bytesperpixel,
          nplane, firstcoord, lastcoord, inc, naxes, nullcheck, nullval,
          array, nullarray, anynul, &nread, status);
    }
    else if (naxis == 3)
    {
        /* test for special case: reading an integral number of planes */
        if (firstcoord[0] == 0 && firstcoord[1] == 0 &&
            lastcoord[0] == naxes[0] - 1 && lastcoord[1] == naxes[1] - 1)
        {
            for (ii = 0; ii < MAX_COMPRESS_DIM; ii++)
            {
                /* convert from zero base to 1 base */
                (firstcoord[ii])++;
                (lastcoord[ii])++;
            }

            /* we can read the contiguous block of pixels in one go */
            fits_read_compressed_img(fptr, datatype, firstcoord, lastcoord, inc,
                nullcheck, nullval, array, nullarray, anynul, status);

            return(*status);
        }

        if (anynul)
            *anynul = 0;  /* initialize */

        /* save last coordinate in temporary variables */
        last0 = lastcoord[0];
        last1 = lastcoord[1];

        if (firstcoord[2] < lastcoord[2])
        {
            /* we will read up to the last pixel in all but the last plane */
            lastcoord[0] = naxes[0] - 1;
            lastcoord[1] = naxes[1] - 1;
        }

        /* read one plane of the cube at a time, for simplicity */
        for (nplane = (long) firstcoord[2]; nplane <= lastcoord[2]; nplane++)
        {
            if (nplane == lastcoord[2])
            {
                lastcoord[0] = last0;
                lastcoord[1] = last1;
            }

            fits_read_compressed_img_plane(fptr, datatype, bytesperpixel,
              nplane, firstcoord, lastcoord, inc, naxes, nullcheck, nullval,
              arrayptr, nullarrayptr, &planenul, &nread, status);

            if (planenul && anynul)
               *anynul = 1;  /* there are null pixels */

            /* for all subsequent planes, we start with the first pixel */
            firstcoord[0] = 0;
            firstcoord[1] = 0;

            /* increment pointers to next elements to be read */
            arrayptr = arrayptr + nread * bytesperpixel;
            if (nullarrayptr && (nullcheck == 2) )
                nullarrayptr = nullarrayptr + nread;
        }
    }
    else
    {
        ffpmsg("only 1D, 2D, or 3D images are currently supported");
        return(*status = DATA_DECOMPRESSION_ERR);
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_read_compressed_img_plane(fitsfile *fptr, /* I - FITS file   */
            int  datatype,  /* I - datatype of the array to be returned      */
            int  bytesperpixel, /* I - number of bytes per pixel in array */
            long   nplane,  /* I - which plane of the cube to read      */
            LONGLONG *firstcoord,  /* coordinate of first pixel to read */
            LONGLONG *lastcoord,   /* coordinate of last pixel to read */
            long *inc,         /* increment of pixels to read */
            long *naxes,      /* size of each image dimension */
            int  nullcheck,  /* I - 0 for no null checking                   */
                              /*     1: set undefined pixels = nullval       */
                              /*     2: set nullarray=1 for undefined pixels */
            void *nullval,    /* I - value for undefined pixels              */
            void *array,      /* O - array of values that are returned       */
            char *nullarray,  /* O - array of flags = 1 if nullcheck = 2     */
            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
            long *nread,      /* O - total number of pixels read and returned*/
            int  *status)     /* IO - error status                           */

   /*
           in general we have to read the first partial row of the image,
           followed by the middle complete rows, followed by the last
           partial row of the image.  If the first or last rows are complete,
           then read them at the same time as all the middle rows.
    */
{
     /* bottom left coord. and top right coord. */
    LONGLONG blc[MAX_COMPRESS_DIM], trc[MAX_COMPRESS_DIM]; 
    char *arrayptr, *nullarrayptr;
    int tnull;

    if (anynul)
        *anynul = 0;

    *nread = 0;

    arrayptr = (char *) array;
    nullarrayptr = nullarray;

    blc[2] = nplane + 1;
    trc[2] = nplane + 1;

    if (firstcoord[0] != 0)
    { 
            /* have to read a partial first row */
            blc[0] = firstcoord[0] + 1;
            blc[1] = firstcoord[1] + 1;
            trc[1] = blc[1];  
            if (lastcoord[1] == firstcoord[1])
               trc[0] = lastcoord[0] + 1; /* 1st and last pixels in same row */
            else
               trc[0] = naxes[0];  /* read entire rest of the row */

            fits_read_compressed_img(fptr, datatype, blc, trc, inc,
                nullcheck, nullval, arrayptr, nullarrayptr, &tnull, status);

            *nread = *nread + (long) (trc[0] - blc[0] + 1);

            if (tnull && anynul)
               *anynul = 1;  /* there are null pixels */

            if (lastcoord[1] == firstcoord[1])
            {
               return(*status);  /* finished */
            }

            /* set starting coord to beginning of next line */
            firstcoord[0] = 0;
            firstcoord[1] += 1;
            arrayptr = arrayptr + (trc[0] - blc[0] + 1) * bytesperpixel;
            if (nullarrayptr && (nullcheck == 2) )
                nullarrayptr = nullarrayptr + (trc[0] - blc[0] + 1);

    }

    /* read contiguous complete rows of the image, if any */
    blc[0] = 1;
    blc[1] = firstcoord[1] + 1;
    trc[0] = naxes[0];

    if (lastcoord[0] + 1 == naxes[0])
    {
            /* can read the last complete row, too */
            trc[1] = lastcoord[1] + 1;
    }
    else
    {
            /* last row is incomplete; have to read it separately */
            trc[1] = lastcoord[1];
    }

    if (trc[1] >= blc[1])  /* must have at least one whole line to read */
    {
        fits_read_compressed_img(fptr, datatype, blc, trc, inc,
                nullcheck, nullval, arrayptr, nullarrayptr, &tnull, status);

        *nread = *nread + (long) ((trc[1] - blc[1] + 1) * naxes[0]);

        if (tnull && anynul)
           *anynul = 1;

        if (lastcoord[1] + 1 == trc[1])
               return(*status);  /* finished */

        /* increment pointers for the last partial row */
        arrayptr = arrayptr + (trc[1] - blc[1] + 1) * naxes[0] * bytesperpixel;
        if (nullarrayptr && (nullcheck == 2) )
                nullarrayptr = nullarrayptr + (trc[1] - blc[1] + 1) * naxes[0];
     }

    if (trc[1] == lastcoord[1] + 1)
        return(*status);           /* all done */

    /* set starting and ending coord to last line */

    trc[0] = lastcoord[0] + 1;
    trc[1] = lastcoord[1] + 1;
    blc[1] = trc[1];

    fits_read_compressed_img(fptr, datatype, blc, trc, inc,
                nullcheck, nullval, arrayptr, nullarrayptr, &tnull, status);

    if (tnull && anynul)
       *anynul = 1;

    *nread = *nread + (long) (trc[0] - blc[0] + 1);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int imcomp_get_compressed_image_par(fitsfile *infptr, int *status)
 
/* 
    This routine reads keywords from a BINTABLE extension containing a
    compressed image.
*/
{
    char keyword[FLEN_KEYWORD];
    char value[FLEN_VALUE];
    int ii, tstatus, doffset;
    long expect_nrows, maxtilelen;

    if (*status > 0)
        return(*status);

    /* Copy relevant header keyword values to structure */
    if (ffgky (infptr, TSTRING, "ZCMPTYPE", value, NULL, status) > 0)
    {
        ffpmsg("required ZCMPTYPE compression keyword not found in");
        ffpmsg(" imcomp_get_compressed_image_par");
        return(*status);
    }

    (infptr->Fptr)->zcmptype[0] = '\0';
    strncat((infptr->Fptr)->zcmptype, value, 11);

    if (!FSTRCMP(value, "RICE_1") || !FSTRCMP(value, "RICE_ONE") )
        (infptr->Fptr)->compress_type = RICE_1;
    else if (!FSTRCMP(value, "HCOMPRESS_1") )
        (infptr->Fptr)->compress_type = HCOMPRESS_1;
    else if (!FSTRCMP(value, "GZIP_1") )
        (infptr->Fptr)->compress_type = GZIP_1;
    else if (!FSTRCMP(value, "GZIP_2") )
        (infptr->Fptr)->compress_type = GZIP_2;
    else if (!FSTRCMP(value, "BZIP2_1") )
        (infptr->Fptr)->compress_type = BZIP2_1;
    else if (!FSTRCMP(value, "PLIO_1") )
        (infptr->Fptr)->compress_type = PLIO_1;
    else if (!FSTRCMP(value, "NOCOMPRESS") )
        (infptr->Fptr)->compress_type = NOCOMPRESS;
    else
    {
        ffpmsg("Unknown image compression type:");
        ffpmsg(value);
	return (*status = DATA_DECOMPRESSION_ERR);
    }

    /* get the floating point to integer quantization type, if present. */
    /* FITS files produced before 2009 will not have this keyword */
    tstatus = 0;
    if (ffgky(infptr, TSTRING, "ZQUANTIZ", value, NULL, &tstatus) > 0)
    {
        (infptr->Fptr)->quantize_method = 0;
        (infptr->Fptr)->quantize_level = 0;
    } else {

        if (!FSTRCMP(value, "NONE") ) {
            (infptr->Fptr)->quantize_level = NO_QUANTIZE;
       } else if (!FSTRCMP(value, "SUBTRACTIVE_DITHER_1") )
            (infptr->Fptr)->quantize_method = SUBTRACTIVE_DITHER_1;
        else if (!FSTRCMP(value, "SUBTRACTIVE_DITHER_2") )
            (infptr->Fptr)->quantize_method = SUBTRACTIVE_DITHER_2;
        else if (!FSTRCMP(value, "NO_DITHER") )
            (infptr->Fptr)->quantize_method = NO_DITHER;
        else
            (infptr->Fptr)->quantize_method = 0;
    }

    /* get the floating point quantization dithering offset, if present. */
    /* FITS files produced before October 2009 will not have this keyword */
    tstatus = 0;
    if (ffgky(infptr, TINT, "ZDITHER0", &doffset, NULL, &tstatus) > 0)
    {
	/* by default start with 1st element of random sequence */
        (infptr->Fptr)->dither_seed = 1;  
    } else {
        (infptr->Fptr)->dither_seed = doffset;
    }

    if (ffgky (infptr, TINT,  "ZBITPIX",  &(infptr->Fptr)->zbitpix,  
               NULL, status) > 0)
    {
        ffpmsg("required ZBITPIX compression keyword not found");
        return(*status);
    }

    if (ffgky (infptr,TINT, "ZNAXIS", &(infptr->Fptr)->zndim, NULL, status) > 0)
    {
        ffpmsg("required ZNAXIS compression keyword not found");
        return(*status);
    }

    if ((infptr->Fptr)->zndim < 1)
    {
        ffpmsg("Compressed image has no data (ZNAXIS < 1)");
	return (*status = BAD_NAXIS);
    }

    if ((infptr->Fptr)->zndim > MAX_COMPRESS_DIM)
    {
        ffpmsg("Compressed image has too many dimensions");
        return(*status = BAD_NAXIS);
    }

    expect_nrows = 1;
    maxtilelen = 1;
    for (ii = 0;  ii < (infptr->Fptr)->zndim;  ii++)
    {
        /* get image size */
        snprintf (keyword, FLEN_KEYWORD,"ZNAXIS%d", ii+1);
	ffgky (infptr, TLONG,keyword, &(infptr->Fptr)->znaxis[ii],NULL,status);

        if (*status > 0)
        {
            ffpmsg("required ZNAXISn compression keyword not found");
            return(*status);
        }

        /* get compression tile size */
	snprintf (keyword, FLEN_KEYWORD,"ZTILE%d", ii+1);

        /* set default tile size in case keywords are not present */
        if (ii == 0)
            (infptr->Fptr)->tilesize[0] = (infptr->Fptr)->znaxis[0];
        else
            (infptr->Fptr)->tilesize[ii] = 1;

        tstatus = 0;
	ffgky (infptr, TLONG, keyword, &(infptr->Fptr)->tilesize[ii], NULL, 
               &tstatus);

        expect_nrows *= (((infptr->Fptr)->znaxis[ii] - 1) / 
                  (infptr->Fptr)->tilesize[ii]+ 1);
        maxtilelen *= (infptr->Fptr)->tilesize[ii];
    }

    /* check number of rows */
    if (expect_nrows != (infptr->Fptr)->numrows)
    {
        ffpmsg(
        "number of table rows != the number of tiles in compressed image");
        return (*status = DATA_DECOMPRESSION_ERR);
    }

    /* read any algorithm specific parameters */
    if ((infptr->Fptr)->compress_type == RICE_1 )
    {
        if (ffgky(infptr, TINT,"ZVAL1", &(infptr->Fptr)->rice_blocksize,
                  NULL, status) > 0)
        {
            ffpmsg("required ZVAL1 compression keyword not found");
            return(*status);
        }

        tstatus = 0;
        if (ffgky(infptr, TINT,"ZVAL2", &(infptr->Fptr)->rice_bytepix,
                  NULL, &tstatus) > 0)
        {
            (infptr->Fptr)->rice_bytepix = 4;  /* default value */
        }

        if ((infptr->Fptr)->rice_blocksize < 16 &&
	    (infptr->Fptr)->rice_bytepix > 8) {
	     /* values are reversed */
	     tstatus = (infptr->Fptr)->rice_bytepix;
	     (infptr->Fptr)->rice_bytepix = (infptr->Fptr)->rice_blocksize;
	     (infptr->Fptr)->rice_blocksize = tstatus;
        }
    } else if ((infptr->Fptr)->compress_type == HCOMPRESS_1 ) {

        if (ffgky(infptr, TFLOAT,"ZVAL1", &(infptr->Fptr)->hcomp_scale,
                  NULL, status) > 0)
        {
            ffpmsg("required ZVAL1 compression keyword not found");
            return(*status);
        }

        tstatus = 0;
        ffgky(infptr, TINT,"ZVAL2", &(infptr->Fptr)->hcomp_smooth,
                  NULL, &tstatus);
    }    

    /* store number of pixels in each compression tile, */
    /* and max size of the compressed tile buffer */
    (infptr->Fptr)->maxtilelen = maxtilelen;

    (infptr->Fptr)->maxelem = 
           imcomp_calc_max_elem ((infptr->Fptr)->compress_type, maxtilelen, 
               (infptr->Fptr)->zbitpix, (infptr->Fptr)->rice_blocksize);

    /* Get Column numbers. */
    if (ffgcno(infptr, CASEINSEN, "COMPRESSED_DATA",
         &(infptr->Fptr)->cn_compressed, status) > 0)
    {
        ffpmsg("couldn't find COMPRESSED_DATA column (fits_get_compressed_img_par)");
        return(*status = DATA_DECOMPRESSION_ERR);
    }

    ffpmrk(); /* put mark on message stack; erase any messages after this */

    tstatus = 0;
    ffgcno(infptr,CASEINSEN, "UNCOMPRESSED_DATA",
          &(infptr->Fptr)->cn_uncompressed, &tstatus);

    tstatus = 0;
    ffgcno(infptr,CASEINSEN, "GZIP_COMPRESSED_DATA",
          &(infptr->Fptr)->cn_gzip_data, &tstatus);

    tstatus = 0;
    if (ffgcno(infptr, CASEINSEN, "ZSCALE", &(infptr->Fptr)->cn_zscale,
              &tstatus) > 0)
    {
        /* CMPSCALE column doesn't exist; see if there is a keyword */
        tstatus = 0;
        if (ffgky(infptr, TDOUBLE, "ZSCALE", &(infptr->Fptr)->zscale, NULL, 
                 &tstatus) <= 0)
            (infptr->Fptr)->cn_zscale = -1;  /* flag for a constant ZSCALE */
    }

    tstatus = 0;
    if (ffgcno(infptr, CASEINSEN, "ZZERO", &(infptr->Fptr)->cn_zzero,
               &tstatus) > 0)
    {
        /* CMPZERO column doesn't exist; see if there is a keyword */
        tstatus = 0;
        if (ffgky(infptr, TDOUBLE, "ZZERO", &(infptr->Fptr)->zzero, NULL, 
                  &tstatus) <= 0)
            (infptr->Fptr)->cn_zzero = -1;  /* flag for a constant ZZERO */
    }

    tstatus = 0;
    if (ffgcno(infptr, CASEINSEN, "ZBLANK", &(infptr->Fptr)->cn_zblank,
               &tstatus) > 0)
    {
        /* ZBLANK column doesn't exist; see if there is a keyword */
        tstatus = 0;
        if (ffgky(infptr, TINT, "ZBLANK", &(infptr->Fptr)->zblank, NULL,
                  &tstatus) <= 0)  {
            (infptr->Fptr)->cn_zblank = -1;  /* flag for a constant ZBLANK */

        } else {
           /* ZBLANK keyword doesn't exist; see if there is a BLANK keyword */
           tstatus = 0;
           if (ffgky(infptr, TINT, "BLANK", &(infptr->Fptr)->zblank, NULL,
                  &tstatus) <= 0)  
              (infptr->Fptr)->cn_zblank = -1;  /* flag for a constant ZBLANK */
        }
    }

    /* read the conventional BSCALE and BZERO scaling keywords, if present */
    tstatus = 0;
    if (ffgky (infptr, TDOUBLE, "BSCALE", &(infptr->Fptr)->cn_bscale, 
        NULL, &tstatus) > 0)
    {
        (infptr->Fptr)->cn_bscale = 1.0;
    }

    tstatus = 0;
    if (ffgky (infptr, TDOUBLE, "BZERO", &(infptr->Fptr)->cn_bzero, 
        NULL, &tstatus) > 0)
    {
        (infptr->Fptr)->cn_bzero = 0.0;
        (infptr->Fptr)->cn_actual_bzero = 0.0;
    } else {
        (infptr->Fptr)->cn_actual_bzero = (infptr->Fptr)->cn_bzero;
    }

    /* special case: the quantization level is not given by a keyword in  */
    /* the HDU header, so we have to explicitly copy the requested value */
    /* to the actual value */
    if ( (infptr->Fptr)->request_quantize_level != 0.)
        (infptr->Fptr)->quantize_level = (infptr->Fptr)->request_quantize_level;

    ffcmrk();  /* clear any spurious error messages, back to the mark */
    return (*status);
}
/*--------------------------------------------------------------------------*/
int imcomp_copy_imheader(fitsfile *infptr, fitsfile *outfptr, int *status)
/*
    This routine reads the header keywords from the input image and
    copies them to the output image;  the manditory structural keywords
    and the checksum keywords are not copied. If the DATE keyword is copied,
    then it is updated with the current date and time.
*/
{
    int nkeys, ii, keyclass;
    char card[FLEN_CARD];	/* a header record */

    if (*status > 0)
        return(*status);

    ffghsp(infptr, &nkeys, NULL, status); /* get number of keywords in image */

    for (ii = 5; ii <= nkeys; ii++)  /* skip the first 4 keywords */
    {
        ffgrec(infptr, ii, card, status);

	keyclass = ffgkcl(card);  /* Get the type/class of keyword */

        /* don't copy structural keywords or checksum keywords */
        if ((keyclass <= TYP_CMPRS_KEY) || (keyclass == TYP_CKSUM_KEY))
	    continue;

        if (FSTRNCMP(card, "DATE ", 5) == 0) /* write current date */
        {
            ffpdat(outfptr, status);
        }
        else if (FSTRNCMP(card, "EXTNAME ", 8) == 0) 
        {
            /* don't copy default EXTNAME keyword from a compressed image */
            if (FSTRNCMP(card, "EXTNAME = 'COMPRESSED_IMAGE'", 28))
            {
                /* if EXTNAME keyword already exists, overwrite it */
                /* otherwise append a new EXTNAME keyword */
                ffucrd(outfptr, "EXTNAME", card, status);
            }
        }
        else
        {
            /* just copy the keyword to the output header */
	    ffprec (outfptr, card, status);
        }

        if (*status > 0)
           return (*status);
    }
    return (*status);
}
/*--------------------------------------------------------------------------*/
int imcomp_copy_img2comp(fitsfile *infptr, fitsfile *outfptr, int *status)
/*
    This routine copies the header keywords from the uncompressed input image 
    and to the compressed image (in a binary table) 
*/
{
    char card[FLEN_CARD], card2[FLEN_CARD];	/* a header record */
    int nkeys, nmore, ii, jj, tstatus, bitpix;

    /* tile compressed image keyword translation table  */
    /*                        INPUT      OUTPUT  */
    /*                       01234567   01234567 */
    char *patterns[][2] = {{"SIMPLE",  "ZSIMPLE" },  
			   {"XTENSION", "ZTENSION" },
			   {"BITPIX",  "ZBITPIX" },
			   {"NAXIS",   "ZNAXIS"  },
			   {"NAXISm",  "ZNAXISm" },
			   {"EXTEND",  "ZEXTEND" },
			   {"BLOCKED", "ZBLOCKED"},
			   {"PCOUNT",  "ZPCOUNT" },  
			   {"GCOUNT",  "ZGCOUNT" },

			   {"CHECKSUM","ZHECKSUM"},  /* save original checksums */
			   {"DATASUM", "ZDATASUM"},
			   
			   {"*",       "+"       }}; /* copy all other keywords */
    int npat;

    if (*status > 0)
        return(*status);

    /* write a default EXTNAME keyword if it doesn't exist in input file*/
    fits_read_card(infptr, "EXTNAME", card, status);
    
    if (*status) {
       *status = 0;
       strcpy(card, "EXTNAME = 'COMPRESSED_IMAGE'");
       fits_write_record(outfptr, card, status);
    }

    /* copy all the keywords from the input file to the output */
    npat = sizeof(patterns)/sizeof(patterns[0][0])/2;
    fits_translate_keywords(infptr, outfptr, 1, patterns, npat,
			    0, 0, 0, status);


    if ( (outfptr->Fptr)->request_lossy_int_compress != 0) { 

	/* request was made to compress integer images as if they had float pixels. */
	/* If input image has positive bitpix value, then reset the output ZBITPIX */
	/* value to -32. */

	fits_read_key(infptr, TINT, "BITPIX", &bitpix, NULL, status);

	if (*status <= 0 && bitpix > 0) {
	    fits_modify_key_lng(outfptr, "ZBITPIX", -32, NULL, status);

	    /* also delete the BSCALE, BZERO, and BLANK keywords */
	    tstatus = 0;
	    fits_delete_key(outfptr, "BSCALE", &tstatus);
	    tstatus = 0;
	    fits_delete_key(outfptr, "BZERO", &tstatus);
	    tstatus = 0;
	    fits_delete_key(outfptr, "BLANK", &tstatus);
	}
    }

   /*
     For compatibility with software that uses an older version of CFITSIO,
     we must make certain that the new ZQUANTIZ keyword, if it exists, must
     occur after the other peudo-required keywords (e.g., ZSIMPLE, ZBITPIX,
     etc.).  Do this by trying to delete the keyword.  If that succeeds (and
     thus the keyword did exist) then rewrite the keyword at the end of header.
     In principle this should not be necessary once all software has upgraded
     to a newer version of CFITSIO (version number greater than 3.181, newer
     than August 2009).
     
     Do the same for the new ZDITHER0 keyword.
   */

   tstatus = 0;
   if (fits_read_card(outfptr, "ZQUANTIZ", card, &tstatus) == 0)
   {
        fits_delete_key(outfptr, "ZQUANTIZ", status);

        /* rewrite the deleted keyword at the end of the header */
        fits_write_record(outfptr, card, status);

	/* write some associated HISTORY keywords */
        fits_parse_value(card, card2, NULL, status);
	if (fits_strncasecmp(card2, "'NONE", 5) ) {
	    /* the value is not 'NONE' */	
	    fits_write_history(outfptr, 
	        "Image was compressed by CFITSIO using scaled integer quantization:", status);
	    snprintf(card2, FLEN_CARD,"  q = %f / quantized level scaling parameter", 
	        (outfptr->Fptr)->request_quantize_level);
	    fits_write_history(outfptr, card2, status); 
	    fits_write_history(outfptr, card+10, status); 
	}
   }

   tstatus = 0;
   if (fits_read_card(outfptr, "ZDITHER0", card, &tstatus) == 0)
   {
        fits_delete_key(outfptr, "ZDITHER0", status);

        /* rewrite the deleted keyword at the end of the header */
        fits_write_record(outfptr, card, status);
   }


    ffghsp(infptr, &nkeys, &nmore, status); /* get number of keywords in image */

    nmore = nmore / 36;  /* how many completely empty header blocks are there? */
     
     /* preserve the same number of spare header blocks in the output header */
     
    for (jj = 0; jj < nmore; jj++)
       for (ii = 0; ii < 36; ii++)
          fits_write_record(outfptr, "    ", status);

    return (*status);
}
/*--------------------------------------------------------------------------*/
int imcomp_copy_comp2img(fitsfile *infptr, fitsfile *outfptr, 
                          int norec, int *status)
/*
    This routine copies the header keywords from the compressed input image 
    and to the uncompressed image (in a binary table) 
*/
{
    char card[FLEN_CARD];	/* a header record */
    char *patterns[40][2];
    char negative[] = "-";
    int ii,jj, npat, nreq, nsp, tstatus = 0;
    int nkeys, nmore;
    
    /* tile compressed image keyword translation table  */
    /*                        INPUT      OUTPUT  */
    /*                       01234567   01234567 */

    /*  only translate these if required keywords not already written */
    char *reqkeys[][2] = {  
			   {"ZSIMPLE",   "SIMPLE" },  
			   {"ZTENSION", "XTENSION"},
			   {"ZBITPIX",   "BITPIX" },
			   {"ZNAXIS",    "NAXIS"  },
			   {"ZNAXISm",   "NAXISm" },
			   {"ZEXTEND",   "EXTEND" },
			   {"ZBLOCKED",  "BLOCKED"},
			   {"ZPCOUNT",   "PCOUNT" },  
			   {"ZGCOUNT",   "GCOUNT" },
			   {"ZHECKSUM",  "CHECKSUM"},  /* restore original checksums */
			   {"ZDATASUM",  "DATASUM"}}; 

    /* other special keywords */
    char *spkeys[][2] = {
			   {"XTENSION", "-"      },
			   {"BITPIX",  "-"       },
			   {"NAXIS",   "-"       },
			   {"NAXISm",  "-"       },
			   {"PCOUNT",  "-"       },
			   {"GCOUNT",  "-"       },
			   {"TFIELDS", "-"       },
			   {"TTYPEm",  "-"       },
			   {"TFORMm",  "-"       },
			   {"THEAP",   "-"       },
			   {"ZIMAGE",  "-"       },
			   {"ZQUANTIZ", "-"      },
			   {"ZDITHER0", "-"      },
			   {"ZTILEm",  "-"       },
			   {"ZCMPTYPE", "-"      },
			   {"ZBLANK",  "-"       },
			   {"ZNAMEm",  "-"       },
			   {"ZVALm",   "-"       },

			   {"CHECKSUM","-"       },  /* delete checksums */
			   {"DATASUM", "-"       },
			   {"EXTNAME", "+"       },  /* we may change this, below */
			   {"*",       "+"      }};  


    if (*status > 0)
        return(*status);
	
    nreq = sizeof(reqkeys)/sizeof(reqkeys[0][0])/2;
    nsp = sizeof(spkeys)/sizeof(spkeys[0][0])/2;

    /* construct translation patterns */

    for (ii = 0; ii < nreq; ii++) {
        patterns[ii][0] = reqkeys[ii][0];
	
        if (norec) 
            patterns[ii][1] = negative;
        else
            patterns[ii][1] = reqkeys[ii][1];
    }
    
    for (ii = 0; ii < nsp; ii++) {
        patterns[ii+nreq][0] = spkeys[ii][0];
        patterns[ii+nreq][1] = spkeys[ii][1];
    }

    npat = nreq + nsp;
    
    /* see if the EXTNAME keyword should be copied or not */
    fits_read_card(infptr, "EXTNAME", card, &tstatus);

    if (tstatus == 0) {
      if (!strncmp(card, "EXTNAME = 'COMPRESSED_IMAGE'", 28)) 
        patterns[npat-2][1] = negative;
    }
    
    /* translate and copy the keywords from the input file to the output */
    fits_translate_keywords(infptr, outfptr, 1, patterns, npat,
			    0, 0, 0, status);

    ffghsp(infptr, &nkeys, &nmore, status); /* get number of keywords in image */

    nmore = nmore / 36;  /* how many completely empty header blocks are there? */
     
    /* preserve the same number of spare header blocks in the output header */
     
    for (jj = 0; jj < nmore; jj++)
       for (ii = 0; ii < 36; ii++)
          fits_write_record(outfptr, "    ", status);


    return (*status);
}
/*--------------------------------------------------------------------------*/
int imcomp_copy_prime2img(fitsfile *infptr, fitsfile *outfptr, int *status)
/*
    This routine copies any unexpected keywords from the primary array
    of the compressed input image into the header of the uncompressed image
    (which is the primary array of the output file). 
*/
{
    int  nsp;

    /* keywords that will not be copied */
    char *spkeys[][2] = {
			   {"SIMPLE", "-"      },
			   {"BITPIX",  "-"       },
			   {"NAXIS",   "-"       },
			   {"NAXISm",  "-"       },
			   {"PCOUNT",  "-"       },
			   {"EXTEND",  "-"       },
			   {"GCOUNT",  "-"       },
			   {"CHECKSUM","-"       }, 
			   {"DATASUM", "-"       },
			   {"EXTNAME", "-"       },
			   {"HISTORY", "-"       },
			   {"COMMENT", "-"       },
			   {"*",       "+"      }};  

    if (*status > 0)
        return(*status);
	
    nsp = sizeof(spkeys)/sizeof(spkeys[0][0])/2;

    /* translate and copy the keywords from the input file to the output */
    fits_translate_keywords(infptr, outfptr, 1, spkeys, nsp,
			    0, 0, 0, status);

    return (*status);
}
/*--------------------------------------------------------------------------*/
int imcomp_decompress_tile (fitsfile *infptr,
          int nrow,            /* I - row of table to read and uncompress */
          int tilelen,         /* I - number of pixels in the tile        */
          int datatype,        /* I - datatype to be returned in 'buffer' */
          int nullcheck,       /* I - 0 for no null checking */
          void *nulval,        /* I - value to be used for undefined pixels */
          void *buffer,        /* O - buffer for returned decompressed values */
          char *bnullarray,    /* O - buffer for returned null flags */
          int *anynul,         /* O - any null values returned?  */
          int *status)

/* This routine decompresses one tile of the image */
{
    int *idata = 0;
    int tiledatatype, pixlen = 0;          /* uncompressed integer data */
    size_t idatalen, tilebytesize;
    int ii, tnull;        /* value in the data which represents nulls */
    unsigned char *cbuf; /* compressed data */
    unsigned char charnull = 0;
    short snull = 0;
    int blocksize, ntilebins, tilecol = 0;
    float fnulval=0;
    float *tempfloat = 0;
    double dnulval=0;
    double bscale, bzero, actual_bzero, dummy = 0;    /* scaling parameters */
    long tilesize;      /* number of bytes */
    int smooth, nx, ny, scale;  /* hcompress parameters */
    LONGLONG nelemll = 0, offset = 0;

    if (*status > 0)
       return(*status);


    /* **************************************************************** */
    /* allocate pointers to array of cached uncompressed tiles, if not already done */
    if ((infptr->Fptr)->tilerow == 0)  {

      /* calculate number of column bins of compressed tile */
      ntilebins =  (((infptr->Fptr)->znaxis[0] - 1) / ((infptr->Fptr)->tilesize[0])) + 1;

     if ((infptr->Fptr)->znaxis[0]   != (infptr->Fptr)->tilesize[0] ||
        (infptr->Fptr)->tilesize[1] != 1 ) {   /* don't cache the tile if only single row of the image */

        (infptr->Fptr)->tilerow = (int *) calloc (ntilebins, sizeof(int));
        (infptr->Fptr)->tiledata = (void**) calloc (ntilebins, sizeof(void*));
        (infptr->Fptr)->tilenullarray = (void **) calloc (ntilebins, sizeof(char*));
        (infptr->Fptr)->tiledatasize = (long *) calloc (ntilebins, sizeof(long));
        (infptr->Fptr)->tiletype = (int *) calloc (ntilebins, sizeof(int));
        (infptr->Fptr)->tileanynull = (int *) calloc (ntilebins, sizeof(int));
      }
    }
 
    /* **************************************************************** */
    /* check if this tile was cached; if so, just copy it out */
    if ((infptr->Fptr)->tilerow)  {
      /* calculate the column bin of the compressed tile */
      tilecol = (nrow - 1) % ((long)(((infptr->Fptr)->znaxis[0] - 1) / ((infptr->Fptr)->tilesize[0])) + 1);

      if (nrow == (infptr->Fptr)->tilerow[tilecol] && datatype == (infptr->Fptr)->tiletype[tilecol] ) {

         memcpy(buffer, ((infptr->Fptr)->tiledata)[tilecol], (infptr->Fptr)->tiledatasize[tilecol]);
	 
	 if (nullcheck == 2)
             memcpy(bnullarray, (infptr->Fptr)->tilenullarray[tilecol], tilelen);

         *anynul = (infptr->Fptr)->tileanynull[tilecol];

         return(*status);
       }
    }

    /* **************************************************************** */
    /* get length of the compressed byte stream */
    ffgdesll (infptr, (infptr->Fptr)->cn_compressed, nrow, &nelemll, &offset, 
            status);

    /* EOF error here indicates that this tile has not yet been written */
    if (*status == END_OF_FILE)
           return(*status = NO_COMPRESSED_TILE);
      
    /* **************************************************************** */
    if (nelemll == 0)  /* special case: tile was not compressed normally */
    {
        if ((infptr->Fptr)->cn_uncompressed >= 1 ) {

	    /* This option of writing the uncompressed floating point data */
	    /* to the tile compressed file was used until about May 2011. */
	    /* This was replaced by the more efficient option of gzipping the */
	    /* floating point data before writing it to the tile-compressed file */
	    
            /* no compressed data, so simply read the uncompressed data */
            /* directly from the UNCOMPRESSED_DATA column */   
            ffgdesll (infptr, (infptr->Fptr)->cn_uncompressed, nrow, &nelemll,
               &offset, status);

            if (nelemll == 0 && offset == 0)  /* this should never happen */
	        return (*status = NO_COMPRESSED_TILE);

            if (nullcheck <= 1) { /* set any null values in the array = nulval */
                fits_read_col(infptr, datatype, (infptr->Fptr)->cn_uncompressed,
                  nrow, 1, (long) nelemll, nulval, buffer, anynul, status);
            } else  { /* set the bnullarray = 1 for any null values in the array */
                fits_read_colnull(infptr, datatype, (infptr->Fptr)->cn_uncompressed,
                  nrow, 1, (long) nelemll, buffer, bnullarray, anynul, status);
            }
        } else if ((infptr->Fptr)->cn_gzip_data >= 1) {

            /* This is the newer option, that was introduced in May 2011 */
            /* floating point data was not quantized,  so read the losslessly */
	    /* compressed data from the GZIP_COMPRESSED_DATA column */   

            ffgdesll (infptr, (infptr->Fptr)->cn_gzip_data, nrow, &nelemll,
               &offset, status);

            if (nelemll == 0 && offset == 0) /* this should never happen */
	        return (*status = NO_COMPRESSED_TILE);

	    /* allocate memory for the compressed tile of data */
            cbuf = (unsigned char *) malloc ((long) nelemll);  
            if (cbuf == NULL) {
	        ffpmsg("error allocating memory for gzipped tile (imcomp_decompress_tile)");
	        return (*status = MEMORY_ALLOCATION);
            }

            /* read array of compressed bytes */
            if (fits_read_col(infptr, TBYTE, (infptr->Fptr)->cn_gzip_data, nrow,
                 1, (long) nelemll, &charnull, cbuf, NULL, status) > 0) {
                ffpmsg("error reading compressed byte stream from binary table");
	        free (cbuf);
                return (*status);
            }

            /* size of the returned (uncompressed) data buffer, in bytes */
            if ((infptr->Fptr)->zbitpix == FLOAT_IMG) {
	         idatalen = tilelen * sizeof(float);
            } else if ((infptr->Fptr)->zbitpix == DOUBLE_IMG) {
	         idatalen = tilelen * sizeof(double);
            } else {
                /* this should never happen! */
                ffpmsg("incompatible data type in gzipped floating-point tile-compressed image");
                free (cbuf);
                return (*status = DATA_DECOMPRESSION_ERR);
            }

            if (datatype == TDOUBLE && (infptr->Fptr)->zbitpix == FLOAT_IMG) {  
                /*  have to allocat a temporary buffer for the uncompressed data in the */
                /*  case where a gzipped "float" tile is returned as a "double" array   */
                tempfloat = (float*) malloc (idatalen); 

                if (tempfloat == NULL) {
	            ffpmsg("Memory allocation failure for tempfloat. (imcomp_decompress_tile)");
                    free (cbuf);
	            return (*status = MEMORY_ALLOCATION);
                }

                /* uncompress the data into temp buffer */
                if (uncompress2mem_from_mem ((char *)cbuf, (long) nelemll,
                     (char **) &tempfloat, &idatalen, NULL, &tilebytesize, status)) {
                    ffpmsg("failed to gunzip the image tile");
                    free (tempfloat);
                    free (cbuf);
                    return (*status);
                }
            } else {

                /* uncompress the data directly into the output buffer in all other cases */
                if (uncompress2mem_from_mem ((char *)cbuf, (long) nelemll,
                  (char **) &buffer, &idatalen, NULL, &tilebytesize, status)) {
                    ffpmsg("failed to gunzip the image tile");
                    free (cbuf);
                    return (*status);
                }
            }

            free(cbuf);

            /* do byte swapping and null value substitution for the tile of pixels */
            if (tilebytesize == 4 * tilelen) {  /* float pixels */

#if BYTESWAPPED
                if (tempfloat)
                    ffswap4((int *) tempfloat, tilelen);
                else
                    ffswap4((int *) buffer, tilelen);
#endif
               if (datatype == TFLOAT) {
                  if (nulval) {
		    fnulval = *(float *) nulval;
  		  }

                  fffr4r4((float *) buffer, (long) tilelen, 1., 0., nullcheck,   
                        fnulval, bnullarray, anynul,
                        (float *) buffer, status);
                } else if (datatype == TDOUBLE) {
                  if (nulval) {
		    dnulval = *(double *) nulval;
		  }

                  /* note that the R*4 data are in the tempfloat array in this case */
                  fffr4r8((float *) tempfloat, (long) tilelen, 1., 0., nullcheck,   
                   dnulval, bnullarray, anynul,
                    (double *) buffer, status);            
                  free(tempfloat);

                } else {
                  ffpmsg("implicit data type conversion is not supported for gzipped image tiles");
                  return (*status = DATA_DECOMPRESSION_ERR);
                }
            } else if (tilebytesize == 8 * tilelen) { /* double pixels */

#if BYTESWAPPED
                ffswap8((double *) buffer, tilelen);
#endif
                if (datatype == TFLOAT) {
                  if (nulval) {
		    fnulval = *(float *) nulval;
  		  }

                  fffr8r4((double *) buffer, (long) tilelen, 1., 0., nullcheck,   
                        fnulval, bnullarray, anynul,
                        (float *) buffer, status);
                } else if (datatype == TDOUBLE) {
                  if (nulval) {
		    dnulval = *(double *) nulval;
		  }

                  fffr8r8((double *) buffer, (long) tilelen, 1., 0., nullcheck,   
                   dnulval, bnullarray, anynul,
                    (double *) buffer, status);            
                } else {
                  ffpmsg("implicit data type conversion is not supported in tile-compressed images");
                  return (*status = DATA_DECOMPRESSION_ERR);
                }
	    } else {
                ffpmsg("error: uncompressed tile has wrong size");
                return (*status = DATA_DECOMPRESSION_ERR);
            }

          /* end of special case of losslessly gzipping a floating-point image tile */
        } else {  /* this should never happen */
	   *status = NO_COMPRESSED_TILE;
        }

        return(*status);
    }

    /* **************************************************************** */
    /* deal with the normal case of a compressed tile of pixels */
    if (nullcheck == 2)  {
        for (ii = 0; ii < tilelen; ii++)  /* initialize the null flage array */
            bnullarray[ii] = 0;
    }

    if (anynul)
       *anynul = 0;

    /* get linear scaling and offset values, if they exist */
    actual_bzero = (infptr->Fptr)->cn_actual_bzero;
    if ((infptr->Fptr)->cn_zscale == 0) {
         /* set default scaling, if scaling is not defined */
         bscale = 1.;
         bzero = 0.;
    } else if ((infptr->Fptr)->cn_zscale == -1) {
        bscale = (infptr->Fptr)->zscale;
        bzero  = (infptr->Fptr)->zzero;
    } else {
        /* read the linear scale and offset values for this row */
	ffgcvd (infptr, (infptr->Fptr)->cn_zscale, nrow, 1, 1, 0.,
				&bscale, NULL, status);
	ffgcvd (infptr, (infptr->Fptr)->cn_zzero, nrow, 1, 1, 0.,
				&bzero, NULL, status);
        if (*status > 0)
        {
          ffpmsg("error reading scaling factor and offset for compressed tile");
          return (*status);
        }

        /* test if floating-point FITS image also has non-default BSCALE and  */
	/* BZERO keywords.  If so, we have to combine the 2 linear scaling factors. */
	
	if ( ((infptr->Fptr)->zbitpix == FLOAT_IMG || 
	      (infptr->Fptr)->zbitpix == DOUBLE_IMG )
	    &&  
	      ((infptr->Fptr)->cn_bscale != 1.0 ||
	       (infptr->Fptr)->cn_bzero  != 0.0 )    ) 
	    {
	       bscale = bscale * (infptr->Fptr)->cn_bscale;
	       bzero  = bzero  * (infptr->Fptr)->cn_bscale + (infptr->Fptr)->cn_bzero;
	    }
    }

    if (bscale == 1.0 && bzero == 0.0 ) {
      /* if no other scaling has been specified, try using the values
         given by the BSCALE and BZERO keywords, if any */

        bscale = (infptr->Fptr)->cn_bscale;
        bzero  = (infptr->Fptr)->cn_bzero;
    }

    /* ************************************************************* */
    /* get the value used to represent nulls in the int array */
    if ((infptr->Fptr)->cn_zblank == 0) {
        nullcheck = 0;  /* no null value; don't check for nulls */
    } else if ((infptr->Fptr)->cn_zblank == -1) {
        tnull = (infptr->Fptr)->zblank;  /* use the the ZBLANK keyword */
    } else {
        /* read the null value for this row */
	ffgcvk (infptr, (infptr->Fptr)->cn_zblank, nrow, 1, 1, 0,
				&tnull, NULL, status);
        if (*status > 0) {
            ffpmsg("error reading null value for compressed tile");
            return (*status);
        }
    }

    /* ************************************************************* */
    /* allocate memory for the uncompressed array of tile integers */
    /* The size depends on the datatype and the compression type. */
    
    if ((infptr->Fptr)->compress_type == HCOMPRESS_1 &&
          ((infptr->Fptr)->zbitpix != BYTE_IMG &&
	   (infptr->Fptr)->zbitpix != SHORT_IMG) ) {

           idatalen = tilelen * sizeof(LONGLONG);  /* 8 bytes per pixel */

    } else if ( (infptr->Fptr)->compress_type == RICE_1 &&
               (infptr->Fptr)->zbitpix == BYTE_IMG && 
	       (infptr->Fptr)->rice_bytepix == 1) {

           idatalen = tilelen * sizeof(char); /* 1 byte per pixel */
    } else if ( ( (infptr->Fptr)->compress_type == GZIP_1  ||
                  (infptr->Fptr)->compress_type == GZIP_2  ||
                  (infptr->Fptr)->compress_type == BZIP2_1 ) &&
               (infptr->Fptr)->zbitpix == BYTE_IMG ) {

           idatalen = tilelen * sizeof(char); /* 1 byte per pixel */
    } else if ( (infptr->Fptr)->compress_type == RICE_1 &&
               (infptr->Fptr)->zbitpix == SHORT_IMG && 
	       (infptr->Fptr)->rice_bytepix == 2) {

           idatalen = tilelen * sizeof(short); /* 2 bytes per pixel */
    } else if ( ( (infptr->Fptr)->compress_type == GZIP_1  ||
                  (infptr->Fptr)->compress_type == GZIP_2  ||
                  (infptr->Fptr)->compress_type == BZIP2_1 )  &&
               (infptr->Fptr)->zbitpix == SHORT_IMG ) {

           idatalen = tilelen * sizeof(short); /* 2 bytes per pixel */
    } else if ( ( (infptr->Fptr)->compress_type == GZIP_1  ||
                  (infptr->Fptr)->compress_type == GZIP_2  ||
                  (infptr->Fptr)->compress_type == BZIP2_1 ) &&
               (infptr->Fptr)->zbitpix == DOUBLE_IMG ) {

           idatalen = tilelen * sizeof(double); /* 8 bytes per pixel  */
    } else {
           idatalen = tilelen * sizeof(int);  /* all other cases have int pixels */
    }

    idata = (int*) malloc (idatalen); 
    if (idata == NULL) {
	    ffpmsg("Memory allocation failure for idata. (imcomp_decompress_tile)");
	    return (*status = MEMORY_ALLOCATION);
    }

    /* ************************************************************* */
    /* allocate memory for the compressed bytes */

    if ((infptr->Fptr)->compress_type == PLIO_1) {
        cbuf = (unsigned char *) malloc ((long) nelemll * sizeof (short));
    } else {
        cbuf = (unsigned char *) malloc ((long) nelemll);
    }
    if (cbuf == NULL) {
	ffpmsg("Out of memory for cbuf. (imcomp_decompress_tile)");
        free(idata);
	return (*status = MEMORY_ALLOCATION);
    }
    
    /* ************************************************************* */
    /* read the compressed bytes from the FITS file */

    if ((infptr->Fptr)->compress_type == PLIO_1) {
        fits_read_col(infptr, TSHORT, (infptr->Fptr)->cn_compressed, nrow,
             1, (long) nelemll, &snull, (short *) cbuf, NULL, status);
    } else {
       fits_read_col(infptr, TBYTE, (infptr->Fptr)->cn_compressed, nrow,
             1, (long) nelemll, &charnull, cbuf, NULL, status);
    }

    if (*status > 0) {
        ffpmsg("error reading compressed byte stream from binary table");
	free (cbuf);
        free(idata);
        return (*status);
    }

    /* ************************************************************* */
    /*  call the algorithm-specific code to uncompress the tile */

    if ((infptr->Fptr)->compress_type == RICE_1) {

        blocksize = (infptr->Fptr)->rice_blocksize;

        if ((infptr->Fptr)->rice_bytepix == 1 ) {
            *status = fits_rdecomp_byte (cbuf, (long) nelemll, (unsigned char *)idata,
                        tilelen, blocksize);
            tiledatatype = TBYTE;
        } else if ((infptr->Fptr)->rice_bytepix == 2 ) {
            *status = fits_rdecomp_short (cbuf, (long) nelemll, (unsigned short *)idata,
                        tilelen, blocksize);
            tiledatatype = TSHORT;
        } else {
            *status = fits_rdecomp (cbuf, (long) nelemll, (unsigned int *)idata,
                         tilelen, blocksize);
            tiledatatype = TINT;
        }

    /* ************************************************************* */
    } else if ((infptr->Fptr)->compress_type == HCOMPRESS_1)  {

        smooth = (infptr->Fptr)->hcomp_smooth;

        if ( ((infptr->Fptr)->zbitpix == BYTE_IMG || (infptr->Fptr)->zbitpix == SHORT_IMG)) {
            *status = fits_hdecompress(cbuf, smooth, idata, &nx, &ny,
	        &scale, status);
        } else {  /* zbitpix = LONG_IMG (32) */
            /* idata must have been allocated twice as large for this to work */
            *status = fits_hdecompress64(cbuf, smooth, (LONGLONG *) idata, &nx, &ny,
	        &scale, status);
        }       

        tiledatatype = TINT;

    /* ************************************************************* */
    } else if ((infptr->Fptr)->compress_type == PLIO_1) {

        pl_l2pi ((short *) cbuf, 1, idata, tilelen);  /* uncompress the data */
        tiledatatype = TINT;

    /* ************************************************************* */
    } else if ( ((infptr->Fptr)->compress_type == GZIP_1) ||
                ((infptr->Fptr)->compress_type == GZIP_2) ) {

        uncompress2mem_from_mem ((char *)cbuf, (long) nelemll,
             (char **) &idata, &idatalen, realloc, &tilebytesize, status);

        /* determine the data type of the uncompressed array, and */
	/*  do byte unshuffling and unswapping if needed */
	if (tilebytesize == (size_t) (tilelen * 2)) {
	    /* this is a short I*2 array */
            tiledatatype = TSHORT;

            if ( (infptr->Fptr)->compress_type == GZIP_2 )
		    fits_unshuffle_2bytes((char *) idata, tilelen, status);

#if BYTESWAPPED
            ffswap2((short *) idata, tilelen);
#endif

	} else if (tilebytesize == (size_t) (tilelen * 4)) {
	    /* this is a int I*4 array (or maybe R*4) */
            tiledatatype = TINT;

            if ( (infptr->Fptr)->compress_type == GZIP_2 )
		    fits_unshuffle_4bytes((char *) idata, tilelen, status);

#if BYTESWAPPED
            ffswap4(idata, tilelen);
#endif

	} else if (tilebytesize == (size_t) (tilelen * 8)) {
	    /* this is a R*8 double array */
            tiledatatype = TDOUBLE;

            if ( (infptr->Fptr)->compress_type == GZIP_2 )
		    fits_unshuffle_8bytes((char *) idata, tilelen, status);
#if BYTESWAPPED
            ffswap8((double *) idata, tilelen);
#endif

        } else if (tilebytesize == (size_t) tilelen) {
	    
	    /* this is an unsigned char I*1 array */
            tiledatatype = TBYTE;

        } else {
            ffpmsg("error: uncompressed tile has wrong size");
            free(idata);
            return (*status = DATA_DECOMPRESSION_ERR);
        }

    /* ************************************************************* */
    } else if ((infptr->Fptr)->compress_type == BZIP2_1) {

/*  BZIP2 is not supported in the public release; this is only for test purposes 

        if (BZ2_bzBuffToBuffDecompress ((char *) idata, &idatalen, 
		(char *)cbuf, (unsigned int) nelemll, 0, 0) )
*/
        {
            ffpmsg("bzip2 decompression error");
            free(idata);
            free (cbuf);
            return (*status = DATA_DECOMPRESSION_ERR);
        }

        if ((infptr->Fptr)->zbitpix == BYTE_IMG) {
	     tiledatatype = TBYTE;
        } else if ((infptr->Fptr)->zbitpix == SHORT_IMG) {
  	     tiledatatype = TSHORT;
#if BYTESWAPPED
            ffswap2((short *) idata, tilelen);
#endif
	} else {
  	     tiledatatype = TINT;
#if BYTESWAPPED
            ffswap4(idata, tilelen);
#endif
	}

    /* ************************************************************* */
    } else {
        ffpmsg("unknown compression algorithm");
        free(idata);
        return (*status = DATA_DECOMPRESSION_ERR);
    }

    free(cbuf);
    if (*status)  {  /* error uncompressing the tile */
            free(idata);
            return (*status);
    }

    /* ************************************************************* */
    /* copy the uncompressed tile data to the output buffer, doing */
    /* null checking, datatype conversion and linear scaling, if necessary */

    if (nulval == 0)
         nulval = &dummy;  /* set address to dummy value */

    if (datatype == TSHORT)
    {
        pixlen = sizeof(short);

	if ((infptr->Fptr)->quantize_level == NO_QUANTIZE) {
	 /* the floating point pixels were losselessly compressed with GZIP */
	 /* Just have to copy the values to the output array */
	 
          if (tiledatatype == TINT) {
              fffr4i2((float *) idata, tilelen, bscale, bzero, nullcheck,   
                *(short *) nulval, bnullarray, anynul,
                (short *) buffer, status);
          } else {
              fffr8i2((double *) idata, tilelen, bscale, bzero, nullcheck,   
                *(short *) nulval, bnullarray, anynul,
                (short *) buffer, status);
          }
        } else if (tiledatatype == TINT) {
          if ((infptr->Fptr)->compress_type == PLIO_1 && actual_bzero == 32768.) {
	    /* special case where unsigned 16-bit integers have been */
	    /* offset by +32768 when using PLIO */
            fffi4i2(idata, tilelen, bscale, bzero - 32768., nullcheck, tnull,
             *(short *) nulval, bnullarray, anynul,
            (short *) buffer, status);
          } else {
            fffi4i2(idata, tilelen, bscale, bzero, nullcheck, tnull,
             *(short *) nulval, bnullarray, anynul,
            (short *) buffer, status);

            /*
	       Hcompress is a special case:  ignore any numerical overflow
	       errors that may have occurred during the integer*4 to integer*2
	       convertion.  Overflows can happen when a lossy Hcompress algorithm
	       is invoked (with a non-zero scale factor).  The fffi4i2 routine
	       clips the returned values to be within the legal I*2 range, so
	       all we need to is to reset the error status to zero.
	    */
	       
             if ((infptr->Fptr)->compress_type == HCOMPRESS_1) {
                if ((*status == NUM_OVERFLOW) || (*status == OVERFLOW_ERR))
                        *status = 0;
             }
          }
        } else if (tiledatatype == TSHORT) {
          fffi2i2((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull,
           *(short *) nulval, bnullarray, anynul,
          (short *) buffer, status);
        } else if (tiledatatype == TBYTE) {
          fffi1i2((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull,
           *(short *) nulval, bnullarray, anynul,
          (short *) buffer, status);
        }
    }
    else if (datatype == TINT)
    {
        pixlen = sizeof(int);

	if ((infptr->Fptr)->quantize_level == NO_QUANTIZE) {
	 /* the floating point pixels were losselessly compressed with GZIP */
	 /* Just have to copy the values to the output array */
	 
          if (tiledatatype == TINT) {
              fffr4int((float *) idata, tilelen, bscale, bzero, nullcheck,   
                *(int *) nulval, bnullarray, anynul,
                (int *) buffer, status);
          } else {
              fffr8int((double *) idata, tilelen, bscale, bzero, nullcheck,   
                *(int *) nulval, bnullarray, anynul,
                (int *) buffer, status);
          }
        } else if (tiledatatype == TINT)
          if ((infptr->Fptr)->compress_type == PLIO_1 && actual_bzero == 32768.) {
	    /* special case where unsigned 16-bit integers have been */
	    /* offset by +32768 when using PLIO */
            fffi4int(idata, (long) tilelen, bscale, bzero - 32768., nullcheck, tnull,
             *(int *) nulval, bnullarray, anynul,
            (int *) buffer, status);
          } else {
            fffi4int(idata, (long) tilelen, bscale, bzero, nullcheck, tnull,
             *(int *) nulval, bnullarray, anynul,
            (int *) buffer, status);
          } 
        else if (tiledatatype == TSHORT)
          fffi2int((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull,
           *(int *) nulval, bnullarray, anynul,
           (int *) buffer, status);
        else if (tiledatatype == TBYTE)
          fffi1int((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull,
           *(int *) nulval, bnullarray, anynul,
           (int *) buffer, status);
    }
    else if (datatype == TLONG)
    {
        pixlen = sizeof(long);

	if ((infptr->Fptr)->quantize_level == NO_QUANTIZE) {
	 /* the floating point pixels were losselessly compressed with GZIP */
	 /* Just have to copy the values to the output array */
	 
          if (tiledatatype == TINT) {
              fffr4i4((float *) idata, tilelen, bscale, bzero, nullcheck,   
                *(long *) nulval, bnullarray, anynul,
                (long *) buffer, status);
          } else {
              fffr8i4((double *) idata, tilelen, bscale, bzero, nullcheck,   
                *(long *) nulval, bnullarray, anynul,
                (long *) buffer, status);
          }
        } else if (tiledatatype == TINT)
          if ((infptr->Fptr)->compress_type == PLIO_1 && actual_bzero == 32768.) {
	    /* special case where unsigned 16-bit integers have been */
	    /* offset by +32768 when using PLIO */
            fffi4i4(idata, tilelen, bscale, bzero - 32768., nullcheck, tnull,
             *(long *) nulval, bnullarray, anynul,
             (long *) buffer, status);
          } else {
            fffi4i4(idata, tilelen, bscale, bzero, nullcheck, tnull,
             *(long *) nulval, bnullarray, anynul,
              (long *) buffer, status);
          }
        else if (tiledatatype == TSHORT)
          fffi2i4((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull,
           *(long *) nulval, bnullarray, anynul,
            (long *) buffer, status);
        else if (tiledatatype == TBYTE)
          fffi1i4((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull,
           *(long *) nulval, bnullarray, anynul,
            (long *) buffer, status);
    }
    else if (datatype == TFLOAT)
    {
        pixlen = sizeof(float);
        if (nulval) {
	      fnulval = *(float *) nulval;
	}
 
	if ((infptr->Fptr)->quantize_level == NO_QUANTIZE) {
	 /* the floating point pixels were losselessly compressed with GZIP */
	 /* Just have to copy the values to the output array */
	 
          if (tiledatatype == TINT) {
              fffr4r4((float *) idata, tilelen, bscale, bzero, nullcheck,   
                fnulval, bnullarray, anynul,
                (float *) buffer, status);
          } else {
              fffr8r4((double *) idata, tilelen, bscale, bzero, nullcheck,   
                fnulval, bnullarray, anynul,
                (float *) buffer, status);
          }
	
        } else if ((infptr->Fptr)->quantize_method == SUBTRACTIVE_DITHER_1 ||
	           (infptr->Fptr)->quantize_method == SUBTRACTIVE_DITHER_2) {

         /* use the new dithering algorithm (introduced in July 2009) */

         if (tiledatatype == TINT)
          unquantize_i4r4(nrow + (infptr->Fptr)->dither_seed - 1, idata, 
	   tilelen, bscale, bzero, (infptr->Fptr)->quantize_method, nullcheck, tnull,
           fnulval, bnullarray, anynul,
            (float *) buffer, status);
         else if (tiledatatype == TSHORT)
          unquantize_i2r4(nrow + (infptr->Fptr)->dither_seed - 1, (short *)idata, 
	   tilelen, bscale, bzero, (infptr->Fptr)->quantize_method, nullcheck, (short) tnull,
           fnulval, bnullarray, anynul,
            (float *) buffer, status);
         else if (tiledatatype == TBYTE)
          unquantize_i1r4(nrow + (infptr->Fptr)->dither_seed - 1, (unsigned char *)idata, 
	   tilelen, bscale, bzero, (infptr->Fptr)->quantize_method, nullcheck, (unsigned char) tnull,
           fnulval, bnullarray, anynul,
            (float *) buffer, status);

        } else {  /* use the old "round to nearest level" quantization algorithm */

         if (tiledatatype == TINT)
          if ((infptr->Fptr)->compress_type == PLIO_1 && actual_bzero == 32768.) {
	    /* special case where unsigned 16-bit integers have been */
	    /* offset by +32768 when using PLIO */
            fffi4r4(idata, tilelen, bscale, bzero - 32768., nullcheck, tnull,
             fnulval, bnullarray, anynul,
             (float *) buffer, status);
          } else {
            fffi4r4(idata, tilelen, bscale, bzero, nullcheck, tnull,  
             fnulval, bnullarray, anynul,
              (float *) buffer, status);
          }
         else if (tiledatatype == TSHORT)
          fffi2r4((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull,  
           fnulval, bnullarray, anynul,
            (float *) buffer, status);
         else if (tiledatatype == TBYTE)
          fffi1r4((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull,
           fnulval, bnullarray, anynul,
            (float *) buffer, status);
	}
    }
    else if (datatype == TDOUBLE)
    {
        pixlen = sizeof(double);
        if (nulval) {
	     dnulval = *(double *) nulval;
	}

	if ((infptr->Fptr)->quantize_level == NO_QUANTIZE) {
	 /* the floating point pixels were losselessly compressed with GZIP */
	 /* Just have to copy the values to the output array */

          if (tiledatatype == TINT) {
              fffr4r8((float *) idata, tilelen, bscale, bzero, nullcheck,   
                dnulval, bnullarray, anynul,
                (double *) buffer, status);
          } else {
              fffr8r8((double *) idata, tilelen, bscale, bzero, nullcheck,   
                dnulval, bnullarray, anynul,
                (double *) buffer, status);
          }
	
	} else if ((infptr->Fptr)->quantize_method == SUBTRACTIVE_DITHER_1 ||
	           (infptr->Fptr)->quantize_method == SUBTRACTIVE_DITHER_2) {

         /* use the new dithering algorithm (introduced in July 2009) */
         if (tiledatatype == TINT)
          unquantize_i4r8(nrow + (infptr->Fptr)->dither_seed - 1, idata,
	   tilelen, bscale, bzero, (infptr->Fptr)->quantize_method, nullcheck, tnull,
           dnulval, bnullarray, anynul,
            (double *) buffer, status);
         else if (tiledatatype == TSHORT)
          unquantize_i2r8(nrow + (infptr->Fptr)->dither_seed - 1, (short *)idata,
	   tilelen, bscale, bzero, (infptr->Fptr)->quantize_method, nullcheck, (short) tnull,
           dnulval, bnullarray, anynul,
            (double *) buffer, status);
         else if (tiledatatype == TBYTE)
          unquantize_i1r8(nrow + (infptr->Fptr)->dither_seed - 1, (unsigned char *)idata,
	   tilelen, bscale, bzero, (infptr->Fptr)->quantize_method, nullcheck, (unsigned char) tnull,
           dnulval, bnullarray, anynul,
            (double *) buffer, status);

        } else {  /* use the old "round to nearest level" quantization algorithm */

         if (tiledatatype == TINT) {
          if ((infptr->Fptr)->compress_type == PLIO_1 && actual_bzero == 32768.) {
	    /* special case where unsigned 16-bit integers have been */
	    /* offset by +32768 when using PLIO */
            fffi4r8(idata, tilelen, bscale, bzero - 32768., nullcheck, tnull,
             dnulval, bnullarray, anynul,
             (double *) buffer, status);
          } else {
            fffi4r8(idata, tilelen, bscale, bzero, nullcheck, tnull,
             dnulval, bnullarray, anynul,
              (double *) buffer, status);
          }
         } else if (tiledatatype == TSHORT) {
          fffi2r8((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull,
           dnulval, bnullarray, anynul,
            (double *) buffer, status);
         } else if (tiledatatype == TBYTE)
          fffi1r8((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull,
           dnulval, bnullarray, anynul,
            (double *) buffer, status);
	}
    }
    else if (datatype == TBYTE)
    {
        pixlen = sizeof(char);
        if (tiledatatype == TINT)
          fffi4i1(idata, tilelen, bscale, bzero, nullcheck, tnull,
           *(unsigned char *) nulval, bnullarray, anynul,
            (unsigned char *) buffer, status);
        else if (tiledatatype == TSHORT)
          fffi2i1((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull,
           *(unsigned char *) nulval, bnullarray, anynul,
            (unsigned char *) buffer, status);
        else if (tiledatatype == TBYTE)
          fffi1i1((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull,
           *(unsigned char *) nulval, bnullarray, anynul,
            (unsigned char *) buffer, status);
    }
    else if (datatype == TSBYTE)
    {
        pixlen = sizeof(char);
        if (tiledatatype == TINT)
          fffi4s1(idata, tilelen, bscale, bzero, nullcheck, tnull,
           *(signed char *) nulval, bnullarray, anynul,
            (signed char *) buffer, status);
        else if (tiledatatype == TSHORT)
          fffi2s1((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull,
           *(signed char *) nulval, bnullarray, anynul,
            (signed char *) buffer, status);
        else if (tiledatatype == TBYTE)
          fffi1s1((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull,
           *(signed char *) nulval, bnullarray, anynul,
            (signed char *) buffer, status);
    }
    else if (datatype == TUSHORT)
    {
        pixlen = sizeof(short);

	if ((infptr->Fptr)->quantize_level == NO_QUANTIZE) {
	 /* the floating point pixels were losselessly compressed with GZIP */
	 /* Just have to copy the values to the output array */
	 
          if (tiledatatype == TINT) {
              fffr4u2((float *) idata, tilelen, bscale, bzero, nullcheck,   
                *(unsigned short *) nulval, bnullarray, anynul,
                (unsigned short *) buffer, status);
          } else {
              fffr8u2((double *) idata, tilelen, bscale, bzero, nullcheck,   
                *(unsigned short *) nulval, bnullarray, anynul,
                (unsigned short *) buffer, status);
          }
        } else if (tiledatatype == TINT)
          if ((infptr->Fptr)->compress_type == PLIO_1 && actual_bzero == 32768.) {
	    /* special case where unsigned 16-bit integers have been */
	    /* offset by +32768 when using PLIO */
            fffi4u2(idata, tilelen, bscale, bzero - 32768., nullcheck, tnull,
             *(unsigned short *) nulval, bnullarray, anynul,
            (unsigned short *) buffer, status);
          } else {
            fffi4u2(idata, tilelen, bscale, bzero, nullcheck, tnull,
             *(unsigned short *) nulval, bnullarray, anynul,
              (unsigned short *) buffer, status);
          }
        else if (tiledatatype == TSHORT)
          fffi2u2((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull,
           *(unsigned short *) nulval, bnullarray, anynul,
            (unsigned short *) buffer, status);
        else if (tiledatatype == TBYTE)
          fffi1u2((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull,
           *(unsigned short *) nulval, bnullarray, anynul,
            (unsigned short *) buffer, status);
    }
    else if (datatype == TUINT)
    {
        pixlen = sizeof(int);

	if ((infptr->Fptr)->quantize_level == NO_QUANTIZE) {
	 /* the floating point pixels were losselessly compressed with GZIP */
	 /* Just have to copy the values to the output array */
	 
          if (tiledatatype == TINT) {
              fffr4uint((float *) idata, tilelen, bscale, bzero, nullcheck,   
                *(unsigned int *) nulval, bnullarray, anynul,
                (unsigned int *) buffer, status);
          } else {
              fffr8uint((double *) idata, tilelen, bscale, bzero, nullcheck,   
                *(unsigned int *) nulval, bnullarray, anynul,
                (unsigned int *) buffer, status);
          }
        } else
         if (tiledatatype == TINT)
          if ((infptr->Fptr)->compress_type == PLIO_1 && actual_bzero == 32768.) {
	    /* special case where unsigned 16-bit integers have been */
	    /* offset by +32768 when using PLIO */
            fffi4uint(idata, tilelen, bscale, bzero - 32768., nullcheck, tnull,
             *(unsigned int *) nulval, bnullarray, anynul,
              (unsigned int *) buffer, status);
          } else {
            fffi4uint(idata, tilelen, bscale, bzero, nullcheck, tnull,
             *(unsigned int *) nulval, bnullarray, anynul,
              (unsigned int *) buffer, status);
          }
        else if (tiledatatype == TSHORT)
          fffi2uint((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull,
           *(unsigned int *) nulval, bnullarray, anynul,
            (unsigned int *) buffer, status);
        else if (tiledatatype == TBYTE)
          fffi1uint((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull,
           *(unsigned int *) nulval, bnullarray, anynul,
            (unsigned int *) buffer, status);
    }
    else if (datatype == TULONG)
    {
        pixlen = sizeof(long);

	if ((infptr->Fptr)->quantize_level == NO_QUANTIZE) {
	 /* the floating point pixels were losselessly compressed with GZIP */
	 /* Just have to copy the values to the output array */
	 
          if (tiledatatype == TINT) {
              fffr4u4((float *) idata, tilelen, bscale, bzero, nullcheck,   
                *(unsigned long *) nulval, bnullarray, anynul,
                (unsigned long *) buffer, status);
          } else {
              fffr8u4((double *) idata, tilelen, bscale, bzero, nullcheck,   
                *(unsigned long *) nulval, bnullarray, anynul,
                (unsigned long *) buffer, status);
          }
        } else if (tiledatatype == TINT)
          if ((infptr->Fptr)->compress_type == PLIO_1 && actual_bzero == 32768.) {
	    /* special case where unsigned 16-bit integers have been */
	    /* offset by +32768 when using PLIO */
            fffi4u4(idata, tilelen, bscale, bzero - 32768., nullcheck, tnull,
             *(unsigned long *) nulval, bnullarray, anynul,
              (unsigned long *) buffer, status);
          } else {
            fffi4u4(idata, tilelen, bscale, bzero, nullcheck, tnull,
             *(unsigned long *) nulval, bnullarray, anynul, 
              (unsigned long *) buffer, status);
          }
        else if (tiledatatype == TSHORT)
          fffi2u4((short *)idata, tilelen, bscale, bzero, nullcheck, (short) tnull,
           *(unsigned long *) nulval, bnullarray, anynul, 
            (unsigned long *) buffer, status);
        else if (tiledatatype == TBYTE)
          fffi1u4((unsigned char *)idata, tilelen, bscale, bzero, nullcheck, (unsigned char) tnull,
           *(unsigned long *) nulval, bnullarray, anynul, 
            (unsigned long *) buffer, status);
    }
    else
         *status = BAD_DATATYPE;

    free(idata);  /* don't need the uncompressed tile any more */

    /* **************************************************************** */
    /* cache the tile, in case the application wants it again  */

    /*   Don't cache the tile if tile is a single row of the image; 
         it is less likely that the cache will be used in this cases,
	 so it is not worth the time and the memory overheads.
    */
    
    if ((infptr->Fptr)->tilerow)  {  /* make sure cache has been allocated */
     if ((infptr->Fptr)->znaxis[0]   != (infptr->Fptr)->tilesize[0] ||
        (infptr->Fptr)->tilesize[1] != 1 )
     {
      tilesize = pixlen * tilelen;

      /* check that tile size/type has not changed */
      if (tilesize != (infptr->Fptr)->tiledatasize[tilecol] ||
        datatype != (infptr->Fptr)->tiletype[tilecol] )  {

        if (((infptr->Fptr)->tiledata)[tilecol]) {
            free(((infptr->Fptr)->tiledata)[tilecol]);	    
        }
	
        if (((infptr->Fptr)->tilenullarray)[tilecol]) {
            free(((infptr->Fptr)->tilenullarray)[tilecol]);
        }
	
        ((infptr->Fptr)->tilenullarray)[tilecol] = 0;
        ((infptr->Fptr)->tilerow)[tilecol] = 0;
        ((infptr->Fptr)->tiledatasize)[tilecol] = 0;
        ((infptr->Fptr)->tiletype)[tilecol] = 0;

        /* allocate new array(s) */
	((infptr->Fptr)->tiledata)[tilecol] = malloc(tilesize);

	if (((infptr->Fptr)->tiledata)[tilecol] == 0)
	   return (*status);

        if (nullcheck == 2) {  /* also need array of null pixel flags */
	    (infptr->Fptr)->tilenullarray[tilecol] = malloc(tilelen);
	    if ((infptr->Fptr)->tilenullarray[tilecol] == 0)
	        return (*status);
        }

        (infptr->Fptr)->tiledatasize[tilecol] = tilesize;
        (infptr->Fptr)->tiletype[tilecol] = datatype;
      }

      /* copy the tile array(s) into cache buffer */
      memcpy((infptr->Fptr)->tiledata[tilecol], buffer, tilesize);

      if (nullcheck == 2) {
	    if ((infptr->Fptr)->tilenullarray == 0)  {
       	      (infptr->Fptr)->tilenullarray[tilecol] = malloc(tilelen);
            }
            memcpy((infptr->Fptr)->tilenullarray[tilecol], bnullarray, tilelen);
      }

      (infptr->Fptr)->tilerow[tilecol] = nrow;
      (infptr->Fptr)->tileanynull[tilecol] = *anynul;
     }
    }
    return (*status);
}
/*--------------------------------------------------------------------------*/
int imcomp_test_overlap (
    int ndim,           /* I - number of dimension in the tile and image */
    long *tfpixel,      /* I - first pixel number in each dim. of the tile */
    long *tlpixel,      /* I - last pixel number in each dim. of the tile */
    long *fpixel,       /* I - first pixel number in each dim. of the image */
    long *lpixel,       /* I - last pixel number in each dim. of the image */
    long *ininc,        /* I - increment to be applied in each image dimen. */
    int *status)

/* 
  test if there are any intersecting pixels between this tile and the section
  of the image defined by fixel, lpixel, ininc. 
*/
{
    long imgdim[MAX_COMPRESS_DIM]; /* product of preceding dimensions in the */
                                   /* output image, allowing for inc factor */
    long tiledim[MAX_COMPRESS_DIM]; /* product of preceding dimensions in the */
                                 /* tile, array;  inc factor is not relevant */
    long imgfpix[MAX_COMPRESS_DIM]; /* 1st img pix overlapping tile: 0 base, */
                                    /*  allowing for inc factor */
    long imglpix[MAX_COMPRESS_DIM]; /* last img pix overlapping tile 0 base, */
                                    /*  allowing for inc factor */
    long tilefpix[MAX_COMPRESS_DIM]; /* 1st tile pix overlapping img 0 base, */
                                    /*  allowing for inc factor */
    long inc[MAX_COMPRESS_DIM]; /* local copy of input ininc */
    int ii;
    long tf, tl;

    if (*status > 0)
        return(*status);


    /* ------------------------------------------------------------ */
    /* calc amount of overlap in each dimension; if there is zero   */
    /* overlap in any dimension then just return  */
    /* ------------------------------------------------------------ */
    
    for (ii = 0; ii < ndim; ii++)
    {
        if (tlpixel[ii] < fpixel[ii] || tfpixel[ii] > lpixel[ii])
            return(0);  /* there are no overlapping pixels */

        inc[ii] = ininc[ii];

        /* calc dimensions of the output image section */
        imgdim[ii] = (lpixel[ii] - fpixel[ii]) / labs(inc[ii]) + 1;
        if (imgdim[ii] < 1) {
            *status = NEG_AXIS;
            return(0);
        }

        /* calc dimensions of the tile */
        tiledim[ii] = tlpixel[ii] - tfpixel[ii] + 1;
        if (tiledim[ii] < 1) {
            *status = NEG_AXIS;
            return(0);
        }

        if (ii > 0)
           tiledim[ii] *= tiledim[ii - 1];  /* product of dimensions */

        /* first and last pixels in image that overlap with the tile, 0 base */
        tf = tfpixel[ii] - 1;
        tl = tlpixel[ii] - 1;

        /* skip this plane if it falls in the cracks of the subsampled image */
        while ((tf-(fpixel[ii] - 1)) % labs(inc[ii]))
        {
           tf++;
           if (tf > tl)
             return(0);  /* no overlapping pixels */
        }

        while ((tl-(fpixel[ii] - 1)) % labs(inc[ii]))
        {
           tl--;
           if (tf > tl)
             return(0);  /* no overlapping pixels */
        }
        imgfpix[ii] = maxvalue((tf - fpixel[ii] +1) / labs(inc[ii]) , 0);
        imglpix[ii] = minvalue((tl - fpixel[ii] +1) / labs(inc[ii]) ,
                               imgdim[ii] - 1);

        /* first pixel in the tile that overlaps with the image (0 base) */
        tilefpix[ii] = maxvalue(fpixel[ii] - tfpixel[ii], 0);

        while ((tfpixel[ii] + tilefpix[ii] - fpixel[ii]) % labs(inc[ii]))
        {
           (tilefpix[ii])++;
           if (tilefpix[ii] >= tiledim[ii])
              return(0);  /* no overlapping pixels */
        }

        if (ii > 0)
           imgdim[ii] *= imgdim[ii - 1];  /* product of dimensions */
    }

    return(1);  /* there appears to be  intersecting pixels */
}
/*--------------------------------------------------------------------------*/
int imcomp_copy_overlap (
    char *tile,         /* I - multi dimensional array of tile pixels */
    int pixlen,         /* I - number of bytes in each tile or image pixel */
    int ndim,           /* I - number of dimension in the tile and image */
    long *tfpixel,      /* I - first pixel number in each dim. of the tile */
    long *tlpixel,      /* I - last pixel number in each dim. of the tile */
    char *bnullarray,   /* I - array of null flags; used if nullcheck = 2 */
    char *image,        /* O - multi dimensional output image */
    long *fpixel,       /* I - first pixel number in each dim. of the image */
    long *lpixel,       /* I - last pixel number in each dim. of the image */
    long *ininc,        /* I - increment to be applied in each image dimen. */
    int nullcheck,      /* I - 0, 1: do nothing; 2: set nullarray for nulls */
    char *nullarray, 
    int *status)

/* 
  copy the intersecting pixels from a decompressed tile to the output image. 
  Both the tile and the image must have the same number of dimensions. 
*/
{
    long imgdim[MAX_COMPRESS_DIM]; /* product of preceding dimensions in the */
                                   /* output image, allowing for inc factor */
    long tiledim[MAX_COMPRESS_DIM]; /* product of preceding dimensions in the */
                                 /* tile, array;  inc factor is not relevant */
    long imgfpix[MAX_COMPRESS_DIM]; /* 1st img pix overlapping tile: 0 base, */
                                    /*  allowing for inc factor */
    long imglpix[MAX_COMPRESS_DIM]; /* last img pix overlapping tile 0 base, */
                                    /*  allowing for inc factor */
    long tilefpix[MAX_COMPRESS_DIM]; /* 1st tile pix overlapping img 0 base, */
                                    /*  allowing for inc factor */
    long inc[MAX_COMPRESS_DIM]; /* local copy of input ininc */
    long i1, i2, i3, i4;   /* offset along each axis of the image */
    long it1, it2, it3, it4;
    long im1, im2, im3, im4;  /* offset to image pixel, allowing for inc */
    long ipos, tf, tl;
    long t2, t3, t4;   /* offset along each axis of the tile */
    long tilepix, imgpix, tilepixbyte, imgpixbyte;
    int ii, overlap_bytes, overlap_flags;

    if (*status > 0)
        return(*status);

    for (ii = 0; ii < MAX_COMPRESS_DIM; ii++)
    {
        /* set default values for higher dimensions */
        inc[ii] = 1;
        imgdim[ii] = 1;
        tiledim[ii] = 1;
        imgfpix[ii] = 0;
        imglpix[ii] = 0;
        tilefpix[ii] = 0;
    }

    /* ------------------------------------------------------------ */
    /* calc amount of overlap in each dimension; if there is zero   */
    /* overlap in any dimension then just return  */
    /* ------------------------------------------------------------ */
    
    for (ii = 0; ii < ndim; ii++)
    {
        if (tlpixel[ii] < fpixel[ii] || tfpixel[ii] > lpixel[ii])
            return(*status);  /* there are no overlapping pixels */

        inc[ii] = ininc[ii];

        /* calc dimensions of the output image section */
        imgdim[ii] = (lpixel[ii] - fpixel[ii]) / labs(inc[ii]) + 1;
        if (imgdim[ii] < 1)
            return(*status = NEG_AXIS);

        /* calc dimensions of the tile */
        tiledim[ii] = tlpixel[ii] - tfpixel[ii] + 1;
        if (tiledim[ii] < 1)
            return(*status = NEG_AXIS);

        if (ii > 0)
           tiledim[ii] *= tiledim[ii - 1];  /* product of dimensions */

        /* first and last pixels in image that overlap with the tile, 0 base */
        tf = tfpixel[ii] - 1;
        tl = tlpixel[ii] - 1;

        /* skip this plane if it falls in the cracks of the subsampled image */
        while ((tf-(fpixel[ii] - 1)) % labs(inc[ii]))
        {
           tf++;
           if (tf > tl)
             return(*status);  /* no overlapping pixels */
        }

        while ((tl-(fpixel[ii] - 1)) % labs(inc[ii]))
        {
           tl--;
           if (tf > tl)
             return(*status);  /* no overlapping pixels */
        }
        imgfpix[ii] = maxvalue((tf - fpixel[ii] +1) / labs(inc[ii]) , 0);
        imglpix[ii] = minvalue((tl - fpixel[ii] +1) / labs(inc[ii]) ,
                               imgdim[ii] - 1);

        /* first pixel in the tile that overlaps with the image (0 base) */
        tilefpix[ii] = maxvalue(fpixel[ii] - tfpixel[ii], 0);

        while ((tfpixel[ii] + tilefpix[ii] - fpixel[ii]) % labs(inc[ii]))
        {
           (tilefpix[ii])++;
           if (tilefpix[ii] >= tiledim[ii])
              return(*status);  /* no overlapping pixels */
        }
/*
printf("ii tfpixel, tlpixel %d %d %d \n",ii, tfpixel[ii], tlpixel[ii]);
printf("ii, tf, tl, imgfpix,imglpix, tilefpix %d %d %d %d %d %d\n",ii,
 tf,tl,imgfpix[ii], imglpix[ii],tilefpix[ii]);
*/
        if (ii > 0)
           imgdim[ii] *= imgdim[ii - 1];  /* product of dimensions */
    }

    /* ---------------------------------------------------------------- */
    /* calc number of pixels in each row (first dimension) that overlap */
    /* multiply by pixlen to get number of bytes to copy in each loop   */
    /* ---------------------------------------------------------------- */

    if (inc[0] != 1)
       overlap_flags = 1;  /* can only copy 1 pixel at a time */
    else
       overlap_flags = imglpix[0] - imgfpix[0] + 1;  /* can copy whole row */

    overlap_bytes = overlap_flags * pixlen;

    /* support up to 5 dimensions for now */
    for (i4 = 0, it4=0; i4 <= imglpix[4] - imgfpix[4]; i4++, it4++)
    {
     /* increment plane if it falls in the cracks of the subsampled image */
     while (ndim > 4 &&  (tfpixel[4] + tilefpix[4] - fpixel[4] + it4)
                          % labs(inc[4]) != 0)
        it4++;

       /* offset to start of hypercube */
       if (inc[4] > 0)
          im4 = (i4 + imgfpix[4]) * imgdim[3];
       else
          im4 = imgdim[4] - (i4 + 1 + imgfpix[4]) * imgdim[3];

      t4 = (tilefpix[4] + it4) * tiledim[3];
      for (i3 = 0, it3=0; i3 <= imglpix[3] - imgfpix[3]; i3++, it3++)
      {
       /* increment plane if it falls in the cracks of the subsampled image */
       while (ndim > 3 &&  (tfpixel[3] + tilefpix[3] - fpixel[3] + it3)
                            % labs(inc[3]) != 0)
          it3++;

       /* offset to start of cube */
       if (inc[3] > 0)
          im3 = (i3 + imgfpix[3]) * imgdim[2] + im4;
       else
          im3 = imgdim[3] - (i3 + 1 + imgfpix[3]) * imgdim[2] + im4;

       t3 = (tilefpix[3] + it3) * tiledim[2] + t4;

       /* loop through planes of the image */
       for (i2 = 0, it2=0; i2 <= imglpix[2] - imgfpix[2]; i2++, it2++)
       {
          /* incre plane if it falls in the cracks of the subsampled image */
          while (ndim > 2 &&  (tfpixel[2] + tilefpix[2] - fpixel[2] + it2)
                               % labs(inc[2]) != 0)
             it2++;

          /* offset to start of plane */
          if (inc[2] > 0)
             im2 = (i2 + imgfpix[2]) * imgdim[1] + im3;
          else
             im2 = imgdim[2] - (i2 + 1 + imgfpix[2]) * imgdim[1] + im3;

          t2 = (tilefpix[2] + it2) * tiledim[1] + t3;

          /* loop through rows of the image */
          for (i1 = 0, it1=0; i1 <= imglpix[1] - imgfpix[1]; i1++, it1++)
          {
             /* incre row if it falls in the cracks of the subsampled image */
             while (ndim > 1 &&  (tfpixel[1] + tilefpix[1] - fpixel[1] + it1)
                                  % labs(inc[1]) != 0)
                it1++;

             /* calc position of first pixel in tile to be copied */
             tilepix = tilefpix[0] + (tilefpix[1] + it1) * tiledim[0] + t2;

             /* offset to start of row */
             if (inc[1] > 0)
                im1 = (i1 + imgfpix[1]) * imgdim[0] + im2;
             else
                im1 = imgdim[1] - (i1 + 1 + imgfpix[1]) * imgdim[0] + im2;
/*
printf("inc = %d %d %d %d\n",inc[0],inc[1],inc[2],inc[3]);
printf("im1,im2,im3,im4 = %d %d %d %d\n",im1,im2,im3,im4);
*/
             /* offset to byte within the row */
             if (inc[0] > 0)
                imgpix = imgfpix[0] + im1;
             else
                imgpix = imgdim[0] - 1 - imgfpix[0] + im1;
/*
printf("tilefpix0,1, imgfpix1, it1, inc1, t2= %d %d %d %d %d %d\n",
       tilefpix[0],tilefpix[1],imgfpix[1],it1,inc[1], t2);
printf("i1, it1, tilepix, imgpix %d %d %d %d \n", i1, it1, tilepix, imgpix);
*/
             /* loop over pixels along one row of the image */
             for (ipos = imgfpix[0]; ipos <= imglpix[0]; ipos += overlap_flags)
             {
               if (nullcheck == 2)
               {
                   /* copy overlapping null flags from tile to image */
                   memcpy(nullarray + imgpix, bnullarray + tilepix,
                          overlap_flags);
               }

               /* convert from image pixel to byte offset */
               tilepixbyte = tilepix * pixlen;
               imgpixbyte  = imgpix  * pixlen;
/*
printf("  tilepix, tilepixbyte, imgpix, imgpixbyte= %d %d %d %d\n",
          tilepix, tilepixbyte, imgpix, imgpixbyte);
*/
               /* copy overlapping row of pixels from tile to image */
               memcpy(image + imgpixbyte, tile + tilepixbyte, overlap_bytes);

               tilepix += (overlap_flags * labs(inc[0]));
               if (inc[0] > 0)
                 imgpix += overlap_flags;
               else
                 imgpix -= overlap_flags;
            }
          }
        }
      }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int imcomp_merge_overlap (
    char *tile,         /* O - multi dimensional array of tile pixels */
    int pixlen,         /* I - number of bytes in each tile or image pixel */
    int ndim,           /* I - number of dimension in the tile and image */
    long *tfpixel,      /* I - first pixel number in each dim. of the tile */
    long *tlpixel,      /* I - last pixel number in each dim. of the tile */
    char *bnullarray,   /* I - array of null flags; used if nullcheck = 2 */
    char *image,        /* I - multi dimensional output image */
    long *fpixel,       /* I - first pixel number in each dim. of the image */
    long *lpixel,       /* I - last pixel number in each dim. of the image */
    int nullcheck,      /* I - 0, 1: do nothing; 2: set nullarray for nulls */
    int *status)

/* 
  Similar to imcomp_copy_overlap, except it copies the overlapping pixels from
  the 'image' to the 'tile'.
*/
{
    long imgdim[MAX_COMPRESS_DIM]; /* product of preceding dimensions in the */
                                   /* output image, allowing for inc factor */
    long tiledim[MAX_COMPRESS_DIM]; /* product of preceding dimensions in the */
                                 /* tile, array;  inc factor is not relevant */
    long imgfpix[MAX_COMPRESS_DIM]; /* 1st img pix overlapping tile: 0 base, */
                                    /*  allowing for inc factor */
    long imglpix[MAX_COMPRESS_DIM]; /* last img pix overlapping tile 0 base, */
                                    /*  allowing for inc factor */
    long tilefpix[MAX_COMPRESS_DIM]; /* 1st tile pix overlapping img 0 base, */
                                    /*  allowing for inc factor */
    long inc[MAX_COMPRESS_DIM]; /* local copy of input ininc */
    long i1, i2, i3, i4;   /* offset along each axis of the image */
    long it1, it2, it3, it4;
    long im1, im2, im3, im4;  /* offset to image pixel, allowing for inc */
    long ipos, tf, tl;
    long t2, t3, t4;   /* offset along each axis of the tile */
    long tilepix, imgpix, tilepixbyte, imgpixbyte;
    int ii, overlap_bytes, overlap_flags;

    if (*status > 0)
        return(*status);

    for (ii = 0; ii < MAX_COMPRESS_DIM; ii++)
    {
        /* set default values for higher dimensions */
        inc[ii] = 1;
        imgdim[ii] = 1;
        tiledim[ii] = 1;
        imgfpix[ii] = 0;
        imglpix[ii] = 0;
        tilefpix[ii] = 0;
    }

    /* ------------------------------------------------------------ */
    /* calc amount of overlap in each dimension; if there is zero   */
    /* overlap in any dimension then just return  */
    /* ------------------------------------------------------------ */
    
    for (ii = 0; ii < ndim; ii++)
    {
        if (tlpixel[ii] < fpixel[ii] || tfpixel[ii] > lpixel[ii])
            return(*status);  /* there are no overlapping pixels */

        /* calc dimensions of the output image section */
        imgdim[ii] = (lpixel[ii] - fpixel[ii]) / labs(inc[ii]) + 1;
        if (imgdim[ii] < 1)
            return(*status = NEG_AXIS);

        /* calc dimensions of the tile */
        tiledim[ii] = tlpixel[ii] - tfpixel[ii] + 1;
        if (tiledim[ii] < 1)
            return(*status = NEG_AXIS);

        if (ii > 0)
           tiledim[ii] *= tiledim[ii - 1];  /* product of dimensions */

        /* first and last pixels in image that overlap with the tile, 0 base */
        tf = tfpixel[ii] - 1;
        tl = tlpixel[ii] - 1;

        /* skip this plane if it falls in the cracks of the subsampled image */
        while ((tf-(fpixel[ii] - 1)) % labs(inc[ii]))
        {
           tf++;
           if (tf > tl)
             return(*status);  /* no overlapping pixels */
        }

        while ((tl-(fpixel[ii] - 1)) % labs(inc[ii]))
        {
           tl--;
           if (tf > tl)
             return(*status);  /* no overlapping pixels */
        }
        imgfpix[ii] = maxvalue((tf - fpixel[ii] +1) / labs(inc[ii]) , 0);
        imglpix[ii] = minvalue((tl - fpixel[ii] +1) / labs(inc[ii]) ,
                               imgdim[ii] - 1);

        /* first pixel in the tile that overlaps with the image (0 base) */
        tilefpix[ii] = maxvalue(fpixel[ii] - tfpixel[ii], 0);

        while ((tfpixel[ii] + tilefpix[ii] - fpixel[ii]) % labs(inc[ii]))
        {
           (tilefpix[ii])++;
           if (tilefpix[ii] >= tiledim[ii])
              return(*status);  /* no overlapping pixels */
        }
/*
printf("ii tfpixel, tlpixel %d %d %d \n",ii, tfpixel[ii], tlpixel[ii]);
printf("ii, tf, tl, imgfpix,imglpix, tilefpix %d %d %d %d %d %d\n",ii,
 tf,tl,imgfpix[ii], imglpix[ii],tilefpix[ii]);
*/
        if (ii > 0)
           imgdim[ii] *= imgdim[ii - 1];  /* product of dimensions */
    }

    /* ---------------------------------------------------------------- */
    /* calc number of pixels in each row (first dimension) that overlap */
    /* multiply by pixlen to get number of bytes to copy in each loop   */
    /* ---------------------------------------------------------------- */

    if (inc[0] != 1)
       overlap_flags = 1;  /* can only copy 1 pixel at a time */
    else
       overlap_flags = imglpix[0] - imgfpix[0] + 1;  /* can copy whole row */

    overlap_bytes = overlap_flags * pixlen;

    /* support up to 5 dimensions for now */
    for (i4 = 0, it4=0; i4 <= imglpix[4] - imgfpix[4]; i4++, it4++)
    {
     /* increment plane if it falls in the cracks of the subsampled image */
     while (ndim > 4 &&  (tfpixel[4] + tilefpix[4] - fpixel[4] + it4)
                          % labs(inc[4]) != 0)
        it4++;

       /* offset to start of hypercube */
       if (inc[4] > 0)
          im4 = (i4 + imgfpix[4]) * imgdim[3];
       else
          im4 = imgdim[4] - (i4 + 1 + imgfpix[4]) * imgdim[3];

      t4 = (tilefpix[4] + it4) * tiledim[3];
      for (i3 = 0, it3=0; i3 <= imglpix[3] - imgfpix[3]; i3++, it3++)
      {
       /* increment plane if it falls in the cracks of the subsampled image */
       while (ndim > 3 &&  (tfpixel[3] + tilefpix[3] - fpixel[3] + it3)
                            % labs(inc[3]) != 0)
          it3++;

       /* offset to start of cube */
       if (inc[3] > 0)
          im3 = (i3 + imgfpix[3]) * imgdim[2] + im4;
       else
          im3 = imgdim[3] - (i3 + 1 + imgfpix[3]) * imgdim[2] + im4;

       t3 = (tilefpix[3] + it3) * tiledim[2] + t4;

       /* loop through planes of the image */
       for (i2 = 0, it2=0; i2 <= imglpix[2] - imgfpix[2]; i2++, it2++)
       {
          /* incre plane if it falls in the cracks of the subsampled image */
          while (ndim > 2 &&  (tfpixel[2] + tilefpix[2] - fpixel[2] + it2)
                               % labs(inc[2]) != 0)
             it2++;

          /* offset to start of plane */
          if (inc[2] > 0)
             im2 = (i2 + imgfpix[2]) * imgdim[1] + im3;
          else
             im2 = imgdim[2] - (i2 + 1 + imgfpix[2]) * imgdim[1] + im3;

          t2 = (tilefpix[2] + it2) * tiledim[1] + t3;

          /* loop through rows of the image */
          for (i1 = 0, it1=0; i1 <= imglpix[1] - imgfpix[1]; i1++, it1++)
          {
             /* incre row if it falls in the cracks of the subsampled image */
             while (ndim > 1 &&  (tfpixel[1] + tilefpix[1] - fpixel[1] + it1)
                                  % labs(inc[1]) != 0)
                it1++;

             /* calc position of first pixel in tile to be copied */
             tilepix = tilefpix[0] + (tilefpix[1] + it1) * tiledim[0] + t2;

             /* offset to start of row */
             if (inc[1] > 0)
                im1 = (i1 + imgfpix[1]) * imgdim[0] + im2;
             else
                im1 = imgdim[1] - (i1 + 1 + imgfpix[1]) * imgdim[0] + im2;
/*
printf("inc = %d %d %d %d\n",inc[0],inc[1],inc[2],inc[3]);
printf("im1,im2,im3,im4 = %d %d %d %d\n",im1,im2,im3,im4);
*/
             /* offset to byte within the row */
             if (inc[0] > 0)
                imgpix = imgfpix[0] + im1;
             else
                imgpix = imgdim[0] - 1 - imgfpix[0] + im1;
/*
printf("tilefpix0,1, imgfpix1, it1, inc1, t2= %d %d %d %d %d %d\n",
       tilefpix[0],tilefpix[1],imgfpix[1],it1,inc[1], t2);
printf("i1, it1, tilepix, imgpix %d %d %d %d \n", i1, it1, tilepix, imgpix);
*/
             /* loop over pixels along one row of the image */
             for (ipos = imgfpix[0]; ipos <= imglpix[0]; ipos += overlap_flags)
             {
               /* convert from image pixel to byte offset */
               tilepixbyte = tilepix * pixlen;
               imgpixbyte  = imgpix  * pixlen;
/*
printf("  tilepix, tilepixbyte, imgpix, imgpixbyte= %d %d %d %d\n",
          tilepix, tilepixbyte, imgpix, imgpixbyte);
*/
               /* copy overlapping row of pixels from image to tile */
               memcpy(tile + tilepixbyte, image + imgpixbyte,  overlap_bytes);

               tilepix += (overlap_flags * labs(inc[0]));
               if (inc[0] > 0)
                 imgpix += overlap_flags;
               else
                 imgpix -= overlap_flags;
            }
          }
        }
      }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
static int unquantize_i1r4(long row, /* tile number = row number in table  */
            unsigned char *input, /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int dither_method,    /* I - dithering method to use             */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
            float nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            float *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
    Unquantize byte values into the scaled floating point values
*/
{
    long ii;
    int nextrand, iseed;

    if (!fits_rand_value) 
       if (fits_init_randoms()) return(MEMORY_ALLOCATION);

    /* initialize the index to the next random number in the list */
    iseed = (int) ((row - 1) % N_RANDOM);
    nextrand = (int) (fits_rand_value[iseed] * 500);

    if (nullcheck == 0)     /* no null checking required */
    {
             for (ii = 0; ii < ntodo; ii++)
            {
/*
		if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE)
		    output[ii] = 0.0;
		else
*/
                    output[ii] = (float) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero);

	        nextrand++;
	        if (nextrand == N_RANDOM) {
	            iseed++;
		    if (iseed == N_RANDOM) iseed = 0;
		    nextrand = (int) (fits_rand_value[iseed] * 500);
	        }
            }
    }
    else        /* must check for null values */
    {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
/*
		    if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE)
		        output[ii] = 0.0;
		    else
*/
                        output[ii] = (float) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero);
                } 

	        nextrand++;
	        if (nextrand == N_RANDOM) {
	            iseed++;
		    if (iseed == N_RANDOM) iseed = 0;
	            nextrand = (int) (fits_rand_value[iseed] * 500);
                }
            }
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
static int unquantize_i2r4(long row, /* seed for random values  */
            short *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int dither_method,    /* I - dithering method to use             */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            short tnull,          /* I - value of FITS TNULLn keyword if any */
            float nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            float *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
    Unquantize short integer values into the scaled floating point values
*/
{
    long ii;
    int nextrand, iseed;

    if (!fits_rand_value) 
       if (fits_init_randoms()) return(MEMORY_ALLOCATION);

    /* initialize the index to the next random number in the list */
    iseed = (int) ((row - 1) % N_RANDOM);
    nextrand = (int) (fits_rand_value[iseed] * 500);

    if (nullcheck == 0)     /* no null checking required */
    {
           for (ii = 0; ii < ntodo; ii++)
            {
/*
		if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE)
		    output[ii] = 0.0;
		else
*/
                    output[ii] = (float) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero);

	        nextrand++;
	        if (nextrand == N_RANDOM) {
	            iseed++;
		    if (iseed == N_RANDOM) iseed = 0;
		    nextrand = (int) (fits_rand_value[iseed] * 500);
	        }
            }
    }
    else        /* must check for null values */
    {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
/*
                    if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE)
		        output[ii] = 0.0;
		    else
*/
                        output[ii] = (float) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero);
                }

	        nextrand++;
	        if (nextrand == N_RANDOM) {
	            iseed++;
		    if (iseed == N_RANDOM) iseed = 0;
		    nextrand = (int) (fits_rand_value[iseed] * 500);
	        }
             }
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
static int unquantize_i4r4(long row, /* tile number = row number in table    */
            INT32BIT *input,      /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int dither_method,    /* I - dithering method to use             */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
            float nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            float *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
    Unquantize int integer values into the scaled floating point values
*/
{
    long ii;
    int nextrand, iseed;

    if (fits_rand_value == 0) 
       if (fits_init_randoms()) return(MEMORY_ALLOCATION);

    /* initialize the index to the next random number in the list */
    iseed = (int) ((row - 1) % N_RANDOM);
    nextrand = (int) (fits_rand_value[iseed] * 500);

    if (nullcheck == 0)     /* no null checking required */
    {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE)
		    output[ii] = 0.0;
		else
                    output[ii] = (float) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero);

	        nextrand++;
	        if (nextrand == N_RANDOM) {
	            iseed++;
		    if (iseed == N_RANDOM) iseed = 0;
		    nextrand = (int) (fits_rand_value[iseed] * 500);
	        }
            }
    }
    else        /* must check for null values */
    {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE)
		        output[ii] = 0.0;
		    else
                        output[ii] = (float) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero);
                }

	        nextrand++;
	        if (nextrand == N_RANDOM) {
	            iseed++;
		    if (iseed == N_RANDOM) iseed = 0;
		    nextrand = (int) (fits_rand_value[iseed] * 500);
	        }
            }
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
static int unquantize_i1r8(long row, /* tile number = row number in table  */
            unsigned char *input, /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int dither_method,    /* I - dithering method to use             */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
            double nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            double *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
    Unquantize byte values into the scaled floating point values
*/
{
    long ii;
    int nextrand, iseed;

    if (!fits_rand_value) 
       if (fits_init_randoms()) return(MEMORY_ALLOCATION);

    /* initialize the index to the next random number in the list */
    iseed = (int) ((row - 1) % N_RANDOM);
    nextrand = (int) (fits_rand_value[iseed] * 500);

    if (nullcheck == 0)     /* no null checking required */
    {
            for (ii = 0; ii < ntodo; ii++)
            {
/*
                if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE)
		    output[ii] = 0.0;
		else
*/
                    output[ii] = (double) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero);

	        nextrand++;
	        if (nextrand == N_RANDOM) {
	            iseed++;
		    if (iseed == N_RANDOM) iseed = 0;
		    nextrand = (int) (fits_rand_value[iseed] * 500);
	        }
            }
    }
    else        /* must check for null values */
    {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
/*
                    if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE)
		        output[ii] = 0.0;
		    else
*/
                        output[ii] = (double) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero);
                }

	        nextrand++;
	        if (nextrand == N_RANDOM) {
	            iseed++;
		    if (iseed == N_RANDOM) iseed = 0;
		    nextrand = (int) (fits_rand_value[iseed] * 500);
	        }
            }
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
static int unquantize_i2r8(long row, /* tile number = row number in table  */
            short *input,         /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int dither_method,    /* I - dithering method to use             */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            short tnull,          /* I - value of FITS TNULLn keyword if any */
            double nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            double *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
    Unquantize short integer values into the scaled floating point values
*/
{
    long ii;
    int nextrand, iseed;

    if (!fits_rand_value) 
       if (fits_init_randoms()) return(MEMORY_ALLOCATION);

    /* initialize the index to the next random number in the list */
    iseed = (int) ((row - 1) % N_RANDOM);
    nextrand = (int) (fits_rand_value[iseed] * 500);

    if (nullcheck == 0)     /* no null checking required */
    {
           for (ii = 0; ii < ntodo; ii++)
            {
/*
                if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE)
		    output[ii] = 0.0;
		else
*/
                    output[ii] = (double) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero);

	        nextrand++;
	        if (nextrand == N_RANDOM) {
	            iseed++;
		    if (iseed == N_RANDOM) iseed = 0;
		    nextrand = (int) (fits_rand_value[iseed] * 500);
	        }
            }
    }
    else        /* must check for null values */
    {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
/*                    if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE)
		        output[ii] = 0.0;
		    else
*/
                        output[ii] = (double) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero);
                }

	        nextrand++;
	        if (nextrand == N_RANDOM) {
	            iseed++;
		    if (iseed == N_RANDOM) iseed = 0;
		    nextrand = (int) (fits_rand_value[iseed] * 500);
	        }
            }
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
static int unquantize_i4r8(long row, /* tile number = row number in table    */
            INT32BIT *input,      /* I - array of values to be converted     */
            long ntodo,           /* I - number of elements in the array     */
            double scale,         /* I - FITS TSCALn or BSCALE value         */
            double zero,          /* I - FITS TZEROn or BZERO  value         */
            int dither_method,    /* I - dithering method to use             */
            int nullcheck,        /* I - null checking code; 0 = don't check */
                                  /*     1:set null pixels = nullval         */
                                  /*     2: if null pixel, set nullarray = 1 */
            INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
            double nullval,        /* I - set null pixels, if nullcheck = 1   */
            char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
            int  *anynull,        /* O - set to 1 if any pixels are null     */
            double *output,        /* O - array of converted pixels           */
            int *status)          /* IO - error status                       */
/*
    Unquantize int integer values into the scaled floating point values
*/
{
    long ii;
    int nextrand, iseed;

    if (fits_rand_value == 0) 
       if (fits_init_randoms()) return(MEMORY_ALLOCATION);

    /* initialize the index to the next random number in the list */
    iseed = (int) ((row - 1) % N_RANDOM);
    nextrand = (int) (fits_rand_value[iseed] * 500);

    if (nullcheck == 0)     /* no null checking required */
    {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE)
		    output[ii] = 0.0;
		else
                    output[ii] = (double) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero);

	        nextrand++;
	        if (nextrand == N_RANDOM) {
	            iseed++;
		    if (iseed == N_RANDOM) iseed = 0;
		    nextrand = (int) (fits_rand_value[iseed] * 500);
	        }
            }
    }
    else        /* must check for null values */
    {
            for (ii = 0; ii < ntodo; ii++)
            {
                if (input[ii] == tnull)
                {
                    *anynull = 1;
                    if (nullcheck == 1)
                        output[ii] = nullval;
                    else
                        nullarray[ii] = 1;
                }
                else
                {
                    if (dither_method == SUBTRACTIVE_DITHER_2 && input[ii] == ZERO_VALUE)
		        output[ii] = 0.0;
		    else
                        output[ii] = (double) (((double) input[ii] - fits_rand_value[nextrand] + 0.5) * scale + zero);
                }

	        nextrand++;
	        if (nextrand == N_RANDOM) {
	            iseed++;
		    if (iseed == N_RANDOM) iseed = 0;
		    nextrand = (int) (fits_rand_value[iseed] * 500);
	        }
            }
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
static int imcomp_float2nan(float *indata, 
    long tilelen,
    int *outdata,
    float nullflagval, 
    int *status)
/*
  convert pixels that are equal to nullflag to NaNs.
  Note that indata and outdata point to the same location.
*/
{
    int ii;
    
    for (ii = 0; ii < tilelen; ii++) {

      if (indata[ii] == nullflagval)
        outdata[ii] = -1;  /* integer -1 has the same bit pattern as a real*4 NaN */
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
static int imcomp_double2nan(double *indata, 
    long tilelen,
    LONGLONG *outdata,
    double nullflagval, 
    int *status)
/*
  convert pixels that are equal to nullflag to NaNs.
  Note that indata and outdata point to the same location.
*/
{
    int ii;
    
    for (ii = 0; ii < tilelen; ii++) {

      if (indata[ii] == nullflagval)
        outdata[ii] = -1;  /* integer -1 has the same bit pattern as a real*8 NaN */
    }

    return(*status);
}

/* ======================================================================= */
/*    TABLE COMPRESSION ROUTINES                                           */
/* =-====================================================================== */

/*--------------------------------------------------------------------------*/
int fits_compress_table(fitsfile *infptr, fitsfile *outfptr, int *status)

/*
  Compress the input FITS Binary Table.
  
  First divide the table into equal sized chunks (analogous to image tiles) where all
  the contain the same number of rows (except perhaps for the last chunk
  which may contain fewer rows).   The chunks should not be too large to copy into memory
  (currently, about 100 MB max seems a reasonable size).
  
  Then, on a chunk by piece basis, do the following:
  
  1. Transpose the table from its original row-major order, into column-major order.
  All the bytes for each column are then continuous.  In addition, the bytes within
  each table element may be shuffled so that the most significant
  byte of every element occurs first in the array, followed by the next most
  significant byte, and so on to the least significant byte.  Byte shuffling often
  improves the gzip compression of floating-point arrays.
   
  2. Compress the contiguous array of bytes in each column using the specified
  compression method.  If no method is specifed, then a default method for that
  data type is chosen. 
  
  3. Store the compressed stream of bytes into a column that has the same name
  as in the input table, but which has a variable-length array data type (1QB).
  The output table will contain one row for each piece of the original table.
  
  4. If the input table contain variable-length arrays, then each VLA
  is compressed individually, and written to the heap in the output table.
  Note that the output table will contain 2 sets of pointers for each VLA column.  
  The first set contains the pointers to the uncompressed VLAs from the input table
  and the second is the set of pointers to the compressed VLAs in the output table.
  The latter set of pointers is used to reconstruct table when it is uncompressed,
  so that the heap has exactly the same structure as in the original file.  The 2
  sets of pointers are concatinated together, compressed with gzip, and written to
  the output table.  When reading the compressed table, the only VLA that is directly
  visible is this compressed array of descriptors.  One has to uncompress this array
  to be able to to read all the descriptors to the individual VLAs in the column.  
*/
{ 
    long maxchunksize = 10000000; /* default value for the size of each chunk of the table */

    char *cm_buffer;  /* memory buffer for the transposed, Column-Major, chunk of the table */ 
    LONGLONG cm_colstart[1000];  /* starting offset of each column in the cm_buffer */
    LONGLONG rm_repeat[1000];    /* repeat count of each column in the input row-major table */
    LONGLONG rm_colwidth[999];   /* width in bytes of each column in the input row-major table */
    LONGLONG cm_repeat[999];  /* total number of elements in each column of the transposed column-major table */

    int coltype[999];         /* data type code for each column */
    int compalgor[999], default_algor = 0;       /* compression algorithm to be applied to each column */
    float cratio[999];        /* compression ratio for each column (for diagnostic purposes) */

    float compressed_size, uncompressed_size, tot_compressed_size, tot_uncompressed_size;
    LONGLONG nrows, firstrow;
    LONGLONG headstart, datastart, dataend, startbyte, jj, kk, naxis1;
    LONGLONG vlalen, vlamemlen, vlastart, bytepos;
    long repeat, width, nchunks, rowspertile, lastrows;
    int ii, ll, ncols, hdutype, ltrue = 1, print_report = 0, tstatus;
    char *cptr, keyname[9], tform[40], *cdescript;
    char comm[FLEN_COMMENT], keyvalue[FLEN_VALUE], *cvlamem, tempstring[FLEN_VALUE], card[FLEN_CARD];

    LONGLONG *descriptors, *outdescript, *vlamem;
    int *pdescriptors;
    size_t dlen, datasize, compmemlen;

    /* ================================================================================== */
    /* perform initial sanity checks */
    /* ================================================================================== */
    
    /* special input flag value that means print out diagnostics */
    if (*status == -999) {
       print_report = 1;
       *status = 0;
    }

    if (*status > 0)
        return(*status);
    
    fits_get_hdu_type(infptr, &hdutype, status);
    if (hdutype != BINARY_TBL) {
        *status = NOT_BTABLE;
        return(*status);
    }

    if (infptr == outfptr) {
        ffpmsg("Cannot compress table 'in place' (fits_compress_table)");
        ffpmsg(" outfptr cannot be the same as infptr.");
        *status = DATA_COMPRESSION_ERR;
        return(*status);
    }

    /* get dimensions of the table */
    fits_get_num_rowsll(infptr, &nrows, status);
    fits_get_num_cols(infptr, &ncols, status);
    fits_read_key(infptr, TLONGLONG, "NAXIS1", &naxis1, NULL, status);
    /* get offset to the start of the data and total size of the table (including the heap) */
    fits_get_hduaddrll(infptr, &headstart, &datastart, &dataend, status);

    if (*status > 0)
        return(*status);

    tstatus = 0;
    if (!fits_read_key(infptr, TSTRING, "FZALGOR", tempstring, NULL, &tstatus)) {

	    if (!fits_strcasecmp(tempstring, "NONE")) {
	            default_algor = NOCOMPRESS;
	    } else if (!fits_strcasecmp(tempstring, "GZIP") || !fits_strcasecmp(tempstring, "GZIP_1")) {
	            default_algor = GZIP_1;
	    } else if (!fits_strcasecmp(tempstring, "GZIP_2")) {
	            default_algor = GZIP_2;
 	    } else if (!fits_strcasecmp(tempstring, "RICE_1")) {
	            default_algor = RICE_1;
 	    } else {
 	        ffpmsg("FZALGOR specifies unsupported table compression algorithm:");
		ffpmsg(tempstring);
	        *status = DATA_COMPRESSION_ERR;
	        return(*status);
	    }
    }

     /* just copy the HDU verbatim if the table has 0 columns or rows or if the table */
    /* is less than 5760 bytes (2 blocks) in size, or compression directive keyword = "NONE" */
    if (nrows < 1  || ncols < 1 || (dataend - datastart) < 5760  || default_algor == NOCOMPRESS) {
	fits_copy_hdu (infptr, outfptr, 0, status);
	return(*status);
    }
   
    /* Check if the chunk size has been specified with the FZTILELN keyword. */
    /* If not, calculate a default number of rows per chunck, */

    tstatus = 0;
    if (fits_read_key(infptr, TLONG, "FZTILELN", &rowspertile, NULL, &tstatus)) {
	rowspertile = (long) (maxchunksize / naxis1);
    }

    if (rowspertile < 1) rowspertile = 1;  
    if (rowspertile > nrows) rowspertile = (long) nrows;
    
    nchunks = (long) ((nrows - 1) / rowspertile + 1);  /* total number of chunks */
    lastrows = (long) (nrows - ((nchunks - 1) * rowspertile)); /* number of rows in last chunk */

    /* allocate space for the transposed, column-major chunk of the table */
    cm_buffer = calloc((size_t) naxis1, (size_t) rowspertile);
    if (!cm_buffer) {
        ffpmsg("Could not allocate cm_buffer for transposed table");
        *status = MEMORY_ALLOCATION;
        return(*status);
    }

    /* ================================================================================== */
    /*  Construct the header of the output compressed table  */
    /* ================================================================================== */
    fits_copy_header(infptr, outfptr, status);  /* start with verbatim copy of the input header */

    fits_write_key(outfptr, TLOGICAL, "ZTABLE", <rue, "this is a compressed table", status);
    fits_write_key(outfptr, TLONG, "ZTILELEN", &rowspertile, "number of rows in each tile", status);

    fits_read_card(outfptr, "NAXIS1", card, status); /* copy NAXIS1 to ZNAXIS1 */
    strncpy(card, "ZNAXIS1", 7);
    fits_write_record(outfptr, card, status);
    
    fits_read_card(outfptr, "NAXIS2", card, status); /* copy NAXIS2 to ZNAXIS2 */
    strncpy(card, "ZNAXIS2", 7);
    fits_write_record(outfptr, card, status);

    fits_read_card(outfptr, "PCOUNT", card, status); /* copy PCOUNT to ZPCOUNT */
    strncpy(card, "ZPCOUNT", 7);
    fits_write_record(outfptr, card, status);

    fits_modify_key_lng(outfptr, "NAXIS2", nchunks, "&", status);  /* 1 row per chunk */
    fits_modify_key_lng(outfptr, "NAXIS1", ncols * 16, "&", status); /* 16 bytes for each 1QB column */
    fits_modify_key_lng(outfptr, "PCOUNT", 0L, "&", status); /* reset PCOUNT to 0 */
    
    /* rename the Checksum keywords, if they exist */
    tstatus = 0;
    fits_modify_name(outfptr, "CHECKSUM", "ZHECKSUM", &tstatus);
    tstatus = 0;
    fits_modify_name(outfptr, "DATASUM", "ZDATASUM", &tstatus);

    /* ================================================================================== */
    /*  Now loop over each column of the input table: write the column-specific keywords */
    /*  and determine which compression algorithm to use.     */
    /*  Also calculate various offsets to the start of the column data in both the */
    /*  original row-major table and in the transposed column-major form of the table.  */
    /* ================================================================================== */

    cm_colstart[0] = 0;
    for (ii = 0; ii < ncols; ii++) {  

 	/* get the structural parameters of the original uncompressed column */
	fits_make_keyn("TFORM", ii+1, keyname, status);
	fits_read_key(outfptr, TSTRING, keyname, tform, comm, status);
        fits_binary_tform(tform, coltype+ii, &repeat, &width, status); /* get the repeat count and the width */

	/* preserve the original TFORM value and comment string in a ZFORMn keyword */
	fits_read_card(outfptr, keyname, card, status); 
	card[0] = 'Z';
	fits_write_record(outfptr, card, status);
 
        /* All columns in the compressed table will have a variable-length array type. */
	fits_modify_key_str(outfptr, keyname, "1QB", "&", status);  /* Use 'Q' pointers (64-bit) */ 

	/* deal with special cases: bit, string, and variable length array columns */
	if (coltype[ii] == TBIT) {
	    repeat = (repeat + 7) / 8;  /* convert from bits to equivalent number of bytes */
	} else if (coltype[ii] == TSTRING) {
	    width = 1;  /* ignore the optional 'w' in 'rAw' format */
	} else if (coltype[ii] < 0) {  /* pointer to variable length array */
	    if (strchr(tform,'Q') ) {
	        width = 16;  /* 'Q' descriptor has 64-bit pointers */
	    } else {
	        width = 8;  /* 'P' descriptor has 32-bit pointers */
 	    }
	    repeat = 1;
	}

	rm_repeat[ii] = repeat;   
	rm_colwidth[ii] = repeat * width; /* column width (in bytes)in the input table */
	
	/* starting offset of each field in the OUTPUT transposed column-major table */
	cm_colstart[ii + 1] = cm_colstart[ii] + rm_colwidth[ii] * rowspertile;
	/* total number of elements in each column of the transposed column-major table */
	cm_repeat[ii] = rm_repeat[ii] * rowspertile;

	compalgor[ii] = default_algor;  /* initialize the column compression algorithm to the default */
	
	/*  check if a compression method has been specified for this column */
	fits_make_keyn("FZALG", ii+1, keyname, status);
	tstatus = 0;
	if (!fits_read_key(outfptr, TSTRING, keyname, tempstring, NULL, &tstatus)) {

	    if (!fits_strcasecmp(tempstring, "GZIP") || !fits_strcasecmp(tempstring, "GZIP_1")) {
	            compalgor[ii] = GZIP_1;
	    } else if (!fits_strcasecmp(tempstring, "GZIP_2")) {
	            compalgor[ii] = GZIP_2;
	    } else if (!fits_strcasecmp(tempstring, "RICE_1")) {
	            compalgor[ii] = RICE_1;
	    } else {
	        ffpmsg("Unsupported table compression algorithm specification.");
		ffpmsg(keyname);
		ffpmsg(tempstring);
	        *status = DATA_COMPRESSION_ERR;
		free(cm_buffer);
	        return(*status);
	    }
	}

	/* do sanity check of the requested algorithm and override if necessary */
	if ( abs(coltype[ii]) == TLOGICAL || abs(coltype[ii]) == TBIT || abs(coltype[ii]) == TSTRING) {
	        if (compalgor[ii] != GZIP_1) {
			compalgor[ii] = GZIP_1;
		}
	} else if ( abs(coltype[ii]) == TCOMPLEX || abs(coltype[ii]) == TDBLCOMPLEX ||
	                abs(coltype[ii]) == TFLOAT   || abs(coltype[ii]) == TDOUBLE ||
			abs(coltype[ii]) == TLONGLONG ) {
	        if (compalgor[ii] != GZIP_1 && compalgor[ii] != GZIP_2) {
			compalgor[ii] = GZIP_2;  /* gzip_2 usually works better gzip_1 */
		}
	} else if ( abs(coltype[ii]) == TSHORT ) {
	        if (compalgor[ii] != GZIP_1 && compalgor[ii] != GZIP_2 && compalgor[ii] != RICE_1) {
			compalgor[ii] = GZIP_2;  /* gzip_2 usually works better rice_1 */
		 }
	} else if (  abs(coltype[ii]) == TLONG	) {
	        if (compalgor[ii] != GZIP_1 && compalgor[ii] != GZIP_2 && compalgor[ii] != RICE_1) {
			compalgor[ii] = RICE_1;
		}
	} else if ( abs(coltype[ii]) == TBYTE ) {
	        if (compalgor[ii] != GZIP_1 && compalgor[ii] != RICE_1 ) {
			compalgor[ii] = GZIP_1;
		}
	}
    }  /* end of loop over columns */

    /* ================================================================================== */
    /*    now process each chunk of the table, in turn          */
    /* ================================================================================== */

    tot_uncompressed_size = 0.;
    tot_compressed_size = 0;
    firstrow = 1;
    for (ll = 0; ll < nchunks; ll++) {

        if (ll == nchunks - 1) {  /* the last chunk may have fewer rows */
	    rowspertile = lastrows; 
            for (ii = 0; ii < ncols; ii++) { 
		cm_colstart[ii + 1] = cm_colstart[ii] + (rm_colwidth[ii] * rowspertile);
		cm_repeat[ii] = rm_repeat[ii] * rowspertile;
	    }
	}

        /* move to the start of the chunk in the input table */
        ffmbyt(infptr, datastart, 0, status);

        /* ================================================================================*/
        /*  First, transpose this chunck from row-major order to column-major order  */
	/*  At the same time, shuffle the bytes in each datum, if doing GZIP_2 compression */
        /* ================================================================================*/

        for (jj = 0; jj < rowspertile; jj++)   {    /* loop over rows */
          for (ii = 0; ii < ncols; ii++) {  /* loop over columns */
      
           if (rm_repeat[ii] > 0) {  /*  skip virtual columns that have 0 elements */

	    kk = 0;	

	     /* if the  GZIP_2 compression algorithm is used, shuffle the bytes */
	    if (coltype[ii] == TSHORT && compalgor[ii] == GZIP_2) {
	      while(kk < rm_colwidth[ii]) {
	        cptr = cm_buffer + (cm_colstart[ii] + (jj * rm_repeat[ii]) + kk/2);  
	        ffgbyt(infptr, 1, cptr, status);  /* get 1st byte */
	        cptr += cm_repeat[ii];  
	        ffgbyt(infptr, 1, cptr, status);  /* get 2nd byte */
	        kk += 2;
	      }
	    } else if ((coltype[ii] == TFLOAT || coltype[ii] == TLONG) && compalgor[ii] == GZIP_2) {
	      while(kk < rm_colwidth[ii]) {
	        cptr = cm_buffer + (cm_colstart[ii] + (jj * rm_repeat[ii]) + kk/4);  
	        ffgbyt(infptr, 1, cptr, status);  /* get 1st byte */
	        cptr += cm_repeat[ii];  
	        ffgbyt(infptr, 1, cptr, status);  /* get 2nd byte */
	        cptr += cm_repeat[ii];  
	        ffgbyt(infptr, 1, cptr, status);  /* get 3rd byte */
	        cptr += cm_repeat[ii];  
	        ffgbyt(infptr, 1, cptr, status);  /* get 4th byte */
	        kk += 4;
	      }
	    } else if ( (coltype[ii] == TDOUBLE || coltype[ii] == TLONGLONG) && compalgor[ii] == GZIP_2) {
	      while(kk < rm_colwidth[ii]) {
	        cptr = cm_buffer + (cm_colstart[ii] + (jj * rm_repeat[ii]) + kk/8);  
	        ffgbyt(infptr, 1, cptr, status);  /* get 1st byte */
	        cptr += cm_repeat[ii];  
	        ffgbyt(infptr, 1, cptr, status);  /* get 2nd byte */
	        cptr += cm_repeat[ii];  
	        ffgbyt(infptr, 1, cptr, status);  /* get 3rd byte */
	        cptr += cm_repeat[ii];  
	        ffgbyt(infptr, 1, cptr, status);  /* get 4th byte */
	        cptr += cm_repeat[ii];  
	        ffgbyt(infptr, 1, cptr, status);  /* get 5th byte */
	        cptr += cm_repeat[ii];  
	        ffgbyt(infptr, 1, cptr, status);  /* get 6th byte */
	        cptr += cm_repeat[ii];  
	        ffgbyt(infptr, 1, cptr, status);  /* get 7th byte */
	        cptr += cm_repeat[ii];  
	        ffgbyt(infptr, 1, cptr, status);  /* get 8th byte */
	        kk += 8;
	      }
	    } else  { /* all other cases: don't shuffle the bytes; simply transpose the column */
	        cptr = cm_buffer + (cm_colstart[ii] + (jj * rm_colwidth[ii]));   /* addr to copy to */
	        startbyte = (infptr->Fptr)->bytepos;  /* save the starting byte location */
	        ffgbyt(infptr, rm_colwidth[ii], cptr, status);  /* copy all the bytes */

	        if (rm_colwidth[ii] >= MINDIRECT) { /* have to explicitly move to next byte */
	  	    ffmbyt(infptr, startbyte + rm_colwidth[ii], 0, status);
	        }
	    }  /* end of test of coltypee */

           }  /* end of not virtual column */
          }  /* end of loop over columns */
        }  /* end of loop over rows */

        /* ================================================================================*/
        /*  now compress each column in the transposed chunk of the table    */
        /* ================================================================================*/

        fits_set_hdustruc(outfptr, status);  /* initialize structures in the output table */
    
        for (ii = 0; ii < ncols; ii++) {  /* loop over columns */
	  /* initialize the diagnostic compression results string */
	  snprintf(results[ii],30,"%3d %3d %3d ", ii+1, coltype[ii], compalgor[ii]);  
          cratio[ii] = 0;
	  
          if (rm_repeat[ii] > 0) {  /* skip virtual columns with zero width */

	    if (coltype[ii] < 0)  {  /* this is a variable length array (VLA) column */

		/*=========================================================================*/	    
	        /* variable-length array columns are a complicated special case  */
		/*=========================================================================*/

		/* allocate memory to hold all the VLA descriptors from the input table, plus */
		/* room to hold the descriptors to the compressed VLAs in the output table */
		/* In total, there will be 2 descriptors for each row in this chunk */

		uncompressed_size = 0.;
		compressed_size = 0;
		
		datasize = (size_t) (cm_colstart[ii + 1] - cm_colstart[ii]); /* size of input descriptors */

		cdescript =  calloc(datasize + (rowspertile * 16), 1); /* room for both descriptors */
		if (!cdescript) {
                    ffpmsg("Could not allocate buffer for descriptors");
                    *status = MEMORY_ALLOCATION;
		    free(cm_buffer);
	            return(*status);
		}

		/* copy the input descriptors to this array */
		memcpy(cdescript, &cm_buffer[cm_colstart[ii]], datasize);
#if BYTESWAPPED
		/* byte-swap the integer values into the native machine representation */
		if (rm_colwidth[ii] == 16) {
		    ffswap8((double *) cdescript,  rowspertile * 2);
		} else {
		    ffswap4((int *) cdescript,  rowspertile * 2);
		}
#endif
		descriptors = (LONGLONG *) cdescript;  /* use this for Q type descriptors */
		pdescriptors = (int *) cdescript;     /* use this instead for or P type descriptors */
		/* pointer to the 2nd set of descriptors */
		outdescript = (LONGLONG *) (cdescript + datasize);  /* this is a LONGLONG pointer */
		
		for (jj = 0; jj < rowspertile; jj++)   {    /* loop to compress each VLA in turn */

		  if (rm_colwidth[ii] == 16) { /* if Q pointers */
			vlalen = descriptors[jj * 2];
			vlastart = descriptors[(jj * 2) + 1];
		  } else {  /* if P pointers */
			vlalen = (LONGLONG) pdescriptors[jj * 2];
			vlastart = (LONGLONG) pdescriptors[(jj * 2) + 1];
		  }

		  if (vlalen > 0) {  /* skip zero-length VLAs */

		    vlamemlen = vlalen * (int) (-coltype[ii] / 10);
		    vlamem = (LONGLONG *) malloc((size_t) vlamemlen); /* memory for the input uncompressed VLA */
		    if (!vlamem) {
			ffpmsg("Could not allocate buffer for VLA");
			*status = MEMORY_ALLOCATION;
			free(cdescript); free(cm_buffer);
			return(*status);
		    }

		    compmemlen = (size_t) (vlalen * ((LONGLONG) (-coltype[ii] / 10)) * 1.5);
		    if (compmemlen < 100) compmemlen = 100;
		    cvlamem = malloc(compmemlen);  /* memory for the output compressed VLA */
		    if (!cvlamem) {
			ffpmsg("Could not allocate buffer for compressed data");
			*status = MEMORY_ALLOCATION;
			free(vlamem); free(cdescript); free(cm_buffer);
			return(*status);
		    }

		    /* read the raw bytes directly from the heap, without any byte-swapping or null value detection */
		    bytepos = (infptr->Fptr)->datastart + (infptr->Fptr)->heapstart + vlastart;
		    ffmbyt(infptr, bytepos, REPORT_EOF, status);
		    ffgbyt(infptr, vlamemlen, vlamem, status);  /* read the bytes */
		    uncompressed_size += vlamemlen;  /* total size of the uncompressed VLAs */
		    tot_uncompressed_size += vlamemlen;  /* total size of the uncompressed file */

		    /* compress the VLA with the appropriate algorithm */
	    	    if (compalgor[ii] == RICE_1) {

		        if (-coltype[ii] == TSHORT) {
#if BYTESWAPPED
			  ffswap2((short *) (vlamem),  (long) vlalen); 
#endif
			  dlen = fits_rcomp_short ((short *)(vlamem), (int) vlalen, (unsigned char *) cvlamem,
			   (int) compmemlen, 32);
		        } else if (-coltype[ii] == TLONG) {
#if BYTESWAPPED
			  ffswap4((int *) (vlamem),  (long) vlalen); 
#endif
			  dlen = fits_rcomp ((int *)(vlamem), (int) vlalen, (unsigned char *) cvlamem,
                           (int) compmemlen, 32);
		        } else if (-coltype[ii] == TBYTE) {
			  dlen = fits_rcomp_byte ((signed char *)(vlamem), (int) vlalen, (unsigned char *) cvlamem,
                           (int) compmemlen, 32);
		        } else {
			  /* this should not happen */
			  ffpmsg(" Error: cannot compress this column type with the RICE algorthm");
			  free(vlamem); free(cdescript); free(cm_buffer); free(cvlamem);
			  *status = DATA_COMPRESSION_ERR;
			  return(*status);
		        }  
		    } else if (compalgor[ii] == GZIP_1 || compalgor[ii] == GZIP_2){  
		       if (compalgor[ii] == GZIP_2 ) {  /* shuffle the bytes before gzipping them */
			   if ( (int) (-coltype[ii] / 10) == 2) {
			       fits_shuffle_2bytes((char *) vlamem, vlalen, status);
			   } else if ( (int) (-coltype[ii] / 10) == 4) {
			       fits_shuffle_4bytes((char *) vlamem, vlalen, status);
			   } else if ( (int) (-coltype[ii] / 10) == 8) {
			       fits_shuffle_8bytes((char *) vlamem, vlalen, status);
			   }
		        }
		        /*: gzip compress the array of bytes */
		        compress2mem_from_mem( (char *) vlamem, (size_t) vlamemlen,
	    		    &cvlamem,  &compmemlen, realloc, &dlen, status);        
		    } else {
			  /* this should not happen */
			  ffpmsg(" Error: unknown compression algorthm");
			  free(vlamem); free(cdescript); free(cm_buffer); free(cvlamem);
			  *status = DATA_COMPRESSION_ERR;
			  return(*status);
		    }  

		    /* write the compressed array to the output table, but... */
		    /* We use a trick of always writing the array to the same row of the output table */
		    /* and then copy the descriptor into the array of descriptors that we allocated. */
		     
		    /* First, reset the descriptor */
		    fits_write_descript(outfptr, ii+1, ll+1, 0, 0, status);

		    /* write the compressed VLA if it is smaller than the original, else write */
		    /* the uncompressed array */
		    fits_set_tscale(outfptr, ii + 1, 1.0, 0.0, status);  /* turn off any data scaling, first */
		    if (dlen < vlamemlen) {
		        fits_write_col(outfptr, TBYTE, ii + 1, ll+1, 1, dlen, cvlamem, status);
		        compressed_size += dlen;  /* total size of the compressed VLAs */
		        tot_compressed_size += dlen;  /* total size of the compressed file */
		    } else {
			if ( -coltype[ii] != TBYTE && compalgor[ii] != GZIP_1) {
			    /* it is probably faster to reread the raw bytes, rather than unshuffle or unswap them */
			    bytepos = (infptr->Fptr)->datastart + (infptr->Fptr)->heapstart + vlastart;
			    ffmbyt(infptr, bytepos, REPORT_EOF, status);
			    ffgbyt(infptr, vlamemlen, vlamem, status);  /* read the bytes */
			}
		        fits_write_col(outfptr, TBYTE, ii + 1, ll+1, 1, vlamemlen, vlamem, status);
		        compressed_size += vlamemlen;  /* total size of the compressed VLAs */
		        tot_compressed_size += vlamemlen;  /* total size of the compressed file */
		    }

		    /* read back the descriptor and save it in the array of descriptors */
		    fits_read_descriptll(outfptr, ii + 1, ll + 1, outdescript+(jj*2), outdescript+(jj*2)+1, status);
		    free(cvlamem);  free(vlamem);

		  } /* end of vlalen > 0 */
		}  /* end of loop over rows */

		if (compressed_size != 0)
		    cratio[ii] = uncompressed_size / compressed_size;

		snprintf(tempstring,FLEN_VALUE," r=%6.2f",cratio[ii]);
		strcat(results[ii],tempstring);

		/* now we just have to compress the array of descriptors (both input and output) */
		/* and write them to the output table. */

		/* allocate memory for the compressed descriptors */
		cvlamem = malloc(datasize + (rowspertile * 16) );
		if (!cvlamem) {
		    ffpmsg("Could not allocate buffer for compressed data");
		    *status = MEMORY_ALLOCATION;
		    free(cdescript); free(cm_buffer);
		    return(*status);
		}

#if BYTESWAPPED
		/* byte swap the input and output descriptors */
		if (rm_colwidth[ii] == 16) {
		    ffswap8((double *) cdescript,  rowspertile * 2);
		} else {
		    ffswap4((int *) cdescript,  rowspertile * 2);
		}
		ffswap8((double *) outdescript,  rowspertile * 2);
#endif
		/* compress the array contain both sets of descriptors */
		compress2mem_from_mem((char *) cdescript, datasize + (rowspertile * 16),
	    		&cvlamem,  &datasize, realloc, &dlen, status);        

		free(cdescript);

		/* write the compressed descriptors to the output column */
		fits_set_tscale(outfptr, ii + 1, 1.0, 0.0, status);  /* turn off any data scaling, first */
		fits_write_descript(outfptr, ii+1, ll+1, 0, 0, status); /* First, reset the descriptor */
		fits_write_col(outfptr, TBYTE, ii + 1, ll+1, 1, dlen, cvlamem, status);
		free(cvlamem); 

		if (ll == 0) {  /* only write the ZCTYPn keyword once, while processing the first column */
			fits_make_keyn("ZCTYP", ii+1, keyname, status);

			if (compalgor[ii] == RICE_1) {
			     strcpy(keyvalue, "RICE_1");
			} else if (compalgor[ii] == GZIP_2) {
			     strcpy(keyvalue, "GZIP_2");
			} else {
			     strcpy(keyvalue, "GZIP_1");
			}

			fits_write_key(outfptr, TSTRING, keyname, keyvalue,
			"compression algorithm for column", status);
		}

	        continue;  /* jump to end of loop, to go to next column */
	    }  /* end of VLA case */

	    /* ================================================================================*/
	    /* deal with all the normal fixed-length columns here */
	    /* ================================================================================*/

	    /* allocate memory for the compressed data */
	    datasize = (size_t) (cm_colstart[ii + 1] - cm_colstart[ii]);
	    cvlamem = malloc(datasize*2);
	    tot_uncompressed_size += datasize;
	    
	    if (!cvlamem) {
                ffpmsg("Could not allocate buffer for compressed data");
                *status = MEMORY_ALLOCATION;
		free(cm_buffer);
	        return(*status);
	    }

	    if (compalgor[ii] == RICE_1) {
	        if (coltype[ii] == TSHORT) {
#if BYTESWAPPED
                    ffswap2((short *) (cm_buffer + cm_colstart[ii]),  datasize / 2); 
#endif
  	            dlen = fits_rcomp_short ((short *)(cm_buffer + cm_colstart[ii]), datasize / 2, (unsigned char *) cvlamem,
                       datasize * 2, 32);

	        } else if (coltype[ii] == TLONG) {
#if BYTESWAPPED
                    ffswap4((int *) (cm_buffer + cm_colstart[ii]),  datasize / 4); 
#endif
   	            dlen = fits_rcomp ((int *)(cm_buffer + cm_colstart[ii]), datasize / 4, (unsigned char *) cvlamem,
                       datasize * 2, 32);

	        } else if (coltype[ii] == TBYTE) {

  	            dlen = fits_rcomp_byte ((signed char *)(cm_buffer + cm_colstart[ii]), datasize, (unsigned char *) cvlamem,
                       datasize * 2, 32);
	        } else {  /* this should not happen */
                    ffpmsg(" Error: cannot compress this column type with the RICE algorthm");
		    free(cvlamem);  free(cm_buffer);
	            *status = DATA_COMPRESSION_ERR;
	            return(*status);
	        }
	    } else {
	    	/* all other cases: gzip compress the column (bytes may have been shuffled previously) */
		compress2mem_from_mem(cm_buffer + cm_colstart[ii], datasize,
	    		&cvlamem,  &datasize, realloc, &dlen, status);        
	    }

	    if (ll == 0) {  /* only write the ZCTYPn keyword once, while processing the first column */
		fits_make_keyn("ZCTYP", ii+1, keyname, status);

		if (compalgor[ii] == RICE_1) {
		     strcpy(keyvalue, "RICE_1");
		} else if (compalgor[ii] == GZIP_2) {
		     strcpy(keyvalue, "GZIP_2");
		} else {
		     strcpy(keyvalue, "GZIP_1");
		}

		fits_write_key(outfptr, TSTRING, keyname, keyvalue,
		"compression algorithm for column", status);
	    }

	    /* write the compressed data to the output column */
	    fits_set_tscale(outfptr, ii + 1, 1.0, 0.0, status);  /* turn off any data scaling, first */
	    fits_write_col(outfptr, TBYTE, ii + 1, ll+1, 1, dlen, cvlamem, status);
	    tot_compressed_size += dlen;

	    free(cvlamem);   /* don't need the compressed data any more */

            /* create diagnostic messages */
	    if (dlen != 0)
	       cratio[ii] = (float) datasize / (float) dlen;  /* compression ratio of the column */

	    snprintf(tempstring,FLEN_VALUE," r=%6.2f",cratio[ii]);
	    strcat(results[ii],tempstring);
 
          }  /* end of not a virtual column */
        }  /* end of loop over columns */

        datastart += (rowspertile * naxis1);   /* increment to start of next chunk */
        firstrow += rowspertile;  /* increment first row in next chunk */

       if (print_report) {
	  printf("\nChunk = %d\n",ll+1);
	  for (ii = 0; ii < ncols; ii++) {  
		printf("%s\n", results[ii]);
	  }
	}
	
    }  /* end of loop over chunks of the table */

    /* =================================================================================*/
    /*  all done; just clean up and return  */
    /* ================================================================================*/

    free(cm_buffer);
    fits_set_hdustruc(outfptr, status);  /* reset internal structures */
       	
    if (print_report) {

       if (tot_compressed_size != 0)
           printf("\nTotal data size (MB) %.3f -> %.3f, ratio = %.3f\n", tot_uncompressed_size/1000000., 
	     tot_compressed_size/1000000., tot_uncompressed_size/tot_compressed_size);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_uncompress_table(fitsfile *infptr, fitsfile *outfptr, int *status)

/*
  Uncompress the table that was compressed with fits_compress_table
*/
{ 
    char colcode[999];  /* column data type code character */
    char coltype[999];  /* column data type numeric code value */
    char *cm_buffer;   /* memory buffer for the transposed, Column-Major, chunk of the table */ 
    char *rm_buffer;   /* memory buffer for the original, Row-Major, chunk of the table */ 
    LONGLONG nrows, rmajor_colwidth[999], rmajor_colstart[1000], cmajor_colstart[1000];
    LONGLONG cmajor_repeat[999], rmajor_repeat[999], cmajor_bytespan[999], kk;
    LONGLONG headstart, datastart = 0, dataend, rowsremain, *descript, *qdescript = 0;
    LONGLONG rowstart, cvlalen, cvlastart, vlalen, vlastart;
    long repeat, width, vla_repeat, vla_address, rowspertile, ntile;
    int  ncols, hdutype, inttype, anynull, tstatus, zctype[999], addspace = 0, *pdescript = 0;
    char *cptr, keyname[9], tform[40];
    long  pcount, zheapptr, naxis1, naxis2, ii, jj;
    char *ptr, comm[FLEN_COMMENT], zvalue[FLEN_VALUE], *uncompressed_vla = 0, *compressed_vla;
    char card[FLEN_CARD];
    size_t dlen, fullsize, cm_size, bytepos, vlamemlen;

    /* ================================================================================== */
    /* perform initial sanity checks */
    /* ================================================================================== */
    if (*status > 0)
        return(*status);
     
    fits_get_hdu_type(infptr, &hdutype, status);
    if (hdutype != BINARY_TBL) {
        ffpmsg("This is not a binary table, so cannot uncompress it!");
        *status = NOT_BTABLE;
        return(*status);
    }

    if (fits_read_key(infptr, TLOGICAL, "ZTABLE", &tstatus, NULL, status)) {
	/* just copy the HDU if the table is not compressed */
	if (infptr != outfptr) { 
		fits_copy_hdu (infptr, outfptr, 0, status);
	}
	return(*status);
    }
 
    fits_get_num_rowsll(infptr, &nrows, status);
    fits_get_num_cols(infptr, &ncols, status);

    if ((ncols < 1)) {
	/* just copy the HDU if the table does not have  more than 0 columns */
	if (infptr != outfptr) { 
		fits_copy_hdu (infptr, outfptr, 0, status);
	}
	return(*status);
    }

    fits_read_key(infptr, TLONG, "ZTILELEN", &rowspertile, comm, status);
    if (*status > 0) {
        ffpmsg("Could not find the required ZTILELEN keyword");
        *status = DATA_DECOMPRESSION_ERR;
        return(*status);
    }

    /**** get size of the uncompressed table */
    fits_read_key(infptr, TLONG, "ZNAXIS1", &naxis1, comm, status);
    if (*status > 0) {
        ffpmsg("Could not find the required ZNAXIS1 keyword");
        *status = DATA_DECOMPRESSION_ERR;
        return(*status);
    }

    fits_read_key(infptr, TLONG, "ZNAXIS2", &naxis2, comm, status);
    if (*status > 0) {
        ffpmsg("Could not find the required ZNAXIS2 keyword");
        *status = DATA_DECOMPRESSION_ERR;
        return(*status);
    }

    /* silently ignore illegal ZTILELEN value if too large */
    if (rowspertile > naxis2) rowspertile = naxis2;

    fits_read_key(infptr, TLONG, "ZPCOUNT", &pcount, comm, status);
    if (*status > 0) {
        ffpmsg("Could not find the required ZPCOUNT keyword");
        *status = DATA_DECOMPRESSION_ERR;
        return(*status);
    }

    tstatus = 0;
    fits_read_key(infptr, TLONG, "ZHEAPPTR", &zheapptr, comm, &tstatus);
    if (tstatus > 0) {
        zheapptr = 0;  /* uncompressed table has no heap */
    }

    /* ================================================================================== */
    /* copy of the input header, then recreate the uncompressed table keywords */
    /* ================================================================================== */
    fits_copy_header(infptr, outfptr, status);

    /* reset the NAXIS1, NAXIS2. and PCOUNT keywords to the original */
    fits_read_card(outfptr, "ZNAXIS1", card, status);
    strncpy(card, "NAXIS1 ", 7);
    fits_update_card(outfptr, "NAXIS1", card, status);
    
    fits_read_card(outfptr, "ZNAXIS2", card, status);
    strncpy(card, "NAXIS2 ", 7);
    fits_update_card(outfptr, "NAXIS2", card, status);
    
    fits_read_card(outfptr, "ZPCOUNT", card, status);
    strncpy(card, "PCOUNT ", 7);
    fits_update_card(outfptr, "PCOUNT", card, status);

    fits_delete_key(outfptr, "ZTABLE", status);
    fits_delete_key(outfptr, "ZTILELEN", status);
    fits_delete_key(outfptr, "ZNAXIS1", status);
    fits_delete_key(outfptr, "ZNAXIS2", status);
    fits_delete_key(outfptr, "ZPCOUNT", status);
    tstatus = 0;
    fits_delete_key(outfptr, "CHECKSUM", &tstatus); 
    tstatus = 0;
    fits_delete_key(outfptr, "DATASUM", &tstatus); 
    /* restore the Checksum keywords, if they exist */
    tstatus = 0;
    fits_modify_name(outfptr, "ZHECKSUM", "CHECKSUM", &tstatus);
    tstatus = 0;
    fits_modify_name(outfptr, "ZDATASUM", "DATASUM", &tstatus);

    /* ================================================================================== */
    /* determine compression paramters for each column and write column-specific keywords */
    /* ================================================================================== */
    for (ii = 0; ii < ncols; ii++) {

	/* get the original column type, repeat count, and unit width */
	fits_make_keyn("ZFORM", ii+1, keyname, status);
	fits_read_key(infptr, TSTRING, keyname, tform, comm, status);

	/* restore the original TFORM value and comment */
	fits_read_card(outfptr, keyname, card, status);
	card[0] = 'T';
	keyname[0] = 'T';
	fits_update_card(outfptr, keyname, card, status);

	/* now delete the ZFORM keyword */
        keyname[0] = 'Z';
	fits_delete_key(outfptr, keyname, status);

	cptr = tform;
	while(isdigit(*cptr)) cptr++;
	colcode[ii] = *cptr; /* save the column type code */

        fits_binary_tform(tform, &inttype, &repeat, &width, status);
        coltype[ii] = inttype;

	/* deal with special cases */
	if (abs(coltype[ii]) == TBIT) { 
	        repeat = (repeat + 7) / 8 ;   /* convert from bits to bytes */
	} else if (abs(coltype[ii]) == TSTRING) {
	        width = 1;
	} else if (coltype[ii] < 0) {  /* pointer to variable length array */
	        if (colcode[ii] == 'P')
	           width = 8;  /* this is a 'P' column */
	        else
	           width = 16;  /* this is a 'Q' not a 'P' column */

                addspace += 16; /* need space for a second set of Q pointers for this column */
	}

	rmajor_repeat[ii] = repeat;

	/* width (in bytes) of each field in the row-major table */
	rmajor_colwidth[ii] = rmajor_repeat[ii] * width;

	/* construct the ZCTYPn keyword name then read the keyword */
	fits_make_keyn("ZCTYP", ii+1, keyname, status);
	tstatus = 0;
        fits_read_key(infptr, TSTRING, keyname, zvalue, NULL, &tstatus);
	if (tstatus) {
           zctype[ii] = GZIP_2;
	} else {
	   if (!strcmp(zvalue, "GZIP_2")) {
               zctype[ii] = GZIP_2;
	   } else if (!strcmp(zvalue, "GZIP_1")) {
               zctype[ii] = GZIP_1;
	   } else if (!strcmp(zvalue, "RICE_1")) {
               zctype[ii] = RICE_1;
	   } else {
	       ffpmsg("Unrecognized ZCTYPn keyword compression code:");
	       ffpmsg(zvalue);
	       *status = DATA_DECOMPRESSION_ERR;
	       return(*status);
	   }
	   
	   /* delete this keyword from the uncompressed header */
	   fits_delete_key(outfptr, keyname, status);
	}
    }

    /* rescan header keywords to reset internal table structure parameters */
    fits_set_hdustruc(outfptr, status);

    /* ================================================================================== */
    /* allocate memory for the transposed and untransposed tile of the table */
    /* ================================================================================== */

    fullsize = naxis1 * rowspertile;
    cm_size = fullsize + (addspace * rowspertile);

    cm_buffer = malloc(cm_size);
    if (!cm_buffer) {
        ffpmsg("Could not allocate buffer for transformed column-major table");
        *status = MEMORY_ALLOCATION;
        return(*status);
    }

    rm_buffer = malloc(fullsize);
    if (!rm_buffer) {
        ffpmsg("Could not allocate buffer for untransformed row-major table");
        *status = MEMORY_ALLOCATION;
        free(cm_buffer);
        return(*status);
    }

    /* ================================================================================== */
    /* Main loop over all the tiles */
    /* ================================================================================== */

    rowsremain = naxis2;
    rowstart = 1;
    ntile = 0;

    while(rowsremain) {

        /* ================================================================================== */
        /* loop over each column: read and uncompress the bytes */
        /* ================================================================================== */
        ntile++;
        rmajor_colstart[0] = 0;
        cmajor_colstart[0] = 0;
        for (ii = 0; ii < ncols; ii++) {

	    cmajor_repeat[ii] = rmajor_repeat[ii] * rowspertile;

	    /* starting offset of each field in the column-major table */
            if (coltype[ii] > 0) {  /* normal fixed length column */
	          cmajor_colstart[ii + 1] = cmajor_colstart[ii] + rmajor_colwidth[ii] * rowspertile;
	    } else { /* VLA column: reserve space for the 2nd set of Q pointers */
	          cmajor_colstart[ii + 1] = cmajor_colstart[ii] + (rmajor_colwidth[ii] + 16) * rowspertile;
	    }
	    /* length of each sequence of bytes, after sorting them in signicant order */
	    cmajor_bytespan[ii] = (rmajor_repeat[ii] * rowspertile);

	    /* starting offset of each field in the  row-major table */
	    rmajor_colstart[ii + 1] = rmajor_colstart[ii] + rmajor_colwidth[ii];

            if (rmajor_repeat[ii] > 0) { /* ignore columns with 0 elements */
	
	        /* read compressed bytes from input table */
	        fits_read_descript(infptr, ii + 1, ntile, &vla_repeat, &vla_address, status);
	
	        /* allocate memory and read in the compressed bytes */
	        ptr = malloc(vla_repeat);
	        if (!ptr) {
                   ffpmsg("Could not allocate buffer for uncompressed bytes");
                   *status = MEMORY_ALLOCATION;
                   free(rm_buffer);  free(cm_buffer);
                   return(*status);
	        }

	        fits_set_tscale(infptr, ii + 1, 1.0, 0.0, status);  /* turn off any data scaling, first */
	        fits_read_col_byt(infptr, ii + 1, ntile, 1, vla_repeat, 0, (unsigned char *) ptr, &anynull, status);
                cptr = cm_buffer + cmajor_colstart[ii];
	
		/* size in bytes of the uncompressed column of bytes */
	        fullsize = (size_t) (cmajor_colstart[ii+1] - cmajor_colstart[ii]);

	        switch (colcode[ii]) {

	        case 'I':

	          if (zctype[ii] == RICE_1) {
   	             dlen = fits_rdecomp_short((unsigned char *)ptr, vla_repeat, (unsigned short *)cptr, 
		       fullsize / 2, 32);
#if BYTESWAPPED
                     ffswap2((short *) cptr, fullsize / 2); 
#endif
	          } else { /* gunzip the data into the correct location */
	             uncompress2mem_from_mem(ptr, vla_repeat, &cptr, &fullsize, realloc, &dlen, status);        
	          }
	          break;

	        case 'J':

	          if (zctype[ii] == RICE_1) {
   	              dlen = fits_rdecomp ((unsigned char *) ptr, vla_repeat, (unsigned int *)cptr, 
		        fullsize / 4, 32);
#if BYTESWAPPED
                      ffswap4((int *) cptr,  fullsize / 4); 
#endif
	          } else { /* gunzip the data into the correct location */
	             uncompress2mem_from_mem(ptr, vla_repeat, &cptr, &fullsize, realloc, &dlen, status);        
	          }
	          break;

	        case 'B':

	          if (zctype[ii] == RICE_1) {
   	              dlen = fits_rdecomp_byte ((unsigned char *) ptr, vla_repeat, (unsigned char *)cptr, 
		        fullsize, 32);
	          } else { /* gunzip the data into the correct location */
	             uncompress2mem_from_mem(ptr, vla_repeat, &cptr, &fullsize, realloc, &dlen, status);        
	          }
	          break;

	        default: 
		  /* all variable length array columns are included in this case */
	          /* gunzip the data into the correct location in the full table buffer */
	          uncompress2mem_from_mem(ptr, vla_repeat,
	              &cptr,  &fullsize, realloc, &dlen, status);              

	        } /* end of switch block */

	        free(ptr);
	  }  /* end of rmajor_repeat > 0 */
      }  /* end of loop over columns */
      
      /* now transpose the rows and columns (from cm_buffer to rm_buffer) */
      /* move each byte, in turn, from the cm_buffer to the appropriate place in the rm_buffer */
      for (ii = 0; ii < ncols; ii++) {  /* loop over columns */
	 ptr = (char *) (cm_buffer + cmajor_colstart[ii]);  /* initialize ptr to start of the column in the cm_buffer */
         if (rmajor_repeat[ii] > 0) {  /* skip columns with zero elements */
             if (coltype[ii] > 0) {  /* normal fixed length array columns */
                 if (zctype[ii] == GZIP_2) {  /*  need to unshuffle the bytes */

	             /* recombine the byte planes for the 2-byte, 4-byte, and 8-byte numeric columns */
	             switch (colcode[ii]) {
	
		     case 'I':
		         /* get the 1st byte of each I*2 value */
	                 for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
		             cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]));  
		             for (kk = 0; kk < rmajor_repeat[ii]; kk++) {
		                 *cptr = *ptr;  /* copy 1 byte */
		                 ptr++;
		                 cptr += 2;  
			     }
			 }
		         /* get the 2nd byte of each I*2 value */
	                 for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
		            cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 1);  
		            for (kk = 0; kk < rmajor_repeat[ii]; kk++) {
		                *cptr = *ptr;  /* copy 1 byte */
		                ptr++;
		                cptr += 2;  
		            }
		         }
		         break;

		   case 'J':
		   case 'E':
		       /* get the 1st byte of each 4-byte value */
	               for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
		         cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]));  
		         for (kk = 0; kk < rmajor_repeat[ii]; kk++) {
		           *cptr = *ptr;  /* copy 1 byte */
		           ptr++;
		           cptr += 4;  
		         }
		       }
		       /* get the 2nd byte  */
	               for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
		         cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 1);  
		          for (kk = 0; kk < rmajor_repeat[ii]; kk++) {
		            *cptr = *ptr;  /* copy 1 byte */
		            ptr++;
		            cptr += 4;  
		          }
		       }
		       /* get the 3rd byte  */
	               for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
		         cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 2);  
		         for (kk = 0; kk < rmajor_repeat[ii]; kk++) {
		           *cptr = *ptr;  /* copy 1 byte */
		           ptr++;
		           cptr += 4;  
		         }
		       }
		       /* get the 4th byte  */
	               for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
		         cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 3);  
		         for (kk = 0; kk < rmajor_repeat[ii]; kk++) {
		           *cptr = *ptr;  /* copy 1 byte */
		           ptr++;
		           cptr += 4;  
		         }
		       }
		       break;

		 case 'D':
		 case 'K':
		       /* get the 1st byte of each 8-byte value */
 	              for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
		         cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]));  
		         for (kk = 0; kk < rmajor_repeat[ii]; kk++) {
		           *cptr = *ptr;  /* copy 1 byte */
		           ptr++;
		           cptr += 8;  
		         }
		       }
		       /* get the 2nd byte  */
	               for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
		         cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 1);  
		         for (kk = 0; kk < rmajor_repeat[ii]; kk++) {
		           *cptr = *ptr;  /* copy 1 byte */
		           ptr++;
		           cptr += 8;  
		         }
		       }
		       /* get the 3rd byte  */
	               for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
		         cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 2);  
		         for (kk = 0; kk < rmajor_repeat[ii]; kk++) {
		           *cptr = *ptr;  /* copy 1 byte */
		           ptr++;
		           cptr += 8;  
		         }
		       }
		       /* get the 4th byte  */
	  	       for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
		         cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 3);  
		         for (kk = 0; kk < rmajor_repeat[ii]; kk++) {
		           *cptr = *ptr;  /* copy 1 byte */
		           ptr++;
		           cptr += 8;  
		         }
		       }
		       /* get the 5th byte */
	               for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
		         cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 4);  
		         for (kk = 0; kk < rmajor_repeat[ii]; kk++) {
		           *cptr = *ptr;  /* copy 1 byte */
		           ptr++;
		           cptr += 8;  
		         }
		       }
		       /* get the 6th byte  */
	               for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
		         cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 5);  
		         for (kk = 0; kk < rmajor_repeat[ii]; kk++) {
		           *cptr = *ptr;  /* copy 1 byte */
		           ptr++;
		           cptr += 8;  
		         }
		       }
		       /* get the 7th byte  */
	               for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
		         cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 6);  
		         for (kk = 0; kk < rmajor_repeat[ii]; kk++) {
		           *cptr = *ptr;  /* copy 1 byte */
		           ptr++;
		           cptr += 8;  
		         }
		       }
		       /* get the 8th byte  */
	               for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
		         cptr = rm_buffer + (rmajor_colstart[ii] + (jj * rmajor_colstart[ncols]) + 7);  
		         for (kk = 0; kk < rmajor_repeat[ii]; kk++) {
		           *cptr = *ptr;  /* copy 1 byte */
		           ptr++;
		           cptr += 8;  
		         }
		       }
		       break;

		default: /*  should never get here */
	            ffpmsg("Error: unexpected attempt to use GZIP_2 to compress a column unsuitable data type");
		    *status = DATA_DECOMPRESSION_ERR;
                    free(rm_buffer);  free(cm_buffer);
	            return(*status);

	        }  /* end of switch  for shuffling the bytes*/

            } else {  /* not GZIP_2, don't have to shuffle bytes, so just transpose the rows and columns */

	         for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output table */
		     cptr = rm_buffer + (rmajor_colstart[ii] + jj * rmajor_colstart[ncols]);   /* addr to copy to */
		     memcpy(cptr, ptr, (size_t) rmajor_colwidth[ii]);
	 
		     ptr += (rmajor_colwidth[ii]);
		 }
	    }
        } else {  /* transpose the variable length array pointers */

              for (jj = 0; jj < rowspertile; jj++) {  /* loop over number of rows in the output uncompressed table */
	        cptr = rm_buffer + (rmajor_colstart[ii] + jj * rmajor_colstart[ncols]);   /* addr to copy to */
	        memcpy(cptr, ptr, (size_t) rmajor_colwidth[ii]);
	 
	        ptr += (rmajor_colwidth[ii]);
	      }

	      if (rmajor_colwidth[ii] == 8 ) {  /* these are P-type descriptors */
	           pdescript = (int *) (cm_buffer + cmajor_colstart[ii]);
#if BYTESWAPPED
	           ffswap4((int *) pdescript,  rowspertile * 2);  /* byte-swap the descriptor */
#endif
	      } else if (rmajor_colwidth[ii] == 16 ) {  /* these are Q-type descriptors */
	           qdescript = (LONGLONG *) (cm_buffer + cmajor_colstart[ii]);
#if BYTESWAPPED
	           ffswap8((double *) qdescript,  rowspertile * 2); /* byte-swap the descriptor */
#endif
	      } else { /* this should never happen */
	            ffpmsg("Error: Descriptor column is neither 8 nor 16 bytes wide");
                    free(rm_buffer);  free(cm_buffer);
		    *status = DATA_DECOMPRESSION_ERR;
	            return(*status);
	      }	
	      	
	      /* First, set pointer to the Q descriptors, and byte-swap them, if needed */
	      descript = (LONGLONG*) (cm_buffer + cmajor_colstart[ii] + (rmajor_colwidth[ii] * rowspertile));
#if BYTESWAPPED
	      /* byte-swap the descriptor */
	      ffswap8((double *) descript,  rowspertile * 2);
#endif

	      /* now uncompress all the individual VLAs, and */
	      /* write them to their original location in the uncompressed file */

	      for (jj = 0; jj < rowspertile; jj++)   {    /* loop over rows */
                    /* get the size and location of the compressed VLA in the compressed table */
		    cvlalen = descript[jj * 2];
		    cvlastart = descript[(jj * 2) + 1]; 
		    if (cvlalen > 0 ) {

			/* get the size and location to write the uncompressed VLA in the uncompressed table */
			if (rmajor_colwidth[ii] == 8 ) { 
			    vlalen = pdescript[jj * 2];
			    vlastart = pdescript[(jj * 2) + 1];
			} else  {
			    vlalen = qdescript[jj * 2];
			    vlastart = qdescript[(jj * 2) + 1];
			}			
			vlamemlen = (size_t) (vlalen * (-coltype[ii] / 10));  /* size of the uncompressed VLA, in bytes */

			/* allocate memory for the compressed vla */
			compressed_vla = malloc( (size_t) cvlalen);
			if (!compressed_vla) {
			    ffpmsg("Could not allocate buffer for compressed VLA");
			    free(rm_buffer);  free(cm_buffer);
			    *status = MEMORY_ALLOCATION;
			    return(*status);
			}

			/* read the compressed VLA from the heap in the input compressed table */
			bytepos = (size_t) ((infptr->Fptr)->datastart + (infptr->Fptr)->heapstart + cvlastart);
			ffmbyt(infptr, bytepos, REPORT_EOF, status);
			ffgbyt(infptr, cvlalen, compressed_vla, status);  /* read the bytes */
			/* if the VLA couldn't be compressed, just copy it directly to the output uncompressed table */
			if (cvlalen   == vlamemlen ) {
			    bytepos = (size_t) ((outfptr->Fptr)->datastart + (outfptr->Fptr)->heapstart + vlastart);
			    ffmbyt(outfptr, bytepos, IGNORE_EOF, status);
			    ffpbyt(outfptr, cvlalen, compressed_vla, status);  /* write the bytes */
			} else {  /* uncompress the VLA  */
		  
			    /* allocate memory for the uncompressed VLA */
			    uncompressed_vla =  malloc(vlamemlen);
			    if (!uncompressed_vla) {
				ffpmsg("Could not allocate buffer for uncompressed VLA");
				*status = MEMORY_ALLOCATION;
			        free(compressed_vla); free(rm_buffer);  free(cm_buffer);
				return(*status);
			    }
			    /* uncompress the VLA with the appropriate algorithm */
			    if (zctype[ii] == RICE_1) {

				if (-coltype[ii] == TSHORT) {
				    dlen = fits_rdecomp_short((unsigned char *) compressed_vla, (int) cvlalen, (unsigned short *)uncompressed_vla, 
					(int) vlalen, 32);
#if BYTESWAPPED
				   ffswap2((short *) uncompressed_vla, (long) vlalen); 
#endif
				} else if (-coltype[ii] == TLONG) {
				    dlen = fits_rdecomp((unsigned char *) compressed_vla, (int) cvlalen, (unsigned int *)uncompressed_vla, 
					(int) vlalen, 32);
#if BYTESWAPPED
				   ffswap4((int *) uncompressed_vla, (long) vlalen); 
#endif
 				} else if (-coltype[ii] == TBYTE) {
				    dlen = fits_rdecomp_byte((unsigned char *) compressed_vla, (int) cvlalen, (unsigned char *) uncompressed_vla, 
					(int) vlalen, 32);
				} else {
				    /* this should not happen */
				    ffpmsg(" Error: cannot uncompress this column type with the RICE algorthm");

				    *status = DATA_DECOMPRESSION_ERR;
			            free(uncompressed_vla); free(compressed_vla); free(rm_buffer);  free(cm_buffer);
				    return(*status);
				}  

			    } else if (zctype[ii] == GZIP_1 || zctype[ii] == GZIP_2){  

			       /*: gzip uncompress the array of bytes */
			       uncompress2mem_from_mem( compressed_vla, (size_t) cvlalen, &uncompressed_vla, &vlamemlen, realloc, &vlamemlen, status);

			       if (zctype[ii] == GZIP_2 ) {
				  /* unshuffle the bytes after ungzipping them */
				  if ( (int) (-coltype[ii] / 10) == 2) {
				    fits_unshuffle_2bytes((char *) uncompressed_vla, vlalen, status);
				  } else if ( (int) (-coltype[ii] / 10) == 4) {
				    fits_unshuffle_4bytes((char *) uncompressed_vla, vlalen, status);
				  } else if ( (int) (-coltype[ii] / 10) == 8) {
				    fits_unshuffle_8bytes((char *) uncompressed_vla, vlalen, status);
				  }
			       }

			    } else {
				/* this should not happen */
				ffpmsg(" Error: unknown compression algorthm");
			        free(uncompressed_vla); free(compressed_vla); free(rm_buffer);  free(cm_buffer);
				*status = DATA_COMPRESSION_ERR;
				return(*status);
			    }  		     

			    bytepos = (size_t) ((outfptr->Fptr)->datastart + (outfptr->Fptr)->heapstart + vlastart);
			    ffmbyt(outfptr, bytepos, IGNORE_EOF, status);
			    ffpbyt(outfptr, vlamemlen, uncompressed_vla, status);  /* write the bytes */
			    
			     free(uncompressed_vla);
			}  /* end of uncompress VLA */

		        free(compressed_vla);

		  } /* end of vlalen > 0 */
		} /* end of loop over rowspertile */

              } /* end of variable length array section*/
           }  /* end of if column repeat > 0 */
        }  /* end of ncols loop */

        /* copy the buffer of data to the output data unit */

        if (datastart == 0) fits_get_hduaddrll(outfptr, &headstart, &datastart, &dataend, status);        

        ffmbyt(outfptr, datastart, 1, status);
        ffpbyt(outfptr, naxis1 * rowspertile, rm_buffer, status);

	/* increment pointers for next tile */
	rowstart += rowspertile;
        rowsremain -= rowspertile;
	datastart += (naxis1 * rowspertile);
	if (rowspertile > rowsremain) rowspertile = (long) rowsremain;

    }  /* end of while rows still remain */

    free(rm_buffer);
    free(cm_buffer);
	
    /* reset internal table structure parameters */
    fits_set_hdustruc(outfptr, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
static int fits_shuffle_2bytes(char *heap, LONGLONG length, int *status)

/* shuffle the bytes in an array of 2-byte integers in the heap */

{
    LONGLONG ii;
    char *ptr, *cptr, *heapptr;
    
    ptr = malloc((size_t) (length * 2));
    heapptr = heap;
    cptr = ptr;
    
    for (ii = 0; ii < length; ii++) {
       *cptr = *heapptr;
       heapptr++;
       *(cptr + length) = *heapptr;
       heapptr++;
       cptr++;
    }
         
    memcpy(heap, ptr, (size_t) (length * 2));
    free(ptr);
    return(*status);
}
/*--------------------------------------------------------------------------*/
static int fits_shuffle_4bytes(char *heap, LONGLONG length, int *status)

/* shuffle the bytes in an array of 4-byte integers or floats  */

{
    LONGLONG ii;
    char *ptr, *cptr, *heapptr;
    
    ptr = malloc((size_t) (length * 4));
    if (!ptr) {
      ffpmsg("malloc failed\n");
      return(*status);
    }

    heapptr = heap;
    cptr = ptr;
 
    for (ii = 0; ii < length; ii++) {
       *cptr = *heapptr;
       heapptr++;
       *(cptr + length) = *heapptr;
       heapptr++;
       *(cptr + (length * 2)) = *heapptr;
       heapptr++;
       *(cptr + (length * 3)) = *heapptr;
       heapptr++;
       cptr++;
    }
        
    memcpy(heap, ptr, (size_t) (length * 4));
    free(ptr);

    return(*status);
}
/*--------------------------------------------------------------------------*/
static int fits_shuffle_8bytes(char *heap, LONGLONG length, int *status)

/* shuffle the bytes in an array of 8-byte integers or doubles in the heap */

{
    LONGLONG ii;
    char *ptr, *cptr, *heapptr;
    
    ptr = calloc(1, (size_t) (length * 8));
    heapptr = heap;
    
/* for some bizarre reason this loop fails to compile under OpenSolaris using
   the proprietary SunStudioExpress C compiler;  use the following equivalent
   loop instead.
   
    cptr = ptr;

    for (ii = 0; ii < length; ii++) {
       *cptr = *heapptr;
       heapptr++;
       *(cptr + length) = *heapptr;
       heapptr++;
       *(cptr + (length * 2)) = *heapptr;
       heapptr++;
       *(cptr + (length * 3)) = *heapptr;
       heapptr++;
       *(cptr + (length * 4)) = *heapptr;
       heapptr++;
       *(cptr + (length * 5)) = *heapptr;
       heapptr++;
       *(cptr + (length * 6)) = *heapptr;
       heapptr++;
       *(cptr + (length * 7)) = *heapptr;
       heapptr++;
       cptr++;
     }
*/
     for (ii = 0; ii < length; ii++) {
        cptr = ptr + ii;

        *cptr = *heapptr;

        heapptr++;
        cptr += length;
        *cptr = *heapptr;

        heapptr++;
        cptr += length;
        *cptr = *heapptr;

        heapptr++;
        cptr += length;
        *cptr = *heapptr;

        heapptr++;
        cptr += length;
        *cptr = *heapptr;

        heapptr++;
        cptr += length;
        *cptr = *heapptr;

        heapptr++;
        cptr += length;
        *cptr = *heapptr;

        heapptr++;
        cptr += length;
        *cptr = *heapptr;

        heapptr++;
     }
        
    memcpy(heap, ptr, (size_t) (length * 8));
    free(ptr);
 
    return(*status);
}
/*--------------------------------------------------------------------------*/
static int fits_unshuffle_2bytes(char *heap, LONGLONG length, int *status)

/* unshuffle the bytes in an array of 2-byte integers */

{
    LONGLONG ii;
    char *ptr, *cptr, *heapptr;
    
    ptr = malloc((size_t) (length * 2));
    heapptr = heap + (2 * length) - 1;
    cptr = ptr + (2 * length) - 1;
    
    for (ii = 0; ii < length; ii++) {
       *cptr = *heapptr;
       cptr--;
       *cptr = *(heapptr - length);
       cptr--;
       heapptr--;
    }
         
    memcpy(heap, ptr, (size_t) (length * 2));
    free(ptr);
    return(*status);
}
/*--------------------------------------------------------------------------*/
static int fits_unshuffle_4bytes(char *heap, LONGLONG length, int *status)

/* unshuffle the bytes in an array of 4-byte integers or floats */

{
    LONGLONG ii;
    char *ptr, *cptr, *heapptr;
    
    ptr = malloc((size_t) (length * 4));
    heapptr = heap + (4 * length) -1;
    cptr = ptr + (4 * length) -1;
 
    for (ii = 0; ii < length; ii++) {
       *cptr = *heapptr;
       cptr--;
       *cptr = *(heapptr - length);
       cptr--;
       *cptr = *(heapptr - (2 * length));
       cptr--;
       *cptr = *(heapptr - (3 * length));
       cptr--;
       heapptr--;
    }
        
    memcpy(heap, ptr, (size_t) (length * 4));
    free(ptr);
    return(*status);
}
/*--------------------------------------------------------------------------*/
static int fits_unshuffle_8bytes(char *heap, LONGLONG length, int *status)

/* unshuffle the bytes in an array of 8-byte integers or doubles */

{
    LONGLONG ii;
    char *ptr, *cptr, *heapptr;
    
    ptr = malloc((size_t) (length * 8));
    heapptr = heap + (8 * length) - 1;
    cptr = ptr + (8 * length)  -1;
    
    for (ii = 0; ii < length; ii++) {
       *cptr = *heapptr;
       cptr--;
       *cptr = *(heapptr - length);
       cptr--;
       *cptr = *(heapptr - (2 * length));
       cptr--;
       *cptr = *(heapptr - (3 * length));
       cptr--;
       *cptr = *(heapptr - (4 * length));
       cptr--;
       *cptr = *(heapptr - (5 * length));
       cptr--;
       *cptr = *(heapptr - (6 * length));
       cptr--;
       *cptr = *(heapptr - (7 * length));
       cptr--;
       heapptr--;
    }
       
    memcpy(heap, ptr, (size_t) (length * 8));
    free(ptr);
    return(*status);
}
/*--------------------------------------------------------------------------*/
static int fits_int_to_longlong_inplace(int *intarray, long length, int *status)

/* convert the input array of 32-bit integers into an array of 64-bit integers,
in place. This will overwrite the input array with the new longer array starting
at the same memory location.  

Note that aliasing the same memory location with pointers of different datatypes is
not allowed in strict ANSI C99, however it is  used here for efficency. In principle,
one could simply copy the input array in reverse order to the output array,
but this only works if the compiler performs the operation in strict order.  Certain
compiler optimization techniques may vioate this assumption.  Therefore, we first
copy a section of the input array to a temporary intermediate array, before copying
the longer datatype values back to the original array.
*/

{
    LONGLONG *longlongarray, *aliasarray;
    long ii, ntodo, firstelem, nmax = 10000;
    
    if (*status > 0) 
        return(*status);

    ntodo = nmax;
    if (length < nmax) ntodo = length;
    
    firstelem = length - ntodo;  /* first element to be converted */
    
    longlongarray = (LONGLONG *) malloc(ntodo * sizeof(LONGLONG));
    
    if (longlongarray == NULL)
    {
	ffpmsg("Out of memory. (fits_int_to_longlong_inplace)");
	return (*status = MEMORY_ALLOCATION);
    }

    aliasarray = (LONGLONG *) intarray; /* alias pointer to the input array */

    while (ntodo > 0) {
    
	/* do datatype conversion into temp array */
        for (ii = 0; ii < ntodo; ii++) { 
	    longlongarray[ii] = intarray[ii + firstelem];
        }

        /* copy temp array back to alias */
        memcpy(&(aliasarray[firstelem]), longlongarray, ntodo * 8);
	
        if (firstelem == 0) {  /* we are all done */
	    ntodo = 0;   
	} else {  /* recalculate ntodo and firstelem for next loop */
	    if (firstelem > nmax) {
	        firstelem -= nmax;
	    } else {
	        ntodo = firstelem;
	        firstelem = 0;
	    }
	}
    }

    free(longlongarray);
    return(*status);
}
/*--------------------------------------------------------------------------*/
static int fits_short_to_int_inplace(short *shortarray, long length, int *status)

/* convert the input array of 16-bit integers into an array of 32-bit integers,
in place. This will overwrite the input array with the new longer array starting
at the same memory location.  

Note that aliasing the same memory location with pointers of different datatypes is
not allowed in strict ANSI C99, however it is  used here for efficency. In principle,
one could simply copy the input array in reverse order to the output array,
but this only works if the compiler performs the operation in strict order.  Certain
compiler optimization techniques may vioate this assumption.  Therefore, we first
copy a section of the input array to a temporary intermediate array, before copying
the longer datatype values back to the original array.
*/

{
    int *intarray, *aliasarray;
    long ii, ntodo, firstelem, nmax = 10000;
    
    if (*status > 0) 
        return(*status);

    ntodo = nmax;
    if (length < nmax) ntodo = length;
    
    firstelem = length - ntodo;  /* first element to be converted */
    
    intarray = (int *) malloc(ntodo * sizeof(int));
    
    if (intarray == NULL)
    {
	ffpmsg("Out of memory. (fits_short_to_int_inplace)");
	return (*status = MEMORY_ALLOCATION);
    }

    aliasarray = (int *) shortarray; /* alias pointer to the input array */

    while (ntodo > 0) {
    
	/* do datatype conversion into temp array */
        for (ii = 0; ii < ntodo; ii++) { 
	    intarray[ii] = shortarray[ii + firstelem];
        }

        /* copy temp array back to alias */
        memcpy(&(aliasarray[firstelem]), intarray, ntodo * 4);
	
        if (firstelem == 0) {  /* we are all done */
	    ntodo = 0;   
	} else {  /* recalculate ntodo and firstelem for next loop */
	    if (firstelem > nmax) {
	        firstelem -= nmax;
	    } else {
	        ntodo = firstelem;
	        firstelem = 0;
	    }
	}
    }

    free(intarray);
    return(*status);
}
/*--------------------------------------------------------------------------*/
static int fits_ushort_to_int_inplace(unsigned short *ushortarray, long length, 
                                      int *status)

/* convert the input array of 16-bit unsigned integers into an array of 32-bit integers,
in place. This will overwrite the input array with the new longer array starting
at the same memory location.  

Note that aliasing the same memory location with pointers of different datatypes is
not allowed in strict ANSI C99, however it is  used here for efficency. In principle,
one could simply copy the input array in reverse order to the output array,
but this only works if the compiler performs the operation in strict order.  Certain
compiler optimization techniques may vioate this assumption.  Therefore, we first
copy a section of the input array to a temporary intermediate array, before copying
the longer datatype values back to the original array.
*/

{
    int *intarray, *aliasarray;
    long ii, ntodo, firstelem, nmax = 10000;
    
    if (*status > 0) 
        return(*status);

    ntodo = nmax;
    if (length < nmax) ntodo = length;
    
    firstelem = length - ntodo;  /* first element to be converted */
    
    intarray = (int *) malloc(ntodo * sizeof(int));
    
    if (intarray == NULL)
    {
	ffpmsg("Out of memory. (fits_ushort_to_int_inplace)");
	return (*status = MEMORY_ALLOCATION);
    }

    aliasarray = (int *) ushortarray; /* alias pointer to the input array */

    while (ntodo > 0) {
    
	/* do datatype conversion into temp array */
        for (ii = 0; ii < ntodo; ii++) { 
	    intarray[ii] = ushortarray[ii + firstelem];
        }

        /* copy temp array back to alias */
        memcpy(&(aliasarray[firstelem]), intarray, ntodo * 4);
	
        if (firstelem == 0) {  /* we are all done */
	    ntodo = 0;   
	} else {  /* recalculate ntodo and firstelem for next loop */
	    if (firstelem > nmax) {
	        firstelem -= nmax;
	    } else {
	        ntodo = firstelem;
	        firstelem = 0;
	    }
	}
    }

    free(intarray);
    return(*status);
}
/*--------------------------------------------------------------------------*/
static int fits_ubyte_to_int_inplace(unsigned char *ubytearray, long length, 
                                      int *status)

/* convert the input array of 8-bit unsigned integers into an array of 32-bit integers,
in place. This will overwrite the input array with the new longer array starting
at the same memory location.  

Note that aliasing the same memory location with pointers of different datatypes is
not allowed in strict ANSI C99, however it is  used here for efficency. In principle,
one could simply copy the input array in reverse order to the output array,
but this only works if the compiler performs the operation in strict order.  Certain
compiler optimization techniques may vioate this assumption.  Therefore, we first
copy a section of the input array to a temporary intermediate array, before copying
the longer datatype values back to the original array.
*/

{
    int *intarray, *aliasarray;
    long ii, ntodo, firstelem, nmax = 10000;
    
    if (*status > 0) 
        return(*status);

    ntodo = nmax;
    if (length < nmax) ntodo = length;
    
    firstelem = length - ntodo;  /* first element to be converted */
    
    intarray = (int *) malloc(ntodo * sizeof(int));
    
    if (intarray == NULL)
    {
	ffpmsg("Out of memory. (fits_ubyte_to_int_inplace)");
	return (*status = MEMORY_ALLOCATION);
    }

    aliasarray = (int *) ubytearray; /* alias pointer to the input array */

    while (ntodo > 0) {
    
	/* do datatype conversion into temp array */
        for (ii = 0; ii < ntodo; ii++) { 
	    intarray[ii] = ubytearray[ii + firstelem];
        }

        /* copy temp array back to alias */
        memcpy(&(aliasarray[firstelem]), intarray, ntodo * 4);
	
        if (firstelem == 0) {  /* we are all done */
	    ntodo = 0;   
	} else {  /* recalculate ntodo and firstelem for next loop */
	    if (firstelem > nmax) {
	        firstelem -= nmax;
	    } else {
	        ntodo = firstelem;
	        firstelem = 0;
	    }
	}
    }

    free(intarray);
    return(*status);
}
/*--------------------------------------------------------------------------*/
static int fits_sbyte_to_int_inplace(signed char *sbytearray, long length, 
                                      int *status)

/* convert the input array of 8-bit signed integers into an array of 32-bit integers,
in place. This will overwrite the input array with the new longer array starting
at the same memory location.  

Note that aliasing the same memory location with pointers of different datatypes is
not allowed in strict ANSI C99, however it is  used here for efficency. In principle,
one could simply copy the input array in reverse order to the output array,
but this only works if the compiler performs the operation in strict order.  Certain
compiler optimization techniques may vioate this assumption.  Therefore, we first
copy a section of the input array to a temporary intermediate array, before copying
the longer datatype values back to the original array.
*/

/*
!!!!!!!!!!!!!!!!!
NOTE THAT THIS IS A SPECIALIZED ROUTINE THAT ADDS AN OFFSET OF 128 TO THE ARRAY VALUES
!!!!!!!!!!!!!!!!!
*/

{
    int *intarray, *aliasarray;
    long ii, ntodo, firstelem, nmax = 10000;
    
    if (*status > 0) 
        return(*status);

    ntodo = nmax;
    if (length < nmax) ntodo = length;
    
    firstelem = length - ntodo;  /* first element to be converted */
    
    intarray = (int *) malloc(ntodo * sizeof(int));
    
    if (intarray == NULL)
    {
	ffpmsg("Out of memory. (fits_sbyte_to_int_inplace)");
	return (*status = MEMORY_ALLOCATION);
    }

    aliasarray = (int *) sbytearray; /* alias pointer to the input array */

    while (ntodo > 0) {
    
	/* do datatype conversion into temp array */
        for (ii = 0; ii < ntodo; ii++) { 
	    intarray[ii] = sbytearray[ii + firstelem] + 128;  /* !! Note the offset !! */
        }

        /* copy temp array back to alias */
        memcpy(&(aliasarray[firstelem]), intarray, ntodo * 4);
	
        if (firstelem == 0) {  /* we are all done */
	    ntodo = 0;   
	} else {  /* recalculate ntodo and firstelem for next loop */
	    if (firstelem > nmax) {
	        firstelem -= nmax;
	    } else {
	        ntodo = firstelem;
	        firstelem = 0;
	    }
	}
    }

    free(intarray);
    return(*status);
}
cfitsio/imcopy.c0000644000225700000360000002223013246025103013443 0ustar  cagordonlhea#include 
#include 
#include 
#include "fitsio.h"

int main(int argc, char *argv[])
{
    fitsfile *infptr, *outfptr;   /* FITS file pointers defined in fitsio.h */
    int status = 0, tstatus, ii = 1, iteration = 0, single = 0, hdupos;
    int hdutype, bitpix, bytepix, naxis = 0, nkeys, datatype = 0, anynul;
    long naxes[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1};
    long first, totpix = 0, npix;
    double *array, bscale = 1.0, bzero = 0.0, nulval = 0.;
    char card[81];

    if (argc != 3)
    {
 printf("\n");
 printf("Usage:  imcopy inputImage outputImage[compress]\n");
 printf("\n");
 printf("Copy an input image to an output image, optionally compressing\n");
 printf("or uncompressing the image in the process.  If the [compress]\n");
 printf("qualifier is appended to the output file name then the input image\n");
 printf("will be compressed using the tile-compressed format.  In this format,\n");
 printf("the image is divided into rectangular tiles and each tile of pixels\n");
 printf("is compressed and stored in a variable-length row of a binary table.\n");
 printf("If the [compress] qualifier is omitted, and the input image is\n");
 printf("in tile-compressed format, then the output image will be uncompressed.\n");
 printf("\n");
 printf("If an extension name or number is appended to the input file name, \n");
 printf("enclosed in square brackets, then only that single extension will be\n");
 printf("copied to the output file.  Otherwise, every extension in the input file\n");
 printf("will be processed in turn and copied to the output file.\n");
 printf("\n");
 printf("Examples:\n");
 printf("\n");
 printf("1)  imcopy image.fit 'cimage.fit[compress]'\n");
 printf("\n");
 printf("    This compresses the input image using the default parameters, i.e.,\n");
 printf("    using the Rice compression algorithm and using row by row tiles.\n");
 printf("\n");
 printf("2)  imcopy cimage.fit image2.fit\n");
 printf("\n");
 printf("    This uncompresses the image created in the first example.\n");
 printf("    image2.fit should be identical to image.fit if the image\n");
 printf("    has an integer datatype.  There will be small differences\n");
 printf("    in the pixel values if it is a floating point image.\n");
 printf("\n");
 printf("3)  imcopy image.fit 'cimage.fit[compress GZIP 100,100;q 16]'\n");
 printf("\n");
 printf("    This compresses the input image using the following parameters:\n");
 printf("         GZIP compression algorithm;\n");
 printf("         100 X 100 pixel compression tiles;\n");
 printf("         quantization level = 16 (only used with floating point images)\n");
 printf("\n");
 printf("The full syntax of the compression qualifier is:\n");
 printf("    [compress ALGORITHM TDIM1,TDIM2,...; q QLEVEL s SCALE]\n");
 printf("where the allowed ALGORITHM values are:\n");
 printf("      Rice, HCOMPRESS, HSCOMPRESS, GZIP, or PLIO. \n");
 printf("       (HSCOMPRESS is a variant of HCOMPRESS in which a small\n");
 printf("        amount of smoothing is applied to the uncompressed image\n");
 printf("        to help suppress blocky compression artifacts in the image\n");
 printf("        when using large values for the 'scale' parameter).\n");
 printf("TDIMn is the size of the compression tile in each dimension,\n");
 printf("\n");
 printf("QLEVEL specifies the quantization level when converting a floating\n");
 printf("point image into integers, prior to compressing the image.  The\n");
 printf("default value = 16, which means the image will be quantized into\n");
 printf("integer levels that are spaced at intervals of sigma/16., where \n");
 printf("sigma is the estimated noise level in background areas of the image.\n");
 printf("If QLEVEL is negative, this means use the absolute value for the\n");
 printf("quantization spacing (e.g. 'q -0.005' means quantize the floating\n");
 printf("point image such that the scaled integers represent steps of 0.005\n");
 printf("in the original image).\n");
 printf("\n");
 printf("SCALE is the integer scale factor that only applies to the HCOMPRESS\n");
 printf("algorithm.  The default value SCALE = 0 forces the image to be\n");
 printf("losslessly compressed; Greater amounts of lossy compression (resulting\n");
 printf("in smaller compressed files) can be specified with larger SCALE values.\n");
 printf("\n");
 printf("\n");
 printf("Note that it may be necessary to enclose the file names\n");
 printf("in single quote characters on the Unix command line.\n");
      return(0);
    }

    /* Open the input file and create output file */
    fits_open_file(&infptr, argv[1], READONLY, &status);
    fits_create_file(&outfptr, argv[2], &status);

    if (status != 0) {    
        fits_report_error(stderr, status);
        return(status);
    }

    fits_get_hdu_num(infptr, &hdupos);  /* Get the current HDU position */

    /* Copy only a single HDU if a specific extension was given */ 
    if (hdupos != 1 || strchr(argv[1], '[')) single = 1;

    for (; !status; hdupos++)  /* Main loop through each extension */
    {

      fits_get_hdu_type(infptr, &hdutype, &status);

      if (hdutype == IMAGE_HDU) {

          /* get image dimensions and total number of pixels in image */
          for (ii = 0; ii < 9; ii++)
              naxes[ii] = 1;

          fits_get_img_param(infptr, 9, &bitpix, &naxis, naxes, &status);

          totpix = naxes[0] * naxes[1] * naxes[2] * naxes[3] * naxes[4]
             * naxes[5] * naxes[6] * naxes[7] * naxes[8];
      }

      if (hdutype != IMAGE_HDU || naxis == 0 || totpix == 0) { 

          /* just copy tables and null images */
          fits_copy_hdu(infptr, outfptr, 0, &status);

      } else {

          /* Explicitly create new image, to support compression */
          fits_create_img(outfptr, bitpix, naxis, naxes, &status);
          if (status) {
                 fits_report_error(stderr, status);
                 return(status);
          }

          if (fits_is_compressed_image(outfptr, &status)) {
              /* write default EXTNAME keyword if it doesn't already exist */
	      tstatus = 0;
              fits_read_card(infptr, "EXTNAME", card, &tstatus);
	      if (tstatus) {
	         strcpy(card, "EXTNAME = 'COMPRESSED_IMAGE'   / name of this binary table extension");
	         fits_write_record(outfptr, card, &status);
	      }
          }
	  	    
          /* copy all the user keywords (not the structural keywords) */
          fits_get_hdrspace(infptr, &nkeys, NULL, &status); 

          for (ii = 1; ii <= nkeys; ii++) {
              fits_read_record(infptr, ii, card, &status);
              if (fits_get_keyclass(card) > TYP_CMPRS_KEY)
                  fits_write_record(outfptr, card, &status);
          }

              /* delete default EXTNAME keyword if it exists */
/*
          if (!fits_is_compressed_image(outfptr, &status)) {
	      tstatus = 0;
              fits_read_key(outfptr, TSTRING, "EXTNAME", card, NULL, &tstatus);
	      if (!tstatus) {
	         if (strcmp(card, "COMPRESSED_IMAGE") == 0)
	            fits_delete_key(outfptr, "EXTNAME", &status);
	      }
          }
*/
	  
          switch(bitpix) {
              case BYTE_IMG:
                  datatype = TBYTE;
                  break;
              case SHORT_IMG:
                  datatype = TSHORT;
                  break;
              case LONG_IMG:
                  datatype = TINT;
                  break;
              case FLOAT_IMG:
                  datatype = TFLOAT;
                  break;
              case DOUBLE_IMG:
                  datatype = TDOUBLE;
                  break;
          }

          bytepix = abs(bitpix) / 8;

          npix = totpix;
          iteration = 0;

          /* try to allocate memory for the entire image */
          /* use double type to force memory alignment */
          array = (double *) calloc(npix, bytepix);

          /* if allocation failed, divide size by 2 and try again */
          while (!array && iteration < 10)  {
              iteration++;
              npix = npix / 2;
              array = (double *) calloc(npix, bytepix);
          }

          if (!array)  {
              printf("Memory allocation error\n");
              return(0);
          }

          /* turn off any scaling so that we copy the raw pixel values */
          fits_set_bscale(infptr,  bscale, bzero, &status);
          fits_set_bscale(outfptr, bscale, bzero, &status);

          first = 1;
          while (totpix > 0 && !status)
          {
             /* read all or part of image then write it back to the output file */
             fits_read_img(infptr, datatype, first, npix, 
                     &nulval, array, &anynul, &status);

             fits_write_img(outfptr, datatype, first, npix, array, &status);
             totpix = totpix - npix;
             first  = first  + npix;
          }
          free(array);
      }

      if (single) break;  /* quit if only copying a single HDU */
      fits_movrel_hdu(infptr, 1, NULL, &status);  /* try to move to next HDU */
    }

    if (status == END_OF_FILE)  status = 0; /* Reset after normal error */

    fits_close_file(outfptr,  &status);
    fits_close_file(infptr, &status);

    /* if error occurred, print out error message */
    if (status)
       fits_report_error(stderr, status);
    return(status);
}
cfitsio/install-sh0000755000225700000360000001272113246025103014007 0ustar  cagordonlhea#! /bin/sh
#
# install - install a program, script, or datafile
# This comes from X11R5 (mit/util/scripts/install.sh).
#
# Copyright 1991 by the Massachusetts Institute of Technology
#
# Permission to use, copy, modify, distribute, and sell this software and its
# documentation for any purpose is hereby granted without fee, provided that
# the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation, and that the name of M.I.T. not be used in advertising or
# publicity pertaining to distribution of the software without specific,
# written prior permission.  M.I.T. makes no representations about the
# suitability of this software for any purpose.  It is provided "as is"
# without express or implied warranty.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.  It can only install one file at a time, a restriction
# shared with many OS's install programs.


# set DOITPROG to echo to test this script

# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"


# put in absolute paths if you don't have them in your path; or use env. vars.

mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"

transformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""

while [ x"$1" != x ]; do
    case $1 in
	-c) instcmd="$cpprog"
	    shift
	    continue;;

	-d) dir_arg=true
	    shift
	    continue;;

	-m) chmodcmd="$chmodprog $2"
	    shift
	    shift
	    continue;;

	-o) chowncmd="$chownprog $2"
	    shift
	    shift
	    continue;;

	-g) chgrpcmd="$chgrpprog $2"
	    shift
	    shift
	    continue;;

	-s) stripcmd="$stripprog"
	    shift
	    continue;;

	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
	    shift
	    continue;;

	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
	    shift
	    continue;;

	*)  if [ x"$src" = x ]
	    then
		src=$1
	    else
		# this colon is to work around a 386BSD /bin/sh bug
		:
		dst=$1
	    fi
	    shift
	    continue;;
    esac
done

if [ x"$src" = x ]
then
	echo "install:	no input file specified"
	exit 1
else
	true
fi

if [ x"$dir_arg" != x ]; then
	dst=$src
	src=""
	
	if [ -d $dst ]; then
		instcmd=:
	else
		instcmd=mkdir
	fi
else

# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad 
# if $src (and thus $dsttmp) contains '*'.

	if [ -f $src -o -d $src ]
	then
		true
	else
		echo "install:  $src does not exist"
		exit 1
	fi
	
	if [ x"$dst" = x ]
	then
		echo "install:	no destination specified"
		exit 1
	else
		true
	fi

# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic

	if [ -d $dst ]
	then
		dst="$dst"/`basename $src`
	else
		true
	fi
fi

## this sed command emulates the dirname command
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`

# Make sure that the destination directory exists.
#  this part is taken from Noah Friedman's mkinstalldirs script

# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='	
'
IFS="${IFS-${defaultIFS}}"

oIFS="${IFS}"
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS="${oIFS}"

pathcomp=''

while [ $# -ne 0 ] ; do
	pathcomp="${pathcomp}${1}"
	shift

	if [ ! -d "${pathcomp}" ] ;
        then
		$mkdirprog "${pathcomp}"
	else
		true
	fi

	pathcomp="${pathcomp}/"
done
fi

if [ x"$dir_arg" != x ]
then
	$doit $instcmd $dst &&

	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
else

# If we're going to rename the final executable, determine the name now.

	if [ x"$transformarg" = x ] 
	then
		dstfile=`basename $dst`
	else
		dstfile=`basename $dst $transformbasename | 
			sed $transformarg`$transformbasename
	fi

# don't allow the sed command to completely eliminate the filename

	if [ x"$dstfile" = x ] 
	then
		dstfile=`basename $dst`
	else
		true
	fi

# Make a temp file name in the proper directory.

	dsttmp=$dstdir/#inst.$$#

# Move or copy the file name to the temp name

	$doit $instcmd $src $dsttmp &&

	trap "rm -f ${dsttmp}" 0 &&

# and set any options; do chmod last to preserve setuid bits

# If any of these fail, we abort the whole thing.  If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.

	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&

# Now rename the file to the real destination.

	$doit $rmcmd -f $dstdir/$dstfile &&
	$doit $mvcmd $dsttmp $dstdir/$dstfile 

fi &&


exit 0
cfitsio/iraffits.c0000644000225700000360000016043513246025103013764 0ustar  cagordonlhea/*------------------------------------------------------------------------*/
/*                                                                        */
/*  These routines have been modified by William Pence for use by CFITSIO */
/*        The original files were provided by Doug Mink                   */
/*------------------------------------------------------------------------*/

/* File imhfile.c
 * August 6, 1998
 * By Doug Mink, based on Mike VanHilst's readiraf.c

 * Module:      imhfile.c (IRAF .imh image file reading and writing)
 * Purpose:     Read and write IRAF image files (and translate headers)
 * Subroutine:  irafrhead (filename, lfhead, fitsheader, lihead)
 *              Read IRAF image header
 * Subroutine:  irafrimage (fitsheader)
 *              Read IRAF image pixels (call after irafrhead)
 * Subroutine:	same_path (pixname, hdrname)
 *		Put filename and header path together
 * Subroutine:	iraf2fits (hdrname, irafheader, nbiraf, nbfits)
 *		Convert IRAF image header to FITS image header
 * Subroutine:  irafgeti4 (irafheader, offset)
 *		Get 4-byte integer from arbitrary part of IRAF header
 * Subroutine:  irafgetc2 (irafheader, offset)
 *		Get character string from arbitrary part of IRAF v.1 header
 * Subroutine:  irafgetc (irafheader, offset)
 *		Get character string from arbitrary part of IRAF header
 * Subroutine:  iraf2str (irafstring, nchar)
 * 		Convert 2-byte/char IRAF string to 1-byte/char string
 * Subroutine:	irafswap (bitpix,string,nbytes)
 *		Swap bytes in string in place, with FITS bits/pixel code
 * Subroutine:	irafswap2 (string,nbytes)
 *		Swap bytes in string in place
 * Subroutine	irafswap4 (string,nbytes)
 *		Reverse bytes of Integer*4 or Real*4 vector in place
 * Subroutine	irafswap8 (string,nbytes)
 *		Reverse bytes of Real*8 vector in place


 * Copyright:   2000 Smithsonian Astrophysical Observatory
 *              You may do anything you like with this file except remove
 *              this copyright.  The Smithsonian Astrophysical Observatory
 *              makes no representations about the suitability of this
 *              software for any purpose.  It is provided "as is" without
 *              express or implied warranty.
 */

#include "fitsio2.h"
#include 		/* define stderr, FD, and NULL */
#include 
#include   /* stddef.h is apparently needed to define size_t */
#include 

#define FILE_NOT_OPENED 104

/* Parameters from iraf/lib/imhdr.h for IRAF version 1 images */
#define SZ_IMPIXFILE	 79		/* name of pixel storage file */
#define SZ_IMHDRFILE	 79   		/* length of header storage file */
#define SZ_IMTITLE	 79		/* image title string */
#define LEN_IMHDR	2052		/* length of std header */

/* Parameters from iraf/lib/imhdr.h for IRAF version 2 images */
#define	SZ_IM2PIXFILE	255		/* name of pixel storage file */
#define	SZ_IM2HDRFILE	255		/* name of header storage file */
#define	SZ_IM2TITLE	383		/* image title string */
#define LEN_IM2HDR	2046		/* length of std header */

/* Offsets into header in bytes for parameters in IRAF version 1 images */
#define IM_HDRLEN	 12		/* Length of header in 4-byte ints */
#define IM_PIXTYPE       16             /* Datatype of the pixels */
#define IM_NDIM          20             /* Number of dimensions */
#define IM_LEN           24             /* Length (as stored) */
#define IM_PHYSLEN       52             /* Physical length (as stored) */
#define IM_PIXOFF        88             /* Offset of the pixels */
#define IM_CTIME        108             /* Time of image creation */
#define IM_MTIME        112             /* Time of last modification */
#define IM_LIMTIME      116             /* Time of min,max computation */
#define IM_MAX          120             /* Maximum pixel value */
#define IM_MIN          124             /* Maximum pixel value */
#define IM_PIXFILE      412             /* Name of pixel storage file */
#define IM_HDRFILE      572             /* Name of header storage file */
#define IM_TITLE        732             /* Image name string */

/* Offsets into header in bytes for parameters in IRAF version 2 images */
#define IM2_HDRLEN	  6		/* Length of header in 4-byte ints */
#define IM2_PIXTYPE      10             /* Datatype of the pixels */
#define IM2_SWAPPED      14             /* Pixels are byte swapped */
#define IM2_NDIM         18             /* Number of dimensions */
#define IM2_LEN          22             /* Length (as stored) */
#define IM2_PHYSLEN      50             /* Physical length (as stored) */
#define IM2_PIXOFF       86             /* Offset of the pixels */
#define IM2_CTIME       106             /* Time of image creation */
#define IM2_MTIME       110             /* Time of last modification */
#define IM2_LIMTIME     114             /* Time of min,max computation */
#define IM2_MAX         118             /* Maximum pixel value */
#define IM2_MIN         122             /* Maximum pixel value */
#define IM2_PIXFILE     126             /* Name of pixel storage file */
#define IM2_HDRFILE     382             /* Name of header storage file */
#define IM2_TITLE       638             /* Image name string */

/* Codes from iraf/unix/hlib/iraf.h */
#define	TY_CHAR		2
#define	TY_SHORT	3
#define	TY_INT		4
#define	TY_LONG		5
#define	TY_REAL		6
#define	TY_DOUBLE	7
#define	TY_COMPLEX	8
#define TY_POINTER      9
#define TY_STRUCT       10
#define TY_USHORT       11
#define TY_UBYTE        12

#define LEN_PIXHDR	1024
#define MAXINT  2147483647 /* Biggest number that can fit in long */

static int isirafswapped(char *irafheader, int offset);
static int irafgeti4(char *irafheader, int offset);
static char *irafgetc2(char *irafheader, int offset, int nc);
static char *irafgetc(char *irafheader,	int offset, int	nc);
static char *iraf2str(char *irafstring, int nchar);
static char *irafrdhead(const char *filename, int *lihead);
static int irafrdimage (char **buffptr, size_t *buffsize,
    size_t *filesize, int *status);
static int iraftofits (char *hdrname, char *irafheader, int nbiraf,
    char **buffptr, size_t *nbfits, size_t *fitssize, int *status);
static char *same_path(char *pixname, const char *hdrname);

static int swaphead=0;	/* =1 to swap data bytes of IRAF header values */
static int swapdata=0;  /* =1 to swap bytes in IRAF data pixels */

static void irafswap(int bitpix, char *string, int nbytes);
static void irafswap2(char *string, int nbytes);
static void irafswap4(char *string, int nbytes);
static void irafswap8(char *string, int nbytes);
static int pix_version (char *irafheader);
static int irafncmp (char *irafheader, char *teststring, int nc);
static int machswap(void);
static int head_version (char *irafheader);
static int hgeti4(char* hstring, char* keyword, int* val);
static int hgets(char* hstring, char* keyword, int lstr, char* string);
static char* hgetc(char* hstring, char* keyword);
static char* ksearch(char* hstring, char* keyword);
static char *blsearch (char* hstring, char* keyword);	
static char *strsrch (char* s1,	char* s2);
static char *strnsrch (	char* s1,char* s2,int ls1);
static void hputi4(char* hstring,char* keyword,	int ival);
static void hputs(char* hstring,char* keyword,char* cval);
static void hputcom(char* hstring,char* keyword,char* comment);
static void hputl(char* hstring,char* keyword,int lval);
static void hputc(char* hstring,char* keyword,char* cval);
static int getirafpixname (const char *hdrname, char *irafheader, char *pixfilename, int *status);
int iraf2mem(char *filename, char **buffptr, size_t *buffsize, 
      size_t *filesize, int *status);

void ffpmsg(const char *err_message);

/* CFITS_API is defined below for use on Windows systems.  */
/* It is used to identify the public functions which should be exported. */
/* This has no effect on non-windows platforms where "WIN32" is not defined */

/* this is only needed to export the "fits_delete_iraf_file" symbol, which */
/* is called in fpackutil.c (and perhaps in other applications programs) */

#if defined (WIN32)
  #if defined(cfitsio_EXPORTS)
    #define CFITS_API __declspec(dllexport)
  #else
    #define CFITS_API //__declspec(dllimport)
  #endif /* CFITS_API */
#else /* defined (WIN32) */
 #define CFITS_API
#endif

int CFITS_API fits_delete_iraf_file(const char *filename, int *status);


/*--------------------------------------------------------------------------*/
int fits_delete_iraf_file(const char *filename,  /* name of input file      */
             int *status)                        /* IO - error status       */

/*
   Delete the iraf .imh header file and the associated .pix data file
*/
{
    char *irafheader;
    int lenirafhead;

    char pixfilename[SZ_IM2PIXFILE+1];

    /* read IRAF header into dynamically created char array (free it later!) */
    irafheader = irafrdhead(filename, &lenirafhead);

    if (!irafheader)
    {
	return(*status = FILE_NOT_OPENED);
    }

    getirafpixname (filename, irafheader, pixfilename, status);

    /* don't need the IRAF header any more */
    free(irafheader);

    if (*status > 0)
       return(*status);

    remove(filename);
    remove(pixfilename);
    
    return(*status);
}

/*--------------------------------------------------------------------------*/
int iraf2mem(char *filename,     /* name of input file                 */
             char **buffptr,     /* O - memory pointer (initially NULL)    */
             size_t *buffsize,   /* O - size of mem buffer, in bytes        */
             size_t *filesize,   /* O - size of FITS file, in bytes         */
             int *status)        /* IO - error status                       */

/*
   Driver routine that reads an IRAF image into memory, also converting
   it into FITS format.
*/
{
    char *irafheader;
    int lenirafhead;

    *buffptr = NULL;
    *buffsize = 0;
    *filesize = 0;

    /* read IRAF header into dynamically created char array (free it later!) */
    irafheader = irafrdhead(filename, &lenirafhead);

    if (!irafheader)
    {
	return(*status = FILE_NOT_OPENED);
    }

    /* convert IRAF header to FITS header in memory */
    iraftofits(filename, irafheader, lenirafhead, buffptr, buffsize, filesize,
               status);

    /* don't need the IRAF header any more */
    free(irafheader);

    if (*status > 0)
       return(*status);

    *filesize = (((*filesize - 1) / 2880 ) + 1 ) * 2880; /* multiple of 2880 */

    /* append the image data onto the FITS header */
    irafrdimage(buffptr, buffsize, filesize, status);

    return(*status);
}

/*--------------------------------------------------------------------------*/
/* Subroutine:	irafrdhead  (was irafrhead in D. Mink's original code)
 * Purpose:	Open and read the iraf .imh file.
 * Returns:	NULL if failure, else pointer to IRAF .imh image header
 * Notes:	The imhdr format is defined in iraf/lib/imhdr.h, some of
 *		which defines or mimicked, above.
 */

static char *irafrdhead (
    const char *filename,  /* Name of IRAF header file */
    int *lihead)           /* Length of IRAF image header in bytes (returned) */
{
    FILE *fd;
    int nbr;
    char *irafheader;
    char errmsg[FLEN_ERRMSG];
    long nbhead;
    int nihead;

    *lihead = 0;

    /* open the image header file */
    fd = fopen (filename, "rb");
    if (fd == NULL) {
        ffpmsg("unable to open IRAF header file:");
        ffpmsg(filename);
	return (NULL);
	}

    /* Find size of image header file */
    if (fseek(fd, 0, 2) != 0)  /* move to end of the file */
    {
        ffpmsg("IRAFRHEAD: cannot seek in file:");
        ffpmsg(filename);
        return(NULL);
    }

    nbhead = ftell(fd);     /* position = size of file */
    if (nbhead < 0)
    {
        ffpmsg("IRAFRHEAD: cannot get pos. in file:");
        ffpmsg(filename);
        return(NULL);
    }

    if (fseek(fd, 0, 0) != 0) /* move back to beginning */
    {
        ffpmsg("IRAFRHEAD: cannot seek to beginning of file:");
        ffpmsg(filename);
        return(NULL);
    }

    /* allocate initial sized buffer */
    nihead = nbhead + 5000;
    irafheader = (char *) calloc (1, nihead);
    if (irafheader == NULL) {
	snprintf(errmsg, FLEN_ERRMSG,"IRAFRHEAD Cannot allocate %d-byte header",
		      nihead);
        ffpmsg(errmsg);
        ffpmsg(filename);
	return (NULL);
	}
    *lihead = nihead;

    /* Read IRAF header */
    nbr = fread (irafheader, 1, nbhead, fd);
    fclose (fd);

    /* Reject if header less than minimum length */
    if (nbr < LEN_PIXHDR) {
	snprintf(errmsg, FLEN_ERRMSG,"IRAFRHEAD header file: %d / %d bytes read.",
		      nbr,LEN_PIXHDR);
        ffpmsg(errmsg);
        ffpmsg(filename);
	free (irafheader);
	return (NULL);
	}

    return (irafheader);
}
/*--------------------------------------------------------------------------*/
static int irafrdimage (
    char **buffptr,	/* FITS image header (filled) */
    size_t *buffsize,      /* allocated size of the buffer */
    size_t *filesize,      /* actual size of the FITS file */
    int *status)
{
    FILE *fd;
    char *bang;
    int nax = 1, naxis1 = 1, naxis2 = 1, naxis3 = 1, naxis4 = 1, npaxis1 = 1, npaxis2;
    int bitpix, bytepix, i;
    char *fitsheader, *image;
    int nbr, nbimage, nbaxis, nbl, nbdiff;
    char *pixheader;
    char *linebuff;
    int imhver, lpixhead = 0;
    char pixname[SZ_IM2PIXFILE+1];
    char errmsg[FLEN_ERRMSG];
    size_t newfilesize;
 
    fitsheader = *buffptr;           /* pointer to start of header */

    /* Convert pixel file name to character string */
    hgets (fitsheader, "PIXFILE", SZ_IM2PIXFILE, pixname);
    hgeti4 (fitsheader, "PIXOFF", &lpixhead);

    /* Open pixel file, ignoring machine name if present */
    if ((bang = strchr (pixname, '!')) != NULL )
	fd = fopen (bang + 1, "rb");
    else
	fd = fopen (pixname, "rb");

    /* Print error message and exit if pixel file is not found */
    if (!fd) {
        ffpmsg("IRAFRIMAGE: Cannot open IRAF pixel file:");
        ffpmsg(pixname);
	return (*status = FILE_NOT_OPENED);
	}

    /* Read pixel header */
    pixheader = (char *) calloc (lpixhead, 1);
    if (pixheader == NULL) {
            ffpmsg("IRAFRIMAGE: Cannot alloc memory for pixel header");
            ffpmsg(pixname);
            fclose (fd);
	    return (*status = FILE_NOT_OPENED);
	}
    nbr = fread (pixheader, 1, lpixhead, fd);

    /* Check size of pixel header */
    if (nbr < lpixhead) {
	snprintf(errmsg, FLEN_ERRMSG,"IRAF pixel file: %d / %d bytes read.",
		      nbr,LEN_PIXHDR);
        ffpmsg(errmsg);
	free (pixheader);
	fclose (fd);
	return (*status = FILE_NOT_OPENED);
	}

    /* check pixel header magic word */
    imhver = pix_version (pixheader);
    if (imhver < 1) {
        ffpmsg("File not valid IRAF pixel file:");
        ffpmsg(pixname);
	free (pixheader);
	fclose (fd);
	return (*status = FILE_NOT_OPENED);
	}
    free (pixheader);

    /* Find number of bytes to read */
    hgeti4 (fitsheader,"NAXIS",&nax);
    hgeti4 (fitsheader,"NAXIS1",&naxis1);
    hgeti4 (fitsheader,"NPAXIS1",&npaxis1);
    if (nax > 1) {
        hgeti4 (fitsheader,"NAXIS2",&naxis2);
        hgeti4 (fitsheader,"NPAXIS2",&npaxis2);
	}
    if (nax > 2)
        hgeti4 (fitsheader,"NAXIS3",&naxis3);
    if (nax > 3)
        hgeti4 (fitsheader,"NAXIS4",&naxis4);

    hgeti4 (fitsheader,"BITPIX",&bitpix);
    if (bitpix < 0)
	bytepix = -bitpix / 8;
    else
	bytepix = bitpix / 8;

    nbimage = naxis1 * naxis2 * naxis3 * naxis4 * bytepix;
    
    newfilesize = *filesize + nbimage;  /* header + data */
    newfilesize = (((newfilesize - 1) / 2880 ) + 1 ) * 2880;

    if (newfilesize > *buffsize)   /* need to allocate more memory? */
    {
      fitsheader =  (char *) realloc (*buffptr, newfilesize);
      if (fitsheader == NULL) {
	snprintf(errmsg, FLEN_ERRMSG,"IRAFRIMAGE Cannot allocate %d-byte image buffer",
		(int) (*filesize));
        ffpmsg(errmsg);
        ffpmsg(pixname);
	fclose (fd);
	return (*status = FILE_NOT_OPENED);
	}
    }

    *buffptr = fitsheader;
    *buffsize = newfilesize;

    image = fitsheader + *filesize;
    *filesize = newfilesize;

    /* Read IRAF image all at once if physical and image dimensions are the same */
    if (npaxis1 == naxis1)
	nbr = fread (image, 1, nbimage, fd);

    /* Read IRAF image one line at a time if physical and image dimensions differ */
    else {
	nbdiff = (npaxis1 - naxis1) * bytepix;
	nbaxis = naxis1 * bytepix;
	linebuff = image;
	nbr = 0;
	if (naxis2 == 1 && naxis3 > 1)
	    naxis2 = naxis3;
	for (i = 0; i < naxis2; i++) {
	    nbl = fread (linebuff, 1, nbaxis, fd);
	    nbr = nbr + nbl;
	    fseek (fd, nbdiff, 1);
	    linebuff = linebuff + nbaxis;
	    }
	}
    fclose (fd);

    /* Check size of image */
    if (nbr < nbimage) {
	snprintf(errmsg, FLEN_ERRMSG,"IRAF pixel file: %d / %d bytes read.",
		      nbr,nbimage);
        ffpmsg(errmsg);
        ffpmsg(pixname);
	return (*status = FILE_NOT_OPENED);
	}

    /* Byte-reverse image, if necessary */
    if (swapdata)
	irafswap (bitpix, image, nbimage);

    return (*status);
}
/*--------------------------------------------------------------------------*/
/* Return IRAF image format version number from magic word in IRAF header*/

static int head_version (
    char *irafheader)	/* IRAF image header from file */

{

    /* Check header file magic word */
    if (irafncmp (irafheader, "imhdr", 5) != 0 ) {
	if (strncmp (irafheader, "imhv2", 5) != 0)
	    return (0);
	else
	    return (2);
	}
    else
	return (1);
}

/*--------------------------------------------------------------------------*/
/* Return IRAF image format version number from magic word in IRAF pixel file */

static int pix_version (
    char *irafheader)   /* IRAF image header from file */
{

    /* Check pixel file header magic word */
    if (irafncmp (irafheader, "impix", 5) != 0) {
	if (strncmp (irafheader, "impv2", 5) != 0)
	    return (0);
	else
	    return (2);
	}
    else
	return (1);
}

/*--------------------------------------------------------------------------*/
/* Verify that file is valid IRAF imhdr or impix by checking first 5 chars
 * Returns:	0 on success, 1 on failure */

static int irafncmp (

char	*irafheader,	/* IRAF image header from file */
char	*teststring,	/* C character string to compare */
int	nc)		/* Number of characters to compate */

{
    char *line;

    if ((line = iraf2str (irafheader, nc)) == NULL)
	return (1);
    if (strncmp (line, teststring, nc) == 0) {
	free (line);
	return (0);
	}
    else {
	free (line);
	return (1);
	}
}
/*--------------------------------------------------------------------------*/

/* Convert IRAF image header to FITS image header, returning FITS header */

static int iraftofits (
    char    *hdrname,  /* IRAF header file name (may be path) */
    char    *irafheader,  /* IRAF image header */
    int	    nbiraf,	  /* Number of bytes in IRAF header */
    char    **buffptr,    /* pointer to the FITS header  */
    size_t  *nbfits,      /* allocated size of the FITS header buffer */
    size_t  *fitssize,  /* Number of bytes in FITS header (returned) */
                        /*  = number of bytes to the end of the END keyword */
    int     *status)
{
    char *objname;	/* object name from FITS file */
    int lstr, i, j, k, ib, nax, nbits;
    char *pixname, *newpixname, *bang, *chead;
    char *fitsheader;
    int nblock, nlines;
    char *fhead, *fhead1, *fp, endline[81];
    char irafchar;
    char fitsline[81];
    int pixtype;
    int imhver, n, imu, pixoff, impixoff;
/*    int immax, immin, imtime;  */
    int imndim, imlen, imphyslen, impixtype;
    char errmsg[FLEN_ERRMSG];

    /* Set up last line of FITS header */
    (void)strncpy (endline,"END", 3);
    for (i = 3; i < 80; i++)
	endline[i] = ' ';
    endline[80] = 0;

    /* Check header magic word */
    imhver = head_version (irafheader);
    if (imhver < 1) {
	ffpmsg("File not valid IRAF image header");
        ffpmsg(hdrname);
	return(*status = FILE_NOT_OPENED);
	}
    if (imhver == 2) {
	nlines = 24 + ((nbiraf - LEN_IM2HDR) / 81);
	imndim = IM2_NDIM;
	imlen = IM2_LEN;
	imphyslen = IM2_PHYSLEN;
	impixtype = IM2_PIXTYPE;
	impixoff = IM2_PIXOFF;
/*	imtime = IM2_MTIME; */
/*	immax = IM2_MAX;  */
/*	immin = IM2_MIN; */
	}
    else {
	nlines = 24 + ((nbiraf - LEN_IMHDR) / 162);
	imndim = IM_NDIM;
	imlen = IM_LEN;
	imphyslen = IM_PHYSLEN;
	impixtype = IM_PIXTYPE;
	impixoff = IM_PIXOFF;
/*	imtime = IM_MTIME; */
/*	immax = IM_MAX; */
/*	immin = IM_MIN; */
	}

    /*  Initialize FITS header */
    nblock = (nlines * 80) / 2880;
    *nbfits = (nblock + 5) * 2880 + 4;
    fitsheader = (char *) calloc (*nbfits, 1);
    if (fitsheader == NULL) {
	snprintf(errmsg, FLEN_ERRMSG,"IRAF2FITS Cannot allocate %d-byte FITS header",
		(int) (*nbfits));
        ffpmsg(hdrname);
	return (*status = FILE_NOT_OPENED);
	}

    fhead = fitsheader;
    *buffptr = fitsheader;
    (void)strncpy (fitsheader, endline, 80);
    hputl (fitsheader, "SIMPLE", 1);
    fhead = fhead + 80;

    /*  check if the IRAF file is in big endian (sun) format (= 0) or not. */
    /*  This is done by checking the 4 byte integer in the header that     */
    /*  represents the iraf pixel type.  This 4-byte word is guaranteed to */
    /*  have the least sig byte != 0 and the most sig byte = 0,  so if the */
    /*  first byte of the word != 0, then the file in little endian format */
    /*  like on an Alpha machine.                                          */

    swaphead = isirafswapped(irafheader, impixtype);
    if (imhver == 1)
        swapdata = swaphead; /* vers 1 data has same swapness as header */
    else
        swapdata = irafgeti4 (irafheader, IM2_SWAPPED); 

    /*  Set pixel size in FITS header */
    pixtype = irafgeti4 (irafheader, impixtype);
    switch (pixtype) {
	case TY_CHAR:
	    nbits = 8;
	    break;
	case TY_UBYTE:
	    nbits = 8;
	    break;
	case TY_SHORT:
	    nbits = 16;
	    break;
	case TY_USHORT:
	    nbits = -16;
	    break;
	case TY_INT:
	case TY_LONG:
	    nbits = 32;
	    break;
	case TY_REAL:
	    nbits = -32;
	    break;
	case TY_DOUBLE:
	    nbits = -64;
	    break;
	default:
	    snprintf(errmsg,FLEN_ERRMSG,"Unsupported IRAF data type: %d", pixtype);
            ffpmsg(errmsg);
            ffpmsg(hdrname);
	    return (*status = FILE_NOT_OPENED);
	}
    hputi4 (fitsheader,"BITPIX",nbits);
    hputcom (fitsheader,"BITPIX", "IRAF .imh pixel type");
    fhead = fhead + 80;

    /*  Set image dimensions in FITS header */
    nax = irafgeti4 (irafheader, imndim);
    hputi4 (fitsheader,"NAXIS",nax);
    hputcom (fitsheader,"NAXIS", "IRAF .imh naxis");
    fhead = fhead + 80;

    n = irafgeti4 (irafheader, imlen);
    hputi4 (fitsheader, "NAXIS1", n);
    hputcom (fitsheader,"NAXIS1", "IRAF .imh image naxis[1]");
    fhead = fhead + 80;

    if (nax > 1) {
	n = irafgeti4 (irafheader, imlen+4);
	hputi4 (fitsheader, "NAXIS2", n);
	hputcom (fitsheader,"NAXIS2", "IRAF .imh image naxis[2]");
        fhead = fhead + 80;
	}
    if (nax > 2) {
	n = irafgeti4 (irafheader, imlen+8);
	hputi4 (fitsheader, "NAXIS3", n);
	hputcom (fitsheader,"NAXIS3", "IRAF .imh image naxis[3]");
	fhead = fhead + 80;
	}
    if (nax > 3) {
	n = irafgeti4 (irafheader, imlen+12);
	hputi4 (fitsheader, "NAXIS4", n);
	hputcom (fitsheader,"NAXIS4", "IRAF .imh image naxis[4]");
	fhead = fhead + 80;
	}

    /* Set object name in FITS header */
    if (imhver == 2)
	objname = irafgetc (irafheader, IM2_TITLE, SZ_IM2TITLE);
    else
	objname = irafgetc2 (irafheader, IM_TITLE, SZ_IMTITLE);
    if ((lstr = strlen (objname)) < 8) {
	for (i = lstr; i < 8; i++)
	    objname[i] = ' ';
	objname[8] = 0;
	}
    hputs (fitsheader,"OBJECT",objname);
    hputcom (fitsheader,"OBJECT", "IRAF .imh title");
    free (objname);
    fhead = fhead + 80;

    /* Save physical axis lengths so image file can be read */
    n = irafgeti4 (irafheader, imphyslen);
    hputi4 (fitsheader, "NPAXIS1", n);
    hputcom (fitsheader,"NPAXIS1", "IRAF .imh physical naxis[1]");
    fhead = fhead + 80;
    if (nax > 1) {
	n = irafgeti4 (irafheader, imphyslen+4);
	hputi4 (fitsheader, "NPAXIS2", n);
	hputcom (fitsheader,"NPAXIS2", "IRAF .imh physical naxis[2]");
	fhead = fhead + 80;
	}
    if (nax > 2) {
	n = irafgeti4 (irafheader, imphyslen+8);
	hputi4 (fitsheader, "NPAXIS3", n);
	hputcom (fitsheader,"NPAXIS3", "IRAF .imh physical naxis[3]");
	fhead = fhead + 80;
	}
    if (nax > 3) {
	n = irafgeti4 (irafheader, imphyslen+12);
	hputi4 (fitsheader, "NPAXIS4", n);
	hputcom (fitsheader,"NPAXIS4", "IRAF .imh physical naxis[4]");
	fhead = fhead + 80;
	}

    /* Save image header filename in header */
    hputs (fitsheader,"IMHFILE",hdrname);
    hputcom (fitsheader,"IMHFILE", "IRAF header file name");
    fhead = fhead + 80;

    /* Save image pixel file pathname in header */
    if (imhver == 2)
	pixname = irafgetc (irafheader, IM2_PIXFILE, SZ_IM2PIXFILE);
    else
	pixname = irafgetc2 (irafheader, IM_PIXFILE, SZ_IMPIXFILE);
    if (strncmp(pixname, "HDR", 3) == 0 ) {
	newpixname = same_path (pixname, hdrname);
        if (newpixname) {
          free (pixname);
          pixname = newpixname;
	  }
	}
    if (strchr (pixname, '/') == NULL && strchr (pixname, '$') == NULL) {
	newpixname = same_path (pixname, hdrname);
        if (newpixname) {
          free (pixname);
          pixname = newpixname;
	  }
	}
	
    if ((bang = strchr (pixname, '!')) != NULL )
	hputs (fitsheader,"PIXFILE",bang+1);
    else
	hputs (fitsheader,"PIXFILE",pixname);
    free (pixname);
    hputcom (fitsheader,"PIXFILE", "IRAF .pix pixel file");
    fhead = fhead + 80;

    /* Save image offset from star of pixel file */
    pixoff = irafgeti4 (irafheader, impixoff);
    pixoff = (pixoff - 1) * 2;
    hputi4 (fitsheader, "PIXOFF", pixoff);
    hputcom (fitsheader,"PIXOFF", "IRAF .pix pixel offset (Do not change!)");
    fhead = fhead + 80;

    /* Save IRAF file format version in header */
    hputi4 (fitsheader,"IMHVER",imhver);
    hputcom (fitsheader,"IMHVER", "IRAF .imh format version (1 or 2)");
    fhead = fhead + 80;

    /* Save flag as to whether to swap IRAF data for this file and machine */
    if (swapdata)
	hputl (fitsheader, "PIXSWAP", 1);
    else
	hputl (fitsheader, "PIXSWAP", 0);
    hputcom (fitsheader,"PIXSWAP", "IRAF pixels, FITS byte orders differ if T");
    fhead = fhead + 80;

    /* Add user portion of IRAF header to FITS header */
    fitsline[80] = 0;
    if (imhver == 2) {
	imu = LEN_IM2HDR;
	chead = irafheader;
	j = 0;
	for (k = 0; k < 80; k++)
	    fitsline[k] = ' ';
	for (i = imu; i < nbiraf; i++) {
	    irafchar = chead[i];
	    if (irafchar == 0)
		break;
	    else if (irafchar == 10) {
		(void)strncpy (fhead, fitsline, 80);
		/* fprintf (stderr,"%80s\n",fitsline); */
		if (strncmp (fitsline, "OBJECT ", 7) != 0) {
		    fhead = fhead + 80;
		    }
		for (k = 0; k < 80; k++)
		    fitsline[k] = ' ';
		j = 0;
		}
	    else {
		if (j > 80) {
		    if (strncmp (fitsline, "OBJECT ", 7) != 0) {
			(void)strncpy (fhead, fitsline, 80);
			/* fprintf (stderr,"%80s\n",fitsline); */
			j = 9;
			fhead = fhead + 80;
			}
		    for (k = 0; k < 80; k++)
			fitsline[k] = ' ';
		    }
		if (irafchar > 32 && irafchar < 127)
		    fitsline[j] = irafchar;
		j++;
		}
	    }
	}
    else {
	imu = LEN_IMHDR;
	chead = irafheader;
	if (swaphead == 1)
	    ib = 0;
	else
	    ib = 1;
	for (k = 0; k < 80; k++)
	    fitsline[k] = ' ';
	j = 0;
	for (i = imu; i < nbiraf; i=i+2) {
	    irafchar = chead[i+ib];
	    if (irafchar == 0)
		break;
	    else if (irafchar == 10) {
		if (strncmp (fitsline, "OBJECT ", 7) != 0) {
		    (void)strncpy (fhead, fitsline, 80);
		    fhead = fhead + 80;
		    }
		/* fprintf (stderr,"%80s\n",fitsline); */
		j = 0;
		for (k = 0; k < 80; k++)
		    fitsline[k] = ' ';
		}
	    else {
		if (j > 80) {
		    if (strncmp (fitsline, "OBJECT ", 7) != 0) {
			(void)strncpy (fhead, fitsline, 80);
			j = 9;
			fhead = fhead + 80;
			}
		    /* fprintf (stderr,"%80s\n",fitsline); */
		    for (k = 0; k < 80; k++)
			fitsline[k] = ' ';
		    }
		if (irafchar > 32 && irafchar < 127)
		    fitsline[j] = irafchar;
		j++;
		}
	    }
	}

    /* Add END to last line */
    (void)strncpy (fhead, endline, 80);

    /* Find end of last 2880-byte block of header */
    fhead = ksearch (fitsheader, "END") + 80;
    nblock = *nbfits / 2880;
    fhead1 = fitsheader + (nblock * 2880);
    *fitssize = fhead - fitsheader;  /* no. of bytes to end of END keyword */

    /* Pad rest of header with spaces */
    strncpy (endline,"   ",3);
    for (fp = fhead; fp < fhead1; fp = fp + 80) {
	(void)strncpy (fp, endline,80);
	}

    return (*status);
}
/*--------------------------------------------------------------------------*/

/* get the IRAF pixel file name */

static int getirafpixname (
    const char *hdrname,  /* IRAF header file name (may be path) */
    char    *irafheader,  /* IRAF image header */
    char    *pixfilename,     /* IRAF pixel file name */
    int     *status)
{
    int imhver;
    char *pixname, *newpixname, *bang;

    /* Check header magic word */
    imhver = head_version (irafheader);
    if (imhver < 1) {
	ffpmsg("File not valid IRAF image header");
        ffpmsg(hdrname);
	return(*status = FILE_NOT_OPENED);
	}

    /* get image pixel file pathname in header */
    if (imhver == 2)
	pixname = irafgetc (irafheader, IM2_PIXFILE, SZ_IM2PIXFILE);
    else
	pixname = irafgetc2 (irafheader, IM_PIXFILE, SZ_IMPIXFILE);

    if (strncmp(pixname, "HDR", 3) == 0 ) {
	newpixname = same_path (pixname, hdrname);
        if (newpixname) {
          free (pixname);
          pixname = newpixname;
	  }
	}

    if (strchr (pixname, '/') == NULL && strchr (pixname, '$') == NULL) {
	newpixname = same_path (pixname, hdrname);
        if (newpixname) {
          free (pixname);
          pixname = newpixname;
	  }
	}
	
    if ((bang = strchr (pixname, '!')) != NULL )
	strcpy(pixfilename,bang+1);
    else
	strcpy(pixfilename,pixname);

    free (pixname);

    return (*status);
}

/*--------------------------------------------------------------------------*/
/* Put filename and header path together */

static char *same_path (

char	*pixname,	/* IRAF pixel file pathname */
const char	*hdrname)	/* IRAF image header file pathname */

{
    int len;
    char *newpixname;

/*  WDP - 10/16/2007 - increased allocation to avoid possible overflow */
/*    newpixname = (char *) calloc (SZ_IM2PIXFILE, sizeof (char)); */

    newpixname = (char *) calloc (2*SZ_IM2PIXFILE+1, sizeof (char));
    if (newpixname == NULL) {
            ffpmsg("iraffits same_path: Cannot alloc memory for newpixname");
	    return (NULL);
	}

    /* Pixel file is in same directory as header */
    if (strncmp(pixname, "HDR$", 4) == 0 ) {
	(void)strncpy (newpixname, hdrname, SZ_IM2PIXFILE);

	/* find the end of the pathname */
	len = strlen (newpixname);
#ifndef VMS
	while( (len > 0) && (newpixname[len-1] != '/') )
#else
	while( (len > 0) && (newpixname[len-1] != ']') && (newpixname[len-1] != ':') )
#endif
	    len--;

	/* add name */
	newpixname[len] = '\0';
	(void)strncat (newpixname, &pixname[4], SZ_IM2PIXFILE);
	}

    /* Bare pixel file with no path is assumed to be same as HDR$filename */
    else if (strchr (pixname, '/') == NULL && strchr (pixname, '$') == NULL) {
	(void)strncpy (newpixname, hdrname, SZ_IM2PIXFILE);

	/* find the end of the pathname */
	len = strlen (newpixname);
#ifndef VMS
	while( (len > 0) && (newpixname[len-1] != '/') )
#else
	while( (len > 0) && (newpixname[len-1] != ']') && (newpixname[len-1] != ':') )
#endif
	    len--;

	/* add name */
	newpixname[len] = '\0';
	(void)strncat (newpixname, pixname, SZ_IM2PIXFILE);
	}

    /* Pixel file has same name as header file, but with .pix extension */
    else if (strncmp (pixname, "HDR", 3) == 0) {

	/* load entire header name string into name buffer */
	(void)strncpy (newpixname, hdrname, SZ_IM2PIXFILE);
	len = strlen (newpixname);
	newpixname[len-3] = 'p';
	newpixname[len-2] = 'i';
	newpixname[len-1] = 'x';
	}

    return (newpixname);
}

/*--------------------------------------------------------------------------*/
static int isirafswapped (

char	*irafheader,	/* IRAF image header */
int	offset)		/* Number of bytes to skip before number */

    /*  check if the IRAF file is in big endian (sun) format (= 0) or not */
    /*  This is done by checking the 4 byte integer in the header that */
    /*  represents the iraf pixel type.  This 4-byte word is guaranteed to */
    /*  have the least sig byte != 0 and the most sig byte = 0,  so if the */
    /*  first byte of the word != 0, then the file in little endian format */
    /*  like on an Alpha machine.                                          */

{
    int  swapped;

    if (irafheader[offset] != 0)
	swapped = 1;
    else
	swapped = 0;

    return (swapped);
}
/*--------------------------------------------------------------------------*/
static int irafgeti4 (

char	*irafheader,	/* IRAF image header */
int	offset)		/* Number of bytes to skip before number */

{
    char *ctemp, *cheader;
    int  temp;

    cheader = irafheader;
    ctemp = (char *) &temp;

    if (machswap() != swaphead) {
	ctemp[3] = cheader[offset];
	ctemp[2] = cheader[offset+1];
	ctemp[1] = cheader[offset+2];
	ctemp[0] = cheader[offset+3];
	}
    else {
	ctemp[0] = cheader[offset];
	ctemp[1] = cheader[offset+1];
	ctemp[2] = cheader[offset+2];
	ctemp[3] = cheader[offset+3];
	}
    return (temp);
}

/*--------------------------------------------------------------------------*/
/* IRAFGETC2 -- Get character string from arbitrary part of v.1 IRAF header */

static char *irafgetc2 (

char	*irafheader,	/* IRAF image header */
int	offset,		/* Number of bytes to skip before string */
int	nc)		/* Maximum number of characters in string */

{
    char *irafstring, *string;

    irafstring = irafgetc (irafheader, offset, 2*(nc+1));
    string = iraf2str (irafstring, nc);
    free (irafstring);

    return (string);
}

/*--------------------------------------------------------------------------*/
/* IRAFGETC -- Get character string from arbitrary part of IRAF header */

static char *irafgetc (

char	*irafheader,	/* IRAF image header */
int	offset,		/* Number of bytes to skip before string */
int	nc)		/* Maximum number of characters in string */

{
    char *ctemp, *cheader;
    int i;

    cheader = irafheader;
    ctemp = (char *) calloc (nc+1, 1);
    if (ctemp == NULL) {
	ffpmsg("IRAFGETC Cannot allocate memory for string variable");
	return (NULL);
	}
    for (i = 0; i < nc; i++) {
	ctemp[i] = cheader[offset+i];
	if (ctemp[i] > 0 && ctemp[i] < 32)
	    ctemp[i] = ' ';
	}

    return (ctemp);
}

/*--------------------------------------------------------------------------*/
/* Convert IRAF 2-byte/char string to 1-byte/char string */

static char *iraf2str (

char	*irafstring,	/* IRAF 2-byte/character string */
int	nchar)		/* Number of characters in string */
{
    char *string;
    int i, j;

    string = (char *) calloc (nchar+1, 1);
    if (string == NULL) {
	ffpmsg("IRAF2STR Cannot allocate memory for string variable");
	return (NULL);
	}

    /* the chars are in bytes 1, 3, 5, ... if bigendian format (SUN) */
    /* else in bytes 0, 2, 4, ... if little endian format (Alpha)    */

    if (irafstring[0] != 0)
	j = 0;
    else
	j = 1;

    /* Convert appropriate byte of input to output character */
    for (i = 0; i < nchar; i++) {
	string[i] = irafstring[j];
	j = j + 2;
	}

    return (string);
}

/*--------------------------------------------------------------------------*/
/* IRAFSWAP -- Reverse bytes of any type of vector in place */

static void irafswap (

int	bitpix,		/* Number of bits per pixel */
			/*  16 = short, -16 = unsigned short, 32 = int */
			/* -32 = float, -64 = double */
char	*string,	/* Address of starting point of bytes to swap */
int	nbytes)		/* Number of bytes to swap */

{
    switch (bitpix) {

	case 16:
	    if (nbytes < 2) return;
	    irafswap2 (string,nbytes);
	    break;

	case 32:
	    if (nbytes < 4) return;
	    irafswap4 (string,nbytes);
	    break;

	case -16:
	    if (nbytes < 2) return;
	    irafswap2 (string,nbytes);
	    break;

	case -32:
	    if (nbytes < 4) return;
	    irafswap4 (string,nbytes);
	    break;

	case -64:
	    if (nbytes < 8) return;
	    irafswap8 (string,nbytes);
	    break;

	}
    return;
}

/*--------------------------------------------------------------------------*/
/* IRAFSWAP2 -- Swap bytes in string in place */

static void irafswap2 (

char *string,	/* Address of starting point of bytes to swap */
int nbytes)	/* Number of bytes to swap */

{
    char *sbyte, temp, *slast;

    slast = string + nbytes;
    sbyte = string;
    while (sbyte < slast) {
	temp = sbyte[0];
	sbyte[0] = sbyte[1];
	sbyte[1] = temp;
	sbyte= sbyte + 2;
	}
    return;
}

/*--------------------------------------------------------------------------*/
/* IRAFSWAP4 -- Reverse bytes of Integer*4 or Real*4 vector in place */

static void irafswap4 (

char *string,	/* Address of Integer*4 or Real*4 vector */
int nbytes)	/* Number of bytes to reverse */

{
    char *sbyte, *slast;
    char temp0, temp1, temp2, temp3;

    slast = string + nbytes;
    sbyte = string;
    while (sbyte < slast) {
	temp3 = sbyte[0];
	temp2 = sbyte[1];
	temp1 = sbyte[2];
	temp0 = sbyte[3];
	sbyte[0] = temp0;
	sbyte[1] = temp1;
	sbyte[2] = temp2;
	sbyte[3] = temp3;
	sbyte = sbyte + 4;
	}

    return;
}

/*--------------------------------------------------------------------------*/
/* IRAFSWAP8 -- Reverse bytes of Real*8 vector in place */

static void irafswap8 (

char *string,	/* Address of Real*8 vector */
int nbytes)	/* Number of bytes to reverse */

{
    char *sbyte, *slast;
    char temp[8];

    slast = string + nbytes;
    sbyte = string;
    while (sbyte < slast) {
	temp[7] = sbyte[0];
	temp[6] = sbyte[1];
	temp[5] = sbyte[2];
	temp[4] = sbyte[3];
	temp[3] = sbyte[4];
	temp[2] = sbyte[5];
	temp[1] = sbyte[6];
	temp[0] = sbyte[7];
	sbyte[0] = temp[0];
	sbyte[1] = temp[1];
	sbyte[2] = temp[2];
	sbyte[3] = temp[3];
	sbyte[4] = temp[4];
	sbyte[5] = temp[5];
	sbyte[6] = temp[6];
	sbyte[7] = temp[7];
	sbyte = sbyte + 8;
	}
    return;
}

/*--------------------------------------------------------------------------*/
static int
machswap (void)

{
    char *ctest;
    int itest;

    itest = 1;
    ctest = (char *)&itest;
    if (*ctest)
	return (1);
    else
	return (0);
}

/*--------------------------------------------------------------------------*/
/*             the following routines were originally in hget.c             */
/*--------------------------------------------------------------------------*/


static int lhead0 = 0;

/*--------------------------------------------------------------------------*/

/* Extract long value for variable from FITS header string */

static int
hgeti4 (hstring,keyword,ival)

char *hstring;	/* character string containing FITS header information
		   in the format =  {/ } */
char *keyword;	/* character string containing the name of the keyword
		   the value of which is returned.  hget searches for a
		   line beginning with this string.  if "[n]" is present,
		   the n'th token in the value is returned.
		   (the first 8 characters must be unique) */
int *ival;
{
char *value;
double dval;
int minint;
char val[30]; 

/* Get value and comment from header string */
	value = hgetc (hstring,keyword);

/* Translate value from ASCII to binary */
	if (value != NULL) {
	    minint = -MAXINT - 1;
	    strcpy (val, value);
	    dval = atof (val);
	    if (dval+0.001 > MAXINT)
		*ival = MAXINT;
	    else if (dval >= 0)
		*ival = (int) (dval + 0.001);
	    else if (dval-0.001 < minint)
		*ival = minint;
	    else
		*ival = (int) (dval - 0.001);
	    return (1);
	    }
	else {
	    return (0);
	    }
}

/*-------------------------------------------------------------------*/
/* Extract string value for variable from FITS header string */

static int
hgets (hstring, keyword, lstr, str)

char *hstring;	/* character string containing FITS header information
		   in the format =  {/ } */
char *keyword;	/* character string containing the name of the keyword
		   the value of which is returned.  hget searches for a
		   line beginning with this string.  if "[n]" is present,
		   the n'th token in the value is returned.
		   (the first 8 characters must be unique) */
int lstr;	/* Size of str in characters */
char *str;	/* String (returned) */
{
	char *value;
	int lval;

/* Get value and comment from header string */
	value = hgetc (hstring,keyword);

	if (value != NULL) {
	    lval = strlen (value);
	    if (lval < lstr)
		strcpy (str, value);
	    else if (lstr > 1)
		strncpy (str, value, lstr-1);
	    else
		str[0] = value[0];
	    return (1);
	    }
	else
	    return (0);
}

/*-------------------------------------------------------------------*/
/* Extract character value for variable from FITS header string */

static char *
hgetc (hstring,keyword0)

char *hstring;	/* character string containing FITS header information
		   in the format =  {/ } */
char *keyword0;	/* character string containing the name of the keyword
		   the value of which is returned.  hget searches for a
		   line beginning with this string.  if "[n]" is present,
		   the n'th token in the value is returned.
		   (the first 8 characters must be unique) */
{
	static char cval[80];
	char *value;
	char cwhite[2];
	char squot[2], dquot[2], lbracket[2], rbracket[2], slash[2], comma[2];
	char keyword[81]; /* large for ESO hierarchical keywords */
	char line[100];
	char *vpos, *cpar = NULL;
	char *q1, *q2 = NULL, *v1, *v2, *c1, *brack1, *brack2;
        char *saveptr;
	int ipar, i;

	squot[0] = 39;
	squot[1] = 0;
	dquot[0] = 34;
	dquot[1] = 0;
	lbracket[0] = 91;
	lbracket[1] = 0;
	comma[0] = 44;
	comma[1] = 0;
	rbracket[0] = 93;
	rbracket[1] = 0;
	slash[0] = 47;
	slash[1] = 0;

/* Find length of variable name */
	strncpy (keyword,keyword0, sizeof(keyword)-1);
	brack1 = strsrch (keyword,lbracket);
	if (brack1 == NULL)
	    brack1 = strsrch (keyword,comma);
	if (brack1 != NULL) {
	    *brack1 = '\0';
	    brack1++;
	    }

/* Search header string for variable name */
	vpos = ksearch (hstring,keyword);

/* Exit if not found */
	if (vpos == NULL) {
	    return (NULL);
	    }

/* Initialize line to nulls */
	 for (i = 0; i < 100; i++)
	    line[i] = 0;

/* In standard FITS, data lasts until 80th character */

/* Extract entry for this variable from the header */
	strncpy (line,vpos,80);

/* check for quoted value */
	q1 = strsrch (line,squot);
	c1 = strsrch (line,slash);
	if (q1 != NULL) {
	    if (c1 != NULL && q1 < c1)
		q2 = strsrch (q1+1,squot);
	    else if (c1 == NULL)
		q2 = strsrch (q1+1,squot);
	    else
		q1 = NULL;
	    }
	else {
	    q1 = strsrch (line,dquot);
	    if (q1 != NULL) {
		if (c1 != NULL && q1 < c1)
		    q2 = strsrch (q1+1,dquot);
		else if (c1 == NULL)
		    q2 = strsrch (q1+1,dquot);
		else
		    q1 = NULL;
		}
	    else {
		q1 = NULL;
		q2 = line + 10;
		}
	    }

/* Extract value and remove excess spaces */
	if (q1 != NULL) {
	    v1 = q1 + 1;
	    v2 = q2;
	    c1 = strsrch (q2,"/");
	    }
	else {
	    v1 = strsrch (line,"=") + 1;
	    c1 = strsrch (line,"/");
	    if (c1 != NULL)
		v2 = c1;
	    else
		v2 = line + 79;
	    }

/* Ignore leading spaces */
	while (*v1 == ' ' && v1 < v2) {
	    v1++;
	    }

/* Drop trailing spaces */
	*v2 = '\0';
	v2--;
	while (*v2 == ' ' && v2 > v1) {
	    *v2 = '\0';
	    v2--;
	    }

	if (!strcmp (v1, "-0"))
	    v1++;
	strcpy (cval,v1);
	value = cval;

/* If keyword has brackets, extract appropriate token from value */
	if (brack1 != NULL) {
	    brack2 = strsrch (brack1,rbracket);
	    if (brack2 != NULL)
		*brack2 = '\0';
	    ipar = atoi (brack1);
	    if (ipar > 0) {
		cwhite[0] = ' ';
		cwhite[1] = '\0';
		for (i = 1; i <= ipar; i++) {
		    cpar = ffstrtok (v1,cwhite,&saveptr);
		    v1 = NULL;
		    }
		if (cpar != NULL) {
		    strcpy (cval,cpar);
		    }
		else
		    value = NULL;
		}
	    }

	return (value);
}


/*-------------------------------------------------------------------*/
/* Find beginning of fillable blank line before FITS header keyword line */

static char *
blsearch (hstring,keyword)

/* Find entry for keyword keyword in FITS header string hstring.
   (the keyword may have a maximum of eight letters)
   NULL is returned if the keyword is not found */

char *hstring;	/* character string containing fits-style header
		information in the format =  {/ }
		the default is that each entry is 80 characters long;
		however, lines may be of arbitrary length terminated by
		nulls, carriage returns or linefeeds, if packed is true.  */
char *keyword;	/* character string containing the name of the variable
		to be returned.  ksearch searches for a line beginning
		with this string.  The string may be a character
		literal or a character variable terminated by a null
		or '$'.  it is truncated to 8 characters. */
{
    char *loc, *headnext, *headlast, *pval, *lc, *line;
    char *bval;
    int icol, nextchar, lkey, nleft, lhstr;

    pval = 0;

    /* Search header string for variable name */
    if (lhead0)
	lhstr = lhead0;
    else {
	lhstr = 0;
	while (lhstr < 57600 && hstring[lhstr] != 0)
	    lhstr++;
	}
    headlast = hstring + lhstr;
    headnext = hstring;
    pval = NULL;
    while (headnext < headlast) {
	nleft = headlast - headnext;
	loc = strnsrch (headnext, keyword, nleft);

	/* Exit if keyword is not found */
	if (loc == NULL) {
	    break;
	    }

	icol = (loc - hstring) % 80;
	lkey = strlen (keyword);
	nextchar = (int) *(loc + lkey);

	/* If this is not in the first 8 characters of a line, keep searching */
	if (icol > 7)
	    headnext = loc + 1;

	/* If parameter name in header is longer, keep searching */
	else if (nextchar != 61 && nextchar > 32 && nextchar < 127)
	    headnext = loc + 1;

	/* If preceeding characters in line are not blanks, keep searching */
	else {
	    line = loc - icol;
	    for (lc = line; lc < loc; lc++) {
		if (*lc != ' ')
		    headnext = loc + 1;
		}

	/* Return pointer to start of line if match */
	    if (loc >= headnext) {
		pval = line;
		break;
		}
	    }
	}

    /* Return NULL if keyword is found at start of FITS header string */
    if (pval == NULL)
	return (pval);

    /* Return NULL if  found the first keyword in the header */
    if (pval == hstring)
        return (NULL);

    /* Find last nonblank line before requested keyword */
    bval = pval - 80;
    while (!strncmp (bval,"        ",8))
	bval = bval - 80;
    bval = bval + 80;

    /* Return pointer to calling program if blank lines found */
    if (bval < pval)
	return (bval);
    else
	return (NULL);
}


/*-------------------------------------------------------------------*/
/* Find FITS header line containing specified keyword */

static char *ksearch (hstring,keyword)

/* Find entry for keyword keyword in FITS header string hstring.
   (the keyword may have a maximum of eight letters)
   NULL is returned if the keyword is not found */

char *hstring;	/* character string containing fits-style header
		information in the format =  {/ }
		the default is that each entry is 80 characters long;
		however, lines may be of arbitrary length terminated by
		nulls, carriage returns or linefeeds, if packed is true.  */
char *keyword;	/* character string containing the name of the variable
		to be returned.  ksearch searches for a line beginning
		with this string.  The string may be a character
		literal or a character variable terminated by a null
		or '$'.  it is truncated to 8 characters. */
{
    char *loc, *headnext, *headlast, *pval, *lc, *line;
    int icol, nextchar, lkey, nleft, lhstr;

    pval = 0;

/* Search header string for variable name */
    if (lhead0)
	lhstr = lhead0;
    else {
	lhstr = 0;
	while (lhstr < 57600 && hstring[lhstr] != 0)
	    lhstr++;
	}
    headlast = hstring + lhstr;
    headnext = hstring;
    pval = NULL;
    while (headnext < headlast) {
	nleft = headlast - headnext;
	loc = strnsrch (headnext, keyword, nleft);

	/* Exit if keyword is not found */
	if (loc == NULL) {
	    break;
	    }

	icol = (loc - hstring) % 80;
	lkey = strlen (keyword);
	nextchar = (int) *(loc + lkey);

	/* If this is not in the first 8 characters of a line, keep searching */
	if (icol > 7)
	    headnext = loc + 1;

	/* If parameter name in header is longer, keep searching */
	else if (nextchar != 61 && nextchar > 32 && nextchar < 127)
	    headnext = loc + 1;

	/* If preceeding characters in line are not blanks, keep searching */
	else {
	    line = loc - icol;
	    for (lc = line; lc < loc; lc++) {
		if (*lc != ' ')
		    headnext = loc + 1;
		}

	/* Return pointer to start of line if match */
	    if (loc >= headnext) {
		pval = line;
		break;
		}
	    }
	}

/* Return pointer to calling program */
	return (pval);

}

/*-------------------------------------------------------------------*/
/* Find string s2 within null-terminated string s1 */

static char *
strsrch (s1, s2)

char *s1;	/* String to search */
char *s2;	/* String to look for */

{
    int ls1;
    ls1 = strlen (s1);
    return (strnsrch (s1, s2, ls1));
}

/*-------------------------------------------------------------------*/
/* Find string s2 within string s1 */

static char *
strnsrch (s1, s2, ls1)

char	*s1;	/* String to search */
char	*s2;	/* String to look for */
int	ls1;	/* Length of string being searched */

{
    char *s,*s1e;
    char cfirst,clast;
    int i,ls2;

    /* Return null string if either pointer is NULL */
    if (s1 == NULL || s2 == NULL)
	return (NULL);

    /* A zero-length pattern is found in any string */
    ls2 = strlen (s2);
    if (ls2 ==0)
	return (s1);

    /* Only a zero-length string can be found in a zero-length string */
    if (ls1 ==0)
	return (NULL);

    cfirst = s2[0];
    clast = s2[ls2-1];
    s1e = s1 + ls1 - ls2 + 1;
    s = s1;
    while (s < s1e) { 

	/* Search for first character in pattern string */
	if (*s == cfirst) {

	    /* If single character search, return */
	    if (ls2 == 1)
		return (s);

	    /* Search for last character in pattern string if first found */
	    if (s[ls2-1] == clast) {

		/* If two-character search, return */
		if (ls2 == 2)
		    return (s);

		/* If 3 or more characters, check for rest of search string */
		i = 1;
		while (i < ls2 && s[i] == s2[i])
		    i++;

		/* If entire string matches, return */
		if (i >= ls2)
		    return (s);
		}
	    }
	s++;
	}
    return (NULL);
}

/*-------------------------------------------------------------------*/
/*             the following routines were originally in hget.c      */
/*-------------------------------------------------------------------*/
/*  HPUTI4 - Set int keyword = ival in FITS header string */

static void
hputi4 (hstring,keyword,ival)

  char *hstring;	/* character string containing FITS-style header
			   information in the format
			   =  {/ }
			   each entry is padded with spaces to 80 characters */

  char *keyword;		/* character string containing the name of the variable
			   to be returned.  hput searches for a line beginning
			   with this string, and if there isn't one, creates one.
		   	   The first 8 characters of keyword must be unique. */
  int ival;		/* int number */
{
    char value[30];

    /* Translate value from binary to ASCII */
    snprintf (value,30,"%d",ival);

    /* Put value into header string */
    hputc (hstring,keyword,value);

    /* Return to calling program */
    return;
}

/*-------------------------------------------------------------------*/

/*  HPUTL - Set keyword = F if lval=0, else T, in FITS header string */

static void
hputl (hstring, keyword,lval)

char *hstring;		/* FITS header */
char *keyword;		/* Keyword name */
int lval;		/* logical variable (0=false, else true) */
{
    char value[8];

    /* Translate value from binary to ASCII */
    if (lval)
	strcpy (value, "T");
    else
	strcpy (value, "F");

    /* Put value into header string */
    hputc (hstring,keyword,value);

    /* Return to calling program */
    return;
}

/*-------------------------------------------------------------------*/

/*  HPUTS - Set character string keyword = 'cval' in FITS header string */

static void
hputs (hstring,keyword,cval)

char *hstring;	/* FITS header */
char *keyword;	/* Keyword name */
char *cval;	/* character string containing the value for variable
		   keyword.  trailing and leading blanks are removed.  */
{
    char squot = 39;
    char value[70];
    int lcval;

    /*  find length of variable string */

    lcval = strlen (cval);
    if (lcval > 67)
	lcval = 67;

    /* Put quotes around string */
    value[0] = squot;
    strncpy (&value[1],cval,lcval);
    value[lcval+1] = squot;
    value[lcval+2] = 0;

    /* Put value into header string */
    hputc (hstring,keyword,value);

    /* Return to calling program */
    return;
}

/*---------------------------------------------------------------------*/
/*  HPUTC - Set character string keyword = value in FITS header string */

static void
hputc (hstring,keyword,value)

char *hstring;
char *keyword;
char *value;	/* character string containing the value for variable
		   keyword.  trailing and leading blanks are removed.  */
{
    char squot = 39;
    char line[100];
    char newcom[50];
    char blank[80];
    char *v, *vp, *v1, *v2, *q1, *q2, *c1, *ve;
    int lkeyword, lcom, lval, lc, i;

    for (i = 0; i < 80; i++)
	blank[i] = ' ';

    /*  find length of keyword and value */
    lkeyword = strlen (keyword);
    lval = strlen (value);

    /*  If COMMENT or HISTORY, always add it just before the END */
    if (lkeyword == 7 && (strncmp (keyword,"COMMENT",7) == 0 ||
	strncmp (keyword,"HISTORY",7) == 0)) {

	/* Find end of header */
	v1 = ksearch (hstring,"END");
	v2 = v1 + 80;

	/* Move END down one line */
	strncpy (v2, v1, 80);

	/* Insert keyword */
	strncpy (v1,keyword,7);

	/* Pad with spaces */
	for (vp = v1+lkeyword; vp < v2; vp++)
	    *vp = ' ';

	/* Insert comment */
	strncpy (v1+9,value,lval);
	return;
	}

    /* Otherwise search for keyword */
    else
	v1 = ksearch (hstring,keyword);

    /*  If parameter is not found, find a place to put it */
    if (v1 == NULL) {
	
	/* First look for blank lines before END */
        v1 = blsearch (hstring, "END");
    
	/*  Otherwise, create a space for it at the end of the header */
	if (v1 == NULL) {
	    ve = ksearch (hstring,"END");
	    v1 = ve;
	    v2 = v1 + 80;
	    strncpy (v2, ve, 80);
	    }
	else
	    v2 = v1 + 80;
	lcom = 0;
	newcom[0] = 0;
	}

    /*  Otherwise, extract the entry for this keyword from the header */
    else {
	strncpy (line, v1, 80);
	line[80] = 0;
	v2 = v1 + 80;

	/*  check for quoted value */
	q1 = strchr (line, squot);
	if (q1 != NULL)
	    q2 = strchr (q1+1,squot);
	else
	    q2 = line;

	/*  extract comment and remove trailing spaces */

	c1 = strchr (q2,'/');
	if (c1 != NULL) {
	    lcom = 80 - (c1 - line);
	    strncpy (newcom, c1+1, lcom);
	    vp = newcom + lcom - 1;
	    while (vp-- > newcom && *vp == ' ')
		*vp = 0;
	    lcom = strlen (newcom);
	    }
	else {
	    newcom[0] = 0;
	    lcom = 0;
	    }
	}

    /* Fill new entry with spaces */
    for (vp = v1; vp < v2; vp++)
	*vp = ' ';

    /*  Copy keyword to new entry */
    strncpy (v1, keyword, lkeyword);

    /*  Add parameter value in the appropriate place */
    vp = v1 + 8;
    *vp = '=';
    vp = v1 + 9;
    *vp = ' ';
    vp = vp + 1;
    if (*value == squot) {
	strncpy (vp, value, lval);
	if (lval+12 > 31)
	    lc = lval + 12;
	else
	    lc = 30;
	}
    else {
	vp = v1 + 30 - lval;
	strncpy (vp, value, lval);
	lc = 30;
	}

    /* Add comment in the appropriate place */
	if (lcom > 0) {
	    if (lc+2+lcom > 80)
		lcom = 78 - lc;
	    vp = v1 + lc + 2;     /* Jul 16 1997: was vp = v1 + lc * 2 */
	    *vp = '/';
	    vp = vp + 1;
	    strncpy (vp, newcom, lcom);
	    for (v = vp + lcom; v < v2; v++)
		*v = ' ';
	    }

	return;
}

/*-------------------------------------------------------------------*/
/*  HPUTCOM - Set comment for keyword or on line in FITS header string */

static void
hputcom (hstring,keyword,comment)

  char *hstring;
  char *keyword;
  char *comment;
{
	char squot;
	char line[100];
	int lkeyword, lcom;
	char *vp, *v1, *v2, *c0 = NULL, *c1, *q1, *q2;

	squot = 39;

/*  Find length of variable name */
	lkeyword = strlen (keyword);

/*  If COMMENT or HISTORY, always add it just before the END */
	if (lkeyword == 7 && (strncmp (keyword,"COMMENT",7) == 0 ||
	    strncmp (keyword,"HISTORY",7) == 0)) {

	/* Find end of header */
	    v1 = ksearch (hstring,"END");
	    v2 = v1 + 80;
	    strncpy (v2, v1, 80);

	/*  blank out new line and insert keyword */
	    for (vp = v1; vp < v2; vp++)
		*vp = ' ';
	    strncpy (v1, keyword, lkeyword);
	    }

/* search header string for variable name */
	else {
	    v1 = ksearch (hstring,keyword);
	    v2 = v1 + 80;

	/* if parameter is not found, return without doing anything */
	    if (v1 == NULL) {
		return;
		}

	/* otherwise, extract entry for this variable from the header */
	    strncpy (line, v1, 80);

	/* check for quoted value */
	    q1 = strchr (line,squot);
	    if (q1 != NULL)
		q2 = strchr (q1+1,squot);
	    else
		q2 = NULL;

	    if (q2 == NULL || q2-line < 31)
		c0 = v1 + 31;
	    else
		c0 = v1 + (q2-line) + 2; /* allan: 1997-09-30, was c0=q2+2 */

	    strncpy (c0, "/ ",2);
	    }

/* create new entry */
	lcom = strlen (comment);

	if (lcom > 0) {
	    c1 = c0 + 2;
	    if (c1+lcom > v2)
		lcom = v2 - c1;
	    strncpy (c1, comment, lcom);
	    }

}
cfitsio/iter_a.c0000644000225700000360000001220513246025103013407 0ustar  cagordonlhea#include 
#include 
#include 
#include "fitsio.h"

/*
  This program illustrates how to use the CFITSIO iterator function.
  It reads and modifies the input 'iter_a.fit' file by computing a
  value for the 'rate' column as a function of the values in the other
  'counts' and 'time' columns.
*/
main()
{
    extern flux_rate(); /* external work function is passed to the iterator */
    fitsfile *fptr;
    iteratorCol cols[3];  /* structure used by the iterator function */
    int n_cols;
    long rows_per_loop, offset;

    int status, nkeys, keypos, hdutype, ii, jj;
    char filename[]  = "iter_a.fit";     /* name of rate FITS file */

    status = 0; 

    fits_open_file(&fptr, filename, READWRITE, &status); /* open file */

    /* move to the desired binary table extension */
    if (fits_movnam_hdu(fptr, BINARY_TBL, "RATE", 0, &status) )
        fits_report_error(stderr, status);    /* print out error messages */

    n_cols  = 3;   /* number of columns */

    /* define input column structure members for the iterator function */
    fits_iter_set_by_name(&cols[0], fptr, "COUNTS", TLONG,  InputCol);
    fits_iter_set_by_name(&cols[1], fptr, "TIME",   TFLOAT, InputCol);
    fits_iter_set_by_name(&cols[2], fptr, "RATE",   TFLOAT, OutputCol);

    rows_per_loop = 0;  /* use default optimum number of rows */
    offset = 0;         /* process all the rows */

    /* apply the rate function to each row of the table */
    printf("Calling iterator function...%d\n", status);

    fits_iterate_data(n_cols, cols, offset, rows_per_loop,
                      flux_rate, 0L, &status);

    fits_close_file(fptr, &status);      /* all done */

    if (status)
        fits_report_error(stderr, status);  /* print out error messages */

    return(status);
}
/*--------------------------------------------------------------------------*/
int flux_rate(long totalrows, long offset, long firstrow, long nrows,
             int ncols, iteratorCol *cols, void *user_strct ) 

/*
   Sample iterator function that calculates the output flux 'rate' column
   by dividing the input 'counts' by the 'time' column.
   It also applies a constant deadtime correction factor if the 'deadtime'
   keyword exists.  Finally, this creates or updates the 'LIVETIME'
   keyword with the sum of all the individual integration times.
*/
{
    int ii, status = 0;

    /* declare variables static to preserve their values between calls */
    static long *counts;
    static float *interval;
    static float *rate;
    static float deadtime, livetime; /* must preserve values between calls */

    /*--------------------------------------------------------*/
    /*  Initialization procedures: execute on the first call  */
    /*--------------------------------------------------------*/
    if (firstrow == 1)
    {
       if (ncols != 3)
           return(-1);  /* number of columns incorrect */

       if (fits_iter_get_datatype(&cols[0]) != TLONG  ||
           fits_iter_get_datatype(&cols[1]) != TFLOAT ||
           fits_iter_get_datatype(&cols[2]) != TFLOAT )
           return(-2);  /* bad data type */

       /* assign the input pointers to the appropriate arrays and null ptrs*/
       counts       = (long *)  fits_iter_get_array(&cols[0]);
       interval     = (float *) fits_iter_get_array(&cols[1]);
       rate         = (float *) fits_iter_get_array(&cols[2]);

       livetime = 0;  /* initialize the total integration time */

       /* try to get the deadtime keyword value */
       fits_read_key(cols[0].fptr, TFLOAT, "DEADTIME", &deadtime, '\0',
                     &status);
       if (status)
       {
           deadtime = 1.0;  /* default deadtime if keyword doesn't exist */
       }
       else if (deadtime < 0. || deadtime > 1.0)
       {
           return(-1);    /* bad deadtime value */
       }

       printf("deadtime = %f\n", deadtime);
    }

    /*--------------------------------------------*/
    /*  Main loop: process all the rows of data */
    /*--------------------------------------------*/

    /*  NOTE: 1st element of array is the null pixel value!  */
    /*  Loop from 1 to nrows, not 0 to nrows - 1.  */

    /* this version tests for null values */
    rate[0] = DOUBLENULLVALUE;   /* define the value that represents null */

    for (ii = 1; ii <= nrows; ii++)
    {
       if (counts[ii] == counts[0])   /*  undefined counts value? */
       {
           rate[ii] = DOUBLENULLVALUE;
       }
       else if (interval[ii] > 0.)
       {
           rate[ii] = counts[ii] / interval[ii] / deadtime;
           livetime += interval[ii];  /* accumulate total integration time */
       }
       else
           return(-2);  /* bad integration time */
    }

    /*-------------------------------------------------------*/
    /*  Clean up procedures:  after processing all the rows  */
    /*-------------------------------------------------------*/

    if (firstrow + nrows - 1 == totalrows)
    {
        /*  update the LIVETIME keyword value */

        fits_update_key(cols[0].fptr, TFLOAT, "LIVETIME", &livetime, 
                 "total integration time", &status);
        printf("livetime = %f\n", livetime);
   }
    return(0);  /* return successful status */
}
cfitsio/iter_a.f0000644000225700000360000001533213246025103013416 0ustar  cagordonlhea      program f77iterate_a

      external flux_rate
      integer ncols
      parameter (ncols=3)
      integer units(ncols), colnum(ncols), datatype(ncols)
      integer iotype(ncols), offset, rows_per_loop, status
      character*70 colname(ncols)
      integer iunit, blocksize
      character*80 fname

C     include f77.inc -------------------------------------
C     Codes for FITS extension types
      integer IMAGE_HDU, ASCII_TBL, BINARY_TBL
      parameter (
     &     IMAGE_HDU  = 0,
     &     ASCII_TBL  = 1,
     &     BINARY_TBL = 2  )

C     Codes for FITS table data types

      integer TBIT,TBYTE,TLOGICAL,TSTRING,TSHORT,TINT
      integer TFLOAT,TDOUBLE,TCOMPLEX,TDBLCOMPLEX
      parameter (
     &     TBIT        =   1,
     &     TBYTE       =  11,
     &     TLOGICAL    =  14,
     &     TSTRING     =  16,
     &     TSHORT      =  21,
     &     TINT        =  31,
     &     TFLOAT      =  42,
     &     TDOUBLE     =  82,
     &     TCOMPLEX    =  83,
     &     TDBLCOMPLEX = 163  )

C     Codes for iterator column types

      integer InputCol, InputOutputCol, OutputCol
      parameter (
     &     InputCol       = 0,
     &     InputOutputCol = 1,
     &     OutputCol      = 2  )
C     End of f77.inc -------------------------------------


      iunit = 15

      units(1) = iunit
      units(2) = iunit
      units(3) = iunit

C open the file
      fname = 'iter_a.fit'
      call ftopen(iunit,fname,1,blocksize,status)

C move to the HDU containing the rate table
      call ftmnhd(iunit, BINARY_TBL, 'RATE', 0, status)

C Select iotypes for column data
      iotype(1) = InputCol
      iotype(2) = InputCol
      iotype(3) = OutputCol

C Select desired datatypes for column data
      datatype(1) = TINT
      datatype(2) = TFLOAT
      datatype(3) = TFLOAT

C find the column number corresponding to each column
      call ftgcno( iunit, 0, 'counts', colnum(1), status )
      call ftgcno( iunit, 0, 'time', colnum(2), status )
      call ftgcno( iunit, 0, 'rate', colnum(3), status )

C use default optimum number of rows
      rows_per_loop = 0
      offset = 0

C apply the rate function to each row of the table
      print *, 'Calling iterator function...', status

C although colname is not being used, still need to send a string
C array in the function
      call ftiter( ncols, units, colnum, colname, datatype, iotype,
     &      offset, rows_per_loop, flux_rate, 3, status )

      call ftclos(iunit, status)
      stop
      end

C***************************************************************************
C   Sample iterator function that calculates the output flux 'rate' column
C   by dividing the input 'counts' by the 'time' column.
C   It also applies a constant deadtime correction factor if the 'deadtime'
C   keyword exists.  Finally, this creates or updates the 'LIVETIME'
C   keyword with the sum of all the individual integration times.
C***************************************************************************
      subroutine flux_rate(totalrows, offset, firstrow, nrows, ncols,
     &     units, colnum, datatype, iotype, repeat, status, userData,
     &     counts, interval, rate )

      integer totalrows, offset, firstrow, nrows, ncols
      integer units(ncols), colnum(ncols), datatype(ncols)
      integer iotype(ncols), repeat(ncols)
      integer userData

C     include f77.inc -------------------------------------
C     Codes for FITS extension types
      integer IMAGE_HDU, ASCII_TBL, BINARY_TBL
      parameter (
     &     IMAGE_HDU  = 0,
     &     ASCII_TBL  = 1,
     &     BINARY_TBL = 2  )

C     Codes for FITS table data types

      integer TBIT,TBYTE,TLOGICAL,TSTRING,TSHORT,TINT
      integer TFLOAT,TDOUBLE,TCOMPLEX,TDBLCOMPLEX
      parameter (
     &     TBIT        =   1,
     &     TBYTE       =  11,
     &     TLOGICAL    =  14,
     &     TSTRING     =  16,
     &     TSHORT      =  21,
     &     TINT        =  31,
     &     TFLOAT      =  42,
     &     TDOUBLE     =  82,
     &     TCOMPLEX    =  83,
     &     TDBLCOMPLEX = 163  )

C     Codes for iterator column types

      integer InputCol, InputOutputCol, OutputCol
      parameter (
     &     InputCol       = 0,
     &     InputOutputCol = 1,
     &     OutputCol      = 2  )
C     End of f77.inc -------------------------------------

      integer counts(*)
      real interval(*),rate(*)

      integer ii, status
      character*80 comment

C**********************************************************************
C  must preserve these values between calls
      real deadtime, livetime
      common /fluxblock/ deadtime, livetime
C**********************************************************************

      if (status .ne. 0) return

C    --------------------------------------------------------
C      Initialization procedures: execute on the first call  
C    --------------------------------------------------------
      if (firstrow .eq. 1) then
         if (ncols .ne. 3) then
C     wrong number of columns
            status = -1
            return
         endif

         if (datatype(1).ne.TINT .or. datatype(2).ne.TFLOAT .or.
     &        datatype(3).ne.TFLOAT ) then
C     bad data type
            status = -2
            return
         endif

C     try to get the deadtime keyword value
         call ftgkye( units(1), 'DEADTIME', deadtime, comment, status )

         if (status.ne.0) then
C     default deadtime if keyword doesn't exist
            deadtime = 1.0
            status = 0
         elseif (deadtime .lt. 0.0 .or. deadtime .gt. 1.0) then
C     bad deadtime value
            status = -3
            return
         endif

         print *, 'deadtime = ', deadtime

         livetime = 0.0
      endif

C    --------------------------------------------
C      Main loop: process all the rows of data
C    --------------------------------------------
      
C     NOTE: 1st element of array is the null pixel value!
C     Loop over elements 2 to nrows+1, not 1 to nrows.
      
C     this version ignores null values

C     set the output null value to zero to ignore nulls */
      rate(1) = 0.0
      do 10 ii = 2,nrows+1
         if ( interval(ii) .gt. 0.0) then
           rate(ii) = counts(ii) / interval(ii) / deadtime
           livetime = livetime + interval(ii)
        else
C     Nonsensical negative time interval
           status = -3
           return
        endif
 10   continue

C    -------------------------------------------------------
C      Clean up procedures:  after processing all the rows  
C    -------------------------------------------------------

      if (firstrow + nrows - 1 .eq. totalrows) then
C     update the LIVETIME keyword value

         call ftukye( units(1),'LIVETIME', livetime, 3,
     &        'total integration time', status )
         print *,'livetime = ', livetime

      endif
 
      return
      end
cfitsio/iter_a.fit0000644000225700000360000037510013246025103013755 0ustar  cagordonlheaSIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    0 / number of data axes                            EXTEND  =                    T / FITS dataset may contain extensions            COMMENT   FITS (Flexible Image Transport System) format defined in Astronomy andCOMMENT   Astrophysics Supplement Series v44/p363, v44/p371, v73/p359, v73/p365.COMMENT   Contact the NASA Science Office of Standards and Technology for the   COMMENT   FITS Definition document #100 and other FITS information.             HISTORY    TASK:FMERGE on file ratefile.fits                                    HISTORY   fmerge3.1c at 29/12/97 16:1:37.                                       HISTORY    TASK:FMERGE on file m1.fits                                          HISTORY   fmerge3.1c at 29/12/97 16:2:30.                                       HISTORY    TASK:FMERGE on file m3.fits                                          HISTORY   fmerge3.1c at 29/12/97 16:3:38.                                       HISTORY    TASK:FMERGE on file m5.fits                                          HISTORY   fmerge3.1c at 29/12/97 16:4:15.                                       HISTORY    TASK:FMERGE on file m7.fits                                          HISTORY   fmerge3.1c at 29/12/97 16:5:1.0                                       HISTORY    TASK:FMERGE on file m9.fits                                          HISTORY   fmerge3.1c at 29/12/97 16:6:48.                                       END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             XTENSION= 'BINTABLE'           / binary table extension                         BITPIX  =                    8 / 8-bit bytes                                    NAXIS   =                    2 / 2-dimensional binary table                     NAXIS1  =                   12 / width of table in bytes                        NAXIS2  =                10000 / number of rows in table                        PCOUNT  =                    0 / size of special data area                      GCOUNT  =                    1 / one data group (required keyword)              TFIELDS =                    3 / number of fields in each row                   TTYPE1  = 'Counts  '           / label for field   1                            TFORM1  = 'J       '           / data format of field: 4-byte INTEGER           TTYPE2  = 'Time    '           / label for field   2                            TFORM2  = 'E       '           / data format of field: 4-byte REAL              TTYPE3  = 'Rate    '           / label for field   3                            TFORM3  = 'E       '           / data format of field: 4-byte REAL              EXTNAME = 'rate    '           / name of this binary table extension            DEADTIME=                  1.0                                                  HISTORY   This FITS file was created by the FCREATE task.                       HISTORY   fcreate3.1 at 29/12/97                                                HISTORY   File modified by user 'pence' with fv  on 97-12-29T15:45:06           HISTORY   File modified by user 'pence' with fv  on 97-12-29T15:54:30           LIVETIME=              30554.5 / total integration time                         HISTORY    TASK:FMERGE copied   26924 rows from file ratefile.fits              HISTORY    TASK:FMERGE appended   26924 rows from file r2.fits                  HISTORY    TASK:FMERGE copied   53848 rows from file m1.fits                    HISTORY    TASK:FMERGE appended   53848 rows from file m2.fits                  HISTORY    TASK:FMERGE copied  107696 rows from file m3.fits                    HISTORY    TASK:FMERGE appended  107696 rows from file m4.fits                  HISTORY    TASK:FMERGE copied  215392 rows from file m5.fits                    HISTORY    TASK:FMERGE appended  215392 rows from file m6.fits                  HISTORY    TASK:FMERGE copied  430784 rows from file m7.fits                    HISTORY    TASK:FMERGE appended  430784 rows from file m8.fits                  HISTORY    TASK:FMERGE copied  861568 rows from file m9.fits                    HISTORY    TASK:FMERGE appended  861568 rows from file m10.fits                 HISTORY   File modified by user 'pence' with fv  on 97-12-30T10:44:37           HISTORY   File modified by user 'pence' with fv  on 97-12-30T10:51:44           HISTORY   ftabcopy V4.0a copied columns from ratefile.fits                      HISTORY   ftabcopy V4.0a at 5/1/98 23:10:24                                     END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À@@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À@@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ ?€@ÀdA A ?€@ ?€@@@AUU-@ð@À
?€A @@°?€@ cfitsio/iter_b.c0000644000225700000360000000716613246025103013422 0ustar  cagordonlhea#include 
#include 
#include 
#include "fitsio.h"

/*
  This program illustrates how to use the CFITSIO iterator function.
  It simply prints out the values in a character string and a logical
  type column in a table, and toggles the value in the logical column
  so that T -> F and F -> T.
*/
main()
{
    extern str_iter(); /* external work function is passed to the iterator */
    fitsfile *fptr;
    iteratorCol cols[2];
    int n_cols;
    long rows_per_loop, offset;
    int status = 0;
    char filename[]  = "iter_b.fit";     /* name of rate FITS file */

    /* open the file and move to the correct extension */
    fits_open_file(&fptr, filename, READWRITE, &status);
    fits_movnam_hdu(fptr, BINARY_TBL, "iter_test", 0, &status);

    /* define input column structure members for the iterator function */
    n_cols  = 2;   /* number of columns */

    /* define input column structure members for the iterator function */
    fits_iter_set_by_name(&cols[0], fptr, "Avalue", TSTRING,  InputOutputCol);
    fits_iter_set_by_name(&cols[1], fptr, "Lvalue", TLOGICAL, InputOutputCol);

    rows_per_loop = 0;  /* use default optimum number of rows */
    offset = 0;         /* process all the rows */

    /* apply the  function to each row of the table */
    printf("Calling iterator function...%d\n", status);

    fits_iterate_data(n_cols, cols, offset, rows_per_loop,
                      str_iter, 0L, &status);

    fits_close_file(fptr, &status);      /* all done */

    if (status)
       fits_report_error(stderr, status); /* print out error messages */

    return(status);
}
/*--------------------------------------------------------------------------*/
int str_iter(long totalrows, long offset, long firstrow, long nrows,
             int ncols, iteratorCol *cols, void *user_strct )

/*
   Sample iterator function.
*/
{
    int ii;

    /* declare variables static to preserve their values between calls */
    static char **stringvals;
    static char *logicalvals;

    /*--------------------------------------------------------*/
    /*  Initialization procedures: execute on the first call  */
    /*--------------------------------------------------------*/
    if (firstrow == 1)
    {
       if (ncols != 2)
           return(-1);  /* number of columns incorrect */

       if (fits_iter_get_datatype(&cols[0]) != TSTRING ||
           fits_iter_get_datatype(&cols[1]) != TLOGICAL )
           return(-2);  /* bad data type */

       /* assign the input pointers to the appropriate arrays */
       stringvals       = (char **) fits_iter_get_array(&cols[0]);
       logicalvals      = (char *)  fits_iter_get_array(&cols[1]);

       printf("Total rows, No. rows = %d %d\n",totalrows, nrows);
    }

    /*------------------------------------------*/
    /*  Main loop: process all the rows of data */
    /*------------------------------------------*/

    /*  NOTE: 1st element of array is the null pixel value!  */
    /*  Loop from 1 to nrows, not 0 to nrows - 1.  */
   
    for (ii = 1; ii <= nrows; ii++)
    {
      printf("%s %d\n", stringvals[ii], logicalvals[ii]);
      if (logicalvals[ii])
      {
         logicalvals[ii] = FALSE;
         strcpy(stringvals[ii], "changed to false");
      }
      else
      {
         logicalvals[ii] = TRUE;
         strcpy(stringvals[ii], "changed to true");
      }
    }

    /*-------------------------------------------------------*/
    /*  Clean up procedures:  after processing all the rows  */
    /*-------------------------------------------------------*/

    if (firstrow + nrows - 1 == totalrows)
    {
      /* no action required in this case */
    }
 
    return(0);
}
cfitsio/iter_b.f0000644000225700000360000001305713246025103013421 0ustar  cagordonlhea      program f77iterate_b

C     external work function is passed to the iterator
      external str_iter

      integer ncols
      parameter (ncols=2)
      integer units(ncols), colnum(ncols), datatype(ncols)
      integer iotype(ncols), offset, rows_per_loop, status
      character*70 colname(ncols)

      integer iunit, blocksize
      character*80 fname

C     include f77.inc -------------------------------------
C     Codes for FITS extension types
      integer IMAGE_HDU, ASCII_TBL, BINARY_TBL
      parameter (
     &     IMAGE_HDU  = 0,
     &     ASCII_TBL  = 1,
     &     BINARY_TBL = 2  )

C     Codes for FITS table data types

      integer TBIT,TBYTE,TLOGICAL,TSTRING,TSHORT,TINT
      integer TFLOAT,TDOUBLE,TCOMPLEX,TDBLCOMPLEX
      parameter (
     &     TBIT        =   1,
     &     TBYTE       =  11,
     &     TLOGICAL    =  14,
     &     TSTRING     =  16,
     &     TSHORT      =  21,
     &     TINT        =  31,
     &     TFLOAT      =  42,
     &     TDOUBLE     =  82,
     &     TCOMPLEX    =  83,
     &     TDBLCOMPLEX = 163  )

C     Codes for iterator column types

      integer InputCol, InputOutputCol, OutputCol
      parameter (
     &     InputCol       = 0,
     &     InputOutputCol = 1,
     &     OutputCol      = 2  )
C     End of f77.inc -------------------------------------

      status = 0

      fname = 'iter_b.fit'
      iunit = 15

C     both columns are in the same FITS file
      units(1) = iunit
      units(2) = iunit

C     open the file and move to the correct extension
      call ftopen(iunit,fname,1,blocksize,status)
      call ftmnhd(iunit, BINARY_TBL, 'iter_test', 0, status)

C     define the desired columns by name
      colname(1) = 'Avalue'
      colname(2) = 'Lvalue'

C     leave column numbers undefined
      colnum(1) = 0
      colnum(2) = 0  

C     define the desired datatype for each column: TSTRING & TLOGICAL
      datatype(1) = TSTRING
      datatype(2) = TLOGICAL

C     define whether columns are input, input/output, or output only
C     Both in/out
      iotype(1) = InputOutputCol
      iotype(2) = InputOutputCol
 
C     use default optimum number of rows and process all the rows
      rows_per_loop = 0
      offset = 0

C     apply the  function to each row of the table
      print *,'Calling iterator function...', status

      call ftiter( ncols, units, colnum, colname, datatype, iotype,
     &      offset, rows_per_loop, str_iter, 0, status )

      call ftclos(iunit, status)

C     print out error messages if problem
      if (status.ne.0) call ftrprt('STDERR', status)
      stop
      end

C--------------------------------------------------------------------------
C
C   Sample iterator function.
C
C--------------------------------------------------------------------------
      subroutine str_iter(totalrows, offset, firstrow, nrows, ncols,
     &     units, colnum, datatype, iotype, repeat, status, 
     &     userData, stringCol, logicalCol )

      integer totalrows,offset,firstrow,nrows,ncols,status
      integer units(*),colnum(*),datatype(*),iotype(*),repeat(*)
      integer userData
      character*(*) stringCol(*)
      logical logicalCol(*)

      integer ii

C     include f77.inc -------------------------------------
C     Codes for FITS extension types
      integer IMAGE_HDU, ASCII_TBL, BINARY_TBL
      parameter (
     &     IMAGE_HDU  = 0,
     &     ASCII_TBL  = 1,
     &     BINARY_TBL = 2  )

C     Codes for FITS table data types

      integer TBIT,TBYTE,TLOGICAL,TSTRING,TSHORT,TINT
      integer TFLOAT,TDOUBLE,TCOMPLEX,TDBLCOMPLEX
      parameter (
     &     TBIT        =   1,
     &     TBYTE       =  11,
     &     TLOGICAL    =  14,
     &     TSTRING     =  16,
     &     TSHORT      =  21,
     &     TINT        =  31,
     &     TFLOAT      =  42,
     &     TDOUBLE     =  82,
     &     TCOMPLEX    =  83,
     &     TDBLCOMPLEX = 163  )

C     Codes for iterator column types

      integer InputCol, InputOutputCol, OutputCol
      parameter (
     &     InputCol       = 0,
     &     InputOutputCol = 1,
     &     OutputCol      = 2  )
C     End of f77.inc -------------------------------------

      if (status .ne. 0) return

C    --------------------------------------------------------
C      Initialization procedures: execute on the first call  
C    --------------------------------------------------------
      if (firstrow .eq. 1) then
         if (ncols .ne. 2) then
            status = -1
            return
         endif
         
         if (datatype(1).ne.TSTRING .or. datatype(2).ne.TLOGICAL) then
            status = -2
            return
         endif
         
         print *,'Total rows, No. rows = ',totalrows, nrows
         
      endif
      
C     -------------------------------------------
C       Main loop: process all the rows of data 
C     -------------------------------------------
      
C     NOTE: 1st element of array is the null pixel value!
C     Loop over elements 2 to nrows+1, not 1 to nrows.
      
      do 10 ii=2,nrows+1
         print *, stringCol(ii), logicalCol(ii)
         if( logicalCol(ii) ) then
            logicalCol(ii) = .false.
            stringCol(ii) = 'changed to false'
         else
            logicalCol(ii) = .true.
            stringCol(ii) = 'changed to true'
         endif
 10   continue
      
C     -------------------------------------------------------
C     Clean up procedures:  after processing all the rows  
C     -------------------------------------------------------
      
      if (firstrow + nrows - 1 .eq. totalrows) then
C     no action required in this case
      endif
      
      return
      end
      
cfitsio/iter_b.fit0000644000225700000360000143660013246025103013762 0ustar  cagordonlheaSIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                   16 / number of bits per data pixel                  NAXIS   =                    0 / number of data axes                            EXTEND  =                    T / FITS dataset may contain extensions            COMMENT   FITS (Flexible Image Transport System) format defined in Astronomy andCOMMENT   Astrophysics Supplement Series v44/p363, v44/p371, v73/p359, v73/p365.COMMENT   Contact the NASA Science Office of Standards and Technology for the   COMMENT   FITS Definition document #100 and other FITS information.             END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             XTENSION= 'BINTABLE'           / binary table extension                         BITPIX  =                    8 / 8-bit bytes                                    NAXIS   =                    2 / 2-dimensional binary table                     NAXIS1  =                 4021 / width of table in bytes                        NAXIS2  =                  100 / number of rows in table                        PCOUNT  =                    0 / size of special data area                      GCOUNT  =                    1 / one data group (required keyword)              TFIELDS =                    3 / number of fields in each row                   TTYPE1  = 'Avalue  '           / label for field   1                            TFORM1  = '20A     '           / data format of field: ASCII Character          TTYPE2  = 'Lvalue  '           / label for field   2                            TFORM2  = '1L      '           / data format of field: 1-byte LOGICAL           TUNIT2  = 'm**2    '           / physical unit of field                         TTYPE3  = 'Evalue  '           / label for field   3                            TFORM3  = '1000E   '           / data format of field: 4-byte REAL              TUNIT3  = 'cm      '           / physical unit of field                         EXTNAME = 'iter_test'          / name of this binary table extension            END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             changed to false    Fchanged to true     Tchanged to false    Fchanged to true     Tchanged to false    Fchanged to true     Tchanged to false    Fchanged to true     Tchanged to false    Fchanged to true     Tchanged to true     Tchanged to true     Tchanged to true     Tchanged to true     Tchanged to true     Tchanged to true     Tchanged to true     Tchanged to true     Tchanged to false    Fchanged to true     Tchanged to false    Fchanged to true     Tchanged to false    Fchanged to true     Tchanged to false    Fchanged to true     Tchanged to false    Fchanged to true     Tchanged to true     Tchanged to true     Tchanged to true     Tchanged to true     Tchanged to true     Tchanged to true     Tchanged to false    Fchanged to true     Tchanged to false    Fchanged to true     Tchanged to false    Fchanged to true     Tchanged to false    Fchanged to true     Tchanged to false    Fchanged to true     Tchanged to true     Tchanged to true     Tchanged to true     Tchanged to true     Tchanged to true     Tchanged to true     Tchanged to true     Tchanged to true     Tchanged to false    Fchanged to true     Tchanged to false    Fchanged to true     Tchanged to false    Fchanged to true     Tchanged to false    Fchanged to true     Tchanged to false    Fchanged to true     Tchanged to true     Tchanged to true     Tchanged to true     Tchanged to true     Tchanged to true     Tchanged to true     Tchanged to false    Fchanged to true     Tchanged to false    Fchanged to true     Tchanged to false    Fchanged to true     Tchanged to false    Fchanged to true     Tchanged to false    Fchanged to true     Tchanged to true     Tchanged to true     Tchanged to true     Tchanged to true     Tchanged to true     Tchanged to true     Tchanged to true     Tchanged to true     Tchanged to false    Fchanged to true     Tchanged to false    Fchanged to true     Tchanged to false    Fchanged to true     Tchanged to false    Fchanged to true     Tchanged to false    Fchanged to true     Tchanged to true     Tchanged to true     Tchanged to true     Tchanged to true     Tcfitsio/iter_c.c0000644000225700000360000001356713246025103013425 0ustar  cagordonlhea#include 
#include 
#include 
#include "fitsio.h"

/*
    This example program illustrates how to use the CFITSIO iterator function.

    This program creates a 2D histogram of the X and Y columns of an event
    list.  The 'main' routine just creates the empty new image, then executes
    the 'writehisto' work function by calling the CFITSIO iterator function.

    'writehisto' opens the FITS event list that contains the X and Y columns.
    It then calls a second work function, calchisto, (by recursively calling
    the CFITSIO iterator function) which actually computes the 2D histogram.
*/

/*   Globally defined parameters */

long xsize = 480; /* size of the histogram image */
long ysize = 480;
long xbinsize = 32;
long ybinsize = 32;

main()
{
    extern writehisto();  /* external work function passed to the iterator */
    extern long xsize, ysize;  /* size of image */

    fitsfile *fptr;
    iteratorCol cols[1];
    int n_cols, status = 0;
    long n_per_loop, offset, naxes[2];
    char filename[]  = "histoimg.fit";     /* name of FITS image */

    remove(filename);   /* delete previous version of the file if it exists */
    fits_create_file(&fptr, filename, &status);  /* create new output image */

    naxes[0] = xsize;
    naxes[1] = ysize;
    fits_create_img(fptr, LONG_IMG, 2, naxes, &status); /* create primary HDU */

    n_cols  = 1;   /* number of columns */

    /* define input column structure members for the iterator function */
    fits_iter_set_by_name(&cols[0], fptr, " ", TLONG, OutputCol);

    n_per_loop = -1;  /* force whole array to be passed at one time */
    offset = 0;       /* don't skip over any pixels */

    /* execute the function to create and write the 2D histogram */
    printf("Calling writehisto iterator work function... %d\n", status);

    fits_iterate_data(n_cols, cols, offset, n_per_loop,
                      writehisto, 0L, &status);

    fits_close_file(fptr, &status);      /* all done; close the file */

    if (status)
        fits_report_error(stderr, status);  /* print out error messages */
    else
        printf("Program completed successfully.\n");

    return(status);
}
/*--------------------------------------------------------------------------*/
int writehisto(long totaln, long offset, long firstn, long nvalues,
             int narrays, iteratorCol *histo, void *userPointer)
/*
   Iterator work function that writes out the 2D histogram.
   The histogram values are calculated by another work function, calchisto.

   This routine is executed only once since nvalues was forced to = totaln.
*/
{
    extern calchisto();  /* external function called by the iterator */
    long *histogram;
    fitsfile *tblptr;
    iteratorCol cols[2];
    int n_cols, status = 0;
    long rows_per_loop, rowoffset;
    char filename[]  = "iter_c.fit";     /* name of FITS table */

    /* do sanity checking of input values */
    if (totaln != nvalues)
        return(-1);  /* whole image must be passed at one time */

    if (narrays != 1)
        return(-2);  /* number of images is incorrect */

    if (fits_iter_get_datatype(&histo[0]) != TLONG)
        return(-3);  /* input array has wrong data type */

    /* assign the FITS array pointer to the global histogram pointer */
    histogram = (long *) fits_iter_get_array(&histo[0]);

    /* open the file and move to the table containing the X and Y columns */
    fits_open_file(&tblptr, filename, READONLY, &status);
    fits_movnam_hdu(tblptr, BINARY_TBL, "EVENTS", 0, &status);
    if (status)
       return(status);
   
    n_cols = 2; /* number of columns */

    /* define input column structure members for the iterator function */
    fits_iter_set_by_name(&cols[0], tblptr, "X", TLONG,  InputCol);
    fits_iter_set_by_name(&cols[1], tblptr, "Y", TLONG, InputCol);

    rows_per_loop = 0;  /* take default number of rows per interation */
    rowoffset = 0;     

    /* calculate the histogram */
    printf("Calling calchisto iterator work function... %d\n", status);

    fits_iterate_data(n_cols, cols, rowoffset, rows_per_loop,
                      calchisto, histogram, &status);

    fits_close_file(tblptr, &status);      /* all done */
    return(status);
}
/*--------------------------------------------------------------------------*/
int calchisto(long totalrows, long offset, long firstrow, long nrows,
             int ncols, iteratorCol *cols, void *userPointer)

/*
   Interator work function that calculates values for the 2D histogram.
*/
{
    extern long xsize, ysize, xbinsize, ybinsize;
    long ii, ihisto, xbin, ybin;
    static long *xcol, *ycol, *histogram;  /* static to preserve values */

    /*--------------------------------------------------------*/
    /*  Initialization procedures: execute on the first call  */
    /*--------------------------------------------------------*/
    if (firstrow == 1)
    {
        /* do sanity checking of input values */
       if (ncols != 2)
         return(-3);  /* number of arrays is incorrect */

       if (fits_iter_get_datatype(&cols[0]) != TLONG ||
           fits_iter_get_datatype(&cols[1]) != TLONG)
         return(-4);  /* wrong datatypes */

       /* assign the input array points to the X and Y arrays */
       xcol = (long *) fits_iter_get_array(&cols[0]);
       ycol = (long *) fits_iter_get_array(&cols[1]);
       histogram = (long *) userPointer;

       /* initialize the histogram image pixels = 0 */
       for (ii = 0; ii <= xsize * ysize; ii++)
           histogram[ii] = 0L;
    }

    /*------------------------------------------------------------------*/
    /*  Main loop: increment the 2D histogram at position of each event */
    /*------------------------------------------------------------------*/

    for (ii = 1; ii <= nrows; ii++) 
    {
        xbin = xcol[ii] / xbinsize;
        ybin = ycol[ii] / ybinsize;

        ihisto = ( ybin * xsize ) + xbin + 1;
        histogram[ihisto]++;
    }

    return(0);
}

cfitsio/iter_c.f0000644000225700000360000002443513246025103013424 0ustar  cagordonlhea      program f77iterate_c
C
C    This example program illustrates how to use the CFITSIO iterator function.
C
C    This program creates a 2D histogram of the X and Y columns of an event
C    list.  The 'main' routine just creates the empty new image, then executes
C    the 'writehisto' work function by calling the CFITSIO iterator function.
C
C    'writehisto' opens the FITS event list that contains the X and Y columns.
C    It then calls a second work function, calchisto, (by recursively calling
C    the CFITSIO iterator function) which actually computes the 2D histogram.

C     external work function to be passed to the iterator
      external writehisto

      integer ncols
      parameter (ncols=1)
      integer units(ncols), colnum(ncols), datatype(ncols)
      integer iotype(ncols), offset, n_per_loop, status
      character*70 colname(ncols)

      integer naxes(2), ounit, blocksize
      character*80 fname
      logical exists

C     include f77.inc -------------------------------------
C     Codes for FITS extension types
      integer IMAGE_HDU, ASCII_TBL, BINARY_TBL
      parameter (
     &     IMAGE_HDU  = 0,
     &     ASCII_TBL  = 1,
     &     BINARY_TBL = 2  )

C     Codes for FITS table data types

      integer TBIT,TBYTE,TLOGICAL,TSTRING,TSHORT,TINT
      integer TFLOAT,TDOUBLE,TCOMPLEX,TDBLCOMPLEX
      parameter (
     &     TBIT        =   1,
     &     TBYTE       =  11,
     &     TLOGICAL    =  14,
     &     TSTRING     =  16,
     &     TSHORT      =  21,
     &     TINT        =  31,
     &     TFLOAT      =  42,
     &     TDOUBLE     =  82,
     &     TCOMPLEX    =  83,
     &     TDBLCOMPLEX = 163  )

C     Codes for iterator column types

      integer InputCol, InputOutputCol, OutputCol
      parameter (
     &     InputCol       = 0,
     &     InputOutputCol = 1,
     &     OutputCol      = 2  )
C     End of f77.inc -------------------------------------

C**********************************************************************
C     Need to make these variables available to the 2 work functions
      integer xsize,ysize,xbinsize,ybinsize
      common /histcomm/ xsize,ysize,xbinsize,ybinsize
C**********************************************************************

      status = 0

      xsize = 480
      ysize = 480
      xbinsize = 32
      ybinsize = 32

      fname = 'histoimg.fit'
      ounit = 15

C     delete previous version of the file if it exists
      inquire(file=fname,exist=exists)
      if( exists ) then
         open(ounit,file=fname,status='old')
         close(ounit,status='delete')
      endif
 99   blocksize = 2880

C     create new output image
      call ftinit(ounit,fname,blocksize,status)

      naxes(1) = xsize
      naxes(2) = ysize

C     create primary HDU
      call ftiimg(ounit,32,2,naxes,status)

      units(1) = ounit

C     Define column as TINT and Output
      datatype(1) = TINT
      iotype(1) = OutputCol

C     force whole array to be passed at one time
      n_per_loop = -1
      offset = 0

C     execute the function to create and write the 2D histogram
      print *,'Calling writehisto iterator work function... ',status

      call ftiter( ncols, units, colnum, colname, datatype, iotype,
     &      offset, n_per_loop, writehisto, 0, status )

      call ftclos(ounit, status)

C     print out error messages if problem
      if (status.ne.0) then
         call ftrprt('STDERR', status)
      else
        print *,'Program completed successfully.'
      endif

      stop
      end

C--------------------------------------------------------------------------
C
C   Sample iterator function.
C
C   Iterator work function that writes out the 2D histogram.
C   The histogram values are calculated by another work function, calchisto.
C
C--------------------------------------------------------------------------
      subroutine writehisto(totaln, offset, firstn, nvalues, narrays,
     &     units_out, colnum_out, datatype_out, iotype_out, repeat,
     &     status, userData, histogram )

      integer totaln,offset,firstn,nvalues,narrays,status
      integer units_out(narrays),colnum_out(narrays)
      integer datatype_out(narrays),iotype_out(narrays)
      integer repeat(narrays)
      integer histogram(*), userData

      external calchisto
      integer ncols
      parameter (ncols=2)
      integer units(ncols), colnum(ncols), datatype(ncols)
      integer iotype(ncols), rowoffset, rows_per_loop
      character*70 colname(ncols)

      integer iunit, blocksize
      character*80 fname

C     include f77.inc -------------------------------------
C     Codes for FITS extension types
      integer IMAGE_HDU, ASCII_TBL, BINARY_TBL
      parameter (
     &     IMAGE_HDU  = 0,
     &     ASCII_TBL  = 1,
     &     BINARY_TBL = 2  )

C     Codes for FITS table data types

      integer TBIT,TBYTE,TLOGICAL,TSTRING,TSHORT,TINT
      integer TFLOAT,TDOUBLE,TCOMPLEX,TDBLCOMPLEX
      parameter (
     &     TBIT        =   1,
     &     TBYTE       =  11,
     &     TLOGICAL    =  14,
     &     TSTRING     =  16,
     &     TSHORT      =  21,
     &     TINT        =  31,
     &     TFLOAT      =  42,
     &     TDOUBLE     =  82,
     &     TCOMPLEX    =  83,
     &     TDBLCOMPLEX = 163  )

C     Codes for iterator column types

      integer InputCol, InputOutputCol, OutputCol
      parameter (
     &     InputCol       = 0,
     &     InputOutputCol = 1,
     &     OutputCol      = 2  )
C     End of f77.inc -------------------------------------

C**********************************************************************
C     Need to make these variables available to the 2 work functions
      integer xsize,ysize,xbinsize,ybinsize
      common /histcomm/ xsize,ysize,xbinsize,ybinsize
C**********************************************************************

      if (status .ne. 0) return

C     name of FITS table
      fname = 'iter_c.fit'
      iunit = 16

C     do sanity checking of input values
      if (totaln .ne. nvalues) then
C     whole image must be passed at one time
         status = -1
         return
      endif

      if (narrays .ne. 1) then
C     number of images is incorrect
         status = -2
         return
      endif

      if (datatype_out(1) .ne. TINT) then
C     input array has wrong data type
         status = -3
         return
      endif

C     open the file and move to the table containing the X and Y columns
      call ftopen(iunit,fname,0,blocksize,status)
      call ftmnhd(iunit, BINARY_TBL, 'EVENTS', 0, status)
      if (status) return
   
C     both the columns are in the same FITS file
      units(1) = iunit
      units(2) = iunit

C     desired datatype for each column: TINT
      datatype(1) = TINT
      datatype(2) = TINT

C     names of the columns
      colname(1) = 'X'
      colname(2) = 'Y'

C     leave column numbers undefined
      colnum(1) = 0
      colnum(2) = 0

C     define whether columns are input, input/output, or output only
C     Both input
      iotype(1) = InputCol
      iotype(1) = InputCol
 
C     take default number of rows per iteration
      rows_per_loop = 0
      rowoffset = 0

C     calculate the histogram
      print *,'Calling calchisto iterator work function... ', status

      call ftiter( ncols, units, colnum, colname, datatype, iotype,
     &      rowoffset, rows_per_loop, calchisto, histogram, status )

      call ftclos(iunit,status)
      return
      end

C--------------------------------------------------------------------------
C
C   Iterator work function that calculates values for the 2D histogram.
C
C--------------------------------------------------------------------------
      subroutine calchisto(totalrows, offset, firstrow, nrows, ncols,
     &     units, colnum, datatype, iotype, repeat, status, 
     &     histogram, xcol, ycol )

      integer totalrows,offset,firstrow,nrows,ncols,status
      integer units(ncols),colnum(ncols),datatype(ncols)
      integer iotype(ncols),repeat(ncols)
      integer histogram(*),xcol(*),ycol(*)
C     include f77.inc -------------------------------------
C     Codes for FITS extension types
      integer IMAGE_HDU, ASCII_TBL, BINARY_TBL
      parameter (
     &     IMAGE_HDU  = 0,
     &     ASCII_TBL  = 1,
     &     BINARY_TBL = 2  )

C     Codes for FITS table data types

      integer TBIT,TBYTE,TLOGICAL,TSTRING,TSHORT,TINT
      integer TFLOAT,TDOUBLE,TCOMPLEX,TDBLCOMPLEX
      parameter (
     &     TBIT        =   1,
     &     TBYTE       =  11,
     &     TLOGICAL    =  14,
     &     TSTRING     =  16,
     &     TSHORT      =  21,
     &     TINT        =  31,
     &     TFLOAT      =  42,
     &     TDOUBLE     =  82,
     &     TCOMPLEX    =  83,
     &     TDBLCOMPLEX = 163  )

C     Codes for iterator column types

      integer InputCol, InputOutputCol, OutputCol
      parameter (
     &     InputCol       = 0,
     &     InputOutputCol = 1,
     &     OutputCol      = 2  )
C     End of f77.inc -------------------------------------

      integer ii, ihisto, xbin, ybin

C**********************************************************************
C     Need to make these variables available to the 2 work functions
      integer xsize,ysize,xbinsize,ybinsize
      common /histcomm/ xsize,ysize,xbinsize,ybinsize
C**********************************************************************

      if (status .ne. 0) return

C    --------------------------------------------------------
C      Initialization procedures: execute on the first call  
C    --------------------------------------------------------
      if (firstrow .eq. 1) then
C     do sanity checking of input values

         if (ncols .ne. 2) then
C     number of arrays is incorrect
            status = -4
            return
         endif

         if (datatype(1).ne.TINT .or. datatype(2).ne.TINT) then
C     wrong datatypes
            status = -5
            return
         endif

C     initialize the histogram image pixels = 0, including null value
         do 10 ii = 1, xsize * ysize + 1
            histogram(ii) = 0
 10     continue

      endif

C     ------------------------------------------------------------------
C       Main loop: increment the 2D histogram at position of each event 
C     ------------------------------------------------------------------

      do 20 ii=2,nrows+1
        xbin = xcol(ii) / xbinsize
        ybin = ycol(ii) / ybinsize

        ihisto = ( ybin * xsize ) + xbin + 2
        histogram(ihisto) = histogram(ihisto) + 1
 20   continue

      return
      end

cfitsio/iter_c.fit0000644000225700000360000026400013246025103013753 0ustar  cagordonlheaSIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                   32 / number of bits per data pixel                  NAXIS   =                    0 / number of data axes                            EXTEND  =                    T / FITS dataset may contain extensions            COMMENT   FITS (Flexible Image Transport System) format defined in Astronomy andCOMMENT   Astrophysics Supplement Series v44/p363, v44/p371, v73/p359, v73/p365.COMMENT   Contact the NASA Science Office of Standards and Technology for the   COMMENT   FITS Definition document #100 and other FITS information.             END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             XTENSION= 'BINTABLE'  /  FITS 3D BINARY TABLE                                   BITPIX  =                    8  /  Binary data                                  NAXIS   =                    2  /  Table is a matrix                            NAXIS1  =                   16 /  Width of table in bytes                       NAXIS2  =                 5000 /  Number of entries in table                    PCOUNT  =                    0  /  Random parameter count                       GCOUNT  =                    1  /  Group count                                  TFIELDS =                    5 /  Number of fields in each row                  EXTNAME = 'EVENTS  '  /  Table name                                             EXTVER  =                    1  /  Version number of table                      TFORM1  = '1I      '  /  Data type for field                                    TTYPE1  = 'X       '  /  Label for field                                        TUNIT1  = '        '  /  Physical units for field                               TFORM2  = '1I      '  /  Data type for field                                    TTYPE2  = 'Y       '  /  Label for field                                        TUNIT2  = '        '  /  Physical units for field                               TFORM3  = '1I      '  /  Data type for field                                    TTYPE3  = 'PHA     '  /  Label for field                                        TUNIT3  = '        '  /  Physical units for field                               TFORM4  = '1D      '  /  Data type for field                                    TTYPE4  = 'TIME    '  /  Label for field                                        TUNIT4  = '        '  /  Physical units for field                               TFORM5  = '1I      '  /  Data type for field                                    TTYPE5  = 'DY      '  /  Label for field                                        TUNIT5  = '        '  /  Physical units for field                               TLMIN1  =                    1                                                  TLMAX1  =                15360                                                  TLMIN2  =                    1                                                  TLMAX2  =                15360                                                  NAXLEN  =                    2  /  Number of QPOE axes                          AXLEN1  =                15360  /  Dim. of qpoe axis 1                          AXLEN2  =                15360  /  Dim. of qpoe axis 2                          TELESCOP= 'ROSAT   '  /  telescope (mission) name                               INSTRUME= 'PSPC    '  /  instrument (detector) name                             RADECSYS= 'FK5     '  /  WCS for this file (e.g. Fk4)                           EQUINOX =           2.000000E3  /  equinox (epoch) for WCS                      CTYPE1  = 'RA---TAN'  /  axis type for dim. 1 (e.g. RA---TAN)                   CTYPE2  = 'DEC--TAN'  /  axis type for dim. 2 (e.g. DEC--TAN)                   CRVAL1  =           8.588000E1  /  sky coord of 1st axis (deg.)                 CRVAL2  =           6.926986E1  /  sky coord of 2nd axis (deg.)                 CDELT1  =         -1.388889E-4  /  x degrees per pixel                          CDELT2  =          1.388889E-4  /  y degrees per pixel                          CRPIX1  =           7.680000E3  /  x pixel of tangent plane direction           CRPIX2  =           7.680000E3  /  y pixel of tangent plane direction           CROTA2  =           0.000000E0  /  rotation angle (degrees)                     MJD-OBS =           4.905444E4  /  MJD of start of obs.                         DATE-OBS= '08/03/93'  /  date of observation start                              TIME-OBS= '10:30:32'  /  time of observation start                              DATE-END= '11/03/93'  /  date of observation end                                TIME-END= '05:02:18'  /  time of observation end                                XS-OBSID= 'US800282P.N1    '  /  observation ID                                 XS-SEQPI= 'ROTS, DR., ARNOLD,H.                                           '  /  XS-SUBIN=                    2  /  subinstrument id                             XS-OBSV =               800282  /  observer id                                  XS-CNTRY= 'USA     '  /  country where data was processed                       XS-FILTR=                    0  /  filter id: 0=none, 1=PSPC boron              XS-MODE =                    1  /  pointing mode: 1=point,2=slew,3=scan         XS-DANG =           0.000000E0  /  detector roll angle (degrees)                XS-MJDRD=                48043  /  integer portion of mjd for SC clock start    XS-MJDRF= 8.797453703700740E-1  /  fractional portion of mjd for SC clock start XS-EVREF=                    0  /  day offset from mjdrday to evenr start times XS-TBASE=  0.000000000000000E0  /  seconds from s/c clock start to obs start    XS-ONTI =  1.476600000000000E4  /  on time (seconds)                            XS-LIVTI=  1.476600000000000E4  /  live time (seconds)                          XS-DTCOR=           1.000000E0  /  dead time correction                         XS-BKDEN=           0.000000E0  /  bkgd density cts/arcmin**2                   XS-MINLT=           0.000000E0  /  min live time factor                         XS-MAXLT=           0.000000E0  /  max live time factor                         XS-XAOPT=           0.000000E0  /  avg. opt. axis x in degrees from tangent planXS-YAOPT=           0.000000E0  /  avg. opt. axis y in degrees from tangent planXS-XAOFF=           0.000000E0  /  avg x aspect offset (degrees)                XS-YAOFF=           0.000000E0  /  avg y aspect offset (degrees)                XS-RAROT=           0.000000E0  /  avg aspect rotation (degrees)                XS-XARMS=           0.000000E0  /  avg x aspect RMS (arcsec)                    XS-YARMS=           0.000000E0  /  avg y aspect RMS (arcsec)                    XS-RARMS=           0.000000E0  /  avg aspect rotation RMS (degrees)            XS-RAPT =           8.588000E1  /  nominal right ascension (degrees)            XS-DECPT=           6.926986E1  /  nominal declination (degrees)                XS-XPT  =                 4096  /  target pointing direction (pixels)           XS-YPT  =                 4096  /  target pointing direction (pixels)           XS-XDET =                 8192  /  x dimen. of detector                         XS-YDET =                 8192  /  y dimen. of detector                         XS-FOV  =                    0  /  field of view (degrees)                      XS-INPXX=          2.595021E-4  /  original degrees per pixel                   XS-INPXY=          2.595021E-4  /  original degrees per pixel                   XS-XDOPT=           4.119000E3  /  detector opt. axis x in detector pixels      XS-YDOPT=           3.929000E3  /  detector opt. axis y in detector pixels      XS-CHANS=                  256  /  pha channels                                 TDISP4  = 'I12     '                                                            HISTORY   modified by pence on Thu Apr 24 15:04:08 EDT 1997                     HISTORY   modified by pence on Thu Apr 24 15:07:24 EDT 1997                     TDISP5  = 'I4      '                                                            HISTORY   modified by pence on Thu Apr 24 16:06:08 EDT 1997                     HISTORY   File modified by user 'pence' with fv  on 97-11-25T14:34:58           HISTORY   File modified by user 'pence' with fv  on 98-01-12T14:03:09           HISTORY   File modified by user 'pence' with fv  on 98-02-06T15:18:24           END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             óµA”ÑU=àq1±&ØA”ÑUAÀ	=#t6A”ÑVo€ö(²RA”ÑX/@¸)P#½FA”ÑX‰@Y[	ƒA”ÑXÕÀê
,~A”ÑY” @ SÁ?A”ÑZ¢ W^A”ÑZÄ€Ó},ŸaA”ÑZï@¨LzA”Ñ[":$÷A”Ñ^àNr€A”Ñ_MÀuëA”Ñ_†@˜'êìnA”Ñ`g@
÷ 	NA”Ñ`§àç$þA”Ñaƒ@ª°*Ÿ	A”Ña¡¢+91í2A”Ña¦À©%	¢A”Ñb tB( A”ÑbD@	Ñ*vhA”ÑbÐ I X,4A”ÑbÛ@O¤®A”Ñc7e$¬.+A”Ñc] 3	OA”ÑdW2+ý©
A”Ñd†€¹*2ÊIA”Ñd¦ C	é )A”Ñd×`ö[#A”Ñf$à™&•^A”Ñf® M
ƒA”ÑgoÀÙ“ÑxA”ÑgÀ å!%ÚA”ÑjS-`hA”ÑkàÄ\×
A”Ñk|À"0ç$SA”Ñl€@
Œ?-aTA”Ñl×@à f)ü
A”Ñm~às1\#âA”Ñm¨`
Á äA”Ñmà`-V%ÍA”Ñnü œ
½¿A”Ñq×`¶5í	A”Ñr{€©Ê“-A”ÑrÆàæ#*)ë
A”ÑrÛ Ps	€A”Ñsg€›'Ú 
A”ÑtìÅyA”Ñu@ PwXA”Ñv`à#cA”Ñyã@3+ËKA”Ñ{/ §!” \/A”Ñ{Q@
u,D
bA”Ñ{`÷
Ä:
A”Ñ{ó@g"Ç'*%A”Ñ|À	ÄM*¨SA”Ñ} 	'2^Q
A”Ñ}s f ›“A”Ñ~0`×"0YA”Ñ~ØÀêŠ
eA”ÑÀë%ÄDIA”Ñ`!v3A”Ñ}ÀT"»-A”Ñ­€½î*¼	A”Ñ€þ X,AN
A”Ñ„¿`ƒ($_A”Ñ„Éà
î¬éOA”Ñ„Ü`ëi:A”Ñ…Ï v*¦-DA”ц´€
 ç0A”цï Ûy	A”чÀš§	A”чL ƒ$¨)oA”ч™À)¢-bA”чæ@
ÝA”шâà(
Z(A”Ñ‹&@+ A”ÑŒý 	¬#±kA”Ñ/91Ö
A”ÑŽh ‚¥¹4A”ÑŽo 'ASA”Ñ޾,/B%vA”Ñ–à	íÙ3œA”Ñji!?åA”Ѥ€ë{+×A”ÑÀf."D:A”Ñê ¼l3A”Ñõ€üP'×	A”Ñ‘®`
Ð1°
A”Ñ’k DÝzA”Ñ”&…=A”Ñ•‹ vy# 
A”Ñ–@
Q3&A”Ñ–ˆÀ	h'À3&0A”Ñ–À
á(A”Ñ™àA/ÑÄA”Ñš€¡ï! ~A”Ñš: 
Öˆ‹A”Ñš¬@èSA”Ñ›& ˜	V2A”Ñžy *Ì&8A”ÑŸ‘@ØÍZA”Ñ v`#
YÁ¡A”Ñ£L€”S×A”Ñ£a@çA”Ѥ€Í1,PA”Ѥn ’/3xwA”ѤÉÍ7 PA”ѥ꠿*E	A”Ѧ« <3ŠëA”ѧ ¸ÊpA”ѧ=`?&ÒA”ѧÝ@zÊ–A”Ѩ\€h0¢¥A”ѨŒ 
õ“#ë?A”Ѩɠ
(U+DA”Ñ©b*:BA”Ñ©Ýà¢$$A”Ñ©à-3DÙA”ѪLÔ*[3'
A”Ѫ¡Ú³}zA”ÑÃl`
$s
ØA”Ñŵà—Ÿ.Å^A”ÑÅØà
§$_'A”ÑÈç mF1A”ÑÊ’€žÿ+ŠA”ÑË`O&¿A”ÑËÖ s
ã7A”ÑËýà×"™A”ÑÍJ@/ P4ˆEA”ÑÍ»`ì
¸
A”ÑÎÀàË+à
A”ÑÎá`×þ'È
A”ÑÏú€
Û/Ù
A”ÑЛÀÐÍA”ÑÑh ð#
A”ÑÒàß+Ì"SEA”ÑÒ ©©A”ÑÒ« ø/Ž 35A”ÑÒÂÀ•	¾)7ÛA”ÑÓïà	áÐ4¦A”ÑÔ4 ®ln	A”ÑÔ:@2%åõ
A”ÑÔZ 
?aÄFA”ÑÔi€”.]´FA”ÑÕ*€

 JA”ÑÕn`äÚ-§
A”ÑÖ`æ+ŠXA”ÑÖU`¥v A”ÑÖìW ŠA”Ñ×,à4`!A”Ñ©@"ÝdA”Ñ« C(ØjA”ѰÀ%,·&¨A”Ñæ€	>¤%L
Aӄo@
¿¥AA”ÑÀ"!!®#A”Ѳ
3$À
A”Ñý`H/™&XA”Ñ 	h(-3ŠA”Ñ- ¢-øA”Ñ[À“,˜A”Ñc`+%$A”ÑúÀÇ4ïSA”Ñ-zâ3â
A”ÑË 0(Õ%A”ÑÛÀ
J	]{A”Ñ €y!7ÂA”Ñ‘ \'È
A”ÑÌ`	}&ø&|A”Ñù 	¥&,Ô	A”Ñ	ë`eç9A”Ñ
—`d%x.A”Ñà"±*WA”Ñp€Õˆ}A”Ñ5`õâ(ÛA”ÑO€È+ÌŠ9A”ÑXÀ|"rAA”Ñy€Å\'«„A”Ñ7@	ÿÁ%
Aӄ
€^
™
8A”Ñe ‚)0ñA”Ѽ ÷31«A”ѯWA”Ñ‚ 
ó"
ØA”Ѱ€¤
RÕA”Ñ€<°s-A”ÑÃ`A °cA”Ñ`L2‹ªA”Ñ@
,º'B@A”Ñ?à,	ðA”ÑÄ`uþ(-A”Ñ×@
…;A”ÑûIãwA”ÑC !% A”Ñmq%§,d+A”Ñq –÷
A”Ñè ,1{—
A”ÑÕ`xv-tA”Ñk@k'£*ÒA”Ñ4`Pc-sA”Ñ ò m!IŸSA”Ñ!¼àh!ü`
A”Ñ!í`÷CÖA”Ñ!òÂ$ÖÔA”Ñ"Š¢%,
+A”Ñ#PÀkó;1A”Ñ$.€æ"¼6A”Ñ$•àl!H
A”Ñ&- g%àA”Ñ'ý@
‡4`PA”Ñ(Z@Ú_¨A”Ñ(È )-(”%A”Ñ)P€	¶	…A”Ñ)w,)œ¶A”Ñ)ì`
ª>ŒA”Ñ*A ©±¦A”Ñ,*@f€°
A”Ñ-I#ê{]A”Ñ-í@_t÷
A”Ñ.Ö yçn;A”Ñ/O Šb6œ	A”Ñ/‹ ….'A”Ñ/öü4²vA”Ñ4S`†·/A”Ñ5€ú%;A”Ñ5à
Ôû¾4A”Ñ5./«ëA”Ñ5¹ ¤%{­A”Ñ6ˆ`¹!A”Ñ6ï`
R×3ÏA”Ñ7_ÿ0r
A”Ñ7µàûr!mA”Ñ8@
Ü>iA”Ñ9ƒ`Û/ŒÞWA”Ñ:f W·fA”Ñ;" y Ç"A”Ñ;:€ñé
‹
A”Ñ;S ³.b!Ð"A”Ñ;c`Æþ )eA”Ñ>@
ç)î"t{A”Ñ>à°íÑ-A”Ñ?=`ù	N&D5A”Ñ?g xb§0A”Ñ?å @Eï	A”Ñ?ùÀ¿Ü PA”Ñ@'à‰Ç$üTA”Ñ@V Ù.þVOA”Ñ@à Ë¢•
A”Ñ@ú`ˆ×ÓA”ÑAW`s!È·A”ÑBÖ e,£s*A”ÑCX wæ1Ù
A”ÑCi€ñ$ùZ$A”ÑC— D
_(UA”ÑDî€
QJëA”ÑE& —wA”ÑFÙ(%Ü'A”ÑF÷ b
1)Õ2A”ÑG
à	^
^nA”ÑG;à¹-+§A”ÑHÀ¢ÎÎA”ÑJ€àóþ–GA”ÑJ› ®#$ÑA”ÑJ±@h1"%œ
A”ÑJú@	¡0"sA”ÑMo 
€3à›A”ÑNq ÏÜA”ÑOø’/ñjA”ÑPc D#;(e
A”ÑQ@ïâ-¡A”ÑQ¨à\4d
A”ÑQþ |eA”ÑR)`G
èA”ÑR- “8,dA”ÑR3$x­3A”ÑTÉàŽ&¸&A”ÑV‚ 
*È
BAA”ÑWdÀù£× A”ÑW@óù3ëjA”ÑY8àÇ1m ¼A”ÑYóÀ?!ÃÎ
A”Ñ\÷ (4Ì	A”Ñ]Π³FPTA”Ñ^+Àû4È	A”Ñ^é@)1¹* 	A”Ñ_“`ú)*¥>A”Ñ`¾àF.ö{OA”Ñ`àëæ#¬JA”ÑaŽ*˜7A”Ñb÷*4^ƒA”Ñb,`š,ã4A”Ñb¯@W´A”Ñeà¢Z'Ý&A”Ñeà
–ªf§A”Ñe1À}!ø'jA”Ñe¸€	“
”
A”Ñeá ™1Ö+ˆA”ÑfAà'~A”ÑfI÷!w	A”ÑfrÌ“õA”Ñgˆ†(mA”Ñh@	u	-¯EA”ÑhD¡.‚©6A”ÑiÀ
	ÂØA”Ñjj€À~ÜA”Ñjí #lÁPA”Ñjô³(›"jHA”Ñk â*~JA”ÑkáÀ‚!ù1`A”Ñkè@Jð#\8A”Ñlà
\Ü1A”ÑlH@.ë%A”ÑnÜ€y/’/
A”Ño@Á%C#²A”Ño3`eA$»rA”ÑpSXöA”Ñq€0÷ænA”Ñq5À)I	’A”Ñq“@Ä2A”Ñr2Àü6:A”Ñr·à[Äâ™A”ÑtÀ’%û+VA”Ñt¡N3žA”Ñtì ©
A”Ñu’@ýG Š
A”Ñu•€í'–!ô{A”Ñvg 7A”Ñv€-!Ë7A”Ñv­ —í%tA”Ñx뀫'å4 A”Ñy“@ˆ¥1-A”Ñzl`&) ¦A”Ñz­
t#¿A”ÑzÇ Ç(Ÿ3A”ÑzàÀm"Ô*A”Ñ{>À&BA”Ñ{lÀê6‚	A”Ñ}ïÀ(„"iA”Ñ~àÿ%€_	A”Ñ~@Û)i%QA”Ñ~æ 
Yª4pA”Ñ~þ :&ûA”Ñ€‘@!:÷	A”Ñ€˜à¹Á)‹A”Ñà	ù1ý!A”ÑL?Þ3A”Ñ €™
.	A”Ñ‚BàÖA”Ñ‚Àý$Ÿ1f7A”Ñ‚á`2'“ùA”уI€UØ>A”у €$ž!A”Ñ…{À
üÁLA”Ñ…” ÛA4JLA”Ñ…ä ¾sA”цNàdK?A”ц»€Ð
ë,|LA”ш5ÀA2ú(†A”ÑŒá&.!ç,A”ÑŒîà1gA”Ñ*@¨!’6–A”ÑŽU ¢
<A”ÑŽàÈ 3A”ÑQ ¡--f
A”Ñ‹ ä&˜E
A”Ñ£àI2V(ÈA”Ѩ2±%ÛA”Ñ‘µ€	™$C5Ê
A”Ñ’ÿ ìÎìA”Ñ“D M-!WA”Ñ”‰ 
Š6~ A”Ñ”ýy¤	A”Ñ–Iì!=9A”Ñ–‹ 1¬ÓA”Ñ–½ 
ò©
m
A”Ñ™a€
+ðA”Ñ™÷ à |mA”Ñš~`
÷'¦³A”Ñšé€<HjA”Ñœo Ì 4ÓA”щ€±ÍA”Ñšà(×!© A”ÑÝ 
Ú&2"vA”Ñž¿ !)˜$ýA”Ñžå 
™-ˆA”ÑžúàTÔ
A”ÑŸC ´°A”Ñ¢Y€ÏA”Ñ¢mÀÆËA”Ñ¢™€dY.òA”Ñ£
 }]A”Ñ£
à5ÓtA”Ñ£¬@¨A”Ѥ–@ï,˜ìA”Ñ¥ A-¦&f	A”Ñ¥£à	£'œ0ž	A”Ñ¥Ë@ˆYA”ѦʀtÖ#¹A”Ѧí 
Tò!A”ѧ¢
†4!	A”ѧ½ «1ì!Y	A”Ѩ$àL#¬A”ѨC
s'y#UA”Ѩ{@Ÿ,
NA”Ñ©|`±s
Ñ
A”Ñ©àÛ´&×A”Ѫà
÷ Ä6A”Ñ«ààSR":A”Ѭ 
+#Ó3A”Ѭ¬€my·A”Ñ¬Ü )åõA”Ѭú 6v"‘%A”Ñ­ 
4"Â#2A”Ñ®€÷çüA”Ñ®tÀÁ}("ŠA”Ñ®àÀ	°A”ѱdŽbB
A”Ѳ„ <.IÃSA”ѲÜlî|A”Ñ´°À£í)A”Ñ´ú jÌn
A”ѵ6@m.™A”ѵj §
÷
A”ѵØ`BØA”ѵí`|¤hA”Ѷ#à“Úa&A”ѹ Œ‹ÁA”ѹ !÷5ÄA”ѹ£à&'–3QA”Ѻò %.xÍ
A”Ѽ‰`{(ú¢VA”ѽpà5š%˜A”ѽè`	®	“{ A”ѽö ’ª%y-A”ѾO¯)ŽbA”ѾS€0*f'
PA”ÑÀ:€	‰,6VA”ÑÃDÀÉ@(A”ÑßÀ&œA”ÑÅÓ`!2æ!r	A”ÑÆ'`-^/5A”ÑÇkÀ
''-A”ÑÈ	 
Ôs	íA”ÑÉ â_$K[A”ÑÉž“	ŽÂA”ÑÉ·`ë%5 A”ÑÉÍ`
‰B5ßA”ÑÊ3€ò“!A”ÑÊe 
¦4û-A”ÑÊàŒŒA”ÑËÀ
œ%LA”ÑϧB†MA”ÑÐ`Ø&˜õA”ÑÐ]€©k)A”ÑÑÖ€Y, A”ÑÓiÀ
9-åA”ÑÓûà1—9A”ÑÕ Î;)»A”ÑÕÜ@	‹x A”ÑÖ¸àí ÿ	A”ÑÖð`6´!A”Ñ×T :©A”Ñ×\ 7t(A”ÑØXÀȬ!´	A”ÑØ•`’é–A”ÑØï€$
1)VA”ÑÙ`
&bpA”ÑÙÿ@z0z+A”ÑÚ\à##èA”ÑÜS@«",6HŸA”ÑÜ~€ð#;.#A”ÑÜÚ 73¦m%A”ÑÝž`Tj$©A”ÑÝÊ@@) 
A”ÑÞX€
e˜ |
A”ÑÞƒà
¾ÇA”ÑÞ¨à€`4!-A”ÑÞÌ`! ûàoA”Ñ߀ëp.A”Ñß @mú#˜A”Ñái@
X"§*A”Ñ㈠¤!9!OA”Ñå9 
J-~1FA”Ñåg`ü»
D.A”Ñåà®u1jA”ÑåìÀ?)’!–'A”Ñæ€ŽÒñ
A”ÑæKà‘†Ñ	A”Ñæ™à*(ó&¦A”Ñç¶`	å™6ã%A”ÑêJ F!Ê$¿
A”Ñì€P3¤ºA”ÑíJ€åA”Ñî( Q5*2A”ÑîŽA]A”Ñ𢠌ü6A”ÑñÀ@0
‰,÷A”ÑñÏ€<4î‡A”ÑôÝ€
ž¡A”Ñôà (­%oA”Ñ÷i€u!E5ò+A”Ñ÷p`3L	Õ	A”Ñø5@Ú!A”Ñø|@
ã™-­A”Ñù`T^A”ÑùßL.[)A	A”ÑûWÀ<  *
A”Ñü§ —[ÕA”ÑüÀàÞ'Ë
Ê
A”Ñþ;àѧ!5A”ÑþýÀ
ò¯5e:A”ÑÿI`–Ä‡A”Ñ #@¬#V+uA”Ñ ­@­¼*A”Ñ Ï "ÄPA”Ñ ê Ó!	=A”Ñ è ’""VRA”Ñ 4@
S
–#¶A”Ñ 	â€
.¬þ6A”Ñ 
s€œ§îIA”Ñ Š %7|=A”Ñ Ÿ C/

A”Ñ ¼`ô.8€
A”Ñ Ú 
caA”Ñ âàÆ,.A”Ñ 
ÓàuM&¢A”Ñ 
ý &	û*8A”Ñ € 	ºç
A”Ñ  €àXA”Ñ ¬à§&¿DA”Ñ ®à | A”Ñ Là–½A”Ñ Mà[(®"5A”Ñ ÛàS õA”Ñ ® ´,¯CA”Ñ ¬ ¬
"Ï~A”Ñ ³
î3úB5A”Ñ ´`¹îÇDA”Ñ Å€¡U!¾
A”Ñ   §0é.éA”Ñ 3@s!A”Ñ `@
¢#ô&A”Ñ ÂkSè
A”Ñ è ?QÆA”Ñ ñà
‡1òA”Ñ  >0ŸŸ	A”Ñ hà˜©$[A”Ñ Æ`ܸ'(A”Ñ C5ËA”Ñ U Ç)È
[A”Ñ ¾ù,$ýA”Ñ ú!ÚA”Ñ O€¤(2¡A”Ñ !­“«A”Ñ #Àu("A”Ñ #`
”]A”Ñ %Ý`¡Ä5Ÿ	A”Ñ &ÞÀ æíA”Ñ 't€=!ýÏA”Ñ ' ¦‡A”Ñ (€	*©eAA”Ñ (:`¹(E  A”Ñ (‚`
7*«A”Ñ (§àÞ'»UA”Ñ )
+!EA”Ñ +€ 
¥ávjA”Ñ +±j#}$A”Ñ +À op6A”Ñ +Ð § ø6¾
A”Ñ ,*`Ü',@A”Ñ ,Å@Q$1ÓA”Ñ -`?'a1KA”Ñ -Y h1ò±A”Ñ .b`”AÎ~A”Ñ .`Ñ!å
=A”Ñ .Ÿ ï‰A”Ñ /# þÄ	A”Ñ /Ë*£ú'A”Ñ 0Ä ƒ%’A”Ñ 1;€MÊ‚KA”Ñ 2:@>']ÎA”Ñ 3SÀ	%&VA”Ñ 3Œ@
Ã? NA”Ñ 3”à~ª:A”Ñ 4¡@ª%Ž(uFA”Ñ 4¹ 	:—+A”Ñ 4àÀœ ÔYA”Ñ 8Àz6C6A”Ñ 8}X@&
A”Ñ :îÀ
Þ]¼AA”Ñ <á`Ç0h,oA”Ñ >? ˆö ¾A”Ñ ? r.–A”Ñ A7 ó+uGA”Ñ AÆ Z$ª&w
Aӄ BG 
_9
©PA”Ñ C€Óv@A”Ñ Cµ@åa„A”Ñ D„€¢&¿úA”Ñ E1ú™#Š>A”Ñ H* 
¹
#A”Ñ HeÀ³»øA”Ñ J{À¢ŸxA”Ñ JÔ@*%jZA”Ñ K­`§%¡-^*A”Ñ MÎ`«W4æÜA”Ñ Mã É][A”Ñ N`j­¢A”Ñ N? 5¿ãA”Ñ NX@|
Ã*£A”Ñ P`	rŒ&È`A”Ñ Q˜ .Z¨JA”Ñ R™=
R7A”Ñ S@¥\.÷A”Ñ S¯`e$?SA”Ñ TÛ Äì6W>A”Ñ TçÀÕKÎ
A”Ñ TéÀLÑA”Ñ U2 ç»_A”Ñ V¾ 2 [.{SA”Ñ Wàbó qA”Ñ X Ì£EA”Ñ X  ÷ú/TA”Ñ Y€½ A”Ñ Z
`gù,ŒA”Ñ Z—€SZ ÞA”Ñ \c€À6JA”Ñ ]`ÔH}A”Ñ ]€˜	ÕäA”Ñ _%`Ä%
A”Ñ _–@`?EA”Ñ `FÀ0)f	A”Ñ `³²Ü(A”Ñ b,@¶2¢$m*A”Ñ cŸ
¾0¢«A”Ñ da ü
Z1A”Ñ eSà?
‰!A”Ñ e» 
K°A”Ñ e ?-ž±0A”Ñ eîð$CpA”Ñ g4ÀÞ$¤ùA”Ñ gˆà
æ+ÆA”Ñ h p:­A”Ñ h¢€'/ô!¯A”Ñ iÀ]ç5¶)A”Ñ iÀ4
›öA”Ñ jJ o"j4òA”Ñ kÓ Þ!zA”Ñ kØq]KÞA”Ñ l  Ë#ƒ0NA”Ñ mÌÀH)PY
A”Ñ n€·*£¤A”Ñ pÒ`I‹-ZJA”Ñ qØ@–&I/A”Ñ r+@s!o2õ(A”Ñ rÀ,5A”Ñ uÀà
ü	‚&„.A”Ñ uß õ' 	A”Ñ v8€ÇƒuÎA”Ñ v· ‚f¶
A”Ñ vÙî“"ŠdA”Ñ w˜à
h+™e°A”Ñ w¸ù  $?A”Ñ yÍÀë¢(éA”Ñ {
€
¾3f?A”Ñ {à 
„$Õ
A”Ñ |Ÿ€6Ä©A”Ñ €“`a&Ð'*A”Ñ >@
(J a*A”Ñ ‚.`
‹-¦)wA”Ñ ƒ`i
Î*ÅA”Ñ ƒ>€	|%$³A”Ñ „H 
2I#òA”Ñ „Œà—ð
™A”Ñ †k€‘!T4­A”Ñ ‡l@"óA”Ñ ˆàA”Ñ ‰íÙ
HA”Ñ Š- Y3KA”Ñ ŠI *(|.`"A”Ñ ‹äàΦA”Ñ ŒTO
g(CA”Ñ ŒÖ ÿ.`A”Ñ ¯àè"É4-A”Ñ Ž†@U£ÚA”Ñ Žú@¤¾ñ®A”Ñ !À%ó‘A”Ñ ‘Z`ì0q	,A”Ñ ‘ëàà_8A”Ñ ’*`H2™+­
A”Ñ ”ÍàþÏ(áSA”Ñ •÷ 	ê'f$¸A”Ñ –vàR"îA”Ñ –à
&V6iA”Ñ –÷àv-×A”Ñ —Ò j	¿A”Ñ ™`Ì+)5A”Ñ ™à
H"´	+A”Ñ œ`I>#ŸA”Ñ œ0 ]"þsA”Ñ œæ |"$A”Ñ `öJA”Ñ ;`›+
“A”Ñ A 0/¥
A”Ñ Ÿl€F%£*ÅvA”Ñ ¡* 7ÓáA”Ñ ¡Ä@¦r/v
A”Ñ £¥àþGA”Ñ £Î §!½OA”Ñ ¥±à½&—4â A”Ñ ¥Ó Ês"Y1A”Ñ ¥í@

#Ë
A”Ñ ¦Àµ!Oe
A”Ñ ¦m
@
QA”Ñ ¦è ¿'@+gA”Ñ §àÍ+þ&—Ê*DA”Ñ ©º 	úàA”Ñ ©È@}2Iœ	A”Ñ ©ðàe€"A”Ñ ªÀ
ž-ÚÝA”Ñ ª—à’!àˆA”Ñ ¬Öàî9-	A”Ñ ¬í€ç5d#A”Ñ ®€­('.˜A”Ñ ¯Z ï%ÁA”Ñ ¯jÀt"¢ _A”Ñ ¯Ñ
ó5PA”Ñ ¯ú@
}ŽE
A”Ñ °§ÀTh„A”Ñ ±X@
Ð!'A”Ñ ²=À±)Ñ!#)A”Ñ ³và
&&‚(%A”Ñ ´ 	›ÿ0%7A”Ñ ´U€RÂ
•!A”Ñ ´{f!TA”Ñ ´Œ 
®&¶ê0A”Ñ ´•€<ò/A”Ñ ¶`àÎ`3A”Ñ ¶kà0Œ$D A”Ñ ¶s
,Š2x	A”Ñ ¸ûÀÈ‹¢FA”Ñ ¹%à®f	/A”Ñ ¹+€'ƒA”Ñ ¹êÀFr(ï	A”Ñ º÷à
ú&yµA”Ñ ¼€ã6ššFA”Ñ ¼Làß*›
A”Ñ ½?àY¿
ÝRA”Ñ ½ºÀÃ0‰A”Ñ ½ý µõ#hA”Ñ ¾nà
 bA”Ñ ¾¶`N0ú";A”Ñ ¿øà2%5E$A”Ñ ÂéàÒ5A”Ñ ÂïÀ„1µ)šA”Ñ ÃQÀ= ¸
?CA”Ñ ÃÂ`G.‚!ŸvA”Ñ Å† « ×!Z4A”Ñ Åº@
’,A$A”Ñ ÆPÀ`†%%
A”Ñ ÆW@Y¨"A”Ñ Æéà
IP=A”Ñ Èp ¢ oó9A”Ñ Êq U/MøA”Ñ Ë©`,'%A”Ñ ËÑ@‹lÃA”Ñ Ì@#-¸,.
A”Ñ Ì„`"t	ç{A”Ñ ÌÌ€ù-v9A”Ñ ÎÒ D*p:A”Ñ ÏÈ/¦9A”Ñ Ð@` ˜!ÍA”Ñ ÐF€
Î1¦(ÙA”Ñ Ðþ@ªDA”Ñ Óq N!fXA”Ñ ÓŠ@`"r÷A”Ñ Óª N&u*lA”Ñ Ô³ u,)U	A”Ñ ÕÃ`	Ž#=hA”Ñ ×'àl)A”Ñ ×ë€ó4õA”Ñ Ù¹@£ô*¡A”Ñ Ú€Ó$hA”Ñ Û€ò/êë
A”Ñ ÜÉ C™]A”Ñ Üò`!;¨A”Ñ Ý(@#.*ÁtA”Ñ Ý¸€ß2"A”Ñ Þ@Iö
A”Ñ Þt`ð Ž-A”Ñ Þžj2…"
A”Ñ Þ¯ :	È5A”Ñ ß4ÖÍA”Ñ àV 1!Ô!
A”Ñ à†à
ºO
§@A”Ñ á±àæ'	'A”Ñ á² 3: âA”Ñ â`Ù4û+l
A”Ñ ä~%0J ËA”Ñ æ?À
©"‚`A”Ñ ç­À
°)È¢A”Ñ çÁ•0!A”Ñ èç _nôÕA”Ñ ê5ê!£	A”Ñ ê4P–!WA”Ñ êKÀ§ O8A”Ñ ë5 Ãá
A”Ñ ì³@Ú#'HA”Ñ ìµ€w
1‹
A”Ñ ìí*ë	vA”Ñ ín Í$o4A”Ñ î­ t3?A”Ñ îâ`rŒgA”Ñ ïG‰ê(¡A”Ñ ïOÀ
6³A”Ñ ñ;À4->?A”Ñ ñ@àyð02QA”Ñ ñ‹à¡æ(¬A”Ñ ñ`	êÐ(=
A”Ñ óä@
ï	'yA”Ñ óø ¸6Ã#A”Ñ õL ê#†ÄA”Ñ õ’À
ðÉ,¾1A”Ñ ÷Œ ï$A”Ñ øà
)â-A”Ñ ù5 
91/ÜA”Ñ ú`ò1à$¥@A”Ñ ú}€
ù)?/ñA”Ñ û p&—*ÌA”Ñ û] S(þXA”Ñ û¨às]ÙCA”Ñ üH`!(Ô%ÿA”Ñ üÚ€
Â:1¢A”Ñ ý[ ß"è£)A”Ñ ýs€Ø*ú5¯A”Ñ þ@JH1TA”Ñ þy@%A6}KA”Ñ þÔàõ(…A”Ñ þÖ@͇ݧA”Ñ ÿ¯@v	3~
A”Ñ ÿü ‘T1/A”Ñ!c â*îA”Ñ!¨ Ã~
A”Ñ!Ê 5Æ65A”Ñ!jàôT19
A”Ñ!Í`þ•/i=A”Ñ!
@séŠ1A”Ñ!F 0t*A”Ñ!ä`	$\
A”Ñ!	Tа'A”Ñ!	à/(ç)A”Ñ!mÀßðA”Ñ!ñ@·%€Ú=A”Ñ!þà	4ï ¨A”Ñ! ùɶA”Ñ!™ÀŸé(ê;A”Ñ!@
)	ŠA”Ñ!Àó ŽÄ
A”Ñ!ý?‹ÌA”Ñ! ¶%Ç,ê
A”Ñ!Y@L,‹~A”Ñ!7ÀÕ(×_A”Ñ!-€:+ÁA”Ñ!> ™$A”Ñ!V ‹0×DA”Ñ!î€
ËöÕA”Ñ!
@Y
E
Ö
A”Ñ!NÀÍF!	A”Ñ!Å€¶ô5(A”Ñ!-@&)A”Ñ!6@	^*4æA”Ñ!UàÒU!œ
A”Ñ!m¾-§ó	A”Ñ!mà
Ç4ŠåA”Ñ!кúIA”Ñ! Š`Û6žN%A”Ñ!!àó+è3–A”Ñ!!R`mG)\A”Ñ!"SàIr2vA”Ñ!"Ç€Æc ×A”Ñ!"È`¨5:	A”Ñ!#3 }¥lA”Ñ!'	€.½8A”Ñ!'- jˆ‰NA”Ñ!'½À·58A”Ñ!(c Y
#$A”Ñ!)= 
è%¢&ñA”Ñ!)F€
…0‘
SA”Ñ!*, .Ód
A”Ñ!-+~+¢A”Ñ!-¦|"
A”Ñ!-á`¡-o)	A”Ñ!.Šàóß.A”Ñ!.®€€)¦/«	A”Ñ!/Àª0ñ#ýA”Ñ!0zÑ"A”Ñ!1.@!1–
A”Ñ!1=À×s*A”Ñ!1øà½"†?RA”Ñ!2<V›A”Ñ!2Ë T#~A”Ñ!3 
€.Ó%A”Ñ!3¶ òÁ3ÐA”Ñ!4N@ô	)A”Ñ!4l1ñ%-
A”Ñ!4Ðà
Ì$$!cA”Ñ!4ñ 
”ÐÉA”Ñ!5‘`E¹.%QA”Ñ!5×€¥s2&GA”Ñ!6\Àù (kA”Ñ!6Ž
l],A”Ñ!6±@Á)(
A”Ñ!7R–8F
A”Ñ!8@ýÞ7&	A”Ñ!8m€Ú&ù6A”Ñ!8³`*Ê$àA”Ñ!8Ê 1zA”Ñ!9ÿ@à!ç,kA”Ñ!:u@Ø/F33A”Ñ!:—~2.4A”Ñ!:á 'Ú0Ú
A”Ñ!;$@# Z‰A”Ñ!< )ŠÁgA”Ñ!<þàÁ&d7]A”Ñ!=e Æ.jV	A”Ñ!=ˆ
*5A”Ñ!=ûá#"L	A”Ñ!?…€
-¸"–
A”Ñ!@M€
5¯àA”Ñ!@Áàö-Î
A”Ñ!@Ò å0ÚA”Ñ!AGà));îA”Ñ!D ]!J	¼A”Ñ!DŸ€\ÑüA”Ñ!DÙ`Ô/!@A”Ñ!F` V"2A”Ñ!FÂàF#+#0OA”Ñ!G(¶ Z\A”Ñ!GE`K((RA”Ñ!HEâA”Ñ!H’ ã.‚7	A”Ñ!I /H¨RA”Ñ!J
@4E1¸A”Ñ!J9À]	á,/A”Ñ!L d$,QA”Ñ!LSàQ!7òA”Ñ!Ld€ò%b!A”Ñ!L} 
¶qÚTA”Ñ!M@.*µ•…A”Ñ!M¿ J%(-wA”Ñ!Nfà%õ
A”Ñ!N›K1ÂãA”Ñ!Ov½R1VA”Ñ!Q Ì!‰2A”Ñ!Qh ì#I'£
A”Ñ!Sz€
[:	µA”Ñ!V# L3Ë úA”Ñ!V þ,
:A”Ñ!WzÀ1!(…A”Ñ!W©	 )¯5A”Ñ!WÏ@¢7ê ‘A”Ñ!W÷€ü­ MA”Ñ!X4€Ú3“µA”Ñ!YÀ¿)û#!'A”Ñ!Z€e4--ç
A”Ñ!Zu`!Ÿ
°A”Ñ![FœA”Ñ![À2£âA”Ñ!\)àïÍ-õ	A”Ñ!]a P0erA”Ñ!]r î(A”Ñ!^aÀ,W,dA”Ñ!^q@X"	A”Ñ!^¨`à'@A”Ñ!a.€
ã&2»A”Ñ!a8@ÑOfaA”Ñ!a³@‹
˜zA”Ñ!aú r]Ó	A”Ñ!c8Àh5ñˆA”Ñ!cOÀÜ- zA”Ñ!cd€‰-ÁA”Ñ!d ÏŒ$ÁA”Ñ!dÆ
•'²5ÂA”Ñ!e¤¡4Á%ŸA”Ñ!f!À
%Ñ+•sA”Ñ!fÔ@'
`#|	Aӄ!g|`
Ñè*˜A”Ñ!gªÀf) $;A”Ñ!gÉ Û%ÞM®A”Ñ!güÀ5Þ-/A”Ñ!h¡ zØPA”Ñ!háàv6à]A”Ñ!ià6ö6A”Ñ!iE œ!EŽA”Ñ!j
àš-„‘A”Ñ!j7 Rˆ1ô"A”Ñ!j:€(‘)‡
A”Ñ!ji@	!Z,?A”Ñ!jÀ
! !A”Ñ!krà„Çð	A”Ñ!k÷[V=A”Ñ!mµ-‚FA”Ñ!m@à“
Ÿ
A”Ñ!mgàï!EŠA”Ñ!m €Z‡A”Ñ!o`Àº„øBA”Ñ!o†#3Ž DA”Ñ!o´`
mLõA”Ñ!rbÀØð,«A”Ñ!r@)ÍPA”Ñ!rî %6A”Ñ!s B±3A”Ñ!sT€S!ã!/3A”Ñ!s‘ 
í6ù£A”Ñ!tŠ 
•	h$ÂA”Ñ!uâ`
b='&(A”Ñ!vî@gS,%
A”Ñ!w€h#c/ÞA”Ñ!y`	ÉA”Ñ!y=€'%a8
A”Ñ!yØ`Š(çA”Ñ!z,€djú#A”Ñ!zr Ï
)43A”Ñ!{.à
Ì·
aAӄ!~
 õLKA”Ñ!~— þ0\ã
A”Ñ! ^µ	A”Ñ!1`«,çA”Ñ!n@yP
ÉA”Ñ!Èy5-'A”Ñ!€“À—2êNA”Ñ!
 
º*A%ÖBA”Ñ!#l1û
A”Ñ!3ÀA7¿$ô6A”Ñ!A 
»1SA”Ñ!Ð@•  FA”Ñ!‚‡“
ãA”Ñ!„UÀÁ+,€A”Ñ!„Á´#XA”Ñ!†C`
§	(MA”Ñ!†œ€
Ô«"¥A”Ñ!†ê±xíA”Ñ!ˆJÀ{ï3]A”Ñ!ˆ› »ØC0A”Ñ!ˆ«€70¶^A”Ñ!ˆÓ_$Ó¦A”Ñ!‰1@½.hÜ A”Ñ!ŠJ #7
ŠA”Ñ!ŠkÀôsÓ`A”Ñ!Š… 3.R%}A”Ñ!Šþ
þ*@(A”Ñ!‹y`@2Î"Ö	A”Ñ!‹¯@(#ï8]	A”Ñ!ŒzÀ…0Ô13A”Ñ!ŒÚàŸ(ª1íA”Ñ!
 °XS
A”Ñ!x@„mìA”Ñ!“ v" A”Ñ!Ž:Àk'sÖA”Ñ!Ža€ü/¶bCA”Ñ!%À8^A”Ñ!@!"ÝA”Ñ!‘ àØ3-¦A”Ñ!“S@K
A”Ñ!”–@ò,½á]A”Ñ!”˜`®3A”Ñ!”€ð†!öA”Ñ!–#
ÒJ7“A”Ñ!—›@G#µ/,A”Ñ!—è 6!wA”Ñ!—ò€µM7A”Ñ!˜8àuf*-A”Ñ!˜Ü@	á’4¹ÇA”Ñ!™ œ9"5A”Ñ!™Ëb-L#¼A”Ñ!™ïT
»	A”Ñ!šV@¶"qA”Ñ!šz@Ã0‹F
A”Ñ!šîà‰¬xA”Ñ!µe Œ&66ÏA”Ñ!¶ŠQ"íO2A”Ñ!¶‹ D*B!²A”Ñ!¶È 
UÐA”Ñ!¶Ï`lðBA”Ñ!·Àÿ@A”Ñ!·x€¶A”Ñ!·™à
Ÿ&×IA”Ñ!·þÀ/( $A”Ñ!¸XÐ
˜
A”Ñ!¹ W,Ô,9A”Ñ!º Ì÷*ÃFA”Ñ!º‡`
#%0fA”Ñ!º¶@ÍÇ­A”Ñ!¼?ÀF2*yA”Ñ!¼ÿ€Z
$"ÉA”Ñ!½@@b£…A”Ñ!ÀjÍÃA”Ñ!À¶ ÃÍ£lA”Ñ!ÚÀ'¹­A”Ñ!Ä?`ÿjA”Ñ!Äd Î"ÚlA”Ñ!Ä÷ 
ü/sA”Ñ!Å`«6+ &(A”Ñ!ÆVÀ
ˆ1ï-H¼A”Ñ!Ç> Ç!sA”Ñ!È+àõ~»)]-A”Ñ!Ü_ 
R-¦,žA”Ñ!Ü›€g IöA”Ñ!Üà G8A”Ñ!Ý ?#CJA”Ñ!Ý^@Ú+2A”Ñ!ÞÞ@X AA”Ñ!áµ ‚à¥A”Ñ!áÁà>1
A”Ñ!â>@4¼y ÛÞ	A”Ñ!ëP ¸%.THA”Ñ!ì#àø-qA”Ñ!ì© ‹+
qZA”Ñ!ì¬àb2çùA”Ñ!ìÚàÛ+/.¡1A”Ñ!î]@€µ"áA”Ñ!îÏÀ4«$íA”Ñ!îØ€$&¢ÝA”Ñ!ïY h½8ÑA”Ñ!ñs`Æ%³	ÓA”Ñ!ñéÀgÞ
Ï9A”Ñ!òO@Ц,A”Ñ!ò’`¯?*iA”Ñ!òž	À,X+	A”Ñ!óA@Q+¨ã
A”Ñ!óΠû*p¢
A”Ñ!óï »"	%o|A”Ñ!ô ês,çA”Ñ!ö“`	%,	A”Ñ!ùt@EÉ5A”Ñ!ú×€Q©,@A”Ñ!û
à	& ë8áÇA”Ñ!û†`£
o7A”Ñ!û‹À½6aBA”Ñ!û˜€Î
*q
A”Ñ!üé 	nÚª
A”Ñ!ý<@ü2ØA”Ñ!ý¦@­0¹ ˜¤A”Ñ!ýæ@
²+`!˜A”Ñ!ÿÕ 
vÃ$ùA”Ñ"i 
”	±åA”Ñ"€7.è	A”Ñ"Ÿ'«!=-A”Ñ"W
Û
/‚A”Ñ"Šà¼êjA”Ñ"À€u4bA”Ñ"ZàÔ& ¥2A”Ñ"¨€F'ñA”Ñ"
Ô®*¨NA”Ñ"	/`	[
VA”Ñ"	 (ê/‰	A”Ñ"
C@1
Ð'(A”Ñ"
8 _:"ŽA”Ñ"
w@ˆ-™(~A”Ñ"
È 	°ƒ,º
A”Ñ" b1ì”+A”Ñ"M…&¹*A”Ñ"+ ã.Ÿ(cA”Ñ"Ô	±6¹$õkA”Ñ"|8.‡A”Ñ"¦`Ç.ç&
A”Ñ"Û€tô
GNA”Ñ"Ä q!µYA”Ñ"@&$F7¾
A”Ñ"ï »RA”Ñ"tÀ
*wA”Ñ"ð@Ó/f(vA”Ñ"h 	ŸLA”Ñ"¯Àç3›A”Ñ"À%f(þ&A”Ñ"& 	æ!‹çA”Ñ"j |˜1åA”Ñ"{`´¤‰A”Ñ"‡@ݵ(c
Aӄ"@	%8
ÆA”Ñ"§f ©kA”Ñ" ?  8A”Ñ"ÝÀéö6ìA”Ñ" Wñ}A”Ñ"˜àv.50A”Ñ") )YÀ
A”Ñ"Ç`(\ A”Ñ"Ê Ì'áA”Ñ" é€{)i&hA”Ñ"#*€ÔwMA”Ñ"$= ;5ù^A”Ñ"$ O<k	A”Ñ"$¦àà& 
A”Ñ"%4$K93A”Ñ"%æ`ç¼+ÆA”Ñ"%ë€	>
$~	Aӄ"&R
 ƒ
A”Ñ"&r`Õ+ÓL	A”Ñ"&é q4¿)ìA”Ñ"'‚ ‘73EA”Ñ"'«€"ÑsA”Ñ"'þÀóf+›JA”Ñ"(	°3g"]A”Ñ"(-à>(ƒ4EYA”Ñ"(‹½j&A”Ñ"(Ò ú%¸7è
A”Ñ"(Ó@õ	*$[*`â$ö)DA”Ñ">Á ({q
A”Ñ">Äà¢ûA”Ñ"?µÃ%>-A”Ñ"@oà€Ý
+OA”Ñ"Bàk*#3A”Ñ"BYà**H0A”Ñ"CÀà)Ü^"A”Ñ"C¶`ƒ"bA”Ñ"D@ $÷5'5A”Ñ"D†ƒÂ"˜DA”Ñ"DÐ@Jù'eA”Ñ"F@T
A/(A”Ñ"GÈ`&ÒÏA”Ñ"HÀç#±:A”Ñ"Inàf!?!CA”Ñ"IÛàa`!A”Ñ"K€ 7)·A”Ñ"K 
çÎÅ/A”Ñ"LW ±& ˜A”Ñ"M4 R ø¾KA”Ñ"M¶ r+,+qA”Ñ"NàC-t2GA”Ñ"NŒ ,v2'A”Ñ"P1Á4ðA”Ñ"QV€/Ÿ=]A”Ñ"Q¸ÀŽ"ï3^A”Ñ"Rã}!8fA”Ñ"T 1+çGA”Ñ"UÀ@	›3"³A”Ñ"V€–&*A”Ñ"Vl€ý™)AA”Ñ"V­à
›¶LJA”Ñ"WqÀ_^0Í	A”Ñ"X<€)á7„A”Ñ"Xœ â
­0$EA”Ñ"Y[€_3+A”Ñ"Z"Àž,{5m…A”Ñ"ZÕ@Ùä6Ä
A”Ñ"[Ý@Ô*¤)3A”Ñ"]·€	sl»\A”Ñ"^Þ@•#gA”Ñ"_‘
zq'_A”Ñ"`€ %!„$r^A”Ñ"`€z'a_3A”Ñ"` )5F:
A”Ñ"`© k!>F$A”Ñ"a3à!šiA”Ñ"aø@Rÿ"†A”Ñ"b4 M)½ËA”Ñ"bs`Ñ/›šA”Ñ"c&@ÉU7A”Ñ"c4`÷Ux6A”Ñ"dãÀ[$R
A”Ñ"e@å) ÕA”Ñ"e *}'lcA”Ñ"ežÀ·ú/d
A”Ñ"fX`c0Ð
A”Ñ"gQ@Qc‰A”Ñ"h
iO0›A”Ñ"h€€%¦0Q#A”Ñ"h! ê»!!_A”Ñ"h³ ~jA”Ñ"hΠ¿'\y	A”Ñ"hÏQ(Ü	âA”Ñ"jCÀ0£A”Ñ"n\àn
¢ ÀA”Ñ"oà~%÷
A”Ñ"ob 2ìë-A”Ñ"oŸ`&2°IA”Ñ"o°`Ö

!A”Ñ"puû"Í7×A”Ñ"q£ 	…^A”Ñ"rÆ (eŠA”Ñ"r×àAß6
A”Ñ"u{ N+H þA”Ñ"vd 
¶Î…MA”Ñ"vÐà@÷7áA”Ñ"w!@n:6A”Ñ"y€r35A”Ñ"z` õS½
A”Ñ"~Xà‡|3ŠjA”Ñ"p€“ÄA”Ñ"  >$FëA”Ñ"€-Ï=A”Ñ"‚4ÀþêA”Ñ"ƒˆ€ÖäÇA”Ñ"ƒ— 	âÛA”Ñ"ƒµÀž&ø*eA”Ñ"…æ`æ'š.3(Ëì{A”Ñ"¡•@¯ôìA”Ñ"¢ê .
A”Ñ"£ø õ2±­>A”Ñ"¤àÝ Î'A”Ñ"¤.€
ëBqA”Ñ"§FÀ¦0`&H
A”Ñ"§K@
{ ¶bA”Ñ"ªKà5è%/gA”Ñ"ªV€¿
BA”Ñ"¬& †ÖŠ6A”Ñ"®ÓÀT4ç¦7A”Ñ"¯l w0“$9
A”Ñ"¯¬€‹8SA”Ñ"°A@G%ÎA”Ñ"°Œ (''Ï,A”Ñ"°Ë¸
˜àA”Ñ"±*`t3)>A”Ñ"±µ
â'àA”Ñ"²d`¢<.õ1A”Ñ"²ß È/"ù+A”Ñ"³§àI+ÒaA”Ñ"³Ìæ(O,á	A”Ñ"´» aÂ+oJA”Ñ"µ‹ 	I BCA”Ñ"·	Àa0NA”Ñ"·`9!ƒ$ÕA”Ñ"·à	6zÒ A”Ñ"·@ U'¨ìA”Ñ"¸ p²	A”Ñ"¸-€Â7"ýA”Ñ"¸ÿ
²CƒA”Ñ"¹Î€‚
if
A”Ñ"º`¼"])B	A”Ñ"»L@	 1RA”Ñ"¼Ý@}0|(9
A”Ñ"½ÍÀ	c+S	ZA”Ñ"¾K`‰9A”Ñ"¾„HjÖA”Ñ"¾™ P-7TA”Ñ"¿g`j!èTA”Ñ"Àx`…$
.QA”Ñ"À‘@Ó3<
A”Ñ"ÀÄ`h »¾A”Ñ"Á«€õ‹¼A”Ñ"Áó ô5|mA”Ñ"Ä2À
Æ ¼A”Ñ"ÄÊ`é4{!I
A”Ñ"ÄÜ€×û.,TA”Ñ"Å› 3í"A”Ñ"Æ+€o )œA”Ñ"Ær¡ ¢&ûA”Ñ"Æç`
ç%7{LA”Ñ"Çá€(\ì
A”Ñ"ÈEàÑ&±|	A”Ñ"ÉþÀ&/ø*†A”Ñ"Ê' )ö2(A”Ñ"Ê@`n(̺A”Ñ"Êt[%ß	A”Ñ"Ê~  ªŸA”Ñ"Ê„€Ð%t:A”Ñ"Ê¢ B&®1A”Ñ"ʹ`:
åA”Ñ"Ëà#ÚZA”Ñ"ÌÑÀK4VWA”Ñ"Í@—­-
A”Ñ"Ï?À) ¡A”Ñ"Ïø ô
}ËRA”Ñ"Ѐì<#ÊA”Ñ"Ñ 
DëëA”Ñ"Ñ|Ž0i
A”Ñ"Ñ­€PëÂA”Ñ"Ò9´$»S*A”Ñ"Òú ¹4H)ŽA”Ñ"Óœ j™i@A”Ñ"Õ›¹ŽA”Ñ"Ö1 „
ÙTA”Ñ"Ö@îÝ
JA”Ñ"×ÂÀí
GA”Ñ"ׯ@χ’$A”Ñ"Ø+àvçä8A”Ñ"ذ`.+A”Ñ"Øþ i(ÈmA”Ñ"Ù‚ÀÁ÷(ÐA”Ñ"Ú

%)¯ëDA”Ñ"Úý¦!‘A”Ñ"Û·àÅ%€àA”Ñ"Ûäào"à<A”Ñ"Ü`àOP)A”Ñ"Üm 	;6A”Ñ"Ü–€tæRCA”Ñ"ß)A”Ñ"á@iaúA”Ñ"á ü(É427A”Ñ"åš@YVŽA”Ñ"æÛ@¤/V'ÀA”Ñ"æã 	›!Þ
A”Ñ"çä2,+A”Ñ"ë5à	ÓΣA”Ñ"ëV e"j
PA”Ñ"ì÷àbŸqA”Ñ"í€ú&( ³A”Ñ"î¯à
Úæ.A”Ñ"îâ(Ã
W	A”Ñ"îïÀtð5¼A”Ñ"ï< *"ö!1A”Ñ"ï¥à
“p
A”Ñ"ðÇ@_!
h
A”Ñ"ñä@_$EâA”Ñ"ò—¡# Z-A”Ñ"õ€¿/‘6A”Ñ"ø} /‹ÁA”Ñ"øƒÀv7±A”Ñ"øøà€(ï
A”Ñ"øû€i! CA”Ñ"ùŒà103A”Ñ"ù¨`É%ìA”Ñ"ùÅÀ<AA”Ñ"ùüà$0/Ê
A”Ñ"úç%3&FA”Ñ"ú¸€=)»A”Ñ"û€O0H1ÈWA”Ñ"ûAà,(;A”Ñ"û×à
Ü"ú
;A”Ñ"üL`öïA”Ñ"üj 1/B>A”Ñ"ýk@9-¡&46A”Ñ"ýäà
z)/#jA”Ñ"ÿ‘ 5+?A”Ñ#œ /A”Ñ#c@Æ"×
A”Ñ#]à
2ª5×+A”Ñ#í@##ÝŒ5A”Ñ#|@Y=A”Ñ#â@Ù°
ÕA”Ñ#á€éú+A”Ñ#Ä€	ÀéA”Ñ#	O@âs4bA”Ñ#	o@w_ÐA”Ñ#	ð€ù%A”Ñ#
kÀGA”Ñ#`aª)àNA”Ñ#9`
`"¢3èšA”Ñ#NàÃ¥ƒA”Ñ#5àú0ùA”Ñ#°@÷#«2ZA”Ñ#>`ˆ…‚pA”Ñ#P š%ÍA”Ñ#|*úA”Ñ#à9 @ Ç	A”Ñ#.DsA”Ñ# 
þ"(A”Ñ#j@
Æ)£)A”Ñ#¯`ö(™
A”Ñ#Å ÞL2/	A”Ñ#Àæy;
A”Ñ#iÀýš)A”Ñ#@	¿,0ÃA”Ñ#1€ä#õ'IA”Ñ#t
b^7ÐA”Ñ#À€V«ž"A”Ñ#/à½2±^A”Ñ#H€<(ÀÆA”Ñ#)`	#qê‰A”Ñ#“ Ð0²#A”Ñ#n Ò%×5A”Ñ#†@
ñ
ÈA”Ñ#—€ÆB&ý'A”Ñ#o`
öU4ýA”Ñ#ï@V\:A”Ñ#ñÀ6× A”Ñ#öÀ
ð ,A”Ñ# ä ž1P)ôA”Ñ# ñÀ6+S2L€A”Ñ#!
.‡áA”Ñ#!~@×
05A”Ñ#"NÀý-/XVA”Ñ#"`’,q0A”Ñ#"À>ã
š.A”Ñ##
R$X#$AA”Ñ##€ $i‹
A”Ñ#$ʽ67A”Ñ#$’€5+ÙWA”Ñ#$éà±Q%™A”Ñ#'“@1k%
A”Ñ#(ä@
Ê$A”Ñ#*ìz Ý01
A”Ñ#,eàÇ(O×
A”Ñ#-ßB-Ç(^‚A”Ñ#.À	8%=#A”Ñ#/F`À£A”Ñ#/p`ª1$ðA”Ñ#0Å`
Ý#‘1É
A”Ñ#1 Å0#:A”Ñ#1èÀÌï'4€‚'È-Ê
A”Ñ#>½À¡0â
AA”Ñ#?€r#7	A”Ñ#@_ g¢2ûA”Ñ#@b Š#­5"A”Ñ#BÂàñïú
A”Ñ#BØàŒÒ A”Ñ#C´&ÍA”Ñ#D  
Òi. A”Ñ#FgÀ.3ç¨PA”Ñ#Fˆ€ˆ,Æ,þA”Ñ#F Ãe![0A”Ñ#FÇÀ¤1$A”Ñ#G?MÇ…A”Ñ#Gý`¸*A”Ñ#H±àM-@$=
A”Ñ#J`d!J wA”Ñ#Jm@0pA”Ñ#K@è3)%A”Ñ#Kcà	Ç“2ÏA”Ñ#L£ Ž+ä*A”Ñ#Mr26ûA”Ñ#Mx€¡»A”Ñ#M” ¯¿2A”Ñ#N×€Ü6„ì¶A”Ñ#O©à%`×A”Ñ#Oéœ#qþuA”Ñ#Oñ@·.µÁ2A”Ñ#P¥ š3ñùA”Ñ#Qh 
F H'µA”Ñ#Q`
?á+Æ
A”Ñ#R@E#A	A”Ñ#Tà
µÐöA”Ñ#T7`&#cA”Ñ#TE€Q/«*êA”Ñ#T¬`¯05þ"A”Ñ#T®`+'Å	A”Ñ#Uhà	œ*>)A”Ñ#Uš @Ì(Ø A”Ñ#U¶À
› ­
§A”Ñ#V  ÒM3A”Ñ#VßàFà	A”Ñ#WÂ`S(Ÿ
 1A”Ñ#X3 §z/ÈA”Ñ#Xvë/y
A”Ñ#XÍà,)é&ƒ†A”Ñ#YV 
U
”A”Ñ#]¶ ik—.A”Ñ#_€Ã2÷%ÒA”Ñ#_À
1#o'…A”Ñ#_Æ 
%ÏéA”Ñ#`qà0N++A”Ñ#`Ë |xµA”Ñ#aù€%o–A”Ñ#b¿ Ë$©+»	A”Ñ#c¸ ÔT#AA”Ñ#cÎà¬"í}A”Ñ#dà8	™(JA”Ñ#fù€(&…">
A”Ñ#h•àÅuA”Ñ#hº€b!c!eA”Ñ#iTà
'"A”Ñ#kà	ý%‡vA”Ñ#l¦—‹ÈA”Ñ#l±m$BRA”Ñ#m…Ú%rºKA”Ñ#m™8 òA”Ñ#n® –ÊA”Ñ#oMàÄ,÷ ¾A”Ñ#oŽ`
2¦%Ç
A”Ñ#pR $2¶¶A”Ñ#p•YA”Ñ#q!`Ï)¸-A”Ñ#s`ÈnŒÌA”Ñ#sz@H¹7d
A”Ñ#tp j¤mA”Ñ#u1€"âA”Ñ#u„€>}$xA”Ñ#u¥ò-*[7A”Ñ#uÛ€³÷!Á
Aӄ#v
 Ü4‡+A”Ñ#x?@d"8 aA”Ñ#xvà7m#vGA”Ñ#x©à'"Ú6Ã
A”Ñ#y€!— ;A”Ñ#y-€(*ÐA”Ñ#y‡`	\,Î7A”Ñ#yËÀ#
¶#A”Ñ#z´
­-æ1¡^A”Ñ#|P`"ñ*ÏA”Ñ# àˆ)mWA”Ñ# Õ/!MA”Ñ#yÀÁò$30A”Ñ#‚”à%:.ªA”Ñ#‚¢à.…
A”Ñ#‚¶À£d*	A”Ñ#ƒ`	£5ìA”Ñ#ƒf@ 0E"^A”Ñ#ƒl€èœA”Ñ#„A@>.H(2A”Ñ#…`õ%1ÐOA”Ñ#‡ž`r0(~A”Ñ#‡¥€ç
8/A”Ñ#ˆ@	7;`
A”Ñ#ˆ¨à	_
A”Ñ#‰[ ¯"(ÝA”Ñ#‰¥ 	n+å8A”Ñ#‹CÀG.·#
A”Ñ#‹P@û/A”Ñ#‹Ú@C!Ÿ2A”Ñ#Œe Ô'2ºA”Ñ#ŒÉ€‡Ÿ(’A”Ñ#Œÿà	ò.8+úA”Ñ#6€ã
A”Ñ#ñ ¢3!6A”Ñ#E€ž/Ÿ
A”Ñ#m Ò(~ãA”Ñ#“H`¢®\A”Ñ#•À.äA”Ñ#•²@ð
•A”Ñ#•ßËF5ZA”Ñ#–†`OG"A”Ñ#—o€
n!@&R
A”Ñ#˜•@
Î'Ë&fÖA”Ñ#™/`
f	Ù9A”Ñ#™Æ@£"*ÄA”Ñ#šR€	x¼A”Ñ#›Ò@”¸ÅA”Ñ#›ð@îýrA”Ñ#œÀ¿^A”Ñ#œûÀV.àA”Ñ#a ;1¬A”Ñ#Ô ë/!Ã:A”Ñ#ž n!ÑÜA”Ñ#ž]`$º0Ö.A”Ñ#žº€&¿A”Ñ#Ÿ@W’|A”Ñ#Ÿ¦@Ð3*SA”Ñ#ŸÜÀ	(
)¯qA”Ñ#¡2ÀŸ*
A”Ñ#¢Høp-[A”Ñ#¢‡@ˆ
[+ºA”Ñ#¢Ó@	.R/Ä
A”Ñ#£| A/*Î6A”Ñ#¤5 ¢!0A”Ñ#¤ËÀS/ƒß
A”Ñ#¥“ÀÐ	Œw
A”Ñ#§Ý ¾¢@A”Ñ#ª!@D+%
A”Ñ#«Ù 
â^À²A”Ñ#¬Nà7eáA”Ñ#¬d »0AA”Ñ#¬n ÿ-´›A”Ñ#­ô ·3Úô
A”Ñ#¯@¤0–ØA”Ñ#°, ®øýA”Ñ#±1€oi’	A”Ñ#±j€¤)Ã+A”Ñ#²‡ÀÉ/A”Ñ#´š«%»7‚èA”Ñ#µ®À\Ý5:A”Ñ#¶, I¶ëA”Ñ#¶Ù `V4°A”Ñ#¶ý anA”Ñ#ºI€Žf	-A”Ñ#º”àm
ŠA”Ñ#¼È 3(ÔA”Ñ#¼÷àô.ËŸ
A”Ñ#½D Y"ô(A”Ñ#¾É€	²æ&;.A”Ñ#¿‚ 
Ý!ù,å
A”Ñ#¿¡€3h"ïA”Ñ#Á¤ 
]"Ë7A”Ñ#Áä`Â6%heA”Ñ#Â2àdaãA”Ñ#Ã,À)feA”Ñ#ÄWæ1òA”Ñ#Å^€Uí0Ñ	A”Ñ#ÅÞ`þÁA”Ñ#ǽàäX6A”Ñ#Ê
Àí)¬A.A”Ñ#Ê- *W%%
A”Ñ#ʘà
Ø£2#}A”Ñ#ËJ 0¶pXA”Ñ#ËWÀpΆ
A”Ñ#Ë£b‰µ
A”Ñ#Ì~à”)ðŸA”Ñ#ÌÕx	A”Ñ#Ìê ,‘-ÚA”Ñ#ÍÀ%b	,
A”Ñ#Í× #Y+mA”Ñ#Î2 â–#;(A”Ñ#Îå»ÙqâA”Ñ#Ï ¦F)‰PA”Ñ#Ïpà
+++Ç
A”Ñ#ÏàE3•ÖA”Ñ#ÐQ ¾-daA”Ñ#ÑN@–Q·A”Ñ#ÑÄ`ÞÉ1Ü
A”Ñ#Ò# ´1æA”Ñ#Ò¡½!xA”Ñ#Ò¤ 
ïþA”Ñ#ÓŽ€Þ*À3V	A”Ñ#Ô<€@y·+A”Ñ#Ô¶ %2¡A”Ñ#Ø.àï"µ}A”Ñ#Ømàs
ù±'A”Ñ#Øœ7·
A”Ñ#Øä Ò-9²A”Ñ#Úd i{º×A”Ñ#ÛDÀ‡†*
A”Ñ#Û¦1Â-~'A”Ñ#Ý€,'(:A”Ñ#ÞI@	Q¥ ®A”Ñ#ßÀS.¸A”Ñ#à-`³¨$ÇA”Ñ#àrÀÜ5¥$|A”Ñ#â°`
Å	•(xA”Ñ#âúà
Ö(:$‰A”Ñ#âý;¿%|$A”Ñ#ã+ £€¦A”Ñ#ãjÀæ*'PA”Ñ#㜠	¦%̶A”Ñ#äkµxÔA”Ñ#åË@ë•%A”Ñ#ç¤À°5	¥+A”Ñ#ç­`	)ò®A”Ñ#èë 
´)Ì •-A”Ñ#é7€
;5A”Ñ#é[X°A”Ñ#éÕ@œÙŒ]A”Ñ#ë…@	
ÚÌA”Ñ#ëžÀOk0A”Ñ#ëÄ`&		!Ò
A”Ñ#ì+@a&ü
žXA”Ñ#ìE &Ã[A”Ñ#ìq`c* A”Ñ#íD
8$Ë1?
A”Ñ#íÙ  "£7
A”Ñ#îÆ §é$XA”Ñ#ïà
6tÛA”Ñ#ðS@€)0£A”Ñ#ñYµ2eAA”Ñ#ñz€x!€A”Ñ#ñÿ@'Þ!ùA”Ñ#ò.À”[A”Ñ#ò® Ú8ßGA”Ñ#óÙ"«A”Ñ#óý*qA”Ñ#ôÝ 	©+…$ïA”Ñ#ôÞ€
Ë$HÈA”Ñ#ôö`S,ž&{*A”Ñ#ö 	è(ˆ
Ÿ
A”Ñ#öq ]×™A”Ñ$˜  y+Ä@A”Ñ$ÊÀ² 
¦A”Ñ$ÀXVŽ2A”Ñ$ÀË6DA”Ñ$f€
!6PXA”Ñ$ª ~0Ç"ÞA”Ñ$œ@ˆGÙA”Ñ$`.-!
A”Ñ$¢àn‚4A”Ñ$ðý¨&AAA”ÑS´` 
ò
OA”ÑSµ/ X³ ŸA”ÑSµh <%P7 -A”ÑSµÜ@É4¹%%A”ÑS·'
È*! A”ÑS·8 Ö›YA”ÑS·§ Çö-Š
A”ÑS¸@Ù&—3A”ÑS¸–À ú§PA”ÑS¸ü@¼,4	A”ÑSº_€T+?QA”ÑS»Sà¯Q!uA”ÑS»‘`7À2A”ÑS¼eÀ:'·?A”ÑS¼o 
âíA”ÑS¼¯@†&{"A”ÑS½ü@ú"ÌvA”ÑS¿J`ë>AA”ÑS¿yàÔ±&k
A”ÑS¿í`r-ŽA”ÑS¿òÀ	±.ÝA”ÑSÀ !Ë0ÙA”ÑS #Ö‡A”ÑSÊ 'ö4¥jA”ÑSá€@7Š

A”ÑSÄ@Ó$
A”ÑSÅ@©Ï–7A”ÑSÆ€œ/æ1GA”ÑSÆÙÀ±	ÛþA”ÑSÇ> AtýOA”ÑSÇ•`'
•%¼
A”ÑSÇÄ Ö8ÒÍA”ÑSÈ1 
iÏA”ÑSÊB€7pA”ÑSËÀŽ3Î'ö)A”ÑSÌ®à	Zîq
A”ÑSÍ´ -D#b
A”ÑSÎë (Ù²#A”ÑSÐà÷@A”ÑSÐo`
+H&WA”ÑSе`
±Û„A”ÑSÐà@w19"A”ÑSÑ–ÀGA”ÑSÓN@V3"TA”ÑSÓd`f!lA”ÑSÓoÀõ'Ì:A”ÑSÓ ®D NA”ÑSÔ CÉ"‚A”ÑSÔ=€
Õm"-A”ÑSÕŠ 
ÝŒ HA”ÑT.! U{	"
A”ÑT.I€Õ#è"{A”ÑT/ýà
PTóA”ÑT1/Š$`÷A”ÑT1F ­ï|A”ÑT2”àržk
A”ÑT37@`"Ð,ï
A”ÑT3`Ðwè|A”ÑT3¶@RvÑ/A”ÑT5°à.+Ä2A”ÑT5Ý —
@$®A”ÑT6³@
•"´é%A”ÑT6³à)f —ƒA”ÑT7ªÀ1XlA”ÑT7åÀÄ ¸A”ÑT9 š(	Š?A”ÑT9c ]ö	A”ÑT9| äŸ#%TA”ÑT:
á/¯9
A”ÑT:{@A(|/bA”ÑT:½€3?+$A”ÑT:ÖàÝ•"ÍlA”ÑT=×`
õ“ØA”ÑT=ã#‡A”ÑT=õ€.@1è	A”ÑT>š@¨&à
A”ÑT>· F¹"ZA”ÑT?À
é~]A”ÑT?ÏÀi$*ÄA”ÑT?éàê!A”ÑT@Ê@‰ñ1˜A”ÑTC¿@‚ü
A”ÑTD] ÊH(A”ÑTEÌà½(Ô *eA”ÑTEáÀL2(ä
A”ÑTFÌà×$– ¼A”ÑTG& ;4÷zA”ÑTGà¶6f&×RA”ÑTG»@	ü¿-kA”ÑTGãÀ¥åÕ*A”ÑTHÀ+ÊA”ÑTH€€_$XÎ
A”ÑTI€@½ö%¯A”ÑTIò`j-Û%×	A”ÑTJÀ
ÿS7¾LA”ÑTJŒàVÜ21 A”ÑTJ§ ŠÏ—A”ÑTK: Ñc	A”ÑTKU § î"A”ÑTK^€
º
Õ½A”ÑTKë ½	—Š>A”ÑTKë@“".4A”ÑTMj 7C0MA”ÑTN? ÜÝ60çA”ÑTQ\àÑ*!
A”ÑTRƒàq#øŽ	A”ÑTR¤`Ä2ˆ%¸A”ÑTSYÀ
Ñ%5ZA”ÑTSå~(¼
AӄTTO@
ë5a	A”ÑTTÈ`é1“A”ÑTUˆ@;..1A”ÑTVÀàG"‚íA”ÑTW.€ÍŸö
A”ÑTW?€ûd]A”ÑTWo I4Ö]A”ÑTW—`V4¡<A”ÑTWÜ %5wÂA”ÑTX¹ ÷'ðA”ÑTXÆ@%59¼A”ÑTXÛ /Ì!]A”ÑTYJ`£4.6A”ÑTYP ø r—A”ÑTYu@Óø&·[A”ÑTYx`U*ÏŒA”ÑTZ`˜WúQA”ÑT[7àè.|%¬	A”ÑT[ù2ÕA”ÑT\n˜T%ÐA”ÑT\ò`œ+¡5A”ÑT]N`é§/A”ÑT]©àKŸ/A”ÑT^’ Ý,•ØA”ÑT^¶ ®1÷œ'A”ÑT^ÕG!ßA”ÑT_kM1A”ÑT_‡¼4±-AA”ÑTbÀ´$þ#œA”ÑTbk`·ú5‹GA”ÑTb´@3\¡
A”ÑTcàã#.-Â)A”ÑTc¬ jÝ*1A”ÑTcЀ	Ç'ö(;A”ÑTcß`
‹žIA”ÑTdÈ@ÅA”ÑTe.`®ÙËA”ÑTe<@(•
á-A”ÑTe@‚$iA”ÑTeà
¨&«&Œ
A”ÑTf0#A”ÑTfa2|C¬A”ÑTgŽ ¹‡VA”ÑThç ó!‰A”ÑTi³F&ø8g
A”ÑTiä`‹(â#:
A”ÑTj­àµ+'‹mA”ÑTjÑ ƒ+º$1	A”ÑTjØ`	,t.˜A”ÑTkG u'hOA”ÑTk À3&FA”ÑTlÎÀV&Ø)|	A”ÑTm@	~$ÈA”ÑTm!àQ3$) 2A”ÑTm5@ÿs£A”ÑTn4àÄ $ÕA”ÑTnÐ »ä=A”ÑTo	àP
´A”ÑTpâÀu
|.fA”ÑTqR@JÒÒ1A”ÑTqUÀЏ4A”ÑTrË@.&	Ý	A”ÑTrÑÀê#A”ÑTs%À¢%ö	±A”ÑTsâ€v6W!5A”ÑTt‹à
.1 ¿A”ÑTt 
»	!&öOA”ÑTtø`~%šA”ÑTvvײ*ôA”ÑTv— 	ª/î
A”ÑTy³ 7¬Â:A”ÑTyÓ b&A”ÑTz<àÓ'µxA”ÑTz¯àÄ-xA”ÑT~+E5‡&iA”ÑT~Ñ€
La1ø
A”ÑT a ßA”ÑT€ö à+A”ÑT¯€	öÝ%A”ÑT‚ÇŸA”ÑT‚äàñU(aNA”ÑT„ _	‚
A”ÑT„o 
/5ä5A”ÑT„ç)«#ÉA”ÑT…^ 
v14$×A”ÑT…b€]w zA”ÑT†­0öW
A”ÑT‡Ñ@D#ˆA”ÑTˆÕ€
+sð[A”ÑTŠ
Àe4ç-]'A”ÑTŠyÀ[zA”ÑTŠ¡€áY	Ã/A”ÑT‹Š 6+ßA”ÑT‹Ã€	X!8'XA”ÑTŒ*`
é5SédA”ÑTŒ2 »¾+zA”ÑTŒô€	Ú0•%,A”ÑT™€4*îlA”ÑT¶@”19
¼A”ÑTÊ£!Ç"’2A”ÑT‘«`
hg2lA”ÑT’Ààšd'öA”ÑT“e,ˆ!	A”ÑT“£à
•‚/qA”ÑT•9à=i
“A”ÑT•=àb.ÈFKA”ÑT•K@J¤®mA”ÑT•á@‰1gA”ÑT–K€˜;,p&A”ÑT–u Y«FA”ÑT–úÀû$…A”ÑT—ÀŸ5ÌA”ÑT—à'.-¬	A”ÑT™[€/!ŠA”ÑT™ÃÀ°
¡gA”ÑTšøàD!Ñ-ÑA”ÑT›( g‹ÑA”ÑT›/ .,“!A”ÑT›\@al)ÃA”ÑTœ4 
#(¹/s
A”ÑTœÄ`%(x7A”ÑT« !*‹$A”ÑTž
C+RA”ÑTŸš`ߨ!Ó@A”ÑT jÀ
ã%é
cA”ÑT ½`Ä'Ð-A”ÑT Ì5!¼$A”ÑT¡w #ûA”ÑT¢d
tCiA”ÑT£Ò€£2âA”ÑT£Ó ÆvNA”ÑT£ýàØ2|6A”ÑT¤÷`N4ì%HA”ÑT¥Ì@
Ü9%.A”ÑT¦À
("6A”ÑT§– Ÿ+øˆA”ÑT§ÛÀ&'A”ÑT¨8 Io
A”ÑT¨Uà~#÷$E
A”ÑT¨€X]P	A”ÑT¨”Ào³!ü=A”ÑT¨Ÿ †E#3A”ÑT¨Ú€
;4ñÓA”ÑT©ž'?/ÿbA”ÑT©C€ë,XxEA”ÑTª
8i&™&A”ÑTª)àÍê	.EA”ÑTª’ ¶‚+HA”ÑTª¯ 	•	.ðA”ÑTªéàpÐ)A”ÑT­€žÈ¸oA”ÑT®|Àì"ò7A”ÑT®Ö 
í
Þ"DGA”ÑT¯“ÀË"A”ÑT°« ¦2ïJPA”ÑT± /„æA”ÑT³` É%­ƒA”ÑT³‘ÀÁ%ÞËTA”ÑT³ç`¸!Â&A”ÑT´Uàh0*š
A”ÑT´`1-åBA”ÑT´°@²!ãµA”ÑT´ì€¶#r#lA”ÑTµ8ÀË
ÂA”ÑT¶€é)úA”ÑT¶X`	Žö"vHA”ÑT¶{À¦ LA”ÑT¸9`Å×}*A”ÑT¸|àK'ÿ8FA”ÑT¸¥HÁA”ÑT»å Bµ®A”ÑT¼~`s0ÌA”ÑT½À
ó$ûCA”ÑT¾È€³,"	²
A”ÑT¿~Àü0»`A”ÑT¿ù€‚5)Y?A”ÑTÂC E*Ê0
A”ÑTÂä`™*°cA”ÑTÃ`,¤&ÊA”ÑTÅŽ %6~A”ÑTÆ6 ß#5qA”ÑTÈ æ½#žA”ÑTÈ'`
	ÀA”ÑTȨ€Œf+KNA”ÑTÈ÷@	1H,ÙA”ÑTÌ `z#*
A”ÑTÍ!
ºk&ÛA”ÑTÍK@â1¸A”ÑTÎÄ@Fð¿A”ÑTÏ 10€äA”ÑTÐ{@£&¶
X!A”ÑTЀ€TÀ!A”ÑTÒªÀFÓ¾A”ÑTÒÉ€£.#"W
A”ÑTÓJà½(É0…MA”ÑTÓl€}&™	åA”ÑTÔ,`+-2#Ú:A”ÑTÔ  ü8!à7A”ÑTÔÂ`™.s²,A”ÑTÕyàs]6QA”ÑTÕ€`5½-€7A”ÑTÖe€¶‡#Á	A”ÑTÖ´€
£Ý3A”ÑTÖØigßA”ÑT×/ 2±3A”ÑT×/@r*·ÝPA”ÑT×çÀ*òA”ÑT×ñ@Ó46´A”ÑTØ\€.1-,hA”ÑTÙ6‚#¡A”ÑTÙw 
¦5` A”ÑTÛ™À
†}$ûA”ÑTÛë`
Š–õA”ÑTܱ ¦î)A”ÑTÜù€øƒ0ÏA”ÑTÝD  $OL5A”ÑTÝ–àâ Œ+A”ÑTÞ¦À¤4#•A”ÑTß`¼
ù(bA”ÑTßE€á
´+ùA”ÑTßX€	”/3A”ÑTáÎÀö0ÚEA”ÑTáÝ15;‡A”ÑTâä9'ØA”ÑTãh 
öw5¹A”ÑTãØ€9o;A”ÑTäšà¤³.A”ÑTä­€:!û-ÀA”ÑTäæÀS)î(ÊA”ÑTæ¸	…3ÝÀA”ÑT盀*“,Ú A”ÑTçû QÝIA”ÑTèÀH)(Þ
A”ÑTê		„(h!ƒ
A”ÑTê
x5+PA”ÑTê@	6,å‚A”ÑTë/€áÔ"Ú
A”ÑTíS ®˜-KA”ÑTí¡@w#9-
A”ÑTíò <|"IA”ÑTîL`\a%OA”ÑTîÆ`84ó#H#A”ÑTðÀÐ*Á!¶
A”ÑTð‚@
8	0"A”ÑTðê ß%'’	A”ÑTðñ 
j.ZVA”ÑTñ| »)À	A”ÑTó2à	¤{78,A”ÑTó¢ ¬´-0
A”ÑTôG@Æ.z
¹A”ÑTôc@=¿Ñ9A”ÑTôêàùŸ °A”ÑTþ`

†OA”ÑTþoTjN	A”ÑTþp`ø%*A”ÑTþw 5Ô{A”ÑTÿ}À”+?!ì/A”ÑTÿÜà
&ý$A”ÑTÿñ Vð
*A”ÑUA@Ã-á¯,A”ÑU€$CA”ÑU& Ð+’ê
A”ÑUp #«,£\A”ÑUœ Â#q7.PA”ÑUt ( ’$Æ
A”ÑU„:…A”ÑUb`XA”ÑUiàu
­-æA”ÑUÀOÁVA”ÑUß ©éÄsA”ÑU«Ã&¸µA”ÑU	à;Ç(øA”ÑU	|À
\_»A”ÑU
.๥
AӄU
:`E$N'AӄU
Ë î	`'¦A”ÑU ÜÈ#¾
A”ÑUSÀ
#)<%A”ÑU€yRŒA”ÑULG!1	A”ÑUÛÀ&*A”ÑU
à˰ž4A”ÑU
. %"ã#ò5A”ÑU
w g!9NAӄU
¦Àü@+A”ÑU
Î`ô5ïø
A”ÑU@`®1/
A”ÑUŠ	Ý
†A”ÑUÕ€6ló
A”ÑU¡ ‡	ScA”ÑUGàù,”–
A”ÑUŒÀ0ñA”ÑU, Ñ/SÐBA”ÑUÊj»/FA”ÑU{Àí+ðóA”ÑUØ€A%d#efA”ÑUð ‹¬.ðA”ÑU„Æ'Ë(JA”ÑU 	ͺÁA”ÑU=Å ŠæjA”ÑUg`—+œ2$A”ÑUÅ W ,A”ÑUÑÛ˜ò(A”ÑU>€±²$éA”ÑU­`5.;A”ÑUà@ä7,4A”ÑU$¿G(A”ÑU‘`ª8"l¦A”ÑUÍÀ
ó-2ò
A”ÑU,`6~Ô	A”ÑU	@m%V.A”ÑUr`
7Ç6d
A”ÑU`.'=ÎA”ÑU:€Þ(q©rA”ÑUjÀ3&¢" sA”ÑUã@
"#èÙA”ÑU8à )ê/üA”ÑU’+ZA”ÑUó 	€¸A”ÑU!³à<®)A”ÑU!ôà*)©!ºA”ÑU"UÀ
*§)WA”ÑU#	 
V€(ÀA”ÑU#`
a è18A”ÑU#Š€g4€B
A”ÑU#±©v2ƒ!A”ÑU#ð v!0ŠA”ÑU%ËvR*A”ÑU%ÀHÅ8¼A”ÑU%ò`".R*OA”ÑU%õ`S!T/8A”ÑU&n lÜ)S
A”ÑU(6 	Ã.øü	A”ÑU(ƒ’#O"‰A”ÑU*'
¶/A”ÑU*Ò€?.+5A”ÑU+£Àë­ÛA”ÑU,. J€!A”ÑU,6G6s7A”ÑU,O
ª&ñ÷A”ÑU,à}
@A”ÑU- ù,ÂA”ÑU-=àì @7À@A”ÑU-¤Àñ¶;A”ÑU.! óB-ñA”ÑU05àS)VA”ÑU0—À
$	ÅfA”ÑU0Ú@H&dµA”ÑU2>€*)Wß
A”ÑU2UÝ7'•
A”ÑU2Ö ¶Éo	A”ÑU3] x*16NA”ÑU4	 %žBA”ÑU5KàBÈ"A”ÑU5V€
Œ"§A”ÑU5Ï€a% A”ÑU6:@Ó£)dA”ÑU7¤`
p*>ÏA”ÑU7ÄÁ,û)0A”ÑU8:À÷+‡2†A”ÑU8l )”A”ÑU9Ê`J$’)ÒA”ÑU:ÿÀ	8A”ÑU;%À1ÆL
A”ÑU<š€x$&àA”ÑU=ˆ`
§-˜A”ÑU>Tà˜‡*ÏA”ÑU?) ä
~A”ÑU?CŒ'?
A”ÑU?… DÄ
QA”ÑU?¤ %Ñ)Ó A”ÑU?¯	-ý$àA”ÑU?Ç€/%„A”ÑU?ꀪ!32 8A”ÑU@à×,â(ÓaA”ÑUA4 	#,õ1TA”ÑUBI`›#Æ A”ÑUBËÀeÎúA”ÑUC- /ÒmGA”ÑUC©àÔ(¨'©
A”ÑUCÔ€	ý:.
A”ÑUCí )ê	mA”ÑUGŒÀèZ:"A”ÑUGà>80…A”ÑUH@
µ,ÈA”ÑUH÷ í{%.A”ÑUI$À[8-,A”ÑUI2À(uÃA”ÑUI>à˜[A”ÑUIZàÜ[
A”ÑUI[ S™
A”ÑUJ, É0ª*P	A”ÑUJ¸ 3 !'A”ÑUJ¿ ÜÊ+tA”ÑUKy`‚-ÝŒxA”ÑUL®™ü#=A”ÑUM 
‰ pWRA”ÑUM Ç2ßUA”ÑUM-ÀZê¢lA”ÑUMÔ@¢4)ÌA”ÑUN¿+ !{A”ÑUO] £#7}&A”ÑUOÜ`n3|	A”ÑUPk`…Dô/A”ÑUQ
 °EšAA”ÑUQ†à9
$ª'A”ÑUQž€Š3b!”A”ÑUQ¯`š%°˜*A”ÑUR`à5Ðy(A”ÑUR¦`$#8A”ÑUSC é, _qA”ÑUSï ÂJ™$A”ÑUTËÜ"w&§A”ÑUTÜà
×P{0A”ÑUU ô¼&º
A”ÑUUˆ ­W5#A”ÑUU¸ý/DsA”ÑUV€¯ —
A”ÑUVFÌ—l4A”ÑUWªà1!…"<	A”ÑUXV€
=˜+'A”ÑUXy	!2S*A”ÑUX¶ ¦(4$A”ÑUX ß"2A”ÑUYÖ€m e2‹
A”ÑU[là.è­A”ÑU[Ë`é"ØA”ÑU\àH.ÃñA”ÑU\­`$|1Œ
A”ÑU\å`ê	I%}fA”ÑU\ó@Ù&
©/¬#‘|A”ÑU^ò€º
Q,;A”ÑU^ó 		ÛA”ÑU_4À5¼2©
A”ÑU_‡ @5
SA”ÑU_ð€71Æ[A”ÑUat 
&éQ8A”ÑUaìÀË"j
½A”ÑUc8 ¬,È\A”ÑUc”àØ3($ 
A”ÑUdSà
õ0¯¤A”ÑUdsÀ¼
ïUA”ÑUdÖ€!×30!A”ÑUe ,²æA”ÑUeà !Ï!$)A”ÑUe- 
Ç©AA”ÑUfT Ñy4)A”ÑUfm s
Ç
§6A”ÑUgWD
ÐÝA”ÑUh(`KV*²A”ÑUho 	â7ñ ˜
A”ÑUix Ô)%	/A”ÑUjK`!Ê&J
A”ÑUjß '2pbA”ÑUlZ %@A”ÑUloà¸é'NA”ÑUluà
í3ã¦
A”ÑUm4 °8¤NOA”ÑU©A 	&µÊ(A”ÑUª„àÏ
ÖHA”ÑUªÊà,2¹
A”ÑU«AŸ/@ßA”ÑU«JÀÍÜ(µA”ÑU«Ç@	ÜTMAA”ÑU¬úàÅ7&†A”ÑU­Ž2Ó+)A”ÑU®@SÃ
.A”ÑU®Ú@u©%8A”ÑU¯Ðàô4m@5A”ÑU°-À³ó*KA”ÑU°Ã€	¹IA”ÑU±¨€lYA”ÑU²€“.ÿA”ÑU³ÀkA”ÑU³`y&d ÎA”ÑU³a
…3ð,f	A”ÑU´F —ú$¬A”ÑU¶Ô`˜
A”ÑU·z@»Å
"A”ÑU¸?èF/`	A”ÑU¹L`C-C"­
A”ÑU¹y !{;A”ÑU¹„ [OåRA”ÑU¹ÆV‹"b8A”ÑUºS`
)ûÑA”ÑUº¬ ¿
A”ÑUºÝ`i 0ûA”ÑU¼OÀÒ L5A”ÑU¼œ@o¹
A”ÑU¼· ì
1?A”ÑU½ï`7
sª^A”ÑU¾Ü ( ( 	A”ÑU¿À
Û
¹0É?A”ÑU¿ÀÀ]*o
A”ÑU¿ÏɃ5†A”ÑUÀ¡àZ€*=	A”ÑUÂJ@	±q2—A”ÑUà ”
±A”ÑUÃn`!”A”ÑUæ Ä#A5–A”ÑUÃÔÀš1¸aMA”ÑUÄ« 
ž³2%A”ÑUÆ /-D3A”ÑUÆH`ŽŽ$PA”ÑUÇIÀ;(Ÿ+mA”ÑUǼ@µ!	îA”ÑUÈàq!×,Ú	A”ÑUÈq€S6_&N	A”ÑUÈÒ`	ª*âç(A”ÑUÉp`}Ë#·A”ÑUÊ 
¿
‘A”ÑUÊ@9=!^YA”ÑUÊ6€j p*àA”ÑUË sœ'6FA”ÑUË< 
ä.à(pA”ÑU˯Àñ«³	A”ÑUËÜ ¥Î$UA”ÑUÌyà!$ý˜3A”ÑUÌ× p‚%ÚA”ÑUÌà H5kjA”ÑUÍñÀ‘$ÊA”ÑU·@ßBÐ
A”ÑU΢€¾&Ü’A”ÑUÎÊÀàq0A”ÑUÎï Ø--"VA”ÑUÏY G«)ÄA”ÑUÏÈà
w/ˆO7A”ÑUÏÔ`2r+JA”ÑUÐÀ7
|ÂA”ÑUÑs€Í*kÙA”ÑUÑ… j,/tA”ÑUÑŒ€Z+%_A”ÑUÑÖða')=A”ÑUÒ’€
yÕ0=A”ÑUÓÌ	´¡ A”ÑUÓ~`{½%¾8A”ÑUÓ¡`
p 'A”ÑUÕ-à3:;6A”ÑUÕ2àCÏ0A”ÑUÕHà.2Ù A”ÑUÕo@¸
ýçA”ÑU×±à7ÌA”ÑUØ€äWB?A”ÑUÙ·à5
A”ÑUÚN`9ç6qfA”ÑUÚˆ Û†
ïA”ÑUÛC€Â†Z&A”ÑUÜ8 Ô0üSA”ÑUßr@p!ä1³ÑA”ÑUß÷À´ ´3ˆA”ÑUàí Ì$P#ÏA”ÑUã‚`öíA”ÑUåРG<UA”ÑUåë€Á*Ù
`
A”ÑUç{ˆ!û"­A”ÑUç®`°Á2A”ÑUçÿ`Í$¯/A”ÑUè®à¶
ÊA”ÑUé©`»Y%l	A”ÑUêôÑ#—4`	A”ÑUê÷@,(ùAA”ÑUëº
(èRGA”ÑUë¿à܉¸ÁA”ÑUí'	[ A”ÑUíÀÎ¹G	A”ÑUí> ÿ2­"
A”ÑUíEæYA”ÑUíÂ`Œ
‹)AA”ÑUî„ 
Q#M0"A”ÑUñ q!A”ÑUòÐ '›1A”ÑUóV`f4fÃWA”ÑUõ@†!ªùRA”ÑUõx`…CÃA”ÑU÷Z MA”ÑUùxÀBø`1A”ÑUûØ€m+;
A”ÑUüO€sÅ.µ‚A”ÑUüÍ9 ®-	
A”ÑUüæ€:"ïiA”ÑUüñÀk$A”ÑUýB
HðHA”ÑUÿ«€ñ0HA”ÑUÿÚ€V
A”ÑUÿÝ€ØRñA”ÑVg Çù6ˆA”ÑVå —*¾H	A”ÑV'@(þ,_A”ÑV° (ó.B	A”ÑV÷À

A”ÑVÁ@cƒ$dA”ÑVÇ@©,+
4A”ÑVn›¸ ‹1A”ÑV`ÝmÕA”ÑV¶ ›c2A”ÑVô Õ
µ)Ñ
A”ÑVøÀ	û Æ£ÔA”ÑV	
€t/7bA”ÑV	³—*l/äA”ÑV
˜ &"I6A”ÑV
Õ`
1*O"ó	A”ÑV„@-Q·A”ÑV³Àü¥'A”ÑVú ±è-I	A”ÑV
q`I‘
AӄV
ª`0I)!A”ÑV@0§(
A”ÑVh€
m ½(WA”ÑVl 	Ò+»1A”ÑV®`? ·A”ÑVC %3,N1A”ÑVX€XœñA”ÑVö`iîAlA”ÑVÀŽå&ñA”ÑV¥ 
Ä
ü$A”ÑVª 
-#¥A”ÑVœà
½*—7A”ÑV@€»wö
A”ÑV)`'7	òA”ÑV¸ „-é ‹6A”ÑV‡ 
#B©A”ÑV]à)2´'cA”ÑVd@	4!M-A”ÑVЀ$߯MA”ÑVZ€~!7ò;A”ÑV¯€%e	*A”ÑV	½>4A”ÑVe€X/AA”ÑVÀ¦'€2,.A”ÑV[1A”ÑV3`!&Ã#b@A”ÑVƒàþ(1ùA”ÑV·€'0’{A”ÑV³§SA”ÑVé J5gA”ÑVÿà8(jA”ÑVF`X÷A”ÑVa`…/È óA”ÑV¯`É$ò%_A”ÑVð /ëAA”ÑV ã@w#2èA”ÑV ûÀíü|ÜA”ÑV!:`À|¿KA”ÑV"I^%[(œA”ÑV"‹À	H÷"'?A”ÑV$* 
¡»'¥A”ÑV$ 
F$œ
A”ÑV%Dào©$^	A”ÑV%tà;"JA”ÑV%‚À
Š'¥$
‡A”ÑV%ûÀ”1´	A”ÑV&À‹e'±âA”ÑV'O`
`3P]A”ÑV(Àߤ5¦A”ÑV)P@Q¬,A”ÑV)e Çô4¯A”ÑV)³à¥+àeA”ÑV*yà»(1wA”ÑV*«àaP{A”ÑV+J€#$§”A”ÑV+ò€¥Ÿ%A”ÑV,-@܇3ÓÀA”ÑV,ˆà¼tA”ÑV,Õ@J&"ÀA”ÑV-C€
;º4ó
A”ÑV.U ;òÊ-A”ÑV/«àü 
éA”ÑV0€][-*A”ÑV0¹ ŒºA”ÑV1˜`
‘A”ÑV2: ·"£â:A”ÑV2? 
z$œ	A”ÑV2dáâ¸?A”ÑV3 P.þÌA”ÑV3¸ í¥1A”ÑV3ÿàÎ'½Y
A”ÑV4vÀO_A”ÑV5Ò`
Î#¢A”ÑV5ëÀü	g®	A”ÑV6Š,ÿNA”ÑV8àŸ11&ÖA”ÑV9«€	…–
õA”ÑV9ßà3*ùA”ÑV:.	n$K2§	A”ÑV:2€ò"	A”ÑV:Ô Ð$&
A”ÑV;· ;0Ù"Æ6A”ÑV;Éà²!L%ìA”ÑV;ó 
â-+¸´A”ÑV<ð€$*›æA”ÑV>@¼)DA”ÑV>¶ 	¡ý B
A”ÑV?é»#ÿ!A”ÑV?À`¬,A”ÑV?% x-N0€	A”ÑV?kÀ“YA”ÑV?
$­
A”ÑV?×`í
èA”ÑV@&@d)à3•A”ÑV@eQ	šPA”ÑV@Ì@!fwUA”ÑV@ßànú-Ü	A”ÑVA@@p#ÿ$A”ÑVB@:-wA”ÑVB-`x
LA”ÑVB@€t?m+A”ÑVCEÀ(³"ëA”ÑVCË@(Q+KA”ÑVDÐ œ+1LA”ÑVE€B¾HA”ÑVEÀàrq3LA”ÑVEø "
‚A”ÑVF´`f.ÍA”ÑVGÄ€“+ó
’A”ÑVGù€Ï'2"lA”ÑVH `›*?A”ÑVJÄ »#>=A”ÑVK´@
#„
ÇA”ÑVL!@%
¾A”ÑVLk á<c-A”ÑVMZÀ¬&,A”ÑVO=`I&L3A-A”ÑVO¸ n*Ê.U
A”ÑVOø€ÌÕ&òA”ÑVP~@,p
-A”ÑVQ	@["k0A”ÑVQ2`J>.ÃA”ÑVQQ@š*2A”ÑVQãÀ	5%!îA”ÑVST`Ïà*{A”ÑVUQ 	Ä"s)A”ÑVVÿ 	«"I	A”ÑVWÀÌ¿0A”ÑVWr@ê¢A”ÑVW¹ µ"(•A”ÑVWÉ º ·A”ÑVX2à
õEJ.A”ÑVXÛ@0%A”ÑVY ^œÊ,A”ÑVZaÀìNA”ÑVZË ©)Ã$ÈA”ÑV[=`
ã6&²A”ÑV[ô€	.@îA”ÑV\@[ã*;NA”ÑV\ð€£Ò!WA”ÑV]; 
t*Â*'A”ÑV]>@öþ_A”ÑV^à&&*@A”ÑV^k€	bþbA”ÑV^{ E…†CA”ÑV^» Ô.¹A”ÑV^¿e0÷/—	A”ÑV_ÐÀµ Ý3A”ÑV`VÉh=A”ÑV`´€X\ü7A”ÑVaK M+Ã,eTA”ÑVa‡ °“$jA”ÑVa”à
Ï"iA”ÑVbRÀ
Žð.A”ÑVbs`-!K Ú4A”ÑVc
h?:A”ÑVc} ƒ)u2/
A”ÑVcй;l
AӄVe
ÀÎ(",gA”ÑVe0 Þ&˜¹A”ÑVfàq^A”ÑVfà”'ÞÔ‘A”ÑVf[À*'ÎöA”ÑVftôq&A”ÑVf¨ ™@6	A”ÑVh[à²	¢ù	A”ÑVh… 6##1A
A”ÑVh™ ‹ø
rA”ÑViŸ`%A”ÑVj«€gÉ2ÙA”ÑVj½À˜1-,›A”ÑVjÄ@:2D u;A”ÑVk,à¢0ÎA”ÑVkc`âë’A”ÑVkº`¥3A”ÑVl¡àC')&A”ÑVl´ 	ÿ"&lA”ÑVnK@
Q…A”ÑVn¨@²A”ÑVo€%ïz
A”ÑVp 7"D ›A”ÑVpÊ
i;)?"A”ÑVpÎà	B¥ 1+A”ÑVqLàã.ÂpA”ÑVr1@
U/¹‘A”ÑVr× Î1m*ò	A”ÑVuU`
„(ZA”ÑVuà
l‚A
A”ÑVuÄ Ò2vA”ÑVv~àd¥*"‰A”ÑVwm 	!ï).
A”ÑVxä 	¹2:%5A”ÑVz 
"I,[A”ÑVz„`G1¼1A”ÑVz˜À{#ì5´	A”ÑV{Và

Á'A”ÑV{÷ 
6A”ÑV|4 j%W	•UA”ÑV|F€u.”kA”ÑV~	 ü.7yêA”ÑV~ã ˆo aA”ÑV~øÀ³ ¢!
A”ÑV€ú Ä.Ä49A”ÑV€ü d#d+Ð[A”ÑVŒ`S(ø	A”ÑVÀ5!©
?
A”ÑV‚ J4tIMA”ÑVƒIM$9$È0A”ÑVªØ€©"s’*A”ÑV¬T@ïV)¹A”ÑV¬tÀ	¥ /dA”ÑV® ‡m31A”ÑV®«€íÑ!“JA”ÑV®±
º
éA”ÑV¯àŸ!FA”ÑV°Z€
*ª®A”ÑV±&à€)v
A”ÑV²€	‰e¼DA”ÑV²`@€0A”ÑV³ŽÀ@/d ÁA”ÑV´£Àtô#'A”ÑV´Ñ 
P!˜RA”ÑVµdÀ*ûdA”ÑVµà`3GÕA”ÑVµú 
BzšA”ÑV¶q €*a1	A”ÑV¶æ`IÞA”ÑV·!€P£:A”ÑV·² ö¡ªA”ÑV·³ÀX¬2»A”ÑV¹³À'JA”ÑV»Ê2ü'
A”ÑV½,àj&o%ž
A”ÑVÀS€
W)[jA”ÑVÀ…Àwä1¿:A”ÑVÀÁ #á	A”ÑVÁNà("î0qA”ÑVÁl@ÆmóA”ÑVÁ¾@ª
•ÞA”ÑVÂë€tkA”ÑVÃ^€$4c":A”ÑVÃg^	×,A”ÑVì CÄòA”ÑVÄ´€¥Ä+šA”ÑVŘ`¢ mA”ÑVÅ¥à¡4Ä$PA”ÑVÅñ 
à‹E€A”ÑVƆ@>)l1
A”ÑVÆÛ`
d‰A”ÑVÇ€'
Øð2A”ÑVÇX€s̺DA”ÑVÈ¡@.F$A”ÑVÉ`
¶0Ê5AA”ÑVÌ4ÀF-0³A”ÑVÍ,`(,,½A”ÑVÝŽ€MêúA”ÑVÞL
·5‚$ÛeA”ÑVÞt	Ü%ÃâA”ÑVÞé`^Û0A”ÑVß¹à%0Õ%’2A”ÑVßÉà	½5)¤A”ÑVຠÔ A”ÑVàÔcVA”ÑVá`¶,,ý
A”ÑVáÒ@{6yºA”ÑVâ
 Ð
ýŒ)A”ÑVâ„à¤h4ÄA”ÑVã, +h0×A”ÑVã™à´N$#A”ÑVä§`"üA”ÑVäÛ tÏäA”ÑVäö v)+A”ÑVå µ¸-¶A”ÑVå|àõ–RA”ÑVæ3~J•¤A”ÑVæÕàrºî¾A”ÑVç(àÜ!a$²A”ÑVç„à
'†èA”ÑV甀C"
A”ÑVçõ`ø/æ#A\A”ÑVèÀ!ßXA”ÑVé, Bè¸	A”ÑWm`š!Ø31*A”ÑWàB"91
AӄWY@E
V"m?A”ÑW¾
}%DA”ÑWÜÀÐ"Í
A”ÑW™ "B	A”ÑW :)I+nA”ÑWfàø0÷)%A”ÑW˜@È4qéA”ÑWÌ`f13ÇA”ÑW€
C2£ÈA”ÑW@@Rû&ÃA”ÑWB€
”!ØA”ÑW  ¡±2A”ÑWþ±¾)H8A”ÑW5 ¢B1A”ÑWn ]Z!?A”ÑWÌ 
'•Ö	A”ÑWï j 7
žA”ÑWj@U.À+ÛOA”ÑWÀm¥*;7A”ÑW 	…öj'A”ÑWg Ž$ÈH
A”ÑW¯@Q"=,lA”ÑWöÑÒ	}A”ÑWz ¨µc
A”ÑW @Ë(LƒÜA”ÑWË`$ô	ñA”ÑWãà)ÛA”ÑW €é#"³!A”ÑW!Lê+%ÔA”ÑW#­`R3
µA”ÑW& $!%0?A”ÑW&- Ô°5¡A”ÑW&†€D
F
ìA”ÑW'¶@÷^4’
A”ÑW'ôÀ-µuA”ÑW)ûà.+Õ
A”ÑW*HÀ°Ñ)¹3A”ÑW+ìàÀ/!NA”ÑW,i&©÷A”ÑW--÷DI6A”ÑW-Î;$9šA”ÑW/D !Ö%îA”ÑW0ê
B,kK(A”ÑW1 f4i}A”ÑW2- ú A”ÑW2‘(Š19A”ÑW3`ßÏ”A”ÑW3 Ã,o÷A”ÑW3¢ Ã%j.«?A”ÑW4¯Àf Ç"9A”ÑW4´@b3˜(ÄA”ÑW5@Áˆ3	A”ÑW5ëàêä!ú"A”ÑW6@ ¯/°	A”ÑW6Ó ‚3öLA”ÑW7; /$·AA”ÑW7Œà´Æ	…;A”ÑW8‡`Š!T;=A”ÑW8à
ÖÓ:YA”ÑW;û`¢0Ó"ÕgA”ÑW<Ó 
54úwA”ÑW=þ€¦¿AA”ÑW>q0-Ã	A”ÑW>N@E ³A”ÑW>œ€×Y)q3A”ÑW@a ÆÚ)PA”ÑW@…@	í²0Ï8A”ÑW@µ@Uº~A”ÑWA8 Gþ2¬A”ÑWA<ào&ï$'	A”ÑWAe
ã$BÖA”ÑWAo ¨$kA”ÑWAË<¤%,A”ÑWB½ 1 c B	A”ÑWBð`
R6A”ÑWCŒ o'£/Ø
A”ÑWDyàž	ãLA”ÑWDÈ 
ì&|(A”ÑWDúà0u,gA”ÑWE€õ*WäA”ÑWEw€ŽªA”ÑWE¾ ï	KA”ÑWEê`"4QA”ÑWF`Š"!e&A”ÑWFê@œ&	*ƒA”ÑWG@Š/;ŸA”ÑWH4I=A”ÑWHœ`
Ï*#>A”ÑWHý@()ÐÊ?A”ÑWI§ ó%>A”ÑWJ3`º+A%JA”ÑWJ>àl+á(¡$A”ÑWJç 5Å4åA”ÑWJì ¡ÜsA”ÑWLt`˜+>+ÌA”ÑWMàŽ¼#¸5A”ÑWN`~3ž JIA”ÑWNË€6P!4A”ÑWNÛÀ
wŠXA”ÑWOj@¶ñ4Q}A”ÑWPdÀÎ$9~9A”ÑWQ0 F ÃA”ÑWQr€ç+0
b.A”ÑWQw@¼#ª´A”ÑWRƒµ&,ÕqA”ÑWR¯@
¹ò"aA”ÑWSA ð
)ðA”ÑWTC	+‚ŠBA”ÑWU|`3¹A”ÑWWÙ 4"ç+A”ÑWX&€iZ£A”ÑWX=@ïzÃkA”ÑWX«À
ÇÍA”ÑWX¬ —”)üYA”ÑWY!À‡B"vA”ÑWZ9
~)Â9A”ÑW[€˜ H'EvA”ÑW[!@	Š'(r
A”ÑW\€ˆ"9Õ	A”ÑW\ ×$$÷A”ÑW\¬à
!þ–A”ÑW]¿ s&ZA”ÑW^è`D­,Ï*A”ÑW^þ`È oHA”ÑW`L`Y&##A”ÑWa g3%Ó.A”ÑWaÉ@ä2A”ÑWe¾€*‚ÂA”ÑWfÆ€S¯=A”ÑWg`µ"ô7A”ÑWgX øÓ,§-A”ÑWg`às%™!ê	A”ÑWh»À
$
A”ÑWhï Ü,rGA”ÑWi*ßvA”ÑWiË`¸öµ(A”ÑWjcà&,	$UA”ÑWjx`)&]£A”ÑWk(€Á"*"A”ÑWkŸ•Ü	TwA”ÑWlø v}!CA”ÑWp 
4z%à1A”ÑWpü๯
Ä#A”ÑWq
  Ã?8A”ÑWrK Ì
G$MA”ÑWs¨@)-¥A”ÑWt@1fA”ÑWt( $RTwA”ÑWtM›!#ÇA”ÑWtš@LB*A”ÑWu ‰C	Ã@A”ÑWu Z}÷A”ÑWv@¤ TãQA”ÑWw|Àˆ*ýÔA”ÑWw÷`Âa5A”ÑWy€ i'ÔÞ3A”ÑWy‹ÀÔ®A”ÑWy¦ ÖE
A”ÑWy€~4-7A”ÑWyì $!Ø]A”ÑW{L@
Ϫ;A”ÑW{àÀ
¾òA”ÑW{óà1V%^$A”ÑW|Ï@	ˆ$ÂsA”ÑW}x€Å û
-
A”ÑW~ QŠ"GA”ÑWÿ 
~1ü'Õ	A”ÑW€ .ì
AGA”ÑW€o cÂÃA”ÑW€ÿ€[	­)EA”ÑW 	§&Ô{A”ÑWFà
Ç	k+»A”ÑW„@Y,¯0n%A”ÑW„, ã"2&n;A”ÑW„Y 	Ë-&A”ÑW†PÀ«V08A”ÑW†ãŸ!'=iA”ÑW†û€	mù,Å
A”ÑW‡” `+$A”ÑW‡½@¹.5
¨A”ÑW‡îé¼vA”ÑWˆÁà¨-XåA”ÑW‰› a'tE $Ò­A”ÑW¬£@+'A”ÑW­€è+Ê1/
A”ÑW®
Œ"×ýA”ÑW®G P$e2.	A”ÑW®§@nˆ×YA”ÑW®½ ‚~
A”ÑW¯ã ˜2râA”ÑW°Ÿ@/"fáA”ÑW²G@{ó*3A”ÑW³*ÀÛ-
[´A”ÑW´Í€Ñß&l
A”ÑWµe 9åA”ÑWµÁ 0|…A”ÑWµÓ€°+ˆ(átA”ÑW¶@ÿ”+¢
A”ÑW¶i ÜFA”ÑW·€ÂÚ4WA”ÑW¸ç`)
FÐA”ÑW»1€hê£FA”ÑW¼añÝ5‡A”ÑW¼„44íS$A”ÑW¼´`ÖÝ1ˆA”ÑW½ÀqcMA”ÑW½VÀ„f«A”ÑW½` œòí±A”ÑW½eàŠüÐA”ÑW¿ÉÒ‹A”ÑWÀ@ÿ$¢.MA”ÑWÀàƒÎlA”ÑWÀb`T,é©
A”ÑWÀ²`Õ#h! A”ÑWÀå˜™™ A”ÑWÁaàZ”- &A”ÑWÁÓ}-f'4A”ÑWÀ±w1lA”ÑWÃÏà1î‘A”ÑWÃß 9bÇA”ÑWÄ)@@^ÕA”ÑWÅ`²™ÿ
A”ÑWÆ]€è¶A”ÑWÆØàk*s#A”ÑWÇ'@èI
+
A”ÑWÈI@G•6A”ÑWÊc@že#Ã\A”ÑWÊe@""³A”ÑWËÂà
q0Š*kA”ÑWÌY`ð Ï,Î6A”ÑWÍF€Šˆ"ÎHA”ÑWÍÏ
}û™fA”ÑWÎ!@x£)eA”ÑWÏE ¥¥+RA”ÑWÏË`	íA”ÑWÏå€M F%>FA”ÑWÐÑ 
™
].w	A”ÑWÒ/ è"‘2—	A”ÑWÒ5€^2Œ1,A”ÑWÒqàh!ÚX0A”ÑWÒïÀ!®0zrA”ÑWÓ÷ Œq(EA”ÑWÔ€	˜-D.—A”ÑWÔàèe 3
A”ÑWÔ9`
äª!’.A”ÑWÔ€ 
^
˜A”ÑWÕ ‹2…ËA”ÑWÕAà‹IZA”ÑWÖ@çŸ(^
A”ÑWÖ:`	Ð'¸5A”ÑWÖ‡ C3QA”ÑWÖÃD2
$îA”ÑW×\à	Ê'H2"A”ÑW×zÀdDA”ÑW×Þ@å¹%	
A”ÑW×ø€
Ï5±-A”ÑWØ·`
03
‡'A”ÑWÙ
“)Æ+kA”ÑWÙ1`Í/%
A”ÑWÙU 	â"Ÿ1†A”ÑWÙ” ó}/B	A”ÑWÚ )
Þ›
A”ÑWÚÚƒ.A”ÑWÜr€
W
A”ÑWÜrÀ#
6DA”ÑWÝN€íÔA”ÑWÝn@° 64ÒA”ÑWÞæ`V/¡,«0A”ÑWß Ò/ 
A”ÑWà3à0Ú‹5A”ÑWàïÀÅ1J,>A”ÑWá@ö.\A”ÑWá”
DŠA”ÑWâMàŠ£A”ÑWâU ÷*.r
A”ÑWâð2©2âdA”ÑWãp@è*1<A”ÑWãs ¬*áWqA”ÑWä"@s%+"qA”ÑWäK`Ûõ×A”ÑWå9À£ƒ2ºA”ÑWæŽàû+>A”ÑWæ™à÷³™
A”ÑWæ¯`*;$¢2A”ÑWæ×à±+ºZ
A”ÑWé9¿ã
ªA”ÑWê@äV<	A”ÑWê˜àÙ%­bA”ÑWë°ÀÝ$D'¾	A”ÑWí
	kA”ÑWí$ ´»´A”ÑWí5`(â3U	A”ÑWíVà¯'•-E
A”ÑWíu ü(¢2'	A”ÑWí“ TÏ*ÒA”ÑWî Ç'¾¯:A”ÑWîš
¾sñA”ÑWï@€"-mA”ÑWïÉà7$°RA”ÑWñwÀ¿Ë
83A”ÑWñ–@~ã‰pA”ÑWòr¿-å
A”ÑWôSàpüA”ÑWô”`i*?A”ÑWõ* Û"e4™0A”ÑWõI€d'Ÿ%A”ÑWö˜#JA”ÑW÷»`5	Ò"ëA”ÑWø 
+!3ÒA”ÑWùàŒƒJ.A”ÑWù Ð-Ò¼/A”ÑWù†`³%ÌFA”ÑWùâ€
îž\A”ÑWý¢ V°%VA”ÑWýÄ`[*À*A”ÑWþÌà
æ/ñ A”ÑX¼àJ)êA”ÑX+`
›ù7A”ÑXl€–583A”ÑX£`È&{ÚA”ÑXô æ/ÈX9A”ÑXÿ Ý2w"*A”ÑX \†áA”ÑXl`½P A”ÑX¯ ²e÷A”ÑXè »1ÞA”ÑX	 E,B1Œ
A”ÑX	¨ ˆ1(yA”ÑX
­ ê
A”ÑXp #–	”SA”ÑX
- (P+ØA”ÑX
õÀÎ&gA”ÑX ™ž&A”ÑX†@äÊ&ÚA”ÑXH 
›YJA”ÑXz v{+ŽA”ÑX’ »*œ.¥A”ÑX³@1ï%;A”ÑXö@>ó"	A”ÑX5àwÌõ
A”ÑXbà²âA”ÑXl€ß<*Ÿ	A”ÑX–€•'Œ"#EA”ÑXÓ@&º&—A”ÑX"À	µq
C\A”ÑXK á"§$A”ÑXi`R0dA”ÑX±à	«)ÀA”ÑX²àm¥A”ÑXùÀŸ*“"A”ÑX3àE™ÍA”ÑX @³	
oA”ÑX®œx#A”ÑX¾ h
YWA”ÑX€l%S
AӄXc
Ü 7A”ÑXg ±!gh*A”ÑX®Àé2ù²sA”ÑX\ÀÙ4@
A”ÑXn@’#v('A”ÑXx€	5w¥A”ÑXª€ï ³2A”ÑXá€ÿ)Ç)^A”ÑXç +"æ'Q
A”ÑXÖ`	‘#˜
A”ÑX'`~z7UÃA”ÑX~JÀ(PA”ÑX°@°N–	A”ÑX“ Lç+?³A”ÑX×`5÷¶BA”ÑX ½`âu³$A”ÑX à ­¬'E_A”ÑX! 
¼#îs	A”ÑX"ñ@Ré.ñA”ÑX# ¥
h‰
A”ÑX#¾`0¹%׃A”ÑX%W ¥1A”ÑX%ñ@¯1ª$¨#A”ÑX&x
4%-ÌA”ÑX&£ ú!K}A”ÑX&®€(—GA”ÑX&Þ`	k+S	A”ÑX(và	$R! A”ÑX(‡ ‹-‡UA”ÑX(ŽàÓ–»A”ÑX)× Ö0O'–2A”ÑX+ð€½
I.ÚnA”ÑX,} ü',1¡A”ÑX,ËÀèÃ!
A”ÑX-@© ’
BA”ÑX- ŸèxA”ÑX.@è$( ÑA”ÑX0L€
Vû	A”ÑX0V€% yA”ÑX0²€u‰#ñ^A”ÑX2M¾
+âA”ÑX2S &
-A”ÑX3s,˜!-
A”ÑX3–`b#ƒ–A”ÑX3À
¼§£A”ÑX4I@´$åA”ÑX4›@µ#º4:A”ÑX4¶€¾.“-yA”ÑX5À¼ëA”ÑX5Aä.í¬A”ÑX5~fpÁ1A”ÑX5–`îê7éÖA”ÑX7ï@Ä3åA”ÑX8^	,jA”ÑX8W@¹"B$A”ÑX8Z 3 Þ5A”ÑX93@€,¢çA”ÑX9Æ€%·"A”ÑX:g Ò%åA”ÑX=z@´ ·
˜	A”ÑX=‚sfA”ÑX>c ›DÙA”ÑX?»ð›&ÇA”ÑXA (j
°'A”ÑXAV€¢-¬A”ÑXAg`>Þ¶A”ÑXDGàä)
A”ÑXEw€U‹'yA”ÑXF˜'O4?·A”ÑXG6Œ
A”ÑXG$`ý÷0LA”ÑXGm ¨
©+‚
A”ÑXGùÖ*\Y
AӄXI
€*_5*A”ÑXI– ½#QA”ÑXJÑà
lß1^NA”ÑXKH V!A”ÑXKJ`
<EA”ÑXKz (hA”ÑXLœ€\
n(dA”ÑXLº@
Z)3IA”ÑXLÖ /!A”ÑXM6Àl&î!A”ÑXMÕ w#>&ªA”ÑXN`
!(î
A”ÑXN•€û¸
7A”ÑXOjÀ™1:ÿA”ÑXQ`Ã
RéA”ÑXQ5¬
	A”ÑXQL¿ŽA
A”ÑXR/À‰"°ÜA”ÑXRD€-#ÙA”ÑXRvÀÄ#Ò&‹,A”ÑXRê`
î.A”ÑXTºy ;A”ÑXTâ@E3rA”ÑXU ð 7nA”ÑXU“`!.åA”ÑXVÏÀl/1'
A”ÑXXÁdüÃA”ÑXZ™€P"4#A”ÑX[ w%. A”ÑX[¦À¿"õ0A”ÑX\(à1!9UA”ÑX\{@8*£1ÅA”ÑX]5`Ä2¾è?A”ÑX]ñÀž n+oA”ÑX^Š€µ4b#¦A”ÑX^ÂÀ
¾3
2A”ÑX^Ø`°2Ã%ÏA”ÑX_h@	¯&	„LA”ÑX_Î@t5ÁA”ÑX`~@Å
Â¥A”ÑX`ˆÐ)Ö!¦A”ÑX`–@e{*â
A”ÑXbAÀò2)SA”ÑXb`v)Ø1&>#u$A”ÑXo®à£íA”ÑXpÁýì)ˆA”ÑXtY	z!Ó!:A”ÑXu6@
$ÏvA”ÑXu¼àq_A”ÑXvàÿøÚ1A”ÑXw= ‹	Z±ÔA”ÑXwµ Ø'Y$v
A”ÑXx=€.kA”ÑXylÀ5˜Æ-A”ÑXyø@|YèA”ÑXz`/q$,A”ÑXz À
¿*Î
A”ÑXz¡à	u%¬dA”ÑXzÍ 5¸ oA”ÑXzúŽT^A”ÑX|c é EA”ÑX|‡€f¤2¿A”ÑX}ä`$3Ê	A”ÑX~
 k"’#<
A”ÑX~ž€õa,@ZA”ÑX~¼@«,˜³A”ÑX~È ¼fyA”ÑX~ìÀNd2pA”ÑX"@¯~ ŸA”ÑX€Àà=@ŠA”ÑXàâØA”ÑXd &™A”ÑX‚À‚
¯*!A”ÑX‚†	œhAA”ÑXƒÇ =xbjA”ÑXƒÕÀtô .A”ÑXƒÛÀ*%{4A”ÑXƒë J#H(ŠA”ÑX„@	*P-ÏA”ÑX„f@ä)â
A”ÑX„Û`ÈŸÖA”ÑX…€%$"FA”ÑX…`ÙA”ÑX… ±9+~A”ÑX†À®2"µA”ÑXˆ†@ø4‹ [A”ÑX‰o`z2÷
A”ÑXŠl€íA”ÑX‹@S&vÙA”ÑX‹©)žfA”ÑXŒ 	B}üA”ÑXŒ+`ÛÌÑ A”ÑXŒlàb?70A”ÑXŒ¼ N4'LŒA”ÑXŽl`Ì3PTA”ÑXŽƒ`*+{A”ÑXŽñ€˜%þ^A”ÑXŽùà
Ú"A”ÑX@Ã4^"A”ÑX ~ÙA”ÑX$ ‚Ž*A”ÑX-@÷!”Æ7A”ÑX¦ààºþ,A”ÑX‘ ÇÜ#¦/A”ÑX‘ 
?	`'bA”ÑX’8àÑ2ÎA”ÑX’Ú`<.dÜA”ÑX“{àBF)BA”ÑX“ `	a+ò"A”ÑX”½”'FA”ÑX”’à
Š"HA”ÑX”ܶ)K>A”ÑX•)€û
Í
"	A”ÑX– š*	ÐFA”ÑX– `O
&ßA”ÑX–$ ÷x,ð#A”ÑX˜@ûûeOA”ÑXš}àr+þ!|A”ÑXšàS,tO	A”ÑX›ø€?3

A”ÑXÏ€õ-VAA”ÑXžàæ’3IKA”ÑXž( ]"}.CA”ÑXŸX ;7{	A”ÑXŸr€Šc05,A”ÑX X`<·/Ý
A”ÑX¡€Ê`
>BA”ÑX¡— Ë…6u-A”ÑX£AÀ-e—
A”ÑX£[€’ý_KA”ÑX£‚ ‡!Hn1A”ÑX£Š`Üjƒ
A”ÑX¥-@/!ÃtXA”ÑX¥I€Ò,•é3A”ÑX¥V@úü~A”ÑX¥c€áO“A”ÑX¥† Å%ª%å5A”ÑX¥à€
R4úA”ÑX§ö D*7¸ÎA”ÑX¨µ@\1Õ„A”ÑXª,¹A”ÑX­aÀ-¼YA”ÑX­iµ=-
A”ÑX®Ç Èç2zA”ÑX¯#À­"âA”ÑX¯ƒ`Ó+ÅñA”ÑX±"à;b	×	A”ÑX±H T~ÚA”ÑX´1À>"ä3*A”ÑX´Jàn)­$¸A”ÑX´œ
¿Â‹A”ÑX´Ä Á¼
‰
A”ÑXµƒ ’ô,=4A”ÑXµ£@ÉŽ€
A”ÑXµÉ ©¹A”ÑX¶ Ä¥/$A”ÑX¶` *:Û	A”ÑXºÚàÖ¸1€A”ÑX»3 ..WsA”ÑX»¬b1è A”ÑX»ïà-u c	A”ÑX¼[ÀÝ¡ÊA”ÑX¼gŒ"&û
A”ÑX¼ôà	ýÍ.ÂA”ÑX½@¤£
úA”ÑX½ÂÀŒ'Ž+”àA”ÑXŹ =í=CA”ÑXÇÀ`»èA”ÑXÇø ”&)íA”ÑXÉ&À: Ü73¬A”ÑXÊT€t«*æHA”ÑXʪà	uNËA”ÑXÊÊ Q*•"nA”ÑXË`C¢
A”ÑXÌ8 +
ñÿAA”ÑXÌD@`+"A”ÑX̨`\0$"+A”ÑXÌÜ Ð)þA”ÑXÍ &·WA”ÑXÎî`Ÿ"ç!A”ÑXÏG à$q4'A”ÑXÐ/`å0§.n	A”ÑXЪD,±A”ÑXÑâ`A(¾A”ÑXÒ
€	b¡
A”ÑXÔ‡€
'/‰A”ÑXÖ€:*qA”ÑXÖh _5z%?>A”ÑXÖw 	èh"A”ÑX×)`
"#³'ÃNA”ÑXØ	#Ó..A”ÑXØ7 7‹j	A”ÑXØ_@'Ð-KA”ÑXØÖ`q'<™A”ÑXØðÀ”)àþA”ÑXÙ-À!@A”ÑXÙA@O%å-«A”ÑXÚ Lf‡ÏA”ÑXÚaŒ&˜lA”ÑXÚÙq(|<A”ÑXÛ(‘¸&+A”ÑXÛ‹`j6«ÁA”ÑXÛ±€	…ÒA”ÑXܨ ->,A”ÑXÜï@'L$NA”ÑXÜøÀ6,“.§?A”ÑXÝP`i.ŸÂ
A”ÑXݵ ä„1äA”ÑXÝñ€1%lA”ÑXÞn`˜ðYA”ÑXÞ¦À)!•#ëA”ÑXߞྨ%>A”ÑXß° Á§A”ÑXßÓ€’2üA”ÑXßéÀì!_A”ÑXàC@Ür€A”ÑXàf Ö ¥61A”ÑXá¤À àw"A”ÑXã*`:–‹&A”ÑXãV ¥
'ÃjA”ÑXã©€ž#_r
A”ÑXäà;2&#€A”ÑXä #2m	A”ÑXä6 ô
ÍA”ÑXä: s
®ìA”ÑXäZ@zê#A”ÑXä@¤%ÐA”ÑXå#€##9A”ÑXåÁ€a6ýA”ÑXåú`³3¦A”ÑXç  7=1|A”ÑXè@:Ž$A”ÑXèvà3Ý"A”ÑXèÉ€(-Û/ÓA”ÑXêoàÀ"CcA”ÑXêÄà#&,3¡A”ÑXêÝà'³2e
A”ÑXëÀRy;A”ÑXìnÀa';A”ÑXí• —ÅA”ÑXíïà_«3ÙA”ÑXî* è «=A”ÑXïf „,JA”ÑXïÑ€é+]A”ÑXðÀµ†AA”ÑXðµ€´Û$¡A”ÑXñ4@QA”ÑXó> ûž&A”ÑXó¬`ì
*	A”ÑXôÀ	—‘
A”ÑXöÀó"ƒ7A”ÑXöNÀ… HA”ÑXöi`/6€JZA”ÑXö’`
 8Þ?A”ÑX÷a (î!A”ÑX÷Öà2#!‰7A”ÑXù‘Àü)î%A”ÑXùö
¸*"ª	A”ÑXûÔ N%A”ÑXþ Ö
&A”ÑXþ6 ü0;'×A”ÑXþP€ép
A”ÑXÿ@õÚ30	A”ÑYB	#^)A”ÑYë!DA”ÑY ‘¸OA”ÑY—@}¨
¹A”ÑY× ¿´,{A”ÑY<àµ
c0A”ÑYL"XA”ÑY	D`µQ H
A”ÑY	zÀ2}RA”ÑY
= k1%6A”ÑY
Ó€
M\FA”ÑYGÞ]èeA”ÑYè`T(H
AӄY
n`9ÓA”ÑY
Ý ×
,/ A”ÑY`Ã+()1A”ÑYà
.&£A”ÑYpð%$'A”ÑY‡ ¾$Û7¼A”ÑY÷@z
 'pTA”ÑY–À!#1QA”ÑY9@§+šA”ÑY‰@•“iA”ÑYÅ`ƒ$¿=A”ÑYóਠÊA”ÑY
ô)'3eA”ÑYö@7$Á*AA”ÑY{€2+i&bA”ÑYâ@
þ%™%A”ÑY=w)
ÞA”ÑY¶ Í$ê!ì8A”ÑYíÃ3A”ÑY[@ù:
?A”ÑYÊàº+)ÂA”ÑYG@BEPA”ÑY)`í8A”ÑYFàÕ¢+’A”ÑYª`|
0 0QA”ÑY,€ )1A”ÑYR 
4
é,ó
A”ÑYº@0'¯âA”ÑYÅ ]4	)ûA”ÑYÒ@¨®‘A”ÑY" ª3W
A”ÑY"™`S%¢ A”ÑY#`m‡A”ÑY$:Àu*EA”ÑY$Èà	€$»2A”ÑY$Í 9!•A”ÑY%¬ %„	›A”ÑY%Ïà´È75A”ÑY%ç`)zMA”ÑY&=€ÿ!/'èA”ÑY&è 	ј2—&A”ÑY&õ c)45qA”ÑY' +sø
A”ÑY' Á$† »
AӄY'f
t›-°A”ÑY(ÀÇ2˜'A”ÑY)`	H%*!w¿A”ÑY)! 
	W&#A”ÑY)nà´„]ÏA”ÑY*­ …=aA”ÑY,€€ò11-oA”ÑY-Q@!VÁ+A”ÑY-ÿ@ !(
A”ÑY/¤à
…+,¿1A”ÑY1f mÂA”ÑY1 ¹	þ[A”ÑY1Ü`èA”ÑY2“@24¸
AӄY3
 2 A”ÑY3' ”~*A”ÑY3¹ 	
" 	A”ÑY4.@Ô©÷A”ÑY4¡À
7¸^
A”ÑY6œ@
¯I!½A”ÑY7~ 
x¨6ÙcA”ÑY7‰wôA”ÑY7­`ó
É,Î
A”ÑY8·€ŸA”ÑY9¢ .+ôJA”ÑY:»@O![,A”ÑY;`<ÿ'#A”ÑY;xàgÛRA”ÑY;Š÷Î
A”ÑY;¬€¹s#‹A”ÑY<¯@¼!S·A”ÑY<ÐÀr$™6PA”ÑY=y )#rA”ÑY=€ Ð8,DA”ÑY=ê Û0v+QA”ÑY>ôà7-)@A”ÑY?B 	ˆ#ž#A”ÑY?t€¼î)A”ÑY?ì€lá!¢A”ÑY@þ@
hÁ&8A”ÑYAZ@À-ðA”ÑYC0Àh+rA”ÑYC@þÊ8A”ÑYC…çŽÛ`A”ÑYD C!f‘-A”ÑYDÁ`,%¥FA”ÑYEJàâ(Ý1
A”ÑYF ž(tŽA”ÑYFYÀt`A”ÑYF¹ ¢±½QA”ÑYF퀛ä!ÅIA”ÑYG€I’)A”ÑYHh#
,­A”ÑYHÛ€B1²(ÕA”ÑYI~¾4ÍA”ÑYI`s•#A”ÑYI¯ #,ˆA”ÑYJó`Wï	A”ÑYK]€	Ù2A”ÑYLs`N	yA”ÑYM„ ðþ,A”ÑYP`Z%·É)A”ÑYQPà:"1,A”ÑYQ“ 7Þ'A”ÑYR·@(/?"-A”ÑYRé /ëé)A”ÑYS`ðó!¨LA”ÑYSÀ Ý&n=
A”ÑYT°@e;5lËA”ÑY™ O'7A”ÑY™ éµA”ÑY™ì ÃÍA”ÑYšˆQi+OA”ÑY›%‰yA”ÑY›@Y'-–vA”ÑY›Ú`µ`/dA”ÑYP`XB/A”ÑY^€Í4-A”ÑYž rÜÃ.A”ÑYžøà//-šA”ÑYŸI€±½¸A”ÑYŸ•€ô6ç#Á
A”ÑY úàDêA”ÑY¡Aà‰)×3	A”ÑY¡†àz$Î6ƒ6A”ÑY¡Ý tÞ
A”ÑY¡îaGA”ÑY¢K ÂË&A”ÑY£Ê$ãQA”ÑY£ÿ ¾#ƒA”ÑY¤€ÓA”ÑY¥)ÀžºA”ÑY¥;/‚!ÈA”ÑY¥‰`
z¯iwA”ÑY¦y µ.².3
A”ÑY¦Ÿ@ù.A.øA”ÑY¦¡€–T$v-A”ÑY¦ª@
s²%
A”ÑY§ 
!c 
A”ÑY§Àº
j(}
A”ÑY§9æ&/
A”ÑY§d€+4é+ª A”ÑY¨®€ú ¼ÂA”ÑY©1`²("«,A”ÑY©‹ î+ŠA”ÑYª;@R&É5OA”ÑYªi€¡%HÝA”ÑY«d€2	óg
A”ÑY¬QÀä+øéA”ÑY¬³`—
ô%¶HA”ÑY¬ò P\ E
A”ÑY®`”°+ÆA”ÑY¯´ â©!ÌEA”ÑY¯Þà¢ÔªA”ÑY°¢à}ÃÂ]A”ÑY±þ`Â
-(A”ÑY²~àB(A”ÑY³u ßË/A”ÑY´
 ps(SA”ÑY´, 
“@-Æ>A”ÑY´Ü@3ØMA”ÑYµå€^íŠA”ÑY¶XÀ3)9¿A”ÑY· ‡%ï!A”ÑY·±:Å$Í	A”ÑY¸Î`ã3â?A”ÑY¸ûàS/	-RA”ÑY¹  ÷%.5QA”ÑY¹’‰6K(ËA”ÑY¹ý v$öA”ÑY½`“%A¦5A”ÑY¾"àH A”ÑY¿= ™%!µ	A”ÑYÀ
3#D(A”ÑYà  	ì#øA”ÑYÃåÀ
k*ÚA”ÑYÃó Û
Ñ,(A”ÑYÄ5€ñIŽA”ÑYÄâ@rÎÅ A”ÑYÄëÀè »°
A”ÑYÆ) !0¼RA”ÑYÆV Z	'A”ÑYÆÆ@©-2)A”ÑYÇ`t1ârA”ÑYÇ Á.|àA”ÑYǹÀ
¬Ì7:A”ÑYȳ +!
-A”ÑYÈ÷Ú
ú/4A”ÑYÈþ`QîaA”ÑYÉ.@؈A”ÑYÉV¨a6cA”ÑYÊJ 2*ö¡	A”ÑYÊç§'Ò´A”ÑY˵ ËÓA”ÑYÌ ¿y*:A”ÑY̱ 
!
Å/¯
AӄY폈?
/.A”ÑYÌê þ5*Ñ:A”ÑYÍm€~)’!kA”ÑY̓â'ràA”ÑYÍ„ «dªA”ÑYÍ»€Û'HiA”ÑYÎK@aø)üLA”ÑYÏ#`	q d^A”ÑYÏe Ú")lA”ÑYω 5î A”ÑYÏ“ êe.'A”ÑY϶àÁ_$œA”ÑYÑs «,ÓA”ÑYÒd ô
,KA”ÑYÓðÙ%mA”ÑYÓaà

Q!¶A”ÑYÔPàB&íÌA”ÑYÔ`f$Ú¢A”ÑYÕC@ÒLcA”ÑYÕ²¦4÷A”ÑYÖ[`ÆA”ÑYÖeÀŠ<Ð
A”ÑYÖÞ€Ø+$
ØA”ÑYÖá }Z8/A”ÑYØù@Ó3;‰0A”ÑYÙ%€).\"à‘A”ÑYÙ{€	A”ÑYÚ Â
ò
„A”ÑYÚMÀãü2A”ÑYÜ5€û)jA”ÑYÝ<`	â;"×A”ÑYÞQà
µu,mlA”ÑYÞÕ&‘5»A”ÑYßB€UBý6A”ÑY߸@Ñ"دA”ÑYà@Ç%$ÚA”ÑYá+€›ÄA”ÑYá\ ·"½ß!A”ÑYã: Y%¡A”ÑYä¯t)ƒòA”ÑYäÀ³Ã#F/A”ÑYäÅÀ
>*AA”ÑYç#`o.œ=qA”ÑYç- þ )ÀA”ÑYçz 	H—³A”ÑYèM&•@-A”ÑYè} „-ð	A”ÑYê#à&&]A”ÑYê… ¤%¡ÐA”ÑYê¯àº÷ª
A”ÑYêÅ!Ü)–	A”ÑYë 	0,¢A”ÑYìàßý,ŠæA”ÑYì
Þ/0´A”ÑYì)$ `*g%A”ÑYîÀï8"oA”ÑYîÇ 
w/&Ù:A”ÑYïs ¬3!x)A”ÑY3*«
YA”ÑYï¾`Õ"±,Õ2A”ÑYðÄ@…
øgA”ÑYðüà¶	€	A”ÑYñbà
“4A”ÑYñl $&ÆH
A”ÑYñ«Õ!¼A”ÑYñÊ hßA”ÑYñØh ­&¨
A”ÑYñïà
ì†x"A”ÑYò@A"¨
â=A”ÑYó瀚£-A”ÑYõÍ@† –A”ÑYö16
á,]UA”ÑYöSÀï$r(îŽA”ÑYøH 	ƒ)DA”ÑYø`1î HuA”ÑYù^ %§*NA”ÑYùæ	âÍ8KA”ÑYù÷À	A”ÑYúË@—ÄËA”ÑYûz€_u$A”ÑYû”À	sñ	A”ÑYü‚àg$ÆA”ÑYýKÏX"¸A”ÑYýTÀ
V‡	A”ÑYþˆàX±/)A”ÑYþâÀ×g/…A”ÑYÿƒÀ0)Æ#¦
A”ÑYÿÉ€—'ôA”ÑYÿÿÀ
ü6*%A”ÑZS€­
^A”ÑZJ‡*A”ÑZgÀ
S„ødA”ÑZ`Àˆ*JW
A”ÑZÁ@û`xA”ÑZo€óÝA”ÑZUÀU5w!),A”ÑZœ »3A”ÑZ ?e2ë
A”ÑZ›À€á-A”ÑZ	W`£æ BA”ÑZ	Š€Ú!$UA”ÑZ	¬€	C)õIA”ÑZ
™€
V°A”ÑZ
Ä@9#Å4¶A”ÑZ`@O4Ø
AӄZiێ
4“A”ÑZé@›$c2
A”ÑZôl&v+‚A”ÑZ
ê@‰#VRA”ÑZþ
"6™÷A”ÑZ ´,@áA”ÑZ"tè
u4A”ÑZb`n„*dµA”ÑZ˜@	7+ëƒA”ÑZ¸`¯ù!hA”ÑZc€5 J åA”ÑZ˜À¸!ñA”ÑZ0
í##¶A”ÑZv`Á L%3DA”ÑZ
@Æ4ï9
A”ÑZÀš )NA”ÑZ,À¥!v×A”ÑZ• "9§¬A”ÑZ®ÀY3%SA”ÑZ"`E •èA”ÑZ¸[*«
A”ÑZš·#†#ìA”ÑZøHG&A”ÑZ; i!–)0	A”ÑZ\à	–½´äA”ÑZg Kì7îA”ÑZx€(öÍA”ÑZ}€Æ$:.c!A”ÑZÆ­(¤ß}A”ÑZí ó1J.‘	A”ÑZÝÀÜ/Ž2Õ-A”ÑZ€¯7	™A”ÑZ: /NÇ
A”ÑZœàè.®	A”ÑZÎ »"ëíA”ÑZO3¶øA”ÑZ®Â+
4V A”ÑZé`$ÊO!A”ÑZú€Én0A”ÑZ€ÉIaA”ÑZ 
àSs1¨A”ÑZ SÀD$9'I9A”ÑZ"à
y,h+A”ÑZ"ÀÀ)Á.JiA”ÑZ"§@q%ûB2A”ÑZ"ÍàÄ'L	’A”ÑZ#Cà HÄA”ÑZ#Ô`÷!#½FA”ÑZ$
m5¶A”ÑZ&Ô ‚CŸ	A”ÑZ(äóq39A”ÑZ)yæ*	-A”ÑZ)Þ@3•lA”ÑZ*R€C
f!A”ÑZ*º€C
î#p7A”ÑZ+` 
É
[A”ÑZ+{À¼»"l\A”ÑZ+© ÖÖ1ZtA”ÑZ,ý òøA”ÑZ-@Ï*¨—A”ÑZ-g éõ#e
A”ÑZ.˜
Š	1)¢A”ÑZ/Z 
ÃHÅA”ÑZ1QÀs  7A”ÑZ5| Z*Ÿ1¿	A”ÑZ5øà›&¥A”ÑZ6àLg
|A”ÑZ6‹àIÑ)­A”ÑZ6›À
d0DA”ÑZ7” Ñ
1A”ÑZ7í`&×!¶A”ÑZ8!Û 89eŠA”ÑZ8OÀþ9A”ÑZ8– ®*¦à1A”ÑZ8è@1	9%²A”ÑZ9`âc+l8A”ÑZ9V@â0Ó¶A”ÑZ9ö(~A”ÑZ:Àc$¢+©A”ÑZ;V 2#¼>FA”ÑZ;’ !“…A”ÑZÀ.Ü+VA”ÑZA	 Ñ2K!LA”ÑZAk`ù*ä´%A”ÑZA«€#Ì
ÉA”ÑZB¼à+(. A”ÑZCï@1#A”ÑZDþà!H)«A”ÑZG/`ªÎ\A”ÑZGª@)^|A”ÑZH.`ØÚ)/aA”ÑZH’à	ý'éèA”ÑZH•À<2+ÂA”ÑZH÷àG)66{A”ÑZI,à:"ä1õA”ÑZI“ üÅ–A”ÑZK“ E-,ÅA”ÑZKÎ`+8#Ò
A”ÑZLF ê'A”ÑZLNàí¿A”ÑZN! ö&O#¤A”ÑZN[@nÈåA”ÑZN ¦ }7—A”ÑZQF$”+ÖA”ÑZR¥`	4ÁA”ÑZRø€-$3óA”ÑZS_`Å"Ü5UA”ÑZS£ 8/.2ÖƒA”ÑZTl€Þ*/~‚A”ÑZUà
3~¿ A”ÑZV:@u7/sfA”ÑZVFà¬à1OA”ÑZVXà‰&A–	A”ÑZWU€7™A”ÑZW»@Ö	E#A”ÑZWÃÀ‰Ÿ$ú
A”ÑZWä $¥fA”ÑZX `¬
ÕØA”ÑZX3 +9ÅBA”ÑZXÕ€î&ŠA”ÑZY³€r#1/ðA”ÑZYÁ€_	XA”ÑZYÅ€¹L2[A”ÑZZ* j.2&A”ÑZ[b Þƒ-—8A”ÑZ[k/ÍÏ4A”ÑZ[  ¦-Û
UAӄZ\ʊ#d
A”ÑZ\”À
=#^
A”ÑZ\²Àj
Ý%j
A”ÑZ]M ã2$LA”ÑZ]xÀz
œ>A”ÑZ]Ê€ê(&„A”ÑZ]Êà
Ò&Ç;A”ÑZ]Ö Ý!ê+ÿ A”ÑZ^ F'¼(xfA”ÑZ_Þ€	ÖÃ/§
A”ÑZ`iàY3z*[A”ÑZaf`1/ŒA”ÑZa¡ R¹Ò­A”ÑZb#@üzärA”ÑZbÍ@DKWA”ÑZcoà¥4L'ŽA”ÑZcƒ	¤M8™:A”ÑZd'`Ø™SA”ÑZde@Ê]A”ÑZdh )A”ÑZdž@þ
»(ÊRA”ÑZdÓ {$'
A”ÑZdû
¸#¥œ
A”ÑZe« Q*F*‰
A”ÑZf)àžÐ,v}A”ÑZfßàI*«
A”ÑZh€ó%S¸"A”ÑZh– R S'A”ÑZi ¡4&­	A”ÑZiÇ b!iÄdA”ÑZjtB*P#A”ÑZjC€	y#ùˆA”ÑZjZàø$·8A”ÑZjÅ€À$C6;+A”ÑZk ¾ÎA”ÑZk* Ê(»
A”ÑZkHà+ô#œ	A”ÑZk¢à;¹»æA”ÑZl< „"A”ÑZmö eÓ%>A”ÑZo á53˜A”ÑZoÀä01
A”ÑZoâ Øu,áA”ÑZpH€ž&	ÈA”ÑZp`€5'fGA”ÑZq9@íPHA”ÑZquà*m4S
A”ÑZr׎3í&A”ÑZsd`
„/áJ	A”ÑZt ñËDA”ÑZuxÀV$Q$6A”ÑZv?€›)Ó÷VA”ÑZvKàTÉ¿A”ÑZv_†“#¶A”ÑZvË 
½Œ
A”ÑZw7@úž/`A”ÑZxD@¥+Ô;A”ÑZy% Ñ T,cA”ÑZyÊ`B//CA”ÑZyæ â0«+‘A”ÑZz-@Ê!Q*ËA”ÑZ{F 	5A4A”ÑZ|I4
1˜A”ÑZ|\cº+oA”ÑZ|î`	•8²!·A”ÑZ}R ˜)N!èA”ÑZ}lÀ
YICA”ÑZ}v`.sÑA”ÑZ~™ ›	O, A”ÑZ7`	°$`,znA”ÑZ­à$ü¡¡A”ÑZ·ÀÛQÃA”ÑZçÀ¤!ædA”ÑZ€SÀöï3A”ÑZ€§€sй	A”ÑZ‚ÚàÈhA”ÑZ„k€á5"W?A”ÑZ„Ï AÍ%,A”ÑZ„çÀŒ*ú/mA”ÑZ…fŸ' A”ÑZ…`0þ…
A”ÑZ…Â@×$"ÓA”ÑZ†E€
-
Œ%'$A”ÑZ†nÀ
[AwA”ÑZ‡ #ú#Ž5A”ÑZ‡qà
…+Œ'þA”ÑZˆÀ
ÑwA”ÑZŠî€¨šA”ÑZ‹ð@ó'Ä04A”ÑZŒ ÞÞéA”ÑZŒí@Êì'~A”ÑZ¯@Ž^#L
A”ÑZa€
pà8¼A”ÑZ¢à*$âA”ÑZÆ`J#(&òA”ÑZNàÒA”ÑZ”; 3$±+÷A”ÑZ”\ÀSß1ŠA”ÑZ–—`Z9?gA”ÑZ—ZÀ¡/‚%A”ÑZ˜ {›ãA”ÑZ˜]À(Ï(ÔA”ÑZ™·@	È®)
A”ÑZšàD¸¡A”ÑZš™à>"ý0A”ÑZ›ª@_•¼A”ÑZœ_À	+O¹A”ÑZœ‰/˜+ñ	A”ÑZœ¶ Â
Ø)sA”ÑZœí€ "(œ	A”ÑZ†€%
ZA”ÑZÃàš/ç>A”ÑZž*2¬¦A”ÑZŸ® îLVA”ÑZ¡Ë€É½n-A”ÑZ¢ ¹)ø#ÓA”ÑZ¢p€h&&A”ÑZ¢½ i	é)¦9A”ÑZ¢ãÚ'A”ÑZ£U A-¸A”ÑZ£…À³ß%y	A”ÑZ£ù`ß¼bOA”ÑZ¤UÀõ3´PA”ÑZ¤©à‰&Á$œA”ÑZ¥-
5UA”ÑZ¥´ ™$×
A”ÑZ§‰@,Ë@
A”ÑZ¨F@'*ë
A”ÑZ¨H`E4N,.A”ÑZ¨ƒ@fs&×A”ÑZ¨‘€ô&ÿA”ÑZ©] ´5Ø#
A”ÑZ©j ,%0<
A”ÑZª# 
p.b1A”ÑZ«EÀŽ•)ÄA”ÑZ¬ªà	ç"â/A”ÑZ¬Ö@Ó%¼0QA”ÑZ­ !Â!9}A”ÑZ®u@G‹#|
A”ÑZ®Š 
y)b%A”ÑZ®£@ФlA”ÑZ®ñ€Û!7iA”ÑZ°ZS/&)A”ÑZ± è0=2ó&A”ÑZ²+@"Mg#A”ÑZ²àV'‘ÿA”ÑZ²å€
àÝA”ÑZ³_à¤
A”ÑZ³z€I7A”ÑZ³¤È'î*L	A”ÑZµ9@	(‚ _A”ÑZ¶?À^1EA”ÑZ¸Œ 6Šh!A”ÑZ¹Ù`-,ÒÊ=A”ÑZ¹ù Å#ÿ'yA”ÑZº_ 
Ø7eëA”ÑZº€"­JA”ÑZº’ 
'±7?A”ÑZ»cÀ>
¢$¥A”ÑZ»Ë€
—0(ÆA”ÑZ¼ƒ`‡t8ïA”ÑZ½)À¯
èA”ÑZ½²@Î- 	A”ÑZ½åÀs™›A”ÑZ¾V€h„A”ÑZ¿tiA”ÑZ¿Ëà•`+vA”ÑZÁ7 	³% þèA”ÑZÁ…à=9;~	A”ÑZÁ“ ”+$ÎA”ÑZÁ¢ ß³!ü“A”ÑZÁð « odA”ÑZ‚ÀÜ!\Â
A”ÑZÂ…@Â'y,¨A”ÑZ¬àäGaA”ÑZÃïàÑæ*r
A”ÑZÄnÀ	î'!
	A”ÑZÄÍÀï1ºuA”ÑZÄ× ÿ0 Y
A”ÑZÆ*` ë3¢EA”ÑZƪ`	F
A”ÑZÈEàcfitsio/iter_image.c0000644000225700000360000000600413246025103014251 0ustar  cagordonlhea#include 
#include 
#include 
#include "fitsio.h"

/*
  This program illustrates how to use the CFITSIO iterator function.
  It reads and modifies the input 'iter_image.fit' image file by setting
  all the pixel values to zero (DESTROYING THE ORIGINAL IMAGE!!!)
*/
main()
{
    extern zero_image(); /* external work function is passed to the iterator */
    fitsfile *fptr;
    iteratorCol cols[3];  /* structure used by the iterator function */
    int n_cols;
    long rows_per_loop, offset;

    int status, nkeys, keypos, hdutype, ii, jj;
    char filename[]  = "iter_image.fit";     /* name of rate FITS file */

    status = 0; 

    fits_open_file(&fptr, filename, READWRITE, &status); /* open file */


    n_cols = 1;

    /* define input column structure members for the iterator function */
    fits_iter_set_file(&cols[0], fptr);
    fits_iter_set_iotype(&cols[0], InputOutputCol);
    fits_iter_set_datatype(&cols[0], 0);

    rows_per_loop = 0;  /* use default optimum number of rows */
    offset = 0;         /* process all the rows */

    /* apply the rate function to each row of the table */
    printf("Calling iterator function...%d\n", status);

    fits_iterate_data(n_cols, cols, offset, rows_per_loop,
                      zero_image, 0L, &status);

    fits_close_file(fptr, &status);      /* all done */

    if (status)
        fits_report_error(stderr, status);  /* print out error messages */

    return(status);
}
/*--------------------------------------------------------------------------*/
int zero_image(long totalrows, long offset, long firstrow, long nrows,
             int ncols, iteratorCol *cols, void *user_strct ) 

/*
   Sample iterator function that calculates the output flux 'rate' column
   by dividing the input 'counts' by the 'time' column.
   It also applies a constant deadtime correction factor if the 'deadtime'
   keyword exists.  Finally, this creates or updates the 'LIVETIME'
   keyword with the sum of all the individual integration times.
*/
{
    int ii, status = 0;

    /* declare variables static to preserve their values between calls */
    static int *counts;

    /*--------------------------------------------------------*/
    /*  Initialization procedures: execute on the first call  */
    /*--------------------------------------------------------*/
    if (firstrow == 1)
    {
       if (ncols != 1)
           return(-1);  /* number of columns incorrect */

       /* assign the input pointers to the appropriate arrays and null ptrs*/
       counts       = (int *)  fits_iter_get_array(&cols[0]);
    }

    /*--------------------------------------------*/
    /*  Main loop: process all the rows of data */
    /*--------------------------------------------*/

    /*  NOTE: 1st element of array is the null pixel value!  */
    /*  Loop from 1 to nrows, not 0 to nrows - 1.  */

    for (ii = 1; ii <= nrows; ii++)
    {
       counts[ii] = 1.;
    }
    printf("firstrows, nrows = %d %d\n", firstrow, nrows);
    
    return(0);  /* return successful status */
}
cfitsio/iter_var.c0000644000225700000360000000636713246025103013773 0ustar  cagordonlhea#include 
#include 
#include 
#include "fitsio.h"

/*
  This program illustrates how to use the CFITSIO iterator function.
  It reads and modifies the input 'iter_a.fit' file by computing a
  value for the 'rate' column as a function of the values in the other
  'counts' and 'time' columns.
*/
main()
{
    extern flux_rate(); /* external work function is passed to the iterator */
    fitsfile *fptr;
    iteratorCol cols[3];  /* structure used by the iterator function */
    int n_cols;
    long rows_per_loop, offset;

    int status, nkeys, keypos, hdutype, ii, jj;
    char filename[]  = "vari.fits";     /* name of rate FITS file */

    status = 0; 

    fits_open_file(&fptr, filename, READWRITE, &status); /* open file */

    /* move to the desired binary table extension */
    if (fits_movnam_hdu(fptr, BINARY_TBL, "COMPRESSED_IMAGE", 0, &status) )
        fits_report_error(stderr, status);    /* print out error messages */

    n_cols  = 1;   /* number of columns */

    /* define input column structure members for the iterator function */
    fits_iter_set_by_name(&cols[0], fptr, "COMPRESSED_DATA", 0,  InputCol);

    rows_per_loop = 0;  /* use default optimum number of rows */
    offset = 0;         /* process all the rows */

    /* apply the rate function to each row of the table */
    printf("Calling iterator function...%d\n", status);

    fits_iterate_data(n_cols, cols, offset, rows_per_loop,
                      flux_rate, 0L, &status);

    fits_close_file(fptr, &status);      /* all done */

    if (status)
        fits_report_error(stderr, status);  /* print out error messages */

    return(status);
}
/*--------------------------------------------------------------------------*/
int flux_rate(long totalrows, long offset, long firstrow, long nrows,
             int ncols, iteratorCol *cols, void *user_strct ) 

/*
   Sample iterator function that calculates the output flux 'rate' column
   by dividing the input 'counts' by the 'time' column.
   It also applies a constant deadtime correction factor if the 'deadtime'
   keyword exists.  Finally, this creates or updates the 'LIVETIME'
   keyword with the sum of all the individual integration times.
*/
{
    int ii, status = 0;
    long repeat;

    /* declare variables static to preserve their values between calls */
    static unsigned char *counts;

    /*--------------------------------------------------------*/
    /*  Initialization procedures: execute on the first call  */
    /*--------------------------------------------------------*/
    if (firstrow == 1)
    {

printf("Datatype of column = %d\n",fits_iter_get_datatype(&cols[0]));

       /* assign the input pointers to the appropriate arrays and null ptrs*/
       counts       = (long *)  fits_iter_get_array(&cols[0]);

    }

    /*--------------------------------------------*/
    /*  Main loop: process all the rows of data */
    /*--------------------------------------------*/

    /*  NOTE: 1st element of array is the null pixel value!  */
    /*  Loop from 1 to nrows, not 0 to nrows - 1.  */


    for (ii = 1; ii <= nrows; ii++)
    {
       repeat = fits_iter_get_repeat(&cols[0]);
       printf ("repeat = %d, %d\n",repeat, counts[1]);
       
    }


    return(0);  /* return successful status */
}
cfitsio/longnam.h0000644000225700000360000005045013246025103013610 0ustar  cagordonlhea#ifndef _LONGNAME_H
#define _LONGNAME_H

#define fits_parse_input_url ffiurl
#define fits_parse_input_filename ffifile
#define fits_parse_rootname ffrtnm
#define fits_file_exists    ffexist
#define fits_parse_output_url ffourl
#define fits_parse_extspec  ffexts
#define fits_parse_extnum   ffextn
#define fits_parse_binspec  ffbins
#define fits_parse_binrange ffbinr
#define fits_parse_range    ffrwrg
#define fits_parse_rangell    ffrwrgll
#define fits_open_memfile   ffomem

/* 
   use the following special macro to test that the fitsio.h include file
   that was used to build the CFITSIO library is compatible with the version
   as included when compiling the application program
*/
#define fits_open_file(A, B, C, D)  ffopentest( CFITSIO_SONAME, A, B, C, D)

#define fits_open_data      ffdopn
#define fits_open_extlist   ffeopn
#define fits_open_table     fftopn
#define fits_open_image     ffiopn
#define fits_open_diskfile  ffdkopn
#define fits_reopen_file    ffreopen
#define fits_create_file    ffinit
#define fits_create_diskfile ffdkinit
#define fits_create_memfile ffimem
#define fits_create_template fftplt
#define fits_flush_file     ffflus
#define fits_flush_buffer   ffflsh
#define fits_close_file     ffclos
#define fits_delete_file    ffdelt
#define fits_file_name      ffflnm
#define fits_file_mode      ffflmd
#define fits_url_type       ffurlt

#define fits_get_version    ffvers
#define fits_uppercase      ffupch
#define fits_get_errstatus  ffgerr
#define fits_write_errmsg   ffpmsg
#define fits_write_errmark  ffpmrk
#define fits_read_errmsg    ffgmsg
#define fits_clear_errmsg   ffcmsg
#define fits_clear_errmark  ffcmrk
#define fits_report_error   ffrprt
#define fits_compare_str    ffcmps
#define fits_test_keyword   fftkey
#define fits_test_record    fftrec
#define fits_null_check     ffnchk
#define fits_make_keyn      ffkeyn
#define fits_make_nkey      ffnkey
#define fits_make_key       ffmkky
#define fits_get_keyclass   ffgkcl
#define fits_get_keytype    ffdtyp
#define fits_get_inttype    ffinttyp
#define fits_parse_value    ffpsvc
#define fits_get_keyname    ffgknm
#define fits_parse_template ffgthd
#define fits_ascii_tform    ffasfm
#define fits_binary_tform   ffbnfm
#define fits_binary_tformll   ffbnfmll
#define fits_get_tbcol      ffgabc
#define fits_get_rowsize    ffgrsz
#define fits_get_col_display_width    ffgcdw

#define fits_write_record       ffprec
#define fits_write_key          ffpky
#define fits_write_key_unit     ffpunt
#define fits_write_comment      ffpcom
#define fits_write_history      ffphis 
#define fits_write_date         ffpdat
#define fits_get_system_time    ffgstm
#define fits_get_system_date    ffgsdt
#define fits_date2str           ffdt2s
#define fits_time2str           fftm2s
#define fits_str2date           ffs2dt
#define fits_str2time           ffs2tm
#define fits_write_key_longstr  ffpkls
#define fits_write_key_longwarn ffplsw
#define fits_write_key_null     ffpkyu
#define fits_write_key_str      ffpkys
#define fits_write_key_log      ffpkyl
#define fits_write_key_lng      ffpkyj
#define fits_write_key_fixflt   ffpkyf
#define fits_write_key_flt      ffpkye
#define fits_write_key_fixdbl   ffpkyg
#define fits_write_key_dbl      ffpkyd
#define fits_write_key_fixcmp   ffpkfc
#define fits_write_key_cmp      ffpkyc
#define fits_write_key_fixdblcmp ffpkfm
#define fits_write_key_dblcmp   ffpkym
#define fits_write_key_triple   ffpkyt
#define fits_write_tdim         ffptdm
#define fits_write_tdimll       ffptdmll
#define fits_write_keys_str     ffpkns
#define fits_write_keys_log     ffpknl
#define fits_write_keys_lng     ffpknj
#define fits_write_keys_fixflt  ffpknf
#define fits_write_keys_flt     ffpkne
#define fits_write_keys_fixdbl  ffpkng
#define fits_write_keys_dbl     ffpknd
#define fits_copy_key           ffcpky
#define fits_write_imghdr       ffphps
#define fits_write_imghdrll     ffphpsll
#define fits_write_grphdr       ffphpr
#define fits_write_grphdrll     ffphprll
#define fits_write_atblhdr      ffphtb
#define fits_write_btblhdr      ffphbn
#define fits_write_exthdr       ffphext
#define fits_write_key_template ffpktp

#define fits_get_hdrspace      ffghsp
#define fits_get_hdrpos        ffghps
#define fits_movabs_key        ffmaky
#define fits_movrel_key        ffmrky
#define fits_find_nextkey      ffgnxk

#define fits_read_record       ffgrec
#define fits_read_card         ffgcrd
#define fits_read_str          ffgstr
#define fits_read_key_unit     ffgunt
#define fits_read_keyn         ffgkyn
#define fits_read_key          ffgky
#define fits_read_keyword      ffgkey
#define fits_read_key_str      ffgkys
#define fits_read_key_log      ffgkyl
#define fits_read_key_lng      ffgkyj
#define fits_read_key_lnglng   ffgkyjj
#define fits_read_key_flt      ffgkye
#define fits_read_key_dbl      ffgkyd
#define fits_read_key_cmp      ffgkyc
#define fits_read_key_dblcmp   ffgkym
#define fits_read_key_triple   ffgkyt
#define fits_get_key_strlen    ffgksl
#define fits_read_key_longstr  ffgkls
#define fits_read_string_key   ffgsky
#define fits_free_memory       fffree
#define fits_read_tdim         ffgtdm
#define fits_read_tdimll       ffgtdmll
#define fits_decode_tdim       ffdtdm
#define fits_decode_tdimll     ffdtdmll
#define fits_read_keys_str     ffgkns
#define fits_read_keys_log     ffgknl
#define fits_read_keys_lng     ffgknj
#define fits_read_keys_lnglng  ffgknjj
#define fits_read_keys_flt     ffgkne
#define fits_read_keys_dbl     ffgknd
#define fits_read_imghdr       ffghpr
#define fits_read_imghdrll     ffghprll
#define fits_read_atblhdr      ffghtb
#define fits_read_btblhdr      ffghbn
#define fits_read_atblhdrll    ffghtbll
#define fits_read_btblhdrll    ffghbnll
#define fits_hdr2str           ffhdr2str
#define fits_convert_hdr2str   ffcnvthdr2str

#define fits_update_card       ffucrd
#define fits_update_key        ffuky
#define fits_update_key_null   ffukyu
#define fits_update_key_str    ffukys
#define fits_update_key_longstr    ffukls
#define fits_update_key_log    ffukyl
#define fits_update_key_lng    ffukyj
#define fits_update_key_fixflt ffukyf
#define fits_update_key_flt    ffukye
#define fits_update_key_fixdbl ffukyg
#define fits_update_key_dbl    ffukyd
#define fits_update_key_fixcmp ffukfc
#define fits_update_key_cmp    ffukyc
#define fits_update_key_fixdblcmp ffukfm
#define fits_update_key_dblcmp ffukym

#define fits_modify_record     ffmrec
#define fits_modify_card       ffmcrd
#define fits_modify_name       ffmnam
#define fits_modify_comment    ffmcom
#define fits_modify_key_null   ffmkyu
#define fits_modify_key_str    ffmkys
#define fits_modify_key_longstr    ffmkls
#define fits_modify_key_log    ffmkyl
#define fits_modify_key_lng    ffmkyj
#define fits_modify_key_fixflt ffmkyf
#define fits_modify_key_flt    ffmkye
#define fits_modify_key_fixdbl ffmkyg
#define fits_modify_key_dbl    ffmkyd
#define fits_modify_key_fixcmp ffmkfc
#define fits_modify_key_cmp    ffmkyc
#define fits_modify_key_fixdblcmp ffmkfm
#define fits_modify_key_dblcmp ffmkym

#define fits_insert_record     ffirec
#define fits_insert_card       ffikey
#define fits_insert_key_null   ffikyu
#define fits_insert_key_str    ffikys
#define fits_insert_key_longstr    ffikls
#define fits_insert_key_log    ffikyl
#define fits_insert_key_lng    ffikyj
#define fits_insert_key_fixflt ffikyf
#define fits_insert_key_flt    ffikye
#define fits_insert_key_fixdbl ffikyg
#define fits_insert_key_dbl    ffikyd
#define fits_insert_key_fixcmp ffikfc
#define fits_insert_key_cmp    ffikyc
#define fits_insert_key_fixdblcmp ffikfm
#define fits_insert_key_dblcmp ffikym

#define fits_delete_key     ffdkey
#define fits_delete_str     ffdstr
#define fits_delete_record  ffdrec
#define fits_get_hdu_num    ffghdn
#define fits_get_hdu_type   ffghdt
#define fits_get_hduaddr    ffghad
#define fits_get_hduaddrll    ffghadll
#define fits_get_hduoff     ffghof

#define fits_get_img_param  ffgipr
#define fits_get_img_paramll  ffgiprll

#define fits_get_img_type   ffgidt
#define fits_get_img_equivtype   ffgiet
#define fits_get_img_dim    ffgidm
#define fits_get_img_size   ffgisz
#define fits_get_img_sizell   ffgiszll

#define fits_movabs_hdu     ffmahd
#define fits_movrel_hdu     ffmrhd
#define fits_movnam_hdu     ffmnhd
#define fits_get_num_hdus   ffthdu
#define fits_create_img     ffcrim
#define fits_create_imgll   ffcrimll
#define fits_create_tbl     ffcrtb
#define fits_create_hdu     ffcrhd
#define fits_insert_img     ffiimg
#define fits_insert_imgll   ffiimgll
#define fits_insert_atbl    ffitab
#define fits_insert_btbl    ffibin
#define fits_resize_img     ffrsim
#define fits_resize_imgll   ffrsimll

#define fits_delete_hdu     ffdhdu
#define fits_copy_hdu       ffcopy
#define fits_copy_file      ffcpfl
#define fits_copy_header    ffcphd
#define fits_copy_data      ffcpdt
#define fits_write_hdu      ffwrhdu

#define fits_set_hdustruc   ffrdef
#define fits_set_hdrsize    ffhdef
#define fits_write_theap    ffpthp

#define fits_encode_chksum  ffesum
#define fits_decode_chksum  ffdsum
#define fits_write_chksum   ffpcks
#define fits_update_chksum  ffupck
#define fits_verify_chksum  ffvcks
#define fits_get_chksum     ffgcks

#define fits_set_bscale     ffpscl
#define fits_set_tscale     fftscl
#define fits_set_imgnull    ffpnul
#define fits_set_btblnull   fftnul
#define fits_set_atblnull   ffsnul

#define fits_get_colnum     ffgcno
#define fits_get_colname    ffgcnn
#define fits_get_coltype    ffgtcl
#define fits_get_coltypell  ffgtclll
#define fits_get_eqcoltype  ffeqty
#define fits_get_eqcoltypell ffeqtyll
#define fits_get_num_rows   ffgnrw
#define fits_get_num_rowsll   ffgnrwll
#define fits_get_num_cols   ffgncl
#define fits_get_acolparms  ffgacl
#define fits_get_bcolparms  ffgbcl
#define fits_get_bcolparmsll  ffgbclll

#define fits_iterate_data   ffiter

#define fits_read_grppar_byt  ffggpb
#define fits_read_grppar_sbyt  ffggpsb
#define fits_read_grppar_usht  ffggpui
#define fits_read_grppar_ulng  ffggpuj
#define fits_read_grppar_sht  ffggpi
#define fits_read_grppar_lng  ffggpj
#define fits_read_grppar_lnglng  ffggpjj
#define fits_read_grppar_int  ffggpk
#define fits_read_grppar_uint  ffggpuk
#define fits_read_grppar_flt  ffggpe
#define fits_read_grppar_dbl  ffggpd

#define fits_read_pix         ffgpxv
#define fits_read_pixll       ffgpxvll
#define fits_read_pixnull     ffgpxf
#define fits_read_pixnullll   ffgpxfll
#define fits_read_img         ffgpv
#define fits_read_imgnull     ffgpf
#define fits_read_img_byt     ffgpvb
#define fits_read_img_sbyt     ffgpvsb
#define fits_read_img_usht     ffgpvui
#define fits_read_img_ulng     ffgpvuj
#define fits_read_img_sht     ffgpvi
#define fits_read_img_lng     ffgpvj
#define fits_read_img_lnglng     ffgpvjj
#define fits_read_img_uint     ffgpvuk
#define fits_read_img_int     ffgpvk
#define fits_read_img_flt     ffgpve
#define fits_read_img_dbl     ffgpvd

#define fits_read_imgnull_byt ffgpfb
#define fits_read_imgnull_sbyt ffgpfsb
#define fits_read_imgnull_usht ffgpfui
#define fits_read_imgnull_ulng ffgpfuj
#define fits_read_imgnull_sht ffgpfi
#define fits_read_imgnull_lng ffgpfj
#define fits_read_imgnull_lnglng ffgpfjj
#define fits_read_imgnull_uint ffgpfuk
#define fits_read_imgnull_int ffgpfk
#define fits_read_imgnull_flt ffgpfe
#define fits_read_imgnull_dbl ffgpfd

#define fits_read_2d_byt      ffg2db
#define fits_read_2d_sbyt     ffg2dsb
#define fits_read_2d_usht      ffg2dui
#define fits_read_2d_ulng      ffg2duj
#define fits_read_2d_sht      ffg2di
#define fits_read_2d_lng      ffg2dj
#define fits_read_2d_lnglng      ffg2djj
#define fits_read_2d_uint      ffg2duk
#define fits_read_2d_int      ffg2dk
#define fits_read_2d_flt      ffg2de
#define fits_read_2d_dbl      ffg2dd

#define fits_read_3d_byt      ffg3db
#define fits_read_3d_sbyt      ffg3dsb
#define fits_read_3d_usht      ffg3dui
#define fits_read_3d_ulng      ffg3duj
#define fits_read_3d_sht      ffg3di
#define fits_read_3d_lng      ffg3dj
#define fits_read_3d_lnglng      ffg3djj
#define fits_read_3d_uint      ffg3duk
#define fits_read_3d_int      ffg3dk
#define fits_read_3d_flt      ffg3de
#define fits_read_3d_dbl      ffg3dd

#define fits_read_subset      ffgsv
#define fits_read_subset_byt  ffgsvb
#define fits_read_subset_sbyt  ffgsvsb
#define fits_read_subset_usht  ffgsvui
#define fits_read_subset_ulng  ffgsvuj
#define fits_read_subset_sht  ffgsvi
#define fits_read_subset_lng  ffgsvj
#define fits_read_subset_lnglng  ffgsvjj
#define fits_read_subset_uint  ffgsvuk
#define fits_read_subset_int  ffgsvk
#define fits_read_subset_flt  ffgsve
#define fits_read_subset_dbl  ffgsvd

#define fits_read_subsetnull_byt ffgsfb
#define fits_read_subsetnull_sbyt ffgsfsb
#define fits_read_subsetnull_usht ffgsfui
#define fits_read_subsetnull_ulng ffgsfuj
#define fits_read_subsetnull_sht ffgsfi
#define fits_read_subsetnull_lng ffgsfj
#define fits_read_subsetnull_lnglng ffgsfjj
#define fits_read_subsetnull_uint ffgsfuk
#define fits_read_subsetnull_int ffgsfk
#define fits_read_subsetnull_flt ffgsfe
#define fits_read_subsetnull_dbl ffgsfd

#define ffcpimg fits_copy_image_section
#define fits_compress_img fits_comp_img
#define fits_decompress_img fits_decomp_img

#define fits_read_col        ffgcv
#define fits_read_colnull    ffgcf
#define fits_read_col_str    ffgcvs
#define fits_read_col_log    ffgcvl
#define fits_read_col_byt    ffgcvb
#define fits_read_col_sbyt    ffgcvsb
#define fits_read_col_usht    ffgcvui
#define fits_read_col_ulng    ffgcvuj
#define fits_read_col_sht    ffgcvi
#define fits_read_col_lng    ffgcvj
#define fits_read_col_lnglng    ffgcvjj
#define fits_read_col_uint    ffgcvuk
#define fits_read_col_int    ffgcvk
#define fits_read_col_flt    ffgcve
#define fits_read_col_dbl    ffgcvd
#define fits_read_col_cmp    ffgcvc
#define fits_read_col_dblcmp ffgcvm
#define fits_read_col_bit    ffgcx
#define fits_read_col_bit_usht ffgcxui
#define fits_read_col_bit_uint ffgcxuk

#define fits_read_colnull_str    ffgcfs
#define fits_read_colnull_log    ffgcfl
#define fits_read_colnull_byt    ffgcfb
#define fits_read_colnull_sbyt    ffgcfsb
#define fits_read_colnull_usht    ffgcfui
#define fits_read_colnull_ulng    ffgcfuj
#define fits_read_colnull_sht    ffgcfi
#define fits_read_colnull_lng    ffgcfj
#define fits_read_colnull_lnglng    ffgcfjj
#define fits_read_colnull_uint    ffgcfuk
#define fits_read_colnull_int    ffgcfk
#define fits_read_colnull_flt    ffgcfe
#define fits_read_colnull_dbl    ffgcfd
#define fits_read_colnull_cmp    ffgcfc
#define fits_read_colnull_dblcmp ffgcfm

#define fits_read_descript ffgdes
#define fits_read_descriptll ffgdesll
#define fits_read_descripts ffgdess
#define fits_read_descriptsll ffgdessll
#define fits_read_tblbytes    ffgtbb

#define fits_write_grppar_byt ffpgpb
#define fits_write_grppar_sbyt ffpgpsb
#define fits_write_grppar_usht ffpgpui
#define fits_write_grppar_ulng ffpgpuj
#define fits_write_grppar_sht ffpgpi
#define fits_write_grppar_lng ffpgpj
#define fits_write_grppar_lnglng ffpgpjj
#define fits_write_grppar_uint ffpgpuk
#define fits_write_grppar_int ffpgpk
#define fits_write_grppar_flt ffpgpe
#define fits_write_grppar_dbl ffpgpd

#define fits_write_pix        ffppx
#define fits_write_pixll      ffppxll
#define fits_write_pixnull    ffppxn
#define fits_write_pixnullll  ffppxnll
#define fits_write_img        ffppr
#define fits_write_img_byt    ffpprb
#define fits_write_img_sbyt    ffpprsb
#define fits_write_img_usht    ffpprui
#define fits_write_img_ulng    ffppruj
#define fits_write_img_sht    ffppri
#define fits_write_img_lng    ffpprj
#define fits_write_img_lnglng    ffpprjj
#define fits_write_img_uint    ffppruk
#define fits_write_img_int    ffpprk
#define fits_write_img_flt    ffppre
#define fits_write_img_dbl    ffpprd

#define fits_write_imgnull     ffppn
#define fits_write_imgnull_byt ffppnb
#define fits_write_imgnull_sbyt ffppnsb
#define fits_write_imgnull_usht ffppnui
#define fits_write_imgnull_ulng ffppnuj
#define fits_write_imgnull_sht ffppni
#define fits_write_imgnull_lng ffppnj
#define fits_write_imgnull_lnglng ffppnjj
#define fits_write_imgnull_uint ffppnuk
#define fits_write_imgnull_int ffppnk
#define fits_write_imgnull_flt ffppne
#define fits_write_imgnull_dbl ffppnd

#define fits_write_img_null ffppru
#define fits_write_null_img ffpprn

#define fits_write_2d_byt   ffp2db
#define fits_write_2d_sbyt   ffp2dsb
#define fits_write_2d_usht   ffp2dui
#define fits_write_2d_ulng   ffp2duj
#define fits_write_2d_sht   ffp2di
#define fits_write_2d_lng   ffp2dj
#define fits_write_2d_lnglng   ffp2djj
#define fits_write_2d_uint   ffp2duk
#define fits_write_2d_int   ffp2dk
#define fits_write_2d_flt   ffp2de
#define fits_write_2d_dbl   ffp2dd

#define fits_write_3d_byt   ffp3db
#define fits_write_3d_sbyt   ffp3dsb
#define fits_write_3d_usht   ffp3dui
#define fits_write_3d_ulng   ffp3duj
#define fits_write_3d_sht   ffp3di
#define fits_write_3d_lng   ffp3dj
#define fits_write_3d_lnglng   ffp3djj
#define fits_write_3d_uint   ffp3duk
#define fits_write_3d_int   ffp3dk
#define fits_write_3d_flt   ffp3de
#define fits_write_3d_dbl   ffp3dd

#define fits_write_subset  ffpss
#define fits_write_subset_byt  ffpssb
#define fits_write_subset_sbyt  ffpsssb
#define fits_write_subset_usht  ffpssui
#define fits_write_subset_ulng  ffpssuj
#define fits_write_subset_sht  ffpssi
#define fits_write_subset_lng  ffpssj
#define fits_write_subset_lnglng  ffpssjj
#define fits_write_subset_uint  ffpssuk
#define fits_write_subset_int  ffpssk
#define fits_write_subset_flt  ffpsse
#define fits_write_subset_dbl  ffpssd

#define fits_write_col         ffpcl
#define fits_write_col_str     ffpcls
#define fits_write_col_log     ffpcll
#define fits_write_col_byt     ffpclb
#define fits_write_col_sbyt     ffpclsb
#define fits_write_col_usht     ffpclui
#define fits_write_col_ulng     ffpcluj
#define fits_write_col_sht     ffpcli
#define fits_write_col_lng     ffpclj
#define fits_write_col_lnglng     ffpcljj
#define fits_write_col_uint     ffpcluk
#define fits_write_col_int     ffpclk
#define fits_write_col_flt     ffpcle
#define fits_write_col_dbl     ffpcld
#define fits_write_col_cmp     ffpclc
#define fits_write_col_dblcmp  ffpclm
#define fits_write_col_null    ffpclu
#define fits_write_col_bit     ffpclx
#define fits_write_nulrows     ffprwu
#define fits_write_nullrows    ffprwu

#define fits_write_colnull ffpcn
#define fits_write_colnull_str ffpcns
#define fits_write_colnull_log ffpcnl
#define fits_write_colnull_byt ffpcnb
#define fits_write_colnull_sbyt ffpcnsb
#define fits_write_colnull_usht ffpcnui
#define fits_write_colnull_ulng ffpcnuj
#define fits_write_colnull_sht ffpcni
#define fits_write_colnull_lng ffpcnj
#define fits_write_colnull_lnglng ffpcnjj
#define fits_write_colnull_uint ffpcnuk
#define fits_write_colnull_int ffpcnk
#define fits_write_colnull_flt ffpcne
#define fits_write_colnull_dbl ffpcnd

#define fits_write_ext ffpextn
#define fits_read_ext  ffgextn

#define fits_write_descript  ffpdes
#define fits_compress_heap   ffcmph
#define fits_test_heap   fftheap

#define fits_write_tblbytes  ffptbb
#define fits_insert_rows  ffirow
#define fits_delete_rows  ffdrow
#define fits_delete_rowrange ffdrrg
#define fits_delete_rowlist ffdrws
#define fits_delete_rowlistll ffdrwsll
#define fits_insert_col   fficol
#define fits_insert_cols  fficls
#define fits_delete_col   ffdcol
#define fits_copy_col     ffcpcl
#define fits_copy_rows    ffcprw
#define fits_modify_vector_len  ffmvec

#define fits_read_img_coord ffgics
#define fits_read_img_coord_version ffgicsa
#define fits_read_tbl_coord ffgtcs
#define fits_pix_to_world ffwldp
#define fits_world_to_pix ffxypx

#define fits_get_image_wcs_keys ffgiwcs
#define fits_get_table_wcs_keys ffgtwcs

#define fits_find_rows          fffrow
#define fits_find_first_row     ffffrw
#define fits_find_rows_cmp      fffrwc
#define fits_select_rows        ffsrow
#define fits_calc_rows          ffcrow
#define fits_calculator         ffcalc
#define fits_calculator_rng     ffcalc_rng
#define fits_test_expr          fftexp

#define fits_create_group       ffgtcr 
#define fits_insert_group       ffgtis 
#define fits_change_group       ffgtch 
#define fits_remove_group       ffgtrm 
#define fits_copy_group         ffgtcp 
#define fits_merge_groups       ffgtmg 
#define fits_compact_group      ffgtcm 
#define fits_verify_group       ffgtvf 
#define fits_open_group         ffgtop 
#define fits_add_group_member   ffgtam 
#define fits_get_num_members    ffgtnm 

#define fits_get_num_groups     ffgmng 
#define fits_open_member        ffgmop 
#define fits_copy_member        ffgmcp 
#define fits_transfer_member    ffgmtf 
#define fits_remove_member      ffgmrm

#define fits_init_https         ffihtps
#define fits_cleanup_https      ffchtps
#define fits_verbose_https      ffvhtps

#endif
cfitsio/makefile.bc0000644000225700000360000003072213246025103014067 0ustar  cagordonlhea#
# Borland C++ IDE generated makefile
# Generated 10/12/99 at 1:24:11 PM 
#
.AUTODEPEND


#
# Borland C++ tools
#
IMPLIB  = Implib
BCC32   = Bcc32 +BccW32.cfg 
BCC32I  = Bcc32i +BccW32.cfg 
TLINK32 = TLink32
ILINK32 = Ilink32
TLIB    = TLib
BRC32   = Brc32
TASM32  = Tasm32
#
# IDE macros
#


#
# Options
#
IDE_LinkFLAGS32 =  -LD:\BC5\LIB
LinkerLocalOptsAtC32_cfitsiodlib =  -Tpd -ap -c
ResLocalOptsAtC32_cfitsiodlib = 
BLocalOptsAtC32_cfitsiodlib = 
CompInheritOptsAt_cfitsiodlib = -ID:\BC5\INCLUDE -D_RTLDLL -DWIN32;
LinkerInheritOptsAt_cfitsiodlib = -x
LinkerOptsAt_cfitsiodlib = $(LinkerLocalOptsAtC32_cfitsiodlib)
ResOptsAt_cfitsiodlib = $(ResLocalOptsAtC32_cfitsiodlib)
BOptsAt_cfitsiodlib = $(BLocalOptsAtC32_cfitsiodlib)

#
# Dependency List
#
Dep_cfitsio = \
   cfitsio.lib

cfitsio : BccW32.cfg $(Dep_cfitsio)
  echo MakeNode

cfitsio.lib : cfitsio.dll
  $(IMPLIB) $@ cfitsio.dll


Dep_cfitsioddll = \
   listhead.obj\
   imcompress.obj\
   quantize.obj\
   ricecomp.obj\
   pliocomp.obj\
   iraffits.obj\
   wcsutil.obj\
   histo.obj\
   scalnull.obj\
   region.obj\
   putkey.obj\
   putcoluk.obj\
   putcoluj.obj\
   putcolui.obj\
   putcolu.obj\
   putcols.obj\
   putcoll.obj\
   putcolk.obj\
   putcolj.obj\
   putcoli.obj\
   putcole.obj\
   putcold.obj\
   putcolb.obj\
   putcolsb.obj\
   putcol.obj\
   modkey.obj\
   swapproc.obj\
   getcol.obj\
   group.obj\
   getkey.obj\
   getcoluk.obj\
   getcoluj.obj\
   getcolui.obj\
   getcols.obj\
   getcoll.obj\
   getcolk.obj\
   getcolj.obj\
   getcoli.obj\
   getcole.obj\
   getcold.obj\
   getcolb.obj\
   getcolsb.obj\
   grparser.obj\
   fitscore.obj\
   f77_wrap1.obj\
   f77_wrap2.obj\
   f77_wrap3.obj\
   f77_wrap4.obj\
   eval_y.obj\
   eval_l.obj\
   eval_f.obj\
   edithdu.obj\
   editcol.obj\
   drvrmem.obj\
   drvrfile.obj\
   checksum.obj\
   cfileio.obj\
   buffers.obj\
   fits_hcompress.obj\
   fits_hdecompress.obj\
   zuncompress.obj\
   zcompress.obj\
   adler32.obj\
   crc32.obj\
   inffast.obj\
   inftrees.obj\
   trees.obj\
   zutil.obj\
   deflate.obj\
   infback.obj\
   inflate.obj\
   uncompr.obj

cfitsio.dll : $(Dep_cfitsioddll) cfitsio.def
  $(ILINK32) @&&|
 /v $(IDE_LinkFLAGS32) $(LinkerOptsAt_cfitsiodlib) $(LinkerInheritOptsAt_cfitsiodlib) +
D:\BC5\LIB\c0d32.obj+
listhead.obj+
imcompress.obj+
quantize.obj+
ricecomp.obj+
pliocomp.obj+
iraffits.obj+
wcsutil.obj+
histo.obj+
iraffits.obj+
scalnull.obj+
region.obj+
putkey.obj+
putcoluk.obj+
putcoluj.obj+
putcolui.obj+
putcolu.obj+
putcols.obj+
putcoll.obj+
putcolk.obj+
putcolj.obj+
putcoli.obj+
putcole.obj+
putcold.obj+
putcolb.obj+
putcolsb.obj+
putcol.obj+
modkey.obj+
swapproc.obj+
getcol.obj+
group.obj+
getkey.obj+
getcoluk.obj+
getcoluj.obj+
getcolui.obj+
getcols.obj+
getcoll.obj+
getcolk.obj+
getcolj.obj+
getcoli.obj+
getcole.obj+
getcold.obj+
getcolb.obj+
getcolsb.obj+
grparser.obj+
fitscore.obj+
f77_wrap1.obj+
f77_wrap2.obj+
f77_wrap3.obj+
f77_wrap4.obj+
eval_y.obj+
eval_l.obj+
eval_f.obj+
edithdu.obj+
editcol.obj+
drvrmem.obj+
drvrfile.obj+
checksum.obj+
cfileio.obj+
buffers.obj+
fits_hcompress.obj+
fits_hdecompress.obj+
zuncompress.obj+
zcompress.obj+
adler32.obj+
crc32.obj+
inffast.obj+
inftrees.obj+
trees.obj+
zutil.obj+
deflate.obj+
infback.obj+
inflate.obj+
uncompr.obj
$<,$*
D:\BC5\LIB\import32.lib+
D:\BC5\LIB\cw32i.lib
cfitsio.def


|
wcsutil.obj :  wcsutil.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ wcsutil.c
|
iraffits.obj :  iraffits.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ iraffits.c
|
histo.obj :  histo.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ histo.c
|

scalnull.obj :  scalnull.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ scalnull.c
|

region.obj :  region.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ region.c
|

putkey.obj :  putkey.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putkey.c
|

putcoluk.obj :  putcoluk.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putcoluk.c
|

putcoluj.obj :  putcoluj.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putcoluj.c
|

putcolui.obj :  putcolui.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putcolui.c
|

putcolu.obj :  putcolu.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putcolu.c
|

putcols.obj :  putcols.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putcols.c
|

putcoll.obj :  putcoll.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putcoll.c
|

putcolk.obj :  putcolk.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putcolk.c
|

putcolj.obj :  putcolj.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putcolj.c
|

putcoli.obj :  putcoli.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putcoli.c
|

putcole.obj :  putcole.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putcole.c
|

putcold.obj :  putcold.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putcold.c
|

putcolb.obj :  putcolb.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putcolb.c
|

putcolsb.obj :  putcolsb.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putcolsb.c
|

putcol.obj :  putcol.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ putcol.c
|

modkey.obj :  modkey.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ modkey.c
|

swapproc.obj :  swapproc.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ swapproc.c
|

getcol.obj :  getcol.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ getcol.c
|

group.obj :  group.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ group.c
|

getkey.obj :  getkey.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ getkey.c
|

getcoluk.obj :  getcoluk.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ getcoluk.c
|

getcoluj.obj :  getcoluj.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ getcoluj.c
|

getcolui.obj :  getcolui.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ getcolui.c
|

getcols.obj :  getcols.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ getcols.c
|

getcoll.obj :  getcoll.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ getcoll.c
|

getcolk.obj :  getcolk.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ getcolk.c
|

getcolj.obj :  getcolj.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ getcolj.c
|

getcoli.obj :  getcoli.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ getcoli.c
|

getcole.obj :  getcole.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ getcole.c
|

getcold.obj :  getcold.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ getcold.c
|

getcolb.obj :  getcolb.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ getcolb.c
|
getcolsb.obj :  getcolsb.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ getcolsb.c
|

grparser.obj :  grparser.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ grparser.c
|

fitscore.obj :  fitscore.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ fitscore.c
|

f77_wrap1.obj :  f77_wrap1.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ f77_wrap1.c
|

f77_wrap2.obj :  f77_wrap2.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ f77_wrap2.c
|

f77_wrap3.obj :  f77_wrap3.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ f77_wrap3.c
|

f77_wrap4.obj :  f77_wrap4.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ f77_wrap4.c
|

eval_y.obj :  eval_y.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ eval_y.c
|

eval_l.obj :  eval_l.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ eval_l.c
|

eval_f.obj :  eval_f.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ eval_f.c
|

edithdu.obj :  edithdu.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ edithdu.c
|

editcol.obj :  editcol.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ editcol.c
|

drvrmem.obj :  drvrmem.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ drvrmem.c
|

drvrfile.obj :  drvrfile.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ drvrfile.c
|

checksum.obj :  checksum.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ checksum.c
|

cfileio.obj :  cfileio.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ cfileio.c
|

listhead.obj :  listhead.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ listhead.c
|

imcompress.obj :  imcompress.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ imcompress.c
|

quantize.obj :  quantize.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ quantize.c
|

ricecomp.obj :  ricecomp.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ ricecomp.c
|

pliocomp.obj :  pliocomp.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ pliocomp.c
|

buffers.obj :  buffers.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ buffers.c
|

fits_hcompress.obj :  fits_hcompress.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ fits_hcompress.c
|

fits_hdecompress.obj :  fits_hdecompress.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ fits_hdecompress.c
|

zuncompress.obj :  zuncompress.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ zuncompress.c
|

zcompress.obj :  zcompress.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ zcompress.c
|

adler32.obj :  adler32.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ adler32.c
|

crc32.obj :  crc32.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ crc32.c
|

inffast.obj :  inffast.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ inffast.c
|

inftrees.obj :  inftrees.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ inftrees.c
|

trees.obj :  trees.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ trees.c
|

zutil.obj :  zutil.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ zutil.c
|

deflate.obj :  deflate.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ deflate.c
|

infback.obj :  infback.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ infback.c
|

inflate.obj :  inflate.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ inflate.c
|

uncompr.obj :  uncompr.c
  $(BCC32) -P- -c @&&|
 $(CompOptsAt_cfitsiodlib) $(CompInheritOptsAt_cfitsiodlib) -o$@ uncompr.c
|


windumpexts.exe :  windumpexts.c
  bcc32 windumpexts.c


cfitsio.def: windumpexts.exe
	windumpexts -o cfitsio.def cfitsio.dll @&&|
		$(Dep_cfitsioddll)
|

# Compiler configuration file
BccW32.cfg : 
   Copy &&|
-w
-R
-v
-WM-
-vi
-H
-H=cfitsio.csm
-WCD
| $@


cfitsio/makefile.vcc0000644000225700000360000004317013246025103014257 0ustar  cagordonlhea# Microsoft Developer Studio Generated NMAKE File, Based on cfitsio.dsp
!IF "$(CFG)" == ""
CFG=Win32 Release
!MESSAGE No configuration specified. Defaulting to Win32 Release.
!ENDIF 

!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug"
!MESSAGE Invalid configuration "$(CFG)" specified.
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE 
!MESSAGE NMAKE /f "cfitsio.mak" CFG="Win32 Debug"
!MESSAGE 
!MESSAGE Possible choices for configuration are:
!MESSAGE 
!MESSAGE "Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE 
!ERROR An invalid configuration is specified.
!ENDIF 

!IF "$(OS)" == "Windows_NT"
NULL=
!ELSE 
NULL=nul
!ENDIF 

CPP=cl.exe
MTL=midl.exe
RSC=rc.exe

!IF  "$(CFG)" == "Win32 Release"

OUTDIR=.
INTDIR=.\Release
# Begin Custom Macros
OutDir=.
# End Custom Macros

ALL : "$(OUTDIR)\cfitsio.dll"


CLEAN :
	-@erase "$(INTDIR)\buffers.obj"
	-@erase "$(INTDIR)\cfileio.obj"
	-@erase "$(INTDIR)\checksum.obj"
	-@erase "$(INTDIR)\drvrfile.obj"
	-@erase "$(INTDIR)\drvrmem.obj"
	-@erase "$(INTDIR)\editcol.obj"
	-@erase "$(INTDIR)\edithdu.obj"
	-@erase "$(INTDIR)\eval_f.obj"
	-@erase "$(INTDIR)\eval_l.obj"
	-@erase "$(INTDIR)\eval_y.obj"
	-@erase "$(INTDIR)\fitscore.obj"
	-@erase "$(INTDIR)\f77_wrap1.obj"
	-@erase "$(INTDIR)\f77_wrap2.obj"
	-@erase "$(INTDIR)\f77_wrap3.obj"
	-@erase "$(INTDIR)\f77_wrap4.obj"
	-@erase "$(INTDIR)\getcol.obj"
	-@erase "$(INTDIR)\getcolb.obj"
	-@erase "$(INTDIR)\getcolsb.obj"
	-@erase "$(INTDIR)\getcold.obj"
	-@erase "$(INTDIR)\getcole.obj"
	-@erase "$(INTDIR)\getcoli.obj"
	-@erase "$(INTDIR)\getcolj.obj"
	-@erase "$(INTDIR)\getcolk.obj"
	-@erase "$(INTDIR)\getcoll.obj"
	-@erase "$(INTDIR)\getcols.obj"
	-@erase "$(INTDIR)\getcolui.obj"
	-@erase "$(INTDIR)\getcoluj.obj"
	-@erase "$(INTDIR)\getcoluk.obj"
	-@erase "$(INTDIR)\getkey.obj"
	-@erase "$(INTDIR)\group.obj"
	-@erase "$(INTDIR)\grparser.obj"
	-@erase "$(INTDIR)\histo.obj"
	-@erase "$(INTDIR)\iraffits.obj"
	-@erase "$(INTDIR)\modkey.obj"
	-@erase "$(INTDIR)\putcol.obj"
	-@erase "$(INTDIR)\putcolb.obj"
	-@erase "$(INTDIR)\putcolsb.obj"
	-@erase "$(INTDIR)\putcold.obj"
	-@erase "$(INTDIR)\putcole.obj"
	-@erase "$(INTDIR)\putcoli.obj"
	-@erase "$(INTDIR)\putcolj.obj"
	-@erase "$(INTDIR)\putcolk.obj"
	-@erase "$(INTDIR)\putcoll.obj"
	-@erase "$(INTDIR)\putcols.obj"
	-@erase "$(INTDIR)\putcolu.obj"
	-@erase "$(INTDIR)\putcolui.obj"
	-@erase "$(INTDIR)\putcoluj.obj"
	-@erase "$(INTDIR)\putcoluk.obj"
	-@erase "$(INTDIR)\putkey.obj"
	-@erase "$(INTDIR)\region.obj"
	-@erase "$(INTDIR)\scalnull.obj"
	-@erase "$(INTDIR)\swapproc.obj"
	-@erase "$(INTDIR)\wcssub.obj"
	-@erase "$(INTDIR)\wcsutil.obj"
	-@erase "$(INTDIR)\imcompress.obj"
	-@erase "$(INTDIR)\ricecomp.obj"
	-@erase "$(INTDIR)\quantize.obj"
	-@erase "$(INTDIR)\pliocomp.obj"
	-@erase "$(INTDIR)\fits_hcompress.obj"
	-@erase "$(INTDIR)\fits_hdecompress.obj"
	-@erase "$(INTDIR)\zuncompress.obj"
	-@erase "$(INTDIR)\zcompress.obj"
	-@erase "$(INTDIR)\adler32.obj"
	-@erase "$(INTDIR)\crc32.obj"
	-@erase "$(INTDIR)\inffast.obj"
	-@erase "$(INTDIR)\inftrees.obj"
	-@erase "$(INTDIR)\trees.obj"
	-@erase "$(INTDIR)\zutil.obj"
	-@erase "$(INTDIR)\deflate.obj"
	-@erase "$(INTDIR)\infback.obj"
	-@erase "$(INTDIR)\inflate.obj"
	-@erase "$(INTDIR)\uncompr.obj"
	-@erase "$(INTDIR)\vc60.idb"
	-@erase "$(OUTDIR)\cfitsio.dll"
	-@erase "$(OUTDIR)\cfitsio.exp"
	-@erase "$(OUTDIR)\cfitsio.lib"

"$(OUTDIR)" :
    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"

"$(INTDIR)" :
    if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"

CPP_PROJ=/nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CFITSIO_EXPORTS" /D "_CRT_SECURE_NO_DEPRECATE" /Fp"$(INTDIR)\cfitsio.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c 
MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 
BSC32=bscmake.exe
BSC32_FLAGS=/nologo /o"$(OUTDIR)\cfitsio.bsc" 
BSC32_SBRS= \
	
LINK32=link.exe
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\cfitsio.pdb" /machine:I386 /def:".\cfitsio.def" /out:"$(OUTDIR)\cfitsio.dll" /implib:"$(OUTDIR)\cfitsio.lib" 
DEF_FILE= ".\cfitsio.def"
LINK32_OBJS= \
	"$(INTDIR)\buffers.obj" \
	"$(INTDIR)\cfileio.obj" \
	"$(INTDIR)\checksum.obj" \
	"$(INTDIR)\drvrfile.obj" \
	"$(INTDIR)\drvrmem.obj" \
	"$(INTDIR)\editcol.obj" \
	"$(INTDIR)\edithdu.obj" \
	"$(INTDIR)\eval_f.obj" \
	"$(INTDIR)\eval_l.obj" \
	"$(INTDIR)\eval_y.obj" \
	"$(INTDIR)\fitscore.obj" \
	"$(INTDIR)\f77_wrap1.obj" \
	"$(INTDIR)\f77_wrap2.obj" \
	"$(INTDIR)\f77_wrap3.obj" \
	"$(INTDIR)\f77_wrap4.obj" \
	"$(INTDIR)\getcol.obj" \
	"$(INTDIR)\getcolb.obj" \
	"$(INTDIR)\getcolsb.obj" \
	"$(INTDIR)\getcold.obj" \
	"$(INTDIR)\getcole.obj" \
	"$(INTDIR)\getcoli.obj" \
	"$(INTDIR)\getcolj.obj" \
	"$(INTDIR)\getcolk.obj" \
	"$(INTDIR)\getcoll.obj" \
	"$(INTDIR)\getcols.obj" \
	"$(INTDIR)\getcolui.obj" \
	"$(INTDIR)\getcoluj.obj" \
	"$(INTDIR)\getcoluk.obj" \
	"$(INTDIR)\getkey.obj" \
	"$(INTDIR)\group.obj" \
	"$(INTDIR)\grparser.obj" \
	"$(INTDIR)\histo.obj" \
	"$(INTDIR)\iraffits.obj" \
	"$(INTDIR)\modkey.obj" \
	"$(INTDIR)\putcol.obj" \
	"$(INTDIR)\putcolb.obj" \
	"$(INTDIR)\putcolsb.obj" \
	"$(INTDIR)\putcold.obj" \
	"$(INTDIR)\putcole.obj" \
	"$(INTDIR)\putcoli.obj" \
	"$(INTDIR)\putcolj.obj" \
	"$(INTDIR)\putcolk.obj" \
	"$(INTDIR)\putcoll.obj" \
	"$(INTDIR)\putcols.obj" \
	"$(INTDIR)\putcolu.obj" \
	"$(INTDIR)\putcolui.obj" \
	"$(INTDIR)\putcoluj.obj" \
	"$(INTDIR)\putcoluk.obj" \
	"$(INTDIR)\putkey.obj" \
	"$(INTDIR)\region.obj" \
	"$(INTDIR)\scalnull.obj" \
	"$(INTDIR)\swapproc.obj" \
	"$(INTDIR)\wcssub.obj"  \
	"$(INTDIR)\wcsutil.obj" \
	"$(INTDIR)\imcompress.obj" \
	"$(INTDIR)\ricecomp.obj" \
	"$(INTDIR)\quantize.obj" \
	"$(INTDIR)\pliocomp.obj" \
	"$(INTDIR)\fits_hcompress.obj" \
	"$(INTDIR)\fits_hdecompress.obj" \
	"$(INTDIR)\zuncompress.obj" \
	"$(INTDIR)\zcompress.obj" \
	"$(INTDIR)\adler32.obj" \
	"$(INTDIR)\crc32.obj" \
	"$(INTDIR)\inffast.obj" \
	"$(INTDIR)\inftrees.obj" \
	"$(INTDIR)\trees.obj" \
	"$(INTDIR)\zutil.obj" \
	"$(INTDIR)\deflate.obj" \
	"$(INTDIR)\infback.obj" \
	"$(INTDIR)\inflate.obj" \
	"$(INTDIR)\uncompr.obj" 

"$(OUTDIR)\cfitsio.dll" : $(LINK32_OBJS) WINDUMP
	windumpexts -o $(DEF_FILE) cfitsio.dll $(LINK32_OBJS)
	$(LINK32) @<<
  $(LINK32_FLAGS) $(LINK32_OBJS)
<<

!ELSEIF  "$(CFG)" == "Win32 Debug"

OUTDIR=.
INTDIR=.\Debug
# Begin Custom Macros
OutDir=.
# End Custom Macros

ALL : "$(OUTDIR)\cfitsio.dll"


CLEAN :
	-@erase "$(INTDIR)\buffers.obj"
	-@erase "$(INTDIR)\cfileio.obj"
	-@erase "$(INTDIR)\checksum.obj"
	-@erase "$(INTDIR)\drvrfile.obj"
	-@erase "$(INTDIR)\drvrmem.obj"
	-@erase "$(INTDIR)\editcol.obj"
	-@erase "$(INTDIR)\edithdu.obj"
	-@erase "$(INTDIR)\eval_f.obj"
	-@erase "$(INTDIR)\eval_l.obj"
	-@erase "$(INTDIR)\eval_y.obj"
	-@erase "$(INTDIR)\fitscore.obj"
	-@erase "$(INTDIR)\f77_wrap1.obj"
	-@erase "$(INTDIR)\f77_wrap2.obj"
	-@erase "$(INTDIR)\f77_wrap3.obj"
	-@erase "$(INTDIR)\f77_wrap4.obj"
	-@erase "$(INTDIR)\getcol.obj"
	-@erase "$(INTDIR)\getcolb.obj"
	-@erase "$(INTDIR)\getcolsb.obj"
	-@erase "$(INTDIR)\getcold.obj"
	-@erase "$(INTDIR)\getcole.obj"
	-@erase "$(INTDIR)\getcoli.obj"
	-@erase "$(INTDIR)\getcolj.obj"
	-@erase "$(INTDIR)\getcolk.obj"
	-@erase "$(INTDIR)\getcoll.obj"
	-@erase "$(INTDIR)\getcols.obj"
	-@erase "$(INTDIR)\getcolui.obj"
	-@erase "$(INTDIR)\getcoluj.obj"
	-@erase "$(INTDIR)\getcoluk.obj"
	-@erase "$(INTDIR)\getkey.obj"
	-@erase "$(INTDIR)\group.obj"
	-@erase "$(INTDIR)\grparser.obj"
	-@erase "$(INTDIR)\histo.obj"
	-@erase "$(INTDIR)\iraffits.obj"
	-@erase "$(INTDIR)\modkey.obj"
	-@erase "$(INTDIR)\putcol.obj"
	-@erase "$(INTDIR)\putcolb.obj"
	-@erase "$(INTDIR)\putcolsb.obj"
	-@erase "$(INTDIR)\putcold.obj"
	-@erase "$(INTDIR)\putcole.obj"
	-@erase "$(INTDIR)\putcoli.obj"
	-@erase "$(INTDIR)\putcolj.obj"
	-@erase "$(INTDIR)\putcolk.obj"
	-@erase "$(INTDIR)\putcoll.obj"
	-@erase "$(INTDIR)\putcols.obj"
	-@erase "$(INTDIR)\putcolu.obj"
	-@erase "$(INTDIR)\putcolui.obj"
	-@erase "$(INTDIR)\putcoluj.obj"
	-@erase "$(INTDIR)\putcoluk.obj"
	-@erase "$(INTDIR)\putkey.obj"
	-@erase "$(INTDIR)\region.obj"
	-@erase "$(INTDIR)\scalnull.obj"
	-@erase "$(INTDIR)\swapproc.obj"
	-@erase "$(INTDIR)\vc60.idb"
	-@erase "$(INTDIR)\vc60.pdb"
	-@erase "$(INTDIR)\wcssub.obj"
	-@erase "$(INTDIR)\wcsutil.obj"
	-@erase "$(INTDIR)\imcompress.obj"
	-@erase "$(INTDIR)\ricecomp.obj"
	-@erase "$(INTDIR)\quantize.obj"
	-@erase "$(INTDIR)\pliocomp.obj"
	-@erase "$(INTDIR)\fits_hcompress.obj"
	-@erase "$(INTDIR)\fits_hdecompress.obj"
	-@erase "$(INTDIR)\zuncompress.obj"
	-@erase "$(INTDIR)\zcompress.obj"
	-@erase "$(INTDIR)\adler32.obj"
	-@erase "$(INTDIR)\crc32.obj"
	-@erase "$(INTDIR)\inffast.obj"
	-@erase "$(INTDIR)\inftrees.obj"
	-@erase "$(INTDIR)\trees.obj"
	-@erase "$(INTDIR)\zutil.obj"
	-@erase "$(INTDIR)\deflate.obj"
	-@erase "$(INTDIR)\infback.obj"
	-@erase "$(INTDIR)\inflate.obj"
	-@erase "$(INTDIR)\uncompr.obj"
	-@erase "$(OUTDIR)\cfitsio.dll"
	-@erase "$(OUTDIR)\cfitsio.exp"
	-@erase "$(OUTDIR)\cfitsio.ilk"
	-@erase "$(OUTDIR)\cfitsio.lib"
	-@erase "$(OUTDIR)\cfitsio.pdb"

"$(OUTDIR)" :
    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"

"$(INTDIR)" :
    if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"

CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /D "__WIN32__" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CFITSIO_EXPORTS" /D "_CRT_SECURE_NO_DEPRECATE" /Fp"$(INTDIR)\cfitsio.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c 
MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 
BSC32=bscmake.exe
BSC32_FLAGS=/nologo /o"$(OUTDIR)\cfitsio.bsc" 
BSC32_SBRS= \
	
LINK32=link.exe
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\cfitsio.pdb" /debug /machine:I386 /def:".\cfitsio.def" /out:"$(OUTDIR)\cfitsio.dll" /implib:"$(OUTDIR)\cfitsio.lib" /pdbtype:sept 
DEF_FILE= ".\cfitsio.def"
LINK32_OBJS= \
	"$(INTDIR)\buffers.obj" \
	"$(INTDIR)\cfileio.obj" \
	"$(INTDIR)\checksum.obj" \
	"$(INTDIR)\drvrfile.obj" \
	"$(INTDIR)\drvrmem.obj" \
	"$(INTDIR)\editcol.obj" \
	"$(INTDIR)\edithdu.obj" \
	"$(INTDIR)\eval_f.obj" \
	"$(INTDIR)\eval_l.obj" \
	"$(INTDIR)\eval_y.obj" \
	"$(INTDIR)\fitscore.obj" \
	"$(INTDIR)\f77_wrap1.obj" \
	"$(INTDIR)\f77_wrap2.obj" \
	"$(INTDIR)\f77_wrap3.obj" \
	"$(INTDIR)\f77_wrap4.obj" \
	"$(INTDIR)\getcol.obj" \
	"$(INTDIR)\getcolb.obj" \
	"$(INTDIR)\getcolsb.obj" \
	"$(INTDIR)\getcold.obj" \
	"$(INTDIR)\getcole.obj" \
	"$(INTDIR)\getcoli.obj" \
	"$(INTDIR)\getcolj.obj" \
	"$(INTDIR)\getcolk.obj" \
	"$(INTDIR)\getcoll.obj" \
	"$(INTDIR)\getcols.obj" \
	"$(INTDIR)\getcolui.obj" \
	"$(INTDIR)\getcoluj.obj" \
	"$(INTDIR)\getcoluk.obj" \
	"$(INTDIR)\getkey.obj" \
	"$(INTDIR)\group.obj" \
	"$(INTDIR)\grparser.obj" \
	"$(INTDIR)\histo.obj" \
	"$(INTDIR)\iraffits.obj" \
	"$(INTDIR)\modkey.obj" \
	"$(INTDIR)\putcol.obj" \
	"$(INTDIR)\putcolb.obj" \
	"$(INTDIR)\putcolsb.obj" \
	"$(INTDIR)\putcold.obj" \
	"$(INTDIR)\putcole.obj" \
	"$(INTDIR)\putcoli.obj" \
	"$(INTDIR)\putcolj.obj" \
	"$(INTDIR)\putcolk.obj" \
	"$(INTDIR)\putcoll.obj" \
	"$(INTDIR)\putcols.obj" \
	"$(INTDIR)\putcolu.obj" \
	"$(INTDIR)\putcolui.obj" \
	"$(INTDIR)\putcoluj.obj" \
	"$(INTDIR)\putcoluk.obj" \
	"$(INTDIR)\putkey.obj" \
	"$(INTDIR)\region.obj" \
	"$(INTDIR)\scalnull.obj" \
	"$(INTDIR)\swapproc.obj" \
	"$(INTDIR)\wcssub.obj" \
	"$(INTDIR)\wcsutil.obj" \
	"$(INTDIR)\imcompress.obj" \
	"$(INTDIR)\ricecomp.obj" \
	"$(INTDIR)\quantize.obj" \
	"$(INTDIR)\pliocomp.obj" \
	"$(INTDIR)\fits_hcompress.obj" \
	"$(INTDIR)\fits_hdecompress.obj" \
	"$(INTDIR)\zuncompress.obj" \
	"$(INTDIR)\zcompress.obj" \
	"$(INTDIR)\adler32.obj" \
	"$(INTDIR)\crc32.obj" \
	"$(INTDIR)\inffast.obj" \
	"$(INTDIR)\inftrees.obj" \
	"$(INTDIR)\trees.obj" \
	"$(INTDIR)\zutil.obj" \
	"$(INTDIR)\deflate.obj" \
	"$(INTDIR)\infback.obj" \
	"$(INTDIR)\inflate.obj" \
	"$(INTDIR)\uncompr.obj" 

"$(OUTDIR)\cfitsio.dll" : $(LINK32_OBJS) WINDUMP
	windumpexts -o $(DEF_FILE) cfitsio.dll $(LINK32_OBJS)    
	$(LINK32) @<<
	$(LINK32_FLAGS) $(LINK32_OBJS)
<<

!ENDIF 

.c{$(INTDIR)}.obj::
   $(CPP) @<<
   $(CPP_PROJ) $< 
<<

.cpp{$(INTDIR)}.obj::
   $(CPP) @<<
   $(CPP_PROJ) $< 
<<

.cxx{$(INTDIR)}.obj::
   $(CPP) @<<
   $(CPP_PROJ) $< 
<<

.c{$(INTDIR)}.sbr::
   $(CPP) @<<
   $(CPP_PROJ) $< 
<<

.cpp{$(INTDIR)}.sbr::
   $(CPP) @<<
   $(CPP_PROJ) $< 
<<

.cxx{$(INTDIR)}.sbr::
   $(CPP) @<<
   $(CPP_PROJ) $< 
<<


!IF "$(NO_EXTERNAL_DEPS)" != "1"
!IF EXISTS("cfitsio.dep")
!INCLUDE "cfitsio.dep"
!ELSE 
!MESSAGE Warning: cannot find "cfitsio.dep"
!ENDIF 
!ENDIF 


!IF "$(CFG)" == "Win32 Release" || "$(CFG)" == "Win32 Debug"
SOURCE=.\buffers.c

"$(INTDIR)\buffers.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\cfileio.c

"$(INTDIR)\cfileio.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\checksum.c

"$(INTDIR)\checksum.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\drvrfile.c

"$(INTDIR)\drvrfile.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\drvrmem.c

"$(INTDIR)\drvrmem.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\editcol.c

"$(INTDIR)\editcol.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\edithdu.c

"$(INTDIR)\edithdu.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\eval_f.c

"$(INTDIR)\eval_f.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\eval_l.c

"$(INTDIR)\eval_l.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\eval_y.c

"$(INTDIR)\eval_y.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\fitscore.c

"$(INTDIR)\fitscore.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\f77_wrap1.c

"$(INTDIR)\f77_wrap1.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\f77_wrap2.c

"$(INTDIR)\f77_wrap2.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\f77_wrap3.c

"$(INTDIR)\f77_wrap3.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\f77_wrap4.c

"$(INTDIR)\f77_wrap4.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\getcol.c

"$(INTDIR)\getcol.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\getcolb.c

"$(INTDIR)\getcolb.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\getcolsb.c

"$(INTDIR)\getcolsb.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\getcold.c

"$(INTDIR)\getcold.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\getcole.c

"$(INTDIR)\getcole.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\getcoli.c

"$(INTDIR)\getcoli.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\getcolj.c

"$(INTDIR)\getcolj.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\getcolk.c

"$(INTDIR)\getcolk.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\getcoll.c

"$(INTDIR)\getcoll.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\getcols.c

"$(INTDIR)\getcols.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\getcolui.c

"$(INTDIR)\getcolui.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\getcoluj.c

"$(INTDIR)\getcoluj.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\getcoluk.c

"$(INTDIR)\getcoluk.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\getkey.c

"$(INTDIR)\getkey.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\group.c

"$(INTDIR)\group.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\grparser.c

"$(INTDIR)\grparser.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\histo.c

"$(INTDIR)\histo.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\iraffits.c

"$(INTDIR)\iraffits.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\modkey.c

"$(INTDIR)\modkey.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\putcol.c

"$(INTDIR)\putcol.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\putcolb.c

"$(INTDIR)\putcolb.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\putcolsb.c

"$(INTDIR)\putcolsb.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\putcold.c

"$(INTDIR)\putcold.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\putcole.c

"$(INTDIR)\putcole.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\putcoli.c

"$(INTDIR)\putcoli.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\putcolj.c

"$(INTDIR)\putcolj.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\putcolk.c

"$(INTDIR)\putcolk.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\putcoll.c

"$(INTDIR)\putcoll.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\putcols.c

"$(INTDIR)\putcols.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\putcolu.c

"$(INTDIR)\putcolu.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\putcolui.c

"$(INTDIR)\putcolui.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\putcoluj.c

"$(INTDIR)\putcoluj.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\putcoluk.c

"$(INTDIR)\putcoluk.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\putkey.c

"$(INTDIR)\putkey.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\region.c

"$(INTDIR)\region.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\scalnull.c

"$(INTDIR)\scalnull.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\swapproc.c

"$(INTDIR)\swapproc.obj" : $(SOURCE) "$(INTDIR)"


SOURCE=.\wcssub.c

"$(INTDIR)\wcssub.obj" : $(SOURCE) "$(INTDIR)"

SOURCE=.\wcsutil.c

"$(INTDIR)\wcsutil.obj" : $(SOURCE) "$(INTDIR)"

SOURCE=imcompress.c

"$(INTDIR)\imcompress.obj" : $(SOURCE) "$(INTDIR)"

SOURCE=ricecomp.c

"$(INTDIR)\ricecomp.obj" : $(SOURCE) "$(INTDIR)"

SOURCE=quantize.c

"$(INTDIR)\quantize.obj" : $(SOURCE) "$(INTDIR)"

SOURCE=pliocomp.c

"$(INTDIR)\pliocomp.obj" : $(SOURCE) "$(INTDIR)"

SOURCE=fits_hcompress.c

"$(INTDIR)\fits_hcompress.obj" : $(SOURCE) "$(INTDIR)"

SOURCE=fits_hdecompress.c

"$(INTDIR)\fits_hdecompress.obj" : $(SOURCE) "$(INTDIR)"

SOURCE=zuncompress.c

"$(INTDIR)\zuncompress.obj" : $(SOURCE) "$(INTDIR)"

SOURCE=zcompress.c

"$(INTDIR)\zcompress.obj" : $(SOURCE) "$(INTDIR)"

SOURCE=adler32.c

"$(INTDIR)\adler32.obj" : $(SOURCE) "$(INTDIR)"

SOURCE=crc32.c

"$(INTDIR)\crc32.obj" : $(SOURCE) "$(INTDIR)"

SOURCE=inffast.c

"$(INTDIR)\inffast.obj" : $(SOURCE) "$(INTDIR)"

SOURCE=inftrees.c

"$(INTDIR)\inftrees.obj" : $(SOURCE) "$(INTDIR)"

SOURCE=trees.c

"$(INTDIR)\trees.obj" : $(SOURCE) "$(INTDIR)"

SOURCE=zutil.c

"$(INTDIR)\zutil.obj" : $(SOURCE) "$(INTDIR)"

SOURCE=deflate.c

"$(INTDIR)\deflate.obj" : $(SOURCE) "$(INTDIR)"

SOURCE=infback.c

"$(INTDIR)\infback.obj" : $(SOURCE) "$(INTDIR)"

SOURCE=inflate.c

"$(INTDIR)\inflate.obj" : $(SOURCE) "$(INTDIR)"

SOURCE=uncompr.c

"$(INTDIR)\uncompr.obj" : $(SOURCE) "$(INTDIR)"

!ENDIF 

$(DEF_FILE):  



WINDUMP:
	nmake -f winDumpExts.mak
cfitsio/makepc.bat0000644000225700000360000000440313246025103013731 0ustar  cagordonlhearem:  this batch file builds the cfitsio library 
rem:  using the Borland C++ v4.5 or new free v5.5 compiler
rem:
bcc32 -c buffers.c
bcc32 -c cfileio.c
bcc32 -c checksum.c
bcc32 -c drvrfile.c
bcc32 -c drvrmem.c
bcc32 -c editcol.c
bcc32 -c edithdu.c
bcc32 -c eval_l.c
bcc32 -c eval_y.c
bcc32 -c eval_f.c
bcc32 -c fitscore.c
bcc32 -c getcol.c
bcc32 -c getcolb.c
bcc32 -c getcolsb.c
bcc32 -c getcoli.c
bcc32 -c getcolj.c
bcc32 -c getcolui.c
bcc32 -c getcoluj.c
bcc32 -c getcoluk.c
bcc32 -c getcolk.c
bcc32 -c getcole.c
bcc32 -c getcold.c
bcc32 -c getcoll.c
bcc32 -c getcols.c
bcc32 -c getkey.c
bcc32 -c group.c
bcc32 -c grparser.c
bcc32 -c histo.c
bcc32 -c iraffits.c
bcc32 -c modkey.c
bcc32 -c putcol.c
bcc32 -c putcolb.c
bcc32 -c putcolsb.c
bcc32 -c putcoli.c
bcc32 -c putcolj.c
bcc32 -c putcolui.c
bcc32 -c putcoluj.c
bcc32 -c putcoluk.c
bcc32 -c putcolk.c
bcc32 -c putcole.c
bcc32 -c putcold.c
bcc32 -c putcols.c
bcc32 -c putcoll.c
bcc32 -c putcolu.c
bcc32 -c putkey.c
bcc32 -c region.c
bcc32 -c scalnull.c
bcc32 -c swapproc.c
bcc32 -c wcsutil.c
bcc32 -c wcssub.c
bcc32 -c imcompress.c
bcc32 -c quantize.c
bcc32 -c ricecomp.c
bcc32 -c pliocomp.c
bcc32 -c fits_hcompress.c
bcc32 -c fits_hdecompress.c
bcc32 -c zuncompress.c
bcc32 -c zcompress.c
bcc32 -c adler32.c
bcc32 -c crc32.c
bcc32 -c inffast.c
bcc32 -c inftrees.c
bcc32 -c trees.c
bcc32 -c zutil.c
bcc32 -c deflate.c
bcc32 -c infback.c
bcc32 -c inflate.c
bcc32 -c uncompr.c
del cfitsio.lib
tlib cfitsio +buffers +cfileio +checksum +drvrfile +drvrmem 
tlib cfitsio +editcol +edithdu +eval_l +eval_y +eval_f +fitscore
tlib cfitsio +getcol +getcolb +getcolsb +getcoli +getcolj +getcolk +getcoluk 
tlib cfitsio +getcolui +getcoluj +getcole +getcold +getcoll +getcols
tlib cfitsio +getkey +group +grparser +histo +iraffits +modkey +putkey 
tlib cfitsio +putcol  +putcolb +putcoli +putcolj +putcolk +putcole +putcold
tlib cfitsio +putcoll +putcols +putcolu +putcolui +putcoluj +putcoluk
tlib cfitsio +region +scalnull +swapproc +wcsutil +wcssub +putcolsb
tlib cfitsio +imcompress +quantize +ricecomp +pliocomp
tlib cfitsio +fits_hcompress +fits_hdecompress
tlib cfitsio +zuncompress +zcompress +adler32 +crc32 +inffast
tlib cfitsio +inftrees +trees +zutil +deflate +infback +inflate +uncompr
bcc32 -f testprog.c cfitsio.lib
bcc32 -f cookbook.c cfitsio.lib

cfitsio/modkey.c0000644000225700000360000017526613246025103013455 0ustar  cagordonlhea/*  This file, modkey.c, contains routines that modify, insert, or update  */
/*  keywords in a FITS header.                                             */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
/* stddef.h is apparently needed to define size_t */
#include 
#include 
#include 
#include "fitsio2.h"
/*--------------------------------------------------------------------------*/
int ffuky( fitsfile *fptr,     /* I - FITS file pointer        */
           int  datatype,      /* I - datatype of the value    */
           const char *keyname,/* I - name of keyword to write */
           void *value,        /* I - keyword value            */
           const char *comm,   /* I - keyword comment          */
           int  *status)       /* IO - error status            */
/*
  Update the keyword, value and comment in the FITS header.
  The datatype is specified by the 2nd argument.
*/
{
    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (datatype == TSTRING)
    {
        ffukys(fptr, keyname, (char *) value, comm, status);
    }
    else if (datatype == TBYTE)
    {
        ffukyj(fptr, keyname, (LONGLONG) *(unsigned char *) value, comm, status);
    }
    else if (datatype == TSBYTE)
    {
        ffukyj(fptr, keyname, (LONGLONG) *(signed char *) value, comm, status);
    }
    else if (datatype == TUSHORT)
    {
        ffukyj(fptr, keyname, (LONGLONG) *(unsigned short *) value, comm, status);
    }
    else if (datatype == TSHORT)
    {
        ffukyj(fptr, keyname, (LONGLONG) *(short *) value, comm, status);
    }
    else if (datatype == TINT)
    {
        ffukyj(fptr, keyname, (LONGLONG) *(int *) value, comm, status);
    }
    else if (datatype == TUINT)
    {
        ffukyg(fptr, keyname, (double) *(unsigned int *) value, 0,
               comm, status);
    }
    else if (datatype == TLOGICAL)
    {
        ffukyl(fptr, keyname, *(int *) value, comm, status);
    }
    else if (datatype == TULONG)
    {
        ffukyg(fptr, keyname, (double) *(unsigned long *) value, 0,
               comm, status);
    }
    else if (datatype == TLONG)
    {
        ffukyj(fptr, keyname, (LONGLONG) *(long *) value, comm, status);
    }
    else if (datatype == TLONGLONG)
    {
        ffukyj(fptr, keyname, *(LONGLONG *) value, comm, status);
    }
    else if (datatype == TFLOAT)
    {
        ffukye(fptr, keyname, *(float *) value, -7, comm, status);
    }
    else if (datatype == TDOUBLE)
    {
        ffukyd(fptr, keyname, *(double *) value, -15, comm, status);
    }
    else if (datatype == TCOMPLEX)
    {
        ffukyc(fptr, keyname, (float *) value, -7, comm, status);
    }
    else if (datatype == TDBLCOMPLEX)
    {
        ffukym(fptr, keyname, (double *) value, -15, comm, status);
    }
    else
        *status = BAD_DATATYPE;

    return(*status);
} 
/*--------------------------------------------------------------------------*/
int ffukyu(fitsfile *fptr,      /* I - FITS file pointer  */
           const char *keyname, /* I - keyword name       */
           const char *comm,    /* I - keyword comment    */
           int *status)         /* IO - error status      */
{
    int tstatus;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    tstatus = *status;

    if (ffmkyu(fptr, keyname, comm, status) == KEY_NO_EXIST)
    {
        *status = tstatus;
        ffpkyu(fptr, keyname, comm, status);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffukys(fitsfile *fptr,       /* I - FITS file pointer  */
           const char *keyname,  /* I - keyword name       */
           const char *value,    /* I - keyword value      */
           const char *comm,     /* I - keyword comment    */
           int *status)          /* IO - error status      */ 
{
    int tstatus;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    tstatus = *status;

    if (ffmkys(fptr, keyname, value, comm, status) == KEY_NO_EXIST)
    {
        *status = tstatus;
        ffpkys(fptr, keyname, value, comm, status);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffukls(fitsfile *fptr,      /* I - FITS file pointer  */
           const char *keyname, /* I - keyword name       */
           const char *value,   /* I - keyword value      */
           const char *comm,    /* I - keyword comment    */
           int *status)         /* IO - error status      */ 
{
    /* update a long string keyword */

    int tstatus;
    char junk[FLEN_ERRMSG];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    tstatus = *status;

    if (ffmkls(fptr, keyname, value, comm, status) == KEY_NO_EXIST)
    {
        /* since the ffmkls call failed, it wrote a bogus error message */
        fits_read_errmsg(junk);  /* clear the error message */
	
        *status = tstatus;
        ffpkls(fptr, keyname, value, comm, status);
    }
    return(*status);
}/*--------------------------------------------------------------------------*/
int ffukyl(fitsfile *fptr,     /* I - FITS file pointer  */
           const char *keyname,/* I - keyword name       */
           int value,          /* I - keyword value      */
           const char *comm,   /* I - keyword comment    */
           int *status)        /* IO - error status      */
{
    int tstatus;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    tstatus = *status;

    if (ffmkyl(fptr, keyname, value, comm, status) == KEY_NO_EXIST)
    {
        *status = tstatus;
        ffpkyl(fptr, keyname, value, comm, status);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffukyj(fitsfile *fptr,     /* I - FITS file pointer  */
           const char *keyname,/* I - keyword name       */
           LONGLONG value,     /* I - keyword value      */
           const char *comm,   /* I - keyword comment    */
           int *status)        /* IO - error status      */
{
    int tstatus;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    tstatus = *status;

    if (ffmkyj(fptr, keyname, value, comm, status) == KEY_NO_EXIST)
    {
        *status = tstatus;
        ffpkyj(fptr, keyname, value, comm, status);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffukyf(fitsfile *fptr,     /* I - FITS file pointer  */
           const char *keyname,/* I - keyword name       */
           float value,        /* I - keyword value      */
           int decim,          /* I - no of decimals     */         
           const char *comm,   /* I - keyword comment    */
           int *status)        /* IO - error status      */
{
    int tstatus;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    tstatus = *status;

    if (ffmkyf(fptr, keyname, value, decim, comm, status) == KEY_NO_EXIST)
    {
        *status = tstatus;
        ffpkyf(fptr, keyname, value, decim, comm, status);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffukye(fitsfile *fptr,     /* I - FITS file pointer  */
           const char *keyname,/* I - keyword name       */
           float value,        /* I - keyword value      */
           int decim,          /* I - no of decimals     */
           const char *comm,   /* I - keyword comment    */
           int *status)        /* IO - error status      */
{
    int tstatus;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    tstatus = *status;

    if (ffmkye(fptr, keyname, value, decim, comm, status) == KEY_NO_EXIST)
    {
        *status = tstatus;
        ffpkye(fptr, keyname, value, decim, comm, status);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffukyg(fitsfile *fptr,     /* I - FITS file pointer  */
           const char *keyname,/* I - keyword name       */
           double value,       /* I - keyword value      */
           int decim,          /* I - no of decimals     */
           const char *comm,   /* I - keyword comment    */
           int *status)        /* IO - error status      */
{
    int tstatus;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    tstatus = *status;

    if (ffmkyg(fptr, keyname, value, decim, comm, status) == KEY_NO_EXIST)
    {
        *status = tstatus;
        ffpkyg(fptr, keyname, value, decim, comm, status);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffukyd(fitsfile *fptr,     /* I - FITS file pointer  */
           const char *keyname,/* I - keyword name       */
           double value,       /* I - keyword value      */
           int decim,          /* I - no of decimals     */
           const char *comm,   /* I - keyword comment    */
           int *status)        /* IO - error status      */
{
    int tstatus;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    tstatus = *status;

    if (ffmkyd(fptr, keyname, value, decim, comm, status) == KEY_NO_EXIST)
    {
        *status = tstatus;
        ffpkyd(fptr, keyname, value, decim, comm, status);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffukfc(fitsfile *fptr,     /* I - FITS file pointer  */
           const char *keyname,/* I - keyword name       */
           float *value,       /* I - keyword value      */
           int decim,          /* I - no of decimals     */         
           const char *comm,   /* I - keyword comment    */
           int *status)        /* IO - error status      */
{
    int tstatus;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    tstatus = *status;

    if (ffmkfc(fptr, keyname, value, decim, comm, status) == KEY_NO_EXIST)
    {
        *status = tstatus;
        ffpkfc(fptr, keyname, value, decim, comm, status);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffukyc(fitsfile *fptr,     /* I - FITS file pointer  */
           const char *keyname,/* I - keyword name       */
           float *value,       /* I - keyword value      */
           int decim,          /* I - no of decimals     */
           const char *comm,   /* I - keyword comment    */
           int *status)        /* IO - error status      */
{
    int tstatus;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    tstatus = *status;

    if (ffmkyc(fptr, keyname, value, decim, comm, status) == KEY_NO_EXIST)
    {
        *status = tstatus;
        ffpkyc(fptr, keyname, value, decim, comm, status);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffukfm(fitsfile *fptr,     /* I - FITS file pointer  */
           const char *keyname,/* I - keyword name       */
           double *value,      /* I - keyword value      */
           int decim,          /* I - no of decimals     */
           const char *comm,   /* I - keyword comment    */
           int *status)        /* IO - error status      */
{
    int tstatus;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    tstatus = *status;

    if (ffmkfm(fptr, keyname, value, decim, comm, status) == KEY_NO_EXIST)
    {
        *status = tstatus;
        ffpkfm(fptr, keyname, value, decim, comm, status);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffukym(fitsfile *fptr,     /* I - FITS file pointer  */
           const char *keyname,/* I - keyword name       */
           double *value,      /* I - keyword value      */
           int decim,          /* I - no of decimals     */
           const char *comm,   /* I - keyword comment    */
           int *status)        /* IO - error status      */
{
    int tstatus;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    tstatus = *status;

    if (ffmkym(fptr, keyname, value, decim, comm, status) == KEY_NO_EXIST)
    {
        *status = tstatus;
        ffpkym(fptr, keyname, value, decim, comm, status);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffucrd(fitsfile *fptr,     /* I - FITS file pointer  */
           const char *keyname,/* I - keyword name       */
           const char *card,   /* I - card string value  */
           int *status)        /* IO - error status      */
{
    int tstatus;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    tstatus = *status;

    if (ffmcrd(fptr, keyname, card, status) == KEY_NO_EXIST)
    {
        *status = tstatus;
        ffprec(fptr, card, status);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffmrec(fitsfile *fptr,    /* I - FITS file pointer               */
           int nkey,          /* I - number of the keyword to modify */
           const char *card,  /* I - card string value               */
           int *status)       /* IO - error status                   */
{
    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    ffmaky(fptr, nkey+1, status);
    ffmkey(fptr, card, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffmcrd(fitsfile *fptr,      /* I - FITS file pointer  */
           const char *keyname, /* I - keyword name       */
           const char *card,    /* I - card string value  */
           int *status)         /* IO - error status      */
{
    char tcard[FLEN_CARD], valstring[FLEN_CARD], comm[FLEN_CARD], value[FLEN_CARD];
    char nextcomm[FLEN_COMMENT];
    int keypos, len;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (ffgcrd(fptr, keyname, tcard, status) > 0)
        return(*status);

    ffmkey(fptr, card, status);

    /* calc position of keyword in header */
    keypos = (int) ((((fptr->Fptr)->nextkey) - ((fptr->Fptr)->headstart[(fptr->Fptr)->curhdu])) / 80) + 1;

    ffpsvc(tcard, valstring, comm, status);

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /* check for string value which may be continued over multiple keywords */
    ffpmrk(); /* put mark on message stack; erase any messages after this */
    ffc2s(valstring, value, status);   /* remove quotes and trailing spaces */

    if (*status == VALUE_UNDEFINED) {
       ffcmrk();  /* clear any spurious error messages, back to the mark */
       *status = 0;
    } else {
 
      len = strlen(value);

      while (len && value[len - 1] == '&')  /* ampersand used as continuation char */
      {
        ffgcnt(fptr, value, nextcomm, status);
        if (*value)
        {
            ffdrec(fptr, keypos, status);  /* delete the keyword */
            len = strlen(value);
        }
        else   /* a null valstring indicates no continuation */
            len = 0;
      }
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffmnam(fitsfile *fptr,     /* I - FITS file pointer     */
           const char *oldname,/* I - existing keyword name */
           const char *newname,/* I - new name for keyword  */
           int *status)        /* IO - error status         */
{
    char comm[FLEN_COMMENT];
    char value[FLEN_VALUE];
    char card[FLEN_CARD];
 
    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (ffgkey(fptr, oldname, value, comm, status) > 0)
        return(*status);

    ffmkky(newname, value, comm, card, status);  /* construct the card */
    ffmkey(fptr, card, status);  /* rewrite with new name */

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffmcom(fitsfile *fptr,     /* I - FITS file pointer  */
           const char *keyname,/* I - keyword name       */
           const char *comm,   /* I - keyword comment    */
           int *status)        /* IO - error status      */
{
    char oldcomm[FLEN_COMMENT];
    char value[FLEN_VALUE];
    char card[FLEN_CARD];
 
    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (ffgkey(fptr, keyname, value, oldcomm, status) > 0)
        return(*status);

    ffmkky(keyname, value, comm, card, status);  /* construct the card */
    ffmkey(fptr, card, status);  /* rewrite with new comment */

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpunt(fitsfile *fptr,     /* I - FITS file pointer   */
           const char *keyname,/* I - keyword name        */
           const char *unit,   /* I - keyword unit string */
           int *status)        /* IO - error status       */
/*
    Write (put) the units string into the comment field of the existing keyword.
    This routine uses a  FITS convention  in which the units are enclosed in 
    square brackets following the '/' comment field delimiter, e.g.:

    KEYWORD =                   12 / [kpc] comment string goes here
*/
{
    char oldcomm[FLEN_COMMENT];
    char newcomm[FLEN_COMMENT];
    char value[FLEN_VALUE];
    char card[FLEN_CARD];
    char *loc;
    size_t len;
 
    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (ffgkey(fptr, keyname, value, oldcomm, status) > 0)
        return(*status);

    /* copy the units string to the new comment string if not null */
    if (*unit)
    {
        strcpy(newcomm, "[");
        strncat(newcomm, unit, 45);  /* max allowed length is about 45 chars */
        strcat(newcomm, "] ");
        len = strlen(newcomm);  
        len = FLEN_COMMENT - len - 1;  /* amount of space left in the field */
    }
    else
    {
        newcomm[0] = '\0';
        len = FLEN_COMMENT - 1;
    }

    if (oldcomm[0] == '[')  /* check for existing units field */
    {
        loc = strchr(oldcomm, ']');  /* look for the closing bracket */
        if (loc)
        {
            loc++;
            while (*loc == ' ')   /* skip any blank spaces */
               loc++;

            strncat(newcomm, loc, len);  /* concat remainder of comment */
        }
        else
        {
            strncat(newcomm, oldcomm, len);  /* append old comment onto new */
        }
    }
    else
    {
        strncat(newcomm, oldcomm, len);
    }

    ffmkky(keyname, value, newcomm, card, status);  /* construct the card */
    ffmkey(fptr, card, status);  /* rewrite with new units string */

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffmkyu(fitsfile *fptr,     /* I - FITS file pointer  */
           const char *keyname,/* I - keyword name       */
           const char *comm,   /* I - keyword comment    */
           int *status)        /* IO - error status      */
{
    char valstring[FLEN_VALUE];
    char oldcomm[FLEN_COMMENT];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
        return(*status);                               /* get old comment */

    strcpy(valstring," ");  /* create a dummy value string */

    if (!comm || comm[0] == '&')  /* preserve the current comment string */
        ffmkky(keyname, valstring, oldcomm, card, status);
    else
        ffmkky(keyname, valstring, comm, card, status);

    ffmkey(fptr, card, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffmkys(fitsfile *fptr,          /* I - FITS file pointer  */
           const char *keyname,     /* I - keyword name       */
           const char *value,       /* I - keyword value      */
           const char *comm,        /* I - keyword comment    */
           int *status)             /* IO - error status      */
{
  /* NOTE: This routine does not support long continued strings */
  /*  It will correctly overwrite an existing long continued string, */
  /*  but it will not write a new long string.  */

    char oldval[FLEN_VALUE], valstring[FLEN_VALUE];
    char oldcomm[FLEN_COMMENT];
    char card[FLEN_CARD], nextcomm[FLEN_COMMENT];
    int len, keypos;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (ffgkey(fptr, keyname, oldval, oldcomm, status) > 0)
        return(*status);                               /* get old comment */

    ffs2c(value, valstring, status);   /* convert value to a string */

    if (!comm || comm[0] == '&')  /* preserve the current comment string */
        ffmkky(keyname, valstring, oldcomm, card, status);
    else
        ffmkky(keyname, valstring, comm, card, status);

    ffmkey(fptr, card, status); /* overwrite the previous keyword */

    keypos = (int) (((((fptr->Fptr)->nextkey) - ((fptr->Fptr)->headstart[(fptr->Fptr)->curhdu])) / 80) + 1);

    if (*status > 0)           
        return(*status);

    /* check if old string value was continued over multiple keywords */
    ffpmrk(); /* put mark on message stack; erase any messages after this */
    ffc2s(oldval, valstring, status); /* remove quotes and trailing spaces */

    if (*status == VALUE_UNDEFINED) {
       ffcmrk();  /* clear any spurious error messages, back to the mark */
       *status = 0;
    } else {
        
      len = strlen(valstring);

      while (len && valstring[len - 1] == '&')  /* ampersand is continuation char */
      {
        ffgcnt(fptr, valstring, nextcomm, status);
        if (*valstring)
        {
            ffdrec(fptr, keypos, status);  /* delete the continuation */
            len = strlen(valstring);
        }
        else   /* a null valstring indicates no continuation */
            len = 0;
      }
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffmkls( fitsfile *fptr,           /* I - FITS file pointer        */
            const char *keyname,      /* I - name of keyword to write */
            const char *value,        /* I - keyword value            */
            const char *incomm,       /* I - keyword comment          */
            int  *status)             /* IO - error status            */
/*
  Modify the value and optionally the comment of a long string keyword.
  This routine supports the
  HEASARC long string convention and can modify arbitrarily long string
  keyword values.  The value is continued over multiple keywords that
  have the name COMTINUE without an equal sign in column 9 of the card.
  This routine also supports simple string keywords which are less than
  69 characters in length.

  This routine is not very efficient, so it should be used sparingly.
*/
{
    char valstring[FLEN_VALUE];
    char card[FLEN_CARD], tmpkeyname[FLEN_CARD];
    char comm[FLEN_COMMENT];
    char tstring[FLEN_VALUE], *cptr;
    char *longval;
    int next, remain, vlen, nquote, nchar, namelen, contin, tstatus = -1;
    int nkeys, keypos;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (!incomm || incomm[0] == '&')  /* preserve the old comment string */
    {
        ffghps(fptr, &nkeys, &keypos, status); /* save current position */

        if (ffgkls(fptr, keyname, &longval, comm, status) > 0)
            return(*status);            /* keyword doesn't exist */

        free(longval);  /* don't need the old value */

        /* move back to previous position to ensure that we delete */
        /* the right keyword in case there are more than one keyword */
        /* with this same name. */
        ffgrec(fptr, keypos - 1, card, status); 
    } else {
        /* copy the input comment string */
        strncpy(comm, incomm, FLEN_COMMENT-1);
        comm[FLEN_COMMENT-1] = '\0';
    }

    /* delete the old keyword */
    if (ffdkey(fptr, keyname, status) > 0)
        return(*status);            /* keyword doesn't exist */

    ffghps(fptr, &nkeys, &keypos, status); /* save current position */

    /* now construct the new keyword, and insert into header */
    remain = strlen(value);    /* number of characters to write out */
    next = 0;                  /* pointer to next character to write */
    
    /* count the number of single quote characters in the string */
    nquote = 0;
    cptr = strchr(value, '\'');   /* search for quote character */

    while (cptr)  /* search for quote character */
    {
        nquote++;            /*  increment no. of quote characters  */
        cptr++;              /*  increment pointer to next character */
        cptr = strchr(cptr, '\'');  /* search for another quote char */
    }

    strncpy(tmpkeyname, keyname, 80);
    tmpkeyname[80] = '\0';
    
    cptr = tmpkeyname;
    while(*cptr == ' ')   /* skip over leading spaces in name */
        cptr++;

    /* determine the number of characters that will fit on the line */
    /* Note: each quote character is expanded to 2 quotes */

    namelen = strlen(cptr);
    if (namelen <= 8 && (fftkey(cptr, &tstatus) <= 0) )
    {
        /* This a normal 8-character FITS keyword */
        nchar = 68 - nquote; /*  max of 68 chars fit in a FITS string value */
    }
    else
    {
	nchar = 80 - nquote - namelen - 5;
    }

    contin = 0;
    while (remain > 0)
    {
        strncpy(tstring, &value[next], nchar); /* copy string to temp buff */
        tstring[nchar] = '\0';
        ffs2c(tstring, valstring, status);  /* put quotes around the string */

        if (remain > nchar)   /* if string is continued, put & as last char */
        {
            vlen = strlen(valstring);
            nchar -= 1;        /* outputting one less character now */

            if (valstring[vlen-2] != '\'')
                valstring[vlen-2] = '&';  /*  over write last char with &  */
            else
            { /* last char was a pair of single quotes, so over write both */
                valstring[vlen-3] = '&';
                valstring[vlen-1] = '\0';
            }
        }

        if (contin)           /* This is a CONTINUEd keyword */
        {
           ffmkky("CONTINUE", valstring, comm, card, status); /* make keyword */
           strncpy(&card[8], "   ",  2);  /* overwrite the '=' */
        }
        else
        {
           ffmkky(keyname, valstring, comm, card, status);  /* make keyword */
        }

        ffirec(fptr, keypos, card, status);  /* insert the keyword */
       
        keypos++;        /* next insert position */
        contin = 1;
        remain -= nchar;
        next  += nchar;
        nchar = 68 - nquote;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffmkyl(fitsfile *fptr,          /* I - FITS file pointer  */
           const char *keyname,     /* I - keyword name       */
           int value,               /* I - keyword value      */
           const char *comm,        /* I - keyword comment    */
           int *status)             /* IO - error status      */
{
    char valstring[FLEN_VALUE];
    char oldcomm[FLEN_COMMENT];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
        return(*status);                               /* get old comment */

    ffl2c(value, valstring, status);   /* convert value to a string */

    if (!comm || comm[0] == '&')  /* preserve the current comment string */
        ffmkky(keyname, valstring, oldcomm, card, status);
    else
        ffmkky(keyname, valstring, comm, card, status);

    ffmkey(fptr, card, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffmkyj(fitsfile *fptr,          /* I - FITS file pointer  */
           const char *keyname,     /* I - keyword name       */
           LONGLONG value,          /* I - keyword value      */
           const char *comm,        /* I - keyword comment    */
           int *status)             /* IO - error status      */
{
    char valstring[FLEN_VALUE];
    char oldcomm[FLEN_COMMENT];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
        return(*status);                               /* get old comment */

    ffi2c(value, valstring, status);   /* convert value to a string */

    if (!comm || comm[0] == '&')  /* preserve the current comment string */
        ffmkky(keyname, valstring, oldcomm, card, status);
    else
        ffmkky(keyname, valstring, comm, card, status);

    ffmkey(fptr, card, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffmkyf(fitsfile *fptr,          /* I - FITS file pointer  */
           const char *keyname,     /* I - keyword name       */
           float value,             /* I - keyword value      */
           int decim,               /* I - no of decimals     */
           const char *comm,        /* I - keyword comment    */
           int *status)             /* IO - error status      */
{
    char valstring[FLEN_VALUE];
    char oldcomm[FLEN_COMMENT];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
        return(*status);                               /* get old comment */

    ffr2f(value, decim, valstring, status);   /* convert value to a string */

    if (!comm || comm[0] == '&')  /* preserve the current comment string */
        ffmkky(keyname, valstring, oldcomm, card, status);
    else
        ffmkky(keyname, valstring, comm, card, status);

    ffmkey(fptr, card, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffmkye(fitsfile *fptr,          /* I - FITS file pointer  */
           const char *keyname,     /* I - keyword name       */
           float value,             /* I - keyword value      */
           int decim,               /* I - no of decimals     */
           const char *comm,        /* I - keyword comment    */
           int *status)             /* IO - error status      */
{
    char valstring[FLEN_VALUE];
    char oldcomm[FLEN_COMMENT];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
        return(*status);                               /* get old comment */

    ffr2e(value, decim, valstring, status);   /* convert value to a string */

    if (!comm || comm[0] == '&')  /* preserve the current comment string */
        ffmkky(keyname, valstring, oldcomm, card, status);
    else
        ffmkky(keyname, valstring, comm, card, status);

    ffmkey(fptr, card, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffmkyg(fitsfile *fptr,          /* I - FITS file pointer  */
           const char *keyname,     /* I - keyword name       */
           double value,            /* I - keyword value      */
           int decim,               /* I - no of decimals     */
           const char *comm,        /* I - keyword comment    */
           int *status)             /* IO - error status      */
{
    char valstring[FLEN_VALUE];
    char oldcomm[FLEN_COMMENT];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
        return(*status);                               /* get old comment */

    ffd2f(value, decim, valstring, status);   /* convert value to a string */

    if (!comm || comm[0] == '&')  /* preserve the current comment string */
        ffmkky(keyname, valstring, oldcomm, card, status);
    else
        ffmkky(keyname, valstring, comm, card, status);

    ffmkey(fptr, card, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffmkyd(fitsfile *fptr,          /* I - FITS file pointer  */
           const char *keyname,     /* I - keyword name       */
           double value,            /* I - keyword value      */
           int decim,               /* I - no of decimals     */
           const char *comm,        /* I - keyword comment    */
           int *status)             /* IO - error status      */
{
    char valstring[FLEN_VALUE];
    char oldcomm[FLEN_COMMENT];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
        return(*status);                               /* get old comment */

    ffd2e(value, decim, valstring, status);   /* convert value to a string */

    if (!comm || comm[0] == '&')  /* preserve the current comment string */
        ffmkky(keyname, valstring, oldcomm, card, status);
    else
        ffmkky(keyname, valstring, comm, card, status);

    ffmkey(fptr, card, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffmkfc(fitsfile *fptr,          /* I - FITS file pointer  */
           const char *keyname,     /* I - keyword name       */
           float *value,            /* I - keyword value      */
           int decim,               /* I - no of decimals     */
           const char *comm,        /* I - keyword comment    */
           int *status)             /* IO - error status      */
{
    char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
    char oldcomm[FLEN_COMMENT];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
        return(*status);                               /* get old comment */

    strcpy(valstring, "(" );
    ffr2f(value[0], decim, tmpstring, status); /* convert to string */
    strcat(valstring, tmpstring);
    strcat(valstring, ", ");
    ffr2f(value[1], decim, tmpstring, status); /* convert to string */
    strcat(valstring, tmpstring);
    strcat(valstring, ")");

    if (!comm || comm[0] == '&')  /* preserve the current comment string */
        ffmkky(keyname, valstring, oldcomm, card, status);
    else
        ffmkky(keyname, valstring, comm, card, status);

    ffmkey(fptr, card, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffmkyc(fitsfile *fptr,          /* I - FITS file pointer  */
           const char *keyname,     /* I - keyword name       */
           float *value,            /* I - keyword value      */
           int decim,               /* I - no of decimals     */
           const char *comm,        /* I - keyword comment    */
           int *status)             /* IO - error status      */
{
    char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
    char oldcomm[FLEN_COMMENT];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
        return(*status);                               /* get old comment */

    strcpy(valstring, "(" );
    ffr2e(value[0], decim, tmpstring, status); /* convert to string */
    strcat(valstring, tmpstring);
    strcat(valstring, ", ");
    ffr2e(value[1], decim, tmpstring, status); /* convert to string */
    strcat(valstring, tmpstring);
    strcat(valstring, ")");

    if (!comm || comm[0] == '&')  /* preserve the current comment string */
        ffmkky(keyname, valstring, oldcomm, card, status);
    else
        ffmkky(keyname, valstring, comm, card, status);

    ffmkey(fptr, card, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffmkfm(fitsfile *fptr,          /* I - FITS file pointer  */
           const char *keyname,     /* I - keyword name       */
           double *value,           /* I - keyword value      */
           int decim,               /* I - no of decimals     */
           const char *comm,        /* I - keyword comment    */
           int *status)             /* IO - error status      */
{
    char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
    char oldcomm[FLEN_COMMENT];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
        return(*status);                               /* get old comment */

    strcpy(valstring, "(" );
    ffd2f(value[0], decim, tmpstring, status); /* convert to string */
    strcat(valstring, tmpstring);
    strcat(valstring, ", ");
    ffd2f(value[1], decim, tmpstring, status); /* convert to string */
    strcat(valstring, tmpstring);
    strcat(valstring, ")");

    if (!comm || comm[0] == '&')  /* preserve the current comment string */
        ffmkky(keyname, valstring, oldcomm, card, status);
    else
        ffmkky(keyname, valstring, comm, card, status);

    ffmkey(fptr, card, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffmkym(fitsfile *fptr,    /* I - FITS file pointer  */
           const char *keyname,     /* I - keyword name       */
           double *value,     /* I - keyword value      */
           int decim,         /* I - no of decimals     */
           const char *comm,        /* I - keyword comment    */
           int *status)       /* IO - error status      */
{
    char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
    char oldcomm[FLEN_COMMENT];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
        return(*status);                               /* get old comment */

    strcpy(valstring, "(" );
    ffd2e(value[0], decim, tmpstring, status); /* convert to string */
    strcat(valstring, tmpstring);
    strcat(valstring, ", ");
    ffd2e(value[1], decim, tmpstring, status); /* convert to string */
    strcat(valstring, tmpstring);
    strcat(valstring, ")");

    if (!comm || comm[0] == '&')  /* preserve the current comment string */
        ffmkky(keyname, valstring, oldcomm, card, status);
    else
        ffmkky(keyname, valstring, comm, card, status);

    ffmkey(fptr, card, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffikyu(fitsfile *fptr,          /* I - FITS file pointer  */
           const char *keyname,     /* I - keyword name       */
           const char *comm,        /* I - keyword comment    */
           int *status)             /* IO - error status      */
/*
  Insert a null-valued keyword and comment into the FITS header.  
*/
{
    char valstring[FLEN_VALUE];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    strcpy(valstring," ");  /* create a dummy value string */
    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
    ffikey(fptr, card, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffikys(fitsfile *fptr,          /* I - FITS file pointer  */
           const char *keyname,     /* I - keyword name       */
           const char *value,       /* I - keyword value      */
           const char *comm,        /* I - keyword comment    */
           int *status)             /* IO - error status      */
{
    char valstring[FLEN_VALUE];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    ffs2c(value, valstring, status);   /* put quotes around the string */

    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
    ffikey(fptr, card, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffikls( fitsfile *fptr,           /* I - FITS file pointer        */
            const char *keyname,      /* I - name of keyword to write */
            const char *value,        /* I - keyword value            */
            const char *comm,         /* I - keyword comment          */
            int  *status)             /* IO - error status            */
/*
  Insert a long string keyword.  This routine supports the
  HEASARC long string convention and can insert arbitrarily long string
  keyword values.  The value is continued over multiple keywords that
  have the name COMTINUE without an equal sign in column 9 of the card.
  This routine also supports simple string keywords which are less than
  69 characters in length.
*/
{
    char valstring[FLEN_VALUE];
    char card[FLEN_CARD], tmpkeyname[FLEN_CARD];
    char tstring[FLEN_VALUE], *cptr;
    int next, remain, vlen, nquote, nchar, namelen, contin, tstatus = -1;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /*  construct the new keyword, and insert into header */
    remain = strlen(value);    /* number of characters to write out */
    next = 0;                  /* pointer to next character to write */
    
    /* count the number of single quote characters in the string */
    nquote = 0;
    cptr = strchr(value, '\'');   /* search for quote character */

    while (cptr)  /* search for quote character */
    {
        nquote++;            /*  increment no. of quote characters  */
        cptr++;              /*  increment pointer to next character */
        cptr = strchr(cptr, '\'');  /* search for another quote char */
    }


    strncpy(tmpkeyname, keyname, 80);
    tmpkeyname[80] = '\0';
    
    cptr = tmpkeyname;
    while(*cptr == ' ')   /* skip over leading spaces in name */
        cptr++;

    /* determine the number of characters that will fit on the line */
    /* Note: each quote character is expanded to 2 quotes */

    namelen = strlen(cptr);
    if (namelen <= 8 && (fftkey(cptr, &tstatus) <= 0) )
    {
        /* This a normal 8-character FITS keyword */
        nchar = 68 - nquote; /*  max of 68 chars fit in a FITS string value */
    }
    else
    {
	nchar = 80 - nquote - namelen - 5;
    }

    contin = 0;
    while (remain > 0)
    {
        strncpy(tstring, &value[next], nchar); /* copy string to temp buff */
        tstring[nchar] = '\0';
        ffs2c(tstring, valstring, status);  /* put quotes around the string */

        if (remain > nchar)   /* if string is continued, put & as last char */
        {
            vlen = strlen(valstring);
            nchar -= 1;        /* outputting one less character now */

            if (valstring[vlen-2] != '\'')
                valstring[vlen-2] = '&';  /*  over write last char with &  */
            else
            { /* last char was a pair of single quotes, so over write both */
                valstring[vlen-3] = '&';
                valstring[vlen-1] = '\0';
            }
        }

        if (contin)           /* This is a CONTINUEd keyword */
        {
           ffmkky("CONTINUE", valstring, comm, card, status); /* make keyword */
           strncpy(&card[8], "   ",  2);  /* overwrite the '=' */
        }
        else
        {
           ffmkky(keyname, valstring, comm, card, status);  /* make keyword */
        }

        ffikey(fptr, card, status);  /* insert the keyword */
       
        contin = 1;
        remain -= nchar;
        next  += nchar;
        nchar = 68 - nquote;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffikyl(fitsfile *fptr,          /* I - FITS file pointer  */
           const char *keyname,     /* I - keyword name       */
           int value,               /* I - keyword value      */
           const char *comm,        /* I - keyword comment    */
           int *status)             /* IO - error status      */
{
    char valstring[FLEN_VALUE];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    ffl2c(value, valstring, status);   /* convert logical to 'T' or 'F' */
    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
    ffikey(fptr, card, status);  /* write the keyword*/

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffikyj(fitsfile *fptr,          /* I - FITS file pointer  */
           const char *keyname,     /* I - keyword name       */
           LONGLONG value,          /* I - keyword value      */
           const char *comm,        /* I - keyword comment    */
           int *status)             /* IO - error status      */
{
    char valstring[FLEN_VALUE];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    ffi2c(value, valstring, status);   /* convert to formatted string */
    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
    ffikey(fptr, card, status);  /* write the keyword*/

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffikyf(fitsfile *fptr,          /* I - FITS file pointer  */
           const char *keyname,     /* I - keyword name       */
           float value,             /* I - keyword value      */
           int decim,               /* I - no of decimals     */
           const char *comm,        /* I - keyword comment    */ 
           int *status)             /* IO - error status      */
{
    char valstring[FLEN_VALUE];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    ffr2f(value, decim, valstring, status);   /* convert to formatted string */
    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
    ffikey(fptr, card, status);  /* write the keyword*/

    return(*status); 
}
/*--------------------------------------------------------------------------*/
int ffikye(fitsfile *fptr,          /* I - FITS file pointer  */
           const char *keyname,     /* I - keyword name       */
           float value,             /* I - keyword value      */
           int decim,               /* I - no of decimals     */
           const char *comm,        /* I - keyword comment    */ 
           int *status)             /* IO - error status      */
{
    char valstring[FLEN_VALUE];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    ffr2e(value, decim, valstring, status);   /* convert to formatted string */
    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
    ffikey(fptr, card, status);  /* write the keyword*/

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffikyg(fitsfile *fptr,          /* I - FITS file pointer  */
           const char *keyname,     /* I - keyword name       */
           double value,            /* I - keyword value      */
           int decim,               /* I - no of decimals     */
           const char *comm,        /* I - keyword comment    */ 
           int *status)             /* IO - error status      */
{
    char valstring[FLEN_VALUE];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    ffd2f(value, decim, valstring, status);   /* convert to formatted string */
    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
    ffikey(fptr, card, status);  /* write the keyword*/

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffikyd(fitsfile *fptr,          /* I - FITS file pointer  */
           const char *keyname,     /* I - keyword name       */
           double value,            /* I - keyword value      */
           int decim,               /* I - no of decimals     */
           const char *comm,        /* I - keyword comment    */ 
           int *status)             /* IO - error status      */
{
    char valstring[FLEN_VALUE];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    ffd2e(value, decim, valstring, status);   /* convert to formatted string */
    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
    ffikey(fptr, card, status);  /* write the keyword*/

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffikfc(fitsfile *fptr,          /* I - FITS file pointer  */
           const char *keyname,     /* I - keyword name       */
           float *value,            /* I - keyword value      */
           int decim,               /* I - no of decimals     */
           const char *comm,        /* I - keyword comment    */ 
           int *status)             /* IO - error status      */
{
    char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    strcpy(valstring, "(" );
    ffr2f(value[0], decim, tmpstring, status); /* convert to string */
    strcat(valstring, tmpstring);
    strcat(valstring, ", ");
    ffr2f(value[1], decim, tmpstring, status); /* convert to string */
    strcat(valstring, tmpstring);
    strcat(valstring, ")");

    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
    ffikey(fptr, card, status);  /* write the keyword*/

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffikyc(fitsfile *fptr,          /* I - FITS file pointer  */
           const char *keyname,     /* I - keyword name       */
           float *value,            /* I - keyword value      */
           int decim,               /* I - no of decimals     */
           const char *comm,        /* I - keyword comment    */ 
           int *status)             /* IO - error status      */
{
    char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    strcpy(valstring, "(" );
    ffr2e(value[0], decim, tmpstring, status); /* convert to string */
    strcat(valstring, tmpstring);
    strcat(valstring, ", ");
    ffr2e(value[1], decim, tmpstring, status); /* convert to string */
    strcat(valstring, tmpstring);
    strcat(valstring, ")");

    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
    ffikey(fptr, card, status);  /* write the keyword*/

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffikfm(fitsfile *fptr,          /* I - FITS file pointer  */
           const char *keyname,     /* I - keyword name       */
           double *value,           /* I - keyword value      */
           int decim,               /* I - no of decimals     */
           const char *comm,        /* I - keyword comment    */ 
           int *status)             /* IO - error status      */
{
    char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);


    strcpy(valstring, "(" );
    ffd2f(value[0], decim, tmpstring, status); /* convert to string */
    strcat(valstring, tmpstring);
    strcat(valstring, ", ");
    ffd2f(value[1], decim, tmpstring, status); /* convert to string */
    strcat(valstring, tmpstring);
    strcat(valstring, ")");

    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
    ffikey(fptr, card, status);  /* write the keyword*/

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffikym(fitsfile *fptr,          /* I - FITS file pointer  */
           const char *keyname,     /* I - keyword name       */
           double *value,           /* I - keyword value      */
           int decim,               /* I - no of decimals     */
           const char *comm,        /* I - keyword comment    */ 
           int *status)             /* IO - error status      */
{
    char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    strcpy(valstring, "(" );
    ffd2e(value[0], decim, tmpstring, status); /* convert to string */
    strcat(valstring, tmpstring);
    strcat(valstring, ", ");
    ffd2e(value[1], decim, tmpstring, status); /* convert to string */
    strcat(valstring, tmpstring);
    strcat(valstring, ")");

    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
    ffikey(fptr, card, status);  /* write the keyword*/

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffirec(fitsfile *fptr,    /* I - FITS file pointer              */
           int nkey,          /* I - position to insert new keyword */
           const char *card,  /* I - card string value              */
           int *status)       /* IO - error status                  */
{
    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    ffmaky(fptr, nkey, status);  /* move to insert position */
    ffikey(fptr, card, status);  /* insert the keyword card */

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffikey(fitsfile *fptr,    /* I - FITS file pointer  */
           const char *card,  /* I - card string value  */
           int *status)       /* IO - error status      */
/*
  insert a keyword at the position of (fptr->Fptr)->nextkey
*/
{
    int ii, len, nshift, keylength;
    long nblocks;
    LONGLONG bytepos;
    char *inbuff, *outbuff, *tmpbuff, buff1[FLEN_CARD], buff2[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /* reset position to the correct HDU if necessary */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    if ( ((fptr->Fptr)->datastart - (fptr->Fptr)->headend) == 80) /* only room for END card */
    {
        nblocks = 1;
        if (ffiblk(fptr, nblocks, 0, status) > 0) /* add new 2880-byte block*/
            return(*status);  
    }

    /* no. keywords to shift */
    nshift= (int) (( (fptr->Fptr)->headend - (fptr->Fptr)->nextkey ) / 80); 

    strncpy(buff2, card, 80);     /* copy card to output buffer */
    buff2[80] = '\0';

    len = strlen(buff2);

    /* silently replace any illegal characters with a space */
    for (ii=0; ii < len; ii++)   
        if (buff2[ii] < ' ' || buff2[ii] > 126) buff2[ii] = ' ';

    for (ii=len; ii < 80; ii++)   /* fill buffer with spaces if necessary */
        buff2[ii] = ' ';

    keylength = strcspn(buff2, "=");
    if (keylength == 80) keylength = 8;
    
    for (ii=0; ii < keylength; ii++)       /* make sure keyword name is uppercase */
        buff2[ii] = toupper(buff2[ii]);

    fftkey(buff2, status);        /* test keyword name contains legal chars */

/*  no need to do this any more, since any illegal characters have been removed
    fftrec(buff2, status);  */      /* test rest of keyword for legal chars   */

    inbuff = buff1;
    outbuff = buff2;

    bytepos = (fptr->Fptr)->nextkey;           /* pointer to next keyword in header */
    ffmbyt(fptr, bytepos, REPORT_EOF, status);

    for (ii = 0; ii < nshift; ii++) /* shift each keyword down one position */
    {
        ffgbyt(fptr, 80, inbuff, status);   /* read the current keyword */

        ffmbyt(fptr, bytepos, REPORT_EOF, status); /* move back */
        ffpbyt(fptr, 80, outbuff, status);  /* overwrite with other buffer */

        tmpbuff = inbuff;   /* swap input and output buffers */
        inbuff = outbuff;
        outbuff = tmpbuff;

        bytepos += 80;
    }

    ffpbyt(fptr, 80, outbuff, status);  /* write the final keyword */

    (fptr->Fptr)->headend += 80; /* increment the position of the END keyword */
    (fptr->Fptr)->nextkey += 80; /* increment the pointer to next keyword */

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffdkey(fitsfile *fptr,    /* I - FITS file pointer  */
           const char *keyname,     /* I - keyword name       */
           int *status)       /* IO - error status      */
/*
  delete a specified header keyword
*/
{
    int keypos, len;
    char valstring[FLEN_VALUE], comm[FLEN_COMMENT], value[FLEN_VALUE];
    char message[FLEN_ERRMSG], nextcomm[FLEN_COMMENT];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (ffgkey(fptr, keyname, valstring, comm, status) > 0) /* read keyword */
    {
        snprintf(message, FLEN_ERRMSG,"Could not find the %s keyword to delete (ffdkey)",
                keyname);
        ffpmsg(message);
        return(*status);
    }

    /* calc position of keyword in header */
    keypos = (int) ((((fptr->Fptr)->nextkey) - ((fptr->Fptr)->headstart[(fptr->Fptr)->curhdu])) / 80);

    ffdrec(fptr, keypos, status);  /* delete the keyword */

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /* check for string value which may be continued over multiple keywords */
    ffpmrk(); /* put mark on message stack; erase any messages after this */
    ffc2s(valstring, value, status);   /* remove quotes and trailing spaces */

    if (*status == VALUE_UNDEFINED) {
       ffcmrk();  /* clear any spurious error messages, back to the mark */
       *status = 0;
    } else {
 
      len = strlen(value);

      while (len && value[len - 1] == '&')  /* ampersand used as continuation char */
      {
        ffgcnt(fptr, value, nextcomm, status);
        if (*value)
        {
            ffdrec(fptr, keypos, status);  /* delete the keyword */
            len = strlen(value);
        }
        else   /* a null valstring indicates no continuation */
            len = 0;
      }
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffdstr(fitsfile *fptr,    /* I - FITS file pointer  */
           const char *string,     /* I - keyword name       */
           int *status)       /* IO - error status      */
/*
  delete a specified header keyword containing the input string
*/
{
    int keypos, len;
    char valstring[FLEN_VALUE], comm[FLEN_COMMENT], value[FLEN_VALUE];
    char card[FLEN_CARD], message[FLEN_ERRMSG], nextcomm[FLEN_COMMENT];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (ffgstr(fptr, string, card, status) > 0) /* read keyword */
    {
        snprintf(message, FLEN_ERRMSG,"Could not find the %s keyword to delete (ffdkey)",
                string);
        ffpmsg(message);
        return(*status);
    }

    /* calc position of keyword in header */
    keypos = (int) ((((fptr->Fptr)->nextkey) - ((fptr->Fptr)->headstart[(fptr->Fptr)->curhdu])) / 80);

    ffdrec(fptr, keypos, status);  /* delete the keyword */

    /* check for string value which may be continued over multiple keywords */
    ffpsvc(card, valstring, comm, status);

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /* check for string value which may be continued over multiple keywords */
    ffpmrk(); /* put mark on message stack; erase any messages after this */
    ffc2s(valstring, value, status);   /* remove quotes and trailing spaces */

    if (*status == VALUE_UNDEFINED) {
       ffcmrk();  /* clear any spurious error messages, back to the mark */
       *status = 0;
    } else {
 
      len = strlen(value);

      while (len && value[len - 1] == '&')  /* ampersand used as continuation char */
      {
        ffgcnt(fptr, value, nextcomm, status);
        if (*value)
        {
            ffdrec(fptr, keypos, status);  /* delete the keyword */
            len = strlen(value);
        }
        else   /* a null valstring indicates no continuation */
            len = 0;
      }
    }

    return(*status);
}/*--------------------------------------------------------------------------*/
int ffdrec(fitsfile *fptr,   /* I - FITS file pointer  */
           int keypos,       /* I - position in header of keyword to delete */
           int *status)      /* IO - error status      */
/*
  Delete a header keyword at position keypos. The 1st keyword is at keypos=1.
*/
{
    int ii, nshift;
    LONGLONG bytepos;
    char *inbuff, *outbuff, *tmpbuff, buff1[81], buff2[81];
    char message[FLEN_ERRMSG];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /* reset position to the correct HDU if necessary */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    if (keypos < 1 ||
        keypos > (fptr->Fptr)->headend - (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] / 80 )
        return(*status = KEY_OUT_BOUNDS);

    (fptr->Fptr)->nextkey = (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] + (keypos - 1) * 80;

    nshift=(int) (( (fptr->Fptr)->headend - (fptr->Fptr)->nextkey ) / 80); /* no. keywords to shift */

    if (nshift <= 0)
    {
        snprintf(message, FLEN_ERRMSG,"Cannot delete keyword number %d.  It does not exist.",
                keypos);
        ffpmsg(message);
        return(*status = KEY_OUT_BOUNDS);
    }

    bytepos = (fptr->Fptr)->headend - 80;  /* last keyword in header */  

    /* construct a blank keyword */
    strcpy(buff2, "                                        ");
    strcat(buff2, "                                        ");
    inbuff  = buff1;
    outbuff = buff2;
    for (ii = 0; ii < nshift; ii++) /* shift each keyword up one position */
    {

        ffmbyt(fptr, bytepos, REPORT_EOF, status);
        ffgbyt(fptr, 80, inbuff, status);   /* read the current keyword */

        ffmbyt(fptr, bytepos, REPORT_EOF, status);
        ffpbyt(fptr, 80, outbuff, status);  /* overwrite with next keyword */

        tmpbuff = inbuff;   /* swap input and output buffers */
        inbuff = outbuff;
        outbuff = tmpbuff;

        bytepos -= 80;
    }

    (fptr->Fptr)->headend -= 80; /* decrement the position of the END keyword */
    return(*status);
}

cfitsio/pliocomp.c0000644000225700000360000001563313246025103013776 0ustar  cagordonlhea/* stdlib is needed for the abs function */
#include 
/*
   The following prototype code was provided by Doug Tody, NRAO, for
   performing conversion between pixel arrays and line lists.  The
   compression technique is used in IRAF.
*/
int pl_p2li (int *pxsrc, int xs, short *lldst, int npix);
int pl_l2pi (short *ll_src, int xs, int *px_dst, int npix);


/*
 * PL_P2L -- Convert a pixel array to a line list.  The length of the list is
 * returned as the function value.
 *
 * Translated from the SPP version using xc -f, f2c.  8Sep99 DCT.
 */

#ifndef min
#define min(a,b)        (((a)<(b))?(a):(b))
#endif
#ifndef max
#define max(a,b)        (((a)>(b))?(a):(b))
#endif

int pl_p2li (int *pxsrc, int xs, short *lldst, int npix)
/* int *pxsrc;                      input pixel array */
/* int xs;                          starting index in pxsrc (?) */
/* short *lldst;                    encoded line list */
/* int npix;                        number of pixels to convert */
{
    /* System generated locals */
    int ret_val, i__1, i__2, i__3;

    /* Local variables */
    int zero, v, x1, hi, ip, dv, xe, np, op, iz, nv = 0, pv, nz;

    /* Parameter adjustments */
    --lldst;
    --pxsrc;

    /* Function Body */
    if (! (npix <= 0)) {
        goto L110;
    }
    ret_val = 0;
    goto L100;
L110:
    lldst[3] = -100;
    lldst[2] = 7;
    lldst[1] = 0;
    lldst[6] = 0;
    lldst[7] = 0;
    xe = xs + npix - 1;
    op = 8;
    zero = 0;
/* Computing MAX */
    i__1 = zero, i__2 = pxsrc[xs];
    pv = max(i__1,i__2);
    x1 = xs;
    iz = xs;
    hi = 1;
    i__1 = xe;
    for (ip = xs; ip <= i__1; ++ip) {
        if (! (ip < xe)) {
            goto L130;
        }
/* Computing MAX */
        i__2 = zero, i__3 = pxsrc[ip + 1];
        nv = max(i__2,i__3);
        if (! (nv == pv)) {
            goto L140;
        }
        goto L120;
L140:
        if (! (pv == 0)) {
            goto L150;
        }
        pv = nv;
        x1 = ip + 1;
        goto L120;
L150:
        goto L131;
L130:
        if (! (pv == 0)) {
            goto L160;
        }
        x1 = xe + 1;
L160:
L131:
        np = ip - x1 + 1;
        nz = x1 - iz;
        if (! (pv > 0)) {
            goto L170;
        }
        dv = pv - hi;
        if (! (dv != 0)) {
            goto L180;
        }
        hi = pv;
        if (! (abs(dv) > 4095)) {
            goto L190;
        }
        lldst[op] = (short) ((pv & 4095) + 4096);
        ++op;
        lldst[op] = (short) (pv / 4096);
        ++op;
        goto L191;
L190:
        if (! (dv < 0)) {
            goto L200;
        }
        lldst[op] = (short) (-dv + 12288);
        goto L201;
L200:
        lldst[op] = (short) (dv + 8192);
L201:
        ++op;
        if (! (np == 1 && nz == 0)) {
            goto L210;
        }
        v = lldst[op - 1];
        lldst[op - 1] = (short) (v | 16384);
        goto L91;
L210:
L191:
L180:
L170:
        if (! (nz > 0)) {
            goto L220;
        }
L230:
        if (! (nz > 0)) {
            goto L232;
        }
        lldst[op] = (short) min(4095,nz);
        ++op;
/* L231: */
        nz += -4095;
        goto L230;
L232:
        if (! (np == 1 && pv > 0)) {
            goto L240;
        }
        lldst[op - 1] = (short) (lldst[op - 1] + 20481);
        goto L91;
L240:
L220:
L250:
        if (! (np > 0)) {
            goto L252;
        }
        lldst[op] = (short) (min(4095,np) + 16384);
        ++op;
/* L251: */
        np += -4095;
        goto L250;
L252:
L91:
        x1 = ip + 1;
        iz = x1;
        pv = nv;
L120:
        ;
    }
/* L121: */
    lldst[4] = (short) ((op - 1) % 32768);
    lldst[5] = (short) ((op - 1) / 32768);
    ret_val = op - 1;
    goto L100;
L100:
    return ret_val;
} /* plp2li_ */

/*
 * PL_L2PI -- Translate a PLIO line list into an integer pixel array.
 * The number of pixels output (always npix) is returned as the function
 * value.
 *
 * Translated from the SPP version using xc -f, f2c.  8Sep99 DCT.
 */

int pl_l2pi (short *ll_src, int xs, int *px_dst, int npix)
/* short *ll_src;                   encoded line list */
/* int xs;                          starting index in ll_src */
/* int *px_dst;                    output pixel array */
/* int npix;                       number of pixels to convert */
{
    /* System generated locals */
    int ret_val, i__1, i__2;

    /* Local variables */
    int data, sw0001, otop, i__, lllen, i1, i2, x1, x2, ip, xe, np,
             op, pv, opcode, llfirt;
    int skipwd;

    /* Parameter adjustments */
    --px_dst;
    --ll_src;

    /* Function Body */
    if (! (ll_src[3] > 0)) {
        goto L110;
    }
    lllen = ll_src[3];
    llfirt = 4;
    goto L111;
L110:
    lllen = (ll_src[5] << 15) + ll_src[4];
    llfirt = ll_src[2] + 1;
L111:
    if (! (npix <= 0 || lllen <= 0)) {
        goto L120;
    }
    ret_val = 0;
    goto L100;
L120:
    xe = xs + npix - 1;
    skipwd = 0;
    op = 1;
    x1 = 1;
    pv = 1;
    i__1 = lllen;
    for (ip = llfirt; ip <= i__1; ++ip) {
        if (! skipwd) {
            goto L140;
        }
        skipwd = 0;
        goto L130;
L140:
        opcode = ll_src[ip] / 4096;
        data = ll_src[ip] & 4095;
        sw0001 = opcode;
        goto L150;
L160:
        x2 = x1 + data - 1;
        i1 = max(x1,xs);
        i2 = min(x2,xe);
        np = i2 - i1 + 1;
        if (! (np > 0)) {
            goto L170;
        }
        otop = op + np - 1;
        if (! (opcode == 4)) {
            goto L180;
        }
        i__2 = otop;
        for (i__ = op; i__ <= i__2; ++i__) {
            px_dst[i__] = pv;
/* L190: */
        }
/* L191: */
        goto L181;
L180:
        i__2 = otop;
        for (i__ = op; i__ <= i__2; ++i__) {
            px_dst[i__] = 0;
/* L200: */
        }
/* L201: */
        if (! (opcode == 5 && i2 == x2)) {
            goto L210;
        }
        px_dst[otop] = pv;
L210:
L181:
        op = otop + 1;
L170:
        x1 = x2 + 1;
        goto L151;
L220:
        pv = (ll_src[ip + 1] << 12) + data;
        skipwd = 1;
        goto L151;
L230:
        pv += data;
        goto L151;
L240:
        pv -= data;
        goto L151;
L250:
        pv += data;
        goto L91;
L260:
        pv -= data;
L91:
        if (! (x1 >= xs && x1 <= xe)) {
            goto L270;
        }
        px_dst[op] = pv;
        ++op;
L270:
        ++x1;
        goto L151;
L150:
        ++sw0001;
        if (sw0001 < 1 || sw0001 > 8) {
            goto L151;
        }
        switch ((int)sw0001) {
            case 1:  goto L160;
            case 2:  goto L220;
            case 3:  goto L230;
            case 4:  goto L240;
            case 5:  goto L160;
            case 6:  goto L160;
            case 7:  goto L250;
            case 8:  goto L260;
        }
L151:
        if (! (x1 > xe)) {
            goto L280;
        }
        goto L131;
L280:
L130:
        ;
    }
L131:
    i__1 = npix;
    for (i__ = op; i__ <= i__1; ++i__) {
        px_dst[i__] = 0;
/* L290: */
    }
/* L291: */
    ret_val = npix;
    goto L100;
L100:
    return ret_val;
} /* pll2pi_ */

cfitsio/putcol.c0000644000225700000360000020156113246025103013457 0ustar  cagordonlhea/*  This file, putcol.c, contains routines that write data elements to     */
/*  a FITS image or table. These are the generic routines.                 */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int ffppx(  fitsfile *fptr,  /* I - FITS file pointer                       */
            int  datatype,   /* I - datatype of the value                   */
            long  *firstpix, /* I - coord of  first pixel to write(1 based) */
            LONGLONG  nelem,     /* I - number of values to write               */
            void  *array,    /* I - array of values that are written        */
            int  *status)    /* IO - error status                           */
/*
  Write an array of pixels to the primary array.  The datatype of the
  input array is defined by the 2nd argument. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written). 
  
  This routine is simillar to ffppr, except it supports writing to 
  large images with more than 2**31 pixels.
*/
{
    int naxis, ii;
    long group = 1;
    LONGLONG firstelem, dimsize = 1, naxes[9];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /* get the size of the image */
    ffgidm(fptr, &naxis, status);
    ffgiszll(fptr, 9, naxes, status);

    firstelem = 0;
    for (ii=0; ii < naxis; ii++)
    {
        firstelem += ((firstpix[ii] - 1) * dimsize);
        dimsize *= naxes[ii];
    }
    firstelem++;

    if (datatype == TBYTE)
    {
      ffpprb(fptr, group, firstelem, nelem, (unsigned char *) array, status);
    }
    else if (datatype == TSBYTE)
    {
      ffpprsb(fptr, group, firstelem, nelem, (signed char *) array, status);
    }
    else if (datatype == TUSHORT)
    {
      ffpprui(fptr, group, firstelem, nelem, (unsigned short *) array,
              status);
    }
    else if (datatype == TSHORT)
    {
      ffppri(fptr, group, firstelem, nelem, (short *) array, status);
    }
    else if (datatype == TUINT)
    {
      ffppruk(fptr, group, firstelem, nelem, (unsigned int *) array, status);
    }
    else if (datatype == TINT)
    {
      ffpprk(fptr, group, firstelem, nelem, (int *) array, status);
    }
    else if (datatype == TULONG)
    {
      ffppruj(fptr, group, firstelem, nelem, (unsigned long *) array, status);
    }
    else if (datatype == TLONG)
    {
      ffpprj(fptr, group, firstelem, nelem, (long *) array, status);
    }
    else if (datatype == TLONGLONG)
    {
      ffpprjj(fptr, group, firstelem, nelem, (LONGLONG *) array, status);
    }
    else if (datatype == TFLOAT)
    {
      ffppre(fptr, group, firstelem, nelem, (float *) array, status);
    }
    else if (datatype == TDOUBLE)
    {
      ffpprd(fptr, group, firstelem, nelem, (double *) array, status);
    }
    else
      *status = BAD_DATATYPE;

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffppxll(  fitsfile *fptr,  /* I - FITS file pointer                       */
            int  datatype,   /* I - datatype of the value                   */
            LONGLONG  *firstpix, /* I - coord of  first pixel to write(1 based) */
            LONGLONG  nelem,     /* I - number of values to write               */
            void  *array,    /* I - array of values that are written        */
            int  *status)    /* IO - error status                           */
/*
  Write an array of pixels to the primary array.  The datatype of the
  input array is defined by the 2nd argument. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written). 
  
  This routine is simillar to ffppr, except it supports writing to 
  large images with more than 2**31 pixels.
*/
{
    int naxis, ii;
    long group = 1;
    LONGLONG firstelem, dimsize = 1, naxes[9];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /* get the size of the image */
    ffgidm(fptr, &naxis, status);
    ffgiszll(fptr, 9, naxes, status);

    firstelem = 0;
    for (ii=0; ii < naxis; ii++)
    {
        firstelem += ((firstpix[ii] - 1) * dimsize);
        dimsize *= naxes[ii];
    }
    firstelem++;

    if (datatype == TBYTE)
    {
      ffpprb(fptr, group, firstelem, nelem, (unsigned char *) array, status);
    }
    else if (datatype == TSBYTE)
    {
      ffpprsb(fptr, group, firstelem, nelem, (signed char *) array, status);
    }
    else if (datatype == TUSHORT)
    {
      ffpprui(fptr, group, firstelem, nelem, (unsigned short *) array,
              status);
    }
    else if (datatype == TSHORT)
    {
      ffppri(fptr, group, firstelem, nelem, (short *) array, status);
    }
    else if (datatype == TUINT)
    {
      ffppruk(fptr, group, firstelem, nelem, (unsigned int *) array, status);
    }
    else if (datatype == TINT)
    {
      ffpprk(fptr, group, firstelem, nelem, (int *) array, status);
    }
    else if (datatype == TULONG)
    {
      ffppruj(fptr, group, firstelem, nelem, (unsigned long *) array, status);
    }
    else if (datatype == TLONG)
    {
      ffpprj(fptr, group, firstelem, nelem, (long *) array, status);
    }
    else if (datatype == TLONGLONG)
    {
      ffpprjj(fptr, group, firstelem, nelem, (LONGLONG *) array, status);
    }
    else if (datatype == TFLOAT)
    {
      ffppre(fptr, group, firstelem, nelem, (float *) array, status);
    }
    else if (datatype == TDOUBLE)
    {
      ffpprd(fptr, group, firstelem, nelem, (double *) array, status);
    }
    else
      *status = BAD_DATATYPE;

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffppxn(  fitsfile *fptr,  /* I - FITS file pointer                       */
            int  datatype,   /* I - datatype of the value                   */
            long  *firstpix, /* I - first vector element to write(1 = 1st)  */
            LONGLONG  nelem,     /* I - number of values to write               */
            void  *array,    /* I - array of values that are written        */
            void  *nulval,   /* I - pointer to the null value               */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to the primary array.  The datatype of the
  input array is defined by the 2nd argument. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written).

  This routine supports writing to large images with
  more than 2**31 pixels.
*/
{
    int naxis, ii;
    long group = 1;
    LONGLONG firstelem, dimsize = 1, naxes[9];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (nulval == NULL)  /* null value not defined? */
    {
        ffppx(fptr, datatype, firstpix, nelem, array, status);
        return(*status);
    }

    /* get the size of the image */
    ffgidm(fptr, &naxis, status);
    ffgiszll(fptr, 9, naxes, status);

    firstelem = 0;
    for (ii=0; ii < naxis; ii++)
    {
        firstelem += ((firstpix[ii] - 1) * dimsize);
        dimsize *= naxes[ii];
    }
    firstelem++;

    if (datatype == TBYTE)
    {
      ffppnb(fptr, group, firstelem, nelem, (unsigned char *) array, 
             *(unsigned char *) nulval, status);
    }
    else if (datatype == TSBYTE)
    {
      ffppnsb(fptr, group, firstelem, nelem, (signed char *) array, 
             *(signed char *) nulval, status);
    }
    else if (datatype == TUSHORT)
    {
      ffppnui(fptr, group, firstelem, nelem, (unsigned short *) array,
              *(unsigned short *) nulval,status);
    }
    else if (datatype == TSHORT)
    {
      ffppni(fptr, group, firstelem, nelem, (short *) array,
             *(short *) nulval, status);
    }
    else if (datatype == TUINT)
    {
      ffppnuk(fptr, group, firstelem, nelem, (unsigned int *) array,
             *(unsigned int *) nulval, status);
    }
    else if (datatype == TINT)
    {
      ffppnk(fptr, group, firstelem, nelem, (int *) array,
             *(int *) nulval, status);
    }
    else if (datatype == TULONG)
    {
      ffppnuj(fptr, group, firstelem, nelem, (unsigned long *) array,
              *(unsigned long *) nulval,status);
    }
    else if (datatype == TLONG)
    {
      ffppnj(fptr, group, firstelem, nelem, (long *) array,
             *(long *) nulval, status);
    }
    else if (datatype == TLONGLONG)
    {
      ffppnjj(fptr, group, firstelem, nelem, (LONGLONG *) array,
             *(LONGLONG *) nulval, status);
    }
    else if (datatype == TFLOAT)
    {
      ffppne(fptr, group, firstelem, nelem, (float *) array,
             *(float *) nulval, status);
    }
    else if (datatype == TDOUBLE)
    {
      ffppnd(fptr, group, firstelem, nelem, (double *) array,
             *(double *) nulval, status);
    }
    else
      *status = BAD_DATATYPE;

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffppxnll(  fitsfile *fptr,  /* I - FITS file pointer                       */
            int  datatype,   /* I - datatype of the value                   */
            LONGLONG  *firstpix, /* I - first vector element to write(1 = 1st)  */
            LONGLONG  nelem,     /* I - number of values to write               */
            void  *array,    /* I - array of values that are written        */
            void  *nulval,   /* I - pointer to the null value               */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to the primary array.  The datatype of the
  input array is defined by the 2nd argument. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written).

  This routine supports writing to large images with
  more than 2**31 pixels.
*/
{
    int naxis, ii;
    long  group = 1;
    LONGLONG firstelem, dimsize = 1, naxes[9];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (nulval == NULL)  /* null value not defined? */
    {
        ffppxll(fptr, datatype, firstpix, nelem, array, status);
        return(*status);
    }

    /* get the size of the image */
    ffgidm(fptr, &naxis, status);
    ffgiszll(fptr, 9, naxes, status);

    firstelem = 0;
    for (ii=0; ii < naxis; ii++)
    {
        firstelem += ((firstpix[ii] - 1) * dimsize);
        dimsize *= naxes[ii];
    }
    firstelem++;

    if (datatype == TBYTE)
    {
      ffppnb(fptr, group, firstelem, nelem, (unsigned char *) array, 
             *(unsigned char *) nulval, status);
    }
    else if (datatype == TSBYTE)
    {
      ffppnsb(fptr, group, firstelem, nelem, (signed char *) array, 
             *(signed char *) nulval, status);
    }
    else if (datatype == TUSHORT)
    {
      ffppnui(fptr, group, firstelem, nelem, (unsigned short *) array,
              *(unsigned short *) nulval,status);
    }
    else if (datatype == TSHORT)
    {
      ffppni(fptr, group, firstelem, nelem, (short *) array,
             *(short *) nulval, status);
    }
    else if (datatype == TUINT)
    {
      ffppnuk(fptr, group, firstelem, nelem, (unsigned int *) array,
             *(unsigned int *) nulval, status);
    }
    else if (datatype == TINT)
    {
      ffppnk(fptr, group, firstelem, nelem, (int *) array,
             *(int *) nulval, status);
    }
    else if (datatype == TULONG)
    {
      ffppnuj(fptr, group, firstelem, nelem, (unsigned long *) array,
              *(unsigned long *) nulval,status);
    }
    else if (datatype == TLONG)
    {
      ffppnj(fptr, group, firstelem, nelem, (long *) array,
             *(long *) nulval, status);
    }
    else if (datatype == TLONGLONG)
    {
      ffppnjj(fptr, group, firstelem, nelem, (LONGLONG *) array,
             *(LONGLONG *) nulval, status);
    }
    else if (datatype == TFLOAT)
    {
      ffppne(fptr, group, firstelem, nelem, (float *) array,
             *(float *) nulval, status);
    }
    else if (datatype == TDOUBLE)
    {
      ffppnd(fptr, group, firstelem, nelem, (double *) array,
             *(double *) nulval, status);
    }
    else
      *status = BAD_DATATYPE;

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffppr(  fitsfile *fptr,  /* I - FITS file pointer                       */
            int  datatype,   /* I - datatype of the value                   */
            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
            LONGLONG  nelem,     /* I - number of values to write               */
            void  *array,    /* I - array of values that are written        */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to the primary array.  The datatype of the
  input array is defined by the 2nd argument. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written).

*/
{
    long group = 1;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (datatype == TBYTE)
    {
      ffpprb(fptr, group, firstelem, nelem, (unsigned char *) array, status);
    }
    else if (datatype == TSBYTE)
    {
      ffpprsb(fptr, group, firstelem, nelem, (signed char *) array, status);
    }
    else if (datatype == TUSHORT)
    {
      ffpprui(fptr, group, firstelem, nelem, (unsigned short *) array,
              status);
    }
    else if (datatype == TSHORT)
    {
      ffppri(fptr, group, firstelem, nelem, (short *) array, status);
    }
    else if (datatype == TUINT)
    {
      ffppruk(fptr, group, firstelem, nelem, (unsigned int *) array, status);
    }
    else if (datatype == TINT)
    {
      ffpprk(fptr, group, firstelem, nelem, (int *) array, status);
    }
    else if (datatype == TULONG)
    {
      ffppruj(fptr, group, firstelem, nelem, (unsigned long *) array, status);
    }
    else if (datatype == TLONG)
    {
      ffpprj(fptr, group, firstelem, nelem, (long *) array, status);
    }
    else if (datatype == TLONGLONG)
    {
      ffpprjj(fptr, group, firstelem, nelem, (LONGLONG *) array, status);
    }
    else if (datatype == TFLOAT)
    {
      ffppre(fptr, group, firstelem, nelem, (float *) array, status);
    }
    else if (datatype == TDOUBLE)
    {
      ffpprd(fptr, group, firstelem, nelem, (double *) array, status);
    }
    else
      *status = BAD_DATATYPE;

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffppn(  fitsfile *fptr,  /* I - FITS file pointer                       */
            int  datatype,   /* I - datatype of the value                   */
            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
            LONGLONG  nelem,     /* I - number of values to write               */
            void  *array,    /* I - array of values that are written        */
            void  *nulval,   /* I - pointer to the null value               */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to the primary array.  The datatype of the
  input array is defined by the 2nd argument. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written).

*/
{
    long group = 1;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (nulval == NULL)  /* null value not defined? */
    {
        ffppr(fptr, datatype, firstelem, nelem, array, status);
        return(*status);
    }

    if (datatype == TBYTE)
    {
      ffppnb(fptr, group, firstelem, nelem, (unsigned char *) array, 
             *(unsigned char *) nulval, status);
    }
    else if (datatype == TSBYTE)
    {
      ffppnsb(fptr, group, firstelem, nelem, (signed char *) array, 
             *(signed char *) nulval, status);
    }
    else if (datatype == TUSHORT)
    {
      ffppnui(fptr, group, firstelem, nelem, (unsigned short *) array,
              *(unsigned short *) nulval,status);
    }
    else if (datatype == TSHORT)
    {
      ffppni(fptr, group, firstelem, nelem, (short *) array,
             *(short *) nulval, status);
    }
    else if (datatype == TUINT)
    {
      ffppnuk(fptr, group, firstelem, nelem, (unsigned int *) array,
             *(unsigned int *) nulval, status);
    }
    else if (datatype == TINT)
    {
      ffppnk(fptr, group, firstelem, nelem, (int *) array,
             *(int *) nulval, status);
    }
    else if (datatype == TULONG)
    {
      ffppnuj(fptr, group, firstelem, nelem, (unsigned long *) array,
              *(unsigned long *) nulval,status);
    }
    else if (datatype == TLONG)
    {
      ffppnj(fptr, group, firstelem, nelem, (long *) array,
             *(long *) nulval, status);
    }
    else if (datatype == TLONGLONG)
    {
      ffppnjj(fptr, group, firstelem, nelem, (LONGLONG *) array,
             *(LONGLONG *) nulval, status);
    }
    else if (datatype == TFLOAT)
    {
      ffppne(fptr, group, firstelem, nelem, (float *) array,
             *(float *) nulval, status);
    }
    else if (datatype == TDOUBLE)
    {
      ffppnd(fptr, group, firstelem, nelem, (double *) array,
             *(double *) nulval, status);
    }
    else
      *status = BAD_DATATYPE;

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpss(  fitsfile *fptr,   /* I - FITS file pointer                       */
            int  datatype,    /* I - datatype of the value                   */
            long *blc,        /* I - 'bottom left corner' of the subsection  */
            long *trc ,       /* I - 'top right corner' of the subsection    */
            void *array,      /* I - array of values that are written        */
            int  *status)     /* IO - error status                           */
/*
  Write a section of values to the primary array. The datatype of the
  input array is defined by the 2nd argument.  Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written).

  This routine supports writing to large images with
  more than 2**31 pixels.
*/
{
    int naxis;
    long naxes[9];

    if (*status > 0)   /* inherit input status value if > 0 */
        return(*status);

    /* get the size of the image */
    ffgidm(fptr, &naxis, status);
    ffgisz(fptr, 9, naxes, status);

    if (datatype == TBYTE)
    {
        ffpssb(fptr, 1, naxis, naxes, blc, trc,
               (unsigned char *) array, status);
    }
    else if (datatype == TSBYTE)
    {
        ffpsssb(fptr, 1, naxis, naxes, blc, trc,
               (signed char *) array, status);
    }
    else if (datatype == TUSHORT)
    {
        ffpssui(fptr, 1, naxis, naxes, blc, trc,
               (unsigned short *) array, status);
    }
    else if (datatype == TSHORT)
    {
        ffpssi(fptr, 1, naxis, naxes, blc, trc,
               (short *) array, status);
    }
    else if (datatype == TUINT)
    {
        ffpssuk(fptr, 1, naxis, naxes, blc, trc,
               (unsigned int *) array, status);
    }
    else if (datatype == TINT)
    {
        ffpssk(fptr, 1, naxis, naxes, blc, trc,
               (int *) array, status);
    }
    else if (datatype == TULONG)
    {
        ffpssuj(fptr, 1, naxis, naxes, blc, trc,
               (unsigned long *) array, status);
    }
    else if (datatype == TLONG)
    {
        ffpssj(fptr, 1, naxis, naxes, blc, trc,
               (long *) array, status);
    }
    else if (datatype == TLONGLONG)
    {
        ffpssjj(fptr, 1, naxis, naxes, blc, trc,
               (LONGLONG *) array, status);
    }    else if (datatype == TFLOAT)
    {
        ffpsse(fptr, 1, naxis, naxes, blc, trc,
               (float *) array, status);
    }
    else if (datatype == TDOUBLE)
    {
        ffpssd(fptr, 1, naxis, naxes, blc, trc,
               (double *) array, status);
    }
    else
      *status = BAD_DATATYPE;

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpcl(  fitsfile *fptr,  /* I - FITS file pointer                       */
            int  datatype,   /* I - datatype of the value                   */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of elements to write             */
            void  *array,    /* I - array of values that are written        */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to a table column.  The datatype of the
  input array is defined by the 2nd argument. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS column is not the same as the array being written).

*/
{
    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (datatype == TBIT)
    {
      ffpclx(fptr, colnum, firstrow, (long) firstelem, (long) nelem, (char *) array, 
             status);
    }
    else if (datatype == TBYTE)
    {
      ffpclb(fptr, colnum, firstrow, firstelem, nelem, (unsigned char *) array,
             status);
    }
    else if (datatype == TSBYTE)
    {
      ffpclsb(fptr, colnum, firstrow, firstelem, nelem, (signed char *) array,
             status);
    }
    else if (datatype == TUSHORT)
    {
      ffpclui(fptr, colnum, firstrow, firstelem, nelem, 
             (unsigned short *) array, status);
    }
    else if (datatype == TSHORT)
    {
      ffpcli(fptr, colnum, firstrow, firstelem, nelem, (short *) array,
             status);
    }
    else if (datatype == TUINT)
    {
      ffpcluk(fptr, colnum, firstrow, firstelem, nelem, (unsigned int *) array,
               status);
    }
    else if (datatype == TINT)
    {
      ffpclk(fptr, colnum, firstrow, firstelem, nelem, (int *) array,
               status);
    }
    else if (datatype == TULONG)
    {
      ffpcluj(fptr, colnum, firstrow, firstelem, nelem, (unsigned long *) array,
              status);
    }
    else if (datatype == TLONG)
    {
      ffpclj(fptr, colnum, firstrow, firstelem, nelem, (long *) array,
             status);
    }
    else if (datatype == TLONGLONG)
    {
      ffpcljj(fptr, colnum, firstrow, firstelem, nelem, (LONGLONG *) array,
             status);
    }
    else if (datatype == TFLOAT)
    {
      ffpcle(fptr, colnum, firstrow, firstelem, nelem, (float *) array,
             status);
    }
    else if (datatype == TDOUBLE)
    {
      ffpcld(fptr, colnum, firstrow, firstelem, nelem, (double *) array,
             status);
    }
    else if (datatype == TCOMPLEX)
    {
      ffpcle(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2,
             (float *) array, status);
    }
    else if (datatype == TDBLCOMPLEX)
    {
      ffpcld(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2,
             (double *) array, status);
    }
    else if (datatype == TLOGICAL)
    {
      ffpcll(fptr, colnum, firstrow, firstelem, nelem, (char *) array,
             status);
    }
    else if (datatype == TSTRING)
    {
      ffpcls(fptr, colnum, firstrow, firstelem, nelem, (char **) array,
             status);
    }
    else
      *status = BAD_DATATYPE;

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpcn(  fitsfile *fptr,  /* I - FITS file pointer                       */
            int  datatype,   /* I - datatype of the value                   */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of elements to write             */
            void  *array,    /* I - array of values that are written        */
            void  *nulval,   /* I - pointer to the null value               */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to a table column.  The datatype of the
  input array is defined by the 2nd argument. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS column is not the same as the array being written).

*/
{
    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (nulval == NULL)  /* null value not defined? */
    {
        ffpcl(fptr, datatype, colnum, firstrow, firstelem, nelem, array,
              status);
        return(*status);
    }

    if (datatype == TBYTE)
    {
      ffpcnb(fptr, colnum, firstrow, firstelem, nelem, (unsigned char *) array,
            *(unsigned char *) nulval, status);
    }
    else if (datatype == TSBYTE)
    {
      ffpcnsb(fptr, colnum, firstrow, firstelem, nelem, (signed char *) array,
            *(signed char *) nulval, status);
    }
    else if (datatype == TUSHORT)
    {
     ffpcnui(fptr, colnum, firstrow, firstelem, nelem, (unsigned short *) array,
             *(unsigned short *) nulval, status);
    }
    else if (datatype == TSHORT)
    {
      ffpcni(fptr, colnum, firstrow, firstelem, nelem, (short *) array,
             *(unsigned short *) nulval, status);
    }
    else if (datatype == TUINT)
    {
      ffpcnuk(fptr, colnum, firstrow, firstelem, nelem, (unsigned int *) array,
             *(unsigned int *) nulval, status);
    }
    else if (datatype == TINT)
    {
      ffpcnk(fptr, colnum, firstrow, firstelem, nelem, (int *) array,
             *(int *) nulval, status);
    }
    else if (datatype == TULONG)
    {
      ffpcnuj(fptr, colnum, firstrow, firstelem, nelem, (unsigned long *) array,
              *(unsigned long *) nulval, status);
    }
    else if (datatype == TLONG)
    {
      ffpcnj(fptr, colnum, firstrow, firstelem, nelem, (long *) array,
             *(long *) nulval, status);
    }
    else if (datatype == TLONGLONG)
    {
      ffpcnjj(fptr, colnum, firstrow, firstelem, nelem, (LONGLONG *) array,
             *(LONGLONG *) nulval, status);
    }
    else if (datatype == TFLOAT)
    {
      ffpcne(fptr, colnum, firstrow, firstelem, nelem, (float *) array,
             *(float *) nulval, status);
    }
    else if (datatype == TDOUBLE)
    {
      ffpcnd(fptr, colnum, firstrow, firstelem, nelem, (double *) array,
             *(double *) nulval, status);
    }
    else if (datatype == TCOMPLEX)
    {
      ffpcne(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2,
             (float *) array, *(float *) nulval, status);
    }
    else if (datatype == TDBLCOMPLEX)
    {
      ffpcnd(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, nelem * 2,
             (double *) array, *(double *) nulval, status);
    }
    else if (datatype == TLOGICAL)
    {
      ffpcnl(fptr, colnum, firstrow, firstelem, nelem, (char *) array,
             *(char *) nulval, status);
    }
    else if (datatype == TSTRING)
    {
      ffpcns(fptr, colnum, firstrow, firstelem, nelem, (char **) array,
             (char *) nulval, status);
    }
    else
      *status = BAD_DATATYPE;

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_iter_set_by_name(iteratorCol *col, /* I - iterator col structure */
           fitsfile *fptr,  /* I - FITS file pointer                      */
           char *colname,   /* I - column name                            */
           int datatype,    /* I - column datatype                        */
           int iotype)      /* I - InputCol, InputOutputCol, or OutputCol */
/*
  set all the parameters for an iterator column, by column name
*/
{
    col->fptr = fptr;
    strcpy(col->colname, colname);
    col->colnum = 0;  /* set column number undefined since name is given */
    col->datatype = datatype;
    col->iotype = iotype;
    return(0);
}
/*--------------------------------------------------------------------------*/
int fits_iter_set_by_num(iteratorCol *col, /* I - iterator column structure */
           fitsfile *fptr,  /* I - FITS file pointer                      */
           int colnum,      /* I - column number                          */
           int datatype,    /* I - column datatype                        */
           int iotype)      /* I - InputCol, InputOutputCol, or OutputCol */
/*
  set all the parameters for an iterator column, by column number
*/
{
    col->fptr = fptr;
    col->colnum = colnum; 
    col->datatype = datatype;
    col->iotype = iotype;
    return(0);
}
/*--------------------------------------------------------------------------*/
int fits_iter_set_file(iteratorCol *col, /* I - iterator column structure   */
           fitsfile *fptr)   /* I - FITS file pointer                      */
/*
  set iterator column parameter
*/
{
    col->fptr = fptr;
    return(0);
}
/*--------------------------------------------------------------------------*/
int fits_iter_set_colname(iteratorCol *col, /* I - iterator col structure  */
           char *colname)    /* I - column name                            */
/*
  set iterator column parameter
*/
{
    strcpy(col->colname, colname);
    col->colnum = 0;  /* set column number undefined since name is given */
    return(0);
}
/*--------------------------------------------------------------------------*/
int fits_iter_set_colnum(iteratorCol *col, /* I - iterator column structure */
           int colnum)       /* I - column number                          */
/*
  set iterator column parameter
*/
{
    col->colnum = colnum; 
    return(0);
}
/*--------------------------------------------------------------------------*/
int fits_iter_set_datatype(iteratorCol *col, /* I - iterator col structure */
           int datatype)    /* I - column datatype                        */
/*
  set iterator column parameter
*/
{
    col->datatype = datatype;
    return(0);
}
/*--------------------------------------------------------------------------*/
int fits_iter_set_iotype(iteratorCol *col, /* I - iterator column structure */
           int iotype)       /* I - InputCol, InputOutputCol, or OutputCol */
/*
  set iterator column parameter
*/
{
    col->iotype = iotype;
    return(0);
}
/*--------------------------------------------------------------------------*/
fitsfile * fits_iter_get_file(iteratorCol *col) /* I -iterator col structure */
/*
  get iterator column parameter
*/
{
     return(col->fptr);
}
/*--------------------------------------------------------------------------*/
char * fits_iter_get_colname(iteratorCol *col) /* I -iterator col structure */
/*
  get iterator column parameter
*/
{
    return(col->colname);
}
/*--------------------------------------------------------------------------*/
int fits_iter_get_colnum(iteratorCol *col) /* I - iterator column structure */
/*
  get iterator column parameter
*/
{
    return(col->colnum);
}
/*--------------------------------------------------------------------------*/
int fits_iter_get_datatype(iteratorCol *col) /* I - iterator col structure */
/*
  get iterator column parameter
*/
{
    return(col->datatype);
}
/*--------------------------------------------------------------------------*/
int fits_iter_get_iotype(iteratorCol *col) /* I - iterator column structure */
/*
  get iterator column parameter
*/
{
     return(col->iotype);
}
/*--------------------------------------------------------------------------*/
void * fits_iter_get_array(iteratorCol *col) /* I - iterator col structure */
/*
  get iterator column parameter
*/
{
     return(col->array);
}
/*--------------------------------------------------------------------------*/
long fits_iter_get_tlmin(iteratorCol *col) /* I - iterator column structure */
/*
  get iterator column parameter
*/
{
     return(col->tlmin);
}
/*--------------------------------------------------------------------------*/
long fits_iter_get_tlmax(iteratorCol *col) /* I - iterator column structure */
/*
  get iterator column parameter
*/
{
     return(col->tlmax);
}
/*--------------------------------------------------------------------------*/
long fits_iter_get_repeat(iteratorCol *col) /* I - iterator col structure */
/*
  get iterator column parameter
*/
{
     return(col->repeat);
}
/*--------------------------------------------------------------------------*/
char * fits_iter_get_tunit(iteratorCol *col) /* I - iterator col structure */
/*
  get iterator column parameter
*/
{
    return(col->tunit);
}
/*--------------------------------------------------------------------------*/
char * fits_iter_get_tdisp(iteratorCol *col) /* I -iterator col structure   */
/*
  get iterator column parameter
*/
{
    return(col->tdisp);
}
/*--------------------------------------------------------------------------*/
int ffiter(int n_cols,
           iteratorCol *cols,
           long offset,
           long n_per_loop,
           int (*work_fn)(long total_n,
                          long offset,
                          long first_n,
                          long n_values,
                          int n_cols,
                          iteratorCol *cols,
                          void *userPointer),
           void *userPointer,
           int *status)
/*
   The iterator function.  This function will pass the specified
   columns from a FITS table or pixels from a FITS image to the 
   user-supplied function.  Depending on the size of the table
   or image, only a subset of the rows or pixels may be passed to the
   function on each call, in which case the function will be called
   multiple times until all the rows or pixels have been processed.
*/
{
    typedef struct  /* structure to store the column null value */
    {  
        int      nullsize;    /* length of the null value, in bytes */
        union {   /*  default null value for the column */
            char   *stringnull;
            unsigned char   charnull;
            signed char scharnull;
            int    intnull;
            short  shortnull;
            long   longnull;
            unsigned int   uintnull;
            unsigned short ushortnull;
            unsigned long  ulongnull;
            float  floatnull;
            double doublenull;
	    LONGLONG longlongnull;
        } null;
    } colNulls;

    void *dataptr, *defaultnull;
    colNulls *col;
    int ii, jj, tstatus, naxis, bitpix;
    int typecode, hdutype, jtype, type, anynul, nfiles, nbytes;
    long totaln, nleft, frow, felement, n_optimum, i_optimum, ntodo;
    long rept, rowrept, width, tnull, naxes[9] = {1,1,1,1,1,1,1,1,1}, groups;
    double zeros = 0.;
    char message[FLEN_ERRMSG], keyname[FLEN_KEYWORD], nullstr[FLEN_VALUE];
    char **stringptr, *nullptr, *cptr;

    if (*status > 0)
        return(*status);

    if (n_cols  < 0 || n_cols > 999 )
    {
        ffpmsg("Illegal number of columms (ffiter)");
        return(*status = BAD_COL_NUM);  /* negative number of columns */
    }

    /*------------------------------------------------------------*/
    /* Make sure column numbers and datatypes are in legal range  */
    /* and column numbers and datatypes are legal.                */ 
    /* Also fill in other parameters in the column structure.     */
    /*------------------------------------------------------------*/

    ffghdt(cols[0].fptr, &hdutype, status);  /* type of first HDU */

    for (jj = 0; jj < n_cols; jj++)
    {
        /* check that output datatype code value is legal */
        type = cols[jj].datatype;  

        /* Allow variable length arrays for InputCol and InputOutputCol columns,
	   but not for OutputCol columns.  Variable length arrays have a
	   negative type code value. */

        if ((cols[jj].iotype != OutputCol) && (type<0)) {
            type*=-1;
        }

        if (type != 0      && type != TBYTE  &&
            type != TSBYTE && type != TLOGICAL && type != TSTRING &&
            type != TSHORT && type != TINT     && type != TLONG && 
            type != TFLOAT && type != TDOUBLE  && type != TCOMPLEX &&
            type != TULONG && type != TUSHORT  && type != TDBLCOMPLEX &&
	    type != TLONGLONG )
        {
	    if (type < 0) {
	      snprintf(message,FLEN_ERRMSG,
              "Variable length array not allowed for output column number %d (ffiter)",
                    jj + 1);
	    } else {
            snprintf(message,FLEN_ERRMSG,
                   "Illegal datatype for column number %d: %d  (ffiter)",
                    jj + 1, cols[jj].datatype);
	    }
	    
            ffpmsg(message);
            return(*status = BAD_DATATYPE);
        }

        /* initialize TLMINn, TLMAXn, column name, and display format */
        cols[jj].tlmin = 0;
        cols[jj].tlmax = 0;
        cols[jj].tunit[0] = '\0';
        cols[jj].tdisp[0] = '\0';

        ffghdt(cols[jj].fptr, &jtype, status);  /* get HDU type */

        if (hdutype == IMAGE_HDU) /* operating on FITS images */
        {
            if (jtype != IMAGE_HDU)
            {
                snprintf(message,FLEN_ERRMSG,
                "File %d not positioned to an image extension (ffiter)",
                    jj + 1);
                return(*status = NOT_IMAGE);
            }

            /* since this is an image, set a dummy column number = 0 */
            cols[jj].colnum = 0;
            strcpy(cols[jj].colname, "IMAGE");  /* dummy name for images */

            tstatus = 0;
            ffgkys(cols[jj].fptr, "BUNIT", cols[jj].tunit, 0, &tstatus);
        }
        else  /* operating on FITS tables */
        {
            if (jtype == IMAGE_HDU)
            {
                snprintf(message,FLEN_ERRMSG,
                "File %d not positioned to a table extension (ffiter)",
                    jj + 1);
                return(*status = NOT_TABLE);
            }

            if (cols[jj].colnum < 1)
            {
                /* find the column number for the named column */
                if (ffgcno(cols[jj].fptr, CASEINSEN, cols[jj].colname,
                           &cols[jj].colnum, status) )
                {
                    snprintf(message,FLEN_ERRMSG,
                      "Column '%s' not found for column number %d  (ffiter)",
                       cols[jj].colname, jj + 1);
                    ffpmsg(message);
                    return(*status);
                }
            }

            /* check that the column number is valid */
            if (cols[jj].colnum < 1 || 
                cols[jj].colnum > ((cols[jj].fptr)->Fptr)->tfield)
            {
                snprintf(message,FLEN_ERRMSG,
                  "Column %d has illegal table position number: %d  (ffiter)",
                    jj + 1, cols[jj].colnum);
                ffpmsg(message);
                return(*status = BAD_COL_NUM);
            }

            /* look for column description keywords and update structure */
            tstatus = 0;
            ffkeyn("TLMIN", cols[jj].colnum, keyname, &tstatus);
            ffgkyj(cols[jj].fptr, keyname, &cols[jj].tlmin, 0, &tstatus);

            tstatus = 0;
            ffkeyn("TLMAX", cols[jj].colnum, keyname, &tstatus);
            ffgkyj(cols[jj].fptr, keyname, &cols[jj].tlmax, 0, &tstatus);

            tstatus = 0;
            ffkeyn("TTYPE", cols[jj].colnum, keyname, &tstatus);
            ffgkys(cols[jj].fptr, keyname, cols[jj].colname, 0, &tstatus);
            if (tstatus)
                cols[jj].colname[0] = '\0';

            tstatus = 0;
            ffkeyn("TUNIT", cols[jj].colnum, keyname, &tstatus);
            ffgkys(cols[jj].fptr, keyname, cols[jj].tunit, 0, &tstatus);

            tstatus = 0;
            ffkeyn("TDISP", cols[jj].colnum, keyname, &tstatus);
            ffgkys(cols[jj].fptr, keyname, cols[jj].tdisp, 0, &tstatus);
        }
    }  /* end of loop over all columns */

    /*-----------------------------------------------------------------*/
    /* use the first file to set the total number of values to process */
    /*-----------------------------------------------------------------*/

    offset = maxvalue(offset, 0L);  /* make sure offset is legal */

    if (hdutype == IMAGE_HDU)   /* get total number of pixels in the image */
    {
      fits_get_img_dim(cols[0].fptr, &naxis, status);
      fits_get_img_size(cols[0].fptr, 9, naxes, status);

      tstatus = 0;
      ffgkyj(cols[0].fptr, "GROUPS", &groups, NULL, &tstatus);
      if (!tstatus && groups && (naxis > 1) && (naxes[0] == 0) )
      {
         /* this is a random groups file, with NAXIS1 = 0 */
         /* Use GCOUNT, the number of groups, as the first multiplier  */
         /* to calculate the total number of pixels in all the groups. */
         ffgkyj(cols[0].fptr, "GCOUNT", &totaln, NULL, status);

      }  else {
         totaln = naxes[0];
      }

      for (ii = 1; ii < naxis; ii++)
          totaln *= naxes[ii];

      frow = 1;
      felement = 1 + offset;
    }
    else   /* get total number or rows in the table */
    {
      ffgkyj(cols[0].fptr, "NAXIS2", &totaln, 0, status);
      frow = 1 + offset;
      felement = 1;
    }

    /*  adjust total by the input starting offset value */
    totaln -= offset;
    totaln = maxvalue(totaln, 0L);   /* don't allow negative number */

    /*------------------------------------------------------------------*/
    /* Determine number of values to pass to work function on each loop */
    /*------------------------------------------------------------------*/

    if (n_per_loop == 0)
    {
        /* Determine optimum number of values for each iteration.    */
        /* Look at all the fitsfile pointers to determine the number */
        /* of unique files.                                          */

        nfiles = 1;
        ffgrsz(cols[0].fptr, &n_optimum, status);

        for (jj = 1; jj < n_cols; jj++)
        {
            for (ii = 0; ii < jj; ii++)
            {
                if (cols[ii].fptr == cols[jj].fptr)
                   break;
            }

            if (ii == jj)  /* this is a new file */
            {
                nfiles++;
                ffgrsz(cols[jj].fptr, &i_optimum, status);
                n_optimum = minvalue(n_optimum, i_optimum);
            }
        }

        /* divid n_optimum by the number of files that will be processed */
        n_optimum = n_optimum / nfiles;
        n_optimum = maxvalue(n_optimum, 1);
    }
    else if (n_per_loop < 0)  /* must pass all the values at one time */
    {
        n_optimum = totaln;
    }
    else /* calling routine specified how many values to pass at a time */
    {
        n_optimum = minvalue(n_per_loop, totaln);
    }

    /*--------------------------------------*/
    /* allocate work arrays for each column */
    /* and determine the null pixel value   */
    /*--------------------------------------*/

    col = calloc(n_cols, sizeof(colNulls) ); /* memory for the null values */
    if (!col)
    {
        ffpmsg("ffiter failed to allocate memory for null values");
        *status = MEMORY_ALLOCATION;  /* memory allocation failed */
        return(*status);
    }

    for (jj = 0; jj < n_cols; jj++)
    {
        /* get image or column datatype and vector length */
        if (hdutype == IMAGE_HDU)   /* get total number of pixels in the image */
        {
           fits_get_img_type(cols[jj].fptr, &bitpix, status);
           switch(bitpix) {
             case BYTE_IMG:
                 typecode = TBYTE;
                 break;
             case SHORT_IMG:
                 typecode = TSHORT;
                 break;
             case LONG_IMG:
                 typecode = TLONG;
                 break;
             case FLOAT_IMG:
                 typecode = TFLOAT;
                 break;
             case DOUBLE_IMG:
                 typecode = TDOUBLE;
                 break;
             case LONGLONG_IMG:
                 typecode = TLONGLONG;
                 break;
            }
        }
        else
        {
            if (ffgtcl(cols[jj].fptr, cols[jj].colnum, &typecode, &rept,
                  &width, status) > 0)
                goto cleanup;
		
	    if (typecode < 0) {  /* if any variable length arrays, then the */ 
	        n_optimum = 1;   /* must process the table 1 row at a time */
		
              /* Allow variable length arrays for InputCol and InputOutputCol columns,
	       but not for OutputCol columns.  Variable length arrays have a
	       negative type code value. */

              if (cols[jj].iotype == OutputCol) {
 	        snprintf(message,FLEN_ERRMSG,
                "Variable length array not allowed for output column number %d (ffiter)",
                    jj + 1);
                ffpmsg(message);
                return(*status = BAD_DATATYPE);
              }
	   }
        }

        /* special case where sizeof(long) = 8: use TINT instead of TLONG */
        if (abs(typecode) == TLONG && sizeof(long) == 8 && sizeof(int) == 4) {
		if(typecode<0) {
			typecode = -TINT;
		} else {
			typecode = TINT;
		}
        }

        /* Special case: interprete 'X' column as 'B' */
        if (abs(typecode) == TBIT)
        {
            typecode  = typecode / TBIT * TBYTE;
            rept = (rept + 7) / 8;
        }

        if (cols[jj].datatype == 0)    /* output datatype not specified? */
        {
            /* special case if sizeof(long) = 8: use TINT instead of TLONG */
            if (abs(typecode) == TLONG && sizeof(long) == 8 && sizeof(int) == 4)
                cols[jj].datatype = TINT;
            else
                cols[jj].datatype = abs(typecode);
        }

        /* calc total number of elements to do on each iteration */
        if (hdutype == IMAGE_HDU || cols[jj].datatype == TSTRING)
        {
            ntodo = n_optimum; 
            cols[jj].repeat = 1;

            /* get the BLANK keyword value, if it exists */
            if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG
                || abs(typecode) == TINT || abs(typecode) == TLONGLONG)
            {
                tstatus = 0;
                ffgkyj(cols[jj].fptr, "BLANK", &tnull, 0, &tstatus);
                if (tstatus)
                {
                    tnull = 0L;  /* no null values */
                }
            }
        }
        else
        {
	    if (typecode < 0) 
	    {
              /* get max size of the variable length vector; dont't trust the value
	         given by the TFORM keyword  */
	      rept = 1;
	      for (ii = 0; ii < totaln; ii++) {
		ffgdes(cols[jj].fptr, cols[jj].colnum, frow + ii, &rowrept, NULL, status);
		
		rept = maxvalue(rept, rowrept);
	      }
            }
	    
            ntodo = n_optimum * rept;   /* vector columns */
            cols[jj].repeat = rept;

            /* get the TNULL keyword value, if it exists */
            if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG
                || abs(typecode) == TINT || abs(typecode) == TLONGLONG)
            {
                tstatus = 0;
                if (hdutype == ASCII_TBL) /* TNULLn value is a string */
                {
                    ffkeyn("TNULL", cols[jj].colnum, keyname, &tstatus);
                    ffgkys(cols[jj].fptr, keyname, nullstr, 0, &tstatus);
                    if (tstatus)
                    {
                        tnull = 0L; /* keyword doesn't exist; no null values */
                    }
                    else
                    {
                        cptr = nullstr;
                        while (*cptr == ' ')  /* skip over leading blanks */
                           cptr++;

                        if (*cptr == '\0')  /* TNULLn is all blanks? */
                            tnull = LONG_MIN;
                        else
                        {                                                
                            /* attempt to read TNULLn string as an integer */
                            ffc2ii(nullstr, &tnull, &tstatus);

                            if (tstatus)
                                tnull = LONG_MIN;  /* choose smallest value */
                        }                          /* to represent nulls */
                    }
                }
                else  /* Binary table; TNULLn value is an integer */
                {
                    ffkeyn("TNULL", cols[jj].colnum, keyname, &tstatus);
                    ffgkyj(cols[jj].fptr, keyname, &tnull, 0, &tstatus);
                    if (tstatus)
                    {
                        tnull = 0L; /* keyword doesn't exist; no null values */
                    }
                    else if (tnull == 0)
                    {
                        /* worst possible case: a value of 0 is used to   */
                        /* represent nulls in the FITS file.  We have to  */
                        /* use a non-zero null value here (zero is used to */
                        /* mean there are no null values in the array) so we */
                        /* will use the smallest possible integer instead. */

                        tnull = LONG_MIN;  /* choose smallest possible value */
                    }
                }
            }
        }

        /* Note that the data array starts with 2nd element;  */
        /* 1st element of the array gives the null data value */

        switch (cols[jj].datatype)
        {
         case TBYTE:
          cols[jj].array = calloc(ntodo + 1, sizeof(char));
          col[jj].nullsize  = sizeof(char);  /* number of bytes per value */

          if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG
              || abs(typecode) == TINT || abs(typecode) == TLONGLONG)
          {
              tnull = minvalue(tnull, 255);
              tnull = maxvalue(tnull, 0);
              col[jj].null.charnull = (unsigned char) tnull;
          }
          else
          {
              col[jj].null.charnull = (unsigned char) 255; /* use 255 as null */
          }
          break;

         case TSBYTE:
          cols[jj].array = calloc(ntodo + 1, sizeof(char));
          col[jj].nullsize  = sizeof(char);  /* number of bytes per value */

          if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG
              || abs(typecode) == TINT || abs(typecode) == TLONGLONG)
          {
              tnull = minvalue(tnull, 127);
              tnull = maxvalue(tnull, -128);
              col[jj].null.scharnull = (signed char) tnull;
          }
          else
          {
              col[jj].null.scharnull = (signed char) -128; /* use -128  null */
          }
          break;

         case TSHORT:
          cols[jj].array = calloc(ntodo + 1, sizeof(short));
          col[jj].nullsize  = sizeof(short);  /* number of bytes per value */

          if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG
              || abs(typecode) == TINT || abs(typecode) == TLONGLONG)
          {
              tnull = minvalue(tnull, SHRT_MAX);
              tnull = maxvalue(tnull, SHRT_MIN);
              col[jj].null.shortnull = (short) tnull;
          }
          else
          {
              col[jj].null.shortnull = SHRT_MIN;  /* use minimum as null */
          }
          break;

         case TUSHORT:
          cols[jj].array = calloc(ntodo + 1, sizeof(unsigned short));
          col[jj].nullsize  = sizeof(unsigned short);  /* bytes per value */

          if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG
               || abs(typecode) == TINT || abs(typecode) == TLONGLONG)
          {
              tnull = minvalue(tnull, (long) USHRT_MAX);
              tnull = maxvalue(tnull, 0);  /* don't allow negative value */
              col[jj].null.ushortnull = (unsigned short) tnull;
          }
          else
          {
              col[jj].null.ushortnull = USHRT_MAX;   /* use maximum null */
          }
          break;

         case TINT:
          cols[jj].array = calloc(sizeof(int), ntodo + 1);
          col[jj].nullsize  = sizeof(int);  /* number of bytes per value */

          if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG
               || abs(typecode) == TINT || abs(typecode) == TLONGLONG)
          {
              tnull = minvalue(tnull, INT_MAX);
              tnull = maxvalue(tnull, INT_MIN);
              col[jj].null.intnull = (int) tnull;
          }
          else
          {
              col[jj].null.intnull = INT_MIN;  /* use minimum as null */
          }
          break;

         case TUINT:
          cols[jj].array = calloc(ntodo + 1, sizeof(unsigned int));
          col[jj].nullsize  = sizeof(unsigned int);  /* bytes per value */

          if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG
               || abs(typecode) == TINT || abs(typecode) == TLONGLONG)
          {
              tnull = minvalue(tnull, INT32_MAX);
              tnull = maxvalue(tnull, 0);
              col[jj].null.uintnull = (unsigned int) tnull;
          }
          else
          {
              col[jj].null.uintnull = UINT_MAX;  /* use maximum as null */
          }
          break;

         case TLONG:
          cols[jj].array = calloc(ntodo + 1, sizeof(long));
          col[jj].nullsize  = sizeof(long);  /* number of bytes per value */

          if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG
               || abs(typecode) == TINT || abs(typecode) == TLONGLONG)
          {
              col[jj].null.longnull = tnull;
          }
          else
          {
              col[jj].null.longnull = LONG_MIN;   /* use minimum as null */
          }
          break;

         case TULONG:
          cols[jj].array = calloc(ntodo + 1, sizeof(unsigned long));
          col[jj].nullsize  = sizeof(unsigned long);  /* bytes per value */

          if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG
               || abs(typecode) == TINT || abs(typecode) == TLONGLONG)
          {
              if (tnull < 0)  /* can't use a negative null value */
                  col[jj].null.ulongnull = LONG_MAX;
              else
                  col[jj].null.ulongnull = (unsigned long) tnull;
          }
          else
          {
              col[jj].null.ulongnull = LONG_MAX;   /* use maximum as null */
          }
          break;

         case TFLOAT:
          cols[jj].array = calloc(ntodo + 1, sizeof(float));
          col[jj].nullsize  = sizeof(float);  /* number of bytes per value */

          if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG
               || abs(typecode) == TINT || abs(typecode) == TLONGLONG)
          {
              col[jj].null.floatnull = (float) tnull;
          }
          else
          {
              col[jj].null.floatnull = FLOATNULLVALUE;  /* special value */
          }
          break;

         case TCOMPLEX:
          cols[jj].array = calloc((ntodo * 2) + 1, sizeof(float));
          col[jj].nullsize  = sizeof(float);  /* number of bytes per value */
          col[jj].null.floatnull = FLOATNULLVALUE;  /* special value */
          break;

         case TDOUBLE:
          cols[jj].array = calloc(ntodo + 1, sizeof(double));
          col[jj].nullsize  = sizeof(double);  /* number of bytes per value */

          if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG
               || abs(typecode) == TINT || abs(typecode) == TLONGLONG)
          {
              col[jj].null.doublenull = (double) tnull;
          }
          else
          {
              col[jj].null.doublenull = DOUBLENULLVALUE;  /* special value */
          }
          break;

         case TDBLCOMPLEX:
          cols[jj].array = calloc((ntodo * 2) + 1, sizeof(double));
          col[jj].nullsize  = sizeof(double);  /* number of bytes per value */
          col[jj].null.doublenull = DOUBLENULLVALUE;  /* special value */
          break;

         case TSTRING:
          /* allocate array of pointers to all the strings  */
	  if( hdutype==ASCII_TBL ) rept = width;
          stringptr = calloc((ntodo + 1) , sizeof(stringptr));
          cols[jj].array = stringptr;
          col[jj].nullsize  = rept + 1;  /* number of bytes per value */

          if (stringptr)
          {
            /* allocate string to store the null string value */
            col[jj].null.stringnull = calloc(rept + 1, sizeof(char) );
            col[jj].null.stringnull[1] = 1; /* to make sure string != 0 */

            /* allocate big block for the array of table column strings */
            stringptr[0] = calloc((ntodo + 1) * (rept + 1), sizeof(char) );

            if (stringptr[0])
            {
              for (ii = 1; ii <= ntodo; ii++)
              {   /* pointer to each string */
                stringptr[ii] = stringptr[ii - 1] + (rept + 1);
              }

              /* get the TNULL keyword value, if it exists */
              tstatus = 0;
              ffkeyn("TNULL", cols[jj].colnum, keyname, &tstatus);
              ffgkys(cols[jj].fptr, keyname, nullstr, 0, &tstatus);
              if (!tstatus)
                  strncat(col[jj].null.stringnull, nullstr, rept);
            }
            else
            {
              ffpmsg("ffiter failed to allocate memory arrays");
              *status = MEMORY_ALLOCATION;  /* memory allocation failed */
              goto cleanup;
            }
          }
          break;

         case TLOGICAL:

          cols[jj].array = calloc(ntodo + 1, sizeof(char));
          col[jj].nullsize  = sizeof(char);  /* number of bytes per value */

          /* use value = 2 to flag null values in logical columns */
          col[jj].null.charnull = 2;
          break;

         case TLONGLONG:
          cols[jj].array = calloc(ntodo + 1, sizeof(LONGLONG));
          col[jj].nullsize  = sizeof(LONGLONG);  /* number of bytes per value */

          if (abs(typecode) == TBYTE || abs(typecode) == TSHORT || abs(typecode) == TLONG ||
	      abs(typecode) == TLONGLONG || abs(typecode) == TINT)
          {
              col[jj].null.longlongnull = tnull;
          }
          else
          {
              col[jj].null.longlongnull = LONGLONG_MIN;   /* use minimum as null */
          }
          break;

         default:
          snprintf(message,FLEN_ERRMSG,
                  "Column %d datatype currently not supported: %d:  (ffiter)",
                   jj + 1, cols[jj].datatype);
          ffpmsg(message);
          *status = BAD_DATATYPE;
          goto cleanup;

        }   /* end of switch block */

        /* check that all the arrays were allocated successfully */
        if (!cols[jj].array)
        {
            ffpmsg("ffiter failed to allocate memory arrays");
            *status = MEMORY_ALLOCATION;  /* memory allocation failed */
            goto cleanup;
        }
    }

    /*--------------------------------------------------*/
    /* main loop while there are values left to process */
    /*--------------------------------------------------*/

    nleft = totaln;

    while (nleft)
    {
      ntodo = minvalue(nleft, n_optimum); /* no. of values for this loop */

      /*  read input columns from FITS file(s)  */
      for (jj = 0; jj < n_cols; jj++)
      {
        if (cols[jj].iotype != OutputCol)
        {
          if (cols[jj].datatype == TSTRING)
          {
            stringptr = cols[jj].array;
            dataptr = stringptr + 1;
            defaultnull = col[jj].null.stringnull; /* ptr to the null value */
          }
          else
          {
            dataptr = (char *) cols[jj].array + col[jj].nullsize;
            defaultnull = &col[jj].null.charnull; /* ptr to the null value */
          }

          if (hdutype == IMAGE_HDU)   
          {
              if (ffgpv(cols[jj].fptr, cols[jj].datatype,
                    felement, cols[jj].repeat * ntodo, defaultnull,
                    dataptr,  &anynul, status) > 0)
              {
                 break;
              }
          }
          else
          {
	      if (ffgtcl(cols[jj].fptr, cols[jj].colnum, &typecode, &rept,&width, status) > 0)
	          goto cleanup;
		  
	      if (typecode<0)
	      {
	        /* get size of the variable length vector */
		ffgdes(cols[jj].fptr, cols[jj].colnum, frow,&cols[jj].repeat, NULL,status);
	      }
		
              if (ffgcv(cols[jj].fptr, cols[jj].datatype, cols[jj].colnum,
                    frow, felement, cols[jj].repeat * ntodo, defaultnull,
                    dataptr,  &anynul, status) > 0)
              {
                 break;
              }
          }

          /* copy the appropriate null value into first array element */

          if (anynul)   /* are there any nulls in the data? */
          {   
            if (cols[jj].datatype == TSTRING)
            {
              stringptr = cols[jj].array;
              memcpy(*stringptr, col[jj].null.stringnull, col[jj].nullsize);
            }
            else
            {
              memcpy(cols[jj].array, defaultnull, col[jj].nullsize);
            }
          }
          else /* no null values so copy zero into first element */
          {
            if (cols[jj].datatype == TSTRING)
            {
              stringptr = cols[jj].array;
              memset(*stringptr, 0, col[jj].nullsize);  
            }
            else
            {
              memset(cols[jj].array, 0, col[jj].nullsize);  
            }
          }
        }
      }

      if (*status > 0) 
         break;   /* looks like an error occurred; quit immediately */

      /* call work function */

      if (hdutype == IMAGE_HDU) 
          *status = work_fn(totaln, offset, felement, ntodo, n_cols, cols,
                    userPointer);
      else
          *status = work_fn(totaln, offset, frow, ntodo, n_cols, cols,
                    userPointer);

      if (*status > 0 || *status < -1 ) 
         break;   /* looks like an error occurred; quit immediately */

      /*  write output columns  before quiting if status = -1 */
      tstatus = 0;
      for (jj = 0; jj < n_cols; jj++)
      {
        if (cols[jj].iotype != InputCol)
        {
          if (cols[jj].datatype == TSTRING)
          {
            stringptr = cols[jj].array;
            dataptr = stringptr + 1;
            nullptr = *stringptr;
            nbytes = 2;
          }
          else
          {
            dataptr = (char *) cols[jj].array + col[jj].nullsize;
            nullptr = (char *) cols[jj].array;
            nbytes = col[jj].nullsize;
          }

          if (memcmp(nullptr, &zeros, nbytes) ) 
          {
            /* null value flag not zero; must check for and write nulls */
            if (hdutype == IMAGE_HDU)   
            {
                if (ffppn(cols[jj].fptr, cols[jj].datatype, 
                      felement, cols[jj].repeat * ntodo, dataptr,
                      nullptr, &tstatus) > 0)
                break;
            }
            else
            {
	    	if (ffgtcl(cols[jj].fptr, cols[jj].colnum, &typecode, &rept,&width, status) > 0)
		    goto cleanup;
		    
		if (typecode<0)  /* variable length array colum */
		{
		   ffgdes(cols[jj].fptr, cols[jj].colnum, frow,&cols[jj].repeat, NULL,status);
		}

                if (ffpcn(cols[jj].fptr, cols[jj].datatype, cols[jj].colnum, frow,
                      felement, cols[jj].repeat * ntodo, dataptr,
                      nullptr, &tstatus) > 0)
                break;
            }
          }
          else
          { 
            /* no null values; just write the array */
            if (hdutype == IMAGE_HDU)   
            {
                if (ffppr(cols[jj].fptr, cols[jj].datatype,
                      felement, cols[jj].repeat * ntodo, dataptr,
                      &tstatus) > 0)
                break;
            }
            else
            {
	    	if (ffgtcl(cols[jj].fptr, cols[jj].colnum, &typecode, &rept,&width, status) > 0)
		    goto cleanup;
		    
		if (typecode<0)  /* variable length array column */
		{
		   ffgdes(cols[jj].fptr, cols[jj].colnum, frow,&cols[jj].repeat, NULL,status);
		}

                 if (ffpcl(cols[jj].fptr, cols[jj].datatype, cols[jj].colnum, frow,
                      felement, cols[jj].repeat * ntodo, dataptr,
                      &tstatus) > 0)
                break;
            }
          }
        }
      }

      if (*status == 0)
         *status = tstatus;   /* propagate any error status from the writes */

      if (*status) 
         break;   /* exit on any error */

      nleft -= ntodo;

      if (hdutype == IMAGE_HDU)
          felement += ntodo;
      else
          frow  += ntodo;
    }

cleanup:

    /*----------------------------------*/
    /* free work arrays for the columns */
    /*----------------------------------*/

    for (jj = 0; jj < n_cols; jj++)
    {
        if (cols[jj].datatype == TSTRING)
        {
            if (cols[jj].array)
            {
                stringptr = cols[jj].array;
                free(*stringptr);     /* free the block of strings */
                free(col[jj].null.stringnull); /* free the null string */
            }
        }
        if (cols[jj].array)
            free(cols[jj].array); /* memory for the array of values from the col */
    }
    free(col);   /* the structure containing the null values */
    return(*status);
}

cfitsio/putcolb.c0000644000225700000360000010750213246025103013621 0ustar  cagordonlhea/*  This file, putcolb.c, contains routines that write data elements to    */
/*  a FITS image or table with char (byte) datatype.                       */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int ffpprb( fitsfile *fptr,  /* I - FITS file pointer                       */
            long  group,     /* I - group to write(1 = 1st group)           */
            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
            LONGLONG  nelem,     /* I - number of values to write               */
            unsigned char *array, /* I - array of values that are written   */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written).
*/
{
    long row;
    unsigned char nullvalue;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_write_compressed_pixels(fptr, TBYTE, firstelem, nelem,
            0, array, &nullvalue, status);
        return(*status);
    }

    row=maxvalue(1,group);

    ffpclb(fptr, 2, row, firstelem, nelem, array, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffppnb( fitsfile *fptr,  /* I - FITS file pointer                       */
            long  group,     /* I - group to write(1 = 1st group)           */
            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
            LONGLONG  nelem,     /* I - number of values to write               */
            unsigned char *array, /* I - array of values that are written   */
            unsigned char nulval, /* I - undefined pixel value              */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).  Any array values
  that are equal to the value of nulval will be replaced with the null
  pixel value that is appropriate for this column.
*/
{
    long row;
    unsigned char nullvalue;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */


        nullvalue = nulval;  /* set local variable */
        fits_write_compressed_pixels(fptr, TBYTE, firstelem, nelem,
            1, array, &nullvalue, status);
        return(*status);
    }

    row=maxvalue(1,group);

    ffpcnb(fptr, 2, row, firstelem, nelem, array, nulval, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffp2db(fitsfile *fptr,   /* I - FITS file pointer                     */
           long  group,      /* I - group to write(1 = 1st group)         */
           LONGLONG  ncols,      /* I - number of pixels in each row of array */
           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
           unsigned char *array, /* I - array to be written               */
           int  *status)     /* IO - error status                         */
/*
  Write an entire 2-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).
*/
{
    /* call the 3D writing routine, with the 3rd dimension = 1 */

    ffp3db(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffp3db(fitsfile *fptr,   /* I - FITS file pointer                     */
           long  group,      /* I - group to write(1 = 1st group)         */
           LONGLONG  ncols,      /* I - number of pixels in each row of array */
           LONGLONG  nrows,      /* I - number of rows in each plane of array */
           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
           LONGLONG  naxis3,     /* I - FITS image NAXIS3 value               */
           unsigned char *array, /* I - array to be written               */
           int  *status)     /* IO - error status                         */
/*
  Write an entire 3-D cube of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).
*/
{
    long tablerow, ii, jj;
    LONGLONG nfits, narray;
    long fpixel[3]= {1,1,1}, lpixel[3];
    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */
           
    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */
        lpixel[0] = (long) ncols;
        lpixel[1] = (long) nrows;
        lpixel[2] = (long) naxis3;
       
        fits_write_compressed_img(fptr, TBYTE, fpixel, lpixel,
            0,  array, NULL, status);
    
        return(*status);
    }

    tablerow=maxvalue(1,group);

    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
    {
      /* all the image pixels are contiguous, so write all at once */
      ffpclb(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status);
      return(*status);
    }

    if (ncols < naxis1 || nrows < naxis2)
       return(*status = BAD_DIMEN);

    nfits = 1;   /* next pixel in FITS image to write to */
    narray = 0;  /* next pixel in input array to be written */

    /* loop over naxis3 planes in the data cube */
    for (jj = 0; jj < naxis3; jj++)
    {
      /* loop over the naxis2 rows in the FITS image, */
      /* writing naxis1 pixels to each row            */

      for (ii = 0; ii < naxis2; ii++)
      {
       if (ffpclb(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0)
         return(*status);

       nfits += naxis1;
       narray += ncols;
      }
      narray += (nrows - naxis2) * ncols;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpssb(fitsfile *fptr,   /* I - FITS file pointer                       */
           long  group,      /* I - group to write(1 = 1st group)           */
           long  naxis,      /* I - number of data axes in array            */
           long  *naxes,     /* I - size of each FITS axis                  */
           long  *fpixel,    /* I - 1st pixel in each axis to write (1=1st) */
           long  *lpixel,    /* I - last pixel in each axis to write        */
           unsigned char *array, /* I - array to be written                 */
           int  *status)     /* IO - error status                           */
/*
  Write a subsection of pixels to the primary array or image.
  A subsection is defined to be any contiguous rectangular
  array of pixels within the n-dimensional FITS data file.
  Data conversion and scaling will be performed if necessary 
  (e.g, if the datatype of the FITS array is not the same as
  the array being written).
*/
{
    long tablerow;
    LONGLONG fpix[7], dimen[7], astart, pstart;
    LONGLONG off2, off3, off4, off5, off6, off7;
    LONGLONG st10, st20, st30, st40, st50, st60, st70;
    LONGLONG st1, st2, st3, st4, st5, st6, st7;
    long ii, i1, i2, i3, i4, i5, i6, i7, irange[7];

    if (*status > 0)
        return(*status);

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_write_compressed_img(fptr, TBYTE, fpixel, lpixel,
            0,  array, NULL, status);
    
        return(*status);
    }

    if (naxis < 1 || naxis > 7)
      return(*status = BAD_DIMEN);

    tablerow=maxvalue(1,group);

     /* calculate the size and number of loops to perform in each dimension */
    for (ii = 0; ii < 7; ii++)
    {
      fpix[ii]=1;
      irange[ii]=1;
      dimen[ii]=1;
    }

    for (ii = 0; ii < naxis; ii++)
    {    
      fpix[ii]=fpixel[ii];
      irange[ii]=lpixel[ii]-fpixel[ii]+1;
      dimen[ii]=naxes[ii];
    }

    i1=irange[0];

    /* compute the pixel offset between each dimension */
    off2 =     dimen[0];
    off3 = off2 * dimen[1];
    off4 = off3 * dimen[2];
    off5 = off4 * dimen[3];
    off6 = off5 * dimen[4];
    off7 = off6 * dimen[5];

    st10 = fpix[0];
    st20 = (fpix[1] - 1) * off2;
    st30 = (fpix[2] - 1) * off3;
    st40 = (fpix[3] - 1) * off4;
    st50 = (fpix[4] - 1) * off5;
    st60 = (fpix[5] - 1) * off6;
    st70 = (fpix[6] - 1) * off7;

    /* store the initial offset in each dimension */
    st1 = st10;
    st2 = st20;
    st3 = st30;
    st4 = st40;
    st5 = st50;
    st6 = st60;
    st7 = st70;

    astart = 0;

    for (i7 = 0; i7 < irange[6]; i7++)
    {
     for (i6 = 0; i6 < irange[5]; i6++)
     {
      for (i5 = 0; i5 < irange[4]; i5++)
      {
       for (i4 = 0; i4 < irange[3]; i4++)
       {
        for (i3 = 0; i3 < irange[2]; i3++)
        {
         pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7;

         for (i2 = 0; i2 < irange[1]; i2++)
         {
           if (ffpclb(fptr, 2, tablerow, pstart, i1, &array[astart],
              status) > 0)
              return(*status);

           astart += i1;
           pstart += off2;
         }
         st2 = st20;
         st3 = st3+off3;    
        }
        st3 = st30;
        st4 = st4+off4;
       }
       st4 = st40;
       st5 = st5+off5;
      }
      st5 = st50;
      st6 = st6+off6;
     }
     st6 = st60;
     st7 = st7+off7;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpgpb( fitsfile *fptr,   /* I - FITS file pointer                      */
            long  group,      /* I - group to write(1 = 1st group)          */
            long  firstelem,  /* I - first vector element to write(1 = 1st) */
            long  nelem,      /* I - number of values to write              */
            unsigned char *array, /* I - array of values that are written   */
            int  *status)     /* IO - error status                          */
/*
  Write an array of group parameters to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written).
*/
{
    long row;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffpclb(fptr, 1L, row, firstelem, nelem, array, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpclb( fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
            unsigned char *array, /* I - array of values to write           */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to a column in the current FITS HDU.
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer to a virtual column in a 1 or more grouped FITS primary
  array.  FITSIO treats a primary array as a binary table with
  2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.

  The input array of values will be converted to the datatype of the column 
  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary.
*/
{
    int tcode, maxelem2, hdutype, writeraw;
    long twidth, incre;
    long  ntodo;
    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull, maxelem;
    double scale, zero;
    char tform[20], cform[20];
    char message[FLEN_ERRMSG];

    char snull[20];   /*  the FITS null value  */

    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
    void *buffer;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    buffer = cbuff;

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
        tform, &twidth, &tcode, &maxelem2, &startpos,  &elemnum, &incre,
        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
        return(*status);
    maxelem = maxelem2;

    if (tcode == TSTRING)   
         ffcfmt(tform, cform);     /* derive C format for writing strings */

    /*
      if there is no scaling 
      then we can simply write the raw data bytes into the FITS file if the
      datatype of the FITS column is the same as the input values.  Otherwise,
      we must convert the raw values into the scaled and/or machine dependent
      format in a temporary buffer that has been allocated for this purpose.
    */
    if (scale == 1. && zero == 0. && tcode == TBYTE)
    {
        writeraw = 1;
        if (nelem < (LONGLONG)INT32_MAX) {
            maxelem = nelem;
        } else {
            maxelem = INT32_MAX;
        }
     }
    else
        writeraw = 0;

    /*---------------------------------------------------------------------*/
    /*  Now write the pixels to the FITS column.                           */
    /*  First call the ffXXfYY routine to  (1) convert the datatype        */
    /*  if necessary, and (2) scale the values by the FITS TSCALn and      */
    /*  TZEROn linear scaling parameters into a temporary buffer.          */
    /*---------------------------------------------------------------------*/
    remain = nelem;           /* remaining number of values to write  */
    next = 0;                 /* next element in array to be written  */
    rownum = 0;               /* row number, relative to firstrow     */

    while (remain)
    {
        /* limit the number of pixels to process a one time to the number that
           will fit in the buffer space or to the number of pixels that remain
           in the current vector, which ever is smaller.
        */
        ntodo = (long) minvalue(remain, maxelem);      
        ntodo = (long) minvalue(ntodo, (repeat - elemnum));

        wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);
        ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */

        switch (tcode) 
        {
            case (TBYTE):
              if (writeraw)
              {
                /* write raw input bytes without conversion */
                ffpi1b(fptr, ntodo, incre, &array[next], status);
              }
              else
              {
                /* convert the raw data before writing to FITS file */
                ffi1fi1(&array[next], ntodo, scale, zero,
                        (unsigned char *) buffer, status);
                ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status);
              }

              break;

            case (TLONGLONG):

                ffi1fi8(&array[next], ntodo, scale, zero,
                        (LONGLONG *) buffer, status);
                ffpi8b(fptr, ntodo, incre, (long *) buffer, status);
                break;

            case (TSHORT):
 
                ffi1fi2(&array[next], ntodo, scale, zero,
                        (short *) buffer, status);
                ffpi2b(fptr, ntodo, incre, (short *) buffer, status);
                break;

            case (TLONG):

                ffi1fi4(&array[next], ntodo, scale, zero,
                        (INT32BIT *) buffer, status);
                ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status);
                break;

            case (TFLOAT):

                ffi1fr4(&array[next], ntodo, scale, zero,
                        (float *)  buffer, status);
                ffpr4b(fptr, ntodo, incre, (float *) buffer, status);
                break;

            case (TDOUBLE):
                ffi1fr8(&array[next], ntodo, scale, zero,
                        (double *) buffer, status);
                ffpr8b(fptr, ntodo, incre, (double *) buffer, status);
                break;

            case (TSTRING):  /* numerical column in an ASCII table */

                if (strchr(tform,'A'))
                {
                    /* write raw input bytes without conversion        */
                    /* This case is a hack to let users write a stream */
                    /* of bytes directly to the 'A' format column      */

                    if (incre == twidth)
                        ffpbyt(fptr, ntodo, &array[next], status);
                    else
                        ffpbytoff(fptr, twidth, ntodo/twidth, incre - twidth, 
                                &array[next], status);
                    break;
                }
                else if (cform[1] != 's')  /*  "%s" format is a string */
                {
                  ffi1fstr(&array[next], ntodo, scale, zero, cform,
                          twidth, (char *) buffer, status);

                  if (incre == twidth)    /* contiguous bytes */
                     ffpbyt(fptr, ntodo * twidth, buffer, status);
                  else
                     ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
                            status);
                  break;
                }
                /* can't write to string column, so fall thru to default: */

            default:  /*  error trap  */
                snprintf(message, FLEN_ERRMSG,
                       "Cannot write numbers to column %d which has format %s",
                        colnum,tform);
                ffpmsg(message);
                if (hdutype == ASCII_TBL)
                    return(*status = BAD_ATABLE_FORMAT);
                else
                    return(*status = BAD_BTABLE_FORMAT);

        } /* End of switch block */

        /*-------------------------*/
        /*  Check for fatal error  */
        /*-------------------------*/
        if (*status > 0)  /* test for error during previous write operation */
        {
          snprintf(message,FLEN_ERRMSG,
          "Error writing elements %.0f thru %.0f of input data array (ffpclb).",
              (double) (next+1), (double) (next+ntodo));
          ffpmsg(message);
          return(*status);
        }

        /*--------------------------------------------*/
        /*  increment the counters for the next loop  */
        /*--------------------------------------------*/
        remain -= ntodo;
        if (remain)
        {
            next += ntodo;
            elemnum += ntodo;
            if (elemnum == repeat)  /* completed a row; start on next row */
            {
                elemnum = 0;
                rownum++;
            }
        }
    }  /*  End of main while Loop  */


    /*--------------------------------*/
    /*  check for numerical overflow  */
    /*--------------------------------*/
    if (*status == OVERFLOW_ERR)
    {
      ffpmsg(
      "Numerical overflow during type conversion while writing FITS data.");
      *status = NUM_OVERFLOW;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpcnb( fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
            unsigned char *array,   /* I - array of values to write         */
            unsigned char nulvalue, /* I - flag for undefined pixels        */
            int  *status)    /* IO - error status                           */
/*
  Write an array of elements to the specified column of a table.  Any input
  pixels equal to the value of nulvalue will be replaced by the appropriate
  null value in the output FITS file. 

  The input array of values will be converted to the datatype of the column 
  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary
*/
{
    tcolumn *colptr;
    LONGLONG  ngood = 0, nbad = 0, ii;
    LONGLONG repeat, first, fstelm, fstrow;
    int tcode, overflow = 0;

    if (*status > 0)
        return(*status);

    /* reset position to the correct HDU if necessary */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
    {
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
    }
    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
    {
        if ( ffrdef(fptr, status) > 0)               /* rescan header */
            return(*status);
    }

    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
    colptr += (colnum - 1);     /* offset to correct column structure */

    tcode  = colptr->tdatatype;

    if (tcode > 0)
       repeat = colptr->trepeat;  /* repeat count for this column */
    else
       repeat = firstelem -1 + nelem;  /* variable length arrays */

    /* if variable length array, first write the whole input vector, 
       then go back and fill in the nulls */
    if (tcode < 0) {
      if (ffpclb(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) {
        if (*status == NUM_OVERFLOW) 
	{
	  /* ignore overflows, which are possibly the null pixel values */
	  /*  overflow = 1;   */
	  *status = 0;
	} else { 
          return(*status);
	}
      }
    }

    /* absolute element number in the column */
    first = (firstrow - 1) * repeat + firstelem;

    for (ii = 0; ii < nelem; ii++)
    {
      if (array[ii] != nulvalue)  /* is this a good pixel? */
      {
         if (nbad)  /* write previous string of bad pixels */
         {
            fstelm = ii - nbad + first;  /* absolute element number */
            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

            if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
                return(*status);

            nbad=0;
         }

         ngood = ngood + 1;  /* the consecutive number of good pixels */
      }
      else
      {
         if (ngood)  /* write previous string of good pixels */
         {
            fstelm = ii - ngood + first;  /* absolute element number */
            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

            if (tcode > 0) {  /* variable length arrays have already been written */
              if (ffpclb(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
                status) > 0) {
		if (*status == NUM_OVERFLOW) 
		{
		  overflow = 1;
		  *status = 0;
		} else { 
                  return(*status);
		}
	      }
	    }
            ngood=0;
         }

         nbad = nbad + 1;  /* the consecutive number of bad pixels */
      }
    }
    
    /* finished loop;  now just write the last set of pixels */

    if (ngood)  /* write last string of good pixels */
    {
      fstelm = ii - ngood + first;  /* absolute element number */
      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

      if (tcode > 0) {  /* variable length arrays have already been written */
        ffpclb(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
      }
    }
    else if (nbad) /* write last string of bad pixels */
    {
      fstelm = ii - nbad + first;  /* absolute element number */
      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

      ffpclu(fptr, colnum, fstrow, fstelm, nbad, status);
    }

    if (*status <= 0) {
      if (overflow) {
        *status = NUM_OVERFLOW;
      }
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpextn( fitsfile *fptr,        /* I - FITS file pointer                        */
            LONGLONG  offset,      /* I - byte offset from start of extension data */
            LONGLONG  nelem,       /* I - number of elements to write              */
            void *buffer,          /* I - stream of bytes to write                 */
            int  *status)          /* IO - error status                            */
/*
  Write a stream of bytes to the current FITS HDU.  This primative routine is mainly
  for writing non-standard "conforming" extensions and should not be used
  for standard IMAGE, TABLE or BINTABLE extensions.
*/
{
    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /* reset position to the correct HDU if necessary */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    /* rescan header if data structure is undefined */
    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
        if ( ffrdef(fptr, status) > 0)               
            return(*status);

    /* move to write position */
    ffmbyt(fptr, (fptr->Fptr)->datastart+ offset, IGNORE_EOF, status);
    
    /* write the buffer */
    ffpbyt(fptr, nelem, buffer, status); 

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffi1fi1(unsigned char *input,  /* I - array of values to be converted  */
            long ntodo,            /* I - number of elements in the array  */
            double scale,          /* I - FITS TSCALn or BSCALE value      */
            double zero,           /* I - FITS TZEROn or BZERO  value      */
            unsigned char *output, /* O - output array of converted values */
            int *status)           /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        memcpy(output, input, ntodo); /* just copy input to output */
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = ( ((double) input[ii]) - zero) / scale;

            if (dvalue < DUCHAR_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = 0;
            }
            else if (dvalue > DUCHAR_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = UCHAR_MAX;
            }
            else
                output[ii] = (unsigned char) (dvalue + .5);
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffi1fi2(unsigned char *input,  /* I - array of values to be converted  */
            long ntodo,            /* I - number of elements in the array  */
            double scale,          /* I - FITS TSCALn or BSCALE value      */
            double zero,           /* I - FITS TZEROn or BZERO  value      */
            short *output,         /* O - output array of converted values */
            int *status)           /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
            output[ii] = input[ii];   /* just copy input to output */
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (((double) input[ii]) - zero) / scale;

            if (dvalue < DSHRT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MIN;
            }
            else if (dvalue > DSHRT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (short) (dvalue + .5);
                else
                    output[ii] = (short) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffi1fi4(unsigned char *input,  /* I - array of values to be converted  */
            long ntodo,            /* I - number of elements in the array  */
            double scale,          /* I - FITS TSCALn or BSCALE value      */
            double zero,           /* I - FITS TZEROn or BZERO  value      */
            INT32BIT *output,      /* O - output array of converted values */
            int *status)           /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
            output[ii] = (INT32BIT) input[ii];   /* copy input to output */
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (((double) input[ii]) - zero) / scale;

            if (dvalue < DINT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MIN;
            }
            else if (dvalue > DINT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (INT32BIT) (dvalue + .5);
                else
                    output[ii] = (INT32BIT) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffi1fi8(unsigned char *input, /* I - array of values to be converted  */
            long ntodo,           /* I - number of elements in the array  */
            double scale,         /* I - FITS TSCALn or BSCALE value      */
            double zero,          /* I - FITS TZEROn or BZERO  value      */
            LONGLONG *output,     /* O - output array of converted values */
            int *status)          /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DLONGLONG_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = LONGLONG_MIN;
            }
            else if (dvalue > DLONGLONG_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = LONGLONG_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (LONGLONG) (dvalue + .5);
                else
                    output[ii] = (LONGLONG) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffi1fr4(unsigned char *input,  /* I - array of values to be converted  */
            long ntodo,            /* I - number of elements in the array  */
            double scale,          /* I - FITS TSCALn or BSCALE value      */
            double zero,           /* I - FITS TZEROn or BZERO  value      */
            float *output,         /* O - output array of converted values */
            int *status)           /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = (float) input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
            output[ii] = (float) (( ( (double) input[ii] ) - zero) / scale);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffi1fr8(unsigned char *input,  /* I - array of values to be converted  */
            long ntodo,            /* I - number of elements in the array  */
            double scale,          /* I - FITS TSCALn or BSCALE value      */
            double zero,           /* I - FITS TZEROn or BZERO  value      */
            double *output,        /* O - output array of converted values */
            int *status)           /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = (double) input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
            output[ii] = ( ( (double) input[ii] ) - zero) / scale;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffi1fstr(unsigned char *input, /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            char *cform,       /* I - format for output string values  */
            long twidth,       /* I - width of each field, in chars    */
            char *output,      /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do scaling if required.
*/
{
    long ii;
    double dvalue;
    char *cptr;

    cptr = output;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
           sprintf(output, cform, (double) input[ii]);
           output += twidth;

           if (*output)  /* if this char != \0, then overflow occurred */
              *status = OVERFLOW_ERR;
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
          dvalue = ((double) input[ii] - zero) / scale;
          sprintf(output, cform, dvalue);
          output += twidth;

          if (*output)  /* if this char != \0, then overflow occurred */
            *status = OVERFLOW_ERR;
        }
    }

    /* replace any commas with periods (e.g., in French locale) */
    while ((cptr = strchr(cptr, ','))) *cptr = '.';
    
    return(*status);
}
cfitsio/putcold.c0000644000225700000360000011212013246025103013613 0ustar  cagordonlhea/*  This file, putcold.c, contains routines that write data elements to    */
/*  a FITS image or table, with double datatype.                           */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int ffpprd( fitsfile *fptr,  /* I - FITS file pointer                       */
            long  group,     /* I - group to write(1 = 1st group)           */
            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
            LONGLONG  nelem,     /* I - number of values to write               */
            double *array,   /* I - array of values that are written        */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written).
*/
{
    long row;
    double nullvalue;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_write_compressed_pixels(fptr, TDOUBLE, firstelem, nelem,
            0, array, &nullvalue, status);
        return(*status);
    }

    row=maxvalue(1,group);

    ffpcld(fptr, 2, row, firstelem, nelem, array, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffppnd( fitsfile *fptr,   /* I - FITS file pointer                       */
            long  group,      /* I - group to write(1 = 1st group)           */
            LONGLONG  firstelem,  /* I - first vector element to write(1 = 1st)  */
            LONGLONG  nelem,      /* I - number of values to write               */
            double *array,    /* I - array of values that are written        */
            double nulval,    /* I - undefined pixel value                   */
            int  *status)     /* IO - error status                           */
/*
  Write an array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).  Any array values
  that are equal to the value of nulval will be replaced with the null
  pixel value that is appropriate for this column.
*/
{
    long row;
    double nullvalue;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        nullvalue = nulval;  /* set local variable */
        fits_write_compressed_pixels(fptr, TDOUBLE, firstelem, nelem,
            1, array, &nullvalue, status);
        return(*status);
    }

    row=maxvalue(1,group);

    ffpcnd(fptr, 2, row, firstelem, nelem, array, nulval, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffp2dd(fitsfile *fptr,   /* I - FITS file pointer                     */
           long  group,      /* I - group to write(1 = 1st group)         */
           LONGLONG  ncols,      /* I - number of pixels in each row of array */
           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
           double *array,    /* I - array to be written                   */
           int  *status)     /* IO - error status                         */
/*
  Write an entire 2-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).
*/
{
    /* call the 3D writing routine, with the 3rd dimension = 1 */

    ffp3dd(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffp3dd(fitsfile *fptr,   /* I - FITS file pointer                     */
           long  group,      /* I - group to write(1 = 1st group)         */
           LONGLONG  ncols,      /* I - number of pixels in each row of array */
           LONGLONG  nrows,      /* I - number of rows in each plane of array */
           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
           LONGLONG  naxis3,     /* I - FITS image NAXIS3 value               */
           double *array,    /* I - array to be written                   */
           int  *status)     /* IO - error status                         */
/*
  Write an entire 3-D cube of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).
*/
{
    long tablerow, ii, jj;
    long fpixel[3]= {1,1,1}, lpixel[3];
    LONGLONG nfits, narray;
    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */
        lpixel[0] = (long) ncols;
        lpixel[1] = (long) nrows;
        lpixel[2] = (long) naxis3;

        fits_write_compressed_img(fptr, TDOUBLE, fpixel, lpixel,
            0,  array, NULL, status);
    
        return(*status);
    }

    tablerow=maxvalue(1,group);

    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
    {
      /* all the image pixels are contiguous, so write all at once */
      ffpcld(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status);
      return(*status);
    }

    if (ncols < naxis1 || nrows < naxis2)
       return(*status = BAD_DIMEN);

    nfits = 1;   /* next pixel in FITS image to write to */
    narray = 0;  /* next pixel in input array to be written */

    /* loop over naxis3 planes in the data cube */
    for (jj = 0; jj < naxis3; jj++)
    {
      /* loop over the naxis2 rows in the FITS image, */
      /* writing naxis1 pixels to each row            */

      for (ii = 0; ii < naxis2; ii++)
      {
       if (ffpcld(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0)
         return(*status);

       nfits += naxis1;
       narray += ncols;
      }
      narray += (nrows - naxis2) * ncols;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpssd(fitsfile *fptr,   /* I - FITS file pointer                       */
           long  group,      /* I - group to write(1 = 1st group)           */
           long  naxis,      /* I - number of data axes in array            */
           long  *naxes,     /* I - size of each FITS axis                  */
           long  *fpixel,    /* I - 1st pixel in each axis to write (1=1st) */
           long  *lpixel,    /* I - last pixel in each axis to write        */
           double *array,    /* I - array to be written                     */
           int  *status)     /* IO - error status                           */
/*
  Write a subsection of pixels to the primary array or image.
  A subsection is defined to be any contiguous rectangular
  array of pixels within the n-dimensional FITS data file.
  Data conversion and scaling will be performed if necessary 
  (e.g, if the datatype of the FITS array is not the same as
  the array being written).
*/
{
    long tablerow;
    LONGLONG fpix[7], dimen[7], astart, pstart;
    LONGLONG off2, off3, off4, off5, off6, off7;
    LONGLONG st10, st20, st30, st40, st50, st60, st70;
    LONGLONG st1, st2, st3, st4, st5, st6, st7;
    long ii, i1, i2, i3, i4, i5, i6, i7, irange[7];

    if (*status > 0)
        return(*status);

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_write_compressed_img(fptr, TDOUBLE, fpixel, lpixel,
            0,  array, NULL, status);
    
        return(*status);
    }

    if (naxis < 1 || naxis > 7)
      return(*status = BAD_DIMEN);

    tablerow=maxvalue(1,group);

     /* calculate the size and number of loops to perform in each dimension */
    for (ii = 0; ii < 7; ii++)
    {
      fpix[ii]=1;
      irange[ii]=1;
      dimen[ii]=1;
    }

    for (ii = 0; ii < naxis; ii++)
    {    
      fpix[ii]=fpixel[ii];
      irange[ii]=lpixel[ii]-fpixel[ii]+1;
      dimen[ii]=naxes[ii];
    }

    i1=irange[0];

    /* compute the pixel offset between each dimension */
    off2 =     dimen[0];
    off3 = off2 * dimen[1];
    off4 = off3 * dimen[2];
    off5 = off4 * dimen[3];
    off6 = off5 * dimen[4];
    off7 = off6 * dimen[5];

    st10 = fpix[0];
    st20 = (fpix[1] - 1) * off2;
    st30 = (fpix[2] - 1) * off3;
    st40 = (fpix[3] - 1) * off4;
    st50 = (fpix[4] - 1) * off5;
    st60 = (fpix[5] - 1) * off6;
    st70 = (fpix[6] - 1) * off7;

    /* store the initial offset in each dimension */
    st1 = st10;
    st2 = st20;
    st3 = st30;
    st4 = st40;
    st5 = st50;
    st6 = st60;
    st7 = st70;

    astart = 0;

    for (i7 = 0; i7 < irange[6]; i7++)
    {
     for (i6 = 0; i6 < irange[5]; i6++)
     {
      for (i5 = 0; i5 < irange[4]; i5++)
      {
       for (i4 = 0; i4 < irange[3]; i4++)
       {
        for (i3 = 0; i3 < irange[2]; i3++)
        {
         pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7;

         for (i2 = 0; i2 < irange[1]; i2++)
         {
           if (ffpcld(fptr, 2, tablerow, pstart, i1, &array[astart],
              status) > 0)
              return(*status);

           astart += i1;
           pstart += off2;
         }
         st2 = st20;
         st3 = st3+off3;    
        }
        st3 = st30;
        st4 = st4+off4;
       }
       st4 = st40;
       st5 = st5+off5;
      }
      st5 = st50;
      st6 = st6+off6;
     }
     st6 = st60;
     st7 = st7+off7;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpgpd( fitsfile *fptr,   /* I - FITS file pointer                      */
            long  group,      /* I - group to write(1 = 1st group)          */
            long  firstelem,  /* I - first vector element to write(1 = 1st) */
            long  nelem,      /* I - number of values to write              */
            double *array,    /* I - array of values that are written       */
            int  *status)     /* IO - error status                          */
/*
  Write an array of group parameters to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written).
*/
{
    long row;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffpcld(fptr, 1L, row, firstelem, nelem, array, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpcld( fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
            double *array,   /* I - array of values to write                */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to a column in the current FITS HDU.
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer to a virtual column in a 1 or more grouped FITS primary
  array.  FITSIO treats a primary array as a binary table
  with 2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.

  The input array of values will be converted to the datatype of the column 
  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary.
*/
{
    int tcode, maxelem2, hdutype, writeraw;
    long twidth, incre;
    long ntodo;
    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull, maxelem;
    double scale, zero;
    char tform[20], cform[20];
    char message[FLEN_ERRMSG];

    char snull[20];   /*  the FITS null value  */

    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
    void *buffer;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    buffer = cbuff;

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
        tform, &twidth, &tcode, &maxelem2, &startpos,  &elemnum, &incre,
        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
        return(*status);
    maxelem = maxelem2;

    if (tcode == TSTRING)   
         ffcfmt(tform, cform);     /* derive C format for writing strings */

    /*
      if there is no scaling and the native machine format is not byteswapped,
      then we can simply write the raw data bytes into the FITS file if the
      datatype of the FITS column is the same as the input values.  Otherwise,
      we must convert the raw values into the scaled and/or machine dependent
      format in a temporary buffer that has been allocated for this purpose.
    */
    if (scale == 1. && zero == 0. && 
       MACHINE == NATIVE && tcode == TDOUBLE)
    {
        writeraw = 1;
        if (nelem < (LONGLONG)INT32_MAX) {
            maxelem = nelem;
        } else {
            maxelem = INT32_MAX/8;
        }
     }
    else
        writeraw = 0;

    /*---------------------------------------------------------------------*/
    /*  Now write the pixels to the FITS column.                           */
    /*  First call the ffXXfYY routine to  (1) convert the datatype        */
    /*  if necessary, and (2) scale the values by the FITS TSCALn and      */
    /*  TZEROn linear scaling parameters into a temporary buffer.          */
    /*---------------------------------------------------------------------*/
    remain = nelem;           /* remaining number of values to write  */
    next = 0;                 /* next element in array to be written  */
    rownum = 0;               /* row number, relative to firstrow     */

    while (remain)
    {
        /* limit the number of pixels to process a one time to the number that
           will fit in the buffer space or to the number of pixels that remain
           in the current vector, which ever is smaller.
        */
        ntodo = (long) minvalue(remain, maxelem);      
        ntodo = (long) minvalue(ntodo, (repeat - elemnum));

        wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);

        ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */

        switch (tcode) 
        {
            case (TDOUBLE):
              if (writeraw)
              {
                /* write raw input bytes without conversion */
                ffpr8b(fptr, ntodo, incre, &array[next], status);
              }
              else
              {
                /* convert the raw data before writing to FITS file */
                ffr8fr8(&array[next], ntodo, scale, zero,
                        (double *) buffer, status);
                ffpr8b(fptr, ntodo, incre, (double *) buffer, status);
              }

              break;

            case (TLONGLONG):

                ffr8fi8(&array[next], ntodo, scale, zero,
                        (LONGLONG *) buffer, status);
                ffpi8b(fptr, ntodo, incre, (long *) buffer, status);
                break;

            case (TBYTE):
 
                ffr8fi1(&array[next], ntodo, scale, zero, 
                        (unsigned char *) buffer, status);
                ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status);
                break;

            case (TSHORT):

                ffr8fi2(&array[next], ntodo, scale, zero, 
                       (short *) buffer, status);
                ffpi2b(fptr, ntodo, incre, (short *) buffer, status);
                break;

            case (TLONG):

                ffr8fi4(&array[next], ntodo, scale, zero,
                        (INT32BIT *) buffer, status);
                ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status);
                break;

            case (TFLOAT):
                ffr8fr4(&array[next], ntodo, scale, zero,
                        (float *) buffer, status);
                ffpr4b(fptr, ntodo, incre, (float *) buffer, status);
                break;

            case (TSTRING):  /* numerical column in an ASCII table */

                if (cform[1] != 's')  /*  "%s" format is a string */
                {
                  ffr8fstr(&array[next], ntodo, scale, zero, cform,
                          twidth, (char *) buffer, status);

                  if (incre == twidth)    /* contiguous bytes */
                     ffpbyt(fptr, ntodo * twidth, buffer, status);
                  else
                     ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
                            status);

                  break;
                }
                /* can't write to string column, so fall thru to default: */

            default:  /*  error trap  */
                snprintf(message, FLEN_ERRMSG,
                      "Cannot write numbers to column %d which has format %s",
                       colnum,tform);
                ffpmsg(message);
                if (hdutype == ASCII_TBL)
                    return(*status = BAD_ATABLE_FORMAT);
                else
                    return(*status = BAD_BTABLE_FORMAT);

        } /* End of switch block */

        /*-------------------------*/
        /*  Check for fatal error  */
        /*-------------------------*/
        if (*status > 0)  /* test for error during previous write operation */
        {
          snprintf(message,FLEN_ERRMSG,
          "Error writing elements %.0f thru %.0f of input data array (ffpcld).",
              (double) (next+1), (double) (next+ntodo));
         ffpmsg(message);
         return(*status);
        }

        /*--------------------------------------------*/
        /*  increment the counters for the next loop  */
        /*--------------------------------------------*/
        remain -= ntodo;
        if (remain)
        {
            next += ntodo;
            elemnum += ntodo;
            if (elemnum == repeat)  /* completed a row; start on next row */
            {
                elemnum = 0;
                rownum++;
            }
        }
    }  /*  End of main while Loop  */


    /*--------------------------------*/
    /*  check for numerical overflow  */
    /*--------------------------------*/
    if (*status == OVERFLOW_ERR)
    {
        ffpmsg(
        "Numerical overflow during type conversion while writing FITS data.");
        *status = NUM_OVERFLOW;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpclm( fitsfile *fptr,   /* I - FITS file pointer                       */
            int  colnum,      /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,   /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem,  /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,      /* I - number of values to write               */
            double *array,    /* I - array of values to write                */
            int  *status)     /* IO - error status                           */
/*
  Write an array of double complex values to a column in the current FITS HDU.
  Each complex number if interpreted as a pair of float values.
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer to a virtual column in a 1 or more grouped FITS primary
  array.  FITSIO treats a primary array as a binary table
  with 2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.

  The input array of values will be converted to the datatype of the column
  if necessary, but normally complex values should only be written to a binary
  table with TFORMn = 'rM' where r is an optional repeat count. The TSCALn and
  TZERO keywords should not be used with complex numbers because mathmatically
  the scaling should only be applied to the real (first) component of the
  complex value.
*/
{
    /* simply multiply the number of elements by 2, and call ffpcld */

    ffpcld(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1, 
            nelem * 2, array, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpcnd( fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
            double *array,   /* I - array of values to write                */
            double nulvalue, /* I - value used to flag undefined pixels     */
            int  *status)    /* IO - error status                           */
/*
  Write an array of elements to the specified column of a table.  Any input
  pixels equal to the value of nulvalue will be replaced by the appropriate
  null value in the output FITS file. 

  The input array of values will be converted to the datatype of the column 
  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary
*/
{
    tcolumn *colptr;
    LONGLONG  ngood = 0, nbad = 0, ii;
    LONGLONG repeat, first, fstelm, fstrow;
    int tcode, overflow = 0;

    if (*status > 0)
        return(*status);

    /* reset position to the correct HDU if necessary */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
    {
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
    }
    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
    {
        if ( ffrdef(fptr, status) > 0)               /* rescan header */
            return(*status);
    }

    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
    colptr += (colnum - 1);     /* offset to correct column structure */

    tcode  = colptr->tdatatype;

    if (tcode > 0)
       repeat = colptr->trepeat;  /* repeat count for this column */
    else
       repeat = firstelem -1 + nelem;  /* variable length arrays */

    if (abs(tcode) >= TCOMPLEX)
    { /* treat complex columns as pairs of numbers */
        repeat *= 2;
    }

    /* if variable length array, first write the whole input vector, 
       then go back and fill in the nulls */
    if (tcode < 0) {
      if (ffpcld(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) {
	if (*status == NUM_OVERFLOW) 
	{
	  /* ignore overflows, which are possibly the null pixel values */
	  /*  overflow = 1;   */
	  *status = 0;
	} else { 
          return(*status);
	}
      }
    }

    /* absolute element number in the column */
    first = (firstrow - 1) * repeat + firstelem;

    for (ii = 0; ii < nelem; ii++)
    {
      if (array[ii] != nulvalue)  /* is this a good pixel? */
      {
         if (nbad)  /* write previous string of bad pixels */
         {
            fstelm = ii - nbad + first;  /* absolute element number */
            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

            /* call ffpcluc, not ffpclu, in case we are writing to a
	       complex ('C') binary table column */
            if (ffpcluc(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
                return(*status);

            nbad=0;
         }

         ngood = ngood +1;  /* the consecutive number of good pixels */
      }
      else
      {
         if (ngood)  /* write previous string of good pixels */
         {
            fstelm = ii - ngood + first;  /* absolute element number */
            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

            if (tcode > 0) {  /* variable length arrays have already been written */
              if (ffpcld(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
                status) > 0) {
		if (*status == NUM_OVERFLOW) 
		{
		  overflow = 1;
		  *status = 0;
		} else {
                  return(*status);
		}
	      }
            }
            ngood=0;
         }

         nbad = nbad +1;  /* the consecutive number of bad pixels */
      }
    }

    /* finished loop;  now just write the last set of pixels */

    if (ngood)  /* write last string of good pixels */
    {
      fstelm = ii - ngood + first;  /* absolute element number */
      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

      if (tcode > 0) {  /* variable length arrays have already been written */
        ffpcld(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
      }
    }
    else if (nbad) /* write last string of bad pixels */
    {
      fstelm = ii - nbad + first;  /* absolute element number */
      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
      ffpcluc(fptr, colnum, fstrow, fstelm, nbad, status);
    }

    if (*status <= 0) {
      if (overflow) {
        *status = NUM_OVERFLOW;
      }
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffr8fi1(double *input,         /* I - array of values to be converted  */
            long ntodo,            /* I - number of elements in the array  */
            double scale,          /* I - FITS TSCALn or BSCALE value      */
            double zero,           /* I - FITS TZEROn or BZERO  value      */
            unsigned char *output, /* O - output array of converted values */
            int *status)           /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
            if (input[ii] < DUCHAR_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = 0;
            }
            else if (input[ii] > DUCHAR_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = UCHAR_MAX;
            }
            else
                output[ii] = (unsigned char) input[ii];
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DUCHAR_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = 0;
            }
            else if (dvalue > DUCHAR_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = UCHAR_MAX;
            }
            else
                output[ii] = (unsigned char) (dvalue + .5);
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffr8fi2(double *input,     /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            short *output,     /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
            if (input[ii] < DSHRT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MIN;
            }
            else if (input[ii] > DSHRT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MAX;
            }
            else
                output[ii] = (short) input[ii];
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DSHRT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MIN;
            }
            else if (dvalue > DSHRT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (short) (dvalue + .5);
                else
                    output[ii] = (short) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffr8fi4(double *input,     /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            INT32BIT *output,  /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
            if (input[ii] < DINT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MIN;
            }
            else if (input[ii] > DINT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MAX;
            }
            else
                output[ii] = (INT32BIT) input[ii];
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DINT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MIN;
            }
            else if (dvalue > DINT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (INT32BIT) (dvalue + .5);
                else
                    output[ii] = (INT32BIT) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffr8fi8(double *input,     /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            LONGLONG *output,      /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
            if (input[ii] < DLONGLONG_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = LONGLONG_MIN;
            }
            else if (input[ii] > DLONGLONG_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = LONGLONG_MAX;
            }
            else
                output[ii] = (LONGLONG) input[ii];
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DLONGLONG_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = LONGLONG_MIN;
            }
            else if (dvalue > DLONGLONG_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = LONGLONG_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (LONGLONG) (dvalue + .5);
                else
                    output[ii] = (LONGLONG) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffr8fr4(double *input,     /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            float *output,     /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = (float) input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
            output[ii] = (float) ((input[ii] - zero) / scale);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffr8fr8(double *input,     /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            double *output,    /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;

    if (scale == 1. && zero == 0.)
    {       
      memcpy(output, input, ntodo * sizeof(double) ); /* copy input to output */
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
            output[ii] = (input[ii] - zero) / scale;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffr8fstr(double *input,     /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            char *cform,       /* I - format for output string values  */
            long twidth,       /* I - width of each field, in chars    */
            char *output,      /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do scaling if required.
*/
{
    long ii;
    double dvalue;
    char *cptr;
    
    cptr = output;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
           sprintf(output, cform, input[ii]);
           output += twidth;

           if (*output)  /* if this char != \0, then overflow occurred */
              *status = OVERFLOW_ERR;
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
          dvalue = (input[ii] - zero) / scale;
          sprintf(output, cform, dvalue);
          output += twidth;

          if (*output)  /* if this char != \0, then overflow occurred */
            *status = OVERFLOW_ERR;
        }
    }

    /* replace any commas with periods (e.g., in French locale) */
    while ((cptr = strchr(cptr, ','))) *cptr = '.';
    
    return(*status);
}
cfitsio/putcole.c0000644000225700000360000011320513246025103013621 0ustar  cagordonlhea/*  This file, putcole.c, contains routines that write data elements to    */
/*  a FITS image or table, with float datatype.                            */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int ffppre( fitsfile *fptr,  /* I - FITS file pointer                       */
            long  group,     /* I - group to write(1 = 1st group)           */
            LONGLONG firstelem, /* I - first vector element to write(1 = 1st)  */
            LONGLONG nelem,     /* I - number of values to write               */
            float *array,    /* I - array of values that are written        */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written).

  This routine cannot be called directly by users to write to large
  arrays with > 2**31 pixels (although CFITSIO can do so by passing
  the firstelem thru a LONGLONG sized global variable)
*/
{
    long row;
    float nullvalue;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_write_compressed_pixels(fptr, TFLOAT, firstelem, nelem,
            0, array, &nullvalue, status);
        return(*status);
    }

    row=maxvalue(1,group);

    ffpcle(fptr, 2, row, firstelem, nelem, array, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffppne( fitsfile *fptr,  /* I - FITS file pointer                       */
            long  group,     /* I - group to write(1 = 1st group)           */
            LONGLONG firstelem, /* I - first vector element to write(1 = 1st)  */
            LONGLONG nelem,     /* I - number of values to write               */
            float *array,    /* I - array of values that are written        */
            float nulval,    /* I - undefined pixel value                   */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).  Any array values
  that are equal to the value of nulval will be replaced with the null
  pixel value that is appropriate for this column.

  This routine cannot be called directly by users to write to large
  arrays with > 2**31 pixels (although CFITSIO can do so by passing
  the firstelem thru a LONGLONG sized global variable)
*/
{
    long row;
    float nullvalue;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        nullvalue = nulval;  /* set local variable */
        fits_write_compressed_pixels(fptr, TFLOAT, firstelem, nelem,
            1, array, &nullvalue, status);
        return(*status);
    }

    row=maxvalue(1,group);

    ffpcne(fptr, 2, row, firstelem, nelem, array, nulval, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffp2de(fitsfile *fptr,   /* I - FITS file pointer                     */
           long  group,      /* I - group to write(1 = 1st group)         */
           LONGLONG  ncols,      /* I - number of pixels in each row of array */
           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
           float *array,     /* I - array to be written                   */
           int  *status)     /* IO - error status                         */
/*
  Write an entire 2-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).

  This routine does not support writing to large images with
  more than 2**31 pixels.
*/
{
    /* call the 3D writing routine, with the 3rd dimension = 1 */

    ffp3de(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffp3de(fitsfile *fptr,   /* I - FITS file pointer                     */
           long  group,      /* I - group to write(1 = 1st group)         */
           LONGLONG  ncols,      /* I - number of pixels in each row of array */
           LONGLONG  nrows,      /* I - number of rows in each plane of array */
           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
           LONGLONG  naxis3,     /* I - FITS image NAXIS3 value               */
           float *array,     /* I - array to be written                   */
           int  *status)     /* IO - error status                         */
/*
  Write an entire 3-D cube of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).

  This routine does not support writing to large images with
  more than 2**31 pixels.
*/
{
    long tablerow, ii, jj;
    long fpixel[3]= {1,1,1}, lpixel[3];
    LONGLONG nfits, narray;
    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */
           
    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */
        lpixel[0] = (long) ncols;
        lpixel[1] = (long) nrows;
        lpixel[2] = (long) naxis3;
       
        fits_write_compressed_img(fptr, TFLOAT, fpixel, lpixel,
            0,  array, NULL, status);
    
        return(*status);
    }

    tablerow=maxvalue(1,group);

    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
    {
      /* all the image pixels are contiguous, so write all at once */
      ffpcle(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status);
      return(*status);
    }

    if (ncols < naxis1 || nrows < naxis2)
       return(*status = BAD_DIMEN);

    nfits = 1;   /* next pixel in FITS image to write to */
    narray = 0;  /* next pixel in input array to be written */

    /* loop over naxis3 planes in the data cube */
    for (jj = 0; jj < naxis3; jj++)
    {
      /* loop over the naxis2 rows in the FITS image, */
      /* writing naxis1 pixels to each row            */

      for (ii = 0; ii < naxis2; ii++)
      {
       if (ffpcle(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0)
         return(*status);

       nfits += naxis1;
       narray += ncols;
      }
      narray += (nrows - naxis2) * ncols;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpsse(fitsfile *fptr,   /* I - FITS file pointer                       */
           long  group,      /* I - group to write(1 = 1st group)           */
           long  naxis,      /* I - number of data axes in array            */
           long  *naxes,     /* I - size of each FITS axis                  */
           long  *fpixel,    /* I - 1st pixel in each axis to write (1=1st) */
           long  *lpixel,    /* I - last pixel in each axis to write        */
           float *array,     /* I - array to be written                     */
           int  *status)     /* IO - error status                           */
/*
  Write a subsection of pixels to the primary array or image.
  A subsection is defined to be any contiguous rectangular
  array of pixels within the n-dimensional FITS data file.
  Data conversion and scaling will be performed if necessary 
  (e.g, if the datatype of the FITS array is not the same as
  the array being written).
*/
{
    long tablerow;
    LONGLONG fpix[7], dimen[7], astart, pstart;
    LONGLONG off2, off3, off4, off5, off6, off7;
    LONGLONG st10, st20, st30, st40, st50, st60, st70;
    LONGLONG st1, st2, st3, st4, st5, st6, st7;
    long ii, i1, i2, i3, i4, i5, i6, i7, irange[7];

    if (*status > 0)
        return(*status);

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_write_compressed_img(fptr, TFLOAT, fpixel, lpixel,
            0,  array, NULL, status);
    
        return(*status);
    }

    if (naxis < 1 || naxis > 7)
      return(*status = BAD_DIMEN);

    tablerow=maxvalue(1,group);

     /* calculate the size and number of loops to perform in each dimension */
    for (ii = 0; ii < 7; ii++)
    {
      fpix[ii]=1;
      irange[ii]=1;
      dimen[ii]=1;
    }

    for (ii = 0; ii < naxis; ii++)
    {    
      fpix[ii]=fpixel[ii];
      irange[ii]=lpixel[ii]-fpixel[ii]+1;
      dimen[ii]=naxes[ii];
    }

    i1=irange[0];

    /* compute the pixel offset between each dimension */
    off2 =     dimen[0];
    off3 = off2 * dimen[1];
    off4 = off3 * dimen[2];
    off5 = off4 * dimen[3];
    off6 = off5 * dimen[4];
    off7 = off6 * dimen[5];

    st10 = fpix[0];
    st20 = (fpix[1] - 1) * off2;
    st30 = (fpix[2] - 1) * off3;
    st40 = (fpix[3] - 1) * off4;
    st50 = (fpix[4] - 1) * off5;
    st60 = (fpix[5] - 1) * off6;
    st70 = (fpix[6] - 1) * off7;

    /* store the initial offset in each dimension */
    st1 = st10;
    st2 = st20;
    st3 = st30;
    st4 = st40;
    st5 = st50;
    st6 = st60;
    st7 = st70;

    astart = 0;

    for (i7 = 0; i7 < irange[6]; i7++)
    {
     for (i6 = 0; i6 < irange[5]; i6++)
     {
      for (i5 = 0; i5 < irange[4]; i5++)
      {
       for (i4 = 0; i4 < irange[3]; i4++)
       {
        for (i3 = 0; i3 < irange[2]; i3++)
        {
         pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7;

         for (i2 = 0; i2 < irange[1]; i2++)
         {
           if (ffpcle(fptr, 2, tablerow, pstart, i1, &array[astart],
              status) > 0)
              return(*status);

           astart += i1;
           pstart += off2;
         }
         st2 = st20;
         st3 = st3+off3;    
        }
        st3 = st30;
        st4 = st4+off4;
       }
       st4 = st40;
       st5 = st5+off5;
      }
      st5 = st50;
      st6 = st6+off6;
     }
     st6 = st60;
     st7 = st7+off7;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpgpe( fitsfile *fptr,   /* I - FITS file pointer                      */
            long  group,      /* I - group to write(1 = 1st group)          */
            long  firstelem,  /* I - first vector element to write(1 = 1st) */
            long  nelem,      /* I - number of values to write              */
            float *array,     /* I - array of values that are written       */
            int  *status)     /* IO - error status                          */
/*
  Write an array of group parameters to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written).
*/
{
    long row;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffpcle(fptr, 1L, row, firstelem, nelem, array, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpcle( fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
            float *array,    /* I - array of values to write                */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to a column in the current FITS HDU.
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer to a virtual column in a 1 or more grouped FITS primary
  array.  FITSIO treats a primary array as a binary table
  with 2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.

  The input array of values will be converted to the datatype of the column 
  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary.
*/
{
    int tcode, maxelem2, hdutype, writeraw;
    long twidth, incre;
    long ntodo;
    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull, maxelem;
    double scale, zero;
    char tform[20], cform[20];
    char message[FLEN_ERRMSG];

    char snull[20];   /*  the FITS null value  */

    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
    void *buffer;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    buffer = cbuff;

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
        tform, &twidth, &tcode, &maxelem2, &startpos,  &elemnum, &incre,
        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
        return(*status);
    maxelem = maxelem2;

    if (tcode == TSTRING)   
         ffcfmt(tform, cform);     /* derive C format for writing strings */

    /*
       if there is no scaling and the native machine format is not byteswapped
       then we can simply write the raw data bytes into the FITS file if the
       datatype of the FITS column is the same as the input values.  Otherwise,
       we must convert the raw values into the scaled and/or machine dependent
       format in a temporary buffer that has been allocated for this purpose.
    */
    if (scale == 1. && zero == 0. && 
       MACHINE == NATIVE && tcode == TFLOAT)
    {
        writeraw = 1;
        if (nelem < (LONGLONG)INT32_MAX) {
            maxelem = nelem;
        } else {
            maxelem = INT32_MAX/4;
        }
     }
    else
        writeraw = 0;

    /*---------------------------------------------------------------------*/
    /*  Now write the pixels to the FITS column.                           */
    /*  First call the ffXXfYY routine to  (1) convert the datatype        */
    /*  if necessary, and (2) scale the values by the FITS TSCALn and      */
    /*  TZEROn linear scaling parameters into a temporary buffer.          */
    /*---------------------------------------------------------------------*/
    remain = nelem;           /* remaining number of values to write  */
    next = 0;                 /* next element in array to be written  */
    rownum = 0;               /* row number, relative to firstrow     */

    while (remain)
    {
        /* limit the number of pixels to process a one time to the number that
           will fit in the buffer space or to the number of pixels that remain
           in the current vector, which ever is smaller.
        */
        ntodo = (long) minvalue(remain, maxelem);      
        ntodo = (long) minvalue(ntodo, (repeat - elemnum));

        wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);

        ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */

        switch (tcode) 
        {
            case (TFLOAT):
              if (writeraw)
              {
                /* write raw input bytes without conversion */
                ffpr4b(fptr, ntodo, incre, &array[next], status);
              }
              else
              {
                /* convert the raw data before writing to FITS file */
                ffr4fr4(&array[next], ntodo, scale, zero,
                        (float *) buffer, status);
                ffpr4b(fptr, ntodo, incre, (float *) buffer, status);
              }

              break;

            case (TLONGLONG):

                ffr4fi8(&array[next], ntodo, scale, zero,
                        (LONGLONG *) buffer, status);
                ffpi8b(fptr, ntodo, incre, (long *) buffer, status);
                break;

            case (TBYTE):
 
                ffr4fi1(&array[next], ntodo, scale, zero, 
                        (unsigned char *) buffer, status);
                ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status);
                break;

            case (TSHORT):

                ffr4fi2(&array[next], ntodo, scale, zero,
                        (short *) buffer, status);
                ffpi2b(fptr, ntodo, incre, (short *) buffer, status);
                break;

            case (TLONG):

                ffr4fi4(&array[next], ntodo, scale, zero,
                        (INT32BIT *) buffer, status);
                ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status);
                break;

            case (TDOUBLE):
                ffr4fr8(&array[next], ntodo, scale, zero,
                       (double *) buffer, status);
                ffpr8b(fptr, ntodo, incre, (double *) buffer, status);
                break;

            case (TSTRING):  /* numerical column in an ASCII table */

                if (cform[1] != 's')  /*  "%s" format is a string */
                {
                  ffr4fstr(&array[next], ntodo, scale, zero, cform,
                          twidth, (char *) buffer, status);

                  if (incre == twidth)    /* contiguous bytes */
                     ffpbyt(fptr, ntodo * twidth, buffer, status);
                  else
                     ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
                            status);

                  break;
                }
                /* can't write to string column, so fall thru to default: */

            default:  /*  error trap  */
                snprintf(message, FLEN_ERRMSG, 
                       "Cannot write numbers to column %d which has format %s",
                        colnum,tform);
                ffpmsg(message);
                if (hdutype == ASCII_TBL)
                    return(*status = BAD_ATABLE_FORMAT);
                else
                    return(*status = BAD_BTABLE_FORMAT);

        } /* End of switch block */

        /*-------------------------*/
        /*  Check for fatal error  */
        /*-------------------------*/
        if (*status > 0)  /* test for error during previous write operation */
        {
          snprintf(message,FLEN_ERRMSG,
          "Error writing elements %.0f thru %.0f of input data array (ffpcle).",
             (double) (next+1), (double) (next+ntodo));
         ffpmsg(message);
         return(*status);
        }

        /*--------------------------------------------*/
        /*  increment the counters for the next loop  */
        /*--------------------------------------------*/
        remain -= ntodo;
        if (remain)
        {
            next += ntodo;
            elemnum += ntodo;
            if (elemnum == repeat)  /* completed a row; start on next row */
            {
                elemnum = 0;
                rownum++;
            }
        }
    }  /*  End of main while Loop  */


    /*--------------------------------*/
    /*  check for numerical overflow  */
    /*--------------------------------*/
    if (*status == OVERFLOW_ERR)
    {
        ffpmsg(
        "Numerical overflow during type conversion while writing FITS data.");
        *status = NUM_OVERFLOW;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpclc( fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
            float *array,    /* I - array of values to write                */
            int  *status)    /* IO - error status                           */
/*
  Write an array of complex values to a column in the current FITS HDU.
  Each complex number if interpreted as a pair of float values.
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer to a virtual column in a 1 or more grouped FITS primary
  array.  FITSIO treats a primary array as a binary table
  with 2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.

  The input array of values will be converted to the datatype of the column
  if necessary, but normally complex values should only be written to a binary
  table with TFORMn = 'rC' where r is an optional repeat count. The TSCALn and
  TZERO keywords should not be used with complex numbers because mathmatically
  the scaling should only be applied to the real (first) component of the
  complex value.
*/
{
    /* simply multiply the number of elements by 2, and call ffpcle */

    ffpcle(fptr, colnum, firstrow, (firstelem - 1) * 2 + 1,
            nelem * 2, array, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpcne( fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
            float *array,    /* I - array of values to write                */
            float  nulvalue, /* I - value used to flag undefined pixels     */
            int  *status)    /* IO - error status                           */
/*
  Write an array of elements to the specified column of a table.  Any input
  pixels equal to the value of nulvalue will be replaced by the appropriate
  null value in the output FITS file. 

  The input array of values will be converted to the datatype of the column 
  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary
*/
{
    tcolumn *colptr;
    LONGLONG  ngood = 0, nbad = 0, ii;
    LONGLONG repeat, first, fstelm, fstrow;
    int tcode, overflow = 0;

    if (*status > 0)
        return(*status);

    /* reset position to the correct HDU if necessary */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
    {
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
    }
    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
    {
        if ( ffrdef(fptr, status) > 0)               /* rescan header */
            return(*status);
    }

    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
    colptr += (colnum - 1);     /* offset to correct column structure */

    tcode  = colptr->tdatatype;

    if (tcode > 0)
       repeat = colptr->trepeat;  /* repeat count for this column */
    else
       repeat = firstelem -1 + nelem;  /* variable length arrays */

    if (abs(tcode) >= TCOMPLEX)
    { /* treat complex columns as pairs of numbers */
        repeat *= 2;
    }
    
    /* if variable length array, first write the whole input vector, 
       then go back and fill in the nulls */
    if (tcode < 0) {
      if (ffpcle(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) {
        if (*status == NUM_OVERFLOW) 
	{
	  /* ignore overflows, which are possibly the null pixel values */
	  /*  overflow = 1;   */
	  *status = 0;
	} else { 
          return(*status);
	}
      }
    }

    /* absolute element number in the column */
    first = (firstrow - 1) * repeat + firstelem;

    for (ii = 0; ii < nelem; ii++)
    {
      if (array[ii] != nulvalue)  /* is this a good pixel? */
      {
         if (nbad)  /* write previous string of bad pixels */
         {
            fstelm = ii - nbad + first;  /* absolute element number */
            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

            /* call ffpcluc, not ffpclu, in case we are writing to a
	       complex ('C') binary table column */
            if (ffpcluc(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
                return(*status);

            nbad=0;
         }

         ngood = ngood +1;  /* the consecutive number of good pixels */
      }
      else
      {
         if (ngood)  /* write previous string of good pixels */
         {
            fstelm = ii - ngood + first;  /* absolute element number */
            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

            if (tcode > 0) {  /* variable length arrays have already been written */
              if (ffpcle(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
                status) > 0) {
		if (*status == NUM_OVERFLOW) 
		{
		  overflow = 1;
		  *status = 0;
		} else { 
                  return(*status);
		}
              }
	    }
            ngood=0;
         }

         nbad = nbad +1;  /* the consecutive number of bad pixels */
      }
    }

    /* finished loop;  now just write the last set of pixels */

    if (ngood)  /* write last string of good pixels */
    {
      fstelm = ii - ngood + first;  /* absolute element number */
      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

      if (tcode > 0) {  /* variable length arrays have already been written */
        ffpcle(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
      }
    }
    else if (nbad) /* write last string of bad pixels */
    {
      fstelm = ii - nbad + first;  /* absolute element number */
      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
      ffpcluc(fptr, colnum, fstrow, fstelm, nbad, status);
    }
    
    if (*status <= 0) {
      if (overflow) {
        *status = NUM_OVERFLOW;
      }
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffr4fi1(float *input,          /* I - array of values to be converted  */
            long ntodo,            /* I - number of elements in the array  */
            double scale,          /* I - FITS TSCALn or BSCALE value      */
            double zero,           /* I - FITS TZEROn or BZERO  value      */
            unsigned char *output, /* O - output array of converted values */
            int *status)           /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
            if (input[ii] < DUCHAR_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = 0;
            }
            else if (input[ii] > DUCHAR_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = UCHAR_MAX;
            }
            else
                output[ii] = (unsigned char) input[ii];
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DUCHAR_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = 0;
            }
            else if (dvalue > DUCHAR_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = UCHAR_MAX;
            }
            else
                output[ii] = (unsigned char) (dvalue + .5);
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffr4fi2(float *input,      /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            short *output,     /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {           
        for (ii = 0; ii < ntodo; ii++)
        {
            if (input[ii] < DSHRT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MIN;
            }
            else if (input[ii] > DSHRT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MAX;
            }
            else
                output[ii] = (short) input[ii];
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DSHRT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MIN;
            }
            else if (dvalue > DSHRT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (short) (dvalue + .5);
                else
                    output[ii] = (short) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffr4fi4(float *input,      /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            INT32BIT *output,  /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
            if (input[ii] < DINT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MIN;
            }
            else if (input[ii] > DINT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MAX;
            }
            else
                output[ii] = (INT32BIT) input[ii];
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DINT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MIN;
            }
            else if (dvalue > DINT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (INT32BIT) (dvalue + .5);
                else
                    output[ii] = (INT32BIT) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffr4fi8(float *input,      /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            LONGLONG *output,  /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
            if (input[ii] < DLONGLONG_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = LONGLONG_MIN;
            }
            else if (input[ii] > DLONGLONG_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = LONGLONG_MAX;
            }
            else
                output[ii] = (long) input[ii];
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DLONGLONG_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = LONGLONG_MIN;
            }
            else if (dvalue > DINT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = LONGLONG_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (LONGLONG) (dvalue + .5);
                else
                    output[ii] = (LONGLONG) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffr4fr4(float *input,      /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            float *output,     /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;

    if (scale == 1. && zero == 0.)
    {       
      memcpy(output, input, ntodo * sizeof(float) ); /* copy input to output */
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
            output[ii] = (float) ((input[ii] - zero) / scale);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffr4fr8(float *input,      /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            double *output,    /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = (double) input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
            output[ii] = (input[ii] - zero) / scale;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffr4fstr(float *input,     /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            char *cform,       /* I - format for output string values  */
            long twidth,       /* I - width of each field, in chars    */
            char *output,      /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do scaling if required.
*/
{
    long ii;
    double dvalue;
    char *cptr;
    
    cptr = output;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
           sprintf(output, cform, (double) input[ii]);
           output += twidth;

           if (*output)  /* if this char != \0, then overflow occurred */
              *status = OVERFLOW_ERR;
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
          dvalue = (input[ii] - zero) / scale;
          sprintf(output, cform, dvalue);
          output += twidth;

          if (*output)  /* if this char != \0, then overflow occurred */
            *status = OVERFLOW_ERR;
        }
    }

    /* replace any commas with periods (e.g., in French locale) */
    while ((cptr = strchr(cptr, ','))) *cptr = '.';
    
    return(*status);
}
cfitsio/putcoli.c0000644000225700000360000010404013246025103013622 0ustar  cagordonlhea/*  This file, putcoli.c, contains routines that write data elements to    */
/*  a FITS image or table, with short datatype.                            */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int ffppri( fitsfile *fptr,  /* I - FITS file pointer                       */
            long  group,     /* I - group to write (1 = 1st group)          */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
            short *array,    /* I - array of values that are written        */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written).
*/
{
    long row;
    short nullvalue;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */


        fits_write_compressed_pixels(fptr, TSHORT, firstelem, nelem,
            0, array, &nullvalue, status);
        return(*status);
    }

    row=maxvalue(1,group);

    ffpcli(fptr, 2, row, firstelem, nelem, array, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffppni( fitsfile *fptr,  /* I - FITS file pointer                       */
            long  group,     /* I - group to write(1 = 1st group)           */
            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
            LONGLONG  nelem,     /* I - number of values to write               */
            short *array,    /* I - array of values that are written        */
            short nulval,    /* I - undefined pixel value                   */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).  Any array values
  that are equal to the value of nulval will be replaced with the null
  pixel value that is appropriate for this column.
*/
{
    long row;
    short nullvalue;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        nullvalue = nulval;  /* set local variable */
        fits_write_compressed_pixels(fptr, TSHORT, firstelem, nelem,
            1, array, &nullvalue, status);
        return(*status);
    }

    row=maxvalue(1,group);

    ffpcni(fptr, 2, row, firstelem, nelem, array, nulval, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffp2di(fitsfile *fptr,   /* I - FITS file pointer                     */
           long  group,      /* I - group to write(1 = 1st group)         */
           LONGLONG  ncols,      /* I - number of pixels in each row of array */
           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
           short *array,     /* I - array to be written                   */
           int  *status)     /* IO - error status                         */
/*
  Write an entire 2-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).
*/
{
    /* call the 3D writing routine, with the 3rd dimension = 1 */

    ffp3di(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffp3di(fitsfile *fptr,   /* I - FITS file pointer                     */
           long  group,      /* I - group to write(1 = 1st group)         */
           LONGLONG  ncols,      /* I - number of pixels in each row of array */
           LONGLONG  nrows,      /* I - number of rows in each plane of array */
           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
           LONGLONG  naxis3,     /* I - FITS image NAXIS3 value               */
           short *array,     /* I - array to be written                   */
           int  *status)     /* IO - error status                         */
/*
  Write an entire 3-D cube of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).
*/
{
    long tablerow, ii, jj;
    long fpixel[3]= {1,1,1}, lpixel[3];
    LONGLONG nfits, narray;
    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */
           
    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */
        lpixel[0] = (long) ncols;
        lpixel[1] = (long) nrows;
        lpixel[2] = (long) naxis3;
       
        fits_write_compressed_img(fptr, TSHORT, fpixel, lpixel,
            0,  array, NULL, status);
    
        return(*status);
    }

    tablerow=maxvalue(1,group);

    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
    {
      /* all the image pixels are contiguous, so write all at once */
      ffpcli(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status);
      return(*status);
    }

    if (ncols < naxis1 || nrows < naxis2)
       return(*status = BAD_DIMEN);

    nfits = 1;   /* next pixel in FITS image to write to */
    narray = 0;  /* next pixel in input array to be written */

    /* loop over naxis3 planes in the data cube */
    for (jj = 0; jj < naxis3; jj++)
    {
      /* loop over the naxis2 rows in the FITS image, */
      /* writing naxis1 pixels to each row            */

      for (ii = 0; ii < naxis2; ii++)
      {
       if (ffpcli(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0)
         return(*status);

       nfits += naxis1;
       narray += ncols;
      }
      narray += (nrows - naxis2) * ncols;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpssi(fitsfile *fptr,   /* I - FITS file pointer                       */
           long  group,      /* I - group to write(1 = 1st group)           */
           long  naxis,      /* I - number of data axes in array            */
           long  *naxes,     /* I - size of each FITS axis                  */
           long  *fpixel,    /* I - 1st pixel in each axis to write (1=1st) */
           long  *lpixel,    /* I - last pixel in each axis to write        */
           short *array,     /* I - array to be written                     */
           int  *status)     /* IO - error status                           */
/*
  Write a subsection of pixels to the primary array or image.
  A subsection is defined to be any contiguous rectangular
  array of pixels within the n-dimensional FITS data file.
  Data conversion and scaling will be performed if necessary 
  (e.g, if the datatype of the FITS array is not the same as
  the array being written).
*/
{
    long tablerow;
    LONGLONG fpix[7], dimen[7], astart, pstart;
    LONGLONG off2, off3, off4, off5, off6, off7;
    LONGLONG st10, st20, st30, st40, st50, st60, st70;
    LONGLONG st1, st2, st3, st4, st5, st6, st7;
    long ii, i1, i2, i3, i4, i5, i6, i7, irange[7];

    if (*status > 0)
        return(*status);

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_write_compressed_img(fptr, TSHORT, fpixel, lpixel,
            0,  array, NULL, status);

        return(*status);
    }

    if (naxis < 1 || naxis > 7)
      return(*status = BAD_DIMEN);

    tablerow=maxvalue(1,group);

     /* calculate the size and number of loops to perform in each dimension */
    for (ii = 0; ii < 7; ii++)
    {
      fpix[ii]=1;
      irange[ii]=1;
      dimen[ii]=1;
    }

    for (ii = 0; ii < naxis; ii++)
    {    
      fpix[ii]=fpixel[ii];
      irange[ii]=lpixel[ii]-fpixel[ii]+1;
      dimen[ii]=naxes[ii];
    }

    i1=irange[0];

    /* compute the pixel offset between each dimension */
    off2 =     dimen[0];
    off3 = off2 * dimen[1];
    off4 = off3 * dimen[2];
    off5 = off4 * dimen[3];
    off6 = off5 * dimen[4];
    off7 = off6 * dimen[5];

    st10 = fpix[0];
    st20 = (fpix[1] - 1) * off2;
    st30 = (fpix[2] - 1) * off3;
    st40 = (fpix[3] - 1) * off4;
    st50 = (fpix[4] - 1) * off5;
    st60 = (fpix[5] - 1) * off6;
    st70 = (fpix[6] - 1) * off7;

    /* store the initial offset in each dimension */
    st1 = st10;
    st2 = st20;
    st3 = st30;
    st4 = st40;
    st5 = st50;
    st6 = st60;
    st7 = st70;

    astart = 0;

    for (i7 = 0; i7 < irange[6]; i7++)
    {
     for (i6 = 0; i6 < irange[5]; i6++)
     {
      for (i5 = 0; i5 < irange[4]; i5++)
      {
       for (i4 = 0; i4 < irange[3]; i4++)
       {
        for (i3 = 0; i3 < irange[2]; i3++)
        {
         pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7;

         for (i2 = 0; i2 < irange[1]; i2++)
         {
           if (ffpcli(fptr, 2, tablerow, pstart, i1, &array[astart],
              status) > 0)
              return(*status);

           astart += i1;
           pstart += off2;
         }
         st2 = st20;
         st3 = st3+off3;    
        }
        st3 = st30;
        st4 = st4+off4;
       }
       st4 = st40;
       st5 = st5+off5;
      }
      st5 = st50;
      st6 = st6+off6;
     }
     st6 = st60;
     st7 = st7+off7;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpgpi( fitsfile *fptr,   /* I - FITS file pointer                      */
            long  group,      /* I - group to write(1 = 1st group)          */
            long  firstelem,  /* I - first vector element to write(1 = 1st) */
            long  nelem,      /* I - number of values to write              */
            short *array,     /* I - array of values that are written       */
            int  *status)     /* IO - error status                          */
/*
  Write an array of group parameters to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written).
*/
{
    long row;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffpcli(fptr, 1L, row, firstelem, nelem, array, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpcli( fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
            short *array,    /* I - array of values to write                */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to a column in the current FITS HDU.
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer to a virtual column in a 1 or more grouped FITS primary
  array.  FITSIO treats a primary array as a binary table with
  2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.

  The input array of values will be converted to the datatype of the column 
  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary.
*/
{
    int tcode, maxelem2, hdutype, writeraw;
    long twidth, incre;
    long ntodo;
    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull, maxelem;
    double scale, zero;
    char tform[20], cform[20];
    char message[FLEN_ERRMSG];

    char snull[20];   /*  the FITS null value  */

    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
    void *buffer;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    buffer = cbuff;

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
        tform, &twidth, &tcode, &maxelem2, &startpos,  &elemnum, &incre,
        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
        return(*status);
    maxelem = maxelem2;

    if (tcode == TSTRING)   
         ffcfmt(tform, cform);     /* derive C format for writing strings */

    /*
      if there is no scaling and the native machine format is not byteswapped,
      then we can simply write the raw data bytes into the FITS file if the
      datatype of the FITS column is the same as the input values.  Otherwise,
      we must convert the raw values into the scaled and/or machine dependent
      format in a temporary buffer that has been allocated for this purpose.
    */
    if (scale == 1. && zero == 0. &&
       MACHINE == NATIVE && tcode == TSHORT)
    {
        writeraw = 1;
        if (nelem < (LONGLONG)INT32_MAX) {
            maxelem = nelem;
        } else {
            maxelem = INT32_MAX/2;
        }
    }
    else
        writeraw = 0;

    /*---------------------------------------------------------------------*/
    /*  Now write the pixels to the FITS column.                           */
    /*  First call the ffXXfYY routine to  (1) convert the datatype        */
    /*  if necessary, and (2) scale the values by the FITS TSCALn and      */
    /*  TZEROn linear scaling parameters into a temporary buffer.          */
    /*---------------------------------------------------------------------*/
    remain = nelem;           /* remaining number of values to write  */
    next = 0;                 /* next element in array to be written  */
    rownum = 0;               /* row number, relative to firstrow     */

    while (remain)
    {
        /* limit the number of pixels to process a one time to the number that
           will fit in the buffer space or to the number of pixels that remain
           in the current vector, which ever is smaller.
        */
        ntodo = (long) minvalue(remain, maxelem);      
        ntodo = (long) minvalue(ntodo, (repeat - elemnum));

        wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);

        ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */

        switch (tcode) 
        {
            case (TSHORT):
              if (writeraw)
              {
                /* write raw input bytes without conversion */
                ffpi2b(fptr, ntodo, incre, &array[next], status);
              }
              else
              {
                /* convert the raw data before writing to FITS file */
                ffi2fi2(&array[next], ntodo, scale, zero,
                        (short *) buffer, status);
                ffpi2b(fptr, ntodo, incre, (short *) buffer, status);
              }

              break;

            case (TLONGLONG):

                ffi2fi8(&array[next], ntodo, scale, zero,
                        (LONGLONG *) buffer, status);
                ffpi8b(fptr, ntodo, incre, (long *) buffer, status);
                break;

             case (TBYTE):

                ffi2fi1(&array[next], ntodo, scale, zero,
                        (unsigned char *) buffer, status);
                ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status);
                break;

            case (TLONG):

                ffi2fi4(&array[next], ntodo, scale, zero,
                        (INT32BIT *) buffer, status);
                ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status);
                break;

            case (TFLOAT):

                ffi2fr4(&array[next], ntodo, scale, zero,
                        (float *) buffer, status);
                ffpr4b(fptr, ntodo, incre, (float *) buffer, status);
                break;

            case (TDOUBLE):
                ffi2fr8(&array[next], ntodo, scale, zero,
                        (double *) buffer, status);
                ffpr8b(fptr, ntodo, incre, (double *) buffer, status);
                break;

            case (TSTRING):  /* numerical column in an ASCII table */

                if (cform[1] != 's')  /*  "%s" format is a string */
                {
                  ffi2fstr(&array[next], ntodo, scale, zero, cform,
                          twidth, (char *) buffer, status);


                  if (incre == twidth)    /* contiguous bytes */
                     ffpbyt(fptr, ntodo * twidth, buffer, status);
                  else
                     ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
                            status);

                  break;
                }
                /* can't write to string column, so fall thru to default: */

            default:  /*  error trap  */
                snprintf(message,FLEN_ERRMSG, 
                    "Cannot write numbers to column %d which has format %s",
                      colnum,tform);
                ffpmsg(message);
                if (hdutype == ASCII_TBL)
                    return(*status = BAD_ATABLE_FORMAT);
                else
                    return(*status = BAD_BTABLE_FORMAT);

        } /* End of switch block */

        /*-------------------------*/
        /*  Check for fatal error  */
        /*-------------------------*/
        if (*status > 0)  /* test for error during previous write operation */
        {
         snprintf(message,FLEN_ERRMSG,
          "Error writing elements %.0f thru %.0f of input data array (ffpcli).",
             (double) (next+1), (double) (next+ntodo));
         ffpmsg(message);
         return(*status);
        }

        /*--------------------------------------------*/
        /*  increment the counters for the next loop  */
        /*--------------------------------------------*/
        remain -= ntodo;
        if (remain)
        {
            next += ntodo;
            elemnum += ntodo;
            if (elemnum == repeat)  /* completed a row; start on next row */
            {
                elemnum = 0;
                rownum++;
            }
        }
    }  /*  End of main while Loop  */


    /*--------------------------------*/
    /*  check for numerical overflow  */
    /*--------------------------------*/
    if (*status == OVERFLOW_ERR)
    {
       ffpmsg(
       "Numerical overflow during type conversion while writing FITS data.");
       *status = NUM_OVERFLOW;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpcni( fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
            short *array,    /* I - array of values to write                */
            short  nulvalue, /* I - value used to flag undefined pixels     */
            int  *status)    /* IO - error status                           */
/*
  Write an array of elements to the specified column of a table.  Any input
  pixels equal to the value of nulvalue will be replaced by the appropriate
  null value in the output FITS file. 

  The input array of values will be converted to the datatype of the column 
  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary
*/
{
    tcolumn *colptr;
    LONGLONG  ngood = 0, nbad = 0, ii;
    LONGLONG repeat, first, fstelm, fstrow;
    int tcode, overflow = 0;

    if (*status > 0)
        return(*status);

    /* reset position to the correct HDU if necessary */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
    {
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
    }
    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
    {
        if ( ffrdef(fptr, status) > 0)               /* rescan header */
            return(*status);
    }

    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
    colptr += (colnum - 1);     /* offset to correct column structure */

    tcode  = colptr->tdatatype;

    if (tcode > 0)
       repeat = colptr->trepeat;  /* repeat count for this column */
    else
       repeat = firstelem -1 + nelem;  /* variable length arrays */

    /* if variable length array, first write the whole input vector, 
       then go back and fill in the nulls */
    if (tcode < 0) {
      if (ffpcli(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) {
        if (*status == NUM_OVERFLOW) 
	{
	  /* ignore overflows, which are possibly the null pixel values */
	  /*  overflow = 1;   */
	  *status = 0;
	} else { 
          return(*status);
	}
      }
    }

    /* absolute element number in the column */
    first = (firstrow - 1) * repeat + firstelem;

    for (ii = 0; ii < nelem; ii++)
    {
      if (array[ii] != nulvalue)  /* is this a good pixel? */
      {
         if (nbad)  /* write previous string of bad pixels */
         {
            fstelm = ii - nbad + first;  /* absolute element number */
            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

            if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
                return(*status);

            nbad=0;
         }

         ngood = ngood +1;  /* the consecutive number of good pixels */
      }
      else
      {
         if (ngood)  /* write previous string of good pixels */
         {
            fstelm = ii - ngood + first;  /* absolute element number */
            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

            if (tcode > 0) {  /* variable length arrays have already been written */
              if (ffpcli(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
                status) > 0) {
		if (*status == NUM_OVERFLOW) 
		{
		  overflow = 1;
		  *status = 0;
		} else { 
                  return(*status);
		}
	      }
	    }
            ngood=0;
         }

         nbad = nbad +1;  /* the consecutive number of bad pixels */
      }
    }

    /* finished loop;  now just write the last set of pixels */

    if (ngood)  /* write last string of good pixels */
    {
      fstelm = ii - ngood + first;  /* absolute element number */
      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

      if (tcode > 0) {  /* variable length arrays have already been written */
        ffpcli(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
      }
    }
    else if (nbad) /* write last string of bad pixels */
    {
      fstelm = ii - nbad + first;  /* absolute element number */
      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

      ffpclu(fptr, colnum, fstrow, fstelm, nbad, status);
    }

    if (*status <= 0) {
      if (overflow) {
        *status = NUM_OVERFLOW;
      }
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffi2fi1(short *input,          /* I - array of values to be converted  */
            long ntodo,            /* I - number of elements in the array  */
            double scale,          /* I - FITS TSCALn or BSCALE value      */
            double zero,           /* I - FITS TZEROn or BZERO  value      */
            unsigned char *output, /* O - output array of converted values */
            int *status)           /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
            if (input[ii] < 0)
            {
                *status = OVERFLOW_ERR;
                output[ii] = 0;
            }
            else if (input[ii] > UCHAR_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = UCHAR_MAX;
            }
            else
                output[ii] = (unsigned char) input[ii];
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DUCHAR_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = 0;
            }
            else if (dvalue > DUCHAR_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = UCHAR_MAX;
            }
            else
                output[ii] = (unsigned char) (dvalue + .5);
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffi2fi2(short *input,       /* I - array of values to be converted  */
            long ntodo,         /* I - number of elements in the array  */
            double scale,       /* I - FITS TSCALn or BSCALE value      */
            double zero,        /* I - FITS TZEROn or BZERO  value      */
            short *output,      /* O - output array of converted values */
            int *status)        /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        memcpy(output, input, ntodo * sizeof(short) );
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DSHRT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MIN;
            }
            else if (dvalue > DSHRT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (short) (dvalue + .5);
                else
                    output[ii] = (short) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffi2fi4(short *input,      /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            INT32BIT *output,  /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
            output[ii] = (INT32BIT) input[ii];   /* just copy input to output */
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DINT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MIN;
            }
            else if (dvalue > DINT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (INT32BIT) (dvalue + .5);
                else
                    output[ii] = (INT32BIT) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffi2fi8(short *input,      /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            LONGLONG *output,  /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DLONGLONG_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = LONGLONG_MIN;
            }
            else if (dvalue > DLONGLONG_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = LONGLONG_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (LONGLONG) (dvalue + .5);
                else
                    output[ii] = (LONGLONG) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffi2fr4(short *input,      /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            float *output,     /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = (float) input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
            output[ii] = (float) ((input[ii] - zero) / scale);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffi2fr8(short *input,      /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            double *output,    /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = (double) input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
            output[ii] = (input[ii] - zero) / scale;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffi2fstr(short *input,     /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            char *cform,       /* I - format for output string values  */
            long twidth,       /* I - width of each field, in chars    */
            char *output,      /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do scaling if required.
*/
{
    long ii;
    double dvalue;
    char *cptr;
    
    cptr = output;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
           sprintf(output, cform, (double) input[ii]);
           output += twidth;

           if (*output)  /* if this char != \0, then overflow occurred */
              *status = OVERFLOW_ERR;
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
          dvalue = (input[ii] - zero) / scale;
          sprintf(output, cform, dvalue);
          output += twidth;

          if (*output)  /* if this char != \0, then overflow occurred */
            *status = OVERFLOW_ERR;
        }
    }

    /* replace any commas with periods (e.g., in French locale) */
    while ((cptr = strchr(cptr, ','))) *cptr = '.';

    return(*status);
}
cfitsio/putcolj.c0000644000225700000360000021111113246025103013621 0ustar  cagordonlhea/*  This file, putcolj.c, contains routines that write data elements to    */
/*  a FITS image or table, with long datatype.                             */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int ffpprj( fitsfile *fptr,  /* I - FITS file pointer                       */
            long  group,     /* I - group to write(1 = 1st group)           */
            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
            LONGLONG  nelem,     /* I - number of values to write               */
            long  *array,    /* I - array of values that are written        */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written).
*/
{
    long row;
    long nullvalue;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_write_compressed_pixels(fptr, TLONG, firstelem, nelem,
            0, array, &nullvalue, status);
        return(*status);
    }

    row=maxvalue(1,group);

    ffpclj(fptr, 2, row, firstelem, nelem, array, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffppnj( fitsfile *fptr,  /* I - FITS file pointer                       */
            long  group,     /* I - group to write(1 = 1st group)           */
            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
            LONGLONG  nelem,     /* I - number of values to write               */
            long  *array,    /* I - array of values that are written        */
            long  nulval,    /* I - undefined pixel value                   */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).  Any array values
  that are equal to the value of nulval will be replaced with the null
  pixel value that is appropriate for this column.
*/
{
    long row;
    long nullvalue;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        nullvalue = nulval;  /* set local variable */
        fits_write_compressed_pixels(fptr, TLONG, firstelem, nelem,
            1, array, &nullvalue, status);
        return(*status);
    }

    row=maxvalue(1,group);

    ffpcnj(fptr, 2, row, firstelem, nelem, array, nulval, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffp2dj(fitsfile *fptr,   /* I - FITS file pointer                     */
           long  group,      /* I - group to write(1 = 1st group)         */
           LONGLONG  ncols,      /* I - number of pixels in each row of array */
           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
           long  *array,     /* I - array to be written                   */
           int  *status)     /* IO - error status                         */
/*
  Write an entire 2-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).
*/
{

    /* call the 3D writing routine, with the 3rd dimension = 1 */

    ffp3dj(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffp3dj(fitsfile *fptr,   /* I - FITS file pointer                     */
           long  group,      /* I - group to write(1 = 1st group)         */
           LONGLONG  ncols,      /* I - number of pixels in each row of array */
           LONGLONG  nrows,      /* I - number of rows in each plane of array */
           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
           LONGLONG  naxis3,     /* I - FITS image NAXIS3 value               */
           long  *array,     /* I - array to be written                   */
           int  *status)     /* IO - error status                         */
/*
  Write an entire 3-D cube of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).
*/
{
    long tablerow, ii, jj;
    long fpixel[3]= {1,1,1}, lpixel[3];
    LONGLONG nfits, narray;
    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */
           
    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */
        lpixel[0] = (long) ncols;
        lpixel[1] = (long) nrows;
        lpixel[2] = (long) naxis3;
       
        fits_write_compressed_img(fptr, TLONG, fpixel, lpixel,
            0,  array, NULL, status);
    
        return(*status);
    }

    tablerow=maxvalue(1,group);

    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
    {
      /* all the image pixels are contiguous, so write all at once */
      ffpclj(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status);
      return(*status);
    }

    if (ncols < naxis1 || nrows < naxis2)
       return(*status = BAD_DIMEN);

    nfits = 1;   /* next pixel in FITS image to write to */
    narray = 0;  /* next pixel in input array to be written */

    /* loop over naxis3 planes in the data cube */
    for (jj = 0; jj < naxis3; jj++)
    {
      /* loop over the naxis2 rows in the FITS image, */
      /* writing naxis1 pixels to each row            */

      for (ii = 0; ii < naxis2; ii++)
      {
       if (ffpclj(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0)
         return(*status);

       nfits += naxis1;
       narray += ncols;
      }
      narray += (nrows - naxis2) * ncols;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpssj(fitsfile *fptr,   /* I - FITS file pointer                       */
           long  group,      /* I - group to write(1 = 1st group)           */
           long  naxis,      /* I - number of data axes in array            */
           long  *naxes,     /* I - size of each FITS axis                  */
           long  *fpixel,    /* I - 1st pixel in each axis to write (1=1st) */
           long  *lpixel,    /* I - last pixel in each axis to write        */
           long *array,      /* I - array to be written                     */
           int  *status)     /* IO - error status                           */
/*
  Write a subsection of pixels to the primary array or image.
  A subsection is defined to be any contiguous rectangular
  array of pixels within the n-dimensional FITS data file.
  Data conversion and scaling will be performed if necessary 
  (e.g, if the datatype of the FITS array is not the same as
  the array being written).
*/
{
    long tablerow;
    LONGLONG fpix[7], dimen[7], astart, pstart;
    LONGLONG off2, off3, off4, off5, off6, off7;
    LONGLONG st10, st20, st30, st40, st50, st60, st70;
    LONGLONG st1, st2, st3, st4, st5, st6, st7;
    long ii, i1, i2, i3, i4, i5, i6, i7, irange[7];

    if (*status > 0)
        return(*status);

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_write_compressed_img(fptr, TLONG, fpixel, lpixel,
            0,  array, NULL, status);
    
        return(*status);
    }

    if (naxis < 1 || naxis > 7)
      return(*status = BAD_DIMEN);

    tablerow=maxvalue(1,group);

     /* calculate the size and number of loops to perform in each dimension */
    for (ii = 0; ii < 7; ii++)
    {
      fpix[ii]=1;
      irange[ii]=1;
      dimen[ii]=1;
    }

    for (ii = 0; ii < naxis; ii++)
    {    
      fpix[ii]=fpixel[ii];
      irange[ii]=lpixel[ii]-fpixel[ii]+1;
      dimen[ii]=naxes[ii];
    }

    i1=irange[0];

    /* compute the pixel offset between each dimension */
    off2 =     dimen[0];
    off3 = off2 * dimen[1];
    off4 = off3 * dimen[2];
    off5 = off4 * dimen[3];
    off6 = off5 * dimen[4];
    off7 = off6 * dimen[5];

    st10 = fpix[0];
    st20 = (fpix[1] - 1) * off2;
    st30 = (fpix[2] - 1) * off3;
    st40 = (fpix[3] - 1) * off4;
    st50 = (fpix[4] - 1) * off5;
    st60 = (fpix[5] - 1) * off6;
    st70 = (fpix[6] - 1) * off7;

    /* store the initial offset in each dimension */
    st1 = st10;
    st2 = st20;
    st3 = st30;
    st4 = st40;
    st5 = st50;
    st6 = st60;
    st7 = st70;

    astart = 0;

    for (i7 = 0; i7 < irange[6]; i7++)
    {
     for (i6 = 0; i6 < irange[5]; i6++)
     {
      for (i5 = 0; i5 < irange[4]; i5++)
      {
       for (i4 = 0; i4 < irange[3]; i4++)
       {
        for (i3 = 0; i3 < irange[2]; i3++)
        {
         pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7;

         for (i2 = 0; i2 < irange[1]; i2++)
         {
           if (ffpclj(fptr, 2, tablerow, pstart, i1, &array[astart],
              status) > 0)
              return(*status);

           astart += i1;
           pstart += off2;
         }
         st2 = st20;
         st3 = st3+off3;    
        }
        st3 = st30;
        st4 = st4+off4;
       }
       st4 = st40;
       st5 = st5+off5;
      }
      st5 = st50;
      st6 = st6+off6;
     }
     st6 = st60;
     st7 = st7+off7;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpgpj( fitsfile *fptr,   /* I - FITS file pointer                      */
            long  group,      /* I - group to write(1 = 1st group)          */
            long  firstelem,  /* I - first vector element to write(1 = 1st) */
            long  nelem,      /* I - number of values to write              */
            long  *array,     /* I - array of values that are written       */
            int  *status)     /* IO - error status                          */
/*
  Write an array of group parameters to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written).
*/
{
    long row;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffpclj(fptr, 1L, row, firstelem, nelem, array, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpclj( fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
            long  *array,    /* I - array of values to write                */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to a column in the current FITS HDU.
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer to a virtual column in a 1 or more grouped FITS primary
  array.  FITSIO treats a primary array as a binary table
  with 2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.

  The input array of values will be converted to the datatype of the column 
  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary.
*/
{
    int tcode, maxelem2, hdutype, writeraw;
    long twidth, incre;
    long ntodo;
    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull, maxelem;
    double scale, zero;
    char tform[20], cform[20];
    char message[FLEN_ERRMSG];

    char snull[20];   /*  the FITS null value  */

    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
    void *buffer;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    buffer = cbuff;

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
        tform, &twidth, &tcode, &maxelem2, &startpos,  &elemnum, &incre,
        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
        return(*status);
    maxelem = maxelem2;

    if (tcode == TSTRING)   
         ffcfmt(tform, cform);     /* derive C format for writing strings */

    /*
       if there is no scaling and the native machine format is not byteswapped
       then we can simply write the raw data bytes into the FITS file if the
       datatype of the FITS column is the same as the input values.  Otherwise
       we must convert the raw values into the scaled and/or machine dependent
       format in a temporary buffer that has been allocated for this purpose.
    */
    if (scale == 1. && zero == 0. && 
       MACHINE == NATIVE && tcode == TLONG && LONGSIZE == 32)
    {
        writeraw = 1;
        if (nelem < (LONGLONG)INT32_MAX) {
            maxelem = nelem;
        } else {
            maxelem = INT32_MAX/8;
        }
    }
    else
        writeraw = 0;

    /*---------------------------------------------------------------------*/
    /*  Now write the pixels to the FITS column.                           */
    /*  First call the ffXXfYY routine to  (1) convert the datatype        */
    /*  if necessary, and (2) scale the values by the FITS TSCALn and      */
    /*  TZEROn linear scaling parameters into a temporary buffer.          */
    /*---------------------------------------------------------------------*/
    remain = nelem;           /* remaining number of values to write  */
    next = 0;                 /* next element in array to be written  */
    rownum = 0;               /* row number, relative to firstrow     */

    while (remain)
    {
        /* limit the number of pixels to process a one time to the number that
           will fit in the buffer space or to the number of pixels that remain
           in the current vector, which ever is smaller.
        */
        ntodo = (long) minvalue(remain, maxelem);      
        ntodo = (long) minvalue(ntodo, (repeat - elemnum));

        wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);

        ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */

        switch (tcode) 
        {
            case (TLONG):
              if (writeraw)
              {
                /* write raw input bytes without conversion */
                ffpi4b(fptr, ntodo, incre, (INT32BIT *) &array[next], status);
              }
              else
              {
                /* convert the raw data before writing to FITS file */
                ffi4fi4(&array[next], ntodo, scale, zero,
                        (INT32BIT *) buffer, status);
                ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status);
              }

              break;

            case (TLONGLONG):

                fflongfi8(&array[next], ntodo, scale, zero,
                        (LONGLONG *) buffer, status);
                ffpi8b(fptr, ntodo, incre, (long *) buffer, status);
                break;

            case (TBYTE):
 
                ffi4fi1(&array[next], ntodo, scale, zero,
                        (unsigned char *) buffer, status);
                ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status);
                break;

            case (TSHORT):

                ffi4fi2(&array[next], ntodo, scale, zero,
                        (short *) buffer, status);
                ffpi2b(fptr, ntodo, incre, (short *) buffer, status);
                break;

            case (TFLOAT):

                ffi4fr4(&array[next], ntodo, scale, zero,
                        (float *) buffer, status);
                ffpr4b(fptr, ntodo, incre, (float *) buffer, status);
                break;

            case (TDOUBLE):
                ffi4fr8(&array[next], ntodo, scale, zero,
                       (double *) buffer, status);
                ffpr8b(fptr, ntodo, incre, (double *) buffer, status);
                break;

            case (TSTRING):  /* numerical column in an ASCII table */

                if (cform[1] != 's')  /*  "%s" format is a string */
                {
                  ffi4fstr(&array[next], ntodo, scale, zero, cform,
                          twidth, (char *) buffer, status);

                  if (incre == twidth)    /* contiguous bytes */
                     ffpbyt(fptr, ntodo * twidth, buffer, status);
                  else
                     ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
                            status);

                  break;
                }
                /* can't write to string column, so fall thru to default: */

            default:  /*  error trap  */
                snprintf(message, FLEN_ERRMSG,
                     "Cannot write numbers to column %d which has format %s",
                      colnum,tform);
                ffpmsg(message);
                if (hdutype == ASCII_TBL)
                    return(*status = BAD_ATABLE_FORMAT);
                else
                    return(*status = BAD_BTABLE_FORMAT);

        } /* End of switch block */

        /*-------------------------*/
        /*  Check for fatal error  */
        /*-------------------------*/
        if (*status > 0)  /* test for error during previous write operation */
        {
          snprintf(message,FLEN_ERRMSG,
          "Error writing elements %.0f thru %.0f of input data array (ffpclj).",
              (double) (next+1), (double) (next+ntodo));
          ffpmsg(message);
          return(*status);
        }

        /*--------------------------------------------*/
        /*  increment the counters for the next loop  */
        /*--------------------------------------------*/
        remain -= ntodo;
        if (remain)
        {
            next += ntodo;
            elemnum += ntodo;
            if (elemnum == repeat)  /* completed a row; start on next row */
            {
                elemnum = 0;
                rownum++;
            }
        }
    }  /*  End of main while Loop  */


    /*--------------------------------*/
    /*  check for numerical overflow  */
    /*--------------------------------*/
    if (*status == OVERFLOW_ERR)
    {
        ffpmsg(
        "Numerical overflow during type conversion while writing FITS data.");
        *status = NUM_OVERFLOW;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpcnj( fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
            long  *array,    /* I - array of values to write                */
            long   nulvalue, /* I - value used to flag undefined pixels     */
            int  *status)    /* IO - error status                           */
/*
  Write an array of elements to the specified column of a table.  Any input
  pixels equal to the value of nulvalue will be replaced by the appropriate
  null value in the output FITS file. 

  The input array of values will be converted to the datatype of the column 
  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary
*/
{
    tcolumn *colptr;
    LONGLONG  ngood = 0, nbad = 0, ii;
    LONGLONG repeat, first, fstelm, fstrow;
    int tcode, overflow = 0;
 
    if (*status > 0)
        return(*status);

    /* reset position to the correct HDU if necessary */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
    {
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
    }
    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
    {
        if ( ffrdef(fptr, status) > 0)               /* rescan header */
            return(*status);
    }

    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
    colptr += (colnum - 1);     /* offset to correct column structure */

    tcode  = colptr->tdatatype;

    if (tcode > 0)
       repeat = colptr->trepeat;  /* repeat count for this column */
    else
       repeat = firstelem -1 + nelem;  /* variable length arrays */

    /* if variable length array, first write the whole input vector, 
       then go back and fill in the nulls */
    if (tcode < 0) {
      if (ffpclj(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) {
        if (*status == NUM_OVERFLOW) 
	{
	  /* ignore overflows, which are possibly the null pixel values */
	  /*  overflow = 1;   */
	  *status = 0;
	} else { 
          return(*status);
	}
      }
    }

    /* absolute element number in the column */
    first = (firstrow - 1) * repeat + firstelem;

    for (ii = 0; ii < nelem; ii++)
    {
      if (array[ii] != nulvalue)  /* is this a good pixel? */
      {
         if (nbad)  /* write previous string of bad pixels */
         {
            fstelm = ii - nbad + first;  /* absolute element number */
            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
	  
            if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
                return(*status);

            nbad=0;
         }

         ngood = ngood + 1;  /* the consecutive number of good pixels */
      }
      else
      {
         if (ngood)  /* write previous string of good pixels */
         {
            fstelm = ii - ngood + first;  /* absolute element number */
            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

            if (tcode > 0) {  /* variable length arrays have already been written */
              if (ffpclj(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
                status) > 0) {
		if (*status == NUM_OVERFLOW) 
		{
		  overflow = 1;
		  *status = 0;
		} else { 
                  return(*status);
		}
	      }
	    }
            ngood=0;
         }

         nbad = nbad +1;  /* the consecutive number of bad pixels */
      }
    }

    /* finished loop;  now just write the last set of pixels */

    if (ngood)  /* write last string of good pixels */
    {
      fstelm = ii - ngood + first;  /* absolute element number */
      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

      if (tcode > 0) {  /* variable length arrays have already been written */
        ffpclj(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
      }
    }
    else if (nbad) /* write last string of bad pixels */
    {
      fstelm = ii - nbad + first;  /* absolute element number */
      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

      ffpclu(fptr, colnum, fstrow, fstelm, nbad, status);
    }

    if (*status <= 0) {
      if (overflow) {
        *status = NUM_OVERFLOW;
      }
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffi4fi1(long *input,           /* I - array of values to be converted  */
            long ntodo,            /* I - number of elements in the array  */
            double scale,          /* I - FITS TSCALn or BSCALE value      */
            double zero,           /* I - FITS TZEROn or BZERO  value      */
            unsigned char *output, /* O - output array of converted values */
            int *status)           /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
            if (input[ii] < 0)
            {
                *status = OVERFLOW_ERR;
                output[ii] = 0;
            }
            else if (input[ii] > UCHAR_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = UCHAR_MAX;
            }
            else
                output[ii] = (unsigned char) input[ii];
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DUCHAR_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = 0;
            }
            else if (dvalue > DUCHAR_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = UCHAR_MAX;
            }
            else
                output[ii] = (unsigned char) (dvalue + .5);
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffi4fi2(long *input,       /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            short *output,     /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
            if (input[ii] < SHRT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MIN;
            }
            else if (input[ii] > SHRT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MAX;
            }
            else
                output[ii] = (short) input[ii];
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DSHRT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MIN;
            }
            else if (dvalue > DSHRT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (short) (dvalue + .5);
                else
                    output[ii] = (short) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffi4fi4(long *input,       /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            INT32BIT *output,  /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = (INT32BIT) input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DINT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MIN;
            }
            else if (dvalue > DINT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (INT32BIT) (dvalue + .5);
                else
                    output[ii] = (INT32BIT) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fflongfi8(long *input,       /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            LONGLONG *output,      /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DLONGLONG_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = LONGLONG_MIN;
            }
            else if (dvalue > DLONGLONG_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = LONGLONG_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (LONGLONG) (dvalue + .5);
                else
                    output[ii] = (LONGLONG) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffi4fr4(long *input,       /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            float *output,     /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = (float) input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
            output[ii] = (float) ((input[ii] - zero) / scale);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffi4fr8(long *input,       /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            double *output,    /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = (double) input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
            output[ii] = (input[ii] - zero) / scale;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffi4fstr(long *input,      /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            char *cform,       /* I - format for output string values  */
            long twidth,       /* I - width of each field, in chars    */
            char *output,      /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do scaling if required.
*/
{
    long ii;
    double dvalue;
    char *cptr;

    cptr = output;
    
    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
           sprintf(output, cform, (double) input[ii]);
           output += twidth;

           if (*output)  /* if this char != \0, then overflow occurred */
              *status = OVERFLOW_ERR;
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
          dvalue = (input[ii] - zero) / scale;
          sprintf(output, cform, dvalue);
          output += twidth;

          if (*output)  /* if this char != \0, then overflow occurred */
            *status = OVERFLOW_ERR;
        }
    }

    /* replace any commas with periods (e.g., in French locale) */
    while ((cptr = strchr(cptr, ','))) *cptr = '.';

    return(*status);
}

/* ======================================================================== */
/*      the following routines support the 'long long' data type            */
/* ======================================================================== */

/*--------------------------------------------------------------------------*/
int ffpprjj(fitsfile *fptr,  /* I - FITS file pointer                       */
            long  group,     /* I - group to write(1 = 1st group)           */
            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
            LONGLONG  nelem,     /* I - number of values to write               */
            LONGLONG  *array, /* I - array of values that are written       */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written).
*/
{
    long row;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        ffpmsg("writing to compressed image is not supported");

        return(*status = DATA_COMPRESSION_ERR);
    }

    row=maxvalue(1,group);

    ffpcljj(fptr, 2, row, firstelem, nelem, array, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffppnjj(fitsfile *fptr,  /* I - FITS file pointer                       */
            long  group,     /* I - group to write(1 = 1st group)           */
            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
            LONGLONG  nelem,     /* I - number of values to write               */
            LONGLONG  *array, /* I - array of values that are written       */
            LONGLONG  nulval,    /* I - undefined pixel value                   */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).  Any array values
  that are equal to the value of nulval will be replaced with the null
  pixel value that is appropriate for this column.
*/
{
    long row;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        ffpmsg("writing to compressed image is not supported");

        return(*status = DATA_COMPRESSION_ERR);
    }

    row=maxvalue(1,group);

    ffpcnjj(fptr, 2, row, firstelem, nelem, array, nulval, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffp2djj(fitsfile *fptr,  /* I - FITS file pointer                     */
           long  group,      /* I - group to write(1 = 1st group)         */
           LONGLONG  ncols,      /* I - number of pixels in each row of array */
           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
           LONGLONG  *array, /* I - array to be written                   */
           int  *status)     /* IO - error status                         */
/*
  Write an entire 2-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).
*/
{

    /* call the 3D writing routine, with the 3rd dimension = 1 */

    ffp3djj(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffp3djj(fitsfile *fptr,  /* I - FITS file pointer                     */
           long  group,      /* I - group to write(1 = 1st group)         */
           LONGLONG  ncols,      /* I - number of pixels in each row of array */
           LONGLONG  nrows,      /* I - number of rows in each plane of array */
           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
           LONGLONG  naxis3,     /* I - FITS image NAXIS3 value               */
           LONGLONG  *array, /* I - array to be written                   */
           int  *status)     /* IO - error status                         */
/*
  Write an entire 3-D cube of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).
*/
{
    long tablerow, ii, jj;
    LONGLONG nfits, narray;
    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        ffpmsg("writing to compressed image is not supported");

        return(*status = DATA_COMPRESSION_ERR);
    }

    tablerow=maxvalue(1,group);

    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
    {
      /* all the image pixels are contiguous, so write all at once */
      ffpcljj(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status);
      return(*status);
    }

    if (ncols < naxis1 || nrows < naxis2)
       return(*status = BAD_DIMEN);

    nfits = 1;   /* next pixel in FITS image to write to */
    narray = 0;  /* next pixel in input array to be written */

    /* loop over naxis3 planes in the data cube */
    for (jj = 0; jj < naxis3; jj++)
    {
      /* loop over the naxis2 rows in the FITS image, */
      /* writing naxis1 pixels to each row            */

      for (ii = 0; ii < naxis2; ii++)
      {
       if (ffpcljj(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0)
         return(*status);

       nfits += naxis1;
       narray += ncols;
      }
      narray += (nrows - naxis2) * ncols;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpssjj(fitsfile *fptr,  /* I - FITS file pointer                       */
           long  group,      /* I - group to write(1 = 1st group)           */
           long  naxis,      /* I - number of data axes in array            */
           long  *naxes,     /* I - size of each FITS axis                  */
           long  *fpixel,    /* I - 1st pixel in each axis to write (1=1st) */
           long  *lpixel,    /* I - last pixel in each axis to write        */
           LONGLONG *array,  /* I - array to be written                     */
           int  *status)     /* IO - error status                           */
/*
  Write a subsection of pixels to the primary array or image.
  A subsection is defined to be any contiguous rectangular
  array of pixels within the n-dimensional FITS data file.
  Data conversion and scaling will be performed if necessary 
  (e.g, if the datatype of the FITS array is not the same as
  the array being written).
*/
{
    long tablerow;
    LONGLONG fpix[7], dimen[7], astart, pstart;
    LONGLONG off2, off3, off4, off5, off6, off7;
    LONGLONG st10, st20, st30, st40, st50, st60, st70;
    LONGLONG st1, st2, st3, st4, st5, st6, st7;
    long ii, i1, i2, i3, i4, i5, i6, i7, irange[7];

    if (*status > 0)
        return(*status);

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        ffpmsg("writing to compressed image is not supported");


        return(*status = DATA_COMPRESSION_ERR);
    }

    if (naxis < 1 || naxis > 7)
      return(*status = BAD_DIMEN);

    tablerow=maxvalue(1,group);

     /* calculate the size and number of loops to perform in each dimension */
    for (ii = 0; ii < 7; ii++)
    {
      fpix[ii]=1;
      irange[ii]=1;
      dimen[ii]=1;
    }

    for (ii = 0; ii < naxis; ii++)
    {    
      fpix[ii]=fpixel[ii];
      irange[ii]=lpixel[ii]-fpixel[ii]+1;
      dimen[ii]=naxes[ii];
    }

    i1=irange[0];

    /* compute the pixel offset between each dimension */
    off2 =     dimen[0];
    off3 = off2 * dimen[1];
    off4 = off3 * dimen[2];
    off5 = off4 * dimen[3];
    off6 = off5 * dimen[4];
    off7 = off6 * dimen[5];

    st10 = fpix[0];
    st20 = (fpix[1] - 1) * off2;
    st30 = (fpix[2] - 1) * off3;
    st40 = (fpix[3] - 1) * off4;
    st50 = (fpix[4] - 1) * off5;
    st60 = (fpix[5] - 1) * off6;
    st70 = (fpix[6] - 1) * off7;

    /* store the initial offset in each dimension */
    st1 = st10;
    st2 = st20;
    st3 = st30;
    st4 = st40;
    st5 = st50;
    st6 = st60;
    st7 = st70;

    astart = 0;

    for (i7 = 0; i7 < irange[6]; i7++)
    {
     for (i6 = 0; i6 < irange[5]; i6++)
     {
      for (i5 = 0; i5 < irange[4]; i5++)
      {
       for (i4 = 0; i4 < irange[3]; i4++)
       {
        for (i3 = 0; i3 < irange[2]; i3++)
        {
         pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7;

         for (i2 = 0; i2 < irange[1]; i2++)
         {
           if (ffpcljj(fptr, 2, tablerow, pstart, i1, &array[astart],
              status) > 0)
              return(*status);

           astart += i1;
           pstart += off2;
         }
         st2 = st20;
         st3 = st3+off3;    
        }
        st3 = st30;
        st4 = st4+off4;
       }
       st4 = st40;
       st5 = st5+off5;
      }
      st5 = st50;
      st6 = st6+off6;
     }
     st6 = st60;
     st7 = st7+off7;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpgpjj(fitsfile *fptr,   /* I - FITS file pointer                      */
            long  group,      /* I - group to write(1 = 1st group)          */
            long  firstelem,  /* I - first vector element to write(1 = 1st) */
            long  nelem,      /* I - number of values to write              */
            LONGLONG  *array, /* I - array of values that are written       */
            int  *status)     /* IO - error status                          */
/*
  Write an array of group parameters to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written).
*/
{
    long row;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffpcljj(fptr, 1L, row, firstelem, nelem, array, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpcljj(fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
            LONGLONG  *array, /* I - array of values to write               */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to a column in the current FITS HDU.
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer to a virtual column in a 1 or more grouped FITS primary
  array.  FITSIO treats a primary array as a binary table
  with 2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.

  The input array of values will be converted to the datatype of the column 
  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary.
*/
{
    int tcode, maxelem2, hdutype, writeraw;
    long twidth, incre;
    long  ntodo;
    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull, maxelem;
    double scale, zero;
    char tform[20], cform[20];
    char message[FLEN_ERRMSG];

    char snull[20];   /*  the FITS null value  */

    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
    void *buffer;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    buffer = cbuff;

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
        tform, &twidth, &tcode, &maxelem2, &startpos,  &elemnum, &incre,
        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
        return(*status);
    maxelem = maxelem2;

    if (tcode == TSTRING)   
         ffcfmt(tform, cform);     /* derive C format for writing strings */

    /*
       if there is no scaling and the native machine format is not byteswapped
       then we can simply write the raw data bytes into the FITS file if the
       datatype of the FITS column is the same as the input values.  Otherwise
       we must convert the raw values into the scaled and/or machine dependent
       format in a temporary buffer that has been allocated for this purpose.
    */
    if (scale == 1. && zero == 0. && 
       MACHINE == NATIVE && tcode == TLONGLONG)
    {
        writeraw = 1;
        if (nelem < (LONGLONG)INT32_MAX/8) {
            maxelem = nelem;
        } else {
            maxelem = INT32_MAX/8;
        }
    }
    else
        writeraw = 0;

    /*---------------------------------------------------------------------*/
    /*  Now write the pixels to the FITS column.                           */
    /*  First call the ffXXfYY routine to  (1) convert the datatype        */
    /*  if necessary, and (2) scale the values by the FITS TSCALn and      */
    /*  TZEROn linear scaling parameters into a temporary buffer.          */
    /*---------------------------------------------------------------------*/
    remain = nelem;           /* remaining number of values to write  */
    next = 0;                 /* next element in array to be written  */
    rownum = 0;               /* row number, relative to firstrow     */

    while (remain)
    {
        /* limit the number of pixels to process a one time to the number that
           will fit in the buffer space or to the number of pixels that remain
           in the current vector, which ever is smaller.
        */
        ntodo = (long) minvalue(remain, maxelem);      
        ntodo = (long) minvalue(ntodo, (repeat - elemnum));

        wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);

        ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */

        switch (tcode) 
        {
            case (TLONGLONG):
              if (writeraw)
              {
                /* write raw input bytes without conversion */
                ffpi8b(fptr, ntodo, incre, (long *) &array[next], status);
              }
              else
              {
                /* convert the raw data before writing to FITS file */
                ffi8fi8(&array[next], ntodo, scale, zero,
                        (LONGLONG *) buffer, status);
                ffpi8b(fptr, ntodo, incre, (long *) buffer, status);
              }

              break;

            case (TLONG):

                ffi8fi4(&array[next], ntodo, scale, zero,
                        (INT32BIT *) buffer, status);
                ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status);
                break;

            case (TBYTE):
 
                ffi8fi1(&array[next], ntodo, scale, zero,
                        (unsigned char *) buffer, status);
                ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status);
                break;

            case (TSHORT):

                ffi8fi2(&array[next], ntodo, scale, zero,
                        (short *) buffer, status);
                ffpi2b(fptr, ntodo, incre, (short *) buffer, status);
                break;

            case (TFLOAT):

                ffi8fr4(&array[next], ntodo, scale, zero,
                        (float *) buffer, status);
                ffpr4b(fptr, ntodo, incre, (float *) buffer, status);
                break;

            case (TDOUBLE):
                ffi8fr8(&array[next], ntodo, scale, zero,
                       (double *) buffer, status);
                ffpr8b(fptr, ntodo, incre, (double *) buffer, status);
                break;

            case (TSTRING):  /* numerical column in an ASCII table */

                if (cform[1] != 's')  /*  "%s" format is a string */
                {
                  ffi8fstr(&array[next], ntodo, scale, zero, cform,
                          twidth, (char *) buffer, status);

                  if (incre == twidth)    /* contiguous bytes */
                     ffpbyt(fptr, ntodo * twidth, buffer, status);
                  else
                     ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
                            status);

                  break;
                }
                /* can't write to string column, so fall thru to default: */

            default:  /*  error trap  */
                snprintf(message, FLEN_ERRMSG,
                     "Cannot write numbers to column %d which has format %s",
                      colnum,tform);
                ffpmsg(message);
                if (hdutype == ASCII_TBL)
                    return(*status = BAD_ATABLE_FORMAT);
                else
                    return(*status = BAD_BTABLE_FORMAT);

        } /* End of switch block */

        /*-------------------------*/
        /*  Check for fatal error  */
        /*-------------------------*/
        if (*status > 0)  /* test for error during previous write operation */
        {
          snprintf(message,FLEN_ERRMSG,
          "Error writing elements %.0f thru %.0f of input data array (ffpclj).",
              (double) (next+1), (double) (next+ntodo));
          ffpmsg(message);
          return(*status);
        }

        /*--------------------------------------------*/
        /*  increment the counters for the next loop  */
        /*--------------------------------------------*/
        remain -= ntodo;
        if (remain)
        {
            next += ntodo;
            elemnum += ntodo;
            if (elemnum == repeat)  /* completed a row; start on next row */
            {
                elemnum = 0;
                rownum++;
            }
        }
    }  /*  End of main while Loop  */


    /*--------------------------------*/
    /*  check for numerical overflow  */
    /*--------------------------------*/
    if (*status == OVERFLOW_ERR)
    {
        ffpmsg(
        "Numerical overflow during type conversion while writing FITS data.");
        *status = NUM_OVERFLOW;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpcnjj(fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
            LONGLONG *array, /* I - array of values to write                */
            LONGLONG nulvalue, /* I - value used to flag undefined pixels   */
            int  *status)    /* IO - error status                           */
/*
  Write an array of elements to the specified column of a table.  Any input
  pixels equal to the value of nulvalue will be replaced by the appropriate
  null value in the output FITS file. 

  The input array of values will be converted to the datatype of the column 
  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary
*/
{
    tcolumn *colptr;
    LONGLONG  ngood = 0, nbad = 0, ii;
    LONGLONG repeat, first, fstelm, fstrow;
    int tcode, overflow = 0;

    if (*status > 0)
        return(*status);

    /* reset position to the correct HDU if necessary */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
    {
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
    }
    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
    {
        if ( ffrdef(fptr, status) > 0)               /* rescan header */
            return(*status);
    }

    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
    colptr += (colnum - 1);     /* offset to correct column structure */

    tcode  = colptr->tdatatype;

    if (tcode > 0)
       repeat = colptr->trepeat;  /* repeat count for this column */
    else
       repeat = firstelem -1 + nelem;  /* variable length arrays */

    /* if variable length array, first write the whole input vector, 
       then go back and fill in the nulls */
    if (tcode < 0) {
      if (ffpcljj(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) {
        if (*status == NUM_OVERFLOW) 
	{
	  /* ignore overflows, which are possibly the null pixel values */
	  /*  overflow = 1;   */
	  *status = 0;
	} else { 
          return(*status);
	}
      }
    }

    /* absolute element number in the column */
    first = (firstrow - 1) * repeat + firstelem;

    for (ii = 0; ii < nelem; ii++)
    {
      if (array[ii] != nulvalue)  /* is this a good pixel? */
      {
         if (nbad)  /* write previous string of bad pixels */
         {
            fstelm = ii - nbad + first;  /* absolute element number */
            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

            if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
                return(*status);

            nbad=0;
         }

         ngood = ngood +1;  /* the consecutive number of good pixels */
      }
      else
      {
         if (ngood)  /* write previous string of good pixels */
         {
            fstelm = ii - ngood + first;  /* absolute element number */
            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

            if (tcode > 0) {  /* variable length arrays have already been written */
              if (ffpcljj(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
                status) > 0) {
		if (*status == NUM_OVERFLOW) 
		{
		  overflow = 1;
		  *status = 0;
		} else { 
                  return(*status);
		}
	      }
	    }
            ngood=0;
         }

         nbad = nbad +1;  /* the consecutive number of bad pixels */
      }
    }

    /* finished loop;  now just write the last set of pixels */

    if (ngood)  /* write last string of good pixels */
    {
      fstelm = ii - ngood + first;  /* absolute element number */
      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

      if (tcode > 0) {  /* variable length arrays have already been written */
        ffpcljj(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
      }
    }
    else if (nbad) /* write last string of bad pixels */
    {
      fstelm = ii - nbad + first;  /* absolute element number */
      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

      ffpclu(fptr, colnum, fstrow, fstelm, nbad, status);
    }

    if (*status <= 0) {
      if (overflow) {
        *status = NUM_OVERFLOW;
      }
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffi8fi1(LONGLONG *input,       /* I - array of values to be converted  */
            long ntodo,            /* I - number of elements in the array  */
            double scale,          /* I - FITS TSCALn or BSCALE value      */
            double zero,           /* I - FITS TZEROn or BZERO  value      */
            unsigned char *output, /* O - output array of converted values */
            int *status)           /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
            if (input[ii] < 0)
            {
                *status = OVERFLOW_ERR;
                output[ii] = 0;
            }
            else if (input[ii] > UCHAR_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = UCHAR_MAX;
            }
            else
                output[ii] = (unsigned char) input[ii];
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DUCHAR_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = 0;
            }
            else if (dvalue > DUCHAR_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = UCHAR_MAX;
            }
            else
                output[ii] = (unsigned char) (dvalue + .5);
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffi8fi2(LONGLONG *input,   /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            short *output,     /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
            if (input[ii] < SHRT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MIN;
            }
            else if (input[ii] > SHRT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MAX;
            }
            else
                output[ii] = (short) input[ii];
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DSHRT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MIN;
            }
            else if (dvalue > DSHRT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (short) (dvalue + .5);
                else
                    output[ii] = (short) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffi8fi4(LONGLONG *input,   /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            INT32BIT *output,  /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
            if (input[ii] < INT32_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MIN;
            }
            else if (input[ii] > INT32_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MAX;
            }
            else
                output[ii] = (INT32BIT) input[ii];
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DINT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MIN;
            }
            else if (dvalue > DINT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (INT32BIT) (dvalue + .5);
                else
                    output[ii] = (INT32BIT) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffi8fi8(LONGLONG *input,   /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            LONGLONG *output,  /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DLONGLONG_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = LONGLONG_MIN;
            }
            else if (dvalue > DLONGLONG_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = LONGLONG_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (LONGLONG) (dvalue + .5);
                else
                    output[ii] = (LONGLONG) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffi8fr4(LONGLONG *input,   /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            float *output,     /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = (float) input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
            output[ii] = (float) ((input[ii] - zero) / scale);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffi8fr8(LONGLONG *input,       /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            double *output,    /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = (double) input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
            output[ii] = (input[ii] - zero) / scale;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffi8fstr(LONGLONG *input,  /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            char *cform,       /* I - format for output string values  */
            long twidth,       /* I - width of each field, in chars    */
            char *output,      /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do scaling if required.
*/
{
    long ii;
    double dvalue;
    char *cptr;
    
    cptr = output;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
           sprintf(output, cform, (double) input[ii]);
           output += twidth;

           if (*output)  /* if this char != \0, then overflow occurred */
              *status = OVERFLOW_ERR;
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
          dvalue = (input[ii] - zero) / scale;
          sprintf(output, cform, dvalue);
          output += twidth;

          if (*output)  /* if this char != \0, then overflow occurred */
            *status = OVERFLOW_ERR;
        }
    }

    /* replace any commas with periods (e.g., in French locale) */
    while ((cptr = strchr(cptr, ','))) *cptr = '.';
    
    return(*status);
}
cfitsio/putcolk.c0000644000225700000360000010571313246025103013634 0ustar  cagordonlhea/*  This file, putcolk.c, contains routines that write data elements to    */
/*  a FITS image or table, with 'int' datatype.                            */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int ffpprk( fitsfile *fptr,  /* I - FITS file pointer                       */
            long  group,     /* I - group to write(1 = 1st group)           */
            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
            LONGLONG  nelem,     /* I - number of values to write               */
            int   *array,    /* I - array of values that are written        */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written).
*/
{
    long row;
    int nullvalue;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_write_compressed_pixels(fptr, TINT, firstelem, nelem,
            0, array, &nullvalue, status);
        return(*status);
    }

    row=maxvalue(1,group);

    ffpclk(fptr, 2, row, firstelem, nelem, array, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffppnk( fitsfile *fptr,  /* I - FITS file pointer                       */
            long  group,     /* I - group to write(1 = 1st group)           */
            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
            LONGLONG  nelem,     /* I - number of values to write               */
            int   *array,    /* I - array of values that are written        */
            int   nulval,    /* I - undefined pixel value                   */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).  Any array values
  that are equal to the value of nulval will be replaced with the null
  pixel value that is appropriate for this column.
*/
{
    long row;
    int nullvalue;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        nullvalue = nulval;  /* set local variable */
        fits_write_compressed_pixels(fptr, TINT, firstelem, nelem,
            1, array, &nullvalue, status);
        return(*status);
    }

    row=maxvalue(1,group);

    ffpcnk(fptr, 2, row, firstelem, nelem, array, nulval, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffp2dk(fitsfile *fptr,   /* I - FITS file pointer                     */
           long  group,      /* I - group to write(1 = 1st group)         */
           LONGLONG  ncols,      /* I - number of pixels in each row of array */
           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
           int   *array,     /* I - array to be written                   */
           int  *status)     /* IO - error status                         */
/*
  Write an entire 2-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).
*/
{
    /* call the 3D writing routine, with the 3rd dimension = 1 */

    ffp3dk(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffp3dk(fitsfile *fptr,   /* I - FITS file pointer                     */
           long  group,      /* I - group to write(1 = 1st group)         */
           LONGLONG  ncols,      /* I - number of pixels in each row of array */
           LONGLONG  nrows,      /* I - number of rows in each plane of array */
           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
           LONGLONG  naxis3,     /* I - FITS image NAXIS3 value               */
           int   *array,     /* I - array to be written                   */
           int  *status)     /* IO - error status                         */
/*
  Write an entire 3-D cube of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).
*/
{
    long tablerow, ii, jj;
    long fpixel[3]= {1,1,1}, lpixel[3];
    LONGLONG nfits, narray;
    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */
           
    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */
        lpixel[0] = (long) ncols;
        lpixel[1] = (long) nrows;
        lpixel[2] = (long) naxis3;
       
        fits_write_compressed_img(fptr, TINT, fpixel, lpixel,
            0,  array, NULL, status);
    
        return(*status);
    }

    tablerow=maxvalue(1,group);

    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
    {
      /* all the image pixels are contiguous, so write all at once */
      ffpclk(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status);
      return(*status);
    }

    if (ncols < naxis1 || nrows < naxis2)
       return(*status = BAD_DIMEN);

    nfits = 1;   /* next pixel in FITS image to write to */
    narray = 0;  /* next pixel in input array to be written */

    /* loop over naxis3 planes in the data cube */
    for (jj = 0; jj < naxis3; jj++)
    {
      /* loop over the naxis2 rows in the FITS image, */
      /* writing naxis1 pixels to each row            */

      for (ii = 0; ii < naxis2; ii++)
      {
       if (ffpclk(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0)
         return(*status);

       nfits += naxis1;
       narray += ncols;
      }
      narray += (nrows - naxis2) * ncols;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpssk(fitsfile *fptr,   /* I - FITS file pointer                       */
           long  group,      /* I - group to write(1 = 1st group)           */
           long  naxis,      /* I - number of data axes in array            */
           long  *naxes,     /* I - size of each FITS axis                  */
           long  *fpixel,    /* I - 1st pixel in each axis to write (1=1st) */
           long  *lpixel,    /* I - last pixel in each axis to write        */
           int *array,      /* I - array to be written                     */
           int  *status)     /* IO - error status                           */
/*
  Write a subsection of pixels to the primary array or image.
  A subsection is defined to be any contiguous rectangular
  array of pixels within the n-dimensional FITS data file.
  Data conversion and scaling will be performed if necessary 
  (e.g, if the datatype of the FITS array is not the same as
  the array being written).
*/
{
    long tablerow;
    LONGLONG fpix[7], dimen[7], astart, pstart;
    LONGLONG off2, off3, off4, off5, off6, off7;
    LONGLONG st10, st20, st30, st40, st50, st60, st70;
    LONGLONG st1, st2, st3, st4, st5, st6, st7;
    long ii, i1, i2, i3, i4, i5, i6, i7, irange[7];

    if (*status > 0)
        return(*status);

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_write_compressed_img(fptr, TINT, fpixel, lpixel,
            0,  array, NULL, status);
    
        return(*status);
    }

    if (naxis < 1 || naxis > 7)
      return(*status = BAD_DIMEN);

    tablerow=maxvalue(1,group);

     /* calculate the size and number of loops to perform in each dimension */
    for (ii = 0; ii < 7; ii++)
    {
      fpix[ii]=1;
      irange[ii]=1;
      dimen[ii]=1;
    }

    for (ii = 0; ii < naxis; ii++)
    {    
      fpix[ii]=fpixel[ii];
      irange[ii]=lpixel[ii]-fpixel[ii]+1;
      dimen[ii]=naxes[ii];
    }

    i1=irange[0];

    /* compute the pixel offset between each dimension */
    off2 =     dimen[0];
    off3 = off2 * dimen[1];
    off4 = off3 * dimen[2];
    off5 = off4 * dimen[3];
    off6 = off5 * dimen[4];
    off7 = off6 * dimen[5];

    st10 = fpix[0];
    st20 = (fpix[1] - 1) * off2;
    st30 = (fpix[2] - 1) * off3;
    st40 = (fpix[3] - 1) * off4;
    st50 = (fpix[4] - 1) * off5;
    st60 = (fpix[5] - 1) * off6;
    st70 = (fpix[6] - 1) * off7;

    /* store the initial offset in each dimension */
    st1 = st10;
    st2 = st20;
    st3 = st30;
    st4 = st40;
    st5 = st50;
    st6 = st60;
    st7 = st70;

    astart = 0;

    for (i7 = 0; i7 < irange[6]; i7++)
    {
     for (i6 = 0; i6 < irange[5]; i6++)
     {
      for (i5 = 0; i5 < irange[4]; i5++)
      {
       for (i4 = 0; i4 < irange[3]; i4++)
       {
        for (i3 = 0; i3 < irange[2]; i3++)
        {
         pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7;

         for (i2 = 0; i2 < irange[1]; i2++)
         {
           if (ffpclk(fptr, 2, tablerow, pstart, i1, &array[astart],
              status) > 0)
              return(*status);

           astart += i1;
           pstart += off2;
         }
         st2 = st20;
         st3 = st3+off3;    
        }
        st3 = st30;
        st4 = st4+off4;
       }
       st4 = st40;
       st5 = st5+off5;
      }
      st5 = st50;
      st6 = st6+off6;
     }
     st6 = st60;
     st7 = st7+off7;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpgpk( fitsfile *fptr,   /* I - FITS file pointer                      */
            long  group,      /* I - group to write(1 = 1st group)          */
            long  firstelem,  /* I - first vector element to write(1 = 1st) */
            long  nelem,      /* I - number of values to write              */
            int   *array,     /* I - array of values that are written       */
            int  *status)     /* IO - error status                          */
/*
  Write an array of group parameters to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written).
*/
{
    long row;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffpclk(fptr, 1L, row, firstelem, nelem, array, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpclk( fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
            int   *array,    /* I - array of values to write                */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to a column in the current FITS HDU.
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer to a virtual column in a 1 or more grouped FITS primary
  array.  FITSIO treats a primary array as a binary table
  with 2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.

  The input array of values will be converted to the datatype of the column 
  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary.
*/
{
    int tcode, maxelem2, hdutype, writeraw;
    long twidth, incre;
    long ntodo;
    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull, maxelem;
    double scale, zero;
    char tform[20], cform[20];
    char message[FLEN_ERRMSG];

    char snull[20];   /*  the FITS null value  */

    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
    void *buffer;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /* call the 'short' or 'long' version of this routine, if possible */
    if (sizeof(int) == sizeof(short))
        ffpcli(fptr, colnum, firstrow, firstelem, nelem, 
              (short *) array, status);
    else if (sizeof(int) == sizeof(long))
        ffpclj(fptr, colnum, firstrow, firstelem, nelem, 
              (long *) array, status);
    else
    {
    /*
      This is a special case: sizeof(int) is not equal to sizeof(short) or
      sizeof(long).  This occurs on Alpha OSF systems where short = 2 bytes,
      int = 4 bytes, and long = 8 bytes.
    */

    buffer = cbuff;

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
        tform, &twidth, &tcode, &maxelem2, &startpos,  &elemnum, &incre,
        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
        return(*status);
    maxelem = maxelem2;

    if (tcode == TSTRING)   
         ffcfmt(tform, cform);     /* derive C format for writing strings */

    /*
       if there is no scaling and the native machine format is not byteswapped
       then we can simply write the raw data bytes into the FITS file if the
       datatype of the FITS column is the same as the input values.  Otherwise
       we must convert the raw values into the scaled and/or machine dependent
       format in a temporary buffer that has been allocated for this purpose.
    */
    if (scale == 1. && zero == 0. && 
       MACHINE == NATIVE && tcode == TLONG)
    {
        writeraw = 1;
        if (nelem < (LONGLONG)INT32_MAX) {
            maxelem = nelem;
        } else {
            maxelem = INT32_MAX/4;
        }
    }
    else
        writeraw = 0;

    /*---------------------------------------------------------------------*/
    /*  Now write the pixels to the FITS column.                           */
    /*  First call the ffXXfYY routine to  (1) convert the datatype        */
    /*  if necessary, and (2) scale the values by the FITS TSCALn and      */
    /*  TZEROn linear scaling parameters into a temporary buffer.          */
    /*---------------------------------------------------------------------*/
    remain = nelem;           /* remaining number of values to write  */
    next = 0;                 /* next element in array to be written  */
    rownum = 0;               /* row number, relative to firstrow     */

    while (remain)
    {
        /* limit the number of pixels to process a one time to the number that
           will fit in the buffer space or to the number of pixels that remain
           in the current vector, which ever is smaller.
        */
        ntodo = (long) minvalue(remain, maxelem);      
        ntodo = (long) minvalue(ntodo, (repeat - elemnum));

        wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);

        ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */

        switch (tcode) 
        {
            case (TLONG):
              if (writeraw)
              {
                /* write raw input bytes without conversion */
                ffpi4b(fptr, ntodo, incre, (INT32BIT *) &array[next], status);
              }
              else
              {
                /* convert the raw data before writing to FITS file */
                ffintfi4(&array[next], ntodo, scale, zero,
                        (INT32BIT *) buffer, status);
                ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status);
              }

                break;

            case (TLONGLONG):

                ffintfi8(&array[next], ntodo, scale, zero,
                        (LONGLONG *) buffer, status);
                ffpi8b(fptr, ntodo, incre, (long *) buffer, status);
                break;

            case (TBYTE):
 
                ffintfi1(&array[next], ntodo, scale, zero,
                        (unsigned char *) buffer, status);
                ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status);
                break;

            case (TSHORT):

                ffintfi2(&array[next], ntodo, scale, zero,
                        (short *) buffer, status);
                ffpi2b(fptr, ntodo, incre, (short *) buffer, status);
                break;

            case (TFLOAT):

                ffintfr4(&array[next], ntodo, scale, zero,
                        (float *) buffer, status);
                ffpr4b(fptr, ntodo, incre, (float *) buffer, status);
                break;

            case (TDOUBLE):
                ffintfr8(&array[next], ntodo, scale, zero,
                       (double *) buffer, status);
                ffpr8b(fptr, ntodo, incre, (double *) buffer, status);
                break;

            case (TSTRING):  /* numerical column in an ASCII table */

                if (cform[1] != 's')  /*  "%s" format is a string */
                {
                  ffintfstr(&array[next], ntodo, scale, zero, cform,
                          twidth, (char *) buffer, status);

                  if (incre == twidth)    /* contiguous bytes */
                     ffpbyt(fptr, ntodo * twidth, buffer, status);
                  else
                     ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
                            status);

                  break;
                }
                /* can't write to string column, so fall thru to default: */

            default:  /*  error trap  */
                snprintf(message, FLEN_ERRMSG,
                     "Cannot write numbers to column %d which has format %s",
                      colnum,tform);
                ffpmsg(message);
                if (hdutype == ASCII_TBL)
                    return(*status = BAD_ATABLE_FORMAT);
                else
                    return(*status = BAD_BTABLE_FORMAT);

        } /* End of switch block */

        /*-------------------------*/
        /*  Check for fatal error  */
        /*-------------------------*/
        if (*status > 0)  /* test for error during previous write operation */
        {
          snprintf(message,FLEN_ERRMSG,
          "Error writing elements %.0f thru %.0f of input data array (ffpclk).",
              (double) (next+1), (double) (next+ntodo));
          ffpmsg(message);
          return(*status);
        }

        /*--------------------------------------------*/
        /*  increment the counters for the next loop  */
        /*--------------------------------------------*/
        remain -= ntodo;
        if (remain)
        {
            next += ntodo;
            elemnum += ntodo;
            if (elemnum == repeat)  /* completed a row; start on next row */
            {
                elemnum = 0;
                rownum++;
            }
        }
    }  /*  End of main while Loop  */


    /*--------------------------------*/
    /*  check for numerical overflow  */
    /*--------------------------------*/
    if (*status == OVERFLOW_ERR)
    {
        ffpmsg(
        "Numerical overflow during type conversion while writing FITS data.");
        *status = NUM_OVERFLOW;
    }

    }   /* end of Dec ALPHA special case */

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpcnk( fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
            int   *array,    /* I - array of values to write                */
            int    nulvalue, /* I - value used to flag undefined pixels     */
            int  *status)    /* IO - error status                           */
/*
  Write an array of elements to the specified column of a table.  Any input
  pixels equal to the value of nulvalue will be replaced by the appropriate
  null value in the output FITS file. 

  The input array of values will be converted to the datatype of the column 
  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary
*/
{
    tcolumn *colptr;
    LONGLONG  ngood = 0, nbad = 0, ii;
    LONGLONG repeat, first, fstelm, fstrow;
    int tcode, overflow = 0;

    if (*status > 0)
        return(*status);

    /* reset position to the correct HDU if necessary */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
    {
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
    }
    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
    {
        if ( ffrdef(fptr, status) > 0)               /* rescan header */
            return(*status);
    }

    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
    colptr += (colnum - 1);     /* offset to correct column structure */

    tcode  = colptr->tdatatype;

    if (tcode > 0)
       repeat = colptr->trepeat;  /* repeat count for this column */
    else
       repeat = firstelem -1 + nelem;  /* variable length arrays */

    /* if variable length array, first write the whole input vector, 
       then go back and fill in the nulls */
    if (tcode < 0) {
      if (ffpclk(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) {
        if (*status == NUM_OVERFLOW) 
	{
	  /* ignore overflows, which are possibly the null pixel values */
	  /*  overflow = 1;   */
	  *status = 0;
	} else { 
          return(*status);
	}
      }
    }

    /* absolute element number in the column */
    first = (firstrow - 1) * repeat + firstelem;

    for (ii = 0; ii < nelem; ii++)
    {
      if (array[ii] != nulvalue)  /* is this a good pixel? */
      {
         if (nbad)  /* write previous string of bad pixels */
         {
            fstelm = ii - nbad + first;  /* absolute element number */
            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

            if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
                return(*status);

            nbad=0;
         }

         ngood = ngood +1;  /* the consecutive number of good pixels */
      }
      else
      {
         if (ngood)  /* write previous string of good pixels */
         {
            fstelm = ii - ngood + first;  /* absolute element number */
            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

            if (tcode > 0) {  /* variable length arrays have already been written */
              if (ffpclk(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
                status) > 0)  {
		if (*status == NUM_OVERFLOW) 
		{
		  overflow = 1;
		  *status = 0;
		} else { 
                  return(*status);
		}
	      }
	    }
            ngood=0;
         }

         nbad = nbad +1;  /* the consecutive number of bad pixels */
      }
    }

    /* finished loop;  now just write the last set of pixels */

    if (ngood)  /* write last string of good pixels */
    {
      fstelm = ii - ngood + first;  /* absolute element number */
      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

      if (tcode > 0) {  /* variable length arrays have already been written */
        ffpclk(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
      }
    }
    else if (nbad) /* write last string of bad pixels */
    {
      fstelm = ii - nbad + first;  /* absolute element number */
      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

      ffpclu(fptr, colnum, fstrow, fstelm, nbad, status);
    }

    if (*status <= 0) {
      if (overflow) {
        *status = NUM_OVERFLOW;
      }
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffintfi1(int *input,           /* I - array of values to be converted  */
            long ntodo,            /* I - number of elements in the array  */
            double scale,          /* I - FITS TSCALn or BSCALE value      */
            double zero,           /* I - FITS TZEROn or BZERO  value      */
            unsigned char *output, /* O - output array of converted values */
            int *status)           /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
            if (input[ii] < 0)
            {
                *status = OVERFLOW_ERR;
                output[ii] = 0;
            }
            else if (input[ii] > UCHAR_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = UCHAR_MAX;
            }
            else
                output[ii] = input[ii];
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DUCHAR_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = 0;
            }
            else if (dvalue > DUCHAR_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = UCHAR_MAX;
            }
            else
                output[ii] = (unsigned char) (dvalue + .5);
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffintfi2(int *input,       /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            short *output,     /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
            if (input[ii] < SHRT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MIN;
            }
            else if (input[ii] > SHRT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MAX;
            }
            else
                output[ii] = input[ii];
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DSHRT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MIN;
            }
            else if (dvalue > DSHRT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (short) (dvalue + .5);
                else
                    output[ii] = (short) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffintfi4(int *input,       /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            INT32BIT *output,      /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)  
    {       
        memcpy(output, input, ntodo * sizeof(int) );
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DINT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MIN;
            }
            else if (dvalue > DINT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (INT32BIT) (dvalue + .5);
                else
                    output[ii] = (INT32BIT) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffintfi8(int *input,  /* I - array of values to be converted  */
            long ntodo,             /* I - number of elements in the array  */
            double scale,           /* I - FITS TSCALn or BSCALE value      */
            double zero,            /* I - FITS TZEROn or BZERO  value      */
            LONGLONG *output,       /* O - output array of converted values */
            int *status)            /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DLONGLONG_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = LONGLONG_MIN;
            }
            else if (dvalue > DLONGLONG_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = LONGLONG_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (LONGLONG) (dvalue + .5);
                else
                    output[ii] = (LONGLONG) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffintfr4(int *input,       /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            float *output,     /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = (float) input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
            output[ii] = (float) ((input[ii] - zero) / scale);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffintfr8(int *input,       /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            double *output,    /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = (double) input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
            output[ii] = (input[ii] - zero) / scale;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffintfstr(int *input,      /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            char *cform,       /* I - format for output string values  */
            long twidth,       /* I - width of each field, in chars    */
            char *output,      /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do scaling if required.
*/
{
    long ii;
    double dvalue;
    char *cptr;
    
    cptr = output;


    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
           sprintf(output, cform, (double) input[ii]);
           output += twidth;

           if (*output)  /* if this char != \0, then overflow occurred */
              *status = OVERFLOW_ERR;
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
          dvalue = (input[ii] - zero) / scale;
          sprintf(output, cform, dvalue);
          output += twidth;

          if (*output)  /* if this char != \0, then overflow occurred */
            *status = OVERFLOW_ERR;
        }
    }

    /* replace any commas with periods (e.g., in French locale) */
    while ((cptr = strchr(cptr, ','))) *cptr = '.';
    
    return(*status);
}
cfitsio/putcoll.c0000644000225700000360000003315513246025103013635 0ustar  cagordonlhea/*  This file, putcoll.c, contains routines that write data elements to    */
/*  a FITS image or table, with logical datatype.                          */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int ffpcll( fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
            char *array,     /* I - array of values to write                */
            int  *status)    /* IO - error status                           */
/*
  Write an array of logical values to a column in the current FITS HDU.
*/
{
    int tcode, maxelem, hdutype;
    long twidth, incre;
    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull;
    double scale, zero;
    char tform[20], ctrue = 'T', cfalse = 'F';
    char message[FLEN_ERRMSG];
    char snull[20];   /*  the FITS null value  */

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
        tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
        return(*status);

    if (tcode != TLOGICAL)   
        return(*status = NOT_LOGICAL_COL);

    /*---------------------------------------------------------------------*/
    /*  Now write the logical values one at a time to the FITS column.     */
    /*---------------------------------------------------------------------*/
    remain = nelem;           /* remaining number of values to write  */
    next = 0;                 /* next element in array to be written  */
    rownum = 0;               /* row number, relative to firstrow     */

    while (remain)
    {
      wrtptr = startpos + (rowlen * rownum) + (elemnum * incre);

      ffmbyt(fptr, wrtptr, IGNORE_EOF, status);  /* move to write position */

      if (array[next])
         ffpbyt(fptr, 1, &ctrue, status);
      else
         ffpbyt(fptr, 1, &cfalse, status);

      if (*status > 0)  /* test for error during previous write operation */
      {
        snprintf(message,FLEN_ERRMSG,
           "Error writing element %.0f of input array of logicals (ffpcll).",
            (double) (next+1));
        ffpmsg(message);
        return(*status);
      }

      /*--------------------------------------------*/
      /*  increment the counters for the next loop  */
      /*--------------------------------------------*/
      remain--;
      if (remain)
      {
        next++;
        elemnum++;
        if (elemnum == repeat)  /* completed a row; start on next row */
        {
           elemnum = 0;
           rownum++;
        }
      }

    }  /*  End of main while Loop  */

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpcnl( fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
            char  *array,    /* I - array of values to write                */
            char  nulvalue,  /* I - array flagging undefined pixels if true */
            int  *status)    /* IO - error status                           */
/*
  Write an array of elements to the specified column of a table.  Any input
  pixels flagged as null will be replaced by the appropriate
  null value in the output FITS file. 
*/
{
    tcolumn *colptr;
    LONGLONG  ngood = 0, nbad = 0, ii;
    LONGLONG repeat, first, fstelm, fstrow;
    int tcode;

    if (*status > 0)
        return(*status);

    /* reset position to the correct HDU if necessary */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
    {
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
    }
    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
    {
        if ( ffrdef(fptr, status) > 0)               /* rescan header */
            return(*status);
    }

    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
    colptr += (colnum - 1);     /* offset to correct column structure */

    tcode  = colptr->tdatatype;

    if (tcode > 0)
       repeat = colptr->trepeat;  /* repeat count for this column */
    else
       repeat = firstelem -1 + nelem;  /* variable length arrays */

    /* first write the whole input vector, then go back and fill in the nulls */
    if (ffpcll(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0)
          return(*status);

    /* absolute element number in the column */
    first = (firstrow - 1) * repeat + firstelem;

    for (ii = 0; ii < nelem; ii++)
    {
      if (array[ii] != nulvalue)  /* is this a good pixel? */
      {
         if (nbad)  /* write previous string of bad pixels */
         {
            fstelm = ii - nbad + first;  /* absolute element number */
            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

            if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
                return(*status);

            nbad=0;
         }

         ngood = ngood +1;  /* the consecutive number of good pixels */
      }
      else
      {
         if (ngood)  /* write previous string of good pixels */
         {
            fstelm = ii - ngood + first;  /* absolute element number */
            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

/*  good values have already been written
            if (ffpcll(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
                status) > 0)
                return(*status);
*/
            ngood=0;
         }

         nbad = nbad +1;  /* the consecutive number of bad pixels */
      }
    }

    /* finished loop;  now just write the last set of pixels */

    if (ngood)  /* write last string of good pixels */
    {
      fstelm = ii - ngood + first;  /* absolute element number */
      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

/*  these have already been written
      ffpcll(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
*/
    }
    else if (nbad) /* write last string of bad pixels */
    {
      fstelm = ii - nbad + first;  /* absolute element number */
      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

      ffpclu(fptr, colnum, fstrow, fstelm, nbad, status);
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpclx( fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  frow,      /* I - first row to write (1 = 1st row)        */
            long  fbit,      /* I - first bit to write (1 = 1st)            */
            long  nbit,      /* I - number of bits to write                 */
            char *larray,    /* I - array of logicals corresponding to bits */
            int  *status)    /* IO - error status                           */
/*
  write an array of logical values to a specified bit or byte
  column of the binary table.   If larray is TRUE, then the corresponding
  bit is set to 1, otherwise it is set to 0.
  The binary table column being written to must have datatype 'B' or 'X'. 
*/
{
    LONGLONG offset, bstart, repeat, rowlen, elemnum, rstart, estart, tnull;
    long fbyte, lbyte, nbyte, bitloc, ndone;
    long ii, twidth, incre;
    int tcode, descrp, maxelem, hdutype;
    double dummyd;
    char tform[12], snull[12];
    unsigned char cbuff;
    static unsigned char onbit[8] = {128,  64,  32,  16,   8,   4,   2,   1};
    static unsigned char offbit[8] = {127, 191, 223, 239, 247, 251, 253, 254};
    LONGLONG heapoffset, lrepeat;
    tcolumn *colptr;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /*  check input parameters */
    if (nbit < 1)
        return(*status);
    else if (frow < 1)
        return(*status = BAD_ROW_NUM);
    else if (fbit < 1)
        return(*status = BAD_ELEM_NUM);

    /* reset position to the correct HDU if necessary */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    /* rescan header if data structure is undefined */
    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
        if ( ffrdef(fptr, status) > 0)               
            return(*status);

    fbyte = (fbit + 7) / 8;
    lbyte = (fbit + nbit + 6) / 8;
    nbyte = lbyte - fbyte +1;

    /* Save the current heapsize; ffgcprll will increment the value if */
    /* we are writing to a variable length column. */
    offset = (fptr->Fptr)->heapsize;

    /* call ffgcprll in case we are writing beyond the current end of   */
    /* the table; it will allocate more space and shift any following */
    /* HDU's.  Otherwise, we have little use for most of the returned */
    /* parameters, therefore just use dummy parameters.               */

    if (ffgcprll( fptr, colnum, frow, fbyte, nbyte, 1, &dummyd, &dummyd,
        tform, &twidth, &tcode, &maxelem, &bstart, &elemnum, &incre,
        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
        return(*status);

    bitloc = fbit - 1 - ((fbit - 1) / 8 * 8);
    ndone = 0;
    rstart = frow - 1;
    estart = fbyte - 1;

    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
    colptr += (colnum - 1);     /* offset to correct column structure */

    tcode = colptr->tdatatype;

    if (abs(tcode) > TBYTE)
        return(*status = NOT_LOGICAL_COL); /* not correct datatype column */

    if (tcode > 0)
    {
        descrp = FALSE;  /* not a variable length descriptor column */
        repeat = colptr->trepeat;

        if (tcode == TBIT)
            repeat = (repeat + 7) / 8; /* convert from bits to bytes */

        if (fbyte > repeat)
            return(*status = BAD_ELEM_NUM);

        /* calc the i/o pointer location to start of sequence of pixels */
        bstart = (fptr->Fptr)->datastart + ((fptr->Fptr)->rowlength * rstart) +
               colptr->tbcol + estart;
    }
    else
    {
        descrp = TRUE;  /* a variable length descriptor column */
        /* only bit arrays (tform = 'X') are supported for variable */
        /* length arrays.  REPEAT is the number of BITS in the array. */

        repeat = fbit + nbit -1;

        /* write the number of elements and the starting offset.    */
        /* Note: ffgcprll previous wrote the descripter, but with the */
        /* wrong repeat value  (gave bytes instead of bits).        */
        /* Make sure to not change the current heap offset value!  */

        if (tcode == -TBIT) {
            ffgdesll(fptr, colnum, frow, &lrepeat, &heapoffset, status);
            ffpdes(  fptr, colnum, frow, (long) repeat, heapoffset, status);
	}

        /* Calc the i/o pointer location to start of sequence of pixels.   */
        /* ffgcprll has already calculated a value for bstart that         */
        /* points to the first element of the vector; we just have to      */
        /* increment it to point to the first element we want to write to. */
        /* Note: ffgcprll also already updated the size of the heap, so we */
        /* don't have to do that again here.                               */

        bstart += estart;
    }

    /* move the i/o pointer to the start of the pixel sequence */
    ffmbyt(fptr, bstart, IGNORE_EOF, status);

    /* read the next byte (we may only be modifying some of the bits) */
    while (1)
    {
      if (ffgbyt(fptr, 1, &cbuff, status) == END_OF_FILE)
      {
        /* hit end of file trying to read the byte, so just set byte = 0 */
        *status = 0;
        cbuff = 0;
      }

      /* move back, to be able to overwrite the byte */
      ffmbyt(fptr, bstart, IGNORE_EOF, status);
 
      for (ii = bitloc; (ii < 8) && (ndone < nbit); ii++, ndone++)
      {
        if(larray[ndone])
          cbuff = cbuff | onbit[ii];
        else
          cbuff = cbuff & offbit[ii];
      }

      ffpbyt(fptr, 1, &cbuff, status); /* write the modified byte */
      if (ndone == nbit)  /* finished all the bits */
        return(*status);

      /* not done, so get the next byte */
      bstart++;
      if (!descrp)
      {
        estart++;
        if (estart == repeat)
        {
          /* move the i/o pointer to the next row of pixels */
          estart = 0;
          rstart = rstart + 1;
          bstart = (fptr->Fptr)->datastart + ((fptr->Fptr)->rowlength * rstart) +
               colptr->tbcol;

          ffmbyt(fptr, bstart, IGNORE_EOF, status);
        }
      }
      bitloc = 0;
    }
}

cfitsio/putcols.c0000644000225700000360000002530013246025103013635 0ustar  cagordonlhea/*  This file, putcols.c, contains routines that write data elements to    */
/*  a FITS image or table, of type character string.                       */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include "fitsio2.h"
/*--------------------------------------------------------------------------*/
int ffpcls( fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of strings to write              */
            char  **array,   /* I - array of pointers to strings            */
            int  *status)    /* IO - error status                           */
/*
  Write an array of string values to a column in the current FITS HDU.
*/
{
    int tcode, maxelem, hdutype, nchar;
    long twidth, incre;
    long ii, jj, ntodo;
    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull;
    double scale, zero;
    char tform[20], *blanks;
    char message[FLEN_ERRMSG];
    char snull[20];   /*  the FITS null value  */
    tcolumn *colptr;

    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
    char *buffer, *arrayptr;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /* reset position to the correct HDU if necessary */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
    {
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
    }
    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
    {
        if ( ffrdef(fptr, status) > 0)               /* rescan header */
            return(*status);
    }

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if (colnum < 1 || colnum > (fptr->Fptr)->tfield)
    {
        snprintf(message, FLEN_ERRMSG,"Specified column number is out of range: %d",
                colnum);
        ffpmsg(message);
        return(*status = BAD_COL_NUM);
    }

    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
    colptr += (colnum - 1);     /* offset to correct column structure */
    tcode = colptr->tdatatype;

    if (tcode == -TSTRING) /* variable length column in a binary table? */
    {
      /* only write a single string; ignore value of firstelem */
      nchar = maxvalue(1,strlen(array[0])); /* will write at least 1 char */
                                          /* even if input string is null */

      if (ffgcprll( fptr, colnum, firstrow, 1, nchar, 1, &scale, &zero,
        tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
        return(*status);
	
      /* simply move to write position, then write the string */
      ffmbyt(fptr, startpos, IGNORE_EOF, status); 
      ffpbyt(fptr, nchar, array[0], status);

      if (*status > 0)  /* test for error during previous write operation */
      {
         snprintf(message,FLEN_ERRMSG,
          "Error writing to variable length string column (ffpcls).");
         ffpmsg(message);
      }

      return(*status);
    }
    else if (tcode == TSTRING)
    {
      if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
        tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
        return(*status);

      /* if string length is greater than a FITS block (2880 char) then must */
      /* only write 1 string at a time, to force writein by ffpbyt instead of */
      /* ffpbytoff (ffpbytoff can't handle this case) */
      if (twidth > IOBUFLEN) {
        maxelem = 1;
        incre = twidth;
        repeat = 1;
      }   

      blanks = (char *) malloc(twidth); /* string for blank fill values */
      if (!blanks)
      {
        ffpmsg("Could not allocate memory for string (ffpcls)");
        return(*status = ARRAY_TOO_BIG);
      }

      for (ii = 0; ii < twidth; ii++)
          blanks[ii] = ' ';          /* fill string with blanks */

      remain = nelem;           /* remaining number of values to write  */
    }
    else 
      return(*status = NOT_ASCII_COL);
 
    /*-------------------------------------------------------*/
    /*  Now write the strings to the FITS column.            */
    /*-------------------------------------------------------*/

    next = 0;                 /* next element in array to be written  */
    rownum = 0;               /* row number, relative to firstrow     */

    while (remain)
    {
      /* limit the number of pixels to process at one time to the number that
         will fit in the buffer space or to the number of pixels that remain
         in the current vector, which ever is smaller.
      */
      ntodo = (long) minvalue(remain, maxelem);      
      ntodo = (long) minvalue(ntodo, (repeat - elemnum));

      wrtptr = startpos + (rownum * rowlen) + (elemnum * incre);
      ffmbyt(fptr, wrtptr, IGNORE_EOF, status);  /* move to write position */

      buffer = (char *) cbuff;

      /* copy the user's strings into the buffer */
      for (ii = 0; ii < ntodo; ii++)
      {
         arrayptr = array[next];

         for (jj = 0; jj < twidth; jj++)  /*  copy the string, char by char */
         {
            if (*arrayptr)
            {
              *buffer = *arrayptr;
              buffer++;
              arrayptr++;
            }
            else
              break;
         }

         for (;jj < twidth; jj++)    /* fill field with blanks, if needed */
         {
           *buffer = ' ';
           buffer++;
         }

         next++;
      }

      /* write the buffer full of strings to the FITS file */
      if (incre == twidth)
         ffpbyt(fptr, ntodo * twidth, cbuff, status);
      else
         ffpbytoff(fptr, twidth, ntodo, incre - twidth, cbuff, status);

      if (*status > 0)  /* test for error during previous write operation */
      {
         snprintf(message,FLEN_ERRMSG,
          "Error writing elements %.0f thru %.0f of input data array (ffpcls).",
             (double) (next+1), (double) (next+ntodo));
         ffpmsg(message);

         if (blanks)
           free(blanks);

         return(*status);
      }

      /*--------------------------------------------*/
      /*  increment the counters for the next loop  */
      /*--------------------------------------------*/
      remain -= ntodo;
      if (remain)
      {
          elemnum += ntodo;
          if (elemnum == repeat)  /* completed a row; start on next row */
          {
              elemnum = 0;
              rownum++;
          }
       }
    }  /*  End of main while Loop  */

    if (blanks)
      free(blanks);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpcns( fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
            char  **array,   /* I - array of values to write                */
            char  *nulvalue, /* I - string representing a null value        */
            int  *status)    /* IO - error status                           */
/*
  Write an array of elements to the specified column of a table.  Any input
  pixels flagged as null will be replaced by the appropriate
  null value in the output FITS file. 
*/
{
    long repeat, width;
    LONGLONG ngood = 0, nbad = 0, ii;
    LONGLONG first, fstelm, fstrow;

    if (*status > 0)
        return(*status);

    /* reset position to the correct HDU if necessary */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
    {
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
    }
    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
    {
        if ( ffrdef(fptr, status) > 0)               /* rescan header */
            return(*status);
    }

    /* get the vector repeat length of the column */
    ffgtcl(fptr, colnum, NULL, &repeat, &width, status);

    if ((fptr->Fptr)->hdutype == BINARY_TBL)
        repeat = repeat / width;    /* convert from chars to unit strings */

    /* absolute element number in the column */
    first = (firstrow - 1) * repeat + firstelem;

    for (ii = 0; ii < nelem; ii++)
    {
      if (strcmp(nulvalue, array[ii]))  /* is this a good pixel? */
      {
         if (nbad)  /* write previous string of bad pixels */
         {
            fstelm = ii - nbad + first;  /* absolute element number */
            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

            if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
                return(*status);
            nbad=0;
         }

         ngood = ngood +1;  /* the consecutive number of good pixels */
      }
      else
      {
         if (ngood)  /* write previous string of good pixels */
         {
            fstelm = ii - ngood + first;  /* absolute element number */
            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

            if (ffpcls(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
                status) > 0)
                return(*status);

            ngood=0;
         }

         nbad = nbad +1;  /* the consecutive number of bad pixels */
      }
    }

    /* finished loop;  now just write the last set of pixels */

    if (ngood)  /* write last string of good pixels */
    {
      fstelm = ii - ngood + first;  /* absolute element number */
      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

      ffpcls(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
    }
    else if (nbad) /* write last string of bad pixels */
    {
      fstelm = ii - nbad + first;  /* absolute element number */
      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

      ffpclu(fptr, colnum, fstrow, fstelm, nbad, status);
    }

    return(*status);
}
cfitsio/putcolsb.c0000644000225700000360000010407313246025103014004 0ustar  cagordonlhea/*  This file, putcolsb.c, contains routines that write data elements to   */
/*  a FITS image or table with signed char (signed byte) datatype.         */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int ffpprsb( fitsfile *fptr,  /* I - FITS file pointer                      */
            long  group,     /* I - group to write(1 = 1st group)           */
            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
            LONGLONG  nelem,     /* I - number of values to write               */
            signed char *array, /* I - array of values that are written     */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written).
*/
{
    long row;
    signed char nullvalue;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_write_compressed_pixels(fptr, TSBYTE, firstelem, nelem,
            0, array, &nullvalue, status);
        return(*status);
    }

    row=maxvalue(1,group);

    ffpclsb(fptr, 2, row, firstelem, nelem, array, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffppnsb( fitsfile *fptr,  /* I - FITS file pointer                      */
            long  group,     /* I - group to write(1 = 1st group)           */
            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
            LONGLONG  nelem,     /* I - number of values to write               */
            signed char *array, /* I - array of values that are written     */
            signed char nulval, /* I - undefined pixel value                */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).  Any array values
  that are equal to the value of nulval will be replaced with the null
  pixel value that is appropriate for this column.
*/
{
    long row;
    signed char nullvalue;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        nullvalue = nulval;  /* set local variable */
        fits_write_compressed_pixels(fptr, TSBYTE, firstelem, nelem,
            1, array, &nullvalue, status);
        return(*status);
    }

    row=maxvalue(1,group);

    ffpcnsb(fptr, 2, row, firstelem, nelem, array, nulval, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffp2dsb(fitsfile *fptr,   /* I - FITS file pointer                    */
           long  group,      /* I - group to write(1 = 1st group)         */
           LONGLONG  ncols,      /* I - number of pixels in each row of array */
           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
           signed char *array, /* I - array to be written                 */
           int  *status)     /* IO - error status                         */
/*
  Write an entire 2-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).
*/
{
    /* call the 3D writing routine, with the 3rd dimension = 1 */

    ffp3dsb(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffp3dsb(fitsfile *fptr,   /* I - FITS file pointer                    */
           long  group,      /* I - group to write(1 = 1st group)         */
           LONGLONG  ncols,      /* I - number of pixels in each row of array */
           LONGLONG  nrows,      /* I - number of rows in each plane of array */
           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
           LONGLONG  naxis3,     /* I - FITS image NAXIS3 value               */
           signed char *array, /* I - array to be written                 */
           int  *status)     /* IO - error status                         */
/*
  Write an entire 3-D cube of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).
*/
{
    long tablerow, ii, jj;
    long fpixel[3]= {1,1,1}, lpixel[3];
    LONGLONG nfits, narray;
    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */
           
    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */
        lpixel[0] = (long) ncols;
        lpixel[1] = (long) nrows;
        lpixel[2] = (long) naxis3;
       
        fits_write_compressed_img(fptr, TSBYTE, fpixel, lpixel,
            0,  array, NULL, status);
    
        return(*status);
    }

    tablerow=maxvalue(1,group);

    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
    {
      /* all the image pixels are contiguous, so write all at once */
      ffpclsb(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status);
      return(*status);
    }

    if (ncols < naxis1 || nrows < naxis2)
       return(*status = BAD_DIMEN);

    nfits = 1;   /* next pixel in FITS image to write to */
    narray = 0;  /* next pixel in input array to be written */

    /* loop over naxis3 planes in the data cube */
    for (jj = 0; jj < naxis3; jj++)
    {
      /* loop over the naxis2 rows in the FITS image, */
      /* writing naxis1 pixels to each row            */

      for (ii = 0; ii < naxis2; ii++)
      {
       if (ffpclsb(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0)
         return(*status);

       nfits += naxis1;
       narray += ncols;
      }
      narray += (nrows - naxis2) * ncols;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpsssb(fitsfile *fptr,   /* I - FITS file pointer                      */
           long  group,      /* I - group to write(1 = 1st group)           */
           long  naxis,      /* I - number of data axes in array            */
           long  *naxes,     /* I - size of each FITS axis                  */
           long  *fpixel,    /* I - 1st pixel in each axis to write (1=1st) */
           long  *lpixel,    /* I - last pixel in each axis to write        */
           signed char *array, /* I - array to be written                   */
           int  *status)     /* IO - error status                           */
/*
  Write a subsection of pixels to the primary array or image.
  A subsection is defined to be any contiguous rectangular
  array of pixels within the n-dimensional FITS data file.
  Data conversion and scaling will be performed if necessary 
  (e.g, if the datatype of the FITS array is not the same as
  the array being written).
*/
{
    long tablerow;
    LONGLONG fpix[7], dimen[7], astart, pstart;
    LONGLONG off2, off3, off4, off5, off6, off7;
    LONGLONG st10, st20, st30, st40, st50, st60, st70;
    LONGLONG st1, st2, st3, st4, st5, st6, st7;
    long ii, i1, i2, i3, i4, i5, i6, i7, irange[7];

    if (*status > 0)
        return(*status);

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_write_compressed_img(fptr, TSBYTE, fpixel, lpixel,
            0,  array, NULL, status);
    
        return(*status);
    }

    if (naxis < 1 || naxis > 7)
      return(*status = BAD_DIMEN);

    tablerow=maxvalue(1,group);

     /* calculate the size and number of loops to perform in each dimension */
    for (ii = 0; ii < 7; ii++)
    {
      fpix[ii]=1;
      irange[ii]=1;
      dimen[ii]=1;
    }

    for (ii = 0; ii < naxis; ii++)
    {    
      fpix[ii]=fpixel[ii];
      irange[ii]=lpixel[ii]-fpixel[ii]+1;
      dimen[ii]=naxes[ii];
    }

    i1=irange[0];

    /* compute the pixel offset between each dimension */
    off2 =     dimen[0];
    off3 = off2 * dimen[1];
    off4 = off3 * dimen[2];
    off5 = off4 * dimen[3];
    off6 = off5 * dimen[4];
    off7 = off6 * dimen[5];

    st10 = fpix[0];
    st20 = (fpix[1] - 1) * off2;
    st30 = (fpix[2] - 1) * off3;
    st40 = (fpix[3] - 1) * off4;
    st50 = (fpix[4] - 1) * off5;
    st60 = (fpix[5] - 1) * off6;
    st70 = (fpix[6] - 1) * off7;

    /* store the initial offset in each dimension */
    st1 = st10;
    st2 = st20;
    st3 = st30;
    st4 = st40;
    st5 = st50;
    st6 = st60;
    st7 = st70;

    astart = 0;

    for (i7 = 0; i7 < irange[6]; i7++)
    {
     for (i6 = 0; i6 < irange[5]; i6++)
     {
      for (i5 = 0; i5 < irange[4]; i5++)
      {
       for (i4 = 0; i4 < irange[3]; i4++)
       {
        for (i3 = 0; i3 < irange[2]; i3++)
        {
         pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7;

         for (i2 = 0; i2 < irange[1]; i2++)
         {
           if (ffpclsb(fptr, 2, tablerow, pstart, i1, &array[astart],
              status) > 0)
              return(*status);

           astart += i1;
           pstart += off2;
         }
         st2 = st20;
         st3 = st3+off3;    
        }
        st3 = st30;
        st4 = st4+off4;
       }
       st4 = st40;
       st5 = st5+off5;
      }
      st5 = st50;
      st6 = st6+off6;
     }
     st6 = st60;
     st7 = st7+off7;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpgpsb( fitsfile *fptr,   /* I - FITS file pointer                     */
            long  group,      /* I - group to write(1 = 1st group)          */
            long  firstelem,  /* I - first vector element to write(1 = 1st) */
            long  nelem,      /* I - number of values to write              */
            signed char *array, /* I - array of values that are written     */
            int  *status)     /* IO - error status                          */
/*
  Write an array of group parameters to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written).
*/
{
    long row;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffpclsb(fptr, 1L, row, firstelem, nelem, array, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpclsb( fitsfile *fptr,  /* I - FITS file pointer                      */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
            signed char *array, /* I - array of values to write             */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to a column in the current FITS HDU.
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer to a virtual column in a 1 or more grouped FITS primary
  array.  FITSIO treats a primary array as a binary table with
  2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.

  The input array of values will be converted to the datatype of the column 
  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary.
*/
{
    int tcode, maxelem, hdutype;
    long twidth, incre;
    long ntodo;
    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull;
    double scale, zero;
    char tform[20], cform[20];
    char message[FLEN_ERRMSG];

    char snull[20];   /*  the FITS null value  */

    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
    void *buffer;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    buffer = cbuff;

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
        tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
        return(*status);

    if (tcode == TSTRING)   
         ffcfmt(tform, cform);     /* derive C format for writing strings */

    /*---------------------------------------------------------------------*/
    /*  Now write the pixels to the FITS column.                           */
    /*  First call the ffXXfYY routine to  (1) convert the datatype        */
    /*  if necessary, and (2) scale the values by the FITS TSCALn and      */
    /*  TZEROn linear scaling parameters into a temporary buffer.          */
    /*---------------------------------------------------------------------*/
    remain = nelem;           /* remaining number of values to write  */
    next = 0;                 /* next element in array to be written  */
    rownum = 0;               /* row number, relative to firstrow     */

    while (remain)
    {
        /* limit the number of pixels to process a one time to the number that
           will fit in the buffer space or to the number of pixels that remain
           in the current vector, which ever is smaller.
        */
        ntodo = (long) minvalue(remain, maxelem);      
        ntodo = (long) minvalue(ntodo, (repeat - elemnum));

        wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);
        ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */

        switch (tcode) 
        {
            case (TBYTE):

                /* convert the raw data before writing to FITS file */
                ffs1fi1(&array[next], ntodo, scale, zero,
                        (unsigned char *) buffer, status);
                ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status);

              break;

            case (TLONGLONG):

                ffs1fi8(&array[next], ntodo, scale, zero,
                        (LONGLONG *) buffer, status);
                ffpi8b(fptr, ntodo, incre, (long *) buffer, status);
                break;

            case (TSHORT):
 
                ffs1fi2(&array[next], ntodo, scale, zero,
                        (short *) buffer, status);
                ffpi2b(fptr, ntodo, incre, (short *) buffer, status);
                break;

            case (TLONG):

                ffs1fi4(&array[next], ntodo, scale, zero,
                        (INT32BIT *) buffer, status);
                ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status);
                break;

            case (TFLOAT):

                ffs1fr4(&array[next], ntodo, scale, zero,
                        (float *)  buffer, status);
                ffpr4b(fptr, ntodo, incre, (float *) buffer, status);
                break;

            case (TDOUBLE):
                ffs1fr8(&array[next], ntodo, scale, zero,
                        (double *) buffer, status);
                ffpr8b(fptr, ntodo, incre, (double *) buffer, status);
                break;

            case (TSTRING):  /* numerical column in an ASCII table */

                if (strchr(tform,'A'))
                {
                    /* write raw input bytes without conversion        */
                    /* This case is a hack to let users write a stream */
                    /* of bytes directly to the 'A' format column      */

                    if (incre == twidth)
                        ffpbyt(fptr, ntodo, &array[next], status);
                    else
                        ffpbytoff(fptr, twidth, ntodo/twidth, incre - twidth, 
                                &array[next], status);
                    break;
                }
                else if (cform[1] != 's')  /*  "%s" format is a string */
                {
                  ffs1fstr(&array[next], ntodo, scale, zero, cform,
                          twidth, (char *) buffer, status);

                  if (incre == twidth)    /* contiguous bytes */
                     ffpbyt(fptr, ntodo * twidth, buffer, status);
                  else
                     ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
                            status);
                  break;
                }
                /* can't write to string column, so fall thru to default: */

            default:  /*  error trap  */
                snprintf(message, FLEN_ERRMSG,
                       "Cannot write numbers to column %d which has format %s",
                        colnum,tform);
                ffpmsg(message);
                if (hdutype == ASCII_TBL)
                    return(*status = BAD_ATABLE_FORMAT);
                else
                    return(*status = BAD_BTABLE_FORMAT);

        } /* End of switch block */

        /*-------------------------*/
        /*  Check for fatal error  */
        /*-------------------------*/
        if (*status > 0)  /* test for error during previous write operation */
        {
          snprintf(message,FLEN_ERRMSG,
          "Error writing elements %.0f thru %.0f of input data array (ffpclsb).",
              (double) (next+1), (double) (next+ntodo));
          ffpmsg(message);
          return(*status);
        }

        /*--------------------------------------------*/
        /*  increment the counters for the next loop  */
        /*--------------------------------------------*/
        remain -= ntodo;
        if (remain)
        {
            next += ntodo;
            elemnum += ntodo;
            if (elemnum == repeat)  /* completed a row; start on next row */
            {
                elemnum = 0;
                rownum++;
            }
        }
    }  /*  End of main while Loop  */


    /*--------------------------------*/
    /*  check for numerical overflow  */
    /*--------------------------------*/
    if (*status == OVERFLOW_ERR)
    {
      ffpmsg(
      "Numerical overflow during type conversion while writing FITS data.");
      *status = NUM_OVERFLOW;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpcnsb( fitsfile *fptr,  /* I - FITS file pointer                      */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
            signed char *array,   /* I - array of values to write           */
            signed char nulvalue, /* I - flag for undefined pixels          */
            int  *status)    /* IO - error status                           */
/*
  Write an array of elements to the specified column of a table.  Any input
  pixels equal to the value of nulvalue will be replaced by the appropriate
  null value in the output FITS file. 

  The input array of values will be converted to the datatype of the column 
  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary
*/
{
    tcolumn *colptr;
    LONGLONG  ngood = 0, nbad = 0, ii;
    LONGLONG repeat, first, fstelm, fstrow;
    int tcode, overflow = 0;

    if (*status > 0)
        return(*status);

    /* reset position to the correct HDU if necessary */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
    {
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
    }
    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
    {
        if ( ffrdef(fptr, status) > 0)               /* rescan header */
            return(*status);
    }

    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
    colptr += (colnum - 1);     /* offset to correct column structure */

    tcode  = colptr->tdatatype;

    if (tcode > 0)
       repeat = colptr->trepeat;  /* repeat count for this column */
    else
       repeat = firstelem -1 + nelem;  /* variable length arrays */

    /* if variable length array, first write the whole input vector, 
       then go back and fill in the nulls */
    if (tcode < 0) {
      if (ffpclsb(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) {
        if (*status == NUM_OVERFLOW) 
	{
	  /* ignore overflows, which are possibly the null pixel values */
	  /*  overflow = 1;   */
	  *status = 0;
	} else { 
          return(*status);
	}
      }
    }

    /* absolute element number in the column */
    first = (firstrow - 1) * repeat + firstelem;

    for (ii = 0; ii < nelem; ii++)
    {
      if (array[ii] != nulvalue)  /* is this a good pixel? */
      {
         if (nbad)  /* write previous string of bad pixels */
         {
            fstelm = ii - nbad + first;  /* absolute element number */
            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

            if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
                return(*status);

            nbad=0;
         }

         ngood = ngood + 1;  /* the consecutive number of good pixels */
      }
      else
      {
         if (ngood)  /* write previous string of good pixels */
         {
            fstelm = ii - ngood + first;  /* absolute element number */
            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

            if (tcode > 0) {  /* variable length arrays have already been written */
              if (ffpclsb(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
                status) > 0) {
		if (*status == NUM_OVERFLOW) 
		{
		  overflow = 1;
		  *status = 0;
		} else { 
                  return(*status);
		}
	      }
	    }
            ngood=0;
         }

         nbad = nbad + 1;  /* the consecutive number of bad pixels */
      }
    }

    /* finished loop;  now just write the last set of pixels */

    if (ngood)  /* write last string of good pixels */
    {
      fstelm = ii - ngood + first;  /* absolute element number */
      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

      if (tcode > 0) {  /* variable length arrays have already been written */
        ffpclsb(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
      }
    }
    else if (nbad) /* write last string of bad pixels */
    {
      fstelm = ii - nbad + first;  /* absolute element number */
      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

      ffpclu(fptr, colnum, fstrow, fstelm, nbad, status);
    }

    if (*status <= 0) {
      if (overflow) {
        *status = NUM_OVERFLOW;
      }
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffs1fi1(signed char *input,    /* I - array of values to be converted  */
            long ntodo,            /* I - number of elements in the array  */
            double scale,          /* I - FITS TSCALn or BSCALE value      */
            double zero,           /* I - FITS TZEROn or BZERO  value      */
            unsigned char *output, /* O - output array of converted values */
            int *status)           /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == -128.)
    {
        /* Instead of adding 128, it is more efficient */
        /* to just flip the sign bit with the XOR operator */

        for (ii = 0; ii < ntodo; ii++)
             output[ii] =  ( *(unsigned char *) &input[ii] ) ^ 0x80;
    }
    else if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
            if (input[ii] < 0)
            {
                *status = OVERFLOW_ERR;
                output[ii] = 0;
            }
            else
                output[ii] = (unsigned char) input[ii];
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = ( ((double) input[ii]) - zero) / scale;

            if (dvalue < DUCHAR_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = 0;
            }
            else if (dvalue > DUCHAR_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = UCHAR_MAX;
            }
            else
                output[ii] = (unsigned char) (dvalue + .5);
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffs1fi2(signed char *input,    /* I - array of values to be converted  */
            long ntodo,            /* I - number of elements in the array  */
            double scale,          /* I - FITS TSCALn or BSCALE value      */
            double zero,           /* I - FITS TZEROn or BZERO  value      */
            short *output,         /* O - output array of converted values */
            int *status)           /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
            output[ii] = input[ii];   /* just copy input to output */
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (((double) input[ii]) - zero) / scale;

            if (dvalue < DSHRT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MIN;
            }
            else if (dvalue > DSHRT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (short) (dvalue + .5);
                else
                    output[ii] = (short) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffs1fi4(signed char *input,    /* I - array of values to be converted  */
            long ntodo,            /* I - number of elements in the array  */
            double scale,          /* I - FITS TSCALn or BSCALE value      */
            double zero,           /* I - FITS TZEROn or BZERO  value      */
            INT32BIT *output,      /* O - output array of converted values */
            int *status)           /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
            output[ii] = (INT32BIT) input[ii];   /* copy input to output */
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (((double) input[ii]) - zero) / scale;

            if (dvalue < DINT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MIN;
            }
            else if (dvalue > DINT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (INT32BIT) (dvalue + .5);
                else
                    output[ii] = (INT32BIT) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffs1fi8(signed char *input,   /* I - array of values to be converted  */
            long ntodo,           /* I - number of elements in the array  */
            double scale,         /* I - FITS TSCALn or BSCALE value      */
            double zero,          /* I - FITS TZEROn or BZERO  value      */
            LONGLONG *output,     /* O - output array of converted values */
            int *status)          /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DLONGLONG_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = LONGLONG_MIN;
            }
            else if (dvalue > DLONGLONG_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = LONGLONG_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (LONGLONG) (dvalue + .5);
                else
                    output[ii] = (LONGLONG) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffs1fr4(signed char *input,    /* I - array of values to be converted  */
            long ntodo,            /* I - number of elements in the array  */
            double scale,          /* I - FITS TSCALn or BSCALE value      */
            double zero,           /* I - FITS TZEROn or BZERO  value      */
            float *output,         /* O - output array of converted values */
            int *status)           /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = (float) input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
            output[ii] = (float) (( ( (double) input[ii] ) - zero) / scale);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffs1fr8(signed char *input,    /* I - array of values to be converted  */
            long ntodo,            /* I - number of elements in the array  */
            double scale,          /* I - FITS TSCALn or BSCALE value      */
            double zero,           /* I - FITS TZEROn or BZERO  value      */
            double *output,        /* O - output array of converted values */
            int *status)           /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = (double) input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
            output[ii] = ( ( (double) input[ii] ) - zero) / scale;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffs1fstr(signed char *input, /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            char *cform,       /* I - format for output string values  */
            long twidth,       /* I - width of each field, in chars    */
            char *output,      /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do scaling if required.
*/
{
    long ii;
    double dvalue;
    char *cptr;
    
    cptr = output;


    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
           sprintf(output, cform, (double) input[ii]);
           output += twidth;

           if (*output)  /* if this char != \0, then overflow occurred */
              *status = OVERFLOW_ERR;
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
          dvalue = ((double) input[ii] - zero) / scale;
          sprintf(output, cform, dvalue);
          output += twidth;

          if (*output)  /* if this char != \0, then overflow occurred */
            *status = OVERFLOW_ERR;
        }
    }

    /* replace any commas with periods (e.g., in French locale) */
    while ((cptr = strchr(cptr, ','))) *cptr = '.';
    
    return(*status);
}
cfitsio/putcolu.c0000644000225700000360000005206313246025103013645 0ustar  cagordonlhea/*  This file, putcolu.c, contains routines that write data elements to    */
/*  a FITS image or table.  Writes null values.                            */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int ffppru( fitsfile *fptr,  /* I - FITS file pointer                       */
            long  group,      /* I - group to write(1 = 1st group)          */
            LONGLONG  firstelem,  /* I - first vector element to write(1 = 1st) */
            LONGLONG  nelem,      /* I - number of values to write              */
            int  *status)     /* IO - error status                          */
/*
  Write null values to the primary array.

*/
{
    long row;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        ffpmsg("writing to compressed image is not supported");

        return(*status = DATA_COMPRESSION_ERR);
    }

    row=maxvalue(1,group);

    ffpclu(fptr, 2, row, firstelem, nelem, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpprn( fitsfile *fptr,  /* I - FITS file pointer                       */
            LONGLONG  firstelem,  /* I - first vector element to write(1 = 1st) */
            LONGLONG  nelem,      /* I - number of values to write              */
            int  *status)     /* IO - error status                          */
/*
  Write null values to the primary array. (Doesn't support groups).

*/
{
    long row = 1;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        ffpmsg("writing to compressed image is not supported");

        return(*status = DATA_COMPRESSION_ERR);
    }

    ffpclu(fptr, 2, row, firstelem, nelem, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpclu( fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelempar,     /* I - number of values to write               */
            int  *status)    /* IO - error status                           */
/*
  Set elements of a table column to the appropriate null value for the column
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer to a virtual column in a 1 or more grouped FITS primary
  array.  FITSIO treats a primary array as a binary table
  with 2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.
  
  This routine support COMPLEX and DOUBLE COMPLEX binary table columns, and
  sets both the real and imaginary components of the element to a NaN.
*/
{
    int tcode, maxelem, hdutype, writemode = 2, leng;
    short i2null;
    INT32BIT i4null;
    long twidth, incre;
    LONGLONG ii;
    LONGLONG largeelem, nelem, tnull, i8null;
    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, ntodo;
    double scale, zero;
    unsigned char i1null, lognul = 0;
    char tform[20], *cstring = 0;
    char message[FLEN_ERRMSG];
    char snull[20];   /*  the FITS null value  */
    long   jbuff[2] = { -1, -1};  /* all bits set is equivalent to a NaN */
    size_t buffsize;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    nelem = nelempar;
    
    largeelem = firstelem;

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/

    /* note that writemode = 2 by default (not 1), so that the returned */
    /* repeat and incre values will be the actual values for this column. */

    /* If writing nulls to a variable length column then dummy data values  */
    /* must have already been written to the heap. */
    /* We just have to overwrite the previous values with null values. */
    /* Set writemode = 0 in this case, to test that values have been written */

    fits_get_coltype(fptr, colnum, &tcode, NULL, NULL, status);
    if (tcode < 0)
         writemode = 0;  /* this is a variable length column */

    if (abs(tcode) >= TCOMPLEX)
    { /* treat complex columns as pairs of numbers */
      largeelem = (largeelem - 1) * 2 + 1;
      nelem *= 2;
    }

    if (ffgcprll( fptr, colnum, firstrow, largeelem, nelem, writemode, &scale,
       &zero, tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
        return(*status);

    if (tcode == TSTRING)
    {
      if (snull[0] == ASCII_NULL_UNDEFINED)
      {
        ffpmsg(
        "Null value string for ASCII table column is not defined (FTPCLU).");
        return(*status = NO_NULL);
      }

      /* allocate buffer to hold the null string.  Must write the entire */
      /* width of the column (twidth bytes) to avoid possible problems */
      /* with uninitialized FITS blocks, in case the field spans blocks */

      buffsize = maxvalue(20, twidth);
      cstring = (char *) malloc(buffsize);
      if (!cstring)
         return(*status = MEMORY_ALLOCATION);

      memset(cstring, ' ', buffsize);  /* initialize  with blanks */

      leng = strlen(snull);
      if (hdutype == BINARY_TBL)
         leng++;        /* copy the terminator too in binary tables */

      strncpy(cstring, snull, leng);  /* copy null string to temp buffer */
    }
    else if ( tcode == TBYTE  ||
              tcode == TSHORT ||
              tcode == TLONG  ||
              tcode == TLONGLONG) 
    {
      if (tnull == NULL_UNDEFINED)
      {
        ffpmsg(
        "Null value for integer table column is not defined (FTPCLU).");
        return(*status = NO_NULL);
      }

      if (tcode == TBYTE)
         i1null = (unsigned char) tnull;
      else if (tcode == TSHORT)
      {
         i2null = (short) tnull;
#if BYTESWAPPED
         ffswap2(&i2null, 1); /* reverse order of bytes */
#endif
      }
      else if (tcode == TLONG)
      {
         i4null = (INT32BIT) tnull;
#if BYTESWAPPED
         ffswap4(&i4null, 1); /* reverse order of bytes */
#endif
      }
      else
      {
         i8null = tnull;
#if BYTESWAPPED
         ffswap8((double *)(&i8null), 1);  /* reverse order of bytes */
#endif
      }
    }

    /*---------------------------------------------------------------------*/
    /*  Now write the pixels to the FITS column.                           */
    /*---------------------------------------------------------------------*/
    remain = nelem;           /* remaining number of values to write  */
    next = 0;                 /* next element in array to be written  */
    rownum = 0;               /* row number, relative to firstrow     */
    ntodo = remain;           /* number of elements to write at one time */

    while (ntodo)
    {
        /* limit the number of pixels to process at one time to the number that
           will fit in the buffer space or to the number of pixels that remain
           in the current vector, which ever is smaller.
        */
        ntodo = minvalue(ntodo, (repeat - elemnum));
        wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);

        ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */

        switch (tcode) 
        {
            case (TBYTE):
 
                for (ii = 0; ii < ntodo; ii++)
                  ffpbyt(fptr, 1,  &i1null, status);
                break;

            case (TSHORT):

                for (ii = 0; ii < ntodo; ii++)
                  ffpbyt(fptr, 2, &i2null, status);
                break;

            case (TLONG):

                for (ii = 0; ii < ntodo; ii++)
                  ffpbyt(fptr, 4, &i4null, status);
                break;

            case (TLONGLONG):

                for (ii = 0; ii < ntodo; ii++)
                  ffpbyt(fptr, 8, &i8null, status);
                break;

            case (TFLOAT):

                for (ii = 0; ii < ntodo; ii++)
                  ffpbyt(fptr, 4, jbuff, status);
                break;

            case (TDOUBLE):

                for (ii = 0; ii < ntodo; ii++)
                  ffpbyt(fptr, 8, jbuff, status);
                break;

            case (TLOGICAL):
 
                for (ii = 0; ii < ntodo; ii++)
                  ffpbyt(fptr, 1, &lognul, status);
                break;

            case (TSTRING):  /* an ASCII table column */
                /* repeat always = 1, so ntodo is also guaranteed to = 1 */
                ffpbyt(fptr, twidth, cstring, status);
                break;

            default:  /*  error trap  */
                snprintf(message,FLEN_ERRMSG, 
                   "Cannot write null value to column %d which has format %s",
                     colnum,tform);
                ffpmsg(message);
                return(*status);

        } /* End of switch block */

        /*-------------------------*/
        /*  Check for fatal error  */
        /*-------------------------*/
        if (*status > 0)  /* test for error during previous write operation */
        {
           snprintf(message,FLEN_ERRMSG,
             "Error writing %.0f thru %.0f of null values (ffpclu).",
              (double) (next+1), (double) (next+ntodo));
           ffpmsg(message);

           if (cstring)
              free(cstring);

           return(*status);
        }

        /*--------------------------------------------*/
        /*  increment the counters for the next loop  */
        /*--------------------------------------------*/
        remain -= ntodo;
        if (remain)
        {
            next += ntodo;
            elemnum += ntodo;
            if (elemnum == repeat)  /* completed a row; start on next row */
            {
                elemnum = 0;
                rownum++;
            }
        }
        ntodo = remain;  /* this is the maximum number to do in next loop */

    }  /*  End of main while Loop  */

    if (cstring)
       free(cstring);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpcluc( fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
            int  *status)    /* IO - error status                           */
/*
  Set elements of a table column to the appropriate null value for the column
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer to a virtual column in a 1 or more grouped FITS primary
  array.  FITSIO treats a primary array as a binary table
  with 2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.
  
  This routine does not do anything special in the case of COMPLEX table columns
  (unlike the similar ffpclu routine).  This routine is mainly for use by
  ffpcne which already compensates for the effective doubling of the number of 
  elements in a complex column.
*/
{
    int tcode, maxelem, hdutype, writemode = 2, leng;
    short i2null;
    INT32BIT i4null;
    long twidth, incre;
    LONGLONG ii;
    LONGLONG tnull, i8null;
    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, ntodo;
    double scale, zero;
    unsigned char i1null, lognul = 0;
    char tform[20], *cstring = 0;
    char message[FLEN_ERRMSG];
    char snull[20];   /*  the FITS null value  */
    long   jbuff[2] = { -1, -1};  /* all bits set is equivalent to a NaN */
    size_t buffsize;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/

    /* note that writemode = 2 by default (not 1), so that the returned */
    /* repeat and incre values will be the actual values for this column. */

    /* If writing nulls to a variable length column then dummy data values  */
    /* must have already been written to the heap. */
    /* We just have to overwrite the previous values with null values. */
    /* Set writemode = 0 in this case, to test that values have been written */

    fits_get_coltype(fptr, colnum, &tcode, NULL, NULL, status);
    if (tcode < 0)
         writemode = 0;  /* this is a variable length column */
    
    if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, writemode, &scale,
       &zero, tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
        return(*status);

    if (tcode == TSTRING)
    {
      if (snull[0] == ASCII_NULL_UNDEFINED)
      {
        ffpmsg(
        "Null value string for ASCII table column is not defined (FTPCLU).");
        return(*status = NO_NULL);
      }

      /* allocate buffer to hold the null string.  Must write the entire */
      /* width of the column (twidth bytes) to avoid possible problems */
      /* with uninitialized FITS blocks, in case the field spans blocks */

      buffsize = maxvalue(20, twidth);
      cstring = (char *) malloc(buffsize);
      if (!cstring)
         return(*status = MEMORY_ALLOCATION);

      memset(cstring, ' ', buffsize);  /* initialize  with blanks */

      leng = strlen(snull);
      if (hdutype == BINARY_TBL)
         leng++;        /* copy the terminator too in binary tables */

      strncpy(cstring, snull, leng);  /* copy null string to temp buffer */

    }
    else if ( tcode == TBYTE  ||
              tcode == TSHORT ||
              tcode == TLONG  ||
              tcode == TLONGLONG) 
    {
      if (tnull == NULL_UNDEFINED)
      {
        ffpmsg(
        "Null value for integer table column is not defined (FTPCLU).");
        return(*status = NO_NULL);
      }

      if (tcode == TBYTE)
         i1null = (unsigned char) tnull;
      else if (tcode == TSHORT)
      {
         i2null = (short) tnull;
#if BYTESWAPPED
         ffswap2(&i2null, 1); /* reverse order of bytes */
#endif
      }
      else if (tcode == TLONG)
      {
         i4null = (INT32BIT) tnull;
#if BYTESWAPPED
         ffswap4(&i4null, 1); /* reverse order of bytes */
#endif
      }
      else
      {
         i8null = tnull;
#if BYTESWAPPED
         ffswap4( (INT32BIT*) &i8null, 2); /* reverse order of bytes */
#endif
      }
    }

    /*---------------------------------------------------------------------*/
    /*  Now write the pixels to the FITS column.                           */
    /*---------------------------------------------------------------------*/
    remain = nelem;           /* remaining number of values to write  */
    next = 0;                 /* next element in array to be written  */
    rownum = 0;               /* row number, relative to firstrow     */
    ntodo = remain;           /* number of elements to write at one time */

    while (ntodo)
    {
        /* limit the number of pixels to process at one time to the number that
           will fit in the buffer space or to the number of pixels that remain
           in the current vector, which ever is smaller.
        */
        ntodo = minvalue(ntodo, (repeat - elemnum));
        wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);

        ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */

        switch (tcode) 
        {
            case (TBYTE):
 
                for (ii = 0; ii < ntodo; ii++)
                  ffpbyt(fptr, 1,  &i1null, status);
                break;

            case (TSHORT):

                for (ii = 0; ii < ntodo; ii++)
                  ffpbyt(fptr, 2, &i2null, status);
                break;

            case (TLONG):

                for (ii = 0; ii < ntodo; ii++)
                  ffpbyt(fptr, 4, &i4null, status);
                break;

            case (TLONGLONG):

                for (ii = 0; ii < ntodo; ii++)
                  ffpbyt(fptr, 8, &i8null, status);
                break;

            case (TFLOAT):

                for (ii = 0; ii < ntodo; ii++)
                  ffpbyt(fptr, 4, jbuff, status);
                break;

            case (TDOUBLE):

                for (ii = 0; ii < ntodo; ii++)
                  ffpbyt(fptr, 8, jbuff, status);
                break;

            case (TLOGICAL):
 
                for (ii = 0; ii < ntodo; ii++)
                  ffpbyt(fptr, 1, &lognul, status);
                break;

            case (TSTRING):  /* an ASCII table column */
                /* repeat always = 1, so ntodo is also guaranteed to = 1 */
                ffpbyt(fptr, twidth, cstring, status);
                break;

            default:  /*  error trap  */
                snprintf(message, FLEN_ERRMSG,
                   "Cannot write null value to column %d which has format %s",
                     colnum,tform);
                ffpmsg(message);
                return(*status);

        } /* End of switch block */

        /*-------------------------*/
        /*  Check for fatal error  */
        /*-------------------------*/
        if (*status > 0)  /* test for error during previous write operation */
        {
           snprintf(message,FLEN_ERRMSG,
             "Error writing %.0f thru %.0f of null values (ffpclu).",
              (double) (next+1), (double) (next+ntodo));
           ffpmsg(message);

           if (cstring)
              free(cstring);

           return(*status);
        }

        /*--------------------------------------------*/
        /*  increment the counters for the next loop  */
        /*--------------------------------------------*/
        remain -= ntodo;
        if (remain)
        {
            next += ntodo;
            elemnum += ntodo;
            if (elemnum == repeat)  /* completed a row; start on next row */
            {
                elemnum = 0;
                rownum++;
            }
        }
        ntodo = remain;  /* this is the maximum number to do in next loop */

    }  /*  End of main while Loop  */

    if (cstring)
       free(cstring);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffprwu(fitsfile *fptr,
           LONGLONG firstrow,
           LONGLONG nrows, 
           int *status)

/* 
 * fits_write_nullrows / ffprwu - write TNULLs to all columns in one or more rows
 *
 * fitsfile *fptr - pointer to FITS HDU opened for read/write
 * long int firstrow - first table row to set to null. (firstrow >= 1)
 * long int nrows - total number or rows to set to null. (nrows >= 1)
 * int *status - upon return, *status contains CFITSIO status code
 *
 * RETURNS: CFITSIO status code
 *
 * written by Craig Markwardt, GSFC 
 */
{
  LONGLONG ntotrows;
  int ncols, i;
  int typecode = 0;
  LONGLONG repeat = 0, width = 0;
  int nullstatus;

  if (*status > 0) return *status;

  if ((firstrow <= 0) || (nrows <= 0)) return (*status = BAD_ROW_NUM);

  fits_get_num_rowsll(fptr, &ntotrows, status);

  if (firstrow + nrows - 1 > ntotrows) return (*status = BAD_ROW_NUM);
  
  fits_get_num_cols(fptr, &ncols, status);
  if (*status) return *status;


  /* Loop through each column and write nulls */
  for (i=1; i <= ncols; i++) {
    repeat = 0;  typecode = 0;  width = 0;
    fits_get_coltypell(fptr, i, &typecode, &repeat, &width, status);
    if (*status) break;

    /* NOTE: data of TSTRING type must not write the total repeat
       count, since the repeat count is the *character* count, not the
       nstring count.  Divide by string width to get number of
       strings. */
    
    if (typecode == TSTRING) repeat /= width;

    /* Write NULLs */
    nullstatus = 0;
    fits_write_col_null(fptr, i, firstrow, 1, repeat*nrows, &nullstatus);

    /* ignore error if no null value is defined for the column */
    if (nullstatus && nullstatus != NO_NULL) return (*status = nullstatus);
    
  }
    
  return *status;
}

cfitsio/putcolui.c0000644000225700000360000010300713246025103014011 0ustar  cagordonlhea/*  This file, putcolui.c, contains routines that write data elements to    */
/*  a FITS image or table, with unsigned short datatype.                            */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int ffpprui(fitsfile *fptr,  /* I - FITS file pointer                       */
            long  group,     /* I - group to write (1 = 1st group)          */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
   unsigned short *array,    /* I - array of values that are written        */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written).
*/
{
    long row;
    unsigned short nullvalue;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_write_compressed_pixels(fptr, TUSHORT, firstelem, nelem,
            0, array, &nullvalue, status);
        return(*status);
    }

    row=maxvalue(1,group);

    ffpclui(fptr, 2, row, firstelem, nelem, array, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffppnui(fitsfile *fptr,  /* I - FITS file pointer                       */
            long  group,     /* I - group to write(1 = 1st group)           */
            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
            LONGLONG  nelem,     /* I - number of values to write               */
   unsigned short *array,    /* I - array of values that are written        */
   unsigned short nulval,    /* I - undefined pixel value                   */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).  Any array values
  that are equal to the value of nulval will be replaced with the null
  pixel value that is appropriate for this column.
*/
{
    long row;
    unsigned short nullvalue;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        nullvalue = nulval;  /* set local variable */
        fits_write_compressed_pixels(fptr, TUSHORT, firstelem, nelem,
            1, array, &nullvalue, status);
        return(*status);
    }

    row=maxvalue(1,group);

    ffpcnui(fptr, 2, row, firstelem, nelem, array, nulval, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffp2dui(fitsfile *fptr,   /* I - FITS file pointer                     */
           long  group,      /* I - group to write(1 = 1st group)         */
           LONGLONG  ncols,      /* I - number of pixels in each row of array */
           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
  unsigned short *array,     /* I - array to be written                   */
           int  *status)     /* IO - error status                         */
/*
  Write an entire 2-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).
*/
{
    /* call the 3D writing routine, with the 3rd dimension = 1 */

    ffp3dui(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffp3dui(fitsfile *fptr,   /* I - FITS file pointer                     */
           long  group,      /* I - group to write(1 = 1st group)         */
           LONGLONG  ncols,      /* I - number of pixels in each row of array */
           LONGLONG  nrows,      /* I - number of rows in each plane of array */
           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
           LONGLONG  naxis3,     /* I - FITS image NAXIS3 value               */
  unsigned short *array,     /* I - array to be written                   */
           int  *status)     /* IO - error status                         */
/*
  Write an entire 3-D cube of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).
*/
{
    long tablerow, ii, jj;
    long fpixel[3]= {1,1,1}, lpixel[3];
    LONGLONG nfits, narray;
    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */
           
    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */
        lpixel[0] = (long) ncols;
        lpixel[1] = (long) nrows;
        lpixel[2] = (long) naxis3;
       
        fits_write_compressed_img(fptr, TUSHORT, fpixel, lpixel,
            0,  array, NULL, status);
    
        return(*status);
    }

    tablerow=maxvalue(1,group);

    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
    {
      /* all the image pixels are contiguous, so write all at once */
      ffpclui(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status);
      return(*status);
    }

    if (ncols < naxis1 || nrows < naxis2)
       return(*status = BAD_DIMEN);

    nfits = 1;   /* next pixel in FITS image to write to */
    narray = 0;  /* next pixel in input array to be written */

    /* loop over naxis3 planes in the data cube */
    for (jj = 0; jj < naxis3; jj++)
    {
      /* loop over the naxis2 rows in the FITS image, */
      /* writing naxis1 pixels to each row            */

      for (ii = 0; ii < naxis2; ii++)
      {
       if (ffpclui(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0)
         return(*status);

       nfits += naxis1;
       narray += ncols;
      }
      narray += (nrows - naxis2) * ncols;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpssui(fitsfile *fptr,   /* I - FITS file pointer                       */
           long  group,      /* I - group to write(1 = 1st group)           */
           long  naxis,      /* I - number of data axes in array            */
           long  *naxes,     /* I - size of each FITS axis                  */
           long  *fpixel,    /* I - 1st pixel in each axis to write (1=1st) */
           long  *lpixel,    /* I - last pixel in each axis to write        */
  unsigned short *array,     /* I - array to be written                     */
           int  *status)     /* IO - error status                           */
/*
  Write a subsection of pixels to the primary array or image.
  A subsection is defined to be any contiguous rectangular
  array of pixels within the n-dimensional FITS data file.
  Data conversion and scaling will be performed if necessary 
  (e.g, if the datatype of the FITS array is not the same as
  the array being written).
*/
{
    long tablerow;
    LONGLONG fpix[7], dimen[7], astart, pstart;
    LONGLONG off2, off3, off4, off5, off6, off7;
    LONGLONG st10, st20, st30, st40, st50, st60, st70;
    LONGLONG st1, st2, st3, st4, st5, st6, st7;
    long ii, i1, i2, i3, i4, i5, i6, i7, irange[7];

    if (*status > 0)
        return(*status);

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_write_compressed_img(fptr, TUSHORT, fpixel, lpixel,
            0,  array, NULL, status);
    
        return(*status);
    }

    if (naxis < 1 || naxis > 7)
      return(*status = BAD_DIMEN);

    tablerow=maxvalue(1,group);

     /* calculate the size and number of loops to perform in each dimension */
    for (ii = 0; ii < 7; ii++)
    {
      fpix[ii]=1;
      irange[ii]=1;
      dimen[ii]=1;
    }

    for (ii = 0; ii < naxis; ii++)
    {    
      fpix[ii]=fpixel[ii];
      irange[ii]=lpixel[ii]-fpixel[ii]+1;
      dimen[ii]=naxes[ii];
    }

    i1=irange[0];

    /* compute the pixel offset between each dimension */
    off2 =     dimen[0];
    off3 = off2 * dimen[1];
    off4 = off3 * dimen[2];
    off5 = off4 * dimen[3];
    off6 = off5 * dimen[4];
    off7 = off6 * dimen[5];

    st10 = fpix[0];
    st20 = (fpix[1] - 1) * off2;
    st30 = (fpix[2] - 1) * off3;
    st40 = (fpix[3] - 1) * off4;
    st50 = (fpix[4] - 1) * off5;
    st60 = (fpix[5] - 1) * off6;
    st70 = (fpix[6] - 1) * off7;

    /* store the initial offset in each dimension */
    st1 = st10;
    st2 = st20;
    st3 = st30;
    st4 = st40;
    st5 = st50;
    st6 = st60;
    st7 = st70;

    astart = 0;

    for (i7 = 0; i7 < irange[6]; i7++)
    {
     for (i6 = 0; i6 < irange[5]; i6++)
     {
      for (i5 = 0; i5 < irange[4]; i5++)
      {
       for (i4 = 0; i4 < irange[3]; i4++)
       {
        for (i3 = 0; i3 < irange[2]; i3++)
        {
         pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7;

         for (i2 = 0; i2 < irange[1]; i2++)
         {
           if (ffpclui(fptr, 2, tablerow, pstart, i1, &array[astart],
              status) > 0)
              return(*status);

           astart += i1;
           pstart += off2;
         }
         st2 = st20;
         st3 = st3+off3;    
        }
        st3 = st30;
        st4 = st4+off4;
       }
       st4 = st40;
       st5 = st5+off5;
      }
      st5 = st50;
      st6 = st6+off6;
     }
     st6 = st60;
     st7 = st7+off7;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpgpui( fitsfile *fptr,   /* I - FITS file pointer                      */
            long  group,      /* I - group to write(1 = 1st group)          */
            long  firstelem,  /* I - first vector element to write(1 = 1st) */
            long  nelem,      /* I - number of values to write              */
   unsigned short *array,     /* I - array of values that are written       */
            int  *status)     /* IO - error status                          */
/*
  Write an array of group parameters to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written).
*/
{
    long row;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffpclui(fptr, 1L, row, firstelem, nelem, array, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpclui( fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
   unsigned short *array,    /* I - array of values to write                */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to a column in the current FITS HDU.
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer to a virtual column in a 1 or more grouped FITS primary
  array.  FITSIO treats a primary array as a binary table with
  2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.

  The input array of values will be converted to the datatype of the column 
  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary.
*/
{
    int tcode, maxelem, hdutype;
    long twidth, incre;
    long ntodo;
    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull;
    double scale, zero;
    char tform[20], cform[20];
    char message[FLEN_ERRMSG];

    char snull[20];   /*  the FITS null value  */

    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
    void *buffer;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    buffer = cbuff;

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
        tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
        return(*status);

    if (tcode == TSTRING)   
         ffcfmt(tform, cform);     /* derive C format for writing strings */

    /*---------------------------------------------------------------------*/
    /*  Now write the pixels to the FITS column.                           */
    /*  First call the ffXXfYY routine to  (1) convert the datatype        */
    /*  if necessary, and (2) scale the values by the FITS TSCALn and      */
    /*  TZEROn linear scaling parameters into a temporary buffer.          */
    /*---------------------------------------------------------------------*/
    remain = nelem;           /* remaining number of values to write  */
    next = 0;                 /* next element in array to be written  */
    rownum = 0;               /* row number, relative to firstrow     */

    while (remain)
    {
        /* limit the number of pixels to process a one time to the number that
           will fit in the buffer space or to the number of pixels that remain
           in the current vector, which ever is smaller.
        */
        ntodo = (long) minvalue(remain, maxelem);      
        ntodo = (long) minvalue(ntodo, (repeat - elemnum));

        wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);

        ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */

        switch (tcode) 
        {
            case (TSHORT):

              ffu2fi2(&array[next], ntodo, scale, zero,
                      (short *) buffer, status);
              ffpi2b(fptr, ntodo, incre, (short *) buffer, status);
              break;

            case (TLONGLONG):

                ffu2fi8(&array[next], ntodo, scale, zero,
                        (LONGLONG *) buffer, status);
                ffpi8b(fptr, ntodo, incre, (long *) buffer, status);
                break;

            case (TBYTE):
 
                ffu2fi1(&array[next], ntodo, scale, zero,
                        (unsigned char *) buffer, status);
                ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status);
                break;

            case (TLONG):

                ffu2fi4(&array[next], ntodo, scale, zero,
                        (INT32BIT *) buffer, status);
                ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status);
                break;

            case (TFLOAT):

                ffu2fr4(&array[next], ntodo, scale, zero,
                        (float *) buffer, status);
                ffpr4b(fptr, ntodo, incre, (float *) buffer, status);
                break;

            case (TDOUBLE):
                ffu2fr8(&array[next], ntodo, scale, zero,
                        (double *) buffer, status);
                ffpr8b(fptr, ntodo, incre, (double *) buffer, status);
                break;

            case (TSTRING):  /* numerical column in an ASCII table */

                if (cform[1] != 's')  /*  "%s" format is a string */
                {
                  ffu2fstr(&array[next], ntodo, scale, zero, cform,
                          twidth, (char *) buffer, status);


                  if (incre == twidth)    /* contiguous bytes */
                     ffpbyt(fptr, ntodo * twidth, buffer, status);
                  else
                     ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
                            status);

                  break;
                }
                /* can't write to string column, so fall thru to default: */

            default:  /*  error trap  */
                snprintf(message,FLEN_ERRMSG, 
                    "Cannot write numbers to column %d which has format %s",
                      colnum,tform);
                ffpmsg(message);
                if (hdutype == ASCII_TBL)
                    return(*status = BAD_ATABLE_FORMAT);
                else
                    return(*status = BAD_BTABLE_FORMAT);

        } /* End of switch block */

        /*-------------------------*/
        /*  Check for fatal error  */
        /*-------------------------*/
        if (*status > 0)  /* test for error during previous write operation */
        {
         snprintf(message,FLEN_ERRMSG,
          "Error writing elements %.0f thru %.0f of input data array (ffpclui).",
             (double) (next+1), (double) (next+ntodo));
         ffpmsg(message);
         return(*status);
        }

        /*--------------------------------------------*/
        /*  increment the counters for the next loop  */
        /*--------------------------------------------*/
        remain -= ntodo;
        if (remain)
        {
            next += ntodo;
            elemnum += ntodo;
            if (elemnum == repeat)  /* completed a row; start on next row */
            {
                elemnum = 0;
                rownum++;
            }
        }
    }  /*  End of main while Loop  */


    /*--------------------------------*/
    /*  check for numerical overflow  */
    /*--------------------------------*/
    if (*status == OVERFLOW_ERR)
    {
       ffpmsg(
       "Numerical overflow during type conversion while writing FITS data.");
       *status = NUM_OVERFLOW;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpcnui(fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
   unsigned short *array,    /* I - array of values to write                */
   unsigned short  nulvalue, /* I - value used to flag undefined pixels     */
            int  *status)    /* IO - error status                           */
/*
  Write an array of elements to the specified column of a table.  Any input
  pixels equal to the value of nulvalue will be replaced by the appropriate
  null value in the output FITS file. 

  The input array of values will be converted to the datatype of the column 
  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary
*/
{
    tcolumn *colptr;
    LONGLONG  ngood = 0, nbad = 0, ii;
    LONGLONG repeat, first, fstelm, fstrow;
    int tcode, overflow = 0;

    if (*status > 0)
        return(*status);

    /* reset position to the correct HDU if necessary */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
    {
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
    }
    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
    {
        if ( ffrdef(fptr, status) > 0)               /* rescan header */
            return(*status);
    }

    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
    colptr += (colnum - 1);     /* offset to correct column structure */

    tcode  = colptr->tdatatype;

    if (tcode > 0)
       repeat = colptr->trepeat;  /* repeat count for this column */
    else
       repeat = firstelem -1 + nelem;  /* variable length arrays */

    /* if variable length array, first write the whole input vector, 
       then go back and fill in the nulls */
    if (tcode < 0) {
      if (ffpclui(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) {
        if (*status == NUM_OVERFLOW) 
	{
	  /* ignore overflows, which are possibly the null pixel values */
	  /*  overflow = 1;   */
	  *status = 0;
	} else { 
          return(*status);
	}
      }
    }

    /* absolute element number in the column */
    first = (firstrow - 1) * repeat + firstelem;

    for (ii = 0; ii < nelem; ii++)
    {
      if (array[ii] != nulvalue)  /* is this a good pixel? */
      {
         if (nbad)  /* write previous string of bad pixels */
         {
            fstelm = ii - nbad + first;  /* absolute element number */
            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

            if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
                return(*status);

            nbad=0;
         }

         ngood = ngood +1;  /* the consecutive number of good pixels */
      }
      else
      {
         if (ngood)  /* write previous string of good pixels */
         {
            fstelm = ii - ngood + first;  /* absolute element number */
            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

            if (tcode > 0) {  /* variable length arrays have already been written */
              if (ffpclui(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
                status) > 0) {
		if (*status == NUM_OVERFLOW) 
		{
		  overflow = 1;
		  *status = 0;
		} else { 
                  return(*status);
		}
	      }
	    }
            ngood=0;
         }

         nbad = nbad +1;  /* the consecutive number of bad pixels */
      }
    }

    /* finished loop;  now just write the last set of pixels */

    if (ngood)  /* write last string of good pixels */
    {
      fstelm = ii - ngood + first;  /* absolute element number */
      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

      if (tcode > 0) {  /* variable length arrays have already been written */
        ffpclui(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
      }
    }
    else if (nbad) /* write last string of bad pixels */
    {
      fstelm = ii - nbad + first;  /* absolute element number */
      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

      ffpclu(fptr, colnum, fstrow, fstelm, nbad, status);
    }

    if (*status <= 0) {
      if (overflow) {
        *status = NUM_OVERFLOW;
      }
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffu2fi1(unsigned short *input, /* I - array of values to be converted  */
            long ntodo,            /* I - number of elements in the array  */
            double scale,          /* I - FITS TSCALn or BSCALE value      */
            double zero,           /* I - FITS TZEROn or BZERO  value      */
            unsigned char *output, /* O - output array of converted values */
            int *status)           /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
            if (input[ii] > UCHAR_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = UCHAR_MAX;
            }
            else
                output[ii] = (unsigned char) input[ii];
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = ((double) input[ii] - zero) / scale;

            if (dvalue < DUCHAR_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = 0;
            }
            else if (dvalue > DUCHAR_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = UCHAR_MAX;
            }
            else
                output[ii] = (unsigned char) (dvalue + .5);
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffu2fi2(unsigned short *input, /* I - array of values to be converted */
            long ntodo,         /* I - number of elements in the array  */
            double scale,       /* I - FITS TSCALn or BSCALE value      */
            double zero,        /* I - FITS TZEROn or BZERO  value      */
            short *output,      /* O - output array of converted values */
            int *status)        /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 32768.)
    {
        /* Instead of subtracting 32768, it is more efficient */
        /* to just flip the sign bit with the XOR operator */

        for (ii = 0; ii < ntodo; ii++)
             output[ii] =  ( *(short *) &input[ii] ) ^ 0x8000;
    }
    else if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
            if (input[ii] > SHRT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MAX;
            }
            else
                output[ii] = input[ii];
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = ((double) input[ii] - zero) / scale;

            if (dvalue < DSHRT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MIN;
            }
            else if (dvalue > DSHRT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (short) (dvalue + .5);
                else
                    output[ii] = (short) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffu2fi4(unsigned short *input, /* I - array of values to be converted */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            INT32BIT *output,      /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
            output[ii] = (INT32BIT) input[ii];   /* copy input to output */
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = ((double) input[ii] - zero) / scale;

            if (dvalue < DINT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MIN;
            }
            else if (dvalue > DINT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (INT32BIT) (dvalue + .5);
                else
                    output[ii] = (INT32BIT) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffu2fi8(unsigned short *input,  /* I - array of values to be converted  */
            long ntodo,             /* I - number of elements in the array  */
            double scale,           /* I - FITS TSCALn or BSCALE value      */
            double zero,            /* I - FITS TZEROn or BZERO  value      */
            LONGLONG *output,       /* O - output array of converted values */
            int *status)            /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DLONGLONG_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = LONGLONG_MIN;
            }
            else if (dvalue > DLONGLONG_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = LONGLONG_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (LONGLONG) (dvalue + .5);
                else
                    output[ii] = (LONGLONG) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffu2fr4(unsigned short *input, /* I - array of values to be converted */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            float *output,     /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = (float) input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
            output[ii] = (float) (((double) input[ii] - zero) / scale);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffu2fr8(unsigned short *input, /* I - array of values to be converted */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            double *output,    /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = (double) input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
            output[ii] = ((double) input[ii] - zero) / scale;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffu2fstr(unsigned short *input, /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            char *cform,       /* I - format for output string values  */
            long twidth,       /* I - width of each field, in chars    */
            char *output,      /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do scaling if required.
*/
{
    long ii;
    double dvalue;
    char *cptr;
    
    cptr = output;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
           sprintf(output, cform, (double) input[ii]);
           output += twidth;

           if (*output)  /* if this char != \0, then overflow occurred */
              *status = OVERFLOW_ERR;
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
          dvalue = ((double) input[ii] - zero) / scale;
          sprintf(output, cform, dvalue);
          output += twidth;

          if (*output)  /* if this char != \0, then overflow occurred */
            *status = OVERFLOW_ERR;
        }
    }

    /* replace any commas with periods (e.g., in French locale) */
    while ((cptr = strchr(cptr, ','))) *cptr = '.';
    
    return(*status);
}
cfitsio/putcoluj.c0000644000225700000360000010321713246025103014015 0ustar  cagordonlhea/*  This file, putcoluj.c, contains routines that write data elements to   */
/*  a FITS image or table, with unsigned long datatype.                             */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int ffppruj( fitsfile *fptr,  /* I - FITS file pointer                       */
            long  group,     /* I - group to write(1 = 1st group)           */
            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
            LONGLONG  nelem,     /* I - number of values to write               */
   unsigned long  *array,    /* I - array of values that are written        */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written).
*/
{
    long row;
    unsigned long nullvalue;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_write_compressed_pixels(fptr, TULONG, firstelem, nelem,
            0, array, &nullvalue, status);
        return(*status);
    }

    row=maxvalue(1,group);

    ffpcluj(fptr, 2, row, firstelem, nelem, array, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffppnuj( fitsfile *fptr,  /* I - FITS file pointer                       */
            long  group,     /* I - group to write(1 = 1st group)           */
            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
            LONGLONG  nelem,     /* I - number of values to write               */
   unsigned long  *array,    /* I - array of values that are written        */
   unsigned long  nulval,    /* I - undefined pixel value                   */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).  Any array values
  that are equal to the value of nulval will be replaced with the null
  pixel value that is appropriate for this column.
*/
{
    long row;
    unsigned long nullvalue;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        nullvalue = nulval;  /* set local variable */
        fits_write_compressed_pixels(fptr, TULONG, firstelem, nelem,
            1, array, &nullvalue, status);
        return(*status);
    }

    row=maxvalue(1,group);

    ffpcnuj(fptr, 2, row, firstelem, nelem, array, nulval, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffp2duj(fitsfile *fptr,   /* I - FITS file pointer                    */
           long  group,      /* I - group to write(1 = 1st group)         */
           LONGLONG  ncols,      /* I - number of pixels in each row of array */
           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
  unsigned long  *array,     /* I - array to be written                   */
           int  *status)     /* IO - error status                         */
/*
  Write an entire 2-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).
*/
{
    /* call the 3D writing routine, with the 3rd dimension = 1 */

    ffp3duj(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffp3duj(fitsfile *fptr,   /* I - FITS file pointer                    */
           long  group,      /* I - group to write(1 = 1st group)         */
           LONGLONG  ncols,      /* I - number of pixels in each row of array */
           LONGLONG  nrows,      /* I - number of rows in each plane of array */
           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
           LONGLONG  naxis3,     /* I - FITS image NAXIS3 value               */
  unsigned long  *array,     /* I - array to be written                   */
           int  *status)     /* IO - error status                         */
/*
  Write an entire 3-D cube of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).
*/
{
    long tablerow, ii, jj;
    long fpixel[3]= {1,1,1}, lpixel[3];
    LONGLONG nfits, narray;
    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */
           
    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */
        lpixel[0] = (long) ncols;
        lpixel[1] = (long) nrows;
        lpixel[2] = (long) naxis3;
       
        fits_write_compressed_img(fptr, TULONG, fpixel, lpixel,
            0,  array, NULL, status);
    
        return(*status);
    }

    tablerow=maxvalue(1,group);

    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
    {
      /* all the image pixels are contiguous, so write all at once */
      ffpcluj(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status);
      return(*status);
    }

    if (ncols < naxis1 || nrows < naxis2)
       return(*status = BAD_DIMEN);

    nfits = 1;   /* next pixel in FITS image to write to */
    narray = 0;  /* next pixel in input array to be written */

    /* loop over naxis3 planes in the data cube */
    for (jj = 0; jj < naxis3; jj++)
    {
      /* loop over the naxis2 rows in the FITS image, */
      /* writing naxis1 pixels to each row            */

      for (ii = 0; ii < naxis2; ii++)
      {
       if (ffpcluj(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0)
         return(*status);

       nfits += naxis1;
       narray += ncols;
      }
      narray += (nrows - naxis2) * ncols;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpssuj(fitsfile *fptr,   /* I - FITS file pointer                       */
           long  group,      /* I - group to write(1 = 1st group)           */
           long  naxis,      /* I - number of data axes in array            */
           long  *naxes,     /* I - size of each FITS axis                  */
           long  *fpixel,    /* I - 1st pixel in each axis to write (1=1st) */
           long  *lpixel,    /* I - last pixel in each axis to write        */
  unsigned long *array,      /* I - array to be written                     */
           int  *status)     /* IO - error status                           */
/*
  Write a subsection of pixels to the primary array or image.
  A subsection is defined to be any contiguous rectangular
  array of pixels within the n-dimensional FITS data file.
  Data conversion and scaling will be performed if necessary 
  (e.g, if the datatype of the FITS array is not the same as
  the array being written).
*/
{
    long tablerow;
    LONGLONG fpix[7], dimen[7], astart, pstart;
    LONGLONG off2, off3, off4, off5, off6, off7;
    LONGLONG st10, st20, st30, st40, st50, st60, st70;
    LONGLONG st1, st2, st3, st4, st5, st6, st7;
    long ii, i1, i2, i3, i4, i5, i6, i7, irange[7];

    if (*status > 0)
        return(*status);

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_write_compressed_img(fptr, TULONG, fpixel, lpixel,
            0,  array, NULL, status);
    
        return(*status);
    }

    if (naxis < 1 || naxis > 7)
      return(*status = BAD_DIMEN);

    tablerow=maxvalue(1,group);

     /* calculate the size and number of loops to perform in each dimension */
    for (ii = 0; ii < 7; ii++)
    {
      fpix[ii]=1;
      irange[ii]=1;
      dimen[ii]=1;
    }

    for (ii = 0; ii < naxis; ii++)
    {    
      fpix[ii]=fpixel[ii];
      irange[ii]=lpixel[ii]-fpixel[ii]+1;
      dimen[ii]=naxes[ii];
    }

    i1=irange[0];

    /* compute the pixel offset between each dimension */
    off2 =     dimen[0];
    off3 = off2 * dimen[1];
    off4 = off3 * dimen[2];
    off5 = off4 * dimen[3];
    off6 = off5 * dimen[4];
    off7 = off6 * dimen[5];

    st10 = fpix[0];
    st20 = (fpix[1] - 1) * off2;
    st30 = (fpix[2] - 1) * off3;
    st40 = (fpix[3] - 1) * off4;
    st50 = (fpix[4] - 1) * off5;
    st60 = (fpix[5] - 1) * off6;
    st70 = (fpix[6] - 1) * off7;

    /* store the initial offset in each dimension */
    st1 = st10;
    st2 = st20;
    st3 = st30;
    st4 = st40;
    st5 = st50;
    st6 = st60;
    st7 = st70;

    astart = 0;

    for (i7 = 0; i7 < irange[6]; i7++)
    {
     for (i6 = 0; i6 < irange[5]; i6++)
     {
      for (i5 = 0; i5 < irange[4]; i5++)
      {
       for (i4 = 0; i4 < irange[3]; i4++)
       {
        for (i3 = 0; i3 < irange[2]; i3++)
        {
         pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7;

         for (i2 = 0; i2 < irange[1]; i2++)
         {
           if (ffpcluj(fptr, 2, tablerow, pstart, i1, &array[astart],
              status) > 0)
              return(*status);

           astart += i1;
           pstart += off2;
         }
         st2 = st20;
         st3 = st3+off3;    
        }
        st3 = st30;
        st4 = st4+off4;
       }
       st4 = st40;
       st5 = st5+off5;
      }
      st5 = st50;
      st6 = st6+off6;
     }
     st6 = st60;
     st7 = st7+off7;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpgpuj( fitsfile *fptr,   /* I - FITS file pointer                      */
            long  group,      /* I - group to write(1 = 1st group)          */
            long  firstelem,  /* I - first vector element to write(1 = 1st) */
            long  nelem,      /* I - number of values to write              */
   unsigned long  *array,     /* I - array of values that are written       */
            int  *status)     /* IO - error status                          */
/*
  Write an array of group parameters to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written).
*/
{
    long row;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffpcluj(fptr, 1L, row, firstelem, nelem, array, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpcluj( fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
   unsigned long  *array,    /* I - array of values to write                */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to a column in the current FITS HDU.
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer to a virtual column in a 1 or more grouped FITS primary
  array.  FITSIO treats a primary array as a binary table
  with 2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.

  The input array of values will be converted to the datatype of the column 
  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary.
*/
{
    int tcode, maxelem, hdutype;
    long twidth, incre;
    long ntodo;
    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull;
    double scale, zero;
    char tform[20], cform[20];
    char message[FLEN_ERRMSG];

    char snull[20];   /*  the FITS null value  */

    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
    void *buffer;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    buffer = cbuff;

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
        tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
        return(*status);

    if (tcode == TSTRING)   
         ffcfmt(tform, cform);     /* derive C format for writing strings */

    /*---------------------------------------------------------------------*/
    /*  Now write the pixels to the FITS column.                           */
    /*  First call the ffXXfYY routine to  (1) convert the datatype        */
    /*  if necessary, and (2) scale the values by the FITS TSCALn and      */
    /*  TZEROn linear scaling parameters into a temporary buffer.          */
    /*---------------------------------------------------------------------*/
    remain = nelem;           /* remaining number of values to write  */
    next = 0;                 /* next element in array to be written  */
    rownum = 0;               /* row number, relative to firstrow     */

    while (remain)
    {
        /* limit the number of pixels to process a one time to the number that
           will fit in the buffer space or to the number of pixels that remain
           in the current vector, which ever is smaller.
        */
        ntodo = (long) minvalue(remain, maxelem);      
        ntodo = (long) minvalue(ntodo, (repeat - elemnum));

        wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);

        ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */

        switch (tcode) 
        {
            case (TLONG):

                ffu4fi4(&array[next], ntodo, scale, zero,
                      (INT32BIT *) buffer, status);
                ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status);
                break;

            case (TLONGLONG):

                ffu4fi8(&array[next], ntodo, scale, zero,
                        (LONGLONG *) buffer, status);
                ffpi8b(fptr, ntodo, incre, (long *) buffer, status);
                break;

            case (TBYTE):
 
                ffu4fi1(&array[next], ntodo, scale, zero,
                        (unsigned char *) buffer, status);
                ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status);
                break;

            case (TSHORT):

                ffu4fi2(&array[next], ntodo, scale, zero,
                        (short *) buffer, status);
                ffpi2b(fptr, ntodo, incre, (short *) buffer, status);
                break;

            case (TFLOAT):

                ffu4fr4(&array[next], ntodo, scale, zero,
                        (float *) buffer, status);
                ffpr4b(fptr, ntodo, incre, (float *) buffer, status);
                break;

            case (TDOUBLE):
                ffu4fr8(&array[next], ntodo, scale, zero,
                       (double *) buffer, status);
                ffpr8b(fptr, ntodo, incre, (double *) buffer, status);
                break;

            case (TSTRING):  /* numerical column in an ASCII table */

                if (cform[1] != 's')  /*  "%s" format is a string */
                {
                  ffu4fstr(&array[next], ntodo, scale, zero, cform,
                          twidth, (char *) buffer, status);

                  if (incre == twidth)    /* contiguous bytes */
                     ffpbyt(fptr, ntodo * twidth, buffer, status);
                  else
                     ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
                            status);

                  break;
                }
                /* can't write to string column, so fall thru to default: */

            default:  /*  error trap  */
                snprintf(message,FLEN_ERRMSG, 
                     "Cannot write numbers to column %d which has format %s",
                      colnum,tform);
                ffpmsg(message);
                if (hdutype == ASCII_TBL)
                    return(*status = BAD_ATABLE_FORMAT);
                else
                    return(*status = BAD_BTABLE_FORMAT);

        } /* End of switch block */

        /*-------------------------*/
        /*  Check for fatal error  */
        /*-------------------------*/
        if (*status > 0)  /* test for error during previous write operation */
        {
          snprintf(message,FLEN_ERRMSG,
          "Error writing elements %.0f thru %.0f of input data array (ffpcluj).",
              (double) (next+1), (double) (next+ntodo));
          ffpmsg(message);
          return(*status);
        }

        /*--------------------------------------------*/
        /*  increment the counters for the next loop  */
        /*--------------------------------------------*/
        remain -= ntodo;
        if (remain)
        {
            next += ntodo;
            elemnum += ntodo;
            if (elemnum == repeat)  /* completed a row; start on next row */
            {
                elemnum = 0;
                rownum++;
            }
        }
    }  /*  End of main while Loop  */


    /*--------------------------------*/
    /*  check for numerical overflow  */
    /*--------------------------------*/
    if (*status == OVERFLOW_ERR)
    {
        ffpmsg(
        "Numerical overflow during type conversion while writing FITS data.");
        *status = NUM_OVERFLOW;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpcnuj( fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
   unsigned long  *array,    /* I - array of values to write                */
   unsigned long   nulvalue, /* I - value used to flag undefined pixels     */
            int  *status)    /* IO - error status                           */
/*
  Write an array of elements to the specified column of a table.  Any input
  pixels equal to the value of nulvalue will be replaced by the appropriate
  null value in the output FITS file. 

  The input array of values will be converted to the datatype of the column 
  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary
*/
{
    tcolumn *colptr;
    LONGLONG  ngood = 0, nbad = 0, ii;
    LONGLONG repeat, first, fstelm, fstrow;
    int tcode, overflow = 0;

    if (*status > 0)
        return(*status);

    /* reset position to the correct HDU if necessary */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
    {
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
    }
    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
    {
        if ( ffrdef(fptr, status) > 0)               /* rescan header */
            return(*status);
    }

    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
    colptr += (colnum - 1);     /* offset to correct column structure */

    tcode  = colptr->tdatatype;

    if (tcode > 0)
       repeat = colptr->trepeat;  /* repeat count for this column */
    else
       repeat = firstelem -1 + nelem;  /* variable length arrays */

    /* if variable length array, first write the whole input vector, 
       then go back and fill in the nulls */
    if (tcode < 0) {
      if (ffpcluj(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) {
        if (*status == NUM_OVERFLOW) 
	{
	  /* ignore overflows, which are possibly the null pixel values */
	  /*  overflow = 1;   */
	  *status = 0;
	} else { 
          return(*status);
	}
      }
    }

    /* absolute element number in the column */
    first = (firstrow - 1) * repeat + firstelem;

    for (ii = 0; ii < nelem; ii++)
    {
      if (array[ii] != nulvalue)  /* is this a good pixel? */
      {
         if (nbad)  /* write previous string of bad pixels */
         {
            fstelm = ii - nbad + first;  /* absolute element number */
            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

            if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
                return(*status);

            nbad=0;
         }

         ngood = ngood +1;  /* the consecutive number of good pixels */
      }
      else
      {
         if (ngood)  /* write previous string of good pixels */
         {
            fstelm = ii - ngood + first;  /* absolute element number */
            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

            if (tcode > 0) {  /* variable length arrays have already been written */
              if (ffpcluj(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
                status) > 0) {
		if (*status == NUM_OVERFLOW) 
		{
		  overflow = 1;
		  *status = 0;
		} else { 
                  return(*status);
		}
	      }
	    }
            ngood=0;
         }

         nbad = nbad +1;  /* the consecutive number of bad pixels */
      }
    }

    /* finished loop;  now just write the last set of pixels */

    if (ngood)  /* write last string of good pixels */
    {
      fstelm = ii - ngood + first;  /* absolute element number */
      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

      if (tcode > 0) {  /* variable length arrays have already been written */
        ffpcluj(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
      }
    }
    else if (nbad) /* write last string of bad pixels */
    {
      fstelm = ii - nbad + first;  /* absolute element number */
      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

      ffpclu(fptr, colnum, fstrow, fstelm, nbad, status);
    }

    if (*status <= 0) {
      if (overflow) {
        *status = NUM_OVERFLOW;
      }
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffu4fi1(unsigned long *input,  /* I - array of values to be converted  */
            long ntodo,            /* I - number of elements in the array  */
            double scale,          /* I - FITS TSCALn or BSCALE value      */
            double zero,           /* I - FITS TZEROn or BZERO  value      */
            unsigned char *output, /* O - output array of converted values */
            int *status)           /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
            if (input[ii] > UCHAR_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = UCHAR_MAX;
            }
            else
                output[ii] = (unsigned char) input[ii];
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DUCHAR_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = 0;
            }
            else if (dvalue > DUCHAR_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = UCHAR_MAX;
            }
            else
                output[ii] = (unsigned char) (dvalue + .5);
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffu4fi2(unsigned long *input, /* I - array of values to be converted */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            short *output,     /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
            if (input[ii] > SHRT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MAX;
            }
            else
                output[ii] = (short) input[ii];
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DSHRT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MIN;
            }
            else if (dvalue > DSHRT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (short) (dvalue + .5);
                else
                    output[ii] = (short) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffu4fi4(unsigned long *input, /* I - array of values to be converted */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            INT32BIT *output,  /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 2147483648. && sizeof(long) == 4)
    {       
        /* Instead of subtracting 2147483648, it is more efficient */
        /* to just flip the sign bit with the XOR operator */

        for (ii = 0; ii < ntodo; ii++)
             output[ii] =  ( *(long *) &input[ii] ) ^ 0x80000000;
    }
    else if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
            if (input[ii] > INT32_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MAX;
            }
            else
                output[ii] = input[ii];
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DINT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MIN;
            }
            else if (dvalue > DINT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (INT32BIT) (dvalue + .5);
                else
                    output[ii] = (INT32BIT) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffu4fi8(unsigned long *input,  /* I - array of values to be converted  */
            long ntodo,             /* I - number of elements in the array  */
            double scale,           /* I - FITS TSCALn or BSCALE value      */
            double zero,            /* I - FITS TZEROn or BZERO  value      */
            LONGLONG *output,       /* O - output array of converted values */
            int *status)            /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DLONGLONG_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = LONGLONG_MIN;
            }
            else if (dvalue > DLONGLONG_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = LONGLONG_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (LONGLONG) (dvalue + .5);
                else
                    output[ii] = (LONGLONG) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffu4fr4(unsigned long *input, /* I - array of values to be converted */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            float *output,     /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = (float) input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
            output[ii] = (float) ((input[ii] - zero) / scale);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffu4fr8(unsigned long *input, /* I - array of values to be converted */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            double *output,    /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = (double) input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
            output[ii] = (input[ii] - zero) / scale;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffu4fstr(unsigned long *input, /* I - array of values to be converted */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            char *cform,       /* I - format for output string values  */
            long twidth,       /* I - width of each field, in chars    */
            char *output,      /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do scaling if required.
*/
{
    long ii;
    double dvalue;
    char *cptr;
    
    cptr = output;


    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
           sprintf(output, cform, (double) input[ii]);
           output += twidth;

           if (*output)  /* if this char != \0, then overflow occurred */
              *status = OVERFLOW_ERR;
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
          dvalue = (input[ii] - zero) / scale;
          sprintf(output, cform, dvalue);
          output += twidth;

          if (*output)  /* if this char != \0, then overflow occurred */
            *status = OVERFLOW_ERR;
        }
    }

    /* replace any commas with periods (e.g., in French locale) */
    while ((cptr = strchr(cptr, ','))) *cptr = '.';
    
    return(*status);
}
cfitsio/putcoluk.c0000644000225700000360000010445513246025103014023 0ustar  cagordonlhea/*  This file, putcolk.c, contains routines that write data elements to    */
/*  a FITS image or table, with 'unsigned int' datatype.                   */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int ffppruk(fitsfile *fptr,  /* I - FITS file pointer                       */
            long  group,     /* I - group to write(1 = 1st group)           */
            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
            LONGLONG  nelem,     /* I - number of values to write               */
   unsigned int   *array,    /* I - array of values that are written        */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written).
*/
{
    long row;
    unsigned int nullvalue;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_write_compressed_pixels(fptr, TUINT, firstelem, nelem,
            0, array, &nullvalue, status);
        return(*status);
    }

    row=maxvalue(1,group);

    ffpcluk(fptr, 2, row, firstelem, nelem, array, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffppnuk(fitsfile *fptr,  /* I - FITS file pointer                       */
            long  group,     /* I - group to write(1 = 1st group)           */
            LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
            LONGLONG  nelem,     /* I - number of values to write               */
   unsigned int   *array,    /* I - array of values that are written        */
   unsigned int   nulval,    /* I - undefined pixel value                   */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).  Any array values
  that are equal to the value of nulval will be replaced with the null
  pixel value that is appropriate for this column.
*/
{
    long row;
    unsigned int nullvalue;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        nullvalue = nulval;  /* set local variable */
        fits_write_compressed_pixels(fptr, TUINT, firstelem, nelem,
            1, array, &nullvalue, status);
        return(*status);
    }

    row=maxvalue(1,group);

    ffpcnuk(fptr, 2, row, firstelem, nelem, array, nulval, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffp2duk(fitsfile *fptr,  /* I - FITS file pointer                     */
           long  group,      /* I - group to write(1 = 1st group)         */
           LONGLONG  ncols,      /* I - number of pixels in each row of array */
           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
  unsigned int   *array,     /* I - array to be written                   */
           int  *status)     /* IO - error status                         */
/*
  Write an entire 2-D array of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).
*/
{
    /* call the 3D writing routine, with the 3rd dimension = 1 */

    ffp3duk(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffp3duk(fitsfile *fptr,  /* I - FITS file pointer                     */
           long  group,      /* I - group to write(1 = 1st group)         */
           LONGLONG  ncols,      /* I - number of pixels in each row of array */
           LONGLONG  nrows,      /* I - number of rows in each plane of array */
           LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
           LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
           LONGLONG  naxis3,     /* I - FITS image NAXIS3 value               */
  unsigned int   *array,     /* I - array to be written                   */
           int  *status)     /* IO - error status                         */
/*
  Write an entire 3-D cube of values to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of the
  FITS array is not the same as the array being written).
*/
{
    long tablerow, ii, jj;
    long fpixel[3]= {1,1,1}, lpixel[3];
    LONGLONG nfits, narray;
    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */
           
    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */
        lpixel[0] = (long) ncols;
        lpixel[1] = (long) nrows;
        lpixel[2] = (long) naxis3;
       
        fits_write_compressed_img(fptr, TUINT, fpixel, lpixel,
            0,  array, NULL, status);
    
        return(*status);
    }

    tablerow=maxvalue(1,group);

    if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
    {
      /* all the image pixels are contiguous, so write all at once */
      ffpcluk(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status);
      return(*status);
    }

    if (ncols < naxis1 || nrows < naxis2)
       return(*status = BAD_DIMEN);

    nfits = 1;   /* next pixel in FITS image to write to */
    narray = 0;  /* next pixel in input array to be written */

    /* loop over naxis3 planes in the data cube */
    for (jj = 0; jj < naxis3; jj++)
    {
      /* loop over the naxis2 rows in the FITS image, */
      /* writing naxis1 pixels to each row            */

      for (ii = 0; ii < naxis2; ii++)
      {
       if (ffpcluk(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0)
         return(*status);

       nfits += naxis1;
       narray += ncols;
      }
      narray += (nrows - naxis2) * ncols;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpssuk(fitsfile *fptr,  /* I - FITS file pointer                       */
           long  group,      /* I - group to write(1 = 1st group)           */
           long  naxis,      /* I - number of data axes in array            */
           long  *naxes,     /* I - size of each FITS axis                  */
           long  *fpixel,    /* I - 1st pixel in each axis to write (1=1st) */
           long  *lpixel,    /* I - last pixel in each axis to write        */
  unsigned int  *array,      /* I - array to be written                     */
           int  *status)     /* IO - error status                           */
/*
  Write a subsection of pixels to the primary array or image.
  A subsection is defined to be any contiguous rectangular
  array of pixels within the n-dimensional FITS data file.
  Data conversion and scaling will be performed if necessary 
  (e.g, if the datatype of the FITS array is not the same as
  the array being written).
*/
{
    long tablerow;
    LONGLONG fpix[7], dimen[7], astart, pstart;
    LONGLONG off2, off3, off4, off5, off6, off7;
    LONGLONG st10, st20, st30, st40, st50, st60, st70;
    LONGLONG st1, st2, st3, st4, st5, st6, st7;
    long ii, i1, i2, i3, i4, i5, i6, i7, irange[7];

    if (*status > 0)
        return(*status);

    if (fits_is_compressed_image(fptr, status))
    {
        /* this is a compressed image in a binary table */

        fits_write_compressed_img(fptr, TUINT, fpixel, lpixel,
            0,  array, NULL, status);
    
        return(*status);
    }

    if (naxis < 1 || naxis > 7)
      return(*status = BAD_DIMEN);

    tablerow=maxvalue(1,group);

     /* calculate the size and number of loops to perform in each dimension */
    for (ii = 0; ii < 7; ii++)
    {
      fpix[ii]=1;
      irange[ii]=1;
      dimen[ii]=1;
    }

    for (ii = 0; ii < naxis; ii++)
    {    
      fpix[ii]=fpixel[ii];
      irange[ii]=lpixel[ii]-fpixel[ii]+1;
      dimen[ii]=naxes[ii];
    }

    i1=irange[0];

    /* compute the pixel offset between each dimension */
    off2 =     dimen[0];
    off3 = off2 * dimen[1];
    off4 = off3 * dimen[2];
    off5 = off4 * dimen[3];
    off6 = off5 * dimen[4];
    off7 = off6 * dimen[5];

    st10 = fpix[0];
    st20 = (fpix[1] - 1) * off2;
    st30 = (fpix[2] - 1) * off3;
    st40 = (fpix[3] - 1) * off4;
    st50 = (fpix[4] - 1) * off5;
    st60 = (fpix[5] - 1) * off6;
    st70 = (fpix[6] - 1) * off7;

    /* store the initial offset in each dimension */
    st1 = st10;
    st2 = st20;
    st3 = st30;
    st4 = st40;
    st5 = st50;
    st6 = st60;
    st7 = st70;

    astart = 0;

    for (i7 = 0; i7 < irange[6]; i7++)
    {
     for (i6 = 0; i6 < irange[5]; i6++)
     {
      for (i5 = 0; i5 < irange[4]; i5++)
      {
       for (i4 = 0; i4 < irange[3]; i4++)
       {
        for (i3 = 0; i3 < irange[2]; i3++)
        {
         pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7;

         for (i2 = 0; i2 < irange[1]; i2++)
         {
           if (ffpcluk(fptr, 2, tablerow, pstart, i1, &array[astart],
              status) > 0)
              return(*status);

           astart += i1;
           pstart += off2;
         }
         st2 = st20;
         st3 = st3+off3;    
        }
        st3 = st30;
        st4 = st4+off4;
       }
       st4 = st40;
       st5 = st5+off5;
      }
      st5 = st50;
      st6 = st6+off6;
     }
     st6 = st60;
     st7 = st7+off7;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpgpuk(fitsfile *fptr,   /* I - FITS file pointer                      */
            long  group,      /* I - group to write(1 = 1st group)          */
            long  firstelem,  /* I - first vector element to write(1 = 1st) */
            long  nelem,      /* I - number of values to write              */
   unsigned int   *array,     /* I - array of values that are written       */
            int  *status)     /* IO - error status                          */
/*
  Write an array of group parameters to the primary array. Data conversion
  and scaling will be performed if necessary (e.g, if the datatype of
  the FITS array is not the same as the array being written).
*/
{
    long row;

    /*
      the primary array is represented as a binary table:
      each group of the primary array is a row in the table,
      where the first column contains the group parameters
      and the second column contains the image itself.
    */

    row=maxvalue(1,group);

    ffpcluk(fptr, 1L, row, firstelem, nelem, array, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpcluk(fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
   unsigned int   *array,    /* I - array of values to write                */
            int  *status)    /* IO - error status                           */
/*
  Write an array of values to a column in the current FITS HDU.
  The column number may refer to a real column in an ASCII or binary table, 
  or it may refer to a virtual column in a 1 or more grouped FITS primary
  array.  FITSIO treats a primary array as a binary table
  with 2 vector columns: the first column contains the group parameters (often
  with length = 0) and the second column contains the array of image pixels.
  Each row of the table represents a group in the case of multigroup FITS
  images.

  The input array of values will be converted to the datatype of the column 
  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary.
*/
{
    int tcode, maxelem, hdutype;
    long twidth, incre;
    long ntodo;
    LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull;
    double scale, zero;
    char tform[20], cform[20];
    char message[FLEN_ERRMSG];

    char snull[20];   /*  the FITS null value  */

    double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
    void *buffer;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /* call the 'short' or 'long' version of this routine, if possible */
    if (sizeof(int) == sizeof(short))
        ffpclui(fptr, colnum, firstrow, firstelem, nelem, 
              (unsigned short *) array, status);
    else if (sizeof(int) == sizeof(long))
        ffpcluj(fptr, colnum, firstrow, firstelem, nelem, 
              (unsigned long *) array, status);
    else
    {
    /*
      This is a special case: sizeof(int) is not equal to sizeof(short) or
      sizeof(long).  This occurs on Alpha OSF systems where short = 2 bytes,
      int = 4 bytes, and long = 8 bytes.
    */

    buffer = cbuff;

    /*---------------------------------------------------*/
    /*  Check input and get parameters about the column: */
    /*---------------------------------------------------*/
    if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
        tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
        &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
        return(*status);

    if (tcode == TSTRING)   
         ffcfmt(tform, cform);     /* derive C format for writing strings */

    /*---------------------------------------------------------------------*/
    /*  Now write the pixels to the FITS column.                           */
    /*  First call the ffXXfYY routine to  (1) convert the datatype        */
    /*  if necessary, and (2) scale the values by the FITS TSCALn and      */
    /*  TZEROn linear scaling parameters into a temporary buffer.          */
    /*---------------------------------------------------------------------*/
    remain = nelem;           /* remaining number of values to write  */
    next = 0;                 /* next element in array to be written  */
    rownum = 0;               /* row number, relative to firstrow     */

    while (remain)
    {
        /* limit the number of pixels to process a one time to the number that
           will fit in the buffer space or to the number of pixels that remain
           in the current vector, which ever is smaller.
        */
        ntodo = (long) minvalue(remain, maxelem);      
        ntodo = (long) minvalue(ntodo, (repeat - elemnum));

        wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);

        ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */

        switch (tcode) 
        {
            case (TLONG):
                /* convert the raw data before writing to FITS file */
                ffuintfi4(&array[next], ntodo, scale, zero,
                        (INT32BIT *) buffer, status);
                ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status);
                break;

            case (TLONGLONG):

                ffuintfi8(&array[next], ntodo, scale, zero,
                        (LONGLONG *) buffer, status);
                ffpi8b(fptr, ntodo, incre, (long *) buffer, status);
                break;

            case (TBYTE):
 
                ffuintfi1(&array[next], ntodo, scale, zero,
                        (unsigned char *) buffer, status);
                ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status);
                break;

            case (TSHORT):

                ffuintfi2(&array[next], ntodo, scale, zero,
                        (short *) buffer, status);
                ffpi2b(fptr, ntodo, incre, (short *) buffer, status);
                break;

            case (TFLOAT):

                ffuintfr4(&array[next], ntodo, scale, zero,
                        (float *) buffer, status);
                ffpr4b(fptr, ntodo, incre, (float *) buffer, status);
                break;

            case (TDOUBLE):
                ffuintfr8(&array[next], ntodo, scale, zero,
                       (double *) buffer, status);
                ffpr8b(fptr, ntodo, incre, (double *) buffer, status);
                break;

            case (TSTRING):  /* numerical column in an ASCII table */

                if (cform[1] != 's')  /*  "%s" format is a string */
                {
                  ffuintfstr(&array[next], ntodo, scale, zero, cform,
                          twidth, (char *) buffer, status);

                  if (incre == twidth)    /* contiguous bytes */
                     ffpbyt(fptr, ntodo * twidth, buffer, status);
                  else
                     ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
                            status);

                  break;
                }
                /* can't write to string column, so fall thru to default: */

            default:  /*  error trap  */
                snprintf(message,FLEN_ERRMSG, 
                     "Cannot write numbers to column %d which has format %s",
                      colnum,tform);
                ffpmsg(message);
                if (hdutype == ASCII_TBL)
                    return(*status = BAD_ATABLE_FORMAT);
                else
                    return(*status = BAD_BTABLE_FORMAT);

        } /* End of switch block */

        /*-------------------------*/
        /*  Check for fatal error  */
        /*-------------------------*/
        if (*status > 0)  /* test for error during previous write operation */
        {
          snprintf(message,FLEN_ERRMSG,
          "Error writing elements %.0f thru %.0f of input data array (ffpcluk).",
              (double) (next+1), (double) (next+ntodo));
          ffpmsg(message);
          return(*status);
        }

        /*--------------------------------------------*/
        /*  increment the counters for the next loop  */
        /*--------------------------------------------*/
        remain -= ntodo;
        if (remain)
        {
            next += ntodo;
            elemnum += ntodo;
            if (elemnum == repeat)  /* completed a row; start on next row */
            {
                elemnum = 0;
                rownum++;
            }
        }
    }  /*  End of main while Loop  */


    /*--------------------------------*/
    /*  check for numerical overflow  */
    /*--------------------------------*/
    if (*status == OVERFLOW_ERR)
    {
        ffpmsg(
        "Numerical overflow during type conversion while writing FITS data.");
        *status = NUM_OVERFLOW;
    }

    }   /* end of Dec ALPHA special case */

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpcnuk(fitsfile *fptr,  /* I - FITS file pointer                       */
            int  colnum,     /* I - number of column to write (1 = 1st col) */
            LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
            LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
            LONGLONG  nelem,     /* I - number of values to write               */
   unsigned int   *array,    /* I - array of values to write                */
   unsigned int    nulvalue, /* I - value used to flag undefined pixels     */
            int  *status)    /* IO - error status                           */
/*
  Write an array of elements to the specified column of a table.  Any input
  pixels equal to the value of nulvalue will be replaced by the appropriate
  null value in the output FITS file. 

  The input array of values will be converted to the datatype of the column 
  and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary
*/
{
    tcolumn *colptr;
    LONGLONG  ngood = 0, nbad = 0, ii;
    LONGLONG repeat, first, fstelm, fstrow;
    int tcode, overflow = 0;

    if (*status > 0)
        return(*status);

    /* reset position to the correct HDU if necessary */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
    {
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
    }
    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
    {
        if ( ffrdef(fptr, status) > 0)               /* rescan header */
            return(*status);
    }

    colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
    colptr += (colnum - 1);     /* offset to correct column structure */

    tcode  = colptr->tdatatype;

    if (tcode > 0)
       repeat = colptr->trepeat;  /* repeat count for this column */
    else
       repeat = firstelem -1 + nelem;  /* variable length arrays */

    /* if variable length array, first write the whole input vector, 
       then go back and fill in the nulls */
    if (tcode < 0) {
      if (ffpcluk(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) {
        if (*status == NUM_OVERFLOW) 
	{
	  /* ignore overflows, which are possibly the null pixel values */
	  /*  overflow = 1;   */
	  *status = 0;
	} else { 
          return(*status);
	}
      }
    }

    /* absolute element number in the column */
    first = (firstrow - 1) * repeat + firstelem;

    for (ii = 0; ii < nelem; ii++)
    {
      if (array[ii] != nulvalue)  /* is this a good pixel? */
      {
         if (nbad)  /* write previous string of bad pixels */
         {
            fstelm = ii - nbad + first;  /* absolute element number */
            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

            if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
                return(*status);

            nbad=0;
         }

         ngood = ngood +1;  /* the consecutive number of good pixels */
      }
      else
      {
         if (ngood)  /* write previous string of good pixels */
         {
            fstelm = ii - ngood + first;  /* absolute element number */
            fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
            fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

            if (tcode > 0) {  /* variable length arrays have already been written */
              if (ffpcluk(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
                status) > 0) {
		if (*status == NUM_OVERFLOW) 
		{
		  overflow = 1;
		  *status = 0;
		} else { 
                  return(*status);
		}
	      }
	    }
            ngood=0;
         }

         nbad = nbad +1;  /* the consecutive number of bad pixels */
      }
    }

    /* finished loop;  now just write the last set of pixels */

    if (ngood)  /* write last string of good pixels */
    {
      fstelm = ii - ngood + first;  /* absolute element number */
      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

      if (tcode > 0) {  /* variable length arrays have already been written */
        ffpcluk(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
      }
    }
    else if (nbad) /* write last string of bad pixels */
    {
      fstelm = ii - nbad + first;  /* absolute element number */
      fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
      fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */

      ffpclu(fptr, colnum, fstrow, fstelm, nbad, status);
    }

    if (*status <= 0) {
      if (overflow) {
        *status = NUM_OVERFLOW;
      }
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffuintfi1(unsigned int *input, /* I - array of values to be converted  */
            long ntodo,            /* I - number of elements in the array  */
            double scale,          /* I - FITS TSCALn or BSCALE value      */
            double zero,           /* I - FITS TZEROn or BZERO  value      */
            unsigned char *output, /* O - output array of converted values */
            int *status)           /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
            if (input[ii] > UCHAR_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = UCHAR_MAX;
            }
            else
                output[ii] = input[ii];
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DUCHAR_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = 0;
            }
            else if (dvalue > DUCHAR_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = UCHAR_MAX;
            }
            else
                output[ii] = (unsigned char) (dvalue + .5);
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffuintfi2(unsigned int *input,  /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            short *output,     /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
            if (input[ii] > SHRT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MAX;
            }
            else
                output[ii] = input[ii];
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DSHRT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MIN;
            }
            else if (dvalue > DSHRT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = SHRT_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (short) (dvalue + .5);
                else
                    output[ii] = (short) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffuintfi4(unsigned int *input,  /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            INT32BIT *output,  /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 2147483648.)
    {       
        /* Instead of subtracting 2147483648, it is more efficient */
        /* to just flip the sign bit with the XOR operator */

        for (ii = 0; ii < ntodo; ii++)
             output[ii] =  ( *(int *) &input[ii] ) ^ 0x80000000;
    }
    else if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
            if (input[ii] > INT32_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MAX;
            }
            else
                output[ii] = input[ii];
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DINT_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MIN;
            }
            else if (dvalue > DINT_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = INT32_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (INT32BIT) (dvalue + .5);
                else
                    output[ii] = (INT32BIT) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffuintfi8(unsigned int *input,  /* I - array of values to be converted  */
            long ntodo,             /* I - number of elements in the array  */
            double scale,           /* I - FITS TSCALn or BSCALE value      */
            double zero,            /* I - FITS TZEROn or BZERO  value      */
            LONGLONG *output,       /* O - output array of converted values */
            int *status)            /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required
*/
{
    long ii;
    double dvalue;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
            dvalue = (input[ii] - zero) / scale;

            if (dvalue < DLONGLONG_MIN)
            {
                *status = OVERFLOW_ERR;
                output[ii] = LONGLONG_MIN;
            }
            else if (dvalue > DLONGLONG_MAX)
            {
                *status = OVERFLOW_ERR;
                output[ii] = LONGLONG_MAX;
            }
            else
            {
                if (dvalue >= 0)
                    output[ii] = (LONGLONG) (dvalue + .5);
                else
                    output[ii] = (LONGLONG) (dvalue - .5);
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffuintfr4(unsigned int *input,  /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            float *output,     /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = (float) input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
            output[ii] = (float) ((input[ii] - zero) / scale);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffuintfr8(unsigned int *input,  /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            double *output,    /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do datatype conversion and scaling if required.
*/
{
    long ii;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
                output[ii] = (double) input[ii];
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
            output[ii] = (input[ii] - zero) / scale;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffuintfstr(unsigned int *input, /* I - array of values to be converted  */
            long ntodo,        /* I - number of elements in the array  */
            double scale,      /* I - FITS TSCALn or BSCALE value      */
            double zero,       /* I - FITS TZEROn or BZERO  value      */
            char *cform,       /* I - format for output string values  */
            long twidth,       /* I - width of each field, in chars    */
            char *output,      /* O - output array of converted values */
            int *status)       /* IO - error status                    */
/*
  Copy input to output prior to writing output to a FITS file.
  Do scaling if required.
*/
{
    long ii;
    double dvalue;
    char *cptr;
    
    cptr = output;

    if (scale == 1. && zero == 0.)
    {       
        for (ii = 0; ii < ntodo; ii++)
        {
           sprintf(output, cform, (double) input[ii]);
           output += twidth;

           if (*output)  /* if this char != \0, then overflow occurred */
              *status = OVERFLOW_ERR;
        }
    }
    else
    {
        for (ii = 0; ii < ntodo; ii++)
        {
          dvalue = (input[ii] - zero) / scale;
          sprintf(output, cform, dvalue);
          output += twidth;

          if (*output)  /* if this char != \0, then overflow occurred */
            *status = OVERFLOW_ERR;
        }
    }

    /* replace any commas with periods (e.g., in French locale) */
    while ((cptr = strchr(cptr, ','))) *cptr = '.';
    
    return(*status);
}
cfitsio/putkey.c0000644000225700000360000032557713246025103013510 0ustar  cagordonlhea/*  This file, putkey.c, contains routines that write keywords to          */
/*  a FITS header.                                                         */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include 
#include 
/* stddef.h is apparently needed to define size_t */
#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int ffcrim(fitsfile *fptr,      /* I - FITS file pointer           */
           int bitpix,          /* I - bits per pixel              */
           int naxis,           /* I - number of axes in the array */
           long *naxes,         /* I - size of each axis           */
           int *status)         /* IO - error status               */
/*
  create an IMAGE extension following the current HDU. If the
  current HDU is empty (contains no header keywords), then simply
  write the required image (or primary array) keywords to the current
  HDU. 
*/
{
    if (*status > 0)
        return(*status);

    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    /* create new extension if current header is not empty */
    if ((fptr->Fptr)->headend != (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] )
        ffcrhd(fptr, status);

    /* write the required header keywords */
    ffphpr(fptr, TRUE, bitpix, naxis, naxes, 0, 1, TRUE, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffcrimll(fitsfile *fptr,    /* I - FITS file pointer           */
           int bitpix,          /* I - bits per pixel              */
           int naxis,           /* I - number of axes in the array */
           LONGLONG *naxes,     /* I - size of each axis           */
           int *status)         /* IO - error status               */
/*
  create an IMAGE extension following the current HDU. If the
  current HDU is empty (contains no header keywords), then simply
  write the required image (or primary array) keywords to the current
  HDU. 
*/
{
    if (*status > 0)
        return(*status);

    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    /* create new extension if current header is not empty */
    if ((fptr->Fptr)->headend != (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] )
        ffcrhd(fptr, status);

    /* write the required header keywords */
    ffphprll(fptr, TRUE, bitpix, naxis, naxes, 0, 1, TRUE, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffcrtb(fitsfile *fptr,  /* I - FITS file pointer                        */
           int tbltype,     /* I - type of table to create                  */
           LONGLONG naxis2, /* I - number of rows in the table              */
           int tfields,     /* I - number of columns in the table           */
           char **ttype,    /* I - name of each column                      */
           char **tform,    /* I - value of TFORMn keyword for each column  */
           char **tunit,    /* I - value of TUNITn keyword for each column  */
           const char *extnm, /* I - value of EXTNAME keyword, if any         */
           int *status)     /* IO - error status                            */
/*
  Create a table extension in a FITS file. 
*/
{
    LONGLONG naxis1 = 0;
    long *tbcol = 0;

    if (*status > 0)
        return(*status);

    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    /* create new extension if current header is not empty */
    if ((fptr->Fptr)->headend != (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] )
        ffcrhd(fptr, status);

    if ((fptr->Fptr)->curhdu == 0)  /* have to create dummy primary array */
    {
       ffcrim(fptr, 16, 0, tbcol, status);
       ffcrhd(fptr, status);
    }
    
    if (tbltype == BINARY_TBL)
    {
      /* write the required header keywords. This will write PCOUNT = 0 */
      ffphbn(fptr, naxis2, tfields, ttype, tform, tunit, extnm, 0, status);
    }
    else if (tbltype == ASCII_TBL)
    {
      /* write the required header keywords */
      /* default values for naxis1 and tbcol will be calculated */
      ffphtb(fptr, naxis1, naxis2, tfields, ttype, tbcol, tform, tunit,
             extnm, status);
    }
    else
      *status = NOT_TABLE;

    return(*status);
}
/*-------------------------------------------------------------------------*/
int ffpktp(fitsfile *fptr,       /* I - FITS file pointer       */
           const char *filename, /* I - name of template file   */
           int *status)          /* IO - error status           */
/*
  read keywords from template file and append to the FITS file
*/
{
    FILE *diskfile;
    char card[FLEN_CARD], template[161];
    char keyname[FLEN_KEYWORD], newname[FLEN_KEYWORD];
    int keytype;
    size_t slen;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    diskfile = fopen(filename,"r"); 
    if (!diskfile)          /* couldn't open file */
    {
            ffpmsg("ffpktp could not open the following template file:");
            ffpmsg(filename);
            return(*status = FILE_NOT_OPENED); 
    }

    while (fgets(template, 160, diskfile) )  /* get next template line */
    {
      template[160] = '\0';      /* make sure string is terminated */
      slen = strlen(template);   /* get string length */
      template[slen - 1] = '\0';  /* over write the 'newline' char */

      if (ffgthd(template, card, &keytype, status) > 0) /* parse template */
         break;

      strncpy(keyname, card, 8);
      keyname[8] = '\0';

      if (keytype == -2)            /* rename the card */
      {
         strncpy(newname, &card[40], 8);
         newname[8] = '\0';

         ffmnam(fptr, keyname, newname, status); 
      }
      else if (keytype == -1)      /* delete the card */
      {
         ffdkey(fptr, keyname, status);
      }
      else if (keytype == 0)       /* update the card */
      {
         ffucrd(fptr, keyname, card, status);
      }
      else if (keytype == 1)      /* append the card */
      {
         ffprec(fptr, card, status);
      }
      else    /* END card; stop here */
      {
         break; 
      }
    }

    fclose(diskfile);   /* close the template file */
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpky( fitsfile *fptr,     /* I - FITS file pointer        */
           int  datatype,      /* I - datatype of the value    */
           const char *keyname,/* I - name of keyword to write */
           void *value,        /* I - keyword value            */
           const char *comm,   /* I - keyword comment          */
           int  *status)       /* IO - error status            */
/*
  Write (put) the keyword, value and comment into the FITS header.
  Writes a keyword value with the datatype specified by the 2nd argument.
*/
{
    char errmsg[FLEN_ERRMSG];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (datatype == TSTRING)
    {
        ffpkys(fptr, keyname, (char *) value, comm, status);
    }
    else if (datatype == TBYTE)
    {
        ffpkyj(fptr, keyname, (LONGLONG) *(unsigned char *) value, comm, status);
    }
    else if (datatype == TSBYTE)
    {
        ffpkyj(fptr, keyname, (LONGLONG) *(signed char *) value, comm, status);
    }
    else if (datatype == TUSHORT)
    {
        ffpkyj(fptr, keyname, (LONGLONG) *(unsigned short *) value, comm, status);
    }
    else if (datatype == TSHORT)
    {
        ffpkyj(fptr, keyname, (LONGLONG) *(short *) value, comm, status);
    }
    else if (datatype == TUINT)
    {
        ffpkyg(fptr, keyname, (double) *(unsigned int *) value, 0,
               comm, status);
    }
    else if (datatype == TINT)
    {
        ffpkyj(fptr, keyname, (LONGLONG) *(int *) value, comm, status);
    }
    else if (datatype == TLOGICAL)
    {
        ffpkyl(fptr, keyname, *(int *) value, comm, status);
    }
    else if (datatype == TULONG)
    {
        ffpkyg(fptr, keyname, (double) *(unsigned long *) value, 0,
               comm, status);
    }
    else if (datatype == TLONG)
    {
        ffpkyj(fptr, keyname, (LONGLONG) *(long *) value, comm, status);
    }
    else if (datatype == TLONGLONG)
    {
        ffpkyj(fptr, keyname, *(LONGLONG *) value, comm, status);
    }
    else if (datatype == TFLOAT)
    {
        ffpkye(fptr, keyname, *(float *) value, -7, comm, status);
    }
    else if (datatype == TDOUBLE)
    {
        ffpkyd(fptr, keyname, *(double *) value, -15, comm, status);
    }
    else if (datatype == TCOMPLEX)
    {
        ffpkyc(fptr, keyname, (float *) value, -7, comm, status);
    }
    else if (datatype == TDBLCOMPLEX)
    {
        ffpkym(fptr, keyname, (double *) value, -15, comm, status);
    }
    else
    {
        snprintf(errmsg, FLEN_ERRMSG,"Bad keyword datatype code: %d (ffpky)", datatype);
        ffpmsg(errmsg);
        *status = BAD_DATATYPE;
    }

    return(*status);
} 
/*-------------------------------------------------------------------------*/
int ffprec(fitsfile *fptr,     /* I - FITS file pointer        */
           const char *card,   /* I - string to be written     */
           int *status)        /* IO - error status            */
/*
  write a keyword record (80 bytes long) to the end of the header
*/
{
    char tcard[FLEN_CARD];
    size_t len, ii;
    long nblocks;
    int keylength;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    if ( ((fptr->Fptr)->datastart - (fptr->Fptr)->headend) == 80) /* no room */
    {
        nblocks = 1;
        if (ffiblk(fptr, nblocks, 0, status) > 0) /* insert 2880-byte block */
            return(*status);  
    }

    strncpy(tcard,card,80);
    tcard[80] = '\0';

    len = strlen(tcard);

    /* silently replace any illegal characters with a space */
    for (ii=0; ii < len; ii++)   
        if (tcard[ii] < ' ' || tcard[ii] > 126) tcard[ii] = ' ';

    for (ii=len; ii < 80; ii++)    /* fill card with spaces if necessary */
        tcard[ii] = ' ';

    keylength = strcspn(tcard, "=");   /* support for free-format keywords */
    if (keylength == 80) keylength = 8;
    
    /* test for the common commentary keywords which by definition have 8-char names */
    if ( !fits_strncasecmp( "COMMENT ", tcard, 8) || !fits_strncasecmp( "HISTORY ", tcard, 8) ||
         !fits_strncasecmp( "        ", tcard, 8) || !fits_strncasecmp( "CONTINUE", tcard, 8) )
	 keylength = 8;

    for (ii=0; ii < keylength; ii++)       /* make sure keyword name is uppercase */
        tcard[ii] = toupper(tcard[ii]);

    fftkey(tcard, status);        /* test keyword name contains legal chars */

/*  no need to do this any more, since any illegal characters have been removed
    fftrec(tcard, status);  */        /* test rest of keyword for legal chars */

    ffmbyt(fptr, (fptr->Fptr)->headend, IGNORE_EOF, status); /* move to end */

    ffpbyt(fptr, 80, tcard, status);   /* write the 80 byte card */

    if (*status <= 0)
       (fptr->Fptr)->headend += 80;    /* update end-of-header position */

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpkyu( fitsfile *fptr,     /* I - FITS file pointer        */
            const char *keyname,/* I - name of keyword to write */
            const char *comm,   /* I - keyword comment          */
            int  *status)       /* IO - error status            */
/*
  Write (put) a null-valued keyword and comment into the FITS header.  
*/
{
    char valstring[FLEN_VALUE];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    strcpy(valstring," ");  /* create a dummy value string */
    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword */
    ffprec(fptr, card, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpkys( fitsfile *fptr,     /* I - FITS file pointer        */
            const char *keyname,/* I - name of keyword to write */
            const char *value,  /* I - keyword value            */
            const char *comm,   /* I - keyword comment          */
            int  *status)       /* IO - error status            */
/*
  Write (put) the keyword, value and comment into the FITS header.
  The value string will be truncated at 68 characters which is the
  maximum length that will fit on a single FITS keyword.
*/
{
    char valstring[FLEN_VALUE];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    ffs2c(value, valstring, status);   /* put quotes around the string */

    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword */
    ffprec(fptr, card, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpkls( fitsfile *fptr,     /* I - FITS file pointer        */
            const char *keyname,/* I - name of keyword to write */
            const char *value,  /* I - keyword value            */
            const char *comm,   /* I - keyword comment          */
            int  *status)       /* IO - error status            */
/*
  Write (put) the keyword, value and comment into the FITS header.
  This routine is a modified version of ffpkys which supports the
  HEASARC long string convention and can write arbitrarily long string
  keyword values.  The value is continued over multiple keywords that
  have the name COMTINUE without an equal sign in column 9 of the card.
  This routine also supports simple string keywords which are less than
  69 characters in length.
*/
{
    char valstring[FLEN_CARD];
    char card[FLEN_CARD], tmpkeyname[FLEN_CARD];
    char tstring[FLEN_CARD], *cptr;
    int next, remain, vlen, nquote, nchar, namelen, contin, tstatus = -1;
    int commlen=0, nocomment = 0;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    remain = maxvalue(strlen(value), 1); /* no. of chars to write (at least 1) */  
    if (comm) { 
       commlen = strlen(comm);
       if (commlen > 47) commlen = 47;  /* only guarantee preserving the first 47 characters */
    }

    /* count the number of single quote characters are in the string */
    tstring[0] = '\0';
    strncat(tstring, value, 68); /* copy 1st part of string to temp buff */
    nquote = 0;
    cptr = strchr(tstring, '\'');   /* search for quote character */
    while (cptr)  /* search for quote character */
    {
        nquote++;            /*  increment no. of quote characters  */
        cptr++;              /*  increment pointer to next character */
        cptr = strchr(cptr, '\'');  /* search for another quote char */
    }

    strncpy(tmpkeyname, keyname, 80);
    tmpkeyname[80] = '\0';
    
    cptr = tmpkeyname;
    while(*cptr == ' ')   /* skip over leading spaces in name */
        cptr++;

    /* determine the number of characters that will fit on the line */
    /* Note: each quote character is expanded to 2 quotes */

    namelen = strlen(cptr);
    if (namelen <= 8 && (fftkey(cptr, &tstatus) <= 0) )
    {
        /* This a normal 8-character FITS keyword */
        nchar = 68 - nquote; /*  max of 68 chars fit in a FITS string value */
    }
    else
    {
	   nchar = 80 - nquote - namelen - 5;
    }

    contin = 0;
    next = 0;                  /* pointer to next character to write */

    while (remain > 0)
    {
        tstring[0] = '\0';
        strncat(tstring, &value[next], nchar); /* copy string to temp buff */
        ffs2c(tstring, valstring, status);  /* expand quotes, and put quotes around the string */

        if (remain > nchar)   /* if string is continued, put & as last char */
        {
            vlen = strlen(valstring);
            nchar -= 1;        /* outputting one less character now */

            if (valstring[vlen-2] != '\'')
                valstring[vlen-2] = '&';  /*  over write last char with &  */
            else
            { /* last char was a pair of single quotes, so over write both */
                valstring[vlen-3] = '&';
                valstring[vlen-1] = '\0';
            }
        }

        if (contin)           /* This is a CONTINUEd keyword */
        {
           if (nocomment) {
               ffmkky("CONTINUE", valstring, NULL, card, status); /* make keyword w/o comment */
           } else {
               ffmkky("CONTINUE", valstring, comm, card, status); /* make keyword */
	   }
           strncpy(&card[8], "   ",  2);  /* overwrite the '=' */
        }
        else
        {
           ffmkky(keyname, valstring, comm, card, status);  /* make keyword */
        }

        ffprec(fptr, card, status);  /* write the keyword */

        contin = 1;
        remain -= nchar;
        next  += nchar;
        nocomment = 0;

        if (remain > 0) 
        {
           /* count the number of single quote characters in next section */
           tstring[0] = '\0';
           strncat(tstring, &value[next], 68); /* copy next part of string */
           nquote = 0;
           cptr = strchr(tstring, '\'');   /* search for quote character */
           while (cptr)  /* search for quote character */
           {
               nquote++;            /*  increment no. of quote characters  */
               cptr++;              /*  increment pointer to next character */
               cptr = strchr(cptr, '\'');  /* search for another quote char */
           }
           nchar = 68 - nquote;  /* max number of chars to write this time */
        }

        /* make adjustment if necessary to allow reasonable room for a comment on last CONTINUE card 
	   only need to do this if 
	     a) there is a comment string, and
	     b) the remaining value string characters could all fit on the next CONTINUE card, and
	     c) there is not enough room on the next CONTINUE card for both the remaining value
	        characters, and at least 47 characters of the comment string.
	*/
	
        if (commlen > 0 && remain + nquote < 69 && remain + nquote + commlen > 65) 
	{
            if (nchar > 18) { /* only false if there are a rediculous number of quotes in the string */
	        nchar = remain - 15;  /* force continuation onto another card, so that */
		                      /* there is room for a comment up to 47 chara long */
                nocomment = 1;  /* don't write the comment string this time */
            }
	}
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffplsw( fitsfile *fptr,     /* I - FITS file pointer  */
            int  *status)       /* IO - error status       */
/*
  Write the LONGSTRN keyword and a series of related COMMENT keywords
  which document that this FITS header may contain long string keyword
  values which are continued over multiple keywords using the HEASARC
  long string keyword convention.  If the LONGSTRN keyword already exists
  then this routine simple returns without doing anything.
*/
{
    char valstring[FLEN_VALUE], comm[FLEN_COMMENT];
    int tstatus;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    tstatus = 0;
    if (ffgkys(fptr, "LONGSTRN", valstring, comm, &tstatus) == 0)
        return(*status);     /* keyword already exists, so just return */

    ffpkys(fptr, "LONGSTRN", "OGIP 1.0", 
       "The HEASARC Long String Convention may be used.", status);

    ffpcom(fptr,
    "  This FITS file may contain long string keyword values that are", status);

    ffpcom(fptr,
    "  continued over multiple keywords.  The HEASARC convention uses the &",
    status);

    ffpcom(fptr,
    "  character at the end of each substring which is then continued", status);

    ffpcom(fptr,
    "  on the next keyword which has the name CONTINUE.", status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpkyl( fitsfile *fptr,     /* I - FITS file pointer        */
            const char *keyname,/* I - name of keyword to write */
            int  value,         /* I - keyword value            */
            const char *comm,   /* I - keyword comment          */
            int  *status)       /* IO - error status            */
/*
  Write (put) the keyword, value and comment into the FITS header.
  Values equal to 0 will result in a False FITS keyword; any other
  non-zero value will result in a True FITS keyword.
*/
{
    char valstring[FLEN_VALUE];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    ffl2c(value, valstring, status);   /* convert to formatted string */
    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
    ffprec(fptr, card, status);  /* write the keyword*/

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpkyj( fitsfile *fptr,     /* I - FITS file pointer        */
            const char *keyname,/* I - name of keyword to write */
            LONGLONG value,     /* I - keyword value            */
            const char *comm,   /* I - keyword comment          */
            int  *status)       /* IO - error status            */
/*
  Write (put) the keyword, value and comment into the FITS header.
  Writes an integer keyword value.
*/
{
    char valstring[FLEN_VALUE];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    ffi2c(value, valstring, status);   /* convert to formatted string */
    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
    ffprec(fptr, card, status);  /* write the keyword*/

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpkyf( fitsfile *fptr,      /* I - FITS file pointer                   */
            const char  *keyname,/* I - name of keyword to write            */
            float value,         /* I - keyword value                       */
            int   decim,         /* I - number of decimal places to display */
            const char  *comm,   /* I - keyword comment                     */
            int   *status)       /* IO - error status                       */
/*
  Write (put) the keyword, value and comment into the FITS header.
  Writes a fixed float keyword value.
*/
{
    char valstring[FLEN_VALUE];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    ffr2f(value, decim, valstring, status);   /* convert to formatted string */
    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
    ffprec(fptr, card, status);  /* write the keyword*/

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpkye( fitsfile *fptr,      /* I - FITS file pointer                   */
            const char  *keyname,/* I - name of keyword to write            */
            float value,         /* I - keyword value                       */
            int   decim,         /* I - number of decimal places to display */
            const char  *comm,   /* I - keyword comment                     */
            int   *status)       /* IO - error status                       */
/*
  Write (put) the keyword, value and comment into the FITS header.
  Writes an exponential float keyword value.
*/
{
    char valstring[FLEN_VALUE];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    ffr2e(value, decim, valstring, status);   /* convert to formatted string */
    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
    ffprec(fptr, card, status);  /* write the keyword*/

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpkyg( fitsfile *fptr,      /* I - FITS file pointer                   */
            const char  *keyname,/* I - name of keyword to write            */
            double value,        /* I - keyword value                       */
            int   decim,         /* I - number of decimal places to display */
            const char  *comm,   /* I - keyword comment                     */
            int   *status)       /* IO - error status                       */
/*
  Write (put) the keyword, value and comment into the FITS header.
  Writes a fixed double keyword value.*/
{
    char valstring[FLEN_VALUE];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    ffd2f(value, decim, valstring, status);  /* convert to formatted string */
    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
    ffprec(fptr, card, status);  /* write the keyword*/

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpkyd( fitsfile *fptr,      /* I - FITS file pointer                   */
            const char  *keyname,/* I - name of keyword to write            */
            double value,        /* I - keyword value                       */
            int   decim,         /* I - number of decimal places to display */
            const char  *comm,   /* I - keyword comment                     */
            int   *status)       /* IO - error status                       */
/*
  Write (put) the keyword, value and comment into the FITS header.
  Writes an exponential double keyword value.*/
{
    char valstring[FLEN_VALUE];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    ffd2e(value, decim, valstring, status);  /* convert to formatted string */
    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
    ffprec(fptr, card, status);  /* write the keyword*/

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpkyc( fitsfile *fptr,      /* I - FITS file pointer                   */
            const char  *keyname,/* I - name of keyword to write            */
            float *value,        /* I - keyword value (real, imaginary)     */
            int   decim,         /* I - number of decimal places to display */
            const char  *comm,   /* I - keyword comment                     */
            int   *status)       /* IO - error status                       */
/*
  Write (put) the keyword, value and comment into the FITS header.
  Writes an complex float keyword value. Format = (realvalue, imagvalue)
*/
{
    char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    strcpy(valstring, "(" );
    ffr2e(value[0], decim, tmpstring, status); /* convert to string */
    strcat(valstring, tmpstring);
    strcat(valstring, ", ");
    ffr2e(value[1], decim, tmpstring, status); /* convert to string */
    strcat(valstring, tmpstring);
    strcat(valstring, ")");

    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
    ffprec(fptr, card, status);  /* write the keyword*/

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpkym( fitsfile *fptr,      /* I - FITS file pointer                   */
            const char  *keyname,/* I - name of keyword to write            */
            double *value,       /* I - keyword value (real, imaginary)     */
            int   decim,         /* I - number of decimal places to display */
            const char  *comm,   /* I - keyword comment                     */
            int   *status)       /* IO - error status                       */
/*
  Write (put) the keyword, value and comment into the FITS header.
  Writes an complex double keyword value. Format = (realvalue, imagvalue)
*/
{
    char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    strcpy(valstring, "(" );
    ffd2e(value[0], decim, tmpstring, status); /* convert to string */
    strcat(valstring, tmpstring);
    strcat(valstring, ", ");
    ffd2e(value[1], decim, tmpstring, status); /* convert to string */
    strcat(valstring, tmpstring);
    strcat(valstring, ")");

    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
    ffprec(fptr, card, status);  /* write the keyword*/

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpkfc( fitsfile *fptr,      /* I - FITS file pointer                   */
            const char  *keyname,/* I - name of keyword to write            */
            float *value,        /* I - keyword value (real, imaginary)     */
            int   decim,         /* I - number of decimal places to display */
            const char  *comm,   /* I - keyword comment                     */
            int   *status)       /* IO - error status                       */
/*
  Write (put) the keyword, value and comment into the FITS header.
  Writes an complex float keyword value. Format = (realvalue, imagvalue)
*/
{
    char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    strcpy(valstring, "(" );
    ffr2f(value[0], decim, tmpstring, status); /* convert to string */
    strcat(valstring, tmpstring);
    strcat(valstring, ", ");
    ffr2f(value[1], decim, tmpstring, status); /* convert to string */
    strcat(valstring, tmpstring);
    strcat(valstring, ")");

    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
    ffprec(fptr, card, status);  /* write the keyword*/

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpkfm( fitsfile *fptr,      /* I - FITS file pointer                   */
            const char  *keyname,/* I - name of keyword to write            */
            double *value,       /* I - keyword value (real, imaginary)     */
            int   decim,         /* I - number of decimal places to display */
            const char  *comm,   /* I - keyword comment                     */
            int   *status)       /* IO - error status                       */
/*
  Write (put) the keyword, value and comment into the FITS header.
  Writes an complex double keyword value. Format = (realvalue, imagvalue)
*/
{
    char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
    char card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    strcpy(valstring, "(" );
    ffd2f(value[0], decim, tmpstring, status); /* convert to string */
    strcat(valstring, tmpstring);
    strcat(valstring, ", ");
    ffd2f(value[1], decim, tmpstring, status); /* convert to string */
    strcat(valstring, tmpstring);
    strcat(valstring, ")");

    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
    ffprec(fptr, card, status);  /* write the keyword*/

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpkyt( fitsfile *fptr,      /* I - FITS file pointer        */
            const char  *keyname,/* I - name of keyword to write */
            long  intval,        /* I - integer part of value    */
            double fraction,     /* I - fractional part of value */
            const char  *comm,   /* I - keyword comment          */
            int   *status)       /* IO - error status            */
/*
  Write (put) a 'triple' precision keyword where the integer and
  fractional parts of the value are passed in separate parameters to
  increase the total amount of numerical precision.
*/
{
    char valstring[FLEN_VALUE];
    char card[FLEN_CARD];
    char fstring[20], *cptr;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (fraction > 1. || fraction < 0.)
    {
        ffpmsg("fraction must be between 0. and 1. (ffpkyt)");
        return(*status = BAD_F2C);
    }

    ffi2c(intval, valstring, status);  /* convert integer to string */
    ffd2f(fraction, 16, fstring, status);  /* convert to 16 decimal string */

    cptr = strchr(fstring, '.');    /* find the decimal point */
    strcat(valstring, cptr);    /* append the fraction to the integer */

    ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
    ffprec(fptr, card, status);  /* write the keyword*/

    return(*status);
}
/*-----------------------------------------------------------------*/
int ffpcom( fitsfile *fptr,      /* I - FITS file pointer   */
            const char  *comm,   /* I - comment string      */
            int   *status)       /* IO - error status       */
/*
  Write 1 or more COMMENT keywords.  If the comment string is too
  long to fit on a single keyword (72 chars) then it will automatically
  be continued on multiple CONTINUE keywords.
*/
{
    char card[FLEN_CARD];
    int len, ii;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    len = strlen(comm);
    ii = 0;

    for (; len > 0; len -= 72)
    {
        strcpy(card, "COMMENT ");
        strncat(card, &comm[ii], 72);
        ffprec(fptr, card, status);
        ii += 72;
    }

    return(*status);
}
/*-----------------------------------------------------------------*/
int ffphis( fitsfile *fptr,      /* I - FITS file pointer  */
            const char *history, /* I - history string     */
            int   *status)       /* IO - error status      */
/*
  Write 1 or more HISTORY keywords.  If the history string is too
  long to fit on a single keyword (72 chars) then it will automatically
  be continued on multiple HISTORY keywords.
*/
{
    char card[FLEN_CARD];
    int len, ii;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    len = strlen(history);
    ii = 0;

    for (; len > 0; len -= 72)
    {
        strcpy(card, "HISTORY ");
        strncat(card, &history[ii], 72);
        ffprec(fptr, card, status);
        ii += 72;
    }

    return(*status);
}
/*-----------------------------------------------------------------*/
int ffpdat( fitsfile *fptr,      /* I - FITS file pointer  */
            int   *status)       /* IO - error status      */
/*
  Write the DATE keyword into the FITS header.  If the keyword already
  exists then the date will simply be updated in the existing keyword.
*/
{
    int timeref;
    char date[30], tmzone[10], card[FLEN_CARD];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    ffgstm(date, &timeref, status);

    if (timeref)           /* GMT not available on this machine */
        strcpy(tmzone, " Local");    
    else
        strcpy(tmzone, " UT");    

    strcpy(card, "DATE    = '");
    strcat(card, date);
    strcat(card, "' / file creation date (YYYY-MM-DDThh:mm:ss");
    strcat(card, tmzone);
    strcat(card, ")");

    ffucrd(fptr, "DATE", card, status);

    return(*status);
}
/*-------------------------------------------------------------------*/
int ffverifydate(int year,          /* I - year (0 - 9999)           */
                 int month,         /* I - month (1 - 12)            */
                 int day,           /* I - day (1 - 31)              */
                 int   *status)     /* IO - error status             */
/*
  Verify that the date is valid
*/
{
    int ndays[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
    char errmsg[FLEN_ERRMSG];
    

    if (year < 0 || year > 9999)
    {
       snprintf(errmsg, FLEN_ERRMSG,
       "input year value = %d is out of range 0 - 9999", year);
       ffpmsg(errmsg);
       return(*status = BAD_DATE);
    }
    else if (month < 1 || month > 12)
    {
       snprintf(errmsg, FLEN_ERRMSG,
       "input month value = %d is out of range 1 - 12", month);
       ffpmsg(errmsg);
       return(*status = BAD_DATE);
    }
    
    if (ndays[month] == 31) {
        if (day < 1 || day > 31)
        {
           snprintf(errmsg, FLEN_ERRMSG,
           "input day value = %d is out of range 1 - 31 for month %d", day, month);
           ffpmsg(errmsg);
           return(*status = BAD_DATE);
        }
    } else if (ndays[month] == 30) {
        if (day < 1 || day > 30)
        {
           snprintf(errmsg, FLEN_ERRMSG,
           "input day value = %d is out of range 1 - 30 for month %d", day, month);
           ffpmsg(errmsg);
           return(*status = BAD_DATE);
        }
    } else {
        if (day < 1 || day > 28)
        {
            if (day == 29)
            {
	      /* year is a leap year if it is divisible by 4 but not by 100,
	         except years divisible by 400 are leap years
	      */
	        if ((year % 4 == 0 && year % 100 != 0 ) || year % 400 == 0)
		   return (*status);
		   
 	        snprintf(errmsg, FLEN_ERRMSG,
           "input day value = %d is out of range 1 - 28 for February %d (not leap year)", day, year);
                ffpmsg(errmsg);
	    } else {
                snprintf(errmsg, FLEN_ERRMSG,
                "input day value = %d is out of range 1 - 28 (or 29) for February", day);
                ffpmsg(errmsg);
	    }
	    
            return(*status = BAD_DATE);
        }
    }
    return(*status);
}
/*-----------------------------------------------------------------*/
int ffgstm( char *timestr,   /* O  - returned system date and time string  */
            int  *timeref,   /* O - GMT = 0, Local time = 1  */
            int   *status)   /* IO - error status      */
/*
  Returns the current date and time in format 'yyyy-mm-ddThh:mm:ss'.
*/
{
    time_t tp;
    struct tm *ptr;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    time(&tp);
    ptr = gmtime(&tp);         /* get GMT (= UTC) time */

    if (timeref)
    {
        if (ptr)
            *timeref = 0;   /* returning GMT */
        else
            *timeref = 1;   /* returning local time */
    }

    if (!ptr)                  /* GMT not available on this machine */
        ptr = localtime(&tp); 

    strftime(timestr, 25, "%Y-%m-%dT%H:%M:%S", ptr);

    return(*status);
}
/*-----------------------------------------------------------------*/
int ffdt2s(int year,          /* I - year (0 - 9999)           */
           int month,         /* I - month (1 - 12)            */
           int day,           /* I - day (1 - 31)              */
           char *datestr,     /* O - date string: "YYYY-MM-DD" */
           int   *status)     /* IO - error status             */
/*
  Construct a date character string
*/
{
    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    *datestr = '\0';
    
    if (ffverifydate(year, month, day, status) > 0)
    {
        ffpmsg("invalid date (ffdt2s)");
        return(*status);
    }

    if (year >= 1900 && year <= 1998)  /* use old 'dd/mm/yy' format */
        sprintf(datestr, "%.2d/%.2d/%.2d", day, month, year - 1900);

    else  /* use the new 'YYYY-MM-DD' format */
        sprintf(datestr, "%.4d-%.2d-%.2d", year, month, day);

    return(*status);
}
/*-----------------------------------------------------------------*/
int ffs2dt(char *datestr,   /* I - date string: "YYYY-MM-DD" or "dd/mm/yy" */
           int *year,       /* O - year (0 - 9999)                         */
           int *month,      /* O - month (1 - 12)                          */
           int *day,        /* O - day (1 - 31)                            */
           int   *status)   /* IO - error status                           */
/*
  Parse a date character string into year, month, and day values
*/
{
    int slen, lyear, lmonth, lday;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (year)
        *year = 0;
    if (month)
        *month = 0;
    if (day)
        *day   = 0;

    if (!datestr)
    {
        ffpmsg("error: null input date string (ffs2dt)");
        return(*status = BAD_DATE);   /* Null datestr pointer ??? */
    }

    slen = strlen(datestr);

    if (slen == 8 && datestr[2] == '/' && datestr[5] == '/')
    {
        if (isdigit((int) datestr[0]) && isdigit((int) datestr[1])
         && isdigit((int) datestr[3]) && isdigit((int) datestr[4])
         && isdigit((int) datestr[6]) && isdigit((int) datestr[7]) )
        {
            /* this is an old format string: "dd/mm/yy" */
            lyear  = atoi(&datestr[6]) + 1900;
            lmonth = atoi(&datestr[3]);
	    lday   = atoi(datestr);
	    
            if (year)
                *year = lyear;
            if (month)
                *month = lmonth;
            if (day)
                *day   = lday;
        }
        else
        {
            ffpmsg("input date string has illegal format (ffs2dt):");
            ffpmsg(datestr);
            return(*status = BAD_DATE);
        }
    }
    else if (slen >= 10 && datestr[4] == '-' && datestr[7] == '-')
        {
        if (isdigit((int) datestr[0]) && isdigit((int) datestr[1])
         && isdigit((int) datestr[2]) && isdigit((int) datestr[3])
         && isdigit((int) datestr[5]) && isdigit((int) datestr[6])
         && isdigit((int) datestr[8]) && isdigit((int) datestr[9]) )
        {
            if (slen > 10 && datestr[10] != 'T')
            {
                ffpmsg("input date string has illegal format (ffs2dt):");
                ffpmsg(datestr);
                return(*status = BAD_DATE);
            }

            /* this is a new format string: "yyyy-mm-dd" */
            lyear  = atoi(datestr);
            lmonth = atoi(&datestr[5]);
            lday   = atoi(&datestr[8]);

            if (year)
               *year  = lyear;
            if (month)
               *month = lmonth;
            if (day)
               *day   = lday;
        }
        else
        {
                ffpmsg("input date string has illegal format (ffs2dt):");
                ffpmsg(datestr);
                return(*status = BAD_DATE);
        }
    }
    else
    {
                ffpmsg("input date string has illegal format (ffs2dt):");
                ffpmsg(datestr);
                return(*status = BAD_DATE);
    }


    if (ffverifydate(lyear, lmonth, lday, status) > 0)
    {
        ffpmsg("invalid date (ffs2dt)");
    }

    return(*status);
}
/*-----------------------------------------------------------------*/
int fftm2s(int year,          /* I - year (0 - 9999)           */
           int month,         /* I - month (1 - 12)            */
           int day,           /* I - day (1 - 31)              */
           int hour,          /* I - hour (0 - 23)             */
           int minute,        /* I - minute (0 - 59)           */
           double second,     /* I - second (0. - 60.9999999)  */
           int decimals,      /* I - number of decimal points to write      */
           char *datestr,     /* O - date string: "YYYY-MM-DDThh:mm:ss.ddd" */
                              /*   or "hh:mm:ss.ddd" if year, month day = 0 */
           int   *status)     /* IO - error status             */
/*
  Construct a date and time character string
*/
{
    int width;
    char errmsg[FLEN_ERRMSG];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    *datestr='\0';

    if (year != 0 || month != 0 || day !=0)
    { 
        if (ffverifydate(year, month, day, status) > 0)
	{
            ffpmsg("invalid date (fftm2s)");
            return(*status);
        }
    }

    if (hour < 0 || hour > 23)
    {
       snprintf(errmsg, FLEN_ERRMSG,
       "input hour value is out of range 0 - 23: %d (fftm2s)", hour);
       ffpmsg(errmsg);
       return(*status = BAD_DATE);
    }
    else if (minute < 0 || minute > 59)
    {
       snprintf(errmsg, FLEN_ERRMSG,
       "input minute value is out of range 0 - 59: %d (fftm2s)", minute);
       ffpmsg(errmsg);
       return(*status = BAD_DATE);
    }
    else if (second < 0. || second >= 61)
    {
       snprintf(errmsg, FLEN_ERRMSG,
       "input second value is out of range 0 - 60.999: %f (fftm2s)", second);
       ffpmsg(errmsg);
       return(*status = BAD_DATE);
    }
    else if (decimals > 25)
    {
       snprintf(errmsg, FLEN_ERRMSG,
       "input decimals value is out of range 0 - 25: %d (fftm2s)", decimals);
       ffpmsg(errmsg);
       return(*status = BAD_DATE);
    }

    if (decimals == 0)
       width = 2;
    else
       width = decimals + 3;

    if (decimals < 0)
    {
        /* a negative decimals value means return only the date, not time */
        sprintf(datestr, "%.4d-%.2d-%.2d", year, month, day);
    }
    else if (year == 0 && month == 0 && day == 0)
    {
        /* return only the time, not the date */
        sprintf(datestr, "%.2d:%.2d:%0*.*f",
            hour, minute, width, decimals, second);
    }
    else
    {
        /* return both the time and date */
        sprintf(datestr, "%.4d-%.2d-%.2dT%.2d:%.2d:%0*.*f",
            year, month, day, hour, minute, width, decimals, second);
    }
    return(*status);
}
/*-----------------------------------------------------------------*/
int ffs2tm(char *datestr,     /* I - date string: "YYYY-MM-DD"    */
                              /*     or "YYYY-MM-DDThh:mm:ss.ddd" */
                              /*     or "dd/mm/yy"                */
           int *year,         /* O - year (0 - 9999)              */
           int *month,        /* O - month (1 - 12)               */
           int *day,          /* O - day (1 - 31)                 */
           int *hour,          /* I - hour (0 - 23)                */
           int *minute,        /* I - minute (0 - 59)              */
           double *second,     /* I - second (0. - 60.9999999)     */
           int   *status)     /* IO - error status                */
/*
  Parse a date character string into date and time values
*/
{
    int slen;
    char errmsg[FLEN_ERRMSG];

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (year)
       *year   = 0;
    if (month)
       *month  = 0;
    if (day)
       *day    = 0;
    if (hour)
       *hour   = 0;
    if (minute)
       *minute = 0;
    if (second)
       *second = 0.;

    if (!datestr)
    {
        ffpmsg("error: null input date string (ffs2tm)");
        return(*status = BAD_DATE);   /* Null datestr pointer ??? */
    }

    if (datestr[2] == '/' || datestr[4] == '-')
    {
        /*  Parse the year, month, and date */
        if (ffs2dt(datestr, year, month, day, status) > 0)
            return(*status);

        slen = strlen(datestr);
        if (slen == 8 || slen == 10)
            return(*status);               /* OK, no time fields */
        else if (slen < 19) 
        {
            ffpmsg("input date string has illegal format:");
            ffpmsg(datestr);
            return(*status = BAD_DATE);
        }

        else if (datestr[10] == 'T' && datestr[13] == ':' && datestr[16] == ':')
        {
          if (isdigit((int) datestr[11]) && isdigit((int) datestr[12])
           && isdigit((int) datestr[14]) && isdigit((int) datestr[15])
           && isdigit((int) datestr[17]) && isdigit((int) datestr[18]) )
            {
                if (slen > 19 && datestr[19] != '.')
                {
                  ffpmsg("input date string has illegal format:");
                  ffpmsg(datestr);
                  return(*status = BAD_DATE);
                }

                /* this is a new format string: "yyyy-mm-ddThh:mm:ss.dddd" */
                if (hour)
                    *hour   = atoi(&datestr[11]);

                if (minute)
                    *minute = atoi(&datestr[14]);

                if (second)
                    *second = atof(&datestr[17]);
            }
            else
            {
                  ffpmsg("input date string has illegal format:");
                  ffpmsg(datestr);
                  return(*status = BAD_DATE);
            }

        }
    }
    else   /* no date fields */
    {
        if (datestr[2] == ':' && datestr[5] == ':')   /* time string */
        {
            if (isdigit((int) datestr[0]) && isdigit((int) datestr[1])
             && isdigit((int) datestr[3]) && isdigit((int) datestr[4])
             && isdigit((int) datestr[6]) && isdigit((int) datestr[7]) )
            {
                 /* this is a time string: "hh:mm:ss.dddd" */
                 if (hour)
                    *hour   = atoi(&datestr[0]);

                 if (minute)
                    *minute = atoi(&datestr[3]);

                if (second)
                    *second = atof(&datestr[6]);
            }
            else
            {
                  ffpmsg("input date string has illegal format:");
                  ffpmsg(datestr);
                  return(*status = BAD_DATE);
            }

        }
        else
        {
                  ffpmsg("input date string has illegal format:");
                  ffpmsg(datestr);
                  return(*status = BAD_DATE);
        }

    }

    if (hour)
       if (*hour < 0 || *hour > 23)
       {
          snprintf(errmsg,FLEN_ERRMSG, 
          "hour value is out of range 0 - 23: %d (ffs2tm)", *hour);
          ffpmsg(errmsg);
          return(*status = BAD_DATE);
       }

    if (minute)
       if (*minute < 0 || *minute > 59)
       {
          snprintf(errmsg, FLEN_ERRMSG,
          "minute value is out of range 0 - 59: %d (ffs2tm)", *minute);
          ffpmsg(errmsg);
          return(*status = BAD_DATE);
       }

    if (second)
       if (*second < 0 || *second >= 61.)
       {
          snprintf(errmsg, FLEN_ERRMSG,
          "second value is out of range 0 - 60.9999: %f (ffs2tm)", *second);
          ffpmsg(errmsg);
          return(*status = BAD_DATE);
       }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsdt( int *day, int *month, int *year, int *status )
{  
/*
      This routine is included for backward compatibility
            with the Fortran FITSIO library.

   ffgsdt : Get current System DaTe (GMT if available)

      Return integer values of the day, month, and year

         Function parameters:
            day      Day of the month
            month    Numerical month (1=Jan, etc.)
            year     Year (1999, 2000, etc.)
            status   output error status

*/
   time_t now;
   struct tm *date;

   now = time( NULL );
   date = gmtime(&now);         /* get GMT (= UTC) time */

   if (!date)                  /* GMT not available on this machine */
   {
       date = localtime(&now); 
   }

   *day = date->tm_mday;
   *month = date->tm_mon + 1;
   *year = date->tm_year + 1900;  /* tm_year is defined as years since 1900 */
   return( *status );
}
/*--------------------------------------------------------------------------*/
int ffpkns( fitsfile *fptr,     /* I - FITS file pointer                    */
            const char *keyroot,      /* I - root name of keywords to write       */
            int  nstart,        /* I - starting index number                */
            int  nkey,          /* I - number of keywords to write          */
            char *value[],      /* I - array of pointers to keyword values  */
            char *comm[],       /* I - array of pointers to keyword comment */
            int  *status)       /* IO - error status                        */
/*
  Write (put) an indexed array of keywords with index numbers between
  NSTART and (NSTART + NKEY -1) inclusive.  Writes string keywords.
  The value strings will be truncated at 68 characters, and the HEASARC
  long string keyword convention is not supported by this routine.
*/
{
    char keyname[FLEN_KEYWORD], tcomment[FLEN_COMMENT];
    int ii, jj, repeat, len;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /* check if first comment string is to be repeated for all the keywords */
    /* by looking to see if the last non-blank character is a '&' char      */

    repeat = 0;

    if (comm)
    {
      len = strlen(comm[0]);

      while (len > 0  && comm[0][len - 1] == ' ')
        len--;                               /* ignore trailing blanks */

      if (comm[0][len - 1] == '&')
      {
        len = minvalue(len, FLEN_COMMENT);
        tcomment[0] = '\0';
        strncat(tcomment, comm[0], len-1); /* don't copy the final '&' char */
        repeat = 1;
      }
    }
    else
    {
      repeat = 1;
      tcomment[0] = '\0';
    }

    for (ii=0, jj=nstart; ii < nkey; ii++, jj++)
    {
        ffkeyn(keyroot, jj, keyname, status);
        if (repeat)
            ffpkys(fptr, keyname, value[ii], tcomment, status);
        else
            ffpkys(fptr, keyname, value[ii], comm[ii], status);

        if (*status > 0)
            return(*status);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpknl( fitsfile *fptr,     /* I - FITS file pointer                    */
            const char *keyroot,      /* I - root name of keywords to write       */
            int  nstart,        /* I - starting index number                */
            int  nkey,          /* I - number of keywords to write          */
            int  *value,        /* I - array of keyword values              */
            char *comm[],       /* I - array of pointers to keyword comment */
            int  *status)       /* IO - error status                        */
/*
  Write (put) an indexed array of keywords with index numbers between
  NSTART and (NSTART + NKEY -1) inclusive.  Writes logical keywords
  Values equal to zero will be written as a False FITS keyword value; any
  other non-zero value will result in a True FITS keyword.
*/
{
    char keyname[FLEN_KEYWORD], tcomment[FLEN_COMMENT];
    int ii, jj, repeat, len;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /* check if first comment string is to be repeated for all the keywords */
    /* by looking to see if the last non-blank character is a '&' char      */

    repeat = 0;
    if (comm)
    {
      len = strlen(comm[0]);

      while (len > 0  && comm[0][len - 1] == ' ')
        len--;                               /* ignore trailing blanks */

      if (comm[0][len - 1] == '&')
      {
        len = minvalue(len, FLEN_COMMENT);
        tcomment[0] = '\0';
        strncat(tcomment, comm[0], len-1); /* don't copy the final '&' char */
        repeat = 1;
      }
    }
    else
    {
      repeat = 1;
      tcomment[0] = '\0';
    }


    for (ii=0, jj=nstart; ii < nkey; ii++, jj++)
    {
        ffkeyn(keyroot, jj, keyname, status);

        if (repeat)
            ffpkyl(fptr, keyname, value[ii], tcomment, status);
        else
            ffpkyl(fptr, keyname, value[ii], comm[ii], status);

        if (*status > 0)
            return(*status);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpknj( fitsfile *fptr,     /* I - FITS file pointer                    */
            const char *keyroot,      /* I - root name of keywords to write       */
            int  nstart,        /* I - starting index number                */
            int  nkey,          /* I - number of keywords to write          */
            long *value,        /* I - array of keyword values              */
            char *comm[],       /* I - array of pointers to keyword comment */
            int  *status)       /* IO - error status                        */
/*
  Write (put) an indexed array of keywords with index numbers between
  NSTART and (NSTART + NKEY -1) inclusive.  Write integer keywords
*/
{
    char keyname[FLEN_KEYWORD], tcomment[FLEN_COMMENT];
    int ii, jj, repeat, len;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /* check if first comment string is to be repeated for all the keywords */
    /* by looking to see if the last non-blank character is a '&' char      */

    repeat = 0;

    if (comm)
    {
      len = strlen(comm[0]);

      while (len > 0  && comm[0][len - 1] == ' ')
        len--;                               /* ignore trailing blanks */

      if (comm[0][len - 1] == '&')
      {
        len = minvalue(len, FLEN_COMMENT);
        tcomment[0] = '\0';
        strncat(tcomment, comm[0], len-1); /* don't copy the final '&' char */
        repeat = 1;
      }
    }
    else
    {
      repeat = 1;
      tcomment[0] = '\0';
    }

    for (ii=0, jj=nstart; ii < nkey; ii++, jj++)
    {
        ffkeyn(keyroot, jj, keyname, status);
        if (repeat)
            ffpkyj(fptr, keyname, value[ii], tcomment, status);
        else
            ffpkyj(fptr, keyname, value[ii], comm[ii], status);

        if (*status > 0)
            return(*status);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpknjj( fitsfile *fptr,    /* I - FITS file pointer                    */
            const char *keyroot,      /* I - root name of keywords to write       */
            int  nstart,        /* I - starting index number                */
            int  nkey,          /* I - number of keywords to write          */
            LONGLONG *value,    /* I - array of keyword values              */
            char *comm[],       /* I - array of pointers to keyword comment */
            int  *status)       /* IO - error status                        */
/*
  Write (put) an indexed array of keywords with index numbers between
  NSTART and (NSTART + NKEY -1) inclusive.  Write integer keywords
*/
{
    char keyname[FLEN_KEYWORD], tcomment[FLEN_COMMENT];
    int ii, jj, repeat, len;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /* check if first comment string is to be repeated for all the keywords */
    /* by looking to see if the last non-blank character is a '&' char      */

    repeat = 0;

    if (comm)
    {
      len = strlen(comm[0]);

      while (len > 0  && comm[0][len - 1] == ' ')
        len--;                               /* ignore trailing blanks */

      if (comm[0][len - 1] == '&')
      {
        len = minvalue(len, FLEN_COMMENT);
        tcomment[0] = '\0';
        strncat(tcomment, comm[0], len-1); /* don't copy the final '&' char */
        repeat = 1;
      }
    }
    else
    {
      repeat = 1;
      tcomment[0] = '\0';
    }

    for (ii=0, jj=nstart; ii < nkey; ii++, jj++)
    {
        ffkeyn(keyroot, jj, keyname, status);
        if (repeat)
            ffpkyj(fptr, keyname, value[ii], tcomment, status);
        else
            ffpkyj(fptr, keyname, value[ii], comm[ii], status);

        if (*status > 0)
            return(*status);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpknf( fitsfile *fptr,     /* I - FITS file pointer                    */
            const char *keyroot,      /* I - root name of keywords to write       */
            int  nstart,        /* I - starting index number                */
            int  nkey,          /* I - number of keywords to write          */
            float *value,       /* I - array of keyword values              */
            int decim,          /* I - number of decimals to display        */
            char *comm[],       /* I - array of pointers to keyword comment */
            int  *status)       /* IO - error status                        */
/*
  Write (put) an indexed array of keywords with index numbers between
  NSTART and (NSTART + NKEY -1) inclusive.  Writes fixed float values.
*/
{
    char keyname[FLEN_KEYWORD], tcomment[FLEN_COMMENT];
    int ii, jj, repeat, len;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /* check if first comment string is to be repeated for all the keywords */
    /* by looking to see if the last non-blank character is a '&' char      */

    repeat = 0;

    if (comm)
    {
      len = strlen(comm[0]);

      while (len > 0  && comm[0][len - 1] == ' ')
        len--;                               /* ignore trailing blanks */

      if (comm[0][len - 1] == '&')
      {
        len = minvalue(len, FLEN_COMMENT);
        tcomment[0] = '\0';
        strncat(tcomment, comm[0], len-1); /* don't copy the final '&' char */
        repeat = 1;
      }
    }
    else
    {
      repeat = 1;
      tcomment[0] = '\0';
    }

    for (ii=0, jj=nstart; ii < nkey; ii++, jj++)
    {
        ffkeyn(keyroot, jj, keyname, status);
        if (repeat)
            ffpkyf(fptr, keyname, value[ii], decim, tcomment, status);
        else
            ffpkyf(fptr, keyname, value[ii], decim, comm[ii], status);

        if (*status > 0)
            return(*status);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpkne( fitsfile *fptr,     /* I - FITS file pointer                    */
            const char *keyroot,      /* I - root name of keywords to write       */
            int  nstart,        /* I - starting index number                */
            int  nkey,          /* I - number of keywords to write          */
            float *value,       /* I - array of keyword values              */
            int decim,          /* I - number of decimals to display        */
            char *comm[],       /* I - array of pointers to keyword comment */
            int  *status)       /* IO - error status                        */
/*
  Write (put) an indexed array of keywords with index numbers between
  NSTART and (NSTART + NKEY -1) inclusive.  Writes exponential float values.
*/
{
    char keyname[FLEN_KEYWORD], tcomment[FLEN_COMMENT];
    int ii, jj, repeat, len;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /* check if first comment string is to be repeated for all the keywords */
    /* by looking to see if the last non-blank character is a '&' char      */

    repeat = 0;

    if (comm)
    {
      len = strlen(comm[0]);

      while (len > 0  && comm[0][len - 1] == ' ')
        len--;                               /* ignore trailing blanks */

      if (comm[0][len - 1] == '&')
      {
        len = minvalue(len, FLEN_COMMENT);
        tcomment[0] = '\0';
        strncat(tcomment, comm[0], len-1); /* don't copy the final '&' char */
        repeat = 1;
      }
    }
    else
    {
      repeat = 1;
      tcomment[0] = '\0';
    }

    for (ii=0, jj=nstart; ii < nkey; ii++, jj++)
    {
        ffkeyn(keyroot, jj, keyname, status);
        if (repeat)
            ffpkye(fptr, keyname, value[ii], decim, tcomment, status);
        else
            ffpkye(fptr, keyname, value[ii], decim, comm[ii], status);

        if (*status > 0)
            return(*status);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpkng( fitsfile *fptr,     /* I - FITS file pointer                    */
            const char *keyroot,      /* I - root name of keywords to write       */
            int  nstart,        /* I - starting index number                */
            int  nkey,          /* I - number of keywords to write          */
            double *value,      /* I - array of keyword values              */
            int decim,          /* I - number of decimals to display        */
            char *comm[],       /* I - array of pointers to keyword comment */
            int  *status)       /* IO - error status                        */
/*
  Write (put) an indexed array of keywords with index numbers between
  NSTART and (NSTART + NKEY -1) inclusive.  Writes fixed double values.
*/
{
    char keyname[FLEN_KEYWORD], tcomment[FLEN_COMMENT];
    int ii, jj, repeat, len;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /* check if first comment string is to be repeated for all the keywords */
    /* by looking to see if the last non-blank character is a '&' char      */

    repeat = 0;

    if (comm)
    {
      len = strlen(comm[0]);

      while (len > 0  && comm[0][len - 1] == ' ')
        len--;                               /* ignore trailing blanks */

      if (comm[0][len - 1] == '&')
      {
        len = minvalue(len, FLEN_COMMENT);
        tcomment[0] = '\0';
        strncat(tcomment, comm[0], len-1); /* don't copy the final '&' char */
        repeat = 1;
      }
    }
    else
    {
      repeat = 1;
      tcomment[0] = '\0';
    }

    for (ii=0, jj=nstart; ii < nkey; ii++, jj++)
    {
        ffkeyn(keyroot, jj, keyname, status);
        if (repeat)
            ffpkyg(fptr, keyname, value[ii], decim, tcomment, status);
        else
            ffpkyg(fptr, keyname, value[ii], decim, comm[ii], status);

        if (*status > 0)
            return(*status);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpknd( fitsfile *fptr,     /* I - FITS file pointer                    */
            const char *keyroot,      /* I - root name of keywords to write       */
            int  nstart,        /* I - starting index number                */
            int  nkey,          /* I - number of keywords to write          */
            double *value,      /* I - array of keyword values              */
            int decim,          /* I - number of decimals to display        */
            char *comm[],       /* I - array of pointers to keyword comment */
            int  *status)       /* IO - error status                        */
/*
  Write (put) an indexed array of keywords with index numbers between
  NSTART and (NSTART + NKEY -1) inclusive.  Writes exponential double values.
*/
{
    char keyname[FLEN_KEYWORD], tcomment[FLEN_COMMENT];
    int ii, jj, repeat, len;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    /* check if first comment string is to be repeated for all the keywords */
    /* by looking to see if the last non-blank character is a '&' char      */

    repeat = 0;

    if (comm)
    {
      len = strlen(comm[0]);

      while (len > 0  && comm[0][len - 1] == ' ')
        len--;                               /* ignore trailing blanks */

      if (comm[0][len - 1] == '&')
      {
        len = minvalue(len, FLEN_COMMENT);
        tcomment[0] = '\0';
        strncat(tcomment, comm[0], len-1); /* don't copy the final '&' char */
        repeat = 1;
      }
    }
    else
    {
      repeat = 1;
      tcomment[0] = '\0';
    }

    for (ii=0, jj=nstart; ii < nkey; ii++, jj++)
    {
        ffkeyn(keyroot, jj, keyname, status);
        if (repeat)
            ffpkyd(fptr, keyname, value[ii], decim, tcomment, status);
        else
            ffpkyd(fptr, keyname, value[ii], decim, comm[ii], status);

        if (*status > 0)
            return(*status);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffptdm( fitsfile *fptr, /* I - FITS file pointer                        */
            int colnum,     /* I - column number                            */
            int naxis,      /* I - number of axes in the data array         */
            long naxes[],   /* I - length of each data axis                 */
            int *status)    /* IO - error status                            */
/*
  write the TDIMnnn keyword describing the dimensionality of a column
*/
{
    char keyname[FLEN_KEYWORD], tdimstr[FLEN_VALUE], comm[FLEN_COMMENT];
    char value[80], message[FLEN_ERRMSG];
    int ii;
    long totalpix = 1, repeat;
    tcolumn *colptr;

    if (*status > 0)
        return(*status);

    if (colnum < 1 || colnum > 999)
    {
        ffpmsg("column number is out of range 1 - 999 (ffptdm)");
        return(*status = BAD_COL_NUM);
    }

    if (naxis < 1)
    {
        ffpmsg("naxis is less than 1 (ffptdm)");
        return(*status = BAD_DIMEN);
    }

    /* reset position to the correct HDU if necessary */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
        if ( ffrdef(fptr, status) > 0)               /* rescan header */
            return(*status);

    if ( (fptr->Fptr)->hdutype != BINARY_TBL)
    {
       ffpmsg(
    "Error: The TDIMn keyword is only allowed in BINTABLE extensions (ffptdm)");
       return(*status = NOT_BTABLE);
    }

    strcpy(tdimstr, "(");            /* start constructing the TDIM value */   

    for (ii = 0; ii < naxis; ii++)
    {
        if (ii > 0)
            strcat(tdimstr, ",");   /* append the comma separator */

        if (naxes[ii] < 0)
        {
            ffpmsg("one or more TDIM values are less than 0 (ffptdm)");
            return(*status = BAD_TDIM);
        }

        snprintf(value, 80,"%ld", naxes[ii]);
        strcat(tdimstr, value);     /* append the axis size */

        totalpix *= naxes[ii];
    }

    colptr = (fptr->Fptr)->tableptr;  /* point to first column structure */
    colptr += (colnum - 1);      /* point to the specified column number */

    if ((long) colptr->trepeat != totalpix)
    {
      /* There is an apparent inconsistency between TDIMn and TFORMn. */
      /* The colptr->trepeat value may be out of date, so re-read     */
      /* the TFORMn keyword to be sure.                               */

      ffkeyn("TFORM", colnum, keyname, status);   /* construct TFORMn name  */
      ffgkys(fptr, keyname, value, NULL, status); /* read TFORMn keyword    */
      ffbnfm(value, NULL, &repeat, NULL, status); /* parse the repeat count */

      if (*status > 0 || repeat != totalpix)
      {
        snprintf(message,FLEN_ERRMSG,
        "column vector length, %ld, does not equal TDIMn array size, %ld",
        (long) colptr->trepeat, totalpix);
        ffpmsg(message);
        return(*status = BAD_TDIM);
      }
    }

    strcat(tdimstr, ")" );            /* append the closing parenthesis */

    strcpy(comm, "size of the multidimensional array");
    ffkeyn("TDIM", colnum, keyname, status);      /* construct TDIMn name */
    ffpkys(fptr, keyname, tdimstr, comm, status);  /* write the keyword */
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffptdmll( fitsfile *fptr, /* I - FITS file pointer                      */
            int colnum,     /* I - column number                            */
            int naxis,      /* I - number of axes in the data array         */
            LONGLONG naxes[], /* I - length of each data axis               */
            int *status)    /* IO - error status                            */
/*
  write the TDIMnnn keyword describing the dimensionality of a column
*/
{
    char keyname[FLEN_KEYWORD], tdimstr[FLEN_VALUE], comm[FLEN_COMMENT];
    char value[80], message[81];
    int ii;
    LONGLONG totalpix = 1, repeat;
    tcolumn *colptr;

    if (*status > 0)
        return(*status);

    if (colnum < 1 || colnum > 999)
    {
        ffpmsg("column number is out of range 1 - 999 (ffptdm)");
        return(*status = BAD_COL_NUM);
    }

    if (naxis < 1)
    {
        ffpmsg("naxis is less than 1 (ffptdm)");
        return(*status = BAD_DIMEN);
    }

    /* reset position to the correct HDU if necessary */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
    else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
        if ( ffrdef(fptr, status) > 0)               /* rescan header */
            return(*status);

    if ( (fptr->Fptr)->hdutype != BINARY_TBL)
    {
       ffpmsg(
    "Error: The TDIMn keyword is only allowed in BINTABLE extensions (ffptdm)");
       return(*status = NOT_BTABLE);
    }

    strcpy(tdimstr, "(");            /* start constructing the TDIM value */   

    for (ii = 0; ii < naxis; ii++)
    {
        if (ii > 0)
            strcat(tdimstr, ",");   /* append the comma separator */

        if (naxes[ii] < 0)
        {
            ffpmsg("one or more TDIM values are less than 0 (ffptdm)");
            return(*status = BAD_TDIM);
        }

        /* cast to double because the 64-bit int conversion character in */
        /* sprintf is platform dependent ( %lld, %ld, %I64d )            */

        snprintf(value, 80, "%.0f", (double) naxes[ii]);

        strcat(tdimstr, value);     /* append the axis size */

        totalpix *= naxes[ii];
    }

    colptr = (fptr->Fptr)->tableptr;  /* point to first column structure */
    colptr += (colnum - 1);      /* point to the specified column number */

    if ( colptr->trepeat != totalpix)
    {
      /* There is an apparent inconsistency between TDIMn and TFORMn. */
      /* The colptr->trepeat value may be out of date, so re-read     */
      /* the TFORMn keyword to be sure.                               */

      ffkeyn("TFORM", colnum, keyname, status);   /* construct TFORMn name  */
      ffgkys(fptr, keyname, value, NULL, status); /* read TFORMn keyword    */
      ffbnfmll(value, NULL, &repeat, NULL, status); /* parse the repeat count */

      if (*status > 0 || repeat != totalpix)
      {
        snprintf(message,FLEN_ERRMSG,
        "column vector length, %.0f, does not equal TDIMn array size, %.0f",
        (double) (colptr->trepeat), (double) totalpix);
        ffpmsg(message);
        return(*status = BAD_TDIM);
      }
    }

    strcat(tdimstr, ")" );            /* append the closing parenthesis */

    strcpy(comm, "size of the multidimensional array");
    ffkeyn("TDIM", colnum, keyname, status);      /* construct TDIMn name */
    ffpkys(fptr, keyname, tdimstr, comm, status);  /* write the keyword */
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffphps( fitsfile *fptr, /* I - FITS file pointer                        */
            int bitpix,     /* I - number of bits per data value pixel      */
            int naxis,      /* I - number of axes in the data array         */
            long naxes[],   /* I - length of each data axis                 */
            int *status)    /* IO - error status                            */
/*
  write STANDARD set of required primary header keywords
*/
{
    int simple = 1;     /* does file conform to FITS standard? 1/0  */
    long pcount = 0;    /* number of group parameters (usually 0)   */
    long gcount = 1;    /* number of random groups (usually 1 or 0) */
    int extend = 1;     /* may FITS file have extensions?           */

    ffphpr(fptr, simple, bitpix, naxis, naxes, pcount, gcount, extend, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffphpsll( fitsfile *fptr, /* I - FITS file pointer                        */
            int bitpix,     /* I - number of bits per data value pixel      */
            int naxis,      /* I - number of axes in the data array         */
            LONGLONG naxes[],   /* I - length of each data axis                 */
            int *status)    /* IO - error status                            */
/*
  write STANDARD set of required primary header keywords
*/
{
    int simple = 1;     /* does file conform to FITS standard? 1/0  */
    LONGLONG pcount = 0;    /* number of group parameters (usually 0)   */
    LONGLONG gcount = 1;    /* number of random groups (usually 1 or 0) */
    int extend = 1;     /* may FITS file have extensions?           */

    ffphprll(fptr, simple, bitpix, naxis, naxes, pcount, gcount, extend, status);
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffphpr( fitsfile *fptr, /* I - FITS file pointer                        */
            int simple,     /* I - does file conform to FITS standard? 1/0  */
            int bitpix,     /* I - number of bits per data value pixel      */
            int naxis,      /* I - number of axes in the data array         */
            long naxes[],   /* I - length of each data axis                 */
            LONGLONG pcount, /* I - number of group parameters (usually 0)   */
            LONGLONG gcount, /* I - number of random groups (usually 1 or 0) */
            int extend,     /* I - may FITS file have extensions?           */
            int *status)    /* IO - error status                            */
/*
  write required primary header keywords
*/
{
    int ii;
    LONGLONG naxesll[20];
   
    for (ii = 0; (ii < naxis) && (ii < 20); ii++)
       naxesll[ii] = naxes[ii];

    ffphprll(fptr, simple, bitpix, naxis, naxesll, pcount, gcount,
             extend, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffphprll( fitsfile *fptr, /* I - FITS file pointer                        */
            int simple,     /* I - does file conform to FITS standard? 1/0  */
            int bitpix,     /* I - number of bits per data value pixel      */
            int naxis,      /* I - number of axes in the data array         */
            LONGLONG naxes[], /* I - length of each data axis                 */
            LONGLONG pcount,  /* I - number of group parameters (usually 0)   */
            LONGLONG gcount,  /* I - number of random groups (usually 1 or 0) */
            int extend,     /* I - may FITS file have extensions?           */
            int *status)    /* IO - error status                            */
/*
  write required primary header keywords
*/
{
    int ii;
    long longbitpix, tnaxes[20];
    char name[FLEN_KEYWORD], comm[FLEN_COMMENT], message[FLEN_ERRMSG];

    if (*status > 0)
        return(*status);

    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    if ((fptr->Fptr)->headend != (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] )
        return(*status = HEADER_NOT_EMPTY);

    if (naxis != 0)   /* never try to compress a null image */
    {
      if ( (fptr->Fptr)->request_compress_type )
      {
      
       for (ii = 0; ii < naxis; ii++)
           tnaxes[ii] = (long) naxes[ii];
	   
        /* write header for a compressed image */
        imcomp_init_table(fptr, bitpix, naxis, tnaxes, 1, status);
        return(*status);
      }
    }  

    if ((fptr->Fptr)->curhdu == 0)
    {                /* write primary array header */
        if (simple)
            strcpy(comm, "file does conform to FITS standard");
        else
            strcpy(comm, "file does not conform to FITS standard");

        ffpkyl(fptr, "SIMPLE", simple, comm, status);
    }
    else
    {               /* write IMAGE extension header */
        strcpy(comm, "IMAGE extension");
        ffpkys(fptr, "XTENSION", "IMAGE", comm, status);
    }

    longbitpix = bitpix;

    /* test for the 3 special cases that represent unsigned integers */
    if (longbitpix == USHORT_IMG)
        longbitpix = SHORT_IMG;
    else if (longbitpix == ULONG_IMG)
        longbitpix = LONG_IMG;
    else if (longbitpix == SBYTE_IMG)
        longbitpix = BYTE_IMG;

    if (longbitpix != BYTE_IMG && longbitpix != SHORT_IMG && 
        longbitpix != LONG_IMG && longbitpix != LONGLONG_IMG &&
        longbitpix != FLOAT_IMG && longbitpix != DOUBLE_IMG)
    {
        snprintf(message,FLEN_ERRMSG,
        "Illegal value for BITPIX keyword: %d", bitpix);
        ffpmsg(message);
        return(*status = BAD_BITPIX);
    }

    strcpy(comm, "number of bits per data pixel");
    if (ffpkyj(fptr, "BITPIX", longbitpix, comm, status) > 0)
        return(*status);

    if (naxis < 0 || naxis > 999)
    {
        snprintf(message,FLEN_ERRMSG,
        "Illegal value for NAXIS keyword: %d", naxis);
        ffpmsg(message);
        return(*status = BAD_NAXIS);
    }

    strcpy(comm, "number of data axes");
    ffpkyj(fptr, "NAXIS", naxis, comm, status);

    strcpy(comm, "length of data axis ");
    for (ii = 0; ii < naxis; ii++)
    {
        if (naxes[ii] < 0)
        {
            snprintf(message,FLEN_ERRMSG,
            "Illegal negative value for NAXIS%d keyword: %.0f", ii + 1, (double) (naxes[ii]));
            ffpmsg(message);
            return(*status = BAD_NAXES);
        }

        snprintf(&comm[20], FLEN_COMMENT-20,"%d", ii + 1);
        ffkeyn("NAXIS", ii + 1, name, status);
        ffpkyj(fptr, name, naxes[ii], comm, status);
    }

    if ((fptr->Fptr)->curhdu == 0)  /* the primary array */
    {
        if (extend)
        {
            /* only write EXTEND keyword if value = true */
            strcpy(comm, "FITS dataset may contain extensions");
            ffpkyl(fptr, "EXTEND", extend, comm, status);
        }

        if (pcount < 0)
        {
            ffpmsg("pcount value is less than 0");
            return(*status = BAD_PCOUNT);
        }

        else if (gcount < 1)
        {
            ffpmsg("gcount value is less than 1");
            return(*status = BAD_GCOUNT);
        }

        else if (pcount > 0 || gcount > 1)
        {
            /* only write these keyword if non-standard values */
            strcpy(comm, "random group records are present");
            ffpkyl(fptr, "GROUPS", 1, comm, status);

            strcpy(comm, "number of random group parameters");
            ffpkyj(fptr, "PCOUNT", pcount, comm, status);
  
            strcpy(comm, "number of random groups");
            ffpkyj(fptr, "GCOUNT", gcount, comm, status);
        }

      /* write standard block of self-documentating comments */
      ffprec(fptr,
      "COMMENT   FITS (Flexible Image Transport System) format is defined in 'Astronomy",
      status);
      ffprec(fptr,
      "COMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H",
      status);
    }

    else  /* an IMAGE extension */

    {   /* image extension; cannot have random groups */
        if (pcount != 0)
        {
            ffpmsg("image extensions must have pcount = 0");
            *status = BAD_PCOUNT;
        }

        else if (gcount != 1)
        {
            ffpmsg("image extensions must have gcount = 1");
            *status = BAD_GCOUNT;
        }

        else
        {
            strcpy(comm, "required keyword; must = 0");
            ffpkyj(fptr, "PCOUNT", 0, comm, status);
  
            strcpy(comm, "required keyword; must = 1");
            ffpkyj(fptr, "GCOUNT", 1, comm, status);
        }
    }

    /* Write the BSCALE and BZERO keywords, if an unsigned integer image */
    if (bitpix == USHORT_IMG)
    {
        strcpy(comm, "offset data range to that of unsigned short");
        ffpkyg(fptr, "BZERO", 32768., 0, comm, status);
        strcpy(comm, "default scaling factor");
        ffpkyg(fptr, "BSCALE", 1.0, 0, comm, status);
    }
    else if (bitpix == ULONG_IMG)
    {
        strcpy(comm, "offset data range to that of unsigned long");
        ffpkyg(fptr, "BZERO", 2147483648., 0, comm, status);
        strcpy(comm, "default scaling factor");
        ffpkyg(fptr, "BSCALE", 1.0, 0, comm, status);
    }
    else if (bitpix == SBYTE_IMG)
    {
        strcpy(comm, "offset data range to that of signed byte");
        ffpkyg(fptr, "BZERO", -128., 0, comm, status);
        strcpy(comm, "default scaling factor");
        ffpkyg(fptr, "BSCALE", 1.0, 0, comm, status);
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffphtb(fitsfile *fptr,  /* I - FITS file pointer                        */
           LONGLONG naxis1,     /* I - width of row in the table                */
           LONGLONG naxis2,     /* I - number of rows in the table              */
           int tfields,     /* I - number of columns in the table           */
           char **ttype,    /* I - name of each column                      */
           long *tbcol,     /* I - byte offset in row to each column        */
           char **tform,    /* I - value of TFORMn keyword for each column  */
           char **tunit,    /* I - value of TUNITn keyword for each column  */
           const char *extnmx,   /* I - value of EXTNAME keyword, if any         */
           int *status)     /* IO - error status                            */
/*
  Put required Header keywords into the ASCII TaBle:
*/
{
    int ii, ncols, gotmem = 0;
    long rowlen; /* must be 'long' because it is passed to ffgabc */
    char tfmt[30], name[FLEN_KEYWORD], comm[FLEN_COMMENT], extnm[FLEN_VALUE];

    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    if (*status > 0)
        return(*status);
    else if ((fptr->Fptr)->headend != (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] )
        return(*status = HEADER_NOT_EMPTY);
    else if (naxis1 < 0)
        return(*status = NEG_WIDTH);
    else if (naxis2 < 0)
        return(*status = NEG_ROWS);
    else if (tfields < 0 || tfields > 999)
        return(*status = BAD_TFIELDS);
    
    extnm[0] = '\0';
    if (extnmx)
        strncat(extnm, extnmx, FLEN_VALUE-1);

    rowlen = (long) naxis1;

    if (!tbcol || !tbcol[0] || (!naxis1 && tfields)) /* spacing not defined? */
    {
      /* allocate mem for tbcol; malloc can have problems allocating small */
      /* arrays, so allocate at least 20 bytes */

      ncols = maxvalue(5, tfields);
      tbcol = (long *) calloc(ncols, sizeof(long));

      if (tbcol)
      {
        gotmem = 1;

        /* calculate width of a row and starting position of each column. */
        /* Each column will be separated by 1 blank space */
        ffgabc(tfields, tform, 1, &rowlen, tbcol, status);
      }
    }
    ffpkys(fptr, "XTENSION", "TABLE", "ASCII table extension", status);
    ffpkyj(fptr, "BITPIX", 8, "8-bit ASCII characters", status);
    ffpkyj(fptr, "NAXIS", 2, "2-dimensional ASCII table", status);
    ffpkyj(fptr, "NAXIS1", rowlen, "width of table in characters", status);
    ffpkyj(fptr, "NAXIS2", naxis2, "number of rows in table", status);
    ffpkyj(fptr, "PCOUNT", 0, "no group parameters (required keyword)", status);
    ffpkyj(fptr, "GCOUNT", 1, "one data group (required keyword)", status);
    ffpkyj(fptr, "TFIELDS", tfields, "number of fields in each row", status);

    for (ii = 0; ii < tfields; ii++) /* loop over every column */
    {
        if ( *(ttype[ii]) )  /* optional TTYPEn keyword */
        {
          snprintf(comm, FLEN_COMMENT,"label for field %3d", ii + 1);
          ffkeyn("TTYPE", ii + 1, name, status);
          ffpkys(fptr, name, ttype[ii], comm, status);
        }

        if (tbcol[ii] < 1 || tbcol[ii] > rowlen)
           *status = BAD_TBCOL;

        snprintf(comm, FLEN_COMMENT,"beginning column of field %3d", ii + 1);
        ffkeyn("TBCOL", ii + 1, name, status);
        ffpkyj(fptr, name, tbcol[ii], comm, status);

        strcpy(tfmt, tform[ii]);  /* required TFORMn keyword */
        ffupch(tfmt);
        ffkeyn("TFORM", ii + 1, name, status);
        ffpkys(fptr, name, tfmt, "Fortran-77 format of field", status);

        if (tunit)
        {
         if (tunit[ii] && *(tunit[ii]) )  /* optional TUNITn keyword */
         {
          ffkeyn("TUNIT", ii + 1, name, status);
          ffpkys(fptr, name, tunit[ii], "physical unit of field", status) ;
         }
        }

        if (*status > 0)
            break;       /* abort loop on error */
    }

    if (extnm[0])       /* optional EXTNAME keyword */
        ffpkys(fptr, "EXTNAME", extnm,
               "name of this ASCII table extension", status);

    if (*status > 0)
        ffpmsg("Failed to write ASCII table header keywords (ffphtb)");

    if (gotmem)
        free(tbcol); 

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffphbn(fitsfile *fptr,  /* I - FITS file pointer                        */
           LONGLONG naxis2,     /* I - number of rows in the table              */
           int tfields,     /* I - number of columns in the table           */
           char **ttype,    /* I - name of each column                      */
           char **tform,    /* I - value of TFORMn keyword for each column  */
           char **tunit,    /* I - value of TUNITn keyword for each column  */
           const char *extnmx,   /* I - value of EXTNAME keyword, if any         */
           LONGLONG pcount,     /* I - size of the variable length heap area    */
           int *status)     /* IO - error status                            */
/*
  Put required Header keywords into the Binary Table:
*/
{
    int ii, datatype, iread = 0;
    long repeat, width;
    LONGLONG naxis1;

    char tfmt[30], name[FLEN_KEYWORD], comm[FLEN_COMMENT], extnm[FLEN_VALUE];
    char *cptr;

    if (*status > 0)
        return(*status);

    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    if ((fptr->Fptr)->headend != (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] )
        return(*status = HEADER_NOT_EMPTY);
    else if (naxis2 < 0)
        return(*status = NEG_ROWS);
    else if (pcount < 0)
        return(*status = BAD_PCOUNT);
    else if (tfields < 0 || tfields > 999)
        return(*status = BAD_TFIELDS);

    extnm[0] = '\0';
    if (extnmx)
        strncat(extnm, extnmx, FLEN_VALUE-1);

    ffpkys(fptr, "XTENSION", "BINTABLE", "binary table extension", status);
    ffpkyj(fptr, "BITPIX", 8, "8-bit bytes", status);
    ffpkyj(fptr, "NAXIS", 2, "2-dimensional binary table", status);

    naxis1 = 0;
    for (ii = 0; ii < tfields; ii++)  /* sum the width of each field */
    {
        ffbnfm(tform[ii], &datatype, &repeat, &width, status);

        if (datatype == TSTRING)
            naxis1 += repeat;   /* one byte per char */
        else if (datatype == TBIT)
            naxis1 += (repeat + 7) / 8;
        else if (datatype > 0)
            naxis1 += repeat * (datatype / 10);
        else if (tform[ii][0] == 'P' || tform[ii][1] == 'P'||
                 tform[ii][0] == 'p' || tform[ii][1] == 'p')
           /* this is a 'P' variable length descriptor (neg. datatype) */
            naxis1 += 8;
        else
           /* this is a 'Q' variable length descriptor (neg. datatype) */
            naxis1 += 16;

        if (*status > 0)
            break;       /* abort loop on error */
    }

    ffpkyj(fptr, "NAXIS1", naxis1, "width of table in bytes", status);
    ffpkyj(fptr, "NAXIS2", naxis2, "number of rows in table", status);

    /*
      the initial value of PCOUNT (= size of the variable length array heap)
      should always be zero.  If any variable length data is written, then
      the value of PCOUNT will be updated when the HDU is closed
    */
    ffpkyj(fptr, "PCOUNT", 0, "size of special data area", status);
    ffpkyj(fptr, "GCOUNT", 1, "one data group (required keyword)", status);
    ffpkyj(fptr, "TFIELDS", tfields, "number of fields in each row", status);

    for (ii = 0; ii < tfields; ii++) /* loop over every column */
    {
        if ( *(ttype[ii]) )  /* optional TTYPEn keyword */
        {
          snprintf(comm, FLEN_COMMENT,"label for field %3d", ii + 1);
          ffkeyn("TTYPE", ii + 1, name, status);
          ffpkys(fptr, name, ttype[ii], comm, status);
        }

        strcpy(tfmt, tform[ii]);  /* required TFORMn keyword */
        ffupch(tfmt);

        ffkeyn("TFORM", ii + 1, name, status);
        strcpy(comm, "data format of field");

        ffbnfm(tfmt, &datatype, &repeat, &width, status);

        if (datatype == TSTRING)
        {
            strcat(comm, ": ASCII Character");

            /* Do sanity check to see if an ASCII table format was used,  */
            /* e.g., 'A8' instead of '8A', or a bad unit width eg '8A9'.  */
            /* Don't want to return an error status, so write error into  */
            /* the keyword comment.  */

            cptr = strchr(tfmt,'A');
            cptr++;

            if (cptr)
               iread = sscanf(cptr,"%ld", &width);

            if (iread == 1 && (width > repeat)) 
            {
              if (repeat == 1)
                strcpy(comm, "ERROR??  USING ASCII TABLE SYNTAX BY MISTAKE??");
              else
                strcpy(comm, "rAw FORMAT ERROR! UNIT WIDTH w > COLUMN WIDTH r");
            }
        }
        else if (datatype == TBIT)
           strcat(comm, ": BIT");
        else if (datatype == TBYTE)
           strcat(comm, ": BYTE");
        else if (datatype == TLOGICAL)
           strcat(comm, ": 1-byte LOGICAL");
        else if (datatype == TSHORT)
           strcat(comm, ": 2-byte INTEGER");
        else if (datatype == TUSHORT)
           strcat(comm, ": 2-byte INTEGER");
        else if (datatype == TLONG)
           strcat(comm, ": 4-byte INTEGER");
        else if (datatype == TLONGLONG)
           strcat(comm, ": 8-byte INTEGER");
        else if (datatype == TULONG)
           strcat(comm, ": 4-byte INTEGER");
        else if (datatype == TFLOAT)
           strcat(comm, ": 4-byte REAL");
        else if (datatype == TDOUBLE)
           strcat(comm, ": 8-byte DOUBLE");
        else if (datatype == TCOMPLEX)
           strcat(comm, ": COMPLEX");
        else if (datatype == TDBLCOMPLEX)
           strcat(comm, ": DOUBLE COMPLEX");
        else if (datatype < 0)
           strcat(comm, ": variable length array");

        if (abs(datatype) == TSBYTE) /* signed bytes */
        {
           /* Replace the 'S' with an 'B' in the TFORMn code */
           cptr = tfmt;
           while (*cptr != 'S') 
              cptr++;

           *cptr = 'B';
           ffpkys(fptr, name, tfmt, comm, status);

           /* write the TZEROn and TSCALn keywords */
           ffkeyn("TZERO", ii + 1, name, status);
           strcpy(comm, "offset for signed bytes");

           ffpkyg(fptr, name, -128., 0, comm, status);

           ffkeyn("TSCAL", ii + 1, name, status);
           strcpy(comm, "data are not scaled");
           ffpkyg(fptr, name, 1., 0, comm, status);
        }
        else if (abs(datatype) == TUSHORT) 
        {
           /* Replace the 'U' with an 'I' in the TFORMn code */
           cptr = tfmt;
           while (*cptr != 'U') 
              cptr++;

           *cptr = 'I';
           ffpkys(fptr, name, tfmt, comm, status);

           /* write the TZEROn and TSCALn keywords */
           ffkeyn("TZERO", ii + 1, name, status);
           strcpy(comm, "offset for unsigned integers");

           ffpkyg(fptr, name, 32768., 0, comm, status);

           ffkeyn("TSCAL", ii + 1, name, status);
           strcpy(comm, "data are not scaled");
           ffpkyg(fptr, name, 1., 0, comm, status);
        }
        else if (abs(datatype) == TULONG) 
        {
           /* Replace the 'V' with an 'J' in the TFORMn code */
           cptr = tfmt;
           while (*cptr != 'V') 
              cptr++;

           *cptr = 'J';
           ffpkys(fptr, name, tfmt, comm, status);

           /* write the TZEROn and TSCALn keywords */
           ffkeyn("TZERO", ii + 1, name, status);
           strcpy(comm, "offset for unsigned integers");

           ffpkyg(fptr, name, 2147483648., 0, comm, status);

           ffkeyn("TSCAL", ii + 1, name, status);
           strcpy(comm, "data are not scaled");
           ffpkyg(fptr, name, 1., 0, comm, status);
        }
        else
        {
           ffpkys(fptr, name, tfmt, comm, status);
        }

        if (tunit)
        {
         if (tunit[ii] && *(tunit[ii]) ) /* optional TUNITn keyword */
         {
          ffkeyn("TUNIT", ii + 1, name, status);
          ffpkys(fptr, name, tunit[ii],
             "physical unit of field", status);
         }
        }

        if (*status > 0)
            break;       /* abort loop on error */
    }

    if (extnm[0])       /* optional EXTNAME keyword */
        ffpkys(fptr, "EXTNAME", extnm,
               "name of this binary table extension", status);

    if (*status > 0)
        ffpmsg("Failed to write binary table header keywords (ffphbn)");

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffphext(fitsfile *fptr,  /* I - FITS file pointer                       */
           const char *xtensionx,   /* I - value for the XTENSION keyword          */
           int bitpix,       /* I - value for the BIXPIX keyword            */
           int naxis,        /* I - value for the NAXIS keyword             */
           long naxes[],     /* I - value for the NAXISn keywords           */
           LONGLONG pcount,  /* I - value for the PCOUNT keyword            */
           LONGLONG gcount,  /* I - value for the GCOUNT keyword            */
           int *status)      /* IO - error status                           */
/*
  Put required Header keywords into a conforming extension:
*/
{
    char message[FLEN_ERRMSG],comm[81], name[20], xtension[FLEN_VALUE];
    int ii;
 
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    if (*status > 0)
        return(*status);
    else if ((fptr->Fptr)->headend != (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] )
        return(*status = HEADER_NOT_EMPTY);

    if (naxis < 0 || naxis > 999)
    {
        snprintf(message,FLEN_ERRMSG,
        "Illegal value for NAXIS keyword: %d", naxis);
        ffpmsg(message);
        return(*status = BAD_NAXIS);
    }

    xtension[0] = '\0';
    strncat(xtension, xtensionx, FLEN_VALUE-1);

    ffpkys(fptr, "XTENSION", xtension, "extension type", status);
    ffpkyj(fptr, "BITPIX",   bitpix,   "number of bits per data pixel", status);
    ffpkyj(fptr, "NAXIS",    naxis,    "number of data axes", status);

    strcpy(comm, "length of data axis ");
    for (ii = 0; ii < naxis; ii++)
    {
        if (naxes[ii] < 0)
        {
            snprintf(message,FLEN_ERRMSG,
            "Illegal negative value for NAXIS%d keyword: %.0f", ii + 1, (double) (naxes[ii]));
            ffpmsg(message);
            return(*status = BAD_NAXES);
        }

        snprintf(&comm[20], 61, "%d", ii + 1);
        ffkeyn("NAXIS", ii + 1, name, status);
        ffpkyj(fptr, name, naxes[ii], comm, status);
    }


    ffpkyj(fptr, "PCOUNT", pcount, " ", status);
    ffpkyj(fptr, "GCOUNT", gcount, " ", status);

    if (*status > 0)
        ffpmsg("Failed to write extension header keywords (ffphext)");

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffi2c(LONGLONG ival,  /* I - value to be converted to a string */
          char *cval,     /* O - character string representation of the value */
          int *status)    /* IO - error status */
/*
  convert  value to a null-terminated formatted string.
*/
{
    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    cval[0] = '\0';

#if defined(_MSC_VER)
    /* Microsoft Visual C++ 6.0 uses '%I64d' syntax  for 8-byte integers */
    if (sprintf(cval, "%I64d", ival) < 0)

#elif (USE_LL_SUFFIX == 1)
    if (sprintf(cval, "%lld", ival) < 0)
#else
    if (sprintf(cval, "%ld", ival) < 0)
#endif
    {
        ffpmsg("Error in ffi2c converting integer to string");
        *status = BAD_I2C;
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffl2c(int lval,    /* I - value to be converted to a string */
          char *cval,  /* O - character string representation of the value */
          int *status) /* IO - error status ) */
/*
  convert logical value to a null-terminated formatted string.  If the
  input value == 0, then the output character is the letter F, else
  the output character is the letter T.  The output string is null terminated.
*/
{
    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (lval)
        strcpy(cval,"T");
    else
        strcpy(cval,"F");

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffs2c(const char *instr, /* I - null terminated input string  */
          char *outstr,      /* O - null terminated quoted output string */
          int *status)       /* IO - error status */
/*
  convert an input string to a quoted string. Leading spaces 
  are significant.  FITS string keyword values must be at least 
  8 chars long so pad out string with spaces if necessary.
      Example:   km/s ==> 'km/s    '
  Single quote characters in the input string will be replace by
  two single quote characters. e.g., o'brian ==> 'o''brian'
*/
{
    size_t len, ii, jj;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (!instr)            /* a null input pointer?? */
    {
       strcpy(outstr, "''");   /* a null FITS string */
       return(*status);
    }

    outstr[0] = '\'';      /* start output string with a quote */

    len = strlen(instr);
    if (len > 68)
        len = 68;    /* limit input string to 68 chars */

    for (ii=0, jj=1; ii < len && jj < 69; ii++, jj++)
    {
        outstr[jj] = instr[ii];  /* copy each char from input to output */
        if (instr[ii] == '\'')
        {
            jj++;
            outstr[jj]='\'';   /* duplicate any apostrophies in the input */
        }
    }

    for (; jj < 9; jj++)       /* pad string so it is at least 8 chars long */
        outstr[jj] = ' ';

    if (jj == 70)   /* only occurs if the last char of string was a quote */
        outstr[69] = '\0';
    else
    {
        outstr[jj] = '\'';         /* append closing quote character */
        outstr[jj+1] = '\0';          /* terminate the string */
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffr2f(float fval,   /* I - value to be converted to a string */
          int  decim,   /* I - number of decimal places to display */
          char *cval,   /* O - character string representation of the value */
          int  *status) /* IO - error status */
/*
  convert float value to a null-terminated F format string
*/
{
    char *cptr;
        
    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    cval[0] = '\0';

    if (decim < 0)
    {
        ffpmsg("Error in ffr2f:  no. of decimal places < 0");
        return(*status = BAD_DECIM);
    }

    if (sprintf(cval, "%.*f", decim, fval) < 0)
    {
        ffpmsg("Error in ffr2f converting float to string");
        *status = BAD_F2C;
    }

    /* replace comma with a period (e.g. in French locale) */
    if ( (cptr = strchr(cval, ','))) *cptr = '.';

    /* test if output string is 'NaN', 'INDEF', or 'INF' */
    if (strchr(cval, 'N'))
    {
        ffpmsg("Error in ffr2f: float value is a NaN or INDEF");
        *status = BAD_F2C;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffr2e(float fval,  /* I - value to be converted to a string */
         int decim,    /* I - number of decimal places to display */
         char *cval,   /* O - character string representation of the value */
         int *status)  /* IO - error status */
/*
  convert float value to a null-terminated exponential format string
*/
{
    char *cptr;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    cval[0] = '\0';

    if (decim < 0)
    {   /* use G format if decim is negative */
        if ( sprintf(cval, "%.*G", -decim, fval) < 0)
        {
            ffpmsg("Error in ffr2e converting float to string");
            *status = BAD_F2C;
        }
        else
        {
            /* test if E format was used, and there is no displayed decimal */
            if ( !strchr(cval, '.') && strchr(cval,'E') )
            {
                /* reformat value with a decimal point and single zero */
                if ( sprintf(cval, "%.1E", fval) < 0)
                {
                    ffpmsg("Error in ffr2e converting float to string");
                    *status = BAD_F2C;
                }

                return(*status);  
            }
        }
    }
    else
    {
        if ( sprintf(cval, "%.*E", decim, fval) < 0)
        {
            ffpmsg("Error in ffr2e converting float to string");
            *status = BAD_F2C;
        }
    }

    if (*status <= 0)
    {
        /* replace comma with a period (e.g. in French locale) */
        if ( (cptr = strchr(cval, ','))) *cptr = '.';

        /* test if output string is 'NaN', 'INDEF', or 'INF' */
        if (strchr(cval, 'N'))
        {
            ffpmsg("Error in ffr2e: float value is a NaN or INDEF");
            *status = BAD_F2C;
        }
        else if ( !strchr(cval, '.') && !strchr(cval,'E') )
        {
            /* add decimal point if necessary to distinquish from integer */
            strcat(cval, ".");
        }
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffd2f(double dval,  /* I - value to be converted to a string */
          int decim,    /* I - number of decimal places to display */
          char *cval,   /* O - character string representation of the value */
          int *status)  /* IO - error status */
/*
  convert double value to a null-terminated F format string
*/
{
    char *cptr;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    cval[0] = '\0';

    if (decim < 0)
    {
        ffpmsg("Error in ffd2f:  no. of decimal places < 0");
        return(*status = BAD_DECIM);
    }

    if (sprintf(cval, "%.*f", decim, dval) < 0)
    {
        ffpmsg("Error in ffd2f converting double to string");
        *status = BAD_F2C;
    }

    /* replace comma with a period (e.g. in French locale) */
    if ( (cptr = strchr(cval, ','))) *cptr = '.';

    /* test if output string is 'NaN', 'INDEF', or 'INF' */
    if (strchr(cval, 'N'))
    {
        ffpmsg("Error in ffd2f: double value is a NaN or INDEF");
        *status = BAD_F2C;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffd2e(double dval,  /* I - value to be converted to a string */
          int decim,    /* I - number of decimal places to display */
          char *cval,   /* O - character string representation of the value */
          int *status)  /* IO - error status */
/*
  convert double value to a null-terminated exponential format string.
*/
{
    char *cptr;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    cval[0] = '\0';

    if (decim < 0)
    {   /* use G format if decim is negative */
        if ( sprintf(cval, "%.*G", -decim, dval) < 0)
        {
            ffpmsg("Error in ffd2e converting float to string");
            *status = BAD_F2C;
        }
        else
        {
            /* test if E format was used, and there is no displayed decimal */
            if ( !strchr(cval, '.') && strchr(cval,'E') )
            {
                /* reformat value with a decimal point and single zero */
                if ( sprintf(cval, "%.1E", dval) < 0)
                {
                    ffpmsg("Error in ffd2e converting float to string");
                    *status = BAD_F2C;
                }

                return(*status);  
            }
        }
    }
    else
    {
        if ( sprintf(cval, "%.*E", decim, dval) < 0)
        {
            ffpmsg("Error in ffd2e converting float to string");
            *status = BAD_F2C;
        }
    }

    if (*status <= 0)
    {
        /* replace comma with a period (e.g. in French locale) */
        if ( (cptr = strchr(cval, ','))) *cptr = '.';

        /* test if output string is 'NaN', 'INDEF', or 'INF' */
        if (strchr(cval, 'N'))
        {
            ffpmsg("Error in ffd2e: double value is a NaN or INDEF");
            *status = BAD_F2C;
        }
        else if ( !strchr(cval, '.') && !strchr(cval,'E') )
        {
            /* add decimal point if necessary to distinquish from integer */
            strcat(cval, ".");
        }
    }

    return(*status);
}

cfitsio/quantize.c0000644000225700000360000035031113246025103014007 0ustar  cagordonlhea/*
  The following code is based on algorithms written by Richard White at STScI and made
  available for use in CFITSIO in July 1999 and updated in January 2008. 
*/

# include 
# include 
# include 
# include 
# include 

#include "fitsio2.h"

/* nearest integer function */
# define NINT(x)  ((x >= 0.) ? (int) (x + 0.5) : (int) (x - 0.5))

#define NULL_VALUE -2147483647 /* value used to represent undefined pixels */
#define ZERO_VALUE -2147483646 /* value used to represent zero-valued pixels */
#define N_RESERVED_VALUES 10   /* number of reserved values, starting with */
                               /* and including NULL_VALUE.  These values */
                               /* may not be used to represent the quantized */
                               /* and scaled floating point pixel values */
			       /* If lossy Hcompression is used, and the */
			       /* array contains null values, then it is also */
			       /* possible for the compressed values to slightly */
			       /* exceed the range of the actual (lossless) values */
			       /* so we must reserve a little more space */
			       
/* more than this many standard deviations from the mean is an outlier */
# define SIGMA_CLIP     5.
# define NITER          3	/* number of sigma-clipping iterations */

static int FnMeanSigma_short(short *array, long npix, int nullcheck, 
  short nullvalue, long *ngoodpix, double *mean, double *sigma, int *status);       
static int FnMeanSigma_int(int *array, long npix, int nullcheck,
  int nullvalue, long *ngoodpix, double *mean, double *sigma, int *status);       
static int FnMeanSigma_float(float *array, long npix, int nullcheck,
  float nullvalue, long *ngoodpix, double *mean, double *sigma, int *status);       
static int FnMeanSigma_double(double *array, long npix, int nullcheck,
  double nullvalue, long *ngoodpix, double *mean, double *sigma, int *status);       

static int FnNoise5_short(short *array, long nx, long ny, int nullcheck, 
   short nullvalue, long *ngood, short *minval, short *maxval, 
   double *n2, double *n3, double *n5, int *status);   
static int FnNoise5_int(int *array, long nx, long ny, int nullcheck, 
   int nullvalue, long *ngood, int *minval, int *maxval, 
   double *n2, double *n3, double *n5, int *status);   
static int FnNoise5_float(float *array, long nx, long ny, int nullcheck, 
   float nullvalue, long *ngood, float *minval, float *maxval, 
   double *n2, double *n3, double *n5, int *status);   
static int FnNoise5_double(double *array, long nx, long ny, int nullcheck, 
   double nullvalue, long *ngood, double *minval, double *maxval, 
   double *n2, double *n3, double *n5, int *status);   

static int FnNoise3_short(short *array, long nx, long ny, int nullcheck, 
   short nullvalue, long *ngood, short *minval, short *maxval, double *noise, int *status);       
static int FnNoise3_int(int *array, long nx, long ny, int nullcheck, 
   int nullvalue, long *ngood, int *minval, int *maxval, double *noise, int *status);          
static int FnNoise3_float(float *array, long nx, long ny, int nullcheck, 
   float nullvalue, long *ngood, float *minval, float *maxval, double *noise, int *status);        
static int FnNoise3_double(double *array, long nx, long ny, int nullcheck, 
   double nullvalue, long *ngood, double *minval, double *maxval, double *noise, int *status);        

static int FnNoise1_short(short *array, long nx, long ny, 
   int nullcheck, short nullvalue, double *noise, int *status);       
static int FnNoise1_int(int *array, long nx, long ny, 
   int nullcheck, int nullvalue, double *noise, int *status);       
static int FnNoise1_float(float *array, long nx, long ny, 
   int nullcheck, float nullvalue, double *noise, int *status);       
static int FnNoise1_double(double *array, long nx, long ny, 
   int nullcheck, double nullvalue, double *noise, int *status);       

static int FnCompare_short (const void *, const void *);
static int FnCompare_int (const void *, const void *);
static int FnCompare_float (const void *, const void *);
static int FnCompare_double (const void *, const void *);
static float quick_select_float(float arr[], int n);
static short quick_select_short(short arr[], int n);
static int quick_select_int(int arr[], int n);
static LONGLONG quick_select_longlong(LONGLONG arr[], int n);
static double quick_select_double(double arr[], int n);

/*---------------------------------------------------------------------------*/
int fits_quantize_float (long row, float fdata[], long nxpix, long nypix, int nullcheck, 
	float in_null_value, float qlevel, int dither_method, int idata[], double *bscale,
	double *bzero, int *iminval, int *imaxval) {

/* arguments:
long row            i: if positive, used to calculate random dithering seed value
                       (this is only used when dithering the quantized values)
float fdata[]       i: array of image pixels to be compressed
long nxpix          i: number of pixels in each row of fdata
long nypix          i: number of rows in fdata
nullcheck           i: check for nullvalues in fdata?
float in_null_value i: value used to represent undefined pixels in fdata
float qlevel        i: quantization level
int dither_method   i; which dithering method to use
int idata[]         o: values of fdata after applying bzero and bscale
double bscale       o: scale factor
double bzero        o: zero offset
int iminval         o: minimum quantized value that is returned
int imaxval         o: maximum quantized value that is returned

The function value will be one if the input fdata were copied to idata;
in this case the parameters bscale and bzero can be used to convert back to
nearly the original floating point values:  fdata ~= idata * bscale + bzero.
If the function value is zero, the data were not copied to idata.
*/

	int status, iseed = 0;
	long i, nx, ngood = 0;
	double stdev, noise2, noise3, noise5;	/* MAD 2nd, 3rd, and 5th order noise values */
	float minval = 0., maxval = 0.;  /* min & max of fdata */
	double delta;		/* bscale, 1 in idata = delta in fdata */
	double zeropt;	        /* bzero */
	double temp;
        int nextrand = 0;
	extern float *fits_rand_value; /* this is defined in imcompress.c */
	LONGLONG iqfactor;

	nx = nxpix * nypix;
	if (nx <= 1) {
	    *bscale = 1.;
	    *bzero  = 0.;
	    return (0);
	}

        if (qlevel >= 0.) {

	    /* estimate background noise using MAD pixel differences */
	    FnNoise5_float(fdata, nxpix, nypix, nullcheck, in_null_value, &ngood,
	        &minval, &maxval, &noise2, &noise3, &noise5, &status);      

	    if (nullcheck && ngood == 0) {   /* special case of an image filled with Nulls */
	        /* set parameters to dummy values, which are not used */
		minval = 0.;
		maxval = 1.;
		stdev = 1;
	    } else {

	        /* use the minimum of noise2, noise3, and noise5 as the best noise value */
	        stdev = noise3;
	        if (noise2 != 0. && noise2 < stdev) stdev = noise2;
	        if (noise5 != 0. && noise5 < stdev) stdev = noise5;
            }

	    if (qlevel == 0.)
	        delta = stdev / 4.;  /* default quantization */
	    else
	        delta = stdev / qlevel;

	    if (delta == 0.) 
	        return (0);			/* don't quantize */

	} else {
	    /* negative value represents the absolute quantization level */
	    delta = -qlevel;

	    /* only nned to calculate the min and max values */
	    FnNoise3_float(fdata, nxpix, nypix, nullcheck, in_null_value, &ngood,
	        &minval, &maxval, 0, &status);      
 	}

        /* check that the range of quantized levels is not > range of int */
	if ((maxval - minval) / delta > 2. * 2147483647. - N_RESERVED_VALUES )
	    return (0);			/* don't quantize */

        if (row > 0) { /* we need to dither the quantized values */
            if (!fits_rand_value) 
	        if (fits_init_randoms()) return(MEMORY_ALLOCATION);

	    /* initialize the index to the next random number in the list */
            iseed = (int) ((row - 1) % N_RANDOM);
	    nextrand = (int) (fits_rand_value[iseed] * 500.);
	}

        if (ngood == nx) {   /* don't have to check for nulls */
            /* return all positive values, if possible since some */
            /* compression algorithms either only work for positive integers, */
            /* or are more efficient.  */

            if (dither_method == SUBTRACTIVE_DITHER_2)
	    {
                /* shift the range to be close to the value used to represent zeros */
                zeropt = minval - delta * (NULL_VALUE + N_RESERVED_VALUES);
            }
	    else if ((maxval - minval) / delta < 2147483647. - N_RESERVED_VALUES )
            {
                zeropt = minval;
		/* fudge the zero point so it is an integer multiple of delta */
		/* This helps to ensure the same scaling will be performed if the */
		/* file undergoes multiple fpack/funpack cycles */
		iqfactor = (LONGLONG) (zeropt/delta  + 0.5);
		zeropt = iqfactor * delta;               
            }
            else
            {
                /* center the quantized levels around zero */
                zeropt = (minval + maxval) / 2.;
            }

            if (row > 0) {  /* dither the values when quantizing */
              for (i = 0;  i < nx;  i++) {
	    
		if (dither_method == SUBTRACTIVE_DITHER_2 && fdata[i] == 0.0) {
		   idata[i] = ZERO_VALUE;
		} else {
		   idata[i] =  NINT((((double) fdata[i] - zeropt) / delta) + fits_rand_value[nextrand] - 0.5);
		}

                nextrand++;
		if (nextrand == N_RANDOM) {
		    iseed++;
		    if (iseed == N_RANDOM) iseed = 0;
	            nextrand = (int) (fits_rand_value[iseed] * 500);
                }
              }
            } else {  /* do not dither the values */

       	        for (i = 0;  i < nx;  i++) {
	            idata[i] = NINT ((fdata[i] - zeropt) / delta);
                }
            } 
        }
        else {
            /* data contains null values; shift the range to be */
            /* close to the value used to represent null values */
            zeropt = minval - delta * (NULL_VALUE + N_RESERVED_VALUES);

            if (row > 0) {  /* dither the values */
	      for (i = 0;  i < nx;  i++) {
                if (fdata[i] != in_null_value) {
		    if (dither_method == SUBTRACTIVE_DITHER_2 && fdata[i] == 0.0) {
		       idata[i] = ZERO_VALUE;
		    } else {
		       idata[i] =  NINT((((double) fdata[i] - zeropt) / delta) + fits_rand_value[nextrand] - 0.5);
		    }
                } else {
                    idata[i] = NULL_VALUE;
                }

                /* increment the random number index, regardless */
                nextrand++;
		if (nextrand == N_RANDOM) {
		    iseed++;
		    if (iseed == N_RANDOM) iseed = 0;
	            nextrand = (int) (fits_rand_value[iseed] * 500);
                }
              }
            } else {  /* do not dither the values */
	       for (i = 0;  i < nx;  i++) {
 
                 if (fdata[i] != in_null_value) {
		    idata[i] =  NINT((fdata[i] - zeropt) / delta);
                 } else { 
                    idata[i] = NULL_VALUE;
                 }
               }
            }
	}

        /* calc min and max values */
        temp = (minval - zeropt) / delta;
        *iminval =  NINT (temp);
        temp = (maxval - zeropt) / delta;
        *imaxval =  NINT (temp);

	*bscale = delta;
	*bzero = zeropt;
	return (1);			/* yes, data have been quantized */
}
/*---------------------------------------------------------------------------*/
int fits_quantize_double (long row, double fdata[], long nxpix, long nypix, int nullcheck, 
	double in_null_value, float qlevel, int dither_method, int idata[], double *bscale,
	double *bzero, int *iminval, int *imaxval) {

/* arguments:
long row            i: tile number = row number in the binary table
                       (this is only used when dithering the quantized values)
double fdata[]      i: array of image pixels to be compressed
long nxpix          i: number of pixels in each row of fdata
long nypix          i: number of rows in fdata
nullcheck           i: check for nullvalues in fdata?
double in_null_value i: value used to represent undefined pixels in fdata
float qlevel        i: quantization level
int dither_method   i; which dithering method to use
int idata[]         o: values of fdata after applying bzero and bscale
double bscale       o: scale factor
double bzero        o: zero offset
int iminval         o: minimum quantized value that is returned
int imaxval         o: maximum quantized value that is returned

The function value will be one if the input fdata were copied to idata;
in this case the parameters bscale and bzero can be used to convert back to
nearly the original floating point values:  fdata ~= idata * bscale + bzero.
If the function value is zero, the data were not copied to idata.
*/

	int status, iseed = 0;
	long i, nx, ngood = 0;
	double stdev, noise2 = 0., noise3 = 0., noise5 = 0.;	/* MAD 2nd, 3rd, and 5th order noise values */
	double minval = 0., maxval = 0.;  /* min & max of fdata */
	double delta;		/* bscale, 1 in idata = delta in fdata */
	double zeropt;	        /* bzero */
	double temp;
        int nextrand = 0;
	extern float *fits_rand_value;
	LONGLONG iqfactor;

	nx = nxpix * nypix;
	if (nx <= 1) {
	    *bscale = 1.;
	    *bzero  = 0.;
	    return (0);
	}

        if (qlevel >= 0.) {

	    /* estimate background noise using MAD pixel differences */
	    FnNoise5_double(fdata, nxpix, nypix, nullcheck, in_null_value, &ngood,
	        &minval, &maxval, &noise2, &noise3, &noise5, &status);      

	    if (nullcheck && ngood == 0) {   /* special case of an image filled with Nulls */
	        /* set parameters to dummy values, which are not used */
		minval = 0.;
		maxval = 1.;
		stdev = 1;
	    } else {

	        /* use the minimum of noise2, noise3, and noise5 as the best noise value */
	        stdev = noise3;
	        if (noise2 != 0. && noise2 < stdev) stdev = noise2;
	        if (noise5 != 0. && noise5 < stdev) stdev = noise5;
            }

	    if (qlevel == 0.)
	        delta = stdev / 4.;  /* default quantization */
	    else
	        delta = stdev / qlevel;

	    if (delta == 0.) 
	        return (0);			/* don't quantize */

	} else {
	    /* negative value represents the absolute quantization level */
	    delta = -qlevel;

	    /* only nned to calculate the min and max values */
	    FnNoise3_double(fdata, nxpix, nypix, nullcheck, in_null_value, &ngood,
	        &minval, &maxval, 0, &status);      
 	}

        /* check that the range of quantized levels is not > range of int */
	if ((maxval - minval) / delta > 2. * 2147483647. - N_RESERVED_VALUES )
	    return (0);			/* don't quantize */

        if (row > 0) { /* we need to dither the quantized values */
            if (!fits_rand_value) 
	       if (fits_init_randoms()) return(MEMORY_ALLOCATION);

	    /* initialize the index to the next random number in the list */
            iseed = (int) ((row - 1) % N_RANDOM);
	    nextrand = (int) (fits_rand_value[iseed] * 500);
	}

        if (ngood == nx) {   /* don't have to check for nulls */
            /* return all positive values, if possible since some */
            /* compression algorithms either only work for positive integers, */
            /* or are more efficient.  */

            if (dither_method == SUBTRACTIVE_DITHER_2)
	    {
                /* shift the range to be close to the value used to represent zeros */
                zeropt = minval - delta * (NULL_VALUE + N_RESERVED_VALUES);
            }
	    else if ((maxval - minval) / delta < 2147483647. - N_RESERVED_VALUES )
            {
                zeropt = minval;
		/* fudge the zero point so it is an integer multiple of delta */
		/* This helps to ensure the same scaling will be performed if the */
		/* file undergoes multiple fpack/funpack cycles */
		iqfactor = (LONGLONG) (zeropt/delta  + 0.5);
		zeropt = iqfactor * delta;               
            }
            else
            {
                /* center the quantized levels around zero */
                zeropt = (minval + maxval) / 2.;
            }

            if (row > 0) {  /* dither the values when quantizing */
       	      for (i = 0;  i < nx;  i++) {

		if (dither_method == SUBTRACTIVE_DITHER_2 && fdata[i] == 0.0) {
		   idata[i] = ZERO_VALUE;
		} else {
		   idata[i] =  NINT((((double) fdata[i] - zeropt) / delta) + fits_rand_value[nextrand] - 0.5);
		}

                nextrand++;
		if (nextrand == N_RANDOM) {
                    iseed++;
		    if (iseed == N_RANDOM) iseed = 0;
	            nextrand = (int) (fits_rand_value[iseed] * 500);
                }
              }
            } else {  /* do not dither the values */

       	        for (i = 0;  i < nx;  i++) {
	            idata[i] = NINT ((fdata[i] - zeropt) / delta);
                }
            } 
        }
        else {
            /* data contains null values; shift the range to be */
            /* close to the value used to represent null values */
            zeropt = minval - delta * (NULL_VALUE + N_RESERVED_VALUES);

            if (row > 0) {  /* dither the values */
	      for (i = 0;  i < nx;  i++) {
                if (fdata[i] != in_null_value) {
		    if (dither_method == SUBTRACTIVE_DITHER_2 && fdata[i] == 0.0) {
		       idata[i] = ZERO_VALUE;
		    } else {
		       idata[i] =  NINT((((double) fdata[i] - zeropt) / delta) + fits_rand_value[nextrand] - 0.5);
		    }
                } else {
                    idata[i] = NULL_VALUE;
                }

                /* increment the random number index, regardless */
                nextrand++;
		if (nextrand == N_RANDOM) {
		    iseed++;
		    if (iseed == N_RANDOM) iseed = 0;
	            nextrand = (int) (fits_rand_value[iseed] * 500);
                }
              }
            } else {  /* do not dither the values */
	       for (i = 0;  i < nx;  i++) {
                 if (fdata[i] != in_null_value)
		    idata[i] =  NINT((fdata[i] - zeropt) / delta);
                 else 
                    idata[i] = NULL_VALUE;
               }
            }
	}

        /* calc min and max values */
        temp = (minval - zeropt) / delta;
        *iminval =  NINT (temp);
        temp = (maxval - zeropt) / delta;
        *imaxval =  NINT (temp);

	*bscale = delta;
	*bzero = zeropt;

	return (1);			/* yes, data have been quantized */
}
/*--------------------------------------------------------------------------*/
int fits_img_stats_short(short *array, /*  2 dimensional array of image pixels */
        long nx,            /* number of pixels in each row of the image */
	long ny,            /* number of rows in the image */
	                    /* (if this is a 3D image, then ny should be the */
			    /* product of the no. of rows times the no. of planes) */
	int nullcheck,      /* check for null values, if true */
	short nullvalue,    /* value of null pixels, if nullcheck is true */

   /* returned parameters (if the pointer is not null)  */
	long *ngoodpix,     /* number of non-null pixels in the image */
	short *minvalue,    /* returned minimum non-null value in the array */
	short *maxvalue,    /* returned maximum non-null value in the array */
	double *mean,       /* returned mean value of all non-null pixels */
	double *sigma,      /* returned R.M.S. value of all non-null pixels */
	double *noise1,     /* 1st order estimate of noise in image background level */
	double *noise2,     /* 2nd order estimate of noise in image background level */
	double *noise3,     /* 3rd order estimate of noise in image background level */
	double *noise5,     /* 5th order estimate of noise in image background level */
	int *status)        /* error status */

/*
    Compute statistics of the input short integer image.
*/
{
	long ngood;
	short minval = 0, maxval = 0;
	double xmean = 0., xsigma = 0., xnoise = 0., xnoise2 = 0., xnoise3 = 0., xnoise5 = 0.;

	/* need to calculate mean and/or sigma and/or limits? */
	if (mean || sigma ) {
		FnMeanSigma_short(array, nx * ny, nullcheck, nullvalue, 
			&ngood, &xmean, &xsigma, status);

	    if (ngoodpix) *ngoodpix = ngood;
	    if (mean)     *mean = xmean;
	    if (sigma)    *sigma = xsigma;
	}

	if (noise1) {
		FnNoise1_short(array, nx, ny, nullcheck, nullvalue, 
		  &xnoise, status);

		*noise1  = xnoise;
	}

	if (minvalue || maxvalue || noise3) {
		FnNoise5_short(array, nx, ny, nullcheck, nullvalue, 
			&ngood, &minval, &maxval, &xnoise2, &xnoise3, &xnoise5, status);

		if (ngoodpix) *ngoodpix = ngood;
		if (minvalue) *minvalue= minval;
		if (maxvalue) *maxvalue = maxval;
		if (noise2) *noise2  = xnoise2;
		if (noise3) *noise3  = xnoise3;
		if (noise5) *noise5  = xnoise5;
	}
	return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_img_stats_int(int *array, /*  2 dimensional array of image pixels */
        long nx,            /* number of pixels in each row of the image */
	long ny,            /* number of rows in the image */
	                    /* (if this is a 3D image, then ny should be the */
			    /* product of the no. of rows times the no. of planes) */
	int nullcheck,      /* check for null values, if true */
	int nullvalue,    /* value of null pixels, if nullcheck is true */

   /* returned parameters (if the pointer is not null)  */
	long *ngoodpix,     /* number of non-null pixels in the image */
	int *minvalue,    /* returned minimum non-null value in the array */
	int *maxvalue,    /* returned maximum non-null value in the array */
	double *mean,       /* returned mean value of all non-null pixels */
	double *sigma,      /* returned R.M.S. value of all non-null pixels */
	double *noise1,     /* 1st order estimate of noise in image background level */
	double *noise2,     /* 2nd order estimate of noise in image background level */
	double *noise3,     /* 3rd order estimate of noise in image background level */
	double *noise5,     /* 5th order estimate of noise in image background level */
	int *status)        /* error status */

/*
    Compute statistics of the input integer image.
*/
{
	long ngood;
	int minval = 0, maxval = 0;
	double xmean = 0., xsigma = 0., xnoise = 0., xnoise2 = 0., xnoise3 = 0., xnoise5 = 0.;

	/* need to calculate mean and/or sigma and/or limits? */
	if (mean || sigma ) {
		FnMeanSigma_int(array, nx * ny, nullcheck, nullvalue, 
			&ngood, &xmean, &xsigma, status);

	    if (ngoodpix) *ngoodpix = ngood;
	    if (mean)     *mean = xmean;
	    if (sigma)    *sigma = xsigma;
	}

	if (noise1) {
		FnNoise1_int(array, nx, ny, nullcheck, nullvalue, 
		  &xnoise, status);

		*noise1  = xnoise;
	}

	if (minvalue || maxvalue || noise3) {
		FnNoise5_int(array, nx, ny, nullcheck, nullvalue, 
			&ngood, &minval, &maxval, &xnoise2, &xnoise3, &xnoise5, status);

		if (ngoodpix) *ngoodpix = ngood;
		if (minvalue) *minvalue= minval;
		if (maxvalue) *maxvalue = maxval;
		if (noise2) *noise2  = xnoise2;
		if (noise3) *noise3  = xnoise3;
		if (noise5) *noise5  = xnoise5;
	}
	return(*status);
}
/*--------------------------------------------------------------------------*/
int fits_img_stats_float(float *array, /*  2 dimensional array of image pixels */
        long nx,            /* number of pixels in each row of the image */
	long ny,            /* number of rows in the image */
	                    /* (if this is a 3D image, then ny should be the */
			    /* product of the no. of rows times the no. of planes) */
	int nullcheck,      /* check for null values, if true */
	float nullvalue,    /* value of null pixels, if nullcheck is true */

   /* returned parameters (if the pointer is not null)  */
	long *ngoodpix,     /* number of non-null pixels in the image */
	float *minvalue,    /* returned minimum non-null value in the array */
	float *maxvalue,    /* returned maximum non-null value in the array */
	double *mean,       /* returned mean value of all non-null pixels */
	double *sigma,      /* returned R.M.S. value of all non-null pixels */
	double *noise1,     /* 1st order estimate of noise in image background level */
	double *noise2,     /* 2nd order estimate of noise in image background level */
	double *noise3,     /* 3rd order estimate of noise in image background level */
	double *noise5,     /* 5th order estimate of noise in image background level */
	int *status)        /* error status */

/*
    Compute statistics of the input float image.
*/
{
	long ngood;
	float minval, maxval;
	double xmean = 0., xsigma = 0., xnoise = 0., xnoise2 = 0., xnoise3 = 0., xnoise5 = 0.;

	/* need to calculate mean and/or sigma and/or limits? */
	if (mean || sigma ) {
		FnMeanSigma_float(array, nx * ny, nullcheck, nullvalue, 
			&ngood, &xmean, &xsigma, status);

	    if (ngoodpix) *ngoodpix = ngood;
	    if (mean)     *mean = xmean;
	    if (sigma)    *sigma = xsigma;
	}

	if (noise1) {
		FnNoise1_float(array, nx, ny, nullcheck, nullvalue, 
		  &xnoise, status);

		*noise1  = xnoise;
	}

	if (minvalue || maxvalue || noise3) {
		FnNoise5_float(array, nx, ny, nullcheck, nullvalue, 
			&ngood, &minval, &maxval, &xnoise2, &xnoise3, &xnoise5, status);

		if (ngoodpix) *ngoodpix = ngood;
		if (minvalue) *minvalue= minval;
		if (maxvalue) *maxvalue = maxval;
		if (noise2) *noise2  = xnoise2;
		if (noise3) *noise3  = xnoise3;
		if (noise5) *noise5  = xnoise5;
	}
	return(*status);
}
/*--------------------------------------------------------------------------*/
static int FnMeanSigma_short
       (short *array,       /*  2 dimensional array of image pixels */
        long npix,          /* number of pixels in the image */
	int nullcheck,      /* check for null values, if true */
	short nullvalue,    /* value of null pixels, if nullcheck is true */

   /* returned parameters */
   
	long *ngoodpix,     /* number of non-null pixels in the image */
	double *mean,       /* returned mean value of all non-null pixels */
	double *sigma,      /* returned R.M.S. value of all non-null pixels */
	int *status)        /* error status */

/*
Compute mean and RMS sigma of the non-null pixels in the input array.
*/
{
	long ii, ngood = 0;
	short *value;
	double sum = 0., sum2 = 0., xtemp;

	value = array;
	    
	if (nullcheck) {
	        for (ii = 0; ii < npix; ii++, value++) {
		    if (*value != nullvalue) {
		        ngood++;
		        xtemp = (double) *value;
		        sum += xtemp;
		        sum2 += (xtemp * xtemp);
		    }
		}
	} else {
	        ngood = npix;
	        for (ii = 0; ii < npix; ii++, value++) {
		        xtemp = (double) *value;
		        sum += xtemp;
		        sum2 += (xtemp * xtemp);
		}
	}

	if (ngood > 1) {
		if (ngoodpix) *ngoodpix = ngood;
		xtemp = sum / ngood;
		if (mean)     *mean = xtemp;
		if (sigma)    *sigma = sqrt((sum2 / ngood) - (xtemp * xtemp));
	} else if (ngood == 1){
		if (ngoodpix) *ngoodpix = 1;
		if (mean)     *mean = sum;
		if (sigma)    *sigma = 0.0;
	} else {
		if (ngoodpix) *ngoodpix = 0;
	        if (mean)     *mean = 0.;
		if (sigma)    *sigma = 0.;
	}	    
	return(*status);
}
/*--------------------------------------------------------------------------*/
static int FnMeanSigma_int
       (int *array,       /*  2 dimensional array of image pixels */
        long npix,          /* number of pixels in the image */
	int nullcheck,      /* check for null values, if true */
	int nullvalue,    /* value of null pixels, if nullcheck is true */

   /* returned parameters */
   
	long *ngoodpix,     /* number of non-null pixels in the image */
	double *mean,       /* returned mean value of all non-null pixels */
	double *sigma,      /* returned R.M.S. value of all non-null pixels */
	int *status)        /* error status */

/*
Compute mean and RMS sigma of the non-null pixels in the input array.
*/
{
	long ii, ngood = 0;
	int *value;
	double sum = 0., sum2 = 0., xtemp;

	value = array;
	    
	if (nullcheck) {
	        for (ii = 0; ii < npix; ii++, value++) {
		    if (*value != nullvalue) {
		        ngood++;
		        xtemp = (double) *value;
		        sum += xtemp;
		        sum2 += (xtemp * xtemp);
		    }
		}
	} else {
	        ngood = npix;
	        for (ii = 0; ii < npix; ii++, value++) {
		        xtemp = (double) *value;
		        sum += xtemp;
		        sum2 += (xtemp * xtemp);
		}
	}

	if (ngood > 1) {
		if (ngoodpix) *ngoodpix = ngood;
		xtemp = sum / ngood;
		if (mean)     *mean = xtemp;
		if (sigma)    *sigma = sqrt((sum2 / ngood) - (xtemp * xtemp));
	} else if (ngood == 1){
		if (ngoodpix) *ngoodpix = 1;
		if (mean)     *mean = sum;
		if (sigma)    *sigma = 0.0;
	} else {
		if (ngoodpix) *ngoodpix = 0;
	        if (mean)     *mean = 0.;
		if (sigma)    *sigma = 0.;
	}	    
	return(*status);
}
/*--------------------------------------------------------------------------*/
static int FnMeanSigma_float
       (float *array,       /*  2 dimensional array of image pixels */
        long npix,          /* number of pixels in the image */
	int nullcheck,      /* check for null values, if true */
	float nullvalue,    /* value of null pixels, if nullcheck is true */

   /* returned parameters */
   
	long *ngoodpix,     /* number of non-null pixels in the image */
	double *mean,       /* returned mean value of all non-null pixels */
	double *sigma,      /* returned R.M.S. value of all non-null pixels */
	int *status)        /* error status */

/*
Compute mean and RMS sigma of the non-null pixels in the input array.
*/
{
	long ii, ngood = 0;
	float *value;
	double sum = 0., sum2 = 0., xtemp;

	value = array;
	    
	if (nullcheck) {
	        for (ii = 0; ii < npix; ii++, value++) {
		    if (*value != nullvalue) {
		        ngood++;
		        xtemp = (double) *value;
		        sum += xtemp;
		        sum2 += (xtemp * xtemp);
		    }
		}
	} else {
	        ngood = npix;
	        for (ii = 0; ii < npix; ii++, value++) {
		        xtemp = (double) *value;
		        sum += xtemp;
		        sum2 += (xtemp * xtemp);
		}
	}

	if (ngood > 1) {
		if (ngoodpix) *ngoodpix = ngood;
		xtemp = sum / ngood;
		if (mean)     *mean = xtemp;
		if (sigma)    *sigma = sqrt((sum2 / ngood) - (xtemp * xtemp));
	} else if (ngood == 1){
		if (ngoodpix) *ngoodpix = 1;
		if (mean)     *mean = sum;
		if (sigma)    *sigma = 0.0;
	} else {
		if (ngoodpix) *ngoodpix = 0;
	        if (mean)     *mean = 0.;
		if (sigma)    *sigma = 0.;
	}	    
	return(*status);
}
/*--------------------------------------------------------------------------*/
static int FnMeanSigma_double
       (double *array,       /*  2 dimensional array of image pixels */
        long npix,          /* number of pixels in the image */
	int nullcheck,      /* check for null values, if true */
	double nullvalue,    /* value of null pixels, if nullcheck is true */

   /* returned parameters */
   
	long *ngoodpix,     /* number of non-null pixels in the image */
	double *mean,       /* returned mean value of all non-null pixels */
	double *sigma,      /* returned R.M.S. value of all non-null pixels */
	int *status)        /* error status */

/*
Compute mean and RMS sigma of the non-null pixels in the input array.
*/
{
	long ii, ngood = 0;
	double *value;
	double sum = 0., sum2 = 0., xtemp;

	value = array;
	    
	if (nullcheck) {
	        for (ii = 0; ii < npix; ii++, value++) {
		    if (*value != nullvalue) {
		        ngood++;
		        xtemp = *value;
		        sum += xtemp;
		        sum2 += (xtemp * xtemp);
		    }
		}
	} else {
	        ngood = npix;
	        for (ii = 0; ii < npix; ii++, value++) {
		        xtemp = *value;
		        sum += xtemp;
		        sum2 += (xtemp * xtemp);
		}
	}

	if (ngood > 1) {
		if (ngoodpix) *ngoodpix = ngood;
		xtemp = sum / ngood;
		if (mean)     *mean = xtemp;
		if (sigma)    *sigma = sqrt((sum2 / ngood) - (xtemp * xtemp));
	} else if (ngood == 1){
		if (ngoodpix) *ngoodpix = 1;
		if (mean)     *mean = sum;
		if (sigma)    *sigma = 0.0;
	} else {
		if (ngoodpix) *ngoodpix = 0;
	        if (mean)     *mean = 0.;
		if (sigma)    *sigma = 0.;
	}	    
	return(*status);
}
/*--------------------------------------------------------------------------*/
static int FnNoise5_short
       (short *array,       /*  2 dimensional array of image pixels */
        long nx,            /* number of pixels in each row of the image */
        long ny,            /* number of rows in the image */
	int nullcheck,      /* check for null values, if true */
	short nullvalue,    /* value of null pixels, if nullcheck is true */
   /* returned parameters */   
	long *ngood,        /* number of good, non-null pixels? */
	short *minval,    /* minimum non-null value */
	short *maxval,    /* maximum non-null value */
	double *noise2,      /* returned 2nd order MAD of all non-null pixels */
	double *noise3,      /* returned 3rd order MAD of all non-null pixels */
	double *noise5,      /* returned 5th order MAD of all non-null pixels */
	int *status)        /* error status */

/*
Estimate the median and background noise in the input image using 2nd, 3rd and 5th
order Median Absolute Differences.

The noise in the background of the image is calculated using the MAD algorithms 
developed for deriving the signal to noise ratio in spectra
(see issue #42 of the ST-ECF newsletter, http://www.stecf.org/documents/newsletter/)

3rd order:  noise = 1.482602 / sqrt(6) * median (abs(2*flux(i) - flux(i-2) - flux(i+2)))

The returned estimates are the median of the values that are computed for each 
row of the image.
*/
{
	long ii, jj, nrows = 0, nrows2 = 0, nvals, nvals2, ngoodpix = 0;
	int *differences2, *differences3, *differences5;
	short *rowpix, v1, v2, v3, v4, v5, v6, v7, v8, v9;
	short xminval = SHRT_MAX, xmaxval = SHRT_MIN;
	int do_range = 0;
	double *diffs2, *diffs3, *diffs5; 
	double xnoise2 = 0, xnoise3 = 0, xnoise5 = 0;
	
	if (nx < 9) {
		/* treat entire array as an image with a single row */
		nx = nx * ny;
		ny = 1;
	}

	/* rows must have at least 9 pixels */
	if (nx < 9) {

		for (ii = 0; ii < nx; ii++) {
		    if (nullcheck && array[ii] == nullvalue)
		        continue;
		    else {
			if (array[ii] < xminval) xminval = array[ii];
			if (array[ii] > xmaxval) xmaxval = array[ii];
			ngoodpix++;
		    }
		}
		if (minval) *minval = xminval;
		if (maxval) *maxval = xmaxval;
		if (ngood) *ngood = ngoodpix;
		if (noise2) *noise2 = 0.;
		if (noise3) *noise3 = 0.;
		if (noise5) *noise5 = 0.;
		return(*status);
	}

	/* do we need to compute the min and max value? */
	if (minval || maxval) do_range = 1;
	
        /* allocate arrays used to compute the median and noise estimates */
	differences2 = calloc(nx, sizeof(int));
	if (!differences2) {
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}
	differences3 = calloc(nx, sizeof(int));
	if (!differences3) {
		free(differences2);
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}
	differences5 = calloc(nx, sizeof(int));
	if (!differences5) {
		free(differences2);
		free(differences3);
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}

	diffs2 = calloc(ny, sizeof(double));
	if (!diffs2) {
		free(differences2);
		free(differences3);
		free(differences5);
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}

	diffs3 = calloc(ny, sizeof(double));
	if (!diffs3) {
		free(differences2);
		free(differences3);
		free(differences5);
		free(diffs2);
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}

	diffs5 = calloc(ny, sizeof(double));
	if (!diffs5) {
		free(differences2);
		free(differences3);
		free(differences5);
		free(diffs2);
		free(diffs3);
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}

	/* loop over each row of the image */
	for (jj=0; jj < ny; jj++) {

                rowpix = array + (jj * nx); /* point to first pixel in the row */

		/***** find the first valid pixel in row */
		ii = 0;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v1 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;

		if (do_range) {
			if (v1 < xminval) xminval = v1;
			if (v1 > xmaxval) xmaxval = v1;
		}

		/***** find the 2nd valid pixel in row (which we will skip over) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v2 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;
		
		if (do_range) {
			if (v2 < xminval) xminval = v2;
			if (v2 > xmaxval) xmaxval = v2;
		}

		/***** find the 3rd valid pixel in row */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v3 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;

		if (do_range) {
			if (v3 < xminval) xminval = v3;
			if (v3 > xmaxval) xmaxval = v3;
		}
				
		/* find the 4nd valid pixel in row (to be skipped) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v4 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;

		if (do_range) {
			if (v4 < xminval) xminval = v4;
			if (v4 > xmaxval) xmaxval = v4;
		}
			
		/* find the 5th valid pixel in row (to be skipped) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v5 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;

		if (do_range) {
			if (v5 < xminval) xminval = v5;
			if (v5 > xmaxval) xmaxval = v5;
		}
				
		/* find the 6th valid pixel in row (to be skipped) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v6 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;

		if (do_range) {
			if (v6 < xminval) xminval = v6;
			if (v6 > xmaxval) xmaxval = v6;
		}
				
		/* find the 7th valid pixel in row (to be skipped) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v7 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;

		if (do_range) {
			if (v7 < xminval) xminval = v7;
			if (v7 > xmaxval) xmaxval = v7;
		}
				
		/* find the 8th valid pixel in row (to be skipped) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v8 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;

		if (do_range) {
			if (v8 < xminval) xminval = v8;
			if (v8 > xmaxval) xmaxval = v8;
		}
		/* now populate the differences arrays */
		/* for the remaining pixels in the row */
		nvals = 0;
		nvals2 = 0;
		for (ii++; ii < nx; ii++) {

		    /* find the next valid pixel in row */
                    if (nullcheck)
		        while (ii < nx && rowpix[ii] == nullvalue) ii++;
		     
		    if (ii == nx) break;  /* hit end of row */
		    v9 = rowpix[ii];  /* store the good pixel value */

		    if (do_range) {
			if (v9 < xminval) xminval = v9;
			if (v9 > xmaxval) xmaxval = v9;
		    }

		    /* construct array of absolute differences */

		    if (!(v5 == v6 && v6 == v7) ) {
		        differences2[nvals2] =  abs((int) v5 - (int) v7);
			nvals2++;
		    }

		    if (!(v3 == v4 && v4 == v5 && v5 == v6 && v6 == v7) ) {
		        differences3[nvals] =  abs((2 * (int) v5) - (int) v3 - (int) v7);
		        differences5[nvals] =  abs((6 * (int) v5) - (4 * (int) v3) - (4 * (int) v7) + (int) v1 + (int) v9);
		        nvals++;  
		    } else {
		        /* ignore constant background regions */
			ngoodpix++;
		    }

		    /* shift over 1 pixel */
		    v1 = v2;
		    v2 = v3;
		    v3 = v4;
		    v4 = v5;
		    v5 = v6;
		    v6 = v7;
		    v7 = v8;
		    v8 = v9;
	        }  /* end of loop over pixels in the row */

		/* compute the median diffs */
		/* Note that there are 8 more pixel values than there are diffs values. */
		ngoodpix += nvals;

		if (nvals == 0) {
		    continue;  /* cannot compute medians on this row */
		} else if (nvals == 1) {
		    if (nvals2 == 1) {
		        diffs2[nrows2] = differences2[0];
			nrows2++;
		    }
		        
		    diffs3[nrows] = differences3[0];
		    diffs5[nrows] = differences5[0];
		} else {
                    /* quick_select returns the median MUCH faster than using qsort */
		    if (nvals2 > 1) {
                        diffs2[nrows2] = quick_select_int(differences2, nvals);
			nrows2++;
		    }

                    diffs3[nrows] = quick_select_int(differences3, nvals);
                    diffs5[nrows] = quick_select_int(differences5, nvals);
		}

		nrows++;
	}  /* end of loop over rows */

	    /* compute median of the values for each row */
	if (nrows == 0) { 
	       xnoise3 = 0;
	       xnoise5 = 0;
	} else if (nrows == 1) {
	       xnoise3 = diffs3[0];
	       xnoise5 = diffs5[0];
	} else {	    
	       qsort(diffs3, nrows, sizeof(double), FnCompare_double);
	       qsort(diffs5, nrows, sizeof(double), FnCompare_double);
	       xnoise3 =  (diffs3[(nrows - 1)/2] + diffs3[nrows/2]) / 2.;
	       xnoise5 =  (diffs5[(nrows - 1)/2] + diffs5[nrows/2]) / 2.;
	}

	if (nrows2 == 0) { 
	       xnoise2 = 0;
	} else if (nrows2 == 1) {
	       xnoise2 = diffs2[0];
	} else {	    
	       qsort(diffs2, nrows2, sizeof(double), FnCompare_double);
	       xnoise2 =  (diffs2[(nrows2 - 1)/2] + diffs2[nrows2/2]) / 2.;
	}

	if (ngood)  *ngood  = ngoodpix;
	if (minval) *minval = xminval;
	if (maxval) *maxval = xmaxval;
	if (noise2)  *noise2  = 1.0483579 * xnoise2;
	if (noise3)  *noise3  = 0.6052697 * xnoise3;
	if (noise5)  *noise5  = 0.1772048 * xnoise5;

	free(diffs5);
	free(diffs3);
	free(diffs2);
	free(differences5);
	free(differences3);
	free(differences2);

	return(*status);
}
/*--------------------------------------------------------------------------*/
static int FnNoise5_int
       (int *array,       /*  2 dimensional array of image pixels */
        long nx,            /* number of pixels in each row of the image */
        long ny,            /* number of rows in the image */
	int nullcheck,      /* check for null values, if true */
	int nullvalue,    /* value of null pixels, if nullcheck is true */
   /* returned parameters */   
	long *ngood,        /* number of good, non-null pixels? */
	int *minval,    /* minimum non-null value */
	int *maxval,    /* maximum non-null value */
	double *noise2,      /* returned 2nd order MAD of all non-null pixels */
	double *noise3,      /* returned 3rd order MAD of all non-null pixels */
	double *noise5,      /* returned 5th order MAD of all non-null pixels */
	int *status)        /* error status */

/*
Estimate the median and background noise in the input image using 2nd, 3rd and 5th
order Median Absolute Differences.

The noise in the background of the image is calculated using the MAD algorithms 
developed for deriving the signal to noise ratio in spectra
(see issue #42 of the ST-ECF newsletter, http://www.stecf.org/documents/newsletter/)

3rd order:  noise = 1.482602 / sqrt(6) * median (abs(2*flux(i) - flux(i-2) - flux(i+2)))

The returned estimates are the median of the values that are computed for each 
row of the image.
*/
{
	long ii, jj, nrows = 0, nrows2 = 0, nvals, nvals2, ngoodpix = 0;
	LONGLONG *differences2, *differences3, *differences5, tdiff;
	int *rowpix, v1, v2, v3, v4, v5, v6, v7, v8, v9;
	int xminval = INT_MAX, xmaxval = INT_MIN;
	int do_range = 0;
	double *diffs2, *diffs3, *diffs5; 
	double xnoise2 = 0, xnoise3 = 0, xnoise5 = 0;
	
	if (nx < 9) {
		/* treat entire array as an image with a single row */
		nx = nx * ny;
		ny = 1;
	}

	/* rows must have at least 9 pixels */
	if (nx < 9) {

		for (ii = 0; ii < nx; ii++) {
		    if (nullcheck && array[ii] == nullvalue)
		        continue;
		    else {
			if (array[ii] < xminval) xminval = array[ii];
			if (array[ii] > xmaxval) xmaxval = array[ii];
			ngoodpix++;
		    }
		}
		if (minval) *minval = xminval;
		if (maxval) *maxval = xmaxval;
		if (ngood) *ngood = ngoodpix;
		if (noise2) *noise2 = 0.;
		if (noise3) *noise3 = 0.;
		if (noise5) *noise5 = 0.;
		return(*status);
	}

	/* do we need to compute the min and max value? */
	if (minval || maxval) do_range = 1;
	
        /* allocate arrays used to compute the median and noise estimates */
	differences2 = calloc(nx, sizeof(LONGLONG));
	if (!differences2) {
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}
	differences3 = calloc(nx, sizeof(LONGLONG));
	if (!differences3) {
		free(differences2);
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}
	differences5 = calloc(nx, sizeof(LONGLONG));
	if (!differences5) {
		free(differences2);
		free(differences3);
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}

	diffs2 = calloc(ny, sizeof(double));
	if (!diffs2) {
		free(differences2);
		free(differences3);
		free(differences5);
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}

	diffs3 = calloc(ny, sizeof(double));
	if (!diffs3) {
		free(differences2);
		free(differences3);
		free(differences5);
		free(diffs2);
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}

	diffs5 = calloc(ny, sizeof(double));
	if (!diffs5) {
		free(differences2);
		free(differences3);
		free(differences5);
		free(diffs2);
		free(diffs3);
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}

	/* loop over each row of the image */
	for (jj=0; jj < ny; jj++) {

                rowpix = array + (jj * nx); /* point to first pixel in the row */

		/***** find the first valid pixel in row */
		ii = 0;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v1 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;

		if (do_range) {
			if (v1 < xminval) xminval = v1;
			if (v1 > xmaxval) xmaxval = v1;
		}

		/***** find the 2nd valid pixel in row (which we will skip over) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v2 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;
		
		if (do_range) {
			if (v2 < xminval) xminval = v2;
			if (v2 > xmaxval) xmaxval = v2;
		}

		/***** find the 3rd valid pixel in row */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v3 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;

		if (do_range) {
			if (v3 < xminval) xminval = v3;
			if (v3 > xmaxval) xmaxval = v3;
		}
				
		/* find the 4nd valid pixel in row (to be skipped) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v4 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;

		if (do_range) {
			if (v4 < xminval) xminval = v4;
			if (v4 > xmaxval) xmaxval = v4;
		}
			
		/* find the 5th valid pixel in row (to be skipped) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v5 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;

		if (do_range) {
			if (v5 < xminval) xminval = v5;
			if (v5 > xmaxval) xmaxval = v5;
		}
				
		/* find the 6th valid pixel in row (to be skipped) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v6 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;

		if (do_range) {
			if (v6 < xminval) xminval = v6;
			if (v6 > xmaxval) xmaxval = v6;
		}
				
		/* find the 7th valid pixel in row (to be skipped) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v7 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;

		if (do_range) {
			if (v7 < xminval) xminval = v7;
			if (v7 > xmaxval) xmaxval = v7;
		}
				
		/* find the 8th valid pixel in row (to be skipped) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v8 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;

		if (do_range) {
			if (v8 < xminval) xminval = v8;
			if (v8 > xmaxval) xmaxval = v8;
		}
		/* now populate the differences arrays */
		/* for the remaining pixels in the row */
		nvals = 0;
		nvals2 = 0;
		for (ii++; ii < nx; ii++) {

		    /* find the next valid pixel in row */
                    if (nullcheck)
		        while (ii < nx && rowpix[ii] == nullvalue) ii++;
		     
		    if (ii == nx) break;  /* hit end of row */
		    v9 = rowpix[ii];  /* store the good pixel value */

		    if (do_range) {
			if (v9 < xminval) xminval = v9;
			if (v9 > xmaxval) xmaxval = v9;
		    }

		    /* construct array of absolute differences */

		    if (!(v5 == v6 && v6 == v7) ) {
		        tdiff =  (LONGLONG) v5 - (LONGLONG) v7;
			if (tdiff < 0)
		            differences2[nvals2] =  -1 * tdiff;
			else
		            differences2[nvals2] =  tdiff;

			nvals2++;
		    }

		    if (!(v3 == v4 && v4 == v5 && v5 == v6 && v6 == v7) ) {
		        tdiff =  (2 * (LONGLONG) v5) - (LONGLONG) v3 - (LONGLONG) v7;
			if (tdiff < 0)
		            differences3[nvals] =  -1 * tdiff;
			else
		            differences3[nvals] =  tdiff;

		        tdiff =  (6 * (LONGLONG) v5) - (4 * (LONGLONG) v3) - (4 * (LONGLONG) v7) + (LONGLONG) v1 + (LONGLONG) v9;
			if (tdiff < 0)
		            differences5[nvals] =  -1 * tdiff;
			else
		            differences5[nvals] =  tdiff;

		        nvals++;  
		    } else {
		        /* ignore constant background regions */
			ngoodpix++;
		    }

		    /* shift over 1 pixel */
		    v1 = v2;
		    v2 = v3;
		    v3 = v4;
		    v4 = v5;
		    v5 = v6;
		    v6 = v7;
		    v7 = v8;
		    v8 = v9;
	        }  /* end of loop over pixels in the row */

		/* compute the median diffs */
		/* Note that there are 8 more pixel values than there are diffs values. */
		ngoodpix += nvals;

		if (nvals == 0) {
		    continue;  /* cannot compute medians on this row */
		} else if (nvals == 1) {
		    if (nvals2 == 1) {
		        diffs2[nrows2] = (double) differences2[0];
			nrows2++;
		    }
		        
		    diffs3[nrows] = (double) differences3[0];
		    diffs5[nrows] = (double) differences5[0];
		} else {
                    /* quick_select returns the median MUCH faster than using qsort */
		    if (nvals2 > 1) {
                        diffs2[nrows2] = (double) quick_select_longlong(differences2, nvals);
			nrows2++;
		    }

                    diffs3[nrows] = (double) quick_select_longlong(differences3, nvals);
                    diffs5[nrows] = (double) quick_select_longlong(differences5, nvals);
		}

		nrows++;
	}  /* end of loop over rows */

	    /* compute median of the values for each row */
	if (nrows == 0) { 
	       xnoise3 = 0;
	       xnoise5 = 0;
	} else if (nrows == 1) {
	       xnoise3 = diffs3[0];
	       xnoise5 = diffs5[0];
	} else {	    
	       qsort(diffs3, nrows, sizeof(double), FnCompare_double);
	       qsort(diffs5, nrows, sizeof(double), FnCompare_double);
	       xnoise3 =  (diffs3[(nrows - 1)/2] + diffs3[nrows/2]) / 2.;
	       xnoise5 =  (diffs5[(nrows - 1)/2] + diffs5[nrows/2]) / 2.;
	}

	if (nrows2 == 0) { 
	       xnoise2 = 0;
	} else if (nrows2 == 1) {
	       xnoise2 = diffs2[0];
	} else {	    
	       qsort(diffs2, nrows2, sizeof(double), FnCompare_double);
	       xnoise2 =  (diffs2[(nrows2 - 1)/2] + diffs2[nrows2/2]) / 2.;
	}

	if (ngood)  *ngood  = ngoodpix;
	if (minval) *minval = xminval;
	if (maxval) *maxval = xmaxval;
	if (noise2)  *noise2  = 1.0483579 * xnoise2;
	if (noise3)  *noise3  = 0.6052697 * xnoise3;
	if (noise5)  *noise5  = 0.1772048 * xnoise5;

	free(diffs5);
	free(diffs3);
	free(diffs2);
	free(differences5);
	free(differences3);
	free(differences2);

	return(*status);
}
/*--------------------------------------------------------------------------*/
static int FnNoise5_float
       (float *array,       /*  2 dimensional array of image pixels */
        long nx,            /* number of pixels in each row of the image */
        long ny,            /* number of rows in the image */
	int nullcheck,      /* check for null values, if true */
	float nullvalue,    /* value of null pixels, if nullcheck is true */
   /* returned parameters */   
	long *ngood,        /* number of good, non-null pixels? */
	float *minval,    /* minimum non-null value */
	float *maxval,    /* maximum non-null value */
	double *noise2,      /* returned 2nd order MAD of all non-null pixels */
	double *noise3,      /* returned 3rd order MAD of all non-null pixels */
	double *noise5,      /* returned 5th order MAD of all non-null pixels */
	int *status)        /* error status */

/*
Estimate the median and background noise in the input image using 2nd, 3rd and 5th
order Median Absolute Differences.

The noise in the background of the image is calculated using the MAD algorithms 
developed for deriving the signal to noise ratio in spectra
(see issue #42 of the ST-ECF newsletter, http://www.stecf.org/documents/newsletter/)

3rd order:  noise = 1.482602 / sqrt(6) * median (abs(2*flux(i) - flux(i-2) - flux(i+2)))

The returned estimates are the median of the values that are computed for each 
row of the image.
*/
{
	long ii, jj, nrows = 0, nrows2 = 0, nvals, nvals2, ngoodpix = 0;
	float *differences2, *differences3, *differences5;
	float *rowpix, v1, v2, v3, v4, v5, v6, v7, v8, v9;
	float xminval = FLT_MAX, xmaxval = -FLT_MAX;
	int do_range = 0;
	double *diffs2, *diffs3, *diffs5; 
	double xnoise2 = 0, xnoise3 = 0, xnoise5 = 0;
	
	if (nx < 9) {
		/* treat entire array as an image with a single row */
		nx = nx * ny;
		ny = 1;
	}

	/* rows must have at least 9 pixels */
	if (nx < 9) {

		for (ii = 0; ii < nx; ii++) {
		    if (nullcheck && array[ii] == nullvalue)
		        continue;
		    else {
			if (array[ii] < xminval) xminval = array[ii];
			if (array[ii] > xmaxval) xmaxval = array[ii];
			ngoodpix++;
		    }
		}
		if (minval) *minval = xminval;
		if (maxval) *maxval = xmaxval;
		if (ngood) *ngood = ngoodpix;
		if (noise2) *noise2 = 0.;
		if (noise3) *noise3 = 0.;
		if (noise5) *noise5 = 0.;
		return(*status);
	}

	/* do we need to compute the min and max value? */
	if (minval || maxval) do_range = 1;
	
        /* allocate arrays used to compute the median and noise estimates */
	differences2 = calloc(nx, sizeof(float));
	if (!differences2) {
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}
	differences3 = calloc(nx, sizeof(float));
	if (!differences3) {
		free(differences2);
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}
	differences5 = calloc(nx, sizeof(float));
	if (!differences5) {
		free(differences2);
		free(differences3);
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}

	diffs2 = calloc(ny, sizeof(double));
	if (!diffs2) {
		free(differences2);
		free(differences3);
		free(differences5);
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}

	diffs3 = calloc(ny, sizeof(double));
	if (!diffs3) {
		free(differences2);
		free(differences3);
		free(differences5);
		free(diffs2);
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}

	diffs5 = calloc(ny, sizeof(double));
	if (!diffs5) {
		free(differences2);
		free(differences3);
		free(differences5);
		free(diffs2);
		free(diffs3);
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}

	/* loop over each row of the image */
	for (jj=0; jj < ny; jj++) {

                rowpix = array + (jj * nx); /* point to first pixel in the row */

		/***** find the first valid pixel in row */
		ii = 0;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v1 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;

		if (do_range) {
			if (v1 < xminval) xminval = v1;
			if (v1 > xmaxval) xmaxval = v1;
		}

		/***** find the 2nd valid pixel in row (which we will skip over) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v2 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;
		
		if (do_range) {
			if (v2 < xminval) xminval = v2;
			if (v2 > xmaxval) xmaxval = v2;
		}

		/***** find the 3rd valid pixel in row */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v3 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;

		if (do_range) {
			if (v3 < xminval) xminval = v3;
			if (v3 > xmaxval) xmaxval = v3;
		}
				
		/* find the 4nd valid pixel in row (to be skipped) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v4 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;

		if (do_range) {
			if (v4 < xminval) xminval = v4;
			if (v4 > xmaxval) xmaxval = v4;
		}
			
		/* find the 5th valid pixel in row (to be skipped) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v5 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;

		if (do_range) {
			if (v5 < xminval) xminval = v5;
			if (v5 > xmaxval) xmaxval = v5;
		}
				
		/* find the 6th valid pixel in row (to be skipped) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v6 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;

		if (do_range) {
			if (v6 < xminval) xminval = v6;
			if (v6 > xmaxval) xmaxval = v6;
		}
				
		/* find the 7th valid pixel in row (to be skipped) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v7 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;

		if (do_range) {
			if (v7 < xminval) xminval = v7;
			if (v7 > xmaxval) xmaxval = v7;
		}
				
		/* find the 8th valid pixel in row (to be skipped) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v8 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;

		if (do_range) {
			if (v8 < xminval) xminval = v8;
			if (v8 > xmaxval) xmaxval = v8;
		}
		/* now populate the differences arrays */
		/* for the remaining pixels in the row */
		nvals = 0;
		nvals2 = 0;
		for (ii++; ii < nx; ii++) {

		    /* find the next valid pixel in row */
                    if (nullcheck)
		        while (ii < nx && rowpix[ii] == nullvalue) ii++;
		     
		    if (ii == nx) break;  /* hit end of row */
		    v9 = rowpix[ii];  /* store the good pixel value */

		    if (do_range) {
			if (v9 < xminval) xminval = v9;
			if (v9 > xmaxval) xmaxval = v9;
		    }

		    /* construct array of absolute differences */

		    if (!(v5 == v6 && v6 == v7) ) {
		        differences2[nvals2] = (float) fabs(v5 - v7);
			nvals2++;
		    }

		    if (!(v3 == v4 && v4 == v5 && v5 == v6 && v6 == v7) ) {
		        differences3[nvals] = (float) fabs((2 * v5) - v3 - v7);
		        differences5[nvals] = (float) fabs((6 * v5) - (4 * v3) - (4 * v7) + v1 + v9);
		        nvals++;  
		    } else {
		        /* ignore constant background regions */
			ngoodpix++;
		    }

		    /* shift over 1 pixel */
		    v1 = v2;
		    v2 = v3;
		    v3 = v4;
		    v4 = v5;
		    v5 = v6;
		    v6 = v7;
		    v7 = v8;
		    v8 = v9;
	        }  /* end of loop over pixels in the row */

		/* compute the median diffs */
		/* Note that there are 8 more pixel values than there are diffs values. */
		ngoodpix += nvals;

		if (nvals == 0) {
		    continue;  /* cannot compute medians on this row */
		} else if (nvals == 1) {
		    if (nvals2 == 1) {
		        diffs2[nrows2] = differences2[0];
			nrows2++;
		    }
		        
		    diffs3[nrows] = differences3[0];
		    diffs5[nrows] = differences5[0];
		} else {
                    /* quick_select returns the median MUCH faster than using qsort */
		    if (nvals2 > 1) {
                        diffs2[nrows2] = quick_select_float(differences2, nvals);
			nrows2++;
		    }

                    diffs3[nrows] = quick_select_float(differences3, nvals);
                    diffs5[nrows] = quick_select_float(differences5, nvals);
		}

		nrows++;
	}  /* end of loop over rows */

	    /* compute median of the values for each row */
	if (nrows == 0) { 
	       xnoise3 = 0;
	       xnoise5 = 0;
	} else if (nrows == 1) {
	       xnoise3 = diffs3[0];
	       xnoise5 = diffs5[0];
	} else {	    
	       qsort(diffs3, nrows, sizeof(double), FnCompare_double);
	       qsort(diffs5, nrows, sizeof(double), FnCompare_double);
	       xnoise3 =  (diffs3[(nrows - 1)/2] + diffs3[nrows/2]) / 2.;
	       xnoise5 =  (diffs5[(nrows - 1)/2] + diffs5[nrows/2]) / 2.;
	}

	if (nrows2 == 0) { 
	       xnoise2 = 0;
	} else if (nrows2 == 1) {
	       xnoise2 = diffs2[0];
	} else {	    
	       qsort(diffs2, nrows2, sizeof(double), FnCompare_double);
	       xnoise2 =  (diffs2[(nrows2 - 1)/2] + diffs2[nrows2/2]) / 2.;
	}

	if (ngood)  *ngood  = ngoodpix;
	if (minval) *minval = xminval;
	if (maxval) *maxval = xmaxval;
	if (noise2)  *noise2  = 1.0483579 * xnoise2;
	if (noise3)  *noise3  = 0.6052697 * xnoise3;
	if (noise5)  *noise5  = 0.1772048 * xnoise5;

	free(diffs5);
	free(diffs3);
	free(diffs2);
	free(differences5);
	free(differences3);
	free(differences2);

	return(*status);
}
/*--------------------------------------------------------------------------*/
static int FnNoise5_double
       (double *array,       /*  2 dimensional array of image pixels */
        long nx,            /* number of pixels in each row of the image */
        long ny,            /* number of rows in the image */
	int nullcheck,      /* check for null values, if true */
	double nullvalue,    /* value of null pixels, if nullcheck is true */
   /* returned parameters */   
	long *ngood,        /* number of good, non-null pixels? */
	double *minval,    /* minimum non-null value */
	double *maxval,    /* maximum non-null value */
	double *noise2,      /* returned 2nd order MAD of all non-null pixels */
	double *noise3,      /* returned 3rd order MAD of all non-null pixels */
	double *noise5,      /* returned 5th order MAD of all non-null pixels */
	int *status)        /* error status */

/*
Estimate the median and background noise in the input image using 2nd, 3rd and 5th
order Median Absolute Differences.

The noise in the background of the image is calculated using the MAD algorithms 
developed for deriving the signal to noise ratio in spectra
(see issue #42 of the ST-ECF newsletter, http://www.stecf.org/documents/newsletter/)

3rd order:  noise = 1.482602 / sqrt(6) * median (abs(2*flux(i) - flux(i-2) - flux(i+2)))

The returned estimates are the median of the values that are computed for each 
row of the image.
*/
{
	long ii, jj, nrows = 0, nrows2 = 0, nvals, nvals2, ngoodpix = 0;
	double *differences2, *differences3, *differences5;
	double *rowpix, v1, v2, v3, v4, v5, v6, v7, v8, v9;
	double xminval = DBL_MAX, xmaxval = -DBL_MAX;
	int do_range = 0;
	double *diffs2, *diffs3, *diffs5; 
	double xnoise2 = 0, xnoise3 = 0, xnoise5 = 0;
	
	if (nx < 9) {
		/* treat entire array as an image with a single row */
		nx = nx * ny;
		ny = 1;
	}

	/* rows must have at least 9 pixels */
	if (nx < 9) {

		for (ii = 0; ii < nx; ii++) {
		    if (nullcheck && array[ii] == nullvalue)
		        continue;
		    else {
			if (array[ii] < xminval) xminval = array[ii];
			if (array[ii] > xmaxval) xmaxval = array[ii];
			ngoodpix++;
		    }
		}
		if (minval) *minval = xminval;
		if (maxval) *maxval = xmaxval;
		if (ngood) *ngood = ngoodpix;
		if (noise2) *noise2 = 0.;
		if (noise3) *noise3 = 0.;
		if (noise5) *noise5 = 0.;
		return(*status);
	}

	/* do we need to compute the min and max value? */
	if (minval || maxval) do_range = 1;
	
        /* allocate arrays used to compute the median and noise estimates */
	differences2 = calloc(nx, sizeof(double));
	if (!differences2) {
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}
	differences3 = calloc(nx, sizeof(double));
	if (!differences3) {
		free(differences2);
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}
	differences5 = calloc(nx, sizeof(double));
	if (!differences5) {
		free(differences2);
		free(differences3);
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}

	diffs2 = calloc(ny, sizeof(double));
	if (!diffs2) {
		free(differences2);
		free(differences3);
		free(differences5);
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}

	diffs3 = calloc(ny, sizeof(double));
	if (!diffs3) {
		free(differences2);
		free(differences3);
		free(differences5);
		free(diffs2);
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}

	diffs5 = calloc(ny, sizeof(double));
	if (!diffs5) {
		free(differences2);
		free(differences3);
		free(differences5);
		free(diffs2);
		free(diffs3);
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}

	/* loop over each row of the image */
	for (jj=0; jj < ny; jj++) {

                rowpix = array + (jj * nx); /* point to first pixel in the row */

		/***** find the first valid pixel in row */
		ii = 0;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v1 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;

		if (do_range) {
			if (v1 < xminval) xminval = v1;
			if (v1 > xmaxval) xmaxval = v1;
		}

		/***** find the 2nd valid pixel in row (which we will skip over) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v2 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;
		
		if (do_range) {
			if (v2 < xminval) xminval = v2;
			if (v2 > xmaxval) xmaxval = v2;
		}

		/***** find the 3rd valid pixel in row */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v3 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;

		if (do_range) {
			if (v3 < xminval) xminval = v3;
			if (v3 > xmaxval) xmaxval = v3;
		}
				
		/* find the 4nd valid pixel in row (to be skipped) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v4 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;

		if (do_range) {
			if (v4 < xminval) xminval = v4;
			if (v4 > xmaxval) xmaxval = v4;
		}
			
		/* find the 5th valid pixel in row (to be skipped) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v5 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;

		if (do_range) {
			if (v5 < xminval) xminval = v5;
			if (v5 > xmaxval) xmaxval = v5;
		}
				
		/* find the 6th valid pixel in row (to be skipped) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v6 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;

		if (do_range) {
			if (v6 < xminval) xminval = v6;
			if (v6 > xmaxval) xmaxval = v6;
		}
				
		/* find the 7th valid pixel in row (to be skipped) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v7 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;

		if (do_range) {
			if (v7 < xminval) xminval = v7;
			if (v7 > xmaxval) xmaxval = v7;
		}
				
		/* find the 8th valid pixel in row (to be skipped) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v8 = rowpix[ii];  /* store the good pixel value */
		ngoodpix++;

		if (do_range) {
			if (v8 < xminval) xminval = v8;
			if (v8 > xmaxval) xmaxval = v8;
		}
		/* now populate the differences arrays */
		/* for the remaining pixels in the row */
		nvals = 0;
		nvals2 = 0;
		for (ii++; ii < nx; ii++) {

		    /* find the next valid pixel in row */
                    if (nullcheck)
		        while (ii < nx && rowpix[ii] == nullvalue) ii++;
		     
		    if (ii == nx) break;  /* hit end of row */
		    v9 = rowpix[ii];  /* store the good pixel value */

		    if (do_range) {
			if (v9 < xminval) xminval = v9;
			if (v9 > xmaxval) xmaxval = v9;
		    }

		    /* construct array of absolute differences */

		    if (!(v5 == v6 && v6 == v7) ) {
		        differences2[nvals2] =  fabs(v5 - v7);
			nvals2++;
		    }

		    if (!(v3 == v4 && v4 == v5 && v5 == v6 && v6 == v7) ) {
		        differences3[nvals] =  fabs((2 * v5) - v3 - v7);
		        differences5[nvals] =  fabs((6 * v5) - (4 * v3) - (4 * v7) + v1 + v9);
		        nvals++;  
		    } else {
		        /* ignore constant background regions */
			ngoodpix++;
		    }

		    /* shift over 1 pixel */
		    v1 = v2;
		    v2 = v3;
		    v3 = v4;
		    v4 = v5;
		    v5 = v6;
		    v6 = v7;
		    v7 = v8;
		    v8 = v9;
	        }  /* end of loop over pixels in the row */

		/* compute the median diffs */
		/* Note that there are 8 more pixel values than there are diffs values. */
		ngoodpix += nvals;

		if (nvals == 0) {
		    continue;  /* cannot compute medians on this row */
		} else if (nvals == 1) {
		    if (nvals2 == 1) {
		        diffs2[nrows2] = differences2[0];
			nrows2++;
		    }
		        
		    diffs3[nrows] = differences3[0];
		    diffs5[nrows] = differences5[0];
		} else {
                    /* quick_select returns the median MUCH faster than using qsort */
		    if (nvals2 > 1) {
                        diffs2[nrows2] = quick_select_double(differences2, nvals);
			nrows2++;
		    }

                    diffs3[nrows] = quick_select_double(differences3, nvals);
                    diffs5[nrows] = quick_select_double(differences5, nvals);
		}

		nrows++;
	}  /* end of loop over rows */

	    /* compute median of the values for each row */
	if (nrows == 0) { 
	       xnoise3 = 0;
	       xnoise5 = 0;
	} else if (nrows == 1) {
	       xnoise3 = diffs3[0];
	       xnoise5 = diffs5[0];
	} else {	    
	       qsort(diffs3, nrows, sizeof(double), FnCompare_double);
	       qsort(diffs5, nrows, sizeof(double), FnCompare_double);
	       xnoise3 =  (diffs3[(nrows - 1)/2] + diffs3[nrows/2]) / 2.;
	       xnoise5 =  (diffs5[(nrows - 1)/2] + diffs5[nrows/2]) / 2.;
	}

	if (nrows2 == 0) { 
	       xnoise2 = 0;
	} else if (nrows2 == 1) {
	       xnoise2 = diffs2[0];
	} else {	    
	       qsort(diffs2, nrows2, sizeof(double), FnCompare_double);
	       xnoise2 =  (diffs2[(nrows2 - 1)/2] + diffs2[nrows2/2]) / 2.;
	}

	if (ngood)  *ngood  = ngoodpix;
	if (minval) *minval = xminval;
	if (maxval) *maxval = xmaxval;
	if (noise2)  *noise2  = 1.0483579 * xnoise2;
	if (noise3)  *noise3  = 0.6052697 * xnoise3;
	if (noise5)  *noise5  = 0.1772048 * xnoise5;

	free(diffs5);
	free(diffs3);
	free(diffs2);
	free(differences5);
	free(differences3);
	free(differences2);

	return(*status);
}
/*--------------------------------------------------------------------------*/
static int FnNoise3_short
       (short *array,       /*  2 dimensional array of image pixels */
        long nx,            /* number of pixels in each row of the image */
        long ny,            /* number of rows in the image */
	int nullcheck,      /* check for null values, if true */
	short nullvalue,    /* value of null pixels, if nullcheck is true */
   /* returned parameters */   
	long *ngood,        /* number of good, non-null pixels? */
	short *minval,    /* minimum non-null value */
	short *maxval,    /* maximum non-null value */
	double *noise,      /* returned R.M.S. value of all non-null pixels */
	int *status)        /* error status */

/*
Estimate the median and background noise in the input image using 3rd order differences.

The noise in the background of the image is calculated using the 3rd order algorithm 
developed for deriving the signal to noise ratio in spectra
(see issue #42 of the ST-ECF newsletter, http://www.stecf.org/documents/newsletter/)

  noise = 1.482602 / sqrt(6) * median (abs(2*flux(i) - flux(i-2) - flux(i+2)))

The returned estimates are the median of the values that are computed for each 
row of the image.
*/
{
	long ii, jj, nrows = 0, nvals, ngoodpix = 0;
	short *differences, *rowpix, v1, v2, v3, v4, v5;
	short xminval = SHRT_MAX, xmaxval = SHRT_MIN, do_range = 0;
	double *diffs, xnoise = 0, sigma;

	if (nx < 5) {
		/* treat entire array as an image with a single row */
		nx = nx * ny;
		ny = 1;
	}

	/* rows must have at least 5 pixels */
	if (nx < 5) {

		for (ii = 0; ii < nx; ii++) {
		    if (nullcheck && array[ii] == nullvalue)
		        continue;
		    else {
			if (array[ii] < xminval) xminval = array[ii];
			if (array[ii] > xmaxval) xmaxval = array[ii];
			ngoodpix++;
		    }
		}
		if (minval) *minval = xminval;
		if (maxval) *maxval = xmaxval;
		if (ngood) *ngood = ngoodpix;
		if (noise) *noise = 0.;
		return(*status);
	}

	/* do we need to compute the min and max value? */
	if (minval || maxval) do_range = 1;
	
        /* allocate arrays used to compute the median and noise estimates */
	differences = calloc(nx, sizeof(short));
	if (!differences) {
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}

	diffs = calloc(ny, sizeof(double));
	if (!diffs) {
		free(differences);
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}

	/* loop over each row of the image */
	for (jj=0; jj < ny; jj++) {

                rowpix = array + (jj * nx); /* point to first pixel in the row */

		/***** find the first valid pixel in row */
		ii = 0;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v1 = rowpix[ii];  /* store the good pixel value */

		if (do_range) {
			if (v1 < xminval) xminval = v1;
			if (v1 > xmaxval) xmaxval = v1;
		}

		/***** find the 2nd valid pixel in row (which we will skip over) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v2 = rowpix[ii];  /* store the good pixel value */
		
		if (do_range) {
			if (v2 < xminval) xminval = v2;
			if (v2 > xmaxval) xmaxval = v2;
		}

		/***** find the 3rd valid pixel in row */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v3 = rowpix[ii];  /* store the good pixel value */

		if (do_range) {
			if (v3 < xminval) xminval = v3;
			if (v3 > xmaxval) xmaxval = v3;
		}
				
		/* find the 4nd valid pixel in row (to be skipped) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v4 = rowpix[ii];  /* store the good pixel value */

		if (do_range) {
			if (v4 < xminval) xminval = v4;
			if (v4 > xmaxval) xmaxval = v4;
		}
		
		/* now populate the differences arrays */
		/* for the remaining pixels in the row */
		nvals = 0;
		for (ii++; ii < nx; ii++) {

		    /* find the next valid pixel in row */
                    if (nullcheck)
		        while (ii < nx && rowpix[ii] == nullvalue) ii++;
		     
		    if (ii == nx) break;  /* hit end of row */
		    v5 = rowpix[ii];  /* store the good pixel value */

		    if (do_range) {
			if (v5 < xminval) xminval = v5;
			if (v5 > xmaxval) xmaxval = v5;
		    }

		    /* construct array of 3rd order absolute differences */
		    if (!(v1 == v2 && v2 == v3 && v3 == v4 && v4 == v5)) {
		        differences[nvals] = abs((2 * v3) - v1 - v5);
		        nvals++;  
		    } else {
		        /* ignore constant background regions */
			ngoodpix++;
		    }


		    /* shift over 1 pixel */
		    v1 = v2;
		    v2 = v3;
		    v3 = v4;
		    v4 = v5;
	        }  /* end of loop over pixels in the row */

		/* compute the 3rd order diffs */
		/* Note that there are 4 more pixel values than there are diffs values. */
		ngoodpix += (nvals + 4);

		if (nvals == 0) {
		    continue;  /* cannot compute medians on this row */
		} else if (nvals == 1) {
		    diffs[nrows] = differences[0];
		} else {
                    /* quick_select returns the median MUCH faster than using qsort */
                    diffs[nrows] = quick_select_short(differences, nvals);
		}

		nrows++;
	}  /* end of loop over rows */

	    /* compute median of the values for each row */
	if (nrows == 0) { 
	       xnoise = 0;
	} else if (nrows == 1) {
	       xnoise = diffs[0];
	} else {	    


	       qsort(diffs, nrows, sizeof(double), FnCompare_double);
	       xnoise =  (diffs[(nrows - 1)/2] + diffs[nrows/2]) / 2.;

              FnMeanSigma_double(diffs, nrows, 0, 0.0, 0, &xnoise, &sigma, status); 

	      /* do a 4.5 sigma rejection of outliers */
	      jj = 0;
	      sigma = 4.5 * sigma;
	      for (ii = 0; ii < nrows; ii++) {
		if ( fabs(diffs[ii] - xnoise) <= sigma)	 {
		   if (jj != ii)
		       diffs[jj] = diffs[ii];
		   jj++;
	        } 
	      }
	      if (ii != jj)
                FnMeanSigma_double(diffs, jj, 0, 0.0, 0, &xnoise, &sigma, status); 
	}

	if (ngood)  *ngood  = ngoodpix;
	if (minval) *minval = xminval;
	if (maxval) *maxval = xmaxval;
	if (noise)  *noise  = 0.6052697 * xnoise;

	free(diffs);
	free(differences);

	return(*status);
}
/*--------------------------------------------------------------------------*/
static int FnNoise3_int
       (int *array,       /*  2 dimensional array of image pixels */
        long nx,            /* number of pixels in each row of the image */
        long ny,            /* number of rows in the image */
	int nullcheck,      /* check for null values, if true */
	int nullvalue,    /* value of null pixels, if nullcheck is true */
   /* returned parameters */   
	long *ngood,        /* number of good, non-null pixels? */
	int *minval,    /* minimum non-null value */
	int *maxval,    /* maximum non-null value */
	double *noise,      /* returned R.M.S. value of all non-null pixels */
	int *status)        /* error status */

/*
Estimate the background noise in the input image using 3rd order differences.

The noise in the background of the image is calculated using the 3rd order algorithm 
developed for deriving the signal to noise ratio in spectra
(see issue #42 of the ST-ECF newsletter, http://www.stecf.org/documents/newsletter/)

  noise = 1.482602 / sqrt(6) * median (abs(2*flux(i) - flux(i-2) - flux(i+2)))

The returned estimates are the median of the values that are computed for each 
row of the image.
*/
{
	long ii, jj, nrows = 0, nvals, ngoodpix = 0;
	int *differences, *rowpix, v1, v2, v3, v4, v5;
	int xminval = INT_MAX, xmaxval = INT_MIN, do_range = 0;
	double *diffs, xnoise = 0, sigma;
	
	if (nx < 5) {
		/* treat entire array as an image with a single row */
		nx = nx * ny;
		ny = 1;
	}

	/* rows must have at least 5 pixels */
	if (nx < 5) {

		for (ii = 0; ii < nx; ii++) {
		    if (nullcheck && array[ii] == nullvalue)
		        continue;
		    else {
			if (array[ii] < xminval) xminval = array[ii];
			if (array[ii] > xmaxval) xmaxval = array[ii];
			ngoodpix++;
		    }
		}
		if (minval) *minval = xminval;
		if (maxval) *maxval = xmaxval;
		if (ngood) *ngood = ngoodpix;
		if (noise) *noise = 0.;
		return(*status);
	}

	/* do we need to compute the min and max value? */
	if (minval || maxval) do_range = 1;
	
        /* allocate arrays used to compute the median and noise estimates */
	differences = calloc(nx, sizeof(int));
	if (!differences) {
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}

	diffs = calloc(ny, sizeof(double));
	if (!diffs) {
		free(differences);
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}

	/* loop over each row of the image */
	for (jj=0; jj < ny; jj++) {

                rowpix = array + (jj * nx); /* point to first pixel in the row */

		/***** find the first valid pixel in row */
		ii = 0;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v1 = rowpix[ii];  /* store the good pixel value */

		if (do_range) {
			if (v1 < xminval) xminval = v1;
			if (v1 > xmaxval) xmaxval = v1;
		}

		/***** find the 2nd valid pixel in row (which we will skip over) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v2 = rowpix[ii];  /* store the good pixel value */
		
		if (do_range) {
			if (v2 < xminval) xminval = v2;
			if (v2 > xmaxval) xmaxval = v2;
		}

		/***** find the 3rd valid pixel in row */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v3 = rowpix[ii];  /* store the good pixel value */

		if (do_range) {
			if (v3 < xminval) xminval = v3;
			if (v3 > xmaxval) xmaxval = v3;
		}
				
		/* find the 4nd valid pixel in row (to be skipped) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v4 = rowpix[ii];  /* store the good pixel value */

		if (do_range) {
			if (v4 < xminval) xminval = v4;
			if (v4 > xmaxval) xmaxval = v4;
		}
		
		/* now populate the differences arrays */
		/* for the remaining pixels in the row */
		nvals = 0;
		for (ii++; ii < nx; ii++) {

		    /* find the next valid pixel in row */
                    if (nullcheck)
		        while (ii < nx && rowpix[ii] == nullvalue) ii++;
		     
		    if (ii == nx) break;  /* hit end of row */
		    v5 = rowpix[ii];  /* store the good pixel value */

		    if (do_range) {
			if (v5 < xminval) xminval = v5;
			if (v5 > xmaxval) xmaxval = v5;
		    }

		    /* construct array of 3rd order absolute differences */
		    if (!(v1 == v2 && v2 == v3 && v3 == v4 && v4 == v5)) {
		        differences[nvals] = abs((2 * v3) - v1 - v5);
		        nvals++;  
		    } else {
		        /* ignore constant background regions */
			ngoodpix++;
		    }

		    /* shift over 1 pixel */
		    v1 = v2;
		    v2 = v3;
		    v3 = v4;
		    v4 = v5;
	        }  /* end of loop over pixels in the row */

		/* compute the 3rd order diffs */
		/* Note that there are 4 more pixel values than there are diffs values. */
		ngoodpix += (nvals + 4);

		if (nvals == 0) {
		    continue;  /* cannot compute medians on this row */
		} else if (nvals == 1) {
		    diffs[nrows] = differences[0];
		} else {
                    /* quick_select returns the median MUCH faster than using qsort */
                    diffs[nrows] = quick_select_int(differences, nvals);
		}

		nrows++;
	}  /* end of loop over rows */

	    /* compute median of the values for each row */
	if (nrows == 0) { 
	       xnoise = 0;
	} else if (nrows == 1) {
	       xnoise = diffs[0];
	} else {	    

	       qsort(diffs, nrows, sizeof(double), FnCompare_double);
	       xnoise =  (diffs[(nrows - 1)/2] + diffs[nrows/2]) / 2.;

              FnMeanSigma_double(diffs, nrows, 0, 0.0, 0, &xnoise, &sigma, status); 

	      /* do a 4.5 sigma rejection of outliers */
	      jj = 0;
	      sigma = 4.5 * sigma;
	      for (ii = 0; ii < nrows; ii++) {
		if ( fabs(diffs[ii] - xnoise) <= sigma)	 {
		   if (jj != ii)
		       diffs[jj] = diffs[ii];
		   jj++;
	        }
	      }
	      if (ii != jj)
                FnMeanSigma_double(diffs, jj, 0, 0.0, 0, &xnoise, &sigma, status); 
	}

	if (ngood)  *ngood  = ngoodpix;
	if (minval) *minval = xminval;
	if (maxval) *maxval = xmaxval;
	if (noise)  *noise  = 0.6052697 * xnoise;

	free(diffs);
	free(differences);

	return(*status);
}
/*--------------------------------------------------------------------------*/
static int FnNoise3_float
       (float *array,       /*  2 dimensional array of image pixels */
        long nx,            /* number of pixels in each row of the image */
        long ny,            /* number of rows in the image */
	int nullcheck,      /* check for null values, if true */
	float nullvalue,    /* value of null pixels, if nullcheck is true */
   /* returned parameters */   
	long *ngood,        /* number of good, non-null pixels? */
	float *minval,    /* minimum non-null value */
	float *maxval,    /* maximum non-null value */
	double *noise,      /* returned R.M.S. value of all non-null pixels */
	int *status)        /* error status */

/*
Estimate the median and background noise in the input image using 3rd order differences.

The noise in the background of the image is calculated using the 3rd order algorithm 
developed for deriving the signal to noise ratio in spectra
(see issue #42 of the ST-ECF newsletter, http://www.stecf.org/documents/newsletter/)

  noise = 1.482602 / sqrt(6) * median (abs(2*flux(i) - flux(i-2) - flux(i+2)))

The returned estimates are the median of the values that are computed for each 
row of the image.
*/
{
	long ii, jj, nrows = 0, nvals, ngoodpix = 0;
	float *differences, *rowpix, v1, v2, v3, v4, v5;
	float xminval = FLT_MAX, xmaxval = -FLT_MAX;
	int do_range = 0;
	double *diffs, xnoise = 0;

	if (nx < 5) {
		/* treat entire array as an image with a single row */
		nx = nx * ny;
		ny = 1;
	}

	/* rows must have at least 5 pixels to calc noise, so just calc min, max, ngood */
	if (nx < 5) {

		for (ii = 0; ii < nx; ii++) {
		    if (nullcheck && array[ii] == nullvalue)
		        continue;
		    else {
			if (array[ii] < xminval) xminval = array[ii];
			if (array[ii] > xmaxval) xmaxval = array[ii];
			ngoodpix++;
		    }
		}
		if (minval) *minval = xminval;
		if (maxval) *maxval = xmaxval;
		if (ngood) *ngood = ngoodpix;
		if (noise) *noise = 0.;
		return(*status);
	}

	/* do we need to compute the min and max value? */
	if (minval || maxval) do_range = 1;
	
        /* allocate arrays used to compute the median and noise estimates */
	if (noise) {
	    differences = calloc(nx, sizeof(float));
	    if (!differences) {
        	*status = MEMORY_ALLOCATION;
		return(*status);
	    }

	    diffs = calloc(ny, sizeof(double));
	    if (!diffs) {
		free(differences);
        	*status = MEMORY_ALLOCATION;
		return(*status);
	    }
	}

	/* loop over each row of the image */
	for (jj=0; jj < ny; jj++) {

                rowpix = array + (jj * nx); /* point to first pixel in the row */

		/***** find the first valid pixel in row */
		ii = 0;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v1 = rowpix[ii];  /* store the good pixel value */

		if (do_range) {
			if (v1 < xminval) xminval = v1;
			if (v1 > xmaxval) xmaxval = v1;
		}

		/***** find the 2nd valid pixel in row (which we will skip over) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v2 = rowpix[ii];  /* store the good pixel value */
		
		if (do_range) {
			if (v2 < xminval) xminval = v2;
			if (v2 > xmaxval) xmaxval = v2;
		}

		/***** find the 3rd valid pixel in row */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v3 = rowpix[ii];  /* store the good pixel value */

		if (do_range) {
			if (v3 < xminval) xminval = v3;
			if (v3 > xmaxval) xmaxval = v3;
		}
				
		/* find the 4nd valid pixel in row (to be skipped) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v4 = rowpix[ii];  /* store the good pixel value */

		if (do_range) {
			if (v4 < xminval) xminval = v4;
			if (v4 > xmaxval) xmaxval = v4;
		}
		
		/* now populate the differences arrays */
		/* for the remaining pixels in the row */
		nvals = 0;
		for (ii++; ii < nx; ii++) {

		    /* find the next valid pixel in row */
                    if (nullcheck)
		        while (ii < nx && rowpix[ii] == nullvalue) {
			  ii++;
		        }
			
		    if (ii == nx) break;  /* hit end of row */
		    v5 = rowpix[ii];  /* store the good pixel value */

		    if (do_range) {
			if (v5 < xminval) xminval = v5;
			if (v5 > xmaxval) xmaxval = v5;
		    }

		    /* construct array of 3rd order absolute differences */
		    if (noise) {
		        if (!(v1 == v2 && v2 == v3 && v3 == v4 && v4 == v5)) {

		            differences[nvals] = (float) fabs((2. * v3) - v1 - v5);
		            nvals++;  
		       } else {
		            /* ignore constant background regions */
			    ngoodpix++;
		       }
		    } else {
		       /* just increment the number of non-null pixels */
		       ngoodpix++;
		    }

		    /* shift over 1 pixel */
		    v1 = v2;
		    v2 = v3;
		    v3 = v4;
		    v4 = v5;
	        }  /* end of loop over pixels in the row */

		/* compute the 3rd order diffs */
		/* Note that there are 4 more pixel values than there are diffs values. */
		ngoodpix += (nvals + 4);

		if (noise) {
		    if (nvals == 0) {
		        continue;  /* cannot compute medians on this row */
		    } else if (nvals == 1) {
		        diffs[nrows] = differences[0];
		    } else {
                        /* quick_select returns the median MUCH faster than using qsort */
                        diffs[nrows] = quick_select_float(differences, nvals);
		    }
		}
		nrows++;
	}  /* end of loop over rows */

	    /* compute median of the values for each row */
	if (noise) {
	    if (nrows == 0) { 
	       xnoise = 0;
	    } else if (nrows == 1) {
	       xnoise = diffs[0];
	    } else {	    
	       qsort(diffs, nrows, sizeof(double), FnCompare_double);
	       xnoise =  (diffs[(nrows - 1)/2] + diffs[nrows/2]) / 2.;
	    }
	}

	if (ngood)  *ngood  = ngoodpix;
	if (minval) *minval = xminval;
	if (maxval) *maxval = xmaxval;
	if (noise) {
		*noise  = 0.6052697 * xnoise;
		free(diffs);
		free(differences);
	}

	return(*status);
}
/*--------------------------------------------------------------------------*/
static int FnNoise3_double
       (double *array,       /*  2 dimensional array of image pixels */
        long nx,            /* number of pixels in each row of the image */
        long ny,            /* number of rows in the image */
	int nullcheck,      /* check for null values, if true */
	double nullvalue,    /* value of null pixels, if nullcheck is true */
   /* returned parameters */   
	long *ngood,        /* number of good, non-null pixels? */
	double *minval,    /* minimum non-null value */
	double *maxval,    /* maximum non-null value */
	double *noise,      /* returned R.M.S. value of all non-null pixels */
	int *status)        /* error status */

/*
Estimate the median and background noise in the input image using 3rd order differences.

The noise in the background of the image is calculated using the 3rd order algorithm 
developed for deriving the signal to noise ratio in spectra
(see issue #42 of the ST-ECF newsletter, http://www.stecf.org/documents/newsletter/)

  noise = 1.482602 / sqrt(6) * median (abs(2*flux(i) - flux(i-2) - flux(i+2)))

The returned estimates are the median of the values that are computed for each 
row of the image.
*/
{
	long ii, jj, nrows = 0, nvals, ngoodpix = 0;
	double *differences, *rowpix, v1, v2, v3, v4, v5;
	double xminval = DBL_MAX, xmaxval = -DBL_MAX;
	int do_range = 0;
	double *diffs, xnoise = 0;
	
	if (nx < 5) {
		/* treat entire array as an image with a single row */
		nx = nx * ny;
		ny = 1;
	}

	/* rows must have at least 5 pixels */
	if (nx < 5) {

		for (ii = 0; ii < nx; ii++) {
		    if (nullcheck && array[ii] == nullvalue)
		        continue;
		    else {
			if (array[ii] < xminval) xminval = array[ii];
			if (array[ii] > xmaxval) xmaxval = array[ii];
			ngoodpix++;
		    }
		}
		if (minval) *minval = xminval;
		if (maxval) *maxval = xmaxval;
		if (ngood) *ngood = ngoodpix;
		if (noise) *noise = 0.;
		return(*status);
	}

	/* do we need to compute the min and max value? */
	if (minval || maxval) do_range = 1;
	
        /* allocate arrays used to compute the median and noise estimates */
	if (noise) {
	    differences = calloc(nx, sizeof(double));
	    if (!differences) {
        	*status = MEMORY_ALLOCATION;
		return(*status);
	    }

	    diffs = calloc(ny, sizeof(double));
	    if (!diffs) {
		free(differences);
        	*status = MEMORY_ALLOCATION;
		return(*status);
	    }
	}

	/* loop over each row of the image */
	for (jj=0; jj < ny; jj++) {

                rowpix = array + (jj * nx); /* point to first pixel in the row */

		/***** find the first valid pixel in row */
		ii = 0;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v1 = rowpix[ii];  /* store the good pixel value */

		if (do_range) {
			if (v1 < xminval) xminval = v1;
			if (v1 > xmaxval) xmaxval = v1;
		}

		/***** find the 2nd valid pixel in row (which we will skip over) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v2 = rowpix[ii];  /* store the good pixel value */
		
		if (do_range) {
			if (v2 < xminval) xminval = v2;
			if (v2 > xmaxval) xmaxval = v2;
		}

		/***** find the 3rd valid pixel in row */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v3 = rowpix[ii];  /* store the good pixel value */

		if (do_range) {
			if (v3 < xminval) xminval = v3;
			if (v3 > xmaxval) xmaxval = v3;
		}
				
		/* find the 4nd valid pixel in row (to be skipped) */
		ii++;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v4 = rowpix[ii];  /* store the good pixel value */

		if (do_range) {
			if (v4 < xminval) xminval = v4;
			if (v4 > xmaxval) xmaxval = v4;
		}
		
		/* now populate the differences arrays */
		/* for the remaining pixels in the row */
		nvals = 0;
		for (ii++; ii < nx; ii++) {

		    /* find the next valid pixel in row */
                    if (nullcheck)
		        while (ii < nx && rowpix[ii] == nullvalue) ii++;
		     
		    if (ii == nx) break;  /* hit end of row */
		    v5 = rowpix[ii];  /* store the good pixel value */

		    if (do_range) {
			if (v5 < xminval) xminval = v5;
			if (v5 > xmaxval) xmaxval = v5;
		    }

		    /* construct array of 3rd order absolute differences */
		    if (noise) {
		        if (!(v1 == v2 && v2 == v3 && v3 == v4 && v4 == v5)) {

		            differences[nvals] = fabs((2. * v3) - v1 - v5);
		            nvals++;  
		        } else {
		            /* ignore constant background regions */
			    ngoodpix++;
		        }
		    } else {
		       /* just increment the number of non-null pixels */
		       ngoodpix++;
		    }

		    /* shift over 1 pixel */
		    v1 = v2;
		    v2 = v3;
		    v3 = v4;
		    v4 = v5;
	        }  /* end of loop over pixels in the row */

		/* compute the 3rd order diffs */
		/* Note that there are 4 more pixel values than there are diffs values. */
		ngoodpix += (nvals + 4);

		if (noise) {
		    if (nvals == 0) {
		        continue;  /* cannot compute medians on this row */
		    } else if (nvals == 1) {
		        diffs[nrows] = differences[0];
		    } else {
                        /* quick_select returns the median MUCH faster than using qsort */
                        diffs[nrows] = quick_select_double(differences, nvals);
		    }
		}
		nrows++;
	}  /* end of loop over rows */

	    /* compute median of the values for each row */
	if (noise) {
	    if (nrows == 0) { 
	       xnoise = 0;
	    } else if (nrows == 1) {
	       xnoise = diffs[0];
	    } else {	    
	       qsort(diffs, nrows, sizeof(double), FnCompare_double);
	       xnoise =  (diffs[(nrows - 1)/2] + diffs[nrows/2]) / 2.;
	    }
	}

	if (ngood)  *ngood  = ngoodpix;
	if (minval) *minval = xminval;
	if (maxval) *maxval = xmaxval;
	if (noise) {
		*noise  = 0.6052697 * xnoise;
		free(diffs);
		free(differences);
	}

	return(*status);
}
/*--------------------------------------------------------------------------*/
static int FnNoise1_short
       (short *array,       /*  2 dimensional array of image pixels */
        long nx,            /* number of pixels in each row of the image */
        long ny,            /* number of rows in the image */
	int nullcheck,      /* check for null values, if true */
	short nullvalue,    /* value of null pixels, if nullcheck is true */
   /* returned parameters */   
	double *noise,      /* returned R.M.S. value of all non-null pixels */
	int *status)        /* error status */
/*
Estimate the background noise in the input image using sigma of 1st order differences.

  noise = 1.0 / sqrt(2) * rms of (flux[i] - flux[i-1])

The returned estimate is the median of the values that are computed for each 
row of the image.
*/
{
	int iter;
	long ii, jj, kk, nrows = 0, nvals;
	short *differences, *rowpix, v1;
	double  *diffs, xnoise, mean, stdev;

	/* rows must have at least 3 pixels to estimate noise */
	if (nx < 3) {
		*noise = 0;
		return(*status);
	}
	
        /* allocate arrays used to compute the median and noise estimates */
	differences = calloc(nx, sizeof(short));
	if (!differences) {
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}

	diffs = calloc(ny, sizeof(double));
	if (!diffs) {
		free(differences);
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}

	/* loop over each row of the image */
	for (jj=0; jj < ny; jj++) {

                rowpix = array + (jj * nx); /* point to first pixel in the row */

		/***** find the first valid pixel in row */
		ii = 0;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v1 = rowpix[ii];  /* store the good pixel value */

		/* now continue populating the differences arrays */
		/* for the remaining pixels in the row */
		nvals = 0;
		for (ii++; ii < nx; ii++) {

		    /* find the next valid pixel in row */
                    if (nullcheck)
		        while (ii < nx && rowpix[ii] == nullvalue) ii++;
		     
		    if (ii == nx) break;  /* hit end of row */
		
		    /* construct array of 1st order differences */
		    differences[nvals] = v1 - rowpix[ii];

		    nvals++;  
		    /* shift over 1 pixel */
		    v1 = rowpix[ii];
	        }  /* end of loop over pixels in the row */

		if (nvals < 2)
		   continue;
		else {

		    FnMeanSigma_short(differences, nvals, 0, 0, 0, &mean, &stdev, status);

		    if (stdev > 0.) {
		        for (iter = 0;  iter < NITER;  iter++) {
		            kk = 0;
		            for (ii = 0;  ii < nvals;  ii++) {
		                if (fabs (differences[ii] - mean) < SIGMA_CLIP * stdev) {
			            if (kk < ii)
			                differences[kk] = differences[ii];
			            kk++;
		                }
		            }
		            if (kk == nvals) break;

		            nvals = kk;
		            FnMeanSigma_short(differences, nvals, 0, 0, 0, &mean, &stdev, status);
	              }
		   }

		   diffs[nrows] = stdev;
		   nrows++;
		}
	}  /* end of loop over rows */

	/* compute median of the values for each row */
	if (nrows == 0) { 
	       xnoise = 0;
	} else if (nrows == 1) {
	       xnoise = diffs[0];
	} else {
	       qsort(diffs, nrows, sizeof(double), FnCompare_double);
	       xnoise =  (diffs[(nrows - 1)/2] + diffs[nrows/2]) / 2.;
	}

	*noise = .70710678 * xnoise;

	free(diffs);
	free(differences);

	return(*status);
}
/*--------------------------------------------------------------------------*/
static int FnNoise1_int
       (int *array,       /*  2 dimensional array of image pixels */
        long nx,            /* number of pixels in each row of the image */
        long ny,            /* number of rows in the image */
	int nullcheck,      /* check for null values, if true */
	int nullvalue,    /* value of null pixels, if nullcheck is true */
   /* returned parameters */   
	double *noise,      /* returned R.M.S. value of all non-null pixels */
	int *status)        /* error status */
/*
Estimate the background noise in the input image using sigma of 1st order differences.

  noise = 1.0 / sqrt(2) * rms of (flux[i] - flux[i-1])

The returned estimate is the median of the values that are computed for each 
row of the image.
*/
{
	int iter;
	long ii, jj, kk, nrows = 0, nvals;
	int *differences, *rowpix, v1;
	double  *diffs, xnoise, mean, stdev;

	/* rows must have at least 3 pixels to estimate noise */
	if (nx < 3) {
		*noise = 0;
		return(*status);
	}
	
        /* allocate arrays used to compute the median and noise estimates */
	differences = calloc(nx, sizeof(int));
	if (!differences) {
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}

	diffs = calloc(ny, sizeof(double));
	if (!diffs) {
		free(differences);
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}

	/* loop over each row of the image */
	for (jj=0; jj < ny; jj++) {

                rowpix = array + (jj * nx); /* point to first pixel in the row */

		/***** find the first valid pixel in row */
		ii = 0;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v1 = rowpix[ii];  /* store the good pixel value */

		/* now continue populating the differences arrays */
		/* for the remaining pixels in the row */
		nvals = 0;
		for (ii++; ii < nx; ii++) {

		    /* find the next valid pixel in row */
                    if (nullcheck)
		        while (ii < nx && rowpix[ii] == nullvalue) ii++;
		     
		    if (ii == nx) break;  /* hit end of row */
		
		    /* construct array of 1st order differences */
		    differences[nvals] = v1 - rowpix[ii];

		    nvals++;  
		    /* shift over 1 pixel */
		    v1 = rowpix[ii];
	        }  /* end of loop over pixels in the row */

		if (nvals < 2)
		   continue;
		else {

		    FnMeanSigma_int(differences, nvals, 0, 0, 0, &mean, &stdev, status);

		    if (stdev > 0.) {
		        for (iter = 0;  iter < NITER;  iter++) {
		            kk = 0;
		            for (ii = 0;  ii < nvals;  ii++) {
		                if (fabs (differences[ii] - mean) < SIGMA_CLIP * stdev) {
			            if (kk < ii)
			                differences[kk] = differences[ii];
			            kk++;
		                }
		            }
		            if (kk == nvals) break;

		            nvals = kk;
		            FnMeanSigma_int(differences, nvals, 0, 0, 0, &mean, &stdev, status);
	              }
		   }

		   diffs[nrows] = stdev;
		   nrows++;
		}
	}  /* end of loop over rows */

	/* compute median of the values for each row */
	if (nrows == 0) { 
	       xnoise = 0;
	} else if (nrows == 1) {
	       xnoise = diffs[0];
	} else {
	       qsort(diffs, nrows, sizeof(double), FnCompare_double);
	       xnoise =  (diffs[(nrows - 1)/2] + diffs[nrows/2]) / 2.;
	}

	*noise = .70710678 * xnoise;

	free(diffs);
	free(differences);

	return(*status);
}
/*--------------------------------------------------------------------------*/
static int FnNoise1_float
       (float *array,       /*  2 dimensional array of image pixels */
        long nx,            /* number of pixels in each row of the image */
        long ny,            /* number of rows in the image */
	int nullcheck,      /* check for null values, if true */
	float nullvalue,    /* value of null pixels, if nullcheck is true */
   /* returned parameters */   
	double *noise,      /* returned R.M.S. value of all non-null pixels */
	int *status)        /* error status */
/*
Estimate the background noise in the input image using sigma of 1st order differences.

  noise = 1.0 / sqrt(2) * rms of (flux[i] - flux[i-1])

The returned estimate is the median of the values that are computed for each 
row of the image.
*/
{
	int iter;
	long ii, jj, kk, nrows = 0, nvals;
	float *differences, *rowpix, v1;
	double  *diffs, xnoise, mean, stdev;

	/* rows must have at least 3 pixels to estimate noise */
	if (nx < 3) {
		*noise = 0;
		return(*status);
	}
	
        /* allocate arrays used to compute the median and noise estimates */
	differences = calloc(nx, sizeof(float));
	if (!differences) {
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}

	diffs = calloc(ny, sizeof(double));
	if (!diffs) {
		free(differences);
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}

	/* loop over each row of the image */
	for (jj=0; jj < ny; jj++) {

                rowpix = array + (jj * nx); /* point to first pixel in the row */

		/***** find the first valid pixel in row */
		ii = 0;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v1 = rowpix[ii];  /* store the good pixel value */

		/* now continue populating the differences arrays */
		/* for the remaining pixels in the row */
		nvals = 0;
		for (ii++; ii < nx; ii++) {

		    /* find the next valid pixel in row */
                    if (nullcheck)
		        while (ii < nx && rowpix[ii] == nullvalue) ii++;
		     
		    if (ii == nx) break;  /* hit end of row */
		
		    /* construct array of 1st order differences */
		    differences[nvals] = v1 - rowpix[ii];

		    nvals++;  
		    /* shift over 1 pixel */
		    v1 = rowpix[ii];
	        }  /* end of loop over pixels in the row */

		if (nvals < 2)
		   continue;
		else {

		    FnMeanSigma_float(differences, nvals, 0, 0, 0, &mean, &stdev, status);

		    if (stdev > 0.) {
		        for (iter = 0;  iter < NITER;  iter++) {
		            kk = 0;
		            for (ii = 0;  ii < nvals;  ii++) {
		                if (fabs (differences[ii] - mean) < SIGMA_CLIP * stdev) {
			            if (kk < ii)
			                differences[kk] = differences[ii];
			            kk++;
		                }
		            }
		            if (kk == nvals) break;

		            nvals = kk;
		            FnMeanSigma_float(differences, nvals, 0, 0, 0, &mean, &stdev, status);
	              }
		   }

		   diffs[nrows] = stdev;
		   nrows++;
		}
	}  /* end of loop over rows */

	/* compute median of the values for each row */
	if (nrows == 0) { 
	       xnoise = 0;
	} else if (nrows == 1) {
	       xnoise = diffs[0];
	} else {
	       qsort(diffs, nrows, sizeof(double), FnCompare_double);
	       xnoise =  (diffs[(nrows - 1)/2] + diffs[nrows/2]) / 2.;
	}

	*noise = .70710678 * xnoise;

	free(diffs);
	free(differences);

	return(*status);
}
/*--------------------------------------------------------------------------*/
static int FnNoise1_double
       (double *array,       /*  2 dimensional array of image pixels */
        long nx,            /* number of pixels in each row of the image */
        long ny,            /* number of rows in the image */
	int nullcheck,      /* check for null values, if true */
	double nullvalue,    /* value of null pixels, if nullcheck is true */
   /* returned parameters */   
	double *noise,      /* returned R.M.S. value of all non-null pixels */
	int *status)        /* error status */
/*
Estimate the background noise in the input image using sigma of 1st order differences.

  noise = 1.0 / sqrt(2) * rms of (flux[i] - flux[i-1])

The returned estimate is the median of the values that are computed for each 
row of the image.
*/
{
	int iter;
	long ii, jj, kk, nrows = 0, nvals;
	double *differences, *rowpix, v1;
	double  *diffs, xnoise, mean, stdev;

	/* rows must have at least 3 pixels to estimate noise */
	if (nx < 3) {
		*noise = 0;
		return(*status);
	}
	
        /* allocate arrays used to compute the median and noise estimates */
	differences = calloc(nx, sizeof(double));
	if (!differences) {
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}

	diffs = calloc(ny, sizeof(double));
	if (!diffs) {
		free(differences);
        	*status = MEMORY_ALLOCATION;
		return(*status);
	}

	/* loop over each row of the image */
	for (jj=0; jj < ny; jj++) {

                rowpix = array + (jj * nx); /* point to first pixel in the row */

		/***** find the first valid pixel in row */
		ii = 0;
		if (nullcheck)
		    while (ii < nx && rowpix[ii] == nullvalue) ii++;

		if (ii == nx) continue;  /* hit end of row */
		v1 = rowpix[ii];  /* store the good pixel value */

		/* now continue populating the differences arrays */
		/* for the remaining pixels in the row */
		nvals = 0;
		for (ii++; ii < nx; ii++) {

		    /* find the next valid pixel in row */
                    if (nullcheck)
		        while (ii < nx && rowpix[ii] == nullvalue) ii++;
		     
		    if (ii == nx) break;  /* hit end of row */
		
		    /* construct array of 1st order differences */
		    differences[nvals] = v1 - rowpix[ii];

		    nvals++;  
		    /* shift over 1 pixel */
		    v1 = rowpix[ii];
	        }  /* end of loop over pixels in the row */

		if (nvals < 2)
		   continue;
		else {

		    FnMeanSigma_double(differences, nvals, 0, 0, 0, &mean, &stdev, status);

		    if (stdev > 0.) {
		        for (iter = 0;  iter < NITER;  iter++) {
		            kk = 0;
		            for (ii = 0;  ii < nvals;  ii++) {
		                if (fabs (differences[ii] - mean) < SIGMA_CLIP * stdev) {
			            if (kk < ii)
			                differences[kk] = differences[ii];
			            kk++;
		                }
		            }
		            if (kk == nvals) break;

		            nvals = kk;
		            FnMeanSigma_double(differences, nvals, 0, 0, 0, &mean, &stdev, status);
	              }
		   }

		   diffs[nrows] = stdev;
		   nrows++;
		}
	}  /* end of loop over rows */

	/* compute median of the values for each row */
	if (nrows == 0) { 
	       xnoise = 0;
	} else if (nrows == 1) {
	       xnoise = diffs[0];
	} else {
	       qsort(diffs, nrows, sizeof(double), FnCompare_double);
	       xnoise =  (diffs[(nrows - 1)/2] + diffs[nrows/2]) / 2.;
	}

	*noise = .70710678 * xnoise;

	free(diffs);
	free(differences);

	return(*status);
}
/*--------------------------------------------------------------------------*/
static int FnCompare_short(const void *v1, const void *v2)
{
   const short *i1 = v1;
   const short *i2 = v2;
   
   if (*i1 < *i2)
     return(-1);
   else if (*i1 > *i2)
     return(1);
   else
     return(0);
}
/*--------------------------------------------------------------------------*/
static int FnCompare_int(const void *v1, const void *v2)
{
   const int *i1 = v1;
   const int *i2 = v2;
   
   if (*i1 < *i2)
     return(-1);
   else if (*i1 > *i2)
     return(1);
   else
     return(0);
}
/*--------------------------------------------------------------------------*/
static int FnCompare_float(const void *v1, const void *v2)
{
   const float *i1 = v1;
   const float *i2 = v2;
   
   if (*i1 < *i2)
     return(-1);
   else if (*i1 > *i2)
     return(1);
   else
     return(0);
}
/*--------------------------------------------------------------------------*/
static int FnCompare_double(const void *v1, const void *v2)
{
   const double *i1 = v1;
   const double *i2 = v2;
   
   if (*i1 < *i2)
     return(-1);
   else if (*i1 > *i2)
     return(1);
   else
     return(0);
}
/*--------------------------------------------------------------------------*/

/*
 *  These Quickselect routines are based on the algorithm described in
 *  "Numerical recipes in C", Second Edition,
 *  Cambridge University Press, 1992, Section 8.5, ISBN 0-521-43108-5
 *  This code by Nicolas Devillard - 1998. Public domain.
 */

/*--------------------------------------------------------------------------*/

#define ELEM_SWAP(a,b) { register float t=(a);(a)=(b);(b)=t; }

static float quick_select_float(float arr[], int n) 
{
    int low, high ;
    int median;
    int middle, ll, hh;

    low = 0 ; high = n-1 ; median = (low + high) / 2;
    for (;;) {
        if (high <= low) /* One element only */
            return arr[median] ;

        if (high == low + 1) {  /* Two elements only */
            if (arr[low] > arr[high])
                ELEM_SWAP(arr[low], arr[high]) ;
            return arr[median] ;
        }

    /* Find median of low, middle and high items; swap into position low */
    middle = (low + high) / 2;
    if (arr[middle] > arr[high])    ELEM_SWAP(arr[middle], arr[high]) ;
    if (arr[low] > arr[high])       ELEM_SWAP(arr[low], arr[high]) ;
    if (arr[middle] > arr[low])     ELEM_SWAP(arr[middle], arr[low]) ;

    /* Swap low item (now in position middle) into position (low+1) */
    ELEM_SWAP(arr[middle], arr[low+1]) ;

    /* Nibble from each end towards middle, swapping items when stuck */
    ll = low + 1;
    hh = high;
    for (;;) {
        do ll++; while (arr[low] > arr[ll]) ;
        do hh--; while (arr[hh]  > arr[low]) ;

        if (hh < ll)
        break;

        ELEM_SWAP(arr[ll], arr[hh]) ;
    }

    /* Swap middle item (in position low) back into correct position */
    ELEM_SWAP(arr[low], arr[hh]) ;

    /* Re-set active partition */
    if (hh <= median)
        low = ll;
        if (hh >= median)
        high = hh - 1;
    }
}

#undef ELEM_SWAP

/*--------------------------------------------------------------------------*/

#define ELEM_SWAP(a,b) { register short t=(a);(a)=(b);(b)=t; }

static short quick_select_short(short arr[], int n) 
{
    int low, high ;
    int median;
    int middle, ll, hh;

    low = 0 ; high = n-1 ; median = (low + high) / 2;
    for (;;) {
        if (high <= low) /* One element only */
            return arr[median] ;

        if (high == low + 1) {  /* Two elements only */
            if (arr[low] > arr[high])
                ELEM_SWAP(arr[low], arr[high]) ;
            return arr[median] ;
        }

    /* Find median of low, middle and high items; swap into position low */
    middle = (low + high) / 2;
    if (arr[middle] > arr[high])    ELEM_SWAP(arr[middle], arr[high]) ;
    if (arr[low] > arr[high])       ELEM_SWAP(arr[low], arr[high]) ;
    if (arr[middle] > arr[low])     ELEM_SWAP(arr[middle], arr[low]) ;

    /* Swap low item (now in position middle) into position (low+1) */
    ELEM_SWAP(arr[middle], arr[low+1]) ;

    /* Nibble from each end towards middle, swapping items when stuck */
    ll = low + 1;
    hh = high;
    for (;;) {
        do ll++; while (arr[low] > arr[ll]) ;
        do hh--; while (arr[hh]  > arr[low]) ;

        if (hh < ll)
        break;

        ELEM_SWAP(arr[ll], arr[hh]) ;
    }

    /* Swap middle item (in position low) back into correct position */
    ELEM_SWAP(arr[low], arr[hh]) ;

    /* Re-set active partition */
    if (hh <= median)
        low = ll;
        if (hh >= median)
        high = hh - 1;
    }
}

#undef ELEM_SWAP

/*--------------------------------------------------------------------------*/

#define ELEM_SWAP(a,b) { register int t=(a);(a)=(b);(b)=t; }

static int quick_select_int(int arr[], int n) 
{
    int low, high ;
    int median;
    int middle, ll, hh;

    low = 0 ; high = n-1 ; median = (low + high) / 2;
    for (;;) {
        if (high <= low) /* One element only */
            return arr[median] ;

        if (high == low + 1) {  /* Two elements only */
            if (arr[low] > arr[high])
                ELEM_SWAP(arr[low], arr[high]) ;
            return arr[median] ;
        }

    /* Find median of low, middle and high items; swap into position low */
    middle = (low + high) / 2;
    if (arr[middle] > arr[high])    ELEM_SWAP(arr[middle], arr[high]) ;
    if (arr[low] > arr[high])       ELEM_SWAP(arr[low], arr[high]) ;
    if (arr[middle] > arr[low])     ELEM_SWAP(arr[middle], arr[low]) ;

    /* Swap low item (now in position middle) into position (low+1) */
    ELEM_SWAP(arr[middle], arr[low+1]) ;

    /* Nibble from each end towards middle, swapping items when stuck */
    ll = low + 1;
    hh = high;
    for (;;) {
        do ll++; while (arr[low] > arr[ll]) ;
        do hh--; while (arr[hh]  > arr[low]) ;

        if (hh < ll)
        break;

        ELEM_SWAP(arr[ll], arr[hh]) ;
    }

    /* Swap middle item (in position low) back into correct position */
    ELEM_SWAP(arr[low], arr[hh]) ;

    /* Re-set active partition */
    if (hh <= median)
        low = ll;
        if (hh >= median)
        high = hh - 1;
    }
}

#undef ELEM_SWAP

/*--------------------------------------------------------------------------*/

#define ELEM_SWAP(a,b) { register LONGLONG  t=(a);(a)=(b);(b)=t; }

static LONGLONG quick_select_longlong(LONGLONG arr[], int n) 
{
    int low, high ;
    int median;
    int middle, ll, hh;

    low = 0 ; high = n-1 ; median = (low + high) / 2;
    for (;;) {
        if (high <= low) /* One element only */
            return arr[median] ;

        if (high == low + 1) {  /* Two elements only */
            if (arr[low] > arr[high])
                ELEM_SWAP(arr[low], arr[high]) ;
            return arr[median] ;
        }

    /* Find median of low, middle and high items; swap into position low */
    middle = (low + high) / 2;
    if (arr[middle] > arr[high])    ELEM_SWAP(arr[middle], arr[high]) ;
    if (arr[low] > arr[high])       ELEM_SWAP(arr[low], arr[high]) ;
    if (arr[middle] > arr[low])     ELEM_SWAP(arr[middle], arr[low]) ;

    /* Swap low item (now in position middle) into position (low+1) */
    ELEM_SWAP(arr[middle], arr[low+1]) ;

    /* Nibble from each end towards middle, swapping items when stuck */
    ll = low + 1;
    hh = high;
    for (;;) {
        do ll++; while (arr[low] > arr[ll]) ;
        do hh--; while (arr[hh]  > arr[low]) ;

        if (hh < ll)
        break;

        ELEM_SWAP(arr[ll], arr[hh]) ;
    }

    /* Swap middle item (in position low) back into correct position */
    ELEM_SWAP(arr[low], arr[hh]) ;

    /* Re-set active partition */
    if (hh <= median)
        low = ll;
        if (hh >= median)
        high = hh - 1;
    }
}

#undef ELEM_SWAP

/*--------------------------------------------------------------------------*/

#define ELEM_SWAP(a,b) { register double t=(a);(a)=(b);(b)=t; }

static double quick_select_double(double arr[], int n) 
{
    int low, high ;
    int median;
    int middle, ll, hh;

    low = 0 ; high = n-1 ; median = (low + high) / 2;
    for (;;) {
        if (high <= low) /* One element only */
            return arr[median] ;

        if (high == low + 1) {  /* Two elements only */
            if (arr[low] > arr[high])
                ELEM_SWAP(arr[low], arr[high]) ;
            return arr[median] ;
        }

    /* Find median of low, middle and high items; swap into position low */
    middle = (low + high) / 2;
    if (arr[middle] > arr[high])    ELEM_SWAP(arr[middle], arr[high]) ;
    if (arr[low] > arr[high])       ELEM_SWAP(arr[low], arr[high]) ;
    if (arr[middle] > arr[low])     ELEM_SWAP(arr[middle], arr[low]) ;

    /* Swap low item (now in position middle) into position (low+1) */
    ELEM_SWAP(arr[middle], arr[low+1]) ;

    /* Nibble from each end towards middle, swapping items when stuck */
    ll = low + 1;
    hh = high;
    for (;;) {
        do ll++; while (arr[low] > arr[ll]) ;
        do hh--; while (arr[hh]  > arr[low]) ;

        if (hh < ll)
        break;

        ELEM_SWAP(arr[ll], arr[hh]) ;
    }

    /* Swap middle item (in position low) back into correct position */
    ELEM_SWAP(arr[low], arr[hh]) ;

    /* Re-set active partition */
    if (hh <= median)
        low = ll;
        if (hh >= median)
        high = hh - 1;
    }
}

#undef ELEM_SWAP


cfitsio/region.c0000644000225700000360000015500313246025103013433 0ustar  cagordonlhea#include 
#include 
#include 
#include 
#include 
#include "fitsio2.h"
#include "region.h"
static int Pt_in_Poly( double x, double y, int nPts, double *Pts );

/*---------------------------------------------------------------------------*/
int fits_read_rgnfile( const char *filename,
            WCSdata    *wcs,
            SAORegion  **Rgn,
            int        *status )
/*  Read regions from either a FITS or ASCII region file and return the information     */
/*  in the "SAORegion" structure.  If it is nonNULL, use wcs to convert the  */
/*  region coordinates to pixels.  Return an error if region is in degrees   */
/*  but no WCS data is provided.                                             */
/*---------------------------------------------------------------------------*/
{
  fitsfile *fptr;
  int tstatus = 0;

  if( *status ) return( *status );

  /* try to open as a FITS file - if that doesn't work treat as an ASCII file */

  fits_write_errmark();
  if ( ffopen(&fptr, filename, READONLY, &tstatus) ) {
    fits_clear_errmark();
    fits_read_ascii_region(filename, wcs, Rgn, status);
  } else {
    fits_read_fits_region(fptr, wcs, Rgn, status);
  }

  return(*status);

}
/*---------------------------------------------------------------------------*/
int fits_read_ascii_region( const char *filename,
			    WCSdata    *wcs,
			    SAORegion  **Rgn,
			    int        *status )
/*  Read regions from a SAO-style region file and return the information     */
/*  in the "SAORegion" structure.  If it is nonNULL, use wcs to convert the  */
/*  region coordinates to pixels.  Return an error if region is in degrees   */
/*  but no WCS data is provided.                                             */
/*---------------------------------------------------------------------------*/
{
   char     *currLine;
   char     *namePtr, *paramPtr, *currLoc;
   char     *pX, *pY, *endp;
   long     allocLen, lineLen, hh, mm, dd;
   double   *coords, X, Y, x, y, ss, div, xsave= 0., ysave= 0.;
   int      nParams, nCoords, negdec;
   int      i, done;
   FILE     *rgnFile;
   coordFmt cFmt;
   SAORegion *aRgn;
   RgnShape *newShape, *tmpShape;

   if( *status ) return( *status );

   aRgn = (SAORegion *)malloc( sizeof(SAORegion) );
   if( ! aRgn ) {
      ffpmsg("Couldn't allocate memory to hold Region file contents.");
      return(*status = MEMORY_ALLOCATION );
   }
   aRgn->nShapes    =    0;
   aRgn->Shapes     = NULL;
   if( wcs && wcs->exists )
      aRgn->wcs = *wcs;
   else
      aRgn->wcs.exists = 0;

   cFmt = pixel_fmt; /* set default format */

   /*  Allocate Line Buffer  */

   allocLen = 512;
   currLine = (char *)malloc( allocLen * sizeof(char) );
   if( !currLine ) {
      free( aRgn );
      ffpmsg("Couldn't allocate memory to hold Region file contents.");
      return(*status = MEMORY_ALLOCATION );
   }

   /*  Open Region File  */

   if( (rgnFile = fopen( filename, "r" ))==NULL ) {
      snprintf(currLine,allocLen,"Could not open Region file %s.",filename);
      ffpmsg( currLine );
      free( currLine );
      free( aRgn );
      return( *status = FILE_NOT_OPENED );
   }
   
   /*  Read in file, line by line  */
   /*  First, set error status in case file is empty */ 
   *status = FILE_NOT_OPENED;

   while( fgets(currLine,allocLen,rgnFile) != NULL ) {

      /* reset status if we got here */
      *status = 0;

      /*  Make sure we have a full line of text  */

      lineLen = strlen(currLine);
      while( lineLen==allocLen-1 && currLine[lineLen-1]!='\n' ) {
         currLoc = (char *)realloc( currLine, 2 * allocLen * sizeof(char) );
         if( !currLoc ) {
            ffpmsg("Couldn't allocate memory to hold Region file contents.");
            *status = MEMORY_ALLOCATION;
            goto error;
         } else {
            currLine = currLoc;
         }
         fgets( currLine+lineLen, allocLen+1, rgnFile );
         allocLen += allocLen;
         lineLen  += strlen(currLine+lineLen);
      }

      currLoc = currLine;
      if( *currLoc == '#' ) {

         /*  Look to see if it is followed by a format statement...  */
         /*  if not skip line                                        */

         currLoc++;
         while( isspace(*currLoc) ) currLoc++;
         if( !fits_strncasecmp( currLoc, "format:", 7 ) ) {
            if( aRgn->nShapes ) {
               ffpmsg("Format code encountered after reading 1 or more shapes.");
               *status = PARSE_SYNTAX_ERR;
               goto error;
            }
            currLoc += 7;
            while( isspace(*currLoc) ) currLoc++;
            if( !fits_strncasecmp( currLoc, "pixel", 5 ) ) {
               cFmt = pixel_fmt;
            } else if( !fits_strncasecmp( currLoc, "degree", 6 ) ) {
               cFmt = degree_fmt;
            } else if( !fits_strncasecmp( currLoc, "hhmmss", 6 ) ) {
               cFmt = hhmmss_fmt;
            } else if( !fits_strncasecmp( currLoc, "hms", 3 ) ) {
               cFmt = hhmmss_fmt;
            } else {
               ffpmsg("Unknown format code encountered in region file.");
               *status = PARSE_SYNTAX_ERR;
               goto error;
            }
         }

      } else if( !fits_strncasecmp( currLoc, "glob", 4 ) ) {
		  /* skip lines that begin with the word 'global' */

      } else {

         while( *currLoc != '\0' ) {

            namePtr  = currLoc;
            paramPtr = NULL;
            nParams  = 1;

            /*  Search for closing parenthesis  */

            done = 0;
            while( !done && !*status && *currLoc ) {
               switch (*currLoc) {
               case '(':
                  *currLoc = '\0';
                  currLoc++;
                  if( paramPtr )   /* Can't have two '(' in a region! */
                     *status = 1;
                  else
                     paramPtr = currLoc;
                  break;
               case ')':
                  *currLoc = '\0';
                  currLoc++;
                  if( !paramPtr )  /* Can't have a ')' without a '(' first */
                     *status = 1;
                  else
                     done = 1;
                  break;
               case '#':
               case '\n':
                  *currLoc = '\0';
                  if( !paramPtr )  /* Allow for a blank line */
                     done = 1;
                  break;
               case ':':  
                  currLoc++;
                  if ( paramPtr ) cFmt = hhmmss_fmt; /* set format if parameter has : */
                  break;
               case 'd':
                  currLoc++;
                  if ( paramPtr ) cFmt = degree_fmt; /* set format if parameter has d */  
                  break;
               case ',':
                  nParams++;  /* Fall through to default */
               default:
                  currLoc++;
                  break;
               }
            }
            if( *status || !done ) {
               ffpmsg( "Error reading Region file" );
               *status = PARSE_SYNTAX_ERR;
               goto error;
            }

            /*  Skip white space in region name  */

            while( isspace(*namePtr) ) namePtr++;

            /*  Was this a blank line? Or the end of the current one  */

            if( ! *namePtr && ! paramPtr ) continue;

            /*  Check for format code at beginning of the line */

            if( !fits_strncasecmp( namePtr, "image;", 6 ) ) {
				namePtr += 6;
				cFmt = pixel_fmt;
            } else if( !fits_strncasecmp( namePtr, "physical;", 9 ) ) {
                                namePtr += 9;
                                cFmt = pixel_fmt;
            } else if( !fits_strncasecmp( namePtr, "linear;", 7 ) ) {
                                namePtr += 7;
                                cFmt = pixel_fmt;
            } else if( !fits_strncasecmp( namePtr, "fk4;", 4 ) ) {
				namePtr += 4;
				cFmt = degree_fmt;
            } else if( !fits_strncasecmp( namePtr, "fk5;", 4 ) ) {
				namePtr += 4;
				cFmt = degree_fmt;
            } else if( !fits_strncasecmp( namePtr, "icrs;", 5 ) ) {
				namePtr += 5;
				cFmt = degree_fmt;

            /* the following 5 cases support region files created by POW 
	       (or ds9 Version 4.x) which
               may have lines containing  only a format code, not followed
               by a ';' (and with no region specifier on the line).  We use
               the 'continue' statement to jump to the end of the loop and
               then continue reading the next line of the region file. */

            } else if( !fits_strncasecmp( namePtr, "fk5", 3 ) ) {
				cFmt = degree_fmt;
                                continue;  /* supports POW region file format */
            } else if( !fits_strncasecmp( namePtr, "fk4", 3 ) ) {
				cFmt = degree_fmt;
                                continue;  /* supports POW region file format */
            } else if( !fits_strncasecmp( namePtr, "icrs", 4 ) ) {
				cFmt = degree_fmt;
                                continue;  /* supports POW region file format */
            } else if( !fits_strncasecmp( namePtr, "image", 5 ) ) {
				cFmt = pixel_fmt;
                                continue;  /* supports POW region file format */
            } else if( !fits_strncasecmp( namePtr, "physical", 8 ) ) {
				cFmt = pixel_fmt;
                                continue;  /* supports POW region file format */


            } else if( !fits_strncasecmp( namePtr, "galactic;", 9 ) ) {
               ffpmsg( "Galactic region coordinates not supported" );
               ffpmsg( namePtr );
               *status = PARSE_SYNTAX_ERR;
               goto error;
            } else if( !fits_strncasecmp( namePtr, "ecliptic;", 9 ) ) {
               ffpmsg( "ecliptic region coordinates not supported" );
               ffpmsg( namePtr );
               *status = PARSE_SYNTAX_ERR;
               goto error;
            }

            /**************************************************/
            /*  We've apparently found a region... Set it up  */
            /**************************************************/

            if( !(aRgn->nShapes % 10) ) {
               if( aRgn->Shapes )
                  tmpShape = (RgnShape *)realloc( aRgn->Shapes,
                                                  (10+aRgn->nShapes)
                                                  * sizeof(RgnShape) );
               else
                  tmpShape = (RgnShape *) malloc( 10 * sizeof(RgnShape) );
               if( tmpShape ) {
                  aRgn->Shapes = tmpShape;
               } else {
                  ffpmsg( "Failed to allocate memory for Region data");
                  *status = MEMORY_ALLOCATION;
                  goto error;
               }

            }
            newShape        = &aRgn->Shapes[aRgn->nShapes++];
            newShape->sign  = 1;
            newShape->shape = point_rgn;
	    for (i=0; i<8; i++) newShape->param.gen.p[i] = 0.0;
	    newShape->param.gen.a = 0.0;
	    newShape->param.gen.b = 0.0;
	    newShape->param.gen.sinT = 0.0;
	    newShape->param.gen.cosT = 0.0;

            while( isspace(*namePtr) ) namePtr++;
            
			/*  Check for the shape's sign  */

            if( *namePtr=='+' ) {
               namePtr++;
            } else if( *namePtr=='-' ) {
               namePtr++;
               newShape->sign = 0;
            }

            /* Skip white space in region name */

            while( isspace(*namePtr) ) namePtr++;
            if( *namePtr=='\0' ) {
               ffpmsg( "Error reading Region file" );
               *status = PARSE_SYNTAX_ERR;
               goto error;
            }
            lineLen = strlen( namePtr ) - 1;
            while( isspace(namePtr[lineLen]) ) namePtr[lineLen--] = '\0';

            /*  Now identify the region  */

            if(        !fits_strcasecmp( namePtr, "circle"  ) ) {
               newShape->shape = circle_rgn;
               if( nParams != 3 )
                  *status = PARSE_SYNTAX_ERR;
               nCoords = 2;
            } else if( !fits_strcasecmp( namePtr, "annulus" ) ) {
               newShape->shape = annulus_rgn;
               if( nParams != 4 )
                  *status = PARSE_SYNTAX_ERR;
               nCoords = 2;
            } else if( !fits_strcasecmp( namePtr, "ellipse" ) ) {
               if( nParams < 4 || nParams > 8 ) {
                  *status = PARSE_SYNTAX_ERR;
	       } else if ( nParams < 6 ) {
		 newShape->shape = ellipse_rgn;
		 newShape->param.gen.p[4] = 0.0;
	       } else {
		 newShape->shape = elliptannulus_rgn;
		 newShape->param.gen.p[6] = 0.0;
		 newShape->param.gen.p[7] = 0.0;
	       }
               nCoords = 2;
            } else if( !fits_strcasecmp( namePtr, "elliptannulus" ) ) {
               newShape->shape = elliptannulus_rgn;
               if( !( nParams==8 || nParams==6 ) )
                  *status = PARSE_SYNTAX_ERR;
               newShape->param.gen.p[6] = 0.0;
               newShape->param.gen.p[7] = 0.0;
               nCoords = 2;
            } else if( !fits_strcasecmp( namePtr, "box"    ) 
                    || !fits_strcasecmp( namePtr, "rotbox" ) ) {
	       if( nParams < 4 || nParams > 8 ) {
		 *status = PARSE_SYNTAX_ERR;
	       } else if ( nParams < 6 ) {
		 newShape->shape = box_rgn;
		 newShape->param.gen.p[4] = 0.0;
	       } else {
		  newShape->shape = boxannulus_rgn;
		  newShape->param.gen.p[6] = 0.0;
		  newShape->param.gen.p[7] = 0.0;
	       }
	       nCoords = 2;
            } else if( !fits_strcasecmp( namePtr, "rectangle"    )
                    || !fits_strcasecmp( namePtr, "rotrectangle" ) ) {
               newShape->shape = rectangle_rgn;
               if( nParams < 4 || nParams > 5 )
                  *status = PARSE_SYNTAX_ERR;
               newShape->param.gen.p[4] = 0.0;
               nCoords = 4;
            } else if( !fits_strcasecmp( namePtr, "diamond"    )
                    || !fits_strcasecmp( namePtr, "rotdiamond" )
                    || !fits_strcasecmp( namePtr, "rhombus"    )
                    || !fits_strcasecmp( namePtr, "rotrhombus" ) ) {
               newShape->shape = diamond_rgn;
               if( nParams < 4 || nParams > 5 )
                  *status = PARSE_SYNTAX_ERR;
               newShape->param.gen.p[4] = 0.0;
               nCoords = 2;
            } else if( !fits_strcasecmp( namePtr, "sector"  )
                    || !fits_strcasecmp( namePtr, "pie"     ) ) {
               newShape->shape = sector_rgn;
               if( nParams != 4 )
                  *status = PARSE_SYNTAX_ERR;
               nCoords = 2;
            } else if( !fits_strcasecmp( namePtr, "point"   ) ) {
               newShape->shape = point_rgn;
               if( nParams != 2 )
                  *status = PARSE_SYNTAX_ERR;
               nCoords = 2;
            } else if( !fits_strcasecmp( namePtr, "line"    ) ) {
               newShape->shape = line_rgn;
               if( nParams != 4 )
                  *status = PARSE_SYNTAX_ERR;
               nCoords = 4;
            } else if( !fits_strcasecmp( namePtr, "polygon" ) ) {
               newShape->shape = poly_rgn;
               if( nParams < 6 || (nParams&1) )
                  *status = PARSE_SYNTAX_ERR;
               nCoords = nParams;
            } else if( !fits_strcasecmp( namePtr, "panda" ) ) {
               newShape->shape = panda_rgn;
               if( nParams != 8 )
                  *status = PARSE_SYNTAX_ERR;
               nCoords = 2;
            } else if( !fits_strcasecmp( namePtr, "epanda" ) ) {
               newShape->shape = epanda_rgn;
               if( nParams < 10 || nParams > 11 )
                  *status = PARSE_SYNTAX_ERR;
               newShape->param.gen.p[10] = 0.0;
               nCoords = 2;
            } else if( !fits_strcasecmp( namePtr, "bpanda" ) ) {
               newShape->shape = bpanda_rgn;
               if( nParams < 10 || nParams > 11 )
                  *status = PARSE_SYNTAX_ERR;
               newShape->param.gen.p[10] = 0.0;
               nCoords = 2;
            } else {
               ffpmsg( "Unrecognized region found in region file:" );
               ffpmsg( namePtr );
               *status = PARSE_SYNTAX_ERR;
               goto error;
            }
            if( *status ) {
               ffpmsg( "Wrong number of parameters found for region" );
               ffpmsg( namePtr );
               goto error;
            }

            /*  Parse Parameter string... convert to pixels if necessary  */

            if( newShape->shape==poly_rgn ) {
               newShape->param.poly.Pts = (double *)malloc( nParams
                                                            * sizeof(double) );
               if( !newShape->param.poly.Pts ) {
                  ffpmsg(
                      "Could not allocate memory to hold polygon parameters" );
                  *status = MEMORY_ALLOCATION;
                  goto error;
               }
               newShape->param.poly.nPts = nParams;
               coords = newShape->param.poly.Pts;
            } else
               coords = newShape->param.gen.p;

            /*  Parse the initial "WCS?" coordinates  */
            for( i=0; iexists ) {
                     ffpmsg("WCS information needed to convert region coordinates.");
                     *status = NO_WCS_KEY;
                     goto error;
                  }
                  
                  if( ffxypx(  X,  Y, wcs->xrefval, wcs->yrefval,
                                      wcs->xrefpix, wcs->yrefpix,
                                      wcs->xinc,    wcs->yinc,
                                      wcs->rot,     wcs->type,
                              &x, &y, status ) ) {
                     ffpmsg("Error converting region to pixel coordinates.");
                     goto error;
                  }
                  X = x; Y = y;
               }
               coords[i]   = X;
               coords[i+1] = Y;

            }

            /*  Read in remaining parameters...  */

            for( ; ixrefval, wcs->yrefval,
			       wcs->xrefpix, wcs->yrefpix,
			       wcs->xinc,    wcs->yinc,
			       wcs->rot,     wcs->type,
                               &x, &y, status ) ) {
		     ffpmsg("Error converting region to pixel coordinates.");
		     goto error;
		  }
		 
		  coords[i] = sqrt( pow(x-coords[0],2) + pow(y-coords[1],2) );

               }
            }

	    /* special case for elliptannulus and boxannulus if only one angle
	       was given */

	    if ( (newShape->shape == elliptannulus_rgn || 
		  newShape->shape == boxannulus_rgn ) && nParams == 7 ) {
	      coords[7] = coords[6];
	    }

            /* Also, correct the position angle for any WCS rotation:  */
            /*    If regions are specified in WCS coordintes, then the angles */
            /*    are relative to the WCS system, not the pixel X,Y system */

	    if( cFmt!=pixel_fmt ) {	    
	      switch( newShape->shape ) {
	      case sector_rgn:
	      case panda_rgn:
		coords[2] += (wcs->rot);
		coords[3] += (wcs->rot);
		break;
	      case box_rgn:
	      case rectangle_rgn:
	      case diamond_rgn:
	      case ellipse_rgn:
		coords[4] += (wcs->rot);
		break;
	      case boxannulus_rgn:
	      case elliptannulus_rgn:
		coords[6] += (wcs->rot);
		coords[7] += (wcs->rot);
		break;
	      case epanda_rgn:
	      case bpanda_rgn:
		coords[2] += (wcs->rot);
		coords[3] += (wcs->rot);
		coords[10] += (wcs->rot);
              default:
                break;
	      }
	    }

	    /* do some precalculations to speed up tests */

	    fits_setup_shape(newShape);

         }  /* End of while( *currLoc ) */
/*
  if (coords)printf("%.8f %.8f %.8f %.8f %.8f\n",
   coords[0],coords[1],coords[2],coords[3],coords[4]); 
*/
      }  /* End of if...else parse line */
   }   /* End of while( fgets(rgnFile) ) */

   /* set up component numbers */

   fits_set_region_components( aRgn );

error:

   if( *status ) {
      fits_free_region( aRgn );
   } else {
      *Rgn = aRgn;
   }

   fclose( rgnFile );
   free( currLine );

   return( *status );
}

/*---------------------------------------------------------------------------*/
int fits_in_region( double    X,
            double    Y,
            SAORegion *Rgn )
/*  Test if the given point is within the region described by Rgn.  X and    */
/*  Y are in pixel coordinates.                                              */
/*---------------------------------------------------------------------------*/
{
   double x, y, dx, dy, xprime, yprime, r, th;
   RgnShape *Shapes;
   int i, cur_comp;
   int result, comp_result;

   Shapes = Rgn->Shapes;

   result = 0;
   comp_result = 0;
   cur_comp = Rgn->Shapes[0].comp;

   for( i=0; inShapes; i++, Shapes++ ) {

     /* if this region has a different component number to the last one  */
     /*	then replace the accumulated selection logical with the union of */
     /*	the current logical and the total logical. Reinitialize the      */
     /* temporary logical.                                               */

     if ( i==0 || Shapes->comp != cur_comp ) {
       result = result || comp_result;
       cur_comp = Shapes->comp;
       /* if an excluded region is given first, then implicitly   */
       /* assume a previous shape that includes the entire image. */
       comp_result = !Shapes->sign;
     }

    /* only need to test if  */
    /*   the point is not already included and this is an include region, */
    /* or the point is included and this is an excluded region */

    if ( (!comp_result && Shapes->sign) || (comp_result && !Shapes->sign) ) { 

      comp_result = 1;

      switch( Shapes->shape ) {

      case box_rgn:
         /*  Shift origin to center of region  */
         xprime = X - Shapes->param.gen.p[0];
         yprime = Y - Shapes->param.gen.p[1];

         /*  Rotate point to region's orientation  */
         x =  xprime * Shapes->param.gen.cosT + yprime * Shapes->param.gen.sinT;
         y = -xprime * Shapes->param.gen.sinT + yprime * Shapes->param.gen.cosT;

         dx = 0.5 * Shapes->param.gen.p[2];
         dy = 0.5 * Shapes->param.gen.p[3];
         if( (x < -dx) || (x > dx) || (y < -dy) || (y > dy) )
            comp_result = 0;
         break;

      case boxannulus_rgn:
         /*  Shift origin to center of region  */
         xprime = X - Shapes->param.gen.p[0];
         yprime = Y - Shapes->param.gen.p[1];

         /*  Rotate point to region's orientation  */
         x =  xprime * Shapes->param.gen.cosT + yprime * Shapes->param.gen.sinT;
         y = -xprime * Shapes->param.gen.sinT + yprime * Shapes->param.gen.cosT;

         dx = 0.5 * Shapes->param.gen.p[4];
         dy = 0.5 * Shapes->param.gen.p[5];
         if( (x < -dx) || (x > dx) || (y < -dy) || (y > dy) ) {
	   comp_result = 0;
	 } else {
	   /* Repeat test for inner box */
	   x =  xprime * Shapes->param.gen.b + yprime * Shapes->param.gen.a;
	   y = -xprime * Shapes->param.gen.a + yprime * Shapes->param.gen.b;
	   
	   dx = 0.5 * Shapes->param.gen.p[2];
	   dy = 0.5 * Shapes->param.gen.p[3];
	   if( (x >= -dx) && (x <= dx) && (y >= -dy) && (y <= dy) )
	     comp_result = 0;
	 }
         break;

      case rectangle_rgn:
         /*  Shift origin to center of region  */
         xprime = X - Shapes->param.gen.p[5];
         yprime = Y - Shapes->param.gen.p[6];

         /*  Rotate point to region's orientation  */
         x =  xprime * Shapes->param.gen.cosT + yprime * Shapes->param.gen.sinT;
         y = -xprime * Shapes->param.gen.sinT + yprime * Shapes->param.gen.cosT;

         dx = Shapes->param.gen.a;
         dy = Shapes->param.gen.b;
         if( (x < -dx) || (x > dx) || (y < -dy) || (y > dy) )
            comp_result = 0;
         break;

      case diamond_rgn:
         /*  Shift origin to center of region  */
         xprime = X - Shapes->param.gen.p[0];
         yprime = Y - Shapes->param.gen.p[1];

         /*  Rotate point to region's orientation  */
         x =  xprime * Shapes->param.gen.cosT + yprime * Shapes->param.gen.sinT;
         y = -xprime * Shapes->param.gen.sinT + yprime * Shapes->param.gen.cosT;

         dx = 0.5 * Shapes->param.gen.p[2];
         dy = 0.5 * Shapes->param.gen.p[3];
         r  = fabs(x/dx) + fabs(y/dy);
         if( r > 1 )
            comp_result = 0;
         break;

      case circle_rgn:
         /*  Shift origin to center of region  */
         x = X - Shapes->param.gen.p[0];
         y = Y - Shapes->param.gen.p[1];

         r  = x*x + y*y;
         if ( r > Shapes->param.gen.a )
            comp_result = 0;
         break;

      case annulus_rgn:
         /*  Shift origin to center of region  */
         x = X - Shapes->param.gen.p[0];
         y = Y - Shapes->param.gen.p[1];

         r = x*x + y*y;
         if ( r < Shapes->param.gen.a || r > Shapes->param.gen.b )
            comp_result = 0;
         break;

      case sector_rgn:
         /*  Shift origin to center of region  */
         x = X - Shapes->param.gen.p[0];
         y = Y - Shapes->param.gen.p[1];

         if( x || y ) {
            r = atan2( y, x ) * RadToDeg;
            if( Shapes->param.gen.p[2] <= Shapes->param.gen.p[3] ) {
               if( r < Shapes->param.gen.p[2] || r > Shapes->param.gen.p[3] )
                  comp_result = 0;
            } else {
               if( r < Shapes->param.gen.p[2] && r > Shapes->param.gen.p[3] )
                  comp_result = 0;
            }
         }
         break;

      case ellipse_rgn:
         /*  Shift origin to center of region  */
         xprime = X - Shapes->param.gen.p[0];
         yprime = Y - Shapes->param.gen.p[1];

         /*  Rotate point to region's orientation  */
         x =  xprime * Shapes->param.gen.cosT + yprime * Shapes->param.gen.sinT;
         y = -xprime * Shapes->param.gen.sinT + yprime * Shapes->param.gen.cosT;

         x /= Shapes->param.gen.p[2];
         y /= Shapes->param.gen.p[3];
         r = x*x + y*y;
         if( r>1.0 )
            comp_result = 0;
         break;

      case elliptannulus_rgn:
         /*  Shift origin to center of region  */
         xprime = X - Shapes->param.gen.p[0];
         yprime = Y - Shapes->param.gen.p[1];

         /*  Rotate point to outer ellipse's orientation  */
         x =  xprime * Shapes->param.gen.cosT + yprime * Shapes->param.gen.sinT;
         y = -xprime * Shapes->param.gen.sinT + yprime * Shapes->param.gen.cosT;

         x /= Shapes->param.gen.p[4];
         y /= Shapes->param.gen.p[5];
         r = x*x + y*y;
         if( r>1.0 )
            comp_result = 0;
         else {
            /*  Repeat test for inner ellipse  */
            x =  xprime * Shapes->param.gen.b + yprime * Shapes->param.gen.a;
            y = -xprime * Shapes->param.gen.a + yprime * Shapes->param.gen.b;

            x /= Shapes->param.gen.p[2];
            y /= Shapes->param.gen.p[3];
            r = x*x + y*y;
            if( r<1.0 )
               comp_result = 0;
         }
         break;

      case line_rgn:
         /*  Shift origin to first point of line  */
         xprime = X - Shapes->param.gen.p[0];
         yprime = Y - Shapes->param.gen.p[1];

         /*  Rotate point to line's orientation  */
         x =  xprime * Shapes->param.gen.cosT + yprime * Shapes->param.gen.sinT;
         y = -xprime * Shapes->param.gen.sinT + yprime * Shapes->param.gen.cosT;

         if( (y < -0.5) || (y >= 0.5) || (x < -0.5)
             || (x >= Shapes->param.gen.a) )
            comp_result = 0;
         break;

      case point_rgn:
         /*  Shift origin to center of region  */
         x = X - Shapes->param.gen.p[0];
         y = Y - Shapes->param.gen.p[1];

         if ( (x<-0.5) || (x>=0.5) || (y<-0.5) || (y>=0.5) )
            comp_result = 0;
         break;

      case poly_rgn:
         if( Xxmin || X>Shapes->xmax
             || Yymin || Y>Shapes->ymax )
            comp_result = 0;
         else
            comp_result = Pt_in_Poly( X, Y, Shapes->param.poly.nPts,
                                       Shapes->param.poly.Pts );
         break;

      case panda_rgn:
         /*  Shift origin to center of region  */
         x = X - Shapes->param.gen.p[0];
         y = Y - Shapes->param.gen.p[1];

         r = x*x + y*y;
         if ( r < Shapes->param.gen.a || r > Shapes->param.gen.b ) {
	   comp_result = 0;
	 } else {
	   if( x || y ) {
	     th = atan2( y, x ) * RadToDeg;
	     if( Shapes->param.gen.p[2] <= Shapes->param.gen.p[3] ) {
               if( th < Shapes->param.gen.p[2] || th > Shapes->param.gen.p[3] )
		 comp_result = 0;
	     } else {
               if( th < Shapes->param.gen.p[2] && th > Shapes->param.gen.p[3] )
		 comp_result = 0;
	     }
	   }
         }
         break;

      case epanda_rgn:
         /*  Shift origin to center of region  */
         xprime = X - Shapes->param.gen.p[0];
         yprime = Y - Shapes->param.gen.p[1];

         /*  Rotate point to region's orientation  */
         x =  xprime * Shapes->param.gen.cosT + yprime * Shapes->param.gen.sinT;
         y = -xprime * Shapes->param.gen.sinT + yprime * Shapes->param.gen.cosT;
	 xprime = x;
	 yprime = y;

	 /* outer region test */
         x = xprime/Shapes->param.gen.p[7];
         y = yprime/Shapes->param.gen.p[8];
         r = x*x + y*y;
	 if ( r>1.0 )
	   comp_result = 0;
	 else {
	   /* inner region test */
	   x = xprime/Shapes->param.gen.p[5];
	   y = yprime/Shapes->param.gen.p[6];
	   r = x*x + y*y;
	   if ( r<1.0 )
	     comp_result = 0;
	   else {
	     /* angle test */
	     if( xprime || yprime ) {
	       th = atan2( yprime, xprime ) * RadToDeg;
	       if( Shapes->param.gen.p[2] <= Shapes->param.gen.p[3] ) {
		 if( th < Shapes->param.gen.p[2] || th > Shapes->param.gen.p[3] )
		   comp_result = 0;
	       } else {
		 if( th < Shapes->param.gen.p[2] && th > Shapes->param.gen.p[3] )
		   comp_result = 0;
	       }
	     }
	   }
	 }
         break;

      case bpanda_rgn:
         /*  Shift origin to center of region  */
         xprime = X - Shapes->param.gen.p[0];
         yprime = Y - Shapes->param.gen.p[1];

         /*  Rotate point to region's orientation  */
         x =  xprime * Shapes->param.gen.cosT + yprime * Shapes->param.gen.sinT;
         y = -xprime * Shapes->param.gen.sinT + yprime * Shapes->param.gen.cosT;

	 /* outer box test */
         dx = 0.5 * Shapes->param.gen.p[7];
         dy = 0.5 * Shapes->param.gen.p[8];
         if( (x < -dx) || (x > dx) || (y < -dy) || (y > dy) )
	   comp_result = 0;
	 else {
	   /* inner box test */
	   dx = 0.5 * Shapes->param.gen.p[5];
	   dy = 0.5 * Shapes->param.gen.p[6];
	   if( (x >= -dx) && (x <= dx) && (y >= -dy) && (y <= dy) )
	     comp_result = 0;
	   else {
	     /* angle test */
	     if( x || y ) {
	       th = atan2( y, x ) * RadToDeg;
	       if( Shapes->param.gen.p[2] <= Shapes->param.gen.p[3] ) {
		 if( th < Shapes->param.gen.p[2] || th > Shapes->param.gen.p[3] )
		   comp_result = 0;
	       } else {
		 if( th < Shapes->param.gen.p[2] && th > Shapes->param.gen.p[3] )
		   comp_result = 0;
	       }
	     }
	   }
	 }
         break;
      }

      if( !Shapes->sign ) comp_result = !comp_result;

     } 

   }

   result = result || comp_result;
   
   return( result );
}

/*---------------------------------------------------------------------------*/
void fits_free_region( SAORegion *Rgn )
/*   Free up memory allocated to hold the region data.                       */
/*---------------------------------------------------------------------------*/
{
   int i;

   for( i=0; inShapes; i++ )
      if( Rgn->Shapes[i].shape == poly_rgn )
         free( Rgn->Shapes[i].param.poly.Pts );
   if( Rgn->Shapes )
      free( Rgn->Shapes );
   free( Rgn );
}

/*---------------------------------------------------------------------------*/
static int Pt_in_Poly( double x,
                       double y,
                       int nPts,
                       double *Pts )
/*  Internal routine for testing whether the coordinate x,y is within the    */
/*  polygon region traced out by the array Pts.                              */
/*---------------------------------------------------------------------------*/
{
   int i, j, flag=0;
   double prevX, prevY;
   double nextX, nextY;
   double dx, dy, Dy;

   nextX = Pts[nPts-2];
   nextY = Pts[nPts-1];

   for( i=0; iprevY && y>=nextY) || (yprevX && x>=nextX) )
         continue;
      
      /* Check to see if x,y lies right on the segment */

      if( x>=prevX || x>nextX ) {
         dy = y - prevY;
         Dy = nextY - prevY;

         if( fabs(Dy)<1e-10 ) {
            if( fabs(dy)<1e-10 )
               return( 1 );
            else
               continue;
         }

         dx = prevX + ( (nextX-prevX)/(Dy) ) * dy - x;
         if( dx < -1e-10 )
            continue;
         if( dx <  1e-10 )
            return( 1 );
      }

      /* There is an intersection! Make sure it isn't a V point.  */

      if( y != prevY ) {
         flag = 1 - flag;
      } else {
         j = i+1;  /* Point to Y component */
         do {
            if( j>1 )
               j -= 2;
            else
               j = nPts-1;
         } while( y == Pts[j] );

         if( (nextY-y)*(y-Pts[j]) > 0 )
            flag = 1-flag;
      }

   }
   return( flag );
}
/*---------------------------------------------------------------------------*/
void fits_set_region_components ( SAORegion *aRgn )
{
/* 
   Internal routine to turn a collection of regions read from an ascii file into
   the more complex structure that is allowed by the FITS REGION extension with
   multiple components. Regions are anded within components and ored between them
   ie for a pixel to be selected it must be selected by at least one component
   and to be selected by a component it must be selected by all that component's
   shapes.

   The algorithm is to replicate every exclude region after every include
   region before it in the list. eg reg1, reg2, -reg3, reg4, -reg5 becomes
   (reg1, -reg3, -reg5), (reg2, -reg5, -reg3), (reg4, -reg5) where the
   parentheses designate components.
*/

  int i, j, k, icomp;

/* loop round shapes */

  i = 0;
  while ( inShapes ) {

    /* first do the case of an exclude region */

    if ( !aRgn->Shapes[i].sign ) {

      /* we need to run back through the list copying the current shape as
	 required. start by findin the first include shape before this exclude */

      j = i-1;
      while ( j > 0 && !aRgn->Shapes[j].sign ) j--;

      /* then go back one more shape */

      j--;

      /* and loop back through the regions */

      while ( j >= 0 ) {

	/* if this is an include region then insert a copy of the exclude
	   region immediately after it */

	if ( aRgn->Shapes[j].sign ) {

	  aRgn->Shapes = (RgnShape *) realloc (aRgn->Shapes,(1+aRgn->nShapes)*sizeof(RgnShape));
	  aRgn->nShapes++;
	  for (k=aRgn->nShapes-1; k>j+1; k--) aRgn->Shapes[k] = aRgn->Shapes[k-1];

	  i++;
	  aRgn->Shapes[j+1] = aRgn->Shapes[i];

	}

	j--;

      }

    }

    i++;

  }

  /* now set the component numbers */

  icomp = 0;
  for ( i=0; inShapes; i++ ) {
    if ( aRgn->Shapes[i].sign ) icomp++;
    aRgn->Shapes[i].comp = icomp;

    /*
    printf("i = %d, shape = %d, sign = %d, comp = %d\n", i, aRgn->Shapes[i].shape, aRgn->Shapes[i].sign, aRgn->Shapes[i].comp);
    */

  }

  return;

}

/*---------------------------------------------------------------------------*/
void fits_setup_shape ( RgnShape *newShape)
{
/* Perform some useful calculations now to speed up filter later             */

  double X, Y, R;
  double *coords;
  int i;

  if ( newShape->shape == poly_rgn ) {
    coords = newShape->param.poly.Pts;
  } else {
    coords = newShape->param.gen.p;
  }

  switch( newShape->shape ) {
  case circle_rgn:
    newShape->param.gen.a = coords[2] * coords[2];
    break;
  case annulus_rgn:
    newShape->param.gen.a = coords[2] * coords[2];
    newShape->param.gen.b = coords[3] * coords[3];
    break;
  case sector_rgn:
    while( coords[2]> 180.0 ) coords[2] -= 360.0;
    while( coords[2]<=-180.0 ) coords[2] += 360.0;
    while( coords[3]> 180.0 ) coords[3] -= 360.0;
    while( coords[3]<=-180.0 ) coords[3] += 360.0;
    break;
  case ellipse_rgn:
    newShape->param.gen.sinT = sin( myPI * (coords[4] / 180.0) );
    newShape->param.gen.cosT = cos( myPI * (coords[4] / 180.0) );
    break;
  case elliptannulus_rgn:
    newShape->param.gen.a    = sin( myPI * (coords[6] / 180.0) );
    newShape->param.gen.b    = cos( myPI * (coords[6] / 180.0) );
    newShape->param.gen.sinT = sin( myPI * (coords[7] / 180.0) );
    newShape->param.gen.cosT = cos( myPI * (coords[7] / 180.0) );
    break;
  case box_rgn:
    newShape->param.gen.sinT = sin( myPI * (coords[4] / 180.0) );
    newShape->param.gen.cosT = cos( myPI * (coords[4] / 180.0) );
    break;
  case boxannulus_rgn:
    newShape->param.gen.a    = sin( myPI * (coords[6] / 180.0) );
    newShape->param.gen.b    = cos( myPI * (coords[6] / 180.0) );
    newShape->param.gen.sinT = sin( myPI * (coords[7] / 180.0) );
    newShape->param.gen.cosT = cos( myPI * (coords[7] / 180.0) );
    break;
  case rectangle_rgn:
    newShape->param.gen.sinT = sin( myPI * (coords[4] / 180.0) );
    newShape->param.gen.cosT = cos( myPI * (coords[4] / 180.0) );
    X = 0.5 * ( coords[2]-coords[0] );
    Y = 0.5 * ( coords[3]-coords[1] );
    newShape->param.gen.a = fabs( X * newShape->param.gen.cosT
				  + Y * newShape->param.gen.sinT );
    newShape->param.gen.b = fabs( Y * newShape->param.gen.cosT
				  - X * newShape->param.gen.sinT );
    newShape->param.gen.p[5] = 0.5 * ( coords[2]+coords[0] );
    newShape->param.gen.p[6] = 0.5 * ( coords[3]+coords[1] );
    break;
  case diamond_rgn:
    newShape->param.gen.sinT = sin( myPI * (coords[4] / 180.0) );
    newShape->param.gen.cosT = cos( myPI * (coords[4] / 180.0) );
    break;
  case line_rgn:
    X = coords[2] - coords[0];
    Y = coords[3] - coords[1];
    R = sqrt( X*X + Y*Y );
    newShape->param.gen.sinT = ( R ? Y/R : 0.0 );
    newShape->param.gen.cosT = ( R ? X/R : 1.0 );
    newShape->param.gen.a    = R + 0.5;
    break;
  case panda_rgn:
    while( coords[2]> 180.0 ) coords[2] -= 360.0;
    while( coords[2]<=-180.0 ) coords[2] += 360.0;
    while( coords[3]> 180.0 ) coords[3] -= 360.0;
    while( coords[3]<=-180.0 ) coords[3] += 360.0;
    newShape->param.gen.a = newShape->param.gen.p[5]*newShape->param.gen.p[5];
    newShape->param.gen.b = newShape->param.gen.p[6]*newShape->param.gen.p[6];
    break;
  case epanda_rgn:
  case bpanda_rgn:
    while( coords[2]> 180.0 ) coords[2] -= 360.0;
    while( coords[2]<=-180.0 ) coords[2] += 360.0;
    while( coords[3]> 180.0 ) coords[3] -= 360.0;
    while( coords[3]<=-180.0 ) coords[3] += 360.0;
    newShape->param.gen.sinT = sin( myPI * (coords[10] / 180.0) );
    newShape->param.gen.cosT = cos( myPI * (coords[10] / 180.0) );
    break;
  default:
    break;
  }

  /*  Set the xmin, xmax, ymin, ymax elements of the RgnShape structure */

  /* For everything which has first two parameters as center position just */
  /* find a circle that encompasses the region and use it to set the       */
  /* bounding box                                                          */

  R = -1.0;

  switch ( newShape->shape ) {

  case circle_rgn:
    R = coords[2];
    break;

  case annulus_rgn:
    R = coords[3];
    break;

  case ellipse_rgn:
    if ( coords[2] > coords[3] ) {
      R = coords[2];
    } else {
      R = coords[3];
    }
    break;

  case elliptannulus_rgn:
    if ( coords[4] > coords[5] ) {
      R = coords[4];
    } else {
      R = coords[5];
    }
    break;

  case box_rgn:
    R = sqrt(coords[2]*coords[2]+
	     coords[3]*coords[3])/2.0;
    break;

  case boxannulus_rgn:
    R = sqrt(coords[4]*coords[5]+
	     coords[4]*coords[5])/2.0;
    break;

  case diamond_rgn:
    if ( coords[2] > coords[3] ) {
      R = coords[2]/2.0;
    } else {
      R = coords[3]/2.0;
    }
    break;
    
  case point_rgn:
    R = 1.0;
    break;

  case panda_rgn:
    R = coords[6];
    break;

  case epanda_rgn:
    if ( coords[7] > coords[8] ) {
      R = coords[7];
    } else {
      R = coords[8];
    }
    break;

  case bpanda_rgn:
    R = sqrt(coords[7]*coords[8]+
	     coords[7]*coords[8])/2.0;
    break;

  default:
    break;
  }

  if ( R > 0.0 ) {

    newShape->xmin = coords[0] - R;
    newShape->xmax = coords[0] + R;
    newShape->ymin = coords[1] - R;
    newShape->ymax = coords[1] + R;

    return;

  }

  /* Now do the rest of the shapes that require individual methods */

  switch ( newShape->shape ) {

  case rectangle_rgn:
    R = sqrt((coords[5]-coords[0])*(coords[5]-coords[0])+
	     (coords[6]-coords[1])*(coords[6]-coords[1]));
    newShape->xmin = coords[5] - R;
    newShape->xmax = coords[5] + R;
    newShape->ymin = coords[6] - R;
    newShape->ymax = coords[6] + R;
    break;

  case poly_rgn:
    newShape->xmin = coords[0];
    newShape->xmax = coords[0];
    newShape->ymin = coords[1];
    newShape->ymax = coords[1];
    for( i=2; i < newShape->param.poly.nPts; ) {
      if( newShape->xmin > coords[i] ) /* Min X */
	newShape->xmin = coords[i];
      if( newShape->xmax < coords[i] ) /* Max X */
	newShape->xmax = coords[i];
      i++;
      if( newShape->ymin > coords[i] ) /* Min Y */
	newShape->ymin = coords[i];
      if( newShape->ymax < coords[i] ) /* Max Y */
	newShape->ymax = coords[i];
      i++;
    }
    break;

  case line_rgn:
    if ( coords[0] > coords[2] ) {
      newShape->xmin = coords[2];
      newShape->xmax = coords[0];
    } else {
      newShape->xmin = coords[0];
      newShape->xmax = coords[2];
    }
    if ( coords[1] > coords[3] ) {
      newShape->ymin = coords[3];
      newShape->ymax = coords[1];
    } else {
      newShape->ymin = coords[1];
      newShape->ymax = coords[3];
    }

    break;

    /* sector doesn't have min and max so indicate by setting max < min */

  case sector_rgn:
    newShape->xmin = 1.0;
    newShape->xmax = -1.0;
    newShape->ymin = 1.0;
    newShape->ymax = -1.0;
    break;

  default:
    break;
  }

  return;

}

/*---------------------------------------------------------------------------*/
int fits_read_fits_region ( fitsfile *fptr, 
			    WCSdata *wcs, 
			    SAORegion **Rgn, 
			    int *status)
/*  Read regions from a FITS region extension and return the information     */
/*  in the "SAORegion" structure.  If it is nonNULL, use wcs to convert the  */
/*  region coordinates to pixels.  Return an error if region is in degrees   */
/*  but no WCS data is provided.                                             */
/*---------------------------------------------------------------------------*/
{

  int i, j, icol[6], idum, anynul, npos;
  int dotransform, got_component = 1, tstatus;
  long icsize[6];
  double X, Y, Theta, Xsave = 0, Ysave = 0, Xpos, Ypos;
  double *coords;
  char *cvalue, *cvalue2;
  char comment[FLEN_COMMENT];
  char colname[6][FLEN_VALUE] = {"X", "Y", "SHAPE", "R", "ROTANG", "COMPONENT"};
  char shapename[17][FLEN_VALUE] = {"POINT","CIRCLE","ELLIPSE","ANNULUS",
				    "ELLIPTANNULUS","BOX","ROTBOX","BOXANNULUS",
				    "RECTANGLE","ROTRECTANGLE","POLYGON","PIE",
				    "SECTOR","DIAMOND","RHOMBUS","ROTDIAMOND",
				    "ROTRHOMBUS"};
  int shapetype[17] = {point_rgn, circle_rgn, ellipse_rgn, annulus_rgn, 
		       elliptannulus_rgn, box_rgn, box_rgn, boxannulus_rgn, 
		       rectangle_rgn, rectangle_rgn, poly_rgn, sector_rgn, 
		       sector_rgn, diamond_rgn, diamond_rgn, diamond_rgn, 
		       diamond_rgn};
  SAORegion *aRgn;
  RgnShape *newShape;
  WCSdata *regwcs = 0;

  if ( *status ) return( *status );

  aRgn = (SAORegion *)malloc( sizeof(SAORegion) );
  if( ! aRgn ) {
    ffpmsg("Couldn't allocate memory to hold Region file contents.");
    return(*status = MEMORY_ALLOCATION );
  }
  aRgn->nShapes    =    0;
  aRgn->Shapes     = NULL;
  if( wcs && wcs->exists )
    aRgn->wcs = *wcs;
  else
    aRgn->wcs.exists = 0;

  /* See if we are already positioned to a region extension, else */
  /* move to the REGION extension (file is already open). */

  tstatus = 0;
  for (i=0; i<5; i++) {
    ffgcno(fptr, CASEINSEN, colname[i], &icol[i], &tstatus);
  }

  if (tstatus) {
    /* couldn't find the required columns, so search for "REGION" extension */
    if ( ffmnhd(fptr, BINARY_TBL, "REGION", 1, status) ) {
      ffpmsg("Could not move to REGION extension.");
      goto error;
    }
  }

  /* get the number of shapes and allocate memory */

  if ( ffgky(fptr, TINT, "NAXIS2", &aRgn->nShapes, comment, status) ) {
    ffpmsg("Could not read NAXIS2 keyword.");
    goto error;
  }

  aRgn->Shapes = (RgnShape *) malloc(aRgn->nShapes * sizeof(RgnShape));
  if ( !aRgn->Shapes ) {
    ffpmsg( "Failed to allocate memory for Region data");
    *status = MEMORY_ALLOCATION;
    goto error;
  }

  /* get the required column numbers */

  for (i=0; i<5; i++) {
    if ( ffgcno(fptr, CASEINSEN, colname[i], &icol[i], status) ) {
      ffpmsg("Could not find column.");
      goto error;
    }
  }

  /* try to get the optional column numbers */

  if ( ffgcno(fptr, CASEINSEN, colname[5], &icol[5], status) ) {
       got_component = 0;
  }

  /* if there was input WCS then read the WCS info for the region in case they */
  /* are different and we have to transform */

  dotransform = 0;
  if ( aRgn->wcs.exists ) {
    regwcs = (WCSdata *) malloc ( sizeof(WCSdata) );
    if ( !regwcs ) {
      ffpmsg( "Failed to allocate memory for Region WCS data");
      *status = MEMORY_ALLOCATION;
      goto error;
    }

    regwcs->exists = 1;
    if ( ffgtcs(fptr, icol[0], icol[1], ®wcs->xrefval,  ®wcs->yrefval,
		®wcs->xrefpix, ®wcs->yrefpix, ®wcs->xinc, ®wcs->yinc,
		®wcs->rot, regwcs->type, status) ) {
      regwcs->exists = 0;
      *status = 0;
    }

    if ( regwcs->exists && wcs->exists ) {
      if ( fabs(regwcs->xrefval-wcs->xrefval) > 1.0e-6 ||
	   fabs(regwcs->yrefval-wcs->yrefval) > 1.0e-6 ||
	   fabs(regwcs->xrefpix-wcs->xrefpix) > 1.0e-6 ||
	   fabs(regwcs->yrefpix-wcs->yrefpix) > 1.0e-6 ||
	   fabs(regwcs->xinc-wcs->xinc) > 1.0e-6 ||
	   fabs(regwcs->yinc-wcs->yinc) > 1.0e-6 ||
	   fabs(regwcs->rot-wcs->rot) > 1.0e-6 ||
	   !strcmp(regwcs->type,wcs->type) ) dotransform = 1;
    }
  }

  /* get the sizes of the X, Y, R, and ROTANG vectors */

  for (i=0; i<6; i++) {
    if ( ffgtdm(fptr, icol[i], 1, &idum, &icsize[i], status) ) {
      ffpmsg("Could not find vector size of column.");
      goto error;
    }
  }

  cvalue = (char *) malloc ((FLEN_VALUE+1)*sizeof(char));

  /* loop over the shapes - note 1-based counting for rows in FITS files */

  for (i=1; i<=aRgn->nShapes; i++) {

    newShape = &aRgn->Shapes[i-1];
    for (j=0; j<8; j++) newShape->param.gen.p[j] = 0.0;
    newShape->param.gen.a = 0.0;
    newShape->param.gen.b = 0.0;
    newShape->param.gen.sinT = 0.0;
    newShape->param.gen.cosT = 0.0;

    /* get the shape */

    if ( ffgcvs(fptr, icol[2], i, 1, 1, " ", &cvalue, &anynul, status) ) {
      ffpmsg("Could not read shape.");
      goto error;
    }

    /* set include or exclude */

    newShape->sign = 1;
    cvalue2 = cvalue;
    if ( !strncmp(cvalue,"!",1) ) {
      newShape->sign = 0;
      cvalue2++;
    }

    /* set the shape type */

    for (j=0; j<17; j++) {
      if ( !strcmp(cvalue2, shapename[j]) ) newShape->shape = shapetype[j];
    }

    /* allocate memory for polygon case and set coords pointer */

    if ( newShape->shape == poly_rgn ) {
      newShape->param.poly.Pts = (double *) calloc (2*icsize[0], sizeof(double));
      if ( !newShape->param.poly.Pts ) {
	ffpmsg("Could not allocate memory to hold polygon parameters" );
	*status = MEMORY_ALLOCATION;
	goto error;
      }
      newShape->param.poly.nPts = 2*icsize[0];
      coords = newShape->param.poly.Pts;
    } else {
      coords = newShape->param.gen.p;
    }


  /* read X and Y. Polygon and Rectangle require special cases */

    npos = 1;
    if ( newShape->shape == poly_rgn ) npos = newShape->param.poly.nPts/2;
    if ( newShape->shape == rectangle_rgn ) npos = 2;

    for (j=0; jparam.poly.nPts = npos * 2;
	break;
      }
      coords++;
      
      if ( ffgcvd(fptr, icol[1], i, j+1, 1, DOUBLENULLVALUE, coords, &anynul, status) ) {
	ffpmsg("Failed to read Y column for polygon region");
	goto error;
      }
      if (*coords == DOUBLENULLVALUE) { /* check for null value end of array marker */
        npos = j;
	newShape->param.poly.nPts = npos * 2;
        coords--;
	break;
      }
      coords++;
 
      if (j == 0) {  /* save the first X and Y coordinate */
        Xsave = *(coords - 2);
	Ysave = *(coords - 1);
      } else if ((Xsave == *(coords - 2)) && (Ysave == *(coords - 1)) ) {
        /* if point has same coordinate as first point, this marks the end of the array */
        npos = j + 1;
	newShape->param.poly.nPts = npos * 2;
	break;
      }
    }

    /* transform positions if the region and input wcs differ */

    if ( dotransform ) {

      coords -= npos*2;
      Xsave = coords[0];
      Ysave = coords[1];
      for (j=0; jxrefval, regwcs->yrefval, regwcs->xrefpix,
	       regwcs->yrefpix, regwcs->xinc, regwcs->yinc, regwcs->rot,
	       regwcs->type, &Xpos, &Ypos, status);
	ffxypx(Xpos, Ypos, wcs->xrefval, wcs->yrefval, wcs->xrefpix,
	       wcs->yrefpix, wcs->xinc, wcs->yinc, wcs->rot,
	       wcs->type, &coords[2*j], &coords[2*j+1], status);
	if ( *status ) {
	  ffpmsg("Failed to transform coordinates");
	  goto error;
	}
      }
      coords += npos*2;
    }

  /* read R. Circle requires one number; Box, Diamond, Ellipse, Annulus, Sector 
     and Panda two; Boxannulus and Elliptannulus four; Point, Rectangle and 
     Polygon none. */

    npos = 0;
    switch ( newShape->shape ) {
    case circle_rgn: 
      npos = 1;
      break;
    case box_rgn:
    case diamond_rgn:
    case ellipse_rgn:
    case annulus_rgn:
    case sector_rgn:
      npos = 2;
      break;
    case boxannulus_rgn:
    case elliptannulus_rgn:
      npos = 4;
      break;
    default:
      break;
    }

    if ( npos > 0 ) {
      if ( ffgcvd(fptr, icol[3], i, 1, npos, 0.0, coords, &anynul, status) ) {
	ffpmsg("Failed to read R column for region");
	goto error;
      }

    /* transform lengths if the region and input wcs differ */

      if ( dotransform ) {
	for (j=0; jxrefval, regwcs->yrefval, regwcs->xrefpix,
		 regwcs->yrefpix, regwcs->xinc, regwcs->yinc, regwcs->rot,
		 regwcs->type, &Xpos, &Ypos, status);
	  ffxypx(Xpos, Ypos, wcs->xrefval, wcs->yrefval, wcs->xrefpix,
		 wcs->yrefpix, wcs->xinc, wcs->yinc, wcs->rot,
		 wcs->type, &X, &Y, status);
	  if ( *status ) {
	    ffpmsg("Failed to transform coordinates");
	    goto error;
	  }
	  *(coords++) = sqrt(pow(X-newShape->param.gen.p[0],2)+pow(Y-newShape->param.gen.p[1],2));
	}
      } else {
	coords += npos;
      }
    }

  /* read ROTANG. Requires two values for Boxannulus, Elliptannulus, Sector, 
     Panda; one for Box, Diamond, Ellipse; and none for Circle, Point, Annulus, 
     Rectangle, Polygon */

    npos = 0;
    switch ( newShape->shape ) {
    case box_rgn:
    case diamond_rgn:
    case ellipse_rgn:
      npos = 1;
      break;
    case boxannulus_rgn:
    case elliptannulus_rgn:
    case sector_rgn:
      npos = 2;
      break;
    default:
     break;
    }

    if ( npos > 0 ) {
      if ( ffgcvd(fptr, icol[4], i, 1, npos, 0.0, coords, &anynul, status) ) {
	ffpmsg("Failed to read ROTANG column for region");
	goto error;
      }

    /* transform angles if the region and input wcs differ */

      if ( dotransform ) {
	Theta = (wcs->rot) - (regwcs->rot);
	for (j=0; jcomp, &anynul, status) ) {
        ffpmsg("Failed to read COMPONENT column for region");
        goto error;
      }
    } else {
      newShape->comp = 1;
    }


    /* do some precalculations to speed up tests */

    fits_setup_shape(newShape);

    /* end loop over shapes */

  }

error:

   if( *status )
      fits_free_region( aRgn );
   else
      *Rgn = aRgn;

   ffclos(fptr, status);

   return( *status );
}

cfitsio/region.h0000644000225700000360000000415513246025103013441 0ustar  cagordonlhea/***************************************************************/
/*                   REGION STUFF                              */
/***************************************************************/

#include "fitsio.h"
#define myPI  3.1415926535897932385
#define RadToDeg 180.0/myPI

typedef struct {
   int    exists;
   double xrefval, yrefval;
   double xrefpix, yrefpix;
   double xinc,    yinc;
   double rot;
   char   type[6];
} WCSdata;

typedef enum {
   point_rgn,
   line_rgn,
   circle_rgn,
   annulus_rgn,
   ellipse_rgn,
   elliptannulus_rgn,
   box_rgn,
   boxannulus_rgn,
   rectangle_rgn,
   diamond_rgn,
   sector_rgn,
   poly_rgn,
   panda_rgn,
   epanda_rgn,
   bpanda_rgn
} shapeType;

typedef enum { pixel_fmt, degree_fmt, hhmmss_fmt } coordFmt;
   
typedef struct {
   char      sign;        /*  Include or exclude?        */
   shapeType shape;       /*  Shape of this region       */
   int       comp;        /*  Component number for this region */

   double xmin,xmax;       /*  bounding box    */
   double ymin,ymax;

   union {                /*  Parameters - In pixels     */

      /****   Generic Shape Data   ****/

      struct {
	 double p[11];       /*  Region parameters       */
	 double sinT, cosT;  /*  For rotated shapes      */
	 double a, b;        /*  Extra scratch area      */
      } gen;

      /****      Polygon Data      ****/

      struct {
         int    nPts;        /*  Number of Polygon pts   */
         double *Pts;        /*  Polygon points          */
      } poly;

   } param;

} RgnShape;

typedef struct {
   int       nShapes;
   RgnShape  *Shapes;
   WCSdata   wcs;
} SAORegion;

/*  SAO region file routines */
int  fits_read_rgnfile( const char *filename, WCSdata *wcs, SAORegion **Rgn, int *status );
int  fits_in_region( double X, double Y, SAORegion *Rgn );
void fits_free_region( SAORegion *Rgn );
void fits_set_region_components ( SAORegion *Rgn );
void fits_setup_shape ( RgnShape *shape);
int fits_read_fits_region ( fitsfile *fptr, WCSdata * wcs, SAORegion **Rgn, int *status);
int fits_read_ascii_region ( const char *filename, WCSdata * wcs, SAORegion **Rgn, int *status);


cfitsio/ricecomp.c0000644000225700000360000010462213246025103013752 0ustar  cagordonlhea/*
  The following code was written by Richard White at STScI and made
  available for use in CFITSIO in July 1999.  These routines were
  originally contained in 2 source files: rcomp.c and rdecomp.c,
  and the 'include' file now called ricecomp.h was originally called buffer.h.
*/

/*----------------------------------------------------------*/
/*                                                          */
/*    START OF SOURCE FILE ORIGINALLY CALLED rcomp.c        */
/*                                                          */
/*----------------------------------------------------------*/
/* @(#) rcomp.c 1.5 99/03/01 12:40:27 */
/* rcomp.c	Compress image line using
 *		(1) Difference of adjacent pixels
 *		(2) Rice algorithm coding
 *
 * Returns number of bytes written to code buffer or
 * -1 on failure
 */

#include 
#include 
#include 

/*
 * nonzero_count is lookup table giving number of bits in 8-bit values not including
 * leading zeros used in fits_rdecomp, fits_rdecomp_short and fits_rdecomp_byte
 */
static const int nonzero_count[256] = {
0, 
1, 
2, 2, 
3, 3, 3, 3, 
4, 4, 4, 4, 4, 4, 4, 4, 
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8};

typedef unsigned char Buffer_t;

typedef struct {
	int bitbuffer;		/* bit buffer			*/
	int bits_to_go;		/* bits to go in buffer		*/
	Buffer_t *start;	/* start of buffer		*/
	Buffer_t *current;	/* current position in buffer	*/
	Buffer_t *end;		/* end of buffer		*/
} Buffer;

#define putcbuf(c,mf) 	((*(mf->current)++ = c), 0)

#include "fitsio2.h"

static void start_outputing_bits(Buffer *buffer);
static int done_outputing_bits(Buffer *buffer);
static int output_nbits(Buffer *buffer, int bits, int n);

/*  only used for diagnoistics
static int case1, case2, case3;
int fits_get_case(int *c1, int*c2, int*c3) {

  *c1 = case1;
  *c2 = case2;
  *c3 = case3;
  return(0);
}
*/

/* this routine used to be called 'rcomp'  (WDP)  */
/*---------------------------------------------------------------------------*/

int fits_rcomp(int a[],		/* input array			*/
	  int nx,		/* number of input pixels	*/
	  unsigned char *c,	/* output buffer		*/
	  int clen,		/* max length of output		*/
	  int nblock)		/* coding block size		*/
{
Buffer bufmem, *buffer = &bufmem;
/* int bsize;  */
int i, j, thisblock;
int lastpix, nextpix, pdiff;
int v, fs, fsmask, top, fsmax, fsbits, bbits;
int lbitbuffer, lbits_to_go;
unsigned int psum;
double pixelsum, dpsum;
unsigned int *diff;

    /*
     * Original size of each pixel (bsize, bytes) and coding block
     * size (nblock, pixels)
     * Could make bsize a parameter to allow more efficient
     * compression of short & byte images.
     */
/*    bsize = 4;   */

/*    nblock = 32; now an input parameter*/
    /*
     * From bsize derive:
     * FSBITS = # bits required to store FS
     * FSMAX = maximum value for FS
     * BBITS = bits/pixel for direct coding
     */

/*
    switch (bsize) {
    case 1:
	fsbits = 3;
	fsmax = 6;
	break;
    case 2:
	fsbits = 4;
	fsmax = 14;
	break;
    case 4:
	fsbits = 5;
	fsmax = 25;
	break;
    default:
        ffpmsg("rdecomp: bsize must be 1, 2, or 4 bytes");
	return(-1);
    }
*/

    /* move out of switch block, to tweak performance */
    fsbits = 5;
    fsmax = 25;

    bbits = 1<start = c;
    buffer->current = c;
    buffer->end = c+clen;
    buffer->bits_to_go = 8;
    /*
     * array for differences mapped to non-negative values
     */
    diff = (unsigned int *) malloc(nblock*sizeof(unsigned int));
    if (diff == (unsigned int *) NULL) {
        ffpmsg("fits_rcomp: insufficient memory");
	return(-1);
    }
    /*
     * Code in blocks of nblock pixels
     */
    start_outputing_bits(buffer);

    /* write out first int value to the first 4 bytes of the buffer */
    if (output_nbits(buffer, a[0], 32) == EOF) {
        ffpmsg("rice_encode: end of buffer");
        free(diff);
        return(-1);
    }

    lastpix = a[0];  /* the first difference will always be zero */

    thisblock = nblock;
    for (i=0; i> 1;
	for (fs = 0; psum>0; fs++) psum >>= 1;

	/*
	 * write the codes
	 * fsbits ID bits used to indicate split level
	 */
	if (fs >= fsmax) {
	    /* Special high entropy case when FS >= fsmax
	     * Just write pixel difference values directly, no Rice coding at all.
	     */
	    if (output_nbits(buffer, fsmax+1, fsbits) == EOF) {
                ffpmsg("rice_encode: end of buffer");
                free(diff);
		return(-1);
	    }
	    for (j=0; jbitbuffer;
	    lbits_to_go = buffer->bits_to_go;
	    for (j=0; j> fs;
		/*
		 * top is coded by top zeros + 1
		 */
		if (lbits_to_go >= top+1) {
		    lbitbuffer <<= top+1;
		    lbitbuffer |= 1;
		    lbits_to_go -= top+1;
		} else {
		    lbitbuffer <<= lbits_to_go;
		    putcbuf(lbitbuffer & 0xff,buffer);

		    for (top -= lbits_to_go; top>=8; top -= 8) {
			putcbuf(0, buffer);
		    }
		    lbitbuffer = 1;
		    lbits_to_go = 7-top;
		}
		/*
		 * bottom FS bits are written without coding
		 * code is output_nbits, moved into this routine to reduce overheads
		 * This code potentially breaks if FS>24, so I am limiting
		 * FS to 24 by choice of FSMAX above.
		 */
		if (fs > 0) {
		    lbitbuffer <<= fs;
		    lbitbuffer |= v & fsmask;
		    lbits_to_go -= fs;
		    while (lbits_to_go <= 0) {
			putcbuf((lbitbuffer>>(-lbits_to_go)) & 0xff,buffer);
			lbits_to_go += 8;
		    }
		}
	    }

	    /* check if overflowed output buffer */
	    if (buffer->current > buffer->end) {
                 ffpmsg("rice_encode: end of buffer");
                 free(diff);
		 return(-1);
	    }
	    buffer->bitbuffer = lbitbuffer;
	    buffer->bits_to_go = lbits_to_go;
	}
    }
    done_outputing_bits(buffer);
    free(diff);
    /*
     * return number of bytes used
     */
    return(buffer->current - buffer->start);
}
/*---------------------------------------------------------------------------*/

int fits_rcomp_short(
	  short a[],		/* input array			*/
	  int nx,		/* number of input pixels	*/
	  unsigned char *c,	/* output buffer		*/
	  int clen,		/* max length of output		*/
	  int nblock)		/* coding block size		*/
{
Buffer bufmem, *buffer = &bufmem;
/* int bsize;  */
int i, j, thisblock;

/* 
NOTE: in principle, the following 2 variable could be declared as 'short'
but in fact the code runs faster (on 32-bit Linux at least) as 'int'
*/
int lastpix, nextpix;
/* int pdiff; */
short pdiff; 
int v, fs, fsmask, top, fsmax, fsbits, bbits;
int lbitbuffer, lbits_to_go;
/* unsigned int psum; */
unsigned short psum;
double pixelsum, dpsum;
unsigned int *diff;

    /*
     * Original size of each pixel (bsize, bytes) and coding block
     * size (nblock, pixels)
     * Could make bsize a parameter to allow more efficient
     * compression of short & byte images.
     */
/*    bsize = 2; */

/*    nblock = 32; now an input parameter */
    /*
     * From bsize derive:
     * FSBITS = # bits required to store FS
     * FSMAX = maximum value for FS
     * BBITS = bits/pixel for direct coding
     */

/*
    switch (bsize) {
    case 1:
	fsbits = 3;
	fsmax = 6;
	break;
    case 2:
	fsbits = 4;
	fsmax = 14;
	break;
    case 4:
	fsbits = 5;
	fsmax = 25;
	break;
    default:
        ffpmsg("rdecomp: bsize must be 1, 2, or 4 bytes");
	return(-1);
    }
*/

    /* move these out of switch block to further tweak performance */
    fsbits = 4;
    fsmax = 14;
    
    bbits = 1<start = c;
    buffer->current = c;
    buffer->end = c+clen;
    buffer->bits_to_go = 8;
    /*
     * array for differences mapped to non-negative values
     */
    diff = (unsigned int *) malloc(nblock*sizeof(unsigned int));
    if (diff == (unsigned int *) NULL) {
        ffpmsg("fits_rcomp: insufficient memory");
	return(-1);
    }
    /*
     * Code in blocks of nblock pixels
     */
    start_outputing_bits(buffer);

    /* write out first short value to the first 2 bytes of the buffer */
    if (output_nbits(buffer, a[0], 16) == EOF) {
        ffpmsg("rice_encode: end of buffer");
        free(diff);
        return(-1);
    }

    lastpix = a[0];  /* the first difference will always be zero */

    thisblock = nblock;
    for (i=0; i> 1; */
	psum = ((unsigned short) dpsum ) >> 1;
	for (fs = 0; psum>0; fs++) psum >>= 1;

	/*
	 * write the codes
	 * fsbits ID bits used to indicate split level
	 */
	if (fs >= fsmax) {
/* case3++; */
	    /* Special high entropy case when FS >= fsmax
	     * Just write pixel difference values directly, no Rice coding at all.
	     */
	    if (output_nbits(buffer, fsmax+1, fsbits) == EOF) {
                ffpmsg("rice_encode: end of buffer");
                free(diff);
		return(-1);
	    }
	    for (j=0; jbitbuffer;
	    lbits_to_go = buffer->bits_to_go;
	    for (j=0; j> fs;
		/*
		 * top is coded by top zeros + 1
		 */
		if (lbits_to_go >= top+1) {
		    lbitbuffer <<= top+1;
		    lbitbuffer |= 1;
		    lbits_to_go -= top+1;
		} else {
		    lbitbuffer <<= lbits_to_go;
		    putcbuf(lbitbuffer & 0xff,buffer);
		    for (top -= lbits_to_go; top>=8; top -= 8) {
			putcbuf(0, buffer);
		    }
		    lbitbuffer = 1;
		    lbits_to_go = 7-top;
		}
		/*
		 * bottom FS bits are written without coding
		 * code is output_nbits, moved into this routine to reduce overheads
		 * This code potentially breaks if FS>24, so I am limiting
		 * FS to 24 by choice of FSMAX above.
		 */
		if (fs > 0) {
		    lbitbuffer <<= fs;
		    lbitbuffer |= v & fsmask;
		    lbits_to_go -= fs;
		    while (lbits_to_go <= 0) {
			putcbuf((lbitbuffer>>(-lbits_to_go)) & 0xff,buffer);
			lbits_to_go += 8;
		    }
		}
	    }
	    /* check if overflowed output buffer */
	    if (buffer->current > buffer->end) {
                 ffpmsg("rice_encode: end of buffer");
                 free(diff);
		 return(-1);
	    }
	    buffer->bitbuffer = lbitbuffer;
	    buffer->bits_to_go = lbits_to_go;
	}
    }
    done_outputing_bits(buffer);
    free(diff);
    /*
     * return number of bytes used
     */
    return(buffer->current - buffer->start);
}
/*---------------------------------------------------------------------------*/

int fits_rcomp_byte(
	  signed char a[],		/* input array			*/
	  int nx,		/* number of input pixels	*/
	  unsigned char *c,	/* output buffer		*/
	  int clen,		/* max length of output		*/
	  int nblock)		/* coding block size		*/
{
Buffer bufmem, *buffer = &bufmem;
/* int bsize; */
int i, j, thisblock;

/* 
NOTE: in principle, the following 2 variable could be declared as 'short'
but in fact the code runs faster (on 32-bit Linux at least) as 'int'
*/
int lastpix, nextpix;
/* int pdiff; */
signed char pdiff; 
int v, fs, fsmask, top, fsmax, fsbits, bbits;
int lbitbuffer, lbits_to_go;
/* unsigned int psum; */
unsigned char psum;
double pixelsum, dpsum;
unsigned int *diff;

    /*
     * Original size of each pixel (bsize, bytes) and coding block
     * size (nblock, pixels)
     * Could make bsize a parameter to allow more efficient
     * compression of short & byte images.
     */
/*    bsize = 1;  */

/*    nblock = 32; now an input parameter */
    /*
     * From bsize derive:
     * FSBITS = # bits required to store FS
     * FSMAX = maximum value for FS
     * BBITS = bits/pixel for direct coding
     */

/*
    switch (bsize) {
    case 1:
	fsbits = 3;
	fsmax = 6;
	break;
    case 2:
	fsbits = 4;
	fsmax = 14;
	break;
    case 4:
	fsbits = 5;
	fsmax = 25;
	break;
    default:
        ffpmsg("rdecomp: bsize must be 1, 2, or 4 bytes");
	return(-1);
    }
*/

    /* move these out of switch block to further tweak performance */
    fsbits = 3;
    fsmax = 6;
    bbits = 1<start = c;
    buffer->current = c;
    buffer->end = c+clen;
    buffer->bits_to_go = 8;
    /*
     * array for differences mapped to non-negative values
     */
    diff = (unsigned int *) malloc(nblock*sizeof(unsigned int));
    if (diff == (unsigned int *) NULL) {
        ffpmsg("fits_rcomp: insufficient memory");
	return(-1);
    }
    /*
     * Code in blocks of nblock pixels
     */
    start_outputing_bits(buffer);

    /* write out first byte value to the first  byte of the buffer */
    if (output_nbits(buffer, a[0], 8) == EOF) {
        ffpmsg("rice_encode: end of buffer");
        free(diff);
        return(-1);
    }

    lastpix = a[0];  /* the first difference will always be zero */

    thisblock = nblock;
    for (i=0; i> 1; */
	psum = ((unsigned char) dpsum ) >> 1;
	for (fs = 0; psum>0; fs++) psum >>= 1;

	/*
	 * write the codes
	 * fsbits ID bits used to indicate split level
	 */
	if (fs >= fsmax) {
	    /* Special high entropy case when FS >= fsmax
	     * Just write pixel difference values directly, no Rice coding at all.
	     */
	    if (output_nbits(buffer, fsmax+1, fsbits) == EOF) {
                ffpmsg("rice_encode: end of buffer");
                free(diff);
		return(-1);
	    }
	    for (j=0; jbitbuffer;
	    lbits_to_go = buffer->bits_to_go;
	    for (j=0; j> fs;
		/*
		 * top is coded by top zeros + 1
		 */
		if (lbits_to_go >= top+1) {
		    lbitbuffer <<= top+1;
		    lbitbuffer |= 1;
		    lbits_to_go -= top+1;
		} else {
		    lbitbuffer <<= lbits_to_go;
		    putcbuf(lbitbuffer & 0xff,buffer);
		    for (top -= lbits_to_go; top>=8; top -= 8) {
			putcbuf(0, buffer);
		    }
		    lbitbuffer = 1;
		    lbits_to_go = 7-top;
		}
		/*
		 * bottom FS bits are written without coding
		 * code is output_nbits, moved into this routine to reduce overheads
		 * This code potentially breaks if FS>24, so I am limiting
		 * FS to 24 by choice of FSMAX above.
		 */
		if (fs > 0) {
		    lbitbuffer <<= fs;
		    lbitbuffer |= v & fsmask;
		    lbits_to_go -= fs;
		    while (lbits_to_go <= 0) {
			putcbuf((lbitbuffer>>(-lbits_to_go)) & 0xff,buffer);
			lbits_to_go += 8;
		    }
		}
	    }
	    /* check if overflowed output buffer */
	    if (buffer->current > buffer->end) {
                 ffpmsg("rice_encode: end of buffer");
                 free(diff);
		 return(-1);
	    }
	    buffer->bitbuffer = lbitbuffer;
	    buffer->bits_to_go = lbits_to_go;
	}
    }
    done_outputing_bits(buffer);
    free(diff);
    /*
     * return number of bytes used
     */
    return(buffer->current - buffer->start);
}
/*---------------------------------------------------------------------------*/
/* bit_output.c
 *
 * Bit output routines
 * Procedures return zero on success, EOF on end-of-buffer
 *
 * Programmer: R. White     Date: 20 July 1998
 */

/* Initialize for bit output */

static void start_outputing_bits(Buffer *buffer)
{
    /*
     * Buffer is empty to start with
     */
    buffer->bitbuffer = 0;
    buffer->bits_to_go = 8;
}

/*---------------------------------------------------------------------------*/
/* Output N bits (N must be <= 32) */

static int output_nbits(Buffer *buffer, int bits, int n)
{
/* local copies */
int lbitbuffer;
int lbits_to_go;
    /* AND mask for the right-most n bits */
    static unsigned int mask[33] = 
         {0,
	  0x1,       0x3,       0x7,       0xf,       0x1f,       0x3f,       0x7f,       0xff,
	  0x1ff,     0x3ff,     0x7ff,     0xfff,     0x1fff,     0x3fff,     0x7fff,     0xffff,
	  0x1ffff,   0x3ffff,   0x7ffff,   0xfffff,   0x1fffff,   0x3fffff,   0x7fffff,   0xffffff,
	  0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff};

    /*
     * insert bits at end of bitbuffer
     */
    lbitbuffer = buffer->bitbuffer;
    lbits_to_go = buffer->bits_to_go;
    if (lbits_to_go+n > 32) {
	/*
	 * special case for large n: put out the top lbits_to_go bits first
	 * note that 0 < lbits_to_go <= 8
	 */
	lbitbuffer <<= lbits_to_go;
/*	lbitbuffer |= (bits>>(n-lbits_to_go)) & ((1<>(n-lbits_to_go)) & *(mask+lbits_to_go);
	putcbuf(lbitbuffer & 0xff,buffer);
	n -= lbits_to_go;
	lbits_to_go = 8;
    }
    lbitbuffer <<= n;
/*    lbitbuffer |= ( bits & ((1<>(-lbits_to_go)) & 0xff,buffer);
	lbits_to_go += 8;
    }
    buffer->bitbuffer = lbitbuffer;
    buffer->bits_to_go = lbits_to_go;
    return(0);
}
/*---------------------------------------------------------------------------*/
/* Flush out the last bits */

static int done_outputing_bits(Buffer *buffer)
{
    if(buffer->bits_to_go < 8) {
	putcbuf(buffer->bitbuffer<bits_to_go,buffer);
	
/*	if (putcbuf(buffer->bitbuffer<bits_to_go,buffer) == EOF)
	    return(EOF);
*/
    }
    return(0);
}
/*---------------------------------------------------------------------------*/
/*----------------------------------------------------------*/
/*                                                          */
/*    START OF SOURCE FILE ORIGINALLY CALLED rdecomp.c      */
/*                                                          */
/*----------------------------------------------------------*/

/* @(#) rdecomp.c 1.4 99/03/01 12:38:41 */
/* rdecomp.c	Decompress image line using
 *		(1) Difference of adjacent pixels
 *		(2) Rice algorithm coding
 *
 * Returns 0 on success or 1 on failure
 */

/*    moved these 'includes' to the beginning of the file (WDP)
#include 
#include 
*/

/*---------------------------------------------------------------------------*/
/* this routine used to be called 'rdecomp'  (WDP)  */

int fits_rdecomp (unsigned char *c,		/* input buffer			*/
	     int clen,			/* length of input		*/
	     unsigned int array[],	/* output array			*/
	     int nx,			/* number of output pixels	*/
	     int nblock)		/* coding block size		*/
{
/* int bsize;  */
int i, k, imax;
int nbits, nzero, fs;
unsigned char *cend, bytevalue;
unsigned int b, diff, lastpix;
int fsmax, fsbits, bbits;
extern const int nonzero_count[];

   /*
     * Original size of each pixel (bsize, bytes) and coding block
     * size (nblock, pixels)
     * Could make bsize a parameter to allow more efficient
     * compression of short & byte images.
     */
/*    bsize = 4; */

/*    nblock = 32; now an input parameter */
    /*
     * From bsize derive:
     * FSBITS = # bits required to store FS
     * FSMAX = maximum value for FS
     * BBITS = bits/pixel for direct coding
     */

/*
    switch (bsize) {
    case 1:
	fsbits = 3;
	fsmax = 6;
	break;
    case 2:
	fsbits = 4;
	fsmax = 14;
	break;
    case 4:
	fsbits = 5;
	fsmax = 25;
	break;
    default:
        ffpmsg("rdecomp: bsize must be 1, 2, or 4 bytes");
	return 1;
    }
*/

    /* move out of switch block, to tweak performance */
    fsbits = 5;
    fsmax = 25;

    bbits = 1<> nbits) - 1;

	b &= (1< nx) imax = nx;
	if (fs<0) {
	    /* low-entropy case, all zero differences */
	    for ( ; i= 0; k -= 8) {
		    b = *c++;
		    diff |= b<0) {
		    b = *c++;
		    diff |= b>>(-k);
		    b &= (1<>1;
		} else {
		    diff = ~(diff>>1);
		}
		array[i] = diff+lastpix;
		lastpix = array[i];
	    }
	} else {
	    /* normal case, Rice coding */
	    for ( ; i>nbits);
		b &= (1<>1;
		} else {
		    diff = ~(diff>>1);
		}
		array[i] = diff+lastpix;
		lastpix = array[i];
	    }
	}
	if (c > cend) {
            ffpmsg("decompression error: hit end of compressed byte stream");
	    return 1;
	}
    }
    if (c < cend) {
        ffpmsg("decompression warning: unused bytes at end of compressed buffer");
    }
    return 0;
}
/*---------------------------------------------------------------------------*/
/* this routine used to be called 'rdecomp'  (WDP)  */

int fits_rdecomp_short (unsigned char *c,		/* input buffer			*/
	     int clen,			/* length of input		*/
	     unsigned short array[],  	/* output array			*/
	     int nx,			/* number of output pixels	*/
	     int nblock)		/* coding block size		*/
{
int i, imax;
/* int bsize; */
int k;
int nbits, nzero, fs;
unsigned char *cend, bytevalue;
unsigned int b, diff, lastpix;
int fsmax, fsbits, bbits;
extern const int nonzero_count[];

   /*
     * Original size of each pixel (bsize, bytes) and coding block
     * size (nblock, pixels)
     * Could make bsize a parameter to allow more efficient
     * compression of short & byte images.
     */

/*    bsize = 2; */
    
/*    nblock = 32; now an input parameter */
    /*
     * From bsize derive:
     * FSBITS = # bits required to store FS
     * FSMAX = maximum value for FS
     * BBITS = bits/pixel for direct coding
     */

/*
    switch (bsize) {
    case 1:
	fsbits = 3;
	fsmax = 6;
	break;
    case 2:
	fsbits = 4;
	fsmax = 14;
	break;
    case 4:
	fsbits = 5;
	fsmax = 25;
	break;
    default:
        ffpmsg("rdecomp: bsize must be 1, 2, or 4 bytes");
	return 1;
    }
*/

    /* move out of switch block, to tweak performance */
    fsbits = 4;
    fsmax = 14;

    bbits = 1<> nbits) - 1;

	b &= (1< nx) imax = nx;
	if (fs<0) {
	    /* low-entropy case, all zero differences */
	    for ( ; i= 0; k -= 8) {
		    b = *c++;
		    diff |= b<0) {
		    b = *c++;
		    diff |= b>>(-k);
		    b &= (1<>1;
		} else {
		    diff = ~(diff>>1);
		}
		array[i] = diff+lastpix;
		lastpix = array[i];
	    }
	} else {
	    /* normal case, Rice coding */
	    for ( ; i>nbits);
		b &= (1<>1;
		} else {
		    diff = ~(diff>>1);
		}
		array[i] = diff+lastpix;
		lastpix = array[i];
	    }
	}
	if (c > cend) {
            ffpmsg("decompression error: hit end of compressed byte stream");
	    return 1;
	}
    }
    if (c < cend) {
        ffpmsg("decompression warning: unused bytes at end of compressed buffer");
    }
    return 0;
}
/*---------------------------------------------------------------------------*/
/* this routine used to be called 'rdecomp'  (WDP)  */

int fits_rdecomp_byte (unsigned char *c,		/* input buffer			*/
	     int clen,			/* length of input		*/
	     unsigned char array[],  	/* output array			*/
	     int nx,			/* number of output pixels	*/
	     int nblock)		/* coding block size		*/
{
int i, imax;
/* int bsize; */
int k;
int nbits, nzero, fs;
unsigned char *cend;
unsigned int b, diff, lastpix;
int fsmax, fsbits, bbits;
extern const int nonzero_count[];

   /*
     * Original size of each pixel (bsize, bytes) and coding block
     * size (nblock, pixels)
     * Could make bsize a parameter to allow more efficient
     * compression of short & byte images.
     */

/*    bsize = 1; */
    
/*    nblock = 32; now an input parameter */
    /*
     * From bsize derive:
     * FSBITS = # bits required to store FS
     * FSMAX = maximum value for FS
     * BBITS = bits/pixel for direct coding
     */

/*
    switch (bsize) {
    case 1:
	fsbits = 3;
	fsmax = 6;
	break;
    case 2:
	fsbits = 4;
	fsmax = 14;
	break;
    case 4:
	fsbits = 5;
	fsmax = 25;
	break;
    default:
        ffpmsg("rdecomp: bsize must be 1, 2, or 4 bytes");
	return 1;
    }
*/

    /* move out of switch block, to tweak performance */
    fsbits = 3;
    fsmax = 6;

    bbits = 1<> nbits) - 1;

	b &= (1< nx) imax = nx;
	if (fs<0) {
	    /* low-entropy case, all zero differences */
	    for ( ; i= 0; k -= 8) {
		    b = *c++;
		    diff |= b<0) {
		    b = *c++;
		    diff |= b>>(-k);
		    b &= (1<>1;
		} else {
		    diff = ~(diff>>1);
		}
		array[i] = diff+lastpix;
		lastpix = array[i];
	    }
	} else {
	    /* normal case, Rice coding */
	    for ( ; i>nbits);
		b &= (1<>1;
		} else {
		    diff = ~(diff>>1);
		}
		array[i] = diff+lastpix;
		lastpix = array[i];
	    }
	}
	if (c > cend) {
            ffpmsg("decompression error: hit end of compressed byte stream");
	    return 1;
	}
    }
    if (c < cend) {
        ffpmsg("decompression warning: unused bytes at end of compressed buffer");
    }
    return 0;
}
cfitsio/sample.tpl0000644000225700000360000000677513246025103014021 0ustar  cagordonlhea# sample template - create 9 HDUs in one FITS file

# syntax :

# everything which starts with a hashmark is ignored
# the same for empty lines

# one can use \include filename to include other files
# equal sign after keyword name is optional
# \group must be terminated by \end
# xtension is terminated by \group, xtension or EOF
# First HDU of type image may be defined using "SIMPLE T"
# group may contain other groups and xtensions
# keywords may be indented, but indentation is limited to max 7chars.

# template parser processes all keywords, makes substitutions
# when necessary (hashmarks -> index), converts keyword names
# to uppercase and writes keywords to file.
# For string keywords, parser uses CFITSIO long string routines
# to store string values longer than 72 characters. Parser can
# read/process lines of any length, as long as there is enough memory.
# For a very limited set of keywords (like NAXIS1 for binary tables)
# template parser ignores values specified in template file
# (one should not specify NAXIS1 for binary tables) and computes and
# writes values respective to table structure.
# number of rows in binary/ascii tables can be specified with NAXIS2

# if the 1st HDU is not defined with "SIMPLE T" and is defined with
# xtension image/asciitable/bintable then dummy primary HDU is
# created by parser.

simple	t
 bitpix		16
 naxis		1
 naxis1		10
COMMENT
 comment  
 sdsdf / keyword without value (null type)
        if line begins with 8+ spaces everything is a comment

xtension image
 bitpix		16
 naxis		1
 naxis1		10
 QWERW		F / dfg dfgsd fg - boolean keyword
 FFFSDS45	3454345 /integer_or_real keyword
 SSSDFS34	32345.453   / real keyword
 adsfd34	(234234.34,2342342.3) / complex keyword - no space between ()
 SDFDF#		adfasdfasdfdfcvxccvzxcvcvcxv / autoindexed keyword, here idx=1
 SDFD#		'asf dfa dfad df dfad f ad fadfdaf dfdfa df loooooong keyyywoooord - reaaalllly verrrrrrrrrryy loooooooooong' / comment is max 80 chars
 history        history record, spaces (all but 1st) after keyname are copied
 SDFDF#		strg_value_without_spaces / autoindexed keyword, here idx=2
 comment        comment record, spaces (all but 1st) after keyname are copied
 strg45		'sdfasdfadfffdfasdfasdfasdf &'
 continue   'sdfsdfsdfsd fsdf' / 3 spaces must follow CONTINUE keyword


xtension image
 bitpix		16
 naxis		1
 naxis1		10

\group
 
 xtension image
  bitpix	16
  naxis		1
  naxis1	10

# create group inside group

 \group

# one can specify additional columns in group HDU. The first column
# specified will have index 7 however, since the first 6 columns are occupied
# by grouping table itself.
# Please note, that it is not allowed to specify EXTNAME keyword as an
# additional keyword for group HDU, since parser automatically writes
# EXTNAME = GROUPING keyword.

  TFORM#	13A
  TTYPE#	ADDIT_COL_IN_GRP_HDU
  TFORM#	1E
  TTYPE#	REAL_COLUMN
  COMMENT sure, there is always place for comments

# the following specifies empty ascii table (0 cols / 0 rows)

  xtension asciitable

 \end
 
\end

# one do not have to specify all NAXISn keywords. If not specified
# NAXISn equals zero.

xtension image
 bitpix	16
 naxis	1
# naxis1	10

# the following tells how to set number of rows in binary table
# note also that the last line in template file does not have to
# have LineFeed character as the last one.

xtension bintable
naxis2	 10
EXTNAME	asdjfhsdkf
TTYPE#   MEMBER_XTENSION
TFORM#   8A
TTYPE#   MEMBER_2
TFORM#   8U
TTYPE#   MEMBER_3
TFORM#   8V
TTYPE#   MEMBER_NAME
TFORM#   32A
TDIM#	 '(8,4)'
TTYPE#   MEMBER_VERSION
TFORM#   1J
TNULL#   0cfitsio/scalnull.c0000644000225700000360000002141513246025103013764 0ustar  cagordonlhea/*  This file, scalnull.c, contains the FITSIO routines used to define     */
/*  the starting heap address, the value scaling and the null values.      */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include "fitsio2.h"
/*--------------------------------------------------------------------------*/
int ffpthp(fitsfile *fptr,      /* I - FITS file pointer */
           long theap,          /* I - starting addrss for the heap */
           int *status)         /* IO - error status     */
/*
  Define the starting address for the heap for a binary table.
  The default address is NAXIS1 * NAXIS2.  It is in units of
  bytes relative to the beginning of the regular binary table data.
  This routine also writes the appropriate THEAP keyword to the
  FITS header.
*/
{
    if (*status > 0 || theap < 1)
        return(*status);

    /* reset position to the correct HDU if necessary */
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    (fptr->Fptr)->heapstart = theap;

    ffukyj(fptr, "THEAP", theap, "byte offset to heap area", status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpscl(fitsfile *fptr,      /* I - FITS file pointer               */
           double scale,        /* I - scaling factor: value of BSCALE */
           double zero,         /* I - zero point: value of BZERO      */
           int *status)         /* IO - error status                   */
/*
  Define the linear scaling factor for the primary array or image extension
  pixel values. This routine overrides the scaling values given by the
  BSCALE and BZERO keywords if present.  Note that this routine does not
  write or modify the BSCALE and BZERO keywords, but instead only modifies
  the values temporarily in the internal buffer.  Thus, a subsequent call to
  the ffrdef routine will reset the scaling back to the BSCALE and BZERO
  keyword values (or 1. and 0. respectively if the keywords are not present).
*/
{
    tcolumn *colptr;
    int hdutype;

    if (*status > 0)
        return(*status);

    if (scale == 0)
        return(*status = ZERO_SCALE);  /* zero scale value is illegal */

    if (ffghdt(fptr, &hdutype, status) > 0)  /* get HDU type */
        return(*status);

    if (hdutype != IMAGE_HDU)
        return(*status = NOT_IMAGE);         /* not proper HDU type */

    if (fits_is_compressed_image(fptr, status)) /* compressed images */
    {
        (fptr->Fptr)->cn_bscale = scale;
        (fptr->Fptr)->cn_bzero  = zero;
        return(*status);
    }

    /* set pointer to the first 'column' (contains group parameters if any) */
    colptr = (fptr->Fptr)->tableptr; 

    colptr++;   /* increment to the 2nd 'column' pointer  (the image itself) */

    colptr->tscale = scale;
    colptr->tzero = zero;

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffpnul(fitsfile *fptr,      /* I - FITS file pointer                */
           LONGLONG nulvalue,   /* I - null pixel value: value of BLANK */
           int *status)         /* IO - error status                    */
/*
  Define the value used to represent undefined pixels in the primary array or
  image extension. This only applies to integer image pixel (i.e. BITPIX > 0).
  This routine overrides the null pixel value given by the BLANK keyword
  if present.  Note that this routine does not write or modify the BLANK
  keyword, but instead only modifies the value temporarily in the internal
  buffer. Thus, a subsequent call to the ffrdef routine will reset the null
  value back to the BLANK  keyword value (or not defined if the keyword is not
  present).
*/
{
    tcolumn *colptr;
    int hdutype;

    if (*status > 0)
        return(*status);

    if (ffghdt(fptr, &hdutype, status) > 0)  /* get HDU type */
        return(*status);

    if (hdutype != IMAGE_HDU)
        return(*status = NOT_IMAGE);         /* not proper HDU type */

    if (fits_is_compressed_image(fptr, status)) /* ignore compressed images */
        return(*status);

    /* set pointer to the first 'column' (contains group parameters if any) */
    colptr = (fptr->Fptr)->tableptr; 

    colptr++;   /* increment to the 2nd 'column' pointer  (the image itself) */

    colptr->tnull = nulvalue;

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fftscl(fitsfile *fptr,      /* I - FITS file pointer */
           int colnum,          /* I - column number to apply scaling to */
           double scale,        /* I - scaling factor: value of TSCALn   */
           double zero,         /* I - zero point: value of TZEROn       */
           int *status)         /* IO - error status     */
/*
  Define the linear scaling factor for the TABLE or BINTABLE extension
  column values. This routine overrides the scaling values given by the
  TSCALn and TZEROn keywords if present.  Note that this routine does not
  write or modify the TSCALn and TZEROn keywords, but instead only modifies
  the values temporarily in the internal buffer.  Thus, a subsequent call to
  the ffrdef routine will reset the scaling back to the TSCALn and TZEROn
  keyword values (or 1. and 0. respectively if the keywords are not present).
*/
{
    tcolumn *colptr;
    int hdutype;

    if (*status > 0)
        return(*status);

    if (scale == 0)
        return(*status = ZERO_SCALE);  /* zero scale value is illegal */

    if (ffghdt(fptr, &hdutype, status) > 0)  /* get HDU type */
        return(*status);

    if (hdutype == IMAGE_HDU)
        return(*status = NOT_TABLE);         /* not proper HDU type */

    colptr = (fptr->Fptr)->tableptr;   /* set pointer to the first column */
    colptr += (colnum - 1);     /* increment to the correct column */

    colptr->tscale = scale;
    colptr->tzero = zero;

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fftnul(fitsfile *fptr,      /* I - FITS file pointer                  */
           int colnum,          /* I - column number to apply nulvalue to */
           LONGLONG nulvalue,   /* I - null pixel value: value of TNULLn  */
           int *status)         /* IO - error status                      */
/*
  Define the value used to represent undefined pixels in the BINTABLE column.
  This only applies to integer datatype columns (TFORM = B, I, or J).
  This routine overrides the null pixel value given by the TNULLn keyword
  if present.  Note that this routine does not write or modify the TNULLn
  keyword, but instead only modifies the value temporarily in the internal
  buffer. Thus, a subsequent call to the ffrdef routine will reset the null
  value back to the TNULLn  keyword value (or not defined if the keyword is not
  present).
*/
{
    tcolumn *colptr;
    int hdutype;

    if (*status > 0)
        return(*status);

    if (ffghdt(fptr, &hdutype, status) > 0)  /* get HDU type */
        return(*status);

    if (hdutype != BINARY_TBL)
        return(*status = NOT_BTABLE);        /* not proper HDU type */
 
    colptr = (fptr->Fptr)->tableptr;   /* set pointer to the first column */
    colptr += (colnum - 1);    /* increment to the correct column */

    colptr->tnull = nulvalue;

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffsnul(fitsfile *fptr,      /* I - FITS file pointer                  */
           int colnum,          /* I - column number to apply nulvalue to */
           char *nulstring,     /* I - null pixel value: value of TNULLn  */
           int *status)         /* IO - error status                      */
/*
  Define the string used to represent undefined pixels in the ASCII TABLE
  column. This routine overrides the null  value given by the TNULLn keyword
  if present.  Note that this routine does not write or modify the TNULLn
  keyword, but instead only modifies the value temporarily in the internal
  buffer. Thus, a subsequent call to the ffrdef routine will reset the null
  value back to the TNULLn keyword value (or not defined if the keyword is not
  present).
*/
{
    tcolumn *colptr;
    int hdutype;

    if (*status > 0)
        return(*status);

    if (ffghdt(fptr, &hdutype, status) > 0)  /* get HDU type */
        return(*status);

    if (hdutype != ASCII_TBL)
        return(*status = NOT_ATABLE);        /* not proper HDU type */
 
    colptr = (fptr->Fptr)->tableptr;   /* set pointer to the first column */
    colptr += (colnum - 1);    /* increment to the correct column */

    colptr->strnull[0] = '\0';
    strncat(colptr->strnull, nulstring, 19);  /* limit string to 19 chars */

    return(*status);
}
cfitsio/simplerng.c0000644000225700000360000003314513246025103014152 0ustar  cagordonlhea/* 
   Simple Random Number Generators
       - getuniform - uniform deviate [0,1]
       - getnorm    - gaussian (normal) deviate (mean=0, stddev=1)
       - getpoisson - poisson deviate for given expected mean lambda

   This code is adapted from SimpleRNG by John D Cook, which is
   provided in the public domain.

   The original C++ code is found here:
   http://www.johndcook.com/cpp_random_number_generation.html

   This code has been modified in the following ways compared to the
   original.
     1. convert to C from C++
     2. keep only uniform, gaussian and poisson deviates
     3. state variables are module static instead of class variables
     4. provide an srand() equivalent to initialize the state
*/
#include 
#include 

#define PI 3.1415926535897932384626433832795

/* Use the standard system rand() library routine if it provides
   enough bits of information, since it probably has better randomness
   than the toy algorithm in this module. */
#if defined(RAND_MAX) && RAND_MAX > 1000000000
#define USE_SYSTEM_RAND
#endif

int simplerng_poisson_small(double lambda);
int simplerng_poisson_large(double lambda);
double simplerng_getuniform_pr(unsigned int *u, unsigned int *v);
unsigned int simplerng_getuint_pr(unsigned int *u, unsigned int *v);
double simplerng_logfactorial(int n);

/*
  These values are not magical, just the default values Marsaglia used.
  Any unit should work.
*/
static unsigned int m_u = 521288629, m_v = 362436069;

/* Set u and v state variables */
void simplerng_setstate(unsigned int u, unsigned int v)
{
    m_u = u;
    m_v = v;
}

/* Retrieve u and v state variables */
void simplerng_getstate(unsigned int *u, unsigned int *v)
{
    *u = m_u;
    *v = m_v;
}

/* srand() equivalent to seed the two state variables */
void simplerng_srand(unsigned int seed)
{
#ifdef USE_SYSTEM_RAND
  srand(seed);
#else
  simplerng_setstate(seed ^ 521288629, seed ^ 362436069);
#endif
}

/* Private routine to get uniform deviate */
double simplerng_getuniform_pr(unsigned int *u, unsigned int *v)
{
  /* 0 <= u <= 2^32 */
  unsigned int z = simplerng_getuint_pr(u, v);
  /* The magic number is 1/(2^32) and so result is positive and less than 1. */
  return z*2.328306435996595e-10;
}

/* Private routine to get unsigned integer */
/* Marsaglia multiply-with-carry algorithm (MWC) */
unsigned int simplerng_getuint_pr(unsigned int *u, unsigned int *v)
{
  *v = 36969*((*v) & 65535) + ((*v) >> 16);
  *u = 18000*((*u) & 65535) + ((*u) >> 16);
  return ((*v) << 16) + (*u);
}

/* Get uniform deviate [0,1] */
double simplerng_getuniform(void)
{
#ifdef USE_SYSTEM_RAND
  return rand()*(1.0 / ((double)RAND_MAX + 1));
#else
  return simplerng_getuniform_pr(&m_u, &m_v);
#endif
}

/* Get unsigned integer [0, UINT_MAX] */
unsigned int simplerng_getuint()
{
  /* WARNING: no option for calling rand() here.  Will need to provide
     a scalar to make the uint in the [0,UINT_MAX] range */
  return simplerng_getuint_pr(&m_u, &m_v);
}
    
/* Get normal (Gaussian) random sample with mean=0, stddev=1 */
double simplerng_getnorm()
{
  double u1, u2, r, theta;
  static int saved = 0;
  static double y;

  /* Since you get two deviates for "free" with each calculation, save
     one of them for later */

  if (saved == 0) {
    /* Use Box-Muller algorithm */
    u1 = simplerng_getuniform();
    u2 = simplerng_getuniform();
    r = sqrt( -2.0*log(u1) );
    theta = 2.0*PI*u2;
    /* save second value for next call */
    y = r*cos(theta);
    saved = 1;
    return r*sin(theta);

  } else {
    /* We already saved a value from the last call so use it */
    saved = 0;
    return y;
  }
}

/* Poisson deviate for expected mean value lambda.
   lambda should be in the range [0, infinity]
   
   For small lambda, a simple rejection method is used
   For large lambda, an approximation is used
*/
int simplerng_getpoisson(double lambda)
{
  if (lambda < 0) lambda = 0;
  return ((lambda < 15.0) 
	  ? simplerng_poisson_small(lambda) 
	  : simplerng_poisson_large(lambda));
}

int simplerng_poisson_small(double lambda)
{
  /* Algorithm due to Donald Knuth, 1969. */
  double p = 1.0, L = exp(-lambda);
  int k = 0;
  do {
    k++;
    p *= simplerng_getuniform();
  }
  while (p > L);
  return k - 1;
}

int simplerng_poisson_large(double lambda)
{
  /* "Rejection method PA" from "The Computer Generation of Poisson Random Variables" by A. C. Atkinson
     Journal of the Royal Statistical Society Series C (Applied Statistics) Vol. 28, No. 1. (1979)
     The article is on pages 29-35. The algorithm given here is on page 32. */
  static double beta, alpha, k;
  static double old_lambda = -999999.;

  if (lambda != old_lambda) {
    double c = 0.767 - 3.36/lambda;
    beta = PI/sqrt(3.0*lambda);
    alpha = beta*lambda;
    k = log(c) - lambda - log(beta);
    old_lambda = lambda;
  }

  for(;;) { /* forever */
    double u, x, v, y, temp, lhs, rhs;
    int n;

    u = simplerng_getuniform();
    x = (alpha - log((1.0 - u)/u))/beta;
    n = (int) floor(x + 0.5);
    if (n < 0) continue;

    v = simplerng_getuniform();
    y = alpha - beta*x;
    temp = 1.0 + exp(y);
    lhs = y + log(v/(temp*temp));
    rhs = k + n*log(lambda) - simplerng_logfactorial(n);
    if (lhs <= rhs) return n;
  }

}

/* Lookup table for log-gamma function */
static double lf[] = {
            0.000000000000000,
            0.000000000000000,
            0.693147180559945,
            1.791759469228055,
            3.178053830347946,
            4.787491742782046,
            6.579251212010101,
            8.525161361065415,
            10.604602902745251,
            12.801827480081469,
            15.104412573075516,
            17.502307845873887,
            19.987214495661885,
            22.552163853123421,
            25.191221182738683,
            27.899271383840894,
            30.671860106080675,
            33.505073450136891,
            36.395445208033053,
            39.339884187199495,
            42.335616460753485,
            45.380138898476908,
            48.471181351835227,
            51.606675567764377,
            54.784729398112319,
            58.003605222980518,
            61.261701761002001,
            64.557538627006323,
            67.889743137181526,
            71.257038967168000,
            74.658236348830158,
            78.092223553315307,
            81.557959456115029,
            85.054467017581516,
            88.580827542197682,
            92.136175603687079,
            95.719694542143202,
            99.330612454787428,
            102.968198614513810,
            106.631760260643450,
            110.320639714757390,
            114.034211781461690,
            117.771881399745060,
            121.533081515438640,
            125.317271149356880,
            129.123933639127240,
            132.952575035616290,
            136.802722637326350,
            140.673923648234250,
            144.565743946344900,
            148.477766951773020,
            152.409592584497350,
            156.360836303078800,
            160.331128216630930,
            164.320112263195170,
            168.327445448427650,
            172.352797139162820,
            176.395848406997370,
            180.456291417543780,
            184.533828861449510,
            188.628173423671600,
            192.739047287844900,
            196.866181672889980,
            201.009316399281570,
            205.168199482641200,
            209.342586752536820,
            213.532241494563270,
            217.736934113954250,
            221.956441819130360,
            226.190548323727570,
            230.439043565776930,
            234.701723442818260,
            238.978389561834350,
            243.268849002982730,
            247.572914096186910,
            251.890402209723190,
            256.221135550009480,
            260.564940971863220,
            264.921649798552780,
            269.291097651019810,
            273.673124285693690,
            278.067573440366120,
            282.474292687630400,
            286.893133295426990,
            291.323950094270290,
            295.766601350760600,
            300.220948647014100,
            304.686856765668720,
            309.164193580146900,
            313.652829949878990,
            318.152639620209300,
            322.663499126726210,
            327.185287703775200,
            331.717887196928470,
            336.261181979198450,
            340.815058870798960,
            345.379407062266860,
            349.954118040770250,
            354.539085519440790,
            359.134205369575340,
            363.739375555563470,
            368.354496072404690,
            372.979468885689020,
            377.614197873918670,
            382.258588773060010,
            386.912549123217560,
            391.575988217329610,
            396.248817051791490,
            400.930948278915760,
            405.622296161144900,
            410.322776526937280,
            415.032306728249580,
            419.750805599544780,
            424.478193418257090,
            429.214391866651570,
            433.959323995014870,
            438.712914186121170,
            443.475088120918940,
            448.245772745384610,
            453.024896238496130,
            457.812387981278110,
            462.608178526874890,
            467.412199571608080,
            472.224383926980520,
            477.044665492585580,
            481.872979229887900,
            486.709261136839360,
            491.553448223298010,
            496.405478487217580,
            501.265290891579240,
            506.132825342034830,
            511.008022665236070,
            515.890824587822520,
            520.781173716044240,
            525.679013515995050,
            530.584288294433580,
            535.496943180169520,
            540.416924105997740,
            545.344177791154950,
            550.278651724285620,
            555.220294146894960,
            560.169054037273100,
            565.124881094874350,
            570.087725725134190,
            575.057539024710200,
            580.034272767130800,
            585.017879388839220,
            590.008311975617860,
            595.005524249382010,
            600.009470555327430,
            605.020105849423770,
            610.037385686238740,
            615.061266207084940,
            620.091704128477430,
            625.128656730891070,
            630.172081847810200,
            635.221937855059760,
            640.278183660408100,
            645.340778693435030,
            650.409682895655240,
            655.484856710889060,
            660.566261075873510,
            665.653857411105950,
            670.747607611912710,
            675.847474039736880,
            680.953419513637530,
            686.065407301994010,
            691.183401114410800,
            696.307365093814040,
            701.437263808737160,
            706.573062245787470,
            711.714725802289990,
            716.862220279103440,
            722.015511873601330,
            727.174567172815840,
            732.339353146739310,
            737.509837141777440,
            742.685986874351220,
            747.867770424643370,
            753.055156230484160,
            758.248113081374300,
            763.446610112640200,
            768.650616799717000,
            773.860102952558460,
            779.075038710167410,
            784.295394535245690,
            789.521141208958970,
            794.752249825813460,
            799.988691788643450,
            805.230438803703120,
            810.477462875863580,
            815.729736303910160,
            820.987231675937890,
            826.249921864842800,
            831.517780023906310,
            836.790779582469900,
            842.068894241700490,
            847.352097970438420,
            852.640365001133090,
            857.933669825857460,
            863.231987192405430,
            868.535292100464630,
            873.843559797865740,
            879.156765776907600,
            884.474885770751830,
            889.797895749890240,
            895.125771918679900,
            900.458490711945270,
            905.796028791646340,
            911.138363043611210,
            916.485470574328820,
            921.837328707804890,
            927.193914982476710,
            932.555207148186240,
            937.921183163208070,
            943.291821191335660,
            948.667099599019820,
            954.046996952560450,
            959.431492015349480,
            964.820563745165940,
            970.214191291518320,
            975.612353993036210,
            981.015031374908400,
            986.422203146368590,
            991.833849198223450,
            997.249949600427840,
            1002.670484599700300,
            1008.095434617181700,
            1013.524780246136200,
            1018.958502249690200,
            1024.396581558613400,
            1029.838999269135500,
            1035.285736640801600,
            1040.736775094367400,
            1046.192096209724900,
            1051.651681723869200,
            1057.115513528895000,
            1062.583573670030100,
            1068.055844343701400,
            1073.532307895632800,
            1079.012946818975000,
            1084.497743752465600,
            1089.986681478622400,
            1095.479742921962700,
            1100.976911147256000,
            1106.478169357800900,
            1111.983500893733000,
            1117.492889230361000,
            1123.006317976526100,
            1128.523770872990800,
            1134.045231790853000,
            1139.570684729984800,
            1145.100113817496100,
            1150.633503306223700,
            1156.170837573242400,
};

double simplerng_logfactorial(int n)
{
  if (n < 0) return 0;
  if (n > 254) {
    double x = n + 1;
    return (x - 0.5)*log(x) - x + 0.5*log(2*PI) + 1.0/(12.0*x);
  }
  return lf[n];
}
cfitsio/simplerng.h0000644000225700000360000000206613246025103014155 0ustar  cagordonlhea/* 
   Simple Random Number Generators
       - getuniform - uniform deviate [0,1]
       - getnorm    - gaussian (normal) deviate (mean=0, stddev=1)
       - getpoisson - poisson deviate for given expected mean lambda

   This code is adapted from SimpleRNG by John D Cook, which is
   provided in the public domain.

   The original C++ code is found here:
   http://www.johndcook.com/cpp_random_number_generation.html

   This code has been modified in the following ways compared to the
   original.
     1. convert to C from C++
     2. keep only uniform, gaussian and poisson deviates
     3. state variables are module static instead of class variables
     4. provide an srand() equivalent to initialize the state
*/

extern void simplerng_setstate(unsigned int u, unsigned int v);
extern void simplerng_getstate(unsigned int *u, unsigned int *v);
extern void simplerng_srand(unsigned int seed);
extern double simplerng_getuniform(void);
extern double simplerng_getnorm(void);
extern int simplerng_getpoisson(double lambda);
extern double simplerng_logfactorial(int n);
cfitsio/smem.c0000644000225700000360000000500413246025103013104 0ustar  cagordonlhea#include 
#include 
#include 
#ifdef __APPLE__
#include 
#else
#include 
#endif
#include "fitsio.h"     /* needed to define LONGLONG */
#include "drvrsmem.h"   /* uses LONGLONG */

int	main(int argc, char **argv)
{ int cmdok, listmode, longlistmode, recovermode, deletemode, id;
int status;
char *address;

listmode = longlistmode = recovermode = deletemode = 0;
id = -1;
cmdok = 1;

switch (argc)
 { case 1:	listmode = 1;
		break;
   case 2:
		if (0 == strcmp("-l", argv[1])) longlistmode = 1;
		else if (0 == strcmp("-r", argv[1])) recovermode = 1;
		else if (0 == strcmp("-d", argv[1])) deletemode = 1;
		else cmdok = 0;
		break;
   case 3:
		if (0 == strcmp("-r", argv[1])) recovermode = 1;
		else if (0 == strcmp("-d", argv[1])) deletemode = 1;
		else
		 { cmdok = 0;		/* signal invalid cmd line syntax */
		   break;
		 }
		if (1 != sscanf(argv[2], "%d", &id)) cmdok = 0;
		break;
   default:
		cmdok = 0;
		break;
 }

if (0 == cmdok)
  { printf("usage :\n\n");
    printf("smem            - list all shared memory segments\n");
    printf("\t!\tcouldn't obtain RDONLY lock - info unreliable\n");
    printf("\tIdx\thandle of shared memory segment (visible by application)\n");
    printf("\tKey\tcurrent system key of shared memory segment. Key\n");
    printf("\t\tchanges whenever shmem segment is reallocated. Use\n");
    printf("\t\tipcs (or ipcs -a) to view all shmem segments\n");
    printf("\tNproc\tnumber of processes attached to segment\n");
    printf("\tSize\tsize of shmem segment in bytes\n");
    printf("\tFlags\tRESIZABLE - realloc allowed, PERSIST - segment is not\n");
    printf("\t\tdeleted after shared_free called by last process attached\n");
    printf("\t\tto it.\n");
    printf("smem -d         - delete all shared memory segments (may block)\n");
    printf("smem -d id      - delete specific shared memory segment (may block)\n");
    printf("smem -r         - unconditionally reset all shared memory segments\n\t\t(does not block, recovers zombie handles left by kill -9)\n");
    printf("smem -r id      - unconditionally reset specific shared memory segment\n");
  }

if (shared_init(0))
  { printf("couldn't initialize shared memory, aborting ...\n");
    return(10);
  }

if (listmode) shared_list(id);
else if (recovermode) shared_recover(id);
else if (deletemode) shared_uncond_delete(id);

for (id = 0; id <16; id++) {
  status = shared_getaddr(id, &address);
  if (!status)printf("id, status, address %d %d %ld %.30s\n", id, status, address, address);
}
return(0);
}
cfitsio/speed.c0000644000225700000360000003614313246025103013253 0ustar  cagordonlhea#include 
#include 
#include 
#include 
#include 

/*
  Every program which uses the CFITSIO interface must include the
  the fitsio.h header file.  This contains the prototypes for all
  the routines and defines the error status values and other symbolic
  constants used in the interface.  
*/
#include "fitsio.h"

#define minvalue(A,B) ((A) < (B) ? (A) : (B))

/* size of the image */
#define XSIZE 3000
#define YSIZE 3000

/* size of data buffer */
#define SHTSIZE 20000
static long sarray[ SHTSIZE ] = {SHTSIZE * 0};

/* no. of rows in binary table */
#define BROWS 2500000

/* no. of rows in ASCII table */
#define AROWS 400000

/*  CLOCKS_PER_SEC should be defined by most compilers */
#if defined(CLOCKS_PER_SEC)
#define CLOCKTICKS CLOCKS_PER_SEC
#else
/* on SUN OS machine, CLOCKS_PER_SEC is not defined, so set its value */
#define CLOCKTICKS 1000000
#define difftime(A,B) ((double) A - (double) B)
#endif

/* define variables for measuring elapsed time */
clock_t scpu, ecpu;
time_t start, finish;
long startsec;   /* start of elapsed time interval */
int startmilli;  /* start of elapsed time interval */

int writeimage(fitsfile *fptr, int *status);
int writebintable(fitsfile *fptr, int *status);
int writeasctable(fitsfile *fptr, int *status);
int readimage(fitsfile *fptr, int *status);
int readatable(fitsfile *fptr, int *status);
int readbtable(fitsfile *fptr, int *status);
void printerror( int status);
int marktime(int *status);
int gettime(double *elapse, float *elapscpu, int *status);
int main(void);

int main()
{
/*************************************************************************
    This program tests the speed of writing/reading FITS files with cfitsio
**************************************************************************/

    FILE *diskfile;
    fitsfile *fptr;        /* pointer to the FITS file, defined in fitsio.h */
    int status, ii;
    long rawloop;
    char filename[] = "speedcc.fit";           /* name for new FITS file */
    char buffer[2880] = {2880 * 0};
    time_t tbegin, tend;
    float rate, size, elapcpu, cpufrac;
    double elapse;

    tbegin = time(0);

    remove(filename);               /* Delete old file if it already exists */

    diskfile =  fopen(filename,"w+b");
    rawloop = XSIZE * YSIZE / 720;

    printf("                                                ");
    printf(" SIZE / ELAPSE(%%CPU) = RATE\n");
    printf("RAW fwrite (2880 bytes/loop)...                 ");
    marktime(&status);

    for (ii = 0; ii < rawloop; ii++)
      if (fwrite(buffer, 1, 2880, diskfile) != 2880)
        printf("write error \n");

    gettime(&elapse, &elapcpu, &status);

    cpufrac = elapcpu / elapse * 100.;
    size = 2880. * rawloop / 1000000.;
    rate = size / elapse;
    printf(" %4.1fMB/%6.3fs(%3.0f) = %5.2fMB/s\n", size, elapse, cpufrac,rate);

    /* read back the binary records */
    fseek(diskfile, 0, 0);

    printf("RAW fread  (2880 bytes/loop)...                 ");
    marktime(&status);

    for (ii = 0; ii < rawloop; ii++)
      if (fread(buffer, 1, 2880, diskfile) != 2880)
        printf("read error \n");

    gettime(&elapse, &elapcpu, &status);

    cpufrac = elapcpu / elapse * 100.;
    size = 2880. * rawloop / 1000000.;
    rate = size / elapse;
    printf(" %4.1fMB/%6.3fs(%3.0f) = %5.2fMB/s\n", size, elapse, cpufrac,rate);

    fclose(diskfile);
    remove(filename);

    status = 0;     
    fptr = 0;

    if (fits_create_file(&fptr, filename, &status)) /* create new FITS file */
       printerror( status);          
   
    if (writeimage(fptr, &status))
       printerror( status);     

    if (writebintable(fptr, &status))
       printerror( status);     

    if (writeasctable(fptr, &status))
       printerror( status);     

    if (readimage(fptr, &status))
       printerror( status);     

    if (readbtable(fptr, &status))
       printerror( status);     

    if (readatable(fptr, &status))
       printerror( status);     

    if (fits_close_file(fptr, &status))     
         printerror( status );

    tend = time(0);
    elapse = difftime(tend, tbegin) + 0.5;
    printf("Total elapsed time = %.3fs, status = %d\n",elapse, status);
    return(0);
}
/*--------------------------------------------------------------------------*/
int writeimage(fitsfile *fptr, int *status)

    /**************************************************/
    /* write the primary array containing a 2-D image */
    /**************************************************/
{
    long  nremain, ii;
    float rate, size, elapcpu, cpufrac;
    double elapse;

    /* initialize FITS image parameters */
    int bitpix   =  32;   /* 32-bit  signed integer pixel values       */
    long naxis    =   2;  /* 2-dimensional image                            */    
    long naxes[2] = {XSIZE, YSIZE }; /* image size */

    /* write the required keywords for the primary array image */
    if ( fits_create_img(fptr, bitpix, naxis, naxes, status) )
         printerror( *status );          

    printf("\nWrite %dx%d I*4 image, %d pixels/loop:   ",XSIZE,YSIZE,SHTSIZE);
    marktime(status);

    nremain = XSIZE * YSIZE;
    for (ii = 1; ii <= nremain; ii += SHTSIZE)
    {
      ffpprj(fptr, 0, ii, SHTSIZE, sarray, status);
    }

    ffflus(fptr, status);  /* flush all buffers to disk */

    gettime(&elapse, &elapcpu, status);

    cpufrac = elapcpu / elapse * 100.;
    size = XSIZE * 4. * YSIZE / 1000000.;
    rate = size / elapse;
    printf(" %4.1fMB/%6.3fs(%3.0f) = %5.2fMB/s\n", size, elapse, cpufrac,rate);

    return( *status );
}
/*--------------------------------------------------------------------------*/
int writebintable (fitsfile *fptr, int *status)

    /*********************************************************/
    /* Create a binary table extension containing 3 columns  */
    /*********************************************************/
{
    int tfields = 2;
    long nremain, ntodo, firstrow = 1, firstelem = 1, nrows;
    float rate, size, elapcpu, cpufrac;
    double elapse;

    char extname[] = "Speed_Test";           /* extension name */

    /* define the name, datatype, and physical units for the columns */
    char *ttype[] = { "first", "second" };
    char *tform[] = {"1J",       "1J"   };
    char *tunit[] = { " ",       " "    };

    /* append a new empty binary table onto the FITS file */

    if ( fits_create_tbl( fptr, BINARY_TBL, BROWS, tfields, ttype, tform,
                tunit, extname, status) )
         printerror( *status );

    /* get table row size and optimum number of rows to write per loop */
    fits_get_rowsize(fptr, &nrows, status);
    nrows = minvalue(nrows, SHTSIZE);
    nremain = BROWS;

    printf("Write %7drow x %dcol bintable %4ld rows/loop:", BROWS, tfields,
       nrows);
    marktime(status);

    while(nremain)
    {
      ntodo = minvalue(nrows, nremain);
      ffpclj(fptr, 1, firstrow, firstelem, ntodo, sarray, status);
      ffpclj(fptr, 2, firstrow, firstelem, ntodo, sarray, status);
      firstrow += ntodo;
      nremain -= ntodo;
    }

    ffflus(fptr, status);  /* flush all buffers to disk */

    gettime(&elapse, &elapcpu, status);

    cpufrac = elapcpu / elapse * 100.;
    size = BROWS * 8. / 1000000.;
    rate = size / elapse;
    printf(" %4.1fMB/%6.3fs(%3.0f) = %5.2fMB/s\n", size, elapse, cpufrac,rate);

    return( *status );
}
/*--------------------------------------------------------------------------*/
int writeasctable (fitsfile *fptr, int *status)

    /*********************************************************/
    /* Create an ASCII table extension containing 2 columns  */
    /*********************************************************/
{
    int tfields = 2;
    long nremain, ntodo, firstrow = 1, firstelem = 1;
    long nrows;
    float rate, size, elapcpu, cpufrac;
    double elapse;

    char extname[] = "Speed_Test";           /* extension name */

    /* define the name, datatype, and physical units for the columns */
    char *ttype[] = { "first", "second" };
    char *tform[] = {"I6",       "I6"   };
    char *tunit[] = { " ",      " "     };

    /* append a new empty ASCII table onto the FITS file */
    if ( fits_create_tbl( fptr, ASCII_TBL, AROWS, tfields, ttype, tform,
                tunit, extname, status) )
         printerror( *status );

    /* get table row size and optimum number of rows to write per loop */
    fits_get_rowsize(fptr, &nrows, status);
    nrows = minvalue(nrows, SHTSIZE);
    nremain = AROWS;

    printf("Write %7drow x %dcol asctable %4ld rows/loop:", AROWS, tfields,
           nrows);
    marktime(status);

    while(nremain)
    {
      ntodo = minvalue(nrows, nremain);
      ffpclj(fptr, 1, firstrow, firstelem, ntodo, sarray, status);
      ffpclj(fptr, 2, firstrow, firstelem, ntodo, sarray, status);
      firstrow += ntodo;
      nremain -= ntodo;
    }

    ffflus(fptr, status);  /* flush all buffers to disk */

    gettime(&elapse, &elapcpu, status);

    cpufrac = elapcpu / elapse * 100.;
    size = AROWS * 13. / 1000000.;
    rate = size / elapse;
    printf(" %4.1fMB/%6.3fs(%3.0f) = %5.2fMB/s\n", size, elapse, cpufrac,rate);

    return( *status );
}
/*--------------------------------------------------------------------------*/
int readimage( fitsfile *fptr, int *status )

    /*********************/
    /* Read a FITS image */
    /*********************/
{
    int anynull, hdutype;
    long nremain, ii;
    long longnull = 0;
    float rate, size, elapcpu, cpufrac;
    double elapse;

    /* move to the primary array */
    if ( fits_movabs_hdu(fptr, 1, &hdutype, status) ) 
         printerror( *status );

    printf("\nRead back image                                 ");
    marktime(status);

    nremain = XSIZE * YSIZE;
    for (ii=1; ii <= nremain; ii += SHTSIZE)
    {
      ffgpvj(fptr, 0, ii, SHTSIZE, longnull, sarray, &anynull, status);
    }

    gettime(&elapse, &elapcpu, status);

    cpufrac = elapcpu / elapse * 100.;
    size = XSIZE * 4. * YSIZE / 1000000.;
    rate = size / elapse;
    printf(" %4.1fMB/%6.3fs(%3.0f) = %5.2fMB/s\n", size, elapse, cpufrac,rate);

    return( *status );
}
/*--------------------------------------------------------------------------*/
int readbtable( fitsfile *fptr, int *status )

    /************************************************************/
    /* read and print data values from the binary table */
    /************************************************************/
{
    int hdutype, anynull;
    long nremain, ntodo, firstrow = 1, firstelem = 1;
    long nrows;
    long lnull = 0;
    float rate, size, elapcpu, cpufrac;
    double elapse;

    /* move to the table */
    if ( fits_movrel_hdu(fptr, 1, &hdutype, status) ) 
           printerror( *status );

    /* get table row size and optimum number of rows to read per loop */
    fits_get_rowsize(fptr, &nrows, status);
    nrows = minvalue(nrows, SHTSIZE);
    
    /*  read the columns */  
    nremain = BROWS;

    printf("Read back BINTABLE                              ");
    marktime(status);

    while(nremain)
    {
      ntodo = minvalue(nrows, nremain);
      ffgcvj(fptr, 1, firstrow, firstelem, ntodo,
                     lnull, sarray, &anynull, status);
      ffgcvj(fptr, 2, firstrow, firstelem, ntodo,
                     lnull, sarray, &anynull, status);
      firstrow += ntodo; 
      nremain  -= ntodo;
    }

    gettime(&elapse, &elapcpu, status);

    cpufrac = elapcpu / elapse * 100.;
    size = BROWS * 8. / 1000000.;
    rate = size / elapse;
    printf(" %4.1fMB/%6.3fs(%3.0f) = %5.2fMB/s\n", size, elapse, cpufrac,rate);

    return( *status );
}
/*--------------------------------------------------------------------------*/
int readatable( fitsfile *fptr, int *status )

    /************************************************************/
    /* read and print data values from an ASCII or binary table */
    /************************************************************/
{
    int hdutype, anynull;
    long nremain, ntodo, firstrow = 1, firstelem = 1;
    long nrows;
    long lnull = 0;
    float rate, size, elapcpu, cpufrac;
    double elapse;

    /* move to the table */
    if ( fits_movrel_hdu(fptr, 1, &hdutype, status) ) 
           printerror( *status );

    /* get table row size and optimum number of rows to read per loop */
    fits_get_rowsize(fptr, &nrows, status);
    nrows = minvalue(nrows, SHTSIZE);
 
    /*  read the columns */  
    nremain = AROWS;

    printf("Read back ASCII Table                           ");
    marktime(status);

    while(nremain)
    {
      ntodo = minvalue(nrows, nremain);
      ffgcvj(fptr, 1, firstrow, firstelem, ntodo,
                     lnull, sarray, &anynull, status);
      ffgcvj(fptr, 2, firstrow, firstelem, ntodo,
                     lnull, sarray, &anynull, status);
      firstrow += ntodo;
      nremain  -= ntodo;
    }

    gettime(&elapse, &elapcpu, status);

    cpufrac = elapcpu / elapse * 100.;
    size = AROWS * 13. / 1000000.;
    rate = size / elapse;
    printf(" %4.1fMB/%6.3fs(%3.0f) = %5.2fMB/s\n", size, elapse, cpufrac,rate);

    return( *status );
}
/*--------------------------------------------------------------------------*/
void printerror( int status)
{
    /*****************************************************/
    /* Print out cfitsio error messages and exit program */
    /*****************************************************/

    char status_str[FLEN_STATUS], errmsg[FLEN_ERRMSG];
  
    if (status)
      fprintf(stderr, "\n*** Error occurred during program execution ***\n");

    fits_get_errstatus(status, status_str);   /* get the error description */
    fprintf(stderr, "\nstatus = %d: %s\n", status, status_str);

    /* get first message; null if stack is empty */
    if ( fits_read_errmsg(errmsg) ) 
    {
         fprintf(stderr, "\nError message stack:\n");
         fprintf(stderr, " %s\n", errmsg);

         while ( fits_read_errmsg(errmsg) )  /* get remaining messages */
             fprintf(stderr, " %s\n", errmsg);
    }

    exit( status );       /* terminate the program, returning error status */
}
/*--------------------------------------------------------------------------*/
int marktime( int *status)
{
    double telapse;
    time_t temp;
    struct  timeval tv;

    temp = time(0);

    /* Since elapsed time is only measured to the nearest second */
    /* keep getting the time until the seconds tick just changes. */
    /* This provides more consistent timing measurements since the */
    /* intervals all start on an integer seconds. */

    telapse = 0.;

        scpu = clock();
        start = time(0);
/*
    while (telapse == 0.)
    {
        scpu = clock();
        start = time(0);
        telapse = difftime( start, temp );
    }
*/
        gettimeofday (&tv, NULL);

	startsec = tv.tv_sec;
        startmilli = tv.tv_usec/1000;

    return( *status );
}
/*--------------------------------------------------------------------------*/
int gettime(double *elapse, float *elapscpu, int *status)
{
        struct  timeval tv;
	int stopmilli;
	long stopsec;


        gettimeofday (&tv, NULL);
    ecpu = clock();
    finish = time(0);

        stopmilli = tv.tv_usec/1000;
	stopsec = tv.tv_sec;
	

	*elapse = (stopsec - startsec) + (stopmilli - startmilli)/1000.;

/*    *elapse = difftime(finish, start) + 0.5; */
    *elapscpu = (ecpu - scpu) * 1.0 / CLOCKTICKS;

    return( *status );
}
cfitsio/swapproc.c0000644000225700000360000001702713246025103014011 0ustar  cagordonlhea/*  This file, swapproc.c, contains general utility routines that are      */
/*  used by other FITSIO routines to swap bytes.                           */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

/* The fast SSE2 and SSSE3 functions were provided by Julian Taylor, ESO */

#include 
#include 
#include "fitsio2.h"

/* bswap builtin is available since GCC 4.3 */
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
#define HAVE_BSWAP
#endif

#ifdef __SSSE3__
#include 
/* swap 16 bytes according to mask, values must be 16 byte aligned */
static inline void swap_ssse3(char * values, __m128i mask)
{
    __m128i v = _mm_load_si128((__m128i *)values);
    __m128i s = _mm_shuffle_epi8(v, mask);
    _mm_store_si128((__m128i*)values, s);
}
#endif
#ifdef __SSE2__
#include 
/* swap 8 shorts, values must be 16 byte aligned
 * faster than ssse3 variant for shorts */
static inline void swap2_sse2(char * values)
{
    __m128i r1 = _mm_load_si128((__m128i *)values);
    __m128i r2 = r1;
    r1 = _mm_srli_epi16(r1, 8);
    r2 = _mm_slli_epi16(r2, 8);
    r1 = _mm_or_si128(r1, r2);
    _mm_store_si128((__m128i*)values, r1);
}
/* the three shuffles required for 4 and 8 byte variants make
 * SSE2 slower than bswap */


/* get number of elements to peel to reach alignment */
static inline size_t get_peel(void * addr, size_t esize, size_t nvals,
                              size_t alignment)
{
    const size_t offset = (size_t)addr % alignment;
    size_t peel = offset ? (alignment - offset) / esize : 0;
    peel = nvals < peel ? nvals : peel;
    return peel;
}
#endif

/*--------------------------------------------------------------------------*/
static void ffswap2_slow(short *svalues, long nvals)
{
    register long ii;
    unsigned short * usvalues;

    usvalues = (unsigned short *) svalues;

    for (ii = 0; ii < nvals; ii++)
    {
        usvalues[ii] = (usvalues[ii]>>8) | (usvalues[ii]<<8);
    }
}
/*--------------------------------------------------------------------------*/
#if __SSE2__
void ffswap2(short *svalues,  /* IO - pointer to shorts to be swapped    */
             long nvals)     /* I  - number of shorts to be swapped     */
/*
  swap the bytes in the input short integers: ( 0 1 -> 1 0 )
*/
{
    if ((long)svalues % 2 != 0) { /* should not happen */
        ffswap2_slow(svalues, nvals);
        return;
    }

    long ii;
    size_t peel = get_peel((void*)&svalues[0], sizeof(svalues[0]), nvals, 16);

    ffswap2_slow(svalues, peel);
    for (ii = peel; ii < (nvals - peel - (nvals - peel) % 8); ii+=8) {
        swap2_sse2((char*)&svalues[ii]);
    }
    ffswap2_slow(&svalues[ii], nvals - ii);
}
#else
void ffswap2(short *svalues,  /* IO - pointer to shorts to be swapped    */
             long nvals)     /* I  - number of shorts to be swapped     */
/*
  swap the bytes in the input 4-byte integer: ( 0 1 2 3 -> 3 2 1 0 )
*/
{
    ffswap2_slow(svalues, nvals);
}
#endif
/*--------------------------------------------------------------------------*/
static void ffswap4_slow(INT32BIT *ivalues, long nvals)
{
    register long ii;

#if defined(HAVE_BSWAP)
    for (ii = 0; ii < nvals; ii++)
    {
        ivalues[ii] = __builtin_bswap32(ivalues[ii]);
    }
#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
    /* intrinsic byte swapping function in Microsoft Visual C++ 8.0 and later */
    unsigned int* uivalues = (unsigned int *) ivalues;

    /* intrinsic byte swapping function in Microsoft Visual C++ */
    for (ii = 0; ii < nvals; ii++)
    {
        uivalues[ii] = _byteswap_ulong(uivalues[ii]);
    }
#else
    char *cvalues, tmp;

    for (ii = 0; ii < nvals; ii++)
    {
        cvalues = (char *)&ivalues[ii];
        tmp = cvalues[0];
        cvalues[0] = cvalues[3];
        cvalues[3] = tmp;
        tmp = cvalues[1];
        cvalues[1] = cvalues[2];
        cvalues[2] = tmp;
    }
#endif
}
/*--------------------------------------------------------------------------*/
#ifdef __SSSE3__
void ffswap4(INT32BIT *ivalues,  /* IO - pointer to INT*4 to be swapped    */
                 long nvals)     /* I  - number of floats to be swapped     */
/*
  swap the bytes in the input 4-byte integer: ( 0 1 2 3 -> 3 2 1 0 )
*/
{
    if ((long)ivalues % 4 != 0) { /* should not happen */
        ffswap4_slow(ivalues, nvals);
        return;
    }

    long ii;
    const __m128i cmask4 = _mm_set_epi8(12, 13, 14, 15,
                                        8, 9, 10, 11,
                                        4, 5, 6, 7,
                                        0, 1, 2 ,3);
    size_t peel = get_peel((void*)&ivalues[0], sizeof(ivalues[0]), nvals, 16);
    ffswap4_slow(ivalues, peel);
    for (ii = peel; ii < (nvals - peel - (nvals - peel) % 4); ii+=4) {
        swap_ssse3((char*)&ivalues[ii], cmask4);
    }
    ffswap4_slow(&ivalues[ii], nvals - ii);
}
#else
void ffswap4(INT32BIT *ivalues,  /* IO - pointer to INT*4 to be swapped    */
                 long nvals)     /* I  - number of floats to be swapped     */
/*
  swap the bytes in the input 4-byte integer: ( 0 1 2 3 -> 3 2 1 0 )
*/
{
    ffswap4_slow(ivalues, nvals);
}
#endif
/*--------------------------------------------------------------------------*/
static void ffswap8_slow(double *dvalues, long nvals)
{
    register long ii;
#ifdef HAVE_BSWAP
    LONGLONG * llvalues = (LONGLONG*)dvalues;

    for (ii = 0; ii < nvals; ii++) {
        llvalues[ii] = __builtin_bswap64(llvalues[ii]);
    }
#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
    /* intrinsic byte swapping function in Microsoft Visual C++ 8.0 and later */
    unsigned __int64 * llvalues = (unsigned __int64 *) dvalues;

    for (ii = 0; ii < nvals; ii++)
    {
        llvalues[ii] = _byteswap_uint64(llvalues[ii]);
    }
#else
    register char *cvalues;
    register char temp;

    cvalues = (char *) dvalues;      /* copy the pointer value */

    for (ii = 0; ii < nvals*8; ii += 8)
    {
        temp = cvalues[ii];
        cvalues[ii] = cvalues[ii+7];
        cvalues[ii+7] = temp;

        temp = cvalues[ii+1];
        cvalues[ii+1] = cvalues[ii+6];
        cvalues[ii+6] = temp;

        temp = cvalues[ii+2];
        cvalues[ii+2] = cvalues[ii+5];
        cvalues[ii+5] = temp;

        temp = cvalues[ii+3];
        cvalues[ii+3] = cvalues[ii+4];
        cvalues[ii+4] = temp;
    }
#endif
}
/*--------------------------------------------------------------------------*/
#ifdef __SSSE3__
void ffswap8(double *dvalues,  /* IO - pointer to doubles to be swapped     */
             long nvals)       /* I  - number of doubles to be swapped      */
/*
  swap the bytes in the input doubles: ( 01234567  -> 76543210 )
*/
{
    if ((long)dvalues % 8 != 0) { /* should not happen on amd64 */
        ffswap8_slow(dvalues, nvals);
        return;
    }

    long ii;
    const __m128i cmask8 = _mm_set_epi8(8, 9, 10, 11, 12, 13, 14, 15,
                                        0, 1, 2 ,3, 4, 5, 6, 7);
    size_t peel = get_peel((void*)&dvalues[0], sizeof(dvalues[0]), nvals, 16);
    ffswap8_slow(dvalues, peel);
    for (ii = peel; ii < (nvals - peel - (nvals - peel) % 2); ii+=2) {
        swap_ssse3((char*)&dvalues[ii], cmask8);
    }
    ffswap8_slow(&dvalues[ii], nvals - ii);
}
#else
void ffswap8(double *dvalues,  /* IO - pointer to doubles to be swapped     */
             long nvals)       /* I  - number of doubles to be swapped      */
/*
  swap the bytes in the input doubles: ( 01234567  -> 76543210 )
*/
{
    ffswap8_slow(dvalues, nvals);
}
#endif
cfitsio/testf77.f0000644000225700000360000023441413246025103013462 0ustar  cagordonlheaC     This is a big and complicated program that tests most of
C     the fitsio routines.  This code does not represent
C     the most efficient method of reading or writing FITS files 
C     because this code is primarily designed to stress the fitsio
C     library routines.

      character asciisum*17
      character*3 cval
      character*1 xinarray(21), binarray(21), boutarray(21), bnul
      character colname*70, tdisp*40, nulstr*40
      character oskey*15
      character iskey*21
      character lstr*200   
      character  comm*73
      character*30 inskey(21)
      character*30 onskey(3)
      character filename*40, card*78, card2*78
      character keyword*8
      character value*68, comment*72
      character uchars*78
      character*15 ttype(10), tform(10), tunit(10)
      character*15 tblname
      character*15 binname
      character errmsg*75
      character*8  inclist(2),exclist(2)
      character*8 xctype,yctype,ctype
      character*18 kunit

      logical simple,extend,larray(42), larray2(42)
      logical olkey, ilkey, onlkey(3), inlkey(3), anynull

      integer*2 imgarray(19,30), imgarray2(10,20)
      integer*2         iinarray(21), ioutarray(21), inul

      integer naxes(3), pcount, gcount, npixels, nrows, rowlen
      integer existkeys, morekeys, keynum
      integer datastatus, hdustatus
      integer status, bitpix, naxis, block
      integer ii, jj, jjj, hdutype, hdunum, tfields
      integer nkeys, nfound, colnum, typecode, signval,nmsg
      integer repeat, offset, width, jnulval
      integer kinarray(21), koutarray(21), knul
      integer jinarray(21), joutarray(21), jnul
      integer ojkey, ijkey, otint
      integer onjkey(3), injkey(3)
      integer tbcol(5)
      integer iunit, tmpunit
      integer fpixels(2), lpixels(2), inc(2)

      real estatus, vers
      real einarray(21), eoutarray(21), enul, cinarray(42)
      real ofkey, oekey, iekey, onfkey(3),onekey(3), inekey(3)

      double precision dinarray(21),doutarray(21),dnul, minarray(42)
      double precision scale, zero
      double precision ogkey, odkey, idkey, otfrac, ongkey(3)
      double precision ondkey(3), indkey(3)
      double precision checksum, datsum
      double precision xrval,yrval,xrpix,yrpix,xinc,yinc,rot
      double precision xpos,ypos,xpix,ypix

      tblname = 'Test-ASCII'
      binname = 'Test-BINTABLE'
      onskey(1) = 'first string'
      onskey(2) = 'second string'
      onskey(3) = '        '
      oskey = 'value_string'
      inclist(1)='key*'
      inclist(2)='newikys'
      exclist(1)='key_pr*'
      exclist(2)='key_pkls'
      xctype='RA---TAN'
      yctype='DEC--TAN'

      olkey = .true.
      ojkey = 11
      otint = 12345678
      ofkey = 12.121212
      oekey = 13.131313
      ogkey = 14.1414141414141414D+00
      odkey = 15.1515151515151515D+00
      otfrac = .1234567890123456D+00
      onlkey(1) = .true.
      onlkey(2) = .false.
      onlkey(3) = .true.
      onjkey(1) = 11
      onjkey(2) = 12
      onjkey(3) = 13
      onfkey(1) = 12.121212
      onfkey(2) = 13.131313
      onfkey(3) = 14.141414
      onekey(1) = 13.131313
      onekey(2) = 14.141414
      onekey(3) = 15.151515
      ongkey(1) = 14.1414141414141414D+00
      ongkey(2) = 15.1515151515151515D+00
      ongkey(3) = 16.1616161616161616D+00
      ondkey(1) = 15.1515151515151515D+00
      ondkey(2) = 16.1616161616161616D+00
      ondkey(3) = 17.1717171717171717D+00

      tbcol(1) = 1
      tbcol(2) =  17
      tbcol(3) =  28
      tbcol(4) =  43
      tbcol(5) =  56
      status = 0

      call ftvers(vers)
      write(*,'(1x,A)') 'FITSIO TESTPROG'
      write(*, '(1x,A)')' '

      iunit = 15
      tmpunit = 16

      write(*,'(1x,A)') 'Try opening then closing a nonexistent file: '
      call ftopen(iunit, 'tq123x.kjl', 1, block, status)
      write(*,'(1x,A,2i4)')'  ftopen iunit, status (expect an error) ='
     & ,iunit, status
      call ftclos(iunit, status)
      write(*,'(1x,A,i4)')'  ftclos status = ', status
      write(*,'(1x,A)')' '

      call ftcmsg
      status = 0

      filename = 'testf77.fit'

C delete previous version of the file, if it exists 

      call ftopen(iunit, filename, 1, block, status)
      if (status .eq. 0)then
         call ftdelt(iunit, status)
      else
C        clear the error message stack
         call ftcmsg
      end if

      status = 0

C
C        #####################
C        #  create FITS file #
C        #####################
      

      call ftinit(iunit, filename, 1, status)
      write(*,'(1x,A,i4)')'ftinit create new file status = ', status
      write(*,'(1x,A)')' '

      if (status .ne. 0)go to 999

      simple = .true.
      bitpix = 32
      naxis = 2
      naxes(1) = 10
      naxes(2) = 2
      npixels = 20
      pcount = 0
      gcount = 1
      extend = .true.
      
C        ############################
C        #  write single keywords   #
C        ############################
      
      call ftphpr(iunit,simple, bitpix, naxis, naxes, 
     & 0,1,extend,status)

      call ftprec(iunit, 
     &'key_prec= ''This keyword was written by fxprec'' / '//
     & 'comment goes here',  status)

      write(*,'(1x,A)') 'test writing of long string keywords: '
      card = '1234567890123456789012345678901234567890'//
     & '12345678901234567890123456789012345'
      call ftpkys(iunit, 'card1', card, ' ', status)
      call ftgkey(iunit, 'card1', card2, comment, status)

      write(*,'(1x,A)') card
      write(*,'(1x,A)') card2
      
      card = '1234567890123456789012345678901234567890'//
     &  '123456789012345678901234''6789012345'
      call ftpkys(iunit, 'card2', card, ' ', status)
      call ftgkey(iunit, 'card2', card2, comment, status)
      write(*,'(1x,A)') card
      write(*,'(1x,A)') card2
      
      card = '1234567890123456789012345678901234567890'//
     &  '123456789012345678901234''''789012345'
      call ftpkys(iunit, 'card3', card, ' ', status)
      call ftgkey(iunit, 'card3', card2, comment, status)
      write(*,'(1x,A)') card
      write(*,'(1x,A)') card2
      
      card = '1234567890123456789012345678901234567890'//
     & '123456789012345678901234567''9012345'
      call ftpkys(iunit, 'card4', card, ' ', status)
      call ftgkey(iunit, 'card4', card2, comment, status)
      write(*,'(1x,A)') card
      write(*,'(1x,A)') card2

      call ftpkys(iunit, 'key_pkys', oskey, 'fxpkys comment', status)
      call ftpkyl(iunit, 'key_pkyl', olkey, 'fxpkyl comment', status)
      call ftpkyj(iunit, 'key_pkyj', ojkey, 'fxpkyj comment', status)
      call ftpkyf(iunit,'key_pkyf',ofkey,5, 'fxpkyf comment', status)
      call ftpkye(iunit,'key_pkye',oekey,6, 'fxpkye comment', status)
      call ftpkyg(iunit,'key_pkyg',ogkey,14, 'fxpkyg comment',status)
      call ftpkyd(iunit,'key_pkyd',odkey,14, 'fxpkyd comment',status)

      lstr='This is a very long string '//
     &   'value that is continued over more than one keyword.'

      call ftpkls(iunit,'key_pkls',lstr,'fxpkls comment',status)

      call ftplsw(iunit, status)
      call ftpkyt(iunit,'key_pkyt',otint,otfrac,'fxpkyt comment',
     & status)
      call ftpcom(iunit, 'This keyword was written by fxpcom.',
     &  status)
      call ftphis(iunit, 
     &'  This keyword written by fxphis (w/ 2 leading spaces).',
     &    status)

      call ftpdat(iunit, status)
      
      if (status .gt. 0)go to 999   

C
C        ###############################
C        #  write arrays of keywords   #
C        ###############################
      
      nkeys = 3

      comm = 'fxpkns comment&'
      call ftpkns(iunit, 'ky_pkns', 1, nkeys, onskey, comm, status)
      comm = 'fxpknl comment&'
      call ftpknl(iunit, 'ky_pknl', 1, nkeys, onlkey, comm, status)

      comm = 'fxpknj comment&'
      call ftpknj(iunit, 'ky_pknj', 1, nkeys, onjkey, comm, status)

      comm = 'fxpknf comment&'
      call ftpknf(iunit, 'ky_pknf', 1, nkeys, onfkey,5,comm,status)

      comm = 'fxpkne comment&'
      call ftpkne(iunit, 'ky_pkne', 1, nkeys, onekey,6,comm,status)

      comm = 'fxpkng comment&'
      call ftpkng(iunit, 'ky_pkng', 1, nkeys, ongkey,13,comm,status)

      comm = 'fxpknd comment&'
      call ftpknd(iunit, 'ky_pknd', 1, nkeys, ondkey,14,comm,status)
      
      if (status .gt. 0)go to 999
      
C        ############################
C        #  write generic keywords  #
C        ############################
      

      oskey = '1'
      call ftpkys(iunit, 'tstring', oskey, 'tstring comment',status)

      olkey = .true.
      call ftpkyl(iunit, 'tlogical', olkey, 'tlogical comment',
     &    status)

      ojkey = 11
      call ftpkyj(iunit, 'tbyte', ojkey, 'tbyte comment', status)

      ojkey = 21
      call ftpkyj(iunit, 'tshort', ojkey, 'tshort comment', status)

      ojkey = 31
      call ftpkyj(iunit, 'tint', ojkey, 'tint comment', status)

      ojkey = 41
      call ftpkyj(iunit, 'tlong', ojkey, 'tlong comment', status)

      oekey = 42
      call ftpkye(iunit, 'tfloat', oekey, 6,'tfloat comment', status)

      odkey = 82.D+00
      call ftpkyd(iunit, 'tdouble', odkey, 14, 'tdouble comment',
     &          status)

      if (status .gt. 0)go to 999
      write(*,'(1x,A)') 'Wrote all Keywords successfully '


C        ############################
C        #  write data              #
C        ############################
      
      
C define the null value (must do this before writing any data) 
      call ftpkyj(iunit,'BLANK',-99,
     & 'value to use for undefined pixels',   status)
      
C initialize arrays of values to write to primary array 
      do ii = 1, npixels
          boutarray(ii) = char(ii)
          ioutarray(ii) = ii
          joutarray(ii) = ii
          eoutarray(ii) = ii
          doutarray(ii) = ii
      end do      

C write a few pixels with each datatype 
C set the last value in each group of 4 as undefined 
      call ftpprb(iunit, 1,  1, 2, boutarray(1),  status)
      call ftppri(iunit, 1,  5, 2, ioutarray(5),  status)
      call ftpprj(iunit, 1,  9, 2, joutarray(9),  status)
      call ftppre(iunit, 1, 13, 2, eoutarray(13), status)
      call ftpprd(iunit, 1, 17, 2, doutarray(17), status)
      bnul = char(4)
      call ftppnb(iunit, 1,  3, 2, boutarray(3),   bnul, status)
      inul = 8
      call ftppni(iunit, 1,  7, 2, ioutarray(7),  inul, status)
      call ftppnj(iunit, 1, 11, 2, joutarray(11),  12, status)
      call ftppne(iunit, 1, 15, 2, eoutarray(15), 16., status)
      dnul = 20.
      call ftppnd(iunit, 1, 19, 2, doutarray(19), dnul, status)
      call ftppru(iunit, 1, 1, 1, status)

      if (status .gt. 0)then
          write(*,'(1x,A,I4)')'ftppnx status = ', status
          goto 999
      end if

      call ftflus(iunit, status)   
C flush all data to the disk file  
      write(*,'(1x,A,I4)')'ftflus status = ', status
      write(*,'(1x,A)')' '

      call ftghdn(iunit, hdunum)
      write(*,'(1x,A,I4)')'HDU number = ', hdunum

C        ############################
C        #  read data               #
C        ############################
      
     
C read back the data, setting null values = 99 
      write(*,'(1x,A)')
     &   'Values read back from primary array (99 = null pixel)'
      write(*,'(1x,A)') 
     &  'The 1st, and every 4th pixel should be undefined: '

      anynull = .false.
      bnul = char(99)
      call ftgpvb(iunit, 1,  1, 10, bnul, binarray, anynull, status)
      call ftgpvb(iunit, 1, 11, 10, bnul, binarray(11),anynull,status)

      do ii = 1,npixels
           iinarray(ii) = ichar(binarray(ii))
      end do

      write(*,1101) (iinarray(ii), ii = 1, npixels), anynull,
     &  ' (ftgpvb) '
1101  format(1x,20i3,l3,a)

      inul = 99
      call ftgpvi(iunit, 1, 1, npixels, inul, iinarray,anynull,status)

      write(*,1101) (iinarray(ii), ii = 1, npixels), anynull,
     &  ' (ftgpvi) '

      call ftgpvj(iunit, 1, 1, npixels, 99,  jinarray,anynull,status)

      write(*,1101) (jinarray(ii), ii = 1, npixels), anynull,
     &  ' (ftgpvj) '

      call ftgpve(iunit, 1, 1, npixels, 99., einarray,anynull,status)

      write(*,1102) (einarray(ii), ii = 1, npixels), anynull,
     &  ' (ftgpve) '

1102  format(2x,20f3.0,l2,a)

      dnul = 99.
      call ftgpvd(iunit, 1,  1, 10, dnul,  dinarray, anynull, status)
      call ftgpvd(iunit, 1, 11, 10, dnul,dinarray(11),anynull,status)

      write(*,1102) (dinarray(ii), ii = 1, npixels), anynull,
     &  ' (ftgpvd) '

      if (status .gt. 0)then
          write(*,'(1x,A,I4)')'ERROR: ftgpv_ status = ', status
          goto 999
      end if
      
      if (.not. anynull)then
         write(*,'(1x,A)') 'ERROR: ftgpv_ did not detect null values '
         go to 999
      end if
      
C reset the output null value to the expected input value 

      do ii = 4, npixels, 4      
          boutarray(ii) = char(99)
          ioutarray(ii) = 99
          joutarray(ii) = 99
          eoutarray(ii) = 99.
          doutarray(ii) = 99.
      end do

          ii = 1
          boutarray(ii) = char(99)
          ioutarray(ii) = 99
          joutarray(ii) = 99
          eoutarray(ii) = 99.
          doutarray(ii) = 99.

      
C compare the output with the input flag any differences 
      do ii = 1, npixels
     
         if (boutarray(ii) .ne. binarray(ii))then
             write(*,'(1x,A,2A2)') 'bout != bin ', boutarray(ii), 
     &      binarray(ii)
         end if

         if (ioutarray(ii) .ne. iinarray(ii))then
             write(*,'(1x,A,2I8)') 'bout != bin ', ioutarray(ii), 
     &      iinarray(ii)
         end if

         if (joutarray(ii) .ne. jinarray(ii))then
             write(*,'(1x,A,2I12)') 'bout != bin ', joutarray(ii), 
     &       jinarray(ii)
         end if

         if (eoutarray(ii) .ne. einarray(ii))then
             write(*,'(1x,A,2E15.3)') 'bout != bin ', eoutarray(ii),
     &       einarray(ii)
         end if
    
         if (doutarray(ii) .ne. dinarray(ii))then
             write(*,'(1x,A,2D20.6)') 'bout != bin ', doutarray(ii), 
     &       dinarray(ii)
         end if
      end do

      do ii = 1, npixels
        binarray(ii) = char(0)
        iinarray(ii) = 0
        jinarray(ii) = 0
        einarray(ii) = 0.
        dinarray(ii) = 0.
      end do      

      anynull = .false.
      call ftgpfb(iunit, 1,  1, 10, binarray, larray, anynull,status)
      call ftgpfb(iunit, 1, 11, 10, binarray(11), larray(11),
     & anynull, status)

      do ii = 1, npixels
        if (larray(ii))binarray(ii) = char(0)
      end do

      do ii = 1,npixels
           iinarray(ii) = ichar(binarray(ii))
      end do

      write(*,1101)(iinarray(ii),ii = 1,npixels),anynull,' (ftgpfb)'

      call ftgpfi(iunit, 1, 1, npixels, iinarray, larray, anynull,
     & status)

      do ii = 1, npixels
        if (larray(ii))iinarray(ii) = 0
      end do

      write(*,1101)(iinarray(ii),ii = 1,npixels),anynull,' (ftgpfi)'

      call ftgpfj(iunit, 1, 1, npixels, jinarray, larray, anynull,
     & status)

      do ii = 1, npixels
        if (larray(ii))jinarray(ii) = 0
      end do

      write(*,1101)(jinarray(ii),ii = 1,npixels),anynull,' (ftgpfj)'

      call ftgpfe(iunit, 1, 1, npixels, einarray, larray, anynull,
     & status)

      do ii = 1, npixels
        if (larray(ii))einarray(ii) = 0.
      end do

      write(*,1102)(einarray(ii),ii = 1,npixels),anynull,' (ftgpfe)'

      call ftgpfd(iunit, 1,  1, 10, dinarray, larray, anynull,status)
      call ftgpfd(iunit, 1, 11, 10, dinarray(11), larray(11),
     & anynull, status)

      do ii = 1, npixels
        if (larray(ii))dinarray(ii) = 0.
      end do

      write(*,1102)(dinarray(ii),ii = 1,npixels),anynull,' (ftgpfd)'

      if (status .gt. 0)then
          write(*,'(1x,A,I4)')'ERROR: ftgpf_ status = ', status
          go to 999
      end if

      if (.not. anynull)then
         write(*,'(1x,A)') 'ERROR: ftgpf_ did not detect null values'
         go to 999
      end if


C        ##########################################
C        #  close and reopen file multiple times  #
C        ##########################################
      

      do ii = 1, 10
         call ftclos(iunit, status)
        
         if (status .gt. 0)then
            write(*,'(1x,A,I4)')'ERROR in ftclos (1) = ', status
            go to 999
         end if

         call ftopen(iunit, filename, 1, block, status)

         if (status .gt. 0)then
            write(*,'(1x,A,I4)')'ERROR: ftopen open file status = ',
     &      status
            go to 999
         end if
      end do
      
      write(*,'(1x,A)') ' '
      write(*,'(1x,A)') 'Closed then reopened the FITS file 10 times.'
      write(*,'(1x,A)')' '

      call ftghdn(iunit, hdunum)
      write(*,'(1x,A,I4)')'HDU number = ', hdunum


C        ############################
C        #  read single keywords    #
C        ############################
      

      simple = .false.
      bitpix = 0
      naxis = 0
      naxes(1) = 0
      naxes(2) = 0
      pcount = -99
      gcount =  -99
      extend = .false.
      write(*,'(1x,A)') 'Read back keywords: '
      call ftghpr(iunit, 3, simple, bitpix, naxis, naxes, pcount,
     &       gcount, extend, status)
      write(*,'(1x,A,L4,4I4)')'simple, bitpix, naxis, naxes = ',
     &       simple, bitpix, naxis, naxes(1), naxes(2)
      write(*,'(1x,A,2I4,L4)')'  pcount, gcount, extend = ',
     &           pcount, gcount, extend

      call ftgrec(iunit, 9, card, status)
      write(*,'(1x,A)') card
      if (card(1:15) .ne. 'KEY_PREC= ''This')
     &    write(*,'(1x,A)') 'ERROR in ftgrec '

      call ftgkyn(iunit, 9, keyword, value, comment, status)
      write(*,'(1x,5A)') keyword,' ', value(1:35),' ', comment(1:20)

      if (keyword(1:8) .ne. 'KEY_PREC' )
     &    write(*,'(1x,2A)') 'ERROR in ftgkyn: ', keyword

      call ftgcrd(iunit, keyword, card, status)
      write(*,'(1x,A)') card

      if (keyword(1:8) .ne.  card(1:8) )
     &    write(*,'(1x,2A)') 'ERROR in ftgcrd: ', keyword

      call ftgkey(iunit, 'KY_PKNS1', value, comment, status)
      write(*,'(1x,5A)') 'KY_PKNS1 ',':', value(1:15),':', comment(1:16)

      if (value(1:14) .ne. '''first string''')
     &  write(*,'(1x,2A)') 'ERROR in ftgkey: ', value

      call ftgkys(iunit, 'key_pkys', iskey, comment, status)
      write(*,'(1x,5A,I4)')'KEY_PKYS ',':',iskey,':',comment(1:16),
     & status

      call ftgkyl(iunit, 'key_pkyl', ilkey, comment, status)
      write(*,'(1x,2A,L4,2A,I4)') 'KEY_PKYL ',':', ilkey,':', 
     &comment(1:16), status

      call ftgkyj(iunit, 'KEY_PKYJ', ijkey, comment, status)
      write(*,'(1x,2A,I4,2A,I4)') 'KEY_PKYJ ',':',ijkey,':', 
     &  comment(1:16), status

      call ftgkye(iunit, 'KEY_PKYJ', iekey, comment, status)
      write(*,'(1x,2A,f12.5,2A,I4)') 'KEY_PKYE ',':',iekey,':',
     & comment(1:16), status

      call ftgkyd(iunit, 'KEY_PKYJ', idkey, comment, status)
      write(*,'(1x,2A,F12.5,2A,I4)') 'KEY_PKYD ',':',idkey,':', 
     & comment(1:16), status

      if (ijkey .ne. 11 .or. iekey .ne. 11. .or. idkey .ne. 11.)
     &   write(*,'(1x,A,I4,2F5.1)') 'ERROR in ftgky(jed): ',
     & ijkey, iekey, idkey

      iskey= ' '
      call ftgkys(iunit, 'key_pkys', iskey, comment, status)
      write(*,'(1x,5A,I4)') 'KEY_PKYS ',':', iskey,':', comment(1:16),
     &  status

      ilkey = .false.
      call ftgkyl(iunit, 'key_pkyl', ilkey, comment, status)
      write(*,'(1x,2A,L4,2A,I4)') 'KEY_PKYL ',':', ilkey,':',
     &  comment(1:16), status

      ijkey = 0
      call ftgkyj(iunit, 'KEY_PKYJ', ijkey, comment, status)
      write(*,'(1x,2A,I4,2A,I4)') 'KEY_PKYJ ',':',ijkey,':', 
     & comment(1:16), status

      iekey = 0
      call ftgkye(iunit, 'KEY_PKYE', iekey, comment, status)
      write(*,'(1x,2A,f12.5,2A,I4)') 'KEY_PKYE ',':',iekey,':', 
     & comment(1:16), status

      idkey = 0
      call ftgkyd(iunit, 'KEY_PKYD', idkey, comment, status)
      write(*,'(1x,2A,F12.5,2A,I4)') 'KEY_PKYD ',':',idkey,':',
     & comment(1:16), status

      iekey = 0
      call ftgkye(iunit, 'KEY_PKYF', iekey, comment, status)
      write(*,'(1x,2A,f12.5,2A,I4)') 'KEY_PKYF ',':',iekey,':',
     & comment(1:16), status

      iekey = 0
      call ftgkye(iunit, 'KEY_PKYE', iekey, comment, status)
      write(*,'(1x,2A,f12.5,2A,I4)') 'KEY_PKYE ',':',iekey,':', 
     & comment(1:16), status

      idkey = 0
      call ftgkyd(iunit, 'KEY_PKYG', idkey, comment, status)
      write(*,'(1x,2A,f16.12,2A,I4)') 'KEY_PKYG ',':',idkey,':',
     & comment(1:16), status

      idkey = 0
      call ftgkyd(iunit, 'KEY_PKYD', idkey, comment, status)
      write(*,'(1x,2A,f16.12,2A,I4)') 'KEY_PKYD ',':',idkey,':', 
     & comment(1:16), status

      call ftgkyt(iunit, 'KEY_PKYT', ijkey, idkey, comment, status)
      write(*,'(1x,2A,i10,A,f16.14,A,I4)') 'KEY_PKYT  ',':',
     & ijkey,':', idkey, comment(1:16), status

      call ftpunt(iunit, 'KEY_PKYJ', 'km/s/Mpc', status)
      ijkey = 0
      call ftgkyj(iunit, 'KEY_PKYJ', ijkey, comment, status)
      write(*,'(1x,2A,I4,2A,I4)') 'KEY_PKYJ ',':',ijkey,':', 
     & comment(1:38), status
      call ftgunt(iunit,'KEY_PKYJ',kunit,status)
      write(*,'(1x,2A)') 'keyword unit=', kunit

      call ftpunt(iunit, 'KEY_PKYJ', ' ', status)
      ijkey = 0
      call ftgkyj(iunit, 'KEY_PKYJ', ijkey, comment, status)
      write(*,'(1x,2A,I4,2A,I4)') 'KEY_PKYJ ',':',ijkey,':', 
     & comment(1:38), status
      call ftgunt(iunit,'KEY_PKYJ',kunit,status)
      write(*,'(1x,2A)') 'keyword unit=', kunit

      call ftpunt(iunit, 'KEY_PKYJ', 'feet/second/second', status)
      ijkey = 0
      call ftgkyj(iunit, 'KEY_PKYJ', ijkey, comment, status)
      write(*,'(1x,2A,I4,2A,I4)') 'KEY_PKYJ ',':',ijkey,':', 
     & comment(1:38), status
      call ftgunt(iunit,'KEY_PKYJ',kunit,status)
      write(*,'(1x,2A)') 'keyword unit=', kunit

      call ftgkys(iunit, 'key_pkls', lstr, comment, status)
      write(*,'(1x,2A)') 'KEY_PKLS long string value = ', lstr(1:50)
      write(*,'(1x,A)')lstr(51:120)

C get size and position in header 
      call ftghps(iunit, existkeys, keynum, status)
      write(*,'(1x,A,I4,A,I4)') 'header contains ', existkeys,
     & ' keywords; located at keyword ', keynum

C        ############################
C        #  read array keywords     #
C        ############################
      
      call ftgkns(iunit, 'ky_pkns', 1, 3, inskey, nfound, status)
      write(*,'(1x,4A)') 'ftgkns: ', inskey(1)(1:14), inskey(2)(1:14),
     &  inskey(3)(1:14)
      if (nfound .ne. 3 .or. status .gt. 0)
     &   write(*,'(1x,A,2I4)') ' ERROR in ftgkns ', nfound, status

      call ftgknl(iunit, 'ky_pknl', 1, 3, inlkey, nfound, status)
      write(*,'(1x,A,3L4)') 'ftgknl: ', inlkey(1), inlkey(2), inlkey(3)
      if (nfound .ne. 3 .or. status .gt. 0)
     &   write(*,'(1x,A,2I4)') ' ERROR in ftgknl ', nfound, status

      call ftgknj(iunit, 'ky_pknj', 1, 3, injkey, nfound, status)
      write(*,'(1x,A,3I4)') 'ftgknj: ', injkey(1), injkey(2), injkey(3)
      if (nfound .ne. 3 .or. status .gt. 0)
     &   write(*,'(1x,A,2I4)') ' ERROR in ftgknj ', nfound, status

      call ftgkne(iunit, 'ky_pkne', 1, 3, inekey, nfound, status)
      write(*,'(1x,A,3F10.5)') 'ftgkne: ',inekey(1),inekey(2),inekey(3)
      if (nfound .ne. 3 .or. status .gt. 0)
     &   write(*,'(1x,A,2I4)') ' ERROR in ftgkne ', nfound, status

      call ftgknd(iunit, 'ky_pknd', 1, 3, indkey, nfound, status)
      write(*,'(1x,A,3F10.5)') 'ftgknd: ',indkey(1),indkey(2),indkey(3)
      if (nfound .ne. 3 .or. status .gt. 0)
     &   write(*,'(1x,A,2I4)') ' ERROR in ftgknd ', nfound, status

      write(*,'(1x,A)')' '
      write(*,'(1x,A)')
     & 'Before deleting the HISTORY and DATE keywords...'
      do ii = 29, 32     
          call ftgrec(iunit, ii, card, status)
          write(*,'(1x,A)') card(1:8)
      end do

C don't print date value, so that 
C the output will always be the same 
      

C        ############################
C        #  delete keywords         #
C        ############################
      

      call ftdrec(iunit, 30, status)
      call ftdkey(iunit, 'DATE', status)

      write(*,'(1x,A)')' '
      write(*,'(1x,A)') 'After deleting the keywords... '
      do ii = 29, 30            
          call ftgrec(iunit, ii, card, status)
          write(*,'(1x,A)') card
      end do      

      if (status .gt. 0)
     &   write(*,'(1x,A)') ' ERROR deleting keywords '
      

C        ############################
C        #  insert keywords         #
C        ############################
      
      call ftirec(iunit,26,
     & 'KY_IREC = ''This keyword inserted by fxirec''',
     &   status)
      call ftikys(iunit, 'KY_IKYS', 'insert_value_string',
     &  'ikys comment', status)
      call ftikyj(iunit, 'KY_IKYJ', 49, 'ikyj comment', status)
      call ftikyl(iunit, 'KY_IKYL', .true., 'ikyl comment', status)
      call ftikye(iunit, 'KY_IKYE',12.3456,4,'ikye comment',status)
      odkey = 12.345678901234567D+00
      call ftikyd(iunit, 'KY_IKYD', odkey, 14,
     &  'ikyd comment', status)
      call ftikyf(iunit, 'KY_IKYF', 12.3456, 4, 'ikyf comment',
     & status)
      call ftikyg(iunit, 'KY_IKYG', odkey, 13,
     & 'ikyg comment', status)

      write(*,'(1x,A)')' '
      write(*,'(1x,A)') 'After inserting the keywords... '
      do ii = 25, 34
          call ftgrec(iunit, ii, card, status)
          write(*,'(1x,A)') card
      end do

      if (status .gt. 0)
     &   write(*,'(1x,A)') ' ERROR inserting keywords '
      

C        ############################
C        #  modify keywords         #
C        ############################
      
      call ftmrec(iunit, 25,
     & 'COMMENT   This keyword was modified by fxmrec', status)
      call ftmcrd(iunit, 'KY_IREC', 
     & 'KY_MREC = ''This keyword was modified by fxmcrd''', status)
      call ftmnam(iunit, 'KY_IKYS', 'NEWIKYS', status)

      call ftmcom(iunit,'KY_IKYJ','This is a modified comment',
     & status)
      call ftmkyj(iunit, 'KY_IKYJ', 50, '&', status)
      call ftmkyl(iunit, 'KY_IKYL', .false., '&', status)
      call ftmkys(iunit, 'NEWIKYS', 'modified_string', '&', status)
      call ftmkye(iunit, 'KY_IKYE', -12.3456, 4, '&', status)
      odkey = -12.345678901234567D+00

      call ftmkyd(iunit, 'KY_IKYD', odkey, 14, 
     & 'modified comment', status)
      call ftmkyf(iunit, 'KY_IKYF', -12.3456, 4, '&', status)
      call ftmkyg(iunit,'KY_IKYG', odkey,13,'&',status)

      write(*,'(1x,A)')' '
      write(*,'(1x,A)') 'After modifying the keywords... '
      do ii = 25, 34
          call ftgrec(iunit, ii, card, status)
          write(*,'(1x,A)') card
      end do
      
      if (status .gt. 0)then
         write(*,'(1x,A)') ' ERROR modifying keywords '
         go to 999
      end if
      
C        ############################
C        #  update keywords         #
C        ############################
      
      call ftucrd(iunit, 'KY_MREC', 
     & 'KY_UCRD = ''This keyword was updated by fxucrd''',
     &         status)

      call ftukyj(iunit, 'KY_IKYJ', 51, '&', status)
      call ftukyl(iunit, 'KY_IKYL', .true., '&', status)
      call ftukys(iunit, 'NEWIKYS', 'updated_string', '&', status)
      call ftukye(iunit, 'KY_IKYE', -13.3456, 4, '&', status)
      odkey = -13.345678901234567D+00

      call ftukyd(iunit, 'KY_IKYD',odkey , 14, 
     & 'modified comment', status)
      call ftukyf(iunit, 'KY_IKYF', -13.3456, 4, '&', status)
      call ftukyg(iunit, 'KY_IKYG', odkey, 13, '&', status)

      write(*,'(1x,A)')' '
      write(*,'(1x,A)') 'After updating the keywords... '
      do ii = 25, 34
          call ftgrec(iunit, ii, card, status)
          write(*,'(1x,A)') card
      end do

      if (status .gt. 0)then
         write(*,'(1x,A)') ' ERROR modifying keywords '
         go to 999
      end if

C     move to top of header and find keywords using wild cards 
      call ftgrec(iunit, 0, card, status)

      write(*,'(1x,A)')' '
      write(*,'(1x,A)')
     &  'Keywords found using wildcard search (should be 9)...'
      nfound = -1
91    nfound = nfound +1
      call ftgnxk(iunit, inclist, 2, exclist, 2, card, status)
      if (status .eq. 0)then
          write(*,'(1x,A)') card
          go to 91
      end if

      if (nfound .ne. 9)then
          write(*,'(1x,A)')
     &    'ERROR reading keywords using wildcards (ftgnxk)'
         go to 999
      end if
      status = 0

C        ############################
C        #  create binary table     #
C        ############################
      
      tform(1) = '15A'
      tform(2) = '1L'
      tform(3) = '16X'
      tform(4) = '1B'
      tform(5) = '1I'
      tform(6) = '1J'
      tform(7) = '1E'
      tform(8) = '1D'
      tform(9) = '1C'
      tform(10)= '1M'

      ttype(1) = 'Avalue'
      ttype(2) = 'Lvalue'
      ttype(3) = 'Xvalue'
      ttype(4) = 'Bvalue'
      ttype(5) = 'Ivalue'
      ttype(6) = 'Jvalue'
      ttype(7) = 'Evalue'
      ttype(8) = 'Dvalue'
      ttype(9) = 'Cvalue'
      ttype(10)= 'Mvalue'

      tunit(1) = ' '
      tunit(2) = 'm**2'
      tunit(3) = 'cm'
      tunit(4) = 'erg/s'
      tunit(5) = 'km/s'
      tunit(6) = ' '
      tunit(7) = ' '
      tunit(8) = ' '
      tunit(9) = ' '
      tunit(10)= ' '

      nrows = 21
      tfields = 10
      pcount = 0

      call ftibin(iunit, nrows, tfields, ttype, tform, tunit, 
     & binname, pcount, status)
      write(*,'(1x,A)')' '
      write(*,'(1x,A,I4)') 'ftibin status = ', status
      call ftghdn(iunit, hdunum)
      write(*,'(1x,A,I4)') 'HDU number = ', hdunum

C get size and position in header, and reserve space for more keywords 
      call ftghps(iunit, existkeys, keynum, status)
      write(*,'(1x,A,I4,A,I4)') 'header contains ',existkeys,
     & ' keywords located at keyword ', keynum

      morekeys = 40
      call fthdef(iunit, morekeys, status)
      call ftghsp(iunit, existkeys, morekeys, status)
      write(*,'(1x,A,I4,A,I4,A)') 'header contains ', existkeys,
     &' keywords with room for ', morekeys,' more'

C define null value for int cols 
      call fttnul(iunit, 4, 99, status)   
      call fttnul(iunit, 5, 99, status)
      call fttnul(iunit, 6, 99, status)

      call ftpkyj(iunit, 'TNULL4', 99, 'value for undefined pixels',
     &  status)
      call ftpkyj(iunit, 'TNULL5', 99, 'value for undefined pixels',
     &  status)
      call ftpkyj(iunit, 'TNULL6', 99, 'value for undefined pixels',
     & status)

      naxis = 3
      naxes(1) = 1
      naxes(2) = 2
      naxes(3) = 8
      call ftptdm(iunit, 3, naxis, naxes, status)

      naxis = 0
      naxes(1) = 0
      naxes(2) = 0
      naxes(3) = 0
      call ftgtdm(iunit, 3, 3, naxis, naxes, status)
      call ftgkys(iunit, 'TDIM3', iskey, comment, status)
      write(*,'(1x,2A,4I4)') 'TDIM3 = ', iskey, naxis, naxes(1),
     &      naxes(2), naxes(3)

C force header to be scanned (not required) 
      call ftrdef(iunit, status)  
    
C        ############################
C        #  write data to columns   #
C        ############################
         
C initialize arrays of values to write to table 
      signval = -1
      do ii = 1, 21
          signval = signval * (-1)
          boutarray(ii) = char(ii)
          ioutarray(ii) = (ii) * signval
          joutarray(ii) = (ii) * signval
          koutarray(ii) = (ii) * signval
          eoutarray(ii) = (ii) * signval
          doutarray(ii) = (ii) * signval
      end do

      call ftpcls(iunit, 1, 1, 1, 3, onskey, status)  
C write string values 
      call ftpclu(iunit, 1, 4, 1, 1, status)  
C write null value 

      larray(1) = .false.
      larray(2) =.true.
      larray(3) = .false.
      larray(4) = .false.
      larray(5) =.true.
      larray(6) =.true.
      larray(7) = .false.
      larray(8) = .false.
      larray(9) = .false.
      larray(10) =.true.
      larray(11) =.true.
      larray(12) = .true.
      larray(13) = .false.
      larray(14) = .false.
      larray(15) =.false.
      larray(16) =.false.
      larray(17) = .true.
      larray(18) = .true.
      larray(19) = .true.
      larray(20) = .true.
      larray(21) =.false.
      larray(22) =.false.
      larray(23) =.false.
      larray(24) =.false.
      larray(25) =.false.
      larray(26) = .true.
      larray(27) = .true.
      larray(28) = .true.
      larray(29) = .true.
      larray(30) = .true.
      larray(31) =.false.
      larray(32) =.false.
      larray(33) =.false.
      larray(34) =.false.
      larray(35) =.false.
      larray(36) =.false.

C write bits
      call ftpclx(iunit, 3, 1, 1, 36, larray, status) 

C loop over cols 4 - 8 
      do ii = 4, 8   
          call ftpclb(iunit, ii, 1, 1, 2, boutarray, status)
          if (status .eq. 412) status = 0

          call ftpcli(iunit, ii, 3, 1, 2, ioutarray(3), status) 
          if (status .eq. 412) status = 0

          call ftpclj(iunit, ii, 5, 1, 2, koutarray(5), status) 
          if (status .eq. 412) status = 0

          call ftpcle(iunit, ii, 7, 1, 2, eoutarray(7), status)
          if (status .eq. 412)status = 0

          call ftpcld(iunit, ii, 9, 1, 2, doutarray(9), status)
          if (status .eq. 412)status = 0

C write null value 
          call ftpclu(iunit, ii, 11, 1, 1, status)  
      end do

      call ftpclc(iunit,  9, 1, 1, 10, eoutarray, status)
      call ftpclm(iunit, 10, 1, 1, 10, doutarray, status)

C loop over cols 4 - 8 
      do ii = 4, 8
          bnul = char(13)
          call ftpcnb(iunit, ii, 12, 1, 2, boutarray(12),bnul,status)
          if (status .eq. 412) status = 0
          inul=15
          call ftpcni(iunit, ii, 14, 1, 2, ioutarray(14),inul,status) 
          if (status .eq. 412) status = 0
          call ftpcnj(iunit, ii, 16, 1, 2, koutarray(16), 17, status) 
          if (status .eq. 412) status = 0
          call ftpcne(iunit, ii, 18, 1, 2, eoutarray(18), 19.,status)
          if (status .eq. 412) status = 0
          dnul = 21.
          call ftpcnd(iunit, ii, 20, 1, 2, doutarray(20),dnul,status)
          if (status .eq. 412) status = 0
      end do
      
C write logicals
      call ftpcll(iunit, 2, 1, 1, 21, larray, status) 
C write null value 
      call ftpclu(iunit, 2, 11, 1, 1, status)  
      write(*,'(1x,A,I4)') 'ftpcl_ status = ', status
      if (status .gt. 0)go to 999
      
C        #########################################
C        #  get information about the columns    #
C        #########################################
      
      write(*,'(1x,A)')' '
      write(*,'(1x,A)')
     & 'Find the column numbers a returned status value'//
     & ' of 237 is'
      write(*,'(1x,A)') 
     & 'expected and indicates that more than one column'//
     & ' name matches'
      write(*,'(1x,A)')'the input column name template.'//
     & '  Status = 219 indicates that'
      write(*,'(1x,A)') 'there was no matching column name.'

      call ftgcno(iunit, 0, 'Xvalue', colnum, status)
      write(*,'(1x,A,I4,A,I4)') 'Column Xvalue is number', colnum,
     &' status =',status

219   continue
      if (status .ne. 219)then
        call ftgcnn(iunit, 1, '*ue', colname, colnum, status)
        write(*,'(1x,3A,I4,A,I4)') 'Column ',colname(1:6),' is number', 
     &   colnum,' status = ',  status
        go to 219
      end if

      status = 0

      write(*,'(1x,A)')' '
      write(*,'(1x,A)') 'Information about each column: '

      do ii = 1, tfields
        call ftgtcl(iunit, ii, typecode, repeat, width, status)
        call ftgbcl(iunit,ii,ttype,tunit,cval,repeat,scale,
     &        zero, jnulval, tdisp, status)

        write(*,'(1x,A,3I4,5A,2F8.2,I12,A)')
     &  tform(ii)(1:3), typecode, repeat, width,' ',
     &  ttype(1)(1:6),' ',tunit(1)(1:6), cval, scale, zero, jnulval,
     &  tdisp(1:8)
      end do

      write(*,'(1x,A)') ' '

C        ###############################################
C        #  insert ASCII table before the binary table #
C        ###############################################

      call ftmrhd(iunit, -1, hdutype, status)
      if (status .gt. 0)goto 999

      tform(1) = 'A15'
      tform(2) = 'I10'
      tform(3) = 'F14.6'
      tform(4) = 'E12.5'
      tform(5) = 'D21.14'

      ttype(1) = 'Name'
      ttype(2) = 'Ivalue'
      ttype(3) = 'Fvalue'
      ttype(4) = 'Evalue'
      ttype(5) = 'Dvalue'

      tunit(1) = ' '
      tunit(2) = 'm**2'
      tunit(3) = 'cm'
      tunit(4) = 'erg/s'
      tunit(5) = 'km/s'

      rowlen = 76
      nrows = 11
      tfields = 5

      call ftitab(iunit, rowlen, nrows, tfields, ttype, tbcol, 
     & tform, tunit, tblname, status)
      write(*,'(1x,A,I4)') 'ftitab status = ', status
      call ftghdn(iunit, hdunum)
      write(*,'(1x,A,I4)') 'HDU number = ', hdunum

C define null value for int cols 
      call ftsnul(iunit, 1, 'null1', status)   
      call ftsnul(iunit, 2, 'null2', status)
      call ftsnul(iunit, 3, 'null3', status)
      call ftsnul(iunit, 4, 'null4', status)
      call ftsnul(iunit, 5, 'null5', status)
 
      call ftpkys(iunit, 'TNULL1', 'null1',
     & 'value for undefined pixels', status)
      call ftpkys(iunit, 'TNULL2', 'null2',
     & 'value for undefined pixels', status)
      call ftpkys(iunit, 'TNULL3', 'null3',
     & 'value for undefined pixels', status)
      call ftpkys(iunit, 'TNULL4', 'null4',
     & 'value for undefined pixels', status)
      call ftpkys(iunit, 'TNULL5', 'null5',
     & 'value for undefined pixels', status)

      if (status .gt. 0) goto 999
      
C        ############################
C        #  write data to columns   #
C        ############################
           
C initialize arrays of values to write to table 
      do ii = 1,21     
          boutarray(ii) = char(ii)
          ioutarray(ii) = ii
          joutarray(ii) = ii
          eoutarray(ii) = ii
          doutarray(ii) = ii
      end do      

C write string values 
      call ftpcls(iunit, 1, 1, 1, 3, onskey, status)  
C write null value 
      call ftpclu(iunit, 1, 4, 1, 1, status)  

      do ii = 2,5 
C loop over cols 2 - 5       
          call ftpclb(iunit, ii, 1, 1, 2, boutarray, status)  
C char array 
          if (status .eq. 412) status = 0
             
          call ftpcli(iunit, ii, 3, 1, 2, ioutarray(3), status)  
C short array 
          if (status .eq. 412) status = 0
             
          call ftpclj(iunit, ii, 5, 1, 2, joutarray(5), status)  
C long array 
          if (status .eq. 412)status = 0
              
          call ftpcle(iunit, ii, 7, 1, 2, eoutarray(7), status)  
C float array 
          if (status .eq. 412) status = 0
             
          call ftpcld(iunit, ii, 9, 1, 2, doutarray(9), status)  
C double array 
          if (status .eq. 412) status = 0

          call ftpclu(iunit, ii, 11, 1, 1, status)  
C write null value 
      end do
      write(*,'(1x,A,I4)') 'ftpcl_ status = ', status
      write(*,'(1x,A)')' '

C        ################################
C        #  read data from ASCII table  #
C        ################################
      
      call ftghtb(iunit, 99, rowlen, nrows, tfields, ttype, tbcol, 
     &       tform, tunit, tblname, status)

      write(*,'(1x,A,3I3,2A)')
     & 'ASCII table: rowlen, nrows, tfields, extname:',
     & rowlen, nrows, tfields,' ',tblname

      do ii = 1,tfields
        write(*,'(1x,A,I4,3A)') 
     & ttype(ii)(1:7), tbcol(ii),' ',tform(ii)(1:7), tunit(ii)(1:7)
      end do

      nrows = 11
      call ftgcvs(iunit, 1, 1, 1, nrows, 'UNDEFINED', inskey,
     &   anynull, status)
      bnul = char(99)
      call ftgcvb(iunit, 2, 1, 1, nrows, bnul, binarray,
     & anynull, status)
      inul = 99
      call ftgcvi(iunit, 2, 1, 1, nrows, inul, iinarray,
     & anynull, status)
      call ftgcvj(iunit, 3, 1, 1, nrows, 99, jinarray,
     & anynull, status)
      call ftgcve(iunit, 4, 1, 1, nrows, 99., einarray,
     & anynull, status)
      dnul = 99.
      call ftgcvd(iunit, 5, 1, 1, nrows, dnul, dinarray,
     & anynull, status)

      write(*,'(1x,A)')' '
      write(*,'(1x,A)') 'Data values read from ASCII table: '
      do ii = 1, nrows
        jj = ichar(binarray(ii))
        write(*,1011) inskey(ii), jj,
     &   iinarray(ii), jinarray(ii), einarray(ii), dinarray(ii)
1011    format(1x,a15,3i3,1x,2f3.0)
      end do

      call ftgtbs(iunit, 1, 20, 78, uchars, status)
      write(*,'(1x,A)')' '
      write(*,'(1x,A)') uchars
      call ftptbs(iunit, 1, 20, 78, uchars, status)
      
C        #########################################
C        #  get information about the columns    #
C        #########################################

      call ftgcno(iunit, 0, 'name', colnum, status)
      write(*,'(1x,A)')' '
      write(*,'(1x,A,I4,A,I4)')
     &  'Column name is number',colnum,' status = ', status

2190  continue
      if (status .ne. 219)then
        if (status .gt. 0 .and. status .ne. 237)go to 999

        call ftgcnn(iunit, 1, '*ue', colname, colnum, status)
        write(*,'(1x,3A,I4,A,I4)')
     & 'Column ',colname(1:6),' is number',colnum,' status = ',status
        go to 2190
      end if
   
      status = 0

      do ii = 1, tfields       
        call ftgtcl(iunit, ii, typecode, repeat, width, status)
        call ftgacl(iunit, ii, ttype, tbcol,tunit,tform, 
     &   scale,zero, nulstr, tdisp, status)

        write(*,'(1x,A,3I4,2A,I4,2A,2F10.2,3A)')
     & tform(ii)(1:7), typecode, repeat, width,' ',
     &  ttype(1)(1:6), tbcol(1), ' ',tunit(1)(1:5),
     &  scale, zero, ' ', nulstr(1:6), tdisp(1:2)

      end do

      write(*,'(1x,A)') ' '

C        ###############################################
C        #  test the insert/delete row/column routines #
C        ###############################################
      
      call ftirow(iunit, 2, 3, status)
      if (status .gt. 0) goto 999

      nrows = 14
      call ftgcvs(iunit, 1, 1, 1, nrows, 'UNDEFINED',
     & inskey,   anynull, status)
      call ftgcvb(iunit, 2, 1, 1, nrows, bnul, binarray,
     & anynull, status)
      call ftgcvi(iunit, 2, 1, 1, nrows, inul, iinarray,
     & anynull, status)
      call ftgcvj(iunit, 3, 1, 1, nrows, 99, jinarray,
     & anynull, status)
      call ftgcve(iunit, 4, 1, 1, nrows, 99., einarray,
     & anynull, status)
      call ftgcvd(iunit, 5, 1, 1, nrows, dnul, dinarray,
     & anynull, status)

      write(*,'(1x,A)')' '
      write(*,'(1x,A)')'Data values after inserting 3 rows after row 2:'
      do ii = 1, nrows     
        jj = ichar(binarray(ii))
        write(*,1011) inskey(ii), jj,
     &   iinarray(ii), jinarray(ii), einarray(ii), dinarray(ii)
      end do

      call ftdrow(iunit, 10, 2, status)

      nrows = 12
      call ftgcvs(iunit, 1, 1, 1, nrows, 'UNDEFINED', inskey,  
     & anynull, status)
      call ftgcvb(iunit, 2, 1, 1, nrows, bnul, binarray, anynull,
     & status)
      call ftgcvi(iunit, 2, 1, 1, nrows, inul, iinarray, anynull,
     & status)
      call ftgcvj(iunit, 3, 1, 1, nrows, 99, jinarray, anynull,
     & status)
      call ftgcve(iunit, 4, 1, 1, nrows, 99., einarray, anynull,
     & status)
      call ftgcvd(iunit, 5, 1, 1, nrows, dnul, dinarray, anynull,
     & status)

      write(*,'(1x,A)')' '
      write(*,'(1x,A)') 'Data values after deleting 2 rows at row 10: '
      do ii = 1, nrows    
        jj = ichar(binarray(ii))
        write(*,1011)  inskey(ii), jj,
     &       iinarray(ii), jinarray(ii), einarray(ii), dinarray(ii)
      end do
      call ftdcol(iunit, 3, status)

      call ftgcvs(iunit, 1, 1, 1, nrows, 'UNDEFINED', inskey, 
     &  anynull, status)
      call ftgcvb(iunit, 2, 1, 1, nrows, bnul, binarray, anynull,
     & status)
      call ftgcvi(iunit, 2, 1, 1, nrows, inul, iinarray, anynull,
     & status)
      call ftgcve(iunit, 3, 1, 1, nrows, 99., einarray, anynull,
     & status)
      call ftgcvd(iunit, 4, 1, 1, nrows, dnul, dinarray, anynull,
     & status)

      write(*,'(1x,A)')' '
      write(*,'(1x,A)') 'Data values after deleting column 3: '
      do ii = 1,nrows
        jj = ichar(binarray(ii))
        write(*,1012) inskey(ii), jj,
     &       iinarray(ii), einarray(ii), dinarray(ii)
1012    format(1x,a15,2i3,1x,2f3.0)

      end do

      call fticol(iunit, 5, 'INSERT_COL', 'F14.6', status)

      call ftgcvs(iunit, 1, 1, 1, nrows, 'UNDEFINED', inskey,
     &   anynull, status)
      call ftgcvb(iunit, 2, 1, 1, nrows, bnul, binarray, anynull,
     & status)
      call ftgcvi(iunit, 2, 1, 1, nrows, inul, iinarray, anynull,
     & status)
      call ftgcve(iunit, 3, 1, 1, nrows, 99., einarray, anynull,
     & status)
      call ftgcvd(iunit, 4, 1, 1, nrows, dnul, dinarray, anynull,
     & status)
      call ftgcvj(iunit, 5, 1, 1, nrows, 99, jinarray, anynull,
     & status)

      write(*,'(1x,A)')' '
      write(*,'(1x,A)') ' Data values after inserting column 5: '
      do ii = 1, nrows
        jj = ichar(binarray(ii))
        write(*,1013) inskey(ii), jj,
     &       iinarray(ii), einarray(ii), dinarray(ii) , jinarray(ii)
1013    format(1x,a15,2i3,1x,2f3.0,i2)

      end do

C        ################################
C        #  read data from binary table #
C        ################################
      

      call ftmrhd(iunit, 1, hdutype, status)
      if (status .gt. 0)go to 999
      call ftghdn(iunit, hdunum)
      write(*,'(1x,A,I4)') 'HDU number = ', hdunum

      call ftghsp(iunit, existkeys, morekeys, status)
      write(*,'(1x,A)')' '
      write(*,'(1x,A)')'Moved to binary table'
      write(*,'(1x,A,I4,A,I4,A)') 'header contains ',existkeys,
     & ' keywords with room for ',morekeys,' more '

      call ftghbn(iunit, 99, nrows, tfields, ttype, 
     &        tform, tunit, binname, pcount, status)

      write(*,'(1x,A)')' '
      write(*,'(1x,A,2I4,A,I4)') 
     & 'Binary table: nrows, tfields, extname, pcount:',
     &        nrows, tfields, binname, pcount

      do ii = 1,tfields
        write(*,'(1x,3A)') ttype(ii), tform(ii), tunit(ii)
      end do

      do ii = 1, 40
          larray(ii) = .false.
      end do

      write(*,'(1x,A)')' '
      write(*,'(1x,A)') 'Data values read from binary table: '
      write(*,'(1x,A)') ' Bit column (X) data values:   '

      call ftgcx(iunit, 3, 1, 1, 36, larray, status)
      write(*,1014) (larray(ii), ii = 1,40)
1014  format(1x,8l1,' ',8l1,' ',8l1,' ',8l1,' ',8l1)

      nrows = 21
      do ii = 1, nrows
        larray(ii) = .false.
        xinarray(ii) = ' '
        binarray(ii) = ' '
        iinarray(ii) = 0 
        kinarray(ii) = 0
        einarray(ii) = 0. 
        dinarray(ii) = 0.
        cinarray(ii * 2 -1) = 0. 
        minarray(ii * 2 -1) = 0.
        cinarray(ii * 2 ) = 0. 
        minarray(ii * 2 ) = 0.
      end do      

      write(*,'(1x,A)') '  '
      call ftgcvs(iunit, 1, 4, 1, 1, ' ',  inskey,   anynull,status)
      if (ichar(inskey(1)(1:1)) .eq. 0)inskey(1)=' '
      write(*,'(1x,2A)') 'null string column value (should be blank):',
     &        inskey(1)

      call ftgcvs(iunit, 1, 1, 1, nrows, 'NOT DEFINED',  inskey,
     &   anynull, status)
      call ftgcl( iunit, 2, 1, 1, nrows, larray, status)
      bnul = char(98)
      call ftgcvb(iunit, 3, 1, 1,nrows,bnul, xinarray,anynull,status)
      call ftgcvb(iunit, 4, 1, 1,nrows,bnul, binarray,anynull,status)
      inul = 98
      call ftgcvi(iunit, 5, 1, 1,nrows,inul, iinarray,anynull,status)
      call ftgcvj(iunit, 6, 1, 1, nrows, 98, kinarray,anynull,status)
      call ftgcve(iunit, 7, 1, 1, nrows, 98.,einarray,anynull,status)
      dnul = 98.
      call ftgcvd(iunit, 8, 1, 1, nrows,dnul,dinarray,anynull,status)
      call ftgcvc(iunit, 9, 1, 1, nrows, 98.,cinarray,anynull,status)
      call ftgcvm(iunit,10, 1, 1, nrows,dnul,minarray,anynull,status)

      write(*,'(1x,A)')' '
      write(*,'(1x,A)') 'Read columns with ftgcv_: '
      do ii = 1,nrows
        jj = ichar(xinarray(ii))
        jjj = ichar(binarray(ii))
      write(*,1201)inskey(ii),larray(ii),jj,jjj,iinarray(ii),
     & kinarray(ii), einarray(ii), dinarray(ii), cinarray(ii * 2 -1), 
     &cinarray(ii * 2 ), minarray(ii * 2 -1), minarray(ii * 2 )
      end do
1201  format(1x,a14,l4,4i4,6f5.0)

      do ii = 1, nrows
        larray(ii) = .false.
        xinarray(ii) = ' '
        binarray(ii) = ' '
        iinarray(ii) = 0 
        kinarray(ii) = 0
        einarray(ii) = 0. 
        dinarray(ii) = 0.
        cinarray(ii * 2 -1) = 0. 
        minarray(ii * 2 -1) = 0.
        cinarray(ii * 2 ) = 0. 
        minarray(ii * 2 ) = 0.
      end do      

      call ftgcfs(iunit, 1, 1, 1, nrows, inskey,   larray2, anynull,
     & status)
C     put blanks in strings if they are undefined.  (contain nulls)
      do ii = 1, nrows
         if (larray2(ii))inskey(ii) = ' '
      end do

      call ftgcfl(iunit, 2, 1, 1, nrows, larray,   larray2, anynull,
     & status)
      call ftgcfb(iunit, 3, 1, 1, nrows, xinarray, larray2, anynull,
     & status)
      call ftgcfb(iunit, 4, 1, 1, nrows, binarray, larray2, anynull,
     & status)
      call ftgcfi(iunit, 5, 1, 1, nrows, iinarray, larray2, anynull,
     & status)
      call ftgcfj(iunit, 6, 1, 1, nrows, kinarray, larray2, anynull,
     & status)
      call ftgcfe(iunit, 7, 1, 1, nrows, einarray, larray2, anynull,
     & status)
      call ftgcfd(iunit, 8, 1, 1, nrows, dinarray, larray2, anynull,
     & status)
      call ftgcfc(iunit, 9, 1, 1, nrows, cinarray, larray2, anynull,
     & status)
      call ftgcfm(iunit, 10,1, 1, nrows, minarray, larray2, anynull,
     & status)

      write(*,'(1x,A)')' '
      write(*,'(1x,A)') ' Read columns with ftgcf_: '
      do ii = 1, 10
        jj = ichar(xinarray(ii))
        jjj = ichar(binarray(ii))
      write(*,1201)
     & inskey(ii),larray(ii),jj,jjj,iinarray(ii),
     & kinarray(ii), einarray(ii), dinarray(ii), cinarray(ii * 2 -1), 
     & cinarray(ii * 2 ), minarray(ii * 2 -1), minarray(ii * 2)
      end do

      do ii = 11, 21
C don't try to print the NaN values 
        jj = ichar(xinarray(ii))
        jjj = ichar(binarray(ii))
        write(*,1201) inskey(ii), larray(ii), jj,
     &    jjj, iinarray(ii)
      end do
      
      call ftprec(iunit,'key_prec= '// 
     &'''This keyword was written by f_prec'' / comment here',
     & status)

C        ###############################################
C        #  test the insert/delete row/column routines #
C        ###############################################
      
      call ftirow(iunit, 2, 3, status)
         if (status .gt. 0) go to 999

      nrows = 14
      call ftgcvs(iunit, 1, 1, 1, nrows, 'NOT DEFINED',  inskey,
     & anynull, status)
      call ftgcvb(iunit, 4, 1, 1, nrows,bnul,binarray,anynull,status)
      call ftgcvi(iunit, 5, 1, 1, nrows,inul,iinarray,anynull,status)
      call ftgcvj(iunit, 6, 1, 1, nrows, 98, jinarray,anynull,status)
      call ftgcve(iunit, 7, 1, 1, nrows, 98.,einarray,anynull,status)
      call ftgcvd(iunit, 8, 1, 1, nrows,dnul,dinarray,anynull,status)

      write(*,'(1x,A)')' '
      write(*,'(1x,A)')'Data values after inserting 3 rows after row 2:'
      do ii = 1, nrows
        jj = ichar(binarray(ii))
        write(*,1202)  inskey(ii), jj,
     &      iinarray(ii), jinarray(ii), einarray(ii), dinarray(ii)
      end do      
1202  format(1x,a14,3i4,2f5.0)

      call ftdrow(iunit, 10, 2, status)
          if (status .gt. 0)goto 999

      nrows = 12
      call ftgcvs(iunit, 1, 1, 1, nrows, 'NOT DEFINED',  inskey,
     &   anynull, status)
      call ftgcvb(iunit, 4, 1, 1, nrows,bnul,binarray,anynull,status)
      call ftgcvi(iunit, 5, 1, 1, nrows,inul,iinarray,anynull,status)
      call ftgcvj(iunit, 6, 1, 1, nrows, 98,jinarray,anynull,status)
      call ftgcve(iunit, 7, 1, 1, nrows, 98.,einarray,anynull,status)
      call ftgcvd(iunit, 8, 1, 1, nrows,dnul,dinarray,anynull,status)

      write(*,'(1x,A)')' '
      write(*,'(1x,A)') 'Data values after deleting 2 rows at row 10: '
      do ii = 1, nrows
        jj = ichar(binarray(ii))
        write(*,1202) inskey(ii), jj,
     &       iinarray(ii), jinarray(ii), einarray(ii), dinarray(ii)
      end do

      call ftdcol(iunit, 6, status)

      call ftgcvs(iunit, 1, 1, 1, nrows, 'NOT DEFINED',  inskey,
     &   anynull, status)
      call ftgcvb(iunit, 4, 1, 1, nrows,bnul,binarray,anynull,status)
      call ftgcvi(iunit, 5, 1, 1, nrows,inul,iinarray,anynull,status)
      call ftgcve(iunit, 6, 1, 1, nrows, 98.,einarray,anynull,status)
      call ftgcvd(iunit, 7, 1, 1, nrows,dnul,dinarray,anynull,status)

      write(*,'(1x,A)')' '
      write(*,'(1x,A)') 'Data values after deleting column 6: '
      do ii = 1, nrows
        jj = ichar(binarray(ii))      
        write(*,1203) inskey(ii), jj,
     &       iinarray(ii), einarray(ii), dinarray(ii)
1203  format(1x,a14,2i4,2f5.0)

      end do
      call fticol(iunit, 8, 'INSERT_COL', '1E', status)

      call ftgcvs(iunit, 1, 1, 1, nrows, 'NOT DEFINED',  inskey,
     &   anynull, status)
      call ftgcvb(iunit, 4, 1, 1, nrows,bnul,binarray,anynull,status)
      call ftgcvi(iunit, 5, 1, 1, nrows,inul,iinarray,anynull,status)
      call ftgcve(iunit, 6, 1, 1, nrows, 98.,einarray,anynull,status)
      call ftgcvd(iunit, 7, 1, 1, nrows,dnul,dinarray,anynull,status)
      call ftgcvj(iunit, 8, 1, 1, nrows, 98,jinarray,anynull,status)

      write(*,'(1x,A)')' '
      write(*,'(1x,A)') 'Data values after inserting column 8: '
      do ii = 1, nrows
        jj = ichar(binarray(ii))
        write(*,1204) inskey(ii), jj,
     &    iinarray(ii), einarray(ii), dinarray(ii) , jinarray(ii)
1204  format(1x,a14,2i4,2f5.0,i3)
      end do
      call ftpclu(iunit, 8, 1, 1, 10, status)

      call ftgcvs(iunit, 1, 1, 1, nrows, 'NOT DEFINED',  inskey,
     &   anynull, status)
      call ftgcvb(iunit, 4,1,1,nrows,bnul,binarray,anynull,status)
      call ftgcvi(iunit, 5,1,1,nrows,inul,iinarray,anynull,status)
      call ftgcve(iunit, 6,1,1,nrows,98., einarray,anynull,status)
      call ftgcvd(iunit, 7,1,1,nrows,dnul, dinarray,anynull,status)
      call ftgcvj(iunit, 8,1,1,nrows,98, jinarray,anynull, status)

      write(*,'(1x,A)')' '
      write(*,'(1x,A)') 
     &  'Values after setting 1st 10 elements in column 8 = null: '
      do ii = 1, nrows
        jj = ichar(binarray(ii))
        write(*,1204) inskey(ii), jj,
     &      iinarray(ii), einarray(ii), dinarray(ii) , jinarray(ii)
      end do      

C        ####################################################
C        #  insert binary table following the primary array #
C        ####################################################
   
      call ftmahd(iunit,  1, hdutype, status)

      tform(1) = '15A'
      tform(2) = '1L'
      tform(3) = '16X'
      tform(4) = '1B'
      tform(5) = '1I'
      tform(6) = '1J'
      tform(7) = '1E'
      tform(8) = '1D'
      tform(9) = '1C'
      tform(10)= '1M'

      ttype(1) = 'Avalue'
      ttype(2) = 'Lvalue'
      ttype(3) = 'Xvalue'
      ttype(4) = 'Bvalue'
      ttype(5) = 'Ivalue'
      ttype(6) = 'Jvalue'
      ttype(7) = 'Evalue'
      ttype(8) = 'Dvalue'
      ttype(9) = 'Cvalue'
      ttype(10)= 'Mvalue'

      tunit(1)= ' '
      tunit(2)= 'm**2'
      tunit(3)= 'cm'
      tunit(4)= 'erg/s'
      tunit(5)= 'km/s'
      tunit(6)= ' '
      tunit(7)= ' '
      tunit(8)= ' '
      tunit(9)= ' '
      tunit(10)= ' '

      nrows = 20
      tfields = 10
      pcount = 0

      call ftibin(iunit, nrows, tfields, ttype, tform, tunit, 
     & binname, pcount, status)
      write(*,'(1x,A)')' '
      write(*,'(1x,A,I4)') 'ftibin status = ', status
      call ftghdn(iunit, hdunum)
      write(*,'(1x,A,I4)') 'HDU number = ', hdunum

      call ftpkyj(iunit, 'TNULL4', 77, 
     & 'value for undefined pixels', status)
      call ftpkyj(iunit, 'TNULL5', 77, 
     & 'value for undefined pixels', status)
      call ftpkyj(iunit, 'TNULL6', 77, 
     & 'value for undefined pixels', status)

      call ftpkyj(iunit, 'TSCAL4', 1000, 'scaling factor', status)
      call ftpkyj(iunit, 'TSCAL5', 1, 'scaling factor', status)
      call ftpkyj(iunit, 'TSCAL6', 100, 'scaling factor', status)

      call ftpkyj(iunit, 'TZERO4', 0, 'scaling offset', status)
      call ftpkyj(iunit, 'TZERO5', 32768, 'scaling offset', status)
      call ftpkyj(iunit, 'TZERO6', 100, 'scaling offset', status)

      call fttnul(iunit, 4, 77, status)   
C define null value for int cols 
      call fttnul(iunit, 5, 77, status)
      call fttnul(iunit, 6, 77, status)
      
C set scaling 
      scale=1000.
      zero = 0.
      call fttscl(iunit, 4, scale, zero, status)   
      scale=1.
      zero = 32768.
      call fttscl(iunit, 5, scale, zero, status)
      scale=100.
      zero = 100.
      call fttscl(iunit, 6, scale, zero, status)

C  for some reason, it is still necessary to call ftrdef at this point
      call ftrdef(iunit,status)

C        ############################
C        #  write data to columns   #
C        ############################
           
C initialize arrays of values to write to table 
 
      joutarray(1) = 0
      joutarray(2) = 1000
      joutarray(3) = 10000
      joutarray(4) = 32768
      joutarray(5) = 65535


      do ii = 4,6
      
          call ftpclj(iunit, ii, 1, 1, 5, joutarray, status) 
          if (status .eq. 412)then
              write(*,'(1x,A,I4)') 'Overflow writing to column  ', ii
              status = 0
          end if

          call ftpclu(iunit, ii, 6, 1, 1, status)  
C write null value 
      end do

      do jj = 4,6  
        call ftgcvj(iunit, jj, 1,1,6, -999,jinarray,anynull,status)
        write(*,'(1x,6I6)') (jinarray(ii), ii=1,6)
      end do

      write(*,'(1x,A)') ' '
      
C turn off scaling, and read the unscaled values 
      scale = 1.
      zero = 0.
      call fttscl(iunit, 4, scale, zero, status)   
      call fttscl(iunit, 5, scale, zero, status)
      call fttscl(iunit, 6, scale, zero, status)

      do jj = 4,6
        call ftgcvj(iunit, jj,1,1,6,-999,jinarray,anynull,status)       
            write(*,'(1x,6I6)') (jinarray(ii), ii = 1,6)
      end do

      if (status .gt. 0)go to 999

C        ######################################################
C        #  insert image extension following the binary table #
C        ######################################################
      
      bitpix = -32
      naxis = 2
      naxes(1) = 15
      naxes(2) = 25
      call ftiimg(iunit, bitpix, naxis, naxes, status)
      write(*,'(1x,A)')' '
      write(*,'(1x,A,I4)') 
     & ' Create image extension: ftiimg status = ', status
      call ftghdn(iunit, hdunum)
      write(*,'(1x,A,I4)') 'HDU number = ', hdunum

      do jj = 0,29
        do ii = 0,18
          imgarray(ii+1,jj+1) = (jj * 10) + ii
        end do
      end do

      call ftp2di(iunit, 1, 19, naxes(1),naxes(2),imgarray,status)
      write(*,'(1x,A)') ' '
      write(*,'(1x,A,I4)')'Wrote whole 2D array: ftp2di status =',
     &      status

      do jj =1, 30
        do ii = 1, 19
          imgarray(ii,jj) = 0
        end do        
      end do
      
      call ftg2di(iunit,1,0,19,naxes(1),naxes(2),imgarray,anynull,
     &       status)
      write(*,'(1x,A)')' '
      write(*,'(1x,A,I4)')'Read whole 2D array: ftg2di status =',status

      do jj =1, 30
        write (*,1301)(imgarray(ii,jj),ii=1,19)
1301    format(1x,19I4)
      end do

        write(*,'(1x,A)') ' '
      

      do jj =1, 30
        do ii = 1, 19
          imgarray(ii,jj) = 0
        end do        
      end do
      
      do jj =0, 19
        do ii = 0, 9
          imgarray2(ii+1,jj+1) = (jj * (-10)) - ii
        end do        
      end do

      fpixels(1) = 5
      fpixels(2) = 5
      lpixels(1) = 14
      lpixels(2) = 14
      call ftpssi(iunit, 1, naxis, naxes, fpixels, lpixels, 
     &     imgarray2, status)
      write(*,'(1x,A)')' '
      write(*,'(1x,A,I4)')'Wrote subset 2D array: ftpssi status =',
     & status

      call ftg2di(iunit,1,0,19,naxes(1), naxes(2),imgarray,anynull,
     &        status)
      write(*,'(1x,A)')' '
      write(*,'(1x,A,I4)')'Read whole 2D array: ftg2di status =',status

      do jj =1, 30
        write (*,1301)(imgarray(ii,jj),ii=1,19)
      end do
      write(*,'(1x,A)') ' '


      fpixels(1) = 2
      fpixels(2) = 5
      lpixels(1) = 10
      lpixels(2) = 8
      inc(1) = 2
      inc(2) = 3

      do jj = 1,30    
        do ii = 1, 19
          imgarray(ii,jj) = 0
        end do
      end do
      
      call ftgsvi(iunit, 1, naxis, naxes, fpixels, lpixels, inc, 0,
     &       imgarray, anynull, status)
      write(*,'(1x,A)')' '
      write(*,'(1x,A,I4)')
     & 'Read subset of 2D array: ftgsvi status = ',status

      write(*,'(1x,10I5)')(imgarray(ii,1),ii = 1,10)

      
C        ###########################################################
C        #  insert another image extension                         #
C        #  copy the image extension to primary array of tmp file. #
C        #  then delete the tmp file, and the image extension      #
C        ###########################################################
      
      bitpix = 16
      naxis = 2
      naxes(1) = 15
      naxes(2) = 25
      call ftiimg(iunit, bitpix, naxis, naxes, status)
      write(*,'(1x,A)') ' '
      write(*,'(1x,A,I4)')'Create image extension: ftiimg status =',
     &   status
      call ftrdef(iunit, status)
      call ftghdn(iunit, hdunum)
      write(*,'(1x,A,I4)') 'HDU number = ', hdunum


      filename = 't1q2s3v4.tmp'
      call ftinit(tmpunit, filename, 1, status)
      write(*,'(1x,A,I4)')'Create temporary file: ftinit status = ',
     & status

      call ftcopy(iunit, tmpunit, 0, status)
      write(*,'(1x,A)') 
     &  'Copy image extension to primary array of tmp file.'
      write(*,'(1x,A,I4)')'ftcopy status = ',status


      call ftgrec(tmpunit, 1, card, status)
      write(*,'(1x,A)')  card
      call ftgrec(tmpunit, 2, card, status)
      write(*,'(1x,A)')  card
      call ftgrec(tmpunit, 3, card, status)
      write(*,'(1x,A)')  card
      call ftgrec(tmpunit, 4, card, status)
      write(*,'(1x,A)')  card
      call ftgrec(tmpunit, 5, card, status)
      write(*,'(1x,A)')  card
      call ftgrec(tmpunit, 6, card, status)
      write(*,'(1x,A)')  card

      call ftdelt(tmpunit, status)
      write(*,'(1x,A,I4)')'Delete the tmp file: ftdelt status =',status
      call ftdhdu(iunit, hdutype, status)
      write(*,'(1x,A,2I4)')
     &  'Delete the image extension hdutype, status =',
     &         hdutype, status
      call ftghdn(iunit, hdunum)
      write(*,'(1x,A,I4)') 'HDU number = ', hdunum

      
C        ###########################################################
C        #  append bintable extension with variable length columns #
C        ###########################################################
      
      call ftcrhd(iunit, status)
      write(*,'(1x,A,I4)') 'ftcrhd status = ', status

      tform(1)= '1PA'
      tform(2)= '1PL'
      tform(3)= '1PB' 
C Fortran FITSIO doesn't support  1PX 
      tform(4)= '1PB'
      tform(5)= '1PI'
      tform(6)= '1PJ'
      tform(7)= '1PE'
      tform(8)= '1PD'
      tform(9)= '1PC'
      tform(10)= '1PM'

      ttype(1)= 'Avalue'
      ttype(2)= 'Lvalue'
      ttype(3)= 'Xvalue'
      ttype(4)= 'Bvalue'
      ttype(5)= 'Ivalue'
      ttype(6)= 'Jvalue'
      ttype(7)= 'Evalue'
      ttype(8)= 'Dvalue'
      ttype(9)= 'Cvalue'
      ttype(10)= 'Mvalue'

      tunit(1)= ' '
      tunit(2)= 'm**2'
      tunit(3)= 'cm'
      tunit(4)= 'erg/s'
      tunit(5)= 'km/s'
      tunit(6)= ' '
      tunit(7)= ' '
      tunit(8)= ' '
      tunit(9)= ' '
      tunit(10)= ' '

      nrows = 20
      tfields = 10
      pcount = 0

      call ftphbn(iunit, nrows, tfields, ttype, tform, 
     & tunit, binname, pcount, status)
      write(*,'(1x,A,I4)')'Variable length arrays: ftphbn status =',
     & status
      call ftpkyj(iunit, 'TNULL4', 88, 'value for undefined pixels',
     & status)
      call ftpkyj(iunit, 'TNULL5', 88, 'value for undefined pixels',
     & status)
      call ftpkyj(iunit, 'TNULL6', 88, 'value for undefined pixels',
     & status)

C        ############################
C        #  write data to columns   #
C        ############################
            
C initialize arrays of values to write to table 
      iskey='abcdefghijklmnopqrst'

      do ii = 1, 20
      
          boutarray(ii) = char(ii)
          ioutarray(ii) = ii
          joutarray(ii) = ii
          eoutarray(ii) = ii
          doutarray(ii) = ii
      end do

      larray(1) = .false.
      larray(2) = .true.
      larray(3) = .false.
      larray(4) = .false.
      larray(5) = .true.
      larray(6) = .true.
      larray(7) = .false.
      larray(8) = .false.
      larray(9) = .false.
      larray(10) = .true.
      larray(11) = .true.
      larray(12) = .true.
      larray(13) = .false.
      larray(14) = .false.
      larray(15) = .false.
      larray(16) = .false.
      larray(17) = .true.
      larray(18) = .true.
      larray(19) = .true.
      larray(20) = .true.

C      inskey(1) = iskey(1:1)
      inskey(1) = ' '

        call ftpcls(iunit, 1, 1, 1, 1, inskey, status)  
C write string values 
        call ftpcll(iunit, 2, 1, 1, 1, larray, status)  
C write logicals 
        call ftpclx(iunit, 3, 1, 1, 1, larray, status)  
C write bits 
        call ftpclb(iunit, 4, 1, 1, 1, boutarray, status)
        call ftpcli(iunit, 5, 1, 1, 1, ioutarray, status) 
        call ftpclj(iunit, 6, 1, 1, 1, joutarray, status) 
        call ftpcle(iunit, 7, 1, 1, 1, eoutarray, status)
        call ftpcld(iunit, 8, 1, 1, 1, doutarray, status)

      do ii = 2, 20   
C loop over rows 1 - 20 
      
        inskey(1) =  iskey(1:ii)
        call ftpcls(iunit, 1, ii, 1, ii, inskey, status)  
C write string values 

        call ftpcll(iunit, 2, ii, 1, ii, larray, status)  
C write logicals 
        call ftpclu(iunit, 2, ii, ii-1, 1, status)

        call ftpclx(iunit, 3, ii, 1, ii, larray, status)  
C write bits 

        call ftpclb(iunit, 4, ii, 1, ii, boutarray, status)
        call ftpclu(iunit, 4, ii, ii-1, 1, status)

        call ftpcli(iunit, 5, ii, 1, ii, ioutarray, status) 
        call ftpclu(iunit, 5, ii, ii-1, 1, status)

        call ftpclj(iunit, 6, ii, 1, ii, joutarray, status) 
        call ftpclu(iunit, 6, ii, ii-1, 1, status)

        call ftpcle(iunit, 7, ii, 1, ii, eoutarray, status)
        call ftpclu(iunit, 7, ii, ii-1, 1, status)

        call ftpcld(iunit, 8, ii, 1, ii, doutarray, status)
        call ftpclu(iunit, 8, ii, ii-1, 1, status)
      end do

C     it is no longer necessary to update the PCOUNT keyword;
C     FITSIO now does this automatically when the HDU is closed.
C     call ftmkyj(iunit,'PCOUNT',4446, '&',status)
      write(*,'(1x,A,I4)') 'ftpcl_ status = ', status

C        #################################
C        #  close then reopen this HDU   #
C        #################################

       call ftmrhd(iunit, -1, hdutype, status)
       call ftmrhd(iunit,  1, hdutype, status)

C        #############################
C        #  read data from columns   #
C        #############################
      

      call ftgkyj(iunit, 'PCOUNT', pcount, comm, status)
      write(*,'(1x,A,I4)') 'PCOUNT = ', pcount
      
C initialize the variables to be read 
      inskey(1) =' '
      iskey = ' '

      do jj = 1, ii
          larray(jj) = .false.
          boutarray(jj) = char(0)
          ioutarray(jj) = 0
          joutarray(jj) = 0
          eoutarray(jj) = 0
          doutarray(jj) = 0
      end do      

      call ftghdn(iunit, hdunum)
      write(*,'(1x,A,I4)') 'HDU number = ', hdunum

      do ii = 1, 20   
C loop over rows 1 - 20 
      
        do jj = 1, ii
          larray(jj) = .false.
          boutarray(jj) = char(0)
          ioutarray(jj) = 0
          joutarray(jj) = 0
          eoutarray(jj) = 0
          doutarray(jj) = 0
        end do      

        call ftgcvs(iunit, 1, ii, 1,1,iskey,inskey,anynull,status)
        write(*,'(1x,2A,I4)') 'A  ', inskey(1), status

        call ftgcl( iunit, 2, ii, 1, ii, larray, status) 
        write(*,1400)'L',status,(larray(jj),jj=1,ii)
1400    format(1x,a1,i3,20l3)
1401    format(1x,a1,21i3)

        call ftgcx(iunit, 3, ii, 1, ii, larray, status)
        write(*,1400)'X',status,(larray(jj),jj=1,ii)

        bnul = char(99)
        call ftgcvb(iunit, 4, ii, 1,ii,bnul,boutarray,anynull,status)
        do jj = 1,ii
          jinarray(jj) = ichar(boutarray(jj))
        end do
        write(*,1401)'B',(jinarray(jj),jj=1,ii),status

        inul = 99
        call ftgcvi(iunit, 5, ii, 1,ii,inul,ioutarray,anynull,status)
        write(*,1401)'I',(ioutarray(jj),jj=1,ii),status

        call ftgcvj(iunit, 6, ii, 1, ii,99,joutarray,anynull,status)
        write(*,1401)'J',(joutarray(jj),jj=1,ii),status

        call ftgcve(iunit, 7, ii, 1,ii,99.,eoutarray,anynull,status)
        estatus=status
        write(*,1402)'E',(eoutarray(jj),jj=1,ii),estatus
1402    format(1x,a1,1x,21f3.0)

        dnul = 99.
        call ftgcvd(iunit, 8, ii,1,ii,dnul,doutarray,anynull,status)
        estatus=status
        write(*,1402)'D',(doutarray(jj),jj=1,ii),estatus

        call ftgdes(iunit, 8, ii, repeat, offset, status)
        write(*,'(1x,A,2I5)')'Column 8 repeat and offset =',
     &       repeat,offset
      end do

C        #####################################
C        #  create another image extension   #
C        #####################################
      

      bitpix = 32
      naxis = 2
      naxes(1) = 10
      naxes(2) = 2
      npixels = 20
 
      call ftiimg(iunit, bitpix, naxis, naxes, status)
      write(*,'(1x,A)')' '
      write(*,'(1x,A,I4)')'Create image extension: ftiimg status =',
     &       status
      
C initialize arrays of values to write to primary array 
      do ii = 1, npixels
          boutarray(ii) = char(ii * 2 -2)
          ioutarray(ii) = ii * 2 -2
          joutarray(ii) = ii * 2 -2
          koutarray(ii) = ii * 2 -2
          eoutarray(ii) = ii * 2 -2
          doutarray(ii) = ii * 2 -2
      end do      

C write a few pixels with each datatype 
      call ftpprb(iunit, 1, 1,  2, boutarray(1),  status)
      call ftppri(iunit, 1, 3,  2, ioutarray(3),  status)
      call ftpprj(iunit, 1, 5,  2, koutarray(5),  status)
      call ftppri(iunit, 1, 7,  2, ioutarray(7),  status)
      call ftpprj(iunit, 1, 9,  2, joutarray(9),  status)
      call ftppre(iunit, 1, 11, 2, eoutarray(11), status)
      call ftpprd(iunit, 1, 13, 2, doutarray(13), status)
      write(*,'(1x,A,I4)') 'ftppr status = ', status

      
C read back the pixels with each datatype 
      bnul = char(0)
      inul = 0
      knul = 0
      jnul = 0
      enul = 0.
      dnul = 0.

      call ftgpvb(iunit, 1,  1,  14, bnul, binarray, anynull, status)
      call ftgpvi(iunit, 1,  1,  14, inul, iinarray, anynull, status)
      call ftgpvj(iunit, 1,  1,  14, knul, kinarray, anynull, status)
      call ftgpvj(iunit, 1,  1,  14, jnul, jinarray, anynull, status)
      call ftgpve(iunit, 1,  1,  14, enul, einarray, anynull, status)
      call ftgpvd(iunit, 1,  1,  14, dnul, dinarray, anynull, status)

      write(*,'(1x,A)')' '
      write(*,'(1x,A)')
     &   'Image values written with ftppr and read with ftgpv:'
      npixels = 14
      do jj = 1,ii
          joutarray(jj) = ichar(binarray(jj))
      end do

      write(*,1501)(joutarray(ii),ii=1,npixels),anynull,'(byte)'
1501  format(1x,14i3,l3,1x,a)
      write(*,1501)(iinarray(ii),ii=1,npixels),anynull,'(short)'
      write(*,1501)(kinarray(ii),ii=1,npixels),anynull,'(int)'
      write(*,1501)(jinarray(ii),ii=1,npixels),anynull,'(long)'
      write(*,1502)(einarray(ii),ii=1,npixels),anynull,'(float)'
      write(*,1502)(dinarray(ii),ii=1,npixels),anynull,'(double)'
1502  format(2x,14f3.0,l2,1x,a)

C      ##########################################
C      #  test world coordinate system routines #
C      ##########################################

      xrval = 45.83D+00
      yrval =  63.57D+00
      xrpix =  256.D+00
      yrpix =  257.D+00
      xinc =   -.00277777D+00
      yinc =   .00277777D+00

C     write the WCS keywords 
C     use example values from the latest WCS document 
      call ftpkyd(iunit, 'CRVAL1', xrval, 10, 'comment', status)
      call ftpkyd(iunit, 'CRVAL2', yrval, 10, 'comment', status)
      call ftpkyd(iunit, 'CRPIX1', xrpix, 10, 'comment', status)
      call ftpkyd(iunit, 'CRPIX2', yrpix, 10, 'comment', status)
      call ftpkyd(iunit, 'CDELT1', xinc, 10, 'comment', status)
      call ftpkyd(iunit, 'CDELT2', yinc, 10, 'comment', status)
C     call ftpkyd(iunit, 'CROTA2', rot, 10, 'comment', status) 
      call ftpkys(iunit, 'CTYPE1', xctype, 'comment', status)
      call ftpkys(iunit, 'CTYPE2', yctype, 'comment', status)
      write(*,'(1x,A)')' '
      write(*,'(1x,A,I4)')'Wrote WCS keywords status =', status

C     reset value, to make sure they are reread correctly
      xrval =  0.D+00
      yrval =  0.D+00
      xrpix =  0.D+00
      yrpix =  0.D+00
      xinc =   0.D+00
      yinc =   0.D+00
      rot =    67.D+00

      call ftgics(iunit, xrval, yrval, xrpix,
     &      yrpix, xinc, yinc, rot, ctype, status)
      write(*,'(1x,A,I4)')'Read WCS keywords with ftgics status =',
     &  status

      xpix = 0.5D+00
      ypix = 0.5D+00

      call ftwldp(xpix,ypix,xrval,yrval,xrpix,yrpix,xinc,yinc,
     &     rot,ctype, xpos, ypos,status)

      write(*,'(1x,A,2f8.3)')'  CRVAL1, CRVAL2 =', xrval,yrval
      write(*,'(1x,A,2f8.3)')'  CRPIX1, CRPIX2 =', xrpix,yrpix
      write(*,'(1x,A,2f12.8)')'  CDELT1, CDELT2 =', xinc,yinc
      write(*,'(1x,A,f8.3,2A)')'  Rotation =',rot,' CTYPE =',ctype
      write(*,'(1x,A,I4)')'Calculated sky coord. with ftwldp status =',
     &   status
      write(*,6501)xpix,ypix,xpos,ypos
6501  format('  Pixels (',f10.6,f10.6,') --> (',f10.6,f10.6,') Sky')

      call ftxypx(xpos,ypos,xrval,yrval,xrpix,yrpix,xinc,yinc,
     &     rot,ctype, xpix, ypix,status)
      write(*,'(1x,A,I4)')
     & 'Calculated pixel coord. with ftxypx status =', status
      write(*,6502)xpos,ypos,xpix,ypix
6502  format('  Sky (',f10.6,f10.6,') --> (',f10.6,f10.6,') Pixels')

     
C        ######################################
C        #  append another ASCII table        #
C        ######################################
      

      tform(1)= 'A15'
      tform(2)= 'I11'
      tform(3)= 'F15.6'
      tform(4)= 'E13.5'
      tform(5)= 'D22.14'

      tbcol(1)= 1
      tbcol(2)= 17
      tbcol(3)= 29
      tbcol(4)= 45
      tbcol(5)= 59
      rowlen = 80

      ttype(1)= 'Name'
      ttype(2)= 'Ivalue'
      ttype(3)= 'Fvalue'
      ttype(4)= 'Evalue'
      ttype(5)= 'Dvalue'

      tunit(1)= ' '
      tunit(2)= 'm**2'
      tunit(3)= 'cm'
      tunit(4)= 'erg/s'
      tunit(5)= 'km/s'

      nrows = 11
      tfields = 5
      tblname = 'new_table'

      call ftitab(iunit, rowlen, nrows, tfields, ttype, tbcol, 
     & tform, tunit, tblname, status)
      write(*,'(1x,A)') ' '
      write(*,'(1x,A,I4)') 'ftitab status = ', status

      call ftpcls(iunit, 1, 1, 1, 3, onskey, status)  
C write string values 

C initialize arrays of values to write to primary array 
      
      do ii = 1,npixels
          boutarray(ii) = char(ii * 3 -3)
          ioutarray(ii) = ii * 3 -3
          joutarray(ii) = ii * 3 -3
          koutarray(ii) = ii * 3 -3
          eoutarray(ii) = ii * 3 -3
          doutarray(ii) = ii * 3 -3
      end do

      do ii = 2,5 
C loop over cols 2 - 5 
      
          call ftpclb(iunit,  ii, 1, 1, 2, boutarray,  status) 
          call ftpcli(iunit,  ii, 3, 1, 2,ioutarray(3),status)
          call ftpclj(iunit,  ii, 5, 1, 2,joutarray(5),status)
          call ftpcle(iunit,  ii, 7, 1, 2,eoutarray(7),status)
          call ftpcld(iunit,  ii, 9, 1, 2,doutarray(9),status)
      end do
      write(*,'(1x,A,I4)') 'ftpcl status = ', status
      
C read back the pixels with each datatype 
      call ftgcvb(iunit,   2, 1, 1, 10, bnul, binarray,anynull,
     & status)
      call ftgcvi(iunit,  2, 1, 1, 10, inul, iinarray,anynull,
     & status)
      call ftgcvj(iunit,    3, 1, 1, 10, knul, kinarray,anynull,
     & status)
      call ftgcvj(iunit,    3, 1, 1, 10, jnul, jinarray,anynull,
     & status)
      call ftgcve(iunit,   4, 1, 1, 10, enul, einarray,anynull,
     & status)
      call ftgcvd(iunit, 5, 1, 1, 10, dnul, dinarray,anynull,
     & status)

      write(*,'(1x,A)') 
     &'Column values written with ftpcl and read with ftgcl: '
      npixels = 10
      do ii = 1,npixels
         joutarray(ii) = ichar(binarray(ii))
      end do
      write(*,1601)(joutarray(ii),ii = 1, npixels),anynull,'(byte) '
      write(*,1601)(iinarray(ii),ii = 1, npixels),anynull,'(short) '
      write(*,1601)(kinarray(ii),ii = 1, npixels),anynull,'(int) '
      write(*,1601)(jinarray(ii),ii = 1, npixels),anynull,'(long) '
      write(*,1602)(einarray(ii),ii = 1, npixels),anynull,'(float) '
      write(*,1602)(dinarray(ii),ii = 1, npixels),anynull,'(double) '
1601  format(1x,10i3,l3,1x,a)
1602  format(2x,10f3.0,l2,1x,a)
      
C        ###########################################################
C        #  perform stress test by cycling thru all the extensions #
C        ###########################################################
      write(*,'(1x,A)')' '
      write(*,'(1x,A)')'Repeatedly move to the 1st 4 HDUs of the file: '

      do ii = 1,10
        call ftmahd(iunit,  1, hdutype, status)
        call ftghdn(iunit, hdunum)
        call ftmrhd(iunit,  1, hdutype, status)
        call ftghdn(iunit, hdunum)
        call ftmrhd(iunit,  1, hdutype, status)
        call ftghdn(iunit, hdunum)
        call ftmrhd(iunit,  1, hdutype, status)
        call ftghdn(iunit, hdunum)
        call ftmrhd(iunit, -1, hdutype, status)
        call ftghdn(iunit, hdunum)
        if (status .gt. 0) go to 999
      end do
      
      write(*,'(1x,A)') ' '

      checksum = 1234567890.D+00
      call ftesum(checksum, .false., asciisum)
      write(*,'(1x,A,F13.1,2A)')'Encode checksum: ',checksum,' -> ',
     &  asciisum
      checksum = 0
      call ftdsum(asciisum, 0, checksum)
      write(*,'(1x,3A,F13.1)') 'Decode checksum: ',asciisum,' -> ',
     & checksum

      call ftpcks(iunit, status)

C         don't print the CHECKSUM value because it is different every day
C         because the current date is in the comment field.

         call ftgcrd(iunit, 'CHECKSUM', card, status)
C         write(*,'(1x,A)') card

      call ftgcrd(iunit, 'DATASUM', card, status)
      write(*,'(1x,A)') card(1:22)

      call ftgcks(iunit, datsum, checksum, status)
      write(*,'(1x,A,F13.1,I4)') 'ftgcks data checksum, status = ',
     &         datsum, status

      call ftvcks(iunit, datastatus, hdustatus, status) 
      write(*,'(1x,A,3I4)')'ftvcks datastatus, hdustatus, status =  ',
     &          datastatus, hdustatus, status
 
      call ftprec(iunit,
     & 'new_key = ''written by fxprec'' / to change checksum',status)
      call ftucks(iunit, status)
      write(*,'(1x,A,I4)') 'ftupck status = ', status

      call ftgcrd(iunit, 'DATASUM', card, status)
      write(*,'(1x,A)') card(1:22)
      call ftvcks(iunit, datastatus, hdustatus, status) 
      write(*,'(1x,A,3I4)') 'ftvcks datastatus, hdustatus, status =  ',
     &          datastatus, hdustatus, status
 
C        delete the checksum keywords, so that the FITS file is always
C        the same, regardless of the date of when testprog is run.
      
      call ftdkey(iunit, 'CHECKSUM', status)
      call ftdkey(iunit, 'DATASUM',  status)


C        ############################
C        #  close file and quit     #
C        ############################
      

999   continue  
C jump here on error 

      call ftclos(iunit, status) 
      write(*,'(1x,A,I4)') 'ftclos status = ', status
      write(*,'(1x,A)')' '

      write(*,'(1x,A)')
     &  'Normally, there should be 8 error messages on the'
      write(*,'(1x,A)') 'stack all regarding ''numerical overflows'':'

      call ftgmsg(errmsg)
      nmsg = 0

998   continue
      if (errmsg .ne. ' ')then      
          write(*,'(1x,A)') errmsg
          nmsg = nmsg + 1
          call ftgmsg(errmsg)
          go to 998
      end if

      if (nmsg .ne. 8)write(*,'(1x,A)')
     & ' WARNING: Did not find the expected 8 error messages!'

      call ftgerr(status, errmsg)
      write(*,'(1x,A)')' '
      write(*,'(1x,A,I4,2A)') 'Status =', status,': ', errmsg(1:50)
      end
cfitsio/testf77.out0000644000225700000360000010122313246025103014033 0ustar  cagordonlhea FITSIO TESTPROG
  
 Try opening then closing a nonexistent file: 
   ftopen iunit, status (expect an error) =  15 104
   ftclos status =  104
  
 ftinit create new file status =    0
  
 test writing of long string keywords: 
 123456789012345678901234567890123456789012345678901234567890123456789012345   
 '12345678901234567890123456789012345678901234567890123456789012345678'        
 1234567890123456789012345678901234567890123456789012345678901234'6789012345   
 '1234567890123456789012345678901234567890123456789012345678901234''67'        
 1234567890123456789012345678901234567890123456789012345678901234''789012345   
 '1234567890123456789012345678901234567890123456789012345678901234'''''        
 1234567890123456789012345678901234567890123456789012345678901234567'9012345   
 '1234567890123456789012345678901234567890123456789012345678901234567'         
 Wrote all Keywords successfully 
 ftflus status =    0
  
 HDU number =    1
 Values read back from primary array (99 = null pixel)
 The 1st, and every 4th pixel should be undefined: 
  99  2  3 99  5  6  7 99  9 10 11 99 13 14 15 99 17 18 19 99  T (ftgpvb) 
  99  2  3 99  5  6  7 99  9 10 11 99 13 14 15 99 17 18 19 99  T (ftgpvi) 
  99  2  3 99  5  6  7 99  9 10 11 99 13 14 15 99 17 18 19 99  T (ftgpvj) 
  99. 2. 3.99. 5. 6. 7.99. 9.10.11.99.13.14.15.99.17.18.19.99. T (ftgpve) 
  99. 2. 3.99. 5. 6. 7.99. 9.10.11.99.13.14.15.99.17.18.19.99. T (ftgpvd) 
   0  2  3  0  5  6  7  0  9 10 11  0 13 14 15  0 17 18 19  0  T (ftgpfb)
   0  2  3  0  5  6  7  0  9 10 11  0 13 14 15  0 17 18 19  0  T (ftgpfi)
   0  2  3  0  5  6  7  0  9 10 11  0 13 14 15  0 17 18 19  0  T (ftgpfj)
   0. 2. 3. 0. 5. 6. 7. 0. 9.10.11. 0.13.14.15. 0.17.18.19. 0. T (ftgpfe)
   0. 2. 3. 0. 5. 6. 7. 0. 9.10.11. 0.13.14.15. 0.17.18.19. 0. T (ftgpfd)
  
 Closed then reopened the FITS file 10 times.
  
 HDU number =    1
 Read back keywords: 
 simple, bitpix, naxis, naxes =    T  32   2  10   2
   pcount, gcount, extend =    0   1   T
 KEY_PREC= 'This keyword was written by fxprec' / comment goes here            
 KEY_PREC 'This keyword was written by fxprec comment goes here   
 KEY_PREC= 'This keyword was written by fxprec' / comment goes here            
 KY_PKNS1 :'first string' :fxpkns comment  
 KEY_PKYS :value_string         :fxpkys comment     0
 KEY_PKYL :   T:fxpkyl comment     0
 KEY_PKYJ :  11:fxpkyj comment     0
 KEY_PKYE :    11.00000:fxpkyj comment     0
 KEY_PKYD :    11.00000:fxpkyj comment     0
 KEY_PKYS :value_string         :fxpkys comment     0
 KEY_PKYL :   T:fxpkyl comment     0
 KEY_PKYJ :  11:fxpkyj comment     0
 KEY_PKYE :    13.13131:fxpkye comment     0
 KEY_PKYD :    15.15152:fxpkyd comment     0
 KEY_PKYF :    12.12121:fxpkyf comment     0
 KEY_PKYE :    13.13131:fxpkye comment     0
 KEY_PKYG : 14.141414141414:fxpkyg comment     0
 KEY_PKYD : 15.151515151515:fxpkyd comment     0
 KEY_PKYT  :  12345678:0.12345678901235fxpkyt comment     0
 KEY_PKYJ :  11:[km/s/Mpc] fxpkyj comment                0
 keyword unit=km/s/Mpc          
 KEY_PKYJ :  11:fxpkyj comment                           0
 keyword unit=                  
 KEY_PKYJ :  11:[feet/second/second] fxpkyj comment      0
 keyword unit=feet/second/second
 KEY_PKLS long string value = This is a very long string value that is continued
  over more than one keyword.                                          
 header contains   61 keywords; located at keyword   23
 ftgkns: first string  second string               
 ftgknl:    T   F   T
 ftgknj:   11  12  13
 ftgkne:   13.13131  14.14141  15.15152
 ftgknd:   15.15152  16.16162  17.17172
  
 Before deleting the HISTORY and DATE keywords...
 COMMENT 
 HISTORY 
 DATE    
 KY_PKNS1
  
 After deleting the keywords... 
 COMMENT This keyword was written by fxpcom.                                   
 KY_PKNS1= 'first string'       / fxpkns comment                               
  
 After inserting the keywords... 
 COMMENT   continued over multiple keywords.  The HEASARC convention uses the &
 KY_IREC = 'This keyword inserted by fxirec'                                   
 KY_IKYS = 'insert_value_string' / ikys comment                                
 KY_IKYJ =                   49 / ikyj comment                                 
 KY_IKYL =                    T / ikyl comment                                 
 KY_IKYE =           1.2346E+01 / ikye comment                                 
 KY_IKYD = 1.23456789012346E+01 / ikyd comment                                 
 KY_IKYF =              12.3456 / ikyf comment                                 
 KY_IKYG =     12.3456789012346 / ikyg comment                                 
 COMMENT   character at the end of each substring which is then continued      
  
 After modifying the keywords... 
 COMMENT   This keyword was modified by fxmrec                                 
 KY_MREC = 'This keyword was modified by fxmcrd'                               
 NEWIKYS = 'modified_string'    / ikys comment                                 
 KY_IKYJ =                   50 / This is a modified comment                   
 KY_IKYL =                    F / ikyl comment                                 
 KY_IKYE =          -1.2346E+01 / ikye comment                                 
 KY_IKYD = -1.23456789012346E+01 / modified comment                            
 KY_IKYF =             -12.3456 / ikyf comment                                 
 KY_IKYG =    -12.3456789012346 / ikyg comment                                 
 COMMENT   character at the end of each substring which is then continued      
  
 After updating the keywords... 
 COMMENT   This keyword was modified by fxmrec                                 
 KY_UCRD = 'This keyword was updated by fxucrd'                                
 NEWIKYS = 'updated_string'     / ikys comment                                 
 KY_IKYJ =                   51 / This is a modified comment                   
 KY_IKYL =                    T / ikyl comment                                 
 KY_IKYE =          -1.3346E+01 / ikye comment                                 
 KY_IKYD = -1.33456789012346E+01 / modified comment                            
 KY_IKYF =             -13.3456 / ikyf comment                                 
 KY_IKYG =    -13.3456789012346 / ikyg comment                                 
 COMMENT   character at the end of each substring which is then continued      
  
 Keywords found using wildcard search (should be 9)...
 KEY_PKYS= 'value_string'       / fxpkys comment                               
 KEY_PKYL=                    T / fxpkyl comment                               
 KEY_PKYJ=                   11 / [feet/second/second] fxpkyj comment          
 KEY_PKYF=             12.12121 / fxpkyf comment                               
 KEY_PKYE=         1.313131E+01 / fxpkye comment                               
 KEY_PKYG=    14.14141414141414 / fxpkyg comment                               
 KEY_PKYD= 1.51515151515152E+01 / fxpkyd comment                               
 NEWIKYS = 'updated_string'     / ikys comment                                 
 KEY_PKYT= 12345678.1234567890123456 / fxpkyt comment                          
  
 ftibin status =    0
 HDU number =    2
 header contains   33 keywords located at keyword    1
 header contains   33 keywords with room for   74 more
 TDIM3 = (1,2,8)                 3   1   2   8
 ftpcl_ status =    0
  
 Find the column numbers a returned status value of 237 is
 expected and indicates that more than one column name matches
 the input column name template.  Status = 219 indicates that
 there was no matching column name.
 Column Xvalue is number   3 status =   0
 Column Avalue is number   1 status =  237
 Column Lvalue is number   2 status =  237
 Column Xvalue is number   3 status =  237
 Column Bvalue is number   4 status =  237
 Column Ivalue is number   5 status =  237
 Column Jvalue is number   6 status =  237
 Column Evalue is number   7 status =  237
 Column Dvalue is number   8 status =  237
 Column Cvalue is number   9 status =  237
 Column Mvalue is number  10 status =  237
 Column        is number   0 status =  219
  
 Information about each column: 
 15A  16  15  15 Avalue       A      1.00    0.00  1234554321        
 1L   14   1   1 Lvalue m**2  L      1.00    0.00  1234554321        
 16X   1  16   1 Xvalue cm    X      1.00    0.00  1234554321        
 1B   11   1   1 Bvalue erg/s B      1.00    0.00          99        
 1I   21   1   2 Ivalue km/s  I      1.00    0.00          99        
 1J   41   1   4 Jvalue       J      1.00    0.00          99        
 1E   42   1   4 Evalue       E      1.00    0.00  1234554321        
 1D   82   1   8 Dvalue       D      1.00    0.00  1234554321        
 1C   83   1   8 Cvalue       C      1.00    0.00  1234554321        
 1M  163   1  16 Mvalue       M      1.00    0.00  1234554321        
  
 ftitab status =    0
 HDU number =    2
 ftpcl_ status =    0
  
 ASCII table: rowlen, nrows, tfields, extname: 76 11  5 Test-ASCII     
 Name      1 A15           
 Ivalue   17 I10    m**2   
 Fvalue   28 F14.6  cm     
 Evalue   43 E12.5  erg/s  
 Dvalue   56 D21.14 km/s   
  
 Data values read from ASCII table: 
 first string     1  1  1  1. 1.
 second string    2  2  2  2. 2.
                  3  3  3  3. 3.
 UNDEFINED        4  4  4  4. 4.
                  5  5  5  5. 5.
                  6  6  6  6. 6.
                  7  7  7  7. 7.
                  8  8  8  8. 8.
                  9  9  9  9. 9.
                 10 10 10 10.10.
                 99 99 99 99.99.
  
       1       1.000000  1.00000E+00  1.00000000000000E+00second string        
  
 Column name is number   1 status =    0
 Column Ivalue is number   2 status =  237
 Column Fvalue is number   3 status =  237
 Column Evalue is number   4 status =  237
 Column Dvalue is number   5 status =  237
 Column        is number   0 status =  219
 A15      16   1  15 Name     1            1.00      0.00 null1   
 I10      41   1  10 Ivalue  17 m**2       1.00      0.00 null2   
 F14.6    82   1  14 Fvalue  28 cm         1.00      0.00 null3   
 E12.5    42   1  12 Evalue  43 erg/s      1.00      0.00 null4   
 D21.14   82   1  21 Dvalue  56 km/s       1.00      0.00 null5   
  
  
 Data values after inserting 3 rows after row 2:
 first string     1  1  1  1. 1.
 second string    2  2  2  2. 2.
                  0  0  0  0. 0.
                  0  0  0  0. 0.
                  0  0  0  0. 0.
                  3  3  3  3. 3.
 UNDEFINED        4  4  4  4. 4.
                  5  5  5  5. 5.
                  6  6  6  6. 6.
                  7  7  7  7. 7.
                  8  8  8  8. 8.
                  9  9  9  9. 9.
                 10 10 10 10.10.
                 99 99 99 99.99.
  
 Data values after deleting 2 rows at row 10: 
 first string     1  1  1  1. 1.
 second string    2  2  2  2. 2.
                  0  0  0  0. 0.
                  0  0  0  0. 0.
                  0  0  0  0. 0.
                  3  3  3  3. 3.
 UNDEFINED        4  4  4  4. 4.
                  5  5  5  5. 5.
                  6  6  6  6. 6.
                  9  9  9  9. 9.
                 10 10 10 10.10.
                 99 99 99 99.99.
  
 Data values after deleting column 3: 
 first string     1  1  1. 1.
 second string    2  2  2. 2.
                  0  0  0. 0.
                  0  0  0. 0.
                  0  0  0. 0.
                  3  3  3. 3.
 UNDEFINED        4  4  4. 4.
                  5  5  5. 5.
                  6  6  6. 6.
                  9  9  9. 9.
                 10 10 10.10.
                 99 99 99.99.
  
  Data values after inserting column 5: 
 first string     1  1  1. 1. 0
 second string    2  2  2. 2. 0
                  0  0  0. 0. 0
                  0  0  0. 0. 0
                  0  0  0. 0. 0
                  3  3  3. 3. 0
 UNDEFINED        4  4  4. 4. 0
                  5  5  5. 5. 0
                  6  6  6. 6. 0
                  9  9  9. 9. 0
                 10 10 10.10. 0
                 99 99 99.99. 0
 HDU number =    3
  
 Moved to binary table
 header contains   37 keywords with room for   70 more 
  
 Binary table: nrows, tfields, extname, pcount:  21  10Test-BINTABLE     0
 Avalue         15A                           
 Lvalue         1L             m**2           
 Xvalue         16X            cm             
 Bvalue         1B             erg/s          
 Ivalue         1I             km/s           
 Jvalue         1J                            
 Evalue         1E                            
 Dvalue         1D                            
 Cvalue         1C                            
 Mvalue         1M                            
  
 Data values read from binary table: 
  Bit column (X) data values:   
 FTFFTTFF FTTTFFFF TTTTFFFF FTTTTTFF FFFFFFFF
   
 null string column value (should be blank):                              
  
 Read columns with ftgcv_: 
 first string     F  76   1   1   1   1.   1.   1.  -2.   1.  -2.
 second string    T 112   2   2   2   2.   2.   3.  -4.   3.  -4.
                  F 240   3   3   3   3.   3.   5.  -6.   5.  -6.
 NOT DEFINED      F 124   0  -4  -4  -4.  -4.   7.  -8.   7.  -8.
 NOT DEFINED      T   0   5   5   5   5.   5.   9. -10.   9. -10.
 NOT DEFINED      T   0   0  -6  -6  -6.  -6.  11. -12.  11. -12.
 NOT DEFINED      F   0   7   7   7   7.   7.  13. -14.  13. -14.
 NOT DEFINED      F   0   0  -8  -8  -8.  -8.  15. -16.  15. -16.
 NOT DEFINED      F   0   9   9   9   9.   9.  17. -18.  17. -18.
 NOT DEFINED      T   0   0 -10 -10 -10. -10.  19. -20.  19. -20.
 NOT DEFINED      F   0  98  98  98  98.  98.   0.   0.   0.   0.
 NOT DEFINED      T   0  12  12  12  12.  12.   0.   0.   0.   0.
 NOT DEFINED      F   0  98  98  98  98.  98.   0.   0.   0.   0.
 NOT DEFINED      F   0   0 -14 -14 -14. -14.   0.   0.   0.   0.
 NOT DEFINED      F   0  98  98  98  98.  98.   0.   0.   0.   0.
 NOT DEFINED      F   0   0 -16 -16 -16. -16.   0.   0.   0.   0.
 NOT DEFINED      T   0  98  98  98  98.  98.   0.   0.   0.   0.
 NOT DEFINED      T   0   0 -18 -18 -18. -18.   0.   0.   0.   0.
 NOT DEFINED      T   0  98  98  98  98.  98.   0.   0.   0.   0.
 NOT DEFINED      T   0   0 -20 -20 -20. -20.   0.   0.   0.   0.
 NOT DEFINED      F   0  98  98  98  98.  98.   0.   0.   0.   0.
  
  Read columns with ftgcf_: 
 first string     F  76   1   1   1   1.   1.   1.  -2.   1.  -2.
 second string    T 112   2   2   2   2.   2.   3.  -4.   3.  -4.
                  F 240   3   3   3   3.   3.   5.  -6.   5.  -6.
                  F 124   0  -4  -4  -4.  -4.   7.  -8.   7.  -8.
                  T   0   5   5   5   5.   5.   9. -10.   9. -10.
                  T   0   0  -6  -6  -6.  -6.  11. -12.  11. -12.
                  F   0   7   7   7   7.   7.  13. -14.  13. -14.
                  F   0   0  -8  -8  -8.  -8.  15. -16.  15. -16.
                  F   0   9   9   9   9.   9.  17. -18.  17. -18.
                  T   0   0 -10 -10 -10. -10.  19. -20.  19. -20.
                  F   0  99  99
                  T   0  12  12
                  F   0  99  99
                  F   0   0 -14
                  F   0  99  99
                  F   0   0 -16
                  T   0  99  99
                  T   0   0 -18
                  T   0  99  99
                  T   0   0 -20
                  F   0  99  99
  
 Data values after inserting 3 rows after row 2:
 first string     1   1   1   1.   1.
 second string    2   2   2   2.   2.
 NOT DEFINED      0   0   0   0.   0.
 NOT DEFINED      0   0   0   0.   0.
 NOT DEFINED      0   0   0   0.   0.
                  3   3   3   3.   3.
 NOT DEFINED      0  -4  -4  -4.  -4.
 NOT DEFINED      5   5   5   5.   5.
 NOT DEFINED      0  -6  -6  -6.  -6.
 NOT DEFINED      7   7   7   7.   7.
 NOT DEFINED      0  -8  -8  -8.  -8.
 NOT DEFINED      9   9   9   9.   9.
 NOT DEFINED      0 -10 -10 -10. -10.
 NOT DEFINED     98  98  98  98.  98.
  
 Data values after deleting 2 rows at row 10: 
 first string     1   1   1   1.   1.
 second string    2   2   2   2.   2.
 NOT DEFINED      0   0   0   0.   0.
 NOT DEFINED      0   0   0   0.   0.
 NOT DEFINED      0   0   0   0.   0.
                  3   3   3   3.   3.
 NOT DEFINED      0  -4  -4  -4.  -4.
 NOT DEFINED      5   5   5   5.   5.
 NOT DEFINED      0  -6  -6  -6.  -6.
 NOT DEFINED      9   9   9   9.   9.
 NOT DEFINED      0 -10 -10 -10. -10.
 NOT DEFINED     98  98  98  98.  98.
  
 Data values after deleting column 6: 
 first string     1   1   1.   1.
 second string    2   2   2.   2.
 NOT DEFINED      0   0   0.   0.
 NOT DEFINED      0   0   0.   0.
 NOT DEFINED      0   0   0.   0.
                  3   3   3.   3.
 NOT DEFINED      0  -4  -4.  -4.
 NOT DEFINED      5   5   5.   5.
 NOT DEFINED      0  -6  -6.  -6.
 NOT DEFINED      9   9   9.   9.
 NOT DEFINED      0 -10 -10. -10.
 NOT DEFINED     98  98  98.  98.
  
 Data values after inserting column 8: 
 first string     1   1   1.   1.  0
 second string    2   2   2.   2.  0
 NOT DEFINED      0   0   0.   0.  0
 NOT DEFINED      0   0   0.   0.  0
 NOT DEFINED      0   0   0.   0.  0
                  3   3   3.   3.  0
 NOT DEFINED      0  -4  -4.  -4.  0
 NOT DEFINED      5   5   5.   5.  0
 NOT DEFINED      0  -6  -6.  -6.  0
 NOT DEFINED      9   9   9.   9.  0
 NOT DEFINED      0 -10 -10. -10.  0
 NOT DEFINED     98  98  98.  98.  0
  
 Values after setting 1st 10 elements in column 8 = null: 
 first string     1   1   1.   1. 98
 second string    2   2   2.   2. 98
 NOT DEFINED      0   0   0.   0. 98
 NOT DEFINED      0   0   0.   0. 98
 NOT DEFINED      0   0   0.   0. 98
                  3   3   3.   3. 98
 NOT DEFINED      0  -4  -4.  -4. 98
 NOT DEFINED      5   5   5.   5. 98
 NOT DEFINED      0  -6  -6.  -6. 98
 NOT DEFINED      9   9   9.   9. 98
 NOT DEFINED      0 -10 -10. -10.  0
 NOT DEFINED     98  98  98.  98.  0
  
 ftibin status =    0
 HDU number =    2
      0  1000 10000 33000 66000  -999
      0  1000 10000 32768 65535  -999
      0  1000 10000 32800 65500  -999
  
      0     1    10    33    66  -999
 -32768-31768-22768     0 32767  -999
     -1     9    99   327   654  -999
  
  Create image extension: ftiimg status =    0
 HDU number =    3
  
 Wrote whole 2D array: ftp2di status =   0
  
 Read whole 2D array: ftg2di status =   0
    0   1   2   3   4   5   6   7   8   9  10  11  12  13  14   0   0   0   0
   10  11  12  13  14  15  16  17  18  19  20  21  22  23  24   0   0   0   0
   20  21  22  23  24  25  26  27  28  29  30  31  32  33  34   0   0   0   0
   30  31  32  33  34  35  36  37  38  39  40  41  42  43  44   0   0   0   0
   40  41  42  43  44  45  46  47  48  49  50  51  52  53  54   0   0   0   0
   50  51  52  53  54  55  56  57  58  59  60  61  62  63  64   0   0   0   0
   60  61  62  63  64  65  66  67  68  69  70  71  72  73  74   0   0   0   0
   70  71  72  73  74  75  76  77  78  79  80  81  82  83  84   0   0   0   0
   80  81  82  83  84  85  86  87  88  89  90  91  92  93  94   0   0   0   0
   90  91  92  93  94  95  96  97  98  99 100 101 102 103 104   0   0   0   0
  100 101 102 103 104 105 106 107 108 109 110 111 112 113 114   0   0   0   0
  110 111 112 113 114 115 116 117 118 119 120 121 122 123 124   0   0   0   0
  120 121 122 123 124 125 126 127 128 129 130 131 132 133 134   0   0   0   0
  130 131 132 133 134 135 136 137 138 139 140 141 142 143 144   0   0   0   0
  140 141 142 143 144 145 146 147 148 149 150 151 152 153 154   0   0   0   0
  150 151 152 153 154 155 156 157 158 159 160 161 162 163 164   0   0   0   0
  160 161 162 163 164 165 166 167 168 169 170 171 172 173 174   0   0   0   0
  170 171 172 173 174 175 176 177 178 179 180 181 182 183 184   0   0   0   0
  180 181 182 183 184 185 186 187 188 189 190 191 192 193 194   0   0   0   0
  190 191 192 193 194 195 196 197 198 199 200 201 202 203 204   0   0   0   0
  200 201 202 203 204 205 206 207 208 209 210 211 212 213 214   0   0   0   0
  210 211 212 213 214 215 216 217 218 219 220 221 222 223 224   0   0   0   0
  220 221 222 223 224 225 226 227 228 229 230 231 232 233 234   0   0   0   0
  230 231 232 233 234 235 236 237 238 239 240 241 242 243 244   0   0   0   0
  240 241 242 243 244 245 246 247 248 249 250 251 252 253 254   0   0   0   0
    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
  
  
 Wrote subset 2D array: ftpssi status =   0
  
 Read whole 2D array: ftg2di status =   0
    0   1   2   3   4   5   6   7   8   9  10  11  12  13  14   0   0   0   0
   10  11  12  13  14  15  16  17  18  19  20  21  22  23  24   0   0   0   0
   20  21  22  23  24  25  26  27  28  29  30  31  32  33  34   0   0   0   0
   30  31  32  33  34  35  36  37  38  39  40  41  42  43  44   0   0   0   0
   40  41  42  43   0  -1  -2  -3  -4  -5  -6  -7  -8  -9  54   0   0   0   0
   50  51  52  53 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19  64   0   0   0   0
   60  61  62  63 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29  74   0   0   0   0
   70  71  72  73 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39  84   0   0   0   0
   80  81  82  83 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49  94   0   0   0   0
   90  91  92  93 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 104   0   0   0   0
  100 101 102 103 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 114   0   0   0   0
  110 111 112 113 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 124   0   0   0   0
  120 121 122 123 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 134   0   0   0   0
  130 131 132 133 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 144   0   0   0   0
  140 141 142 143 144 145 146 147 148 149 150 151 152 153 154   0   0   0   0
  150 151 152 153 154 155 156 157 158 159 160 161 162 163 164   0   0   0   0
  160 161 162 163 164 165 166 167 168 169 170 171 172 173 174   0   0   0   0
  170 171 172 173 174 175 176 177 178 179 180 181 182 183 184   0   0   0   0
  180 181 182 183 184 185 186 187 188 189 190 191 192 193 194   0   0   0   0
  190 191 192 193 194 195 196 197 198 199 200 201 202 203 204   0   0   0   0
  200 201 202 203 204 205 206 207 208 209 210 211 212 213 214   0   0   0   0
  210 211 212 213 214 215 216 217 218 219 220 221 222 223 224   0   0   0   0
  220 221 222 223 224 225 226 227 228 229 230 231 232 233 234   0   0   0   0
  230 231 232 233 234 235 236 237 238 239 240 241 242 243 244   0   0   0   0
  240 241 242 243 244 245 246 247 248 249 250 251 252 253 254   0   0   0   0
    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
  
  
 Read subset of 2D array: ftgsvi status =    0
    41   43   -1   -3   -5   71   73  -31  -33  -35
  
 Create image extension: ftiimg status =   0
 HDU number =    4
 Create temporary file: ftinit status =    0
 Copy image extension to primary array of tmp file.
 ftcopy status =    0
 SIMPLE  =                    T / file does conform to FITS standard           
 BITPIX  =                   16 / number of bits per data pixel                
 NAXIS   =                    2 / number of data axes                          
 NAXIS1  =                   15 / length of data axis 1                        
 NAXIS2  =                   25 / length of data axis 2                        
 EXTEND  =                    T / FITS dataset may contain extensions          
 Delete the tmp file: ftdelt status =   0
 Delete the image extension hdutype, status =   1   0
 HDU number =    4
 ftcrhd status =    0
 Variable length arrays: ftphbn status =   0
 ftpcl_ status =    0
 PCOUNT = 4446
 HDU number =    6
 A                                   0
 L  0  F
 X  0  F
 B  1  0
 I  1  0
 J  1  0
 E  1. 0.
 D  1. 0.
 Column 8 repeat and offset =    1   14
 A  ab                               0
 L  0  F  T
 X  0  F  T
 B 99  2  0
 I 99  2  0
 J 99  2  0
 E 99. 2. 0.
 D 99. 2. 0.
 Column 8 repeat and offset =    2   49
 A  abc                              0
 L  0  F  F  F
 X  0  F  T  F
 B  1 99  3  0
 I  1 99  3  0
 J  1 99  3  0
 E  1.99. 3. 0.
 D  1.99. 3. 0.
 Column 8 repeat and offset =    3  105
 A  abcd                             0
 L  0  F  T  F  F
 X  0  F  T  F  F
 B  1  2 99  4  0
 I  1  2 99  4  0
 J  1  2 99  4  0
 E  1. 2.99. 4. 0.
 D  1. 2.99. 4. 0.
 Column 8 repeat and offset =    4  182
 A  abcde                            0
 L  0  F  T  F  F  T
 X  0  F  T  F  F  T
 B  1  2  3 99  5  0
 I  1  2  3 99  5  0
 J  1  2  3 99  5  0
 E  1. 2. 3.99. 5. 0.
 D  1. 2. 3.99. 5. 0.
 Column 8 repeat and offset =    5  280
 A  abcdef                           0
 L  0  F  T  F  F  F  T
 X  0  F  T  F  F  T  T
 B  1  2  3  4 99  6  0
 I  1  2  3  4 99  6  0
 J  1  2  3  4 99  6  0
 E  1. 2. 3. 4.99. 6. 0.
 D  1. 2. 3. 4.99. 6. 0.
 Column 8 repeat and offset =    6  399
 A  abcdefg                          0
 L  0  F  T  F  F  T  F  F
 X  0  F  T  F  F  T  T  F
 B  1  2  3  4  5 99  7  0
 I  1  2  3  4  5 99  7  0
 J  1  2  3  4  5 99  7  0
 E  1. 2. 3. 4. 5.99. 7. 0.
 D  1. 2. 3. 4. 5.99. 7. 0.
 Column 8 repeat and offset =    7  539
 A  abcdefgh                         0
 L  0  F  T  F  F  T  T  F  F
 X  0  F  T  F  F  T  T  F  F
 B  1  2  3  4  5  6 99  8  0
 I  1  2  3  4  5  6 99  8  0
 J  1  2  3  4  5  6 99  8  0
 E  1. 2. 3. 4. 5. 6.99. 8. 0.
 D  1. 2. 3. 4. 5. 6.99. 8. 0.
 Column 8 repeat and offset =    8  700
 A  abcdefghi                        0
 L  0  F  T  F  F  T  T  F  F  F
 X  0  F  T  F  F  T  T  F  F  F
 B  1  2  3  4  5  6  7 99  9  0
 I  1  2  3  4  5  6  7 99  9  0
 J  1  2  3  4  5  6  7 99  9  0
 E  1. 2. 3. 4. 5. 6. 7.99. 9. 0.
 D  1. 2. 3. 4. 5. 6. 7.99. 9. 0.
 Column 8 repeat and offset =    9  883
 A  abcdefghij                       0
 L  0  F  T  F  F  T  T  F  F  F  T
 X  0  F  T  F  F  T  T  F  F  F  T
 B  1  2  3  4  5  6  7  8 99 10  0
 I  1  2  3  4  5  6  7  8 99 10  0
 J  1  2  3  4  5  6  7  8 99 10  0
 E  1. 2. 3. 4. 5. 6. 7. 8.99.10. 0.
 D  1. 2. 3. 4. 5. 6. 7. 8.99.10. 0.
 Column 8 repeat and offset =   10 1087
 A  abcdefghijk                      0
 L  0  F  T  F  F  T  T  F  F  F  F  T
 X  0  F  T  F  F  T  T  F  F  F  T  T
 B  1  2  3  4  5  6  7  8  9 99 11  0
 I  1  2  3  4  5  6  7  8  9 99 11  0
 J  1  2  3  4  5  6  7  8  9 99 11  0
 E  1. 2. 3. 4. 5. 6. 7. 8. 9.99.11. 0.
 D  1. 2. 3. 4. 5. 6. 7. 8. 9.99.11. 0.
 Column 8 repeat and offset =   11 1312
 A  abcdefghijkl                     0
 L  0  F  T  F  F  T  T  F  F  F  T  F  T
 X  0  F  T  F  F  T  T  F  F  F  T  T  T
 B  1  2  3  4  5  6  7  8  9 10 99 12  0
 I  1  2  3  4  5  6  7  8  9 10 99 12  0
 J  1  2  3  4  5  6  7  8  9 10 99 12  0
 E  1. 2. 3. 4. 5. 6. 7. 8. 9.10.99.12. 0.
 D  1. 2. 3. 4. 5. 6. 7. 8. 9.10.99.12. 0.
 Column 8 repeat and offset =   12 1558
 A  abcdefghijklm                    0
 L  0  F  T  F  F  T  T  F  F  F  T  T  F  F
 X  0  F  T  F  F  T  T  F  F  F  T  T  T  F
 B  1  2  3  4  5  6  7  8  9 10 11 99 13  0
 I  1  2  3  4  5  6  7  8  9 10 11 99 13  0
 J  1  2  3  4  5  6  7  8  9 10 11 99 13  0
 E  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.99.13. 0.
 D  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.99.13. 0.
 Column 8 repeat and offset =   13 1825
 A  abcdefghijklmn                   0
 L  0  F  T  F  F  T  T  F  F  F  T  T  T  F  F
 X  0  F  T  F  F  T  T  F  F  F  T  T  T  F  F
 B  1  2  3  4  5  6  7  8  9 10 11 12 99 14  0
 I  1  2  3  4  5  6  7  8  9 10 11 12 99 14  0
 J  1  2  3  4  5  6  7  8  9 10 11 12 99 14  0
 E  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.99.14. 0.
 D  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.99.14. 0.
 Column 8 repeat and offset =   14 2113
 A  abcdefghijklmno                  0
 L  0  F  T  F  F  T  T  F  F  F  T  T  T  F  F  F
 X  0  F  T  F  F  T  T  F  F  F  T  T  T  F  F  F
 B  1  2  3  4  5  6  7  8  9 10 11 12 13 99 15  0
 I  1  2  3  4  5  6  7  8  9 10 11 12 13 99 15  0
 J  1  2  3  4  5  6  7  8  9 10 11 12 13 99 15  0
 E  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.99.15. 0.
 D  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.99.15. 0.
 Column 8 repeat and offset =   15 2422
 A  abcdefghijklmnop                 0
 L  0  F  T  F  F  T  T  F  F  F  T  T  T  F  F  F  F
 X  0  F  T  F  F  T  T  F  F  F  T  T  T  F  F  F  F
 B  1  2  3  4  5  6  7  8  9 10 11 12 13 14 99 16  0
 I  1  2  3  4  5  6  7  8  9 10 11 12 13 14 99 16  0
 J  1  2  3  4  5  6  7  8  9 10 11 12 13 14 99 16  0
 E  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.99.16. 0.
 D  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.99.16. 0.
 Column 8 repeat and offset =   16 2752
 A  abcdefghijklmnopq                0
 L  0  F  T  F  F  T  T  F  F  F  T  T  T  F  F  F  F  T
 X  0  F  T  F  F  T  T  F  F  F  T  T  T  F  F  F  F  T
 B  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 99 17  0
 I  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 99 17  0
 J  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 99 17  0
 E  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.15.99.17. 0.
 D  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.15.99.17. 0.
 Column 8 repeat and offset =   17 3104
 A  abcdefghijklmnopqr               0
 L  0  F  T  F  F  T  T  F  F  F  T  T  T  F  F  F  F  F  T
 X  0  F  T  F  F  T  T  F  F  F  T  T  T  F  F  F  F  T  T
 B  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 99 18  0
 I  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 99 18  0
 J  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 99 18  0
 E  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.15.16.99.18. 0.
 D  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.15.16.99.18. 0.
 Column 8 repeat and offset =   18 3477
 A  abcdefghijklmnopqrs              0
 L  0  F  T  F  F  T  T  F  F  F  T  T  T  F  F  F  F  T  F  T
 X  0  F  T  F  F  T  T  F  F  F  T  T  T  F  F  F  F  T  T  T
 B  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 99 19  0
 I  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 99 19  0
 J  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 99 19  0
 E  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.15.16.17.99.19. 0.
 D  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.15.16.17.99.19. 0.
 Column 8 repeat and offset =   19 3871
 A  abcdefghijklmnopqrst             0
 L  0  F  T  F  F  T  T  F  F  F  T  T  T  F  F  F  F  T  T  F  T
 X  0  F  T  F  F  T  T  F  F  F  T  T  T  F  F  F  F  T  T  T  T
 B  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 99 20  0
 I  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 99 20  0
 J  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 99 20  0
 E  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.15.16.17.18.99.20. 0.
 D  1. 2. 3. 4. 5. 6. 7. 8. 9.10.11.12.13.14.15.16.17.18.99.20. 0.
 Column 8 repeat and offset =   20 4286
  
 Create image extension: ftiimg status =   0
 ftppr status =    0
  
 Image values written with ftppr and read with ftgpv:
   0  2  4  6  8 10 12 14 16 18 20 22 24 26  F (byte)
   0  2  4  6  8 10 12 14 16 18 20 22 24 26  F (short)
   0  2  4  6  8 10 12 14 16 18 20 22 24 26  F (int)
   0  2  4  6  8 10 12 14 16 18 20 22 24 26  F (long)
   0. 2. 4. 6. 8.10.12.14.16.18.20.22.24.26. F (float)
   0. 2. 4. 6. 8.10.12.14.16.18.20.22.24.26. F (double)
  
 Wrote WCS keywords status =   0
 Read WCS keywords with ftgics status =   0
   CRVAL1, CRVAL2 =  45.830  63.570
   CRPIX1, CRPIX2 = 256.000 257.000
   CDELT1, CDELT2 = -0.00277777  0.00277777
   Rotation =   0.000 CTYPE =-TAN    
 Calculated sky coord. with ftwldp status =   0
  Pixels (  0.500000  0.500000) --> ( 47.385204 62.848968) Sky
 Calculated pixel coord. with ftxypx status =   0
  Sky ( 47.385204 62.848968) --> (  0.500000  0.500000) Pixels
  
 ftitab status =    0
 ftpcl status =    0
 Column values written with ftpcl and read with ftgcl: 
   0  3  6  9 12 15 18 21 24 27  F (byte) 
   0  3  6  9 12 15 18 21 24 27  F (short) 
   0  3  6  9 12 15 18 21 24 27  F (int) 
   0  3  6  9 12 15 18 21 24 27  F (long) 
   0. 3. 6. 9.12.15.18.21.24.27. F (float) 
   0. 3. 6. 9.12.15.18.21.24.27. F (double) 
  
 Repeatedly move to the 1st 4 HDUs of the file: 
  
 Encode checksum:  1234567890.0 -> dCW2fBU0dBU0dBU0 
 Decode checksum: dCW2fBU0dBU0dBU0  ->  1234567890.0
 DATASUM = '2338390162'
 ftgcks data checksum, status =  2338390162.0   0
 ftvcks datastatus, hdustatus, status =     1   1   0
 ftupck status =    0
 DATASUM = '2338390162'
 ftvcks datastatus, hdustatus, status =     1   1   0
 ftclos status =    0
  
 Normally, there should be 8 error messages on the
 stack all regarding 'numerical overflows':
 Numerical overflow during type conversion while writing FITS data.         
 Numerical overflow during type conversion while writing FITS data.         
 Numerical overflow during type conversion while writing FITS data.         
 Numerical overflow during type conversion while writing FITS data.         
 Numerical overflow during type conversion while writing FITS data.         
 Numerical overflow during type conversion while writing FITS data.         
 Numerical overflow during type conversion while writing FITS data.         
 Numerical overflow during type conversion while writing FITS data.         
  
 Status =   0: OK - no error                                     
cfitsio/testf77.std0000644000225700000360000020130013246025103014013 0ustar  cagordonlheaSIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                   32 / number of bits per data pixel                  NAXIS   =                    2 / number of data axes                            NAXIS1  =                   10 / length of data axis 1                          NAXIS2  =                    2 / length of data axis 2                          EXTEND  =                    T / FITS dataset may contain extensions            COMMENT   FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H KEY_PREC= 'This keyword was written by fxprec' / comment goes here              CARD1   = '12345678901234567890123456789012345678901234567890123456789012345678'CARD2   = '1234567890123456789012345678901234567890123456789012345678901234''67'CARD3   = '1234567890123456789012345678901234567890123456789012345678901234'''''CARD4   = '1234567890123456789012345678901234567890123456789012345678901234567' KEY_PKYS= 'value_string'       / fxpkys comment                                 KEY_PKYL=                    T / fxpkyl comment                                 KEY_PKYJ=                   11 / [feet/second/second] fxpkyj comment            KEY_PKYF=             12.12121 / fxpkyf comment                                 KEY_PKYE=         1.313131E+01 / fxpkye comment                                 KEY_PKYG=    14.14141414141414 / fxpkyg comment                                 KEY_PKYD= 1.51515151515152E+01 / fxpkyd comment                                 KEY_PKLS= 'This is a very long string value that is continued over more than o&'CONTINUE  'ne keyword.'        / fxpkls comment                                 LONGSTRN= 'OGIP 1.0'           / The HEASARC Long String Convention may be used.COMMENT   This FITS file may contain long string keyword values that are        COMMENT   This keyword was modified by fxmrec                                   KY_UCRD = 'This keyword was updated by fxucrd'                                  NEWIKYS = 'updated_string'     / ikys comment                                   KY_IKYJ =                   51 / This is a modified comment                     KY_IKYL =                    T / ikyl comment                                   KY_IKYE =          -1.3346E+01 / ikye comment                                   KY_IKYD = -1.33456789012346E+01 / modified comment                              KY_IKYF =             -13.3456 / ikyf comment                                   KY_IKYG =    -13.3456789012346 / ikyg comment                                   COMMENT   character at the end of each substring which is then continued        COMMENT   on the next keyword which has the name CONTINUE.                      KEY_PKYT= 12345678.1234567890123456 / fxpkyt comment                            COMMENT This keyword was written by fxpcom.                                     KY_PKNS1= 'first string'       / fxpkns comment                                 KY_PKNS2= 'second string'      / fxpkns comment                                 KY_PKNS3= '        '           / fxpkns comment                                 KY_PKNL1=                    T / fxpknl comment                                 KY_PKNL2=                    F / fxpknl comment                                 KY_PKNL3=                    T / fxpknl comment                                 KY_PKNJ1=                   11 / fxpknj comment                                 KY_PKNJ2=                   12 / fxpknj comment                                 KY_PKNJ3=                   13 / fxpknj comment                                 KY_PKNF1=             12.12121 / fxpknf comment                                 KY_PKNF2=             13.13131 / fxpknf comment                                 KY_PKNF3=             14.14141 / fxpknf comment                                 KY_PKNE1=         1.313131E+01 / fxpkne comment                                 KY_PKNE2=         1.414141E+01 / fxpkne comment                                 KY_PKNE3=         1.515152E+01 / fxpkne comment                                 KY_PKNG1=     14.1414141414141 / fxpkng comment                                 KY_PKNG2=     15.1515151515152 / fxpkng comment                                 KY_PKNG3=     16.1616161616162 / fxpkng comment                                 KY_PKND1= 1.51515151515152E+01 / fxpknd comment                                 KY_PKND2= 1.61616161616162E+01 / fxpknd comment                                 KY_PKND3= 1.71717171717172E+01 / fxpknd comment                                 TSTRING = '1       '           / tstring comment                                TLOGICAL=                    T / tlogical comment                               TBYTE   =                   11 / tbyte comment                                  TSHORT  =                   21 / tshort comment                                 TINT    =                   31 / tint comment                                   TLONG   =                   41 / tlong comment                                  TFLOAT  =         4.200000E+01 / tfloat comment                                 TDOUBLE = 8.20000000000000E+01 / tdouble comment                                BLANK   =                  -99 / value to use for undefined pixels              END                                                                                                                                                                                                                                                                                                                                                                                                             ÿÿÿÿÿÿÿÿÿ	
ÿÿÿ
ÿÿÿÿÿÿXTENSION= 'BINTABLE'           / binary table extension                         BITPIX  =                    8 / 8-bit bytes                                    NAXIS   =                    2 / 2-dimensional binary table                     NAXIS1  =                   61 / width of table in bytes                        NAXIS2  =                   20 / number of rows in table                        PCOUNT  =                    0 / size of special data area                      GCOUNT  =                    1 / one data group (required keyword)              TFIELDS =                   10 / number of fields in each row                   TTYPE1  = 'Avalue  '           / label for field   1                            TFORM1  = '15A     '           / data format of field: ASCII Character          TTYPE2  = 'Lvalue  '           / label for field   2                            TFORM2  = '1L      '           / data format of field: 1-byte LOGICAL           TUNIT2  = 'm**2    '           / physical unit of field                         TTYPE3  = 'Xvalue  '           / label for field   3                            TFORM3  = '16X     '           / data format of field: BIT                      TUNIT3  = 'cm      '           / physical unit of field                         TTYPE4  = 'Bvalue  '           / label for field   4                            TFORM4  = '1B      '           / data format of field: BYTE                     TUNIT4  = 'erg/s   '           / physical unit of field                         TTYPE5  = 'Ivalue  '           / label for field   5                            TFORM5  = '1I      '           / data format of field: 2-byte INTEGER           TUNIT5  = 'km/s    '           / physical unit of field                         TTYPE6  = 'Jvalue  '           / label for field   6                            TFORM6  = '1J      '           / data format of field: 4-byte INTEGER           TTYPE7  = 'Evalue  '           / label for field   7                            TFORM7  = '1E      '           / data format of field: 4-byte REAL              TTYPE8  = 'Dvalue  '           / label for field   8                            TFORM8  = '1D      '           / data format of field: 8-byte DOUBLE            TTYPE9  = 'Cvalue  '           / label for field   9                            TFORM9  = '1C      '           / data format of field: COMPLEX                  TTYPE10 = 'Mvalue  '           / label for field  10                            TFORM10 = '1M      '           / data format of field: DOUBLE COMPLEX           EXTNAME = 'Test-BINTABLE'      / name of this binary table extension            TNULL4  =                   77 / value for undefined pixels                     TNULL5  =                   77 / value for undefined pixels                     TNULL6  =                   77 / value for undefined pixels                     TSCAL4  =                 1000 / scaling factor                                 TSCAL5  =                    1 / scaling factor                                 TSCAL6  =                  100 / scaling factor                                 TZERO4  =                    0 / scaling offset                                 TZERO5  =                32768 / scaling offset                                 TZERO6  =                  100 / scaling offset                                 END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             €ÿÿÿÿƒè	
§c!GBÿŽMMMXTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    2 / number of data axes                            NAXIS1  =                   15 / length of data axis 1                          NAXIS2  =                   25 / length of data axis 2                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     NEW_KEY = 'written by fxprec' / to change checksum                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ?€@@@@€@ @À@àAAA A0A@APA`A A0A@APA`ApA€AˆAA˜A A¨A°A¸AÀA A¨A°A¸AÀAÈAÐAØAàAèAðAøBBBAðAøBBBBBBBBB B$B(B,B0B B$B(B,¿€ÀÀ@À€À ÀÀÀàÁÁBXBHBLBPBTÁ Á0Á@ÁPÁ`ÁpÁ€ÁˆÁÁ˜B€BpBtBxB|Á Á¨Á°Á¸ÁÀÁÈÁÐÁØÁàÁèB”BŒBŽBB’ÁðÁøÂÂÂÂÂÂÂÂB¨B B¢B¤B¦Â Â$Â(Â,Â0Â4Â8Â<Â@ÂDB¼B´B¶B¸BºÂHÂLÂPÂTÂXÂ\Â`ÂdÂhÂlBÐBÈBÊBÌBÎÂpÂtÂxÂ|€‚„†ˆŠBäBÜBÞBàB⌎’”–˜šœžBøBðBòBôBö ¢¤¦¨ª¬®°²CCCCC´¶¸º¼¾ÂÀÂÂÂÄÂÆCCC
CCCCCCCCCCCCCCCCCCCCCCCC C!C"C#C$C C!C"C#C$C%C&C'C(C)C*C+C,C-C.C*C+C,C-C.C/C0C1C2C3C4C5C6C7C8C4C5C6C7C8C9C:C;C<C=C>C?C@CACBC>C?C@CACBCCCDCECFCGCHCICJCKCLCHCICJCKCLCMCNCOCPCQCRCSCTCUCVCRCSCTCUCVCWCXCYCZC[C\C]C^C_C`C\C]C^C_C`CaCbCcCdCeCfCgChCiCjCfCgChCiCjCkClCmCnCoCpCqCrCsCtCpCqCrCsCtCuCvCwCxCyCzC{C|C}C~XTENSION= 'TABLE   '           / ASCII table extension                          BITPIX  =                    8 / 8-bit ASCII characters                         NAXIS   =                    2 / 2-dimensional ASCII table                      NAXIS1  =                   76 / width of table in characters                   NAXIS2  =                   12 / number of rows in table                        PCOUNT  =                    0 / no group parameters (required keyword)         GCOUNT  =                    1 / one data group (required keyword)              TFIELDS =                    5 / number of fields in each row                   TTYPE1  = 'Name    '           / label for field   1                            TBCOL1  =                    1 / beginning column of field   1                  TFORM1  = 'A15     '           / Fortran-77 format of field                     TTYPE2  = 'Ivalue  '           / label for field   2                            TBCOL2  =                   17 / beginning column of field   2                  TFORM2  = 'I10     '           / Fortran-77 format of field                     TUNIT2  = 'm**2    '           / physical unit of field                         TTYPE3  = 'Evalue  '           / label for field   4                            TBCOL3  =                   28 / beginning column of field   4                  TFORM3  = 'E12.5   '           / Fortran-77 format of field                     TUNIT3  = 'erg/s   '           / physical unit of field                         TTYPE4  = 'Dvalue  '           / label for field   5                            TBCOL4  =                   41 / beginning column of field   5                  TFORM4  = 'D21.14  '           / Fortran-77 format of field                     TUNIT4  = 'km/s    '           / physical unit of field                         EXTNAME = 'Test-ASCII'         / name of this ASCII table extension             TNULL1  = 'null1   '           / value for undefined pixels                     TNULL2  = 'null2   '           / value for undefined pixels                     TNULL3  = 'null4   '           / value for undefined pixels                     TNULL4  = 'null5   '           / value for undefined pixels                     TTYPE5  = 'INSERT_COL'         / label for field                                TFORM5  = 'F14.6   '           / format of field                                TBCOL5  =                   63 / beginning column of field                      END                                                                                                                                                                                                                                                                                                                                                                                                             first string             1  1.00000E+00  1.00000000000000E+00               second string            2  2.00000E+00  2.00000000000000E+00                                                                                                                                                                                                                                                                            3  3.00000E+00  3.00000000000000E+00               null1                    4  4.00000E+00  4.00000000000000E+00                                        5  5.00000E+00  5.00000000000000E+00                                        6  6.00000E+00  6.00000000000000E+00                                        9  9.00000E+00  9.00000000000000E+00                                       10  1.00000E+01  1.00000000000000E+01                               null2      null4        null5                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               XTENSION= 'BINTABLE'           / binary table extension                         BITPIX  =                    8 / 8-bit bytes                                    NAXIS   =                    2 / 2-dimensional binary table                     NAXIS1  =                   61 / width of table in bytes                        NAXIS2  =                   22 / number of rows in table                        PCOUNT  =                    0 / size of special data area                      GCOUNT  =                    1 / one data group (required keyword)              TFIELDS =                   10 / number of fields in each row                   TTYPE1  = 'Avalue  '           / label for field   1                            TFORM1  = '15A     '           / data format of field: ASCII Character          TTYPE2  = 'Lvalue  '           / label for field   2                            TFORM2  = '1L      '           / data format of field: 1-byte LOGICAL           TUNIT2  = 'm**2    '           / physical unit of field                         TTYPE3  = 'Xvalue  '           / label for field   3                            TFORM3  = '16X     '           / data format of field: BIT                      TUNIT3  = 'cm      '           / physical unit of field                         TTYPE4  = 'Bvalue  '           / label for field   4                            TFORM4  = '1B      '           / data format of field: BYTE                     TUNIT4  = 'erg/s   '           / physical unit of field                         TTYPE5  = 'Ivalue  '           / label for field   5                            TFORM5  = '1I      '           / data format of field: 2-byte INTEGER           TUNIT5  = 'km/s    '           / physical unit of field                         TTYPE6  = 'Evalue  '           / label for field   7                            TFORM6  = '1E      '           / data format of field: 4-byte REAL              TTYPE7  = 'Dvalue  '           / label for field   8                            TFORM7  = '1D      '           / data format of field: 8-byte DOUBLE            TTYPE9  = 'Cvalue  '           / label for field   9                            TFORM9  = '1C      '           / data format of field: COMPLEX                  TTYPE10 = 'Mvalue  '           / label for field  10                            TFORM10 = '1M      '           / data format of field: DOUBLE COMPLEX           EXTNAME = 'Test-BINTABLE'      / name of this binary table extension            TNULL4  =                   99 / value for undefined pixels                     TNULL5  =                   99 / value for undefined pixels                     TDIM3   = '(1,2,8) '           / size of the multidimensional array             KEY_PREC= 'This keyword was written by f_prec' / comment here                   TTYPE8  = 'INSERT_COL'         / label for field                                TFORM8  = '1E      '           / format of field                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             first string   FLp?€?ðÿÿÿÿ?€À?ðÀsecond string  Tð|@@ÿÿÿÿ@@À€@Àÿÿÿÿÿÿÿÿÿÿÿÿ               F@@@ÿÿÿÿ@ ÀÀ@À              FÿüÀ€Àÿÿÿÿ@àÁ@À T@ @ÿÿÿÿAÁ @"À$TÿúÀÀÀÿÿÿÿA0Á@@&À(F		A@"ÿÿÿÿAˆÁ@1À2TÿöÁ À$A˜Á @3À4ccÿÿÿÿÿÿÿÿÿÿÿÿTA@@(FccÿÿÿÿÿÿÿÿÿÿÿÿFÿòÁ`À,FccÿÿÿÿÿÿÿÿÿÿÿÿFÿðÁ€À0TccÿÿÿÿÿÿÿÿÿÿÿÿTÿîÁÀ2TccÿÿÿÿÿÿÿÿÿÿÿÿTÿìÁ À4FccÿÿÿÿÿÿÿÿÿÿÿÿXTENSION= 'BINTABLE'           / binary table extension                         BITPIX  =                    8 / 8-bit bytes                                    NAXIS   =                    2 / 2-dimensional binary table                     NAXIS1  =                   80 / width of table in bytes                        NAXIS2  =                   20 / number of rows in table                        PCOUNT  =                 4446 / size of special data area                      GCOUNT  =                    1 / one data group (required keyword)              TFIELDS =                   10 / number of fields in each row                   TTYPE1  = 'Avalue  '           / label for field   1                            TFORM1  = '1PA(20) '           / data format of field: variable length array    TTYPE2  = 'Lvalue  '           / label for field   2                            TFORM2  = '1PL(20) '           / data format of field: variable length array    TUNIT2  = 'm**2    '           / physical unit of field                         TTYPE3  = 'Xvalue  '           / label for field   3                            TFORM3  = '1PB(3)  '           / data format of field: variable length array    TUNIT3  = 'cm      '           / physical unit of field                         TTYPE4  = 'Bvalue  '           / label for field   4                            TFORM4  = '1PB(20) '           / data format of field: variable length array    TUNIT4  = 'erg/s   '           / physical unit of field                         TTYPE5  = 'Ivalue  '           / label for field   5                            TFORM5  = '1PI(20) '           / data format of field: variable length array    TUNIT5  = 'km/s    '           / physical unit of field                         TTYPE6  = 'Jvalue  '           / label for field   6                            TFORM6  = '1PJ(20) '           / data format of field: variable length array    TTYPE7  = 'Evalue  '           / label for field   7                            TFORM7  = '1PE(20) '           / data format of field: variable length array    TTYPE8  = 'Dvalue  '           / label for field   8                            TFORM8  = '1PD(20) '           / data format of field: variable length array    TTYPE9  = 'Cvalue  '           / label for field   9                            TFORM9  = '1PC(0)  '           / data format of field: variable length array    TTYPE10 = 'Mvalue  '           / label for field  10                            TFORM10 = '1PM(0)  '           / data format of field: variable length array    EXTNAME = 'Test-BINTABLE'      / name of this binary table extension            TNULL4  =                   88 / value for undefined pixels                     TNULL5  =                   88 / value for undefined pixels                     TNULL6  =                   88 / value for undefined pixels                     END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
!)1ADGHKQ]i…‰ŠŽ–¦¶ÖÛàáæð@FLMS_w¿ÆÍÎÕãÿS[cdl|œ¼	ü				+	O	s
»
ÅÏ
Ñ
Û
ï

?𥧲Èô x„’ž¶æ
v
ƒ
’
Ÿ
¹
í
!‰—¥§µÑ	A±ÀÏÑàþ	:	v	î	þ


 
@
€
À@Qbev˜Ü ¨ºÌÏá

M
•%8KNa‡Ó·Ëßâön¾F?€?ðabT@XXXÿÿÿÿ@ÿÿÿÿÿÿÿÿ@abcFF@XXX?€ÿÿÿÿ@@?ðÿÿÿÿÿÿÿÿ@abcdFTF@XXX?€@ÿÿÿÿ@€?ð@ÿÿÿÿÿÿÿÿ@abcdeFTFTHXXX?€@@@ÿÿÿÿ@ ?ð@@ÿÿÿÿÿÿÿÿ@abcdefFTFFTLXXX?€@@@@€ÿÿÿÿ@À?ð@@@ÿÿÿÿÿÿÿÿ@abcdefgFTFFTFLXXX?€@@@@€@ ÿÿÿÿ@à?ð@@@@ÿÿÿÿÿÿÿÿ@abcdefghFTFFTTFLXXX?€@@@@€@ @ÀÿÿÿÿA?ð@@@@@ÿÿÿÿÿÿÿÿ@ abcdefghiFTFFTTFFLX	X	X	?€@@@@€@ @À@àÿÿÿÿA?ð@@@@@@ÿÿÿÿÿÿÿÿ@"abcdefghijFTFFTTFFTL@X
X
X
?€@@@@€@ @À@àAÿÿÿÿA ?ð@@@@@@@ ÿÿÿÿÿÿÿÿ@$abcdefghijkFTFFTTFFFTL`	X	X	X?€@@@@€@ @À@àAAÿÿÿÿA0?ð@@@@@@@ @"ÿÿÿÿÿÿÿÿ@&abcdefghijklFTFFTTFFFTTLp	
X	
X	
X?€@@@@€@ @À@àAAA ÿÿÿÿA@?ð@@@@@@@ @"@$ÿÿÿÿÿÿÿÿ@(abcdefghijklmFTFFTTFFFTTFLp	
X
	
X
	
X
?€@@@@€@ @À@àAAA A0ÿÿÿÿAP?ð@@@@@@@ @"@$@&ÿÿÿÿÿÿÿÿ@*abcdefghijklmnFTFFTTFFFTTTFLp	
X	
X	
X?€@@@@€@ @À@àAAA A0A@ÿÿÿÿA`?ð@@@@@@@ @"@$@&@(ÿÿÿÿÿÿÿÿ@,abcdefghijklmnoFTFFTTFFFTTTFFLp	

X	

X	

X?€@@@@€@ @À@àAAA A0A@APÿÿÿÿAp?ð@@@@@@@ @"@$@&@(@*ÿÿÿÿÿÿÿÿ@.abcdefghijklmnopFTFFTTFFFTTTFFFLp	

X	

X	

X?€@@@@€@ @À@àAAA A0A@APA`ÿÿÿÿA€?ð@@@@@@@ @"@$@&@(@*@,ÿÿÿÿÿÿÿÿ@0abcdefghijklmnopqFTFFTTFFFTTTFFFTLp€	

X	

X	

X?€@@@@€@ @À@àAAA A0A@APA`ApÿÿÿÿAˆ?ð@@@@@@@ @"@$@&@(@*@,@.ÿÿÿÿÿÿÿÿ@1abcdefghijklmnopqrFTFFTTFFFTTTFFFFTLpÀ	

X	

X	

X?€@@@@€@ @À@àAAA A0A@APA`ApA€ÿÿÿÿA?ð@@@@@@@ @"@$@&@(@*@,@.@0ÿÿÿÿÿÿÿÿ@2abcdefghijklmnopqrsFTFFTTFFFTTTFFFFTTLpà	

X	

X	

X?€@@@@€@ @À@àAAA A0A@APA`ApA€AˆÿÿÿÿA˜?ð@@@@@@@ @"@$@&@(@*@,@.@0@1ÿÿÿÿÿÿÿÿ@3abcdefghijklmnopqrstFTFFTTFFFTTTFFFFTTTLpð	

X	

X	

X?€@@@@€@ @À@àAAA A0A@APA`ApA€AˆAÿÿÿÿA ?ð@@@@@@@ @"@$@&@(@*@,@.@0@1@2ÿÿÿÿÿÿÿÿ@4XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   32 / number of bits per data pixel                  NAXIS   =                    2 / number of data axes                            NAXIS1  =                   10 / length of data axis 1                          NAXIS2  =                    2 / length of data axis 2                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     CRVAL1  =     4.5830000000E+01 / comment                                        CRVAL2  =     6.3570000000E+01 / comment                                        CRPIX1  =     2.5600000000E+02 / comment                                        CRPIX2  =     2.5700000000E+02 / comment                                        CDELT1  =    -2.7777700000E-03 / comment                                        CDELT2  =     2.7777700000E-03 / comment                                        CTYPE1  = 'RA---TAN'           / comment                                        CTYPE2  = 'DEC--TAN'           / comment                                        END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
XTENSION= 'TABLE   '           / ASCII table extension                          BITPIX  =                    8 / 8-bit ASCII characters                         NAXIS   =                    2 / 2-dimensional ASCII table                      NAXIS1  =                   80 / width of table in characters                   NAXIS2  =                   11 / number of rows in table                        PCOUNT  =                    0 / no group parameters (required keyword)         GCOUNT  =                    1 / one data group (required keyword)              TFIELDS =                    5 / number of fields in each row                   TTYPE1  = 'Name    '           / label for field   1                            TBCOL1  =                    1 / beginning column of field   1                  TFORM1  = 'A15     '           / Fortran-77 format of field                     TTYPE2  = 'Ivalue  '           / label for field   2                            TBCOL2  =                   17 / beginning column of field   2                  TFORM2  = 'I11     '           / Fortran-77 format of field                     TUNIT2  = 'm**2    '           / physical unit of field                         TTYPE3  = 'Fvalue  '           / label for field   3                            TBCOL3  =                   29 / beginning column of field   3                  TFORM3  = 'F15.6   '           / Fortran-77 format of field                     TUNIT3  = 'cm      '           / physical unit of field                         TTYPE4  = 'Evalue  '           / label for field   4                            TBCOL4  =                   45 / beginning column of field   4                  TFORM4  = 'E13.5   '           / Fortran-77 format of field                     TUNIT4  = 'erg/s   '           / physical unit of field                         TTYPE5  = 'Dvalue  '           / label for field   5                            TBCOL5  =                   59 / beginning column of field   5                  TFORM5  = 'D22.14  '           / Fortran-77 format of field                     TUNIT5  = 'km/s    '           / physical unit of field                         EXTNAME = 'new_table'          / name of this ASCII table extension             END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             first string              0        0.000000   0.00000E+00   0.00000000000000E+00second string             3        3.000000   3.00000E+00   3.00000000000000E+00                          6        6.000000   6.00000E+00   6.00000000000000E+00                          9        9.000000   9.00000E+00   9.00000000000000E+00                         12       12.000000   1.20000E+01   1.20000000000000E+01                         15       15.000000   1.50000E+01   1.50000000000000E+01                         18       18.000000   1.80000E+01   1.80000000000000E+01                         21       21.000000   2.10000E+01   2.10000000000000E+01                         24       24.000000   2.40000E+01   2.40000000000000E+01                         27       27.000000   2.70000E+01   2.70000000000000E+01                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                cfitsio/testprog.c0000644000225700000360000024765613246025103014037 0ustar  cagordonlhea#include 
#include 
#include "fitsio.h"
int main(void);

int main()
{
/*  
    This is a big and complicated program that tests most of
    the cfitsio routines.  This code does not represent
    the most efficient method of reading or writing FITS files 
    because this code is primarily designed to stress the cfitsio
    library routines.
*/
    char asciisum[17];
    unsigned long checksum, datsum;
    int datastatus, hdustatus, filemode;
    int status, simple, bitpix, naxis, extend, hdutype, hdunum, tfields;
    long ii, jj, extvers;
    int nkeys, nfound, colnum, typecode, signval,nmsg;
    char cval, cvalstr[2];
    long repeat, offset, width, jnulval;
    int anynull;
/*    float vers;   */
    unsigned char xinarray[21], binarray[21], boutarray[21], bnul;
    short         iinarray[21], ioutarray[21], inul;
    int           kinarray[21], koutarray[21], knul;
    long          jinarray[21], joutarray[21], jnul;
    float         einarray[21], eoutarray[21], enul, cinarray[42];
    double        dinarray[21], doutarray[21], dnul, minarray[42];
    double scale, zero;
    long naxes[3], pcount, gcount, npixels, nrows, rowlen, firstpix[3];
    int existkeys, morekeys, keynum;

    char larray[42], larray2[42], colname[70], tdisp[40], nulstr[40];
    char oskey[] = "value_string";
    char iskey[21];
    int olkey = 1;
    int ilkey;
    short oshtkey, ishtkey;
    long ojkey = 11, ijkey;
    long otint = 12345678;
    float ofkey = 12.121212f;
    float oekey = 13.131313f, iekey;
    double ogkey = 14.1414141414141414;
    double odkey = 15.1515151515151515, idkey;
    double otfrac = .1234567890123456;

    double xrval,yrval,xrpix,yrpix,xinc,yinc,rot,xpos,ypos,xpix,ypix;
    char xcoordtype[] = "RA---TAN";
    char ycoordtype[] = "DEC--TAN";
    char ctype[5];

    char *lsptr;    /* pointer to long string value */
    char  comm[73];
    char *comms[3];
    char *inskey[21];
    char *onskey[3] = {"first string", "second string", "        "};
    char *inclist[2] = {"key*", "newikys"};
    char *exclist[2] = {"key_pr*", "key_pkls"};

    int   onlkey[3] = {1, 0, 1}, inlkey[3];
    long  onjkey[3] = {11, 12, 13}, injkey[3];
    float onfkey[3] = {12.121212f, 13.131313f, 14.141414f};
    float onekey[3] = {13.131313f, 14.141414f, 15.151515f}, inekey[3];
    double ongkey[3] = {14.1414141414141414, 15.1515151515151515,
           16.1616161616161616};
    double ondkey[3] = {15.1515151515151515, 16.1616161616161616,
           17.1717171717171717}, indkey[3];

    long tbcol[5] = {1, 17, 28, 43, 56};

    char filename[40], card[FLEN_CARD], card2[FLEN_CARD];
    char keyword[FLEN_KEYWORD];
    char value[FLEN_VALUE], comment[FLEN_COMMENT];
    unsigned char uchars[80];

    fitsfile *fptr, *tmpfptr;
    char *ttype[10], *tform[10], *tunit[10];
    char tblname[40];
    char binname[] = "Test-BINTABLE";
    char templt[] = "testprog.tpt";
    char errmsg[FLEN_ERRMSG];
    short imgarray[30][19], imgarray2[20][10];
    long fpixels[2], lpixels[2], inc[2];

    status = 0;
    strcpy(tblname, "Test-ASCII");

/*    ffvers(&vers); 
    printf("CFITSIO TESTPROG, v%.3f\n\n",vers);
*/
    printf("CFITSIO TESTPROG\n\n");
    printf("Try opening then closing a nonexistent file:\n");
    fits_open_file(&fptr, "tq123x.kjl", READWRITE, &status);
    printf("  ffopen fptr, status  = %lu %d (expect an error)\n", 
           (unsigned long) fptr, status);
    ffclos(fptr, &status);
    printf("  ffclos status = %d\n\n", status);
    ffcmsg();
    status = 0;

    for (ii = 0; ii < 21; ii++)  /* allocate space for string column value */
        inskey[ii] = (char *) malloc(21);   

    for (ii = 0; ii < 10; ii++)
    {
      ttype[ii] = (char *) malloc(20);
      tform[ii] = (char *) malloc(20);
      tunit[ii] = (char *) malloc(20);
    }

    comms[0] = comm;

    /* delete previous version of the file, if it exists (with ! prefix) */
    strcpy(filename, "!testprog.fit");

    status = 0;

    /*
      #####################
      #  create FITS file #
      #####################
    */

    ffinit(&fptr, filename, &status);
    printf("ffinit create new file status = %d\n", status);
    if (status)
        goto errstatus;

    filename[0] = '\0';
    ffflnm(fptr, filename, &status);

    ffflmd(fptr, &filemode, &status);
    printf("Name of file = %s, I/O mode = %d\n", filename, filemode);
    simple = 1;
    bitpix = 32;
    naxis = 2;
    naxes[0] = 10;
    naxes[1] = 2;
    npixels = 20;
    pcount = 0;
    gcount = 1;
    extend = 1;
    /*
      ############################
      #  write single keywords   #
      ############################
    */

    if (ffphps(fptr, bitpix, naxis, naxes, &status) > 0)
        printf("ffphps status = %d\n", status);

    if (ffprec(fptr, 
    "key_prec= 'This keyword was written by fxprec' / comment goes here", 
     &status) > 0 )
        printf("ffprec status = %d\n", status);

    printf("\ntest writing of long string keywords:\n");
    strcpy(card, "1234567890123456789012345678901234567890");
    strcat(card, "12345678901234567890123456789012345");
    ffpkys(fptr, "card1", card, "", &status);
    ffgkey(fptr, "card1", card2, comment, &status);
    printf(" %s\n%s\n", card, card2);
    
    strcpy(card, "1234567890123456789012345678901234567890");
    strcat(card, "123456789012345678901234'6789012345");
    ffpkys(fptr, "card2", card, "", &status);
    ffgkey(fptr, "card2", card2, comment, &status);
    printf(" %s\n%s\n", card, card2);
    
    strcpy(card, "1234567890123456789012345678901234567890");
    strcat(card, "123456789012345678901234''789012345");
    ffpkys(fptr, "card3", card, "", &status);
    ffgkey(fptr, "card3", card2, comment, &status);
    printf(" %s\n%s\n", card, card2);
    
    strcpy(card, "1234567890123456789012345678901234567890");
    strcat(card, "123456789012345678901234567'9012345");
    ffpkys(fptr, "card4", card, "", &status);
    ffgkey(fptr, "card4", card2, comment, &status);
    printf(" %s\n%s\n", card, card2);
    
    if (ffpkys(fptr, "key_pkys", oskey, "fxpkys comment", &status) > 0)
        printf("ffpkys status = %d\n", status);

    if (ffpkyl(fptr, "key_pkyl", olkey, "fxpkyl comment", &status) > 0)
        printf("ffpkyl status = %d\n", status);

    if (ffpkyj(fptr, "key_pkyj", ojkey, "fxpkyj comment", &status) > 0)
        printf("ffpkyj status = %d\n", status);

    if (ffpkyf(fptr, "key_pkyf", ofkey, 5, "fxpkyf comment", &status) > 0)
        printf("ffpkyf status = %d\n", status);

    if (ffpkye(fptr, "key_pkye", oekey, 6, "fxpkye comment", &status) > 0)
        printf("ffpkye status = %d\n", status);

    if (ffpkyg(fptr, "key_pkyg", ogkey, 14, "fxpkyg comment", &status) > 0)
        printf("ffpkyg status = %d\n", status);

    if (ffpkyd(fptr, "key_pkyd", odkey, 14, "fxpkyd comment", &status) > 0)
        printf("ffpkyd status = %d\n", status);

    if (ffpkyc(fptr, "key_pkyc", onekey, 6, "fxpkyc comment", &status) > 0)
        printf("ffpkyc status = %d\n", status);

    if (ffpkym(fptr, "key_pkym", ondkey, 14, "fxpkym comment", &status) > 0)
        printf("ffpkym status = %d\n", status);

    if (ffpkfc(fptr, "key_pkfc", onekey, 6, "fxpkfc comment", &status) > 0)
        printf("ffpkfc status = %d\n", status);

    if (ffpkfm(fptr, "key_pkfm", ondkey, 14, "fxpkfm comment", &status) > 0)
        printf("ffpkfm status = %d\n", status);

    if (ffpkls(fptr, "key_pkls", 
"This is a very long string value that is continued over more than one keyword.",
     "fxpkls comment", &status) > 0)
        printf("ffpkls status = %d\n", status);

    if (ffplsw(fptr, &status) > 0 )
        printf("ffplsw status = %d\n", status);

    if (ffpkyt(fptr, "key_pkyt", otint, otfrac, "fxpkyt comment", &status) > 0)
        printf("ffpkyt status = %d\n", status);

    if (ffpcom(fptr, "  This keyword was written by fxpcom.", &status) > 0)
        printf("ffpcom status = %d\n", status);

    if (ffphis(fptr, "    This keyword written by fxphis (w/ 2 leading spaces).",
        &status) > 0)
        printf("ffphis status = %d\n", status);

    if (ffpdat(fptr, &status) > 0)
    {
        printf("ffpdat status = %d\n", status);
        goto errstatus;
    }

    /*
      ###############################
      #  write arrays of keywords   #
      ###############################
    */
    nkeys = 3;

    comms[0] = comm;  /* use the inskey array of pointers for the comments */

    strcpy(comm, "fxpkns comment&");
    if (ffpkns(fptr, "ky_pkns", 1, nkeys, onskey, comms, &status) > 0)
        printf("ffpkns status = %d\n", status);

    strcpy(comm, "fxpknl comment&");
    if (ffpknl(fptr, "ky_pknl", 1, nkeys, onlkey, comms, &status) > 0)
        printf("ffpknl status = %d\n", status);

    strcpy(comm, "fxpknj comment&");
    if (ffpknj(fptr, "ky_pknj", 1, nkeys, onjkey, comms, &status) > 0)
        printf("ffpknj status = %d\n", status);

    strcpy(comm, "fxpknf comment&");
    if (ffpknf(fptr, "ky_pknf", 1, nkeys, onfkey, 5, comms, &status) > 0)
        printf("ffpknf status = %d\n", status);

    strcpy(comm, "fxpkne comment&");
    if (ffpkne(fptr, "ky_pkne", 1, nkeys, onekey, 6, comms, &status) > 0)
        printf("ffpkne status = %d\n", status);

    strcpy(comm, "fxpkng comment&");
    if (ffpkng(fptr, "ky_pkng", 1, nkeys, ongkey, 13, comms, &status) > 0)
        printf("ffpkng status = %d\n", status);

    strcpy(comm, "fxpknd comment&");
    if (ffpknd(fptr, "ky_pknd", 1, nkeys, ondkey, 14, comms, &status) > 0)
    {
        printf("ffpknd status = %d\n", status);
        goto errstatus;
    }
    /*
      ############################
      #  write generic keywords  #
      ############################
    */

    strcpy(oskey, "1");
    if (ffpky(fptr, TSTRING, "tstring", oskey, "tstring comment", &status) > 0)
        printf("ffpky status = %d\n", status);

    olkey = TLOGICAL;
    if (ffpky(fptr, TLOGICAL, "tlogical", &olkey, "tlogical comment",
        &status) > 0)
        printf("ffpky status = %d\n", status);

    cval = TBYTE;
    if (ffpky(fptr, TBYTE, "tbyte", &cval, "tbyte comment", &status) > 0)
        printf("ffpky status = %d\n", status);

    oshtkey = TSHORT;
    if (ffpky(fptr, TSHORT, "tshort", &oshtkey, "tshort comment", &status) > 0)
        printf("ffpky status = %d\n", status);

    olkey = TINT;
    if (ffpky(fptr, TINT, "tint", &olkey, "tint comment", &status) > 0)
        printf("ffpky status = %d\n", status);

    ojkey = TLONG;
    if (ffpky(fptr, TLONG, "tlong", &ojkey, "tlong comment", &status) > 0)
        printf("ffpky status = %d\n", status);

    oekey = TFLOAT;
    if (ffpky(fptr, TFLOAT, "tfloat", &oekey, "tfloat comment", &status) > 0)
        printf("ffpky status = %d\n", status);

    odkey = TDOUBLE;
    if (ffpky(fptr, TDOUBLE, "tdouble", &odkey, "tdouble comment",
              &status) > 0)
        printf("ffpky status = %d\n", status);

    /*
      ############################
      #  write data              #
      ############################
    */
    /* define the null value (must do this before writing any data) */
    if (ffpkyj(fptr, "BLANK", -99, "value to use for undefined pixels",
       &status) > 0)
        printf("BLANK keyword status = %d\n", status);

    /* initialize arrays of values to write to primary array */
    for (ii = 0; ii < npixels; ii++)
    {
        boutarray[ii] = (unsigned char) (ii + 1);
        ioutarray[ii] = (short) (ii + 1);
        joutarray[ii] = ii + 1;
        eoutarray[ii] = (float) (ii + 1);
        doutarray[ii] = ii + 1;
    }

    /* write a few pixels with each datatype */
    /* set the last value in each group of 4 as undefined */

/*
    ffpprb(fptr, 1,  1, 2, &boutarray[0],  &status);
    ffppri(fptr, 1,  5, 2, &ioutarray[4],  &status);
    ffpprj(fptr, 1,  9, 2, &joutarray[8],  &status);
    ffppre(fptr, 1, 13, 2, &eoutarray[12], &status);
    ffpprd(fptr, 1, 17, 2, &doutarray[16], &status);
*/

/*  test the newer ffpx routine, instead of the older ffppr_ routines */
    firstpix[0]=1;
    firstpix[1]=1;
    ffppx(fptr, TBYTE, firstpix, 2, &boutarray[0],  &status);
    firstpix[0]=5;
    ffppx(fptr, TSHORT, firstpix, 2, &ioutarray[4],  &status);
    firstpix[0]=9;
    ffppx(fptr, TLONG, firstpix, 2, &joutarray[8],  &status);
    firstpix[0]=3;
    firstpix[1]=2;
    ffppx(fptr, TFLOAT, firstpix, 2, &eoutarray[12],  &status);
    firstpix[0]=7;
    ffppx(fptr, TDOUBLE, firstpix, 2, &doutarray[16],  &status);

/*
    ffppnb(fptr, 1,  3, 2, &boutarray[2],   4, &status);
    ffppni(fptr, 1,  7, 2, &ioutarray[6],   8, &status);
    ffppnj(fptr, 1, 11, 2, &joutarray[10],  12, &status);
    ffppne(fptr, 1, 15, 2, &eoutarray[14], 16., &status);
    ffppnd(fptr, 1, 19, 2, &doutarray[18], 20., &status);
*/
    firstpix[0]=3;
    firstpix[1]=1;
    bnul = 4;
    ffppxn(fptr, TBYTE, firstpix, 2, &boutarray[2], &bnul,  &status);
    firstpix[0]=7;
    inul = 8;
    ffppxn(fptr, TSHORT, firstpix, 2, &ioutarray[6], &inul, &status);
    firstpix[0]=1;
    firstpix[1]=2;
    jnul = 12;
    ffppxn(fptr, TLONG, firstpix, 2, &joutarray[10], &jnul, &status);
    firstpix[0]=5;
    enul = 16.;
    ffppxn(fptr, TFLOAT, firstpix, 2, &eoutarray[14], &enul,  &status);
    firstpix[0]=9;
    dnul = 20.;
    ffppxn(fptr, TDOUBLE, firstpix, 2, &doutarray[18], &dnul, &status);

    ffppru(fptr, 1, 1, 1, &status);


    if (status > 0)
    {
        printf("ffppnx status = %d\n", status);
        goto errstatus;
    }

    ffflus(fptr, &status);   /* flush all data to the disk file */ 
    printf("ffflus status = %d\n", status);
    printf("HDU number = %d\n", ffghdn(fptr, &hdunum));

    /*
      ############################
      #  read data               #
      ############################
    */
    /* read back the data, setting null values = 99 */
    printf("\nValues read back from primary array (99 = null pixel)\n");
    printf("The 1st, and every 4th pixel should be undefined:\n");

    anynull = 0;
    ffgpvb(fptr, 1,  1, 10, 99, binarray, &anynull, &status); 

    ffgpvb(fptr, 1, 11, 10, 99, &binarray[10], &anynull, &status);

    for (ii = 0; ii < npixels; ii++)
        printf(" %2d", binarray[ii]);
    printf("  %d (ffgpvb)\n", anynull);  

    ffgpvi(fptr, 1, 1, npixels, 99,   iinarray, &anynull, &status);

    for (ii = 0; ii < npixels; ii++)
        printf(" %2d", iinarray[ii]);
    printf("  %d (ffgpvi)\n", anynull);  

    ffgpvj(fptr, 1, 1, npixels, 99,  jinarray, &anynull, &status);

    for (ii = 0; ii < npixels; ii++)
        printf(" %2ld", jinarray[ii]);
    printf("  %d (ffgpvj)\n", anynull);  

    ffgpve(fptr, 1, 1, npixels, 99., einarray, &anynull, &status);

    for (ii = 0; ii < npixels; ii++)
        printf(" %2.0f", einarray[ii]);
    printf("  %d (ffgpve)\n", anynull);  

    ffgpvd(fptr, 1,  1, 10, 99.,  dinarray, &anynull, &status);
    ffgpvd(fptr, 1, 11, 10, 99.,  &dinarray[10], &anynull, &status);

    for (ii = 0; ii < npixels; ii++)
        printf(" %2.0f", dinarray[ii]);
    printf("  %d (ffgpvd)\n", anynull);  

    if (status > 0)
    {
        printf("ERROR: ffgpv_ status = %d\n", status);
        goto errstatus;
    }
    if (anynull == 0)
       printf("ERROR: ffgpv_ did not detect null values\n");

    /* reset the output null value to the expected input value */
    for (ii = 3; ii < npixels; ii += 4)
    {
        boutarray[ii] = 99;
        ioutarray[ii] = 99;
        joutarray[ii] = 99;
        eoutarray[ii] = 99.;
        doutarray[ii] = 99.;
    }
        ii = 0;
        boutarray[ii] = 99;
        ioutarray[ii] = 99;
        joutarray[ii] = 99;
        eoutarray[ii] = 99.;
        doutarray[ii] = 99.;

    /* compare the output with the input; flag any differences */
    for (ii = 0; ii < npixels; ii++)
    {
       if (boutarray[ii] != binarray[ii])
           printf("bout != bin = %u %u \n", boutarray[ii], binarray[ii]);

       if (ioutarray[ii] != iinarray[ii])
           printf("iout != iin = %d %d \n", ioutarray[ii], iinarray[ii]);

       if (joutarray[ii] != jinarray[ii])
           printf("jout != jin = %ld %ld \n", joutarray[ii], jinarray[ii]);

       if (eoutarray[ii] != einarray[ii])
           printf("eout != ein = %f %f \n", eoutarray[ii], einarray[ii]);

       if (doutarray[ii] != dinarray[ii])
           printf("dout != din = %f %f \n", doutarray[ii], dinarray[ii]);
    }

    for (ii = 0; ii < npixels; ii++)
    {
      binarray[ii] = 0;
      iinarray[ii] = 0;
      jinarray[ii] = 0;
      einarray[ii] = 0.;
      dinarray[ii] = 0.;
    }

    anynull = 0;
    ffgpfb(fptr, 1,  1, 10, binarray, larray, &anynull, &status);
    ffgpfb(fptr, 1, 11, 10, &binarray[10], &larray[10], &anynull, &status);

    for (ii = 0; ii < npixels; ii++)
      if (larray[ii])
        printf("  *");
      else
        printf(" %2d", binarray[ii]);
    printf("  %d (ffgpfb)\n", anynull);  

    ffgpfi(fptr, 1, 1, npixels, iinarray, larray, &anynull, &status);

    for (ii = 0; ii < npixels; ii++)
      if (larray[ii])
        printf("  *");
      else
        printf(" %2d", iinarray[ii]);
    printf("  %d (ffgpfi)\n", anynull);  

    ffgpfj(fptr, 1, 1, npixels, jinarray, larray, &anynull, &status);

    for (ii = 0; ii < npixels; ii++)
      if (larray[ii])
        printf("  *");
      else
        printf(" %2ld", jinarray[ii]);
    printf("  %d (ffgpfj)\n", anynull);  

    ffgpfe(fptr, 1, 1, npixels, einarray, larray, &anynull, &status);

    for (ii = 0; ii < npixels; ii++)
      if (larray[ii])
        printf("  *");
      else
        printf(" %2.0f", einarray[ii]);
    printf("  %d (ffgpfe)\n", anynull);  

    ffgpfd(fptr, 1,  1, 10, dinarray, larray, &anynull, &status);
    ffgpfd(fptr, 1, 11, 10, &dinarray[10], &larray[10], &anynull, &status);

    for (ii = 0; ii < npixels; ii++)
      if (larray[ii])
        printf("  *");
      else
        printf(" %2.0f", dinarray[ii]);
    printf("  %d (ffgpfd)\n", anynull);  

    if (status > 0)
    {
        printf("ERROR: ffgpf_ status = %d\n", status);
        goto errstatus;
    }
    if (anynull == 0)
       printf("ERROR: ffgpf_ did not detect null values\n");


    /*
      ##########################################
      #  close and reopen file multiple times  #
      ##########################################
    */

    for (ii = 0; ii < 10; ii++)
    {
      if (ffclos(fptr, &status) > 0)
      {
        printf("ERROR in ftclos (1) = %d", status);
        goto errstatus;
      }

      if (fits_open_file(&fptr, filename, READWRITE, &status) > 0)
      {
        printf("ERROR: ffopen open file status = %d\n", status);
        goto errstatus;
      }
    }
    printf("\nClosed then reopened the FITS file 10 times.\n");
    printf("HDU number = %d\n", ffghdn(fptr, &hdunum));

    filename[0] = '\0';
    ffflnm(fptr, filename, &status);

    ffflmd(fptr, &filemode, &status);
    printf("Name of file = %s, I/O mode = %d\n", filename, filemode);

    /*
      ############################
      #  read single keywords    #
      ############################
    */

    simple = 0;
    bitpix = 0;
    naxis = 0;
    naxes[0] = 0;
    naxes[1] = 0;
    pcount = -99;
    gcount =  -99;
    extend = -99;
    printf("\nRead back keywords:\n");
    ffghpr(fptr, 99, &simple, &bitpix, &naxis, naxes, &pcount,
           &gcount, &extend, &status);
    printf("simple = %d, bitpix = %d, naxis = %d, naxes = (%ld, %ld)\n",
           simple, bitpix, naxis, naxes[0], naxes[1]);
    printf("  pcount = %ld, gcount = %ld, extend = %d\n",
               pcount, gcount, extend);

    ffgrec(fptr, 9, card, &status);
    printf("%s\n", card);
    if (strncmp(card, "KEY_PREC= 'This", 15) )
       printf("ERROR in ffgrec\n");

    ffgkyn(fptr, 9, keyword, value, comment, &status);
    printf("%s : %s : %s :\n",keyword, value, comment);
    if (strncmp(keyword, "KEY_PREC", 8) )
       printf("ERROR in ffgkyn: %s\n", keyword);

    ffgcrd(fptr, keyword, card, &status);
    printf("%s\n", card);

    if (strncmp(keyword, card, 8) )
       printf("ERROR in ffgcrd: %s\n", keyword);

    ffgkey(fptr, "KY_PKNS1", value, comment, &status);
    printf("KY_PKNS1 : %s : %s :\n", value, comment);

    if (strncmp(value, "'first string'", 14) )
       printf("ERROR in ffgkey: %s\n", value);

    ffgkys(fptr, "key_pkys", iskey, comment, &status);
    printf("KEY_PKYS %s %s %d\n", iskey, comment, status);

    ffgkyl(fptr, "key_pkyl", &ilkey, comment, &status);
    printf("KEY_PKYL %d %s %d\n", ilkey, comment, status);

    ffgkyj(fptr, "KEY_PKYJ", &ijkey, comment, &status);
    printf("KEY_PKYJ %ld %s %d\n",ijkey, comment, status);

    ffgkye(fptr, "KEY_PKYJ", &iekey, comment, &status);
    printf("KEY_PKYJ %f %s %d\n",iekey, comment, status);

    ffgkyd(fptr, "KEY_PKYJ", &idkey, comment, &status);
    printf("KEY_PKYJ %f %s %d\n",idkey, comment, status);

    if (ijkey != 11 || iekey != 11. || idkey != 11.)
       printf("ERROR in ffgky[jed]: %ld, %f, %f\n",ijkey, iekey, idkey);

    iskey[0] = '\0';
    ffgky(fptr, TSTRING, "key_pkys", iskey, comment, &status);
    printf("KEY_PKY S %s %s %d\n", iskey, comment, status);

    ilkey = 0;
    ffgky(fptr, TLOGICAL, "key_pkyl", &ilkey, comment, &status);
    printf("KEY_PKY L %d %s %d\n", ilkey, comment, status);

    ffgky(fptr, TBYTE, "KEY_PKYJ", &cval, comment, &status);
    printf("KEY_PKY BYTE %d %s %d\n",cval, comment, status);

    ffgky(fptr, TSHORT, "KEY_PKYJ", &ishtkey, comment, &status);
    printf("KEY_PKY SHORT %d %s %d\n",ishtkey, comment, status);

    ffgky(fptr, TINT, "KEY_PKYJ", &ilkey, comment, &status);
    printf("KEY_PKY INT %d %s %d\n",ilkey, comment, status);

    ijkey = 0;
    ffgky(fptr, TLONG, "KEY_PKYJ", &ijkey, comment, &status);
    printf("KEY_PKY J %ld %s %d\n",ijkey, comment, status);

    iekey = 0;
    ffgky(fptr, TFLOAT, "KEY_PKYE", &iekey, comment, &status);
    printf("KEY_PKY E %f %s %d\n",iekey, comment, status);

    idkey = 0;
    ffgky(fptr, TDOUBLE, "KEY_PKYD", &idkey, comment, &status);
    printf("KEY_PKY D %f %s %d\n",idkey, comment, status);

    ffgkyd(fptr, "KEY_PKYF", &idkey, comment, &status);
    printf("KEY_PKYF %f %s %d\n",idkey, comment, status);

    ffgkyd(fptr, "KEY_PKYE", &idkey, comment, &status);
    printf("KEY_PKYE %f %s %d\n",idkey, comment, status);

    ffgkyd(fptr, "KEY_PKYG", &idkey, comment, &status);
    printf("KEY_PKYG %.14f %s %d\n",idkey, comment, status);

    ffgkyd(fptr, "KEY_PKYD", &idkey, comment, &status);
    printf("KEY_PKYD %.14f %s %d\n",idkey, comment, status);

    ffgkyc(fptr, "KEY_PKYC", inekey, comment, &status);
    printf("KEY_PKYC %f %f %s %d\n",inekey[0], inekey[1], comment, status);

    ffgkyc(fptr, "KEY_PKFC", inekey, comment, &status);
    printf("KEY_PKFC %f %f %s %d\n",inekey[0], inekey[1], comment, status);

    ffgkym(fptr, "KEY_PKYM", indkey, comment, &status);
    printf("KEY_PKYM %f %f %s %d\n",indkey[0], indkey[1], comment, status);

    ffgkym(fptr, "KEY_PKFM", indkey, comment, &status);
    printf("KEY_PKFM %f %f %s %d\n",indkey[0], indkey[1], comment, status);

    ffgkyt(fptr, "KEY_PKYT", &ijkey, &idkey, comment, &status);
    printf("KEY_PKYT %ld %.14f %s %d\n",ijkey, idkey, comment, status);

    ffpunt(fptr, "KEY_PKYJ", "km/s/Mpc", &status);
    ijkey = 0;
    ffgky(fptr, TLONG, "KEY_PKYJ", &ijkey, comment, &status);
    printf("KEY_PKY J %ld %s %d\n",ijkey, comment, status);
    ffgunt(fptr,"KEY_PKYJ", comment, &status);
    printf("KEY_PKY units = %s\n",comment);

    ffpunt(fptr, "KEY_PKYJ", "", &status);
    ijkey = 0;
    ffgky(fptr, TLONG, "KEY_PKYJ", &ijkey, comment, &status);
    printf("KEY_PKY J %ld %s %d\n",ijkey, comment, status);
    ffgunt(fptr,"KEY_PKYJ", comment, &status);
    printf("KEY_PKY units = %s\n",comment);

    ffpunt(fptr, "KEY_PKYJ", "feet/second/second", &status);
    ijkey = 0;
    ffgky(fptr, TLONG, "KEY_PKYJ", &ijkey, comment, &status);
    printf("KEY_PKY J %ld %s %d\n",ijkey, comment, status);
    ffgunt(fptr,"KEY_PKYJ", comment, &status);
    printf("KEY_PKY units = %s\n",comment);

    ffgkls(fptr, "key_pkls", &lsptr, comment, &status);
    printf("KEY_PKLS long string value = \n%s\n", lsptr);

    /* free the memory for the long string value */
    fits_free_memory(lsptr, &status);

    /* get size and position in header */
    ffghps(fptr, &existkeys, &keynum, &status);
    printf("header contains %d keywords; located at keyword %d \n",existkeys,
            keynum);

    /*
      ############################
      #  read array keywords     #
      ############################
    */
    ffgkns(fptr, "ky_pkns", 1, 3, inskey, &nfound, &status);
    printf("ffgkns:  %s, %s, %s\n", inskey[0], inskey[1], inskey[2]);
    if (nfound != 3 || status > 0)
       printf("\nERROR in ffgkns %d, %d\n", nfound, status);

    ffgknl(fptr, "ky_pknl", 1, 3, inlkey, &nfound, &status);
    printf("ffgknl:  %d, %d, %d\n", inlkey[0], inlkey[1], inlkey[2]);
    if (nfound != 3 || status > 0)
       printf("\nERROR in ffgknl %d, %d\n", nfound, status);

    ffgknj(fptr, "ky_pknj", 1, 3, injkey, &nfound, &status);
    printf("ffgknj:  %ld, %ld, %ld\n", injkey[0], injkey[1], injkey[2]);
    if (nfound != 3 || status > 0)
       printf("\nERROR in ffgknj %d, %d\n", nfound, status);

    ffgkne(fptr, "ky_pkne", 1, 3, inekey, &nfound, &status);
    printf("ffgkne:  %f, %f, %f\n", inekey[0], inekey[1], inekey[2]);
    if (nfound != 3 || status > 0)
       printf("\nERROR in ffgkne %d, %d\n", nfound, status);

    ffgknd(fptr, "ky_pknd", 1, 3, indkey, &nfound, &status);
    printf("ffgknd:  %f, %f, %f\n", indkey[0], indkey[1], indkey[2]);
    if (nfound != 3 || status > 0)
       printf("\nERROR in ffgknd %d, %d\n", nfound, status);

    /* get position of HISTORY keyword for subsequent deletes and inserts */
    ffgcrd(fptr, "HISTORY", card, &status);
    ffghps(fptr, &existkeys, &keynum, &status);
    keynum -= 2;

    printf("\nBefore deleting the HISTORY and DATE keywords...\n");
    for (ii = keynum; ii <= keynum + 3; ii++)
    {
        ffgrec(fptr, ii, card, &status);
        printf("%.8s\n", card);  /* don't print date value, so that */
    }                            /* the output will always be the same */
    /*
      ############################
      #  delete keywords         #
      ############################
    */

    ffdrec(fptr, keynum + 1, &status);
    ffdkey(fptr, "DATE", &status);

    printf("\nAfter deleting the keywords...\n");
    for (ii = keynum; ii <= keynum + 1; ii++)
    {
        ffgrec(fptr, ii, card, &status);
        printf("%s\n", card);
    }

    if (status > 0)
       printf("\nERROR deleting keywords\n");
    /*
      ############################
      #  insert keywords         #
      ############################
    */
    keynum += 4;
    ffirec(fptr, keynum - 3, "KY_IREC = 'This keyword inserted by fxirec'",
           &status);
    ffikys(fptr, "KY_IKYS", "insert_value_string", "ikys comment", &status);
    ffikyj(fptr, "KY_IKYJ", 49, "ikyj comment", &status);
    ffikyl(fptr, "KY_IKYL", 1, "ikyl comment", &status);
    ffikye(fptr, "KY_IKYE", 12.3456f, 4, "ikye comment", &status);
    ffikyd(fptr, "KY_IKYD", 12.345678901234567, 14, "ikyd comment", &status);
    ffikyf(fptr, "KY_IKYF", 12.3456f, 4, "ikyf comment", &status);
    ffikyg(fptr, "KY_IKYG", 12.345678901234567, 13, "ikyg comment", &status);

    printf("\nAfter inserting the keywords...\n");
    for (ii = keynum - 4; ii <= keynum + 5; ii++)
    {
        ffgrec(fptr, ii, card, &status);
        printf("%s\n", card);
    }

    if (status > 0)
       printf("\nERROR inserting keywords\n");
    /*
      ############################
      #  modify keywords         #
      ############################
    */
    ffmrec(fptr, keynum - 4, "COMMENT   This keyword was modified by fxmrec", &status);
    ffmcrd(fptr, "KY_IREC", "KY_MREC = 'This keyword was modified by fxmcrd'",
            &status);
    ffmnam(fptr, "KY_IKYS", "NEWIKYS", &status);

    ffmcom(fptr, "KY_IKYJ","This is a modified comment", &status);
    ffmkyj(fptr, "KY_IKYJ", 50, "&", &status);
    ffmkyl(fptr, "KY_IKYL", 0, "&", &status);
    ffmkys(fptr, "NEWIKYS", "modified_string", "&", &status);
    ffmkye(fptr, "KY_IKYE", -12.3456f, 4, "&", &status);
    ffmkyd(fptr, "KY_IKYD", -12.345678901234567, 14, "modified comment",
            &status);
    ffmkyf(fptr, "KY_IKYF", -12.3456f, 4, "&", &status);
    ffmkyg(fptr, "KY_IKYG", -12.345678901234567, 13, "&", &status);

    printf("\nAfter modifying the keywords...\n");
    for (ii = keynum - 4; ii <= keynum + 5; ii++)
    {
        ffgrec(fptr, ii, card, &status);
        printf("%s\n", card);
    }
    if (status > 0)
       printf("\nERROR modifying keywords\n");

    /*
      ############################
      #  update keywords         #
      ############################
    */
    ffucrd(fptr, "KY_MREC", "KY_UCRD = 'This keyword was updated by fxucrd'",
            &status);

    ffukyj(fptr, "KY_IKYJ", 51, "&", &status);
    ffukyl(fptr, "KY_IKYL", 1, "&", &status);
    ffukys(fptr, "NEWIKYS", "updated_string", "&", &status);
    ffukye(fptr, "KY_IKYE", -13.3456f, 4, "&", &status);
    ffukyd(fptr, "KY_IKYD", -13.345678901234567, 14, "modified comment",
            &status);
    ffukyf(fptr, "KY_IKYF", -13.3456f, 4, "&", &status);
    ffukyg(fptr, "KY_IKYG", -13.345678901234567, 13, "&", &status);

    printf("\nAfter updating the keywords...\n");
    for (ii = keynum - 4; ii <= keynum + 5; ii++)
    {
        ffgrec(fptr, ii, card, &status);
        printf("%s\n", card);
    }
    if (status > 0)
       printf("\nERROR modifying keywords\n");

    /* move to top of header and find keywords using wild cards */
    ffgrec(fptr, 0, card, &status);

    printf("\nKeywords found using wildcard search (should be 13)...\n");
    nfound = 0;
    while (!ffgnxk(fptr,inclist, 2, exclist, 2, card, &status))
    {
        nfound++;
        printf("%s\n", card);
    }
    if (nfound != 13)
    {
       printf("\nERROR reading keywords using wildcards (ffgnxk)\n");
       goto errstatus;
    }
    status = 0;

    /*
      ############################
      #  copy index keyword      #
      ############################
    */
    ffcpky(fptr, fptr, 1, 4, "KY_PKNE", &status);
    ffgkne(fptr, "ky_pkne", 2, 4, inekey, &nfound, &status);
    printf("\nCopied keyword: ffgkne:  %f, %f, %f\n", inekey[0], inekey[1],
           inekey[2]);

    if (status > 0)
    {
       printf("\nERROR in ffgkne %d, %d\n", nfound, status);
       goto errstatus;
    }

    /*
      ######################################
      #  modify header using template file #
      ######################################
    */
    if (ffpktp(fptr, templt, &status))
    {
       printf("\nERROR returned by ffpktp:\n");
       printf("Could not open or process the file 'testprog.tpt'.\n");
       printf("  This file is included with the CFITSIO distribution\n");
       printf("  and should be copied into the current directory\n");
       printf("  before running the testprog program.\n");
       status = 0;
    }
    printf("Updated header using template file (ffpktp)\n");
    /*
      ############################
      #  create binary table     #
      ############################
    */

    strcpy(tform[0], "15A");
    strcpy(tform[1], "1L");
    strcpy(tform[2], "16X");
    strcpy(tform[3], "1B");
    strcpy(tform[4], "1I");
    strcpy(tform[5], "1J");
    strcpy(tform[6], "1E");
    strcpy(tform[7], "1D");
    strcpy(tform[8], "1C");
    strcpy(tform[9], "1M");

    strcpy(ttype[0], "Avalue");
    strcpy(ttype[1], "Lvalue");
    strcpy(ttype[2], "Xvalue");
    strcpy(ttype[3], "Bvalue");
    strcpy(ttype[4], "Ivalue");
    strcpy(ttype[5], "Jvalue");
    strcpy(ttype[6], "Evalue");
    strcpy(ttype[7], "Dvalue");
    strcpy(ttype[8], "Cvalue");
    strcpy(ttype[9], "Mvalue");

    strcpy(tunit[0], "");
    strcpy(tunit[1], "m**2");
    strcpy(tunit[2], "cm");
    strcpy(tunit[3], "erg/s");
    strcpy(tunit[4], "km/s");
    strcpy(tunit[5], "");
    strcpy(tunit[6], "");
    strcpy(tunit[7], "");
    strcpy(tunit[8], "");
    strcpy(tunit[9], "");

    nrows = 21;
    tfields = 10;
    pcount = 0;

/*
    ffcrtb(fptr, BINARY_TBL, nrows, tfields, ttype, tform, tunit, binname,
            &status);
*/
    ffibin(fptr, nrows, tfields, ttype, tform, tunit, binname, 0L,
            &status);

    printf("\nffibin status = %d\n", status);
    printf("HDU number = %d\n", ffghdn(fptr, &hdunum));

    /* get size and position in header, and reserve space for more keywords */
    ffghps(fptr, &existkeys, &keynum, &status);
    printf("header contains %d keywords; located at keyword %d \n",existkeys,
            keynum);

    morekeys = 40;
    ffhdef(fptr, morekeys, &status);
    ffghsp(fptr, &existkeys, &morekeys, &status);
    printf("header contains %d keywords with room for %d more\n",existkeys,
            morekeys);

    fftnul(fptr, 4, 99, &status);   /* define null value for int cols */
    fftnul(fptr, 5, 99, &status);
    fftnul(fptr, 6, 99, &status);

    extvers = 1;
    ffpkyj(fptr, "EXTVER", extvers, "extension version number", &status);
    ffpkyj(fptr, "TNULL4", 99, "value for undefined pixels", &status);
    ffpkyj(fptr, "TNULL5", 99, "value for undefined pixels", &status);
    ffpkyj(fptr, "TNULL6", 99, "value for undefined pixels", &status);

    naxis = 3;
    naxes[0] = 1;
    naxes[1] = 2;
    naxes[2] = 8;
    ffptdm(fptr, 3, naxis, naxes, &status);

    naxis = 0;
    naxes[0] = 0;
    naxes[1] = 0;
    naxes[2] = 0;
    ffgtdm(fptr, 3, 3, &naxis, naxes, &status);
    ffgkys(fptr, "TDIM3", iskey, comment, &status);
    printf("TDIM3 = %s, %d, %ld, %ld, %ld\n", iskey, naxis, naxes[0],
         naxes[1], naxes[2]);

    ffrdef(fptr, &status);  /* force header to be scanned (not required) */

    /*
      ############################
      #  write data to columns   #
      ############################
    */

    /* initialize arrays of values to write to table */
    signval = -1;
    for (ii = 0; ii < 21; ii++)
    {
        signval *= -1;
        boutarray[ii] = (unsigned char) (ii + 1);
        ioutarray[ii] = (short) ((ii + 1) * signval);
        joutarray[ii] = (ii + 1) * signval;
        koutarray[ii] = (ii + 1) * signval;
        eoutarray[ii] = (float) ((ii + 1) * signval);
        doutarray[ii] = (ii + 1) * signval;
    }

    ffpcls(fptr, 1, 1, 1, 3, onskey, &status);  /* write string values */
    ffpclu(fptr, 1, 4, 1, 1, &status);  /* write null value */

    larray[0] = 0;
    larray[1] = 1;
    larray[2] = 0;
    larray[3] = 0;
    larray[4] = 1;
    larray[5] = 1;
    larray[6] = 0;
    larray[7] = 0;
    larray[8] = 0;
    larray[9] = 1;
    larray[10] = 1;
    larray[11] = 1;
    larray[12] = 0;
    larray[13] = 0;
    larray[14] = 0;
    larray[15] = 0;
    larray[16] = 1;
    larray[17] = 1;
    larray[18] = 1;
    larray[19] = 1;
    larray[20] = 0;
    larray[21] = 0;
    larray[22] = 0;
    larray[23] = 0;
    larray[24] = 0;
    larray[25] = 1;
    larray[26] = 1;
    larray[27] = 1;
    larray[28] = 1;
    larray[29] = 1;
    larray[30] = 0;
    larray[31] = 0;
    larray[32] = 0;
    larray[33] = 0;
    larray[34] = 0;
    larray[35] = 0;


    ffpclx(fptr, 3, 1, 1, 36, larray, &status); /*write bits*/

    for (ii = 4; ii < 9; ii++)   /* loop over cols 4 - 8 */
    {
        ffpclb(fptr, ii, 1, 1, 2, boutarray, &status);
        if (status == NUM_OVERFLOW)
            status = 0;
        ffpcli(fptr, ii, 3, 1, 2, &ioutarray[2], &status); 
        if (status == NUM_OVERFLOW)
            status = 0;
        ffpclk(fptr, ii, 5, 1, 2, &koutarray[4], &status); 
        if (status == NUM_OVERFLOW)
            status = 0;
        ffpcle(fptr, ii, 7, 1, 2, &eoutarray[6], &status);
        if (status == NUM_OVERFLOW)
            status = 0;
        ffpcld(fptr, ii, 9, 1, 2, &doutarray[8], &status);
        if (status == NUM_OVERFLOW)
            status = 0;

        ffpclu(fptr, ii, 11, 1, 1, &status);  /* write null value */
    }

    ffpclc(fptr, 9, 1, 1, 10, eoutarray, &status);
    ffpclm(fptr, 10, 1, 1, 10, doutarray, &status);

    for (ii = 4; ii < 9; ii++)   /* loop over cols 4 - 8 */
    {
        ffpcnb(fptr, ii, 12, 1, 2, &boutarray[11], 13, &status);
        if (status == NUM_OVERFLOW)
            status = 0;
        ffpcni(fptr, ii, 14, 1, 2, &ioutarray[13], 15, &status); 
        if (status == NUM_OVERFLOW)
            status = 0;
        ffpcnk(fptr, ii, 16, 1, 2, &koutarray[15], 17, &status); 
        if (status == NUM_OVERFLOW)
            status = 0;
        ffpcne(fptr, ii, 18, 1, 2, &eoutarray[17], 19., &status);
        if (status == NUM_OVERFLOW)
            status = 0;
        ffpcnd(fptr, ii, 20, 1, 2, &doutarray[19], 21., &status);
        if (status == NUM_OVERFLOW)
            status = 0;

    }
    ffpcll(fptr, 2, 1, 1, 21, larray, &status); /*write logicals*/
    ffpclu(fptr, 2, 11, 1, 1, &status);  /* write null value */
    printf("ffpcl_ status = %d\n", status);

    /*
      #########################################
      #  get information about the columns    #
      #########################################
    */

    printf("\nFind the column numbers; a returned status value of 237 is");
    printf("\nexpected and indicates that more than one column name matches");
    printf("\nthe input column name template.  Status = 219 indicates that");
    printf("\nthere was no matching column name.");

    ffgcno(fptr, 0, "Xvalue", &colnum, &status);
    printf("\nColumn Xvalue is number %d; status = %d.\n", colnum, status);

    while (status != COL_NOT_FOUND)
    {
      ffgcnn(fptr, 1, "*ue", colname, &colnum, &status);
      printf("Column %s is number %d; status = %d.\n", 
           colname, colnum, status);
    }
    status = 0;

    printf("\nInformation about each column:\n");

    for (ii = 0; ii < tfields; ii++)
    {
      ffgtcl(fptr, ii + 1, &typecode, &repeat, &width, &status);
      printf("%4s %3d %2ld %2ld", tform[ii], typecode, repeat, width);
      ffgbcl(fptr, ii + 1, ttype[0], tunit[0], cvalstr, &repeat, &scale,
           &zero, &jnulval, tdisp, &status);
      printf(" %s, %s, %c, %ld, %f, %f, %ld, %s.\n",
         ttype[0], tunit[0], cvalstr[0], repeat, scale, zero, jnulval, tdisp);
    }

    printf("\n");

    /*
      ###############################################
      #  insert ASCII table before the binary table #
      ###############################################
    */

    if (ffmrhd(fptr, -1, &hdutype, &status) > 0)
        goto errstatus;

    strcpy(tform[0], "A15");
    strcpy(tform[1], "I10");
    strcpy(tform[2], "F14.6");
    strcpy(tform[3], "E12.5");
    strcpy(tform[4], "D21.14");

    strcpy(ttype[0], "Name");
    strcpy(ttype[1], "Ivalue");
    strcpy(ttype[2], "Fvalue");
    strcpy(ttype[3], "Evalue");
    strcpy(ttype[4], "Dvalue");

    strcpy(tunit[0], "");
    strcpy(tunit[1], "m**2");
    strcpy(tunit[2], "cm");
    strcpy(tunit[3], "erg/s");
    strcpy(tunit[4], "km/s");

    rowlen = 76;
    nrows = 11;
    tfields = 5;

    ffitab(fptr, rowlen, nrows, tfields, ttype, tbcol, tform, tunit, tblname,
            &status);
    printf("ffitab status = %d\n", status);
    printf("HDU number = %d\n", ffghdn(fptr, &hdunum));

    ffsnul(fptr, 1, "null1", &status);   /* define null value for int cols */
    ffsnul(fptr, 2, "null2", &status);
    ffsnul(fptr, 3, "null3", &status);
    ffsnul(fptr, 4, "null4", &status);
    ffsnul(fptr, 5, "null5", &status);
 
    extvers = 2;
    ffpkyj(fptr, "EXTVER", extvers, "extension version number", &status);

    ffpkys(fptr, "TNULL1", "null1", "value for undefined pixels", &status);
    ffpkys(fptr, "TNULL2", "null2", "value for undefined pixels", &status);
    ffpkys(fptr, "TNULL3", "null3", "value for undefined pixels", &status);
    ffpkys(fptr, "TNULL4", "null4", "value for undefined pixels", &status);
    ffpkys(fptr, "TNULL5", "null5", "value for undefined pixels", &status);

    if (status > 0)
        goto errstatus;

    /*
      ############################
      #  write data to columns   #
      ############################
    */

    /* initialize arrays of values to write to table */
    for (ii = 0; ii < 21; ii++)
    {
        boutarray[ii] = (unsigned char) (ii + 1);
        ioutarray[ii] = (short) (ii + 1);
        joutarray[ii] = ii + 1;
        eoutarray[ii] = (float) (ii + 1);
        doutarray[ii] = ii + 1;
    }

    ffpcls(fptr, 1, 1, 1, 3, onskey, &status);  /* write string values */
    ffpclu(fptr, 1, 4, 1, 1, &status);  /* write null value */

    for (ii = 2; ii < 6; ii++)   /* loop over cols 2 - 5 */
    {
        ffpclb(fptr, ii, 1, 1, 2, boutarray, &status);  /* char array */
        if (status == NUM_OVERFLOW)
            status = 0;
        ffpcli(fptr, ii, 3, 1, 2, &ioutarray[2], &status);  /* short array */
        if (status == NUM_OVERFLOW)
            status = 0;
        ffpclj(fptr, ii, 5, 1, 2, &joutarray[4], &status);  /* long array */
        if (status == NUM_OVERFLOW)
            status = 0;
        ffpcle(fptr, ii, 7, 1, 2, &eoutarray[6], &status);  /* float array */
        if (status == NUM_OVERFLOW)
            status = 0;
        ffpcld(fptr, ii, 9, 1, 2, &doutarray[8], &status);  /* double array */
        if (status == NUM_OVERFLOW)
            status = 0;

        ffpclu(fptr, ii, 11, 1, 1, &status);  /* write null value */
    }
    printf("ffpcl_ status = %d\n", status);

    /*
      ################################
      #  read data from ASCII table  #
      ################################
    */
    ffghtb(fptr, 99, &rowlen, &nrows, &tfields, ttype, tbcol, 
           tform, tunit, tblname, &status);

    printf("\nASCII table: rowlen, nrows, tfields, extname: %ld %ld %d %s\n",
           rowlen, nrows, tfields, tblname);

    for (ii = 0; ii < tfields; ii++)
      printf("%8s %3ld %8s %8s \n", ttype[ii], tbcol[ii], 
                                   tform[ii], tunit[ii]);

    nrows = 11;
    ffgcvs(fptr, 1, 1, 1, nrows, "UNDEFINED", inskey,   &anynull, &status);
    ffgcvb(fptr, 2, 1, 1, nrows, 99, binarray, &anynull, &status);
    ffgcvi(fptr, 2, 1, 1, nrows, 99, iinarray, &anynull, &status);
    ffgcvj(fptr, 3, 1, 1, nrows, 99, jinarray, &anynull, &status);
    ffgcve(fptr, 4, 1, 1, nrows, 99., einarray, &anynull, &status);
    ffgcvd(fptr, 5, 1, 1, nrows, 99., dinarray, &anynull, &status);

    printf("\nData values read from ASCII table:\n");
    for (ii = 0; ii < nrows; ii++)
    {
      printf("%15s %2d %2d %2ld %4.1f %4.1f\n", inskey[ii], binarray[ii],
           iinarray[ii], jinarray[ii], einarray[ii], dinarray[ii]); 
    }

    ffgtbb(fptr, 1, 20, 78, uchars, &status);
    uchars[78] = '\0';
    printf("\n%s\n", uchars);
    ffptbb(fptr, 1, 20, 78, uchars, &status);

    /*
      #########################################
      #  get information about the columns    #
      #########################################
    */

    ffgcno(fptr, 0, "name", &colnum, &status);
    printf("\nColumn name is number %d; status = %d.\n", colnum, status);

    while (status != COL_NOT_FOUND)
    {
      ffgcnn(fptr, 1, "*ue", colname, &colnum, &status);
      printf("Column %s is number %d; status = %d.\n", 
           colname, colnum, status);
    }
    status = 0;

    for (ii = 0; ii < tfields; ii++)
    {
      ffgtcl(fptr, ii + 1, &typecode, &repeat, &width, &status);
      printf("%4s %3d %2ld %2ld", tform[ii], typecode, repeat, width);
      ffgacl(fptr, ii + 1, ttype[0], tbcol, tunit[0], tform[0], &scale,
           &zero, nulstr, tdisp, &status);
      printf(" %s, %ld, %s, %s, %f, %f, %s, %s.\n",
         ttype[0], tbcol[0], tunit[0], tform[0], scale, zero,
         nulstr, tdisp);
    }

    printf("\n");

    /*
      ###############################################
      #  test the insert/delete row/column routines #
      ###############################################
    */

    if (ffirow(fptr, 2, 3, &status) > 0)
        goto errstatus;

    nrows = 14;
    ffgcvs(fptr, 1, 1, 1, nrows, "UNDEFINED", inskey,   &anynull, &status);
    ffgcvb(fptr, 2, 1, 1, nrows, 99, binarray, &anynull, &status);
    ffgcvi(fptr, 2, 1, 1, nrows, 99, iinarray, &anynull, &status);
    ffgcvj(fptr, 3, 1, 1, nrows, 99, jinarray, &anynull, &status);
    ffgcve(fptr, 4, 1, 1, nrows, 99., einarray, &anynull, &status);
    ffgcvd(fptr, 5, 1, 1, nrows, 99., dinarray, &anynull, &status);


    printf("\nData values after inserting 3 rows after row 2:\n");
    for (ii = 0; ii < nrows; ii++)
    {
      printf("%15s %2d %2d %2ld %4.1f %4.1f\n",  inskey[ii], binarray[ii],
          iinarray[ii], jinarray[ii], einarray[ii], dinarray[ii]);
    }

    if (ffdrow(fptr, 10, 2, &status) > 0)
        goto errstatus;

    nrows = 12;
    ffgcvs(fptr, 1, 1, 1, nrows, "UNDEFINED", inskey,   &anynull, &status);
    ffgcvb(fptr, 2, 1, 1, nrows, 99, binarray, &anynull, &status);
    ffgcvi(fptr, 2, 1, 1, nrows, 99, iinarray, &anynull, &status);
    ffgcvj(fptr, 3, 1, 1, nrows, 99, jinarray, &anynull, &status);
    ffgcve(fptr, 4, 1, 1, nrows, 99., einarray, &anynull, &status);
    ffgcvd(fptr, 5, 1, 1, nrows, 99., dinarray, &anynull, &status);

    printf("\nData values after deleting 2 rows at row 10:\n");
    for (ii = 0; ii < nrows; ii++)
    {
      printf("%15s %2d %2d %2ld %4.1f %4.1f\n",  inskey[ii], binarray[ii],
          iinarray[ii], jinarray[ii], einarray[ii], dinarray[ii]);
    }
    if (ffdcol(fptr, 3, &status) > 0)
        goto errstatus;

    ffgcvs(fptr, 1, 1, 1, nrows, "UNDEFINED", inskey,   &anynull, &status);
    ffgcvb(fptr, 2, 1, 1, nrows, 99, binarray, &anynull, &status);
    ffgcvi(fptr, 2, 1, 1, nrows, 99, iinarray, &anynull, &status);
    ffgcve(fptr, 3, 1, 1, nrows, 99., einarray, &anynull, &status);
    ffgcvd(fptr, 4, 1, 1, nrows, 99., dinarray, &anynull, &status);

    printf("\nData values after deleting column 3:\n");
    for (ii = 0; ii < nrows; ii++)
    {
      printf("%15s %2d %2d %4.1f %4.1f\n", inskey[ii], binarray[ii],
          iinarray[ii], einarray[ii], dinarray[ii]);
    }

    if (fficol(fptr, 5, "INSERT_COL", "F14.6", &status) > 0)
        goto errstatus;

    ffgcvs(fptr, 1, 1, 1, nrows, "UNDEFINED", inskey,   &anynull, &status);
    ffgcvb(fptr, 2, 1, 1, nrows, 99, binarray, &anynull, &status);
    ffgcvi(fptr, 2, 1, 1, nrows, 99, iinarray, &anynull, &status);
    ffgcve(fptr, 3, 1, 1, nrows, 99., einarray, &anynull, &status);
    ffgcvd(fptr, 4, 1, 1, nrows, 99., dinarray, &anynull, &status);
    ffgcvj(fptr, 5, 1, 1, nrows, 99, jinarray, &anynull, &status);

    printf("\nData values after inserting column 5:\n");
    for (ii = 0; ii < nrows; ii++)
    {
      printf("%15s %2d %2d %4.1f %4.1f %ld\n", inskey[ii], binarray[ii],
          iinarray[ii], einarray[ii], dinarray[ii] , jinarray[ii]);
    }

    /*
      ############################################################
      #  create a temporary file and copy the ASCII table to it, #
      #  column by column.                                       #
      ############################################################
    */
    bitpix = 16;
    naxis = 0;

    strcpy(filename, "!t1q2s3v6.tmp");
    ffinit(&tmpfptr, filename, &status);
    printf("Create temporary file: ffinit status = %d\n", status);

    ffiimg(tmpfptr, bitpix, naxis, naxes, &status);
    printf("\nCreate null primary array: ffiimg status = %d\n", status);

    /* create an empty table with 12 rows and 0 columns */
    nrows = 12;
    tfields = 0;
    rowlen = 0;
    ffitab(tmpfptr, rowlen, nrows, tfields, ttype, tbcol, tform, tunit,
           tblname, &status);
    printf("\nCreate ASCII table with 0 columns: ffitab status = %d\n",
           status);

    /* copy columns from one table to the other */
    ffcpcl(fptr, tmpfptr, 4, 1, TRUE, &status);
    printf("copy column, ffcpcl status = %d\n", status);
    ffcpcl(fptr, tmpfptr, 3, 1, TRUE, &status);
    printf("copy column, ffcpcl status = %d\n", status);
    ffcpcl(fptr, tmpfptr, 2, 1, TRUE, &status);
    printf("copy column, ffcpcl status = %d\n", status);
    ffcpcl(fptr, tmpfptr, 1, 1, TRUE, &status);
    printf("copy column, ffcpcl status = %d\n", status);

    /* now repeat by copying ASCII input to Binary output table */
    ffibin(tmpfptr, nrows, tfields, ttype, tform, tunit,
           tblname,  0L, &status);
    printf("\nCreate Binary table with 0 columns: ffibin status = %d\n",
           status);

    /* copy columns from one table to the other */
    ffcpcl(fptr, tmpfptr, 4, 1, TRUE, &status);
    printf("copy column, ffcpcl status = %d\n", status);
    ffcpcl(fptr, tmpfptr, 3, 1, TRUE, &status);
    printf("copy column, ffcpcl status = %d\n", status);
    ffcpcl(fptr, tmpfptr, 2, 1, TRUE, &status);
    printf("copy column, ffcpcl status = %d\n", status);
    ffcpcl(fptr, tmpfptr, 1, 1, TRUE, &status);
    printf("copy column, ffcpcl status = %d\n", status);


/*
    ffclos(tmpfptr, &status);
    printf("Close the tmp file: ffclos status = %d\n", status);
*/

    ffdelt(tmpfptr, &status);  
    printf("Delete the tmp file: ffdelt status = %d\n", status);

    if (status > 0)
    {
        goto errstatus;
    }

    /*
      ################################
      #  read data from binary table #
      ################################
    */

    if (ffmrhd(fptr, 1, &hdutype, &status) > 0)
        goto errstatus;

    printf("HDU number = %d\n", ffghdn(fptr, &hdunum));

    ffghsp(fptr, &existkeys, &morekeys, &status);
    printf("header contains %d keywords with room for %d more\n",existkeys,
            morekeys);

    ffghbn(fptr, 99, &nrows, &tfields, ttype, 
           tform, tunit, binname, &pcount, &status);

    printf("\nBinary table: nrows, tfields, extname, pcount: %ld %d %s %ld\n",
           nrows, tfields, binname, pcount);

    for (ii = 0; ii < tfields; ii++)
      printf("%8s %8s %8s \n", ttype[ii], tform[ii], tunit[ii]);

    for (ii = 0; ii < 40; ii++)
        larray[ii] = 0;

    printf("\nData values read from binary table:\n");
    printf("  Bit column (X) data values: \n\n");

    ffgcx(fptr, 3, 1, 1, 36, larray, &status);
    for (jj = 0; jj < 5; jj++)
    {
      for (ii = 0; ii < 8; ii++)
        printf("%1d",larray[jj * 8 + ii]);
      printf(" ");
    }

    for (ii = 0; ii < nrows; ii++)
    {
      larray[ii] = 0;
      xinarray[ii] = 0;
      binarray[ii] = 0;
      iinarray[ii] = 0; 
      kinarray[ii] = 0;
      einarray[ii] = 0.; 
      dinarray[ii] = 0.;
      cinarray[ii * 2] = 0.; 
      minarray[ii * 2] = 0.;
      cinarray[ii * 2 + 1] = 0.; 
      minarray[ii * 2 + 1] = 0.;
    }

    printf("\n\n");
    ffgcvs(fptr, 1, 4, 1, 1, "",  inskey,   &anynull, &status);
    printf("null string column value = -%s- (should be --)\n",inskey[0]);

    nrows = 21;
    ffgcvs(fptr, 1, 1, 1, nrows, "NOT DEFINED",  inskey,   &anynull, &status);
    ffgcl( fptr, 2, 1, 1, nrows, larray, &status);
    ffgcvb(fptr, 3, 1, 1, nrows, 98, xinarray, &anynull, &status);
    ffgcvb(fptr, 4, 1, 1, nrows, 98, binarray, &anynull, &status);
    ffgcvi(fptr, 5, 1, 1, nrows, 98, iinarray, &anynull, &status);
    ffgcvk(fptr, 6, 1, 1, nrows, 98, kinarray, &anynull, &status);
    ffgcve(fptr, 7, 1, 1, nrows, 98., einarray, &anynull, &status);
    ffgcvd(fptr, 8, 1, 1, nrows, 98., dinarray, &anynull, &status);
    ffgcvc(fptr, 9, 1, 1, nrows, 98., cinarray, &anynull, &status);
    ffgcvm(fptr, 10, 1, 1, nrows, 98., minarray, &anynull, &status);

    printf("\nRead columns with ffgcv_:\n");
    for (ii = 0; ii < nrows; ii++)
    {
  printf("%15s %d %3d %2d %3d %3d %5.1f %5.1f (%5.1f,%5.1f) (%5.1f,%5.1f) \n",
        inskey[ii], larray[ii], xinarray[ii], binarray[ii], iinarray[ii], 
        kinarray[ii], einarray[ii], dinarray[ii], cinarray[ii * 2], 
        cinarray[ii * 2 + 1], minarray[ii * 2], minarray[ii * 2 + 1]);
    }

    for (ii = 0; ii < nrows; ii++)
    {
      larray[ii] = 0;
      xinarray[ii] = 0;
      binarray[ii] = 0;
      iinarray[ii] = 0; 
      kinarray[ii] = 0;
      einarray[ii] = 0.; 
      dinarray[ii] = 0.;
      cinarray[ii * 2] = 0.; 
      minarray[ii * 2] = 0.;
      cinarray[ii * 2 + 1] = 0.; 
      minarray[ii * 2 + 1] = 0.;
    }

    ffgcfs(fptr, 1, 1, 1, nrows, inskey,   larray2, &anynull, &status);
    ffgcfl(fptr, 2, 1, 1, nrows, larray,   larray2, &anynull, &status);
    ffgcfb(fptr, 3, 1, 1, nrows, xinarray, larray2, &anynull, &status);
    ffgcfb(fptr, 4, 1, 1, nrows, binarray, larray2, &anynull, &status);
    ffgcfi(fptr, 5, 1, 1, nrows, iinarray, larray2, &anynull, &status);
    ffgcfk(fptr, 6, 1, 1, nrows, kinarray, larray2, &anynull, &status);
    ffgcfe(fptr, 7, 1, 1, nrows, einarray, larray2, &anynull, &status);
    ffgcfd(fptr, 8, 1, 1, nrows, dinarray, larray2, &anynull, &status);
    ffgcfc(fptr, 9, 1, 1, nrows, cinarray, larray2, &anynull, &status);
    ffgcfm(fptr, 10, 1, 1, nrows, minarray, larray2, &anynull, &status);

    printf("\nRead columns with ffgcf_:\n");
    for (ii = 0; ii < 10; ii++)
    {
    
    printf("%15s %d %3d %2d %3d %3d %5.1f %5.1f (%5.1f,%5.1f) (%5.1f,%5.1f)\n",
        inskey[ii], larray[ii], xinarray[ii], binarray[ii], iinarray[ii], 
        kinarray[ii], einarray[ii], dinarray[ii], cinarray[ii * 2], 
        cinarray[ii * 2 + 1], minarray[ii * 2], minarray[ii * 2 + 1]);
    }
    for (ii = 10; ii < nrows; ii++)
    {
      /* don't try to print the NaN values */
      printf("%15s %d %3d %2d %3d \n",
        inskey[ii], larray[ii], xinarray[ii], binarray[ii], iinarray[ii]);
    }
    ffprec(fptr, 
    "key_prec= 'This keyword was written by f_prec' / comment here", &status);

    /*
      ###############################################
      #  test the insert/delete row/column routines #
      ###############################################
    */
    if (ffirow(fptr, 2, 3, &status) > 0)
        goto errstatus;

    nrows = 14;
    ffgcvs(fptr, 1, 1, 1, nrows, "NOT DEFINED",  inskey,   &anynull, &status);
    ffgcvb(fptr, 4, 1, 1, nrows, 98, binarray, &anynull, &status);
    ffgcvi(fptr, 5, 1, 1, nrows, 98, iinarray, &anynull, &status);
    ffgcvj(fptr, 6, 1, 1, nrows, 98, jinarray, &anynull, &status);
    ffgcve(fptr, 7, 1, 1, nrows, 98., einarray, &anynull, &status);
    ffgcvd(fptr, 8, 1, 1, nrows, 98., dinarray, &anynull, &status);

    printf("\nData values after inserting 3 rows after row 2:\n");
    for (ii = 0; ii < nrows; ii++)
    {
      printf("%15s %2d %3d %3ld %5.1f %5.1f\n",  inskey[ii], binarray[ii],
          iinarray[ii], jinarray[ii], einarray[ii], dinarray[ii]);
    }

    if (ffdrow(fptr, 10, 2, &status) > 0)
        goto errstatus;

    nrows = 12;
    ffgcvs(fptr, 1, 1, 1, nrows, "NOT DEFINED",  inskey,   &anynull, &status);
    ffgcvb(fptr, 4, 1, 1, nrows, 98, binarray, &anynull, &status);
    ffgcvi(fptr, 5, 1, 1, nrows, 98, iinarray, &anynull, &status);
    ffgcvj(fptr, 6, 1, 1, nrows, 98, jinarray, &anynull, &status);
    ffgcve(fptr, 7, 1, 1, nrows, 98., einarray, &anynull, &status);
    ffgcvd(fptr, 8, 1, 1, nrows, 98., dinarray, &anynull, &status);

    printf("\nData values after deleting 2 rows at row 10:\n");
    for (ii = 0; ii < nrows; ii++)
    {
      printf("%15s %2d %3d %3ld %5.1f %5.1f\n",  inskey[ii], binarray[ii],
          iinarray[ii], jinarray[ii], einarray[ii], dinarray[ii]);
    }

    if (ffdcol(fptr, 6, &status) > 0)
        goto errstatus;

    ffgcvs(fptr, 1, 1, 1, nrows, "NOT DEFINED",  inskey,   &anynull, &status);
    ffgcvb(fptr, 4, 1, 1, nrows, 98, binarray, &anynull, &status);
    ffgcvi(fptr, 5, 1, 1, nrows, 98, iinarray, &anynull, &status);
    ffgcve(fptr, 6, 1, 1, nrows, 98., einarray, &anynull, &status);
    ffgcvd(fptr, 7, 1, 1, nrows, 98., dinarray, &anynull, &status);

    printf("\nData values after deleting column 6:\n");
    for (ii = 0; ii < nrows; ii++)
    {
      printf("%15s %2d %3d %5.1f %5.1f\n", inskey[ii], binarray[ii],
          iinarray[ii], einarray[ii], dinarray[ii]);
    }

    if (fficol(fptr, 8, "INSERT_COL", "1E", &status) > 0)
        goto errstatus;

    ffgcvs(fptr, 1, 1, 1, nrows, "NOT DEFINED",  inskey,   &anynull, &status);
    ffgcvb(fptr, 4, 1, 1, nrows, 98, binarray, &anynull, &status);
    ffgcvi(fptr, 5, 1, 1, nrows, 98, iinarray, &anynull, &status);
    ffgcve(fptr, 6, 1, 1, nrows, 98., einarray, &anynull, &status);
    ffgcvd(fptr, 7, 1, 1, nrows, 98., dinarray, &anynull, &status);
    ffgcvj(fptr, 8, 1, 1, nrows, 98, jinarray, &anynull, &status);

    printf("\nData values after inserting column 8:\n");
    for (ii = 0; ii < nrows; ii++)
    {
      printf("%15s %2d %3d %5.1f %5.1f %ld\n", inskey[ii], binarray[ii],
          iinarray[ii], einarray[ii], dinarray[ii] , jinarray[ii]);
    }

    ffpclu(fptr, 8, 1, 1, 10, &status);

    ffgcvs(fptr, 1, 1, 1, nrows, "NOT DEFINED",  inskey,   &anynull, &status);
    ffgcvb(fptr, 4, 1, 1, nrows, 98, binarray, &anynull, &status);
    ffgcvi(fptr, 5, 1, 1, nrows, 98, iinarray, &anynull, &status);
    ffgcve(fptr, 6, 1, 1, nrows, 98., einarray, &anynull, &status);
    ffgcvd(fptr, 7, 1, 1, nrows, 98., dinarray, &anynull, &status);
    ffgcvj(fptr, 8, 1, 1, nrows, 98, jinarray, &anynull, &status);

    printf("\nValues after setting 1st 10 elements in column 8 = null:\n");
    for (ii = 0; ii < nrows; ii++)
    {
      printf("%15s %2d %3d %5.1f %5.1f %ld\n", inskey[ii], binarray[ii],
          iinarray[ii], einarray[ii], dinarray[ii] , jinarray[ii]);
    }

    /*
      ############################################################
      #  create a temporary file and copy the binary table to it,#
      #  column by column.                                       #
      ############################################################
    */
    bitpix = 16;
    naxis = 0;

    strcpy(filename, "!t1q2s3v5.tmp");
    ffinit(&tmpfptr, filename, &status);
    printf("Create temporary file: ffinit status = %d\n", status);

    ffiimg(tmpfptr, bitpix, naxis, naxes, &status);
    printf("\nCreate null primary array: ffiimg status = %d\n", status);

    /* create an empty table with 22 rows and 0 columns */
    nrows = 22;
    tfields = 0;
    ffibin(tmpfptr, nrows, tfields, ttype, tform, tunit, binname, 0L,
            &status);
    printf("\nCreate binary table with 0 columns: ffibin status = %d\n",
           status);

    /* copy columns from one table to the other */
    ffcpcl(fptr, tmpfptr, 7, 1, TRUE, &status);
    printf("copy column, ffcpcl status = %d\n", status);
    ffcpcl(fptr, tmpfptr, 6, 1, TRUE, &status);
    printf("copy column, ffcpcl status = %d\n", status);
    ffcpcl(fptr, tmpfptr, 5, 1, TRUE, &status);
    printf("copy column, ffcpcl status = %d\n", status);
    ffcpcl(fptr, tmpfptr, 4, 1, TRUE, &status);
    printf("copy column, ffcpcl status = %d\n", status);
    ffcpcl(fptr, tmpfptr, 3, 1, TRUE, &status);
    printf("copy column, ffcpcl status = %d\n", status);
    ffcpcl(fptr, tmpfptr, 2, 1, TRUE, &status);
    printf("copy column, ffcpcl status = %d\n", status);
    ffcpcl(fptr, tmpfptr, 1, 1, TRUE, &status);
    printf("copy column, ffcpcl status = %d\n", status);

/*
    ffclos(tmpfptr, &status);
    printf("Close the tmp file: ffclos status = %d\n", status);
*/

    ffdelt(tmpfptr, &status);
    printf("Delete the tmp file: ffdelt status = %d\n", status);
    if (status > 0)
    {
        goto errstatus;
    }
    /*
      ####################################################
      #  insert binary table following the primary array #
      ####################################################
    */

    ffmahd(fptr,  1, &hdutype, &status);

    strcpy(tform[0], "15A");
    strcpy(tform[1], "1L");
    strcpy(tform[2], "16X");
    strcpy(tform[3], "1B");
    strcpy(tform[4], "1I");
    strcpy(tform[5], "1J");
    strcpy(tform[6], "1E");
    strcpy(tform[7], "1D");
    strcpy(tform[8], "1C");
    strcpy(tform[9], "1M");

    strcpy(ttype[0], "Avalue");
    strcpy(ttype[1], "Lvalue");
    strcpy(ttype[2], "Xvalue");
    strcpy(ttype[3], "Bvalue");
    strcpy(ttype[4], "Ivalue");
    strcpy(ttype[5], "Jvalue");
    strcpy(ttype[6], "Evalue");
    strcpy(ttype[7], "Dvalue");
    strcpy(ttype[8], "Cvalue");
    strcpy(ttype[9], "Mvalue");

    strcpy(tunit[0], "");
    strcpy(tunit[1], "m**2");
    strcpy(tunit[2], "cm");
    strcpy(tunit[3], "erg/s");
    strcpy(tunit[4], "km/s");
    strcpy(tunit[5], "");
    strcpy(tunit[6], "");
    strcpy(tunit[7], "");
    strcpy(tunit[8], "");
    strcpy(tunit[9], "");

    nrows = 20;
    tfields = 10;
    pcount = 0;

    ffibin(fptr, nrows, tfields, ttype, tform, tunit, binname, pcount,
            &status);
    printf("ffibin status = %d\n", status);
    printf("HDU number = %d\n", ffghdn(fptr, &hdunum));

    extvers = 3;
    ffpkyj(fptr, "EXTVER", extvers, "extension version number", &status);


    ffpkyj(fptr, "TNULL4", 77, "value for undefined pixels", &status);
    ffpkyj(fptr, "TNULL5", 77, "value for undefined pixels", &status);
    ffpkyj(fptr, "TNULL6", 77, "value for undefined pixels", &status);

    ffpkyj(fptr, "TSCAL4", 1000, "scaling factor", &status);
    ffpkyj(fptr, "TSCAL5", 1, "scaling factor", &status);
    ffpkyj(fptr, "TSCAL6", 100, "scaling factor", &status);

    ffpkyj(fptr, "TZERO4", 0, "scaling offset", &status);
    ffpkyj(fptr, "TZERO5", 32768, "scaling offset", &status);
    ffpkyj(fptr, "TZERO6", 100, "scaling offset", &status);

    fftnul(fptr, 4, 77, &status);   /* define null value for int cols */
    fftnul(fptr, 5, 77, &status);
    fftnul(fptr, 6, 77, &status);
    /* set scaling */
    fftscl(fptr, 4, 1000., 0., &status);   
    fftscl(fptr, 5, 1., 32768., &status);
    fftscl(fptr, 6, 100., 100., &status);

    /*
      ############################
      #  write data to columns   #
      ############################
    */

    /* initialize arrays of values to write to table */
 
    joutarray[0] = 0;
    joutarray[1] = 1000;
    joutarray[2] = 10000;
    joutarray[3] = 32768;
    joutarray[4] = 65535;


    for (ii = 4; ii < 7; ii++)
    {
        ffpclj(fptr, ii, 1, 1, 5, joutarray, &status); 
        if (status == NUM_OVERFLOW)
        {
            printf("Overflow writing to column %ld\n", ii);
            status = 0;
        }

        ffpclu(fptr, ii, 6, 1, 1, &status);  /* write null value */
    }

    for (jj = 4; jj < 7; jj++)
    {
      ffgcvj(fptr, jj, 1, 1, 6, -999, jinarray, &anynull, &status);
      for (ii = 0; ii < 6; ii++)
      {
        printf(" %6ld", jinarray[ii]);
      }
      printf("\n");
    }

    printf("\n");
    /* turn off scaling, and read the unscaled values */
    fftscl(fptr, 4, 1., 0., &status);   
    fftscl(fptr, 5, 1., 0., &status);
    fftscl(fptr, 6, 1., 0., &status);

    for (jj = 4; jj < 7; jj++)
    {
      ffgcvj(fptr, jj, 1, 1, 6, -999, jinarray, &anynull, &status);
      for (ii = 0; ii < 6; ii++)
      {
        printf(" %6ld", jinarray[ii]);
      }
      printf("\n");
    }
    /*
      ######################################################
      #  insert image extension following the binary table #
      ######################################################
    */

    bitpix = -32;
    naxis = 2;
    naxes[0] = 15;
    naxes[1] = 25;
    ffiimg(fptr, bitpix, naxis, naxes, &status);
    printf("\nCreate image extension: ffiimg status = %d\n", status);
    printf("HDU number = %d\n", ffghdn(fptr, &hdunum));

    for (jj = 0; jj < 30; jj++)
    {
      for (ii = 0; ii < 19; ii++)
      {
        imgarray[jj][ii] = (short) ((jj * 10) + ii);
      }
    }

    ffp2di(fptr, 1, 19, naxes[0], naxes[1], imgarray[0], &status);
    printf("\nWrote whole 2D array: ffp2di status = %d\n", status);

    for (jj = 0; jj < 30; jj++)
    {
      for (ii = 0; ii < 19; ii++)
      {
        imgarray[jj][ii] = 0;
      }
    }
    
    ffg2di(fptr, 1, 0, 19, naxes[0], naxes[1], imgarray[0], &anynull,
           &status);
    printf("\nRead whole 2D array: ffg2di status = %d\n", status);

    for (jj = 0; jj < 30; jj++)
    {
      for (ii = 0; ii < 19; ii++)
      {
        printf(" %3d", imgarray[jj][ii]);
      }
      printf("\n");
    }

    for (jj = 0; jj < 30; jj++)
    {
      for (ii = 0; ii < 19; ii++)
      {
        imgarray[jj][ii] = 0;
      }
    }
    
    for (jj = 0; jj < 20; jj++)
    {
      for (ii = 0; ii < 10; ii++)
      {
        imgarray2[jj][ii] = (short) ((jj * -10) - ii);
      }
    }

    fpixels[0] = 5;
    fpixels[1] = 5;
    lpixels[0] = 14;
    lpixels[1] = 14;
    ffpssi(fptr, 1, naxis, naxes, fpixels, lpixels, 
         imgarray2[0], &status);
    printf("\nWrote subset 2D array: ffpssi status = %d\n", status);

    ffg2di(fptr, 1, 0, 19, naxes[0], naxes[1], imgarray[0], &anynull,
           &status);
    printf("\nRead whole 2D array: ffg2di status = %d\n", status);

    for (jj = 0; jj < 30; jj++)
    {
      for (ii = 0; ii < 19; ii++)
      {
        printf(" %3d", imgarray[jj][ii]);
      }
      printf("\n");
    }

    fpixels[0] = 2;
    fpixels[1] = 5;
    lpixels[0] = 10;
    lpixels[1] = 8;
    inc[0] = 2;
    inc[1] = 3;

    for (jj = 0; jj < 30; jj++)
    {
      for (ii = 0; ii < 19; ii++)
      {
        imgarray[jj][ii] = 0;
      }
    }
    
    ffgsvi(fptr, 1, naxis, naxes, fpixels, lpixels, inc, 0,
          imgarray[0], &anynull, &status);
    printf("\nRead subset of 2D array: ffgsvi status = %d\n", status);

    for (ii = 0; ii < 10; ii++)
    {
        printf(" %3d", imgarray[0][ii]);
    }
    printf("\n");

    /*
      ###########################################################
      #  insert another image extension                         #
      #  copy the image extension to primary array of tmp file. #
      #  then delete the tmp file, and the image extension      #
      ###########################################################
    */
    bitpix = 16;
    naxis = 2;
    naxes[0] = 15;
    naxes[1] = 25;
    ffiimg(fptr, bitpix, naxis, naxes, &status);
    printf("\nCreate image extension: ffiimg status = %d\n", status);
    printf("HDU number = %d\n", ffghdn(fptr, &hdunum));

    strcpy(filename, "t1q2s3v4.tmp");
    ffinit(&tmpfptr, filename, &status);
    printf("Create temporary file: ffinit status = %d\n", status);

    ffcopy(fptr, tmpfptr, 0, &status);
    printf("Copy image extension to primary array of tmp file.\n");
    printf("ffcopy status = %d\n", status);

    ffgrec(tmpfptr, 1, card, &status);
    printf("%s\n", card);
    ffgrec(tmpfptr, 2, card, &status);
    printf("%s\n", card);
    ffgrec(tmpfptr, 3, card, &status);
    printf("%s\n", card);
    ffgrec(tmpfptr, 4, card, &status);
    printf("%s\n", card);
    ffgrec(tmpfptr, 5, card, &status);
    printf("%s\n", card);
    ffgrec(tmpfptr, 6, card, &status);
    printf("%s\n", card);

    ffdelt(tmpfptr, &status);
    printf("Delete the tmp file: ffdelt status = %d\n", status);

    ffdhdu(fptr, &hdutype, &status);
    printf("Delete the image extension; hdutype, status = %d %d\n",
             hdutype, status);
    printf("HDU number = %d\n", ffghdn(fptr, &hdunum));

    /*
      ###########################################################
      #  append bintable extension with variable length columns #
      ###########################################################
    */

    ffcrhd(fptr, &status);
    printf("ffcrhd status = %d\n", status);

    strcpy(tform[0], "1PA");
    strcpy(tform[1], "1PL");
    strcpy(tform[2], "1PB"); /* Fortran FITSIO doesn't support  1PX */
    strcpy(tform[3], "1PB");
    strcpy(tform[4], "1PI");
    strcpy(tform[5], "1PJ");
    strcpy(tform[6], "1PE");
    strcpy(tform[7], "1PD");
    strcpy(tform[8], "1PC");
    strcpy(tform[9], "1PM");

    strcpy(ttype[0], "Avalue");
    strcpy(ttype[1], "Lvalue");
    strcpy(ttype[2], "Xvalue");
    strcpy(ttype[3], "Bvalue");
    strcpy(ttype[4], "Ivalue");
    strcpy(ttype[5], "Jvalue");
    strcpy(ttype[6], "Evalue");
    strcpy(ttype[7], "Dvalue");
    strcpy(ttype[8], "Cvalue");
    strcpy(ttype[9], "Mvalue");

    strcpy(tunit[0], "");
    strcpy(tunit[1], "m**2");
    strcpy(tunit[2], "cm");
    strcpy(tunit[3], "erg/s");
    strcpy(tunit[4], "km/s");
    strcpy(tunit[5], "");
    strcpy(tunit[6], "");
    strcpy(tunit[7], "");
    strcpy(tunit[8], "");
    strcpy(tunit[9], "");

    nrows = 20;
    tfields = 10;
    pcount = 0;

    ffphbn(fptr, nrows, tfields, ttype, tform, tunit, binname, pcount,
            &status);
    printf("Variable length arrays: ffphbn status = %d\n", status);


    extvers = 4;
    ffpkyj(fptr, "EXTVER", extvers, "extension version number", &status);

    ffpkyj(fptr, "TNULL4", 88, "value for undefined pixels", &status);
    ffpkyj(fptr, "TNULL5", 88, "value for undefined pixels", &status);
    ffpkyj(fptr, "TNULL6", 88, "value for undefined pixels", &status);

    /*
      ############################
      #  write data to columns   #
      ############################
    */

    /* initialize arrays of values to write to table */
    strcpy(iskey,"abcdefghijklmnopqrst");

    for (ii = 0; ii < 20; ii++)
    {
        boutarray[ii] = (unsigned char) (ii + 1);
        ioutarray[ii] = (short) (ii + 1);
        joutarray[ii] = ii + 1;
        eoutarray[ii] = (float) (ii + 1);
        doutarray[ii] = ii + 1;
    }

    larray[0] = 0;
    larray[1] = 1;
    larray[2] = 0;
    larray[3] = 0;
    larray[4] = 1;
    larray[5] = 1;
    larray[6] = 0;
    larray[7] = 0;
    larray[8] = 0;
    larray[9] = 1;
    larray[10] = 1;
    larray[11] = 1;
    larray[12] = 0;
    larray[13] = 0;
    larray[14] = 0;
    larray[15] = 0;
    larray[16] = 1;
    larray[17] = 1;
    larray[18] = 1;
    larray[19] = 1;

    /* write values in 1st row */
    /*  strncpy(inskey[0], iskey, 1); */
      inskey[0][0] = '\0';  /* write a null string (i.e., a blank) */
      ffpcls(fptr, 1, 1, 1, 1, inskey, &status);  /* write string values */
      ffpcll(fptr, 2, 1, 1, 1, larray, &status);  /* write logicals */
      ffpclx(fptr, 3, 1, 1, 1, larray, &status);  /* write bits */
      ffpclb(fptr, 4, 1, 1, 1, boutarray, &status);
      ffpcli(fptr, 5, 1, 1, 1, ioutarray, &status); 
      ffpclj(fptr, 6, 1, 1, 1, joutarray, &status); 
      ffpcle(fptr, 7, 1, 1, 1, eoutarray, &status);
      ffpcld(fptr, 8, 1, 1, 1, doutarray, &status);

    for (ii = 2; ii <= 20; ii++)   /* loop over rows 1 - 20 */
    {
      strncpy(inskey[0], iskey, ii);
      inskey[0][ii] = '\0';
      ffpcls(fptr, 1, ii, 1, 1, inskey, &status);  /* write string values */

      ffpcll(fptr, 2, ii, 1, ii, larray, &status);  /* write logicals */
      ffpclu(fptr, 2, ii, ii-1, 1, &status);

      ffpclx(fptr, 3, ii, 1, ii, larray, &status);  /* write bits */

      ffpclb(fptr, 4, ii, 1, ii, boutarray, &status);
      ffpclu(fptr, 4, ii, ii-1, 1, &status);

      ffpcli(fptr, 5, ii, 1, ii, ioutarray, &status); 
      ffpclu(fptr, 5, ii, ii-1, 1, &status);

      ffpclj(fptr, 6, ii, 1, ii, joutarray, &status); 
      ffpclu(fptr, 6, ii, ii-1, 1, &status);

      ffpcle(fptr, 7, ii, 1, ii, eoutarray, &status);
      ffpclu(fptr, 7, ii, ii-1, 1, &status);

      ffpcld(fptr, 8, ii, 1, ii, doutarray, &status);
      ffpclu(fptr, 8, ii, ii-1, 1, &status);
    }
    printf("ffpcl_ status = %d\n", status);

    /*
      #################################
      #  close then reopen this HDU   #
      #################################
    */


     ffmrhd(fptr, -1, &hdutype, &status);
     ffmrhd(fptr,  1, &hdutype, &status);

    /*
      #############################
      #  read data from columns   #
      #############################
    */

    ffgkyj(fptr, "PCOUNT", &pcount, comm, &status);
    printf("PCOUNT = %ld\n", pcount);

    /* initialize the variables to be read */
    strcpy(inskey[0]," ");
    strcpy(iskey," ");


    printf("HDU number = %d\n", ffghdn(fptr, &hdunum));
    for (ii = 1; ii <= 20; ii++)   /* loop over rows 1 - 20 */
    {
      for (jj = 0; jj < ii; jj++)
      {
        larray[jj] = 0;
        boutarray[jj] = 0;
        ioutarray[jj] = 0;
        joutarray[jj] = 0;
        eoutarray[jj] = 0;
        doutarray[jj] = 0;
      }

      ffgcvs(fptr, 1, ii, 1, 1, iskey, inskey, &anynull, &status);  
      printf("A %s %d\nL", inskey[0], status);

      ffgcl( fptr, 2, ii, 1, ii, larray, &status); 
      for (jj = 0; jj < ii; jj++)
        printf(" %2d", larray[jj]);
      printf(" %d\nX", status);

      ffgcx(fptr, 3, ii, 1, ii, larray, &status);
      for (jj = 0; jj < ii; jj++)
        printf(" %2d", larray[jj]);
      printf(" %d\nB", status);

      ffgcvb(fptr, 4, ii, 1, ii, 99, boutarray, &anynull, &status);
      for (jj = 0; jj < ii; jj++)
        printf(" %2d", boutarray[jj]);
      printf(" %d\nI", status);

      ffgcvi(fptr, 5, ii, 1, ii, 99, ioutarray, &anynull, &status); 
      for (jj = 0; jj < ii; jj++)
        printf(" %2d", ioutarray[jj]);
      printf(" %d\nJ", status);

      ffgcvj(fptr, 6, ii, 1, ii, 99, joutarray, &anynull, &status); 
      for (jj = 0; jj < ii; jj++)
        printf(" %2ld", joutarray[jj]);
      printf(" %d\nE", status);

      ffgcve(fptr, 7, ii, 1, ii, 99., eoutarray, &anynull, &status);
      for (jj = 0; jj < ii; jj++)
        printf(" %2.0f", eoutarray[jj]);
      printf(" %d\nD", status);

      ffgcvd(fptr, 8, ii, 1, ii, 99., doutarray, &anynull, &status);
      for (jj = 0; jj < ii; jj++)
        printf(" %2.0f", doutarray[jj]);
      printf(" %d\n", status);

      ffgdes(fptr, 8, ii, &repeat, &offset, &status);
      printf("Column 8 repeat and offset = %ld %ld\n", repeat, offset);
    }

    /*
      #####################################
      #  create another image extension   #
      #####################################
    */

    bitpix = 32;
    naxis = 2;
    naxes[0] = 10;
    naxes[1] = 2;
    npixels = 20;
 
/*    ffcrim(fptr, bitpix, naxis, naxes, &status); */
    ffiimg(fptr, bitpix, naxis, naxes, &status);
    printf("\nffcrim status = %d\n", status);

    /* initialize arrays of values to write to primary array */
    for (ii = 0; ii < npixels; ii++)
    {
        boutarray[ii] = (unsigned char) (ii * 2);
        ioutarray[ii] = (short) (ii * 2);
        joutarray[ii] = ii * 2;
        koutarray[ii] = ii * 2;
        eoutarray[ii] = (float) (ii * 2);
        doutarray[ii] = ii * 2;
    }

    /* write a few pixels with each datatype */
    ffppr(fptr, TBYTE,   1,  2, &boutarray[0],  &status);
    ffppr(fptr, TSHORT,  3,  2, &ioutarray[2],  &status);
    ffppr(fptr, TINT,    5,  2, &koutarray[4],  &status);
    ffppr(fptr, TSHORT,  7,  2, &ioutarray[6],  &status);
    ffppr(fptr, TLONG,   9,  2, &joutarray[8],  &status);
    ffppr(fptr, TFLOAT,  11, 2, &eoutarray[10], &status);
    ffppr(fptr, TDOUBLE, 13, 2, &doutarray[12], &status);
    printf("ffppr status = %d\n", status);

    /* read back the pixels with each datatype */
    bnul = 0;
    inul = 0;
    knul = 0;
    jnul = 0;
    enul = 0.;
    dnul = 0.;

    ffgpv(fptr, TBYTE,   1,  14, &bnul, binarray, &anynull, &status);
    ffgpv(fptr, TSHORT,  1,  14, &inul, iinarray, &anynull, &status);
    ffgpv(fptr, TINT,    1,  14, &knul, kinarray, &anynull, &status);
    ffgpv(fptr, TLONG,   1,  14, &jnul, jinarray, &anynull, &status);
    ffgpv(fptr, TFLOAT,  1,  14, &enul, einarray, &anynull, &status);
    ffgpv(fptr, TDOUBLE, 1,  14, &dnul, dinarray, &anynull, &status);

    printf("\nImage values written with ffppr and read with ffgpv:\n");
    npixels = 14;
    for (ii = 0; ii < npixels; ii++)
        printf(" %2d", binarray[ii]);
    printf("  %d (byte)\n", anynull);  
    for (ii = 0; ii < npixels; ii++)
        printf(" %2d", iinarray[ii]);
    printf("  %d (short)\n", anynull);  
    for (ii = 0; ii < npixels; ii++)
        printf(" %2d", kinarray[ii]);
    printf("  %d (int)\n", anynull); 
    for (ii = 0; ii < npixels; ii++)
        printf(" %2ld", jinarray[ii]);
    printf("  %d (long)\n", anynull); 
    for (ii = 0; ii < npixels; ii++)
        printf(" %2.0f", einarray[ii]);
    printf("  %d (float)\n", anynull);
    for (ii = 0; ii < npixels; ii++)
        printf(" %2.0f", dinarray[ii]);
    printf("  %d (double)\n", anynull);

    /*
      ##########################################
      #  test world coordinate system routines #
      ##########################################
    */

    xrval = 45.83;
    yrval =  63.57;
    xrpix =  256.;
    yrpix =  257.;
    xinc =   -.00277777;
    yinc =   .00277777;

    /* write the WCS keywords */
    /* use example values from the latest WCS document */
    ffpkyd(fptr, "CRVAL1", xrval, 10, "comment", &status);
    ffpkyd(fptr, "CRVAL2", yrval, 10, "comment", &status);
    ffpkyd(fptr, "CRPIX1", xrpix, 10, "comment", &status);
    ffpkyd(fptr, "CRPIX2", yrpix, 10, "comment", &status);
    ffpkyd(fptr, "CDELT1", xinc, 10, "comment", &status);
    ffpkyd(fptr, "CDELT2", yinc, 10, "comment", &status);
 /*   ffpkyd(fptr, "CROTA2", rot, 10, "comment", &status); */
    ffpkys(fptr, "CTYPE1", xcoordtype, "comment", &status);
    ffpkys(fptr, "CTYPE2", ycoordtype, "comment", &status);
    printf("\nWrote WCS keywords status = %d\n",status);

    xrval =  0.;
    yrval =  0.;
    xrpix =  0.;
    yrpix =  0.;
    xinc =   0.;
    yinc =   0.;
    rot =    0.;

    ffgics(fptr, &xrval, &yrval, &xrpix,
           &yrpix, &xinc, &yinc, &rot, ctype, &status);
    printf("Read WCS keywords with ffgics status = %d\n",status);

    xpix = 0.5;
    ypix = 0.5;

    ffwldp(xpix,ypix,xrval,yrval,xrpix,yrpix,xinc,yinc,rot,ctype,
           &xpos, &ypos,&status);

    printf("  CRVAL1, CRVAL2 = %16.12f, %16.12f\n", xrval,yrval);
    printf("  CRPIX1, CRPIX2 = %16.12f, %16.12f\n", xrpix,yrpix);
    printf("  CDELT1, CDELT2 = %16.12f, %16.12f\n", xinc,yinc);
    printf("  Rotation = %10.3f, CTYPE = %s\n", rot, ctype);
    printf("Calculated sky coordinate with ffwldp status = %d\n",status);
    printf("  Pixels (%8.4f,%8.4f) --> (%11.6f, %11.6f) Sky\n",
            xpix,ypix,xpos,ypos);
    ffxypx(xpos,ypos,xrval,yrval,xrpix,yrpix,xinc,yinc,rot,ctype,
           &xpix, &ypix,&status);
    printf("Calculated pixel coordinate with ffxypx status = %d\n",status);
    printf("  Sky (%11.6f, %11.6f) --> (%8.4f,%8.4f) Pixels\n",
            xpos,ypos,xpix,ypix);
    /*
      ######################################
      #  append another ASCII table        #
      ######################################
    */

    strcpy(tform[0], "A15");
    strcpy(tform[1], "I11");
    strcpy(tform[2], "F15.6");
    strcpy(tform[3], "E13.5");
    strcpy(tform[4], "D22.14");

    strcpy(ttype[0], "Name");
    strcpy(ttype[1], "Ivalue");
    strcpy(ttype[2], "Fvalue");
    strcpy(ttype[3], "Evalue");
    strcpy(ttype[4], "Dvalue");

    strcpy(tunit[0], "");
    strcpy(tunit[1], "m**2");
    strcpy(tunit[2], "cm");
    strcpy(tunit[3], "erg/s");
    strcpy(tunit[4], "km/s");

    nrows = 11;
    tfields = 5;
    strcpy(tblname, "new_table");

    ffcrtb(fptr, ASCII_TBL, nrows, tfields, ttype, tform, tunit, tblname,
            &status);
    printf("\nffcrtb status = %d\n", status);

    extvers = 5;
    ffpkyj(fptr, "EXTVER", extvers, "extension version number", &status);

    ffpcl(fptr, TSTRING, 1, 1, 1, 3, onskey, &status);  /* write string values */

    /* initialize arrays of values to write */
    
    for (ii = 0; ii < npixels; ii++)
    {
        boutarray[ii] = (unsigned char) (ii * 3);
        ioutarray[ii] = (short) (ii * 3);
        joutarray[ii] = ii * 3;
        koutarray[ii] = ii * 3;
        eoutarray[ii] = (float) (ii * 3);
        doutarray[ii] = ii * 3;
    }

    for (ii = 2; ii < 6; ii++)   /* loop over cols 2 - 5 */
    {
        ffpcl(fptr, TBYTE,   ii, 1, 1, 2, boutarray,     &status); 
        ffpcl(fptr, TSHORT,  ii, 3, 1, 2, &ioutarray[2], &status);  
        ffpcl(fptr, TLONG,   ii, 5, 1, 2, &joutarray[4], &status);  
        ffpcl(fptr, TFLOAT,  ii, 7, 1, 2, &eoutarray[6], &status);
        ffpcl(fptr, TDOUBLE, ii, 9, 1, 2, &doutarray[8], &status); 
    }
    printf("ffpcl status = %d\n", status);

    /* read back the pixels with each datatype */
    ffgcv(fptr, TBYTE,   2, 1, 1, 10, &bnul, binarray, &anynull, &status);
    ffgcv(fptr, TSHORT,  2, 1, 1, 10, &inul, iinarray, &anynull, &status);
    ffgcv(fptr, TINT,    3, 1, 1, 10, &knul, kinarray, &anynull, &status);
    ffgcv(fptr, TLONG,   3, 1, 1, 10, &jnul, jinarray, &anynull, &status);
    ffgcv(fptr, TFLOAT,  4, 1, 1, 10, &enul, einarray, &anynull, &status);
    ffgcv(fptr, TDOUBLE, 5, 1, 1, 10, &dnul, dinarray, &anynull, &status);

    printf("\nColumn values written with ffpcl and read with ffgcl:\n");
    npixels = 10;
    for (ii = 0; ii < npixels; ii++)
        printf(" %2d", binarray[ii]);
    printf("  %d (byte)\n", anynull);  
    for (ii = 0; ii < npixels; ii++)
        printf(" %2d", iinarray[ii]);
    printf("  %d (short)\n", anynull);

    for (ii = 0; ii < npixels; ii++)
        printf(" %2d", kinarray[ii]);
    printf("  %d (int)\n", anynull); 

    for (ii = 0; ii < npixels; ii++)
        printf(" %2ld", jinarray[ii]);
    printf("  %d (long)\n", anynull); 
    for (ii = 0; ii < npixels; ii++)
        printf(" %2.0f", einarray[ii]);
    printf("  %d (float)\n", anynull);
    for (ii = 0; ii < npixels; ii++)
        printf(" %2.0f", dinarray[ii]);
    printf("  %d (double)\n", anynull);

    /*
      ###########################################################
      #  perform stress test by cycling thru all the extensions #
      ###########################################################
    */
    printf("\nRepeatedly move to the 1st 4 HDUs of the file:\n");
    for (ii = 0; ii < 10; ii++)
    {
      ffmahd(fptr,  1, &hdutype, &status);
      printf("%d", ffghdn(fptr, &hdunum));
      ffmrhd(fptr,  1, &hdutype, &status);
      printf("%d", ffghdn(fptr, &hdunum));
      ffmrhd(fptr,  1, &hdutype, &status);
      printf("%d", ffghdn(fptr, &hdunum));
      ffmrhd(fptr,  1, &hdutype, &status);
      printf("%d", ffghdn(fptr, &hdunum));
      ffmrhd(fptr, -1, &hdutype, &status);
      printf("%d", ffghdn(fptr, &hdunum));
      if (status > 0)
         break;
    }
    printf("\n");

    printf("Move to extensions by name and version number: (ffmnhd)\n");
    extvers = 1;
    ffmnhd(fptr, ANY_HDU, binname, (int) extvers, &status);
    ffghdn(fptr, &hdunum);
    printf(" %s, %ld = hdu %d, %d\n", binname, extvers, hdunum, status);
    extvers = 3;
    ffmnhd(fptr, ANY_HDU, binname, (int) extvers, &status);
    ffghdn(fptr, &hdunum);
    printf(" %s, %ld = hdu %d, %d\n", binname, extvers, hdunum, status);
    extvers = 4;
    ffmnhd(fptr, ANY_HDU, binname, (int) extvers, &status);
    ffghdn(fptr, &hdunum);
    printf(" %s, %ld = hdu %d, %d\n", binname, extvers, hdunum, status);


    strcpy(tblname, "Test-ASCII");
    extvers = 2;
    ffmnhd(fptr, ANY_HDU, tblname, (int) extvers, &status);
    ffghdn(fptr, &hdunum);
    printf(" %s, %ld = hdu %d, %d\n", tblname, extvers, hdunum, status);

    strcpy(tblname, "new_table");
    extvers = 5;
    ffmnhd(fptr, ANY_HDU, tblname, (int) extvers, &status);
    ffghdn(fptr, &hdunum);
    printf(" %s, %ld = hdu %d, %d\n", tblname, extvers, hdunum, status);
    extvers = 0;
    ffmnhd(fptr, ANY_HDU, binname, (int) extvers, &status);
    ffghdn(fptr, &hdunum);
    printf(" %s, %ld = hdu %d, %d\n", binname, extvers, hdunum, status);
    extvers = 17;
    ffmnhd(fptr, ANY_HDU, binname, (int) extvers, &status);
    ffghdn(fptr, &hdunum);
    printf(" %s, %ld = hdu %d, %d", binname, extvers, hdunum, status);
    printf (" (expect a 301 error status here)\n");
    status = 0;

    ffthdu(fptr, &hdunum, &status);
    printf("Total number of HDUs in the file = %d\n", hdunum);
    /*
      ########################
      #  checksum tests      #
      ########################
    */
    checksum = 1234567890;
    ffesum(checksum, 0, asciisum);
    printf("\nEncode checksum: %lu -> %s\n", checksum, asciisum);
    checksum = 0;
    ffdsum(asciisum, 0, &checksum);
    printf("Decode checksum: %s -> %lu\n", asciisum, checksum);

    ffpcks(fptr, &status);

    /*
       don't print the CHECKSUM value because it is different every day
       because the current date is in the comment field.

       ffgcrd(fptr, "CHECKSUM", card, &status);
       printf("%s\n", card);
    */

    ffgcrd(fptr, "DATASUM", card, &status);
    printf("%.30s\n", card);

    ffgcks(fptr, &datsum, &checksum, &status);
    printf("ffgcks data checksum, status = %lu, %d\n",
            datsum, status);

    ffvcks(fptr, &datastatus, &hdustatus, &status); 
    printf("ffvcks datastatus, hdustatus, status = %d %d %d\n",
              datastatus, hdustatus, status);
 
    ffprec(fptr,
    "new_key = 'written by fxprec' / to change checksum", &status);
    ffupck(fptr, &status);
    printf("ffupck status = %d\n", status);

    ffgcrd(fptr, "DATASUM", card, &status);
    printf("%.30s\n", card);
    ffvcks(fptr, &datastatus, &hdustatus, &status); 
    printf("ffvcks datastatus, hdustatus, status = %d %d %d\n",
              datastatus, hdustatus, status);
 
    /*
      delete the checksum keywords, so that the FITS file is always
      the same, regardless of the date of when testprog is run.
    */

    ffdkey(fptr, "CHECKSUM", &status);
    ffdkey(fptr, "DATASUM",  &status);

    /*
      ############################
      #  close file and quit     #
      ############################
    */

 errstatus:  /* jump here on error */

    ffclos(fptr, &status); 
    printf("ffclos status = %d\n", status);

    printf("\nNormally, there should be 8 error messages on the stack\n");
    printf("all regarding 'numerical overflows':\n");

    ffgmsg(errmsg);
    nmsg = 0;

    while (errmsg[0])
    {
        printf(" %s\n", errmsg);
        nmsg++;
        ffgmsg(errmsg);
    }

    if (nmsg != 8)
        printf("\nWARNING: Did not find the expected 8 error messages!\n");

    ffgerr(status, errmsg);
    printf("\nStatus = %d: %s\n", status, errmsg);

    /* free the allocated memory */
    for (ii = 0; ii < 21; ii++) 
        free(inskey[ii]);   
    for (ii = 0; ii < 10; ii++)
    {
      free(ttype[ii]);
      free(tform[ii]);
      free(tunit[ii]);
    }

    return(status);
}

cfitsio/testprog.out0000644000225700000360000007673713246025103014424 0ustar  cagordonlheaCFITSIO TESTPROG

Try opening then closing a nonexistent file:
  ffopen fptr, status  = 0 104 (expect an error)
  ffclos status = 115

ffinit create new file status = 0
Name of file = testprog.fit, I/O mode = 1

test writing of long string keywords:
 123456789012345678901234567890123456789012345678901234567890123456789012345
'12345678901234567890123456789012345678901234567890123456789012345678'
 1234567890123456789012345678901234567890123456789012345678901234'6789012345
'1234567890123456789012345678901234567890123456789012345678901234''67'
 1234567890123456789012345678901234567890123456789012345678901234''789012345
'1234567890123456789012345678901234567890123456789012345678901234'''''
 1234567890123456789012345678901234567890123456789012345678901234567'9012345
'1234567890123456789012345678901234567890123456789012345678901234567'
ffflus status = 0
HDU number = 1

Values read back from primary array (99 = null pixel)
The 1st, and every 4th pixel should be undefined:
 99  2  3 99  5  6  7 99  9 10 11 99 13 14 15 99 17 18 19 99  1 (ffgpvb)
 99  2  3 99  5  6  7 99  9 10 11 99 13 14 15 99 17 18 19 99  1 (ffgpvi)
 99  2  3 99  5  6  7 99  9 10 11 99 13 14 15 99 17 18 19 99  1 (ffgpvj)
 99  2  3 99  5  6  7 99  9 10 11 99 13 14 15 99 17 18 19 99  1 (ffgpve)
 99  2  3 99  5  6  7 99  9 10 11 99 13 14 15 99 17 18 19 99  1 (ffgpvd)
  *  2  3  *  5  6  7  *  9 10 11  * 13 14 15  * 17 18 19  *  1 (ffgpfb)
  *  2  3  *  5  6  7  *  9 10 11  * 13 14 15  * 17 18 19  *  1 (ffgpfi)
  *  2  3  *  5  6  7  *  9 10 11  * 13 14 15  * 17 18 19  *  1 (ffgpfj)
  *  2  3  *  5  6  7  *  9 10 11  * 13 14 15  * 17 18 19  *  1 (ffgpfe)
  *  2  3  *  5  6  7  *  9 10 11  * 13 14 15  * 17 18 19  *  1 (ffgpfd)

Closed then reopened the FITS file 10 times.
HDU number = 1
Name of file = testprog.fit, I/O mode = 1

Read back keywords:
simple = 1, bitpix = 32, naxis = 2, naxes = (10, 2)
  pcount = 0, gcount = 1, extend = 1
KEY_PREC= 'This keyword was written by fxprec' / comment goes here
KEY_PREC : 'This keyword was written by fxprec' : comment goes here :
KEY_PREC= 'This keyword was written by fxprec' / comment goes here
KY_PKNS1 : 'first string' : fxpkns comment :
KEY_PKYS value_string fxpkys comment 0
KEY_PKYL 1 fxpkyl comment 0
KEY_PKYJ 11 fxpkyj comment 0
KEY_PKYJ 11.000000 fxpkyj comment 0
KEY_PKYJ 11.000000 fxpkyj comment 0
KEY_PKY S value_string fxpkys comment 0
KEY_PKY L 1 fxpkyl comment 0
KEY_PKY BYTE 11 fxpkyj comment 0
KEY_PKY SHORT 11 fxpkyj comment 0
KEY_PKY INT 11 fxpkyj comment 0
KEY_PKY J 11 fxpkyj comment 0
KEY_PKY E 13.131310 fxpkye comment 0
KEY_PKY D 15.151515 fxpkyd comment 0
KEY_PKYF 12.121210 fxpkyf comment 0
KEY_PKYE 13.131310 fxpkye comment 0
KEY_PKYG 14.14141414141414 fxpkyg comment 0
KEY_PKYD 15.15151515151520 fxpkyd comment 0
KEY_PKYC 13.131310 14.141410 fxpkyc comment 0
KEY_PKFC 13.131313 14.141414 fxpkfc comment 0
KEY_PKYM 15.151515 16.161616 fxpkym comment 0
KEY_PKFM 15.151515 16.161616 fxpkfm comment 0
KEY_PKYT 12345678 0.12345678901235 fxpkyt comment 0
KEY_PKY J 11 [km/s/Mpc] fxpkyj comment 0
KEY_PKY units = km/s/Mpc
KEY_PKY J 11 fxpkyj comment 0
KEY_PKY units = 
KEY_PKY J 11 [feet/second/second] fxpkyj comment 0
KEY_PKY units = feet/second/second
KEY_PKLS long string value = 
This is a very long string value that is continued over more than one keyword.
header contains 65 keywords; located at keyword 27 
ffgkns:  first string, second string, 
ffgknl:  1, 0, 1
ffgknj:  11, 12, 13
ffgkne:  13.131310, 14.141410, 15.151520
ffgknd:  15.151515, 16.161616, 17.171717

Before deleting the HISTORY and DATE keywords...
COMMENT 
HISTORY 
DATE    
KY_PKNS1

After deleting the keywords...
COMMENT   This keyword was written by fxpcom.
KY_PKNS1= 'first string'       / fxpkns comment

After inserting the keywords...
COMMENT   This keyword was written by fxpcom.
KY_IREC = 'This keyword inserted by fxirec'
KY_IKYS = 'insert_value_string' / ikys comment
KY_IKYJ =                   49 / ikyj comment
KY_IKYL =                    T / ikyl comment
KY_IKYE =           1.2346E+01 / ikye comment
KY_IKYD = 1.23456789012346E+01 / ikyd comment
KY_IKYF =              12.3456 / ikyf comment
KY_IKYG =     12.3456789012346 / ikyg comment
KY_PKNS1= 'first string'       / fxpkns comment

After modifying the keywords...
COMMENT   This keyword was modified by fxmrec
KY_MREC = 'This keyword was modified by fxmcrd'
NEWIKYS = 'modified_string'    / ikys comment
KY_IKYJ =                   50 / This is a modified comment
KY_IKYL =                    F / ikyl comment
KY_IKYE =          -1.2346E+01 / ikye comment
KY_IKYD = -1.23456789012346E+01 / modified comment
KY_IKYF =             -12.3456 / ikyf comment
KY_IKYG =    -12.3456789012346 / ikyg comment
KY_PKNS1= 'first string'       / fxpkns comment

After updating the keywords...
COMMENT   This keyword was modified by fxmrec
KY_UCRD = 'This keyword was updated by fxucrd'
NEWIKYS = 'updated_string'     / ikys comment
KY_IKYJ =                   51 / This is a modified comment
KY_IKYL =                    T / ikyl comment
KY_IKYE =          -1.3346E+01 / ikye comment
KY_IKYD = -1.33456789012346E+01 / modified comment
KY_IKYF =             -13.3456 / ikyf comment
KY_IKYG =    -13.3456789012346 / ikyg comment
KY_PKNS1= 'first string'       / fxpkns comment

Keywords found using wildcard search (should be 13)...
KEY_PKYS= 'value_string'       / fxpkys comment
KEY_PKYL=                    T / fxpkyl comment
KEY_PKYJ=                   11 / [feet/second/second] fxpkyj comment
KEY_PKYF=             12.12121 / fxpkyf comment
KEY_PKYE=         1.313131E+01 / fxpkye comment
KEY_PKYG=    14.14141414141414 / fxpkyg comment
KEY_PKYD= 1.51515151515152E+01 / fxpkyd comment
KEY_PKYC= (1.313131E+01, 1.414141E+01) / fxpkyc comment
KEY_PKYM= (1.51515151515152E+01, 1.61616161616162E+01) / fxpkym comment
KEY_PKFC= (13.131313, 14.141414) / fxpkfc comment
KEY_PKFM= (15.15151515151515, 16.16161616161616) / fxpkfm comment
KEY_PKYT= 12345678.1234567890123456 / fxpkyt comment
NEWIKYS = 'updated_string'     / ikys comment

Copied keyword: ffgkne:  14.141410, 15.151520, 13.131310
Updated header using template file (ffpktp)

ffibin status = 0
HDU number = 2
header contains 33 keywords; located at keyword 1 
header contains 33 keywords with room for 74 more
TDIM3 = (1,2,8), 3, 1, 2, 8
ffpcl_ status = 0

Find the column numbers; a returned status value of 237 is
expected and indicates that more than one column name matches
the input column name template.  Status = 219 indicates that
there was no matching column name.
Column Xvalue is number 3; status = 0.
Column Avalue is number 1; status = 237.
Column Lvalue is number 2; status = 237.
Column Xvalue is number 3; status = 237.
Column Bvalue is number 4; status = 237.
Column Ivalue is number 5; status = 237.
Column Jvalue is number 6; status = 237.
Column Evalue is number 7; status = 237.
Column Dvalue is number 8; status = 237.
Column Cvalue is number 9; status = 237.
Column Mvalue is number 10; status = 237.
Column  is number 0; status = 219.

Information about each column:
 15A  16 15 15 Avalue, , A, 15, 1.000000, 0.000000, 1234554321, .
  1L  14  1  1 Lvalue, m**2, L, 1, 1.000000, 0.000000, 1234554321, .
 16X   1 16  1 Xvalue, cm, X, 16, 1.000000, 0.000000, 1234554321, .
  1B  11  1  1 Bvalue, erg/s, B, 1, 1.000000, 0.000000, 99, .
  1I  21  1  2 Ivalue, km/s, I, 1, 1.000000, 0.000000, 99, .
  1J  41  1  4 Jvalue, , J, 1, 1.000000, 0.000000, 99, .
  1E  42  1  4 Evalue, , E, 1, 1.000000, 0.000000, 1234554321, .
  1D  82  1  8 Dvalue, , D, 1, 1.000000, 0.000000, 1234554321, .
  1C  83  1  8 Cvalue, , C, 1, 1.000000, 0.000000, 1234554321, .
  1M 163  1 16 Mvalue, , M, 1, 1.000000, 0.000000, 1234554321, .

ffitab status = 0
HDU number = 2
ffpcl_ status = 0

ASCII table: rowlen, nrows, tfields, extname: 76 11 5 Test-ASCII
    Name   1      A15          
  Ivalue  17      I10     m**2 
  Fvalue  28    F14.6       cm 
  Evalue  43    E12.5    erg/s 
  Dvalue  56   D21.14     km/s 

Data values read from ASCII table:
   first string  1  1  1  1.0  1.0
  second string  2  2  2  2.0  2.0
                 3  3  3  3.0  3.0
      UNDEFINED  4  4  4  4.0  4.0
                 5  5  5  5.0  5.0
                 6  6  6  6.0  6.0
                 7  7  7  7.0  7.0
                 8  8  8  8.0  8.0
                 9  9  9  9.0  9.0
                10 10 10 10.0 10.0
                99 99 99 99.0 99.0

      1       1.000000  1.00000E+00  1.00000000000000E+00second string        

Column name is number 1; status = 0.
Column Ivalue is number 2; status = 237.
Column Fvalue is number 3; status = 237.
Column Evalue is number 4; status = 237.
Column Dvalue is number 5; status = 237.
Column  is number 0; status = 219.
 A15  16  1 15 Name, 1, , A15, 1.000000, 0.000000, null1, .
 I10  41  1 10 Ivalue, 17, m**2, I10, 1.000000, 0.000000, null2, .
F14.6  82  1 14 Fvalue, 28, cm, F14.6, 1.000000, 0.000000, null3, .
E12.5  42  1 12 Evalue, 43, erg/s, E12.5, 1.000000, 0.000000, null4, .
D21.14  82  1 21 Dvalue, 56, km/s, D21.14, 1.000000, 0.000000, null5, .


Data values after inserting 3 rows after row 2:
   first string  1  1  1  1.0  1.0
  second string  2  2  2  2.0  2.0
                 0  0  0  0.0  0.0
                 0  0  0  0.0  0.0
                 0  0  0  0.0  0.0
                 3  3  3  3.0  3.0
      UNDEFINED  4  4  4  4.0  4.0
                 5  5  5  5.0  5.0
                 6  6  6  6.0  6.0
                 7  7  7  7.0  7.0
                 8  8  8  8.0  8.0
                 9  9  9  9.0  9.0
                10 10 10 10.0 10.0
                99 99 99 99.0 99.0

Data values after deleting 2 rows at row 10:
   first string  1  1  1  1.0  1.0
  second string  2  2  2  2.0  2.0
                 0  0  0  0.0  0.0
                 0  0  0  0.0  0.0
                 0  0  0  0.0  0.0
                 3  3  3  3.0  3.0
      UNDEFINED  4  4  4  4.0  4.0
                 5  5  5  5.0  5.0
                 6  6  6  6.0  6.0
                 9  9  9  9.0  9.0
                10 10 10 10.0 10.0
                99 99 99 99.0 99.0

Data values after deleting column 3:
   first string  1  1  1.0  1.0
  second string  2  2  2.0  2.0
                 0  0  0.0  0.0
                 0  0  0.0  0.0
                 0  0  0.0  0.0
                 3  3  3.0  3.0
      UNDEFINED  4  4  4.0  4.0
                 5  5  5.0  5.0
                 6  6  6.0  6.0
                 9  9  9.0  9.0
                10 10 10.0 10.0
                99 99 99.0 99.0

Data values after inserting column 5:
   first string  1  1  1.0  1.0 0
  second string  2  2  2.0  2.0 0
                 0  0  0.0  0.0 0
                 0  0  0.0  0.0 0
                 0  0  0.0  0.0 0
                 3  3  3.0  3.0 0
      UNDEFINED  4  4  4.0  4.0 0
                 5  5  5.0  5.0 0
                 6  6  6.0  6.0 0
                 9  9  9.0  9.0 0
                10 10 10.0 10.0 0
                99 99 99.0 99.0 0
Create temporary file: ffinit status = 0

Create null primary array: ffiimg status = 0

Create ASCII table with 0 columns: ffitab status = 0
copy column, ffcpcl status = 0
copy column, ffcpcl status = 0
copy column, ffcpcl status = 0
copy column, ffcpcl status = 0

Create Binary table with 0 columns: ffibin status = 0
copy column, ffcpcl status = 0
copy column, ffcpcl status = 0
copy column, ffcpcl status = 0
copy column, ffcpcl status = 0
Delete the tmp file: ffdelt status = 0
HDU number = 3
header contains 38 keywords with room for 69 more

Binary table: nrows, tfields, extname, pcount: 21 10 Test-BINTABLE 0
  Avalue      15A          
  Lvalue       1L     m**2 
  Xvalue      16X       cm 
  Bvalue       1B    erg/s 
  Ivalue       1I     km/s 
  Jvalue       1J          
  Evalue       1E          
  Dvalue       1D          
  Cvalue       1C          
  Mvalue       1M          

Data values read from binary table:
  Bit column (X) data values: 

01001100 01110000 11110000 01111100 00000000 

null string column value = -- (should be --)

Read columns with ffgcv_:
   first string 0  76  1   1   1   1.0   1.0 (  1.0, -2.0) (  1.0, -2.0) 
  second string 1 112  2   2   2   2.0   2.0 (  3.0, -4.0) (  3.0, -4.0) 
                0 240  3   3   3   3.0   3.0 (  5.0, -6.0) (  5.0, -6.0) 
    NOT DEFINED 0 124  0  -4  -4  -4.0  -4.0 (  7.0, -8.0) (  7.0, -8.0) 
    NOT DEFINED 1   0  5   5   5   5.0   5.0 (  9.0,-10.0) (  9.0,-10.0) 
    NOT DEFINED 1   0  0  -6  -6  -6.0  -6.0 ( 11.0,-12.0) ( 11.0,-12.0) 
    NOT DEFINED 0   0  7   7   7   7.0   7.0 ( 13.0,-14.0) ( 13.0,-14.0) 
    NOT DEFINED 0   0  0  -8  -8  -8.0  -8.0 ( 15.0,-16.0) ( 15.0,-16.0) 
    NOT DEFINED 0   0  9   9   9   9.0   9.0 ( 17.0,-18.0) ( 17.0,-18.0) 
    NOT DEFINED 1   0  0 -10 -10 -10.0 -10.0 ( 19.0,-20.0) ( 19.0,-20.0) 
    NOT DEFINED 0   0 98  98  98  98.0  98.0 (  0.0,  0.0) (  0.0,  0.0) 
    NOT DEFINED 1   0 12  12  12  12.0  12.0 (  0.0,  0.0) (  0.0,  0.0) 
    NOT DEFINED 0   0 98  98  98  98.0  98.0 (  0.0,  0.0) (  0.0,  0.0) 
    NOT DEFINED 0   0  0 -14 -14 -14.0 -14.0 (  0.0,  0.0) (  0.0,  0.0) 
    NOT DEFINED 0   0 98  98  98  98.0  98.0 (  0.0,  0.0) (  0.0,  0.0) 
    NOT DEFINED 0   0  0 -16 -16 -16.0 -16.0 (  0.0,  0.0) (  0.0,  0.0) 
    NOT DEFINED 1   0 98  98  98  98.0  98.0 (  0.0,  0.0) (  0.0,  0.0) 
    NOT DEFINED 1   0  0 -18 -18 -18.0 -18.0 (  0.0,  0.0) (  0.0,  0.0) 
    NOT DEFINED 1   0 98  98  98  98.0  98.0 (  0.0,  0.0) (  0.0,  0.0) 
    NOT DEFINED 1   0  0 -20 -20 -20.0 -20.0 (  0.0,  0.0) (  0.0,  0.0) 
    NOT DEFINED 0   0 98  98  98  98.0  98.0 (  0.0,  0.0) (  0.0,  0.0) 

Read columns with ffgcf_:
   first string 0  76  1   1   1   1.0   1.0 (  1.0, -2.0) (  1.0, -2.0)
  second string 1 112  2   2   2   2.0   2.0 (  3.0, -4.0) (  3.0, -4.0)
                0 240  3   3   3   3.0   3.0 (  5.0, -6.0) (  5.0, -6.0)
                0 124  0  -4  -4  -4.0  -4.0 (  7.0, -8.0) (  7.0, -8.0)
                1   0  5   5   5   5.0   5.0 (  9.0,-10.0) (  9.0,-10.0)
                1   0  0  -6  -6  -6.0  -6.0 ( 11.0,-12.0) ( 11.0,-12.0)
                0   0  7   7   7   7.0   7.0 ( 13.0,-14.0) ( 13.0,-14.0)
                0   0  0  -8  -8  -8.0  -8.0 ( 15.0,-16.0) ( 15.0,-16.0)
                0   0  9   9   9   9.0   9.0 ( 17.0,-18.0) ( 17.0,-18.0)
                1   0  0 -10 -10 -10.0 -10.0 ( 19.0,-20.0) ( 19.0,-20.0)
                0   0 99  99 
                1   0 12  12 
                0   0 99  99 
                0   0  0 -14 
                0   0 99  99 
                0   0  0 -16 
                1   0 99  99 
                1   0  0 -18 
                1   0 99  99 
                1   0  0 -20 
                0   0 99  99 

Data values after inserting 3 rows after row 2:
   first string  1   1   1   1.0   1.0
  second string  2   2   2   2.0   2.0
    NOT DEFINED  0   0   0   0.0   0.0
    NOT DEFINED  0   0   0   0.0   0.0
    NOT DEFINED  0   0   0   0.0   0.0
                 3   3   3   3.0   3.0
    NOT DEFINED  0  -4  -4  -4.0  -4.0
    NOT DEFINED  5   5   5   5.0   5.0
    NOT DEFINED  0  -6  -6  -6.0  -6.0
    NOT DEFINED  7   7   7   7.0   7.0
    NOT DEFINED  0  -8  -8  -8.0  -8.0
    NOT DEFINED  9   9   9   9.0   9.0
    NOT DEFINED  0 -10 -10 -10.0 -10.0
    NOT DEFINED 98  98  98  98.0  98.0

Data values after deleting 2 rows at row 10:
   first string  1   1   1   1.0   1.0
  second string  2   2   2   2.0   2.0
    NOT DEFINED  0   0   0   0.0   0.0
    NOT DEFINED  0   0   0   0.0   0.0
    NOT DEFINED  0   0   0   0.0   0.0
                 3   3   3   3.0   3.0
    NOT DEFINED  0  -4  -4  -4.0  -4.0
    NOT DEFINED  5   5   5   5.0   5.0
    NOT DEFINED  0  -6  -6  -6.0  -6.0
    NOT DEFINED  9   9   9   9.0   9.0
    NOT DEFINED  0 -10 -10 -10.0 -10.0
    NOT DEFINED 98  98  98  98.0  98.0

Data values after deleting column 6:
   first string  1   1   1.0   1.0
  second string  2   2   2.0   2.0
    NOT DEFINED  0   0   0.0   0.0
    NOT DEFINED  0   0   0.0   0.0
    NOT DEFINED  0   0   0.0   0.0
                 3   3   3.0   3.0
    NOT DEFINED  0  -4  -4.0  -4.0
    NOT DEFINED  5   5   5.0   5.0
    NOT DEFINED  0  -6  -6.0  -6.0
    NOT DEFINED  9   9   9.0   9.0
    NOT DEFINED  0 -10 -10.0 -10.0
    NOT DEFINED 98  98  98.0  98.0

Data values after inserting column 8:
   first string  1   1   1.0   1.0 0
  second string  2   2   2.0   2.0 0
    NOT DEFINED  0   0   0.0   0.0 0
    NOT DEFINED  0   0   0.0   0.0 0
    NOT DEFINED  0   0   0.0   0.0 0
                 3   3   3.0   3.0 0
    NOT DEFINED  0  -4  -4.0  -4.0 0
    NOT DEFINED  5   5   5.0   5.0 0
    NOT DEFINED  0  -6  -6.0  -6.0 0
    NOT DEFINED  9   9   9.0   9.0 0
    NOT DEFINED  0 -10 -10.0 -10.0 0
    NOT DEFINED 98  98  98.0  98.0 0

Values after setting 1st 10 elements in column 8 = null:
   first string  1   1   1.0   1.0 98
  second string  2   2   2.0   2.0 98
    NOT DEFINED  0   0   0.0   0.0 98
    NOT DEFINED  0   0   0.0   0.0 98
    NOT DEFINED  0   0   0.0   0.0 98
                 3   3   3.0   3.0 98
    NOT DEFINED  0  -4  -4.0  -4.0 98
    NOT DEFINED  5   5   5.0   5.0 98
    NOT DEFINED  0  -6  -6.0  -6.0 98
    NOT DEFINED  9   9   9.0   9.0 98
    NOT DEFINED  0 -10 -10.0 -10.0 0
    NOT DEFINED 98  98  98.0  98.0 0
Create temporary file: ffinit status = 0

Create null primary array: ffiimg status = 0

Create binary table with 0 columns: ffibin status = 0
copy column, ffcpcl status = 0
copy column, ffcpcl status = 0
copy column, ffcpcl status = 0
copy column, ffcpcl status = 0
copy column, ffcpcl status = 0
copy column, ffcpcl status = 0
copy column, ffcpcl status = 0
Delete the tmp file: ffdelt status = 0
ffibin status = 0
HDU number = 2
      0   1000  10000  33000  66000   -999
      0   1000  10000  32768  65535   -999
      0   1000  10000  32800  65500   -999

      0      1     10     33     66   -999
 -32768 -31768 -22768      0  32767   -999
     -1      9     99    327    654   -999

Create image extension: ffiimg status = 0
HDU number = 3

Wrote whole 2D array: ffp2di status = 0

Read whole 2D array: ffg2di status = 0
   0   1   2   3   4   5   6   7   8   9  10  11  12  13  14   0   0   0   0
  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24   0   0   0   0
  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34   0   0   0   0
  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44   0   0   0   0
  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54   0   0   0   0
  50  51  52  53  54  55  56  57  58  59  60  61  62  63  64   0   0   0   0
  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74   0   0   0   0
  70  71  72  73  74  75  76  77  78  79  80  81  82  83  84   0   0   0   0
  80  81  82  83  84  85  86  87  88  89  90  91  92  93  94   0   0   0   0
  90  91  92  93  94  95  96  97  98  99 100 101 102 103 104   0   0   0   0
 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114   0   0   0   0
 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124   0   0   0   0
 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134   0   0   0   0
 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144   0   0   0   0
 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154   0   0   0   0
 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164   0   0   0   0
 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174   0   0   0   0
 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184   0   0   0   0
 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194   0   0   0   0
 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204   0   0   0   0
 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214   0   0   0   0
 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224   0   0   0   0
 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234   0   0   0   0
 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244   0   0   0   0
 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0

Wrote subset 2D array: ffpssi status = 0

Read whole 2D array: ffg2di status = 0
   0   1   2   3   4   5   6   7   8   9  10  11  12  13  14   0   0   0   0
  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24   0   0   0   0
  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34   0   0   0   0
  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44   0   0   0   0
  40  41  42  43   0  -1  -2  -3  -4  -5  -6  -7  -8  -9  54   0   0   0   0
  50  51  52  53 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19  64   0   0   0   0
  60  61  62  63 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29  74   0   0   0   0
  70  71  72  73 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39  84   0   0   0   0
  80  81  82  83 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49  94   0   0   0   0
  90  91  92  93 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 104   0   0   0   0
 100 101 102 103 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 114   0   0   0   0
 110 111 112 113 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 124   0   0   0   0
 120 121 122 123 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 134   0   0   0   0
 130 131 132 133 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 144   0   0   0   0
 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154   0   0   0   0
 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164   0   0   0   0
 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174   0   0   0   0
 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184   0   0   0   0
 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194   0   0   0   0
 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204   0   0   0   0
 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214   0   0   0   0
 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224   0   0   0   0
 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234   0   0   0   0
 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244   0   0   0   0
 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0

Read subset of 2D array: ffgsvi status = 0
  41  43  -1  -3  -5  71  73 -31 -33 -35

Create image extension: ffiimg status = 0
HDU number = 4
Create temporary file: ffinit status = 0
Copy image extension to primary array of tmp file.
ffcopy status = 0
SIMPLE  =                    T / file does conform to FITS standard
BITPIX  =                   16 / number of bits per data pixel
NAXIS   =                    2 / number of data axes
NAXIS1  =                   15 / length of data axis 1
NAXIS2  =                   25 / length of data axis 2
EXTEND  =                    T / FITS dataset may contain extensions
Delete the tmp file: ffdelt status = 0
Delete the image extension; hdutype, status = 1 0
HDU number = 4
ffcrhd status = 0
Variable length arrays: ffphbn status = 0
ffpcl_ status = 0
PCOUNT = 4446
HDU number = 6
A   0
L  0 0
X  0 0
B  1 0
I  1 0
J  1 0
E  1 0
D  1 0
Column 8 repeat and offset = 1 14
A ab 0
L  0  1 0
X  0  1 0
B 99  2 0
I 99  2 0
J 99  2 0
E 99  2 0
D 99  2 0
Column 8 repeat and offset = 2 49
A abc 0
L  0  0  0 0
X  0  1  0 0
B  1 99  3 0
I  1 99  3 0
J  1 99  3 0
E  1 99  3 0
D  1 99  3 0
Column 8 repeat and offset = 3 105
A abcd 0
L  0  1  0  0 0
X  0  1  0  0 0
B  1  2 99  4 0
I  1  2 99  4 0
J  1  2 99  4 0
E  1  2 99  4 0
D  1  2 99  4 0
Column 8 repeat and offset = 4 182
A abcde 0
L  0  1  0  0  1 0
X  0  1  0  0  1 0
B  1  2  3 99  5 0
I  1  2  3 99  5 0
J  1  2  3 99  5 0
E  1  2  3 99  5 0
D  1  2  3 99  5 0
Column 8 repeat and offset = 5 280
A abcdef 0
L  0  1  0  0  0  1 0
X  0  1  0  0  1  1 0
B  1  2  3  4 99  6 0
I  1  2  3  4 99  6 0
J  1  2  3  4 99  6 0
E  1  2  3  4 99  6 0
D  1  2  3  4 99  6 0
Column 8 repeat and offset = 6 399
A abcdefg 0
L  0  1  0  0  1  0  0 0
X  0  1  0  0  1  1  0 0
B  1  2  3  4  5 99  7 0
I  1  2  3  4  5 99  7 0
J  1  2  3  4  5 99  7 0
E  1  2  3  4  5 99  7 0
D  1  2  3  4  5 99  7 0
Column 8 repeat and offset = 7 539
A abcdefgh 0
L  0  1  0  0  1  1  0  0 0
X  0  1  0  0  1  1  0  0 0
B  1  2  3  4  5  6 99  8 0
I  1  2  3  4  5  6 99  8 0
J  1  2  3  4  5  6 99  8 0
E  1  2  3  4  5  6 99  8 0
D  1  2  3  4  5  6 99  8 0
Column 8 repeat and offset = 8 700
A abcdefghi 0
L  0  1  0  0  1  1  0  0  0 0
X  0  1  0  0  1  1  0  0  0 0
B  1  2  3  4  5  6  7 99  9 0
I  1  2  3  4  5  6  7 99  9 0
J  1  2  3  4  5  6  7 99  9 0
E  1  2  3  4  5  6  7 99  9 0
D  1  2  3  4  5  6  7 99  9 0
Column 8 repeat and offset = 9 883
A abcdefghij 0
L  0  1  0  0  1  1  0  0  0  1 0
X  0  1  0  0  1  1  0  0  0  1 0
B  1  2  3  4  5  6  7  8 99 10 0
I  1  2  3  4  5  6  7  8 99 10 0
J  1  2  3  4  5  6  7  8 99 10 0
E  1  2  3  4  5  6  7  8 99 10 0
D  1  2  3  4  5  6  7  8 99 10 0
Column 8 repeat and offset = 10 1087
A abcdefghijk 0
L  0  1  0  0  1  1  0  0  0  0  1 0
X  0  1  0  0  1  1  0  0  0  1  1 0
B  1  2  3  4  5  6  7  8  9 99 11 0
I  1  2  3  4  5  6  7  8  9 99 11 0
J  1  2  3  4  5  6  7  8  9 99 11 0
E  1  2  3  4  5  6  7  8  9 99 11 0
D  1  2  3  4  5  6  7  8  9 99 11 0
Column 8 repeat and offset = 11 1312
A abcdefghijkl 0
L  0  1  0  0  1  1  0  0  0  1  0  1 0
X  0  1  0  0  1  1  0  0  0  1  1  1 0
B  1  2  3  4  5  6  7  8  9 10 99 12 0
I  1  2  3  4  5  6  7  8  9 10 99 12 0
J  1  2  3  4  5  6  7  8  9 10 99 12 0
E  1  2  3  4  5  6  7  8  9 10 99 12 0
D  1  2  3  4  5  6  7  8  9 10 99 12 0
Column 8 repeat and offset = 12 1558
A abcdefghijklm 0
L  0  1  0  0  1  1  0  0  0  1  1  0  0 0
X  0  1  0  0  1  1  0  0  0  1  1  1  0 0
B  1  2  3  4  5  6  7  8  9 10 11 99 13 0
I  1  2  3  4  5  6  7  8  9 10 11 99 13 0
J  1  2  3  4  5  6  7  8  9 10 11 99 13 0
E  1  2  3  4  5  6  7  8  9 10 11 99 13 0
D  1  2  3  4  5  6  7  8  9 10 11 99 13 0
Column 8 repeat and offset = 13 1825
A abcdefghijklmn 0
L  0  1  0  0  1  1  0  0  0  1  1  1  0  0 0
X  0  1  0  0  1  1  0  0  0  1  1  1  0  0 0
B  1  2  3  4  5  6  7  8  9 10 11 12 99 14 0
I  1  2  3  4  5  6  7  8  9 10 11 12 99 14 0
J  1  2  3  4  5  6  7  8  9 10 11 12 99 14 0
E  1  2  3  4  5  6  7  8  9 10 11 12 99 14 0
D  1  2  3  4  5  6  7  8  9 10 11 12 99 14 0
Column 8 repeat and offset = 14 2113
A abcdefghijklmno 0
L  0  1  0  0  1  1  0  0  0  1  1  1  0  0  0 0
X  0  1  0  0  1  1  0  0  0  1  1  1  0  0  0 0
B  1  2  3  4  5  6  7  8  9 10 11 12 13 99 15 0
I  1  2  3  4  5  6  7  8  9 10 11 12 13 99 15 0
J  1  2  3  4  5  6  7  8  9 10 11 12 13 99 15 0
E  1  2  3  4  5  6  7  8  9 10 11 12 13 99 15 0
D  1  2  3  4  5  6  7  8  9 10 11 12 13 99 15 0
Column 8 repeat and offset = 15 2422
A abcdefghijklmnop 0
L  0  1  0  0  1  1  0  0  0  1  1  1  0  0  0  0 0
X  0  1  0  0  1  1  0  0  0  1  1  1  0  0  0  0 0
B  1  2  3  4  5  6  7  8  9 10 11 12 13 14 99 16 0
I  1  2  3  4  5  6  7  8  9 10 11 12 13 14 99 16 0
J  1  2  3  4  5  6  7  8  9 10 11 12 13 14 99 16 0
E  1  2  3  4  5  6  7  8  9 10 11 12 13 14 99 16 0
D  1  2  3  4  5  6  7  8  9 10 11 12 13 14 99 16 0
Column 8 repeat and offset = 16 2752
A abcdefghijklmnopq 0
L  0  1  0  0  1  1  0  0  0  1  1  1  0  0  0  0  1 0
X  0  1  0  0  1  1  0  0  0  1  1  1  0  0  0  0  1 0
B  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 99 17 0
I  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 99 17 0
J  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 99 17 0
E  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 99 17 0
D  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 99 17 0
Column 8 repeat and offset = 17 3104
A abcdefghijklmnopqr 0
L  0  1  0  0  1  1  0  0  0  1  1  1  0  0  0  0  0  1 0
X  0  1  0  0  1  1  0  0  0  1  1  1  0  0  0  0  1  1 0
B  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 99 18 0
I  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 99 18 0
J  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 99 18 0
E  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 99 18 0
D  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 99 18 0
Column 8 repeat and offset = 18 3477
A abcdefghijklmnopqrs 0
L  0  1  0  0  1  1  0  0  0  1  1  1  0  0  0  0  1  0  1 0
X  0  1  0  0  1  1  0  0  0  1  1  1  0  0  0  0  1  1  1 0
B  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 99 19 0
I  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 99 19 0
J  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 99 19 0
E  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 99 19 0
D  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 99 19 0
Column 8 repeat and offset = 19 3871
A abcdefghijklmnopqrst 0
L  0  1  0  0  1  1  0  0  0  1  1  1  0  0  0  0  1  1  0  1 0
X  0  1  0  0  1  1  0  0  0  1  1  1  0  0  0  0  1  1  1  1 0
B  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 99 20 0
I  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 99 20 0
J  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 99 20 0
E  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 99 20 0
D  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 99 20 0
Column 8 repeat and offset = 20 4286

ffcrim status = 0
ffppr status = 0

Image values written with ffppr and read with ffgpv:
  0  2  4  6  8 10 12 14 16 18 20 22 24 26  0 (byte)
  0  2  4  6  8 10 12 14 16 18 20 22 24 26  0 (short)
  0  2  4  6  8 10 12 14 16 18 20 22 24 26  0 (int)
  0  2  4  6  8 10 12 14 16 18 20 22 24 26  0 (long)
  0  2  4  6  8 10 12 14 16 18 20 22 24 26  0 (float)
  0  2  4  6  8 10 12 14 16 18 20 22 24 26  0 (double)

Wrote WCS keywords status = 0
Read WCS keywords with ffgics status = 0
  CRVAL1, CRVAL2 =  45.830000000000,  63.570000000000
  CRPIX1, CRPIX2 = 256.000000000000, 257.000000000000
  CDELT1, CDELT2 =  -0.002777770000,   0.002777770000
  Rotation =      0.000, CTYPE = -TAN
Calculated sky coordinate with ffwldp status = 0
  Pixels (  0.5000,  0.5000) --> (  47.385204,   62.848968) Sky
Calculated pixel coordinate with ffxypx status = 0
  Sky (  47.385204,   62.848968) --> (  0.5000,  0.5000) Pixels

ffcrtb status = 0
ffpcl status = 0

Column values written with ffpcl and read with ffgcl:
  0  3  6  9 12 15 18 21 24 27  0 (byte)
  0  3  6  9 12 15 18 21 24 27  0 (short)
  0  3  6  9 12 15 18 21 24 27  0 (int)
  0  3  6  9 12 15 18 21 24 27  0 (long)
  0  3  6  9 12 15 18 21 24 27  0 (float)
  0  3  6  9 12 15 18 21 24 27  0 (double)

Repeatedly move to the 1st 4 HDUs of the file:
12343123431234312343123431234312343123431234312343
Move to extensions by name and version number: (ffmnhd)
 Test-BINTABLE, 1 = hdu 5, 0
 Test-BINTABLE, 3 = hdu 2, 0
 Test-BINTABLE, 4 = hdu 6, 0
 Test-ASCII, 2 = hdu 4, 0
 new_table, 5 = hdu 8, 0
 Test-BINTABLE, 0 = hdu 2, 0
 Test-BINTABLE, 17 = hdu 2, 301 (expect a 301 error status here)
Total number of HDUs in the file = 8

Encode checksum: 1234567890 -> dCW2fBU0dBU0dBU0
Decode checksum: dCW2fBU0dBU0dBU0 -> 1234567890
DATASUM = '475248536'         
ffgcks data checksum, status = 475248536, 0
ffvcks datastatus, hdustatus, status = 1 1 0
ffupck status = 0
DATASUM = '475248536'         
ffvcks datastatus, hdustatus, status = 1 1 0
ffclos status = 0

Normally, there should be 8 error messages on the stack
all regarding 'numerical overflows':
 Numerical overflow during type conversion while writing FITS data.
 Numerical overflow during type conversion while writing FITS data.
 Numerical overflow during type conversion while writing FITS data.
 Numerical overflow during type conversion while writing FITS data.
 Numerical overflow during type conversion while writing FITS data.
 Numerical overflow during type conversion while writing FITS data.
 Numerical overflow during type conversion while writing FITS data.
 Numerical overflow during type conversion while writing FITS data.

Status = 0: OK - no error
cfitsio/testprog.std0000644000225700000360000020700013246025103014362 0ustar  cagordonlheaSIMPLE  =                    T / file does conform to FITS standard             BITPIX  =                   32 / number of bits per data pixel                  NAXIS   =                    2 / number of data axes                            NAXIS1  =                   10 / length of data axis 1                          NAXIS2  =                    2 / length of data axis 2                          EXTEND  =                    T / FITS dataset may contain extensions            COMMENT   FITS (Flexible Image Transport System) format is defined in 'AstronomyCOMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H KEY_PREC= 'This keyword was written by fxprec' / comment goes here              CARD1   = '12345678901234567890123456789012345678901234567890123456789012345678'CARD2   = '1234567890123456789012345678901234567890123456789012345678901234''67'CARD3   = '1234567890123456789012345678901234567890123456789012345678901234'''''CARD4   = '1234567890123456789012345678901234567890123456789012345678901234567' KEY_PKYS= 'value_string'       / fxpkys comment                                 KEY_PKYL=                    T / fxpkyl comment                                 KEY_PKYJ=                   11 / [feet/second/second] fxpkyj comment            KEY_PKYF=             12.12121 / fxpkyf comment                                 KEY_PKYE=         1.313131E+01 / fxpkye comment                                 KEY_PKYG=    14.14141414141414 / fxpkyg comment                                 KEY_PKYD= 1.51515151515152E+01 / fxpkyd comment                                 KEY_PKYC= (1.313131E+01, 1.414141E+01) / fxpkyc comment                         KEY_PKYM= (1.51515151515152E+01, 1.61616161616162E+01) / fxpkym comment         KEY_PKFC= (13.131313, 14.141414) / fxpkfc comment                               KEY_PKFM= (15.15151515151515, 16.16161616161616) / fxpkfm comment               KEY_PKLS= 'This is a very long string value that is continued over more than o&'CONTINUE  'ne keyword.'        / fxpkls comment                                 LONGSTRN= 'OGIP 1.0'           / The HEASARC Long String Convention may be used.COMMENT   This FITS file may contain long string keyword values that are        COMMENT   continued over multiple keywords.  The HEASARC convention uses the &  COMMENT   character at the end of each substring which is then continued        COMMENT   on the next keyword which has the name CONTINUE.                      KEY_PKYT= 12345678.1234567890123456 / fxpkyt comment                            COMMENT   This keyword was modified by fxmrec                                   KY_UCRD = 'This keyword was updated by fxucrd'                                  NEWIKYS = 'updated_string'     / ikys comment                                   KY_IKYJ =                   51 / This is a modified comment                     KY_IKYL =                    T / ikyl comment                                   KY_IKYE =          -1.3346E+01 / ikye comment                                   KY_IKYD = -1.33456789012346E+01 / modified comment                              KY_IKYF =             -13.3456 / ikyf comment                                   KY_IKYG =    -13.3456789012346 / ikyg comment                                   KY_PKNS1= 'first string'       / fxpkns comment                                 KY_PKNS2= 'second string'      / fxpkns comment                                 KY_PKNS3= '        '           / fxpkns comment                                 KY_PKNL1=                    T / fxpknl comment                                 KY_PKNL2=                    F / fxpknl comment                                 KY_PKNL3=                    T / fxpknl comment                                 KY_PKNJ1=                   11 / fxpknj comment                                 KY_PKNJ2=                   12 / fxpknj comment                                 KY_PKNJ3=                   13 / fxpknj comment                                 KY_PKNF1=             12.12121 / fxpknf comment                                 KY_PKNF2=             13.13131 / fxpknf comment                                 KY_PKNF3=             14.14141 / fxpknf comment                                 KY_PKNE1=         1.313131E+01 / fxpkne comment                                 KY_PKNE2=         1.414141E+01 / fxpkne comment                                 KY_PKNE3=         1.515152E+01 / fxpkne comment                                 KY_PKNG1=     14.1414141414141 / fxpkng comment                                 KY_PKNG2=     15.1515151515152 / fxpkng comment                                 KY_PKNG3=     16.1616161616162 / fxpkng comment                                 KY_PKND1= 1.51515151515152E+01 / fxpknd comment                                 KY_PKND2= 1.61616161616162E+01 / fxpknd comment                                 KY_PKND3= 1.71717171717172E+01 / fxpknd comment                                 TSTRING = '1       '           / tstring comment                                TLOGICAL=                    T / tlogical comment                               TBYTE   =                   11 / tbyte comment                                  TSHORT  =                   21 / tshort comment                                 TINT    =                   31 / tint comment                                   TLONG   =                   41 / tlong comment                                  TFLOAT  =                  42. / tfloat comment                                 TDOUBLE =                  82. / tdouble comment                                BLANK   =                  -99 / value to use for undefined pixels              KY_PKNE4=         1.313131E+01 / fxpkne comment                                 TMPCARDA=                 1001 / this is the 1st template card                  TMPCARD2= 'ABCD    '           / this is the 2nd template card                  TMPCARD3=              1001.23 / this is the 3rd template card                  COMMENT this is the 5th template card                                           HISTORY this is the 6th template card                                           TMPCARD7=                      / comment for null keyword                       END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ÿÿÿÿÿÿÿÿÿ	
ÿÿÿ
ÿÿÿÿÿÿXTENSION= 'BINTABLE'           / binary table extension                         BITPIX  =                    8 / 8-bit bytes                                    NAXIS   =                    2 / 2-dimensional binary table                     NAXIS1  =                   61 / width of table in bytes                        NAXIS2  =                   20 / number of rows in table                        PCOUNT  =                    0 / size of special data area                      GCOUNT  =                    1 / one data group (required keyword)              TFIELDS =                   10 / number of fields in each row                   TTYPE1  = 'Avalue  '           / label for field   1                            TFORM1  = '15A     '           / data format of field: ASCII Character          TTYPE2  = 'Lvalue  '           / label for field   2                            TFORM2  = '1L      '           / data format of field: 1-byte LOGICAL           TUNIT2  = 'm**2    '           / physical unit of field                         TTYPE3  = 'Xvalue  '           / label for field   3                            TFORM3  = '16X     '           / data format of field: BIT                      TUNIT3  = 'cm      '           / physical unit of field                         TTYPE4  = 'Bvalue  '           / label for field   4                            TFORM4  = '1B      '           / data format of field: BYTE                     TUNIT4  = 'erg/s   '           / physical unit of field                         TTYPE5  = 'Ivalue  '           / label for field   5                            TFORM5  = '1I      '           / data format of field: 2-byte INTEGER           TUNIT5  = 'km/s    '           / physical unit of field                         TTYPE6  = 'Jvalue  '           / label for field   6                            TFORM6  = '1J      '           / data format of field: 4-byte INTEGER           TTYPE7  = 'Evalue  '           / label for field   7                            TFORM7  = '1E      '           / data format of field: 4-byte REAL              TTYPE8  = 'Dvalue  '           / label for field   8                            TFORM8  = '1D      '           / data format of field: 8-byte DOUBLE            TTYPE9  = 'Cvalue  '           / label for field   9                            TFORM9  = '1C      '           / data format of field: COMPLEX                  TTYPE10 = 'Mvalue  '           / label for field  10                            TFORM10 = '1M      '           / data format of field: DOUBLE COMPLEX           EXTNAME = 'Test-BINTABLE'      / name of this binary table extension            EXTVER  =                    3 / extension version number                       TNULL4  =                   77 / value for undefined pixels                     TNULL5  =                   77 / value for undefined pixels                     TNULL6  =                   77 / value for undefined pixels                     TSCAL4  =                 1000 / scaling factor                                 TSCAL5  =                    1 / scaling factor                                 TSCAL6  =                  100 / scaling factor                                 TZERO4  =                    0 / scaling offset                                 TZERO5  =                32768 / scaling offset                                 TZERO6  =                  100 / scaling offset                                 NEW_KEY = 'written by fxprec' / to change checksum                              END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             €ÿÿÿÿƒè	
§c!GBÿŽMMMXTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                  -32 / number of bits per data pixel                  NAXIS   =                    2 / number of data axes                            NAXIS1  =                   15 / length of data axis 1                          NAXIS2  =                   25 / length of data axis 2                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ?€@@@@€@ @À@àAAA A0A@APA`A A0A@APA`ApA€AˆAA˜A A¨A°A¸AÀA A¨A°A¸AÀAÈAÐAØAàAèAðAøBBBAðAøBBBBBBBBB B$B(B,B0B B$B(B,¿€ÀÀ@À€À ÀÀÀàÁÁBXBHBLBPBTÁ Á0Á@ÁPÁ`ÁpÁ€ÁˆÁÁ˜B€BpBtBxB|Á Á¨Á°Á¸ÁÀÁÈÁÐÁØÁàÁèB”BŒBŽBB’ÁðÁøÂÂÂÂÂÂÂÂB¨B B¢B¤B¦Â Â$Â(Â,Â0Â4Â8Â<Â@ÂDB¼B´B¶B¸BºÂHÂLÂPÂTÂXÂ\Â`ÂdÂhÂlBÐBÈBÊBÌBÎÂpÂtÂxÂ|€‚„†ˆŠBäBÜBÞBàB⌎’”–˜šœžBøBðBòBôBö ¢¤¦¨ª¬®°²CCCCC´¶¸º¼¾ÂÀÂÂÂÄÂÆCCC
CCCCCCCCCCCCCCCCCCCCCCCC C!C"C#C$C C!C"C#C$C%C&C'C(C)C*C+C,C-C.C*C+C,C-C.C/C0C1C2C3C4C5C6C7C8C4C5C6C7C8C9C:C;C<C=C>C?C@CACBC>C?C@CACBCCCDCECFCGCHCICJCKCLCHCICJCKCLCMCNCOCPCQCRCSCTCUCVCRCSCTCUCVCWCXCYCZC[C\C]C^C_C`C\C]C^C_C`CaCbCcCdCeCfCgChCiCjCfCgChCiCjCkClCmCnCoCpCqCrCsCtCpCqCrCsCtCuCvCwCxCyCzC{C|C}C~XTENSION= 'TABLE   '           / ASCII table extension                          BITPIX  =                    8 / 8-bit ASCII characters                         NAXIS   =                    2 / 2-dimensional ASCII table                      NAXIS1  =                   76 / width of table in characters                   NAXIS2  =                   12 / number of rows in table                        PCOUNT  =                    0 / no group parameters (required keyword)         GCOUNT  =                    1 / one data group (required keyword)              TFIELDS =                    5 / number of fields in each row                   TTYPE1  = 'Name    '           / label for field   1                            TBCOL1  =                    1 / beginning column of field   1                  TFORM1  = 'A15     '           / Fortran-77 format of field                     TTYPE2  = 'Ivalue  '           / label for field   2                            TBCOL2  =                   17 / beginning column of field   2                  TFORM2  = 'I10     '           / Fortran-77 format of field                     TUNIT2  = 'm**2    '           / physical unit of field                         TTYPE3  = 'Evalue  '           / label for field   4                            TBCOL3  =                   28 / beginning column of field   4                  TFORM3  = 'E12.5   '           / Fortran-77 format of field                     TUNIT3  = 'erg/s   '           / physical unit of field                         TTYPE4  = 'Dvalue  '           / label for field   5                            TBCOL4  =                   41 / beginning column of field   5                  TFORM4  = 'D21.14  '           / Fortran-77 format of field                     TUNIT4  = 'km/s    '           / physical unit of field                         EXTNAME = 'Test-ASCII'         / name of this ASCII table extension             EXTVER  =                    2 / extension version number                       TNULL1  = 'null1   '           / value for undefined pixels                     TNULL2  = 'null2   '           / value for undefined pixels                     TNULL3  = 'null4   '           / value for undefined pixels                     TNULL4  = 'null5   '           / value for undefined pixels                     TTYPE5  = 'INSERT_COL'         / label for field                                TFORM5  = 'F14.6   '           / format of field                                TBCOL5  =                   63 / beginning column of field                      END                                                                                                                                                                                                                                                                                                                             first string             1  1.00000E+00  1.00000000000000E+00               second string            2  2.00000E+00  2.00000000000000E+00                                                                                                                                                                                                                                                                            3  3.00000E+00  3.00000000000000E+00               null1                    4  4.00000E+00  4.00000000000000E+00                                        5  5.00000E+00  5.00000000000000E+00                                        6  6.00000E+00  6.00000000000000E+00                                        9  9.00000E+00  9.00000000000000E+00                                       10  1.00000E+01  1.00000000000000E+01                               null2      null4        null5                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               XTENSION= 'BINTABLE'           / binary table extension                         BITPIX  =                    8 / 8-bit bytes                                    NAXIS   =                    2 / 2-dimensional binary table                     NAXIS1  =                   61 / width of table in bytes                        NAXIS2  =                   22 / number of rows in table                        PCOUNT  =                    0 / size of special data area                      GCOUNT  =                    1 / one data group (required keyword)              TFIELDS =                   10 / number of fields in each row                   TTYPE1  = 'Avalue  '           / label for field   1                            TFORM1  = '15A     '           / data format of field: ASCII Character          TTYPE2  = 'Lvalue  '           / label for field   2                            TFORM2  = '1L      '           / data format of field: 1-byte LOGICAL           TUNIT2  = 'm**2    '           / physical unit of field                         TTYPE3  = 'Xvalue  '           / label for field   3                            TFORM3  = '16X     '           / data format of field: BIT                      TUNIT3  = 'cm      '           / physical unit of field                         TTYPE4  = 'Bvalue  '           / label for field   4                            TFORM4  = '1B      '           / data format of field: BYTE                     TUNIT4  = 'erg/s   '           / physical unit of field                         TTYPE5  = 'Ivalue  '           / label for field   5                            TFORM5  = '1I      '           / data format of field: 2-byte INTEGER           TUNIT5  = 'km/s    '           / physical unit of field                         TTYPE6  = 'Evalue  '           / label for field   7                            TFORM6  = '1E      '           / data format of field: 4-byte REAL              TTYPE7  = 'Dvalue  '           / label for field   8                            TFORM7  = '1D      '           / data format of field: 8-byte DOUBLE            TTYPE9  = 'Cvalue  '           / label for field   9                            TFORM9  = '1C      '           / data format of field: COMPLEX                  TTYPE10 = 'Mvalue  '           / label for field  10                            TFORM10 = '1M      '           / data format of field: DOUBLE COMPLEX           EXTNAME = 'Test-BINTABLE'      / name of this binary table extension            EXTVER  =                    1 / extension version number                       TNULL4  =                   99 / value for undefined pixels                     TNULL5  =                   99 / value for undefined pixels                     TDIM3   = '(1,2,8) '           / size of the multidimensional array             KEY_PREC= 'This keyword was written by f_prec' / comment here                   TTYPE8  = 'INSERT_COL'         / label for field                                TFORM8  = '1E      '           / format of field                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             first string   FLp?€?ðÿÿÿÿ?€À?ðÀsecond string  Tð|@@ÿÿÿÿ@@À€@Àÿÿÿÿÿÿÿÿÿÿÿÿ               F@@@ÿÿÿÿ@ ÀÀ@À              FÿüÀ€Àÿÿÿÿ@àÁ@À T@ @ÿÿÿÿAÁ @"À$TÿúÀÀÀÿÿÿÿA0Á@@&À(F		A@"ÿÿÿÿAˆÁ@1À2TÿöÁ À$A˜Á @3À4ccÿÿÿÿÿÿÿÿÿÿÿÿTA@@(FccÿÿÿÿÿÿÿÿÿÿÿÿFÿòÁ`À,FccÿÿÿÿÿÿÿÿÿÿÿÿFÿðÁ€À0TccÿÿÿÿÿÿÿÿÿÿÿÿTÿîÁÀ2TccÿÿÿÿÿÿÿÿÿÿÿÿTÿìÁ À4FccÿÿÿÿÿÿÿÿÿÿÿÿXTENSION= 'BINTABLE'           / binary table extension                         BITPIX  =                    8 / 8-bit bytes                                    NAXIS   =                    2 / 2-dimensional binary table                     NAXIS1  =                   80 / width of table in bytes                        NAXIS2  =                   20 / number of rows in table                        PCOUNT  =                 4446 / size of special data area                      GCOUNT  =                    1 / one data group (required keyword)              TFIELDS =                   10 / number of fields in each row                   TTYPE1  = 'Avalue  '           / label for field   1                            TFORM1  = '1PA(20) '           / data format of field: variable length array    TTYPE2  = 'Lvalue  '           / label for field   2                            TFORM2  = '1PL(20) '           / data format of field: variable length array    TUNIT2  = 'm**2    '           / physical unit of field                         TTYPE3  = 'Xvalue  '           / label for field   3                            TFORM3  = '1PB(3)  '           / data format of field: variable length array    TUNIT3  = 'cm      '           / physical unit of field                         TTYPE4  = 'Bvalue  '           / label for field   4                            TFORM4  = '1PB(20) '           / data format of field: variable length array    TUNIT4  = 'erg/s   '           / physical unit of field                         TTYPE5  = 'Ivalue  '           / label for field   5                            TFORM5  = '1PI(20) '           / data format of field: variable length array    TUNIT5  = 'km/s    '           / physical unit of field                         TTYPE6  = 'Jvalue  '           / label for field   6                            TFORM6  = '1PJ(20) '           / data format of field: variable length array    TTYPE7  = 'Evalue  '           / label for field   7                            TFORM7  = '1PE(20) '           / data format of field: variable length array    TTYPE8  = 'Dvalue  '           / label for field   8                            TFORM8  = '1PD(20) '           / data format of field: variable length array    TTYPE9  = 'Cvalue  '           / label for field   9                            TFORM9  = '1PC(0)  '           / data format of field: variable length array    TTYPE10 = 'Mvalue  '           / label for field  10                            TFORM10 = '1PM(0)  '           / data format of field: variable length array    EXTNAME = 'Test-BINTABLE'      / name of this binary table extension            EXTVER  =                    4 / extension version number                       TNULL4  =                   88 / value for undefined pixels                     TNULL5  =                   88 / value for undefined pixels                     TNULL6  =                   88 / value for undefined pixels                     END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
!)1ADGHKQ]i…‰ŠŽ–¦¶ÖÛàáæð@FLMS_w¿ÆÍÎÕãÿS[cdl|œ¼	ü				+	O	s
»
ÅÏ
Ñ
Û
ï

?𥧲Èô x„’ž¶æ
v
ƒ
’
Ÿ
¹
í
!‰—¥§µÑ	A±ÀÏÑàþ	:	v	î	þ


 
@
€
À@Qbev˜Ü ¨ºÌÏá

M
•%8KNa‡Ó·Ëßâön¾F?€?ðabT@XXXÿÿÿÿ@ÿÿÿÿÿÿÿÿ@abcFF@XXX?€ÿÿÿÿ@@?ðÿÿÿÿÿÿÿÿ@abcdFTF@XXX?€@ÿÿÿÿ@€?ð@ÿÿÿÿÿÿÿÿ@abcdeFTFTHXXX?€@@@ÿÿÿÿ@ ?ð@@ÿÿÿÿÿÿÿÿ@abcdefFTFFTLXXX?€@@@@€ÿÿÿÿ@À?ð@@@ÿÿÿÿÿÿÿÿ@abcdefgFTFFTFLXXX?€@@@@€@ ÿÿÿÿ@à?ð@@@@ÿÿÿÿÿÿÿÿ@abcdefghFTFFTTFLXXX?€@@@@€@ @ÀÿÿÿÿA?ð@@@@@ÿÿÿÿÿÿÿÿ@ abcdefghiFTFFTTFFLX	X	X	?€@@@@€@ @À@àÿÿÿÿA?ð@@@@@@ÿÿÿÿÿÿÿÿ@"abcdefghijFTFFTTFFTL@X
X
X
?€@@@@€@ @À@àAÿÿÿÿA ?ð@@@@@@@ ÿÿÿÿÿÿÿÿ@$abcdefghijkFTFFTTFFFTL`	X	X	X?€@@@@€@ @À@àAAÿÿÿÿA0?ð@@@@@@@ @"ÿÿÿÿÿÿÿÿ@&abcdefghijklFTFFTTFFFTTLp	
X	
X	
X?€@@@@€@ @À@àAAA ÿÿÿÿA@?ð@@@@@@@ @"@$ÿÿÿÿÿÿÿÿ@(abcdefghijklmFTFFTTFFFTTFLp	
X
	
X
	
X
?€@@@@€@ @À@àAAA A0ÿÿÿÿAP?ð@@@@@@@ @"@$@&ÿÿÿÿÿÿÿÿ@*abcdefghijklmnFTFFTTFFFTTTFLp	
X	
X	
X?€@@@@€@ @À@àAAA A0A@ÿÿÿÿA`?ð@@@@@@@ @"@$@&@(ÿÿÿÿÿÿÿÿ@,abcdefghijklmnoFTFFTTFFFTTTFFLp	

X	

X	

X?€@@@@€@ @À@àAAA A0A@APÿÿÿÿAp?ð@@@@@@@ @"@$@&@(@*ÿÿÿÿÿÿÿÿ@.abcdefghijklmnopFTFFTTFFFTTTFFFLp	

X	

X	

X?€@@@@€@ @À@àAAA A0A@APA`ÿÿÿÿA€?ð@@@@@@@ @"@$@&@(@*@,ÿÿÿÿÿÿÿÿ@0abcdefghijklmnopqFTFFTTFFFTTTFFFTLp€	

X	

X	

X?€@@@@€@ @À@àAAA A0A@APA`ApÿÿÿÿAˆ?ð@@@@@@@ @"@$@&@(@*@,@.ÿÿÿÿÿÿÿÿ@1abcdefghijklmnopqrFTFFTTFFFTTTFFFFTLpÀ	

X	

X	

X?€@@@@€@ @À@àAAA A0A@APA`ApA€ÿÿÿÿA?ð@@@@@@@ @"@$@&@(@*@,@.@0ÿÿÿÿÿÿÿÿ@2abcdefghijklmnopqrsFTFFTTFFFTTTFFFFTTLpà	

X	

X	

X?€@@@@€@ @À@àAAA A0A@APA`ApA€AˆÿÿÿÿA˜?ð@@@@@@@ @"@$@&@(@*@,@.@0@1ÿÿÿÿÿÿÿÿ@3abcdefghijklmnopqrstFTFFTTFFFTTTFFFFTTTLpð	

X	

X	

X?€@@@@€@ @À@àAAA A0A@APA`ApA€AˆAÿÿÿÿA ?ð@@@@@@@ @"@$@&@(@*@,@.@0@1@2ÿÿÿÿÿÿÿÿ@4XTENSION= 'IMAGE   '           / IMAGE extension                                BITPIX  =                   32 / number of bits per data pixel                  NAXIS   =                    2 / number of data axes                            NAXIS1  =                   10 / length of data axis 1                          NAXIS2  =                    2 / length of data axis 2                          PCOUNT  =                    0 / required keyword; must = 0                     GCOUNT  =                    1 / required keyword; must = 1                     CRVAL1  =     4.5830000000E+01 / comment                                        CRVAL2  =     6.3570000000E+01 / comment                                        CRPIX1  =     2.5600000000E+02 / comment                                        CRPIX2  =     2.5700000000E+02 / comment                                        CDELT1  =    -2.7777700000E-03 / comment                                        CDELT2  =     2.7777700000E-03 / comment                                        CTYPE1  = 'RA---TAN'           / comment                                        CTYPE2  = 'DEC--TAN'           / comment                                        END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
XTENSION= 'TABLE   '           / ASCII table extension                          BITPIX  =                    8 / 8-bit ASCII characters                         NAXIS   =                    2 / 2-dimensional ASCII table                      NAXIS1  =                   80 / width of table in characters                   NAXIS2  =                   11 / number of rows in table                        PCOUNT  =                    0 / no group parameters (required keyword)         GCOUNT  =                    1 / one data group (required keyword)              TFIELDS =                    5 / number of fields in each row                   TTYPE1  = 'Name    '           / label for field   1                            TBCOL1  =                    1 / beginning column of field   1                  TFORM1  = 'A15     '           / Fortran-77 format of field                     TTYPE2  = 'Ivalue  '           / label for field   2                            TBCOL2  =                   17 / beginning column of field   2                  TFORM2  = 'I11     '           / Fortran-77 format of field                     TUNIT2  = 'm**2    '           / physical unit of field                         TTYPE3  = 'Fvalue  '           / label for field   3                            TBCOL3  =                   29 / beginning column of field   3                  TFORM3  = 'F15.6   '           / Fortran-77 format of field                     TUNIT3  = 'cm      '           / physical unit of field                         TTYPE4  = 'Evalue  '           / label for field   4                            TBCOL4  =                   45 / beginning column of field   4                  TFORM4  = 'E13.5   '           / Fortran-77 format of field                     TUNIT4  = 'erg/s   '           / physical unit of field                         TTYPE5  = 'Dvalue  '           / label for field   5                            TBCOL5  =                   59 / beginning column of field   5                  TFORM5  = 'D22.14  '           / Fortran-77 format of field                     TUNIT5  = 'km/s    '           / physical unit of field                         EXTNAME = 'new_table'          / name of this ASCII table extension             EXTVER  =                    5 / extension version number                       END                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             first string              0        0.000000   0.00000E+00   0.00000000000000E+00second string             3        3.000000   3.00000E+00   3.00000000000000E+00                          6        6.000000   6.00000E+00   6.00000000000000E+00                          9        9.000000   9.00000E+00   9.00000000000000E+00                         12       12.000000   1.20000E+01   1.20000000000000E+01                         15       15.000000   1.50000E+01   1.50000000000000E+01                         18       18.000000   1.80000E+01   1.80000000000000E+01                         21       21.000000   2.10000E+01   2.10000000000000E+01                         24       24.000000   2.40000E+01   2.40000000000000E+01                         27       27.000000   2.70000E+01   2.70000000000000E+01                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                cfitsio/testprog.tpt0000644000225700000360000000061413246025103014401 0ustar  cagordonlheatmpcard1  1001 this is the 1st template card 
tmpcard2  ABCD this is the 2nd template card
tmpcard3  1001.23 this is the 3rd template card
tmpcard4  1001.45 this is the 4rd template card
comment this is the 5th template card
history this is the 6th template card
tmpcard7 =            / comment for null keyword
-tmpcard1 tmpcarda  change the name of tmpcard1
-tmpcard4
end

junk will be ignored
cfitsio/vmsieee.c0000644000225700000360000000730613246025103013607 0ustar  cagordonlhea#include 
#include 

unsigned long CVT$CONVERT_FLOAT();

/* IEEVPAKR -- Pack a native floating point vector into an IEEE one.
*/
void ieevpr (unsigned int *native, unsigned int *ieee, int *nelem)
{
        unsigned long status;
        unsigned long options;
        unsigned int *unanval;
        int nanval = -1;
        int     i,n;

        unanval = (unsigned int *) &nanval;
        options = CVT$M_BIG_ENDIAN;
        
        n = *nelem;
        status = CVT$_NORMAL;

        for (i = 0; i < n ; i++) {

            status = CVT$CONVERT_FLOAT (&native[i], CVT$K_VAX_F,
                                        &ieee[i], CVT$K_IEEE_S, 
                                        options);
           if (status != CVT$_NORMAL) {
                 ieee[i] = *unanval;
           }
        }       

}
/* IEEVPAKD -- Pack a native double floating point vector into an IEEE one.
*/
void ieevpd (unsigned long *native, unsigned long *ieee, int *nelem)
{
        unsigned long status;
        unsigned long options;
        unsigned long *unanval;
        long nanval = -1;
        int     i,n;

        unanval = (unsigned long *) &nanval;
        options = CVT$M_BIG_ENDIAN;
        
        n = *nelem * 2;
        status = CVT$_NORMAL;

        for (i = 0; i < n ; i=i+2) {

            status = CVT$CONVERT_FLOAT (&native[i], CVT$K_VAX_D,
                                        &ieee[i], CVT$K_IEEE_T, 
                                        options);
           if (status != CVT$_NORMAL) {
                 ieee[i]   = *unanval;
                 ieee[i+1] = *unanval;
           }
        }       

}
/* IEEVUPKR -- Unpack an ieee vector into native single floating point vector.
*/
void ieevur (unsigned int *ieee, unsigned int *native, int *nelem)
{
        unsigned long status;
        unsigned long options;
        unsigned int *unanval;
        int nanval = -1;
        int     j,n;

        unanval = (unsigned int *) &nanval;
        options = CVT$M_ERR_UNDERFLOW+CVT$M_BIG_ENDIAN;
        
        n = *nelem;

        status = CVT$_NORMAL;

        for (j = 0; j < n ; j++) {
           status = CVT$CONVERT_FLOAT (&ieee[j], CVT$K_IEEE_S,
                                        &native[j], CVT$K_VAX_F, 
                                        options);
           if (status != CVT$_NORMAL)
              switch(status) {
              case CVT$_INVVAL:
              case CVT$_NEGINF:
              case CVT$_OVERFLOW:
              case CVT$_POSINF:
                 native[j]   = *unanval;
                 break;
              default:
                 native[j] = 0;             
              }
        }
}
/* IEEVUPKD -- Unpack an ieee vector into native double floating point vector.
*/
void ieevud (unsigned long *ieee, unsigned long *native, int *nelem)
{
        unsigned long status;
        unsigned long options;
        unsigned long *unanval;
        long nanval = -1;
        int     j,n;

        unanval = (unsigned long *) &nanval;
        options = CVT$M_BIG_ENDIAN + CVT$M_ERR_UNDERFLOW; 
        
        n = *nelem * 2;

        status = CVT$_NORMAL;

        for (j = 0; j < n ; j=j+2) {
           status = CVT$CONVERT_FLOAT (&ieee[j], CVT$K_IEEE_T,
                                        &native[j], CVT$K_VAX_D, 
                                        options);
           if (status != CVT$_NORMAL)
              switch(status) {
              case CVT$_INVVAL:
              case CVT$_NEGINF:
              case CVT$_OVERFLOW:
              case CVT$_POSINF:
                 native[j]   = *unanval;
                 native[j+1] = *unanval;
                 break;
              default:
                 native[j]   = 0;             
                 native[j+1] = 0;             
              }
        }
}
cfitsio/wcssub.c0000644000225700000360000010470313246025103013457 0ustar  cagordonlhea#include 
#include 
#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int fits_read_wcstab(
   fitsfile   *fptr, /* I - FITS file pointer           */
   int  nwtb,        /* Number of arrays to be read from the binary table(s) */
   wtbarr *wtb,      /* Address of the first element of an array of wtbarr
                         typedefs.  This wtbarr typedef is defined below to
                         match the wtbarr struct defined in WCSLIB.  An array
                         of such structs returned by the WCSLIB function
                         wcstab(). */
   int  *status)

/*
*   Author: Mark Calabretta, Australia Telescope National Facility
*   http://www.atnf.csiro.au/~mcalabre/index.html
*
*   fits_read_wcstab() extracts arrays from a binary table required in
*   constructing -TAB coordinates.  This helper routine is intended for
*   use by routines in the WCSLIB library when dealing with the -TAB table
*   look up WCS convention.
*/

{
   int  anynul, colnum, hdunum, iwtb, m, naxis, nostat;
   long *naxes = 0, nelem;
   wtbarr *wtbp;


   if (*status) return *status;

   if (fptr == 0) {
      return (*status = NULL_INPUT_PTR);
   }

   if (nwtb == 0) return 0;

   /* Zero the array pointers. */
   wtbp = wtb;
   for (iwtb = 0; iwtb < nwtb; iwtb++, wtbp++) {
     *wtbp->arrayp = 0x0;
   }

   /* Save HDU number so that we can move back to it later. */
   fits_get_hdu_num(fptr, &hdunum);

   wtbp = wtb;
   for (iwtb = 0; iwtb < nwtb; iwtb++, wtbp++) {
      /* Move to the required binary table extension. */
      if (fits_movnam_hdu(fptr, BINARY_TBL, (char *)(wtbp->extnam),
          wtbp->extver, status)) {
         goto cleanup;
      }

      /* Locate the table column. */
      if (fits_get_colnum(fptr, CASEINSEN, (char *)(wtbp->ttype), &colnum,
          status)) {
         goto cleanup;
      }

      /* Get the array dimensions and check for consistency. */
      if (wtbp->ndim < 1) {
         *status = NEG_AXIS;
         goto cleanup;
      }

      if (!(naxes = calloc(wtbp->ndim, sizeof(long)))) {
         *status = MEMORY_ALLOCATION;
         goto cleanup;
      }

      if (fits_read_tdim(fptr, colnum, wtbp->ndim, &naxis, naxes, status)) {
         goto cleanup;
      }

      if (naxis != wtbp->ndim) {
         if (wtbp->kind == 'c' && wtbp->ndim == 2) {
            /* Allow TDIMn to be omitted for degenerate coordinate arrays. */
            naxis = 2;
            naxes[1] = naxes[0];
            naxes[0] = 1;
         } else {
            *status = BAD_TDIM;
            goto cleanup;
         }
      }

      if (wtbp->kind == 'c') {
         /* Coordinate array; calculate the array size. */
         nelem = naxes[0];
         for (m = 0; m < naxis-1; m++) {
            *(wtbp->dimlen + m) = naxes[m+1];
            nelem *= naxes[m+1];
         }
      } else {
         /* Index vector; check length. */
         if ((nelem = naxes[0]) != *(wtbp->dimlen)) {
            /* N.B. coordinate array precedes the index vectors. */
            *status = BAD_TDIM;
            goto cleanup;
         }
      }

      free(naxes);
      naxes = 0;

      /* Allocate memory for the array. */
      if (!(*wtbp->arrayp = calloc((size_t)nelem, sizeof(double)))) {
         *status = MEMORY_ALLOCATION;
         goto cleanup;
      }

      /* Read the array from the table. */
      if (fits_read_col_dbl(fptr, colnum, wtbp->row, 1L, nelem, 0.0,
          *wtbp->arrayp, &anynul, status)) {
         goto cleanup;
      }
   }

cleanup:
   /* Move back to the starting HDU. */
   nostat = 0;
   fits_movabs_hdu(fptr, hdunum, 0, &nostat);

   /* Release allocated memory. */
   if (naxes) free(naxes);
   if (*status) {
      wtbp = wtb;
      for (iwtb = 0; iwtb < nwtb; iwtb++, wtbp++) {
         if (*wtbp->arrayp) free(*wtbp->arrayp);
      }
   }

   return *status;
}
/*--------------------------------------------------------------------------*/
int ffgiwcs(fitsfile *fptr,  /* I - FITS file pointer                    */
           char **header,   /* O - pointer to the WCS related keywords  */
           int *status)     /* IO - error status                        */
/*
  int fits_get_image_wcs_keys 
  return a string containing all the image WCS header keywords.
  This string is then used as input to the wcsinit WCSlib routine.
  
  THIS ROUTINE IS DEPRECATED. USE fits_hdr2str INSTEAD
*/
{
    int hdutype;

    if (*status > 0)
        return(*status);

    fits_get_hdu_type(fptr, &hdutype, status);
    if (hdutype != IMAGE_HDU)
    {
      ffpmsg(
     "Error in ffgiwcs. This HDU is not an image. Can't read WCS keywords");
      return(*status = NOT_IMAGE);
    }

    /* read header keywords into a long string of chars */
    if (ffh2st(fptr, header, status) > 0)
    {
        ffpmsg("error creating string of image WCS keywords (ffgiwcs)");
        return(*status);
    }

    return(*status);
}

/*--------------------------------------------------------------------------*/
int ffgics(fitsfile *fptr,    /* I - FITS file pointer           */
           double *xrval,     /* O - X reference value           */
           double *yrval,     /* O - Y reference value           */
           double *xrpix,     /* O - X reference pixel           */
           double *yrpix,     /* O - Y reference pixel           */
           double *xinc,      /* O - X increment per pixel       */
           double *yinc,      /* O - Y increment per pixel       */
           double *rot,       /* O - rotation angle (degrees)    */
           char *type,        /* O - type of projection ('-tan') */
           int *status)       /* IO - error status               */
/*
       read the values of the celestial coordinate system keywords.
       These values may be used as input to the subroutines that
       calculate celestial coordinates. (ffxypx, ffwldp)

       Modified in Nov 1999 to convert the CD matrix keywords back
       to the old CDELTn form, and to swap the axes if the dec-like
       axis is given first, and to assume default values if any of the
       keywords are not present.
*/
{
    int tstat = 0, cd_exists = 0, pc_exists = 0;
    char ctype[FLEN_VALUE];
    double cd11 = 0.0, cd21 = 0.0, cd22 = 0.0, cd12 = 0.0;
    double pc11 = 1.0, pc21 = 0.0, pc22 = 1.0, pc12 = 0.0;
    double pi =  3.1415926535897932;
    double phia, phib, temp;
    double toler = .0002;  /* tolerance for angles to agree (radians) */
                           /*   (= approximately 0.01 degrees) */

    if (*status > 0)
       return(*status);

    tstat = 0;
    if (ffgkyd(fptr, "CRVAL1", xrval, NULL, &tstat))
       *xrval = 0.;

    tstat = 0;
    if (ffgkyd(fptr, "CRVAL2", yrval, NULL, &tstat))
       *yrval = 0.;

    tstat = 0;
    if (ffgkyd(fptr, "CRPIX1", xrpix, NULL, &tstat))
        *xrpix = 0.;

    tstat = 0;
    if (ffgkyd(fptr, "CRPIX2", yrpix, NULL, &tstat))
        *yrpix = 0.;

    /* look for CDELTn first, then CDi_j keywords */
    tstat = 0;
    if (ffgkyd(fptr, "CDELT1", xinc, NULL, &tstat))
    {
        /* CASE 1: no CDELTn keyword, so look for the CD matrix */
        tstat = 0;
        if (ffgkyd(fptr, "CD1_1", &cd11, NULL, &tstat))
            tstat = 0;  /* reset keyword not found error */
        else
            cd_exists = 1;  /* found at least 1 CD_ keyword */

        if (ffgkyd(fptr, "CD2_1", &cd21, NULL, &tstat))
            tstat = 0;  /* reset keyword not found error */
        else
            cd_exists = 1;  /* found at least 1 CD_ keyword */

        if (ffgkyd(fptr, "CD1_2", &cd12, NULL, &tstat))
            tstat = 0;  /* reset keyword not found error */
        else
            cd_exists = 1;  /* found at least 1 CD_ keyword */

        if (ffgkyd(fptr, "CD2_2", &cd22, NULL, &tstat))
            tstat = 0;  /* reset keyword not found error */
        else
            cd_exists = 1;  /* found at least 1 CD_ keyword */

        if (cd_exists)  /* convert CDi_j back to CDELTn */
        {
            /* there are 2 ways to compute the angle: */
            phia = atan2( cd21, cd11);
            phib = atan2(-cd12, cd22);

            /* ensure that phia <= phib */
            temp = minvalue(phia, phib);
            phib = maxvalue(phia, phib);
            phia = temp;

            /* there is a possible 180 degree ambiguity in the angles */
            /* so add 180 degress to the smaller value if the values  */
            /* differ by more than 90 degrees = pi/2 radians.         */
            /* (Later, we may decide to take the other solution by    */
            /* subtracting 180 degrees from the larger value).        */

            if ((phib - phia) > (pi / 2.))
               phia += pi;

            if (fabs(phia - phib) > toler) 
            {
               /* angles don't agree, so looks like there is some skewness */
               /* between the axes.  Return with an error to be safe. */
               *status = APPROX_WCS_KEY;
            }
      
            phia = (phia + phib) /2.;  /* use the average of the 2 values */
            *xinc = cd11 / cos(phia);
            *yinc = cd22 / cos(phia);
            *rot = phia * 180. / pi;

            /* common usage is to have a positive yinc value.  If it is */
            /* negative, then subtract 180 degrees from rot and negate  */
            /* both xinc and yinc.  */

            if (*yinc < 0)
            {
                *xinc = -(*xinc);
                *yinc = -(*yinc);
                *rot = *rot - 180.;
            }
        }
        else   /* no CD matrix keywords either */
        {
            *xinc = 1.;

            /* there was no CDELT1 keyword, but check for CDELT2 just in case */
            tstat = 0;
            if (ffgkyd(fptr, "CDELT2", yinc, NULL, &tstat))
                *yinc = 1.;

            tstat = 0;
            if (ffgkyd(fptr, "CROTA2", rot, NULL, &tstat))
                *rot=0.;
        }
    }
    else  /* Case 2: CDELTn + optional PC matrix */
    {
        if (ffgkyd(fptr, "CDELT2", yinc, NULL, &tstat))
            *yinc = 1.;

        tstat = 0;
        if (ffgkyd(fptr, "CROTA2", rot, NULL, &tstat))
        {
            *rot=0.;

            /* no CROTA2 keyword, so look for the PC matrix */
            tstat = 0;
            if (ffgkyd(fptr, "PC1_1", &pc11, NULL, &tstat))
                tstat = 0;  /* reset keyword not found error */
            else
                pc_exists = 1;  /* found at least 1 PC_ keyword */

            if (ffgkyd(fptr, "PC2_1", &pc21, NULL, &tstat))
                tstat = 0;  /* reset keyword not found error */
            else
                pc_exists = 1;  /* found at least 1 PC_ keyword */

            if (ffgkyd(fptr, "PC1_2", &pc12, NULL, &tstat))
                tstat = 0;  /* reset keyword not found error */
            else
                pc_exists = 1;  /* found at least 1 PC_ keyword */

            if (ffgkyd(fptr, "PC2_2", &pc22, NULL, &tstat))
                tstat = 0;  /* reset keyword not found error */
            else
                pc_exists = 1;  /* found at least 1 PC_ keyword */

            if (pc_exists)  /* convert PCi_j back to CDELTn */
            {
                /* there are 2 ways to compute the angle: */
                phia = atan2( pc21, pc11);
                phib = atan2(-pc12, pc22);

                /* ensure that phia <= phib */
                temp = minvalue(phia, phib);
                phib = maxvalue(phia, phib);
                phia = temp;

                /* there is a possible 180 degree ambiguity in the angles */
                /* so add 180 degress to the smaller value if the values  */
                /* differ by more than 90 degrees = pi/2 radians.         */
                /* (Later, we may decide to take the other solution by    */
                /* subtracting 180 degrees from the larger value).        */

                if ((phib - phia) > (pi / 2.))
                   phia += pi;

                if (fabs(phia - phib) > toler) 
                {
                  /* angles don't agree, so looks like there is some skewness */
                  /* between the axes.  Return with an error to be safe. */
                  *status = APPROX_WCS_KEY;
                }
      
                phia = (phia + phib) /2.;  /* use the average of the 2 values */
                *rot = phia * 180. / pi;
            }
        }
    }

    /* get the type of projection, if any */
    tstat = 0;
    if (ffgkys(fptr, "CTYPE1", ctype, NULL, &tstat))
         type[0] = '\0';
    else
    {
        /* copy the projection type string */
        strncpy(type, &ctype[4], 4);
        type[4] = '\0';

        /* check if RA and DEC are inverted */
        if (!strncmp(ctype, "DEC-", 4) || !strncmp(ctype+1, "LAT", 3))
        {
            /* the latitudinal axis is given first, so swap them */

/*
 this case was removed on 12/9.  Apparently not correct.

            if ((*xinc / *yinc) < 0. )  
                *rot = -90. - (*rot);
            else
*/
            *rot = 90. - (*rot);

            /* Empirical tests with ds9 show the y-axis sign must be negated */
            /* and the xinc and yinc values must NOT be swapped. */
            *yinc = -(*yinc);

            temp = *xrval;
            *xrval = *yrval;
            *yrval = temp;
        }   
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgicsa(fitsfile *fptr,    /* I - FITS file pointer           */
           char version,      /* I - character code of desired version */
	                      /*     A - Z or blank */
           double *xrval,     /* O - X reference value           */
           double *yrval,     /* O - Y reference value           */
           double *xrpix,     /* O - X reference pixel           */
           double *yrpix,     /* O - Y reference pixel           */
           double *xinc,      /* O - X increment per pixel       */
           double *yinc,      /* O - Y increment per pixel       */
           double *rot,       /* O - rotation angle (degrees)    */
           char *type,        /* O - type of projection ('-tan') */
           int *status)       /* IO - error status               */
/*
       read the values of the celestial coordinate system keywords.
       These values may be used as input to the subroutines that
       calculate celestial coordinates. (ffxypx, ffwldp)

       Modified in Nov 1999 to convert the CD matrix keywords back
       to the old CDELTn form, and to swap the axes if the dec-like
       axis is given first, and to assume default values if any of the
       keywords are not present.
*/
{
    int tstat = 0, cd_exists = 0, pc_exists = 0;
    char ctype[FLEN_VALUE], keyname[FLEN_VALUE], alt[2];
    double cd11 = 0.0, cd21 = 0.0, cd22 = 0.0, cd12 = 0.0;
    double pc11 = 1.0, pc21 = 0.0, pc22 = 1.0, pc12 = 0.0;
    double pi =  3.1415926535897932;
    double phia, phib, temp;
    double toler = .0002;  /* tolerance for angles to agree (radians) */
                           /*   (= approximately 0.01 degrees) */

    if (*status > 0)
       return(*status);

    if (version == ' ') {
      ffgics(fptr, xrval, yrval, xrpix, yrpix, xinc, yinc, rot, type, status);
      return (*status);
    }

    if (version > 'Z' || version < 'A') {
      ffpmsg("ffgicsa: illegal WCS version code (must be A - Z or blank)");
      return(*status = WCS_ERROR);
    }

    alt[0] = version;
    alt[1] = '\0';
    
    tstat = 0;
    strcpy(keyname, "CRVAL1");
    strcat(keyname, alt);
    if (ffgkyd(fptr, keyname, xrval, NULL, &tstat))
       *xrval = 0.;

    tstat = 0;
    strcpy(keyname, "CRVAL2");
    strcat(keyname, alt);
    if (ffgkyd(fptr, keyname, yrval, NULL, &tstat))
       *yrval = 0.;

    tstat = 0;
    strcpy(keyname, "CRPIX1");
    strcat(keyname, alt);
    if (ffgkyd(fptr, keyname, xrpix, NULL, &tstat))
        *xrpix = 0.;

    tstat = 0;
    strcpy(keyname, "CRPIX2");
    strcat(keyname, alt);
     if (ffgkyd(fptr, keyname, yrpix, NULL, &tstat))
        *yrpix = 0.;

    /* look for CDELTn first, then CDi_j keywords */
    tstat = 0;
    strcpy(keyname, "CDELT1");
    strcat(keyname, alt);
    if (ffgkyd(fptr, keyname, xinc, NULL, &tstat))
    {
        /* CASE 1: no CDELTn keyword, so look for the CD matrix */
        tstat = 0;
        strcpy(keyname, "CD1_1");
        strcat(keyname, alt);
        if (ffgkyd(fptr, keyname, &cd11, NULL, &tstat))
            tstat = 0;  /* reset keyword not found error */
        else
            cd_exists = 1;  /* found at least 1 CD_ keyword */

        strcpy(keyname, "CD2_1");
        strcat(keyname, alt);
        if (ffgkyd(fptr, keyname, &cd21, NULL, &tstat))
            tstat = 0;  /* reset keyword not found error */
        else
            cd_exists = 1;  /* found at least 1 CD_ keyword */

        strcpy(keyname, "CD1_2");
        strcat(keyname, alt);
        if (ffgkyd(fptr, keyname, &cd12, NULL, &tstat))
            tstat = 0;  /* reset keyword not found error */
        else
            cd_exists = 1;  /* found at least 1 CD_ keyword */

        strcpy(keyname, "CD2_2");
        strcat(keyname, alt);
        if (ffgkyd(fptr, keyname, &cd22, NULL, &tstat))
            tstat = 0;  /* reset keyword not found error */
        else
            cd_exists = 1;  /* found at least 1 CD_ keyword */

        if (cd_exists)  /* convert CDi_j back to CDELTn */
        {
            /* there are 2 ways to compute the angle: */
            phia = atan2( cd21, cd11);
            phib = atan2(-cd12, cd22);

            /* ensure that phia <= phib */
            temp = minvalue(phia, phib);
            phib = maxvalue(phia, phib);
            phia = temp;

            /* there is a possible 180 degree ambiguity in the angles */
            /* so add 180 degress to the smaller value if the values  */
            /* differ by more than 90 degrees = pi/2 radians.         */
            /* (Later, we may decide to take the other solution by    */
            /* subtracting 180 degrees from the larger value).        */

            if ((phib - phia) > (pi / 2.))
               phia += pi;

            if (fabs(phia - phib) > toler) 
            {
               /* angles don't agree, so looks like there is some skewness */
               /* between the axes.  Return with an error to be safe. */
               *status = APPROX_WCS_KEY;
            }
      
            phia = (phia + phib) /2.;  /* use the average of the 2 values */
            *xinc = cd11 / cos(phia);
            *yinc = cd22 / cos(phia);
            *rot = phia * 180. / pi;

            /* common usage is to have a positive yinc value.  If it is */
            /* negative, then subtract 180 degrees from rot and negate  */
            /* both xinc and yinc.  */

            if (*yinc < 0)
            {
                *xinc = -(*xinc);
                *yinc = -(*yinc);
                *rot = *rot - 180.;
            }
        }
        else   /* no CD matrix keywords either */
        {
            *xinc = 1.;

            /* there was no CDELT1 keyword, but check for CDELT2 just in case */
            tstat = 0;
            strcpy(keyname, "CDELT2");
            strcat(keyname, alt);
            if (ffgkyd(fptr, keyname, yinc, NULL, &tstat))
                *yinc = 1.;

            tstat = 0;
            strcpy(keyname, "CROTA2");
            strcat(keyname, alt);
            if (ffgkyd(fptr, keyname, rot, NULL, &tstat))
                *rot=0.;
        }
    }
    else  /* Case 2: CDELTn + optional PC matrix */
    {
        strcpy(keyname, "CDELT2");
        strcat(keyname, alt);
        if (ffgkyd(fptr, keyname, yinc, NULL, &tstat))
            *yinc = 1.;

        tstat = 0;
        strcpy(keyname, "CROTA2");
        strcat(keyname, alt);
        if (ffgkyd(fptr, keyname, rot, NULL, &tstat))
        {
            *rot=0.;

            /* no CROTA2 keyword, so look for the PC matrix */
            tstat = 0;
            strcpy(keyname, "PC1_1");
            strcat(keyname, alt);
            if (ffgkyd(fptr, keyname, &pc11, NULL, &tstat))
                tstat = 0;  /* reset keyword not found error */
            else
                pc_exists = 1;  /* found at least 1 PC_ keyword */

            strcpy(keyname, "PC2_1");
            strcat(keyname, alt);
            if (ffgkyd(fptr, keyname, &pc21, NULL, &tstat))
                tstat = 0;  /* reset keyword not found error */
            else
                pc_exists = 1;  /* found at least 1 PC_ keyword */

            strcpy(keyname, "PC1_2");
            strcat(keyname, alt);
            if (ffgkyd(fptr, keyname, &pc12, NULL, &tstat))
                tstat = 0;  /* reset keyword not found error */
            else
                pc_exists = 1;  /* found at least 1 PC_ keyword */

            strcpy(keyname, "PC2_2");
            strcat(keyname, alt);
            if (ffgkyd(fptr, keyname, &pc22, NULL, &tstat))
                tstat = 0;  /* reset keyword not found error */
            else
                pc_exists = 1;  /* found at least 1 PC_ keyword */

            if (pc_exists)  /* convert PCi_j back to CDELTn */
            {
                /* there are 2 ways to compute the angle: */
                phia = atan2( pc21, pc11);
                phib = atan2(-pc12, pc22);

                /* ensure that phia <= phib */
                temp = minvalue(phia, phib);
                phib = maxvalue(phia, phib);
                phia = temp;

                /* there is a possible 180 degree ambiguity in the angles */
                /* so add 180 degress to the smaller value if the values  */
                /* differ by more than 90 degrees = pi/2 radians.         */
                /* (Later, we may decide to take the other solution by    */
                /* subtracting 180 degrees from the larger value).        */

                if ((phib - phia) > (pi / 2.))
                   phia += pi;

                if (fabs(phia - phib) > toler) 
                {
                  /* angles don't agree, so looks like there is some skewness */
                  /* between the axes.  Return with an error to be safe. */
                  *status = APPROX_WCS_KEY;
                }
      
                phia = (phia + phib) /2.;  /* use the average of the 2 values */
                *rot = phia * 180. / pi;
            }
        }
    }

    /* get the type of projection, if any */
    tstat = 0;
    strcpy(keyname, "CTYPE1");
    strcat(keyname, alt);
    if (ffgkys(fptr, keyname, ctype, NULL, &tstat))
         type[0] = '\0';
    else
    {
        /* copy the projection type string */
        strncpy(type, &ctype[4], 4);
        type[4] = '\0';

        /* check if RA and DEC are inverted */
        if (!strncmp(ctype, "DEC-", 4) || !strncmp(ctype+1, "LAT", 3))
        {
            /* the latitudinal axis is given first, so swap them */

            *rot = 90. - (*rot);

            /* Empirical tests with ds9 show the y-axis sign must be negated */
            /* and the xinc and yinc values must NOT be swapped. */
            *yinc = -(*yinc);

            temp = *xrval;
            *xrval = *yrval;
            *yrval = temp;
        }   
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgtcs(fitsfile *fptr,    /* I - FITS file pointer           */
           int xcol,          /* I - column containing the RA coordinate  */
           int ycol,          /* I - column containing the DEC coordinate */
           double *xrval,     /* O - X reference value           */
           double *yrval,     /* O - Y reference value           */
           double *xrpix,     /* O - X reference pixel           */
           double *yrpix,     /* O - Y reference pixel           */
           double *xinc,      /* O - X increment per pixel       */
           double *yinc,      /* O - Y increment per pixel       */
           double *rot,       /* O - rotation angle (degrees)    */
           char *type,        /* O - type of projection ('-sin') */
           int *status)       /* IO - error status               */
/*
       read the values of the celestial coordinate system keywords
       from a FITS table where the X and Y or RA and DEC coordinates
       are stored in separate column.  Do this by converting the
       table to a temporary FITS image, then reading the keywords
       from the image file.
       These values may be used as input to the subroutines that
       calculate celestial coordinates. (ffxypx, ffwldp)
*/
{
    int colnum[2];
    long naxes[2];
    fitsfile *tptr;

    if (*status > 0)
       return(*status);

    colnum[0] = xcol;
    colnum[1] = ycol;
    naxes[0] = 10;
    naxes[1] = 10;

    /* create temporary  FITS file, in memory */
    ffinit(&tptr, "mem://", status);
    
    /* create a temporary image; the datatype and size are not important */
    ffcrim(tptr, 32, 2, naxes, status);
    
    /* now copy the relevant keywords from the table to the image */
    fits_copy_pixlist2image(fptr, tptr, 9, 2, colnum, status);

    /* write default WCS keywords, if they are not present */
    fits_write_keys_histo(fptr, tptr, 2, colnum, status);

    if (*status > 0)
       return(*status);
         
    /* read the WCS keyword values from the temporary image */
    ffgics(tptr, xrval, yrval, xrpix, yrpix, xinc, yinc, rot, type, status); 

    if (*status > 0)
    {
      ffpmsg
      ("ffgtcs could not find all the celestial coordinate keywords");
      return(*status = NO_WCS_KEY); 
    }

    /* delete the temporary file */
    fits_delete_file(tptr, status);
    
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgtwcs(fitsfile *fptr,  /* I - FITS file pointer              */
           int xcol,        /* I - column number for the X column  */
           int ycol,        /* I - column number for the Y column  */
           char **header,   /* O - string of all the WCS keywords  */
           int *status)     /* IO - error status                   */
/*
  int fits_get_table_wcs_keys
  Return string containing all the WCS keywords appropriate for the 
  pair of X and Y columns containing the coordinate
  of each event in an event list table.  This string may then be passed
  to Doug Mink's WCS library wcsinit routine, to create and initialize the
  WCS structure.  The calling routine must free the header character string
  when it is no longer needed. 

  THIS ROUTINE IS DEPRECATED. USE fits_hdr2str INSTEAD
*/
{
    int hdutype, ncols, tstatus, length;
    int naxis1 = 1, naxis2 = 1;
    long tlmin, tlmax;
    char keyname[FLEN_KEYWORD];
    char valstring[FLEN_VALUE];
    char comm[2];
    char *cptr;
    /*  construct a string of 80 blanks, for adding fill to the keywords */
                 /*  12345678901234567890123456789012345678901234567890123456789012345678901234567890 */
    char blanks[] = "                                                                                ";

    if (*status > 0)
        return(*status);

    fits_get_hdu_type(fptr, &hdutype, status);
    if (hdutype == IMAGE_HDU)
    {
        ffpmsg("Can't read table WSC keywords. This HDU is not a table");
        return(*status = NOT_TABLE);
    }

    fits_get_num_cols(fptr, &ncols, status);
    
    if (xcol < 1 || xcol > ncols)
    {
        ffpmsg("illegal X axis column number in fftwcs");
        return(*status = BAD_COL_NUM);
    }

    if (ycol < 1 || ycol > ncols)
    {
        ffpmsg("illegal Y axis column number in fftwcs");
        return(*status = BAD_COL_NUM);
    }

    /* allocate character string for all the WCS keywords */
    *header = calloc(1, 2401);  /* room for up to 30 keywords */
    if (*header == 0)
    {
        ffpmsg("error allocating memory for WCS header keywords (fftwcs)");
        return(*status = MEMORY_ALLOCATION);
    }

    cptr = *header;
    comm[0] = '\0';
    
    tstatus = 0;
    ffkeyn("TLMIN",xcol,keyname,status);
    ffgkyj(fptr,keyname, &tlmin,NULL,&tstatus);

    if (!tstatus)
    {
        ffkeyn("TLMAX",xcol,keyname,status);
        ffgkyj(fptr,keyname, &tlmax,NULL,&tstatus);
    }

    if (!tstatus)
    {
        naxis1 = tlmax - tlmin + 1;
    }

    tstatus = 0;
    ffkeyn("TLMIN",ycol,keyname,status);
    ffgkyj(fptr,keyname, &tlmin,NULL,&tstatus);

    if (!tstatus)
    {
        ffkeyn("TLMAX",ycol,keyname,status);
        ffgkyj(fptr,keyname, &tlmax,NULL,&tstatus);
    }

    if (!tstatus)
    {
        naxis2 = tlmax - tlmin + 1;
    }

    /*            123456789012345678901234567890    */
    strcat(cptr, "NAXIS   =                    2");
    strncat(cptr, blanks, 50);
    cptr += 80;

    ffi2c(naxis1, valstring, status);   /* convert to formatted string */
    ffmkky("NAXIS1", valstring, comm, cptr, status);  /* construct the keyword*/
    strncat(cptr, blanks, 50);  /* pad with blanks */
    cptr += 80;

    strcpy(keyname, "NAXIS2");
    ffi2c(naxis2, valstring, status);   /* convert to formatted string */
    ffmkky(keyname, valstring, comm, cptr, status);  /* construct the keyword*/
    strncat(cptr, blanks, 50);  /* pad with blanks */
    cptr += 80;

    /* read the required header keywords (use defaults if not found) */

    /*  CTYPE1 keyword */
    tstatus = 0;
    ffkeyn("TCTYP",xcol,keyname,status);
    if (ffgkey(fptr, keyname, valstring, NULL, &tstatus) )
       valstring[0] =  '\0';
    ffmkky("CTYPE1", valstring, comm, cptr, status);  /* construct the keyword*/
    length = strlen(cptr);
    strncat(cptr, blanks, 80 - length);  /* pad with blanks */
    cptr += 80;

    /*  CTYPE2 keyword */
    tstatus = 0;
    ffkeyn("TCTYP",ycol,keyname,status);
    if (ffgkey(fptr, keyname, valstring, NULL, &tstatus) )
       valstring[0] =  '\0';
    ffmkky("CTYPE2", valstring, comm, cptr, status);  /* construct the keyword*/
    length = strlen(cptr);
    strncat(cptr, blanks, 80 - length);  /* pad with blanks */
    cptr += 80;

    /*  CRPIX1 keyword */
    tstatus = 0;
    ffkeyn("TCRPX",xcol,keyname,status);
    if (ffgkey(fptr, keyname, valstring, NULL, &tstatus) )
       strcpy(valstring, "1");
    ffmkky("CRPIX1", valstring, comm, cptr, status);  /* construct the keyword*/
    strncat(cptr, blanks, 50);  /* pad with blanks */
    cptr += 80;

    /*  CRPIX2 keyword */
    tstatus = 0;
    ffkeyn("TCRPX",ycol,keyname,status);
    if (ffgkey(fptr, keyname, valstring, NULL, &tstatus) )
       strcpy(valstring, "1");
    ffmkky("CRPIX2", valstring, comm, cptr, status);  /* construct the keyword*/
    strncat(cptr, blanks, 50);  /* pad with blanks */
    cptr += 80;

    /*  CRVAL1 keyword */
    tstatus = 0;
    ffkeyn("TCRVL",xcol,keyname,status);
    if (ffgkey(fptr, keyname, valstring, NULL, &tstatus) )
       strcpy(valstring, "1");
    ffmkky("CRVAL1", valstring, comm, cptr, status);  /* construct the keyword*/
    strncat(cptr, blanks, 50);  /* pad with blanks */
    cptr += 80;

    /*  CRVAL2 keyword */
    tstatus = 0;
    ffkeyn("TCRVL",ycol,keyname,status);
    if (ffgkey(fptr, keyname, valstring, NULL, &tstatus) )
       strcpy(valstring, "1");
    ffmkky("CRVAL2", valstring, comm, cptr, status);  /* construct the keyword*/
    strncat(cptr, blanks, 50);  /* pad with blanks */
    cptr += 80;

    /*  CDELT1 keyword */
    tstatus = 0;
    ffkeyn("TCDLT",xcol,keyname,status);
    if (ffgkey(fptr, keyname, valstring, NULL, &tstatus) )
       strcpy(valstring, "1");
    ffmkky("CDELT1", valstring, comm, cptr, status);  /* construct the keyword*/
    strncat(cptr, blanks, 50);  /* pad with blanks */
    cptr += 80;

    /*  CDELT2 keyword */
    tstatus = 0;
    ffkeyn("TCDLT",ycol,keyname,status);
    if (ffgkey(fptr, keyname, valstring, NULL, &tstatus) )
       strcpy(valstring, "1");
    ffmkky("CDELT2", valstring, comm, cptr, status);  /* construct the keyword*/
    strncat(cptr, blanks, 50);  /* pad with blanks */
    cptr += 80;

    /* the following keywords may not exist */

    /*  CROTA2 keyword */
    tstatus = 0;
    ffkeyn("TCROT",ycol,keyname,status);
    if (ffgkey(fptr, keyname, valstring, NULL, &tstatus) == 0 )
    {
        ffmkky("CROTA2", valstring, comm, cptr, status);  /* construct keyword*/
        strncat(cptr, blanks, 50);  /* pad with blanks */
        cptr += 80;
    }

    /*  EPOCH keyword */
    tstatus = 0;
    if (ffgkey(fptr, "EPOCH", valstring, NULL, &tstatus) == 0 )
    {
        ffmkky("EPOCH", valstring, comm, cptr, status);  /* construct keyword*/
        length = strlen(cptr);
        strncat(cptr, blanks, 80 - length);  /* pad with blanks */
        cptr += 80;
    }

    /*  EQUINOX keyword */
    tstatus = 0;
    if (ffgkey(fptr, "EQUINOX", valstring, NULL, &tstatus) == 0 )
    {
        ffmkky("EQUINOX", valstring, comm, cptr, status); /* construct keyword*/
        length = strlen(cptr);
        strncat(cptr, blanks, 80 - length);  /* pad with blanks */
        cptr += 80;
    }

    /*  RADECSYS keyword */
    tstatus = 0;
    if (ffgkey(fptr, "RADECSYS", valstring, NULL, &tstatus) == 0 )
    {
        ffmkky("RADECSYS", valstring, comm, cptr, status); /*construct keyword*/
        length = strlen(cptr);
        strncat(cptr, blanks, 80 - length);  /* pad with blanks */
        cptr += 80;
    }

    /*  TELESCOPE keyword */
    tstatus = 0;
    if (ffgkey(fptr, "TELESCOP", valstring, NULL, &tstatus) == 0 )
    {
        ffmkky("TELESCOP", valstring, comm, cptr, status); 
        length = strlen(cptr);
        strncat(cptr, blanks, 80 - length);  /* pad with blanks */
        cptr += 80;
    }

    /*  INSTRUME keyword */
    tstatus = 0;
    if (ffgkey(fptr, "INSTRUME", valstring, NULL, &tstatus) == 0 )
    {
        ffmkky("INSTRUME", valstring, comm, cptr, status);  
        length = strlen(cptr);
        strncat(cptr, blanks, 80 - length);  /* pad with blanks */
        cptr += 80;
    }

    /*  DETECTOR keyword */
    tstatus = 0;
    if (ffgkey(fptr, "DETECTOR", valstring, NULL, &tstatus) == 0 )
    {
        ffmkky("DETECTOR", valstring, comm, cptr, status);  
        length = strlen(cptr);
        strncat(cptr, blanks, 80 - length);  /* pad with blanks */
        cptr += 80;
    }

    /*  MJD-OBS keyword */
    tstatus = 0;
    if (ffgkey(fptr, "MJD-OBS", valstring, NULL, &tstatus) == 0 )
    {
        ffmkky("MJD-OBS", valstring, comm, cptr, status);  
        length = strlen(cptr);
        strncat(cptr, blanks, 80 - length);  /* pad with blanks */
        cptr += 80;
    }

    /*  DATE-OBS keyword */
    tstatus = 0;
    if (ffgkey(fptr, "DATE-OBS", valstring, NULL, &tstatus) == 0 )
    {
        ffmkky("DATE-OBS", valstring, comm, cptr, status);  
        length = strlen(cptr);
        strncat(cptr, blanks, 80 - length);  /* pad with blanks */
        cptr += 80;
    }

    /*  DATE keyword */
    tstatus = 0;
    if (ffgkey(fptr, "DATE", valstring, NULL, &tstatus) == 0 )
    {
        ffmkky("DATE", valstring, comm, cptr, status);  
        length = strlen(cptr);
        strncat(cptr, blanks, 80 - length);  /* pad with blanks */
        cptr += 80;
    }

    strcat(cptr, "END");
    strncat(cptr, blanks, 77);

    return(*status);
}
cfitsio/wcsutil.c0000644000225700000360000004060113246025103013637 0ustar  cagordonlhea#include 
#include "fitsio2.h"
#define D2R 0.01745329252
#define TWOPI 6.28318530717959

/*--------------------------------------------------------------------------*/
int ffwldp(double xpix, double ypix, double xref, double yref,
      double xrefpix, double yrefpix, double xinc, double yinc, double rot,
      char *type, double *xpos, double *ypos, int *status)

/* This routine is based on the classic AIPS WCS routine. 

   It converts from pixel location to RA,Dec for 9 projective geometries:
   "-CAR", "-SIN", "-TAN", "-ARC", "-NCP", "-GLS", "-MER", "-AIT" and "-STG".
*/

/*-----------------------------------------------------------------------*/
/* routine to determine accurate position for pixel coordinates          */
/* returns 0 if successful otherwise:                                    */
/* 501 = angle too large for projection;                                 */
/* does: -CAR, -SIN, -TAN, -ARC, -NCP, -GLS, -MER, -AIT  -STG projections*/
/* Input:                                                                */
/*   f   xpix    x pixel number  (RA or long without rotation)           */
/*   f   ypiy    y pixel number  (dec or lat without rotation)           */
/*   d   xref    x reference coordinate value (deg)                      */
/*   d   yref    y reference coordinate value (deg)                      */
/*   f   xrefpix x reference pixel                                       */
/*   f   yrefpix y reference pixel                                       */
/*   f   xinc    x coordinate increment (deg)                            */
/*   f   yinc    y coordinate increment (deg)                            */
/*   f   rot     rotation (deg)  (from N through E)                      */
/*   c  *type    projection type code e.g. "-SIN";                       */
/* Output:                                                               */
/*   d   *xpos   x (RA) coordinate (deg)                                 */
/*   d   *ypos   y (dec) coordinate (deg)                                */
/*-----------------------------------------------------------------------*/
 {double cosr, sinr, dx, dy, dz, temp, x, y, z;
  double sins, coss, dect, rat, dt, l, m, mg, da, dd, cos0, sin0;
  double dec0, ra0;
  double geo1, geo2, geo3;
  double deps = 1.0e-5;
  char *cptr;
  
  if (*status > 0)
     return(*status);

/*   Offset from ref pixel  */
  dx = (xpix-xrefpix) * xinc;
  dy = (ypix-yrefpix) * yinc;

/*   Take out rotation  */
  cosr = cos(rot * D2R);
  sinr = sin(rot * D2R);
  if (rot != 0.0) {
     temp = dx * cosr - dy * sinr;
     dy = dy * cosr + dx * sinr;
     dx = temp;
  }

/* convert to radians  */
  ra0 = xref * D2R;
  dec0 = yref * D2R;

  l = dx * D2R;
  m = dy * D2R;
  sins = l*l + m*m;
  cos0 = cos(dec0);
  sin0 = sin(dec0);

  if (*type != '-') {  /* unrecognized projection code */
     return(*status = 504);
  }

    cptr = type + 1;

    if (*cptr == 'C') { /* linear -CAR */
      if (*(cptr + 1) != 'A' ||  *(cptr + 2) != 'R') {
         return(*status = 504);
      }
      rat =  ra0 + l;
      dect = dec0 + m;

    } else if (*cptr == 'T') {  /* -TAN */
      if (*(cptr + 1) != 'A' ||  *(cptr + 2) != 'N') {
         return(*status = 504);
      }
      x = cos0*cos(ra0) - l*sin(ra0) - m*cos(ra0)*sin0;
      y = cos0*sin(ra0) + l*cos(ra0) - m*sin(ra0)*sin0;
      z = sin0                       + m*         cos0;
      rat  = atan2( y, x );
      dect = atan ( z / sqrt(x*x+y*y) );

    } else if (*cptr == 'S') {

      if (*(cptr + 1) == 'I' &&  *(cptr + 2) == 'N') { /* -SIN */
          if (sins>1.0)
	    return(*status = 501);
          coss = sqrt (1.0 - sins);
          dt = sin0 * coss + cos0 * m;
          if ((dt>1.0) || (dt<-1.0))
	    return(*status = 501);
          dect = asin (dt);
          rat = cos0 * coss - sin0 * m;
          if ((rat==0.0) && (l==0.0))
	    return(*status = 501);
          rat = atan2 (l, rat) + ra0;

       } else if (*(cptr + 1) == 'T' &&  *(cptr + 2) == 'G') {  /* -STG Sterographic*/
          dz = (4.0 - sins) / (4.0 + sins);
          if (fabs(dz)>1.0)
	    return(*status = 501);
          dect = dz * sin0 + m * cos0 * (1.0+dz) / 2.0;
          if (fabs(dect)>1.0)
	    return(*status = 501);
          dect = asin (dect);
          rat = cos(dect);
          if (fabs(rat)1.0)
	    return(*status = 501);
          rat = asin (rat);
          mg = 1.0 + sin(dect) * sin0 + cos(dect) * cos0 * cos(rat);
          if (fabs(mg)deps)
	    rat = TWOPI /2.0 - rat;
          rat = ra0 + rat;
        } else  {
          return(*status = 504);
        }
 
    } else if (*cptr == 'A') {

      if (*(cptr + 1) == 'R' &&  *(cptr + 2) == 'C') { /* ARC */
          if (sins>=TWOPI*TWOPI/4.0)
	    return(*status = 501);
          sins = sqrt(sins);
          coss = cos (sins);
          if (sins!=0.0)
	    sins = sin (sins) / sins;
          else
	    sins = 1.0;
          dt = m * cos0 * sins + sin0 * coss;
          if ((dt>1.0) || (dt<-1.0))
	    return(*status = 501);
          dect = asin (dt);
          da = coss - dt * sin0;
          dt = l * sins * cos0;
          if ((da==0.0) && (dt==0.0))
	    return(*status = 501);
          rat = ra0 + atan2 (dt, da);

      } else if (*(cptr + 1) == 'I' &&  *(cptr + 2) == 'T') {  /* -AIT Aitoff */
          dt = yinc*cosr + xinc*sinr;
          if (dt==0.0)
	    dt = 1.0;
          dt = dt * D2R;
          dy = yref * D2R;
          dx = sin(dy+dt)/sqrt((1.0+cos(dy+dt))/2.0) -
	      sin(dy)/sqrt((1.0+cos(dy))/2.0);
          if (dx==0.0)
	    dx = 1.0;
          geo2 = dt / dx;
          dt = xinc*cosr - yinc* sinr;
          if (dt==0.0)
	    dt = 1.0;
          dt = dt * D2R;
          dx = 2.0 * cos(dy) * sin(dt/2.0);
          if (dx==0.0) dx = 1.0;
          geo1 = dt * sqrt((1.0+cos(dy)*cos(dt/2.0))/2.0) / dx;
          geo3 = geo2 * sin(dy) / sqrt((1.0+cos(dy))/2.0);
          rat = ra0;
          dect = dec0;
          if ((l != 0.0) || (m != 0.0)) {
            dz = 4.0 - l*l/(4.0*geo1*geo1) - ((m+geo3)/geo2)*((m+geo3)/geo2) ;
            if ((dz>4.0) || (dz<2.0)) return(*status = 501);
            dz = 0.5 * sqrt (dz);
            dd = (m+geo3) * dz / geo2;
            if (fabs(dd)>1.0) return(*status = 501);
            dd = asin (dd);
            if (fabs(cos(dd))1.0) return(*status = 501);
            da = asin (da);
            rat = ra0 + 2.0 * da;
            dect = dd;
          }
        } else  {
          return(*status = 504);
        }
 
    } else if (*cptr == 'N') { /* -NCP North celestial pole*/
      if (*(cptr + 1) != 'C' ||  *(cptr + 2) != 'P') {
         return(*status = 504);
      }
      dect = cos0 - m * sin0;
      if (dect==0.0)
        return(*status = 501);
      rat = ra0 + atan2 (l, dect);
      dt = cos (rat-ra0);
      if (dt==0.0)
        return(*status = 501);
      dect = dect / dt;
      if ((dect>1.0) || (dect<-1.0))
        return(*status = 501);
      dect = acos (dect);
      if (dec0<0.0) dect = -dect;

    } else if (*cptr == 'G') {   /* -GLS global sinusoid */
      if (*(cptr + 1) != 'L' ||  *(cptr + 2) != 'S') {
         return(*status = 504);
      }
      dect = dec0 + m;
      if (fabs(dect)>TWOPI/4.0)
        return(*status = 501);
      coss = cos (dect);
      if (fabs(l)>TWOPI*coss/2.0)
        return(*status = 501);
      rat = ra0;
      if (coss>deps) rat = rat + l / coss;

    } else if (*cptr == 'M') {  /* -MER mercator*/
      if (*(cptr + 1) != 'E' ||  *(cptr + 2) != 'R') {
         return(*status = 504);
      }
      dt = yinc * cosr + xinc * sinr;
      if (dt==0.0) dt = 1.0;
      dy = (yref/2.0 + 45.0) * D2R;
      dx = dy + dt / 2.0 * D2R;
      dy = log (tan (dy));
      dx = log (tan (dx));
      geo2 = dt * D2R / (dx - dy);
      geo3 = geo2 * dy;
      geo1 = cos (yref*D2R);
      if (geo1<=0.0) geo1 = 1.0;
      rat = l / geo1 + ra0;
      if (fabs(rat - ra0) > TWOPI)
        return(*status = 501);
      dt = 0.0;
      if (geo2!=0.0) dt = (m + geo3) / geo2;
      dt = exp (dt);
      dect = 2.0 * atan (dt) - TWOPI / 4.0;

    } else  {
      return(*status = 504);
    }

  /*  correct for RA rollover  */
  if (rat-ra0>TWOPI/2.0) rat = rat - TWOPI;
  if (rat-ra0<-TWOPI/2.0) rat = rat + TWOPI;
  if (rat < 0.0) rat += TWOPI;

  /*  convert to degrees  */
  *xpos  = rat  / D2R;
  *ypos  = dect  / D2R;
  return(*status);
} 
/*--------------------------------------------------------------------------*/
int ffxypx(double xpos, double ypos, double xref, double yref, 
      double xrefpix, double yrefpix, double xinc, double yinc, double rot,
      char *type, double *xpix, double *ypix, int *status)

/* This routine is based on the classic AIPS WCS routine. 

   It converts from RA,Dec to pixel location to for 9 projective geometries:
   "-CAR", "-SIN", "-TAN", "-ARC", "-NCP", "-GLS", "-MER", "-AIT" and "-STG".
*/
/*-----------------------------------------------------------------------*/
/* routine to determine accurate pixel coordinates for an RA and Dec     */
/* returns 0 if successful otherwise:                                    */
/* 501 = angle too large for projection;                                 */
/* 502 = bad values                                                      */
/* does: -SIN, -TAN, -ARC, -NCP, -GLS, -MER, -AIT projections            */
/* anything else is linear                                               */
/* Input:                                                                */
/*   d   xpos    x (RA) coordinate (deg)                                 */
/*   d   ypos    y (dec) coordinate (deg)                                */
/*   d   xref    x reference coordinate value (deg)                      */
/*   d   yref    y reference coordinate value (deg)                      */
/*   f   xrefpix x reference pixel                                       */
/*   f   yrefpix y reference pixel                                       */
/*   f   xinc    x coordinate increment (deg)                            */
/*   f   yinc    y coordinate increment (deg)                            */
/*   f   rot     rotation (deg)  (from N through E)                      */
/*   c  *type    projection type code e.g. "-SIN";                       */
/* Output:                                                               */
/*   f  *xpix    x pixel number  (RA or long without rotation)           */
/*   f  *ypiy    y pixel number  (dec or lat without rotation)           */
/*-----------------------------------------------------------------------*/
 {
  double dx, dy, dz, r, ra0, dec0, ra, dec, coss, sins, dt, da, dd, sint;
  double l, m, geo1, geo2, geo3, sinr, cosr, cos0, sin0;
  double deps=1.0e-5;
  char *cptr;

  if (*type != '-') {  /* unrecognized projection code */
     return(*status = 504);
  }

  cptr = type + 1;

  dt = (xpos - xref);
  if (dt >  180) xpos -= 360;
  if (dt < -180) xpos += 360;
  /* NOTE: changing input argument xpos is OK (call-by-value in C!) */

  /* default values - linear */
  dx = xpos - xref;
  dy = ypos - yref;

  /*  Correct for rotation */
  r = rot * D2R;
  cosr = cos (r);
  sinr = sin (r);
  dz = dx*cosr + dy*sinr;
  dy = dy*cosr - dx*sinr;
  dx = dz;

  /*     check axis increments - bail out if either 0 */
  if ((xinc==0.0) || (yinc==0.0)) {*xpix=0.0; *ypix=0.0;
    return(*status = 502);}

  /*     convert to pixels  */
  *xpix = dx / xinc + xrefpix;
  *ypix = dy / yinc + yrefpix;

  if (*cptr == 'C') { /* linear -CAR */
      if (*(cptr + 1) != 'A' ||  *(cptr + 2) != 'R') {
         return(*status = 504);
      }

      return(*status);  /* done if linear */
  }

  /* Non linear position */
  ra0 = xref * D2R;
  dec0 = yref * D2R;
  ra = xpos * D2R;
  dec = ypos * D2R;

  /* compute direction cosine */
  coss = cos (dec);
  sins = sin (dec);
  cos0 = cos (dec0);
  sin0 = sin (dec0);
  l = sin(ra-ra0) * coss;
  sint = sins * sin0 + coss * cos0 * cos(ra-ra0);

    /* process by case  */
    if (*cptr == 'T') {  /* -TAN tan */
         if (*(cptr + 1) != 'A' ||  *(cptr + 2) != 'N') {
           return(*status = 504);
         }

         if (sint<=0.0)
	   return(*status = 501);
         if( cos0<0.001 ) {
            /* Do a first order expansion around pole */
            m = (coss * cos(ra-ra0)) / (sins * sin0);
            m = (-m + cos0 * (1.0 + m*m)) / sin0;
         } else {
            m = ( sins/sint - sin0 ) / cos0;
         }
	 if( fabs(sin(ra0)) < 0.3 ) {
	    l  = coss*sin(ra)/sint - cos0*sin(ra0) + m*sin(ra0)*sin0;
	    l /= cos(ra0);
	 } else {
	    l  = coss*cos(ra)/sint - cos0*cos(ra0) + m*cos(ra0)*sin0;
	    l /= -sin(ra0);
	 }

    } else if (*cptr == 'S') {

      if (*(cptr + 1) == 'I' &&  *(cptr + 2) == 'N') { /* -SIN */
         if (sint<0.0)
	   return(*status = 501);
         m = sins * cos(dec0) - coss * sin(dec0) * cos(ra-ra0);

      } else if (*(cptr + 1) == 'T' &&  *(cptr + 2) == 'G') {  /* -STG Sterographic*/
         da = ra - ra0;
         if (fabs(dec)>TWOPI/4.0)
	   return(*status = 501);
         dd = 1.0 + sins * sin(dec0) + coss * cos(dec0) * cos(da);
         if (fabs(dd)1.0) m = 1.0;
         m = acos (m);
         if (m!=0) 
            m = m / sin(m);
         else
            m = 1.0;
         l = l * m;
         m = (sins * cos(dec0) - coss * sin(dec0) * cos(ra-ra0)) * m;

      } else if (*(cptr + 1) == 'I' &&  *(cptr + 2) == 'T') {  /* -AIT Aitoff */
         da = (ra - ra0) / 2.0;
         if (fabs(da)>TWOPI/4.0)
	     return(*status = 501);
         dt = yinc*cosr + xinc*sinr;
         if (dt==0.0) dt = 1.0;
         dt = dt * D2R;
         dy = yref * D2R;
         dx = sin(dy+dt)/sqrt((1.0+cos(dy+dt))/2.0) -
             sin(dy)/sqrt((1.0+cos(dy))/2.0);
         if (dx==0.0) dx = 1.0;
         geo2 = dt / dx;
         dt = xinc*cosr - yinc* sinr;
         if (dt==0.0) dt = 1.0;
         dt = dt * D2R;
         dx = 2.0 * cos(dy) * sin(dt/2.0);
         if (dx==0.0) dx = 1.0;
         geo1 = dt * sqrt((1.0+cos(dy)*cos(dt/2.0))/2.0) / dx;
         geo3 = geo2 * sin(dy) / sqrt((1.0+cos(dy))/2.0);
         dt = sqrt ((1.0 + cos(dec) * cos(da))/2.0);
         if (fabs(dt)TWOPI/4.0)
	   return(*status = 501);
         if (fabs(dec0)>TWOPI/4.0)
	   return(*status = 501);
         m = dec - dec0;
         l = dt * coss;

    } else if (*cptr == 'M') {  /* -MER mercator*/
         if (*(cptr + 1) != 'E' ||  *(cptr + 2) != 'R') {
             return(*status = 504);
         }

         dt = yinc * cosr + xinc * sinr;
         if (dt==0.0) dt = 1.0;
         dy = (yref/2.0 + 45.0) * D2R;
         dx = dy + dt / 2.0 * D2R;
         dy = log (tan (dy));
         dx = log (tan (dx));
         geo2 = dt * D2R / (dx - dy);
         geo3 = geo2 * dy;
         geo1 = cos (yref*D2R);
         if (geo1<=0.0) geo1 = 1.0;
         dt = ra - ra0;
         l = geo1 * dt;
         dt = dec / 2.0 + TWOPI / 8.0;
         dt = tan (dt);
         if (dt
#include 
#include 
#include 

#ifdef _ALPHA_
#define e_magic_number IMAGE_FILE_MACHINE_ALPHA
#else
#define e_magic_number IMAGE_FILE_MACHINE_I386
#endif

/*
 *----------------------------------------------------------------------
 * GetArgcArgv --
 * 
 *	Break up a line into argc argv
 *----------------------------------------------------------------------
 */
int
GetArgcArgv(char *s, char **argv)
{
    int quote = 0;
    int argc = 0;
    char *bp;

    bp = s;
    while (1) {
	while (isspace(*bp)) {
	    bp++;
	}
	if (*bp == '\n' || *bp == '\0') {
	    *bp = '\0';
	    return argc;
	}
	if (*bp == '\"') {
	    quote = 1;
	    bp++;
	}
	argv[argc++] = bp;

	while (*bp != '\0') {
	    if (quote) {
		if (*bp == '\"') {
		    quote = 0;
		    *bp = '\0';
		    bp++;
		    break;
		}
		bp++;
		continue;
	    }
	    if (isspace(*bp)) {
		*bp = '\0';
		bp++;
		break;
	    }
	    bp++;
	}
    }
}

/*
 *  The names of the first group of possible symbol table storage classes
 */
char * SzStorageClass1[] = {
    "NULL","AUTOMATIC","EXTERNAL","STATIC","REGISTER","EXTERNAL_DEF","LABEL",
    "UNDEFINED_LABEL","MEMBER_OF_STRUCT","ARGUMENT","STRUCT_TAG",
    "MEMBER_OF_UNION","UNION_TAG","TYPE_DEFINITION","UNDEFINED_STATIC",
    "ENUM_TAG","MEMBER_OF_ENUM","REGISTER_PARAM","BIT_FIELD"
};

/*
 * The names of the second group of possible symbol table storage classes
 */
char * SzStorageClass2[] = {
    "BLOCK","FUNCTION","END_OF_STRUCT","FILE","SECTION","WEAK_EXTERNAL"
};

/*
 *----------------------------------------------------------------------
 * GetSZStorageClass --
 *
 *	Given a symbol storage class value, return a descriptive
 *	ASCII string
 *----------------------------------------------------------------------
 */
PSTR
GetSZStorageClass(BYTE storageClass)
{
	if ( storageClass <= IMAGE_SYM_CLASS_BIT_FIELD )
		return SzStorageClass1[storageClass];
	else if ( (storageClass >= IMAGE_SYM_CLASS_BLOCK)
		      && (storageClass <= IMAGE_SYM_CLASS_WEAK_EXTERNAL) )
		return SzStorageClass2[storageClass-IMAGE_SYM_CLASS_BLOCK];
	else
		return "???";
}

/*
 *----------------------------------------------------------------------
 * GetSectionName --
 *
 *	Used by DumpSymbolTable, it gives meaningful names to
 *	the non-normal section number.
 *
 * Results:
 *	A name is returned in buffer
 *----------------------------------------------------------------------
 */
void
GetSectionName(WORD section, PSTR buffer, unsigned cbBuffer)
{
    char tempbuffer[10];
	
    switch ( (SHORT)section )
    {
      case IMAGE_SYM_UNDEFINED: strcpy(tempbuffer, "UNDEF"); break;
      case IMAGE_SYM_ABSOLUTE:  strcpy(tempbuffer, "ABS  "); break;
      case IMAGE_SYM_DEBUG:	  strcpy(tempbuffer, "DEBUG"); break;
      default: wsprintf(tempbuffer, "%-5X", section);
    }
	
    strncpy(buffer, tempbuffer, cbBuffer-1);
}

/*
 *----------------------------------------------------------------------
 * DumpSymbolTable --
 *
 *	Dumps a COFF symbol table from an EXE or OBJ.  We only use
 *	it to dump tables from OBJs.
 *----------------------------------------------------------------------
 */
void
DumpSymbolTable(PIMAGE_SYMBOL pSymbolTable, FILE *fout, unsigned cSymbols)
{
    unsigned i;
    PSTR stringTable;
    char sectionName[10];
	
    fprintf(fout, "Symbol Table - %X entries  (* = auxillary symbol)\n",
	    cSymbols);

    fprintf(fout, 
     "Indx Name                 Value    Section    cAux  Type    Storage\n"
     "---- -------------------- -------- ---------- ----- ------- --------\n");

    /*
     * The string table apparently starts right after the symbol table
     */
    stringTable = (PSTR)&pSymbolTable[cSymbols]; 
		
    for ( i=0; i < cSymbols; i++ ) {
	fprintf(fout, "%04X ", i);
	if ( pSymbolTable->N.Name.Short != 0 )
	    fprintf(fout, "%-20.8s", pSymbolTable->N.ShortName);
	else
	    fprintf(fout, "%-20s", stringTable + pSymbolTable->N.Name.Long);

	fprintf(fout, " %08X", pSymbolTable->Value);

	GetSectionName(pSymbolTable->SectionNumber, sectionName,
		       sizeof(sectionName));
	fprintf(fout, " sect:%s aux:%X type:%02X st:%s\n",
	       sectionName,
	       pSymbolTable->NumberOfAuxSymbols,
	       pSymbolTable->Type,
	       GetSZStorageClass(pSymbolTable->StorageClass) );
#if 0
	if ( pSymbolTable->NumberOfAuxSymbols )
	    DumpAuxSymbols(pSymbolTable);
#endif

	/*
	 * Take into account any aux symbols
	 */
	i += pSymbolTable->NumberOfAuxSymbols;
	pSymbolTable += pSymbolTable->NumberOfAuxSymbols;
	pSymbolTable++;
    }
}

/*
 *----------------------------------------------------------------------
 * DumpExternals --
 *
 *	Dumps a COFF symbol table from an EXE or OBJ.  We only use
 *	it to dump tables from OBJs.
 *----------------------------------------------------------------------
 */
void
DumpExternals(PIMAGE_SYMBOL pSymbolTable, FILE *fout, unsigned cSymbols)
{
    unsigned i;
    PSTR stringTable;
    char *s, *f;
    char symbol[1024];
	
    /*
     * The string table apparently starts right after the symbol table
     */
    stringTable = (PSTR)&pSymbolTable[cSymbols]; 
		
    for ( i=0; i < cSymbols; i++ ) {
	if (pSymbolTable->SectionNumber > 0 && pSymbolTable->Type == 0x20) {
	    if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) {
		if (pSymbolTable->N.Name.Short != 0) {
		    strncpy(symbol, pSymbolTable->N.ShortName, 8);
		    symbol[8] = 0;
		} else {
		    s = stringTable + pSymbolTable->N.Name.Long;
		    strcpy(symbol, s);
		}
		s = symbol;
		f = strchr(s, '@');
		if (f) {
		    *f = 0;
		}
#if defined(_MSC_VER) && defined(_X86_)
		if (symbol[0] == '_') {
		    s = &symbol[1];
		}
#endif
		if ((stricmp(s, "DllEntryPoint") != 0) 
			&& (stricmp(s, "DllMain") != 0)) {
		    fprintf(fout, "\t%s\n", s);
		}
	    }
	}

	/*
	 * Take into account any aux symbols
	 */
	i += pSymbolTable->NumberOfAuxSymbols;
	pSymbolTable += pSymbolTable->NumberOfAuxSymbols;
	pSymbolTable++;
    }
}

/*
 *----------------------------------------------------------------------
 * DumpObjFile --
 *
 *	Dump an object file--either a full listing or just the exported
 *	symbols.
 *----------------------------------------------------------------------
 */
void
DumpObjFile(PIMAGE_FILE_HEADER pImageFileHeader, FILE *fout, int full)
{
    PIMAGE_SYMBOL PCOFFSymbolTable;
    DWORD COFFSymbolCount;
    
    PCOFFSymbolTable = (PIMAGE_SYMBOL)
	((DWORD)pImageFileHeader + pImageFileHeader->PointerToSymbolTable);
    COFFSymbolCount = pImageFileHeader->NumberOfSymbols;

    if (full) {
	DumpSymbolTable(PCOFFSymbolTable, fout, COFFSymbolCount);
    } else {
	DumpExternals(PCOFFSymbolTable, fout, COFFSymbolCount);
    }
}

/*
 *----------------------------------------------------------------------
 * SkipToNextRecord --
 *
 *	Skip over the current ROMF record and return the type of the
 *	next record.
 *----------------------------------------------------------------------
 */

BYTE
SkipToNextRecord(BYTE **ppBuffer)
{
    int length;
    (*ppBuffer)++;		/* Skip over the type.*/
    length = *((WORD*)(*ppBuffer))++; /* Retrieve the length. */
    *ppBuffer += length;	/* Skip over the rest. */
    return **ppBuffer;		/* Return the type. */
}

/*
 *----------------------------------------------------------------------
 * DumpROMFObjFile --
 *
 *	Dump a Relocatable Object Module Format file, displaying only
 *	the exported symbols.
 *----------------------------------------------------------------------
 */
void
DumpROMFObjFile(LPVOID pBuffer, FILE *fout)
{
    BYTE type, length;
    char symbol[1024], *s;

    while (1) {
	type = SkipToNextRecord(&(BYTE*)pBuffer);
	if (type == 0x90) {	/* PUBDEF */
	    if (((BYTE*)pBuffer)[4] != 0) {
		length = ((BYTE*)pBuffer)[5];
		strncpy(symbol, ((char*)pBuffer) + 6, length);
		symbol[length] = '\0';
		s = symbol;
		if ((stricmp(s, "DllEntryPoint") != 0) 
			&& (stricmp(s, "DllMain") != 0)) {
		    if (s[0] == '_') {
			s++;
			fprintf(fout, "\t_%s\n\t%s=_%s\n", s, s, s);
		    } else {
			fprintf(fout, "\t%s\n", s);
		    }
		}
	    }
	} else if (type == 0x8B || type == 0x8A) { /* MODEND */
	    break;
	}
    }
}

/*
 *----------------------------------------------------------------------
 * DumpFile --
 *
 *	Open up a file, memory map it, and call the appropriate
 *	dumping routine
 *----------------------------------------------------------------------
 */
void
DumpFile(LPSTR filename, FILE *fout, int full)
{
    HANDLE hFile;
    HANDLE hFileMapping;
    LPVOID lpFileBase;
    PIMAGE_DOS_HEADER dosHeader;
	
    hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
		       OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
					
    if (hFile == INVALID_HANDLE_VALUE) {
	fprintf(stderr, "Couldn't open file with CreateFile()\n");
	return;
    }

    hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
    if (hFileMapping == 0) {
	CloseHandle(hFile);
	fprintf(stderr, "Couldn't open file mapping with CreateFileMapping()\n");
	return;
    }

    lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
    if (lpFileBase == 0) {
	CloseHandle(hFileMapping);
	CloseHandle(hFile);
	fprintf(stderr, "Couldn't map view of file with MapViewOfFile()\n");
	return;
    }

    dosHeader = (PIMAGE_DOS_HEADER)lpFileBase;
    if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) {
#if 0
	DumpExeFile( dosHeader );
#else
	fprintf(stderr, "File is an executable.  I don't dump those.\n");
	return;
#endif
    }
    /* Does it look like a i386 COFF OBJ file??? */
    else if ((dosHeader->e_magic == e_magic_number)
	    && (dosHeader->e_sp == 0)) {
	/*
	 * The two tests above aren't what they look like.  They're
	 * really checking for IMAGE_FILE_HEADER.Machine == i386 (0x14C)
	 * and IMAGE_FILE_HEADER.SizeOfOptionalHeader == 0;
	 */
	DumpObjFile((PIMAGE_FILE_HEADER) lpFileBase, fout, full);
    } else if (*((BYTE *)lpFileBase) == 0x80) {
	/*
	 * This file looks like it might be a ROMF file.
	 */
	DumpROMFObjFile(lpFileBase, fout);
    } else {
	printf("unrecognized file format\n");
    }
    UnmapViewOfFile(lpFileBase);
    CloseHandle(hFileMapping);
    CloseHandle(hFile);
}

void
main(int argc, char **argv)
{
    char *fargv[1000];
    char cmdline[10000];
    int i, arg;
    FILE *fout;
    int pos;
    int full = 0;
    char *outfile = NULL;

    if (argc < 3) {
      Usage:
	fprintf(stderr, "Usage: %s ?-o outfile? ?-f(ull)?   ..\n", argv[0]);
	exit(1);
    }

    arg = 1;
    while (argv[arg][0] == '-') {
	if (strcmp(argv[arg], "--") == 0) {
	    arg++;
	    break;
	} else if (strcmp(argv[arg], "-f") == 0) {
	    full = 1;
	} else if (strcmp(argv[arg], "-o") == 0) {
	    arg++;
	    if (arg == argc) {
		goto Usage;
	    }
	    outfile = argv[arg];
	}
	arg++;
    }
    if (arg == argc) {
	goto Usage;
    }

    if (outfile) {
	fout = fopen(outfile, "w+");
	if (fout == NULL) {
	    fprintf(stderr, "Unable to open \'%s\' for writing:\n",
		    argv[arg]);
	    perror("");
	    exit(1);
	}
    } else {
	fout = stdout;
    }
    
    if (! full) {
	char *dllname = argv[arg];
	arg++;
	if (arg == argc) {
	    goto Usage;
	}
	fprintf(fout, "LIBRARY    %s\n", dllname);
	fprintf(fout, "EXETYPE WINDOWS\n");
	fprintf(fout, "CODE PRELOAD MOVEABLE DISCARDABLE\n");
	fprintf(fout, "DATA PRELOAD MOVEABLE MULTIPLE\n\n");
	fprintf(fout, "EXPORTS\n");
    }

    for (; arg < argc; arg++) {
	if (argv[arg][0] == '@') {
	    FILE *fargs = fopen(&argv[arg][1], "r");
	    if (fargs == NULL) {
		fprintf(stderr, "Unable to open \'%s\' for reading:\n",
			argv[arg]);
		perror("");
		exit(1);
	    }
	    pos = 0;
	    for (i = 0; i < arg; i++) {
		strcpy(&cmdline[pos], argv[i]);
		pos += strlen(&cmdline[pos]) + 1;
		fargv[i] = argv[i];
	    }
	    fgets(&cmdline[pos], sizeof(cmdline), fargs);
	    fprintf(stderr, "%s\n", &cmdline[pos]);
	    fclose(fargs);
	    i += GetArgcArgv(&cmdline[pos], &fargv[i]);
	    argc = i;
	    argv = fargv;
	}
	DumpFile(argv[arg], fout, full);
    }
    exit(0);
}
cfitsio/zlib/0000755000225700000360000000000013246025103012740 5ustar  cagordonlheacfitsio/zlib/adler32.c0000644000225700000360000001164713246025103014351 0ustar  cagordonlhea/* adler32.c -- compute the Adler-32 checksum of a data stream
 * Copyright (C) 1995-2007 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

#include "zutil.h"

#define local static

local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2);

#define BASE 65521UL    /* largest prime smaller than 65536 */
#define NMAX 5552
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */

#define DO1(buf,i)  {adler += (buf)[i]; sum2 += adler;}
#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
#define DO16(buf)   DO8(buf,0); DO8(buf,8);

/* use NO_DIVIDE if your processor does not do division in hardware */
#ifdef NO_DIVIDE
#  define MOD(a) \
    do { \
        if (a >= (BASE << 16)) a -= (BASE << 16); \
        if (a >= (BASE << 15)) a -= (BASE << 15); \
        if (a >= (BASE << 14)) a -= (BASE << 14); \
        if (a >= (BASE << 13)) a -= (BASE << 13); \
        if (a >= (BASE << 12)) a -= (BASE << 12); \
        if (a >= (BASE << 11)) a -= (BASE << 11); \
        if (a >= (BASE << 10)) a -= (BASE << 10); \
        if (a >= (BASE << 9)) a -= (BASE << 9); \
        if (a >= (BASE << 8)) a -= (BASE << 8); \
        if (a >= (BASE << 7)) a -= (BASE << 7); \
        if (a >= (BASE << 6)) a -= (BASE << 6); \
        if (a >= (BASE << 5)) a -= (BASE << 5); \
        if (a >= (BASE << 4)) a -= (BASE << 4); \
        if (a >= (BASE << 3)) a -= (BASE << 3); \
        if (a >= (BASE << 2)) a -= (BASE << 2); \
        if (a >= (BASE << 1)) a -= (BASE << 1); \
        if (a >= BASE) a -= BASE; \
    } while (0)
#  define MOD4(a) \
    do { \
        if (a >= (BASE << 4)) a -= (BASE << 4); \
        if (a >= (BASE << 3)) a -= (BASE << 3); \
        if (a >= (BASE << 2)) a -= (BASE << 2); \
        if (a >= (BASE << 1)) a -= (BASE << 1); \
        if (a >= BASE) a -= BASE; \
    } while (0)
#else
#  define MOD(a) a %= BASE
#  define MOD4(a) a %= BASE
#endif

/* ========================================================================= */
uLong ZEXPORT adler32(adler, buf, len)
    uLong adler;
    const Bytef *buf;
    uInt len;
{
    unsigned long sum2;
    unsigned n;

    /* split Adler-32 into component sums */
    sum2 = (adler >> 16) & 0xffff;
    adler &= 0xffff;

    /* in case user likes doing a byte at a time, keep it fast */
    if (len == 1) {
        adler += buf[0];
        if (adler >= BASE)
            adler -= BASE;
        sum2 += adler;
        if (sum2 >= BASE)
            sum2 -= BASE;
        return adler | (sum2 << 16);
    }

    /* initial Adler-32 value (deferred check for len == 1 speed) */
    if (buf == Z_NULL)
        return 1L;

    /* in case short lengths are provided, keep it somewhat fast */
    if (len < 16) {
        while (len--) {
            adler += *buf++;
            sum2 += adler;
        }
        if (adler >= BASE)
            adler -= BASE;
        MOD4(sum2);             /* only added so many BASE's */
        return adler | (sum2 << 16);
    }

    /* do length NMAX blocks -- requires just one modulo operation */
    while (len >= NMAX) {
        len -= NMAX;
        n = NMAX / 16;          /* NMAX is divisible by 16 */
        do {
            DO16(buf);          /* 16 sums unrolled */
            buf += 16;
        } while (--n);
        MOD(adler);
        MOD(sum2);
    }

    /* do remaining bytes (less than NMAX, still just one modulo) */
    if (len) {                  /* avoid modulos if none remaining */
        while (len >= 16) {
            len -= 16;
            DO16(buf);
            buf += 16;
        }
        while (len--) {
            adler += *buf++;
            sum2 += adler;
        }
        MOD(adler);
        MOD(sum2);
    }

    /* return recombined sums */
    return adler | (sum2 << 16);
}

/* ========================================================================= */
local uLong adler32_combine_(adler1, adler2, len2)
    uLong adler1;
    uLong adler2;
    z_off64_t len2;
{
    unsigned long sum1;
    unsigned long sum2;
    unsigned rem;

    /* the derivation of this formula is left as an exercise for the reader */
    rem = (unsigned)(len2 % BASE);
    sum1 = adler1 & 0xffff;
    sum2 = rem * sum1;
    MOD(sum2);
    sum1 += (adler2 & 0xffff) + BASE - 1;
    sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
    if (sum1 >= BASE) sum1 -= BASE;
    if (sum1 >= BASE) sum1 -= BASE;
    if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1);
    if (sum2 >= BASE) sum2 -= BASE;
    return sum1 | (sum2 << 16);
}

/* ========================================================================= */
uLong ZEXPORT adler32_combine(adler1, adler2, len2)
    uLong adler1;
    uLong adler2;
    z_off_t len2;
{
    return adler32_combine_(adler1, adler2, len2);
}

uLong ZEXPORT adler32_combine64(adler1, adler2, len2)
    uLong adler1;
    uLong adler2;
    z_off64_t len2;
{
    return adler32_combine_(adler1, adler2, len2);
}
cfitsio/zlib/crc32.c0000644000225700000360000003254013246025103014024 0ustar  cagordonlhea/* crc32.c -- compute the CRC-32 of a data stream
 * Copyright (C) 1995-2006, 2010 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 *
 * Thanks to Rodney Brown  for his contribution of faster
 * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
 * tables for updating the shift register in one step with three exclusive-ors
 * instead of four steps with four exclusive-ors.  This results in about a
 * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
 */

/*
  Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
  protection on the static variables used to control the first-use generation
  of the crc tables.  Therefore, if you #define DYNAMIC_CRC_TABLE, you should
  first call get_crc_table() to initialize the tables before allowing more than
  one thread to use crc32().
 */

#ifdef MAKECRCH
#  include 
#  ifndef DYNAMIC_CRC_TABLE
#    define DYNAMIC_CRC_TABLE
#  endif /* !DYNAMIC_CRC_TABLE */
#endif /* MAKECRCH */

#include "zutil.h"      /* for STDC and FAR definitions */

#define local static

/* Find a four-byte integer type for crc32_little() and crc32_big(). */
#ifndef NOBYFOUR
#  ifdef STDC           /* need ANSI C limits.h to determine sizes */
#    include 
#    define BYFOUR
#    if (UINT_MAX == 0xffffffffUL)
       typedef unsigned int u4;
#    else
#      if (ULONG_MAX == 0xffffffffUL)
         typedef unsigned long u4;
#      else
#        if (USHRT_MAX == 0xffffffffUL)
           typedef unsigned short u4;
#        else
#          undef BYFOUR     /* can't find a four-byte integer type! */
#        endif
#      endif
#    endif
#  endif /* STDC */
#endif /* !NOBYFOUR */

/* Definitions for doing the crc four data bytes at a time. */
#ifdef BYFOUR
#  define REV(w) ((((w)>>24)&0xff)+(((w)>>8)&0xff00)+ \
                (((w)&0xff00)<<8)+(((w)&0xff)<<24))
   local unsigned long crc32_little OF((unsigned long,
                        const unsigned char FAR *, unsigned));
   local unsigned long crc32_big OF((unsigned long,
                        const unsigned char FAR *, unsigned));
#  define TBLS 8
#else
#  define TBLS 1
#endif /* BYFOUR */

/* Local functions for crc concatenation */
local unsigned long gf2_matrix_times OF((unsigned long *mat,
                                         unsigned long vec));
local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2);


#ifdef DYNAMIC_CRC_TABLE

local volatile int crc_table_empty = 1;
local unsigned long FAR crc_table[TBLS][256];
local void make_crc_table OF((void));
#ifdef MAKECRCH
   local void write_table OF((FILE *, const unsigned long FAR *));
#endif /* MAKECRCH */
/*
  Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
  x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.

  Polynomials over GF(2) are represented in binary, one bit per coefficient,
  with the lowest powers in the most significant bit.  Then adding polynomials
  is just exclusive-or, and multiplying a polynomial by x is a right shift by
  one.  If we call the above polynomial p, and represent a byte as the
  polynomial q, also with the lowest power in the most significant bit (so the
  byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
  where a mod b means the remainder after dividing a by b.

  This calculation is done using the shift-register method of multiplying and
  taking the remainder.  The register is initialized to zero, and for each
  incoming bit, x^32 is added mod p to the register if the bit is a one (where
  x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
  x (which is shifting right by one and adding x^32 mod p if the bit shifted
  out is a one).  We start with the highest power (least significant bit) of
  q and repeat for all eight bits of q.

  The first table is simply the CRC of all possible eight bit values.  This is
  all the information needed to generate CRCs on data a byte at a time for all
  combinations of CRC register values and incoming bytes.  The remaining tables
  allow for word-at-a-time CRC calculation for both big-endian and little-
  endian machines, where a word is four bytes.
*/
local void make_crc_table()
{
    unsigned long c;
    int n, k;
    unsigned long poly;                 /* polynomial exclusive-or pattern */
    /* terms of polynomial defining this crc (except x^32): */
    static volatile int first = 1;      /* flag to limit concurrent making */
    static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};

    /* See if another task is already doing this (not thread-safe, but better
       than nothing -- significantly reduces duration of vulnerability in
       case the advice about DYNAMIC_CRC_TABLE is ignored) */
    if (first) {
        first = 0;

        /* make exclusive-or pattern from polynomial (0xedb88320UL) */
        poly = 0UL;
        for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
            poly |= 1UL << (31 - p[n]);

        /* generate a crc for every 8-bit value */
        for (n = 0; n < 256; n++) {
            c = (unsigned long)n;
            for (k = 0; k < 8; k++)
                c = c & 1 ? poly ^ (c >> 1) : c >> 1;
            crc_table[0][n] = c;
        }

#ifdef BYFOUR
        /* generate crc for each value followed by one, two, and three zeros,
           and then the byte reversal of those as well as the first table */
        for (n = 0; n < 256; n++) {
            c = crc_table[0][n];
            crc_table[4][n] = REV(c);
            for (k = 1; k < 4; k++) {
                c = crc_table[0][c & 0xff] ^ (c >> 8);
                crc_table[k][n] = c;
                crc_table[k + 4][n] = REV(c);
            }
        }
#endif /* BYFOUR */

        crc_table_empty = 0;
    }
    else {      /* not first */
        /* wait for the other guy to finish (not efficient, but rare) */
        while (crc_table_empty)
            ;
    }

#ifdef MAKECRCH
    /* write out CRC tables to crc32.h */
    {
        FILE *out;

        out = fopen("crc32.h", "w");
        if (out == NULL) return;
        fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
        fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
        fprintf(out, "local const unsigned long FAR ");
        fprintf(out, "crc_table[TBLS][256] =\n{\n  {\n");
        write_table(out, crc_table[0]);
#  ifdef BYFOUR
        fprintf(out, "#ifdef BYFOUR\n");
        for (k = 1; k < 8; k++) {
            fprintf(out, "  },\n  {\n");
            write_table(out, crc_table[k]);
        }
        fprintf(out, "#endif\n");
#  endif /* BYFOUR */
        fprintf(out, "  }\n};\n");
        fclose(out);
    }
#endif /* MAKECRCH */
}

#ifdef MAKECRCH
local void write_table(out, table)
    FILE *out;
    const unsigned long FAR *table;
{
    int n;

    for (n = 0; n < 256; n++)
        fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : "    ", table[n],
                n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
}
#endif /* MAKECRCH */

#else /* !DYNAMIC_CRC_TABLE */
/* ========================================================================
 * Tables of CRC-32s of all single-byte values, made by make_crc_table().
 */
#include "crc32.h"
#endif /* DYNAMIC_CRC_TABLE */

/* =========================================================================
 * This function can be used by asm versions of crc32()
 */
const unsigned long FAR * ZEXPORT get_crc_table()
{
#ifdef DYNAMIC_CRC_TABLE
    if (crc_table_empty)
        make_crc_table();
#endif /* DYNAMIC_CRC_TABLE */
    return (const unsigned long FAR *)crc_table;
}

/* ========================================================================= */
#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1

/* ========================================================================= */
unsigned long ZEXPORT crc32(crc, buf, len)
    unsigned long crc;
    const unsigned char FAR *buf;
    uInt len;
{
    if (buf == Z_NULL) return 0UL;

#ifdef DYNAMIC_CRC_TABLE
    if (crc_table_empty)
        make_crc_table();
#endif /* DYNAMIC_CRC_TABLE */

#ifdef BYFOUR
    if (sizeof(void *) == sizeof(ptrdiff_t)) {
        u4 endian;

        endian = 1;
        if (*((unsigned char *)(&endian)))
            return crc32_little(crc, buf, len);
        else
            return crc32_big(crc, buf, len);
    }
#endif /* BYFOUR */
    crc = crc ^ 0xffffffffUL;
    while (len >= 8) {
        DO8;
        len -= 8;
    }
    if (len) do {
        DO1;
    } while (--len);
    return crc ^ 0xffffffffUL;
}

#ifdef BYFOUR

/* ========================================================================= */
#define DOLIT4 c ^= *buf4++; \
        c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
            crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4

/* ========================================================================= */
local unsigned long crc32_little(crc, buf, len)
    unsigned long crc;
    const unsigned char FAR *buf;
    unsigned len;
{
    register u4 c;
    register const u4 FAR *buf4;

    c = (u4)crc;
    c = ~c;
    while (len && ((ptrdiff_t)buf & 3)) {
        c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
        len--;
    }

    buf4 = (const u4 FAR *)(const void FAR *)buf;
    while (len >= 32) {
        DOLIT32;
        len -= 32;
    }
    while (len >= 4) {
        DOLIT4;
        len -= 4;
    }
    buf = (const unsigned char FAR *)buf4;

    if (len) do {
        c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
    } while (--len);
    c = ~c;
    return (unsigned long)c;
}

/* ========================================================================= */
#define DOBIG4 c ^= *++buf4; \
        c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
            crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4

/* ========================================================================= */
local unsigned long crc32_big(crc, buf, len)
    unsigned long crc;
    const unsigned char FAR *buf;
    unsigned len;
{
    register u4 c;
    register const u4 FAR *buf4;

    c = REV((u4)crc);
    c = ~c;
    while (len && ((ptrdiff_t)buf & 3)) {
        c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
        len--;
    }

    buf4 = (const u4 FAR *)(const void FAR *)buf;
    buf4--;
    while (len >= 32) {
        DOBIG32;
        len -= 32;
    }
    while (len >= 4) {
        DOBIG4;
        len -= 4;
    }
    buf4++;
    buf = (const unsigned char FAR *)buf4;

    if (len) do {
        c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
    } while (--len);
    c = ~c;
    return (unsigned long)(REV(c));
}

#endif /* BYFOUR */

#define GF2_DIM 32      /* dimension of GF(2) vectors (length of CRC) */

/* ========================================================================= */
local unsigned long gf2_matrix_times(mat, vec)
    unsigned long *mat;
    unsigned long vec;
{
    unsigned long sum;

    sum = 0;
    while (vec) {
        if (vec & 1)
            sum ^= *mat;
        vec >>= 1;
        mat++;
    }
    return sum;
}

/* ========================================================================= */
local void gf2_matrix_square(square, mat)
    unsigned long *square;
    unsigned long *mat;
{
    int n;

    for (n = 0; n < GF2_DIM; n++)
        square[n] = gf2_matrix_times(mat, mat[n]);
}

/* ========================================================================= */
local uLong crc32_combine_(crc1, crc2, len2)
    uLong crc1;
    uLong crc2;
    z_off64_t len2;
{
    int n;
    unsigned long row;
    unsigned long even[GF2_DIM];    /* even-power-of-two zeros operator */
    unsigned long odd[GF2_DIM];     /* odd-power-of-two zeros operator */

    /* degenerate case (also disallow negative lengths) */
    if (len2 <= 0)
        return crc1;

    /* put operator for one zero bit in odd */
    odd[0] = 0xedb88320UL;          /* CRC-32 polynomial */
    row = 1;
    for (n = 1; n < GF2_DIM; n++) {
        odd[n] = row;
        row <<= 1;
    }

    /* put operator for two zero bits in even */
    gf2_matrix_square(even, odd);

    /* put operator for four zero bits in odd */
    gf2_matrix_square(odd, even);

    /* apply len2 zeros to crc1 (first square will put the operator for one
       zero byte, eight zero bits, in even) */
    do {
        /* apply zeros operator for this bit of len2 */
        gf2_matrix_square(even, odd);
        if (len2 & 1)
            crc1 = gf2_matrix_times(even, crc1);
        len2 >>= 1;

        /* if no more bits set, then done */
        if (len2 == 0)
            break;

        /* another iteration of the loop with odd and even swapped */
        gf2_matrix_square(odd, even);
        if (len2 & 1)
            crc1 = gf2_matrix_times(odd, crc1);
        len2 >>= 1;

        /* if no more bits set, then done */
    } while (len2 != 0);

    /* return combined crc */
    crc1 ^= crc2;
    return crc1;
}

/* ========================================================================= */
uLong ZEXPORT crc32_combine(crc1, crc2, len2)
    uLong crc1;
    uLong crc2;
    z_off_t len2;
{
    return crc32_combine_(crc1, crc2, len2);
}

uLong ZEXPORT crc32_combine64(crc1, crc2, len2)
    uLong crc1;
    uLong crc2;
    z_off64_t len2;
{
    return crc32_combine_(crc1, crc2, len2);
}
cfitsio/zlib/crc32.h0000644000225700000360000007355013246025103014037 0ustar  cagordonlhea/* crc32.h -- tables for rapid CRC calculation
 * Generated automatically by crc32.c
 */

local const unsigned long FAR crc_table[TBLS][256] =
{
  {
    0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
    0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
    0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
    0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
    0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
    0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
    0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
    0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
    0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
    0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
    0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
    0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
    0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
    0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
    0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
    0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
    0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
    0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
    0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
    0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
    0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
    0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
    0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
    0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
    0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
    0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
    0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
    0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
    0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
    0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
    0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
    0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
    0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
    0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
    0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
    0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
    0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
    0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
    0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
    0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
    0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
    0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
    0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
    0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
    0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
    0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
    0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
    0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
    0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
    0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
    0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
    0x2d02ef8dUL
#ifdef BYFOUR
  },
  {
    0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
    0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
    0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
    0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
    0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
    0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
    0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
    0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
    0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
    0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
    0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
    0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
    0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
    0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
    0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
    0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
    0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
    0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
    0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
    0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
    0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
    0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
    0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
    0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
    0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
    0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
    0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
    0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
    0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
    0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
    0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
    0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
    0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
    0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
    0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
    0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
    0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
    0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
    0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
    0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
    0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
    0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
    0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
    0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
    0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
    0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
    0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
    0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
    0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
    0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
    0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
    0x9324fd72UL
  },
  {
    0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
    0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
    0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
    0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
    0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
    0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
    0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
    0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
    0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
    0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
    0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
    0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
    0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
    0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
    0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
    0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
    0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
    0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
    0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
    0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
    0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
    0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
    0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
    0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
    0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
    0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
    0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
    0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
    0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
    0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
    0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
    0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
    0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
    0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
    0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
    0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
    0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
    0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
    0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
    0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
    0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
    0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
    0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
    0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
    0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
    0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
    0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
    0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
    0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
    0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
    0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
    0xbe9834edUL
  },
  {
    0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
    0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
    0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
    0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
    0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
    0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
    0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
    0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
    0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
    0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
    0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
    0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
    0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
    0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
    0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
    0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
    0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
    0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
    0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
    0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
    0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
    0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
    0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
    0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
    0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
    0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
    0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
    0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
    0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
    0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
    0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
    0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
    0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
    0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
    0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
    0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
    0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
    0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
    0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
    0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
    0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
    0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
    0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
    0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
    0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
    0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
    0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
    0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
    0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
    0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
    0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
    0xde0506f1UL
  },
  {
    0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
    0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
    0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
    0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
    0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
    0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
    0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
    0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
    0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
    0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
    0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
    0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
    0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
    0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
    0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
    0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
    0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
    0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
    0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
    0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
    0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
    0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
    0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
    0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
    0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
    0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
    0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
    0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
    0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
    0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
    0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
    0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
    0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
    0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
    0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
    0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
    0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
    0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
    0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
    0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
    0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
    0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
    0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
    0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
    0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
    0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
    0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
    0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
    0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
    0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
    0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
    0x8def022dUL
  },
  {
    0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
    0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
    0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
    0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
    0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
    0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
    0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
    0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
    0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
    0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
    0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
    0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
    0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
    0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
    0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
    0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
    0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
    0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
    0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
    0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
    0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
    0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
    0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
    0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
    0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
    0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
    0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
    0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
    0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
    0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
    0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
    0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
    0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
    0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
    0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
    0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
    0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
    0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
    0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
    0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
    0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
    0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
    0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
    0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
    0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
    0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
    0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
    0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
    0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
    0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
    0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
    0x72fd2493UL
  },
  {
    0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
    0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
    0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
    0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
    0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
    0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
    0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
    0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
    0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
    0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
    0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
    0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
    0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
    0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
    0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
    0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
    0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
    0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
    0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
    0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
    0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
    0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
    0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
    0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
    0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
    0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
    0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
    0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
    0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
    0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
    0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
    0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
    0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
    0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
    0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
    0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
    0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
    0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
    0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
    0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
    0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
    0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
    0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
    0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
    0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
    0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
    0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
    0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
    0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
    0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
    0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
    0xed3498beUL
  },
  {
    0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
    0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
    0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
    0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
    0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
    0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
    0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
    0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
    0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
    0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
    0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
    0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
    0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
    0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
    0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
    0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
    0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
    0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
    0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
    0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
    0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
    0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
    0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
    0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
    0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
    0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
    0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
    0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
    0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
    0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
    0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
    0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
    0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
    0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
    0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
    0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
    0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
    0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
    0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
    0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
    0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
    0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
    0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
    0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
    0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
    0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
    0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
    0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
    0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
    0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
    0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
    0xf10605deUL
#endif
  }
};
cfitsio/zlib/deflate.c0000644000225700000360000020460713246025103014521 0ustar  cagordonlhea/* deflate.c -- compress data using the deflation algorithm
 * Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

/*
 *  ALGORITHM
 *
 *      The "deflation" process depends on being able to identify portions
 *      of the input text which are identical to earlier input (within a
 *      sliding window trailing behind the input currently being processed).
 *
 *      The most straightforward technique turns out to be the fastest for
 *      most input files: try all possible matches and select the longest.
 *      The key feature of this algorithm is that insertions into the string
 *      dictionary are very simple and thus fast, and deletions are avoided
 *      completely. Insertions are performed at each input character, whereas
 *      string matches are performed only when the previous match ends. So it
 *      is preferable to spend more time in matches to allow very fast string
 *      insertions and avoid deletions. The matching algorithm for small
 *      strings is inspired from that of Rabin & Karp. A brute force approach
 *      is used to find longer strings when a small match has been found.
 *      A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
 *      (by Leonid Broukhis).
 *         A previous version of this file used a more sophisticated algorithm
 *      (by Fiala and Greene) which is guaranteed to run in linear amortized
 *      time, but has a larger average cost, uses more memory and is patented.
 *      However the F&G algorithm may be faster for some highly redundant
 *      files if the parameter max_chain_length (described below) is too large.
 *
 *  ACKNOWLEDGEMENTS
 *
 *      The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
 *      I found it in 'freeze' written by Leonid Broukhis.
 *      Thanks to many people for bug reports and testing.
 *
 *  REFERENCES
 *
 *      Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
 *      Available in http://www.ietf.org/rfc/rfc1951.txt
 *
 *      A description of the Rabin and Karp algorithm is given in the book
 *         "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
 *
 *      Fiala,E.R., and Greene,D.H.
 *         Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
 *
 */

#include "deflate.h"

const char deflate_copyright[] =
   " deflate 1.2.5 Copyright 1995-2010 Jean-loup Gailly and Mark Adler ";
/*
  If you use the zlib library in a product, an acknowledgment is welcome
  in the documentation of your product. If for some reason you cannot
  include such an acknowledgment, I would appreciate that you keep this
  copyright string in the executable of your product.
 */

/* ===========================================================================
 *  Function prototypes.
 */
typedef enum {
    need_more,      /* block not completed, need more input or more output */
    block_done,     /* block flush performed */
    finish_started, /* finish started, need only more output at next deflate */
    finish_done     /* finish done, accept no more input or output */
} block_state;

typedef block_state (*compress_func) OF((deflate_state *s, int flush));
/* Compression function. Returns the block state after the call. */

local void fill_window    OF((deflate_state *s));
local block_state deflate_stored OF((deflate_state *s, int flush));
local block_state deflate_fast   OF((deflate_state *s, int flush));
#ifndef FASTEST
local block_state deflate_slow   OF((deflate_state *s, int flush));
#endif
local block_state deflate_rle    OF((deflate_state *s, int flush));
local block_state deflate_huff   OF((deflate_state *s, int flush));
local void lm_init        OF((deflate_state *s));
local void putShortMSB    OF((deflate_state *s, uInt b));
local void flush_pending  OF((z_streamp strm));
local int read_buf        OF((z_streamp strm, Bytef *buf, unsigned size));
#ifdef ASMV
      void match_init OF((void)); /* asm code initialization */
      uInt longest_match  OF((deflate_state *s, IPos cur_match));
#else
local uInt longest_match  OF((deflate_state *s, IPos cur_match));
#endif

#ifdef DEBUG
local  void check_match OF((deflate_state *s, IPos start, IPos match,
                            int length));
#endif

/* ===========================================================================
 * Local data
 */

#define NIL 0
/* Tail of hash chains */

#ifndef TOO_FAR
#  define TOO_FAR 4096
#endif
/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */

/* Values for max_lazy_match, good_match and max_chain_length, depending on
 * the desired pack level (0..9). The values given below have been tuned to
 * exclude worst case performance for pathological files. Better values may be
 * found for specific files.
 */
typedef struct config_s {
   ush good_length; /* reduce lazy search above this match length */
   ush max_lazy;    /* do not perform lazy search above this match length */
   ush nice_length; /* quit search above this match length */
   ush max_chain;
   compress_func func;
} config;

#ifdef FASTEST
local const config configuration_table[2] = {
/*      good lazy nice chain */
/* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */
/* 1 */ {4,    4,  8,    4, deflate_fast}}; /* max speed, no lazy matches */
#else
local const config configuration_table[10] = {
/*      good lazy nice chain */
/* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */
/* 1 */ {4,    4,  8,    4, deflate_fast}, /* max speed, no lazy matches */
/* 2 */ {4,    5, 16,    8, deflate_fast},
/* 3 */ {4,    6, 32,   32, deflate_fast},

/* 4 */ {4,    4, 16,   16, deflate_slow},  /* lazy matches */
/* 5 */ {8,   16, 32,   32, deflate_slow},
/* 6 */ {8,   16, 128, 128, deflate_slow},
/* 7 */ {8,   32, 128, 256, deflate_slow},
/* 8 */ {32, 128, 258, 1024, deflate_slow},
/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */
#endif

/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
 * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
 * meaning.
 */

#define EQUAL 0
/* result of memcmp for equal strings */

#ifndef NO_DUMMY_DECL
struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
#endif

/* ===========================================================================
 * Update a hash value with the given input byte
 * IN  assertion: all calls to to UPDATE_HASH are made with consecutive
 *    input characters, so that a running hash key can be computed from the
 *    previous key instead of complete recalculation each time.
 */
#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask)


/* ===========================================================================
 * Insert string str in the dictionary and set match_head to the previous head
 * of the hash chain (the most recent string with same hash key). Return
 * the previous length of the hash chain.
 * If this file is compiled with -DFASTEST, the compression level is forced
 * to 1, and no hash chains are maintained.
 * IN  assertion: all calls to to INSERT_STRING are made with consecutive
 *    input characters and the first MIN_MATCH bytes of str are valid
 *    (except for the last MIN_MATCH-1 bytes of the input file).
 */
#ifdef FASTEST
#define INSERT_STRING(s, str, match_head) \
   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
    match_head = s->head[s->ins_h], \
    s->head[s->ins_h] = (Pos)(str))
#else
#define INSERT_STRING(s, str, match_head) \
   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
    match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \
    s->head[s->ins_h] = (Pos)(str))
#endif

/* ===========================================================================
 * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
 * prev[] will be initialized on the fly.
 */
#define CLEAR_HASH(s) \
    s->head[s->hash_size-1] = NIL; \
    zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));

/* ========================================================================= */
int ZEXPORT deflateInit_(strm, level, version, stream_size)
    z_streamp strm;
    int level;
    const char *version;
    int stream_size;
{
    return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
                         Z_DEFAULT_STRATEGY, version, stream_size);
    /* To do: ignore strm->next_in if we use it as window */
}

/* ========================================================================= */
int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
                  version, stream_size)
    z_streamp strm;
    int  level;
    int  method;
    int  windowBits;
    int  memLevel;
    int  strategy;
    const char *version;
    int stream_size;
{
    deflate_state *s;
    int wrap = 1;
    static const char my_version[] = ZLIB_VERSION;

    ushf *overlay;
    /* We overlay pending_buf and d_buf+l_buf. This works since the average
     * output size for (length,distance) codes is <= 24 bits.
     */

    if (version == Z_NULL || version[0] != my_version[0] ||
        stream_size != sizeof(z_stream)) {
        return Z_VERSION_ERROR;
    }
    if (strm == Z_NULL) return Z_STREAM_ERROR;

    strm->msg = Z_NULL;
    if (strm->zalloc == (alloc_func)0) {
        strm->zalloc = zcalloc;
        strm->opaque = (voidpf)0;
    }
    if (strm->zfree == (free_func)0) strm->zfree = zcfree;

#ifdef FASTEST
    if (level != 0) level = 1;
#else
    if (level == Z_DEFAULT_COMPRESSION) level = 6;
#endif

    if (windowBits < 0) { /* suppress zlib wrapper */
        wrap = 0;
        windowBits = -windowBits;
    }
#ifdef GZIP
    else if (windowBits > 15) {
        wrap = 2;       /* write gzip wrapper instead */
        windowBits -= 16;
    }
#endif
    if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
        windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
        strategy < 0 || strategy > Z_FIXED) {
        return Z_STREAM_ERROR;
    }
    if (windowBits == 8) windowBits = 9;  /* until 256-byte window bug fixed */
    s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
    if (s == Z_NULL) return Z_MEM_ERROR;
    strm->state = (struct internal_state FAR *)s;
    s->strm = strm;

    s->wrap = wrap;
    s->gzhead = Z_NULL;
    s->w_bits = windowBits;
    s->w_size = 1 << s->w_bits;
    s->w_mask = s->w_size - 1;

    s->hash_bits = memLevel + 7;
    s->hash_size = 1 << s->hash_bits;
    s->hash_mask = s->hash_size - 1;
    s->hash_shift =  ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);

    s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
    s->prev   = (Posf *)  ZALLOC(strm, s->w_size, sizeof(Pos));
    s->head   = (Posf *)  ZALLOC(strm, s->hash_size, sizeof(Pos));

    s->high_water = 0;      /* nothing written to s->window yet */

    s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */

    overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
    s->pending_buf = (uchf *) overlay;
    s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);

    if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
        s->pending_buf == Z_NULL) {
        s->status = FINISH_STATE;
        strm->msg = (char*)ERR_MSG(Z_MEM_ERROR);
        deflateEnd (strm);
        return Z_MEM_ERROR;
    }
    s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
    s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;

    s->level = level;
    s->strategy = strategy;
    s->method = (Byte)method;

    return deflateReset(strm);
}

/* ========================================================================= */
int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
    z_streamp strm;
    const Bytef *dictionary;
    uInt  dictLength;
{
    deflate_state *s;
    uInt length = dictLength;
    uInt n;
    IPos hash_head = 0;

    if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL ||
        strm->state->wrap == 2 ||
        (strm->state->wrap == 1 && strm->state->status != INIT_STATE))
        return Z_STREAM_ERROR;

    s = strm->state;
    if (s->wrap)
        strm->adler = adler32(strm->adler, dictionary, dictLength);

    if (length < MIN_MATCH) return Z_OK;
    if (length > s->w_size) {
        length = s->w_size;
        dictionary += dictLength - length; /* use the tail of the dictionary */
    }
    zmemcpy(s->window, dictionary, length);
    s->strstart = length;
    s->block_start = (long)length;

    /* Insert all strings in the hash table (except for the last two bytes).
     * s->lookahead stays null, so s->ins_h will be recomputed at the next
     * call of fill_window.
     */
    s->ins_h = s->window[0];
    UPDATE_HASH(s, s->ins_h, s->window[1]);
    for (n = 0; n <= length - MIN_MATCH; n++) {
        INSERT_STRING(s, n, hash_head);
    }
    if (hash_head) hash_head = 0;  /* to make compiler happy */
    return Z_OK;
}

/* ========================================================================= */
int ZEXPORT deflateReset (strm)
    z_streamp strm;
{
    deflate_state *s;

    if (strm == Z_NULL || strm->state == Z_NULL ||
        strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) {
        return Z_STREAM_ERROR;
    }

    strm->total_in = strm->total_out = 0;
    strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
    strm->data_type = Z_UNKNOWN;

    s = (deflate_state *)strm->state;
    s->pending = 0;
    s->pending_out = s->pending_buf;

    if (s->wrap < 0) {
        s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */
    }
    s->status = s->wrap ? INIT_STATE : BUSY_STATE;
    strm->adler =
#ifdef GZIP
        s->wrap == 2 ? crc32(0L, Z_NULL, 0) :
#endif
        adler32(0L, Z_NULL, 0);
    s->last_flush = Z_NO_FLUSH;

    _tr_init(s);
    lm_init(s);

    return Z_OK;
}

/* ========================================================================= */
int ZEXPORT deflateSetHeader (strm, head)
    z_streamp strm;
    gz_headerp head;
{
    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
    if (strm->state->wrap != 2) return Z_STREAM_ERROR;
    strm->state->gzhead = head;
    return Z_OK;
}

/* ========================================================================= */
int ZEXPORT deflatePrime (strm, bits, value)
    z_streamp strm;
    int bits;
    int value;
{
    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
    strm->state->bi_valid = bits;
    strm->state->bi_buf = (ush)(value & ((1 << bits) - 1));
    return Z_OK;
}

/* ========================================================================= */
int ZEXPORT deflateParams(strm, level, strategy)
    z_streamp strm;
    int level;
    int strategy;
{
    deflate_state *s;
    compress_func func;
    int err = Z_OK;

    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
    s = strm->state;

#ifdef FASTEST
    if (level != 0) level = 1;
#else
    if (level == Z_DEFAULT_COMPRESSION) level = 6;
#endif
    if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {
        return Z_STREAM_ERROR;
    }
    func = configuration_table[s->level].func;

    if ((strategy != s->strategy || func != configuration_table[level].func) &&
        strm->total_in != 0) {
        /* Flush the last buffer: */
        err = deflate(strm, Z_BLOCK);
    }
    if (s->level != level) {
        s->level = level;
        s->max_lazy_match   = configuration_table[level].max_lazy;
        s->good_match       = configuration_table[level].good_length;
        s->nice_match       = configuration_table[level].nice_length;
        s->max_chain_length = configuration_table[level].max_chain;
    }
    s->strategy = strategy;
    return err;
}

/* ========================================================================= */
int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain)
    z_streamp strm;
    int good_length;
    int max_lazy;
    int nice_length;
    int max_chain;
{
    deflate_state *s;

    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
    s = strm->state;
    s->good_match = good_length;
    s->max_lazy_match = max_lazy;
    s->nice_match = nice_length;
    s->max_chain_length = max_chain;
    return Z_OK;
}

/* =========================================================================
 * For the default windowBits of 15 and memLevel of 8, this function returns
 * a close to exact, as well as small, upper bound on the compressed size.
 * They are coded as constants here for a reason--if the #define's are
 * changed, then this function needs to be changed as well.  The return
 * value for 15 and 8 only works for those exact settings.
 *
 * For any setting other than those defaults for windowBits and memLevel,
 * the value returned is a conservative worst case for the maximum expansion
 * resulting from using fixed blocks instead of stored blocks, which deflate
 * can emit on compressed data for some combinations of the parameters.
 *
 * This function could be more sophisticated to provide closer upper bounds for
 * every combination of windowBits and memLevel.  But even the conservative
 * upper bound of about 14% expansion does not seem onerous for output buffer
 * allocation.
 */
uLong ZEXPORT deflateBound(strm, sourceLen)
    z_streamp strm;
    uLong sourceLen;
{
    deflate_state *s;
    uLong complen, wraplen;
    Bytef *str;

    /* conservative upper bound for compressed data */
    complen = sourceLen +
              ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5;

    /* if can't get parameters, return conservative bound plus zlib wrapper */
    if (strm == Z_NULL || strm->state == Z_NULL)
        return complen + 6;

    /* compute wrapper length */
    s = strm->state;
    switch (s->wrap) {
    case 0:                                 /* raw deflate */
        wraplen = 0;
        break;
    case 1:                                 /* zlib wrapper */
        wraplen = 6 + (s->strstart ? 4 : 0);
        break;
    case 2:                                 /* gzip wrapper */
        wraplen = 18;
        if (s->gzhead != Z_NULL) {          /* user-supplied gzip header */
            if (s->gzhead->extra != Z_NULL)
                wraplen += 2 + s->gzhead->extra_len;
            str = s->gzhead->name;
            if (str != Z_NULL)
                do {
                    wraplen++;
                } while (*str++);
            str = s->gzhead->comment;
            if (str != Z_NULL)
                do {
                    wraplen++;
                } while (*str++);
            if (s->gzhead->hcrc)
                wraplen += 2;
        }
        break;
    default:                                /* for compiler happiness */
        wraplen = 6;
    }

    /* if not default parameters, return conservative bound */
    if (s->w_bits != 15 || s->hash_bits != 8 + 7)
        return complen + wraplen;

    /* default settings: return tight bound for that case */
    return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
           (sourceLen >> 25) + 13 - 6 + wraplen;
}

/* =========================================================================
 * Put a short in the pending buffer. The 16-bit value is put in MSB order.
 * IN assertion: the stream state is correct and there is enough room in
 * pending_buf.
 */
local void putShortMSB (s, b)
    deflate_state *s;
    uInt b;
{
    put_byte(s, (Byte)(b >> 8));
    put_byte(s, (Byte)(b & 0xff));
}

/* =========================================================================
 * Flush as much pending output as possible. All deflate() output goes
 * through this function so some applications may wish to modify it
 * to avoid allocating a large strm->next_out buffer and copying into it.
 * (See also read_buf()).
 */
local void flush_pending(strm)
    z_streamp strm;
{
    unsigned len = strm->state->pending;

    if (len > strm->avail_out) len = strm->avail_out;
    if (len == 0) return;

    zmemcpy(strm->next_out, strm->state->pending_out, len);
    strm->next_out  += len;
    strm->state->pending_out  += len;
    strm->total_out += len;
    strm->avail_out  -= len;
    strm->state->pending -= len;
    if (strm->state->pending == 0) {
        strm->state->pending_out = strm->state->pending_buf;
    }
}

/* ========================================================================= */
int ZEXPORT deflate (strm, flush)
    z_streamp strm;
    int flush;
{
    int old_flush; /* value of flush param for previous deflate call */
    deflate_state *s;

    if (strm == Z_NULL || strm->state == Z_NULL ||
        flush > Z_BLOCK || flush < 0) {
        return Z_STREAM_ERROR;
    }
    s = strm->state;

    if (strm->next_out == Z_NULL ||
        (strm->next_in == Z_NULL && strm->avail_in != 0) ||
        (s->status == FINISH_STATE && flush != Z_FINISH)) {
        ERR_RETURN(strm, Z_STREAM_ERROR);
    }
    if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);

    s->strm = strm; /* just in case */
    old_flush = s->last_flush;
    s->last_flush = flush;

    /* Write the header */
    if (s->status == INIT_STATE) {
#ifdef GZIP
        if (s->wrap == 2) {
            strm->adler = crc32(0L, Z_NULL, 0);
            put_byte(s, 31);
            put_byte(s, 139);
            put_byte(s, 8);
            if (s->gzhead == Z_NULL) {
                put_byte(s, 0);
                put_byte(s, 0);
                put_byte(s, 0);
                put_byte(s, 0);
                put_byte(s, 0);
                put_byte(s, s->level == 9 ? 2 :
                            (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
                             4 : 0));
                put_byte(s, OS_CODE);
                s->status = BUSY_STATE;
            }
            else {
                put_byte(s, (s->gzhead->text ? 1 : 0) +
                            (s->gzhead->hcrc ? 2 : 0) +
                            (s->gzhead->extra == Z_NULL ? 0 : 4) +
                            (s->gzhead->name == Z_NULL ? 0 : 8) +
                            (s->gzhead->comment == Z_NULL ? 0 : 16)
                        );
                put_byte(s, (Byte)(s->gzhead->time & 0xff));
                put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff));
                put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff));
                put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff));
                put_byte(s, s->level == 9 ? 2 :
                            (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
                             4 : 0));
                put_byte(s, s->gzhead->os & 0xff);
                if (s->gzhead->extra != Z_NULL) {
                    put_byte(s, s->gzhead->extra_len & 0xff);
                    put_byte(s, (s->gzhead->extra_len >> 8) & 0xff);
                }
                if (s->gzhead->hcrc)
                    strm->adler = crc32(strm->adler, s->pending_buf,
                                        s->pending);
                s->gzindex = 0;
                s->status = EXTRA_STATE;
            }
        }
        else
#endif
        {
            uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
            uInt level_flags;

            if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2)
                level_flags = 0;
            else if (s->level < 6)
                level_flags = 1;
            else if (s->level == 6)
                level_flags = 2;
            else
                level_flags = 3;
            header |= (level_flags << 6);
            if (s->strstart != 0) header |= PRESET_DICT;
            header += 31 - (header % 31);

            s->status = BUSY_STATE;
            putShortMSB(s, header);

            /* Save the adler32 of the preset dictionary: */
            if (s->strstart != 0) {
                putShortMSB(s, (uInt)(strm->adler >> 16));
                putShortMSB(s, (uInt)(strm->adler & 0xffff));
            }
            strm->adler = adler32(0L, Z_NULL, 0);
        }
    }
#ifdef GZIP
    if (s->status == EXTRA_STATE) {
        if (s->gzhead->extra != Z_NULL) {
            uInt beg = s->pending;  /* start of bytes to update crc */

            while (s->gzindex < (s->gzhead->extra_len & 0xffff)) {
                if (s->pending == s->pending_buf_size) {
                    if (s->gzhead->hcrc && s->pending > beg)
                        strm->adler = crc32(strm->adler, s->pending_buf + beg,
                                            s->pending - beg);
                    flush_pending(strm);
                    beg = s->pending;
                    if (s->pending == s->pending_buf_size)
                        break;
                }
                put_byte(s, s->gzhead->extra[s->gzindex]);
                s->gzindex++;
            }
            if (s->gzhead->hcrc && s->pending > beg)
                strm->adler = crc32(strm->adler, s->pending_buf + beg,
                                    s->pending - beg);
            if (s->gzindex == s->gzhead->extra_len) {
                s->gzindex = 0;
                s->status = NAME_STATE;
            }
        }
        else
            s->status = NAME_STATE;
    }
    if (s->status == NAME_STATE) {
        if (s->gzhead->name != Z_NULL) {
            uInt beg = s->pending;  /* start of bytes to update crc */
            int val;

            do {
                if (s->pending == s->pending_buf_size) {
                    if (s->gzhead->hcrc && s->pending > beg)
                        strm->adler = crc32(strm->adler, s->pending_buf + beg,
                                            s->pending - beg);
                    flush_pending(strm);
                    beg = s->pending;
                    if (s->pending == s->pending_buf_size) {
                        val = 1;
                        break;
                    }
                }
                val = s->gzhead->name[s->gzindex++];
                put_byte(s, val);
            } while (val != 0);
            if (s->gzhead->hcrc && s->pending > beg)
                strm->adler = crc32(strm->adler, s->pending_buf + beg,
                                    s->pending - beg);
            if (val == 0) {
                s->gzindex = 0;
                s->status = COMMENT_STATE;
            }
        }
        else
            s->status = COMMENT_STATE;
    }
    if (s->status == COMMENT_STATE) {
        if (s->gzhead->comment != Z_NULL) {
            uInt beg = s->pending;  /* start of bytes to update crc */
            int val;

            do {
                if (s->pending == s->pending_buf_size) {
                    if (s->gzhead->hcrc && s->pending > beg)
                        strm->adler = crc32(strm->adler, s->pending_buf + beg,
                                            s->pending - beg);
                    flush_pending(strm);
                    beg = s->pending;
                    if (s->pending == s->pending_buf_size) {
                        val = 1;
                        break;
                    }
                }
                val = s->gzhead->comment[s->gzindex++];
                put_byte(s, val);
            } while (val != 0);
            if (s->gzhead->hcrc && s->pending > beg)
                strm->adler = crc32(strm->adler, s->pending_buf + beg,
                                    s->pending - beg);
            if (val == 0)
                s->status = HCRC_STATE;
        }
        else
            s->status = HCRC_STATE;
    }
    if (s->status == HCRC_STATE) {
        if (s->gzhead->hcrc) {
            if (s->pending + 2 > s->pending_buf_size)
                flush_pending(strm);
            if (s->pending + 2 <= s->pending_buf_size) {
                put_byte(s, (Byte)(strm->adler & 0xff));
                put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
                strm->adler = crc32(0L, Z_NULL, 0);
                s->status = BUSY_STATE;
            }
        }
        else
            s->status = BUSY_STATE;
    }
#endif

    /* Flush as much pending output as possible */
    if (s->pending != 0) {
        flush_pending(strm);
        if (strm->avail_out == 0) {
            /* Since avail_out is 0, deflate will be called again with
             * more output space, but possibly with both pending and
             * avail_in equal to zero. There won't be anything to do,
             * but this is not an error situation so make sure we
             * return OK instead of BUF_ERROR at next call of deflate:
             */
            s->last_flush = -1;
            return Z_OK;
        }

    /* Make sure there is something to do and avoid duplicate consecutive
     * flushes. For repeated and useless calls with Z_FINISH, we keep
     * returning Z_STREAM_END instead of Z_BUF_ERROR.
     */
    } else if (strm->avail_in == 0 && flush <= old_flush &&
               flush != Z_FINISH) {
        ERR_RETURN(strm, Z_BUF_ERROR);
    }

    /* User must not provide more input after the first FINISH: */
    if (s->status == FINISH_STATE && strm->avail_in != 0) {
        ERR_RETURN(strm, Z_BUF_ERROR);
    }

    /* Start a new block or continue the current one.
     */
    if (strm->avail_in != 0 || s->lookahead != 0 ||
        (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
        block_state bstate;

        bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) :
                    (s->strategy == Z_RLE ? deflate_rle(s, flush) :
                        (*(configuration_table[s->level].func))(s, flush));

        if (bstate == finish_started || bstate == finish_done) {
            s->status = FINISH_STATE;
        }
        if (bstate == need_more || bstate == finish_started) {
            if (strm->avail_out == 0) {
                s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
            }
            return Z_OK;
            /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
             * of deflate should use the same flush parameter to make sure
             * that the flush is complete. So we don't have to output an
             * empty block here, this will be done at next call. This also
             * ensures that for a very small output buffer, we emit at most
             * one empty block.
             */
        }
        if (bstate == block_done) {
            if (flush == Z_PARTIAL_FLUSH) {
                _tr_align(s);
            } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */
                _tr_stored_block(s, (char*)0, 0L, 0);
                /* For a full flush, this empty block will be recognized
                 * as a special marker by inflate_sync().
                 */
                if (flush == Z_FULL_FLUSH) {
                    CLEAR_HASH(s);             /* forget history */
                    if (s->lookahead == 0) {
                        s->strstart = 0;
                        s->block_start = 0L;
                    }
                }
            }
            flush_pending(strm);
            if (strm->avail_out == 0) {
              s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
              return Z_OK;
            }
        }
    }
    Assert(strm->avail_out > 0, "bug2");

    if (flush != Z_FINISH) return Z_OK;
    if (s->wrap <= 0) return Z_STREAM_END;

    /* Write the trailer */
#ifdef GZIP
    if (s->wrap == 2) {
        put_byte(s, (Byte)(strm->adler & 0xff));
        put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
        put_byte(s, (Byte)((strm->adler >> 16) & 0xff));
        put_byte(s, (Byte)((strm->adler >> 24) & 0xff));
        put_byte(s, (Byte)(strm->total_in & 0xff));
        put_byte(s, (Byte)((strm->total_in >> 8) & 0xff));
        put_byte(s, (Byte)((strm->total_in >> 16) & 0xff));
        put_byte(s, (Byte)((strm->total_in >> 24) & 0xff));
    }
    else
#endif
    {
        putShortMSB(s, (uInt)(strm->adler >> 16));
        putShortMSB(s, (uInt)(strm->adler & 0xffff));
    }
    flush_pending(strm);
    /* If avail_out is zero, the application will call deflate again
     * to flush the rest.
     */
    if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */
    return s->pending != 0 ? Z_OK : Z_STREAM_END;
}

/* ========================================================================= */
int ZEXPORT deflateEnd (strm)
    z_streamp strm;
{
    int status;

    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;

    status = strm->state->status;
    if (status != INIT_STATE &&
        status != EXTRA_STATE &&
        status != NAME_STATE &&
        status != COMMENT_STATE &&
        status != HCRC_STATE &&
        status != BUSY_STATE &&
        status != FINISH_STATE) {
      return Z_STREAM_ERROR;
    }

    /* Deallocate in reverse order of allocations: */
    TRY_FREE(strm, strm->state->pending_buf);
    TRY_FREE(strm, strm->state->head);
    TRY_FREE(strm, strm->state->prev);
    TRY_FREE(strm, strm->state->window);

    ZFREE(strm, strm->state);
    strm->state = Z_NULL;

    return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
}

/* =========================================================================
 * Copy the source state to the destination state.
 * To simplify the source, this is not supported for 16-bit MSDOS (which
 * doesn't have enough memory anyway to duplicate compression states).
 */
int ZEXPORT deflateCopy (dest, source)
    z_streamp dest;
    z_streamp source;
{
#ifdef MAXSEG_64K
    return Z_STREAM_ERROR;
#else
    deflate_state *ds;
    deflate_state *ss;
    ushf *overlay;


    if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) {
        return Z_STREAM_ERROR;
    }

    ss = source->state;

    zmemcpy(dest, source, sizeof(z_stream));

    ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
    if (ds == Z_NULL) return Z_MEM_ERROR;
    dest->state = (struct internal_state FAR *) ds;
    zmemcpy(ds, ss, sizeof(deflate_state));
    ds->strm = dest;

    ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
    ds->prev   = (Posf *)  ZALLOC(dest, ds->w_size, sizeof(Pos));
    ds->head   = (Posf *)  ZALLOC(dest, ds->hash_size, sizeof(Pos));
    overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
    ds->pending_buf = (uchf *) overlay;

    if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
        ds->pending_buf == Z_NULL) {
        deflateEnd (dest);
        return Z_MEM_ERROR;
    }
    /* following zmemcpy do not work for 16-bit MSDOS */
    zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
    zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos));
    zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos));
    zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);

    ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
    ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
    ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;

    ds->l_desc.dyn_tree = ds->dyn_ltree;
    ds->d_desc.dyn_tree = ds->dyn_dtree;
    ds->bl_desc.dyn_tree = ds->bl_tree;

    return Z_OK;
#endif /* MAXSEG_64K */
}

/* ===========================================================================
 * Read a new buffer from the current input stream, update the adler32
 * and total number of bytes read.  All deflate() input goes through
 * this function so some applications may wish to modify it to avoid
 * allocating a large strm->next_in buffer and copying from it.
 * (See also flush_pending()).
 */
local int read_buf(strm, buf, size)
    z_streamp strm;
    Bytef *buf;
    unsigned size;
{
    unsigned len = strm->avail_in;

    if (len > size) len = size;
    if (len == 0) return 0;

    strm->avail_in  -= len;

    if (strm->state->wrap == 1) {
        strm->adler = adler32(strm->adler, strm->next_in, len);
    }
#ifdef GZIP
    else if (strm->state->wrap == 2) {
        strm->adler = crc32(strm->adler, strm->next_in, len);
    }
#endif
    zmemcpy(buf, strm->next_in, len);
    strm->next_in  += len;
    strm->total_in += len;

    return (int)len;
}

/* ===========================================================================
 * Initialize the "longest match" routines for a new zlib stream
 */
local void lm_init (s)
    deflate_state *s;
{
    s->window_size = (ulg)2L*s->w_size;

    CLEAR_HASH(s);

    /* Set the default configuration parameters:
     */
    s->max_lazy_match   = configuration_table[s->level].max_lazy;
    s->good_match       = configuration_table[s->level].good_length;
    s->nice_match       = configuration_table[s->level].nice_length;
    s->max_chain_length = configuration_table[s->level].max_chain;

    s->strstart = 0;
    s->block_start = 0L;
    s->lookahead = 0;
    s->match_length = s->prev_length = MIN_MATCH-1;
    s->match_available = 0;
    s->ins_h = 0;
#ifndef FASTEST
#ifdef ASMV
    match_init(); /* initialize the asm code */
#endif
#endif
}

#ifndef FASTEST
/* ===========================================================================
 * Set match_start to the longest match starting at the given string and
 * return its length. Matches shorter or equal to prev_length are discarded,
 * in which case the result is equal to prev_length and match_start is
 * garbage.
 * IN assertions: cur_match is the head of the hash chain for the current
 *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
 * OUT assertion: the match length is not greater than s->lookahead.
 */
#ifndef ASMV
/* For 80x86 and 680x0, an optimized version will be provided in match.asm or
 * match.S. The code will be functionally equivalent.
 */
local uInt longest_match(s, cur_match)
    deflate_state *s;
    IPos cur_match;                             /* current match */
{
    unsigned chain_length = s->max_chain_length;/* max hash chain length */
    register Bytef *scan = s->window + s->strstart; /* current string */
    register Bytef *match;                       /* matched string */
    register int len;                           /* length of current match */
    int best_len = s->prev_length;              /* best match length so far */
    int nice_match = s->nice_match;             /* stop if match long enough */
    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
        s->strstart - (IPos)MAX_DIST(s) : NIL;
    /* Stop when cur_match becomes <= limit. To simplify the code,
     * we prevent matches with the string of window index 0.
     */
    Posf *prev = s->prev;
    uInt wmask = s->w_mask;

#ifdef UNALIGNED_OK
    /* Compare two bytes at a time. Note: this is not always beneficial.
     * Try with and without -DUNALIGNED_OK to check.
     */
    register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
    register ush scan_start = *(ushf*)scan;
    register ush scan_end   = *(ushf*)(scan+best_len-1);
#else
    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
    register Byte scan_end1  = scan[best_len-1];
    register Byte scan_end   = scan[best_len];
#endif

    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
     * It is easy to get rid of this optimization if necessary.
     */
    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");

    /* Do not waste too much time if we already have a good match: */
    if (s->prev_length >= s->good_match) {
        chain_length >>= 2;
    }
    /* Do not look for matches beyond the end of the input. This is necessary
     * to make deflate deterministic.
     */
    if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;

    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");

    do {
        Assert(cur_match < s->strstart, "no future");
        match = s->window + cur_match;

        /* Skip to next match if the match length cannot increase
         * or if the match length is less than 2.  Note that the checks below
         * for insufficient lookahead only occur occasionally for performance
         * reasons.  Therefore uninitialized memory will be accessed, and
         * conditional jumps will be made that depend on those values.
         * However the length of the match is limited to the lookahead, so
         * the output of deflate is not affected by the uninitialized values.
         */
#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
        /* This code assumes sizeof(unsigned short) == 2. Do not use
         * UNALIGNED_OK if your compiler uses a different size.
         */
        if (*(ushf*)(match+best_len-1) != scan_end ||
            *(ushf*)match != scan_start) continue;

        /* It is not necessary to compare scan[2] and match[2] since they are
         * always equal when the other bytes match, given that the hash keys
         * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
         * strstart+3, +5, ... up to strstart+257. We check for insufficient
         * lookahead only every 4th comparison; the 128th check will be made
         * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
         * necessary to put more guard bytes at the end of the window, or
         * to check more often for insufficient lookahead.
         */
        Assert(scan[2] == match[2], "scan[2]?");
        scan++, match++;
        do {
        } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
                 scan < strend);
        /* The funny "do {}" generates better code on most compilers */

        /* Here, scan <= window+strstart+257 */
        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
        if (*scan == *match) scan++;

        len = (MAX_MATCH - 1) - (int)(strend-scan);
        scan = strend - (MAX_MATCH-1);

#else /* UNALIGNED_OK */

        if (match[best_len]   != scan_end  ||
            match[best_len-1] != scan_end1 ||
            *match            != *scan     ||
            *++match          != scan[1])      continue;

        /* The check at best_len-1 can be removed because it will be made
         * again later. (This heuristic is not always a win.)
         * It is not necessary to compare scan[2] and match[2] since they
         * are always equal when the other bytes match, given that
         * the hash keys are equal and that HASH_BITS >= 8.
         */
        scan += 2, match++;
        Assert(*scan == *match, "match[2]?");

        /* We check for insufficient lookahead only every 8th comparison;
         * the 256th check will be made at strstart+258.
         */
        do {
        } while (*++scan == *++match && *++scan == *++match &&
                 *++scan == *++match && *++scan == *++match &&
                 *++scan == *++match && *++scan == *++match &&
                 *++scan == *++match && *++scan == *++match &&
                 scan < strend);

        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");

        len = MAX_MATCH - (int)(strend - scan);
        scan = strend - MAX_MATCH;

#endif /* UNALIGNED_OK */

        if (len > best_len) {
            s->match_start = cur_match;
            best_len = len;
            if (len >= nice_match) break;
#ifdef UNALIGNED_OK
            scan_end = *(ushf*)(scan+best_len-1);
#else
            scan_end1  = scan[best_len-1];
            scan_end   = scan[best_len];
#endif
        }
    } while ((cur_match = prev[cur_match & wmask]) > limit
             && --chain_length != 0);

    if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
    return s->lookahead;
}
#endif /* ASMV */

#else /* FASTEST */

/* ---------------------------------------------------------------------------
 * Optimized version for FASTEST only
 */
local uInt longest_match(s, cur_match)
    deflate_state *s;
    IPos cur_match;                             /* current match */
{
    register Bytef *scan = s->window + s->strstart; /* current string */
    register Bytef *match;                       /* matched string */
    register int len;                           /* length of current match */
    register Bytef *strend = s->window + s->strstart + MAX_MATCH;

    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
     * It is easy to get rid of this optimization if necessary.
     */
    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");

    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");

    Assert(cur_match < s->strstart, "no future");

    match = s->window + cur_match;

    /* Return failure if the match length is less than 2:
     */
    if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;

    /* The check at best_len-1 can be removed because it will be made
     * again later. (This heuristic is not always a win.)
     * It is not necessary to compare scan[2] and match[2] since they
     * are always equal when the other bytes match, given that
     * the hash keys are equal and that HASH_BITS >= 8.
     */
    scan += 2, match += 2;
    Assert(*scan == *match, "match[2]?");

    /* We check for insufficient lookahead only every 8th comparison;
     * the 256th check will be made at strstart+258.
     */
    do {
    } while (*++scan == *++match && *++scan == *++match &&
             *++scan == *++match && *++scan == *++match &&
             *++scan == *++match && *++scan == *++match &&
             *++scan == *++match && *++scan == *++match &&
             scan < strend);

    Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");

    len = MAX_MATCH - (int)(strend - scan);

    if (len < MIN_MATCH) return MIN_MATCH - 1;

    s->match_start = cur_match;
    return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead;
}

#endif /* FASTEST */

#ifdef DEBUG
/* ===========================================================================
 * Check that the match at match_start is indeed a match.
 */
local void check_match(s, start, match, length)
    deflate_state *s;
    IPos start, match;
    int length;
{
    /* check that the match is indeed a match */
    if (zmemcmp(s->window + match,
                s->window + start, length) != EQUAL) {
        fprintf(stderr, " start %u, match %u, length %d\n",
                start, match, length);
        do {
            fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
        } while (--length != 0);
        z_error("invalid match");
    }
    if (z_verbose > 1) {
        fprintf(stderr,"\\[%d,%d]", start-match, length);
        do { putc(s->window[start++], stderr); } while (--length != 0);
    }
}
#else
#  define check_match(s, start, match, length)
#endif /* DEBUG */

/* ===========================================================================
 * Fill the window when the lookahead becomes insufficient.
 * Updates strstart and lookahead.
 *
 * IN assertion: lookahead < MIN_LOOKAHEAD
 * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
 *    At least one byte has been read, or avail_in == 0; reads are
 *    performed for at least two bytes (required for the zip translate_eol
 *    option -- not supported here).
 */
local void fill_window(s)
    deflate_state *s;
{
    register unsigned n, m;
    register Posf *p;
    unsigned more;    /* Amount of free space at the end of the window. */
    uInt wsize = s->w_size;

    do {
        more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);

        /* Deal with !@#$% 64K limit: */
        if (sizeof(int) <= 2) {
            if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
                more = wsize;

            } else if (more == (unsigned)(-1)) {
                /* Very unlikely, but possible on 16 bit machine if
                 * strstart == 0 && lookahead == 1 (input done a byte at time)
                 */
                more--;
            }
        }

        /* If the window is almost full and there is insufficient lookahead,
         * move the upper half to the lower one to make room in the upper half.
         */
        if (s->strstart >= wsize+MAX_DIST(s)) {

            zmemcpy(s->window, s->window+wsize, (unsigned)wsize);
            s->match_start -= wsize;
            s->strstart    -= wsize; /* we now have strstart >= MAX_DIST */
            s->block_start -= (long) wsize;

            /* Slide the hash table (could be avoided with 32 bit values
               at the expense of memory usage). We slide even when level == 0
               to keep the hash table consistent if we switch back to level > 0
               later. (Using level 0 permanently is not an optimal usage of
               zlib, so we don't care about this pathological case.)
             */
            n = s->hash_size;
            p = &s->head[n];
            do {
                m = *--p;
                *p = (Pos)(m >= wsize ? m-wsize : NIL);
            } while (--n);

            n = wsize;
#ifndef FASTEST
            p = &s->prev[n];
            do {
                m = *--p;
                *p = (Pos)(m >= wsize ? m-wsize : NIL);
                /* If n is not on any hash chain, prev[n] is garbage but
                 * its value will never be used.
                 */
            } while (--n);
#endif
            more += wsize;
        }
        if (s->strm->avail_in == 0) return;

        /* If there was no sliding:
         *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
         *    more == window_size - lookahead - strstart
         * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
         * => more >= window_size - 2*WSIZE + 2
         * In the BIG_MEM or MMAP case (not yet supported),
         *   window_size == input_size + MIN_LOOKAHEAD  &&
         *   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
         * Otherwise, window_size == 2*WSIZE so more >= 2.
         * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
         */
        Assert(more >= 2, "more < 2");

        n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
        s->lookahead += n;

        /* Initialize the hash value now that we have some input: */
        if (s->lookahead >= MIN_MATCH) {
            s->ins_h = s->window[s->strstart];
            UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
#if MIN_MATCH != 3
            Call UPDATE_HASH() MIN_MATCH-3 more times
#endif
        }
        /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
         * but this is not important since only literal bytes will be emitted.
         */

    } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);

    /* If the WIN_INIT bytes after the end of the current data have never been
     * written, then zero those bytes in order to avoid memory check reports of
     * the use of uninitialized (or uninitialised as Julian writes) bytes by
     * the longest match routines.  Update the high water mark for the next
     * time through here.  WIN_INIT is set to MAX_MATCH since the longest match
     * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
     */
    if (s->high_water < s->window_size) {
        ulg curr = s->strstart + (ulg)(s->lookahead);
        ulg init;

        if (s->high_water < curr) {
            /* Previous high water mark below current data -- zero WIN_INIT
             * bytes or up to end of window, whichever is less.
             */
            init = s->window_size - curr;
            if (init > WIN_INIT)
                init = WIN_INIT;
            zmemzero(s->window + curr, (unsigned)init);
            s->high_water = curr + init;
        }
        else if (s->high_water < (ulg)curr + WIN_INIT) {
            /* High water mark at or above current data, but below current data
             * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
             * to end of window, whichever is less.
             */
            init = (ulg)curr + WIN_INIT - s->high_water;
            if (init > s->window_size - s->high_water)
                init = s->window_size - s->high_water;
            zmemzero(s->window + s->high_water, (unsigned)init);
            s->high_water += init;
        }
    }
}

/* ===========================================================================
 * Flush the current block, with given end-of-file flag.
 * IN assertion: strstart is set to the end of the current match.
 */
#define FLUSH_BLOCK_ONLY(s, last) { \
   _tr_flush_block(s, (s->block_start >= 0L ? \
                   (charf *)&s->window[(unsigned)s->block_start] : \
                   (charf *)Z_NULL), \
                (ulg)((long)s->strstart - s->block_start), \
                (last)); \
   s->block_start = s->strstart; \
   flush_pending(s->strm); \
   Tracev((stderr,"[FLUSH]")); \
}

/* Same but force premature exit if necessary. */
#define FLUSH_BLOCK(s, last) { \
   FLUSH_BLOCK_ONLY(s, last); \
   if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \
}

/* ===========================================================================
 * Copy without compression as much as possible from the input stream, return
 * the current block state.
 * This function does not insert new strings in the dictionary since
 * uncompressible data is probably not useful. This function is used
 * only for the level=0 compression option.
 * NOTE: this function should be optimized to avoid extra copying from
 * window to pending_buf.
 */
local block_state deflate_stored(s, flush)
    deflate_state *s;
    int flush;
{
    /* Stored blocks are limited to 0xffff bytes, pending_buf is limited
     * to pending_buf_size, and each stored block has a 5 byte header:
     */
    ulg max_block_size = 0xffff;
    ulg max_start;

    if (max_block_size > s->pending_buf_size - 5) {
        max_block_size = s->pending_buf_size - 5;
    }

    /* Copy as much as possible from input to output: */
    for (;;) {
        /* Fill the window as much as possible: */
        if (s->lookahead <= 1) {

            Assert(s->strstart < s->w_size+MAX_DIST(s) ||
                   s->block_start >= (long)s->w_size, "slide too late");

            fill_window(s);
            if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more;

            if (s->lookahead == 0) break; /* flush the current block */
        }
        Assert(s->block_start >= 0L, "block gone");

        s->strstart += s->lookahead;
        s->lookahead = 0;

        /* Emit a stored block if pending_buf will be full: */
        max_start = s->block_start + max_block_size;
        if (s->strstart == 0 || (ulg)s->strstart >= max_start) {
            /* strstart == 0 is possible when wraparound on 16-bit machine */
            s->lookahead = (uInt)(s->strstart - max_start);
            s->strstart = (uInt)max_start;
            FLUSH_BLOCK(s, 0);
        }
        /* Flush if we may have to slide, otherwise block_start may become
         * negative and the data will be gone:
         */
        if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) {
            FLUSH_BLOCK(s, 0);
        }
    }
    FLUSH_BLOCK(s, flush == Z_FINISH);
    return flush == Z_FINISH ? finish_done : block_done;
}

/* ===========================================================================
 * Compress as much as possible from the input stream, return the current
 * block state.
 * This function does not perform lazy evaluation of matches and inserts
 * new strings in the dictionary only for unmatched strings or for short
 * matches. It is used only for the fast compression options.
 */
local block_state deflate_fast(s, flush)
    deflate_state *s;
    int flush;
{
    IPos hash_head;       /* head of the hash chain */
    int bflush;           /* set if current block must be flushed */

    for (;;) {
        /* Make sure that we always have enough lookahead, except
         * at the end of the input file. We need MAX_MATCH bytes
         * for the next match, plus MIN_MATCH bytes to insert the
         * string following the next match.
         */
        if (s->lookahead < MIN_LOOKAHEAD) {
            fill_window(s);
            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
                return need_more;
            }
            if (s->lookahead == 0) break; /* flush the current block */
        }

        /* Insert the string window[strstart .. strstart+2] in the
         * dictionary, and set hash_head to the head of the hash chain:
         */
        hash_head = NIL;
        if (s->lookahead >= MIN_MATCH) {
            INSERT_STRING(s, s->strstart, hash_head);
        }

        /* Find the longest match, discarding those <= prev_length.
         * At this point we have always match_length < MIN_MATCH
         */
        if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
            /* To simplify the code, we prevent matches with the string
             * of window index 0 (in particular we have to avoid a match
             * of the string with itself at the start of the input file).
             */
            s->match_length = longest_match (s, hash_head);
            /* longest_match() sets match_start */
        }
        if (s->match_length >= MIN_MATCH) {
            check_match(s, s->strstart, s->match_start, s->match_length);

            _tr_tally_dist(s, s->strstart - s->match_start,
                           s->match_length - MIN_MATCH, bflush);

            s->lookahead -= s->match_length;

            /* Insert new strings in the hash table only if the match length
             * is not too large. This saves time but degrades compression.
             */
#ifndef FASTEST
            if (s->match_length <= s->max_insert_length &&
                s->lookahead >= MIN_MATCH) {
                s->match_length--; /* string at strstart already in table */
                do {
                    s->strstart++;
                    INSERT_STRING(s, s->strstart, hash_head);
                    /* strstart never exceeds WSIZE-MAX_MATCH, so there are
                     * always MIN_MATCH bytes ahead.
                     */
                } while (--s->match_length != 0);
                s->strstart++;
            } else
#endif
            {
                s->strstart += s->match_length;
                s->match_length = 0;
                s->ins_h = s->window[s->strstart];
                UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
#if MIN_MATCH != 3
                Call UPDATE_HASH() MIN_MATCH-3 more times
#endif
                /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
                 * matter since it will be recomputed at next deflate call.
                 */
            }
        } else {
            /* No match, output a literal byte */
            Tracevv((stderr,"%c", s->window[s->strstart]));
            _tr_tally_lit (s, s->window[s->strstart], bflush);
            s->lookahead--;
            s->strstart++;
        }
        if (bflush) FLUSH_BLOCK(s, 0);
    }
    FLUSH_BLOCK(s, flush == Z_FINISH);
    return flush == Z_FINISH ? finish_done : block_done;
}

#ifndef FASTEST
/* ===========================================================================
 * Same as above, but achieves better compression. We use a lazy
 * evaluation for matches: a match is finally adopted only if there is
 * no better match at the next window position.
 */
local block_state deflate_slow(s, flush)
    deflate_state *s;
    int flush;
{
    IPos hash_head;          /* head of hash chain */
    int bflush;              /* set if current block must be flushed */

    /* Process the input block. */
    for (;;) {
        /* Make sure that we always have enough lookahead, except
         * at the end of the input file. We need MAX_MATCH bytes
         * for the next match, plus MIN_MATCH bytes to insert the
         * string following the next match.
         */
        if (s->lookahead < MIN_LOOKAHEAD) {
            fill_window(s);
            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
                return need_more;
            }
            if (s->lookahead == 0) break; /* flush the current block */
        }

        /* Insert the string window[strstart .. strstart+2] in the
         * dictionary, and set hash_head to the head of the hash chain:
         */
        hash_head = NIL;
        if (s->lookahead >= MIN_MATCH) {
            INSERT_STRING(s, s->strstart, hash_head);
        }

        /* Find the longest match, discarding those <= prev_length.
         */
        s->prev_length = s->match_length, s->prev_match = s->match_start;
        s->match_length = MIN_MATCH-1;

        if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
            s->strstart - hash_head <= MAX_DIST(s)) {
            /* To simplify the code, we prevent matches with the string
             * of window index 0 (in particular we have to avoid a match
             * of the string with itself at the start of the input file).
             */
            s->match_length = longest_match (s, hash_head);
            /* longest_match() sets match_start */

            if (s->match_length <= 5 && (s->strategy == Z_FILTERED
#if TOO_FAR <= 32767
                || (s->match_length == MIN_MATCH &&
                    s->strstart - s->match_start > TOO_FAR)
#endif
                )) {

                /* If prev_match is also MIN_MATCH, match_start is garbage
                 * but we will ignore the current match anyway.
                 */
                s->match_length = MIN_MATCH-1;
            }
        }
        /* If there was a match at the previous step and the current
         * match is not better, output the previous match:
         */
        if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
            uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
            /* Do not insert strings in hash table beyond this. */

            check_match(s, s->strstart-1, s->prev_match, s->prev_length);

            _tr_tally_dist(s, s->strstart -1 - s->prev_match,
                           s->prev_length - MIN_MATCH, bflush);

            /* Insert in hash table all strings up to the end of the match.
             * strstart-1 and strstart are already inserted. If there is not
             * enough lookahead, the last two strings are not inserted in
             * the hash table.
             */
            s->lookahead -= s->prev_length-1;
            s->prev_length -= 2;
            do {
                if (++s->strstart <= max_insert) {
                    INSERT_STRING(s, s->strstart, hash_head);
                }
            } while (--s->prev_length != 0);
            s->match_available = 0;
            s->match_length = MIN_MATCH-1;
            s->strstart++;

            if (bflush) FLUSH_BLOCK(s, 0);

        } else if (s->match_available) {
            /* If there was no match at the previous position, output a
             * single literal. If there was a match but the current match
             * is longer, truncate the previous match to a single literal.
             */
            Tracevv((stderr,"%c", s->window[s->strstart-1]));
            _tr_tally_lit(s, s->window[s->strstart-1], bflush);
            if (bflush) {
                FLUSH_BLOCK_ONLY(s, 0);
            }
            s->strstart++;
            s->lookahead--;
            if (s->strm->avail_out == 0) return need_more;
        } else {
            /* There is no previous match to compare with, wait for
             * the next step to decide.
             */
            s->match_available = 1;
            s->strstart++;
            s->lookahead--;
        }
    }
    Assert (flush != Z_NO_FLUSH, "no flush?");
    if (s->match_available) {
        Tracevv((stderr,"%c", s->window[s->strstart-1]));
        _tr_tally_lit(s, s->window[s->strstart-1], bflush);
        s->match_available = 0;
    }
    FLUSH_BLOCK(s, flush == Z_FINISH);
    return flush == Z_FINISH ? finish_done : block_done;
}
#endif /* FASTEST */

/* ===========================================================================
 * For Z_RLE, simply look for runs of bytes, generate matches only of distance
 * one.  Do not maintain a hash table.  (It will be regenerated if this run of
 * deflate switches away from Z_RLE.)
 */
local block_state deflate_rle(s, flush)
    deflate_state *s;
    int flush;
{
    int bflush;             /* set if current block must be flushed */
    uInt prev;              /* byte at distance one to match */
    Bytef *scan, *strend;   /* scan goes up to strend for length of run */

    for (;;) {
        /* Make sure that we always have enough lookahead, except
         * at the end of the input file. We need MAX_MATCH bytes
         * for the longest encodable run.
         */
        if (s->lookahead < MAX_MATCH) {
            fill_window(s);
            if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) {
                return need_more;
            }
            if (s->lookahead == 0) break; /* flush the current block */
        }

        /* See how many times the previous byte repeats */
        s->match_length = 0;
        if (s->lookahead >= MIN_MATCH && s->strstart > 0) {
            scan = s->window + s->strstart - 1;
            prev = *scan;
            if (prev == *++scan && prev == *++scan && prev == *++scan) {
                strend = s->window + s->strstart + MAX_MATCH;
                do {
                } while (prev == *++scan && prev == *++scan &&
                         prev == *++scan && prev == *++scan &&
                         prev == *++scan && prev == *++scan &&
                         prev == *++scan && prev == *++scan &&
                         scan < strend);
                s->match_length = MAX_MATCH - (int)(strend - scan);
                if (s->match_length > s->lookahead)
                    s->match_length = s->lookahead;
            }
        }

        /* Emit match if have run of MIN_MATCH or longer, else emit literal */
        if (s->match_length >= MIN_MATCH) {
            check_match(s, s->strstart, s->strstart - 1, s->match_length);

            _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush);

            s->lookahead -= s->match_length;
            s->strstart += s->match_length;
            s->match_length = 0;
        } else {
            /* No match, output a literal byte */
            Tracevv((stderr,"%c", s->window[s->strstart]));
            _tr_tally_lit (s, s->window[s->strstart], bflush);
            s->lookahead--;
            s->strstart++;
        }
        if (bflush) FLUSH_BLOCK(s, 0);
    }
    FLUSH_BLOCK(s, flush == Z_FINISH);
    return flush == Z_FINISH ? finish_done : block_done;
}

/* ===========================================================================
 * For Z_HUFFMAN_ONLY, do not look for matches.  Do not maintain a hash table.
 * (It will be regenerated if this run of deflate switches away from Huffman.)
 */
local block_state deflate_huff(s, flush)
    deflate_state *s;
    int flush;
{
    int bflush;             /* set if current block must be flushed */

    for (;;) {
        /* Make sure that we have a literal to write. */
        if (s->lookahead == 0) {
            fill_window(s);
            if (s->lookahead == 0) {
                if (flush == Z_NO_FLUSH)
                    return need_more;
                break;      /* flush the current block */
            }
        }

        /* Output a literal byte */
        s->match_length = 0;
        Tracevv((stderr,"%c", s->window[s->strstart]));
        _tr_tally_lit (s, s->window[s->strstart], bflush);
        s->lookahead--;
        s->strstart++;
        if (bflush) FLUSH_BLOCK(s, 0);
    }
    FLUSH_BLOCK(s, flush == Z_FINISH);
    return flush == Z_FINISH ? finish_done : block_done;
}
cfitsio/zlib/deflate.h0000644000225700000360000003055713246025103014527 0ustar  cagordonlhea/* deflate.h -- internal compression state
 * Copyright (C) 1995-2010 Jean-loup Gailly
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

/* WARNING: this file should *not* be used by applications. It is
   part of the implementation of the compression library and is
   subject to change. Applications should only use zlib.h.
 */

#ifndef DEFLATE_H
#define DEFLATE_H

#include "zutil.h"

/* define NO_GZIP when compiling if you want to disable gzip header and
   trailer creation by deflate().  NO_GZIP would be used to avoid linking in
   the crc code when it is not needed.  For shared libraries, gzip encoding
   should be left enabled. */
#ifndef NO_GZIP
#  define GZIP
#endif

/* ===========================================================================
 * Internal compression state.
 */

#define LENGTH_CODES 29
/* number of length codes, not counting the special END_BLOCK code */

#define LITERALS  256
/* number of literal bytes 0..255 */

#define L_CODES (LITERALS+1+LENGTH_CODES)
/* number of Literal or Length codes, including the END_BLOCK code */

#define D_CODES   30
/* number of distance codes */

#define BL_CODES  19
/* number of codes used to transfer the bit lengths */

#define HEAP_SIZE (2*L_CODES+1)
/* maximum heap size */

#define MAX_BITS 15
/* All codes must not exceed MAX_BITS bits */

#define INIT_STATE    42
#define EXTRA_STATE   69
#define NAME_STATE    73
#define COMMENT_STATE 91
#define HCRC_STATE   103
#define BUSY_STATE   113
#define FINISH_STATE 666
/* Stream status */


/* Data structure describing a single value and its code string. */
typedef struct ct_data_s {
    union {
        ush  freq;       /* frequency count */
        ush  code;       /* bit string */
    } fc;
    union {
        ush  dad;        /* father node in Huffman tree */
        ush  len;        /* length of bit string */
    } dl;
} FAR ct_data;

#define Freq fc.freq
#define Code fc.code
#define Dad  dl.dad
#define Len  dl.len

typedef struct static_tree_desc_s  static_tree_desc;

typedef struct tree_desc_s {
    ct_data *dyn_tree;           /* the dynamic tree */
    int     max_code;            /* largest code with non zero frequency */
    static_tree_desc *stat_desc; /* the corresponding static tree */
} FAR tree_desc;

typedef ush Pos;
typedef Pos FAR Posf;
typedef unsigned IPos;

/* A Pos is an index in the character window. We use short instead of int to
 * save space in the various tables. IPos is used only for parameter passing.
 */

typedef struct internal_state {
    z_streamp strm;      /* pointer back to this zlib stream */
    int   status;        /* as the name implies */
    Bytef *pending_buf;  /* output still pending */
    ulg   pending_buf_size; /* size of pending_buf */
    Bytef *pending_out;  /* next pending byte to output to the stream */
    uInt   pending;      /* nb of bytes in the pending buffer */
    int   wrap;          /* bit 0 true for zlib, bit 1 true for gzip */
    gz_headerp  gzhead;  /* gzip header information to write */
    uInt   gzindex;      /* where in extra, name, or comment */
    Byte  method;        /* STORED (for zip only) or DEFLATED */
    int   last_flush;    /* value of flush param for previous deflate call */

                /* used by deflate.c: */

    uInt  w_size;        /* LZ77 window size (32K by default) */
    uInt  w_bits;        /* log2(w_size)  (8..16) */
    uInt  w_mask;        /* w_size - 1 */

    Bytef *window;
    /* Sliding window. Input bytes are read into the second half of the window,
     * and move to the first half later to keep a dictionary of at least wSize
     * bytes. With this organization, matches are limited to a distance of
     * wSize-MAX_MATCH bytes, but this ensures that IO is always
     * performed with a length multiple of the block size. Also, it limits
     * the window size to 64K, which is quite useful on MSDOS.
     * To do: use the user input buffer as sliding window.
     */

    ulg window_size;
    /* Actual size of window: 2*wSize, except when the user input buffer
     * is directly used as sliding window.
     */

    Posf *prev;
    /* Link to older string with same hash index. To limit the size of this
     * array to 64K, this link is maintained only for the last 32K strings.
     * An index in this array is thus a window index modulo 32K.
     */

    Posf *head; /* Heads of the hash chains or NIL. */

    uInt  ins_h;          /* hash index of string to be inserted */
    uInt  hash_size;      /* number of elements in hash table */
    uInt  hash_bits;      /* log2(hash_size) */
    uInt  hash_mask;      /* hash_size-1 */

    uInt  hash_shift;
    /* Number of bits by which ins_h must be shifted at each input
     * step. It must be such that after MIN_MATCH steps, the oldest
     * byte no longer takes part in the hash key, that is:
     *   hash_shift * MIN_MATCH >= hash_bits
     */

    long block_start;
    /* Window position at the beginning of the current output block. Gets
     * negative when the window is moved backwards.
     */

    uInt match_length;           /* length of best match */
    IPos prev_match;             /* previous match */
    int match_available;         /* set if previous match exists */
    uInt strstart;               /* start of string to insert */
    uInt match_start;            /* start of matching string */
    uInt lookahead;              /* number of valid bytes ahead in window */

    uInt prev_length;
    /* Length of the best match at previous step. Matches not greater than this
     * are discarded. This is used in the lazy match evaluation.
     */

    uInt max_chain_length;
    /* To speed up deflation, hash chains are never searched beyond this
     * length.  A higher limit improves compression ratio but degrades the
     * speed.
     */

    uInt max_lazy_match;
    /* Attempt to find a better match only when the current match is strictly
     * smaller than this value. This mechanism is used only for compression
     * levels >= 4.
     */
#   define max_insert_length  max_lazy_match
    /* Insert new strings in the hash table only if the match length is not
     * greater than this length. This saves time but degrades compression.
     * max_insert_length is used only for compression levels <= 3.
     */

    int level;    /* compression level (1..9) */
    int strategy; /* favor or force Huffman coding*/

    uInt good_match;
    /* Use a faster search when the previous match is longer than this */

    int nice_match; /* Stop searching when current match exceeds this */

                /* used by trees.c: */
    /* Didn't use ct_data typedef below to supress compiler warning */
    struct ct_data_s dyn_ltree[HEAP_SIZE];   /* literal and length tree */
    struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
    struct ct_data_s bl_tree[2*BL_CODES+1];  /* Huffman tree for bit lengths */

    struct tree_desc_s l_desc;               /* desc. for literal tree */
    struct tree_desc_s d_desc;               /* desc. for distance tree */
    struct tree_desc_s bl_desc;              /* desc. for bit length tree */

    ush bl_count[MAX_BITS+1];
    /* number of codes at each bit length for an optimal tree */

    int heap[2*L_CODES+1];      /* heap used to build the Huffman trees */
    int heap_len;               /* number of elements in the heap */
    int heap_max;               /* element of largest frequency */
    /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
     * The same heap array is used to build all trees.
     */

    uch depth[2*L_CODES+1];
    /* Depth of each subtree used as tie breaker for trees of equal frequency
     */

    uchf *l_buf;          /* buffer for literals or lengths */

    uInt  lit_bufsize;
    /* Size of match buffer for literals/lengths.  There are 4 reasons for
     * limiting lit_bufsize to 64K:
     *   - frequencies can be kept in 16 bit counters
     *   - if compression is not successful for the first block, all input
     *     data is still in the window so we can still emit a stored block even
     *     when input comes from standard input.  (This can also be done for
     *     all blocks if lit_bufsize is not greater than 32K.)
     *   - if compression is not successful for a file smaller than 64K, we can
     *     even emit a stored file instead of a stored block (saving 5 bytes).
     *     This is applicable only for zip (not gzip or zlib).
     *   - creating new Huffman trees less frequently may not provide fast
     *     adaptation to changes in the input data statistics. (Take for
     *     example a binary file with poorly compressible code followed by
     *     a highly compressible string table.) Smaller buffer sizes give
     *     fast adaptation but have of course the overhead of transmitting
     *     trees more frequently.
     *   - I can't count above 4
     */

    uInt last_lit;      /* running index in l_buf */

    ushf *d_buf;
    /* Buffer for distances. To simplify the code, d_buf and l_buf have
     * the same number of elements. To use different lengths, an extra flag
     * array would be necessary.
     */

    ulg opt_len;        /* bit length of current block with optimal trees */
    ulg static_len;     /* bit length of current block with static trees */
    uInt matches;       /* number of string matches in current block */
    int last_eob_len;   /* bit length of EOB code for last block */

#ifdef DEBUG
    ulg compressed_len; /* total bit length of compressed file mod 2^32 */
    ulg bits_sent;      /* bit length of compressed data sent mod 2^32 */
#endif

    ush bi_buf;
    /* Output buffer. bits are inserted starting at the bottom (least
     * significant bits).
     */
    int bi_valid;
    /* Number of valid bits in bi_buf.  All bits above the last valid bit
     * are always zero.
     */

    ulg high_water;
    /* High water mark offset in window for initialized bytes -- bytes above
     * this are set to zero in order to avoid memory check warnings when
     * longest match routines access bytes past the input.  This is then
     * updated to the new high water mark.
     */

} FAR deflate_state;

/* Output a byte on the stream.
 * IN assertion: there is enough room in pending_buf.
 */
#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}


#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
/* Minimum amount of lookahead, except at the end of the input file.
 * See deflate.c for comments about the MIN_MATCH+1.
 */

#define MAX_DIST(s)  ((s)->w_size-MIN_LOOKAHEAD)
/* In order to simplify the code, particularly on 16 bit machines, match
 * distances are limited to MAX_DIST instead of WSIZE.
 */

#define WIN_INIT MAX_MATCH
/* Number of bytes after end of data in window to initialize in order to avoid
   memory checker errors from longest match routines */

        /* in trees.c */
void ZLIB_INTERNAL _tr_init OF((deflate_state *s));
int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf,
                        ulg stored_len, int last));
void ZLIB_INTERNAL _tr_align OF((deflate_state *s));
void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
                        ulg stored_len, int last));

#define d_code(dist) \
   ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
/* Mapping from a distance to a distance code. dist is the distance - 1 and
 * must not have side effects. _dist_code[256] and _dist_code[257] are never
 * used.
 */

#ifndef DEBUG
/* Inline versions of _tr_tally for speed: */

#if defined(GEN_TREES_H) || !defined(STDC)
  extern uch ZLIB_INTERNAL _length_code[];
  extern uch ZLIB_INTERNAL _dist_code[];
#else
  extern const uch ZLIB_INTERNAL _length_code[];
  extern const uch ZLIB_INTERNAL _dist_code[];
#endif

# define _tr_tally_lit(s, c, flush) \
  { uch cc = (c); \
    s->d_buf[s->last_lit] = 0; \
    s->l_buf[s->last_lit++] = cc; \
    s->dyn_ltree[cc].Freq++; \
    flush = (s->last_lit == s->lit_bufsize-1); \
   }
# define _tr_tally_dist(s, distance, length, flush) \
  { uch len = (length); \
    ush dist = (distance); \
    s->d_buf[s->last_lit] = dist; \
    s->l_buf[s->last_lit++] = len; \
    dist--; \
    s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
    s->dyn_dtree[d_code(dist)].Freq++; \
    flush = (s->last_lit == s->lit_bufsize-1); \
  }
#else
# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
# define _tr_tally_dist(s, distance, length, flush) \
              flush = _tr_tally(s, distance, length)
#endif

#endif /* DEFLATE_H */
cfitsio/zlib/infback.c0000644000225700000360000005413613246025103014512 0ustar  cagordonlhea/* infback.c -- inflate using a call-back interface
 * Copyright (C) 1995-2009 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

/*
   This code is largely copied from inflate.c.  Normally either infback.o or
   inflate.o would be linked into an application--not both.  The interface
   with inffast.c is retained so that optimized assembler-coded versions of
   inflate_fast() can be used with either inflate.c or infback.c.
 */

#include "zutil.h"
#include "inftrees.h"
#include "inflate.h"
#include "inffast.h"

/* function prototypes */
local void fixedtables OF((struct inflate_state FAR *state));

/*
   strm provides memory allocation functions in zalloc and zfree, or
   Z_NULL to use the library memory allocation functions.

   windowBits is in the range 8..15, and window is a user-supplied
   window and output buffer that is 2**windowBits bytes.
 */
int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
z_streamp strm;
int windowBits;
unsigned char FAR *window;
const char *version;
int stream_size;
{
    struct inflate_state FAR *state;

    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
        stream_size != (int)(sizeof(z_stream)))
        return Z_VERSION_ERROR;
    if (strm == Z_NULL || window == Z_NULL ||
        windowBits < 8 || windowBits > 15)
        return Z_STREAM_ERROR;
    strm->msg = Z_NULL;                 /* in case we return an error */
    if (strm->zalloc == (alloc_func)0) {
        strm->zalloc = zcalloc;
        strm->opaque = (voidpf)0;
    }
    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
    state = (struct inflate_state FAR *)ZALLOC(strm, 1,
                                               sizeof(struct inflate_state));
    if (state == Z_NULL) return Z_MEM_ERROR;
    Tracev((stderr, "inflate: allocated\n"));
    strm->state = (struct internal_state FAR *)state;
    state->dmax = 32768U;
    state->wbits = windowBits;
    state->wsize = 1U << windowBits;
    state->window = window;
    state->wnext = 0;
    state->whave = 0;
    return Z_OK;
}

/*
   Return state with length and distance decoding tables and index sizes set to
   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
   If BUILDFIXED is defined, then instead this routine builds the tables the
   first time it's called, and returns those tables the first time and
   thereafter.  This reduces the size of the code by about 2K bytes, in
   exchange for a little execution time.  However, BUILDFIXED should not be
   used for threaded applications, since the rewriting of the tables and virgin
   may not be thread-safe.
 */
local void fixedtables(state)
struct inflate_state FAR *state;
{
#ifdef BUILDFIXED
    static int virgin = 1;
    static code *lenfix, *distfix;
    static code fixed[544];

    /* build fixed huffman tables if first call (may not be thread safe) */
    if (virgin) {
        unsigned sym, bits;
        static code *next;

        /* literal/length table */
        sym = 0;
        while (sym < 144) state->lens[sym++] = 8;
        while (sym < 256) state->lens[sym++] = 9;
        while (sym < 280) state->lens[sym++] = 7;
        while (sym < 288) state->lens[sym++] = 8;
        next = fixed;
        lenfix = next;
        bits = 9;
        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);

        /* distance table */
        sym = 0;
        while (sym < 32) state->lens[sym++] = 5;
        distfix = next;
        bits = 5;
        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);

        /* do this just once */
        virgin = 0;
    }
#else /* !BUILDFIXED */
#   include "inffixed.h"
#endif /* BUILDFIXED */
    state->lencode = lenfix;
    state->lenbits = 9;
    state->distcode = distfix;
    state->distbits = 5;
}

/* Macros for inflateBack(): */

/* Load returned state from inflate_fast() */
#define LOAD() \
    do { \
        put = strm->next_out; \
        left = strm->avail_out; \
        next = strm->next_in; \
        have = strm->avail_in; \
        hold = state->hold; \
        bits = state->bits; \
    } while (0)

/* Set state from registers for inflate_fast() */
#define RESTORE() \
    do { \
        strm->next_out = put; \
        strm->avail_out = left; \
        strm->next_in = next; \
        strm->avail_in = have; \
        state->hold = hold; \
        state->bits = bits; \
    } while (0)

/* Clear the input bit accumulator */
#define INITBITS() \
    do { \
        hold = 0; \
        bits = 0; \
    } while (0)

/* Assure that some input is available.  If input is requested, but denied,
   then return a Z_BUF_ERROR from inflateBack(). */
#define PULL() \
    do { \
        if (have == 0) { \
            have = in(in_desc, &next); \
            if (have == 0) { \
                next = Z_NULL; \
                ret = Z_BUF_ERROR; \
                goto inf_leave; \
            } \
        } \
    } while (0)

/* Get a byte of input into the bit accumulator, or return from inflateBack()
   with an error if there is no input available. */
#define PULLBYTE() \
    do { \
        PULL(); \
        have--; \
        hold += (unsigned long)(*next++) << bits; \
        bits += 8; \
    } while (0)

/* Assure that there are at least n bits in the bit accumulator.  If there is
   not enough available input to do that, then return from inflateBack() with
   an error. */
#define NEEDBITS(n) \
    do { \
        while (bits < (unsigned)(n)) \
            PULLBYTE(); \
    } while (0)

/* Return the low n bits of the bit accumulator (n < 16) */
#define BITS(n) \
    ((unsigned)hold & ((1U << (n)) - 1))

/* Remove n bits from the bit accumulator */
#define DROPBITS(n) \
    do { \
        hold >>= (n); \
        bits -= (unsigned)(n); \
    } while (0)

/* Remove zero to seven bits as needed to go to a byte boundary */
#define BYTEBITS() \
    do { \
        hold >>= bits & 7; \
        bits -= bits & 7; \
    } while (0)

/* Assure that some output space is available, by writing out the window
   if it's full.  If the write fails, return from inflateBack() with a
   Z_BUF_ERROR. */
#define ROOM() \
    do { \
        if (left == 0) { \
            put = state->window; \
            left = state->wsize; \
            state->whave = left; \
            if (out(out_desc, put, left)) { \
                ret = Z_BUF_ERROR; \
                goto inf_leave; \
            } \
        } \
    } while (0)

/*
   strm provides the memory allocation functions and window buffer on input,
   and provides information on the unused input on return.  For Z_DATA_ERROR
   returns, strm will also provide an error message.

   in() and out() are the call-back input and output functions.  When
   inflateBack() needs more input, it calls in().  When inflateBack() has
   filled the window with output, or when it completes with data in the
   window, it calls out() to write out the data.  The application must not
   change the provided input until in() is called again or inflateBack()
   returns.  The application must not change the window/output buffer until
   inflateBack() returns.

   in() and out() are called with a descriptor parameter provided in the
   inflateBack() call.  This parameter can be a structure that provides the
   information required to do the read or write, as well as accumulated
   information on the input and output such as totals and check values.

   in() should return zero on failure.  out() should return non-zero on
   failure.  If either in() or out() fails, than inflateBack() returns a
   Z_BUF_ERROR.  strm->next_in can be checked for Z_NULL to see whether it
   was in() or out() that caused in the error.  Otherwise,  inflateBack()
   returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
   error, or Z_MEM_ERROR if it could not allocate memory for the state.
   inflateBack() can also return Z_STREAM_ERROR if the input parameters
   are not correct, i.e. strm is Z_NULL or the state was not initialized.
 */
int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
z_streamp strm;
in_func in;
void FAR *in_desc;
out_func out;
void FAR *out_desc;
{
    struct inflate_state FAR *state;
    unsigned char FAR *next;    /* next input */
    unsigned char FAR *put;     /* next output */
    unsigned have, left;        /* available input and output */
    unsigned long hold;         /* bit buffer */
    unsigned bits;              /* bits in bit buffer */
    unsigned copy;              /* number of stored or match bytes to copy */
    unsigned char FAR *from;    /* where to copy match bytes from */
    code here;                  /* current decoding table entry */
    code last;                  /* parent table entry */
    unsigned len;               /* length to copy for repeats, bits to drop */
    int ret;                    /* return code */
    static const unsigned short order[19] = /* permutation of code lengths */
        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};

    /* Check that the strm exists and that the state was initialized */
    if (strm == Z_NULL || strm->state == Z_NULL)
        return Z_STREAM_ERROR;
    state = (struct inflate_state FAR *)strm->state;

    /* Reset the state */
    strm->msg = Z_NULL;
    state->mode = TYPE;
    state->last = 0;
    state->whave = 0;
    next = strm->next_in;
    have = next != Z_NULL ? strm->avail_in : 0;
    hold = 0;
    bits = 0;
    put = state->window;
    left = state->wsize;

    /* Inflate until end of block marked as last */
    for (;;)
        switch (state->mode) {
        case TYPE:
            /* determine and dispatch block type */
            if (state->last) {
                BYTEBITS();
                state->mode = DONE;
                break;
            }
            NEEDBITS(3);
            state->last = BITS(1);
            DROPBITS(1);
            switch (BITS(2)) {
            case 0:                             /* stored block */
                Tracev((stderr, "inflate:     stored block%s\n",
                        state->last ? " (last)" : ""));
                state->mode = STORED;
                break;
            case 1:                             /* fixed block */
                fixedtables(state);
                Tracev((stderr, "inflate:     fixed codes block%s\n",
                        state->last ? " (last)" : ""));
                state->mode = LEN;              /* decode codes */
                break;
            case 2:                             /* dynamic block */
                Tracev((stderr, "inflate:     dynamic codes block%s\n",
                        state->last ? " (last)" : ""));
                state->mode = TABLE;
                break;
            case 3:
                strm->msg = (char *)"invalid block type";
                state->mode = BAD;
            }
            DROPBITS(2);
            break;

        case STORED:
            /* get and verify stored block length */
            BYTEBITS();                         /* go to byte boundary */
            NEEDBITS(32);
            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
                strm->msg = (char *)"invalid stored block lengths";
                state->mode = BAD;
                break;
            }
            state->length = (unsigned)hold & 0xffff;
            Tracev((stderr, "inflate:       stored length %u\n",
                    state->length));
            INITBITS();

            /* copy stored block from input to output */
            while (state->length != 0) {
                copy = state->length;
                PULL();
                ROOM();
                if (copy > have) copy = have;
                if (copy > left) copy = left;
                zmemcpy(put, next, copy);
                have -= copy;
                next += copy;
                left -= copy;
                put += copy;
                state->length -= copy;
            }
            Tracev((stderr, "inflate:       stored end\n"));
            state->mode = TYPE;
            break;

        case TABLE:
            /* get dynamic table entries descriptor */
            NEEDBITS(14);
            state->nlen = BITS(5) + 257;
            DROPBITS(5);
            state->ndist = BITS(5) + 1;
            DROPBITS(5);
            state->ncode = BITS(4) + 4;
            DROPBITS(4);
#ifndef PKZIP_BUG_WORKAROUND
            if (state->nlen > 286 || state->ndist > 30) {
                strm->msg = (char *)"too many length or distance symbols";
                state->mode = BAD;
                break;
            }
#endif
            Tracev((stderr, "inflate:       table sizes ok\n"));

            /* get code length code lengths (not a typo) */
            state->have = 0;
            while (state->have < state->ncode) {
                NEEDBITS(3);
                state->lens[order[state->have++]] = (unsigned short)BITS(3);
                DROPBITS(3);
            }
            while (state->have < 19)
                state->lens[order[state->have++]] = 0;
            state->next = state->codes;
            state->lencode = (code const FAR *)(state->next);
            state->lenbits = 7;
            ret = inflate_table(CODES, state->lens, 19, &(state->next),
                                &(state->lenbits), state->work);
            if (ret) {
                strm->msg = (char *)"invalid code lengths set";
                state->mode = BAD;
                break;
            }
            Tracev((stderr, "inflate:       code lengths ok\n"));

            /* get length and distance code code lengths */
            state->have = 0;
            while (state->have < state->nlen + state->ndist) {
                for (;;) {
                    here = state->lencode[BITS(state->lenbits)];
                    if ((unsigned)(here.bits) <= bits) break;
                    PULLBYTE();
                }
                if (here.val < 16) {
                    NEEDBITS(here.bits);
                    DROPBITS(here.bits);
                    state->lens[state->have++] = here.val;
                }
                else {
                    if (here.val == 16) {
                        NEEDBITS(here.bits + 2);
                        DROPBITS(here.bits);
                        if (state->have == 0) {
                            strm->msg = (char *)"invalid bit length repeat";
                            state->mode = BAD;
                            break;
                        }
                        len = (unsigned)(state->lens[state->have - 1]);
                        copy = 3 + BITS(2);
                        DROPBITS(2);
                    }
                    else if (here.val == 17) {
                        NEEDBITS(here.bits + 3);
                        DROPBITS(here.bits);
                        len = 0;
                        copy = 3 + BITS(3);
                        DROPBITS(3);
                    }
                    else {
                        NEEDBITS(here.bits + 7);
                        DROPBITS(here.bits);
                        len = 0;
                        copy = 11 + BITS(7);
                        DROPBITS(7);
                    }
                    if (state->have + copy > state->nlen + state->ndist) {
                        strm->msg = (char *)"invalid bit length repeat";
                        state->mode = BAD;
                        break;
                    }
                    while (copy--)
                        state->lens[state->have++] = (unsigned short)len;
                }
            }

            /* handle error breaks in while */
            if (state->mode == BAD) break;

            /* check for end-of-block code (better have one) */
            if (state->lens[256] == 0) {
                strm->msg = (char *)"invalid code -- missing end-of-block";
                state->mode = BAD;
                break;
            }

            /* build code tables -- note: do not change the lenbits or distbits
               values here (9 and 6) without reading the comments in inftrees.h
               concerning the ENOUGH constants, which depend on those values */
            state->next = state->codes;
            state->lencode = (code const FAR *)(state->next);
            state->lenbits = 9;
            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
                                &(state->lenbits), state->work);
            if (ret) {
                strm->msg = (char *)"invalid literal/lengths set";
                state->mode = BAD;
                break;
            }
            state->distcode = (code const FAR *)(state->next);
            state->distbits = 6;
            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
                            &(state->next), &(state->distbits), state->work);
            if (ret) {
                strm->msg = (char *)"invalid distances set";
                state->mode = BAD;
                break;
            }
            Tracev((stderr, "inflate:       codes ok\n"));
            state->mode = LEN;

        case LEN:
            /* use inflate_fast() if we have enough input and output */
            if (have >= 6 && left >= 258) {
                RESTORE();
                if (state->whave < state->wsize)
                    state->whave = state->wsize - left;
                inflate_fast(strm, state->wsize);
                LOAD();
                break;
            }

            /* get a literal, length, or end-of-block code */
            for (;;) {
                here = state->lencode[BITS(state->lenbits)];
                if ((unsigned)(here.bits) <= bits) break;
                PULLBYTE();
            }
            if (here.op && (here.op & 0xf0) == 0) {
                last = here;
                for (;;) {
                    here = state->lencode[last.val +
                            (BITS(last.bits + last.op) >> last.bits)];
                    if ((unsigned)(last.bits + here.bits) <= bits) break;
                    PULLBYTE();
                }
                DROPBITS(last.bits);
            }
            DROPBITS(here.bits);
            state->length = (unsigned)here.val;

            /* process literal */
            if (here.op == 0) {
                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
                        "inflate:         literal '%c'\n" :
                        "inflate:         literal 0x%02x\n", here.val));
                ROOM();
                *put++ = (unsigned char)(state->length);
                left--;
                state->mode = LEN;
                break;
            }

            /* process end of block */
            if (here.op & 32) {
                Tracevv((stderr, "inflate:         end of block\n"));
                state->mode = TYPE;
                break;
            }

            /* invalid code */
            if (here.op & 64) {
                strm->msg = (char *)"invalid literal/length code";
                state->mode = BAD;
                break;
            }

            /* length code -- get extra bits, if any */
            state->extra = (unsigned)(here.op) & 15;
            if (state->extra != 0) {
                NEEDBITS(state->extra);
                state->length += BITS(state->extra);
                DROPBITS(state->extra);
            }
            Tracevv((stderr, "inflate:         length %u\n", state->length));

            /* get distance code */
            for (;;) {
                here = state->distcode[BITS(state->distbits)];
                if ((unsigned)(here.bits) <= bits) break;
                PULLBYTE();
            }
            if ((here.op & 0xf0) == 0) {
                last = here;
                for (;;) {
                    here = state->distcode[last.val +
                            (BITS(last.bits + last.op) >> last.bits)];
                    if ((unsigned)(last.bits + here.bits) <= bits) break;
                    PULLBYTE();
                }
                DROPBITS(last.bits);
            }
            DROPBITS(here.bits);
            if (here.op & 64) {
                strm->msg = (char *)"invalid distance code";
                state->mode = BAD;
                break;
            }
            state->offset = (unsigned)here.val;

            /* get distance extra bits, if any */
            state->extra = (unsigned)(here.op) & 15;
            if (state->extra != 0) {
                NEEDBITS(state->extra);
                state->offset += BITS(state->extra);
                DROPBITS(state->extra);
            }
            if (state->offset > state->wsize - (state->whave < state->wsize ?
                                                left : 0)) {
                strm->msg = (char *)"invalid distance too far back";
                state->mode = BAD;
                break;
            }
            Tracevv((stderr, "inflate:         distance %u\n", state->offset));

            /* copy match from window to output */
            do {
                ROOM();
                copy = state->wsize - state->offset;
                if (copy < left) {
                    from = put + copy;
                    copy = left - copy;
                }
                else {
                    from = put - state->offset;
                    copy = left;
                }
                if (copy > state->length) copy = state->length;
                state->length -= copy;
                left -= copy;
                do {
                    *put++ = *from++;
                } while (--copy);
            } while (state->length != 0);
            break;

        case DONE:
            /* inflate stream terminated properly -- write leftover output */
            ret = Z_STREAM_END;
            if (left < state->wsize) {
                if (out(out_desc, state->window, state->wsize - left))
                    ret = Z_BUF_ERROR;
            }
            goto inf_leave;

        case BAD:
            ret = Z_DATA_ERROR;
            goto inf_leave;

        default:                /* can't happen, but makes compilers happy */
            ret = Z_STREAM_ERROR;
            goto inf_leave;
        }

    /* Return unused input */
  inf_leave:
    strm->next_in = next;
    strm->avail_in = have;
    return ret;
}

int ZEXPORT inflateBackEnd(strm)
z_streamp strm;
{
    if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
        return Z_STREAM_ERROR;
    ZFREE(strm, strm->state);
    strm->state = Z_NULL;
    Tracev((stderr, "inflate: end\n"));
    return Z_OK;
}
cfitsio/zlib/inffast.c0000644000225700000360000003217713246025103014550 0ustar  cagordonlhea/* inffast.c -- fast decoding
 * Copyright (C) 1995-2008, 2010 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

#include "zutil.h"
#include "inftrees.h"
#include "inflate.h"
#include "inffast.h"

#ifndef ASMINF

/* Allow machine dependent optimization for post-increment or pre-increment.
   Based on testing to date,
   Pre-increment preferred for:
   - PowerPC G3 (Adler)
   - MIPS R5000 (Randers-Pehrson)
   Post-increment preferred for:
   - none
   No measurable difference:
   - Pentium III (Anderson)
   - M68060 (Nikl)
 */
#ifdef POSTINC
#  define OFF 0
#  define PUP(a) *(a)++
#else
#  define OFF 1
#  define PUP(a) *++(a)
#endif

/*
   Decode literal, length, and distance codes and write out the resulting
   literal and match bytes until either not enough input or output is
   available, an end-of-block is encountered, or a data error is encountered.
   When large enough input and output buffers are supplied to inflate(), for
   example, a 16K input buffer and a 64K output buffer, more than 95% of the
   inflate execution time is spent in this routine.

   Entry assumptions:

        state->mode == LEN
        strm->avail_in >= 6
        strm->avail_out >= 258
        start >= strm->avail_out
        state->bits < 8

   On return, state->mode is one of:

        LEN -- ran out of enough output space or enough available input
        TYPE -- reached end of block code, inflate() to interpret next block
        BAD -- error in block data

   Notes:

    - The maximum input bits used by a length/distance pair is 15 bits for the
      length code, 5 bits for the length extra, 15 bits for the distance code,
      and 13 bits for the distance extra.  This totals 48 bits, or six bytes.
      Therefore if strm->avail_in >= 6, then there is enough input to avoid
      checking for available input while decoding.

    - The maximum bytes that a single length/distance pair can output is 258
      bytes, which is the maximum length that can be coded.  inflate_fast()
      requires strm->avail_out >= 258 for each loop to avoid checking for
      output space.
 */
void ZLIB_INTERNAL inflate_fast(strm, start)
z_streamp strm;
unsigned start;         /* inflate()'s starting value for strm->avail_out */
{
    struct inflate_state FAR *state;
    unsigned char FAR *in;      /* local strm->next_in */
    unsigned char FAR *last;    /* while in < last, enough input available */
    unsigned char FAR *out;     /* local strm->next_out */
    unsigned char FAR *beg;     /* inflate()'s initial strm->next_out */
    unsigned char FAR *end;     /* while out < end, enough space available */
#ifdef INFLATE_STRICT
    unsigned dmax;              /* maximum distance from zlib header */
#endif
    unsigned wsize;             /* window size or zero if not using window */
    unsigned whave;             /* valid bytes in the window */
    unsigned wnext;             /* window write index */
    unsigned char FAR *window;  /* allocated sliding window, if wsize != 0 */
    unsigned long hold;         /* local strm->hold */
    unsigned bits;              /* local strm->bits */
    code const FAR *lcode;      /* local strm->lencode */
    code const FAR *dcode;      /* local strm->distcode */
    unsigned lmask;             /* mask for first level of length codes */
    unsigned dmask;             /* mask for first level of distance codes */
    code here;                  /* retrieved table entry */
    unsigned op;                /* code bits, operation, extra bits, or */
                                /*  window position, window bytes to copy */
    unsigned len;               /* match length, unused bytes */
    unsigned dist;              /* match distance */
    unsigned char FAR *from;    /* where to copy match from */

    /* copy state to local variables */
    state = (struct inflate_state FAR *)strm->state;
    in = strm->next_in - OFF;
    last = in + (strm->avail_in - 5);
    out = strm->next_out - OFF;
    beg = out - (start - strm->avail_out);
    end = out + (strm->avail_out - 257);
#ifdef INFLATE_STRICT
    dmax = state->dmax;
#endif
    wsize = state->wsize;
    whave = state->whave;
    wnext = state->wnext;
    window = state->window;
    hold = state->hold;
    bits = state->bits;
    lcode = state->lencode;
    dcode = state->distcode;
    lmask = (1U << state->lenbits) - 1;
    dmask = (1U << state->distbits) - 1;

    /* decode literals and length/distances until end-of-block or not enough
       input data or output space */
    do {
        if (bits < 15) {
            hold += (unsigned long)(PUP(in)) << bits;
            bits += 8;
            hold += (unsigned long)(PUP(in)) << bits;
            bits += 8;
        }
        here = lcode[hold & lmask];
      dolen:
        op = (unsigned)(here.bits);
        hold >>= op;
        bits -= op;
        op = (unsigned)(here.op);
        if (op == 0) {                          /* literal */
            Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
                    "inflate:         literal '%c'\n" :
                    "inflate:         literal 0x%02x\n", here.val));
            PUP(out) = (unsigned char)(here.val);
        }
        else if (op & 16) {                     /* length base */
            len = (unsigned)(here.val);
            op &= 15;                           /* number of extra bits */
            if (op) {
                if (bits < op) {
                    hold += (unsigned long)(PUP(in)) << bits;
                    bits += 8;
                }
                len += (unsigned)hold & ((1U << op) - 1);
                hold >>= op;
                bits -= op;
            }
            Tracevv((stderr, "inflate:         length %u\n", len));
            if (bits < 15) {
                hold += (unsigned long)(PUP(in)) << bits;
                bits += 8;
                hold += (unsigned long)(PUP(in)) << bits;
                bits += 8;
            }
            here = dcode[hold & dmask];
          dodist:
            op = (unsigned)(here.bits);
            hold >>= op;
            bits -= op;
            op = (unsigned)(here.op);
            if (op & 16) {                      /* distance base */
                dist = (unsigned)(here.val);
                op &= 15;                       /* number of extra bits */
                if (bits < op) {
                    hold += (unsigned long)(PUP(in)) << bits;
                    bits += 8;
                    if (bits < op) {
                        hold += (unsigned long)(PUP(in)) << bits;
                        bits += 8;
                    }
                }
                dist += (unsigned)hold & ((1U << op) - 1);
#ifdef INFLATE_STRICT
                if (dist > dmax) {
                    strm->msg = (char *)"invalid distance too far back";
                    state->mode = BAD;
                    break;
                }
#endif
                hold >>= op;
                bits -= op;
                Tracevv((stderr, "inflate:         distance %u\n", dist));
                op = (unsigned)(out - beg);     /* max distance in output */
                if (dist > op) {                /* see if copy from window */
                    op = dist - op;             /* distance back in window */
                    if (op > whave) {
                        if (state->sane) {
                            strm->msg =
                                (char *)"invalid distance too far back";
                            state->mode = BAD;
                            break;
                        }
#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
                        if (len <= op - whave) {
                            do {
                                PUP(out) = 0;
                            } while (--len);
                            continue;
                        }
                        len -= op - whave;
                        do {
                            PUP(out) = 0;
                        } while (--op > whave);
                        if (op == 0) {
                            from = out - dist;
                            do {
                                PUP(out) = PUP(from);
                            } while (--len);
                            continue;
                        }
#endif
                    }
                    from = window - OFF;
                    if (wnext == 0) {           /* very common case */
                        from += wsize - op;
                        if (op < len) {         /* some from window */
                            len -= op;
                            do {
                                PUP(out) = PUP(from);
                            } while (--op);
                            from = out - dist;  /* rest from output */
                        }
                    }
                    else if (wnext < op) {      /* wrap around window */
                        from += wsize + wnext - op;
                        op -= wnext;
                        if (op < len) {         /* some from end of window */
                            len -= op;
                            do {
                                PUP(out) = PUP(from);
                            } while (--op);
                            from = window - OFF;
                            if (wnext < len) {  /* some from start of window */
                                op = wnext;
                                len -= op;
                                do {
                                    PUP(out) = PUP(from);
                                } while (--op);
                                from = out - dist;      /* rest from output */
                            }
                        }
                    }
                    else {                      /* contiguous in window */
                        from += wnext - op;
                        if (op < len) {         /* some from window */
                            len -= op;
                            do {
                                PUP(out) = PUP(from);
                            } while (--op);
                            from = out - dist;  /* rest from output */
                        }
                    }
                    while (len > 2) {
                        PUP(out) = PUP(from);
                        PUP(out) = PUP(from);
                        PUP(out) = PUP(from);
                        len -= 3;
                    }
                    if (len) {
                        PUP(out) = PUP(from);
                        if (len > 1)
                            PUP(out) = PUP(from);
                    }
                }
                else {
                    from = out - dist;          /* copy direct from output */
                    do {                        /* minimum length is three */
                        PUP(out) = PUP(from);
                        PUP(out) = PUP(from);
                        PUP(out) = PUP(from);
                        len -= 3;
                    } while (len > 2);
                    if (len) {
                        PUP(out) = PUP(from);
                        if (len > 1)
                            PUP(out) = PUP(from);
                    }
                }
            }
            else if ((op & 64) == 0) {          /* 2nd level distance code */
                here = dcode[here.val + (hold & ((1U << op) - 1))];
                goto dodist;
            }
            else {
                strm->msg = (char *)"invalid distance code";
                state->mode = BAD;
                break;
            }
        }
        else if ((op & 64) == 0) {              /* 2nd level length code */
            here = lcode[here.val + (hold & ((1U << op) - 1))];
            goto dolen;
        }
        else if (op & 32) {                     /* end-of-block */
            Tracevv((stderr, "inflate:         end of block\n"));
            state->mode = TYPE;
            break;
        }
        else {
            strm->msg = (char *)"invalid literal/length code";
            state->mode = BAD;
            break;
        }
    } while (in < last && out < end);

    /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
    len = bits >> 3;
    in -= len;
    bits -= len << 3;
    hold &= (1U << bits) - 1;

    /* update state and return */
    strm->next_in = in + OFF;
    strm->next_out = out + OFF;
    strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
    strm->avail_out = (unsigned)(out < end ?
                                 257 + (end - out) : 257 - (out - end));
    state->hold = hold;
    state->bits = bits;
    return;
}

/*
   inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
   - Using bit fields for code structure
   - Different op definition to avoid & for extra bits (do & for table bits)
   - Three separate decoding do-loops for direct, window, and wnext == 0
   - Special case for distance > 1 copies to do overlapped load and store copy
   - Explicit branch predictions (based on measured branch probabilities)
   - Deferring match copy and interspersed it with decoding subsequent codes
   - Swapping literal/length else
   - Swapping window/direct else
   - Larger unrolled copy loops (three is about right)
   - Moving len -= 3 statement into middle of loop
 */

#endif /* !ASMINF */
cfitsio/zlib/inffast.h0000644000225700000360000000065313246025103014547 0ustar  cagordonlhea/* inffast.h -- header to use inffast.c
 * Copyright (C) 1995-2003, 2010 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

/* WARNING: this file should *not* be used by applications. It is
   part of the implementation of the compression library and is
   subject to change. Applications should only use zlib.h.
 */

void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start));
cfitsio/zlib/inffixed.h0000644000225700000360000001430713246025103014712 0ustar  cagordonlhea    /* inffixed.h -- table for decoding fixed codes
     * Generated automatically by makefixed().
     */

    /* WARNING: this file should *not* be used by applications. It
       is part of the implementation of the compression library and
       is subject to change. Applications should only use zlib.h.
     */

    static const code lenfix[512] = {
        {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
        {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
        {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
        {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
        {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
        {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
        {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
        {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
        {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
        {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
        {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
        {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
        {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
        {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
        {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
        {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
        {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
        {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
        {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
        {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
        {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
        {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
        {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
        {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
        {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
        {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
        {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
        {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
        {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
        {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
        {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
        {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
        {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
        {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
        {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
        {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
        {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
        {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
        {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
        {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
        {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
        {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
        {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
        {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
        {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
        {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
        {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
        {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
        {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
        {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
        {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
        {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
        {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
        {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
        {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
        {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
        {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
        {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
        {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
        {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
        {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
        {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
        {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
        {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
        {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
        {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
        {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
        {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
        {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
        {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
        {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
        {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
        {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
        {0,9,255}
    };

    static const code distfix[32] = {
        {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
        {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
        {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
        {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
        {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
        {22,5,193},{64,5,0}
    };
cfitsio/zlib/inflate.c0000644000225700000360000014661713246025103014545 0ustar  cagordonlhea/* inflate.c -- zlib decompression
 * Copyright (C) 1995-2010 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

/*
 * Change history:
 *
 * 1.2.beta0    24 Nov 2002
 * - First version -- complete rewrite of inflate to simplify code, avoid
 *   creation of window when not needed, minimize use of window when it is
 *   needed, make inffast.c even faster, implement gzip decoding, and to
 *   improve code readability and style over the previous zlib inflate code
 *
 * 1.2.beta1    25 Nov 2002
 * - Use pointers for available input and output checking in inffast.c
 * - Remove input and output counters in inffast.c
 * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
 * - Remove unnecessary second byte pull from length extra in inffast.c
 * - Unroll direct copy to three copies per loop in inffast.c
 *
 * 1.2.beta2    4 Dec 2002
 * - Change external routine names to reduce potential conflicts
 * - Correct filename to inffixed.h for fixed tables in inflate.c
 * - Make hbuf[] unsigned char to match parameter type in inflate.c
 * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
 *   to avoid negation problem on Alphas (64 bit) in inflate.c
 *
 * 1.2.beta3    22 Dec 2002
 * - Add comments on state->bits assertion in inffast.c
 * - Add comments on op field in inftrees.h
 * - Fix bug in reuse of allocated window after inflateReset()
 * - Remove bit fields--back to byte structure for speed
 * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
 * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
 * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
 * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
 * - Use local copies of stream next and avail values, as well as local bit
 *   buffer and bit count in inflate()--for speed when inflate_fast() not used
 *
 * 1.2.beta4    1 Jan 2003
 * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
 * - Move a comment on output buffer sizes from inffast.c to inflate.c
 * - Add comments in inffast.c to introduce the inflate_fast() routine
 * - Rearrange window copies in inflate_fast() for speed and simplification
 * - Unroll last copy for window match in inflate_fast()
 * - Use local copies of window variables in inflate_fast() for speed
 * - Pull out common wnext == 0 case for speed in inflate_fast()
 * - Make op and len in inflate_fast() unsigned for consistency
 * - Add FAR to lcode and dcode declarations in inflate_fast()
 * - Simplified bad distance check in inflate_fast()
 * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
 *   source file infback.c to provide a call-back interface to inflate for
 *   programs like gzip and unzip -- uses window as output buffer to avoid
 *   window copying
 *
 * 1.2.beta5    1 Jan 2003
 * - Improved inflateBack() interface to allow the caller to provide initial
 *   input in strm.
 * - Fixed stored blocks bug in inflateBack()
 *
 * 1.2.beta6    4 Jan 2003
 * - Added comments in inffast.c on effectiveness of POSTINC
 * - Typecasting all around to reduce compiler warnings
 * - Changed loops from while (1) or do {} while (1) to for (;;), again to
 *   make compilers happy
 * - Changed type of window in inflateBackInit() to unsigned char *
 *
 * 1.2.beta7    27 Jan 2003
 * - Changed many types to unsigned or unsigned short to avoid warnings
 * - Added inflateCopy() function
 *
 * 1.2.0        9 Mar 2003
 * - Changed inflateBack() interface to provide separate opaque descriptors
 *   for the in() and out() functions
 * - Changed inflateBack() argument and in_func typedef to swap the length
 *   and buffer address return values for the input function
 * - Check next_in and next_out for Z_NULL on entry to inflate()
 *
 * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
 */

#include "zutil.h"
#include "inftrees.h"
#include "inflate.h"
#include "inffast.h"

#ifdef MAKEFIXED
#  ifndef BUILDFIXED
#    define BUILDFIXED
#  endif
#endif

/* function prototypes */
local void fixedtables OF((struct inflate_state FAR *state));
local int updatewindow OF((z_streamp strm, unsigned out));
#ifdef BUILDFIXED
   void makefixed OF((void));
#endif
local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf,
                              unsigned len));

int ZEXPORT inflateReset(strm)
z_streamp strm;
{
    struct inflate_state FAR *state;

    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
    state = (struct inflate_state FAR *)strm->state;
    strm->total_in = strm->total_out = state->total = 0;
    strm->msg = Z_NULL;
    strm->adler = 1;        /* to support ill-conceived Java test suite */
    state->mode = HEAD;
    state->last = 0;
    state->havedict = 0;
    state->dmax = 32768U;
    state->head = Z_NULL;
    state->wsize = 0;
    state->whave = 0;
    state->wnext = 0;
    state->hold = 0;
    state->bits = 0;
    state->lencode = state->distcode = state->next = state->codes;
    state->sane = 1;
    state->back = -1;
    Tracev((stderr, "inflate: reset\n"));
    return Z_OK;
}

int ZEXPORT inflateReset2(strm, windowBits)
z_streamp strm;
int windowBits;
{
    int wrap;
    struct inflate_state FAR *state;

    /* get the state */
    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
    state = (struct inflate_state FAR *)strm->state;

    /* extract wrap request from windowBits parameter */
    if (windowBits < 0) {
        wrap = 0;
        windowBits = -windowBits;
    }
    else {
        wrap = (windowBits >> 4) + 1;
#ifdef GUNZIP
        if (windowBits < 48)
            windowBits &= 15;
#endif
    }

    /* set number of window bits, free window if different */
    if (windowBits && (windowBits < 8 || windowBits > 15))
        return Z_STREAM_ERROR;
    if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) {
        ZFREE(strm, state->window);
        state->window = Z_NULL;
    }

    /* update state and reset the rest of it */
    state->wrap = wrap;
    state->wbits = (unsigned)windowBits;
    return inflateReset(strm);
}

int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
z_streamp strm;
int windowBits;
const char *version;
int stream_size;
{
    int ret;
    struct inflate_state FAR *state;

    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
        stream_size != (int)(sizeof(z_stream)))
        return Z_VERSION_ERROR;
    if (strm == Z_NULL) return Z_STREAM_ERROR;
    strm->msg = Z_NULL;                 /* in case we return an error */
    if (strm->zalloc == (alloc_func)0) {
        strm->zalloc = zcalloc;
        strm->opaque = (voidpf)0;
    }
    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
    state = (struct inflate_state FAR *)
            ZALLOC(strm, 1, sizeof(struct inflate_state));
    if (state == Z_NULL) return Z_MEM_ERROR;
    Tracev((stderr, "inflate: allocated\n"));
    strm->state = (struct internal_state FAR *)state;
    state->window = Z_NULL;
    ret = inflateReset2(strm, windowBits);
    if (ret != Z_OK) {
        ZFREE(strm, state);
        strm->state = Z_NULL;
    }
    return ret;
}

int ZEXPORT inflateInit_(strm, version, stream_size)
z_streamp strm;
const char *version;
int stream_size;
{
    return inflateInit2_(strm, DEF_WBITS, version, stream_size);
}

int ZEXPORT inflatePrime(strm, bits, value)
z_streamp strm;
int bits;
int value;
{
    struct inflate_state FAR *state;

    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
    state = (struct inflate_state FAR *)strm->state;
    if (bits < 0) {
        state->hold = 0;
        state->bits = 0;
        return Z_OK;
    }
    if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
    value &= (1L << bits) - 1;
    state->hold += value << state->bits;
    state->bits += bits;
    return Z_OK;
}

/*
   Return state with length and distance decoding tables and index sizes set to
   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
   If BUILDFIXED is defined, then instead this routine builds the tables the
   first time it's called, and returns those tables the first time and
   thereafter.  This reduces the size of the code by about 2K bytes, in
   exchange for a little execution time.  However, BUILDFIXED should not be
   used for threaded applications, since the rewriting of the tables and virgin
   may not be thread-safe.
 */
local void fixedtables(state)
struct inflate_state FAR *state;
{
#ifdef BUILDFIXED
    static int virgin = 1;
    static code *lenfix, *distfix;
    static code fixed[544];

    /* build fixed huffman tables if first call (may not be thread safe) */
    if (virgin) {
        unsigned sym, bits;
        static code *next;

        /* literal/length table */
        sym = 0;
        while (sym < 144) state->lens[sym++] = 8;
        while (sym < 256) state->lens[sym++] = 9;
        while (sym < 280) state->lens[sym++] = 7;
        while (sym < 288) state->lens[sym++] = 8;
        next = fixed;
        lenfix = next;
        bits = 9;
        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);

        /* distance table */
        sym = 0;
        while (sym < 32) state->lens[sym++] = 5;
        distfix = next;
        bits = 5;
        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);

        /* do this just once */
        virgin = 0;
    }
#else /* !BUILDFIXED */
#   include "inffixed.h"
#endif /* BUILDFIXED */
    state->lencode = lenfix;
    state->lenbits = 9;
    state->distcode = distfix;
    state->distbits = 5;
}

#ifdef MAKEFIXED
#include 

/*
   Write out the inffixed.h that is #include'd above.  Defining MAKEFIXED also
   defines BUILDFIXED, so the tables are built on the fly.  makefixed() writes
   those tables to stdout, which would be piped to inffixed.h.  A small program
   can simply call makefixed to do this:

    void makefixed(void);

    int main(void)
    {
        makefixed();
        return 0;
    }

   Then that can be linked with zlib built with MAKEFIXED defined and run:

    a.out > inffixed.h
 */
void makefixed()
{
    unsigned low, size;
    struct inflate_state state;

    fixedtables(&state);
    puts("    /* inffixed.h -- table for decoding fixed codes");
    puts("     * Generated automatically by makefixed().");
    puts("     */");
    puts("");
    puts("    /* WARNING: this file should *not* be used by applications.");
    puts("       It is part of the implementation of this library and is");
    puts("       subject to change. Applications should only use zlib.h.");
    puts("     */");
    puts("");
    size = 1U << 9;
    printf("    static const code lenfix[%u] = {", size);
    low = 0;
    for (;;) {
        if ((low % 7) == 0) printf("\n        ");
        printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits,
               state.lencode[low].val);
        if (++low == size) break;
        putchar(',');
    }
    puts("\n    };");
    size = 1U << 5;
    printf("\n    static const code distfix[%u] = {", size);
    low = 0;
    for (;;) {
        if ((low % 6) == 0) printf("\n        ");
        printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
               state.distcode[low].val);
        if (++low == size) break;
        putchar(',');
    }
    puts("\n    };");
}
#endif /* MAKEFIXED */

/*
   Update the window with the last wsize (normally 32K) bytes written before
   returning.  If window does not exist yet, create it.  This is only called
   when a window is already in use, or when output has been written during this
   inflate call, but the end of the deflate stream has not been reached yet.
   It is also called to create a window for dictionary data when a dictionary
   is loaded.

   Providing output buffers larger than 32K to inflate() should provide a speed
   advantage, since only the last 32K of output is copied to the sliding window
   upon return from inflate(), and since all distances after the first 32K of
   output will fall in the output data, making match copies simpler and faster.
   The advantage may be dependent on the size of the processor's data caches.
 */
local int updatewindow(strm, out)
z_streamp strm;
unsigned out;
{
    struct inflate_state FAR *state;
    unsigned copy, dist;

    state = (struct inflate_state FAR *)strm->state;

    /* if it hasn't been done already, allocate space for the window */
    if (state->window == Z_NULL) {
        state->window = (unsigned char FAR *)
                        ZALLOC(strm, 1U << state->wbits,
                               sizeof(unsigned char));
        if (state->window == Z_NULL) return 1;
    }

    /* if window not in use yet, initialize */
    if (state->wsize == 0) {
        state->wsize = 1U << state->wbits;
        state->wnext = 0;
        state->whave = 0;
    }

    /* copy state->wsize or less output bytes into the circular window */
    copy = out - strm->avail_out;
    if (copy >= state->wsize) {
        zmemcpy(state->window, strm->next_out - state->wsize, state->wsize);
        state->wnext = 0;
        state->whave = state->wsize;
    }
    else {
        dist = state->wsize - state->wnext;
        if (dist > copy) dist = copy;
        zmemcpy(state->window + state->wnext, strm->next_out - copy, dist);
        copy -= dist;
        if (copy) {
            zmemcpy(state->window, strm->next_out - copy, copy);
            state->wnext = copy;
            state->whave = state->wsize;
        }
        else {
            state->wnext += dist;
            if (state->wnext == state->wsize) state->wnext = 0;
            if (state->whave < state->wsize) state->whave += dist;
        }
    }
    return 0;
}

/* Macros for inflate(): */

/* check function to use adler32() for zlib or crc32() for gzip */
#ifdef GUNZIP
#  define UPDATE(check, buf, len) \
    (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
#else
#  define UPDATE(check, buf, len) adler32(check, buf, len)
#endif

/* check macros for header crc */
#ifdef GUNZIP
#  define CRC2(check, word) \
    do { \
        hbuf[0] = (unsigned char)(word); \
        hbuf[1] = (unsigned char)((word) >> 8); \
        check = crc32(check, hbuf, 2); \
    } while (0)

#  define CRC4(check, word) \
    do { \
        hbuf[0] = (unsigned char)(word); \
        hbuf[1] = (unsigned char)((word) >> 8); \
        hbuf[2] = (unsigned char)((word) >> 16); \
        hbuf[3] = (unsigned char)((word) >> 24); \
        check = crc32(check, hbuf, 4); \
    } while (0)
#endif

/* Load registers with state in inflate() for speed */
#define LOAD() \
    do { \
        put = strm->next_out; \
        left = strm->avail_out; \
        next = strm->next_in; \
        have = strm->avail_in; \
        hold = state->hold; \
        bits = state->bits; \
    } while (0)

/* Restore state from registers in inflate() */
#define RESTORE() \
    do { \
        strm->next_out = put; \
        strm->avail_out = left; \
        strm->next_in = next; \
        strm->avail_in = have; \
        state->hold = hold; \
        state->bits = bits; \
    } while (0)

/* Clear the input bit accumulator */
#define INITBITS() \
    do { \
        hold = 0; \
        bits = 0; \
    } while (0)

/* Get a byte of input into the bit accumulator, or return from inflate()
   if there is no input available. */
#define PULLBYTE() \
    do { \
        if (have == 0) goto inf_leave; \
        have--; \
        hold += (unsigned long)(*next++) << bits; \
        bits += 8; \
    } while (0)

/* Assure that there are at least n bits in the bit accumulator.  If there is
   not enough available input to do that, then return from inflate(). */
#define NEEDBITS(n) \
    do { \
        while (bits < (unsigned)(n)) \
            PULLBYTE(); \
    } while (0)

/* Return the low n bits of the bit accumulator (n < 16) */
#define BITS(n) \
    ((unsigned)hold & ((1U << (n)) - 1))

/* Remove n bits from the bit accumulator */
#define DROPBITS(n) \
    do { \
        hold >>= (n); \
        bits -= (unsigned)(n); \
    } while (0)

/* Remove zero to seven bits as needed to go to a byte boundary */
#define BYTEBITS() \
    do { \
        hold >>= bits & 7; \
        bits -= bits & 7; \
    } while (0)

/* Reverse the bytes in a 32-bit value */
#define REVERSE(q) \
    ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
     (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))

/*
   inflate() uses a state machine to process as much input data and generate as
   much output data as possible before returning.  The state machine is
   structured roughly as follows:

    for (;;) switch (state) {
    ...
    case STATEn:
        if (not enough input data or output space to make progress)
            return;
        ... make progress ...
        state = STATEm;
        break;
    ...
    }

   so when inflate() is called again, the same case is attempted again, and
   if the appropriate resources are provided, the machine proceeds to the
   next state.  The NEEDBITS() macro is usually the way the state evaluates
   whether it can proceed or should return.  NEEDBITS() does the return if
   the requested bits are not available.  The typical use of the BITS macros
   is:

        NEEDBITS(n);
        ... do something with BITS(n) ...
        DROPBITS(n);

   where NEEDBITS(n) either returns from inflate() if there isn't enough
   input left to load n bits into the accumulator, or it continues.  BITS(n)
   gives the low n bits in the accumulator.  When done, DROPBITS(n) drops
   the low n bits off the accumulator.  INITBITS() clears the accumulator
   and sets the number of available bits to zero.  BYTEBITS() discards just
   enough bits to put the accumulator on a byte boundary.  After BYTEBITS()
   and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.

   NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
   if there is no input available.  The decoding of variable length codes uses
   PULLBYTE() directly in order to pull just enough bytes to decode the next
   code, and no more.

   Some states loop until they get enough input, making sure that enough
   state information is maintained to continue the loop where it left off
   if NEEDBITS() returns in the loop.  For example, want, need, and keep
   would all have to actually be part of the saved state in case NEEDBITS()
   returns:

    case STATEw:
        while (want < need) {
            NEEDBITS(n);
            keep[want++] = BITS(n);
            DROPBITS(n);
        }
        state = STATEx;
    case STATEx:

   As shown above, if the next state is also the next case, then the break
   is omitted.

   A state may also return if there is not enough output space available to
   complete that state.  Those states are copying stored data, writing a
   literal byte, and copying a matching string.

   When returning, a "goto inf_leave" is used to update the total counters,
   update the check value, and determine whether any progress has been made
   during that inflate() call in order to return the proper return code.
   Progress is defined as a change in either strm->avail_in or strm->avail_out.
   When there is a window, goto inf_leave will update the window with the last
   output written.  If a goto inf_leave occurs in the middle of decompression
   and there is no window currently, goto inf_leave will create one and copy
   output to the window for the next call of inflate().

   In this implementation, the flush parameter of inflate() only affects the
   return code (per zlib.h).  inflate() always writes as much as possible to
   strm->next_out, given the space available and the provided input--the effect
   documented in zlib.h of Z_SYNC_FLUSH.  Furthermore, inflate() always defers
   the allocation of and copying into a sliding window until necessary, which
   provides the effect documented in zlib.h for Z_FINISH when the entire input
   stream available.  So the only thing the flush parameter actually does is:
   when flush is set to Z_FINISH, inflate() cannot return Z_OK.  Instead it
   will return Z_BUF_ERROR if it has not reached the end of the stream.
 */

int ZEXPORT inflate(strm, flush)
z_streamp strm;
int flush;
{
    struct inflate_state FAR *state;
    unsigned char FAR *next;    /* next input */
    unsigned char FAR *put;     /* next output */
    unsigned have, left;        /* available input and output */
    unsigned long hold;         /* bit buffer */
    unsigned bits;              /* bits in bit buffer */
    unsigned in, out;           /* save starting available input and output */
    unsigned copy;              /* number of stored or match bytes to copy */
    unsigned char FAR *from;    /* where to copy match bytes from */
    code here;                  /* current decoding table entry */
    code last;                  /* parent table entry */
    unsigned len;               /* length to copy for repeats, bits to drop */
    int ret;                    /* return code */
#ifdef GUNZIP
    unsigned char hbuf[4];      /* buffer for gzip header crc calculation */
#endif
    static const unsigned short order[19] = /* permutation of code lengths */
        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};

    if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL ||
        (strm->next_in == Z_NULL && strm->avail_in != 0))
        return Z_STREAM_ERROR;

    state = (struct inflate_state FAR *)strm->state;
    if (state->mode == TYPE) state->mode = TYPEDO;      /* skip check */
    LOAD();
    in = have;
    out = left;
    ret = Z_OK;
    for (;;)
        switch (state->mode) {
        case HEAD:
            if (state->wrap == 0) {
                state->mode = TYPEDO;
                break;
            }
            NEEDBITS(16);
#ifdef GUNZIP
            if ((state->wrap & 2) && hold == 0x8b1f) {  /* gzip header */
                state->check = crc32(0L, Z_NULL, 0);
                CRC2(state->check, hold);
                INITBITS();
                state->mode = FLAGS;
                break;
            }
            state->flags = 0;           /* expect zlib header */
            if (state->head != Z_NULL)
                state->head->done = -1;
            if (!(state->wrap & 1) ||   /* check if zlib header allowed */
#else
            if (
#endif
                ((BITS(8) << 8) + (hold >> 8)) % 31) {
                strm->msg = (char *)"incorrect header check";
                state->mode = BAD;
                break;
            }
            if (BITS(4) != Z_DEFLATED) {
                strm->msg = (char *)"unknown compression method";
                state->mode = BAD;
                break;
            }
            DROPBITS(4);
            len = BITS(4) + 8;
            if (state->wbits == 0)
                state->wbits = len;
            else if (len > state->wbits) {
                strm->msg = (char *)"invalid window size";
                state->mode = BAD;
                break;
            }
            state->dmax = 1U << len;
            Tracev((stderr, "inflate:   zlib header ok\n"));
            strm->adler = state->check = adler32(0L, Z_NULL, 0);
            state->mode = hold & 0x200 ? DICTID : TYPE;
            INITBITS();
            break;
#ifdef GUNZIP
        case FLAGS:
            NEEDBITS(16);
            state->flags = (int)(hold);
            if ((state->flags & 0xff) != Z_DEFLATED) {
                strm->msg = (char *)"unknown compression method";
                state->mode = BAD;
                break;
            }
            if (state->flags & 0xe000) {
                strm->msg = (char *)"unknown header flags set";
                state->mode = BAD;
                break;
            }
            if (state->head != Z_NULL)
                state->head->text = (int)((hold >> 8) & 1);
            if (state->flags & 0x0200) CRC2(state->check, hold);
            INITBITS();
            state->mode = TIME;
        case TIME:
            NEEDBITS(32);
            if (state->head != Z_NULL)
                state->head->time = hold;
            if (state->flags & 0x0200) CRC4(state->check, hold);
            INITBITS();
            state->mode = OS;
        case OS:
            NEEDBITS(16);
            if (state->head != Z_NULL) {
                state->head->xflags = (int)(hold & 0xff);
                state->head->os = (int)(hold >> 8);
            }
            if (state->flags & 0x0200) CRC2(state->check, hold);
            INITBITS();
            state->mode = EXLEN;
        case EXLEN:
            if (state->flags & 0x0400) {
                NEEDBITS(16);
                state->length = (unsigned)(hold);
                if (state->head != Z_NULL)
                    state->head->extra_len = (unsigned)hold;
                if (state->flags & 0x0200) CRC2(state->check, hold);
                INITBITS();
            }
            else if (state->head != Z_NULL)
                state->head->extra = Z_NULL;
            state->mode = EXTRA;
        case EXTRA:
            if (state->flags & 0x0400) {
                copy = state->length;
                if (copy > have) copy = have;
                if (copy) {
                    if (state->head != Z_NULL &&
                        state->head->extra != Z_NULL) {
                        len = state->head->extra_len - state->length;
                        zmemcpy(state->head->extra + len, next,
                                len + copy > state->head->extra_max ?
                                state->head->extra_max - len : copy);
                    }
                    if (state->flags & 0x0200)
                        state->check = crc32(state->check, next, copy);
                    have -= copy;
                    next += copy;
                    state->length -= copy;
                }
                if (state->length) goto inf_leave;
            }
            state->length = 0;
            state->mode = NAME;
        case NAME:
            if (state->flags & 0x0800) {
                if (have == 0) goto inf_leave;
                copy = 0;
                do {
                    len = (unsigned)(next[copy++]);
                    if (state->head != Z_NULL &&
                            state->head->name != Z_NULL &&
                            state->length < state->head->name_max)
                        state->head->name[state->length++] = len;
                } while (len && copy < have);
                if (state->flags & 0x0200)
                    state->check = crc32(state->check, next, copy);
                have -= copy;
                next += copy;
                if (len) goto inf_leave;
            }
            else if (state->head != Z_NULL)
                state->head->name = Z_NULL;
            state->length = 0;
            state->mode = COMMENT;
        case COMMENT:
            if (state->flags & 0x1000) {
                if (have == 0) goto inf_leave;
                copy = 0;
                do {
                    len = (unsigned)(next[copy++]);
                    if (state->head != Z_NULL &&
                            state->head->comment != Z_NULL &&
                            state->length < state->head->comm_max)
                        state->head->comment[state->length++] = len;
                } while (len && copy < have);
                if (state->flags & 0x0200)
                    state->check = crc32(state->check, next, copy);
                have -= copy;
                next += copy;
                if (len) goto inf_leave;
            }
            else if (state->head != Z_NULL)
                state->head->comment = Z_NULL;
            state->mode = HCRC;
        case HCRC:
            if (state->flags & 0x0200) {
                NEEDBITS(16);
                if (hold != (state->check & 0xffff)) {
                    strm->msg = (char *)"header crc mismatch";
                    state->mode = BAD;
                    break;
                }
                INITBITS();
            }
            if (state->head != Z_NULL) {
                state->head->hcrc = (int)((state->flags >> 9) & 1);
                state->head->done = 1;
            }
            strm->adler = state->check = crc32(0L, Z_NULL, 0);
            state->mode = TYPE;
            break;
#endif
        case DICTID:
            NEEDBITS(32);
            strm->adler = state->check = REVERSE(hold);
            INITBITS();
            state->mode = DICT;
        case DICT:
            if (state->havedict == 0) {
                RESTORE();
                return Z_NEED_DICT;
            }
            strm->adler = state->check = adler32(0L, Z_NULL, 0);
            state->mode = TYPE;
        case TYPE:
            if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
        case TYPEDO:
            if (state->last) {
                BYTEBITS();
                state->mode = CHECK;
                break;
            }
            NEEDBITS(3);
            state->last = BITS(1);
            DROPBITS(1);
            switch (BITS(2)) {
            case 0:                             /* stored block */
                Tracev((stderr, "inflate:     stored block%s\n",
                        state->last ? " (last)" : ""));
                state->mode = STORED;
                break;
            case 1:                             /* fixed block */
                fixedtables(state);
                Tracev((stderr, "inflate:     fixed codes block%s\n",
                        state->last ? " (last)" : ""));
                state->mode = LEN_;             /* decode codes */
                if (flush == Z_TREES) {
                    DROPBITS(2);
                    goto inf_leave;
                }
                break;
            case 2:                             /* dynamic block */
                Tracev((stderr, "inflate:     dynamic codes block%s\n",
                        state->last ? " (last)" : ""));
                state->mode = TABLE;
                break;
            case 3:
                strm->msg = (char *)"invalid block type";
                state->mode = BAD;
            }
            DROPBITS(2);
            break;
        case STORED:
            BYTEBITS();                         /* go to byte boundary */
            NEEDBITS(32);
            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
                strm->msg = (char *)"invalid stored block lengths";
                state->mode = BAD;
                break;
            }
            state->length = (unsigned)hold & 0xffff;
            Tracev((stderr, "inflate:       stored length %u\n",
                    state->length));
            INITBITS();
            state->mode = COPY_;
            if (flush == Z_TREES) goto inf_leave;
        case COPY_:
            state->mode = COPY;
        case COPY:
            copy = state->length;
            if (copy) {
                if (copy > have) copy = have;
                if (copy > left) copy = left;
                if (copy == 0) goto inf_leave;
                zmemcpy(put, next, copy);
                have -= copy;
                next += copy;
                left -= copy;
                put += copy;
                state->length -= copy;
                break;
            }
            Tracev((stderr, "inflate:       stored end\n"));
            state->mode = TYPE;
            break;
        case TABLE:
            NEEDBITS(14);
            state->nlen = BITS(5) + 257;
            DROPBITS(5);
            state->ndist = BITS(5) + 1;
            DROPBITS(5);
            state->ncode = BITS(4) + 4;
            DROPBITS(4);
#ifndef PKZIP_BUG_WORKAROUND
            if (state->nlen > 286 || state->ndist > 30) {
                strm->msg = (char *)"too many length or distance symbols";
                state->mode = BAD;
                break;
            }
#endif
            Tracev((stderr, "inflate:       table sizes ok\n"));
            state->have = 0;
            state->mode = LENLENS;
        case LENLENS:
            while (state->have < state->ncode) {
                NEEDBITS(3);
                state->lens[order[state->have++]] = (unsigned short)BITS(3);
                DROPBITS(3);
            }
            while (state->have < 19)
                state->lens[order[state->have++]] = 0;
            state->next = state->codes;
            state->lencode = (code const FAR *)(state->next);
            state->lenbits = 7;
            ret = inflate_table(CODES, state->lens, 19, &(state->next),
                                &(state->lenbits), state->work);
            if (ret) {
                strm->msg = (char *)"invalid code lengths set";
                state->mode = BAD;
                break;
            }
            Tracev((stderr, "inflate:       code lengths ok\n"));
            state->have = 0;
            state->mode = CODELENS;
        case CODELENS:
            while (state->have < state->nlen + state->ndist) {
                for (;;) {
                    here = state->lencode[BITS(state->lenbits)];
                    if ((unsigned)(here.bits) <= bits) break;
                    PULLBYTE();
                }
                if (here.val < 16) {
                    NEEDBITS(here.bits);
                    DROPBITS(here.bits);
                    state->lens[state->have++] = here.val;
                }
                else {
                    if (here.val == 16) {
                        NEEDBITS(here.bits + 2);
                        DROPBITS(here.bits);
                        if (state->have == 0) {
                            strm->msg = (char *)"invalid bit length repeat";
                            state->mode = BAD;
                            break;
                        }
                        len = state->lens[state->have - 1];
                        copy = 3 + BITS(2);
                        DROPBITS(2);
                    }
                    else if (here.val == 17) {
                        NEEDBITS(here.bits + 3);
                        DROPBITS(here.bits);
                        len = 0;
                        copy = 3 + BITS(3);
                        DROPBITS(3);
                    }
                    else {
                        NEEDBITS(here.bits + 7);
                        DROPBITS(here.bits);
                        len = 0;
                        copy = 11 + BITS(7);
                        DROPBITS(7);
                    }
                    if (state->have + copy > state->nlen + state->ndist) {
                        strm->msg = (char *)"invalid bit length repeat";
                        state->mode = BAD;
                        break;
                    }
                    while (copy--)
                        state->lens[state->have++] = (unsigned short)len;
                }
            }

            /* handle error breaks in while */
            if (state->mode == BAD) break;

            /* check for end-of-block code (better have one) */
            if (state->lens[256] == 0) {
                strm->msg = (char *)"invalid code -- missing end-of-block";
                state->mode = BAD;
                break;
            }

            /* build code tables -- note: do not change the lenbits or distbits
               values here (9 and 6) without reading the comments in inftrees.h
               concerning the ENOUGH constants, which depend on those values */
            state->next = state->codes;
            state->lencode = (code const FAR *)(state->next);
            state->lenbits = 9;
            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
                                &(state->lenbits), state->work);
            if (ret) {
                strm->msg = (char *)"invalid literal/lengths set";
                state->mode = BAD;
                break;
            }
            state->distcode = (code const FAR *)(state->next);
            state->distbits = 6;
            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
                            &(state->next), &(state->distbits), state->work);
            if (ret) {
                strm->msg = (char *)"invalid distances set";
                state->mode = BAD;
                break;
            }
            Tracev((stderr, "inflate:       codes ok\n"));
            state->mode = LEN_;
            if (flush == Z_TREES) goto inf_leave;
        case LEN_:
            state->mode = LEN;
        case LEN:
            if (have >= 6 && left >= 258) {
                RESTORE();
                inflate_fast(strm, out);
                LOAD();
                if (state->mode == TYPE)
                    state->back = -1;
                break;
            }
            state->back = 0;
            for (;;) {
                here = state->lencode[BITS(state->lenbits)];
                if ((unsigned)(here.bits) <= bits) break;
                PULLBYTE();
            }
            if (here.op && (here.op & 0xf0) == 0) {
                last = here;
                for (;;) {
                    here = state->lencode[last.val +
                            (BITS(last.bits + last.op) >> last.bits)];
                    if ((unsigned)(last.bits + here.bits) <= bits) break;
                    PULLBYTE();
                }
                DROPBITS(last.bits);
                state->back += last.bits;
            }
            DROPBITS(here.bits);
            state->back += here.bits;
            state->length = (unsigned)here.val;
            if ((int)(here.op) == 0) {
                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
                        "inflate:         literal '%c'\n" :
                        "inflate:         literal 0x%02x\n", here.val));
                state->mode = LIT;
                break;
            }
            if (here.op & 32) {
                Tracevv((stderr, "inflate:         end of block\n"));
                state->back = -1;
                state->mode = TYPE;
                break;
            }
            if (here.op & 64) {
                strm->msg = (char *)"invalid literal/length code";
                state->mode = BAD;
                break;
            }
            state->extra = (unsigned)(here.op) & 15;
            state->mode = LENEXT;
        case LENEXT:
            if (state->extra) {
                NEEDBITS(state->extra);
                state->length += BITS(state->extra);
                DROPBITS(state->extra);
                state->back += state->extra;
            }
            Tracevv((stderr, "inflate:         length %u\n", state->length));
            state->was = state->length;
            state->mode = DIST;
        case DIST:
            for (;;) {
                here = state->distcode[BITS(state->distbits)];
                if ((unsigned)(here.bits) <= bits) break;
                PULLBYTE();
            }
            if ((here.op & 0xf0) == 0) {
                last = here;
                for (;;) {
                    here = state->distcode[last.val +
                            (BITS(last.bits + last.op) >> last.bits)];
                    if ((unsigned)(last.bits + here.bits) <= bits) break;
                    PULLBYTE();
                }
                DROPBITS(last.bits);
                state->back += last.bits;
            }
            DROPBITS(here.bits);
            state->back += here.bits;
            if (here.op & 64) {
                strm->msg = (char *)"invalid distance code";
                state->mode = BAD;
                break;
            }
            state->offset = (unsigned)here.val;
            state->extra = (unsigned)(here.op) & 15;
            state->mode = DISTEXT;
        case DISTEXT:
            if (state->extra) {
                NEEDBITS(state->extra);
                state->offset += BITS(state->extra);
                DROPBITS(state->extra);
                state->back += state->extra;
            }
#ifdef INFLATE_STRICT
            if (state->offset > state->dmax) {
                strm->msg = (char *)"invalid distance too far back";
                state->mode = BAD;
                break;
            }
#endif
            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
            state->mode = MATCH;
        case MATCH:
            if (left == 0) goto inf_leave;
            copy = out - left;
            if (state->offset > copy) {         /* copy from window */
                copy = state->offset - copy;
                if (copy > state->whave) {
                    if (state->sane) {
                        strm->msg = (char *)"invalid distance too far back";
                        state->mode = BAD;
                        break;
                    }
#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
                    Trace((stderr, "inflate.c too far\n"));
                    copy -= state->whave;
                    if (copy > state->length) copy = state->length;
                    if (copy > left) copy = left;
                    left -= copy;
                    state->length -= copy;
                    do {
                        *put++ = 0;
                    } while (--copy);
                    if (state->length == 0) state->mode = LEN;
                    break;
#endif
                }
                if (copy > state->wnext) {
                    copy -= state->wnext;
                    from = state->window + (state->wsize - copy);
                }
                else
                    from = state->window + (state->wnext - copy);
                if (copy > state->length) copy = state->length;
            }
            else {                              /* copy from output */
                from = put - state->offset;
                copy = state->length;
            }
            if (copy > left) copy = left;
            left -= copy;
            state->length -= copy;
            do {
                *put++ = *from++;
            } while (--copy);
            if (state->length == 0) state->mode = LEN;
            break;
        case LIT:
            if (left == 0) goto inf_leave;
            *put++ = (unsigned char)(state->length);
            left--;
            state->mode = LEN;
            break;
        case CHECK:
            if (state->wrap) {
                NEEDBITS(32);
                out -= left;
                strm->total_out += out;
                state->total += out;
                if (out)
                    strm->adler = state->check =
                        UPDATE(state->check, put - out, out);
                out = left;
                if ((
#ifdef GUNZIP
                     state->flags ? hold :
#endif
                     REVERSE(hold)) != state->check) {
                    strm->msg = (char *)"incorrect data check";
                    state->mode = BAD;
                    break;
                }
                INITBITS();
                Tracev((stderr, "inflate:   check matches trailer\n"));
            }
#ifdef GUNZIP
            state->mode = LENGTH;
        case LENGTH:
            if (state->wrap && state->flags) {
                NEEDBITS(32);
                if (hold != (state->total & 0xffffffffUL)) {
                    strm->msg = (char *)"incorrect length check";
                    state->mode = BAD;
                    break;
                }
                INITBITS();
                Tracev((stderr, "inflate:   length matches trailer\n"));
            }
#endif
            state->mode = DONE;
        case DONE:
            ret = Z_STREAM_END;
            goto inf_leave;
        case BAD:
            ret = Z_DATA_ERROR;
            goto inf_leave;
        case MEM:
            return Z_MEM_ERROR;
        case SYNC:
        default:
            return Z_STREAM_ERROR;
        }

    /*
       Return from inflate(), updating the total counts and the check value.
       If there was no progress during the inflate() call, return a buffer
       error.  Call updatewindow() to create and/or update the window state.
       Note: a memory error from inflate() is non-recoverable.
     */
  inf_leave:
    RESTORE();
    if (state->wsize || (state->mode < CHECK && out != strm->avail_out))
        if (updatewindow(strm, out)) {
            state->mode = MEM;
            return Z_MEM_ERROR;
        }
    in -= strm->avail_in;
    out -= strm->avail_out;
    strm->total_in += in;
    strm->total_out += out;
    state->total += out;
    if (state->wrap && out)
        strm->adler = state->check =
            UPDATE(state->check, strm->next_out - out, out);
    strm->data_type = state->bits + (state->last ? 64 : 0) +
                      (state->mode == TYPE ? 128 : 0) +
                      (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
    if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
        ret = Z_BUF_ERROR;
    return ret;
}

int ZEXPORT inflateEnd(strm)
z_streamp strm;
{
    struct inflate_state FAR *state;
    if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
        return Z_STREAM_ERROR;
    state = (struct inflate_state FAR *)strm->state;
    if (state->window != Z_NULL) ZFREE(strm, state->window);
    ZFREE(strm, strm->state);
    strm->state = Z_NULL;
    Tracev((stderr, "inflate: end\n"));
    return Z_OK;
}

int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
z_streamp strm;
const Bytef *dictionary;
uInt dictLength;
{
    struct inflate_state FAR *state;
    unsigned long id;

    /* check state */
    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
    state = (struct inflate_state FAR *)strm->state;
    if (state->wrap != 0 && state->mode != DICT)
        return Z_STREAM_ERROR;

    /* check for correct dictionary id */
    if (state->mode == DICT) {
        id = adler32(0L, Z_NULL, 0);
        id = adler32(id, dictionary, dictLength);
        if (id != state->check)
            return Z_DATA_ERROR;
    }

    /* copy dictionary to window */
    if (updatewindow(strm, strm->avail_out)) {
        state->mode = MEM;
        return Z_MEM_ERROR;
    }
    if (dictLength > state->wsize) {
        zmemcpy(state->window, dictionary + dictLength - state->wsize,
                state->wsize);
        state->whave = state->wsize;
    }
    else {
        zmemcpy(state->window + state->wsize - dictLength, dictionary,
                dictLength);
        state->whave = dictLength;
    }
    state->havedict = 1;
    Tracev((stderr, "inflate:   dictionary set\n"));
    return Z_OK;
}

int ZEXPORT inflateGetHeader(strm, head)
z_streamp strm;
gz_headerp head;
{
    struct inflate_state FAR *state;

    /* check state */
    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
    state = (struct inflate_state FAR *)strm->state;
    if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;

    /* save header structure */
    state->head = head;
    head->done = 0;
    return Z_OK;
}

/*
   Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff.  Return when found
   or when out of input.  When called, *have is the number of pattern bytes
   found in order so far, in 0..3.  On return *have is updated to the new
   state.  If on return *have equals four, then the pattern was found and the
   return value is how many bytes were read including the last byte of the
   pattern.  If *have is less than four, then the pattern has not been found
   yet and the return value is len.  In the latter case, syncsearch() can be
   called again with more data and the *have state.  *have is initialized to
   zero for the first call.
 */
local unsigned syncsearch(have, buf, len)
unsigned FAR *have;
unsigned char FAR *buf;
unsigned len;
{
    unsigned got;
    unsigned next;

    got = *have;
    next = 0;
    while (next < len && got < 4) {
        if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
            got++;
        else if (buf[next])
            got = 0;
        else
            got = 4 - got;
        next++;
    }
    *have = got;
    return next;
}

int ZEXPORT inflateSync(strm)
z_streamp strm;
{
    unsigned len;               /* number of bytes to look at or looked at */
    unsigned long in, out;      /* temporary to save total_in and total_out */
    unsigned char buf[4];       /* to restore bit buffer to byte string */
    struct inflate_state FAR *state;

    /* check parameters */
    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
    state = (struct inflate_state FAR *)strm->state;
    if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;

    /* if first time, start search in bit buffer */
    if (state->mode != SYNC) {
        state->mode = SYNC;
        state->hold <<= state->bits & 7;
        state->bits -= state->bits & 7;
        len = 0;
        while (state->bits >= 8) {
            buf[len++] = (unsigned char)(state->hold);
            state->hold >>= 8;
            state->bits -= 8;
        }
        state->have = 0;
        syncsearch(&(state->have), buf, len);
    }

    /* search available input */
    len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
    strm->avail_in -= len;
    strm->next_in += len;
    strm->total_in += len;

    /* return no joy or set up to restart inflate() on a new block */
    if (state->have != 4) return Z_DATA_ERROR;
    in = strm->total_in;  out = strm->total_out;
    inflateReset(strm);
    strm->total_in = in;  strm->total_out = out;
    state->mode = TYPE;
    return Z_OK;
}

/*
   Returns true if inflate is currently at the end of a block generated by
   Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
   implementation to provide an additional safety check. PPP uses
   Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
   block. When decompressing, PPP checks that at the end of input packet,
   inflate is waiting for these length bytes.
 */
int ZEXPORT inflateSyncPoint(strm)
z_streamp strm;
{
    struct inflate_state FAR *state;

    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
    state = (struct inflate_state FAR *)strm->state;
    return state->mode == STORED && state->bits == 0;
}

int ZEXPORT inflateCopy(dest, source)
z_streamp dest;
z_streamp source;
{
    struct inflate_state FAR *state;
    struct inflate_state FAR *copy;
    unsigned char FAR *window;
    unsigned wsize;

    /* check input */
    if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL ||
        source->zalloc == (alloc_func)0 || source->zfree == (free_func)0)
        return Z_STREAM_ERROR;
    state = (struct inflate_state FAR *)source->state;

    /* allocate space */
    copy = (struct inflate_state FAR *)
           ZALLOC(source, 1, sizeof(struct inflate_state));
    if (copy == Z_NULL) return Z_MEM_ERROR;
    window = Z_NULL;
    if (state->window != Z_NULL) {
        window = (unsigned char FAR *)
                 ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
        if (window == Z_NULL) {
            ZFREE(source, copy);
            return Z_MEM_ERROR;
        }
    }

    /* copy state */
    zmemcpy(dest, source, sizeof(z_stream));
    zmemcpy(copy, state, sizeof(struct inflate_state));
    if (state->lencode >= state->codes &&
        state->lencode <= state->codes + ENOUGH - 1) {
        copy->lencode = copy->codes + (state->lencode - state->codes);
        copy->distcode = copy->codes + (state->distcode - state->codes);
    }
    copy->next = copy->codes + (state->next - state->codes);
    if (window != Z_NULL) {
        wsize = 1U << state->wbits;
        zmemcpy(window, state->window, wsize);
    }
    copy->window = window;
    dest->state = (struct internal_state FAR *)copy;
    return Z_OK;
}

int ZEXPORT inflateUndermine(strm, subvert)
z_streamp strm;
int subvert;
{
    struct inflate_state FAR *state;

    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
    state = (struct inflate_state FAR *)strm->state;
    state->sane = !subvert;
#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
    return Z_OK;
#else
    state->sane = 1;
    return Z_DATA_ERROR;
#endif
}

long ZEXPORT inflateMark(strm)
z_streamp strm;
{
    struct inflate_state FAR *state;

    if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16;
    state = (struct inflate_state FAR *)strm->state;
    return ((long)(state->back) << 16) +
        (state->mode == COPY ? state->length :
            (state->mode == MATCH ? state->was - state->length : 0));
}
cfitsio/zlib/inflate.h0000644000225700000360000001437713246025103014547 0ustar  cagordonlhea/* inflate.h -- internal inflate state definition
 * Copyright (C) 1995-2009 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

/* WARNING: this file should *not* be used by applications. It is
   part of the implementation of the compression library and is
   subject to change. Applications should only use zlib.h.
 */

/* define NO_GZIP when compiling if you want to disable gzip header and
   trailer decoding by inflate().  NO_GZIP would be used to avoid linking in
   the crc code when it is not needed.  For shared libraries, gzip decoding
   should be left enabled. */
#ifndef NO_GZIP
#  define GUNZIP
#endif

/* Possible inflate modes between inflate() calls */
typedef enum {
    HEAD,       /* i: waiting for magic header */
    FLAGS,      /* i: waiting for method and flags (gzip) */
    TIME,       /* i: waiting for modification time (gzip) */
    OS,         /* i: waiting for extra flags and operating system (gzip) */
    EXLEN,      /* i: waiting for extra length (gzip) */
    EXTRA,      /* i: waiting for extra bytes (gzip) */
    NAME,       /* i: waiting for end of file name (gzip) */
    COMMENT,    /* i: waiting for end of comment (gzip) */
    HCRC,       /* i: waiting for header crc (gzip) */
    DICTID,     /* i: waiting for dictionary check value */
    DICT,       /* waiting for inflateSetDictionary() call */
        TYPE,       /* i: waiting for type bits, including last-flag bit */
        TYPEDO,     /* i: same, but skip check to exit inflate on new block */
        STORED,     /* i: waiting for stored size (length and complement) */
        COPY_,      /* i/o: same as COPY below, but only first time in */
        COPY,       /* i/o: waiting for input or output to copy stored block */
        TABLE,      /* i: waiting for dynamic block table lengths */
        LENLENS,    /* i: waiting for code length code lengths */
        CODELENS,   /* i: waiting for length/lit and distance code lengths */
            LEN_,       /* i: same as LEN below, but only first time in */
            LEN,        /* i: waiting for length/lit/eob code */
            LENEXT,     /* i: waiting for length extra bits */
            DIST,       /* i: waiting for distance code */
            DISTEXT,    /* i: waiting for distance extra bits */
            MATCH,      /* o: waiting for output space to copy string */
            LIT,        /* o: waiting for output space to write literal */
    CHECK,      /* i: waiting for 32-bit check value */
    LENGTH,     /* i: waiting for 32-bit length (gzip) */
    DONE,       /* finished check, done -- remain here until reset */
    BAD,        /* got a data error -- remain here until reset */
    MEM,        /* got an inflate() memory error -- remain here until reset */
    SYNC        /* looking for synchronization bytes to restart inflate() */
} inflate_mode;

/*
    State transitions between above modes -

    (most modes can go to BAD or MEM on error -- not shown for clarity)

    Process header:
        HEAD -> (gzip) or (zlib) or (raw)
        (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT ->
                  HCRC -> TYPE
        (zlib) -> DICTID or TYPE
        DICTID -> DICT -> TYPE
        (raw) -> TYPEDO
    Read deflate blocks:
            TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK
            STORED -> COPY_ -> COPY -> TYPE
            TABLE -> LENLENS -> CODELENS -> LEN_
            LEN_ -> LEN
    Read deflate codes in fixed or dynamic block:
                LEN -> LENEXT or LIT or TYPE
                LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
                LIT -> LEN
    Process trailer:
        CHECK -> LENGTH -> DONE
 */

/* state maintained between inflate() calls.  Approximately 10K bytes. */
struct inflate_state {
    inflate_mode mode;          /* current inflate mode */
    int last;                   /* true if processing last block */
    int wrap;                   /* bit 0 true for zlib, bit 1 true for gzip */
    int havedict;               /* true if dictionary provided */
    int flags;                  /* gzip header method and flags (0 if zlib) */
    unsigned dmax;              /* zlib header max distance (INFLATE_STRICT) */
    unsigned long check;        /* protected copy of check value */
    unsigned long total;        /* protected copy of output count */
    gz_headerp head;            /* where to save gzip header information */
        /* sliding window */
    unsigned wbits;             /* log base 2 of requested window size */
    unsigned wsize;             /* window size or zero if not using window */
    unsigned whave;             /* valid bytes in the window */
    unsigned wnext;             /* window write index */
    unsigned char FAR *window;  /* allocated sliding window, if needed */
        /* bit accumulator */
    unsigned long hold;         /* input bit accumulator */
    unsigned bits;              /* number of bits in "in" */
        /* for string and stored block copying */
    unsigned length;            /* literal or length of data to copy */
    unsigned offset;            /* distance back to copy string from */
        /* for table and code decoding */
    unsigned extra;             /* extra bits needed */
        /* fixed and dynamic code tables */
    code const FAR *lencode;    /* starting table for length/literal codes */
    code const FAR *distcode;   /* starting table for distance codes */
    unsigned lenbits;           /* index bits for lencode */
    unsigned distbits;          /* index bits for distcode */
        /* dynamic table building */
    unsigned ncode;             /* number of code length code lengths */
    unsigned nlen;              /* number of length code lengths */
    unsigned ndist;             /* number of distance code lengths */
    unsigned have;              /* number of code lengths in lens[] */
    code FAR *next;             /* next available space in codes[] */
    unsigned short lens[320];   /* temporary storage for code lengths */
    unsigned short work[288];   /* work area for code table building */
    code codes[ENOUGH];         /* space for code tables */
    int sane;                   /* if false, allow invalid distance too far */
    int back;                   /* bits back of last unprocessed length/lit */
    unsigned was;               /* initial length of match */
};
cfitsio/zlib/inftrees.c0000644000225700000360000003271113246025103014727 0ustar  cagordonlhea/* inftrees.c -- generate Huffman trees for efficient decoding
 * Copyright (C) 1995-2010 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

#include "zutil.h"
#include "inftrees.h"

#define MAXBITS 15

const char inflate_copyright[] =
   " inflate 1.2.5 Copyright 1995-2010 Mark Adler ";
/*
  If you use the zlib library in a product, an acknowledgment is welcome
  in the documentation of your product. If for some reason you cannot
  include such an acknowledgment, I would appreciate that you keep this
  copyright string in the executable of your product.
 */

/*
   Build a set of tables to decode the provided canonical Huffman code.
   The code lengths are lens[0..codes-1].  The result starts at *table,
   whose indices are 0..2^bits-1.  work is a writable array of at least
   lens shorts, which is used as a work area.  type is the type of code
   to be generated, CODES, LENS, or DISTS.  On return, zero is success,
   -1 is an invalid code, and +1 means that ENOUGH isn't enough.  table
   on return points to the next available entry's address.  bits is the
   requested root table index bits, and on return it is the actual root
   table index bits.  It will differ if the request is greater than the
   longest code or if it is less than the shortest code.
 */
int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work)
codetype type;
unsigned short FAR *lens;
unsigned codes;
code FAR * FAR *table;
unsigned FAR *bits;
unsigned short FAR *work;
{
    unsigned len;               /* a code's length in bits */
    unsigned sym;               /* index of code symbols */
    unsigned min, max;          /* minimum and maximum code lengths */
    unsigned root;              /* number of index bits for root table */
    unsigned curr;              /* number of index bits for current table */
    unsigned drop;              /* code bits to drop for sub-table */
    int left;                   /* number of prefix codes available */
    unsigned used;              /* code entries in table used */
    unsigned huff;              /* Huffman code */
    unsigned incr;              /* for incrementing code, index */
    unsigned fill;              /* index for replicating entries */
    unsigned low;               /* low bits for current root entry */
    unsigned mask;              /* mask for low root bits */
    code here;                  /* table entry for duplication */
    code FAR *next;             /* next available space in table */
    const unsigned short FAR *base;     /* base value table to use */
    const unsigned short FAR *extra;    /* extra bits table to use */
    int end;                    /* use base and extra for symbol > end */
    unsigned short count[MAXBITS+1];    /* number of codes of each length */
    unsigned short offs[MAXBITS+1];     /* offsets in table for each length */
    static const unsigned short lbase[31] = { /* Length codes 257..285 base */
        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
    static const unsigned short lext[31] = { /* Length codes 257..285 extra */
        16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
        19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 195};
    static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
        8193, 12289, 16385, 24577, 0, 0};
    static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
        16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
        23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
        28, 28, 29, 29, 64, 64};

    /*
       Process a set of code lengths to create a canonical Huffman code.  The
       code lengths are lens[0..codes-1].  Each length corresponds to the
       symbols 0..codes-1.  The Huffman code is generated by first sorting the
       symbols by length from short to long, and retaining the symbol order
       for codes with equal lengths.  Then the code starts with all zero bits
       for the first code of the shortest length, and the codes are integer
       increments for the same length, and zeros are appended as the length
       increases.  For the deflate format, these bits are stored backwards
       from their more natural integer increment ordering, and so when the
       decoding tables are built in the large loop below, the integer codes
       are incremented backwards.

       This routine assumes, but does not check, that all of the entries in
       lens[] are in the range 0..MAXBITS.  The caller must assure this.
       1..MAXBITS is interpreted as that code length.  zero means that that
       symbol does not occur in this code.

       The codes are sorted by computing a count of codes for each length,
       creating from that a table of starting indices for each length in the
       sorted table, and then entering the symbols in order in the sorted
       table.  The sorted table is work[], with that space being provided by
       the caller.

       The length counts are used for other purposes as well, i.e. finding
       the minimum and maximum length codes, determining if there are any
       codes at all, checking for a valid set of lengths, and looking ahead
       at length counts to determine sub-table sizes when building the
       decoding tables.
     */

    /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
    for (len = 0; len <= MAXBITS; len++)
        count[len] = 0;
    for (sym = 0; sym < codes; sym++)
        count[lens[sym]]++;

    /* bound code lengths, force root to be within code lengths */
    root = *bits;
    for (max = MAXBITS; max >= 1; max--)
        if (count[max] != 0) break;
    if (root > max) root = max;
    if (max == 0) {                     /* no symbols to code at all */
        here.op = (unsigned char)64;    /* invalid code marker */
        here.bits = (unsigned char)1;
        here.val = (unsigned short)0;
        *(*table)++ = here;             /* make a table to force an error */
        *(*table)++ = here;
        *bits = 1;
        return 0;     /* no symbols, but wait for decoding to report error */
    }
    for (min = 1; min < max; min++)
        if (count[min] != 0) break;
    if (root < min) root = min;

    /* check for an over-subscribed or incomplete set of lengths */
    left = 1;
    for (len = 1; len <= MAXBITS; len++) {
        left <<= 1;
        left -= count[len];
        if (left < 0) return -1;        /* over-subscribed */
    }
    if (left > 0 && (type == CODES || max != 1))
        return -1;                      /* incomplete set */

    /* generate offsets into symbol table for each length for sorting */
    offs[1] = 0;
    for (len = 1; len < MAXBITS; len++)
        offs[len + 1] = offs[len] + count[len];

    /* sort symbols by length, by symbol order within each length */
    for (sym = 0; sym < codes; sym++)
        if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;

    /*
       Create and fill in decoding tables.  In this loop, the table being
       filled is at next and has curr index bits.  The code being used is huff
       with length len.  That code is converted to an index by dropping drop
       bits off of the bottom.  For codes where len is less than drop + curr,
       those top drop + curr - len bits are incremented through all values to
       fill the table with replicated entries.

       root is the number of index bits for the root table.  When len exceeds
       root, sub-tables are created pointed to by the root entry with an index
       of the low root bits of huff.  This is saved in low to check for when a
       new sub-table should be started.  drop is zero when the root table is
       being filled, and drop is root when sub-tables are being filled.

       When a new sub-table is needed, it is necessary to look ahead in the
       code lengths to determine what size sub-table is needed.  The length
       counts are used for this, and so count[] is decremented as codes are
       entered in the tables.

       used keeps track of how many table entries have been allocated from the
       provided *table space.  It is checked for LENS and DIST tables against
       the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
       the initial root table size constants.  See the comments in inftrees.h
       for more information.

       sym increments through all symbols, and the loop terminates when
       all codes of length max, i.e. all codes, have been processed.  This
       routine permits incomplete codes, so another loop after this one fills
       in the rest of the decoding tables with invalid code markers.
     */

    /* set up for code type */
    switch (type) {
    case CODES:
        base = extra = work;    /* dummy value--not used */
        end = 19;
        break;
    case LENS:
        base = lbase;
        base -= 257;
        extra = lext;
        extra -= 257;
        end = 256;
        break;
    default:            /* DISTS */
        base = dbase;
        extra = dext;
        end = -1;
    }

    /* initialize state for loop */
    huff = 0;                   /* starting code */
    sym = 0;                    /* starting code symbol */
    len = min;                  /* starting code length */
    next = *table;              /* current table to fill in */
    curr = root;                /* current table index bits */
    drop = 0;                   /* current bits to drop from code for index */
    low = (unsigned)(-1);       /* trigger new sub-table when len > root */
    used = 1U << root;          /* use root table entries */
    mask = used - 1;            /* mask for comparing low */

    /* check available table space */
    if ((type == LENS && used >= ENOUGH_LENS) ||
        (type == DISTS && used >= ENOUGH_DISTS))
        return 1;

    /* process all codes and make table entries */
    for (;;) {
        /* create table entry */
        here.bits = (unsigned char)(len - drop);
        if ((int)(work[sym]) < end) {
            here.op = (unsigned char)0;
            here.val = work[sym];
        }
        else if ((int)(work[sym]) > end) {
            here.op = (unsigned char)(extra[work[sym]]);
            here.val = base[work[sym]];
        }
        else {
            here.op = (unsigned char)(32 + 64);         /* end of block */
            here.val = 0;
        }

        /* replicate for those indices with low len bits equal to huff */
        incr = 1U << (len - drop);
        fill = 1U << curr;
        min = fill;                 /* save offset to next table */
        do {
            fill -= incr;
            next[(huff >> drop) + fill] = here;
        } while (fill != 0);

        /* backwards increment the len-bit code huff */
        incr = 1U << (len - 1);
        while (huff & incr)
            incr >>= 1;
        if (incr != 0) {
            huff &= incr - 1;
            huff += incr;
        }
        else
            huff = 0;

        /* go to next symbol, update count, len */
        sym++;
        if (--(count[len]) == 0) {
            if (len == max) break;
            len = lens[work[sym]];
        }

        /* create new sub-table if needed */
        if (len > root && (huff & mask) != low) {
            /* if first time, transition to sub-tables */
            if (drop == 0)
                drop = root;

            /* increment past last table */
            next += min;            /* here min is 1 << curr */

            /* determine length of next table */
            curr = len - drop;
            left = (int)(1 << curr);
            while (curr + drop < max) {
                left -= count[curr + drop];
                if (left <= 0) break;
                curr++;
                left <<= 1;
            }

            /* check for enough space */
            used += 1U << curr;
            if ((type == LENS && used >= ENOUGH_LENS) ||
                (type == DISTS && used >= ENOUGH_DISTS))
                return 1;

            /* point entry in root table to sub-table */
            low = huff & mask;
            (*table)[low].op = (unsigned char)curr;
            (*table)[low].bits = (unsigned char)root;
            (*table)[low].val = (unsigned short)(next - *table);
        }
    }

    /*
       Fill in rest of table for incomplete codes.  This loop is similar to the
       loop above in incrementing huff for table indices.  It is assumed that
       len is equal to curr + drop, so there is no loop needed to increment
       through high index bits.  When the current sub-table is filled, the loop
       drops back to the root table to fill in any remaining entries there.
     */
    here.op = (unsigned char)64;                /* invalid code marker */
    here.bits = (unsigned char)(len - drop);
    here.val = (unsigned short)0;
    while (huff != 0) {
        /* when done with sub-table, drop back to root table */
        if (drop != 0 && (huff & mask) != low) {
            drop = 0;
            len = root;
            next = *table;
            here.bits = (unsigned char)len;
        }

        /* put invalid code marker in table */
        next[huff >> drop] = here;

        /* backwards increment the len-bit code huff */
        incr = 1U << (len - 1);
        while (huff & incr)
            incr >>= 1;
        if (incr != 0) {
            huff &= incr - 1;
            huff += incr;
        }
        else
            huff = 0;
    }

    /* set return parameters */
    *table += used;
    *bits = root;
    return 0;
}
cfitsio/zlib/inftrees.h0000644000225700000360000000556013246025103014736 0ustar  cagordonlhea/* inftrees.h -- header to use inftrees.c
 * Copyright (C) 1995-2005, 2010 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

/* WARNING: this file should *not* be used by applications. It is
   part of the implementation of the compression library and is
   subject to change. Applications should only use zlib.h.
 */

/* Structure for decoding tables.  Each entry provides either the
   information needed to do the operation requested by the code that
   indexed that table entry, or it provides a pointer to another
   table that indexes more bits of the code.  op indicates whether
   the entry is a pointer to another table, a literal, a length or
   distance, an end-of-block, or an invalid code.  For a table
   pointer, the low four bits of op is the number of index bits of
   that table.  For a length or distance, the low four bits of op
   is the number of extra bits to get after the code.  bits is
   the number of bits in this code or part of the code to drop off
   of the bit buffer.  val is the actual byte to output in the case
   of a literal, the base length or distance, or the offset from
   the current table to the next table.  Each entry is four bytes. */
typedef struct {
    unsigned char op;           /* operation, extra bits, table bits */
    unsigned char bits;         /* bits in this part of the code */
    unsigned short val;         /* offset in table or code value */
} code;

/* op values as set by inflate_table():
    00000000 - literal
    0000tttt - table link, tttt != 0 is the number of table index bits
    0001eeee - length or distance, eeee is the number of extra bits
    01100000 - end of block
    01000000 - invalid code
 */

/* Maximum size of the dynamic table.  The maximum number of code structures is
   1444, which is the sum of 852 for literal/length codes and 592 for distance
   codes.  These values were found by exhaustive searches using the program
   examples/enough.c found in the zlib distribtution.  The arguments to that
   program are the number of symbols, the initial root table size, and the
   maximum bit length of a code.  "enough 286 9 15" for literal/length codes
   returns returns 852, and "enough 30 6 15" for distance codes returns 592.
   The initial root table size (9 or 6) is found in the fifth argument of the
   inflate_table() calls in inflate.c and infback.c.  If the root table size is
   changed, then these maximum sizes would be need to be recalculated and
   updated. */
#define ENOUGH_LENS 852
#define ENOUGH_DISTS 592
#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS)

/* Type of code to build for inflate_table() */
typedef enum {
    CODES,
    LENS,
    DISTS
} codetype;

int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens,
                             unsigned codes, code FAR * FAR *table,
                             unsigned FAR *bits, unsigned short FAR *work));
cfitsio/zlib/trees.c0000644000225700000360000013025113246025103014230 0ustar  cagordonlhea/* trees.c -- output deflated data using Huffman coding
 * Copyright (C) 1995-2010 Jean-loup Gailly
 * detect_data_type() function provided freely by Cosmin Truta, 2006
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

/*
 *  ALGORITHM
 *
 *      The "deflation" process uses several Huffman trees. The more
 *      common source values are represented by shorter bit sequences.
 *
 *      Each code tree is stored in a compressed form which is itself
 * a Huffman encoding of the lengths of all the code strings (in
 * ascending order by source values).  The actual code strings are
 * reconstructed from the lengths in the inflate process, as described
 * in the deflate specification.
 *
 *  REFERENCES
 *
 *      Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
 *      Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
 *
 *      Storer, James A.
 *          Data Compression:  Methods and Theory, pp. 49-50.
 *          Computer Science Press, 1988.  ISBN 0-7167-8156-5.
 *
 *      Sedgewick, R.
 *          Algorithms, p290.
 *          Addison-Wesley, 1983. ISBN 0-201-06672-6.
 */

/* #define GEN_TREES_H */

#include "deflate.h"

#ifdef DEBUG
#  include 
#endif

/* ===========================================================================
 * Constants
 */

#define MAX_BL_BITS 7
/* Bit length codes must not exceed MAX_BL_BITS bits */

#define END_BLOCK 256
/* end of block literal code */

#define REP_3_6      16
/* repeat previous bit length 3-6 times (2 bits of repeat count) */

#define REPZ_3_10    17
/* repeat a zero length 3-10 times  (3 bits of repeat count) */

#define REPZ_11_138  18
/* repeat a zero length 11-138 times  (7 bits of repeat count) */

local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */
   = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};

local const int extra_dbits[D_CODES] /* extra bits for each distance code */
   = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};

local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */
   = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};

local const uch bl_order[BL_CODES]
   = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
/* The lengths of the bit length codes are sent in order of decreasing
 * probability, to avoid transmitting the lengths for unused bit length codes.
 */

#define Buf_size (8 * 2*sizeof(char))
/* Number of bits used within bi_buf. (bi_buf might be implemented on
 * more than 16 bits on some systems.)
 */

/* ===========================================================================
 * Local data. These are initialized only once.
 */

#define DIST_CODE_LEN  512 /* see definition of array dist_code below */

#if defined(GEN_TREES_H) || !defined(STDC)
/* non ANSI compilers may not accept trees.h */

local ct_data static_ltree[L_CODES+2];
/* The static literal tree. Since the bit lengths are imposed, there is no
 * need for the L_CODES extra codes used during heap construction. However
 * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
 * below).
 */

local ct_data static_dtree[D_CODES];
/* The static distance tree. (Actually a trivial tree since all codes use
 * 5 bits.)
 */

uch _dist_code[DIST_CODE_LEN];
/* Distance codes. The first 256 values correspond to the distances
 * 3 .. 258, the last 256 values correspond to the top 8 bits of
 * the 15 bit distances.
 */

uch _length_code[MAX_MATCH-MIN_MATCH+1];
/* length code for each normalized match length (0 == MIN_MATCH) */

local int base_length[LENGTH_CODES];
/* First normalized length for each code (0 = MIN_MATCH) */

local int base_dist[D_CODES];
/* First normalized distance for each code (0 = distance of 1) */

#else
#  include "trees.h"
#endif /* GEN_TREES_H */

struct static_tree_desc_s {
    const ct_data *static_tree;  /* static tree or NULL */
    const intf *extra_bits;      /* extra bits for each code or NULL */
    int     extra_base;          /* base index for extra_bits */
    int     elems;               /* max number of elements in the tree */
    int     max_length;          /* max bit length for the codes */
};

local static_tree_desc  static_l_desc =
{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};

local static_tree_desc  static_d_desc =
{static_dtree, extra_dbits, 0,          D_CODES, MAX_BITS};

local static_tree_desc  static_bl_desc =
{(const ct_data *)0, extra_blbits, 0,   BL_CODES, MAX_BL_BITS};

/* ===========================================================================
 * Local (static) routines in this file.
 */

local void tr_static_init OF((void));
local void init_block     OF((deflate_state *s));
local void pqdownheap     OF((deflate_state *s, ct_data *tree, int k));
local void gen_bitlen     OF((deflate_state *s, tree_desc *desc));
local void gen_codes      OF((ct_data *tree, int max_code, ushf *bl_count));
local void build_tree     OF((deflate_state *s, tree_desc *desc));
local void scan_tree      OF((deflate_state *s, ct_data *tree, int max_code));
local void send_tree      OF((deflate_state *s, ct_data *tree, int max_code));
local int  build_bl_tree  OF((deflate_state *s));
local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
                              int blcodes));
local void compress_block OF((deflate_state *s, ct_data *ltree,
                              ct_data *dtree));
local int  detect_data_type OF((deflate_state *s));
local unsigned bi_reverse OF((unsigned value, int length));
local void bi_windup      OF((deflate_state *s));
local void bi_flush       OF((deflate_state *s));
local void copy_block     OF((deflate_state *s, charf *buf, unsigned len,
                              int header));

#ifdef GEN_TREES_H
local void gen_trees_header OF((void));
#endif

#ifndef DEBUG
#  define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
   /* Send a code of the given tree. c and tree must not have side effects */

#else /* DEBUG */
#  define send_code(s, c, tree) \
     { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
       send_bits(s, tree[c].Code, tree[c].Len); }
#endif

/* ===========================================================================
 * Output a short LSB first on the stream.
 * IN assertion: there is enough room in pendingBuf.
 */
#define put_short(s, w) { \
    put_byte(s, (uch)((w) & 0xff)); \
    put_byte(s, (uch)((ush)(w) >> 8)); \
}

/* ===========================================================================
 * Send a value on a given number of bits.
 * IN assertion: length <= 16 and value fits in length bits.
 */
#ifdef DEBUG
local void send_bits      OF((deflate_state *s, int value, int length));

local void send_bits(s, value, length)
    deflate_state *s;
    int value;  /* value to send */
    int length; /* number of bits */
{
    Tracevv((stderr," l %2d v %4x ", length, value));
    Assert(length > 0 && length <= 15, "invalid length");
    s->bits_sent += (ulg)length;

    /* If not enough room in bi_buf, use (valid) bits from bi_buf and
     * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
     * unused bits in value.
     */
    if (s->bi_valid > (int)Buf_size - length) {
        s->bi_buf |= (ush)value << s->bi_valid;
        put_short(s, s->bi_buf);
        s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
        s->bi_valid += length - Buf_size;
    } else {
        s->bi_buf |= (ush)value << s->bi_valid;
        s->bi_valid += length;
    }
}
#else /* !DEBUG */

#define send_bits(s, value, length) \
{ int len = length;\
  if (s->bi_valid > (int)Buf_size - len) {\
    int val = value;\
    s->bi_buf |= (ush)val << s->bi_valid;\
    put_short(s, s->bi_buf);\
    s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
    s->bi_valid += len - Buf_size;\
  } else {\
    s->bi_buf |= (ush)(value) << s->bi_valid;\
    s->bi_valid += len;\
  }\
}
#endif /* DEBUG */


/* the arguments must not have side effects */

/* ===========================================================================
 * Initialize the various 'constant' tables.
 */
local void tr_static_init()
{
#if defined(GEN_TREES_H) || !defined(STDC)
    static int static_init_done = 0;
    int n;        /* iterates over tree elements */
    int bits;     /* bit counter */
    int length;   /* length value */
    int code;     /* code value */
    int dist;     /* distance index */
    ush bl_count[MAX_BITS+1];
    /* number of codes at each bit length for an optimal tree */

    if (static_init_done) return;

    /* For some embedded targets, global variables are not initialized: */
#ifdef NO_INIT_GLOBAL_POINTERS
    static_l_desc.static_tree = static_ltree;
    static_l_desc.extra_bits = extra_lbits;
    static_d_desc.static_tree = static_dtree;
    static_d_desc.extra_bits = extra_dbits;
    static_bl_desc.extra_bits = extra_blbits;
#endif

    /* Initialize the mapping length (0..255) -> length code (0..28) */
    length = 0;
    for (code = 0; code < LENGTH_CODES-1; code++) {
        base_length[code] = length;
        for (n = 0; n < (1< dist code (0..29) */
    dist = 0;
    for (code = 0 ; code < 16; code++) {
        base_dist[code] = dist;
        for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */
    for ( ; code < D_CODES; code++) {
        base_dist[code] = dist << 7;
        for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
            _dist_code[256 + dist++] = (uch)code;
        }
    }
    Assert (dist == 256, "tr_static_init: 256+dist != 512");

    /* Construct the codes of the static literal tree */
    for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
    n = 0;
    while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
    while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
    while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
    while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
    /* Codes 286 and 287 do not exist, but we must include them in the
     * tree construction to get a canonical Huffman tree (longest code
     * all ones)
     */
    gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);

    /* The static distance tree is trivial: */
    for (n = 0; n < D_CODES; n++) {
        static_dtree[n].Len = 5;
        static_dtree[n].Code = bi_reverse((unsigned)n, 5);
    }
    static_init_done = 1;

#  ifdef GEN_TREES_H
    gen_trees_header();
#  endif
#endif /* defined(GEN_TREES_H) || !defined(STDC) */
}

/* ===========================================================================
 * Genererate the file trees.h describing the static trees.
 */
#ifdef GEN_TREES_H
#  ifndef DEBUG
#    include 
#  endif

#  define SEPARATOR(i, last, width) \
      ((i) == (last)? "\n};\n\n" :    \
       ((i) % (width) == (width)-1 ? ",\n" : ", "))

void gen_trees_header()
{
    FILE *header = fopen("trees.h", "w");
    int i;

    Assert (header != NULL, "Can't open trees.h");
    fprintf(header,
            "/* header created automatically with -DGEN_TREES_H */\n\n");

    fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n");
    for (i = 0; i < L_CODES+2; i++) {
        fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code,
                static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5));
    }

    fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n");
    for (i = 0; i < D_CODES; i++) {
        fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code,
                static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));
    }

    fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n");
    for (i = 0; i < DIST_CODE_LEN; i++) {
        fprintf(header, "%2u%s", _dist_code[i],
                SEPARATOR(i, DIST_CODE_LEN-1, 20));
    }

    fprintf(header,
        "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n");
    for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) {
        fprintf(header, "%2u%s", _length_code[i],
                SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20));
    }

    fprintf(header, "local const int base_length[LENGTH_CODES] = {\n");
    for (i = 0; i < LENGTH_CODES; i++) {
        fprintf(header, "%1u%s", base_length[i],
                SEPARATOR(i, LENGTH_CODES-1, 20));
    }

    fprintf(header, "local const int base_dist[D_CODES] = {\n");
    for (i = 0; i < D_CODES; i++) {
        fprintf(header, "%5u%s", base_dist[i],
                SEPARATOR(i, D_CODES-1, 10));
    }

    fclose(header);
}
#endif /* GEN_TREES_H */

/* ===========================================================================
 * Initialize the tree data structures for a new zlib stream.
 */
void ZLIB_INTERNAL _tr_init(s)
    deflate_state *s;
{
    tr_static_init();

    s->l_desc.dyn_tree = s->dyn_ltree;
    s->l_desc.stat_desc = &static_l_desc;

    s->d_desc.dyn_tree = s->dyn_dtree;
    s->d_desc.stat_desc = &static_d_desc;

    s->bl_desc.dyn_tree = s->bl_tree;
    s->bl_desc.stat_desc = &static_bl_desc;

    s->bi_buf = 0;
    s->bi_valid = 0;
    s->last_eob_len = 8; /* enough lookahead for inflate */
#ifdef DEBUG
    s->compressed_len = 0L;
    s->bits_sent = 0L;
#endif

    /* Initialize the first block of the first file: */
    init_block(s);
}

/* ===========================================================================
 * Initialize a new block.
 */
local void init_block(s)
    deflate_state *s;
{
    int n; /* iterates over tree elements */

    /* Initialize the trees. */
    for (n = 0; n < L_CODES;  n++) s->dyn_ltree[n].Freq = 0;
    for (n = 0; n < D_CODES;  n++) s->dyn_dtree[n].Freq = 0;
    for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;

    s->dyn_ltree[END_BLOCK].Freq = 1;
    s->opt_len = s->static_len = 0L;
    s->last_lit = s->matches = 0;
}

#define SMALLEST 1
/* Index within the heap array of least frequent node in the Huffman tree */


/* ===========================================================================
 * Remove the smallest element from the heap and recreate the heap with
 * one less element. Updates heap and heap_len.
 */
#define pqremove(s, tree, top) \
{\
    top = s->heap[SMALLEST]; \
    s->heap[SMALLEST] = s->heap[s->heap_len--]; \
    pqdownheap(s, tree, SMALLEST); \
}

/* ===========================================================================
 * Compares to subtrees, using the tree depth as tie breaker when
 * the subtrees have equal frequency. This minimizes the worst case length.
 */
#define smaller(tree, n, m, depth) \
   (tree[n].Freq < tree[m].Freq || \
   (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))

/* ===========================================================================
 * Restore the heap property by moving down the tree starting at node k,
 * exchanging a node with the smallest of its two sons if necessary, stopping
 * when the heap property is re-established (each father smaller than its
 * two sons).
 */
local void pqdownheap(s, tree, k)
    deflate_state *s;
    ct_data *tree;  /* the tree to restore */
    int k;               /* node to move down */
{
    int v = s->heap[k];
    int j = k << 1;  /* left son of k */
    while (j <= s->heap_len) {
        /* Set j to the smallest of the two sons: */
        if (j < s->heap_len &&
            smaller(tree, s->heap[j+1], s->heap[j], s->depth)) {
            j++;
        }
        /* Exit if v is smaller than both sons */
        if (smaller(tree, v, s->heap[j], s->depth)) break;

        /* Exchange v with the smallest son */
        s->heap[k] = s->heap[j];  k = j;

        /* And continue down the tree, setting j to the left son of k */
        j <<= 1;
    }
    s->heap[k] = v;
}

/* ===========================================================================
 * Compute the optimal bit lengths for a tree and update the total bit length
 * for the current block.
 * IN assertion: the fields freq and dad are set, heap[heap_max] and
 *    above are the tree nodes sorted by increasing frequency.
 * OUT assertions: the field len is set to the optimal bit length, the
 *     array bl_count contains the frequencies for each bit length.
 *     The length opt_len is updated; static_len is also updated if stree is
 *     not null.
 */
local void gen_bitlen(s, desc)
    deflate_state *s;
    tree_desc *desc;    /* the tree descriptor */
{
    ct_data *tree        = desc->dyn_tree;
    int max_code         = desc->max_code;
    const ct_data *stree = desc->stat_desc->static_tree;
    const intf *extra    = desc->stat_desc->extra_bits;
    int base             = desc->stat_desc->extra_base;
    int max_length       = desc->stat_desc->max_length;
    int h;              /* heap index */
    int n, m;           /* iterate over the tree elements */
    int bits;           /* bit length */
    int xbits;          /* extra bits */
    ush f;              /* frequency */
    int overflow = 0;   /* number of elements with bit length too large */

    for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;

    /* In a first pass, compute the optimal bit lengths (which may
     * overflow in the case of the bit length tree).
     */
    tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */

    for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
        n = s->heap[h];
        bits = tree[tree[n].Dad].Len + 1;
        if (bits > max_length) bits = max_length, overflow++;
        tree[n].Len = (ush)bits;
        /* We overwrite tree[n].Dad which is no longer needed */

        if (n > max_code) continue; /* not a leaf node */

        s->bl_count[bits]++;
        xbits = 0;
        if (n >= base) xbits = extra[n-base];
        f = tree[n].Freq;
        s->opt_len += (ulg)f * (bits + xbits);
        if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits);
    }
    if (overflow == 0) return;

    Trace((stderr,"\nbit length overflow\n"));
    /* This happens for example on obj2 and pic of the Calgary corpus */

    /* Find the first bit length which could increase: */
    do {
        bits = max_length-1;
        while (s->bl_count[bits] == 0) bits--;
        s->bl_count[bits]--;      /* move one leaf down the tree */
        s->bl_count[bits+1] += 2; /* move one overflow item as its brother */
        s->bl_count[max_length]--;
        /* The brother of the overflow item also moves one step up,
         * but this does not affect bl_count[max_length]
         */
        overflow -= 2;
    } while (overflow > 0);

    /* Now recompute all bit lengths, scanning in increasing frequency.
     * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
     * lengths instead of fixing only the wrong ones. This idea is taken
     * from 'ar' written by Haruhiko Okumura.)
     */
    for (bits = max_length; bits != 0; bits--) {
        n = s->bl_count[bits];
        while (n != 0) {
            m = s->heap[--h];
            if (m > max_code) continue;
            if ((unsigned) tree[m].Len != (unsigned) bits) {
                Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
                s->opt_len += ((long)bits - (long)tree[m].Len)
                              *(long)tree[m].Freq;
                tree[m].Len = (ush)bits;
            }
            n--;
        }
    }
}

/* ===========================================================================
 * Generate the codes for a given tree and bit counts (which need not be
 * optimal).
 * IN assertion: the array bl_count contains the bit length statistics for
 * the given tree and the field len is set for all tree elements.
 * OUT assertion: the field code is set for all tree elements of non
 *     zero code length.
 */
local void gen_codes (tree, max_code, bl_count)
    ct_data *tree;             /* the tree to decorate */
    int max_code;              /* largest code with non zero frequency */
    ushf *bl_count;            /* number of codes at each bit length */
{
    ush next_code[MAX_BITS+1]; /* next code value for each bit length */
    ush code = 0;              /* running code value */
    int bits;                  /* bit index */
    int n;                     /* code index */

    /* The distribution counts are first used to generate the code values
     * without bit reversal.
     */
    for (bits = 1; bits <= MAX_BITS; bits++) {
        next_code[bits] = code = (code + bl_count[bits-1]) << 1;
    }
    /* Check that the bit counts in bl_count are consistent. The last code
     * must be all ones.
     */
    Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree;
    const ct_data *stree  = desc->stat_desc->static_tree;
    int elems             = desc->stat_desc->elems;
    int n, m;          /* iterate over heap elements */
    int max_code = -1; /* largest code with non zero frequency */
    int node;          /* new node being created */

    /* Construct the initial heap, with least frequent element in
     * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
     * heap[0] is not used.
     */
    s->heap_len = 0, s->heap_max = HEAP_SIZE;

    for (n = 0; n < elems; n++) {
        if (tree[n].Freq != 0) {
            s->heap[++(s->heap_len)] = max_code = n;
            s->depth[n] = 0;
        } else {
            tree[n].Len = 0;
        }
    }

    /* The pkzip format requires that at least one distance code exists,
     * and that at least one bit should be sent even if there is only one
     * possible code. So to avoid special checks later on we force at least
     * two codes of non zero frequency.
     */
    while (s->heap_len < 2) {
        node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
        tree[node].Freq = 1;
        s->depth[node] = 0;
        s->opt_len--; if (stree) s->static_len -= stree[node].Len;
        /* node is 0 or 1 so it does not have extra bits */
    }
    desc->max_code = max_code;

    /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
     * establish sub-heaps of increasing lengths:
     */
    for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);

    /* Construct the Huffman tree by repeatedly combining the least two
     * frequent nodes.
     */
    node = elems;              /* next internal node of the tree */
    do {
        pqremove(s, tree, n);  /* n = node of least frequency */
        m = s->heap[SMALLEST]; /* m = node of next least frequency */

        s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
        s->heap[--(s->heap_max)] = m;

        /* Create a new node father of n and m */
        tree[node].Freq = tree[n].Freq + tree[m].Freq;
        s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ?
                                s->depth[n] : s->depth[m]) + 1);
        tree[n].Dad = tree[m].Dad = (ush)node;
#ifdef DUMP_BL_TREE
        if (tree == s->bl_tree) {
            fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
                    node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
        }
#endif
        /* and insert the new node in the heap */
        s->heap[SMALLEST] = node++;
        pqdownheap(s, tree, SMALLEST);

    } while (s->heap_len >= 2);

    s->heap[--(s->heap_max)] = s->heap[SMALLEST];

    /* At this point, the fields freq and dad are set. We can now
     * generate the bit lengths.
     */
    gen_bitlen(s, (tree_desc *)desc);

    /* The field len is now set, we can generate the bit codes */
    gen_codes ((ct_data *)tree, max_code, s->bl_count);
}

/* ===========================================================================
 * Scan a literal or distance tree to determine the frequencies of the codes
 * in the bit length tree.
 */
local void scan_tree (s, tree, max_code)
    deflate_state *s;
    ct_data *tree;   /* the tree to be scanned */
    int max_code;    /* and its largest code of non zero frequency */
{
    int n;                     /* iterates over all tree elements */
    int prevlen = -1;          /* last emitted length */
    int curlen;                /* length of current code */
    int nextlen = tree[0].Len; /* length of next code */
    int count = 0;             /* repeat count of the current code */
    int max_count = 7;         /* max repeat count */
    int min_count = 4;         /* min repeat count */

    if (nextlen == 0) max_count = 138, min_count = 3;
    tree[max_code+1].Len = (ush)0xffff; /* guard */

    for (n = 0; n <= max_code; n++) {
        curlen = nextlen; nextlen = tree[n+1].Len;
        if (++count < max_count && curlen == nextlen) {
            continue;
        } else if (count < min_count) {
            s->bl_tree[curlen].Freq += count;
        } else if (curlen != 0) {
            if (curlen != prevlen) s->bl_tree[curlen].Freq++;
            s->bl_tree[REP_3_6].Freq++;
        } else if (count <= 10) {
            s->bl_tree[REPZ_3_10].Freq++;
        } else {
            s->bl_tree[REPZ_11_138].Freq++;
        }
        count = 0; prevlen = curlen;
        if (nextlen == 0) {
            max_count = 138, min_count = 3;
        } else if (curlen == nextlen) {
            max_count = 6, min_count = 3;
        } else {
            max_count = 7, min_count = 4;
        }
    }
}

/* ===========================================================================
 * Send a literal or distance tree in compressed form, using the codes in
 * bl_tree.
 */
local void send_tree (s, tree, max_code)
    deflate_state *s;
    ct_data *tree; /* the tree to be scanned */
    int max_code;       /* and its largest code of non zero frequency */
{
    int n;                     /* iterates over all tree elements */
    int prevlen = -1;          /* last emitted length */
    int curlen;                /* length of current code */
    int nextlen = tree[0].Len; /* length of next code */
    int count = 0;             /* repeat count of the current code */
    int max_count = 7;         /* max repeat count */
    int min_count = 4;         /* min repeat count */

    /* tree[max_code+1].Len = -1; */  /* guard already set */
    if (nextlen == 0) max_count = 138, min_count = 3;

    for (n = 0; n <= max_code; n++) {
        curlen = nextlen; nextlen = tree[n+1].Len;
        if (++count < max_count && curlen == nextlen) {
            continue;
        } else if (count < min_count) {
            do { send_code(s, curlen, s->bl_tree); } while (--count != 0);

        } else if (curlen != 0) {
            if (curlen != prevlen) {
                send_code(s, curlen, s->bl_tree); count--;
            }
            Assert(count >= 3 && count <= 6, " 3_6?");
            send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2);

        } else if (count <= 10) {
            send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3);

        } else {
            send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7);
        }
        count = 0; prevlen = curlen;
        if (nextlen == 0) {
            max_count = 138, min_count = 3;
        } else if (curlen == nextlen) {
            max_count = 6, min_count = 3;
        } else {
            max_count = 7, min_count = 4;
        }
    }
}

/* ===========================================================================
 * Construct the Huffman tree for the bit lengths and return the index in
 * bl_order of the last bit length code to send.
 */
local int build_bl_tree(s)
    deflate_state *s;
{
    int max_blindex;  /* index of last bit length code of non zero freq */

    /* Determine the bit length frequencies for literal and distance trees */
    scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
    scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);

    /* Build the bit length tree: */
    build_tree(s, (tree_desc *)(&(s->bl_desc)));
    /* opt_len now includes the length of the tree representations, except
     * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
     */

    /* Determine the number of bit length codes to send. The pkzip format
     * requires that at least 4 bit length codes be sent. (appnote.txt says
     * 3 but the actual value used is 4.)
     */
    for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
        if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
    }
    /* Update opt_len to include the bit length tree and counts */
    s->opt_len += 3*(max_blindex+1) + 5+5+4;
    Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
            s->opt_len, s->static_len));

    return max_blindex;
}

/* ===========================================================================
 * Send the header for a block using dynamic Huffman trees: the counts, the
 * lengths of the bit length codes, the literal tree and the distance tree.
 * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
 */
local void send_all_trees(s, lcodes, dcodes, blcodes)
    deflate_state *s;
    int lcodes, dcodes, blcodes; /* number of codes for each tree */
{
    int rank;                    /* index in bl_order */

    Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
    Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
            "too many codes");
    Tracev((stderr, "\nbl counts: "));
    send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */
    send_bits(s, dcodes-1,   5);
    send_bits(s, blcodes-4,  4); /* not -3 as stated in appnote.txt */
    for (rank = 0; rank < blcodes; rank++) {
        Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
        send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
    }
    Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));

    send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */
    Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));

    send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */
    Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
}

/* ===========================================================================
 * Send a stored block
 */
void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last)
    deflate_state *s;
    charf *buf;       /* input block */
    ulg stored_len;   /* length of input block */
    int last;         /* one if this is the last block for a file */
{
    send_bits(s, (STORED_BLOCK<<1)+last, 3);    /* send block type */
#ifdef DEBUG
    s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
    s->compressed_len += (stored_len + 4) << 3;
#endif
    copy_block(s, buf, (unsigned)stored_len, 1); /* with header */
}

/* ===========================================================================
 * Send one empty static block to give enough lookahead for inflate.
 * This takes 10 bits, of which 7 may remain in the bit buffer.
 * The current inflate code requires 9 bits of lookahead. If the
 * last two codes for the previous block (real code plus EOB) were coded
 * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
 * the last real code. In this case we send two empty static blocks instead
 * of one. (There are no problems if the previous block is stored or fixed.)
 * To simplify the code, we assume the worst case of last real code encoded
 * on one bit only.
 */
void ZLIB_INTERNAL _tr_align(s)
    deflate_state *s;
{
    send_bits(s, STATIC_TREES<<1, 3);
    send_code(s, END_BLOCK, static_ltree);
#ifdef DEBUG
    s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
#endif
    bi_flush(s);
    /* Of the 10 bits for the empty block, we have already sent
     * (10 - bi_valid) bits. The lookahead for the last real code (before
     * the EOB of the previous block) was thus at least one plus the length
     * of the EOB plus what we have just sent of the empty static block.
     */
    if (1 + s->last_eob_len + 10 - s->bi_valid < 9) {
        send_bits(s, STATIC_TREES<<1, 3);
        send_code(s, END_BLOCK, static_ltree);
#ifdef DEBUG
        s->compressed_len += 10L;
#endif
        bi_flush(s);
    }
    s->last_eob_len = 7;
}

/* ===========================================================================
 * Determine the best encoding for the current block: dynamic trees, static
 * trees or store, and output the encoded block to the zip file.
 */
void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
    deflate_state *s;
    charf *buf;       /* input block, or NULL if too old */
    ulg stored_len;   /* length of input block */
    int last;         /* one if this is the last block for a file */
{
    ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
    int max_blindex = 0;  /* index of last bit length code of non zero freq */

    /* Build the Huffman trees unless a stored block is forced */
    if (s->level > 0) {

        /* Check if the file is binary or text */
        if (s->strm->data_type == Z_UNKNOWN)
            s->strm->data_type = detect_data_type(s);

        /* Construct the literal and distance trees */
        build_tree(s, (tree_desc *)(&(s->l_desc)));
        Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
                s->static_len));

        build_tree(s, (tree_desc *)(&(s->d_desc)));
        Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
                s->static_len));
        /* At this point, opt_len and static_len are the total bit lengths of
         * the compressed block data, excluding the tree representations.
         */

        /* Build the bit length tree for the above two trees, and get the index
         * in bl_order of the last bit length code to send.
         */
        max_blindex = build_bl_tree(s);

        /* Determine the best encoding. Compute the block lengths in bytes. */
        opt_lenb = (s->opt_len+3+7)>>3;
        static_lenb = (s->static_len+3+7)>>3;

        Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
                opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
                s->last_lit));

        if (static_lenb <= opt_lenb) opt_lenb = static_lenb;

    } else {
        Assert(buf != (char*)0, "lost buf");
        opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
    }

#ifdef FORCE_STORED
    if (buf != (char*)0) { /* force stored block */
#else
    if (stored_len+4 <= opt_lenb && buf != (char*)0) {
                       /* 4: two words for the lengths */
#endif
        /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
         * Otherwise we can't have processed more than WSIZE input bytes since
         * the last block flush, because compression would have been
         * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
         * transform a block into a stored block.
         */
        _tr_stored_block(s, buf, stored_len, last);

#ifdef FORCE_STATIC
    } else if (static_lenb >= 0) { /* force static trees */
#else
    } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
#endif
        send_bits(s, (STATIC_TREES<<1)+last, 3);
        compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
#ifdef DEBUG
        s->compressed_len += 3 + s->static_len;
#endif
    } else {
        send_bits(s, (DYN_TREES<<1)+last, 3);
        send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
                       max_blindex+1);
        compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree);
#ifdef DEBUG
        s->compressed_len += 3 + s->opt_len;
#endif
    }
    Assert (s->compressed_len == s->bits_sent, "bad compressed size");
    /* The above check is made mod 2^32, for files larger than 512 MB
     * and uLong implemented on 32 bits.
     */
    init_block(s);

    if (last) {
        bi_windup(s);
#ifdef DEBUG
        s->compressed_len += 7;  /* align on byte boundary */
#endif
    }
    Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
           s->compressed_len-7*last));
}

/* ===========================================================================
 * Save the match info and tally the frequency counts. Return true if
 * the current block must be flushed.
 */
int ZLIB_INTERNAL _tr_tally (s, dist, lc)
    deflate_state *s;
    unsigned dist;  /* distance of matched string */
    unsigned lc;    /* match length-MIN_MATCH or unmatched char (if dist==0) */
{
    s->d_buf[s->last_lit] = (ush)dist;
    s->l_buf[s->last_lit++] = (uch)lc;
    if (dist == 0) {
        /* lc is the unmatched char */
        s->dyn_ltree[lc].Freq++;
    } else {
        s->matches++;
        /* Here, lc is the match length - MIN_MATCH */
        dist--;             /* dist = match distance - 1 */
        Assert((ush)dist < (ush)MAX_DIST(s) &&
               (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
               (ush)d_code(dist) < (ush)D_CODES,  "_tr_tally: bad match");

        s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
        s->dyn_dtree[d_code(dist)].Freq++;
    }

#ifdef TRUNCATE_BLOCK
    /* Try to guess if it is profitable to stop the current block here */
    if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {
        /* Compute an upper bound for the compressed length */
        ulg out_length = (ulg)s->last_lit*8L;
        ulg in_length = (ulg)((long)s->strstart - s->block_start);
        int dcode;
        for (dcode = 0; dcode < D_CODES; dcode++) {
            out_length += (ulg)s->dyn_dtree[dcode].Freq *
                (5L+extra_dbits[dcode]);
        }
        out_length >>= 3;
        Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
               s->last_lit, in_length, out_length,
               100L - out_length*100L/in_length));
        if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
    }
#endif
    return (s->last_lit == s->lit_bufsize-1);
    /* We avoid equality with lit_bufsize because of wraparound at 64K
     * on 16 bit machines and because stored blocks are restricted to
     * 64K-1 bytes.
     */
}

/* ===========================================================================
 * Send the block data compressed using the given Huffman trees
 */
local void compress_block(s, ltree, dtree)
    deflate_state *s;
    ct_data *ltree; /* literal tree */
    ct_data *dtree; /* distance tree */
{
    unsigned dist;      /* distance of matched string */
    int lc;             /* match length or unmatched char (if dist == 0) */
    unsigned lx = 0;    /* running index in l_buf */
    unsigned code;      /* the code to send */
    int extra;          /* number of extra bits to send */

    if (s->last_lit != 0) do {
        dist = s->d_buf[lx];
        lc = s->l_buf[lx++];
        if (dist == 0) {
            send_code(s, lc, ltree); /* send a literal byte */
            Tracecv(isgraph(lc), (stderr," '%c' ", lc));
        } else {
            /* Here, lc is the match length - MIN_MATCH */
            code = _length_code[lc];
            send_code(s, code+LITERALS+1, ltree); /* send the length code */
            extra = extra_lbits[code];
            if (extra != 0) {
                lc -= base_length[code];
                send_bits(s, lc, extra);       /* send the extra length bits */
            }
            dist--; /* dist is now the match distance - 1 */
            code = d_code(dist);
            Assert (code < D_CODES, "bad d_code");

            send_code(s, code, dtree);       /* send the distance code */
            extra = extra_dbits[code];
            if (extra != 0) {
                dist -= base_dist[code];
                send_bits(s, dist, extra);   /* send the extra distance bits */
            }
        } /* literal or match pair ? */

        /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
        Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
               "pendingBuf overflow");

    } while (lx < s->last_lit);

    send_code(s, END_BLOCK, ltree);
    s->last_eob_len = ltree[END_BLOCK].Len;
}

/* ===========================================================================
 * Check if the data type is TEXT or BINARY, using the following algorithm:
 * - TEXT if the two conditions below are satisfied:
 *    a) There are no non-portable control characters belonging to the
 *       "black list" (0..6, 14..25, 28..31).
 *    b) There is at least one printable character belonging to the
 *       "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
 * - BINARY otherwise.
 * - The following partially-portable control characters form a
 *   "gray list" that is ignored in this detection algorithm:
 *   (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
 * IN assertion: the fields Freq of dyn_ltree are set.
 */
local int detect_data_type(s)
    deflate_state *s;
{
    /* black_mask is the bit mask of black-listed bytes
     * set bits 0..6, 14..25, and 28..31
     * 0xf3ffc07f = binary 11110011111111111100000001111111
     */
    unsigned long black_mask = 0xf3ffc07fUL;
    int n;

    /* Check for non-textual ("black-listed") bytes. */
    for (n = 0; n <= 31; n++, black_mask >>= 1)
        if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0))
            return Z_BINARY;

    /* Check for textual ("white-listed") bytes. */
    if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0
            || s->dyn_ltree[13].Freq != 0)
        return Z_TEXT;
    for (n = 32; n < LITERALS; n++)
        if (s->dyn_ltree[n].Freq != 0)
            return Z_TEXT;

    /* There are no "black-listed" or "white-listed" bytes:
     * this stream either is empty or has tolerated ("gray-listed") bytes only.
     */
    return Z_BINARY;
}

/* ===========================================================================
 * Reverse the first len bits of a code, using straightforward code (a faster
 * method would use a table)
 * IN assertion: 1 <= len <= 15
 */
local unsigned bi_reverse(code, len)
    unsigned code; /* the value to invert */
    int len;       /* its bit length */
{
    register unsigned res = 0;
    do {
        res |= code & 1;
        code >>= 1, res <<= 1;
    } while (--len > 0);
    return res >> 1;
}

/* ===========================================================================
 * Flush the bit buffer, keeping at most 7 bits in it.
 */
local void bi_flush(s)
    deflate_state *s;
{
    if (s->bi_valid == 16) {
        put_short(s, s->bi_buf);
        s->bi_buf = 0;
        s->bi_valid = 0;
    } else if (s->bi_valid >= 8) {
        put_byte(s, (Byte)s->bi_buf);
        s->bi_buf >>= 8;
        s->bi_valid -= 8;
    }
}

/* ===========================================================================
 * Flush the bit buffer and align the output on a byte boundary
 */
local void bi_windup(s)
    deflate_state *s;
{
    if (s->bi_valid > 8) {
        put_short(s, s->bi_buf);
    } else if (s->bi_valid > 0) {
        put_byte(s, (Byte)s->bi_buf);
    }
    s->bi_buf = 0;
    s->bi_valid = 0;
#ifdef DEBUG
    s->bits_sent = (s->bits_sent+7) & ~7;
#endif
}

/* ===========================================================================
 * Copy a stored block, storing first the length and its
 * one's complement if requested.
 */
local void copy_block(s, buf, len, header)
    deflate_state *s;
    charf    *buf;    /* the input data */
    unsigned len;     /* its length */
    int      header;  /* true if block header must be written */
{
    bi_windup(s);        /* align on byte boundary */
    s->last_eob_len = 8; /* enough lookahead for inflate */

    if (header) {
        put_short(s, (ush)len);
        put_short(s, (ush)~len);
#ifdef DEBUG
        s->bits_sent += 2*16;
#endif
    }
#ifdef DEBUG
    s->bits_sent += (ulg)len<<3;
#endif
    while (len--) {
        put_byte(s, *buf++);
    }
}
cfitsio/zlib/trees.h0000644000225700000360000002043013246025103014232 0ustar  cagordonlhea/* header created automatically with -DGEN_TREES_H */

local const ct_data static_ltree[L_CODES+2] = {
{{ 12},{  8}}, {{140},{  8}}, {{ 76},{  8}}, {{204},{  8}}, {{ 44},{  8}},
{{172},{  8}}, {{108},{  8}}, {{236},{  8}}, {{ 28},{  8}}, {{156},{  8}},
{{ 92},{  8}}, {{220},{  8}}, {{ 60},{  8}}, {{188},{  8}}, {{124},{  8}},
{{252},{  8}}, {{  2},{  8}}, {{130},{  8}}, {{ 66},{  8}}, {{194},{  8}},
{{ 34},{  8}}, {{162},{  8}}, {{ 98},{  8}}, {{226},{  8}}, {{ 18},{  8}},
{{146},{  8}}, {{ 82},{  8}}, {{210},{  8}}, {{ 50},{  8}}, {{178},{  8}},
{{114},{  8}}, {{242},{  8}}, {{ 10},{  8}}, {{138},{  8}}, {{ 74},{  8}},
{{202},{  8}}, {{ 42},{  8}}, {{170},{  8}}, {{106},{  8}}, {{234},{  8}},
{{ 26},{  8}}, {{154},{  8}}, {{ 90},{  8}}, {{218},{  8}}, {{ 58},{  8}},
{{186},{  8}}, {{122},{  8}}, {{250},{  8}}, {{  6},{  8}}, {{134},{  8}},
{{ 70},{  8}}, {{198},{  8}}, {{ 38},{  8}}, {{166},{  8}}, {{102},{  8}},
{{230},{  8}}, {{ 22},{  8}}, {{150},{  8}}, {{ 86},{  8}}, {{214},{  8}},
{{ 54},{  8}}, {{182},{  8}}, {{118},{  8}}, {{246},{  8}}, {{ 14},{  8}},
{{142},{  8}}, {{ 78},{  8}}, {{206},{  8}}, {{ 46},{  8}}, {{174},{  8}},
{{110},{  8}}, {{238},{  8}}, {{ 30},{  8}}, {{158},{  8}}, {{ 94},{  8}},
{{222},{  8}}, {{ 62},{  8}}, {{190},{  8}}, {{126},{  8}}, {{254},{  8}},
{{  1},{  8}}, {{129},{  8}}, {{ 65},{  8}}, {{193},{  8}}, {{ 33},{  8}},
{{161},{  8}}, {{ 97},{  8}}, {{225},{  8}}, {{ 17},{  8}}, {{145},{  8}},
{{ 81},{  8}}, {{209},{  8}}, {{ 49},{  8}}, {{177},{  8}}, {{113},{  8}},
{{241},{  8}}, {{  9},{  8}}, {{137},{  8}}, {{ 73},{  8}}, {{201},{  8}},
{{ 41},{  8}}, {{169},{  8}}, {{105},{  8}}, {{233},{  8}}, {{ 25},{  8}},
{{153},{  8}}, {{ 89},{  8}}, {{217},{  8}}, {{ 57},{  8}}, {{185},{  8}},
{{121},{  8}}, {{249},{  8}}, {{  5},{  8}}, {{133},{  8}}, {{ 69},{  8}},
{{197},{  8}}, {{ 37},{  8}}, {{165},{  8}}, {{101},{  8}}, {{229},{  8}},
{{ 21},{  8}}, {{149},{  8}}, {{ 85},{  8}}, {{213},{  8}}, {{ 53},{  8}},
{{181},{  8}}, {{117},{  8}}, {{245},{  8}}, {{ 13},{  8}}, {{141},{  8}},
{{ 77},{  8}}, {{205},{  8}}, {{ 45},{  8}}, {{173},{  8}}, {{109},{  8}},
{{237},{  8}}, {{ 29},{  8}}, {{157},{  8}}, {{ 93},{  8}}, {{221},{  8}},
{{ 61},{  8}}, {{189},{  8}}, {{125},{  8}}, {{253},{  8}}, {{ 19},{  9}},
{{275},{  9}}, {{147},{  9}}, {{403},{  9}}, {{ 83},{  9}}, {{339},{  9}},
{{211},{  9}}, {{467},{  9}}, {{ 51},{  9}}, {{307},{  9}}, {{179},{  9}},
{{435},{  9}}, {{115},{  9}}, {{371},{  9}}, {{243},{  9}}, {{499},{  9}},
{{ 11},{  9}}, {{267},{  9}}, {{139},{  9}}, {{395},{  9}}, {{ 75},{  9}},
{{331},{  9}}, {{203},{  9}}, {{459},{  9}}, {{ 43},{  9}}, {{299},{  9}},
{{171},{  9}}, {{427},{  9}}, {{107},{  9}}, {{363},{  9}}, {{235},{  9}},
{{491},{  9}}, {{ 27},{  9}}, {{283},{  9}}, {{155},{  9}}, {{411},{  9}},
{{ 91},{  9}}, {{347},{  9}}, {{219},{  9}}, {{475},{  9}}, {{ 59},{  9}},
{{315},{  9}}, {{187},{  9}}, {{443},{  9}}, {{123},{  9}}, {{379},{  9}},
{{251},{  9}}, {{507},{  9}}, {{  7},{  9}}, {{263},{  9}}, {{135},{  9}},
{{391},{  9}}, {{ 71},{  9}}, {{327},{  9}}, {{199},{  9}}, {{455},{  9}},
{{ 39},{  9}}, {{295},{  9}}, {{167},{  9}}, {{423},{  9}}, {{103},{  9}},
{{359},{  9}}, {{231},{  9}}, {{487},{  9}}, {{ 23},{  9}}, {{279},{  9}},
{{151},{  9}}, {{407},{  9}}, {{ 87},{  9}}, {{343},{  9}}, {{215},{  9}},
{{471},{  9}}, {{ 55},{  9}}, {{311},{  9}}, {{183},{  9}}, {{439},{  9}},
{{119},{  9}}, {{375},{  9}}, {{247},{  9}}, {{503},{  9}}, {{ 15},{  9}},
{{271},{  9}}, {{143},{  9}}, {{399},{  9}}, {{ 79},{  9}}, {{335},{  9}},
{{207},{  9}}, {{463},{  9}}, {{ 47},{  9}}, {{303},{  9}}, {{175},{  9}},
{{431},{  9}}, {{111},{  9}}, {{367},{  9}}, {{239},{  9}}, {{495},{  9}},
{{ 31},{  9}}, {{287},{  9}}, {{159},{  9}}, {{415},{  9}}, {{ 95},{  9}},
{{351},{  9}}, {{223},{  9}}, {{479},{  9}}, {{ 63},{  9}}, {{319},{  9}},
{{191},{  9}}, {{447},{  9}}, {{127},{  9}}, {{383},{  9}}, {{255},{  9}},
{{511},{  9}}, {{  0},{  7}}, {{ 64},{  7}}, {{ 32},{  7}}, {{ 96},{  7}},
{{ 16},{  7}}, {{ 80},{  7}}, {{ 48},{  7}}, {{112},{  7}}, {{  8},{  7}},
{{ 72},{  7}}, {{ 40},{  7}}, {{104},{  7}}, {{ 24},{  7}}, {{ 88},{  7}},
{{ 56},{  7}}, {{120},{  7}}, {{  4},{  7}}, {{ 68},{  7}}, {{ 36},{  7}},
{{100},{  7}}, {{ 20},{  7}}, {{ 84},{  7}}, {{ 52},{  7}}, {{116},{  7}},
{{  3},{  8}}, {{131},{  8}}, {{ 67},{  8}}, {{195},{  8}}, {{ 35},{  8}},
{{163},{  8}}, {{ 99},{  8}}, {{227},{  8}}
};

local const ct_data static_dtree[D_CODES] = {
{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
};

const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {
 0,  1,  2,  3,  4,  4,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  8,
 8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  0,  0, 16, 17,
18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
};

const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {
 0,  1,  2,  3,  4,  5,  6,  7,  8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 12, 12,
13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
};

local const int base_length[LENGTH_CODES] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
64, 80, 96, 112, 128, 160, 192, 224, 0
};

local const int base_dist[D_CODES] = {
    0,     1,     2,     3,     4,     6,     8,    12,    16,    24,
   32,    48,    64,    96,   128,   192,   256,   384,   512,   768,
 1024,  1536,  2048,  3072,  4096,  6144,  8192, 12288, 16384, 24576
};

cfitsio/zlib/uncompr.c0000644000225700000360000000367113246025103014576 0ustar  cagordonlhea/* uncompr.c -- decompress a memory buffer
 * Copyright (C) 1995-2003, 2010 Jean-loup Gailly.
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

#define ZLIB_INTERNAL
#include "zlib.h"

/* ===========================================================================
     Decompresses the source buffer into the destination buffer.  sourceLen is
   the byte length of the source buffer. Upon entry, destLen is the total
   size of the destination buffer, which must be large enough to hold the
   entire uncompressed data. (The size of the uncompressed data must have
   been saved previously by the compressor and transmitted to the decompressor
   by some mechanism outside the scope of this compression library.)
   Upon exit, destLen is the actual size of the compressed buffer.

     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
   enough memory, Z_BUF_ERROR if there was not enough room in the output
   buffer, or Z_DATA_ERROR if the input data was corrupted.
*/
int ZEXPORT uncompress (dest, destLen, source, sourceLen)
    Bytef *dest;
    uLongf *destLen;
    const Bytef *source;
    uLong sourceLen;
{
    z_stream stream;
    int err;

    stream.next_in = (Bytef*)source;
    stream.avail_in = (uInt)sourceLen;
    /* Check for source > 64K on 16-bit machine: */
    if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;

    stream.next_out = dest;
    stream.avail_out = (uInt)*destLen;
    if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;

    stream.zalloc = (alloc_func)0;
    stream.zfree = (free_func)0;

    err = inflateInit(&stream);
    if (err != Z_OK) return err;

    err = inflate(&stream, Z_FINISH);
    if (err != Z_STREAM_END) {
        inflateEnd(&stream);
        if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
            return Z_DATA_ERROR;
        return err;
    }
    *destLen = stream.total_out;

    err = inflateEnd(&stream);
    return err;
}
cfitsio/zlib/zcompress.c0000644000225700000360000004500213246025103015132 0ustar  cagordonlhea#include 
#include 
#include 
#include 
#include 
#include "zlib.h"  

#define GZBUFSIZE 115200    /* 40 FITS blocks */
#define BUFFINCR   28800    /* 10 FITS blocks */

/* prototype for the following functions */
int uncompress2mem(char *filename, 
             FILE *diskfile, 
             char **buffptr, 
             size_t *buffsize, 
             void *(*mem_realloc)(void *p, size_t newsize),
             size_t *filesize,
             int *status);

int uncompress2mem_from_mem(                                                
             char *inmemptr,     
             size_t inmemsize, 
             char **buffptr,  
             size_t *buffsize,  
             void *(*mem_realloc)(void *p, size_t newsize), 
             size_t *filesize,  
             int *status);

int uncompress2file(char *filename, 
             FILE *indiskfile, 
             FILE *outdiskfile, 
             int *status);


int compress2mem_from_mem(                                                
             char *inmemptr,     
             size_t inmemsize, 
             char **buffptr,  
             size_t *buffsize,  
             void *(*mem_realloc)(void *p, size_t newsize), 
             size_t *filesize,  
             int *status);

int compress2file_from_mem(                                                
             char *inmemptr,     
             size_t inmemsize, 
             FILE *outdiskfile, 
             size_t *filesize,   /* O - size of file, in bytes              */
             int *status);


/*--------------------------------------------------------------------------*/
int uncompress2mem(char *filename,  /* name of input file                 */
             FILE *diskfile,     /* I - file pointer                        */
             char **buffptr,   /* IO - memory pointer                     */
             size_t *buffsize,   /* IO - size of buffer, in bytes           */
             void *(*mem_realloc)(void *p, size_t newsize), /* function     */
             size_t *filesize,   /* O - size of file, in bytes              */
             int *status)        /* IO - error status                       */

/*
  Uncompress the disk file into memory.  Fill whatever amount of memory has
  already been allocated, then realloc more memory, using the supplied
  input function, if necessary.
*/
{
    int err, len;
    char *filebuff;
    z_stream d_stream;   /* decompression stream */
    /* Input args buffptr and buffsize may refer to a block of memory
        larger than the 2^32 4 byte limit.  If so, must be broken
        up into "pages" when assigned to d_stream.  
        (d_stream.avail_out is a uInt type, which might be smaller
        than buffsize's size_t type.)
    */
    const uLong nPages = (uLong)(*buffsize)/(uLong)UINT_MAX;
    uLong iPage=0;
    uInt outbuffsize = (nPages > 0) ? UINT_MAX : (uInt)(*buffsize);
    

    if (*status > 0) 
        return(*status); 

    /* Allocate memory to hold compressed bytes read from the file. */
    filebuff = (char*)malloc(GZBUFSIZE);
    if (!filebuff) return(*status = 113); /* memory error */

    d_stream.zalloc = (alloc_func)0;
    d_stream.zfree = (free_func)0;
    d_stream.opaque = (voidpf)0;
    d_stream.next_out = (unsigned char*) *buffptr;
    d_stream.avail_out = outbuffsize;

    /* Initialize the decompression.  The argument (15+16) tells the
       decompressor that we are to use the gzip algorithm */

    err = inflateInit2(&d_stream, (15+16));
    if (err != Z_OK) return(*status = 414);

    /* loop through the file, reading a buffer and uncompressing it */
    for (;;)
    {
        len = fread(filebuff, 1, GZBUFSIZE, diskfile);
	if (ferror(diskfile)) {
              inflateEnd(&d_stream);
              free(filebuff);
              return(*status = 414);
	}

        if (len == 0) break;  /* no more data */

        d_stream.next_in = (unsigned char*)filebuff;
        d_stream.avail_in = len;

        for (;;) {
            /* uncompress as much of the input as will fit in the output */
            err = inflate(&d_stream, Z_NO_FLUSH);

            if (err == Z_STREAM_END ) { /* We reached the end of the input */
	        break; 
            } else if (err == Z_OK ) { 

                if (!d_stream.avail_in) break; /* need more input */
		
                /* need more space in output buffer */
                /* First check if more memory is available above the
                    4Gb limit in the originally input buffptr array */
                if (iPage < nPages)
                {
                   ++iPage;
                   d_stream.next_out = (unsigned char*)(*buffptr + iPage*(uLong)UINT_MAX);
                   if (iPage < nPages)
                      d_stream.avail_out = UINT_MAX;
                   else
                      d_stream.avail_out = (uInt)((uLong)(*buffsize) % (uLong)UINT_MAX);
                }
                else if (mem_realloc) {   
                    *buffptr = mem_realloc(*buffptr,*buffsize + BUFFINCR);
                    if (*buffptr == NULL){
                        inflateEnd(&d_stream);
                        free(filebuff);
                        return(*status = 414);  /* memory allocation failed */
                    }

                    d_stream.avail_out = BUFFINCR;
                    d_stream.next_out = (unsigned char*) (*buffptr + *buffsize);
                    *buffsize = *buffsize + BUFFINCR;
                } else  { /* error: no realloc function available */
                    inflateEnd(&d_stream);
                    free(filebuff);
                    return(*status = 414);
                }
            } else {  /* some other error */
                inflateEnd(&d_stream);
                free(filebuff);
                return(*status = 414);
            }
        }
	
	if (feof(diskfile))  break;
/*     
        These settings for next_out and avail_out appear to be redundant,
        as the inflate() function should already be re-setting these.
        For case where *buffsize < 4Gb this did not matter, but for
        > 4Gb it would produce the wrong value in the avail_out assignment.
        (C. Gordon Jul 2016)
        d_stream.next_out = (unsigned char*) (*buffptr + d_stream.total_out);
        d_stream.avail_out = *buffsize - d_stream.total_out;
*/    }

    /* Set the output file size to be the total output data */
    *filesize = d_stream.total_out;
    
    free(filebuff); /* free temporary output data buffer */
    
    err = inflateEnd(&d_stream); /* End the decompression */
    if (err != Z_OK) return(*status = 414);
  
    return(*status);
}
/*--------------------------------------------------------------------------*/
int uncompress2mem_from_mem(                                                
             char *inmemptr,     /* I - memory pointer to compressed bytes */
             size_t inmemsize,   /* I - size of input compressed file      */
             char **buffptr,   /* IO - memory pointer                      */
             size_t *buffsize,   /* IO - size of buffer, in bytes           */
             void *(*mem_realloc)(void *p, size_t newsize), /* function     */
             size_t *filesize,   /* O - size of file, in bytes              */
             int *status)        /* IO - error status                       */

/*
  Uncompress the file in memory into memory.  Fill whatever amount of memory has
  already been allocated, then realloc more memory, using the supplied
  input function, if necessary.
*/
{
    int err; 
    z_stream d_stream;   /* decompression stream */

    if (*status > 0) 
        return(*status); 

    d_stream.zalloc = (alloc_func)0;
    d_stream.zfree = (free_func)0;
    d_stream.opaque = (voidpf)0;

    /* Initialize the decompression.  The argument (15+16) tells the
       decompressor that we are to use the gzip algorithm */
    err = inflateInit2(&d_stream, (15+16));
    if (err != Z_OK) return(*status = 414);

    d_stream.next_in = (unsigned char*)inmemptr;
    d_stream.avail_in = inmemsize;

    d_stream.next_out = (unsigned char*) *buffptr;
    d_stream.avail_out = *buffsize;

    for (;;) {
        /* uncompress as much of the input as will fit in the output */
        err = inflate(&d_stream, Z_NO_FLUSH);

        if (err == Z_STREAM_END) { /* We reached the end of the input */
	    break; 
        } else if (err == Z_OK ) { /* need more space in output buffer */

            if (mem_realloc) {   
                *buffptr = mem_realloc(*buffptr,*buffsize + BUFFINCR);
                if (*buffptr == NULL){
                    inflateEnd(&d_stream);
                    return(*status = 414);  /* memory allocation failed */
                }

                d_stream.avail_out = BUFFINCR;
                d_stream.next_out = (unsigned char*) (*buffptr + *buffsize);
                *buffsize = *buffsize + BUFFINCR;

            } else  { /* error: no realloc function available */
                inflateEnd(&d_stream);
                return(*status = 414);
            }
        } else {  /* some other error */
            inflateEnd(&d_stream);
            return(*status = 414);
        }
    }

    /* Set the output file size to be the total output data */
    if (filesize) *filesize = d_stream.total_out;

    /* End the decompression */
    err = inflateEnd(&d_stream);

    if (err != Z_OK) return(*status = 414);
    
    return(*status);
}
/*--------------------------------------------------------------------------*/
int uncompress2file(char *filename,  /* name of input file                  */
             FILE *indiskfile,     /* I - input file pointer                */
             FILE *outdiskfile,    /* I - output file pointer               */
             int *status)        /* IO - error status                       */
/*
  Uncompress the file into another file. 
*/
{
    int err, len;
    unsigned long bytes_out = 0;
    char *infilebuff, *outfilebuff;
    z_stream d_stream;   /* decompression stream */

    if (*status > 0) 
        return(*status); 

    /* Allocate buffers to hold compressed and uncompressed */
    infilebuff = (char*)malloc(GZBUFSIZE);
    if (!infilebuff) return(*status = 113); /* memory error */

    outfilebuff = (char*)malloc(GZBUFSIZE);
    if (!outfilebuff) return(*status = 113); /* memory error */

    d_stream.zalloc = (alloc_func)0;
    d_stream.zfree = (free_func)0;
    d_stream.opaque = (voidpf)0;

    d_stream.next_out = (unsigned char*) outfilebuff;
    d_stream.avail_out = GZBUFSIZE;

    /* Initialize the decompression.  The argument (15+16) tells the
       decompressor that we are to use the gzip algorithm */

    err = inflateInit2(&d_stream, (15+16));
    if (err != Z_OK) return(*status = 414);

    /* loop through the file, reading a buffer and uncompressing it */
    for (;;)
    {
        len = fread(infilebuff, 1, GZBUFSIZE, indiskfile);
	if (ferror(indiskfile)) {
              inflateEnd(&d_stream);
              free(infilebuff);
              free(outfilebuff);
              return(*status = 414);
	}

        if (len == 0) break;  /* no more data */

        d_stream.next_in = (unsigned char*)infilebuff;
        d_stream.avail_in = len;

        for (;;) {
            /* uncompress as much of the input as will fit in the output */
            err = inflate(&d_stream, Z_NO_FLUSH);

            if (err == Z_STREAM_END ) { /* We reached the end of the input */
	        break; 
            } else if (err == Z_OK ) { 

                if (!d_stream.avail_in) break; /* need more input */
		
                /* flush out the full output buffer */
                if ((int)fwrite(outfilebuff, 1, GZBUFSIZE, outdiskfile) != GZBUFSIZE) {
                    inflateEnd(&d_stream);
                    free(infilebuff);
                    free(outfilebuff);
                    return(*status = 414);
                }
                bytes_out += GZBUFSIZE;
                d_stream.next_out = (unsigned char*) outfilebuff;
                d_stream.avail_out = GZBUFSIZE;

            } else {  /* some other error */
                inflateEnd(&d_stream);
                free(infilebuff);
                free(outfilebuff);
                return(*status = 414);
            }
        }
	
	if (feof(indiskfile))  break;
    }

    /* write out any remaining bytes in the buffer */
    if (d_stream.total_out > bytes_out) {
        if ((int)fwrite(outfilebuff, 1, (d_stream.total_out - bytes_out), outdiskfile) 
	    != (d_stream.total_out - bytes_out)) {
            inflateEnd(&d_stream);
            free(infilebuff);
            free(outfilebuff);
            return(*status = 414);
        }
    }

    free(infilebuff); /* free temporary output data buffer */
    free(outfilebuff); /* free temporary output data buffer */

    err = inflateEnd(&d_stream); /* End the decompression */
    if (err != Z_OK) return(*status = 414);
  
    return(*status);
}
/*--------------------------------------------------------------------------*/
int compress2mem_from_mem(                                                
             char *inmemptr,     /* I - memory pointer to uncompressed bytes */
             size_t inmemsize,   /* I - size of input uncompressed file      */
             char **buffptr,   /* IO - memory pointer for compressed file    */
             size_t *buffsize,   /* IO - size of buffer, in bytes           */
             void *(*mem_realloc)(void *p, size_t newsize), /* function     */
             size_t *filesize,   /* O - size of file, in bytes              */
             int *status)        /* IO - error status                       */

/*
  Compress the file into memory.  Fill whatever amount of memory has
  already been allocated, then realloc more memory, using the supplied
  input function, if necessary.
*/
{
    int err;
    z_stream c_stream;  /* compression stream */

    if (*status > 0)
        return(*status);

    c_stream.zalloc = (alloc_func)0;
    c_stream.zfree = (free_func)0;
    c_stream.opaque = (voidpf)0;

    /* Initialize the compression.  The argument (15+16) tells the 
       compressor that we are to use the gzip algorythm.
       Also use Z_BEST_SPEED for maximum speed with very minor loss
       in compression factor. */
    err = deflateInit2(&c_stream, Z_BEST_SPEED, Z_DEFLATED,
                       (15+16), 8, Z_DEFAULT_STRATEGY);

    if (err != Z_OK) return(*status = 413);

    c_stream.next_in = (unsigned char*)inmemptr;
    c_stream.avail_in = inmemsize;

    c_stream.next_out = (unsigned char*) *buffptr;
    c_stream.avail_out = *buffsize;

    for (;;) {
        /* compress as much of the input as will fit in the output */
        err = deflate(&c_stream, Z_FINISH);

        if (err == Z_STREAM_END) {  /* We reached the end of the input */
	   break;
        } else if (err == Z_OK ) { /* need more space in output buffer */

            if (mem_realloc) {   
                *buffptr = mem_realloc(*buffptr,*buffsize + BUFFINCR);
                if (*buffptr == NULL){
                    deflateEnd(&c_stream);
                    return(*status = 413);  /* memory allocation failed */
                }

                c_stream.avail_out = BUFFINCR;
                c_stream.next_out = (unsigned char*) (*buffptr + *buffsize);
                *buffsize = *buffsize + BUFFINCR;

            } else  { /* error: no realloc function available */
                deflateEnd(&c_stream);
                return(*status = 413);
            }
        } else {  /* some other error */
            deflateEnd(&c_stream);
            return(*status = 413);
        }
    }

    /* Set the output file size to be the total output data */
    if (filesize) *filesize = c_stream.total_out;

    /* End the compression */
    err = deflateEnd(&c_stream);

    if (err != Z_OK) return(*status = 413);
     
    return(*status);
}
/*--------------------------------------------------------------------------*/
int compress2file_from_mem(                                                
             char *inmemptr,     /* I - memory pointer to uncompressed bytes */
             size_t inmemsize,   /* I - size of input uncompressed file      */
             FILE *outdiskfile, 
             size_t *filesize,   /* O - size of file, in bytes              */
             int *status)

/*
  Compress the memory file into disk file. 
*/
{
    int err;
    unsigned long bytes_out = 0;
    char  *outfilebuff;
    z_stream c_stream;  /* compression stream */

    if (*status > 0)
        return(*status);

    /* Allocate buffer to hold compressed bytes */
    outfilebuff = (char*)malloc(GZBUFSIZE);
    if (!outfilebuff) return(*status = 113); /* memory error */

    c_stream.zalloc = (alloc_func)0;
    c_stream.zfree = (free_func)0;
    c_stream.opaque = (voidpf)0;

    /* Initialize the compression.  The argument (15+16) tells the 
       compressor that we are to use the gzip algorythm.
       Also use Z_BEST_SPEED for maximum speed with very minor loss
       in compression factor. */
    err = deflateInit2(&c_stream, Z_BEST_SPEED, Z_DEFLATED,
                       (15+16), 8, Z_DEFAULT_STRATEGY);

    if (err != Z_OK) return(*status = 413);

    c_stream.next_in = (unsigned char*)inmemptr;
    c_stream.avail_in = inmemsize;

    c_stream.next_out = (unsigned char*) outfilebuff;
    c_stream.avail_out = GZBUFSIZE;

    for (;;) {
        /* compress as much of the input as will fit in the output */
        err = deflate(&c_stream, Z_FINISH);

        if (err == Z_STREAM_END) {  /* We reached the end of the input */
	   break;
        } else if (err == Z_OK ) { /* need more space in output buffer */

            /* flush out the full output buffer */
            if ((int)fwrite(outfilebuff, 1, GZBUFSIZE, outdiskfile) != GZBUFSIZE) {
                deflateEnd(&c_stream);
                free(outfilebuff);
                return(*status = 413);
            }
            bytes_out += GZBUFSIZE;
            c_stream.next_out = (unsigned char*) outfilebuff;
            c_stream.avail_out = GZBUFSIZE;


        } else {  /* some other error */
            deflateEnd(&c_stream);
            free(outfilebuff);
            return(*status = 413);
        }
    }

    /* write out any remaining bytes in the buffer */
    if (c_stream.total_out > bytes_out) {
        if ((int)fwrite(outfilebuff, 1, (c_stream.total_out - bytes_out), outdiskfile) 
	    != (c_stream.total_out - bytes_out)) {
            deflateEnd(&c_stream);
            free(outfilebuff);
            return(*status = 413);
        }
    }

    free(outfilebuff); /* free temporary output data buffer */

    /* Set the output file size to be the total output data */
    if (filesize) *filesize = c_stream.total_out;

    /* End the compression */
    err = deflateEnd(&c_stream);

    if (err != Z_OK) return(*status = 413);
     
    return(*status);
}
cfitsio/zlib/zconf.h0000644000225700000360000003205113246025103014231 0ustar  cagordonlhea/* zconf.h -- configuration of the zlib compression library
 * Copyright (C) 1995-2010 Jean-loup Gailly.
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

#ifndef ZCONF_H
#define ZCONF_H

/*
 * If you *really* need a unique prefix for all types and library functions,
 * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
 * Even better than compiling with -DZ_PREFIX would be to use configure to set
 * this permanently in zconf.h using "./configure --zprefix".
 */
#ifdef Z_PREFIX     /* may be set to #if 1 by ./configure */

/* all linked symbols */
#  define _dist_code            z__dist_code
#  define _length_code          z__length_code
#  define _tr_align             z__tr_align
#  define _tr_flush_block       z__tr_flush_block
#  define _tr_init              z__tr_init
#  define _tr_stored_block      z__tr_stored_block
#  define _tr_tally             z__tr_tally
#  define adler32               z_adler32
#  define adler32_combine       z_adler32_combine
#  define adler32_combine64     z_adler32_combine64
#  define compress              z_compress
#  define compress2             z_compress2
#  define compressBound         z_compressBound
#  define crc32                 z_crc32
#  define crc32_combine         z_crc32_combine
#  define crc32_combine64       z_crc32_combine64
#  define deflate               z_deflate
#  define deflateBound          z_deflateBound
#  define deflateCopy           z_deflateCopy
#  define deflateEnd            z_deflateEnd
#  define deflateInit2_         z_deflateInit2_
#  define deflateInit_          z_deflateInit_
#  define deflateParams         z_deflateParams
#  define deflatePrime          z_deflatePrime
#  define deflateReset          z_deflateReset
#  define deflateSetDictionary  z_deflateSetDictionary
#  define deflateSetHeader      z_deflateSetHeader
#  define deflateTune           z_deflateTune
#  define deflate_copyright     z_deflate_copyright
#  define get_crc_table         z_get_crc_table
#  define gz_error              z_gz_error
#  define gz_intmax             z_gz_intmax
#  define gz_strwinerror        z_gz_strwinerror
#  define gzbuffer              z_gzbuffer
#  define gzclearerr            z_gzclearerr
#  define gzclose               z_gzclose
#  define gzclose_r             z_gzclose_r
#  define gzclose_w             z_gzclose_w
#  define gzdirect              z_gzdirect
#  define gzdopen               z_gzdopen
#  define gzeof                 z_gzeof
#  define gzerror               z_gzerror
#  define gzflush               z_gzflush
#  define gzgetc                z_gzgetc
#  define gzgets                z_gzgets
#  define gzoffset              z_gzoffset
#  define gzoffset64            z_gzoffset64
#  define gzopen                z_gzopen
#  define gzopen64              z_gzopen64
#  define gzprintf              z_gzprintf
#  define gzputc                z_gzputc
#  define gzputs                z_gzputs
#  define gzread                z_gzread
#  define gzrewind              z_gzrewind
#  define gzseek                z_gzseek
#  define gzseek64              z_gzseek64
#  define gzsetparams           z_gzsetparams
#  define gztell                z_gztell
#  define gztell64              z_gztell64
#  define gzungetc              z_gzungetc
#  define gzwrite               z_gzwrite
#  define inflate               z_inflate
#  define inflateBack           z_inflateBack
#  define inflateBackEnd        z_inflateBackEnd
#  define inflateBackInit_      z_inflateBackInit_
#  define inflateCopy           z_inflateCopy
#  define inflateEnd            z_inflateEnd
#  define inflateGetHeader      z_inflateGetHeader
#  define inflateInit2_         z_inflateInit2_
#  define inflateInit_          z_inflateInit_
#  define inflateMark           z_inflateMark
#  define inflatePrime          z_inflatePrime
#  define inflateReset          z_inflateReset
#  define inflateReset2         z_inflateReset2
#  define inflateSetDictionary  z_inflateSetDictionary
#  define inflateSync           z_inflateSync
#  define inflateSyncPoint      z_inflateSyncPoint
#  define inflateUndermine      z_inflateUndermine
#  define inflate_copyright     z_inflate_copyright
#  define inflate_fast          z_inflate_fast
#  define inflate_table         z_inflate_table
#  define uncompress            z_uncompress
#  define zError                z_zError
#  define zcalloc               z_zcalloc
#  define zcfree                z_zcfree
#  define zlibCompileFlags      z_zlibCompileFlags
#  define zlibVersion           z_zlibVersion

/* all zlib typedefs in zlib.h and zconf.h */
#  define Byte                  z_Byte
#  define Bytef                 z_Bytef
#  define alloc_func            z_alloc_func
#  define charf                 z_charf
#  define free_func             z_free_func
#  define gzFile                z_gzFile
#  define gz_header             z_gz_header
#  define gz_headerp            z_gz_headerp
#  define in_func               z_in_func
#  define intf                  z_intf
#  define out_func              z_out_func
#  define uInt                  z_uInt
#  define uIntf                 z_uIntf
#  define uLong                 z_uLong
#  define uLongf                z_uLongf
#  define voidp                 z_voidp
#  define voidpc                z_voidpc
#  define voidpf                z_voidpf

/* all zlib structs in zlib.h and zconf.h */
#  define gz_header_s           z_gz_header_s
#  define internal_state        z_internal_state

#endif

#if defined(__MSDOS__) && !defined(MSDOS)
#  define MSDOS
#endif
#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
#  define OS2
#endif
#if defined(_WINDOWS) && !defined(WINDOWS)
#  define WINDOWS
#endif
#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
#  ifndef WIN32
#    define WIN32
#  endif
#endif
#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
#  if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
#    ifndef SYS16BIT
#      define SYS16BIT
#    endif
#  endif
#endif

/*
 * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
 * than 64k bytes at a time (needed on systems with 16-bit int).
 */
#ifdef SYS16BIT
#  define MAXSEG_64K
#endif
#ifdef MSDOS
#  define UNALIGNED_OK
#endif

#ifdef __STDC_VERSION__
#  ifndef STDC
#    define STDC
#  endif
#  if __STDC_VERSION__ >= 199901L
#    ifndef STDC99
#      define STDC99
#    endif
#  endif
#endif
#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
#  define STDC
#endif
#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
#  define STDC
#endif
#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
#  define STDC
#endif
#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
#  define STDC
#endif

#if defined(__OS400__) && !defined(STDC)    /* iSeries (formerly AS/400). */
#  define STDC
#endif

#ifndef STDC
#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
#    define const       /* note: need a more gentle solution here */
#  endif
#endif

/* Some Mac compilers merge all .h files incorrectly: */
#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
#  define NO_DUMMY_DECL
#endif

/* Maximum value for memLevel in deflateInit2 */
#ifndef MAX_MEM_LEVEL
#  ifdef MAXSEG_64K
#    define MAX_MEM_LEVEL 8
#  else
#    define MAX_MEM_LEVEL 9
#  endif
#endif

/* Maximum value for windowBits in deflateInit2 and inflateInit2.
 * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
 * created by gzip. (Files created by minigzip can still be extracted by
 * gzip.)
 */
#ifndef MAX_WBITS
#  define MAX_WBITS   15 /* 32K LZ77 window */
#endif

/* The memory requirements for deflate are (in bytes):
            (1 << (windowBits+2)) +  (1 << (memLevel+9))
 that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
 plus a few kilobytes for small objects. For example, if you want to reduce
 the default memory requirements from 256K to 128K, compile with
     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
 Of course this will generally degrade compression (there's no free lunch).

   The memory requirements for inflate are (in bytes) 1 << windowBits
 that is, 32K for windowBits=15 (default value) plus a few kilobytes
 for small objects.
*/

                        /* Type declarations */

#ifndef OF /* function prototypes */
#  ifdef STDC
#    define OF(args)  args
#  else
#    define OF(args)  ()
#  endif
#endif

/* The following definitions for FAR are needed only for MSDOS mixed
 * model programming (small or medium model with some far allocations).
 * This was tested only with MSC; for other MSDOS compilers you may have
 * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
 * just define FAR to be empty.
 */
#ifdef SYS16BIT
#  if defined(M_I86SM) || defined(M_I86MM)
     /* MSC small or medium model */
#    define SMALL_MEDIUM
#    ifdef _MSC_VER
#      define FAR _far
#    else
#      define FAR far
#    endif
#  endif
#  if (defined(__SMALL__) || defined(__MEDIUM__))
     /* Turbo C small or medium model */
#    define SMALL_MEDIUM
#    ifdef __BORLANDC__
#      define FAR _far
#    else
#      define FAR far
#    endif
#  endif
#endif

#if defined(WINDOWS) || defined(WIN32)
   /* If building or using zlib as a DLL, define ZLIB_DLL.
    * This is not mandatory, but it offers a little performance increase.
    */
#  ifdef ZLIB_DLL
#    if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
#      ifdef ZLIB_INTERNAL
#        define ZEXTERN extern __declspec(dllexport)
#      else
#        define ZEXTERN extern __declspec(dllimport)
#      endif
#    endif
#  endif  /* ZLIB_DLL */
   /* If building or using zlib with the WINAPI/WINAPIV calling convention,
    * define ZLIB_WINAPI.
    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
    */
#  ifdef ZLIB_WINAPI
#    ifdef FAR
#      undef FAR
#    endif
#    include 
     /* No need for _export, use ZLIB.DEF instead. */
     /* For complete Windows compatibility, use WINAPI, not __stdcall. */
#    define ZEXPORT WINAPI
#    ifdef WIN32
#      define ZEXPORTVA WINAPIV
#    else
#      define ZEXPORTVA FAR CDECL
#    endif
#  endif
#endif

#if defined (__BEOS__)
#  ifdef ZLIB_DLL
#    ifdef ZLIB_INTERNAL
#      define ZEXPORT   __declspec(dllexport)
#      define ZEXPORTVA __declspec(dllexport)
#    else
#      define ZEXPORT   __declspec(dllimport)
#      define ZEXPORTVA __declspec(dllimport)
#    endif
#  endif
#endif

#ifndef ZEXTERN
#  define ZEXTERN extern
#endif
#ifndef ZEXPORT
#  define ZEXPORT
#endif
#ifndef ZEXPORTVA
#  define ZEXPORTVA
#endif

#ifndef FAR
#  define FAR
#endif

#if !defined(__MACTYPES__)
typedef unsigned char  Byte;  /* 8 bits */
#endif
typedef unsigned int   uInt;  /* 16 bits or more */
typedef unsigned long  uLong; /* 32 bits or more */

#ifdef SMALL_MEDIUM
   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
#  define Bytef Byte FAR
#else
   typedef Byte  FAR Bytef;
#endif
typedef char  FAR charf;
typedef int   FAR intf;
typedef uInt  FAR uIntf;
typedef uLong FAR uLongf;

#ifdef STDC
   typedef void const *voidpc;
   typedef void FAR   *voidpf;
   typedef void       *voidp;
#else
   typedef Byte const *voidpc;
   typedef Byte FAR   *voidpf;
   typedef Byte       *voidp;
#endif

#if !defined(MSDOS) && !defined(WINDOWS) && !defined(WIN32)
#  define Z_HAVE_UNISTD_H
#endif

#ifdef STDC
#  include     /* for off_t */
#endif

/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
 * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
 * though the former does not conform to the LFS document), but considering
 * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
 * equivalently requesting no 64-bit operations
 */
#if -_LARGEFILE64_SOURCE - -1 == 1
#  undef _LARGEFILE64_SOURCE
#endif

#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
#  include        /* for SEEK_* and off_t */
#  ifdef VMS
#    include      /* for off_t */
#  endif
#  ifndef z_off_t
#    define z_off_t off_t
#  endif
#endif

#ifndef SEEK_SET
#  define SEEK_SET        0       /* Seek from beginning of file.  */
#  define SEEK_CUR        1       /* Seek from current position.  */
#  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
#endif

#ifndef z_off_t
#  define z_off_t long
#endif

#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
#  define z_off64_t off64_t
#else
#  define z_off64_t z_off_t
#endif

#if defined(__OS400__)
#  define NO_vsnprintf
#endif

#if defined(__MVS__)
#  define NO_vsnprintf
#endif

/* MVS linker does not support external names larger than 8 bytes */
#if defined(__MVS__)
  #pragma map(deflateInit_,"DEIN")
  #pragma map(deflateInit2_,"DEIN2")
  #pragma map(deflateEnd,"DEEND")
  #pragma map(deflateBound,"DEBND")
  #pragma map(inflateInit_,"ININ")
  #pragma map(inflateInit2_,"ININ2")
  #pragma map(inflateEnd,"INEND")
  #pragma map(inflateSync,"INSY")
  #pragma map(inflateSetDictionary,"INSEDI")
  #pragma map(compressBound,"CMBND")
  #pragma map(inflate_table,"INTABL")
  #pragma map(inflate_fast,"INFA")
  #pragma map(inflate_copyright,"INCOPY")
#endif

#endif /* ZCONF_H */
cfitsio/zlib/zlib.h0000644000225700000360000023331413246025103014057 0ustar  cagordonlhea/* zlib.h -- interface of the 'zlib' general purpose compression library
  version 1.2.5, April 19th, 2010

  Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler

  This software is provided 'as-is', without any express or implied
  warranty.  In no event will the authors be held liable for any damages
  arising from the use of this software.

  Permission is granted to anyone to use this software for any purpose,
  including commercial applications, and to alter it and redistribute it
  freely, subject to the following restrictions:

  1. The origin of this software must not be misrepresented; you must not
     claim that you wrote the original software. If you use this software
     in a product, an acknowledgment in the product documentation would be
     appreciated but is not required.
  2. Altered source versions must be plainly marked as such, and must not be
     misrepresented as being the original software.
  3. This notice may not be removed or altered from any source distribution.

  Jean-loup Gailly        Mark Adler
  jloup@gzip.org          madler@alumni.caltech.edu


  The data format used by the zlib library is described by RFCs (Request for
  Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt
  (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
*/

#ifndef ZLIB_H
#define ZLIB_H

#include "zconf.h"

#ifdef __cplusplus
extern "C" {
#endif

#define ZLIB_VERSION "1.2.5"
#define ZLIB_VERNUM 0x1250
#define ZLIB_VER_MAJOR 1
#define ZLIB_VER_MINOR 2
#define ZLIB_VER_REVISION 5
#define ZLIB_VER_SUBREVISION 0

/*
    The 'zlib' compression library provides in-memory compression and
  decompression functions, including integrity checks of the uncompressed data.
  This version of the library supports only one compression method (deflation)
  but other algorithms will be added later and will have the same stream
  interface.

    Compression can be done in a single step if the buffers are large enough,
  or can be done by repeated calls of the compression function.  In the latter
  case, the application must provide more input and/or consume the output
  (providing more output space) before each call.

    The compressed data format used by default by the in-memory functions is
  the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
  around a deflate stream, which is itself documented in RFC 1951.

    The library also supports reading and writing files in gzip (.gz) format
  with an interface similar to that of stdio using the functions that start
  with "gz".  The gzip format is different from the zlib format.  gzip is a
  gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.

    This library can optionally read and write gzip streams in memory as well.

    The zlib format was designed to be compact and fast for use in memory
  and on communications channels.  The gzip format was designed for single-
  file compression on file systems, has a larger header than zlib to maintain
  directory information, and uses a different, slower check method than zlib.

    The library does not install any signal handler.  The decoder checks
  the consistency of the compressed data, so the library should never crash
  even in case of corrupted input.
*/

typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
typedef void   (*free_func)  OF((voidpf opaque, voidpf address));

struct internal_state;

typedef struct z_stream_s {
    Bytef    *next_in;  /* next input byte */
    uInt     avail_in;  /* number of bytes available at next_in */
    uLong    total_in;  /* total nb of input bytes read so far */

    Bytef    *next_out; /* next output byte should be put there */
    uInt     avail_out; /* remaining free space at next_out */
    uLong    total_out; /* total nb of bytes output so far */

    char     *msg;      /* last error message, NULL if no error */
    struct internal_state FAR *state; /* not visible by applications */

    alloc_func zalloc;  /* used to allocate the internal state */
    free_func  zfree;   /* used to free the internal state */
    voidpf     opaque;  /* private data object passed to zalloc and zfree */

    int     data_type;  /* best guess about the data type: binary or text */
    uLong   adler;      /* adler32 value of the uncompressed data */
    uLong   reserved;   /* reserved for future use */
} z_stream;

typedef z_stream FAR *z_streamp;

/*
     gzip header information passed to and from zlib routines.  See RFC 1952
  for more details on the meanings of these fields.
*/
typedef struct gz_header_s {
    int     text;       /* true if compressed data believed to be text */
    uLong   time;       /* modification time */
    int     xflags;     /* extra flags (not used when writing a gzip file) */
    int     os;         /* operating system */
    Bytef   *extra;     /* pointer to extra field or Z_NULL if none */
    uInt    extra_len;  /* extra field length (valid if extra != Z_NULL) */
    uInt    extra_max;  /* space at extra (only when reading header) */
    Bytef   *name;      /* pointer to zero-terminated file name or Z_NULL */
    uInt    name_max;   /* space at name (only when reading header) */
    Bytef   *comment;   /* pointer to zero-terminated comment or Z_NULL */
    uInt    comm_max;   /* space at comment (only when reading header) */
    int     hcrc;       /* true if there was or will be a header crc */
    int     done;       /* true when done reading gzip header (not used
                           when writing a gzip file) */
} gz_header;

typedef gz_header FAR *gz_headerp;

/*
     The application must update next_in and avail_in when avail_in has dropped
   to zero.  It must update next_out and avail_out when avail_out has dropped
   to zero.  The application must initialize zalloc, zfree and opaque before
   calling the init function.  All other fields are set by the compression
   library and must not be updated by the application.

     The opaque value provided by the application will be passed as the first
   parameter for calls of zalloc and zfree.  This can be useful for custom
   memory management.  The compression library attaches no meaning to the
   opaque value.

     zalloc must return Z_NULL if there is not enough memory for the object.
   If zlib is used in a multi-threaded application, zalloc and zfree must be
   thread safe.

     On 16-bit systems, the functions zalloc and zfree must be able to allocate
   exactly 65536 bytes, but will not be required to allocate more than this if
   the symbol MAXSEG_64K is defined (see zconf.h).  WARNING: On MSDOS, pointers
   returned by zalloc for objects of exactly 65536 bytes *must* have their
   offset normalized to zero.  The default allocation function provided by this
   library ensures this (see zutil.c).  To reduce memory requirements and avoid
   any allocation of 64K objects, at the expense of compression ratio, compile
   the library with -DMAX_WBITS=14 (see zconf.h).

     The fields total_in and total_out can be used for statistics or progress
   reports.  After compression, total_in holds the total size of the
   uncompressed data and may be saved for use in the decompressor (particularly
   if the decompressor wants to decompress everything in a single step).
*/

                        /* constants */

#define Z_NO_FLUSH      0
#define Z_PARTIAL_FLUSH 1
#define Z_SYNC_FLUSH    2
#define Z_FULL_FLUSH    3
#define Z_FINISH        4
#define Z_BLOCK         5
#define Z_TREES         6
/* Allowed flush values; see deflate() and inflate() below for details */

#define Z_OK            0
#define Z_STREAM_END    1
#define Z_NEED_DICT     2
#define Z_ERRNO        (-1)
#define Z_STREAM_ERROR (-2)
#define Z_DATA_ERROR   (-3)
#define Z_MEM_ERROR    (-4)
#define Z_BUF_ERROR    (-5)
#define Z_VERSION_ERROR (-6)
/* Return codes for the compression/decompression functions. Negative values
 * are errors, positive values are used for special but normal events.
 */

#define Z_NO_COMPRESSION         0
#define Z_BEST_SPEED             1
#define Z_BEST_COMPRESSION       9
#define Z_DEFAULT_COMPRESSION  (-1)
/* compression levels */

#define Z_FILTERED            1
#define Z_HUFFMAN_ONLY        2
#define Z_RLE                 3
#define Z_FIXED               4
#define Z_DEFAULT_STRATEGY    0
/* compression strategy; see deflateInit2() below for details */

#define Z_BINARY   0
#define Z_TEXT     1
#define Z_ASCII    Z_TEXT   /* for compatibility with 1.2.2 and earlier */
#define Z_UNKNOWN  2
/* Possible values of the data_type field (though see inflate()) */

#define Z_DEFLATED   8
/* The deflate compression method (the only one supported in this version) */

#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */

#define zlib_version zlibVersion()
/* for compatibility with versions < 1.0.2 */


                        /* basic functions */

ZEXTERN const char * ZEXPORT zlibVersion OF((void));
/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
   If the first character differs, the library code actually used is not
   compatible with the zlib.h header file used by the application.  This check
   is automatically made by deflateInit and inflateInit.
 */

/*
ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));

     Initializes the internal stream state for compression.  The fields
   zalloc, zfree and opaque must be initialized before by the caller.  If
   zalloc and zfree are set to Z_NULL, deflateInit updates them to use default
   allocation functions.

     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
   1 gives best speed, 9 gives best compression, 0 gives no compression at all
   (the input data is simply copied a block at a time).  Z_DEFAULT_COMPRESSION
   requests a default compromise between speed and compression (currently
   equivalent to level 6).

     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
   memory, Z_STREAM_ERROR if level is not a valid compression level, or
   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
   with the version assumed by the caller (ZLIB_VERSION).  msg is set to null
   if there is no error message.  deflateInit does not perform any compression:
   this will be done by deflate().
*/


ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
/*
    deflate compresses as much data as possible, and stops when the input
  buffer becomes empty or the output buffer becomes full.  It may introduce
  some output latency (reading input without producing any output) except when
  forced to flush.

    The detailed semantics are as follows.  deflate performs one or both of the
  following actions:

  - Compress more input starting at next_in and update next_in and avail_in
    accordingly.  If not all input can be processed (because there is not
    enough room in the output buffer), next_in and avail_in are updated and
    processing will resume at this point for the next call of deflate().

  - Provide more output starting at next_out and update next_out and avail_out
    accordingly.  This action is forced if the parameter flush is non zero.
    Forcing flush frequently degrades the compression ratio, so this parameter
    should be set only when necessary (in interactive applications).  Some
    output may be provided even if flush is not set.

    Before the call of deflate(), the application should ensure that at least
  one of the actions is possible, by providing more input and/or consuming more
  output, and updating avail_in or avail_out accordingly; avail_out should
  never be zero before the call.  The application can consume the compressed
  output when it wants, for example when the output buffer is full (avail_out
  == 0), or after each call of deflate().  If deflate returns Z_OK and with
  zero avail_out, it must be called again after making room in the output
  buffer because there might be more output pending.

    Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
  decide how much data to accumulate before producing output, in order to
  maximize compression.

    If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
  flushed to the output buffer and the output is aligned on a byte boundary, so
  that the decompressor can get all input data available so far.  (In
  particular avail_in is zero after the call if enough output space has been
  provided before the call.) Flushing may degrade compression for some
  compression algorithms and so it should be used only when necessary.  This
  completes the current deflate block and follows it with an empty stored block
  that is three bits plus filler bits to the next byte, followed by four bytes
  (00 00 ff ff).

    If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the
  output buffer, but the output is not aligned to a byte boundary.  All of the
  input data so far will be available to the decompressor, as for Z_SYNC_FLUSH.
  This completes the current deflate block and follows it with an empty fixed
  codes block that is 10 bits long.  This assures that enough bytes are output
  in order for the decompressor to finish the block before the empty fixed code
  block.

    If flush is set to Z_BLOCK, a deflate block is completed and emitted, as
  for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to
  seven bits of the current block are held to be written as the next byte after
  the next deflate block is completed.  In this case, the decompressor may not
  be provided enough bits at this point in order to complete decompression of
  the data provided so far to the compressor.  It may need to wait for the next
  block to be emitted.  This is for advanced applications that need to control
  the emission of deflate blocks.

    If flush is set to Z_FULL_FLUSH, all output is flushed as with
  Z_SYNC_FLUSH, and the compression state is reset so that decompression can
  restart from this point if previous compressed data has been damaged or if
  random access is desired.  Using Z_FULL_FLUSH too often can seriously degrade
  compression.

    If deflate returns with avail_out == 0, this function must be called again
  with the same value of the flush parameter and more output space (updated
  avail_out), until the flush is complete (deflate returns with non-zero
  avail_out).  In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
  avail_out is greater than six to avoid repeated flush markers due to
  avail_out == 0 on return.

    If the parameter flush is set to Z_FINISH, pending input is processed,
  pending output is flushed and deflate returns with Z_STREAM_END if there was
  enough output space; if deflate returns with Z_OK, this function must be
  called again with Z_FINISH and more output space (updated avail_out) but no
  more input data, until it returns with Z_STREAM_END or an error.  After
  deflate has returned Z_STREAM_END, the only possible operations on the stream
  are deflateReset or deflateEnd.

    Z_FINISH can be used immediately after deflateInit if all the compression
  is to be done in a single step.  In this case, avail_out must be at least the
  value returned by deflateBound (see below).  If deflate does not return
  Z_STREAM_END, then it must be called again as described above.

    deflate() sets strm->adler to the adler32 checksum of all input read
  so far (that is, total_in bytes).

    deflate() may update strm->data_type if it can make a good guess about
  the input data type (Z_BINARY or Z_TEXT).  In doubt, the data is considered
  binary.  This field is only for information purposes and does not affect the
  compression algorithm in any manner.

    deflate() returns Z_OK if some progress has been made (more input
  processed or more output produced), Z_STREAM_END if all input has been
  consumed and all output has been produced (only when flush is set to
  Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
  if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible
  (for example avail_in or avail_out was zero).  Note that Z_BUF_ERROR is not
  fatal, and deflate() can be called again with more input and more output
  space to continue compressing.
*/


ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
/*
     All dynamically allocated data structures for this stream are freed.
   This function discards any unprocessed input and does not flush any pending
   output.

     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
   stream state was inconsistent, Z_DATA_ERROR if the stream was freed
   prematurely (some input or output was discarded).  In the error case, msg
   may be set but then points to a static string (which must not be
   deallocated).
*/


/*
ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));

     Initializes the internal stream state for decompression.  The fields
   next_in, avail_in, zalloc, zfree and opaque must be initialized before by
   the caller.  If next_in is not Z_NULL and avail_in is large enough (the
   exact value depends on the compression method), inflateInit determines the
   compression method from the zlib header and allocates all data structures
   accordingly; otherwise the allocation will be deferred to the first call of
   inflate.  If zalloc and zfree are set to Z_NULL, inflateInit updates them to
   use default allocation functions.

     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
   version assumed by the caller, or Z_STREAM_ERROR if the parameters are
   invalid, such as a null pointer to the structure.  msg is set to null if
   there is no error message.  inflateInit does not perform any decompression
   apart from possibly reading the zlib header if present: actual decompression
   will be done by inflate().  (So next_in and avail_in may be modified, but
   next_out and avail_out are unused and unchanged.) The current implementation
   of inflateInit() does not process any header information -- that is deferred
   until inflate() is called.
*/


ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
/*
    inflate decompresses as much data as possible, and stops when the input
  buffer becomes empty or the output buffer becomes full.  It may introduce
  some output latency (reading input without producing any output) except when
  forced to flush.

  The detailed semantics are as follows.  inflate performs one or both of the
  following actions:

  - Decompress more input starting at next_in and update next_in and avail_in
    accordingly.  If not all input can be processed (because there is not
    enough room in the output buffer), next_in is updated and processing will
    resume at this point for the next call of inflate().

  - Provide more output starting at next_out and update next_out and avail_out
    accordingly.  inflate() provides as much output as possible, until there is
    no more input data or no more space in the output buffer (see below about
    the flush parameter).

    Before the call of inflate(), the application should ensure that at least
  one of the actions is possible, by providing more input and/or consuming more
  output, and updating the next_* and avail_* values accordingly.  The
  application can consume the uncompressed output when it wants, for example
  when the output buffer is full (avail_out == 0), or after each call of
  inflate().  If inflate returns Z_OK and with zero avail_out, it must be
  called again after making room in the output buffer because there might be
  more output pending.

    The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH,
  Z_BLOCK, or Z_TREES.  Z_SYNC_FLUSH requests that inflate() flush as much
  output as possible to the output buffer.  Z_BLOCK requests that inflate()
  stop if and when it gets to the next deflate block boundary.  When decoding
  the zlib or gzip format, this will cause inflate() to return immediately
  after the header and before the first block.  When doing a raw inflate,
  inflate() will go ahead and process the first block, and will return when it
  gets to the end of that block, or when it runs out of data.

    The Z_BLOCK option assists in appending to or combining deflate streams.
  Also to assist in this, on return inflate() will set strm->data_type to the
  number of unused bits in the last byte taken from strm->next_in, plus 64 if
  inflate() is currently decoding the last block in the deflate stream, plus
  128 if inflate() returned immediately after decoding an end-of-block code or
  decoding the complete header up to just before the first byte of the deflate
  stream.  The end-of-block will not be indicated until all of the uncompressed
  data from that block has been written to strm->next_out.  The number of
  unused bits may in general be greater than seven, except when bit 7 of
  data_type is set, in which case the number of unused bits will be less than
  eight.  data_type is set as noted here every time inflate() returns for all
  flush options, and so can be used to determine the amount of currently
  consumed input in bits.

    The Z_TREES option behaves as Z_BLOCK does, but it also returns when the
  end of each deflate block header is reached, before any actual data in that
  block is decoded.  This allows the caller to determine the length of the
  deflate block header for later use in random access within a deflate block.
  256 is added to the value of strm->data_type when inflate() returns
  immediately after reaching the end of the deflate block header.

    inflate() should normally be called until it returns Z_STREAM_END or an
  error.  However if all decompression is to be performed in a single step (a
  single call of inflate), the parameter flush should be set to Z_FINISH.  In
  this case all pending input is processed and all pending output is flushed;
  avail_out must be large enough to hold all the uncompressed data.  (The size
  of the uncompressed data may have been saved by the compressor for this
  purpose.) The next operation on this stream must be inflateEnd to deallocate
  the decompression state.  The use of Z_FINISH is never required, but can be
  used to inform inflate that a faster approach may be used for the single
  inflate() call.

     In this implementation, inflate() always flushes as much output as
  possible to the output buffer, and always uses the faster approach on the
  first call.  So the only effect of the flush parameter in this implementation
  is on the return value of inflate(), as noted below, or when it returns early
  because Z_BLOCK or Z_TREES is used.

     If a preset dictionary is needed after this call (see inflateSetDictionary
  below), inflate sets strm->adler to the adler32 checksum of the dictionary
  chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
  strm->adler to the adler32 checksum of all output produced so far (that is,
  total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
  below.  At the end of the stream, inflate() checks that its computed adler32
  checksum is equal to that saved by the compressor and returns Z_STREAM_END
  only if the checksum is correct.

    inflate() can decompress and check either zlib-wrapped or gzip-wrapped
  deflate data.  The header type is detected automatically, if requested when
  initializing with inflateInit2().  Any information contained in the gzip
  header is not retained, so applications that need that information should
  instead use raw inflate, see inflateInit2() below, or inflateBack() and
  perform their own processing of the gzip header and trailer.

    inflate() returns Z_OK if some progress has been made (more input processed
  or more output produced), Z_STREAM_END if the end of the compressed data has
  been reached and all uncompressed output has been produced, Z_NEED_DICT if a
  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
  corrupted (input stream not conforming to the zlib format or incorrect check
  value), Z_STREAM_ERROR if the stream structure was inconsistent (for example
  next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory,
  Z_BUF_ERROR if no progress is possible or if there was not enough room in the
  output buffer when Z_FINISH is used.  Note that Z_BUF_ERROR is not fatal, and
  inflate() can be called again with more input and more output space to
  continue decompressing.  If Z_DATA_ERROR is returned, the application may
  then call inflateSync() to look for a good compression block if a partial
  recovery of the data is desired.
*/


ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
/*
     All dynamically allocated data structures for this stream are freed.
   This function discards any unprocessed input and does not flush any pending
   output.

     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
   was inconsistent.  In the error case, msg may be set but then points to a
   static string (which must not be deallocated).
*/


                        /* Advanced functions */

/*
    The following functions are needed only in some special applications.
*/

/*
ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
                                     int  level,
                                     int  method,
                                     int  windowBits,
                                     int  memLevel,
                                     int  strategy));

     This is another version of deflateInit with more compression options.  The
   fields next_in, zalloc, zfree and opaque must be initialized before by the
   caller.

     The method parameter is the compression method.  It must be Z_DEFLATED in
   this version of the library.

     The windowBits parameter is the base two logarithm of the window size
   (the size of the history buffer).  It should be in the range 8..15 for this
   version of the library.  Larger values of this parameter result in better
   compression at the expense of memory usage.  The default value is 15 if
   deflateInit is used instead.

     windowBits can also be -8..-15 for raw deflate.  In this case, -windowBits
   determines the window size.  deflate() will then generate raw deflate data
   with no zlib header or trailer, and will not compute an adler32 check value.

     windowBits can also be greater than 15 for optional gzip encoding.  Add
   16 to windowBits to write a simple gzip header and trailer around the
   compressed data instead of a zlib wrapper.  The gzip header will have no
   file name, no extra data, no comment, no modification time (set to zero), no
   header crc, and the operating system will be set to 255 (unknown).  If a
   gzip stream is being written, strm->adler is a crc32 instead of an adler32.

     The memLevel parameter specifies how much memory should be allocated
   for the internal compression state.  memLevel=1 uses minimum memory but is
   slow and reduces compression ratio; memLevel=9 uses maximum memory for
   optimal speed.  The default value is 8.  See zconf.h for total memory usage
   as a function of windowBits and memLevel.

     The strategy parameter is used to tune the compression algorithm.  Use the
   value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
   filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
   string match), or Z_RLE to limit match distances to one (run-length
   encoding).  Filtered data consists mostly of small values with a somewhat
   random distribution.  In this case, the compression algorithm is tuned to
   compress them better.  The effect of Z_FILTERED is to force more Huffman
   coding and less string matching; it is somewhat intermediate between
   Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY.  Z_RLE is designed to be almost as
   fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data.  The
   strategy parameter only affects the compression ratio but not the
   correctness of the compressed output even if it is not set appropriately.
   Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler
   decoder for special applications.

     deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
   memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid
   method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is
   incompatible with the version assumed by the caller (ZLIB_VERSION).  msg is
   set to null if there is no error message.  deflateInit2 does not perform any
   compression: this will be done by deflate().
*/

ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
                                             const Bytef *dictionary,
                                             uInt  dictLength));
/*
     Initializes the compression dictionary from the given byte sequence
   without producing any compressed output.  This function must be called
   immediately after deflateInit, deflateInit2 or deflateReset, before any call
   of deflate.  The compressor and decompressor must use exactly the same
   dictionary (see inflateSetDictionary).

     The dictionary should consist of strings (byte sequences) that are likely
   to be encountered later in the data to be compressed, with the most commonly
   used strings preferably put towards the end of the dictionary.  Using a
   dictionary is most useful when the data to be compressed is short and can be
   predicted with good accuracy; the data can then be compressed better than
   with the default empty dictionary.

     Depending on the size of the compression data structures selected by
   deflateInit or deflateInit2, a part of the dictionary may in effect be
   discarded, for example if the dictionary is larger than the window size
   provided in deflateInit or deflateInit2.  Thus the strings most likely to be
   useful should be put at the end of the dictionary, not at the front.  In
   addition, the current implementation of deflate will use at most the window
   size minus 262 bytes of the provided dictionary.

     Upon return of this function, strm->adler is set to the adler32 value
   of the dictionary; the decompressor may later use this value to determine
   which dictionary has been used by the compressor.  (The adler32 value
   applies to the whole dictionary even if only a subset of the dictionary is
   actually used by the compressor.) If a raw deflate was requested, then the
   adler32 value is not computed and strm->adler is not set.

     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is
   inconsistent (for example if deflate has already been called for this stream
   or if the compression method is bsort).  deflateSetDictionary does not
   perform any compression: this will be done by deflate().
*/

ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
                                    z_streamp source));
/*
     Sets the destination stream as a complete copy of the source stream.

     This function can be useful when several compression strategies will be
   tried, for example when there are several ways of pre-processing the input
   data with a filter.  The streams that will be discarded should then be freed
   by calling deflateEnd.  Note that deflateCopy duplicates the internal
   compression state which can be quite large, so this strategy is slow and can
   consume lots of memory.

     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
   (such as zalloc being Z_NULL).  msg is left unchanged in both source and
   destination.
*/

ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
/*
     This function is equivalent to deflateEnd followed by deflateInit,
   but does not free and reallocate all the internal compression state.  The
   stream will keep the same compression level and any other attributes that
   may have been set by deflateInit2.

     deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
   stream state was inconsistent (such as zalloc or state being Z_NULL).
*/

ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
                                      int level,
                                      int strategy));
/*
     Dynamically update the compression level and compression strategy.  The
   interpretation of level and strategy is as in deflateInit2.  This can be
   used to switch between compression and straight copy of the input data, or
   to switch to a different kind of input data requiring a different strategy.
   If the compression level is changed, the input available so far is
   compressed with the old level (and may be flushed); the new level will take
   effect only at the next call of deflate().

     Before the call of deflateParams, the stream state must be set as for
   a call of deflate(), since the currently available input may have to be
   compressed and flushed.  In particular, strm->avail_out must be non-zero.

     deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
   stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if
   strm->avail_out was zero.
*/

ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
                                    int good_length,
                                    int max_lazy,
                                    int nice_length,
                                    int max_chain));
/*
     Fine tune deflate's internal compression parameters.  This should only be
   used by someone who understands the algorithm used by zlib's deflate for
   searching for the best matching string, and even then only by the most
   fanatic optimizer trying to squeeze out the last compressed bit for their
   specific input data.  Read the deflate.c source code for the meaning of the
   max_lazy, good_length, nice_length, and max_chain parameters.

     deflateTune() can be called after deflateInit() or deflateInit2(), and
   returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
 */

ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
                                       uLong sourceLen));
/*
     deflateBound() returns an upper bound on the compressed size after
   deflation of sourceLen bytes.  It must be called after deflateInit() or
   deflateInit2(), and after deflateSetHeader(), if used.  This would be used
   to allocate an output buffer for deflation in a single pass, and so would be
   called before deflate().
*/

ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
                                     int bits,
                                     int value));
/*
     deflatePrime() inserts bits in the deflate output stream.  The intent
   is that this function is used to start off the deflate output with the bits
   leftover from a previous deflate stream when appending to it.  As such, this
   function can only be used for raw deflate, and must be used before the first
   deflate() call after a deflateInit2() or deflateReset().  bits must be less
   than or equal to 16, and that many of the least significant bits of value
   will be inserted in the output.

     deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
   stream state was inconsistent.
*/

ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
                                         gz_headerp head));
/*
     deflateSetHeader() provides gzip header information for when a gzip
   stream is requested by deflateInit2().  deflateSetHeader() may be called
   after deflateInit2() or deflateReset() and before the first call of
   deflate().  The text, time, os, extra field, name, and comment information
   in the provided gz_header structure are written to the gzip header (xflag is
   ignored -- the extra flags are set according to the compression level).  The
   caller must assure that, if not Z_NULL, name and comment are terminated with
   a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
   available there.  If hcrc is true, a gzip header crc is included.  Note that
   the current versions of the command-line version of gzip (up through version
   1.3.x) do not support header crc's, and will report that it is a "multi-part
   gzip file" and give up.

     If deflateSetHeader is not used, the default gzip header has text false,
   the time set to zero, and os set to 255, with no extra, name, or comment
   fields.  The gzip header is returned to the default state by deflateReset().

     deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
   stream state was inconsistent.
*/

/*
ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
                                     int  windowBits));

     This is another version of inflateInit with an extra parameter.  The
   fields next_in, avail_in, zalloc, zfree and opaque must be initialized
   before by the caller.

     The windowBits parameter is the base two logarithm of the maximum window
   size (the size of the history buffer).  It should be in the range 8..15 for
   this version of the library.  The default value is 15 if inflateInit is used
   instead.  windowBits must be greater than or equal to the windowBits value
   provided to deflateInit2() while compressing, or it must be equal to 15 if
   deflateInit2() was not used.  If a compressed stream with a larger window
   size is given as input, inflate() will return with the error code
   Z_DATA_ERROR instead of trying to allocate a larger window.

     windowBits can also be zero to request that inflate use the window size in
   the zlib header of the compressed stream.

     windowBits can also be -8..-15 for raw inflate.  In this case, -windowBits
   determines the window size.  inflate() will then process raw deflate data,
   not looking for a zlib or gzip header, not generating a check value, and not
   looking for any check values for comparison at the end of the stream.  This
   is for use with other formats that use the deflate compressed data format
   such as zip.  Those formats provide their own check values.  If a custom
   format is developed using the raw deflate format for compressed data, it is
   recommended that a check value such as an adler32 or a crc32 be applied to
   the uncompressed data as is done in the zlib, gzip, and zip formats.  For
   most applications, the zlib format should be used as is.  Note that comments
   above on the use in deflateInit2() applies to the magnitude of windowBits.

     windowBits can also be greater than 15 for optional gzip decoding.  Add
   32 to windowBits to enable zlib and gzip decoding with automatic header
   detection, or add 16 to decode only the gzip format (the zlib format will
   return a Z_DATA_ERROR).  If a gzip stream is being decoded, strm->adler is a
   crc32 instead of an adler32.

     inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
   version assumed by the caller, or Z_STREAM_ERROR if the parameters are
   invalid, such as a null pointer to the structure.  msg is set to null if
   there is no error message.  inflateInit2 does not perform any decompression
   apart from possibly reading the zlib header if present: actual decompression
   will be done by inflate().  (So next_in and avail_in may be modified, but
   next_out and avail_out are unused and unchanged.) The current implementation
   of inflateInit2() does not process any header information -- that is
   deferred until inflate() is called.
*/

ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
                                             const Bytef *dictionary,
                                             uInt  dictLength));
/*
     Initializes the decompression dictionary from the given uncompressed byte
   sequence.  This function must be called immediately after a call of inflate,
   if that call returned Z_NEED_DICT.  The dictionary chosen by the compressor
   can be determined from the adler32 value returned by that call of inflate.
   The compressor and decompressor must use exactly the same dictionary (see
   deflateSetDictionary).  For raw inflate, this function can be called
   immediately after inflateInit2() or inflateReset() and before any call of
   inflate() to set the dictionary.  The application must insure that the
   dictionary that was used for compression is provided.

     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is
   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
   expected one (incorrect adler32 value).  inflateSetDictionary does not
   perform any decompression: this will be done by subsequent calls of
   inflate().
*/

ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
/*
     Skips invalid compressed data until a full flush point (see above the
   description of deflate with Z_FULL_FLUSH) can be found, or until all
   available input is skipped.  No output is provided.

     inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
   if no more input was provided, Z_DATA_ERROR if no flush point has been
   found, or Z_STREAM_ERROR if the stream structure was inconsistent.  In the
   success case, the application may save the current current value of total_in
   which indicates where valid compressed data was found.  In the error case,
   the application may repeatedly call inflateSync, providing more input each
   time, until success or end of the input data.
*/

ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
                                    z_streamp source));
/*
     Sets the destination stream as a complete copy of the source stream.

     This function can be useful when randomly accessing a large stream.  The
   first pass through the stream can periodically record the inflate state,
   allowing restarting inflate at those points when randomly accessing the
   stream.

     inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
   (such as zalloc being Z_NULL).  msg is left unchanged in both source and
   destination.
*/

ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
/*
     This function is equivalent to inflateEnd followed by inflateInit,
   but does not free and reallocate all the internal decompression state.  The
   stream will keep attributes that may have been set by inflateInit2.

     inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
   stream state was inconsistent (such as zalloc or state being Z_NULL).
*/

ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm,
                                      int windowBits));
/*
     This function is the same as inflateReset, but it also permits changing
   the wrap and window size requests.  The windowBits parameter is interpreted
   the same as it is for inflateInit2.

     inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source
   stream state was inconsistent (such as zalloc or state being Z_NULL), or if
   the windowBits parameter is invalid.
*/

ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
                                     int bits,
                                     int value));
/*
     This function inserts bits in the inflate input stream.  The intent is
   that this function is used to start inflating at a bit position in the
   middle of a byte.  The provided bits will be used before any bytes are used
   from next_in.  This function should only be used with raw inflate, and
   should be used before the first inflate() call after inflateInit2() or
   inflateReset().  bits must be less than or equal to 16, and that many of the
   least significant bits of value will be inserted in the input.

     If bits is negative, then the input stream bit buffer is emptied.  Then
   inflatePrime() can be called again to put bits in the buffer.  This is used
   to clear out bits leftover after feeding inflate a block description prior
   to feeding inflate codes.

     inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
   stream state was inconsistent.
*/

ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm));
/*
     This function returns two values, one in the lower 16 bits of the return
   value, and the other in the remaining upper bits, obtained by shifting the
   return value down 16 bits.  If the upper value is -1 and the lower value is
   zero, then inflate() is currently decoding information outside of a block.
   If the upper value is -1 and the lower value is non-zero, then inflate is in
   the middle of a stored block, with the lower value equaling the number of
   bytes from the input remaining to copy.  If the upper value is not -1, then
   it is the number of bits back from the current bit position in the input of
   the code (literal or length/distance pair) currently being processed.  In
   that case the lower value is the number of bytes already emitted for that
   code.

     A code is being processed if inflate is waiting for more input to complete
   decoding of the code, or if it has completed decoding but is waiting for
   more output space to write the literal or match data.

     inflateMark() is used to mark locations in the input data for random
   access, which may be at bit positions, and to note those cases where the
   output of a code may span boundaries of random access blocks.  The current
   location in the input stream can be determined from avail_in and data_type
   as noted in the description for the Z_BLOCK flush parameter for inflate.

     inflateMark returns the value noted above or -1 << 16 if the provided
   source stream state was inconsistent.
*/

ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
                                         gz_headerp head));
/*
     inflateGetHeader() requests that gzip header information be stored in the
   provided gz_header structure.  inflateGetHeader() may be called after
   inflateInit2() or inflateReset(), and before the first call of inflate().
   As inflate() processes the gzip stream, head->done is zero until the header
   is completed, at which time head->done is set to one.  If a zlib stream is
   being decoded, then head->done is set to -1 to indicate that there will be
   no gzip header information forthcoming.  Note that Z_BLOCK or Z_TREES can be
   used to force inflate() to return immediately after header processing is
   complete and before any actual data is decompressed.

     The text, time, xflags, and os fields are filled in with the gzip header
   contents.  hcrc is set to true if there is a header CRC.  (The header CRC
   was valid if done is set to one.) If extra is not Z_NULL, then extra_max
   contains the maximum number of bytes to write to extra.  Once done is true,
   extra_len contains the actual extra field length, and extra contains the
   extra field, or that field truncated if extra_max is less than extra_len.
   If name is not Z_NULL, then up to name_max characters are written there,
   terminated with a zero unless the length is greater than name_max.  If
   comment is not Z_NULL, then up to comm_max characters are written there,
   terminated with a zero unless the length is greater than comm_max.  When any
   of extra, name, or comment are not Z_NULL and the respective field is not
   present in the header, then that field is set to Z_NULL to signal its
   absence.  This allows the use of deflateSetHeader() with the returned
   structure to duplicate the header.  However if those fields are set to
   allocated memory, then the application will need to save those pointers
   elsewhere so that they can be eventually freed.

     If inflateGetHeader is not used, then the header information is simply
   discarded.  The header is always checked for validity, including the header
   CRC if present.  inflateReset() will reset the process to discard the header
   information.  The application would need to call inflateGetHeader() again to
   retrieve the header from the next gzip stream.

     inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
   stream state was inconsistent.
*/

/*
ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
                                        unsigned char FAR *window));

     Initialize the internal stream state for decompression using inflateBack()
   calls.  The fields zalloc, zfree and opaque in strm must be initialized
   before the call.  If zalloc and zfree are Z_NULL, then the default library-
   derived memory allocation routines are used.  windowBits is the base two
   logarithm of the window size, in the range 8..15.  window is a caller
   supplied buffer of that size.  Except for special applications where it is
   assured that deflate was used with small window sizes, windowBits must be 15
   and a 32K byte window must be supplied to be able to decompress general
   deflate streams.

     See inflateBack() for the usage of these routines.

     inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
   the paramaters are invalid, Z_MEM_ERROR if the internal state could not be
   allocated, or Z_VERSION_ERROR if the version of the library does not match
   the version of the header file.
*/

typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *));
typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));

ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
                                    in_func in, void FAR *in_desc,
                                    out_func out, void FAR *out_desc));
/*
     inflateBack() does a raw inflate with a single call using a call-back
   interface for input and output.  This is more efficient than inflate() for
   file i/o applications in that it avoids copying between the output and the
   sliding window by simply making the window itself the output buffer.  This
   function trusts the application to not change the output buffer passed by
   the output function, at least until inflateBack() returns.

     inflateBackInit() must be called first to allocate the internal state
   and to initialize the state with the user-provided window buffer.
   inflateBack() may then be used multiple times to inflate a complete, raw
   deflate stream with each call.  inflateBackEnd() is then called to free the
   allocated state.

     A raw deflate stream is one with no zlib or gzip header or trailer.
   This routine would normally be used in a utility that reads zip or gzip
   files and writes out uncompressed files.  The utility would decode the
   header and process the trailer on its own, hence this routine expects only
   the raw deflate stream to decompress.  This is different from the normal
   behavior of inflate(), which expects either a zlib or gzip header and
   trailer around the deflate stream.

     inflateBack() uses two subroutines supplied by the caller that are then
   called by inflateBack() for input and output.  inflateBack() calls those
   routines until it reads a complete deflate stream and writes out all of the
   uncompressed data, or until it encounters an error.  The function's
   parameters and return types are defined above in the in_func and out_func
   typedefs.  inflateBack() will call in(in_desc, &buf) which should return the
   number of bytes of provided input, and a pointer to that input in buf.  If
   there is no input available, in() must return zero--buf is ignored in that
   case--and inflateBack() will return a buffer error.  inflateBack() will call
   out(out_desc, buf, len) to write the uncompressed data buf[0..len-1].  out()
   should return zero on success, or non-zero on failure.  If out() returns
   non-zero, inflateBack() will return with an error.  Neither in() nor out()
   are permitted to change the contents of the window provided to
   inflateBackInit(), which is also the buffer that out() uses to write from.
   The length written by out() will be at most the window size.  Any non-zero
   amount of input may be provided by in().

     For convenience, inflateBack() can be provided input on the first call by
   setting strm->next_in and strm->avail_in.  If that input is exhausted, then
   in() will be called.  Therefore strm->next_in must be initialized before
   calling inflateBack().  If strm->next_in is Z_NULL, then in() will be called
   immediately for input.  If strm->next_in is not Z_NULL, then strm->avail_in
   must also be initialized, and then if strm->avail_in is not zero, input will
   initially be taken from strm->next_in[0 ..  strm->avail_in - 1].

     The in_desc and out_desc parameters of inflateBack() is passed as the
   first parameter of in() and out() respectively when they are called.  These
   descriptors can be optionally used to pass any information that the caller-
   supplied in() and out() functions need to do their job.

     On return, inflateBack() will set strm->next_in and strm->avail_in to
   pass back any unused input that was provided by the last in() call.  The
   return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
   if in() or out() returned an error, Z_DATA_ERROR if there was a format error
   in the deflate stream (in which case strm->msg is set to indicate the nature
   of the error), or Z_STREAM_ERROR if the stream was not properly initialized.
   In the case of Z_BUF_ERROR, an input or output error can be distinguished
   using strm->next_in which will be Z_NULL only if in() returned an error.  If
   strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning
   non-zero.  (in() will always be called before out(), so strm->next_in is
   assured to be defined if out() returns non-zero.) Note that inflateBack()
   cannot return Z_OK.
*/

ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
/*
     All memory allocated by inflateBackInit() is freed.

     inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
   state was inconsistent.
*/

ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
/* Return flags indicating compile-time options.

    Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
     1.0: size of uInt
     3.2: size of uLong
     5.4: size of voidpf (pointer)
     7.6: size of z_off_t

    Compiler, assembler, and debug options:
     8: DEBUG
     9: ASMV or ASMINF -- use ASM code
     10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
     11: 0 (reserved)

    One-time table building (smaller code, but not thread-safe if true):
     12: BUILDFIXED -- build static block decoding tables when needed
     13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
     14,15: 0 (reserved)

    Library content (indicates missing functionality):
     16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
                          deflate code when not needed)
     17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
                    and decode gzip streams (to avoid linking crc code)
     18-19: 0 (reserved)

    Operation variations (changes in library functionality):
     20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
     21: FASTEST -- deflate algorithm with only one, lowest compression level
     22,23: 0 (reserved)

    The sprintf variant used by gzprintf (zero is best):
     24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
     25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
     26: 0 = returns value, 1 = void -- 1 means inferred string length returned

    Remainder:
     27-31: 0 (reserved)
 */


                        /* utility functions */

/*
     The following utility functions are implemented on top of the basic
   stream-oriented functions.  To simplify the interface, some default options
   are assumed (compression level and memory usage, standard memory allocation
   functions).  The source code of these utility functions can be modified if
   you need special options.
*/

ZEXTERN int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,
                                 const Bytef *source, uLong sourceLen));
/*
     Compresses the source buffer into the destination buffer.  sourceLen is
   the byte length of the source buffer.  Upon entry, destLen is the total size
   of the destination buffer, which must be at least the value returned by
   compressBound(sourceLen).  Upon exit, destLen is the actual size of the
   compressed buffer.

     compress returns Z_OK if success, Z_MEM_ERROR if there was not
   enough memory, Z_BUF_ERROR if there was not enough room in the output
   buffer.
*/

ZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,
                                  const Bytef *source, uLong sourceLen,
                                  int level));
/*
     Compresses the source buffer into the destination buffer.  The level
   parameter has the same meaning as in deflateInit.  sourceLen is the byte
   length of the source buffer.  Upon entry, destLen is the total size of the
   destination buffer, which must be at least the value returned by
   compressBound(sourceLen).  Upon exit, destLen is the actual size of the
   compressed buffer.

     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
   Z_STREAM_ERROR if the level parameter is invalid.
*/

ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
/*
     compressBound() returns an upper bound on the compressed size after
   compress() or compress2() on sourceLen bytes.  It would be used before a
   compress() or compress2() call to allocate the destination buffer.
*/

ZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,
                                   const Bytef *source, uLong sourceLen));
/*
     Decompresses the source buffer into the destination buffer.  sourceLen is
   the byte length of the source buffer.  Upon entry, destLen is the total size
   of the destination buffer, which must be large enough to hold the entire
   uncompressed data.  (The size of the uncompressed data must have been saved
   previously by the compressor and transmitted to the decompressor by some
   mechanism outside the scope of this compression library.) Upon exit, destLen
   is the actual size of the uncompressed buffer.

     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
   enough memory, Z_BUF_ERROR if there was not enough room in the output
   buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.
*/


                        /* gzip file access functions */

/*
     This library supports reading and writing files in gzip (.gz) format with
   an interface similar to that of stdio, using the functions that start with
   "gz".  The gzip format is different from the zlib format.  gzip is a gzip
   wrapper, documented in RFC 1952, wrapped around a deflate stream.
*/

typedef voidp gzFile;       /* opaque gzip file descriptor */

/*
ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));

     Opens a gzip (.gz) file for reading or writing.  The mode parameter is as
   in fopen ("rb" or "wb") but can also include a compression level ("wb9") or
   a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only
   compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F'
   for fixed code compression as in "wb9F".  (See the description of
   deflateInit2 for more information about the strategy parameter.) Also "a"
   can be used instead of "w" to request that the gzip stream that will be
   written be appended to the file.  "+" will result in an error, since reading
   and writing to the same gzip file is not supported.

     gzopen can be used to read a file which is not in gzip format; in this
   case gzread will directly read from the file without decompression.

     gzopen returns NULL if the file could not be opened, if there was
   insufficient memory to allocate the gzFile state, or if an invalid mode was
   specified (an 'r', 'w', or 'a' was not provided, or '+' was provided).
   errno can be checked to determine if the reason gzopen failed was that the
   file could not be opened.
*/

ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
/*
     gzdopen associates a gzFile with the file descriptor fd.  File descriptors
   are obtained from calls like open, dup, creat, pipe or fileno (if the file
   has been previously opened with fopen).  The mode parameter is as in gzopen.

     The next call of gzclose on the returned gzFile will also close the file
   descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor
   fd.  If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd,
   mode);.  The duplicated descriptor should be saved to avoid a leak, since
   gzdopen does not close fd if it fails.

     gzdopen returns NULL if there was insufficient memory to allocate the
   gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not
   provided, or '+' was provided), or if fd is -1.  The file descriptor is not
   used until the next gz* read, write, seek, or close operation, so gzdopen
   will not detect if fd is invalid (unless fd is -1).
*/

ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
/*
     Set the internal buffer size used by this library's functions.  The
   default buffer size is 8192 bytes.  This function must be called after
   gzopen() or gzdopen(), and before any other calls that read or write the
   file.  The buffer memory allocation is always deferred to the first read or
   write.  Two buffers are allocated, either both of the specified size when
   writing, or one of the specified size and the other twice that size when
   reading.  A larger buffer size of, for example, 64K or 128K bytes will
   noticeably increase the speed of decompression (reading).

     The new buffer size also affects the maximum length for gzprintf().

     gzbuffer() returns 0 on success, or -1 on failure, such as being called
   too late.
*/

ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
/*
     Dynamically update the compression level or strategy.  See the description
   of deflateInit2 for the meaning of these parameters.

     gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
   opened for writing.
*/

ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
/*
     Reads the given number of uncompressed bytes from the compressed file.  If
   the input file was not in gzip format, gzread copies the given number of
   bytes into the buffer.

     After reaching the end of a gzip stream in the input, gzread will continue
   to read, looking for another gzip stream, or failing that, reading the rest
   of the input file directly without decompression.  The entire input file
   will be read if gzread is called until it returns less than the requested
   len.

     gzread returns the number of uncompressed bytes actually read, less than
   len for end of file, or -1 for error.
*/

ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
                                voidpc buf, unsigned len));
/*
     Writes the given number of uncompressed bytes into the compressed file.
   gzwrite returns the number of uncompressed bytes written or 0 in case of
   error.
*/

ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...));
/*
     Converts, formats, and writes the arguments to the compressed file under
   control of the format string, as in fprintf.  gzprintf returns the number of
   uncompressed bytes actually written, or 0 in case of error.  The number of
   uncompressed bytes written is limited to 8191, or one less than the buffer
   size given to gzbuffer().  The caller should assure that this limit is not
   exceeded.  If it is exceeded, then gzprintf() will return an error (0) with
   nothing written.  In this case, there may also be a buffer overflow with
   unpredictable consequences, which is possible only if zlib was compiled with
   the insecure functions sprintf() or vsprintf() because the secure snprintf()
   or vsnprintf() functions were not available.  This can be determined using
   zlibCompileFlags().
*/

ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
/*
     Writes the given null-terminated string to the compressed file, excluding
   the terminating null character.

     gzputs returns the number of characters written, or -1 in case of error.
*/

ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
/*
     Reads bytes from the compressed file until len-1 characters are read, or a
   newline character is read and transferred to buf, or an end-of-file
   condition is encountered.  If any characters are read or if len == 1, the
   string is terminated with a null character.  If no characters are read due
   to an end-of-file or len < 1, then the buffer is left untouched.

     gzgets returns buf which is a null-terminated string, or it returns NULL
   for end-of-file or in case of error.  If there was an error, the contents at
   buf are indeterminate.
*/

ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
/*
     Writes c, converted to an unsigned char, into the compressed file.  gzputc
   returns the value that was written, or -1 in case of error.
*/

ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
/*
     Reads one byte from the compressed file.  gzgetc returns this byte or -1
   in case of end of file or error.
*/

ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
/*
     Push one character back onto the stream to be read as the first character
   on the next read.  At least one character of push-back is allowed.
   gzungetc() returns the character pushed, or -1 on failure.  gzungetc() will
   fail if c is -1, and may fail if a character has been pushed but not read
   yet.  If gzungetc is used immediately after gzopen or gzdopen, at least the
   output buffer size of pushed characters is allowed.  (See gzbuffer above.)
   The pushed character will be discarded if the stream is repositioned with
   gzseek() or gzrewind().
*/

ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
/*
     Flushes all pending output into the compressed file.  The parameter flush
   is as in the deflate() function.  The return value is the zlib error number
   (see function gzerror below).  gzflush is only permitted when writing.

     If the flush parameter is Z_FINISH, the remaining data is written and the
   gzip stream is completed in the output.  If gzwrite() is called again, a new
   gzip stream will be started in the output.  gzread() is able to read such
   concatented gzip streams.

     gzflush should be called only when strictly necessary because it will
   degrade compression if called too often.
*/

/*
ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
                                   z_off_t offset, int whence));

     Sets the starting position for the next gzread or gzwrite on the given
   compressed file.  The offset represents a number of bytes in the
   uncompressed data stream.  The whence parameter is defined as in lseek(2);
   the value SEEK_END is not supported.

     If the file is opened for reading, this function is emulated but can be
   extremely slow.  If the file is opened for writing, only forward seeks are
   supported; gzseek then compresses a sequence of zeroes up to the new
   starting position.

     gzseek returns the resulting offset location as measured in bytes from
   the beginning of the uncompressed stream, or -1 in case of error, in
   particular if the file is opened for writing and the new starting position
   would be before the current position.
*/

ZEXTERN int ZEXPORT    gzrewind OF((gzFile file));
/*
     Rewinds the given file. This function is supported only for reading.

     gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
*/

/*
ZEXTERN z_off_t ZEXPORT    gztell OF((gzFile file));

     Returns the starting position for the next gzread or gzwrite on the given
   compressed file.  This position represents a number of bytes in the
   uncompressed data stream, and is zero when starting, even if appending or
   reading a gzip stream from the middle of a file using gzdopen().

     gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
*/

/*
ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file));

     Returns the current offset in the file being read or written.  This offset
   includes the count of bytes that precede the gzip stream, for example when
   appending or when using gzdopen() for reading.  When reading, the offset
   does not include as yet unused buffered input.  This information can be used
   for a progress indicator.  On error, gzoffset() returns -1.
*/

ZEXTERN int ZEXPORT gzeof OF((gzFile file));
/*
     Returns true (1) if the end-of-file indicator has been set while reading,
   false (0) otherwise.  Note that the end-of-file indicator is set only if the
   read tried to go past the end of the input, but came up short.  Therefore,
   just like feof(), gzeof() may return false even if there is no more data to
   read, in the event that the last read request was for the exact number of
   bytes remaining in the input file.  This will happen if the input file size
   is an exact multiple of the buffer size.

     If gzeof() returns true, then the read functions will return no more data,
   unless the end-of-file indicator is reset by gzclearerr() and the input file
   has grown since the previous end of file was detected.
*/

ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
/*
     Returns true (1) if file is being copied directly while reading, or false
   (0) if file is a gzip stream being decompressed.  This state can change from
   false to true while reading the input file if the end of a gzip stream is
   reached, but is followed by data that is not another gzip stream.

     If the input file is empty, gzdirect() will return true, since the input
   does not contain a gzip stream.

     If gzdirect() is used immediately after gzopen() or gzdopen() it will
   cause buffers to be allocated to allow reading the file to determine if it
   is a gzip file.  Therefore if gzbuffer() is used, it should be called before
   gzdirect().
*/

ZEXTERN int ZEXPORT    gzclose OF((gzFile file));
/*
     Flushes all pending output if necessary, closes the compressed file and
   deallocates the (de)compression state.  Note that once file is closed, you
   cannot call gzerror with file, since its structures have been deallocated.
   gzclose must not be called more than once on the same file, just as free
   must not be called more than once on the same allocation.

     gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a
   file operation error, or Z_OK on success.
*/

ZEXTERN int ZEXPORT gzclose_r OF((gzFile file));
ZEXTERN int ZEXPORT gzclose_w OF((gzFile file));
/*
     Same as gzclose(), but gzclose_r() is only for use when reading, and
   gzclose_w() is only for use when writing or appending.  The advantage to
   using these instead of gzclose() is that they avoid linking in zlib
   compression or decompression code that is not used when only reading or only
   writing respectively.  If gzclose() is used, then both compression and
   decompression code will be included the application when linking to a static
   zlib library.
*/

ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
/*
     Returns the error message for the last error which occurred on the given
   compressed file.  errnum is set to zlib error number.  If an error occurred
   in the file system and not in the compression library, errnum is set to
   Z_ERRNO and the application may consult errno to get the exact error code.

     The application must not modify the returned string.  Future calls to
   this function may invalidate the previously returned string.  If file is
   closed, then the string previously returned by gzerror will no longer be
   available.

     gzerror() should be used to distinguish errors from end-of-file for those
   functions above that do not distinguish those cases in their return values.
*/

ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
/*
     Clears the error and end-of-file flags for file.  This is analogous to the
   clearerr() function in stdio.  This is useful for continuing to read a gzip
   file that is being written concurrently.
*/


                        /* checksum functions */

/*
     These functions are not related to compression but are exported
   anyway because they might be useful in applications using the compression
   library.
*/

ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
/*
     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
   return the updated checksum.  If buf is Z_NULL, this function returns the
   required initial value for the checksum.

     An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
   much faster.

   Usage example:

     uLong adler = adler32(0L, Z_NULL, 0);

     while (read_buffer(buffer, length) != EOF) {
       adler = adler32(adler, buffer, length);
     }
     if (adler != original_adler) error();
*/

/*
ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
                                          z_off_t len2));

     Combine two Adler-32 checksums into one.  For two sequences of bytes, seq1
   and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
   each, adler1 and adler2.  adler32_combine() returns the Adler-32 checksum of
   seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.
*/

ZEXTERN uLong ZEXPORT crc32   OF((uLong crc, const Bytef *buf, uInt len));
/*
     Update a running CRC-32 with the bytes buf[0..len-1] and return the
   updated CRC-32.  If buf is Z_NULL, this function returns the required
   initial value for the for the crc.  Pre- and post-conditioning (one's
   complement) is performed within this function so it shouldn't be done by the
   application.

   Usage example:

     uLong crc = crc32(0L, Z_NULL, 0);

     while (read_buffer(buffer, length) != EOF) {
       crc = crc32(crc, buffer, length);
     }
     if (crc != original_crc) error();
*/

/*
ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));

     Combine two CRC-32 check values into one.  For two sequences of bytes,
   seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
   calculated for each, crc1 and crc2.  crc32_combine() returns the CRC-32
   check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
   len2.
*/


                        /* various hacks, don't look :) */

/* deflateInit and inflateInit are macros to allow checking the zlib version
 * and the compiler's view of z_stream:
 */
ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
                                     const char *version, int stream_size));
ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
                                     const char *version, int stream_size));
ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int  level, int  method,
                                      int windowBits, int memLevel,
                                      int strategy, const char *version,
                                      int stream_size));
ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,
                                      const char *version, int stream_size));
ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
                                         unsigned char FAR *window,
                                         const char *version,
                                         int stream_size));
#define deflateInit(strm, level) \
        deflateInit_((strm), (level),       ZLIB_VERSION, sizeof(z_stream))
#define inflateInit(strm) \
        inflateInit_((strm),                ZLIB_VERSION, sizeof(z_stream))
#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
        deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
                      (strategy),           ZLIB_VERSION, sizeof(z_stream))
#define inflateInit2(strm, windowBits) \
        inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
#define inflateBackInit(strm, windowBits, window) \
        inflateBackInit_((strm), (windowBits), (window), \
                                            ZLIB_VERSION, sizeof(z_stream))

/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or
 * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if
 * both are true, the application gets the *64 functions, and the regular
 * functions are changed to 64 bits) -- in case these are set on systems
 * without large file support, _LFS64_LARGEFILE must also be true
 */
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
   ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
   ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
   ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
   ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
   ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t));
   ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));
#endif

#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0
#  define gzopen gzopen64
#  define gzseek gzseek64
#  define gztell gztell64
#  define gzoffset gzoffset64
#  define adler32_combine adler32_combine64
#  define crc32_combine crc32_combine64
#  ifdef _LARGEFILE64_SOURCE
     ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
     ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int));
     ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile));
     ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));
     ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
     ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
#  endif
#else
   ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));
   ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int));
   ZEXTERN z_off_t ZEXPORT gztell OF((gzFile));
   ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile));
   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
#endif

/* hack for buggy compilers */
#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL)
    struct internal_state {int dummy;};
#endif

/* undocumented functions */
ZEXTERN const char   * ZEXPORT zError           OF((int));
ZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp));
ZEXTERN const uLongf * ZEXPORT get_crc_table    OF((void));
ZEXTERN int            ZEXPORT inflateUndermine OF((z_streamp, int));

#ifdef __cplusplus
}
#endif

#endif /* ZLIB_H */
cfitsio/zlib/zuncompress.c0000644000225700000360000004005113246025103015474 0ustar  cagordonlhea/* gzcompress.h -- definitions for the .Z decompression routine used in CFITSIO */

#include 
#include 
#include 
#include 

#define get_char() get_byte()

/* gzip.h -- common declarations for all gzip modules  */

#define OF(args)  args
typedef void *voidp;

#define memzero(s, n)     memset ((voidp)(s), 0, (n))

typedef unsigned char  uch;
typedef unsigned short ush;
typedef unsigned long  ulg;

/* private version of MIN function */
#define MINZIP(a,b) ((a) <= (b) ? (a) : (b))

/* Return codes from gzip */
#define OK      0
#define ERROR   1
#define COMPRESSED  1
#define DEFLATED    8
#define INBUFSIZ  0x8000    /* input buffer size */
#define INBUF_EXTRA  64     /* required by unlzw() */
#define OUTBUFSIZ  16384    /* output buffer size */
#define OUTBUF_EXTRA 2048   /* required by unlzw() */
#define DIST_BUFSIZE 0x8000 /* buffer for distances, see trees.c */
#define WSIZE 0x8000        /* window size--must be a power of two, and */
#define DECLARE(type, array, size)  type array[size]
#define tab_suffix window
#define tab_prefix prev    /* hash link (see deflate.c) */
#define head (prev+WSIZE)  /* hash head (see deflate.c) */
#define	LZW_MAGIC      "\037\235" /* Magic header for lzw files, 1F 9D */
#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf(0))

/* Diagnostic functions */
#  define Assert(cond,msg)
#  define Trace(x)
#  define Tracev(x)
#  define Tracevv(x)
#  define Tracec(c,x)
#  define Tracecv(c,x)

/* lzw.h -- define the lzw functions. */

#ifndef BITS
#  define BITS 16
#endif
#define INIT_BITS 9              /* Initial number of bits per code */
#define BIT_MASK    0x1f /* Mask for 'number of compression bits' */
#define BLOCK_MODE  0x80
#define LZW_RESERVED 0x60 /* reserved bits */
#define	CLEAR  256       /* flush the dictionary */
#define FIRST  (CLEAR+1) /* first free entry */

/* prototypes */

#define local static
void ffpmsg(const char *err_message);

local int  fill_inbuf    OF((int eof_ok));
local void write_buf     OF((voidp buf, unsigned cnt));
local void error         OF((char *m));
local int unlzw  OF((FILE *in, FILE *out));

typedef int file_t;     /* Do not use stdio */

int (*work) OF((FILE *infile, FILE *outfile)) = unlzw; /* function to call */

local void error         OF((char *m));

		/* global buffers */

static DECLARE(uch, inbuf,  INBUFSIZ +INBUF_EXTRA);
static DECLARE(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
static DECLARE(ush, d_buf,  DIST_BUFSIZE);
static DECLARE(uch, window, 2L*WSIZE);

#ifndef MAXSEG_64K
    static DECLARE(ush, tab_prefix, 1L< 0)
        return(*status);

    /*  save input parameters into global variables */
    ifname[0] = '\0';
    strncat(ifname, filename, 127);
    ifd = indiskfile;
    memptr = (void **) buffptr;
    memsize = buffsize;
    realloc_fn = mem_realloc;

    /* clear input and output buffers */

    insize = inptr = 0;
    bytes_in = bytes_out = 0L;

    magic[0] = (char)get_byte();
    magic[1] = (char)get_byte();

    if (memcmp(magic, LZW_MAGIC, 2) != 0) {
      error("ERROR: input .Z file is in unrecognized compression format.\n");
      return(-1);
    }

    work = unlzw;
    method = COMPRESSED;
    last_member = 1;

    /* do the uncompression */
    if ((*work)(ifd, ofd) != OK) {
        method = -1; /* force cleanup */
        *status = 414;    /* report some sort of decompression error */
    }

    if (filesize)  *filesize = bytes_out;

    return(*status);
}
/*=========================================================================*/
/*=========================================================================*/
/* this marks the begining of the original file 'unlzw.c'                  */
/*=========================================================================*/
/*=========================================================================*/

/* unlzw.c -- decompress files in LZW format.
 * The code in this file is directly derived from the public domain 'compress'
 * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies,
 * Ken Turkowski, Dave Mack and Peter Jannesen.
 */

typedef	unsigned char	char_type;
typedef          long   code_int;
typedef unsigned long 	count_int;
typedef unsigned short	count_short;
typedef unsigned long 	cmp_code_int;

#define MAXCODE(n)	(1L << (n))
    
#ifndef	REGISTERS
#	define	REGISTERS	2
#endif
#define	REG1	
#define	REG2	
#define	REG3	
#define	REG4	
#define	REG5	
#define	REG6	
#define	REG7	
#define	REG8	
#define	REG9	
#define	REG10
#define	REG11	
#define	REG12	
#define	REG13
#define	REG14
#define	REG15
#define	REG16
#if REGISTERS >= 1
#	undef	REG1
#	define	REG1	register
#endif
#if REGISTERS >= 2
#	undef	REG2
#	define	REG2	register
#endif
#if REGISTERS >= 3
#	undef	REG3
#	define	REG3	register
#endif
#if REGISTERS >= 4
#	undef	REG4
#	define	REG4	register
#endif
#if REGISTERS >= 5
#	undef	REG5
#	define	REG5	register
#endif
#if REGISTERS >= 6
#	undef	REG6
#	define	REG6	register
#endif
#if REGISTERS >= 7
#	undef	REG7
#	define	REG7	register
#endif
#if REGISTERS >= 8
#	undef	REG8
#	define	REG8	register
#endif
#if REGISTERS >= 9
#	undef	REG9
#	define	REG9	register
#endif
#if REGISTERS >= 10
#	undef	REG10
#	define	REG10	register
#endif
#if REGISTERS >= 11
#	undef	REG11
#	define	REG11	register
#endif
#if REGISTERS >= 12
#	undef	REG12
#	define	REG12	register
#endif
#if REGISTERS >= 13
#	undef	REG13
#	define	REG13	register
#endif
#if REGISTERS >= 14
#	undef	REG14
#	define	REG14	register
#endif
#if REGISTERS >= 15
#	undef	REG15
#	define	REG15	register
#endif
#if REGISTERS >= 16
#	undef	REG16
#	define	REG16	register
#endif
    
#ifndef	BYTEORDER
#	define	BYTEORDER	0000
#endif
	
#ifndef	NOALLIGN
#	define	NOALLIGN	0
#endif


union	bytes {
    long  word;
    struct {
#if BYTEORDER == 4321
	char_type	b1;
	char_type	b2;
	char_type	b3;
	char_type	b4;
#else
#if BYTEORDER == 1234
	char_type	b4;
	char_type	b3;
	char_type	b2;
	char_type	b1;
#else
#	undef	BYTEORDER
	int  dummy;
#endif
#endif
    } bytes;
};

#if BYTEORDER == 4321 && NOALLIGN == 1
#  define input(b,o,c,n,m){ \
     (c) = (*(long *)(&(b)[(o)>>3])>>((o)&0x7))&(m); \
     (o) += (n); \
   }
#else
#  define input(b,o,c,n,m){ \
     REG1 char_type *p = &(b)[(o)>>3]; \
     (c) = ((((long)(p[0]))|((long)(p[1])<<8)| \
     ((long)(p[2])<<16))>>((o)&0x7))&(m); \
     (o) += (n); \
   }
#endif

#ifndef MAXSEG_64K
   /* DECLARE(ush, tab_prefix, (1<>1]
#  define clear_tab_prefixof()	\
      memzero(tab_prefix0, 128), \
      memzero(tab_prefix1, 128);
#endif
#define de_stack        ((char_type *)(&d_buf[DIST_BUFSIZE-1]))
#define tab_suffixof(i) tab_suffix[i]

int block_mode = BLOCK_MODE; /* block compress mode -C compatible with 2.0 */

/* ============================================================================
 * Decompress in to out.  This routine adapts to the codes in the
 * file building the "string" table on-the-fly; requiring no table to
 * be stored in the compressed file.
 * IN assertions: the buffer inbuf contains already the beginning of
 *   the compressed data, from offsets iptr to insize-1 included.
 *   The magic header has already been checked and skipped.
 *   bytes_in and bytes_out have been initialized.
 */
local int unlzw(FILE *in, FILE *out) 
    /* input and output file descriptors */
{
    REG2   char_type  *stackp;
    REG3   code_int   code;
    REG4   int        finchar;
    REG5   code_int   oldcode;
    REG6   code_int   incode;
    REG7   long       inbits;
    REG8   long       posbits;
    REG9   int        outpos;
/*  REG10  int        insize; (global) */
    REG11  unsigned   bitmask;
    REG12  code_int   free_ent;
    REG13  code_int   maxcode;
    REG14  code_int   maxmaxcode;
    REG15  int        n_bits;
    REG16  int        rsize;
    
    ofd = out;

#ifdef MAXSEG_64K
    tab_prefix[0] = tab_prefix0;
    tab_prefix[1] = tab_prefix1;
#endif
    maxbits = get_byte();
    block_mode = maxbits & BLOCK_MODE;
    if ((maxbits & LZW_RESERVED) != 0) {
	error( "warning, unknown flags in unlzw decompression");
    }
    maxbits &= BIT_MASK;
    maxmaxcode = MAXCODE(maxbits);
    
    if (maxbits > BITS) {
	error("compressed with too many bits; cannot handle file");
	exit_code = ERROR;
	return ERROR;
    }
    rsize = insize;
    maxcode = MAXCODE(n_bits = INIT_BITS)-1;
    bitmask = (1<= 0 ; --code) {
	tab_suffixof(code) = (char_type)code;
    }
    do {
	REG1 int i;
	int  e;
	int  o;
	
    resetbuf:
	e = insize-(o = (posbits>>3));
	
	for (i = 0 ; i < e ; ++i) {
	    inbuf[i] = inbuf[i+o];
	}
	insize = e;
	posbits = 0;
	
	if (insize < INBUF_EXTRA) {
/*  modified to use fread instead of read - WDP 10/22/97  */
/*	    if ((rsize = read(in, (char*)inbuf+insize, INBUFSIZ)) == EOF) { */

	    if ((rsize = fread((char*)inbuf+insize, 1, INBUFSIZ, in)) == EOF) {
		error("unexpected end of file");
	        exit_code = ERROR;
                return ERROR;
	    }
	    insize += rsize;
	    bytes_in += (ulg)rsize;
	}
	inbits = ((rsize != 0) ? ((long)insize - insize%n_bits)<<3 : 
		  ((long)insize<<3)-(n_bits-1));
	
	while (inbits > posbits) {
	    if (free_ent > maxcode) {
		posbits = ((posbits-1) +
			   ((n_bits<<3)-(posbits-1+(n_bits<<3))%(n_bits<<3)));
		++n_bits;
		if (n_bits == maxbits) {
		    maxcode = maxmaxcode;
		} else {
		    maxcode = MAXCODE(n_bits)-1;
		}
		bitmask = (1<= 256) {
                    error("corrupt input.");
	            exit_code = ERROR;
                    return ERROR;
                }

		outbuf[outpos++] = (char_type)(finchar = (int)(oldcode=code));
		continue;
	    }
	    if (code == CLEAR && block_mode) {
		clear_tab_prefixof();
		free_ent = FIRST - 1;
		posbits = ((posbits-1) +
			   ((n_bits<<3)-(posbits-1+(n_bits<<3))%(n_bits<<3)));
		maxcode = MAXCODE(n_bits = INIT_BITS)-1;
		bitmask = (1<= free_ent) { /* Special case for KwKwK string. */
		if (code > free_ent) {
		    if (outpos > 0) {
			write_buf((char*)outbuf, outpos);
			bytes_out += (ulg)outpos;
		    }
		    error("corrupt input.");
	            exit_code = ERROR;
                    return ERROR;

		}
		*--stackp = (char_type)finchar;
		code = oldcode;
	    }

	    while ((cmp_code_int)code >= (cmp_code_int)256) {
		/* Generate output characters in reverse order */
		*--stackp = tab_suffixof(code);
		code = tab_prefixof(code);
	    }
	    *--stackp =	(char_type)(finchar = tab_suffixof(code));
	    
	    /* And put them out in forward order */
	    {
	/*	REG1 int	i;   already defined above (WDP) */
	    
		if (outpos+(i = (de_stack-stackp)) >= OUTBUFSIZ) {
		    do {
			if (i > OUTBUFSIZ-outpos) i = OUTBUFSIZ-outpos;

			if (i > 0) {
			    memcpy(outbuf+outpos, stackp, i);
			    outpos += i;
			}
			if (outpos >= OUTBUFSIZ) {
			    write_buf((char*)outbuf, outpos);
			    bytes_out += (ulg)outpos;
			    outpos = 0;
			}
			stackp+= i;
		    } while ((i = (de_stack-stackp)) > 0);
		} else {
		    memcpy(outbuf+outpos, stackp, i);
		    outpos += i;
		}
	    }

	    if ((code = free_ent) < maxmaxcode) { /* Generate the new entry. */

		tab_prefixof(code) = (unsigned short)oldcode;
		tab_suffixof(code) = (char_type)finchar;
		free_ent = code+1;
	    } 
	    oldcode = incode;	/* Remember previous code.	*/
	}
    } while (rsize != 0);
    
    if (outpos > 0) {
	write_buf((char*)outbuf, outpos);
	bytes_out += (ulg)outpos;
    }
    return OK;
}
/* ========================================================================*/
/* this marks the start of the code from 'util.c'  */

local int fill_inbuf(int eof_ok)
         /* set if EOF acceptable as a result */
{
    int len;

      /* Read as much as possible from file */
      insize = 0;
      do {
        len = fread((char*)inbuf+insize, 1, INBUFSIZ-insize, ifd);
        if (len == 0 || len == EOF) break;
	insize += len;
      } while (insize < INBUFSIZ);

    if (insize == 0) {
	if (eof_ok) return EOF;
	error("unexpected end of file");
        exit_code = ERROR;
        return ERROR;
    }

    bytes_in += (ulg)insize;
    inptr = 1;
    return inbuf[0];
}
/* =========================================================================== */
local void write_buf(voidp buf, unsigned cnt)
/*              copy buffer into memory; allocate more memory if required*/
{
    if (!realloc_fn)
    {
      /* append buffer to file */
      /* added 'unsigned' to get rid of compiler warning (WDP 1/1/99) */
      if ((unsigned long) fwrite(buf, 1, cnt, ofd) != cnt)
      {
          error
          ("failed to write buffer to uncompressed output file (write_buf)");
          exit_code = ERROR;
          return;
      }
    }
    else
    {
      /* get more memory if current buffer is too small */
      if (bytes_out + cnt > *memsize)
      {
        *memptr = realloc_fn(*memptr, bytes_out + cnt);
        *memsize = bytes_out + cnt;  /* new memory buffer size */

        if (!(*memptr))
        {
            error("malloc failed while uncompressing (write_buf)");
            exit_code = ERROR;
            return;
        }  
      }
      /* copy  into memory buffer */
      memcpy((char *) *memptr + bytes_out, (char *) buf, cnt);
    }
}
/* ======================================================================== */
local void error(char *m)
/*                Error handler */
{
    ffpmsg(ifname);
    ffpmsg(m);
}
cfitsio/zlib/zutil.c0000644000225700000360000001620013246025103014252 0ustar  cagordonlhea/* zutil.c -- target dependent utility functions for the compression library
 * Copyright (C) 1995-2005, 2010 Jean-loup Gailly.
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

#include "zutil.h"

#ifndef NO_DUMMY_DECL
struct internal_state      {int dummy;}; /* for buggy compilers */
#endif

const char * const z_errmsg[10] = {
"need dictionary",     /* Z_NEED_DICT       2  */
"stream end",          /* Z_STREAM_END      1  */
"",                    /* Z_OK              0  */
"file error",          /* Z_ERRNO         (-1) */
"stream error",        /* Z_STREAM_ERROR  (-2) */
"data error",          /* Z_DATA_ERROR    (-3) */
"insufficient memory", /* Z_MEM_ERROR     (-4) */
"buffer error",        /* Z_BUF_ERROR     (-5) */
"incompatible version",/* Z_VERSION_ERROR (-6) */
""};


const char * ZEXPORT zlibVersion()
{
    return ZLIB_VERSION;
}

uLong ZEXPORT zlibCompileFlags()
{
    uLong flags;

    flags = 0;
    switch ((int)(sizeof(uInt))) {
    case 2:     break;
    case 4:     flags += 1;     break;
    case 8:     flags += 2;     break;
    default:    flags += 3;
    }
    switch ((int)(sizeof(uLong))) {
    case 2:     break;
    case 4:     flags += 1 << 2;        break;
    case 8:     flags += 2 << 2;        break;
    default:    flags += 3 << 2;
    }
    switch ((int)(sizeof(voidpf))) {
    case 2:     break;
    case 4:     flags += 1 << 4;        break;
    case 8:     flags += 2 << 4;        break;
    default:    flags += 3 << 4;
    }
    switch ((int)(sizeof(z_off_t))) {
    case 2:     break;
    case 4:     flags += 1 << 6;        break;
    case 8:     flags += 2 << 6;        break;
    default:    flags += 3 << 6;
    }
#ifdef DEBUG
    flags += 1 << 8;
#endif
#if defined(ASMV) || defined(ASMINF)
    flags += 1 << 9;
#endif
#ifdef ZLIB_WINAPI
    flags += 1 << 10;
#endif
#ifdef BUILDFIXED
    flags += 1 << 12;
#endif
#ifdef DYNAMIC_CRC_TABLE
    flags += 1 << 13;
#endif
#ifdef NO_GZCOMPRESS
    flags += 1L << 16;
#endif
#ifdef NO_GZIP
    flags += 1L << 17;
#endif
#ifdef PKZIP_BUG_WORKAROUND
    flags += 1L << 20;
#endif
#ifdef FASTEST
    flags += 1L << 21;
#endif
#ifdef STDC
#  ifdef NO_vsnprintf
        flags += 1L << 25;
#    ifdef HAS_vsprintf_void
        flags += 1L << 26;
#    endif
#  else
#    ifdef HAS_vsnprintf_void
        flags += 1L << 26;
#    endif
#  endif
#else
        flags += 1L << 24;
#  ifdef NO_snprintf
        flags += 1L << 25;
#    ifdef HAS_sprintf_void
        flags += 1L << 26;
#    endif
#  else
#    ifdef HAS_snprintf_void
        flags += 1L << 26;
#    endif
#  endif
#endif
    return flags;
}

#ifdef DEBUG

#  ifndef verbose
#    define verbose 0
#  endif
int ZLIB_INTERNAL z_verbose = verbose;

void ZLIB_INTERNAL z_error (m)
    char *m;
{
    fprintf(stderr, "%s\n", m);
    exit(1);
}
#endif

/* exported to allow conversion of error code to string for compress() and
 * uncompress()
 */
const char * ZEXPORT zError(err)
    int err;
{
    return ERR_MSG(err);
}

#if defined(_WIN32_WCE)
    /* The Microsoft C Run-Time Library for Windows CE doesn't have
     * errno.  We define it as a global variable to simplify porting.
     * Its value is always 0 and should not be used.
     */
    int errno = 0;
#endif

#ifndef HAVE_MEMCPY

void ZLIB_INTERNAL zmemcpy(dest, source, len)
    Bytef* dest;
    const Bytef* source;
    uInt  len;
{
    if (len == 0) return;
    do {
        *dest++ = *source++; /* ??? to be unrolled */
    } while (--len != 0);
}

int ZLIB_INTERNAL zmemcmp(s1, s2, len)
    const Bytef* s1;
    const Bytef* s2;
    uInt  len;
{
    uInt j;

    for (j = 0; j < len; j++) {
        if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
    }
    return 0;
}

void ZLIB_INTERNAL zmemzero(dest, len)
    Bytef* dest;
    uInt  len;
{
    if (len == 0) return;
    do {
        *dest++ = 0;  /* ??? to be unrolled */
    } while (--len != 0);
}
#endif


#ifdef SYS16BIT

#ifdef __TURBOC__
/* Turbo C in 16-bit mode */

#  define MY_ZCALLOC

/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
 * and farmalloc(64K) returns a pointer with an offset of 8, so we
 * must fix the pointer. Warning: the pointer must be put back to its
 * original form in order to free it, use zcfree().
 */

#define MAX_PTR 10
/* 10*64K = 640K */

local int next_ptr = 0;

typedef struct ptr_table_s {
    voidpf org_ptr;
    voidpf new_ptr;
} ptr_table;

local ptr_table table[MAX_PTR];
/* This table is used to remember the original form of pointers
 * to large buffers (64K). Such pointers are normalized with a zero offset.
 * Since MSDOS is not a preemptive multitasking OS, this table is not
 * protected from concurrent access. This hack doesn't work anyway on
 * a protected system like OS/2. Use Microsoft C instead.
 */

voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size)
{
    voidpf buf = opaque; /* just to make some compilers happy */
    ulg bsize = (ulg)items*size;

    /* If we allocate less than 65520 bytes, we assume that farmalloc
     * will return a usable pointer which doesn't have to be normalized.
     */
    if (bsize < 65520L) {
        buf = farmalloc(bsize);
        if (*(ush*)&buf != 0) return buf;
    } else {
        buf = farmalloc(bsize + 16L);
    }
    if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
    table[next_ptr].org_ptr = buf;

    /* Normalize the pointer to seg:0 */
    *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
    *(ush*)&buf = 0;
    table[next_ptr++].new_ptr = buf;
    return buf;
}

void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
{
    int n;
    if (*(ush*)&ptr != 0) { /* object < 64K */
        farfree(ptr);
        return;
    }
    /* Find the original pointer */
    for (n = 0; n < next_ptr; n++) {
        if (ptr != table[n].new_ptr) continue;

        farfree(table[n].org_ptr);
        while (++n < next_ptr) {
            table[n-1] = table[n];
        }
        next_ptr--;
        return;
    }
    ptr = opaque; /* just to make some compilers happy */
    Assert(0, "zcfree: ptr not found");
}

#endif /* __TURBOC__ */


#ifdef M_I86
/* Microsoft C in 16-bit mode */

#  define MY_ZCALLOC

#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
#  define _halloc  halloc
#  define _hfree   hfree
#endif

voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size)
{
    if (opaque) opaque = 0; /* to make compiler happy */
    return _halloc((long)items, size);
}

void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
{
    if (opaque) opaque = 0; /* to make compiler happy */
    _hfree(ptr);
}

#endif /* M_I86 */

#endif /* SYS16BIT */


#ifndef MY_ZCALLOC /* Any system without a special alloc function */

#ifndef STDC
extern voidp  malloc OF((uInt size));
extern voidp  calloc OF((uInt items, uInt size));
extern void   free   OF((voidpf ptr));
#endif

voidpf ZLIB_INTERNAL zcalloc (opaque, items, size)
    voidpf opaque;
    unsigned items;
    unsigned size;
{
    if (opaque) items += size - size; /* make compiler happy */
    return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
                              (voidpf)calloc(items, size);
}

void ZLIB_INTERNAL zcfree (opaque, ptr)
    voidpf opaque;
    voidpf ptr;
{
    free(ptr);
    if (opaque) return; /* make compiler happy */
}

#endif /* MY_ZCALLOC */
cfitsio/zlib/zutil.h0000644000225700000360000001574013246025103014267 0ustar  cagordonlhea/* zutil.h -- internal interface and configuration of the compression library
 * Copyright (C) 1995-2010 Jean-loup Gailly.
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

/* WARNING: this file should *not* be used by applications. It is
   part of the implementation of the compression library and is
   subject to change. Applications should only use zlib.h.
 */

#ifndef ZUTIL_H
#define ZUTIL_H

#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ)
#  define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
#else
#  define ZLIB_INTERNAL
#endif

#include "zlib.h"

#ifdef STDC
#  if !(defined(_WIN32_WCE) && defined(_MSC_VER))
#    include 
#  endif
#  include 
#  include 
#endif

#ifndef local
#  define local static
#endif
/* compile with -Dlocal if your debugger can't find static symbols */

typedef unsigned char  uch;
typedef uch FAR uchf;
typedef unsigned short ush;
typedef ush FAR ushf;
typedef unsigned long  ulg;

extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
/* (size given to avoid silly warnings with Visual C++) */

#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]

#define ERR_RETURN(strm,err) \
  return (strm->msg = (char*)ERR_MSG(err), (err))
/* To be used only when the state is known to be valid */

        /* common constants */

#ifndef DEF_WBITS
#  define DEF_WBITS MAX_WBITS
#endif
/* default windowBits for decompression. MAX_WBITS is for compression only */

#if MAX_MEM_LEVEL >= 8
#  define DEF_MEM_LEVEL 8
#else
#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
#endif
/* default memLevel */

#define STORED_BLOCK 0
#define STATIC_TREES 1
#define DYN_TREES    2
/* The three kinds of block type */

#define MIN_MATCH  3
#define MAX_MATCH  258
/* The minimum and maximum match lengths */

#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */

        /* target dependencies */

#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
#  define OS_CODE  0x00
#  if defined(__TURBOC__) || defined(__BORLANDC__)
#    if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
       /* Allow compilation with ANSI keywords only enabled */
       void _Cdecl farfree( void *block );
       void *_Cdecl farmalloc( unsigned long nbytes );
#    else
#      include 
#    endif
#  else /* MSC or DJGPP */
#    include 
#  endif
#endif

#ifdef AMIGA
#  define OS_CODE  0x01
#endif

#if defined(VAXC) || defined(VMS)
#  define OS_CODE  0x02
#  define F_OPEN(name, mode) \
     fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
#endif

#if defined(ATARI) || defined(atarist)
#  define OS_CODE  0x05
#endif

#ifdef OS2
#  define OS_CODE  0x06
#  ifdef M_I86
#    include 
#  endif
#endif

#if defined(MACOS) || defined(TARGET_OS_MAC)
#  define OS_CODE  0x07
#  if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
#    include  /* for fdopen */
#  else
#    ifndef fdopen
#      define fdopen(fd,mode) NULL /* No fdopen() */
#    endif
#  endif
#endif

#ifdef TOPS20
#  define OS_CODE  0x0a
#endif

#ifdef WIN32
#  ifndef __CYGWIN__  /* Cygwin is Unix, not Win32 */
#    define OS_CODE  0x0b
#  endif
#endif

#ifdef __50SERIES /* Prime/PRIMOS */
#  define OS_CODE  0x0f
#endif

#if defined(_BEOS_) || defined(RISCOS)
#  define fdopen(fd,mode) NULL /* No fdopen() */
#endif

#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX
#  if defined(_WIN32_WCE)
#    define fdopen(fd,mode) NULL /* No fdopen() */
#    ifndef _PTRDIFF_T_DEFINED
       typedef int ptrdiff_t;
#      define _PTRDIFF_T_DEFINED
#    endif
#  else
#    define fdopen(fd,type)  _fdopen(fd,type)
#  endif
#endif

#if defined(__BORLANDC__)
  #pragma warn -8004
  #pragma warn -8008
  #pragma warn -8066
#endif

/* provide prototypes for these when building zlib without LFS */
#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
    ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
    ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
#endif

        /* common defaults */

#ifndef OS_CODE
#  define OS_CODE  0x03  /* assume Unix */
#endif

#ifndef F_OPEN
#  define F_OPEN(name, mode) fopen((name), (mode))
#endif

         /* functions */

#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
#  ifndef HAVE_VSNPRINTF
#    define HAVE_VSNPRINTF
#  endif
#endif
#if defined(__CYGWIN__)
#  ifndef HAVE_VSNPRINTF
#    define HAVE_VSNPRINTF
#  endif
#endif
#ifndef HAVE_VSNPRINTF
#  ifdef MSDOS
     /* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
        but for now we just assume it doesn't. */
#    define NO_vsnprintf
#  endif
#  ifdef __TURBOC__
#    define NO_vsnprintf
#  endif
#  ifdef WIN32
     /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
#    if !defined(vsnprintf) && !defined(NO_vsnprintf)
#      if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )
#         define vsnprintf _vsnprintf
#      endif
#    endif
#  endif
#  ifdef __SASC
#    define NO_vsnprintf
#  endif
#endif
#ifdef VMS
#  define NO_vsnprintf
#endif

#if defined(pyr)
#  define NO_MEMCPY
#endif
#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
 /* Use our own functions for small and medium model with MSC <= 5.0.
  * You may have to use the same strategy for Borland C (untested).
  * The __SC__ check is for Symantec.
  */
#  define NO_MEMCPY
#endif
#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
#  define HAVE_MEMCPY
#endif
#ifdef HAVE_MEMCPY
#  ifdef SMALL_MEDIUM /* MSDOS small or medium model */
#    define zmemcpy _fmemcpy
#    define zmemcmp _fmemcmp
#    define zmemzero(dest, len) _fmemset(dest, 0, len)
#  else
#    define zmemcpy memcpy
#    define zmemcmp memcmp
#    define zmemzero(dest, len) memset(dest, 0, len)
#  endif
#else
   void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
   int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
   void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len));
#endif

/* Diagnostic functions */
#ifdef DEBUG
#  include 
   extern int ZLIB_INTERNAL z_verbose;
   extern void ZLIB_INTERNAL z_error OF((char *m));
#  define Assert(cond,msg) {if(!(cond)) z_error(msg);}
#  define Trace(x) {if (z_verbose>=0) fprintf x ;}
#  define Tracev(x) {if (z_verbose>0) fprintf x ;}
#  define Tracevv(x) {if (z_verbose>1) fprintf x ;}
#  define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
#  define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
#else
#  define Assert(cond,msg)
#  define Trace(x)
#  define Tracev(x)
#  define Tracevv(x)
#  define Tracec(c,x)
#  define Tracecv(c,x)
#endif


voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items,
                        unsigned size));
void ZLIB_INTERNAL zcfree  OF((voidpf opaque, voidpf ptr));

#define ZALLOC(strm, items, size) \
           (*((strm)->zalloc))((strm)->opaque, (items), (size))
#define ZFREE(strm, addr)  (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}

#endif /* ZUTIL_H */
cfitsio/getkey.c0000644000225700000360000036047513246025103013453 0ustar  cagordonlhea/*  This file, getkey.c, contains routines that read keywords from         */
/*  a FITS header.                                                         */

/*  The FITSIO software was written by William Pence at the High Energy    */
/*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
/*  Goddard Space Flight Center.                                           */

#include 
#include 
#include 
#include 
/* stddef.h is apparently needed to define size_t */
#include 
#include "fitsio2.h"

/*--------------------------------------------------------------------------*/
int ffghsp(fitsfile *fptr,  /* I - FITS file pointer                     */
           int *nexist,     /* O - number of existing keywords in header */
           int *nmore,      /* O - how many more keywords will fit       */
           int *status)     /* IO - error status                         */
/*
  returns the number of existing keywords (not counting the END keyword)
  and the number of more keyword that will fit in the current header 
  without having to insert more FITS blocks.
*/
{
    if (*status > 0)
        return(*status);

    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    if (nexist)
        *nexist = (int) (( ((fptr->Fptr)->headend) - 
                ((fptr->Fptr)->headstart[(fptr->Fptr)->curhdu]) ) / 80);

    if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
    {
      if (nmore)
        *nmore = -1;   /* data not written yet, so room for any keywords */
    }
    else
    {
      /* calculate space available between the data and the END card */
      if (nmore)
        *nmore = (int) (((fptr->Fptr)->datastart - (fptr->Fptr)->headend) / 80 - 1);
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffghps(fitsfile *fptr, /* I - FITS file pointer                     */
          int *nexist,     /* O - number of existing keywords in header */
          int *position,   /* O - position of next keyword to be read   */
          int *status)     /* IO - error status                         */
/*
  return the number of existing keywords and the position of the next
  keyword that will be read.
*/
{
    if (*status > 0)
        return(*status);

    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    if (nexist)
      *nexist = (int) (( ((fptr->Fptr)->headend) - ((fptr->Fptr)->headstart[(fptr->Fptr)->curhdu]) ) / 80);

    if (position)
      *position = (int) (( ((fptr->Fptr)->nextkey) - ((fptr->Fptr)->headstart[(fptr->Fptr)->curhdu]) ) / 80 + 1);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffnchk(fitsfile *fptr,  /* I - FITS file pointer                     */
           int *status)     /* IO - error status                         */
/*
  function returns the position of the first null character (ASCII 0), if
  any, in the current header.  Null characters are illegal, but the other
  CFITSIO routines that read the header will not detect this error, because
  the null gets interpreted as a normal end of string character.
*/
{
    long ii, nblock;
    LONGLONG bytepos;
    int length, nullpos;
    char block[2881];
    
    if (*status > 0)
        return(*status);

    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
    {
        return(0);  /* Don't check a file that is just being created.  */
                    /* It cannot contain nulls since CFITSIO wrote it. */
    }
    else
    {
        /* calculate number of blocks in the header */
        nblock = (long) (( (fptr->Fptr)->datastart - 
                   (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] ) / 2880);
    }

    bytepos = (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu];
    ffmbyt(fptr, bytepos, REPORT_EOF, status);  /* move to read pos. */

    block[2880] = '\0';
    for (ii = 0; ii < nblock; ii++)
    {
        if (ffgbyt(fptr, 2880, block, status) > 0)
            return(0);   /* read error of some sort */

        length = strlen(block);
        if (length != 2880)
        {
            nullpos = (ii * 2880) + length + 1;
            return(nullpos);
        }
    }

    return(0);
}
/*--------------------------------------------------------------------------*/
int ffmaky(fitsfile *fptr,    /* I - FITS file pointer                    */
          int nrec,           /* I - one-based keyword number to move to  */
          int *status)        /* IO - error status                        */
{
/*
  move pointer to the specified absolute keyword position.  E.g. this keyword 
  will then be read by the next call to ffgnky.
*/
    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    (fptr->Fptr)->nextkey = (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] + ( (nrec - 1) * 80);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffmrky(fitsfile *fptr,    /* I - FITS file pointer                   */
          int nmove,          /* I - relative number of keywords to move */
          int *status)        /* IO - error status                       */
{
/*
  move pointer to the specified keyword position relative to the current
  position.  E.g. this keyword  will then be read by the next call to ffgnky.
*/

    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    (fptr->Fptr)->nextkey += (nmove * 80);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgnky(fitsfile *fptr,  /* I - FITS file pointer     */
           char *card,      /* O - card string           */
           int *status)     /* IO - error status         */
/*
  read the next keyword from the header - used internally by cfitsio
*/
{
    int jj, nrec;
    LONGLONG bytepos, endhead;
    char message[FLEN_ERRMSG];

    if (*status > 0)
        return(*status);

    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    card[0] = '\0';  /* make sure card is terminated, even affer read error */

/*
  Check that nextkey points to a legal keyword position.  Note that headend
  is the current end of the header, i.e., the position where a new keyword
  would be appended, however, if there are more than 1 FITS block worth of
  blank keywords at the end of the header (36 keywords per 2880 byte block)
  then the actual physical END card must be located at a starting position
  which is just 2880 bytes prior to the start of the data unit.
*/

    bytepos = (fptr->Fptr)->nextkey;
    endhead = maxvalue( ((fptr->Fptr)->headend), ((fptr->Fptr)->datastart - 2880) );

    /* nextkey must be < endhead and > than  headstart */
    if (bytepos > endhead ||  
        bytepos < (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] ) 
    {
        nrec= (int) ((bytepos - (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu]) / 80 + 1);
        snprintf(message, FLEN_ERRMSG,"Cannot get keyword number %d.  It does not exist.",
                nrec);
        ffpmsg(message);
        return(*status = KEY_OUT_BOUNDS);
    }
      
    ffmbyt(fptr, bytepos, REPORT_EOF, status);  /* move to read pos. */

    card[80] = '\0';  /* make sure card is terminate, even if ffgbyt fails */

    if (ffgbyt(fptr, 80, card, status) <= 0) 
    {
        (fptr->Fptr)->nextkey += 80;   /* increment pointer to next keyword */

        /* strip off trailing blanks with terminated string */
        jj = 79;
        while (jj >= 0 && card[jj] == ' ')
               jj--;

        card[jj + 1] = '\0';
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgnxk( fitsfile *fptr,     /* I - FITS file pointer              */
            char **inclist,     /* I - list of included keyword names */
            int ninc,           /* I - number of names in inclist     */
            char **exclist,     /* I - list of excluded keyword names */
            int nexc,           /* I - number of names in exclist     */
            char *card,         /* O - first matching keyword         */
            int  *status)       /* IO - error status                  */
/*
    Return the next keyword that matches one of the names in inclist
    but does not match any of the names in exclist.  The search
    goes from the current position to the end of the header, only.
    Wild card characters may be used in the name lists ('*', '?' and '#').
*/
{
    int casesn, match, exact, namelen;
    long ii, jj;
    char keybuf[FLEN_CARD], keyname[FLEN_KEYWORD];

    card[0] = '\0';
    if (*status > 0)
        return(*status);

    casesn = FALSE;

    /* get next card, and return with an error if hit end of header */
    while( ffgcrd(fptr, "*", keybuf, status) <= 0)
    {
        ffgknm(keybuf, keyname, &namelen, status); /* get the keyword name */
        
        /* does keyword match any names in the include list? */
        for (ii = 0; ii < ninc; ii++)
        {
            ffcmps(inclist[ii], keyname, casesn, &match, &exact);
            if (match)
            {
                /* does keyword match any names in the exclusion list? */
                jj = -1;
                while ( ++jj < nexc )
                {
                    ffcmps(exclist[jj], keyname, casesn, &match, &exact);
                    if (match)
                        break;
                }

                if (jj >= nexc)
                {
                    /* not in exclusion list, so return this keyword */
                    strcat(card, keybuf);
                    return(*status);
                }
            }
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgky( fitsfile *fptr,     /* I - FITS file pointer        */
           int  datatype,      /* I - datatype of the value    */
           const char *keyname,      /* I - name of keyword to read  */
           void *value,        /* O - keyword value            */
           char *comm,         /* O - keyword comment          */
           int  *status)       /* IO - error status            */
/*
  Read (get) the keyword value and comment from the FITS header.
  Reads a keyword value with the datatype specified by the 2nd argument.
*/
{
    long longval;
    double doubleval;

    if (*status > 0)           /* inherit input status value if > 0 */
        return(*status);

    if (datatype == TSTRING)
    {
        ffgkys(fptr, keyname, (char *) value, comm, status);
    }
    else if (datatype == TBYTE)
    {
        if (ffgkyj(fptr, keyname, &longval, comm, status) <= 0)
        {
            if (longval > UCHAR_MAX || longval < 0)
                *status = NUM_OVERFLOW;
            else
                *(unsigned char *) value = (unsigned char) longval;
        }
    }
    else if (datatype == TSBYTE)
    {
        if (ffgkyj(fptr, keyname, &longval, comm, status) <= 0)
        {
            if (longval > 127 || longval < -128)
                *status = NUM_OVERFLOW;
            else
                *(signed char *) value = (signed char) longval;
        }
    }
    else if (datatype == TUSHORT)
    {
        if (ffgkyj(fptr, keyname, &longval, comm, status) <= 0)
        {
            if (longval > (long) USHRT_MAX || longval < 0)
                *status = NUM_OVERFLOW;
            else
                *(unsigned short *) value = (unsigned short) longval;
        }
    }
    else if (datatype == TSHORT)
    {
        if (ffgkyj(fptr, keyname, &longval, comm, status) <= 0)
        {
            if (longval > SHRT_MAX || longval < SHRT_MIN)
                *status = NUM_OVERFLOW;
            else
                *(short *) value = (short) longval;
        }
    }
    else if (datatype == TUINT)
    {
        if (ffgkyj(fptr, keyname, &longval, comm, status) <= 0)
        {
            if (longval > (long) UINT_MAX || longval < 0)
                *status = NUM_OVERFLOW;
            else
                *(unsigned int *) value = longval;
        }
    }
    else if (datatype == TINT)
    {
        if (ffgkyj(fptr, keyname, &longval, comm, status) <= 0)
        {
            if (longval > INT_MAX || longval < INT_MIN)
                *status = NUM_OVERFLOW;
            else
                *(int *) value = longval;
        }
    }
    else if (datatype == TLOGICAL)
    {
        ffgkyl(fptr, keyname, (int *) value, comm, status);
    }
    else if (datatype == TULONG)
    {
        if (ffgkyd(fptr, keyname, &doubleval, comm, status) <= 0)
        {
            if (doubleval > (double) ULONG_MAX || doubleval < 0)
                *status = NUM_OVERFLOW;
            else
                 *(unsigned long *) value = (unsigned long) doubleval;
        }
    }
    else if (datatype == TLONG)
    {
        ffgkyj(fptr, keyname, (long *) value, comm, status);
    }
    else if (datatype == TLONGLONG)
    {
        ffgkyjj(fptr, keyname, (LONGLONG *) value, comm, status);
    }
    else if (datatype == TFLOAT)
    {
        ffgkye(fptr, keyname, (float *) value, comm, status);
    }
    else if (datatype == TDOUBLE)
    {
        ffgkyd(fptr, keyname, (double *) value, comm, status);
    }
    else if (datatype == TCOMPLEX)
    {
        ffgkyc(fptr, keyname, (float *) value, comm, status);
    }
    else if (datatype == TDBLCOMPLEX)
    {
        ffgkym(fptr, keyname, (double *) value, comm, status);
    }
    else
        *status = BAD_DATATYPE;

    return(*status);
} 
/*--------------------------------------------------------------------------*/
int ffgkey( fitsfile *fptr,     /* I - FITS file pointer        */
            const char *keyname,      /* I - name of keyword to read  */
            char *keyval,       /* O - keyword value            */
            char *comm,         /* O - keyword comment          */
            int  *status)       /* IO - error status            */
/*
  Read (get) the named keyword, returning the keyword value and comment.
  The value is just the literal string of characters in the value field
  of the keyword.  In the case of a string valued keyword, the returned
  value includes the leading and closing quote characters.  The value may be
  up to 70 characters long, and the comment may be up to 72 characters long.
  If the keyword has no value (no equal sign in column 9) then a null value
  is returned.
*/
{
    char card[FLEN_CARD];

    keyval[0] = '\0';
    if (comm)
       comm[0] = '\0';

    if (*status > 0)
        return(*status);

    if (ffgcrd(fptr, keyname, card, status) > 0)    /* get the 80-byte card */
        return(*status);

    ffpsvc(card, keyval, comm, status);      /* parse the value and comment */

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgrec( fitsfile *fptr,     /* I - FITS file pointer          */
            int nrec,           /* I - number of keyword to read  */
            char *card,         /* O - keyword card               */
            int  *status)       /* IO - error status              */
/*
  Read (get) the nrec-th keyword, returning the entire keyword card up to
  80 characters long.  The first keyword in the header has nrec = 1, not 0.
  The returned card value is null terminated with any trailing blank 
  characters removed.  If nrec = 0, then this routine simply moves the
  current header pointer to the top of the header.
*/
{
    if (*status > 0)
        return(*status);

    if (nrec == 0)
    {
        ffmaky(fptr, 1, status);  /* simply move to beginning of header */
        if (card)
            card[0] = '\0';           /* and return null card */
    }
    else if (nrec > 0)
    {
        ffmaky(fptr, nrec, status);
        ffgnky(fptr, card, status);
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgcrd( fitsfile *fptr,     /* I - FITS file pointer        */
            const char *name,         /* I - name of keyword to read  */
            char *card,         /* O - keyword card             */
            int  *status)       /* IO - error status            */
/*
  Read (get) the named keyword, returning the entire keyword card up to
  80 characters long.  
  The returned card value is null terminated with any trailing blank 
  characters removed.

  If the input name contains wild cards ('?' matches any single char
  and '*' matches any sequence of chars, # matches any string of decimal
  digits) then the search ends once the end of header is reached and does 
  not automatically resume from the top of the header.
*/
{
    int nkeys, nextkey, ntodo, namelen, namelen_limit, namelenminus1, cardlen;
    int ii = 0, jj, kk, wild, match, exact, hier = 0;
    char keyname[FLEN_KEYWORD], cardname[FLEN_KEYWORD];
    char *ptr1, *ptr2, *gotstar;

    if (*status > 0)
        return(*status);

    *keyname = '\0';
    
    while (name[ii] == ' ')  /* skip leading blanks in name */
        ii++;

    strncat(keyname, &name[ii], FLEN_KEYWORD - 1);

    namelen = strlen(keyname);

    while (namelen > 0 && keyname[namelen - 1] == ' ')
         namelen--;            /* ignore trailing blanks in name */

    keyname[namelen] = '\0';  /* terminate the name */

    for (ii=0; ii < namelen; ii++)       
        keyname[ii] = toupper(keyname[ii]);    /*  make upper case  */

    if (FSTRNCMP("HIERARCH", keyname, 8) == 0)
    {
        if (namelen == 8)
        {
            /* special case: just looking for any HIERARCH keyword */
            hier = 1;
        }
        else
        {
            /* ignore the leading HIERARCH and look for the 'real' name */
            /* starting with first non-blank character following HIERARCH */
            ptr1 = keyname;
            ptr2 = &keyname[8];

            while(*ptr2 == ' ')
                ptr2++;

            namelen = 0;
            while(*ptr2)
            {
                *ptr1 = *ptr2;
                 ptr1++;
                 ptr2++;
                 namelen++;
            }
            *ptr1 = '\0';
        }
    }

    /* does input name contain wild card chars?  ('?',  '*', or '#') */
    /* wild cards are currently not supported with HIERARCH keywords */

    namelen_limit = namelen;
    gotstar = 0;
    if (namelen < 9 && 
       (strchr(keyname,'?') || (gotstar = strchr(keyname,'*')) || 
        strchr(keyname,'#')) )
    {
        wild = 1;

        /* if we found a '*' wild card in the name, there might be */
        /* more than one.  Support up to 2 '*' in the template. */
        /* Thus we need to compare keywords whose names have at least */
        /* namelen - 2 characters.                                   */
        if (gotstar)
           namelen_limit -= 2;           
    }
    else
        wild = 0;

    ffghps(fptr, &nkeys, &nextkey, status); /* get no. keywords and position */

    namelenminus1 = maxvalue(namelen - 1, 1);
    ntodo = nkeys - nextkey + 1;  /* first, read from next keyword to end */
    for (jj=0; jj < 2; jj++)
    {
      for (kk = 0; kk < ntodo; kk++)
      {
        ffgnky(fptr, card, status);     /* get next keyword */

        if (hier)
        {
           if (FSTRNCMP("HIERARCH", card, 8) == 0)
                return(*status);  /* found a HIERARCH keyword */
        }
        else
        {
          ffgknm(card, cardname, &cardlen, status); /* get the keyword name */

          if (cardlen >= namelen_limit)  /* can't match if card < name */
          { 
            /* if there are no wild cards, lengths must be the same */
            if (!( !wild && cardlen != namelen) )
            {
              for (ii=0; ii < cardlen; ii++)
              {    
                /* make sure keyword is in uppercase */
                if (cardname[ii] > 96)
                {
                  /* This assumes the ASCII character set in which */
                  /* upper case characters start at ASCII(97)  */
                  /* Timing tests showed that this is 20% faster */
                  /* than calling the isupper function.          */

                  cardname[ii] = toupper(cardname[ii]);  /* make upper case */
                }
              }

              if (wild)
              {
                ffcmps(keyname, cardname, 1, &match, &exact);
                if (match)
                    return(*status); /* found a matching keyword */
              }
              else if (keyname[namelenminus1] == cardname[namelenminus1])
              {
                /* test the last character of the keyword name first, on */
                /* the theory that it is less likely to match then the first */
                /* character since many keywords begin with 'T', for example */

                if (FSTRNCMP(keyname, cardname, namelenminus1) == 0)
                {
                  return(*status);   /* found the matching keyword */
                }
              }
	      else if (namelen == 0 && cardlen == 0)
	      {
	         /* matched a blank keyword */
		 return(*status);
	      }
            }
          }
        }
      }

      if (wild || jj == 1)
            break;  /* stop at end of header if template contains wildcards */

      ffmaky(fptr, 1, status);  /* reset pointer to beginning of header */
      ntodo = nextkey - 1;      /* number of keyword to read */ 
    }

    return(*status = KEY_NO_EXIST);  /* couldn't find the keyword */
}
/*--------------------------------------------------------------------------*/
int ffgstr( fitsfile *fptr,     /* I - FITS file pointer        */
            const char *string, /* I - string to match  */
            char *card,         /* O - keyword card             */
            int  *status)       /* IO - error status            */
/*
  Read (get) the next keyword record that contains the input character string,
  returning the entire keyword card up to 80 characters long.
  The returned card value is null terminated with any trailing blank 
  characters removed.
*/
{
    int nkeys, nextkey, ntodo, stringlen;
    int jj, kk;

    if (*status > 0)
        return(*status);

    stringlen = strlen(string);
    if (stringlen > 80) {
        return(*status = KEY_NO_EXIST);  /* matching string is too long to exist */
    }

    ffghps(fptr, &nkeys, &nextkey, status); /* get no. keywords and position */
    ntodo = nkeys - nextkey + 1;  /* first, read from next keyword to end */

    for (jj=0; jj < 2; jj++)
    {
      for (kk = 0; kk < ntodo; kk++)
      {
        ffgnky(fptr, card, status);     /* get next keyword */
        if (strstr(card, string) != 0) {
            return(*status);   /* found the matching string */
        }
      }

      ffmaky(fptr, 1, status);  /* reset pointer to beginning of header */
      ntodo = nextkey - 1;      /* number of keyword to read */ 
    }

    return(*status = KEY_NO_EXIST);  /* couldn't find the keyword */
}
/*--------------------------------------------------------------------------*/
int ffgknm( char *card,         /* I - keyword card                   */
            char *name,         /* O - name of the keyword            */
            int *length,        /* O - length of the keyword name     */
            int  *status)       /* IO - error status                  */

/*
  Return the name of the keyword, and the name length.  This supports the
  ESO HIERARCH convention where keyword names may be > 8 characters long.
*/
{
    char *ptr1, *ptr2;
    int ii, namelength;

    namelength = FLEN_KEYWORD - 1;
    *name = '\0';
    *length = 0;

    /* support for ESO HIERARCH keywords; find the '=' */
    if (FSTRNCMP(card, "HIERARCH ", 9) == 0)
    {
        ptr2 = strchr(card, '=');

        if (!ptr2)   /* no value indicator ??? */
        {
            /* this probably indicates an error, so just return FITS name */
            strcat(name, "HIERARCH");
            *length = 8;
            return(*status);
        }

        /* find the start and end of the HIERARCH name */
        ptr1 = &card[9];
        while (*ptr1 == ' ')   /* skip spaces */
            ptr1++;

        strncat(name, ptr1, ptr2 - ptr1);
        ii = ptr2 - ptr1;

        while (ii > 0 && name[ii - 1] == ' ')  /* remove trailing spaces */
            ii--;

        name[ii] = '\0';
        *length = ii;
    }
    else
    {
        for (ii = 0; ii < namelength; ii++)
        {
           /* look for string terminator, or a blank */
           if (*(card+ii) != ' ' && *(card+ii) != '=' && *(card+ii) !='\0')
           {
               *(name+ii) = *(card+ii);
           }
           else
           {
               name[ii] = '\0';
               *length = ii;
               return(*status);
           }
        }

        /* if we got here, keyword is namelength characters long */
        name[namelength] = '\0';
        *length = namelength;
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgunt( fitsfile *fptr,     /* I - FITS file pointer         */
            const char *keyname,      /* I - name of keyword to read   */
            char *unit,         /* O - keyword units             */
            int  *status)       /* IO - error status             */
/*
    Read (get) the units string from the comment field of the existing
    keyword. This routine uses a local FITS convention (not defined in the
    official FITS standard) in which the units are enclosed in 
    square brackets following the '/' comment field delimiter, e.g.:

    KEYWORD =                   12 / [kpc] comment string goes here
*/
{
    char valstring[FLEN_VALUE];
    char comm[FLEN_COMMENT];
    char *loc;

    if (*status > 0)
        return(*status);

    ffgkey(fptr, keyname, valstring, comm, status);  /* read the keyword */

    if (comm[0] == '[')
    {
        loc = strchr(comm, ']');   /*  find the closing bracket */
        if (loc)
            *loc = '\0';           /*  terminate the string */

        strcpy(unit, &comm[1]);    /*  copy the string */
     }
     else
        unit[0] = '\0';
 
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgkys( fitsfile *fptr,     /* I - FITS file pointer         */
            const char *keyname,      /* I - name of keyword to read   */
            char *value,        /* O - keyword value             */
            char *comm,         /* O - keyword comment           */
            int  *status)       /* IO - error status             */
/*
  Get KeYword with a String value:
  Read (get) a simple string valued keyword.  The returned value may be up to 
  68 chars long ( + 1 null terminator char).  The routine does not support the
  HEASARC convention for continuing long string values over multiple keywords.
  The ffgkls routine may be used to read long continued strings. The returned
  comment string may be up to 69 characters long (including null terminator).
*/
{
    char valstring[FLEN_VALUE];

    if (*status > 0)
        return(*status);

    ffgkey(fptr, keyname, valstring, comm, status);  /* read the keyword */
    value[0] = '\0';
    ffc2s(valstring, value, status);   /* remove quotes from string */
 
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgksl( fitsfile *fptr,     /* I - FITS file pointer             */
           const char *keyname, /* I - name of keyword to read       */
           int *length,         /* O - length of the string value    */
           int  *status)        /* IO - error status                 */
/*
  Get the length of the keyword value string.
  This routine explicitly supports the CONTINUE convention for long string values.
*/
{
    char valstring[FLEN_VALUE], value[FLEN_VALUE];
    int position, contin, len;
    
    if (*status > 0)
        return(*status);

    ffgkey(fptr, keyname, valstring, NULL, status);  /* read the keyword */

    if (*status > 0)
        return(*status);

    ffghps(fptr, NULL,  &position, status); /* save the current header position */
    
    if (!valstring[0])  { /* null value string? */
        *length = 0;
    } else {
      ffc2s(valstring, value, status);  /* in case string contains "/" char  */
      *length = strlen(value);

      /* If last character is a & then value may be continued on next keyword */
      contin = 1;
      while (contin)  
      {
        len = strlen(value);

        if (len && *(value+len-1) == '&')  /*  is last char an anpersand?  */
        {
            ffgcnt(fptr, value, NULL, status);
            if (*value)    /* a null valstring indicates no continuation */
            {
               *length += strlen(value) - 1;
            }
            else
	    {
                contin = 0;
            }
        }
        else
	{
            contin = 0;
	}
      }
    }

    ffmaky(fptr, position - 1, status); /* reset header pointer to the keyword */
                                        /* since in many cases the program will read */
					/* the string value after getting the length */
    
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgkls( fitsfile *fptr,     /* I - FITS file pointer             */
           const char *keyname, /* I - name of keyword to read       */
           char **value,        /* O - pointer to keyword value      */
           char *comm,          /* O - keyword comment (may be NULL) */
           int  *status)        /* IO - error status                 */
/*
  This is the original routine for reading long string keywords that use
  the CONTINUE keyword convention.  In 2016 a new routine called
  ffgsky / fits_read_string_key was added, which may provide a more 
  convenient user interface  for most applications.

  Get Keyword with possible Long String value:
  Read (get) the named keyword, returning the value and comment.
  The returned value string may be arbitrarily long (by using the HEASARC
  convention for continuing long string values over multiple keywords) so
  this routine allocates the required memory for the returned string value.
  It is up to the calling routine to free the memory once it is finished
  with the value string.  The returned comment string may be up to 69
  characters long.
*/
{
    char valstring[FLEN_VALUE], nextcomm[FLEN_COMMENT];
    int contin, commspace = 0;
    size_t len;

    if (*status > 0)
        return(*status);

    *value = NULL;  /* initialize a null pointer in case of error */

    ffgkey(fptr, keyname, valstring, comm, status);  /* read the keyword */

    if (*status > 0)
        return(*status);

    if (comm)
    {
        /* remaining space in comment string */
        commspace = FLEN_COMMENT - strlen(comm) - 2;
    }
    
    if (!valstring[0])   /* null value string? */
    {
      *value = (char *) malloc(1);  /* allocate and return a null string */
      **value = '\0';
    }
    else
    {
      /* allocate space,  plus 1 for null */
      *value = (char *) malloc(strlen(valstring) + 1);

      ffc2s(valstring, *value, status);   /* convert string to value */
      len = strlen(*value);

      /* If last character is a & then value may be continued on next keyword */
      contin = 1;
      while (contin)  
      {
        if (len && *(*value+len-1) == '&')  /*  is last char an anpersand?  */
        {
            ffgcnt(fptr, valstring, nextcomm, status);
            if (*valstring)    /* a null valstring indicates no continuation */
            {
               *(*value+len-1) = '\0';         /* erase the trailing & char */
               len += strlen(valstring) - 1;
               *value = (char *) realloc(*value, len + 1); /* increase size */
               strcat(*value, valstring);     /* append the continued chars */
            }
            else
	    {
                contin = 0;
            }

            /* concantenate comment strings (if any) */
	    if ((commspace > 0) && (*nextcomm != 0)) 
	    {
                strncat(comm, " ", 1);
		strncat(comm, nextcomm, commspace);
                commspace = FLEN_COMMENT - strlen(comm) - 2;
            }
        }
        else
	{
            contin = 0;
	}
      }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgsky( fitsfile *fptr,     /* I - FITS file pointer             */
           const char *keyname, /* I - name of keyword to read       */
           int firstchar,       /* I - first character of string to return */
           int maxchar,         /* I - maximum length of string to return */
	                        /*    (string will be null terminated)  */      
           char *value,         /* O - pointer to keyword value      */
           int *valuelen,       /* O - total length of the keyword value string */
                                /*     The returned 'value' string may only */
				/*     contain a piece of the total string, depending */
				/*     on the value of firstchar and maxchar */
           char *comm,          /* O - keyword comment (may be NULL) */
           int  *status)        /* IO - error status                 */
/*
  Read and return the value of the specified string-valued keyword.
  
  This new routine was added in 2016 to provide a more convenient user
  interface than the older ffgkls routine.

  Read a string keyword, returning up to 'naxchars' characters of the value
  starting with the 'firstchar' character.
  The input 'value' string must be allocated at least 1 char bigger to
  allow for the terminating null character.
  
  This routine may be used to read continued string keywords that use 
  the CONTINUE keyword convention, as well as normal string keywords
  that are contained within a single header record.
  
  This routine differs from the ffkls routine in that it does not
  internally allocate memory for the returned value string, and consequently
  the calling routine does not need to call fffree to free the memory.
*/
{
    char valstring[FLEN_VALUE], nextcomm[FLEN_COMMENT];
    char *tempstring;
    int contin, commspace = 0;
    size_t len;

    if (*status > 0)
        return(*status);

    tempstring = NULL;  /* initialize in case of error */
    *value = '\0';
    if (valuelen) *valuelen = 0;
    
    ffgkey(fptr, keyname, valstring, comm, status);  /* read the keyword */

    if (*status > 0)
        return(*status);

    if (comm)
    {
        /* remaining space in comment string */
        commspace = FLEN_COMMENT - strlen(comm) - 2;
    }
    
    if (!valstring[0])   /* null value string? */
    {
      tempstring = (char *) malloc(1);  /* allocate and return a null string */
      *tempstring = '\0';
    }
    else
    {
      /* allocate space,  plus 1 for null */
      tempstring = (char *) malloc(strlen(valstring) + 1);

      ffc2s(valstring, tempstring, status);   /* convert string to value */
      len = strlen(tempstring);

      /* If last character is a & then value may be continued on next keyword */
      contin = 1;
      while (contin && *status <= 0)  
      {
        if (len && *(tempstring+len-1) == '&')  /*  is last char an anpersand?  */
        {
            ffgcnt(fptr, valstring, nextcomm, status);
            if (*valstring)    /* a null valstring indicates no continuation */
            {
               *(tempstring+len-1) = '\0';         /* erase the trailing & char */
               len += strlen(valstring) - 1;
               tempstring = (char *) realloc(tempstring, len + 1); /* increase size */
               strcat(tempstring, valstring);     /* append the continued chars */
            }
            else
	    {
                contin = 0;
            }

            /* concantenate comment strings (if any) */
	    if ((commspace > 0) && (*nextcomm != 0)) 
	    {
                strncat(comm, " ", 1);
		strncat(comm, nextcomm, commspace);
                commspace = FLEN_COMMENT - strlen(comm) - 2;
            }
        }
        else
	{
            contin = 0;
	}
      }
    }
    
    if (tempstring) 
    {
        len = strlen(tempstring);
	if (firstchar <= len)
            strncat(value, tempstring + (firstchar - 1), maxchar);
        free(tempstring);
	if (valuelen) *valuelen = len;  /* total length of the keyword value */
    }
    
    return(*status);
}
/*--------------------------------------------------------------------------*/
int fffree( void *value,       /* I - pointer to keyword value  */
            int  *status)      /* IO - error status             */
/*
  Free the memory that was previously allocated by CFITSIO, 
  such as by ffgkls or fits_hdr2str
*/
{
    if (*status > 0)
        return(*status);

    if (value)
        free(value);

    return(*status);
}
 /*--------------------------------------------------------------------------*/
int ffgcnt( fitsfile *fptr,     /* I - FITS file pointer         */
            char *value,        /* O - continued string value    */
            char *comm,         /* O - continued comment string  */
            int  *status)       /* IO - error status             */
/*
  Attempt to read the next keyword, returning the string value
  if it is a continuation of the previous string keyword value.
  This uses the HEASARC convention for continuing long string values
  over multiple keywords.  Each continued string is terminated with a
  backslash character, and the continuation follows on the next keyword
  which must have the name CONTINUE without an equal sign in column 9
  of the card.  If the next card is not a continuation, then the returned
  value string will be null.
*/
{
    int tstatus;
    char card[FLEN_CARD], strval[FLEN_VALUE];

    if (*status > 0)
        return(*status);

    tstatus = 0;
    value[0] = '\0';

    if (ffgnky(fptr, card, &tstatus) > 0)  /*  read next keyword  */
        return(*status);                   /*  hit end of header  */

    if (strncmp(card, "CONTINUE  ", 10) == 0)  /* a continuation card? */
    {
        strncpy(card, "D2345678=  ", 10); /* overwrite a dummy keyword name */
        ffpsvc(card, strval, comm, &tstatus);  /*  get the string value & comment */
        ffc2s(strval, value, &tstatus);    /* remove the surrounding quotes */

        if (tstatus)       /*  return null if error status was returned  */
           value[0] = '\0';
    }
    else
        ffmrky(fptr, -1, status);  /* reset the keyword pointer */

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgkyl( fitsfile *fptr,     /* I - FITS file pointer         */
            const char *keyname,      /* I - name of keyword to read   */
            int  *value,        /* O - keyword value             */
            char *comm,         /* O - keyword comment           */
            int  *status)       /* IO - error status             */
/*
  Read (get) the named keyword, returning the value and comment.
  The returned value = 1 if the keyword is true, else = 0 if false.
  The comment may be up to 69 characters long.
*/
{
    char valstring[FLEN_VALUE];

    if (*status > 0)
        return(*status);

    ffgkey(fptr, keyname, valstring, comm, status);  /* read the keyword */
    ffc2l(valstring, value, status);   /* convert string to value */

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgkyj( fitsfile *fptr,     /* I - FITS file pointer         */
            const char *keyname,      /* I - name of keyword to read   */
            long *value,        /* O - keyword value             */
            char *comm,         /* O - keyword comment           */
            int  *status)       /* IO - error status             */
/*
  Read (get) the named keyword, returning the value and comment.
  The value will be implicitly converted to a (long) integer if it not
  already of this datatype.  The comment may be up to 69 characters long.
*/
{
    char valstring[FLEN_VALUE];

    if (*status > 0)
        return(*status);

    ffgkey(fptr, keyname, valstring, comm, status);  /* read the keyword */
    ffc2i(valstring, value, status);   /* convert string to value */

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgkyjj( fitsfile *fptr,     /* I - FITS file pointer         */
            const char *keyname,      /* I - name of keyword to read   */
            LONGLONG *value,    /* O - keyword value             */
            char *comm,         /* O - keyword comment           */
            int  *status)       /* IO - error status             */
/*
  Read (get) the named keyword, returning the value and comment.
  The value will be implicitly converted to a (long) integer if it not
  already of this datatype.  The comment may be up to 69 characters long.
*/
{
    char valstring[FLEN_VALUE];

    if (*status > 0)
        return(*status);

    ffgkey(fptr, keyname, valstring, comm, status);  /* read the keyword */
    ffc2j(valstring, value, status);   /* convert string to value */

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgkye( fitsfile *fptr,     /* I - FITS file pointer         */
            const char  *keyname,     /* I - name of keyword to read   */
            float *value,       /* O - keyword value             */
            char  *comm,        /* O - keyword comment           */
            int   *status)      /* IO - error status             */
/*
  Read (get) the named keyword, returning the value and comment.
  The value will be implicitly converted to a float if it not
  already of this datatype.  The comment may be up to 69 characters long.
*/
{
    char valstring[FLEN_VALUE];

    if (*status > 0)
        return(*status);

    ffgkey(fptr, keyname, valstring, comm, status);  /* read the keyword */
    ffc2r(valstring, value, status);   /* convert string to value */

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgkyd( fitsfile *fptr,      /* I - FITS file pointer         */
            const char   *keyname,     /* I - name of keyword to read   */
            double *value,       /* O - keyword value             */
            char   *comm,        /* O - keyword comment           */
            int    *status)      /* IO - error status             */
/*
  Read (get) the named keyword, returning the value and comment.
  The value will be implicitly converted to a double if it not
  already of this datatype.  The comment may be up to 69 characters long.
*/
{
    char valstring[FLEN_VALUE];

    if (*status > 0)
        return(*status);

    ffgkey(fptr, keyname, valstring, comm, status);  /* read the keyword */
    ffc2d(valstring, value, status);   /* convert string to value */

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgkyc( fitsfile *fptr,     /* I - FITS file pointer         */
            const char  *keyname,     /* I - name of keyword to read   */
            float *value,       /* O - keyword value (real,imag) */
            char  *comm,        /* O - keyword comment           */
            int   *status)      /* IO - error status             */
/*
  Read (get) the named keyword, returning the value and comment.
  The keyword must have a complex value. No implicit data conversion
  will be performed.
*/
{
    char valstring[FLEN_VALUE], message[FLEN_ERRMSG];
    int len;

    if (*status > 0)
        return(*status);

    ffgkey(fptr, keyname, valstring, comm, status);  /* read the keyword */

    if (valstring[0] != '(' )   /* test that this is a complex keyword */
    {
      snprintf(message, FLEN_ERRMSG, "keyword %s does not have a complex value (ffgkyc):",
              keyname);
      ffpmsg(message);
      ffpmsg(valstring);
      return(*status = BAD_C2F);
    }

    valstring[0] = ' ';            /* delete the opening parenthesis */
    len = strcspn(valstring, ")" );  
    valstring[len] = '\0';         /* delete the closing parenthesis */

    len = strcspn(valstring, ",");
    valstring[len] = '\0';

    ffc2r(valstring, &value[0], status);       /* convert the real part */
    ffc2r(&valstring[len + 1], &value[1], status); /* convert imag. part */
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgkym( fitsfile *fptr,     /* I - FITS file pointer         */
            const char  *keyname,     /* I - name of keyword to read   */
            double *value,      /* O - keyword value (real,imag) */
            char  *comm,        /* O - keyword comment           */
            int   *status)      /* IO - error status             */
/*
  Read (get) the named keyword, returning the value and comment.
  The keyword must have a complex value. No implicit data conversion
  will be performed.
*/
{
    char valstring[FLEN_VALUE], message[FLEN_ERRMSG];
    int len;

    if (*status > 0)
        return(*status);

    ffgkey(fptr, keyname, valstring, comm, status);  /* read the keyword */

    if (valstring[0] != '(' )   /* test that this is a complex keyword */
    {
      snprintf(message, FLEN_ERRMSG, "keyword %s does not have a complex value (ffgkym):",
              keyname);
      ffpmsg(message);
      ffpmsg(valstring);
      return(*status = BAD_C2D);
    }

    valstring[0] = ' ';            /* delete the opening parenthesis */
    len = strcspn(valstring, ")" );  
    valstring[len] = '\0';         /* delete the closing parenthesis */

    len = strcspn(valstring, ",");
    valstring[len] = '\0';

    ffc2d(valstring, &value[0], status);        /* convert the real part */
    ffc2d(&valstring[len + 1], &value[1], status);  /* convert the imag. part */

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgkyt( fitsfile *fptr,      /* I - FITS file pointer                 */
            const char   *keyname,     /* I - name of keyword to read           */
            long   *ivalue,      /* O - integer part of keyword value     */
            double *fraction,    /* O - fractional part of keyword value  */
            char   *comm,        /* O - keyword comment                   */
            int    *status)      /* IO - error status                     */
/*
  Read (get) the named keyword, returning the value and comment.
  The integer and fractional parts of the value are returned in separate
  variables, to allow more numerical precision to be passed.  This
  effectively passes a 'triple' precision value, with a 4-byte integer
  and an 8-byte fraction.  The comment may be up to 69 characters long.
*/
{
    char valstring[FLEN_VALUE];
    char *loc;

    if (*status > 0)
        return(*status);

    ffgkey(fptr, keyname, valstring, comm, status);  /* read the keyword */

    /*  read the entire value string as a double, to get the integer part */
    ffc2d(valstring, fraction, status);

    *ivalue = (long) *fraction;

    *fraction = *fraction - *ivalue;

    /* see if we need to read the fractional part again with more precision */
    /* look for decimal point, without an exponential E or D character */

    loc = strchr(valstring, '.');
    if (loc)
    {
        if (!strchr(valstring, 'E') && !strchr(valstring, 'D'))
            ffc2d(loc, fraction, status);
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgkyn( fitsfile *fptr,      /* I - FITS file pointer             */
            int    nkey,         /* I - number of the keyword to read */
            char   *keyname,     /* O - name of the keyword           */
            char   *value,       /* O - keyword value                 */
            char   *comm,        /* O - keyword comment               */
            int    *status)      /* IO - error status                 */
/*
  Read (get) the nkey-th keyword returning the keyword name, value and comment.
  The value is just the literal string of characters in the value field
  of the keyword.  In the case of a string valued keyword, the returned
  value includes the leading and closing quote characters.  The value may be
  up to 70 characters long, and the comment may be up to 72 characters long.
  If the keyword has no value (no equal sign in column 9) then a null value
  is returned.  If comm = NULL, then do not return the comment string.
*/
{
    char card[FLEN_CARD], sbuff[FLEN_CARD];
    int namelen;

    keyname[0] = '\0';
    value[0] = '\0';
    if (comm)
        comm[0] = '\0';

    if (*status > 0)
        return(*status);

    if (ffgrec(fptr, nkey, card, status) > 0 )  /* get the 80-byte card */
        return(*status);

    ffgknm(card, keyname, &namelen, status); /* get the keyword name */

    if (ffpsvc(card, value, comm, status) > 0)   /* parse value and comment */
        return(*status);

    if (fftrec(keyname, status) > 0)  /* test keyword name; catches no END */
    {
     snprintf(sbuff, FLEN_CARD, "Name of keyword no. %d contains illegal character(s): %s",
              nkey, keyname);
     ffpmsg(sbuff);

     if (nkey % 36 == 0)  /* test if at beginning of 36-card FITS record */
            ffpmsg("  (This may indicate a missing END keyword).");
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgkns( fitsfile *fptr,     /* I - FITS file pointer                    */
            const char *keyname,      /* I - root name of keywords to read        */
            int  nstart,        /* I - starting index number                */
            int  nmax,          /* I - maximum number of keywords to return */
            char *value[],      /* O - array of pointers to keyword values  */
            int  *nfound,       /* O - number of values that were returned  */
            int  *status)       /* IO - error status                        */
/*
  Read (get) an indexed array of keywords with index numbers between
  NSTART and (NSTART + NMAX -1) inclusive.  
  This routine does NOT support the HEASARC long string convention.
*/
{
    int nend, lenroot, ii, nkeys, mkeys, tstatus, undefinedval;
    long ival;
    char keyroot[FLEN_KEYWORD], keyindex[8], card[FLEN_CARD];
    char svalue[FLEN_VALUE], comm[FLEN_COMMENT], *equalssign;

    if (*status > 0)
        return(*status);

    *nfound = 0;
    nend = nstart + nmax - 1;

    keyroot[0] = '\0';
    strncat(keyroot, keyname, FLEN_KEYWORD - 1);
     
    lenroot = strlen(keyroot);
    
    if (lenroot == 0)     /*  root must be at least 1 char long  */
        return(*status);

    for (ii=0; ii < lenroot; ii++)           /*  make sure upper case  */
        keyroot[ii] = toupper(keyroot[ii]);

    ffghps(fptr, &nkeys, &mkeys, status);  /*  get the number of keywords  */

    undefinedval = FALSE;
    for (ii=3; ii <= nkeys; ii++)  
    {
       if (ffgrec(fptr, ii, card, status) > 0)     /*  get next keyword  */
           return(*status);

       if (strncmp(keyroot, card, lenroot) == 0)  /* see if keyword matches */
       {
          keyindex[0] = '\0';
          equalssign = strchr(card, '=');
	  if (equalssign == 0) continue;  /* keyword has no value */

          strncat(keyindex, &card[lenroot], equalssign - card  - lenroot);  /*  copy suffix  */
          tstatus = 0;
          if (ffc2ii(keyindex, &ival, &tstatus) <= 0)     /*  test suffix  */
          {
             if (ival <= nend && ival >= nstart)
             {
                ffpsvc(card, svalue, comm, status);  /*  parse the value */
                ffc2s(svalue, value[ival-nstart], status); /* convert */
                if (ival - nstart + 1 > *nfound)
                      *nfound = ival - nstart + 1;  /*  max found */ 

                if (*status == VALUE_UNDEFINED)
                {
                   undefinedval = TRUE;
                   *status = 0;  /* reset status to read remaining values */
                }
             }
          }
       }
    }
    if (undefinedval && (*status <= 0) )
        *status = VALUE_UNDEFINED;  /* report at least 1 value undefined */

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgknl( fitsfile *fptr,     /* I - FITS file pointer                    */
            const char *keyname,      /* I - root name of keywords to read        */
            int  nstart,        /* I - starting index number                */
            int  nmax,          /* I - maximum number of keywords to return */
            int  *value,        /* O - array of keyword values              */
            int  *nfound,       /* O - number of values that were returned  */
            int  *status)       /* IO - error status                        */
/*
  Read (get) an indexed array of keywords with index numbers between
  NSTART and (NSTART + NMAX -1) inclusive.  
  The returned value = 1 if the keyword is true, else = 0 if false.
*/
{
    int nend, lenroot, ii, nkeys, mkeys, tstatus, undefinedval;
    long ival;
    char keyroot[FLEN_KEYWORD], keyindex[8], card[FLEN_CARD];
    char svalue[FLEN_VALUE], comm[FLEN_COMMENT], *equalssign;

    if (*status > 0)
        return(*status);

    *nfound = 0;
    nend = nstart + nmax - 1;

    keyroot[0] = '\0';
    strncat(keyroot, keyname, FLEN_KEYWORD - 1);

    lenroot = strlen(keyroot);
    
    if (lenroot == 0)     /*  root must be at least 1 char long  */
        return(*status);
 
    for (ii=0; ii < lenroot; ii++)           /*  make sure upper case  */
        keyroot[ii] = toupper(keyroot[ii]);

    ffghps(fptr, &nkeys, &mkeys, status);  /*  get the number of keywords  */

    ffmaky(fptr, 3, status);  /* move to 3rd keyword (skip 1st 2 keywords) */

    undefinedval = FALSE;
    for (ii=3; ii <= nkeys; ii++)  
    {
       if (ffgnky(fptr, card, status) > 0)     /*  get next keyword  */
           return(*status);

       if (strncmp(keyroot, card, lenroot) == 0)  /* see if keyword matches */
       {
          keyindex[0] = '\0';
          equalssign = strchr(card, '=');
	  if (equalssign == 0) continue;  /* keyword has no value */

          strncat(keyindex, &card[lenroot], equalssign - card  - lenroot);  /*  copy suffix  */

          tstatus = 0;
          if (ffc2ii(keyindex, &ival, &tstatus) <= 0)    /*  test suffix  */
          {
             if (ival <= nend && ival >= nstart)
             {
                ffpsvc(card, svalue, comm, status);   /*  parse the value */
                ffc2l(svalue, &value[ival-nstart], status); /* convert*/
                if (ival - nstart + 1 > *nfound)
                      *nfound = ival - nstart + 1;  /*  max found */ 

                if (*status == VALUE_UNDEFINED)
                {
                    undefinedval = TRUE;
                   *status = 0;  /* reset status to read remaining values */
                }
             }
          }
       }
    }
    if (undefinedval && (*status <= 0) )
        *status = VALUE_UNDEFINED;  /* report at least 1 value undefined */

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgknj( fitsfile *fptr,     /* I - FITS file pointer                    */
            const char *keyname,      /* I - root name of keywords to read        */
            int  nstart,        /* I - starting index number                */
            int  nmax,          /* I - maximum number of keywords to return */
            long *value,        /* O - array of keyword values              */
            int  *nfound,       /* O - number of values that were returned  */
            int  *status)       /* IO - error status                        */
/*
  Read (get) an indexed array of keywords with index numbers between
  NSTART and (NSTART + NMAX -1) inclusive.  
*/
{
    int nend, lenroot, ii, nkeys, mkeys, tstatus, undefinedval;
    long ival;
    char keyroot[FLEN_KEYWORD], keyindex[8], card[FLEN_CARD];
    char svalue[FLEN_VALUE], comm[FLEN_COMMENT], *equalssign;

    if (*status > 0)
        return(*status);

    *nfound = 0;
    nend = nstart + nmax - 1;

    keyroot[0] = '\0';
    strncat(keyroot, keyname, FLEN_KEYWORD - 1);

    lenroot = strlen(keyroot);
    
    if (lenroot == 0)     /*  root must be at least 1 char long  */
        return(*status);
 
    for (ii=0; ii < lenroot; ii++)           /*  make sure upper case  */
        keyroot[ii] = toupper(keyroot[ii]);

    ffghps(fptr, &nkeys, &mkeys, status);  /*  get the number of keywords  */

    ffmaky(fptr, 3, status);  /* move to 3rd keyword (skip 1st 2 keywords) */

    undefinedval = FALSE;
    for (ii=3; ii <= nkeys; ii++)  
    {
       if (ffgnky(fptr, card, status) > 0)     /*  get next keyword  */
           return(*status);

       if (strncmp(keyroot, card, lenroot) == 0)  /* see if keyword matches */
       {
          keyindex[0] = '\0';
          equalssign = strchr(card, '=');
	  if (equalssign == 0) continue;  /* keyword has no value */

          strncat(keyindex, &card[lenroot], equalssign - card  - lenroot);  /*  copy suffix  */

          tstatus = 0;
          if (ffc2ii(keyindex, &ival, &tstatus) <= 0)     /*  test suffix  */
          {
             if (ival <= nend && ival >= nstart)
             {
                ffpsvc(card, svalue, comm, status);   /*  parse the value */
                ffc2i(svalue, &value[ival-nstart], status);  /* convert */
                if (ival - nstart + 1 > *nfound)
                      *nfound = ival - nstart + 1;  /*  max found */ 

                if (*status == VALUE_UNDEFINED)
                {
                    undefinedval = TRUE;
                   *status = 0;  /* reset status to read remaining values */
                }
             }
          }
       }
    }
    if (undefinedval && (*status <= 0) )
        *status = VALUE_UNDEFINED;  /* report at least 1 value undefined */

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgknjj( fitsfile *fptr,    /* I - FITS file pointer                    */
            const char *keyname,      /* I - root name of keywords to read        */
            int  nstart,        /* I - starting index number                */
            int  nmax,          /* I - maximum number of keywords to return */
            LONGLONG *value,    /* O - array of keyword values              */
            int  *nfound,       /* O - number of values that were returned  */
            int  *status)       /* IO - error status                        */
/*
  Read (get) an indexed array of keywords with index numbers between
  NSTART and (NSTART + NMAX -1) inclusive.  
*/
{
    int nend, lenroot, ii, nkeys, mkeys, tstatus, undefinedval;
    long ival;
    char keyroot[FLEN_KEYWORD], keyindex[8], card[FLEN_CARD];
    char svalue[FLEN_VALUE], comm[FLEN_COMMENT], *equalssign;

    if (*status > 0)
        return(*status);

    *nfound = 0;
    nend = nstart + nmax - 1;

    keyroot[0] = '\0';
    strncat(keyroot, keyname, FLEN_KEYWORD - 1);

    lenroot = strlen(keyroot);
    
    if (lenroot == 0)     /*  root must be at least 1 char long  */
        return(*status);

    for (ii=0; ii < lenroot; ii++)           /*  make sure upper case  */
        keyroot[ii] = toupper(keyroot[ii]);

    ffghps(fptr, &nkeys, &mkeys, status);  /*  get the number of keywords  */

    ffmaky(fptr, 3, status);  /* move to 3rd keyword (skip 1st 2 keywords) */

    undefinedval = FALSE;
    for (ii=3; ii <= nkeys; ii++)  
    {
       if (ffgnky(fptr, card, status) > 0)     /*  get next keyword  */
           return(*status);

       if (strncmp(keyroot, card, lenroot) == 0)  /* see if keyword matches */
       {
          keyindex[0] = '\0';
          equalssign = strchr(card, '=');
	  if (equalssign == 0) continue;  /* keyword has no value */

          strncat(keyindex, &card[lenroot], equalssign - card  - lenroot);  /*  copy suffix  */

          tstatus = 0;
          if (ffc2ii(keyindex, &ival, &tstatus) <= 0)     /*  test suffix  */
          {
             if (ival <= nend && ival >= nstart)
             {
                ffpsvc(card, svalue, comm, status);   /*  parse the value */
                ffc2j(svalue, &value[ival-nstart], status);  /* convert */
                if (ival - nstart + 1 > *nfound)
                      *nfound = ival - nstart + 1;  /*  max found */ 

                if (*status == VALUE_UNDEFINED)
                {
                    undefinedval = TRUE;
                   *status = 0;  /* reset status to read remaining values */
                }
             }
          }
       }
    }
    if (undefinedval && (*status <= 0) )
        *status = VALUE_UNDEFINED;  /* report at least 1 value undefined */

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgkne( fitsfile *fptr,     /* I - FITS file pointer                    */
            const char *keyname,      /* I - root name of keywords to read        */
            int  nstart,        /* I - starting index number                */
            int  nmax,          /* I - maximum number of keywords to return */
            float *value,       /* O - array of keyword values              */
            int  *nfound,       /* O - number of values that were returned  */
            int  *status)       /* IO - error status                        */
/*
  Read (get) an indexed array of keywords with index numbers between
  NSTART and (NSTART + NMAX -1) inclusive.  
*/
{
    int nend, lenroot, ii, nkeys, mkeys, tstatus, undefinedval;
    long ival;
    char keyroot[FLEN_KEYWORD], keyindex[8], card[FLEN_CARD];
    char svalue[FLEN_VALUE], comm[FLEN_COMMENT], *equalssign;

    if (*status > 0)
        return(*status);

    *nfound = 0;
    nend = nstart + nmax - 1;

    keyroot[0] = '\0';
    strncat(keyroot, keyname, FLEN_KEYWORD - 1);

    lenroot = strlen(keyroot);
    
    if (lenroot == 0)     /*  root must be at least 1 char long  */
        return(*status);

    for (ii=0; ii < lenroot; ii++)           /*  make sure upper case  */
        keyroot[ii] = toupper(keyroot[ii]);

    ffghps(fptr, &nkeys, &mkeys, status);  /*  get the number of keywords  */

    ffmaky(fptr, 3, status);  /* move to 3rd keyword (skip 1st 2 keywords) */

    undefinedval = FALSE;
    for (ii=3; ii <= nkeys; ii++)  
    {
       if (ffgnky(fptr, card, status) > 0)     /*  get next keyword  */
           return(*status);

       if (strncmp(keyroot, card, lenroot) == 0)  /* see if keyword matches */
       {
          keyindex[0] = '\0';
          equalssign = strchr(card, '=');
	  if (equalssign == 0) continue;  /* keyword has no value */

          strncat(keyindex, &card[lenroot], equalssign - card  - lenroot);  /*  copy suffix  */

          tstatus = 0;
          if (ffc2ii(keyindex, &ival, &tstatus) <= 0)     /*  test suffix  */
          {
             if (ival <= nend && ival >= nstart)
             {
                ffpsvc(card, svalue, comm, status);   /*  parse the value */
                ffc2r(svalue, &value[ival-nstart], status); /* convert */
                if (ival - nstart + 1 > *nfound)
                      *nfound = ival - nstart + 1;  /*  max found */ 

                if (*status == VALUE_UNDEFINED)
                {
                    undefinedval = TRUE;
                   *status = 0;  /* reset status to read remaining values */
                }
             }
          }
       }
    }
    if (undefinedval && (*status <= 0) )
        *status = VALUE_UNDEFINED;  /* report at least 1 value undefined */

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgknd( fitsfile *fptr,     /* I - FITS file pointer                    */
            const char *keyname,      /* I - root name of keywords to read        */
            int  nstart,        /* I - starting index number                */
            int  nmax,          /* I - maximum number of keywords to return */
            double *value,      /* O - array of keyword values              */
            int  *nfound,       /* O - number of values that were returned  */
            int  *status)       /* IO - error status                        */
/*
  Read (get) an indexed array of keywords with index numbers between
  NSTART and (NSTART + NMAX -1) inclusive.  
*/
{
    int nend, lenroot, ii, nkeys, mkeys, tstatus, undefinedval;
    long ival;
    char keyroot[FLEN_KEYWORD], keyindex[8], card[FLEN_CARD];
    char svalue[FLEN_VALUE], comm[FLEN_COMMENT], *equalssign;

    if (*status > 0)
        return(*status);

    *nfound = 0;
    nend = nstart + nmax - 1;

    keyroot[0] = '\0';
    strncat(keyroot, keyname, FLEN_KEYWORD - 1);

    lenroot = strlen(keyroot);

    if (lenroot == 0)     /*  root must be at least 1 char long  */
        return(*status);

    for (ii=0; ii < lenroot; ii++)           /*  make sure upper case  */
        keyroot[ii] = toupper(keyroot[ii]);

    ffghps(fptr, &nkeys, &mkeys, status);  /*  get the number of keywords  */

    ffmaky(fptr, 3, status);  /* move to 3rd keyword (skip 1st 2 keywords) */

    undefinedval = FALSE;
    for (ii=3; ii <= nkeys; ii++)  
    {
       if (ffgnky(fptr, card, status) > 0)     /*  get next keyword  */
           return(*status);
       if (strncmp(keyroot, card, lenroot) == 0)   /* see if keyword matches */
       {
          keyindex[0] = '\0';
          equalssign = strchr(card, '=');
	  if (equalssign == 0) continue;  /* keyword has no value */

          strncat(keyindex, &card[lenroot], equalssign - card  - lenroot);  /*  copy suffix  */
          tstatus = 0;
          if (ffc2ii(keyindex, &ival, &tstatus) <= 0)      /*  test suffix */
          {
             if (ival <= nend && ival >= nstart) /* is index within range? */
             {
                ffpsvc(card, svalue, comm, status);   /*  parse the value */
                ffc2d(svalue, &value[ival-nstart], status); /* convert */
                if (ival - nstart + 1 > *nfound)
                      *nfound = ival - nstart + 1;  /*  max found */ 

                if (*status == VALUE_UNDEFINED)
                {
                    undefinedval = TRUE;
                   *status = 0;  /* reset status to read remaining values */
                }
             }
          }
       }
    }
    if (undefinedval && (*status <= 0) )
        *status = VALUE_UNDEFINED;  /* report at least 1 value undefined */

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgtdm(fitsfile *fptr,  /* I - FITS file pointer                        */
           int colnum,      /* I - number of the column to read             */
           int maxdim,      /* I - maximum no. of dimensions to read;       */
           int *naxis,      /* O - number of axes in the data array         */
           long naxes[],    /* O - length of each data axis                 */
           int *status)     /* IO - error status                            */
/*
  read and parse the TDIMnnn keyword to get the dimensionality of a column
*/
{
    int tstatus = 0;
    char keyname[FLEN_KEYWORD], tdimstr[FLEN_VALUE];

    if (*status > 0)
        return(*status);

    ffkeyn("TDIM", colnum, keyname, status);      /* construct keyword name */

    ffgkys(fptr, keyname, tdimstr, NULL, &tstatus); /* try reading keyword */

    ffdtdm(fptr, tdimstr, colnum, maxdim,naxis, naxes, status); /* decode it */

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgtdmll(fitsfile *fptr,  /* I - FITS file pointer                      */
           int colnum,      /* I - number of the column to read             */
           int maxdim,      /* I - maximum no. of dimensions to read;       */
           int *naxis,      /* O - number of axes in the data array         */
           LONGLONG naxes[], /* O - length of each data axis                 */
           int *status)     /* IO - error status                            */
/*
  read and parse the TDIMnnn keyword to get the dimensionality of a column
*/
{
    int tstatus = 0;
    char keyname[FLEN_KEYWORD], tdimstr[FLEN_VALUE];

    if (*status > 0)
        return(*status);

    ffkeyn("TDIM", colnum, keyname, status);      /* construct keyword name */

    ffgkys(fptr, keyname, tdimstr, NULL, &tstatus); /* try reading keyword */

    ffdtdmll(fptr, tdimstr, colnum, maxdim,naxis, naxes, status); /* decode it */

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffdtdm(fitsfile *fptr,  /* I - FITS file pointer                        */
           char *tdimstr,   /* I - TDIMn keyword value string. e.g. (10,10) */
           int colnum,      /* I - number of the column             */
           int maxdim,      /* I - maximum no. of dimensions to read;       */
           int *naxis,      /* O - number of axes in the data array         */
           long naxes[],    /* O - length of each data axis                 */
           int *status)     /* IO - error status                            */
/*
  decode the TDIMnnn keyword to get the dimensionality of a column.
  Check that the value is legal and consistent with the TFORM value.
  If colnum = 0, then the validity checking is disabled.
*/
{
    long dimsize, totalpix = 1;
    char *loc, *lastloc, message[FLEN_ERRMSG];
    tcolumn *colptr = 0;

    if (*status > 0)
        return(*status);

    if (colnum != 0) {
        if (fptr->HDUposition != (fptr->Fptr)->curhdu)
            ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

        if (colnum < 1 || colnum > (fptr->Fptr)->tfield)
            return(*status = BAD_COL_NUM);

        colptr = (fptr->Fptr)->tableptr;   /* set pointer to the first column */
        colptr += (colnum - 1);    /* increment to the correct column */

        if (!tdimstr[0])   /* TDIMn keyword doesn't exist? */
        {
            *naxis = 1;                   /* default = 1 dimensional */
            if (maxdim > 0)
                naxes[0] = (long) colptr->trepeat; /* default length = repeat */

            return(*status);
        }
    }

    *naxis = 0;

    loc = strchr(tdimstr, '(' );  /* find the opening quote */
    if (!loc)
    {
            snprintf(message, FLEN_ERRMSG, "Illegal dimensions format: %s", tdimstr);
            return(*status = BAD_TDIM);
    }

    while (loc)
    {
            loc++;
            dimsize = strtol(loc, &loc, 10);  /* read size of next dimension */
            if (*naxis < maxdim)
                naxes[*naxis] = dimsize;

            if (dimsize < 0)
            {
                ffpmsg("one or more dimension are less than 0 (ffdtdm)");
                ffpmsg(tdimstr);
                return(*status = BAD_TDIM);
            }

            totalpix *= dimsize;
            (*naxis)++;
            lastloc = loc;
            loc = strchr(loc, ',');  /* look for comma before next dimension */
    }

    loc = strchr(lastloc, ')' );  /* check for the closing quote */
    if (!loc)
    {
            snprintf(message, FLEN_ERRMSG, "Illegal dimensions format: %s", tdimstr);
            return(*status = BAD_TDIM);
    }

    if (colnum != 0) {
        if ((colptr->tdatatype > 0) && ((long) colptr->trepeat != totalpix))
        {
          snprintf(message, FLEN_ERRMSG,
          "column vector length, %ld, does not equal TDIMn array size, %ld",
          (long) colptr->trepeat, totalpix);
          ffpmsg(message);
          ffpmsg(tdimstr);
          return(*status = BAD_TDIM);
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffdtdmll(fitsfile *fptr,  /* I - FITS file pointer                        */
           char *tdimstr,   /* I - TDIMn keyword value string. e.g. (10,10) */
           int colnum,      /* I - number of the column             */
           int maxdim,      /* I - maximum no. of dimensions to read;       */
           int *naxis,      /* O - number of axes in the data array         */
           LONGLONG naxes[],    /* O - length of each data axis                 */
           int *status)     /* IO - error status                            */
/*
  decode the TDIMnnn keyword to get the dimensionality of a column.
  Check that the value is legal and consistent with the TFORM value.
*/
{
    LONGLONG dimsize;
    LONGLONG totalpix = 1;
    char *loc, *lastloc, message[FLEN_ERRMSG];
    tcolumn *colptr;
    double doublesize;

    if (*status > 0)
        return(*status);

    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    if (colnum < 1 || colnum > (fptr->Fptr)->tfield)
        return(*status = BAD_COL_NUM);

    colptr = (fptr->Fptr)->tableptr;   /* set pointer to the first column */
    colptr += (colnum - 1);    /* increment to the correct column */

    if (!tdimstr[0])   /* TDIMn keyword doesn't exist? */
    {
        *naxis = 1;                   /* default = 1 dimensional */
        if (maxdim > 0)
            naxes[0] = colptr->trepeat; /* default length = repeat */
    }
    else
    {
        *naxis = 0;

        loc = strchr(tdimstr, '(' );  /* find the opening quote */
        if (!loc)
        {
            snprintf(message, FLEN_ERRMSG, "Illegal TDIM keyword value: %s", tdimstr);
            return(*status = BAD_TDIM);
        }

        while (loc)
        {
            loc++;

    /* Read value as a double because the string to 64-bit int function is  */
    /* platform dependent (strtoll, strtol, _atoI64).  This still gives     */
    /* about 48 bits of precision, which is plenty for this purpose.        */

            doublesize = strtod(loc, &loc);
            dimsize = (LONGLONG) (doublesize + 0.1);

            if (*naxis < maxdim)
                naxes[*naxis] = dimsize;

            if (dimsize < 0)
            {
                ffpmsg("one or more TDIM values are less than 0 (ffdtdm)");
                ffpmsg(tdimstr);
                return(*status = BAD_TDIM);
            }

            totalpix *= dimsize;
            (*naxis)++;
            lastloc = loc;
            loc = strchr(loc, ',');  /* look for comma before next dimension */
        }

        loc = strchr(lastloc, ')' );  /* check for the closing quote */
        if (!loc)
        {
            snprintf(message, FLEN_ERRMSG, "Illegal TDIM keyword value: %s", tdimstr);
            return(*status = BAD_TDIM);
        }

        if ((colptr->tdatatype > 0) && (colptr->trepeat != totalpix))
        {
          snprintf(message, FLEN_ERRMSG,
          "column vector length, %.0f, does not equal TDIMn array size, %.0f",
          (double) (colptr->trepeat), (double) totalpix);
          ffpmsg(message);
          ffpmsg(tdimstr);
          return(*status = BAD_TDIM);
        }
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffghpr(fitsfile *fptr,  /* I - FITS file pointer                        */
           int maxdim,      /* I - maximum no. of dimensions to read;       */
           int *simple,     /* O - does file conform to FITS standard? 1/0  */
           int *bitpix,     /* O - number of bits per data value pixel      */
           int *naxis,      /* O - number of axes in the data array         */
           long naxes[],    /* O - length of each data axis                 */
           long *pcount,    /* O - number of group parameters (usually 0)   */
           long *gcount,    /* O - number of random groups (usually 1 or 0) */
           int *extend,     /* O - may FITS file haave extensions?          */
           int *status)     /* IO - error status                            */
/*
  Get keywords from the Header of the PRimary array:
  Check that the keywords conform to the FITS standard and return the
  parameters which determine the size and structure of the primary array
  or IMAGE extension.
*/
{
    int idummy, ii;
    LONGLONG lldummy;
    double ddummy;
    LONGLONG tnaxes[99];

    ffgphd(fptr, maxdim, simple, bitpix, naxis, tnaxes, pcount, gcount, extend,
          &ddummy, &ddummy, &lldummy, &idummy, status);
	  
    if (naxis && naxes) {
         for (ii = 0; (ii < *naxis) && (ii < maxdim); ii++)
	     naxes[ii] = (long) tnaxes[ii];
    } else if (naxes) {
         for (ii = 0; ii < maxdim; ii++)
	     naxes[ii] = (long) tnaxes[ii];
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffghprll(fitsfile *fptr,  /* I - FITS file pointer                        */
           int maxdim,      /* I - maximum no. of dimensions to read;       */
           int *simple,     /* O - does file conform to FITS standard? 1/0  */
           int *bitpix,     /* O - number of bits per data value pixel      */
           int *naxis,      /* O - number of axes in the data array         */
           LONGLONG naxes[],    /* O - length of each data axis                 */
           long *pcount,    /* O - number of group parameters (usually 0)   */
           long *gcount,    /* O - number of random groups (usually 1 or 0) */
           int *extend,     /* O - may FITS file haave extensions?          */
           int *status)     /* IO - error status                            */
/*
  Get keywords from the Header of the PRimary array:
  Check that the keywords conform to the FITS standard and return the
  parameters which determine the size and structure of the primary array
  or IMAGE extension.
*/
{
    int idummy;
    LONGLONG lldummy;
    double ddummy;

    ffgphd(fptr, maxdim, simple, bitpix, naxis, naxes, pcount, gcount, extend,
          &ddummy, &ddummy, &lldummy, &idummy, status);

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffghtb(fitsfile *fptr,  /* I - FITS file pointer                        */
           int maxfield,    /* I - maximum no. of columns to read;          */
           long *naxis1,    /* O - length of table row in bytes             */
           long *naxis2,    /* O - number of rows in the table              */
           int *tfields,    /* O - number of columns in the table           */
           char **ttype,    /* O - name of each column                      */
           long *tbcol,     /* O - byte offset in row to each column        */
           char **tform,    /* O - value of TFORMn keyword for each column  */
           char **tunit,    /* O - value of TUNITn keyword for each column  */
           char *extnm,   /* O - value of EXTNAME keyword, if any         */
           int *status)     /* IO - error status                            */
/*
  Get keywords from the Header of the ASCII TaBle:
  Check that the keywords conform to the FITS standard and return the
  parameters which describe the table.
*/
{
    int ii, maxf, nfound, tstatus;
    long fields;
    char name[FLEN_KEYWORD], value[FLEN_VALUE], comm[FLEN_COMMENT];
    char xtension[FLEN_VALUE], message[FLEN_ERRMSG];
    LONGLONG llnaxis1, llnaxis2, pcount;

    if (*status > 0)
        return(*status);

    /* read the first keyword of the extension */
    ffgkyn(fptr, 1, name, value, comm, status);

    if (!strcmp(name, "XTENSION"))
    {
            if (ffc2s(value, xtension, status) > 0)  /* get the value string */
            {
                ffpmsg("Bad value string for XTENSION keyword:");
                ffpmsg(value);
                return(*status);
            }

            /* allow the quoted string value to begin in any column and */
            /* allow any number of trailing blanks before the closing quote */
            if ( (value[0] != '\'')   ||  /* first char must be a quote */
                 ( strcmp(xtension, "TABLE") ) )
            {
                snprintf(message, FLEN_ERRMSG,
                "This is not a TABLE extension: %s", value);
                ffpmsg(message);
                return(*status = NOT_ATABLE);
            }
    }

    else  /* error: 1st keyword of extension != XTENSION */
    {
        snprintf(message, FLEN_ERRMSG,
        "First keyword of the extension is not XTENSION: %s", name);
        ffpmsg(message);
        return(*status = NO_XTENSION);
    }

    if (ffgttb(fptr, &llnaxis1, &llnaxis2, &pcount, &fields, status) > 0)
        return(*status);

    if (naxis1)
       *naxis1 = (long) llnaxis1;

    if (naxis2)
       *naxis2 = (long) llnaxis2;

    if (pcount != 0)
    {
       snprintf(message, FLEN_ERRMSG, "PCOUNT = %.0f is illegal in ASCII table; must = 0",
               (double) pcount);
       ffpmsg(message);
       return(*status = BAD_PCOUNT);
    }

    if (tfields)
       *tfields = fields;

    if (maxfield < 0)
        maxf = fields;
    else
        maxf = minvalue(maxfield, fields);

    if (maxf > 0)
    {
        for (ii = 0; ii < maxf; ii++)
        {   /* initialize optional keyword values */
            if (ttype)
                *ttype[ii] = '\0';   

            if (tunit)
                *tunit[ii] = '\0';
        }

   
        if (ttype)
            ffgkns(fptr, "TTYPE", 1, maxf, ttype, &nfound, status);

        if (tunit)
            ffgkns(fptr, "TUNIT", 1, maxf, tunit, &nfound, status);

        if (*status > 0)
            return(*status);

        if (tbcol)
        {
            ffgknj(fptr, "TBCOL", 1, maxf, tbcol, &nfound, status);

            if (*status > 0 || nfound != maxf)
            {
                ffpmsg(
        "Required TBCOL keyword(s) not found in ASCII table header (ffghtb).");
                return(*status = NO_TBCOL);
            }
        }

        if (tform)
        {
            ffgkns(fptr, "TFORM", 1, maxf, tform, &nfound, status);

            if (*status > 0 || nfound != maxf)
            {
                ffpmsg(
        "Required TFORM keyword(s) not found in ASCII table header (ffghtb).");
                return(*status = NO_TFORM);
            }
        }
    }

    if (extnm)
    {
        extnm[0] = '\0';

        tstatus = *status;
        ffgkys(fptr, "EXTNAME", extnm, comm, status);

        if (*status == KEY_NO_EXIST)
            *status = tstatus;  /* keyword not required, so ignore error */
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffghtbll(fitsfile *fptr, /* I - FITS file pointer                        */
           int maxfield,    /* I - maximum no. of columns to read;          */
           LONGLONG *naxis1, /* O - length of table row in bytes             */
           LONGLONG *naxis2, /* O - number of rows in the table              */
           int *tfields,    /* O - number of columns in the table           */
           char **ttype,    /* O - name of each column                      */
           LONGLONG *tbcol, /* O - byte offset in row to each column        */
           char **tform,    /* O - value of TFORMn keyword for each column  */
           char **tunit,    /* O - value of TUNITn keyword for each column  */
           char *extnm,     /* O - value of EXTNAME keyword, if any         */
           int *status)     /* IO - error status                            */
/*
  Get keywords from the Header of the ASCII TaBle:
  Check that the keywords conform to the FITS standard and return the
  parameters which describe the table.
*/
{
    int ii, maxf, nfound, tstatus;
    long fields;
    char name[FLEN_KEYWORD], value[FLEN_VALUE], comm[FLEN_COMMENT];
    char xtension[FLEN_VALUE], message[FLEN_ERRMSG];
    LONGLONG llnaxis1, llnaxis2, pcount;

    if (*status > 0)
        return(*status);

    /* read the first keyword of the extension */
    ffgkyn(fptr, 1, name, value, comm, status);

    if (!strcmp(name, "XTENSION"))
    {
            if (ffc2s(value, xtension, status) > 0)  /* get the value string */
            {
                ffpmsg("Bad value string for XTENSION keyword:");
                ffpmsg(value);
                return(*status);
            }

            /* allow the quoted string value to begin in any column and */
            /* allow any number of trailing blanks before the closing quote */
            if ( (value[0] != '\'')   ||  /* first char must be a quote */
                 ( strcmp(xtension, "TABLE") ) )
            {
                snprintf(message, FLEN_ERRMSG,
                "This is not a TABLE extension: %s", value);
                ffpmsg(message);
                return(*status = NOT_ATABLE);
            }
    }

    else  /* error: 1st keyword of extension != XTENSION */
    {
        snprintf(message, FLEN_ERRMSG,
        "First keyword of the extension is not XTENSION: %s", name);
        ffpmsg(message);
        return(*status = NO_XTENSION);
    }

    if (ffgttb(fptr, &llnaxis1, &llnaxis2, &pcount, &fields, status) > 0)
        return(*status);

    if (naxis1)
       *naxis1 = llnaxis1;

    if (naxis2)
       *naxis2 = llnaxis2;

    if (pcount != 0)
    {
       snprintf(message, FLEN_ERRMSG, "PCOUNT = %.0f is illegal in ASCII table; must = 0",
             (double) pcount);
       ffpmsg(message);
       return(*status = BAD_PCOUNT);
    }

    if (tfields)
       *tfields = fields;

    if (maxfield < 0)
        maxf = fields;
    else
        maxf = minvalue(maxfield, fields);

    if (maxf > 0)
    {
        for (ii = 0; ii < maxf; ii++)
        {   /* initialize optional keyword values */
            if (ttype)
                *ttype[ii] = '\0';   

            if (tunit)
                *tunit[ii] = '\0';
        }

   
        if (ttype)
            ffgkns(fptr, "TTYPE", 1, maxf, ttype, &nfound, status);

        if (tunit)
            ffgkns(fptr, "TUNIT", 1, maxf, tunit, &nfound, status);

        if (*status > 0)
            return(*status);

        if (tbcol)
        {
            ffgknjj(fptr, "TBCOL", 1, maxf, tbcol, &nfound, status);

            if (*status > 0 || nfound != maxf)
            {
                ffpmsg(
        "Required TBCOL keyword(s) not found in ASCII table header (ffghtbll).");
                return(*status = NO_TBCOL);
            }
        }

        if (tform)
        {
            ffgkns(fptr, "TFORM", 1, maxf, tform, &nfound, status);

            if (*status > 0 || nfound != maxf)
            {
                ffpmsg(
        "Required TFORM keyword(s) not found in ASCII table header (ffghtbll).");
                return(*status = NO_TFORM);
            }
        }
    }

    if (extnm)
    {
        extnm[0] = '\0';

        tstatus = *status;
        ffgkys(fptr, "EXTNAME", extnm, comm, status);

        if (*status == KEY_NO_EXIST)
            *status = tstatus;  /* keyword not required, so ignore error */
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffghbn(fitsfile *fptr,  /* I - FITS file pointer                        */
           int maxfield,    /* I - maximum no. of columns to read;          */
           long *naxis2,    /* O - number of rows in the table              */
           int *tfields,    /* O - number of columns in the table           */
           char **ttype,    /* O - name of each column                      */
           char **tform,    /* O - TFORMn value for each column             */
           char **tunit,    /* O - TUNITn value for each column             */
           char *extnm,     /* O - value of EXTNAME keyword, if any         */
           long *pcount,    /* O - value of PCOUNT keyword                  */
           int *status)     /* IO - error status                            */
/*
  Get keywords from the Header of the BiNary table:
  Check that the keywords conform to the FITS standard and return the
  parameters which describe the table.
*/
{
    int ii, maxf, nfound, tstatus;
    long  fields;
    char name[FLEN_KEYWORD], value[FLEN_VALUE], comm[FLEN_COMMENT];
    char xtension[FLEN_VALUE], message[FLEN_ERRMSG];
    LONGLONG naxis1ll, naxis2ll, pcountll;

    if (*status > 0)
        return(*status);

    /* read the first keyword of the extension */
    ffgkyn(fptr, 1, name, value, comm, status);

    if (!strcmp(name, "XTENSION"))
    {
            if (ffc2s(value, xtension, status) > 0)  /* get the value string */
            {
                ffpmsg("Bad value string for XTENSION keyword:");
                ffpmsg(value);
                return(*status);
            }

            /* allow the quoted string value to begin in any column and */
            /* allow any number of trailing blanks before the closing quote */
            if ( (value[0] != '\'')   ||  /* first char must be a quote */
                 ( strcmp(xtension, "BINTABLE") &&
                   strcmp(xtension, "A3DTABLE") &&
                   strcmp(xtension, "3DTABLE")
                 ) )
            {
                snprintf(message, FLEN_ERRMSG,
                "This is not a BINTABLE extension: %s", value);
                ffpmsg(message);
                return(*status = NOT_BTABLE);
            }
    }

    else  /* error: 1st keyword of extension != XTENSION */
    {
        snprintf(message, FLEN_ERRMSG,
        "First keyword of the extension is not XTENSION: %s", name);
        ffpmsg(message);
        return(*status = NO_XTENSION);
    }

    if (ffgttb(fptr, &naxis1ll, &naxis2ll, &pcountll, &fields, status) > 0)
        return(*status);

    if (naxis2)
       *naxis2 = (long) naxis2ll;

    if (pcount)
       *pcount = (long) pcountll;

    if (tfields)
        *tfields = fields;

    if (maxfield < 0)
        maxf = fields;
    else
        maxf = minvalue(maxfield, fields);

    if (maxf > 0)
    {
        for (ii = 0; ii < maxf; ii++)
        {   /* initialize optional keyword values */
            if (ttype)
                *ttype[ii] = '\0';   

            if (tunit)
                *tunit[ii] = '\0';
        }

        if (ttype)
            ffgkns(fptr, "TTYPE", 1, maxf, ttype, &nfound, status);

        if (tunit)
            ffgkns(fptr, "TUNIT", 1, maxf, tunit, &nfound, status);

        if (*status > 0)
            return(*status);

        if (tform)
        {
            ffgkns(fptr, "TFORM", 1, maxf, tform, &nfound, status);

            if (*status > 0 || nfound != maxf)
            {
                ffpmsg(
        "Required TFORM keyword(s) not found in binary table header (ffghbn).");
                return(*status = NO_TFORM);
            }
        }
    }

    if (extnm)
    {
        extnm[0] = '\0';

        tstatus = *status;
        ffgkys(fptr, "EXTNAME", extnm, comm, status);

        if (*status == KEY_NO_EXIST)
          *status = tstatus;  /* keyword not required, so ignore error */
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffghbnll(fitsfile *fptr,  /* I - FITS file pointer                        */
           int maxfield,    /* I - maximum no. of columns to read;          */
           LONGLONG *naxis2,    /* O - number of rows in the table              */
           int *tfields,    /* O - number of columns in the table           */
           char **ttype,    /* O - name of each column                      */
           char **tform,    /* O - TFORMn value for each column             */
           char **tunit,    /* O - TUNITn value for each column             */
           char *extnm,     /* O - value of EXTNAME keyword, if any         */
           LONGLONG *pcount,    /* O - value of PCOUNT keyword                  */
           int *status)     /* IO - error status                            */
/*
  Get keywords from the Header of the BiNary table:
  Check that the keywords conform to the FITS standard and return the
  parameters which describe the table.
*/
{
    int ii, maxf, nfound, tstatus;
    long  fields;
    char name[FLEN_KEYWORD], value[FLEN_VALUE], comm[FLEN_COMMENT];
    char xtension[FLEN_VALUE], message[FLEN_ERRMSG];
    LONGLONG naxis1ll, naxis2ll, pcountll;

    if (*status > 0)
        return(*status);

    /* read the first keyword of the extension */
    ffgkyn(fptr, 1, name, value, comm, status);

    if (!strcmp(name, "XTENSION"))
    {
            if (ffc2s(value, xtension, status) > 0)  /* get the value string */
            {
                ffpmsg("Bad value string for XTENSION keyword:");
                ffpmsg(value);
                return(*status);
            }

            /* allow the quoted string value to begin in any column and */
            /* allow any number of trailing blanks before the closing quote */
            if ( (value[0] != '\'')   ||  /* first char must be a quote */
                 ( strcmp(xtension, "BINTABLE") &&
                   strcmp(xtension, "A3DTABLE") &&
                   strcmp(xtension, "3DTABLE")
                 ) )
            {
                snprintf(message, FLEN_ERRMSG,
                "This is not a BINTABLE extension: %s", value);
                ffpmsg(message);
                return(*status = NOT_BTABLE);
            }
    }

    else  /* error: 1st keyword of extension != XTENSION */
    {
        snprintf(message, FLEN_ERRMSG,
        "First keyword of the extension is not XTENSION: %s", name);
        ffpmsg(message);
        return(*status = NO_XTENSION);
    }

    if (ffgttb(fptr, &naxis1ll, &naxis2ll, &pcountll, &fields, status) > 0)
        return(*status);

    if (naxis2)
       *naxis2 = naxis2ll;

    if (pcount)
       *pcount = pcountll;

    if (tfields)
        *tfields = fields;

    if (maxfield < 0)
        maxf = fields;
    else
        maxf = minvalue(maxfield, fields);

    if (maxf > 0)
    {
        for (ii = 0; ii < maxf; ii++)
        {   /* initialize optional keyword values */
            if (ttype)
                *ttype[ii] = '\0';   

            if (tunit)
                *tunit[ii] = '\0';
        }

        if (ttype)
            ffgkns(fptr, "TTYPE", 1, maxf, ttype, &nfound, status);

        if (tunit)
            ffgkns(fptr, "TUNIT", 1, maxf, tunit, &nfound, status);

        if (*status > 0)
            return(*status);

        if (tform)
        {
            ffgkns(fptr, "TFORM", 1, maxf, tform, &nfound, status);

            if (*status > 0 || nfound != maxf)
            {
                ffpmsg(
        "Required TFORM keyword(s) not found in binary table header (ffghbn).");
                return(*status = NO_TFORM);
            }
        }
    }

    if (extnm)
    {
        extnm[0] = '\0';

        tstatus = *status;
        ffgkys(fptr, "EXTNAME", extnm, comm, status);

        if (*status == KEY_NO_EXIST)
          *status = tstatus;  /* keyword not required, so ignore error */
    }
    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgphd(fitsfile *fptr,  /* I - FITS file pointer                        */
           int maxdim,      /* I - maximum no. of dimensions to read;       */
           int *simple,     /* O - does file conform to FITS standard? 1/0  */
           int *bitpix,     /* O - number of bits per data value pixel      */
           int *naxis,      /* O - number of axes in the data array         */
           LONGLONG naxes[],    /* O - length of each data axis                 */
           long *pcount,    /* O - number of group parameters (usually 0)   */
           long *gcount,    /* O - number of random groups (usually 1 or 0) */
           int *extend,     /* O - may FITS file haave extensions?          */
           double *bscale,  /* O - array pixel linear scaling factor        */
           double *bzero,   /* O - array pixel linear scaling zero point    */
           LONGLONG *blank, /* O - value used to represent undefined pixels */
           int *nspace,     /* O - number of blank keywords prior to END    */
           int *status)     /* IO - error status                            */
{
/*
  Get the Primary HeaDer parameters.  Check that the keywords conform to
  the FITS standard and return the parameters which determine the size and
  structure of the primary array or IMAGE extension.
*/
    int unknown, found_end, tstatus, ii, nextkey, namelen;
    long longbitpix, longnaxis;
    LONGLONG axislen;
    char message[FLEN_ERRMSG], keyword[FLEN_KEYWORD];
    char card[FLEN_CARD];
    char name[FLEN_KEYWORD], value[FLEN_VALUE], comm[FLEN_COMMENT];
    char xtension[FLEN_VALUE];

    if (*status > 0)
        return(*status);

    if (fptr->HDUposition != (fptr->Fptr)->curhdu)
        ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);

    if (simple)
       *simple = 1;

    unknown = 0;

    /*--------------------------------------------------------------------*/
    /*  Get 1st keyword of HDU and test whether it is SIMPLE or XTENSION  */
    /*--------------------------------------------------------------------*/
    ffgkyn(fptr, 1, name, value, comm, status);

    if ((fptr->Fptr)->curhdu == 0) /* Is this the beginning of the FITS file? */
    {
        if (!strcmp(name, "SIMPLE"))
        {
            if (value[0] == 'F')
            {
                if (simple)
                    *simple=0;          /* not a simple FITS file */
            }
            else if (value[0] != 'T')
                return(*status = BAD_SIMPLE);
        }

        else
        {
            snprintf(message, FLEN_ERRMSG,
                   "First keyword of the file is not SIMPLE: %s", name);
            ffpmsg(message);
            return(*status = NO_SIMPLE);
        }
    }

    else    /* not beginning of the file, so presumably an IMAGE extension */
    {       /* or it could be a compressed image in a binary table */

        if (!strcmp(name, "XTENSION"))
        {
            if (ffc2s(value, xtension, status) > 0)  /* get the value string */
            {
                ffpmsg("Bad value string for XTENSION keyword:");
                ffpmsg(value);
                return(*status);
            }

            /* allow the quoted string value to begin in any column and */
            /* allow any number of trailing blanks before the closing quote */
            if ( (value[0] != '\'')   ||  /* first char must be a quote */
                  ( strcmp(xtension, "IMAGE")  &&
                    strcmp(xtension, "IUEIMAGE") ) )
            {
                unknown = 1;  /* unknown type of extension; press on anyway */
                snprintf(message, FLEN_ERRMSG,
                   "This is not an IMAGE extension: %s", value);
                ffpmsg(message);
            }
        }

        else  /* error: 1st keyword of extension != XTENSION */
        {
            snprintf(message, FLEN_ERRMSG,
            "First keyword of the extension is not XTENSION: %s", name);
            ffpmsg(message);
            return(*status = NO_XTENSION);
        }
    }

    if (unknown && (fptr->Fptr)->compressimg)
    {
        /* this is a compressed image, so read ZBITPIX, ZNAXIS keywords */
        unknown = 0;  /* reset flag */
        ffxmsg(3, message); /* clear previous spurious error message */

        if (bitpix)
        {
            ffgidt(fptr, bitpix, status); /* get bitpix value */

            if (*status > 0)
            {
                ffpmsg("Error reading BITPIX value of compressed image");
                return(*status);
            }
        }

        if (naxis)
        {
            ffgidm(fptr, naxis, status); /* get NAXIS value */

            if (*status > 0)
            {
                ffpmsg("Error reading NAXIS value of compressed image");
                return(*status);
            }
        }

        if (naxes)
        {
            ffgiszll(fptr, maxdim, naxes, status);  /* get NAXISn value */

            if (*status > 0)
            {
                ffpmsg("Error reading NAXISn values of compressed image");
                return(*status);
            }
        }

        nextkey = 9; /* skip required table keywords in the following search */
    }
    else
    {

        /*----------------------------------------------------------------*/
        /*  Get 2nd keyword;  test whether it is BITPIX with legal value  */
        /*----------------------------------------------------------------*/
        ffgkyn(fptr, 2, name, value, comm, status);  /* BITPIX = 2nd keyword */

        if (strcmp(name, "BITPIX"))
        {
            snprintf(message, FLEN_ERRMSG,
            "Second keyword of the extension is not BITPIX: %s", name);
            ffpmsg(message);
            return(*status = NO_BITPIX);
        }

        if (ffc2ii(value,  &longbitpix, status) > 0)
        {
            snprintf(message, FLEN_ERRMSG,
            "Value of BITPIX keyword is not an integer: %s", value);
            ffpmsg(message);
            return(*status = BAD_BITPIX);
        }
        else if (longbitpix != BYTE_IMG && longbitpix != SHORT_IMG &&
             longbitpix != LONG_IMG && longbitpix != LONGLONG_IMG &&
             longbitpix != FLOAT_IMG && longbitpix != DOUBLE_IMG)
        {
            snprintf(message, FLEN_ERRMSG,
            "Illegal value for BITPIX keyword: %s", value);
            ffpmsg(message);
            return(*status = BAD_BITPIX);
        }
        if (bitpix)
            *bitpix = longbitpix;  /* do explicit type conversion */

        /*---------------------------------------------------------------*/
        /*  Get 3rd keyword;  test whether it is NAXIS with legal value  */
        /*---------------------------------------------------------------*/
        ffgtkn(fptr, 3, "NAXIS",  &longnaxis, status);

        if (*status == BAD_ORDER)
            return(*status = NO_NAXIS);
        else if (*status == NOT_POS_INT || longnaxis > 999)
        {
            snprintf(message,FLEN_ERRMSG,"NAXIS = %ld is illegal", longnaxis);
            ffpmsg(message);
            return(*status = BAD_NAXIS);
        }
        else
            if (naxis)
                 *naxis = longnaxis;  /* do explicit type conversion */

        /*---------------------------------------------------------*/
        /*  Get the next NAXISn keywords and test for legal values */
        /*---------------------------------------------------------*/
        for (ii=0, nextkey=4; ii < longnaxis; ii++, nextkey++)
        {
            ffkeyn("NAXIS", ii+1, keyword, status);
            ffgtknjj(fptr, 4+ii, keyword, &axislen, status);

            if (*status == BAD_ORDER)
                return(*status = NO_NAXES);
            else if (*status == NOT_POS_INT)
                return(*status = BAD_NAXES);
            else if (ii < maxdim)
                if (naxes)
                    naxes[ii] = axislen;
        }
    }

    /*---------------------------------------------------------*/
    /*  now look for other keywords of interest:               */
    /*  BSCALE, BZERO, BLANK, PCOUNT, GCOUNT, EXTEND, and END  */
    /*---------------------------------------------------------*/

    /*  initialize default values in case keyword is not present */
    if (bscale)
        *bscale = 1.0;
    if (bzero)
        *bzero  = 0.0;
    if (pcount)
        *pcount = 0;
    if (gcount)
        *gcount = 1;
    if (extend)
        *extend = 0;
    if (blank)
      *blank = NULL_UNDEFINED; /* no default null value for BITPIX=8,16,32 */

    *nspace = 0;
    found_end = 0;
    tstatus = *status;

    for (; !found_end; nextkey++)  
    {
      /* get next keyword */
      /* don't use ffgkyn here because it trys to parse the card to read */
      /* the value string, thus failing to read the file just because of */
      /* minor syntax errors in optional keywords.                       */

      if (ffgrec(fptr, nextkey, card, status) > 0 )  /* get the 80-byte card */
      {
        if (*status == KEY_OUT_BOUNDS)
        {
          found_end = 1;  /* simply hit the end of the header */
          *status = tstatus;  /* reset error status */
        }
        else          
        {
          ffpmsg("Failed to find the END keyword in header (ffgphd).");
        }
      }
      else /* got the next keyword without error */
      {
        ffgknm(card, name, &namelen, status); /* get the keyword name */

        if (fftrec(name, status) > 0)  /* test keyword name; catches no END */
        {
          snprintf(message, FLEN_ERRMSG,
              "Name of keyword no. %d contains illegal character(s): %s",
              nextkey, name);
          ffpmsg(message);

          if (nextkey % 36 == 0) /* test if at beginning of 36-card record */
            ffpmsg("  (This may indicate a missing END keyword).");
        }

        if (!strcmp(name, "BSCALE") && bscale)
        {
            *nspace = 0;  /* reset count of blank keywords */
            ffpsvc(card, value, comm, status); /* parse value and comment */

            if (ffc2dd(value, bscale, status) > 0) /* convert to double */
            {
                /* reset error status and continue, but still issue warning */
                *status = tstatus;
                *bscale = 1.0;

                snprintf(message, FLEN_ERRMSG,
                "Error reading BSCALE keyword value as a double: %s", value);
                ffpmsg(message);
            }
        }

        else if (!strcmp(name, "BZERO") && bzero)
        {
            *nspace = 0;  /* reset count of blank keywords */
            ffpsvc(card, value, comm, status); /* parse value and comment */

            if (ffc2dd(value, bzero, status) > 0) /* convert to double */
            {
                /* reset error status and continue, but still issue warning */
                *status = tstatus;
                *bzero = 0.0;

                snprintf(message, FLEN_ERRMSG,
                "Error reading BZERO keyword value as a double: %s", value);
                ffpmsg(message);
            }
        }

        else if (!strcmp(name, "BLANK") && blank)
        {
            *nspace = 0;  /* reset count of blank keywords */
            ffpsvc(card, value, comm, status); /* parse value and comment */

            if (ffc2jj(value, blank, status) > 0) /* convert to LONGLONG */
            {
                /* reset error status and continue, but still issue warning */
                *status = tstatus;
                *blank = NULL_UNDEFINED;

                snprintf(message, FLEN_ERRMSG,
                "Error reading BLANK keyword value as an integer: %s", value);
                ffpmsg(message);
            }
        }

        else if (!strcmp(name, "PCOUNT") && pcount)
        {
            *nspace = 0;  /* reset count of blank keywords */
            ffpsvc(card, value, comm, status); /* parse value and comment */

            if (ffc2ii(value, pcount, status) > 0) /* convert to long */
            {
                snprintf(message, FLEN_ERRMSG,
                "Error reading PCOUNT keyword value as an integer: %s", value);
                ffpmsg(message);
            }
        }

        else if (!strcmp(name, "GCOUNT") && gcount)
        {
            *nspace = 0;  /* reset count of blank keywords */
            ffpsvc(card, value, comm, status); /* parse value and comment */

            if (ffc2ii(value, gcount, status) > 0) /* convert to long */
            {
                snprintf(message, FLEN_ERRMSG,
                "Error reading GCOUNT keyword value as an integer: %s", value);
                ffpmsg(message);
            }
        }

        else if (!strcmp(name, "EXTEND") && extend)
        {
            *nspace = 0;  /* reset count of blank keywords */
            ffpsvc(card, value, comm, status); /* parse value and comment */

            if (ffc2ll(value, extend, status) > 0) /* convert to logical */
            {
                /* reset error status and continue, but still issue warning */
                *status = tstatus;
                *extend = 0;

                snprintf(message, FLEN_ERRMSG,
                "Error reading EXTEND keyword value as a logical: %s", value);
                ffpmsg(message);
            }
        }

        else if (!strcmp(name, "END"))
            found_end = 1;

        else if (!card[0] )
            *nspace = *nspace + 1;  /* this is a blank card in the header */

        else
            *nspace = 0;  /* reset count of blank keywords immediately
                            before the END keyword to zero   */
      }

      if (*status > 0)  /* exit on error after writing error message */
      {
        if ((fptr->Fptr)->curhdu == 0)
            ffpmsg(
            "Failed to read the required primary array header keywords.");
        else
            ffpmsg(
            "Failed to read the required image extension header keywords.");

        return(*status);
      }
    }

    if (unknown)
       *status = NOT_IMAGE;

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgttb(fitsfile *fptr,      /* I - FITS file pointer*/
           LONGLONG *rowlen,        /* O - length of a table row, in bytes */
           LONGLONG *nrows,         /* O - number of rows in the table */
           LONGLONG *pcount,    /* O - value of PCOUNT keyword */
           long *tfields,       /* O - number of fields in the table */
           int *status)         /* IO - error status    */
{
/*
  Get and Test TaBle;
  Test that this is a legal ASCII or binary table and get some keyword values.
  We assume that the calling routine has already tested the 1st keyword
  of the extension to ensure that this is really a table extension.
*/
    if (*status > 0)
        return(*status);

    if (fftkyn(fptr, 2, "BITPIX", "8", status) == BAD_ORDER) /* 2nd keyword */
        return(*status = NO_BITPIX);  /* keyword not BITPIX */
    else if (*status == NOT_POS_INT)
        return(*status = BAD_BITPIX); /* value != 8 */

    if (fftkyn(fptr, 3, "NAXIS", "2", status) == BAD_ORDER) /* 3rd keyword */
        return(*status = NO_NAXIS);  /* keyword not NAXIS */
    else if (*status == NOT_POS_INT)
        return(*status = BAD_NAXIS); /* value != 2 */

    if (ffgtknjj(fptr, 4, "NAXIS1", rowlen, status) == BAD_ORDER) /* 4th key */
        return(*status = NO_NAXES);  /* keyword not NAXIS1 */
    else if (*status == NOT_POS_INT)
        return(*status == BAD_NAXES); /* bad NAXIS1 value */

    if (ffgtknjj(fptr, 5, "NAXIS2", nrows, status) == BAD_ORDER) /* 5th key */
        return(*status = NO_NAXES);  /* keyword not NAXIS2 */
    else if (*status == NOT_POS_INT)
        return(*status == BAD_NAXES); /* bad NAXIS2 value */

    if (ffgtknjj(fptr, 6, "PCOUNT", pcount, status) == BAD_ORDER) /* 6th key */
        return(*status = NO_PCOUNT);  /* keyword not PCOUNT */
    else if (*status == NOT_POS_INT)
        return(*status = BAD_PCOUNT); /* bad PCOUNT value */

    if (fftkyn(fptr, 7, "GCOUNT", "1", status) == BAD_ORDER) /* 7th keyword */
        return(*status = NO_GCOUNT);  /* keyword not GCOUNT */
    else if (*status == NOT_POS_INT)
        return(*status = BAD_GCOUNT); /* value != 1 */

    if (ffgtkn(fptr, 8, "TFIELDS", tfields, status) == BAD_ORDER) /* 8th key*/
        return(*status = NO_TFIELDS);  /* keyword not TFIELDS */
    else if (*status == NOT_POS_INT || *tfields > 999)
        return(*status == BAD_TFIELDS); /* bad TFIELDS value */


    if (*status > 0)
       ffpmsg(
       "Error reading required keywords in the table header (FTGTTB).");

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgtkn(fitsfile *fptr,  /* I - FITS file pointer              */
           int numkey,      /* I - number of the keyword to read  */
           char *name,      /* I - expected name of the keyword   */
           long *value,     /* O - integer value of the keyword   */
           int *status)     /* IO - error status                  */
{
/*
  test that keyword number NUMKEY has the expected name and get the
  integer value of the keyword.  Return an error if the keyword
  name does not match the input name, or if the value of the
  keyword is not a positive integer.
*/
    char keyname[FLEN_KEYWORD], valuestring[FLEN_VALUE];
    char comm[FLEN_COMMENT], message[FLEN_ERRMSG];
   
    if (*status > 0)
        return(*status);
    
    keyname[0] = '\0';
    valuestring[0] = '\0';

    if (ffgkyn(fptr, numkey, keyname, valuestring, comm, status) <= 0)
    {
        if (strcmp(keyname, name) )
            *status = BAD_ORDER;  /* incorrect keyword name */

        else
        {
            ffc2ii(valuestring, value, status);  /* convert to integer */

            if (*status > 0 || *value < 0 )
               *status = NOT_POS_INT;
        }

        if (*status > 0)
        {
            snprintf(message, FLEN_ERRMSG,
              "ffgtkn found unexpected keyword or value for keyword no. %d.",
              numkey);
            ffpmsg(message);

            snprintf(message, FLEN_ERRMSG,
              " Expected positive integer keyword %s, but instead", name);
            ffpmsg(message);

            snprintf(message, FLEN_ERRMSG,
              " found keyword %s with value %s", keyname, valuestring);
            ffpmsg(message);
        }
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffgtknjj(fitsfile *fptr,  /* I - FITS file pointer              */
           int numkey,      /* I - number of the keyword to read  */
           char *name,      /* I - expected name of the keyword   */
           LONGLONG *value, /* O - integer value of the keyword   */
           int *status)     /* IO - error status                  */
{
/*
  test that keyword number NUMKEY has the expected name and get the
  integer value of the keyword.  Return an error if the keyword
  name does not match the input name, or if the value of the
  keyword is not a positive integer.
*/
    char keyname[FLEN_KEYWORD], valuestring[FLEN_VALUE];
    char comm[FLEN_COMMENT], message[FLEN_ERRMSG];
   
    if (*status > 0)
        return(*status);
    
    keyname[0] = '\0';
    valuestring[0] = '\0';

    if (ffgkyn(fptr, numkey, keyname, valuestring, comm, status) <= 0)
    {
        if (strcmp(keyname, name) )
            *status = BAD_ORDER;  /* incorrect keyword name */

        else
        {
            ffc2jj(valuestring, value, status);  /* convert to integer */

            if (*status > 0 || *value < 0 )
               *status = NOT_POS_INT;
        }

        if (*status > 0)
        {
            snprintf(message, FLEN_ERRMSG,
              "ffgtknjj found unexpected keyword or value for keyword no. %d.",
              numkey);
            ffpmsg(message);

            snprintf(message, FLEN_ERRMSG,
              " Expected positive integer keyword %s, but instead", name);
            ffpmsg(message);

            snprintf(message, FLEN_ERRMSG,
              " found keyword %s with value %s", keyname, valuestring);
            ffpmsg(message);
        }
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int fftkyn(fitsfile *fptr,  /* I - FITS file pointer              */
           int numkey,      /* I - number of the keyword to read  */
           char *name,      /* I - expected name of the keyword   */
           char *value,     /* I - expected value of the keyword  */
           int *status)     /* IO - error status                  */
{
/*
  test that keyword number NUMKEY has the expected name and the
  expected value string.
*/
    char keyname[FLEN_KEYWORD], valuestring[FLEN_VALUE];
    char comm[FLEN_COMMENT], message[FLEN_ERRMSG];
   
    if (*status > 0)
        return(*status);
    
    keyname[0] = '\0';
    valuestring[0] = '\0';

    if (ffgkyn(fptr, numkey, keyname, valuestring, comm, status) <= 0)
    {
        if (strcmp(keyname, name) )
            *status = BAD_ORDER;  /* incorrect keyword name */

        if (strcmp(value, valuestring) )
            *status = NOT_POS_INT;  /* incorrect keyword value */
    }

    if (*status > 0)
    {
        snprintf(message, FLEN_ERRMSG,
          "fftkyn found unexpected keyword or value for keyword no. %d.",
          numkey);
        ffpmsg(message);

        snprintf(message, FLEN_ERRMSG,
          " Expected keyword %s with value %s, but", name, value);
        ffpmsg(message);

        snprintf(message, FLEN_ERRMSG,
          " found keyword %s with value %s", keyname, valuestring);
        ffpmsg(message);
    }

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffh2st(fitsfile *fptr,   /* I - FITS file pointer           */
           char **header,    /* O - returned header string      */
           int  *status)     /* IO - error status               */

/*
  read header keywords into a long string of chars.  This routine allocates
  memory for the string, so the calling routine must eventually free the
  memory when it is not needed any more.
*/
{
    int nkeys;
    long nrec;
    LONGLONG headstart;

    if (*status > 0)
        return(*status);

    /* get number of keywords in the header (doesn't include END) */
    if (ffghsp(fptr, &nkeys, NULL, status) > 0)
        return(*status);

    nrec = (nkeys / 36 + 1);

    /* allocate memory for all the keywords (multiple of 2880 bytes) */
    *header = (char *) calloc ( nrec * 2880 + 1, 1);
    if (!(*header))
    {
         *status = MEMORY_ALLOCATION;
         ffpmsg("failed to allocate memory to hold all the header keywords");
         return(*status);
    }

    ffghadll(fptr, &headstart, NULL, NULL, status); /* get header address */
    ffmbyt(fptr, headstart, REPORT_EOF, status);   /* move to header */
    ffgbyt(fptr, nrec * 2880, *header, status);     /* copy header */
    *(*header + (nrec * 2880)) = '\0';

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffhdr2str( fitsfile *fptr,  /* I - FITS file pointer                    */
            int exclude_comm,   /* I - if TRUE, exclude commentary keywords */
            char **exclist,     /* I - list of excluded keyword names       */
            int nexc,           /* I - number of names in exclist           */
            char **header,      /* O - returned header string               */
            int *nkeys,         /* O - returned number of 80-char keywords  */
            int  *status)       /* IO - error status                        */
/*
  read header keywords into a long string of chars.  This routine allocates
  memory for the string, so the calling routine must eventually free the
  memory when it is not needed any more.  If exclude_comm is TRUE, then all 
  the COMMENT, HISTORY, and  keywords will be excluded from the output
  string of keywords.  Any other list of keywords to be excluded may be
  specified with the exclist parameter.
*/
{
    int casesn, match, exact, totkeys;
    long ii, jj;
    char keybuf[162], keyname[FLEN_KEYWORD], *headptr;

    *nkeys = 0;

    if (*status > 0)
        return(*status);

    /* get number of keywords in the header (doesn't include END) */
    if (ffghsp(fptr, &totkeys, NULL, status) > 0)
        return(*status);

    /* allocate memory for all the keywords */
    /* (will reallocate it later to minimize the memory size) */
    
    *header = (char *) calloc ( (totkeys + 1) * 80 + 1, 1);
    if (!(*header))
    {
         *status = MEMORY_ALLOCATION;
         ffpmsg("failed to allocate memory to hold all the header keywords");
         return(*status);
    }

    headptr = *header;
    casesn = FALSE;

    /* read every keyword */
    for (ii = 1; ii <= totkeys; ii++) 
    {
        ffgrec(fptr, ii, keybuf, status);
        /* pad record with blanks so that it is at least 80 chars long */
        strcat(keybuf,
    "                                                                                ");

        keyname[0] = '\0';
        strncat(keyname, keybuf, 8); /* copy the keyword name */
        
        if (exclude_comm)
        {
            if (!FSTRCMP("COMMENT ", keyname) ||
                !FSTRCMP("HISTORY ", keyname) ||
                !FSTRCMP("        ", keyname) )
              continue;  /* skip this commentary keyword */
        }

        /* does keyword match any names in the exclusion list? */
        for (jj = 0; jj < nexc; jj++ )
        {
            ffcmps(exclist[jj], keyname, casesn, &match, &exact);
                 if (match)
                     break;
        }

        if (jj == nexc)
        {
            /* not in exclusion list, add this keyword to the string */
            strcpy(headptr, keybuf);
            headptr += 80;
            (*nkeys)++;
        }
    }

    /* add the END keyword */
    strcpy(headptr,
    "END                                                                             ");
    headptr += 80;
    (*nkeys)++;

    *headptr = '\0';   /* terminate the header string */
    /* minimize the allocated memory */
    *header = (char *) realloc(*header, (*nkeys *80) + 1);  

    return(*status);
}
/*--------------------------------------------------------------------------*/
int ffcnvthdr2str( fitsfile *fptr,  /* I - FITS file pointer                    */
            int exclude_comm,   /* I - if TRUE, exclude commentary keywords */
            char **exclist,     /* I - list of excluded keyword names       */
            int nexc,           /* I - number of names in exclist           */
            char **header,      /* O - returned header string               */
            int *nkeys,         /* O - returned number of 80-char keywords  */
            int  *status)       /* IO - error status                        */
/*
  Same as ffhdr2str, except that if the input HDU is a tile compressed image
  (stored in a binary table) then it will first convert that header back
  to that of a normal uncompressed FITS image before concatenating the header
  keyword records.
*/
{
    fitsfile *tempfptr;
    
    if (*status > 0)
        return(*status);

    if (fits_is_compressed_image(fptr, status) )
    {
        /* this is a tile compressed image, so need to make an uncompressed */
	/* copy of the image header in memory before concatenating the keywords */
        if (fits_create_file(&tempfptr, "mem://", status) > 0) {
	    return(*status);
	}

	if (fits_img_decompress_header(fptr, tempfptr, status) > 0) {
	    fits_delete_file(tempfptr, status);
	    return(*status);
	}

	ffhdr2str(tempfptr, exclude_comm, exclist, nexc, header, nkeys, status);
	fits_close_file(tempfptr, status);

    } else {
        ffhdr2str(fptr, exclude_comm, exclist, nexc, header, nkeys, status);
    }

    return(*status);
}